My last experiment got out of hand and now the cubes have become self aware. See for yourself!
The earlier "lil cube" example worked by creating individual box meshes and adding them to the scene. This is not a very scalable approach if we want a lot of boxes! Creating a single chunk of 16 x 16 x 32 blocks would take about 20ms to create: More than a single frame at 60 fps, and way too long to do anything dynamic.
Then next thing I tried was to merge the boxes into a parent geometry, rather than adding each mesh individually. This did indeed give a performance boost, with each chunk only taking 5 to 10ms to create. Good, but still pretty slow.
Finally, I went all in for building the geometry myself. Using Three.js's
BoxBufferedGeometry as a base, I wrote a function that would create the entire geometry for a single chunk. Each plane is added to a BufferGeometry - excluding any planes that would be obscured by a neigbouring box.
To work with Multi Materials (so you can have a different texture for each side of a cube) I had to split the creation into faces: rendering all the "top" faces first, then all the "front" faces and so on.
The result is a ~1ms render for most chunks on my machine: getting up higher with very complex and hole-y chunks.