Realtime Voxel Landscape Engines - Part 5 - Quality Improvement by (21 February 2000) | Return to The Archives

Heightmap Mip-mapping

The thing people complain the most about when they see voxel landscapes is the wobbling. Indeed the mountains tend to jigger up and down when you move along at moderate speed. This is due to the way we step through the heightmap, and skip a certain number of voxel columns depending on the step size. This is especially awkward when we set our LOD extremely low, thereby using big steps through the map. Apart from the obvious answer of reducing the step size, there is a solution.
The trick is to mip-map the heightmap, and use a map size that corresponds best to the size of the step. terraVox uses simple unidirectional mip-mapping, which greatly reduces the wobbling, especially in the distance. You can however notice the area where the next level of mip-map is used. Bidirectional mip-mapping would help a bit more, but using trilinear filtering would produce the best results. This wasn't implemented mainly due to the tremendous speed hit that would entail.

Texture Filtering

When we load a texel from our textures, we have the possibility of simply loading the closest texel, or applying a filter. Bilinear filtering in this case would look amazing, but we would have to load 8 texels to do that, which slows down the rendering pipeline by over 50%. Another technique is to use a form of dithering. We use a small precomputed array of noise with the intensity interpolated from the four corners. We use this value to determine which texel to load.
So in the end, we only need to load 2 texels, and the results when the texture is magnified is much nicer. The texels however tend to flicker a bit when moving, especially in the distance. But the overall effect of a static image is surprisingly good, giving the impression of an old oil painting.

Bidirectional Mip-mapping

There is another important problem with the texturing. Texels applied onto voxels far in the distance, or voxels that form a sharp angles with the camera seem to disappear and reappear randomly. This is not a problem with the voxel engine itself, just a general texturing problem. As you probably know, this can be easily solved by introducing multiple layers of mip-maps. terraVox can perform bidirectional mip-mapping, which to be perfectly honest is not that much better than unidirectional mip-mapping, except when the spans have a sharp angle in the texture.

Antialiasing

Antialiasing can be performed in various different ways. You can render multiple frames and blend them together, apply a simple filter or use a clever technique to smooth the edges only. The most effective is of course the last technique, since we can find the mountain crests extremely easily. This is done during the wave surfing. When a voxel column is projected below the previous, then we have a crest. We then alpha blend the lowest pixel of the new span with the highest pixel of the previous span. The alpha coefficient used is simply the fractional part of the Y coordinate projected onto the screen.

The Sky

This section is not really within the context of this tutorial, so I'll just cover it briefly. There are basically three simple ways of rendering skies in software.

- The first is extremely appropriate in this case, since it works only with 4 DOF engines. All you need is a reasonably wide bitmap and scroll it in parralax, like in the game DOOM.
- The second way consists of drawing a simple textured plane. This would also be quite quick, since all horizontal scanlines would have constant depth, so standard texture mapping optimisations could be performed.
- The third method is admittedly a bit bizarre: you draw vertical spans on the screen textured from a fish-eyed sky texture. For 4 DOF engines this looks like a parralax sky, but the technique would also work for engines with full degree of freedom.
  I'm not quite sure why, but I implemented this in the latest version of terraVox.

Water

Water can often be the most interesting feature of a landscape. The trick of course is to be able to render it in realtime. I can think of a few ways of doing this, off the top of my head.

- The most obvious would be to render the water as a plane, in a similar fashion to the sky plane. This would probably have to be done with an additionnal pass, since the spans of the landscape are best drawn vertically, and the water spans are ideally rendered horizontally. My advice would be to pre-render the water in a seperate buffer, and then check the occlusion buffer to see which part actually need to be blended in.
- You could also use a different texture array for under water parts of the landscape
- The concept of depth fog could also be introduced. That is, you alpha blend the voxels more or less depending on how much water is above.

Either technique would work fine, but combining them would probably give much better results.

Article Series:

> - Realtime Voxel Landscape Engines - Part 1 - Introduction
> - Realtime Voxel Landscape Engines - Part 2 - Rendering the Landscape's Structure
> - Realtime Voxel Landscape Engines - Part 3 - Texture and Lighting
> - Realtime Voxel Landscape Engines - Part 4 - Level of Detail and Optimisation
> - Realtime Voxel Landscape Engines - Part 5 - Quality Improvement
> - Realtime Voxel Landscape Engines - Part 6 - Hardware Acceleration
> - Realtime Voxel Landscape Engines - Part 7 - The Engine
> - Realtime Voxel Landscape Engines - Part 8 - Final Words

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.