Ergebnis 1 bis 5 von 5

Thema: OpenGL Blending & Depth Test für volles 32-Bit Alpha-Blending

  1. #1

    OpenGL Blending & Depth Test für volles 32-Bit Alpha-Blending

    Guten Tag,
    Ich kämpfe mich gerade mit java und lwjgl (Als Schnittstelle für OpenGL) durch das Darstellen von Texturen in einem 2D Kontext.
    Bisher funktioniert alles wunderbar doch nun stieß ich auf ein großes Problem, das korrekte Blenden von Texturen mit Alphakanälen.

    Als BlendFunc benutze ich:
    Code:
    GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
    Und die DepthFunc ist:
    Code:
    GL11.glDepthFunc(GL11.GL_LEQUAL);
    mit einem Viewport Setting von:
    Code:
        private static final int VIEW_NEAR_Z = -10000;
        private static final int VIEW_FAR_Z = 10000;
    Code:
    GL11.glOrtho(0, resolution_width, resolution_height, 0, VIEW_NEAR_Z, VIEW_FAR_Z);
    Das Ergebnis sieht leider so aus:
    Anhang 15693
    Der Planet hat hierbei eine niedrigere Z-Koordinate als der Sternenhintergrund. Wie man erkennt wird hier nicht korrekt "geblendet" sondern die ankommenden Pixel der Sterne einfach so übernommen ohne eine Umrechnung mit den bereits vorhandenen Pixeln des Planeten.

    Ich habe dazu schon ein wenig recherche betrieben und das Internet hat mir folgenden Artikel ausgespuckt:
    Zitat Zitat
    [...]

    We enable blending just like everything else. Then we set the equation, and turn off depth buffer writing when drawing transparent objects, since we still want objects behind the translucent shapes to be drawn. This isn't the proper way to blend, but most the time in simple projects it will work fine. Rui Martins Adds: The correct way is to draw all the transparent (with alpha < 1.0) polys after you have drawn the entire scene, and to draw them in reverse depth order (farthest first). This is due to the fact that blending two polygons (1 and 2) in different order gives different results, i.e. (assuming poly 1 is nearest to the viewer, the correct way would be to draw poly 2 first and then poly 1. If you look at it, like in reality, all the light comming from behind these two polys (which are transparent) has to pass poly 2 first and then poly 1 before it reaches the eye of the viewer. You should SORT THE TRANSPARENT POLYGONS BY DEPTH and draw them AFTER THE ENTIRE SCENE HAS BEEN DRAWN, with the DEPTH BUFFER ENABLED, or you will get incorrect results. I know this sometimes is a pain, but this is the correct way to do it.

    [...]
    Das wäre nun ein enormer Aufwand und nach meinem derzeitigen Verständnis der Depth-Funktion auch nicht im Sinne der Sache.
    Immerhin soll doch die Depth-Funktion dafür da sein, damit ich mich eben nicht darum kümmern muss die einzelnen Objekte nach ihrer Höhe zu sortieren sondern, dass die Grafikkarte dies übernehmen kann.
    Kann mir jemand vielleicht sagen, ob der Artikel recht hat? Oder ob es eine einfachere Alternative dazu gibt?

    Vielen Dank für die Antworten.

  2. #2
    Ich denke dass es nicht an den Blend-Modes liegt. Die Blend- und DepthFunc sieht soweit gut aus.

    Es fehlt glaub ich nur folgendes
    Code:
    GL11.glAlphaFunc(GL11.GL_GREATER, 0f);
    EDIT: Hast du vor dem Einstellung des Blendmodes auch das Blending via
    Code:
    glEnable(GL_BLEND);
    an gemacht?

    Geändert von niR-kun (17.10.2012 um 18:45 Uhr)

  3. #3
    Zitat Zitat von niR-kun Beitrag anzeigen
    Ich denke dass es nicht an den Blend-Modes liegt. Die Blend- und DepthFunc sieht soweit gut aus.

    Es fehlt glaub ich nur folgendes
    Code:
    GL11.glAlphaFunc(GL11.GL_GREATER, 0f);
    Die Alpha-Funktion ist mit eben diesen Werten bereits eingestellt.

    Als kleine Randinformation.
    Wenn ich die Depth-Funktion deaktiviere dann sieht das Bild korrekt aus. Allerdings werden dann eben meine Texturen nichtmehr nach Z-Koordinaten sortiert.

  4. #4
    Hab leider nicht viel Zeit und das Thema nur kurz überfolgen aber vlt hilfts ja:

    Zitat Zitat von Cornix Beitrag anzeigen
    Das wäre nun ein enormer Aufwand und nach meinem derzeitigen Verständnis der Depth-Funktion auch nicht im Sinne der Sache.
    Immerhin soll doch die Depth-Funktion dafür da sein, damit ich mich eben nicht darum kümmern muss die einzelnen Objekte nach ihrer Höhe zu sortieren sondern, dass die Grafikkarte dies übernehmen kann.
    Nicht unbedingt. Das ganze funktioniert nur so lange pixel entweder komplett transparent(können im fragment shader mit dem befehl "discard" verworfen werden) oder opak sind. Bei Zwischenwerten hast du das Problem, dass die pixelwerte zusammen geblendet werden müssen mit dem was bereits da ist. In so einem fall musst du nach dem "painters algorithm" rendern, d.h. von hinten nach vorne. Wenn du zuerst deine vorderen transparenten Objekte renderst und depth writing aktiviert ist, dann wird nachher kein fragment an der stelle mehr gerendert, wenn es sich weiter hinten befindet. Depth writing muss aber in den meisten fällen aktiviert sein, weil wir ja keine weiter entfernten Objekte über näher liegende Objekte zeichnen wollen.

    Eine simple und beim partikel rendern oft ausreichende Lösung ist es, zuerst alle opaken Objekte mit depth write und test zu rendern, und anschließend alle transparenten Objekte mit depth test aber ohne depth write.

    edit:
    Ok, ich seh du hast einen planeten und sterne und wahrsch. beide mit alpha zwischen 0 und 1. In dem Fall bleibt dir meines wissens nichts anderes über, als die Objekte nach distanz zu sortieren und von hinten (-z) nach vorne (+z) zu rendern. Das Problem ist einfach, dass du sonst in den depth buffer schreiben musst, wenn du den planeten renderst. Wenn du anschließend dahinter liegende Sterne renderst und sich die Sterne am Rand des Planeten befinden(wo der planet transparent ist), dann werden die Sterne an der Stelle garnicht gerendert, weil sie sich ja weiter hinten befinden. Wenn du aber nicht in den depth buffer schreibst und ohne sortierung renderst, dann würden nachfolgende Objekte drübergezeichnet werden, selbst wenn es sich um dahinterliegende Sterne handelt. Der Planet muss auserdem einen höheren z-wert haben, wenn er vor den Sternen gerendert werden soll. Je niedriger der z-wert, desto weiter weg.

    Oder du gehst einfach davon aus, dass Sterne Hintergrund sind. Du kannst den Hintergrund zuerst einfach ohne depth writing rendern. Dadurch bleibt der depth buffer unberührt und alles was du nachher renderst wird über den hintergrund drüber gerendert.

    Geändert von nudelsalat (17.10.2012 um 19:46 Uhr)

  5. #5
    Soweit ich es verstanden habe dient die Depth-Funktion dafür zu ermitteln ob ein ankommender Pixel in das darzustellende Bild übernommen werden soll oder nicht.
    Mit den von mir getroffenen Einstellungen, eben dann, wenn seine Z-Koordinate über derjenigen des Pixels liegt welcher bereits mit identischer X- und Y-Koordinate im Buffer vorhanden ist.
    Falls das korrekt ist, so verstehe ich nicht, weshalb für den ankommenden Pixel, welcher nun "oberhalb" des vorhandenen Pixels im Buffer, nicht die Blend-Funktion verwendet wird um die Farbwerte des letzendlichen Pixels bestimmen zu können.
    Wenn ich nun nämlich die Depth-Funktion aktiviert habe wird doch deshalb nicht die Blend-Funktion deaktiviert.
    Ich verstehe derzeit nicht an welcher Stelle die Blend-Funktion nun überhaupt zu greifen scheint.

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •