glDrawElements的例外情况

时间:2014-04-08 14:40:53

标签: c++ opengl-es opengl-es-2.0

我正在尝试将模型加载到我的项目中,并在glDrawElements处获得异常。 我读取了模型文件(.nfg),并将顶点和索引保留在矢量中,并使用Vertex Buffer Object来绑定我的模型。

我试过this: 我从(GLvoid*)(sizeof(Vector3) * x)修改了第四个参数 到了(GLvoid*)(offset(Vertex, attribute)),但没有做任何事情(在链接中,问题是他在第4个参数中发送了内存地址,我想也许我正在向错误的属性发送错误的参数,实际上,在显示模型时会出现问题。

我使用的是OpenGL ES 2.0,而且我没有为Android或iOS做过这个项目;目前在Windows 8.1上的Visual Studio 2013中工作

模型加载器:

void loadModelNfg(const std::string &filename, 
                    GLuint &vbo, GLuint &ibo, GLuint &num, Shaders shaders){

    // put here the verteces and indices from the file
    std::vector<Vertex> vertices;
    std::vector<GLushort> indices;

    _loadModelNfg(filename, vertices, indices);
    std::cout << "Mesh Loader: loaded file: " << filename << "\n";

    // creates OpenGL objects necessary for drawing
    GLuint gl_vertex_buffer_object, gl_index_buffer_object;

    // vertex buffer object -> object in which to keep the vertices
    glGenBuffers(1, &gl_vertex_buffer_object);
    glBindBuffer(GL_ARRAY_BUFFER, gl_vertex_buffer_object);

    glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), 
                    &vertices[0], GL_STATIC_DRAW);

    glBindBuffer(GL_ARRAY_BUFFER, 0);

    // index buffer object -> object in which to keep the indices
    glGenBuffers(1, &gl_index_buffer_object);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gl_index_buffer_object);

    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), 
                    &indices[0], GL_STATIC_DRAW);

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    vbo = gl_vertex_buffer_object;
    ibo = gl_index_buffer_object;
    num = indices.size();
}

调用上一个函数:

// for now, global variables:
GLuint vbo, ibo, num;
Shader myShaders;

int Init ( ESContext* esContext ) {
    glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );

    // this one works: tried with a triangle
    int ret = myShaders.Init("../Resources/Shaders/TriangleShaderVS.vs", 
                    "../Resources/Shaders/TriangleShaderFS.fs");
    if (ret == 0)
        loadModelNfg("../../ResourcesPacket/Models/Bila.nfg", vbo, ibo, num, myShaders);

    return ret;
}

绘制模型:

void Draw(ESContext* esContext) {
    Matrix world;
    world.SetIdentity();
    Matrix view = c.getView();
    Matrix persp = c.getPerspective();
    Matrix trans = world * view *persp;

    glClear(GL_COLOR_BUFFER_BIT);
    glUseProgram(myShaders.program);

    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);

    if (myShaders.positionAttribute != -1) {
            glEnableVertexAttribArray(myShaders.positionAttribute);
            glVertexAttribPointer(myShaders.positionAttribute, 3, GL_FLOAT, 
                    GL_FALSE, sizeof(Vertex), (GLvoid*)(offsetof(Vertex, pos)));
    }
    if (myShaders.normalAttribute != -1) {
            glEnableVertexAttribArray(myShaders.normalAttribute);
            glVertexAttribPointer(myShaders.normalAttribute, 3, GL_FLOAT, 
                    GL_FALSE, sizeof(Vertex), (GLvoid*)(offsetof(Vertex, norm)));
    }
    if (myShaders.binormalAttribute != -1) {
            glEnableVertexAttribArray(myShaders.binormalAttribute);
            glVertexAttribPointer(myShaders.binormalAttribute, 3, GL_FLOAT, 
                    GL_FALSE, sizeof(Vertex), (GLvoid*)(offsetof(Vertex, binorm)));
    }
    if (myShaders.tangentAttribute != -1) {
            glEnableVertexAttribArray(myShaders.tangentAttribute);
            glVertexAttribPointer(myShaders.tangentAttribute, 3, GL_FLOAT, 
                    GL_FALSE, sizeof(Vertex), (GLvoid*)(offsetof(Vertex, tgt)));
    }
    if (myShaders.texcoordAttribute != -1) {
            glEnableVertexAttribArray(myShaders.texcoordAttribute);
            glVertexAttribPointer(myShaders.texcoordAttribute, 2, GL_FLOAT, 
                    GL_FALSE, sizeof(Vertex), (GLvoid*)(offsetof(Vertex, uv)));
    }
    if (myShaders.colorAttribute != -1) {
            glEnableVertexAttribArray(myShaders.colorAttribute);
            glVertexAttribPointer(myShaders.colorAttribute, 3, GL_FLOAT, 
                    GL_FALSE, sizeof(Vertex), (GLvoid*)(offsetof(Vertex, col)));
    }
    if (myShaders.MVPuniform != -1) {
            glUniformMatrix4fv(myShaders.MVPuniform, 1, GL_FALSE, (GLfloat*) trans.m);
    }

    // HERE GETS EXCEPTION
    glDrawElements(GL_TRIANGLES, num, GL_UNSIGNED_SHORT, (GLvoid*) 0);

    eglSwapBuffers (esContext->eglDisplay, esContext->eglSurface);
}

我不确定我是否正确绑定了loadModelNfg()函数中的缓冲区。

问题出在哪里以及如何解决?

编辑:

GL_VENDOR:   Imagination Technologies (Host GL: 'Intel'); 
GL_RENDERER: PowerVR PVRVFrame 4.2SGX 530 (Host 'Intel(R) HD Graphics 400'); 
GL_VERSION:  OpenGL ES 2.0 (SDK build: 2.04.24.0809)

编辑:

我用try-catch语句包围了这个函数,但是在调用它时它仍然会中断:

try {
    glDrawElements(GL_TRIANGLES, num, GL_UNSIGNED_SHORT, (GLvoid*)0);
}
catch (const std::exception& e) {
    std::cout << e.what() << "\n";
}

我忘了提及项目/解决方案构建成功(清理后或通过重建)。

1 个答案:

答案 0 :(得分:2)

在得知OpenGL没有抛出异常后,我开始研究它如何处理错误。我发现它&#34;返回&#34;错误代码(如果成功,则为0),可以使用glGetError()找到。

通过代码glGetError(),我发现错误是由glUseProgram(myShaders.program);引起的。

知道了,我查看了使用myShaders变量的函数,我发现在调用loadModelNfg("../../ResourcesPacket/Models/Bila.nfg", vbo, ibo, num, myShaders);之后,变量发生了变化。

记住我不再使用它,我只是删除它,一切都很好。

奇怪的是,我没有在该函数的任何地方修改myShaders变量(问题中的代码是最后一个)。我认为问题在于我没有声明参数const Shaders shaders

所以,结论是: 在代码中使用glGetError()和断点来查找真正的问题。它可能不是它破碎的地方!

PS:我希望我能把它作为答案。如果不是,我会更新问题。