UNITY_LIGHTMODEL_AMBIENT equal to half the expected value?

I’m starting to learn how to write shaders so when playing around with a shader I was writing I noticed something odd. My ambient light was a lot darker than I expected.

I set the ambient light in the render settings to full red (255, 0, 0) and the built in diffuse shader correctly display the object (in a lightless world) as bright red. However, my object was displaying as a darker red. I did some testing and realized that it was exactly half as red. I don’t understand why this is? Here’s a sample shader showing what I am doing.

Shader "test/AmbientOnly" 
{
    SubShader 
    {   
        Pass
        {   
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag

            // base structs
            struct vertexInput
            {
                float4 vertex : POSITION;
            };

            struct vertexOutput
            {
                float4 pos : SV_POSITION;
                float4 color : COLOR;
            };

            // vertex function
            vertexOutput vert(vertexInput v)
            {
                vertexOutput output;

                float3 colorFinal = UNITY_LIGHTMODEL_AMBIENT;

                // Debug purposes
                if (colorFinal.r == 0.5)
                {
                    // When I place the ambient light to full red only (255, 0, 0) then this triggers and it turn it green.
                    colorFinal.r = 0;
                    colorFinal.g = 1;
                }
                else
                {
                    // Otherwise I double the values and it turns the appropriate color.
                    colorFinal *= 2;
                }

                output.color = float4(colorFinal, 1.0);
                output.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                return output;
            }

            // fragment function
            float4 frag(vertexOutput i) : COLOR
            {
                return i.color;
            }

        ENDCG
        }
    } 

    // Fallback "Diffuse"
}

As this shader shows, I will make the object bright green if it detects the ambient light being at half (which is FULL in the render settings) otherwise will double the values. Once doubled it correctly matches the built in shader.

I’d like to just understand why this is! Thanks!

Well I cant say why its half … but I can say from having dabbled with shaders a little bit and having looked at many examples that light calculation results always seem to get multiplied by 2… like its some sort of standard. I do it in my shaders as well, perhaps someone clever knows the actual reason … anyone?

It is indeed multiplied by 2, just need to account for that. perhaps an early unity oversight that stayed for compatibility.

All lighting values in Unity are multiplied by 2.

It was an early thing to allow for overbrightening, and it’s had to stay in for compatibility reasons. I think Aras mentioned it may get removed in the next major release (Unity 5) but that it’ll have to stay in for this cycle at least so that it stays consistent.

Cool, thanks for the information. Will keep in mind!

Actually, the _LightColor0 in my case need to multiply by 3, not 2. And by the way, where is the documentation that specify the multiplier for light color ?

There is no documentation, just the built-in shader code - everything is multiplied by 2.