So I am making a voxel based game that uses cubes. I have already figured out how to draw hundreds, even thousands of them on screen easily. I need them however, to be removable. Instead of rendering all of them all of the time, so of them will be removed based on certain events. Currently I have a single array of 24 vertices, and I am using offsets in the vertex shader. What is the best way to achieve this? A dynamic array perhaps?
Sure. And this could take a number of forms. Assuming you’re using non-instanced drawing now (pseudo-instancing) to render these instances…
You could patch the vertex attr arrays to remove the vertex data for those cubes you want to remove. That’s fairly heavy-weight.
If using indexed rendering (gl*DrawElements*()
, or the gl*DrawIndirect
versions of these), you could alternatively update the index list and just replace the indices for the verts belonging to removed cube instances with primitive restart indices. That’s less data
Alternatively, you could switch this over to using instance rendering (glDraw*Instanced*()
, or the gl*DrawIndirect*()
versions of these) and then just have a single piece of per-instance data for each cube instance (as opposed to one that is duplicated per vertex) that indicates how to draw each instance. When drawing each instance, you either lookup into this per-instance data array using gl_InstanceID
in the shader or have the pipeline “push” this per-instance data into the shader on vertex attribute(s) (via instanced arrays). However, for instance removal, you just remove the per-instance data from this array for instances that you want to stop drawing.
Moreover, if you flip to using instance rendering using the “indirect” draw calls (gl*DrawIndirect*()
), you also have the option of just patching the DRAW_INDIRECT
buffer and either 1) removing the instance record (these records are tiny), or 2) just changing the instance record to set the number of instances to 0 (even fewer bytes touched). The advantage to the latter is that the number of sub-draws that you provide the indirect draw call can stay the same; the instance is killed off down in the driver before it schedules its sub-draw on the GPU.
There are pros and cons of each. The latter (GL instance rendering) is probably the cleanest from a dev perspective, as there’s just one piece of data to update per instance. OTOH, if you’re trying to push your GPU to the absolute max throughput, you might find that patching the index list (while more data to update) yields faster overall throughput. But it’s going to depend on how efficient your dynamic buffer/texture update logic is, how efficient the rest of your rendering is, and the GPU/driver you’re running on of course.