【问题标题】:Java (LWJGL) - Is binding a specific VBO necessary before/during drawing?Java (LWJGL) - 在绘图之前/期间是否需要绑定特定的 VBO?
【发布时间】:2013-12-29 11:15:05
【问题描述】:

我正在尝试实现顶点缓冲区对象 (VBO),作为通过轻量级 Java 游戏库 (LWJGL) 使用 openGL 进行 3D 渲染的一种方式。我的特定程序允许每个具有图形表示的对象在屏幕上呈现和绘制自身。我的问题不在于这种渲染管理在什么情况下是否是一个好主意。我对LWJGL本身的绘制过程比较感兴趣。我准备了简单的绘制方法,比如说点云:

public void drawVBO(){
        // enable Vertex Arrays (VBOs)
        glEnableClientState(GL_VERTEX_ARRAY);

        // tell OpenGL to draw the data supplied by the pointer method
        // as points.length amount of points
        glDrawArrays(GL_POINTS, 0, points.length);
        // otherwise use GL_LINES, GL_TRIANGLES, GL_QUADS, etc. 
        // (http://wiki.delphigl.com/index.php/glDrawArrays)

        // Disable Vertex Arrays (VBOs)
        glDisableClientState(GL_VERTEX_ARRAY);
    }

    public void drawVBOBound(){
        // enable Vertex Arrays (VBOs)
        glEnableClientState(GL_VERTEX_ARRAY);
        // tell OpenGL to use our VBO
        glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);

        // tell OpenGL to draw the data supplied by the pointer method
        // as points.length amount of points
        glDrawArrays(GL_POINTS, 0, points.length);
        // otherwise use GL_LINES, GL_TRIANGLES, GL_QUADS, etc. 
        // (http://wiki.delphigl.com/index.php/glDrawArrays)

        // Unbind the VBO
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        // Disable Vertex Arrays (VBOs)
        glDisableClientState(GL_VERTEX_ARRAY);
    }

它们之间的区别在于对象自身 VBO 的绑定和解除绑定。在我渲染和绘制大量不同点云对象的场景中,我将绑定多个顶点缓冲区。这表明我必须明确告诉 openGL 在渲染过程中使用哪个顶点缓冲区(如方法drawVBOBound 所示)。否则,openGL 将通过当前绘图对象绘制每个绑定的顶点缓冲区,该对象在程序的一个渲染/绘图周期内等于多个绘图(没有人会想要这样)。这个假设正确吗?

【问题讨论】:

  • 是的,如果你只有一个 VBO,那么一直绑定它就足够了。尽管正如您所说,如果您有多个 VBO,则需要绑定它们,因为一次只能绑定一个 VBO。

标签: java opengl bind lwjgl vbo


【解决方案1】:

您的两个代码变体缺少要点:顶点属性指针。

glDraw* 函数从不关心当前在GL_ARRAY_BUFFER 绑定点绑定的内容。真正关心的是顶点数组(对于glDrawElements* 变体,当前绑定的GL_ELEMENT_ARRAY_POINTER)。

您目前缺少的是 GL_ARRAY_BUFFER 绑定在您设置顶点 attrob 指针时是相关的(在您的情况下可能通过 glVertexPointer )。在设置时对 VBO 绑定的引用将成为 指针的一部分

因此,当您真的想从不同的 VBO 中进行绘制时,您必须重新指定属性指针(并为此重新绑定 VBO)。请注意,现代 GL 使用 VAOs 封装顶点数组状态并允许通过单个函数调用在不同的 VA 指针集之间进行切换。

附带说明:您也不需要一直启用和禁用这些属性指针。只要您不打算在没有 GL_VERTEX 属性数组的情况下对glDraw* 进行任何调用,就可以将其保留。正如 Martijn Courteaux 已经指出的那样,它不会启用或禁用 VBO,它只是告诉 GL 将使用数组的哪些属性,以及它将使用当前值(对于绘制的所有顶点将是常量)然后打电话)。

【讨论】:

  • 这非常有用。我还帮我解决了另一个问题。现在我启用客户端状态,绑定特定的顶点缓冲区并定义指针。我不知道一旦指定,openGL 仍然假定属性指针定义。知道代码比以前更好更干净,并且不会不必要地浪费 CPU 使用时间和内存。谢谢。
【解决方案2】:

不。一次只能绑定一个 VBO。那是您使用

绑定的最后一个
glBindBuffer(GL_ARRAY_BUFFER, vbo);

如果您不取消绑定缓冲区,那么它将在您绑定下一个缓冲区时自动取消绑定。这意味着您不会“一次绘制多个 VBO”。

接下来,GL_VERTEX_ARRAY 是保存位置坐标的内置顶点属性的名称。所以你的评论:

// Disable Vertex Arrays (VBOs)

技术上不正确。您在着色器中禁用该属性,这并没有真正禁用 VBO。

【讨论】:

  • 好吧,我并不是说它们必须同时在 Java 中使用。他们在openGL中是相当熟悉的。您的回答不是问题的答案,但是,它指出了我解释的一些解释性部分。
  • 那么,你的问题是什么?
  • 问题是绑定是否必要。 Vallentin 已经指出,这是对初始帖子的直接评论。当您添加一些旁注时,derhass 给出了更深入的回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-24
  • 1970-01-01
  • 2013-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多