// // Created by atdunbg on 2026/9/23. // // SceneRenderer:场景 → 渲染数据的每帧翻译层(UE FSceneRenderer / // Unity CullingResults 的对应物)。 // // 职责(全部是"读场景、产数据",不碰 GPU、不碰 Vulkan): // 1. 相机/灯光/环境色 → UniformBufferObject 语义组装(含阴影光空间矩阵) // 2. 单趟实例收集 + 双视图剔除(相机视锥/光源视锥各自独立可见列表—— // 相机外实体仍可能投影子进视野,shadow popping 的教训) // Renderer 拿 FrameSceneData 写 buffer、驱动 pass;场景理解全部收口在此。 // // 扩展性: // - 多光源:lights 数组已就位(kMaxLights),每灯各自 lightSpace 即 CSM 前置 // - 级联阴影:BuildFrame 内按级联多出几份 lightSpace + shadowView, // pass 侧按索引消费,本类结构不变 // - 遮挡剔除/GPU 剔除:只改本类收集逻辑,下游无感知 // #ifndef HELLOVULKAN_SCENERENDERER_H #define HELLOVULKAN_SCENERENDERER_H #include #include #include #include namespace Engine { namespace ECS { class Scene; } namespace Assets { class AssetManager; } class SceneRenderer { public: // 从场景构建当帧渲染数据。无 primary 相机返回 false(渲染跳帧)。 // targetExtent 用于 TAA 子像素抖动的 NDC 偏移折算。 bool BuildFrame(ECS::Scene& scene, Assets::AssetManager& assets, vk::Extent2D targetExtent); FrameSceneData& Frame() { return m_Frame; } // ---- 遥测 ---- u32 GetMainInstanceCount() const { return m_Frame.mainView.instanceCount; } u32 GetShadowInstanceCount() const { u32 sum = 0; for (const auto& c : m_Frame.shadowCascades) sum += c.instanceCount; return sum; } f32 GetCollectMs() const { return m_Frame.collectMs; } private: // CSM:把相机视锥按实用分割切 N 段,每段独立拟合光源正交投影 //(含纹素对齐防阴影边缘闪烁)。写入(Shadow pass push)与采样 //(Forward UBO)共用同一组矩阵。 void ComputeCascades(const glm::vec3& shadowDir); FrameSceneData m_Frame; // ---- 剔除中间量(每帧 clear 复用,拼接进 m_Frame 后保留容量)---- struct ViewScratch { CullResult result; std::vector worlds; std::vector prevWorlds; std::unordered_map lookup; void Clear() { result.batches.clear(); result.instanceCount = 0; worlds.clear(); prevWorlds.clear(); lookup.clear(); } }; ViewScratch m_MainScratch; ViewScratch m_CascScratch[kMaxCascades]; // ---- TAA 时域状态 ---- u64 m_FrameIndex = 0; // 抖动序列游标(Halton 2,3 ×8 采样) glm::mat4 m_LastView{1.0f}; // 上一帧视图(velocity) glm::mat4 m_LastProjNoJitter{1.0f}; // 上一帧未抖动投影(velocity) // 实体的上一帧世界矩阵(key = entt 实体 integral)。 // 每帧重建 m_CurWorlds 后与 m_PrevWorlds swap——自动清理销毁实体 std::unordered_map m_PrevWorlds; std::unordered_map m_CurWorlds; bool m_TruncationWarned = false; // 实例缓冲打满只告警一次 }; } // namespace Engine #endif //HELLOVULKAN_SCENERENDERER_H