2009-07-02 6 views
1

Bei dem Versuch, meine 2D Shadow-Rendering-Technik von DirectX nach OpenGL zu portieren, bin ich auf ein Problem gestoßen, bei dem ich nicht gut genug auf den OpenGL-Mixer zugreifen kann.Wie kann ich die Farb- und Alpha-Mischfunktionen in opengl trennen?

Aber zuerst, so dass die folgenden macht Sinn, mein Algorithmus:

ich alle Sprites ohne Verwendung eines Tiefenpuffer von hinten nach vorne sortieren und machen. Schatten-Sprites werden unmittelbar vor den Objekten gezeichnet, die sie darstellen, und verwenden den zweiten Mischstatus unten, gShadowBlendState. Das bringt sie dazu, nur ihre Alpha-Werte auf den Alpha-Kanal des Framebuffers zu zeichnen.

Sprites für reguläre Objekte verwenden gBlendState, das zuerst unten angegeben wird. Dies ist nur eine normale Alpha-Mischung zum Backbuffer. Sie entfernen jedoch auch Alpha aus dem Backbuffer-Alpha-Kanal, so dass sie undurchsichtig sind. Dadurch wird sichergestellt, dass Schatten nicht durch undurchsichtige Objekte vor ihnen angezeigt werden.

Die dritte Sache, die gezeichnet wird, und die nach allem anderen gezeichnet wird, ist ein Fullscreen-Quad, das die Verwendung der Schattenfarbe und des endgültigen Mischzustands unten rendert. Es nutzt den Alpha-Kanal des Backbuffers für die Deckkraft und bringt so effektiv alle Schatteninformationen zum Vorschein.

Der ganze Sinn dieser Übung ist es, Schatten zu bekommen, die dort, wo sie sich überlappen, nicht dunkler werden.

gBlendState.SrcBlend  = D3DBLEND_SRCALPHA; 
    gBlendState.BlendOp  = D3DBLENDOP_ADD; 
    gBlendState.DestBlend  = D3DBLEND_INVSRCALPHA; 
    gBlendState.SrcBlendAlpha = D3DBLEND_ZERO; 
    gBlendState.BlendOpAlpha = D3DBLENDOP_ADD; 
    gBlendState.DestBlendAlpha = D3DBLEND_INVSRCALPHA; 

    gShadowBlendState.SrcBlend  = D3DBLEND_ZERO; 
    gShadowBlendState.BlendOp  = D3DBLENDOP_ADD; 
    gShadowBlendState.DestBlend  = D3DBLEND_ONE; 
    gShadowBlendState.SrcBlendAlpha = D3DBLEND_ONE; 
    gShadowBlendState.BlendOpAlpha = D3DBLENDOP_MAX; 
    gShadowBlendState.DestBlendAlpha = D3DBLEND_ONE; 

    gShadowFillBlendState.SrcBlend  = D3DBLEND_DESTALPHA; 
    gShadowFillBlendState.BlendOp  = D3DBLENDOP_ADD; 
    gShadowFillBlendState.DestBlend  = D3DBLEND_INVDESTALPHA; 
    gShadowFillBlendState.SrcBlendAlpha = D3DBLEND_ONE; 
    gShadowFillBlendState.BlendOpAlpha = D3DBLENDOP_MAX; 
    gShadowFillBlendState.DestBlendAlpha = D3DBLEND_ONE; 

Wie auch immer. Ich versuche das jetzt in OpenGL zu machen. Derzeit mit

glEnable(GL_BLEND); 
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 

I Alpha-Blending aktiviert habe, aber ich bin nicht sicher, wie es separate Anleitung geben, wie die Farb- und Alpha-Komponenten zu berechnen. Meine Frage ist also: Gibt es eine Möglichkeit, den Blender in OpenGL feiner zu kontrollieren als nur glBlendFunc()?

Antwort

4
+0

Danke, Goz, das ist in etwa das, wonach ich suche. Irgendeine Idee, wie man die D3DBLENDOP_MAX-Operation zusätzlich zu dem grundlegenden Add erhält? – Cheesington

+1

Entschuldigung für die langsame Antwort have awat auf Arbeit in den Staaten ... aber ich denke, die Erweiterung, die Sie suchen, ist http://www.opengl.org/registry/specs/EXT/blend_logic_op.txt – Goz

1

Ich bin mir nicht sicher, ob Sie eine bessere Kontrolle erhalten, aber Sie sollten in der Lage sein, das meiste zu erreichen, indem Sie glColorMask verwenden, um zuerst die Farbkanäle zu rendern und dann den Alpha-Kanal zu rendern. Der letzte Schritt scheint so zu sein, als ob er unverändert bleiben sollte.

+0

Dank Eric, das sieht nach einem anderen Weg um das Problem. Ich bin nicht so begeistert davon, meine Geometrie zweimal zu rendern, aber dies ist eine Möglichkeit, den Alpha-Kanal zu isolieren, den ich nicht berücksichtigt hatte. – Cheesington

1

verließ ich die Antwort hier:

http://pastie.org/542369

Außer es ein Problem ist: Ersetzen Sie alle GL_ ADD mit GL_ FUNC_ ADD. Mein Fehler.