RealTime-Rendering22-Reconstruct position from depth

Reconstruct Position from depth

Reconstruct from ViewRay and Depth

01.png

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; //viewSpace
vec3 worldSpacePosition = cameraPosition + viewSpacePosition; //worldSpace
}

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; //[0, 1] -> [-1, 1]
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, 需要确保在像素中心点.