2016-09-11 153 views
0

我想创建OpenGL应用程序,能够绘制超过100000个2d原始对象。我们可以使用现代的OpenGL和VBO来实现AFAIK。用OpenGL VBO绘制数以千计的多边形

所以这里是代码(使用Qt):

#include "paintwidget.h" 

PaintWidget::PaintWidget(QGLWidget *parent) : QGLWidget(parent) 
{ 
    QTimer *timer = new QTimer(this); 
    connect(timer, SIGNAL(timeout()), this, SLOT(updateTimer())); 
    timer->start(16); 
} 

GLuint indices[100000]; 

void PaintWidget::initializeGL() 
{ 
    VBOBuffer= new QGLBuffer(QGLBuffer::VertexBuffer); 
    VBOBuffer->create(); 
    VBOBuffer->bind(); 
    VBOBuffer->setUsagePattern(QGLBuffer::DynamicDraw); 
    VBOBuffer->allocate(100000 * 10 * sizeof(double)); 

    // load data into VBO: 
    for(int i=0; i<100000; i++) 
    { 

     GLdouble vertices[] = {100 + (double)i * 100, 100 + (double)i * 100, 
           100 + (double)i * 100, 200 + (double)i * 100, 
           200 + (double)i * 100, 200 + (double)i * 100, 
           300 + (double)i * 100, 150 + (double)i * 100, 
           200 + (double)i * 100, 100 + (double)i * 100 }; 

     VBOBuffer->write(i * 10 * sizeof(double), vertices, 10 * sizeof(double)); 
    } 

    // fill indices array: 
    for(int i=0; i<100000; i+=10) 
    { 
     indices[i] = i; 
     indices[i+1] = i+1; 
     indices[i+2] = i+1; 
     indices[i+3] = i+2; 
     indices[i+4] = i+2; 
     indices[i+5] = i+3; 
     indices[i+6] = i+3; 
     indices[i+7] = i+4; 
     indices[i+8] = i+4; 
     indices[i+9] = i; 
    } 
} 

void PaintWidget::paintEvent(QPaintEvent*) 
{ 
    QPainter paint(this); 
    paint.beginNativePainting(); 

    glEnable(GL_LINE_SMOOTH); 
    glEnable(GL_MULTISAMPLE); 
    glClearColor(0.1, 0.96, 0.1, 1.0); 
    glClear(GL_COLOR_BUFFER_BIT); 
    glEnable(GL_BLEND); 
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 


    glEnableClientState(GL_VERTEX_ARRAY); 
    glVertexPointer(2, GL_DOUBLE, 0, 0); 

    // draw my polygons: 
    for(int i=0; i<100000; i+=5) 
    { 
     glDrawArrays(GL_POLYGON, i, 5); 
    } 
    glDisableClientState(GL_VERTEX_ARRAY); 

    paint.endNativePainting(); 
} 

void PaintWidget::updateTimer() 
{ 
    paintEvent(nullptr); 
} 

此代码只是呈现100000个多边形每16毫秒。

而我对代码的优先性并不满意。它加载处理器相当多(尽管使用VBO)。我能让它更有效率吗?或者这是最好的表现?

谢谢。

+2

您正在使用每个多边形的单个绘制调用。难怪这很慢,并且消耗了所有的GPU负载。而且你根本没有使用现代的OpenGL - 现代GL没有'GL_POLYGON',它也没有'glEnableClientState'或'glVertexPointer'。 – derhass

回答

4

那么有你的问题:

// draw my polygons: 
for(int i=0; i<100000; i+=5) 
{ 
    glDrawArrays(GL_POLYGON, i, 5); 
} 

你做得100000平局呼吁该单一VBO。这是什么税你的CPU。为了比较,最新的平均Doom需要少于1500次整个场景的平局。

您应该通过一次性调用glDrawArraysglDrawElements来绘制整个几何图形。顺便说一句:GL_POLYGON不再受现代OpenGL(唯一受支持的基元GL_POINTS,GL_LINE *和GL_TRIANGLE *)支持。

如果您的关注是关于开始一个新的基元,with glDrawElements you can specify a special index that restarts。或者(这实际上是首选的方法)只是将其绘制为索引三角形。索引是高效缓存的关键,所以如果您希望获得最佳性能,那么这是一条可行的路线。

+0

谢谢,它真的有帮助,但我该如何索引这个VBO?我已经尝试了一些配置,但它们根本没有工作。 – Soup71

+0

@ Soup71:创建一个元素数组缓冲区('glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,...)'),用索引数组填充它,然后用'glDrawElements(...,NULL)'填充它。您已经有了索引创建代码,您也可以使用QGLBuffer及其“写入”方法。请记住,顶点数组对象只包含顶点*属性*,所以元素索引缓冲区必须分开绑定和维护。 – datenwolf

+0

谢谢你,再次。 – Soup71