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

View File

@@ -1,23 +1,5 @@
# BuiltinObjectIdOutlinePass::Render # 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` **命名空间**: `XCEngine::Rendering::Passes`
**类型**: `method` **类型**: `method`
@@ -30,7 +12,7 @@ bool Render(
bool Render( bool Render(
const RenderContext& renderContext, const RenderContext& renderContext,
const RenderSurface& surface, const RenderSurface& surface,
RHI::RHIResourceView* objectIdTextureView, const ObjectIdOutlinePassInputs& inputs,
const std::vector<uint64_t>& selectedObjectIds, const std::vector<uint64_t>& selectedObjectIds,
const ObjectIdOutlineStyle& style = {}); const ObjectIdOutlineStyle& style = {});
``` ```
@@ -41,20 +23,22 @@ bool Render(
## 当前实现流程 ## 当前实现流程
1. 如果 `renderContext` 无效、后端不是 `D3D12``objectIdTextureView == nullptr``selectedObjectIds` 为空,直接返回 `false` 1. 如果 `renderContext` 无效、`inputs.objectIdTextureView == nullptr``selectedObjectIds` 为空,直接返回 `false`
2. 调用 `EnsureInitialized(renderContext)`;如果当前 device/backend 变化,会先销毁旧资源再重建。若 `shaderPath` 为空或配置路径下的 shader 无法加载,也会在这里失败 2. 检查 `surface` 是否具备单个有效颜色附件,以及有效的 `renderArea`
3. 检查 `surface.GetColorAttachments()`,要求至少存在一个有效颜色附件 3. 调用 `EnsureInitialized(renderContext, surface)`;如果当前 device/backend、render target format 或 sample count 变化,会先销毁旧资源再重建
4. 构建 `OutlineConstants`,写入 viewport 尺寸、轮廓颜色、调试开关、像素宽度和最多 `256` 个选中对象编码颜色 4. `selectedObjectIds` 逐个转换成 render object id最多编码 `256` 个,转换失败的条目会被跳过;若最终一个都没留下,返回 `false`
5. 把常量缓冲写到 `m_constantSet`,把 `objectIdTextureView` 绑定到 `m_textureSet` 5. 构建 `OutlineConstants`,写入 viewport 尺寸、轮廓颜色、调试开关、像素宽度和选中对象编码颜色
6. 设置渲染目标为 `surface` 的第一个颜色附件,并提交一次全屏三角形 `Draw(3, 1, 0, 0)` 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` 的第一个颜色附件。 - 当前只使用 `surface` 的第一个颜色附件。
- pass 自己不会做 render target 清空;如果要输出 debug mask 这“整张替换”的结果,需要由调用方先清空目标。 - pass 自己不会做 render target 清空;如果要输出 debug mask 这“整张替换”的结果,需要由调用方先清空目标。
- pass 自己也不负责资源状态切换;调用前应保证颜色目标已经在 `RenderTarget` 状态、object-id SRV 已经可读 - 当自动状态切换关闭时pass 不会替调用方检查目标与 object-id 输入是否已经处于正确资源状态
- 当前 viewport 和 scissor 始终覆盖整张 surface而不是 `surface.GetRenderArea()` - viewport 和 scissor 当前都会遵循 `surface.GetRenderArea()`
## 典型使用位置 ## 典型使用位置
@@ -65,5 +49,6 @@ bool Render(
- [BuiltinObjectIdOutlinePass](BuiltinObjectIdOutlinePass.md) - [BuiltinObjectIdOutlinePass](BuiltinObjectIdOutlinePass.md)
- [SetShaderPath](SetShaderPath.md) - [SetShaderPath](SetShaderPath.md)
- [ObjectIdOutlinePassInputs](../ObjectIdOutlinePassInputs/ObjectIdOutlinePassInputs.md)
- [ObjectIdOutlineStyle](../ObjectIdOutlineStyle/ObjectIdOutlineStyle.md) - [ObjectIdOutlineStyle](../ObjectIdOutlineStyle/ObjectIdOutlineStyle.md)
- [RenderSurface](../../RenderSurface/RenderSurface.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` 是当前体积渲染链路的核心执行器。 `BuiltinVolumetricPass` 是当前体积渲染链路的核心执行器。
它继承自 `RenderPass`,但和普通 mesh pass 相比有几处明显特点: 它继承自 `RenderPass`,但和普通 mesh pass 相比有几处明显特点:
- 几何始终来自 builtin cube mesh而不是体积资源自带网格 - 几何始终来自 builtin cube mesh而不是体积资源自带网格
- 着色器必须声明 `PerObject``VolumeField` 资源绑定 - 着色器必须声明 `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 1. [Initialize](Initialize.md) / `EnsureInitialized(...)` 加载 builtin cube mesh 和基础资源
2. [Execute](Execute.md) 校验 `RenderSurface` 是否具备单颜色附件和深度附件 2. [PrepareVolumeResources](PrepareVolumeResources.md) 预热当前帧可见体积需要的 mesh / volume GPU 资源
3. 逐个遍历 `sceneData.visibleVolumes` 3. [Execute](Execute.md) 校验 `RenderSurface` 是否具备单颜色附件、深度附件和有效 render area
4. 为每个体积解析兼容的 volumetric shader pass 4. 逐个遍历 `sceneData.visibleVolumes`
5. 构建或复用 pipeline layout、pipeline state 和动态 descriptor set 5. 为每个体积解析兼容的 volumetric shader pass
6. 把体积 bounds、材质常量、主方向光常量与 volume SRV 绑定后提交 draw 6. 构建或复用 pipeline layout、pipeline state 和动态 descriptor set
7. 把体积 bounds、材质常量、光照常量与 volume SRV 绑定后提交 draw
## 关键内部状态 ## 关键内部状态
@@ -42,15 +34,16 @@
| `m_builtinCubeMesh` | 所有体积绘制共用的 cube proxy mesh | | `m_builtinCubeMesh` | 所有体积绘制共用的 cube proxy mesh |
| `m_resourceCache` | 复用 mesh 与 volume GPU 资源 | | `m_resourceCache` | 复用 mesh 与 volume GPU 资源 |
| `m_passResourceLayouts` | 按 shader/pass 缓存资源布局 | | `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 缓存动态描述符集 | | `m_dynamicDescriptorSets` | 按对象、材质、volume field 缓存动态描述符集 |
## 当前实现边界 ## 当前实现边界
- 只处理 `VisibleVolumeItem` - 只处理 `VisibleVolumeItem`
- 只接受 `VolumeStorageKind::NanoVDB` - 当前只为 `VolumeStorageKind::NanoVDB` 体积准备 GPU 资源并参与绘制
- 当前要求 surface 为“单颜色附件 + 深度附件”模型 - 当前要求 surface 为“单颜色附件 + 深度附件”模型
- 若 shader pass 未声明 `PerObject``VolumeField` 绑定,会直接失败而不是做 legacy fallback - 若 shader pass 未声明 `PerObject``VolumeField` 绑定,会直接失败而不是做 legacy fallback
- 这仍然是 builtin forward 链路中的一个 scene pass不是独立的体渲染框架或 render graph 子系统
## 公开方法 ## 公开方法
@@ -58,14 +51,20 @@
|------|------| |------|------|
| [BuildInputLayout](BuildInputLayout.md) | 返回体积 pass 使用的顶点布局 | | [BuildInputLayout](BuildInputLayout.md) | 返回体积 pass 使用的顶点布局 |
| [GetName](GetName.md) | 返回 pass 名称 | | [GetName](GetName.md) | 返回 pass 名称 |
| [Initialize](Initialize.md) | 预热 builtin cube mesh 等资源 | | [Initialize](Initialize.md) | 预热 builtin cube mesh 等基础资源 |
| [PrepareVolumeResources](PrepareVolumeResources.md) | 预热可见体渲染所需的 mesh / volume GPU 资源 | | [PrepareVolumeResources](PrepareVolumeResources.md) | 为当前帧可见体积预热 mesh volume GPU 资源 |
| [Execute](Execute.md) | 绘制所有可见体积 | | [Execute](Execute.md) | 绘制所有可见体积 |
| [Shutdown](Shutdown.md) | 销毁缓存的 RHI 资源 | | [Shutdown](Shutdown.md) | 销毁缓存的 RHI 资源 |
## 真实接入位置
- [BuiltinForwardPipeline](../../Pipelines/BuiltinForwardPipeline/BuiltinForwardPipeline.md) 在场景存在 `visibleVolumes` 时,会先调用 [PrepareVolumeResources](PrepareVolumeResources.md) 预热资源,再把当前 pass 放进 scene-pass 执行序列
- `RenderSceneExtractor` 负责把体积对象提取到 `sceneData.visibleVolumes`
## 相关文档 ## 相关文档
- [Passes](../Passes.md) - [Passes](../Passes.md)
- [VisibleVolumeItem](../../FrameData/VisibleVolumeItem/VisibleVolumeItem.md) - [VisibleVolumeItem](../../FrameData/VisibleVolumeItem/VisibleVolumeItem.md)
- [VolumeField](../../../Resources/Volume/VolumeField/VolumeField.md) - [VolumeField](../../../Resources/Volume/VolumeField/VolumeField.md)
- [RenderResourceCache](../../Caches/RenderResourceCache/RenderResourceCache.md)
- [VolumeRendererComponent](../../../Components/VolumeRendererComponent/VolumeRendererComponent.md) - [VolumeRendererComponent](../../../Components/VolumeRendererComponent/VolumeRendererComponent.md)

View File

@@ -4,28 +4,26 @@
bool Execute(const RenderPassContext& context) override; 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。 `context.sceneData.visibleVolumes` 中的体积绘制到当前 render target。
## 当前实现流程 ## 当前实现流程
1. 校验 `renderContext` 1. 校验 `renderContext`
2.`visibleVolumes` 为空,直接返回 `true` 2.`visibleVolumes` 为空,直接返回 `true`
3. 要求 surface 具备单颜色附件、深度附件和有效 render area 3. 要求 surface 具备单颜色附件、深度附件和有效 render area
4. 设置 viewport、scissor 和 triangle-list topology 4. 调用 [PrepareVolumeResources](PrepareVolumeResources.md) 预热当前帧体积资源。
5. 逐个调用内部 `DrawVisibleVolume(...)` 5. 设置 viewport、scissor 和 triangle-list topology。
6. 逐个调用内部 `DrawVisibleVolume(...)`
## 关键语义 ## 关键语义
- 这里不负责 scene extraction输入必须已经是 `VisibleVolumeItem` - 这里不负责 scene extraction输入必须已经是 `VisibleVolumeItem`
- 体积绘制依赖材质 shader pass 与 volume SRV 都已可用 - 体积绘制依赖材质 shader pass 与 volume SRV 都已可用
- 某个体积绘制失败不会自动切换为其他 shader 或 fallback path - pipeline state 会按 surface 的颜色/深度格式与 sample count / quality 建立或复用。
- 某个体积绘制失败不会自动切换为其他 shader 或 fallback path。
## 相关文档 ## 相关文档
- [BuiltinVolumetricPass](BuiltinVolumetricPass.md) - [BuiltinVolumetricPass](BuiltinVolumetricPass.md)
- [PrepareVolumeResources](PrepareVolumeResources.md)
- [VisibleVolumeItem](../../FrameData/VisibleVolumeItem/VisibleVolumeItem.md) - [VisibleVolumeItem](../../FrameData/VisibleVolumeItem/VisibleVolumeItem.md)

View File

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

View File

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

View File

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