precision highp float; uniform vec2 resolution; uniform vec2 mouse; uniform float time; uniform sampler2D backbuffer; #define lightPos vec3(3., 0., 0.) mat2 rot(float t){return mat2(cos(t), sin(t), -sin(t), cos(t));} float hash(vec2 uv){return fract(sin(dot(uv,vec2(12.9898, 78.233)))*43758.5453123);} float noise(vec2 uv){ vec2 f = fract(uv); vec2 i = floor(uv); float a = hash(i); float b = hash(i + vec2(1., 0.)); float c = hash(i + vec2(0., 1.)); float d = hash(i + vec2(1., 1.)); return mix(mix(a, b, f.x), mix(c, d, f.x), f.y); } vec2 intersect(vec3 p){ vec2 res = vec2(-1., 20.); vec2 obj; vec3 p_o = p; float sdBox; p.y = abs(p.y); vec3 q = abs(p-vec3(0., 4., 0.))-vec3(5., .01, 5.); sdBox = length(max(q, 0.)+min(max(q.x, max(q.y, q.z)), 0.)); obj = vec2(1.1, sdBox); if(obj.y < res.y)res = obj; p = p_o; p.x = abs(p.x); q = abs(p-vec3(5., 0., 0.))-vec3(.01, 4., 5.); sdBox = length(max(q, 0.)+min(max(q.x, max(q.y, q.z)), 0.)); obj = vec2(1.2, sdBox); if(obj.y < res.y)res = obj; p = p_o; p.z = abs(p.z); q = abs(p-vec3(0., 0., 5.))-vec3(5., 4., .2); sdBox = length(max(q, 0.)+min(max(q.x, max(q.y, q.z)), 0.)); obj = vec2(1.3, sdBox); if(obj.y < res.y)res = obj; p = p_o; p = abs(p)-.2; p.xy = rot(.4)*p.xy; p = abs(p)-1.;//-1. p.yz = rot(.4)*p.yz; p.xz = rot(time/10.)*p.xz; q = abs(p-vec3(0., 0., 0.))-vec3(1.); sdBox = length(max(q, 0.))-length(min(max(q.x, max(q.y, q.z)), 0.))-.12; obj = vec2(1., sdBox); if(obj.y < res.y)res = obj; return res; } vec2 rayMarch(vec3 ro, vec3 rd){ vec2 res = vec2(-1., 20.); float t = 0.; vec3 ray; for(float i = 0.;i < 200.;i++){ ray = ro + rd*t; vec2 obj = intersect(ray); if(abs(obj.y) < .01){ res = obj; break; } if(t > 20.)break; t += abs(obj.y)*.5; } return vec2(res.x, t); } vec3 getNor(vec3 p){ vec2 e = vec2(0., 0.01); return normalize(vec3( intersect(p+e.yxx).y - intersect(p-e.yxx).y, intersect(p+e.xyx).y - intersect(p-e.xyx).y, intersect(p+e.xxy).y - intersect(p-e.xxy).y )); } vec3 sideWallCol(vec3 p, bool light){ vec3 col; vec3 mate = vec3(step(hash(floor(p.yz*2.)+floor(time)), .5)); mate = light?mate:mate*.03; vec3 nor = getNor(p); float diff = clamp(dot(normalize(lightPos-p), nor), 0., 1.); col = mate*diff; return col; } vec3 wallCol(vec3 p, bool light){ vec3 col; vec3 mate = fract(p.x*.1+time/10.)<.5?vec3(1.):vec3(0.); mate = light?mate:mate*.03; vec3 nor = getNor(p); float diff = clamp(dot(normalize(lightPos-p), nor), 0., 1.); col = mate*diff; return col; } vec3 floorCol(vec3 p, bool light){ vec3 col; vec3 mate = fract(p.z+time/10.)<.5?vec3(1.):vec3(0.); mate = light?mate:mate*.03; vec3 nor = getNor(p); float diff = clamp(dot(normalize(lightPos-p), nor), 0., 1.); col = mate*diff; return col; } vec3 lightCol(vec3 p){ return vec3(1.); } vec3 colHub(float id, vec3 hitPos, bool light){ vec3 col = vec3(0.); if(id == 1.1)col = floorCol(hitPos, light); else if(id == 1.2)col = sideWallCol(hitPos, light); else if(id == 1.3)col = wallCol(hitPos, light); return col; } vec3 prismCol(vec3 p, vec3 rd, bool light, vec3 baseCol){ vec3 col = vec3(0.); vec3 norIn = getNor(p); //surface reflection vec3 rdRefl = reflect(rd, norIn); vec2 obj = rayMarch(p+norIn*.5, rdRefl); vec3 reflCol = colHub(obj.x, p + rdRefl*obj.y, light); float diff = .2-clamp(dot(rd, norIn), 0., .2); //refraction vec3 rdIn = refract(rd, norIn, 1./1.45); vec3 roIn = p - norIn*.02; obj = rayMarch(roIn, rdIn); vec3 inPos = roIn + rdIn*obj.y; vec3 norOut = getNor(inPos); //inside reflection & refraction vec3 rdOut = refract(rdIn, -norOut, 1.45); vec3 roOut = inPos + norOut*.02; if(length(rdOut) == 0.){ rdOut = reflect(rdIn, -norOut); vec3 inPos2 = inPos + rdOut*rayMarch(inPos, rdOut).y; roOut = inPos2 + rdOut*2.; } obj = rayMarch(roOut, rdOut); vec3 hitPos = roOut + rdOut*obj.y; col = colHub(obj.x, hitPos, light); col = baseCol*col; return col*.5 + reflCol*diff; } void main(void) { vec2 p = (gl_FragCoord.xy*2.-resolution.xy)/min(resolution.x, resolution.y); vec3 ray; vec3 ro = fract(time/12.)<.5?vec3(0., -2., 4.5):vec3(0., 0., 4.5); ro.xz = rot(time*.1)*ro.xz; vec3 rd = normalize(vec3(p, -1.)); rd.yz = fract(time/12.)<.5?rot(radians(20.))*rd.yz:rot(radians(0.))*rd.yz; rd.xz = rot(time*.1)*rd.xz; float t = 0.; vec3 col = vec3(0.); vec2 obj = rayMarch(ro, rd); ray = ro + rd*obj.y; float tcycle = fract(time/12.); bool light = tcycle< .95?true:tcycle<.97?mod(floor(tcycle*400.),2.)==0.?true:false:false; int colIndex = int(mod(floor(time/12.), 4.)); vec3 baseCol = colIndex==0?vec3(1.):colIndex==1?vec3(1., .2, 0.):colIndex==2?vec3(0., .2, 1.):vec3(1., .8, .1); if(obj.x != -1.){ if(obj.x == 1.1)col = floorCol(ray, light); else if(obj.x == 1.2)col = sideWallCol(ray, light); else if(obj.x == 1.)col = prismCol(ray, rd, light, baseCol); else if(obj.x == 1.3)col = wallCol(ray, light); } col = pow(col, vec3(.4545)); gl_FragColor = vec4(col, 1.); }