用顶点缓冲对象(VBO)渲染Kinect点云

8
我正在尝试制作一个动态点云可视化器。这些点每帧都会通过Kinect传感器更新。我使用OpenCV和GLUT来捕获帧并显示。 OpenCV API返回一个大小为640×480的浮点数数组,表示点的xyz位置,以及一个大小为640×480的整数数组,表示RGB颜色数据。 为了获得最大的性能,我尝试使用流模式的顶点缓冲对象而不是简单的顶点数组。我可以使用顶点数组进行渲染,但使用VBO实现时没有任何渲染。我尝试了许多不同的声明顺序,但找不到我漏掉了什么。有人能指点我正确的方向吗?以下是简化后的代码:(我已经按照Christian Rau的要求改写了错误版本,所以你们可以理解我的错误)
int main()
{
    //Delaring variables, inittiating glut, setting camera and checking the compatibility as http://www.songho.ca/opengl/gl_vbo.html
    glutDisplayFunc(displayCB);
    glutIdleFunc(displayCB); 
    ... 
    //Inittiating the vertex buffers
    if(vboSupported)
    {
        glGenBuffers(1, &vertex_buffer);
        glBindBuffer(GL_ARRAY_BUFFER_ARB, buffer);
        glBufferData(GL_ARRAY_BUFFER_ARB, (sizeof(GLfloat) * 640 * 480 * 3), 0, GL_STREAM_DRAW_ARB);
        glBufferSubData(GL_ARRAY_BUFFER_ARB, 0,  (sizeof(float) * 640 * 480 * 3), point_cloud.points_position); 

        glGenBuffers(2, &color_buffer);
        glBindBuffer(GL_ARRAY_BUFFER_ARB, buffer);
        glBufferData(GL_ARRAY_BUFFER_ARB, (sizeof(GLbyte) * 640 * 480 * 3), 0, GL_STREAM_DRAW_ARB);
        glBufferSubData(GL_ARRAY_BUFFER_ARB, 0,  (sizeof(char) * 640 * 480 * 3), point_cloud.points_color); 
    }
    //glutMainLoop(), cleaning memory, ending main
    ..
}

//Updating the screen
void displayCB()
{
    point_cloud.update();

    // clear buffer
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

    // save the initial ModelView matrix before modifying ModelView matrix
    glPushMatrix();

        glBindBuffer(GL_ARRAY_BUFFER_ARB, color_buffer);
        glBufferSubData(GL_ARRAY_BUFFER_ARB, 0,  (sizeof(char) * 640 * 480 * 3), point_cloud.points_color); 
        glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0);

        glBindBuffer(GL_ARRAY_BUFFER_ARB, vertex_buffer);
        glBufferSubData(GL_ARRAY_BUFFER_ARB, 0,  (sizeof(float) * 640 * 480 * 3), point_cloud.points_position); 
        glVertexPointer(3, GL_FLOAT, 0, 0));

        // enable vertex arrays
        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_COLOR_ARRAY);

        glDrawArrays(GL_POINT, 0, 640*480);

        glDisableClientState(GL_VERTEX_ARRAY);  // disable vertex arrays
        glDisableClientState(GL_COLOR_ARRAY);

        glBindBuffer(GL_ARRAY_BUFFER_ARB, 0);

    glPopMatrix();

    glutSwapBuffers();
}

1
相当无关的评论:在更新整个缓冲区时,最好使用glBufferData(而不是glBufferSubData)。这可能有助于驱动程序优化,但我现在不会详细介绍。至少在主代码中,glBufferData后面的glBufferSubData是完全无用的。 - Christian Rau
1
你应该将新版本的代码追加到问题中,而不是在每个答案或评论后完全更改问题的代码,因为这会使其他答案无效,并且阅读问题和答案的人会完全困惑。 - Christian Rau
我通过发布一个新答案来实现这个功能? - Ian Medeiros
1
不,你只需要像这样编辑你的问题:“更新:根据...的答案/评论,我将代码/...部分更改为...,但它仍然无法工作/现在我有这些错误...”或类似的内容。但是,如果更改相当重要,你不应该覆盖你现有的问题代码,特别是当这会使其他答案失效时。 - Christian Rau
1
既然您已经解决了这个问题,您可以考虑将解决方案作为答案添加,并将其标记为已解决,以便将此问题从未回答列表中移除。 - appas
完成。对不起,我之前不知道。 :) - Ian Medeiros
1个回答

