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:
@@ -1,18 +1,16 @@
|
||||
//
|
||||
// Created by atdunbg on 2026/9/23.
|
||||
//
|
||||
// Cubemap:环境立方体贴图 + 漫反射辐照度图(IBL 阶段②)。
|
||||
// Cubemap:环境立方体贴图 + IBL 预积分资源(阶段②③,split-sum)。
|
||||
//
|
||||
// 从等距柱状 HDR(.hdr,polyhaven 等)生成:CPU 重采样到 6 面
|
||||
//(一次性加载成本,亚秒级),转 fp16 后整块上传,硬件 Cube 采样。
|
||||
// 同一次加载内完成 irradiance 卷积(半球积分,源数据在手零额外 IO)。
|
||||
// 从等距柱状 HDR(.hdr,polyhaven 等)生成,CPU 一次性预积分:
|
||||
// env cube —— 重采样 6 面(Skybox 背景)
|
||||
// irradiance cube —— 半球 Lambert 积分(PBR 漫反射 ambient)
|
||||
// prefilter cube —— GGX 重要性采样 × mip 分级 roughness(镜面 IBL)
|
||||
// BRDF LUT —— 2D 积分表(纯数学,与环境内容无关)
|
||||
// 全部 fp16 上传,运行时采样零积分开销。
|
||||
//
|
||||
// 双图契约:
|
||||
// Get()/GetView() —— 环境 cube(Skybox 背景)
|
||||
// GetIrradianceView() —— 漫反射辐照度 cube(PBR ambient)
|
||||
// 镜面 IBL(pre-filter + BRDF LUT)后续接入,形态一致。
|
||||
//
|
||||
// 后续演进:CPU 卷积 → compute pass(动态环境零卡顿);本类的
|
||||
// 后续演进:CPU 预积分 → compute pass(动态环境零卡顿);本类的
|
||||
// 方向表/上传路径届时整体迁移,接口不变。
|
||||
//
|
||||
|
||||
@@ -30,14 +28,14 @@ namespace Engine {
|
||||
|
||||
class Cubemap {
|
||||
public:
|
||||
// 从等距柱状 HDR 生成(CPU 重采样 6 面 + irradiance 卷积)
|
||||
// 从等距柱状 HDR 生成(CPU 重采样 + irradiance/prefilter/BRDF 预积分)
|
||||
static Scope<Cubemap> CreateFromHdrEquirect(Device& device,
|
||||
MemoryAllocator& allocator,
|
||||
const std::string& path,
|
||||
u32 faceSize);
|
||||
|
||||
// 中性兜底(无 HDR 资产时):env/irradiance 均为常数色。
|
||||
// 保证引用侧描述符恒有效(validation),渲染退化为常数环境
|
||||
// 中性兜底(无 HDR 资产时):cube 均为常数色;BRDF LUT 仍为
|
||||
// 真实积分(纯数学)。保证引用侧描述符恒有效(validation)
|
||||
static Scope<Cubemap> CreateNeutral(Device& device,
|
||||
MemoryAllocator& allocator,
|
||||
const glm::vec3& rgb);
|
||||
@@ -51,23 +49,43 @@ namespace Engine {
|
||||
vk::Image Get() const { return m_EnvImage; }
|
||||
vk::ImageView GetView() const { return m_EnvView; }
|
||||
|
||||
// ---- 漫反射辐照度 cube(PBR ambient)----
|
||||
// ---- 漫反射辐照度 cube(PBR ambient diffuse 项)----
|
||||
vk::ImageView GetIrradianceView() const { return m_IrrView; }
|
||||
|
||||
// ---- pre-filtered cube(PBR ambient specular 项,按 mip 分 roughness)----
|
||||
vk::ImageView GetPrefilteredView() const { return m_PrefView; }
|
||||
u32 GetPrefilteredMipCount() const { return m_PrefMipLevels; }
|
||||
|
||||
// ---- BRDF LUT(envBRDF 查表,vec2(NdotV, roughness) → F 缩放/偏置)----
|
||||
vk::ImageView GetBrdfLutView() const { return m_LutView; }
|
||||
// LUT 专用采样器(clamp-to-edge):共享的 border 白采样器会在
|
||||
// uv=1.0 处混入 50% 白色 border,导致高 roughness 镜面偏大
|
||||
vk::Sampler GetBrdfLutSampler() const { return m_LutSampler; }
|
||||
|
||||
vk::Sampler GetSampler() const { return m_Sampler; }
|
||||
u32 GetFaceSize() const { return m_FaceSize; }
|
||||
|
||||
private:
|
||||
Cubemap(Device& device, MemoryAllocator& allocator,
|
||||
vk::Image envImage, vk::ImageView envView,
|
||||
vk::Image irrImage, vk::ImageView irrView, vk::Sampler sampler,
|
||||
vk::Image irrImage, vk::ImageView irrView,
|
||||
vk::Image prefImage, vk::ImageView prefView, u32 prefMips,
|
||||
vk::Image lutImage, vk::ImageView lutView,
|
||||
vk::Sampler sampler, vk::Sampler lutSampler,
|
||||
MemoryAllocator::Allocation envAlloc,
|
||||
MemoryAllocator::Allocation irrAlloc, u32 faceSize)
|
||||
MemoryAllocator::Allocation irrAlloc,
|
||||
MemoryAllocator::Allocation prefAlloc,
|
||||
MemoryAllocator::Allocation lutAlloc, u32 faceSize)
|
||||
: m_Device(device), m_Allocator(allocator),
|
||||
m_EnvImage(envImage), m_EnvView(envView),
|
||||
m_IrrImage(irrImage), m_IrrView(irrView),
|
||||
m_Sampler(sampler), m_EnvAllocation(envAlloc),
|
||||
m_IrrAllocation(irrAlloc), m_FaceSize(faceSize) {}
|
||||
m_PrefImage(prefImage), m_PrefView(prefView),
|
||||
m_PrefMipLevels(prefMips),
|
||||
m_LutImage(lutImage), m_LutView(lutView),
|
||||
m_Sampler(sampler), m_LutSampler(lutSampler),
|
||||
m_EnvAllocation(envAlloc), m_IrrAllocation(irrAlloc),
|
||||
m_PrefAllocation(prefAlloc), m_LutAllocation(lutAlloc),
|
||||
m_FaceSize(faceSize) {}
|
||||
|
||||
Device& m_Device;
|
||||
MemoryAllocator& m_Allocator;
|
||||
@@ -76,9 +94,18 @@ namespace Engine {
|
||||
vk::ImageView m_EnvView;
|
||||
vk::Image m_IrrImage;
|
||||
vk::ImageView m_IrrView;
|
||||
vk::Image m_PrefImage;
|
||||
vk::ImageView m_PrefView;
|
||||
u32 m_PrefMipLevels;
|
||||
vk::Image m_LutImage;
|
||||
vk::ImageView m_LutView;
|
||||
vk::Sampler m_Sampler;
|
||||
vk::Sampler m_LutSampler;
|
||||
|
||||
MemoryAllocator::Allocation m_EnvAllocation;
|
||||
MemoryAllocator::Allocation m_IrrAllocation;
|
||||
MemoryAllocator::Allocation m_PrefAllocation;
|
||||
MemoryAllocator::Allocation m_LutAllocation;
|
||||
u32 m_FaceSize;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user