带有 GLFW 和 GLEW 的 OpenGL 应用程序崩溃

Posted

技术标签:

【中文标题】带有 GLFW 和 GLEW 的 OpenGL 应用程序崩溃【英文标题】:OpenGL app with GLFW and GLEW crashes 【发布时间】:2014-01-30 05:07:24 【问题描述】:

问题: 我尝试编写一个类来绘制可点击的矩形,问题是因为我开始在程序中使用新的 OpenGL 版本(4.0),它不会渲染,并且在读取位置 0x00000000 时给我运行时错误错误。 我将在底部包含类的代码以及主循环。

GUI::GUI(std::string name, int top, int left,int heigh, int width, bool isvisible, void(_cdecl * func)())

    Name=name;
    Top=top;
    Left=left;
    Heigh=heigh;
    Width=width;
    BackColor = struct_RGB();
    glClearColor(0.0f, 0.0f, 0.4f, 1.0f);
    BackDrawFunc=func;
    Visibility=isvisible;
    GuiObj = std::vector<GUIOBJ *>();

    vertices = std::vector<float>();
    vertices.clear();

    for(unsigned int i=0; i<GuiObj.size(); i++)
    
        GuiObj[i]->addVertices();
    ;

    glGenVertexArrays(1, &VertexArrayID);
    glBindVertexArray(VertexArrayID);

    // Generate 1 buffer, put the resulting identifier in vertexbuffer
    glGenBuffers(1, &VBO);

    // The following commands will talk about our 'vertexbuffer' buffer
    glBindBuffer(GL_ARRAY_BUFFER, VBO);

    glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float), vertices.data(), GL_STATIC_DRAW);

    program = LoadShaders("res/VertexShader.glsl", "res/FragmentShader.glsl");



void GUI::Draw()

    glClear(GL_COLOR_BUFFER_BIT);
                 // Use our shader
                glUseProgram(program);
                // 1rst attribute buffer : vertices
                glBindBuffer(GL_ARRAY_BUFFER, VBO);
                glEnableVertexAttribArray(0);
                glVertexAttribPointer(
                        0,                  // attribute 0. No particular reason for 0, but must match the layout in the shader.
                        vertices.size(),                  // size
                        GL_FLOAT,           // type
                        GL_FALSE,           // normalized?
                        0,                  // stride
                        (void*)0            // array buffer offset
                );
                // Draw the triangle !
                glDrawArrays(GL_TRIANGLES, 0, vertices.size()); // 3 indices starting at 0 -> 1 triangle
                printf("drawing\n");
                glDisableVertexAttribArray(0);






