chore: checkpoint current workspace changes

This commit is contained in:
2026-04-11 22:14:02 +08:00
parent 3e55f8c204
commit 8848cfd958
227 changed files with 34027 additions and 6711 deletions

View File

@@ -0,0 +1,248 @@
# 3DGS 渲染路径对齐参考实现修复计划
日期2026-04-11
## 1. 文档定位
旧计划《3DGS渲染集成测试与Renderer正式接入计划》已经完成了主体接入工作
1. `GaussianSplat` 资源链路已经打通
2. `GaussianSplatRendererComponent` / `VisibleGaussianSplatItem` / `BuiltinGaussianSplatPass` 已经落地
3. `tests/Rendering/integration/gaussian_splat_scene` 已经建立
当前剩下的不是“是否接进 Renderer”而是“当前 Renderer 中的 3DGS 正式路径与参考实现仍有关键偏差,导致画面结果错误”。
因此这份新计划只聚焦当前的渲染正确性修复与测试收口,不再重复旧计划里已经完成的接入事项。
## 2. 已确认的根因
这轮问题已经不是相机摆放、PLY 导入或简单参数调节问题,而是渲染路径本身与参考实现不一致。
### 2.1 当前引擎缺少正式的 accumulation + composite 两段式路径
参考实现的关键流程是:
1. 先把 splat 绘制到单独的半浮点累积 RT
2. splat draw 使用前向累积专用 blend
3. 最后再把累积 RT composite 回主场景颜色缓冲
参考位置:
1. `mvs/3DGS-Unity/Shaders/RenderGaussianSplats.shader`
2. `mvs/3DGS-Unity/Shaders/GaussianComposite.shader`
3. `mvs/3DGS-Unity/Runtime/GaussianSplatRenderer.cs`
当前引擎却是:
1.`engine/assets/builtin/shaders/gaussian-splat.shader` 中直接输出到主场景颜色
2. `BuiltinGaussianSplatPass` 直接把 camera color attachment 作为 render target
3. 虽然 `BuiltinGaussianSplatPassResources` 已经有 `AccumulationSurface` 抽象,但执行路径没有真正使用它
这说明当前实现是“资源抽象已经开始正式化,但执行流仍停在临时路径上”,这是第一根因。
### 2.2 当前排序方向与当前 blend 方程不匹配
当前引擎:
1. `PrepareOrder` 阶段使用相机空间 `viewCenter.z` 作为排序距离
2. bitonic 结果本质上是按升序排列
3. draw shader 却使用普通透明混合 `Blend SrcAlpha OneMinusSrcAlpha`
如果保留当前普通透明混合,就应当使用严格的 back-to-front 语义;
如果要对齐参考实现的 front-to-back 累积,就必须同时切到参考的累积 blend 与独立 accumulation target。
也就是说,当前并不是“排序可能有一点不准”,而是“排序约定与 blend 合约本身冲突”。
### 2.3 当前测试参数只是在放大问题,不是问题本体
当前集成测试里:
1. 只取了 `65536` 个 splat 子集
2. `_PointScale = 3.0`
3. 最终输出直接落在主 backbuffer
这些会让错误更明显,但不会单独制造当前这种大面积拖影、糊片、黑色尖刺。
真正的问题仍然是 draw/composite 路径设计错误。
## 3. 本轮修复目标
本轮只做一件事:把当前引擎中的 3DGS 渲染主链,彻底对齐到参考实现所依赖的那组最小正确语义。
具体目标:
1. 建立正式的 accumulation render target
2. draw shader 改为服务 accumulation 的输出与 blend 合约
3. 新增正式的 composite pass把 accumulation 结果混回主场景
4. 统一排序方向与 blend 语义,不允许继续“排序一套、混合一套”
5. 保证 `gaussian_splat_scene` 在 D3D12 / Vulkan / OpenGL 三后端下都能稳定回归
## 4. 非目标
这轮明确不做:
1. 不接 editor 中的 3DGS 显示与交互
2. 不做 selection / cutout / 编辑工具链
3. 不做 3DGS 的 streaming / LOD / chunk 级高级优化
4. 不在这轮重做 `GaussianSplat` artifact schema
5. 不引入 compute shader 之外的新渲染架构分支
## 5. 执行原则
### 5.1 先对齐正确性,再谈进一步优化
这轮优先级必须是:
1. 先把“渲染方程”和“执行路径”对齐
2. 先让集成测试输出正确
3. 再考虑性能、压缩、子集规模、排序频率等问题
### 5.2 不允许继续保留半套正式化、半套临时方案
一旦正式启用 accumulation/composite就必须
1. 把 draw shader、pass 资源、pass 执行流一起接完整
2. 把当前直接画到 scene color 的临时路径清掉
3. 不保留两个语义不同但名字相同的渲染路线
### 5.3 修复必须由测试驱动收口
本轮所有核心改动都必须由以下验证闭环约束:
1. `gaussian_splat_scene` 的三后端输出
2. 中间调试图可视化检查
3. 现有 `GaussianSplat` 资源与缓存相关测试不回退
## 6. 分阶段计划
### Phase 1补齐 3DGS 中间结果观测面
目标:
1. 在不改渲染语义之前,先把中间状态可视化出来
任务:
1. 允许 `gaussian_splat_scene` 在调试模式下输出 accumulation RT
2. 允许单独检查 sort/order 与 view-data 是否为空或异常
3. 固化一套最小调试截图流程,避免后续继续靠猜
验收标准:
1. 可以直接看到 accumulation RT 的内容
2. 可以区分“prepare 阶段错误”和“draw/composite 阶段错误”
### Phase 2把 accumulation surface 正式接入 `BuiltinGaussianSplatPass`
目标:
1.`BuiltinGaussianSplatPassResources::AccumulationSurface` 从未使用状态变成正式执行资源
任务:
1. 在 pass 执行前按 viewport 尺寸创建或复用 accumulation RT
2.`alpha = 0` 清空 accumulation RT
3. draw 阶段只向 accumulation RT 输出,不再直接写主场景颜色
4. 明确 accumulation RT 的资源状态流转
验收标准:
1. draw pass 不再直接绑定主场景颜色附件
2. accumulation RT 生命周期与 working set 生命周期边界清晰
### Phase 3对齐 draw shader 的输出语义与 blend 合约
目标:
1. 让 splat draw 输出和参考实现使用同一套前向累积语义
任务:
1. 对齐 draw shader 输出格式
2. 对齐 draw shader blend 状态
3. 确认当前相机空间 `z` 约定下,排序方向与累积方向一致
4. 不允许通过后端分支打补丁解决语义冲突
验收标准:
1. draw shader 的颜色输出、alpha 输出、blend 方程是自洽的
2. `PrepareOrder -> Sort -> Draw` 是同一套排序约定
### Phase 4新增正式的 composite pass
目标:
1. 把 accumulation RT 稳定地合成回主场景颜色缓冲
任务:
1. 新增 builtin composite shader
2.`BuiltinGaussianSplatPass` 内建立 draw + compose 的完整顺序
3. 明确主场景颜色、深度与 accumulation RT 的交互边界
4. 不通过测试侧手写 command list 绕过 renderer
验收标准:
1. 最终颜色由 composite pass 统一输出
2. 3DGS pass 对主场景颜色缓冲的写入语义单一清晰
### Phase 5回归基线与参数收口
目标:
1. 在正确渲染路径跑通后,再校正当前测试参数
任务:
1. 重新评估当前子集数量是否足够形成稳定 GT
2. 重新评估 `_PointScale` 的默认值
3. 必要时重建 `GT.ppm`
4. 三后端重新运行并固定基线
验收标准:
1. `gaussian_splat_scene` 的 GT 是基于正式渲染路径得到的
2. 不再把“错误输出截图”继续当成 GT
## 7. 风险与提前约束
### 7.1 不能把参考实现照搬成 Unity 特有依赖
本轮只吸收以下内容:
1. 累积 RT + composite 的渲染语义
2. 排序与 blend 的契约关系
3. 中间资源与 draw/composite 的分层方式
不吸收:
1. Unity 特有 `CommandBuffer` 接口设计
2. Unity 运行时生命周期组织方式
3. Unity 专有材质属性命名与 editor 逻辑
### 7.2 不能把 accumulation/composite 做成测试专用旁路
这条路径必须属于正式 renderer而不是
1. 只在 `gaussian_splat_scene` 里额外手写一套
2. 只在 D3D12 下工作
3. 通过测试宏临时切换
### 7.3 不允许继续保留错误 GT
如果当前 `GT.ppm` 来自错误渲染路径,就必须重建。
否则后续再怎么修,测试也会被旧基线误导。
## 8. 完成标志
当以下条件同时成立,这份计划才算完成:
1. `BuiltinGaussianSplatPass` 正式使用 accumulation surface
2. draw shader 与 sort 语义彻底自洽
3. composite pass 正式接回主场景颜色
4. `gaussian_splat_scene` 在 D3D12 / Vulkan / OpenGL 下都能稳定输出正确图像
5. 调试图证明 accumulation RT 本身干净且可解释
6. 当前 3DGS 渲染路径中不再残留“直接写 scene color 的临时旧路线”
## 9. 一句话结论
当前 3DGS 的问题不是“参数没调对”,而是“渲染执行链条还停在错误的临时语义上”。
下一步必须把 `Prepare/Sort -> Accumulation Draw -> Composite` 这条正式路径一次接完整,再重新建立三后端的 GT 基线。