2D Shadows



  • Hallo.

    Einige von euch kennen sicherlich folgenden netten Artikel über 2D soft-shadows:

    http://archive.gamedev.net/reference/articles/article2032.asp

    Der Ansatz zusammengefasst:

    Für jeden Renderdurchgang,

    -Clear screen, initialise camera matrix
    -Fill z buffer with all visible objects.
    -For every light:
    -Clear alpha buffer
    -Load alpha buffer with light intensity
    -Mask away shadow regions with shadow geometry
    -Render geometry with full detail

    Der Nachteil davon ist klar: Für jedes Licht muss im Prinzip die ganze Szene jeweils einmal gerendert werden.

    Außerdem funktioniert diese Methode nicht auf Rechnern mit Windows, deren Grafikkarten bei OpenGL kein GL_DST_ALPHA unterstützen (wie viele Laptops mit ihren Intel Mobile Grafikkarten).

    Kennt jemand von euch Artikel über alternative Methoden Licht & Schatten in 2D umzusetzen?



  • Mit dem Stencil-Puffer.



  • EOutOfResources schrieb:

    Mit dem Stencil-Puffer.

    koenntest du grob die vorgehensweise beschreiben?



  • schattenspieler schrieb:

    koenntest du grob die vorgehensweise beschreiben?

    • Lichtkreis in den Stencil-Puffer schreiben (mit Intensität (erfordert eine 8-bit Genauigkeit des Puffers))
    • Objekte subtrahieren
    • Schattenkegel subtrahieren
    • Farbpuffer mit der Lichtfarbe füllen (mit aktivem Stencilmasking)
    • Stencil-Puffer leeren
    • Auf zum nächsten Licht


  • EOutOfResources schrieb:

    schattenspieler schrieb:

    koenntest du grob die vorgehensweise beschreiben?

    • Lichtkreis in den Stencil-Puffer schreiben (mit Intensität (erfordert eine 8-bit Genauigkeit des Puffers))
    • Objekte subtrahieren
    • Schattenkegel subtrahieren
    • Farbpuffer mit der Lichtfarbe füllen (mit aktivem Stencilmasking)
    • Stencil-Puffer leeren
    • Auf zum nächsten Licht

    Was genau meinst du mit "subtrahieren"?



  • schattenspieler schrieb:

    Was genau meinst du mit "subtrahieren"?

    Minus-Rechnen.



  • EOutOfResources schrieb:

    schattenspieler schrieb:

    Was genau meinst du mit "subtrahieren"?

    Minus-Rechnen.

    😃 😃 😃



  • ja, ist schon sau witzig. echt originell und intelligent, das witzchen. das haette ich ja fast nicht erwartet.

    ...



  • Er meint - wenn ich ihn richtig verstehe - das selbe wie in dem von dir verlinkten Artikel beschrieben ist. Nur mit Stencil-Buffer statt Alpha-Kanal.



  • schattenrechner schrieb:

    ja, ist schon sau witzig. echt originell und intelligent, das witzchen. das haette ich ja fast nicht erwartet.

    ...

    Klar ist es witzig. Was soll er denn sonst meinen? Verstehe grad nicht was man da nicht verstehen kann...



  • hustbaer schrieb:

    schattenrechner schrieb:

    ja, ist schon sau witzig. echt originell und intelligent, das witzchen. das haette ich ja fast nicht erwartet.

    ...

    Klar ist es witzig. Was soll er denn sonst meinen? Verstehe grad nicht was man da nicht verstehen kann...

    Wieso ist das bitte klar? Wenn man z.B. noch nit mit einem Stencilbuffer gearbeitet hat, ist das ueberhaupt nicht klar. Ist ja wohl offensichtlich, dass ihm die Bedeutung des Wortes subtrahieren klar ist, nur nicht was es in diesem Kontext bedeutet.

    Er meint mit subtrahieren wohl: Bei erfolgreichen Z/Stenciltest den Wert im DepthStencilBuffer dekrementieren.



  • this->that schrieb:

    hustbaer schrieb:

    schattenrechner schrieb:

    ja, ist schon sau witzig. echt originell und intelligent, das witzchen. das haette ich ja fast nicht erwartet.

    ...

    Klar ist es witzig. Was soll er denn sonst meinen? Verstehe grad nicht was man da nicht verstehen kann...

    Wieso ist das bitte klar? Wenn man z.B. noch nit mit einem Stencilbuffer gearbeitet hat, ist das ueberhaupt nicht klar. Ist ja wohl offensichtlich, dass ihm die Bedeutung des Wortes subtrahieren klar ist, nur nicht was es in diesem Kontext bedeutet.

    Er meint mit subtrahieren wohl: Bei erfolgreichen Z/Stenciltest den Wert im DepthStencilBuffer dekrementieren.

    Danke!

    Die funktionsweise des Stencilbuffers war mir schon klar (in der Theorie), aber damit gearbeitet habe ich tatsächlich noch nie.

    Ich habe grade mal eine Methode zusammengefrickelt um zumindest mal nur das Gebiet des Kreises zeichnen zu lassen (der Rest wird per Stencil-Test rausgefiltert). Ich mache das im Moment grob gesagt so:

    //render methode
    //keine farben in buffer malen
    GL11.glColorMask(false, false, false, false);
    
    //1 in stencilbuffer schreiben wo die lichter gezeichnet werden
    GL11.glEnable(GL11.GL_STENCIL_TEST);
    GL11.glStencilFunc(GL11.GL_ALWAYS,1,1);
    GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_REPLACE);
    GL11.glDisable(GL11.GL_DEPTH_TEST);
    
    //pseudocode zum lichterzeichnen
    zeichnelichter();
    
    //farben ab jetzt wieder zeichnen
    GL11.glColorMask(true,true,true,true);
    //wenn im stencil buffer 1 und nur 1 steht, zeichnen
    GL11.glStencilFunc(GL11.GL_EQUAL, 1, 1);
    GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP);
    GL11.glEnable(GL11.GL_DEPTH_TEST);
    
    //rest der geometry zeichnen
    zeichneallesprites();
    zeichnealleformenundlinien();
    zeichnerestlicheszeugs();
    

    Wie würde ich das anpassen, dass nach Intensität gemalt wird? Im Moment habe ich einen vollen Lichtradius der komplett hell gezeichnet wird. Aber je weiter man vom Zentrum des Lichts weg geht, desto dunkler soll dort ja gezeichnet werden. Muss ich das noch irgenwie mit Blending kombinieren oder kann ich das mit dem Stencilbuffer alleine hinbekommen?



  • Was ist GL11 ? Habe ich etwas verpasst?



  • EOutOfResources schrieb:

    Was ist GL11 ? Habe ich etwas verpasst?

    Der GL11 namespace.



  • schattenspieler schrieb:

    namespace.

    Namensbereiche löst man mit dem Bereichauflösungsoperator (::) auf und nicht mit dem Memberzugriffsoperator (heisst der so?).



  • Ja, sorry, das ist Java, kein C++. Genauer gesagt ist das LWJGL und in GL11 befinden sich die ganzen Bindings von OpenGL 1.1.



  • Schattenspieler schrieb:

    Ja, sorry, das ist Java, kein C++.

    Aha! Ich dachte, du arbeitest in C++. Deshalb habe ich mich gefragt, was GL11 ist, denn der OpenGL-Header von C globalisiert alle Funktionen.



  • Kein Problem. Die Frage bleibt aber immer noch:

    schattenmaler schrieb:

    this->that schrieb:

    hustbaer schrieb:

    schattenrechner schrieb:

    ja, ist schon sau witzig. echt originell und intelligent, das witzchen. das haette ich ja fast nicht erwartet.

    ...

    Klar ist es witzig. Was soll er denn sonst meinen? Verstehe grad nicht was man da nicht verstehen kann...

    Wieso ist das bitte klar? Wenn man z.B. noch nit mit einem Stencilbuffer gearbeitet hat, ist das ueberhaupt nicht klar. Ist ja wohl offensichtlich, dass ihm die Bedeutung des Wortes subtrahieren klar ist, nur nicht was es in diesem Kontext bedeutet.

    Er meint mit subtrahieren wohl: Bei erfolgreichen Z/Stenciltest den Wert im DepthStencilBuffer dekrementieren.

    Danke!

    Die funktionsweise des Stencilbuffers war mir schon klar (in der Theorie), aber damit gearbeitet habe ich tatsächlich noch nie.

    Ich habe grade mal eine Methode zusammengefrickelt um zumindest mal nur das Gebiet des Kreises zeichnen zu lassen (der Rest wird per Stencil-Test rausgefiltert). Ich mache das im Moment grob gesagt so:

    //render methode
    //keine farben in buffer malen
    GL11.glColorMask(false, false, false, false);
    
    //1 in stencilbuffer schreiben wo die lichter gezeichnet werden
    GL11.glEnable(GL11.GL_STENCIL_TEST);
    GL11.glStencilFunc(GL11.GL_ALWAYS,1,1);
    GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_REPLACE);
    GL11.glDisable(GL11.GL_DEPTH_TEST);
    
    //pseudocode zum lichterzeichnen
    zeichnelichter();
    
    //farben ab jetzt wieder zeichnen
    GL11.glColorMask(true,true,true,true);
    //wenn im stencil buffer 1 und nur 1 steht, zeichnen
    GL11.glStencilFunc(GL11.GL_EQUAL, 1, 1);
    GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP);
    GL11.glEnable(GL11.GL_DEPTH_TEST);
    
    //rest der geometry zeichnen
    zeichneallesprites();
    zeichnealleformenundlinien();
    zeichnerestlicheszeugs();
    

    Wie würde ich das anpassen, dass nach Intensität gemalt wird? Im Moment habe ich einen vollen Lichtradius der komplett hell gezeichnet wird. Aber je weiter man vom Zentrum des Lichts weg geht, desto dunkler soll dort ja gezeichnet werden. Muss ich das noch irgenwie mit Blending kombinieren oder kann ich das mit dem Stencilbuffer alleine hinbekommen?



  • Hast du die Extention ARB_depth_buffer_float geladen? Sie erlaubt 8-bit-Werte im Stencil-Puffer.



  • ja, mein stencil buffer ist schon 8 bit lang, aber wie hilft mir das einen die farben innerhalb des lichts abzudunkeln je nachdem welcher wert im stencil buffer ist?

    vor allem, wie bekomme ich so weich interpolierte uebergaenge, die mir beim malen des lichtes automatisch erstellt werden (indem ich in der mitte einfach als alpha die intensitaet und bei den punkten aussenrum als alpha 0 angebe) in den stencil buffer?


Log in to reply