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

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

本文关键字:TRIANGLES model indicesCount GL openGL 上的 未处理 异常 glDrawArrays      更新时间:2023-10-16

所以我试图在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 "GLglew.h"
#include "GLFWglfw3.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 failedn";
            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 windown";
            system("pause");
            exit(EXIT_FAILURE);
        }
        glewExperimental = GL_TRUE;
        if(glewInit() != GLEW_OK){
            std::cerr << "GLEW init failedn";
            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;
    }
};

装载机.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);
    }
};

渲染器.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);,它就会工作,我会得到一个绿色窗口。

错误在这里:

    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()实际上应该失败,尽管一些实现者忽略了这一点,并在该场景中使用了一些琐碎的着色器。