Add CFA occlusion culling and render bounds debug renderer 锻星砧遮挡剔除与渲染包围盒调试渲染器 - #4922
ZhuRuoLing wants to merge 2 commits into
Conversation
feat(rendering): occlusion culling and render-bounds debug renderer for the CFA - 升级 anvillib 至 2.0.0+snapshot.531 - CFARenderer 新增 getOcclusionBoundingBox:以所有图层共用的渲染中心 (blockX + 0.5, blockY + centerY, blockZ + 0.5) 为基准,按实际绘制的环类图层 (可见机械环 / 巨构恒星同步层 / 戴森球外环)与天体分支(恒星 / 黑洞 / 中子星 / 行星环 / 玩家头颅)的实际模型外接半径计算,并计入托举光束与超新星放射光束 - 抽出 VisibleRings 统一束星环可见性判定,extractRings 与包围盒计算共用 - 新增 F3 调试渲染器 anvilcraft:cfa_render_bounds,按原版 DebugRenderer + Gizmos 机制注册(RegisterDebugRenderersEvent / RegisterDebugEntriesEvent), 默认关闭,颜色由包围盒哈希派生 - 新增客户端配置 cfaOcclusionCulling(默认关闭):提交遮挡记录前建立跨帧稳定的 OcclusionKey,调试轮廓与遮挡记录互不影响
Reason: Security scan — [MEDIUM] Archive extraction to sensitive path: Archive command 'tar' extracts to a potentially sensitive location Reply |
Reason: script execution via -e/-c flag Reply |
Reason: Security scan — [MEDIUM] Archive extraction to sensitive path: Archive command 'tar' extracts to a potentially sensitive location Reply |
Reason: script execution via -e/-c flag Reply |
代码审查摘要 — PR #4922操作: 本次核对手段(除读 diff 外):
🔴 关键
|
| 声称 | 状态 | 证据 |
|---|---|---|
| anvillib 519 → 531 | ✅ | 两者同版本号一处改动;occlusion 包确实只在 531 的 anvillib-rendering 里 |
新增 getOcclusionBoundingBox,原 getRenderBoundingBox 未改动 |
✅ | diff 只新增;旧方法在 context 中未见 +/- |
VisibleRings 统一可见性规则、避免两处漂移 |
规则确实集中了,但同时把 has*Ring 语义改成"可见"、内环条件外扩到 anyDyson(见 |
|
调试条目 + 调试渲染器(RegisterDebugEntries/Renderers,默认关闭) |
✅ | 新文件 + DebugEntryNoop + isCurrentlyEnabled 门控 |
配置 cfaOcclusionCulling 默认关闭 |
✅ | = false,lang 三处齐全 |
| 环层半径"实测自模型文件" | ✅ | 复算完全吻合(见 🟢) |
| "巨构占用层按对应环层半径计入,实测均 ≤ 对应环层" | ✅ | 24 个变体模型逐个复算成立 |
| 天体系数(1.386 / 1.414 / 1.503·0.406 / 1.4·1.0 / 0.75×16 / 1.5 兜底) | 前四项复算吻合;SPECIAL_BODY_RADIUS=1.5 无实测依据(资源包模型不可预知,只能算兜底,建议注明) |
|
上界纳入托举光束、超新星并入 12×√进度×scale |
光束 ✅;超新星漏了射线的最长 1.3× 随机系数(见 🔴1) | |
| "F3 逐状态比对已与可见几何贴合" | 无天体/无巨构/戴森球状态可信;超新星期会短 30%,行星环走的是"可见半径"口径 | |
| 遮挡剔除记录仍用旧包围盒(有意为之) | ✅(但见 🔴2) | 描述已说明;影响是功能实际不生效 + 文案不符 |
🧪 测试建议
| 被测目标 | 推荐场景 | 优先级 |
|---|---|---|
ringRadius() / bodyRadiusFactor() |
解析 models/block/celestial_forging_anvil_ring_{1..6}.json 与 celestial_body/*.json 复算最大顶点半径,断言 ≥ 常量(防模型微调后静默漂移) |
🔴 |
getOcclusionBoundingBox() |
逐状态(无天体 / 主序星 / 黑洞 / 中子星±喷流 / 有环岩石行星 / 玩家头颅 / 各巨构 / 超新星)断言半径等于预期值,并断言超新星期 half ≥ 12 × 1.3 × √t × scale |
🔴 |
遮挡记录(beginOcclusionRecord) |
断言开启配置后 renderBounds 换用 getOcclusionBoundingBox 时盒不缩小于可见几何;配置关闭时零开销(不建键、不记录) |
🟡 |
OCCLUSION_KEYS |
开启配置 → 移除方块实体 → 断言 map 不保留该 BE(含仅剩最后一个 CFA 的情形);关闭配置后再次提取应仍能清理 | 🟡 |
VisibleRings.of() |
表格化单测:(bodyData × isAmplify × option 各 id) → (outer, middle, inner),并对照旧实现的 hasMechanicalRings + 巨构隐藏 语义,把有意的差异(anyDyson)固化成用例 |
🟡 |
| 过渡淡出(观感) | 手动:恒星→岩石行星(应看到 R3 缩放淡出)、巨型行星出现(R1 淡出)、放大态 大/小天体互换(R6/R4 淡出)、天体移除(淡入) | 🟢 |
结论: COMMENT — 包围盒数值推导扎实(硬编码常量逐值复算全部吻合,巨构变体覆盖结论成立),anvillib 的 OcclusionKey 身份语义与该 PR 的缓存策略相互印证。建议合并前处理 🔴1(超新星半径漏 1.3×,与自测结论冲突)与 🔴2(记录仍用旧盒 ⇒ 开了不生效,但文案宣称生效),并确认/修正 has*Ring 语义与 anyDyson 外扩、
PR 标题:当前标题只有中文部分。gh auth status 显示 token 已失效(The token in /opt/data/home/.config/gh/hosts.yml is invalid),本次未能自动修改标题,建议改为:
feat(rendering): CFA occlusion culling and render-bounds debug renderer 锻星砧遮挡剔除与渲染包围盒调试渲染器
由 Hermes Agent 审查
|
I have enough verified data (including reverse-engineering the ring/body model radii from the actual assets). Writing the review now. 代码审查摘要 — PR #4922操作: opened | 范围: 10 个文件 (7 Java, 3 新增) / 635 行 diff (386 +, 41 −, 3 new, 0 删除) 包围盒数值我做了独立复算( 🔴 关键
|
| 声称 | 状态 | 证据 |
|---|---|---|
anvillib 519 → 531 |
✅ | libs.versions.toml |
getRenderBoundingBox 未改动 |
✅ | diff 仅新增 getOcclusionBoundingBox |
| 六层环半径 0.336/0.487/0.708/0.614/0.796/1.039 | ✅ | 我复算 0.3358/0.4871/0.7078/0.6144/0.7961/1.0390 |
| 巨构同步层 ≤ 对应环层 | ✅ | 全部模型实测(见上) |
| 戴森球额外 R5(小恒星)/R6(其它) | ✅ | 与 extractMegastructureRings:555-561 一致 |
| 天体系数(黑洞 1.414、中子星 0.406/1.503、行星 1.0/1.4、头颅 0.75×16) | ✅ | 模型实测 1.4142 / 0.4059 / 1.5026 / 0.866×1.125 |
| 恒星 1.386(光晕 0.866×1.6) | 实际光晕最大倍率 = 1.0+0.9×0.6 = 1.54 → 1.334,1.386 偏保守但注释里的 1.6 不对 |
|
| 行星环 1.0 × 1.4 | ❌ | 实际可见半径 1.327 × 倍率(1.72–1.86) |
超新星 12 × √进度 × scale |
漏了每根光束 0.7–1.3 的随机系数 | |
| 典型尺寸 8.5 / 12.5 / 9.5 / 5.8 格 | ✅ | 逐状态复算一致(R3/R6/R5/被隐藏外环的岩石行星) |
| 配置默认关闭 + lang 一致 | ✅ | cfaOcclusionCulling = false,三处文案一致 |
| 「F3 逐状态比对与可见几何贴合」 | 调试器画的是 getOcclusionBoundingBox,剔除记录用的是旧 getRenderBoundingBox,验收对象不一致 |
结论: REQUEST_CHANGES(改动大多很小)—— 建议至少修掉 🔴 的淡出回归 + 两个包围盒数值偏差(行星环、超新星光束),并明确剔除记录究竟该用哪个盒子;其余为可选优化。遮挡剔除 API 用法、环半径推导、巨构规则重构三项我逐值复算通过,质量是好的。
建议标题(gh auth status 显示 token 失效,本次未自动改):PR 标题目前只有中文,且未体现「包围盒重算/可见性重构」的实质:
Add CFA occlusion culling and render bounds debug renderer 锻星砧遮挡剔除与渲染包围盒调试渲染器
🧪 测试建议
| 被测目标 | 建议场景 | 优先级 |
|---|---|---|
VisibleRings.of(...) |
参数化:body×{null,星,巨行星,岩石行星,头颅,自定义} × amplify × {戴森球小/大,线圈,彭罗斯,解压器} × 加速器开关,断言与旧规则逐格等价 | 🔴 |
getOcclusionBoundingBox |
各分支半径下界断言(环/天体/光束/超新星),并新增「任意状态下 half ≥ 可见几何实测半径」的护栏断言 |
🔴 |
bodyRadiusFactor / ringRadius |
与模型文件解析结果做数值回归(可脚本化,防止以后改模型忘改常量) | 🟡 |
OCCLUSION_KEYS |
模拟区块卸载/换世界后表大小不增长 | 🟡 |
submit 遮挡记录 |
提交中抛异常后下一帧几何仍正常转发(try/finally 保护) |
🟡 |
由 Hermes Agent 审查(本地未提供 MC 26.1 反编译源码,debugEntries.isCurrentlyEnabled、levelRenderer.iterateVisibleBlockEntities、GizmoStyle.stroke 三处 API 依赖作者的 compileJava 结果,其余结论均有源码/资源实测支撑)
|
💾 Self-improvement review: Patched SKILL.md in skill 'rendering-gpu-pr-review' (1 replacement). |
Reason: Security scan — [HIGH] Pipe to interpreter: curl | python3: Command pipes output from 'curl' directly to interpreter 'python3'. Downloaded content will be executed without inspection. Reply |
Reason: Security scan — [MEDIUM] Archive extraction to sensitive path: Archive command 'tar' extracts to a potentially sensitive location Reply |
Reason: script execution via -e/-c flag Reply |
|
审查完成。以下是审查意见(已尽量核对源码/模型/依赖 jar 实证): 代码审查摘要 — PR #4922操作: 🔴 1.
|
| 项 | 结论 |
|---|---|
anvillib 依赖 2.0.0+snapshot.531 |
✅ Cjsah Maven 上存在;anvillib-rendering 中 dev.anvilcraft.lib.v2.rendering.optimization.occlusion 包确实含 OcclusionCuller.wrapSubmitNodeStorage(SubmitNodeCollector)→OcclusionSubmitNodeStorage、OcclusionKey(Supplier,AABB)+setBoundingBox、beginOcclusionRecord/endOcclusionRecord、ALROptimizations,调用签名一致 |
| 环层半径表 R1–R6 = 0.336/0.487/0.708/0.614/0.796/1.039 | ✅ 逐模型顶点复算:0.3358 / 0.4871 / 0.7078 / 0.6144 / 0.7961 / 1.0390 |
| "同层巨构变体 ≤ 该层环模型" | ✅ 挖掘机 0.336、提取器 0.336/0.487、戴森球 R4 0.595/R5 0.785、线圈 0.614、彭罗斯 0.614、解压器 0.614、对撞机 0.539、虫洞稳定器 0.614、R5/R6 加速器 0.796/1.039 全部 ≤ 对应环层 |
| 天体系数 | ✅ 黑洞 1.4142(=√2,模型实测)、中子星 0.406/喷流 1.503、恒星/行星立方体 0.866 ≤ 1.386/1.0;玩家头颅 0.75×16 足够(头颅模型 ≈0.43×16) |
| 超新星/光束上界 | ✅ SUPERNOVA_RAY_LENGTH=12 > SUPERNOVA_MAX_RADIUS=8(且平板对角 8√2≈11.3 < 12);托举光束上界用 BEAM_BASE_Y + smoothBeamHeight,水平半宽 ≤0.4 远小于环半径 |
| 中心与坐标系 | ✅ (pos.x+0.5, pos.y+smoothCenterY, pos.z+0.5) 与 submit 的 translate(0.5, centerY, 0.5)、MultiPartBlockEntity 的 BOTTOM_CENTER 主部件一致;javadoc 里 8.5 / 12.5 / 9.5 格的例子复算无误 |
| 遮挡记录覆盖面 | ✅ 机械环/巨构层/天体/天体环/超新星全部改走 target;submitStarBloom(后处理)与延迟托举光束不入采集器,与描述一致;submit 内 begin/end 配对无提前 return |
| 配置与 lang | ✅ cfaOcclusionCulling 默认 false,ConfigScreenLang 覆盖 + en_us/en_ud(含 en_ud 倒序)齐全,tooltip 描述与实现相符 |
📋 声称验证表
| 声称 | 状态 | 依据 |
|---|---|---|
| 接入 anvillib 遮挡剔除(519→531) | ✅ | 依赖存在 + API 签名匹配 |
VisibleRings 统一可见性判定"避免两处规则漂移" |
统一了规则但改变了行为(见 🔴1) | |
| 包围盒按"实际绘制的图层"取外接半径 | 环层部分 ✅,程序化行星环部分低估(见 🔴2) | |
getRenderBoundingBox 未改动 |
✅ | 旧实现逐字未动;但剔除记录仍用它(见 |
| F3 调试项默认关闭、颜色由包围盒哈希派生 | ✅ | DebugEntryNoop 默认不启用;颜色随尺寸变化 |
compileJava / runData 通过 |
未复核 | 无本地构建环境,未验证 |
结论: COMMENT(draft,不建议直接转正式 PR 合并) — 阻断项为 🔴1(环淡出动画回归)与 🔴2(行星环半径低估,切到新包围盒前必须修);
标题建议: 现标题只有中文,建议改为 Add CFA occlusion culling and render bounds debug renderer 锻星砧遮挡剔除与渲染包围盒调试渲染器。(本次 gh auth status 显示 /opt/data/home/.config/gh/hosts.yml 的 token 已失效,故未自动执行 gh pr edit。)
由 Hermes Agent 审查
|
💾 Self-improvement review: Patched SKILL.md in skill 'rendering-gpu-pr-review' (1 replacement). · Patched references/pr-class-routing.md in skill 'github-webhook-pr-review' (1 replacement). |
代码审查摘要 — PR #4922(
|
| 声称 | 结论 | 我的独立复算 |
|---|---|---|
升级 anvillib 至 2.0.0+snapshot.531 |
✅ | libs.versions.toml:9;531 的 render 模块里确有 optimization.occlusion 包(含 OcclusionCuller/OcclusionKey/OcclusionSubmitNodeStorage) |
| 环层半径 R1–R6 = 0.336/0.487/0.708/0.614/0.796/1.039 | ✅ 完全吻合 | 逐 element 顶点(含 rotation)到原点距离 ÷16:0.3358 / 0.4871 / 0.7078 / 0.6144 / 0.7961 / 1.0390;且 r_origin == r_center,证明「模型原点即渲染中心」成立 |
| 巨构占用的同步层「实测均 ≤ 对应环层」 | ✅ 逐模型核对通过 | 挖掘机/提取器/生态站/神殿 0.3358=R1;巨行星提取器 0.4871=R2;对撞机 0.5386、线圈 0.6144、彭罗斯球 0.6144、解压器 0.6144、虫洞稳定器 0.6144 ≤R4;小型戴森球 0.5954 ≤R4;大型戴森球 0.7848 ≤R5;恒星演化加速器 0.7961/1.0390 =R5/R6 |
戴森球额外外层环:小型恒星 R5、其余 R6,「与 extractMegastructureRings 一致」 |
✅ | 两处条件逐字一致(isSmallStar = size < 48;R4&&small → R5 / R5&&!small → R6,CFARenderer.java:553-561 ↔ :317-323) |
| 中子星 1.503/0.406(有无喷流) | ✅ | neutron_star_jet.json 中心半径 1.5026、neutron_star.json 0.4059;喷流开启条件 rotationSpeed() >= 5(extractBody :615)与 bodyRadiusFactor :452 一致 |
| 黑洞 1.414、玩家头颅 0.75×16、资源包天体 1.5 兜底 | ✅ | black_hole.json 1.4142(精确);头颅模型在 translate(0.5,0.25,0.5) 偏移下,角点到渲染中心恰好 √(0.5²+0.25²+0.5²)=0.75,常数取得很准;自定义天体实测 1.08/1.16 ≤ 1.5 |
| 普通恒星 1.386(光晕 0.866×1.6) | submitHalo(..., 10, 1.0f, 0.6f, ...) 的 progress=i/iterations 最大为 0.9 ⇒ 实际最大缩放 1.54(不是 1.6),实际半径 0.866×1.54=1.334。1.386 偏保守 ✅,但描述里的「×1.6」不是代码值,建议改成 0.866×(1.0+0.9×0.6) 以免下一个人按 1.6 反推 |
|
上界额外纳入托举光束 / 超新星中心改用 getSupernovaCenterY() 且半径并入 12×√进度×scale |
✅ | :1657-1661、:1632-1655 与 pushRing/submitMechanicalRing/submitCelestialBody/submitCelestialRing 的 (0.5, centerY, 0.5) 中心一致 |
| 「非增幅无天体 8.5 格、增幅无天体 12.5 格、小型恒星戴森球 9.5 格、有岩石行星 5.8 格」 | ✅ | 复算:0.708×6×2=8.50;1.039×6×2=12.47;0.796×6×2=9.55;0.487×6×2=5.84 |
「遮挡剔除仍使用原 getRenderBoundingBox(按要求未改动)」 |
✅ 与代码一致 | :195-196 存旧盒、:757-759 喂旧盒;新盒只在调试渲染器用(:47)。但这与配置文案冲突,见下 |
anvillib / NeoForge API 契约核对(常量池级别)
OcclusionKey.hashCode()=System.identityHashCode(this)、equals为身份语义 ⇒ 必须跨帧复用同一实例(:176-180的按 BE 身份缓存是必需且写法正确 ✅);setBoundingBox每帧改盒不会破坏哈希 ✅。OcclusionSubmitNodeStorage extends net.minecraft.client.renderer.SubmitNodeStorage,只覆写order(int)⇒ 所有提交入口(submitModel/submitCustomGeometry/submitBlockModel…)都被统一拦截,不存在某类几何被漏转发的风险 ✅(这是本 PR 最值得担心的点,已验证排除)。RegisterDebugRenderersEvent.register(SimpleDebugRenderer)与RegisterDebugEntriesEvent.register(Identifier, DebugEntry)两个重载都存在 ✅;emitGizmos(DDD,DebugValueAccess,Frustum,F)与 26.1 原版BeeDebugRenderer签名一致 ✅;iterateVisibleBlockEntities是 NeoForge 对LevelRenderer的补丁方法(userdev patch 内可见)✅;DebugScreenEntryList.isCurrentlyEnabled(Identifier)存在 ✅;ALRDebugEntries(Javadoc 引用的 anvillib 参考实现)也只register(id, entry)、不加 profile ⇒ 注册方式与库内一致 ✅。
🔴 关键(仍未修,建议合并前处理)
-
:1654超新星半径仍漏掉放射光束的随机长度系数(最多少算 30%)
实际绘制len = rayLen * (0.7f + 0.6f * rand.nextFloat())(:1338,上限 1.3×),而包围盒只取SUPERNOVA_RAY_LENGTH * grow * max(1, scale)。t→1 时真实可达12×1.3=15.6格,盒仅 12 格 ⇒ 小约 23%。这正是「新盒与可见几何贴合」这条验收标准的反例,切换到该盒做剔除后会出现可见几何被误剔。建议提常量(与:1338共用)而不是就地写1.3f。 -
:315-317+:832束星环淡出动画被这次重构静默关闭(观感回归)
旧代码present = hasMechanicalRings(存在性:仅排除玩家头颅),新代码present = VisibleRings.*(当前可见性)。而present == false会在submitRingMaybe的if (model == null || !present) return;处先于淡出分支返回,于是visibleNow=false && wasVisible=true的缩放淡出永远走不到。受影响(旧=缩小淡出,新=瞬间消失):恒星→岩石行星(R3)、任意→巨行星(R1)、任意→SpecialCelestialBodyData(R3)、增幅下大小恒星跨越 48 阈值(R6/R4)。静止态渲染无差异,只在过渡窗口内。最小修法:present传state.isHasOuterRing() || state.isOuterWasVisible(),或把VisibleRings拆成present/visibleNow两组、has*Ring恢复存在性语义。 -
:757-759遮挡记录喂的仍是旧getRenderBoundingBox,新配置当前「开着也不剔任何东西」
旧盒尺寸为max(bodyScale,ringScale)×3×1.5(无天体时6×3×1.5=27格),HZB 判定基本永远可见 ⇒ 开cfaOcclusionCulling只白付记录开销;而 F3 里看到的框是新盒,不是剔除实际使用的框(PR 描述的「逐状态比对贴合」验证不到真正上线的那个盒)。描述里已注明「按要求未改动」,这点我可以接受,但新增 lang/配置文案写的是 “geometry fully hidden behind terrain is skipped”,对玩家是过度承诺。二选一:本期直接切到getOcclusionBoundingBox(...),或把 tooltip 改成「当前仅提交遮挡记录,剔除待新包围盒验收后启用」。
⚠️ 警告
-
:456-457有环行星的半径系数偏小约 21–27%(新发现的关键数值缺口)
renderRing画的是x,z ∈ [-0.5, 1.5]的 2×2 方片,UV 映射到贴图[0,0.5]²(16 px = 1 格,环心 = 象限中心)。我逐像素量了planet_giant_ring_0.png(64×64):不透明像素到环心的最大距离 = 21.9 px = 1.37 格(几何角点 1.414,仅角尖透明)。
描述里「半径 1.0 × 最大倍率 1.4」的 1.0 只是未旋转方片沿轴的半宽;方片每帧绕 Y 连续自转(:1197-1199),转到 ~45° 时那条 1.37 的对角方向就变成轴方向 ⇒ AABB 需要1.37 × ringMultiplier:岩石 1.85 / 巨行星 1.78 / 其它 1.92 格,而bodyRadiusFactor只给 1.4 ⇒ 盒比可见几何小 21–27%。建议把环单列一项:ringType != NONE ? 1.37f * ringMultiplier(body) * smoothBodyScale : ...再与天体项取 max(顺便把 1.37 的来历写进注释,避免下次又被「半径 1.0」误导)。 -
:197-201OCCLUSION_KEYS的清理时机与规模
清理写在if (CONFIG.cfaOcclusionCulling)内部,且该 map 持有 BE 强引用(间接强引用ClientLevel):关闭配置后旧条目永不清理(也不再新增,纯残留);退出世界/换存档后不再有 CFA 提取 ⇒ 最后一批条目 + 世界对象常驻;removeIf在每个 CFA 每次提取全表遍历 ⇒ n 个锻星砧每帧 O(n²)。建议把清理移出配置判断(或if (!map.isEmpty())守卫),并在客户端世界卸载/LoggingOut处clear()。 -
:1172-1175褐矮星光晕超出 1.0 系数约 14%
brownDwarf()额外画submitHalo(..., 3, 1.15f, 0.25f, ...),最大缩放1.15 + (2/3)×0.25 = 1.317⇒ 半径0.866×1.317 ≈ 1.14;无环巨行星走1.0f分支 ⇒ 光晕外缘被切约 12–14%。建议褐矮星至少取 1.14。
💡 建议
- 调试盒最好直接对比「真正上线的盒」:NeoForge 26.1.2 自带
net.neoforged.neoforge.client.BlockEntityRenderBoundsDebugRenderer(同样走iterateVisibleBlockEntities,画的是每个 BE 的getRenderBoundingBox,客户端指令开关)。也就是说现在两个调试视图会互相打架:原版的框=剔除真正用的框,本 PR 的框=「待验收的新框」。建议在描述/注释里点明这一点(或在本 PR 里让记录盒与新盒同源,问题自然消失)。 - 半径常量建议从模型/贴图推导而不是硬编码:
ringRadius()的 6 个值与实测完全相等(差 ≤0.05%),巨构变体也刚好等于所在层半径(0.6144/0.7961/1.0390)——这意味着「变体 ≤ 所在层」这条不变量没有任何余量,任何一次模型微调都会静默破坏包围盒。可考虑在 bake 时取模型 bbox、或至少加注释断言并附上实测脚本/数值出处。 :747-749endOcclusionRecord()仍无try/finally:submit()中途抛异常时本帧记录不会转发给真正的 collector(几何整体消失且记录悬空)。库侧beginOcclusionRecord有IllegalStateException守卫,建议对称加保护。:51调试描边色bounds.hashCode()会逐帧闪烁:盒子含平滑缩放、红石系数、超新星进度(含partialTicks)⇒ 颜色持续抖动,反而难以「辨识尺寸变化」。建议用量化后的稳定依据(环层数/是否增幅/是否超新星)派生。:195-196每帧无条件算/存旧盒:配置关闭时这次计算(以及 state 字段赋值)是纯开销,且原版 frustum 剔除路径本身也会调用getRenderBoundingBox⇒ 同一帧对同一 BE 算两遍。建议移进if (cfaOcclusionCulling)分支,或与剔除路径复用。:1632-1635超新星期间中心取「瞬时」getSupernovaCenterY(),而环/天体渲染用的是平滑getSmoothCenterY()(:236-237):闪光期间若红石/缩放变化,平滑值滞后 ⇒ 盒心与几何中心有偏差(量级为平滑残差,目前小,但和 在REI渲染方块(初步测试) #1 叠加时更容易漏边)。另:托举光束只纳入了上界,BEAM_BASE_Y=1.5(:161)在极端过渡帧(半宽 < 3.0)可能比盒底低约 0.1 格。- 描述里
1.0f(无环行星)的括号注释只写了大气层立方体,建议补一句「褐矮星光晕另计」(见⚠️ 6)。 - 新增 lang 键只进了
en_us/en_ud,其余语言走 Weblate,属正常流程,仅提示。
🟢 看起来不错
- 6 个环半径常量与模型文件逐顶点复算完全对得上(
0.3358/0.4871/0.7078/0.6144/0.7961/1.0390),且模型关于原点对称 ⇒pushRing的「原点即中心」前提成立;VisibleRings把「提取」与「包围盒」两处判定收拢到一处,消除了规则漂移的可能(本轮重点验收方向是对的)。 - 巨构/戴森球/加速器的层占用与半径映射逐条核对无误,戴森球外层环的 R5/R6 选择与
extractMegastructureRings完全一致;option.id()为null时的equals调用是 null 安全的。 - anvillib 的遮挡 API 用法正确:身份哈希键 + 按 BE 缓存的写法与库设计匹配;
OcclusionSubmitNodeStorage只覆写order(int),因此submitModel(tessellation)与submitCustomGeometry(天体环/光晕/新星)都会被完整拦截,不会出现「开了 culling 就掉几何」。 - 描述主动披露了两处不参与剔除的独立绘制(托举光束 AFTER_WEATHER、恒星 bloom),并明确「实验性、默认关闭」——诚实且降低误解。
- 调试渲染器放在提取阶段用
Gizmos提交、由原版每帧收集器统一绘制,符合 26.1 原版调试渲染器机制(与BeeDebugRenderer同构);选iterateVisibleBlockEntities也意味着即使某个锻星砧被剔除、其调试框仍会画出,便于验收。
🧪 测试建议
| 被测目标 | 推荐测试场景 | 优先级 |
|---|---|---|
getOcclusionBoundingBox |
纯数学函数:对每种天体/巨构组合断言盒包含该状态下所有可见几何(尤其有环行星 ×45° 自转、超新星 t→1、戴森球小型/大型) | 🔴 |
CFARenderer.submitRingMaybe |
过渡回归:恒星→岩石行星/巨行星/特殊天体,断言过渡窗口内 submitRingScaled 仍被调用(当前语义已破坏) |
🔴 |
OCCLUSION_KEYS |
开关切换 + 多次进出世界/换维度后断言 map 为空(当前会残留) | 🟡 |
getOrCreateKey |
同一 BE 跨帧返回同一实例;BE 移除后条目被回收;名字供应器不捕获 BE | 🟡 |
结论: REQUEST_CHANGES — 描述与推导表本身质量很高(半径表、巨构映射我逐项复算全部吻合),但 #1(超新星光束少算 30%) 与 Add CFA occlusion culling and render bounds debug renderer 锻星砧遮挡剔除与渲染包围盒调试渲染器 准确,无需修改。
由 Hermes Agent 审查
|
💾 Self-improvement review: Patched references/occlusion-culling-bounds-integration-review.md in skill 'rendering-gpu-pr-review' (1 replacement). · Patched scripts/model_json_radius_probe.py in skill 'rendering-gpu-pr-review' (1 replacement). · Patched SKILL.md in skill 'rendering-gpu-pr-review' (1 replacement). |
概要
为锻星砧(CFA)接入 anvillib 的遮挡剔除能力,并按原版调试渲染器机制提供渲染包围盒可视化(F3 调试项开关,默认关闭)。
同时把 anvillib 升级到
2.0.0+snapshot.531(该版本才有dev.anvilcraft.lib.v2.rendering.optimization.occlusion包)。变更点
anvillib2.0.0+snapshot.519→2.0.0+snapshot.531。CFARenderer#getOcclusionBoundingBox(be, partialTicks)(新增,原getRenderBoundingBox未改动):以所有渲染图层共用的渲染中心为基准,按「实际绘制的图层」取外接半径。VisibleRings(新增):束星环可见性判定(天体类型 + 巨构隐藏规则)统一到一处,extractRings与包围盒计算共用,避免两处规则漂移。CfaRenderBoundsDebugRenderer+DebugRendererEventListener(新增):按原版DebugRenderer.SimpleDebugRenderer+Gizmos绘制包围盒,通过RegisterDebugRenderersEvent/RegisterDebugEntriesEvent注册调试条目anvilcraft:cfa_render_bounds(F3 调试选项中开关,默认关闭),颜色由包围盒哈希派生以辨识尺寸变化。cfaOcclusionCulling(默认关闭),开启时在提交几何前建立跨帧稳定的OcclusionKey并提交遮挡记录。包围盒推导依据
渲染中心:所有图层都以
(blockX + 0.5, blockY + centerY, blockZ + 0.5)为中心缩放(submitMechanicalRing/pushRing/submitCelestialBody/submitCelestialRing/submitSupernovaFlash/emitBeamPyramid)。centerY取be.getSmoothCenterY();方块实体只存在于BOTTOM_CENTER主部件(MultiPartBlockEntity#newBlockEntity),故其方块中心即整机 3×3 底面中心。半径:环类图层都经
pushRing以同一个ringScale绘制,且模型原点即渲染中心,因此半径 = 图层模型「顶点到原点的最大距离」×ringScale(实测自模型文件,非单轴半宽):VisibleRings(天体类型会隐藏外层环;戴森球/彭罗斯球等巨构会隐藏对应层);extractMegastructureRings一致:小型恒星用 R5(0.796),其余用 R6(1.039)。1.5 + beamHeight,超新星期间中心改为getSupernovaCenterY()且半径并入12 × √进度 × scale。ringScale = 6时:非增幅无天体约 8.5 格、增幅无天体约 12.5 格、小型恒星戴森球约 9.5 格、有岩石行星(外环被隐藏)约 5.8 格。验证
./gradlew.bat compileJava --console=plain通过;./gradlew.bat runData --console=plain通过,生成的 diff 仅包含新增/删除的配置项 lang 键;anvilcraft:cfa_render_bounds逐状态比对:无天体、有星体无巨构、无巨构增幅、小型恒星戴森球、大恒星戴森球均已与可见几何贴合。说明
getRenderBoundingBox(本次按要求未改动它),待新包围盒验收完成后可切换;