docs(rendering): refine outline and volumetric pass docs

This commit is contained in:
2026-04-10 18:28:20 +08:00
parent bb9a4d5ef4
commit 0c52e0f640
7 changed files with 114 additions and 137 deletions

View File

@@ -6,76 +6,64 @@
**头文件**: `XCEngine/Rendering/Passes/BuiltinObjectIdOutlinePass.h`
**描述**: 内建的全屏后处理 pass读取 object-id 纹理并把选中对象轮廓或调试 selection mask 合成到当前颜色目标;真正使用哪份 shader 由调用方通过 `shaderPath` 注入。
**描述**: 内建的全屏轮廓合成 pass读取 object-id 纹理并把选中对象轮廓或调试 selection mask 叠加到当前颜色目标;真正使用哪份 shader 由调用方通过 `shaderPath` 注入。
## 概览
## 2026-04-10 同步补充
以下内容以当前 `BuiltinObjectIdOutlinePass.h/.cpp` 为准:
- `Render(...)` 的输入不再是裸 `objectIdTextureView` 指针,而是
[ObjectIdOutlinePassInputs](../ObjectIdOutlinePassInputs/ObjectIdOutlinePassInputs.md)
这让调用方可以同时声明 object-id 纹理在进入 pass 前的资源状态。
- `EnsureInitialized(...)` / `CreateResources(...)` 现在按 backend、目标颜色格式和目标 `sampleCount` 重新建资源;当 surface 配置变化时会销毁旧的 pipeline / descriptor 重新创建。
- viewport / scissor 已经按 `surface.GetRenderArea()` 取值,不再固定覆盖整张 surface。
-`surface.IsAutoTransitionEnabled()``true`pass 会把目标颜色从 `surface.GetColorStateAfter()` 切到 `RenderTarget`,并把 object-id 纹理从 `inputs.objectIdTextureState` 切到 `PixelShaderResource`,结束后再恢复。
`BuiltinObjectIdOutlinePass` 处在“object-id 已经生成,但主场景也已经画完”的阶段。它本身不负责提取可见物体,也不负责生成 object-id 纹理,而是消费这些上游结果:
- object-id 纹理通常来自 `BuiltinObjectIdPass`
- 选中对象列表和 style 当前通常由 editor 侧 Scene View render plan 提供
- 调用时机当前`editor/src/Viewport/Passes/SceneViewportSelectionOutlinePass.cpp` 这类包装 pass 决定,并最终通过 [CameraRenderer](../../Execution/CameraRenderer/CameraRenderer.md) 的 `postScenePasses` 提交
- object-id 纹理通常来自 `BuiltinObjectIdPass`
- 选中对象列表和样式通常由 editor 侧 Scene View render plan 提供
- 调用时机通常`SceneViewportSelectionOutlinePass` 这类包装逻辑决定,并最终通过 [CameraRenderer](../../Execution/CameraRenderer/CameraRenderer.md) 的 `postScenePasses` 提交
因此它更接近一个“builtin selection feedback compositor”而不是一个通用 post-process 框架。
因此它更接近一个“selection feedback compositor”而不是通用 post-process 框架。
和早期实现不同,当前类已经不再把 outline shader 写死为 engine builtin 资源。源码里的职责边界
和早期实现不同,当前类不再把 outline shader 写死成某个单一后端资源,也不再直接接受裸 `objectIdTextureView` 参数。源码里的职责边界已经变成
- `BuiltinObjectIdOutlinePass`
只负责资源创建、object-id 采样、常量编码和一次全屏三角形执行
- editor 调用方
通过 [SetShaderPath](SetShaderPath.md) 或构造函数参数注入具体 shader 路径。
- `SceneViewportSelectionOutlinePass`
当前用 [SceneViewportResourcePaths](../../../Editor/Viewport/SceneViewportResourcePaths/SceneViewportResourcePaths.md)
生成 editor-owned object-id outline shader 路径,再交给这里执行;`SceneViewportShaderPaths` 只是兼容 include 层。
只负责资源创建、选中对象编码、object-id 采样和一次全屏三角形执行
- [ObjectIdOutlinePassInputs](../ObjectIdOutlinePassInputs/ObjectIdOutlinePassInputs.md)
描述 object-id 纹理视图及其进入 pass 前的资源状态
- editor / 调用方
通过 [SetShaderPath](SetShaderPath.md) 或构造函数参数注入具体 shader 路径,并负责准备选中对象列表
## 输入与输出契约
| 输入 / 输出 | 当前要求 |
|------|------|
| `renderContext` | 必须有效,且后端类型必须是 `D3D12`。 |
| `surface` | 至少要有一个有效颜色附件pass 只写 `colorAttachments[0]`。 |
| `objectIdTextureView` | 不能为空,并且调用方要保证它已经处于可作为 SRV 读取的状态。 |
| `selectedObjectIds` | 不能为空;超过 `256` 个时只会取前 `256`。 |
| `renderContext` | 必须有效。 |
| `surface` | 必须具备恰好一个有效颜色附件,且 render area 有效pass 只写 `colorAttachments[0]`。 |
| `inputs` | 由 [ObjectIdOutlinePassInputs](../ObjectIdOutlinePassInputs/ObjectIdOutlinePassInputs.md) 描述;`objectIdTextureView` 不能为空。 |
| `selectedObjectIds` | 运行时对象 ID 列表;最多编码前 `256` 个,且至少要有一个能成功转换成 render object id。 |
| `style` | 决定轮廓颜色、宽度和是否改为输出 debug mask。 |
| 输出 | 在主颜色目标上 alpha 混合轮廓,或在 debug 模式下输出黑白 selection mask。 |
| 输出 | 在主颜色目标上合轮廓,或在 debug 模式下输出 selection mask 可视化结果。 |
## 当前渲染算法
## 当前渲染流程
`BuiltinObjectIdOutlinePass.cpp` 与当前配置 shader 的实现,流程是:
1. 校验上下文、后端、object-id SRV 和选中对象列表。
2. 懒初始化内部资源,必要时重新创建 pipeline layout、pipeline state 和两个 descriptor set;这一步要求 `shaderPath` 非空且可成功加载。
3. `surface.GetWidth()` / `GetHeight()` 计算视口尺寸与 texel size。
4. `EncodeObjectIdToColor()` 把选中对象 ID 编码进常量缓冲,最多写入 `kMaxSelectedObjectCount = 256` 项。
5. 绑定一个 CBV set 和一个 SRV set设置目标为 `surface` 的第一个颜色附件。
6. 以全屏三角形方式执行 `Draw(3, 1, 0, 0)`
1. 校验 `renderContext``inputs.objectIdTextureView``selectedObjectIds` 和目标 `surface`
2. 通过 `EnsureInitialized(renderContext, surface)` 懒创建或重建 pipeline layout、pipeline state 和两个 descriptor set
3. 把运行时对象 ID 转成 render object id并最多写入 `kMaxSelectedObjectCount = 256` 项编码颜色
4. 把常量缓冲写到 `m_constantSet`,把 `inputs.objectIdTextureView` 写到 `m_textureSet`
5. `surface` 开启自动状态切换,则把输出颜色附件和 object-id 纹理切到本 pass 需要的状态,并在结束后恢复
6. `surface.GetRenderArea()` 作为 viewport/scissor执行一次全屏三角形 `Draw(3, 1, 0, 0)`
## 生命周期
- [Constructor](Constructor.md) 只做状态清零,不会立刻创建 GPU 资源
- [SetShaderPath](SetShaderPath.md) 更新路径时,会立刻销毁当前缓存的 RHI 资源,等待下一次 `Render()` 重新初始化
- 第一次 [Render](Render.md) 成功进入初始化路径时,才会真正创建 descriptor 和 PSO
- [Shutdown](Shutdown.md) 会显式销毁所有内部缓存对象
- [Destructor](Destructor.md) 当前是默认析构,因此如果把它作为长期 renderer 成员使用,调用方仍在销毁前显式执行 `Shutdown()`
- [Constructor](Constructor.md) 只初始化状态,不会立刻创建 GPU 资源
- [SetShaderPath](SetShaderPath.md) 更新路径时,会销毁当前缓存的 RHI 资源,等待下一次 [Render](Render.md) 重新初始化
- 第一次成功进入初始化路径时,才会真正创建 descriptor set 和 PSO
- [Shutdown](Shutdown.md) 会显式销毁所有内部缓存对象
- [Destructor](Destructor.md) 当前是默认析构,因此把它作为长期 renderer 成员使用,调用方仍在销毁前显式执行 `Shutdown()`
## 当前实现边界
- 只接受 `D3D12`,其它后端直接返回 `false`
- 在第一次创建资源前必须先提供有效 `shaderPath`;空路径会记录错误并返回 `false`
- 处理资源状态切换,也不负责清屏;这些由调用方保证。
-前完全忽略 `surface.GetRenderArea()`viewport 和 scissor 都直接取整张 surface 的宽高。
- 只使用第一个颜色附件;多 render target 场景不会同步写其它附件。
- 当前不再硬编码限定 `D3D12`;只要配置 shader 在当前 backend 上存在兼容 graphics variant即可建立资源并执行
- 在第一次创建资源前必须先提供有效 `shaderPath`
- 处理单颜色附件输出,不写深度
-`surface.IsAutoTransitionEnabled()``false`pass 不会替调用方检查或修正目标与输入纹理的资源状态
- pipeline 资源会按 backend、render target format 和 sample count 重新建立;当前未把 sample quality 纳入该类自身的缓存键
## 公开方法
@@ -86,21 +74,19 @@
| [SetShaderPath](SetShaderPath.md) | 更新当前要加载的 shader 路径,并清空已创建资源。 |
| [GetShaderPath](GetShaderPath.md) | 返回当前记录的 shader 路径。 |
| [Shutdown](Shutdown.md) | 销毁已创建的 pipeline、descriptor 和 shader handle。 |
| [Render](Render.md) | 读取 object-id SRV,并把轮廓或 debug mask 写入颜色目标。 |
| [Render](Render.md) | 读取 object-id 输入,并把轮廓或 debug mask 写入颜色目标。 |
## 真实使用位置
- `editor/src/Viewport/Passes/SceneViewportSelectionOutlinePass.cpp` `SceneViewportSelectionOutlinePassRenderer` 包装它,
并通过 `GetSceneViewportObjectIdOutlineShaderPath()` 注入 editor-owned shader 路径。
- [SceneViewportRenderPlan](../../../Editor/Viewport/SceneViewportRenderPlan/SceneViewportRenderPlan.md) 决定当前帧是否要创建 selection outline pass。
- [CameraRenderer](../../Execution/CameraRenderer/CameraRenderer.md) 在主场景与 object-id pass 之后执行这些 `postScenePasses`
- `editor/src/Viewport/ViewportHostRenderFlowUtils.h` 当前为 Scene View 组装默认橙色、`2px` 的 outline style。
- `editor/src/Viewport/Passes/SceneViewportSelectionOutlinePass.cpp` 当前会包装它,并通过 `GetSceneViewportObjectIdOutlineShaderPath()` 注入 editor-owned shader 路径
- [SceneViewportRenderPlan](../../../Editor/Viewport/SceneViewportRenderPlan/SceneViewportRenderPlan.md) 决定当前帧是否创建 object-id outline 链路
- [CameraRenderer](../../Execution/CameraRenderer/CameraRenderer.md) 在主场景与 object-id pass 之后执行这些 `postScenePasses`
## 相关文档
- [Passes](../Passes.md)
- [SetShaderPath](SetShaderPath.md)
- [GetShaderPath](GetShaderPath.md)
- [Render](Render.md)
- [ObjectIdOutlinePassInputs](../ObjectIdOutlinePassInputs/ObjectIdOutlinePassInputs.md)
- [ObjectIdOutlineStyle](../ObjectIdOutlineStyle/ObjectIdOutlineStyle.md)
- [CameraRenderer](../../Execution/CameraRenderer/CameraRenderer.md)
- [RenderSurface](../../RenderSurface/RenderSurface.md)

