103 lines
4.9 KiB
Markdown
103 lines
4.9 KiB
Markdown
# SceneRenderRequestPlanner
|
||
|
||
**命名空间**: `XCEngine::Rendering`
|
||
|
||
**类型**: `class`
|
||
|
||
**头文件**: `XCEngine/Rendering/Planning/SceneRenderRequestPlanner.h`
|
||
|
||
**描述**: 负责从场景和可选 override camera 生成实际要提交给 `CameraRenderer` 的相机请求列表。
|
||
|
||
## 概览
|
||
|
||
`SceneRenderRequestPlanner` 处在 [SceneRenderer](../../Execution/SceneRenderer/SceneRenderer.md) 和 [SceneRenderRequestUtils](../SceneRenderRequestUtils/SceneRenderRequestUtils.md) 之间。
|
||
它不亲自渲染任何东西,而是把“应该渲染哪些相机、按什么顺序、哪些请求应该被丢弃”整理成一组 [CameraRenderRequest](../CameraRenderRequest/CameraRenderRequest.md)。
|
||
|
||
这种“先规划 request,再执行 request”的拆法很接近商业引擎里常见的 camera scheduling 思路。它的价值不是抽象更漂亮,而是把两类会频繁变化的逻辑拆开:
|
||
|
||
- 场景侧规则:相机收集、stack/depth 排序、clear 推导、viewport 解析
|
||
- 执行侧规则:scene extraction、主管线、object-id、post/overlay pass
|
||
|
||
这样 Editor、离屏渲染和手工 request 注入都能复用同一套规划规则,而不用直接碰 `CameraRenderer` 内部执行链。
|
||
|
||
## 公开类型与方法
|
||
|
||
当前头文件除了 planner 本体,还公开了:
|
||
|
||
- `DirectionalShadowPlanningSettings`
|
||
负责控制自动方向光阴影规划的 map 尺寸、focus 距离、padding 和深度范围下限。
|
||
|
||
公开方法包括:
|
||
|
||
| 方法 | 说明 |
|
||
|------|------|
|
||
| `SetDirectionalShadowPlanningSettings(...)` | 写入一份会先经过 sanitize 的阴影规划参数。 |
|
||
| `GetDirectionalShadowPlanningSettings()` | 返回当前生效的阴影规划参数。 |
|
||
| [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 计数。
|
||
|
||
如果当前相机满足方向光阴影规划条件,planner 还会:
|
||
|
||
- 查找当前 `cullingMask` 下可投影阴影的主方向光
|
||
- 用 `DirectionalShadowPlanningSettings` 生成 `request.directionalShadow`
|
||
- 在 plan 有效时,把 `shadowCaster.clearFlags` 固定为 `RenderClearFlags::Depth`
|
||
- 同时把 `shadowCaster.hasCameraDataOverride` 和 `cameraDataOverride` 写成阴影相机数据
|
||
|
||
## 设计取舍
|
||
|
||
当前 planner 故意保持“只做一件事”:
|
||
|
||
- 负责决定 request 集合
|
||
- 不负责 request 执行
|
||
- 不负责附加 pass 组装
|
||
|
||
这是一种比很多早期引擎实现更稳的做法。否则 Scene View 一旦要加 object-id、grid、selection outline、editor overlay,规划逻辑和执行逻辑很容易在一个类里互相缠死。
|
||
|
||
另一个重要取舍是:当前只支持 base / overlay + depth 的线性排序,而不是更复杂的 stacking 依赖图。
|
||
这不是文档漏写,而是当前实现的真实边界。它优先保证顺序简单、稳定、可测试。
|
||
|
||
## 真实使用位置
|
||
|
||
- `engine/include/XCEngine/Rendering/Execution/SceneRenderer.h` 持有一个 `SceneRenderRequestPlanner` 实例。
|
||
- `engine/src/Rendering/Planning/SceneRenderRequestPlanner.cpp` 实现具体收集与构建逻辑。
|
||
- `tests/Rendering/unit/test_scene_render_request_planner.cpp` 覆盖了 override camera、稳定排序和零尺寸 viewport 的行为。
|
||
|
||
## 当前实现边界
|
||
|
||
- 它只规划相机请求,不处理 `objectId` 或各类 `RenderPassSequence` 的具体填充;那部分通常由更上层调用方补充。
|
||
- 当前没有 camera stacking 的更复杂依赖分析,只有 base / overlay 与 depth 的线性排序。
|
||
- `BuildRequests()` 只返回成功构建的请求,不单独报告被过滤掉的相机原因。
|
||
- 自动方向光阴影规划目前只产出单张 shadow map 方案,不在这里处理级联阴影或多光源阴影编排。
|
||
|
||
## 相关文档
|
||
|
||
- [当前模块](../../Rendering.md)
|
||
- [CollectCameras](CollectCameras.md)
|
||
- [BuildRequests](BuildRequests.md)
|
||
- [SceneRenderer](../../Execution/SceneRenderer/SceneRenderer.md)
|
||
- [SceneRenderRequestUtils](../SceneRenderRequestUtils/SceneRenderRequestUtils.md)
|
||
- [CameraRenderRequest](../CameraRenderRequest/CameraRenderRequest.md)
|
||
- [Camera Request Planning And Clear Rules](../../../../_guides/Rendering/Camera-Request-Planning-And-Clear-Rules.md)
|
||
|