2026-04-07 00:17:51 +08:00
|
|
|
|
# CameraRenderer
|
|
|
|
|
|
|
|
|
|
|
|
**命名空间**: `XCEngine::Rendering`
|
|
|
|
|
|
|
|
|
|
|
|
**类型**: `class`
|
|
|
|
|
|
|
|
|
|
|
|
**头文件**: `XCEngine/Rendering/Execution/CameraRenderer.h`
|
|
|
|
|
|
|
2026-04-10 16:55:33 +08:00
|
|
|
|
**描述**: 单个 `CameraRenderRequest` 的执行器,负责把一份显式 request 变成稳定的逐阶段渲染流程。
|
2026-04-07 00:17:51 +08:00
|
|
|
|
|
|
|
|
|
|
## 概览
|
|
|
|
|
|
|
2026-04-10 16:55:33 +08:00
|
|
|
|
`CameraRenderer` 是 Execution 层里最靠近“真正发起一次相机渲染”的类。
|
2026-04-07 00:17:51 +08:00
|
|
|
|
|
2026-04-10 16:55:33 +08:00
|
|
|
|
它不负责决定应该渲染哪些相机,也不负责 request 排序;这些职责在 [Planning](../../Planning/Planning.md) 和 [SceneRenderer](../SceneRenderer/SceneRenderer.md)。
|
|
|
|
|
|
它负责的是另一半:把一份已经构造好的 `CameraRenderRequest` 按当前引擎约定的阶段顺序完整跑完。
|
2026-04-07 00:17:51 +08:00
|
|
|
|
|
|
|
|
|
|
## 当前持有对象
|
|
|
|
|
|
|
|
|
|
|
|
- `m_sceneExtractor`
|
2026-04-10 16:55:33 +08:00
|
|
|
|
负责把 `Scene + Camera` 压成 `RenderSceneData`。
|
2026-04-07 00:17:51 +08:00
|
|
|
|
- `m_pipelineAsset`
|
2026-04-10 16:55:33 +08:00
|
|
|
|
当前主管线的创建来源;为空时表示直接持有 runtime pipeline。
|
2026-04-07 00:17:51 +08:00
|
|
|
|
- `m_pipeline`
|
2026-04-10 16:55:33 +08:00
|
|
|
|
真正执行主场景绘制的 [RenderPipeline](../../RenderPipeline/RenderPipeline.md)。
|
2026-04-07 00:17:51 +08:00
|
|
|
|
- `m_objectIdPass`
|
2026-04-10 16:55:33 +08:00
|
|
|
|
object-id 输出阶段使用的 `RenderPass`。
|
2026-04-07 00:17:51 +08:00
|
|
|
|
- `m_depthOnlyPass`
|
2026-04-10 16:55:33 +08:00
|
|
|
|
depth-only 阶段使用的 `RenderPass`。
|
2026-04-07 00:17:51 +08:00
|
|
|
|
- `m_shadowCasterPass`
|
2026-04-10 16:55:33 +08:00
|
|
|
|
shadow-caster 阶段使用的 `RenderPass`。
|
2026-04-07 00:17:51 +08:00
|
|
|
|
- `m_directionalShadowSurface`
|
2026-04-10 16:55:33 +08:00
|
|
|
|
当 request 只提供 `DirectionalShadowRenderPlan`、而没有显式 `shadowCaster.surface` 时,按需生成阴影贴图 surface。
|
2026-04-07 00:17:51 +08:00
|
|
|
|
- `m_postProcessSurfaceCache`
|
|
|
|
|
|
- `m_finalOutputSurfaceCache`
|
2026-04-10 16:55:33 +08:00
|
|
|
|
fullscreen 阶段多 pass 链使用的中间 surface cache。
|
2026-04-07 00:17:51 +08:00
|
|
|
|
|
|
|
|
|
|
## 当前执行顺序
|
|
|
|
|
|
|
2026-04-10 16:55:33 +08:00
|
|
|
|
`CameraRenderer::Render(...)` 会按 `kOrderedCameraFrameStages` 依次执行:
|
|
|
|
|
|
|
|
|
|
|
|
1. `PreScenePasses`
|
|
|
|
|
|
2. `ShadowCaster`
|
|
|
|
|
|
3. `DepthOnly`
|
|
|
|
|
|
4. `MainScene`
|
|
|
|
|
|
5. `PostProcess`
|
|
|
|
|
|
6. `FinalOutput`
|
|
|
|
|
|
7. `ObjectId`
|
|
|
|
|
|
8. `PostScenePasses`
|
|
|
|
|
|
9. `OverlayPasses`
|
|
|
|
|
|
|
|
|
|
|
|
其中:
|
|
|
|
|
|
|
|
|
|
|
|
- `MainScene` 永远会尝试执行。
|
|
|
|
|
|
- 其他阶段是否执行,由 `CameraRenderRequest::HasFrameStage(...)` 决定。
|
|
|
|
|
|
- `ShadowCaster` 既可以消费显式 `request.shadowCaster`,也可以由 `request.directionalShadow` 推导出内部阴影 surface。
|
|
|
|
|
|
|
|
|
|
|
|
## 设计要点
|
2026-04-07 00:17:51 +08:00
|
|
|
|
|
2026-04-10 16:55:33 +08:00
|
|
|
|
### 为什么这里坚持“显式阶段链”
|
|
|
|
|
|
|
|
|
|
|
|
这和 Unity SRP 里常见的 camera render loop 思路相似:每个阶段有稳定顺序,request 只是声明“这一帧这个阶段要不要做”。
|
|
|
|
|
|
这样做的好处是:
|
|
|
|
|
|
|
|
|
|
|
|
- post-process、final-output 和 editor 注入 pass 都能接到同一条链上
|
|
|
|
|
|
- 不同调用方不需要各自复制一套“主场景之后到底先做什么”的隐式约定
|
|
|
|
|
|
- object-id、selection、scene view overlay 这类非主画面输出,不会反向污染主管线实现
|
|
|
|
|
|
|
|
|
|
|
|
### 为什么 fullscreen 阶段不放到 pipeline 内部
|
|
|
|
|
|
|
|
|
|
|
|
`RenderPipeline` 关注的是主场景绘制;fullscreen 链更像是 request 级组合层。
|
|
|
|
|
|
把它们留在 `CameraRenderer`,可以让不同 pipeline 共享一致的 post-process / final-output 接线方式。
|
2026-04-07 00:17:51 +08:00
|
|
|
|
|
|
|
|
|
|
## 当前实现边界
|
|
|
|
|
|
|
2026-04-10 16:55:33 +08:00
|
|
|
|
- 这里只执行单个 request,不负责 request 排序。
|
|
|
|
|
|
- 这里只消费 request 上已经挂好的 sequence / sub-request,不负责为 Editor 自动生成这些附加阶段。
|
|
|
|
|
|
- `RenderPassSequence` 的生命周期由 request 拥有方管理;当前实现不会在一次 `Render()` 结束后主动销毁这些 sequence。
|
|
|
|
|
|
|
|
|
|
|
|
## 公开方法
|
|
|
|
|
|
|
|
|
|
|
|
| 方法 | 说明 |
|
|
|
|
|
|
|------|------|
|
|
|
|
|
|
| [Constructor](Constructor.md) | 构造执行器,并决定主管线与 builtin pass 的初始来源。 |
|
|
|
|
|
|
| [Destructor](Destructor.md) | 关闭当前主管线与 builtin pass。 |
|
|
|
|
|
|
| [SetPipeline](SetPipeline.md) | 直接替换 runtime `RenderPipeline`。 |
|
|
|
|
|
|
| [SetPipelineAsset](SetPipelineAsset.md) | 通过 `RenderPipelineAsset` 重建当前主管线。 |
|
|
|
|
|
|
| [SetObjectIdPass](SetObjectIdPass.md) | 替换 object-id pass。 |
|
|
|
|
|
|
| [SetDepthOnlyPass](SetDepthOnlyPass.md) | 替换 depth-only pass。 |
|
|
|
|
|
|
| [SetShadowCasterPass](SetShadowCasterPass.md) | 替换 shadow-caster 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) | 执行一次完整的单相机 request。 |
|
2026-04-07 00:17:51 +08:00
|
|
|
|
|
|
|
|
|
|
## 相关文档
|
|
|
|
|
|
|
|
|
|
|
|
- [Execution](../Execution.md)
|
|
|
|
|
|
- [SceneRenderer](../SceneRenderer/SceneRenderer.md)
|
|
|
|
|
|
- [CameraRenderRequest](../../Planning/CameraRenderRequest/CameraRenderRequest.md)
|
|
|
|
|
|
- [RenderSceneExtractor](../../Extraction/RenderSceneExtractor/RenderSceneExtractor.md)
|
2026-04-10 16:55:33 +08:00
|
|
|
|
- [BuiltinForwardPipeline](../../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md)
|
|
|
|
|
|
- [BuiltinObjectIdPass](../../Passes/BuiltinObjectIdPass/BuiltinObjectIdPass.md)
|
2026-04-07 00:17:51 +08:00
|
|
|
|
- [BuiltinDepthOnlyPass](../../Passes/BuiltinDepthOnlyPass/BuiltinDepthOnlyPass.md)
|
|
|
|
|
|
- [BuiltinShadowCasterPass](../../Passes/BuiltinShadowCasterPass/BuiltinShadowCasterPass.md)
|