Probleme mit Shadowmapping



  • Hallo zusammen
    Ich bin es... Wieder einmal... :p
    Ich habe irgendwie Probleme mit dem Shadowmapping und zwar wird beim zweiten Renderpass, also wärend ich die effektive Scene rendere, sämtliche Regionen hinter der Lichtquelle (Spotlight) als schattiert beleuchtet. Hatte das vielleicht bereits jemand oder kann mir sonst sagen, woran dies liegen könnte?

    Mfg Samuel



  • Ich habe mittlerweile festgestellt, dass die z komponente einiger Pixel, welcher in den Viewspace gemappt wurden, grösser als eins sind. Aber wie ist das mögliche, ich habe alle durch w dividiert und nach der Projektion sollte doch z nicht mehr grösser als 1 sein können? 😮



  • Die z-Koordinate sollte nach der Multiplikation mit der World-, LightView- und LightProjectionmatrix und der Division durch w im Bereich [0,1] liegen. Da das bei dir nicht der Fall ist, stimmt wohl etwas mit den Matrizen nicht. Um weiter helfen zu können, wäre es sinnvoll zu wissen, wie die Matrizen bei dir aufgebaut sind.


  • Mod

    Ishildur schrieb:

    sämtliche Regionen hinter der Lichtquelle (Spotlight) als schattiert beleuchtet.

    ist ja auch richtig, hinter dem spotlight ist alles im schatten.

    aber ein bild sagt mehr als 1000worte 😉



  • @rapso
    Nicht beleuchtet != im schatten eines lichts :p

    Screen:
    http://www.imageload.net/view/1jm/screen.jpg/

    Shadowmap:

    float4x4 Transform;
    
    struct VertexInput{
     float4 Pos:POSITION0;
    };
    
    struct VertexOutput{
     float4 Pos:POSITION0;
     float  Dph:TEXCOORD0;
    };
    
    VertexOutput VertexShaderFunction(VertexInput IN){
     VertexOutput OUT;
     OUT.Pos = mul(IN.Pos,Transform);
     OUT.Dph = (OUT.Pos.z/OUT.Pos.w);
     return OUT;
    }
    
    float4 PixelShaderFunction(VertexOutput IN):COLOR0{
     return float4(IN.Dph,0.0f,0.0f,1.0f);
    }
    

    Render:
    Vertexshader:

    // pos is a texcoord, fhgt is computed previously
    OUT.Pos = float4(IN.Pos.x,fHgt,IN.Pos.z,IN.Pos.w);
    

    Pixelshader:

    // Calculate the texture projection texcoords, we divide by 2 and add 0.5 because
     // we need to convert the coordinates from a -1.0 - 1.0 range into the 0.0 - 1.0 range
    float4 lpos = mul(IN.Pot,TransformLight);
    float2 tc = float2((lpos.x/lpos.w/2.0f)+0.5f,(-lpos.y/lpos.w/2.0f)+0.5f);
    
    // Get our depth colour from the projected depth map
    float shadowdepth = tex2D(ShadowSampler,tc).r;
    float ourdepth = (lpos.z/lpos.w);
    
      // Test if the distance from the pixel to the light is bigger than the depth we have in the texture
     if(ourdepth-0.003f > shadowdepth.r/* && ourdepth <= 1.0f*/){
      // yes? then lets darken the pixel to black
      // (In normal use, you'd use a lighting equation here to determine exactly how much to darken the pixel)
     rst *= float4(0.5f,0.5f,0.5f,1.0f);
    }
    

    Wenn ich ourdepth <= 1.0f wieder einkommentiere funktioniert alles tadellos, daher meine Annahme, dass einige Werte in outdepth und somit in der projezierten z komponente grösser als 1.0f ist 😉

    Die Matrizen sehen folgendermassen aus:

    Matrix mtxViw = Matrix.CreateLookAt(new Vector3(0.0f,15.0f,15.0f),Vector3.Zero,Vector3.Up);
       Matrix mtxPrj = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4,1.0f,1.0f,1000.0f);
    

    So ich hoffe, mit diesen Informationen dienen zu können: 😉


  • Mod

    Ishildur schrieb:

    @rapso
    Nicht beleuchtet != im schatten eines lichts :p

    genau! hinterm spotlight -> im schatten. alles ok der beschreibung nach:P

    auf die schnelle seh ich nichts falsches.

    wenn das shadowfrustum nicht die komplette scene eindeckt, hast du halt werte >1 und <0 fuer z.



  • @rapso

    wenn das shadowfrustum nicht die komplette scene eindeckt, hast du halt werte >1 und <0 fuer z.

    Hmmm, sowas hatte ich befürchtet. Ja daran hatte ich gar nicht gedacht. Wenn ich natürlich einen Punkt in den Viewspace des Lichts setze, welcher sich gar nicht in dessen Viewfustum befindet, dann haben wir ein Problem...

    Die konkrete Situation in diesem Fall sieht folgendermassen aus. Die Wasseroberfläche umfasst 1000m^2 und dienen hauptsächlich de Optik. Das Spielfeld hingegen umfasst ca. 50^2 und ist die einzige Region, welche Objekte beinhaltet. Also habe ich das Shadowfrustum so gesetzt, dass einfach dieser verhältnissmässig kleine Teil beleuchtet wird, weil sonst die Auflösung der Shadowmap nicht ausreicht, um eine gutes Ergebnis hinzugebkommen.

    Also ist meine Lösung mit der zusätzlichen Condition im Pixelshader vielleicht gar nicht so verkehrt?

    P.S.
    Das Hauptproblem liegt in den sehr aufwendigen Wellenberechnungen. Damit ich diese nicht mehrmals machen muss, rendere ich das Spielfeld in einem vorgängigen Renderpass und lege die somit erstellte Textur aufs Wasser, obwohl dieses nur ca. 8% der Wasseroberfläche betrifft. Den Sampler habe ich auf Border gestellt und die BorderColor auf 0x00000000 aufgrund der additiven Identität gestellt. Auf diese Weise muss ich im Pixelshader nicht unterscheiden, ob der aktuelle Pixel Teil des Spielfeldes ist oder nicht. Allerdings wird natürlich trotzedem zu 92% ein Texture lookup gemacht, welches einfach in den "Border" der Textur zeigt. Allerdings ist diese immer noch schneller, als die Teile des Wasser, welche die Textur beinhalten mehrmals zu rendern. Mit der Shadowmap kommt nun noch einmal relativ viele Berechnungen zum Zug, welche in 92% der Fälle zu nichts führen...

    Gibt es vielleicht bessere Möglichkeiten, die vorhandene Situation umzusetzen?



  • Ich frage mich ausserdem, ob es wirklich erforderlich ist, die Tranformation des World in den Viewspace des Lichts auf Pixelebene zu machen... Würde es nicht ausreichen, diese per Vertex zu machen und vom Sampler interpolieren zu lassen?

    Natürlich habe ich es ausprobiert und konnte keinen Unterschied feststellen. Ich bin jedoch verunsichert, weil es eben sämtliche Tutorials, welche ich gefunden hatte, im Pixelshader berechnen...



  • ob es wirklich erforderlich ist, die Tranformation des World in den Viewspace des Lichts auf Pixelebene zu machen...

    Die Transformation ist linear, kann also per-Vertex stattfinden, die Projektion muss pro-Pixel.

    Wenn ich natürlich einen Punkt in den Viewspace des Lichts setze, welcher sich gar nicht in dessen Viewfustum befindet, dann haben wir ein Problem...

    Ich seh da kein Problem.


Log in to reply