Fixing and 99% improvement in voxel replay

Catch-up: For campaign mode, SnwScf needs bigger arenas/levels.  This means (1) much wider voxel snow coverage (e.g. across mountains) which mandates LOD levels (level of detail) and (2) removing/replacing snow as the player(s) move.  All in all, lots of optimizations, etc.  Some of the funnest work 😀

This one’s all about fixing then optimizing the replay of actions (dig, build, etc).  This is used when voxels are (a) tidied due to being further away than we wish to keep or (b) when we switch their LOD levels = a lot more common!

At the start, it didn’t work.  This was mostly due to other work I’d done on the codebase while not worrying about this functionality since I hadn’t been using it.  With small arenas I never let the snow be tidied — I just kept it all!  Obviously this meant larger load on CPU, Memory and GPU!  In past posts (12 & 3) I talked about improving with LOD, etc.  Now the voxels can be swapped-out to lower LOD levels so we definitely need it!

Here’s out test patch of snow.  To keep things consistent, I saved the snow so I can reload it every time.  This is a slight over-complication — it actually stores all of the generation settings and simply loads them then does generation and gets the same result every time!



Here are the numbers:

Total time (ms) Percentage improvement Num replay calls Num DoOperation() calls Comments
(didn’t work) Original (didn’t work)
4552 0% 486 31104 Original (fixed)
752 -83% 78 4992 (1) Switched to Chunk-per-call (rather than whole height each time)
(not-timed) 6 4144 (2) Optimized what was considered actually modifying a ChunkData.
53 -99% 6 1120 (3) Bounded start & end bounds by original sizes
8 Blocks to a side in a Chunk
8 Height of this operation (Chunks)
-3 MinY
1 MaxY
4 World height (Chunks)

And some comments on what I did:

  1. The original code found all ActionData instances that had affected a Chunk then re-ran it for every column… but it didn’t bound the height of the column so it was affecting each Chunk as many times as the number of vertical Chunks it had affected!! (e.g. ActionData touched 3 Chunks high, all 3 Chunks would be done 3 times!?)  This seems a bug in the original code.
  2. The original ActionData code considered a Chunk touched if it was within certain bounds even if it didn’t change the isovalue.  This might have been for painting?  Even that guess is a bit of a stretch — I can’t really see any reason for it so I ‘fixed’ it.  I don’t use it anyway so meh.  It’s easy enough to revert if I offer these changes back to the die-hard users of TerraVol (if there are any).
  3. So previously we’d operated on *every* Block within the Chunk.  For the edge ones, that was superfluous.  Instead, I bounded the Blocks affected by the original size affected.  Great improvement — albeit most useful on edge Chunks which this test-case has lots of.  A larger operation will be more inner ones but I have ideas for that!
    (care to guess along at home … or write in on a stamped self-addressed envelope 😉 )

Here are a couple of pictures of the operation.  The white boxes are Chunk boundaries and the purple boxes are the reduced bounds that are now operated upon 🙂  If you’re wondering why the purple boxes extend outside the green capsule, it’s because the isovalues are smoothed over that range from no-effect to full-effect to produce a smooth result at about the threshold where the green capsule is drawn.



53ms is actually still a long time and needs reducing / parallelizing but it’s a lot better.  To give you an idea — this is a tiny operation.  Most are much larger.  This one’s equivalent to rolling a small snowman 1 meter.  A carrocket hit at smallest level would be about 100 times larger.

Now this is all done off the main thread so it’s not so bad however it’s all done on a Generation thread (which has responsibility for getting the data ready before the Builder threads turn that into a mesh).  Sadly, the way things are structured at the moment, the Builder can time-out if the Generation takes too long and won’t notice a change until the camera moves sufficiently far.  Also generally I’ve tended to only need 1 or 2 Generation threads whereas what we’re really doing here is ActionData application — which I have tended to have 4 threads for since it’s done a lot!  It would feel a lot cleaner to move this re-application of ActionData to the ActionDataThread then get the BuilderThread to be informed when the Chunks are ready for meshing.  So that’s next!

