简体   繁体   中英

openGL Unhandled exception on glDrawArrays(GL_TRIANGLES, 0, model.indicesCount); call

So I'm trying to write a simple 3D rendering engine using GLFW and GLEW in C++. However the program crashes on glDrawArrays(GL_TRIANGLES, 0, model.indicesCount); call. I'm pretty sure I'm doing something wrong but I can't figure out where or what needs to be changed/altered. I'm actually rewriting a perfectly working engine from Java.

My code:

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);
    }
};

and the Source.cpp with the main function:

#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;
}

If I comment out the glDrawArrays(GL_TRIANGLES, 0, model.indicesCount); it seams to be working and I get a green window.

The error is here:

  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 is not a valid buffer target in OpenGL, the correct one is GL_ARRAY_BUFFER . As a consequence, these commands all should generate a GL error. The attrib pointer function will should generate GL_INVALID_OPERATION , since no GL_ARRAY_BUFFER is bound at the time of the call, the others should just generate GL_INVALID_ENUM . Now you have basically an uninitialized vertex attribute pointer, you later enable that attribute array and try to draw from it, resulting in the crash.

Another thing: I don't see any shaders in your code. Shaders are mandatory in the core profile, which you use. Now glDrawElements() actually should fail , although some implementors ignore that and use some trivial shaders in that scenario.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM