#version 300 es precision highp float; uniform vec4 top_color; uniform vec4 bottom_color; uniform vec2 resolution; uniform float time; uniform float progress; in vec2 tex_coord; out vec4 fragment_color; // // 2-D tiling simplex noise with rotating gradients and analytical derivative. // "vec2 x" is the point (x,y) to evaluate, // "vec2 period" is the desired periods along x and y, and // "float alpha" is the rotation (in radians) for the swirling gradients. // The "float" return value is the noise value, and // the "out vec2 gradient" argument returns the x,y partial derivatives. // // Setting either period to 0.0 or a negative value will skip the wrapping // along that dimension. Setting both periods to 0.0 makes the function // execute about 15% faster. // // Not using the return value for the gradient will make the compiler // eliminate the code for computing it. This speeds up the function // by 10-15%. // // The rotation by alpha uses one single addition. Unlike the 3-D version // of psrdnoise(), setting alpha == 0.0 gives no speedup. // float psrdnoise(vec2 x, vec2 period, float alpha, out vec2 gradient) { // Transform to simplex space (axis-aligned hexagonal grid) vec2 uv = vec2(x.x + x.y*0.5, x.y); // Determine which simplex we're in, with i0 being the "base" vec2 i0 = floor(uv); vec2 f0 = fract(uv); // o1 is the offset in simplex space to the second corner float cmp = step(f0.y, f0.x); vec2 o1 = vec2(cmp, 1.0-cmp); // Enumerate the remaining simplex corners vec2 i1 = i0 + o1; vec2 i2 = i0 + vec2(1.0, 1.0); // Transform corners back to texture space vec2 v0 = vec2(i0.x - i0.y * 0.5, i0.y); vec2 v1 = vec2(v0.x + o1.x - o1.y * 0.5, v0.y + o1.y); vec2 v2 = vec2(v0.x + 0.5, v0.y + 1.0); // Compute vectors from v to each of the simplex corners vec2 x0 = x - v0; vec2 x1 = x - v1; vec2 x2 = x - v2; vec3 iu, iv; vec3 xw, yw; // Wrap to periods, if desired if(any(greaterThan(period, vec2(0.0)))) { xw = vec3(v0.x, v1.x, v2.x); yw = vec3(v0.y, v1.y, v2.y); if(period.x > 0.0) xw = mod(vec3(v0.x, v1.x, v2.x), period.x); if(period.y > 0.0) yw = mod(vec3(v0.y, v1.y, v2.y), period.y); // Transform back to simplex space and fix rounding errors iu = floor(xw + 0.5*yw + 0.5); iv = floor(yw + 0.5); } else { // Shortcut if neither x nor y periods are specified iu = vec3(i0.x, i1.x, i2.x); iv = vec3(i0.y, i1.y, i2.y); } // Compute one pseudo-random hash value for each corner vec3 hash = mod(iu, 289.0); hash = mod((hash*51.0 + 2.0)*hash + iv, 289.0); hash = mod((hash*34.0 + 10.0)*hash, 289.0); // Pick a pseudo-random angle and add the desired rotation vec3 psi = hash * 0.07482 + alpha; vec3 gx = cos(psi); vec3 gy = sin(psi); // Reorganize for dot products below vec2 g0 = vec2(gx.x,gy.x); vec2 g1 = vec2(gx.y,gy.y); vec2 g2 = vec2(gx.z,gy.z); // Radial decay with distance from each simplex corner vec3 w = 0.8 - vec3(dot(x0, x0), dot(x1, x1), dot(x2, x2)); w = max(w, 0.0); vec3 w2 = w * w; vec3 w4 = w2 * w2; // The value of the linear ramp from each of the corners vec3 gdotx = vec3(dot(g0, x0), dot(g1, x1), dot(g2, x2)); // Multiply by the radial decay and sum up the noise value float n = dot(w4, gdotx); // Compute the first order partial derivatives vec3 w3 = w2 * w; vec3 dw = -8.0 * w3 * gdotx; vec2 dn0 = w4.x * g0 + dw.x * x0; vec2 dn1 = w4.y * g1 + dw.y * x1; vec2 dn2 = w4.z * g2 + dw.z * x2; gradient = 10.9 * (dn0 + dn1 + dn2); // Scale the return value to fit nicely into the range [-1,1] return 10.9 * n; } float bounceOut(in float t) { const float a = 4.0 / 11.0; const float b = 8.0 / 11.0; const float c = 9.0 / 10.0; const float ca = 4356.0 / 361.0; const float cb = 35442.0 / 1805.0; const float cc = 16061.0 / 1805.0; float t2 = t * t; return t < a ? 7.5625 * t2 : t < b ? 9.075 * t2 - 9.9 * t + 3.4 : t < c ? ca * t2 - cb * t + cc : 10.8 * t * t - 20.52 * t + 10.72; } vec2 rot(vec2 v, float a){ return mat2x2( cos(a), -sin(a), sin(a), cos(a) ) * v; } float bounceIn(in float t) { return 1.0 - bounceOut(1.0 - t); } void main() { float PI = radians(180.0); vec2 st = tex_coord; st = rot(st, -PI / 2.0); vec2 gradient; float n = psrdnoise(vec2(3.) * st, vec2(0.), 3.0 * time, gradient); float lines = cos((st.x + n * 0.05 + progress * 0.8 + 0.1) * PI); if (tex_coord.y < 0.1 + progress * 0.9) { fragment_color = bottom_color; } else { fragment_color = mix(top_color, bottom_color, bounceIn(lines * 0.5 + 0.5)); } }