OpenGL阴影映射与延迟渲染,位置转换

时间:2015-03-16 13:17:39

标签: opengl shadow-mapping

我正在使用延迟渲染,我将眼睛空间位置存储在纹理中:

顶点:

gl_Position = vec4(vertex_position, 1.0);

几何形状:

vertexOut.position = vec3(viewMatrix * modelMatrix * gl_in[i].gl_Position);

片段:

positionOut = vec3(vertexIn.position);

现在,在第二次传递(光照传递)中,我尝试使用从此vec4计算的UV坐标来对阴影贴图进行采样

vec4 lightSpacePos = lightProjectionMatrix * lightViewMatrix * lightModelMatrix * vec4(position, 1.0);

使用的位置是从位置纹理存储和采样的相同位置。 在进行此计算之前,是否需要使用逆摄像机视图矩阵转换位置?把它带回世界空间或我该怎么办?

1 个答案:

答案 0 :(得分:0)

通常,阴影贴图是通过比较当前片段与光线的窗口空间Z坐标(这是深度纹理存储的坐标)来完成的。这必须使用共同的参考方向来完成,因此需要从光的角度重新投射当前片段的位置。

您现在拥有视图空间位置,这与您的当前相机相关,并不是特别有用。要有效地做到这一点,你需要世界空间的位置。如果通过逆视图矩阵变换视图空间位置,则可以得到它。

给定世界空间位置,从光的角度转换为剪辑空间:

// This will be in clip-space
vec4 lightSpacePos = lightProjectionMatrix * lightViewMatrix * vec4 (worldPos);

// Transform it into NDC-space by dividing by w
lightSpacePos /= lightSpacePos.w;

// Range is now [-1.0, 1.0], but you need [0.0, 1.0]
lightSpacePos = lightSpacePos * vec4 (0.5) + vec4 (0.5);

假设默认深度范围,lightSpacePos现在可以使用了。 xy包含从阴影贴图中采样的纹理坐标,z包含用于比较的深度。

有关更详尽的说明,请参阅following answer


顺便提一下,您需要从G-Buffer中消除位置纹理以获得合理的性能。只给出深度和投影以及视图矩阵并且所涉及的算法比额外的纹理提取快得多,很容易重建世界或视图空间位置。以足够的精度存储额外的纹理来表示3D空间中的位置将每帧燃烧大量的内存带宽,并且完全没有必要。

来自OpenGL Wiki的

This article解释了如何执行此操作。你可以更进一步,回到世界空间,这比视空间更令人满意。您可能需要稍微调整深度缓冲区以获得足够的精度,但它仍然比单独存储位置更快。