I’ve been playing around with VBOs a lot today (mostly because a game I’m working on necessitates it), and while I have a basic idea of how glBufferSubData() and glMapBuffer() work, I’m not quite sure of how to implement them. My game is essentially a Terraria clone, and the primary VBO contains data about the blocks in the world. The world is divided into “chunks” which are 16x128 blocks large. When the player modifies a block in a chunk, that chunk is updated. Up until now, I’ve been doing this by storing each chunk’s vertex data to its own array in a HashMap and updating each array as needed. This also means I have to splice them together into a single array, which causes a minor lag spike. But, I digress. I’d be set to go with the two aforementioned methods, except that some blocks are sometimes null. When a player places a block in a chunk, its number of vertices increases. Therefore, it wouldn’t suffice to simply replace the existing data for the chunk in the VBO, as it would cause the game to crash due to a lack of allocated memory for the vertices. My first thought as to preventing this would be to allocate enough memory for 16 times 128 times four vertices (the number of vertices which would exist in a chunk if every block were filled in). But, I’m not entirely sure as to how to accomplish this. Would anyone mind pointing me in the right direction?
If you’re going down that road. Firstly you should have one VBO containing all vertex data for a generic chunk. Then have an IBO specific to each chunk which contains which blocks are where. Change the transformation matrix to position each chunk in the right place (or just have a uniform x-offset in your shader if you aren’t doing any other model transforms). Secondly than single VBO should only be (16 + 1) * (128 + 1) since each vertex is shared between 4 blocks and there is no point having the same data 4 times now you are using IBOs.
Now, technicals aside. To create a VBO of a specific side, pass in a Buffer of that size. It doesn’t have to be full or in fact used at all. Then you can use, as you said, glBufferSubData() or glMapBuffer() / glUnmapBuffer() to fill in the gaps as it were. All you have to do is store how many blocks you have and where they are in the IBO. Ideally you would bunch them all together and draw a whole chunk with one OpenGL call, but then you would need to move the whole buffer down once you deleted the first block. Certainly fill up empty slots from the bottom and try to group together draw calls into one.
Now I think about it, that was quite technical.