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:
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):
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:
Und noch besser zu zeigen, wie es Abbildung auf die Welt:
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.