Unity Virtual Mesh 解读

Unity Virtual Mesh 解读 它是什么 Unity Virtual Mesh 是 Unity Technologies 发布的实验性参考实现仓库,用来验证一种基于 triangle cluster / meshlet、memory page 流送和 GPU driven culling / LOD 的虚拟几何方案,而不是面向生产环境的成熟通用包。 关键依据: 仓库描述明确写明这是 “…


Unity Virtual Mesh 解读

它是什么

Unity Virtual Mesh 是 Unity Technologies 发布的实验性参考实现仓库,用来验证一种基于 triangle cluster / meshlet、memory page 流送和 GPU-driven culling / LOD 的虚拟几何方案,而不是面向生产环境的成熟通用包。

关键依据:

  • 仓库描述明确写明这是 “a GPU-driven pipeline that supports triangle cluster LODs and two-pass occlusion culling at a triangle level” https://github.com/Unity-Technologies/com.unity.virtualmesh
  • Runtime 的核心入口是 Runtime/VirtualMeshManager.cs,文档直接说明它负责 Unity game loop 中 virtual mesh system 的处理与 runtime buffer 持有。Documentation~/implementation.md:7
  • 渲染功能入口是 Runtime/RenderFeatures/VirtualMeshRenderFeature.cs,文档说明它负责插入 rendering pipeline 的自定义 pass,并构成 GPU-driven pipeline。Documentation~/implementation.md:9-11

核心结论

1. 它不是“整物体 LOD 包”,而是 cluster / group / page 驱动的几何系统

术语文档直接定义:

  • Cluster / meshlet:最大 64 triangles 的固定几何块。Documentation~/glossary.md:13-15
  • Cluster group:一组带父子层级关系的 clusters,共享包围盒,用于 occlusion culling。Documentation~/glossary.md:17-19
  • Memory page:若干 cluster groups 的磁盘序列化单元,按屏幕投影大小决定流送优先级。Documentation~/glossary.md:21-23
  • Upload buffer:页面数据从磁盘到 GPU 的中转缓冲,最终再写入 page slot。Documentation~/glossary.md:29-31

2. 它的核心思想是“离线重构 + 运行时按需驻留”

编辑期不是直接使用原始 mesh,而是先:

  • spatial sort triangles Documentation~/implementation.md:69-73
  • build meshlets Documentation~/implementation.md:71-73
  • partition meshlets 形成 leaf cluster groups Documentation~/implementation.md:73-75
  • 递归 simplify + re-cluster 生成 cluster hierarchy Documentation~/implementation.md:75-77
  • 将 group 装入 memory pages 并序列化为流送文件 Documentation~/implementation.md:77-81

源码对应实现:

  • meshlet 最大三角数和 page 常量定义在 Editor/VirtualMeshBakerAPI.cs:46-49
  • 实际 meshlet 构建在 Editor/VirtualMeshBakerAPI.cs:476-482
  • 分区在 Editor/VirtualMeshBakerAPI.cs:484-499

3. 运行时调度主线是“GPU 请求页面,CPU 负责流送,GPU 完成驻留后再剔除与绘制”

实现文档说明:

  • GPU 先做 culling / LOD 并决定需要哪些 pages。Documentation~/implementation.md:29-33
  • CPU 通过 RequestAsyncReadback 读取反馈,派发 jobs 做文件 I/O 和 streaming。Documentation~/implementation.md:31-35
  • 完成后通过 compute shader 把 upload buffer 拷贝到 runtime buffers。Documentation~/implementation.md:33

源码直接证据:

  • GPU 反馈回读入口:Runtime/VirtualMeshManager.cs:495 (FeedbackReadbackCallback)
  • Streaming loop 调度:Runtime/VirtualMeshManager.cs:612-613
  • header load job:Runtime/VirtualMeshManager.cs:195-197
  • page data load job:Runtime/VirtualMeshManager.cs:231-233

4. 这是明确的 GPU-driven 渲染,而不是 CPU 逐对象提交

源码注释明确说明 render feature 负责 “GPU-driven culling and LOD processing”。Runtime/RenderFeatures/VirtualMeshRenderFeature.cs:8-10

进一步证据:

  • first pass / second pass 的 two-pass occlusion culling 在 render feature 中有明确注释。Runtime/RenderFeatures/VirtualMeshRenderFeature.cs:229, Runtime/RenderFeatures/VirtualMeshRenderFeature.cs:571
  • 绘制采用 DrawProceduralIndirectRuntime/RenderFeatures/VirtualMeshRenderFeature.cs:161, Runtime/RenderFeatures/VirtualMeshRenderFeature.cs:296, Runtime/RenderFeatures/VirtualMeshRenderFeature.cs:348, Runtime/RenderFeatures/VirtualMeshRenderFeature.cs:612
  • CPU 侧说明 draw 基于 post-culling compacted index buffer。Runtime/VirtualMeshManager.cs:618-620

