#version 450 // Portal Gameplay // ciberxtrem - https://www.shadertoy.com/view/XlsSzM // Inspired in Portal, Chamber 8. // Note: Set the APPLY_COLORS and APPLY_SHADOW to 1 to see all colors and shadows layout(std140, set = 0, binding = 0) uniform UBO { mat4 MVP; vec4 OutputSize; vec4 OriginalSize; vec4 SourceSize; uint FrameCount; } global; #pragma stage vertex layout(location = 0) in vec4 Position; layout(location = 1) in vec2 TexCoord; layout(location = 0) out vec2 vTexCoord; const vec2 madd = vec2(0.5, 0.5); void main() { gl_Position = global.MVP * Position; vTexCoord = gl_Position.xy; } #pragma stage fragment layout(location = 0) in vec2 vTexCoord; layout(location = 0) out vec4 FragColor; float iGlobalTime = float(global.FrameCount)*0.025; vec2 iResolution = global.OutputSize.xy; // Thanks iq and the Shadertoy comunity for all the shared knowledge! :) // Set this to 1 to enable colors! #define APPLY_COLORS 0 #define APPLY_SHADOW 0 //--------------------------- #define PI 3.14159265359 struct LightStruct { vec3 pos; vec3 color; }; struct PortalStruct { vec3 pos; vec3 front; float rotateY; float time; }; struct StateStruct { vec3 posStart; vec3 posEnd; float lerptime; float duration; float isEnterTime; float enterPortal; float exitPortal; }; struct OrientationStruct { vec3 orientation; float lerptime; float duration; }; PortalStruct portalA; PortalStruct portalB; PortalStruct portalsA[8]; StateStruct states[10]; OrientationStruct orientations[15]; LightStruct lights[3]; float t; vec3 position; vec3 orientation; float ambient = 0.05; vec3 ambientcolor; vec3 rotateY(vec3 p, float a){ return vec3( p.x*cos(a) + p.z*sin(a), p.y, p.z*cos(a) - p.x*sin(a) ); } float hash( float n ) { return fract(sin(n)*43758.5453123); } float noise( in vec2 x ) { vec2 p = floor(x); vec2 f = fract(x); f = f*f*(3.0-2.0*f); float n = p.x + p.y*157.0; return mix(mix( hash(n+ 0.0), hash(n+ 1.0),f.x), mix( hash(n+157.0), hash(n+158.0),f.x),f.y); } const mat2 m2 = mat2( 0.80, -0.60, 0.60, 0.80 ); float fbm( vec2 p ) { float f = 0.0; f += 0.5000*noise( p ); p = m2*p*2.02; f += 0.2500*noise( p ); p = m2*p*2.03; f += 0.1250*noise( p ); p = m2*p*2.01; f += 0.0625*noise( p ); return f/0.9375; } float dBox(vec3 p, vec3 hsize) { return length(max(abs(p)-hsize,0.0)); } float udRoundBox( vec3 p, vec3 b, float r ) { return length(max(abs(p)-b,0.0))-r; } float sdCappedCylinder( vec3 p, vec2 h ) { vec2 d = abs(vec2(length(p.xz),p.y)) - h; return min(max(d.x,d.y),0.0) + length(max(d,0.0)); } //------------------------------- // Scene float dElipse(vec3 p, vec3 hsize, float globalSize) { float d = length(max(abs(p)-hsize,0.0)); vec3 q = p; q.y *= 0.6; return max(d, length(q)-max(max(hsize.x, hsize.y)*globalSize, hsize.z)); } vec2 dStructure(vec3 p) { // Front vec2 res = vec2(-1., -1.); vec3 q = p - vec3(0., 0.5, 28.25); vec2 c = vec2(3., 6.2); vec3 q2 = q; q2.xy = mod(q2.xy,c.xy)-0.5*c.xy; float d = udRoundBox(q2, vec3(1.35, 3., 1.0), 0.25); q = p - vec3(0.0, 9.5, 28.); // Hole for exit float d2 = udRoundBox(q, vec3(3.0, 3.25, 2.0), 0.1); d = max(d,-d2); res = vec2(d, 24.); //Back q = p - vec3(0., 3.5, -28.0); c = vec2(3., 6.2); q.x = mod(q.x,c.x)-0.5*c.x; d = udRoundBox(q, vec3(1.35, 3., 1.0), 0.25); res = mix(vec2(d, 24.), res, step(res.x, d)); q = p - vec3(0., 0.6, -28.01); // Brown block c = vec2(3., 3.0); q.xy = mod(q.xy,c.xy)-0.5*c.xy; d = udRoundBox(q, vec3(1.35, 1.35, 1.0), 0.25); q = p - vec3(0.0, 9.5, -28.); // Hole for exit d2 = udRoundBox(q, vec3(3.0, 3.25, 2.0), 0.1); d = max(d,-d2); res = mix(vec2(d, 20.), res, step(res.x, d)); //Exit vec3 p2 = p; p2.z = abs(p.z); q = p2 - vec3(0.0, 9.5, 30.5); d = udRoundBox(q, vec3(3.0, 3.25, 0.1), 0.1); if(d 29.0){ float phase = (t-29.)/7.; float seq = mod(phase, 2.); leftPlatPos =mix(vec3(-10, 7., -2.), vec3(-11.6, 7., -23.0), fract(phase)); } q = p - leftPlatPos; d = udRoundBox(q, vec3(3.8, 0.02, 3.8), 0.01); res = mix(vec2(d, 22.), res, step(res.x, d)); // Border d = udRoundBox(q, vec3(4.0, 0.05, 4.0), 0.1); float d2 = udRoundBox(q, vec3(3.5, 0.1, 3.5), 0.1); d = max(d, -d2); res = mix(vec2(d, 24.), res, step(res.x, d)); // Crosses d = udRoundBox(q-vec3(0., -0.05, 0.), vec3(4.0, 0.08, 0.1), 0.05); d = min(d, udRoundBox(q-vec3(0., -0.05, 0.), vec3(0.1, 0.08, 4.0), 0.05)); res = mix(vec2(d, 24.), res, step(res.x, d)); //Tube d = sdCappedCylinder(q-vec3(0., -1.5, 0.), vec2(0.65, 1.6)); d = min(d, sdCappedCylinder(q-vec3(0., -5.0, 0.), vec2(1.0, 2.))); res = mix(vec2(d, 6.), res, step(res.x, d)); return res; } vec4 dBloomObjects(vec3 p) { vec4 res = vec4(-1, -1, 999., 0.); //Lamp vec3 q = p - vec3(0.0, 14.6, 0.0); q.y *= 1.4; float d = length(q)-0.8; res.zw = vec2(d, 1.); res.xy = vec2(d, 7.); // FireballBaseStart q = p - vec3(10.5, 9.5, 27.5); d = length(vec3(q.x, q.y, q.z))-2.5; d = max(d, -(q.z+1.5)); float d2 = (length((vec3(q.x, q.y, (q.z+1.5)*0.8)))-1.5); d2 += cos((p.z+0.5)*4.5)*0.1; d = min(d, d2); d += mix(0., 1., smoothstep(0.6, 1., cos(q.x*2.)*cos(q.y*2.)*cos(q.z+1.)))*1.0; res.xy = mix(vec2(d, 12.), res.xy, step(res.x, d)); // FireballBaseEnd q = p - vec3(-15.9, 9.5, -12.0); q = rotateY(q, PI*0.5); d = length(vec3(q.x, q.y, q.z))-2.5; d = max(d, -(q.z+1.5)); d = max(d, -(length(q-vec3(0., 0., -5.6))-4.5)); d += mix(0., 1., smoothstep(0.5, 1., cos(q.x*2.)*cos(q.y*2.)*cos(q.z+1.)))*1.0; res.xy = mix(vec2(d, 12.), res.xy, step(res.x, d)); // Redpoint q = p - vec3(-15.4, 9.5, -12.0); d = length(q)-0.9; res.xy = mix(vec2(d, 22.), res.xy, step(res.x, d)); res.zw = mix(vec2(d, 0.),res.zw, step(res.z, d)); // RedPoint q = p - vec3(14.8, 9.5, -12.0); d = length(q)-0.01; res.xy = mix(vec2(d, 22.), res.xy, step(res.x, d)); res.zw = mix(vec2(d, 0.),res.zw, step(res.z, d)); // Fireball vec3 firePos = vec3(0.); if(t < 20.) { float phase = t/4.; float phasePart = fract(phase); float phaseSeq = mod(phase, 2.); firePos = mix( mix(vec3(10., 9.5, 20.5), vec3(10., 9.5, -19.0), phasePart), mix(vec3(10., 9.5, -19.0), vec3(10., 9.5, 20.5), phasePart), step(1.0, phaseSeq)); } else if(t < 22.3) { firePos = mix(vec3(14.5, 10., 7.5), vec3(-14.5, 10., 7.5), smoothstep(20., 22.3, t)); } else if(t < 24.3) { firePos = mix(vec3(-14.5, 10., 7.5), vec3(14.5, 10., 7.5), smoothstep(22.3, 24.3, t)); } else { firePos = mix(vec3(14.5, 9.5, -12.0), vec3(-15.0, 9.5, -12.0), smoothstep(24.3, 27.5, t)); } q = p - firePos; d = length(vec3(q.x, q.y, q.z))-0.15; d += cos(q.x*15.+t*2.)*cos(q.y*12.)*cos(q.z*10.)*0.05; res.xy = mix(vec2(d, 13.), res.xy, step(res.x, d)); res.zw = mix(vec2(d, 0.),res.zw, step(res.z, d)); return res; } vec2 dPortalA(vec3 p) { vec3 q = rotateY(p - portalA.pos, portalA.rotateY); float d = dElipse(q, vec3(1.6, 2.6, 0.05), smoothstep(0., 0.15, t-portalA.time)*0.6); return vec2(d, 1.); } vec2 dPortalB(vec3 p) { vec3 q = rotateY(p - portalB.pos, portalB.rotateY); float d = dElipse(q, vec3(1.6, 2.6, 0.05), smoothstep(0., 0.15, t-portalB.time)*0.6); return vec2(d, 2.); } vec4 map(vec3 p) { vec4 res = dBloomObjects(p); vec2 res2 = dStructure(p); if(res2.x < res.x) res.xy = res2.xy; res2 = dWater(p); if(res2.x < res.x) res.xy = res2.xy; res2 = dPortalA(p); if(res2.x < res.x) res.xy = res2.xy; res2 = dPortalB(p); if(res2.x < res.x) res.xy = res2.xy; res2 = dPlatforms(p); if(res2.x < res.x) res.xy = res2.xy; return res; } vec4 intersect(vec3 o, vec3 rd, float tmin, float tmax) { float k = tmin; vec4 res = vec4(tmax, -1, 999., 0.); for(int i=0; i<120; ++i) { vec4 r = map(o + rd*k); res.zw = mix(r.zw, res.zw, step(res.z, r.z)); if(r.x < 0.01) { res.x = k; res.y = r.y; break; } k+=r.x; if(k > tmax) { break; } } return res; } vec3 calcnormal(vec3 p) { vec2 e = vec2(0.001, 0.); return normalize( vec3(map(p+e.xyy).x-map(p-e.xyy).x, map(p+e.yxy).x-map(p-e.yxy).x, map(p+e.yyx).x-map(p-e.yyx).x) ); } #if APPLY_SHADOW == 1 float calcshadow(vec3 o, vec3 rd, float tmin, float tmax) { float k = tmin; float shadow = 1.; for(int i = 0; i < 20; ++i) { vec4 res = map(o + rd*k); shadow = min(shadow, res.x*1.5); k+=res.x; if(k > tmax) { break; } } return shadow; } #endif vec4 mapPortalColor(vec3 p, vec3 portalPos, float rotY, vec4 cristalcolor, vec4 fxcolor) { vec2 q = rotateY(p-portalPos, rotY).xy; q.y *= 0.55; float d = length(q) - 1.4 + sin(q.x*10.+t*2.)*cos(q.y*10.+t*2.) * 0.05; return mix(cristalcolor, fxcolor, smoothstep(-0.5, 0.2, d)); } void calculatePosRayDirFromPortals(in PortalStruct portalO, in PortalStruct portalD, in vec3 p, in vec3 rd, out vec3 refpos, out vec3 refdir) { vec3 oRight = cross(vec3(0., 1., 0.), portalO.front); vec3 oUp = cross(portalO.front, oRight); vec3 dRight = cross(vec3(0., 1., 0.), portalD.front); vec3 dUp = cross(portalD.front, dRight); vec3 projRD=vec3(dot(oRight, rd), dot(oUp, rd), dot(portalO.front, rd)); vec3 localPos = p-portalO.pos; vec3 projPos = vec3(dot(localPos, oRight), dot(localPos, oUp), dot(localPos, portalO.front)); refdir = normalize(-portalD.front*projRD.z + -dRight*projRD.x + dUp*projRD.y); refpos = portalD.pos + -dRight*projPos.x + dUp*projPos.y + -portalD.front*projPos.z; } vec4 texcube( sampler2D sam, in vec3 p, in vec3 n ) { vec4 x = texture( sam, p.yz ); vec4 y = texture( sam, p.zx ); vec4 z = texture( sam, p.xy ); return x*abs(n.x) + y*abs(n.y) + z*abs(n.z); } vec2 point2plane( in vec3 p, in vec3 n ) { return p.zy*abs(n.x) + p.xz*abs(n.y) + p.xy*abs(n.z); } vec4 mapcolor(inout vec3 p, in vec4 res, inout vec3 normal, in vec3 rd, out vec3 refpos, out vec3 refdir, out vec4 lparams) { vec4 color = vec4(0.498, 0.584, 0.619, 1.0); lparams = vec4(1.0, 10., 0., 0.); refdir = reflect(rd, normal); refpos = p; if(res.y < 1.1) { // PortalA color = mapPortalColor(p, portalA.pos, portalA.rotateY, vec4(1., 1., 1., 0.1), vec4(0.0, 0.35, 1.0, 1.)); calculatePosRayDirFromPortals(portalA, portalB, p, rd, refpos, refdir); } else if(res.y < 2.1) { // PortalB color = mapPortalColor(p, portalB.pos, portalB.rotateY, vec4(0.0, 1., 1.0, 0.1), vec4(0.91, 0.46, 0.07, 1.)); calculatePosRayDirFromPortals(portalB, portalA, p, rd, refpos, refdir); } #if APPLY_COLORS == 1 else if(res.y < 3.1) { // Water color = vec4(0.254, 0.239, 0.007, 1.0); lparams.xy = vec2(2.0, 50.); color.rgb = mix(color.rgb, vec3(0.254, 0.023, 0.007), 1.-smoothstep(0.2, 1., fbm((p.xz+vec2(cos(t+p.x*2.)*0.2, cos(t+p.y*2.)*0.2))*0.5))); color.rgb = mix(color.rgb, vec3(0.007, 0.254, 0.058), smoothstep(0.5, 1., fbm((p.xz*0.4+vec2(cos(t+p.x*2.)*0.2, cos(t+p.y*2.)*0.2))*0.5))); } else if(res.y < 4.1) { // Turbina color = vec4(0.447, 0.490, 0.513, 1.0); } else if(res.y < 5.1) { //Window color = vec4(0.662, 0.847, 0.898, 0.6); lparams=vec4(3., 5., 0., 0.9); } else if(res.y < 6.1) { // Metal tube color = vec4(0.431, 0.482, 0.650, 0.6); lparams.xy=vec2(2., 5.); } else if(res.y < 7.1) {// Plastic color = vec4(0.8, 0.8, 0.8, 1.); lparams.xy=vec2(0.5, 1.); } else if(res.y < 8.1) { //Railing color = mix(vec4(1.), vec4(1., 1., 1., 0.), smoothstep(0.2, 0.21, fract(p.x))); color = mix(vec4(1.), color, smoothstep(0.2, 0.21, fract(p.z))); lparams.xy=vec2(1.0, 1.); refdir = rd; } else if(res.y < 9.1) { // Reflectance -> can be plastic color = vec4(1., 1., 1., 0.1); lparams.xy=vec2(1.0, 10.); } else if(res.y < 10.1) { // Exit vec3 q = p - vec3(1.5, 11.0, -31.); color = vec4(0.6, 0.6, 0.6, 0.65); color.rgb = mix(vec3(0.749, 0.898, 0.909), color.rgb, smoothstep(2., 10., length(q.xy))); color.rgb += mix(vec3(0.1), vec3(0.), smoothstep(2., 5., length(q.xy))); vec3 q2 = q; vec2 c = vec2(2., 1.5); float velsign = mix(-1., 1., step(0.5, fract(q2.y*0.5))); q2.x = mod(velsign*t+q2.x+cos(q2.y*3.)*0.5, 1.8); q2.y = mod(q2.y, 1.15); float d = max(abs(q2.x)-0.9, abs(q2.y)-0.1); color.rgb += mix(vec3(0.286, 0.941, 0.992)*1.6, vec3(0.), smoothstep(-0.1, 0.1, d)); vec3 localp = p - vec3(1.5, 11.0, -31.); refpos = vec3(1.5, 11.0, 28.0) + localp; lparams=vec4(1.0, 10., 0., 0.1); refdir = rd; } else if(res.y < 11.1) { // Exit border vec3 q = p; q.z = abs(q.z); q = q - vec3(0.0, 9.5, 31.); color = vec4(0.8, 0.8, 0.8, 1.); float d =length(abs(q.x+cos(q.y*0.5)*0.6 -3.0))-0.06; d = min(d, length(abs(q.x+cos(PI+q.y*0.5)*0.6 +3.0))-0.06); color.rgb = mix(vec3(0.286, 0.941, 0.992), color.rgb, smoothstep(0., 0.01, d)); lparams = mix(vec4(0., 0., 0., 1.), lparams, smoothstep(0., 0.2, d)); } else if(res.y < 12.1) { // Fireball base vec3 q = p - vec3(10., 9.5, 26.5); color = vec4(1.0, 1.0, 1.0, 1.); float d = length(q-vec3(0., 0., -2.5)) - 2.0; color = mix(vec4(0.976, 0.423, 0.262, 1.), color, smoothstep(-2., 0.01, d)); } else if(res.y < 13.1) { // Fireball color = vec4(1., 0.0, 0.0, 1.0); color.rgb = mix(color.rgb, vec3(0.75, 0.94, 0.28), smoothstep(26.5, 27.0, t)); } else if(res.y > 19. && res.y < 25.) { // Walls float rand = fbm(point2plane(p, normal)); vec3 col = vec3(0.498, 0.584, 0.619); color = vec4(vec3(col), 1.0); color = mix(color, vec4(col*0.75, 1.0), smoothstep(0.2, 1.0, rand)); color = mix(color, vec4(col*0.80, 1.0), smoothstep(0.4, 1.0, fbm(point2plane(p*1.5, normal)))); color = mix(color, vec4(col*0.7, 1.0), smoothstep(0.6, 1.0, fbm(point2plane(p*4.5, normal)))); vec3 dirtcolor = mix(vec3(0., 0., 0.), vec3(0.403, 0.380, 0.274)*0.2, rand); float dirtheight = 0.1+rand*1.0; dirtcolor = mix(dirtcolor, vec3(0.243, 0.223, 0.137), smoothstep(dirtheight, dirtheight + 0.5, p.y)); dirtheight = rand*2.; color.rgb = mix(dirtcolor, color.rgb, smoothstep(dirtheight, dirtheight+2.0, p.y)); #ifdef TEXTURE vec4 noise = mix(vec4(0.), texture(iChannel0, point2plane(p*0.037, normal)) * 0.2, smoothstep(0.2, 1., rand)); #else vec4 noise = vec4(0.0, 0.0, 0.0, 0.0); #endif normal = normalize(normal + vec3(noise.x, 0., noise.z)); refdir = normalize(reflect(rd, normal)); if(res.y < 20.1) { // BROWN_WALL_BLOCK float d = -(p.x-6.1); d = max(d, p.y-12.6); d = min(d, p.y-6.5); color *= mix(vec4(1.), vec4(0.227, 0.137, 0.011, 1.0), smoothstep(0.0, 0.1, d)); } else if(res.y < 21.1) { // WHITE_PLATFORM_BLOCK color *= vec4(0.529, 0.572, 0.709, 1.0); vec3 q = p - vec3(11.5, 6.85, 7.0); float d = abs(q.y)-0.05; color.rgb = mix(vec3(0.945, 0.631, 0.015), color.rgb, smoothstep(0., 0.01, d)); lparams.w = mix(1., 0., smoothstep(0., 0.2, d)); } else if(res.y < 22.1) { // TRANSPARENT_PLATFORM_BLOCK color *= vec4(0.431, 0.482, 0.650, 0.1); refdir = rd; lparams.xy=vec2(2., 5.); } else if(res.y < 23.1) { // CEILING_BLOCK color *= mix(vec4(0.227, 0.137, 0.011, 1.0), vec4(1.), smoothstep(0., 0.01, p.z+6.)); } } #endif return color; } void initLights() { vec3 col = vec3(0.925, 0.968, 0.972); ambientcolor = col; // Center Up lights[0].pos = vec3(0., 13.0, 0.); lights[0].color = col*0.25; // Window lights[1].pos = vec3(14.0, 15.5, -12.0); lights[1].color = col*0.25; lights[2].pos = vec3(14.0, 15.5, -6.0); lights[2].color = col*0.25; } void initPortals() { portalsA[0].pos = vec3(-140.5, 10., 23.0); portalsA[0].front = vec3(1., 0., 0.); portalsA[0].rotateY = PI*0.5; portalsA[0].time = 0.; portalsA[1].pos = vec3(-14.5, 10., 23.0); portalsA[1].front = vec3(1., 0., 0.); portalsA[1].rotateY = PI*0.5; portalsA[1].time = 6.0; portalsA[2].pos = vec3(-14.5, 10., -2.5); portalsA[2].front = vec3(1., 0., 0.); portalsA[2].rotateY = PI*0.5; portalsA[2].time = 13.5; portalsA[3].pos = vec3(10.5, 9.6, -20.5); portalsA[3].front = vec3(0., 0., 1.); portalsA[3].rotateY = 0.; portalsA[3].time = 18.; portalsA[4].pos = vec3(14.5, 9.5, -12.0); portalsA[4].front = vec3(-1., 0., 0.); portalsA[4].rotateY = PI*0.5; portalsA[4].time = 23.5; portalA = portalsA[0]; portalB.pos = vec3(14.5, 10., 7.5); portalB.front = vec3(-1., 0., 0.); portalB.rotateY = -PI*0.5; portalB.time = 0.; } void initState() { states[0].posStart = vec3(0., 11.0, 26.0); states[0].posEnd = vec3(0., 11.0, 26.0); states[0].duration = 0.; states[0].lerptime = 0.; states[0].isEnterTime = 0.; states[0].enterPortal = 0.; states[0].exitPortal = 1.; states[1].posStart = vec3(0., 11.0, 26.0); states[1].posEnd = vec3(0., 11.0, 23.0); states[1].duration = 6.75; states[1].lerptime = 0.5; states[0].isEnterTime = 0.; states[0].enterPortal = 0.; states[0].exitPortal = 1.; states[2].posStart = vec3(0., 11.0, 23.0); states[2].posEnd = vec3(-12.6, 11.0, 23.0); states[2].duration = 4.0; states[2].lerptime = 1.0; states[0].isEnterTime = 0.; states[0].enterPortal = 0.; states[0].exitPortal = 1.; // Go to Portal B states[3].posStart = vec3(-12.6, 11.0, 23.0); states[3].posEnd = vec3(-14.5, 11., 23.0); states[3].duration = 0.1; states[3].lerptime = 0.1; states[0].isEnterTime = 0.; states[0].enterPortal = 0.; states[0].exitPortal = 1.; states[4].posStart = vec3(14.5, 11., 7.5); states[4].posEnd = vec3(13.5, 11., 7.5); states[4].duration = 3.0; states[4].lerptime = 0.5; states[0].isEnterTime = 1.; states[0].enterPortal = 0.; states[0].exitPortal = 1.; // Go to Portal A states[5].posStart = vec3(13.5, 11., 7.5); states[5].posEnd = vec3(14.5, 11., 7.5); states[5].duration = 0.1; states[5].lerptime = 1.25; states[0].isEnterTime = 0.; states[0].enterPortal = 0.; states[0].exitPortal = 1.; states[6].posStart = vec3(-14.5, 11., -2.5); states[6].posEnd = vec3(-11.6, 11., -2.5); states[6].duration = 15.; states[6].lerptime = 1.0; states[0].isEnterTime = 1.; states[0].enterPortal = 0.; states[0].exitPortal = 1.; states[7].posStart = vec3(-11.6, 11., -2.5); states[7].posEnd = vec3(-11.6, 11., -23.0); states[7].duration = 7.5; states[7].lerptime = 7.0; states[0].isEnterTime = 0.; states[0].enterPortal = 0.; states[0].exitPortal = 1.; states[8].posStart = vec3(-11.6, 11., -23.0); states[8].posEnd = vec3(0.5, 11., -23.0); states[8].duration = 3.0; states[8].lerptime = 2.5; states[0].isEnterTime = 0.; states[0].enterPortal = 0.; states[0].exitPortal = 1.; states[9].posStart = vec3(0.5, 11., -23.0); states[9].posEnd = vec3(0.5, 11., -28.0); states[9].duration = 10.; states[9].lerptime = 0.5; states[0].isEnterTime = 0.; states[0].enterPortal = 0.; states[0].exitPortal = 1.; t = mod(t, 40.); } void initOrientations() { orientations[0].orientation = vec3(0., 0., -1.); orientations[0].lerptime = 0.; orientations[0].duration = 0.; orientations[1].orientation = vec3(0., 0., -1.); orientations[1].lerptime = 0.0; orientations[1].duration = 1.0; orientations[2].orientation = normalize(vec3(0.1, 0.25, -0.5)); orientations[2].lerptime = 1.50; orientations[2].duration = 2.0; orientations[3].orientation = normalize(vec3(1., 0., -1.5)); orientations[3].lerptime = 0.75; orientations[3].duration = 2.0; orientations[4].orientation = vec3(0., 0., -1.); orientations[4].lerptime = 1.25; orientations[4].duration = 1.25; orientations[4].orientation = vec3(-1., 0., 0.); orientations[4].lerptime = 1.0; orientations[4].duration = 6.25; orientations[5].orientation = vec3(0., 0., -1.); orientations[5].lerptime = 0.75; orientations[5].duration = 1.25; orientations[6].orientation = vec3(-1., 0., -0.4); orientations[6].lerptime = 0.60; orientations[6].duration = 3.25; orientations[7].orientation = vec3(0., 0., 1.); orientations[7].lerptime = 0.75; orientations[7].duration = 0.75; orientations[8].orientation = vec3(1., 0., -0.65); orientations[8].lerptime = 0.75; orientations[8].duration = 3.8; orientations[9].orientation = vec3(0.0, 0., 1.); orientations[9].lerptime = 1.0; orientations[9].duration = 1.5; orientations[10].orientation = vec3(1.0, 0., -0.2); orientations[10].lerptime = 0.75; orientations[10].duration = 3.2; orientations[11].orientation = vec3(-0.2, 0., -1.); orientations[11].lerptime = 2.0; orientations[11].duration = 5.0; orientations[12].orientation = normalize(vec3(0.6, -0.5, -1.)); orientations[12].lerptime = 0.5; orientations[12].duration = 5.0; orientations[13].orientation = vec3(1., 0., 0.); orientations[13].lerptime = 0.5; orientations[13].duration = 3.5; orientations[14].orientation = vec3(0., 0., -1.); orientations[14].lerptime = 0.5; orientations[14].duration = 10.0; orientation = orientations[0].orientation; } vec3 modOrientationToPortals(vec3 or, vec3 enterFront, vec3 exitFront) { vec3 enterRight = cross(vec3(0., 1., 0.), enterFront); vec3 enterUp = cross(enterFront, enterRight); vec3 exitRight = cross(vec3(0., 1., 0.), exitFront); vec3 exitUp = cross(exitFront, exitRight); vec3 enterProjection = vec3 ( dot(or, enterRight), dot(or, enterUp), dot(or, enterFront) ); return exitFront*enterProjection.z + exitRight*enterProjection.x + exitUp*enterProjection.y; } void updateState() { vec3 axisEnterFront = vec3(0., 0., -1.); vec3 axisExitFront = vec3(0., 0., -1.); float portalEnterTime = 0.; float at = 0.; position = vec3(-5., 11.0, 26.); for(int i = 4; i >= 0; i--) { // Set current Portal if(t > portalsA[i].time) { portalA = portalsA[i]; break; } } for(int i = 1; i < 10; ++i) { // Set Camera position at += states[i].duration; portalEnterTime = mix(portalEnterTime, at-states[i].duration, step(0.5, states[i].isEnterTime)); vec3 axisEnterFrontA = -mix(portalA.front, portalB.front, step(0.5, states[i].enterPortal)); axisEnterFront = mix(axisEnterFront, axisEnterFrontA, step(0.5, states[i].isEnterTime)); vec3 axisExitFrontA = mix(portalA.front, portalB.front, step(0.5, states[i].exitPortal)); axisExitFront = mix(axisExitFront, axisExitFrontA, step(0.5, states[i].isEnterTime)); if(t < at) { position = mix(states[i].posStart, states[i].posEnd, clamp((t - (at-states[i].duration)) / (states[i].lerptime), 0., 1.)); break; } } at = 0.; for(int i = 1; i < 15; ++i) { // Set Camera orientation at += orientations[i].duration; if(t < at) { vec3 prevOrientation = mix(modOrientationToPortals(orientations[i-1].orientation, axisEnterFront, axisExitFront), orientations[i-1].orientation, step(portalEnterTime, at-orientations[i].duration-orientations[i-1].duration)); vec3 currentOrientation = mix(modOrientationToPortals(orientations[i].orientation, axisEnterFront, axisExitFront), orientations[i].orientation, step(portalEnterTime, at-orientations[i].duration)); orientation = normalize(mix(prevOrientation, currentOrientation, clamp((t - (at-orientations[i].duration)) / (orientations[i].lerptime), 0., 1.))); break; } } } void mainImage( out vec4 fragColor, in vec2 fragCoord ) { t = iGlobalTime; initState(); initPortals(); initOrientations(); initLights(); updateState(); vec2 uv = fragCoord.xy / iResolution.xy; vec2 p = (uv * 2. -1.) * vec2(iResolution.x/iResolution.y, 1.); #ifdef MOUSE vec2 mo = mix(vec2(0.), iMouse.xy / iResolution.xy, step(0.001, length(iMouse.zw))); #else vec2 mo = mix(vec2(0.), 0.0 / iResolution.xy, step(0.001, length(0.0))); #endif vec3 right = cross(vec3(0., 1., 0.), orientation); orientation += right*mo.x + vec3(0., 1., 0)*mo.y; vec3 ww = normalize(orientation); vec3 uu = normalize(cross(vec3(0., 1., 0.), ww)); vec3 vv = normalize(cross(ww, uu)); vec3 rd = normalize(p.x*uu*0.7 + p.y*vv + 1.*ww); float fov = tan(0.46); rd = normalize(p.x*uu*fov + p.y*vv*fov + 1.*ww); vec3 color = vec3(0.); float att = 1.; for(int i = 0; i < 3; ++i) { vec4 res = intersect(position, rd, 0.40, 9999.); if(res.y > 0.0) { vec3 point = position + rd*res.x; vec3 normal = calcnormal(point); vec3 refposition; vec3 refdir; vec4 lparams; vec4 colorrgba = mapcolor(point, res, normal, rd, refposition, refdir, lparams); float latt = 1.-ambient; vec3 acolor = colorrgba.rgb*ambientcolor*ambient; for(int lidx = 0; lidx < 3; ++lidx) { vec3 ldir = lights[lidx].pos - point; float ldirLength = length(ldir); ldir /= ldirLength; latt *= 1.-clamp((ldirLength-5.)/35., 0., 1.); vec3 diffuse = colorrgba.rgb; float diffactor = max(0., pow(dot(ldir, normal), 1.0))*latt; vec3 reflec = reflect(rd, normal); float specfactor = pow(max(0., dot(ldir, reflec)), lparams.y) * lparams.x; float shadow = 1.; #if APPLY_SHADOW == 1 shadow = max(calcshadow(point, ldir, 0.8, ldirLength), 0.01); #endif acolor += diffuse * diffactor * lights[lidx].color* shadow; acolor += specfactor * lights[lidx].color* shadow; color += (acolor*colorrgba.a*att); } color = lparams.w*colorrgba.rgb + (1.-lparams.w)*color.rgb;; vec3 fireballcolor = mix(vec3(0.91, 0.46, 0.07), vec3(0.42, 0.90, 0.00), smoothstep(26.5, 27.0, t)); vec3 bloomcolor = mix(fireballcolor, vec3(1.6, 1.65, 1.65), step(0.5, res.w)); color.rgb = mix(mix(bloomcolor, color.rgb, 0.5), color.rgb, smoothstep(0., 1.0, res.z)); att = max(att*(1.-colorrgba.a), 0.); if(att < 0.01) { break; } rd = refdir; position = refposition; } else { att = 0.; break; } } float fadeFactor = mix(0., 1., smoothstep(39., 40., t)); fadeFactor = mix(1., fadeFactor, smoothstep(0., 1., t)); fragColor = mix(vec4(color, 1.), vec4(0.), fadeFactor); } void main(void) { //just some shit to wrap shadertoy's stuff vec2 FragCoord = vTexCoord.xy*global.OutputSize.xy; FragCoord.y = -FragCoord.y; mainImage(FragColor,FragCoord); }