// classic(300es) precision highp float; precision highp int; uniform vec2 resolution; uniform vec2 mouse; uniform float time; uniform sampler2D backbuffer; out vec4 outColor; // const const float PI = 3.141592653589793; // utilities float atan2(float y, float x){ return x == 0.0 ? 0.5*PI*sign(y) : atan(y, x); } vec3 hsv2rgb(float h, float s, float v){ return ((clamp(abs(fract(h+vec3(0.0, 2.0, 1.0) / 3.0) * 6.0 - 3.0) - 1.0, 0.0, 1.0) - 1.0) * s + 1.0) * v; } mat2 rotate2D(float th){ float c = cos(th); float s = sin(th); return mat2(c, -s, s, c); } // hash const uint UINT_MAX = 0xffffffffu; uvec3 k = uvec3(0x456789abu, 0x6789ab45u, 0x89ab4567u); uvec3 u = uvec3(1u, 2u, 3u); uint uhash11(uint n){ n ^= n << u.x; n ^= n >> u.x; n *= k.x; n ^= n << u.x; return n * k.x; } uvec2 uhash22(uvec2 n){ n ^= n.yx << u.xy; n ^= n.yx >> u.xy; n *= k.xy; n ^= n.yx << u.xy; return n * k.xy; } uvec3 uhash33(uvec3 n){ n ^= n.yzx << u; n ^= n.yzx >> u; n *= k; n ^= n.yzx << u; return n * k; } float hash11(float p){ uint n = floatBitsToUint(p); return float(uhash11(n)) / float(UINT_MAX); } vec2 hash22(vec2 p){ uvec2 n = floatBitsToUint(p); return vec2(uhash22(n)) / vec2(UINT_MAX); } vec3 hash33(vec3 p){ uvec3 n = floatBitsToUint(p); return vec3(uhash33(n)) / vec3(UINT_MAX); } float hash21(vec2 p){ uvec2 n = floatBitsToUint(p); return float(uhash22(n).x) / float(UINT_MAX); } float hash31(vec3 p){ uvec3 n = floatBitsToUint(p); return float(uhash33(n).x) / float(UINT_MAX); } // voronoi c e m void voronoi3e(vec3 p, out vec3 id0, out vec3 id1, out float d0, out float d1){ d0 = 3.0; d1 = 4.0; vec3 pf = floor(p); vec3 lat; vec3 jit; vec3 point; vec3 dis; float d; for(float i=-1.0; i<2.0; i++){ for(float j=-1.0; j<2.0; j++){ for(float k=-1.0; k<2.0; k++){ lat = vec3(i, j, k); jit = hash33(pf + lat); point = pf + lat + jit; dis = point - p; d = length(dis); if(d < d0){ d1 = d0; d0 = d; id1 = id0; id0 = point; } else if(d < d1){ d1 = d; id1 = point; } } } } } // sdf3D float sdf3_sphere(vec3 p, float r){ return length(p) - r; } float sdf3_box(vec3 p, vec3 s){ vec3 d = abs(p) - s; return length(max(d, 0.0)) + min(0.0, max(max(d.x, d.y), d.z)); } float sdf3_torus_z(vec3 p, float r, float R){ vec2 d = vec2(length(p.xy) - R, p.z); return length(d) - r; } // scene float dist(vec3 p, float t, out int material){ float d; float dt; float th; vec3 pt = p; material = 0; d = sdf3_sphere(p, 1.0); float r = 0.4; float R = 0.8; for (int i = 0; i < 50; i++){ pt = p; th = 2.0*PI*(t+float(i)*0.125); pt.xy *= rotate2D(th*0.11); pt.yz *= rotate2D(th*0.13); pt.zx *= rotate2D(th*0.17); dt = sdf3_torus_z(pt, r, R*float(2+i)); material = d < dt ? material : i+1; d = min(d, dt); } dt = -sdf3_sphere(p, 80.0); material = d < dt ? material : 100; d = min(d, dt); return d; } vec3 getNormal(vec3 p, float t){ vec2 d = vec2(1.0e-4, 0.0); int m; return normalize(vec3( dist(p+d.xyy, t, m) - dist(p-d.xyy, t, m), dist(p+d.yxy, t, m) - dist(p-d.yxy, t, m), dist(p+d.yyx, t, m) - dist(p-d.yyx, t, m) )); } vec3 getColor(vec3 p, float t, out int m, vec2 ss){ if (m == 100){ p *= 0.1; p.xy *= rotate2D(2.0*PI*t*0.07); p.yz *= rotate2D(2.0*PI*t*0.05); p.zx *= rotate2D(2.0*PI*t*0.03); vec3 id0; vec3 id1; float d0; float d1; voronoi3e(0.5*p, id0, id1, d0, d1); if (d1 - d0 < 0.1){ return hsv2rgb(0.25*t + 0.1*(p.x+p.y+p.z), 1.0, 1.0); } else{ // skybox ss *= 4.0; ss = 2.0*fract(ss)-1.0; ss = abs(ss); return ss.x+ss.y < 1.0 ? vec3(0.4) : vec3(0.8); } } else{ vec3 id0; vec3 id1; float d0; float d1; voronoi3e(p, id0, id1, d0, d1); float h = 0.25*t+float(m)/25.0; return d1 - d0 < 0.1 ? hsv2rgb(h, 0.9, 1.0) : hsv2rgb(h, 0.1, 1.0); } } void camera(vec2 p, float t, out vec3 cPos, out vec3 ray){ // camera float th = PI*t; float r = 30.0 + 20.0 * cos(0.17*th); cPos = vec3(r*cos(th*0.13), 0.0, r*sin(th*0.11)); r = 12.0; vec3 cDir = normalize(vec3(r*cos(th*0.17), r*sin(th*0.19), 0.0)-cPos); vec3 cUp = normalize(vec3(0.0, 1.0, 0.0)); vec3 cSide = normalize(cross(cDir, cUp)); cUp = normalize(cross(cSide, cDir)); float targetDepth = 1.0; // ray ray = normalize(cSide * p.x + cUp * p.y + cDir * targetDepth); /* float angle = 60.0; float fov = angle * 0.5 * PI / 180.0; ray = normalize(vec3(sin(fov)*p.x, sin(fov)*p.y, -cos(fov))); //*/ } float genShadow(vec3 ro, vec3 rd, float t){ float h = 0.0; float c = 1.0e-3; float r = 1.0; float shadowCoef = 0.5; int m; for (float t = 0.0; t < 64.0; t++){ h = dist(ro+rd*c, t, m); if (h < 1.0e-3){ return shadowCoef; } else{ r = min(r, h*16.0/c); c += h; } } return mix(shadowCoef, 1.0, r); } void main(){ float t = time; vec2 r = resolution; vec4 FC = gl_FragCoord; vec4 o; vec2 p = (2.0 * FC.xy - r) / min(r.x, r.y); //p *= rotate2D(2.0*PI*cos(-0.0625*PI*t)); vec3 cPos; vec3 ray; camera(p, t, cPos, ray); // marchging loop float d = 0.0; float rLen = 0.0; vec3 rPos = cPos; float dmin = 1.0e-4; int material; for (int i = 0; i < 128; i++){ d = dist(rPos, t, material); rLen += d; rPos = cPos + ray * rLen; if (d < dmin || 1.0e4 < rLen){ break; } } // hit check //float shadow = 1.0; vec3 color; if (d < dmin){ vec3 normal = getNormal(rPos, t); vec3 lightDir = normalize(vec3(1.0, 2.0, 3.0)); float diffuse = clamp(dot(normal, lightDir), 0.2, 1.0); color = getColor(rPos, t, material, p); color *= diffuse; // 天球の明るさ調節 color += material == 100 ? 0.5 : 0.0; // fog (天球以外) color += material < 100 ? length(p) / 60.0 : 0.0; // SSS color += clamp(dist(rPos+ray*1.2, t, material), 0.0, 1.0) * 0.75; // shadow //shadow = genShadow(rPos+normal*1.0e-3, lightDir, t); } else{ // skybox p *= 8.0; p = fract(p); p = 2.0*p-1.0; p = abs(p); color = p.x + p.y < 1.0 ? vec3(0.4, 0.4, 0.4) : vec3(0.8, 0.8, 0.8); } // モーションブラー vec2 uv = FC.xy/r; vec3 bcol = texture(backbuffer, uv).xyz; color = mix(color, bcol, 0.4+0.4*cos(0.115*PI*t)); o.xyz = color;// * max(0.5, shadow); o.w = 1.0; outColor = o; }