如何以非矩形形式裁剪精灵?

发布于 2025-01-14 08:46:36 字数 543 浏览 2 评论 0原文

我正在尝试以非矩形形式切割精灵,我发现了这个 有角度的切割但是如果给出方程,有没有办法进行切割?

例如,椭圆形 (x−h)^2/a^2 + (y−k)^2/b^2=1 的方程将如下裁剪:

在此处输入图像描述
输入图片此处描述

I'm trying to cut sprites in non-rectangular forms, I found this for angled cutting but is there a way to crop if an equation is given?

for example the equation of an oval (x−h)^2/a^2 + (y−k)^2/b^2=1 would crop as such:

enter image description here
enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

第七度阳光i 2025-01-21 08:46:36

我假设您知道我们可以使用 UV 来获取坐标。

由于公式有一些参数,让我们将它们添加为制服:

uniform float a:hint_range(0.0, 1.0);
uniform float b:hint_range(0.0, 1.0);
uniform float h:hint_range(0.0, 1.0);
uniform float k:hint_range(0.0, 1.0);

我们计算我们的公式:

shader_type canvas_item;
uniform float a:hint_range(0.0, 1.0);
uniform float b:hint_range(0.0, 1.0);
uniform float h:hint_range(0.0, 1.0);
uniform float k:hint_range(0.0, 1.0);

void fragment()
{
    float r = ((UV.x - h)*(UV.x - h))/(a*a) + ((UV.y - k)*(UV.y - k))/(b*b);
    COLOR = vec4(vec3(r), 1.0);
}

这应该会产生从白色到黑色的渐变。

请记住编辑着色器参数。如果将它们保留为零,您将只能看到白色。


因此我们可以继续使用discard

shader_type canvas_item;
uniform float a:hint_range(0.0, 1.0);
uniform float b:hint_range(0.0, 1.0);
uniform float h:hint_range(0.0, 1.0);
uniform float k:hint_range(0.0, 1.0);

void fragment()
{
    float r = ((UV.x - h)*(UV.x - h))/(a*a) + ((UV.y - k)*(UV.y - k))/(b*b);
    if (r > 1.0)
    {
        discard;
    }
}

这应该会给您想要的结果。


或者,让我们使用 step 这样我们就得到了黑白结果:

shader_type canvas_item;
uniform float a:hint_range(0.0, 1.0);
uniform float b:hint_range(0.0, 1.0);
uniform float h:hint_range(0.0, 1.0);
uniform float k:hint_range(0.0, 1.0);

void fragment()
{
    float r = step(((UV.x - h)*(UV.x - h))/(a*a) + ((UV.y - k)*(UV.y - k))/(b*b), 1.0);
    COLOR = vec4(vec3(r), 1.0);
}

现在我们用它来决定在哪里输出原始纹理以及在哪里输出透明度:

shader_type canvas_item;
uniform float a:hint_range(0.0, 1.0);
uniform float b:hint_range(0.0, 1.0);
uniform float h:hint_range(0.0, 1.0);
uniform float k:hint_range(0.0, 1.0);

void fragment()
{
    float r = step(((UV.x - h)*(UV.x - h))/(a*a) + ((UV.y - k)*(UV.y - k))/(b*b), 1.0);
    COLOR = mix(vec4(0.0), texture(TEXTURE, UV), r);
}

这也应该给你你的结果想。


附录:我没有注意到在你的例子中你已经按整个像素剪切了图像。您可以这样做:

shader_type canvas_item;
uniform float a:hint_range(0.0, 1.0);
uniform float b:hint_range(0.0, 1.0);
uniform float h:hint_range(0.0, 1.0);
uniform float k:hint_range(0.0, 1.0);

void fragment()
{
    vec2 uv = floor(UV / TEXTURE_PIXEL_SIZE) * TEXTURE_PIXEL_SIZE;
    float r = step(((uv.x - h)*(uv.x - h))/(a*a) + ((uv.y - k)*(uv.y - k))/(b*b), 1.0);
    COLOR = mix(vec4(0.0), texture(TEXTURE, UV), r);
}

在这里,我已经将方程的坐标用于以与纹理像素大小相匹配的离散步骤前进。

I'll asume you are aware that we can work with UV for the coordinates.

Since the formula has some parameters, let us add them as uniforms:

uniform float a:hint_range(0.0, 1.0);
uniform float b:hint_range(0.0, 1.0);
uniform float h:hint_range(0.0, 1.0);
uniform float k:hint_range(0.0, 1.0);

And we compute our formula:

shader_type canvas_item;
uniform float a:hint_range(0.0, 1.0);
uniform float b:hint_range(0.0, 1.0);
uniform float h:hint_range(0.0, 1.0);
uniform float k:hint_range(0.0, 1.0);

void fragment()
{
    float r = ((UV.x - h)*(UV.x - h))/(a*a) + ((UV.y - k)*(UV.y - k))/(b*b);
    COLOR = vec4(vec3(r), 1.0);
}

This should result in a gradient from white to black.

Remember to edit the shader parameters. If you leave them at zero you will see only white.


So we can go ahead and use discard:

shader_type canvas_item;
uniform float a:hint_range(0.0, 1.0);
uniform float b:hint_range(0.0, 1.0);
uniform float h:hint_range(0.0, 1.0);
uniform float k:hint_range(0.0, 1.0);

void fragment()
{
    float r = ((UV.x - h)*(UV.x - h))/(a*a) + ((UV.y - k)*(UV.y - k))/(b*b);
    if (r > 1.0)
    {
        discard;
    }
}

This should give you the result you want.


Alternatively, let us use step so we get a black and white result:

shader_type canvas_item;
uniform float a:hint_range(0.0, 1.0);
uniform float b:hint_range(0.0, 1.0);
uniform float h:hint_range(0.0, 1.0);
uniform float k:hint_range(0.0, 1.0);

void fragment()
{
    float r = step(((UV.x - h)*(UV.x - h))/(a*a) + ((UV.y - k)*(UV.y - k))/(b*b), 1.0);
    COLOR = vec4(vec3(r), 1.0);
}

And now we use that to decide where to output the original texture and where to output transparency:

shader_type canvas_item;
uniform float a:hint_range(0.0, 1.0);
uniform float b:hint_range(0.0, 1.0);
uniform float h:hint_range(0.0, 1.0);
uniform float k:hint_range(0.0, 1.0);

void fragment()
{
    float r = step(((UV.x - h)*(UV.x - h))/(a*a) + ((UV.y - k)*(UV.y - k))/(b*b), 1.0);
    COLOR = mix(vec4(0.0), texture(TEXTURE, UV), r);
}

And this should also give you the result you want.


Addendum: I had not payed attention that in your example you had cut the image at whole pixels. You can do that like this:

shader_type canvas_item;
uniform float a:hint_range(0.0, 1.0);
uniform float b:hint_range(0.0, 1.0);
uniform float h:hint_range(0.0, 1.0);
uniform float k:hint_range(0.0, 1.0);

void fragment()
{
    vec2 uv = floor(UV / TEXTURE_PIXEL_SIZE) * TEXTURE_PIXEL_SIZE;
    float r = step(((uv.x - h)*(uv.x - h))/(a*a) + ((uv.y - k)*(uv.y - k))/(b*b), 1.0);
    COLOR = mix(vec4(0.0), texture(TEXTURE, UV), r);
}

Here I had made the coordinates uses for the equation advance at discrete steps that match the size of the pixels of the texture.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文