如何有效地画点 [英] How to draw points efficiently

查看:125
本文介绍了如何有效地画点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的程序接收PCL点云,并使用以下命令逐个绘制每个点:

My program receives PCL pointcloud and plot each point one by one using:

glBegin(GL_POINTS);
glVertex3f(point.x, point.y, point].z);
glEnd();

它可以工作,但是由于要点很多,程序运行缓慢.有没有更有效的方法可以做到这一点?

It works but due to the large number of points the program is pretty slow. Is there a more efficient way to do this?

推荐答案

将所有要点加进一个大的将所有顶点数据转移一次到GPU,而不是您

Jam all the points into a big VBO when the point-cloud changes & draw 'em all in one go using a single glDrawArrays() call. That way OpenGL can shift all the vertex data to GPU once instead of you spoon-feeding the driver geometry one glVertex() at a time every frame.

通过避免在GL驱动程序中成千上万的函数调用,甚至顶点数组也可以为您带来巨大的提速.

Heck, even vertex arrays will buy you a huge speed-up by avoiding hundreds of thousands of function-calls into the GL driver.

编辑:比较:

1000万个随机点,使用顶点缓冲对象:

10 million random points, using vertex buffer objects:

顶点数组:

显示列表:

并使用立即模式:

代码(按"n"可在绘制方法之间循环):

Code (hit 'n' to cycle between drawing methods):

// http://glew.sourceforge.net/
#include <GL/glew.h>

// http://freeglut.sourceforge.net/
#include <GL/freeglut.h>

// http://glm.g-truc.net/
#include <glm/glm.hpp>
#include <glm/gtc/random.hpp>
#include <glm/gtc/type_ptr.hpp>

#include <vector>
#include <sstream>
#include <chrono>
#include <cstddef>

struct Vertex
{
    glm::vec4 pos;
    glm::vec4 color;
};
std::vector< Vertex > verts;
GLuint vbo = 0;
GLuint dlist = 0;

void init()
{
    // init geometry
    for( size_t i = 0; i < 10000000; i++ )
    {
        Vertex vert;
        vert.pos = glm::vec4( glm::linearRand( glm::vec3( -1.0f, -1.0f, -1.0f ), glm::vec3( 1.0f, 1.0f, 1.0f ) ), 1.0f );
        vert.color = glm::vec4( glm::linearRand( glm::vec3( 0.00f, 0.0f, 0.0f ), glm::vec3( 1.0f, 1.0f, 1.0f ) ), 1.0f );
        verts.push_back( vert );
    }

    // create display list
    dlist = glGenLists( 1 );
    glNewList( dlist, GL_COMPILE );
    glBegin( GL_POINTS );
    for( size_t i = 0; i < verts.size(); ++i )
    {
        glColor4fv( glm::value_ptr( verts[i].color) );
        glVertex4fv( glm::value_ptr( verts[i].pos) );
    }
    glEnd();
    glEndList();

    // create VBO
    glGenBuffers( 1, &vbo );
    glBindBuffer( GL_ARRAY_BUFFER, vbo );
    glBufferData( GL_ARRAY_BUFFER, sizeof( Vertex ) * verts.size(), verts.data(), GL_STATIC_DRAW );
}

unsigned int method = 0;
void keyboard( unsigned char key, int x, int y )
{
    if( 'n' == key )
    {
        method++;
        if( method > 3 ) method = 0;
    }
}

void display()
{
    // timekeeping
    static std::chrono::steady_clock::time_point prv = std::chrono::steady_clock::now();
    std::chrono::steady_clock::time_point cur = std::chrono::steady_clock::now();
    const float dt = std::chrono::duration< float >( cur - prv ).count();
    prv = cur;

    glClearColor( 0, 0, 0, 1 );
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    double w = glutGet( GLUT_WINDOW_WIDTH );
    double h = glutGet( GLUT_WINDOW_HEIGHT );
    gluPerspective( 60.0, w / h, 0.1, 10.0 );

    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
    gluLookAt( 2, 2, 2, 0, 0, 0, 0, 0, 1 );

    static float angle = 0.0f;
    angle += dt * 6.0f;
    glRotatef( angle, 0, 0, 1 );

    // render
    switch( method )
    {
    case 0:
        // VBO
        glBindBuffer( GL_ARRAY_BUFFER, vbo );
        glEnableClientState( GL_VERTEX_ARRAY );
        glEnableClientState( GL_COLOR_ARRAY );
        glVertexPointer( 4, GL_FLOAT, sizeof( Vertex ), (void*)offsetof( Vertex, pos ) );
        glColorPointer( 4, GL_FLOAT, sizeof( Vertex ), (void*)offsetof( Vertex, color ) );
        glDrawArrays( GL_POINTS, 0, verts.size() );
        glDisableClientState( GL_VERTEX_ARRAY );
        glDisableClientState( GL_COLOR_ARRAY );
        glBindBuffer( GL_ARRAY_BUFFER, 0 );
        break;

    case 1:
        // vertex array
        glEnableClientState( GL_VERTEX_ARRAY );
        glEnableClientState( GL_COLOR_ARRAY );
        glVertexPointer( 4, GL_FLOAT, sizeof( Vertex ), &verts[0].pos );
        glColorPointer( 4, GL_FLOAT, sizeof( Vertex ), &verts[0].color );
        glDrawArrays( GL_POINTS, 0, verts.size() );
        glDisableClientState( GL_VERTEX_ARRAY );
        glDisableClientState( GL_COLOR_ARRAY );
        break;

    case 2:
        // display list
        glCallList( dlist );
        break;

    case 3:
        // immediate mode
        glBegin( GL_POINTS );
        for( size_t i = 0; i < verts.size(); ++i )
        {
            glColor4fv( glm::value_ptr( verts[i].color) );
            glVertex4fv( glm::value_ptr( verts[i].pos) );
        }
        glEnd();
        break;
    }

    // info/frame time output
    std::stringstream msg;
    msg << "Using ";
    switch( method )
    {
    case 0: msg << "vertex buffer object"; break;
    case 1: msg << "vertex array"; break;
    case 2: msg << "display list"; break;
    case 3: msg << "immediate mode"; break;
    }
    msg << std::endl;
    msg << "Frame time: " << (dt * 1000.0f) << " ms";
    glColor3ub( 255, 255, 0 );
    glWindowPos2i( 10, 25 );
    glutBitmapString( GLUT_BITMAP_9_BY_15, (unsigned const char*)( msg.str().c_str() ) );

    glutSwapBuffers();
}

int main(int argc, char **argv)
{
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
    glutInitWindowSize( 600, 600 );
    glutCreateWindow( "GLUT" );
    glewInit();
    init();
    glutDisplayFunc( display );
    glutKeyboardFunc( keyboard );
    glutIdleFunc( display );
    glutMainLoop();
    return 0;
}

这篇关于如何有效地画点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