LIGHT_ATTENUATION doesn't work

Hi, I’m trying to get the atten of a point light in a forwardadd pass, I add LIGHTING_COORDS in my v2f struct, and TRANSFER_VERTEX_TO_FRAGMENT in the vertex function. Then I use LIGHT_ATTENUATION to get the atten in the fragment function. But it seems that nothing changed when I move the point light away from my model.

Here is my forwardadd pass code:

        Pass {
            Tags { "LightMode" = "ForwardAdd" }
           
            Cull Back
            Lighting On
            Blend One One
           
            CGPROGRAM
           
            #pragma vertex vert
            #pragma fragment frag
           
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            #include "AutoLight.cginc"
           
            sampler _MainTex;
            sampler _BumpTex;
           
            float4 _MainTex_ST;
            float4 _BumpTex_ST;
           
            struct a2v {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float4 texcoord : TEXCOORD0;
                float4 tangent : TANGENT;
            };
           
            struct v2f {
                float4 pos : POSITION;
                float2 uv : TEXCOORD0;
                float2 uv2 : TEXCOORD1;
                float3 lightDirection : TEXCOORD2;
                LIGHTING_COORDS(3,4)
            };

            v2f vert(a2v v) {
                v2f o;
               
                TANGENT_SPACE_ROTATION;
                o.lightDirection = mul(rotation, ObjSpaceLightDir(v.vertex));
                o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                o.uv2 = TRANSFORM_TEX(v.texcoord, _MainTex);
               
                TRANSFER_VERTEX_TO_FRAGMENT(o);
                return o;
            }
           
            float4 frag(v2f i) : COLOR {
                float4 c = tex2D(_MainTex, i.uv);
                float3 n = UnpackNormal(tex2D(_BumpTex, i.uv2));
               
                float3 lightColor = float3(0);
               
                float lengthSq = dot(i.lightDirection, i.lightDirection);
                float atten = LIGHT_ATTENUATION(i);
               
                // Angle to the light
                float diff = saturate(dot(n, normalize(i.lightDirection)));
                lightColor += _LightColor0.rgb * (diff * atten);
               
                c.rgb = lightColor * c.rgb * 2;

                return c;
            }
           
            ENDCG
        }

What’s wrong with it?

I solved it myself. All thing is right when I add #pragma multi_compile_fwdadd.

But I don’t know why… What has multi_compile_fwdadd done?

It tells Unity that this pass should be a forward add pass - this is the additive pass for all point/spot lights and for any extra directional lights (forward base gets the most prominent directional light - or no lights at all if there are no directional lights).

Thanks for your reply. But i thought Tags { “LightMode” = “ForwardAdd” } had done that for me! The Doc said:

  • ForwardAdd: Used in Forward rendering; additive per-pixel lights are applied, one pass per light.

So why i need to add #pragma multi_compile_fwdadd when i have already add Tags { “LightMode” = “ForwardAdd” } to the pass?

Not 100% sure.

As far as I understand it, the LightMode tag doesn’t tell Unity to compile the shader to be compatible as a forward add pass, only that it should be treated as one when it comes to rendering it.

I found some info from this thread. Aras said, “If your shader pass doesn’t have any LightMode tags, then no light variables are set up.” So LightMode tags set some light variables, and #pragma multi_compile_fwdadd set something other? If i want to get everything right, i’d better add both of them to the pass. Am i right?

Yes, the pass should have both of them in order to fully work as forward add.

Hope that Unity would provide more details. :frowning:

Thanks for the help.