Image effect "Color Correction Curves" doesn't work correctly with Linear Space rendering ; how to fix that?

Hello,

title says it all :
Image effect “Color Correction Curves” doesn’t work correctly with Linear Space rendering ; how to fix that ?

More explanations :
I’m creating a brightness slider using the “Color Correction Curves” Image effect ( http://docs.unity3d.com/Documentation/Components/script-ColorCorrectionCurves.html ).


===1st Issue=== SOLVED!
The expected result, which I'm getting with Gamma Space rendering is : http://s12.postimage.org/fiuwyv2r0/Color_Correction_Curve_Gamma_Space_Rendering.jpg

The actual result, with Linear Space rendering is :

For comparison, without brightness change :

As you can see by looking at the created curve, it’s like 95% of the colors are mapped within [0; 0.01], while the 5 other % are within [0.01; 1] (ie: all values within [0.01; 1] should be remapped to 1 after the correction, and it’s obviously not the case).

I checked the remapping texture creation (the colors are remapped using that texture), and the result is same either “linear” is true or not.
I checked the texture filling, and the correct values are put in it.

ANSWER:
I found what’s going on : this is actually a normal result. The screen in Linear space is more dark, thus there are a lot of pixels with 1 or more of their RGB channels to have a value of 0, 1, 2 or 3, thus even with full brightness on [4;255] ( = [0.0125; 1] which is my exact range giving an output value of 1 in my curve), there are a lot of pixels who don’t end fully white, but instead they end pure yellow, or even in mid-tones.


2nd Issue: In Progress!
The Image Effect "eats" the dark colors, even with 1:1 curve (ie: f(x) -> x).

Look this, this is without the effect enabled :

Now, with the effect enabled, with a flat curve (y = x) :

The colors which RGB values are under about 10/255 in the 1st screen ends all being at 0 in the 2nd screen.

According to this Unity - Manual: Color space , as I’m using HDR mode, the render buffer should be in float, thus it should support reading & re-writing without losing these dark details, but it doesn’t.

How to make it work ? Should I modify the texture type ? The way the shader works ?


Thanks in advance for any help about this matter…!

Ok, I post a self-answer :

About 1st issue, as explained in the question :
in the linear space render buffer, dark values get much darker, as the linear space intensity (LSI) is equal to power(Gamma Space Intensity, 2.2).
It means, 1/255 in the final output is pow(1/255, 2.2) = 0.0013/255 in the Linear buffer, and 10/255 is 0.2/255, and 21/255 is 1.05/255 . This means the whole [0-20] range equals 0 if floored to a classic 8 bits buffer.

Thus the surprising result I got with the whole range [0.0125; 1] being remapped to 1, and 0 being still mapped to 0.

About 2nd issue, as explained in the comments :
the issue comes from the texture sampling that is not accurate enough. The solution is to dump the texture sampling all together, and use pow() function ( = gamma correction) directly within the fragment shader to get a correct result, like this :

	half4 frag(v2f i) : COLOR
	{
		half4 color = tex2D(_MainTex, i.uv);
		return pow(color, _Gamma);
	}

It means I can’t use too special curves, but in my case, it’s alright.

As this issue can raise with all Image Effects using a texture to remap the RGB channel values while using a Linear Space render buffer, I hope these explanations will save a few headaches to fellow coders… :slight_smile:

And if you use HDR and want some gamma/brightness correction, have a look at Tonemapping effect, it can do the trick (it’s much more complex than a gamma correction though).