docs: expand rendering core docs

This commit is contained in:
2026-04-03 15:30:47 +08:00
parent e8f64407ba
commit 4616e6fd1f
16 changed files with 636 additions and 241 deletions

View File

@@ -0,0 +1,57 @@
# ObjectIdEncoding
**命名空间**: `XCEngine::Rendering`
**类型**: `utility header`
**头文件**: `XCEngine/Rendering/ObjectIdEncoding.h`
**描述**: 提供对象 ID 和颜色缓冲之间的轻量编解码 helper供 object-id 渲染与拾取链路共享。
## 概览
`ObjectIdEncoding.h` 把“对象 ID 写进颜色缓冲,再从颜色缓冲读回来”的协议固定成了三段小函数。
当前这套协议主要服务于:
- [BuiltinObjectIdPass](../Passes/BuiltinObjectIdPass/BuiltinObjectIdPass.md) 把对象 ID 编码到 object-id 纹理
- [BuiltinObjectIdOutlinePass](../Passes/BuiltinObjectIdOutlinePass/BuiltinObjectIdOutlinePass.md) 生成选中轮廓时复用同样的颜色表示
- editor viewport 的 object picker 从像素颜色反解回 `entityId`
## 编码规则
### `EncodeObjectIdToUInt32()`
把传入的 `uint64_t objectId` 截断成低 `32` 位。
### `EncodeObjectIdToColor()`
把编码后的 `uint32` 拆成四个 `8-bit` 通道,并按 `0..255 -> 0..1` 归一化为 `Vector4`
- `r` 对应最低 8 位
- `g` 对应第 8-15 位
- `b` 对应第 16-23 位
- `a` 对应第 24-31 位
### `DecodeObjectIdFromColor()`
按同样的通道顺序把 `r/g/b/a` 重新拼回 `uint32_t`
## 当前实现边界
- 高于 `32` 位的对象身份当前会被截断,无法通过 object-id 颜色缓冲完整保真。
- 这里的 helper 只定义字节打包协议,不处理颜色空间、纹理格式选择或 GPU 读回流程。
- `DecodeObjectIdFromColor()` 返回 `uint32_t`,调用方如果内部仍使用 `uint64_t`,需要自己做扩展或约定。
## 真实使用位置
- `engine/src/Rendering/Passes/BuiltinObjectIdPass.cpp` 用它把对象 ID 写进 shader 常量。
- `engine/src/Rendering/Passes/BuiltinObjectIdOutlinePass.cpp` 用它构建选中对象颜色列表。
- `editor/src/Viewport/ViewportObjectIdPicker.h` 用它把像素颜色解码成拾取结果。
## 相关文档
- [当前模块](../Rendering.md)
- [ObjectIdPass](../ObjectIdPass/ObjectIdPass.md)
- [BuiltinObjectIdPass](../Passes/BuiltinObjectIdPass/BuiltinObjectIdPass.md)
- [BuiltinObjectIdOutlinePass](../Passes/BuiltinObjectIdOutlinePass/BuiltinObjectIdOutlinePass.md)

View File

@@ -10,16 +10,17 @@
## 概览
`BuiltinForwardPipelineAsset` 是当前渲染模块里唯一公开的 concrete pipeline asset。它的职责很简单:
`BuiltinForwardPipelineAsset` 是当前渲染模块里唯一公开的 concrete pipeline asset。
它的职责很窄:
- 作为默认主管线工厂存在
- 在需要时返回一条新的 `BuiltinForwardPipeline`
`engine/src/Rendering/CameraRenderer.cpp` 的当前接线:
- `CameraRenderer` 默认构造路径会使用静态共享的 `BuiltinForwardPipelineAsset`
- `SetPipelineAsset()` 也会通过这类 asset 重建当前主管线实例
- 如果外部传入空 asset当前仍会回退到默认 `BuiltinForwardPipelineAsset`
- `CameraRenderer` 默认构造会使用静态共享的 `BuiltinForwardPipelineAsset`
- [SetPipelineAsset](../../CameraRenderer/SetPipelineAsset.md) 也可以显式切回这条 asset 路径
- 如果外部 asset 传空,回退到默认 `BuiltinForwardPipelineAsset` 的逻辑发生在 `CameraRenderer`,不是这个类内部
## 生命周期与所有权
@@ -27,13 +28,11 @@
- 它创建出来的 pipeline 以 `std::unique_ptr<RenderPipeline>` 返回
- runtime pipeline 的生命周期最终由 `CameraRenderer` 或调用方接管,而不是由 asset 自己保留
这就是“共享工厂对象 + 独占运行时实例”的典型渲染系统分层。
## 当前实现边界
- 当前没有任何可配置字段
- 不能通过它选择不同 shader、不同 pass 序列或不同渲染路径
-不是项目资源数据库里的可序列化 renderer asset只是 C++ 工厂对象
- 当前没有任何可配置字段
- 不能通过它切换不同 shader、不同 pass 序列或不同渲染路径
-仍然不是项目资源数据库里的 renderer asset只是一个 C++ 工厂对象
## 公开方法

View File

@@ -24,17 +24,18 @@ std::make_unique<BuiltinForwardPipeline>()
- 每次调用都会生成一条新的 `BuiltinForwardPipeline`
- 当前不会复用已有 runtime pipeline
- 当前也不会返回 `nullptr`
- 当前这个方法本身不会做额外 fallback 分支
## 当前调用位置
## 与外层 fallback 的边界
`CameraRenderer` 通过内部 `CreatePipelineFromAsset()` 使用这个方法:
1. 若当前有 `pipelineAsset`,先执行 `asset->CreatePipeline()`
2. 拿到有效实例,就接管这条新管线
3. asset 为空或返回空指针,再回退到直接 `std::make_unique<BuiltinForwardPipeline>()`
1. 先尝试 `asset->CreatePipeline()`
2. 如果拿到有效实例,就接管这条新管线
3. 如果 asset 为空或返回空指针,再`CameraRenderer` 回退到直接 `std::make_unique<BuiltinForwardPipeline>()`
`BuiltinForwardPipelineAsset` 来说,第 3 步当前基本不会触发
`BuiltinForwardPipelineAsset` 来说,第 3 步是调用方策略,不是这里的方法体逻辑
按当前实现,这个方法自身也不会返回 `nullptr`
## 返回值

View File

