談一下unity3d的光照

其實學習shader的話,搞unity開發,就是《unity 3d shaderLab開發實戰詳解》。unity在opengl的基礎上又封裝了了一個表面着色器,本id其實並不怎麼喜歡寫表面着色器,因爲以前學習opengl的時候都沒有聽說過這個東西,其實表面着色器最終是要編譯成頂點和片元着色器的。

今天本id突然想說起這個,是因爲昨天下午被自己坑了一把,就導致了在unity編輯器上運行正常,手機上卻看不到效果。就是對於點光源的光照計算,當然如果是平行光就不會出現這種情況,unity對於點光源的計算在《unity 3d shaderLab開發實戰詳解》這本書上也是有介紹的,這是原文:

VcHexL⒒渲染模式下,FomardBasc和
FowardAdd的 ughtM。 de都 不被支持。 另外,FwdAddX.shadcr在 3個 渲染路徑下都沒有輸出,這
說明 FoⅢ ardAdd這個 Pass需 要和 FomardBasc— 起使用,否 則會被Unity所忽視掉。 在 Fomard
Dcfcrred渲 染路徑下,Fomard的 Pass均 能被正常渲染。


下面是關於光照的shader:

Shader "Custom/LightAndOutline" {
	Properties {
		_Color ("Main Color", Color) = (1,1,1,1)
		_OutlineColor ("Outline Color", Color) = (1,1,1,1)
		_Outline ("Outline width", Range (0.0, 0.03)) = .005
		_MainTex ("Base (RGB)", 2D) = "white" { }
		_BumpMap ("Bumpmap", 2D) = "bump" {}
	}
 
	
 
	SubShader {
		//Tags { "Queue" = "Transparent" }
 
		// 描邊通道
		/*Pass {
			CGINCLUDE
			#include "UnityCG.cginc"
			 
			struct appdata {
				float4 vertex : POSITION;
				float3 normal : NORMAL;
			};
			struct v2f {
				float4 pos : POSITION;
				float4 color : COLOR;
			};
			 
			uniform float _Outline;
			uniform float4 _OutlineColor;
			ENDCG
			Name "OUTLINE"
			Tags { "LightMode" = "Always" }
			Cull Back
			ZWrite Off
			ZTest Less
			//Blend Off
			// you can choose what kind of blending mode you want for the outline
			Blend SrcAlpha OneMinusSrcAlpha // Normal
			//Blend One One // Additive
			//Blend One OneMinusDstColor // Soft Additive
			//Blend DstColor Zero // Multiplicative
			//Blend DstColor SrcColor // 2x Multiplicative

			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			 v2f vert(appdata v) {
				// just make a copy of incoming vertex data but scaled according to normal direction
				v2f o;
				o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
			 
				float3 norm   = mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal);
				float2 offset = TransformViewToProjection(norm.xy);
			 
				o.pos.xy += offset * o.pos.z * _Outline;
				o.color = _OutlineColor;
				return o;
			}
			half4 frag(v2f i) : COLOR {
				return i.color;
			}
			ENDCG
		}*/
		
		Pass {  
			Tags{ "LightMode"="ForwardBase"}
			Cull Off
			Blend SrcAlpha OneMinusSrcAlpha 
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#include "UnityCG.cginc"
			#include "Lighting.cginc"
			struct appdata_t {
				float4 vertex : POSITION;
				float2 texcoord : TEXCOORD0;
			};
			struct v2f_t {
				float4 vertex : SV_POSITION;
				half2 texcoord : TEXCOORD0;
			};
			sampler2D _MainTex;
			float4 _MainTex_ST;
			v2f_t vert (appdata_t v)
			{
				v2f_t o;
				o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
				o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
				return o;
			}
			fixed4 frag (v2f_t i) : SV_Target
			{
				fixed4 col = tex2D(_MainTex, i.texcoord);
				return col;
			}
			ENDCG
		}
		
		
		//光亮通道
	Pass {  
			Tags{ "LightMode"="ForwardAdd"}
			Cull Off
			Blend One Zero
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#include "UnityCG.cginc"
			#include "Lighting.cginc"
			struct appdata_t {
				float4 vertex : POSITION;
				float2 texcoord : TEXCOORD0;
				float3 normal : NORMAL;
			};
			struct v2f_t {
				float4 vertex : SV_POSITION;
				half2 texcoord : TEXCOORD0;
				float3 lightDir:TEXCOORD1;
				float color : COLOR;
			};
			sampler2D _MainTex;
			float4 _MainTex_ST;
			v2f_t vert (appdata_t v)
			{
				v2f_t o;
				o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
				o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
				
				
				
				float3 lightColor = _LightColor0.xyz;
				o.lightDir = ObjSpaceLightDir(v.vertex);
				float cos_a = saturate(dot(o.lightDir, v.normal));
				cos_a = pow(lightColor*cos_a, 5);
				o.color = cos_a + 0.9;
				
				
				return o;
			}
			fixed4 frag (v2f_t i) : SV_Target
			{
				fixed4 col = tex2D(_MainTex, i.texcoord);
				col.r = col.r*i.color;
				col.g = col.g*i.color;
				col.b = col.b*i.color;
				return col;
			}
			ENDCG
		}
 
	}
 Fallback "Diffuse"
}

注意,這裏的光照部分使用了兩個通道,我們的光照計算主要在Tags{ "LightMode"="ForwardAdd"}這個通道中,書上說,要使得這個通道有效,必須有一個Tags{ "LightMode"="ForwardBase"}通道,所以在Add通道中需要使用Blend One Zero,把前一個通道隱藏起來。

這裏只是簡單光照模型,見笑了

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