p5.js : 加算合成を試してみる

Processingでは、OpenGLを使うかPixel配列を操作する方法が選択できます。p5jsでもそれは同様ですが、OpenGLを利用する場合はp5.jsの範疇を超えてWebGLを使うなどする必要があるので、必然的にPixel配列操作になります。

ここでは、p5.jsでPixel配列操作による加算合成をしてみたので、記事にしておきたいと思います。

※ちなみに、すごい計算が重いです。なので実用性はあまりないかも…WebGLを勉強したらBlendとくらべてみたいです。

加算合成の考え方

加算合成は、ProcessingでのPixel配列によるパーティクル表現の記事がとても参考になりました。

Proce55ing.walker,blog » Blog Archive » 光り輝くパーティクルを作ってみよう

Photoshopなどでお馴染みの加算合成ですが、簡単に言うと色を足し算しているだけです。 参照先の記事にあるように、RGB系であれば足せば足しただけ白に近づくように表現することができます。

このコードをベースにして、3原色による色加算の様子がわかる簡単なアプリを作成してみたいと思います。

p5.jsのPixel配列

Processingでは、各Pixelの色は一つの要素に格納され、シフトによって各色を取り出していますが、p5.jsではRGBAの順に各Pixelの要素が配列要素に順に格納されています。

Processing

int r = pixels[pixelIndex] >> 16 & 0xFF;
int g = pixels[pixelIndex] >> 8 & 0xFF;
int b = pixels[pixelIndex] & 0xFF;

p5.js

pixels[i] = red(pink);
pixels[i+1] = green(pink);
pixels[i+2] = blue(pink);
pixels[i+3] = alpha(pink);

なので、Processingコードを参考に組む場合は、for文によって各Pixelにアクセスするロジックをp5.js用にケアする必要があります。

加算合成された四角形の描画

マウス位置に応じて、RGB各色の四角形がずれて、重なっている部分が加算合成されて白くなってみえる様子がわかるスケッチです。

f:id:tomoyukim:20150509225105p:plain

http://tomoyukim.net/gallery/ (ADDITIVE)

以下がコードになります。 計算量を減らすためにCanvasサイズを150x150にしてあり、その中に100x100の3原色の四角形を描画します。

    var posX = new Array();
    var posY = new Array();
    var direction = 1;

    function setup() {
      createCanvas(150,150);
      frameRate(30);
    }

    function draw() {
      background(0);
      var start = 0;
      var end = width*4;
      var top = 0;
      var bottom = height;

      var diffX = map(mouseX, 0, windowWidth, 0, 20);
      var diffY = map(mouseY, 0, windowHeight, 0, 20);
      posX[0] = width/2;
      posY[0] = height/2;
      posX[1] = width/2+diffX;
      posY[1] = height/2+diffY;
      posX[2] = width/2-diffX;
      posY[2] = height/2-diffY;

      loadPixels();
      for(var col = 0; col < 3; col++) {
        for(var y = top; y <= bottom; y++) {
          for(var x = start; x <= end; x+=4) {
            var pixelIndex = x + y * end;
            var dx = posX[col] - x/4;
            var dy = posY[col] - y;
            if (abs(dx) < 50 && abs(dy) < 50) {
              var c = pixels[pixelIndex + col];
              c += 255;
              pixels[pixelIndex + col] = c;
            }
          }
        }
      }
      updatePixels();
    }

ちなみに、このロジックのまま

background(255);
...
      c-=255;

と変更すると、CMYKで黒い四角形を描画することができます。