openGL glDrawArrays上的未处理异常(GL_TRIANGLES,0,model.indicesCount);呼叫

时间:2014-10-10 11:02:48

标签: c++ opengl 3d glfw glew

所以我试图在C ++中使用GLFW和GLEW编写一个简单的3D渲染引擎。但是程序在glDrawArrays(GL_TRIANGLES, 0, model.indicesCount);调用时崩溃了。我很确定我做错了什么,但我无法弄清楚需要改变/改变的地方或地点。我实际上是用Java重写了一个完美工作的引擎。

我的代码:

COMMON.H:

#ifndef _COMMON
#define _COMMON

// standard stuff
#include <iostream>
#include <list>

// openGL stuff
#include "GL\glew.h"
#include "GLFW\glfw3.h"

// my stuff
#include "DisplayManager.h"
#include "RawModel.h"
#include "Loader.h"
#include "Renderer.h"

#endif

DisplayManager.h:

#pragma once

#include "common.h"

class DisplayManager{
private:
    GLFWwindow* window;
public:
    void create(int width = 1280, int height = 720, std::string title = "Untitled"){
        if(!glfwInit()){
            std::cerr << "GLFW init failed\n";
            system("pause");
            exit(EXIT_FAILURE);
        }

        glfwWindowHint(GLFW_SAMPLES, 4);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
        window = glfwCreateWindow(width, height, title.c_str(), NULL, NULL);
        glfwMakeContextCurrent(window);

        if(!window){
            std::cerr << "Failed to create a window\n";
            system("pause");
            exit(EXIT_FAILURE);
        }

        glewExperimental = GL_TRUE;
        if(glewInit() != GLEW_OK){
            std::cerr << "GLEW init failed\n";
            system("pause");
            glfwTerminate();
            exit(EXIT_FAILURE);
        }
    }

    void update(){
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    int isCloseRequested(){
        return glfwWindowShouldClose(window);
    }

    void close(){
        glfwDestroyWindow(window);
        glfwTerminate();
    }

};

RawModel.h:

#pragma once

struct RawModel{

public:
    GLuint vaoID;
    GLuint indicesCount;

    RawModel(GLuint vaoID, GLuint indicesCount){
        this->vaoID = vaoID;
        this->indicesCount = indicesCount;
    }

};

Loader.h:

#pragma once

#include "common.h"

#define VERTEX_ATTRIB_INDEX 0
#define VERTEX_SIZE 3

class Loader{
public:
    // functions
    RawModel loadModel(const GLfloat vertices[], GLuint verticesCount){
        GLuint vaoID = createAndBindVao();
        storeFloatDataInVAO(VERTEX_ATTRIB_INDEX, vertices, verticesCount, VERTEX_SIZE);
        unbindVAO();
        return RawModel(vaoID, verticesCount);
    }

    void cleanUp(){
        std::list<GLuint>::iterator vao_it = vaos.begin();
        for(; vao_it != vaos.end(); ++vao_it){
            const GLuint vao = *vao_it;
            glDeleteVertexArrays(1, &vao);
        }

        std::list<GLuint>::iterator vbo_it = vbos.begin();
        for(; vbo_it != vbos.end(); ++vbo_it){
            const GLuint vbo = *vbo_it;
            glDeleteBuffers(1, &vbo);
        }
    }
private:
    // variables
    std::list<GLuint> vaos;
    std::list<GLuint> vbos;

    // functions
    GLuint createAndBindVao(){
        GLuint vaoID; 
        glGenVertexArrays(1, &vaoID);
        vaos.push_back(vaoID);
        glBindVertexArray(vaoID);
        return vaoID;
    }

    void storeFloatDataInVAO(const GLuint attributeIndex, const GLfloat data[], const GLuint dataLength, const GLuint chunkSize){
        GLuint vboID;
        glGenBuffers(1, &vboID);
        vbos.push_back(vboID);
        glBindBuffer(GL_VERTEX_ARRAY, vboID);
        glBufferData(GL_VERTEX_ARRAY, sizeof(GLfloat) * dataLength * chunkSize, data, GL_STATIC_DRAW);
        glVertexAttribPointer(attributeIndex, chunkSize, GL_FLOAT, GL_FALSE, 0, (void*)0);
        glBindBuffer(GL_VERTEX_ARRAY, 0);
    }

    void unbindVAO(){
        glBindVertexArray(0);
    }
};

Renderer.h:

#pragma once

#include "common.h"

#define BLACK   0.0f, 0.0f, 0.0f, 1.0f
#define WHITE   1.0f, 1.0f, 1.0f, 1.0f
#define RED     1.0f, 0.0f, 0.0f, 1.0f
#define GREEN   0.0f, 1.0f, 0.0f, 1.0f
#define BLUE    0.0f, 0.0f, 1.0f, 1.0f
#define YELLOW  1.0f, 1.0f, 0.0f, 1.0f

class Renderer{
public:
    void prepare(){
        glClear(GL_COLOR_BUFFER_BIT);
        glClearColor(YELLOW);
    };

    void render(RawModel model){
        glBindVertexArray(model.vaoID);
        glEnableVertexAttribArray(VERTEX_ATTRIB_INDEX);
        glDrawArrays(GL_TRIANGLES, 0, model.indicesCount);
        glDisableVertexAttribArray(VERTEX_ATTRIB_INDEX);
        glBindVertexArray(0);
    }
};

和Source.cpp与主函数:

#include "common.h"

static const GLfloat VERTICES[] = {
//  X       Y       Z
   -0.5f,   0.5f,   0,
   -0.5f,  -0.5f,   0,
    0.5f,   0.5f,   0
};

int main(){

    DisplayManager display;
    display.create();

    Loader loader;
    RawModel model = loader.loadModel(VERTICES, 3);

    Renderer renderer;

    // main loop
    while(!display.isCloseRequested()){
        renderer.prepare();
        renderer.render(model);
        display.update();
    }

    loader.cleanUp();
    display.close();
    return EXIT_SUCCESS;
}

如果我评论glDrawArrays(GL_TRIANGLES, 0, model.indicesCount);它的接缝有效,我会看到绿色窗口。

1 个答案:

答案 0 :(得分:3)

错误在于:

    glBindBuffer(GL_VERTEX_ARRAY, vboID);
    glBufferData(GL_VERTEX_ARRAY, sizeof(GLfloat) * dataLength * chunkSize, data, GL_STATIC_DRAW);
    glVertexAttribPointer(attributeIndex, chunkSize, GL_FLOAT, GL_FALSE, 0, (void*)0);
    glBindBuffer(GL_VERTEX_ARRAY, 0);

GL_VERTEX_ARRAY不是OpenGL中的有效缓冲区目标,正确的是GL_ARRAY_BUFFER。因此,这些命令都应该生成GL错误。 attrib指针函数将生成GL_INVALID_OPERATION,因为在调用时没有约束GL_ARRAY_BUFFER,其他函数应该只生成GL_INVALID_ENUM。现在您基本上有一个未初始化的顶点属性指针,稍后您启用该属性数组并尝试从中绘制,从而导致崩溃。

另一件事:我的代码中没有看到任何着色器。着色器在您使用的核心配置文件中是必需的。现在glDrawElements()实际应该失败,尽管有些实现者会忽略它并在该场景中使用一些简单的着色器。