UnityShader開發之光照 - 簡單光照模型 - Phong反射光模型參數分析

1.概念

light color = emissive + ambient + diffuse + specluar

emissive:自發光

ambient:環境光

diffuse :漫反射光

specluar:鏡面光

 

Phong模型 鏡面光公式爲  C_{specular}= C_{light} \cdot M_{specular}\cdot max\left ( 0,\overrightarrow{v}\cdot \overrightarrow{r} \right )^{M_{gloss}}

C_{specular} 爲求得的高光顏色值

C_{light}爲燈光顏色

M_{specular}爲材質的高光反射顏色

C_{light}\cdot M_{specular} 是經驗模型,需要兩個變量能影響到最終值,用加、減法容易觸發溢出,於是使用乘法(個人觀點)

\overrightarrow{v}爲指向視覺的方向向量

\overrightarrow{r}爲光的反射方向與強度向量

\overrightarrow{v}\cdot \overrightarrow{r}表示將\overrightarrow{r}投影到\overrightarrow{v},獲得\overrightarrow{r}\overrightarrow{v}方向上的分量的標量(大小),即能被攝像機看到的值。

max主要是將反面的光照剔除掉

M_{gloss}是材質的光澤度

\left (\overrightarrow{v}\cdot \overrightarrow{r} \right )^{M_{gloss}}作爲一個指數函數,由於兩個向量的分量xyz\in[0,1],並且夾角大於0,所以得出來的數小於1,當M_{gloss}增大時,所得的值變小,即光澤越大,高光範圍越小。

2.Phong中的向量計算

        圖中r爲反射向量,v爲指向視覺的向量,n爲法向量,I爲指向光源的向量。一般v,n,I已知,通過已知參數可以求得r。

        從單純的向量計算的角度來說

\overrightarrow{AO}爲入射光方向,\overrightarrow{OB}爲反射光方向向量,\overrightarrow{OP}爲 \overrightarrow{OB} 或 -\overrightarrow{AO} 在法向量\overrightarrow{ON}上的分量

(1)\overrightarrow{AB}=\overrightarrow{OB}-\overrightarrow{OA}

(2)\overrightarrow{AB}=2\overrightarrow{AP}=2(\overrightarrow{OP}-\overrightarrow{OA}

(3)\overrightarrow{OP}=|\overrightarrow{OA}|·cosθ·\overrightarrow{ON}=\left |\overrightarrow{OA} \right |\cdot \frac{\overrightarrow{OA}\cdot \overrightarrow{OP}}{\left |\overrightarrow{OA} \right |\cdot \left |\overrightarrow{OP} \right |}\cdot\overrightarrow{ON} = \frac{\overrightarrow{OA}\cdot \overrightarrow{OP}}{\left |\overrightarrow{OP} \right |}\cdot\overrightarrow{ON}

如果\overrightarrow{ON}爲方向向量則       \overrightarrow{OP}=\overrightarrow{OA}\cdot\overrightarrow{ON}\cdot\overrightarrow{ON}

\overrightarrow{OB}=\overrightarrow{AB}+\overrightarrow{OA}

           =2\overrightarrow{AP}+\overrightarrow{AO}

           =2(\overrightarrow{OP}-\overrightarrow{OA})+\overrightarrow{OA}

           =2(\overrightarrow{OA}\cdot\overrightarrow{ON}\cdot\overrightarrow{ON}-\overrightarrow{OA})+\overrightarrow{OA}

           =2(\overrightarrow{OA}\cdot\overrightarrow{ON}\cdot\overrightarrow{ON}-\overrightarrow{OA}

 

即反射光\overrightarrow{r}=2\left (\overrightarrow{I} \cdot \overrightarrow{n}\right )\cdot \overrightarrow{n}-\overrightarrow{I}

 

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
		}
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章