【问题标题】:How can i generate multiple VBO with an ByteBuffer如何使用 ByteBuffer 生成多个 VBO
【发布时间】:2015-08-04 11:14:41
【问题描述】:

根据lwjgl javadooc,有一个函数:

public static void glGenBuffers(int n, ByteBuffer buffer)

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

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

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

我的想法是,当我只创建 1 个 Buffer 来存储顶点、纹理坐标、法线和索引时,效率会更高。

【问题讨论】:

    标签: java opengl lwjgl


    【解决方案1】:

    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);
    

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

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

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

    【讨论】:

    • 哇,谢谢你的解释
    • 对术语的吹毛求疵:glGenBuffers() 不会生成 VBO,它会生成 names(或 ids,如果您愿意称它们为那)用于缓冲区对象。 VBO 仅在名称第一次绑定时创建。此外,如果您使用索引,则不必使用两个 VBO。尽管这并不常见,但将索引和顶点数据存储在同一个缓冲区中是完全合法的。
    • @RetoKoradi 谢谢,我不知道。
    猜你喜欢
    • 2011-08-08
    • 1970-01-01
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-06
    • 2015-05-21
    相关资源
    最近更新 更多