OpenGL——glGenVertexArrays,“线程 1:exc_bad_access(代码 = 1,地址 = 0x0)”

Posted

技术标签:

【中文标题】OpenGL——glGenVertexArrays,“线程 1:exc_bad_access(代码 = 1,地址 = 0x0)”【英文标题】:OpenGL -- glGenVertexArrays, "thread 1: exc_bad_access (code =1, address=0x0)" 【发布时间】:2017-09-23 04:24:21 【问题描述】:

我正在编写一个 openGL 程序(C++),它在地面上绘制两个 3D 对象。我使用的编程工具是Xcode version 8.0(8A218a)(OSX 10.11.6)。

我的代码(main.cpp):

   #include <GL/glew.h>
    #include <GL/freeglut.h>
    #include <glm/glm.hpp>
    #include <glm/gtc/matrix_transform.hpp>
    #include <iostream>
    #include <fstream>
    using namespace std;

    using glm::vec3;
    using glm::mat4;

    GLint programID;
    //initialize all OpenGL objects
    GLuint groundVAO, groundVBO, groundEBO; //ground


    bool checkStatus( //OK
        GLuint objectID,
        PFNGLGETSHADERIVPROC objectPropertyGetterFunc,
        PFNGLGETSHADERINFOLOGPROC getInfoLogFunc,
        GLenum statusType)
        
        GLint status;
        objectPropertyGetterFunc(objectID, statusType, &status);
        if (status != GL_TRUE)
        
            GLint infoLogLength;
            objectPropertyGetterFunc(objectID, GL_INFO_LOG_LENGTH, &infoLogLength);
            GLchar* buffer = new GLchar[infoLogLength];

            GLsizei bufferSize;
            getInfoLogFunc(objectID, infoLogLength, &bufferSize, buffer);
            cout << buffer << endl;

            delete[] buffer;
            return false;
        
        return true;
    

     bool checkShaderStatus(GLuint shaderID) //OK
    
        return checkStatus(shaderID, glGetShaderiv, glGetShaderInfoLog, GL_COMPILE_STATUS);
    

     bool checkProgramStatus(GLuint programID) //OK
    
        return checkStatus(programID, glGetProgramiv, glGetProgramInfoLog, GL_LINK_STATUS);
    

    string readShaderCode(const char* fileName) //OK
    
        ifstream meInput(fileName);
        if (!meInput.good())
        
            cout << "File failed to load..." << fileName;
            exit(1);
        
        return std::string(
            std::istreambuf_iterator<char>(meInput),
            std::istreambuf_iterator<char>()
        );
    

    void installShaders() //OK
    
        GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
        GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);

        const GLchar* adapter[1];
        //adapter[0] = vertexShaderCode;
        string temp = readShaderCode("VertexShaderCode.glsl");
        adapter[0] = temp.c_str();
        glShaderSource(vertexShaderID, 1, adapter, 0);
        //adapter[0] = fragmentShaderCode;
        temp = readShaderCode("FragmentShaderCode.glsl");
        adapter[0] = temp.c_str();
        glShaderSource(fragmentShaderID, 1, adapter, 0);

        glCompileShader(vertexShaderID);
        glCompileShader(fragmentShaderID);

        if (!checkShaderStatus(vertexShaderID) || 
    !checkShaderStatus(fragmentShaderID))
            return;

        programID = glCreateProgram();
        glAttachShader(programID, vertexShaderID);
        glAttachShader(programID, fragmentShaderID);
        glLinkProgram(programID);

        if (!checkProgramStatus(programID))
            return;

        glDeleteShader(vertexShaderID);
        glDeleteShader(fragmentShaderID);

        glUseProgram(programID);
     

     void keyboard(unsigned char key, int x, int y)
     
         //TODO:
     

     void sendDataToOpenGL()
     
         //TODO:
        //create solid objects here and bind to VAO & VBO

        //Ground, vertices info
        const GLfloat Ground[]
        
             -5.0f, +0.0f, -5.0f, //0
             +0.498f, +0.898, +0.0f, //grass color
             +5.0f, +0.0f, -5.0f, //1
             +0.498f, +0.898, +0.0f,
             +5.0f, +0.0f, +5.0f, //2
             +0.498f, +0.898, +0.0f,
             -5.0f, +0.0f, +5.0f
        ;
        GLushort groundIndex[] = 1,2,3, 1,0,3;

        //Pass ground to vertexShader
        //VAO
        glGenVertexArrays(1, &groundVAO);
        glBindVertexArray(groundVAO);

        //VBO
        glGenBuffers(1, &groundVBO);
        glBindBuffer(GL_ARRAY_BUFFER, groundVBO);
        glBufferData(GL_ARRAY_BUFFER, sizeof(Ground), Ground, GL_STATIC_DRAW);

        //EBO
        glGenBuffers(1, &groundEBO);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, groundEBO);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(groundIndex), groundIndex, GL_STATIC_DRAW);

        //connectToVertexShader
        glEnableVertexAttribArray(0); //position
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, 0);
        glEnableVertexAttribArray(1); //color
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, (char*)(sizeof(float)*3));
     

    void paintGL(void)
    
        //TODO:
        //render your objects and control the transformation here
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        //translate model
        glm::mat4 modelTransformMatrix = glm::translate(glm::mat4(), vec3(+0.0f, +0.0f, -3.0f));
        //perspective view
        glm::mat4 projectionMatrix = glm::perspective(+40.0f, +1.0f, +1.0f, +60.0f);
        //ultimate matrix
        glm::mat4 ultimateMatrix;

        //register location on the graphics cards
        GLint ultimateMatrixUniformLocation = glGetUniformLocation(programID, "ultimateMatrix");
        /*GLint modelTransformMatrixUniformLocation = glGetUniformLocation(programID, "modelTransformMatrix");
        GLint projectionMatrixUniformLocation = glGetUniformLocation(programID, "projectionMatrix");*/

        //drawing the ground

        /*glUniformMatrix4fv(modelTransformMatrixUniformLocation, 1, GL_FALSE, &modelTransformMatrix[0][0]);
        glUniformMatrix4fv(projectionMatrixUniformLocation, 1, GL_FALSE, &projectionMatrix[0][0]);*/
        glBindVertexArray(groundVAO);
        ultimateMatrix = projectionMatrix * modelTransformMatrix;
        glUniformMatrix4fv(ultimateMatrixUniformLocation, 1, GL_FALSE, &ultimateMatrix[0][0]);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);

        glFlush();
        glutPostRedisplay();
    

    void initializedGL(void) //run only once
    
        glewInit();
        glEnable(GL_DEPTH_TEST);
        sendDataToOpenGL();
        installShaders();
    

    int main(int argc, char *argv[])
    
        /*Initialization*/
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
        glutCreateWindow("Try");
        glutInitWindowSize(700, 700);

        //const GLubyte* glversion = glGetString(GL_VERSION);

        /*Register different CALLBACK function for GLUT to response
        with different events, e.g. window sizing, mouse click or
        keyboard stroke */
        initializedGL();

        //glewExperimental = GL_TRUE;

        glutDisplayFunc(paintGL);
        glutKeyboardFunc(keyboard);

        /*Enter the GLUT event processing loop which never returns.
        it will call different registered CALLBACK according
        to different events. */
        //printf("OpenGL ver: %s\n", glversion);
        glutMainLoop();

        return 0;
    

