1. 程式人生 > 其它 >小地圖毒圈遮罩挖洞的實現

小地圖毒圈遮罩挖洞的實現

技術標籤:unity3dnguishader

										NGUI在圖片上挖洞

小地圖毒圈遮罩挖洞的實現

要實現的效果就是在一張圖片上以任意圓心和半徑為圓,挖一個圓形的洞


最開始想到的方法是傳入shader一個圓心的世界座標和半徑,然後判斷和圓心距離小於半徑的點就捨棄。實現後發現,NGUI中在傳入半徑相同的情況下,在不同解析度下挖洞的大小會不一樣,這是不行的,在嘗試了一些適配方法後,沒能解決,由於時間原因,沒能繼續深入研究不同解析度和傳入shader的半徑的對應比例關係。在這裡如果有知道的,或有解決方法的希望不吝賜教。

值得一提的是,在UGUI下測試,沒有這個問題,不同的螢幕解析度對應的挖空的大小是不變的。最終NGUI下我採用了另外一種思路,傳入shader一個圓心的世界座標和圓上任意一點的世界座標,根據這兩個點計算出半徑,在進行裁剪,這樣在不同解析度下被挖空的圓的大小就不會變了。


第一種方法的關鍵程式碼:

v2f vert (appdata v)

{
   v2f o;
   o.vertex = UnityObjectToClipPos(v.vertex);
   o.worldPos = mul(unity_ObjectToWorld, v.vertex);
   o.uv = TRANSFORM_TEX(v.uv, _MainTex);
   o.color = v.color;
   return o;
}

fixed4 frag (v2f i) : SV_Target
{
   float2 center = float2(i.worldPos.x,i.
worldPos.y) - float2(_Center1.x, _Center1.y); float dis = sqrt(center.x * center.x + center.y * center.y); clip(dis - _Radius1); fixed4 col = tex2D(_MainTex, i.uv) * i.color; return col; }

第二種也是最終的實現方法的關鍵程式碼:

v2f vert (appdata v)
{
   v2f o;
   o.vertex = UnityObjectToClipPos(v.vertex);
o.worldPos = mul(unity_ObjectToWorld, v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); o.color = v.color; return o; } fixed4 frag (v2f i) : SV_Target { float2 center = float2(i.worldPos.x, i.worldPos.y) - float2(_Center1.x, _Center1.y); float dis = sqrt(center.x * center.x + center.y * center.y); float radius = distance(_Center1, _Center2); clip(dis - radius); fixed4 col = tex2D(_MainTex, i.uv) * i.color; return col; }

然後c#中傳入兩點的世界座標即可。世界座標的獲取方法,首先把真實場景中安全區的圓心safePoint轉換成小地圖上對應的座標localPos,然後用小地圖的transform.TransformPoint(localPos)把相對於小地的本地座標轉換成世界座標center,最後把世界座標傳入shader中

_bgMask.material.SetVector("_Center1", center);

效果圖


總結

牢騷與感慨:作為程式設計師深入瞭解並探索問題的本質是必須的,這有助於我們技術的進步。但是在工作中時間排期緊迫的情況下,換一種思路有可能會更容易實現我們的需求,同時也避免了處理其他複雜的情況。所以最後我還是想提出上面提到的這個問題:如何解決不同解析度下,NGUI中傳入shader相同的半徑值,但是裁剪的圓的大小不一樣的問題。