2016-09-02 7 views
1

Ich habe schon seit einiger Zeit versucht, ein Screen-Space-Pixel (von einem verzögerten HLSL-Shader) in den Lichtraum zu konvertieren. Die Ergebnisse waren für mich überraschend, da mein Licht-Rendering den Tiefenpuffer zu füllen scheint.DirectX Konvertieren der Pixel-Weltposition in die Schatten-Map-Position führt zu seltsamen, gekachelten Ergebnissen

Wichtig, die Szene Kamera (oder Auge) und das Licht von Start an der gleichen Position gerendert werden.

Zuerst extrahieren ich die Welt Position des Pixels unter Verwendung des Codes:

float3 eye = Eye; 
float4 position = { 
    IN.texCoord.x * 2 - 1, 
    (1 - IN.texCoord.y) * 2 - 1, 
    zbuffer.r, 
    1 
}; 
float4 hposition = mul(position, EyeViewProjectionInverse); 
position = float4(hposition.xyz/hposition.w, hposition.w); 
float3 eyeDirection = normalize(eye - position.xyz); 

Das Ergebnis wird als Rendern der XYZ-Position korrekt zu sein scheint, als RGB bzw. liefert diese (scheinbar korrekt) Ergebnis:

Correctly rendered XYZ

die rote Komponente scheint die Ausgabe X korrekt zu sein, wie es nach rechts bewegt und blau zeigt Z vorwärts bewegt. Der Y-Faktor sieht auch korrekt aus, da der Boden etwas unterhalb der Y-Achse liegt.

Als nächstes (und um sicher zu gehen, dass ich nicht verrückt werde) habe ich beschlossen, den ursprünglichen Tiefenpuffer auszugeben. Normalerweise behalte ich den Tiefenpuffer in einem Texture2D namens DepthMap, das als Eingabe an den Shader übergeben wird. In diesem Fall jedoch, versuche ich es wieder in die richtige Position, um die Pixel-Transformation rückgängig zu machen durch Verrechnung und es durch das Auge der Blick-Projektionsmatrix multipliziert:

float4 cpos = mul(position, EyeViewProjection); 
cpos.xyz = cpos.xyz/cpos.w; 
cpos.x = cpos.x * 0.5f + 0.5f; 
cpos.y = 1 - (cpos.y * 0.5f + 0.5f); 
float camera_depth = pow(DepthMap.Sample(Sampler, cpos.xy).r, 100); // Power 100 just to visualize the map since scales are really tiny 
return float4(camera_depth, camera_depth, camera_depth, 1); 

Dies auch ein korrektes aussehendes Ergebnis ergibt (obwohl ich bin nicht 100% sicher über den Z-Wert). Beachten Sie auch, dass ich die Ergebnisse exponentiellen gemacht haben, um besser die Tiefeninformationen zu visualisieren (dies nicht geschieht, wenn Live-Vergleiche versucht):

Reinterpreting XYZ back to ZBuffer space

So theoretisch, ich den gleichen Code verwenden können, um diese Pixel Welt zu umwandeln Positionieren Sie den Raum, indem Sie ihn mit der Projektionsmatrix des Lichts multiplizieren. Richtig? Hier ist, was ich versucht:

float4 lpos = mul(position, ShadowLightViewProjection[0]); 
lpos.xyz = lpos.xyz/lpos.w; 
lpos.x = lpos.x * 0.5f + 0.5f; 
lpos.y = 1 - (lpos.y * 0.5f + 0.5f); 
float shadow_map_depth = pow(ShadowLightMap[0].Sample(Sampler, lpos.xy).r, 100); // Power 100 just to visualize the map since scales are really tiny 
return float4(shadow_map_depth, shadow_map_depth, shadow_map_depth, 1); 

Und hier ist das Ergebnis:

Broken light space

Und noch besser zu zeigen, wie es Abbildung auf die Welt:

Broken light space #2

I don‘ Ich verstehe, was hier vor sich geht. Es scheint, dass es etwas mit der Projektionsmatrix zu tun haben könnte, aber ich bin nicht so gut in Mathematik, um sicher zu wissen, was passiert. Es ist definitiv nicht die Breite/Höhe der Lichtkarte, da ich mehrere Kartengrößen ausprobiert habe und die Projektionsmatrix mit FOV und Seitenverhältnissen berechnet wurde, die niemals Breite/Höhe eingegeben haben.

Schließlich hier einig C++ Code zeigt, wie meine Perspektive Matrix (sowohl für Auge und Licht verwendet wird) berechnet:

const auto ys = std::tan((T)1.57079632679f - (fov/(T)2.0)); 
    const auto xs = ys/aspect; 
    const auto& zf = view_far; 
    const auto& zn = view_near; 
    const auto zfn = zf - zn; 

    row1(xs, 0, 0, 0); 
    row2(0, ys, 0, 0); 
    row3(0, 0, zf/zfn, 1); 
    row4(0, 0, -zn * zf/zfn, 0); 
    return *this; 

ich hier völlig ratlos bin. Jede Anleitung oder Empfehlungen würden sehr geschätzt werden!

BEARBEITEN - Ich habe auch vergessen zu erwähnen, dass das gekachelte Bild auf dem Kopf steht, als ob die Y-Flip es brach. Das ist seltsam für mich, da es erforderlich ist, um es richtig in den Augen-Textur-Raum zu bringen.

Antwort

1

Ich habe hier und da etwas optimiert und Dinge repariert. Letztendlich war mein größtes Problem eine unerwartet umgesetzte Matrix. Es ist ein bisschen kompliziert, wie die Matrix transponiert wurde, aber deshalb wurden die Dinge umgedreht. Ich habe auch zu D32-Tiefenpuffern gewechselt (obwohl ich nicht sicher bin, ob es geholfen hat) und dafür gesorgt, dass alle Positionen, die durch ihre W geteilt sind, alle Komponenten (einschließlich W) beeinflusst haben.

So Code wie folgt: hposition.xyz = hposition.xyz/hposition.w wurde dies: hposition = hposition/hposition.w

Nach all diesen Zwicken, es fängt eher wie ein Schattenkarte zu suchen.

Oh und die transponierte Matrix war die ViewProjection des Lichts.

Verwandte Themen