2016-09-11 4 views
0

Ich versuche OpenGL-Anwendung zu erstellen, die in der Lage ist, über 100000 2d primitive Objekte zu rendern.Zeichnen von Tausenden von Polygonen mit OpenGL VBO

AFAIK, sollte es mit modernen OpenGL und VBO möglich sein.

So, hier ist der Code (verwendet 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); 
} 

Dieser Code einfach macht 100.000 Polygone alle 16ms.

Und ich bin nicht wirklich zufrieden mit der Vorliebe meines Codes. Es lädt Prozessor ziemlich viel (trotz der Verwendung von VBO). Kann ich es effizienter machen, oder ist das die beste Leistung?

Danke.

+2

Sie verwenden einen einzelnen Zeichenaufruf pro Polygon. Es ist kein Wunder, dass dies langsam ist und all Ihre GPU-Last verbraucht. Und Sie verwenden überhaupt kein modernes OpenGL - das moderne GL hat weder 'GL_POLYGON' noch' glEnableClientState' oder 'glVertexPointer'. – derhass

Antwort

4

Nun, es ist Ihr Problem:

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

Sie tun 100000 Unentschieden fordert, dass einzelne VBO. Das belastet Ihre CPU. Zum Vergleich benötigt der neueste Doom im Durchschnitt weniger als 1500 Draw-Aufrufe für eine ganze Szene.

Sie sollten Ihre gesamte Geometrie mit einem einzigen Aufruf an glDrawArrays oder glDrawElements zeichnen. BTW: GL_POLYGON wird nicht mehr von modernen OpenGL unterstützt (der einzige unterstützte Primitive ein GL_POINTS, GL_LINE * und GL_TRIANGLE *).

Wenn es Ihr Anliegen ist, ein neues Primitiv zu starten, with glDrawElements you can specify a special index that restarts. Oder (und das ist die bevorzugte Methode) zeichne es einfach als indizierte Dreiecke. Indexierung ist der Schlüssel für effizientes Caching. Wenn Sie also maximale Leistung wünschen, ist dies der richtige Weg.

+0

Danke, es hat wirklich geholfen, aber wie soll ich diesen VBO indizieren? Ich habe bereits einige Konfigurationen versucht, aber sie haben überhaupt nicht funktioniert. – Soup71

+0

@ Soup71: Erstellen Sie einen Element-Array-Puffer ('glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, ...)'), füllen Sie ihn mit einem Index-Array und dann 'glDrawElements (..., NULL)'. Sie haben bereits Indexerstellungscode, und Sie können auch einen QGLBuffer und seine 'write'-Methode für Indizes verwenden. Beachten Sie, dass Vertex-Array-Objekte nur Vertex * -Attribute * abdecken, sodass die Element-Index-Puffer separat gebunden und verwaltet werden müssen. – datenwolf

+0

Thak du wieder. – Soup71