glVertexAttribPointer GL_INVALID_OPERATION 无效 vao vbo 指针使用

Posted

技术标签:

【中文标题】glVertexAttribPointer GL_INVALID_OPERATION 无效 vao vbo 指针使用【英文标题】:glVertexAttribPointer GL_INVALID_OPERATION invalid vao vbo pointer usage 【发布时间】:2014-11-19 21:44:50 【问题描述】:

我正在尝试在安装了最新驱动程序的 NVIDIA GTX 970 上使用 OpenGL 4.4 实现延迟着色。我的代码可以直接渲染到屏幕。为了添加第二个通道,我创建了一个用于渲染场景的 FBO 和一个用于渲染最终图像的四边形。当我尝试在第一遍中不渲染任何内容并在第二遍之后绘制四边形时,四边形是可见的。当我在第一次通过时尝试渲染网格(例如立方体)时,四边形消失了。我还收到以下错误消息:

网格已加载 AssImp。 我使用以下代码创建 VBO / VAO:

void Mesh::genGPUBuffers()

    glGenBuffers(1, &vertexbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(vec3), &vertices[0], GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glGenBuffers(1, &uvbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
    glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(vec2), &uvs[0], GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glGenBuffers(1, &normalbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
    glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(vec3), &normals[0], GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glGenBuffers(1, &indexbuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexbuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned short), &indices[0], GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

我像这样渲染我的网格:

void Mesh::render()

    if (shader != nullptr)
    
        shader->use();
        shader->setModelMatrix(modelMatrix);
    

    for (int i = 0x1; i <= 0xB; i++)
    
        if (texture[i] != nullptr)
        
            glBindMultiTextureEXT(GL_TEXTURE0 + i, GL_TEXTURE_2D, texture[i]->getTextureID());
        
    

    // 1rst attribute buffer : vertices
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glVertexAttribPointer(
        0,                  // attribute
        3,                  // size
        GL_FLOAT,           // type
        GL_FALSE,           // normalized?
        0,                  // stride
        (void*)0            // array buffer offset
    );

    // 2nd attribute buffer : UVs
    glEnableVertexAttribArray(1);
    glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
    glVertexAttribPointer(
        1,                                // attribute
        2,                                // size
        GL_FLOAT,                         // type
        GL_FALSE,                         // normalized?
        0,                                // stride
        (void*)0                          // array buffer offset
    );

    // 3rd attribute buffer : normals
    glEnableVertexAttribArray(2);
    glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
    glVertexAttribPointer(
        2,                                // attribute
        3,                                // size
        GL_FLOAT,                         // type
        GL_FALSE,                         // normalized?
        0,                                // stride
        (void*)0                          // array buffer offset
    );

    // Index buffer
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexbuffer);

    // Draw the triangles
    glDrawElements(
        GL_TRIANGLES,      // mode
        (GLsizei)indexCount,    // count
        GL_UNSIGNED_SHORT,   // type
        (void*)0           // element array buffer offset
    );

    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
    glDisableVertexAttribArray(2);

使用 gDEBugger 我发现错误消息来自 glVertexAttribPointer。但是由于 gDEBugger 不支持 OpenGL 4,所以它本身会抛出很多错误,并且实际上并不能正常工作。

FBO 是这样生成的:

GLuint depthBuf;
Texture
    posTex(this),
    normTex(this),
    colorTex(this)
;

// Create and bind the FBO
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);

// The depth buffer
glGenRenderbuffers(1, &depthBuf);
glBindRenderbuffer(GL_RENDERBUFFER, depthBuf);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, static_cast<GLsizei>(resolution.x), static_cast<GLsizei>(resolution.y));

// Create the textures for position, normal and color
posTex.createGBuf(GL_TEXTURE0, GL_RGB32F, static_cast<int>(resolution.x), static_cast<int>(resolution.y));
normTex.createGBuf(GL_TEXTURE1, GL_RGB32F, static_cast<int>(resolution.x), static_cast<int>(resolution.y));
colorTex.createGBuf(GL_TEXTURE2, GL_RGB8, static_cast<int>(resolution.x), static_cast<int>(resolution.y));

