Capture high resolution screenshots

For my free Photo Session tool I wanted higher than screen resolution capturing. Unity’s own mechanisms using the ScreenCapture class didn’t deliver satisfactory results, not even using the supersize parameter.

However, I found a solution that fit my needs, so here’s the core mechanism I came up with. I thought I’d share in case anyone has use for it.

The main problem was that even though you specify a rendertexture for the camera, it doesn’t work. You have to disable the camera first.

/// <summary>
/// Create a custom resolution screenshot using the specified camera.
/// The resolution can be higher than the screen size.
/// </summary>
/// <param name="camera"></param>
/// <param name="width"></param>
/// <param name="height"></param>
public void Capture( Camera camera, int width, int height) {
   
    // save data which we'll modify
    RenderTexture prevRenderTexture = RenderTexture.active;
    RenderTexture prevCameraTargetTexture = camera.targetTexture;
    bool prevCameraEnabled = camera.enabled;

    // create rendertexture
    int msaaSamples = 1;
    RenderTexture renderTexture = RenderTexture.GetTemporary(width, height, 24, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default, msaaSamples);

    try
    {
        // disabling the camera is important, otherwise you get e. g. a blurry image with different focus than the one the camera displays
        // see https://docs.unity3d.com/ScriptReference/Camera.Render.html
        camera.enabled = false;

        // set rendertexture into which the camera renders
        camera.targetTexture = renderTexture;

        // render a single frame
        camera.Render();

        // create image using the camera's render texture
        RenderTexture.active = camera.targetTexture;

        Texture2D screenShot = new Texture2D(width, height, TextureFormat.RGB24, false);
        screenShot.ReadPixels(new Rect(0, 0, width, height), 0, 0);
        screenShot.Apply();

        // save the image
        byte[] bytes = screenShot.EncodeToPNG();

        string filepath = Path.Combine(this.screenshotPath, GetFilename());

        System.IO.File.WriteAllBytes(filepath, bytes);

        Debug.Log(string.Format("[<color=blue>Screenshot</color>]Screenshot captured\n<color=grey>{0}</color>", filepath));

    }
    catch (Exception ex)
    {
        Debug.LogError("Screenshot capture exception: " + ex);
    }
    finally
    {
        RenderTexture.ReleaseTemporary(renderTexture);

        // restore modified data
        RenderTexture.active = prevRenderTexture;
        camera.targetTexture = prevCameraTargetTexture;
        camera.enabled = prevCameraEnabled;

    }

}
1 Like

Cheers!

Have you had any need to modify the images for linear vs gamma brightness issues?

And/or tried grabbing images with alpha?

I didn’t check either. Just try my free tool or the code above. Or alternatively try Unity’s own recorder, with that everything should / must work :slight_smile:

All I can tell is that eg for HDRP there are issues with eg automatic exposure. You’d have to wait multiple frames and capture afterwards. Or set exposure to fixed. Stuff like that.

What I do know is that Unity’s Recorder still doesn’t record e.g. 4K images properly. They are upscaled. Tried it last week out of curiosity.