【问题标题】:Calculate signed distance between point and rectangle计算点和矩形之间的有符号距离
【发布时间】:2015-08-13 05:36:13
【问题描述】:

我正在尝试在 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.

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

【问题讨论】:

    标签: geometry glsl shader euclidean-distance


    【解决方案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));
    }
    

    这是result,其中绿色表示正距离,红色表示负距离(代码如下):


    细分:

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

    2. 结合 x 和 y:

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

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

      3. 如果两个值都是正数,则最近的点是角,在这种情况下,我们需要长度。这可以与上述情况相结合,无论如何取长度并确保两个值都是正数:length(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);
    }
    

    【讨论】:

    • 太棒了!完美地完成了这项工作。
    • @jozxyqk 你是怎么想到这个功能的?
    • @v.shashenko 真的是反复试验。我已经更新了答案以更详细地介绍。
    猜你喜欢
    • 1970-01-01
    • 2018-12-02
    • 2017-05-28
    • 2023-03-25
    • 2021-10-25
    • 2014-11-29
    • 2020-03-13
    • 2017-02-21
    • 2014-05-24
    相关资源
    最近更新 更多