unity 制作3D等温图

来源:互联网 发布:鲍勃.马利 知乎 编辑:程序博客网 时间:2024/04/28 00:02

3D等温图的制作过程

思路1

动态生成mesh

动态生成texture2D

将texture2D通过uv赋值

思路2

动态生成mesh

通过赋值mesh.color赋值颜色

思路2过于复杂,对于我有点难度,选择1

mesh生成通过贝塞尔曲线使它更加光滑

实现代码如下

private void CreatMeshWithValue() {BezierTerrain bezier = new BezierTerrain();                //va,vb....为vector3[]数组,bezier.CreatPath方法会返回一个贝塞尔曲线的路径                object[] allV = new object[]{bezier.CreatPath(va,6),bezier.CreatPath(vb,6),bezier.CreatPath(vc,6),bezier.CreatPath(vd,6),bezier.CreatPath(ve,6),bezier.CreatPath(vf,6),bezier.CreatPath(vg,6)};float MaxMinValue = 12f;List<object> allC = new List<object>();foreach (Vector3[] v in allV){List<Color> colorArr = new List<Color>();foreach (Vector3 item in v){float value = (item.y / MaxMinValue) * 4 * 255;Color color;if (0f <= value && value < 255){color = new Color(0f, value, 255f);}else if (value >= 255f && value < 510f){color = new Color(0, 255f, 255f - (value - 255f));}else if (value >= 510f && value < 765f){color = new Color((value - 510f), 255f, 0f);}else{color = new Color(255, 255f - (value - 765f), 0f);}colorArr.Add(color);}allC.Add(colorArr.ToArray());}object[] a = allC.ToArray();MeshWithVector3sColors(allV, allC.ToArray());}//meshvoid MeshWithVector3sColors(object[] allV,object[] allC) {MeshFilter meshFilter = this.gameObject.GetComponent<MeshFilter>();Mesh mesh = new Mesh();mesh.name = "ColorMesh";//顶点数量int verticesCount = allV.Length * (allV[0] as Vector3[]).Length;Vector3[] vertices = new Vector3[verticesCount];//三角形数量int triangles_count = (allV.Length - 1) * ((allV[0] as Vector3[]).Length - 1 ) * 2 ;//三角形顶点IDint[] triangles = new int[triangles_count * 3];//Color[] colorCount = new Color[verticesCount];int index_v = 0;//Vector2[] uvs = new Vector2[verticesCount];//vertice colorfor (int i = 0; i < allV.Length; i++) {Vector3[] vi = allV[i] as Vector3[];for (int j = 0; j < (allV[i] as Vector3[]).Length; j++) {vertices[index_v] = vi[j];Color color = (allC[i] as Color[])[j];colorCount[index_v] = new Color(color.r / 255f,color.g / 255f,color.b / 255f,1f);index_v++;}}//trianglesint index_t = 0;for (int i = 0; i < allV.Length - 1; i++){Vector3[] vi = allV[i] as Vector3[];int nW = allV.Length;int nH = vi.Length;for (int j = 0; j < vi.Length - 1; j++){triangles[index_t++] = i * vi.Length + j;triangles[index_t++] = (i + 1) * vi.Length + j;triangles[index_t++] = (i + 1) * vi.Length + j + 1;triangles[index_t++] = i * vi.Length + j;triangles[index_t++] = (i + 1) * vi.Length + j + 1;triangles[index_t++] = i * vi.Length + j + 1;}}//uv贴图与veritces重合便可以将制作的贴图贴上,但是个点的比例要与mesh三角形比例相同,否则无法贴上//List<Vector2> uvV2 = new List<Vector2>();//for (int i = 0; i < allV.Length; i++)//{//for (int j = 0; j < (allV[i] as Vector3[]).Length; j++)//{//Vector2 v = new Vector2((float)j * (1f / (float)((allV[i] as Vector3[]).Length - 1)), (float)i * (1f / ((float)allV.Length - 1)));//uvV2.Add(v);//Debug.Log(v.x + " " + v.y);//countUV++;//}//}//mesh.uv = new Vector2[] { new Vector2 (0,0),new Vector2(0,1),new Vector2(1,1) };mesh.vertices = vertices;mesh.triangles = triangles;mesh.colors = colorCount;mesh.RecalculateNormals();meshFilter.mesh = mesh;}

使用shader,具体的参考

http://blog.csdn.net/qq_29579137/article/details/77854504

参考这个博主的文章,使用里面的shader,当然我还学着写了一个高光的shader,更有立体感

Shader "Volume13/4.Specular"  {      //------------------------------------【属性值】------------------------------------      Properties      {          //主颜色          _Color("Main Color", Color) = (1, 1, 1, 1)          //镜面反射颜色          _SpecColor("Specular Color", Color) = (1, 1, 1, 1)          //镜面反射光泽度          _SpecShininess("Specular Shininess", Range(1.0, 100.0)) = 10.0      }        //------------------------------------【唯一的子着色器】------------------------------------      SubShader      {          //渲染类型设置:不透明          Tags{ "RenderType" = "Opaque" }          LOD 200          //--------------------------------唯一的通道-------------------------------          Pass          {                  //光照模型ForwardBase              Tags{ "LightMode" = "ForwardBase" }Cull OFF            //===========开启CG着色器语言编写模块===========              CGPROGRAM                //编译指令:告知编译器顶点和片段着色函数的名称              #pragma vertex vert              #pragma fragment frag                //顶点着色器输入结构              struct appdata              {                  float4 vertex : POSITION;//顶点位置                  float3 normal : NORMAL;//法线向量坐标  fixed4 color :COLOR;            };                //顶点着色器输出结构              struct v2f              {                  float4 pos : SV_POSITION;//像素位置                  float3 normal : NORMAL;//法线向量坐标                  float4 posWorld : TEXCOORD0;//在世界空间中的坐标位置  fixed4 color :COLOR;            };                  //变量的声明              float4 _LightColor0;              float4 _Color;              float4 _SpecColor;              float _SpecShininess;                //--------------------------------【顶点着色函数】-----------------------------              // 输入:顶点输入结构体              // 输出:顶点输出结构体              //---------------------------------------------------------------------------------              //顶点着色函数              v2f vert(appdata IN)              {                  //【1】声明一个输出结构对象                  v2f OUT;                    //【2】填充此输出结构                  //输出的顶点位置为模型视图投影矩阵乘以顶点位置,也就是将三维空间中的坐标投影到了二维窗口                  OUT.pos = mul(UNITY_MATRIX_MVP, IN.vertex);                  //获得顶点在世界空间中的位置坐标                  OUT.posWorld = mul(unity_ObjectToWorld, IN.vertex);                  //获取顶点在世界空间中的法线向量坐标                  OUT.normal = mul(float4(IN.normal, 0.0), unity_WorldToObject).xyz;                  OUT.color = IN.color;                //【3】返回此输出结构对象                  return OUT;              }                //--------------------------------【片段着色函数】-----------------------------              // 输入:顶点输出结构体              // 输出:float4型的像素颜色值              //---------------------------------------------------------------------------------              fixed4 frag(v2f IN) : COLOR              {                  //【1】先准备好需要的参数                  //获取法线的方向                  float3 normalDirection = normalize(IN.normal);                  //获取入射光线的方向                  float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz);                  //获取视角方向                  float3 viewDirection = normalize(_WorldSpaceCameraPos - IN.posWorld.xyz);                    //【2】计算出漫反射颜色值  Diffuse=LightColor * MainColor * max(0,dot(N,L))                  float3 diffuse = _LightColor0.rgb * IN.color * max(0.0, dot(normalDirection, lightDirection));                    //【3】计算镜面反射颜色值                   float3 specular;                  //若是法线方向和入射光方向大于180度,镜面反射值为0                  if (dot(normalDirection, lightDirection) < 0.0)                  {                      specular = float3(0.0, 0.0, 0.0);                  }                  //否则,根据公式进行计算 Specular =LightColor * SpecColor *pow(max(0,dot(R,V)),Shiness),R=reflect(-L,N)                  else                  {                      float3 reflectDirection = reflect(-lightDirection, normalDirection);                          specular = _LightColor0.rgb * _SpecColor.rgb * pow(max(0.0, dot(reflectDirection, viewDirection)), _SpecShininess);                  }                    //【4】合并漫反射、镜面反射、环境光的颜色值                  float4 diffuseSpecularAmbient = float4(diffuse, 1.0) + float4(specular, 1.0) + UNITY_LIGHTMODEL_AMBIENT;                    //【5】将漫反射-镜面反射-环境光的颜色值返回                  return diffuseSpecularAmbient;              }                //===========结束CG着色器语言编写模块===========              ENDCG          }      }  }
这样输入几个vector3[]路径,就可以返回一个3D的等温图了

贝塞尔曲线类的代码是可以参考我过去的博文

http://blog.csdn.net/qq_37240033/article/details/77945599


学习过程中还学会了制作渐变texture2D

具体代码是

        Texture2D allTexture(object[] allC,int width,int height){proceduralTexture = new Texture2D(width * ((allC[0] as Color[]).Length - 1), (allC.Length - 1) * height);int j = 0;for (int color_x = 0; color_x < allC.Length - 1; color_x++){int i = 0;Color[] color_0 = allC[color_x] as Color[];Color[] color_1 = allC[color_x + 1] as Color[];for (int color_y = 0; color_y < (allC[color_x] as Color[]).Length - 1; color_y++){CreatMeshItemTexture(color_0[color_y], color_0[color_y + 1], color_1[color_y], color_1[color_y + 1], width, height, i, j);i++;}j++;}proceduralTexture.Apply();return proceduralTexture;}public void CreatMeshItemTexture(Color a1, Color a2, Color a3, Color a4, int width, int height, int coutWidth, int coutHeight){for (int y = 0; y < height; y++){float dr_13 = (a3.r - a1.r) / height;float dg_13 = (a3.g - a1.g) / height;float db_13 = (a3.b - a1.b) / height;Color dx0 = new Color(dr_13 * y + a1.r, dg_13 * y + a1.g, db_13 * y + a1.b);float dr_24 = (a4.r - a2.r) / height;float dg_24 = (a4.g - a2.g) / height;float db_24 = (a4.b - a2.b) / height;Color dx1 = new Color(dr_24 * y + a2.r, dg_24 * y + a2.g, db_24 * y + a2.b);for (int x = 0; x < width; x++){float dr = (dx1.r - dx0.r) / width;float dg = (dx1.g - dx0.g) / width;float db = (dx1.b - dx0.b) / width;Color pixeColor = new Color((dr * x + dx0.r) / 255f , (dg * x + dx0.g) / 255f, (db * x + dx0.b) / 255f);proceduralTexture.SetPixel(x + coutWidth * width, y + coutHeight * height, pixeColor);}}}


最终效果



参考了

http://blog.csdn.net/qq_29579137/article/details/77854504

http://blog.csdn.net/nanggong/article/details/54311090