问题
What are the fastest and the most flexible (applicable in most situations) ways to use VBOs?
I am developing an openGL application and i want it to get to the best performance, so i need someone to answer these questions. I read many questions and anwers but i guess there's to much information that i don't need which messes up my brain...
- How many vbos should i use?
- How should i create vbos?
- How should i update vbos data, if the data size is not fixed?
- How should i render vbos?
- How should i deal with data in vbos that i don't want to render anymore?
回答1:
- How many vbos should i use?
As few as possible. Switching VBOs comes with a small, but measureable cost. In general you'll try to group similar data into VBOs. For example in a FPS game all the different kinds of garbage lying on the street, small props, etc., will be usually located in the same or only a small number of VBOs.
It also comes down to drawing batch sizes. glDraw…
calls which render less than about 100 primitives are suboptimal (this has always been the case, even 15 years ago). So you want to batch at least 100 primitives where possible. But if a single mesh has only, say 20 triangles (low polycount props for instancing or such), each in its own VBO you can no longer batch more.
- How should i create vbos?
glGenBuffers → glBindBuffer → glBufferData
UPDATE You can pass a null pointer to the data
parameter of glBufferData to initialize the buffer object without setting the data.
- How should i update vbos data, if the data size is not fixed?
Create VBOs with a coarser size granularity than your data size is. Your operating system is doing this anyway for your host side data, it's called paging. Also if you want to use glMapBuffer making the buffer object a multiple of the host page size is very nice to the whole system.
The usual page size on current systems is 4kiB. So that's the VBO size granularity I'd choose. UPDATE: You can BTW ask your operating system which page size it is using. That's OS dependent though, I'd ask another question for that.
Update the data using glBufferSubData or map it with glMapBuffer modify in the host side mapped memory, then glUnmapBuffer.
If the data outgrows the buffer object, create a new, larger one and copy with glCopyBufferSubData. See the lase paragraph.
- How should i render vbos?
glBindBuffer → glDraw…
- How should i deal with data in vbos that i don't want to render anymore?
If the data consumes only a part of the VBO and shares it with other data and you're not running out of memory then, well, just don't access it. Ideally you keep around some index in which you keep track of which VBO has which parts of it available for what kind of task. This is very much like memory management, specifically a scheme known as object stacks (obstacks).
However eventually it may make sense to compactify an existing buffer object. For this you'd create a new buffer object, bind it as writing target, with the old buffer object being selected as reading target. Then use glCopyBufferSubData to copy the contents into a new, tightened buffer object. Of course you will then have to update all references to buffer object name (=OpenGL ID) and offsets.
For this reason it makes sense to write a thin abstraction layer on top of OpenGL buffer objects that keeps track of the actual typed data within the structureless blobs OpenGL buffer objects are.
回答2:
How many vbo's should i use?
As many as you need, sounds silly but well, its that way
How should i update vbos data, if the data size is not fixed?
Overwrite and render the same VBO with different data and lengths.
How should i create vbos?
How should i render vbos?
see VBO tutorial
How should i deal with data in vbos that i don't want to render anymore?
create a new vbo and copy the data into it or render only parts of that vbo which is in memory.
To render only parts see glVertexBuffer glTexCoordPointer(just calculate the new pointer and new size based on the offset)
Edit 1:
Using a single VBO for everything feels wrong, because you have to manage the allcation of new vertex positions/texture coordinates yourself which gets really messy really fast.
It is better to group small props into VBO's and batch the drawing commands.
Can i add data to a buffer with glBufferSubData (adding 100 elements to a buffer with size x)?
No, its not possible because the description says updates a subset of a buffer object's data store
and a subset is a smaller set inside a set.
Edit 2
A good tutorial is also Learning Modern 3D Graphics Programming but its not VBO specific.
来源:https://stackoverflow.com/questions/15923075/the-best-way-to-use-vbos