在 SceneKit 中,如何在不同大小的对象上平铺纹理,同时保持最小的绘制调用?

Posted

技术标签:

【中文标题】在 SceneKit 中,如何在不同大小的对象上平铺纹理,同时保持最小的绘制调用?【英文标题】:In SceneKit, how can one tile a texture on differently sized objects while keeping draw calls minimal? 【发布时间】:2021-01-23 16:42:00 【问题描述】:

为了提高 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)

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

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

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

【问题讨论】:

【参考方案1】:

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

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

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

【讨论】:

嗨@mnuages,也想试试这个其他的SceneKit 问题吗? ***.com/questions/59670506/… 我悬赏了。 :-)

以上是关于在 SceneKit 中,如何在不同大小的对象上平铺纹理,同时保持最小的绘制调用?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Xcode 10 在 SceneKit 编辑器中旋转对象

如何在 iOS SceneKit 中使用具有不同场景图形的 DAE 文件

如何访问从 Firebase 下载的 SceneKit 文件?

SceneKit 移动相机

SceneKit:如何控制导入资产的大小,一个 DAE 文件创建巨大的 SCNNode 而另一个是“正常”

Scenekit:动画时模型改变大小