gpt4 book ai didi

c++ - 如何有效地画点

转载 作者:行者123 更新时间:2023-11-30 01:39:50 26 4
gpt4 key购买 nike

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

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

它可以工作,但由于点数过多,程序运行速度很慢。有没有更有效的方法来做到这一点?

最佳答案

将所有点塞进一个大的 VBO当点云发生变化并使用单个 glDrawArrays() 调用一次性绘制它们。这样 OpenGL 就可以 shift所有的顶点数据都给 GPU 一次,而不是你 spoon-feeding驱动程序几何glVertex()一次每一帧

哎呀,通过避免对 GL 驱动程序的数十万次函数调用,即使是顶点数组也会为您带来巨大的加速。

编辑:比较:

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

vertex buffer object

顶点数组:

vertex array

显示列表:

display list

并使用即时模式:

immediate-mode

代码(点击'n'在绘图方法之间循环):

// 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;
}

关于c++ - 如何有效地画点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44687061/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com