glsl中的带边框的圆角矩形
Bordered rounded rectangle in glsl
你好,我正在尝试获得一个快速的圆角矩形 glsl 着色器,但我只能使用此函数为填充的矩形做到这一点 (https://github.com/marklundin/glsl-sdf-primitives/blob/master/udRoundBox.glsl):
float udRoundBox( vec3 p, vec3 b, float r )
{
return length(max(abs(p)-b,0.0))-r;
}
我一直在努力寻找一个带有边框而不是填充的版本,甚至试图想出一个版本,但没有成功。有人对此有解决方案吗?
由于您使用的是带符号的距离函数,最简单的方法可能是使用减法运算符从初始的圆框中减去一个较小的圆框。
看起来像这样:
// unsigned round box
float udRoundBox( vec3 p, vec3 b, float r )
{
return length(max(abs(p)-b,0.0))-r;
}
// substracts shape d1 from shape d2
float opS( float d1, float d2 )
{
return max(-d1,d2);
}
// to get the border of a udRoundBox, simply substract a smaller udRoundBox !
float udRoundBoxBorder( vec3 p, vec3 b, float r, float borderFactor )
{
return opS(udRoundBox(p, b*borderFactor, r), udRoundBox(p, b, r));
}
borderFactor
需要是[0:1]
中的值,越大边框越小。
这是一个 ShaderToy 示例来证明这一点:
使用第二个盒子来挤压第一个盒子是个坏主意,因为它会导致性能下降。您不是计算单个对象,而是计算两个对象。 SDF 的性能通常受您在距离函数中添加的对象数量的限制;这就是 mod/floor 函数在制作 SDF 时如此有用的原因。您可以(几乎)不增加成本地添加无限数量的对象。
这里使用box signed exact function http://iquilezles.org/www/articles/distfunctions/distfunctions.htm如果你想自己写,试着想办法得到box上的最近点,然后return到这个的距离点.
你可以通过距离减去一个项得到一个圆角框,但你已经弄明白了(你的例子中的 r)。
您可以使用距离的绝对值来获得边框。 Abs(de) 基本上会将物体内部(负距离)设为正,从而将其移除。这使对象具有 "empty" 边框。如果你想让边框变大,只需减去另一个项来增加它的大小,就像你做一个圆角框一样。
这适用于任何形状,只要距离估计正确即可。 SDF 非常适合这样的小技巧。
我想这就是您要搜索的内容...
//---------------------------------------------------------
// draw rectangle frame with rounded edges
//---------------------------------------------------------
float roundedFrame (vec2 pos, vec2 size, float radius, float thickness)
{
float d = length(max(abs(uv - pos),size) - size) - radius;
return smoothstep(0.55, 0.45, abs(d / thickness) * 5.0);
}
看看我的 shadertoy 示例 https://www.shadertoy.com/view/MssyRN
.
你好,我正在尝试获得一个快速的圆角矩形 glsl 着色器,但我只能使用此函数为填充的矩形做到这一点 (https://github.com/marklundin/glsl-sdf-primitives/blob/master/udRoundBox.glsl):
float udRoundBox( vec3 p, vec3 b, float r )
{
return length(max(abs(p)-b,0.0))-r;
}
我一直在努力寻找一个带有边框而不是填充的版本,甚至试图想出一个版本,但没有成功。有人对此有解决方案吗?
由于您使用的是带符号的距离函数,最简单的方法可能是使用减法运算符从初始的圆框中减去一个较小的圆框。
看起来像这样:
// unsigned round box
float udRoundBox( vec3 p, vec3 b, float r )
{
return length(max(abs(p)-b,0.0))-r;
}
// substracts shape d1 from shape d2
float opS( float d1, float d2 )
{
return max(-d1,d2);
}
// to get the border of a udRoundBox, simply substract a smaller udRoundBox !
float udRoundBoxBorder( vec3 p, vec3 b, float r, float borderFactor )
{
return opS(udRoundBox(p, b*borderFactor, r), udRoundBox(p, b, r));
}
borderFactor
需要是[0:1]
中的值,越大边框越小。
这是一个 ShaderToy 示例来证明这一点:
使用第二个盒子来挤压第一个盒子是个坏主意,因为它会导致性能下降。您不是计算单个对象,而是计算两个对象。 SDF 的性能通常受您在距离函数中添加的对象数量的限制;这就是 mod/floor 函数在制作 SDF 时如此有用的原因。您可以(几乎)不增加成本地添加无限数量的对象。
这里使用box signed exact function http://iquilezles.org/www/articles/distfunctions/distfunctions.htm如果你想自己写,试着想办法得到box上的最近点,然后return到这个的距离点.
你可以通过距离减去一个项得到一个圆角框,但你已经弄明白了(你的例子中的 r)。
您可以使用距离的绝对值来获得边框。 Abs(de) 基本上会将物体内部(负距离)设为正,从而将其移除。这使对象具有 "empty" 边框。如果你想让边框变大,只需减去另一个项来增加它的大小,就像你做一个圆角框一样。
这适用于任何形状,只要距离估计正确即可。 SDF 非常适合这样的小技巧。
我想这就是您要搜索的内容...
//---------------------------------------------------------
// draw rectangle frame with rounded edges
//---------------------------------------------------------
float roundedFrame (vec2 pos, vec2 size, float radius, float thickness)
{
float d = length(max(abs(uv - pos),size) - size) - radius;
return smoothstep(0.55, 0.45, abs(d / thickness) * 5.0);
}
看看我的 shadertoy 示例 https://www.shadertoy.com/view/MssyRN