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

猜你喜欢

转载自blog.csdn.net/qq_28474981/article/details/84338161