smoothstep( x ) 関数と smootherstep( x ) 関数のグラフ。左端を 0、右端を 1 とする。Smoothstepは、 コンピュータグラフィックス [ 1 ] [ 2 ] 、 ビデオゲームエンジン [ 3 ] 、機械学習 [ 4 ] などで一般的に使用される、シグモイドのような 補間 およびクランプ 関数のファミリーです。
この関数は、入力x 、「左端」、「右端」の 3 つのパラメータに依存し、左端は右端よりも小さいと想定されます。関数は引数として実数 x を受け取ります。x が左端以下の場合は 0 を返し、x が右端以上の場合は 1 を返し ます。それ以外の場合は、 エルミート補間 を使用して滑らかに補間し、0 から 1 の間の値を返します。smoothstep 関数の傾きは、両端でゼロです。これは、より高度な補間 技術やコストのかかる補間技術を使用する代わりに、smoothstep を使用して各セグメントを補間する遷移のシーケンスを作成するのに便利です。
HLSL とGLSL では、smoothstep はS 1 ( x ) {\displaystyle \operatorname {S} _{1}(x)} クランプ 後の3次エルミート補間 :
スムーズステップ ( x ) = S 1 ( x ) = { 0 、 x ≤ 0 3 x 2 − 2 x 3 、 0 ≤ x ≤ 1 1 、 1 ≤ x {\displaystyle \operatorname {smoothstep} (x)=S_{1}(x)={\begin{cases}0,&x\leq 0\\3x^{2}-2x^{3},&0\leq x\leq 1\\1,&1\leq x\\\end{cases}}} 左端を0、右端を1とし、0 ≤ x ≤ 1 の範囲で辺間の遷移が発生すると仮定します。
AMD [ 5 ] が提供する修正版C/C++実装例を以下に示します。
float smoothstep ( float edge0 , float edge1 , float x ) { // スケールして、x を 0..1 の範囲にクランプします x = clamp (( x - edge0 ) / ( edge1 - edge0 )); return x * x * ( 3.0f - 2.0f * x ); } float clamp ( float x , float lowerlimit = 0.0f , float upperlimit = 1.0f ) { if ( x < lowerlimit ) return lowerlimit ; if ( x > upperlimit ) return upperlimit ; return x ; } 左端が0、右端が1であると仮定した場合のsmoothstep の一般形は次のようになります。
S n ( x ) = { 0 、 もし x ≤ 0 x n + 1 ∑ k = 0 n ( n + k k ) ( 2 n + 1 n − k ) ( − x ) k 、 もし 0 ≤ x ≤ 1 1 、 もし 1 ≤ x {\displaystyle \operatorname {S} _{n}(x)={\begin{cases}0,&{\text{if }}x\leq 0\\x^{n+1}\sum _{k=0}^{n}{\binom {n+k}{k}}{\binom {2n+1}{n-k}}(-x)^{k},&{\text{if }}0\leq x\leq 1\\1,&{\text{if }}1\leq x\\\end{cases}}} S 0 ( x ) {\displaystyle \operatorname {S} _{0}(x)} クランプ機能 と同一です。
S 0 ( x ) = { 0 、 もし x ≤ 0 x 、 もし 0 ≤ x ≤ 1 1 、 もし 1 ≤ x {\displaystyle \operatorname {S} _{0}(x)={\begin{cases}0,&{\text{if }}x\leq 0\\x,&{\text{if }}0\leq x\leq 1\\1,&{\text{if }}1\leq x\\\end{cases}}} 特徴的なS字型のシグモイド曲線は、S n ( x ) {\displaystyle \operatorname {S} _{n}(x)} n ≥ 1 の整数 に限ります。一般的な smoothstep の多項式 の次数は 2 n + 1 です。n = 1 の場合、 smoothstep の傾きまたは 1 階微分は、曲線が定数または飽和 レベルに追加される左端と右端 ( x = 0 およびx = 1) でゼロになります。より大きな整数n の場合、2 階以上の微分が端でゼロになるため、多項式関数は可能な限り平坦になり、0 または 1 の極限値への接続がよりシームレスになります。
バリエーション ケン・パーリンは [ 6 ] 、一般的に使用されている1次スムースステップ関数の改良版を提案した。これは、その一般形の2次に相当する。x = 0およびx = 1において、1次および2次の導関数はゼロである。
よりスムーズなステップ ( x ) = S 2 ( x ) = { 0 、 x ≤ 0 6 x 5 − 15 x 4 + 10 x 3 、 0 ≤ x ≤ 1 1 、 1 ≤ x {\displaystyle \operatorname {smootherstep} (x)=S_{2}(x)={\begin{cases}0,&x\leq 0\\6x^{5}-15x^{4}+10x^{3},&0\leq x\leq 1\\1,&1\leq x\\\end{cases}}} C/C++リファレンス実装 :
float smootherstep ( float edge0 , float edge1 , float x ) { // スケールして、x を 0..1 の範囲にクランプします x = clamp (( x - edge0 ) / ( edge1 - edge0 )); return x * x * x * ( x * ( 6.0f * x - 15.0f ) + 10.0f ); } float clamp ( float x , float lowerlimit = 0.0f , float upperlimit = 1.0f ) { if ( x < lowerlimit ) return lowerlimit ; if ( x > upperlimit ) return upperlimit ; return x ; }
起源
3次方程式 一般的な3次多項式 関数とその1階導関数 から始めます。
S 1 ( x ) = 1 3 x 3 + 1 2 x 2 + 1 1 x + 1 0 、 S 1 ′ ( x ) = 3 1 3 x 2 + 2 1 2 x + 1 1 。 {\displaystyle {\begin{alignedat}{9}\operatorname {S} _{1}(x)&&\;=\;&&a_{3}x^{3}&&\;+\;&&a_{2}x^{2}&&\;+\;&&a_{1}x&&\;+\;&&a_{0},&\\\operatorname {S} _{1}'(x)&&\;=\;&&3a_{3}x^{2}&&\;+\;&&2a_{2}x&&\;+\;&&a_{1}.&\end{alignedat}}} 関数の両端点に、必要な値を適用する:
S 1 ( 0 ) = 0 ⇒ 0 + 0 + 0 + 1 0 = 0 、 S 1 ( 1 ) = 1 ⇒ 1 3 + 1 2 + 1 1 + 1 0 = 1. {\displaystyle {\begin{alignedat}{13}\operatorname {S} _{1}(0)&&\;=\;&&0\quad &&\Rightarrow &&\quad 0\;&&+&&\;0\;&&+&&\;0\;&&+&&\;a_{0}&&\;=\;&&0,&\\\operatorname {S} _{1}(1)&&\;=\;&&1\quad &&\Rightarrow &&\quad a_{3}\;&&+&&\;a_{2}\;&&+&&\;a_{1}\;&&+&&\;a_{0}&&\;=\;&&1.&\end{alignedat}}} 関数の両端点における一次導関数の所望の値を適用する:
S 1 ′ ( 0 ) = 0 ⇒ 0 + 0 + 1 1 = 0 、 S 1 ′ ( 1 ) = 0 ⇒ 3 1 3 + 2 1 2 + 1 1 = 0. {\displaystyle {\begin{alignedat}{11}\operatorname {S} _{1}'(0)&&\;=\;&&0\quad &&\Rightarrow &&\quad 0\;&&+&&\;0\;&&+&&\;a_{1}\;&&=\;&&0,&\\\operatorname {S} _{1}'(1)&&\;=\;&&0\quad &&\Rightarrow &&\quad 3a_{3}\;&&+&&\;2a_{2}\;&&+&&\;a_{1}\;&&=\;&&0.&\end{alignedat}}} 最後の4つの方程式で構成される4つの未知数の連立方程式を解くと、多項式の係数の値が得られます。
1 0 = 0 、 1 1 = 0 、 1 2 = 3 、 1 3 = − 2. {\displaystyle a_{0}=0,\quad a_{1}=0,\quad a_{2}=3,\quad a_{3}=-2.} これにより、3次関数である「smoothstep」 が得られます。
S 1 ( x ) = − 2 x 3 + 3 x 2 。 {\displaystyle \operatorname {S} _{1}(x)=-2x^{3}+3x^{2}.} これは、3次エルミートスプラインの基底関数の 1つであることに注意してください。
5次方程式 一般的な5次多項式 関数から始め、その1階導関数と2階導関数を求めます。
S 2 ( x ) = 1 5 x 5 + 1 4 x 4 + 1 3 x 3 + 1 2 x 2 + 1 1 x + 1 0 、 S 2 ′ ( x ) = 5 1 5 x 4 + 4 1 4 x 3 + 3 1 3 x 2 + 2 1 2 x + 1 1 、 S 2 」 ( x ) = 20 1 5 x 3 + 12 1 4 x 2 + 6 1 3 x + 2 1 2 。 {\displaystyle {\begin{alignedat}{13}\operatorname {S} _{2}(x)&&\;=\;&&a_{5}x^{5}&&\;+\;&&a_{4}x^{4}&&\;+\;&&a_{3}x^{3}&&\;+\;&&a_{2}x^{2}&&\;+\;&&a_{1}x&&\;+\;&&a_{0},&\\\operatorname {S} _{2}'(x)&&\;=\;&&5a_{5}x^{4}&&\;+\;&&4a_{4}x^{3}&&\;+\;&&3a_{3}x^{2}&&\;+\;&&2a_{2}x&&\;+\;&&a_{1},&\\\operatorname {S} _{2}''(x)&&\;=\;&&20a_{5}x^{3}&&\;+\;&&12a_{4}x^{2}&&\;+\;&&6a_{3}x&&\;+\;&&2a_{2}.&\end{alignedat}}} 関数の両端点に、必要な値を適用する:
S 2 ( 0 ) = 0 ⇒ 0 + 0 + 0 + 0 + 0 + 1 0 = 0 、 S 2 ( 1 ) = 1 ⇒ 1 5 + 1 4 + 1 3 + 1 2 + 1 1 + 1 0 = 1. {\displaystyle {\begin{alignedat}{17}\operatorname {S} _{2}(0)&&\;=\;&&0\;\;\;\;\;&&\Rightarrow &&\;\;\;\;\;0\;&&+&&\;0\;&&+&&\;0\;&&+&&\;0\;&&+&&\;0\;&&+&&\;a_{0}&&\;=\;&&0,&\\\operatorname {S} _{2}(1)&&\;=\;&&1\;\;\;\;\;&&\Rightarrow &&\;\;\;\;\;a_{5}\;&&+&&\;a_{4}\;&&+&&\;a_{3}\;&&+&&\;a_{2}\;&&+&&\;a_{1}\;&&+&&\;a_{0}&&\;=\;&&1.&\end{alignedat}}} 関数の両端点における一次導関数の所望の値を適用する:
S 2 ′ ( 0 ) = 0 ⇒ 0 + 0 + 0 + 0 + 1 1 = 0 、 S 2 ′ ( 1 ) = 0 ⇒ 5 1 5 + 4 1 4 + 3 1 3 + 2 1 2 + 1 1 = 0. {\displaystyle {\begin{alignedat}{15}\operatorname {S} _{2}'(0)&&\;=\;&&0\;\;\;\;&&\Rightarrow &&\;\;\;\;0\;&&+&&\;0\;&&+&&\;0\;&&+&&\;0\;&&+&&\;a_{1}\;&&=\;&&0,&\\\operatorname {S} _{2}'(1)&&\;=\;&&0\;\;\;\;&&\Rightarrow &&\;\;\;\;5a_{5}\;&&+&&\;4a_{4}\;&&+&&\;3a_{3}\;&&+&&\;2a_{2}\;&&+&&\;a_{1}\;&&=\;&&0.&\end{alignedat}}} 関数の2階微分に、両端点における所望の値を適用する。
S 2 」 ( 0 ) = 0 ⇒ 0 + 0 + 0 + 2 1 2 = 0 、 S 2 」 ( 1 ) = 0 ⇒ 20 1 5 + 12 1 4 + 6 1 3 + 2 1 2 = 0. {\displaystyle {\begin{alignedat}{15}\operatorname {S} _{2}''(0)&&\;=\;&&0\;\;\;\;&&\Rightarrow &&\;\;\;\;0\;&&+&&\;0\;&&+&&\;0\;&&+&&\;2a_{2}\;&&=\;&&0,&\\\operatorname {S} _{2}''(1)&&\;=\;&&0\;\;\;\;&&\Rightarrow &&\;\;\;\;20a_{5}\;&&+&&\;12a_{4}\;&&+&&\;6a_{3}\;&&+&&\;2a_{2}\;&&=\;&&0.&\end{alignedat}}} 最後の6つの方程式で構成される6つの未知数の連立方程式を解くと、多項式の係数の値が得られます。
1 0 = 0 、 1 1 = 0 、 1 2 = 0 、 1 3 = 10 、 1 4 = − 15 、 1 5 = 6. {\displaystyle a_{0}=0,\quad a_{1}=0,\quad a_{2}=0,\quad a_{3}=10,\quad a_{4}=-15,\quad a_{5}=6.} これにより、5次関数である「smootherstep」 関数が得られます。
S 2 ( x ) = 6 x 5 − 15 x 4 + 10 x 3 。 {\displaystyle \operatorname {S} _{2}(x)=6x^{5}-15x^{4}+10x^{3}.}
7次方程式 同様の手法を適用すると、7次方程式は次のようになる。
S 3 ( x ) = − 20 x 7 + 70 x 6 − 84 x 5 + 35 x 4 。 {\displaystyle \operatorname {S} _{3}(x)=-20x^{7}+70x^{6}-84x^{5}+35x^{4}.}
高階方程式への一般化 滑らかなステップ多項式は、0 ≤ x ≤ 1として一般化されます。
S N ( x ) = x N + 1 ∑ n = 0 N ( N + n n ) ( 2 N + 1 N − n ) ( − x ) n N ∈ N = ∑ n = 0 N ( − 1 ) n ( N + n n ) ( 2 N + 1 N − n ) x N + n + 1 = ∑ n = 0 N ( − N − 1 n ) ( 2 N + 1 N − n ) x N + n + 1 、 {\displaystyle {\begin{aligned}\operatorname {S} _{N}(x)&=x^{N+1}\sum _{n=0}^{N}{\binom {N+n}{n}}{\binom {2N+1}{N-n}}(-x)^{n}\qquad N\in \mathbb {N} \\&=\sum _{n=0}^{N}(-1)^{n}{\binom {N+n}{n}}{\binom {2N+1}{N-n}}x^{N+n+1}\\&=\sum _{n=0}^{N}{\binom {-N-1}{n}}{\binom {2N+1}{N-n}}x^{N+n+1},\\\end{aligned}}} ここで、N は 結果として得られる多項式関数の次数を決定するもので、2N + 1 です。0 ≤ x ≤ 1 の最初の 7 つのスムーズステップ多項式は次のとおりです。
S 0 ( x ) = x 、 S 1 ( x ) = − 2 x 3 + 3 x 2 、 S 2 ( x ) = 6 x 5 − 15 x 4 + 10 x 3 、 S 3 ( x ) = − 20 x 7 + 70 x 6 − 84 x 5 + 35 x 4 、 S 4 ( x ) = 70 x 9 − 315 x 8 + 540 x 7 − 420 x 6 + 126 x 5 、 S 5 ( x ) = − 252 x 11 + 1386 x 10 − 3080 x 9 + 3465 x 8 − 1980 x 7 + 462 x 6 、 S 6 ( x ) = 924 x 13 − 6006 x 12 + 16380 x 11 − 24024 x 10 + 20020 x 9 − 9009 x 8 + 1716 x 7 。 {\displaystyle {\begin{aligned}\operatorname {S} _{0}(x)&=x,\\\operatorname {S} _{1}(x)&=-2x^{3}+3x^{2},\\\operatorname {S} _{2}(x)&=6x^{5}-15x^{4}+10x^{3},\\\operatorname {S} _{3}(x)&=-20x^{7}+70x^{6}-84x^{5}+35x^{4},\\\operatorname {S} _{4}(x)&=70x^{9}-315x^{8}+540x^{7}-420x^{6}+126x^{5},\\\operatorname {S} _{5}(x)&=-252x^{11}+1386x^{10}-3080x^{9}+3465x^{8}-1980x^{7}+462x^{6},\\\operatorname {S} _{6}(x)&=924x^{13}-6006x^{12}+16380x^{11}-24024x^{10}+20020x^{9}-9009x^{8}+1716x^{7}.\\\end{aligned}}} の導関数S N ( x ) {\displaystyle \operatorname {S} _{N}(x)} は
d d x S N ( x ) = ( 2 N + 1 ) ( 2 N N ) ( x − x 2 ) N 。 {\displaystyle {\begin{aligned}\operatorname {d \over dx} {S}_{N}(x)&=(2N+1){\binom {2N}{N}}(x-x^{2})^{N}.\\\end{aligned}}} 滑らかなステップ多項式は、S N ( x ) {\displaystyle \operatorname {S} _{N}(x)} xが 0から1に変化するときの、0から1への変化は、奇対称 多項式に簡単にマッピングできる。
R N ( x ) = ( ∫ 0 1 ( 1 − u 2 ) N d u ) − 1 ∫ 0 x ( 1 − u 2 ) N d u 、 {\displaystyle \operatorname {R} _{N}(x)=\left(\int _{0}^{1}{\big (}1-u^{2}{\big )}^{N}\,du\right)^{-1}\int _{0}^{x}{\big (}1-u^{2}{\big )}^{N}\,du,} どこ
S N ( x ) = 1 2 R N ( 2 x − 1 ) + 1 2 {\displaystyle \operatorname {S} _{N}(x)={\tfrac {1}{2}}\operatorname {R} _{N}(2x-1)+{\tfrac {1}{2}}} そして
R N ( − x ) = − R N ( x ) 。 {\displaystyle \operatorname {R} _{N}(-x)=-\operatorname {R} _{N}(x).} R N ( x )の引数は−1 ≤ x ≤ 1 であり、左側の定数 −1 と右側の定数 +1 に付加されます。
実装S N ( x ) {\displaystyle \operatorname {S} _{N}(x)} JavaScript では:[ 7 ]
// 一般化されたスムースステップ 関数 generalSmoothStep ( N , x ) { x = clamp ( x , 0 , 1 ); // x は 0 以上 1 でなければなりません var result = 0 ; for ( var n = 0 ; n <= N ; ++ n ) result += pascalTriangle ( - N - 1 , n ) * pascalTriangle ( 2 * N + 1 , N - n ) * Math . pow ( x , N + n + 1 ); return result ; } // 階乗を明示的に使用せずに二項係数を返します。 // 階乗は負の整数には使用できません。 function pascalTriangle ( a , b ) { var result = 1 ; for ( var i = 0 ; i < b ; ++ i ) result *= ( a - i ) / ( i + 1 ); return result ; } function clamp ( x , lowerlimit , upperlimit ) { if ( x < lowerlimit ) x = lowerlimit ; if ( x > upperlimit ) x = upperlimit ; return x ; }
周波数領域特性 我々の元のsmoothstep関数は、ヘヴィサイド階段関数 を用いて次のように書き換えることができる。
S 1 ( x ) = H ( x ) ( 3 x 2 − 2 x 3 ) − H ( x − 1 ) ( 3 x 2 − 2 x 3 − 1 ) {\displaystyle S_{1}(x)=H(x)\left(3x^{2}-2x^{3}\right)-H(x-1)\left(3x^{2}-2x^{3}-1\right)}
代数的な操作をいくつか実行して、
S 1 ( x ) = H ( x ) ( − 12 6 x 3 + 6 2 x 2 ) − H ( x − 1 ) ( − 12 6 ( x − 1 ) 3 − 6 2 ( x − 1 ) 2 ) {\displaystyle S_{1}(x)=H(x)\left(-{\frac {12}{6}}x^{3}+{\frac {6}{2}}x^{2}\right)-H(x-1)\left(-{\frac {12}{6}}\left(x-1\right)^{3}-{\frac {6}{2}}\left(x-1\right)^{2}\right)}
ラプラス変換は 次のようになる。
S 1 ( s ) = − 12 + 12 e − s s 4 + 6 + 6 e − s s 3 {\displaystyle S_{1}(s)={\frac {-12+12e^{-s}}{s^{4}}}+{\frac {6+6e^{-s}}{s^{3}}}}
これは漸近的に60dB/decadeのロールオフを持ちます(1 / s 3 {\displaystyle 1/s^{3}} ( )とは対照的に、ヘビーサイドステップの 20dB/decade、または線形補間の 40dB/decade とは対照的に(S 0 ( x ) {\displaystyle S_{0}(x)} )- 連続性の次数が高いほど、周波数スペクトルがより局所化されることを示しています。これは、ナイキスト・シャノン標本化定理 に従ってエイリアシングを 減らすために帯域制限が重要な離散システムにとって重要となる可能性があります。
同様の分析はそれぞれに対して実行できますS N ( x ) {\displaystyle S_{N}(x)} ロールオフは20(2 + N)dB/decadeです。
逆スムースステップ smoothstep() の逆関数は、コンピュータグラフィックスにおいて、その効果を反転または補正する必要がある場合に役立ちます。3次方程式の場合、逆関数には解析解が存在し、それは次のようになります。
InvS 1 ( x ) = 1 / 2 − 罪 ( ASIN ( 1 − 2 x ) / 3 ) {\displaystyle \operatorname {InvS} _{1}(x)=1/2-\sin(\operatorname {asin} (1-2x)/3)} これは関数が原因で発生しますf ( x ) = 1 / 2 − 罪 ( 3 ASIN ( 0.5 − x ) ) / 2 {\displaystyle \operatorname {f} (x)=1/2-\sin(3\operatorname {asin} (0.5-x))/2} 関数と同等です3 x 2 − 2 x 3 = S 1 ( x ) {\displaystyle 3x^{2}-2x^{3}=S_{1}(x)} 範囲内− 1 / 2 ≤ x ≤ 3 / 2 {\displaystyle -1/2\leq x\leq 3/2} 一方、逆関数には、正確な多項式表現は存在しない。
GLSLでは:
float inverse_smoothstep ( float x ) { return 0.5 - sin ( asin ( 1.0 - 2.0 * x ) / 3.0 ); }
参考文献 ↑ Microsoft Developer Network の Smoothstep。 ↑ GLSL言語仕様、バージョン1.40。 ↑ UnityゲームエンジンのSmoothStepドキュメント。 ↑ Hazimeh, Hussein; Ponomareva, Natalia; Mol, Petros; Tan, Zhenyu; Mazumder, Rahul (2020). The Tree Ensemble Layer: Differentiability meets Conditional Computation (PDF) . International Conference on Machine Learning. PMLR. ↑ Natalya Tatarchuk (2003). "Advanced Real-Time Shader Techniques" . AMD . p. 94. 2021-05-30 の オリジナルからアーカイブ済み 。2022-04-16 に取得 。 ↑ テクスチャリングとモデリング、第 3 版: 手続き的アプローチ。 ↑ 一般的なスムーズステップ方程式。
外部リンク マルコム・ケソン教授によるRenderManシェーディング言語 のsmoothstepを使用します。 Jari Komppa による補間トリック Simon Gladman によるSwift の プレイグラウンドでsmoothStep() 、smootherStep() 、smoothestStep() を実演するSwift Interpolation Playground Inigo QuilezによるInverse smoothstep