/** Spot Lighting Dave Bollinger, Dec 2006 http://www.davebollinger.com for Processing 0123 Beta Quick & Dirty Spot Lighting Move mouse to change light position The effect is similar to additive blending, but is actually multiplicative, so doesn't tend to whitewash as much as additive. The formula is basically RGB' = RGB * (1+light) (though it appears slightly different in coded form due to minor factoring) To compare: Press 'a' or 'A' to use additive blending Press 's' or 'S' to use multiplicative (spotlight) blending */ PImage src, dst, spot; boolean useAdditiveMode = false; void setup() { size(200,200,P3D); src = loadImage("eames.jpg"); dst = src.get(); spot = loadImage("spot.jpg"); } void draw() { if (useAdditiveMode) { background(src); blend(spot, 0, 0, 160, 160, mouseX-80, mouseY-80, 160, 160, ADD); } else { applyLight(src,dst,mouseX,mouseY,80); background(dst); } } void keyPressed() { if ((key=='a') || (key=='A')) useAdditiveMode = true; if ((key=='s') || (key=='S')) useAdditiveMode = false; } int peg(int n) { return (n < 0) ? 0 : ((n > 255) ? 255 : n); } int isqrt(int n) { int guess=0; int bit = 1 << 15; do { guess ^= bit; if (guess * guess > n ) guess ^= bit; } while ((bit >>= 1) != 0); return guess; } // on-the-fly, not a blend (though it could be) void applyLight(PImage src, PImage dst, int lx, int ly, int rad) { int srcw = src.width, srch = src.height; int [] sp = src.pixels, dp = dst.pixels; int radsq = rad * rad; int idx = 0; for (int y=0; y> 16; int g = (c & 0xFF00) >> 8; int b = c & 0xFF; int q = 512 - (isqrt(distsq) << 8) / rad; dp[idx] = (c & 0xFF000000) | (peg((r*q)>>8) << 16) | (peg((g*q)>>8) << 8) | (peg((b*q)>>8) ); } else { dp[idx] = sp[idx]; } idx++; } } }