// BEGIN: shadertoy porting template // https://gam0022.net/blog/2019/03/04/porting-from-shadertoy-to-glslsandbox/ precision highp float; uniform vec2 resolution; uniform float time; uniform vec2 mouse; uniform sampler2D backbuffer; #define iResolution resolution #define iTime time #define iMouse (vec4(mouse, .5, .5) * resolution.xyxy) #define iChannel0 backbuffer void mainImage(out vec4 fragColor, vec2 fragCoord); out vec4 outColor; void main () { vec4 col; mainImage(col, gl_FragCoord.xy); outColor = col; } // END: shadertoy porting template const float TAU = 6.28318530718; #define BPM 120.0 #define saturate(x) clamp(x, 0., 1.) #define tri(x) (1. - 4. * abs(fract(x) - .5)) #define phase(x) (floor(x) + .5 + .5 * cos(TAU * .5 * exp(-5. * fract(x)))) void rot(inout vec2 p, float a) { p *= mat2(cos(a), sin(a), -sin(a), cos(a)); } // Hash without Sine by David Hoskins. // https://www.shadertoy.com/view/4djSRW float hash11(float p) { p = fract(p * .1031); p *= p + 33.33; p *= p + p; return fract(p); } float hash12(vec2 p) { vec3 p3 = fract(vec3(p.xyx) * .1031); p3 += dot(p3, p3.yzx + 33.33); return fract((p3.x + p3.y) * p3.z); } vec2 hash22(vec2 p) { vec3 p3 = fract(vec3(p.xyx) * vec3(.1031, .1030, .0973)); p3 += dot(p3, p3.yzx + 33.33); return fract((p3.xx + p3.yz) * p3.zy); } vec2 hash23(vec3 p3) { p3 = fract(p3 * vec3(.1031, .1030, .0973)); p3 += dot(p3, p3.yzx + 33.33); return fract((p3.xx + p3.yz) * p3.zy); } // hemisphere hash function based on a hash by Slerpy vec3 hashHs(vec3 n, vec3 seed) { vec2 h = hash23(seed); float a = h.x * 2. - 1.; float b = TAU * h.y * 2. - 1.; float c = sqrt(1. - a * a); vec3 r = vec3(c * cos(b), a, c * sin(b)); return r; } // global vars vec3 ro, target; float fov; vec3 scol; float beat, beatTau, beatPhase; // Timeline float prevEndTime = 0., t = 0.; #define TL(end) if (t = beat - prevEndTime, beat < (prevEndTime = end)) // Material Types #define VOL 0. #define SOL 1. vec2 opRep(vec2 p, vec2 a) { return mod(p, a) - 0.5 * a; } void opUnion(inout vec4 m, float d, float type, float roughness_or_emissive, float hue) { if (d < m.x) m = vec4(d, type, roughness_or_emissive, hue); } vec3 pal(vec4 m) { // Integer part: Blend ratio with white (0-10) // Decimal part: Hue (0-1) vec3 col = vec3(.5) + .5 * cos(TAU * (vec3(0., .33, .67) + m.w)); return mix(col, vec3(.5), .1 * floor(m.w)); } float sdBox(vec3 p, vec3 b) { vec3 q = abs(p) - b; return length(max(q, 0.)) + min(max(q.x, max(q.y, q.z)), 0.); } // マンハッタン距離によるボロノイ // https://qiita.com/7CIT/items/4126d23ffb1b28b80f27 // https://neort.io/art/br0fmis3p9f48fkiuk50 float voronoi(vec2 uv) { vec2 i = floor(uv); vec2 f = fract(uv); vec2 res = vec2(8, 8); for (int x = -1; x <= 1; x++) { for (int y = -1; y <= 1; y++) { vec2 n = vec2(x, y); vec2 np = 0.5 + 0.5 * sin((beatPhase / 4. + hash22(i + n)) * TAU); vec2 p = n + np - f; // マンハッタン距離 float d = abs(p.x) + abs(p.y); // float d = length(p); // float d = lpnorm(p, -3); if (d < res.x) { res.y = res.x; res.x = d; } else if (d < res.y) { res.y = d; } } } float c = res.y - res.x; c = sqrt(c); c = smoothstep(0.4, 0.0, c); return c; } vec4 map(vec3 pos, bool isFull) { vec4 m = vec4(2, VOL, 0, 0); // x: Distance // y: MaterialType (VOL or SOL) // z: Roughness in (0-1), Emissive when z>1 // w: ColorPalette float roughness = 0.05; vec3 p1 = pos; int _IFS_Iteration = 3; vec3 _IFS_Rot = vec3(0, 0.15, -0.25); vec3 _IFS_Offset = vec3(3, 4, 12); p1 -= _IFS_Offset.xyz; for (int i = 0; i < _IFS_Iteration; i++) { p1 = abs(p1 + _IFS_Offset.xyz) - _IFS_Offset.xyz; rot(p1.xz, TAU * _IFS_Rot.x); rot(p1.zy, TAU * _IFS_Rot.y); rot(p1.xy, TAU * _IFS_Rot.z); } float power = (beat >= 32. && beat < 64.) ? 100.0 : 1.0; float emi = 1.2 * pow(saturate(cos((beatTau - pos.y * 2.) / 8.)), power); float hue = fract(beat / 16.); vec3 size = vec3(4, 0.1, 4); opUnion(m, sdBox(p1, size) + voronoi(p1.xz), SOL, roughness, 0.); opUnion(m, sdBox(p1 - vec3(0, -0.2, 0), size), SOL, roughness + emi, hue); // wall emi = pow(saturate(cos(TAU * p1.x * 0.5)), 50.) * saturate(cos((beatTau - pos.y * 2.) / 8.)); hue = 3.4; opUnion(m, sdBox(p1 - vec3(0, 4, 0), size), SOL, emi * 2., hue); return m; } vec3 normal(vec3 p) { vec2 e = vec2(0, .05); return normalize(map(p, false).x - vec3(map(p - e.yxx, false).x, map(p - e.xyx, false).x, map(p - e.xxy, false).x)); } // Based on EOT - Grid scene by Virgill // https://www.shadertoy.com/view/Xt3cWS void madtracer(vec3 ro1, vec3 rd1, float seed) { scol = vec3(0); vec2 rand = hash23(vec3(seed, iTime, iTime)) * .5; float t = rand.x, t2 = rand.y; vec4 m1, m2; vec3 rd2, ro2, nor2; for (int i = 0; i < 100; i++) { m1 = map(ro1 + rd1 * t, true); // t += m1.y == VOL ? 0.25 * abs(m1.x) + 0.0008 : 0.25 * m1.x; t += 0.5 * mix(abs(m1.x) + 0.0032, m1.x, m1.y); ro2 = ro1 + rd1 * t; nor2 = normal(ro2); rd2 = mix(reflect(rd1, nor2), hashHs(nor2, vec3(seed, i, iTime)), saturate(m1.z)); m2 = map(ro2 + rd2 * t2, true); // t2 += m2.y == VOL ? 0.15 * abs(m2.x) : 0.15 * m2.x; t2 += 0.25 * mix(abs(m2.x), m2.x, m2.y); scol += .15 * (pal(m2) * max(0., m2.z - 1.) + pal(m1) * max(0., m1.z - 1.)); // force disable unroll for WebGL 1.0 if (t < -1.) break; } } void raymarching(vec3 ro1, vec3 rd1) { scol = vec3(0); float t = 0.; vec4 m; for (int i = 0; i < 160; i++) { vec3 p = ro1 + rd1 * t; m = map(p, true); t += m.x; if (m.x < 0.01) { vec3 light = normalize(vec3(1, 1, -1)); vec3 albedo = vec3(0.3); if (m.z > 1.) albedo = pal(m); scol = albedo * (0.5 + 0.5 * saturate(dot(normal(p), light))); break; } } } void mainImage(out vec4 fragColor, vec2 fragCoord) { beat = iTime * BPM / 60.0; // beat = 48.; beat = mod(beat, 96.0); beatTau = beat * TAU; beatPhase = phase(beat / 2.); vec2 uv = fragCoord.xy / iResolution.xy; // Camera vec2 noise = hash23(vec3(iTime, fragCoord)) - .5; // AA vec2 uv2 = (2. * (fragCoord.xy + noise) - iResolution.xy) / iResolution.x; // Timeline TL(16.) { vec3 a = vec3(0, 0.1, 0.01) * t; ro = vec3(3.685370226301841, -4.959968195098165, -20.681291773889914) + a; target = vec3(0, 0, 0) + a; fov = 38.; } else TL(32.) { vec3 a = vec3(0, 0, 0.01) * t; ro = vec3(0., 11.945982556636304, 38.08763743207477) + a; target = vec3(0, 0, 0) + a; fov = 38.; } else TL(64.) { vec3 a = vec3(0, 0, 0.2) * t; ro = vec3(0, 9.715572757794958e-16, 15.866734416093387) + a; target = vec3(0, 0, 0) + a; fov = 38. + t; } else TL(80.) { vec3 a = vec3(0, 0.1, 0.01) * t; ro = vec3(-1.3462260362305196, -8.261048814107882, -28.966739530232058) + a; target = vec3(1.593920748030086, -0.030320796976565673, -0.9344052773004179) + a; fov = 38.; } else TL(96.) { vec3 a = vec3(0, -1, 0.01) * t; ro = vec3(0., -63.37835217641502, -0.414008392856417) + a; target = vec3(0, 0, 0) + a; fov = 38.; } // #define DEBUG_CAMERA #ifdef DEBUG_CAMERA if (gCameraDebug > 0.) { ro = vec3(gCameraEyeX, gCameraEyeY, gCameraEyeZ); target = vec3(gCameraTargetX, gCameraTargetY, gCameraTargetZ); fov = gCameraFov; } #endif vec3 up = vec3(0, 1, 0); vec3 fwd = normalize(target - ro); vec3 right = normalize(cross(up, fwd)); up = normalize(cross(fwd, right)); vec3 rd = normalize(right * uv2.x + up * uv2.y + fwd / tan(fov * TAU / 720.)); // #define DEBUG_SCENE #ifdef DEBUG_SCENE raymarching(ro, rd); fragColor = vec4(scol, 1.); #else madtracer(ro, rd, hash12(uv2)); vec3 bufa = texture(iChannel0, uv).xyz; // fade out // scol = mix(scol, vec3(0), smoothstep(92., 96., beat)); fragColor = saturate(vec4(0.7 * scol + 0.7 * bufa, 1.)); #endif }