UnityShader开发之光照 - 简单光照模型 - 兰伯特(Lambert)漫反射模型参数分析

1.概念公式

漫反射 公式:C_{diffuse}=\left ( C_{light}\cdot M_{diffuse} \right )max\left ( 0,\overrightarrow{n}\cdot \overrightarrow{I} \right )

其中 C_{diffuse} 为漫反射模型计算最终的颜色值

M_{diffuse} 是材质的漫反射颜色

C_{light} 是光源颜色

C_{light}\cdot M_{diffuse} 是经验模型,需要两个变量能影响到最终值,用加、减法容易触发溢出,于是使用乘法(个人观点)

\overrightarrow{n} 是表面法线

\overrightarrow{I} 是指向光源的单位矢量

\overrightarrow{n}\cdot \overrightarrow{I} 表示将\overrightarrow{I}投影到\overrightarrow{n},获得\overrightarrow{I}\overrightarrow{n}方向上的分量的标量(大小),即能被摄像机看到的值。

从全局来看的话大致是这张图

黑到白为[0,1],乘于这个值相当于加了一层遮罩

2.实现


Shader "Custom/Light/PixelDiffuseLight"
{
	Properties
	{
		_Diffuse("Diffuse",Color)=(1,1,1,1)
	}
	SubShader
	{
		Tags { "RenderType"="Opaque" }
		LOD 100

		Pass
		{
			Tags { "LightMode" = "ForwardBase" }
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			
			#include "UnityCG.cginc"
			#include "Lighting.cginc"

			struct a2v
			{
				float4 vertex : POSITION;
				float2 normal : NORMAL;
			};

			struct v2f
			{
				float4 pos:SV_Position;
				fixed3 worldNormal:TEXCOORD0;
			};

			float4 _Diffuse;//模型自带漫反射颜色
			
			v2f vert (a2v 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 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;//环境光

				fixed3 worldNormal=i.worldNormal;
				
				fixed3 worldLightDir=_WorldSpaceLightPos0.xyz;

				fixed3 diffuse= _LightColor0.rgb * _Diffuse.rgb *dot(worldNormal,worldLightDir);

				fixed3 color=ambient+diffuse;

				return fixed4(color,1.0);
			}
			ENDCG
		}
	}
}

_LightColor0是平行光源的颜色值,_Diffuse是物体自带漫反射颜色值,worldNormal是法向量,worldLightDir是像素到光源的方向向量。

猜你喜欢

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