feat: CSM 软阴影——sampler2DShadow 硬件 PCF + 3×3 纹素 tap
- 阴影采样器开启硬件深度比较(compareOp=eLess + linear filter): 单次采样 = 2×2 深度比较插值,clamp-to-border 白色语义不变 - ShadowFactor 改 3×3 纹素偏移 tap(等效 36 次比较),影中保留 0.3 环境感并按 PCF 结果插值——阴影边缘软过渡,消除二值硬边锯齿
This commit is contained in:
@@ -103,7 +103,9 @@ namespace Engine::Passes
|
||||
ENGINE_FATAL("SceneGpu: failed to create shader objects");
|
||||
}
|
||||
|
||||
// 阴影采样器:clamp-to-border 白色 = 光视锥之外无阴影
|
||||
// 阴影采样器:clamp-to-border 白色 = 光视锥外自动无阴影
|
||||
//(省 shader 出界分支);开启硬件深度比较(sampler2DShadow)
|
||||
// ——单次采样即 2×2 PCF,配合 shader 3×3 tap 得软阴影
|
||||
vk::SamplerCreateInfo shadowSamplerInfo;
|
||||
shadowSamplerInfo.setMagFilter(vk::Filter::eLinear)
|
||||
.setMinFilter(vk::Filter::eLinear)
|
||||
@@ -113,7 +115,8 @@ namespace Engine::Passes
|
||||
.setAddressModeW(vk::SamplerAddressMode::eClampToBorder)
|
||||
.setBorderColor(vk::BorderColor::eFloatOpaqueWhite)
|
||||
.setUnnormalizedCoordinates(VK_FALSE)
|
||||
.setCompareEnable(VK_FALSE);
|
||||
.setCompareEnable(VK_TRUE)
|
||||
.setCompareOp(vk::CompareOp::eLess);
|
||||
shadowSampler = device.GetDevice().createSampler(shadowSamplerInfo);
|
||||
|
||||
// per-slot 描述符分配 + Set0 绑定(buffer 句柄全程稳定,不用重绑)
|
||||
|
||||
+27
-12
@@ -2,6 +2,7 @@
|
||||
|
||||
const int MAX_LIGHTS = 4;
|
||||
const float PI = 3.14159265359;
|
||||
const int kCascadeRes = 1024; // CSM 级联图边长(与引擎 SceneTypes.h 同步)
|
||||
|
||||
struct Light {
|
||||
vec4 color; // rgb = 颜色,a = 强度
|
||||
@@ -43,16 +44,18 @@ layout(set = 1, binding = 5) uniform MaterialParams {
|
||||
vec4 factors; // x = metallic 因子,y = roughness 因子
|
||||
} matParams;
|
||||
|
||||
layout(set = 2, binding = 0) uniform sampler2D shadowMap0; // CSM 级联 0(最近)
|
||||
layout(set = 2, binding = 1) uniform sampler2D shadowMap1; // 级联 1
|
||||
layout(set = 2, binding = 2) uniform sampler2D shadowMap2; // 级联 2(最远)
|
||||
// CSM 阴影(sampler2DShadow:单次采样 = 硬件 2×2 深度比较 PCF)
|
||||
layout(set = 2, binding = 0) uniform sampler2DShadow shadowMap0; // CSM 级联 0(最近)
|
||||
layout(set = 2, binding = 1) uniform sampler2DShadow shadowMap1; // 级联 1
|
||||
layout(set = 2, binding = 2) uniform sampler2DShadow shadowMap2; // 级联 2(最远)
|
||||
layout(set = 2, binding = 3) uniform samplerCube irradianceMap; // 漫反射环境光(IBL 阶段②)
|
||||
layout(set = 2, binding = 4) uniform samplerCube prefilteredMap; // 镜面环境(mip 分 roughness,阶段③)
|
||||
layout(set = 2, binding = 5) uniform sampler2D brdfLut; // BRDF 积分表 (NdotV, roughness) → (scale, bias)
|
||||
|
||||
// 第 0 盏方向光(KeyLight)的 CSM 阴影因子:0.3 影中 / 1.0 受光。
|
||||
// 级联按视图深度选择;采样器均 clamp-to-border 白色:
|
||||
// 光视锥外自动 1.0(无阴影),省出界分支。
|
||||
// 第 0 盏方向光(KeyLight)的 CSM 阴影因子。
|
||||
// 级联按视图深度选择;3×3 纹素偏移采样(每 tap 硬件 2×2 PCF,
|
||||
// 等效 36 次比较)→ 软阴影边缘;采样器 clamp-to-border 白色:
|
||||
// 光视锥外自动 1.0(无阴影),省出界分支
|
||||
float ShadowFactor(vec3 N, float viewDepth) {
|
||||
int cascade = 2;
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
@@ -63,15 +66,27 @@ float ShadowFactor(vec3 N, float viewDepth) {
|
||||
vec3 proj = ls.xyz / ls.w;
|
||||
vec2 uv = proj.xy * 0.5 + 0.5;
|
||||
|
||||
float closest;
|
||||
if (cascade == 0) closest = texture(shadowMap0, uv).r;
|
||||
else if (cascade == 1) closest = texture(shadowMap1, uv).r;
|
||||
else closest = texture(shadowMap2, uv).r;
|
||||
|
||||
vec3 L = normalize(-ubo.lights[0].direction.xyz);
|
||||
float bias = max(0.004 * (1.0 - dot(N, L)), 0.0012);
|
||||
|
||||
return (proj.z - bias > closest) ? 0.3 : 1.0;
|
||||
float texel = 1.0 / float(kCascadeRes); // 与引擎 kCascadeRes 同步
|
||||
float shadow = 0.0;
|
||||
for (int y = -1; y <= 1; ++y) {
|
||||
for (int x = -1; x <= 1; ++x) {
|
||||
float lit;
|
||||
if (cascade == 0)
|
||||
lit = texture(shadowMap0, vec3(uv + vec2(x, y) * texel,
|
||||
proj.z - bias));
|
||||
else if (cascade == 1)
|
||||
lit = texture(shadowMap1, vec3(uv + vec2(x, y) * texel,
|
||||
proj.z - bias));
|
||||
else
|
||||
lit = texture(shadowMap2, vec3(uv + vec2(x, y) * texel,
|
||||
proj.z - bias));
|
||||
shadow += mix(0.3, 1.0, lit); // 影中保留 0.3 环境感
|
||||
}
|
||||
}
|
||||
return shadow / 9.0;
|
||||
}
|
||||
|
||||
// 法线贴图 → 世界空间法线(TBN 构建)。
|
||||
|
||||
Reference in New Issue
Block a user