GLSL利用SDF进行矩形绘制公式推导

简单记录一下关于SDF绘制矩形的公式推导,因为我们在iq的SDF代码中,给的直接是最后的推导结果,对它是怎么得来的,还是有点困惑。

//这是利用sdf绘制矩形
float sdBox( in vec2 p, in vec2 b )
{
    vec2 d = abs(p)-b;
    return length(max(d,0.0)) + min(max(d.x,d.y),0.0); // 突然看到这个代码,还是挺疑惑的,为什么就可以得到矩形的区域呢?
}

推导一下

1)常规计算(这种会导致GPU运行效率下降)
\begin{array}{*{20}{l}}
{{ \left( 1 \left) \text{ }d=\mathop{{P}}\nolimits_{{y}}-R\mathop{{}}\nolimits_{{y}}\right. \right. }}\
{ \left( 2 \left) d=\mathop{{P}}\nolimits_{{x}}-R\mathop{{}}\nolimits_{{x}}\right. \right. }\
{ \left( 3 \left) d\text{ }=\text{ }\sqrt{{ \left( \mathop{{P}}\nolimits_{{x}}-R\mathop{{}}\nolimits_{{x}} \left) \mathop{{}}\nolimits^{{2}}+ \left( \mathop{{P}}\nolimits_{{y}}-R\mathop{{}}\nolimits_{{y}} \left) \mathop{{}}\nolimits^{{2}}\right. \right. \right. \right. }}\right. \right. }
\end{array}
2)机智的办法,就是说用一个公式同时满足上述三个条件。

from numpy import *
d = sqrt(pow(max(Px-Rx,0), 2) + pow(max(Py-Ry, 0), 2))

当然用向量表示出来就是:

d = length(max(abs(P) - R), 0);

其中abs(P)表示将平面上的点转换到其第一象限所对应的点。

存在的问题

上述公式虽然可以在一定程度上绘制出矩形,但是对于矩形里面的点,我们其实是没有照顾到的,如果我们要对矩形里面进行一些操作,那就是一件非常糟糕的事情。所以我们还需要获取到矩形里面的距离值。我们知道,上述公式得到的 d>=0,也就是说,上述公式考虑的都是矩形之外的点。如果要考虑矩形内部的点,那势必d<0。所以我们需要对公式进行一点改进。

q = abs(P) - R;
d = length(max(q, 0.0)) + min(max(q.x, q.y), 0.0);

我们可以看到,上述公式我们添加了 min(max(q.x, q.y), 0.0) 这个公式,直白来说,就是我们需要找到q.x(<0)和q.y(<0)的最大值,那么久越靠近矩形边缘,越靠近矩形中心,那么p.x和p.y的值就越小。

应用

所以我们需要对矩形内部边缘添加一些模糊的话,会很有效果。

posted @ 2023-09-14 21:41  九叶草  阅读(82)  评论(0编辑  收藏  举报