Linear, Gamma and Render Textures.

Hi guys,

I have a texture. Now I want to send its data to a video encoder (which takes a byte[ ] as input) so I use ReadPixels(), then GetPixels32().

This works fine in gamma space, however when storing stuff in linear space into this texture (which is a must, as I use it to additively blend several layers of images), then using GetPixels32(), it returns linear space data and I must do the conversion to gamma space manually, pixel by pixel, which is terribly slow.

Is there any way to get Color32 values from a texture, already converted to gamma space? (Edit: setting the “linear” parameter in the Texture2D constructor to true or false has no effect on the values returned by GetPixels32)

Thanks!

Hi!
Why don’t you use a shader to do the conversion?

Hi! Thanks for the answer!

I did just that literally an hour ago, came back to post the solution:

I perform a Blit() from the original RenderTexture to a second one, using a shader that applies the ^0.45 conversion. Then, bind this second RT and call ReadPixels(). Works nice and fast.

Still, it would be nicer for ReadPixels() to optionally perform the conversion itself, depending on what the active RT is (linear or sRGB). Or get GetPixels32 to do the same based on the Texture2D (the Color class already has .linear and .gamma properties, but calling this pixel by pixel which is what I was initially doing is too slow). Maybe there’s a built-in way to achieve it (or a good reason for ReadPixels and GetPixels to stay colorspace agnostic) but in case anyone comes across the same problem: using a shader works fine.

ReadPixels and GetPixels just give you the values stored in the memory, without trying to interpret stuff like color space, as they should. Doing a conversion manually is not a big deal, so I don’t think it’s worth it to provide this as built-in functionality.

2 Likes

Assuming that you have an input texture (Texture2D), how can you learn if GetPixels returns colors in the linear space? There doesn’t seem to be a way to detect this based on just a texture. My understanding is that if you want to e.g. blend two textures in CPU, it should be done in the linear space. If a texture is in the linear space, it should not be converted to the linear space before the blend operation. However, if the texture is in the gamma space, it should be converted to the linear space.
When you import a texture in the Unity Editor, you can tick the “sRGB (Color Texture)” check box. According to the description, it will matter for a shader, but it doesn’t seem to matter for GetPixels operations. So if you want to process a texture in CPU, by using GetPixels, you would need to know if sRGB was ticked or not, but the value of this checkbox doesn’t seem to be stored with the Texture2D object or am I missing something?