From ed95aa1dc540be673cb3e951930bdbad5a65503a Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Fri, 3 Apr 2026 14:09:36 +0800 Subject: [PATCH] docs: expand render request planning docs --- .../BuiltinPostProcessRequest.md | 40 +++++++++ .../BuiltinPostProcessRequest/IsRequested.md | 32 +++++++ .../CameraRenderRequest.md | 6 +- .../ObjectIdRenderRequest/IsRequested.md | 31 +++++++ .../ObjectIdRenderRequest/IsValid.md | 36 ++++++++ .../ObjectIdRenderRequest.md | 37 ++++++++ .../BuildRequests.md | 38 ++++++++ .../CollectCameras.md | 33 +++++++ .../SceneRenderRequestPlanner.md | 65 ++++++++++++++ .../SceneRenderRequestUtils.md | 89 +++++++++++++++++++ 10 files changed, 405 insertions(+), 2 deletions(-) create mode 100644 docs/api/XCEngine/Rendering/CameraRenderRequest/BuiltinPostProcessRequest/BuiltinPostProcessRequest.md create mode 100644 docs/api/XCEngine/Rendering/CameraRenderRequest/BuiltinPostProcessRequest/IsRequested.md create mode 100644 docs/api/XCEngine/Rendering/CameraRenderRequest/ObjectIdRenderRequest/IsRequested.md create mode 100644 docs/api/XCEngine/Rendering/CameraRenderRequest/ObjectIdRenderRequest/IsValid.md create mode 100644 docs/api/XCEngine/Rendering/CameraRenderRequest/ObjectIdRenderRequest/ObjectIdRenderRequest.md create mode 100644 docs/api/XCEngine/Rendering/SceneRenderRequestPlanner/BuildRequests.md create mode 100644 docs/api/XCEngine/Rendering/SceneRenderRequestPlanner/CollectCameras.md create mode 100644 docs/api/XCEngine/Rendering/SceneRenderRequestPlanner/SceneRenderRequestPlanner.md create mode 100644 docs/api/XCEngine/Rendering/SceneRenderRequestUtils/SceneRenderRequestUtils.md diff --git a/docs/api/XCEngine/Rendering/CameraRenderRequest/BuiltinPostProcessRequest/BuiltinPostProcessRequest.md b/docs/api/XCEngine/Rendering/CameraRenderRequest/BuiltinPostProcessRequest/BuiltinPostProcessRequest.md new file mode 100644 index 00000000..325f9157 --- /dev/null +++ b/docs/api/XCEngine/Rendering/CameraRenderRequest/BuiltinPostProcessRequest/BuiltinPostProcessRequest.md @@ -0,0 +1,40 @@ +# BuiltinPostProcessRequest + +**命名空间**: `XCEngine::Rendering` + +**类型**: `struct` + +**头文件**: `XCEngine/Rendering/CameraRenderRequest.h` + +**描述**: 描述 scene viewport 一类内建后处理请求,包括无限网格、选中轮廓和调试遮罩所需输入。 + +## 概述 + +`BuiltinPostProcessRequest` 是 [CameraRenderRequest](../CameraRenderRequest.md) 里的内建后处理子请求。它不直接决定执行哪些 GPU 步骤,而是把原始输入交给 `BuiltinPostProcessPassSequenceBuilder` 去规划。 + +## 字段 + +| 字段 | 说明 | +|------|------| +| `gridPassData` | 控制是否绘制 scene viewport 的无限网格。 | +| `objectIdTextureView` | 供 outline / debug mask 读取的 object-id 纹理 SRV。 | +| `selectedObjectIds` | 当前需要描边或调试的对象 ID 集合。 | +| `outlineStyle` | 轮廓颜色、宽度和调试遮罩开关。 | + +## 关键语义 + +- [IsRequested](IsRequested.md) 当前只看 `gridPassData.valid` 和 `selectedObjectIds`,不会因为单独设置了 `objectIdTextureView` 或 `outlineStyle.debugSelectionMask` 就自动变成“已请求”。 +- 这意味着 `objectIdTextureView` 更像是 outline / debug 路径的依赖输入,而不是请求开关本身。 +- 更细的回退策略和步骤顺序由 `BuiltinPostProcessPassSequenceBuilder` 与 `BuiltinPostProcessPassPlan` 决定。 + +## 真实使用位置 + +- 编辑器 scene viewport 会构造这份请求,把无限网格、选中实体 ID 和 outline style 传进 `CameraRenderer`。 +- `CameraRenderer::Render()` 在主场景和 `postScenePasses` 之后,调用 builtin post-process builder 处理这里的内容。 + +## 相关文档 + +- [CameraRenderRequest](../CameraRenderRequest.md) +- [IsRequested](IsRequested.md) +- [Passes](../../Passes/Passes.md) +- [BuiltinPostProcessPassSequenceBuilder](../../Passes/BuiltinPostProcessPassSequenceBuilder/BuiltinPostProcessPassSequenceBuilder.md) diff --git a/docs/api/XCEngine/Rendering/CameraRenderRequest/BuiltinPostProcessRequest/IsRequested.md b/docs/api/XCEngine/Rendering/CameraRenderRequest/BuiltinPostProcessRequest/IsRequested.md new file mode 100644 index 00000000..72423d3f --- /dev/null +++ b/docs/api/XCEngine/Rendering/CameraRenderRequest/BuiltinPostProcessRequest/IsRequested.md @@ -0,0 +1,32 @@ +# BuiltinPostProcessRequest::IsRequested + +检查当前是否请求了 builtin 后处理。 + +```cpp +bool IsRequested() const; +``` + +## 行为说明 + +当前头文件内联实现只有一条规则: + +```cpp +return gridPassData.valid || !selectedObjectIds.empty(); +``` + +## 返回值 + +- 当 `gridPassData.valid` 为真,或 `selectedObjectIds` 非空时,返回 `true`。 +- 否则返回 `false`。 + +## 注意事项 + +- 单独设置 `objectIdTextureView` 不会让请求生效。 +- 单独把 `outlineStyle.debugSelectionMask` 设成 `true` 也不会让请求生效;仍然需要 grid 或 selection 至少有一个真正开启。 +- 这也是为什么 scene viewport 必须显式提供选中对象 ID,outline / debug mask 路径才会进入 builder。 + +## 相关文档 + +- [返回类型总览](BuiltinPostProcessRequest.md) +- [CameraRenderRequest](../CameraRenderRequest.md) +- [BuiltinPostProcessPassSequenceBuilder](../../Passes/BuiltinPostProcessPassSequenceBuilder/BuiltinPostProcessPassSequenceBuilder.md) diff --git a/docs/api/XCEngine/Rendering/CameraRenderRequest/CameraRenderRequest.md b/docs/api/XCEngine/Rendering/CameraRenderRequest/CameraRenderRequest.md index 2816147d..c352e259 100644 --- a/docs/api/XCEngine/Rendering/CameraRenderRequest/CameraRenderRequest.md +++ b/docs/api/XCEngine/Rendering/CameraRenderRequest/CameraRenderRequest.md @@ -40,7 +40,7 @@ ### `objectId` -`objectId` 是一个 `ObjectIdRenderRequest`,用于描述“是否要额外渲染一张 object-id 辅助纹理”。 +`objectId` 是一个 [ObjectIdRenderRequest](ObjectIdRenderRequest/ObjectIdRenderRequest.md),用于描述“是否要额外渲染一张 object-id 辅助纹理”。 - `IsRequested()` 只检查 `surface` 是否挂了颜色附件。 - `IsValid()` 进一步要求: @@ -52,7 +52,7 @@ ### `builtinPostProcess` -`builtinPostProcess` 是一个 `BuiltinPostProcessRequest`,用于描述 scene viewport 一类内建附加效果: +`builtinPostProcess` 是一个 [BuiltinPostProcessRequest](BuiltinPostProcessRequest/BuiltinPostProcessRequest.md),用于描述 scene viewport 一类内建附加效果: - `gridPassData` 控制无限网格 - `objectIdTextureView` 把 object-id 纹理作为 SRV 传给后处理 @@ -79,6 +79,8 @@ ## 相关文档 - [IsValid](IsValid.md) +- [ObjectIdRenderRequest](ObjectIdRenderRequest/ObjectIdRenderRequest.md) +- [BuiltinPostProcessRequest](BuiltinPostProcessRequest/BuiltinPostProcessRequest.md) - [CameraRenderer](../CameraRenderer/CameraRenderer.md) - [SceneRenderer](../SceneRenderer/SceneRenderer.md) - [RenderContext](../RenderContext/RenderContext.md) diff --git a/docs/api/XCEngine/Rendering/CameraRenderRequest/ObjectIdRenderRequest/IsRequested.md b/docs/api/XCEngine/Rendering/CameraRenderRequest/ObjectIdRenderRequest/IsRequested.md new file mode 100644 index 00000000..cd46e38c --- /dev/null +++ b/docs/api/XCEngine/Rendering/CameraRenderRequest/ObjectIdRenderRequest/IsRequested.md @@ -0,0 +1,31 @@ +# ObjectIdRenderRequest::IsRequested + +检查当前是否请求了 object-id 辅助输出。 + +```cpp +bool IsRequested() const; +``` + +## 行为说明 + +当前头文件内联实现只有一条判断: + +```cpp +return !surface.GetColorAttachments().empty(); +``` + +## 返回值 + +- 只要 `surface` 上至少挂了一个颜色附件,就返回 `true`。 +- 否则返回 `false`。 + +## 注意事项 + +- 这不是完整性校验;颜色附件数组非空并不代表第一个附件非空,也不代表深度附件和 render area 合法。 +- 真正更严格的检查在 [IsValid](IsValid.md)。 + +## 相关文档 + +- [返回类型总览](ObjectIdRenderRequest.md) +- [IsValid](IsValid.md) +- [CameraRenderRequest](../CameraRenderRequest.md) diff --git a/docs/api/XCEngine/Rendering/CameraRenderRequest/ObjectIdRenderRequest/IsValid.md b/docs/api/XCEngine/Rendering/CameraRenderRequest/ObjectIdRenderRequest/IsValid.md new file mode 100644 index 00000000..a4e2bd66 --- /dev/null +++ b/docs/api/XCEngine/Rendering/CameraRenderRequest/ObjectIdRenderRequest/IsValid.md @@ -0,0 +1,36 @@ +# ObjectIdRenderRequest::IsValid + +检查当前 object-id 输出目标是否满足执行 pass 的最小条件。 + +```cpp +bool IsValid() const; +``` + +## 行为说明 + +当前头文件内联实现要求同时满足: + +```cpp +const std::vector& colorAttachments = surface.GetColorAttachments(); +return !colorAttachments.empty() && + colorAttachments[0] != nullptr && + surface.GetDepthAttachment() != nullptr && + surface.GetRenderAreaWidth() > 0 && + surface.GetRenderAreaHeight() > 0; +``` + +## 返回值 + +- 第一个颜色附件非空、深度附件非空且 render area 宽高都大于 `0` 时返回 `true`。 +- 否则返回 `false`。 + +## 与 `CameraRenderer::Render()` 的关系 + +- `CameraRenderer::Render()` 会先看 [IsRequested](IsRequested.md)。 +- 如果请求了 object-id 输出,但这里返回 `false`,整次相机渲染会直接失败。 + +## 相关文档 + +- [返回类型总览](ObjectIdRenderRequest.md) +- [IsRequested](IsRequested.md) +- [CameraRenderer::Render](../../CameraRenderer/Render.md) diff --git a/docs/api/XCEngine/Rendering/CameraRenderRequest/ObjectIdRenderRequest/ObjectIdRenderRequest.md b/docs/api/XCEngine/Rendering/CameraRenderRequest/ObjectIdRenderRequest/ObjectIdRenderRequest.md new file mode 100644 index 00000000..683dffc7 --- /dev/null +++ b/docs/api/XCEngine/Rendering/CameraRenderRequest/ObjectIdRenderRequest/ObjectIdRenderRequest.md @@ -0,0 +1,37 @@ +# ObjectIdRenderRequest + +**命名空间**: `XCEngine::Rendering` + +**类型**: `struct` + +**头文件**: `XCEngine/Rendering/CameraRenderRequest.h` + +**描述**: 描述一份 camera request 是否需要额外输出 object-id 纹理,以及这份输出目标是否完整可用。 + +## 概述 + +`ObjectIdRenderRequest` 是 [CameraRenderRequest](../CameraRenderRequest.md) 里的辅助子请求,用来把“主场景颜色输出”和“object-id 辅助输出”拆开描述。 + +它当前只持有一个字段: + +| 字段 | 说明 | +|------|------| +| `surface` | object-id pass 要写入的目标表面,通常是单独的颜色附件 + 深度附件组合。 | + +## 关键语义 + +- [IsRequested](IsRequested.md) 只回答“调用方有没有挂一个颜色附件过来”。 +- [IsValid](IsValid.md) 才回答“这份 object-id 输出目标是否足够完整,可以真正执行 pass”。 +- `CameraRenderer::Render()` 会在主场景之后检查并消费这个子请求。 + +## 真实使用位置 + +- 编辑器 scene viewport 会准备一张单独的 object-id render target,并把它装进 `request.objectId.surface`。 +- `CameraRenderer::Render()` 在 `request.objectId.IsRequested()` 为真时,调用当前的 `ObjectIdPass` 执行辅助输出。 + +## 相关文档 + +- [CameraRenderRequest](../CameraRenderRequest.md) +- [IsRequested](IsRequested.md) +- [IsValid](IsValid.md) +- [CameraRenderer](../../CameraRenderer/CameraRenderer.md) diff --git a/docs/api/XCEngine/Rendering/SceneRenderRequestPlanner/BuildRequests.md b/docs/api/XCEngine/Rendering/SceneRenderRequestPlanner/BuildRequests.md new file mode 100644 index 00000000..c3750971 --- /dev/null +++ b/docs/api/XCEngine/Rendering/SceneRenderRequestPlanner/BuildRequests.md @@ -0,0 +1,38 @@ +# SceneRenderRequestPlanner::BuildRequests + +```cpp +std::vector BuildRequests( + const Components::Scene& scene, + Components::CameraComponent* overrideCamera, + const RenderContext& context, + const RenderSurface& surface) const; +``` + +## 行为说明 + +当前实现先调用 [CollectCameras](CollectCameras.md) 取得这次需要处理的相机列表,然后逐个调用 `SceneRenderRequestUtils::BuildCameraRenderRequest(...)` 生成请求。 + +构建过程中会维护两类计数: + +- `renderedBaseCameraCount` +- 已成功加入结果数组的 request 数量 + +这两个计数会传给 `ResolveClearFlags()`,用于推导 `Auto` clear mode 的最终清屏行为。 + +## 当前过滤规则 + +- 如果某台相机最终生成的 request render area 宽高为 `0`,该请求会被跳过。 +- 只有真正成功加入结果数组的 base camera,才会推进 `renderedBaseCameraCount`。 +- 方法不会抛出失败原因;调用方只会拿到最终保留下来的请求数组。 + +## 返回值 + +- 一组已经完成基础字段填充的 [CameraRenderRequest](../CameraRenderRequest/CameraRenderRequest.md)。 +- 结果可能为空,例如没有可用相机,或所有相机的 render area 都被裁成了零尺寸。 + +## 相关文档 + +- [SceneRenderRequestPlanner](SceneRenderRequestPlanner.md) +- [CollectCameras](CollectCameras.md) +- [SceneRenderRequestUtils](../SceneRenderRequestUtils/SceneRenderRequestUtils.md) +- [SceneRenderer::BuildRenderRequests](../SceneRenderer/BuildRenderRequests.md) diff --git a/docs/api/XCEngine/Rendering/SceneRenderRequestPlanner/CollectCameras.md b/docs/api/XCEngine/Rendering/SceneRenderRequestPlanner/CollectCameras.md new file mode 100644 index 00000000..d3c4f72b --- /dev/null +++ b/docs/api/XCEngine/Rendering/SceneRenderRequestPlanner/CollectCameras.md @@ -0,0 +1,33 @@ +# SceneRenderRequestPlanner::CollectCameras + +```cpp +std::vector CollectCameras( + const Components::Scene& scene, + Components::CameraComponent* overrideCamera) const; +``` + +## 行为说明 + +当前实现按下面的顺序决定这次真正参与渲染规划的相机列表: + +1. 如果 `overrideCamera` 通过 [SceneRenderRequestUtils](../SceneRenderRequestUtils/SceneRenderRequestUtils.md) 的 `IsUsableCamera()` 检查,则只返回这一台相机。 +2. 否则从 `scene` 里收集全部 `CameraComponent`。 +3. 过滤掉不可用相机。 +4. 调用 `SceneRenderRequestUtils::SortSceneCamerasForRendering(...)` 做稳定排序。 + +## 返回值 + +- 一个已经过滤并排序好的相机数组。 +- 如果没有任何可用相机,返回空数组。 + +## 当前排序语义 + +- `base` 相机会排在 `overlay` 前面。 +- 同一 stack 类型内部再按 `depth` 升序。 +- 排序使用 `std::stable_sort()`,所以完全同键时仍保留场景原始枚举顺序。 + +## 相关文档 + +- [SceneRenderRequestPlanner](SceneRenderRequestPlanner.md) +- [BuildRequests](BuildRequests.md) +- [SceneRenderRequestUtils](../SceneRenderRequestUtils/SceneRenderRequestUtils.md) diff --git a/docs/api/XCEngine/Rendering/SceneRenderRequestPlanner/SceneRenderRequestPlanner.md b/docs/api/XCEngine/Rendering/SceneRenderRequestPlanner/SceneRenderRequestPlanner.md new file mode 100644 index 00000000..d85a821d --- /dev/null +++ b/docs/api/XCEngine/Rendering/SceneRenderRequestPlanner/SceneRenderRequestPlanner.md @@ -0,0 +1,65 @@ +# SceneRenderRequestPlanner + +**命名空间**: `XCEngine::Rendering` + +**类型**: `class` + +**头文件**: `XCEngine/Rendering/SceneRenderRequestPlanner.h` + +**描述**: 负责从场景和可选 override camera 生成实际要提交给 `CameraRenderer` 的相机请求列表。 + +## 概览 + +`SceneRenderRequestPlanner` 处在 [SceneRenderer](../SceneRenderer/SceneRenderer.md) 和 [SceneRenderRequestUtils](../SceneRenderRequestUtils/SceneRenderRequestUtils.md) 之间。 + +它不亲自渲染任何东西,而是把“应该渲染哪些相机、按什么顺序、哪些请求应该被丢弃”整理成一组 [CameraRenderRequest](../CameraRenderRequest/CameraRenderRequest.md)。 + +## 公开方法 + +| 方法 | 说明 | +|------|------| +| [CollectCameras](CollectCameras.md) | 收集本次应参与渲染的相机列表。 | +| [BuildRequests](BuildRequests.md) | 把相机列表展开成可执行的 `CameraRenderRequest` 数组。 | + +## 当前规划规则 + +### `CollectCameras()` + +当前规则是: + +1. 如果 `overrideCamera` 可用,则只渲染它自己。 +2. 否则从场景里查找全部 `CameraComponent`。 +3. 过滤掉不可用相机。 +4. 按 [SceneRenderRequestUtils](../SceneRenderRequestUtils/SceneRenderRequestUtils.md) 里的稳定排序规则整理顺序。 + +### `BuildRequests()` + +它会按相机顺序逐个调用 `BuildCameraRenderRequest()`,并维护: + +- `renderedBaseCameraCount` +- 已成功生成的 request 数量 + +这两个计数会影响自动 clear flag 的推导。 + +如果某个相机最终解析出的 render area 宽高为 `0`,该请求会被直接丢弃,而且不会错误地推进 base camera 计数。 + +## 真实使用位置 + +- `engine/include/XCEngine/Rendering/SceneRenderer.h` 持有一个 `SceneRenderRequestPlanner` 实例。 +- `engine/src/Rendering/SceneRenderRequestPlanner.cpp` 实现具体收集与构建逻辑。 +- `tests/Rendering/unit/test_scene_render_request_planner.cpp` 覆盖了 override camera、稳定排序和零尺寸 viewport 的行为。 + +## 当前实现边界 + +- 它只规划相机请求,不处理 object-id 或 builtin post-process 的具体填充;那部分通常由更上层调用方补充。 +- 当前没有 camera stacking 的更复杂依赖分析,只有 base / overlay 与 depth 的线性排序。 +- `BuildRequests()` 只返回成功构建的请求,不单独报告被过滤掉的相机原因。 + +## 相关文档 + +- [当前模块](../Rendering.md) +- [CollectCameras](CollectCameras.md) +- [BuildRequests](BuildRequests.md) +- [SceneRenderer](../SceneRenderer/SceneRenderer.md) +- [SceneRenderRequestUtils](../SceneRenderRequestUtils/SceneRenderRequestUtils.md) +- [CameraRenderRequest](../CameraRenderRequest/CameraRenderRequest.md) diff --git a/docs/api/XCEngine/Rendering/SceneRenderRequestUtils/SceneRenderRequestUtils.md b/docs/api/XCEngine/Rendering/SceneRenderRequestUtils/SceneRenderRequestUtils.md new file mode 100644 index 00000000..81fa7452 --- /dev/null +++ b/docs/api/XCEngine/Rendering/SceneRenderRequestUtils/SceneRenderRequestUtils.md @@ -0,0 +1,89 @@ +# SceneRenderRequestUtils + +**命名空间**: `XCEngine::Rendering::SceneRenderRequestUtils` + +**类型**: `utility header` + +**头文件**: `XCEngine/Rendering/SceneRenderRequestUtils.h` + +**描述**: 提供相机可用性判断、稳定排序、clear flag 推导、render area 计算和 request 组装等内联 helper。 + +## 概览 + +`SceneRenderRequestUtils.h` 是当前相机请求规划链路的规则库。 + +和 [SceneRenderRequestPlanner](../SceneRenderRequestPlanner/SceneRenderRequestPlanner.md) 的职责分工是: + +- planner 决定“要处理哪些相机” +- utils 决定“这些相机和请求该怎样排序、怎样计算 clear、怎样落成具体 request” + +## 公开规则 + +### 相机可用性 + +`IsUsableCamera()` 只接受: + +- 非空相机 +- 组件启用 +- 挂载 `GameObject` 非空 +- 对象处于 `IsActiveInHierarchy()` + +### 排序 + +`SortSceneCamerasForRendering()` 与 `SortCameraRenderRequests()` 都使用 `std::stable_sort()`,因此在排序键完全相同的情况下,会保留原始相对顺序。 + +当前排序键分别是: + +- 场景相机: `stackType` -> `depth` +- 渲染请求: `cameraStackOrder` -> `cameraDepth` + +### clear flag 推导 + +`ResolveClearFlags()` 的规则是: + +- `ColorAndDepth` -> `RenderClearFlags::All` +- `DepthOnly` -> `RenderClearFlags::Depth` +- `None` -> `RenderClearFlags::None` +- `Auto` + - overlay camera: 本次若还是首个已渲染 request,则清 `All`,否则只清 `Depth` + - base camera: 若还没有任何成功渲染的 base camera,则清 `All`,否则只清 `Depth` + +### render area 计算 + +`ResolveCameraRenderArea()` 会把相机 `viewportRect` 解释为父 `RenderSurface` 当前 render area 的归一化子矩形: + +- 左上边界使用 `floor` +- 右下边界使用 `ceil` + +### request 组装 + +`BuildCameraRenderRequest()` 当前会: + +- 清空输出 request +- 绑定 `scene`、`camera`、`context` +- 复制输入 `surface`,再把 render area 改成相机子区域 +- 写入 `cameraDepth`、`cameraStackOrder`、`clearFlags` +- 只有 render area 宽高都大于 `0` 时才返回 `true` + +## 测试验证的真实行为 + +`tests/Rendering/unit/test_scene_render_request_utils.cpp` 已覆盖: + +- 空指针 / 禁用 / 非激活相机都会被拒绝 +- 场景相机与 request 排序都保持稳定 tie 顺序 +- `Auto` clear mode 在 base / overlay 下的回退行为 +- 嵌套 render area 的矩形组合规则 +- 零尺寸 viewport 会导致 request 构建失败 + +## 当前实现边界 + +- 这些 helper 是纯局部规则,不处理多表面、多窗口或跨帧状态。 +- clear 推导只依赖当前计数,不关心更复杂的 camera stack 依赖关系。 +- request 组装阶段只填基础字段,object-id 与 builtin post-process 仍需上层补全。 + +## 相关文档 + +- [当前模块](../Rendering.md) +- [SceneRenderRequestPlanner](../SceneRenderRequestPlanner/SceneRenderRequestPlanner.md) +- [CameraRenderRequest](../CameraRenderRequest/CameraRenderRequest.md) +- [SceneRenderer](../SceneRenderer/SceneRenderer.md)