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:
@@ -1,11 +1,19 @@
|
||||
//
|
||||
// Created by atdunbg on 2026/9/23.
|
||||
//
|
||||
// Cubemap:环境立方体贴图。
|
||||
// Cubemap:环境立方体贴图 + 漫反射辐照度图(IBL 阶段②)。
|
||||
//
|
||||
// 从等距柱状 HDR(.hdr,polyhaven 等)生成:CPU 重采样到 6 面
|
||||
//(一次性加载成本,亚秒级),转 fp16 后整块上传,硬件 Cube 采样。
|
||||
// 后续 IBL 的 irradiance/prefilter 卷积也基于本类的数据形态。
|
||||
// 同一次加载内完成 irradiance 卷积(半球积分,源数据在手零额外 IO)。
|
||||
//
|
||||
// 双图契约:
|
||||
// Get()/GetView() —— 环境 cube(Skybox 背景)
|
||||
// GetIrradianceView() —— 漫反射辐照度 cube(PBR ambient)
|
||||
// 镜面 IBL(pre-filter + BRDF LUT)后续接入,形态一致。
|
||||
//
|
||||
// 后续演进:CPU 卷积 → compute pass(动态环境零卡顿);本类的
|
||||
// 方向表/上传路径届时整体迁移,接口不变。
|
||||
//
|
||||
|
||||
#ifndef HELLOVULKAN_CUBEMAP_H
|
||||
@@ -13,6 +21,7 @@
|
||||
|
||||
#include <Engine/Core/Types.h>
|
||||
#include <Engine/Vulkan/MemoryAllocator.h>
|
||||
#include <glm/glm.hpp>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
namespace Engine {
|
||||
@@ -21,36 +30,55 @@ namespace Engine {
|
||||
|
||||
class Cubemap {
|
||||
public:
|
||||
// 从等距柱状 HDR 生成(CPU 重采样到 6 面,faceSize 为每面边长)
|
||||
// 从等距柱状 HDR 生成(CPU 重采样 6 面 + irradiance 卷积)
|
||||
static Scope<Cubemap> CreateFromHdrEquirect(Device& device,
|
||||
MemoryAllocator& allocator,
|
||||
const std::string& path,
|
||||
u32 faceSize);
|
||||
|
||||
// 中性兜底(无 HDR 资产时):env/irradiance 均为常数色。
|
||||
// 保证引用侧描述符恒有效(validation),渲染退化为常数环境
|
||||
static Scope<Cubemap> CreateNeutral(Device& device,
|
||||
MemoryAllocator& allocator,
|
||||
const glm::vec3& rgb);
|
||||
|
||||
~Cubemap();
|
||||
|
||||
Cubemap(const Cubemap&) = delete;
|
||||
Cubemap& operator=(const Cubemap&) = delete;
|
||||
|
||||
vk::Image Get() const { return m_Image; }
|
||||
vk::ImageView GetView() const { return m_View; }
|
||||
// ---- 环境 cube(Skybox 背景)----
|
||||
vk::Image Get() const { return m_EnvImage; }
|
||||
vk::ImageView GetView() const { return m_EnvView; }
|
||||
|
||||
// ---- 漫反射辐照度 cube(PBR ambient)----
|
||||
vk::ImageView GetIrradianceView() const { return m_IrrView; }
|
||||
|
||||
vk::Sampler GetSampler() const { return m_Sampler; }
|
||||
u32 GetFaceSize() const { return m_FaceSize; }
|
||||
|
||||
private:
|
||||
Cubemap(Device& device, MemoryAllocator& allocator,
|
||||
vk::Image image, vk::ImageView view, vk::Sampler sampler,
|
||||
MemoryAllocator::Allocation allocation, u32 faceSize)
|
||||
vk::Image envImage, vk::ImageView envView,
|
||||
vk::Image irrImage, vk::ImageView irrView, vk::Sampler sampler,
|
||||
MemoryAllocator::Allocation envAlloc,
|
||||
MemoryAllocator::Allocation irrAlloc, u32 faceSize)
|
||||
: m_Device(device), m_Allocator(allocator),
|
||||
m_Image(image), m_View(view), m_Sampler(sampler),
|
||||
m_Allocation(allocation), m_FaceSize(faceSize) {}
|
||||
m_EnvImage(envImage), m_EnvView(envView),
|
||||
m_IrrImage(irrImage), m_IrrView(irrView),
|
||||
m_Sampler(sampler), m_EnvAllocation(envAlloc),
|
||||
m_IrrAllocation(irrAlloc), m_FaceSize(faceSize) {}
|
||||
|
||||
Device& m_Device;
|
||||
MemoryAllocator& m_Allocator;
|
||||
vk::Image m_Image;
|
||||
vk::ImageView m_View;
|
||||
|
||||
vk::Image m_EnvImage;
|
||||
vk::ImageView m_EnvView;
|
||||
vk::Image m_IrrImage;
|
||||
vk::ImageView m_IrrView;
|
||||
vk::Sampler m_Sampler;
|
||||
MemoryAllocator::Allocation m_Allocation;
|
||||
MemoryAllocator::Allocation m_EnvAllocation;
|
||||
MemoryAllocator::Allocation m_IrrAllocation;
|
||||
u32 m_FaceSize;
|
||||
};
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace Engine {
|
||||
class DescriptorManager;
|
||||
class ShaderManager;
|
||||
class UniformBuffer;
|
||||
class Cubemap;
|
||||
|
||||
namespace Passes {
|
||||
|
||||
@@ -40,8 +41,8 @@ namespace Engine {
|
||||
|
||||
// ---- set 布局(shader 契约,改绑定必须同步 shaders/)----
|
||||
vk::DescriptorSetLayout uboSetLayout; // Set0 = {UBO, ObjectBuffer, PrevObjectBuffer}
|
||||
vk::DescriptorSetLayout textureSetLayout; // Set1 = {albedo}
|
||||
vk::DescriptorSetLayout shadowSetLayout; // Set2 = {级联 0/1/2 阴影图}
|
||||
vk::DescriptorSetLayout textureSetLayout; // Set1 = {材质 4 槽 + 参数 UBO}
|
||||
vk::DescriptorSetLayout shadowSetLayout; // Set2 = {级联 0/1/2 阴影图, irradiance cube}
|
||||
vk::PipelineLayout forwardLayout; // 3 sets,无 push(GPUDriven 经 SSBO)
|
||||
vk::PipelineLayout shadowLayout; // Set0,push = lightVP 64B
|
||||
|
||||
@@ -60,6 +61,9 @@ namespace Engine {
|
||||
void BindShadowMaps(RG::RenderGraph& rg,
|
||||
const std::array<RG::TextureHandle, kMaxCascades>& maps);
|
||||
|
||||
// 环境辐照度(Set2 binding 3):view 全程稳定,绑一次即可
|
||||
void BindEnvironment(const Cubemap& env);
|
||||
|
||||
private:
|
||||
Device& m_Device;
|
||||
DescriptorManager& m_Descriptors;
|
||||
|
||||
Reference in New Issue
Block a user