首页 > 代码库 > 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 }
渲染地形的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 }
生成的mesh与原terrain对比如下,左边为mesh,右边为terrain:
性能对比如下:
mesh:
terrain:
转载请注明出处:
http://www.cnblogs.com/jietian331/p/5831062.html
Unity3d之将terrain转化成mesh
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。