Classic Demo Effects, Twister

1 month ago 6

The twister effect is one of the most iconic demoscene effects. It simulates the twisting motion of a cuboid that is made of a soft, pliable material.

The mathematical background behind this visual effect is suprisingly simple.

Imagine a cuboid sliced into thin wafers from top to bottom. For each slice, we essentially have a 2D quad, which is mathematically defined by four points: x0, x1, x2, x3. When we view the geometry standing in front of it, each of these slices will appear as a horizontal line.

The cuboid sliced into with wafers

Our image is a 2D plane and each of the slices essentially appears and behaves as a 1D line. All we can see is a horizontal line that maps to one of the edges of the respective quad.

For each quad, the 1D position of its points is calculated using the formula below:

\[x_i = sin(a + \frac{\pi}{2} * i )\]

where a is a phase value.

Each quad has 4 edges: x1-x2, x2-x3, x3-x4, x4-x1.

We need to draw all of the visible edges. Practically, in most cases there will be two edges visible. When a slice is aligned to 90 degree intervals, there will only be one edge visible.

The following condition can determine whether an edge is visible or not. Occluded edges are obviously not drawn.

\[x_{start} < x_{end}\]

A single slice, top and side views

Below is an implementation of the twister effect and its live preview in shadertoy.

#define P2 1.57079632679 define E (0.07) // Edge width define T iTime // Time define C vec3(.15) // Background Color define A vec2(.5,1.5) // Amplitude XY define S(x) texture(iChannel0, vec2(2.43, 1) * x).xyz // Texture void mainImage(out vec4 c, vec2 p) vec2 u = p.xy/iResolution.xy*2.-1.; vec3 r = C; float v[4]; for (int i = 0; i < 4; ++i) v[i] = A.x * sin(A.y * sin(u.y * cos(T)) + (cos(T) + P2 * float(i))); for (int i = 0; i < 4; ++i) { float n = v[int(mod(float(i)+1.,4.))], p = v[i]; if (n-p > 0. && u.x < n && u.x > p) { float k = n-p, x = (u.x-p) / k; r = k * S(vec2( x * A.x, u.y * A.y)); float l = smoothstep(0., A.x * E, x) * smoothstep(0., A.x * E, 1.-x); r *= pow(l, 32.); } } c = vec4(r, 1); }
Read Entire Article