[Unity] GPU动画实现(三)——材质合并

实现合批的必要条件是只有一个material,因此将多texture对象合并成一张texture是必要的。无论是SkinnedMeshRenderer或是MeshRenderer,其合并材质的原理都是一样的。

其调用到的核心API是Texture2D.PackTextures 

            // 合并贴图(从收集的各Material中取)
            List<Texture2D> MainTexs = new List<Texture2D>();
            for (int i = 0; i < materials.Count; i++)
            {
                MainTexs.Add(materials[i].GetTexture("_MainTex") as Texture2D);
            }

            //所有贴图合并到newDiffuseTex这张大贴图上
            newMainTex = new Texture2D(COMBINE_TEXTURE_MAX, COMBINE_TEXTURE_MAX, TextureFormat.RGBA32, true);

            Rect[] uvs = newMainTex.PackTextures(MainTexs.ToArray(), 0);

            newMaterial.SetTexture("_MainTex", newMainTex);
            AssetDatabase.CreateAsset(newMainTex, $"Assets/Resources/CombineTexture.asset");

这里先获取到每个material里用到的材质(手动合并可以自己声明一个texture2d数组,之后在editor模式下拖拽),之后直接声明一张1024*1024的texture,我用到的子tex为512*512,因此1024*1024对我已经足够,可视实际情况进行调整。

调用Texture2D.PackTextures接口生成合并贴图,返回合并后的uv,这里的uv对应的是子texture在合并后的大texture的uv,而不是传统意义上片元的uv。

之后将新的材质直接赋值到新的material,也可以调用AssetDatabase.CreateAsset接口,将合并后的材质保存下来。

PS:这里有个问题是执行:newMaterial.SetTexture("_MainTex", newMainTex)后,理论上新的材质应该是合并后的材质,但实际上材质仍然是合并前的子材质,而调用AssetDatabase.CreateAsset创建出来的材质是正常的,在editor模式下拖拽赋值后,才表现正常。目前作者暂不清楚原因,如果有人知道原因务必在评论区告知我,非常感谢。

            // reset uv
            // 计算好uvb赋值到到combineInstances[j].mesh.uv
            oldUV = new List<Vector2[]>();
            Vector2[] uva, uvb;
            for (int j = 0; j < combineInstances.Count; j++)
            {
                //uva = (Vector2[])(combineInstances[j].mesh.uv);
                uva = combineInstances[j].mesh.uv;
                uvb = new Vector2[uva.Length];
                for (int k = 0; k < uva.Length; k++)
                {
                    uvb[k] = new Vector2((uva[k].x * uvs[j].width) + uvs[j].x, (uva[k].y * uvs[j].height) + uvs[j].y);
                }
                //oldUV.Add(combineInstances[j].mesh.uv);
                oldUV.Add(uva);
                combineInstances[j].mesh.uv = uvb;
            }

在合并完材质之后,还需要对uv进行处理,根据合并的偏移对每个uv加上对应的偏移值即可,这里不赘述,只得一提的是,这里还需要保存旧的uv,在合并网格之后,将旧的uv重新赋值回去,以免影响到其他使用到同一个Mesh的对象。

            //重新赋值,以免影响其他对象的Mesh
            for (int i = 0; i < combineInstances.Count; i++)
            {
                combineInstances[i].mesh.uv = oldUV[i];
            }

合并网格依旧是调用Mesh.CombineMeshes ,不同的是,第二个参数我们设置为true,因为我们已经将其合并成一个材质,因此不再需要多material。

render.sharedMesh.CombineMeshes(combineInstances.ToArray(), true, false);

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值