How do I efficiently map a high-res SKScene in SceneKit?

730 Views Asked by At

Possibly related: Optimizing SceneKit performance with high-res textures

I am mapping a SKScene onto a board geometry to create a board game. The scene needs to be relatively large (2048x1024) so that I can zoom in on the action and still have pretty details. Now, to solve this common problem I already know about two approaches:

  • Use lower resolution textures when zooming out (i.e. mipmapping) - That's not an issue, SceneKit does it for me.
  • Tile the scene for close-ups and only display those tiles that are on screen.

Now the second point gets me thinking. How can I tile up a SKScene and map them to different locations on the geometry? Is there another way to make this work?


Screenshots

Here is the geometry: Plain geometry without texture.

This is the geometry with a static image (2048x1024) as texture: Geometry with an image texture.

This is the geometry with a SKScene (2048x1024) as texture: enter image description here

The scene does not contain any physics bodies, just about 40 SKSpriteNodes that do nothing. I need it to be able to change the colors of territories, maybe add some additional overlays etc. Would there be a way to do that with SceneKit, entirely? Maybe create a geometry for each territory?


Implemented Answers

I have now tried to achieve the same scene using SceneKit only. Each territory is a quad, using textures with pre-rendered borders included. Different blend modes help the underlaying paper texture to come forward. Unfortunately, the performance hit is roughly the same - My conclusion is that it's not SpriteKit after all that hogs resources, but the node count in combination with high-res textures (which are sadly needed to keep borders crisp if you're not using paths).

Solution using SceneKit only

3

There are 3 best solutions below

1
On

Are the SKSpriteNodes your territories? That is, one SKSpriteNode per territory? From the huge performance hit you saw when going from a static image to SKScene, it sounds like SpriteKit is what's killing you.

It would be interesting to try using SCNShape geometries, one per territory, instead of using a SpriteKit-derived texture, perhaps adding a levelOfDetail or two to each territory node. I don't see offhand how to get the same darker-toned boundary effect you're using. But you could do some interesting effects with SCNShape, for instance animating a change to the extrusion depth for a given territory.

15
On

Yes, you could do this with unique geometries for each territory, simple quads for each, and then add a material that's just like a sprite (made up of textures), with alpha, to articulate each region.

In this way you could have different textures for each state of each region (selected, tapped, greyed out, whatever you have).

The difficult part will be laying out all those quads and their textures to form your world map. You'll have to do that in a 2D or 3D design app, first, so that you can get everything just so. Then convert whatever coordinate system you use in the design app to something that works for you in SceneKit.

You can, quite probably, do this first positioning in whatever design app you created the original textures. Just make squares/rectangles like slices for all your regions, and begin writing down their coordinates and sizes.

Not fun, but it will work, and be quite efficient. I'd think.

1
On

Your frame rate is probably hit by SpriteKit. Have you enabled rasterization on the scene? Make sure no scaling is done on the nodes and follow apple’s recommendations for dealing with node counts.