【问题标题】:The 4th argument in glDrawElements is WHAT?glDrawElements 中的第四个参数是什么?
【发布时间】:2014-02-11 15:32:07
【问题描述】:

我对 glDrawElements() 感到困惑。我正在关注一个教程,它说glDrawElements() 的第四个参数是“GL_ELEMENT_ARRAY_BUFFER 内的偏移量”。但是如果我将 0 作为偏移量传递,我会遇到错误“访问破坏:尝试读取 0x0000”。

所以我进一步深入研究了这个问题,发现 OpenGL 文档对第四个参数提供了两种不同的定义:

第一:

indices:指定一个字节偏移量(转换为指针类型)到 绑定到 GL_ELEMENT_ARRAY_BUFFER 的缓冲区开始读取索引 来自。

(在这里找到:https://www.opengl.org/wiki/GLAPI/glDrawElements

第二:

indices:指定一个指向索引存储位置的指针。

(在这里找到:https://www.opengl.org/sdk/docs/man4/index.php 在这里:http://www.khronos.org/opengles/sdk/docs/man/xhtml/glDrawElements.xml)

哪一个是真的,如何正确使用?

编辑:这是我的代码:http://pastebin.com/fdxTMjnC

【问题讨论】:

    标签: c++ opengl


    【解决方案1】:

    两者都是正确的。这两种情况与索引缓冲区如何上传到 GL 硬件以及如何使用它进行绘制有关。这些描述如下:

    (1)不使用VBO(顶点缓冲对象):

    在这种情况下,参数表示指向索引数组的指针。每次调用glDrawElements,缓冲区都会上传到GL HW。

    (2) 使用 VBO:

    对于这种情况 - 请参阅 Index 的定义为“指定字节偏移量(转换为指针类型)到绑定到 GL_ELEMENT_ARRAY_BUFFER​的缓冲区中以开始读取索引”。这意味着数据已经使用glBufferData单独上传,并且索引仅用作偏移量。每次调用glDrawElements 时,不会上传缓冲区,但如果需要,只能更改偏移量。这使其更加高效,尤其是在涉及大量顶点的情况下。

    【讨论】:

    • 我正在使用 VBO...但我得到“访问破坏读取 0x00”。这意味着我的 VBO 设置不正确?
    • 我发现:除了 VBO(顶点缓冲区对象)和 EBO(元素数组缓冲区)之外,您还需要创建 VAO(顶点数组对象)才能正常工作
    • 是的,你是对的:根据上下文,这两个定义都是正确的。 +1 讨论效率
    【解决方案2】:

    如果你使用direct drawing,那么

    indices​定义了索引缓冲区对象的偏移量(绑定到 GL_ELEMENT_ARRAY_BUFFER​,存储在 VAO 中)以开始读取数据。

    也就是说,你需要创建VAO,绑定它,然后使用glDrawElements()进行渲染

    【讨论】:

    • VAO 是关键!我正在创建 VAO,但在创建 EBO 之后。进一步向其他人澄清:您需要在 EBO 和 VBO 之前创建 VAO,并将这些缓冲区绑定到 VAO 才能正常工作..
    • @CashifIlyas 好的,在这种情况下,您可能需要查看this question and answers
    • 从技术上讲,您不必执行任何这些操作。这取决于您的 OpenGL 版本和上下文。在兼容性配置文件中,您可以使用客户端内存而不是缓冲区对象。同样,在这种情况下,您根本不需要 VAO。当没有绑定元素数组缓冲区时,它告诉 GL 从您作为第 4 个参数传递的地址读取内存;当一个 绑定时,它告诉 GL 使用由绑定元素数组缓冲区定义的内存中的偏移量。
    【解决方案3】:

    该参数的解释取决于内部数组是否已绑定在 GL 状态机中。如果绑定了这样的数组,则它是一个偏移量。如果没有绑定这样的数组,则它是指向您的内存的指针。

    使用内部数组的性能更高,因此最近的文档(尤其是 wiki)强烈倾向于这种用法。然而,有一个很长的歌舞来设置它们。

    绑定或解绑内部数组的函数是glBindVertexArray。查看这些相关功能的文档:

    • glGenVertexArrays
    • glBufferData

    (这是一个不完整的列表。我必须运行,所以我必须稍后进行编辑。)

    【讨论】:

      【解决方案4】:

      opengl.org/wiki 上的内容很可能是正确的。我可以从工作项目中告诉你,它确实定义如下:

      Specifies a byte offset (cast to a pointer type) into the buffer bound to
      GL_ELEMENT_ARRAY_BUFFER​ to start reading indices from.
      

      只需将一些整数转换为 GLvoid* 就可以了。至少对于现代可编程管道来说,我不知道固定管道(也不应该使用它!)。

      如果您使用的是现代管道,如果没有更多信息,我敢打赌实际函数没有正确加载。那是 GLEW 没有正确初始化,或者如果您正在手动执行操作,试图在 win32 上使用 GetProcAddress(因为 glDrawElements 是自 1.1 以来的核心,并且不应在 win32 上使用 GetProcAddress 加载 1.0/1.1)。

      确实请注意,您应该像其他人所说的那样将元素缓冲区绑定到绑定点。尽管在实践中您可以在不绑定 VAO 的情况下摆脱它。我已经在 NVidia、AMD 甚至 Intel 上做到了这一点。但在生产中,您应该使用 VAO。

      【讨论】:

      • 我在 Windows 机器上使用 OpenGL 3.1.0 和 GLEW 1.10.0
      • 我建议打印您的函数指针(从而检查它们是否为 0x0000)并查看 GLEW 是否已正确初始化。如果两者都检出,那肯定是其他问题,或者是我们在此处看不到的代码中的其他内容,或者您​​没有绑定元素缓冲区,或者您正在做其他奇怪的巫毒教相关事情。
      • 还有一点:如果我使用glDrawArrays(),那么它可以正常工作。这意味着 GLEW 初始化良好。对吗?
      • 可能是,可能不是,我不知道 GLEW 如何在内部处理错误。你应该使用官方的方式来检查初始化+打印出相关的函数指针来检查NULL不会有坏处。
      猜你喜欢
      • 1970-01-01
      • 2012-08-14
      • 2014-06-02
      • 1970-01-01
      • 2018-09-21
      • 1970-01-01
      • 2010-11-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多