正常的漫反射公式(Lambert)是这样的:
C(diffuse) = C(light) * M(diffuse)max(0,n*I)
C(light):入射光的颜色和强度
M(diffuse):材质的漫反射系数
n:世界坐标系下的表面法线
I:世界坐标系下的光源方向(反射点指向光源的矢量)
max函数:,将结果截取到0,防止法线与光源方向的点乘为负值,被背后的光源照亮的错误效果
然后是毫无依据的半兰伯特公式:C(diffuse) = (C(light) * M(diffuse))(0.5(n*l)+0.5)
最后是代码(unity5.5.4):
Shader "Custom/DiffuseVertexLevel3" {
Properties {
_Color("color",Color)=(1,1,1,1)
}
SubShader {
Pass{
//定义光照模式
Tags{"LightMode"="ForwardBase"}
CGPROGRAM
//顶点着色器
#pragma vertex vert
//片元着色器
#pragma fragment frag
//引入unity的Lighting库
#include "Lighting.cginc"
//衔接Properties的_Color属性
fixed4 _Color;
//定义顶点着色器的输入和输出结构体
struct a2v{
float4 vertex:POSITION;
float3 normal:NORMAL;
};
//顶点着色器的输出结构体也是片元着色器的输入结构体
struct v2f{
float4 pos:SV_POSITION;
float3 worldNoraml:TEXCOORD0;
};
v2f vert(a2v v){
//顶点着色器不需要计算光照模型,只需要把世界空间下的法线传递给片元着色器即可
v2f o;
o.pos=UnityObjectToClipPos(v.vertex);
o.worldNoraml=mul(v.normal,(float3x3)unity_WorldToObject);
return o;
}
fixed4 frag(v2f f):SV_Target{
//在片元着色器中计算漫反射光照模型
fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 worldNoraml=normalize(f.worldNoraml);
fixed3 worldLightDir=normalize(_WorldSpaceLightPos0.xyz);
//使用半兰伯特公式
fixed halfLambert=dot(worldNoraml,worldLightDir)*0.5+0.5;
fixed3 diffuse=_LightColor0.rgb*_Color.rgb*halfLambert;
float3 color=ambient+diffuse;
return fixed4(color,1.0);
}
ENDCG
}
}
//设置回调shader
FallBack "Diffuse"
}
另外还有一个据说是加强版,原谅我眼拙没有看出太大区别....也放在这里记录一下吧
Shader "Custom/DiffuseVertexLevel4" {
Properties
{
_MainTex("Main Tex",2D) = "white"{}
_DiffuseColor("Diffuse Color",Color) = (1,1,1,1)
}
SubShader
{
Tags{"Queque" = "Opaque"}
Pass
{
Tags{"LightMode" = "ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
float4 _DiffuseColor;
struct a2v
{
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
float3 normal :NORMAL;
};
struct v2f
{
float4 pos : SV_POSITION;
//float3 color : COLOR;
float halfLambert : TEXCOORD0;
float2 uv : TEXCOORD1;
};
v2f vert(a2v v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
float3 worldNormal = normalize(UnityObjectToWorldNormal(v.normal));
float3 worldPos = mul(unity_ObjectToWorld, o.pos);
float3 worldLightDir = normalize(UnityWorldSpaceLightDir(worldPos));
o.halfLambert = dot(worldNormal, worldLightDir)*0.5 + 0.5;
return o;
}
float4 frag(v2f f) : SV_Target
{
float3 col = tex2D(_MainTex, f.uv).rgb;
float3 diffuse = col * _DiffuseColor.rgb;
float3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb * col;
float3 color = ambient + _LightColor0.rgb * diffuse * f.halfLambert;
return float4(color,1);
}
ENDCG
}
}
}