3

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

Double M
  • 1,449
  • 1
  • 12
  • 29

3 Answers3

3

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.

Hal Mueller
  • 7,019
  • 2
  • 24
  • 42
  • Correct, one sprite per territory, plus an "old paper" sprite on top with blend mode `SKBlendMode.multiply`. Thank you for the `SCNShape` hint, I think this would be the best way to go if `SpriteKit` is not an option. Deriving the paths will be difficult, though. I might as well generate static images from the `SKScene` without ever presenting it, update the texture upon change, and use `SceneKit` for any animations. I will keep your alternative in mind, thanks! – Double M Jan 16 '17 at 08:49
1

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.

Confused
  • 6,048
  • 6
  • 34
  • 75
  • Do you have any thoughts on how to make the pretty deeper toned stroking of the borders? – Hal Mueller Jan 16 '17 at 08:59
  • That's an interesting idea. Positioning wouldn't even be as difficult as you think, thanks to Xcode's Scene Editor. It's the layering that worries me here. If I had multiple geometries like you suggest, and placed them slightly above each other like the layers in `SpriteKit`, could I achieve the same effect using different `SCNBlendModes`? – Double M Jan 16 '17 at 09:00
  • 1
    @Hal Mueller Since the geometries are merely quads with textures, the border gradient could be part of the texture. – Double M Jan 16 '17 at 09:04
  • @DoubleM Yes, SCNBlendModes are actually more powerful and better than the ones in SpriteKit. Probably more performant, too ;) – Confused Jan 16 '17 at 09:05
  • @HalMueller the border could be another quad, with a another texture that ONLY contains the border, that's placed slightly higher in the (let's call it zPosition) space of quads, and then multiplied (blend mode) with the underlying texture. Or, if SceneKit ever gets the ability to have multiple textures on the same quad/surface, then use this. I imagine decals will be in the next update. Or hope so, at least. – Confused Jan 16 '17 at 09:07
  • Or could use @DoubleM's suggestion, and just swap out textures for ones with borders rendered into them already. – Confused Jan 16 '17 at 09:08
  • @DoubleM if you've got the patience to work with the SceneKit Scene Editor, all power to you!!! – Confused Jan 16 '17 at 09:09
  • Perhaps the biggest advantage of @HalMueller approach is that touch/hit detection is super simple because of the unique geometries for each region never overlapping anywhere. With the quads, there's going to be overlaps at various points, at which point you'll need to find which has material/texture in that position with some other form of hit detection. – Confused Jan 16 '17 at 09:11
  • I wonder...use a fine texture for one material channel, maybe diffuse. And a coarse texture (to draw the borders) in another channel. Or maybe do a fine rendering of the texture, with borders, and use that as the material? I think I just nerdsniped myself :-/ – Hal Mueller Jan 16 '17 at 09:24
  • 1
    3DMaterialSnipped yourself, definitely ;) @HalMueller – Confused Jan 16 '17 at 09:25
  • I've tried the above approach - see my updated question. Worth a shot! – Double M Jan 16 '17 at 11:03
  • @DoubleM how big are your textures? How many of them are there? – Confused Jan 16 '17 at 11:56
  • In the `SceneKit` example there are five textured sprites, one for the outer border gradients (2899 × 1934), one for the outer borders (2883 × 1913), one for the inner borders (2498 × 1803), one for the paper background (3150 × 2033) and finally the shape of Great Britain (446 × 538) including border gradients. If I reduce the resolution, the border will look washed out when I zoom in as close as shown in the 4th screenshot. I admit, using paths would be way smarter but also lots of work. – Double M Jan 16 '17 at 13:59
  • argh. Ok. @DoubleM, there's a LOT of optimisation and LOD stuff built into SceneKit and stuff that you can do yourself with little difficulty, that means you only have one big texture open at any one time, for those things that are close to the camera. I think Mr Mueller can describe the features in SceneKit for this better than I can. My specialty is general ideas on optimisation of textures from a long history of making 3D on many platforms, so they're kind of custom tips. Ask a new question about texture optimisation so HalMueller can answer that, and I'll chip in with generalisation tips. – Confused Jan 16 '17 at 14:24
  • @HalMueller thanks for both your awesome ideas and support, I've been meaning to try a few more things and report my progress to you, sadly I no longer have the time to play around with this project. For what it's worth, I've learned a lot and it has been super fun working with you both. Thanks again. – Double M Jun 28 '17 at 14:16
0

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.

FrostyL
  • 811
  • 6
  • 9
  • Thanks for the hint, but I no longer pursue this project :) I'll keep your recommendations in mind though for future work. – Double M Nov 28 '19 at 14:34