@@ -6,20 +6,31 @@
**头文件**: `XCEngine/Rendering/RenderCameraData.h`
**描述**: 保存渲染阶段实际使用的相机矩阵、清屏和视口尺寸。
**描述**: 保存渲染阶段实际使用的相机矩阵、清屏参数和视口尺寸。
## 概
## 概
`RenderCameraData` 是“场景组件层的相机”“渲染层可直接消费的数据块”之间的桥接结构。
`RenderCameraData` 是“组件层的相机”“渲染层可直接消费的数据块”之间的桥接结构。
当前主链路里:
这种拆分很有价值,因为渲染层通常不应该直接依赖完整 `CameraComponent` 行为,而是应该消费一份已经拍平的渲染数据:
- [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) 判断本次主场景是否需要清颜色/深度。
## 字段
@@ -29,18 +40,22 @@
| `projection` | `Math::Matrix4x4` | 投影矩阵。 |
| `viewProjection` | `Math::Matrix4x4` | `projection * view` 组合矩阵。 |
| `worldPosition` | `Math::Vector3` | 相机世界坐标。 |
| `clearColor` | `Math::Color` | 默认清屏色。 |
| `clearColor` | `Math::Color` | 当前提交使用的清屏色。 |
| `clearFlags` | `RenderClearFlags` | 当前提交使用的清屏标志;默认值是 `All`。 |
| `viewportWidth` | `uint32_t` | 当前视口宽度。 |
| `viewportHeight` | `uint32_t` | 当前视口高度。 |
## 当前实现说明
- 这组矩阵由 [RenderSceneExtractor](../RenderSceneExtractor/RenderSceneExtractor.md) 构造
- 当前 extractor 会在写入这里之前对 `view``projection``viewProjection` 做转置
- 这说明当前渲染路径是按“尽量让 shader 直接消费统一矩阵布局”的思路设计的
- `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.md)
- [Rendering](../Rendering.md)
- [RenderSceneUtility](../RenderSceneUtility/RenderSceneUtility.md)
- [RenderSceneExtractor](../RenderSceneExtractor/RenderSceneExtractor.md)
- [VisibleRenderObject](../VisibleRenderObject/VisibleRenderObject.md)
- [CameraRenderer](../CameraRenderer/CameraRenderer.md)
- [CameraRenderRequest](../CameraRenderRequest/CameraRenderRequest.md)

View File

@@ -0,0 +1,44 @@
# BuildBuiltinForwardMaterialData
**命名空间**: `XCEngine::Rendering`
**类型**: `function`
**头文件**: `XCEngine/Rendering/RenderMaterialUtility.h`
## 签名
```cpp
BuiltinForwardMaterialData BuildBuiltinForwardMaterialData(const Resources::Material* material);
```
## 作用
把 builtin forward 当前真正消费的材质常量打包成 `BuiltinForwardMaterialData`
## 当前实现行为
当前实现非常窄,只做一件事:
1. 构造默认的 `BuiltinForwardMaterialData`
2. 用 [ResolveBuiltinBaseColorFactor](ResolveBuiltinBaseColorFactor.md) 填充 `baseColorFactor`
3. 返回结果
也就是说,当前 builtin forward 材质常量块里只公开收口了颜色因子,没有把纹理、采样器或其它材质属性打进这个 struct。
## 当前语义边界
- 这是 builtin forward 私有契约的一部分,不是通用材质序列化格式。
- 贴图绑定不在这里返回;调用方仍需单独用 [ResolveBuiltinBaseColorTexture](ResolveBuiltinBaseColorTexture.md) 解析。
- 如果未来 builtin forward 的 per-material 常量扩展,这个 helper 和 `BuiltinForwardMaterialData` 也会一起扩展。
## 测试覆盖
`tests/Rendering/unit/test_render_scene_extractor.cpp` 当前验证了它会按 canonical 名称和别名路径正确写入 `baseColorFactor`
## 相关文档
- [ResolveBuiltinBaseColorFactor](ResolveBuiltinBaseColorFactor.md)
- [ResolveBuiltinBaseColorTexture](ResolveBuiltinBaseColorTexture.md)
- [BuiltinForwardPipeline](../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md)
- [RenderMaterialUtility](RenderMaterialUtility.md)

View File

@@ -6,19 +6,20 @@
**头文件**: `XCEngine/Rendering/RenderMaterialUtility.h`
**描述**: 把 `Material` 的 pass 元数据、render queue 和 render state 解释成渲染提取与图形管线可直接使用的规则。
**描述**: 把 `Material` 的 pass 元数据、builtin forward 材质契约、render queue 和 render state 解释成渲染提取与图形管线可直接使用的规则。
## 概览
`RenderMaterialUtility.h` 不是运行时对象,而是一组内联规则函数。它当前承担类工作:
`RenderMaterialUtility.h` 不是运行时对象,而是一组内联规则函数。它当前承担类工作:
1. 解析“这次绘制真正要用哪份材质”。
2. 判断该材质是否匹配某个 builtin pass。
3. 把材质里的 `MaterialRenderState` 翻译成 `RHI::GraphicsPipelineDesc` 需要的状态结构
3. 解析 builtin forward 路径要消费的 base-color 因子与贴图
4. 把材质里的 `MaterialRenderState` 翻译成 `RHI::GraphicsPipelineDesc` 需要的状态结构。
这组函数位于 [RenderSceneExtractor](../RenderSceneExtractor/RenderSceneExtractor.md)、builtin forward pipeline 和 object-id 相关 pass 之间,是当前材质语义进入渲染路的关键翻译层。
位于 [RenderSceneExtractor](../RenderSceneExtractor/RenderSceneExtractor.md)、[BuiltinForwardPipeline](../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md) 和 object-id 相关 pass 之间,是当前材质语义进入渲染路的关键翻译层。
## BuiltinMaterialPass
## `BuiltinMaterialPass`
当前公开的 builtin pass 枚举包括:
@@ -26,8 +27,8 @@
|------|------|
| `ForwardLit` | 默认前向绘制路径。 |
| `Unlit` | 非受光绘制路径。 |
| `DepthOnly` | 深度预写 / depth-only 通道。 |
| `ShadowCaster` | 阴影投射通道。 |
| `DepthOnly` | 深度预写 / depth-only 通道。 |
| `ShadowCaster` | 阴影投射通道。 |
| `ObjectId` | object-id 输出通道。 |
| `Forward` | `ForwardLit` 的别名。 |
@@ -39,7 +40,7 @@
2. 如果材质没写显式 pass 元数据,再看材质引用 shader 里的 pass 名称和 `LightMode` tag。
3. 如果材质和 shader 都没写显式 builtin metadata则把它隐式视为 `ForwardLit`
因此 `RenderMaterialUtility` 实际把 [MaterialLoader](../../Resources/Material/MaterialLoader/MaterialLoader.md) 解析出的:
因此这里实际把 [MaterialLoader](../../Resources/Material/MaterialLoader/MaterialLoader.md) 解析出的:
- `shaderPass`
- `tags.LightMode`
@@ -48,6 +49,25 @@
全部接进了渲染路径。
## builtin forward 材质契约
同一个头文件里还公开了 `BuiltinForwardMaterialData`
| 字段 | 类型 | 说明 |
|------|------|------|
| `baseColorFactor` | `Math::Vector4` | builtin forward 当前消费的颜色因子。 |
对应 helper 的当前职责是:
- [ResolveBuiltinBaseColorFactor](ResolveBuiltinBaseColorFactor.md)
解析 base color 因子,优先走 shader semantic再回退到常见别名属性名最后可只从 opacity/alpha 补 `w` 分量。
- [ResolveBuiltinBaseColorTexture](ResolveBuiltinBaseColorTexture.md)
解析 base color 贴图,优先走 shader semantic再回退到 `_MainTex``baseColorTexture` 等常见别名。
- [BuildBuiltinForwardMaterialData](BuildBuiltinForwardMaterialData.md)
把当前 builtin forward 真正要消费的材质常量打包出来。
这组 helper 当前直接被 `BuiltinForwardPipeline` 用来填充 per-material 常量和纹理绑定。
## render state 映射
`BuildRasterizerState()``BuildBlendState()``BuildDepthStencilState()` 会把 `MaterialRenderState` 映射成 RHI 状态,再由 [ApplyMaterialRenderState](ApplyMaterialRenderState.md) 一次性写入 `GraphicsPipelineDesc`
@@ -61,9 +81,10 @@
## 当前实现边界
- 它只处理 pass 归类、render queue 和固定渲染状态,不负责 shader variant、keyword 或多 pass 编排。
- 它只处理 pass 归类、builtin forward 材质契约、render queue 和固定渲染状态,不负责 shader variant、keyword 或多 pass 编排。
- 没有显式元数据的材质会默认进入 `ForwardLit`,这是一种“先让基础路径可用”的保守回退。
- `MatchesBuiltinPass(nullptr, pass)` 只有在 `pass == ForwardLit` 时才返回 `true`,而不是对所有 pass 都放行
- `MatchesBuiltinPass(nullptr, pass)` 只有在 `pass == ForwardLit` 时才返回 `true`
- `BuildBuiltinForwardMaterialData()` 当前只打包 `baseColorFactor`;贴图仍由调用方单独通过 [ResolveBuiltinBaseColorTexture](ResolveBuiltinBaseColorTexture.md) 解析。
## 公开函数
@@ -73,6 +94,9 @@
| [ResolveMaterialRenderQueue](ResolveMaterialRenderQueue.md) | 读取材质 render queue空材质时回退到 `Geometry`。 |
| [IsTransparentRenderQueue](IsTransparentRenderQueue.md) | 判断 queue 是否处于透明区间。 |
| [MatchesBuiltinPass](MatchesBuiltinPass.md) | 判断材质是否匹配某个 builtin pass。 |
| [ResolveBuiltinBaseColorFactor](ResolveBuiltinBaseColorFactor.md) | 解析 builtin forward 使用的 base color 因子。 |
| [ResolveBuiltinBaseColorTexture](ResolveBuiltinBaseColorTexture.md) | 解析 builtin forward 使用的 base color 贴图。 |
| [BuildBuiltinForwardMaterialData](BuildBuiltinForwardMaterialData.md) | 打包 builtin forward 当前消费的材质常量。 |
| [BuildRasterizerState](BuildRasterizerState.md) | 构建栅格化状态。 |
| [BuildBlendState](BuildBlendState.md) | 构建混合状态。 |
| [BuildDepthStencilState](BuildDepthStencilState.md) | 构建深度状态。 |

View File

@@ -0,0 +1,55 @@
# ResolveBuiltinBaseColorFactor
**命名空间**: `XCEngine::Rendering`
**类型**: `function`
**头文件**: `XCEngine/Rendering/RenderMaterialUtility.h`
## 签名
```cpp
Math::Vector4 ResolveBuiltinBaseColorFactor(const Resources::Material* material);
```
## 作用
解析 builtin forward 当前使用的 base color 因子。
## 当前实现行为
当前按以下顺序解析:
1. 如果 `material == nullptr`,直接返回 `Math::Vector4::One()`
2. 优先根据 shader property semantic `BaseColor` 查找属性。
3. 如果 semantic 路径没命中,再回退到常见属性名:
- `baseColor`
- `_BaseColor`
- `color`
- `_Color`
4. 如果仍然没有 base color则先以 `(1, 1, 1, 1)` 为默认值,再尝试只从这些属性补 alpha
- `opacity`
- `_Opacity`
- `alpha`
- `_Alpha`
## 当前语义要点
- semantic 元数据优先级高于约定别名。
- 如果没有颜色因子但有 opacity/alpha当前会只改 `w` 分量RGB 仍保持 `1`
- 这条 helper 只解析颜色因子,不解析纹理;纹理由 [ResolveBuiltinBaseColorTexture](ResolveBuiltinBaseColorTexture.md) 负责。
## 测试覆盖
`tests/Rendering/unit/test_render_scene_extractor.cpp` 当前验证了:
- canonical 名称 `baseColor`
- 别名 `_BaseColor`
- shader semantic `BaseColor`
- 只有 opacity 时的 alpha-only fallback
## 相关文档
- [ResolveBuiltinBaseColorTexture](ResolveBuiltinBaseColorTexture.md)
- [BuildBuiltinForwardMaterialData](BuildBuiltinForwardMaterialData.md)
- [RenderMaterialUtility](RenderMaterialUtility.md)

View File

@@ -0,0 +1,52 @@
# ResolveBuiltinBaseColorTexture
**命名空间**: `XCEngine::Rendering`
**类型**: `function`
**头文件**: `XCEngine/Rendering/RenderMaterialUtility.h`
## 签名
```cpp
const Resources::Texture* ResolveBuiltinBaseColorTexture(const Resources::Material* material);
```
## 作用
解析 builtin forward 当前使用的 base color 贴图。
## 当前实现行为
当前按以下顺序解析:
1. 如果 `material == nullptr`,直接返回 `nullptr`
2. 优先根据 shader property semantic `BaseColorTexture` 查找属性。
3. 如果 semantic 路径没命中,再回退到常见纹理名:
- `baseColorTexture`
- `_BaseColorTexture`
- `_MainTex`
- `albedoTexture`
- `mainTexture`
- `texture`
4. 只有当 `ResourceHandle<Texture>` 非空且 `IsValid()` 为真时,才返回底层 `Texture*`
## 当前语义要点
- semantic 元数据优先级高于约定别名。
- 这条 helper 只返回当前应绑定的贴图资源,不负责上传 GPU 纹理或创建 SRV那部分由 [RenderResourceCache](../RenderResourceCache/RenderResourceCache.md) 处理。
- 如果所有路径都没命中,返回 `nullptr`,再由调用方决定是否使用 fallback 纹理。
## 测试覆盖
`tests/Rendering/unit/test_render_scene_extractor.cpp` 当前验证了:
- 别名 `_BaseColorTexture`
- shader semantic `BaseColorTexture`
## 相关文档
- [ResolveBuiltinBaseColorFactor](ResolveBuiltinBaseColorFactor.md)
- [BuildBuiltinForwardMaterialData](BuildBuiltinForwardMaterialData.md)
- [BuiltinForwardPipeline](../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md)
- [RenderMaterialUtility](RenderMaterialUtility.md)

View File

@@ -0,0 +1,81 @@
# RenderPass
**命名空间**: `XCEngine::Rendering`
**类型**: `header-overview`
**头文件**: `XCEngine/Rendering/RenderPass.h`
**描述**: 定义轻量通用 pass 抽象 `RenderPass`、执行上下文 `RenderPassContext` 以及顺序执行容器 `RenderPassSequence`
## 概览
`RenderPass.h` 是当前渲染基础设施里最通用的一层 pass 协议。
它统一回答三件事:
- pass 执行时能拿到什么上下文
- 一个 pass 最少需要实现哪些生命周期函数
- 多个 pass 如何按顺序组成一个小型执行序列
## 当前定义
### `RenderPassContext`
`RenderPassContext` 只是三个引用的聚合:
- `renderContext`
- `surface`
- `sceneData`
### `RenderPass`
抽象基类包含四个核心成员:
| 成员 | 当前语义 |
|------|------|
| `GetName()` | 返回 pass 的人类可读名称。 |
| `Initialize()` | 默认返回 `true`,需要时准备一次性资源。 |
| `Execute()` | 纯虚函数,执行真正的 pass 逻辑。 |
| `Shutdown()` | 默认空实现,释放 pass 资源。 |
### `RenderPassSequence`
`RenderPassSequence` 是一个拥有型容器,内部以 `std::unique_ptr<RenderPass>` 顺序保存 pass。
当前行为是:
- `AddPass()` 会忽略空指针
- `GetPassCount()` 返回当前持有的 pass 数
- `Initialize()` 按插入顺序调用每个 pass 的 `Initialize()`
- `Execute()` 按插入顺序调用每个 pass 的 `Execute()`
- `Shutdown()` 按逆序调用每个 pass 的 `Shutdown()`
## 失败与回滚语义
- `Initialize()` 遇到失败会立即返回 `false`
- `Execute()` 遇到失败也会立即停止后续 pass
- `RenderPassSequence` 自身不会在 `Initialize()` 失败时自动回滚已经初始化过的 pass
当前更高层调用方,例如 `CameraRenderer`,会额外包一层 helper若 sequence 初始化失败,就主动执行一次 `Shutdown()` 回滚。
## 测试验证的真实行为
`tests/Rendering/unit/test_render_pass.cpp` 已覆盖:
- 初始化和执行按插入顺序发生
- `Shutdown()` 按逆序发生
- 中间某个 pass 执行失败时,后续 pass 不再执行
## 当前实现边界
- 这套协议仍然是线性顺序执行,不是 render graph也没有显式资源依赖建模。
- `RenderPassSequence` 只管理 pass 对象,不管理共享资源或跨 pass 的状态同步。
- `RenderPassContext` 暂时只暴露一个目标表面和一份 `RenderSceneData`,不适合表达更复杂的多目标或多阶段图结构。
## 相关文档
- [当前模块](../Rendering.md)
- [CameraRenderRequest](../CameraRenderRequest/CameraRenderRequest.md)
- [CameraRenderer](../CameraRenderer/CameraRenderer.md)
- [Passes](../Passes/Passes.md)

View File

@@ -14,28 +14,29 @@ virtual std::unique_ptr<RenderPipeline> CreatePipeline() const = 0;
## 接口契约
从接口形状上,调用方可以依赖这几点
从接口形状上,调用方可以依赖这些事实
- 返回值拥有独占所有权
- 返回对象是 `RenderPipeline` 派生实例
- 这是一个 `const` 工厂方法asset 自己不需要暴露可变运行时状态
- 这是一个 `const` 工厂方法asset 自己不需要暴露可变运行时状态
## 当前调用链
当前最主要的消费`CameraRenderer` 内部的 `CreatePipelineFromAsset()`
当前最主要的消费`CameraRenderer` 内部的 `CreatePipelineFromAsset()`
1. 若存在 `pipelineAsset`,先调用 `asset->CreatePipeline()`
2. 若拿到有效实例,就把它作为当前主管线
3. 若 asset 为空或返回空指针,再回退到 `BuiltinForwardPipeline`
2. 若拿到有效实例,就把它接成当前主管线
3. 若 asset 为空或返回空指针,再`CameraRenderer` 的调用路径回退到 builtin forward
因此派生类最好遵守一个明确的工程约定
要点是
- 返回一条新的、可独立 `Shutdown()` / `Render()` runtime pipeline
- 不要把某条活动中的共享 pipeline 实例直接借给调用方
- “创建 runtime pipeline”是这个接口的职责
- “创建失败后如何回退”是调用方的职责,不是接口本身的内建语义
## 返回值
- `std::unique_ptr<RenderPipeline>` - 新创建的运行时管线;允许派生类返回 `nullptr`,但当前默认调用方会把这视为失败并继续走 fallback
- `std::unique_ptr<RenderPipeline>` - 新创建的运行时管线
- 允许派生类返回 `nullptr`;但这会被当前调用方视为“创建失败”,并走自己的 fallback 路径
## 当前公开实现示例
@@ -43,14 +44,8 @@ virtual std::unique_ptr<RenderPipeline> CreatePipeline() const = 0;
## 设计说明
这里使用 `std::unique_ptr` 很关键,因为 runtime pipeline 往往持有
- 设备指针
- pipeline state
- descriptor set
- 缓存和临时 GPU 资源
这类对象通常应当具备清晰的唯一生命周期,而不是被多处共享。
这里使用 `std::unique_ptr` 很关键,因为 runtime pipeline 往往持有设备指针、pipeline state、descriptor set、缓存和临时 GPU 资源。
这类对象通常应当有清晰的唯一生命周期,而不是被多处共享。
## 相关文档

View File

@@ -6,51 +6,42 @@
**头文件**: `XCEngine/Rendering/RenderPipelineAsset.h`
**描述**: 渲染管线工厂接口,用于按需创建新的 runtime [RenderPipeline](../RenderPipeline/RenderPipeline.md) 实例。
**描述**: 管线工厂接口,用于按需创建新的 runtime [RenderPipeline](../RenderPipeline/RenderPipeline.md) 实例。
## 概览
`RenderPipelineAsset` 的职责不是自己渲染,而是回答一个更高层的问题:
`RenderPipelineAsset` 不负责自己绘制场景,而是回答一个更高层的问题:
- 当前这台 `CameraRenderer` 应该创建哪一种主管线实例
- 当前这台 [CameraRenderer](../CameraRenderer/CameraRenderer.md) 应该创建哪一种主场景 runtime 管线
和商业引擎里常见的 `RenderPipelineAsset -> RenderPipeline` 分层很接近。好处是
层抽象把“选择哪条主管线”和“真正执行主场景绘制”拆开
- 上层编排器只依赖抽象接口,不直接硬编码具体管线类型
- runtime pipeline 可以被重建、替换或按不同入口注入
- 工厂对象和运行时实例可以采用不同所有权模型
- asset 负责创建 runtime pipeline
- runtime pipeline 负责执行主场景绘制
## 当前真实接线
当前最直接的消费是 [CameraRenderer](../CameraRenderer/CameraRenderer.md)
当前最直接的消费是 [CameraRenderer](../CameraRenderer/CameraRenderer.md)
- 默认构造时会拿到一份默认 pipeline asset
- [SetPipelineAsset](../CameraRenderer/SetPipelineAsset.md) 会通过 asset 重建主管线
- `GetPipelineAsset()` 返回的是当前工厂对象,不是 runtime pipeline
- 默认构造路径会持有一份默认 asset
- [SetPipelineAsset](../CameraRenderer/SetPipelineAsset.md) 会通过 asset 重建当前 runtime pipeline
- [GetPipelineAsset](../CameraRenderer/GetPipelineAsset.md) 返回的是工厂对象,不是 runtime pipeline 实例
按当前源码,默认 concrete asset 是 [Pipelines::BuiltinForwardPipelineAsset](../Pipelines/BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md)。
## 当前公开实现
当前公开的 concrete 实现有:
- [BuiltinForwardPipelineAsset](../Pipelines/BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md)
它会创建 [BuiltinForwardPipeline](../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md)。
按当前源码,默认 concrete asset 是 [BuiltinForwardPipelineAsset](../Pipelines/BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md)。
## 生命周期与所有权
- `RenderPipelineAsset` 通常以 `std::shared_ptr<const RenderPipelineAsset>` 共享持有
- asset 通常以 `std::shared_ptr<const RenderPipelineAsset>` 共享持有
- [CreatePipeline](CreatePipeline.md) 返回新的 `std::unique_ptr<RenderPipeline>`
- asset 不保留运行时实例;实例生命周期由 `CameraRenderer` 或调用方接管
这种“共享工厂 + 独占运行体”的组合很适合渲染系统,因为 runtime pipeline 往往持有设备、pipeline state 和 descriptor set不适合被多方共享所有权
是一种“共享工厂对象 + 独占运行时实例”的分层
## 当前实现边界
- 当前它仍然只是纯 C++ 工厂接口,不是项目资源数据库里的可序列化资产类型
- 还没有 renderer asset inspector、热重载或多 profile 配置
- 当前 fallback 策略很保守,目标是“即使 asset 路径出问题,也尽量总有 builtin pipeline 可跑”
- 这里仍然只是纯 C++ 工厂接口,不是项目资源数据库里的可序列化 renderer asset。
- “空 asset”或“asset 返回空指针”之后如何回退,不属于这个接口本身的职责;当前 fallback 逻辑发生在 `CameraRenderer``CreatePipelineFromAsset()` 调用路径里。
- 当前公开的 concrete asset 仍只有 builtin forward 一条。
## 公开方法
@@ -61,11 +52,8 @@
## 设计说明
这一层的重要性不在于“多包一层接口”,而在于把“选哪种主管线”和“真正执行绘制”分开:
- `CameraRenderer` 不需要知道 builtin forward 的内部细节
- 不同 asset 后续可以创建完全不同的 runtime pipeline 类型
- 如果未来要把主管线选择接入项目设置或 viewport 模式,不必重写 camera submission 主流程
这一层的重要性不在于“多包一层接口”,而在于把“选哪种主管线”从 [CameraRenderer](../CameraRenderer/CameraRenderer.md) 的执行逻辑里抽出来。
这样后续即便增加新的 concrete pipeline也不需要改动单 request 执行主链路。
## 相关文档

View File

@@ -0,0 +1,73 @@
# RenderSceneUtility
**命名空间**: `XCEngine::Rendering`
**类型**: `utility header`
**头文件**: `XCEngine/Rendering/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

