【MMEの作り方】シェーダーエフェクト編04/ノイズの作り方の基礎
▼今回の記事ページで使うサンプルファイル
今回の記事ぺージの解説で使うサンプルとなるfxファイルは以下のリンクからダウンロードできます。
ただし、ファイルをDL・使用した際にトラブル・不利益が生じたとしても筆者は責任を負わないものとします。自己責任で御利用ください。
▼ノイズを作れれば色々質感表現ができる
今回の記事ではノイズ生成の話をします。
材質に設定するシェーダーエフェクトでノイズというとピンと来づらいかもですが、ようするにガサガサした質感のことです。
シェーダーエフェクトでノイズを表現できるコードを書けるようになると、わざわざ外部かノイズ専用の画像を読み込む必要がなくなります。
ノイズにも様々な種類がありますが今回の記事では、
・ホワイトノイズ
・ブロックノイズ
・パーリンノイズ
・fbmノイズ
の作り方をご紹介していきます。
▼ハッシュ値を使って基本となるホワイトノイズを作る
まずはホワイトノイズです。
サンプルファイル『1-4-0_Cube01.pmx』をMMD内に設置して『1-4-1_WhiteNoise.fx』を割り当ててみてください。
以下のような質感になります。

ではコードの中身を見ていきましょう。
まず、大前提としてこのコードでは面に表示するノイズの値(0~1)を設定するためにワールド座標の値を取っています。
オブジェクトに対して、ワールド座標の値をピクセルシェーダーに設定するための処理は以下の通りです。

続いてノイズに関する処理について。
ノイズの生成のメインはコードのこの部分で行っています。

まず疑問になりそうなのは、コードが書いてある場所かと思います。
頂点シェーダー内でもなく、ピクセルシェーダー内でもない中途半端な場所にコードが書かれています。
実はこういう書き方も可能だったりします。
そして、この部分は現状でピクセルシェーダーの外に書かれていますが後々ピクセルシェーダー内で使用します。

このように、処理のまとまりを定義して後々の行で使用するための仕組みを『関数』(あるいは『メソッド』とも)と言います。
では、ノイズ生成に関する関数の中身を具体的に見ていきましょう。

ここで使われている『frac』とは、入力された値の小数部分のみを返す演算子です。
例えば、
・1.25 → 0.25
・55.666 → 0.666
・254.77 → 0.77
みたいな感じです。
取り出した小数点部分に更にゴチャゴチャした定数を乗算したり加算したりしているのがこの関数です。
「そんな処理をしたらデタラメな値が出力されるのでは?」と思った人はお目が高い。
その通りです。
この関数は数式を使って疑似的にデタラメな値(つまり乱数)を生成しています。
このように疑似的な乱数を生成する手法を『ハッシュ』、生成された値を『ハッシュ値』といい、今回のホワイトノイズはハッシュ値をベースに作られています。
▼ブロックノイズ
続いてブロックノイズです。
ブロックノイズとは、以下のようなモザイクタイル状のノイズのことをいいます。

ではブロックノイズを生成する関数を見てみましょう。

はい、これだけです。
短かすぎて逆に何をしているの想像しづらいので、もう少し詳しく解説します。
まず、関数内で使われている『floor』についてを説明します。
これは入力した値の小数点部分を切り捨てて返す演算子です。
例えば、
・1.222 → 1
・54.555 → 54
・321.654 → 321
という具合です。
通常、実数の値は整数だけでなく小数も含むのでグラデーションになっています。
数直線は小数部分もあるからどこまでも切れ目なく続く一本の線になっていると言うと伝わるでしょうか。
ところがこれを小数部分だけカットするとグラデーションが帯状になります。
図で描いてみると以下のような感じです。

このようにグラデーション上になっている値をブツ切りにして飛び飛びの値にすることを『離散化』といいます。
そして、この離散化した値をホワイトノイズ生成用の関数に入れて再計算するとブロックノイズが出来上がります

▼パーリンノイズ
続いてパーリンノイズです。
パーリンノイズとは、以下のようなまだら模様みたいなノイズです。

コード内のパーリンノイズに関する処理は以下の通り。

パーリンノイズは大きく分けて2つのステップで生成されます。
まず、1つ目の部分に関して。
この部分でハッシュ(ホワイトノイズ)を生成する関数を利用して、まだら模様のベースを作っています。
しかし、これだけでは以下の画像のように切れ目が目立つパーリンノイズが出来てしまいます。

なので、この見苦しい切れ目を消すために2つ目の部分があるわけです。
今『切れ目を消すために』とは書きましたが実際には「消す」というよりは「切れ目を滑らかにして誤魔化す」という方が適切です。
その為に使われているのが関数内の『lerp』という演算子です。
lerp演算子はカッコ内の値の間を出力する指定をします。
例えば、
・lerp(0, 1, 0.7) → 0~1の間の0.7(70%)の値を取るので0.7が出力される
・lerp(0, 0.5, 0.7) → 0~0.5の間の0.7(70%)の値を取るので0.35が出力される
・lerp(0, 100, 0.4) → 0~100の値の0.4(40%)の値を取るので40が出力される
という具合です。
パーリンノイズに切れ目が出来るのは、切れ目の境界では色を指定するための値が極端な差が出来ているからです。
なので、lerp演算子が2つ値の間の中から別の値を取り出すという処理の特性を利用して極端な値の差を滑らかにしているわけです。
これを『補間』といいます。
▼fbmノイズにする
最後にfbmノイズです。
fbmノイズとは以下のように雲というか靄みたいなノイズです。

fbmノイズに関する処理は以下の通り。

関数内に書かれているコードを見ると、for文(繰り返し文)があってその中でパーリンノイズに関する処理が呼び出されています。
つまり、fbmノイズがどういうものかを超ざっくり説明すると、
「パーリンノイズを使った処理を複数回繰り返して生成された雲や霞のようなノイズ」になります。
雲や霞のような、と書きましたが実際に雲などの自然物を表現するときにfbmノイズが利用されます。
そこら辺については筆者は過去にfbxノイズを使い『雲が流れるスカイドーム』という作品を作っています。
Boothにて無料配布中ですので興味がありましたら作例として御参照くださいませ(ダイレクトマーケティング)
【目次ぺージに戻る】
