OpenGL: VBO oder glBegin () + glEnd ()?

16

Vor kurzem habe ich diesen Link zu einer Tutorial-Site von jemandem erhalten, dem ich das ursprüngliche OGL-Redbook gegeben habe. In der dritten Überschrift steht deutlich, dass glBegin () und glEnd () als typische Rendermethode vergessen werden sollen. Ich habe über die Redbook-Methode gelernt, sehe aber einige Vorteile bei VBOs. Ist dies wirklich der richtige Weg, und wenn ja, gibt es eine Möglichkeit, den Rendercode und nachfolgende Shader einfach in VBOs und nachfolgende Datentypen zu konvertieren?

S. Fitzgerald
quelle

Antworten:

27

Mit modernen OpenGLs sind VBOs der Weg, feste Funktionen (einschließlich glBegin / glEnd und die Sachen dazwischen) sind seit 3.0 veraltet und seit 3.1 entfernt worden.

Mit dem OpenGL Core Profile, OpenGL ES 2.0+ und WebGL haben Sie nicht einmal Zugriff auf das alte Zeug.

Einige Leute denken, dass es besser ist, das Alte zuerst zu lernen, weil es ein bisschen einfacher ist, aber das, was man lernt, ist meistens nutzlos und das, was man verlernen muss.

Es sind jedoch nicht nur VBOs, Sie müssen für alles Shader verwenden und selbst Matrix-Transformationen durchführen (oder GLM verwenden).

Der einzige Grund, das alte Zeug zu benutzen, wäre, wenn Sie OpenGL vor 2.0 als Ziel haben wollten. Es gibt ein paar wirklich beschissene eingebettete Netbook-Chipsätze, die 1,5 sind, aber sogar 1,5 sollten VBOs unterstützen, nur keine Shader. Oder OpenGL ES 1.x, das auf der festen Funktionspipeline basiert (z. B. auf älteren iPhones). Oder OpenGL SC (für sicherheitskritische Systeme).

Die folgenden häufig verwendeten Funktionen sind alle veraltet:

  • glBegin
  • glEnd
  • glVertex *
  • glNormal *
  • glTextCoord *
  • glTranslate *
  • glRotate *
  • glScale *
  • glLoadIdenity
  • glModelViewMatrix

Die Tutorials auf opengl-tutorial.org bieten meines Erachtens die beste Möglichkeit, OpenGL zu erlernen. Sie verlassen sich auf einige der alten Kompatibilitätsmaterialien, bringen es Ihnen jedoch nicht bei. Sie sollten zum Beispiel nichts ohne Shader rendern, aber es funktioniert. Und Sie müssen Matrizenoperationen (Drehen, Übersetzen usw.) selbst ausführen, aber standardmäßig erhalten Sie ein einfaches flaches 2D-Ansichtsfenster.

Zusätzlich zum Vermeiden des veralteten Materials gibt es eine Reihe von Funktionen, die das Codieren von OpenGL viel angenehmer machen. Bei vielen von ihnen müssen Sie sich jedoch entscheiden, ob Sie mit neueren 3.x + -Versionen von OpenGL und kompatibler Hardware einverstanden sind.

Es gibt mehr Informationen in einem Beitrag, den ich hier gemacht habe .

Wenn Sie aus irgendeinem Grund älteres OpenGL unterstützen müssen, können Sie nach Möglichkeit VBOs verwenden und, wenn dies nicht der Fall ist, ein Fallback bereitstellen, das glBegin / glEnd verwendet und sich über Ihre Vertex-Daten erstreckt.

Auf der anderen Seite gibt es keine einfache Möglichkeit, alten Render-Code zu konvertieren. Sie könnten vielleicht Ihre eigene Version der Funktionen implementieren, die die Scheitelpunkte zu einem Array / Vektor hinzufügen, der es dann in einen VBO ausgibt und es zeichnet, wenn Sie fälschlicherweise glEnd aufrufen. Das wäre jedoch sehr ineffizient, da es jeden Frame ausführen würde (es sei denn, Sie setzen ein Häkchen, um es nur einmal auszuführen, aber das funktioniert nicht für animierte Objekte) und wahrscheinlich mehr Arbeit wäre, als nur zu VBOs zu wechseln. Ich nehme an, wenn Sie viel Code hätten, könnte dieser Ansatz funktionieren.

David C. Bishop
quelle
7

Mit VBOs haben Sie in der Regel zwei wesentliche Vorteile.

Vorteil 1 bezieht sich auf vollständig statische Daten und ergibt sich aus der Möglichkeit, Ihre Eckendaten im Speicher zu halten, der für die GPU optimaler ist.

Vorteil 2 bezieht sich auf dynamische Daten und ergibt sich aus der Möglichkeit, Ihre Scheitelpunktdaten zu einem beliebigen Zeitpunkt vor der Verwendung für das Rendern anzugeben, wodurch die Pipeline verbessert werden kann.