// Attach the textures to the framebuffer
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuf);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, posTex.getTextureID(), 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, normTex.getTextureID(), 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, colorTex.getTextureID(), 0);

glBindFramebuffer(GL_FRAMEBUFFER, 0);

createGBuf() 函数如下所示:

void C0::Texture::createGBuf(GLenum texUnit, GLenum format, int width, int height)

    this->width = width;
    this->height = height;
    glActiveTexture(texUnit);
    glGenTextures(1, &textureID);
    glBindTexture(GL_TEXTURE_2D, textureID);
    glTexStorage2D(GL_TEXTURE_2D, 1, format, width, height);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

【问题讨论】:

顺便说一下,gDEBugger 可以很好地与 GL4 配合使用。在 AMD 购买之前,您可能正在使用旧的 gRemedy 版本。它支持现代 GL 调试输出,您可以使用它来获得与调试跟踪中列出的几乎相同的错误。我认为您的实际问题只是您没有非零顶点数组对象绑定。 调用glGetError几次,找到实际产生错误的地方 【参考方案1】:

您的代码错误可能是因为您从未生成过 VertexArrayObject, 调用 glGenVertexArray(1, 你的 vao 指针);如果您没有,现代opengl 会将其标记为错误,这可能是您正在发生的事情。生成一个顶点数组,然后用 glBindVertexArray(your vao);

绑定它

其次,您不应该在每个渲染周期都缓冲数据。这是令人难以置信的低效。您应该创建多个 VAO,将顶点数据绑定到它们然后取消绑定 vao,当您渲染相应的网格时,只需重新绑定 VAO 和 glDrawElements。

一个例子就是这样,

如果你有这样的结构顶点

struct Vertex
  vec3 position;
  vec2 uv;
  vec3 normal;
;
struct Mesh
   std::vector<Vertex> vertices;
   std::vector<unsigned int> indices;

   GLuint VAO;

   void initializeVAO();
   void Render();
;

然后你像这样初始化。

Mesh::initializeVAO()
    GLuint vertexBuffer, indiceBuffer;
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);

    glGenBuffers(1, &vertexBuffer);
    glGenBuffers(1, &indiceBuffer);

    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);

    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)sizeof(vec3));

    glEnableVertexAttribArray(2);
    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(sizeof(:vec3) + sizeof(glm::vec2)));

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indiceBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indiceBuffer);

    glBindVertexArray(0);
    glDeleteBuffers(1, &vertexBuffer);
    glDeleteBuffers(1, &indiceBuffer);

然后渲染

Mesh::Render()

     glBindVertexArray(VAO);
     glDrawElements(GL_TRIANGLES, indices.size(), 0);
     glBindVertexArray(0);

如果您有任何问题,请随时提出。

【讨论】:

非常感谢!错误确实消失了。但是当我在第一遍中渲染立方体时,四边形仍然没有渲染。明天我将尝试对新代码进行更多调试,我住的地方已经很晚了;) 场景渲染良好,无需通过。通过它不起作用:/问题:这个纹理状态使用警告是什么?这可能是我麻烦的原因吗? @MarcoAlka 该警告表示您在执行纹理功能之前没有绑定有效的纹理。在使用任何 glTextureFunctions 之前,检查您是否在生成的纹理上调用了 glBindTexture。 我来到这里是因为同样的问题,从 GL 2.0 升级了一些没有明确 VAO 的旧代码。您的回答很有帮助,除了我认为当您计划仍使用这些缓冲区进行渲染时,在初始化时 glDeleteBuffers() 是错误的。当我尝试这样做时,我的程序崩溃了;摆脱早期删除修复它。

以上是关于glVertexAttribPointer GL_INVALID_OPERATION 无效 vao vbo 指针使用的主要内容,如果未能解决你的问题,请参考以下文章

VertexArray glVertexAttribPointer GL_INVALID_VALUE 0x0501

glVertexAttribPointer GL_INVALID_OPERATION 无效 vao vbo 指针使用

glVertexAttribPointer

Opengl顶点着色器为每个顶点设置布尔值(glVertexAttribPointer)

带有 glvertexattribpointer 问题的 glsl 布局

慢跑。 OpenGL。如何更新 VBO?