@@ -4,65 +4,70 @@
**类型**: `module`
**描述**: 提供场景提取、相机渲染请求、主管线执行、object-id 辅助输出和 builtin post-process 叠加的当前渲染主链路
**描述**: 当前场景渲染主链路所在模块,覆盖 request 规划、场景提取、主管线执行、object-id 输出,以及调用方注入的 post / overlay pass
## 概览
当前 `XCEngine::Rendering` 可以按一条更完整的链路理解
当前 `Rendering` 模块已经不是简单的“scene -> pipeline”两段式结构而是一条更完整的提交链:
1. [SceneRenderer](SceneRenderer/SceneRenderer.md) 负责组织和排序多个相机请求
2. [CameraRenderRequest](CameraRenderRequest/CameraRenderRequest.md) 把单次提交的主表面、object-id 输出和 builtin 后处理需求打包起来
3. [CameraRenderer](CameraRenderer/CameraRenderer.md) 执行单个请求
4. [RenderSceneExtractor](RenderSceneExtractor/RenderSceneExtractor.md) 依据相机和 render area 提取 `RenderSceneData`
5. [RenderPipelineAsset](RenderPipelineAsset/RenderPipelineAsset.md) 决定创建哪条 runtime 主场景管线;默认实现是 [Pipelines::BuiltinForwardPipelineAsset](Pipelines/BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md)
6. [RenderPipeline](RenderPipeline/RenderPipeline.md) 负责主场景绘制;当前默认 runtime 实现是 [Pipelines::BuiltinForwardPipeline](Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md)
7. `ObjectIdPass` 与 [Passes](Passes/Passes.md) 子模块在主场景之后补上 object-id、grid 和 selection outline 等额外结果。
8. [RenderMaterialUtility](RenderMaterialUtility/RenderMaterialUtility.md) 把材质元数据与 render state 翻译成这条链路能消费的规则。
1. [SceneRenderer](SceneRenderer/SceneRenderer.md) 规划并排序 `CameraRenderRequest`
2. [CameraRenderer](CameraRenderer/CameraRenderer.md) 执行单个 request
3. [RenderSceneExtractor](RenderSceneExtractor/RenderSceneExtractor.md) 生成 `RenderSceneData`
4. [RenderPipelineAsset](RenderPipelineAsset/RenderPipelineAsset.md) 决定当前主管线实例如何创建
5. [RenderPipeline](RenderPipeline/RenderPipeline.md) 执行主场景绘制
6. [ObjectIdPass](ObjectIdPass/ObjectIdPass.md) 与 [Passes](Passes/Passes.md) 子模块补上 object-id、grid、outline 等附加阶段
这意味着当前渲染模块已经不只是“scene -> pipeline”两段式结构而是包含了主场景、辅助缓冲和 builtin post-process 的完整相机提交流程。
默认主链路当前是:
更底层的基础协议则由 [SceneRenderRequestPlanner](SceneRenderRequestPlanner/SceneRenderRequestPlanner.md)、[SceneRenderRequestUtils](SceneRenderRequestUtils/SceneRenderRequestUtils.md)、[RenderSceneUtility](RenderSceneUtility/RenderSceneUtility.md)、[RenderPass](RenderPass/RenderPass.md)、[ObjectIdPass](ObjectIdPass/ObjectIdPass.md) 和 [ObjectIdEncoding](ObjectIdEncoding/ObjectIdEncoding.md) 补齐。它们分别负责请求规划、排序规则、场景提取 helper、通用 pass 生命周期以及 object-id 编解码约定。
- [BuiltinForwardPipelineAsset](Pipelines/BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md)
- [BuiltinForwardPipeline](Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md)
## 当前主流程
对一台相机,当前主流程大致是:
对一台相机的大致流程是:
1. `SceneRenderer` 生成并排序 `CameraRenderRequest`
2. `CameraRenderer` 校验请求
3. `RenderSceneExtractor` 提取可见物体与相机数据
4. 通过 `RenderPipelineAsset` 创建或替换主管线实例
5. `RenderPipeline` 绘制主颜色目标
6. 如有需要,执行 object-id pass生成辅助 object-id 纹理
7. 执行调用方注入的 post pass、builtin post-process 和 overlay pass
1. `SceneRenderer` 生成 `CameraRenderRequest`
2. `CameraRenderer` 校验 request 与 render-area。
3. `RenderSceneExtractor` 基于相机和 render-area 提取 `RenderSceneData`
4. `RenderPipeline` 绘制主颜色目标。
5. 如有需要,执行 object-id pass。
6. 执行 `postScenePasses``overlayPasses`
scene viewport 的无限网格选中轮廓,就是通过这条 object-id + builtin post-process 链路接入的
Scene View 的无限网格选中轮廓和编辑器 overlay当前都不是 `CameraRenderer` 内部动态规划出来的,而是先在 Editor 层组装成 request plan再通过 `postScenePasses` / `overlayPasses` 接入这条主链
## 材质语义如何进入渲染路径
## 材质与 shader 语义如何进入主链路
[RenderMaterialUtility](RenderMaterialUtility/RenderMaterialUtility.md) 当前负责消费材质里的:
[RenderMaterialUtility](RenderMaterialUtility/RenderMaterialUtility.md) 当前负责材质里的:
- `shaderPass`
- `LightMode`
- `renderQueue`
- `renderState`
这些元数据可能来自普通材质文件,也可能来自 `MaterialLoader` 读取的 `.xcmat` artifact。它们最终会影响
翻译成渲染链路可消费的规则。
- 某个可见物体属于哪个 builtin pass
- 不透明 / 透明排序语义
- 剔除、混合和深度状态如何写进图形管线描述
在默认 builtin forward 路径里shader pass 的 `resources` 声明还会进一步参与 `PassResourceLayout` 构建,因为 [BuiltinForwardPipeline](Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md) 已经开始按资源契约生成 descriptor set layout。
在当前默认 builtin forward 路径里shader pass 的 `resources` 声明还会进一步参与 `PassResourceLayout` 构建,因为 `BuiltinForwardPipeline` 已经开始按资源契约生成 descriptor set layout。
## 当前基础设施分层
更底层的基础协议由这些页面补齐:
- [SceneRenderRequestPlanner](SceneRenderRequestPlanner/SceneRenderRequestPlanner.md)
- [SceneRenderRequestUtils](SceneRenderRequestUtils/SceneRenderRequestUtils.md)
- [RenderSceneUtility](RenderSceneUtility/RenderSceneUtility.md)
- [RenderPass](RenderPass/RenderPass.md)
- [ObjectIdEncoding](ObjectIdEncoding/ObjectIdEncoding.md)
它们分别负责 request 规划、排序规则、scene helper、通用 pass 生命周期和 object-id 编解码约定。
## 当前实现边界
- 当前默认路径仍然是内建前向渲染,而不是完整 SRP / render graph。
- `RenderPipelineAsset` 已经接入默认主链路,但当前还不是项目资源系统里的完整 renderer asset。
- object-id 和 builtin post-process 主要服务于编辑器视口与调试链路
- builtin selection outline 当前依赖单独的 object-id SRV而不是从主颜色结果反推
- 多相机排序由 `SceneRenderer` 处理,`CameraRenderer` 本身只执行单请求。
- 默认路径仍然是 builtin forward不是完整 SRP render graph。
- `RenderPipelineAsset` 已经接入默认主链路,但当前还不是项目资源数据库里的完整 renderer asset。
- 多相机排序由 `SceneRenderer` 处理,`CameraRenderer` 只执行单个 request
- 编辑器特有的 grid / outline / overlay 组装逻辑不在 `Rendering` 模块里完成,而是在 Editor 层先转成 `RenderPassSequence`
## 头文件
## 头文件索引
- [CameraRenderRequest](CameraRenderRequest/CameraRenderRequest.md) - `CameraRenderRequest.h`
- [CameraRenderer](CameraRenderer/CameraRenderer.md) - `CameraRenderer.h`
@@ -93,5 +98,5 @@ scene viewport 的无限网格和选中轮廓,就是通过这条 object-id + b
- [Components](../Components/Components.md)
- [RHI](../RHI/RHI.md)
- [上级目录](../XCEngine.md)
- [API 索引](../../main.md)
- [XCEngine](../XCEngine.md)
- [API 索引](../../main.md)

