Project_2026-03-01_18-18-20

GLSL shader by scry · created 2026-03-02 · 10s loop · 2 passes

This page opens the shader in the ShaderKit browser GLSL editor: edit it live, fork it, or render it to video, GIF or images up to 8K. Also available as a full-screen view and an embeddable player.

Shader source (GLSL)

Common

#define pi acos(-1.)
#define deg pi/180.  //1 degree
#define time iTime*2.*pi/40. //sin(time) loops 10 seconds
#define R iResolution.xy //shorthand
#define ar R.x/R.y //aspect ratio
#define M iMouse //shorthand
#define xm (M.xy/R) //normalized mouse
#define nm ((xm.xy-0.5)*vec2(ar,1.)+0.5) //aspect ratio correction
vec3 cs = vec3(1.,2.,3.);
mat2 r2d(float a) {
    return mat2(cos(a),sin(a),-sin(a),cos(a));
}

float sdBox(vec3 p, vec3 b) {
    vec3 q = abs(p) - b;
    return length(max(q, 0.0)) + min(max(q.x, max(q.y, q.z)), 0.0);
}

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

vec2 hash22(vec2 p) {
    return fract(sin(vec2(dot(p,vec2(127.1,311.7)),dot(p,vec2(269.5,183.3))))*43758.5453);
}

Buffer A (iChannel0)

// Scene SDF
float mapScene(vec3 p) {
    vec3 bp = p;
    bp.xz *= r2d(0.6);
    bp.xy *= r2d(0.4);
    bp.yz *= r2d(time * 0.5);
    //bp = abs(bp)-14.;
    //bp = abs(bp)-14.;
    for (int i=0;i<39;i++) {
        bp = abs(bp)-0.03+sin(time+bp.yzx*2.)*0.01;
        bp.xz *= r2d(cos(time/4.));
        bp.yz *= r2d(cos(time/4.));
    }
    float cube = sdBox(bp, vec3(0.03+sin(time*2.+pi/2.)*0.01));
    return cube;
}

vec3 calcNorm(vec3 p) {
    vec2 e = vec2(0.001, 0.0);
    return normalize(vec3(
        mapScene(p + e.xyy) - mapScene(p - e.xyy),
        mapScene(p + e.yxy) - mapScene(p - e.yxy),
        mapScene(p + e.yyx) - mapScene(p - e.yyx)
    ));
}

vec2 raymarch(vec3 ro, vec3 rd) {
    float t = 0.0;
    float steps = 0.0;
    for (int i = 0; i < 180; i++) {
        vec3 p = ro + rd * t;
        float d = mapScene(p)/2.5;
        if (d < 0.001 || t > 130.0) break;
        t += d;
        steps += 1.0;
    }
    return vec2(t, steps);
}

// Voronoi star field
float starField(vec2 uv) {
    float scale = 30.0;
    vec2 id = floor(uv * scale);
    vec2 gv = fract(uv * scale) - 0.5;

    float minDist = 1.0;
    for (int y = -1; y <= 1; y++) {
        for (int x = -1; x <= 1; x++) {
            vec2 offset = vec2(float(x), float(y));
            vec2 n = hash22(id + offset);
            vec2 p = offset + n - 0.5;
            float d = length(gv - p);
            minDist = min(minDist, d);
        }
    }

    // Brightness varies per cell
    float brightness = hash21(id) ;
    brightness = pow(brightness, 8.0); // make most stars dim, few bright
    float star = smoothstep(0.05, 0.0, minDist) * brightness;

    // Twinkle
    float twinkle = sin(iTime * 2.0 + hash21(id) * 6.28) * 0.5 + 0.5;
    star *= mix(0.5, 1.0, twinkle);

    return star;
}

// Aurora effect
vec3 aurora(vec2 uv) {
    vec3 col = vec3(0.0);
    float y = uv.y;

    // Aurora only in upper portion
    //if (y < 0.1) return col;

    float intensity = smoothstep(0.1, .3, y) * smoothstep(0.95, 0.6, y)*0.5;
    intensity += 0.8;
    for (int i=0;i<4;i++) {
        //uv += sin(uv.xy*2.+3.+time)*0.1;
    }
    for (int i = 0; i < 5; i++) {
        float fi = float(i);
        float freq = 1.5 + fi * 0.7;
        float speed = 0.3 + fi * 0.1;
        float wave = sin(uv.x * freq * 3.0 + iTime * speed + fi * 1.3)
                    * cos(uv.x * freq * 1.7 - iTime * speed * 0.7 + fi * 2.1);
        wave = wave * 0.5 + 0.5;

        // Green/blue/purple aurora palette
        vec3 auroraCol = mix(
            vec3(0.1, 0.8, 0.3),
            vec3(0.3, 0.2, 0.9),
            fi / 5.0
        );
        auroraCol = mix(auroraCol, vec3(0.8, 0.2, 0.5), smoothstep(0.6, 0.9, y));

        col += auroraCol * wave * intensity * 0.35;
    }

    return col;
}

