Processingのnoise関数を使うと興味深い模様が簡単にできる


2019年 08月 27日

次のような模様を見たことが無いだろうか?

これは、Processingに用意されているnoize関数を用いることで、簡単に作ることができる。

パーリンノイズ(Perlin noise) と呼ばれるこの関数は、自然なテクスチャを表現するために用意されたもので、雲を表現するためなどに使われる。

PerlinNoise1.png

この画像は、以下のプログラムを実行すると、静止画として表示されたものである。

void setup() {
  background(255);
  colorMode(HSB, 100);
  size(500, 500);
  strokeWeight(1);
}

void draw() {
  for ( int x=0; x < width; ++x ) {
    for ( int y=0; y < height; ++y ) {
      float co =100 * noise(x/50.0, y/50.0);
      stroke(co, 100, 100);
      point(x, y);
    }
  }
}

最初に、setup()が呼ばれる。

  colorMode(HSB, 100);

が、カラーモード指定で、色をHue(色相)、Saturation(彩度)、 Brightness(明度)で表現し、範囲が0から100である。

draw() が実際に描画する部分だが、noise()関数は、引数を1個,2個,または3個とり、それぞれ1次元、2次元、3次元のnoize空間に対応する。引数に対しては、型はfloatで、範囲の指定は特にない。しかし、noise()の戻り値は0.0〜1.0となっている。
そのため、100倍して、HSBの色として利用している。
これを、ピクセル数だけ繰り返しているという、非常に単純なプログラムである。

のこのままでは、かなりぼやっとした感じなので、等高線のようなものを入れてみた。

PerlinNoise2.png

地図のような感じになってきた。
青が海で、緑が陸地で、山が黄色から橙色になっているとみなせるだろう。

色のmode 10 を計算し、整数化した時に0になる場合は、そのピクセルを黒にしただけである。

void setup() {
  background(255);
  colorMode(HSB, 100);
  size(500, 500);
  strokeWeight(1);
}

void draw() {
  for ( int x=0; x < width; ++x ) {
    for ( int y=0; y < height; ++y ) {
      float co =100 * noise(x/50.0, y/50.0);
      if ( int(co)%10 == 0 ) {
        stroke(0, 0, 0);
      } else {
        stroke(co, 100, 100);
      }
      point(x, y);
    }
  }
}

最後に、3次元のnoise()関数を使って、時間と共に変化していく様を見てみよう。

PerlinNoiseMove.mp4

このプログラムは、noize()関数の第3引数に時間を加えただけであるので、説明は省略する。

float t = 100;

void setup() {
  background(255);
  colorMode(HSB, 100);
  size(500, 500);
  strokeWeight(1);
}

void draw() {
  for ( int x=0; x < width; ++x ) {
    for ( int y=0; y < height; ++y ) {
      float co =100 * noise(x/50.0, y/50.0, t);
      if ( int(co)%10 == 0 ) {
        stroke(0, 0, 0);
      } else {
        stroke(co, 100, 100);
      }
      point(x, y);
    }
  }
  t += 0.03;
}

noise()を、テクスチャに使うだけではもったいない。さまざまなデータの初期化とか、色々なことに使えそうである。