【问题标题】:multiple VBOs --> IBO多个 VBO --> IBO
【发布时间】:2013-12-03 03:37:00
【问题描述】:

我只是想了解 VBO 和 IBO 如何在 WEBGL 中工作。 以下是我的理解: IBO 有助于减少传递给 GPU 的信息量。所以我们有一个 VBO,然后我们创建一个 IBO,其索引指向 VBO。我怀疑 WEBGL 如何知道 IBO VBO 映射。在单个 VBO/IBO 的情况下,我认为 GL 是一个状态机,它会看到它绑定到的最后一个 ARRAY_BUFFER,然后将该缓冲区用作 IBO 目标。以下是多个 VBO(位置缓冲区和颜色缓冲区)的情况如下所示:

    gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);
    gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, cubeVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);

    gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexColorBuffer);
    gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, cubeVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0);

    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
    setMatrixUniforms();
    gl.drawElements(gl.TRIANGLES, cubeVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);

在上面的代码中(有效 - 我从教程中获取),我们有两个 VBO 和一个 IBO (cubeVertexIndexBuffer),我不明白 WEBGL 如何知道 IBO 的索引指向位置缓冲区而不是颜色缓冲区(尽管颜色缓冲区是最后一个绑定的 ARRAY_BUFFER)。

请让我知道我在这里缺少什么......

【问题讨论】:

    标签: opengl-es opengl-es-2.0 webgl


    【解决方案1】:

    GL_ELEMENT_ARRAY_BUFFER 绑定与 GL_ARRAY_BUFFER 绑定无关,每个绑定都由一组不同的命令使用。这就是为什么人们一开始不应该使用多个 VBO 来学习 OpenGL,交错的 VBO 避免了这种混淆。我将在下面尝试消除您的困惑。

    GL_ARRAY_BUFFER 绑定用于glVertexAttribPointer (...) 等命令。 GL_ELEMENT_ARRAY_BUFFER 绑定,另一方面,由glDrawElements (...) 绑定。

    IBO 中的索引不指向任何元素数组本身。他们指向什么 是您在 GL_ARRAY_BUFFER 绑定时设置的glVertexAttribPointer (...)s。


    如果还不是很明显,则在任何给定时间都不能绑定多个相同类型的缓冲区对象。当您设置属性指针并且不使用交错数组时,您必须更改绑定的 VBO。因此,glDrawElements (...) 不关心绑定了哪个 VBO,它只关心您设置的顶点属性指针和绑定的元素数组。这些指针与您设置它们时绑定的任何 VBO 相关,但在设置指针后,绑定的状态不再相关。

    【讨论】:

    • 嗨 Andon,感谢您的回复 ....但我还是没听明白 好吧,让我试着这样说吧,目前在上面的代码中,索引被链接到位置通过 gl.vertexAttribPointer 缓冲...如何更改它以使索引引用颜色缓冲区...
    • @user108788:不,他们不是。我不知道如何更清楚地说明这一点。元素数组缓冲区与您的各个 VBO没有任何关系。元素数组缓冲区实际上提供了一个索引数组到您通过调用glVertexAttribPointer (...) 设置的POINTERS。换句话说,与绑定 VBO 有任何关系的唯一命令是 glVertexAttribPointer (...) 在该命令完成后,您可以假装您的顶点数据来自 GPU 上的单个位置,而忘记用于创建指针。
    • @user108788:这就是为什么我不建议人们开始使用多个 VBO 而不是交错数组来学习 OpenGL。这可能会令人困惑。可以这么说,当您使用glDrawElements (...) 绘制时,元素数组缓冲区会从每组属性中提取顶点属性 N,当它遇到索引 N 时。元素数组缓冲区确实 NOT 索引单个顶点缓冲区,它使用来自每个属性的相同索引。用于拉取重新调整所需的每个顶点属性的指针。
    • 嗨安东..为我清除了它..非常感谢!!我有点意识到我完全偏离了轨道......你为像我这样的新手推荐的任何好的链接/书籍......
    • @user108788:arcsynthesis.org/gltut 有一系列优秀的桌面 OpenGL 教程。这有点理论重,但老实说,这是一件好事。如果一开始你能忍受学习比实际编码更多的理论,从长远来看,你会做得更好。然而,它适用于桌面 GLSL,它的语法与 OpenGL ES 2.0 / WebGL 不同(它们使用接近桌面 GLSL 1.2 版的东西)。不幸的是,我不熟悉任何特定于 WebGL 或 ES 2.0 的教程 - 我知道它们存在,但我不能推荐任何:-\
    【解决方案2】:

    OpenGL 的状态性很糟糕。如果你想使用任何缓冲区,你几乎总是需要两个调用:一个告诉 OpenGL 你想使用哪个缓冲区,第二个(第三个和更多)对缓冲区进行操作。模棱两可的缓冲区名称使整个事情更加混乱。所以,让我们快速弄清楚一些事情:

    1. 正如here 解释的那样,绑定到gl.ARRAY_BUFFER(或GL_ARRAY_BUFFER)表示指定的缓冲区是VBO
    2. gl.ELEMENT_ARRAY_BUFFER(或GL_ELEMENT_ARRAY_BUFFER)表示IBOthat link 值得一试)。一个 IBO 代表一个完整的曲面。它是构成此表面的所有顶点的索引列表。 IBO 需要在绘制调用之前绑定到 gl.ELEMENT_ARRAY_BUFFER,因为这是管道知道哪些顶点在哪里的方式。
    3. 由于有时您可能(出于某种原因)希望将多个属性存储在单独的缓冲区中,因此您可以使用单个 IBO 来索引多个 VBO。
    4. 最后,(我认为,这是您的困惑),vertexAttribPointer 告诉着色器在调用vertexAttribPointer 时绑定的 VBO 中的给定相对偏移量中查找给定类型的给定属性。这样,管道一旦拥有从 IBO 读取的正确顶点索引,就可以获取每个属性。在您的情况下,vertexAttribPointer 表示vertexPositionAttribute 来自cubeVertexPositionBuffer,颜色来自您的颜色缓冲区。为了避免在每次绘制调用之前调用vertexAttribPointer,您可以改为使用VAO 来缓存该信息。

    【讨论】:

    • 我不会说着色器从当前绑定的 VBO 中查找属性。当着色器开始运行时,当前绑定的 VBO 已无关紧要。 VBO 绑定唯一相关的是对glVertexAttribPointer (...) 的调用。
    • @AndonM.Coleman 我不认为“vertexAttribPointer 告诉着色器在当前绑定的 VBO 中查找给定类型的给定属性”意味着“在着色器时绑定的缓冲区正在运行”,但让我改变一下措辞。
    猜你喜欢
    • 2017-09-23
    • 1970-01-01
    • 2012-07-24
    • 1970-01-01
    • 1970-01-01
    • 2020-07-21
    • 1970-01-01
    • 1970-01-01
    • 2021-11-04
    相关资源
    最近更新 更多