Any reason why this shader isn't compiling? :|

Hello guys,

I’ve recently started to port a set of shaders (part of my personal self-free-learning-time). I have some CgFX shading programming knowledge so I’ve decided to get my hands quite dirty on more low level graphic programming stuff, by recreating some lighting models from scratch, using the depth buffer (more in deep ^^) etc, all using plain Cg inside Unity instead of surface shaders.

So, this shader, is the first part of a simple shader that I’m working on. At it’s current stage, It takes a color and a light direction as an input and computes it using the lambert lighting equation.
Though, for an unknown reason I’m having two weird errors! Which btw doesn’t really tell me anything.
Here is:

Shader code:

Shader "Mobile FM/Lambert_Color" 
{
    Properties 
    {
        _Color ("Main Color", Color) = (1,1,1,0.5)
        _MainTex ("Texture", 2D) = "white" {}
        _lightDirection ("Light Direction", Vector) = (0.5, 0.5, 0.5, 1.0)
    }
    SubShader 
    {
        Pass
        {            
            CGPROGRAM [COLOR=red][B]//THIS CORRESPOND TO THE LINE 13[/B][/COLOR]
            #pragma vertex vShader
            #pragma fragment pShader
            //#include "UnityCG.glslinc"
            
            //////////////////////////////////////////////////////////////
            // Matrices Section 
            float4x4 worldViewProjection     : WorldViewProjection;   
            float4x4 worldInverseTranspose   : WorldInverseTranspose; 
            float4x4 viewInverse             : ViewInverse;           
            float4x4 world                   : World;                 

            //////////////////////////////////////////////////////////////
            // Parameters section             
            float4 _Color;
            sampler2D _MainTex;
            float4 _lightDirection;
            
            //////////////////////////////////////////////////////////////
            // Structs section 
            // input from application
            struct a2v 
            {
                float4 position  : POSITION;
                float4 normal    : NORMAL;
            };

            // output to fragment program
            struct v2f 
            {
                    float4 position        : POSITION;
                    float3 worldNormal     : TEXCOORD0;
            };

            //////////////////////////////////////////////////////////////
            // Vertex Shader 
            v2f vShader(a2v In)
            {
                v2f Out;
                Out.position = mul(worldViewProjection, In.position);
                Out.worldNormal = mul(worldInverseTranspose, In.normal).xyz;
                
                return Out;
            }

            //////////////////////////////////////////////////////////////
            // Pixel Shader 
            float4 pShader(v2f In) : COLOR
            {
                float4 outColor;
                
                float3 worldNormal = normalize(In.worldNormal);
                //float3 lightDirection = float3(_lightDirection.xyz);
                //float3 lightDir = normalize(-(_lightDirection)).xyz;
                float3 lightDir = normalize(-(float3(0.5f,0.5f,0.5f)));
                
                float3 lambert = saturate(dot(lightDir, worldNormal));
                
                outColor.rgb = lambert * _Color;
                outColor.a = 1.0f;
                
                
                return outColor;
            }
            ENDCG
        }
    } 
    Fallback "VertexLit"
}

Any reason why this shader isn’t compiling? :expressionless:

I think the proper channel is

float4	pos : SV_POSITION;

rather than

float4	position : POSITION;

I think SV_POSITION is from Unity internal definitions (UnityCG.glslinc). Using POSITION semantic should work out of the box i guess. I’ll try it out to be sure.

Hi. I am not so experienced in shaders, but I hope this code might help you

