diff --git a/docs/api/XCEngine/Components/Components.md b/docs/api/XCEngine/Components/Components.md index 3c5e0dcc..35c9fe6f 100644 --- a/docs/api/XCEngine/Components/Components.md +++ b/docs/api/XCEngine/Components/Components.md @@ -54,7 +54,6 @@ - [MeshRendererComponent](MeshRendererComponent/MeshRendererComponent.md) - `MeshRendererComponent.h`,材质槽和渲染附加参数。 - [VolumeRendererComponent](VolumeRendererComponent/VolumeRendererComponent.md) - `VolumeRendererComponent.h`,体积资源、体积材质与阴影标志绑定。 - [TransformComponent](TransformComponent/TransformComponent.md) - `TransformComponent.h`,局部/世界变换与层级矩阵。 -- [VolumeRendererComponent](VolumeRendererComponent/VolumeRendererComponent.md) - `VolumeRendererComponent.h`,体数据、体材质和阴影标记组件。 ## 推荐阅读顺序 diff --git a/docs/api/XCEngine/Components/VolumeRendererComponent/VolumeRendererComponent.md b/docs/api/XCEngine/Components/VolumeRendererComponent/VolumeRendererComponent.md index d8ae4581..5181a239 100644 --- a/docs/api/XCEngine/Components/VolumeRendererComponent/VolumeRendererComponent.md +++ b/docs/api/XCEngine/Components/VolumeRendererComponent/VolumeRendererComponent.md @@ -6,107 +6,113 @@ **头文件**: `XCEngine/Components/VolumeRendererComponent.h` -**源文件**: `engine/src/Components/VolumeRendererComponent.cpp` - -**描述**: 体积渲染组件,负责把 `VolumeField`、体积材质和少量阴影标志绑定到 `GameObject` 上,并在序列化/反序列化与 deferred load 场景中保持资源身份恢复。 +**描述**: 体积渲染组件,保存 `VolumeField` 与 `Material` 的运行时句柄、项目资源身份与序列化路径,并暴露阴影相关开关。 ## 角色概述 -`VolumeRendererComponent` 回答的问题是: +`VolumeRendererComponent` 是当前场景里体积对象进入渲染链路的组件侧入口。它回答的是: -- 这个对象是否要作为体积参与渲染? -- 它绑定的是哪一个 `VolumeField`? -- 它使用哪一个 `Material`? -- 体积对象当前的阴影开关是什么? +- 这个 `GameObject` 当前绑定的是哪份体积资源? +- 这个体积资源应当使用哪份材质参与 `BuiltinVolumetricPass`? +- 反序列化后是立即同步加载,还是在 deferred scene load 模式下延迟到首次访问时异步兑现? -和 [MeshRendererComponent](../MeshRendererComponent/MeshRendererComponent.md) 类似,它同时承担“运行时资源句柄”和“可持久化资源身份”两层职责。 +按当前实现,它同时维护两组并行状态: -## 当前状态模型 +- `VolumeField` + - 运行时 `ResourceHandle` + - 路径缓存 `m_volumeFieldPath` + - 项目资源身份 `m_volumeFieldRef` + - deferred async load 挂起状态 +- `Material` + - 运行时 `ResourceHandle` + - 路径缓存 `m_materialPath` + - 项目资源身份 `m_materialRef` + - deferred async load 挂起状态 -当前实现维护两组几乎对称的资源状态: +## 当前实现语义 -| 状态 | 作用 | +### 资源绑定 + +- `SetVolumeFieldPath(...)` / `SetMaterialPath(...)` + - 立即清空挂起异步状态 + - 同步调用 `ResourceManager::Load(path)` + - 尝试把路径回填成稳定的 `AssetRef` +- `SetVolumeField(...)` / `SetMaterial(...)` + - 从句柄反推当前路径 + - 如果路径可解析为项目资源,则同步回填 `AssetRef` +- `ClearVolumeField()` / `ClearMaterial()` + - 同时清空句柄、路径、`AssetRef` 与挂起异步状态 + +### 序列化与反序列化 + +当前序列化优先级是: + +- 对有有效 `AssetRef` 的项目资源,优先写 `volumeRef=` / `materialRef=` +- 只有在没有有效 `AssetRef` 且路径带虚拟 scheme 时,才额外写 `volumePath=` / `materialPath=` +- 阴影标志始终写为 `castShadows=` 与 `receiveShadows=` + +`Deserialize(...)` 的恢复顺序是: + +1. 先重置当前绑定与阴影标志。 +2. 如果存在有效 `AssetRef`,优先按 `AssetRef` 恢复。 +3. 在 deferred scene load 模式下,优先只恢复可解析路径,不立刻加载资源。 +4. 只有虚拟路径在没有 `AssetRef` 时会被保留并作为恢复入口。 + +这意味着: + +- 普通项目资源的正式持久化协议是 `AssetRef` +- `test://`、`builtin://` 这类虚拟路径才长期依赖路径文本本身 + +### deferred async load + +`GetVolumeField()` / `GetVolumeFieldHandle()` 与 `GetMaterial()` / `GetMaterialHandle()` 都带副作用: + +- 如果当前只有路径没有已兑现句柄,会先触发 `EnsureDeferredAsync*LoadStarted()` +- 如果异步结果已经完成,会在读取前调用 `ResolvePending*()` 收口结果 + +因此在 deferred scene load 模式下,组件常见的中间状态是: + +- 路径与 `AssetRef` 已恢复 +- 运行时句柄仍为空 +- 首次读取句柄时才真正发起或收口异步加载 + +## 公开接口 + +| 接口 | 作用 | |------|------| -| `m_volumeField` / `m_volumeFieldPath` / `m_volumeFieldRef` | 体积资源句柄、路径缓存与稳定 `AssetRef`。 | -| `m_material` / `m_materialPath` / `m_materialRef` | 材质句柄、路径缓存与稳定 `AssetRef`。 | -| `m_pendingVolumeLoad` / `m_pendingMaterialLoad` | deferred async load 的挂起结果。 | -| `m_asyncVolumeLoadRequested` / `m_asyncMaterialLoadRequested` | 防止重复发起异步加载。 | -| `m_castShadows` / `m_receiveShadows` | 阴影相关附加开关。 | +| `GetVolumeField()` / `GetVolumeFieldHandle()` | 读取体积资源,并在需要时触发 deferred async load 收口 | +| `GetVolumeFieldPath()` / `GetVolumeFieldAssetRef()` | 读取体积资源元数据,不直接暴露 GPU/渲染行为 | +| `SetVolumeFieldPath(...)` / `SetVolumeField(...)` / `ClearVolumeField()` | 绑定或清空体积资源 | +| `GetMaterial()` / `GetMaterialHandle()` | 读取材质,并在需要时触发 deferred async load 收口 | +| `GetMaterialPath()` / `GetMaterialAssetRef()` | 读取材质元数据 | +| `SetMaterialPath(...)` / `SetMaterial(...)` / `ClearMaterial()` | 绑定或清空材质 | +| `GetCastShadows()` / `SetCastShadows(...)` | 控制组件层阴影投射标志 | +| `GetReceiveShadows()` / `SetReceiveShadows(...)` | 控制组件层阴影接收标志 | +| `Serialize(...)` / `Deserialize(...)` | 负责场景文本中的体积/材质引用恢复协议 | -## 绑定与恢复流程 - -### 1. 运行时按路径设置 - -- `SetVolumeFieldPath(...)` 会立即尝试 `ResourceManager::Load(path)`。 -- `SetMaterialPath(...)` 会立即尝试 `ResourceManager::Load(path)`。 -- 两条路径都会额外调用 `TryGetAssetRef(...)`,尽量把项目路径回填成稳定资源身份。 - -### 2. 运行时按句柄设置 - -- `SetVolumeField(...)` 与 `SetMaterial(...)` 会从句柄反推出路径。 -- 若路径对应项目资产,也会同步尝试回填 `AssetRef`。 - -### 3. 序列化与反序列化 - -`Serialize()` 当前优先写: - -- `volumeRef` -- `materialRef` - -只有在没有有效 `AssetRef` 且路径带 virtual scheme 时,才会保留: - -- `volumePath` -- `materialPath` - -`Deserialize()` 当前会先清空旧状态,再恢复: - -- 体积资源身份 -- 材质资源身份 -- `castShadows` -- `receiveShadows` - -若开启 deferred scene load,则会优先只恢复路径/身份,等首次访问句柄时再启动异步兑现。 - -## 与 deferred scene load 的关系 - -- `GetVolumeField()` / `GetVolumeFieldHandle()` 会触发: - - `EnsureDeferredAsyncVolumeLoadStarted()` - - `ResolvePendingVolumeField()` -- `GetMaterial()` / `GetMaterialHandle()` 会触发: - - `EnsureDeferredAsyncMaterialLoadStarted()` - - `ResolvePendingMaterial()` - -因此这几个 getter 不是纯只读访问器,而是带有“补发异步兑现”的副作用。 - -## 与渲染链路的关系 - -- `RenderSceneUtility` 当前会从对象上提取 `VolumeRendererComponent`,并构造 [VisibleVolumeItem](../../Rendering/FrameData/VisibleVolumeItem/VisibleVolumeItem.md)。 -- 后续 [BuiltinVolumetricPass](../../Rendering/Passes/BuiltinVolumetricPass/BuiltinVolumetricPass.md) 会消费这些可见体积项。 -- 这意味着“组件存在”不等于“这一帧一定有可绘制体积”: - - 体积资源可能尚未兑现 - - 材质可能为空 - - deferred load 可能仍在挂起 - -## 测试与锚点 +## 测试与调用链 - `tests/Components/test_volume_renderer_component.cpp` - - `SetResourcesCachesHandlesPathsAndFlags` - - `SerializeAndDeserializePreservesVirtualPathsAndFlags` - - `DeferredSceneDeserializeLoadsVolumeFieldAsyncByPath` -- `tests/Rendering/unit/test_render_scene_extractor.cpp` - - 覆盖体积对象被提取进渲染场景数据 -- `engine/src/Components/ComponentFactoryRegistry.cpp` - - 当前把 `"VolumeRenderer"` 注册为内建组件类型 + - 覆盖句柄/路径缓存 + - 覆盖虚拟路径序列化 + - 覆盖 deferred scene load 下按路径异步恢复体积资源 +- `engine/src/Rendering/Extraction/RenderSceneUtility.cpp` + - 当前通过本组件读取 `VolumeField` 与 `Material`,组装 `VisibleVolumeItem` +- `editor/src/ComponentEditors/VolumeRendererComponentEditor.h` + - 当前 Inspector 里的 Volume Renderer 面板直接调用本组件的路径与阴影接口 ## 当前实现边界 -- 正式持久化协议优先是 `AssetRef`,不是普通项目路径。 -- 只有 virtual scheme 路径才会在没有有效 `AssetRef` 时稳定保留。 -- 当前组件只维护一个体积资源和一个材质,不涉及更复杂的多体积槽位模型。 +- 组件只负责 CPU 侧资源引用与场景序列化,不负责 GPU 上传。 +- 当前 `Get*Handle()` / `Get*()` 不是纯读取器,调用方要接受其会触发异步加载状态推进。 +- 没有有效 `AssetRef` 的普通项目路径不会被当成正式持久化协议长期保留。 +- 阴影标志当前在组件侧可读写可序列化,但具体是否在所有渲染路径都生效,要看上游提取与 pass 实现。 ## 相关文档 -- [当前模块](../Components.md) +- [Components](../Components.md) - [VolumeField](../../Resources/Volume/VolumeField/VolumeField.md) +- [Material](../../Resources/Material/Material/Material.md) - [VisibleVolumeItem](../../Rendering/FrameData/VisibleVolumeItem/VisibleVolumeItem.md) - [BuiltinVolumetricPass](../../Rendering/Passes/BuiltinVolumetricPass/BuiltinVolumetricPass.md) +- [VolumeRendererComponentEditor](../../Editor/ComponentEditors/VolumeRendererComponentEditor/VolumeRendererComponentEditor.md) diff --git a/docs/api/XCEngine/Rendering/FrameData/FrameData.md b/docs/api/XCEngine/Rendering/FrameData/FrameData.md index f9fd6f66..f9e88ac6 100644 --- a/docs/api/XCEngine/Rendering/FrameData/FrameData.md +++ b/docs/api/XCEngine/Rendering/FrameData/FrameData.md @@ -19,7 +19,6 @@ - [RenderSceneData](RenderSceneData/RenderSceneData.md) - [VisibleRenderItem](VisibleRenderItem/VisibleRenderItem.md) - [VisibleVolumeItem](VisibleVolumeItem/VisibleVolumeItem.md) -- [VisibleVolumeItem](VisibleVolumeItem/VisibleVolumeItem.md) ## 当前职责 @@ -28,7 +27,6 @@ - 承载主方向光、阴影和 additional lights 快照 - 承载 scene extraction 之后的 `visibleItems` - 承载 scene extraction 之后的 `visibleVolumes` -- 承载 scene extraction 之后的 `visibleVolumes` ## 相关文档 diff --git a/docs/api/XCEngine/Rendering/FrameData/VisibleVolumeItem/VisibleVolumeItem.md b/docs/api/XCEngine/Rendering/FrameData/VisibleVolumeItem/VisibleVolumeItem.md index c61942b7..866c5319 100644 --- a/docs/api/XCEngine/Rendering/FrameData/VisibleVolumeItem/VisibleVolumeItem.md +++ b/docs/api/XCEngine/Rendering/FrameData/VisibleVolumeItem/VisibleVolumeItem.md @@ -6,38 +6,49 @@ **头文件**: `XCEngine/Rendering/FrameData/VisibleVolumeItem.h` -**描述**: scene extraction 之后交给体积渲染阶段消费的一条可见体积记录,已经带上体积组件、体积资源、材质、渲染队列、相机距离和世界变换。 +**描述**: scene extraction 之后交给体积渲染阶段消费的一条可见体积记录,已经带上组件、资源、渲染队列、相机距离和世界变换。 ## 字段 | 字段 | 说明 | |------|------| -| `gameObject` | 来源场景对象。 | -| `volumeRenderer` | 提供体积资源与阴影标志的组件。 | -| `volumeField` | 当前解析出的体积资源。 | -| `material` | 当前解析出的材质指针,可为空。 | -| `renderQueue` | 当前体积项的渲染队列。 | -| `cameraDistanceSq` | 到当前相机的距离平方。 | -| `localToWorld` | 当前体积项的世界变换。 | +| `gameObject` | 来源场景对象 | +| `volumeRenderer` | 提供体积资源与阴影标志的组件 | +| `volumeField` | 当前要渲染的体积资源 | +| `material` | 当前体积对象使用的材质 | +| `renderQueue` | 当前体积对象的渲染队列 | +| `cameraDistanceSq` | 到当前相机的距离平方 | +| `localToWorld` | 当前体积对象的世界变换 | ## 当前语义 -- 只有对象上存在有效 [VolumeRendererComponent](../../../Components/VolumeRendererComponent/VolumeRendererComponent.md) 且体积资源可解析时,scene extraction 才会生成这条记录。 -- opaque / transparent 的排序规则同样会消费 `renderQueue` 与 `cameraDistanceSq`。 -- 这条记录与 [VisibleRenderItem](../VisibleRenderItem/VisibleRenderItem.md) 平行存在,前者服务体积链路,后者服务 mesh 链路。 +- 同一个 `GameObject` 至多展开成一条 `VisibleVolumeItem`,不像网格那样会按 section 细分。 +- `renderQueue` 与 `cameraDistanceSq` 当前会参与稳定排序: + - opaque 队列按近到远 + - transparent 队列按远到近 +- `localToWorld` 当前直接来自 `TransformComponent::GetLocalToWorldMatrix()`,下游体积 pass 会据此构造 `model` 与 `inverseModel` 常量。 -## 当前调用链 +## 测试与调用链 - `engine/src/Rendering/Extraction/RenderSceneUtility.cpp` - - 负责构造 `VisibleVolumeItem` + - 当前负责从 `VolumeRendererComponent` 组装本结构 - `engine/src/Rendering/Extraction/RenderSceneExtractor.cpp` - - 负责提取与排序 `sceneData.visibleVolumes` -- [BuiltinVolumetricPass](../../Passes/BuiltinVolumetricPass/BuiltinVolumetricPass.md) - - 当前消费 `visibleVolumes` + - 当前对 `visibleVolumes` 执行稳定排序 +- `engine/src/Rendering/Passes/BuiltinVolumetricPass.cpp` + - 当前直接消费本结构执行逐体积绘制 +- `tests/Rendering/unit/test_render_scene_extractor.cpp` + - 覆盖可见体积提取、剔除和按 `renderQueue` 排序 + +## 当前实现边界 + +- 这是 extraction 与 execution 之间的中间结构,不负责资源生命周期。 +- 本结构不记录 GPU 资源句柄;GPU 上传由 `RenderResourceCache` 处理。 +- 当前没有额外的体积 section、LOD 或 batching 语义。 ## 相关文档 - [FrameData](../FrameData.md) -- [VisibleRenderItem](../VisibleRenderItem/VisibleRenderItem.md) +- [RenderSceneData](../RenderSceneData/RenderSceneData.md) - [VolumeRendererComponent](../../../Components/VolumeRendererComponent/VolumeRendererComponent.md) - [BuiltinVolumetricPass](../../Passes/BuiltinVolumetricPass/BuiltinVolumetricPass.md) +- [RenderSceneUtility](../../Extraction/RenderSceneUtility/RenderSceneUtility.md) diff --git a/docs/api/XCEngine/Rendering/Passes/BuiltinVolumetricPass/BuildInputLayout.md b/docs/api/XCEngine/Rendering/Passes/BuiltinVolumetricPass/BuildInputLayout.md index 7c5a2e25..e2b1f2d3 100644 --- a/docs/api/XCEngine/Rendering/Passes/BuiltinVolumetricPass/BuildInputLayout.md +++ b/docs/api/XCEngine/Rendering/Passes/BuiltinVolumetricPass/BuildInputLayout.md @@ -1,29 +1,18 @@ # BuiltinVolumetricPass::BuildInputLayout -**命名空间**: `XCEngine::Rendering::Passes` - -**类型**: `method` - -**头文件**: `XCEngine/Rendering/Passes/BuiltinVolumetricPass.h` - -## 签名 - ```cpp static RHI::InputLayoutDesc BuildInputLayout(); ``` -## 作用 +返回体积绘制当前使用的顶点布局。 -返回 `BuiltinVolumetricPass` 当前使用的顶点布局描述。 +## 当前布局 -## 当前行为 +- `POSITION` +- `NORMAL` +- `TEXCOORD0` -- 当前布局直接基于 `Resources::StaticMeshVertex`。 -- 依次声明: - - `POSITION` - - `NORMAL` - - `TEXCOORD0` -- 说明体积 pass 当前复用静态网格顶点结构,而不是定义单独的体积代理顶点格式。 +这些元素都来自 `Resources::StaticMeshVertex`,说明体积 pass 当前沿用静态 mesh 顶点格式来绘制 cube proxy mesh。 ## 相关文档 diff --git a/docs/api/XCEngine/Rendering/Passes/BuiltinVolumetricPass/BuiltinVolumetricPass.md b/docs/api/XCEngine/Rendering/Passes/BuiltinVolumetricPass/BuiltinVolumetricPass.md index 4eec474e..97efb934 100644 --- a/docs/api/XCEngine/Rendering/Passes/BuiltinVolumetricPass/BuiltinVolumetricPass.md +++ b/docs/api/XCEngine/Rendering/Passes/BuiltinVolumetricPass/BuiltinVolumetricPass.md @@ -6,66 +6,52 @@ **头文件**: `XCEngine/Rendering/Passes/BuiltinVolumetricPass.h` -**描述**: builtin 体积渲染 pass,消费 `RenderSceneData::visibleVolumes`,为每个可见体积解析 shader pass、管线状态、descriptor set 与 `VolumeField` GPU 资源后执行绘制。 +**描述**: 内建体积绘制 pass,使用 cube 代理网格、材质 shader pass 和体积资源描述符把可见体积绘制到当前颜色目标。 ## 概览 -`BuiltinVolumetricPass` 当前是体积渲染进入 builtin forward 链路的实际执行者。它不是独立的体积框架,而是围绕现有 scene-pass 体系补出的一条专用路径: +`BuiltinVolumetricPass` 是当前体积渲染链路的核心执行器。 +它继承自 `RenderPass`,但和普通 mesh pass 相比有几处明显特点: -- 输入来自 `RenderSceneData::visibleVolumes` -- 几何代理当前固定使用 builtin cube mesh -- 资源绑定依赖 shader pass 的 builtin resource layout 解析 -- 当前只接受 `VolumeStorageKind::NanoVDB` +- 几何始终来自 builtin cube mesh,而不是体积资源自带网格 +- 着色器必须声明 `PerObject` 与 `VolumeField` 资源绑定 +- descriptor set 与 pipeline state 会按 shader pass、材质和 volume SRV 动态缓存 ## 当前执行流程 -1. `Initialize(...)` / `EnsureInitialized(...)` 保证 device、backend 与 builtin cube mesh 就绪。 -2. `Execute(...)` 校验 `RenderContext`、颜色附件、深度附件和 render area。 -3. 遍历 `sceneData.visibleVolumes`。 -4. 每项调用 `DrawVisibleVolume(...)`: - - 通过 `ResolveVolumeShaderPass(...)` 选择兼容的 volumetric shader pass - - 通过 `GetOrCreatePassResourceLayout(...)` 创建或复用 pipeline layout - - 通过 `GetOrCreatePipelineState(...)` 创建或复用 graphics pipeline - - 通过 `RenderResourceCache` 获取 cube mesh 与 `VolumeField` 的 GPU 视图 - - 组装 `PerObjectConstants` 与 `LightingConstants` - - 写 descriptor set 并提交 draw call +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 -## 关键资源约束 +## 关键内部状态 -- 需要单一颜色附件和有效深度附件。 -- `BuiltinPassResourceBindingPlan` 里必须至少存在: - - `PerObject` - - `VolumeField` -- 若 shader pass 还声明了 `Material`,则材质必须能提供有效的 schema constant payload。 -- 体积资源当前必须是 `NanoVDB`,否则该条目会被跳过。 - -## 当前缓存层 - -类内部当前维护三类缓存: - -- `m_passResourceLayouts` - - 以 `shader + passName` 为键缓存 pipeline layout 与 binding metadata -- `m_pipelineStates` - - 以 render state、shader、keyword signature、render target format 等为键缓存 pipeline state -- `m_dynamicDescriptorSets` - - 以 pass-layout、set、objectId、material、volumeField 为键缓存动态 descriptor set +| 状态 | 说明 | +|------|------| +| `m_builtinCubeMesh` | 所有体积绘制共用的 cube proxy mesh | +| `m_resourceCache` | 复用 mesh 与 volume GPU 资源 | +| `m_passResourceLayouts` | 按 shader/pass 缓存资源布局 | +| `m_pipelineStates` | 按 render state、shader、格式与 keyword 签名缓存 pipeline | +| `m_dynamicDescriptorSets` | 按对象、材质、volume field 缓存动态描述符集 | ## 当前实现边界 -- pass 本身不负责 scene extraction,也不负责决定 `visibleVolumes` 的排序策略。 -- 当前代理几何固定为 builtin cube,而不是从体数据本身生成裁剪几何。 -- 当前 lighting constants 只消费主方向光。 -- 资源清理通过 `Shutdown()` / 析构集中处理。 +- 只处理 `VisibleVolumeItem` +- 只接受 `VolumeStorageKind::NanoVDB` +- 当前要求 surface 为“单颜色附件 + 深度附件”模型 +- 若 shader pass 未声明 `PerObject` 或 `VolumeField` 绑定,会直接失败而不是做 legacy fallback ## 公开方法 | 方法 | 说明 | |------|------| -| [BuildInputLayout](BuildInputLayout.md) | 构建当前体积 pass 使用的顶点布局。 | -| [GetName](GetName.md) | 返回 pass 名称。 | -| [Initialize](Initialize.md) | 预热 device/backend 相关资源。 | -| [Execute](Execute.md) | 遍历 `visibleVolumes` 并提交绘制。 | -| [Shutdown](Shutdown.md) | 销毁缓存的管线、descriptor 与资源状态。 | +| [BuildInputLayout](BuildInputLayout.md) | 返回体积 pass 使用的顶点布局 | +| [GetName](GetName.md) | 返回 pass 名称 | +| [Initialize](Initialize.md) | 预热 builtin cube mesh 等资源 | +| [Execute](Execute.md) | 绘制所有可见体积 | +| [Shutdown](Shutdown.md) | 销毁缓存的 RHI 资源 | ## 相关文档 diff --git a/docs/api/XCEngine/Rendering/Passes/BuiltinVolumetricPass/Execute.md b/docs/api/XCEngine/Rendering/Passes/BuiltinVolumetricPass/Execute.md index b85eaa44..7cc1bc0a 100644 --- a/docs/api/XCEngine/Rendering/Passes/BuiltinVolumetricPass/Execute.md +++ b/docs/api/XCEngine/Rendering/Passes/BuiltinVolumetricPass/Execute.md @@ -1,31 +1,24 @@ # BuiltinVolumetricPass::Execute -**命名空间**: `XCEngine::Rendering::Passes` - -**类型**: `method` - -**头文件**: `XCEngine/Rendering/Passes/BuiltinVolumetricPass.h` - -## 签名 - ```cpp bool Execute(const RenderPassContext& context) override; ``` -## 作用 +把 `context.sceneData.visibleVolumes` 中的体积绘制到当前 render target。 -遍历 `visibleVolumes`,为每个可见体积提交一次 volumetric draw。 +## 当前实现流程 -## 当前行为 +1. 校验 `renderContext` +2. 若 `visibleVolumes` 为空,直接返回 `true` +3. 要求 surface 具备单颜色附件、深度附件和有效 render area +4. 设置 viewport、scissor 和 triangle-list topology +5. 逐个调用内部 `DrawVisibleVolume(...)` -- `renderContext` 无效时返回 `false`。 -- `visibleVolumes` 为空时直接返回 `true`,表示“没有工作但不算失败”。 -- 要求: - - 单一颜色附件 - - 非空深度附件 - - 正常的 `renderArea` -- 会设置 render target、viewport、scissor 和三角形拓扑。 -- 最终逐项调用内部 `DrawVisibleVolume(...)`。 +## 关键语义 + +- 这里不负责 scene extraction;输入必须已经是 `VisibleVolumeItem` +- 体积绘制依赖材质 shader pass 与 volume SRV 都已可用 +- 某个体积绘制失败不会自动切换为其他 shader 或 fallback path ## 相关文档 diff --git a/docs/api/XCEngine/Rendering/Passes/BuiltinVolumetricPass/GetName.md b/docs/api/XCEngine/Rendering/Passes/BuiltinVolumetricPass/GetName.md index 40ee292e..cd8c748b 100644 --- a/docs/api/XCEngine/Rendering/Passes/BuiltinVolumetricPass/GetName.md +++ b/docs/api/XCEngine/Rendering/Passes/BuiltinVolumetricPass/GetName.md @@ -1,24 +1,10 @@ # BuiltinVolumetricPass::GetName -**命名空间**: `XCEngine::Rendering::Passes` - -**类型**: `method` - -**头文件**: `XCEngine/Rendering/Passes/BuiltinVolumetricPass.h` - -## 签名 - ```cpp const char* GetName() const override; ``` -## 作用 - -返回当前 pass 的稳定名称。 - -## 当前行为 - -- 固定返回 `"BuiltinVolumetricPass"`。 +返回固定名称 `BuiltinVolumetricPass`。 ## 相关文档 diff --git a/docs/api/XCEngine/Rendering/Passes/BuiltinVolumetricPass/Initialize.md b/docs/api/XCEngine/Rendering/Passes/BuiltinVolumetricPass/Initialize.md index 23372b7d..4218d9e8 100644 --- a/docs/api/XCEngine/Rendering/Passes/BuiltinVolumetricPass/Initialize.md +++ b/docs/api/XCEngine/Rendering/Passes/BuiltinVolumetricPass/Initialize.md @@ -1,28 +1,18 @@ # BuiltinVolumetricPass::Initialize -**命名空间**: `XCEngine::Rendering::Passes` - -**类型**: `method` - -**头文件**: `XCEngine/Rendering/Passes/BuiltinVolumetricPass.h` - -## 签名 - ```cpp bool Initialize(const RenderContext& context) override; ``` -## 作用 - -预热当前 device/backend 相关资源。 +预热体积 pass 依赖的基础资源。 ## 当前行为 -- 直接转发到内部 `EnsureInitialized(context)`。 -- 若 device/backend 变化,旧缓存会先被 `DestroyResources()` 清掉,再重新创建。 -- 当前初始化阶段最关键的资源是 builtin cube mesh。 +- 实际入口会转到内部 `EnsureInitialized(...)` +- 当前最关键的初始化工作是加载 builtin cube mesh +- 若 `RenderContext` 无效或 cube mesh 加载失败,返回 `false` ## 相关文档 - [BuiltinVolumetricPass](BuiltinVolumetricPass.md) -- [Shutdown](Shutdown.md) +- [Execute](Execute.md) diff --git a/docs/api/XCEngine/Rendering/Passes/BuiltinVolumetricPass/Shutdown.md b/docs/api/XCEngine/Rendering/Passes/BuiltinVolumetricPass/Shutdown.md index ee6334f3..67dd5080 100644 --- a/docs/api/XCEngine/Rendering/Passes/BuiltinVolumetricPass/Shutdown.md +++ b/docs/api/XCEngine/Rendering/Passes/BuiltinVolumetricPass/Shutdown.md @@ -1,33 +1,19 @@ # BuiltinVolumetricPass::Shutdown -**命名空间**: `XCEngine::Rendering::Passes` - -**类型**: `method` - -**头文件**: `XCEngine/Rendering/Passes/BuiltinVolumetricPass.h` - -## 签名 - ```cpp void Shutdown() override; ``` -## 作用 - -销毁 `BuiltinVolumetricPass` 当前持有的缓存资源。 +销毁体积 pass 缓存的 GPU 资源与运行时状态。 ## 当前行为 -- 转发到 `DestroyResources()`。 -- 会清理: - - `RenderResourceCache` - - 所有 pipeline state - - 所有动态 descriptor set - - 所有 pass resource layout - - builtin cube mesh 句柄 -- 最后把 device/backend 状态恢复到初始值。 +- 关闭 `RenderResourceCache` +- 释放缓存的 pipeline state +- 释放动态 descriptor set 与 pool +- 释放按 shader pass 建立的 pipeline layout / set layout 元数据 +- 清空 builtin cube mesh 句柄 ## 相关文档 - [BuiltinVolumetricPass](BuiltinVolumetricPass.md) -- [Initialize](Initialize.md) diff --git a/docs/api/XCEngine/Resources/Volume/Volume.md b/docs/api/XCEngine/Resources/Volume/Volume.md index efc3f58f..d8e25d70 100644 --- a/docs/api/XCEngine/Resources/Volume/Volume.md +++ b/docs/api/XCEngine/Resources/Volume/Volume.md @@ -4,25 +4,20 @@ **类型**: `submodule` -**描述**: 体积资源子模块,承载 `VolumeField` 运行时资源对象与 `VolumeFieldLoader` 的 `.nvdb` / `.xcvol` 加载链路。 +**描述**: 体积资源子模块,覆盖体积 payload 运行时资源与对应的 loader。 -## 概览 +## 概述 -该目录与 `XCEngine/Resources/Volume` 对应的 public headers 保持平行,用于承载唯一的 canonical API 文档入口。 +`Resources::Volume` 当前是 NanoVDB 体积资源进入资源系统与渲染系统的汇合点。按当前实现,主链路是: -当前 `Resources/Volume` 这条链路主要覆盖两件事: - -- [VolumeField](VolumeField/VolumeField.md) - - 运行时体积资源对象,保存 payload、边界、体素尺寸和 grid 元数据。 -- [VolumeFieldLoader](VolumeFieldLoader/VolumeFieldLoader.md) - - 负责 source `.nvdb` 与 artifact `.xcvol` 的加载。 - -## 当前主链路 - -1. 项目里的 `.nvdb` 体积文件通过 `VolumeFieldLoader` 读取。 -2. `AssetDatabase` 会把可复用的导入结果写成 `.xcvol` artifact。 -3. 运行时或编辑器通过 `ResourceManager` 加载 `VolumeField`。 -4. 渲染侧再通过 `RenderResourceCache` 把 `VolumeField` payload 上传成 GPU 可读结构化缓冲。 +1. `VolumeFieldLoader` + - 读取 `.nvdb` 源文件或 `.xcvol` artifact +2. `VolumeField` + - 保存体积 payload 与边界元数据 +3. `VolumeRendererComponent` + - 把资源挂到场景对象 +4. `RenderSceneExtractor` / `BuiltinVolumetricPass` + - 提取并绘制体积对象 ## 头文件 @@ -31,8 +26,6 @@ ## 相关文档 -- [AssetDatabase](../../Core/Asset/AssetDatabase/AssetDatabase.md) -- [ArtifactFormats](../../Core/Asset/ArtifactFormats/ArtifactFormats.md) -- [RenderResourceCache](../../Rendering/RenderResourceCache/RenderResourceCache.md) -- [上级目录](../Resources.md) -- [API 总索引](../../../main.md) +- [Resources](../Resources.md) +- [VolumeRendererComponent](../../Components/VolumeRendererComponent/VolumeRendererComponent.md) +- [BuiltinVolumetricPass](../../Rendering/Passes/BuiltinVolumetricPass/BuiltinVolumetricPass.md) diff --git a/docs/api/XCEngine/Resources/Volume/VolumeField/VolumeField.md b/docs/api/XCEngine/Resources/Volume/VolumeField/VolumeField.md index 977d3c29..5044ca5f 100644 --- a/docs/api/XCEngine/Resources/Volume/VolumeField/VolumeField.md +++ b/docs/api/XCEngine/Resources/Volume/VolumeField/VolumeField.md @@ -2,66 +2,63 @@ **命名空间**: `XCEngine::Resources` -**类型**: `enum + struct + class` +**类型**: `class` **头文件**: `XCEngine/Resources/Volume/VolumeField.h` **源文件**: `engine/src/Resources/Volume/VolumeField.cpp` -**描述**: 体积资源对象,保存体积 payload、包围盒、体素尺寸、index bounds 与 grid 元数据,供资源系统、资产导入链路和体积渲染 pass 共同消费。 +**描述**: 体积 payload 的运行时资源对象,保存存储类型、包围盒、体素尺寸、索引边界和原始字节载荷。 -## 声明概览 +## 概述 -| 声明 | 类型 | 说明 | -|------|------|------| -| `VolumeStorageKind` | `enum class` | 当前体积 payload 的存储格式,现阶段主要是 `NanoVDB`。 | -| `VolumeIndexBounds` | `struct` | 体素索引空间的最小/最大坐标范围,并提供 `==` / `!=`。 | -| `VolumeField` | `class` | 运行时体积资源对象。 | +`VolumeField` 是当前体积资源在运行时的最小封装。它并不解析体积体素内容,而是把 loader 导入的 payload 和元数据原样保存下来,供后续: -## 当前资源模型 +- 场景组件绑定 +- artifact 重建 +- `RenderResourceCache` 上传 structured-buffer -`VolumeField` 继承 `IResource`,因此同时具备两层信息: +使用。 -- 资源身份 - - `name` - - `path` - - `guid` - - `memorySize` -- 体积内容 - - `storageKind` - - `bounds` - - `voxelSize` - - `indexBounds` - - `gridType` - - `gridClass` - - 原始 payload +## 当前状态模型 -这意味着它不是“只给渲染器看的裸 payload 缓冲”,而是资源系统可缓存、可导入、可按 `AssetRef` 恢复的正式资源对象。 +| 字段 | 说明 | +|------|------| +| `m_storageKind` | 当前体积存储类型,现阶段主要是 `NanoVDB` | +| `m_bounds` | 体积世界/局部包围盒 | +| `m_voxelSize` | 体素尺寸 | +| `m_indexBounds` | 体素索引空间边界 | +| `m_gridType` / `m_gridClass` | NanoVDB metadata 的轻量转存 | +| `m_payload` | 原始 payload 字节数组 | -## 创建与读取语义 +## 当前实现行为 -- `Create(...)` 要求 `payload != nullptr` 且 `payloadSize > 0`,否则直接失败。 -- 创建成功后会拷贝整份 payload,而不是只保存外部指针。 -- `GetWorldBounds()` 当前直接返回 `m_bounds`,尚未引入独立的局部/世界体积边界变换语义。 -- `GetPayloadData()` / `GetPayloadSize()` 暴露的是当前缓存 payload,用于后续 GPU 上传。 - -## 当前实现边界 - -- 当前正式声明的存储格式只有 `Unknown` 与 `NanoVDB`。 -- `VolumeField` 自身不负责解析 `.nvdb` 文件格式;格式解析由 [VolumeFieldLoader](../VolumeFieldLoader/VolumeFieldLoader.md) 完成。 -- 运行时 `memorySize` 由 `UpdateMemorySize()` 基于对象本体、资源身份字符串和 payload 大小估算。 +- `Create(...)` + - `payload == nullptr` 或 `payloadSize == 0` 时直接失败 + - 成功时会复制整份 payload,而不是借用外部内存 + - 会写入边界、体素尺寸、索引边界与 grid metadata + - 成功后把资源标记为 valid,并更新 `memorySize` +- `GetWorldBounds()` 当前只是 `GetBounds()` 的别名 +- `Release()` 当前直接执行 `delete this` ## 测试与调用链 - `tests/Resources/Volume/test_volume_field.cpp` - - 覆盖 `Create(...)` 对 payload、bounds、voxelSize、indexBounds、gridType、gridClass 的保留行为。 + - 覆盖 payload 拷贝、边界元数据与 `GetMemorySize()` +- `engine/src/Core/Asset/AssetDatabase.cpp` + - 当前会把本资源写回 `.xcvol` artifact - `engine/src/Rendering/Caches/RenderResourceCache.cpp` - - 当前会读取 payload 并把它上传成 GPU 结构化缓冲。 -- [BuiltinVolumetricPass](../../../Rendering/Passes/BuiltinVolumetricPass/BuiltinVolumetricPass.md) - - 通过 `RenderResourceCache` 消费 `VolumeField`。 + - 当前把 payload 上传成体积 structured-buffer + +## 当前实现边界 + +- 当前只保存 payload,不提供体素级查询 API。 +- `Create(...)` 是一次性初始化入口,没有增量修改协议。 +- `GetWorldBounds()` 尚未引入独立于 `GetBounds()` 的额外变换语义。 ## 相关文档 - [Volume](../Volume.md) - [VolumeFieldLoader](../VolumeFieldLoader/VolumeFieldLoader.md) -- [RenderResourceCache](../../../Rendering/RenderResourceCache/RenderResourceCache.md) +- [VolumeRendererComponent](../../../Components/VolumeRendererComponent/VolumeRendererComponent.md) +- [BuiltinVolumetricPass](../../../Rendering/Passes/BuiltinVolumetricPass/BuiltinVolumetricPass.md) diff --git a/docs/api/XCEngine/Resources/Volume/VolumeFieldLoader/VolumeFieldLoader.md b/docs/api/XCEngine/Resources/Volume/VolumeFieldLoader/VolumeFieldLoader.md index a65ab333..5554afb6 100644 --- a/docs/api/XCEngine/Resources/Volume/VolumeFieldLoader/VolumeFieldLoader.md +++ b/docs/api/XCEngine/Resources/Volume/VolumeFieldLoader/VolumeFieldLoader.md @@ -6,60 +6,89 @@ **头文件**: `XCEngine/Resources/Volume/VolumeFieldLoader.h` -**源文件**: `engine/src/Resources/Volume/VolumeFieldLoader.cpp` +**描述**: `VolumeField` 的资源 loader,负责识别 `.nvdb` 与 `.xcvol`,并把体积文件转换成运行时 `VolumeField` 资源。 -**描述**: `VolumeField` 资源加载器,负责识别 source `.nvdb` 与 artifact `.xcvol` 路径,并把它们统一转换成 `VolumeField` 资源对象。 +## 概述 -## 概览 +`VolumeFieldLoader` 继承自 `IResourceLoader`,是当前体积资源进入 `ResourceManager` 的标准入口。它支持两类输入: -`VolumeFieldLoader` 当前承载两条正式加载路径: +- `.xcvol` + - 由 `AssetDatabase` 产出的正式 artifact +- `.nvdb` + - 原始 NanoVDB 源文件 -1. `.xcvol` - - 读取引擎自己的体积 artifact 格式。 -2. `.nvdb` - - 在启用 `XCENGINE_HAS_NANOVDB` 时直接读取 NanoVDB source 文件。 +## 当前实现行为 -因此它既是运行时加载器,也是 `AssetDatabase` 体积导入链路的核心入口。 +### 扩展名与资源类型 -## 当前加载模型 +- `GetResourceType()` 固定返回 `ResourceType::VolumeField` +- `GetSupportedExtensions()` 当前返回: + - `nvdb` + - `xcvol` +- `CanLoad(...)` 只接受这两种扩展名 -- `GetSupportedExtensions()` 当前返回 `nvdb` 和 `xcvol`。 -- `CanLoad(...)` 只按扩展名判定,不预先验证文件存在。 -- 相对路径会先尝试当前路径;若不存在,再回退到 `ResourceManager::Get().GetResourceRoot()`。 -- `.xcvol` 路径会读取 `VolumeFieldArtifactHeader`,要求: - - `magic == "XCVOL02"` - - schema 版本匹配 - - `payloadSize > 0` -- `.nvdb` 路径在支持 NanoVDB 时会读取 grid metadata,并回填: - - `bounds` +### `.xcvol` artifact + +加载 `.xcvol` 时,当前实现会: + +1. 解析真实路径,必要时拼接 `ResourceManager::Get().GetResourceRoot()` +2. 读取 `VolumeFieldArtifactHeader` +3. 校验: + - `magic == "XCVOL02"` + - `schemaVersion == kVolumeFieldArtifactSchemaVersion` + - `payloadSize > 0` +4. 读取 payload 与体积元数据 +5. 构造 `VolumeField` + +### `.nvdb` 源文件 + +只有在定义 `XCENGINE_HAS_NANOVDB` 时,当前 loader 才支持直接加载 `.nvdb` 源文件。成功时会: + +- 通过 `nanovdb::io::readGrid(...)` 读取 grid payload +- 从 `GridMetaData` 中提取: + - `worldBBox` - `voxelSize` - - `indexBounds` + - `indexBBox` - `gridType` - `gridClass` +- 构造 `VolumeField` + +如果当前构建未启用 NanoVDB,则 `.nvdb` 会返回失败结果,而不是静默降级。 + +### 默认设置与注册 + +- `GetDefaultSettings()` 当前返回 `nullptr` +- 文件末尾通过 `REGISTER_RESOURCE_LOADER(VolumeFieldLoader)` 注册到资源系统 + +## 测试与调用链 + +- `tests/Resources/Volume/test_volume_field_loader.cpp` + - 覆盖扩展名识别 + - 覆盖源 `.nvdb` 读取 + - 覆盖 `AssetDatabase` 产出 `.xcvol` 后的复用 + - 覆盖 `ResourceManager` 按 `AssetRef` 加载体积资源 +- `engine/src/Core/Asset/AssetDatabase.cpp` + - 当前使用本 loader 导入体积资产并生成 artifact ## 当前实现边界 -- 未启用 `XCENGINE_HAS_NANOVDB` 时,source `.nvdb` 会返回 `NanoVDB source-file support is unavailable in this build`。 -- `GetDefaultSettings()` 当前固定返回 `nullptr`,说明这条导入链路暂时没有独立的 volume import settings 对象。 -- 当前 loader 通过 `REGISTER_RESOURCE_LOADER(VolumeFieldLoader)` 注册到资源系统。 +- `.nvdb` 源文件直读依赖编译期开关 `XCENGINE_HAS_NANOVDB`。 +- 当前没有单独的导入设置对象;所有默认行为都在 loader 内硬编码。 +- `.xcvol` header 不通过时会直接失败,不做向后兼容解析。 -## 测试与真实调用点 +## 公开接口 -- `tests/Resources/Volume/test_volume_field_loader.cpp` - - 覆盖 `GetResourceType` - - 覆盖 `CanLoad` - - 覆盖无效路径加载 - - 覆盖直接读取 NanoVDB source payload - - 覆盖 `AssetDatabase` 生成与复用 `.xcvol` artifact - - 覆盖按 `AssetRef` 回读项目体积资源 -- `engine/src/Core/Asset/AssetDatabase.cpp` - - 当前通过 `VolumeFieldLoader` 导入项目体积资源并写出 `.xcvol` -- `engine/src/Core/Asset/ResourceManager.cpp` - - 当前会注册这条 loader +| 接口 | 作用 | +|------|------| +| `VolumeFieldLoader()` / `~VolumeFieldLoader()` | 创建 / 销毁 loader | +| `GetResourceType()` | 返回 `ResourceType::VolumeField` | +| `GetSupportedExtensions()` | 声明 `nvdb` / `xcvol` | +| `CanLoad(...)` | 判断路径是否可由当前 loader 处理 | +| `Load(...)` | 加载 `.nvdb` 或 `.xcvol` | +| `GetDefaultSettings()` | 当前固定返回 `nullptr` | ## 相关文档 - [Volume](../Volume.md) - [VolumeField](../VolumeField/VolumeField.md) -- [AssetDatabase](../../../Core/Asset/AssetDatabase/AssetDatabase.md) -- [ResourceManager](../../../Core/Asset/ResourceManager/ResourceManager.md) +- [Resources](../../Resources.md)