如何使用ByteBuffer生成多个VBO

3
根据lwjgl javadooc文档,存在一个函数:
public static void glGenBuffers(int n, ByteBuffer buffer)

但我并不完全理解这是如何工作的。我需要创建一个 ByteBuffer 吗:

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

我需要使用glBufferSubData来填充缓冲区吗?或者创建4个缓冲区并绑定和填充它们更好?

我的想法是,只创建一个缓冲区来存储顶点、纹理坐标、法线和索引会更有效率。

1个回答

2

glGenBuffers(int n, ByteBuffer buffer) 生成n个顶点缓冲对象(VBOs),您可以使用它们来存储数据,并将它们放入指定的缓冲区中。这个缓冲区实际上并不是保存您的数据,而是刚刚生成的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 中。 然而,性能差异非常小,因此可能更容易使用几个不同的 VBOs。

推荐紧密打包所有数据到一个缓冲区,并使用 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的最后一个参数是偏移量(以字节为单位),即从缓冲区开头到第一个值所在位置的字节数。


哇,感谢您提供这么好的解释。 - greedsin
1
有关术语的一些细节:glGenBuffers()并不会生成VBO,它只是为缓冲对象生成名称(或者如果你更喜欢这样称呼的话,id)。只有在第一次绑定名称时才会创建VBO。此外,如果使用索引,您不必使用两个VBO。尽管这不常见,但在同一个缓冲区中存储索引和顶点数据是完全合法的。 - Reto Koradi
@RetoKoradi 谢谢,我不知道那个。 - javac

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接