SceneKit Cocoa 添加贴花
SceneKit Cocoa Adding decals
是否有足够的方法向 SCNNode
添加贴花(纹理)?
现在我所能做的就是用 SCNPlane
几何图形创建新的 SCNNode
为其漫反射内容分配纹理并将其添加到场景中......
这种方法效率很低。
我想添加一个不会成为场景一部分的贴花 - 以提高游戏的性能。
因为我想在地板节点上有比较多的贴花。
也许有点类似于粒子内部的工作原理?
或者其他一些快速图像绘制方法。
我已经尝试过@rickster 的建议 1
Use SKEffectNode as a buffer in the SpriteKit scene — throw splatters
into an effect node until it gets to a certain number of children,
then turn on its shouldRasterize option so that it doesn't re-render
its children anymore (and start using a new effect node for more
splatters).
在同一个 SceneKit showreel 项目中 - 仅此一项就已经给出了很好的结果,FPS 在继续播放场景后 5 分钟内没有下降,这很好。
期待实施建议 #2
- 我相信它会减少 2D 场景渲染时间(现在相当长)。
在此屏幕截图中有 5k 个贴花
我建议使用 SpriteKit 场景作为您的 "splattered-on" 几何体的 material。 Apple 有 sample code 说明了很多你在这里想要的东西:
- 制作一个 SpriteKit 场景,它是 SceneKit 几何体的 material。
- 当 3D 世界中的某些东西需要飞溅时,使用命中测试在 material 中查找纹理坐标并将其转换为 SpriteKit 场景坐标。
- 在 SpriteKit 场景中的该位置放置一个精灵以创建贴花。
从你的 other question 来看,你似乎已经开始朝着这个方向前进了......如果你能详细说明问题,也许你会得到更好的帮助?
注意:该示例代码在 iOS 9 / macOS 10.11 及更高版本上存在错误,会干扰飞溅效果。您可以通过在 AAPLGameViewController.m
:
中找到这一行来解决它
ball.physicsBody.collisionBitMask = ~(0x4);
并在其后添加这一行:
ball.physicsBody.contactTestBitMask = ~(0x4);
您可能会在该演示中注意到,一段时间后,您的帧速率开始下降 — SpriteKit 场景中精灵数量的不断增加使得 2D 渲染占用了越来越多的渲染循环。
尽管无法 "screenshot" 纹理,但有一些方法可以针对这种情况进行优化。调查的一些想法:
在 SpriteKit 场景中使用 SKEffectNode
作为缓冲区——将 splatters 扔到效果节点中,直到它达到一定数量的 children,然后打开它的 shouldRasterize
选项,这样它就不再 re-render 它的 children (并开始使用新的效果节点来获得更多的飞溅效果)。
很多 2D 时间都浪费在绘制不可见的 SK 精灵上,因为它们被其他精灵掩埋了。 (或者大部分被掩埋,只有几个像素可见。)因为你的,嗯,"paint" 都是相同的颜色,你可以使用一些简单的方法将你的 SpriteKit 场景分块成区域并决定什么时候一个区域已完全覆盖 — 到那时,您可以从该区域移除所有精灵,用一个 "total coverage" 精灵替换它们,并停止在该区域添加新精灵。 quadtree 可能是在这里使用的好工具。
如果您想通过着色器修改器而不是 SpriteKit-based material 进行自定义绘图,那么 SceneKit hit-test 到纹理坐标映射技巧同样有效,您可能会在那里找到更有效的 long-term 覆盖率跟踪方法(可能会借助 #3 中的一些技巧)。
如果您的飞溅不是经常发生,您可以在 CPU 上渲染它们,然后在 material 上设置一个新图像。
一个想法的远景,不知道它是否可行或性能良好:使用 Core Image as an accumulation buffer 绘制飞溅,并将其渲染成相同的 MTLTexture
material 的内容设置为。 (使用 SceneKit 的 willRenderScene
回调每帧渲染一次。)
是否有足够的方法向 SCNNode
添加贴花(纹理)?
现在我所能做的就是用 SCNPlane
几何图形创建新的 SCNNode
为其漫反射内容分配纹理并将其添加到场景中......
这种方法效率很低。
我想添加一个不会成为场景一部分的贴花 - 以提高游戏的性能。 因为我想在地板节点上有比较多的贴花。
也许有点类似于粒子内部的工作原理? 或者其他一些快速图像绘制方法。
我已经尝试过@rickster 的建议 1
Use SKEffectNode as a buffer in the SpriteKit scene — throw splatters into an effect node until it gets to a certain number of children, then turn on its shouldRasterize option so that it doesn't re-render its children anymore (and start using a new effect node for more splatters).
在同一个 SceneKit showreel 项目中 - 仅此一项就已经给出了很好的结果,FPS 在继续播放场景后 5 分钟内没有下降,这很好。
期待实施建议 #2 - 我相信它会减少 2D 场景渲染时间(现在相当长)。
在此屏幕截图中有 5k 个贴花
我建议使用 SpriteKit 场景作为您的 "splattered-on" 几何体的 material。 Apple 有 sample code 说明了很多你在这里想要的东西:
- 制作一个 SpriteKit 场景,它是 SceneKit 几何体的 material。
- 当 3D 世界中的某些东西需要飞溅时,使用命中测试在 material 中查找纹理坐标并将其转换为 SpriteKit 场景坐标。
- 在 SpriteKit 场景中的该位置放置一个精灵以创建贴花。
从你的 other question 来看,你似乎已经开始朝着这个方向前进了......如果你能详细说明问题,也许你会得到更好的帮助?
注意:该示例代码在 iOS 9 / macOS 10.11 及更高版本上存在错误,会干扰飞溅效果。您可以通过在 AAPLGameViewController.m
:
ball.physicsBody.collisionBitMask = ~(0x4);
并在其后添加这一行:
ball.physicsBody.contactTestBitMask = ~(0x4);
您可能会在该演示中注意到,一段时间后,您的帧速率开始下降 — SpriteKit 场景中精灵数量的不断增加使得 2D 渲染占用了越来越多的渲染循环。
尽管无法 "screenshot" 纹理,但有一些方法可以针对这种情况进行优化。调查的一些想法:
在 SpriteKit 场景中使用
SKEffectNode
作为缓冲区——将 splatters 扔到效果节点中,直到它达到一定数量的 children,然后打开它的shouldRasterize
选项,这样它就不再 re-render 它的 children (并开始使用新的效果节点来获得更多的飞溅效果)。很多 2D 时间都浪费在绘制不可见的 SK 精灵上,因为它们被其他精灵掩埋了。 (或者大部分被掩埋,只有几个像素可见。)因为你的,嗯,"paint" 都是相同的颜色,你可以使用一些简单的方法将你的 SpriteKit 场景分块成区域并决定什么时候一个区域已完全覆盖 — 到那时,您可以从该区域移除所有精灵,用一个 "total coverage" 精灵替换它们,并停止在该区域添加新精灵。 quadtree 可能是在这里使用的好工具。
如果您想通过着色器修改器而不是 SpriteKit-based material 进行自定义绘图,那么 SceneKit hit-test 到纹理坐标映射技巧同样有效,您可能会在那里找到更有效的 long-term 覆盖率跟踪方法(可能会借助 #3 中的一些技巧)。
如果您的飞溅不是经常发生,您可以在 CPU 上渲染它们,然后在 material 上设置一个新图像。
一个想法的远景,不知道它是否可行或性能良好:使用 Core Image as an accumulation buffer 绘制飞溅,并将其渲染成相同的
MTLTexture
material 的内容设置为。 (使用 SceneKit 的willRenderScene
回调每帧渲染一次。)