偶然性のデザイン(ランダム・ノイズ)

      偶然性のデザイン(ランダム・ノイズ) はコメントを受け付けていません

このページでは、Processingのrandom()noise()を使って、偶然性のある表現を作る方法を学びます。random()はサイコロのように毎回バラバラな値を作り、noise()は波のようになめらかに変化する値を作ります。

最初は数値だけを確認し、そのあと図形の位置・大きさ・色・動きに応用していきます。

1. random()とは

random()は、ランダムな数値を作る命令です。たとえばrandom(5)と書くと、0.0以上、5.0未満の数値が作られます。

リスト1
void setup() {
}

void draw() {
  // 0以上5未満のランダムな数値を表示する
  println(random(5));
}

実行すると、コンソールに0.0から5.0未満の数値が次々と表示されます。ここで重要なのは、5.0は含まれないという点です。

書き方作られる値
random(5)0.0以上、5.0未満
random(10)0.0以上、10.0未満
random(-5, 5)-5.0以上、5.0未満

random()の結果はfloat型です。整数として使いたい場合は、int()で変換します。

リスト2
void setup() {
  // random(5)は0.0以上5.0未満の小数を作る
  // int()で小数を整数に変換する
  int n = int(random(5));

  // 0, 1, 2, 3, 4のどれかが表示される
  println(n);
}

この場合、01234のどれかが表示されます。

2. ランダムな位置に円を描く

次に、random()を使って円をランダムな位置に描いてみます。random(width)は画面の横幅の範囲、random(height)は画面の高さの範囲で値を作ります。

リスト3
void setup() {
  size(400, 400);

  // 最初に背景を白にする
  background(255);
}

void draw() {
  // x座標とy座標をランダムに決めて円を描く
  ellipse(random(width), random(height), 30, 30);
}

このサンプルでは、draw()が繰り返されるたびに、違う場所へ円が描かれます。背景を毎回消していないので、円が画面に残っていきます。

ポイント:random(width)は、画面の左端から右端までのどこかの位置を作ります。

3. クリックするたびにランダムな絵を作る

次のサンプルでは、クリックするたびに円の配置が変わります。noLoop()で自動更新を止め、mousePressed()の中でredraw()を呼ぶことで、クリックしたときだけ描き直します。

リスト4
void setup() {
  size(400, 400);

  // draw()の自動くり返しを止める
  noLoop();
}

void draw() {
  background(255);

  // 100個の円を描く
  for (int i = 0; i < 100; i++) {
    // 画面内のランダムな位置に円を描く
    ellipse(random(width), random(height), 30, 30);
  }
}

void mousePressed() {
  // クリックされたときだけdraw()を1回実行する
  redraw();
}

この書き方にすると、毎フレーム描き変わるのではなく、クリックしたときだけ新しい画面が生成されます。ランダムな作品を作るときに便利です。

4. 大きさと色もランダムにする

円の位置だけでなく、大きさや色にもrandom()を使ってみます。これだけで、偶然性のある画面を作ることができます。

リスト5
void setup() {
  size(400, 400);

  // クリックしたときだけ描き直す
  noLoop();
}

void draw() {
  background(255);

  // 100個の円を描く
  for (int i = 0; i < 100; i++) {
    // 円の大きさをランダムに決める
    float s = random(5, 60);

    // 線の色をランダムに決める
    stroke(random(50, 150), random(0, 100), random(50, 200), 200);

    // 塗りの色をランダムに決める
    fill(random(0, 200), random(0, 100), random(100, 255), 50);

    // ランダムな位置に円を描く
    ellipse(random(width), random(height), s, s);
  }
}

void mousePressed() {
  // クリックすると新しいランダムな画面になる
  redraw();
}

sは円の大きさです。random(5, 60)によって、5から60未満の大きさが毎回選ばれます。stroke()fill()にもランダムな値を入れることで、線の色や塗りの色も変化します。

5. 動きにrandom()を使う

random()は、動きにも使えます。次のサンプルでは、円の位置に少しだけランダムな値を足して、震えているような動きを作ります。

リスト6
void setup() {
  size(400, 400);
  noStroke();
}

void draw() {
  background(255);

  // 画面中央の位置に、少しだけランダムなずれを足す
  float x = width/2 + random(-5, 5);
  float y = height/2 + random(-5, 5);

  fill(0);

  // 少し震えるように見える円を描く
  ellipse(x, y, 100, 100);
}

random(-5, 5)によって、中心位置から少しだけずれた場所に円が描かれます。毎フレームずれ方が変わるため、円が細かく振動しているように見えます。

6. 色にrandom()を使う

背景色にrandom()を使うと、色がチカチカ変化します。完全にランダムにすると変化が激しすぎるので、ここではグレーに近い色に少しだけランダムな値を足します。

リスト7
// 基準になるグレーの明るさ
float gray = 120;

void setup() {
  size(400, 400);
}

void draw() {
  // 基準の明るさに、少しだけランダムな変化を足す
  float r = gray + random(-20, 20);
  float g = gray + random(-20, 20);
  float b = gray + random(-20, 20);

  // 毎フレーム少し違う背景色になる
  background(r, g, b);
}

このサンプルでは、赤・緑・青の値が毎回少しずつ変わります。そのため、背景色が細かく揺れているように見えます。

7. noise()とは

noise()も不規則な値を作る命令ですが、random()とは大きく違います。random()は毎回バラバラな値を作りますが、noise()は前後の値がなめらかにつながります。

命令特徴向いている表現
random()毎回バラバラに変化するちらつき、偶然の配置、突然の変化
noise()なめらかに変化する波、雲、地形、ゆっくりした動き

