在片元着色器中计算光照模型,成为逐像素光照;在顶点着色器中计算,称为逐顶点光照。
在逐像素光照中,会以每一个像素为基础进行光照计算,得到法线进行插值计算,这种技术叫做Phong着色。
逐顶点光照,也称为高洛德着色,我们在每一个顶点进行光照计算,然后会在渲染图元内部进行线性插值,最后输出成像素着色。
逐顶点光照的性能开销远远小于逐像素,这是因为顶点数远远要小于像素数(这也是为什么在移动平台shader能逐顶点绝不逐像素的原因)。但是由于逐顶点的像素依赖于顶点的线性插值来取得效果,因此只要是非线性的光照计算使用逐像素光照都会或多或少的产生有问题的效果(如高光要对_Gloss进行乘方)。
区别:说白了就是,光照计算的逻辑是在vertex函数或者fragment函数中。
例如:
//在顶点中计算漫反射
Properties{
_Color("Color",Color) = (1,1,1,1)
}
SubShader{
Pass{
Tags{"LightMode" = "ForwardBase"}
CGPROGRAM
#include "Lighting.cginc"
#pargma vertex vert
#pargma fragment frag
fixed4 _Color;
struct app_data{
float4 vertex:POSITION;
fixed3 normal:NORMAL;
};
struct vtof{
float4 pos:SV_POSITION;
float3 color:COLOR;
};
vtof vert (app_data a){
vtof o;
o.pos = UnityObjectToWorldPos(a.vertex);
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 worldNormal = UnityObjectToWorldNormal(a.normal);
fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
float3 diffuse = _Color.rgb * _LightColor0.rgb * (dot(worldNormal,lightDir) * 0.5 + 0.5);
o.color = ambient + diffuse;
}
fixed4 frag(vtof i):SV_Target{
return fixed4(i.color,1.0);
}
ENDCG
}
FallBack"Diffuse"
}
//在片段中计算漫反射
Properties{
_Color("Color",Color) = (1,1,1,1)
}
SubShader{
Pass{
Tags{"LightMode" = "ForwardBase"}
CGPROGRAM
#include "Lighting.cginc"
#pargma vertex vert
#pargma fragment frag
fixed4 _Color;
struct app_data{
float4 vertex:POSITION;
fixed3 normal:NORMAL;
};
struct vtof{
float4 pos:SV_POSITION;
float3 worldNormal:COLOR;
};
vtof vert (app_data a){
vtof o;
o.pos = UnityObjectToWorldPos(a.vertex);
o.worldNormal = UnityObjectToWorldNormal(a.normal);
return o;
}
fixed4 frag(vtof i):SV_Target{
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
float3 diffuse = _Color.rgb * _LightColor0.rgb * (dot(i.worldNormal,lightDir) * 0.5 + 0.5);
return fixed4((ambient + diffuse),1.0);
}
ENDCG
}
FallBack"Diffuse"
}