如何使用ByteBuffer生成多个VBO

时间:2015-08-04 11:14:42

标签: java opengl lwjgl

根据lwjgl javadooc,有一个函数:

public static void glGenBuffers(int n, ByteBuffer buffer)

但我并不完全明白这是如何运作的。 我是否创建了一个ByteBuffer:

ByteBuffer buffer = ByteBuffer.allocate("how much???")
glGenBuffers(4, buffer);

尤其是我必须用glBufferSubData OR填充缓冲区 创建4个缓冲区并绑定并填充它们会更好吗?

我的想法是,当我只创建1个缓冲区时会更有效率,缓冲区存储顶点,纹理,法线和索引。

1 个答案:

答案 0 :(得分:2)

glGenBuffers(int n, ByteBuffer buffer)生成n个顶点缓冲区对象(VBO),您可以使用它们来存储数据,并将它们放在指定的缓冲区中。此缓冲区实际上不是保存数据的缓冲区,而是刚刚生成的VBO的 ids 。您必须使用glBufferData手动定义VBO数据。

如果您想通过一次调用创建多个VBO,该功能非常有用。每个VBO id都是一个整数,缓冲区必须足够大才能容纳n个(在这种情况下为4个)缓冲区。

ByteBuffer buffer = BufferUtils.createByteBuffer(4 * Integer.BYTES);
glGenBuffers(4, buffer);

但是,为了方便起见,您还可以使用IntBuffer

IntBuffer buffer = BufferUtils.createIntBuffer(4);
glGenBuffers(4, buffer);

然后,您可以将数据附加到每个VBO。

glBindBuffer(GL_ARRAY_BUFFER, buffer.get(2); /*value from 0 to 3*/
glBufferData(GL_ARRAY_BUFFER, data, GL_STATIC_DRAW);

(如果您使用ByteBuffer,则必须拨打buffer.getInt(2)。)

将所有数据放在单个缓冲区中通常更有效,但请注意,在这种情况下,您必须使用至少两个因为索引必须位于GL_ELEMENT_ARRAY_BUFFER 中。但是,性能差异非常小,因此使用几种不同的VBO可能更容易。

最好将所有数据紧密打包到缓冲区中,并使用glBufferData上传,而不是为每种类型的数据调用glBufferSubData。您的数据布局将看起来像这样(P =位置,T =纹理坐标,N =法向量):

PPPTTNNNPPPTTNNNPPPTTN...

现在您可以设置顶点属性指针以正确读取此缓冲区中的值。

int vbo = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, tightlyPackedData, GL_STATIC_DRAW);

int stride = (3 + 2 + 3) * Float.BYTES;

glVertexAttribPointer(positionIndex, 3, GL_FLOAT, false, stride, 0);
glVertexAttribPointer(texCoordIndex, 2, GL_FLOAT, false, stride, 3 * Float.BYTES);
glVertexAttribPointer(normalIndex,   3, GL_FLOAT, false, stride, (3 + 2) * Float.BYTES);

positionIndextexCoordIndexnormalIndex是顶点着色器属性的属性位置。您可以使用glGetAttribLocation获取它们。

stride是一个顶点的值与下一个顶点的值之间的字节数。我们有3个位置,2个纹理坐标和3个法线,它们都是浮点数,所以我们将它们乘以Float.BYTES

glVertexAttribPointer的最后一个参数是以字节为单位的偏移量,即从缓冲区起始处到第一个值所在位置的字节数。