5 Stimmen

OpenGL - Schnelle texturierte Quads?

Ich versuche, so viele texturierte Quads wie möglich an zufälligen Positionen im 3D-Raum anzuzeigen. Nach meiner bisherigen Erfahrung kann ich nicht einmal ein paar Tausend von ihnen anzeigen, ohne die fps deutlich unter 30 (meine Kamera Bewegung Skript wird verzögert).

Im Moment folge ich einer alten Anleitung. Nach der Initialisierung von OpenGL:

glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glClearColor(0, 0, 0, 0);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

Ich bestimme den Blickwinkel und die Perspektive:

glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

Dann lade ich einige Texturen:

glGenTextures(TEXTURE_COUNT, &texture[0]);
for (int i...){
    glBindTexture(GL_TEXTURE_2D, texture[i]);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
    gluBuild2DMipmaps(GL_TEXTURE_2D,3,TextureImage[0]->w,TextureImage[0]->h,GL_RGB,GL_UNSIGNED_BYTE,TextureImage[0]->pixels);
}

Und schließlich zeichne ich meine GL_QUADS mit:

glBindTexture(GL_TEXTURE_2D, q);
glTranslatef(fDistanceX,fDistanceZ,-fDistanceY); 
glBegin(GL_QUADS);
    glNormal3f(a,b,c);
    glTexCoord2f(d, e); glVertex3f(x1, y1,  z1);
    glTexCoord2f(f, g); glVertex3f(x2, y2,  z2);
    glTexCoord2f(h, k); glVertex3f(x3, y3,  z3);
    glTexCoord2f(m, n); glVertex3f(x4, y4,  z4);
glEnd();
glTranslatef(-fDistanceX,-fDistanceZ,fDistanceY);

Ich finde diesen ganzen Code sehr selbsterklärend. Leider ist diese Art, Dinge zu tun, veraltet, soweit ich weiß. Ich habe einige vage Dinge über PBO und vertexArrays im Internet gelesen, aber ich habe keine Anleitung gefunden, wie man sie benutzt. Ich weiß nicht einmal, ob diese Objekte geeignet sind, das zu realisieren, was ich hier zu tun versuche (eine Milliarde Quads auf dem Bildschirm ohne Verzögerung). Vielleicht kann mir jemand hier einen definitiven Vorschlag machen, was ich verwenden sollte, um das Ergebnis zu erreichen? Und wenn Sie zufällig noch eine Minute Zeit haben, könnten Sie mir eine kurze Zusammenfassung geben, wie diese Funktionen verwendet werden (so wie ich es mit den veralteten oben getan habe)?

8voto

Nicol Bolas Punkte 409659

Vielleicht kann mir jemand hier einen definitiven Vorschlag machen, was ich verwenden sollte, um das Ergebnis zu erreichen?

Was ist "das Ergebnis"? Sie haben nicht sehr gut erklärt, was genau Sie zu erreichen versuchen. Alles, was Sie gesagt haben, ist, dass Sie versuchen, eine Menge strukturierter Quads zu zeichnen. Was versuchst du zu erreichen? tun mit diesen strukturierten Quads?

Sie scheinen zum Beispiel die gleiche Textur mit der gleichen Breite und Höhe zu erstellen, wenn Sie die gleichen Pixeldaten verwenden. Aber Sie speichern diese in verschiedenen Texturobjekten. OpenGL weiß nicht, dass sie dieselben Daten enthalten. Daher verbringen Sie beim Rendern von Quads viel Zeit damit, Texturen unnötigerweise zu vertauschen.

Wenn Sie sie nur zufällig ziehen, um die Leistung zu testen, dann ist die Frage sinnlos. Solche Tests sind sinnlos, weil sie völlig künstlich sind. Sie testen nur dieses künstliche Szenario, bei dem Sie die Texturen jedes Mal ändern, wenn Sie ein Quad rendern.

Ohne zu wissen, was Sie letztendlich rendern wollen, kann ich nur allgemeine Leistungsempfehlungen geben. In der Reihenfolge (d.h.: machen Sie die ersten, bevor Sie die späteren machen):

  1. Hören Sie auf, die Texturen für jedes Quad zu ändern. Sie können mehrere Bilder in dieselbe Textur packen und dann alle Quads, die diese Textur verwenden, auf einmal rendern, mit nur einer glBindTexture anrufen. Die Texturkoordinaten des Quad geben an, welches Bild innerhalb der Textur es verwendet.

  2. Nicht mehr verwenden glTranslate um jeden einzelnen Quad zu positionieren. Sie können damit Gruppen von Quads positionieren, aber Sie sollten die Berechnung der Eckpunktpositionen der Quads selbst vornehmen. Sobald diese glTranslate Aufrufen verschwunden sind, können Sie mehrere Quads in den Raum eines einzigen glBegin/glEnd Paar.

  3. Unter der Annahme, dass Ihre Quads statisch sind (feste Position im Modellraum), sollten Sie die Verwendung eines Pufferobjekt zu speichern und machen mit Ihre Quad-Daten.

Ich habe einige vage Dinge über PBO und vertexArrays im Internet gelesen, aber ich habe keine Anleitung gefunden, wie man sie benutzt.

Haben Sie die OpenGL-Wiki die einen ziemlich gute Liste von Tutorials (sowie allgemeine Informationen über OpenGL)? Im Interesse einer vollständigen Offenlegung habe ich einen davon geschrieben.

7voto

datenwolf Punkte 154484

Ich habe gehört, dass in modernen Spielen Milliarden von Polygonen in Echtzeit gerendert werden.

Die Zahl geht in die Millionen. Ich nehme an, Sie sind Deutscher: "Milliarde" bedeutet auf Englisch "Billion".

Im Moment folge ich einer alten Anleitung.

Dies ist Ihr Hauptproblem. Moderne OpenGL-Anwendungen verwenden keine alten Rendering-Methoden. Sie verwenden den Sofortmodus, was bedeutet, dass Sie mehrere Funktionsaufrufe durchlaufen, um nur einen einzigen Vertex zu übermitteln. Das ist höchst ineffizient. Moderne Anwendungen, wie z.B. Spiele, können so hohe Dreieckszahlen erreichen, weil sie ihre CPU-Zeit nicht mit dem Aufruf so vieler Funktionen verschwenden, sie verschwenden keine CPUGPU-Bandbreite mit dem Datenstrom.

Um diese hohe Anzahl von Dreiecken, die in Echtzeit gerendert werden, zu erreichen, müssen Sie alle Geometriedaten im "schnellen Speicher", d. h. im RAM der Grafikkarte, ablegen. Die Technik, die OpenGL dafür anbietet, heißt "Vertex Buffer Objects". Mit einem VBO können Sie große Mengen an Geometrie mit einem einzigen Zeichenaufruf zeichnen (glDrawArrays, glDrawElements und ihre Verwandten).

Nachdem Sie die Geometrie aus dem Weg geräumt haben, müssen Sie nett zu der GPU sein. GPUs mögen es nicht, wenn man häufig Texturen oder Shader wechselt. Das Wechseln einer Textur macht den Inhalt des Cache ungültig, das Wechseln eines Shaders bedeutet ein Abwürgen der GPU-Pipeline, aber schlimmer noch, es macht die Ausführungspfad-Vorhersagestatistiken ungültig (die GPU führt Statistiken darüber, welche Ausführungspfade eines Shaders am wahrscheinlichsten ausgeführt werden und welche Speicherzugriffsmuster er aufweist; dies wird zur iterativen Optimierung der Shader-Ausführung verwendet).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X