如何使用 ByteBuffer 生成多个 VBO
How can i generate multiple VBO with an ByteBuffer
根据 lwjgl javadooc,有一个函数:
public static void glGenBuffers(int n, ByteBuffer buffer)
但我不太明白这是怎么回事。
我是否创建一个 ByteBuffer :
ByteBuffer buffer = ByteBuffer.allocate("how much???")
glGenBuffers(4, buffer);
特别是我必须用 glBufferSubData
或
创建 4 个缓冲区并绑定并填充它们是否更好?
我的想法是,当我只创建 1 个 Buffer 时效率更高,它存储顶点、纹理坐标、法线和索引。
glGenBuffers(int n, ByteBuffer buffer)
生成 n 个顶点缓冲区对象 (VBO),您可以使用它们来存储数据,并将它们放入指定的缓冲区中。这个缓冲区实际上不是保存你的 data 的缓冲区,而是刚刚生成的 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);
positionIndex
、texCoordIndex
和 normalIndex
是顶点着色器属性的属性位置。您可以使用 glGetAttribLocation
.
获取它们
stride
是一个顶点的值和下一个顶点的值之间的字节数。我们有 3 个位置,2 个纹理坐标和 3 个法线,它们都是浮点数,所以我们将它们乘以 Float.BYTES
。
glVertexAttribPointer
的最后一个参数是以字节为单位的偏移量,即从缓冲区开始到第一个值所在位置的字节数。
根据 lwjgl javadooc,有一个函数:
public static void glGenBuffers(int n, ByteBuffer buffer)
但我不太明白这是怎么回事。 我是否创建一个 ByteBuffer :
ByteBuffer buffer = ByteBuffer.allocate("how much???")
glGenBuffers(4, buffer);
特别是我必须用 glBufferSubData
或
创建 4 个缓冲区并绑定并填充它们是否更好?
我的想法是,当我只创建 1 个 Buffer 时效率更高,它存储顶点、纹理坐标、法线和索引。
glGenBuffers(int n, ByteBuffer buffer)
生成 n 个顶点缓冲区对象 (VBO),您可以使用它们来存储数据,并将它们放入指定的缓冲区中。这个缓冲区实际上不是保存你的 data 的缓冲区,而是刚刚生成的 VBO 的 ids。您必须使用 glBufferData
.
如果您想通过一次调用创建多个 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)
。)
将所有数据放在一个缓冲区中通常效率更高,但请注意,在这种情况下,您必须至少使用两个缓冲区,因为索引必须位于 。不过,性能差异很小,所以使用几个不同的VBO可能会更容易。GL_ELEMENT_ARRAY_BUFFER
最好将所有数据紧密打包在缓冲区中并使用 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);
positionIndex
、texCoordIndex
和 normalIndex
是顶点着色器属性的属性位置。您可以使用 glGetAttribLocation
.
stride
是一个顶点的值和下一个顶点的值之间的字节数。我们有 3 个位置,2 个纹理坐标和 3 个法线,它们都是浮点数,所以我们将它们乘以 Float.BYTES
。
glVertexAttribPointer
的最后一个参数是以字节为单位的偏移量,即从缓冲区开始到第一个值所在位置的字节数。