feat: IBL 阶段②——漫反射辐照度卷积,PBR ambient 接入环境光

- Cubemap 构造期同步 CPU 半球 Lambert 积分(64×32 网格 ≈2048 采样/像素)
  生成 32² irradiance cube(漫反射是超低频信号,分辨率无需高)
- shader:kD 用粗糙度感知 FresnelSchlickRoughness + (1-metallic),
  N 采样 irradianceMap(Set2 binding 3)替换常数 ambient;
  ambientColor 保留为强度/色调乘子
- CreateNeutral 兜底:无 HDR 资产时 1×1 常数 cube,描述符恒有效
- FaceDir 改为返回单位方向(equirect 查表要求,修掉未归一化的畸变)
This commit is contained in:
2026-09-23 18:50:34 +08:00
parent 4b5990e6c8
commit fa25cb3348
6 changed files with 325 additions and 141 deletions
+14
View File
@@ -4,6 +4,7 @@
#include <Engine/Renderer/Passes/SceneGpu.h>
#include <Engine/Renderer/Material.h>
#include <Engine/Renderer/Cubemap.h>
#include <Engine/Vulkan/Device.h>
#include <Engine/Vulkan/DescriptorManager.h>
#include <Engine/Vulkan/ShaderManager.h>
@@ -46,12 +47,16 @@ namespace Engine::Passes
textureSetLayout = descriptors.CreateLayout(texBindings);
// Set 2: CSM 级联阴影图(fragment 采样,binding = 级联序号)
// + 漫反射辐照度 cube(IBL 阶段②,binding 3)
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});
shadowSetLayout = descriptors.CreateLayout(shadowBindings);
// Forward pipeline layout:三个 set;无 push(GPUDriven 经 SSBO)
@@ -157,4 +162,13 @@ namespace Engine::Passes
}
}
void SceneGpu::BindEnvironment(const Cubemap& env)
{
// irradiance view 全程稳定(不随 RG 重编译变化),绑一次即可
for (u32 slot = 0; slot < kMaxFramesInFlight; ++slot) {
m_Descriptors.UpdateTexture(shadowSets[slot], 3, shadowSampler,
env.GetIrradianceView());
}
}
} // namespace Engine::Passes