SDF矩形(附圆角)公式推导
矩形
一般情况下,我们会使用(top_left, top_bottom), (width, height)
来定义一个矩形,但是对于SDF而言,使用(centerX, centerY), (HalfSizeX, HalfSizeY)
会更方便一些。
假设一个矩形,我们先定义原点在(0, 0)
,那图像如下:
记住要计算的内容:点与形状最近边缘之间的距离。
那么会出现两种情况,当要计算矩形内点 与 矩形最近边缘的距离时,都是一致的:
找到最近的边缘,然后做垂线就可以找到。A,B,C点皆是如此。
但是对于形状外的点,情况就有些不同:
对于AB点来说,情况是一致的,找到最近的边缘,然后就可以得到距离了。
但是我们发现,对于C,D点,矩形内点与矩形最近边缘的距离其实是到角点E
的距离。所以当计算矩形SDF时候,要考虑这种特殊情况。在第一象限的时候,代码如下:
float sdf_rect(vec2 point, vec2 half_size) {
point = abs(point);
// 计算每个点到两个边的距离
float x_dist = point.x - half_size.x;
float y_dist = point.y - half_size.y;
// 如果一正一负,或者全是负数
// 则可以直接取max(x_dist, y_dist)作为对应点的SDF值
// distance to corner
float c_dist = length(point - half_size); // 求一下到corner的距离
// 如果都为正数,说明是C、D点的情况,则要返回到corner的距离
float res = x_dist > 0.0 && y_dist > 0.0 ?
c_dist :
max(x_dist, y_dist);
return res;
}
那对于其他象限呢,要知道,一个矩形是对称的,所以现在假设要求的其他象限的点的SDF值,可以都映射到第一象限去求:
所以最终的代码是这样的:
float sdf_rect(vec2 point, vec2 half_size) {
point = abs(point);
// 计算每个点到两个边的距离
float x_dist = point.x - half_size.x;
float y_dist = point.y - half_size.y;
// 如果一正一负,或者全是负数
// 则可以直接取max(x_dist, y_dist)作为对应点的SDF值
// distance to corner
float c_dist = length(point - half_size); // 求一下到corner的距离
// 如果都为正数,说明是C、D点的情况,则要返回到corner的距离
float res = x_dist > 0.0 && y_dist > 0.0 ?
c_dist :
max(x_dist, y_dist);
return res;
}
进一步探讨
圆角矩形
现在的设备设计都开始讲究一个圆角矩形了,比如苹果的各种设备,我们也希望得到的矩形是一个圆角,该怎么做呢,读者可以在这里自行分析一下。
答案很简单,就是将最终的SDF值减去一个r,对的,就是这么简单。
我们知道,处在矩形边缘上的点的SDF值是0,如果把所有相同值的SDF化成一条线,则可以得到一个类似这样的等高线图。
其实问题的关键(问题的关键就是关键的问题?
标签:圆角,dist,point,float,SDF,矩形 From: https://www.cnblogs.com/curiositywang/p/18294750