void main()

    init();

    //Main Loop
        while(!glfwWindowShouldClose(Window))
        
            if (glfwGetKey(Window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
                glfwSetWindowShouldClose(Window, GL_TRUE);

            Test->Draw();
           glfwSwapBuffers(Window);
           glfwPollEvents();
        
    //Termination
        glfwTerminate();

编辑: 我将所有代码复制到同一个文件中,错误已解决,但仍无法呈现

#include "extincludes.h"
#include <vector>
#include <fstream>
#include <sstream>

GLFWwindow* Window;

typedef unsigned int GLuint;

GLuint VertexArrayID;
GLuint VBO;
GLuint program;

GLuint LoadShaders(const char * vertex_file_path,const char * fragment_file_path)

    // Create the shaders
    GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
    GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);

    // Read the Vertex Shader code from the file
    std::string VertexShaderCode;
    std::ifstream VertexShaderStream = std::ifstream(vertex_file_path, std::ios::in);
    if (!VertexShaderStream.is_open()) VertexShaderStream.open(vertex_file_path, std::ios::in);
    if(VertexShaderStream.is_open())
    
        std::string Line = "";
        while(getline(VertexShaderStream, Line))
            VertexShaderCode += "\n" + Line;
        VertexShaderStream.close();
     else
        printf("Couldn't open VertexShader");

    // Read the Fragment Shader code from the file
    std::string FragmentShaderCode;
    std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
    if(FragmentShaderStream.is_open())
        std::string Line = "";
        while(getline(FragmentShaderStream, Line))
            FragmentShaderCode += "\n" + Line;
        FragmentShaderStream.close();
     else
        printf("Couldn't open FragmentShader");

    GLint Result = GL_FALSE;
    int InfoLogLength;

    // Compile Vertex Shader
    printf("Compiling shader : %s\n", vertex_file_path);
    char const * VertexSourcePointer = VertexShaderCode.c_str();
    glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
    glCompileShader(VertexShaderID);

    // Check Vertex Shader
    glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    std::vector<char> VertexShaderErrorMessage(InfoLogLength);
    glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
    fprintf(stdout, "%s\n", &VertexShaderErrorMessage[0]);

    // Compile Fragment Shader
    printf("Compiling shader : %s\n", fragment_file_path);
    char const * FragmentSourcePointer = FragmentShaderCode.c_str();
    glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
    glCompileShader(FragmentShaderID);

    // Check Fragment Shader
    glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    std::vector<char> FragmentShaderErrorMessage(InfoLogLength);
    glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
    fprintf(stdout, "%s\n", &FragmentShaderErrorMessage[0]);

    // Link the program
    fprintf(stdout, "Linking program\n");
    GLuint ProgramID = glCreateProgram();
    glAttachShader(ProgramID, VertexShaderID);
    glAttachShader(ProgramID, FragmentShaderID);
    glLinkProgram(ProgramID);

    // Check the program
    glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
    glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    std::vector<char> ProgramErrorMessage( glm::max(InfoLogLength, int(1)) );
    glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
    fprintf(stdout, "%s\n", &ProgramErrorMessage[0]);

    glDeleteShader(VertexShaderID);
    glDeleteShader(FragmentShaderID);

    return ProgramID;


void main()


    //GLFW
    printf("started init of GLFW \n");
    if (!glfwInit())
        printf("startup of GLFW errored \n");
    printf("started GLFW \n");
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //excluding old openGL functionality

    Window = glfwCreateWindow(640, 768, "Simple example", NULL, NULL);
    printf("attempt to create window \n");
    if (!Window)
    
        glfwTerminate();
        exit(EXIT_FAILURE);
    
    glfwMakeContextCurrent(Window);
    printf("Init of GLFW done \n");
    //GLEW
        printf("start init of GLEW \n");
    glewExperimental = true; // Needed for core profile
    printf("using experimental version of GLEW\n");
    if (glewInit() != GLEW_OK) 
                printf("Failed to initialize GLEW\n");

        
    printf("done with GLEW\n");

    if (glfwGetCurrentContext()!=Window)
        printf("context error");

    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);


    glGenVertexArrays(1, &VertexArrayID);
    glBindVertexArray(VertexArrayID);
    program = LoadShaders("res/VertexShader.glsl", "res/FragmentShader.glsl");

    std::vector<float> vertices = std::vector<float>();
    vertices.clear();

    //triangle 1
    vertices.push_back(1);
    vertices.push_back(1);

    vertices.push_back(0);
    vertices.push_back(1);

    vertices.push_back(0);
    vertices.push_back(3);
    //triangle 2
    vertices.push_back(1);
    vertices.push_back(1);

    vertices.push_back(0);
    vertices.push_back(1);

    vertices.push_back(0);
    vertices.push_back(3);

    // Generate 1 buffer, put the resulting identifier in vertexbuffer
    glGenBuffers(1, &VBO);

    // The following commands will talk about our 'vertexbuffer' buffer
    glBindBuffer(GL_ARRAY_BUFFER, VBO);

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

    glEnableVertexAttribArray(0);


    glVertexAttribPointer(
       0,                  // attribute 0. No particular reason for 0, but must match the layout in the shader.
       3,                  // size
       GL_FLOAT,           // type
       GL_FALSE,           // normalized?
       0,                  // stride
       (void*)0            // array buffer offset
    );



    //Main Loop
        while(!glfwWindowShouldClose(Window))
        
            if (glfwGetKey(Window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
                glfwSetWindowShouldClose(Window, GL_TRUE);

            glClear(GL_COLOR_BUFFER_BIT);
                 // Use our shader
                glUseProgram(program);
                // 1rst attribute buffer : vertices
                glBindBuffer(GL_ARRAY_BUFFER, VBO);
                glBindVertexArray(VertexArrayID);
                // Draw the triangle !
                printf("everything setup we can draw \n");
                glDrawArrays(GL_TRIANGLES, 0, vertices.size()); // 3 indices starting at 0 -> 1 triangle
                printf("drawing\n");

           glfwSwapBuffers(Window);
           glfwPollEvents();
        
    //Termination
glDisableVertexAttribArray(0);
glfwDestroyWindow(Window);
        glfwTerminate();
 

【问题讨论】:

使用跟踪语句或调试器尝试隔离在哪里发生故障。除此之外,请先尝试glewExperimental = true;,然后再致电glewInit(); 你打电话给glewInit()了吗? 是的,我没有添加初始化阶段,但 glew 设置正确。 glDrawArrays 也发生了崩溃,我忘了提 顺便说一句,您没有有效地使用 VAO。如果您按照预期的方式使用它们,您就不必每次调用GUI::Draw (...) 时都调用glBindBuffer (...)glEnableVertexAttribArray (...)glVertexAttribPointer (...)。您所要做的就是绑定您的 VAO 并绘制。 请显示GUI 的对象在哪里被实例化。我相信您在拥有 OpenGL 上下文之前就实例化了GUI,这可以解释很多。如果在你有上下文之前调用了那个构造函数,你会很抱歉。 【参考方案1】:

我发现崩溃的错误只是你需要三个维度而不是一个维度。这导致了draw函数读取超出范围的错误......

【讨论】:

它仍然没有渲染四边形 :(

以上是关于带有 GLFW 和 GLEW 的 OpenGL 应用程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL开发环境配置:VS2015+glew+glfw

glew和glfw的opengl初始化问题

如何将 GLEW 和 GLFW 以及 OpenGL 链接到 MingW 的 g++

使用 GLFW/GLEW 进行 OpenGL 编程

OpenGL配置GLFW与GLEW的问题

OpenGL, GLEW,GLFW配置