feat: CSM 级联阴影(3 级联 × 1024²,实用分割 + 纹素对齐)
- SceneRenderer::ComputeCascades:相机视锥实用分割(λ=0.6)→ 反投影 取切片角点 → 光空间 AABB 拟合 → 纹素对齐(消除相机移动时阴影边缘 闪烁)→ [0,1] 深度重映射 - Shadow pass 单 pass 渲 3 个 region,每级联 push 各自光空间 VP - Forward:UBO lightSpace[3]+cascadeSplits(视图深度选级联),Set2 三张级联图按 binding 0/1/2 采样;vertex 输出 fragViewDepth - 光源视锥剔除用最远级联(覆盖全阴影范围);双视锥独立剔除铁律保留 - 旧单张 2048 全场景图退役;近处级联分辨率 ~128px/unit(约 2× 提升) - 编译零错误、validation 零警告、8 秒冒烟通过(10 pass 全活跃)
This commit is contained in:
+30
-11
@@ -10,7 +10,7 @@ struct Light {
|
||||
layout(location = 0) in vec2 fragUV;
|
||||
layout(location = 1) in vec3 fragNormal;
|
||||
layout(location = 2) in vec3 fragWorldPos;
|
||||
layout(location = 3) in vec3 fragLightSpacePos;
|
||||
layout(location = 3) in float fragViewDepth;
|
||||
layout(location = 4) in vec2 fragVelocity;
|
||||
|
||||
layout(location = 0) out vec4 outColor;
|
||||
@@ -19,26 +19,45 @@ layout(location = 1) out vec2 outVelocity; // TAA velocity 附件
|
||||
layout(set = 0, binding = 0) uniform UniformBufferObject {
|
||||
mat4 view;
|
||||
mat4 proj;
|
||||
mat4 lightSpace;
|
||||
mat4 lightSpace[3]; // CSM 各级联光空间 VP
|
||||
vec4 cascadeSplits; // xyz = 级联 0..2 远边界(视图深度)
|
||||
vec4 ambientColor;
|
||||
Light lights[MAX_LIGHTS];
|
||||
mat4 projNoJitter;
|
||||
mat4 prevView;
|
||||
mat4 prevProj;
|
||||
} ubo;
|
||||
|
||||
layout(set = 1, binding = 0) uniform sampler2D texSampler;
|
||||
layout(set = 2, binding = 0) uniform sampler2D shadowMap;
|
||||
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(最远)
|
||||
|
||||
// 第 0 盏灯(KeyLight)的阴影因子:0.3 影中 / 1.0 受光。
|
||||
// 采样器为 clamp-to-border 白色:光视锥外自动 1.0(无阴影)。
|
||||
float ShadowFactor(vec3 N) {
|
||||
// NDC [-1,1] → UV [0,1](ortho 的 w=1,无需透视除法)
|
||||
vec2 uv = fragLightSpacePos.xy * 0.5 + 0.5;
|
||||
float closest = texture(shadowMap, uv).r;
|
||||
// 第 0 盏灯(KeyLight)的 CSM 阴影因子:0.3 影中 / 1.0 受光。
|
||||
// 级联按视图深度选择;采样器均 clamp-to-border 白色:
|
||||
// 光视锥外自动 1.0(无阴影),省出界分支。
|
||||
float ShadowFactor(vec3 N, float viewDepth) {
|
||||
// 级联选择:第一个 viewDepth < split 的级联
|
||||
int cascade = 2;
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
if (viewDepth < ubo.cascadeSplits[i]) { cascade = i; break; }
|
||||
}
|
||||
|
||||
vec4 ls = ubo.lightSpace[cascade] * vec4(fragWorldPos, 1.0);
|
||||
vec3 proj = ls.xyz / ls.w;
|
||||
// NDC [-1,1] → UV [0,1](ortho 的 w=1)
|
||||
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;
|
||||
|
||||
// 斜率缩放 bias:掠射面用更大的 bias 压 acne
|
||||
vec3 L = normalize(-ubo.lights[0].direction.xyz);
|
||||
float bias = max(0.004 * (1.0 - dot(N, L)), 0.0012);
|
||||
|
||||
return (fragLightSpacePos.z - bias > closest) ? 0.3 : 1.0;
|
||||
return (proj.z - bias > closest) ? 0.3 : 1.0;
|
||||
}
|
||||
|
||||
void main() {
|
||||
@@ -50,7 +69,7 @@ void main() {
|
||||
for (int i = 0; i < MAX_LIGHTS; ++i) {
|
||||
vec3 L = normalize(-ubo.lights[i].direction.xyz);
|
||||
float diff = max(dot(N, L), 0.0);
|
||||
float shade = (i == 0) ? ShadowFactor(N) : 1.0;
|
||||
float shade = (i == 0) ? ShadowFactor(N, fragViewDepth) : 1.0;
|
||||
result += ubo.lights[i].color.rgb * ubo.lights[i].color.a * diff * albedo * shade;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@ layout(location = 2) in vec2 inUV;
|
||||
layout(location = 0) out vec2 fragUV;
|
||||
layout(location = 1) out vec3 fragNormal;
|
||||
layout(location = 2) out vec3 fragWorldPos;
|
||||
layout(location = 3) out vec3 fragLightSpacePos;
|
||||
layout(location = 4) out vec2 fragVelocity; // TAA:clip 空间运动向量
|
||||
layout(location = 3) out float fragViewDepth; // CSM:视图深度(级联选择)
|
||||
layout(location = 4) out vec2 fragVelocity; // TAA:clip 空间运动向量
|
||||
|
||||
// GPUDriven:模型矩阵从实例缓冲按实例索引取。
|
||||
// 同一 mesh 的 N 个实体 = 1 次 drawIndexed(instanceCount=N),
|
||||
@@ -31,12 +31,13 @@ layout(std430, set = 0, binding = 2) readonly buffer PrevObjectBuffer {
|
||||
|
||||
layout(set = 0, binding = 0) uniform UniformBufferObject {
|
||||
mat4 view;
|
||||
mat4 proj; // 抖动后(光栅化)
|
||||
mat4 lightSpace;
|
||||
mat4 proj;
|
||||
mat4 lightSpace[3]; // CSM 各级联光空间 VP
|
||||
vec4 cascadeSplits; // xyz = 级联 0..2 远边界(视图深度)
|
||||
vec4 ambientColor;
|
||||
Light lights[MAX_LIGHTS];
|
||||
mat4 projNoJitter; // 未抖动(velocity 当前帧)
|
||||
mat4 prevView; // velocity 上一帧
|
||||
mat4 projNoJitter;
|
||||
mat4 prevView;
|
||||
mat4 prevProj;
|
||||
} ubo;
|
||||
|
||||
@@ -54,8 +55,8 @@ void main() {
|
||||
fragVelocity = (currClip.xy / currClip.w - prevClip.xy / prevClip.w) * 0.5;
|
||||
|
||||
fragWorldPos = worldPos.xyz;
|
||||
// 光空间坐标(含 Vulkan [0,1] 深度重映射,与 shadow pass 写入端共用同一矩阵)
|
||||
fragLightSpacePos = (ubo.lightSpace * worldPos).xyz;
|
||||
// CSM:视图深度(正值,与 cascadeSplits 同尺度)
|
||||
fragViewDepth = -(ubo.view * worldPos).z;
|
||||
|
||||
mat3 normalMatrix = mat3(transpose(inverse(model)));
|
||||
fragNormal = normalize(normalMatrix * inNormal);
|
||||
|
||||
Reference in New Issue
Block a user