c++ - OpenGL——glGenVertexArrays, "thread 1: exc_bad_access (code =1, address=0x0)"

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

我正在编写一个 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 行:
enter image description here

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

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

有人可以帮我吗?谢谢你!

最佳答案

glGenVertexArrays自 OpenGL 3.0 版起可用。如果支持顶点数组对象,可以通过 glewGetExtension("GL_ARB_vertex_array_object") 检查。

Glew 可以通过 glewExperimental = GL_TRUE; 启用额外的扩展。查看GLEW documantation其中说:

GLEW obtains information on the supported extensions from the graphics driver. Experimental or pre-release drivers, however, might not report every available extension through the standard mechanism, in which case GLEW will report it unsupported. To circumvent this situation, the glewExperimental global switch can be turned on by setting it to GL_TRUE before calling glewInit(), which ensures that all extensions with valid entry points will be exposed.

将此添加到您的代码中:

glewExperimental = GL_TRUE;
glewInit();

关于c++ - OpenGL——glGenVertexArrays, "thread 1: exc_bad_access (code =1, address=0x0)",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46376020/

相关文章:

c++ - 未定义对友元运算符的引用

c++ - 使用 FTGL 在 openGL 中呈现复合字符字体的问题

ios - 使用 Xcode 8.3.3 和 Swift 3 从移动应用程序向服务器发送 NS 用户身份验证数据问题

Swift 3、Xcode 8 类(class) - 高度约束错误

c++ - OpenCV Draw 绘制 2 个最大对象的轮廓

c++ - Autotools 和 OpenSSL MD5/RAND_bytes 未定义

opengl - 在单个 VAO 中使用多个索引列表

opengl - 将光照贴图与漫反射纹理混合

xcode8 - 如何让Xcode8响应更快

c++ - 如何在 C++ 中修改知道内存地址的对象?