クリコー 3分クッキング:極座標でパーリンノイズを綺麗に繋げたい

2025年5月4日日曜日

3分クッキング p5.js Processing 作例

t f B! P L
title

3分で読めるクリエイティブコーディングの小ネタです。 お題は「円弧に沿って綺麗に色が変化する図を描く」です。

普通にやると境目ができて不自然な変化になってしまいます。この記事でそれを解決するアイデアを紹介します。

このアイデアを使うと、このように綺麗に繋る色の変化を描けるようになります。

rainbow arc

角度で変化するパーリンノイズ

色を自然に変化させるなら「パーリンノイズ 」を使いましょう。

「円弧に沿って綺麗に色を変化」は、角度でパーリンノイズを変化させればよさそうです。


noise(角度);


【参考】
パーリンノイズ : Wikipedia
noise() : p5js
noise() : Processing

参考記事:Processing/p5.js の noise() で遊ぼう! 前編

クリエイティブ・コーディングでよく使われるノイズですが、とっつきにくいとか、いまいち使い方がよくわからないという声も聞かれるようです。 今回、簡単な作例を交えながら noise() の特徴や使い方をご紹介したいと思います。noise() をマスターすれば作品作りがグッと面白くなるかも!

でも境目が出来ちゃう…

ところが、普通に noise(角度) とすると、角度が 0 と 2PI(=360度)のところで境目が出来てしまいます。

color gap

円弧が一周してきて接するところは、全然違う値であろう noise(0) と noise(2PI) が隣り合わせなので、急激に色が変わってしまって境目が出てしまうんですね。

color gap by noise parameter

ここで noise(sin(角度)) とすれば、角度が 0 と 2PI のときでどちらも noise(0) になり境目は出ませんが、今度は変化が周期的になってしまいます。

cyclic color

さて、どうしたものか?

アイデアひとつでうまくいく

この悩みを呟いてみたところ、山辺真幸(@masakick)さんからナイスなアイデアをいただきました。


このアイデアを元に以下のように透明度を操作すると、ご覧の通りうまくいきました。

  • 一周目は薄く始めて濃く終わる
  • 二周目は濃く始めて薄く終わる
no color gap example

※透明度の変化によって、若干彩度が落ちて一部 "くすみ" が感じられます。

極座標でパーリンノイズのサンプルコード(Processing / p5js)

角度だけでなく半径でも色が変化するように noise(角度, 半径) でコードを書いてみます。

example image of rainbow color arc
example image of rainbow color arc
【参考】
角度と半径で場所を指定する方式は「極座標系」と呼ばれます。よくある (x, y) で場所を指定するのは「直交座標系」です。
極座標系 : Wikipedia
直交座標系 : Wikipedia

Processing


/*
 * クリコー 3分クッキング:極座標でパーリンノイズを綺麗に繋げたい
 * Processing サンプルコード
 *
 * @author @deconbatch
 * @version 0.1
 * @license CC0 1.0 https://creativecommons.org/publicdomain/zero/1.0/deed.ja
 * Processing 4.3.3
 * 2025.05.03
 */

float marginRate = 0.1;
int cirMax = 7;
int arcMax = 60;

void setup() {
  // キャンバスの設定
  size(800, 800);
  colorMode(HSB, 360.0, 100.0, 100.0, 100.0);
  background(0.0, 0.0, 90.0, 100.0);
  noFill();
  noStroke();

  // 指定したパラメータから描画用の数値を計算
  float margin = min(width, height) * marginRate;
  float cirWidth = (min(width, height) * 0.5 - margin * 2) / cirMax;
  float angleDiv = PI / arcMax;

  //描画
  translate(width * 0.5, height * 0.5);
  strokeWeight(cirWidth * 0.8);
  strokeCap(SQUARE);
  ellipseMode(RADIUS); // arc を直径指定ではなく半径指定に
  for (int cirCnt = 0; cirCnt < cirMax; cirCnt++) {
    for (float angle = 0; angle < TWO_PI * 2; angle += angleDiv) {
      float aHue = (noise(cirCnt * 0.1, angle * 0.2) * 720) % 360;
      float aAlp = 100 * sin(angle / 4); // 一周目は薄くから濃く, 二周目は濃くから薄く終わる
      stroke(aHue, 60.0, 60.0, aAlp);
      arc(
          0.0, 0.0,
          margin + cirWidth * cirCnt, margin + cirWidth * cirCnt,
          angle, angle + angleDiv
          );
    }
  }
}

p5js


/*
 * クリコー 3分クッキング:極座標でパーリンノイズを綺麗に繋げたい
 * p5js サンプルコード
 *
 * @author @deconbatch
 * @version 0.1
 * @license CC0 1.0 https://creativecommons.org/publicdomain/zero/1.0/deed.ja
 * p5js 2.0.0
 * 2025.05.03
 */

const w = 800;
const h = w;
const marginRate = 0.1;
const cirMax = 7;
const arcMax = 60;

function setup() {
  // キャンバスの設定
  createCanvas(w, h);
  colorMode(HSB, 360, 100, 100, 100);
  background(0, 0, 90, 100);
  noFill();
  noStroke();

  // 指定したパラメータから描画用の数値を計算
  const margin = min(w, h) * marginRate;
  const cirWidth = (min(w, h) * 0.5 - margin * 2) / cirMax;
  const angleDiv = PI / arcMax;

  //描画
  translate(w * 0.5, h * 0.5);
  strokeWeight(cirWidth * 0.8);
  strokeCap(SQUARE);
  ellipseMode(RADIUS); // arc を直径指定ではなく半径指定に
  for (let cirCnt = 0; cirCnt < cirMax; cirCnt++) {
    for (let angle = 0; angle < TWO_PI * 2; angle += angleDiv) {
      let aHue = (noise(cirCnt * 0.1, angle * 0.2) * 720) % 360;
      let aAlp = 100 * sin(angle / 4); // 一周目は薄くから濃く, 二周目は濃くから薄く終わる
      stroke(aHue, 60, 60, aAlp);
      arc(
          0, 0,
          margin + cirWidth * cirCnt, margin + cirWidth * cirCnt,
          angle, angle + angleDiv
      );
    }
  }
}

まとめ

ここまで、極座標系のパーリンノイズを使って、円弧に沿って境目なく色を変化させる方法を解説しました。

今回のサンプルコードを改造して、アニメーションにしたり、おなじみの直交座標系でのノイズと組み合わせてみたり、いろいろと楽しめると思います。

【アニメーション例】

【直交座標系でのノイズと組み合わせて】

パーリンノイズに関する他記事も合わせてお楽しみください。

noise() 関数を用いてドット絵風のアニメーション|deconbatch

2次元ノイズで遊んでいたら思いがけずドット絵風のアニメーションが出来たのでご紹介。ノイズの使い方のコツ Processing/p5.js の noise() 関数は「パーリン・ノイズ」を生成してくれる楽しい関数。

改造して遊ぼう!距離関数とノイズで作るジェネラティブアート

改造して楽しく遊べる、Processing で書いたシンプルなサンプル・コードです。Worley ノイズとパーリン・ノイズの組み合わせで描くジェネラティブアートが題材となっています。

パラメータの工夫でパーリンノイズをもっと面白くするテクニック

'noise()' 関数に与えるパラメータを工夫することで様々な表情の絵を作ることが出来ます。クリエイティブ・コーディングにおいて、'noise()' での絵作りに飽きた、行き詰まった方に試してほしい。

QooQ