Files
XCEngine/docs/api/_guides/Rendering/Scene-Extraction-And-Builtin-Forward-Pipeline.md

150 lines
5.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Scene Extraction And Builtin Forward Pipeline
## 先理解这套渲染架构在做什么
当前 XCEngine 的渲染链路,不是“场景对象自己直接调用 RHI 去画”,而是先做一次轻量的场景提取,再交给具体渲染管线执行:
1. `Scene``GameObject` 维护对象层级与组件。
2. `MeshFilterComponent` 提供几何数据。
3. `MeshRendererComponent` 提供材质槽和渲染标志。
4. `RenderSceneExtractor` 把这些信息拍平为 `RenderSceneData`
5. `SceneRenderer` 把提取结果交给 `BuiltinForwardPipeline`
6. `BuiltinForwardPipeline` 通过 RHI 发出真正 draw call。
这条链路和很多商业引擎的基本思路是一致的。真正成熟的区别,不在“有没有 scene extraction 这个词”,而在于提取阶段做得有多深。
## 为什么要把 Mesh 和 Renderer 分开
`MeshFilterComponent + MeshRendererComponent` 这种拆分,和 Unity 的老思路非常接近。它背后的设计理由很实用:
- 几何数据和材质配置是两种不同维度的信息。
- 同一个 mesh 可能被不同材质配置复用。
- 渲染系统提取时,可以分别读取 geometry source 和 material state。
如果把这两层全部混在一个组件里,短期写起来更省事,但长期会让复用、序列化和编辑器展示都更别扭。
## 为什么需要 Scene Extraction
对游戏对象系统来说,最自然的数据组织方式是树状层级和组件组合;但对渲染来说,最自然的数据组织方式通常是:
- 一台相机
- 一组可见对象
- 每个对象对应的变换、mesh 和材质
所以提取阶段的意义,就是把“适合编辑和运行时逻辑”的数据形状,转换成“适合绘制”的数据形状。
当前 `RenderSceneExtractor` 做的是这条路线中最基础的一版:
- 选相机
- 算矩阵
- 遍历层级
- 收集 mesh 对象
这和商业引擎的真正可见性阶段相比还很早期,但方向没有问题。
## 当前 extractor 做了什么,没做什么
已经做的:
- 覆盖相机优先。
- 没有覆盖相机时,优先选择 `IsPrimary()``depth` 更高的相机。
- 只收集激活层级中的对象。
- 只收集同时拥有 `MeshFilterComponent``MeshRendererComponent` 的对象。
还没做的:
- 视锥裁剪。
- 遮挡裁剪。
- 透明排序。
- render layer 过滤。
- 阴影 caster / receiver 分类。
- instancing / batching。
所以当前 `visibleObjects` 更准确地说是“当前场景里满足基础绘制条件的对象集合”,而不是严格意义上的最终可见集。
## RenderSurface 为什么重要
很多小型引擎一开始会把“渲染目标”写死成 swap chain back buffer但这条路很快就会卡住
- 离屏渲染怎么办?
- 编辑器预览窗口怎么办?
- 反射探针、后处理链路怎么办?
`RenderSurface` 的作用,就是把这些目标抽象出来。当前它虽然还很轻量,但已经能描述:
- 尺寸
- 颜色附件
- 深度附件
- 清屏色覆盖
- 渲染前后颜色资源状态
这一步非常关键,因为它让 pipeline 不再只服务于窗口表面。
## 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` 看作默认可运行路径,而不是最终渲染架构。
## 相关 API
- [Rendering](../../XCEngine/Rendering/Rendering.md)
- [RenderSceneExtractor](../../XCEngine/Rendering/RenderSceneExtractor/RenderSceneExtractor.md)
- [RenderSurface](../../XCEngine/Rendering/RenderSurface/RenderSurface.md)
- [SceneRenderer](../../XCEngine/Rendering/SceneRenderer/SceneRenderer.md)
- [BuiltinForwardPipeline](../../XCEngine/Rendering/Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md)
- [MeshFilterComponent](../../XCEngine/Components/MeshFilterComponent/MeshFilterComponent.md)
- [MeshRendererComponent](../../XCEngine/Components/MeshRendererComponent/MeshRendererComponent.md)