OpenGL崩溃之前它可以呈现一个框架 - 维也纳国际组织

时间:2015-11-24 20:24:51

标签: c++ opengl vbo vao

放弃缓慢的glBegin / glEnd技术后,我终于决定使用VBO。经过几个小时的挫折,我终于得到了编译。但这并不意味着它有效。函数“CreateVBO”执行时没有错误,但只要调用glutMainLoop(),程序就会崩溃,甚至不会调用Reshape()Render()函数。

这是CreateVBO()函数: (注意:“lines”变量等于400万,整个程序只是一个压力测试,用于渲染很多行,然后才能做出真正有意义的事情)

void CreateVBO()
{
    glGenBuffers = (PFNGLGENBUFFERSPROC)wglGetProcAddress("glGenBuffers");
    glBindBuffer=(PFNGLBINDBUFFERPROC)wglGetProcAddress("glBindBuffer");
    glBufferData=(PFNGLBUFFERDATAPROC)wglGetProcAddress("glBufferData");
    glDeleteBuffers=(PFNGLDELETEBUFFERSPROC)wglGetProcAddress("glDeleteBuffers");
    glMapBuffer=(PFNGLMAPBUFFERPROC)wglGetProcAddress("glMapBuffer");


    for(float i=0; i<lines*2; i++)
    {

        t_vertices.push_back(i/9000);
        t_vertices.push_back(5 * (((int)i%2)*2-1));
        t_vertices.push_back(20);

        vert_cols.push_back(0);
        vert_cols.push_back(255);
        vert_cols.push_back(0);


        t_indices.push_back((int)i);
    }

    glGenBuffers(1, &VertexVBOID);
    glBindBuffer(GL_ARRAY_BUFFER, VertexVBOID);
    glBufferData(GL_ARRAY_BUFFER, sizeof(float)*t_vertices.size(), &t_vertices[0], GL_STATIC_DRAW);

    glGenBuffers(1, &IndexVBOID);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexVBOID);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int)*t_indices.size(), NULL, GL_STATIC_DRAW);

    GLvoid * buf = glMapBuffer( GL_ARRAY_BUFFER, GL_WRITE_ONLY );

    memcpy( (void*)buf, &vert_cols[0], (size_t)(sizeof(float)*vert_cols.size()));

    glBindBuffer( GL_ARRAY_BUFFER, 0 );
}

这是Render()函数。我不知道它有什么问题,因为程序在调用该函数之前崩溃了。

void Display()
{
    glRotatef(1, 0, 1, 0);
    glClearColor(0, 0, 0, 0);
    glClear(GL_COLOR_BUFFER_BIT);

    glBindBuffer(GL_ARRAY_BUFFER, VertexVBOID);
    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(t_vertices.size(), GL_FLOAT, 0, 0);   //The starting point of the VBO, for the vertices
    glEnableClientState(GL_COLOR_ARRAY);
    glColorPointer(vert_cols.size(), GL_FLOAT, 0, 0);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexVBOID);
    glDrawElements(GL_LINES, lines, GL_UNSIGNED_INT, 0);
    glutSwapBuffers();
    //Sleep(16);
    glutPostRedisplay();
}

1 个答案:

答案 0 :(得分:1)

您的代码没有意义。

首先,您创建的vertexVBOID足够大,可以容纳t_vertices向量,并使用该数组填充它。 然后,将VBO和覆盖其中的数据与vert_color向量中的数据进行映射。对于绘图,您指定顶点位置和颜色属性来自内存中的相同位置 - 因此也有效地将颜色用作位置。

但这不是崩溃的原因。崩溃实际上有两个主要原因:

  1. 您创建的IndexVBOID足以容纳索引数组,但您永远不会使用某些数据初始化该缓冲区。您改为将NULL指定为数据指针,因此存储已创建,但未初始化。因此,您最终会在该缓冲区中找到未定义的内容,并且GL在使用该内容进行绘制时将访问arbtrary内存位置。

  2. 您的glVertexPointerglColorPointer来电是错误的。第一个参数size 不是数组的大小。它是单向量的大小,可以是1,2,3或4.您的数组大小可能是其他内容,因此这些调用最终会产生GL_INVALID_VALUE错误,并且根本没有设置attrib指针。默认情况下,这些指针为NULL。

  3. 所以最终,你要求GL从相对于NULL指针的未定义数组索引中绘制。那很可能会崩溃。一般来说,它只是未定义的行为,结果可能是任何东西。

    此外,您还保持VertexVBOID缓冲区映射 - 您永远不会取消映射它。使用缓冲区作为GL命令的源或目标是无效的,只要它被映射(除非创建持久映射,这是一个相对较新的特性,并不属于此处)。