step・smoothstep


title: "step・smoothstep" description: "step関数とsmoothstep関数の使い方を学びます。鋭いエッジと滑らかな遷移の作り方を理解します。" chapter: "03-shaping" order: 1 challenge: description: "smoothstep を使って、画面の中央に幅のあるソフトな縦のストライプを描いてください。ストライプは中央で白く、端に向かってなめらかに暗くなるようにします。" hints:

  • "左側のエッジは smoothstep(0.3, 0.4, uv.x) で作れます。"
  • "右側のエッジは 1.0 - smoothstep(0.6, 0.7, uv.x) で作れます。"
  • "両方を掛け合わせます: float stripe = smoothstep(0.3, 0.4, uv.x) * (1.0 - smoothstep(0.6, 0.7, uv.x));"

step・smoothstep

シェーピング関数とは

シェーダーでは、ある値を別の値に変換する関数をシェーピング関数と呼びます。入力の値を「整形」して、望み通りの出力を得るための道具です。

最も基本的なシェーピング関数が stepsmoothstep です。

step関数

float result = step(edge, x);
  • x < edge0.0
  • x >= edge1.0

つまり、しきい値で0か1に切り替える関数です。

// 画面の左半分は黒、右半分は白
float color = step(0.5, uv.x);

step は if 文の代わりに使えます。シェーダーでは条件分岐よりも数学的な関数を使う方が効率的です。

smoothstep関数

float result = smoothstep(edge0, edge1, x);
  • x < edge00.0
  • x > edge11.0
  • その間はなめらかなS字カーブ

step が瞬時に切り替わるのに対し、smoothstepなめらかに遷移します。

// なめらかな遷移(0.4 ~ 0.6 の区間でグラデーション)
float color = smoothstep(0.4, 0.6, uv.x);

edge0edge1 の差が遷移の幅を決めます。差が小さいほど急な遷移、大きいほどなだらかな遷移になります。

step と smoothstep の比較

右のプレビューでは、上半分に step、下半分に smoothstep を表示しています。境界の違いを観察してみてください。

反転と組み合わせ

1.0 - step(...) で結果を反転できます:

// 右半分が黒、左半分が白(反転)
float inverted = 1.0 - step(0.5, uv.x);

2つの step を組み合わせると帯(バンド)が作れます:

// 0.3 ~ 0.7 の範囲が白い帯
float band = step(0.3, uv.x) - step(0.7, uv.x);

なぜ step を使うのか

GPUは条件分岐(if文)が苦手です。すべてのピクセルが同じ命令を実行するのが理想的で、分岐があると性能が低下する場合があります。

stepsmoothstep を使えば、分岐なしで同じ結果が得られます:

// if文による分岐(避けたい)
if (uv.x > 0.5) color = 1.0;
else color = 0.0;

// step による同等の処理(推奨)
float color = step(0.5, uv.x);

まとめ

  • step(edge, x) — しきい値で 0/1 を切り替え
  • smoothstep(edge0, edge1, x) — なめらかな遷移
  • 組み合わせてバンドやストライプを作れる
  • if文より step/smoothstep の方がGPUフレンドリー