Fragment shader output colour has incorrect values when hardcoded

Hi guys,

I’m experimenting with some custom shaders but have noticed that when I output a hardcoded colour in the fragment shader it gives me a different colour that expected. For example return float4(0.5f, 0.5f, 0.5f, 1.0f); gives me #BCBCBC instead of #808080 as expected.

However, if I define a property and return its value (untouched/unedited), it gives the correct colour.

The below gives some examples of some variations I’ve tried which cause/don’t cause this issue to occur.

Does anyone have any suggestions as to what could be the cause of this?

Note: the below is a dumbed-down version of a more complex shader which I had to strip down in order to pinpoint the source of my problem: the “return output.color;” in the frag shader which was not returning the proper colour…which then led me to notice the whole colour discrepancy issue.

Shader "Faction Overlord/VectorColour" {
    Properties
    {
        _ExplicitColour ("Explicit Colour", Color) = (0.5, 0.5, 0.5, 1.0)       
     }
   
    SubShader {
        Lighting Off Blend Off
        Pass {
            CGPROGRAM

            #pragma vertex vert            
            #pragma fragment frag
           
            float4 _ExplicitColour;
       
            struct vertInput {
                float4 pos : POSITION;
                float4 color : COLOR;
            }; 

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

            vertOutput vert(vertInput input) {
                vertOutput o;
                o.pos = mul(UNITY_MATRIX_MVP, input.pos);
                o.color = input.color;
                return o;
            }

            float4 frag(vertOutput output) : COLOR {
                //return output.color;
               
                //Originally this was meant to output the vertex colour (hence the commented-out lines of code above), which was returning a wrong colour
                //So I tried multiple variations of setting explicit values, as below, with and without the "f" after each number
               
                //=====================
                //These don't work well
                //=====================
               
                return float4(0.5, 0.5, 0.5, 1.0);
               
                //output.color = float4(0.5, 0.5, 0.5, 1.0);
                //return output.color;
               
                //_ExplicitColour = float4(0.5, 0.5, 0.5, 1.0);
                //return _ExplicitColour;
               
                //===============
                //These work well
                //===============
               
                //return _ExplicitColour;
               
                //or
               
                //float4 f = float4(_ExplicitColour[0], _ExplicitColour[1], _ExplicitColour[2], _ExplicitColour[3]);
                //return f;               
            }
           
            ENDCG
        }           
    }
}
1 Like

Color material properties are actually defining color in sRGB. That means color (0.5, 0.5, 0.5, 1.0) equals RGBA 127.5 127.5 127.5 255.0 will get rounded to RGB 128, 128, 128 or that expected #808080.

Colors defined in the shader are in linear space, so float4(0.5, 0.5, 0.5, 1.0) ends up as RGB 188 188 188 or #BCBCBC

4 Likes

Oh I see! That pointed me in the right direction! It turns out that somehow my project was set to use linear lighting.

I realised this since the shader was also interpreting values set via C# code incorrectly as well (only inspector-set values were being properly converted).

Switching it off (Project Settings → Player → Other Settings → Color Space) fixed the issue.

Thanks a whole bunch!

3 Likes

Thanks, Save my Day.