processingで加算処理

画像とソースコード参照サイト様からの引用。
ソースコードに理解用のコメントを自分で加えています。
f:id:peroon:20090803002218j:image
以下はソースコード。参照サイト様からlight.jpgをダウンロードして、
processingエディタにD&Dすればそのまま動きます。
ここにも一応置いておきますが、サイズが変わってしまって
表示されているかもしれません。light.jpg
f:id:peroon:20090803002524j:image
jpg画像を「加算」することで透過画像のように
扱っています。黒は値で0なのでうまくいきます。
たまにlight.jpg画像が連続で重なるときがあって、
そのときはとても明るくなるのが印象的です。

//思ったこと
//ウィンドウサイズを1000ずつ増やすとリサージュみたいな動きだとわかる
//変数宣言がキチキチ
//見とれる。。。

import processing.opengl.*;
import javax.media.opengl.*;

PGraphicsOpenGL pgl;  //?
GL gl;  //?

PImage light01;

int oldX,oldY,oldZ;
float rot,ss;
ArrayList aLight01;
int[] cl,dcl;

void setup() {
  size(640,480,OPENGL);  
  background(0);
  pgl = (PGraphicsOpenGL) g;  //こうする
  gl = pgl.gl;  //こうする
  light01 = loadImage("light.jpg");  //jpgなのに透過処理みたいに見えるのが加算のすごいところ!
  oldX = 0;
  oldY = 0;
  oldZ = 0;
  rot = 0;//rotation?
  ss = 0;//theta?
  aLight01 = new ArrayList();
  for (int i=0;i<=5;i++) {
    aLight01.add(new Light01()); 
  }
  cl = new int[3];
  cl[0] = 0;
  cl[1] = 0;
  cl[2] = 0;
  dcl = new int[3];
  dcl[0] = ceil(random(1,4));//2〜4
  dcl[1] = ceil(random(1,4));//delta colorの略で、colorの変化量
  dcl[2] = ceil(random(1,4));
}

void draw() {
  translate(width/2,height/2);  //move live lissajous around center
  
  //gradually black
  fill(0, 8);
  rect(-width/2, -height/2, width, height);
  
  //setup?ok
  pgl.beginGL();
  gl.glDisable(GL.GL_DEPTH_TEST);
  gl.glEnable(GL.GL_BLEND);  //これを入れることで光のように見える
  gl.glBlendFunc(GL.GL_ONE,GL.GL_ONE);
  pgl.endGL();

  //画像表示
  for (int i=0;i<aLight01.size();i++) {
    Light01 lt = (Light01) aLight01.get(i);
    lt.update();
    translate(0,0,lt.getZ());
    tint(cl[0], cl[1], cl[2]);
    image(light01,lt.getX(),lt.getY(),lt.getW(),lt.getW());
    translate(0,0,-lt.getZ());
  }
  
  //color change
  for (int i=0;i<3;i++) {
    cl[i]+=dcl[i];
    if (dcl[i]>0&&cl[i]>255) {  //up to down
      cl[i] = 255;
      dcl[i] = -ceil(random(1,4));
    } else if (dcl[i]<0&&cl[i]<0) {  //down to up
      cl[i] = 0;
      dcl[i] = ceil(random(1,4));
    }
  }
}


class Light01 {
  int xx,yy,zz,ww,rx,ry,rz;
  float sx,dsx,sy,dsy,sz,dsz;
  Light01() {
    xx = 0;
    yy = 0;
    zz = 0;
    ww = 50;//image width
    rx = ceil(random(150,300));//rotation radius
    ry = ceil(random(150,300));
    rz = ceil(random(150,400));
    sx = 0;//theta xの略?
    dsx = PI/random(18,72);//rotation speed
    sy = 0;
    dsy = PI/random(18,72);
    sz = 0;
    dsz = PI/random(18,72);
  }
  void update() {
    xx = ceil(sin(sx)*rx);
    yy = ceil(sin(sy)*ry);
    zz = ceil(sin(sz)*rz);
    sx += dsx;
    sy += dsy;
    sz += dsz;
  }
  int getX() {
   return xx-ww; 
  }
  int getY() {
   return yy-ww; 
  }
  int getZ() {
   return zz; 
  }
  int getW() {
   return ww*2; 
  }
}