Processingで残像表現を実現する

風邪で咳が3週間ぐらい止まりません。問答無用で腹筋が鍛えられてます。早くマスクから卒業したいです。

今日はProcessingで残像表現を実現する方法について書いてみたいと思います。

簡易的な残像表現

まずはProcessingでよく使われる、半透明のrectを利用したシンプルな残像表現を行ってみます。

draw関数の中で通常backgroundでクリアするところを、次のように半透明のrectを使ってクリアすることで、簡易的に残像表現を実現することができます。

void draw() {
  fill(255, 250);
  rect(0, 0, width, height);
  // 以下描画処理
}

簡易的な残像表現の例

実際の動作例です。

この方法はお手軽でいいのですが、背景が単色か一枚絵の時しか使えず、アレンジも難しいところが難点です。

オフスクリーンバッファを使った残像表現

続いて表示画面のコピーを利用した、もう少し凝った残像表現を行ってみます。

オフスクリーンバッファの準備

最初に表示画面のコピー先(オフスクリーンバッファ)を用意します。PImage変数を用意してsetup関数で以下のように初期化します。

PImage offscr;

void setup() {
  size(300, 300);
  offscr = createImage(width, height, RGB);
}

オフスクリーンバッファの更新と描画

次にdraw関数でオフスクリーンバッファの更新と描画を行います。

void draw() {
  // オフスクリーンバッファの更新
  loadPixels();
  offscr.pixels = pixels;
  offscr.updatePixels();

  // 通常の描画処理

  // オフスクリーンバッファの描画
  tint(255, 240);
  image(offscr, -3, -3, width + 6, height + 6); // 少しだけ拡大してみる
}

オフスクリーンバッファの描画では、tint命令を使って半透明で画像を上描きします。この際に画像の描画サイズや色を変えることで、様々な効果を作り出すことができます。

オフスクリーンバッファを使った残像表現の例

実際にサンプルを作って動かしてみます。

int x, vx;
PImage offscr;

void setup() {
  size(300, 300);
  background(0);

  x = 100;
  vx = 2;
  offscr = createImage(width, height, RGB);
}

void draw() {
  x += vx;
  if (x < 50 || x > width - 50) { vx = -vx; }

  loadPixels();
  offscr.pixels = pixels;
  offscr.updatePixels();

  background(0);
  noStroke();
  fill(128, 255, 128);
  ellipse(x, 150, 100, 100);

  tint(255, 240);
  image(offscr, -3, -3, width + 6, height + 6);
}

先ほどとは違う雰囲気の残像表現が実現できました。

終わりに

今回はloadPixelsを利用して画面のコピーを行ったのですが、もしかするとPGraphicsを使ってオフスクリーンレンダリング(別画面への描画)をした方が高速に動作するかもしれません。(風邪が治ったら)そのうち試してみたいですね。