【问题标题】:OpenGL, FreeGlut and Glew crash with glGenVertexArrays callOpenGL、FreeGlut 和 Glew 因 glGenVertexArrays 调用而崩溃
【发布时间】:2012-06-21 16:10:48
【问题描述】:

我有一个程序如下:

#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);
}

【问题讨论】:

  • 你的程序在哪个命令上崩溃了?
  • 它在 glutMainLoop() 中崩溃,但只有当我使用 VAO(确切地说是 glGenVertexArrays)时,它才能成功渲染,但在我关闭 freeglut 窗口时崩溃。
  • 也许这个问题(stackoverflow.com/questions/8302625/…)是相关的。
  • 我在glewInit() 的正上方添加了glewExperimental = GL_TRUE;,但这并不能解决我的问题。我的程序不会在glGenVertexArrays 上崩溃,但在glutMainLoop 上只有当我在程序中使用glGenVertexArrays 时才崩溃:-(
  • 我很确定,它不会直接在 glutMainLoop 中崩溃,而是在主循环期间调用的您的一个函数(reshapedisplay)中崩溃。

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


【解决方案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 支持。

【讨论】:

  • 我认为我的显卡支持 ARB_vertex_array_object,这是我支持的扩展:postimage.org/image/dsavjjqmn。我没有任何解决方案来解决这个问题:-|
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多