71 lines
2.4 KiB
Plaintext
71 lines
2.4 KiB
Plaintext
shader_type canvas_item;
|
||
|
||
uniform float outline_thickness: hint_range(0.0, 8.0, 0.5) = 1.0;
|
||
uniform vec4 outline_color: source_color = vec4(1.0);
|
||
uniform bool high_performance_mode = true; // 高性能模式,减少采样
|
||
|
||
void vertex() {
|
||
VERTEX += (UV * 2.0 - 1.0) * outline_thickness;
|
||
}
|
||
|
||
void fragment() {
|
||
vec2 uv = UV;
|
||
vec2 texture_pixel_size = vec2(1.0) / (vec2(1.0) / TEXTURE_PIXEL_SIZE + vec2(outline_thickness * 2.0));
|
||
uv = (uv - texture_pixel_size * outline_thickness) * TEXTURE_PIXEL_SIZE / texture_pixel_size;
|
||
|
||
vec4 texture_color = vec4(0.0);
|
||
if (uv.x >= 0.0 && uv.x <= 1.0 && uv.y >= 0.0 && uv.y <= 1.0) {
|
||
texture_color = texture(TEXTURE, uv);
|
||
}
|
||
|
||
// 如果当前像素不透明,直接设置颜色
|
||
if (texture_color.a > 0.5) {
|
||
COLOR = texture_color;
|
||
} else {
|
||
// 需要计算描边
|
||
float outline_alpha = 0.0;
|
||
|
||
if (high_performance_mode) {
|
||
// 高性能模式:只检查4个主要方向
|
||
vec2 directions[4] = {
|
||
vec2(outline_thickness, 0.0),
|
||
vec2(-outline_thickness, 0.0),
|
||
vec2(0.0, outline_thickness),
|
||
vec2(0.0, -outline_thickness)
|
||
};
|
||
|
||
for (int i = 0; i < 4; i++) {
|
||
vec2 check_uv = uv + directions[i] * TEXTURE_PIXEL_SIZE;
|
||
if (check_uv.x >= 0.0 && check_uv.x <= 1.0 && check_uv.y >= 0.0 && check_uv.y <= 1.0) {
|
||
float check_alpha = texture(TEXTURE, check_uv).a;
|
||
outline_alpha = max(outline_alpha, check_alpha);
|
||
if (outline_alpha > 0.9) break; // 早期退出
|
||
}
|
||
}
|
||
} else {
|
||
// 标准模式:8方向检查
|
||
vec2 directions[8] = {
|
||
vec2(outline_thickness, 0.0), vec2(-outline_thickness, 0.0),
|
||
vec2(0.0, outline_thickness), vec2(0.0, -outline_thickness),
|
||
vec2(outline_thickness * 0.707, outline_thickness * 0.707),
|
||
vec2(-outline_thickness * 0.707, outline_thickness * 0.707),
|
||
vec2(outline_thickness * 0.707, -outline_thickness * 0.707),
|
||
vec2(-outline_thickness * 0.707, -outline_thickness * 0.707)
|
||
};
|
||
|
||
for (int i = 0; i < 8; i++) {
|
||
vec2 check_uv = uv + directions[i] * TEXTURE_PIXEL_SIZE;
|
||
if (check_uv.x >= 0.0 && check_uv.x <= 1.0 && check_uv.y >= 0.0 && check_uv.y <= 1.0) {
|
||
float check_alpha = texture(TEXTURE, check_uv).a;
|
||
outline_alpha = max(outline_alpha, check_alpha);
|
||
if (outline_alpha > 0.9) break; // 早期退出
|
||
}
|
||
}
|
||
}
|
||
|
||
// 混合颜色
|
||
float final_alpha = outline_alpha * outline_color.a;
|
||
COLOR = vec4(outline_color.rgb * final_alpha + texture_color.rgb * texture_color.a,
|
||
max(final_alpha, texture_color.a));
|
||
}
|
||
} |