Documentation

Shader Example: Cloud Tunnel

<div class="playground_container">

Shader Example: Cloud Tunnel

Live Demo

Fragment Shader

Copy paste from below to see its effect; Use the Divooka version when using with Shader Lab in Divooka.

Snippets

WebGL

precision mediump float;
uniform vec2 u_Resolution;
uniform float u_Time;
uniform vec3 u_Mouse; // x, y, pressed

#define TAU 6.28318530718

mat2 rot(float a)
{
    float c = cos(a), s = sin(a);
    return mat2(c, -s, s, c);
}

float hash21(vec2 p)
{
    p = fract(p * vec2(123.34, 456.21));
    p += dot(p, p + 45.32);
    return fract(p.x * p.y);
}

float noise(vec2 p)
{
    vec2 i = floor(p);
    vec2 f = fract(p);

    float a = hash21(i);
    float b = hash21(i + vec2(1.0, 0.0));
    float c = hash21(i + vec2(0.0, 1.0));
    float d = hash21(i + vec2(1.0, 1.0));

    vec2 u = f * f * (3.0 - 2.0 * f);

    return mix(mix(a, b, u.x), mix(c, d, u.x), u.y);
}

float fbm(vec2 p)
{
    float v = 0.0;
    float a = 0.5;

    for (int i = 0; i < 6; i++)
    {
        v += a * noise(p);
        p = rot(0.5) * p * 2.0 + 0.17;
        a *= 0.5;
    }

    return v;
}

vec3 palette(float t)
{
    vec3 a = vec3(0.5, 0.5, 0.5);
    vec3 b = vec3(0.5, 0.5, 0.5);
    vec3 c = vec3(1.0, 1.0, 1.0);
    vec3 d = vec3(0.00, 0.15, 0.35);

    return a + b * cos(TAU * (c * t + d));
}

float starLayer(vec2 uv, float depth, float t)
{
    vec2 gv = fract(uv) - 0.5;
    vec2 id = floor(uv);

    float n = hash21(id + depth * 37.1);
    float size = mix(0.004, 0.03, pow(n, 8.0));

    vec2 offset = vec2(
        sin(t * (0.7 + n * 1.3) + n * 40.0),
        cos(t * (0.9 + n * 1.1) + n * 57.0)
    ) * 0.12;

    float d = length(gv - offset);
    float star = smoothstep(size, 0.0, d);

    star += 0.35 * smoothstep(size * 4.0, 0.0, d);
    return star * step(0.985, n);
}

vec3 stars(vec2 uv, float t)
{
    vec3 col = vec3(0.0);

    for (int i = 0; i < 4; i++)
    {
        float fi = float(i);
        float depth = fract(fi * 0.23 + t * 0.03);
        float scale = mix(16.0, 2.5, depth);
        float fade = depth * smoothstep(1.0, 0.8, depth);

        vec2 suv = uv * scale + vec2(depth * 31.7, depth * 19.3);
        float s = starLayer(suv, fi, t);
        vec3 scol = mix(vec3(0.4, 0.7, 1.0), vec3(1.0, 0.8, 0.9), fract(fi * 0.37));

        col += s * fade * scol;
    }

    return col;
}

void main()
{
    vec2 uv = (gl_FragCoord.xy - 0.5 * u_Resolution.xy) / u_Resolution.y;
    float t = u_Time;

    // Camera / drift
    vec2 p = uv;
    p *= rot(0.15 * sin(t * 0.23));
    p += 0.06 * vec2(sin(t * 0.7), cos(t * 0.5));

    // Radial warp
    float r = length(p);
    float a = atan(p.y, p.x);
    float spiral = a + 0.9 / max(r, 0.15) + t * 0.35;

    vec2 q = vec2(
        spiral * 0.9,
        2.0 / (r + 0.25) + t * 0.25
    );

    // Plasma fields
    float n1 = fbm(q * 1.2);
    float n2 = fbm((q + vec2(3.1, -1.7)) * 1.8 - t * 0.08);
    float n3 = fbm((p * 3.0 + vec2(n1, n2) * 2.0) + t * 0.15);

    float plasma = n1 * 0.55 + n2 * 0.3 + n3 * 0.15;

    // Bright filament bands
    float bands = sin(10.0 * r - t * 3.0 + plasma * 5.0);
    bands = pow(0.5 + 0.5 * bands, 6.0);

    // Core glow
    float core = 0.08 / (r * r + 0.02);
    core *= 0.7 + 0.3 * sin(t * 2.0 + plasma * 8.0);

    // Coloring
    float hue = plasma * 0.7 + r * 0.25 - t * 0.03;
    vec3 col = palette(hue);

    // Emphasize bright structures
    col *= 0.35 + 1.8 * plasma * plasma;
    col += vec3(0.4, 0.7, 1.2) * bands * 0.9;
    col += vec3(0.7, 0.9, 1.4) * core;

    // Add stars behind the plasma
    vec2 suv = uv * (1.0 + r * 0.35);
    col += stars(suv, t) * (1.0 - smoothstep(0.0, 0.9, plasma));

    // Vignette
    float vignette = smoothstep(1.4, 0.2, length(uv));
    col *= vignette;

    // Soft bloom-ish curve
    col = 1.0 - exp(-col * 1.25);

    // Slight contrast / gamma
    col = pow(col, vec3(0.92));

    gl_FragColor = vec4(col, 1.0);
}

