1. 程式人生 > >[unity+shader] 模擬一個三稜柱廣告牌

[unity+shader] 模擬一個三稜柱廣告牌

三面翻廣告牌(Trivision, Triangular Billboard)是由一組並排定位的三稜柱構成,通過旋轉三稜柱,利用其三個側面形成三幅畫面的廣告牌,在LED廣告牌大規模出現之前是個很常見的東西。

在這篇文章裡,我們就講一下如何製作一個稜柱翻轉切換圖片的效果。

https://en.wikipedia.org/wiki/Trivision

模擬稜柱翻轉的基本,就在於將同時顯示的兩張貼圖按一定比例縮放。這個比例由一個property  _Progress來控制。 

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
//AnimationEffects2D-->sakuraplus-->https://sakuraplus.github.io/make-terrain-with-google-elevation/index.html
Shader "TUT/TriangularBillboard01" {
	Properties {
		_MainTex ("Texture A", 2D) = "white" {}
		_MainTexB ("Texture B", 2D) = "black" {}
		[Space(10)]
		_Progress("Progress", Range(0,1))=0
	}

	SubShader {
		Tags {"Queue"="Transparent" }
		CGINCLUDE
		#include "UnityCG.cginc"
		sampler2D _MainTex;  
		sampler2D _MainTexB;  
		uniform half4 _MainTex_ST;
		uniform half4 _MainTexB_ST;
		fixed _Progress;

		struct v2f {
			float4 pos : SV_POSITION;
			half2 uvTA: TEXCOORD0;
			half2 uvTB: TEXCOORD1;
			half2 uvORI: TEXCOORD2;//original
		};
		  
		v2f vert(appdata_img v) {
			v2f o;
			o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
			o.uvTA=(v.texcoord-_MainTex_ST.zw)*_MainTex_ST.xy ;
			o.uvTB=(v.texcoord-_MainTexB_ST.zw)*_MainTexB_ST.xy ;
			o.uvORI=v.texcoord;
			o.uvORI=v.texcoord;

			return o;
		}

		fixed4 frag(v2f i) : SV_Target {
			fixed4 texA;
			fixed4 texB ;
			fixed4 color;
			float posmod;

			texA = tex2D(_MainTex, i.uvTA).rgba ;
			texB = tex2D(_MainTexB, i.uvTB).rgba ;

			if(i.uvORI.x>_Progress){
					color=texA;
			}else{
					color=texB;
			}
			return color;
		}
		    
		ENDCG
		Pass {
			//ZWrite Off
			Blend SrcAlpha OneMinusSrcAlpha
			CGPROGRAM
			#pragma vertex vert  
			#pragma fragment frag
			#pragma target 3.0
			ENDCG  
		}
	} 
	FallBack "Diffuse"
}

這樣我們得到了一個使用progress控制切換兩張貼圖的效果。

但是一個三稜柱廣告牌不應該只有一個稜柱,於是加上一個width的property,來設定每個稜柱的寬度。

                  _Width("Width",Float )=0.5

雖然可能用不到,但是這個寬度其實是可以超過uv的範圍的,所以不需要限定成Range(0,1)。

修改一下這個部分,計算當前uv與width屬性的餘數:

			float	posmod= fmod(i.uvORI.x,_Width);
			if(posmod/_Width>_Progress){
					color=texA;
			}else{
					color=texB;
			}

這樣,就實現了一個簡單的百葉窗效果,把這裡的uvORI.x換成y,百葉窗就可以變成橫向開啟的啦。

作為一個模擬稜柱,圖片旋轉造成的壓縮效果必不可少,接下來我們來計算壓縮部分。

兩張貼圖uv的y座標不變,x根據自身的位置和progress計算。

              fixed2       uvA=fixed2(i.uvTA.x+(posmod-_Width)* _Progress/(1-_Progress), i.uvTA.y);
              fixed2       uvB=fixed2(i.uvTB.x+(1-_Progress)*posmod /_Progress, i.uvTB.y);
              texA = tex2D(_MainTex, uvA).rgba ;
              texB = tex2D(_MainTexB, uvB).rgba ;             

這個公式實在不記得是怎麼匯出來的了,也懶得再想一遍,反正只是平面幾何,有興趣的自己算一下吧……

接下來給它新增一個假的陰影。先新增一個表示陰影基礎強度的property。

		_ShadowStrength("Shadow",  Range(0,2)) = 1.0

之後,讓稜柱的兩個面都有顯示的時候,加上一個從內側向外逐步減淡的陰影,即讓最終的顏色乘以一個小於1的數。在面所佔的比例變大時,這個數逐漸接近1,比例變小的時候,逐漸接近0。

			fixed shadowOn=1;		
			fixed strengtnWithProgress=_Progress/(1-_Progress);
			fixed ratioInOneSide=(_Width*_Progress-posmod)/_Width;
			if(posmod/_Width>_Progress){
				shadowOn=1+_ShadowStrength*ratioInOneSide*strengtnWithProgress;
			}else{				
				shadowOn=1-_ShadowStrength*ratioInOneSide/strengtnWithProgress;
			}			
			
			color.rgb*=shadowOn;

至此,一個所有三稜柱同時旋轉以切換圖片的模擬三稜柱廣告牌就完成了。

希望觀看更多效果,去

作為攝像機特效也可以使用