1. 程式人生 > >Unity&Shader案例篇—地圖上熱圖分佈

Unity&Shader案例篇—地圖上熱圖分佈

一、介紹

        在2維平面地圖上隨機或者指定位置生成一系列的熱量、能源或者其他需要表示的資訊的分佈圖。可以通過切換不同的貼圖表示不同的資訊,如圖所示表示的是該地區的降水量的變化


如圖所示為表示該地區的溫度變化分佈圖


二、實現

       在貼圖的的某個位置處繪製指定半徑的圓圈,然後調整圓圈的強度也即透明度。因此Shader部分會定義這兩類變數,因為Shader裡面不能定義沒有長度的陣列,只能一開始給個固定比較大的100作為初始長度,在程式碼裡傳這個陣列變數的時候只要不超過這個陣列的長度的引數都是可以的。當然你穿了101個數組的引數也不會報錯,但是超出100的肯定也不會被shader程式碼使用到

			//自定義變數
			uniform int _Points_Length = 0;
			uniform float3 _Points[100];		// (x, y, z) = 位置
			uniform float2 _Properties[100];	// x = 半徑, y = 透明度
			sampler2D _HeatTex;

然後,計算每個分佈點位置相對世界座標原地的距離,再結合強度就可以都到一個輸出的透明度值。片段著色器程式碼為:

half4 frag(vertOutput output) : COLOR
			{
				half h = 0;
				for (int i = 0; i < _Points_Length; i++)
				{
					// 計算每一個分佈點位置的距離
					half di = distance(output.worldPos, _Points[i].xyz);

					half ri = _Properties[i].x;
					half hi = 1 - saturate(di / ri);

					h += hi * _Properties[i].y;
				}

				
				h = saturate(h);
				half4 col = tex2D(_HeatTex, fixed2(h, 0.5));
				return col;
			}

接下來編寫控制指令碼,這裡寫了一個隨機的位置、半徑和強度。

  pointPoses = new Vector4[countPoint];
        pointProper = new Vector4[countPoint];

        for (int i = 0; i < pointPoses.Length; i++)
        {
            pointPoses[i] = new Vector2(Random.Range(-0.9f, 0.9f), Random.Range(-0.5f, 0.5f));
            pointProper[i] = new Vector2(Random.Range(0f, 0.25f), Random.Range(-0.25f, 1f)); // (Radius, Intensities)
        }

        heatMat.SetVectorArray("_Properties", pointProper);
        heatMat.SetInt("_Points_Length", countPoint);

最後要得到如上圖所示的閃爍的熱圖效果,就是在已有的點位置上加一個噪聲處理,如:

 for (int i = 0; i < countPoint; i++)
        {
            pointPoses[i] += new Vector4(Random.Range(-0.1f, +0.1f), Random.Range(-0.1f, +0.1f), 0f, 0f) * Time.deltaTime;
        }
        heatMat.SetVectorArray("_Points", pointPoses);

三、總結

 1、通過處理不同強度的噪聲變化也能得到一些區域著重顯示的效果