【Shader笔记2】基础光照-逐顶点漫反射和逐像素漫反射

函数图像绘制工具-https://zh.numberempire.com/graphingcalculator.php?
两者都是漫反射,只是处理光照的函数一个放在顶点函数里,一个放在片元函数里

一.逐顶点漫反射

 Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

			#include "Lighting.cginc"
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
				float3 normal:NORMAL;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
				fixed3 color:COLOR;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);

				//环境光的颜色
				fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.rgb;

				//模型空间转换到世界空间
				fixed3 normalDir=normalize( mul(unity_ObjectToWorld,v.normal));

				//取到世界空间下平行光的位置
				fixed3 lightDir=normalize(_WorldSpaceLightPos0.xyz);

				//取得第一个平行光的颜色_LightColor0.rgb
				fixed3 diffuse=_LightColor0.rgb*max(0,dot(normalDir,lightDir));
				o.color=diffuse+ambient;

                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                return fixed4(i.color,1);
            }
            ENDCG
        }
}

二.逐像素漫反射

 struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
				fixed3 worldNormalDir:COLOR0;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
				
				//把模型空间中的法线向量转换到世界空间中,然后传给片元函数
				o.worldNormalDir=normalize( mul(unity_ObjectToWorld,v.normal));

                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {	
				//法线向量归一化
				fixed3 normalDir=normalize(i.worldNormalDir);

				fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.rgb;
				fixed3 lightDir=normalize(_WorldSpaceLightPos0.xyz);
				fixed3 diffuse=_LightColor0.rgb * max(0,dot(normalDir,lightDir));
				fixed3 tempColor =diffuse+ambient;
                return fixed4(tempColor,1);
            }
            ENDCG
        }
    }
	FallBack"DIFFUSE" //系统自带的漫反射

区别:
一个模型顶点的数量较少,放在顶点函数里计算会快点,不过效果可能不那么好,模型都是由很多面组成,而每个面只有三个顶点,逐顶点只是对每个顶点进行处理,而中间的像素值都是用插值(三角形遍历)得出的,所以就有点“敷衍”;

然后放在片元函数里效果会比较好,因为是对每个像素点进行处理,光照和阴影的过渡也很平滑,不过因为每个像素点都要计算,所以会对性能有影响。
【Shader笔记2】基础光照-逐顶点漫反射和逐像素漫反射_第1张图片
兰伯特光照模型与半兰伯特光照模型
兰伯特光照模型:Diffuse = 平行光.颜色 * max(0,cosθ)
半兰伯特光照模型:Diffuse = 平行光.颜色 * (cosθ * 0.5 +0.5)
区别:通过公式我们可以看到处于背光面(与环境光的夹角 >= 90° )的cosθ值基本全为0-1,这样呈现出来的颜色即全为黑色;而半兰伯特通过变换公式,使得这部分的cosθ值处在01之间,使得背光面不是全黑的

cosθ
【Shader笔记2】基础光照-逐顶点漫反射和逐像素漫反射_第2张图片
(cosθ * 0.5 +0.5)
【Shader笔记2】基础光照-逐顶点漫反射和逐像素漫反射_第3张图片
代码修改
fixed3 diffuse=_LightColor0.rgb * max(0,dot(normalDir,lightDir));
改为
float halfLambert=dot(normalDir,lightDir)*0.5+0.5;
fixed3 diffuse=_LightColor0.rgb * halfLambert ;

你可能感兴趣的:(Shader)