ランダムについて理解が深まったでしょうか?次はノイズです。ここではプログラミングの世界で最もよく使われているパーリンノイズを使ってみます。
このパーリンノイズは、波や炎など、連続的に変化する形態を作ることに適しています。
まず、一つサンプルを作成してみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | float myNoise = 0.0; //ノイズの初期値 float step = 0.02; //ステップの数値が少ないと変化が滑らかになる size(400, 400); background(255); for (int x = 0; x < width; x += 3) { //noise()の引数がいくつでも、必ず結果は0.0 ~ 1.0の間の値が返される //0.0 ~ 1.0にheightを掛けているので、結果は0.0 ~ 400.0 float y = noise(myNoise) * height; //ノイズを使ってy座標を設定 line(x, 0, x, y); //ランダムを使った場合は連続性がない //line(x, 0, x, random(height)); myNoise += step; //ノイズの値を更新 } |
このサンプルは、lineの2点目のy座標を決定する際にnoise()を使っています。ポイントは2点です。
・myNoiseには規則的に増加する値を入れる。このサンプルではstep
・stepの値は少なければ連続的変化が小さく(形は滑らか)、大きければ変化が大きく(形は荒く)なる
stepの値を変えて確認してみましょう。
myNoiseの初期値を変えてみる
また、myNoiseの初期値を変えると全く違った図形を得ることができます。次のサンプルはクリックするごとに0.0 ~ 10.0の間でランダムに初期値を設定します。初期値が変わることによって、形が大きく変わることを確認してみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | float myNoise = 0.0; //ノイズの初期値 float start = 0.0; //myNoiseのスタート地点 float step = 0.02; //ステップの数値が少ないと変化が滑らかになる void setup() { size(400, 400); } void draw() { background(255); myNoise = start; //myNoiseをスタート地点で初期化 for (int x = 0; x < width; x += 3) { float y = noise(myNoise) * height; //ノイズを使ってy座標を設定 line(x, 0, x, y); //ランダムを使った場合は連続性がない //line(x, 0, x, random(height)); myNoise += step; //ノイズの値を更新 } } void mousePressed() { start = random(10); //myNoiseのスタート位置を変える } |
stepの値をリアルタイムに変えてみる
このサンプルでは、マウスのx座標の動きに合わせてstepの値を変化させています。画面左下にstepの値を出力しているので、値を確認しながらマウスを動かしてみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | float myNoise = 0.0; //ノイズ変数 float start = 0.0; //myNoiseのスタート地点 float step = 0.0; //ステップの数値が少ないと変化が滑らかになる PFont myFont; //フォント用変数 void setup() { size(400, 400); myFont = createFont("Arial", 12); //フォント作成 textFont(myFont, 14); //テキストのサイズを設定 } void draw() { background(255); myNoise = start; step = map(mouseX, 0, width, 0.0, 0.1); for (int x = 0; x < width; x += 3) { float y = noise(myNoise) * height; line(x, 0, x, y); //ランダムを使った場合は連続性がない //line(x, 0, x, random(height)); myNoise += step; //ノイズの値を更新 } fill(0); text("step = " + step, 20, height - 20); //月を描画 } void mousePressed() { start = random(10); //myNoiseのスタート位置を変える } |
色彩にノイズを使ってみる
それでは、色彩にノイズを使ってみたらどのような応用ができるでしょうか。
次のサンプルは縦に位置ピクセルずつ描画される線にノイズを使ってみました。x軸方向の変化が滑らかになっています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | float myNoise = 0.0; //ノイズ変数 float start = 0.0; //myNoiseのスタート地点 float step = 0.02; //ステップの数値が少ないと変化が滑らかになる void setup() { size(400, 400); } void draw() { background(255); myNoise = start; //myNoiseをスタート地点で初期化 for (int x = 0; x < width; x ++) { float myColor = noise(myNoise) * 255; //ノイズによる値を色にする stroke(myColor); line(x, 0, x, height); myNoise += step; //ノイズの値を更新 } } void mousePressed() { start = random(10); //myNoiseのスタート位置を変える } |
それでは、R, G, Bそれぞれにノイズを使ったらどうなるでしょうか。無数のバリエーションによるストライプになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | float rNoise; //赤用ノイズ変数 float gNoise; //緑用ノイズ変数 float bNoise; //青用ノイズ変数 float rStart; //赤ノイズのスタート地点 float gStart; //緑ノイズのスタート地点 float bStart; //青ノイズのスタート地点 float step = 0.01; //ステップの数値が少ないと変化が滑らかになる void setup() { size(400, 400); rStart = random(10); //スタート地点をrandom()で初期化 gStart = random(10); bStart = random(10); } void draw() { background(255); rNoise = rStart; //ノイズをスタート地点で初期化 gNoise = gStart; bNoise = bStart; for (int x = 0; x < width; x ++) { //noise(rNoise) * 255の結果は0 ~ 255なので、暗い色を出さないために //map関数を使って100 ~ 255の値にしている float r = map(noise(rNoise) * 255, 0, 255, 100, 255); float g = map(noise(gNoise) * 255, 0, 255, 100, 255); float b = map(noise(bNoise) * 255, 0, 255, 100, 255); stroke(r, g, b); line(x, 0, x, height); rNoise += step; //ノイズの値を更新 gNoise += step; bNoise += step; } } void mousePressed() { rStart = random(10); //ノイズのスタート位置を変える gStart = random(10); bStart = random(10); } |
2次元のノイズ
これまでの例は1次元のノイズでしたが、2次元のノイズ(実は3次元も)というものがあります。このノイズを使うと横方向と縦方向に連続的なノイズを得ることができ、結果的に雲のようなテクスチャを作ることができます。ステップ数を変えるとテクスチャの密度が変わります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | float noiseX = 0.0; //x座標用ノイズ変数 float noiseY = 0.0; //y座標用ノイズ変数 float start = 0.0; //noiseX, noiseYのスタート地点 float step = 0.02; //ステップの数値が少ないと変化が滑らかになる void setup() { size(400, 400); } void draw() { loadPixels(); //ピクセルをロードする noiseY = start; //noiseYをスタート地点で初期化 for (int y = 0; y < height; y ++) { noiseX = start; //noiseXをスタート地点で初期化 for (int x = 0; x < width; x ++) { float c = noise(noiseX, noiseY) * 255; pixels[y * width + x] = color(c); //決定した色をピクセルに反映 noiseX += step; //noiseXを更新 } noiseY += step; //noiseYを更新 } updatePixels(); //ピクセルを更新 } void mousePressed() { start = random(10); //myNoiseのスタート位置を変える } |
運動にノイズを使ってみる
この2次元のノイズは、発想を変えてみると1次元分は形に、もう1次元分は運動に使うこともできます。以下のサンプルは1次元分を運動に使った例です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | float myNoise = 0.0; //ノイズの初期値 float noiseT = 0.0; float start = 0.0; //myNoiseのスタート地点 float step = 0.02; //ステップの数値が少ないと変化が滑らかになる void setup() { size(400, 400); } void draw() { background(255); myNoise = start; //myNoiseをスタート地点で初期化 for (int x = 0; x < width; x += 3) { float y = noise(myNoise, noiseT) * height; //ノイズを使ってy座標を設定 line(x, 0, x, y); //ランダムを使った場合は連続性がない //line(x, 0, x, random(height)); myNoise += step; //ノイズの値を更新 } noiseT += 0.005; } void mousePressed() { start = random(10); //myNoiseのスタート位置を変える } |
この考え方で、3次元のノイズを作って、1, 2次元分は縦横の連続的変化に使い、最後の3次元目は運動に使うとテクスチャの動きになります。色々なパラメータを変えて実験してみてください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | float noiseX = 0.0; //x座標用ノイズ変数 float noiseY = 0.0; //y座標用ノイズ変数 float noiseT = 0.0; //時間経過用ノイズ float start = 0.0; //noiseX, noiseYのスタート地点 float step = 0.02; //ステップの数値が少ないと変化が滑らかになる void setup() { size(400, 400); } void draw() { loadPixels(); //ピクセルをロードする noiseY = start; //noiseYをスタート地点で初期化 for (int y = 0; y < height; y ++) { noiseX = start; //noiseXをスタート地点で初期化 for (int x = 0; x < width; x ++) { float c = noise(noiseX, noiseY, noiseT) * 255; pixels[y * width + x] = color(c); //決定した色をピクセルに反映 noiseX += step; //noiseXを更新 } noiseY += step; //noiseYを更新 } noiseT += 0.005; updatePixels(); //ピクセルを更新 } void mousePressed() { start = random(10); //myNoiseのスタート位置を変える } |