原理
- 如果当前像素点为非透明,则输出像素点上的内容。
- 如果当前像素点透明,且相邻像素不透明,则输出屏幕上的内容。
代码
背景图片先进行
- 背景图
- 缓存背景图到SCREEN_TEXTURE中
- 执行抠边代码
shader_type canvas_item;
void fragment(){
COLOR=textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0);
}
再执行抠边代码
shader_type canvas_item;
render_mode blend_mix;
uniform vec3 modulate_color = vec3(1.0, 1.0, 1.0);
uniform float modulate_alpha = 1.0;
uniform bool outline_diagonals = false; //true to extend the outline to diagonal pixels
void fragment(){
vec4 col = texture(TEXTURE, UV); //original color
if (col.a == 0.0) //might be part of where the outline should be
{
bool isOutline = false;
if (texture(TEXTURE, UV + vec2(0.0, TEXTURE_PIXEL_SIZE.y)).a != 0.0 ||
texture(TEXTURE, UV + vec2(0.0, -TEXTURE_PIXEL_SIZE.y)).a != 0.0 ||
texture(TEXTURE, UV + vec2(TEXTURE_PIXEL_SIZE.x, 0.0)).a != 0.0 ||
texture(TEXTURE, UV + vec2(-TEXTURE_PIXEL_SIZE.x, 0.0)).a != 0.0){
isOutline = true;
}
if (outline_diagonals){
if (texture(TEXTURE, UV + vec2(-TEXTURE_PIXEL_SIZE.x, TEXTURE_PIXEL_SIZE.y)).a != 0.0 ||
texture(TEXTURE, UV + vec2(-TEXTURE_PIXEL_SIZE.x, -TEXTURE_PIXEL_SIZE.y)).a != 0.0 ||
texture(TEXTURE, UV + vec2(TEXTURE_PIXEL_SIZE.x, TEXTURE_PIXEL_SIZE.y)).a != 0.0 ||
texture(TEXTURE, UV + vec2(TEXTURE_PIXEL_SIZE.x, -TEXTURE_PIXEL_SIZE.y)).a != 0.0){
isOutline = true;
}
}
if (isOutline){
col = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0).rgba; //set to background screen texture
}
}else{ //part of the original image
col = col*vec4(modulate_color, modulate_alpha) //modulate by a given amount if any
}
COLOR = col;
}
源码:
- 源码中用了两种不同的方式来使边缘透明
- 第一幅图到方案是需要边框形状,不太可取
- 第二种方案就是上面实现的方式
https://github.com/skison/Godot-Alpha-Outline-Test