Back to shaders

Shader test bench

Fragment

zero-x7444ff-shader-art transition glsl runnable fragment MIT
Source
runnable fragment

Complete GLSL fragment shader. Stronghold runs it directly when the browser can compile it.

Code

precision mediump float;
uniform sampler2D uTexture1;
uniform sampler2D uTexture2;
uniform vec2 u_resolution;
uniform float u_time;
uniform float uTransition;
uniform float uPattern;

varying vec2 v_texcoord;

/* 
* * Helpers
*/
vec3 gammaCorrect(vec3 color, float gamma) {
    return pow(color, vec3(1.0 / gamma));
}

vec4 sround(vec4 s) {
    return floor(s + 0.5);
}

vec2 scaleUvs(vec2 uv, vec2 aspectCorrection) {
    return (uv - 0.5) * aspectCorrection + 0.5;
}

float hash(vec2 p) {
    return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123);
}

float floatNoise(vec2 uv) {
    vec2 i = floor(uv);
    vec2 f = fract(uv);
    float a = hash(i);
    float b = hash(i + vec2(1.0, 0.0));
    float c = hash(i + vec2(0.0, 1.0));
    float d = hash(i + vec2(1.0, 1.0));
    vec2 u = f * f * (3.0 - 2.0 * f);
    return mix(a, b, u.x) +
        (c - a) * u.y * (1.0 - u.x) +
        (d - b) * u.x * u.y;
}
vec3 mod289(vec3 x) {
    return x - floor(x * (1.0 / 289.0)) * 289.0;
}

vec2 mod289(vec2 x) {
    return x - floor(x * (1.0 / 289.0)) * 289.0;
}

vec3 permute(vec3 x) {
    return mod289(((x * 34.0) + 1.0) * x);
}

float simplexNoise(vec2 v) {
    const vec4 C = vec4(0.211324865405187, 0.366025403784439, -0.577350269189626, 0.024390243902439);
    vec2 i = floor(v + dot(v, C.yy));
    vec2 x0 = v - i + dot(i, C.xx);

    vec2 i1;
    i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
    vec4 x12 = x0.xyxy + C.xxzz;
    x12.xy -= i1;

    i = mod289(i);
    vec3 p = permute(permute(i.y + vec3(0.0, i1.y, 1.0)) + i.x + vec3(0.0, i1.x, 1.0));

    vec3 m = max(0.5 - vec3(dot(x0, x0), dot(x12.xy, x12.xy), dot(x12.zw, x12.zw)), 0.0);
    m = m * m;
    m = m * m;

    vec3 x = 2.0 * fract(p * C.www) - 1.0;
    vec3 h = abs(x) - 0.5;
    vec3 ox = floor(x + 0.5);
    vec3 a0 = x - ox;

    m *= 1.79284291400159 - 0.85373472095314 * (a0 * a0 + h * h);

    vec3 g;
    g.x = a0.x * x0.x + h.x * x0.y;
    g.yz = a0.yz * x12.xz + h.yz * x12.yw;
    return 130.0 * dot(m, g);
}

float remap(float value, float a, float b, float c, float d) {
    return c + (value - a) * (d - c) / (b - a);
}

/*
* * Grid generators
*/
float squareDistance(vec2 uv) {
    vec2 p = abs(uv);
    return max(p.x, p.y);
}

float hexagonDistance(vec2 uv) {
    vec2 s = vec2(1.0, 1.73205);
    vec2 p = abs(uv);
    return max(dot(p, s * 0.5), p.x);
}

float circleDistance(vec2 uv) {
    float dist = length(uv);
    float outerRadius = 0.49;
    float innerRadius = 0.45;
    return smoothstep(innerRadius - 0.02, innerRadius, dist) - smoothstep(outerRadius, outerRadius + 0.02, dist);
}

vec4 squareCoordinates(vec2 uv) {
    vec2 squareCenter = floor(uv) + 0.5;
    vec2 offset = uv - squareCenter;
    return vec4(offset, squareCenter);
}

vec4 hexCoordinates(vec2 uv) {
    vec2 s = vec2(1.0, 1.73205);
    vec4 hexCenter = sround(vec4(uv, uv - vec2(0.5, 1.0)) / s.xyxy);
    vec4 offset = vec4(uv - (hexCenter.xy * s), uv - ((hexCenter.zw + 0.5) * s));

    float dot1 = dot(offset.xy, offset.xy);
    float dot2 = dot(offset.zw, offset.zw);

    vec4 final1 = vec4(offset.xy, hexCenter.xy);
    vec4 final2 = vec4(offset.zw, hexCenter.zw);
    float diff = dot1 - dot2;
    vec4 final = mix(final1, final2, step(0.0, diff));

    return final;
}

