Mesh绘制调用过多咨询:3种材质却产生28次Draw Call
嘿,这个问题我之前帮不少开发者排查过,明明只有3种材质却跑出28次Draw Call,大概率是这些细节没注意到:
网格被拆成了多个子网格:Blender里的单个Mesh对象,可能因为编辑时的分离操作、不同顶点组/UV集的存在,导出后被拆成了多个独立子网格。three.js里哪怕子网格用的是同一种材质,只要是独立的网格实例,就会单独触发Draw Call。你可以在three.js里打印
mesh.children或者检查mesh.geometry的结构,看看是不是被拆分了。材质存在隐藏的细微差异:你以为是3种材质,但实际导出后可能有些材质参数不一样——比如有的是双面渲染(
side: THREE.DoubleSide)有的是单面,或者透明设置、节点树里的细微区别。three.js对材质的判断是严格的,任何参数不同都会被视为不同材质,各自触发Draw Call。建议逐个对比每个子网格的材质属性,找出那些看似相同实则不同的地方。导出器的拆分选项默认开启:你用的three.js导出器可能默认开启了按UV层、顶点颜色等属性拆分网格的选项。打开Blender的导出设置,看看有没有类似“Split by UV Maps”“Split by Vertex Colors”的选项,把这些不必要的拆分关掉再重新导出。
渲染状态不一致导致的拆分:如果同材质的网格之间有不同的渲染状态(比如
renderOrder不同、阴影接收/投射设置不一样),three.js也会分开绘制。检查一下这些子网格的渲染相关属性,尽量统一相同材质网格的设置。没启用材质合并优化:three.js不会自动合并同材质的网格,你需要手动用
BufferGeometryUtils.mergeBufferGeometries()来合并共享同一材质的子网格,这样就能把多个Draw Call合并成一个。不过合并前要确认这些网格不需要单独做动画或交互哦。
内容的提问来源于stack exchange,提问作者user9731024

