ギンの備忘録

デジタルアートやプログラミングやテクノロジー関連のこと。

青海波文様を描く【p5.jsで和柄】

青海波文様をp5.jsを使って描きます。

青海波文様

青海波文様は半円形を重ねたものを鱗状に並べた文様です。 波を表した文様で、平安時代雅楽の舞曲「青海波」が名前の由来だそうです。

作例

f:id:gin_graphic:20210424170644p:plain:w300

カラーパレット["#4267D8", "#DDDeF1"]

f:id:gin_graphic:20210424170650p:plain:w300

カラーパレット["#F3F3FA", "#D9213C"]

ソースコード

const w=720; //キャンバスサイズ
const draw_num = 4; //一方向に円を何個並べるか
const draw_size = w/draw_num; //円一個の大きさ
const mark_num = 8; //円一つ当たり何個の円で描くか
const mark_size = draw_size/mark_num;
const set_color=["#4267D8", "#DDDeF1"]; //描くための二色を指定

function setup() {
   createCanvas(w, w);
   noStroke();

   for(let j=0;j<4*(draw_num+1);j++){
      const y = draw_size/4 * j; //縦方向は円の大きさの4分の1ずつ移動させる
      const dx = (j%2==1) ? draw_size/2 : 0 ; //縦方向が奇数番目であれば横方向に円半個分移動

      for(let i=0;i<draw_num+1;i++){
         const x = draw_size * i; //横方向は円一個分ずつ移動
         push();
         translate(x+dx, y);

         //一つの描画
         for(let k=0;k<mark_num;k++){
          fill(set_color[k%2]); //二色を交互に設定する
          circle(0, 0, mark_size * (mark_num-k)); //外側の円描いていく
         }

         pop();
      }
   }
}

二色の円を順番に重ね、それを並べることで青海波を表現しました。

鱗文様を描く【p5.jsで和柄】

鱗文様をp5.jsを使って描きます。

鱗文様

鱗文様は正三角形あるいは二等辺三角形を上下左右に連続して配置した文様です。 三角の連なりが魚や龍、蛇の鱗に似ていることから鱗文と呼ばれるようになったそうです。

作例

f:id:gin_graphic:20210422204216p:plain:w300

f:id:gin_graphic:20210422204221p:plain:w300

ソースコード

const w=720;
const N=10;
const d=w/N;
const setcol=[]
setcol[0]=["#623768", "#c4aee1"];
setcol[1]=["#69B1EC", "#D39577"];

function setup() {
   createCanvas(w, w);
   ellipseMode(CORNER);
   noStroke();

   col = random(setcol);
   noLoop();
}

function draw() {
   for(let i=0;i<N;i++){
      const x = d*i;
      for(let j=0;j<N;j++){
         const y = d*j;
         const mode = (j%2==0);
         push();
         translate(x, y);
         pattern(0, 0, d, mode);
         pop();
      }
   }
}

function pattern(x, y, size, mode){
   const point = [];
   point[0] = [0, 0];
   point[1] = [size/2, 0];
   point[2] = [size, 0];
   point[3] = [0, size];
   point[4] = [size/2, size];
   point[5] = [size, size];

   push();
   translate(x, y);
   if(mode==true){
     fill(col[0]);
     triangle(...point[0], ...point[3], ...point[1]);
     triangle(...point[2], ...point[5], ...point[1]);
     fill(col[1]);
     triangle(...point[4], ...point[3], ...point[1]);
     triangle(...point[4], ...point[5], ...point[1]);
   } else{
      fill(col[0]);
      triangle(...point[1], ...point[0], ...point[4]);
      triangle(...point[1], ...point[2], ...point[4]);
      fill(col[1]);
      triangle(...point[3], ...point[0], ...point[4]);
      triangle(...point[5], ...point[2], ...point[4]);
   }
   pop();
}

三角形のパターンを上下の二種類生成して、それを並べることで表現しています。

七宝文様を描く【p5.jsで和柄】

七宝文様をp5.jsを使って描きます。

七宝文様

七宝文様は円の上に同じ大きさの円を四分の一ずつ重ね、それを並べた文様です。 光を表す菱のような形と花びらのような形の組み合わせが見えるという仕掛けになっています。

