PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : OpenGL Objekte sortieren


rotalever
2006-08-08, 15:02:11
Wenn man Objekte mit teilweise transparent Texturen in OpenGL zeichnen will muss man ja zuerst alle nicht transparenten Objekte mit aktiviertem ZBuffer zeichen und dann den ZBuffer auf nur lesbar stellen und über das Blending die transparenten Objekte zeichnen (entnommen aus red book).
Damit das korrekt geschieht, müssen die transparenten Objekte aber sortiert werden. Da liegt jetzt mein Problem. Vor dem Zeichen werden ja einige Matrix-Operationen an den Objekten ausgeführt, unter anderem ein drehen. Beim sortieren der Objekte muss ich das drehen aber auch berücksichtigen oder? Dadurch ändern sich ja schließlich ihre Z-Koordinaten. Und weiter ist es so, dass zum Beispiel drei Objekte so im Kreis liegen könnten, dass nicht bestimmt werden kann, welches das vorderste ist. Oder auch wenn sie sonst irgendwie verdreht zueinander im Raum liegen. Wie muss ich da beim sortieren Vorgehen, bzw. gibt es noch andere alternativen zum korrekten Zeichnen? Irgendwie muss das ja gehen, schließlich findet man das ja in zahlreichen Spielen.

Gruß, rotalever

