#version 300 es
precision highp float;
in vec2 v_texCoord;
uniform sampler2D sTexture;
uniform sampler2D sPortraitTexture;
uniform highp vec2 inputSize;
layout(location = 0) out vec4 outColor;
float sdCircle(in vec2 p, in float r) {
return length(p)-r;
}
void main() {
float effectValue = 0.4;
vec2 uv = v_texCoord;
vec2 d = 1.0 / inputSize;
float scale = (inputSize.x + inputSize.y)/1080.0;
float kernel = floor(20.0 * scale * effectValue);
vec4 maxCol = vec4(0.0);
vec4 mask = texture(sPortraitTexture, uv);
for(float x = -kernel;x<kernel;x++) {
for(float y = -kernel;y<kernel;y++) {
vec2 xy = vec2(x,y)/kernel;
if(sdCircle(xy, 0.5 + effectValue * 0.2) < 0.0) {
vec4 col = texture(sTexture, uv + d * vec2(x,y));
maxCol = max(maxCol, col * mask.a);
}
}
}
outColor = maxCol;
}
有了光斑效果和抠出来的人像,可以使用 Blend 滤镜来验证一波:
//Blend
#version 300 es
precision highp float;
in vec2 v_texCoord;
uniform sampler2D sTexture;//做完光斑效果后的图像
uniform sampler2D sPortraitTexture;//mask 分割出来的人像
layout(location = 0) out vec4 outColor;
void main() {
vec4 portraitCol = texture(sPortraitTexture, v_texCoord);
vec4 srcCol = texture(sTexture, v_texCoord);
outColor = mix(srcCol, portraitCol, portraitCol.a);
}
效果如下:
由2个原因导致的这个问题,一是算法抠图精确度不足,人像没有扣干净;二是融合的时候没有 alpha 预乘导致半透明的边缘发黑。针对这两个原因优化下我们的 blend shader :
#version 300 es
precision highp float;
in vec2 v_texCoord;
uniform sampler2D sTexture;//做完光斑和模糊效果后的图像
uniform sampler2D sPortraitTexture;/mask 分割出来的人像
layout(location = 0) out vec4 outColor;
void main() {
vec4 portraitCol = texture(sPortraitTexture, v_texCoord);
vec4 srcCol = texture(sTexture, v_texCoord);
srcCol *= srcCol.a;// alpha 预乘
portraitCol *= portraitCol.a;// alpha 预乘
outColor = mix(srcCol, portraitCol, portraitCol.a);
outColor.rgb /= max(0.000001, outColor.a);
}
来看最后的效果: