2016-09-11 94 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