具有延迟渲染、位置转换的 OpenGL 阴影映射
OpenGL shadow mapping with deferred rendering, position transformation
我正在使用延迟渲染,我相应地在纹理中存储眼睛 space 位置:
顶点:
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);
使用的位置与从位置纹理存储和采样的位置相同。
在进行此计算之前,我是否需要使用逆相机视图矩阵转换位置?要将它带回世界 space 或者我应该如何进行?
通常阴影贴图是通过比较当前片段与光线的 window-space Z 坐标(这是深度纹理存储的)来完成的。这必须使用共同的参考方向来完成,因此涉及从光线的角度重新投影当前片段的位置。
您现在的视图-space 位置是相对于您的当前 相机的,不是特别有用。要有效地做到这一点,您需要 world-space 位置。如果你通过逆视图矩阵转换视图-space 位置,你可以得到它。
给定 world-space 位置,从光的角度转换为 clip-space:
// 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 中消除位置纹理以实现合理的性能。仅给定深度以及投影和视图矩阵,重建世界或视图-space 位置非常容易,所涉及的算法比额外的纹理获取快得多。以足够的精度存储额外的纹理来表示 3D 中的位置 space 将消耗每帧大量的内存带宽,这是完全没有必要的。
OpenGL Wiki 中的 This article 解释了如何执行此操作。你可以更进一步,回到 world-space,这比 view-space 更令人向往。您可能需要稍微调整深度缓冲区以获得足够的精度,但它仍然比单独存储位置更快。
我正在使用延迟渲染,我相应地在纹理中存储眼睛 space 位置:
顶点:
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);
使用的位置与从位置纹理存储和采样的位置相同。 在进行此计算之前,我是否需要使用逆相机视图矩阵转换位置?要将它带回世界 space 或者我应该如何进行?
通常阴影贴图是通过比较当前片段与光线的 window-space Z 坐标(这是深度纹理存储的)来完成的。这必须使用共同的参考方向来完成,因此涉及从光线的角度重新投影当前片段的位置。
您现在的视图-space 位置是相对于您的当前 相机的,不是特别有用。要有效地做到这一点,您需要 world-space 位置。如果你通过逆视图矩阵转换视图-space 位置,你可以得到它。
给定 world-space 位置,从光的角度转换为 clip-space:
// 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 中消除位置纹理以实现合理的性能。仅给定深度以及投影和视图矩阵,重建世界或视图-space 位置非常容易,所涉及的算法比额外的纹理获取快得多。以足够的精度存储额外的纹理来表示 3D 中的位置 space 将消耗每帧大量的内存带宽,这是完全没有必要的。
OpenGL Wiki 中的This article 解释了如何执行此操作。你可以更进一步,回到 world-space,这比 view-space 更令人向往。您可能需要稍微调整深度缓冲区以获得足够的精度,但它仍然比单独存储位置更快。