ギンの備忘録

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

【p5.js】p5.jsでグリッチエフェクト

f:id:gin_graphic:20211208215429p:plain:w400

Processing Advent Calendar 2021の17日目の記事になります。

adventar.org

今回はp5.jsでグリッチエフェクトを行っていきます。

目次


グリッチエフェクト(Glitch Effect)

グリッチ(Glitch)は突発的な故障・不具合を意味し、映像や画像が乱れることを指します。
グリッチエフェクトは映像や画像を敢えて乱す表現方法になります。

グリッチアート - Wikipedia

簡単言ってしまうと、「画像を乱して壊す」のがグリッチエフェクトですね

下の図が今回グリッチエフェクトを掛けて乱した画像になります。

f:id:gin_graphic:20211204181347p:plain:w300

p5.jsでグリッチエフェクト

上で見た画像を作例として説明していきます。

ソースコードはこちら

ここでは静止画で作成して説明していくので、setup()へ記述して描画をしていきます。
setup()のコードは次の様になります。

function setup() {
  createCanvas(600, 600);

  let img = draw_image();

  img = draw_noise(img);
  img = draw_color_glitch(img, 5);
  img = draw_shift_glitch(img, 10);

  background(0);
  image(img, 0, 0);

  draw_scanline();
}

各処理を関数にしてまとめました。
以下で各処理の意味合いと実装について説明していきます。
各処理は適宜調整したり、要らない処理は消したりして、好みのグリッチにするのが良いと思います。

なんだかよくわからんという方は、draw_image()の記述を自分のコードに置き換えれば、 グリッチエフェクトを楽しめると思います。

できる方はcreateGraphics()を使って実装するのも良いかと思います。 今回はcreateGraphics()は説明するのを省くために使いませんでした。

元画像を生成

f:id:gin_graphic:20211204181331p:plain:w300

グリッチエフェクトを適用する元の画像を作成していきます。
元画像はdraw_image()関数として実装します。

function draw_image(){
  background(0);
  for(let i=0;i<10;i++){
    let size = 50;
    push();
    strokeWeight(0);
    fill(255);
    ellipse(random(width), random(height), size);
    pop();
  }

  let img = get();
  clear();

  return img;
}

背景色を黒にして、白い円を10個描いています。
円の大きさはsize = 50で固定の大きさにしています。
円はキャンバス内のランダムな位置に配置しています。

描画したものをget()で画像として変数imgに入れ、生成した絵を保持しておきます。

カラーチャンネルを乱す

f:id:gin_graphic:20211204181335p:plain:w300

画像のRGBのカラーチャンネル毎に位置をずらす処理を行います。
draw_color_glitch(img, shift_size)関数として実装します。

ここでは赤を左にずらして、緑と青を右にずらします。
赤色-水色の組み合わせで色グリッチを作ることができます。

function draw_color_glitch(img, shift_size){
  background(0);

  let left_color = color(255, 0, 0);
  let right_color = color(0, 255, 255);

  push();
  blendMode(ADD);

  tint(left_color);
  image(img, -shift_size, 0);

  tint(right_color);
  image(img, shift_size, 0);
  pop();
    
  let img_glitch = get();
  clear();

  return img_glitch;
}

tint()を使うと指定した色だけを抜き出して描画することができます。
詳細は下の記事で説明しているので、気になる方は読んでみて下さい。

gin-graphic.hatenablog.com

left_colorに赤、right_colorに緑青(水色)をtint()へ指定します。
左にずらした赤色と右にずらした水色をblendMode(ADD)で加算することで、
ズレた部分は赤色or水色に見えて、重なっている部分は元の色に近い状態になります。

また、このleft_colorright_colorの色を変えれば、赤色-水色以外の組み合わせで作ることもできます。

image(img, shift_size, 0)としているので、shift_sizeが左右にずらす幅になります。
好みで引数のshift_sizeを大きくしたり、小さくすることで画像の雰囲気が変わります。
大きくずらせばより崩れたエフェクトになりますが、大きくしすぎると元が判別できなくなるので注意してください。

ちなみに、image(img, 0, shift_size)とすれば縦方向に色のずれを加えたり、
image(img, shift_size, shift_size)で斜め方向にずらすことも可能です。
(逆側の変更も合わせて必要です。)

画像の一部を乱す

f:id:gin_graphic:20211204181339p:plain:w300

画像をランダムに切り貼りする処理を行います。
draw_shift_glitch(img, shift_size)関数として実装します。

ランダムに画像の一部を切り出して、切り出したものを左右にずらして貼り付けることで、 画像が壊れたような表現をしていきます。

function draw_shift_glitch(img, shift_size){
  background(0);    
  image(img, 0, 0);

  for(let i=0;i<100;i++){
    let sx = random(img.width*0.5);
    let sy = random(img.height*0.05);
    let x = random(img.width - sx*0.5);
    let y = random(img.height - sy*0.5);
    let ix = x + random(-1, 1)*shift_size;
    let iy = y ;

    image(img, ix, iy, sx, sy, x, y, sx, sy);
  }

  let img_glitch = get();
  clear();

  return img_glitch;
}

100回ランダムに画像の一部を切り出し、ずらして貼り付けました。

まず、sx, syで切り出すサイズをランダムに決定します。
ここでは横が最大img.width*0.5の乱数、縦が最大img.height*0.05の乱数を設定しています。
つまり、横長になりやすいような設定です。
切り出しサイズは好みで変えて下さい。

