Optimizing a Voxel Mesher with One Weird Hack

Ben Nolan
4 min readAug 4, 2018

--

Cryptovoxels is a virtual world on the Ethereum Blockchain. Follow us on Twitter or join the Discord.

Lighting using the new global illumination engine + shadows

I woke up on Saturday morning at 5am and so put myself on the couch with some coffee and some banging electro (the new Planete album is great) and decided to try rewriting the Cryptovoxels voxel mesher.

Some background — Cryptovoxels has been using Mikalo Lysenkos ao-mesher since it was created. I wrote a ao-mesher -> babylon.js mesh converter and it’s got the world to where it is now. The ao-mesher is great, it does:

  • Culling (don’t render faces that are hidden between two opaque blocks)
  • Ambient occlusion (Use vertex coloring to make corners darker)
  • Greedy meshing (Turn co-planar faces into one big face so less triangles)

However, there were a few problems with the ao-mesher:

  • It requires a shader with 4x the texture2d() calls so that you don’t get weird aliasing when looking up the texture in the texture atlas
  • It’s a really gnarly piece of code, so adding more advanced lighting to it wasn’t really possible
  • I wanted to write my mesher to learn what it would involve

So I sat down from first principles and wrote a mesher.

The cage prebuild looks great with shadows

Writing a simple mesher

I had a few goals for my new mesher:

  • Simple code (so I can port it to unity later on)
  • Super duper fast (without doing crazy optimisations)
  • Support fake global illumination
  • Culling mesher but not greedy mesher

Weirdly, the culling mesher, even though it creates way more faces, is waay faster to render on my Galaxy S6 and Oculus Go. I think the shader that I wrote to render the greedy meshed faces was quite slow, and being able to use the babylon.js standard material is way faster.

My super simple voxel mesher

The Theory

Single sweep through the 3 dimensional ndarray, if the block changes from this block to a neighbour in the +x, +y or +z direction, then draw a face. I’m not sharing any vertices between faces which is kind of dumb, but I couldn’t work out an easy way to do that (ideas welcome!)

Lighting

Seed of Andromeda have a great post on using flood fill to do lighting in a voxel based world. I’m using it here to great effect. I start the light floodfill on the edges of the parcel and then move inwards. It means the insides of buildings are darkened, with light only coming in through windows and skylights. It really looks fantastic.

Inside the bank of cryptovoxels

What’s left?

I don’t have ambient occlusion, and there is a bug with texture lookups. So I’ll fix that bug, and I might bake the ambient occlusion back in, the code is so simple now that I don’t think it’d be super hard to look at the surrounding voxels and work out what colour to set to the vertex. Well, I say it’ll be easy, I haven’t done it yet so it might be super hard.

The exciting thing coming out of this is that the current sunlight contribution code can easily be extended to allow light emitting voxels inside structures. And also red, green and blue voxels, so you could have fluorescent / neon lighting inside your shop for that real cyberpunk look.

An experiment in red / green / blue lighting

We discussed light emitting voxel in the Discord and the community raised the idea of light emitting voxels being scarce, possibly an ERC20 token that you burn to associate a light with a parcel. That way parcels can be developed and sold with some nice geometry and associated lighting. Anyway — it’s been a great weekend hack, hopefully we’ll get it deployed soon.

Cryptovoxels is a virtual world on the Ethereum Blockchain. Follow us on Twitter or join the Discord.

--

--