VertexShaderCode.glsl:

#version 430  // GLSL version your computer supports

in layout(location=0) vec3 position;
in layout(location=1) vec3 vertexColor;

uniform mat4 ultimateMatrix;

out vec3 theColor;

void main()

    vec4 v = vec4(position, 1.0);
    gl_Position = ultimateMatrix * v;
    theColor = vertexColor;
 

FragmentShaderCode.glsl:

#version 430 //GLSL version your computer supports

out vec4 theColor2;
in vec3 theColor;

void main()

    theColor2 = vec4(theColor, 1.0);

函数:checkStatus、checkShaderStatus、checkProgramStatus、readShaderCode、installShaders应该没问题。

void keyboard() 可以忽略,因为我还没有实现它(仅用于键盘控制)。

我在 sendDataToOpenGL() 中实现了对象“Ground”。但是当我编译运行程序时,"thread 1: exc_bad_access (code =1, address=0x0)"出现在VAO这一行

而且弹出的窗口只是一个白屏而不是绿草(3d)。

我尝试了其他 *** 帖子中提供的方法:使用 glewExperimental = GL_TRUE;。使用它我没有看到任何错误,但是弹出屏幕在它出现后立即消失了。好像解决不了问题。

有人可以帮我吗?谢谢!

【问题讨论】:

