一个Shader包含了很多我们不经常遇到的内容,这些内容和程序常用的编程有很大不同,我希望不要太多凭空出现的变量和公式,这样会加大我们掌握东西的难度。其中下面的内容很大一部分涉及了:

1. 大量数学知识,其中很大一部分几何学
2. 物理光照模拟,其实这个也是数学
3. 还有一些颜色在数学里的计算
4. 还有一些硬件指征(渲染管线)
5. 以及之前我们整理的内置变量和内置函数等
6. 还有一些预备知识: 比如模型导出来的时候,就会带有顶点信息,以及法线等信息,这些都是我们需要准备的知识,这里我只能再以后慢慢补充了,现在先写一点是一点

在这一章节开始之前有一个很有意思的地方: vert >> fragment的执行次数,这也是一个硬件指征


下面,我们还是从代码开始进入今天的内容

Shader "Custom/Chapter 6/DiffuseVertexLevel" {
    // Unity提供的方法,C#和编辑器可以向Shader通过属性(Properties)传递参数
    Properties {
        _Diffuse ("Diffuse",Color) = (1,1,1,1)
    }
    SubShader {
        Pass {
            Tags {"LightMode" = "ForwardBase"}              // 1.标签:光照流水线,定义了才能得到一些内置光照变量
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "Lighting.cginc"                       // 2.引用:光照,后面用到 _LightColor0
            fixed4 _Diffuse;                                // 3.1 变量:声明属性变量
            struct a2v {
                float4 vertex : POSITION;                   // 4.语义:顶点位置(模型空间)
                float3 normal : NORMAL; 
            };
            struct v2f {
                float4 pos : SV_POSITION;
                fixed3 color : COLOR0;
            };
            v2f vert(a2v v) {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex); // 5. 内置函数,相当于左乘MVP
                // 3.2 获得环境光,Unity内置变量
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;                          
                // 3.3 内置变量 等价 UnityObjectToWorldNormal(v.normal)
                // 5.1 计算方法. 将法线从模型空间转到世界空间
                fixed3 worldNormal = normalize(mul(v.normal,(float3x3)unity_WorldToObject));    
                // 3.4 求光源方向(归一化:世界空间中的),光源方向(假设场景只有一个光源且为平行光)
                fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);                
                // 3.5 _LightColor0:光源颜色和强度。
                // 3.6 saturate:把参数限制在[0,1],CG提供的函数
                // 6. 漫反射公式:通过这个公式叠加计算后的颜色值,o.color直接赋值了操作
                // 7. 颜色乘法 5.2 叉乘点乘
                fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal,worldLight));
                o.color = ambient + diffuse;
                return o;
            }
            // 9. SV_Target标签
            fixed4 frag(v2f i) : SV_Target {
                return fixed4(i.color,1.0);
            }
            ENDCG
        }
    }
    FallBack "Diffuse"
}

1. 标签

Unity Shader Tags

标签告诉引擎:如何和何时执行此Shader的动作。待整理

2. 引用

我们在之前的(二)中讲过: 内置变量和函数是通过Include包含进来的。

3. 变量

内置变量

3.1 我们定义的参数: _Diffuse,此变量也在Property中有声明。可以通过C#脚本到顶点vert再到fragment传递
3.2 ~ 3.5 都是内置变量了,再之前的(二)我一样有过整理一些。
3.2 UNITY_LIGHTMODEL_AMBIENT
3.3 unity_WorldToObject
3.4 _WorldSpaceLightPos0
3.5 _LightColor0

4. 语义

待补充

6. 常用计算

左乘右乘:
归一化:


7. 颜色计算方法