0
\$\begingroup\$

I have a VBO storing some data in my game. The thing is, the data can change at a rate of about a second. The data is not fixed size, meaning that some objects will sometimes be visible, sometimes invisible and could even have a different polygon count. I'm trying to figure out how I could do that efficiently using VBOs. In immediate mode, I would simply not call the render method of the single objet, and it would simply not appear! And if I needed more polygons, I would just... call glVertex2f more often! I understand why using immediate mode is really bad in performance, but I really can't think of any good way to "build" the VBO.

I thought about using a list, append the vertices to the list and then create the vbo, but this would have, I think, three drawbacks. More CPU intensive, requires more memory copying, and would require me to recreate (I could work this out) the VBO every time, since I don't know the size before building the lists!

Is there a common way of building a VBO for many small objects without using a list?

Some pseudo code:

void GlobalRender()
{
    foreach (chunk in chunks)
    {
        if (chunk.RequiresUpdate)
        {
            chunk.UpdateVBO(); //In there, that's where I don't know how large I'll need my VBO to be.
        }

        chunk.Render();
    }
}

void UpdateVBO() //The code called above
{
    foreach (node in nodes)
    {
        if (node.Visible)
        {
        //Emit vertices from here!
        }
        else
        {
            //There's nothing here really, just pointing out that there could be no vertices for a single node
        }
    }
}
\$\endgroup\$
  • \$\begingroup\$ Have you tried to use glSubBufferData? It's built for things like this. \$\endgroup\$ – Jordan Schnur Feb 23 '16 at 1:34
  • \$\begingroup\$ @Jordan Yes I use glSubBufferData all the time actually, but I can't figure out how to fill my vbo (or create it) if I don't know what the size will be! \$\endgroup\$ – Philippe Paré Feb 23 '16 at 1:35
  • \$\begingroup\$ I'm no expert by any means, but just find the largest a size will be. Set that to the size of the array and just replace the buffer with that. \$\endgroup\$ – Jordan Schnur Feb 23 '16 at 1:36
  • \$\begingroup\$ Could you add some code so I can see what you're doing? \$\endgroup\$ – Jordan Schnur Feb 23 '16 at 1:39
  • \$\begingroup\$ I guess I could yeah, I'll do that but I want to point out that the resulting size can be from 0 to like 150k vertices... I really don't know until I cycle throught the data \$\endgroup\$ – Philippe Paré Feb 23 '16 at 1:41
1
\$\begingroup\$

Firstly, I'm sure you're aware of this, but I'll state it just in case: your draw calls don't take their data from the buffers directly, rather, they refer to the enabled attribute arrays in the currently bound Vertex Array Object, or VAO. So, for every object you want to draw, you bind the associated VAO and GLSL program, and call the glDraw* function you need to draw your model. So, when you say

In immediate mode, I would simply not call the render method of the single objet, and it would simply not appear!

This is the same thing that you would do with modern, programmable OpenGL. Just don't call the glDraw* command related to your model, and it won't show!

Now, onto your question. We need to know more about the nature of your data in order to properly answer, but right off the bat, we can address a few issues:

And if I needed more polygons, I would just... call glVertex2f more often!

Well, this is not a good idea at all. Even in immediate mode, using glBegin() and glEnd() and all those glVertex() calls between them is not recommended at all. You mention that the option of updating the buffer is CPU intensive, but it doesn't get more CPU intensive than glBegin() and glEnd() when it comes to OpenGL.

I really can't think of any good way to "build" the VBO

Without knowing more about your models, I will assume that your model's vertices will indeed need to change once per second, in which case you have a Dynamic VBO. In that case, you have no choice; you have to update the vertex buffer object. However, there are several practices you can adhere to to make this process more performant, and these are discussed here and here

\$\endgroup\$
0
\$\begingroup\$

Disclaimer: I am by NO means an expert. I've written projects similar to this and this is the way I used and it seemed to work well.

This is a very complicated subject. Optimizations are a huge part of video games, and very difficult. Here are a few of my suggestions.

You have a list of nodes that can be visible or not. You need to come up with a formula to reduce the number of vertices so not show the inside vertices. It'll be worth it. This can save you like 100k vertices.

Secondly for each chuck make sure to record the size and beginning vertices so when you update you can use glSubBufferData

You mentioned it's a voxel engine. I know when dealing with them you should simplify the vbo to only include the edges. Basicly don't include the middle. I'm not sure if you're doing this already but obviously this can save like 100k worth of vertices.

As for objects (Anything not being the map itself) should be in a separate vbo.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.