我不确定我的问题是否足够清楚。你可以问我更多细节。在没有解释的情况下投反对票是一种糟糕的行为。 @Rabbid76 感谢您的帮助,它看起来更清晰了。 :) "顺便说一句,应该在 glutCreateWindow 之前调用 glutInitWindowSize" 好的,我切换了它们。然后,我在 "glutCreateWindow("Try");"(inside int main()) 下添加了这些代码: if(glewGetExtension("GL_ARB_vertex_array_object") != GL_TRUE) fprintf(stderr, "It is not supported!\n" ); “不支持!”被打印出来。嗯,是不是说不能支持glGenvertexarray? 我得到: 1: glGenVertexArrays(1, &groundVAO);错误从“thread 1: exc_bad_access (code =1, address=0x0)”变为“Thread 1:breakpoint1.1” 2. fprintf 中的语句:“不支持!”已打印。 【参考方案1】:

glGenVertexArrays 从 OpenGL 版本 3.0 开始可用。是否支持顶点数组对象可以通过glewGetExtension("GL_ARB_vertex_array_object")查看。

Glew 可以通过glewExperimental = GL_TRUE; 启用其他扩展。请参阅GLEW documantation,上面写着:

GLEW 从图形驱动程序获取有关支持的扩展的信息。然而,实验性或预发布驱动程序可能不会通过标准机制报告每个可用的扩展,在这种情况下,GLEW 将报告它不受支持。为了规避这种情况,可以在调用glewInit()之前将glewExperimental全局开关设置为GL_TRUE,这样可以确保所有具有有效入口点的扩展都会被暴露。

将此添加到您的代码中:

glewExperimental = GL_TRUE;
glewInit();

【讨论】:

我添加了您建议的代码。 “线程 1:exc_bad_access (code =1, address=0x0)”已经消失了!谢谢!但现在我面临另一个问题: File failed to load...VertexShaderCode.glslProgram end with exit code: 1 The vertexshader cant be loaded。但是我已经在 installShaders() 函数中实现了代码来读取所有着色器代码。另外,我将 vertexshadercode.glsl、fragmentsshadercode.glsl 和 main.cpp 都放在同一个文件中。我不明白为什么无法加载 glsl 文件..... 从文件中读取时,着色器文件必须包含在应用程序的工作目录中。出于调试原因,您可以将绝对文件路径应用于readShaderCode(...) 的调用。 您的建议一直很棒。我更改为绝对文件路径,现在可以读取着色器。但是后来我遇到了一个问题,我认为这与我的 opengl 和 glsl 的版本有关。但我会在新帖子中提出这个问题,以便更清楚地说明。再次感谢兔子!!!!

以上是关于OpenGL——glGenVertexArrays,“线程 1:exc_bad_access(代码 = 1,地址 = 0x0)”的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL——glGenVertexArrays,“线程 1:exc_bad_access(代码 = 1,地址 = 0x0)”

glGenVertexArrays 上的 OpenGL C++ glfw 3 glew 错误 1282

未处理的异常,glGenVertexArrays 调用上的访问冲突

glGenVertexArrays 没有给出唯一的 vaos

OpenGL 顶点缓冲区绑定点可以在不同的 VAO 之间重复使用吗?

OpenGL - 纹理映射不完整