Ich tue mich immer noch sehr schwer mit den verschiedenen Blend Modi, vielleicht aber auch weil ich immer irgendwelche "Sonderfälle" habe:
Siehe Anhang. Ich befinde mich im glOrtho-Modus. Alles in 2D, damit nichts verzerrt, sondern Alles pixelgenau dargestellt wird.
Entsprechend Tutorial 7 ( https://wiki.delphigl.com/index.php/Tutorial_Lektion_7 ) rendere ich zuerst das Hintergrundbild. Dies kann zwar nach Benutzereinstellung teilweise transparent sein (entweder wegen Alpha < 100% oder weil PNG-Bild mit Teiltransparenz). Hier in diesem konkreten Beispiel nehmen wir aber an, dass es zu 100% deckend dargestellt wird.
Nun wird mit glVertex2i(x, y) eine halbtransparente, weiße Box drübergelegt.
Vielleicht nicht ganz unwichtiger Hinweis: Ich zeichne in einen FrameBuffer, was vielleicht zusätzliche Probleme mit sich bringt, und Diese hier überhaupt erst erzeugt:
Statt dass das dunkelblaue Hintergrundbild ein wenig aufgehellt wird, wird dieses nun selbst an den betroffenen Pixelstellen 50% transparent. Damit habe ich nun genau die Situation vom Tutorial ("Der ahnungslose Programmierer wird dann mit großen Augen vor dem Fenster stehen und sich wundern, wieso er durch die hintere Wand des Hauses ins Freie sehen kann."), obwohl ich jedoch zuerst die hintere Wand gezeichnet habe.
Ich denke, ich kenne die Ursache des Problems: Da im 2D-Modus (von mir) alles auf die Z-Ebene "0" gezeichnet wird, hat eben der Zeichenvorgang "Recht", der zuletzt gezeichnet hat. Wenn ich zuerst den betroffenen Bereich deckend zeichne (Wolken / Dunkelblau), und dann die kleinere halbtransparente Box drüberzeichne, wird in diesem Bereich (leider?) nicht einfach nur die Farbe des kleinen Bereichs halbtransparent dazuaddiert, sondern auch der komplette Alphawert der Z-Ebene 0 auf 50% gesetzt.
Ich arbeite bisher mit glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Vermutlich gibt es zwei korrekte Lösungswege: 1) Arbeiten mit "Tiefe", also Z Korrdinate --> glVertex3i . Hintergrundbild mit Z-Koordinate wirklich "hinter" der kleineren Box zeichnen, damit sollte es dann auch keine Probleme geben, wenn das Hintergrundbild mit Alpha nur 90% deckend ist...(?) Problem: Ich muss nun nachträglich überall in meinen Programmen die Z-Ebene einführen, was erheblicher aufwand wäre...
2) Arbeiten mit anderem BlenModus/BlendFunc (Welchem?) Im Tutorial sind ja zahlreiche Möglichkeiten erleutert, die man einfach nur Auswählen muss. Leider weiß ich nicht, was ich auswählen möchte. Wenn ich z.B. DST-Alpha behalten möchte, wird dann die kleine Box gar nicht mehr geblendet sonder zu 100% decken draufgeklatscht oder wie? (Leider setzen meine einzelnen Objekt jeweils mehrmals glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) damit, nach meiner damaligen Meinung, auch alles richtig gezeichnet wird (ist ja ansonsten auch der Fall); damit kann ich nicht "mal eben" in einen anderen Blendmodus wechseln und auch wirklich Resultate sehen.
glBlend kann ich auch für das Hintergrundbild nicht pauschal ausschalten, da ja im richtigen Betrieb auch das Hintergrundbild halbtransparent sein kann (es liegt dann noch ein anderes Hintergrundbild hintendran...).
Falls ich auf mehrere Z-Ebenen umstellen soll, wie mache ich das am unproblematischsten für den kompletten Code? glDepthFunc(GL_ALWAYS), und bei glVertext3i die Z-Koordinate immer entsprechend ändern so, wie ich bisher "von Hinten nach Vorne" gezeichnet habe?
Sobald Transparenz verwendet wird, kann der Tiefentest zumindest für diese Teile nicht mehr benutzt werden. Dies würde zu Fehlern führen, da das transparente Fragment ggfs. das durchscheinende, jedoch erst später an die Grafik-Pipeline gesendete und somit vom Tiefentest verworfene Fragment dahinter völlig verbirgt. Wenn man Transparente Fragmente nicht in den Tiefenbuffer schreibt, so können diese Fragmente von anderen, eigentlich weiter hinten liegenden, Fragmenten komplett überschrieben werden. Aus diesem Grund sollten Transparente Objekte nach allen anderen Objekten an OpenGL geschickt werden und diese möglichst von hinten nach vorne sortiert sein. Das Sortieren kann durch einen Alpha Wert im Framebuffer umgangen werden, jedoch ist dieser nur selten in Hardware vorhanden, wodurch in den weit langsameren Softwaremodus gewechselt wird.
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
Zuletzt geändert von berens am Mo Jul 09, 2018 13:16, insgesamt 1-mal geändert.
Sobald Transparenz verwendet wird, kann der Tiefentest zumindest für diese Teile nicht mehr benutzt werden. Dies würde zu Fehlern führen, da das transparente Fragment ggfs. das durchscheinende, jedoch erst später an die Grafik-Pipeline gesendete und somit vom Tiefentest verworfene Fragment dahinter völlig verbirgt. Wenn man Transparente Fragmente nicht in den Tiefenbuffer schreibt, so können diese Fragmente von anderen, eigentlich weiter hinten liegenden, Fragmenten komplett überschrieben werden.
Ich denke, damit hast du den Nagel auf den Kopf getroffen. Wen man Alpha-Blending verwendet, ist es sehr wichtig, in welcher Reihenfolge gezeichnet wird. Man muss die Objekte/Meshes sortieren.
Edit siehe unten, ich will nicht dauernd Beiträge "spammen"
Also das Problem hängt definitiv mit dem Framebuffer zusammen!
Das möchte ich machen (ein kleines, halbtransparentes, rotes Rechteck auf einem blauen undurchsichtigem) im glOrto-Modus entsprechend Dimensdimensionen des Fensters, bzw. FBO.
Dateianhang:
2018-07-09 11_52_48-OhneFrameBuffer.png
Dateianhang:
2018-07-09 11_52_48-MitFrameBuffer.png
Vielleicht habe ich in der Framebufferunit ein Fehler/Problem mit dem Tiefenpuffer?
Edit 1: Zunächste mal wieder vielen Dank an @mathias für den bisherigen Tip.
Die Erkenntnis, dass das Problem definitiv mit FrameBufferObject (FBO) und Alpha-Werten zu tun hat, lieferte mit nun auch seeehr viele Ergebnisse zum selben Thema hier im Forum.
Die Eigentliche Lösung kam von @Bergmann89 - ich folge ihm mit der Erfahrungssammlung in OpenGL was Probleme etc. an geht sehr direkt nach, bin halt nur ein paar Jahre hinten dran
Wie bereits festgestellt, überschreiben die zuletzt gerenderten Objekte -auch wenn Sie näher am Betrachter liegen- den Alpha-Wert des dahinterliegenden Objektes - wenn in eine Framebufferobject (FBO) gezeichnet wird! (Wie gesagt, beim normalen rendern geht alles.) Stellen wir uns den FBO einfach als normale Textur oder PNG-Datei mit Transparenz vor, so ist nun das Bild an Stellen teilweise oder komplett durchsichtig, wo eigentlich nur ein Objekt hätte draufgeblendet werden sollen.
Die Lösung lässt sich nun auch bei mir einfach anwenden: Der Hintergrund des Framebuffers muss nun nochmal seinen kompletten Alpha-Wert neu zeichnen. Nur Alpha, nicht das Bild (Freche Kopie aus dem verlinkten Thread):
Code:
glColorMask(False,False,False,True);
glColor4f(1,1,1,1);
glDisable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glVertex2f(0,0);
glVertex2f(W(Button),0);
glVertex2f(W(Button), H(Button));
glVertex2f(0, H(Button));
glEnd;
glEnable(GL_TEXTURE_2D);
glColorMask(True,True,True,True);
Mein Pendant ist:
Code:
glEnable(GL_BLEND);
glColorMask(False,False,False,True);
glColor4f(1,1,1,1);
Background.Render;
glColorMask(True,True,True,True);
Somit kann nun das Hintergrundbild immernoch problemlos Transparent sein ("Farbverlauf" von Deckend zu Transparent, PNG mit teilweiser Transparenz, ...) es wird (für mich: ebenso überraschender wie erfreulicher Weise) korrekt dargestellt. Da die Elemente im Vordergrund schon vorher gerendert und geblendet waren (die kleinen Boxen und bei mir der Text etc.) hat das drüberzeichnen eines "anderen" Alphawertes nun keine Auswirkungen mehr, die das Ergebnis verfälschen würden.
Wieder was gelernt, danke für Lesen und Antworten!
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
Mitglieder in diesem Forum: 0 Mitglieder und 22 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.