Reconstruct Position from depth
Reconstruct from ViewRay and Depth

1 2 3 4 5 6 7 8 9 10 11 12 13
| layout(location = 0) in vec3 aPos;
out VsOut { vec3 viewRay; } vsOut;
void main() { vsOut.viewRay = viewMatrix * modelMatrix * vec4(aPos, 1.0); vsOut.viewRay = vec3((vsOut.viewRay.xy / vsOut.viewRay.z), 1.0); gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(aPos, 1.0); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| in VsOut { vec3 viewRay; } fsIn;
uniform sampler2D depthTex; uniform vec3 cameraPosition;
float linearizeDepth(float depth) { float z = depth * 2.0 - 1.0; float linearDepth = (2.0 * nearPlane * farPlane) / (farPlane + nearPlane - z * (farPlane - nearPlane)); return linearDepth; }
void main() { float depth = texture(depthTex, uv).r; float linearDepth = linearizeDepth(depth); vec3 viewSpacePosition = fsIn.viewRay * linearDepth; vec3 worldSpacePosition = cameraPosition + viewSpacePosition; }
|
Reconstruct from uv and Depth(fullScreenQuad)
screenSpace->ndc->clipSpace->worldSpace
1 2 3 4 5 6 7 8 9 10 11 12
| uniform sampler2D depthTex; uniform mat4 inverseViewProjectionMatrix; in vec2 vUv; void main() { float depth = texture(depthTex, uv).r; depth = depth * 2.0 - 1.0; vec2 uv = vUv * 2.0 - 1.0; vec4 clipSpacePos = vec4(uv, depth, 1.0); vec4 worldSpacePos = inverseViewProjectionMatrix * clipSpacePos; worldSpacePos = worldSpacePos.xyz / worldSpacePos.w; }
|
深度值范围:从深度纹理中读取的深度值depth通常是非线性的,范围在[0, 1]。但在OpenGL中,NDC(归一化设备坐标)的Z值范围是[-1, 1],因此必须进行映射ndcZ = depth * 2.0 - 1.0。如果是DirectX,NDC的Z值范围是[0, 1],则无需此此步骤.
Reconstruct from gl_globalInvocationID and Depth
1 2 3 4 5 6 7 8 9 10 11 12 13
| uniform mat4 inverseViewProjectionMatrix;
void main() { ivec2 index = ivec2(gl_GlobalInvocationID.xy); vec2 uv = (index + 0.5f) / viewSize.xy; uv = uv * 2.0 - 1.0; float depth = imageLoad(depthTex, index).r; depth = depth * 2.0 - 1.0; vec4 clipSpacePos = vec4(uv, depth, 1.0); vec4 worldSpacePos = inverseViewProjectionMatrix * clipSpacePos; worldSpacePos = worldSpacePos.xyz / worldSpacePos.w; }
|
注意在computeShader中基于gl_GlobalIvocationID重构世界空间位置, 需要+ 0.5, 需要确保在像素中心点.