Position required for color-input-only fragment shaders? (possible bug?)

Hi,

I’m starting to learn shaders. At first, I was implementing my shaders in an OpenGL program I have created, just to study them better, but now I’m moving to Unity to make it easier to test my shaders. I wrote some small shaders just to test the implementation of vertex and fragment shaders with ShaderLab, but one of these small shaders is getting me confused because it didn’t work as expected.

The vertex shader I wrote just outputs the clip space position and a red color for the vertex. The fragment shader is just supposed to receive the color (which has been output by the vertex program) and output it (that is, the fragment shader is just a simple passthrough program). Here is my code:

Shader "Tests/MyTest" {
    SubShader {
        Pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            struct VertexInput {
                float4 position : POSITION;
            };

            struct VertexOutput {
                float4 position : POSITION;
                float4 color : COLOR;
            };
           
            struct FragmentInput {
                float4 color : COLOR;
            };
           
            VertexOutput vert( VertexInput input ) {
                VertexOutput output;
                output.position = mul( UNITY_MATRIX_MVP, input.position );
                output.color = float4( 1, 0, 0, 1 );
                return output;
            }
           
            half4 frag( FragmentInput input ) : COLOR {
                return input.color;
            }
            ENDCG
        }
    }
}

I have applied this shader to a material used in a sphere which I have created in Unity. The problem is: the sphere is rendered in a black color, instead of red!

What’s making me even more confuse is that to fix this, I only have to add a position field to the FragmentInput struct, like that:

            struct FragmentInput {
                float4 thePos : POSITION;   // added this
                float4 color : COLOR;
            };

Voilà! The sphere turns red with this simple declaration. And what’s even weirder: the position field I’ve just added has to be declared as the struct’s first member. If it is declared after the “color” member, the sphere just turns black again…

Why is this happening? Why do I need to input the position to the fragment shader program, if the fragment shader program doesn’t even use it? Am I missing something here? Is this a bug?

Thanks in advance =)

The output struct out the vertex shader must be the same than the input struct of the fragment/pixel shader

What is happening here is that if you declare position in a different order, it won’t match properly (position will be in color and vice versa…)

Just use VertexOutput as input for the fragment shader. Values in it will be interpolated for each pixels.

Careful though, the semantic for clip position is “SV_POSITION” not “POSITION” (I think Dx9 still ok with it, but better use the right semantic you never know!)