View File

@@ -1,149 +1,146 @@
# Scene Extraction And Builtin Forward Pipeline
## 先理解这套渲染架构在做什么
## 这条链路现在怎么工作
当前 XCEngine 的渲染链路,不是“场景对象自己直接调用 RHI 去画”,而是先做一次轻量的场景提取,再交给具体渲染管线执行
当前 XCEngine 的主场景渲染链路可以按下面的顺序理解
1. `Scene``GameObject` 维护对象层级与组件
2. `MeshFilterComponent` 提供几何数据
3. `MeshRendererComponent` 提供材质槽和渲染标志
4. `RenderSceneExtractor` 把这些信息拍平为 `RenderSceneData`
5. `SceneRenderer` 把提取结果交给 `BuiltinForwardPipeline`
6. `BuiltinForwardPipeline` 通过 RHI 发出真正 draw call。
1. `SceneRenderer` 负责组织相机请求和执行顺序
2. `CameraRenderer` 选择主渲染管线;默认情况下,它通过 `BuiltinForwardPipelineAsset` 创建 `BuiltinForwardPipeline`
3. `RenderSceneExtractor` 把 scene/game-object/component 结构压平成 `RenderSceneData`
4. `BuiltinForwardPipeline``RenderSceneData` 绘制到 `RenderSurface`
条链路和很多商业引擎的基本思路是一致的。真正成熟的区别,不在“有没有 scene extraction 这个词”,而在于提取阶段做得有多深。
里的关键点不是“有没有前向渲染”,而是场景数据和绘制数据已经被拆成两层:
## 为什么要把 Mesh 和 Renderer 分开
- 提取阶段负责从场景组织里收集相机、光照和可绘制项。
- pipeline 阶段只消费已经整理好的 `RenderSceneData`
`MeshFilterComponent + MeshRendererComponent` 这种拆分,和 Unity 的老思路非常接近。它背后的设计理由很实用
不过这里讲的只是主场景绘制槽位,不是整次相机提交的完整尾段。按 `engine/src/Rendering/CameraRenderer.cpp` 的当前实现,`BuiltinForwardPipeline` 前后还可能包着
- 几何数据和材质配置是两种不同维度的信息。
- 同一个 mesh 可能被不同材质配置复用。
- 渲染系统提取时,可以分别读取 geometry source 和 material state。
- `preScenePasses`
- object-id pass
- `postScenePasses`
- `overlayPasses`
如果把这两层全部混在一个组件里,短期写起来更省事,但长期会让复用、序列化和编辑器展示都更别扭
Scene View 的网格、选中描边和 editor overlay当前就是先在 Editor 层组装成这些 request 级序列,再交给 `CameraRenderer` 执行
## 为什么需要 Scene Extraction
## `RenderSceneData` 现在包含什么
对游戏对象系统来说,最自然的数据组织方式是树状层级和组件组合;但对渲染来说,最自然的数据组织方式通常是
`RenderSceneExtractor` 当前产出的核心数据有三块
- 一台相机
- 一组可见对象
- 每个对象对应的变换、mesh 和材质
- `camera``cameraData`
- `lighting`
- `visibleItems`
所以提取阶段的意义,就是把“适合编辑和运行时逻辑”的数据形状,转换成“适合绘制”的数据形状
其中 `visibleItems` 的元素类型是 `VisibleRenderItem`。头文件里仍保留 `VisibleRenderObject = VisibleRenderItem` 的兼容别名,但当前实现和新文档都应以 `visibleItems` 为准,而不是旧说法 `visibleObjects`
当前 `RenderSceneExtractor` 做的是这条路线中最基础的一版
每个 `VisibleRenderItem` 除了 mesh 和变换,还已经携带
- 选相机
- 算矩阵
- 遍历层级
- 收集 mesh 对象
- `material`
- `materialIndex`
- `sectionIndex`
- `hasSection`
- `renderQueue`
- `cameraDistanceSq`
和商业引擎的真正可见性阶段相比还很早期,但方向没有问题
让后续 pipeline 不需要回到场景层重新做组件查询
## 当前 extractor 做了什么,没做什么
## 为什么还要保留 scene extraction
已经做的:
游戏对象系统天然偏向层级、组件和编辑器语义;渲染系统天然偏向“当前相机要画哪些项”。`RenderSceneExtractor` 的价值就是把这两种数据形状解耦。
- 覆盖相机优先。
- 没有覆盖相机时,优先选择 `IsPrimary()``depth` 更高的相机。
- 只收集激活层级中的对象。
- 只收集同时拥有 `MeshFilterComponent``MeshRendererComponent` 的对象。
当前 extractor 已经做的事情包括:
还没做的:
- 选择相机并生成 `RenderCameraData`
- 提取主方向光数据
- 递归收集满足基础绘制条件的可见项
- 产出 `visibleItems` 并带上 material / section / distance 等渲染侧字段
- 视锥裁剪。
- 遮挡裁剪。
- 透明排序。
- render layer 过滤。
- 阴影 caster / receiver 分类。
- instancing / batching。
它还没有做完整的商业级可见性系统,例如:
所以当前 `visibleObjects` 更准确地说是“当前场景里满足基础绘制条件的对象集合”,而不是严格意义上的最终可见集。
- 视锥裁剪
- 遮挡裁剪
- instancing / batching
- 透明排序主路径
## RenderSurface 为什么重要
## `BuiltinForwardPipeline` 的当前定位
很多小型引擎一开始会把“渲染目标”写死成 swap chain back buffer但这条路很快就会卡住
`BuiltinForwardPipeline` 现在是默认主渲染路径,但它内部已经不是旧的固定绑定模型,而是三层缓存
- 离屏渲染怎么办?
- 编辑器预览窗口怎么办?
- 反射探针、后处理链路怎么办?
- `(shader*, passName)` 缓存 `PassResourceLayout`
- `(shader*, passName, render state)` 缓存 `RHIPipelineState`
- `(passLayout, setIndex, objectId, material)` 缓存动态 descriptor set
`RenderSurface` 的作用,就是把这些目标抽象出来。当前它虽然还很轻量,但已经能描述
此外它已经接入 [RenderPassSequence](../../XCEngine/Rendering/RenderPass/RenderPass.md)
- 构造时注册 `BuiltinForwardOpaquePass`
- `Initialize()` 走 sequence 生命周期
- `Render()` 先构造 `RenderPassContext`,再执行 sequence
- `Shutdown()` 也走 sequence再由 opaque pass 回调资源清理
所以当前 builtin forward 更像“一条默认可运行的 pass-sequence 管线”,而不是过去那种把所有逻辑揉在一个固定 layout 里的实现。
## Shader pass 资源契约
当前 builtin forward 对 shader pass 的资源声明有明确白名单。可识别语义只有:
- `PerObject`:必需,单个 CBV
- `Material`:可选,单个 CBV
- `BaseColorTexture`:可选,单个 `Texture2D``TextureCube`
- `LinearClampSampler`:可选,单个 sampler
如果 shader pass 没有声明 `resources`,则会回退到 legacy builtin forward 绑定:
- `set 1 binding 0` -> `PerObject`
- `set 2 binding 0` -> `Material`
- `set 3 binding 0` -> `BaseColorTexture`
- `set 4 binding 0` -> `LinearClampSampler`
如果声明不合法,例如未知语义、同 set 混用 sampler 和非 sampler、重复 binding 或缺少 `PerObject`pipeline 会拒绝为该 pass 创建布局。
测试 `tests/Rendering/unit/test_builtin_forward_pipeline.cpp` 还明确校验了 builtin shader `ForwardLit` pass 的这组资源契约,以及 `BuildInputLayout()` 现在使用 `POSITION=float3`
## 单个可见项如何被画出来
`BuiltinForwardOpaquePass` 遍历 `RenderSceneData::visibleItems` 时,每个物体大致会经历以下步骤:
1. 根据材质解析真正要用的 shader/pass没有合适 pass 时回退到 builtin forward shader。
2. 取得 mesh 的 GPU 资源缓存。
3. 生成 `PerObjectConstants``PerMaterialConstants`
4. 获取或创建当前 shader pass 的 `PassResourceLayout`
5. 逐 set 绑定 descriptor
-`PerObject / Material / Texture` 的 set 走动态缓存。
- 只含 sampler 的 set 走静态缓存。
6. 按 section 或整 mesh 发出 draw call。
`BaseColorTexture` 如果解析不到,会回退到初始化阶段创建的 1x1 白色纹理 SRV。
## `RenderSurface` 在这里的作用
`RenderSurface` 不是单纯的附件容器而是当前这一帧输出目标的完整描述。builtin forward 会消费它的:
- 尺寸
- 颜色附件
- 深度附件
- 清屏色覆盖
- 渲染前后颜色资源状态
- render area
- clear color override
- 自动状态切换开关
- `colorStateBefore` / `colorStateAfter`
这一步非常关键,因为它让 pipeline 不再只服务于窗口表面
因此这条主渲染路径既能服务于窗口 back buffer也能服务于 editor viewport、离屏 RT 或其它自定义输出目标
## BuiltinForwardPipeline 的定位
## 当前限制
`BuiltinForwardPipeline` 当前的定位,不是“最终渲染架构”,而是“默认可用的第一条内建管线”
它现在主要解决的是:
- 把 mesh 上传成 vertex/index buffer
- 把 texture 上传成 shader resource
- 创建一套最基本的 pipeline state
- 对每个对象写常量、绑纹理、发 draw
这和很多商业引擎早期 builtin pipeline 的定位很像:先确保有一条完整闭环,再逐步扩展能力。
## 为什么要有 RenderResourceCache
场景对象和资源系统不应该直接持有具体 RHI 对象,否则很快会把层级关系搞乱:
- 资源层会被具体后端污染。
- 不同 backend 的资源生命周期会混到游戏对象逻辑里。
`RenderResourceCache` 把“CPU 资源 -> GPU 资源”的转换收口到渲染层,这是对的。
但当前它还只是基础版:
- 以裸指针做 cache key。
- 没有资源变更失效。
- 没有线程安全。
- 格式支持有限。
所以它更像“运行时上传缓存”,还不是完整的 render resource system。
## 当前这套设计和商业引擎相比差什么
如果拿商业级游戏引擎的渲染系统作参照,当前最明显的缺口包括:
1. 没有真正的 visibility / culling pipeline。
2. 没有 render queue、pass 分类和排序系统。
3. 没有 lighting、shadow、post-processing 等完整渲染特性。
4. 没有 render graph 或更强的 target dependency 管理。
5. `RenderPipelineAsset` 还没有真正驱动运行时 pipeline 创建。
但从架构骨架看,当前已经把最核心的几个边界切开了:
- scene data
- render data
- render target
- pipeline implementation
- GPU resource upload
这恰恰是后续能继续演进的前提。
## 当前阶段的推荐用法
- 需要渲染场景时,优先通过 `SceneRenderer` 作为统一入口。
- 几何数据放在 `MeshFilterComponent`,材质槽和渲染标志放在 `MeshRendererComponent`
-`RenderSurface` 当作“这一帧的输出目标描述”,而不是只当附件容器。
- 当前把 `BuiltinForwardPipeline` 看作默认可运行路径,而不是最终渲染架构。
- 主场景默认只有 builtin forward opaque pass
- 透明、阴影、延迟渲染和更复杂的资源依赖管理还不在这条链路里。
- `RenderPassSequence` 目前只提供顺序执行,不是 render graph。
## 相关 API
- [Rendering](../../XCEngine/Rendering/Rendering.md)
- [RenderSceneExtractor](../../XCEngine/Rendering/RenderSceneExtractor/RenderSceneExtractor.md)
- [RenderSurface](../../XCEngine/Rendering/RenderSurface/RenderSurface.md)
- [RenderPass](../../XCEngine/Rendering/RenderPass/RenderPass.md)
- [SceneRenderer](../../XCEngine/Rendering/SceneRenderer/SceneRenderer.md)
- [BuiltinForwardPipeline](../../XCEngine/Rendering/Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md)
- [BuiltinForwardPipelineAsset](../../XCEngine/Rendering/Pipelines/BuiltinForwardPipelineAsset/BuiltinForwardPipelineAsset.md)
- [MeshFilterComponent](../../XCEngine/Components/MeshFilterComponent/MeshFilterComponent.md)
- [MeshRendererComponent](../../XCEngine/Components/MeshRendererComponent/MeshRendererComponent.md)

