1. 程式人生 > >Unity Shaders and Effects Cookbook (3-5) 金屬軟高光

Unity Shaders and Effects Cookbook (3-5) 金屬軟高光

書上這一節看得我頭昏腦脹,數學渣表示自理不能…… 而且也不瞭解這個效果的實際意義。

先記錄下來,後面真正看懂了再來補充詳細理論。


通過一張紋理貼圖,定義高光的形狀,利用到的紋理貼圖有三種

這裡並不是把紋理 UV對映。而是讀取了 R通道值。

這幾張圖都是黑白的,也就是說,畫素的一個點的 RGB 是相同值,所以 讀取 R 或者 讀取 G、B都是同等的。

著色器程式碼為高光生成了一些粗糙度值。

然後這節利用菲涅爾法則,當我們的視線剛好正對著物體表面的時候,會幫我們遮蔽高光。

轉自 http://blog.csdn.net/huutu http://www.thisisgame.com.cn

這一節的完整Shader程式碼:

Shader "CookBookShaders/Metallicsoft" 
{
	Properties 
	{
		_MainTex ("Base (RGB)", 2D) = "white" {}
		_MainTint ("Diffuse Tint",Color)=(1,1,1,1)
		_RoughnessTex("Roughness Texture",2D)="white"{}
		_Roughness("Roughness",Range(0,1))=0.5
		_SpecularColor("Specular Color",Color)=(1,1,1,1)
		_SpecularPower("Specular Power",Range(0,30))=2
		_Fresnel("Fresnel",Range(0,1.0))=0.05
	}
	SubShader {
		Tags { "RenderType"="Opaque" }
		LOD 200
		
		CGPROGRAM
		#pragma surface surf Metallicsoft

		sampler2D _MainTex;
		float4  _MainTint;
		sampler2D _RoughnessTex;
		float _Roughness;
		float4 _SpecularColor;
		float _SpecularPower;
		float _Fresnel;


		struct Input {
			float2 uv_MainTex;
		};

		void surf (Input IN, inout SurfaceOutput o) 
		{
			half4 c = tex2D (_MainTex, IN.uv_MainTex) * _MainTint;
			o.Albedo = c.rgb;
			o.Alpha = c.a;
		}


		inline fixed4 LightingMetallicsoft(SurfaceOutput s,fixed3 lightDir,half3 viewDir,fixed atten)
		{
			//先計算出來所有的漫反射以及視點相關的向量;
			float3 halfVector=normalize(lightDir + viewDir);
			float NdotL=saturate(dot(s.Normal,normalize(lightDir)));
			float NdotH_raw=dot(s.Normal,halfVector);
			float NdotH = saturate(dot(s.Normal,halfVector));
			float NdotV=saturate(dot(s.Normal,normalize(viewDir)));
			float VdotH=saturate(dot(halfVector,normalize(viewDir)));

			//生成一些粗糙度值,然後從紋理中讀取高光形狀
			float geoEnum=2.0*NdotH;
			float3 G1=(geoEnum * NdotV)/NdotH;
			float3 G2=(geoEnum * NdotL)/NdotH;
			float3 G= min(1.0f,min(G1,G2));

			float roughness=tex2D(_RoughnessTex,float2(NdotH_raw * 0.5 +0.5,_Roughness)).r;

			//菲涅爾準則;當我們視線正好對著物體表面時,會幫我們遮蔽高光;
			float fresnel=pow(1.0-VdotH,5.0);
			fresnel*=(1.0-_Fresnel);
			fresnel+=_Fresnel;

			//組合計算高光值;
			float3 specular=float3(fresnel * G * roughness * roughness) * _SpecularPower;

			//漫反射 加上 高光 
			float4 c;
			c.rgb=(s.Albedo * _LightColor0.rgb * NdotL)+(specular * _SpecularColor.rgb)*(atten * 2.0f);
			c.a=s.Alpha;
			return c;
		}

		ENDCG
	} 
	FallBack "Diffuse"
}

測試效果

示例工程下載:

http://pan.baidu.com/s/1bpDfEpT