x, yで切り出し位置をランダムに決めます。 切り出し位置はサイズを考慮して、切り出しサイズの半分sx*0.5を用いて、random(img.width - sx*0.5)としています。

ix, iyが貼り付け位置です。貼り付け位置はx, yを起点として、引数のずらす幅shift_sizeでランダムにずらします。
今回は左右のずらすだけにしてixを計算しています。
iylet iy = y + random(-1, 1)*shift_size;などに変更すれば、上下にも切り出した部分をずらすこともできます。

ノイズを加える

f:id:gin_graphic:20211204181343p:plain:w300

ノイズを加える処理を行います。
draw_noise(img)関数として実装します。

ブロックノイズを加えて、更に画像を崩します。

function draw_noise(img){
  background(0);
  image(img, 0, 0);

  let noise_size = 5;

  push();
  strokeWeight(0);
  for(let i=0;i<img.width;i+=noise_size){
    for(let j=0;j<img.height;j+=noise_size){
      if(random()<0.5){
        fill(random([0, 255]), 100*noise(i, j));
        rect(i, j, noise_size);
      }
    }
  }
  pop();

  let img_noise = get();
  clear();

  return img_noise;
}

黒または白で透明度をnoise()で変化させた四角形でブロックノイズを表現しています。
noise_sizeでブロックノイズの大きさを指定しています。 画面作りの好みで大きさは調整して下さい。

四角形はf(random()<0.5)で50%の確率で描画しています。
ノイズを増やしたければ数値を上げ、減らしたければ数値を下げてください。

走査線を付ける

f:id:gin_graphic:20211204181347p:plain:w300

走査線を加える処理を行います。
draw_scanline()関数として実装します。

走査線を入れることで、アナログTVのような風合いを付けます。

走査線として横長の線を縦方向に並べて描画します。
画像を縮小しているとわからないですが、拡大してみると横線が描かれています。

function draw_scanline(){
  push();
  stroke(0, 50);
  strokeWeight(1);
  for(let i=0;i<height;i+=height/200){
    line(0, i, width, i);
  }
  pop();
}

処理は単純で全体の高さに対して等間隔に200本の線を描いてるだけです。
線の色は黒で透明度を50にして、うっすら線が描かれる様にしています。

作品へ使ってみる

作例としてp5.patternを使った作品にグリッチエフェクトを掛けてみます。

p5.patternはp5.js用のライブラリです。 p5.patternの詳細はこちら

ソースコードはこちら

f:id:gin_graphic:20211204181415p:plain:w300

f:id:gin_graphic:20211204181421p:plain:w300

この様に簡単に作品にグリッチエフェクトを適用できます。
カラーの画像に対してグリッチを適用するとアナログっぽさが出て、レトロ感のある作品になります。

写真に適用

写真に適用しても、良い雰囲気になります。

ソースコードはこちら

f:id:gin_graphic:20211204181352p:plain:h300

draw_image()を書き換えて写真にグリッチエフェクトを適用していきます。
写真にそのままグリッチエフェクトを適用しても良いのですが、ここでは少し処理をして見栄えを整えています。
写真のコントラストを上げ、彩度を落とす処理をしています。

特に必要なければ下の処理を行わずに、読み込んだ写真に上で説明したグリッチエフェクトを適用するだけでも構いません。

function draw_image(){
  image(photo, 0, 0);

  push();
  blendMode(HARD_LIGHT);
  image(photo, 0, 0);
  pop();

  filter(GRAY);

  push();
  blendMode(OVERLAY);
  tint(255, 200);
  image(photo, 0, 0);
  pop();

  let img = get();
  clear();
    
  return img;
}

初めにキャンバスに貼り付けた写真に対して、blendMode(HARD_LIGHT)を設定して再度写真を貼り付けます。
これにより写真のコントラストを上げています。
その後filter(GRAY)で白黒(グレースケール)にします。

blendMode(OVERLAY)を設定して、 元の写真を透明度を付けて(tint(255, 200))重ねることで 彩度を落とした雰囲気に仕上がります。

応用例

緑と紫でグリッチ

グリッチでずらす色を緑色と紫色にした作例。

ソースコードはこちら

f:id:gin_graphic:20211204181359p:plain:w300

グリッチを強くする

写真にグリッチを適用して、全体的にグリッチを強くした作例。

ソースコードはこちら

f:id:gin_graphic:20211204181404p:plain:h300

文字に適用

文字を使った作例。
更に一部の色を反転する処理を追加。

ソースコードはこちら

f:id:gin_graphic:20211204181410p:plain:w300

この作例は下の記事も参考にしてみて下さい。

gin-graphic.hatenablog.com

gin-graphic.hatenablog.com

まとめ

p5.jsでグリッチエフェクトを実現する方法を紹介しました。
中身が全て分からなくても、ソースコードをマネして貰えば、自分の作品や画像・写真に対して適応できる様にしたつもりです。
グリッチエフェクトを使ってみたり、遊んでみたりして、いつもの雰囲気と異なる作品を作ってみて下さい。

ここにある例だけがグリッチエフェクトではないので、他のグリッチエフェクトを実装してみても面白いと思います。

質問・指摘などあれば、SNSなどで気軽にコメント頂ければと思います。

参考

Photoshopで画像にグリッチノイズ風の効果をつける|Photoshopド定番チュートリアル|デザインする|デザインってオモシロイ -MdN Design Interactive-

Photoshopで画像にグリッチエフェクトを簡単にかける方法│RIoT DESIGN Studio