首页 > 解决方案 > 在 SceneKit 中,如何在不同大小的对象上平铺纹理,同时保持最小的绘制调用?

问题描述

为了提高 SceneKit 场景中的性能/fps,我想尽量减少绘制调用的数量。该场景包含一个程序生成的城市,我为它生成随机高度的房屋(每个都是一个 SCNBox),并用一个相同的重复立面纹理平铺它们,如下所示:

在此处输入图像描述

应用纹理的正确方法如下所示:

let material = SCNMaterial()
material.diffuse.contents = image
material.diffuse.wrapS = SCNWrapMode.repeat
material.diffuse.wrapT = SCNWrapMode.repeat
buildingGeometry.firstMaterial = material

这行得通。但正如所写,它会拉伸材料以适应盒子表面的大小。要调整纹理大小以保持纵横比,需要添加以下代码:

material.diffuse.contentsTransform = SCNMatrix4MakeScale(sx, sy, sz)

其中sx,sysz是从几何中的面大小得出的适当比例因子。这也有效。

但后一种方法意味着每个节点都需要自定义材质,这反过来意味着我不能为所有房屋重复使用单一材质,这反过来意味着每个节点都需要额外的绘制调用。

有没有办法使用单一纹理材料来平铺所有房屋(不拉伸纹理)?

标签: macosperformance3dtexturesscenekit

解决方案


使用表面着色器修改器 ( SCNShaderModifierEntryPointSurface),您可以_surface.diffuseTexcoord根据scn_node.boundingBox.

由于边界框是动态馈送到着色器的,所有对象都将使用相同的着色器,并将受益于实例化(减少绘制调用的数量)。

SCNShadable.h 头文件对此有更多详细信息。


推荐阅读