feat: 环境背景管线(IBL 阶段①)——HDR 等距柱状转 cube + Skybox pass
- Cubemap:stbi_loadf 加载 .hdr,CPU 双线性重采样 6 面(GL 规范方向表), f32→fp16 转换后整块上传 eCubeCompatible image(R16G16B16A16Sfloat) - SkyboxPass:HDRColor 的 first writer,承担清屏职责;无环境贴图自动 退化为纯清屏(Forward 不受影响) - frag 逐像素 NDC 反投影取世界方向(invVP push,投影变换不可线性插值) - Forward color 附件 Clear→Load:几何合成在天空之上 - SceneRenderer 产出 skyInvVP = inverse(proj × mat4(mat3(view)))
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
//
|
||||
// Created by atdunbg on 2026/9/23.
|
||||
//
|
||||
// Cubemap:环境立方体贴图。
|
||||
//
|
||||
// 从等距柱状 HDR(.hdr,polyhaven 等)生成:CPU 重采样到 6 面
|
||||
//(一次性加载成本,亚秒级),转 fp16 后整块上传,硬件 Cube 采样。
|
||||
// 后续 IBL 的 irradiance/prefilter 卷积也基于本类的数据形态。
|
||||
//
|
||||
|
||||
#ifndef HELLOVULKAN_CUBEMAP_H
|
||||
#define HELLOVULKAN_CUBEMAP_H
|
||||
|
||||
#include <Engine/Core/Types.h>
|
||||
#include <Engine/Vulkan/MemoryAllocator.h>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
namespace Engine {
|
||||
|
||||
class Device;
|
||||
|
||||
class Cubemap {
|
||||
public:
|
||||
// 从等距柱状 HDR 生成(CPU 重采样到 6 面,faceSize 为每面边长)
|
||||
static Scope<Cubemap> CreateFromHdrEquirect(Device& device,
|
||||
MemoryAllocator& allocator,
|
||||
const std::string& path,
|
||||
u32 faceSize);
|
||||
|
||||
~Cubemap();
|
||||
|
||||
Cubemap(const Cubemap&) = delete;
|
||||
Cubemap& operator=(const Cubemap&) = delete;
|
||||
|
||||
vk::Image Get() const { return m_Image; }
|
||||
vk::ImageView GetView() const { return m_View; }
|
||||
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)
|
||||
: m_Device(device), m_Allocator(allocator),
|
||||
m_Image(image), m_View(view), m_Sampler(sampler),
|
||||
m_Allocation(allocation), m_FaceSize(faceSize) {}
|
||||
|
||||
Device& m_Device;
|
||||
MemoryAllocator& m_Allocator;
|
||||
vk::Image m_Image;
|
||||
vk::ImageView m_View;
|
||||
vk::Sampler m_Sampler;
|
||||
MemoryAllocator::Allocation m_Allocation;
|
||||
u32 m_FaceSize;
|
||||
};
|
||||
|
||||
} // namespace Engine
|
||||
|
||||
#endif //HELLOVULKAN_CUBEMAP_H
|
||||
@@ -0,0 +1,61 @@
|
||||
//
|
||||
// Created by atdunbg on 2026/9/23.
|
||||
//
|
||||
// SkyboxPass:环境背景(IBL 阶段①)。
|
||||
//
|
||||
// HDRColor 的 first writer:承担清屏职责(loadOp Clear),有环境贴图时
|
||||
// 再画天空——Forward 随之改为 loadOp Load,几何在天空之上合成。
|
||||
// 职责收口对齐 UE:sky pass 是场景渲染的第一步,无深度附件,
|
||||
// 深度测试关(几何完全覆盖由 Forward 的深度决定)。
|
||||
//
|
||||
// 环境贴图生命周期:Renderer 持有 Cubemap(声明序先于 pass),
|
||||
// 本 pass 只引用。描述符绑定一次(cube view 全程稳定,不随 RG 重编译)。
|
||||
//
|
||||
|
||||
#ifndef HELLOVULKAN_SKYBOXPASS_H
|
||||
#define HELLOVULKAN_SKYBOXPASS_H
|
||||
|
||||
#include <Engine/Core/FrameContext.h>
|
||||
#include <Engine/Renderer/Passes/RenderPass.h>
|
||||
#include <Engine/Renderer/SceneTypes.h>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
namespace Engine {
|
||||
|
||||
class Device;
|
||||
class DescriptorManager;
|
||||
class ShaderManager;
|
||||
class Cubemap;
|
||||
|
||||
namespace Passes {
|
||||
|
||||
class SkyboxPass final : public RenderPass {
|
||||
public:
|
||||
// env 可为空(HDR 资产缺失):仅承担清屏,天空保持清屏色
|
||||
SkyboxPass(Device& device, ShaderManager& shaders,
|
||||
DescriptorManager& descriptors, FrameSceneData& frame,
|
||||
RG::TextureHandle hdrColor, const Cubemap* env);
|
||||
~SkyboxPass();
|
||||
|
||||
SkyboxPass(const SkyboxPass&) = delete;
|
||||
SkyboxPass& operator=(const SkyboxPass&) = delete;
|
||||
|
||||
void Register(RG::RenderGraph& rg) override;
|
||||
|
||||
private:
|
||||
Device& m_Device;
|
||||
DescriptorManager& m_Descriptors;
|
||||
FrameSceneData& m_Frame;
|
||||
RG::TextureHandle m_HDRColor;
|
||||
const Cubemap* m_Env; // 可空
|
||||
|
||||
vk::DescriptorSetLayout m_SetLayout; // Set0 = {samplerCube}
|
||||
vk::PipelineLayout m_Layout; // push = invVP 64B
|
||||
vk::ShaderEXT m_Vert{}, m_Frag{};
|
||||
std::array<vk::DescriptorSet, kMaxFramesInFlight> m_Sets{};
|
||||
};
|
||||
|
||||
} // namespace Passes
|
||||
} // namespace Engine
|
||||
|
||||
#endif //HELLOVULKAN_SKYBOXPASS_H
|
||||
@@ -41,6 +41,7 @@ namespace Engine {
|
||||
class UniformBuffer;
|
||||
class SceneRenderer;
|
||||
class VulkanAssetUploader;
|
||||
class Cubemap;
|
||||
class ImGuiLayer;
|
||||
|
||||
namespace ECS { class Scene; }
|
||||
@@ -113,6 +114,9 @@ namespace Engine {
|
||||
Scope<UniformBuffer> m_PrevObjectBuffer; // 上一帧实例矩阵 ring(TAA velocity)
|
||||
Scope<Passes::SceneGpu> m_SceneGpu; // 场景类 pass 共享装配
|
||||
Scope<Passes::FullscreenGpu> m_FullscreenGpu; // 全屏 pass 共享装配
|
||||
// 环境贴图(IBL 阶段①):HDR → cube,被 SkyboxPass 引用;
|
||||
// 声明在 m_Passes 之前 → 析构晚于 pass(引用安全)
|
||||
Scope<Cubemap> m_Environment;
|
||||
Scope<Swapchain> m_Swapchain;
|
||||
Scope<SyncManager> m_SyncManager;
|
||||
Scope<CommandManager> m_CommandManager;
|
||||
|
||||
@@ -68,6 +68,10 @@ namespace Engine {
|
||||
struct FrameSceneData {
|
||||
UniformBufferObject ubo{};
|
||||
|
||||
// 天空盒反投影矩阵:inverse(projNoJitter × mat4(mat3(view)))
|
||||
//(视图去平移只留旋转 → 反投影结果即世界方向;Skybox pass push)
|
||||
glm::mat4 skyInvVP{1.0f};
|
||||
|
||||
// 实例矩阵数组 = [主视图段 | 阴影视图段](共享同一 per-slot SSBO)
|
||||
std::vector<glm::mat4> instanceModels;
|
||||
// 上一帧世界矩阵,与 instanceModels 平行对齐(同一下标 = 同一
|
||||
|
||||
Reference in New Issue
Block a user