Project_2026-02-11_13-02-58
GLSL shader by scry · created 2026-02-11 · 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/10. //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));
}
Buffer A (iChannel0)
// Scene SDF
float hash31(vec3 p) {
p = fract(p * vec3(0.1031, 0.1030, 0.0973));
p += dot(p, p.yzx + 33.33);
return fract((p.x + p.y) * p.z);
}
vec4 map(vec3 p) {
float scene = 1e10;
// Animated twist
float twist = sin(time * 0.7) * 1.5;
// Torus knot-like shape via domain repetition + distortion
vec3 cellSize = vec3(6.0);
vec3 cellId = floor(p / cellSize + 0.5);
vec3 q = (fract(p / cellSize + 0.5) - 0.5) * cellSize;
// Per-cell random values for unique transforms
float h0 = hash31(cellId);
float h1 = hash31(cellId + 71.7);
float h2 = hash31(cellId + 143.3);
// Morphing phase offset per cell
float morph = sin(time * 0.5 + h0 * 6.28) * 0.5 + 0.5;
// Per-cell rotation speeds/offsets
q.xz *= r2d(time * (0.15 + h1 * 0.3) + h0 * 6.28);
q.yz *= r2d(time * (0.1 + h2 * 0.3) + h1 * 6.28);
// Twisted torus
float angle = atan(q.z, q.x);
vec3 tp = q;
tp.xz *= r2d(twist * angle);
vec2 torusQ = vec2(length(tp.xz) - 1.2, tp.y);
float torus = length(torusQ) - 0.35;
// Sphere
float sphere = length(q) - 1.0;
// Octahedron (approx)
vec3 aq = abs(q);
float octa = (aq.x + aq.y + aq.z - 1.3) * 0.577;
// Morph between shapes
float morphSelect = sin(time * 0.35 + h2 * 6.28) * 0.5 + 0.5;
scene = mix(torus, mix(sphere, octa, morph), morphSelect);
// Add displacement
float disp = sin(p.x * 5.0 + time * 2.0) * sin(p.y * 5.0 + time * 1.7) * sin(p.z * 5.0 + time * 1.3) * 0.06;
scene += disp;
return vec4(p, scene);
}
vec3 calcNormal(vec3 p) {
vec2 e = vec2(0.001, 0.0);
return normalize(vec3(
map(p + e.xyy).w - map(p - e.xyy).w,
map(p + e.yxy).w - map(p - e.yxy).w,
map(p + e.yyx).w - map(p - e.yyx).w
));
}
vec2 RM(vec3 ro, vec3 rd) {
float dO = 0.0;
float ii = 0.0;
for (int i = 0; i < 80; i++) {
vec3 p = ro + rd * dO;
float dS = map(p).w;
dO += dS;
ii += 1.0;
if (dO > 120.0 || dS < 0.001) break;
}
return vec2(dO, ii);
}
vec3 palette(float t, vec3 a, vec3 b, vec3 c, vec3 d) {
return a + b * cos(6.28318 * (c * t + d));
}
vec3 shade(vec3 ro, vec3 rd, float t, float steps) {
vec3 hitP = ro + rd * t;
vec3 n = calcNormal(hitP);
// Lighting
vec3 lightDir = normalize(vec3(1.0, 1.5, -0.5));
vec3 lightDir2 = normalize(vec3(-1.0, 0.5, 1.0));
float diff = max(dot(n, lightDir), 0.0);
float diff2 = max(dot(n, lightDir2), 0.0);
float spec = pow(max(dot(reflect(-lightDir, n), -rd), 0.0), 64.0);
float fres = pow(1.0 - max(dot(n, -rd), 0.0), 3.0);
// Iridescent color based on normal + view angle + time
float colorParam = dot(n, rd) * 0.5 + 0.5 + time * 0.15;
vec3 matCol = palette(colorParam, vec3(0.5), vec3(0.5), vec3(1.0, 1.0, 1.0), vec3(0.0, 0.1, 0.2));
vec3 matCol2 = palette(colorParam + 0.3, vec3(0.5), vec3(0.5), vec3(1.0, 1.0, 1.0), vec3(0.3, 0.2, 0.2));
vec3 col = matCol * diff * 0.7 + matCol2 * diff2 * 0.3;
col += vec3(1.0, 0.95, 0.9) * spec * 2.0;
col += palette(fres + time * 0.1, vec3(0.5), vec3(0.5), vec3(1.0), vec3(0.8, 0.9, 0.3)) * fres * 0.5;
return col;
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord.xy / iResolution.xy;
vec2 p = (fragCoord.xy - 0.5 * iResolution.xy) / iResolution.y;
p *= 2.;
// Camera
float camDist = 3.5 + 0.5 * sin(time * 0.4);
float camAngle = time * 0.25;
vec3 ro = vec3(camDist * cos(camAngle), 1.0 * sin(time * 0.3), camDist * sin(camAngle));
// Mouse control
if (M.z > 0.0) {
float mx = xm.x * 2.0 * pi;
float my = (xm.y - 0.5) * pi;
ro = vec3(camDist * cos(mx) * cos(my), camDist * sin(my), camDist * sin(mx) * cos(my));
}
vec3 ta = vec3(0.0);
vec3 ww = normalize(ta - ro);
vec3 uu = normalize(cross(ww, vec3(0.0, 1.0, 0.0)));
vec3 vv = cross(uu, ww);
vec3 rd = normalize(p.x * uu + p.y * vv + 1.5 * ww);
// Raymarch
vec2 res = RM(ro, rd);
float t = res.x;
float steps = res.y;
// Background - subtle gradient
vec3 col = mix(vec3(0.02, 0.01, 0.05), vec3(0.08, 0.02, 0.12), p.y + 0.5);
// Glow from steps (volumetric feel)
float glow = steps / 80.0;
vec3 glowCol = palette(glow + time * 0.1, vec3(0.5), vec3(0.5), vec3(1.0, 1.0, 1.0), vec3(0.0, 0.33, 0.67));
vec3 bgGlow = glowCol * glow * 0.6;
col += bgGlow;
// Reflections via bounce loop
vec3 curRo = ro;
vec3 curRd = rd;
float reflWeight = 1.0;
vec3 accum = vec3(0.0);
for (int bounce = 0; bounce < 3; bounce++) {
vec2 bRes = (bounce == 0) ? res : RM(curRo, curRd);
float bT = bRes.x;
float bSteps = bRes.y;
if (bT >= 120.0) {
// Hit background
vec3 bg = mix(vec3(0.02, 0.01, 0.05), vec3(0.08, 0.02, 0.12), curRd.y + 0.5);
float bGlow = bSteps / 80.0;
vec3 bGlowCol = palette(bGlow + time * 0.1, vec3(0.5), vec3(0.5), vec3(1.0, 1.0, 1.0), vec3(0.0, 0.33, 0.67));
bg += bGlowCol * bGlow * 0.6;
accum += reflWeight * bg;
break;
}
vec3 hitP = curRo + curRd * bT;
vec3 n = calcNormal(hitP);
vec3 surfCol = shade(curRo, curRd, bT, bSteps);
float fres = pow(1.0 - max(dot(n, -curRd), 0.0), 2.5);
float reflAmount = mix(0.55, 0.95, fres); // High base reflectivity - metallic mirror
// AO approximation
float ao = 1.0 - bSteps / 80.0 * 0.5;
accum += reflWeight * surfCol * (1.0 - reflAmount * 0.7) * ao;
reflWeight *= reflAmount * ao;
// Setup next bounce
curRo = hitP + n * 0.01;
curRd = reflect(curRd, n);
}
if (t < 120.0) {
col = accum;
} else {
col = accum;
float ao = 1.0 - glow * 0.5;
col *= ao;
}
// Tone mapping + gamma
col = col / (1.0 + col); // Reinhard
col = pow(col, vec3(0.8)); // Slight gamma
col *= 2.5;
// Vignette
float vig = 1.0 - 0.1 * dot(p, p);
col *= vig;
fragColor = vec4(col, 1.0);
}
Image
Not used
More shaders by scry
- Project_2026-08-15_18-22-06
- Project_2026-08-14_16-45-00
- Project_2026-07-24_15-10-23
- Project_2026-07-15_03-18-26
- Glass of Orange Juice (raymarched)
- Project_2026-07-13_00-53-50
- Project_2026-07-10_16-39-54
- Popcorn ceiling
- Project_2026-06-20_15-32-19
- Project_2026-06-25_12-22-43
- Visual Enhancer
- Project_2026-06-24_11-11-39
Browse all public shaders · All shaders by scry · ShaderKit home
Unread comments
×Projects with new comments. Click to open and read.