We have a reasonably complex mesh and need to update the vertex positions for every frame using custom code running on the CPU.
It seems like SceneKit is not really set up to make this easy, as the SCNGeometry is immutable.
What is the easiest (yet performant) way to achieve this?
So far I can see two possible approaches:
1) Create a new SCNGeometry for every frame. I suspect that this will be prohibitively expensive, but maybe not?
2) It seems that SCNProgram and its handleBinding... method would allow updating the vertex positions. But does using SCNProgram mean that we have to write all our own shaders from scratch? Or can we still use the default Scenekit vertex and fragment shaders even when using SCNProgram?
Just in case somebody else with the same problem finds this post:
The solution I found was to use a SCNGeometrySource wrapping a custom MTLBuffer.
We then use another MTLBuffer (actually multiple in a ring-buffer scheme) that we write to from our CPU code. Once the CPU has finished writing the vertex positions, the next time renderer(_:willRenderScene:atTime:) comes around, we queue up a blit shader that copies from this MTLBuffer into the MTLBuffer used by the SCNGeometrySource.
I also wrote a two stage compute shader for computing the vertex normals based on the updated vertex positions. These vertex normals are also written to a MTLBuffer that is wrapped in a SCNGeometrySource.
This scheme works beautifully and seems to have very low overhead in terms of both CPU and GPU load.