noiseX.js リファレンス

概要

プロシージャルにノイズテクスチャを生成するためのヘルパーライブラリです。

noiseX.js を用いると、簡単にノイズテクスチャを生成できます。また、シームレスなノイズテクスチャを簡単に生成できることも特徴で、プロシージャルにノイズを生成したい場合に便利です。

当ライブラリは canvas タグの 2D コンテキストを利用しており、WebGL は一切利用しません。ライブラリを利用して出力したノイズは、canvas エレメントをテクスチャのソースとして扱うことで、WebGL に流用することが可能です。

また当ライブラリのライセンスは完全フリーです。改変も自由です。さほど大層なものでもありませんしね。※疑似乱数生成をもっと最適化すればだいぶ速くなると思うのですが……放置してます……アハハ……

パーリンノイズ

当ライブラリでのノイズ生成は、パーリンノイズ(perlin noize)と呼ばれるノイズ生成の仕組みを参考にしています。パーリンというのは人名で、このノイズ生成の仕組みを考えた人の名前です。

※ここで解説するのはパーリンノイズそのものではなく、それを参考に実装した noiseX.js の仕組みについてですのであしからず。

パーリンノイズではポイントとなるいくつかの単語が出てきます。それがオクターブ(octave)とパーシステンス(persistence)です。

オクターブとは、簡潔に言うといくつの階層のノイズを合成するかを表しています。合成するノイズの階層数を増やせば増やすほどより精細なノイズが得られますが、必要以上の解像度でノイズを生成しても無意味です。ですから、どのようなサイズのノイズテクスチャがほしいのかによって、オクターブの値はある程度収束します。

パーシステンスはその響きからなんとなく想像がつくと思いますが、ノイズをどのような割合いで合成するかを決定します。先ほど書いたように、ノイズ生成においてはオクターブの値に応じて複数の階層のノイズを生成してから、それらを合成して最終的なノイズ値を決定します。この最終的な合成の場面で、どのような割合いで合成を行なうのかを決めるのがパーシステンスの値です。

とまぁ、ここまで読んでもなかなかイメージしにくいと思いますので、画像を引用しつつ見ていきます。

ノイズ生成と合成

そもそも、ノイズというのは普通ランダムな値です。例として、javascript に最初から実装されている Math.random() という乱数を返すメソッドを使って、これを canvas 上のピクセルに順番に出力してみるとどうなるでしょうか。

ランダムな値を canvas に出力

ランダムな値を出力

ノイズというより、完全な砂嵐状態ですね。

たとえば WebGL で雲やフォグ、岩の表面などに自然なノイズを適用したいとき、上記のようなノイズでは使い物になりません。我々が求めているのは、以下のようなノイズです。

自然なノイズ

自然なノイズ

先ほどの完全ランダムな値の場合と比べて、ノイズの自然さがグッと増していますね。これなら雲などを表現する際に非常に自然な仕上がりにできそうです。それでは如何にしてこのような自然なノイズを生成するのでしょうか。ヒントは、先ほど登場したキーワード、オクターブです。

今回は例として、オクターブの値を 6 にした場合のノイズ生成過程を、わかりやすくするために分解して見ていきます。まずは 6 つあるオクターブ分の、各階層のノイズを生成します。さらに、このノイズを線形補間することで、ある程度均衡化します。

各階層のノイズ生成と均衡化

4x4n4x4l

8x8n8x8l

16x16n16x16l

32x32n32x32l

64x64n64x64l

128x128n128x128l

このように各階層のノイズが生成され、さらに均衡化まで行なったら、今度はこれを合成していきます。この合成の段階で登場するのが、パーシステンスでしたね。

どの階層のノイズを、どの程度の割合いで合成するのか。これにはパーシステンスの値をうまく使うことで対応します。パーシステンスは大抵の場合 0.5 程度の値に設定します。そして、解像度の低いノイズから順に、パーシステンスの値を元に割合を決定していきます。具体的には、パーシステンスの値をべき乗することによって処理します。

パーシステンスの値が 0.5 の場合

4 x 4 のノイズに掛けるパーシステンスは……パーシステンスの 1 乗、つまり 0.5。

8 x 8 のノイズに掛けるパーシステンスは……パーシステンスの 2 乗、つまり 0.25。

16 x 16 のノイズに掛けるパーシステンスは……パーシステンスの 3 乗、つまり 0.125。

32 x 32 のノイズに掛けるパーシステンスは……パーシステンスの 4 乗、つまり 0.0625。

64 x 64 のノイズに掛けるパーシステンスは……パーシステンスの 5 乗、つまり 0.03125。

128 x 128 のノイズに掛けるパーシステンスは……パーシステンスの 6 乗、つまり 0.015625。

このように、各階層のノイズにはパーシステンスの値に応じた係数が掛けられます。これらを全て加算すると、最終系として次のようなノイズが生成されます。

最終ノイズ

最終ノイズテクスチャ

上のノイズ画像はペイントソフトで手動で合成したので若干見映えが悪いですが、要は上記で説明した手順を動的に、且つピクセル単位で行なうことができれば、自然なノイズ画像が得られることは理解できると思います。noiseX.js は、これを簡単に行なってくれるライブラリということですね。

以下、コンストラクタやメソッドの解説です。

