OpenGL: Verständnisfrage zum Blending



  • Ich hab mal eine kleine Verständnisfrage zum Blending in OpenGL.
    Momentan benutze ich diese Blending Funktion:

    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
    

    Was für mich heißt, dass abhängig vom Alpha-Wert die "Durchsichtigkeit" eines Objekts bestimmt wird.
    Wenn ich jetzt aber eine Display Liste habe, mit der ein rotes Quadrat gezeichnet wird, und ich darüber ganz normal ein schwarzez Quadrat render, sehe ich das schwarze Quadrat komplett ohne durchsichtigkeit. Wenn ich das schwarze Quadrat jetzt in eine Display Liste packe und die beiden übereinander render, ist das schwarze Quadrat bei mir halb durchsichtig.
    Woran liegt das, und wie schaffe ich es, dass das schwarze Quadrat auch in einer Display Liste undurchsichtig bleibt?



  • Kannst du einen Beispielcode zur Verfügung stellen, der das Problem wiedergibt?



  • Ich versteh noch nicht ganz was du erreichen möchtest.

    Du zeichnest also zwei unterschiedlich gefärbte Quadrate und möchtest blending einsetzen. Soweit so gut.
    Die Blend-Funktion klappt natürlich nur wenn du im RGBA Modus arbeitest und auch Alpha-Werte angibst.
    Bei aktivem Depth-Testing muss natürlich ebenfalls eine vernünftige Funktion eingestellt sein. (GL_LESS) wird beispielsweise nicht klappen, wenn du mit gleichen Z-werten arbeitest.

    Ob du DisplayListen verwendest sollte eigentlich ziemlich egal sein. Wenn es bei dir einen Unterschied macht, dann musst du nochmal deinen code durchgehen, ob du beispielsweise irgendwo glDisable(GL_BLEND) aufrufst.

    Warum du allerdings erreichen möchstes, dass das schwarze Quadrat keine Transluzenz aufweist ist mir jetzt nicht klar. Genau das möchtest du doch mit deiner BlendFunktion erreichen.

    openglnoob schrieb:

    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
    

    Was für mich heißt, dass abhängig vom Alpha-Wert die "Durchsichtigkeit" eines Objekts bestimmt wird.

    Das ist so nicht ganz richtig. Du gibst hier an, wie die Blending-Faktoren für source UND destination berechnet werden sollen. Es werden also nicht nur die Farbwerte des neuen Fragments modifiziert, sondern auch die Destination-Werte. Letztendlich wird dadurch natürlich ein Transluzenter Effekt erreicht, aber es werden eben nicht NUR die Werte der ab jetzt gezeichneten Objekte geändert.

    Wie die Berechnung vonstatten geht wird im Kapitel 7 des Redbooks erklärt.



  • inter2k3 schrieb:

    Warum du allerdings erreichen möchstes, dass das schwarze Quadrat keine Transluzenz aufweist ist mir jetzt nicht klar. Genau das möchtest du doch mit deiner BlendFunktion erreichen.

    Ich möchte, die Transluzenz anhand des Alpha-Werts des gezeichneten Obekts bestimmen.



  • Ich versuch es mal kurz zu erklären:

    Mit der glBlendFunc(source,destination) gibst du an, wie die Blending-Faktoren berrrechnet werden sollen.

    Source wird auf das neu zu zeichnende Objekt angewand, Destination auf die werte im framebuffer.

    Dabei werden die Rot-, Blau-, Grün- und Alphawerte des Sourceobjekts mit dem source-Faktor multipliziert und die entsprechenden Werte im framebuffer mit dem destination-Faktor.
    Anschliessend werden die berechneten bieden Rotwerte addiert und dann auf das Intervall [0.0f..1.0f] beschnitten (kann ja sein dass bei der Addition ein Wert >1.0f entsteht).
    Das gleiche wird jetzt für den Blau- Grün- und Alphaanteil gemacht.
    Soweit zur Funktionsweise.

    Nehmen wir dein konkretes Beispiel:
    Du zeichnest erstmal mit deaktiviertem blending ein rotes Quadrat mit einem Farbwert von (1.0f,0.0f,0.0f,1.0f).
    Das sind dann auch erstmal die Farbwerte, die im framebuffer stehen.

    Jetzt aktivierst du blending mit glEnable(GL_BLEND) und zeichnest ein schwarzes Quadrat, dass transluzent sein soll. Beispielsweise nimmst du die Farbwerte (0.0f,0.0f,0.0f,0.75f).

    Benutzt du die BlendingFunktion glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA) erhalten wir also folgende Farbwerte:
    -für das neue schwarze Quadrat: (0.0f * 0.75f, 0.0f * 0.75f, 0.0f * 0.75f, 0.75f * 0.75f ) = (0.0f, 0.0f, 0.0f, 0.5625f), also weiterhin schwarz 🙂
    -die destination-werte werden mit 0.25f multipliziert (wegen 1-srcAlpha): (1.0f * 0.25f, 0.0f * 0.25f, 0.0f * 0.25f, 1.0f * 0.25f) = (0.25f, 0.0f, 0.0f, 0.25f)

    Jetzt werden die Werte addiert und das ist das sind dann die neuen Farbwerte im framebuffer: (0.0f + 0.25f, 0.0f + 0.0f, 0.0f + 0.0f, 0.5625f + 0.25f) = (0.25f, 0.0f, 0.0f, 0.8125f)

    Du erhälst also ein wesentlich dunkleres rotes Quadrat, da die Transluzenz des schwarzen Quadrates ja nur bei 25% lag.
    Das Problem bei einem schwarzen Quadrat ist, dass die Farbwerte alle 0 sind, und du somit schlecht die Auswirkung des Blendings erkennen kannst, da bei der Multiplikation mit dem Blendfaktor natürlich die neuen Werte wieder 0 sind. Vielleicht ist das der Grund, warum du da noch nicht ganz durchschaust.

    Ob dabei DisplayListen verwendet werden oder nicht ist völlig egal. Du musst nur darauf achten, wann und wo du bestimmte Zustände aktivierst bzw deaktivierst. Steht z.B. in der Displayliste glEnable(GL_BLEND), aber nirgends ein entsprechendes glDisable(GL_BLEND), so wird beim nächsten Durchlauf natürlich alles geblendet, also auch das rote Quadrat.

    Um die ganzen BlendFaktoren besser zu verstehen würde ich einfach mal die Hintergrundfarbe auf ein helles grau setzten, dann das rote Quadrat zeichen, eine BlendFunktion angeben, und dann ein sagen wir mal gruenes Quadrat zeichnen, dieses allerdings leicht versetzt zum roten, sodass nur eine Teilüberlappung entsteht. So lässt sich am besten nachvollziehen, warum und wie welche Farbwerte entstehen.



  • Es ist zwar eine wiki für Delphi und OpenGL. Aber die Funktions ist die selbe und die Erklärung ist sehr gut:
    http://wiki.delphigl.com/index.php/glBlendFunc


Anmelden zum Antworten