作例

f:id:gin_graphic:20210421072552p:plain:w300

f:id:gin_graphic:20210421072546p:plain:w300

ソースコード

const w=720;
const N=10;
const d=w/N;
const setcol=[]
setcol[0]=["#223768", "#54aee1"];
setcol[1]=["#B9416C", "#D3B5A7"];

function setup() {
   createCanvas(w, w);
   ellipseMode(CORNER);
   noFill();
   strokeWeight(d/20);

   col = random(setcol);
   noLoop();
}

function draw() {
   background(col[0])
   for(let i=0;i<N;i++){
      const x = d*i;
      for(let j=0;j<N;j++){
         const y = d*j;
         push();
         stroke(col[1]);
         translate(x, y);
         circle(0, 0, d);
         pop();
      }
   }

   for(let i=0;i<N+1;i++){
      const x = d*(i-0.5);
      for(let j=0;j<N+1;j++){
         const y = d*(j-0.5);
         push();
         stroke(col[1]);
         translate(x, y);
         circle(0, 0, d);
         pop();
      }
   }
}

円を重ねる表現は、円を並べるforループを2つ記述して生成しています。

市松文様を描く【p5.jsで和柄】

和柄の中でも有名な市松文様。

この市松文様をp5.jsを使って描きます。

市松文様

市松は二色の四角形を交互に配した文様です。 今回は二色の正方形を用いて、市松文様を表現します。

作例

f:id:gin_graphic:20210419073520p:plain:w300

f:id:gin_graphic:20210419073514p:plain:w300

ソースコード

const w=720;
const N=10*2-1;
const d=w/N;
const setcol=[]
setcol[0]=["#52b788", "#344e41"];
setcol[1]=["#D9713C", "#ffd597"];

function setup() {
   createCanvas(w, w);
   noStroke();

   col = random(setcol);
   noLoop();
}

function draw() {
   for(let i=0;i<N;i++){
      const x = d*i;
      for(let j=0;j<N;j++){
         const y = d*j;
         push();
         fill(col[(i+j)%2]);
         translate(x, y);
         rect(0, 0, d);
         pop();
      }
   }
}

ソース内のsetcolに二色の組み合わせを用意しておきます。 setcolからランダムに選ぶようにしました。

ランダムウォークで作るGenerativArt

ランダムウォークの軌跡

ランダムウォークというのは進む方向をランダムに決めて動いた時の軌跡のことです。

黒い四角形をランダムウォークさせてみます。 動く方向を上下左右にランダムに決めて動かしていきます。 すると下のような線になります。これがランダムウォークさせた軌跡です。

f:id:gin_graphic:20210402125511p:plain:w150 f:id:gin_graphic:20210402125515p:plain:w150 f:id:gin_graphic:20210402125519p:plain:w150

ソースコードを表示する

function setup() {
   const w = 720;
   createCanvas(w, w);

   rectMode(CENTER);
   colorMode(HSB);
   noStroke();

   const N=1;
   let p=[];

   for(let i=0;i<N;i++){
     p[i]={ x: int(w/2),
            y: int(w/2),
            size: int(5),
            func: rect,
            color: [0, 0, 0, 1]
     }
   }

   background(100);

   for(let k=0;k<10000;k=k+1){
      for(let i=0;i<N;i=i+1){
        push();
        const pp = p[i];
        fill(...pp.color);
        translate(pp.x, pp.y);
        pp.func(0, 0, pp.size);
        pop();

        const r =  pp.size;
        p[i].x += int(random(-1, 1)*r);
        p[i].y += int(random(-1, 1)*r);
      }
   }
}

透明度を変えたランダムウォーク

ランダムウォークさせた時の軌跡を描く際に、透明度を変化させてみます。 透明度を時間経過するごとに減少させていくと、徐々に描く軌跡が薄くなり、最後には消えます。 このようにすることで、最後がかすれたような表現になり、筆っぽい雰囲気が出ると思います。

f:id:gin_graphic:20210402130245p:plain:w150 f:id:gin_graphic:20210402130250p:plain:w150 f:id:gin_graphic:20210402130255p:plain:w150

ソースコードを表示する

