ノイズのタイリング

ノイズのタイリング

パーリンノイズのタイリング

 九個のQuadを並べ、シェーダでノイズ2(パーリンノイズ)で作成したパーリンノイズを生成すると

このように、境界ができてしまいます。この原因と解決法を探るため、一次元パーリンノイズを並べたグラフと作成しました。

グラフの中央が境界となっています。パーリンノイズは青色の直線と赤色の直線を補間することにより求めています。このグラフより、青色と赤色の直線は一つの直線となっていますが、境界における直線はv字となっていることが分かります。これが、境界部分で滑らかに数値が変化していない理由となります。この両直線の傾きを一致させると境界部分が滑らかにつながるはずです。傾きを一致させたグラフを以下に示します。

このグラフより、境界における直線の傾きを一致させることで、滑らかにつながることが分かりました。

shader

通常のパーリンノイズのシェーダは以下の通りです。

このシェーダにおいて座標は0~_NoiseScaleとなります。そのため、rand(_NoiseScale)がv字となっている青色の直線の傾きに該当します。よって、このrand(_NoiseScale)をrand(0)へ変更する処理を追加すればタイリングできるはずです。これを踏まえ、ノイズを計算する関数を以下のように変更しました。

fmodにより、rand(floor(st)+int2(1, 1))がrand(_Noisescale)となったときにrand(0)となるように処理をしています。

実行結果

 上記の通りに変更を加えたシェーダを実行した結果は以下の通りです。境界部分がきれいに繋がっていることが分かります。

オフセットの追加

 uv座標に一定の数値を加算することで、ノイズを移動できるようにします。オフセットを行わない場合はp1をfmodで処理しなくても問題ありませんでしたが、オフセットによってノイズを移動する場合はp2と同様にp1にもfmodを追加する必要があります。

x方向へ9動かした状態(offset=(9,0))で上記シェーダを実行すると以下のようになります。

ノイズをオフセットによって動かすと境界が生じてしまいました。これは、fmodによって求められるp1及びp2 が本来求められるべき値より小さい値になっていることが原因のようです(日々量産:fmod)。そこで、以下のように変更を加えました。

p1及びp2に小さな値を加算することで、正しい値が求まるように処理をしています。これを実行すると以下のようになります。

境界をなくすことができました。さらに、オフセットをマイナスの数値としても問題なくノイズが求まるように処理を変更します。現状では、p1及びp2はそれぞれ・・・0,-4,-3,-2,-1,0・・・0,1,2,3,4,0・・・となります。これを・・・ 0,1,2,3,4,0・・・0,1,2,3,4,0・・・となるようにコードを変更します。まず、以下のコードで座標が0以上か0未満で処理を変更できるようにします。

次に、・・・0,-4,-3,-2,-1,0・・・0,1,2,3,4,0・・・となるように処理を行います。

fmodで求められた値に小さい数値を加算することで、正しい値が求まるようにしていましたが、マイナスの場合は小さな値を減算する必要があります。よって、epsにsign(st)を乗算することでこれに対応しています。最後に、・・・ 0,1,2,3,4,0・・・0,1,2,3,4,0・・・となるように処理を加えます。

sigを用いてpが正と負の場合によって処理を変更できるようにしています。また、pが負の時はscaleを加算することで・・・0,-4,-3,-2,-1,0・・・は・・・5,1,2,3,4,5・・・となり、sign(-p)を乗算することで・・・0,1,2,3,4,0・・・となります。

shader

オフセットに対応したノイズは以下のコードで求めることができます。

shader

 オフセットに対応したタイリング可能なパーリンノイズのシェーダを以下の通りです。

セルラーノイズのタイリング

 セルラーノイズ(シェーダでノイズ3(セルノイズ))もパーリンノイズと同様の方法でタイリングできます。

shader

 オフセットに対応したタイリング可能なセルラーノイズのシェーダは以下の通りです。

実行結果

 Quadを9個並べた状態で上記シェーダを実行すると以下のようになります(noise scale=5、offset=(-3,-9))。セルラーノイズも問題なくタイリングできていることが分かります。

参考サイト

日々量産:fmod