diff --git a/docs/api/XCEngine/Rendering/CameraRenderer/CameraRenderer.md b/docs/api/XCEngine/Rendering/CameraRenderer/CameraRenderer.md new file mode 100644 index 00000000..7cd48430 --- /dev/null +++ b/docs/api/XCEngine/Rendering/CameraRenderer/CameraRenderer.md @@ -0,0 +1,109 @@ +# CameraRenderer + +**命名空间**: `XCEngine::Rendering` + +**类型**: `class` + +**头文件**: `XCEngine/Rendering/Execution/CameraRenderer.h` + +**描述**: 单个 `CameraRenderRequest` 的执行器,负责在一次提交里串起 scene extraction、shadow/depth 预 pass、主主管线、object-id,以及注入式 pre/post/overlay pass。 + +## 概述 + +`CameraRenderer` 是当前 Rendering 模块里的“单 request 执行层”。它不负责决定应该渲染哪些相机,也不负责 request 排序;这些职责在 [SceneRenderer](../SceneRenderer/SceneRenderer.md) 与 [SceneRenderRequestPlanner](../SceneRenderRequestPlanner/SceneRenderRequestPlanner.md)。 + +它关心的是另一件事:一份已经组装好的 `CameraRenderRequest`,到底按什么顺序跑完。 + +## 当前持有的运行时对象 + +- `m_sceneExtractor` + 使用 request surface 的 render-area 尺寸提取当前相机对应的 `RenderSceneData`。 +- `m_pipelineAsset` + 当前主管线的创建来源工厂;可能为空。 +- `m_pipeline` + 当前实际执行主场景绘制的 runtime [RenderPipeline](../RenderPipeline/RenderPipeline.md)。 +- `m_objectIdPass` + 按需消费 `request.objectId` 的 object-id pass;默认是 [Passes::BuiltinObjectIdPass](../Passes/BuiltinObjectIdPass/BuiltinObjectIdPass.md)。 +- `m_depthOnlyPass` + 按需消费 `request.depthOnly` 的独立 scene pass;默认是 [Passes::BuiltinDepthOnlyPass](../Passes/BuiltinDepthOnlyPass/BuiltinDepthOnlyPass.md)。 +- `m_shadowCasterPass` + 按需消费 `request.shadowCaster` 的独立 scene pass;默认是 [Passes::BuiltinShadowCasterPass](../Passes/BuiltinShadowCasterPass/BuiltinShadowCasterPass.md)。 + +这意味着 `CameraRenderer` 不替调用方生成 Scene View 的特殊效果,但会直接消费 request 上已经明确给出的 depth-only / shadow-caster / object-id / post / overlay 槽位。 + +## 当前执行顺序 + +对一份有效 request,当前 `Render()` 的主顺序是: + +1. 校验 request、自身主管线、render-area,以及 `shadowCaster / depthOnly / objectId` 请求前置条件。 +2. 用 `m_sceneExtractor.ExtractForCamera(...)` 生成 `RenderSceneData`。 +3. 用 request 覆盖 `sceneData.cameraData.clearFlags`,必要时再覆盖 `clearColor`。 +4. 执行 `preScenePasses`。 +5. 如请求了 shadow-caster,执行 `m_shadowCasterPass`。 +6. 如请求了 depth-only,执行 `m_depthOnlyPass`。 +7. 执行 `m_pipeline->Render(...)`。 +8. 如请求了 object-id,执行 `m_objectIdPass->Render(...)`。 +9. 执行 `postScenePasses`。 +10. 执行 `overlayPasses`。 +11. 按已初始化的 sequence 逆向 `Shutdown()`。 + +`tests/Rendering/unit/test_camera_scene_renderer.cpp` 已覆盖这条顺序,包括 shadow-caster / depth-only 位于主主管线之前这一点。 + +## 生命周期与回退策略 + +- 默认构造会使用静态共享的 [BuiltinForwardPipelineAsset](../Pipelines/BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md),并同时创建 builtin object-id / depth-only / shadow-caster pass。 +- `SetPipeline()` 走“手动注入 runtime pipeline”路径,并清空当前 `m_pipelineAsset`。 +- `SetPipelineAsset()` 走“由 asset 创建 runtime pipeline”路径;传空时会回退到默认 asset。 +- `ResetPipeline()` 会先 `Shutdown()` 旧主管线,再接管新实例;若新实例为空,则再次回退到默认 asset 并创建 builtin forward。 +- [SetObjectIdPass](SetObjectIdPass.md) 会先关闭旧 pass;传空时回退到 builtin object-id pass。 +- [SetDepthOnlyPass](SetDepthOnlyPass.md) 会先关闭旧 pass;传空时回退到 builtin depth-only pass。 +- [SetShadowCasterPass](SetShadowCasterPass.md) 会先关闭旧 pass;传空时回退到 builtin shadow-caster pass。 + +## 当前验证规则 + +`Render()` 当前会显式拒绝: + +- `request.IsValid()` 为假 +- 当前 `m_pipeline == nullptr` +- `request.surface` 的 render-area 宽或高为 `0` +- 请求了 shadow-caster,但 `request.shadowCaster.IsValid()` 为假 +- 请求了 depth-only,但 `request.depthOnly.IsValid()` 为假 +- 请求了 object-id,但 `request.objectId.IsValid()` 为假 + +## 当前实现边界 + +- 这里只执行单个 request;多相机排序、stack 顺序和 clear 规则在 `SceneRenderer` / `SceneRenderRequestPlanner` 层完成。 +- 这里只消费 request 上已经存在的 scene-pass 与 pass-sequence 槽位,不主动构建 editor 专用 overlay。 +- post / overlay 阶段仍然只是顺序执行的 `RenderPassSequence`,不是 render graph。 + +## 公开方法 + +| 方法 | 说明 | +|------|------| +| [Constructor](Constructor.md) | 构造 `CameraRenderer`,并决定主主管线与 builtin 独立 pass 的初始来源。 | +| [Destructor](Destructor.md) | 关闭当前主管线、object-id pass、depth-only pass 与 shadow-caster pass。 | +| [SetPipeline](SetPipeline.md) | 手动替换当前 runtime pipeline。 | +| [SetPipelineAsset](SetPipelineAsset.md) | 通过 `RenderPipelineAsset` 重建当前 runtime pipeline。 | +| [SetObjectIdPass](SetObjectIdPass.md) | 替换当前 object-id pass。 | +| [SetDepthOnlyPass](SetDepthOnlyPass.md) | 替换当前 depth-only scene pass。 | +| [SetShadowCasterPass](SetShadowCasterPass.md) | 替换当前 shadow-caster scene pass。 | +| [GetPipeline](GetPipeline.md) | 读取当前主管线的非拥有指针。 | +| [GetPipelineAsset](GetPipelineAsset.md) | 读取当前 pipeline asset 的非拥有指针。 | +| [GetObjectIdPass](GetObjectIdPass.md) | 读取当前 object-id pass 的非拥有指针。 | +| [GetDepthOnlyPass](GetDepthOnlyPass.md) | 读取当前 depth-only pass 的非拥有指针。 | +| [GetShadowCasterPass](GetShadowCasterPass.md) | 读取当前 shadow-caster pass 的非拥有指针。 | +| [Render](Render.md) | 执行一次完整的单相机提交。 | + +## 相关文档 + +- [Rendering](../Rendering.md) +- [SceneRenderer](../SceneRenderer/SceneRenderer.md) +- [CameraRenderRequest](../CameraRenderRequest/CameraRenderRequest.md) +- [RenderSceneExtractor](../RenderSceneExtractor/RenderSceneExtractor.md) +- [RenderPipeline](../RenderPipeline/RenderPipeline.md) +- [ObjectIdPass](../ObjectIdPass/ObjectIdPass.md) +- [BuiltinDepthOnlyPass](../Passes/BuiltinDepthOnlyPass/BuiltinDepthOnlyPass.md) +- [BuiltinShadowCasterPass](../Passes/BuiltinShadowCasterPass/BuiltinShadowCasterPass.md) +- [Camera Request Planning And Clear Rules](../../../_guides/Rendering/Camera-Request-Planning-And-Clear-Rules.md) +- [Scene Extraction And Builtin Forward Pipeline](../../../_guides/Rendering/Scene-Extraction-And-Builtin-Forward-Pipeline.md) + diff --git a/docs/api/XCEngine/Rendering/CameraRenderer/Constructor.md b/docs/api/XCEngine/Rendering/CameraRenderer/Constructor.md new file mode 100644 index 00000000..d1ac0e5f --- /dev/null +++ b/docs/api/XCEngine/Rendering/CameraRenderer/Constructor.md @@ -0,0 +1,73 @@ +# CameraRenderer::Constructor + +**命名空间**: `XCEngine::Rendering` + +**类型**: `constructor-overload group` + +**头文件**: `XCEngine/Rendering/Execution/CameraRenderer.h` + +## 签名 + +```cpp +CameraRenderer(); +explicit CameraRenderer(std::unique_ptr pipeline); +explicit CameraRenderer(std::shared_ptr pipelineAsset); +CameraRenderer( + std::unique_ptr pipeline, + std::unique_ptr objectIdPass, + std::unique_ptr depthOnlyPass = nullptr, + std::unique_ptr shadowCasterPass = nullptr); +``` + +## 行为说明 + +构造函数的核心职责是决定三件事: + +- 当前主管线实例从哪里来 +- 当前 object-id pass 是否使用默认 builtin 实现 +- 当前 depth-only / shadow-caster pass 是否使用默认 builtin 实现 + +## 当前构造路径 + +### 默认构造 + +- 通过内部静态 `CreateDefaultPipelineAsset()` 取得共享的默认 asset。 +- 默认 asset 是 [BuiltinForwardPipelineAsset](../Pipelines/BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md)。 +- 随后走 asset 构造路径生成 runtime pipeline。 + +### `std::unique_ptr` 重载 + +- 交由四参重载处理。 +- 如果未显式提供 object-id / depth-only / shadow-caster pass,会分别补: + - [Passes::BuiltinObjectIdPass](../Passes/BuiltinObjectIdPass/BuiltinObjectIdPass.md) + - [Passes::BuiltinDepthOnlyPass](../Passes/BuiltinDepthOnlyPass/BuiltinDepthOnlyPass.md) + - [Passes::BuiltinShadowCasterPass](../Passes/BuiltinShadowCasterPass/BuiltinShadowCasterPass.md) + +### `std::shared_ptr` 重载 + +- 先保存 asset。 +- 再调用 [SetPipelineAsset](SetPipelineAsset.md),立即由 asset 创建 runtime pipeline。 +- 默认同时创建 builtin object-id / depth-only / shadow-caster pass。 + +### 四参重载 + +- 若 `objectIdPass` 为空,自动回退到 builtin object-id pass。 +- 若 `depthOnlyPass` 为空,自动回退到 builtin depth-only pass。 +- 若 `shadowCasterPass` 为空,自动回退到 builtin shadow-caster pass。 +- 调用内部 `ResetPipeline(std::move(pipeline))`。 +- 如果传入 `pipeline` 为空,`ResetPipeline()` 会继续回退到默认 pipeline asset,并创建 builtin forward 主管线。 + +## 所有权 + +- `RenderPipeline`、`ObjectIdPass`、`depthOnlyPass` 和 `shadowCasterPass` 都由 `CameraRenderer` 以 `std::unique_ptr` 独占持有。 +- `RenderPipelineAsset` 以 `std::shared_ptr` 共享持有,只作为 runtime pipeline 的创建来源。 + +## 相关文档 + +- [CameraRenderer](CameraRenderer.md) +- [SetPipeline](SetPipeline.md) +- [SetPipelineAsset](SetPipelineAsset.md) +- [SetObjectIdPass](SetObjectIdPass.md) +- [SetDepthOnlyPass](SetDepthOnlyPass.md) +- [SetShadowCasterPass](SetShadowCasterPass.md) + diff --git a/docs/api/XCEngine/Rendering/CameraRenderer/Destructor.md b/docs/api/XCEngine/Rendering/CameraRenderer/Destructor.md new file mode 100644 index 00000000..c572bcba --- /dev/null +++ b/docs/api/XCEngine/Rendering/CameraRenderer/Destructor.md @@ -0,0 +1,47 @@ +# CameraRenderer::~CameraRenderer + +**命名空间**: `XCEngine::Rendering` + +**类型**: `destructor` + +**头文件**: `XCEngine/Rendering/Execution/CameraRenderer.h` + +## 签名 + +```cpp +~CameraRenderer(); +``` + +## 作用 + +在对象销毁前关闭当前持有的主管线、object-id pass、depth-only pass 和 shadow-caster pass。 + +## 当前实现行为 + +析构函数当前按以下顺序执行清理: + +1. 如果 `m_pipeline` 非空,调用 `m_pipeline->Shutdown()`。 +2. 如果 `m_objectIdPass` 非空,调用 `m_objectIdPass->Shutdown()`。 +3. 如果 `m_depthOnlyPass` 非空,调用 `m_depthOnlyPass->Shutdown()`。 +4. 如果 `m_shadowCasterPass` 非空,调用 `m_shadowCasterPass->Shutdown()`。 + +随后由 `unique_ptr` 和成员对象自身析构负责释放内存。 + +## 设计含义 + +- 主管线、object-id pass、depth-only pass 和 shadow-caster pass 的 GPU 资源回收路径都是显式 `Shutdown()`,而不是只依赖 C++ 析构。 +- 调用方注入到 `CameraRenderRequest` 里的 `RenderPassSequence` 并不由这里持有,因此也不在这里做统一回收。 + +## 注意事项 + +- 当前没有内部同步;不应在其它线程仍可能访问这些对象时销毁 `CameraRenderer`。 +- 如果你只是想切换主管线或这些独立 pass,不要等到析构,应该优先使用 [SetPipeline](SetPipeline.md)、[SetPipelineAsset](SetPipelineAsset.md)、[SetObjectIdPass](SetObjectIdPass.md)、[SetDepthOnlyPass](SetDepthOnlyPass.md) 或 [SetShadowCasterPass](SetShadowCasterPass.md)。 + +## 相关文档 + +- [CameraRenderer](CameraRenderer.md) +- [SetPipeline](SetPipeline.md) +- [SetObjectIdPass](SetObjectIdPass.md) +- [SetDepthOnlyPass](SetDepthOnlyPass.md) +- [SetShadowCasterPass](SetShadowCasterPass.md) + diff --git a/docs/api/XCEngine/Rendering/CameraRenderer/GetDepthOnlyPass.md b/docs/api/XCEngine/Rendering/CameraRenderer/GetDepthOnlyPass.md new file mode 100644 index 00000000..e8daf36c --- /dev/null +++ b/docs/api/XCEngine/Rendering/CameraRenderer/GetDepthOnlyPass.md @@ -0,0 +1,33 @@ +# CameraRenderer::GetDepthOnlyPass + +**命名空间**: `XCEngine::Rendering` + +**类型**: `method` + +**头文件**: `XCEngine/Rendering/Execution/CameraRenderer.h` + +## 签名 + +```cpp +RenderPass* GetDepthOnlyPass() const; +``` + +## 作用 + +返回当前 depth-only scene pass 的裸指针。 + +## 当前实现行为 + +- 这是头文件内联访问器,直接返回 `m_depthOnlyPass.get()`。 +- 不转移所有权。 + +## 注意事项 + +- 调用 [SetDepthOnlyPass](SetDepthOnlyPass.md) 之后,之前读取到的裸指针可能立刻失效。 +- 当前默认返回的通常是 builtin depth-only pass,但调用方不应把这个 API 当成“只会返回某个具体类型”的承诺。 + +## 相关文档 + +- [SetDepthOnlyPass](SetDepthOnlyPass.md) +- [Render](Render.md) + diff --git a/docs/api/XCEngine/Rendering/CameraRenderer/GetObjectIdPass.md b/docs/api/XCEngine/Rendering/CameraRenderer/GetObjectIdPass.md new file mode 100644 index 00000000..cfe93c41 --- /dev/null +++ b/docs/api/XCEngine/Rendering/CameraRenderer/GetObjectIdPass.md @@ -0,0 +1,32 @@ +# CameraRenderer::GetObjectIdPass + +**命名空间**: `XCEngine::Rendering` + +**类型**: `method` + +**头文件**: `XCEngine/Rendering/Execution/CameraRenderer.h` + +## 签名 + +```cpp +ObjectIdPass* GetObjectIdPass() const; +``` + +## 作用 + +返回当前 object-id pass 的裸指针。 + +## 当前实现行为 + +- 这是头文件内联访问器,直接返回 `m_objectIdPass.get()`。 +- 不转移所有权。 + +## 注意事项 + +- 调用 [SetObjectIdPass](SetObjectIdPass.md) 后,之前读取到的裸指针可能立即失效。 + +## 相关文档 + +- [SetObjectIdPass](SetObjectIdPass.md) +- [Render](Render.md) + diff --git a/docs/api/XCEngine/Rendering/CameraRenderer/GetPipeline.md b/docs/api/XCEngine/Rendering/CameraRenderer/GetPipeline.md new file mode 100644 index 00000000..5628bad1 --- /dev/null +++ b/docs/api/XCEngine/Rendering/CameraRenderer/GetPipeline.md @@ -0,0 +1,38 @@ +# CameraRenderer::GetPipeline + +**命名空间**: `XCEngine::Rendering` + +**类型**: `method` + +**头文件**: `XCEngine/Rendering/Execution/CameraRenderer.h` + +## 签名 + +```cpp +RenderPipeline* GetPipeline() const; +``` + +## 作用 + +返回当前主管线实例的裸指针。 + +## 当前实现行为 + +- 这是头文件内联访问器,直接返回 `m_pipeline.get()`。 +- 不转移所有权,也不提供额外生命周期保证。 + +## 返回值 + +- 正常路径下通常会返回一个有效指针,因为构造和 `SetPipeline()` / `SetPipelineAsset()` 都会回退到默认管线。 +- 理论上如果对象正处于构造中的异常路径或未来实现改变,也不能把“永不为空”当成稳定契约。 + +## 注意事项 + +- 不要长期缓存这个裸指针;调用 [SetPipeline](SetPipeline.md) 或 [SetPipelineAsset](SetPipelineAsset.md) 后它可能立即失效。 + +## 相关文档 + +- [SetPipeline](SetPipeline.md) +- [SetPipelineAsset](SetPipelineAsset.md) +- [GetPipelineAsset](GetPipelineAsset.md) + diff --git a/docs/api/XCEngine/Rendering/CameraRenderer/GetPipelineAsset.md b/docs/api/XCEngine/Rendering/CameraRenderer/GetPipelineAsset.md new file mode 100644 index 00000000..bcd9e910 --- /dev/null +++ b/docs/api/XCEngine/Rendering/CameraRenderer/GetPipelineAsset.md @@ -0,0 +1,33 @@ +# CameraRenderer::GetPipelineAsset + +**命名空间**: `XCEngine::Rendering` + +**类型**: `method` + +**头文件**: `XCEngine/Rendering/Execution/CameraRenderer.h` + +## 签名 + +```cpp +const RenderPipelineAsset* GetPipelineAsset() const; +``` + +## 作用 + +返回当前绑定的 pipeline asset 裸指针。 + +## 当前实现行为 + +- 这是头文件内联访问器,直接返回 `m_pipelineAsset.get()`。 +- 如果最近一次切换是通过 [SetPipeline](SetPipeline.md) 手动注入实例完成的,这里可能返回 `nullptr`。 + +## 返回值 + +- 返回当前 asset 裸指针,或空指针。 + +## 相关文档 + +- [SetPipelineAsset](SetPipelineAsset.md) +- [SetPipeline](SetPipeline.md) +- [GetPipeline](GetPipeline.md) + diff --git a/docs/api/XCEngine/Rendering/CameraRenderer/GetShadowCasterPass.md b/docs/api/XCEngine/Rendering/CameraRenderer/GetShadowCasterPass.md new file mode 100644 index 00000000..5ed946e9 --- /dev/null +++ b/docs/api/XCEngine/Rendering/CameraRenderer/GetShadowCasterPass.md @@ -0,0 +1,33 @@ +# CameraRenderer::GetShadowCasterPass + +**命名空间**: `XCEngine::Rendering` + +**类型**: `method` + +**头文件**: `XCEngine/Rendering/Execution/CameraRenderer.h` + +## 签名 + +```cpp +RenderPass* GetShadowCasterPass() const; +``` + +## 作用 + +返回当前 shadow-caster scene pass 的裸指针。 + +## 当前实现行为 + +- 这是头文件内联访问器,直接返回 `m_shadowCasterPass.get()`。 +- 不转移所有权。 + +## 注意事项 + +- 调用 [SetShadowCasterPass](SetShadowCasterPass.md) 之后,之前读取到的裸指针可能立刻失效。 +- 当前默认返回的通常是 builtin shadow-caster pass,但调用方不应假定返回值一定来自某个具体实现类。 + +## 相关文档 + +- [SetShadowCasterPass](SetShadowCasterPass.md) +- [Render](Render.md) + diff --git a/docs/api/XCEngine/Rendering/CameraRenderer/Render.md b/docs/api/XCEngine/Rendering/CameraRenderer/Render.md new file mode 100644 index 00000000..39119d12 --- /dev/null +++ b/docs/api/XCEngine/Rendering/CameraRenderer/Render.md @@ -0,0 +1,83 @@ +# CameraRenderer::Render + +**命名空间**: `XCEngine::Rendering` + +**类型**: `method` + +**头文件**: `XCEngine/Rendering/Execution/CameraRenderer.h` + +## 签名 + +```cpp +bool Render(const CameraRenderRequest& request); +``` + +## 行为说明 + +执行一次完整的单相机提交。当前实现会把 shadow-caster、depth-only、主场景、object-id,以及调用方注入的 pre / post / overlay pass 串成一条固定顺序的执行链。 + +## 当前流程 + +1. 校验 `request.IsValid()`,并确认 `m_pipeline` 非空。 +2. 拒绝 render-area 宽或高为 `0` 的 `surface`。 +3. 如果请求了 shadow-caster,要让 `request.shadowCaster.IsValid()` 为真。 +4. 如果请求了 depth-only,要让 `request.depthOnly.IsValid()` 为真。 +5. 如果请求了 object-id,要让 `request.objectId.IsValid()` 为真。 +6. 用 `request.surface.GetRenderAreaWidth()` / `GetRenderAreaHeight()` 调用 `m_sceneExtractor.ExtractForCamera(...)`。 +7. 若 `sceneData.HasCamera()` 为假,则返回 `false`。 +8. 用 request 覆盖 `sceneData.cameraData.clearFlags`;如果 request 提供了 clear-color override,则继续覆盖 `sceneData.cameraData.clearColor`。 +9. 依次初始化并执行: + - `preScenePasses` + - `m_shadowCasterPass->Execute(...)` + - `m_depthOnlyPass->Execute(...)` + - `m_pipeline->Render(...)` + - `m_objectIdPass->Render(...)` + - `postScenePasses` + - `overlayPasses` +10. 按已经成功初始化的 sequence 做逆向 `Shutdown()`。 + +## `postScenePasses` / `overlayPasses` 接入点 + +`CameraRenderer` 只消费调用方传入的 pass 序列,不额外构建内部后处理层。 + +- `postScenePasses` 直接来自调用方提供的 `RenderPassSequence` +- `overlayPasses` 也是同样的注入点 +- 编辑器 Scene View 当前会先通过 [SceneViewportRenderPlan](../../Editor/Viewport/SceneViewportRenderPlan/SceneViewportRenderPlan.md) 组装这些序列,再调用 `ApplySceneViewportRenderPlan(...)` 挂到 request + +这意味着 Scene View 的无限网格、选中轮廓和编辑器 overlay,已经被上移到 request 组装层,不再由 `CameraRenderer` 内部再做一次翻译。与之相对,`shadowCaster` 和 `depthOnly` 当前仍属于 `CameraRenderRequest` 上的专用 scene-pass 槽位,由 `CameraRenderer` 直接在主主管线之前消费。 + +## 失败与清理语义 + +- 任一验证失败会直接返回 `false`。 +- `shadowCaster` 或 `depthOnly` 请求校验失败时,不会进入主主管线。 +- 任一 sequence 初始化失败会立刻执行对应 `Shutdown()` 回滚。 +- `shadowCaster`、`depthOnly`、主管线、object-id pass、post 或 overlay 任一阶段失败,都会按已经初始化过的 sequence 做清理再返回 `false`。 + +## 参数 + +- `request` - 本次单相机渲染的完整输入。 + +## 返回值 + +- 整条提交流成功执行时返回 `true`。 +- request 校验失败、场景提取失败、主管线失败,或任一附加阶段失败时返回 `false`。 + +## 测试覆盖 + +`tests/Rendering/unit/test_camera_scene_renderer.cpp` 当前验证了: + +- render-area 会影响提取到的相机 viewport 尺寸 +- clear-flags 和 clear-color override 会写回 `sceneData.cameraData` +- `shadowCaster / depthOnly / pipeline / object-id / post / overlay` 的执行顺序 +- shadow-caster 请求无效、object-id 失败和 post-pass 初始化失败时的回滚路径 + +## 相关文档 + +- [CameraRenderer](CameraRenderer.md) +- [CameraRenderRequest](../CameraRenderRequest/CameraRenderRequest.md) +- [RenderSceneExtractor](../RenderSceneExtractor/RenderSceneExtractor.md) +- [RenderPipeline::Render](../RenderPipeline/Render.md) +- [SetDepthOnlyPass](SetDepthOnlyPass.md) +- [SetShadowCasterPass](SetShadowCasterPass.md) +- [Passes](../Passes/Passes.md) + diff --git a/docs/api/XCEngine/Rendering/CameraRenderer/SetDepthOnlyPass.md b/docs/api/XCEngine/Rendering/CameraRenderer/SetDepthOnlyPass.md new file mode 100644 index 00000000..5f22f2b1 --- /dev/null +++ b/docs/api/XCEngine/Rendering/CameraRenderer/SetDepthOnlyPass.md @@ -0,0 +1,36 @@ +# CameraRenderer::SetDepthOnlyPass + +**命名空间**: `XCEngine::Rendering` + +**类型**: `method` + +**头文件**: `XCEngine/Rendering/Execution/CameraRenderer.h` + +## 签名 + +```cpp +void SetDepthOnlyPass(std::unique_ptr depthOnlyPass); +``` + +## 作用 + +替换当前用于消费 `request.depthOnly` 的独立 scene pass。 + +## 当前实现行为 + +1. 如果旧 `m_depthOnlyPass` 非空,先调用它的 `Shutdown()`。 +2. 接管新的 `depthOnlyPass`。 +3. 如果新指针为空,则自动回退到 [Passes::BuiltinDepthOnlyPass](../Passes/BuiltinDepthOnlyPass/BuiltinDepthOnlyPass.md)。 + +## 关键语义 + +- 这里替换的是一个普通 `RenderPass`,并不要求具体类型必须来自 builtin pass 层。 +- `CameraRenderer::Render()` 只在 `request.depthOnly.IsRequested()` 时才会真正执行这里持有的 pass。 +- `tests/Rendering/unit/test_camera_scene_renderer.cpp` 通过 mock pass 验证了这条注入链会在主主管线之前执行,并正确消费 `ScenePassRenderRequest` 的 surface / clear-color override。 + +## 相关文档 + +- [GetDepthOnlyPass](GetDepthOnlyPass.md) +- [Render](Render.md) +- [BuiltinDepthOnlyPass](../Passes/BuiltinDepthOnlyPass/BuiltinDepthOnlyPass.md) + diff --git a/docs/api/XCEngine/Rendering/CameraRenderer/SetObjectIdPass.md b/docs/api/XCEngine/Rendering/CameraRenderer/SetObjectIdPass.md new file mode 100644 index 00000000..1ca5ddb7 --- /dev/null +++ b/docs/api/XCEngine/Rendering/CameraRenderer/SetObjectIdPass.md @@ -0,0 +1,35 @@ +# CameraRenderer::SetObjectIdPass + +**命名空间**: `XCEngine::Rendering` + +**类型**: `method` + +**头文件**: `XCEngine/Rendering/Execution/CameraRenderer.h` + +## 签名 + +```cpp +void SetObjectIdPass(std::unique_ptr objectIdPass); +``` + +## 作用 + +替换主场景之后使用的 object-id 输出 pass。 + +## 当前实现行为 + +1. 如果旧 `m_objectIdPass` 非空,先调用它的 `Shutdown()`。 +2. 接管新的 `objectIdPass`。 +3. 如果新指针为空,则自动回退到 `Passes::BuiltinObjectIdPass`。 + +## 关键语义 + +- 这是 object-id 渲染链路的主要注入点,测试里可以通过它替换 mock pass。 +- `CameraRenderer::Render()` 只在 `request.objectId.IsRequested()` 时才会真正调用这里持有的 pass。 + +## 相关文档 + +- [GetObjectIdPass](GetObjectIdPass.md) +- [Render](Render.md) +- [Passes](../Passes/Passes.md) + diff --git a/docs/api/XCEngine/Rendering/CameraRenderer/SetPipeline.md b/docs/api/XCEngine/Rendering/CameraRenderer/SetPipeline.md new file mode 100644 index 00000000..a58da904 --- /dev/null +++ b/docs/api/XCEngine/Rendering/CameraRenderer/SetPipeline.md @@ -0,0 +1,44 @@ +# CameraRenderer::SetPipeline + +**命名空间**: `XCEngine::Rendering` + +**类型**: `method` + +**头文件**: `XCEngine/Rendering/Execution/CameraRenderer.h` + +## 签名 + +```cpp +void SetPipeline(std::unique_ptr pipeline); +``` + +## 作用 + +手动替换当前主管线实例,并切断与 `RenderPipelineAsset` 的绑定关系。 + +## 当前实现行为 + +1. 先把 `m_pipelineAsset.reset()`,表示后续不再认为当前管线来自某个 asset。 +2. 调用内部 `ResetPipeline(std::move(pipeline))`。 +3. `ResetPipeline()` 会: + - 对旧 `m_pipeline` 调用 `Shutdown()` + - 接管新的 `pipeline` + - 如果新指针为空,则回退到默认 pipeline asset 创建的内建前向管线 + +## 参数 + +| 参数 | 说明 | +|------|------| +| `pipeline` | 新的主管线实例所有权。可以为空;为空时会自动回退到默认内建前向管线。 | + +## 关键语义 + +- 这是“直接注入实例”的入口,不会保留原来的 pipeline asset。 +- 替换时走的是显式关停旧管线的路径,而不是简单换指针。 + +## 相关文档 + +- [SetPipelineAsset](SetPipelineAsset.md) +- [GetPipeline](GetPipeline.md) +- [GetPipelineAsset](GetPipelineAsset.md) + diff --git a/docs/api/XCEngine/Rendering/CameraRenderer/SetPipelineAsset.md b/docs/api/XCEngine/Rendering/CameraRenderer/SetPipelineAsset.md new file mode 100644 index 00000000..36e0297f --- /dev/null +++ b/docs/api/XCEngine/Rendering/CameraRenderer/SetPipelineAsset.md @@ -0,0 +1,36 @@ +# CameraRenderer::SetPipelineAsset + +**命名空间**: `XCEngine::Rendering` + +**类型**: `method` + +**头文件**: `XCEngine/Rendering/Execution/CameraRenderer.h` + +## 签名 + +```cpp +void SetPipelineAsset(std::shared_ptr pipelineAsset); +``` + +## 作用 + +通过一份 `RenderPipelineAsset` 重建当前主管线实例。 + +## 当前实现行为 + +1. 如果传入的 `pipelineAsset` 非空,则保存它。 +2. 如果传入为空,则回退到内部静态默认 asset。 +3. 调用 `CreatePipelineFromAsset(m_pipelineAsset)` 创建新的管线实例。 +4. 再通过 `ResetPipeline(...)` 关停旧管线并接管新实例。 + +## 关键语义 + +- 这是“从 asset 创建实例”的入口,和 [SetPipeline](SetPipeline.md) 的手动注入路径不同。 +- 即使 asset 无法返回有效实例,`CreatePipelineFromAsset()` 也会继续回退到内建前向管线。 + +## 相关文档 + +- [SetPipeline](SetPipeline.md) +- [GetPipelineAsset](GetPipelineAsset.md) +- [Constructor](Constructor.md) + diff --git a/docs/api/XCEngine/Rendering/CameraRenderer/SetShadowCasterPass.md b/docs/api/XCEngine/Rendering/CameraRenderer/SetShadowCasterPass.md new file mode 100644 index 00000000..234c74a4 --- /dev/null +++ b/docs/api/XCEngine/Rendering/CameraRenderer/SetShadowCasterPass.md @@ -0,0 +1,36 @@ +# CameraRenderer::SetShadowCasterPass + +**命名空间**: `XCEngine::Rendering` + +**类型**: `method` + +**头文件**: `XCEngine/Rendering/Execution/CameraRenderer.h` + +## 签名 + +```cpp +void SetShadowCasterPass(std::unique_ptr shadowCasterPass); +``` + +## 作用 + +替换当前用于消费 `request.shadowCaster` 的独立 scene pass。 + +## 当前实现行为 + +1. 如果旧 `m_shadowCasterPass` 非空,先调用它的 `Shutdown()`。 +2. 接管新的 `shadowCasterPass`。 +3. 如果新指针为空,则自动回退到 [Passes::BuiltinShadowCasterPass](../Passes/BuiltinShadowCasterPass/BuiltinShadowCasterPass.md)。 + +## 关键语义 + +- 这里替换的是一个普通 `RenderPass`,并不要求必须是 builtin shadow-caster 实现。 +- `CameraRenderer::Render()` 只在 `request.shadowCaster.IsRequested()` 时才会执行这里持有的 pass。 +- 当前执行顺序里,shadow-caster pass 位于 depth-only 与主主管线之前。 + +## 相关文档 + +- [GetShadowCasterPass](GetShadowCasterPass.md) +- [Render](Render.md) +- [BuiltinShadowCasterPass](../Passes/BuiltinShadowCasterPass/BuiltinShadowCasterPass.md) + diff --git a/docs/api/XCEngine/Rendering/SceneRenderer/BuildRenderRequests.md b/docs/api/XCEngine/Rendering/SceneRenderer/BuildRenderRequests.md new file mode 100644 index 00000000..823b3fde --- /dev/null +++ b/docs/api/XCEngine/Rendering/SceneRenderer/BuildRenderRequests.md @@ -0,0 +1,45 @@ +# SceneRenderer::BuildRenderRequests + +```cpp +std::vector BuildRenderRequests( + const Components::Scene& scene, + Components::CameraComponent* overrideCamera, + const RenderContext& context, + const RenderSurface& surface) const; +``` + +## 行为说明 + +当前实现直接委托给内部 `SceneRenderRequestPlanner`: + +```cpp +return m_requestPlanner.BuildRequests(scene, overrideCamera, context, surface); +``` + +## 当前用途 + +这个方法只负责“规划请求”,不负责真正渲染。生成的每个 `CameraRenderRequest` 会携带: + +- 选中的相机 +- 相机深度和 stack 顺序 +- 针对该相机解析后的 clear-flags +- 继承并裁剪后的 `RenderSurface` +- 随后交给 `CameraRenderer` 执行所需的上下文 + +## 参数 + +- `scene` - 要规划的场景。 +- `overrideCamera` - 可选的 override 相机;可用时只为它构建请求。 +- `context` - 当前渲染上下文。 +- `surface` - 当前输出目标模板,planner 会基于它推导每个相机的 render-area 和 clear 行为。 + +## 返回值 + +- 按 `SceneRenderRequestPlanner` 规则生成的请求数组。 + +## 相关文档 + +- [SceneRenderer](SceneRenderer.md) +- [Render](Render.md) +- [SceneRenderRequestPlanner](../SceneRenderRequestPlanner/SceneRenderRequestPlanner.md) +- [CameraRenderRequest](../CameraRenderRequest/CameraRenderRequest.md) diff --git a/docs/api/XCEngine/Rendering/SceneRenderer/Constructor.md b/docs/api/XCEngine/Rendering/SceneRenderer/Constructor.md new file mode 100644 index 00000000..10538ae2 --- /dev/null +++ b/docs/api/XCEngine/Rendering/SceneRenderer/Constructor.md @@ -0,0 +1,33 @@ +# SceneRenderer::SceneRenderer + +构造一个场景级渲染器。 + +```cpp +SceneRenderer(); +explicit SceneRenderer(std::unique_ptr pipeline); +explicit SceneRenderer(std::shared_ptr pipelineAsset); +``` + +## 当前语义 + +- 三个构造路径的差别只在于内部 `m_cameraRenderer` 如何初始化。 +- 默认构造:使用 `CameraRenderer` 的默认构造路径,最终回退到默认 builtin forward pipeline asset。 +- `std::unique_ptr` 构造:把调用方提供的 runtime pipeline 直接交给内部 `CameraRenderer` 持有。 +- `std::shared_ptr` 构造:让内部 `CameraRenderer` 通过 asset 创建 runtime pipeline。 + +## 当前实现细节 + +- `SceneRenderer` 自己不在构造阶段创建额外的 GPU 资源;真正的 runtime pipeline 创建和回退逻辑都委托给 `CameraRenderer`。 +- 如果传入的 `pipeline` 是空指针,`CameraRenderer` 会回退到默认 pipeline asset,而不是保留一个永久空 pipeline。 +- 如果传入的 `pipelineAsset` 是空指针,也会回退到默认 builtin forward asset。 + +## 测试覆盖 + +- `tests/Rendering/unit/test_camera_scene_renderer.cpp` 验证了默认构造的 `SceneRenderer` 能创建默认 pipeline 并完成渲染。 +- 同一测试文件也覆盖了注入 runtime pipeline 和注入 pipeline asset 两条构造路径。 + +## 相关文档 + +- [SceneRenderer](SceneRenderer.md) +- [SetPipeline](SetPipeline.md) +- [SetPipelineAsset](SetPipelineAsset.md) diff --git a/docs/api/XCEngine/Rendering/SceneRenderer/Destructor.md b/docs/api/XCEngine/Rendering/SceneRenderer/Destructor.md new file mode 100644 index 00000000..b811dd84 --- /dev/null +++ b/docs/api/XCEngine/Rendering/SceneRenderer/Destructor.md @@ -0,0 +1,30 @@ +# SceneRenderer::~SceneRenderer + +销毁场景级渲染器对象。 + +```cpp +~SceneRenderer() = default; +``` + +## 当前语义 + +- `SceneRenderer` 自身没有自定义析构逻辑。 +- 真正的 teardown 发生在成员对象析构阶段: + - `m_cameraRenderer` 会关闭当前 runtime pipeline 和 object-id pass。 + - `m_requestPlanner` 作为普通值成员按常规方式销毁。 +- `SceneRenderer` 不拥有外部传入请求上的 `RenderPassSequence`,因此析构时不会回收这些外部序列对象。 + +## 调用方影响 + +- 即使 `SceneRenderer` 的析构函数是 `= default`,离开作用域时仍会触发内部 `CameraRenderer` 的资源释放路径。 +- 任何此前通过 [GetPipeline](GetPipeline.md) 或 [GetPipelineAsset](GetPipelineAsset.md) 观察到的非拥有指针,都会在 `SceneRenderer` 销毁后失效。 + +## 测试覆盖 + +- `tests/Rendering/unit/test_camera_scene_renderer.cpp` 使用作用域退出断言了 `SceneRenderer` 内部持有的 pipeline 会在对象销毁时执行 `Shutdown()`。 + +## 相关文档 + +- [SceneRenderer](SceneRenderer.md) +- [GetPipeline](GetPipeline.md) +- [Render](Render.md) diff --git a/docs/api/XCEngine/Rendering/SceneRenderer/GetPipeline.md b/docs/api/XCEngine/Rendering/SceneRenderer/GetPipeline.md new file mode 100644 index 00000000..0d0fd8c8 --- /dev/null +++ b/docs/api/XCEngine/Rendering/SceneRenderer/GetPipeline.md @@ -0,0 +1,35 @@ +# SceneRenderer::GetPipeline + +返回当前场景渲染器正在使用的 runtime pipeline。 + +```cpp +RenderPipeline* GetPipeline() const; +``` + +## 返回值 + +- 返回内部 `m_cameraRenderer.GetPipeline()` 的结果。 + +## 当前语义 + +- 这是一个非拥有裸指针,只用于观察当前绑定的是哪一个 `RenderPipeline` 实例。 +- 该指针可能指向: + - 手动注入的 runtime pipeline。 + - 由当前 pipeline asset 创建出的 runtime pipeline。 + - 在空指针回退路径中自动补出的默认 builtin forward pipeline。 +- 调用 [SetPipeline](SetPipeline.md) 或 [SetPipelineAsset](SetPipelineAsset.md) 后,这个指针都可能变化。 + +## 调用方影响 + +- 不应跨生命周期长期缓存这个指针;`SceneRenderer` 销毁、替换 pipeline 或回退默认 pipeline 后,它都可能失效。 +- 它也不是“可由外部 delete 的所有权句柄”;真正的持有者仍是内部 `CameraRenderer`。 + +## 测试覆盖 + +- `tests/Rendering/unit/test_camera_scene_renderer.cpp` 覆盖了替换 pipeline 前后 `GetPipeline()` 返回值的变化,以及旧 pipeline 被 `Shutdown()` 的行为。 + +## 相关文档 + +- [SceneRenderer](SceneRenderer.md) +- [SetPipeline](SetPipeline.md) +- [GetPipelineAsset](GetPipelineAsset.md) diff --git a/docs/api/XCEngine/Rendering/SceneRenderer/GetPipelineAsset.md b/docs/api/XCEngine/Rendering/SceneRenderer/GetPipelineAsset.md new file mode 100644 index 00000000..140ab654 --- /dev/null +++ b/docs/api/XCEngine/Rendering/SceneRenderer/GetPipelineAsset.md @@ -0,0 +1,33 @@ +# SceneRenderer::GetPipelineAsset + +返回当前场景渲染器绑定的 pipeline asset。 + +```cpp +const RenderPipelineAsset* GetPipelineAsset() const; +``` + +## 返回值 + +- 返回内部 `m_cameraRenderer.GetPipelineAsset()` 的结果。 + +## 当前语义 + +- 这是一个非拥有观察指针,用来回答“当前 runtime pipeline 是由哪个 asset 工厂派生出来的”。 +- 默认构造的 `SceneRenderer` 通常会返回默认 builtin forward pipeline asset。 +- 如果最近一次切换是 [SetPipeline](SetPipeline.md) 且传入了非空 runtime pipeline,这里会变成 `nullptr`,因为那条路径会清掉当前 asset 绑定。 +- 如果 [SetPipelineAsset](SetPipelineAsset.md) 传入空指针,内部不会保留 `nullptr`,而是回退到默认 builtin forward asset。 + +## 调用方影响 + +- 这不是 `shared_ptr` 的外露别名,不提供所有权,也不保证在 `SceneRenderer` 生命周期之外继续有效。 +- 对外部来说,它更适合做调试、状态展示或测试断言,而不适合做长期缓存键。 + +## 测试覆盖 + +- `tests/Rendering/unit/test_camera_scene_renderer.cpp` 覆盖了默认 asset、替换 asset,以及替换 runtime pipeline 后 asset 观察值的变化。 + +## 相关文档 + +- [SceneRenderer](SceneRenderer.md) +- [SetPipelineAsset](SetPipelineAsset.md) +- [GetPipeline](GetPipeline.md) diff --git a/docs/api/XCEngine/Rendering/SceneRenderer/Render.md b/docs/api/XCEngine/Rendering/SceneRenderer/Render.md new file mode 100644 index 00000000..4ad1f50c --- /dev/null +++ b/docs/api/XCEngine/Rendering/SceneRenderer/Render.md @@ -0,0 +1,63 @@ +# SceneRenderer::Render + +```cpp +bool Render(const CameraRenderRequest& request); +bool Render(const std::vector& requests); +bool Render( + const Components::Scene& scene, + Components::CameraComponent* overrideCamera, + const RenderContext& context, + const RenderSurface& surface); +``` + +## 行为说明 + +`SceneRenderer` 当前提供三种提交入口。 + +### `Render(const CameraRenderRequest&)` + +这是最薄的转发层,直接调用: + +```cpp +m_cameraRenderer.Render(request) +``` + +### `Render(const std::vector&)` + +当前实现会: + +1. 拒绝空数组。 +2. 检查每个请求都必须 `IsValid()`。 +3. 复制一份数组并调用 `SceneRenderRequestUtils::SortCameraRenderRequests(...)` 做稳定排序。 +4. 逐个转发给 `m_cameraRenderer.Render(request)`。 +5. 任一请求失败即返回 `false`。 + +### `Render(const Components::Scene&, ...)` + +这是便捷入口,等价于: + +```cpp +return Render(BuildRenderRequests(scene, overrideCamera, context, surface)); +``` + +因此它本身不直接做 scene extraction;真正的 `RenderSceneExtractor` 调用发生在 `CameraRenderer::Render(...)` 内部。 + +## 返回值 + +- 所有需要执行的请求都成功完成时返回 `true`。 +- 请求数组为空、任一请求无效,或任一请求执行失败时返回 `false`。 + +## 测试覆盖 + +`tests/Rendering/unit/test_camera_scene_renderer.cpp` 当前覆盖了: + +- 多相机请求的排序与稳定性。 +- `Render(scene, ...)` 的请求构建与提交链路。 +- 手工提交请求数组时的排序规则。 + +## 相关文档 + +- [SceneRenderer](SceneRenderer.md) +- [BuildRenderRequests](BuildRenderRequests.md) +- [CameraRenderer](../CameraRenderer/CameraRenderer.md) +- [SceneRenderRequestUtils](../SceneRenderRequestUtils/SceneRenderRequestUtils.md) diff --git a/docs/api/XCEngine/Rendering/SceneRenderer/SceneRenderer.md b/docs/api/XCEngine/Rendering/SceneRenderer/SceneRenderer.md new file mode 100644 index 00000000..0c5c5255 --- /dev/null +++ b/docs/api/XCEngine/Rendering/SceneRenderer/SceneRenderer.md @@ -0,0 +1,119 @@ +# SceneRenderer + +**命名空间**: `XCEngine::Rendering` + +**类型**: `class` + +**头文件**: `XCEngine/Rendering/Execution/SceneRenderer.h` + +**描述**: 场景级渲染编排入口。它负责构建和排序 `CameraRenderRequest`,再把每个请求转交给 [CameraRenderer](../CameraRenderer/CameraRenderer.md) 执行。 + +## 概览 + +`SceneRenderer` 当前不再自己持有 `RenderSceneExtractor` 或直接驱动主管线。它只维护两块运行时对象: + +- `m_requestPlanner`:负责从 `Scene` 和可选 override camera 生成 `CameraRenderRequest` 列表。 +- `m_cameraRenderer`:负责真正执行单个相机请求,包括场景提取、主管线提交、object-id pass,以及 request 上挂接的 pre/post/overlay pass sequence。 + +这意味着当前的主链路已经拆成两层: + +1. `SceneRenderer` 负责“这次要渲染哪些相机、按什么顺序、每个请求的 surface/render-area/clear-flags 是什么”。 +2. `CameraRenderer` 负责“单个请求如何真正跑完”。 + +这条边界是当前 Rendering 模块里最值得保留的设计决定之一。 +如果把相机规划和 request 执行重新揉回一个类里,Editor 的 Scene View、object-id picking、overlay 注入和离屏渲染很快就会和主管线细节耦合到一起。 + +现在的拆法则让 `SceneRenderer` 更像一个稳定的编排入口: + +- 从 `Scene` 直接提交时,它负责生成 request +- 从外部手工提交 request 时,它负责复用同一排序规则 +- 不管 request 来源是什么,真正执行都统一落到 `CameraRenderer` + +## 当前执行路径 + +### `BuildRenderRequests(...)` + +直接委托给 [SceneRenderRequestPlanner](../SceneRenderRequestPlanner/SceneRenderRequestPlanner.md): + +```cpp +return m_requestPlanner.BuildRequests(scene, overrideCamera, context, surface); +``` + +### `Render(const Components::Scene&, ...)` + +这是“从场景直接提交”的便捷入口,本质上等价于: + +```cpp +return Render(BuildRenderRequests(scene, overrideCamera, context, surface)); +``` + +### `Render(const std::vector&)` + +当前会: + +1. 拒绝空请求数组。 +2. 拒绝任何 `IsValid()` 为假的请求。 +3. 复制一份请求数组,并通过 `SceneRenderRequestUtils::SortCameraRenderRequests(...)` 做稳定排序。 +4. 依次调用 `m_cameraRenderer.Render(request)`。 +5. 任一请求失败就立即返回 `false`。 + +这里不会额外改写 request 里的 `objectId` 或各类 pass sequence;如果上层已经补好了这些字段,`SceneRenderer` 只负责排序后转交执行。 + +这也是为什么手工 request 提交路径仍然会再次排序。当前实现明确认为“stack/depth 规则”属于 `SceneRenderer` 的稳定契约,而不是调用方各自维护的一套隐式约定。 + +### `Render(const CameraRenderRequest&)` + +这是最薄的一层,直接转发到 `m_cameraRenderer.Render(request)`。 + +## 构造与默认行为 + +- 默认构造通过默认构造的 `CameraRenderer` 获得默认主管线与默认 object-id pass。 +- 传入 `std::unique_ptr` 时,走“手动注入 runtime pipeline”路径。 +- 传入 `std::shared_ptr` 时,走“由 asset 创建 runtime pipeline”路径。 + +默认主管线的具体创建不在 `SceneRenderer` 内部硬编码,而是由 `CameraRenderer` 通过默认 [BuiltinForwardPipelineAsset](../Pipelines/BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md) 负责。 + +## 当前实现边界 + +- 不直接做 scene extraction;真正的 `RenderSceneExtractor` 调用发生在 `CameraRenderer` 里。 +- 不直接操作 `RenderPipeline` 的初始化或渲染细节;它只负责请求规划和排序。 +- 不负责替 request 自动补 `objectId` 或各类 `RenderPassSequence`;这类附加阶段通常由 Editor 或其他上层调用方在提交前写入。 +- 对手工提交的请求数组,会再次按相机优先级稳定排序,而不是按调用方原始顺序盲目执行。 + +## 测试覆盖 + +`tests/Rendering/unit/test_camera_scene_renderer.cpp` 当前验证了: + +- `BuildRenderRequests()` 的多相机排序、override camera、clear-flags 和 viewport/render-area 解析。 +- 手工提交请求数组时的排序和稳定性。 +- `SetPipeline()` / `SetPipelineAsset()` 的转发、替换与 shutdown 行为。 + +这些测试锚点说明,`SceneRenderer` 当前不是一个“薄到没有语义”的转发器。它真正承担了 request planning 契约本身,包括: + +- override camera 的回退语义 +- base / overlay 排序 +- `Auto` clear 的默认策略 +- 手工 request 重新排序的稳定性 + +## 公开方法 + +| 方法 | 说明 | +|------|------| +| [Constructor](Constructor.md) | 构造 `SceneRenderer`,并决定 `CameraRenderer` 的主管线路径。 | +| [Destructor](Destructor.md) | 默认析构;真正的运行时清理由成员对象完成。 | +| [SetPipeline](SetPipeline.md) | 手动替换当前 runtime `RenderPipeline`。 | +| [SetPipelineAsset](SetPipelineAsset.md) | 通过 `RenderPipelineAsset` 重建当前 runtime `RenderPipeline`。 | +| [GetPipeline](GetPipeline.md) | 返回当前主管线的非拥有指针。 | +| [GetPipelineAsset](GetPipelineAsset.md) | 返回当前 pipeline asset 的非拥有指针。 | +| [BuildRenderRequests](BuildRenderRequests.md) | 生成当前场景对应的相机请求列表。 | +| [Render](Render.md) | 执行单个请求、请求数组,或从场景直接生成请求并执行。 | + +## 相关文档 + +- [Rendering](../Rendering.md) +- [CameraRenderer](../CameraRenderer/CameraRenderer.md) +- [SceneRenderRequestPlanner](../SceneRenderRequestPlanner/SceneRenderRequestPlanner.md) +- [SceneRenderRequestUtils](../SceneRenderRequestUtils/SceneRenderRequestUtils.md) +- [RenderSceneExtractor](../RenderSceneExtractor/RenderSceneExtractor.md) +- [Camera Request Planning And Clear Rules](../../../_guides/Rendering/Camera-Request-Planning-And-Clear-Rules.md) + diff --git a/docs/api/XCEngine/Rendering/SceneRenderer/SetPipeline.md b/docs/api/XCEngine/Rendering/SceneRenderer/SetPipeline.md new file mode 100644 index 00000000..205da9db --- /dev/null +++ b/docs/api/XCEngine/Rendering/SceneRenderer/SetPipeline.md @@ -0,0 +1,32 @@ +# SceneRenderer::SetPipeline + +```cpp +void SetPipeline(std::unique_ptr pipeline); +``` + +## 行为说明 + +当前实现只是把调用转发给内部 `m_cameraRenderer`: + +```cpp +m_cameraRenderer.SetPipeline(std::move(pipeline)); +``` + +## 当前语义 + +沿用 `CameraRenderer::SetPipeline()` 的规则: + +- 当前绑定的 `RenderPipelineAsset` 会被清空。 +- 被替换掉的旧 runtime pipeline 会先执行 `Shutdown()`。 +- 如果新传入的 `pipeline` 为空,内部会回退到默认 pipeline asset,并重新创建默认主管线。 + +## 参数 + +- `pipeline` - 新的 runtime pipeline 所有权,可为空。 + +## 相关文档 + +- [SceneRenderer](SceneRenderer.md) +- [SetPipelineAsset](SetPipelineAsset.md) +- [GetPipeline](GetPipeline.md) +- [CameraRenderer::SetPipeline](../CameraRenderer/SetPipeline.md) diff --git a/docs/api/XCEngine/Rendering/SceneRenderer/SetPipelineAsset.md b/docs/api/XCEngine/Rendering/SceneRenderer/SetPipelineAsset.md new file mode 100644 index 00000000..c6b4f531 --- /dev/null +++ b/docs/api/XCEngine/Rendering/SceneRenderer/SetPipelineAsset.md @@ -0,0 +1,34 @@ +# SceneRenderer::SetPipelineAsset + +切换当前场景渲染器使用的 pipeline asset。 + +```cpp +void SetPipelineAsset(std::shared_ptr pipelineAsset); +``` + +## 参数 + +- `pipelineAsset` - 目标 pipeline asset;允许传入空指针。 + +## 当前语义 + +- 当前实现直接转发到内部 `m_cameraRenderer.SetPipelineAsset(...)`。 +- 如果传入 asset 非空,后续 runtime pipeline 会由该 asset 创建。 +- 如果传入 asset 为空,内部会回退到默认 builtin forward pipeline asset,而不是保留空绑定。 +- 被替换掉的旧 runtime pipeline 会先执行 `Shutdown()`,再由新 asset 创建新实例。 + +## 调用方影响 + +- 调用之后,[GetPipelineAsset](GetPipelineAsset.md) 和 [GetPipeline](GetPipeline.md) 的返回值都可能变化。 +- 任何此前缓存的旧 pipeline 指针都应视为潜在失效。 +- 如果调用方只是想直接接管 runtime pipeline,而不是保留 asset 工厂关系,应改用 [SetPipeline](SetPipeline.md)。 + +## 测试覆盖 + +- `tests/Rendering/unit/test_camera_scene_renderer.cpp` 验证了替换 asset 时旧 pipeline 会被 `Shutdown()`,并且新 asset 会创建新的 runtime pipeline 实例。 + +## 相关文档 + +- [SceneRenderer](SceneRenderer.md) +- [SetPipeline](SetPipeline.md) +- [GetPipelineAsset](GetPipelineAsset.md)