1
0
Fork 0
mirror of https://github.com/Orama-Interactive/Pixelorama.git synced 2025-02-01 16:09:49 +00:00
Pixelorama/src/Shaders/Effects/OutlineInline.gdshader

48 lines
1.3 KiB
Plaintext

// Based on https://godotshaders.com/shader/2d-outline-inline/
shader_type canvas_item;
render_mode unshaded;
uniform vec4 color : source_color = vec4(1.0);
uniform float width : hint_range(0, 10, 1) = 1.0;
uniform int pattern : hint_range(0, 2) = 0; // diamond, circle, square
uniform bool inside = false;
uniform sampler2D selection;
bool has_contrary_neighbour(vec2 uv, vec2 texture_pixel_size, sampler2D tex) {
for (float i = -ceil(width); i <= ceil(width); i++) {
float offset;
if (pattern == 0) {
offset = width - abs(i);
} else if (pattern == 1) {
offset = floor(sqrt(pow(width + 0.5, 2) - i * i));
} else if (pattern == 2) {
offset = width;
}
for (float j = -ceil(offset); j <= ceil(offset); j++) {
vec2 xy = uv + texture_pixel_size * vec2(i, j);
if ((xy != clamp(xy, vec2(0.0), vec2(1.0)) || texture(tex, xy).a == 0.0) == inside) {
return true;
}
}
}
return false;
}
void fragment() {
vec4 original_color = texture(TEXTURE, UV);
vec4 selection_color = texture(selection, UV);
vec4 output = texture(TEXTURE, UV);
if ((output.a > 0.0) == inside && has_contrary_neighbour(UV, TEXTURE_PIXEL_SIZE, TEXTURE)) {
output.rgb = inside ? mix(output.rgb, color.rgb, color.a) : color.rgb;
output.a += (1.0 - output.a) * color.a;
}
COLOR = mix(original_color, output, selection_color.a);
}