※テキストの最後にファイルへのリンクがあります

noiseX コンストラクタ

noiseX.js の全ての機能を内包するクラスのコンストラクタです。

コンストラクタの初期化に際しては、いくつかの引数を与えます。

記述例

n = new noiseX(int oct, int ofs, float per)

第一引数:oct:オクターブ

第二引数:ofs:オクターブのオフセット

第三引数:per:パーシステンス

コンストラクタの呼び出しに与える引数は、いずれも後述する detail メソッドと全く同じです。新しいインスタンスの生成と同時にノイズを生成するためのパラメータが、引数から与えられた値によってセットされます。

オクターブは、先述のとおり重ねる階層の数を表します。先ほど提示した重ねるノイズ画像をよく見ていただければわかると思いますが、先ほどの例では最も低い解像度は 4 x 4 でしたね。最も高い解像度は 128 x 128 でした。解像度の一辺が 4 から 128 までの範囲だったわけですね。

4 は、2 の 2 乗であり、128 は 2 の 7 乗です。実際に合成する階層の数は 6 つでした。これらの数字の関係性が非常に大切です。

合成する(重ねる)階層の数が、オクターブ。これがコンストラクタの第一引数ですね。そして、その最小解像度がオフセット、つまり第二引数に与える値です。先ほど提示した画像と同じようにノイズを生成するなら、オクターブには 6 を、オフセットには 2 を指定すればいいというわけです。

ちなみに第三引数のパーシステンスはそのままの意味です。通常、0.5 前後に設定すると最も自然な結果になるでしょう。

※以降、n を noiseX オブジェクトのインスタンスとみなします

detail メソッド

noiseX オブジェクトに与えるパラメータをセットします。コンストラクタの初期化時に与える引数と全く同じ意味を持つ三つの引数を持ちます。

構文

void noiseX.detail(int oct, int ofs, float per)

第一引数:oct:オクターブ

第二引数:ofs:オクターブのオフセット

第三引数:per:パーシステンス

記述例

n.detail(oct, ofs, per);

setSeed メソッド

乱数生成に用いる初期シード値をセットします。

構文

void noiseX.setSeed(int seed)

第一引数:seed:初期シード値

記述例

n.setSeed(seed);

interpolate メソッド

二つの値を線形補間した結果を返します。このメソッドはノイズを均衡化するために、内部的に呼び出される補助的なメソッドです。

構文

float noiseX.interpolate(float a, float b, float t)

第一引数:a:値 1

第二引数:b:値 2

第三引数:t:補間比率

rnd メソッド

Xorshift と呼ばれる疑似乱数生成手法を少し改良したメソッドで、乱数を生成するのに使われます。

構文

float noiseX.rnd(int x, int y)

第一引数:x:x 座標

第二引数:y:y 座標

srnd メソッド

乱数を均衡化するために使われる補助的なメソッド。

構文

float noiseX.srnd(int x, int y)

第一引数:x:x 座標

第二引数:y:y 座標

irnd メソッド

先述の interpolate メソッドを用いてノイズを線形補間するのに使われる補助的なメソッドです。

構文

float noiseX.irnd(int x, int y)

第一引数:x:x 座標

第二引数:y:y 座標

noise メソッド

ノイズ生成を行なうメソッドで、戻り値は指定された座標の値を正規化したものになります。(つまり 0 ~ 1 の範囲の値が返されます)

このメソッドこそが、本ライブラリにおける最重要メソッドです。逆に言うと初期化さえちゃんとできていれば、あとはこのメソッドを呼び出すだけでノイズは生成できます。内部的には、先述の rnd メソッドや interpolate メソッドなどの補助的な役割を持つメソッドが呼ばれ、最終的なノイズ値だけが戻り値として返される仕様になっています。

構文

float noiseX.noise(int x, int y)

第一引数:x:x 座標

第二引数:y:y 座標

記述例

t = n.noise(x, y);

snoise メソッド

ほとんどが上記の noise メソッドと同じですが、こちらはシームレスなノイズテクスチャを生成することができる特殊なノイズメソッドです。使い方は noise メソッドと全く同じです。

構文

float noiseX.snoise(int x, int y, int w)

第一引数:x:x 座標

第二引数:y:y 座標

第三引数:w:canvas の一辺の幅

記述例

t = n.snoise(x, y);

canvasExport メソッド

生成したノイズを、簡単に canvas 上に出力するための補助的なメソッドです。戻り値は canvas エレメントとして返されますので、 appendChild 等で HTML 内に挿し込んでから、後はスタイルシートで非表示にするなりなんなり好きなように加工できます。

引数には、上記の noise メソッドなどの戻り値を一次元配列に格納したデータを第一引数に、canvas の一辺のサイズを第二引数に与えます。

構文

canvasElement noiseX.canvasExport(array data, int width)

第一引数:data:一次元配列に格納したノイズデータ

第二引数:width:canvas の一辺の幅

記述例

canvas = n.canvasExport(data, width);

ダウンロード

以下のリンクから、javascript ファイル本体をダウンロードできます。また、当テキストはライブラリのリファレンスになります。実際にライブラリをどのように利用するのかは別途テキストを用意しましたので、そちらを参照していただくほうがわかりやすいと思います。

entry

PR

press Z key