[Built-in] What is the formula from Light Intensity to RGB value in Linear-space ?

Hello,

I’ve read this post, but it seems to be for the Gamma space : Lighting Intensity and Overbright Color .

It gives this formula :

``````albedo * lightColor * lightIntensity * 2 = output
``````

I’m using the legacy Built-in pipeline.

My light intensity is 35. I’m using an unlit shader whose I’m scaling the output so it’d reach the luminance of the lit shaders.

``````fixed4 frag(v2f i) : SV_Target
{
return tex2D(_MainTex, i.texcoord) * _Color * fixed4(_ColorScale, _ColorScale, _ColorScale, 1);
}
``````

Manually, I found out the value should be around 1000.

If I convert the above formula to the linear space (if I got that correctly), then it gives :

``````pow(albedo * lightColor * lightIntensity * 2, 2.2) = output
``````

Which gives for the color scale with a light’s white color :

``````pow(35 * 2, 2.2) = 11460
``````

More than 10 times more than the empirical value, and the result is indeed way too bright !

So I ended up using this formula :

``````float ColorScale = Mathf.Pow(Sun.intensity * 0.5f, 2.2f) * 2f;
``````

which gives 1086, and works well for other light intensities as well.

But why the *0.5 and why the *2, I really wonder why…?!?

Is it how Unity converts the light intensity internally when using the Linear color space ?

Hi, convert to linear intensity

``````// Correct intensity calculation (Different from Unity)
var lightColorR = light.intensity * Mathf.GammaToLinearSpace(light.color.r);
var lightColorG = light.intensity * Mathf.GammaToLinearSpace(light.color.g);
var lightColorB = light.intensity * Mathf.GammaToLinearSpace(light.color.b);

l.color.Set(lightColorR, lightColorG, lightColorB);
``````

AFAIK, light intensity is already a linear value. You only want to linearize light color and albedo.

The texture value will be linearized automatically if it is in _SRGB format.

The color value will be linearized automatically if it is a Color struct, linear colorspace is set in the options and you are passing it via Material.SetColor or MaterialPropertyBlock.SetColor but not Shader.SetGlobalColor. Otherwise, you can convert it simply by calling the Color.linear property. Best check the frame analyzer if your color comes in linearized already.

@c0d3_m0nk3y ,
if the intensity was linear, then I’d likely not have to scale by ~1000 the unlit shader output to match the standard lit shader output.

All the colors are white, so their values are the same in Gamma & Linear space (ie: 1,1,1 for RGB), so we can completely ignore them in the calculations.