View File

@@ -1,12 +1,12 @@
# API 文档重构状态
**生成时间**: `2026-04-03 15:07:08`
**生成时间**: `2026-04-03 15:30:08`
**来源**: `docs/api/_tools/audit_api_docs.py`
## 摘要
- Markdown 页面数(全部): `3327`
- Markdown 页面数(全部): `3324`
- Markdown 页面数canonical: `3298`
- Public headers 数: `244`
- Editor source headers 数: `124`
@@ -74,8 +74,8 @@
| 字段 | 页面数 |
|------|--------|
| `命名空间` | `891` |
| `类型` | `891` |
| `命名空间` | `941` |
| `类型` | `941` |
| `描述` | `417` |
| `头文件` | `502` |
| `头文件` | `552` |
| `源文件` | `348` |

View File

@@ -4,17 +4,21 @@
**类型**: `index`
**描述**: 指向 `docs/api/XCEngine` 平行目录树的唯一 canonical API 文档入口。
**描述**: 指向 `docs/api/XCEngine` 平行目录树与审计状态页的统一 API 文档入口。
## 概览
`docs/api/XCEngine/**` 是唯一正式 API 文档树,其层级与 `engine/include/XCEngine/**` 保持平行。
模块总览页、子模块总览页、类型总览页和方法页都应从这棵目录树进入,不再保留第二套正式入口。
`docs/api/XCEngine/**`当前唯一正式的 canonical API 文档树,其层级与 `engine/include/XCEngine/**` 保持平行。
根索引负责两件事:
- 给出所有主要模块的入口导航。
- 指向最新的文档审计状态,方便确认覆盖率、断链和遗留缺口。
## Canonical 入口
- [XCEngine/XCEngine.md](XCEngine/XCEngine.md) - 与 `engine/include/XCEngine` 平行的文档根目录
- [_meta/rebuild-status.md](_meta/rebuild-status.md) - 当前覆盖率审计状态
- [_meta/rebuild-status.md](_meta/rebuild-status.md) - 当前覆盖率、链接检查和审计状态
## 模块导航
@@ -24,12 +28,15 @@
| `Components` | [XCEngine/Components/Components.md](XCEngine/Components/Components.md) | `XCEngine/Components/` |
| `Core` | [XCEngine/Core/Core.md](XCEngine/Core/Core.md) | `XCEngine/Core/` |
| `Debug` | [XCEngine/Debug/Debug.md](XCEngine/Debug/Debug.md) | `XCEngine/Debug/` |
| `Editor` | [XCEngine/Editor/Editor.md](XCEngine/Editor/Editor.md) | `editor/src/` |
| `Input` | [XCEngine/Input/Input.md](XCEngine/Input/Input.md) | `XCEngine/Input/` |
| `Memory` | [XCEngine/Memory/Memory.md](XCEngine/Memory/Memory.md) | `XCEngine/Memory/` |
| `Platform` | [XCEngine/Platform/Platform.md](XCEngine/Platform/Platform.md) | `XCEngine/Platform/` |
| `Rendering` | [XCEngine/Rendering/Rendering.md](XCEngine/Rendering/Rendering.md) | `XCEngine/Rendering/` |
| `Resources` | [XCEngine/Resources/Resources.md](XCEngine/Resources/Resources.md) | `XCEngine/Resources/` |
| `RHI` | [XCEngine/RHI/RHI.md](XCEngine/RHI/RHI.md) | `XCEngine/RHI/` |
| `Scene` | [XCEngine/Scene/Scene.md](XCEngine/Scene/Scene.md) | `XCEngine/Scene/` |
| `Scripting` | [XCEngine/Scripting/Scripting.md](XCEngine/Scripting/Scripting.md) | `XCEngine/Scripting/` |
| `Threading` | [XCEngine/Threading/Threading.md](XCEngine/Threading/Threading.md) | `XCEngine/Threading/` |
## 关键子模块
@@ -40,6 +47,8 @@
| `Core/Containers` | [XCEngine/Core/Containers/Containers.md](XCEngine/Core/Containers/Containers.md) | `XCEngine/Core/Containers/` |
| `Core/IO` | [XCEngine/Core/IO/IO.md](XCEngine/Core/IO/IO.md) | `XCEngine/Core/IO/` |
| `Core/Math` | [XCEngine/Core/Math/Math.md](XCEngine/Core/Math/Math.md) | `XCEngine/Core/Math/` |
| `Editor/Viewport` | [XCEngine/Editor/Viewport/Viewport.md](XCEngine/Editor/Viewport/Viewport.md) | `editor/src/Viewport/` |
| `Rendering/Passes` | [XCEngine/Rendering/Passes/Passes.md](XCEngine/Rendering/Passes/Passes.md) | `XCEngine/Rendering/Passes/` |
| `Platform/Windows` | [XCEngine/Platform/Windows/Windows.md](XCEngine/Platform/Windows/Windows.md) | `XCEngine/Platform/Windows/` |
| `Resources/Mesh` | [XCEngine/Resources/Mesh/Mesh.md](XCEngine/Resources/Mesh/Mesh.md) | `XCEngine/Resources/Mesh/` |
| `Resources/Texture` | [XCEngine/Resources/Texture/Texture.md](XCEngine/Resources/Texture/Texture.md) | `XCEngine/Resources/Texture/` |
@@ -50,4 +59,4 @@
- [XCEngine 平行目录根](XCEngine/XCEngine.md)
- [API 文档重构状态](_meta/rebuild-status.md)
- [XCEngine 架构设计](../plan/XCEngine渲染引擎架构设计.md)
- [XCEngine 架构设计](../used/XCEngine渲染引擎架构设计.md)