鏡面高光
上節學習了漫反射,這節我們來探索下鏡面反射(高光),鏡面反射可以讓物體看起來是有光澤的,比如金屬材質。
通過上圖我們可以清楚的看到,鏡面反射和入射光,法向量,反射光方向,視角方向這幾個因素有關,
很明顯我們可以通過反射光的方向和視角方向的夾角來計算鏡面反射強度,如果夾角越小,那麼鏡面反射光的強度就越大。
計算公式:
:光顏色
:材質顏色
:視角方向
:反射光方向
:光澤強度
在CG中,我們可以通過reflect(I,n)
函數來計算反射光方向,I
代表入射光方向,n
代表法向量。
更多常用函數可以參考這篇文章
shader代碼:
//高光反射(Specular)
Shader "lcl/005_Specular_fargment" {
Properties{
//主紋理
_MainTex("Texture", 2D) = "white" {}
//整體顏色
_Color("Diffuse Color",Color) = (1,1,1,1)
// 高光顏色
_Specular("_Specular Color",Color) = (1,1,1,1)
// 高光強度
_Gloss("Gloss",Range(8,200)) = 10
}
SubShader {
Pass{
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#include "Lighting.cginc"
#pragma vertex vert
#pragma fragment frag
// 變量定義
sampler2D _MainTex;
fixed4 _Color;
half _Gloss;
fixed4 _Specular;
//CPU傳輸到頂點着色器的數據
struct a2v {
// 頂點座標
float4 vertex : POSITION;
// 法向量
float3 normal: NORMAL;
// 紋理座標
float3 texcoord: TEXCOORD0;
};
//頂點傳輸到片元着色器的數據
struct v2f{
//頂點座標
float4 position:SV_POSITION;
// 世界空間下的法向量
float3 worldNormal: TEXCOORD0;
// 世界空間下座標
float3 worldVertex: TEXCOORD1;
// 紋理座標
float3 texcoord: TEXCOORD2;
};
//頂點着色
v2f vert(a2v v){
v2f f;
f.position = UnityObjectToClipPos(v.vertex);
f.worldNormal = mul(v.normal,(float3x3) unity_WorldToObject);
f.worldVertex = mul(v.vertex,unity_WorldToObject).xyz;
f.texcoord = v.texcoord;
return f;
};
// 片元着色器
fixed4 frag(v2f f):SV_TARGET{
//紋理顏色
float4 texColor = tex2D(_MainTex, f.texcoord);
// 環境光
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;
//法向量
fixed3 normalDir = normalize(f.worldNormal);
// 光源方向
fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
//漫反射
fixed3 diffuse = _LightColor0.rgb * max(dot(normalDir,lightDir),0) * _Color.rgb;
//反射光計算
fixed3 reflectDir = reflect(-lightDir,normalDir);
//計算視角方向
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - f.worldVertex );
//計算高光反射
fixed3 specular = _LightColor0.rgb * pow(max(0,dot(viewDir,reflectDir)),_Gloss) *_Specular;
//合併漫反射,環境光,高光反射
fixed3 tempColor = diffuse+ambient+specular;
//融合紋理顏色
return fixed4(tempColor*texColor.rgb,1);
};
ENDCG
}
}
FallBack "VertexLit"
}
效果顏色;