疑似乱数として三角関数を利用する。
概要
現在自分は擬似乱数生成の方法として三角関数を利用しているが、あまりに利用が楽なのと説明が面倒になので一度まとめることにする。
疑似乱数とは
コンピュータ上では擬似的に乱数を生成する。
すなわち完全なランダムは再現不可能で、何らかのインプットに対してアウトプットを返すというのが基本的な流れ。
上記を前提として、「それでもインプットなしに(少なく)偏りのない乱数を返せないか」というのがテーマであって、質の良い乱数となるとメルセンヌ・ツイスタとかになってくる。
で、今回はその乱数の生成として三角関数を利用してみるという内容である。
なんのこっちゃ。
出力方法
一応ゲームに使うのを前提にして話を進める。
例えば等速のフレーム制御を前提として、以下のような式を立てる。
y = x * sin(a*frame+b)
以下の属性を持つことができる。
- sin関数によって-1~1の数を返す。
- xによってsin関数の幅(出力範囲)を変更できる
- aは任意の数値。これはPIでなくていいというのが重要。(まずPIを避けるのがいい)
- frameは画面更新回数の累積。
- a*frameは「PIに依存しない等速的な角度の加算を実装できる」ということ。
- bは、a*frame=0 のときに取りうる値。最初の値が固定になってしまうので意図的に入力する使い方がメイン
すなわち、上記の式によってsin関数は中途半端なところでプロットされるため、1や-1ではない値を取得できる。
また周期的に取得できるということがわかる。(大きな値の加算によりオーバーフローを起こすこともない)
かつ再現性のある数値が出力される。
勿論記述は改造してもいいので、cos関数にする・角度指定に別のカウンタを使う等割と応用が効く。
あと周期的な計算がきになるのであれば、角度指定のところにさらにsin関数で計算させることで二重にランダム要素を出すことができる。
ちなみに余談だけど、この計算は楽器でいうところのFM音源の計算方式に近いものである。
利用事例
CryPic./救哭ノ鳥/WeatherReports./Bow-A Unlimited
今開発中のゲームだけど、ランダム出力に対しては上記の式で出力させている。
これ便利なのは、ランダムだけど「再現性がある」ということ。
敵の配置に利用しても毎回再現性があるように作れるので、適当に配置してみて問題なければそのまま本番パターンみたいなのも可能。
A stranger.(4K intro)
ハイハットの音色を作るために使った。
元々上記の4k intro作ってる時に「GLSLは文字列で保存されるのでパッカーでうまく縮む記述にしたい」「簡単な調整ができるようにしたい」として開発した手法になる。
まさかゲームでも使うことになるとは思ってなかった・・・w
類似例
fractとsin関数で出力するやつ。小数部を抽出するため範囲調整もしやすそう。
記事まとめるときに調べて初めて知った。この書籍読んでたはずだが記憶にねえ(汗
https://thebookofshaders.com/10/