Files
HelloVulkan/Engine/include/Engine/Renderer/Renderer.h
T
atdunbg a1c6ad20be feat: 特性开关 + Pass 调试视图接口(ImGui 可控,统一帧契约)
三个运行时开关(Shadows/TAA/Bloom)与 9 种调试视图(Final/
TemporalDiff/HDR/TAAColor/Bloom/Velocity/ShadowMap0-2)。

统一设计:开关状态收敛 FrameSceneData 契约,SceneRenderer 唯一
写入、各 pass 只读(零虚接口路由);调试视图经 tonemap push
int 路由已绑定的中间目标(声明超集、运行时零重绑);HDR 域
资源过同一 tonemap 保证观感可比。

- Shadows:ShadowPass lambda 空转 + frag cascadeSplits.w 短路
- TAA:alpha=0 直通 + SceneRenderer 停投影抖动(同一持有者同步)
- Bloom:3 子 pass 空转 + tonemap 强度归零
- Renderer 门面 Get/Set 转发,App ImGui 3 Checkbox + Combo
- PostProcessParams 瘦身为纯数值参数,showTemporalDiff 被取缔
2026-09-24 13:03:00 +08:00

172 lines
7.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//
// Created by atdunbg on 2026/9/20.
//
// Renderer:渲染门面 + 渲染侧组合根。
//
// 分工(对照 UE/Unity 的渲染架构):
// Renderer —— 装配模块、声明 RG 资源、注册 pass 对象、
// 每帧编排(翻译场景 → 写 buffer → 驱动 RG → 提交呈现)。
// 不理解场景细节,不含 pass 实现。
// SceneRenderer —— 场景 → FrameSceneData 的翻译层(相机/灯光/剔除,
// 对应 UE FSceneRenderer / Unity CullingResults)。
// Passes::* —— 各 pass 的声明与录制(对应 Unity ScriptableRenderPass)。
// 新增效果 = 新增 pass 类 + BuildGraph 注册一行。
//
// 对外只暴露两个入口:Render(Scene&, Assets&) 和给 App 层调参的访问器。
//
#ifndef HELLOVULKAN_RENDERER_H
#define HELLOVULKAN_RENDERER_H
#pragma once
#include <Engine/Core/Types.h>
#include <Engine/Core/FrameContext.h>
#include <Engine/Renderer/SceneTypes.h>
#include <Engine/RenderGraph/RenderGraph.h>
#include <vulkan/vulkan.hpp>
#include <array>
#include <vector>
namespace Engine {
class Window;
class Device;
class MemoryAllocator;
class DescriptorManager;
class ShaderManager;
class Swapchain;
class SyncManager;
class CommandManager;
class UniformBuffer;
class SceneRenderer;
class VulkanAssetUploader;
class Cubemap;
class ImGuiLayer;
namespace ECS { class Scene; }
namespace Assets { class AssetManager; class IAssetUploader; }
namespace Passes { class RenderPass; class SceneGpu; class FullscreenGpu; class PostProcessParams; }
class Renderer {
public:
explicit Renderer(Window& window);
~Renderer();
Renderer(const Renderer&) = delete;
Renderer& operator=(const Renderer&) = delete;
void Render(ECS::Scene& scene, Assets::AssetManager& assets);
// ---- 组合根(Application)装配其他模块时需要的访问器 ----
Device& GetDevice() const { return *m_Device; }
MemoryAllocator& GetAllocator() const { return *m_Allocator; }
DescriptorManager& GetDescriptorManager() const { return *m_DescriptorManager; }
vk::DescriptorSetLayout GetTextureSetLayout() const; // 实现在 cpp(SceneGpu 成员)
vk::Format GetSwapchainFormat() const;
u32 GetSwapchainImageCount() const;
// 资产上传服务(渲染层对资产层提供的 IAssetUploader 实现)
Assets::IAssetUploader& GetAssetUploader() const;
// 可选叠加层(ImGui):不设置则 RG 里的 ImGui pass 为空转。
// 生命周期:层必须先于 Renderer 析构(Application 成员序保证)。
void SetImGuiLayer(ImGuiLayer* layer) { m_ImGuiLayer = layer; }
// ---- 后处理参数(ImGui 可调,转发到 pass 共享的 PostProcessParams)----
f32 GetExposure() const;
void SetExposure(f32 e);
bool GetUseACES() const;
void SetUseACES(bool b);
f32 GetBloomThreshold() const;
void SetBloomThreshold(f32 v);
f32 GetBloomStrength() const;
void SetBloomStrength(f32 v);
// ---- 特性开关 / 调试视图(转发到 SceneRenderer,每帧落
// FrameSceneData 契约,pass 只读;ImGui 直接对接)----
bool GetShadowsEnabled() const;
void SetShadowsEnabled(bool b);
bool GetTAAEnabled() const;
void SetTAAEnabled(bool b);
bool GetBloomEnabled() const;
void SetBloomEnabled(bool b);
int GetDebugView() const;
void SetDebugView(int v); // Passes::DebugView 枚举值
// 调试视图名表(下标 = DebugView 枚举值,ImGui combo 直接枚举)
const std::vector<const char*>& GetDebugViewNames() const;
// pass 级 GPU 耗时(最近完成帧,毫秒;与 GetPassGpuMs 下标对应)
const std::vector<std::string>& GetPassNames() const { return m_PassNames; }
const std::vector<f32>& GetPassGpuMs() const { return m_PassGpuMs; }
// 双视图剔除后的实例数(遥测)
u32 GetMainInstanceCount() const;
u32 GetShadowInstanceCount() const;
// 垂直同步开关(present mode 切换会重建 swapchain),
// 只应在帧 UI 构建段调用(Render 之前)
void SetVSync(bool vsync);
private:
void BuildGraph(); // 声明 RG 资源 + 注册 pass 对象
void HandleResize();
void ReadGpuTimes(u32 frameSlot);
Window& m_Window;
// ---- 底层模块(析构序:后声明者先析构;引用他人者先析构)----
Scope<Device> m_Device;
Scope<MemoryAllocator> m_Allocator;
Scope<DescriptorManager> m_DescriptorManager;
Scope<ShaderManager> m_ShaderManager;
Scope<UniformBuffer> m_UniformBuffer; // per-slot UBO ring
Scope<UniformBuffer> m_ObjectBuffer; // GPUDriven 实例矩阵 ring(SSBO)
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;
Scope<SceneRenderer> m_SceneRenderer; // 场景翻译层(先于 pass 构造)
Scope<RG::RenderGraph> m_RenderGraph;
Scope<VulkanAssetUploader> m_AssetUploader;
// pass 对象(注册序;执行序由 RG 拓扑排序决定)
std::vector<Scope<Passes::RenderPass>> m_Passes;
// ---- RenderGraph 资源句柄 ----
RG::TextureHandle m_Backbuffer{};
RG::TextureHandle m_Depth{};
std::array<RG::TextureHandle, kMaxCascades> m_ShadowMaps{}; // CSM 级联
RG::TextureHandle m_HDRColor{}; // Forward 输出(线性 HDR),TAA 归一
RG::TextureHandle m_Velocity{}; // Forward 输出(clip 空间运动向量)
RG::TextureHandle m_TAAColor{}; // TAA 累积输出(自引用历史),后处理源
RG::TextureHandle m_BloomA{}; // 半分辨率:提取 + 垂直模糊结果
RG::TextureHandle m_BloomB{}; // 半分辨率:水平模糊中间结果
RG::TextureHandle m_TemporalDiff{}; // 半分辨率:帧历史差异(调试)
// pass 共享的可调参数(Renderer 持有,App 层访问器转发)
Scope<Passes::PostProcessParams> m_PostParams;
// 可选叠加层(不拥有;Application 持有)
ImGuiLayer* m_ImGuiLayer = nullptr;
// GPU timestamp(pass 级耗时,ImGui 可读)
vk::QueryPool m_QueryPool;
u32 m_QueriesPerFrame = 0; // 每帧槽位的查询数 = pass 数 × 2
f32 m_TimestampPeriod = 1.0f; // ns/tick(设备属性缓存)
std::vector<std::string> m_PassNames; // 执行序 pass 名
std::vector<f32> m_PassGpuMs; // 最近一帧各 pass 耗时
bool m_TimesPrimed[2] = {false, false}; // 每槽位首帧跳过读取
vk::Extent2D m_Extent{};
u32 m_CurrentFrame = 0;
};
} // namespace Engine
#endif //HELLOVULKAN_RENDERER_H