函数图像绘制工具-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" //系统自带的漫反射
区别:
一个模型顶点的数量较少,放在顶点函数里计算会快点,不过效果可能不那么好,模型都是由很多面组成,而每个面只有三个顶点,逐顶点只是对每个顶点进行处理,而中间的像素值都是用插值(三角形遍历)得出的,所以就有点“敷衍”;
然后放在片元函数里效果会比较好,因为是对每个像素点进行处理,光照和阴影的过渡也很平滑,不过因为每个像素点都要计算,所以会对性能有影响。
兰伯特光照模型与半兰伯特光照模型
兰伯特光照模型:Diffuse = 平行光.颜色 * max(0,cosθ)
半兰伯特光照模型:Diffuse = 平行光.颜色 * (cosθ * 0.5 +0.5)
区别:通过公式我们可以看到处于背光面(与环境光的夹角 >= 90° )的cosθ值基本全为0-1,这样呈现出来的颜色即全为黑色;而半兰伯特通过变换公式,使得这部分的cosθ值处在01之间,使得背光面不是全黑的
cosθ
(cosθ * 0.5 +0.5)
代码修改
fixed3 diffuse=_LightColor0.rgb * max(0,dot(normalDir,lightDir));
改为
float halfLambert=dot(normalDir,lightDir)*0.5+0.5;
fixed3 diffuse=_LightColor0.rgb * halfLambert ;