在BAS及M7实现伪蒙板效果的一种方式

在BAS及M7实现伪蒙板效果的一种方式

2025年2月9日

之前看ILAS这个代码弹幕作品时,对这种之前BAS弹幕从未真正实现过的效果(逐帧svg不算)有过短暂的思考,当时想到可以用半透明图层覆盖的形式做覆盖改色,但简单实验过半透明上层覆盖半透明文字后,感觉效果非常不理想,就没再进一步研究了。

几年过去,本来都已经退组织了,忽然在首页刷到奏奏发的弹幕系统大加强的视频,又听闻2年没消息的蓝白也要开始组织了,便想再把之前停工在10秒的鹅妈妈重做补完后凑个数。但又感觉直接报名之后不能保证不会鸽有点过意不去,于是就登小号进群先占个后备位置看看最近的弹幕有啥新花样。

于是今晚例行在群里聊天时,水群姬忽然提到他一直无法使用m7做出来“切色”效果,让我也想到了之前考虑ILIAS蒙板效果的事,就想干脆在半透明图层叠色的基础上多尝试一下颜色叠加与图层遮挡的组合形式,在群里吹水一下。没想到最后效果真的还算可以,用简单的半透明叠色和层级覆盖的原理,就可以实现“切字”这种之前一直没法复刻的代码弹幕效果。而且由于是最基本的图层叠色原理应用,所以支持透明度的M7和BAS弹幕均可实现同样的效果。

这里先放一下最终效果,原始测试弹幕在 https://www.bilibili.com/video/BV1hp411f7me/?p=11的开头0秒,因为M7加载问题,有时中间的文字层级可能显示错误,导致“颜”字是个不会变化的蓝色文字,这时刷新几下页面应该就能解决。

没错,这是用M7实现的

接下来讲讲原理,就像上面说的,这只用了简单的半透明叠色和层级覆盖。在制作过程中,在背景色之外只需要3层弹幕便可实现切色效果:最上层和最下层是运动、定位、字号完全一致的文字弹幕,中间穿插一层遮挡图层。其中底层文字和穿插层的Alpha均为1,而顶层文字Alpha需要设定为合适的半透明数值,一般设定为0.5即可。

这三层弹幕的颜色可以简略记为:顶层颜色A,中间层颜色B,底层颜色C

如此这般,在文字未与中间层互相遮挡时,观察到的文字颜色是底层颜色C叠加半透明顶层颜色A后的C+0.5A,背景色为视频最底层的原始背景色,与文字颜色无关。

而中间层在插入到两个文字层之间时,会完全遮挡住下层颜色,此时观察到的文字颜色将替换为B+0.5A,背景颜色即为B。此时文字背景与文字自身的颜色存在一定关联,因此需要合理选择半透明文字和穿插图层的色号,以便在遮挡后仍能保留足够的对比度而不至于呈现出色盲测试图的低色差效果。

将文字弹幕轻微错开便可看到颜色关系:
背景颜色是浅蓝,底层不透明文字颜色是天蓝,中层颜色是淡紫,顶层则是半透明的黄色,未被遮挡时黄色会叠加蓝色变为绿色。

这样,就能实现移动的文字弹幕在穿越形状,或是移动的形状覆盖文字时,让形状边界成为字体颜色的即时切换边界了。

不过什么文字、口头介绍都不如实践验证最能传达这些有的没的的原理,以下是实现了我截图上颜色对比、图层遮挡关系的BAS弹幕,弹幕友人不妨复制去实验室实际运行一下,看看实际效果,并试着调整相关颜色、定位、透明度参数,看看究竟会是什么效果。