function setup() {
   const w = 720;
   createCanvas(w, w);

   rectMode(CENTER);
   colorMode(HSB);
   noStroke();

   const N=1;
   let p=[];

   for(let i=0;i<N;i++){
     p[i]={ x: int(w/2),
            y: int(w/2),
            size: int(5),
            func: rect,
            color: [0, 0, 0, 1]
     }
   }

   background(100);

   const L=3000;
   for(let k=0;k<L;k=k+1){
      for(let i=0;i<N;i=i+1){
        push();
        const pp = p[i];
        fill(...pp.color);
        translate(pp.x, pp.y);
        pp.func(0, 0, pp.size);
        pop();

        const r =  pp.size;
        p[i].x += int(random(-1, 1)*r);
        p[i].y += int(random(-1, 1)*r);
        p[i].color[3] -= 1/L;
      }
   }
}

多数の図形をランダムウォーク

多数の図形をランダムウォークさせてみます。 更に色もランダムに着けてみます。

これで一つの形になり、作品になりました。

f:id:gin_graphic:20210402131343p:plain:w150 f:id:gin_graphic:20210402131337p:plain:w150 f:id:gin_graphic:20210402131332p:plain:w150

ソースコードを表示する

function setup() {
   const w = 720;
   createCanvas(w, w);

   rectMode(CENTER);
   colorMode(HSB);
   noStroke();

   const N=100;
   let p=[];

   for(let i=0;i<N;i++){
     p[i]={ x: int(w/2),
            y: int(w/2),
            size: int(5),
            func: rect,
            color: [int(random([230, 240, 250])),
                    int(random(100)),
                    int(100),
                    int(1)
                   ]
     }
   }

   background(100);

   const L=3000;
   for(let k=0;k<L;k=k+1){
      for(let i=0;i<N;i=i+1){
        push();
        const pp = p[i];
        fill(...pp.color);
        translate(pp.x, pp.y);
        pp.func(0, 0, pp.size);
        pop();

        const r =  pp.size;
        p[i].x += int(random(-1, 1)*r);
        p[i].y += int(random(-1, 1)*r);
        p[i].color[3] -= 1/L;
      }
   }
}

作例

最後に色の付け方や図形の大きさを変え、移動や透明度の時間変化をパラメータで色々と調整します。 これでランダムウォークを使った作品の完成です。

試行錯誤しながらこの形に辿り着きました。 かなりお気に入りの作品になって嬉しいです。(その嬉しさがこの記事をまとめたモチベーション)

f:id:gin_graphic:20210331210559p:plain:w350

f:id:gin_graphic:20210331210605p:plain:w350

ソースコードを表示する

function setup() {
   const w = 720;
   createCanvas(w, w);

   rectMode(CENTER);
   colorMode(HSB);
   noStroke();

   const N=1200;
   let p=[];
   const col=[];
   col[0] = [200,220, 180, 20];
   col[1] = [30, 50, 10, 360, 270];

   const sel_col = random(col);

   for(let i=0;i<N;i++){
     p[i]={ x: int(random(w)),
            y: int(random(w)),
            size: int(random(3, 20)),
            func:random([ellipse, ellipse, rect]),
            color: [ int(random(sel_col)),
                     int(random(0, 80)),
                     int(random(70, 100)),
                     random(0.5, 1.5)
            ]
     }
   }

   background(100);

   for(let k=0;k<720;k=k+1){
      const t = k / 20;
      const r = 3*sin(t) + 3 ;
      const s = r / 1500;

      for(let i=0;i<N;i=i+1){
        push();
        const pp = p[i];
        fill(...pp.color);
        translate(pp.x, pp.y);
        pp.func(0, 0, pp.size);
        pop();

        p[i].x += int(random(-1, 1)*r);
        p[i].y += int(random(-1, 1)*r);
        p[i].color[3] -= s + random(-1, 1)/300;
      }
   }
}

//save PNG
function mousePressed() {
   save("img_" + month() + day() + hour() + minute() + second() + ".png");
}

まとめ

今回はランダムウォークを作品に取り入れてみました。 ランダムウォークの軌跡も上手く使うと作品に面白さが出ますね。 皆さんの作品へも取り入れてみてはいかがでしょうか。