点光源PCF阴影出现圆形伪影问题排查
点光源阴影PCF实现中的伪影与质量问题
问题背景
我正在给DirectX 12渲染器添加点光源阴影,基础阴影渲染正常:
基础采样逻辑
辅助方法SamplePointLightShadowMaps:
// @See: https://en.wikipedia.org/wiki/Cube_mapping float SamplePointLightShadowMaps(Texture2DArray<float> shadowMaps, SamplerState samplerSate, uint lightLinearIdx, float lightFarPlane, float3 toP) { const float3 toPNormalized = normalize(toP); const float x = toPNormalized.x; const float y = toPNormalized.y; const float z = toPNormalized.z; const float absX = abs(x); const float absY = abs(y); const float absZ = abs(z); const int isXPositive = x > 0 ? 1 : 0; const int isYPositive = y > 0 ? 1 : 0; const int isZPositive = z > 0 ? 1 : 0; float maxAxis, uc, vc; int faceIdx; // POSITIVE X if (isXPositive && absX >= absY && absX >= absZ) { // u (0 to 1) goes from +z to -z // v (0 to 1) goes from -y to +y maxAxis = absX; uc = -z; vc = y; faceIdx = 0u; } // NEGATIVE X if (!isXPositive && absX >= absY && absX >= absZ) { // u (0 to 1) goes from -z to +z // v (0 to 1) goes from -y to +y maxAxis = absX; uc = z; vc = y; faceIdx = 1u; } // POSITIVE Y if (isYPositive && absY >= absX && absY >= absZ) { // u (0 to 1) goes from -x to +x // v (0 to 1) goes from +z to -z maxAxis = absY; uc = x; vc = -z; faceIdx = 2u; } // NEGATIVE Y if (!isYPositive && absY >= absX && absY >= absZ) { // u (0 to 1) goes from -x to +x // v (0 to 1) goes from -z to +z maxAxis = absY; uc = x; vc = z; faceIdx = 3u; } // POSITIVE Z if (isZPositive && absZ >= absX && absZ >= absY) { // u (0 to 1) goes from -x to +x // v (0 to 1) goes from -y to +y maxAxis = absZ; uc = x; vc = y; faceIdx = 4u; } // NEGATIVE Z if (!isZPositive && absZ >= absX && absZ >= absY) { // u (0 to 1) goes from +x to -x // v (0 to 1) goes from -y to +y maxAxis = absZ; uc = -x; vc = y; faceIdx = 5u; } // Convert range from -1 to 1 to 0 to 1 const float2 uv = float2(0.5f * (uc / maxAxis + 1.0f), 0.5f * (vc / maxAxis + 1.0f)); return shadowMaps.SampleLevel(samplerSate, float3(uv, lightLinearIdx * NB_SHADOW_MAP_PER_LIGHT + faceIdx), 0).x * lightFarPlane; }
采样方法:
float PointLightShadowMapping(Texture2DArray<float> shadowMaps, LightStruct light, float3 P, float2 pixelCoord, SamplerState samplerSate) { const float3 toP = P - light.positionOrDirection.xyz; const float currentDepth = length(toP); const float bias = 0.05f; const float closestDepth = SamplePointLightShadowMaps(shadowMaps, samplerSate, light.linearIdx, light.farZ, toP); const float shadow = currentDepth - bias > closestDepth ? 0.0f : 1.0f; return shadow; }
此时得到预期效果:
PCF修改后的问题
添加PCF后,修改的采样逻辑如下:
static const uint pcf3DSampleCount = 20u; static float3 pcf3DSamples[pcf3DSampleCount] = { float3(1, 1, 1), float3(1, -1, 1), float3(-1, -1, 1), float3(-1, 1, 1), float3( 1, 1, -1), float3( 1, -1, -1), float3(-1, -1, -1), float3(-1, 1, -1), float3( 1, 1, 0), float3( 1, -1, 0), float3(-1, -1, 0), float3(-1, 1, 0), float3( 1, 0, 1), float3(-1, 0, 1), float3( 1, 0, -1), float3(-1, 0, -1), float3( 0, 1, 1), float3( 0, -1, 1), float3( 0, -1, -1), float3( 0, 1, -1) }; float PointLightShadowMapping(Texture2DArray<float> shadowMaps, LightStruct light, float3 P, float2 pixelCoord, SamplerState samplerSate) { const float3 toP = P - light.positionOrDirection.xyz; const float currentDepth = length(toP); const float diskRadius = 0.05f; const float bias = 0.05f;; float shadow = 0.0f; for(uint i = 0u; i < pcf3DSampleCount; ++i) { const float3 sampleToP = toP + pcf3DSamples[i] * diskRadius; const float closestDepth = SamplePointLightShadowMaps(shadowMaps, samplerSate, light.linearIdx, light.farZ, sampleToP); shadow += currentDepth - bias > closestDepth ? 0.0f : 1.0f; } return shadow / pcf3DSampleCount; }
出现的问题
- 墙面出现圆形伪影:

- PCF质量较差:

请问这是什么原因?感谢解答!
内容的提问来源于stack exchange,提问作者TheChamp
相关产品推荐
相关产品推荐

