Return Raw Float Values From Frag Shader

Hi,
I was converting some OpenGL code to Unity and ran into an issue. I have a solution where I was do some calculations on the Frag Shader. I just realized that all return values are being clamped to a max of 1.

So for instance, in openGL my frag shader has:

out vec4 gl_FragData;
gl_FragData = vec4(5.0f, 6.0f, 7.0f, 8.0f);

and when I read the values out with:

glReadPixels(0,0,widthTexture, heightTexture, GL_RED, GL_FLOAT, myBuff);

I will have a buffer populated with floats with a value of 5.0f.

In Unity my shader returns:

return float4(5.0f, 6.0f, 7.0f, 8.0f);

when I read the pixels back everything is clamped to 1.0

Cannot seem to find an answer in the documentation. Would really appreciate any help

What is the format of the buffer you’re rendering to? Is not HDR checked on for the camera or have you assigned a non float/half render texture as the target?

Hey, HDR is checked and the RenderTarget is ARGB32. I am reading back into a Color array with
So my shader returns:

return float4(0.5f, 0.9f, 7.5f, 1);

and I read back the data with:

Color[ ] buffer= myTex.GetPixels();

buffer now has values of Color(0.5, 0.9, 1, 1);

Thanks for any help

Each of RGBA color channels is stored as an 8-bit value in [0…1] range.

you need a format with “float” or “half” in its name

Hey, cheers. I had spotted that. I did switch to ARGB Float but same issue.

maybe you’re reading data after tonemapping?

I think its the fact that I am reading into a Color array it is clamping the return value to 0-1. Not sure how to read back raw float data. Any ideas?

how do you render to your texture? when do you read the data? I’m pretty sure it’s default tonemapping which mangles your texture (by clamping values to the 0-1 range)

What format is the Texture2D you’re copying data to? Is it RGBA32 or RGBAHalf/Float? Is the render texture also ARGBHalf/Float? If they’re not both float or half formats, the values will be clamped.

1 Like

there is no second texture, he gets data to RAM with GetPixels

So I am basically doing a custom render on each of my agents into a RT.

Graphics.DrawMeshInstanced(agentProxy.Mesh,
0,
agentMat,
idents,
null,
UnityEngine.Rendering.ShadowCastingMode.On,
false,
LayerMask.NameToLayer(“Agents”));
AgentCam.Render();

The camera has got HDR enabled so that I can get values of greater than 1. This is called once per Update and written into a . Once every agent has rendered into the RT the values are then read back into a buffer at the end of the Update:

Color[ ] h_idata = myTex.GetPixels();

Not sure about the tone mapper and how to read before its being changed back into LDR.

There has to be a second texture. You can’t read a RenderTexture using GetPixels(). You have to copy the RenderTexture’s contents to a Texture2D using ReadPixels() before you can use GetPixels() to read the values of the Texture2D.

1 Like

Graphics.DrawMeshInstanced doesn’t draw mesh instantly, instead, it enqueues it to be rendered within the normal rendering loop (after update, lateupdate and so on). so you’re actually reading data from the previous frame, after tonemapping.

or maybe bgolus is right and it’s simply because of the format of your texture2d

Thanks guys, I appreciate the help. I do create a Texture to read back from, the texture looks great, just the clamp at issue for further processing.

Finally got it. I had to set the TextureFormat on the Texture2D to RGBAFloat also. Thanks for helping me guys, small error but I probably would have been tearing my hair out next week trying to figure this out.

1 Like