我编写了一个管理聚光灯阴影映射的3D应用程序。为此,我使用经典阴影贴图技术(我在第一个渲染过程中填充深度纹理,在第二个渲染过程中,我比较从光到第一个遮挡物的距离以及从光到顶点位置的距离,以了解我是否片段是否在阴影中。)
这是截图(聚光灯/ 2D深度纹理阴影贴图):
在这个例子中,我使用'textureProjOffset'函数使用PCF阴影映射技术。这是我的片段着色器中的一段代码:
使用的采样器:
sampler2DShadow Shadow2DSampler[MAX_LIGHTS_COUNT];
对于HARD阴影:
shadowFactor = textureProj(Shadow2DSampler[idx], ShadowCoords[idx]);
对于PCF SOFT阴影:
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个渲染状态)。
这是截图(聚光灯/立方体深度纹理阴影贴图):
如您所见,它只是HARD阴影贴图。为了恢复编码到立方体贴图中的深度值,我必须使用函数'texture'('samplerCube'和'samplerCubeShadow'不存在textureProj)。接下来,我必须计算世界空间中光位置和顶点位置之间的距离,然后将其转换为剪辑空间,因为纹理中包含的深度值已经在剪辑空间中。
这是片段着色器中的一段代码,用于查看过程:
使用的采样器:
samplerCubeShadow ShadowCubeSampler[MAX_LIGHTS_COUNT];
对于HARD阴影:
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 SOFT阴影怎么样?我做了一些研究,显然它不存在恢复纹理偏移的任何功能,就像使用简单的2D纹理并在片段着色器中使用关键字'sampler2DShadow'一样。我错了吗 ? (我希望如此!)。
我认为我有一个解决方案(当然,如果它不存在任何使用cubemap的解决方案):
显然,要恢复纹理偏移,我将不得不使用6个单独的纹理(所以'sampler2DShadow'的数组大小为6而不是'samplerCubeShadow')。所以我将同样一致地使用matrix4x4数组来表示在光空间中的世界表示,就像我在第一种情况下为点光阴影映射所做的那样。然后我将使用6个纹理方法'textureProjOffset'。
那么,您怎么看?是否可以使用立方体贴图进行PCF软阴影?如果不是这样,我的解决方案是否正确?是否可以使用'samplerCff''或'samplerCubeShadow'之类的'textureProjOffset'这样的函数?还是有替代方案吗?
非常感谢您的帮助!