Onwards and faster-wards 😉

Floating polar ice, part 2

Since last time on floating polar ice environment, I’ve fixed all those “obvious things” and improved the ice blocks!

Details below on Blender work, UBER, pushing and long-jumping.  First, here’s the video!


Spent much of Saturday learning 2 things for my ice blocks (which will hopefully be useful in future modeling jobs, eh-hum!)


Firstly, modeling the ice block with Blender (with links to tutorials, etc used — some of which I’d done before but it’s nice to have a simple list of references, eh!):

  1. Clone original object (in case wish to start again)
  2. Fracture to create detailed object
  3. Duplicate and ensure it has unique data blocks,
  4. Bake AO map, normal map, etc.
  5. (after playing with UBER below, realize I’d prefer to hand-paint the translucency map so…)
  6. Texture paint translucency map (I painted to black and white though this needs moving to either the Albedo’s Alpha channel or the AO map’s green channel for UBER).


The second thing that took most of Saturday was fiddling with UBER shader‘s (yes, it’s name is all capitals) refractive and translucency capabilities.  I’d previously gotten reasonable results for the PlayerSetupArena’s ice walls but, on reflection (see what I did there … er, ‘cuz I spent ages fiddling with all those optics parameters, oh never mind 😉 ).  Yes, on reflection, I realized I’d used an amount of emission to get the blue-ish hue from the ice.  While that worked OK in a static environment with no time-of-day changes, it ruins the PBS capability for nighttime.  As such, I think I need a different way.  For the PlayerSetupArena I’m toying with adding some point lights behind the ice walls that slowly rotate around the arena.  I’ve not done it yet but will post a (hopefully very pretty pic) once done.

However for the ice-blocks floating on the ocean, I eventually concluded that UBER has difficulty with Realistic Water‘s shader.  I suspect (after some invetigating) that both UBER and RW do a grab pass to get information about what is behind them to do their refractive effects.  This likely needs unifying to get them to work together.  For now I’m resetting the floating ice blocks back to Unity Standard shader since the effect is still very pleasant.

Madness, Ceto and Beautify

Lastly (on the aesthetics front), to tie-off my comments last time about the recent Unity Asset Store Madness sale, I also tweaked the RW ocean shader to give some ripple highlights using its Fresnel capability.  They aren’t everything I’d envisaged but might actually be better.  Let me know your thoughts!  RW doesn’t do volumetric subsurface scattering which I’d really like but neither does Ceto — the water shader in the sale.  As such, I decided not to buy that and save for PlayWay if I ever need more (which I think is the most impressive one).  Instead, at the recommendation of a few dev friends, I picked-up Beautify.  It is another post-effect and sharpens up the image.  I suspect I’ll need to combine it with Scion to save passes later but for now, it’s added a lovely ‘pop’ to my aesthetic so good suggestion, guys!


Lastly (really this time), a couple of gameplay bits!

Several people made the same comment on the last picture of the floating ice — “Jump! Jump!” and “Push him!“.  Yep, that’s all in there!  I’ve included it in the video to satisfy the schadenfreude of my audience 😉

However I also discovered a ‘feature’ of my movement controller that allows jumping much larger gaps than I’d previously believed — by rolling, releasing and double-jumping, you can long-jump!  This wasn’t something I built in intentional but is actually quite a lot of fun so I’ll be labelling that a feature.  The big question is whether it’s accessible enough for regular players to use or is it primarily for expert players to access secrets!  (your thoughts as always are most welcome 🙂 )

p.s. Are blog posts like this better?  I’m not writing them as I go so they’re twice less useful to me (I can’t use you for Rubber Duck Debugging and it takes time to write them instead of more GameDev!) but I think the overall feeling is nicer.  What do you think?  Would you prefer more dev ponderings? more conclusions? half-way? other?  TTYS!