Ein dritter Vorteil ergibt sich aus der Stapelverarbeitung von Draw-Anrufen, wird aber auch mit Vertex-Arrays der alten Schule geteilt, sodass ich dies nicht speziell für VBOs ausspreche. Das Senden von Daten an eine GPU (oder das Verwenden von Daten, die sich bereits auf der GPU befinden) ähnelt in vielerlei Hinsicht dem Festplatten-E / A-Verkehr und dem Netzwerkverkehr. Wenn Sie einige große Stapel haben, ist dies effizienter als viele kleine Stapel.

Eine gute Analogie (nicht 100% genau, aber genug, um Ihnen zu helfen, die Idee zu verstehen) ist, wenn Sie ein Busfahrer sind, der 50 Personen von einer Stadt in eine andere bringen muss. Sie können sie einzeln laden und 50 verschiedene Fahrten durchführen - das ist glBegin / glEnd. Alternativ können Sie alle 50 von ihnen in den Bus setzen und nur eine einzige Fahrt machen - das ist eine Stapelung mit Vertex-Arrays oder VBOs (im VBO-Fall wären die 50 Personen bereits im Bus;)).

Dies ist jedoch mit einem Preis verbunden, und hier besteht der Preis darin, dass Sie die Möglichkeit verlieren, nur Eckendaten anzugeben, wenn Sie sie benötigen. Okay, das können Sie (mit ein wenig zusätzlicher Arbeit), aber Sie werden nicht die volle Leistung aus Ihrem Code herausholen. Stattdessen müssen Sie mehr über Ihre Vertex-Daten nachdenken, wie sie verwendet werden, wie (und ob) sie aktualisiert werden müssen, ob Animationen in einem Shader durchgeführt werden können (wodurch die Daten statisch bleiben können - VBOs benötigen Shader für a viele Animationsfälle, um gut zu funktionieren) oder ob Sie die Scheitelpunktdaten für jeden Frame neu spezifizieren müssen, effiziente Aktualisierungsstrategien, wenn letzteres usw. Wenn Sie dies nicht tun und nur eine naive Konvertierung implementieren, besteht ein sehr hohes Risiko für das Putten bei viel arbeit läuft nur das endergebnis tatsächlich langsamer!

Dies kann wie eine Menge Arbeit erscheinen, wenn Sie es zum ersten Mal begegnen, aber es ist nicht wirklich. Wenn Sie erst einmal so denken, werden Sie feststellen, dass es unglaublich einfach und fast selbstverständlich ist. Aber Sie können Ihre ersten Versuche vermasseln, und Sie sollten sich nicht entmutigen lassen, wenn dies der Fall ist. Vermasseln ist eine Gelegenheit, aus Ihren Fehlern zu lernen.

Ein paar abschließende Gedanken.

Wenn Sie Ihre Modelldaten in einem Format haben, das einfach in einen VBO geladen werden kann, kann dies den gesamten Vorgang für Sie erheblich vereinfachen. Das bedeutet, dass Sie zumindest zunächst komplexere oder exotischere Formate vermeiden sollten (und bis Sie sich mit dem Prozess besser auskennen). Halten Sie die Dinge beim Lernen so einfach und grundlegend wie möglich, und es wird weniger Dinge geben, die schief gehen, und weniger Orte, an denen nach Fehlern gesucht werden muss, wenn (oder wann!) etwas schief geht.

Menschen werden manchmal abgelehnt, wenn sie eine VBO-Implementierung sehen, die mehr Speicher als eine optimierte / komprimierte glBegin / glEnd-Implementierung verwendet (sie können dies sogar als "Verschwendung" bezeichnen). Sei nicht so. Außer in extremen Fällen ist die Speichernutzung wirklich nicht so wichtig. Dies ist ein klarer Kompromiss: Sie akzeptieren eine potenziell höhere Speichernutzung als Gegenleistung für eine wesentlich höhere Leistung. Es hilft auch dabei, die Einstellung zu entwickeln, dass das Gedächtnis eine billige und reichlich vorhandene Ressource ist, die genutzt werden kann. Leistung ist nicht.

Und schließlich die alte Kastanie - wenn es schon schnell genug ist, ist Ihre Arbeit erledigt. Wenn Sie Ihre Ziel-Framerate erreichen, wenn Sie Spielraum für vorübergehende Bedingungen haben, ist dies gut genug, und Sie können mit dem nächsten Schritt fortfahren. Sie können viel Zeit und Energie verschwenden , indem Sie 10% mehr aus etwas herausholen, das Sie nicht wirklich brauchen (seien Sie dabei, tun Sie das, tappen Sie immer noch in die Falle). Überlegen Sie sich also immer, wie Sie Ihre Zeit am besten nutzen - weil die Programmierzeit noch günstiger und weniger umfangreich ist als die Leistung!

Maximus Minimus
quelle