2014-03-12 17 views
6

Ich versuche, 3D-Weltkoordinaten aus Tiefenwerten in meinem Deferred-Renderer zu rekonstruieren, aber ich habe eine Menge Zeit. Die meisten Beispiele, die ich online finde, gehen von einer Standardperspektivtransformation aus, aber ich möchte diese Annahme nicht machen.Weltkoordinaten aus Tiefenpuffer und willkürlicher Ansichts-Projektionsmatrix rekonstruieren

In meinen Geometrie Pass Vertex-Shader, berechne ich gl_Position mit:

gl_Position = wvpMatrix * vec4(vertexLocation, 1.0f); 

und in meinem Lichtpass Fragment-Shader, ich versuche, die Welt zu bekommen Koordinaten:

vec3 decodeLocation() 
{ 
    vec4 clipSpaceLocation; 
    clipSpaceLocation.xy = texcoord * 2.0f - 1.0f; 
    clipSpaceLocation.z = texture(depthSampler, texcoord).r; 
    clipSpaceLocation.w = 1.0f; 
    vec4 homogenousLocation = viewProjectionInverseMatrix * clipSpaceLocation; 
    return homogenousLocation.xyz/homogenousLocation.w; 
} 

Ich dachte, mich hatte es richtig, und tatsächlich scheinen Objekte in der Nähe der Kamera richtig zu leuchten. Aber vor kurzem habe ich festgestellt, dass Objekte, wenn ich mich weiter entferne, beleuchtet werden, als ob sie weiter von der Kamera entfernt wären, als sie tatsächlich sind. Ich habe mit meinem Lichtpass gespielt und verifiziert, dass meine Weltkoordinaten das einzige sind, was sich verrechnet hat.

Ich kann nicht helfen, aber denke, dass meine clipSpaceLocation.z und clipSpaceLocation.w die Quelle des Problems sind, aber ich habe versucht jede Variation, die ich denken kann, um sie zu berechnen, und der obige Code führt am meisten- korrekte Ergebnisse.

Irgendwelche Ideen oder Vorschläge?

+0

wie haben Sie Ihre inverse Ansicht Projektionsmatrix berechnen? Ich habe das Problem mit Licht Raum Position greifen und ich nehme die Annahme, dass es meine inversen Ansicht Projektionsmatrix. –

Antwort

4

ändern Ich musste nur eine winzige Lösung machen. Die Linie:

clipSpaceLocation.z = texture(depthSampler, texcoord).r; 

sollte lauten:

clipSpaceLocation.z = texture(depthSampler, texcoord).r * 2.0f - 1.0f; 

So wie ich es verstehe, Projektionsmatrizen ausgelegt sind, so dass sie die nahen und fernen Ebenen [-1,1], nicht [0 Karte, 1] wie ich es immer angenommen habe. OpenGL dann normalisiert sie auf den Bereich [0,1] (a.k.a. "Window Space"), so dass ich die Umkehrung dieser Normalisierung durchführen musste.

Dies ist alles vorausgesetzt glDepthRange (0, 1), die es standardmäßig ist, und es gibt wenig Grund, es zu ändern.

+0

Eigentlich GLSL erlaubt nicht das Suffix "f" auf Gleitkommazahlen ... – Tara

+0

Es hat seit OpenGL 2.1 (GLSL 1.20.8). Siehe https://www.opengl.org/registry/doc/GLSLangSpec.Full.1.20.8.pdf Abschnitt 4.1.4 –

+0

Auch wenn Ihre Antwort mehr als ein Jahr "zu spät" ist, haben Sie recht. Scheint so, als wäre es nur ein Problem, weil ich vergessen habe "#version xyz" in die Shader zu setzen. – Tara

1

Ihr allgemeiner Ansatz ist korrekt, Sie haben die Fensterraumtransformation nicht korrekt umgekehrt. Der Fensterbereich z (den Sie wahrscheinlich in Ihre Tiefenstruktur geschrieben haben) ist [0,1] (standardmäßig wäre allgemeiner glDepthRange()), aber der NDC-Raum z ist [-1,1]. So können Sie diese Zeile analog zu Ihren X- und Y-Zuordnungen zu

clipSpaceLocation.z = texture(depthSampler, texcoord).r * 2.0 - 1.0;