/* * Omino Glass * * Pixel Bender plugin by David Van Brink, 2010 * * Simulates glass refraction with chromatic aberration. */ kernel omino_glass_32 < displayname: "omino glass 32"; category: "omino"; namespace : "omino"; vendor : "omino"; version : 1; description : "refraction & aberration"; > { input image4 src; input image4 distort; output pixel4 dst; parameter int wrap < minValue : 0; maxValue: 1; aeUIControl:"aePopup"; aePopupString:"black|repeat"; >; parameter float refraction < minValue : -100.0; maxValue : 100.0; defaultValue : 5.0; aeDisplayName: "refraction"; >; parameter float aberration < minValue : -100.0; maxValue : 100.0; defaultValue : 5.0; aeDisplayName: "aberration"; >; parameter float featureSize < minValue : 5.0; maxValue : 500.0; defaultValue : 100.0; aeDisplayName: "feature size"; >; parameter int samples < minValue : 1; maxValue : 20; defaultValue : 2; aeDisplayName: "smoothing samples"; >; parameter float2 imageSize < minValue : float2(1,1); maxValue : float2(4096,4096); defaultValue : float2(1920,1080); aeUIControl: "aePoint"; aePointRelativeDefaultValue: float2(1,1); aeDisplayName: "image size"; >; pixel4 pluckColor(float2 xy,pixel4 rgb) { if(wrap > 0) xy = mod(xy,imageSize); pixel4 c = sampleLinear(src,xy); c *= rgb; return c; } pixel4 chromatizePixel(float2 xy,float2 offset) { pixel4 result = float4(0,0,0,0); result += pluckColor(xy - offset * 1.5,float4(.2,0,0,0.2)); result += pluckColor(xy - offset,float4(.3,0,0,0.2)); result += pluckColor(xy - offset / 2.0,float4(.5,.3333,0,0.2)); result += pluckColor(xy,float4(0,.33333,0,0.2)); result += pluckColor(xy + offset / 2.0,float4(0,.33333,.5,0.2)); result += pluckColor(xy + offset,float4(0,0,.3,.2)); result += pluckColor(xy + offset * 1.5,float4(0,0,.2,.2)); return result; } pixel4 evaluatePixelXy(float2 srcXy) { float srcX = srcXy.x; float srcY = srcXy.y; float4 zero = float4(0,0,0,0); float4 slopeX = float4(0,0,0,0); float4 slopeY = float4(0,0,0,0); float i; float n = float(samples); float xLow = max(0.0,srcX - n); float xHigh = min(imageSize.x,srcX + n); for(float x = xLow; x < xHigh; x++) slopeX += sampleNearest(distort,float2(x + 1.0,srcY)) - sampleNearest(distort,float2(x,srcY)); slopeX /= xHigh - xLow; float yLow = max(0.0,srcY - n); float yHigh = min(imageSize.y,srcY + n); for(float y = yLow; y < yHigh; y++) slopeY += sampleNearest(distort,float2(srcX,y + 1.0)) - sampleNearest(distort,float2(srcX,y)); slopeY /= yHigh - yLow; float2 sourceXy = srcXy + float2(slopeX.x,slopeY.x) * featureSize * refraction; float2 aberrXy = float2(slopeX.g,slopeY.g) * featureSize * aberration; if(srcX >= imageSize.x || srcY >= imageSize.y) { // or ditch all that... sourceXy = srcXy; aberrXy = float2(0,0); } pixel4 result = chromatizePixel(sourceXy,aberrXy); //pixel4 result = sampleNearest(src,srcXy + float2(slopeX.r,slopeY.g) * 300.0); result.a = 1.0; return result; } void evaluatePixel() { float4 s = float4(0,0,0,0); float2 oc = outCoord(); if(oc.x < imageSize.x && oc.y < imageSize.y) s += evaluatePixelXy(oc); dst = s; } }