ギンの備忘録

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

よつばと15巻の発売記念にダンボーを描く

p5.jsでダンボーを描く

よつばと15巻が発売です。 とても嬉しく、喜ばしいことですね。

この喜びを表すためにp5.jsでダンボーを描きました。

画像を貼り付けておきます。

f:id:gin_graphic:20210227075949p:plain:w250f:id:gin_graphic:20210227075932p:plain:w250f:id:gin_graphic:20210227075944p:plain:w250f:id:gin_graphic:20210227075937p:plain:w250

ダンボーの描写

関数function danbo(x, y, size, tex)ダンボーを描いています。 ダンボーは顔の四角形、目の円、口の三角形で構成されるので、シンプルに描画できます。

顔の模様はテクスチャを作成して、四角形に貼り付けています。

模様テクスチャは

  • 縦縞
  • 横縞
  • ランダム円
  • ランダム四角形
  • パーリンノイズ

を作りました。 それぞれ、2色の色をランダムに選んで模様にしています。

Openproccessing

Openproccessingの方にもアップしておきました。 ランダムでダンボーを描きます。

www.openprocessing.org

ソースコード

let vs = `
   precision highp float;
   precision highp int;

   attribute vec3 aPosition;
   attribute vec2 aTexCoord;

   varying vec2 vTexCoord;

   uniform mat4 uProjectionMatrix;
   uniform mat4 uModelViewMatrix;

    void main() {
      vec4 positionVec4 = vec4(aPosition, 1.0);
      gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;
      vTexCoord = aTexCoord;
   }
`;

let fs = `
   precision highp float;
   precision highp int;

   varying vec2 vTexCoord;

   uniform sampler2D u_tex;
   uniform float u_time;

   float pi = 3.14159265358979;

   float rand(vec2 co) {
     float a = fract(dot(co, vec2(2.067390879775102, 12.451168662908249))) - 0.5;
     float s = a * (6.182785114200511 + a * a * (-38.026512460676566 + a * a * 53.392573080032137));
     float t = fract(s * 43758.5453);
     return t;
   }

   void main() {
      vec2 uv = vTexCoord;

      float radius = 0.0035;
      uv.x = uv.x + rand(uv + u_time*0.02)*radius ;
      uv.y = uv.y + rand(uv + u_time*0.01)*radius;
      vec4 tex = texture2D(u_tex, uv);

      gl_FragColor = tex;
    }
`;

const w = 720;
const N = 5;
const span = w/N;

let theShader ;
let pg ;
let obj = new Array(N);

function setup() {
  setAttributes("alpha", false);
  setAttributes("premultipliedAlpha", true);
  setAttributes("antialias", true);
  setAttributes("depth", true);
  setAttributes("powerPreference", "high-performance");

  createCanvas(w, w, WEBGL);
  //noStroke();
  drawingContext.enable(drawingContext.BLEND);

  theShader = createShader(vs, fs);
  pg = createGraphics(w*1.25, w*1.25);

  rectMode(CENTER);
  colorMode(HSB);
  noLoop();


  for(let i=0;i<N;i+=1){
    obj[i] = new Array(N);
    for(let j=0;j<N;j+=1){
      obj[i][j] = new danbo_obj(span*(i+0.5), span*(j+0.5), span*0.95);
    }
  }
}

