Unity 热力图建立方法

Unity 热力图建立方法

实现效果


工程文件下载

基本思路

之前有写过用网格顶点赋值颜色生成热力图的方法。有一个很大的缺点,需要大量的网格点支持,提高了GPU的渲染压力。所以换了一个思路,直接创建并修改图片像素的颜色,这样只需要四个顶点的网格就可以承载热力图的生成。

计算前fbs→97.5

计算后fbs→96.5

基本不受影响。

解决问题及办法

  1. 世界坐标和像素坐标的转换;

  2. 像素的初始化及像素的加权值;

  3. 色块的颜色和影响范围关系的配置;

  4. 分辨率和性能的调节。

世界坐标和像素坐标的转换

这里有两个注意点,一是网格的轴心点,二是uv的坐标轴。网格的原点是模型美术规定的,但是在世界坐标转像素坐标时,需要将原点对应,所以要改变一下网格的原点。改变原点有两种方式,1.让美术修改,将网格的原点改成uv坐标系的原点;2.给网格加一个父物体,父物体的位置在网格的uv坐标原点。如下图所示

完成原点对齐后,自需要求出比例就可以。

            Vector3 modelSize = gameObject.GetComponent<Collider>().bounds.size;
            float MapRatio = heatMapBase.Resolution / modelSize.x;
            //heatMapBase.Resolution是定义的图片像素分辨率。
            //MapRatio是图片坐标和世界坐标转换的比例

像素的初始化及像素的加权值

运行之前要先把所以像素的权值全部归零。带权的参考点会对周围的像素点进行影响,影响的范围和自身的权值有关,这里还可以引入一个变量DisRatio,用于改变权值的影响范围。给像素赋权值的时,只能值覆盖小值。

 //每个像素初始化
            List<Vector2> my_Pixels = new List<Vector2>();
            List<float> my_Values = new List<float>();
            for (int y = 0; y < texture.height; y++)
            {
                for (int x = 0; x < texture.width; x++)
                {

                    Vector2 pixel = new Vector2(x, y);
                    my_Pixels.Add(pixel);
                    my_Values.Add(0);
                }
            }
            int allLength = my_Pixels.Count;//所以像素点数量
            int pointLength = heatMapInfos.Count;//热力图兴趣点点数量
            int colorLength = heatMapBase.HeatMapInfos.Count;//色块等级
            //每个像素加权值
            for (int p = 0; p < pointLength; p++)
            {
                for (int a = 0; a < allLength; a++)
                {
                    float my_Distance = Vector2.Distance(heatMapInfos[p].Pixel* MapRatio, my_Pixels[a]);

                    float my_MaxDis = heatMapBase.DisRatio * heatMapInfos[p].Amount;

                    if (my_Distance < my_MaxDis)
                    {

                        float value = (1 - (Mathf.Pow(my_Distance, 2) / Mathf.Pow(my_MaxDis, 2))) * heatMapInfos[p].Amount;
                        if (value > my_Values[a])
                        {
                            my_Values[a] = value;
                        }
                    }
                }
            }

色块的颜色和影响范围关系的配置

色块的颜色选取,权值,图片的分辨率和影响范围是动态可以配置的。这里加一个模板用来控制。为了方便像素颜色的赋值,规定权值由大到小填入。

    public class HeatMapBase : ScriptableObject
    {
        public float DisRatio;//距离比例
        public float Resolution;//分辨率
        public List<HeatMapInfo> HeatMapInfos;
   
        [Serializable]
        public class HeatMapInfo
        {
            public float MaxAmount;//最大权值
            public Color Color;//颜色
        }
    }

分辨率和性能的调节

在编写之初,考虑动态改变分辨率,网格越大分辨率越大。但这个无疑是增加了性能的消耗。所以考虑将分辨率写入配置表。转而出现了图片大范围的锯齿如下图。后面引入了color的插值运算,完美解决问题。

不加插值

加插值

  //每个像素赋值颜色
            for (int i = 0; i < allLength; i++)
            {
                for (int j = 0; j < colorLength; j++)
                {
                    float my_CurMaxAmount = heatMapBase.HeatMapInfos[j].MaxAmount;
                  
                    if (my_Values[i] >= my_CurMaxAmount)
                    {
                        //当前块的颜色
                        Color my_CurColor = heatMapBase.HeatMapInfos[j].Color;

                        if (j != 0)
                        {

                            float my_UpDiffValue = heatMapBase.HeatMapInfos[j - 1].MaxAmount - my_CurMaxAmount;
                            Color my_UpColor = heatMapBase.HeatMapInfos[j - 1].Color;

                            float t = (my_Values[i] - my_CurMaxAmount) / my_UpDiffValue;
                            texture.SetPixel((int)my_Pixels[i].x, (int)my_Pixels[i].y, Color.Lerp(my_CurColor, my_UpColor, t));
                            break;
                        }
                        else
                        {
                            texture.SetPixel((int)my_Pixels[i].x, (int)my_Pixels[i].y, my_CurColor);
                            break;
                        }
                    }
                }
            }

猜你喜欢

转载自blog.csdn.net/dxs1990/article/details/125395095