记录:Shader 光照模型公式及实现

以下内容来自<UnityShader 入门精要> 第六章 Unity中的基础光照

1.漫反射公式
兰伯特定律:反射光线的强度与表面法线和光源方向之间夹角的余弦值成正比
Cdiffuse = (Clight * Mdiffuse) * saturate(dot(n,i))
Clight:入射光线的颜色和强度
Mdiffuse:材质的漫反射系数
saturate(x):将x截取在[0,1]范围内
dot(x,y):对x和y 点乘
n:表面法线
i:光源方向
实现:

Shader "Custom/Diffuse" {
Properties{
	_Diffuse("Color", Color) = (1,1,1,1)

}
SubShader{
	Pass
	{
		Tags{ "RenderType" = "Opaque" }
		CGPROGRAM
		#pragma vertex vert
		#pragma fragment frag
		#include "Lighting.cginc"


		fixed4 _Diffuse;
		struct Input {
			float4 vertex:POSITION;
			float3 normal:Normal;
		};
		struct v2f {
			float4 pos:SV_POSITION;
			fixed3 color : COLOR;
		};
		
		v2f vert(Input i)
		{
			v2f o;
			//转换顶点坐标
			o.pos = mul(UNITY_MATRIX_MVP, i.vertex);
			//环境色
			fixed3 ambine = UNITY_LIGHTMODEL_AMBIENT.xyz;
			//法线
			fixed3 worldNormal = normalize(mul(i.normal, (float3x3)unity_WorldToObject));
			//入射光线
			fixed3 worldLight = normalize(-_WorldSpaceLightPos0.xyz);
			//漫反射公式
			fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLight));
			//最终颜色
			o.color = ambine + diffuse;
			return o;
		}

		fixed4 frag(v2f i):SV_Target
		{
			return fixed4(i.color,1.0);
		}
		ENDCG
	}
}
FallBack "Diffuse"
}

2.半兰伯特公式:
Cdiffuse = (Clight * Mdiffuse)(S * dot(n,i) + O)
Clight:入射光线的颜色和强度
Mdiffuse:材质的漫反射系数
dot(x,y):对x和y 点乘
n:表面法线
i:光源方向
S:缩放系数,一般为0.5
O:偏移系数,一般为0.5
实现:

	//在漫反射公式 实现代码中替换漫反射公式
	fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLight)*0.5+0.5);

3.高光反射公式
Cspecular=(Clight * Mspecular) * saturate(dot(v,reflect(i,n)))gloss
Clight:入射光线的颜色和强度
Mspecular:材质的高光反射系数
saturate(x):将x截取在[0,1]范围内
dot(x,y):对x和y 点乘
v:视角方向
i:光照方向
n:法线方向
reflect(i,n):根据i(入射方向)和n(法线方向)返回反射方向
gloss:光泽度,越大,亮点越小。

Shader "Custom/Specular" {
	Properties{
		_Diffuse("Color", Color) = (1,1,1,1)
		_Specular("Specular",Color) = (1,1,1,1)
		_Gloss("Gloss",Range(1,10)) = 1
	}
	SubShader{
		Pass
		{
			Tags{ "RenderType" = "Opaque" }
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#include "Lighting.cginc"


			fixed4 _Diffuse;
			float _Gloss;
			fixed4 _Specular;
			struct Input {
				float4 vertex:POSITION;
				float3 normal:Normal;
			};
			struct v2f {
				float4 pos:SV_POSITION;
				fixed3 color : COLOR;
			};
			
			v2f vert(Input i)
			{
			v2f o;
				//转换顶点坐标
				o.pos = mul(UNITY_MATRIX_MVP, i.vertex);
				//环境色
				fixed3 ambine = UNITY_LIGHTMODEL_AMBIENT.xyz;
				//法线
				fixed3 worldNormal = normalize(mul(i.normal, (float3x3)unity_WorldToObject));
				//入射光线
				fixed3 worldLight = normalize(-_WorldSpaceLightPos0.xyz);
				//漫反射公式
				fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(0.5f * dot(worldNormal, worldLight)+0.5f);

				//反射方向 reflect(入射方向,法线)
				fixed3 reflectDir = normalize(reflect(worldLight, worldNormal));
				//视觉方向
				fixed3 viewDir = normalize(-_WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, i.vertex).xyz);
				//高光公式
				fixed3 specular = _LightColor0.rgb*_Specular.rgb*pow(saturate(dot(reflectDir, viewDir)), _Gloss);

				//最终颜色
				o.color = ambine + diffuse + specular;
				return o;
			}
			fixed4 frag(v2f i):SV_Target
			{
				return fixed4(i.color,1.0);
			}
			ENDCG
		}
	}
	FallBack "Diffuse"
}

4.Blinn-Phong公式
Cspecular = (Clight * Mspecular) saturate(dot(n, normalize(v+i)))gloss
Clight:入射光线的颜色和强度
Mspecular:材质的高光反射系数
saturate(x):将x截取在[0,1]范围内
dot(x,y):对x和y 点乘
v:视角方向
i:光照方向
normalize:归一化矢量
gloss:光泽度,越大,亮点越小。
实现:

//在高光反射公式中做如下修改
//反射方向 reflect(入射方向,法线)
//fixed3 reflectDir = normalize(reflect(worldLight, worldNormal));
//视觉方向
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, i.vertex).xyz);
//高光公式
fixed3 specular = _LightColor0.rgb*_Specular.rgb*pow(saturate(dot(worldNormal, normalize(viewDir+worldLight))), _Gloss);

5.自发光
Cemissive = Memissive
Memissive:自发光颜色
实现:

//高光反射中,定义自发光颜色,在着色器输出最后颜色之前,把自发光颜色添加到输出颜色上即可
o.color = ambine + diffuse + specular+ _Emissive;
发布了28 篇原创文章 · 获赞 18 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_18192161/article/details/103002112