1
0
Fork 0
mirror of https://github.com/Orama-Interactive/Pixelorama.git synced 2025-02-02 00:19:48 +00:00
Pixelorama/src/Shaders/OutlineInline.gdshader
Emmanouil Papadeas 2da5b1e944 Outline generation with shaders
This results in both better and faster results. Unfortunately, the shader does not work in the Web version, so we have to rely on the old method for that platform.
2022-04-22 21:11:02 +03:00

50 lines
1.4 KiB
Plaintext

// Based on https://godotshaders.com/shader/2d-outline-inline/
shader_type canvas_item;
render_mode unshaded;
uniform vec4 color : hint_color = vec4(1.0);
uniform float width : hint_range(0, 10) = 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 x = abs(i) > width ? width * sign(i) : i;
float offset;
if (pattern == 0) {
offset = width - abs(x);
} else if (pattern == 1) {
offset = floor(sqrt(pow(width + 0.5, 2) - x * x));
} else if (pattern == 2) {
offset = width;
}
for (float j = -ceil(offset); j <= ceil(offset); j++) {
float y = abs(j) > offset ? offset * sign(j) : j;
vec2 xy = uv + texture_pixel_size * vec2(x, y);
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);
}