docs(rendering): realign api docs to module structure

This commit is contained in:
2026-04-10 16:55:33 +08:00
parent 8cde4e0649
commit 4d8a51aee2
95 changed files with 1136 additions and 1585 deletions

View File

@@ -0,0 +1,38 @@
# RenderResourceCache::GetOrCreateBufferView
**命名空间**: `XCEngine::Rendering`
**类型**: `method`
**头文件**: `XCEngine/Rendering/Caches/RenderResourceCache.h`
## 签名
```cpp
const CachedBufferView* GetOrCreateBufferView(
RHI::RHIDevice* device,
RHI::RHIBuffer* buffer,
RHI::ResourceViewType viewType,
const RHI::ResourceViewDesc& viewDesc);
```
## 作用
为任意 buffer 描述获取或创建可复用的 resource view 缓存。
## 当前实现行为
- `device == nullptr``buffer == nullptr` 时直接返回 `nullptr`
-`buffer + viewType + viewDesc` 组合构建缓存 key
- 命中时直接返回已有 `CachedBufferView`
- 未命中时按 `viewType` 创建 SRV 或 UAV其他 view 类型当前直接失败
## 关键语义
- 这个接口解决的是“同一 buffer 上相同 view 反复创建”的重复开销,而不是 buffer 本身的上传。
- 当前只缓存 view不接管 buffer 的生命周期。
## 相关文档
- [RenderResourceCache](RenderResourceCache.md)
- [GetOrCreateVolumeField](GetOrCreateVolumeField.md)

View File

@@ -33,11 +33,11 @@ const CachedMesh* GetOrCreateMesh(RHI::RHIDevice* device, const Resources::Mesh*
- 缓存键是资源指针身份不是资源内容摘要mesh 内容后续被修改时,这里不会自动失效或重建。
- 返回的是缓存内部对象地址;调用 [Shutdown](Shutdown.md) 或析构后这些地址会失效。
- 当前主消费者是 [BuiltinForwardPipeline](../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md) 的 `DrawVisibleItem(...)` 路径。
- 当前主消费者是 [BuiltinForwardPipeline](../../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md) 的 `DrawVisibleItem(...)` 路径。
## 相关文档
- [RenderResourceCache](RenderResourceCache.md)
- [GetOrCreateTexture](GetOrCreateTexture.md)
- [Shutdown](Shutdown.md)
- [BuiltinForwardPipeline](../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md)
- [BuiltinForwardPipeline](../../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md)

View File

@@ -34,11 +34,11 @@ const CachedTexture* GetOrCreateTexture(RHI::RHIDevice* device, const Resources:
- 虽然 `TextureType` 会被映射到多个 RHI texture type但当前上传路径仍把 `arraySize` 固定为 `1`SRV 维度也固定为 `Texture2D`
- 缓存同样不会因为纹理内容变化而自动失效。
- 当前主消费者是 [BuiltinForwardPipeline](../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md) 中解析 base-color 纹理的材质路径。
- 当前主消费者是 [BuiltinForwardPipeline](../../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md) 中解析 base-color 纹理的材质路径。
## 相关文档
- [RenderResourceCache](RenderResourceCache.md)
- [GetOrCreateMesh](GetOrCreateMesh.md)
- [Shutdown](Shutdown.md)
- [BuiltinForwardPipeline](../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md)
- [BuiltinForwardPipeline](../../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md)

View File

@@ -0,0 +1,42 @@
# RenderResourceCache::GetOrCreateVolumeField
**命名空间**: `XCEngine::Rendering`
**类型**: `method`
**头文件**: `XCEngine/Rendering/Caches/RenderResourceCache.h`
## 签名
```cpp
const CachedVolumeField* GetOrCreateVolumeField(
RHI::RHIDevice* device,
const Resources::VolumeField* volumeField);
```
## 作用
`VolumeField` 的 payload 上传成 storage buffer并返回可复用的 structured-buffer 视图缓存。
## 当前实现行为
- `device == nullptr``volumeField == nullptr`、payload 为空或 `volumeField->IsValid() == false` 时直接返回 `nullptr`
- 先按 `VolumeField*` 查缓存
- 未命中时调用 `UploadVolumeField(...)`
- 上传失败会清理临时对象并返回 `nullptr`
## 当前缓存结果
返回的 `CachedVolumeField` 目前包含:
- `payloadBuffer`
- `shaderResourceView`
- `elementStride`
- `elementCount`
- `payloadSize`
- `storageKind`
## 相关文档
- [RenderResourceCache](RenderResourceCache.md)
- [BuiltinVolumetricPass](../../Passes/BuiltinVolumetricPass/BuiltinVolumetricPass.md)

View File

@@ -6,33 +6,83 @@
**头文件**: `XCEngine/Rendering/Caches/RenderResourceCache.h`
**描述**: 负责把 `Mesh``Texture` 上传成 RHI 资源,并按资源指针缓存这些 GPU 副本
**描述**: 负责把 CPU 侧 mesh、texture、volume payload 与 buffer view 转成渲染阶段可复用的 GPU 资源缓存
## 概览
`RenderResourceCache` 是当前 builtin pipeline 与 depth/object-id pass 共享的 GPU 资源缓存
`RenderResourceCache` 解决的不是“资源怎么加载”,而是“已经加载好的资源怎样稳定映射成后端可直接消费的 GPU 对象”
当前定义两类缓存条目
当前它维护四类缓存:
- `CachedMesh`
- `CachedTexture`
- `CachedVolumeField`
- `CachedBufferView`
## 当前公开能力
这让 builtin forward、object-id、体积 pass 等不同渲染路径可以共享上传结果,而不必各自重复创建 buffer / SRV。
- `Shutdown()`
- `GetOrCreateMesh(...)`
- `GetOrCreateTexture(...)`
## 公开方法
| 方法 | 说明 |
|------|------|
| [Destructor](Destructor.md) | 析构时统一释放所有已缓存 GPU 资源。 |
| [Shutdown](Shutdown.md) | 主动清空全部缓存。 |
| [GetOrCreateMesh](GetOrCreateMesh.md) | 获取或创建 mesh 缓存。 |
| [GetOrCreateTexture](GetOrCreateTexture.md) | 获取或创建 texture 缓存。 |
| [GetOrCreateVolumeField](GetOrCreateVolumeField.md) | 获取或创建 volume payload 缓存。 |
| [GetOrCreateBufferView](GetOrCreateBufferView.md) | 获取或创建 buffer resource view 缓存。 |
## 缓存模型
### `CachedMesh`
保存顶点/索引 buffer 与对应 view并记录 `vertexCount``indexCount``vertexStride` 和索引位宽。
### `CachedTexture`
保存 GPU 纹理对象、SRV 以及最终尺寸。
### `CachedVolumeField`
`VolumeField` 的 payload 对齐到 4-byte word stride 后上传为 storage buffer并生成 structured-buffer SRV。
当前还会保留:
- `elementStride`
- `elementCount`
- `payloadSize`
- `storageKind`
### `CachedBufferView`
对任意 `RHIBuffer` + `ResourceViewDesc` 组合做 view 级复用,避免同一 buffer 上重复创建结构相同的 SRV/UAV。
## 当前实现语义
- mesh / texture / volume cache 以资源裸指针为 key。
- buffer view cache 以 `buffer + viewType + format + dimension + firstElement + elementCount + stride` 组合作为 key。
- 任何上传或 view 创建失败都会立即清理临时对象并返回 `nullptr`
- `Shutdown()` 会遍历四类缓存并显式调用底层 `Shutdown()` 后释放对象。
## 设计说明
把上传与缓存放在渲染层,而不是资源层,是一个很典型的引擎分层选择:
- 资源层可以继续只关心 CPU 侧资产生命周期
- 渲染层可以按具体 backend 和 pass 需求决定资源布局
- 新渲染路径只要遵守 `RenderResourceCache` 契约,就能复用既有上传结果
这和 Unity/Unreal 里“asset object”与“render resource”分离的思路是一致的。
## 当前实现边界
- cache key 仍是 `Mesh*` / `Texture*` 裸指针
- 当前没有版本号或自动失效机制。
- 目前没有版本号或脏标记,底层资源内容变化后不会自动失效
- 当前不是线程安全对象。
- texture 上传路径虽然已覆盖多种格式,但仍依赖当前 RHI 纹理创建约定。
- volume payload 当前统一按 4-byte word stride 构建 structured-buffer 视图。
## 相关文档
- [Caches](../Caches.md)
- [BuiltinForwardPipeline](../../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md)
- [BuiltinObjectIdPass](../../Passes/BuiltinObjectIdPass/BuiltinObjectIdPass.md)
- [BuiltinDepthStylePassBase](../../Passes/BuiltinDepthStylePassBase/BuiltinDepthStylePassBase.md)
- [BuiltinVolumetricPass](../../Passes/BuiltinVolumetricPass/BuiltinVolumetricPass.md)

View File

@@ -1,105 +0,0 @@
# CameraRenderRequest
**命名空间**: `XCEngine::Rendering`
**类型**: `struct`
**头文件**: `XCEngine/Rendering/Planning/CameraRenderRequest.h`
**描述**: 把一次单相机提交所需的场景、目标表面、shadow-caster / depth-only / object-id 子请求、清屏覆盖和可选 pass 序列打包成显式请求对象。
## 概览
`CameraRenderRequest` 是 [SceneRenderer](../SceneRenderer/SceneRenderer.md) 和 [CameraRenderer](../CameraRenderer/CameraRenderer.md) 之间的主要数据契约。它本身不执行渲染,只负责描述“这一台相机这次要怎么提交”:
- 主场景渲染所需的 `scene``camera``context``surface`
- 可选的 depth-only / shadow-caster scene pass 子请求
- 可选的 object-id 辅助输出 `objectId`
- 多相机排序和清屏覆盖字段
- 主场景前后与最终叠加阶段要执行的可选 pass 序列
Editor Scene View 的网格和选中轮廓,当前由 editor 侧先组装进 `postScenePasses` / `overlayPasses`,再随 request 一起交给 [CameraRenderer](../CameraRenderer/CameraRenderer.md) 执行。
## 核心字段
| 字段 | 角色 |
|------|------|
| `scene` | 本次要提取可见物体的场景。 |
| `camera` | 本次渲染使用的相机组件。 |
| `context` | 当前帧的 RHI 上下文。 |
| `surface` | 主颜色输出目标及其 render area。 |
| `depthOnly` | 可选的 depth-only scene pass 子请求。 |
| `shadowCaster` | 可选的 shadow-caster scene pass 子请求。 |
| `objectId` | 可选的 object-id 辅助输出。 |
| `cameraDepth` | 多相机排序辅助值。 |
| `cameraStackOrder` | `Base` / `Overlay` camera stack 的附加排序键。 |
| `clearFlags` | 回写到 `RenderSceneData::cameraData.clearFlags` 的覆盖值。 |
| `hasClearColorOverride` / `clearColorOverride` | 是否覆盖提取出的相机清屏色。 |
| `preScenePasses` | 主管线执行前的可选 `RenderPassSequence*`。 |
| `postScenePasses` | 主场景和 object-id 之后、overlay 之前执行的可选 `RenderPassSequence*`。 |
| `overlayPasses` | 最后叠加到主颜色目标上的可选 `RenderPassSequence*`。 |
## `depthOnly` / `shadowCaster`
`depthOnly``shadowCaster` 当前都是 [ScenePassRenderRequest](ScenePassRenderRequest/ScenePassRenderRequest.md) 的类型别名,用来描述“是否要在主 `RenderPipeline` 之前额外执行一次 scene pass 重绘”。
- [IsRequested](ScenePassRenderRequest/IsRequested.md) 只检查 `surface` 是否真的挂了颜色附件。
- [IsValid](ScenePassRenderRequest/IsValid.md) 进一步要求第一张颜色附件非空、深度附件非空且 render area 宽高都大于 `0`
-`engine/src/Rendering/CameraRenderer.cpp` 的当前实现,`CameraRenderer::Render()` 会先执行 `shadowCaster`,再执行 `depthOnly`,之后才进入主 `RenderPipeline`
## `objectId`
`objectId` 是一个 [ObjectIdRenderRequest](ObjectIdRenderRequest/ObjectIdRenderRequest.md),用于描述“是否要额外输出一张 object-id 辅助表面”。
- `IsRequested()` 只检查 `surface` 是否真的挂了颜色附件。
- `IsValid()` 进一步要求:
- 第一张颜色附件非空
- 深度附件非空
- render area 宽高大于 `0`
`engine/src/Rendering/CameraRenderer.cpp` 的当前实现,`CameraRenderer::Render()` 会在主场景主管线之后、`postScenePasses` 之前执行当前的 [ObjectIdPass](../ObjectIdPass/ObjectIdPass.md)。
## pass 序列字段
`preScenePasses``postScenePasses``overlayPasses` 都是非拥有指针。调用方需要保证这些序列在本次 `Render()` 完成前保持有效。
- `preScenePasses` 适合放主场景之前的准备阶段。
- `postScenePasses` 适合放主场景和 object-id 之后的附加绘制。
- `overlayPasses` 适合放最后叠加到主颜色目标上的编辑器覆盖层。
Editor Scene View 当前会先通过 [SceneViewportRenderPlan](../../Editor/Viewport/SceneViewportRenderPlan/SceneViewportRenderPlan.md) 组装一份 plan再由 [ApplySceneViewportRenderPlan](../../Editor/Viewport/SceneViewportRenderPlan/ApplySceneViewportRenderPlan.md) 和 [ViewportHostRenderFlowUtils](../../Editor/Viewport/ViewportHostRenderFlowUtils/ViewportHostRenderFlowUtils.md) 把:
- `objectId`
- `postScenePasses`
- `overlayPasses`
- clear-color override
写回到这份 request。
## 当前数据契约
- [IsValid](IsValid.md) 只检查 `scene``camera``context`,不会验证 `surface``shadowCaster``depthOnly``objectId` 是否完整。
- `CameraRenderer::Render()` 会额外拒绝:
- `surface` 的 render area 宽高为 `0`
- `shadowCaster.IsRequested()``shadowCaster.IsValid()` 为假
- `depthOnly.IsRequested()``depthOnly.IsValid()` 为假
- `objectId.IsRequested()``objectId.IsValid()` 为假
- `SceneRenderer::Render(const std::vector<CameraRenderRequest>&)` 会先检查每条 request 的 `IsValid()`,再按 `cameraStackOrder``cameraDepth` 排序后逐条提交。
## 真实使用位置
- `SceneRenderer` 负责构建和排序多个 `CameraRenderRequest`
- Editor Scene View 当前通过 [SceneViewportRenderPlan](../../Editor/Viewport/SceneViewportRenderPlan/SceneViewportRenderPlan.md) 组装 `postScenePasses``overlayPasses` 与 clear override并通过 [ViewportHostRenderFlowUtils](../../Editor/Viewport/ViewportHostRenderFlowUtils/ViewportHostRenderFlowUtils.md) 挂入 object-id surface。
- `tests/Rendering/unit/test_camera_scene_renderer.cpp` 明确验证了 `preScenePasses -> shadowCaster -> depthOnly -> pipeline -> objectId -> postScenePasses -> overlayPasses` 的真实执行顺序,以及 request clear override / 排序规则。
## 相关文档
- [IsValid](IsValid.md)
- [ScenePassRenderRequest](ScenePassRenderRequest/ScenePassRenderRequest.md)
- [ObjectIdRenderRequest](ObjectIdRenderRequest/ObjectIdRenderRequest.md)
- [CameraRenderer](../CameraRenderer/CameraRenderer.md)
- [SceneRenderer](../SceneRenderer/SceneRenderer.md)
- [RenderContext](../RenderContext/RenderContext.md)
- [RenderSurface](../RenderSurface/RenderSurface.md)
- [Passes](../Passes/Passes.md)

View File

@@ -1,109 +0,0 @@
# 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)

View File

@@ -1,73 +0,0 @@
# CameraRenderer::Constructor
**命名空间**: `XCEngine::Rendering`
**类型**: `constructor-overload group`
**头文件**: `XCEngine/Rendering/Execution/CameraRenderer.h`
## 签名
```cpp
CameraRenderer();
explicit CameraRenderer(std::unique_ptr<RenderPipeline> pipeline);
explicit CameraRenderer(std::shared_ptr<const RenderPipelineAsset> pipelineAsset);
CameraRenderer(
std::unique_ptr<RenderPipeline> pipeline,
std::unique_ptr<ObjectIdPass> objectIdPass,
std::unique_ptr<RenderPass> depthOnlyPass = nullptr,
std::unique_ptr<RenderPass> 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<RenderPipeline>` 重载
- 交由四参重载处理。
- 如果未显式提供 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<const RenderPipelineAsset>` 重载
- 先保存 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<const ...>` 共享持有,只作为 runtime pipeline 的创建来源。
## 相关文档
- [CameraRenderer](CameraRenderer.md)
- [SetPipeline](SetPipeline.md)
- [SetPipelineAsset](SetPipelineAsset.md)
- [SetObjectIdPass](SetObjectIdPass.md)
- [SetDepthOnlyPass](SetDepthOnlyPass.md)
- [SetShadowCasterPass](SetShadowCasterPass.md)

View File

@@ -1,32 +0,0 @@
# 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)

View File

@@ -1,83 +0,0 @@
# 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)

View File

@@ -1,35 +0,0 @@
# CameraRenderer::SetObjectIdPass
**命名空间**: `XCEngine::Rendering`
**类型**: `method`
**头文件**: `XCEngine/Rendering/Execution/CameraRenderer.h`
## 签名
```cpp
void SetObjectIdPass(std::unique_ptr<ObjectIdPass> 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)

View File

@@ -6,51 +6,94 @@
**头文件**: `XCEngine/Rendering/Execution/CameraRenderer.h`
**描述**: 单个 `CameraRenderRequest` 的执行器,负责在一次提交里串起 scene extraction、shadow/depth 预阶段、主管线、fullscreen 阶段,以及注入式 pre / post / overlay pass
**描述**: 单个 `CameraRenderRequest` 的执行器,负责把一份显式 request 变成稳定的逐阶段渲染流程
## 概览
`CameraRenderer`当前 Rendering 执行层里最核心的“单 request 执行器”
`CameraRenderer` Execution 层里最靠近“真正发起一次相机渲染”的类
它不负责决定有哪些相机会进入本次渲染;那属于 [Planning](../../Planning/Planning.md) 和 [SceneRenderer](../SceneRenderer/SceneRenderer.md) 的职责。它负责的是另一半:
- 使用 [RenderSceneExtractor](../../Extraction/RenderSceneExtractor/RenderSceneExtractor.md) 生成 `RenderSceneData`
- 按阶段执行 `shadowCaster``depthOnly`、主管线、`postProcess``finalOutput``objectId`
- 消费调用方注入的 `preScenePasses``postScenePasses``overlayPasses`
它不负责决定应该渲染哪些相机,也不负责 request 排序;这些职责在 [Planning](../../Planning/Planning.md) 和 [SceneRenderer](../SceneRenderer/SceneRenderer.md)
它负责的是另一半:把一份已经构造好的 `CameraRenderRequest` 按当前引擎约定的阶段顺序完整跑完。
## 当前持有对象
- `m_sceneExtractor`
负责把 `Scene + Camera` 压成 `RenderSceneData`
- `m_pipelineAsset`
当前主管线的创建来源;为空时表示直接持有 runtime pipeline。
- `m_pipeline`
真正执行主场景绘制的 [RenderPipeline](../../RenderPipeline/RenderPipeline.md)。
- `m_objectIdPass`
object-id 输出阶段使用的 `RenderPass`
- `m_depthOnlyPass`
depth-only 阶段使用的 `RenderPass`
- `m_shadowCasterPass`
shadow-caster 阶段使用的 `RenderPass`
- `m_directionalShadowSurface`
当 request 只提供 `DirectionalShadowRenderPlan`、而没有显式 `shadowCaster.surface` 时,按需生成阴影贴图 surface。
- `m_postProcessSurfaceCache`
- `m_finalOutputSurfaceCache`
fullscreen 阶段多 pass 链使用的中间 surface cache。
## 当前执行顺序
对一份有效 request当前主顺序是
`CameraRenderer::Render(...)` 会按 `kOrderedCameraFrameStages` 依次执行
1. 校验 request 与 surface 前置条件
2. 解析 shadow surface 与 `RenderSceneData`
3. 执行 `preScenePasses`
4. 执行 `shadowCaster`
5. 执行 `depthOnly`
6. 执行 `m_pipeline->Render(...)`
7. 执行 `postProcess`
8. 执行 `finalOutput`
9. 执行 `objectId`
10. 执行 `postScenePasses`
11. 执行 `overlayPasses`
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。
## 设计要点
### 为什么这里坚持“显式阶段链”
这和 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 接线方式。
## 当前实现边界
- 只执行单个 request不负责 request 排序。
- 它会消费 `DirectionalShadowRenderPlan``PostProcessRenderRequest``FinalOutputRenderRequest`,因此比旧版 `CameraRenderer` 更完整
- 它不自己规划 Editor 的 Scene View pass那仍由 Editor 层先写回 request
- 这里只执行单个 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。 |
## 相关文档
@@ -58,8 +101,7 @@
- [SceneRenderer](../SceneRenderer/SceneRenderer.md)
- [CameraRenderRequest](../../Planning/CameraRenderRequest/CameraRenderRequest.md)
- [RenderSceneExtractor](../../Extraction/RenderSceneExtractor/RenderSceneExtractor.md)
- [RenderPipeline](../../RenderPipeline/RenderPipeline.md)
- [BuiltinForwardPipeline](../../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md)
- [BuiltinObjectIdPass](../../Passes/BuiltinObjectIdPass/BuiltinObjectIdPass.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)

View File

@@ -0,0 +1,62 @@
# CameraRenderer::CameraRenderer
**命名空间**: `XCEngine::Rendering`
**类型**: `constructor overload set`
**头文件**: `XCEngine/Rendering/Execution/CameraRenderer.h`
## 签名
```cpp
CameraRenderer();
explicit CameraRenderer(std::unique_ptr<RenderPipeline> pipeline);
explicit CameraRenderer(std::shared_ptr<const RenderPipelineAsset> pipelineAsset);
CameraRenderer(
std::unique_ptr<RenderPipeline> pipeline,
std::unique_ptr<RenderPass> objectIdPass,
std::unique_ptr<RenderPass> depthOnlyPass = nullptr,
std::unique_ptr<RenderPass> shadowCasterPass = nullptr);
```
## 当前构造路径
- 默认构造
回退到静态共享的 `BuiltinForwardPipelineAsset`,并建立 builtin object-id / depth-only / shadow-caster pass 与 fullscreen surface cache。
- `std::unique_ptr<RenderPipeline>` 重载
接管外部传入的 runtime pipeline并对三个独立 pass 使用 builtin 默认实现。
- `std::shared_ptr<const RenderPipelineAsset>` 重载
保存 asset再通过 [SetPipelineAsset](SetPipelineAsset.md) 创建当前 runtime pipeline。
- 完整重载
允许同时注入 pipeline 和三类独立 `RenderPass`;任一 pass 传空时都会回退到对应 builtin 实现。
## 回退规则
- `objectIdPass == nullptr` 时,回退到 `Passes::BuiltinObjectIdPass`
- `depthOnlyPass == nullptr` 时,回退到 `Passes::BuiltinDepthOnlyPass`
- `shadowCasterPass == nullptr` 时,回退到 `Passes::BuiltinShadowCasterPass`
- `pipeline == nullptr` 时,`ResetPipeline(...)` 会继续回退到默认 `BuiltinForwardPipelineAsset`
## 生命周期
- `RenderPipeline` 与三个独立 pass 都由 `CameraRenderer` 通过 `std::unique_ptr` 独占持有。
- `RenderPipelineAsset` 通过 `std::shared_ptr<const ...>` 共享持有,只用来派生 runtime pipeline。
- 构造函数还会准备 `DirectionalShadowSurfaceCache` / `FullscreenPassSurfaceCache` 所需的成员槽位,使后续帧内阶段切换不必重新分配整个执行器。
## 设计说明
这组重载同时覆盖两种接线方式:
- 上层已经准备好 runtime pipeline直接注入执行器
- 上层只声明 pipeline asset让执行器按当前默认规则创建 runtime pipeline
这让运行时、测试和编辑器都能复用同一套单相机执行器,而不会把“如何创建主管线”写散在多个调用方里。
## 相关文档
- [CameraRenderer](CameraRenderer.md)
- [SetPipeline](SetPipeline.md)
- [SetPipelineAsset](SetPipelineAsset.md)
- [SetObjectIdPass](SetObjectIdPass.md)
- [SetDepthOnlyPass](SetDepthOnlyPass.md)
- [SetShadowCasterPass](SetShadowCasterPass.md)

View File

@@ -1,4 +1,4 @@
# CameraRenderer::~CameraRenderer
# CameraRenderer::~CameraRenderer
**命名空间**: `XCEngine::Rendering`

View File

@@ -1,4 +1,4 @@
# CameraRenderer::GetDepthOnlyPass
# CameraRenderer::GetDepthOnlyPass
**命名空间**: `XCEngine::Rendering`

View File

@@ -0,0 +1,33 @@
# CameraRenderer::GetObjectIdPass
**命名空间**: `XCEngine::Rendering`
**类型**: `method`
**头文件**: `XCEngine/Rendering/Execution/CameraRenderer.h`
## 签名
```cpp
RenderPass* GetObjectIdPass() const;
```
## 作用
返回当前 object-id 阶段使用的非拥有 `RenderPass*`
## 当前实现行为
- 这是头文件内联访问器,直接返回 `m_objectIdPass.get()`
- 不转移所有权,也不会增加引用计数。
## 注意事项
- 调用 [SetObjectIdPass](SetObjectIdPass.md) 后,之前取到的裸指针可能立即失效。
- 返回值的动态类型通常是 `Passes::BuiltinObjectIdPass`,但也可以是调用方注入的其他 `RenderPass` 实现。
## 相关文档
- [SetObjectIdPass](SetObjectIdPass.md)
- [Render](Render.md)
- [CameraRenderer](CameraRenderer.md)

View File

@@ -1,4 +1,4 @@
# CameraRenderer::GetPipeline
# CameraRenderer::GetPipeline
**命名空间**: `XCEngine::Rendering`

View File

@@ -1,4 +1,4 @@
# CameraRenderer::GetPipelineAsset
# CameraRenderer::GetPipelineAsset
**命名空间**: `XCEngine::Rendering`

View File

@@ -1,4 +1,4 @@
# CameraRenderer::GetShadowCasterPass
# CameraRenderer::GetShadowCasterPass
**命名空间**: `XCEngine::Rendering`

View File

@@ -0,0 +1,66 @@
# CameraRenderer::Render
**命名空间**: `XCEngine::Rendering`
**类型**: `method`
**头文件**: `XCEngine/Rendering/Execution/CameraRenderer.h`
## 签名
```cpp
bool Render(const CameraRenderRequest& request);
```
## 行为说明
执行一次完整的单相机 request。
## 当前验证规则
进入真正执行前,当前实现会拒绝以下情况:
- `!request.IsValid()`
- `m_pipeline == nullptr`
- `request.GetMainSceneSurface()` 的 render area 宽或高为 `0`
- `depthOnly` 被请求但 `depthOnly.IsValid()` 为假
- `postProcess` 被请求但 `postProcess.IsValid()` 为假
- `finalOutput` 被请求但 `finalOutput.IsValid()` 为假
- `objectId` 被请求但 `objectId.IsValid()` 为假
- `shadowCaster` 显式被请求但无效,或 `directionalShadow` 无法成功解析出内部阴影 surface
## 当前执行流程
1. 通过 `ResolveShadowCasterRequest(...)` 解析真实的 shadow-caster 输入
2.`request.GetMainSceneSurface()` 的 render area 调用 `m_sceneExtractor.ExtractForCamera(...)`
3. 回写 `sceneData.cameraData.clearFlags`
4. 按需写入 clear-color override
5. 如果 `request.directionalShadow.IsValid()`,把阴影数据写入 `sceneData.lighting.mainDirectionalShadow`
6. 根据相机 skybox 配置构建 `sceneData.environment`
7.`kOrderedCameraFrameStages` 顺序依次执行各阶段
## fullscreen 阶段语义
`PostProcess``FinalOutput` 都通过 `RenderPassSequence` 执行:
- 当 sequence 只有一个 pass 时,直接读源 surface、写目标 surface
- 当 sequence 有多个 pass 时,会复用 `FullscreenPassSurfaceCache` 提供的中间 surface
- `PostProcess``FinalOutput` 各自持有独立的中间 cache避免状态串扰
## 设计说明
把 object-id、fullscreen、overlay 都放进这条执行链,意味着“单相机一帧的完整输出”在这里有唯一真相。
这比让不同模块各自绕开主管线单独提交一遍更稳定,也更容易做测试。
## 返回值
- 整条 request 成功执行时返回 `true`
- 任一验证、提取或阶段执行失败时返回 `false`
## 相关文档
- [CameraRenderer](CameraRenderer.md)
- [CameraRenderRequest](../../Planning/CameraRenderRequest/CameraRenderRequest.md)
- [SceneRenderer](../SceneRenderer/SceneRenderer.md)
- [RenderSceneExtractor](../../Extraction/RenderSceneExtractor/RenderSceneExtractor.md)
- [RenderPipeline::Render](../../RenderPipeline/Render.md)

View File

@@ -1,4 +1,4 @@
# CameraRenderer::SetDepthOnlyPass
# CameraRenderer::SetDepthOnlyPass
**命名空间**: `XCEngine::Rendering`
@@ -20,7 +20,7 @@ void SetDepthOnlyPass(std::unique_ptr<RenderPass> depthOnlyPass);
1. 如果旧 `m_depthOnlyPass` 非空,先调用它的 `Shutdown()`
2. 接管新的 `depthOnlyPass`
3. 如果新指针为空,则自动回退到 [Passes::BuiltinDepthOnlyPass](../Passes/BuiltinDepthOnlyPass/BuiltinDepthOnlyPass.md)。
3. 如果新指针为空,则自动回退到 [Passes::BuiltinDepthOnlyPass](../../Passes/BuiltinDepthOnlyPass/BuiltinDepthOnlyPass.md)。
## 关键语义
@@ -32,5 +32,5 @@ void SetDepthOnlyPass(std::unique_ptr<RenderPass> depthOnlyPass);
- [GetDepthOnlyPass](GetDepthOnlyPass.md)
- [Render](Render.md)
- [BuiltinDepthOnlyPass](../Passes/BuiltinDepthOnlyPass/BuiltinDepthOnlyPass.md)
- [BuiltinDepthOnlyPass](../../Passes/BuiltinDepthOnlyPass/BuiltinDepthOnlyPass.md)

View File

@@ -0,0 +1,35 @@
# CameraRenderer::SetObjectIdPass
**命名空间**: `XCEngine::Rendering`
**类型**: `method`
**头文件**: `XCEngine/Rendering/Execution/CameraRenderer.h`
## 签名
```cpp
void SetObjectIdPass(std::unique_ptr<RenderPass> objectIdPass);
```
## 作用
替换当前 object-id 阶段使用的独立 `RenderPass` 实例。
## 当前实现行为
1. 如果旧 `m_objectIdPass` 非空,先调用 `Shutdown()`
2. 接管新的 `objectIdPass`
3. 如果传入空指针,则自动回退到 `Passes::BuiltinObjectIdPass`
## 关键语义
- 这里接收的是通用 `RenderPass`,不是已经移除的专用 `ObjectIdPass` 基类。
- `CameraRenderer::Render()` 只有在 `request.objectId.IsRequested()` 为真时才会执行这里持有的 pass。
- 该指针的所有权完全转移给 `CameraRenderer`;调用方不再负责释放。
## 相关文档
- [GetObjectIdPass](GetObjectIdPass.md)
- [Render](Render.md)
- [BuiltinObjectIdPass](../../Passes/BuiltinObjectIdPass/BuiltinObjectIdPass.md)

View File

@@ -1,4 +1,4 @@
# CameraRenderer::SetPipeline
# CameraRenderer::SetPipeline
**命名空间**: `XCEngine::Rendering`

View File

@@ -1,4 +1,4 @@
# CameraRenderer::SetPipelineAsset
# CameraRenderer::SetPipelineAsset
**命名空间**: `XCEngine::Rendering`

View File

@@ -1,4 +1,4 @@
# CameraRenderer::SetShadowCasterPass
# CameraRenderer::SetShadowCasterPass
**命名空间**: `XCEngine::Rendering`
@@ -20,7 +20,7 @@ void SetShadowCasterPass(std::unique_ptr<RenderPass> shadowCasterPass);
1. 如果旧 `m_shadowCasterPass` 非空,先调用它的 `Shutdown()`
2. 接管新的 `shadowCasterPass`
3. 如果新指针为空,则自动回退到 [Passes::BuiltinShadowCasterPass](../Passes/BuiltinShadowCasterPass/BuiltinShadowCasterPass.md)。
3. 如果新指针为空,则自动回退到 [Passes::BuiltinShadowCasterPass](../../Passes/BuiltinShadowCasterPass/BuiltinShadowCasterPass.md)。
## 关键语义
@@ -32,5 +32,5 @@ void SetShadowCasterPass(std::unique_ptr<RenderPass> shadowCasterPass);
- [GetShadowCasterPass](GetShadowCasterPass.md)
- [Render](Render.md)
- [BuiltinShadowCasterPass](../Passes/BuiltinShadowCasterPass/BuiltinShadowCasterPass.md)
- [BuiltinShadowCasterPass](../../Passes/BuiltinShadowCasterPass/BuiltinShadowCasterPass.md)

View File

@@ -6,33 +6,34 @@
**头文件目录**: `engine/include/XCEngine/Rendering/Execution/`
**描述**: Rendering 执行层,负责把已经规划好的 `CameraRenderRequest` 真正跑过 scene extraction、shadow/depth 预阶段、主管线、fullscreen 阶段与注入式 pass 序列。
**描述**: Rendering 执行层,负责把已经规划好的 `CameraRenderRequest` 真正跑过 scene extraction、主场景管线、fullscreen 阶段与注入式 pass 序列。
## 概览
`Execution` 是当前 Rendering 主链里最接近“真正执行渲染”的一层。
`Execution` 和 [Planning](../Planning/Planning.md) 的分工是当前渲染架构里最重要的边界之一:
它和 [Planning](../Planning/Planning.md) 的边界很明确:
- `Planning` 决定这帧有哪些 request、它们的排序、clear 规则和基础 surface。
- `Execution` 决定单个 request 以什么阶段顺序被真正执行。
- `Planning` 决定“有哪些 request、顺序是什么”
- `Execution` 决定“单个 request 如何被真正执行”
这种拆法很接近商业引擎里常见的 camera render loop 设计。好处是 camera 选择、编辑器附加阶段、post-process 链和主管线执行不会揉成一个难以维护的大类。
当前这一层包含两个核心入口:
## 当前模块内容
- [CameraRenderer](CameraRenderer/CameraRenderer.md)
单个 `CameraRenderRequest` 的执行器。
- [SceneRenderer](SceneRenderer/SceneRenderer.md)
场景级执行入口,负责把 planner 产出的 request 进一步补全成可执行链,并调度 `CameraRenderer`
## 当前职责
- 执行单个 `CameraRenderRequest`
- 执行 request 数组
- 在执行前调用 [Extraction](../Extraction/Extraction.md) 生成 `RenderSceneData`
- 调度 shadow-caster、depth-only、main-scene、post-process、final-output、object-id、post-scene 与 overlay 阶段
- 执行 `PreScenePasses -> ShadowCaster -> DepthOnly -> MainScene -> PostProcess -> FinalOutput -> ObjectId -> PostScenePasses -> OverlayPasses`
- 在真正提交前调用 [Extraction](../Extraction/Extraction.md) 生成 `RenderSceneData`
- 管理 fullscreen pass 需要的中间 surface cache
- 保持单 request 执行和多 request 编排之间的职责边界清晰
## 相关文档
- [Rendering](../Rendering.md)
- [Planning](../Planning/Planning.md)
- [FrameData](../FrameData/FrameData.md)
- [Extraction](../Extraction/Extraction.md)
- [FrameData](../FrameData/FrameData.md)

View File

@@ -0,0 +1,65 @@
# SceneRenderer::BuildRenderRequests
**命名空间**: `XCEngine::Rendering`
**类型**: `method`
**头文件**: `XCEngine/Rendering/Execution/SceneRenderer.h`
## 签名
```cpp
std::vector<CameraRenderRequest> BuildRenderRequests(
const Components::Scene& scene,
Components::CameraComponent* overrideCamera,
const RenderContext& context,
const RenderSurface& surface);
```
## 行为说明
基于当前场景生成一组“可以立即执行”的 `CameraRenderRequest`
## 当前流程
1. 调用 `m_requestPlanner.BuildRequests(...)` 生成基础 request
2. 调用 `ResolveCameraFinalColorPolicies(...)`,把 pipeline 默认值和相机 override 合并成 `request.finalColorPolicy`
3. 调用 `AttachFullscreenStageRequests(...)`
4. 返回最终 request 数组
## fullscreen 阶段补全规则
`AttachFullscreenStageRequests(...)` 当前会:
- 为每个 request 按需构建 post-process sequence
- 为每个 request 按需构建 final-output sequence
- 为这些 sequence 分配 `FullscreenPassSurfaceCache`
-`sourceSurface``destinationSurface``sourceColorView``passes` 写回 request
但并不是所有 request 都会成功挂上 fullscreen 阶段。当前会跳过这些情况:
- `request.camera == nullptr`
- `request.context.device == nullptr`
- `request.surface` 没有有效颜色目标
- post-process 和 final-output 都为空
- 主颜色 surface 是多重采样
- 颜色格式未知
- 中间 surface cache 创建失败
## 为什么这里不是纯 planner
`BuildRenderRequests(...)` 已经不只是“收集相机并填基础字段”,它还会分配执行阶段真正需要的临时资源。
因此它必须位于 `SceneRenderer`,而不是继续下沉到 planner 层。
## 返回值
- 一组已完成基础规划、final-color 解析和 fullscreen 阶段补全的 request
- 如果当前场景没有可用相机,结果可能为空
## 相关文档
- [SceneRenderer](SceneRenderer.md)
- [Render](Render.md)
- [SceneRenderRequestPlanner](../../Planning/SceneRenderRequestPlanner/SceneRenderRequestPlanner.md)
- [CameraRenderRequest](../../Planning/CameraRenderRequest/CameraRenderRequest.md)
- [FinalColorSettings](../../Planning/FinalColorSettings/FinalColorSettings.md)

View File

@@ -0,0 +1,40 @@
# SceneRenderer::SceneRenderer
**命名空间**: `XCEngine::Rendering`
**类型**: `constructor`
**头文件**: `XCEngine/Rendering/Execution/SceneRenderer.h`
## 签名
```cpp
SceneRenderer();
explicit SceneRenderer(std::unique_ptr<RenderPipeline> pipeline);
explicit SceneRenderer(std::shared_ptr<const RenderPipelineAsset> pipelineAsset);
```
## 行为说明
构造场景级执行入口。
## 当前构造行为
- 默认构造
使用默认构造的 `CameraRenderer`,也就是默认 builtin forward 管线接线。
- `std::unique_ptr<RenderPipeline>` 重载
把外部传入的 runtime pipeline 交给内部 `m_cameraRenderer`
- `std::shared_ptr<const RenderPipelineAsset>` 重载
把 asset 交给内部 `m_cameraRenderer`,由它创建 runtime pipeline。
## 设计说明
`SceneRenderer` 自己不直接创建 pipeline而是把这件事继续委托给 `CameraRenderer`
这样所有“主管线如何创建 / 如何回退”的规则都只在单 request 执行器里维护一份。
## 相关文档
- [SceneRenderer](SceneRenderer.md)
- [CameraRenderer](../CameraRenderer/CameraRenderer.md)
- [SetPipeline](SetPipeline.md)
- [SetPipelineAsset](SetPipelineAsset.md)

View File

@@ -0,0 +1,67 @@
# SceneRenderer::Render
**命名空间**: `XCEngine::Rendering`
**类型**: `method overload set`
**头文件**: `XCEngine/Rendering/Execution/SceneRenderer.h`
## 签名
```cpp
bool Render(const CameraRenderRequest& request);
bool Render(const std::vector<CameraRenderRequest>& requests);
bool Render(
const Components::Scene& scene,
Components::CameraComponent* overrideCamera,
const RenderContext& context,
const RenderSurface& surface);
```
## 行为说明
执行单条 request、执行 request 数组,或从场景直接生成并执行。
## 各重载的当前语义
### `Render(const CameraRenderRequest& request)`
直接转发给 `m_cameraRenderer.Render(request)`
### `Render(const std::vector<CameraRenderRequest>& requests)`
当前会:
1. 拒绝空数组
2. 拒绝任一 `!request.IsValid()` 的输入
3. 复制一份请求数组
4. 调用 `SceneRenderRequestUtils::SortCameraRenderRequests(...)` 做稳定排序
5. 逐条交给 `m_cameraRenderer.Render(...)`
6. 在每条 request 成功后,回写自己持有的 fullscreen surface 状态
这里的“状态回写”很关键。因为 `SceneRenderer` 可能为本帧生成了中间 fullscreen surface如果不在 request 之间同步颜色状态,多相机链路就可能拿到错误的 `ResourceStates`
### `Render(scene, overrideCamera, context, surface)`
等价于:
```cpp
return Render(BuildRenderRequests(scene, overrideCamera, context, surface));
```
## 设计说明
即使调用方手工构造了 request 数组,`SceneRenderer` 仍然会再次排序。
这不是多余而是为了保证“camera stack / depth 规则”只有一份权威定义,不依赖每个调用方自己记住顺序约定。
## 返回值
- 至少成功执行一条 request 时返回 `true`
- 空输入、无效 request 或任一 request 执行失败时返回 `false`
## 相关文档
- [SceneRenderer](SceneRenderer.md)
- [BuildRenderRequests](BuildRenderRequests.md)
- [CameraRenderer](../CameraRenderer/CameraRenderer.md)
- [SceneRenderRequestUtils](../../Planning/SceneRenderRequestUtils/SceneRenderRequestUtils.md)

View File

@@ -6,45 +6,69 @@
**头文件**: `XCEngine/Rendering/Execution/SceneRenderer.h`
**描述**: 场景级渲染编排入口,负责构建并补全 `CameraRenderRequest`包括 final-color policy、fullscreen post-process/final-output 子请求,再把请求转交给 [CameraRenderer](../CameraRenderer/CameraRenderer.md) 执行。
**描述**: 场景级执行入口,负责构建或接收 `CameraRenderRequest`补齐 fullscreen 阶段请求,再交给 [CameraRenderer](../CameraRenderer/CameraRenderer.md) 执行。
## 概览
`SceneRenderer` 当前是执行层的外层编排器。
`SceneRenderer` Rendering 执行层的外层编排器。
维护两块公开可见的核心运行时对象
一方面承接 [SceneRenderRequestPlanner](../../Planning/SceneRenderRequestPlanner/SceneRenderRequestPlanner.md) 的结果,另一方面又比纯 planner 多做了一层“执行前补全”
- 解析每个相机的 `FinalColorPolicy`
- 为 post-process / final-output 生成 pass sequence
- 为 fullscreen 阶段分配中间 surface cache
所以它不只是“把 planner 的结果原样转发给 `CameraRenderer`”,而是执行层和规划层之间的桥。
## 当前持有对象
- `m_requestPlanner`
负责基础 request 生成。
- `m_cameraRenderer`
除此之外,它还维护每帧按 request 数量扩展的 owned fullscreen-stage 状态:
负责单 request 真正执行。
- `m_ownedPostProcessSequences`
- `m_ownedFinalOutputSequences`
- `m_ownedFullscreenStageSurfaces`
这些对象保存当前帧由 `SceneRenderer` 自己构建出来的 fullscreen 阶段资源。
这条拆分让 Rendering 主链明确分成两层:
## 当前职责
- `SceneRenderer` 负责“这次要渲染哪些 request、按什么顺序”
- `SceneRenderer` 还负责把每个 request 进一步补成“主场景颜色 -> post-process -> final-output”的完整链
- `CameraRenderer` 负责“单个 request 怎样被真正执行”
- `Scene + overrideCamera + surface` 生成 request 数组
- 为 request 解析最终输出策略
- 为 request 挂接 post-process / final-output 子请求
- 对 request 数组做稳定排序并逐条执行
- 维护自己创建的 fullscreen surface 的资源状态
## 当前公开能力
## 设计理念
- 构建 request 数组
- 执行单个 request
- 执行 request 数组
- 直接从 `Scene + overrideCamera + surface` 生成 request 并执行
- 为每个 request 解析 final-color policy
- 按相机 post-process / final-color 需求挂接 fullscreen-stage 子请求
### 为什么 fullscreen 链放在 `SceneRenderer`
planner 只该关心“这一帧有哪些相机 request”;
而 fullscreen pass sequence 和中间 render target 明显属于执行阶段的临时对象。
把这层逻辑放在 `SceneRenderer`,有两个直接好处:
- planner 仍然可以保持轻量、纯规则化
- `CameraRenderer` 仍然只处理“单条 request 如何执行”,不会反向承担 per-frame 资源编排
## 当前实现边界
- 不直接做 scene extraction
- 不直接操作主管线内部细节。
- `BuildRenderRequests(...)` 当前会先让 `SceneRenderRequestPlanner` 生成基础 request再调用 `ResolveCameraFinalColorPolicies(...)``AttachFullscreenStageRequests(...)` 做后处理补全。
- fullscreen-stage 只会在 request 同时具备 `camera`、有效 `device` 和有效颜色目标时挂接。
- 对手工提交的 request 数组,当前仍会再次按 stack / depth 做稳定排序。
- 不直接做 scene extraction;那属于 `CameraRenderer`
- 不直接参与主管线内部 draw-call 组织;那属于 `RenderPipeline`
- 对手工传入的 request 数组,仍然会再次稳定排序,以保持统一的 camera stack 语义
## 公开方法
| 方法 | 说明 |
|------|------|
| [Constructor](Constructor.md) | 构造场景级执行入口。 |
| [Destructor](Destructor.md) | 默认析构。 |
| [SetPipeline](SetPipeline.md) | 替换当前主管线实例。 |
| [SetPipelineAsset](SetPipelineAsset.md) | 通过 asset 重建主管线。 |
| [GetPipeline](GetPipeline.md) | 返回当前主管线的非拥有指针。 |
| [GetPipelineAsset](GetPipelineAsset.md) | 返回当前 pipeline asset 的非拥有指针。 |
| [BuildRenderRequests](BuildRenderRequests.md) | 生成并补齐当前帧 request 数组。 |
| [Render](Render.md) | 执行单个 request、request 数组,或从场景直接生成并执行。 |
## 相关文档
@@ -52,4 +76,4 @@
- [CameraRenderer](../CameraRenderer/CameraRenderer.md)
- [SceneRenderRequestPlanner](../../Planning/SceneRenderRequestPlanner/SceneRenderRequestPlanner.md)
- [SceneRenderRequestUtils](../../Planning/SceneRenderRequestUtils/SceneRenderRequestUtils.md)
- [Camera Request Planning And Clear Rules](../../../../_guides/Rendering/Camera-Request-Planning-And-Clear-Rules.md)
- [CameraRenderRequest](../../Planning/CameraRenderRequest/CameraRenderRequest.md)

View File

@@ -6,36 +6,87 @@
**头文件**: `XCEngine/Rendering/Extraction/RenderSceneExtractor.h`
**描述**: 把 `Scene` 压平成渲染侧可消费的 `RenderSceneData`,负责相机选择、环境与光照提取,以及网格 `visibleItems` 和体对象 `visibleVolumes` 收集
**描述**: 把场景对象树压平成执行层可直接消费的 `RenderSceneData`,负责相机选择、可见渲染项/体积项提取和光照快照构建
## 概览
`RenderSceneExtractor` 处在 `Scene``CameraRenderer` 之间
`RenderSceneExtractor` 是运行时场景语义和渲染提交语义之间的桥
它不负责发 draw call而是把 `Scene` 转换成一份更稳定的帧数据快照,供 [CameraRenderer](../../Execution/CameraRenderer/CameraRenderer.md) 和各类 builtin pass 消费。
当前公开三条入口
当前导出的 `RenderSceneData` 重点包含
- `Extract(...)`
- `ExtractForCamera(...)`
- `SelectCamera(...)`
## 当前提取内容
- 当前相机
- [RenderCameraData](../../FrameData/RenderCameraData/RenderCameraData.md)
- [RenderEnvironmentData](../../FrameData/RenderEnvironmentData/RenderEnvironmentData.md)
- `RenderLightingData`
- `camera`
- `cameraData`
- `environment`
- `lighting`
- `globalShaderKeywords`
- `visibleItems`
- `visibleVolumes`
## 公开方法
| 方法 | 说明 |
|------|------|
| [Extract](Extract.md) | 自动选择相机并提取 `RenderSceneData`。 |
| [ExtractForCamera](ExtractForCamera.md) | 使用显式相机提取 `RenderSceneData`。 |
| [SelectCamera](SelectCamera.md) | 按当前规则选择可用相机。 |
## 当前提取规则
### 相机选择
- `overrideCamera` 可用时优先使用它。
- 否则优先选择场景里深度最高的 `primary` 相机。
- 若没有 primary相机列表里第一个可用相机会作为回退。
### 可见内容
提取器会从场景根对象开始递归遍历:
- 先按 `IsActiveInHierarchy()` 和相机 `cullingMask` 过滤对象
- 再调用 `RenderSceneUtility` 展开 mesh 渲染项
- 同时调用 `AppendVisibleVolumesForGameObject(...)` 提取体积渲染项
因此当前 `RenderSceneData` 已经同时覆盖:
- 常规 mesh 的 `visibleItems`
- 体积渲染的 `visibleVolumes`
两类结果都会在提取结束后做稳定排序。
### 光照快照
`ExtractLighting(...)` 当前会:
- 选出主方向光并构建 `mainDirectionalLight`
- 基于影响度、光源类型和对象 ID 选出有限数量的 `additionalLights`
- 保留阴影相关槽位,供后续执行层写入 `mainDirectionalShadow`
这意味着 extractor 不只是“找一盏太阳光”,而是已经承担了运行时可消费的光照快照整理职责。
## 设计取舍
这类 extractor 设计和 Unity/Unreal 常见的 render-view 构建阶段类似,本质上是在做一件事:
把场景图的层级语义压扁成一份更适合渲染排序、pass 复用和后续 GPU 提交的帧快照。
这样做的好处很直接:
- `CameraRenderer` 不必在执行阶段重新遍历整个场景树
- builtin pipeline、object-id pass、体积 pass 可以共享同一批 frame data
- editor 或工具链要加附加阶段时,不必重新发明一套“场景如何提取”的规则
## 当前实现边界
- 当前仍没有 frustum culling、occlusion culling 或 batching
- 当前光照提取仍以主方向光和 additional lights 快照为主
- 体对象提取已经进入正式 `RenderSceneData` 主链,但更复杂的 volume-specific culling 或排序策略当前还没有单独拆层
- 没有 frustum culling。
- 没有 occlusion culling
- 没有 batching / instancing
- `globalShaderKeywords` 主要仍由后续执行层补充。
## 相关文档
- [Extraction](../Extraction.md)
- [RenderSceneUtility](../RenderSceneUtility/RenderSceneUtility.md)
- [RenderSceneData](../../FrameData/RenderSceneData/RenderSceneData.md)
- [VisibleRenderItem](../../FrameData/VisibleRenderItem/VisibleRenderItem.md)
- [VisibleVolumeItem](../../FrameData/VisibleVolumeItem/VisibleVolumeItem.md)
- [CameraRenderer](../../Execution/CameraRenderer/CameraRenderer.md)

View File

@@ -33,4 +33,4 @@ Components::CameraComponent* SelectCamera(
- [RenderSceneExtractor](RenderSceneExtractor.md)
- [Extract](Extract.md)
- [SceneRenderer::BuildRenderRequests](../SceneRenderer/BuildRenderRequests.md)
- [SceneRenderer::BuildRenderRequests](../../Execution/SceneRenderer/BuildRenderRequests.md)

View File

@@ -6,29 +6,89 @@
**头文件**: `XCEngine/Rendering/Extraction/RenderSceneUtility.h`
**描述**: 提供把相机和场景对象翻译成 `RenderCameraData``VisibleRenderItem`基础 helper。
**描述**: 为 scene extraction 提供相机数据构建、mesh/volume 展开、稳定排序和光照辅助查询等基础 helper。
## 当前公开函数
## 概览
`RenderSceneUtility.h` 是 [RenderSceneExtractor](../RenderSceneExtractor/RenderSceneExtractor.md) 的下层规则库。
它把最容易散落在 extractor 里的局部逻辑单独收口,当前主要覆盖四类工作:
1. 构建 [RenderCameraData](../../FrameData/RenderCameraData/RenderCameraData.md)
2. 展开 `VisibleRenderItem`
3. 展开 `VisibleVolumeItem`
4. 提供可见排序与光照辅助函数
## 公开函数
### 相机与可见项构建
- `BuildRenderCameraData(...)`
- `AppendRenderItemsForGameObject(...)`
- `CompareVisibleRenderItemsStable(...)`
- `AppendVisibleVolumesForGameObject(...)`
- `CollectRenderItemsForEntityIds(...)`
### 稳定排序
- `CompareVisibleRenderItemsStable(...)`
- `CompareVisibleVolumesStable(...)`
### 光照辅助
- `IsUsableLight(...)`
- `IsLightVisibleForCullingMask(...)`
- `BuildRenderLightDirection(...)`
- `FindMainDirectionalLight(...)`
## 当前语义
## 当前实现语义
- `BuildRenderCameraData(...)` 负责构建矩阵、姿态、viewport 尺寸与默认 clear 参数。
- `AppendRenderItemsForGameObject(...)` 会把 `GameObject` 展开成一个或多个 `VisibleRenderItem`
- `CollectRenderItemsForEntityIds(...)` 用于按实体 ID 收集渲染项,常见于 editor 工具链。
### `BuildRenderCameraData()`
- 读取相机的世界位置、朝向、clear color、投影参数与 clip plane
- 根据 perspective / orthographic 模式构建投影矩阵
- 写入 `view``projection``viewProjection`
- 同时补 `worldRight``worldUp``worldForward``aspectRatio`
它不会解析 `clearFlags`;那部分由 planning 层写进 `CameraRenderRequest`,再在执行层回写。
### `AppendRenderItemsForGameObject()`
- 仅接受激活且启用的 mesh 物体
- 按 mesh section 展开成多个 `VisibleRenderItem`
- 为每项补 `material``renderQueue``cameraDistanceSq``localToWorld`
- 同时把运行时对象 ID 转成渲染侧 `renderObjectId`
### `AppendVisibleVolumesForGameObject()`
- 仅接受激活且启用的 `VolumeRendererComponent`
- 要求 `VolumeField` 有效且材质存在
- 生成 `VisibleVolumeItem`,写入 `volumeField``material``renderQueue``cameraDistanceSq``localToWorld`
### 排序与光照
- `CompareVisibleRenderItemsStable(...)``CompareVisibleVolumesStable(...)` 都按 `renderQueue` 和相机距离做稳定比较
- `FindMainDirectionalLight(...)` 负责找出当前 culling mask 下的主方向光
- `BuildRenderLightDirection(...)` 统一把组件朝向转换为渲染侧光照方向
## 设计说明
把这些 helper 独立出来是一个典型的商业引擎做法:
不是为了“拆文件而拆文件”,而是为了让 extractor 保持在“组织一帧数据”的层级,而不是同时背负矩阵约定、排序约定和组件过滤约定。
这样做的收益是:
- 提取逻辑更容易单元测试
- `RenderSceneExtractor` 的职责边界更清晰
- 新增体积、额外光源、材质排序规则时,不必把所有细节塞回一个大类
## 当前实现边界
- 仍然直接操作场景组件,还不是完全解耦的 render proxy 阶段。
- `cameraDistanceSq` 目前按对象变换位置估算,不使用更精细的 bounds 中心。
- 没有 LOD、culling 或 batching。
## 相关文档
- [Extraction](../Extraction.md)
- [RenderSceneExtractor](../RenderSceneExtractor/RenderSceneExtractor.md)
- [RenderCameraData](../../FrameData/RenderCameraData/RenderCameraData.md)
- [VisibleRenderItem](../../FrameData/VisibleRenderItem/VisibleRenderItem.md)
- [VisibleVolumeItem](../../FrameData/VisibleVolumeItem/VisibleVolumeItem.md)

View File

@@ -2,48 +2,61 @@
**命名空间**: `XCEngine::Rendering`
**类型**: `struct + enum`
**类型**: `struct`
**头文件**: `XCEngine/Rendering/FrameData/RenderCameraData.h`
**描述**: 承载渲染阶段实际使用的相机矩阵、视口尺寸、世界姿态和清屏参数;同头文件还定义 `RenderClearFlags` 位标志
**描述**: 保存渲染阶段实际使用的相机矩阵、清屏参数和视口尺寸。
## 概览
`RenderCameraData` 是组件层相机到渲染层 frame data 的桥接结构。
`RenderCameraData`组件层相机”到“渲染层可直接消费的数据块”之间的桥接结构。
当前主链路里:
当前它不仅保存:
- [RenderSceneUtility](../../Extraction/RenderSceneUtility/RenderSceneUtility.md) 的 `BuildRenderCameraData()` 负责先构建矩阵、世界位置和默认清屏色。
- [RenderSceneExtractor](../../Extraction/RenderSceneExtractor/RenderSceneExtractor.md) 把它装进 `RenderSceneData`
- [CameraRenderer](../../Execution/CameraRenderer/CameraRenderer.md) 会在真正提交前再按 request 覆盖 `clearFlags`,必要时覆盖 `clearColor`
- `view / projection / viewProjection`
- `worldPosition / worldRight / worldUp / worldForward`
- `viewportWidth / viewportHeight`
还保存当前提交最终会消费的:
- `clearColor`
- `clearFlags`
- projection mode 与 clip 参数
因此它不是“纯相机组件快照”,而是一次渲染提交最终会消费的相机数据槽位。
## `RenderClearFlags`
同头文件里`RenderClearFlags` 当前定义
一个头文件里还定义了当前使用的清屏位标志
- `None`
- `Color`
- `Depth`
- `All`
| 枚举值 | 说明 |
|------|------|
| `None` | 不清任何内容。 |
| `Color` | 只清颜色。 |
| `Depth` | 只清深度。 |
| `All` | 同时清颜色和深度。 |
并提供 `operator|``operator&``HasRenderClearFlag(...)` helper
当前还提供了按位 `|``&` 运算,以及 `HasRenderClearFlag(flags, flag)` helper供 [BuiltinForwardPipeline](../../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md) 判断本次主场景是否需要清颜色/深度
## 当前调用链
## 字段
- [RenderSceneUtility](../../Extraction/RenderSceneUtility/RenderSceneUtility.md) 负责构建初始 `RenderCameraData`
- [RenderSceneData](../RenderSceneData/RenderSceneData.md) 持有它
- [CameraRenderRequest](../../Planning/CameraRenderRequest/CameraRenderRequest.md) 会在执行前进一步覆盖 clear 语义
| 字段 | 类型 | 说明 |
|------|------|------|
| `view` | `Math::Matrix4x4` | 视图矩阵。 |
| `projection` | `Math::Matrix4x4` | 投影矩阵。 |
| `viewProjection` | `Math::Matrix4x4` | `projection * view` 组合矩阵。 |
| `worldPosition` | `Math::Vector3` | 相机世界坐标。 |
| `clearColor` | `Math::Color` | 当前提交使用的清屏色。 |
| `clearFlags` | `RenderClearFlags` | 当前提交使用的清屏标志;默认值是 `All`。 |
| `viewportWidth` | `uint32_t` | 当前视口宽度。 |
| `viewportHeight` | `uint32_t` | 当前视口高度。 |
## 当前实现说明
- `BuildRenderCameraData()` 当前会写入 `view``projection``viewProjection``worldPosition``clearColor` 和 viewport 尺寸。
- 该函数不会根据 `CameraComponent::GetClearMode()` 推导 `clearFlags``RenderCameraData` 此时保留 struct 默认值 `RenderClearFlags::All`
- 真正的 per-request clear 语义在 `CameraRenderer::Render()` 里由 `request.clearFlags` 覆盖写回 `sceneData.cameraData.clearFlags`
- 当前 extractor 会在写入矩阵前对 `view``projection``viewProjection` 做转置,以适配现有 shader 常量布局。
## 相关文档
- [FrameData](../FrameData.md)
- [Rendering](../../Rendering.md)
- [RenderSceneUtility](../../Extraction/RenderSceneUtility/RenderSceneUtility.md)
- [RenderSceneData](../RenderSceneData/RenderSceneData.md)
- [RenderSceneExtractor](../../Extraction/RenderSceneExtractor/RenderSceneExtractor.md)
- [CameraRenderer](../../Execution/CameraRenderer/CameraRenderer.md)
- [CameraRenderRequest](../../Planning/CameraRenderRequest/CameraRenderRequest.md)

View File

@@ -1,49 +0,0 @@
# ObjectIdEncoding
**命名空间**: `XCEngine::Rendering`
**类型**: `compatibility note`
**头文件**: `XCEngine/Rendering/Picking/ObjectIdCodec.h`
**描述**: 历史文档里的 `ObjectIdEncoding` 现已收口到 `Picking/ObjectIdCodec.h`;当前公开 API 提供 object-id 与 RGBA 颜色之间的稳定编码约定。
## 当前公开项
`ObjectIdCodec.h` 当前公开:
- `EncodedObjectId`
- `CanEncodeObjectIdWithoutLoss(...)`
- `EncodeObjectIdToEncodedId(...)`
- `EncodeObjectIdToUInt32(...)`
- `EncodeObjectIdToColor(...)`
- `DecodeEncodedObjectIdFromColor(...)`
- `DecodeObjectIdFromColor(...)`
## 当前语义
- object-id 渲染目标只保留运行时对象 ID 的低 `32` 位。
- `CanEncodeObjectIdWithoutLoss(...)` 用来判断高 `32` 位是否全为 `0`
- RGBA 编码顺序固定为:
- `r` 对应最低 `8`
- `g` 对应 `8-15`
- `b` 对应 `16-23`
- `a` 对应 `24-31`
## 使用位置
- [BuiltinObjectIdPass](../Passes/BuiltinObjectIdPass/BuiltinObjectIdPass.md)
- [BuiltinObjectIdOutlinePass](../Passes/BuiltinObjectIdOutlinePass/BuiltinObjectIdOutlinePass.md)
- [ObjectIdCodec](../Picking/ObjectIdCodec/ObjectIdCodec.md)
## 迁移说明
- 旧名称 `ObjectIdEncoding` 只保留为兼容文档入口。
- 需要查看当前权威说明时,优先使用 [ObjectIdCodec](../Picking/ObjectIdCodec/ObjectIdCodec.md)。
## 相关文档
- [Rendering](../Rendering.md)
- [Picking](../Picking/Picking.md)
- [ObjectIdCodec](../Picking/ObjectIdCodec/ObjectIdCodec.md)
- [BuiltinObjectIdPass](../Passes/BuiltinObjectIdPass/BuiltinObjectIdPass.md)

View File

@@ -1,45 +0,0 @@
# ObjectIdPass
**命名空间**: `XCEngine::Rendering`
**类型**: `compatibility note`
**描述**: 历史上的 `ObjectIdPass.h` 抽象接口已经移除;当前 object-id 渲染插槽改为由 `CameraRenderer` 持有的通用 `RenderPass` 实例,默认实现是 `Passes::BuiltinObjectIdPass`
## 当前实现
当前公开 API 不再提供单独的 `ObjectIdPass` 基类:
- [CameraRenderer::SetObjectIdPass](../CameraRenderer/SetObjectIdPass.md) 接收 `std::unique_ptr<RenderPass>`
- [CameraRenderer::GetObjectIdPass](../CameraRenderer/GetObjectIdPass.md) 返回当前 object-id 插槽里的 `RenderPass*`
- 默认注入的实现是 [BuiltinObjectIdPass](../Passes/BuiltinObjectIdPass/BuiltinObjectIdPass.md)。
因此“object-id pass” 现在描述的是执行阶段里的一个职责槽位,而不是一个独立的公开头文件类型。
## 执行时机
`engine/src/Rendering/Execution/CameraRenderer.cpp` 的当前实现object-id 阶段位于:
1. `preScenePasses`
2. `shadowCaster`
3. `depthOnly`
4.`RenderPipeline`
5. object-id pass
6. `postScenePasses`
7. `overlayPasses`
只有当 `request.objectId.IsRequested()` 为真时,`CameraRenderer` 才会执行这里持有的 pass。
## 迁移说明
- 旧文档里把 `ObjectIdPass` 视为独立接口的描述,已经不再对应当前源码。
- 需要理解 object-id 语义时,优先查看 [BuiltinObjectIdPass](../Passes/BuiltinObjectIdPass/BuiltinObjectIdPass.md) 和 [ObjectIdCodec](../Picking/ObjectIdCodec/ObjectIdCodec.md)。
- 需要理解插槽生命周期时,优先查看 [CameraRenderer](../CameraRenderer/CameraRenderer.md)。
## 相关文档
- [Rendering](../Rendering.md)
- [CameraRenderer](../CameraRenderer/CameraRenderer.md)
- [ObjectIdRenderRequest](../CameraRenderRequest/ObjectIdRenderRequest/ObjectIdRenderRequest.md)
- [BuiltinObjectIdPass](../Passes/BuiltinObjectIdPass/BuiltinObjectIdPass.md)
- [ObjectIdCodec](../Picking/ObjectIdCodec/ObjectIdCodec.md)

View File

@@ -13,7 +13,7 @@
`BuiltinDepthStylePassBase` 把两类 pass 的公共逻辑集中在一起:
-`BuiltinMaterialPass` 解析可兼容的 shader pass。
- 复用 [RenderResourceCache](../../RenderResourceCache/RenderResourceCache.md) 上传 mesh GPU 副本。
- 复用 [RenderResourceCache](../../Caches/RenderResourceCache/RenderResourceCache.md) 上传 mesh GPU 副本。
- 只接受“单个 `PerObject` 常量缓冲”这一类资源绑定计划。
- 在 [Execute](Execute.md) 中统一处理 `RenderSurface` 检查、viewport/scissor、清屏、绘制循环和颜色附件状态切换。
- 虽然是“深度风格” pass当前执行框架仍要求 `RenderSurface` 同时提供 `colorAttachments[0]``depthAttachment`,并沿用颜色 clear / transition 路径。
@@ -41,4 +41,4 @@
- [BuiltinDepthOnlyPass](../BuiltinDepthOnlyPass/BuiltinDepthOnlyPass.md)
- [BuiltinShadowCasterPass](../BuiltinShadowCasterPass/BuiltinShadowCasterPass.md)
- [RenderPass](../../RenderPass/RenderPass.md)
- [RenderResourceCache](../../RenderResourceCache/RenderResourceCache.md)
- [RenderResourceCache](../../Caches/RenderResourceCache/RenderResourceCache.md)

View File

@@ -10,7 +10,7 @@ void Shutdown() override;
- 当前实现直接调用内部 `DestroyResources()`
- 它会清理:
- [RenderResourceCache](../../RenderResourceCache/RenderResourceCache.md)
- [RenderResourceCache](../../Caches/RenderResourceCache/RenderResourceCache.md)
- 按 object ID 缓存的 per-object descriptor set / pool
- pipeline state 缓存
- pass resource layout 缓存

View File

@@ -14,7 +14,7 @@
- object-id 纹理通常来自 `BuiltinObjectIdPass`
- 选中对象列表和 style 当前通常由 editor 侧的 Scene View render plan 提供。
- 调用时机当前由 `editor/src/Viewport/Passes/SceneViewportSelectionOutlinePass.cpp` 这类包装 pass 决定,并最终通过 [CameraRenderer](../../CameraRenderer/CameraRenderer.md) 的 `postScenePasses` 提交。
- 调用时机当前由 `editor/src/Viewport/Passes/SceneViewportSelectionOutlinePass.cpp` 这类包装 pass 决定,并最终通过 [CameraRenderer](../../Execution/CameraRenderer/CameraRenderer.md) 的 `postScenePasses` 提交。
因此它更接近一个“builtin selection feedback compositor”而不是一个通用 post-process 框架。
@@ -82,7 +82,7 @@
- `editor/src/Viewport/Passes/SceneViewportSelectionOutlinePass.cpp``SceneViewportSelectionOutlinePassRenderer` 包装它,
并通过 `GetSceneViewportObjectIdOutlineShaderPath()` 注入 editor-owned shader 路径。
- [SceneViewportRenderPlan](../../../Editor/Viewport/SceneViewportRenderPlan/SceneViewportRenderPlan.md) 决定当前帧是否要创建 selection outline pass。
- [CameraRenderer](../../CameraRenderer/CameraRenderer.md) 在主场景与 object-id pass 之后执行这些 `postScenePasses`
- [CameraRenderer](../../Execution/CameraRenderer/CameraRenderer.md) 在主场景与 object-id pass 之后执行这些 `postScenePasses`
- `editor/src/Viewport/ViewportHostRenderFlowUtils.h` 当前为 Scene View 组装默认橙色、`2px` 的 outline style。
## 相关文档
@@ -91,6 +91,6 @@
- [SetShaderPath](SetShaderPath.md)
- [GetShaderPath](GetShaderPath.md)
- [ObjectIdOutlineStyle](../ObjectIdOutlineStyle/ObjectIdOutlineStyle.md)
- [CameraRenderer](../../CameraRenderer/CameraRenderer.md)
- [CameraRenderer](../../Execution/CameraRenderer/CameraRenderer.md)
- [RenderSurface](../../RenderSurface/RenderSurface.md)
- [SceneViewportResourcePaths](../../../Editor/Viewport/SceneViewportResourcePaths/SceneViewportResourcePaths.md)

View File

@@ -40,4 +40,4 @@ static RHI::InputLayoutDesc BuildInputLayout();
- [BuiltinObjectIdPass](BuiltinObjectIdPass.md)
- [Render](Render.md)
- [ObjectIdEncoding](../../ObjectIdEncoding/ObjectIdEncoding.md)
- [ObjectIdEncoding](../../Picking/ObjectIdCodec/ObjectIdCodec.md)

View File

@@ -66,4 +66,4 @@
- [Render](Render.md)
- [Shutdown](Shutdown.md)
- [BuiltinObjectIdOutlinePass](../BuiltinObjectIdOutlinePass/BuiltinObjectIdOutlinePass.md)
- [CameraRenderer](../../CameraRenderer/CameraRenderer.md)
- [CameraRenderer](../../Execution/CameraRenderer/CameraRenderer.md)

View File

@@ -9,7 +9,7 @@
## 当前语义
- 当前析构函数会直接调用 [Shutdown](Shutdown.md)。
- 因此对象销毁前会释放 pipeline state、pipeline layout、per-object descriptor set/pool、builtin shader handle以及内部 [RenderResourceCache](../../RenderResourceCache/RenderResourceCache.md)。
- 因此对象销毁前会释放 pipeline state、pipeline layout、per-object descriptor set/pool、builtin shader handle以及内部 [RenderResourceCache](../../Caches/RenderResourceCache/RenderResourceCache.md)。
- 之前按 object id 缓存的 descriptor set 也会在这一步一起清掉。
## 调用方影响

View File

@@ -33,5 +33,5 @@ bool Render(
- [BuiltinObjectIdPass](BuiltinObjectIdPass.md)
- [BuildInputLayout](BuildInputLayout.md)
- [ObjectIdEncoding](../../ObjectIdEncoding/ObjectIdEncoding.md)
- [CameraRenderer::Render](../../CameraRenderer/Render.md)
- [ObjectIdEncoding](../../Picking/ObjectIdCodec/ObjectIdCodec.md)
- [CameraRenderer::Render](../../Execution/CameraRenderer/Render.md)

View File

@@ -10,7 +10,7 @@ void Shutdown() override;
- 当前实现直接转发到内部 `DestroyResources()`
- 它会依次清理:
- 内部 [RenderResourceCache](../../RenderResourceCache/RenderResourceCache.md)
- 内部 [RenderResourceCache](../../Caches/RenderResourceCache/RenderResourceCache.md)
- `m_perObjectSets` 中按 object ID 缓存的 descriptor pool / descriptor set
- `m_pipelineState`
- `m_pipelineLayout`
@@ -33,4 +33,4 @@ void Shutdown() override;
- [BuiltinObjectIdPass](BuiltinObjectIdPass.md)
- [Destructor](Destructor.md)
- [Render](Render.md)
- [RenderResourceCache](../../RenderResourceCache/RenderResourceCache.md)
- [RenderResourceCache](../../Caches/RenderResourceCache/RenderResourceCache.md)

View File

@@ -28,8 +28,8 @@
当前 Scene View 相关链路大致是:
1. [CameraRenderer](../CameraRenderer/CameraRenderer.md) 先执行主 `RenderPipeline`
2. 如果 [CameraRenderRequest](../CameraRenderRequest/CameraRenderRequest.md) 里请求了 `objectId.surface`,则额外执行 [BuiltinObjectIdPass](BuiltinObjectIdPass/BuiltinObjectIdPass.md)。
1. [CameraRenderer](../Execution/CameraRenderer/CameraRenderer.md) 先执行主 `RenderPipeline`
2. 如果 [CameraRenderRequest](../Planning/CameraRenderRequest/CameraRenderRequest.md) 里请求了 `objectId.surface`,则额外执行 [BuiltinObjectIdPass](BuiltinObjectIdPass/BuiltinObjectIdPass.md)。
3. editor 侧的 `SceneViewportRenderPlan` 再构建 `postScenePasses``overlayPasses`
4. 其中 `SceneViewportGridPass` / `SceneViewportSelectionOutlinePass` 当前分别调用 [BuiltinInfiniteGridPass](BuiltinInfiniteGridPass/BuiltinInfiniteGridPass.md) 与“[BuiltinSelectionMaskPass](BuiltinSelectionMaskPass/BuiltinSelectionMaskPass.md) + [BuiltinSelectionOutlinePass](BuiltinSelectionOutlinePass/BuiltinSelectionOutlinePass.md)”这一组 selection outline 组合。
@@ -106,6 +106,6 @@
- [BuiltinDepthStylePassBase](BuiltinDepthStylePassBase/BuiltinDepthStylePassBase.md)
- [BuiltinDepthOnlyPass](BuiltinDepthOnlyPass/BuiltinDepthOnlyPass.md)
- [BuiltinShadowCasterPass](BuiltinShadowCasterPass/BuiltinShadowCasterPass.md)
- [CameraRenderRequest](../CameraRenderRequest/CameraRenderRequest.md)
- [CameraRenderer](../CameraRenderer/CameraRenderer.md)
- [CameraRenderRequest](../Planning/CameraRenderRequest/CameraRenderRequest.md)
- [CameraRenderer](../Execution/CameraRenderer/CameraRenderer.md)
- [Rendering](../Rendering.md)

View File

@@ -33,5 +33,4 @@
## 相关文档
- [Picking](../Picking.md)
- [ObjectIdEncoding](../../ObjectIdEncoding/ObjectIdEncoding.md)
- [BuiltinObjectIdPass](../../Passes/BuiltinObjectIdPass/BuiltinObjectIdPass.md)

View File

@@ -17,7 +17,7 @@
当前公开入口:
- [ObjectIdCodec](ObjectIdCodec/ObjectIdCodec.md)
- [ObjectIdEncoding](../ObjectIdEncoding/ObjectIdEncoding.md)
- [ObjectIdEncoding](ObjectIdCodec/ObjectIdCodec.md)
## 当前职责

View File

@@ -71,7 +71,7 @@ binding-plan 解析之后,布局构建阶段还会继续拒绝以下情况:
- 逐物体常量来自 `PerObjectConstants`
- 逐材质常量优先来自 `ResolveSchemaMaterialConstantPayload(material)` 暴露的 schema-driven payload
如果 view 无效,才回退到内部 `FallbackPerMaterialConstants { baseColorFactor, alphaCutoffParams }`
- 采样器和 1x1 白色 fallback 纹理在初始化后长期复用;具体 `Texture``Mesh` 的 GPU 资源则由 [RenderResourceCache](../../RenderResourceCache/RenderResourceCache.md) 按需上传。
- 采样器和 1x1 白色 fallback 纹理在初始化后长期复用;具体 `Texture``Mesh` 的 GPU 资源则由 [RenderResourceCache](../../Caches/RenderResourceCache/RenderResourceCache.md) 按需上传。
- 体对象阶段当前已经正式接入 [BuiltinVolumetricPass](../../Passes/BuiltinVolumetricPass/BuiltinVolumetricPass.md),因此 `RenderSceneData` 不再只有 `visibleItems` 一条几何主链。
## 当前限制
@@ -97,6 +97,6 @@ binding-plan 解析之后,布局构建阶段还会继续拒绝以下情况:
- [BuiltinForwardPipelineAsset](../BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md)
- [RenderPipeline](../../RenderPipeline/RenderPipeline.md)
- [RenderPipelineAsset](../../RenderPipelineAsset/RenderPipelineAsset.md)
- [CameraRenderer](../../CameraRenderer/CameraRenderer.md)
- [CameraRenderer](../../Execution/CameraRenderer/CameraRenderer.md)
- [RenderPass](../../RenderPass/RenderPass.md)
- [Scene Extraction And Builtin Forward Pipeline](../../../../_guides/Rendering/Scene-Extraction-And-Builtin-Forward-Pipeline.md)

View File

@@ -10,7 +10,7 @@
- 当前析构函数会直接调用 [Shutdown](Shutdown.md)。
- `Shutdown()` 又会通过内部 `m_passSequence` 触发 `BuiltinForwardOpaquePass::Shutdown()`,最终回收到 `DestroyPipelineResources()`
- 因此析构前会清掉 builtin shader handle、pass layout、descriptor set 缓存、pipeline state、fallback 纹理/采样器,以及内部 [RenderResourceCache](../../RenderResourceCache/RenderResourceCache.md)。
- 因此析构前会清掉 builtin shader handle、pass layout、descriptor set 缓存、pipeline state、fallback 纹理/采样器,以及内部 [RenderResourceCache](../../Caches/RenderResourceCache/RenderResourceCache.md)。
## 设计说明

View File

@@ -34,5 +34,5 @@ m_passSequence.Shutdown();
- [BuiltinForwardPipeline](BuiltinForwardPipeline.md)
- [Destructor](Destructor.md)
- [RenderResourceCache](../../RenderResourceCache/RenderResourceCache.md)
- [RenderResourceCache](../../Caches/RenderResourceCache/RenderResourceCache.md)
- [RenderPass](../../RenderPass/RenderPass.md)

View File

@@ -16,10 +16,10 @@
- 作为默认主管线工厂存在
- 在需要时返回一条新的 `BuiltinForwardPipeline`
`engine/src/Rendering/CameraRenderer.cpp` 的当前接线:
`engine/src/Rendering/Execution/CameraRenderer.cpp` 的当前接线:
- `CameraRenderer` 默认构造会使用静态共享的 `BuiltinForwardPipelineAsset`
- [SetPipelineAsset](../../CameraRenderer/SetPipelineAsset.md) 也可以显式切回这条 asset 路径
- [SetPipelineAsset](../../Execution/CameraRenderer/SetPipelineAsset.md) 也可以显式切回这条 asset 路径
- 如果外部把 asset 传空,回退到默认 `BuiltinForwardPipelineAsset` 的逻辑发生在 `CameraRenderer`,不是这个类内部
## 生命周期与所有权
@@ -45,4 +45,4 @@
- [BuiltinForwardPipeline](../BuiltinForwardPipeline/BuiltinForwardPipeline.md)
- [Pipelines](../Pipelines.md)
- [RenderPipelineAsset](../../RenderPipelineAsset/RenderPipelineAsset.md)
- [CameraRenderer](../../CameraRenderer/CameraRenderer.md)
- [CameraRenderer](../../Execution/CameraRenderer/CameraRenderer.md)

View File

@@ -53,5 +53,5 @@
- [Rendering](../Rendering.md)
- [RenderPipeline](../RenderPipeline/RenderPipeline.md)
- [RenderPipelineAsset](../RenderPipelineAsset/RenderPipelineAsset.md)
- [CameraRenderer](../CameraRenderer/CameraRenderer.md)
- [CameraRenderer](../Execution/CameraRenderer/CameraRenderer.md)
- [Scene Extraction And Builtin Forward Pipeline](../../../_guides/Rendering/Scene-Extraction-And-Builtin-Forward-Pipeline.md)

View File

@@ -6,24 +6,14 @@
**头文件**: `XCEngine/Rendering/Planning/CameraRenderRequest.h`
**描述**: 单相机渲染提交的显式请求对象,打包主场景 surface、shadow/depth/object-id/fullscreen 子请求、clear 覆盖、frame-stage 辅助查询,以及可选 pass 序列
**描述**: 单相机渲染提交的显式数据契约统一描述主场景、阴影、depth-only、fullscreen、object-id 和 editor 注入阶段
## 概览
`CameraRenderRequest` [Planning](../Planning.md) [Execution](../../Execution/Execution.md) 之间最核心的数据契约
`CameraRenderRequest` 处在 [Planning](../Planning.md) [Execution](../../Execution/Execution.md) 之间。
它不直接渲染任何内容,而是把“这一台相机这一帧该怎样执行”压平成一份可验证、可排序、可扩展的 request。
相较旧版 request 模型,当前头文件已经把更多阶段正式纳入同一份 request
- `shadowCaster`
- `depthOnly`
- `postProcess`
- `finalOutput`
- `objectId`
- `preScenePasses`
- `postScenePasses`
- `overlayPasses`
## 头文件中的主要类型
当前头文件里与它一同公开的核心类型包括
- `CameraFrameStage`
- `CameraFrameStageInfo`
@@ -33,23 +23,116 @@
- `FullscreenPassRenderRequest`
- `CameraRenderRequest`
## 当前语义
这套设计的价值在于:规划层只需要把 request 组装完整,执行层就能按统一阶段顺序跑完一台相机,而不必让 editor、runtime、离屏渲染各自维护一套隐式约定。
- `ScenePassRenderRequest` 同时服务 `DepthOnlyRenderRequest``ShadowCasterRenderRequest`
- `DirectionalShadowRenderPlan` 保存 directional shadow 相机与 map 配置。
- `FullscreenPassRenderRequest` 同时服务 `PostProcessRenderRequest``FinalOutputRenderRequest`
- `HasFrameStage(...)``GetPassSequence(...)``GetOutputSurface(...)` 让执行层可以按统一阶段名查询 request。
## 关键字段
## 当前实现边界
| 字段 | 角色 |
|------|------|
| `scene` / `camera` / `context` | 主场景提取与执行的最小上下文。 |
| `surface` | 当前相机最终主输出目标。 |
| `depthOnly` | depth-only scene pass 子请求。 |
| `shadowCaster` | 显式 shadow-caster scene pass 子请求。 |
| `directionalShadow` | 仅声明方向光阴影计划;必要时由 `CameraRenderer` 自动生成内部 shadow surface。 |
| `postProcess` | fullscreen 后处理阶段请求。 |
| `finalOutput` | fullscreen 最终输出阶段请求。 |
| `finalColorPolicy` | fullscreen 最终颜色策略的解析结果。 |
| `objectId` | object-id 辅助输出请求。 |
| `cameraDepth` / `cameraStackOrder` | 多相机稳定排序键。 |
| `clearFlags` / `clearColorOverride` | 本次提交覆盖写回 `RenderSceneData::cameraData` 的清屏语义。 |
| `preScenePasses` / `postScenePasses` / `overlayPasses` | 调用方注入的附加阶段序列。 |
- `IsValid()` 仍只检查 `scene``camera``context` 是否存在,具体子请求完整性由执行层进一步验证。
- request 本身不生成任何 passEditor 或更上层系统仍要先把 sequence 和 surface 写进来。
## 当前阶段顺序
`CameraRenderer` 会按 `kOrderedCameraFrameStages` 解释这份 request
1. `PreScenePasses`
2. `ShadowCaster`
3. `DepthOnly`
4. `MainScene`
5. `PostProcess`
6. `FinalOutput`
7. `ObjectId`
8. `PostScenePasses`
9. `OverlayPasses`
这意味着 fullscreen 阶段和 object-id 不再是调用方各自拼出来的旁路,而是 request 模型里的正式阶段。
## 子请求模型
### `ScenePassRenderRequest`
`depthOnly``shadowCaster` 当前都只是 `ScenePassRenderRequest` 的别名。
它描述“在主 `RenderPipeline` 前,是否要额外执行一次 scene pass”。
- [IsRequested](ScenePassRenderRequest/IsRequested.md) 只判断是否真的挂了目标附件。
- [IsValid](ScenePassRenderRequest/IsValid.md) 进一步要求深度附件、颜色附件和 render area 全部可用。
- `hasCameraDataOverride` / `cameraDataOverride` 允许这条 scene pass 使用不同于主相机的数据;当前方向光阴影路径会利用这一点。
### `DirectionalShadowRenderPlan`
`shadowCaster.surface` 没有显式提供,但 `directionalShadow.IsValid()` 为真时,`CameraRenderer` 会借助 `DirectionalShadowSurfaceCache` 自动构建内部阴影 surface并把 plan 里的 `cameraData` 写回 shadow-caster 子请求。
### `FullscreenPassRenderRequest`
`postProcess``finalOutput` 都是 `FullscreenPassRenderRequest` 的别名。
它们描述:
- 从哪张 source surface 读取
- 用哪张 `sourceColorView` 作为输入
- 把结果写到哪张 destination surface
- 由哪条 `RenderPassSequence` 执行
`SceneRenderer::BuildRenderRequests(...)` 会根据相机后处理描述和 final-color policy 自动补齐这两段 request。
### `ObjectIdRenderRequest`
`objectId` 描述独立的 object-id 辅助输出目标。
当前执行层要求它至少具备:
- 第一张颜色附件
- 深度附件
- 有效 render area
object-id 阶段发生在 `FinalOutput` 之后、`PostScenePasses` 之前。
## 辅助查询函数
头文件还提供了一组阶段化查询 helper
- `HasFrameStage(...)`
- `GetPassSequence(...)`
- `GetScenePassRequest(...)`
- `GetObjectIdRequest(...)`
- `GetMainSceneSurface()`
- `GetFinalCompositedSurface()`
- `GetOutputSurface(...)`
- `GetSourceSurface(...)`
- `GetSourceColorView(...)`
- `GetSourceColorState(...)`
- `RequiresIntermediateSceneColor()`
这些 helper 的意义是把“不同阶段该读哪张 surface、写哪张 surface、是否需要中间颜色缓存”统一收口到 request 模型本身,而不是散落在调用方里。
## 当前数据契约
- [IsValid](IsValid.md) 只检查 `scene``camera``context`,不会替执行层验证所有子请求。
- `CameraRenderer::Render()` 还会继续拒绝无效的 `depthOnly``postProcess``finalOutput``objectId`,以及无法解析的 shadow-caster 请求。
- `SceneRenderer::Render(const std::vector<CameraRenderRequest>&)` 会先按 `cameraStackOrder -> cameraDepth` 稳定排序,再逐条提交。
## 真实使用位置
- [SceneRenderRequestPlanner](../SceneRenderRequestPlanner/SceneRenderRequestPlanner.md) 负责先构建基础 request。
- [SceneRenderer](../../Execution/SceneRenderer/SceneRenderer.md) 负责补 `finalColorPolicy``postProcess``finalOutput`
- editor Scene View 通过 `SceneViewportRenderPlan``ViewportHostRenderFlowUtils` 再补 `objectId``postScenePasses``overlayPasses` 与 clear override。
- [CameraRenderer](../../Execution/CameraRenderer/CameraRenderer.md) 最终按阶段执行整份 request。
## 相关文档
- [Planning](../Planning.md)
- [IsValid](IsValid.md)
- [ScenePassRenderRequest](ScenePassRenderRequest/ScenePassRenderRequest.md)
- [ObjectIdRenderRequest](ObjectIdRenderRequest/ObjectIdRenderRequest.md)
- [SceneRenderRequestPlanner](../SceneRenderRequestPlanner/SceneRenderRequestPlanner.md)
- [SceneRenderRequestUtils](../SceneRenderRequestUtils/SceneRenderRequestUtils.md)
- [SceneRenderer](../../Execution/SceneRenderer/SceneRenderer.md)
- [CameraRenderer](../../Execution/CameraRenderer/CameraRenderer.md)

View File

@@ -1,4 +1,4 @@
# CameraRenderRequest::IsValid
# CameraRenderRequest::IsValid
**命名空间**: `XCEngine::Rendering`
@@ -49,5 +49,5 @@ return scene != nullptr &&
## 相关文档
- [CameraRenderRequest](CameraRenderRequest.md)
- [CameraRenderer::Render](../CameraRenderer/Render.md)
- [CameraRenderer::Render](../../Execution/CameraRenderer/Render.md)

View File

@@ -33,4 +33,4 @@ return !colorAttachments.empty() &&
- [返回类型总览](ObjectIdRenderRequest.md)
- [IsRequested](IsRequested.md)
- [CameraRenderer::Render](../../CameraRenderer/Render.md)
- [CameraRenderer::Render](../../../Execution/CameraRenderer/Render.md)

View File

@@ -1,4 +1,4 @@
# ObjectIdRenderRequest
# ObjectIdRenderRequest
**命名空间**: `XCEngine::Rendering`
@@ -34,5 +34,5 @@
- [CameraRenderRequest](../CameraRenderRequest.md)
- [IsRequested](IsRequested.md)
- [IsValid](IsValid.md)
- [CameraRenderer](../../CameraRenderer/CameraRenderer.md)
- [CameraRenderer](../../../Execution/CameraRenderer/CameraRenderer.md)

View File

@@ -33,4 +33,4 @@ return !colorAttachments.empty() &&
- [返回类型总览](ScenePassRenderRequest.md)
- [IsRequested](IsRequested.md)
- [CameraRenderer::Render](../../CameraRenderer/Render.md)
- [CameraRenderer::Render](../../../Execution/CameraRenderer/Render.md)

View File

@@ -1,4 +1,4 @@
# ScenePassRenderRequest
# ScenePassRenderRequest
**命名空间**: `XCEngine::Rendering`
@@ -25,17 +25,17 @@
- [IsRequested](IsRequested.md) 只回答“调用方有没有挂一个颜色附件过来”。
- [IsValid](IsValid.md) 才回答“这份 scene pass 输出目标是否足够完整,可以真正执行”。
- 按 `engine/src/Rendering/CameraRenderer.cpp` 的当前实现,`CameraRenderer::Render()` 会先消费 `shadowCaster`,再消费 `depthOnly`,之后才进入主 `RenderPipeline`
- 按 `engine/src/Rendering/Execution/CameraRenderer.cpp` 的当前实现,`CameraRenderer::Render()` 会先消费 `shadowCaster`,再消费 `depthOnly`,之后才进入主 `RenderPipeline`
## 真实使用位置
- `CameraRenderRequest::shadowCaster``CameraRenderRequest::depthOnly` 都是这个结构的别名实例。
- `CameraRenderer` 默认分别用 [BuiltinShadowCasterPass](../../Passes/BuiltinShadowCasterPass/BuiltinShadowCasterPass.md) 与 [BuiltinDepthOnlyPass](../../Passes/BuiltinDepthOnlyPass/BuiltinDepthOnlyPass.md) 来消费它。
- `CameraRenderer` 默认分别用 [BuiltinShadowCasterPass](../../../Passes/BuiltinShadowCasterPass/BuiltinShadowCasterPass.md) 与 [BuiltinDepthOnlyPass](../../../Passes/BuiltinDepthOnlyPass/BuiltinDepthOnlyPass.md) 来消费它。
## 相关文档
- [CameraRenderRequest](../CameraRenderRequest.md)
- [IsRequested](IsRequested.md)
- [IsValid](IsValid.md)
- [CameraRenderer](../../CameraRenderer/CameraRenderer.md)
- [CameraRenderer](../../../Execution/CameraRenderer/CameraRenderer.md)

View File

@@ -35,4 +35,4 @@ std::vector<CameraRenderRequest> BuildRequests(
- [SceneRenderRequestPlanner](SceneRenderRequestPlanner.md)
- [CollectCameras](CollectCameras.md)
- [SceneRenderRequestUtils](../SceneRenderRequestUtils/SceneRenderRequestUtils.md)
- [SceneRenderer::BuildRenderRequests](../SceneRenderer/BuildRenderRequests.md)
- [SceneRenderer::BuildRenderRequests](../../Execution/SceneRenderer/BuildRenderRequests.md)

View File

@@ -6,32 +6,80 @@
**头文件**: `XCEngine/Rendering/Planning/SceneRenderRequestPlanner.h`
**描述**: 从场景和可选 override camera 生成最终要提交给执行层的 `CameraRenderRequest` 数组
**描述**: 负责从场景和可选 override camera 生成实际要提交给 `CameraRenderer` 的相机请求列表
## 概览
`SceneRenderRequestPlanner` 处在 request planning 主链的中心位置
`SceneRenderRequestPlanner` 处在 [SceneRenderer](../../Execution/SceneRenderer/SceneRenderer.md) 和 [SceneRenderRequestUtils](../SceneRenderRequestUtils/SceneRenderRequestUtils.md) 之间
它不亲自渲染任何东西,而是把“应该渲染哪些相机、按什么顺序、哪些请求应该被丢弃”整理成一组 [CameraRenderRequest](../CameraRenderRequest/CameraRenderRequest.md)。
它负责
这种“先规划 request再执行 request”的拆法很接近商业引擎里常见的 camera scheduling 思路。它的价值不是抽象更漂亮,而是把两类会频繁变化的逻辑拆开
- 收集本次要参与渲染的相机
- 复用 [SceneRenderRequestUtils](../SceneRenderRequestUtils/SceneRenderRequestUtils.md) 的规则组装 request
- 丢弃 render area 无效的 request
- 场景侧规则相机收集、stack/depth 排序、clear 推导、viewport 解析
- 执行侧规则scene extraction、主管线、object-id、post/overlay pass
这样 Editor、离屏渲染和手工 request 注入都能复用同一套规划规则,而不用直接碰 `CameraRenderer` 内部执行链。
## 公开方法
| 方法 | 说明 |
|------|------|
| [CollectCameras](CollectCameras.md) | 收集本次应参与渲染的相机列表。 |
| [BuildRequests](BuildRequests.md) | 把相机列表展开成可执行的 `CameraRenderRequest` 数组。 |
## 当前规划规则
- `CollectCameras(...)` 优先接受可用的 `overrideCamera`,否则收集场景相机并做稳定排序。
- `BuildRequests(...)` 逐个调用 `BuildCameraRenderRequest(...)`,并维护 base/request 计数以推导 `Auto` clear 行为。
### `CollectCameras()`
当前规则是:
1. 如果 `overrideCamera` 可用,则只渲染它自己。
2. 否则从场景里查找全部 `CameraComponent`
3. 过滤掉不可用相机。
4. 按 [SceneRenderRequestUtils](../SceneRenderRequestUtils/SceneRenderRequestUtils.md) 里的稳定排序规则整理顺序。
### `BuildRequests()`
它会按相机顺序逐个调用 `BuildCameraRenderRequest()`,并维护:
- `renderedBaseCameraCount`
- 已成功生成的 request 数量
这两个计数会影响自动 clear flag 的推导。
如果某个相机最终解析出的 render area 宽高为 `0`,该请求会被直接丢弃,而且不会错误地推进 base camera 计数。
## 设计取舍
当前 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 的行为。
## 当前实现边界
- 它只生成 request不执行 request
- 它不填充 `objectId`、fullscreen 阶段或 editor 注入的 pass sequence
- 它只规划相机请求,不处理 `objectId` 或各类 `RenderPassSequence` 的具体填充;那部分通常由更上层调用方补充
- 当前没有 camera stacking 的更复杂依赖分析,只有 base / overlay 与 depth 的线性排序
- `BuildRequests()` 只返回成功构建的请求,不单独报告被过滤掉的相机原因。
## 相关文档
- [Planning](../Planning.md)
- [当前模块](../../Rendering.md)
- [CollectCameras](CollectCameras.md)
- [BuildRequests](BuildRequests.md)
- [SceneRenderer](../../Execution/SceneRenderer/SceneRenderer.md)
- [SceneRenderRequestUtils](../SceneRenderRequestUtils/SceneRenderRequestUtils.md)
- [CameraRenderRequest](../CameraRenderRequest/CameraRenderRequest.md)
- [SceneRenderer](../../Execution/SceneRenderer/SceneRenderer.md)
- [Camera Request Planning And Clear Rules](../../../../_guides/Rendering/Camera-Request-Planning-And-Clear-Rules.md)

View File

@@ -6,32 +6,99 @@
**头文件**: `XCEngine/Rendering/Planning/SceneRenderRequestUtils.h`
**描述**: request planning 规则库,统一相机可用性判断、稳定排序、clear flag 推导、render area 解析,以及基础 `CameraRenderRequest` 组装。
**描述**: 提供相机可用性判断、稳定排序、clear flag 推导、render area 计算和 request 组装等内联 helper
## 概览
`SceneRenderRequestUtils` planning 层的规则收口点
`SceneRenderRequestUtils.h`当前相机请求规划链路的规则库
和 [SceneRenderRequestPlanner](../SceneRenderRequestPlanner/SceneRenderRequestPlanner.md) 的职责分工是:
它当前提供的核心 helper 包括:
- planner 决定“要处理哪些相机”
- utils 决定“这些相机和请求该怎样排序、怎样计算 clear、怎样落成具体 request”
- `IsUsableCamera(...)`
- `SortSceneCamerasForRendering(...)`
- `SortCameraRenderRequests(...)`
- `ResolveClearFlags(...)`
- `ResolveCameraRenderArea(...)`
- `BuildCameraRenderRequest(...)`
从工程角度看,`SceneRenderRequestUtils` 其实承担的是“统一规则口径”的角色。它把多相机渲染里最容易在不同调用方之间写散掉的逻辑收口成一套 header-level helper
## 当前规则重点
- 相机是否可用
- base / overlay 与 depth 的稳定排序
- `CameraClearMode::Auto` 的默认推导
- viewport 到最终 render area 的换算
- 场景相机按 `stackType -> depth` 稳定排序
- request 按 `cameraStackOrder -> cameraDepth` 稳定排序。
- `CameraClearMode::Auto` 不是固定值,而要结合 base/overlay 计数推导。
- normalized viewport 会叠加到父 `RenderSurface::renderArea` 上,而不是总以整张 surface 为基准。
这样 `SceneRenderer``SceneRenderRequestPlanner` 以及手工 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`
这里最值得注意的是overlay camera 不是永远只清 `Depth`
如果场景里根本没有 base camera第一个成功进入队列的 overlay request 仍然会回退到 `All`。这保证了“纯 overlay 场景”也能得到一个稳定起始帧,而不会直接叠到未定义颜色上。
### render area 计算
`ResolveCameraRenderArea()` 会把相机 `viewportRect` 解释成父 `RenderSurface` 当前 render area 的归一化子矩形:
- 左上边界使用 `floor`
- 右下边界使用 `ceil`
这意味着当前系统支持“在已有 render area 上再切子视口”,而不只是对整张 surface 做 0..1 映射。这对 Scene View、离屏窗口和分块渲染都很关键。
### 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 组装阶段只填基础字段;`objectId``preScenePasses``postScenePasses``overlayPasses` 仍可由上层继续补全。
## 相关文档
- [Planning](../Planning.md)
- [当前模块](../../Rendering.md)
- [SceneRenderRequestPlanner](../SceneRenderRequestPlanner/SceneRenderRequestPlanner.md)
- [CameraRenderRequest](../CameraRenderRequest/CameraRenderRequest.md)
- [SceneRenderer](../../Execution/SceneRenderer/SceneRenderer.md)
- [Camera Request Planning And Clear Rules](../../../../_guides/Rendering/Camera-Request-Planning-And-Clear-Rules.md)

View File

@@ -1,62 +0,0 @@
# RenderCameraData
**命名空间**: `XCEngine::Rendering`
**类型**: `struct`
**头文件**: `XCEngine/Rendering/FrameData/RenderCameraData.h`
**描述**: 保存渲染阶段实际使用的相机矩阵、清屏参数和视口尺寸。
## 概览
`RenderCameraData` 是“组件层的相机”到“渲染层可直接消费的数据块”之间的桥接结构。
当前主链路里:
- [RenderSceneUtility](../RenderSceneUtility/RenderSceneUtility.md) 的 `BuildRenderCameraData()` 负责先构建矩阵、世界位置和默认清屏色。
- [RenderSceneExtractor](../RenderSceneExtractor/RenderSceneExtractor.md) 把它装进 `RenderSceneData`
- [CameraRenderer](../CameraRenderer/CameraRenderer.md) 会在真正提交前再按 request 覆盖 `clearFlags`,必要时覆盖 `clearColor`
因此它不是“纯相机组件快照”,而是一次渲染提交最终会消费的相机数据槽位。
## `RenderClearFlags`
同一个头文件里还定义了当前使用的清屏位标志:
| 枚举值 | 说明 |
|------|------|
| `None` | 不清任何内容。 |
| `Color` | 只清颜色。 |
| `Depth` | 只清深度。 |
| `All` | 同时清颜色和深度。 |
当前还提供了按位 `|``&` 运算,以及 `HasRenderClearFlag(flags, flag)` helper供 [BuiltinForwardPipeline](../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md) 判断本次主场景是否需要清颜色/深度。
## 字段
| 字段 | 类型 | 说明 |
|------|------|------|
| `view` | `Math::Matrix4x4` | 视图矩阵。 |
| `projection` | `Math::Matrix4x4` | 投影矩阵。 |
| `viewProjection` | `Math::Matrix4x4` | `projection * view` 组合矩阵。 |
| `worldPosition` | `Math::Vector3` | 相机世界坐标。 |
| `clearColor` | `Math::Color` | 当前提交使用的清屏色。 |
| `clearFlags` | `RenderClearFlags` | 当前提交使用的清屏标志;默认值是 `All`。 |
| `viewportWidth` | `uint32_t` | 当前视口宽度。 |
| `viewportHeight` | `uint32_t` | 当前视口高度。 |
## 当前实现说明
- `BuildRenderCameraData()` 当前会写入 `view``projection``viewProjection``worldPosition``clearColor` 和 viewport 尺寸。
- 该函数不会根据 `CameraComponent::GetClearMode()` 推导 `clearFlags``RenderCameraData` 此时保留 struct 默认值 `RenderClearFlags::All`
- 真正的 per-request clear 语义在 `CameraRenderer::Render()` 里由 `request.clearFlags` 覆盖写回 `sceneData.cameraData.clearFlags`
- 当前 extractor 会在写入矩阵前对 `view``projection``viewProjection` 做转置,以适配现有 shader 常量布局。
## 相关文档
- [Rendering](../Rendering.md)
- [RenderSceneUtility](../RenderSceneUtility/RenderSceneUtility.md)
- [RenderSceneExtractor](../RenderSceneExtractor/RenderSceneExtractor.md)
- [CameraRenderer](../CameraRenderer/CameraRenderer.md)
- [CameraRenderRequest](../CameraRenderRequest/CameraRenderRequest.md)

View File

@@ -28,5 +28,5 @@ return device != nullptr && commandList != nullptr && commandQueue != nullptr;
## 相关文档
- [返回类型总览](RenderContext.md)
- [SceneRenderer::Render](../SceneRenderer/Render.md)
- [SceneRenderer::Render](../Execution/SceneRenderer/Render.md)
- [RenderPipeline::Initialize](../RenderPipeline/Initialize.md)

View File

@@ -44,4 +44,4 @@
- [当前模块](../Rendering.md)
- [RenderPipeline](../RenderPipeline/RenderPipeline.md)
- [SceneRenderer](../SceneRenderer/SceneRenderer.md)
- [SceneRenderer](../Execution/SceneRenderer/SceneRenderer.md)

View File

@@ -34,4 +34,4 @@ return renderQueue >=
## 相关文档
- [ResolveMaterialRenderQueue](ResolveMaterialRenderQueue.md)
- [RenderSceneExtractor](../RenderSceneExtractor/Extract.md)
- [RenderSceneExtractor](../Extraction/RenderSceneExtractor/Extract.md)

View File

@@ -34,7 +34,7 @@ const Resources::Texture* ResolveBuiltinBaseColorTexture(const Resources::Materi
## 当前语义要点
- semantic 元数据优先级高于约定别名。
- 这条 helper 只返回当前应绑定的贴图资源,不负责上传 GPU 纹理或创建 SRV那部分由 [RenderResourceCache](../RenderResourceCache/RenderResourceCache.md) 处理。
- 这条 helper 只返回当前应绑定的贴图资源,不负责上传 GPU 纹理或创建 SRV那部分由 [RenderResourceCache](../Caches/RenderResourceCache/RenderResourceCache.md) 处理。
- 如果所有路径都没命中,返回 `nullptr`,再由调用方决定是否使用 fallback 纹理。
## 测试覆盖

View File

@@ -76,6 +76,6 @@
## 相关文档
- [当前模块](../Rendering.md)
- [CameraRenderRequest](../CameraRenderRequest/CameraRenderRequest.md)
- [CameraRenderer](../CameraRenderer/CameraRenderer.md)
- [CameraRenderRequest](../Planning/CameraRenderRequest/CameraRenderRequest.md)
- [CameraRenderer](../Execution/CameraRenderer/CameraRenderer.md)
- [Passes](../Passes/Passes.md)

View File

@@ -9,7 +9,7 @@ virtual bool Initialize(const RenderContext& context) = 0;
## 当前语义
- 这是一个“显式预热”入口,用来让具体管线提前准备 shader、pipeline state、descriptor set、采样器等资源。
- 上层当前并不保证一定会在首次 [Render](Render.md) 前先调用这里。按 `engine/src/Rendering/CameraRenderer.cpp` 的现状,`CameraRenderer` 会直接进入 `m_pipeline->Render(...)`
- 上层当前并不保证一定会在首次 [Render](Render.md) 前先调用这里。按 `engine/src/Rendering/Execution/CameraRenderer.cpp` 的现状,`CameraRenderer` 会直接进入 `m_pipeline->Render(...)`
- 因此调用方只能依赖“成功后这条管线进入可渲染状态”这一契约,不能依赖具体初始化时机。
## 当前实现弹性

View File

@@ -24,11 +24,11 @@ virtual bool Render(
- object-id pass
- `preScenePasses` / `postScenePasses` / `overlayPasses` 编排
这些外层编排由 [CameraRenderer](../CameraRenderer/CameraRenderer.md) 负责。
这些外层编排由 [CameraRenderer](../Execution/CameraRenderer/CameraRenderer.md) 负责。
## 当前调用位置
`engine/src/Rendering/CameraRenderer.cpp`,当前主链路顺序是:
`engine/src/Rendering/Execution/CameraRenderer.cpp`,当前主链路顺序是:
1. `preScenePasses`
2. `shadowCaster`
@@ -42,7 +42,7 @@ virtual bool Render(
## 当前实现弹性
- 具体实现可以假定 `sceneData` 已经由 [RenderSceneExtractor](../RenderSceneExtractor/RenderSceneExtractor.md) 产出。
- 具体实现可以假定 `sceneData` 已经由 [RenderSceneExtractor](../Extraction/RenderSceneExtractor/RenderSceneExtractor.md) 产出。
- 具体实现也可以在这里内部做惰性初始化,只要对调用方维持一致的成败语义。
## 参数
@@ -59,6 +59,6 @@ virtual bool Render(
## 相关文档
- [返回类型总览](RenderPipeline.md)
- [CameraRenderer::Render](../CameraRenderer/Render.md)
- [RenderSceneExtractor](../RenderSceneExtractor/RenderSceneExtractor.md)
- [CameraRenderer::Render](../Execution/CameraRenderer/Render.md)
- [RenderSceneExtractor](../Extraction/RenderSceneExtractor/RenderSceneExtractor.md)
- [RenderSurface](../RenderSurface/RenderSurface.md)

View File

@@ -39,7 +39,7 @@
- object-id pass 与 object-id 输出目标
- `preScenePasses` / `postScenePasses` / `overlayPasses` 的外层编排
这些都由 [CameraRenderer](../CameraRenderer/CameraRenderer.md) 在外层编排。
这些都由 [CameraRenderer](../Execution/CameraRenderer/CameraRenderer.md) 在外层编排。
## 当前实现弹性
@@ -72,7 +72,7 @@
## 相关文档
- [Rendering](../Rendering.md)
- [CameraRenderer](../CameraRenderer/CameraRenderer.md)
- [CameraRenderer](../Execution/CameraRenderer/CameraRenderer.md)
- [RenderPipelineAsset](../RenderPipelineAsset/RenderPipelineAsset.md)
- [BuiltinForwardPipelineAsset](../Pipelines/BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md)
- [SceneRenderer](../SceneRenderer/SceneRenderer.md)
- [SceneRenderer](../Execution/SceneRenderer/SceneRenderer.md)

View File

@@ -8,7 +8,7 @@ virtual void Shutdown() = 0;
## 当前调用语义
`engine/src/Rendering/CameraRenderer.cpp` 可以看到,当前主要调用方会在这些时机直接调用它:
`engine/src/Rendering/Execution/CameraRenderer.cpp` 可以看到,当前主要调用方会在这些时机直接调用它:
- `CameraRenderer` 析构时。
- `CameraRenderer::ResetPipeline()` 替换旧 pipeline 时。

View File

@@ -12,7 +12,7 @@
`RenderPipelineAsset` 不负责自己绘制场景,而是回答一个更高层的问题:
- 当前这台 [CameraRenderer](../CameraRenderer/CameraRenderer.md) 应该创建哪一种主场景 runtime 管线?
- 当前这台 [CameraRenderer](../Execution/CameraRenderer/CameraRenderer.md) 应该创建哪一种主场景 runtime 管线?
这层抽象把“选择哪条主管线”和“真正执行主场景绘制”拆开:
@@ -21,11 +21,11 @@
## 当前真实接线
当前最直接的消费者是 [CameraRenderer](../CameraRenderer/CameraRenderer.md)
当前最直接的消费者是 [CameraRenderer](../Execution/CameraRenderer/CameraRenderer.md)
- 默认构造路径会持有一份默认 asset
- [SetPipelineAsset](../CameraRenderer/SetPipelineAsset.md) 会通过 asset 重建当前 runtime pipeline
- [GetPipelineAsset](../CameraRenderer/GetPipelineAsset.md) 返回的是工厂对象,不是 runtime pipeline 实例
- [SetPipelineAsset](../Execution/CameraRenderer/SetPipelineAsset.md) 会通过 asset 重建当前 runtime pipeline
- [GetPipelineAsset](../Execution/CameraRenderer/GetPipelineAsset.md) 返回的是工厂对象,不是 runtime pipeline 实例
按当前源码,默认 concrete asset 是 [BuiltinForwardPipelineAsset](../Pipelines/BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md)。
@@ -52,7 +52,7 @@
## 设计说明
这一层的重要性不在于“多包一层接口”,而在于把“选哪种主管线”从 [CameraRenderer](../CameraRenderer/CameraRenderer.md) 的执行逻辑里抽出来。
这一层的重要性不在于“多包一层接口”,而在于把“选哪种主管线”从 [CameraRenderer](../Execution/CameraRenderer/CameraRenderer.md) 的执行逻辑里抽出来。
这样后续即便增加新的 concrete pipeline也不需要改动单 request 执行主链路。
## 相关文档

View File

@@ -1,71 +0,0 @@
# RenderResourceCache
**命名空间**: `XCEngine::Rendering`
**类型**: `class`
**头文件**: `XCEngine/Rendering/Caches/RenderResourceCache.h`
**描述**: 负责把 `Mesh``Texture` 上传成 RHI 资源,并在渲染阶段按资源指针缓存这些 GPU 对象。
## 概述
`RenderResourceCache` 解决的是一个典型渲染层问题:场景与资源系统持有的是 CPU 侧 `Mesh` / `Texture` 对象,但绘制时真正需要的是 GPU 侧 buffer、texture 和 resource view。
当前缓存分成两类:
- `CachedMesh`
- `CachedTexture`
## `CachedMesh`
| 字段 | 说明 |
|------|------|
| `vertexBuffer` | 顶点缓冲对象。 |
| `vertexBufferView` | 顶点缓冲视图。 |
| `indexBuffer` | 索引缓冲对象。 |
| `indexBufferView` | 索引缓冲视图。 |
| `vertexCount` | 顶点数量。 |
| `indexCount` | 索引数量。 |
| `vertexStride` | 顶点步长。 |
| `uses32BitIndices` | 是否使用 32 位索引。 |
## `CachedTexture`
| 字段 | 说明 |
|------|------|
| `texture` | GPU 纹理对象。 |
| `shaderResourceView` | 着色器资源视图。 |
| `width` | 纹理宽度。 |
| `height` | 纹理高度。 |
## 当前实现边界
- cache key 是 `const Resources::Mesh*``const Resources::Texture*` 裸指针。
- 当前没有脏标记或版本号,因此资源内容发生变化后,缓存不会自动失效。
- 当前不是线程安全的。
- 纹理格式映射目前只覆盖 `RGBA8_UNORM``RGBA8_SRGB`
- 上传纹理时当前固定按 `width * 4` 计算 `rowPitch`,因此只适用于当前支持的 4 字节每像素路径。
## 公开方法
| 方法 | 说明 |
|------|------|
| [Destructor](Destructor.md) | 析构时清空缓存。 |
| [Shutdown](Shutdown.md) | 释放所有已缓存 GPU 资源。 |
| [GetOrCreateMesh](GetOrCreateMesh.md) | 获取或创建网格缓存。 |
| [GetOrCreateTexture](GetOrCreateTexture.md) | 获取或创建纹理缓存。 |
## 设计说明
把上传和缓存放在渲染层,而不是资源层,是个务实选择:
- 资源层可以保持对具体 RHI 后端无感。
- 渲染层可以根据当前 backend 和管线需要决定上传方式。
## 相关文档
- [当前模块](../Rendering.md)
- [BuiltinForwardPipeline](../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md)
- [RenderContext](../RenderContext/RenderContext.md)

View File

@@ -1,87 +0,0 @@
# RenderSceneExtractor
**命名空间**: `XCEngine::Rendering`
**类型**: `class + related structs`
**头文件**: `XCEngine/Rendering/Extraction/RenderSceneExtractor.h`
**描述**: 把 `Scene` 压平成渲染侧可消费的 `RenderSceneData`,负责相机选择、主方向光提取和 `visibleItems` 收集。
## 概览
`RenderSceneExtractor` 处在“场景对象组织”和“单相机渲染提交”之间。它不负责真正发 draw call而是把场景转换成一份更适合渲染阶段消费的数据
- `camera`
- `cameraData`
- `lighting`
- `visibleItems`
当前 `CameraRenderer` 会在执行单个 `CameraRenderRequest` 时调用它。
## `RenderSceneData`
| 字段 | 类型 | 说明 |
|------|------|------|
| `camera` | `Components::CameraComponent*` | 当前提取使用的相机。 |
| `cameraData` | `RenderCameraData` | 由相机和 viewport 推导出的渲染相机数据。 |
| `lighting` | `RenderLightingData` | 当前主方向光快照。 |
| `visibleItems` | `std::vector<VisibleRenderItem>` | 当前帧提取出的可绘制项列表。 |
`RenderSceneData::HasCamera()` 当前只是检查 `camera != nullptr`
## 当前提取规则
### 相机
- `SelectCamera()` 优先使用可用的 `overrideCamera`
- 否则在场景里选出所有可用相机中的“最高深度 primary camera”。
- 如果没有 primary则回退到第一个可用相机。
### 光照
- 只提取可用的方向光。
- 当前只保留一盏“主方向光”。
- 选择规则是“强度最高的可用方向光”。
### 可绘制项
- 只递归遍历 `IsActiveInHierarchy()` 的对象。
- 先按相机 `cullingMask` 过滤 `GameObject` 层。
- 对通过过滤的对象,调用 `AppendRenderItemsForGameObject(...)` 展开成一个或多个 `VisibleRenderItem`
因此当前 `visibleItems` 不只是旧说法里的“visible object 列表”而是已经展开过材质、section、render queue 和相机距离的渲染项数组。
## 当前排序规则
提取完成后,`visibleItems` 会做一次 `std::stable_sort`
1. `renderQueue` 小的排前面。
2. 如果是透明队列,按 `cameraDistanceSq` 从远到近。
3. 否则按 `cameraDistanceSq` 从近到远。
4. 最后再按 `gameObject` 指针和 `sectionIndex` 打破平局。
这让 opaque 与 transparent 的默认排序方向和当前 `RenderMaterialUtility` 的队列语义保持一致。
## 当前限制
- 没有 frustum culling。
- 没有 occlusion culling。
- 没有 batching 或 instancing。
- 只提取单个主方向光,不保留多光源列表。
## 公开方法
| 方法 | 说明 |
|------|------|
| [Extract](Extract.md) | 自动选择相机并提取 `RenderSceneData`。 |
| [ExtractForCamera](ExtractForCamera.md) | 使用显式给定相机提取 `RenderSceneData`。 |
| [SelectCamera](SelectCamera.md) | 按当前规则选择可用相机。 |
## 相关文档
- [Rendering](../Rendering.md)
- [VisibleRenderObject](../VisibleRenderObject/VisibleRenderObject.md)
- [CameraRenderer](../CameraRenderer/CameraRenderer.md)
- [Scene Extraction And Builtin Forward Pipeline](../../../_guides/Rendering/Scene-Extraction-And-Builtin-Forward-Pipeline.md)

View File

@@ -1,74 +0,0 @@
# RenderSceneUtility
**命名空间**: `XCEngine::Rendering`
**类型**: `utility header`
**头文件**: `XCEngine/Rendering/Extraction/RenderSceneUtility.h`
**描述**: 提供把相机和场景对象翻译成 `RenderCameraData``VisibleRenderItem` 的基础 helper。
## 概览
`RenderSceneUtility.h` 位于 [RenderSceneExtractor](../RenderSceneExtractor/RenderSceneExtractor.md) 的下层,负责两类最基础的转换:
1.`CameraComponent` 的参数整理成渲染侧消费的 [RenderCameraData](../RenderCameraData/RenderCameraData.md)
2.`GameObject + MeshFilter + MeshRenderer` 组合展开成可绘制的 `VisibleRenderItem`
## 公开函数
### `BuildRenderCameraData()`
根据相机组件和目标视口大小构建 [RenderCameraData](../RenderCameraData/RenderCameraData.md)
- 复制 `viewportWidth` / `viewportHeight`
- 读取相机世界位置和 `clearColor`
- 根据投影模式构建 perspective 或 orthographic 投影矩阵
-`view``projection``viewProjection` 以转置后的矩阵形式写入结果
当前还要注意一个边界:
- 这里不会根据 `CameraComponent::GetClearMode()` 推导 `clearFlags`
- 返回结果里的 `clearFlags` 仍保留 [RenderCameraData](../RenderCameraData/RenderCameraData.md) 的默认值 `RenderClearFlags::All`
- 真正的 per-request clear 规则是在 [SceneRenderRequestUtils](../SceneRenderRequestUtils/SceneRenderRequestUtils.md) 先解析成 `CameraRenderRequest::clearFlags`,再由 [CameraRenderer](../CameraRenderer/CameraRenderer.md) 写回 `sceneData.cameraData.clearFlags`
### `AppendRenderItemsForGameObject()`
把单个 `GameObject` 追加成一个或多个 `VisibleRenderItem`
当前筛选规则是:
- 非激活对象直接跳过
- 缺少 `MeshFilterComponent``MeshRendererComponent` 直接跳过
- 任一组件被禁用时跳过
- `mesh == nullptr``mesh->IsValid() == false` 时跳过
若 mesh 存在 section则每个 section 生成一个 `VisibleRenderItem`;否则退化成单个无 section 的 item。
### `CollectRenderItemsForEntityIds()`
按给定 `entityIds` 收集可绘制对象,当前会:
- 跳过 `0`
- 去重重复实体 ID
- 忽略找不到的对象
- 复用 `AppendRenderItemsForGameObject()` 展开 section
## 真实使用位置
- `engine/src/Rendering/RenderSceneExtractor.cpp` 用它构建相机数据和可见物体列表。
- `tests/Rendering/unit/test_render_scene_utility.cpp` 覆盖了相机矩阵约定、实体过滤和 section 展开。
## 当前实现边界
- 当前没有做 frustum culling、LOD、遮挡剔除或 batching。
- `cameraDistanceSq` 只按对象变换平移量估算,不考虑 bounds 中心或 section 级差异。
- 这些函数直接操作场景对象和组件引用,还不是完全解耦的 render proxy 阶段。
## 相关文档
- [Rendering](../Rendering.md)
- [RenderCameraData](../RenderCameraData/RenderCameraData.md)
- [RenderSceneExtractor](../RenderSceneExtractor/RenderSceneExtractor.md)
- [VisibleRenderObject](../VisibleRenderObject/VisibleRenderObject.md)
- [RenderMaterialUtility](../RenderMaterialUtility/RenderMaterialUtility.md)

View File

@@ -18,7 +18,7 @@ uint32_t GetWidth() const;
## 调用方影响
- [CameraRenderer](../CameraRenderer/Render.md) 会通过 render area 的宽高决定是否继续渲染;默认 render area 又直接依赖这里的宽度。
- [CameraRenderer](../Execution/CameraRenderer/Render.md) 会通过 render area 的宽高决定是否继续渲染;默认 render area 又直接依赖这里的宽度。
- `SceneRenderer` 构建请求时,也会把 surface 的宽高传播到每个相机请求的默认 viewport 尺寸。
## 测试覆盖

View File

@@ -1,85 +0,0 @@
# SceneRenderRequestPlanner
**命名空间**: `XCEngine::Rendering`
**类型**: `class`
**头文件**: `XCEngine/Rendering/Planning/SceneRenderRequestPlanner.h`
**描述**: 负责从场景和可选 override camera 生成实际要提交给 `CameraRenderer` 的相机请求列表。
## 概览
`SceneRenderRequestPlanner` 处在 [SceneRenderer](../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` 内部执行链。
## 公开方法
| 方法 | 说明 |
|------|------|
| [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 故意保持“只做一件事”:
- 负责决定 request 集合
- 不负责 request 执行
- 不负责附加 pass 组装
这是一种比很多早期引擎实现更稳的做法。否则 Scene View 一旦要加 object-id、grid、selection outline、editor overlay规划逻辑和执行逻辑很容易在一个类里互相缠死。
另一个重要取舍是:当前只支持 base / overlay + depth 的线性排序,而不是更复杂的 stacking 依赖图。
这不是文档漏写,而是当前实现的真实边界。它优先保证顺序简单、稳定、可测试。
## 真实使用位置
- `engine/include/XCEngine/Rendering/SceneRenderer.h` 持有一个 `SceneRenderRequestPlanner` 实例。
- `engine/src/Rendering/SceneRenderRequestPlanner.cpp` 实现具体收集与构建逻辑。
- `tests/Rendering/unit/test_scene_render_request_planner.cpp` 覆盖了 override camera、稳定排序和零尺寸 viewport 的行为。
## 当前实现边界
- 它只规划相机请求,不处理 `objectId` 或各类 `RenderPassSequence` 的具体填充;那部分通常由更上层调用方补充。
- 当前没有 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)
- [Camera Request Planning And Clear Rules](../../../_guides/Rendering/Camera-Request-Planning-And-Clear-Rules.md)

View File

@@ -1,104 +0,0 @@
# SceneRenderRequestUtils
**命名空间**: `XCEngine::Rendering::SceneRenderRequestUtils`
**类型**: `utility header`
**头文件**: `XCEngine/Rendering/Planning/SceneRenderRequestUtils.h`
**描述**: 提供相机可用性判断、稳定排序、clear flag 推导、render area 计算和 request 组装等内联 helper。
## 概览
`SceneRenderRequestUtils.h` 是当前相机请求规划链路的规则库。
和 [SceneRenderRequestPlanner](../SceneRenderRequestPlanner/SceneRenderRequestPlanner.md) 的职责分工是:
- planner 决定“要处理哪些相机”
- utils 决定“这些相机和请求该怎样排序、怎样计算 clear、怎样落成具体 request”
从工程角度看,`SceneRenderRequestUtils` 其实承担的是“统一规则口径”的角色。它把多相机渲染里最容易在不同调用方之间写散掉的逻辑收口成一套 header-level helper
- 相机是否可用
- base / overlay 与 depth 的稳定排序
- `CameraClearMode::Auto` 的默认推导
- viewport 到最终 render area 的换算
这样 `SceneRenderer``SceneRenderRequestPlanner` 以及手工 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`
这里最值得注意的是overlay camera 不是永远只清 `Depth`
如果场景里根本没有 base camera第一个成功进入队列的 overlay request 仍然会回退到 `All`。这保证了“纯 overlay 场景”也能得到一个稳定起始帧,而不会直接叠到未定义颜色上。
### render area 计算
`ResolveCameraRenderArea()` 会把相机 `viewportRect` 解释成父 `RenderSurface` 当前 render area 的归一化子矩形:
- 左上边界使用 `floor`
- 右下边界使用 `ceil`
这意味着当前系统支持“在已有 render area 上再切子视口”,而不只是对整张 surface 做 0..1 映射。这对 Scene View、离屏窗口和分块渲染都很关键。
### 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 组装阶段只填基础字段;`objectId``preScenePasses``postScenePasses``overlayPasses` 仍可由上层继续补全。
## 相关文档
- [当前模块](../Rendering.md)
- [SceneRenderRequestPlanner](../SceneRenderRequestPlanner/SceneRenderRequestPlanner.md)
- [CameraRenderRequest](../CameraRenderRequest/CameraRenderRequest.md)
- [SceneRenderer](../SceneRenderer/SceneRenderer.md)
- [Camera Request Planning And Clear Rules](../../../_guides/Rendering/Camera-Request-Planning-And-Clear-Rules.md)

View File

@@ -1,45 +0,0 @@
# SceneRenderer::BuildRenderRequests
```cpp
std::vector<CameraRenderRequest> 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)

View File

@@ -1,33 +0,0 @@
# SceneRenderer::SceneRenderer
构造一个场景级渲染器。
```cpp
SceneRenderer();
explicit SceneRenderer(std::unique_ptr<RenderPipeline> pipeline);
explicit SceneRenderer(std::shared_ptr<const RenderPipelineAsset> pipelineAsset);
```
## 当前语义
- 三个构造路径的差别只在于内部 `m_cameraRenderer` 如何初始化。
- 默认构造:使用 `CameraRenderer` 的默认构造路径,最终回退到默认 builtin forward pipeline asset。
- `std::unique_ptr<RenderPipeline>` 构造:把调用方提供的 runtime pipeline 直接交给内部 `CameraRenderer` 持有。
- `std::shared_ptr<const RenderPipelineAsset>` 构造:让内部 `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)

View File

@@ -1,63 +0,0 @@
# SceneRenderer::Render
```cpp
bool Render(const CameraRenderRequest& request);
bool Render(const std::vector<CameraRenderRequest>& 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<CameraRenderRequest>&)`
当前实现会:
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)

View File

@@ -1,119 +0,0 @@
# 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<CameraRenderRequest>&)`
当前会:
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<RenderPipeline>` 时,走“手动注入 runtime pipeline”路径。
- 传入 `std::shared_ptr<const RenderPipelineAsset>` 时,走“由 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)

View File

@@ -1,61 +0,0 @@
# VisibleRenderObject
**命名空间**: `XCEngine::Rendering`
**类型**: `struct alias`
**头文件**: `XCEngine/Rendering/FrameData/VisibleRenderItem.h`
**描述**: `VisibleRenderObject` 当前只是 `VisibleRenderItem` 的兼容别名。它表示 scene extraction 之后交给渲染阶段消费的一条可绘制项记录。
## 概览
头文件里的真实结构名已经是 `VisibleRenderItem`
```cpp
using VisibleRenderObject = VisibleRenderItem;
```
因此这页保留的是历史命名入口,但语义应按当前 `VisibleRenderItem` 来理解。它不再只是“一个 mesh 对象”而是已经带上材质槽位、section 信息、render queue 和相机距离的渲染项。
## 当前字段
| 字段 | 类型 | 说明 |
|------|------|------|
| `gameObject` | `Components::GameObject*` | 来源场景对象。 |
| `meshFilter` | `Components::MeshFilterComponent*` | 提供 mesh 引用的组件。 |
| `meshRenderer` | `Components::MeshRendererComponent*` | 提供材质与渲染状态的组件。 |
| `mesh` | `Resources::Mesh*` | 当前要绘制的 mesh。 |
| `material` | `const Resources::Material*` | 当前解析出的材质指针,可为空。 |
| `materialIndex` | `Core::uint32` | 当前材质槽位索引。 |
| `sectionIndex` | `Core::uint32` | 当前 section 索引。 |
| `hasSection` | `bool` | 当前项是否绑定到特定 section。 |
| `renderQueue` | `Core::int32` | 当前项的渲染队列。 |
| `cameraDistanceSq` | `float` | 到当前相机的距离平方,用于排序。 |
| `localToWorld` | `Math::Matrix4x4` | 当前项的世界变换。 |
## 当前生成方式
- [RenderSceneExtractor](../RenderSceneExtractor/RenderSceneExtractor.md) 会递归遍历场景并调用 `AppendRenderItemsForGameObject(...)`
- 同一个 `GameObject` 可能展开成多个 `VisibleRenderItem`,例如一个 mesh 有多个 section 时。
- `material``materialIndex``renderQueue``cameraDistanceSq` 都在提取阶段就已经写入,后续主管线不必再回到场景层重新推导。
## 当前使用位置
- `RenderSceneExtractor` 输出 `RenderSceneData::visibleItems`
- `BuiltinForwardPipeline` 遍历这些项并决定 shader/pass、descriptor set 和 draw call。
- `BuiltinObjectIdPass` 也复用同一批 `visibleItems` 做 object-id 绘制。
## 当前限制
- 当前仍是轻量运行时结构,不是长期缓存的 render proxy。
- `cameraDistanceSq` 只是当前相机视角下的一次性排序辅助数据。
- 兼容别名 `VisibleRenderObject` 仍保留,但新文档和新实现都应优先使用 `VisibleRenderItem` 这个名称。
## 相关文档
- [Rendering](../Rendering.md)
- [RenderSceneExtractor](../RenderSceneExtractor/RenderSceneExtractor.md)
- [RenderSceneUtility](../RenderSceneUtility/RenderSceneUtility.md)
- [BuiltinForwardPipeline](../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md)