見出し画像

コードを一切書かずにp5.jsで幻想的なブルーパターンの動画を作成する

このブログを訪れてくださりありがとうございます。

私は、技術を広く浅く楽しむタイプのぴせらび.exeです。「ぴせらび」と読みます。3Dモデリングや音楽、漫画、本など、好きなものを自由に楽しみながら、少しずつ「作る」ことに挑戦しています。

本ブログでは、このような動画の作り方を紹介します。


素人が作ってみた、という日常ブログに近い形式ですので、技術だけをサクッと知りたい方は、目次から「幻想的なブルーパターンを描くp5.jsコード解説」まで飛んでください。



自己紹介

  • 趣味で3Dモデリング
    Blenderを使って3Dモデルを作り、それを3Dプリンターで形にするのが好きです。目に見える形でアイデアを具現化できるのが楽しくて、技術と趣味が結びつく瞬間にワクワクします。

  • 好きな音楽とその魅力
    Tempalayを愛しています!また、Aphex Twinのようなテクノやアンビエント、実験的な音楽も大好きです。意外性のある音や複雑なリズム、心地よい和音にはつい耳を奪われてしまいます。

  • 漫画や本も大好き
    漫画はコアな作品から定番まで幅広く読みますが、感想を書くのは少し苦手です。好きなものを語り合うよりも、胸に秘めて楽しむタイプです。このブログを通じて、少しずつアウトプットにも挑戦していこうと思っています。


このブログについて

このブログでは、技術の話題を中心に、趣味や日々の気づきも織り交ぜながら、自由に発信していきます。

いままで、自分は音楽や絵が好きでも、作る才能がないことが悩みでした。絵も描けないし、音楽も作れない。感想を書くのも苦手で、好きなものがあっても人と語り合うことなく胸に秘めてきました。

しかし、技術の進歩によって状況は変わりました。コードだけで音楽を作れたり、3Dモデリングで絵が描けなくてもイラストを作れたりします。また、文章が苦手でも、断片的な考えをChatGPTに入力すれば、人に伝わる文章に整えてもらうこともできます。

こんなふうに技術の力を借りながら、少しずつでも「作る」ことに挑戦していきたいです。


ジェネレティブアートとは

最近なんですが、generative art(ジェネレティブアート)に興味があり、p5.jsを触り始めました。

ジェネレーティブアートとは何ぞや?って思う人が多いと思うので説明すると、プログラムにより自動・半自動的に生成されるアートのことを言います。アーティストはルールを作成し、その結果として生成されるアートを楽しみます。

つまり、絵心がなくても楽しめるアートなのです。

興味をもったきっかけは、
ホモ・コーデンス—AI時代、人類はどう描くのか|山口情報芸術センター[YCAM]
というイベント関連のツイートを見たことです。


めっちゃよくないですか???

プログラムだけでこんな良いものが作れるのならやるっきゃない。

p5.jsを導入する

ジェネレティブアートに取り組むにあたり、一番使いやすいp5.jsを始めることにしました。

p5.jsは、絵やアニメーション、音楽などをプログラミングで作れるツールです。ウェブブラウザで動くので、特別なソフトをインストールしなくても使えます。初心者でも簡単に使えるように作られています。

p5.jsについてはこちらの公式サイトが一番わかりやすいと思います。
↓のリンクでp5.jsの導入方法を説明しているので、グーグル翻訳して指示通りにすれば即使えるようになります。


自分で一切コードを書かずに作ってみる

せっかくなのでカラフルで幻想的なものを作ろうと決めました。
作り方はシンプルです。

ChatGPTをひたすら劇詰めする


アバウトなイメージを雑に投げるところから始める

ChatGPTはコードまで全部書いてくれるので、それを実行し自分の納得できる落としどころまで修正させます。

ChatGPTを詰めていく

謎の方向性に行ったので修正させる

だんだん完成形に近づいてきた

明るさが時間経過で累積し、ものの数秒で動画が真っ白になってしまう事態が発生。このあと数時間解決しない白飛びに悩まされることになる。


あまりにも直らないので投げやりになる。

なぜかこれをきっかけに白飛び問題が解決。

ChatGPT覚醒


ここで、一端の完成を見せる。

これはこれで綺麗。
しかし、まだ可能性を追求したいので、さらに詰めていく