def text TOP {
content = "测试弹幕"
fontSize = 20%
x = 50%
y = 50%
alpha = 0.5
color = 0xFFFF00
textShadow = 0
bold = 1
anchorX = 0.5
anchorY = 0.5
zIndex = 3
duration = 5s
}
def text MIDDLE {
content = "█"
fontSize = 50%
x = 40%
y = 50%
alpha = 1
color = 0xcca0FF
textShadow = 0
anchorX = 1
anchorY = 0.5
zIndex = 2
duration = 5s
}
def text BOTTOM {
content = "测试弹幕"
fontSize = 20%
x = 50%
y = 50%
alpha = 1
color = 0x00F9FF
textShadow = 0
strokeWidth = 0
anchorX = 0.5
anchorY = 0.5
zIndex = 1
duration = 5s
}
def text BG {
content = "█"
fontSize = 500%
x = 60%
y = 50%
alpha =1
color = 0xCCFFFF
textShadow = 0
anchorX = 0.5
anchorY = 0.5
zIndex = 0
duration = 5s
}
set MIDDLE{ x=120% }5s

总之,在制作这类弹幕时,由于涉及颜色叠加,因此文字颜色的选择是非常硬核的,比如互补色叠加后是灰色,而相邻色叠加会取中间色。这里我推荐查询色盘等美术色彩资料确定合适的颜色。此外,我还简单找了个互补色对照表,可以简单参考。

次日更新:奏奏在群里发了一个渐变色差分的在线工具,发现在step=1时完全可以看成两种颜色1:1混色的结果,也就是本文说的底层alpha=1叠加顶层alpha=0.5的混色效果,是个很方便直观的试色工具,所以也把那个网站分享在这里了:https://photokit.com/colors/color-gradient/?lang=zh

以下是两个混色范例:

经典相邻色,黄+蓝=绿
互补色,红+绿=灰

如果多花点时间打磨一下配色关系,就可以实现更还原的“蒙板”效果,即只有2个颜色的交错效果。但是因为混色原理会降低颜色纯度,而为了调整成只有两种颜色,大色块颜色需要调整成跟混色后的字体颜色相同,所以整体画面的颜色会显得不那么纯净,有点脏脏的感觉,而且明暗对比度会随之下降。因此如果不是非要追求这种二色蒙板效果,建议还是不要使用这种配色。以下是一个bas范例:

def text TOP {
content = "测试弹幕"
fontSize = 20%
x = 50%
y = 50%
alpha = 0.5
color = 0xFFFF00
textShadow = 0
bold = 1
anchorX = 0.5
anchorY = 0.5
zIndex = 3
duration = 5s
}
def text MIDDLE {
content = "█"
fontSize = 50%
x = 40%
y = 51.3%
alpha = 1
color = 0xB49480
textShadow = 0
anchorX = 1
anchorY = 1
zIndex = 2
duration = 5s
}
def text BOTTOM {
content = "测试弹幕"
fontSize = 20%
x = 50%
y = 50%
alpha = 1
color = 0x6929ff
textShadow = 0
strokeWidth = 0
anchorX = 0.5
anchorY = 0.5
zIndex = 1
duration = 5s
}
def text BG {
content = "█"
fontSize = 500%
x = 60%
y = 50%
alpha =1
color = 0xdaca40
textShadow = 0
anchorX = 0.5
anchorY = 0.5
zIndex = 0
duration = 5s
}
set MIDDLE{ x=120% }5s

效果如图:

这几个颜色的选取是有先后顺序的:

  1. 先用合适的上下层文字颜色叠加出组合文字的视觉颜色A,这里可以通过上面那个渐变色网站输入两层文字的色号,获得混色后A的色号;
  2. 把A作为中层插入元素的颜色,与上层字体的颜色叠加,成为切换后的文字视觉颜色B,此时同样可以在渐变色网站输入A和上层颜色,获得B的色号;
  3. 把颜色B设定为最底层背景颜色;
  4. 至此四层图层的颜色全部定义完成,虽然看起来只有两个颜色,但其实内外层字的颜色是叠加色,而插入层和背景色的颜色是实际的纯色。

这样就能让外部未切换文字的颜色与插入层颜色相同,而切换后文字的颜色与外部背景颜色相同,也就是实现了双色“蒙板”效果。