0

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

顶点:

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);

使用的位置与从位置纹理存储和采样的位置相同。在进行此计算之前,我是否需要使用逆相机视图矩阵转换位置?将其带回世界空间或我应该如何进行?

4

1 回答 1

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包含用于比较的深度。

有关更详尽的解释,请参阅以下答案


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

OpenGL Wiki 中的这篇文章解释了如何做到这一点。你可以更进一步,回到世界空间,这比视图空间更可取。您可能需要稍微调整深度缓冲区以获得足够的精度,但它仍然比单独存储位置更快。

于 2015-03-16T21:30:54.450 回答