ついに完成!やったね!

幻想的なブルーパターンを描く p5.js コード解説

p5.jsを使った幻想的なブルーパターンを描くコードを一緒に見ていきます。このプログラムでは、色鮮やかな四角形が動き回りながら、重なりによって光のようなエフェクトを生み出します。特に、コードに組み込まれたアルゴリズムが、自然で美しいパターンを生成します。


コード全体の流れ

  1. 初期設定 (setup 関数)
    キャンバスを作成し、ランダムな色と形状のデータを生成します。

  2. 毎フレームの描画 (draw 関数)
    四角形が動きながら重なり、光のような効果を生み出します。

  3. 補助的な関数
    色を生成する関数や、重なりの数をカウントする関数を使って、パターンに深みを持たせています。


1. 初期設定(setup 関数)

setup 関数ではキャンバスの作成と、四角形の初期データを準備します。

let shapes = [];
let colors = [];

function setup() {
  createCanvas(windowWidth, windowHeight);
  noStroke();

  // 美しい色を生成する
  colors = generateColors(12, 100, 80, 50, 100); // 12色生成

  // ランダムな形状を生成
  for (let i = 0; i < 230; i++) {
    shapes.push({
      x: random(-200, width + 200),
      y: random(-200, height + 200),
      size: pow(random(1), 2) * 1000 + 120, // 小さいサイズが多くなる
      speedX: random(-1, 1),
      speedY: random(-1, 1),
      col: random(colors),
    });
  }
}

ポイント解説

  • createCanvas: ウィンドウサイズのキャンバスを作成。

  • generateColors: 後述する色生成関数を使用して、12色のパレットを作成。

  • shapes.push(): ランダムな位置、大きさ、色を持つ四角形データをリストに追加。pow(random(1), 2) を使い、小さいサイズが多く生成されるように工夫しています。


2. 描画処理(draw 関数)

draw 関数では、背景をリセットし、四角形を描画していきます。

function draw() {
  background(20, 40, 120); // 深い青系の背景

  blendMode(BLEND); // 通常描画モード
  for (let s of shapes) {
    let overlappingCount = countOverlappingShapes(s);
    let alphaAdjustment = constrain(255 / overlappingCount, 30, 100);
    let col = color(
      red(s.col),
      green(s.col),
      blue(s.col),
      alphaAdjustment
    );

    fill(col);
    rect(s.x, s.y, s.size, s.size);

    // 位置を更新
    s.x += s.speedX;
    s.y += s.speedY;

    // 画面外で跳ね返る
    if (s.x < -s.size || s.x > width + s.size) s.speedX *= -1;
    if (s.y < -s.size || s.y > height + s.size) s.speedY *= -1;
  }

  blendMode(ADD); // 光のようなエフェクト
  for (let s of shapes) {
    let overlappingCount = countOverlappingShapes(s);
    let alphaAdjustment = constrain(255 / overlappingCount, 30, 50);
    let col = color(
      red(s.col),
      green(s.col),
      blue(s.col),
      alphaAdjustment
    );

    fill(col);
    rect(s.x, s.y, s.size, s.size);
  }

  blendMode(BLEND);
}

ポイント解説

  • background: 毎フレーム背景を塗り直すことで、動きがリセットされます。

  • blendMode:

    • BLEND では通常の描画を行います。

    • ADD を使うと、四角形が重なった部分が光のように明るくなります。

  • rect: 各四角形を描画。

  • 跳ね返りの動き: 四角形が画面外に出ないよう、位置を反転して跳ね返る動きを再現。


3. 補助関数

色を生成する関数

function generateColors(count, hueRange, saturation, brightnessMin, brightnessMax) {
  let generatedColors = [];
  for (let i = 0; i < count; i++) {
    let hue = map(i, 0, count, 0, hueRange);
    let brightness = random(brightnessMin, brightnessMax);
    generatedColors.push(color(hue, saturation, brightness, 100));
  }
  return generatedColors;
}
  • map: 色相(hue)を均等に分けて色を生成。

  • 明度(brightness)はランダムに設定して色に変化を持たせています。


重なりをカウントする関数

