1. 程式人生 > >基於過程渲染的小地圖shader

基於過程渲染的小地圖shader

小地圖中有很多標誌物,大量的物件一直顯示在螢幕中,所以想了一種優化方式,優化點這部分的效能

優點:
1. 只需要一個DrawCall,全部渲染到一張圖片,就可以渲染出小地圖
2. 不需要生成大量的標誌物例項
3. 規則圖形直接使用程式碼計算生成來代替取樣(一般小地圖上的很多標誌物都是取樣圖片)
缺點:
小地圖的每個畫素經過了大量的運算。

總結:
我沒有測試這樣是否優化了效能,所以只能算是小地圖的另一種實現方式,不過由於GPG的高併發計算能力,這樣也許會使效能得到優化。如果有人測試了效能,希望告知

效果如下:

這裡寫圖片描述

程式碼如下:

Shader "Unlit/MinMap"
{ Properties { _MainTex("Texture", 2D) = "white" {} _PointTex("Point Texture", 2D) = "white" {} _CircleColor("Point Col",Color) = (1,1,1,1) _CircleColor2("Point Col2",Color) = (1,1,1,1) _Angle("Angle",float)=0 _Parameters("Parameters",Vector) = (0
,0,0,0) } SubShader { Tags { "RenderType" = "Opaque" } LOD 100 Pass { Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" //渲染圓點 fixed4 circle(float2 pos, float2 center, float radius, fixed3 color, float antialias) { float d = length(pos - center) - radius;
float t = smoothstep(0, antialias, d); return fixed4(color, 1.0 - t); } //混合操作 fixed4 mix(fixed4 col1, fixed4 col2, fixed alpha) { return fixed4(col1.rgb*(1 - alpha) + col2.rgb*alpha ,max(col1.a,col2.a)); } struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float2 uv2 : TEXCOORD1; float4 vertex : SV_POSITION; }; sampler2D _MainTex; sampler2D _PointTex; float4 _MainTex_ST; float4 _PointTex_ST; //一共渲染20個點,分為兩部分 float4 _Pos[20]; float4 _RolePos; //渲染的點的顏色,這個也可以使用C#程式碼傳入,在沒一點的資訊裡記錄,目前只記錄了位置 fixed4 _CircleColor; fixed4 _CircleColor2; float4 _Parameters; float _Angle; v2f vert(appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); //構造旋轉矩陣 float cosA = cos(_Angle); float sinA = sin(_Angle); float3x3 _Matrix = { cosA,-sinA,0, sinA,cosA,0, 0,0,1, }; o.uv2 = TRANSFORM_TEX(v.uv, _PointTex); o.uv2 = mul(_Matrix, o.uv2-float2(0.5,0.5)) + float2(0.5, 0.5); return o; } fixed4 frag(v2f i) : SV_Target { // sample the texture fixed4 col = tex2D(_MainTex, i.uv); fixed4 col2 = tex2D(_PointTex, i.uv2); //程式碼看起來可能比較low,為了不使用迴圈,我也沒辦法了,希望有改進的意見 fixed4 layer0 = circle(i.uv, _Pos[0], _Pos[0].z, _CircleColor.rgb, _Parameters.w); fixed4 layer1 = circle(i.uv, _Pos[1], _Pos[1].z, _CircleColor.rgb, _Parameters.w); fixed4 layer2 = circle(i.uv, _Pos[2], _Pos[2].z, _CircleColor.rgb, _Parameters.w); fixed4 layer3 = circle(i.uv, _Pos[3], _Pos[3].z, _CircleColor.rgb, _Parameters.w); fixed4 layer4 = circle(i.uv, _Pos[4], _Pos[4].z, _CircleColor.rgb, _Parameters.w); fixed4 layer5 = circle(i.uv, _Pos[5], _Pos[5].z, _CircleColor.rgb, _Parameters.w); fixed4 layer6 = circle(i.uv, _Pos[6], _Pos[6].z, _CircleColor.rgb, _Parameters.w); fixed4 layer7 = circle(i.uv, _Pos[7], _Pos[7].z, _CircleColor.rgb, _Parameters.w); fixed4 layer8 = circle(i.uv, _Pos[8], _Pos[8].z, _CircleColor.rgb, _Parameters.w); fixed4 layer9 = circle(i.uv, _Pos[9], _Pos[9].z, _CircleColor.rgb, _Parameters.w); fixed4 layer10= circle(i.uv, _Pos[10], _Pos[10].z, _CircleColor2.rgb, _Parameters.w); fixed4 layer11= circle(i.uv, _Pos[11], _Pos[11].z, _CircleColor2.rgb, _Parameters.w); fixed4 layer12= circle(i.uv, _Pos[12], _Pos[12].z, _CircleColor2.rgb, _Parameters.w); fixed4 layer13= circle(i.uv, _Pos[13], _Pos[13].z, _CircleColor2.rgb, _Parameters.w); fixed4 layer14= circle(i.uv, _Pos[14], _Pos[14].z, _CircleColor2.rgb, _Parameters.w); fixed4 layer15= circle(i.uv, _Pos[15], _Pos[15].z, _CircleColor2.rgb, _Parameters.w); fixed4 layer16= circle(i.uv, _Pos[16], _Pos[16].z, _CircleColor2.rgb, _Parameters.w); fixed4 layer17= circle(i.uv, _Pos[17], _Pos[17].z, _CircleColor2.rgb, _Parameters.w); fixed4 layer18= circle(i.uv, _Pos[18], _Pos[18].z, _CircleColor2.rgb, _Parameters.w); fixed4 layer19= circle(i.uv, _Pos[19], _Pos[19].z, _CircleColor2.rgb, _Parameters.w); fixed4 fragColor = mix(col, layer0, layer0.a); fragColor = mix(fragColor, layer1, layer1.a); fragColor = mix(fragColor, layer2, layer2.a); fragColor = mix(fragColor, layer3, layer3.a); fragColor = mix(fragColor, layer4, layer4.a); fragColor = mix(fragColor, layer5, layer5.a); fragColor = mix(fragColor, layer6, layer6.a); fragColor = mix(fragColor, layer7, layer7.a); fragColor = mix(fragColor, layer8, layer8.a); fragColor = mix(fragColor, layer9, layer9.a); fragColor = mix(fragColor, layer10, layer10.a); fragColor = mix(fragColor, layer11, layer11.a); fragColor = mix(fragColor, layer12, layer12.a); fragColor = mix(fragColor, layer13, layer13.a); fragColor = mix(fragColor, layer14, layer14.a); fragColor = mix(fragColor, layer15, layer15.a); fragColor = mix(fragColor, layer16, layer16.a); fragColor = mix(fragColor, layer17, layer17.a); fragColor = mix(fragColor, layer18, layer18.a); fragColor = mix(fragColor, col2, col2.a);//顯示在最上面 return fragColor; } ENDCG } } }

shader程式碼一共就這些,實現了npc的移動,玩家的移動和旋轉,npc通過計算得到(使用了圓形,當然也可以使用其他的形狀,修改圓形的程式碼即可),玩家通過取樣圖片(一般遊戲這樣區別玩家和npc)
C#程式碼
比較簡單,傳遞玩家旋轉資訊和npc的位置資訊,玩家的位置資訊不需要傳遞,只需要讓玩家保持在小地圖中心,使用程式碼調整image的縮放和偏移即可

    public void SetM(Vector4[] _pos, float angle)
    {
        pos = _pos;
        m.SetVectorArray("_Pos", pos);
        m.SetFloat("_Angle", angle);
    }