feat: Shadow pass 接入 RenderGraph,支持 SRT 变换与程序化平面
阴影(本修正的核心根因):
- Shadow pass 光源正交写深度(2048 D32),Forward 采样比较;
写入与采样共用同一 lightSpace 矩阵,杜绝姿态/镜像不一致
- 修复:push constant range 64B→128B(原 Shadow pass 推 {lightVP,model}
超出 layout 声明范围 = UB,阴影中模型矩阵读到垃圾导致旋转错乱)
- 修复:ShadowFactor 缺少 NDC→UV 映射(*0.5+0.5),采样区域整体错位
- 修复:RG ShaderRead stage 位值直转(eFragment=0x10 在 PipelineStage2
是 TESSELLATION_CONTROL),改为逐位显式映射
- Camera perspective 深度重映射到 Vulkan [0,1](公式与 ortho 不同:
M22=M22*0.5-0.5, M32*=0.5);光源 ortho remap 用 M32=M32*0.5+0.5
引擎配套:
- TransformComponent 重构为 position/rotation/scale + Compose()
- Texture::CreateSolidColor / Model::CreatePlane 程序化资产
(两段式上传公共路径),AssetManager.CreatePlane 带缓存入口
- RG 新增 GetPhysicalView(h, slot):按帧槽位把 RG 资源绑进外部描述符
(阴影图 per-slot 物理镜像各自绑定)
验证:validation 0 error 0 warning,阴影随实体旋转正确
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
#version 450
|
||||
|
||||
// Shadow pass fragment:depth-only,无输出。
|
||||
// 深度写入由深度附件 + 光栅化完成(含管线深度 bias)。
|
||||
|
||||
void main() {
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#version 450
|
||||
|
||||
// Shadow pass vertex:光源视角写深度。
|
||||
// push constant = { lightVP, model },与 Forward pass 用同一份
|
||||
// lightVP(UBO.lightSpace)和同一份 model(TransformComponent.world),
|
||||
// 保证阴影贴图与主视角几何严格一致。
|
||||
|
||||
layout(location = 0) in vec3 inPosition;
|
||||
|
||||
layout(push_constant) uniform ShadowPush {
|
||||
mat4 lightVP;
|
||||
mat4 model;
|
||||
} pc;
|
||||
|
||||
void main() {
|
||||
gl_Position = pc.lightVP * pc.model * vec4(inPosition, 1.0);
|
||||
}
|
||||
@@ -10,17 +10,34 @@ 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 = 0) out vec4 outColor;
|
||||
|
||||
layout(set = 0, binding = 0) uniform UniformBufferObject {
|
||||
mat4 view;
|
||||
mat4 proj;
|
||||
mat4 lightSpace;
|
||||
vec4 ambientColor;
|
||||
Light lights[MAX_LIGHTS];
|
||||
} ubo;
|
||||
|
||||
layout(set = 1, binding = 0) uniform sampler2D texSampler;
|
||||
layout(set = 2, binding = 0) uniform sampler2D shadowMap;
|
||||
|
||||
// 第 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;
|
||||
|
||||
// 斜率缩放 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;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec3 albedo = texture(texSampler, fragUV).rgb;
|
||||
@@ -31,8 +48,9 @@ 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);
|
||||
result += ubo.lights[i].color.rgb * ubo.lights[i].color.a * diff * albedo;
|
||||
float shade = (i == 0) ? ShadowFactor(N) : 1.0;
|
||||
result += ubo.lights[i].color.rgb * ubo.lights[i].color.a * diff * albedo * shade;
|
||||
}
|
||||
|
||||
outColor = vec4(result, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ 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(push_constant) uniform PushConstants {
|
||||
mat4 model;
|
||||
@@ -22,6 +23,7 @@ layout(push_constant) uniform PushConstants {
|
||||
layout(set = 0, binding = 0) uniform UniformBufferObject {
|
||||
mat4 view;
|
||||
mat4 proj;
|
||||
mat4 lightSpace;
|
||||
vec4 ambientColor;
|
||||
Light lights[MAX_LIGHTS];
|
||||
} ubo;
|
||||
@@ -31,6 +33,8 @@ void main() {
|
||||
gl_Position = ubo.proj * ubo.view * worldPos;
|
||||
|
||||
fragWorldPos = worldPos.xyz;
|
||||
// 光空间坐标(含 Vulkan [0,1] 深度重映射,与 shadow pass 写入端共用同一矩阵)
|
||||
fragLightSpacePos = (ubo.lightSpace * worldPos).xyz;
|
||||
|
||||
mat3 normalMatrix = mat3(transpose(inverse(pc.model)));
|
||||
fragNormal = normalize(normalMatrix * inNormal);
|
||||
|
||||
Reference in New Issue
Block a user