sketch教程:有趣的轮廓蒙版Alpha Mask
mask蒙版在设计软件中是个很常见的功能,它是在想要显示的图层对象上加一层遮罩蒙版,然后只显示遮罩部分,或者说显示两者重叠的部分。显示的透明度来自于蒙版对应的透明度。这种蒙版就是最常见的透明度蒙版,英文Alpha Mask。
介绍
一般来说,透明度蒙版已经足够用了。不过sketch提供了另外一种叫做轮廓蒙版的东西,英文Outline Mask。它的特点如下:
- 蒙版本身透明度视作100%,不会像透明度蒙版那样可以设置;
- 蒙版内容区域也视作节点轮廓有内容,哪怕是没有填充色的空矢量;
- 矢量的外描边、图层的阴影等会扩大原本轮廓区域的忽略掉蒙版作用;
- 超过被遮罩对象的蒙版区域,会按原本内容显示,不像透明度蒙版无效。
比如说有这样一张汽车的图片:

想要遮罩只显示汽车,无论哪种蒙版,都是在上面绘出汽车的轮廓矢量,然后应用蒙版。

如果是透明度蒙版,用一种不透明颜色填充即可,如果是轮廓蒙版,则无论填不填充都有效。

现在让我们加点需求:显示出车轮廓的时候,底部加点阴影。
当然可以直接新建图层画上阴影,但有时会因为一些原因使得只能改蒙版内容时就麻烦了。此时轮廓蒙版的第4个特点则非常好用。
将蒙版内容绘制成这样的红色:

应用轮廓蒙版:

不是很好看,笔者不是设计师,只是为了说明展示功能哈哈。
实现
看下sketch中的层级树状结构:

导入到Figma/MasterGo中:

左边是Figma,右边是MasterGo。
可以看到,Figma没有变动原始的图层结构数据,MasterGo为了实现轮廓蒙版,先是copy了一份蒙版,然后将copy作为底层内容,再将原始蒙版作为透明度蒙版应用。这样会冗余一份蒙版层级节点,修改时会有是否同步更新的小麻烦。
那么怎么在Web中实现这种轮廓蒙版功能呢(以Canvas/Webgl为例)?
首先,要收集这个作为蒙版的轮廓。蒙版可能只是一个单一图层,也可能是若干图层组成的一个复合图层,sketch中叫做组。
- 先以轮廓蒙版作为局部根节点汇总内容,即复合图层情况下的汇总;
- 如果是矢量节点,则忽略掉矢量节点的描边,填充固定用不透明色;
- 如果是其他节点,则忽略掉阴影、模糊等外围扩展,视作一个矩形矢量框填充;
- 各自应用相对于局部根节点的transform/matrix,最后得出一个轮廓汇总矢量图形。
这是我们能得到一个位图纹理,称作A。
接着,因为蒙版可能作用于nextSibling多个图层,收集后面兄弟节点的内容汇总。
- 先将轮廓蒙版内容视作普通内容渲染;
- 遍历后面兄弟节点,将原本的transform/matrix求出逆矩阵应用并渲染;
- 将这些渲染内容叠加汇总,得出纹理B。
然后,应用这个蒙版就好了,将A和B进行混合,和透明度蒙版的编写一样,结果称作C。
最后,将蒙版自身内容做底,再把C覆盖到上面即可。
这里给出个简单的shader范例,如何混合透明度:
#version 100
#ifdef GL_ES
precision mediump float;
#endif
varying vec2 v_texCoords;
uniform sampler2D u_texture1; // 纹理A即mask
uniform sampler2D u_texture2; // 纹理B即内容
uniform int mode;
void main() {
vec4 color1 = texture2D(u_texture1, v_texCoords);
vec4 color2 = texture2D(u_texture2, v_texCoords);
float a = color1.a * color2.a;
gl_FragColor = vec4(color2.rgb, a);
}