noise()の結果は、常に0.0から1.0の範囲になります。そのままだと小さい値なので、画面の座標や色に使うときは、height255をかけて使います。

8. noise()でなめらかな線を作る

次のサンプルでは、noise()を使って、なめらかに変化する縦線の長さを作ります。

リスト8
// noise()に入れる値
float n = 0;

// noise()の変化の細かさ
float step = 0.02;

void setup() {
  size(400, 400);
  background(255);
}

void draw() {
  background(255);

  // 左端から同じ形を描き始めるため、nを0に戻す
  n = 0;

  // xを3ずつ増やしながら、縦線を並べる
  for (int x = 0; x < width; x += 3) {
    // noise(n)は0.0〜1.0なので、heightをかけて画面の高さに合わせる
    float y = noise(n) * height;

    // 下から上に向かって線を描く
    line(x, height, x, height - y);

    // 次の線では、少し進んだノイズ値を使う
    n += step;
  }
}

noise(n)0.0から1.0の値を返します。そこにheightをかけることで、画面の高さに合った値に変換しています。

stepは、ノイズの変化の細かさを決める値です。小さいほどなめらかに、大きいほど変化が激しくなります。

9. random()とnoise()を比べる

次のサンプルでは、上半分にrandom()、下半分にnoise()を使って線を描きます。違いを見比べてみましょう。

リスト9
// noise()に入れる値
float n = 0;

// noise()の変化の細かさ
float step = 0.02;

void setup() {
  size(400, 400);
}

void draw() {
  background(255);
  stroke(0);

  // 上半分:random()でバラバラな高さの線を描く
  for (int x = 0; x < width; x += 4) {
    float y = random(180);
    line(x, 180, x, 180 - y);
  }

  // 下半分:noise()でなめらかにつながる高さの線を描く
  n = 0;

  for (int x = 0; x < width; x += 4) {
    float y = noise(n) * 180;
    line(x, 400, x, 400 - y);
    n += step;
  }
}

上のrandom()は、線の高さが毎回バラバラです。下のnoise()は、隣の線と高さがなめらかにつながっています。

10. stepの値をマウスで変える

noise()では、stepの値が大切です。次のサンプルでは、マウスの横位置によってstepを変えます。

リスト10
// noise()の開始位置
float start = 0;

void setup() {
  size(400, 400);
}

void draw() {
  background(255);

  // startからノイズを読み始める
  float n = start;

  // マウスのx座標でstepの値を変える
  float step = map(mouseX, 0, width, 0.005, 0.1);

  for (int x = 0; x < width; x += 3) {
    // noise()の値を画面の高さに変換する
    float y = noise(n) * height;

    line(x, height, x, height - y);

    // stepが大きいほど、形の変化が荒くなる
    n += step;
  }

  fill(0);
  text("step = " + step, 20, height - 20);
}

void mousePressed() {
  // クリックすると、別のノイズの形になる
  start = random(10);
}

マウスを左に動かすと、stepが小さくなり、形がなめらかになります。右に動かすと、stepが大きくなり、形の変化が荒くなります。クリックすると、ノイズの開始位置が変わるため、別の形になります。

11. 色にnoise()を使う

noise()は色にも使えます。次のサンプルでは、横方向に少しずつ明るさが変わるストライプを作ります。

リスト11
// noise()の開始位置
float start = 0;

// 色の変化の細かさ
float step = 0.02;

void setup() {
  size(400, 400);
}

void draw() {
  float n = start;

  // 画面の左から右へ、1pxずつ縦線を描く
  for (int x = 0; x < width; x++) {
    // noise()の値を0〜255の明るさに変換する
    float gray = noise(n) * 255;

    stroke(gray);
    line(x, 0, x, height);

    // 次の線では少し進んだノイズ値を使う
    n += step;
  }
}

void mousePressed() {
  // クリックすると、別の模様になる
  start = random(10);
}

noise(n) * 255によって、0から255の明るさを作っています。クリックすると、ノイズの開始位置が変わるため、違う模様になります。

12. RGBそれぞれにnoise()を使う

最後に、赤・緑・青それぞれに別のノイズを使ってみます。なめらかに色が変化するカラフルなストライプになります。

リスト12
// 赤・緑・青、それぞれのnoise()の開始位置
float rStart = 0;
float gStart = 10;
float bStart = 20;

// 色の変化の細かさ
float step = 0.01;

void setup() {
  size(400, 400);
}

void draw() {
  // それぞれの色のノイズ値を用意する
  float rNoise = rStart;
  float gNoise = gStart;
  float bNoise = bStart;

  // 画面の左から右へ、1pxずつ縦線を描く
  for (int x = 0; x < width; x++) {
    // noise()の値を0〜255の色に変換する
    float r = noise(rNoise) * 255;
    float g = noise(gNoise) * 255;
    float b = noise(bNoise) * 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);
}

RGBそれぞれに別のノイズを使うことで、色の変化が複雑になります。random()だけで色を決めるとチカチカした印象になりますが、noise()を使うと、なめらかにつながる色の変化になります。

まとめ

命令意味
random(a)0.0以上、a未満のランダムな値を作る
random(a, b)a以上、b未満のランダムな値を作る
int(random(a))ランダムな値を整数に変換する
noise(n)0.0から1.0の、なめらかに変化する値を作る
stepノイズの変化の細かさを決める値

今日の重要ポイント:random()は毎回バラバラな変化、noise()はなめらかにつながる変化です。偶然性を使った表現では、この2つの違いを意識して使い分けることが大切です。