Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Fitting an ortographic cameras size to capture a 2D plane (aka image)

Discussion in 'Scripting' started by Di_o, Aug 8, 2019.

  1. Di_o

    Di_o

    Joined:
    May 10, 2016
    Posts:
    55
    Hey there,

    I'm working on a little project where the player can draw/write a line renderer on a plane. All of this is working fine. Now I want a function that saves an actual image (*.png) of that plane. For that I place an ortographic camera on it, that generates a RenderTexture. This RenderTexture is then used to calculate it's bytes to a png file.

    Here is the code for the camera, if someone is interested:

    Code (CSharp):
    1. public class ScreenshotTool : MonoBehaviour
    2.     {
    3.         private int i;
    4.         private Camera cam;
    5.  
    6.         private void Start()
    7.         {
    8.             cam = GetComponent<Camera>();
    9.             cam.enabled = false;
    10.         }
    11.  
    12.         public void CaptureImageOfTarget(Transform target, int resWidth, int resHeight)
    13.         {        
    14.             cam.orthographicSize = target.localScale.x / 11.111f;
    15.             transform.rotation = target.rotation;
    16.             transform.position = target.position + transform.forward * -0.1f;
    17.  
    18.             RenderTexture rt = new RenderTexture(resWidth, resHeight, 24);
    19.             cam.targetTexture = rt;
    20.             Texture2D screenShot = new Texture2D(resWidth, resHeight, TextureFormat.RGB24, false);
    21.             cam.Render();
    22.             RenderTexture.active = rt;
    23.             screenShot.ReadPixels(new Rect(0, 0, resWidth, resHeight), 0, 0);
    24.             cam.targetTexture = null;
    25.             RenderTexture.active = null; // JC: added to avoid errors
    26.             Destroy(rt);
    27.             byte[] bytes = screenShot.EncodeToPNG();
    28.             i++;
    29.             string filename = target.name + "_Screenshot_" + i;
    30.             File.WriteAllBytes(Path.Combine(Application.persistentDataPath, filename + ".png"), bytes);
    31.             cam.enabled = false;
    32.         }
    33.     }
    This line...
    Code (CSharp):
    1.             cam.orthographicSize = target.localScale.x / 11.111f;
    ... is just a placeholder that sort of works for my images that acually have a resolutuion I can calculate. But my goal is to fit the orthographicSize to a value, that fits my plane in worldSpace. So if my plane is 5x5 units, the frustum of the camera should wrap around the 5x5 units.

    Could not really find a solution for that, yet.
     
  2. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,745
    You can use overlay canvas for your render texture instead of camere, there's handy pixels per unit option
     
    Di_o likes this.
  3. Di_o

    Di_o

    Joined:
    May 10, 2016
    Posts:
    55
    Found a solution:

    Code (CSharp):
    1.   private float GetHeight(Canvas canvas)
    2.         {
    3.             Vector3[] v = new Vector3[4];
    4.             canvas.GetComponent<RectTransform>().GetWorldCorners(v);
    5.  
    6.             return Vector3.Distance(v[0], v[1]) / 2;
    7.         }
    8.  
    I'm using this method to get my orthographicSize. It gets the hight of my target canvas in world space. Don't need the width, because of the aspect ratio that comes from the resolution