how to increase the texture region without repeating the border pixels?
Asked Answered
S

5

0

I want to create a shader outline for a sprite and for that I want to expand the region around the sprite so there is more white space.

I know there is a region option for Sprite2D but that one repeats the border pixels
godot region

I tried to play around the rect values and the texture settings (both Filter and Repeat) but I could never just get rid of the repeated pixels. Am I missing something?

Stingo answered 18/4, 2023 at 8:58 Comment(0)
T
0

Stingo You need to check UV. If UV is in range 0-1, the pixel is "inside" the image, otherwise it's the pixel you want to "hide" by setting its alpha to 0.

if(UV.x < 0.0 || UV.x > 1.0 || UV.y < 0.0 || UV.y > 1.0){
	COLOR.a = 0.0;
}

However we don't want to do it like that in a shader because it involves code branching. And this ties in with your previous question 😉
Instead we do this:

COLOR.a = step(UV.x, 1.0) * step(0.0, UV.x) * step(UV.y, 1.0) * step(0.0, UV.y);
Tain answered 18/4, 2023 at 10:23 Comment(0)
C
0

You can do this in a shader with two function calls. I think this is the most optimized.

const vec2 bottomLeft = vec2(0.0, 0.0);
const vec2 topRight = vec2(1.0, 1.0);

float withinTexture(vec2 uv) {
    vec2 within = step(bottomLeft, uv) - step(topRight, uv);
    return within.x * within.y;
}

1.0 is true and 0.0 is false.

Cape answered 18/4, 2023 at 10:29 Comment(0)
S
0

Thanks for the answers!

Using the alpha values of the current pixel is a really good solution. Although if someone else is reading this: I think the easiest solution is to use an AtlasTexture and give it a single texture. Then you don't even need to code anything.

Stingo answered 18/4, 2023 at 10:38 Comment(0)
T
0

Stingo Not a good idea to pull in all the atlas overhead just to mask out the texture. If you're doing the outline around the sprite you'll have to use a shader anyway.

Tain answered 18/4, 2023 at 10:48 Comment(0)
T
0

Cape
Just for fun, here's the least expensive way I could think of:

COLOR.a = 1.0 - length(floor(UV));

On the second thought maybe it's not least expensive but it certainly is the shortest.
Here's the one that might actually be though:

COLOR.a = float(!any(bvec2(floor(UV))));

EDIT: Missed the obvious one. This is probably the fastest way:

COLOR.a = 1.0 - dot(floor(UV), floor(UV));

Double call to floor will be optimized by the compiler. I didn't want to use a temp variable so it stays an oneliner.
Sorry, got a little bit obsessed 😃.

To avoid confusion - all of the methods suggested in this thread are ok to use.

Tain answered 18/4, 2023 at 12:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.