ShaderToy

#define TAU 6.28318530718

mat2 rot(float a)
{
    float c = cos(a), s = sin(a);
    return mat2(c, -s, s, c);
}

float hash21(vec2 p)
{
    p = fract(p * vec2(123.34, 456.21));
    p += dot(p, p + 45.32);
    return fract(p.x * p.y);
}

float noise(vec2 p)
{
    vec2 i = floor(p);
    vec2 f = fract(p);

    float a = hash21(i);
    float b = hash21(i + vec2(1.0, 0.0));
    float c = hash21(i + vec2(0.0, 1.0));
    float d = hash21(i + vec2(1.0, 1.0));

    vec2 u = f * f * (3.0 - 2.0 * f);

    return mix(mix(a, b, u.x), mix(c, d, u.x), u.y);
}

float fbm(vec2 p)
{
    float v = 0.0;
    float a = 0.5;

    for (int i = 0; i < 6; i++)
    {
        v += a * noise(p);
        p = rot(0.5) * p * 2.0 + 0.17;
        a *= 0.5;
    }

    return v;
}

vec3 palette(float t)
{
    vec3 a = vec3(0.5, 0.5, 0.5);
    vec3 b = vec3(0.5, 0.5, 0.5);
    vec3 c = vec3(1.0, 1.0, 1.0);
    vec3 d = vec3(0.00, 0.15, 0.35);

    return a + b * cos(TAU * (c * t + d));
}

float starLayer(vec2 uv, float depth, float t)
{
    vec2 gv = fract(uv) - 0.5;
    vec2 id = floor(uv);

    float n = hash21(id + depth * 37.1);
    float size = mix(0.004, 0.03, pow(n, 8.0));

    vec2 offset = vec2(
        sin(t * (0.7 + n * 1.3) + n * 40.0),
        cos(t * (0.9 + n * 1.1) + n * 57.0)
    ) * 0.12;

    float d = length(gv - offset);
    float star = smoothstep(size, 0.0, d);

    star += 0.35 * smoothstep(size * 4.0, 0.0, d);
    return star * step(0.985, n);
}

vec3 stars(vec2 uv, float t)
{
    vec3 col = vec3(0.0);

    for (int i = 0; i < 4; i++)
    {
        float fi = float(i);
        float depth = fract(fi * 0.23 + t * 0.03);
        float scale = mix(16.0, 2.5, depth);
        float fade = depth * smoothstep(1.0, 0.8, depth);

        vec2 suv = uv * scale + vec2(depth * 31.7, depth * 19.3);
        float s = starLayer(suv, fi, t);
        vec3 scol = mix(vec3(0.4, 0.7, 1.0), vec3(1.0, 0.8, 0.9), fract(fi * 0.37));

        col += s * fade * scol;
    }

    return col;
}

void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
    vec2 uv = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;
    float t = iTime;

    // Camera / drift
    vec2 p = uv;
    p *= rot(0.15 * sin(t * 0.23));
    p += 0.06 * vec2(sin(t * 0.7), cos(t * 0.5));

    // Radial warp
    float r = length(p);
    float a = atan(p.y, p.x);
    float spiral = a + 0.9 / max(r, 0.15) + t * 0.35;

    vec2 q = vec2(
        spiral * 0.9,
        2.0 / (r + 0.25) + t * 0.25
    );

    // Plasma fields
    float n1 = fbm(q * 1.2);
    float n2 = fbm((q + vec2(3.1, -1.7)) * 1.8 - t * 0.08);
    float n3 = fbm((p * 3.0 + vec2(n1, n2) * 2.0) + t * 0.15);

    float plasma = n1 * 0.55 + n2 * 0.3 + n3 * 0.15;

    // Bright filament bands
    float bands = sin(10.0 * r - t * 3.0 + plasma * 5.0);
    bands = pow(0.5 + 0.5 * bands, 6.0);

    // Core glow
    float core = 0.08 / (r * r + 0.02);
    core *= 0.7 + 0.3 * sin(t * 2.0 + plasma * 8.0);

    // Coloring
    float hue = plasma * 0.7 + r * 0.25 - t * 0.03;
    vec3 col = palette(hue);

    // Emphasize bright structures
    col *= 0.35 + 1.8 * plasma * plasma;
    col += vec3(0.4, 0.7, 1.2) * bands * 0.9;
    col += vec3(0.7, 0.9, 1.4) * core;

    // Add stars behind the plasma
    vec2 suv = uv * (1.0 + r * 0.35);
    col += stars(suv, t) * (1.0 - smoothstep(0.0, 0.9, plasma));

    // Vignette
    float vignette = smoothstep(1.4, 0.2, length(uv));
    col *= vignette;

    // Soft bloom-ish curve
    col = 1.0 - exp(-col * 1.25);

    // Slight contrast / gamma
    col = pow(col, vec3(0.92));

    fragColor = vec4(col, 1.0);
}