提问者:小点点

计算点和矩形之间的带符号距离


我正在尝试用GLSL编写一个函数,将带符号的距离返回给一个矩形。矩形是轴对齐的。我觉得有点卡住了;我只是不知道我需要做什么来使它工作。

我想出的最好的办法是:

float sdAxisAlignedRect(vec2 uv, vec2 tl, vec2 br)
{
    // signed distances for x and y. these work fine.
    float dx = max(tl.x - uv.x, uv.x - br.x);
    float dy = max(tl.y - uv.y, uv.y - br.y);
    dx = max(0.,dx);
    dy = max(0.,dy);
    return sqrt(dx*dx+dy*dy);
}

它产生一个矩形,看起来像:

线条显示与矩形的距离。它可以正常工作,但仅适用于矩形之外的距离。矩形内部的距离是静态0.

如何使用统一公式获得矩形内的精确距离?


共1个答案

匿名用户

这个怎么样…

float sdAxisAlignedRect(vec2 uv, vec2 tl, vec2 br)
{
    vec2 d = max(tl-uv, uv-br);
    return length(max(vec2(0.0), d)) + min(0.0, max(d.x, d.y));
}

这是结果,其中绿色标记为正距离,红色标记为负距离(代码如下):

分解:

>

  • 获取x和y边框的带符号距离。u-左右-u是两个x轴距离。取这些值中的最大值给出到最近边框的带符号距离。查看d. xd.y分别显示在下图中。

    组合x和y:

    >

  • 如果两个值都是负数,则取最大值(即最接近边框)。这是通过min(0.0, max(d.x,d.y))完成的。

    如果只有一个值是正的,那就是我们想要的距离。

    如果两个值都是正数,则最近的点是一个角,在这种情况下,我们想要长度。这可以与上述情况结合使用,无论如何都取长度并确保两个值都是正数:长度(max(vec2(0.0), d)

    这两部分对方程是互斥的,即只有一部分会产生非零值,并且可以求和。

    void mainImage( out vec4 fragColor, in vec2 fragCoord )
    {
        vec2 uv = fragCoord.xy / iResolution.xy;
        uv -= 0.5;
        uv *= vec2(iResolution.x/iResolution.y,1.0);
        uv += 0.5;
        float d = sdAxisAlignedRect(uv, vec2(0.3), vec2(0.7));
        float m = 1.0 - abs(d)/0.1;
        float s = sin(d*400.0) * 0.5 + 0.5;
        fragColor = vec4(s*m*(-sign(d)*0.5+0.5),s*m*(sign(d)*0.5+0.5),0,1);
    }