tokugawa
2006-08-08, 16:11:26
In Spielen kommen als transparente Objekte fast nur "einfache" Objekte vor, etwa Partikel (Explosionen, Rauch), oder Billboards. Jene sind recht einfach zu sortieren (etwa einfach Abstand vom Mittelpunkt zu Augpunkt, und danach sortieren - man kann auch einfach den quadrierten Abstand sortieren, dann erspart man sich die Wurzel). Hier brauchst du auch nicht wirklich vorher den Z-Buffer rendern - Sortieren back-to-front und danach rendern reicht (Painter's Algorithm).

Bei komplexeren transparenten 3D-Meshes (speziell nichtkonvexe) kann es zu Visibility-Cycles kommen (wenn ein Teil von Objekt A Objekt B verdeckt, und ein Teil von Objekt B Objekt A). In diesem Fall mußt du eine Art "Depth-Peeling" verwenden (mit 2 Depthbuffern und "Depthbuffer-Ping-Ponging"). Dies verwendet aber kaum ein Spiel, da diese Art von transparenten Objekten möglichst verhindert wird.

Gast
2006-08-08, 16:56:39
1. Ja, aber wenn ich mich zum beispiel um so eine Partikelwolke rumbewege, dann sehe ich sieh von verschiedenen Seiten. Die erzeuge ich mit einem rotieren mittels der Matrixrotation von OpenGL (glRotatef(...)). Beim sortieren müsste ich doch diese Drehung berücksichtigen oder nicht? D.h. die eigentlichen Koordinaten der Partikel im Raum stimmen nicht mehr mit denen Überein, die ich in meinem Partikel-Array gespeichert habe, weil diese durch die Matrixmanipulation verändert worden sind.

2. Wenn ich bei einem Baum die Blätter durch große Texturen simuliere, dann habe ich ja transparente Bereiche zwischen den Blättern. Um die Blätter korrekt darzustellen müsste ich sie also eigentlich auch sortieren. Genausogut könnte ich mir das auch bei anderen Objekten vorstellen. Wie man soetwas vermeinden kann würde ich auch gern mal wisen.

Gast
2006-08-08, 17:32:11
1. Ja, aber wenn ich mich zum beispiel um so eine Partikelwolke rumbewege, dann sehe ich sieh von verschiedenen Seiten. Die erzeuge ich mit einem rotieren mittels der Matrixrotation von OpenGL (glRotatef(...)). Beim sortieren müsste ich doch diese Drehung berücksichtigen oder nicht? D.h. die eigentlichen Koordinaten der Partikel im Raum stimmen nicht mehr mit denen Überein, die ich in meinem Partikel-Array gespeichert habe, weil diese durch die Matrixmanipulation verändert worden sind.ein solches Problem hatte ich beim Experimentieren mit einem der Nehe-Tutorials, einem von denen mit dem rotierenden Würfel. Wenn ich da die Würfelflächen transparent gemacht habe, ergaben sich je nachdem, welche Seite nach vorne zeigte, ganz komisch aussehende Effekte.

Die einzige Lösung wird wohl darin bestehen, daß du Drehungen nicht bequem durch Matrixmanipulation mit glRotate machst, sondern von Hand mit sin und cos, und dabei das Koordinatensystem von OpenGL in Ruhe läßt. Ist natürlich mehr Arbeit.

Alternativ kannst du auch das Blending so einstellen, daß der Destination-Faktor von der Source unabhängig ist, also z.B. statt GL_SRC_ALPHA für Source und GL_ONE_MINUS_SRC_ALPHA für Destination für beide GL_ONE, dann ist die Sortierung egal.

2. Wenn ich bei einem Baum die Blätter durch große Texturen simuliere, dann habe ich ja transparente Bereiche zwischen den Blättern. Um die Blätter korrekt darzustellen müsste ich sie also eigentlich auch sortieren. Genausogut könnte ich mir das auch bei anderen Objekten vorstellen. Wie man soetwas vermeinden kann würde ich auch gern mal wisen.dafür gibt es den Alpha-Test. Da ist jeder Texel deiner Textur entweder komplett undurchsichtig (Blätter), oder komplett durchsichtig (Zwischen zwischen den Blättern). Da braucht es dann kein Blenden (also Mischen) mehr, und die Sortierung ist wieder egal.

rotalever
2006-08-08, 17:53:38
Also bevor ich jetzt meinen Baum zeichne aktiviere ich glEnable(GL_ALPHA_TEST) . Das Blending ist ausgestellt und sonst ist noch der DepthBuffer auf glEnable(GL_DEPTH_TEST);glDepthFunc(GL_LESS);
Die Textur lade ich aus einem PNG und ist an den Stellen wo kein Blätter sind vollkommen durchsichtig. Trotzdem werden diese Bereiche nicht transparent dargestellt.

edit: ok habs gefunden glAlphaFunc(GL_GREATER, ...);

tokugawa
2006-08-08, 18:57:15
1. Ja, aber wenn ich mich zum beispiel um so eine Partikelwolke rumbewege, dann sehe ich sieh von verschiedenen Seiten. Die erzeuge ich mit einem rotieren mittels der Matrixrotation von OpenGL (glRotatef(...)). Beim sortieren müsste ich doch diese Drehung berücksichtigen oder nicht? D.h. die eigentlichen Koordinaten der Partikel im Raum stimmen nicht mehr mit denen Überein, die ich in meinem Partikel-Array gespeichert habe, weil diese durch die Matrixmanipulation verändert worden sind.


Du mußt sowieso die Partikel einzeln sortieren, wenn die im Koordinatensystem der Partikelwolke gespeichert sind, mußt du halt die Positionen der Einzelparktikel in Weltkoordinaten transformieren und dort mittels Abstand zum Augpunkt sortieren.


2. Wenn ich bei einem Baum die Blätter durch große Texturen simuliere, dann habe ich ja transparente Bereiche zwischen den Blättern. Um die Blätter korrekt darzustellen müsste ich sie also eigentlich auch sortieren. Genausogut könnte ich mir das auch bei anderen Objekten vorstellen. Wie man soetwas vermeinden kann würde ich auch gern mal wisen.

Bei Bäumen würdest du wohl, auch aus Performance-Gründen, eher auf Alpha-Testing setzen.

Und auch bei Blending würde man tw. recht approximativ vorgehen. Grad bei Massen-Partikeln wie Gräsern ist es egal ob da einzelne Grashalme nicht richtig sortiert sind, sondern das Gesamtbild muß passen. Deswegen kommt man eventuell mit einer billigeren Methode ("Distanz Mittelpunkt-Augpunkt") aus, trotz Drehung.

Xmas
2006-08-08, 19:21:31
1. Ja, aber wenn ich mich zum beispiel um so eine Partikelwolke rumbewege, dann sehe ich sieh von verschiedenen Seiten. Die erzeuge ich mit einem rotieren mittels der Matrixrotation von OpenGL (glRotatef(...)). Beim sortieren müsste ich doch diese Drehung berücksichtigen oder nicht? D.h. die eigentlichen Koordinaten der Partikel im Raum stimmen nicht mehr mit denen Überein, die ich in meinem Partikel-Array gespeichert habe, weil diese durch die Matrixmanipulation verändert worden sind.
Ja, um die Objekte korrekt zu sortieren musst du den Tiefenwert im Viewspace ermitteln. Das kann aber in mehrerer Hinsicht vereinfacht werden:
- Partikel müssen selten untereinander sortiert werden, sofern du garantieren kannst dass kein anderes transparentes Objekt die Partikelwolke durchdringt. Sind sie "leuchtend" (Feuer), so brauchst du additives Blending. Sind sie abschirmend und annähernd einfarbig (Rauch) müssen sie auch nicht sortiert werden. In beiden Fällen kann die Partikelwolke als ein einziges Objekt betrachtet werden, das dann nur noch unter den anderen transparenten Objekten sortiert werden muss.
- Zum sortieren brauchst du nur Z im Viewspace. Dazu benötigt man keine vollständige Matrix-Vektor-Multiplikation, sondern nur ein 3-Komponenten-Skalarprodukt (sofern deine Eckpunkte alle ein identisches W haben) mit der dritten Zeile der Modelview-Matrix.
- Space-Partitioning-Strukturen wie BSP oder Octree erlauben eine schnelle Sortierung ohne Berechnung der tatsächlichen Tiefenwerte.

2. Wenn ich bei einem Baum die Blätter durch große Texturen simuliere, dann habe ich ja transparente Bereiche zwischen den Blättern. Um die Blätter korrekt darzustellen müsste ich sie also eigentlich auch sortieren. Genausogut könnte ich mir das auch bei anderen Objekten vorstellen. Wie man soetwas vermeinden kann würde ich auch gern mal wisen.
Wenn der Baum nicht besonders komplex ist, kann man problemlos sortieren (allerdings muss man Polygone aufteilen, wenn sie sich durchdringen). Dazu speichert man die Sortierreihenfolge für das nächste Frame, so dass man von einer annähernd sortierten Liste ausgeht.
Oder man nimmt Alpha-Test, sieht aber nicht so schön aus.

Mit Alpha-Test ist die beste Renderreihenfolge übrigens:
- Nicht-transparente Objekte erst nach Renderstates, dann grob front-to-back sortiert
- Objekte mit Alpha-Test nach Renderstates, dann sehr grob front-to-back sortiert
- Objekte mit Alpha-Blending back-to-front ohne Z-Writes

rotalever
2006-08-08, 20:28:49
- Partikel müssen selten untereinander sortiert werden, sofern du garantieren kannst dass kein anderes transparentes Objekt die Partikelwolke durchdringt.
Stimmt ist eigentlich klar, sieht schließlich ohne sortierung wunderbar aus.
... als ein einziges Objekt betrachtet werden, das dann nur noch unter den anderen transparenten Objekten sortiert werden muss.
Gute idee...
- Zum sortieren brauchst du nur Z im Viewspace. Dazu benötigt man keine vollständige Matrix-Vektor-Multiplikation, sondern nur ein 3-Komponenten-Skalarprodukt (sofern deine Eckpunkte alle ein identisches W haben) mit der dritten Zeile der Modelview-Matrix.
Das muss ich mir dann erstmal genauer anschauen... Aber scheint wohl war zu sein.

Wenn der Baum nicht besonders komplex ist, kann man problemlos sortieren (allerdings muss man Polygone aufteilen, wenn sie sich durchdringen). Dazu speichert man die Sortierreihenfolge für das nächste Frame, so dass man von einer annähernd sortierten Liste ausgeht.
Oder man nimmt Alpha-Test, sieht aber nicht so schön aus.
Vielleicht begnüge ich mich da doch lieber erstmal mit Alpha-Test.
Mit Alpha-Test ist die beste Renderreihenfolge übrigens:
- Nicht-transparente Objekte erst nach Renderstates, dann grob front-to-back sortiert
- Objekte mit Alpha-Test nach Renderstates, dann sehr grob front-to-back sortiert
- Objekte mit Alpha-Blending back-to-front ohne Z-Writes
Was meinst Du damit? Ich mach es so:

glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
"Normale" Objekte malen
glEnable(GL_ALPHA_TEST);
Bäume malen
glDisable(GL_ALPHA_TEST);
glEnable(GL_BLEND);
glDepthMask (GL_FALSE);
glBlendFunc(GL_SRC_ALPHA,GL_DST_ALPHA);
Feuer malen
glDepthMask (GL_TRUE);
(hier zwischen noch 2D aber das ist unwichtig)
glDisable(GL_BLEND);

Gast
2006-08-09, 10:05:49
Mit Alpha-Test ist die beste Renderreihenfolge übrigens:
- Nicht-transparente Objekte erst nach Renderstates, dann grob front-to-back sortiert
- Objekte mit Alpha-Test nach Renderstates, dann sehr grob front-to-back sortiert
- Objekte mit Alpha-Blending back-to-front ohne Z-Writesund warum ist das die beste Reihenfolge?
Müßte die Reihenfolge beim Alpha-Test nicht egal sein? D.h. wenn man z.B. zuerst ein teilweise durchsichtiges Objekt vorne zeichnet und dann ein Objekt dahinter, werden die von den durchsichtigen Teilen des vorderen Objektes verdeckten Teile des hinteren Objektes trotzdem gezeichnet, oder?

Xmas
2006-08-09, 11:23:52
Für das Ergebnis ist die Reihenfolge egal, für die Performance ist es meist besser zuerst alle nicht-transparenten Objekte zu rendern, da Alpha-Test und Early-Z-Methoden nicht gut zusammenarbeiten.

Gast
2006-08-09, 12:10:57
glBlendFunc(GL_SRC_ALPHA,GL_DST_ALPHA);
was ist eigentlich der Sinn dieser Zeile? Du nimmst Source Alpha als Source Faktor, Destination Alpha als Destination Faktor, wozu soll das gut sein?
Wenn die Source die Destination entsprechend ihres Undurchsichtigkeitsgrades verdecken soll, wäre (GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA) am sinnvollsten: der Destination-Faktor ist umso höher/niedriger, je transparenter/undurchsichtiger die Source ist.
Sollen dagegen Source und Destination additiv gemischt werden, würde sich als Destination-Faktor GL_ONE anbieten, oder, wenn du ein paar nette Farbeffekte haben willst, GL_DST_COLOR.
Die Berücksichtigung von Destination Alpha macht eigentlich in keinem Fall wirklich Sinn.

rotalever
2006-08-09, 12:17:26
was ist eigentlich der Sinn dieser Zeile? Du nimmst Source Alpha als Source Faktor, Destination Alpha als Destination Faktor, wozu soll das gut sein?
Ok GL_ONE ist wohl besser allerdings liefert es dasselbe Ergebnis...
(In diesem Fall für Feuer, wodurch sich bei Oranger Farbe eine Farbverlauf von Weiß -> Gelb -> Rot durch das Blenden ergibt)