unity 3d 之合并网格和贴图(combine mesh and texture) unity 3d 之合并网格和贴图(combine mesh and texture)

https://www.cnblogs.com/eangulee/p/3877824.html

 

unity 3d 之合并网格和贴图(combine mesh and texture)

 

  本人是个小白,但是有个做技术的理想。

  关于合并网格和贴图这个问题困扰了我好久,问群友,逛论坛,翻帖子,或者说是我的愚笨吧,不过经过努力还是我解决了,测试通过,一个8drawcall的模型,合并后降到2drawcall,当然现在移动设备的性能都比较高了,不必过多纠结于drawcall,如果没这需要请路过吧。。。

  好的,废话不多说,我把代码贴出来。

复制代码
  1 using UnityEngine;
  2 using System.Collections;
  3 using System.Collections.Generic;
  4 using System.IO;
  5 
  6 public class CombineMesher : MonoBehaviour
  7 {
  8     // Use this for initialization
  9     void Start()
 10     {
 11         Combine(transform);
 12     }
 13 
 14     // Update is called once per frame
 15     void Update()
 16     {
 17 
 18     }
 19 
 20 
 21     public Transform Combine(Transform root)
 22     {
 23         float startTime = Time.realtimeSinceStartup;
 24 
 25         // The SkinnedMeshRenderers that will make up a character will be
 26         // combined into one SkinnedMeshRenderers using one material.
 27         // This will speed up rendering the resulting character.
 28         // note:each SkinnedMeshRenderer must share a same material
 29         List<CombineInstance> combineInstances = new List<CombineInstance>();
 30         List<Material> materials = new List<Material>();
 31         Material material = null;
 32         List<Transform> bones = new List<Transform>();
 33         Transform[] transforms = root.GetComponentsInChildren<Transform>();
 34         List<Texture2D> textures = new List<Texture2D>();
 35         int width = 0;
 36         int height = 0;
 37 
 38         int uvCount = 0;
 39 
 40         List<Vector2[]> uvList = new List<Vector2[]>();
 41 
 42         foreach (SkinnedMeshRenderer smr in root.GetComponentsInChildren<SkinnedMeshRenderer>())
 43         {
 44             if (material == null)
 45                 material = Instantiate(smr.sharedMaterial) as Material;
 46             for (int sub = 0; sub < smr.sharedMesh.subMeshCount; sub++)
 47             {
 48                 CombineInstance ci = new CombineInstance();
 49                 ci.mesh = smr.sharedMesh;
 50                 ci.subMeshIndex = sub;
 51                 combineInstances.Add(ci);
 52             }
 53 
 54             uvList.Add(smr.sharedMesh.uv);
 55             uvCount += smr.sharedMesh.uv.Length;
 56 
 57             if (smr.material.mainTexture != null)
 58             {
 59                 textures.Add(smr.renderer.material.mainTexture as Texture2D);
 60                 width += smr.renderer.material.mainTexture.width;
 61                 height += smr.renderer.material.mainTexture.height;
 62             }
 63 
 64             // we need to recollect references to the bones we are using
 65             foreach (Transform bone in smr.bones)
 66             {
 67                 foreach (Transform transform in transforms)
 68                 {
 69                     if (transform.name != bone.name) continue;
 70                     bones.Add(transform);
 71                     break;
 72                 }
 73             }
 74             Object.Destroy(smr.gameObject);
 75         }
 76 
 77         // Obtain and configure the SkinnedMeshRenderer attached to
 78         // the character base.
 79         SkinnedMeshRenderer r = root.gameObject.GetComponent<SkinnedMeshRenderer>();
 80         if (!r)
 81             r = root.gameObject.AddComponent<SkinnedMeshRenderer>();
 82         
 83         r.sharedMesh = new Mesh();
 84 
 85         //only set mergeSubMeshes true will combine meshs into single submesh
 86         r.sharedMesh.CombineMeshes(combineInstances.ToArray(), true, false);
 87         r.bones = bones.ToArray();
 88         r.material = material;
 89 
 90         Texture2D skinnedMeshAtlas = new Texture2D(1024, 512);
 91         Rect[] packingResult = skinnedMeshAtlas.PackTextures(textures.ToArray(), 0);
 92         Vector2[] atlasUVs = new Vector2[uvCount];
 93 
 94         //as combine textures into single texture,so need recalculate uvs
 95 
 96         int j = 0;        
 97         for (int i = 0; i < uvList.Count; i++)
 98         {
 99             foreach (Vector2 uv in uvList[i])
100             {
101                 atlasUVs[j].x = Mathf.Lerp(packingResult[i].xMin, packingResult[i].xMax, uv.x);
102                 atlasUVs[j].y = Mathf.Lerp(packingResult[i].yMin, packingResult[i].yMax, uv.y);
103                 j++;
104             }
105         }
106         
107         r.material.mainTexture = skinnedMeshAtlas;
108         r.sharedMesh.uv = atlasUVs;
109 
110         Debug.Log("combine meshes takes : " + (Time.realtimeSinceStartup - startTime) * 1000 + " ms");
111         return root;
112     }
113 }
复制代码

  本人是个小白,但是有个做技术的理想。

  关于合并网格和贴图这个问题困扰了我好久,问群友,逛论坛,翻帖子,或者说是我的愚笨吧,不过经过努力还是我解决了,测试通过,一个8drawcall的模型,合并后降到2drawcall,当然现在移动设备的性能都比较高了,不必过多纠结于drawcall,如果没这需要请路过吧。。。

  好的,废话不多说,我把代码贴出来。

复制代码
  1 using UnityEngine;
  2 using System.Collections;
  3 using System.Collections.Generic;
  4 using System.IO;
  5 
  6 public class CombineMesher : MonoBehaviour
  7 {
  8     // Use this for initialization
  9     void Start()
 10     {
 11         Combine(transform);
 12     }
 13 
 14     // Update is called once per frame
 15     void Update()
 16     {
 17 
 18     }
 19 
 20 
 21     public Transform Combine(Transform root)
 22     {
 23         float startTime = Time.realtimeSinceStartup;
 24 
 25         // The SkinnedMeshRenderers that will make up a character will be
 26         // combined into one SkinnedMeshRenderers using one material.
 27         // This will speed up rendering the resulting character.
 28         // note:each SkinnedMeshRenderer must share a same material
 29         List<CombineInstance> combineInstances = new List<CombineInstance>();
 30         List<Material> materials = new List<Material>();
 31         Material material = null;
 32         List<Transform> bones = new List<Transform>();
 33         Transform[] transforms = root.GetComponentsInChildren<Transform>();
 34         List<Texture2D> textures = new List<Texture2D>();
 35         int width = 0;
 36         int height = 0;
 37 
 38         int uvCount = 0;
 39 
 40         List<Vector2[]> uvList = new List<Vector2[]>();
 41 
 42         foreach (SkinnedMeshRenderer smr in root.GetComponentsInChildren<SkinnedMeshRenderer>())
 43         {
 44             if (material == null)
 45                 material = Instantiate(smr.sharedMaterial) as Material;
 46             for (int sub = 0; sub < smr.sharedMesh.subMeshCount; sub++)
 47             {
 48                 CombineInstance ci = new CombineInstance();
 49                 ci.mesh = smr.sharedMesh;
 50                 ci.subMeshIndex = sub;
 51                 combineInstances.Add(ci);
 52             }
 53 
 54             uvList.Add(smr.sharedMesh.uv);
 55             uvCount += smr.sharedMesh.uv.Length;
 56 
 57             if (smr.material.mainTexture != null)
 58             {
 59                 textures.Add(smr.renderer.material.mainTexture as Texture2D);
 60                 width += smr.renderer.material.mainTexture.width;
 61                 height += smr.renderer.material.mainTexture.height;
 62             }
 63 
 64             // we need to recollect references to the bones we are using
 65             foreach (Transform bone in smr.bones)
 66             {
 67                 foreach (Transform transform in transforms)
 68                 {
 69                     if (transform.name != bone.name) continue;
 70                     bones.Add(transform);
 71                     break;
 72                 }
 73             }
 74             Object.Destroy(smr.gameObject);
 75         }
 76 
 77         // Obtain and configure the SkinnedMeshRenderer attached to
 78         // the character base.
 79         SkinnedMeshRenderer r = root.gameObject.GetComponent<SkinnedMeshRenderer>();
 80         if (!r)
 81             r = root.gameObject.AddComponent<SkinnedMeshRenderer>();
 82         
 83         r.sharedMesh = new Mesh();
 84 
 85         //only set mergeSubMeshes true will combine meshs into single submesh
 86         r.sharedMesh.CombineMeshes(combineInstances.ToArray(), true, false);
 87         r.bones = bones.ToArray();
 88         r.material = material;
 89 
 90         Texture2D skinnedMeshAtlas = new Texture2D(1024, 512);
 91         Rect[] packingResult = skinnedMeshAtlas.PackTextures(textures.ToArray(), 0);
 92         Vector2[] atlasUVs = new Vector2[uvCount];
 93 
 94         //as combine textures into single texture,so need recalculate uvs
 95 
 96         int j = 0;        
 97         for (int i = 0; i < uvList.Count; i++)
 98         {
 99             foreach (Vector2 uv in uvList[i])
100             {
101                 atlasUVs[j].x = Mathf.Lerp(packingResult[i].xMin, packingResult[i].xMax, uv.x);
102                 atlasUVs[j].y = Mathf.Lerp(packingResult[i].yMin, packingResult[i].yMax, uv.y);
103                 j++;
104             }
105         }
106         
107         r.material.mainTexture = skinnedMeshAtlas;
108         r.sharedMesh.uv = atlasUVs;
109 
110         Debug.Log("combine meshes takes : " + (Time.realtimeSinceStartup - startTime) * 1000 + " ms");
111         return root;
112     }
113 }
复制代码

猜你喜欢

转载自www.cnblogs.com/nafio/p/9221650.html