Custom lighting models

Don't think I want to cover writing actual custom lighting models just yet. However, here is how you might implement the Lambert lighting model within your shader. Blinn is done below, with a brief explanation.

Essentially they are like mini functions. They must begin with the word "Lighting" and match the name of the lighting model that you specify in the #pragma surface surf ______

Lambert works by taking the dot product of the surface normal and light direction vectors. Where the light is aligned to the surface normal, the surface will seem brighter. As it gets closer to 90degrees/perpendicular the surface will be darker. This value NdotL is multiplied by the surface colour (albedo) ,the colour of any lights (_LightColor0, a built in variable) and the attenuation, which is how intense the light is.

 Shader "Dave/customLightingmodel" {
    Properties{
        _Color("Color",color) = (1,1,1,1)
    }

    SubShader{
        Tags{"Queue" = "Geometry"}
        CGPROGRAM
        #pragma surface surf BasicLambert
        
        half4 LightingBasicLambert(SurfaceOutput s, half3 lightDir,half atten) {
        half NdotL = dot(s.Normal,lightDir);
        half4 c;
        c.rgb = s.Albedo*_LightColor0*(NdotL*atten);
        c.a = s.Alpha;
        return c;
        }



        float4 _Color;


        struct Input {
        float2 uv_MainTex;
        };

        void surf(Input IN, inout SurfaceOutput o)
        {
        o.Albedo = _Color.rgb;
        }

        ENDCG
    }
     Fallback "Diffuse"

}

 

BlinnPhong is a bit of a different beast. It takes into account the viewing direction (ie the vector that goes to the camera/your eyes). It adds another vector into the mix, which we call "h", for the halfway vector. It is between the light direction and the viewing direction vectors and is calculated by normalising the sum of those two vectors.

The diffuse factor (diff) is calculated as in the lambert model, using the dot product of the surface normal and light direction. Then the specular factor is calculated by taking the dot product of the surface normal with the halfway h vector - it is then raised to a power. In the case of Unity, this power is 48.0
To calculate the final colour "c", we multiply the albedo colour by the light colour, by the diffuse factor and add this to the light colour multiplied by the spec. This is all then multiplied by the attenuation.

It's quite likely you'll never need to use this code... but at least you know what's going on...

Shader "Dave/customLightingmodelBLINN" {
    Properties{
        _Color("Color",color) = (1,1,1,1)


    }

        SubShader{
            Tags{"Queue" = "Geometry"}
            CGPROGRAM
            #pragma surface surf BasicBlinn

            half4 LightingBasicBlinn(SurfaceOutput s, half3 lightDir,half3 viewDir,half atten) {
        half3 h = normalize(lightDir + viewDir);
        half diff = max(0, dot(s.Normal, lightDir));
        float nh = max(0, dot(s.Normal, h));
        float spec = pow(nh, 48.0);
       
       
        half4 c;
        c.rgb = (s.Albedo*_LightColor0.rgb*diff+_LightColor0.rgb*spec)*atten;
        c.a = s.Alpha;
        return c;



}



            float4 _Color;
    struct Input {
        float2 uv_MainTex;
            };

    void surf(Input IN, inout SurfaceOutput o)
    {

        o.Albedo = _Color.rgb;

    }

        ENDCG
    }
        Fallback "Diffuse"

}

Comments

Popular posts from this blog

setting VFX graph properties using C#

scripting custom render texture creation, assignment, shaders