Created
July 11, 2016 15:57
-
-
Save erikaderstedt/a4eba3d7f311d7aa7f0cd967d14058c7 to your computer and use it in GitHub Desktop.
Core Image kernel for the Genie effect
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// ASGenieKernel.cikernel | |
// | |
// (c) Aderstedt Software AB 2008. | |
// Erik Aderstedt 2008-09-05. | |
// | |
kernel vec4 ASGenieKernel(sampler src, float t, float D, float ytarget, float scale) | |
{ | |
// Given a point (destCoord) we are tasked to find its colour. | |
// We do it by finding a source point (takeFrom) and take its | |
// colour. If no source point can be found, we return the | |
// colour (0.0,0.0,0.0,0.0). | |
// Given a point in the original image, where do we end up? | |
// A transformation from takeFrom -> destCoord. | |
// At t = 0: destCoord = takeFrom. | |
// At t = 1: destCoord = (takeFrom - ytarget)*D/ymax + ytarget | |
// At t = t: destCoord = takeFrom*(1-t) + t*((takeFrom - ytarget)*D/ymax + ytarget) | |
// = takeFrom*(1-t+t*D/ymax) + t*ytarget-t*ytarget*D/ymax | |
// = takeFrom*(1-t*(1-D/ymax)) + t*ytarget*(1-D/ymax) | |
// -> takeFrom.y = (destCoord.y - t*ytarget*(1-D/ymax))/(1-t*(1-D/ymax)) | |
// destCoord.y = ymax, D = 0.04*ymax, t = 0.5 -> (ymax - 0.5*ytarget*0.96)/(1-0.5*0.96). ymax = 1, ytarget = 0.5 -> 0.75/0.5 -> 1.5. | |
// If takeFrom.y is out of bounds, we set the alpha to 0 and return immediately. | |
// | |
// Use an envelope function. From 1 to 0. (1-tan((x/xmax * pi/2) - pi/4))/2. | |
// Multiply the t value with that in the expression above. | |
// For t > 1 we also transform the x coordinate using a simple linear transformation. | |
// At t > 1 the y shape is fixed, so we set t = 1 before applying the envelope (but after | |
// applying the transformation). | |
vec2 takeFrom; // In destination coordinates. | |
vec2 original = samplerCoord(src); | |
vec2 size; | |
float g, t2, a; | |
vec4 c; | |
size = samplerSize(src); | |
original = vec2(original.x / scale, original.y / scale); | |
t2 = compare(t-1.0,t,1.0); | |
takeFrom.x = original.x + compare(t-1.0,0.0,1.0)*size.x*(t-1.0); | |
a = compare(takeFrom.x, 0.0, 1.0); | |
a = compare(a-0.5,0.0,compare(takeFrom.x-size.x, 1.0, 0.0)); | |
// Apply an envelope. This is where non-linearity is introduced. | |
t2 = t2 * (1.0 - tan_(1.57*original.x/size.x - 0.78539))*0.5; | |
g = 1.0 - D / size.y; | |
takeFrom.y = (original.y - t2*ytarget*g)/(1.0-t2*g); | |
a = compare(a-0.5,0.0,compare(takeFrom.y, 0.0, 1.0)); | |
a = compare(a-0.5,0.0,compare(takeFrom.y-size.y, 1.0, 0.0)); | |
takeFrom.x = compare(takeFrom.x, 0.0, takeFrom.x); | |
takeFrom.x = compare(takeFrom.x-size.x, takeFrom.x, 0.0); | |
takeFrom.y = compare(takeFrom.y, 0.0, takeFrom.y); | |
takeFrom.y = compare(takeFrom.y-size.y, takeFrom.y, 0.0); | |
takeFrom = vec2(takeFrom.x*scale, takeFrom.y*scale); | |
c = sample(src, takeFrom); | |
c.w = a; | |
return c; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment