使用glBufferSubData()更新VBO数据

时间:2012-08-14 19:21:25

标签: java opengl vbo

我目前正在使用LWJGL编写一个用Java 1.6编写的2d自上而下的RPG。我在我的游戏中实现了VBO的使用,现在我维护了两个:一个用于顶点数据,一个用于纹理坐标。

除了我仍然没有一个真正合理的方式来更新对象之外,一切正常。作为一个例子,如果我想要一个特定的瓷砖来改变它的纹理(改变VBO内的纹理坐标以显示纹理表的另一个区域),我看不到只改变对应的纹理坐标的方法这个单一的瓷砖。我现在所能想到的可能是填充每个循环所需的所有数据的缓冲区,并且每帧都使用glBufferData上传它们。它有效,但似乎不是最好的方式(或它确实如此?)。

现在,有glBufferSubData命令,它不会分配新的内存,只会改变我告诉它改变的部分。问题是我不知道如何跟踪必须改变的区域(偏移)。 LWJGL提供glBufferSubData(目标,偏移,数据);命令,只需要缓冲区的开始工作。偏移是否像索引一样?

因此,如果我首先将这些缓冲区上传到VBO,然后想要更改第二个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();

我会生成新数据,将其放在一个小的FloatBuffer中并使用glBufferSubData(GL_VERTEX_ARRAY,10,newFloatBuffer)上传; 10是因为我想从第十个旧值改变值。

是吗?有没有更好的方法呢?再说一遍:如果我每帧重新上传整个数据,这样可以吗?

1 个答案:

答案 0 :(得分:7)

LWJGL's glBufferSubData()期望偏移量为字节计数,因为应该能够将任意数据写入任意缓冲区位置。如果要更新索引i处的浮点数,则偏移量将为i * 4,因为java浮点数采用非常常见的4字节。将写入所有剩余的缓冲区内容,因此,目标缓冲区需要具有至少为(i + floatBuffer.remaining()) * 4字节的容量。 有关正确的准备工作,请参阅缓冲区flip()方法或使用position(int)limit(int)一起指定要写入的剩余内容。

只要您不使用临时FloatBuffers多次调用glBufferSubData(),此更新策略就可以了。 您还可以使用相同大小的第二个目标缓冲区进行交换(乒乓),可以使用MapBuffer()进行整体更新,而另一个正在使用中。

我宁愿在客户端持有一个完整的FloatBuffer,并使用glBufferData()一次上传,而不是多次调用glBufferSubData()。但不知道一些数字,很难说。