尽管有 vao,但 glVertexAttribPointer 导致无效操作错误

Posted

技术标签:

【中文标题】尽管有 vao,但 glVertexAttribPointer 导致无效操作错误【英文标题】:glVertexAttribPointer causing Invalid Operation error despite having vao 【发布时间】:2015-03-03 00:19:04 【问题描述】:

可能是一个简单的问题,因为我可能搞砸了一些愚蠢的事情。

我一直在尝试在空闲时间让渲染系统在我的旧笔记本电脑上运行。我遇到了问题,并认为这与我的程序的原始设计有关,但现在我不太确定是不是这样。我已将渲染调用简化为一个简单的渲染三角形示例,但仍然出现错误。

void RenderSystem::Render()

    glClear( GL_COLOR_BUFFER_BIT );
    GLuint vao;
    glGenVertexArrays(1, &vao);
    glBindVertexArray( vao );

    glUseProgram( shaderProgram );
    CheckForError();
    glEnableVertexAttribArray( coord3dAttrib );
    CheckForError();

    GLfloat triangle[] = 
        0.0, 0.8, 0.0,
        -0.8, -0.8, 0.0,
        0.8, -0.8, 0.0,
    ;

    glVertexAttribPointer(
        coord3dAttrib,
        3,
        GL_FLOAT,
        GL_FALSE,
        0,
        triangle
    );
    CheckForError();

    glDrawArrays(GL_TRIANGLES, 0 , 3);
    CheckForError();

    glDisableVertexAttribArray( coord3dAttrib );
    CheckForError();

    SDL_GL_SwapWindow( window );

忽略过多的 CheckForError 函数调用——这只是为了查明是哪个函数导致了错误。它肯定发生在我调用 glVertexAttribPointer 之后。

值得注意的是,所有着色器和程序都已正确编译。上下文已初始化并由 SDL2 处理,并且在上下文初始化方面没有错误。我得到的唯一奇怪的错误是调用 SDL_GL_SetSwapInterval(0) 以关闭 vsync 时枚举数无效。

此外,这台笔记本电脑是一台旧笔记本电脑,我开始考虑这样一个事实,即这台电脑的驱动程序/硬件可能太旧而无法实际执行这种更现代的 GL 渲染风格。在这种情况下,有没有一种好方法来测试我应该在这个硬件上运行哪个版本的 GL? (我在 Crunchbang,一个 linux debian 发行版。Iirc,我已经正确设置并安装了很多驱动程序和头文件,所以我认为它应该可以工作,但如果驱动程序问题导致这种情况,我会进一步研究。 )

有什么线索吗?我假设我错过了一些基本的东西,因为我上次使用 OpenGL 已经有一段时间了。

【问题讨论】:

VAO 不需要指向 VBO 的数据吗? 我真的不确定。我曾经有一个 VBO,但当我想简化渲染过程时将其删除。我会尝试添加一个 VBO,但是当我之前有一个时,它仍然会导致无效操作错误。当我删除所有这些以尝试渲染一个简单的三角形时,它仍然给了我错误。我在网上看到了一些关于在没有 VAO 时如何发生此错误的帖子,并重新添加了 VAO 初始化调用,以查看它是否可以修复错误。 在核心配置文件中让顶点属性指针指向客户端内存是无效的。 "如果指针不为 NULL,则必须将非零命名缓冲区对象绑定到 GL_ARRAY_BUFFER 目标(请参阅 glBindBuffer),否则会生成错误。指针被视为缓冲区对象数据存储中的字节偏移量。缓冲区对象绑定 (GL_ARRAY_BUFFER_BINDING) 保存为索引索引的通用顶点属性数组状态 (GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)。” 对于兼容性配置文件,这种行为是放宽的,但我不知道你有什么样的配置文件。跨度> 对,当你这样说的时候,它更有意义。我正在尝试访问硬件无法访问的内存池。 【参考方案1】:

我认为你的绑定有问题。您只需为 VAO 生成一个名称,绑定并设置您的缓冲区,然后使用分配的名称稍后绑定它。

因此,您应该执行以下操作。

    以某种初始化方法(当您设置缓冲区时)为您的 VAO 变量生成名称:

    GLuint vao; // make this accessible in global scope or through some class
    glGenVertexArrays(1, &vao);
    

    像以前一样在渲染方法中调用绑定函数,使用之前分配给变量vaoname

    glUseProgram( shaderProgram );
    glBindVertexArray( vao );
    

我想这可能是你的答案,最后,这就是我习惯于在书籍和教程中看到 VAO 的处理方式。

【讨论】:

以上是关于尽管有 vao,但 glVertexAttribPointer 导致无效操作错误的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL:VAO/VBO 混淆

VAO 中的 C++ GLSL 多个 IBO

多网格模型的 vao 管理

是否可以将活动着色器程序保存在 VAO 中?如果可以,如何?

为两个不同的 VAOS 使用两个不同的着色器

顶点着色器 VAO 是不是需要 VBO?