Plane deformation

Setup

The effect can be performed in a fragment shader on any textured quad with uv coords 'normalized' to place (0,0) at the center before performing any calculations.

the brick texture is sourced from the Pixar One Twenty Eight texture library

before deform after deform

Tunnel

A tunnel effect can be created by converting the the uv's to polar coordnate space and stretching things out a tad

``````void main() {
vec2 uv = vUv * 2.0 - 1.0;
gl_FragColor = deformationFunction(uv);
}
``````
``````vec2 deformationFunction(vec2 uv) {
vec2 p = uv;
float a = atan( p.y, p.x ) ;
float r = sqrt( dot(p,p) );
uv.x = 3.0/(r + .1);
uv.y = 3.0*a/3.1416;
return uv;
}
``````

Not quite what we want there's a large amount of distortion which makes the result looks nothing like a tunnel, the values for uv.x and uv.y are growing out of bounds (< 0.0 && > 1.0) one quick fix for this is clamping the result based on a threshold, grabbing the fractional component could also work

``````vec2 clampUv(vec2 uv, float m) {
return vec2( mod(uv.x, m), mod(uv.y, m));
}
``````

Now we have something that looks like a tunnel but not quite, what's missing is depth which can be added by applying a circular gradiant to the alpha channel 0.0 in the center expanding out to 1.0

Since uv coords were adjusted our coordnate space to have (0.0, 0.0) in the center we can just smoothstep the alpha component

``````float alpha = smoothstep(0.0, 0.5, length(uv.y));
``````

Expanding on what we have

With a base to work off we can continue experimenting with different deformations

Interpolation between scenes

Transitioning between deformations can be handled by mixing the computed uv values

``````    DistortOut a = doForScene(scene, p);
DistortOut b = doForScene(scene+1, p);
vec2 mixUV = mix(a.uv, b.uv, sceneDelta);
``````

Scene management

All that's left to do is figuring out which scene is being displayed and it's progress based on the current time

``````int sceneIndex(float time, float sceneLength, float totalScenes) {
float sceneIndex = time / sceneLength;
float scene = mod(floor(sceneIndex), totalScenes);
int sI = int(scene);
return sI;
}
``````
``````float sceneDelta(float time, float sceneLength) {
float sceneIndex = floor(time / sceneLength);
float sceneStartTime = (sceneIndex) * sceneLength;
float progress = time - sceneStartTime;
return progress / sceneLength;
}
``````

Result

https://dro.pe/luts