View File

@@ -1,23 +1,5 @@
# BuiltinObjectIdOutlinePass::Render
> 2026-04-10 同步:当前签名与语义如下;若下文旧段落仍出现旧的 `objectIdTextureView` 单参数写法,请以这里为准。
```cpp
bool Render(
const RenderContext& renderContext,
const RenderSurface& surface,
const ObjectIdOutlinePassInputs& inputs,
const std::vector<uint64_t>& selectedObjectIds,
const ObjectIdOutlineStyle& style = {});
```
## 当前语义更新
- object-id 输入纹理由 [ObjectIdOutlinePassInputs](../ObjectIdOutlinePassInputs/ObjectIdOutlinePassInputs.md) 描述,同时显式携带进入 pass 前的资源状态。
- `EnsureInitialized(...)` 现在按 backend、目标颜色格式和目标 `sampleCount` 重新建资源surface 变化时会销毁旧的 pipeline / descriptor 再创建。
- viewport 和 scissor 取自 `surface.GetRenderArea()`,不再固定使用整张 surface。
-`surface.IsAutoTransitionEnabled()``true` 时,会把目标颜色从 `surface.GetColorStateAfter()` 切到 `RenderTarget`,并把 `inputs.objectIdTextureView``inputs.objectIdTextureState` 切到 `PixelShaderResource`,结束后再恢复。
**命名空间**: `XCEngine::Rendering::Passes`
**类型**: `method`
@@ -30,7 +12,7 @@ bool Render(
bool Render(
const RenderContext& renderContext,
const RenderSurface& surface,
RHI::RHIResourceView* objectIdTextureView,
const ObjectIdOutlinePassInputs& inputs,
const std::vector<uint64_t>& selectedObjectIds,
const ObjectIdOutlineStyle& style = {});
```
@@ -41,20 +23,22 @@ bool Render(
## 当前实现流程
1. 如果 `renderContext` 无效、后端不是 `D3D12``objectIdTextureView == nullptr``selectedObjectIds` 为空,直接返回 `false`
2. 调用 `EnsureInitialized(renderContext)`;如果当前 device/backend 变化,会先销毁旧资源再重建。若 `shaderPath` 为空或配置路径下的 shader 无法加载,也会在这里失败
3. 检查 `surface.GetColorAttachments()`,要求至少存在一个有效颜色附件
4. 构建 `OutlineConstants`,写入 viewport 尺寸、轮廓颜色、调试开关、像素宽度和最多 `256` 个选中对象编码颜色
5. 把常量缓冲写到 `m_constantSet`,把 `objectIdTextureView` 绑定到 `m_textureSet`
6. 设置渲染目标为 `surface` 的第一个颜色附件,并提交一次全屏三角形 `Draw(3, 1, 0, 0)`
1. 如果 `renderContext` 无效、`inputs.objectIdTextureView == nullptr``selectedObjectIds` 为空,直接返回 `false`
2. 检查 `surface` 是否具备单个有效颜色附件,以及有效的 `renderArea`
3. 调用 `EnsureInitialized(renderContext, surface)`;如果当前 device/backend、render target format 或 sample count 变化,会先销毁旧资源再重建
4. `selectedObjectIds` 逐个转换成 render object id最多编码 `256` 个,转换失败的条目会被跳过;若最终一个都没留下,返回 `false`
5. 构建 `OutlineConstants`,写入 viewport 尺寸、轮廓颜色、调试开关、像素宽度和选中对象编码颜色
6. 把常量缓冲写到 `m_constantSet`,把 `inputs.objectIdTextureView` 绑定到 `m_textureSet`
7.`surface.IsAutoTransitionEnabled()``true`,则把输出颜色附件切到 `RenderTarget`、把 object-id 输入从 `inputs.objectIdTextureState` 切到 `PixelShaderResource`,并在结束后恢复。
8. 使用 `surface.GetRenderArea()` 设置 viewport 与 scissor提交一次全屏三角形 `Draw(3, 1, 0, 0)`
## 关键语义
- 这条路径不再隐式依赖 engine builtin outline shader调用方必须先通过构造函数或 [SetShaderPath](SetShaderPath.md) 提供有效路径。
- 这条路径不再隐式依赖某个固定后端 outline shader调用方必须先通过构造函数或 [SetShaderPath](SetShaderPath.md) 提供有效路径。
- 当前只使用 `surface` 的第一个颜色附件。
- pass 自己不会做 render target 清空;如果要输出 debug mask 这“整张替换”的结果,需要由调用方先清空目标。
- pass 自己也不负责资源状态切换;调用前应保证颜色目标已经在 `RenderTarget` 状态、object-id SRV 已经可读
- 当前 viewport 和 scissor 始终覆盖整张 surface而不是 `surface.GetRenderArea()`
- pass 自己不会做 render target 清空;如果要输出 debug mask 这“整张替换”的结果,需要由调用方先清空目标。
- 当自动状态切换关闭时pass 不会替调用方检查目标与 object-id 输入是否已经处于正确资源状态
- viewport 和 scissor 当前都会遵循 `surface.GetRenderArea()`
## 典型使用位置
@@ -65,5 +49,6 @@ bool Render(
- [BuiltinObjectIdOutlinePass](BuiltinObjectIdOutlinePass.md)
- [SetShaderPath](SetShaderPath.md)
- [ObjectIdOutlinePassInputs](../ObjectIdOutlinePassInputs/ObjectIdOutlinePassInputs.md)
- [ObjectIdOutlineStyle](../ObjectIdOutlineStyle/ObjectIdOutlineStyle.md)
- [RenderSurface](../../RenderSurface/RenderSurface.md)

View File

@@ -10,30 +10,22 @@
## 概览
## 2026-04-10 同步补充
以下内容以当前 `BuiltinVolumetricPass.h/.cpp` 为准:
- 新增了公开预热接口 [PrepareVolumeResources](PrepareVolumeResources.md),用于在真正 `Execute(...)` 之前把 cube proxy mesh 和可见 `NanoVDB` volume 的 GPU 资源准备好。
- pipeline cache key 现在显式包含目标 surface 的 `sampleCount``sampleQuality`,不再只按 render state、shader、format 和 keyword 签名区分。
- `Execute(...)` 仍要求 surface 具备“单颜色附件 + depth 附件”,但 viewport / scissor 现在按 `surface.GetRenderArea()` 生效。
- volume 字段的真实上传与缓存复用由 `RenderResourceCache` 负责;`BuiltinVolumetricPass` 自己不做 legacy fallback。
`BuiltinVolumetricPass` 是当前体积渲染链路的核心执行器。
它继承自 `RenderPass`,但和普通 mesh pass 相比有几处明显特点:
- 几何始终来自 builtin cube mesh而不是体积资源自带网格
- 着色器必须声明 `PerObject``VolumeField` 资源绑定
- descriptor set 与 pipeline state 会按 shader pass、材质和 volume SRV 动态缓存
- descriptor set 与 pipeline state 会按 shader pass、材质、surface 格式以及采样参数动态缓存
## 当前执行流程
1. [Initialize](Initialize.md) / `EnsureInitialized(...)` 加载 builtin cube mesh
2. [Execute](Execute.md) 校验 `RenderSurface` 是否具备单颜色附件和深度附件
3. 逐个遍历 `sceneData.visibleVolumes`
4. 为每个体积解析兼容的 volumetric shader pass
5. 构建或复用 pipeline layout、pipeline state 和动态 descriptor set
6. 把体积 bounds、材质常量、主方向光常量与 volume SRV 绑定后提交 draw
1. [Initialize](Initialize.md) / `EnsureInitialized(...)` 加载 builtin cube mesh 和基础资源
2. [PrepareVolumeResources](PrepareVolumeResources.md) 预热当前帧可见体积需要的 mesh / volume GPU 资源
3. [Execute](Execute.md) 校验 `RenderSurface` 是否具备单颜色附件、深度附件和有效 render area
4. 逐个遍历 `sceneData.visibleVolumes`
5. 为每个体积解析兼容的 volumetric shader pass
6. 构建或复用 pipeline layout、pipeline state 和动态 descriptor set
7. 把体积 bounds、材质常量、光照常量与 volume SRV 绑定后提交 draw
## 关键内部状态
@@ -42,15 +34,16 @@
| `m_builtinCubeMesh` | 所有体积绘制共用的 cube proxy mesh |
| `m_resourceCache` | 复用 mesh 与 volume GPU 资源 |
| `m_passResourceLayouts` | 按 shader/pass 缓存资源布局 |
| `m_pipelineStates` | 按 render state、shader、格式与 keyword 签名缓存 pipeline |
| `m_pipelineStates` | 按 render state、shader、格式、sample count / quality 与 keyword 签名缓存 pipeline |
| `m_dynamicDescriptorSets` | 按对象、材质、volume field 缓存动态描述符集 |
## 当前实现边界
- 只处理 `VisibleVolumeItem`
- 只接受 `VolumeStorageKind::NanoVDB`
- 当前只为 `VolumeStorageKind::NanoVDB` 体积准备 GPU 资源并参与绘制
- 当前要求 surface 为“单颜色附件 + 深度附件”模型
- 若 shader pass 未声明 `PerObject``VolumeField` 绑定,会直接失败而不是做 legacy fallback
- 这仍然是 builtin forward 链路中的一个 scene pass不是独立的体渲染框架或 render graph 子系统
## 公开方法
@@ -58,14 +51,20 @@
|------|------|
| [BuildInputLayout](BuildInputLayout.md) | 返回体积 pass 使用的顶点布局 |
| [GetName](GetName.md) | 返回 pass 名称 |
| [Initialize](Initialize.md) | 预热 builtin cube mesh 等资源 |
| [PrepareVolumeResources](PrepareVolumeResources.md) | 预热可见体渲染所需的 mesh / volume GPU 资源 |
| [Initialize](Initialize.md) | 预热 builtin cube mesh 等基础资源 |
| [PrepareVolumeResources](PrepareVolumeResources.md) | 为当前帧可见体积预热 mesh volume GPU 资源 |
| [Execute](Execute.md) | 绘制所有可见体积 |
| [Shutdown](Shutdown.md) | 销毁缓存的 RHI 资源 |
## 真实接入位置
- [BuiltinForwardPipeline](../../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md) 在场景存在 `visibleVolumes` 时,会先调用 [PrepareVolumeResources](PrepareVolumeResources.md) 预热资源,再把当前 pass 放进 scene-pass 执行序列
- `RenderSceneExtractor` 负责把体积对象提取到 `sceneData.visibleVolumes`
## 相关文档
- [Passes](../Passes.md)
- [VisibleVolumeItem](../../FrameData/VisibleVolumeItem/VisibleVolumeItem.md)
- [VolumeField](../../../Resources/Volume/VolumeField/VolumeField.md)
- [RenderResourceCache](../../Caches/RenderResourceCache/RenderResourceCache.md)
- [VolumeRendererComponent](../../../Components/VolumeRendererComponent/VolumeRendererComponent.md)

View File

@@ -4,28 +4,26 @@
bool Execute(const RenderPassContext& context) override;
```
## 2026-04-10 更新
- `Execute(...)` 现在依赖 surface 的 `renderArea``sampleCount``sampleQuality` 契约;这些字段会进入 pipeline 选择与 viewport/scissor 设置。
- volume 数据上传不是在这里兜底完成的;更推荐在前置阶段调用 [PrepareVolumeResources](PrepareVolumeResources.md) 先把 mesh / volume cache 预热好。
`context.sceneData.visibleVolumes` 中的体积绘制到当前 render target。
## 当前实现流程
1. 校验 `renderContext`
2.`visibleVolumes` 为空,直接返回 `true`
3. 要求 surface 具备单颜色附件、深度附件和有效 render area
4. 设置 viewport、scissor 和 triangle-list topology
5. 逐个调用内部 `DrawVisibleVolume(...)`
1. 校验 `renderContext`
2.`visibleVolumes` 为空,直接返回 `true`
3. 要求 surface 具备单颜色附件、深度附件和有效 render area
4. 调用 [PrepareVolumeResources](PrepareVolumeResources.md) 预热当前帧体积资源。
5. 设置 viewport、scissor 和 triangle-list topology。
6. 逐个调用内部 `DrawVisibleVolume(...)`
## 关键语义
- 这里不负责 scene extraction输入必须已经是 `VisibleVolumeItem`
- 体积绘制依赖材质 shader pass 与 volume SRV 都已可用
- 某个体积绘制失败不会自动切换为其他 shader 或 fallback path
- 这里不负责 scene extraction输入必须已经是 `VisibleVolumeItem`
- 体积绘制依赖材质 shader pass 与 volume SRV 都已可用
- pipeline state 会按 surface 的颜色/深度格式与 sample count / quality 建立或复用。
- 某个体积绘制失败不会自动切换为其他 shader 或 fallback path。
## 相关文档
- [BuiltinVolumetricPass](BuiltinVolumetricPass.md)
- [PrepareVolumeResources](PrepareVolumeResources.md)
- [VisibleVolumeItem](../../FrameData/VisibleVolumeItem/VisibleVolumeItem.md)

View File

@@ -4,20 +4,17 @@
bool Initialize(const RenderContext& context) override;
```
## 2026-04-10 更新
- `Initialize(...)` 当前仍只是进入内部 `EnsureInitialized(...)`,重点是预热 builtin cube mesh 等基础资源。
- 可见 volume 的 GPU 资源预热已经拆到 [PrepareVolumeResources](PrepareVolumeResources.md);如果要在真正绘制前确保 `NanoVDB` 数据和 SRV 就绪,应调用那个入口。
预热体积 pass 依赖的基础资源。
## 当前行为
- 实际入口会转到内部 `EnsureInitialized(...)`
- 当前最关键的初始化工作是加载 builtin cube mesh
- `RenderContext` 无效或 cube mesh 加载失败,返回 `false`
- 实际入口会转到内部 `EnsureInitialized(...)`
- 当前最关键的初始化工作是加载 builtin cube mesh,并准备与 `RenderContext` 绑定的基础缓存。
- 这里不会为某一帧具体的 `visibleVolumes` 预热 GPU 资源;这部分工作已经拆到 [PrepareVolumeResources](PrepareVolumeResources.md)。
-`RenderContext` 无效或 cube mesh 加载失败,返回 `false`
## 相关文档
- [BuiltinVolumetricPass](BuiltinVolumetricPass.md)
- [PrepareVolumeResources](PrepareVolumeResources.md)
- [Execute](Execute.md)

View File

@@ -6,22 +6,29 @@ bool PrepareVolumeResources(
const RenderSceneData& sceneData);
```
在真正 `Execute(...)` 之前预热体渲染依赖的 mesh / volume GPU 资源。
为当前帧可见体积预热 `BuiltinVolumetricPass` 需要的 mesh volume GPU 资源。
## 当前行为
## 当前实现流程
- 会先确保 builtin cube mesh 基础资源已经初始化完成
-`sceneData.visibleVolumes` 非空时,会先通过 `RenderResourceCache` cube proxy mesh 的缓存视图
- 遍历可见体积时,只会继续处理同时满足以下条件的项:
- `volumeField != nullptr`
- `material != nullptr`
- `volumeField->GetStorageKind() == VolumeStorageKind::NanoVDB`
- 对于满足条件的体积,会调用 `RenderResourceCache::GetOrCreateVolumeField(...)` 预热 volume SRV如果缓存创建失败返回 `false`
- 如果没有可见体积,或所有可见体积都被过滤掉,函数仍然可以返回 `true`
1. 先调用内部 `EnsureInitialized(context)`确保 builtin cube mesh 基础资源可用
2. 如果 `visibleVolumes` 非空,则先通过 `RenderResourceCache` cube proxy mesh 的 GPU 缓存,并要求 `vertexBufferView` 有效
3. 逐个遍历 `sceneData.visibleVolumes`
4. 对同时满足“存在 `volumeField`、存在 `material`、且存储类型为 `NanoVDB`”的条目,调用 `RenderResourceCache::GetOrCreateVolumeField(...)` 预热 volume SRV。
5. 只要某个必要资源创建失败,就返回 `false`
## 当前语义
- 这是场景相关的资源预热步骤,和 [Initialize](Initialize.md) 的“基础一次性准备”不同。
-`visibleVolumes` 为空时,该接口会返回 `true`
- 对不满足绘制条件的体积条目,当前实现会直接跳过,而不是报错。
## 真实接入位置
- [BuiltinForwardPipeline](../../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md) 当前会在场景存在体积时提前调用它,避免真正进入 [Execute](Execute.md) 后才发现 volume 资源还没准备好。
## 相关文档
- [BuiltinVolumetricPass](BuiltinVolumetricPass.md)
- [Initialize](Initialize.md)
- [Execute](Execute.md)
- [VisibleVolumeItem](../../FrameData/VisibleVolumeItem/VisibleVolumeItem.md)
- [RenderResourceCache](../../Caches/RenderResourceCache/RenderResourceCache.md)

View File

@@ -13,12 +13,17 @@
| 字段 | 说明 |
|------|------|
| `objectIdTextureView` | object-id 纹理视图。 |
| `objectIdTextureState` | object-id 纹理在进入 pass 前的资源状态。 |
| `objectIdTextureState` | object-id 纹理在进入 pass 前的资源状态。 |
## 当前作用
-`BuiltinObjectIdOutlinePass::Render(...)` 提供 object-id SRV 与恢复状态信息
- surface 开启自动状态切换时,`objectIdTextureState` 会被当作进入 pass 前的原始状态,用于从/恢复`PixelShaderResource`
-`BuiltinObjectIdOutlinePass::Render(...)` 提供 object-id 输入 SRV。
- 在目标 `surface` 开启自动状态切换时,提供“进入 pass 前的原始状态,以便 pass 临时切`PixelShaderResource` 并在结束后恢复
## 当前实现边界
- 这个结构只描述 object-id 输入,不描述输出 surface。
-`surface.IsAutoTransitionEnabled()``false`pass 不会自动验证这里声明的状态是否与真实资源状态一致。
## 相关文档