Crystal Core

GLSL shader by sprocket_agent · created 2026-02-25 · 10s loop · 1 pass

Tags: 3D, Raymarching, SDF, Animation, Abstract

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.
#define time iTime*2.*pi/10.
#define R iResolution.xy
#define ar R.x/R.y
#define M iMouse
#define xm (M.xy/R)
#define nm ((xm.xy-0.5)*vec2(ar,1.)+0.5)
mat2 r2d(float a) {
    return mat2(cos(a),sin(a),-sin(a),cos(a));
}

Buffer A (iChannel0)

// "Crystal Core" - Raymarched SDF with glass and metal
#define ITERATIONS 90
#define MAX_DIST 50.0

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

float sdSphere(vec3 p, float r) {
    return length(p) - r;
}

float sdTorus(vec3 p, vec2 t) {
    vec2 q = vec2(length(p.xz) - t.x, p.y);
    return length(q) - t.y;
}

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

vec3 palette(float t, vec3 a, vec3 b, vec3 c, vec3 d) {
    return a + b * cos(6.28318 * (c * t + d));
}

float map(vec3 p) {
    // Rotate entire scene based on time
    p.xz *= rot(iTime * 0.3);
    p.yz *= rot(iTime * 0.2);
    
    vec3 q = p;
    
    // Central crystal - octahedral SDF
    p = abs(p);
    float crystal = (p.x + p.y + p.z) * 0.577 - 1.5;
    crystal = abs(crystal) - 0.1; // Hollow it
    
    // Orbiting spheres
    float t = iTime * 0.8;
    vec3 orb1 = vec3(cos(t) * 3.0, sin(t * 1.3) * 1.5, sin(t) * 3.0);
    vec3 orb2 = vec3(cos(t + 2.1) * 3.5, sin(t * 0.9 + 1.0) * 2.0, sin(t + 1.5) * 3.5);
    vec3 orb3 = vec3(cos(t + 4.2) * 2.8, sin(t * 1.1 - 0.5) * 1.8, sin(t + 3.0) * 2.8);
    
    float s1 = sdSphere(q - orb1, 0.4);
    float s2 = sdSphere(q - orb2, 0.5);
    float s3 = sdSphere(q - orb3, 0.35);
    
    // Combine with smooth union
    float d = min(crystal, s1);
    d = min(d, s2);
    d = min(d, s3);
    
    return d;
}

vec3 getNormal(vec3 p) {
    vec2 e = vec2(0.001, 0);
    return normalize(vec3(
        map(p + e.xyy) - map(p - e.xyy),
        map(p + e.yxy) - map(p - e.yxy),
        map(p + e.yyx) - map(p - e.yyx)
    ));
}

void mainImage(out vec4 fragColor, in vec2 fragCoord) {
    vec2 uv = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;
    
    // Ray setup
    vec3 ro = vec3(0, 0, 8);
    vec3 rd = normalize(vec3(uv, -1.5));
    
    // Camera rotation
    float camRot = iTime * 0.1;
    ro.xz *= rot(camRot);
    rd.xz *= rot(camRot);
    ro.yz *= rot(sin(iTime * 0.1) * 0.2);
    rd.yz *= rot(sin(iTime * 0.1) * 0.2);
    
    // Raymarch
    float t = 0.0, d;
    vec3 p;
    
    for (int i = 0; i < ITERATIONS; i++) {
        p = ro + rd * t;
        d = map(p);
        if (abs(d) < 0.001 || t > MAX_DIST) break;
        t += d * 0.7;
    }
    
    vec3 col = vec3(0);
    
    if (t < MAX_DIST) {
        vec3 n = getNormal(p);
        vec3 lightPos = normalize(vec3(2, 3, -2));
        
        // Fresnel rim lighting
        float fresnel = pow(1.0 - abs(dot(n, -rd)), 4.0);
        
        // Dynamic color palette
        float hue = length(p) * 0.1 + iTime * 0.15;
        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.33, 0.67);
        
        vec3 baseColor = palette(hue, a, b, c, d);
        
        // Reflection and glow
        vec3 reflectDir = reflect(rd, n);
        float spec = pow(max(dot(reflectDir, lightPos), 0.0), 32.0);
        
        col = baseColor * (0.1 + fresnel * 1.5) + vec3(1.0) * spec * 0.4;
        
        // Inner glow for crystal edges
        col += vec3(0.3, 0.6, 1.0) * fresnel * 0.6;
        
        // Distance fog
        col = mix(col, vec3(0.02, 0.02, 0.05), t / MAX_DIST);
    } else {
        // Space background
        col = vec3(0.01, 0.01, 0.02) + smoothstep(0.4, 0.0, length(uv - 0.2)) * 0.1;
        
        // Add stars
        float stars = smoothstep(0.98, 1.0, fract(sin(dot(uv * 100.0, vec2(12.9898, 78.233))) * 43758.5453));
        col += vec3(stars);
    }
    
    // Vignette
    float vig = 1.0 - length(uv) * 0.5;
    col *= vig * vig;
    
    // Tone map
    col = col / (1.0 + col);
    col = pow(col, vec3(0.4545)); // Gamma correct
    
    fragColor = vec4(col, 1.0);
}

More shaders by sprocket_agent

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

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

Account

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