Sylor
Sylor

Reputation: 13

Does an VBO must "glBufferData" before the first render loop?

I am a newbee to OpenGL. Now I could render something on screen, which is great. Now I want to streaming some data point(GL_POINTS) on my screen. However, initially it doesn't show anything. And it costs me several days to find out how to make it works.

The point is, I use an VBO to save my data and call glBufferSubData() to update the buffer. However, it ONLY works if I call glBufferData() before the first render loop. In other words, if I just do

glGenVertexArrays(1, &VAO);    
glGenBuffers(1, &VBO);

in my initializing function (before first render loop), and in my updateData loop I do

glBindVertexArray(VAO);
glBindBuffer(VBO);
glBufferData(GL_ARRAY_BUFFER, myData.size() * sizeof(float), &myData[0], GL_DYNAMIC_DRAW);
... // glVertexAttribPointer and other required general process

It won't render anything. It seems I have to glBufferData(/some random data here/) to "allocate" the buffer (I thought it was allocated when calling glGenBuffer()). And use

glBufferSubData(/*override previous data*/) or
glMapData()

to update that buffer. So my question would be...what is the proper/normal way to initialize an VBO if I don't know how much data/vertex I need to draw in the compile time? (right now I just glBufferData() a loooooong buffer and update it when needed)

Note: OpenGL3.3, Ubuntu16.04

Update:

In my opinion, it works in the way like allocating char[], I have to say pointing out how much I need for the string char[200], and fill in the data via snprintf(). But we now have vector or string, that allows us to dynamically change the memory location. Why OpenGL doesn't support that? If they did, how should I use it.

Upvotes: 0

Views: 714

Answers (1)

Nicol Bolas
Nicol Bolas

Reputation: 473192

I thought it was allocated when calling glGenBuffer()

The statement:

int *p;

Creates an object in C/C++. That object is a pointer. It does not point to an actual object or any kind of storage; it's just a pointer, waiting to be given a valid address.

So too with the result of glGenBuffers. It's a buffer object, but it has no storage. And like an uninitialized pointer, there's not much you can do with a buffer object with no storage.

what is the proper/normal way to initialize an VBO if I only don't know how much data/vertex I need to draw in the compile time?

Pick a reasonable starting number. If you overflow that buffer, then either terminate the application or allocate additional storage.

But we now have vector or string, that allows us to dynamically change the memory location. Why OpenGL doesn't support that?

Because OpenGL is a low-level API (relatively speaking).

In order to support dynamic reallocation of storage in the way you suggest, the OpenGL implementation would have to allocate new storage of the size you request, copy the old data into the new storage, and then destroy the old storage. std::vector and std::string have to do the same stuff; they just do it invisibly.

Also, repeatedly doing that kind of operation horribly fragments the GPU's address space. That's not too much of a problem with vector and string, since those arrays are usually quite small (on the order of kilobytes or low megabytes). Whereas a single buffer object that takes up 10% of a GPU's total memory are hardly uncommon in serious graphics applications. Reallocating that is not a pleasant idea.

OpenGL gives you the low-level pieces to build that, if you want to suffer the performance penalty for doing so. But it doesn't implement it for you.

Upvotes: 4

Related Questions