以下內容來自<UnityShader 入門精要> 第六章 Unity中的基礎光照
1.漫反射公式
蘭伯特定律:反射光線的強度與表面法線和光源方向之間夾角的餘弦值成正比
Cdiffuse = (Clight * Mdiffuse) * saturate(dot(n,i))
Clight:入射光線的顏色和強度
Mdiffuse:材質的漫反射係數
saturate(x):將x截取在[0,1]範圍內
dot(x,y):對x和y 點乘
n:表面法線
i:光源方向
實現:
Shader "Custom/Diffuse" {
Properties{
_Diffuse("Color", Color) = (1,1,1,1)
}
SubShader{
Pass
{
Tags{ "RenderType" = "Opaque" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 _Diffuse;
struct Input {
float4 vertex:POSITION;
float3 normal:Normal;
};
struct v2f {
float4 pos:SV_POSITION;
fixed3 color : COLOR;
};
v2f vert(Input i)
{
v2f o;
//轉換頂點座標
o.pos = mul(UNITY_MATRIX_MVP, i.vertex);
//環境色
fixed3 ambine = UNITY_LIGHTMODEL_AMBIENT.xyz;
//法線
fixed3 worldNormal = normalize(mul(i.normal, (float3x3)unity_WorldToObject));
//入射光線
fixed3 worldLight = normalize(-_WorldSpaceLightPos0.xyz);
//漫反射公式
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLight));
//最終顏色
o.color = ambine + diffuse;
return o;
}
fixed4 frag(v2f i):SV_Target
{
return fixed4(i.color,1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}
2.半蘭伯特公式:
Cdiffuse = (Clight * Mdiffuse)(S * dot(n,i) + O)
Clight:入射光線的顏色和強度
Mdiffuse:材質的漫反射係數
dot(x,y):對x和y 點乘
n:表面法線
i:光源方向
S:縮放係數,一般爲0.5
O:偏移係數,一般爲0.5
實現:
//在漫反射公式 實現代碼中替換漫反射公式
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLight)*0.5+0.5);
3.高光反射公式
Cspecular=(Clight * Mspecular) * saturate(dot(v,reflect(i,n)))gloss
Clight:入射光線的顏色和強度
Mspecular:材質的高光反射係數
saturate(x):將x截取在[0,1]範圍內
dot(x,y):對x和y 點乘
v:視角方向
i:光照方向
n:法線方向
reflect(i,n):根據i(入射方向)和n(法線方向)返回反射方向
gloss:光澤度,越大,亮點越小。
Shader "Custom/Specular" {
Properties{
_Diffuse("Color", Color) = (1,1,1,1)
_Specular("Specular",Color) = (1,1,1,1)
_Gloss("Gloss",Range(1,10)) = 1
}
SubShader{
Pass
{
Tags{ "RenderType" = "Opaque" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 _Diffuse;
float _Gloss;
fixed4 _Specular;
struct Input {
float4 vertex:POSITION;
float3 normal:Normal;
};
struct v2f {
float4 pos:SV_POSITION;
fixed3 color : COLOR;
};
v2f vert(Input i)
{
v2f o;
//轉換頂點座標
o.pos = mul(UNITY_MATRIX_MVP, i.vertex);
//環境色
fixed3 ambine = UNITY_LIGHTMODEL_AMBIENT.xyz;
//法線
fixed3 worldNormal = normalize(mul(i.normal, (float3x3)unity_WorldToObject));
//入射光線
fixed3 worldLight = normalize(-_WorldSpaceLightPos0.xyz);
//漫反射公式
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(0.5f * dot(worldNormal, worldLight)+0.5f);
//反射方向 reflect(入射方向,法線)
fixed3 reflectDir = normalize(reflect(worldLight, worldNormal));
//視覺方向
fixed3 viewDir = normalize(-_WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, i.vertex).xyz);
//高光公式
fixed3 specular = _LightColor0.rgb*_Specular.rgb*pow(saturate(dot(reflectDir, viewDir)), _Gloss);
//最終顏色
o.color = ambine + diffuse + specular;
return o;
}
fixed4 frag(v2f i):SV_Target
{
return fixed4(i.color,1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}
4.Blinn-Phong公式
Cspecular = (Clight * Mspecular) saturate(dot(n, normalize(v+i)))gloss
Clight:入射光線的顏色和強度
Mspecular:材質的高光反射係數
saturate(x):將x截取在[0,1]範圍內
dot(x,y):對x和y 點乘
v:視角方向
i:光照方向
normalize:歸一化矢量
gloss:光澤度,越大,亮點越小。
實現:
//在高光反射公式中做如下修改
//反射方向 reflect(入射方向,法線)
//fixed3 reflectDir = normalize(reflect(worldLight, worldNormal));
//視覺方向
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, i.vertex).xyz);
//高光公式
fixed3 specular = _LightColor0.rgb*_Specular.rgb*pow(saturate(dot(worldNormal, normalize(viewDir+worldLight))), _Gloss);
5.自發光
Cemissive = Memissive
Memissive:自發光顏色
實現:
//高光反射中,定義自發光顏色,在着色器輸出最後顏色之前,把自發光顏色添加到輸出顏色上即可
o.color = ambine + diffuse + specular+ _Emissive;