1.概念
light color = emissive + ambient + diffuse + specluar
emissive:自發光
ambient:環境光
diffuse :漫反射光
specluar:鏡面光
Phong模型 鏡面光公式爲
爲求得的高光顏色值
爲燈光顏色
爲材質的高光反射顏色
是經驗模型,需要兩個變量能影響到最終值,用加、減法容易觸發溢出,於是使用乘法(個人觀點)
爲指向視覺的方向向量
爲光的反射方向與強度向量
表示將投影到,獲得在方向上的分量的標量(大小),即能被攝像機看到的值。
max主要是將反面的光照剔除掉
是材質的光澤度
作爲一個指數函數,由於兩個向量的分量xyz[0,1],並且夾角大於0,所以得出來的數小於1,當增大時,所得的值變小,即光澤越大,高光範圍越小。
2.Phong中的向量計算
圖中r爲反射向量,v爲指向視覺的向量,n爲法向量,I爲指向光源的向量。一般v,n,I已知,通過已知參數可以求得r。
從單純的向量計算的角度來說
設爲入射光方向,爲反射光方向向量,爲 或 - 在法向量上的分量
(1)=-
(2)=2=2()
(3)=||·cosθ·= =
如果爲方向向量則 =
則=+
=2+
=2()+
=2()+
=2()
即反射光
2.實現
效果:
Shader "Custom/Light/PhongSpecularLight"
{
Properties
{
_Specular ("Specular", Color)=(1,1,1,1)
_Gloss ("Gloss", Range(8.0,256))=20
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
Tags{ "LightMode" = "ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f
{
float4 pos:SV_Position;
float3 worldNormal:TEXCOORD0;
float3 worldPos:TEXCOORD1;
};
fixed4 _Specular;
float _Gloss;
v2f vert (appdata v)
{
v2f o;
o.pos=UnityObjectToClipPos(v.vertex);
o.worldNormal =mul(v.normal,(float3x3)unity_WorldToObject);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed3 worldLightDir=_WorldSpaceLightPos0.xyz;
fixed3 reflectDir=normalize(reflect(-worldLightDir,i.worldNormal));
fixed3 viewDir=normalize(_WorldSpaceCameraPos.xyz-i.worldPos.xyz);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(dot(reflectDir,viewDir),_Gloss);
return fixed4(specular,1.0);
}
ENDCG
}
}
}