Shader "Mobile FM/Lambert_Color" 
{
    Properties 
    {
        _Color ("Main Color", Color) = (1,1,1,0.5)
        _MainTex ("Texture", 2D) = "white" {}
        _lightDirection ("Light Direction", Vector) = (0.5, 0.5, 0.5, 1.0)
    }
    SubShader 
    {
        Pass 
        {
            CGPROGRAM
            #pragma vertex vShader
            #pragma fragment pShader
            
            
            float4x4 worldViewProjection     : WorldViewProjection;   
            float4x4 worldInverseTranspose   : WorldInverseTranspose; 
            float4x4 viewInverse             : ViewInverse;           
            float4x4 world                   : World;  
            
            float4 _Color;
            sampler2D _MainTex;
            float4 _lightDirection;
            
            struct a2v 
            {
                //Cannot change this name from vertex to position, gives errors
                float4 vertex : POSITION;
                float4 normal    : NORMAL;
            };
            
            struct v2f 
            {
                float4 pos : POSITION;
                //Since you use only the first 3 components in line 49, I placed float3 here
                float3 worldNormal : TEXCOORD0;
            };
            
            v2f vShader (a2v  In) 
            {
                v2f  Out;
                //This seems wrong, should be sth like model view projection instead
                Out.pos = mul( worldViewProjection, In.vertex );
                Out.worldNormal = mul(worldInverseTranspose, In.normal).xyz;
                return  Out;
            }
            
            
            
            half4 pShader( v2f In ) : COLOR 
            {
                float4 outColor;
                float3 worldNormal = normalize(In.worldNormal);
                float3 lightDir = normalize(-(float3(0.5f,0.5f,0.5f)));
                float3 lambert = saturate(dot(lightDir, worldNormal));
                outColor.rgb = lambert * _Color;
                //Since you are not enabling blending, this seems useless
                outColor.a = 1.0f;
                return outColor;
            }
            ENDCG
        }
    } 
    Fallback "VertexLit"
}

I would replace

with

for a start.
Good luck !

@Ippokratis,
You are right on the projection matrix, i should use modelViewProjection instead of worldViewProjection! I could also go with your suggestion (UNITY_MATRIX_MVP) but that requires using the UnityCGs which i’m trying to avoid right now. :wink:
Regarding the compile error, it looks like a Unity compile bug.

Unity can’t seem to differs two variables on differents structs using the same name.
For example in my case i got two structs (a2v and v2f) which are different structs but have the same variable type/name (position).
If i change one of the position variable name the errors goes out. Weird.
Can someone at Unity confirm if this a bug or not?

[EDIT] Seriously, can’t figure out what’s going on here. Using position as the name of the struct variables gives some weird errors. But using vertex as the name of the variable (for each struct) doesn’t give any errors and using vertex and position (position and vertex) as struct variable names doesn’t give any errors, what the h**l is going ont here?

[EDIT2] I just discovered that a2v struct variable name “must” be “vertex” (can’t change it) or i get compile errors. Seirously… :expressionless:

Hi,

You can use UNITY_MATRIX_MVP without UnityCG.cginc. Also, I cannot understand how to pass this matrix to the shader otherwise.
I tried other names for

All of them do not work for some reason. My knowledge is limited on why.
[EDIT] Solved, see below.
I try to learn Cg at the moment, if you have some resources or examples that you try to port in unity I see it as a nice exercise.
Bring more :slight_smile:

I’ve updated my post above, check it out.

I’m also learning more in deep graphic programming right now (i got some CgFX knowledge and I’m trying to get my hand a bit dirtier by converting them into plain Cg inside Unity). My goal is to create optimized mobile shaders, I’ll post them all here, so we can debug those things all together and learn more low level graphic thingies! :slight_smile:
The first part of this series is a full lambertian lighing model, then I’ll move out to others lighting models (phong, rim, etc).
Tanks for your input! Ippokratis!

It works now (but the issue with structs variable names still there):

Hi,
Regarding the reason for obligatory naming the POSITION semantic as vertex in the a2v struct :
In the docs ( second paragraph, after the first example ) states :

Yeah,
I’ve made a deep search on the documentation about CG programs inside Unity and found the page you just posted regarding struct members name (which in fact makes sense cause that’s the only way Unity pass internal 3D data to the CG program mind you). I forgot to post them out over here. But tanks anyways. Hopefully that will do it for a moment, till i got a good working optimized mobile shader (or any other trouble). ^^
I’m keeping an eye here, just in case. :wink: