您的位置:首页 > 移动开发 > Unity3D

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

2014-07-30 13:34 585 查看
  本人是个小白,但是有个做技术的理想。

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

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

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;

public class CombineMesher : MonoBehaviour
{
// Use this for initialization
void Start()
{
Combine(transform);
}

// Update is called once per frame
void Update()
{

}

public Transform Combine(Transform root)
{
float startTime = Time.realtimeSinceStartup;

// The SkinnedMeshRenderers that will make up a character will be
// combined into one SkinnedMeshRenderers using one material.
// This will speed up rendering the resulting character.
// note:each SkinnedMeshRenderer must share a same material
List<CombineInstance> combineInstances = new List<CombineInstance>();
List<Material> materials = new List<Material>();
Material material = null;
List<Transform> bones = new List<Transform>();
Transform[] transforms = root.GetComponentsInChildren<Transform>();
List<Texture2D> textures = new List<Texture2D>();
int width = 0;
int height = 0;

int uvCount = 0;

List<Vector2[]> uvList = new List<Vector2[]>();

foreach (SkinnedMeshRenderer smr in root.GetComponentsInChildren<SkinnedMeshRenderer>())
{
if (material == null)
material = Instantiate(smr.sharedMaterial) as Material;
for (int sub = 0; sub < smr.sharedMesh.subMeshCount; sub++)
{
CombineInstance ci = new CombineInstance();
ci.mesh = smr.sharedMesh;
ci.subMeshIndex = sub;
combineInstances.Add(ci);
}

uvList.Add(smr.sharedMesh.uv);
uvCount += smr.sharedMesh.uv.Length;

if (smr.material.mainTexture != null)
{
textures.Add(smr.renderer.material.mainTexture as Texture2D);
width += smr.renderer.material.mainTexture.width;
height += smr.renderer.material.mainTexture.height;
}

// we need to recollect references to the bones we are using
foreach (Transform bone in smr.bones)
{
foreach (Transform transform in transforms)
{
if (transform.name != bone.name) continue;
bones.Add(transform);
break;
}
}
Object.Destroy(smr.gameObject);
}

// Obtain and configure the SkinnedMeshRenderer attached to
// the character base.
SkinnedMeshRenderer r = root.gameObject.GetComponent<SkinnedMeshRenderer>();
if (!r)
r = root.gameObject.AddComponent<SkinnedMeshRenderer>();

r.sharedMesh = new Mesh();

//only set mergeSubMeshes true will combine meshs into single submesh
r.sharedMesh.CombineMeshes(combineInstances.ToArray(), true, false);
r.bones = bones.ToArray();
r.material = material;

Texture2D skinnedMeshAtlas = new Texture2D(1024, 512);
Rect[] packingResult = skinnedMeshAtlas.PackTextures(textures.ToArray(), 0);
Vector2[] atlasUVs = new Vector2[uvCount];

//as combine textures into single texture,so need recalculate uvs

int j = 0;
for (int i = 0; i < uvList.Count; i++)
{
foreach (Vector2 uv in uvList[i])
{
atlasUVs[j].x = Mathf.Lerp(packingResult[i].xMin, packingResult[i].xMax, uv.x);
atlasUVs[j].y = Mathf.Lerp(packingResult[i].yMin, packingResult[i].yMax, uv.y);
j++;
}
}

r.material.mainTexture = skinnedMeshAtlas;
r.sharedMesh.uv = atlasUVs;

Debug.Log("combine meshes takes : " + (Time.realtimeSinceStartup - startTime) * 1000 + " ms");
return root;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: