Unity Shader之自定义漫反射光照模型

不积跬步,无以至千里;不积小流,无以成江海。(来自《劝学》- 荀子)

在CSDN或者其他前辈的blog中大家都可以找到类似的教程
为什么我还要去写呢 , 主要是因为我想加入些自己的理解

发现文字真是个好东西,它可以引起人们的无限遐想,所以很多前辈都会推荐看书学习,也许正是因为这个原因吧。

本节重点
:如何在unity shader中实现可定义光照模型
注:unity3D在cginc中已经提供了很强大的光照模型函数,不过,一个好的项目,或者是一个好的游戏视觉冲击,需要的就不仅仅是这些了。

直接上代码了,注释将尽可能详细

shader"Cook Book Shader / Basic Diffuse"
{
    Properties
    {
        _MainTex("MainTex",2D) = "white"{}  
    }

    SubShader
    {
        //告诉系统在渲染非透明物体时调用这个着色器,当然也有在渲染透明物体时的设置,以后再说
        Tags{"RenderType" = "Opaque"}
        LOD 200

        CGPROGRAM
        //告诉着色器将采用basicdiffuse光照模型进行计算
        #pragma surface surf BasicDiffuse

        //声明一个光照模型函数,这里注意,函数名的格式是:Lighting + 你自定义的任何名字 以这里为例:Lighting + BasicDiffuse
        inline float4 LightingBasicDiffuse(SurfaceOutput s,fixed3 LightDir,fixed atten)
        { 
            //max大家应该很清楚,就是取当前最大值
            //而dot函数是CG语言的内置数学函数,作用呢便是知道两个向量之间的角度是多少
            //a b 两个向量点积运算可以用公式:a b = ||a|| ||b|| cos(a与b的夹角)
            //所以大家可以计算出,如果两个向量之间夹角是锐角,点积结果将大于0,反之将小于0,如果恰巧等于90度则点积结果为0

            //所以 在这里进行点积运算,max的作用便是限制点击函数的计算结果,确保计算结果永远大于0
            float DifLight = max(0,dot(s.Normal,LightDir));

            float4 col;
            //s.Albedo是surf函数处理后的输出,也就是说我们这个光照模型将在原基础上进行增强
            //这里的_LightColor0.rgb则来自unity,由Unity根据场景中的光源得到的,它在Lighting.cginc中声明的
            //然后再与刚才计算的光强系数(DifLight)和输入的衰减系数(atten)相乘
            col.rgb = s.Albedo  * _LightColor0.rgb * (DifLight * atten * 2);
            col.a = s.Alpha;

            return col;
        }


        sampler2D _MainTex;

        struct Input
        {
            float2 uv_MainTex;
        };

        void surf(Input IN,inout SurfaceOutput o)
        {
            float4 c = tex2D(_MainTex,IN.uv_MainTex);

            o.Albedo = c.rgb;
            o.Alpha = c.a;

        }





        ENDCG

    }

    fallback"Diffuse"
}

在最后介绍下三种格式的光照模型函数

1.half4 LightingName1(SurfaceOutput s,half3 LightDir,half atten){}
该函数用于不需要视角方向的前向着色(也就是我们刚才用的)
2.half4 LightingName2(SurfaceOutput s,half3 LightDir,half3 viewDir,half atten){}
该函数用于需要视角方向的前向着色(多了个viewDir)
3.half4 LightingName3_PrePass(SurfaceOutput s, half4 Light){}
用于延迟着色

还是忘记了说明一些问题,下面进行补充吧
1.surfaceOutput:是表面着色器的标准输出结构,它的内容是这样的

struct SurfaceOutput   
{  
    half3 Albedo;            //也就是纹理颜色值(r,g,b),上述shader中可以看出它的作用 
    half3 Normal;            //法线,法向量(x, y, z) , 上述中也用到了
    half3 Emission;          //自发光颜色值(r, g,b) 
    half Specular;           //镜面反射度 
    half Gloss;              //光泽度 
    half Alpha;              //透明度 ,上述中也用到了 
}; 

2.表面着色器必须放在SubShader块内,而不是指定在某个pass内,因为,表面着色器将在多重通道内编译自己。

你可能感兴趣的:(unity3d特效)