使用立方体贴图(OpenGL / GLSL),使用点光源可以产生柔和的阴影吗?

Are soft shadows possible with point light using cubemap (OpenGL/GLSL)?

我编写了一个3D应用程序,用于管理点光源阴影贴图。为此,我使用经典的阴影贴图技术(我在第一个渲染通道中填充了深度纹理,在第二个渲染通道中,我比较了从光到第一个遮挡物的距离以及从光到顶点位置的距离,以了解是否片段是否在阴影中)。

这是屏幕截图(点光源/ 2D深度纹理阴影贴图):

enter image description here

在此示例中,我使用功能为" textureProjOffset"的PCF阴影映射技术。这是片段着色器中的一段代码:

使用的采样器:

1
sampler2DShadow Shadow2DSampler[MAX_LIGHTS_COUNT];

对于硬阴影:

1
shadowFactor = textureProj(Shadow2DSampler[idx], ShadowCoords[idx]);

对于PCF SOFT阴影:

1
2
3
4
for (int idy = offset; idy >= -offset; idy--)
                for (int idx = -offset; idx <= offset; idx++)
                    shadowFactor += textureProjOffset(
                        Shadow2DSampler[idz], ShadowCoords[idz], ivec2(idx, idy));

我还管理了基本的立方体贴图阴影贴图,以管理当前应用于点光源的全向阴影贴图。为此,我在第一个渲染通道中使用了一个几何着色器来调度由6个阴影平截头体提供的投影和视图矩阵(所有通道都通过一次!这一次的技术与6个渲染状态填充6个单独的纹理不同)。

这是屏幕截图(点光源/立方体深度纹理阴影贴图):

enter image description here

如您所见,这只是HARD阴影映射。为了恢复编码到立方体贴图中的深度值,我这次必须使用功能"纹理"(" samplerCube"和" samplerCubeShadow"不存在textureProj)。接下来,我必须计算世界空间中光照位置和顶点位置之间的距离,然后将其转换为剪贴空间,因为包含在纹理中的深度值已经在剪贴空间中。

这是片段着色器中的一段代码,用于查看该过程:

使用的采样器:

1
samplerCubeShadow ShadowCubeSampler[MAX_LIGHTS_COUNT];

对于硬阴影:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
float ConvertDistToClipSpace(vec3 lightDir_ws)
{
    vec3 AbsVec = abs(lightDir_ws);
    float LocalZcomp = max(AbsVec.x, max(AbsVec.y, AbsVec.z));

    float NormZComp = (NearFar.y + NearFar.x)/(NearFar.y - NearFar.x)
        - (2.0f * NearFar.y * NearFar.x)/(LocalZcomp * NearFar.y - NearFar.x);

    return ((NormZComp + 1) * 0.5f);
}

float GetBiased_Cube_Hard_ShadowFactor(vec3 vertexPosition_ws, int idx)
{
    vec3 lightToVertexDir_ws = vertexPosition_ws - LightPos_ws.xyz;
    float LightToVertexClipDist = ConvertDistToClipSpace(lightToVertexDir_ws);

    float LightToOccluderClipDist = texture(
        ShadowCubeSampler[idx], vec4(lightToVertexDir_ws, LightToVertexClipDist));

    if (LightToOccluderClipDist < LightToVertexClipDist)
        return (0.0f);
    return (1.0f);
}

而且知道,使用cubemap的PCF SOFT阴影怎么样?我做了一些研究,显然它不存在任何恢复纹理偏移的功能,就像使用简单的2D纹理并在片段着色器中使用关键字" sampler2DShadow"一样。我错了吗 ? (希望如此!)。

我想我有一个解决方案(当然,如果它不存在任何使用cubemap的解决方案):

显然,要恢复纹理偏移,我将必须使用6个单独的纹理(因此,大小为6的" sampler2DShadow"数组而不是" samplerCubeShadow")。因此,我将像在我的第一种情况下一样,均匀地使用矩阵4x4数组来表示光空间中的世界表示,就像我对聚光阴影映射所做的那样。然后我将使用6种纹理方法'textureProjOffset'。

所以你怎么看?是否可以使用cubemap制作PCF软阴影?如果不是这种情况,我的解决方案正确吗?是否可以通过" samplerCube"或" samplerCubeShadow"使用" textureProjOffset"之类的功能?还是有其他选择?

在此先感谢您的帮助!


我知道的为立方贴图实现PCF软阴影的唯一方法是多次以小偏移量查询纹理。 例如,此GPU Gems文章(12.4)中介绍了此方法。