// Background
vec3 background(vec3 rd) {
    rd = normalize(rd);
    rd.xz *= r2d(deg*-190.);    
    
    // Sun
    vec3 sunColor = vec3(1.0, 0.95, 0.85);
    vec3 sunDir = normalize(vec3(2.0, 1.5, -3.0));
    float sunDot = max(dot(rd, sunDir), 0.0);
    vec3 sun = vec3(1.0, 0.95, 0.85) * pow(sunDot, 4000.0) * 80.0; // small bright disc
    sun += vec3(1.0, 0.8, 0.5) * pow(sunDot, 400.0) * 0.3; // subtle glow halo

    // Map ray direction to UV for sky
    vec3 wrd = rd;
    for (int i=0;i<14;i++) {
        wrd += sin(wrd.yxz*2.)*0.1;
        wrd.xz *= r2d(deg*220.+sin(time/4.+float(i))*deg*20.);
        wrd.yz *= r2d(deg*120.+sin(time/4.+float(i))*deg*20.);
    }
    vec2 skyUV = vec2(atan(wrd.z, wrd.x) + 0.5, wrd.y * 0.5 + 0.5);
    skyUV.x = sin(skyUV.x*2.);

    // Dark sky gradient
    vec3 sky = mix(vec3(0.01, 0.01, 0.03), vec3(0.02, 0.0, 0.06), skyUV.y);

    // Stars
    float stars = starField(skyUV * vec2(3.5, 1.2));
    sky += vec3(0.9, 0.9, 1.0) * stars * 1.5;
    for (int i=0;i<4;i++) {
        //skyUV += sin(skyUV.yx*14.)*0.1;
    }
    // Aurora
    sky += aurora(skyUV*1.)*0.01;

    return sky + sun;
}

void mainImage(out vec4 fragColor, in vec2 fragCoord) {
    vec2 uv = fragCoord.xy / iResolution.xy;
    vec2 p = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;
    p *= 4.0;
    // Camera
    //p.xz *= r2d(time);
    vec3 ro = vec3(0.0, 0.0, 3.5);
    vec3 rd = normalize(vec3(p, -6.5+sin(time/2.)*1.5));
    //ro.xz *= r2d(time);
    vec2 res = raymarch(ro, rd);
    float t = res.x;

    // Multi-bounce reflections for mirror stainless steel
    vec3 col = vec3(0.0);
    vec3 throughput = vec3(1.0);
    vec3 metalColor = vec3(0.85, 0.86, 0.88); // bright stainless steel
    float F0 = 0.7; // high base reflectivity for mirror steel

    vec3 curRo = ro;
    vec3 curRd = rd;
    
    vec3 sunDir = normalize(vec3(2.0, 1.5, -3.0));
    vec3 sunColor = vec3(1.0, 0.95, 0.85) * 3.5;

    for (int bounce = 0; bounce < 5; bounce++) {
        vec2 bres = (bounce == 0) ? res : raymarch(curRo, curRd);
        float bt = bres.x;
        col += bres.y*0.0002+sin(bres.y*0.2+cs+time*8.)*bres.y*bres.y*0.000002;
        //col += bt*0.001;
        if (bt >= 130.0) {
            // Ray escaped — sample background
            col += throughput * background(curRd * 4.0);
            //col += bres.y*0.001+sin(bres.y*0.2+cs+time*8.)*bres.y*bres.y*0.00001;
            break;
        }

        vec3 hp = curRo + curRd * bt;
        vec3 n = calcNorm(hp);
        vec3 viewDir = -curRd;

        // Fresnel (Schlick) — mirror steel has high reflectivity at all angles
        float cosTheta = max(dot(n, viewDir), 0.0);
        float fres = F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);

        // Sun lighting (matches background sun direction)
        vec3 halfDir = normalize(sunDir + viewDir);
        float sunDiff = max(dot(n, sunDir), 0.0);
        float sunSpec = pow(max(dot(n, halfDir), 0.0), 128.0);
        
        // Subtle fill light from opposite side
        vec3 fillDir = normalize(vec3(-1.0, 0.5, -1.0));
        float fillDiff = max(dot(n, fillDir), 0.0) * 0.2;

        // Diffuse colored ambient lights — green and purple
        vec3 greenLightDir = normalize(vec3(-1.5, 0.8, 1.0));
        vec3 purpleLightDir = normalize(vec3(1.0, -0.5, 1.5));
        vec3 greenLight = vec3(0.15, 0.9, 0.3) * 1.0 * max(dot(n, greenLightDir), 0.0);
        vec3 purpleLight = vec3(0.7, 0.15, 0.85) * 0.8 * max(dot(n, purpleLightDir), 0.0);
        
        // Warm ambient from below
        float upFace = dot(n, vec3(0.0, -1.0, 0.0)) * 0.5 + 0.5;
        vec3 ambientWarm = mix(vec3(0.05, 0.02, 0.08), vec3(0.08, 0.15, 0.06), upFace) * 0.5;

        // Add direct lighting contribution (non-reflected part)
        vec3 direct = metalColor * (sunDiff * 0.6 * sunColor + fillDiff * vec3(0.3, 0.35, 0.5));
        direct += sunSpec * sunColor * 15.; // bright sun specular
        direct += metalColor * (greenLight + purpleLight + ambientWarm);
        col += throughput * direct * (1.0 - fres)*0.15;
        col += sin(n.x+n.y+n.z*40.+cs)*0.008;
        // Attenuate throughput by fresnel reflectance * metal tint
        throughput *= fres * metalColor;

        // Set up next bounce
        curRd = reflect(curRd, n);
        curRo = hp + n * 0.005;
    }

    // Contrast boost before tone mapping
    col *= 1.4;
    
    // ACES tone map (punchier contrast than Reinhard)
    col = clamp((col * (2.51 * col + 0.03)) / (col * (2.43 * col + 0.59) + 0.14), 0.0, 1.0);
    col = pow(col, vec3(1.0 / 2.2));

    fragColor = vec4(col, 1.0);
}

Image

Not used

More shaders by scry

Browse all public shaders · All shaders by scry · ShaderKit home

Vibe Mode BETA
💰 ~0 credits
Uniforms
FPS: 0
Time: 0
Resolution: 0 x 0

Account

FPS: -- Time: -- --×-- 1x