5. “从对象驱动转向屏幕贡献驱动”在这个仓库里是有明确源码落点的

不是抽象理念,而是具体落在:

  • page priority 由页面包围盒投影大小和距离决定。Documentation~/implementation.md:40-50
  • LOD layer 选择基于 simplification error,并转为 screen-space error。Documentation~/implementation.md:83-87
  • GPU shader 中存在 page / cluster / triangle 三层 pass:
    • PageOcclusionPass Runtime/Shaders/DXCVisibilityPasses.compute:58
    • ClusterOcclusionPass Runtime/Shaders/DXCVisibilityPasses.compute:102
    • TriangleOcclusionPass Runtime/Shaders/DXCVisibilityPasses.compute:203

关键数据结构

  • Cluster triangle 上限:64。Editor/VirtualMeshBakerAPI.cs:46, Runtime/VirtualMeshManager.cs:108
  • Memory page 最大数量:256。Editor/VirtualMeshBakerAPI.cs:49, Runtime/VirtualMeshManager.cs:109
  • 单 page 最大 instance 数:1600。Editor/VirtualMeshBakerAPI.cs:48, Runtime/VirtualMeshManager.cs:111
  • PageData / VertexPosition / VertexAttribute / Index / GroupData / InstanceData / FeedbackBuffer 等 runtime buffer 都集中由 VirtualMeshManager 持有。Runtime/VirtualMeshManager.cs:364-426

快速上手(源码阅读顺序)

  1. 看总实现说明:
    • Documentation~/implementation.md
    • Documentation~/glossary.md
  2. 看编辑期几何烘焙:
    • Editor/VirtualMeshBakerAPI.cs
    • Editor/MeshOperations.cs
  3. 看运行时管理器:
    • Runtime/VirtualMeshManager.cs
  4. 看渲染管线整合:
    • Runtime/RenderFeatures/VirtualMeshRenderFeature.cs
  5. 看 GPU pass:
    • Runtime/Shaders/DXCVisibilityPasses.compute
    • Runtime/Shaders/DepthPyramidPass.compute
    • Runtime/Shaders/CopyPasses.compute

适用场景

从当前实现可推断它适合:

  • 大量静态几何
  • 需要细粒度 LOD 与按需流送的场景
  • 希望把可见性决策更多下放给 GPU 的实验型渲染方案

依据:cluster/page 设计、GPU-driven pass、two-pass occlusion、AsyncGPUReadback 流送闭环。Documentation~/implementation.md:29-50, Runtime/RenderFeatures/VirtualMeshRenderFeature.cs:229-229, Runtime/RenderFeatures/VirtualMeshRenderFeature.cs:571-571

限制与定位

当前证据更支持把它定义为“实验性/参考实现”,而不是生产就绪方案:

  • 仓库位于 Unity-Technologies 官方公开仓库,但文档集中讨论的是实现路径与技术原理,没有给出生产稳定性承诺;现有公开定位更接近 implementation reference。主要依据是文档文件名和内容都在解释系统如何实现,而不是提供成熟产品使用手册:Documentation~/implementation.md, Documentation~/glossary.md
  • 多个关键常量是硬编码上限,例如 page 数 256、page instance 上限 1600、cluster triangle 上限 64。Editor/VirtualMeshBakerAPI.cs:46-49, Runtime/VirtualMeshManager.cs:108-111
  • LOD 投影误差依赖 baking 时相机 FOV,文档明确说 changing camera FOV requires a rebake。Documentation~/implementation.md:85-87

待确认问题

  • page feedback buffer 的完整位编码格式,本轮未完全展开;已确认 CPU 读回并驱动状态机,但若要写精确 bitfield 规范,仍需继续逐行追踪 FeedbackReadbackCallback 与 shader 写入逻辑。
  • 当前结论基于官方仓库源码与文档在线读取,未在本地 Unity 环境实际编译运行。

相关链接

一句话总结

Unity Virtual Mesh 的关键价值不只是“把模型切成 meshlet”,而是把几何数据重组织成 cluster group + memory page,并用 GPU-driven 的 page / cluster / triangle 多级剔除与按需流送,验证一种更接近“几何虚拟化”的渲染路线。