Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating VBO data with glBufferSubData()

Tags:

java

opengl

vbo

I am currently working on a 2d Top-down RPG written in Java 1.6 with the LWJGL. I implemented the use of VBOs into my game and now I maintain two of them: one for vertex data and one for texture coords.

It's all working fine except that I still don't have a really logical way to update the Objects. As an example, if I want a certain tile to change its texture (change the texture coordinates inside the VBO in order to show another area of the Texture Sheet), I can't see a way to only changing the texture coordinates that correspond to this single tile. All I can think of now is maybe filling up the buffers with all the data needed every loop and uploading them with glBufferData every frame. It works but does not seem to be the best way of doing it (or it does?).

Now, there is the glBufferSubData command which will not allocate new memory but only change the portion I tell it to change. The thing is I don't know how to keep track of the area that has to be changed (the offset). LWJGL offers a glBufferSubData(target, offset, data); command, which only needs the beggining of the buffer to work. Is the offset something like an index?

So if I first upload these buffers to the VBO and then want to change the second value of the second float[]:

FloatBuffer vertexData = BufferUtils.createFloatBuffer(amountOfVertices * vertexSize);
vertexData.put(new float[]{100, 100, 300, 100, 300, 300, 100, 300});
vertexData.put(new float[]{400, 100, 600, 100, 600, 300, 400, 300});
vertexData.flip();

I would generate the new data, put it inside a small FloatBuffer and upload it with glBufferSubData(GL_VERTEX_ARRAY, 10, newFloatBuffer);? 10 is because I want to change values from the tenth old value on.

Is that right? Is there a better way to do it? And again: is it ok if I re-upload the whole data every frame?

like image 233
Thiago Avatar asked Aug 14 '12 19:08

Thiago


People also ask

How do I update my VBO?

The simplest method of updating VBO is copying again new data into the bound VBO with glBufferData() or glBufferSubData(). For this case, your application should have a valid vertex array all the time in your application.

When to use glMapBuffer?

Using glMapBuffer is useful for directly mapping data to a buffer, without first storing it in temporary memory. Think of directly reading data from file and copying it into the buffer's memory.

What is a buffer OpenGL?

Buffer Objects are OpenGL Objects that store an array of unformatted memory allocated by the OpenGL context (AKA the GPU). These can be used to store vertex data, pixel data retrieved from images or the framebuffer, and a variety of other things.


1 Answers

LWJGL's glBufferSubData() expects the offset as byte count, since one should be able to write arbitrary data to arbitrary buffer locations. If you want to update the float at index i, the offset would be i * 4, since java floats take, the very common, 4 bytes. All remaining buffer contents will be written, therefore, the target buffer is required to have a capacity of at least
(i + floatBuffer.remaining()) * 4 bytes. For correct preparation, see the Buffers flip() method or use position(int) together with limit(int) to specify the remaining contents to be written.

This updating strategy is OK as long as you don't call glBufferSubData() too many times with temporary FloatBuffers. You could also have a second target buffer with equal size for swapping (ping pong), which one could map using MapBuffer() for an overall update, while the other one is in use.

I'd rather hold a complete FloatBuffer at the client side and upload it at once using glBufferData() instead of calling glBufferSubData() many times. But without knowing some numbers, it's hard to tell.

like image 108
Sam Avatar answered Oct 01 '22 17:10

Sam