PGraphics deformationEffect; PImage textureImg; int w, h; int[] mLUT; void setup(){ // set canvas size size(600,400); // create off-screen buffer deformationEffect = createGraphics(300, 200, JAVA2D); w = deformationEffect.width; h = deformationEffect.height; // create math lookup table(LUT) array mLUT = new int[3 * w * h]; // load texture textureImg=loadImage("water.jpg"); // use higher resolution textures if things get to pixelated // populate look up table with deformation effect createLUT(9); } // fill math lookup table values with crazy values void createLUT(int effectStyle){ // increment placeholder int k = 0; // u and v are euclidean coordinates float u,v,bright = 0; for( int j=0; j < h; j++ ) { float y = -1.00 + 2.00*(float)j/(float)h; for( int i=0; i < w; i++ ) { float x = -1.00 + 2.00*(float)i/(float)w; float d = sqrt( x*x + y*y ); float a = atan2( y, x ); float r = d; switch(effectStyle) { case 1: // hypnotic rainbow spiral v = sin(a+cos(3*r))/(pow(r,.2)); u = cos(a+cos(3*r))/(pow(r,.2)); bright = 1; break; default: // show texture with no deformation or lighting u = x; v = y; bright = 0; break; } mLUT[k++] = int(textureImg.width*u) & textureImg.width-1; mLUT[k++] = int(textureImg.height*v) & textureImg.height-1; mLUT[k++] = int(bright); } } } void draw() { int timeDisplacement = frameCount; deformationEffect.beginDraw(); deformationEffect.loadPixels(); // for every frame, go through every pixel and use the reference table (mLUT) to get which pixel of the texture it should draw at the current pixel. for (int pixelCount = 0; pixelCount < deformationEffect.pixels.length; pixelCount++) { int o = (pixelCount << 1) + pixelCount; // equivalent to 3 * pixelCount int u = mLUT[o+0] + timeDisplacement; // to look like its animating, add timeDisplacement int v = mLUT[o+1] + timeDisplacement; int adjustBrightness = mLUT[o+2]; // get the R,G,B values from texture color currentPixel = textureImg.pixels[textureImg.width * (v & textureImg.height-1) + (u & textureImg.width-1)]; // only apply brightness if it was calculated if (adjustBrightness != 0) { float r,g,b; // disassemble pixel using bit mask to remove color components for greater speed r = currentPixel >> 16 & 0xFF; // equivalent to red(currentPixel); g = currentPixel >> 8 & 0xFF; // equivalent to green(currentPixel); b = currentPixel & 0xFF; // equivalent to blue(currentPixel); // make darker or brighter r += adjustBrightness; g += adjustBrightness; b += adjustBrightness; // constrain RGB to make sure they are within 0-255 color range r = constrain(r,0,255); g = constrain(g,0,255); b = constrain(b,0,255); // reassemble colors back into pixel currentPixel = color(r,g,b); } // put texture pixel on buffer screen deformationEffect.pixels[pixelCount] = currentPixel; } deformationEffect.updatePixels(); deformationEffect.endDraw(); // display the results image(deformationEffect, 0, 0, width, height); } // pressing keyboard number keys(1-9) will switch between different effects void keyTyped() { switch(key) { case 49: // 1 key textureImg=loadImage("tex4_128.jpg"); createLUT(1); break; default: // any other key textureImg=loadImage("tex5_512.jpg"); createLUT(0); break; } }