Unity 3D 热力图效果实现

                                                效果图

一、动态创建mesh

首先需要创建一个Mesh,当然这不是必须的,可以使用plane,自己创建主要方便控制精度。修改顶点高度,如果顶点不够可能不够平滑,太多又浪费资源。因此最好根据实际需求大小生成。

 private void CreateMesh()
    {
        float perxlength = mapSize.x /(meshSize.x - 1);
        float perzlength = mapSize.y / (meshSize.y - 1);


        int totalcount = (int)meshSize.x * (int)meshSize.y;
        Vector3[] vertexs = new Vector3[totalcount];
        Vector3[] normals = new Vector3[totalcount];

        int[] triangles = new int[((int)meshSize.x - 1) * ((int)meshSize.y - 1) * 2 * 3];

        int trianglesindex = 0;
        for (int i = 0; i < meshSize.y; i++)
        {

            for (int j = 0; j < meshSize.x; j++)
            {
                float x = perxlength * j;
                float z = perzlength * i;

                int index = i * (int)meshSize.x + j;

                vertexs[index] = new Vector3(x, 0, z);
                normals[index] = transform.up;

                if(j != meshSize.x - 1&& i != meshSize.y - 1)
                {
                    triangles[trianglesindex] = j + i * (int)meshSize.x;
                    trianglesindex++;
                    triangles[trianglesindex] = j + 1 + (int)meshSize.x + i * (int)meshSize.x;
                    trianglesindex++;
                    triangles[trianglesindex] = j + 1 + i * (int)meshSize.x;
                    trianglesindex++;
                    triangles[trianglesindex] = j + i * (int)meshSize.x;
                    trianglesindex++;
                    triangles[trianglesindex] = j + (int)meshSize.x + i * (int)meshSize.x;
                    trianglesindex++;
                    triangles[trianglesindex] = j + 1 + (int)meshSize.x + i * (int)meshSize.x;
                    trianglesindex++;
                }
            }
        }

        Mesh mesh = new Mesh();
        mesh.vertices = vertexs;
        mesh.normals = normals;
        mesh.triangles = triangles;

        GetComponent<MeshFilter>().mesh = mesh;
    }

二、Shader修改顶点高度

mesh是一个平面,顶点高度的修改在Shader中完成。具体高度根据热力数据计算,因为热力数据是某一个点的数据,所以需要计算扩散的热力值。

Shader "Unlit/thermograph3d"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}

        _Alpha("Alpha" , Range(0,1)) = 0.5
    }
    SubShader
    {
        Tags { "RenderType"="Transparent" "Queue" ="Transparent"}

        Blend SrcAlpha OneMinusSrcAlpha

        Pass
        {
            CGPROGRAM
// Upgrade NOTE: excluded shader from DX11, OpenGL ES 2.0 because it uses unsized arrays
            #pragma exclude_renderers d3d11 gles
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"


            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float temp : TEXCOORD1;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            float _Alpha ;

            vector tempData[30];
            float tempcount;

            float perTempHeight;

            float maxRefrence;

            vector colorLine;

            float GetHeight(float2 vertex)
            {
                float height;
                for(int i = 0;i<tempcount;i++)
                {
                     float deltax = vertex.x  - tempData[i].x;
                     float deltay = vertex.y  - tempData[i].y;

                     float distance = sqrt(deltax * deltax + deltay * deltay);
                     if(distance > maxRefrence)
                           continue;
                     float centerheight = perTempHeight * tempData[i].z;

                     float releaseDis =( 1 - (maxRefrence - distance)/maxRefrence);

                     height += centerheight *  -(releaseDis *releaseDis * releaseDis ) + centerheight;
                }

                return  height;
            }

            fixed4 Temp2Color(float temp , fixed4 color , float _Alpha)
            {
                color.a = 0;
                if(temp > colorLine.x + 20)
                    return fixed4(1,0,0,_Alpha);
                if(temp > colorLine.x)
                    return fixed4(1,0,0,_Alpha) * (1 - (colorLine.x + 20 - temp) / 20) + fixed4(1,1,0,_Alpha) * (colorLine.x + 20 - temp) / 20;
                if(temp > colorLine.y + 20)
                    return fixed4(1,1,0,_Alpha);
                if(temp > colorLine.y)
                    return fixed4(1,1,0,_Alpha) * (1 - (colorLine.y + 20 - temp) / 20) + fixed4(0,1,1,_Alpha) * (colorLine.y + 20 - temp) / 20;
                if(temp > colorLine.z + 20)
                    return fixed4(0,1,1,_Alpha);
                if(temp > colorLine.z)
                    return fixed4(0,1,1,_Alpha) * (1 - (colorLine.z + 20 - temp) / 20) + color * (colorLine.z + 20 - temp) / 20;
                return color;
            }

            v2f vert (appdata v)
            {
                v2f o;
             
                v.vertex.y = GetHeight(v.vertex.xz);
                o.temp = v.vertex.y / perTempHeight;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                              
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);
                fixed4 color = Temp2Color(i.temp , col ,_Alpha);
                return color;
            }
            ENDCG
        }
    }
}

这是shader的完整代码,高度计算部分可以自己根据算法修改,这个算法没有根据,只是满足变化曲线的随便一个计算方式。

融合部分也是没有根据的算法,不能用到检测环境中,具体算法也需要按照温度变化算法计算的。

C#部分如果要源码,可以私信我(先关注)。觉得有用,麻烦点个赞👍。

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页