クリエイティブ・コーディング:コードで構図を作る試行

2022年9月3日土曜日

p5.js お勉強

t f B! P L
p5.js のコードで構図作りの訓練

「カッコいい構図を描く」ではなく、「カッコいい構図を描くコードを書く」ための勉強をしています。

私のクリエイティブ・コーディング、ワンパターンの「日の丸構図」から脱却したくて、先日は美術作品の構図をコードで模写する訓練を行いました。

今回は p5.js で書いたコードで構図を作る試行をします。

👉 Read this article in English.

 

基本のコード(p5.js)

こういう図を描くコードです。

9つのノード間を線で結んだオブジェクト


/** 
 * Trying to make a composition with the code.
 * ref. 220616a by takawo (https://openprocessing.org/sketch/1600130)
 * 
 * p5.js 1.3
 * @license Creative Commons Attribution NonCommercial ShareAlike
 * @author @deconbatch
 * @version 0.1
 * created 2022.09.01
 */

function setup() {
  createCanvas(800, 1000);
  colorMode(HSB, 360.0, 100.0, 100.0, 100.0);
  smooth();
  noLoop();
}

function draw() {
  const nodeNum = 9;
  const offset  = height * 0.15;
  const hueBase = random(360.0);
  
  // set objects attibutes
  const nodes = new Array(nodeNum);
  for (let i = 0; i < nodeNum; i++) {
    nodes[i] = createVector(
      random(0.2, 0.8) * width,
      offset + i * (height - offset * 2.0) / (nodeNum - 1),
      random(20.0, 60.0)
    );
  }

  background(hueBase % 360.0, 40.0, 20.0, 100.0);
  
  // draw objects
  for (let i = 0; i < nodeNum; i++) {
    drawLines(
      nodes[i],
      nodes[(i + 1) % nodeNum],
      hueBase + 90.0 + 15.0 * i
    );
  }

  // casing
  noFill();
  stroke(0.0, 0.0, 90.0, 100.0);
  strokeWeight(offset * 0.5);
  rect(0.0, 0.0, width, height);
}

/**
 * drawLines : draw lines between node _nS and _nE with _hue color.
 */
function drawLines(_nS, _nE, _hue) {
  const lMax  = floor(random(3.0, (_nS.z + _nE.z) * 0.1));
  const phase = atan2(_nE.y - _nS.y, _nE.x - _nS.x) + random(0.25, 0.75) * PI;

  noFill();
  stroke(_hue % 360.0, random(30.0, 50.0), random(80.0, 90.0), 100.0);
  strokeWeight(6.0 / lMax);
  strokeCap(SQUARE);
  for (let l = 0; l < lMax; l++) {
    // calculate the start and end points
    const rS = (_nS.z * l) / lMax;
    const xS = cos(phase) * rS;
    const yS = sin(phase) * rS;
    const rE = (_nE.z * l) / lMax;
    const xE = cos(phase) * rE;
    const yE = sin(phase) * rE;
    
    line(_nS.x + xS, _nS.y + yS, _nE.x + xE, _nE.y + yE);
    line(_nS.x - xS, _nS.y - yS, _nE.x - xE, _nE.y - yE);
    arc(_nS.x, _nS.y, rS * 2, rS * 2, phase, phase + PI);
    arc(_nE.x, _nE.y, rE * 2, rE * 2, phase + PI, phase + TWO_PI);
  }
}

/**
 * mouseClicked : redraw if mouse clicked.
 */
function mouseClicked() {
  redraw();
}


元は @takawo さんこちらの作品です。コードをフォークして作りました。ライセンスは元コードと同じ Creative Commons Attribution NonCommercial ShareAlike にしています。

220616a by takawo (https://openprocessing.org/sketch/1600130)

 

ランダム配置じゃランダムだ

キャンバス上に配置したノードを順番に線で結んだ絵です。ノードの配置は x 方向をランダム、y 方向を上から下に等間隔にしています。

配置がランダムなので、描画の結果もランダムです。面白い構図になることもあれば、つまらない構図のときもあります。体感上、つまらないことが多いです。

ノードをランダム配置にしたオブジェクト例

ノードをランダム配置にしたオブジェクト例

いい構図のものだけピックアップするという考えもありますが、それだと「カッコいい構図を描く」になって「カッコいい構図を描くコードを書く」にならないので、ヤなのです。

 

例えば3つ並べて規則性を加える

これを3つ横に並べてお互いの関係性を表現するなんてできたらカッコいいんでしょうけど、私の手には余ります。真ん中のオブジェクトだけノードの数を多くして、左右を引き立て役にするという工夫がせいぜいです。

 

ただ3つ並べる

ランダムのままだとやはりランダムです。

ランダム配置ノードのオブジェクトを3つ横に並べた

 

左右を鏡像にする

左右を阿吽的に鏡像にしてみます。

左右のオブジェクトを鏡像にする

左右のオブジェクトを鏡像にする

 

若干のランダムネスを加える

きっちり鏡像だと固いので、ランダムで若干崩してみます。

鏡像にした左右のオブジェクトを少し崩す


なかなか良いのでは?真ん中が完全ランダムなのでここの出来次第ですが。

 

まとめ

コードで構図をコントロールすることを試行してみました。

しかし、これ、オブジェクトの形の話であって、全体の構図としては結局「日の丸構図」のままなのでは…

 

QooQ