使用glGenVertexArrays调用OpenGL,FreeGlut和Glew崩溃

时间:2012-06-19 15:14:13

标签: c++ c opengl visual-studio-2008

我有一个如下程序:

#include <iostream>
#include <fstream>
#include <sstream>

#include <gl/glew.h>
#include <gl/freeglut.h>

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

using namespace std;

#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480

GLuint prog, verShader, fragShader;

GLint attrPos, attrNor;
GLint uniModelView, uniProjection, uniModelViewTransposeInverse;

glm::mat4 modelMatrix, viewMatrix, projectionMatrix, MV, MVP;
glm::mat3 MVI;

const string loadFile(string name)
{
    ifstream in(name.c_str(), ios::in);
    if (in.fail()) {
        cout << "File: '" << name << "' could not exist!!" << endl;
        return "";
    }

    stringstream data;
    data << in.rdbuf();
    in.close();

    return data.str();
}

GLuint createShader(GLenum type, const string name)
{
    GLint isCompileOk;
    GLuint shader;
    string shaderText, shaderType;
    const char *shaderSource;

    switch(type)
    {
    case GL_VERTEX_SHADER:
        shaderType = "GL_VERTEX_SHADER";
        break;
    case GL_FRAGMENT_SHADER:
        shaderType = "GL_FRAGMENT_SHADER";
        break;
    }

    shaderText = loadFile(name);
    shaderSource = shaderText.c_str();

    shader = glCreateShader(type);
    glShaderSource(shader, 1, &shaderSource, NULL);
    glCompileShader(shader);
    glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompileOk);
    if (isCompileOk == GL_FALSE) {
        char *shaderErr;
        int errLength, errRetrieve;

        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &errLength);
        shaderErr = new char [errLength + 1];
        glGetShaderInfoLog(shader, errLength, &errRetrieve, shaderErr);

        cout << "Compile '" << shaderType << "' error:" << endl;
        cout << shaderErr << endl;

        delete [] shaderErr;
        return 0;
    } else {
        cout << "Compile '" << shaderType << "' ok!" << endl;
    }

    return shader;
}

bool makeShader()
{
    GLint isLinkOk;

    verShader = createShader(GL_VERTEX_SHADER, "vert.glsl");
    fragShader = createShader(GL_FRAGMENT_SHADER, "frag.glsl");

    prog = glCreateProgram();
    glAttachShader(prog, verShader);
    glAttachShader(prog, fragShader);
    glLinkProgram(prog);
    glGetProgramiv(prog, GL_LINK_STATUS, &isLinkOk);
    if (isLinkOk == GL_FALSE) {
        char *progErr;
        int errLenght, errRetrieve;

        glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &errLenght);
        progErr = new char[errLenght + 1];

        glGetProgramInfoLog(prog, errLenght, &errRetrieve, progErr);
        cout << "Link program error:" << endl;
        cout << progErr << endl;

        delete [] progErr;

        return false;
    } else {
        cout << "Link program Ok!" << endl;
    }

    attrPos = glGetAttribLocation(prog, "position");

    uniModelView = glGetUniformLocation(prog, "ModelViewMatrix");
    uniProjection = glGetUniformLocation(prog, "ProjectionMatrix");
    uniModelViewTransposeInverse = glGetUniformLocation(prog, "ModelViewTransposeInverseMatrix");

    return true;
}

float vertexs[] = {
    -1.0f, 1.0f, 1.0f,
     1.0f, 1.0f, 1.0f,
     1.0f, -1.0f, 1.0f,
    -1.0f, -1.0f, 1.0f
};

unsigned short indicates[] = {
    0, 1, 2,
    2, 3, 0
};

GLuint vao, vbo, ibo;
void display()
{
    MV = viewMatrix * modelMatrix;
    MVP = projectionMatrix * MV;
    MVI = glm::transpose(glm::inverse(glm::mat3(MV)));

    glUseProgram(prog);
    glUniformMatrix4fv(uniModelView, 1, GL_FALSE, glm::value_ptr(MV));
    glUniformMatrix3fv(uniModelViewTransposeInverse, 1, GL_FALSE, glm::value_ptr(MVI));

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glBindVertexArray(vao);
    glDrawElements(GL_TRIANGLES, sizeof(indicates)/sizeof(unsigned short), GL_UNSIGNED_SHORT, 0);

    glutSwapBuffers();
}

void reshape(int w, int h)
{
    glViewport(0, 0, w, h);
    projectionMatrix = glm::perspective(45.0f, float(w)/h, 0.1f, 1000.0f);

    glUseProgram(prog);
    glUniformMatrix4fv(uniProjection, 1, GL_FALSE, glm::value_ptr(projectionMatrix));
}

void idle()
{
    glutPostRedisplay();
}

void Init()
{
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    glClearDepth(1.0);
    glDepthFunc(GL_LEQUAL);
    glEnable(GL_DEPTH_TEST);

    modelMatrix = glm::mat4(1.0f);
    viewMatrix = glm::lookAt(
        glm::vec3(0.0f, 5.0f, 10.0f),
        glm::vec3(0.0f, 0.0f, 0.0f),
        glm::vec3(0.0f, 1.0f, 0.0f)
    );
    projectionMatrix = glm::mat4(1.0f); 

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

    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertexs), vertexs, GL_STATIC_DRAW);
    glVertexAttribPointer(attrPos, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, 0);
    glEnableVertexAttribArray(attrPos);

    glGenBuffers(1, &ibo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indicates), indicates, GL_STATIC_DRAW);

    glBindVertexArray(0);
}

int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
    glutCreateWindow("Rectangle!");

    if (glewInit() != GLEW_OK) {
        cout << "glewInit() fail!" << endl;
        return -1;
    }

    if (!makeShader()) {
        cout << "makeShader() error!!" << endl;
        return -1;
    }

    Init();

    reshape(WINDOW_WIDTH, WINDOW_HEIGHT);
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutIdleFunc(idle);

    glutMainLoop();

    return 0;
}

当我添加VAO缓冲区时,freeglut将在glutMainLoop()中崩溃,如果我删除了glGenVertexArrays来电(同时删除了与VAO的亲属),那么运行正常,所以我的猜测是freeglut glGenVertexArrays中的问题。

问题:我的问题是什么? ps:我的图形校准支持opengl 2.1,我使用的是Visual Studio 2008。

更新:使用VAO,以上程序运行良好,但只有在关闭freeglut窗口时才会崩溃。

更新着色器:我的着色器非常简单:

顶点着色器:

#version 120

attribute vec3 position;
// attribute vec3 normal;

uniform mat4 ModelViewMatrix;
uniform mat3 ModelViewTransposeInverseMatrix;
uniform mat4 ProjectionMatrix;

void main(void)
{
    gl_Position = ProjectionMatrix * ModelViewMatrix * vec4(position, 1.0);
}

片段着色器:

#version 120

void main()
{
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

1 个答案:

答案 0 :(得分:1)

glVertexAttribPointer(attrPos, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, 0);

您的顶点数据紧凑。使用0代替sizeof(float) * 3的步幅。

  

我的图形校准支持opengl 2.1

此外,VAO仅成为core in 3.0。在使用该功能之前,您应该检查ARB_vertex_array_object支持。