function countOverlappingShapes(target) {
  let count = 1;
  for (let s of shapes) {
    if (
      target !== s &&
      dist(target.x, target.y, s.x, s.y) < (target.size + s.size) / 2
    ) {
      count++;
    }
  }
  return count;
}
  • 各四角形が他の四角形と重なっているかを計算します。

  • dist を使って距離を計算し、重なりがある場合にカウントを増やします。


実行の手順

  1. p5.js Webエディタ:
    p5.js Web Editor にコードをコピーして実行してください。

  2. カスタマイズの提案:

    • 四角形の数を増やす:
      for (let i = 0; i < 230; i++) の数値を変更。

    • 背景色を変える:
      background(20, 40, 120) を好きなRGB値に。


コード全文

let shapes = [];
let colors = [];

function setup() {
  createCanvas(windowWidth, windowHeight);
  noStroke();

  // 美しい色を生成する
  colors = generateColors(12, 100, 80, 50, 100); // 12色生成

  // ランダムな形状を生成
  for (let i = 0; i < 230; i++) {
    shapes.push({
      x: random(-200, width + 200),
      y: random(-200, height + 200),
      size: pow(random(1), 2) * 1000 + 120, // 小さいサイズが多くなる
      speedX: random(-1, 1),
      speedY: random(-1, 1),
      col: random(colors),
    });
  }
}

function draw() {
  background(20, 40, 120); //background(red, green, blue) 数字が多いほどそれぞれ赤みや青みなどが強くなる。

  blendMode(BLEND); // 通常描画
  for (let s of shapes) {
    let overlappingCount = countOverlappingShapes(s);
    let alphaAdjustment = constrain(255 / overlappingCount, 30, 100); // 最大7枚重なりで調整
    let col = color(
      red(s.col),
      green(s.col),
      blue(s.col),
      alphaAdjustment
    );

    fill(col);
    rect(s.x, s.y, s.size, s.size);

    // 動きを更新
    s.x += s.speedX;
    s.y += s.speedY;

    // 画面外で跳ね返る
    if (s.x < -s.size || s.x > width + s.size) s.speedX *= -1;
    if (s.y < -s.size || s.y > height + s.size) s.speedY *= -1;
  }

  blendMode(ADD); // 光の重なり表現
  for (let s of shapes) {
    let overlappingCount = countOverlappingShapes(s);
    let alphaAdjustment = constrain(255 / overlappingCount, 30, 50); // 最大7枚重なりで調整
    let col = color(
      red(s.col),
      green(s.col),
      blue(s.col),
      alphaAdjustment
    );

    fill(col);
    rect(s.x, s.y, s.size, s.size);
  }

  blendMode(BLEND);
}

// 色を生成する関数
function generateColors(count, hueRange, saturation, brightnessMin, brightnessMax) {
  let generatedColors = [];
  for (let i = 0; i < count; i++) {
    let hue = map(i, 0, count, 0, hueRange);
    let brightness = random(brightnessMin, brightnessMax);
    generatedColors.push(color(hue, saturation, brightness, 100)); // アルファ値を固定
  }
  return generatedColors;
}

// 重なりの枚数をカウントする関数
function countOverlappingShapes(target) {
  let count = 1;
  for (let s of shapes) {
    if (
      target !== s &&
      dist(target.x, target.y, s.x, s.y) < (target.size + s.size) / 2
    ) {
      count++;
    }
  }
  return count;
}

function windowResized() {
  resizeCanvas(windowWidth, windowHeight);
}


感想

自分では一切手を動かさず、ChatGPTに雑にプロンプトを投げてコードを書かせているので、まるでガチャを回しているような感覚。ほとんど理解せずに完成してしまった。

ただ、ChatGPTの限界も感じる。プロンプトを投げて終わりじゃなくて、コードの意味も解説させてちゃんと理解していかないと、より複雑な、芸術として価値のあるクオリティのものは生み出せないなと感じる。

ただ、とっかかりとしてはめちゃくちゃいい。


だって知識がなくても完成品ができるんだよ?


新しいことに取り組む時って、まず完成品を作れないことが一番しんどいんですよ。プログラミングの勉強だと、環境構築がわからず疲弊して時間を溶かし、ただ"Hello World"を出力しただけで疲れ果てて、もうええわ!と終わる。そんな悲劇はもうこりごり。

さあ、みんなもChatGPTを劇詰めして楽しい創作ライフを送ろう!





いいなと思ったら応援しよう!