Lambert光照模型,根据光照向量与顶点发现的夹角来确定光照强度:
Shader "James/VP Shader/LightModel-Lambert"
{
Properties
{
_MainTex ("MainTex", 2D) = "white" {}
}
SubShader
{
Pass
{
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
float _LightColor0;
sampler2D _MainTex;
float4 _MainTex_ST;
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float3 lightDir : TEXCOORD1;
float3 normal : TEXCOORD2;
};
v2f vert(appdata_full v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
// 从顶点位置到Light的局部向量
o.lightDir = ObjSpaceLightDir(v.vertex);
o.normal = v.normal;
return o;
}
float4 frag(v2f i) : COLOR
{
i.lightDir = normalize(i.lightDir);
i.normal = normalize(i.normal);
// 纹理采样
float4 c = tex2D(_MainTex, i.uv);
// 光强度,法向和光照方向的cos值
float diffuse = max(0, dot(i.normal, i.lightDir));
// 纹理色 * 光源色 * 强度参数
c = c * _LightColor0 * diffuse;
return c * 2;
}
ENDCG
}
}
FallBack "Diffuse"
}
Phong光照模型,根据光照向量的反射向量与视线的夹角来计算镜面高光的强度,另外再加上漫射光的成分:
Shader "James/VP Shader/LightModel-Phong"
{
Properties
{
_MainTex ("MainTex", 2D) = "white" {}
_gloss ("Gloss", Float) = 1
}
SubShader
{
Pass
{
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
float _LightColor0;
sampler2D _MainTex;
float4 _MainTex_ST;
float _gloss;
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float3 normal : TEXCOORD1;
float3 lightDir : TEXCOORD2; // 光照方向
float3 reflectLightDir : TEXCOORD3; // 光照反射方向
float3 viewDir : TEXCOORD4; // 视线方向
};
v2f vert(appdata_full v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
o.normal = v.normal;
// 从顶点位置到light的局部向量
o.lightDir = ObjSpaceLightDir(v.vertex);
// 反射向量,注意需要使用-o.lightDir
o.reflectLightDir = reflect(-o.lightDir, v.normal);
// 视线,顶点到camera的局部变量
o.viewDir = ObjSpaceViewDir(v.vertex);
return o;
}
float4 frag(v2f i) : COLOR
{
i.normal = normalize(i.normal);
i.reflectLightDir = normalize(i.reflectLightDir);
i.viewDir = normalize(i.viewDir);
// 纹理采样
float4 c = tex2D(_MainTex, i.uv);
// 漫射光强度
float diffuse = max(0, dot(i.normal, i.lightDir));
// 镜面光强度
float specular = max(0, dot(i.reflectLightDir, i.viewDir));
specular = pow(specular, 32) * _gloss;
// 纹理色 * 光源色 * 强度参数
c = c * _LightColor0 * (diffuse + specular);
return c * 2;
}
ENDCG
}
}
FallBack "Diffuse"
}
BinnPhong光照模型,根据光照向量和视线的半角向量,与顶点法线的夹角来计算镜面高光的强度,另外再加上漫射光的成分:
Shader "James/VP Shader/LightModel-BinnPhong"
{
Properties
{
_MainTex ("MainTex", 2D) = "white" {}
_gloss ("Gloss", Float) = 5
}
SubShader
{
Pass
{
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
float _LightColor0;
sampler2D _MainTex;
float4 _MainTex_ST;
float _gloss;
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float3 normal : TEXCOORD1;
float3 lightDir : TEXCOORD2; // 光照方向
};
v2f vert(appdata_full v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
o.normal = v.normal;
// 顶点->light的局部向量
o.lightDir = ObjSpaceLightDir(v.vertex);
// 顶点->camera的局部向量
float3 viewDir = ObjSpaceViewDir(v.vertex);
return o;
}
float4 frag(v2f i) : COLOR
{
i.lightDir = normalize(i.lightDir);
i.normal = normalize(i.normal);
// 半角向量,光照方向和视线的中间值
float3 halfDir = (i.lightDir + i.normal) * 0.5;
// 纹理采样
float4 c = tex2D(_MainTex, i.uv);
// 漫射光强度
float diffuse = max(0, dot(i.normal, i.lightDir));
// 镜面光强度
float specular = max(0, dot(i.normal, halfDir));
specular = pow(specular, 32) * _gloss;
// 纹理色 * 光源色 * 强度参数
c = c * _LightColor0 * (diffuse + specular);
return c * 2;
}
ENDCG
}
}
FallBack "Diffuse"
}
BinnPhong比Phong少计算一次反射向量,会更简洁和高效。