小地圖毒圈遮罩挖洞的實現
阿新 • • 發佈:2021-02-03
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相同的半徑值,但是裁剪的圓的大小不一樣的問題。