Shader "Custom/testShader" {
properties
{
_Diffuse("my Diffuse",Color)=(1.0, 1.0, 0.0, 1.0)
}
subshader
{
Tags{"LightMode"="ForwardBase"}
pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 _Diffuse;
struct a2v
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f
{
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
};
v2f vert(a2v v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.worldNormal = mul(v.normal, (float3x3)_World2Object);
return o;
}
fixed4 frag(v2f i):SV_Target //计算漫反射光照模型
{
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz; //得到环境光
fixed3 worldNormal = normalize(i.worldNormal); //得到世界空间中的法线
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz); //得到世界空间中的光照
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb *saturate(dot(worldNormal, worldLightDir));
fixed3 color = ambient + diffuse;
return fixed4(color, 1.0);
}
ENDCG
}
}
Fallback "Diffuse"
properties
{
_Diffuse("my Diffuse",Color)=(1.0, 1.0, 0.0, 1.0)
}
subshader
{
Tags{"LightMode"="ForwardBase"}
pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 _Diffuse;
struct a2v
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f
{
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
};
v2f vert(a2v v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.worldNormal = mul(v.normal, (float3x3)_World2Object);
return o;
}
fixed4 frag(v2f i):SV_Target //计算漫反射光照模型
{
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz; //得到环境光
fixed3 worldNormal = normalize(i.worldNormal); //得到世界空间中的法线
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz); //得到世界空间中的光照
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb *saturate(dot(worldNormal, worldLightDir));
fixed3 color = ambient + diffuse;
return fixed4(color, 1.0);
}
ENDCG
}
}
Fallback "Diffuse"
}
【说明】
1. 顶点着色器不需要计算光照模型,只需要把世界空间下的法线传递给片元着色器即可。
2. 在光线无法达到的区域,模型的外观是黑色的,解决背光面明暗问题,提出了半兰伯特模型
在逐像素光照上只需改变如下:
fixed4 frag(v2f i) : SV_Target {
// Get ambient term
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
fixed halfLambert = dot(worldNormal, worldLightDir) * 0.5 + 0.5;
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * halfLambert;
fixed3 color = ambient + diffuse;
return fixed4(color, 1.0);
}
3. 半兰伯特模型原理:
Half Lambert技术实现的是原理是把漫反射光照值的范围分成两半,然后加上0.5。基本意思就是如果光照值是1,对半开后就是0.5,然后再加0.5回去,将会再得到1。如果你对0进行操作,那么你会得到0.5,因此我们将0~1之间的值重新映射到区间0.5~1。
下图展示了漫反射的值经过Half Lambert计算后的函数曲线图。