10
votes

So, I am using SceneKit to render a collection of parametric surfaces (the sum of which make an object). To put these on screen I am creating custom geometries by sampling the points and creating triangles. Here is a quick over view of how I do it.

Loop through the collection of surfaces
    Generate a random color C
    For each surface calculate a grid of N x N points (both positions and normals)
    Assign all vertexes for that surface the color C
    Add groups of 3 vertexes from this surface to the face index list

And that seems to work. After I get all this data, I make it into the proper structures (SCNGeometrySource and SCNGeometryElement) and make a SCNGeometry like so

SCNGeometry(sources: [vertexSource, normalSource, colorSource], elements: [element])

This works and displays my surfaces on the screen fine as one single geometry element. My problem is, I have some really complicated objects that I am trying to work with and it is just running really slow to move the camera around when looking at the object. Rendering is taking around 500 ms. Which is making my frame rate and experience awful.

So the question is, what steps can I take to speed up SceneKit performance? I did this same project with WebGL using Three.js with the same amount of data and was able to use an orbiting camera fine, so I can't believe that scene kit couldn't at least compete with that. What features can I tweak and turn off to speed up performance? I am using the triangle primitive type, the allowsCameraControl = true for the orbiting camera, and metal for the SCNView.

For those curious, the model I am struggling on generated 231,900 vertices and 347,850 indices for faces (11.1312 MB of vertex data (position and normal) and 1.3914 MB of face data (essentially just index positions of vertexes in order for triangles.))

1
On an iPad 3 or earlier, this is getting near the vertices limits. Add to this however much fill rate you're using up and you're likely going to be struggling to get at 60fps, but shouldn't be far off. 500ms is truly abnormal.Confused
My old 4s used to handle those kind of numbers at 20fps or so. Your pseudo code seems fine, that's how I generate my geometry. At various times I'd get the indexes messed up resulting in a faceted mess on screen. This would really hit the framerate, I put it down to the fragment shader having to do a lot more work. I'd double check the mesh, maybe make it semi transparent and turn on wireframe svnView.debugOptions = .ShowWireframe.lock
How do I manually change the fill rate?Red
You could completely "disable" filtrate by applying a totally transparent material, that way you could isolate the cost of geometry from material rendering. Or even a "null" material could result in this. I'm not entirely sure... but there should be a way to test geometry performance without any texture/skin/material.Confused

1 Answers

3
votes

1) If you are "standing" on center of your generated surface, then your problem maybe that you drawing alot offscreen (no frustum culling) and you need to split your sufrface (single node) into subsurfaces (child nodes), so only nodes that is visible in camera view space is drawn.

That being said, 231,900 vertices is really not much, I draw several milions @60fps with SceneKit Metal renderer (+20% faster than using OpenGL renderer) on OSX.

2) If you are looking on your surfaces from distance and have bad performance, check what ammount of bytesPerComponent: you feeding when creating SCNGeometrySource. I experienced big performance drop when using CGFloat (double) instead of plain float on GeForce GTX (while okay on integrated Intel graphics).