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
シェーピング関数とは
シェーダーでは、ある値を別の値に変換する関数をシェーピング関数と呼びます。入力の値を「整形」して、望み通りの出力を得るための道具です。
最も基本的なシェーピング関数が step と smoothstep です。
step関数
float result = step(edge, x);
x < edge→0.0x >= edge→1.0
つまり、しきい値で0か1に切り替える関数です。
// 画面の左半分は黒、右半分は白
float color = step(0.5, uv.x);
step は if 文の代わりに使えます。シェーダーでは条件分岐よりも数学的な関数を使う方が効率的です。
smoothstep関数
float result = smoothstep(edge0, edge1, x);
x < edge0→0.0x > edge1→1.0- その間はなめらかなS字カーブ
step が瞬時に切り替わるのに対し、smoothstep はなめらかに遷移します。
// なめらかな遷移(0.4 ~ 0.6 の区間でグラデーション)
float color = smoothstep(0.4, 0.6, uv.x);
edge0 と edge1 の差が遷移の幅を決めます。差が小さいほど急な遷移、大きいほどなだらかな遷移になります。
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文)が苦手です。すべてのピクセルが同じ命令を実行するのが理想的で、分岐があると性能が低下する場合があります。
step や smoothstep を使えば、分岐なしで同じ結果が得られます:
// 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フレンドリー