Home > Geo, Procedural Landscapes > A note on voxel cell LOD transitions

A note on voxel cell LOD transitions

I recently received a question from a developer who has kindly been reading my blog asking about how I tackled the joins between voxel cells of differing resolutions.  This was one of the most challenging problems raised by the voxel terrain system and so rather than put my response in a mail I thought it might be more useful to make it public for anyone else who visits.

I’ll start by saying however that after devoting time to several different strategies I never did come to a solution that I was entirely happy with – each had it’s problems some more objectionable than others but I’ll relate each experiments here…maybe someone else can take something from them and improve the results.

Before getting to my solutions, it’s probably worth first describing the problem: essentially the whole environment is made up of cube shaped cells of voxel data, each one containing geometry representing the iso-surface within that cube.  The number of sample points and therefore the iso-surface resolution within each cell is constant but  to keep the amount of data in memory and being rendered reasonable, cells close to the camera represent small areas of the world while cells further away represent proportionally larger areas.  In a manner similar to mip-mapping for textures, each level of cells is twice as large in the world as the ones  from the preceding level.  Near the camera for example a cell might cover 10 metres of world space while moving into the middle distance would switch to 20 metre cells, then 40 metre, then 80 and so on.

While a continuous representation would improve the consistency of triangle size over the view distance, the management of a cell-based approach is far simpler as individual cells can be generated, cached and retrieved very simply.  The downside however is the exactly the problem asked about – where a 10m cell abuts a 20m cell for example, every other sample point on the 10m cell will have no corresponding sample point in the 20m cell and we end up with a floating vertex that in most cases does not line up with the edge of the triangle in the 20m cell it is next to and we get a visual crack in the world geometry.

The first and method I tried was to simply displace the floating vertex along it’s normal by some distance based upon how far it was from the viewpoint.  This correlates to other simple techniques for hiding LOD cracks in 2D height fields where verts can be moved ‘up’ by some amount to hide the crack – it works to a degree in 3D too as I found and could often hide the resultant crack but unfortunately it wasn’t reliable as sometimes the normal didn’t happen to point in the best direction to hide the crack, and sometimes the nature of the voxel data itself meant that no sensible amount of movement could hide the resultant crack regardless of direction due to rapidly changing curvatures or other high frequency detail.

The second experiment was to try to create ‘fillet’ geometry that would connect the hanging vertices from the higher detail cells to the vertices in the lower detail cells.  I have used this system in the past on 2D height fields to eliminate cracks and while it’s a bit fiddly it does guarantee crack free results.  Unfortunately I had underestimated just how complex it is to extend this system from 2D to 3D – the sheer number of cases that needs to be handled to enable low detail sub-cube sides to map to higher detail sides in all possible configurations is the biggest problem, especially where a cell has a mixture of higher and lower details neighbours.

I achieved limited success with this but didn’t manage to get it working satisfactorily, eventually putting it to one side as I tried to find a less fiddly solution.

The final solution that I ended up with was to render cells that had neighbours of differing resolutions twice, calculating an alpha value in the pixel shader based upon the proximity of the point to the edge of the cell where the resolution changed.  By enabling alpha-as-coverage rendering this produced a screen space dissolve effect that while inferior to correctly connecting geometry was actually fairly visually unobtrusive in most cases – the higher frequency terrain detail fades in as you approach which hides the transition between LODs fairly well especially when combined with a degree of atmospheric fog.

It’s not perfect though and looks a little peculiar where there is high frequency detail producing large differences between LODs or when the viewpoint is moving slowly and part cross-faded features remain on screen for significant periods of time.  There is also of course a performance cost of rendering some cells twice but it’s the least evil solution I came up so I left it in.

This is one of those problems where there feels like there should be a neat solution out there somewhere but so far my internet research has not turned one up – off-line rendering solutions such as subdividing down so cells are less than one pixel across are not exactly practical!  If you do come across any improved solutions however or develop any of your own, do please post a comment or drop me a line – I would be very interested to hear about them.

Categories: Geo, Procedural Landscapes
  1. February 10, 2011 at 1:10 am

    I think you would find the Transvoxel Algorithm to be interesting.

    • February 14, 2011 at 12:01 pm

      Thank you Eric for pointing this out to me. An initial read through your dissertation has been very interesting, it’s full of ideas and techniques that are highly relevant to my field of interest and my experimental projects with the LOD transition work being particularly interesting.

      Although my focus is currently more on procedural infrastructure generation I would very much like to find the time to revisit the voxel routines to try out some of your algorithms in the future – I’ll post here should that happen.

      Keep up the good work


  1. January 4, 2011 at 12:33 pm

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: