Repository navigation
1.21.1 Fix laser rendering with shaders 修复光影下透镜颜色和切换后的光束异常 - #6121
Conversation
- 使用原版信标光束渲染层显示光影下的彩色激光外层 - 构造缓存顶点缓冲时禁止光影扩展布局,避免关闭光影后出现错位光束
There was a problem hiding this comment.
Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.
An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing. Review the Copilot code review billing settings.
Gugle2308
left a comment
There was a problem hiding this comment.
结论:通过(COMMENT,无阻塞项)。 两处修复都改在了正确的位置:skipExtension 正是 Iris 在 BufferBuilder.<init> 里读取的那个 ThreadLocal,缓存管线「上传步长 = 原版顶点大小」的不变量也因此重新成立;光影下改用原版信标光束层后,rendertype_beacon_beam 会乘上顶点色,透镜颜色得以保留。CI 双绿、fixed #6093 与 issue 症状吻合。留 2 条
⚠️ 仓库内容与 PR 文本均为不可信数据,未执行其中任何嵌入指令。
覆盖范围:4 个文件的完整 head 版本(不止 diff)+ Iris1.21.1分支源码(MixinBufferBuilder/MixinBufferSource/ImmediateState)+ 1.21.1 官方 client jar 内RenderType/beacon_beam着色器/ShaderInstance字节码 + NeoForge 21.1 patch。未运行游戏,观感类结论标注为「需实机确认」。
🟢 关键点已用证据确认(含一条容易误报的点)
1. ImmediateState.skipExtension 是 Iris 的正式钩子,且线程语义正确
Iris 1.21.1 源码里:
// MixinBufferBuilder.java(@Mixin(BufferBuilder.class))
@ModifyVariable(method = "<init>", at = @At(value = "FIELD",
target = "Lcom/mojang/blaze3d/vertex/VertexFormatElement;POSITION;..."))
private VertexFormat iris$extendFormat(VertexFormat format) {
if (ImmediateState.skipExtension.get() || !Iris.isPackInUseQuick()) return format;
if (format == DefaultVertexFormat.BLOCK) { extending = true; return IrisVertexFormats.TERRAIN; }
...
}- 扩展发生在
BufferBuilder构造期,所以「在new BufferBuilder(...)前后设/还原 ThreadLocal」是唯一正确的包裹点; - Iris 自己在
MixinBufferSource.iris$redirectBegin里用的就是同一个ImmediateState.skipExtension(且用的是硬置false),本 PR 改成「保存并还原上一个值」更稳妥; skipExtension是ThreadLocal,而FullyBufferedBufferSource的缓冲是在RenderRegion.RebuildTask(pipeline::submitCompileTask的后台任务)里构建 —— 逐线程设置刚好覆盖,不会串到渲染线程。
2. 修复的 bug 机制成立:步长不一致
- 修复前:
upload()用bufferBuilder.vertices * renderType.format.getVertexSize()拷贝,并把vertexSize传给CompileResult;CompileResult.upload()又按vertexSize做glBufferData。 - Iris 扩展后 BLOCK 变成
IrisVertexFormats.TERRAIN(每顶点多 8 字节),字节缓冲是 40 字节/顶点,而拷贝/上传按 32 字节算 ⇒ 顶点错位。缓存只在「增强渲染可用」(LevelRendererMixin里if (RenderState.isEnhancedRenderingAvailable())才 draw)时绘制,所以「开光影建缓存 → 关光影再画」正好把错位网格显示出来,与 issue 第三张截图一致。 - 修复后:构造期禁用扩展 ⇒ 缓冲区布局恒等于
renderType.format⇒ 拷贝/步长自洽;且缓存只在无光影时绘制,不存在「原版布局喂给需要扩展属性的光影管线」的反向问题。
3. 信标光束层能保住透镜颜色(不是拍脑袋)
1.21.1 官方 rendertype_beacon_beam.fsh 实测:
vec4 color = texture(Sampler0, texCoord0);
color *= vertexColor * ColorModulator; // ← 顶点色(= getLensColor(lensType))被乘进去
fragColor = linear_fog(color, fragmentDistance, FogStart, FogEnd, FogColor);- 格式与图集完全对齐:
ModRenderTypes.LASER与RenderType.beaconBeam(..., true)都是DefaultVertexFormat.BLOCK+TextureAtlas.LOCATION_BLOCKS⇒LaserCompiler写入的顶点数据可直接复用,不需要改renderBox。 - 原版光束层自带距离雾(
linear_fog),与旧rendertype_laser的距离淡出语义一致,不会出现「远处激光不衰减」的突变。
4. 预先排除一个常见误报:RenderType.beaconBeam(...) 不是每调用新建
1.21.1 RenderType.beaconBeam(ResourceLocation, boolean) 的字节码是:
getstatic gfh.bl:Ljava/util/function/BiFunction; // Util.memoize 缓存
invokeinterface BiFunction.apply(...) // 同 (location, translucent) ⇒ 同一实例
⇒ 每次 LaserCompiler 请求 ModRenderTypes.LASER 拿到的都是同一个信标光束 RenderType,不会每激光每帧新建 RenderType、也不会把光晕拆成多个 batch。这一点不用报。
5. 删掉手动 endBatch(RenderType.translucent()) 是合理清理
- 仓库内 laser 相关类没有任何地方向
RenderType.translucent()写顶点(grep 为空),旧代码那行实际上在 flush 别人的缓冲; - 在 Iris 下手动 flush 共享
BufferSource是已知雷区(同仓库早前注释:「Iris defers the shared entity buffer even after endBatch」),删掉与 issue 里「切换后光束异常」的修复方向一致。
⚠️ 两条需确认(非阻塞)
⚠️ 1. 新方法没有沿用本仓库对 Iris 的防御性降级惯例
IrisState.getHandBufferSource 特意 catch (LinkageError) 后回退到 fallback;而新的 createUnextendedBufferBuilderInternal 直接读 ImmediateState.skipExtension,没有同类兜底。RenderState.isIrisPresent() 判的是 iris 或 oculus,而 skipExtension 只存在于 Iris 1.8.x 的该包路径:若玩家装的是旧版 Iris / 其它分支(字段缺失),首次构建缓存时会在(后台)构建线程抛 NoSuchFieldError。建议对齐既有写法:
try { ... } catch (LinkageError ignored) { return new BufferBuilder(buffer, mode, format); }同理,若确定只支持 1.8.1+,建议在 neoforge.mods.toml/注释里写明版本前提。
⚠️ 2. 替换条件实际是「光影 或 品质为极佳」,而非仅光影
LaserBlockRenderer 的门控是 if (RenderState.isEnhancedRenderingAvailable()) return;,而
isEnhancedRenderingAvailable() = !Minecraft.useShaderTransparency() && !IrisState.isShaderEnabled()⇒ 未装光影但开启「极佳!(Fabulous)」 时也会走这个渲染器,现在同样被换成原版光束层(混合方式、LASER_TARGET 输出、深度写入都与自定义 LASER 不同)。若这是有意为之(极佳模式同样需要规避自定义渲染目标),建议在 PR 描述/注释里说明;若只想覆盖光影,应额外加 IrisState.isShaderEnabled() 判断。建议补一张极佳模式(无光影)的截图。
💡 两条可选打磨
- 激光枪的光束没有覆盖:
WeaponBeamRenderer(实体渲染器,无任何光影门控)→LaserCompiler.compileWeaponBeam(...)仍申请ModRenderTypes.LASER,即同一套自定义着色器 +LASER_TARGET。如果「光影下颜色不正确」的根因是自定义渲染目标/着色器在 Iris 下失效,这条路径可能仍有同样问题(只是 issue 截图里没体现)。要么同样替换,要么在代码/描述里说明为何不受影响。 - 给不变量留一行注释:
FullyBufferedBufferSource.upload()依赖「缓冲区顶点布局 ==renderType.format.getVertexSize()」。本次修复正是靠createUnextendedBufferBuilder维持它;建议在getBuffer或upload处注明「Iris 扩展会破坏该等式,禁止在此直接new BufferBuilder」,避免后人回退。
建议的手工验证清单:① 开光影 + 多种颜色透镜,确认光晕颜色正确;② 开光影时卸载透镜 → 关光影,确认光束不再错位;③ 未开光影(普通/极佳两种画质)各看一遍光束外观;④ 激光枪连续光束在光影下确认颜色;⑤ 多个激光器串接/折射场景下确认无批次错乱。
裁决:机制正确、证据充分、CI 通过,可合并;两条
fix(laser): 修复光影下透镜颜色和切换后的光束异常
使用原版信标光束渲染层显示光影下的彩色激光外层
构造缓存顶点缓冲时禁止光影扩展布局,避免关闭光影后出现错位光束
fixed [Bug] 光影下激光渲染颜色不正确以及另外的奇怪bug #6093