opengl - blending mit dem vorherigen Inhalt des framebuffer
Ich bin Rendern in eine textur über ein framebuffer-Objekt, und wenn ich zeichne transparenten primitive die primitive vermischt werden, die ordnungsgemäß mit anderen primitiven gezeichnet, single draw Schritt, aber Sie werden nicht verschnitten richtig mit dem vorherigen Inhalt des Framebuffers.
Gibt es einen Weg, um richtig mischen die Inhalte der Struktur mit den neuen Daten kommen?
EDIT: Mehr Informationen requsted, ich werde zu erklären versuchen, mehr klar;
Den blendmode ich verwende, ist GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA. (Ich glaube, das ist in der Regel die standard-blendmode)
Bin ich erstellen, eine Anwendung, die Spuren der Maus-Bewegung. Es zieht Verbindungslinien von der vorherigen position der Maus an der aktuellen Mauszeiger-position, und da ich nicht wollen, ziehen die Linien wieder jeden Rahmen, ich dachte, ich würde zeichnen Sie auf eine textur, nie klar, die textur und dann ziehen Sie einfach ein Rechteck mit textur, um es anzuzeigen.
Das alles funktioniert gut, außer, dass wenn ich zeichne Formen mit alpha weniger als 1 auf die textur, ist es nicht mischen richtig mit der textur der vorherigen Inhalte. Sagen wir, ich habe einige schwarze Linien mit alpha = .6 gezogen auf die textur. Ein paar ziehen Zyklen später habe ich dann zeichnen Sie einen schwarzen Kreis mit alpha = .4 über diesen Zeilen. Die Zeilen "unterhalb" der Kreis vollständig überschrieben. Obwohl der Kreis ist eben nicht schwarz (Es verschmilzt richtig mit dem weißen hintergrund) es gibt keine "dunkler Linien" unter dem Kreis, wie man es erwarten würde.
Wenn ich zeichnen Sie die Linien und den Kreis im gleichen Rahmen, aber Sie mischen richtig mit. Meine Vermutung ist, dass die textur nur nicht mischen mit seinem bisherigen Inhalt. Es ist wie es ist nur die Vermischung mit der glclearcolor. (In diesem Fall ist <1.0 f, 1.0 f, 1.0 f, 1.0 f>)
InformationsquelleAutor der Frage staticfloat | 2010-01-31
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich denke, es gibt zwei mögliche Probleme hier.
Denken Sie daran, dass alle overlay-Linien sind gemischt zweimal hier. Einmal, wenn Sie gemischt sind, in die FBO-textur, und wieder, wenn die FBO-textur überblendet wird, der über der Szene.
Also die erste Möglichkeit ist, dass Sie nicht haben, blending aktiviert beim zeichnen eine Linie über die andere in die FBO-overlay. Wenn Sie ziehen in ein RGBA-Oberfläche mit dem mischen aus der aktuellen alpha ist einfach geschrieben, die direkt in die FBO-overlay-alpha-Kanal. Dann später, wenn Sie mischen das ganze FBO-textur auf die Szene, die alpha macht Ihre Linien durchscheinend. Also, wenn Sie haben-blending "die Welt", aber nicht zwischen overlay-Elemente, ist es möglich, dass kein mischen passiert.
Ein weiteres Verwandtes problem: bei der Mischung eine Linie über die andere im "standard" blend-Modus (src alpha, 1 - src alpha) in der FBO, den alpha-Kanal von "blended" - Teil wird enthalten eine Mischung von die alphas der beiden overlay-Elemente. Dies ist wahrscheinlich nicht das, was Sie wollen.
Zum Beispiel, wenn Sie zeichnen Sie zwei 50% - alpha-Linien über einander in das overlay zu bekommen die gleiche Wirkung, wenn Sie blit-FBO, müssen Sie die FBO ' s alpha zu sein...75%. (1 - (1-.5) * (1-0.5), was passieren würde, wenn Sie nur zog zwei 50% - alpha-Linien in Ihrer Szene. Aber, wenn Sie beim zeichnen die zwei 50% - Linien, erhalten Sie 50% alpha in der FBO (eine Mischung aus 50%...50%.
Das bringt uns zu der letzten Frage: durch die pre-mischen der Linien mit einander, bevor Sie die Mischung über die Welt, die Sie ändern der Zeichenreihenfolge. In der Erwägung, dass Sie vielleicht gehabt haben:
Mischung(Mischung(Mischung(hintergrund, Farbe, Modell), erste Zeile) zweite Zeile);
nun haben Sie
Mischung(blend(erste Zeile, zweite Zeile), Mischung(hintergrund, Farbe, Modell)).
In anderen Worten, pre-mischen der overlay-Linien in ein FBO-ändert die Reihenfolge des vermischens und so ändert das endgültige Aussehen in einer Weise, die Sie können nicht wollen.
Zunächst die einfache Möglichkeit, dies zu umgehen: benutzen Sie nicht ein FBO. Ich weiß, das ist ein "go redesign Ihrer app" Art von Antwort, aber mit dem FBO ist nicht die billigste Sache, und moderne GL-Karten sind sehr gut im zeichnen von Linien. Also eine Möglichkeit wäre: statt der Vermischung von Linien in ein FBO, schreiben Sie die Zeile geometrie in ein vertex buffer object (VBO). Erweitern Sie ganz einfach die VBO ein wenig jedes mal. Wenn Sie zeichnen, weniger als, sagen wir, 40.000 Zeilen zu einer Zeit, dies wird mit ziemlicher Sicherheit so schnell wie das, was Sie Taten, bevor.
(Ein Tipp, wenn Sie diesen Weg gehen: verwenden Sie glBufferSubData zu schreiben die Zeilen nicht glMapBuffer - Zuordnung kann nicht teuer sein und funktioniert nicht auf sub-Bereiche auf vielen Treiber...besser, nur lassen sich die Treiber kopieren Sie die paar neue Ecken.)
Wenn das nicht eine option (zum Beispiel, wenn Sie zeichnen ein mix von Form, Art oder verwenden Sie eine Mischung von GL Zustand, so, dass "erinnern", was du getan hast ist viel komplexer als nur die Anhäufung vertices), dann möchten Sie vielleicht ändern, wie Sie ziehen in das VBO.
Im Grunde, was Sie tun müssen, ist, aktivieren separate blending; initialisieren der überlagerung schwarz + 0% alpha (0,0,0,0) und die Mischung von "standard-blending" die RGB -, sondern die additive blending das alpha-Kanäle. Dieser ist noch nicht ganz das richtige für den alpha-Kanal, sondern es ist in der Regel sehr viel näher - ohne dies im Laufe der gezogenen Bereiche werden zu transparent.
Dann, wenn die Zeichnung der FBO, verwenden Sie "pre-multipliziert" alpha, dass ist, (eins, eins-minus-src-alph).
Hier ist der Grund, dass im letzten Schritt ist erforderlich: wenn Sie beim zeichnen in der FBO, haben Sie bereits multipliziert jeder draw call-by-alpha-Kanal (wenn blending). Da Sie mit der Zeichnung in schwarz, eine grüne (0,1,0,0.5) Linie ist jetzt dunkel grün (0,0.5,0,0.5). Wenn alpha auf und mischen Sie wieder normal, die alpha ist erneut angewendet und Sie ' L haben 0,0.25,0,0.5.). Einfach mit der FBO Farbe so wie Sie ist, vermeiden Sie die zweite alpha-Multiplikation.
Dies wird manchmal als "pre-multipliziert" alpha, weil alpha schon multipliziert in die RGB-Farbe. In diesem Fall, dass Sie wollen, dass es um richtige Ergebnisse zu erzielen, in anderen Fällen aber, die Programmierer verwenden Sie es für die Geschwindigkeit. (Von pre-zu multiplizieren, es entfernt eine mult pro pixel, wenn die blend-op durchgeführt wird.)
Hoffe, das hilft! Immer mischen rechts, wenn die Schichten nicht vermischt, um mal wirklich knifflig, und eine separate Mischung nicht auf alte hardware, so einfach zeichnen von Linien jeder Zeit kann der Weg des geringsten Elend.
InformationsquelleAutor der Antwort Ben Supnik
Klar das FBO mit transparent schwarz (0, 0, 0, 0), zeichnen Sie es in back-to-front mit
und zeichnen Sie die FBO mit
um das genaue Ergebnis.
Als Ben Supnik schrieb, FBO-enthält den Farbstoff bereits multipliziert mit dem alpha-Kanal, also anstatt das zu tun, wieder mit GL_SRC_ALPHA, es ist gezeichnet mit GL_ONE. Das Ziel ist in der Farbe abgeschwächt, die normalerweise mit GL_ONE_MINUS_SRC_ALPHA.
Der Grund für das mischen der alpha-Kanal in dem Puffer dieser Weg ist anders:
Die Formel zu kombinieren Transparenz ist
(Ich verwende s und d, weil der parallel zu OpenGL Quelle und Ziel, aber wie Sie sehen können, die Reihenfolge spielt keine Rolle.)
Geschrieben mit Linsentrübung (alpha-Werte), dies wird
das ist das gleiche wie die blend-Funktion (Quell-und Ziel-Faktoren) (GL_ONE, GL_ONE_MINUS_SRC_ALPHA) mit dem Standard -blend Gleichung GL_FUNC_ADD.
Nebenbei:
Den oben genannten Antworten, die das problem aus der Frage, aber wenn Sie können wählen Sie einfach die Zeichenreihenfolge kann es in der Theorie besser zu zeichnen integriert Farbe in den Puffer front-to-back mit
und anderweitig zu verwenden die gleiche Methode.
Meine Argumentation hinter diesem ist, dass die Grafikkarte möglicherweise in der Lage zu überspringen shader-Ausführung für die Regionen, die bereits solide. Ich habe noch nicht getestet, obwohl, so kann es keinen Unterschied machen in der Praxis.
InformationsquelleAutor der Antwort Tamschi
Als Ben Supnik sagte, der beste Weg, dies zu tun, ist das rendering der gesamten Szene, mit separaten blend-Funktionen für Farbe und alpha. Wenn Sie mit den klassischen, nicht integrierte blend-Funktion versuchen glBlendFuncSeparateOES(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE) zum Rendern Ihrer Szene zu FBO. und glBlendFuncSeparateOES(GL_ONE, GL_ONE_MINUS_SRC_ALPHA) zum Rendern der FBO auf den Bildschirm.
Es ist nicht 100% genau, aber in den meisten Fällen zu schaffen, der keine unerwarteten Transparenz.
Beachten Sie, dass alte Hardware und einige mobile Geräte (meist OpenGL ES 1.x-Geräte, wie das original iPhone und 3G) unterstützt nicht getrennt blend-Funktionen. 🙁
InformationsquelleAutor der Antwort Filipi Nascimento Silva