vec4 circleCoordinates(vec2 uv) {
    vec2 circleCenter = floor(uv) + 0.5;
    vec2 offset = uv - circleCenter;
    float dist = length(offset);
    vec4 circleCoord = vec4(offset, circleCenter);
    return circleCoord;
}

void main() {
    vec2 aspectCorrection = vec2(1.0, u_resolution.y * 1.75 / u_resolution.x);
    vec2 correctedUvs = v_texcoord;

    // Barrel distortion effect
    vec2 barrelDistortionUvs = scaleUvs(correctedUvs, vec2(1.0 + length(v_texcoord - 0.5)));

    // Grid parameters
    float gridSize = 20.0;

    // Get all patterns with dynamic time distortion
    vec2 squareUv = barrelDistortionUvs * gridSize;
    vec4 squareCoords = squareCoordinates(squareUv);
    float squareDist = squareDistance(squareCoords.xy);
    float squareBorder = smoothstep(0.42, 0.5, squareDist);

    vec2 hexUv = barrelDistortionUvs * gridSize;
    vec4 hexCoords = hexCoordinates(hexUv);
    float hexDist = hexagonDistance(hexCoords.xy);
    float hexBorder = smoothstep(0.42, 0.50, hexDist);

    vec2 circleUv = barrelDistortionUvs * gridSize;
    vec4 circleCoords = circleCoordinates(circleUv);
    float circleDist = circleDistance(circleCoords.xy);
    float circleBorder = smoothstep(0.47, 0.48, circleDist);

    // Enhanced pattern blending using fract and time-based variation
    float patternFract = fract(uPattern);
    float patternBase = floor(uPattern);

    float currentPattern;
    vec2 blendedCoords;
    float patternDist;

    if(patternBase == 0.0) {
        currentPattern = mix(squareBorder, hexBorder, patternFract);
        blendedCoords = mix(squareCoords.zw, hexCoords.zw, patternFract);
        patternDist = mix(squareDist, hexDist, patternFract);
    } else if(patternBase == 1.0) {
        currentPattern = mix(hexBorder, circleBorder, patternFract);
        blendedCoords = mix(hexCoords.zw, circleCoords.zw, patternFract);
        patternDist = mix(hexDist, circleDist, patternFract);
    } else {
        currentPattern = mix(circleBorder, squareBorder, patternFract);
        blendedCoords = mix(circleCoords.zw, squareCoords.zw, patternFract);
        patternDist = mix(circleDist, squareDist, patternFract);
    }

    // Apply simplex noise and dynamic lighting influence
    float z = simplexNoise(blendedCoords * 0.5);
    float y = pow(1.0 - max(0.0, 0.5 - patternDist), 20.0) * 1.0;

    // Transition effects, controlled by pattern and time
    float offset = 0.2;
    float bounceTransition = 1.0 - smoothstep(0.0, 0.5, abs(uTransition - 0.5));
    float blendCut = smoothstep(v_texcoord.y - offset, v_texcoord.y + offset, remap(uTransition + z * 0.08 * bounceTransition, 0.0, 1.0, -1.0 * offset, 1.0 + offset));
    float merge = 1.0 - smoothstep(0.0, 0.5, abs(blendCut - 0.5));
    float cut = step(v_texcoord.y, uTransition + (((y + z) * 0.15) * bounceTransition));

    vec2 textureUV = correctedUvs + (y * sin(v_texcoord.y * 15.0 - u_time) * merge * 0.025);
    vec2 fromUV = textureUV;
    vec2 toUV = textureUV;
    float colorBlend = merge * currentPattern * bounceTransition;

    fromUV = scaleUvs(fromUV, vec2(1.0 + z * 0.2 * merge));
    toUV = scaleUvs(toUV, vec2(1.0 + z * 0.2 * blendCut));

    // Apply textures with smooth blending
    vec4 texture1 = texture2D(uTexture1, toUV);
    vec4 texture2 = texture2D(uTexture2, fromUV);

    // Final color mixing with gradient background and texture blend
    vec3 topColor = gammaCorrect(vec3(0.55, 0.5, 0.27), 1.2);
    vec3 bottomColor = gammaCorrect(vec3(0.32, 0.14, 0.8), 1.2);
    vec4 final_color = mix(texture1, texture2, cut) + vec4(mix(topColor, bottomColor, 0.5), 1.0) * colorBlend * 2.0;

    // Apply post-processing effects like bloom or light scattering (optional)
    final_color.rgb += (sin(u_time * 2.0) * 0.1) * colorBlend * 2.0;

    gl_FragColor = final_color;
}