[SOLVED] [OGL] Stencilbuffer - Shadow Volumes - blackout :-(



  • Hallo.

    Ich versuche derzeit verzweifelt hinter die Magie des Stencilbuffers zu kommen um damit Echtzeitschatten berechnen zu können, leider hört es mit dem Verständis jenseits eines Stencil-Spiegels auf 😞

    Ich bastle nach diesem Tutorial:
    http://www.3ddrome.com/articles/shadowvolumes.php

    Das Problem ist folgendes: Ich habe in einer testszene eine wand und einen kleineren würfel. Hinter letzterem befindet sich eine Lichtquelle die den Schatten des Würfels auf die Wand werfen soll. Es existiert nun ein schatten auf der wand (leider auf beiden seiten, aber das ist wohl ein extra thread wert ^^). Allerdings gibt es recht massive Darstellungsfehler auf dem Würfel, die sich wie folgt äußern:

    1. (Ist das problem zu doof schaut doch bitte weiter unten 🤡 )

    Bevor ich jetzt einen Roman schreibe lieber hier Bilder:

    Aus sicht nahe der Lichtquelle scheinen wohl die eigendlich nicht sichtbare schattierte Rückseite durch!!!

    (Licht=gelber punkt, blau = shadow-volumes, rot = schattenwerfende kanten)
    Schatten-werfender Würfel von vorne ...
    http://www.hostpix.de/file.php?dat=WkVJeABD.jpg
    ... und von hinten:
    http://www.hostpix.de/file.php?dat=D8Vx0Mml.jpg
    -> Es sind wohl zumindest theoretisch die richtigen seiten schattiert? ^^

    Zu aller erst mal meinen code bisschen vereinfacht:

    void initOGL()
    {
    	glClearColor(0.0, 0.0, 0.0, 0.0);
    	glInitNames();
    	glEnable(GL_DEPTH_TEST);
    	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
    	glMatrixMode(GL_PROJECTION);
    	glOrtho(-vWidth/30,vWidth/30,-vHeight/30, vHeight/30,-1000.0f,1000.0f);
    	glMatrixMode(GL_MODELVIEW);
    }
    
    void drawGL()
    {
    	glMatrixMode(GL_MODELVIEW);
    	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    	glLoadIdentity();
    
            cam.setCamera(); //glTranslatef/glRotatef
    
            ZEICHNE_DIE_GESMATE_SZENE_BIS_NUR_NOCH_SCHATTEN_FEHLT();
    
            for( jedesObject o )
            {
                   shadow_t s(o, lightPosition); //Berechnet im Konstruktor ShadowVolume 
                  s.rendeShadow();
            }
    
    }
    
    void shadow_t::renderShadow()
    {
    	glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
    	glDepthMask(GL_FALSE);
    	glEnable(GL_CULL_FACE);
    	glEnable(GL_STENCIL_TEST);
    	glEnable(GL_POLYGON_OFFSET_FILL);
    	glPolygonOffset(0.0f, 100.0f);
    
    	glCullFace(GL_FRONT);
    	glStencilFunc(GL_ALWAYS, 0x0, 0xff);
    	glStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
    	drawShadowVolume();
    
    	glCullFace(GL_BACK);
    	glStencilFunc(GL_ALWAYS, 0x0, 0xff);
    	glStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
    	drawShadowVolume();
    
    	glDisable(GL_POLYGON_OFFSET_FILL);
    	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
    	glDepthMask(GL_TRUE);
    	glDisable(GL_CULL_FACE);
    
    	glStencilFunc(GL_NOTEQUAL, 0x0, 0xff);
    	glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
    	draw_shadow(); // Bedeckt den bildschirm mit einem halbtransparenten schwarzen quad
    	glDisable(GL_STENCIL_TEST);
    }
    

    Ich bin völlig ratlos 😞

    1. Hier kann mir sicher jeder helfen:

    ich verstehe den Stencilbuffer einfach nicht, nicht, nicht!!! 😞 😞
    Das rendern der Shatten folgt ja in 2 Schritten:

    A: Back-faces der shadow-volumes rendern, wenn DEPTH-test fehlschlägt (Was genau soll ich darunter verstehen?!?!?! das shadow-volume ist an der stelle nicht sichtbar wenn es hinter irgendwas ist oder wie????) incrementiere stencil-buffer

    B: Zeichne front-faces und dekrementiere beim depth-test-fehlschlag. und das ergebnis ist der schatten??!

    //(...)
    
    //A:
    	glCullFace(GL_FRONT);
    	glStencilFunc(GL_ALWAYS, 0x0, 0xff);
    	glStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
    	drawShadowVolume();
    
    //B:
    	glCullFace(GL_BACK);
    	glStencilFunc(GL_ALWAYS, 0x0, 0xff);
    	glStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
    	drawShadowVolume();
    
    // (....)
    
            glStencilFunc(GL_NOTEQUAL, 0x0, 0xff);
    	glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
    
    // (...)
    

    Ich bitte euch, erklärt es mir 😞 Ich werde aus glStencilFunc und glStencilOp nicht schlau! Welche werte und wo nimmt der Stencilbuffer nach A) ein und welche nach B)?! und warum?!?! wieso wird immerzu 0x0, 0xff gewählt?! warum wird der schatten dann mit GL_NOTEQUAL gezeichnet ... 😕 😕
    Ich hätte jetzt noch mehr fragen, aber ich glaube wenn ich noch ein Wort schreibe liest niemand mehr ^^

    Vielen Dank schonmal wenn ihr bis hierher gelesen habt. 🕶

    P.S: Ja, ich kenne Nehe. Von google habe ich auch schon gehört. von den Man-pages ebenso. 😕



  • Es geht ja darum herauszufinden ob ein Pixel im Schattenvolumen liegt.
    Dazu ueberlegt man sich wie oft der Strahl zwischen Kamera und dem zu schattierenden Pixel in einen Volumenkoerper ein- bzw austritt.

    Alle Pixel des Volumens die den Z-Test bestehen (also auch vor dem zu schattierenden Pixel liegen) und zu einem zugewandten Polygon des Volumens gehoeren (Strahl tritt in Volumen ein) erhoehen den Wert im Stencil-Buffer.

    Alle Pixel die zu einem abgewandten Polygon gehoeren (Strahl tritt aus dem Volumen wieder aus) verringern den Wert im Stencil-Buffer.

    Ist der Strahl oefter ein- als ausgetreten (Stencilwert!=0) liegt der Pixel im Schatten.

    Jene Pixel die den Z-Test nicht bestehen interessieren nicht.
    Genausogut kann man aber auch die Pixel des Schattenvolumens zaehlen die den Z-Test nicht bestehen:
    Ein Pixel liegt dann im Schatten wenn hinter ihm der Strahl oefter aus einem Volumen aus- als eintritt).
    Naeheres hier.



  • Ja danke 🙂 So habe ichs ja auch verstanden, da es aber nicht funktioniert hat .... 🙂

    Das Problem war dass ich das Shadow Volume nicht richtig generiert habe, also einfach nur die Vertices der Schatten werfenden Ecken verbunden und das als "Deckel" genommen. Allerdings muss man logischerweiße die Oberfläche des Objects nachbilden, zumindest wenn die Konturen komplexer werden ....

    Danke euch 🤡



  • Exakter gesagt muss man die Silhouette des Occluders aus Sicht der Lichtquelle extrudieren.


Anmelden zum Antworten