我试图从延迟渲染器中的深度值重建3D世界坐标,但我有一点时间。我在网上找到的大多数例子都假设了标准的透视转换,但我不想做出这样的假设。
在我的几何传递顶点着色器中,我使用:
计算gl_Positiongl_Position = wvpMatrix * vec4(vertexLocation, 1.0f);
在我的照明传递片段着色器中,我尝试使用以下方法获取世界坐标:
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;
}
我以为我做对了,事实上,相机附近的物体似乎正确点亮了。但是我最近意识到,当我向远处移动时,物体会被照亮,好像他们离相机更远,而不是实际。我已经玩过我的灯光通行证,并确认我的世界坐标是唯一被误算的东西。
我无法帮助,但我认为我的clipSpaceLocation.z和clipSpaceLocation.w是问题的根源,但我已经尝试过我能想到的每个变体来计算它们,上面的代码会导致最正确的结果。
有任何想法或建议吗?
答案 0 :(得分:6)
我只需要做一个微小的修复。这一行:
clipSpaceLocation.z = texture(depthSampler, texcoord).r;
应为:
clipSpaceLocation.z = texture(depthSampler, texcoord).r * 2.0f - 1.0f;
我理解它的方式,投影矩阵的设计使它们将近和远的平面映射到[-1,1],而不是像我一直假设的那样[0,1]。然后OpenGL将它们归一化到范围[0,1](a.k.a。“窗口空间”),所以我需要执行该规范化的反转。
这都是假设glDepthRange(0,1),默认情况下,没有理由改变它。
答案 1 :(得分:1)
您的一般方法是正确的,您只是没有正确反转窗口空间转换。窗口空间z(你可能进入你的深度纹理)是[0,1](默认情况下,更通用的是glDepthRange()
),但NDC空间z是[-1,1]。因此,您可以将与x和y映射类似的行更改为
clipSpaceLocation.z = texture(depthSampler, texcoord).r * 2.0 - 1.0;
答案 2 :(得分:1)
请参阅我对gamedev.stackexchange的回答,以便更有效地重建世界和查看空间位置: