
是_BSL
修复了 BSL 光影在 Yes Steve Model 及其他自定义渲染管线模型上导致的半透明闪烁问题。
YES BSL —— BSL 光影 × Yes Steve Model 兼容修复
纯客户端模组 | Minecraft 1.21 | NeoForge | MIT
修复 BSL Shaders 在由原生 / 自定义渲染管线绘制的模型上导致的 半透明闪烁 —— 目前针对 Yes Steve Model (YSM) 验证,覆盖玩家模型与第一人称手模。
与 BSL Shaders、Iris 或 Yes Steve Model 均无隶属关系。
现象
开启 BSL Shaders 与 Advanced Materials 后,某些模型在镜头移动时出现 半透明并闪烁。YSM 的玩家模型与第一人称手模是已知案例。
模型本身没坏,YSM 也没坏。是光影包采样到了 贴图的错误区域。
原理
BSL 在 Advanced Materials 下启用视差遮挡贴图(POM)—— 而这一点才是关键 —— 它 使用视差校正后的坐标去采样模型自身的贴图:
若 未设置 "跳过视差" 标记:
newCoord = parallax(原始纹理坐标, ...)
modelColor = texture(modelTexture, newCoord) <- 不再是原始纹理坐标
newCoord 由 vTexCoord / vTexCoordAM 推导,二者又来自 OptiFine / Iris 围绕 mc_midTexCoord 与 at_tangent 的约定。
| 几何体来源 | 顶点由谁写入 | 扩展属性是否正确 | 结果 |
|---|---|---|---|
| MC 标准模型(方块、原版生物、手持物品) | BufferBuilder |
✅ Iris 的 MixinBufferBuilder 每 4 个顶点填充一次 |
POM 映射成立 —— 正常 |
| YSM 等模组 | 原生代码直接写入 IrisVertexFormats.ENTITY 内存 |
❌ 取值不满足该映射前提 | newCoord 偏离真实的 texCoord |
于是 albedo 采样到贴图 错误的区域。这类模型贴图布局紧凑、充满空白像素 —— 而 空白像素的 alpha 会被 alpha test 丢弃:
- 于是看起来 半透明(空白处被抠掉了);
- 偏移量随视角每帧变化,于是 闪烁。
一个现成的对照实验。 BSL 为 地图 这个物品单独预留了一个类别(id
400),因为地图是平面贴图,同样经不起 POM。 手持地图时手臂渲染完全正常,而空手时闪烁 —— 两者显示的却是同一份 YSM 手模。 唯一差异就是这个 id。仅凭这一条就能锁定 POM 是元凶。
修复方式
在渲染目标几何体期间,让 Iris 对外报告光影包自己预留的 "跳过法线与视差" 类别值。
这里有 两条完全独立的路径 —— 同一个几何体,在不同 program 里使用不同的变量:
| 渲染对象 | program | 判据 | 光影包逃生舱 |
|---|---|---|---|
| 玩家模型 | gbuffers_entities |
entityId == 10100 |
实体侧的"跳过法线与视差"类别 |
| 第一人称手模 | gbuffers_hand |
heldItemId / 100 == 4 |
物品侧的"地图"类别(id 400) |
为什么是"读取时覆盖"而不是"写入时改写"。 Iris 也在同一位置写 currentEntity。若本模组也去改写,谁先谁后取决于 Mixin 的应用顺序 —— 不可靠。改为在 读取 时覆盖则与顺序无关:读取发生在渲染过程中,此时上下文恰好指向被渲染的对象。
为什么不会误伤。
- 实体侧:本模组 不 盲目信任
10100。它在运行时读取光影包 真实的 映射表,只有当它确实遵循 BSL 这套约定时修复才生效。换成别的光影包会自动不生效。 - 手模侧:只在 空手 时伪造该 id;持有物品时保持真值。在 BSL 中,
heldItemId真正被读取的只有三处,而空手时伪造400与真值0完全等价(400的彩色光数据位恰好是00)。
性能
CapturedRenderingState.getCurrentRenderedEntity() 会 按顶点 被调用,因此热路径被压缩为一次 volatile int 读取:
final int overrideId = EntityIdOverride.activeOverrideId;
if (overrideId >= 0) { cir.setReturnValue(overrideId); }
不参与渲染时 —— 也就是绝大多数绘制:方块、生物、粒子、GUI —— 这次读取就是全部开销。无反射。实测与未安装时的差距约 1 FPS,属浮动误差范围。
安装
- Minecraft 1.21 + NeoForge;
- 把
YES_BSL-1.0.0.jar放入.minecraft/mods/(版本隔离时是versions/<name>/mods/); - 完成。
仅客户端。 服务器上不需要,装不装也没有区别。
依赖 —— 均为可选;缺失时对应部分自动失效,不会崩溃:
| 模组 | 版本 | 说明 |
|---|---|---|
| Iris | 1.8+ | 实际必需 —— 没有光影加载器就没有要修的东西 |
| Yes Steve Model | 2.x | 当前针对它验证 |
启动日志:
[YES-BSL] 已就绪:渲染目标模型时会把 iris 报告的 id 映射到光影包预留的 Skip 类别(entityId=10100 / heldItemId=400)。
配置
首次启动生成 config/yes_bsl.properties:
| 键 | 默认 | 作用 |
|---|---|---|
enabled |
true |
总开关;false 时完全惰性(等价于卸载本模组) |
affectsAllEntities |
false |
是否也作用于非玩家实体 —— 为其它模组适配时可用 |
skipEntityId |
10100 |
光影包为"不适合视差贴图"预留的类别 id |
关于「注入失败」的两种不同严格程度
本模组有两个 mixin 配置,对失败的态度 刻意不同:
| 配置 | 目标 | 失败的后果 |
|---|---|---|
yes_bsl.mixins.json |
Minecraft 自己的 EntityRenderDispatcher |
直接报错(required=true) |
yes_bsl.iris.mixins.json |
Iris 内部类 | 静默失效(required=false) |
前者是刻意的:本模组的唯一功能就挂在这一处,而靶点签名在大版本内非常稳定。一旦它不再匹配,明确报错 远比"悄悄什么都不做"更好排查。后者则相反 —— Iris 内部结构变动更频繁,且光影相关的失败不该拖垮游戏。
若你看到
EntityRenderDispatcher相关的 Mixin 报错,说明本模组与该 Minecraft 版本不兼容。请先移除它,或等待适配版本。
为其它模组适配
骨架与 YSM 解耦,适配新目标通常只需要改 一处判定 —— 要么是 TargetDetector#isTargetEntity(实体路径),要么是 HandMaterialOverride#shouldReportHeldItemId(手持物路径)。更换光影包时,需确认它的 entity.properties / item.properties 里"跳过法线与视差"对应哪个编号,再填进 skipEntityId。
务必保留"实际映射校验"这一步 —— 它保证只有当光影包确实把该编号分配给该用途时修复才生效。完整指引见项目 README。
许可
MIT —— 可自由使用、修改、分发,仅需保留署名。
本项目 不包含 任何第三方的代码或资源,与下列项目 无隶属关系,也不代表它们的立场。
| 项目 | 协议 | 本项目的关系 |
|---|---|---|
| BSL Shaders | All Rights Reserved | 不含、不修改、不再分发;本模组仅调整 Iris 对外报告的 id |
| Iris | LGPL-3.0 | 仅通过 @Mixin(targets=...) 引用其类名 —— 未复制其代码 |
| Yes Steve Model | All Rights Reserved | 不反编译、不修改、不内嵌;仅用于检测其是否加载 |
致谢 Capt Tatsu(BSL Shaders)—— 本模组完全依赖他在 entity.properties / item.properties 中预留的跳过类别,以及 400 这个精心设计的编号(彩色光数据位为 00,使伪造它不产生副作用);以及 Iris 团队 提供的规范 id 映射 API 与注入点。
代码由 DeepSeek 监修。
正在加载版本记录…
正在加载评论…
评论在新手盒子客户端中发表,这里同步展示。