function draw(){
  background(random(360), random(30,50), random(90,100));

  push();
  translate(-w/2, -w/2)

  for(let i=0;i<N;i+=1){
    for(let j=0;j<N;j+=1){
      obj[i][j].draw();
    }
  }
  pop();

  let tex = get();
  shader(theShader);
  theShader.setUniform(`u_tex`, tex);
  theShader.setUniform(`u_time`, frameCount/200);

  clear();
  fill(0, 0, 0, 0);
  rect(0, 0, w);

}

 function danbo(x, y, size, tex){
   const w = size;
   const h = size * 0.65;

   const eye_span = size * 0.42;
   const eye_d = size * 0.125;
   const eye_y = y - h*0.5*0.15;

   const mouth_y = y + h*0.5*0.5;
   const mouth_d = eye_d*0.85;

   const mouth_y0 = mouth_y - mouth_d*0.5;
   const mouth_y1 = mouth_y + mouth_d*0.5;
   const mouth_x0 = x+mouth_d*0.8;
   const mouth_x1 = x-mouth_d*0.8;

   push();
   strokeWeight(size/32);
   stroke("#202020");
   texture(tex);
   rect(x, y, w, h);
   pop();

   push();
   strokeWeight(0);
   fill("#202020");
   ellipse(x + eye_span*0.5, eye_y, eye_d, eye_d);
   ellipse(x - eye_span*0.5, eye_y, eye_d, eye_d);

   triangle(x, mouth_y0, mouth_x0, mouth_y1, mouth_x1, mouth_y1);
   pop();
 }

function rand_color(){
   return color(random(360), random(20, 100), random(50, 100));
}

class danbo_obj{
   constructor(x, y, size){
      this.x = x;
      this.y = y;
      this.size = size;
      this.tex = this.gen_tex();
   }

   draw(){
     danbo(this.x, this.y, this.size, this.tex);
   }

   gen_tex(){
    let pg = createGraphics(this.size, this.size*0.65);

    const p = random(0.6);

    if(p<0.1){
      this.line_v_tex(pg);
    } else if(p<0.2){
      this.line_h_tex(pg);
    } else if(p<0.3){
      this.dot_tex(pg);
    } else if(p<0.4){
      this.rect_tex(pg);
    } else if(p<0.5){
      this.noise_tex(pg);
    } else{
      this.normal_tex(pg);
    }

    return pg;
   }

   normal_tex(pg){
    pg.colorMode(HSB);
    pg.background(rand_color());
   }

   line_v_tex(pg){
    pg.colorMode(HSB);
    pg.noStroke();
    pg.background(rand_color());
    pg.fill(rand_color());

    const line_num = int(random(5,16));
    for(let i=0;i<line_num;i+=2){
      pg.rect(pg.width/line_num*i, 0, pg.width/line_num, pg.height);
    }
   }

   line_h_tex(pg){
    pg.colorMode(HSB);
    pg.noStroke();
    pg.background(rand_color());
    pg.fill(rand_color());

    const line_num = int(random(5,16));
    for(let i=0;i<line_num;i+=2){
      pg.rect(0, pg.height/line_num*i, pg.width, pg.height/line_num);
    }
   }

   dot_tex(pg){
    pg.colorMode(HSB);
    pg.noStroke();
    pg.background(rand_color());
    pg.fill(rand_color());

    const dot_num = int(random(10,70));
    for(let i=0;i<dot_num;i+=2){
      let x = random(pg.width);
      let y = random(pg.height);
      pg.ellipse(x, y, random(random(pg.width/2)));
    }
   }

   rect_tex(pg){
    pg.colorMode(HSB);
    pg.rectMode(CENTER);
    pg.noFill();
    pg.background(rand_color());
    pg.stroke(rand_color());
    pg.strokeWeight(random(0.5, 4));

    const dot_num = int(random(3,30));
    for(let i=0;i<dot_num;i+=2){
      let x = random(pg.width);
      let y = random(pg.height);
      pg.rect(x, y, random(random(pg.width/2)));
    }
   }

   noise_tex(pg){
    pg.colorMode(HSB);
    pg.noStroke();
    pg.background(rand_color());

    const noiseVal = random(1,50);
    const cellSize = int(random(2,5));
    const seed = random(1);

    let col = rand_color();

    for (let y=0; y*cellSize < pg.height; y++) {
      for (let x=0; x*cellSize < pg.width; x++) {
          let alpha = noise(x/noiseVal, y/noiseVal, seed) *1.5;
          col.setAlpha(alpha);
          pg.fill(col);
          pg.rect(x*cellSize, y*cellSize, cellSize, cellSize);
      }
    }

   }
}

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