修复 3DGS 的 SH 1-3 阶系数从未上传到 SSBO-4(INSTANCING 方法下视角相关色丢失) - #30
Merged
Conversation
GaussianGeometry::finalize() gates the SSBO-4 upload on noSH, i.e. on the INSTANCING_TEXTURE / INSTANCING_TEX2D methods, but _shcoefBuffer is only allocated for INSTANCING (see the constructor). So under INSTANCING the block is skipped and under the texture methods the buffer is null: the SH bands 1-3 the reader decoded (PLY f_rest_*, SOG shN) never reach the GPU, while checkShaderFlag() still defines FULL_SH for INSTANCING whenever the degree is > 0 -- the shader then samples an unbound buffer. Symptom: the view-dependent colour is lost (DC-only look) or, on drivers without robust buffer access, garbage. Invert the gate and require the buffer. Also accept degree 1 / 2 data (3 / 7 layers) instead of only degree 3 (> 10): the buffer is zero-filled, so missing higher bands evaluate to 0 against the shader's fixed 15-entry layout. GEOMETRY_SHADER passes SH through vertex attributes and never enters this code path; the texture methods still do not enter it. Only the INSTANCING path -- the broken one -- changes behaviour. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013yKGp8faVmYP2Ao6NGQnxj
Owner
|
非常有道理,感谢您和Claude~如果有别的问题也欢迎随时提交 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
问题
用
GaussianGeometry::INSTANCING(默认渲染方法)加载带球谐的 3DGS 数据时,读取器解出来的 SH 1-3 阶系数(PLY 的
f_rest_*、SOG 的shN)从来没有被上传到 GPU。表现是模型只剩 DC 项的固定颜色,视角相关的高光/色彩变化整个消失;
而 shader 那边
FULL_SH宏仍然是打开的,采样的是一个未绑定的 SSBO——在没有 robust buffer access 的驱动上会读到垃圾数据。
根因
modeling/GaussianGeometry.cpp的GaussianGeometry::finalize()(当前 master 第 398-400 行):noSH的语义是「这个方法不带 SH」,但上传块的门却建在noSH == true上。而
_shcoefBuffer只在构造函数里给INSTANCING分配(第 156-161 行):两边一叠加,结果是没有任何一条路径能真正上传 SH:
noSH_shcoefBufferINSTANCINGINSTANCING_TEXTURE/INSTANCING_TEX2DGEOMETRY_SHADERsetShRed/Green/Blue的 else 分支),不受影响与此同时
checkShaderFlag()(第 203-206 行)对INSTANCING照样定义FULL_SH:于是
gaussian_splatting.vert.glsl里FULL_SH分支会去读 binding=4 这个从未绑定的 SSBO。复现
任意一个带 SH 的
.ply(含f_rest_*)或.sog(含shN),用默认的INSTANCING方法加载并旋转视角:颜色完全不随视角变化。加断点在上面那个
if上,可以看到INSTANCING下noSH == false直接跳过整块。修改
把门反过来,并显式要求缓冲存在:
顺带把
shDataSize > 10放宽成>= 3:原来的阈值只接受 3 阶(15 层)数据,1 阶(3 层)和 2 阶(7 层)的数据会被静默丢掉。
_shcoefBuffer上传前resize(..., 0)是零填充的,shader 又按固定 15 槽读,所以低阶数据缺的那几档天然算成 0,不需要额外分支。
GEOMETRY_SHADER路径完全不经过这段代码,行为不变;两个纹理方法因为!noSH依然进不去,也和改前一致(它们本来就没有 SH 缓冲、也不定义FULL_SH)。即只有原本就坏掉的
INSTANCING路径的行为发生变化。验证
INSTANCING方法。改后随视角正确变色。
.ply/.sog成果:视角相关高光恢复。附注(不在本 PR 范围内,供参考)
pipeline/ShaderLibrary.cpp的processIncludes()在处理#pragma import_defines(...)时会把这一行整个erase掉,只把当次传入的defines列表里命中的键重新插成#define。这意味着 shader 一旦经过ShaderLibrary 预处理,之后再通过
StateSet::setDefine()设置的宏(例如checkShaderFlag()设的FULL_SH)就到不了 program 了——因为 OSG 注入stateset defines 依赖编译时源码里那行 pragma 还在。
readerwriter/UtilitiesEx.cpp:996和tests/gaussian_splatting_test.cpp:185里那两条
// FIXME: it seems import_defines failed in GLCore/GLES mode?注释很可能就是这个现象。我们目前是在应用侧手工
setShaderDefines()补回来绕过的,没有把它做进这个 PR;如果确认是个 bug,我可以另开一个。
🤖 Generated with Claude Code
https://claude.ai/code/session_013yKGp8faVmYP2Ao6NGQnxj