Search Unity

Performance Problems in Rendering a Camera

Discussion in 'Scripting' started by jacopolottero, Mar 19, 2018.

  1. jacopolottero

    jacopolottero

    Joined:
    Apr 10, 2017
    Posts:
    1
    Hello,

    i'm trying to get the content of one camera in my game and send the raw image to another script.
    The problem is that the script for rendering the camera is really slow and volatile (10 - 80 ms).

    We are speaking about very small images (128 x 128 px; 24 bit). Here is the code we are currently using:


    public class ScreenRecorder : MonoBehaviour
    {
    // Communicator myCommunicator;
    public static byte[] fileData;
    public static byte[] tempFileData;

    public static int captureWidth = 128;
    public static int captureHeight = 128;

    // optional game object to hide during screenshots (usually your scene canvas hud)
    public GameObject hideGameObject;

    // optimize for many screenshots will not destroy any objects so future screenshots will be fast
    public bool optimizeForManyScreenshots = true;

    // configure with raw, jpg, png, or ppm (simple raw format)
    public enum Format { RAW, JPG, PNG, PPM };
    public Format format = Format.PPM;

    // folder to write output (defaults to data path)
    public string folder;

    // private vars for screenshot
    private Rect rect = new Rect(0, 0, captureWidth, captureHeight);
    private RenderTexture renderTexture = null;
    private Texture2D screenShot = null;
    private int counter = 0; // image #

    private void Start()
    {
    screenShot = new Texture2D(captureWidth, captureHeight, TextureFormat.RGB24, false);
    renderTexture = new RenderTexture(captureWidth, captureHeight, 24);
    }

    public static byte[] getScreen()
    {
    if (fileData == null) return tempFileData;
    else return fileData;
    }


    // commands
    private bool captureScreenshot = false;
    private bool captureVideo = false;
    private double speed;

    public void CaptureScreenshot()
    {
    captureScreenshot = true;
    }

    void Update()
    {

    captureScreenshot = true;
    captureVideo = Input.GetKey("v");


    if (captureScreenshot || captureVideo)
    {
    captureScreenshot = false;

    // hide optional game object if set
    if (hideGameObject != null) hideGameObject.SetActive(false);

    // get main camera and manually render scene into rt
    Camera camera = this.GetComponent<Camera>(); // NOTE: added because there was no reference to camera in original script; must add this script to Camera
    camera.targetTexture = renderTexture;

    camera.Render();

    // read pixels will read from the currently active render texture so make our offscreen
    // render texture active and then read the pixels
    RenderTexture.active = renderTexture;
    screenShot.ReadPixels(rect, 0, 0);

    // reset active camera texture and render texture
    camera.targetTexture = null;
    RenderTexture.active = null;


    // pull in our file header/data bytes for the specified image format (has to be done from main thread)

    fileData = null;

    // This is the image we send over the socket.
    fileData = screenShot.GetRawTextureData();


    if (fileData != null) tempFileData = fileData;

    if (fileData == null) Debug.Log("null");

    // unhide optional game object if set
    if (hideGameObject != null) hideGameObject.SetActive(true);

    // cleanup if needed
    if (optimizeForManyScreenshots == false)
    {
    Destroy(renderTexture);
    renderTexture = null;
    screenShot = null;
    }
    }
    }
    }

    We found this code online and we know that it is not optimized. However, we found based on timers that this is a huge bottleneck and we are wondering why this is the case since we are dealing with smalle images without lights etc. Do you have some suggestion for improving this code or could you help me in finding the problem?

    Thank you!
     
  2. ThermalFusion

    ThermalFusion

    Joined:
    May 1, 2011
    Posts:
    906
    The issue unlikely related to rendering the image. That is usually very fast unless your scene is very complex.
    Most of your performance loss is probably from Texture2D.ReadPixels and Texture2D.GetRawTextureData.
    Getting image data back from the GPU is usually very slow.
    You may see some performance gain if you disable automatic mipmap generation in ReadPixels.
    I would avoid reading textures like this if at all possible.