【免费下载链接】mesh2splat
Fast mesh to 3D gaussian splat conversion
Mesh2Splat 是一款可将 3D 网格(Mesh)在亚毫秒级转换为 3D Gaussian Splatting(3DGS)模型的高性能开源工具,并自带一个功能完整的 3DGS 渲染器。这套渲染器的核心是一条由8 大 RenderPass 协同工作的 GPU 渲染管线:从毫秒级网格转 3DGS、深度预渲染、GPU 预筛选、RadixSort 深度排序,到最终的高斯实例化绘制、实时阴影与延迟光照。本文将逐个拆解这 8 个 RenderPass 的职责、依赖关系和数据流,带你完整看懂这条管线的协作机制。
🗺️ 渲染管线全景:8 大 RenderPass 的执行顺序
整个管线的"总调度台"在 renderer.cpp 中:Renderer::initialize()会注册全部 8 个 Pass,并按固定顺序存入renderPassesOrder;每帧renderFrame()遍历该顺序,只执行被 UI 启用的 Pass(Pass 默认关闭,按需开启),同时用GL_TIME_ELPASSED查询池异步统计 GPU 帧耗时。
| 顺序 | Pass 类名 | 内部标识 | 核心职责 |
|---|---|---|---|
| 1 | ConversionPass | conversion | Mesh → 3DGS 亚毫秒级转换 |
| 2 | DepthPrepass | depthPrepass | 网格深度预渲染,供高斯遮挡测试 |
| 3 | MeshRenderPass | meshRender | 渲染网格 GBuffer(分屏对比用) |
| 4 | GaussiansPrepass | gaussianPrepass | 高斯预筛选与屏幕空间投影 |
| 5 | RadixSortPass | radixSort | 按深度的基数排序 |
| 6 | GaussianSplattingPass | gaussianSplatting | 高斯四边形实例化绘制(写 GBuffer) |
| 7 | GaussianShadowPass | gaussianSplattingShadows | 点光源 360° 阴影立方体贴图 |
| 8 | GaussianRelightingPass | gaussianSplattingDeferredLighting | 全屏延迟 PBR 光照与合成 |
Pass 的启停逻辑由 UI 层 guiRendererConcreteMediator.cpp 控制:点击"Convert Mesh to 3DGS"时启用转换+排序+绘制链路;开启光照时追加阴影 Pass;需要网格深度测试或分屏对比时才启用前两个 Pass。这种"按需执行"的设计让每个 Pass 都可以独立开关,也方便学习时单独调试。
⚡ ConversionPass:亚毫秒级 Mesh 转 3DGS 的核心
ConversionPass.cpp 是整个项目的灵魂。它完全绕开了经典 3DGS 的"渲染数据集→离线优化"流程,直接复用 GPU 光栅化器的硬件插值器:
- VS → GS:几何着色器按三角形做三平面正交投影(Triplanar),计算每个三角形的 Jacobian 矩阵,得到 3D 高斯的 Scale 与 Rotation;
- 光栅化插值:把归一化 UV 编码进
gl_Position,让光栅化器在正交空间逐片元插值,一个片元 = 一个 3D 高斯; - PS:采样 Albedo / Normal / Metallic-Roughness 贴图,每个片元通过原子操作向共享 SSBO(
gaussianBuffer)追加一个高斯; - 转换结束
glFinish()同步后读回原子计数器,得到高斯总数,全程平均 < 0.5ms。
转换容量上限为resolutionTarget² × 6 × 网格数,并受 RenderPass.hpp 中MAX_GAUSSIANS_TO_SORT = 7000000的硬顶约束——这也是下游排序缓冲的统一容量。
下图是实际运行效果:点击 Convert 后,左侧界面即可看到高斯数量与帧时间统计。
🧱 DepthPrepass + MeshRenderPass:深度与 GBuffer 双准备
- DepthPrepass.cpp:只绘制不透明网格(
baseColorFactor.a == 1.0),把深度写入独立depthFBO。这份深度纹理随后交给 GaussiansPrepass 做"网格遮挡高斯"的剔除测试,可显著减少无效高斯数量; - MeshRenderPass.cpp:把网格的 PBR 属性(世界坐标、法线、Albedo、深度、Metallic-Roughness)写入 5 个 Color Attachment 的
meshGBufferFBO,供最终 Pass 做分屏对比(左网格 / 右高斯)使用。
这两个 Pass 是可选的"增强项",它们不产生画面,而是为后续 Pass 提供深度数据与对比基准。
🔍 GaussiansPrepass:GPU 预筛选与屏幕空间投影
GaussiansPrepass.cpp 是一个 Compute Shader(每组 256 线程、近似正方形网格分发):
- 对每个高斯做视锥裁剪与深度遮挡测试(读取上面生成的
meshDepthTexture); - 把通过筛选的高斯投影到屏幕空间,计算每个高斯四边形的变换矩阵,写入
perQuadTransformationsBuffer; - 用原子计数器累加"可见高斯数"(validCount),这个计数值会一路传递给后续 Pass,避免全量遍历 700 万个高斯。
这一步是性能关键:排序与绘制阶段只处理真正可见的高斯子集。
🔢 RadixSortPass:三步走完成深度排序
高斯混合要求从远到近绘制,RadixSortPass.cpp 用经典三阶段完成 GPU 排序:
| 阶段 | 函数 | 作用 |
|---|---|---|
| ① 计算 Key | computeKeyValuesPre | 把高斯深度编码成排序 Key,写入keysBuffer/valuesBuffer |
| ② 基数排序 | sort | 调用 RadixSort.hpp 中的glu::RadixSort(LSB 基数排序,内部自动同步) |
| ③ 收集结果 | gatherPost | 按排序后的索引重排四边形变换到perQuadTransformationBufferSorted,并把实例数写进drawIndirectBuffer |
最后一步写好的间接绘制命令(instanceCount)正是下一个 Pass 一次 Draw Call 绘制百万高斯的秘密武器。
🎨 GaussianSplattingPass:实例化绘制与 Front-to-Back 混合
GaussianSplattingPass.cpp 是画面的"生产者":
- 用一个全屏四边形 VAO + 逐实例属性(divisor = 1)+
glDrawElementsIndirect,单次 Draw Call画完所有排序后的高斯四边形; - 采用 Front-to-Back 顺序配合混合函数
GL_ONE_MINUS_DST_ALPHA, GL_ONE(预乘 Alpha),近处像素算完即可提前剔除远处像素; - 结果不直接输出颜色,而是写入 5 通道的
gBufferFBO(位置/法线/Albedo/深度/Metallic-Roughness)——为延迟光照做准备; - 调试彩蛋:切到overdraw模式时混合函数变为
GL_ONE, GL_ONE,可以直观看到重叠绘制次数。
💡 GaussianShadowPass + GaussianRelightingPass:实时光照与延迟着色
最后两个 Pass 让 3DGS 具备了传统渲染器才有的可重光照(Relightability):
1. GaussianShadowPass.cpp —— 360° 点光源阴影
- 以点光源为中心构建 6 个
glm::lookAt视角,配合 90° 透视投影; - 先用 Compute 预筛选出落入各立方体面视锥的高斯,再把每面高斯变换写入统一缓冲;
- 循环 6 次间接绘制,生成 6×1024² 的深度阴影立方体贴图(shadow cubemap)。
2. GaussianRelightingPass.cpp —— 全屏延迟光照
- 绘制全屏四边形,从
gBufferFBO读取 PBR 属性,结合点光源参数与阴影立方体贴图,在片元着色器里完成 PBR 光照计算; - 开启分屏对比时,巧妙用Stencil 缓冲区分区:左半屏采样网格 GBuffer、右半屏采样高斯 GBuffer,再用 Scissor 画一条白色分割线,实现"网格 vs 高斯"的同屏 PBR 对比。
🔗 数据流总览:共享 Buffer 串起整条管线
8 个 Pass 并非孤立运行,它们通过 RenderContext.hpp 定义的一组共享 GPU 缓冲接力传递数据:
| 共享资源 | 生产者 → 消费者 | 说明 |
|---|---|---|
gaussianBuffer(SSBO) | Conversion → Prepass/Shadow | 全部高斯的原始数据 |
keysBuffer/valuesBuffer | Prepass → RadixSort | 深度 Key 与索引 Value |
perQuadTransformation…Sorted | RadixSort → Splatting | 排序后的逐实例变换 |
drawIndirectBuffer | RadixSort → Splatting | 间接绘制的实例数 |
atomicCounterBuffer | Prepass → RadixSort | 可见高斯计数(validCount) |
meshDepthTexture | DepthPrepass → Prepass | 网格遮挡测试 |
gBufferFBO/meshGBufferFBO | Splatting/MeshRender → Relighting | PBR 延迟光照输入 |
| 阴影立方体贴图 | Shadow → Relighting | 360° 阴影采样 |
可以看到一条清晰的主线:转换产出数据 → 预筛选缩小范围 → 排序确定顺序 → 一次绘制生成 GBuffer → 光照合成画面,每个 Pass 只做一件事,职责单一、边界清晰。
📁 关键源码文件速查
- 管线调度:renderer.cpp、RenderPasses.hpp
- 8 个 Pass 实现:src/renderer/renderPasses/
- GPU 基数排序:RadixSort.hpp
- 转换核心着色器:converterGS.glsl、converterPS.glsl
- 高斯预筛选着色器:gaussianSplattingPrepassCS.glsl
- 延迟光照着色器:gaussianSplattingDeferredPS.glsl
- 排序着色器:radixSortPrepass.glsl、radixSortGather.glsl
- 项目总览与数学原理:README.md
总结:Mesh2Splat 的渲染管线把"转换"和"渲染"两条链路统一在 8 个职责单一的 RenderPass 中——ConversionPass 用硬件插值器实现亚毫秒转换,Prepass + RadixSort 用"先筛选后排序"控制规模,Splatting Pass 用单次间接绘制 + Front-to-Back 混合保证帧率,最后的 Shadow + Relighting 两个 Pass 则赋予 3DGS 实时 PBR 光照能力。理解了这条管线,你也就掌握了现代 3D Gaussian Splatting 渲染器的通用设计范式。
【免费下载链接】mesh2splat
Fast mesh to 3D gaussian splat conversion
相关推荐
Vulkano渲染流程:RenderPass和Framebuffer深度解析
Vulkano渲染流程:RenderPass和Framebuffer深度解析 想要掌握Vulkano渲染技术?RenderPass和Framebuffer绝对是
图形学深度解析MemLab架构:六大模块如何协同工作
深度解析MemLab架构:六大模块如何协同工作 MemLab是一个端到端的JavaScript内存分析框架,专门用于检测内存泄漏和优化内存使用。通过六大核心模块
开发工具测试CLIMCP 服务Enriched Markdown架构深度解析:C++ md4c解析器、Fabric与跨平台渲染管线是如何工作的
Enriched Markdown架构深度解析:C++ md4c解析器、Fabric与跨平台渲染管线是如何工作的 Enriched Markdown 是一款多平
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考