Voxel engine development
hakkthazard Code and Eng DK30 Fall 2020 1 2
Description
I’d like to prototype some voxel game ideas with the game prototyping engine I have been working on, but my game engine only really supports some basic 3d rendering. I’d like to add voxel rendering and related systems to my existing crossplatform engine, even if it’s pretty barebones and inefficient.
Recent Updates
I added the ability to add and remove blocks at run time. The game follows a raycast from the camera and does a grid traversal until it hits a solid block, then marks the previous block as the target for placing a new block.
I didn’t get around to saving/loading chunks from disk, so any blocks that were added or removed are reset when the chunk leaves memory.
This will complete this project for now. I am happy with the amount that I got done, considering that I started late. The only things in my weekly goals that I did not get to are supporting multiple blocks shapes, and saving/loading chunks. Both are big tasks that I would like to come back to in the future.
The browser version of the project can be played here. Use WASD to move, click and drag to orient the camera, and use the F and G keys to add and remove blocks.
I added frustum culling for the voxel chunks. Now, chunks outside the view frustum aren’t rendered, which looks no different visually but saves on rendering time.
There appear to be some stray chunks that are still rendering behind the camera, so my math is probably off somewhere, but there only seem to be a few, so it shouldn’t have too much of a performance impact.
I added the idea of “chunks” to the engine. 32x32x32 voxel chunks are generated for the area around the player. I keep a hash map of voxels indexed by (x,y,z) coords, load and generate the mesh for any active chunks near the player, and mark far away chunks as inactive so they don’t need to be rendered, take up memory, use up gpu buffers, etc.
I am not loading or saving chunks from files, but I generated some simple 3D terrain with some sine and cosine functions. The voxel chunk meshes use up a lot more storage than they need, and I’m not doing any frustum culling, so I’m not rendering a lot of chunks at once. I added a fog effect to hide the pop-in when moving around the world.
I added the basic optimization of not generating mesh data for voxels that are completely surrounded by other voxels.
I am generating all 6 faces for each voxel, so it’s not as good as generating each face separately. But I think it will extend nicely to voxels of different shapes without adding a lot of complexity.
I finished the first version of voxel meshing, by just generating a whole 6-sided cube for every voxel without considering voxel visibility. I added a sine wave effect to test how quickly the new mesh could be generated and transferred to the GPU.
As a test, I first tried rendering a separate cube for each voxel. The framerate really slowed down at the top of the sine wave, where the number of draw calls approaches 32000. Compared to that first test, creating dynamic meshes for the voxel chunk is much faster. I’d still like to try culling interior voxels, because I think the game will start to run slowly when rendering multiple chunks that were generated with this brute force approach.
I had a very busy October and only just started to work on my project.
I spent a few days revamping the asset loading system in my engine. Instead of manually adding asset keys in code, introducing dependencies in the order they are defined, I now run a tool to pack all of my assets into a single file, and am able to add and access new assets by simply adding them to a folder, and referencing them by their filenames in string form.
It’s not really related to voxels but it is an improvement that I have wanted to work on for a while.
Estimated Timeframe
Oct 15th - Nov 14th
Week 1 Goal
- Before adding any voxel systems, I’ll try to clean up the existing codebase, with a focus on adding iOS features. I want to be able to test on iOS as I go, because I want my engine to work on mobile platforms but they are the most resource constrained.
Week 2 Goal
- Start adding voxel systems. I’m going to try something like reading a 3D array of voxel values and rendering a cube for each one. Depending on how long that takes, I can start adding optimizations; I don’t want to focus on making a very efficient engine, but there are some necessary optimizations to make a voxel engine work reasonably, like culling interior voxels.
Week 3 Goal
It’s hard to say how well the engine will be working by Week 3, and I would like to focus more on working bit by bit to just get the voxels rendering correctly and having the engine run smoothly. But some ideas for further development are:
- Adding shapes that are not strictly cube shaped; specifically, 45 degree slopes, 30 and 60 degree slopes, and slopes that work around corners. I want to test some game ideas that require smooth movement on sloped terrain.
- Chunk management: keeping a list of chunks of voxels that are active, only rendering/simulating those, and handling the loading/storing of chunks to disk. This will be necessary to implement at some point if I want to have big levels.
Week 4 Goal
- Stop adding new features, fix any major bugs and put time in to polish up what I have. In this case I want to have a solid foundation to build on in the future, rather than a throw-away prototype