画像とソースコードは参照サイト様からの引用。
ソースコードに理解用のコメントを自分で加えています。

以下はソースコード。参照サイト様からlight.jpgをダウンロードして、
processingエディタにD&Dすればそのまま動きます。
ここにも一応置いておきますが、サイズが変わってしまって
表示されているかもしれません。light.jpg

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;
}
}