【问题标题】:How does glDrawArrays know what to draw?glDrawArrays 怎么知道要画什么?
【发布时间】:2013-10-06 18:52:06
【问题描述】:

我正在关注一些初学者的 OpenGL 教程,对这段代码的 sn-p 有点困惑:

glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject); //Bind GL_ARRAY_BUFFER to our handle
glEnableVertexAttribArray(0); //?
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); //Information about the array, 3 points for each vertex, using the float type, don't normalize, no stepping, and an offset of 0. I don't know what the first parameter does however, and how does this function know which array to deal with (does it always assume we're talking about GL_ARRAY_BUFFER?

glDrawArrays(GL_POINTS, 0, 1); //Draw the vertices, once again how does this know which vertices to draw? (Does it always use the ones in GL_ARRAY_BUFFER)

glDisableVertexAttribArray(0); //?
glBindBuffer(GL_ARRAY_BUFFER, 0); //Unbind

我不明白 glDrawArrays 如何知道要绘制哪些顶点,以及与 glEnableVertexAttribArray 相关的所有内容。有人能说明一下情况吗?

【问题讨论】:

    标签: opengl graphics rendering vertex


    【解决方案1】:

    glBindBuffer 的调用告诉OpenGL 在需要GL_ARRAY_BUFFER 时使用vertexBufferObject

    glEnableVertexAttribArray表示希望OpenGL使用顶点属性数组;如果没有此调用,您提供的数据将被忽略。

    glVertexAttribPointer,正如您所说,告诉 OpenGL 如何处理提供的数组数据,因为 OpenGL 本身并不知道该数据的格式。

    glDrawArrays使用以上所有数据来绘制点。

    请记住,OpenGL 是一个大型状态机。大多数对 OpenGL 函数的调用都会修改您无法直接访问的全局状态。这就是代码以glDisableVertexAttribArrayglBindBuffer(..., 0) 结尾的原因:您必须在使用完该全局状态后将其恢复。

    【讨论】:

    • 好的,最后一件让我困惑的事情。 glDrawArrays 如何知道要使用哪个顶点属性。我假设我可以有多个,所以我可以启用索引 1:glEnableVertexAttribArray(1),然后使用 glVertexAttribPointer() 给出一些属性,但是在我的示例中 glDrawArrays 如何知道使用索引 0 处的属性解释数据的格式。
    • @handuel:它使用 all 启用的顶点属性。每个属性的含义是通过顶点着色器的编程精确定义的。
    • @datenwolf 好的,所以我设置了顶点属性,然后着色器程序使用这些 + 中的数据/(指向?) GL_ARRAY_BUFFER 生成输出,由 glDrawArrays 绘制?希望这是正确的,因为在那种情况下我终于明白了。
    • @handuel:实际上顶点着色器是在调用 glDrawArrays 之后开始工作的。 glDrawArrays 只是将使用glEnableVertexAttribArray 启用的每个活动顶点属性的数据传递到绘图队列中。在顶点着色器中,每个顶点属性数组都有一个绑定,着色器决定什么变成屏幕位置,什么颜色等等。
    • @handuel:当glVertexAttribPointer(attrib_index, …) 被调用时,glBindBuffer(GL_ARRAY_BUFFER, …) 绑定的缓冲区将绑定到glVertexAttribPointerfirst 参数指定的顶点属性。要将另一个缓冲区绑定到另一个属性,请执行另一个 glBindBuffer(GL_ARRAY_BUFFER, …); glVertexAttribPointer(…);。 –– 不需要调用glEnableVertexAttribArray 来进行缓冲区和属性之间的绑定。但是启用顶点属性数组会使glDraw… 调用使用启用的属性。
    【解决方案2】:

    DrawArrays 从ARRAY_BUFFER 获取数据。

    根据您在glVertexAttribPointer 中的设置“映射”数据,它告诉您顶点的定义是什么。

    在您的示例中,您在位置 0 有一个顶点属性 (glEnableVertexAttribArray)(通常可以有 16 个顶点属性,每个 4 个浮点数)。 然后你告诉每个属性将通过从位置 0 开始从缓冲区中读取 3 个 GL_FLOATS 来获得。

    【讨论】:

    • 谢谢,这有助于我理解。 glEnableVertexAttribArray 有什么作用?
    • @handuel 更新了答案,请参阅 arcsynthesis.org 的教程
    • @fen 但是,如果 drawArrays 从 ARRAY_BUFFER 获取数据,是否意味着我不能在着色器中使用来自多个缓冲区的数据?因为您不能同时将多个缓冲区绑定到 ARRAY_BUFFER。顺便说一句,发布的链接不再起作用。
    猜你喜欢
    • 1970-01-01
    • 2017-08-04
    • 2021-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-01
    • 1970-01-01
    相关资源
    最近更新 更多