SDFs
03.28.2024I’m having a realization: When working with SDFs, you at some point convert from an SDF to a mask. It’s often implicit, but the second you do it, you can no longer perform operations across that boundary. ie. you cannot do mask - sdf and expect to get a mask or an sdf - it’ll end up being a weird combination of the two (that may or may not be useful to you).
Example
Say I want to draw a rectangle’s border. Drawing a rectangle is easy:
float
sdf_box(vec2 pos, vec2 center, vec2 half_dim)
{
vec2 p = pos - center;
vec2 pp = abs(p) - half_dim;
float d = length(max(pp, 0.0)) + min(max(pp.x, pp.y), 0.0);
return d;
}
void
mainImage( out vec4 fragColor, in vec2 fragCoord)
{
vec2 uv = fragCoord/iResolution.x;
float d = sdf_box(fragCoord, vec2(600, 325), vec2(100, 100));
if (d < 0) fragColor = vec4(1.0);
fragColor = vec4(0.0,0.0,0.0,1.0);
}
d
in this case, is an sdf - that is, d contains a value that denotes a distance from the edge of the box, with negative values being inside the box and positive values being outside.
We can turn d
into a mask by inverting and clamping it. ie.
float box_mask = clamp(-1 * d, 0.0, 1.0);
fragColor = float4(box_mask, box_mask, box_mask, 1.0);
Now I can use this information to more easily construct my box outline.
void
mainImage( out vec4 fragColor, in vec2 fragCoord)
{
vec2 c = vec2(600, 325);
vec2 hd = vec2(100,100);
float ot = 10.0;
float outer_d = sdf_box(fragCoord, c, hd);
float outer_box_mask = clamp(-1.0 * outer_d, 0.0, 1.0);
float inner_d = sdf_box(fragCoord, c, hd - vec2(ot,ot));
float inner_box_mask = clamp(-1.0 * inner_d, 0.0, 1.0);
float outline_mask = outer_box_mask - inner_box_mask;
fragColor = vec4(outline_mask, outline_mask, outline_mask, 1.0);
}