Efficient vertex buffer memory management?

I am building a voxel engine with a similar mechanism to minecraft(yes, I know...). It works by loading and unloading individual chunks of 16*64*16 cubes each in a square grid around the player. This works fine for small render distances - like a 9x9 square grid of chunks. However, since updating a single vertex buffer entirely with a new mesh of millions of blocks each time a chunk is loaded/unloaded is inefficient, I have designed it so that each chunk has its own VB of fixed size, and rendering the entire world is basically looping through all the buffers, using d3dDeviceContext->IASetVertexBuffers(...).

When I increase the render distance, say to a square grid of 11x11 (around minecraft's large render distance), creating the vertex buffers simply cannot proceed beyond a certain point, and d3dDevice->CreateBuffer() returns E_OUTOFMEMORY.

So my question is: How do i manage the memory usage of the vertices, to both maintain good FPS (not using a single buffer for the entire terrain) and to have decent memory usage?

Additional Details: My vertex datatype is a struct composed of x,y,z coords, u,v texture coords and 3 normal coords. I know it can be improved in ways like a single byte for normals, since in voxels there are only 6 possible directions, however this will come later.

The fixed size of each chunk's vertex buffer is 16*16*64*18 vertices (16*16*64 blocks with a maximum of half of the sides showing, or 36/2 vertices max per block). This could also use some work, as each of these buffers is around 10MB.

How do games like minecraft handle this amount of data at once? (not to say i am using 64 blocks high chunks, where minecraft has 256) I have briefly considered using points as vertex shader inputs and expanding them to cubes in the geometry shader, to save 87.5% of the space, but this seems rather intense on the GPU.

• you don't need to reserve any space for air – ratchet freak Dec 12 '15 at 13:09
• I'm not that familiar with D3D, but I'm pretty sure it has facilities that allow you to modify only part of a vertex buffer. So I don't see why each chunk needs its own buffer. Also: "I know it can be improved in ways like a single byte for normals, since in voxels there are only 6 possible directions, however this will come later." If you're running out of memory, then improving that now is probably important. – Nicol Bolas Dec 12 '15 at 15:06

1 Answer

i have implemented a minecraft renderer on myself 2 years ago.

You have a vertexbuffer for every chunks. Thats right, so you only need to update that chunk if Anything changes.

Due to the fact you only handle voxels, and voxels have a fixed orientation you dont need any normals in buffer.

You Need to write a complex geometry shader. You dont even need any positions.

The pos of every voxel can be computed from the sv-vertexId. Then You only need a global offset to draw the chunk to the correct Position.

So all in all The only thing you Need for your voxels is a textype (8bit) to access one of the 255 textures in your array.

This will save lot of memory.

The next thing you need is frustum culling, so that the graphics device only renders what your camera really sees.

I think your underating the possibilities of a graphics card... If you have memory problems, compute as much as you can on your video card.

GOOD LUCK