首页 > 代码库 > Unity3d之将terrain转化成mesh

Unity3d之将terrain转化成mesh

Unity3d中,terrain还是比较耗的,DrawCall数也比较多,为了优化性能,可能需要将terrain转化成mesh。

现提供一工具,思路是根据terrain高度图生成mesh等,可参考: http://wiki.unity3d.com/index.php?title=TerrainObjExporter

代码还有诸多问题,如下:

技术分享
  1 using UnityEditor;  2 using UnityEngine;  3   4 public class TerrainToMeshConverter : ScriptableObject  5 {  6     [MenuItem("Custom/Convert terrain to mesh")]  7     static void Init()  8     {  9         if (Selection.objects.Length <= 0) 10         { 11             DevDebug.Log("Selection.objects.Length <= 0"); 12             return; 13         } 14  15         var terrainObj = Selection.objects[0] as GameObject; 16         if (terrainObj == null) 17         { 18             DevDebug.Log("terrainObj == null"); 19             return; 20         } 21  22         var terrain = terrainObj.GetComponent<Terrain>(); 23         if (terrain == null) 24         { 25             DevDebug.Log("terrain == null"); 26             return; 27         } 28  29         var terrainData =http://www.mamicode.com/ terrain.terrainData; 30         if (terrainData =http://www.mamicode.com/= null) 31         { 32             DevDebug.Log("terrainData =http://www.mamicode.com/= null"); 33             return; 34         } 35  36         int vertexCountScale = 4;       // [dev] 将顶点数稀释 vertexCountScale*vertexCountScale 倍 37         int w = terrainData.heightmapWidth; 38         int h = terrainData.heightmapHeight; 39         Vector3 size = terrainData.size; 40         float[, ,] alphaMapData = http://www.mamicode.com/terrainData.GetAlphamaps(0, 0, terrainData.alphamapWidth, terrainData.alphamapHeight); 41         Vector3 meshScale = new Vector3(size.x / (w - 1f) * vertexCountScale, 1, size.z / (h - 1f) * vertexCountScale); 42         Vector2 uvScale = new Vector2(1f / (w - 1f), 1f / (h - 1f)) * vertexCountScale * (size.x / terrainData.splatPrototypes[0].tileSize.x);     // [dev] 此处有问题,若每个图片大小不一,则出问题。日后改善 43  44         w = (w - 1) / vertexCountScale + 1; 45         h = (h - 1) / vertexCountScale + 1; 46         Vector3[] vertices = new Vector3[w * h]; 47         Vector2[] uvs = new Vector2[w * h]; 48         Vector4[] alphasWeight = new Vector4[w * h];            // [dev] 只支持4张图片 49  50         // 顶点,uv,每个顶点每个图片所占比重 51         for (int i = 0; i < w; i++) 52         { 53             for (int j = 0; j < h; j++) 54             { 55                 int index = j * w + i; 56                 float z = terrainData.GetHeight(i * vertexCountScale, j * vertexCountScale); 57                 vertices[index] = Vector3.Scale(new Vector3(i, z, j), meshScale); 58                 uvs[index] = Vector2.Scale(new Vector2(i, j), uvScale); 59  60                 // alpha map 61                 int i2 = (int)(i * terrainData.alphamapWidth / (w - 1f)); 62                 int j2 = (int)(j * terrainData.alphamapHeight / (h - 1f)); 63                 i2 = Mathf.Min(terrainData.alphamapWidth - 1, i2); 64                 j2 = Mathf.Min(terrainData.alphamapHeight - 1, j2); 65                 var alpha0 = alphaMapData[j2, i2, 0]; 66                 var alpha1 = alphaMapData[j2, i2, 1]; 67                 var alpha2 = alphaMapData[j2, i2, 2]; 68                 var alpha3 = alphaMapData[j2, i2, 3]; 69                 alphasWeight[index] = new Vector4(alpha0, alpha1, alpha2, alpha3); 70             } 71         } 72  73         /* 74          * 三角形 75          *     b       c 76          *      ******* 77          *      *   * * 78          *      * *   * 79          *      ******* 80          *     a       d 81          */ 82         int[] triangles = new int[(w - 1) * (h - 1) * 6]; 83         int triangleIndex = 0; 84         for (int i = 0; i < w - 1; i++) 85         { 86             for (int j = 0; j < h - 1; j++) 87             { 88                 int a = j * w + i; 89                 int b = (j + 1) * w + i; 90                 int c = (j + 1) * w + i + 1; 91                 int d = j * w + i + 1; 92  93                 triangles[triangleIndex++] = a; 94                 triangles[triangleIndex++] = b; 95                 triangles[triangleIndex++] = c; 96  97                 triangles[triangleIndex++] = a; 98                 triangles[triangleIndex++] = c; 99                 triangles[triangleIndex++] = d;100             }101         }102 103         Mesh mesh = new Mesh();104         mesh.vertices = vertices;105         mesh.uv = uvs;106         mesh.triangles = triangles;107         mesh.tangents = alphasWeight;108         mesh.Optimize();109 110         // 地形渲染  [dev] 目前不支持光照,有待改善111         var mat = new Material(Shader.Find("Custom/TerrainDiffuse"));112         for (int i = 0; i < terrainData.splatPrototypes.Length; i++)113         {114             var sp = terrainData.splatPrototypes[i];115             mat.SetTexture("_Texture" + i, sp.texture);116         }117 118         string transName = "[dev]MeshFromTerrainData";119         var t = terrainObj.transform.parent.Find(transName);120         if (t == null)121         {122             GameObject go = new GameObject(transName, typeof(MeshFilter), typeof(MeshRenderer), typeof(MeshCollider));123             t = go.transform;124         }125 126         t.parent = terrainObj.transform.parent;127         t.position = terrainObj.transform.position;128         t.gameObject.layer = terrainObj.layer;129         t.GetComponent<MeshFilter>().sharedMesh = mesh;130         t.GetComponent<MeshCollider>().sharedMesh = mesh;131         t.GetComponent<MeshRenderer>().sharedMaterial = mat;132 133         t.gameObject.SetActive(true);134         terrainObj.SetActive(false);135     }136 }
TerrainToMeshConverter

渲染地形的shader如下:

技术分享
 1 Shader "Custom/TerrainDiffuse" 2 { 3     Properties 4     { 5         _Texture0 ("Texture 1", 2D) = "white" {} 6         _Texture1 ("Texture 2", 2D) = "white" {} 7         _Texture2 ("Texture 3", 2D) = "white" {} 8         _Texture3 ("Texture 4", 2D) = "white" {} 9     }10     11     SubShader12     {13         Tags { "RenderType"="Opaque" }14         LOD 20015         16         Pass17         {18             CGPROGRAM19             #pragma vertex Vert20             #pragma fragment Frag21 22             sampler2D _Texture0;23             sampler2D _Texture1;24             sampler2D _Texture2;25             sampler2D _Texture3;26 27             struct VertexData28             {29                 float4 Pos : POSITION;30                 float4 Tangent : TANGENT;31                 float2 uv : TEXCOORD0;32             };33 34             struct V2F35             {36                 float4 Pos : SV_POSITION;37                 float4 Color : COLOR;38                 float2 uv : TEXCOORD0;39             };40 41             V2F Vert(VertexData v)42             {43                 V2F o;44                 o.Pos = mul(UNITY_MATRIX_MVP, v.Pos);45                 o.Color = v.Tangent;46                 o.uv = v.uv;47                 return o;48             }49 50             float4 Frag(V2F i) : COLOR51             {52                 float4 t0 = tex2D(_Texture0, i.uv);53                 float4 t1 = tex2D(_Texture1, i.uv);54                 float4 t2 = tex2D(_Texture2, i.uv);55                 float4 t3 = tex2D(_Texture3, i.uv);56 57                 return t0 * i.Color.x + t1 * i.Color.y + t2 * i.Color.z + t3 * i.Color.w;58             }59 60             ENDCG61         }62     } 63 }
Shader

生成的mesh与原terrain对比如下,左边为mesh,右边为terrain:

技术分享

性能对比如下:

mesh:

技术分享

terrain:

技术分享

 

转载请注明出处:

 http://www.cnblogs.com/jietian331/p/5831062.html

Unity3d之将terrain转化成mesh