Writting to rendertexture comes out darker

Hi, I was trying to render the encoded depth and normals of the screen to a RenderTexture, but for some reason the results in the render texture are a bit more darker that the original ( see pic below).

I was wondering if it could be something related to gamma correction.
Also note that I’m using the exact same shader to render to the screen and to the render texture. The color format of the render texture is ARGB32, and to render the encoded depth and normals I’m using the texture that unity provides me ( _CameraDepthNormalsTexture).
Any Ideas?

I had this issue as well, and while I haven’t put in the time to find the root cause, my solution was to not use a pre-made render-texture, but instead generate it in code, which for some reason gives me a proper color space RenderTexture.
I had first tried fixing it by doing a pow(color, 1 / 2.2); to gamma correct in the shader, but when I sampled the colors in photoshop, they were still a bit off from my input colors.

RenderTexture outputMap = new RenderTexture(textureSize, textureSize, 32);
outputMap.name = "Whatever";
outputMap.enableRandomWrite = true;
outputMap.Create();
//Put the above stuff in Awake()  if you need to update this every frame...
RenderTexture.active = outputMap;
GL.Clear(true, true, Color.black);
Graphics.Blit(mainTexture, outputMap, rtMat);
3 Likes

I did the exact same thing lol. Thanks for your answer, I’ve already spent an entire day trying to figure this out.

Btw, is the GL.Clear necessary? If I understood correctly, with that you are clearing the current active render texture, which you just created so it should be empty, right?.

Nah it’s probably not necessary, just haven’t done a bake yet to test without it.

Alright, thanks!

Scratch that, at least in my case, without the GL.Clear, I just end up with a blank, transparent texture.

Oh wow, thank you for letting me know

Shouldn’t you be using _CameraDepthNormalsTexture instead of _CameraDepthTexture for normals?

Yes, I’m using that, I just noticed that I wrote the other one :stuck_out_tongue:

Were the screenshots above taken during run time? If so, the render texture will always be darker because Unity darkens everything except the Game preview area.

I did a quick test exporting the Render Texture as well as screen content to a png fie. They both turned out to be exactly the same.

Unfortunately I’m not at my computer at this moment but I believe that yes, it was taken during runtime. Will test it when I get home, thanks!

Well now I feel dumb, you were right :stuck_out_tongue: I can’t believe I didn’t notice it.

Btw is it possible that the _CameraDepthNormalsTexture is not generated when you do a camera.Render() in the editor?, because it seems to render gray, but in runtime works fine.

Happens to all of us. Just a day ago, I was wondering why the camera.Render() was messing up my depth. Turned out I forgot to set the depthbuffer on RenderTexture.

_CameraDepthNormalsTexture should be generated in editor mode as well. I was just playing around with it a few days ago.

Years late, but for anyone else reading, this can be an issue between linear and gamma space. If your project is in gamma, this’ll happen. You can use a pre-made RenderTexture, but in the Inspector options for that texture, try enabling sRGB (Color RenderTexture).

7 Likes

In Unity 2018.3+, I get a darkening due to what seems to be a bug in Unity’s handling of writing alpha values to the RT. If you’re in ARGB32 (as OP was), writing alpha values are rendered correctly in the Texture-Preview window (they blend), but it breaks Unity’s rendering of the resulting image in any Canvas. Short term solution is to switch down to RGB565 (RGB24 doesn’t exist as an option, which is depressing).

1 Like

For me, the source of the issue was in writing from RenderTexture to Texture using ReadPixels.
When you create Texture2D, there is an additional parameter: linear. Set it to true to avoid additional Gamma Correction.

Texture2D tex = new Texture2D(rTex.width, rTex.height, TextureFormat.RGB24, false, true); //last parameter
RenderTexture.active = rTex;
tex.ReadPixels(new Rect(0, 0, rTex.width, rTex.height), 0, 0);
tex.Apply();
13 Likes

This did it for me. :slight_smile:

It works! You are such a genius!

I did a minor adjustment to check if the texture is linear or not.
This should adapt to any texture format.

bool isLinear = !GraphicsFormatUtility.IsSRGBFormat(rTex.graphicsFormat);

Texture2D tex = new Texture2D(
    rTex.width, 
    rTex.height, 
    TextureFormat.RGB24, 
    false, 
    isLinear );
RenderTexture.active = rTex;
tex.ReadPixels(new Rect(0, 0, rTex.width, rTex.height), 0, 0);
tex.Apply();

Thanks. this did it for me.