OpenGL 在渲染帧之前崩溃 - VBO

Posted

技术标签:

【中文标题】OpenGL 在渲染帧之前崩溃 - VBO【英文标题】:OpenGL crashing before it can render a frame - VBOs 【发布时间】:2015-11-24 20:24:50 【问题描述】:

在放弃了缓慢的 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();

【问题讨论】:

显示过剩设置代码 注意:我知道问题出在 GenerateVBO() 上,有一次它可以处理 3 行,但是当我将其更改为 30 时,它崩溃了 【参考方案1】:

您的代码没有意义。

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

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

    你创建了足够大的IndexVBOID 来保存你的索引数组,但是你从来没有用一些数据初始化那个缓冲区。您改为指定 NULL 作为数据指针,因此创建了存储,但未初始化。因此,您最终会在该缓冲区中获得未定义的内容,并且 GL 将在使用该缓冲区进行绘制时访问任意内存位置。

    您的glVertexPointerglColorPointer 调用错误。第一个参数size不是数组的大小。它是 单个向量 的大小,可以是 1、2、3 或 4。您的数组大小可能是别的东西,所以这个调用最终会生成 GL_INVALID_VALUE 错误,而不是设置属性指针。默认情况下,这些指针为 NULL。

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

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

【讨论】:

非常感谢,我真的不知道我在写什么,现在我意识到代码是多么愚蠢......显然我的代码现在很好,但似乎有一个 65535 顶点限制,即使我使用 32 位整数进行索引。但是还是非常感谢你;)

以上是关于OpenGL 在渲染帧之前崩溃 - VBO的主要内容,如果未能解决你的问题,请参考以下文章

在OpenGL中绘制到半透明帧缓冲区时如何抗锯齿? [复制]

OpenGL ES 学习教程(十四) 帧缓冲区对象(FBO) 实现渲染到纹理(Render To Texture/RTT)

Bresenham 线抽屉在渲染任何东西之前在某个循环后崩溃? [关闭]

OpenGL 帧缓冲区缺失面

OpenGL中的单色渲染到帧缓冲区对象?

OpenGL - 重新排序渲染方法后崩溃