feat: IBL 阶段③——pre-filtered cubemap + BRDF LUT,split-sum 镜面项接入

- pre-filter:GGX 重要性采样(Hammersley + van der Corput 位反转),
  128²×5 mip 分级 roughness,采样数 32<<mip 上限 256;UploadCube 泛化
  支持 mip 链([mip: 6面] 紧凑排布逐 mip 逐面拷贝)
- BRDF LUT:128² R16G16Sfloat 积分表((NdotV,roughness)→F 缩放/偏置),
  纯数学与环境无关,中性兜底同样生成;专用 clamp-to-edge 采样器
  (共享 border 白采样器在 uv=1.0 混入白色导致高 roughness 偏大)
- shader:specular = prefiltered(R, roughness×4) × (F·A+B),
  ambient = (diffuse + specular) × ambientColor
- Hammersley 分母修正为当次积分采样数(低 mip 偏差 bug)
- Debug 构建预积分 26s→14s(采样预算收敛 + pow 改乘法链;
  env 1024² 重采样为大头,compute 迁移后归零)
This commit is contained in:
2026-09-23 19:04:25 +08:00
parent fa25cb3348
commit 9269afaa18
4 changed files with 522 additions and 136 deletions
+13 -6
View File
@@ -46,17 +46,19 @@ namespace Engine::Passes
vk::ShaderStageFlagBits::eFragment});
textureSetLayout = descriptors.CreateLayout(texBindings);
// Set 2: CSM 级联阴影图(fragment 采样,binding = 级联序号)
// + 漫反射辐照度 cube(IBL 阶段②,binding 3)
// Set 2: CSM 级联阴影图(0/1/2)+ IBL 环境三件套(3 irradiance
// / 4 pre-filtered / 5 BRDF LUT),均 fragment 采样
std::vector<DescriptorBinding> shadowBindings;
for (u32 c = 0; c < kMaxCascades; ++c) {
shadowBindings.push_back(
{c, vk::DescriptorType::eCombinedImageSampler,
vk::ShaderStageFlagBits::eFragment});
}
shadowBindings.push_back(
{3, vk::DescriptorType::eCombinedImageSampler,
vk::ShaderStageFlagBits::eFragment});
for (const u32 b : {3u, 4u, 5u}) {
shadowBindings.push_back(
{b, vk::DescriptorType::eCombinedImageSampler,
vk::ShaderStageFlagBits::eFragment});
}
shadowSetLayout = descriptors.CreateLayout(shadowBindings);
// Forward pipeline layout:三个 set;无 push(GPUDriven 经 SSBO)
@@ -164,10 +166,15 @@ namespace Engine::Passes
void SceneGpu::BindEnvironment(const Cubemap& env)
{
// irradiance view 全程稳定(不随 RG 重编译变化),绑一次即可
// IBL 资源 view 全程稳定(不随 RG 重编译变化),绑一次即可
for (u32 slot = 0; slot < kMaxFramesInFlight; ++slot) {
m_Descriptors.UpdateTexture(shadowSets[slot], 3, shadowSampler,
env.GetIrradianceView());
m_Descriptors.UpdateTexture(shadowSets[slot], 4, shadowSampler,
env.GetPrefilteredView());
m_Descriptors.UpdateTexture(shadowSets[slot], 5,
env.GetBrdfLutSampler(),
env.GetBrdfLutView());
}
}