使用cubemap(OpenGL/GLSL)的点光源是否可以使用软阴影?

使用cubemap(OpenGL/GLSL)的点光源是否可以使用软阴影?,opengl,glsl,shader,shadow,shadow-mapping,Opengl,Glsl,Shader,Shadow,Shadow Mapping,我编写了一个管理聚光灯阴影贴图的3D应用程序。为此,我使用经典的阴影贴图技术(我在第一个渲染过程中填充深度纹理,在第二个渲染过程中,我比较从灯光到第一个遮罩的距离和从灯光到顶点位置的距离,以了解片段是否在阴影中) 下面是一个屏幕截图(聚光灯/2D深度纹理阴影贴图): 在本例中,我使用函数“textureProjOffset”使用PCF阴影映射技术。下面是我的片段着色器中的一段代码: 使用的取样器: sampler2DShadow Shadow2DSampler[MAX_LIGHTS_COUNT

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

下面是一个屏幕截图(聚光灯/2D深度纹理阴影贴图):

在本例中,我使用函数“textureProjOffset”使用PCF阴影映射技术。下面是我的片段着色器中的一段代码:

使用的取样器:

sampler2DShadow Shadow2DSampler[MAX_LIGHTS_COUNT];
samplerCubeShadow ShadowCubeSampler[MAX_LIGHTS_COUNT];
对于硬阴影:

shadowFactor = textureProj(Shadow2DSampler[idx], ShadowCoords[idx]);
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);
}
对于PCF软阴影:

for (int idy = offset; idy >= -offset; idy--)
                for (int idx = -offset; idx <= offset; idx++)
                    shadowFactor += textureProjOffset(
                        Shadow2DSampler[idz], ShadowCoords[idz], ivec2(idx, idy)); 
对于硬阴影:

shadowFactor = textureProj(Shadow2DSampler[idx], ShadowCoords[idx]);
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);
}
float-ConvertDistToClipSpace(vec3-lightDir\u-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);
返回值((正常比较+1)*0.5f);
}
float-GetBiased\u-Cube\u-Hard\u-ShadowFactor(vec3-vert\u-ws,int-idx)
{
vec3 lightToVertexDir_ws=vertexdir_ws-LightPos_ws.xyz;
float LightToVertexClipDist=ConvertDistToClipSpace(lightToVertexDir_ws);
float LightToOccluderClipDist=纹理(
阴影立方体采样器[idx],vec4(lightToVertexDir_ws,LightToVertexClipDist));
if(LightToOccluderClipDist
知道吗,使用立方体贴图的PCF软阴影呢?我做了一些研究,显然它不存在任何功能来恢复纹理偏移,就像使用简单的2D纹理和在片段着色器中使用关键字“sampler2DShadow”一样。我错了吗?(我希望如此!)

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

显然,要恢复纹理偏移,我必须使用6个单独的纹理(因此是一个大小为6的“sampler2DShadow”数组,而不是一个“samplerCubeShadow”)。因此,我将有一个同样均匀的矩阵数组x4x4,代表光空间中的世界,就像我在第一个案例中对聚光灯阴影贴图所做的那样。然后我将使用“TextureProjectOffset”方法处理6种纹理

那么,你认为呢?是否可以使用立方体贴图进行PCF软阴影处理?如果不是这样,我的解决方案正确吗?是否可以使用“samplerCube”或“samplerCubeShadow”使用类似“TextureProjectOffset”的函数?还是有其他选择


非常感谢您的帮助

我所知道的为立方体贴图实现PCF软阴影的唯一方法是使用小偏移量多次查询纹理。例如,本文介绍了此方法。

非常感谢您的回答。拜拜。在现代AMD和NV驱动程序上,如果您对过滤器使用
samplerCubeShadow
GL_LINEAR
,它将自动执行2x2 PCF。2x2窗口非常小,因此您可能应该将硬件PCF与一些偏移结合起来,以增加有效窗口大小。这篇文章没有利用硬件的能力做2x2 PCF,因为它的年龄,但这通常是你应该如何处理这个问题。如果利用这一点,您可以使用4个查找而不是16个查找来实现4x4 PCF。