0

I have this original png file:

enter image description here

And I am applying this shader from the GDQuest shader tutorial in the Sprite Node:

As the png is cut at the edge of the image I have to enlarge the Region, but then the pixels that are on the edge are duplicated instead of drawing the outline, as you can see here:

enter image description here

If I use a png file with 1 transparent pixel around:

enter image description here

Then the shader works well:

enter image description here

Of course, the obvious solution is adding an extra transparent border to all my image assets, but this is not always possible, or easy. And also I would like to learn, to see what is the cause and how to solve it.

fguillen
  • 36,125
  • 23
  • 149
  • 210
  • I have been debugging again and it looks like it is a behavior from the Region functionality: https://github.com/godotengine/godot/issues/6957 it looks like a bug for me, but I am not sure if they will like to fix it. Also: https://godotengine.org/qa/126487/sprite-region-enabled-keeps-drawing-extra-border-frames – fguillen Feb 16 '23 at 13:46

1 Answers1

0

After doing some debug I have confirmed that the problem is not in the shader but how the Sprite Region is behaving in case the edges of the Texture contain colored pixels:

I have to check in the shader if UV is out of the limits (0 and 1).

This is the code that is working for me:

shader_type canvas_item;

uniform vec4 line_color : hint_color = vec4(1.0);
uniform float line_thickness : hint_range(0, 10) = 1.0;

const vec2 OFFSETS[8] = {
    vec2(-1, -1), vec2(-1, 0), vec2(-1, 1), vec2(0, -1), vec2(0, 1), 
    vec2(1, -1), vec2(1, 0), vec2(1, 1)
};

void fragment() {
    vec2 size = TEXTURE_PIXEL_SIZE * line_thickness;
    float outline_alpha = 0.0;
    vec4 color = vec4(0);
    
    for (int i = 0; i < OFFSETS.length(); i++) {
        vec2 coordinate_offset = UV + size * OFFSETS[i];
        
        if(coordinate_offset.x > 1.0 || coordinate_offset.x < 0.0 || coordinate_offset.y > 1.0 || coordinate_offset.y < 0.0) {
        } else {
            outline_alpha += texture(TEXTURE, coordinate_offset).a;
        }
    }
    
    outline_alpha = min(outline_alpha, 1.0);
    
    if(UV.x > 1.0 || UV.x < 0.0 || UV.y > 1.0 || UV.y < 0.0) {
        color = vec4(0)
    } else {
        color = texture(TEXTURE, UV);
    } 
    
    COLOR = mix(color, line_color, outline_alpha - color.a);
}

It looks very ugly, if you have any code edition suggestions, please go ahead and edit my code :). Or suggest it somehow.

fguillen
  • 36,125
  • 23
  • 149
  • 210