OpenGL - glGenVertexArrays,"线程1:exc_bad_access(代码= 1,地址= 0x0)"

时间:2017-09-23 04:24:21

标签: c++ opengl xcode8 exc-bad-access glew

我正在编写一个 openGL程序(C ++),它在其上面绘制了两个3D对象。我使用的编程工具是 Xcode版本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() 可以忽略,因为我还没有实现它(仅用于键盘控制)。

我实现了对象&#34; Ground&#34;在sendDataToOpenGL()中。但是当我编译并运行程序时, &#34;线程1:exc_bad_access(代码= 1,地址= 0x0)&#34; 出现在 VAO
enter image description here

弹出窗口只是一个白色的屏幕,而不是绿草(3d) enter image description here

我尝试过在其他stackoverflow帖子中提供的方法:使用glewExperimental = GL_TRUE;。我没有看到使用它的任何错误,但弹出窗口在它出现后立即消失。它似乎无法解决问题。

有人能帮我一个忙吗?谢谢!

1 个答案:

答案 0 :(得分:1)

自从OpenGL 3.0版开始,

glGenVertexArrays可用。如果支持顶点数组对象,则可以glewGetExtension("GL_ARB_vertex_array_object")检查。

Glew可以通过glewExperimental = GL_TRUE;启用其他扩展程序。请参阅GLEW documantation说明:

  

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

将此添加到您的代码中:

glewExperimental = GL_TRUE;
glewInit();