5

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

除了我仍然没有真正合乎逻辑的方式来更新对象之外,一切都很好。例如,如果我希望某个图块更改其纹理(更改 VBO 内的纹理坐标以显示纹理表的另一个区域),我看不到仅更改对应于的纹理坐标的方法这个单一的瓷砖。我现在能想到的可能就是用每个循环所需的所有数据填充缓冲区,然后每帧用 glBufferData 上传它们。它有效,但似乎不是最好的方法(或者确实如此?)。

现在,有 glBufferSubData 命令不会分配新内存,而只会更改我告诉它更改的部分。问题是我不知道如何跟踪必须更改的区域(偏移量)。LWJGL 提供了一个 glBufferSubData(target, offset, data); 命令,它只需要缓冲区的开始即可工作。偏移量是否类似于索引?

因此,如果我首先将这些缓冲区上传到 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 是因为我想从第十个旧值开始更改值。

那正确吗?有更好的方法吗?再说一遍:如果我每帧重新上传整个数据可以吗?

4

1 回答 1

8

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.

于 2012-08-14T20:43:26.063 回答