基於過程渲染的小地圖shader
阿新 • • 發佈:2019-02-18
小地圖中有很多標誌物,大量的物件一直顯示在螢幕中,所以想了一種優化方式,優化點這部分的效能
優點:
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);
}