矩形


title: "矩形" description: "abs関数を使って矩形のSDFを構築する方法と、角丸矩形の作り方を学びます。" chapter: "04-shapes" order: 3 challenge: description: "画面中央に角丸矩形を描いてください。角の丸み(radius)を 0.05 に設定し、矩形のサイズは横 0.4、縦 0.25 にしましょう。" hints:

  • "角丸矩形は sdBox の結果から角丸の半径を引くことで作れます。"
  • "sdBox の引数 b を (0.4 - 0.05, 0.25 - 0.05) のように角丸分だけ小さくし、結果から 0.05 を引きます。"
  • "float d = sdBox(p, vec2(0.35, 0.20)) - 0.05; で角丸矩形になります。"

矩形

abs()を使った矩形のSDF

矩形のSDFは、abs() 関数を使って構築します。考え方は:

  1. 座標の絶対値を取る(対称性を利用)
  2. 矩形の半分のサイズを引く
  3. 外側の距離を計算する
float sdBox(vec2 p, vec2 b) {
    vec2 d = abs(p) - b;
    return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0);
}

この関数を分解して理解しましょう:

ステップ1: abs(p) - b

abs(p) で座標を第1象限に折りたたみます。矩形は対称なので、4つの象限すべてを同じように扱えます。そこから矩形の半サイズ b を引きます。

ステップ2: 外側の距離

length(max(d, 0.0)) は矩形の外側の距離を正しく計算します。max(d, 0.0) で負の成分をゼロにクランプし、外側の距離だけを残します。

ステップ3: 内側の距離

min(max(d.x, d.y), 0.0) は矩形の内側の距離(負の値)を返します。

矩形を描く

vec2 p = uv - vec2(0.5);
p.x *= u_resolution.x / u_resolution.y;

float d = sdBox(p, vec2(0.3, 0.2));
float box = smoothstep(0.005, 0.0, d);

角丸矩形

角丸矩形は驚くほど簡単に作れます。SDFの結果から角丸の半径を引くだけです:

float roundRadius = 0.05;
// 矩形サイズを角丸分だけ小さくする
float d = sdBox(p, vec2(0.3 - roundRadius, 0.2 - roundRadius)) - roundRadius;

SDFから定数を引くと、図形が均一に膨張します。これは等距離面のオフセットと同じで、角が自然に丸くなります。

まとめ

  • 矩形のSDFは abs() を使って対称性を利用する
  • length(max(d, 0.0)) + min(max(d.x, d.y), 0.0) で正確な距離が得られる
  • SDFから定数を引くだけで角丸矩形が作れる