Transparenz - OpenGL
-
Habe ein Prob in OpenGL.
Ich will Transparenz ohne eine Tiefensortierung.
Dazu habe ich einen Ansatz aus Gems 1 benutzt.
Grobablauf wäre:1. alle soliden Objekte ohne Blending zeichnen
2. Zeichnen eines transparenten Objekte
2.1. zuerst mit GL_GREATER ohne Schreiben des Tiefenpuffers
2.2. danach schreiben mit GL_LEQUAL und eingeschaltetem Schreiben des
Tiefenpuffers
2.3. das ganze über alle transparenten ObjekteSoar nur irgendwie haut das nicht hin. Vor allem der GL_GREATER-Teil scheint irgendwie 0 Auswirkung zu haben. Hat wer ne Idee woran das liegt und wie ich das hinbekomme?
Hier mal mein Object-Pascal-Code:
setBackground(backGround.red,backGround.green,backGround.blue,0); i:= 0; glDisable(GL_BLEND); glDepthFunc(GL_LEQUAL); glDepthMask(GL_TRUE); //zuerst alle soliden Objekte zeichnen while (i <> m_dataBase.count) do begin if (TGeoObject(m_dataBase[i]).transparent = true) then begin inc(i); continue; end; // TGeoObject(m_dataBase[i]).draw; inc(i); end; //transparente Objekte zeichnen glEnable(GL_BLEND); i:= 0; while (i <> m_dataBase.count) do begin if (TGeoObject(m_dataBase[i]).transparent = false) then begin inc(i); continue; end; // glDepthFunc(GL_GREATER); glBlendFunc(GL_ONE_MINUS_DST_ALPHA,GL_DST_ALPHA); glDepthMask(GL_FALSE); TGeoObject(m_dataBase[i]).draw; glDepthFunc(GL_LEQUAL); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glDepthMask(GL_TRUE); TGeoObject(m_dataBase[i]).draw; inc(i); end;Also grundsätzlich soll die das korrekte Alpha-Blending halt realisiert werden, indem die trans. Objekte 2 mal gerendert werden, jeweils mit der korrekten Blendingformel(wenn das Objekt hinter einem transparenten liegt ist die Formel ja anders, als wenn es davor liegt)
Tja wenn ich halt den GL_GREATER-Teil da auskommentier macht das nix, also irgendwie scheint das noch nicht zu funktionieren und ich habe keine Idee, warum

-
der algorithmus scheint fuer mich keinen sinn zu ergeben.
du renderst mit z-test GL_GREATER. dh es werden nur die pixel gesetzt die verdeckt hinter einem anderen liegen. was soll das?
du benutzt in deiner blend-function dst-alpha, also die alpha-komponente im screenbuffer. ist die vorhanden? wenn nicht: 1*srcpixel + 0*dstpixel = keine transparenz.
das gleiche gilt fuer den zweiten pass: woher kommt die alpha-komponente im src-pixel?
daruber hinaus gibt es keinen algorithmus, der uneingeschraenkt ohne sortierung korrekte transparenz darstellen kann. ein polygon wird durch die alpha-komponente in den hintergrund geblendet. dafuer muss der hintergrund bereits gerendert worden sein.
-
hellihjb schrieb:
du renderst mit z-test GL_GREATER. dh es werden nur die pixel gesetzt die verdeckt hinter einem anderen liegen. was soll das?
Wenn die vordere Fläche transparent ist, muss die neue, wenn sie dahinter liegt ja durchscheinen.
-
Wenn die vordere Fläche transparent ist, muss die dahinter ja durchscheinen
aber die polygone die du schon gerendert hast, sind ja die nicht-transparenten.
und was da hinter liegt, scheint auch nicht durch.
-
Nun ich habe ja mehr als 1 transparentes Objekt. Es geht ja um den Fall, wenn sich transparente Objekte überdecken und vor den Soliden sind.
Das dieser Algorithmus nicht gerade der schnellste ist, weis ich. Mir geht es aber um die korrekte Darstellung und nicht um die beste Performance in diesem Fall.
-
du kannst anhand des ergebnisses vom zbuffer-test nicht feststellen, ob
ein pixel hinter einem nicht-durchsichtigen objekt liegt, und
wieviele durchsichtige polygone vor dem pixel liegen.generell kann ohne vorherige sortierung der fall auftreten, dass ein durchsichtiger pixel zwischen zwei weiteren durchsichtigen pixeln gezeichnet werden muss, was allgemein nicht zufriedenstellend loesbar ist.
-
Ja du hast ja recht, es ist mathematisch nicht perfekt, aber es soll ja optisch nur recht gut aussehen. Das reicht mir ja. Und wenn es ganz abwegig wäre, dann würde es sicher nicht in Gems 1 stehen
Gems 1 schrieb:
1. Lösche Z-Buffer
2. Lösche Alpha-Buffer mit Wert 0(transparent)
3. Setze Z-Funktion auf "größer als"(zeichne hinter), verwende Blend-Formel A(glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);) und zeichne die erste transparente Primitive bei ausgeschaltetem Z-Überschreiben. Zusätzlich schreibe den Alphawert der Primitiven in den Framebuffer, sodass
nachfolgender Pixel dahinter korrekt geblendet werden.4. Setze Z-Funktion auf "kleiner oder gleich"(zeichne davor), verwende Blend-Formel A und zeichne diese Primitive noch einmal mit eingeschaltetem Z-Überschreiben. Schreibe den Alpha-Wert der Primitiven in den Framebuffer, sodass nachfolgender Pixel dahinter korrekt geblendet werden.
5. Wiederhole die letzten beiden Schritte für alle transparenten Objekte
6. Setze Z-Funktion auf "größer als"(zeichne hinter), verwende Blendformel B (glBlendFunc(GL_ONE_MINUS_DST_ALPHA,GL_DST_ALPHA);). und zeichne alle opaken Primitive mit ausgeschaltetem Z-Überschreiben. Der Alpha-Wert, um in den Framebuffer zu schreiben, ist 1.0 (bzw. der maximale Integerwert).
7. Setze Z-Funktion auf "kleiner oder gleich" (zeichne davor) und zeichne alle opaken Primitive mit eingeschaltetem Z-Überschreiben und ausgeschaltetem Blending
So steht das da drinnen. Nur diese Reihenfolge hat mir nicht ganz geklappt. Daher habe ich das etwas umgedreht. Evtl mach ich auch was mit OpenGL falsch? Aber die States oben müssten doch stimmen oder?
-
bist du sicher, dass in deinem screenbuffer auch eine alpha-komponente existiert (PIXELFORMATDESCRIPTOR/PFD_TYPE_RGBA) ?
schreibst du auch was rein?
solang nichts drin ist, kann dst-alpha nichts blenden...
-
jo das habe ich gemacht, daran liegts nicht