0

PS:程序已经运行起来了,但是与顶点数组版本相比,平均性能没有任何改善。这样可以吗?问题已经解决了。我进行了三个修改:

1 - I though that glGenBuffers first parameter was the number that
would be associated to the buffer, instead, its the number of
buffers that would be allocated. This doesn't matter anyway, because
now I'm using a single buffer and adding all the data to it. Didn't
solved the problem, but was going in the right way.

2 - There are two ways of being able to use OpenGL VBO functions.
First, you can bind the ARB  version functions by yourself OR you
can add glew.h and use glewInit() after starting an OpenGL context.
The second option is a LOT cleaner and I changed my code so I don't
use the ARB versions anymore. Still didn't solved the problem.

3 - Christian Rau asked me for glErrors in the code, so, I wrote it
after each OpenGL operation in displayCB. After glDrawArrays I got
an 0x00500 error, that means there is an invalid enum, so I noticed
I was using GL_POINT as parameter to glDrawArrays, instead of
GL_POINTS, so silly that makes me want to kill myself.

最终代码:
//EDIT: Added glew.h as a header and I´m not using the ARB version anymore
#include <glew.h>

    int main()
    {
        //Declaring variables, initiating glut, setting camera and checking the compatibility as http://www.songho.ca/opengl/gl_vbo.html
        glutDisplayFunc(displayCB);
        glutIdleFunc(displayCB); 
        ...

        //EDIT: IS VERY IMPORTANT TO ADD IT AS SOON AS YOU START AN OPENGL CONTEXT.
        initGlew();

        //Inittiating the vertex buffers
        if(vboSupported)
        {
           //EDIT: I was using two buffers, one for color and another for the vertex. I changed the code so I use  a single buffer now.
           //EDIT: Notice that I'm not using the ARB version of the functions anymore.
            glGenBuffers(1, &buffer);
            glBindBuffer(GL_ARRAY_BUFFER_ARB, buffer);
            glBufferData(GL_ARRAY_BUFFER_ARB, (sizeof(GLfloat) * 640 * 480 * 3) + (sizeof(GLbyte) * 640 * 480 * 3), 0, GL_STREAM_DRAW_ARB);
        }
        //glutMainLoop(), cleaning memory, ending main
        ..
    }

    //Updating the screen
    void displayCB()
    {
        point_cloud.update();

        // clear buffer
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

        // save the initial ModelView matrix before modifying ModelView matrix
        glPushMatrix();

            glBindBuffer(GL_ARRAY_BUFFER_ARB, buffer);
            glBufferSubData(GL_ARRAY_BUFFER_ARB, 0,  (sizeof(char) * 640 * 480 * 3), point_cloud.points_color); 
            glBufferSubData(GL_ARRAY_BUFFER_ARB, (sizeof(char) * 640 * 480 * 3), (sizeof(float) * 640 * 480 * 3), point_cloud.points_position);

            // enable vertex arrays
            glEnableClientState(GL_VERTEX_ARRAY);
            glEnableClientState(GL_COLOR_ARRAY);

            glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0);
            //EDIT: Added the right offset at the vertex pointer position
            glVertexPointer(3, GL_FLOAT, 0, (void*)(sizeof(char) * 640 * 480 * 3));

            //EDIT: Was using GL_POINT instead of GL_POINTS
            glDrawArrays(GL_POINTS, 0, 640*480);

            glDisableClientState(GL_VERTEX_ARRAY);  // disable vertex arrays
            glDisableClientState(GL_COLOR_ARRAY);

            glBindBuffer(GL_ARRAY_BUFFER_ARB, 0);

        glPopMatrix();

        glutSwapBuffers();
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接