我目前正在使用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是因为我想从第十个旧值改变值。
是吗?有没有更好的方法呢?再说一遍:如果我每帧重新上传整个数据,这样可以吗?
答案 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()
。但不知道一些数字,很难说。