DevLog #006 – Adding Water

Part of a series of posts in which we write a voxel engine from scratch for Android.

Water is weird stuff – and it gets even weirder when you’re thinking in blocks. You can’t just plonk it down like a regular block and have it sit there doing nothing. It needs to move around and flood-fill an area.

So what’s the most efficient way to fill-up pools of water in our terrain without complex computation? Well, we already have a sand-height in our terrain generation, and it tends to create enclosed pits of sand at lower elevation, and nice sandy beaches at the edge of our map – it’s almost like we were planning ahead!

When a terrain is generated for the first time, we don’t actually have to calculate any flood-fill at all – we can simply say “If this block is sand, and it’s below the water level, add a column of water blocks up-to the water level“.

But in real life, water doesn’t just sit at one level – we have elevated pools of water above sea-level. Ok, so we’ll have a water-level and a sea-level. So now we can say “If this block is sand, (and it’s below the sea level, add water blocks up-to sea-level, else add water blocks up-to water-level)“.

Finally, we can say “Any water blocks that aren’t touching air will not be rendered” to avoid problems with transparency.

For the surface of the water, we’re setting texture coordinates to world-coordinates to avoid too much repetition, and we have a simple DUDV shader to displace the texture for a moving ripple effect. We also move the vertices down a bit to make it slightly lower than the surrounding blocks.

To add a sense of volume to the water, we can decrease the fog distance in the water shader, and increase the alpha by the fog strength, causing it to look more translucent as you get closer to it.

What’s missing? Trees! Next post.

If you’re interested in DUDV Maps, there’s a brief explanation on the Polycount wiki