-
Notifications
You must be signed in to change notification settings - Fork 0
/
TheTetrisFacility.sttf
1 lines (1 loc) · 26.4 KB
/
TheTetrisFacility.sttf
1
{"links":[{"end":"RenderOutput","filter":"Linear","slot":0,"start":"Image","wrapMode":"Repeat"},{"end":"Image","filter":"Linear","slot":0,"start":"Buffer A","wrapMode":"Clamp"},{"end":"Buffer A","filter":"Linear","slot":0,"start":"LastFrame","wrapMode":"Clamp"}],"metadata":{"Author":"Hyeve","Description":"New tetris-based shader, now with less being-broken and significantly better lighting too!\nStill some minor rendering issues in here, but that's my own fault for doing such very weird things with the geometry.","Name":"The Tetris Facility","ShaderToyURL":"https://www.shadertoy.com/view/dt33z2"},"nodes":[{"class":"RenderOutput","name":"RenderOutput"},{"class":"GLSLShader","name":"Image","source":"//fps control for performance. Assumes the refresh rate of your monitor is 60hz\n//(120hz monitor set to 30 here will actually run at 60fps)\n#define FPS 60.\n\n\n\n\n//Consts\n\n#define pi 3.1415926535\n#define degs_to_rads 0.01745329\n\n\n\n//\"Generic\" functions\n\n//Rotation matrix for an angle in radians\n#define angle(a) mat2(cos(a), sin(a), -sin(a), cos(a))\n\n//Min by X component - for combined distance/ID sdfs\n#define vector_min(a, b) (a.x < b.x ? a : b)\n\n//Splits a value into hard-edge segments. B = steps per 1 unit\n#define quantize(value, steps) (floor((value)*(steps))/(steps))\n\n//Repeats a range with a given spacing a particular number of times\n#define repeat(value, space, min, max) (value - space*clamp(round(value / space), -min, max))\n\n//Repeats a range with a given spacing an infinite number of times\n#define repeat_inf(value, space) (value - space*round(value / space))\n\n//Maths\nfloat hash11(float value) {\n return fract(sin((value) * 12.9898) * 43758.5453123);\n}\n\n//Two hashes smoothed together\nfloat noise(float value) {\n float i = floor(value), f = fract(value);\n return mix(hash11(i) * f, hash11(i + 1.) * (f - 1.),f * f * (3. - 2. * f));\n}\n\n//\"Sharpens\" a 0-1 value by powing both ends\nfloat sharpen(float value, float scale) {\n return 1.-pow(1.-pow(value, scale), scale * 2.);\n}\n\nfloat fbm_sine(float pos, float intensity, int iters, float offset)\n{ \n vec2 g = vec2(2, exp2(-intensity));\n\tvec3 f = vec3(1, 1, 0);\n\tpos -= offset * .5;\n for(int i = 0; i < iters; i++) {\n f = vec3(f.xy * g, f.z + f.y * sin(f.x * pos + offset));\n }\n return f.z;\n}\n\nfloat wave_saw(float value) {\n return mod(value, 2.);\n}\n\n//Is this a good way to calculate a triangle wave? No idea, but it works, so...\nfloat wave_tri(float value) {\n return wave_saw(value*sign(mod(value, 2.)-1.)) - 1.5; \n}\n\n\nvec3 rotate(vec3 a, vec3 r) {\n a.zy *= angle(r.x);\n a.xz *= angle(r.y);\n a.yx *= angle(r.z);\n return a;\n}\n\nfloat luma(vec3 col) {\n return col.r * 0.2126 + col.g * 0.7152 + col.b * 0.0722;\n}\n\nvec3 rgb_to_hsv(vec3 col) {\n vec4 k = vec4(0., -1./3., 2./3., -1.),\n p = mix(vec4(col.bg, k.wz), vec4(col.gb, k.xy), step(col.b, col.g)),\n q = mix(vec4(p.xyw, col.r), vec4(col.r, p.yzx), step(p.x, col.r));\n \n float d = q.x - min(q.w, q.y);\n \n return vec3(abs(q.z + (q.w - q.y) / (6. * d)), d / (q.x), q.x);\n}\n\n\nvec3 hsv_to_rgb(vec3 col) {\n vec4 k = vec4(1., 2./3., 1./3., 3.);\n vec3 p = abs(fract(col.xxx + k.xyz) * 6. - k.www);\n return col.z * mix(k.xxx, clamp(p - k.xxx, 0., 1.), col.y);\n}\n\nvec2 to_radial(vec2 xy) {\n return vec2(length(xy), atan(xy.x,xy.y));\n}\n\nvec2 from_radial(vec2 ra) {\n return vec2(sin(ra.y), cos(ra.y)) * ra.x;\n}\n\n\n//My tonemapping function. Does a pass through HSV and back to adjust hue, sat, & value\n\n//Hue/Sat params:\n//XY = Hue shift by value, X = exponent, Y = strength\n//ZW = Sat shift by value, Z = exponent, W = strength\n\n//Value params:\n//X = Contrast (value exponent)\n//Y = Intensity (value multiplier)\n//Z = Brightness (value gain)\n//W = Quantization (Number of colour steps)\n\nvec3 recolor(vec4 base, vec4 hs_params, vec4 v_params) {\n\n vec3 base_hsv = rgb_to_hsv(base.rgb);\n \n \n float value = quantize(pow(max(base.w * base_hsv.z +v_params.z, 0.),v_params.x)*v_params.y,v_params.w);\n \n \n float hueShiftLow = pow(max(0.5 - value * 0.5,0.), hs_params.x);\n float hueShiftHigh = -pow(max(value * 0.5 - 0.5, 0.), hs_params.x);\n float hueShiftDir = (base_hsv.x > .19 && base_hsv.x < .69) ? 1. : -1.; //Towards yellow / sunlight\n float hueShift = (hueShiftLow + hueShiftHigh) * hs_params.y * hueShiftDir;\n \n \n \n float hue = base_hsv.x + hueShift;\n\n \n float satShift = pow(max(0.5 - value * 0.5, 0.), hs_params.z) * hs_params.w * base_hsv.y;\n float sat = base_hsv.y + satShift;\n \n\n return hsv_to_rgb(vec3(hue,sat,value));\n \n}\n\nvec3 bezier(vec3 a, vec3 b, vec3 c, float v) {\n return mix(mix(a, b, v), mix(b, c, v), v);\n}\n\nvec3 bezier(vec3 a, vec3 b, vec3 c, vec3 d, float v) {\n return mix(bezier(a, b, c, v),bezier(b, c, d, v), v);\n}\n\nvec3 bezier(vec3 a, vec3 b, vec3 c, vec3 d, vec3 e, float v) {\n return mix(bezier(a, b, c, d, v),bezier(b, c, d, e, v), v);\n}\n\n\n//Custom refraction that ignores total internal reflection\n//Not at all physically realistic, but looks better for shaders.\nvec3 refract_abs(vec3 incident, vec3 normal, float refraction) {\n float ndi = dot(normal, incident);\n float k = 1. - pow(refraction, 2.) * (1. - pow(ndi,2.));\n k = max(abs(k),1e-4); //Negative K would be TIR\n return refraction * incident - (refraction * ndi + sqrt(k)) * normal;\n}\n\n\n//Quantization with a smoothed boundary between values.\nfloat smooth_quantize(float value, float steps, float smoothing, float sharpness) {\n float l = floor(value * steps) / steps,\n h = ceil(value * steps) / steps, \n s = (h - l),\n m = l + s * .5;\n return mix(l, h, pow(smoothstep(m - smoothing * s,m + smoothing * s, value), sharpness));\n}\n\nvec3 smooth_quantize(vec3 value, float steps, float smoothing, float sharpness) {\n vec3 l = floor(value * steps) / steps,\n h = ceil(value * steps) / steps, \n s = (h - l),\n m = l + s * .5;\n return mix(l, h, pow(smoothstep(m - smoothing * s,m + smoothing * s, value), vec3(sharpness)));\n}\n\n\n//Clamps a 0-1 range around..?\nfloat snip(float v, float w, float a) {\n return clamp(v - (a - w / 2.), 0., w) * (1. / w);\n}\n\n\n\n//SDF Maths\n\n//IQ's smooth min for SDFs\nfloat smooth_min(float a, float b, float smoothing) {\n float h = clamp(.5 + .5 * (b - a) / smoothing, 0., 1.);\n return mix(b, a, h) - smoothing * h * (1. - h);\n}\n\n\n//Range dividing for better and more dynamic domain repetition\nvec2 divide(vec2 range, float pos, float axis, inout float id) {\n float z = range.x + range.y * pos;\n if(z < axis) {\n range.y = range.x + range.y - z;\n range.x = z;\n id += 1.0;\n }\n else {\n range.y = z - range.x;\n id *= 1.5;\n }\n return range;\n}\n\n//Generates a sharp impulse designed for use as a normal offset to create an indent/bump line\nfloat normal_edge(vec2 vs, vec2 mm) {\n return mix(mix(mm.x, mm.y, smoothstep(.5 - vs.y, .5 + vs.y, vs.x)),0., abs(vs.x - .5) * 2.);\n}\n\n\n\n//3D Shapes\n\nfloat sdf_box(vec3 pos, vec3 size) {\n vec3 q = abs(pos) - size;\n return min(max(q.x, max(q.y, q.z)), 0.) + length(max(q, 0.));\n}\n\nfloat sdf_cylinder(vec3 pos, vec2 size) {\n vec2 w = vec2(length(pos.xy) - size.x, abs(pos.z) - size.y);\n return min(max(w.x, w.y), 0.) + length(max(w, 0.));\n}\n\nfloat sdf_torus(vec3 pos, vec2 size) {\n return length(vec2(length(pos.xz) - size.x, pos.y)) - size.y;\n}\n\nfloat sdf_gyroid(vec3 pos, vec3 size) {\n return abs(dot(sin(pos * size.x), cos((pos * size.y).zxy)) - size.z) / max(size.x, size.y) * 1.8;\n}\n\n\n//Params = offset for fbm A, offset for fbm B, and scaling\nfloat sdf_fluid(vec3 pos, vec3 params)\n{\n\tfloat v = pos.y;\n\tv -= fbm_sine(pos.z * .5, 1., 3, params.x)*params.z+.5;\n\tv -= fbm_sine(pos.x * .5, 1., 3, params.y)*params.z+.5;\n\treturn v;\n}\n\n\n//4D Shapes\n\nfloat sdf_hyper_cube(vec4 pos, vec4 size) {\n vec4 q = abs(pos) - size;\n return min(max(q.x, max(q.y, max(q.z, q.w))), 0.) + length(max(q, 0.));\n}\n\n\nfloat sdf_hyper_gyroid(vec4 pos, vec3 size) {\n return abs(dot(sin(pos * size.x), cos((pos * size.y).zxyw)) - size.z) / max(size.x, size.y) * 1.8;\n}\n\n\n//See the common tab for fps control.\n\nvoid mainImage( out vec4 fragColor, in vec2 fragCoord )\n{\n fragColor = texture(iChannel0, fragCoord / iResolution.xy);\n}\n\n","type":"Image"},{"class":"GLSLShader","name":"Buffer A","source":"//fps control for performance. Assumes the refresh rate of your monitor is 60hz\n//(120hz monitor set to 30 here will actually run at 60fps)\n#define FPS 60.\n\n\n\n\n//Consts\n\n#define pi 3.1415926535\n#define degs_to_rads 0.01745329\n\n\n\n//\"Generic\" functions\n\n//Rotation matrix for an angle in radians\n#define angle(a) mat2(cos(a), sin(a), -sin(a), cos(a))\n\n//Min by X component - for combined distance/ID sdfs\n#define vector_min(a, b) (a.x < b.x ? a : b)\n\n//Splits a value into hard-edge segments. B = steps per 1 unit\n#define quantize(value, steps) (floor((value)*(steps))/(steps))\n\n//Repeats a range with a given spacing a particular number of times\n#define repeat(value, space, min, max) (value - space*clamp(round(value / space), -min, max))\n\n//Repeats a range with a given spacing an infinite number of times\n#define repeat_inf(value, space) (value - space*round(value / space))\n\n//Maths\nfloat hash11(float value) {\n return fract(sin((value) * 12.9898) * 43758.5453123);\n}\n\n//Two hashes smoothed together\nfloat noise(float value) {\n float i = floor(value), f = fract(value);\n return mix(hash11(i) * f, hash11(i + 1.) * (f - 1.),f * f * (3. - 2. * f));\n}\n\n//\"Sharpens\" a 0-1 value by powing both ends\nfloat sharpen(float value, float scale) {\n return 1.-pow(1.-pow(value, scale), scale * 2.);\n}\n\nfloat fbm_sine(float pos, float intensity, int iters, float offset)\n{ \n vec2 g = vec2(2, exp2(-intensity));\n\tvec3 f = vec3(1, 1, 0);\n\tpos -= offset * .5;\n for(int i = 0; i < iters; i++) {\n f = vec3(f.xy * g, f.z + f.y * sin(f.x * pos + offset));\n }\n return f.z;\n}\n\nfloat wave_saw(float value) {\n return mod(value, 2.);\n}\n\n//Is this a good way to calculate a triangle wave? No idea, but it works, so...\nfloat wave_tri(float value) {\n return wave_saw(value*sign(mod(value, 2.)-1.)) - 1.5; \n}\n\n\nvec3 rotate(vec3 a, vec3 r) {\n a.zy *= angle(r.x);\n a.xz *= angle(r.y);\n a.yx *= angle(r.z);\n return a;\n}\n\nfloat luma(vec3 col) {\n return col.r * 0.2126 + col.g * 0.7152 + col.b * 0.0722;\n}\n\nvec3 rgb_to_hsv(vec3 col) {\n vec4 k = vec4(0., -1./3., 2./3., -1.),\n p = mix(vec4(col.bg, k.wz), vec4(col.gb, k.xy), step(col.b, col.g)),\n q = mix(vec4(p.xyw, col.r), vec4(col.r, p.yzx), step(p.x, col.r));\n \n float d = q.x - min(q.w, q.y);\n \n return vec3(abs(q.z + (q.w - q.y) / (6. * d)), d / (q.x), q.x);\n}\n\n\nvec3 hsv_to_rgb(vec3 col) {\n vec4 k = vec4(1., 2./3., 1./3., 3.);\n vec3 p = abs(fract(col.xxx + k.xyz) * 6. - k.www);\n return col.z * mix(k.xxx, clamp(p - k.xxx, 0., 1.), col.y);\n}\n\nvec2 to_radial(vec2 xy) {\n return vec2(length(xy), atan(xy.x,xy.y));\n}\n\nvec2 from_radial(vec2 ra) {\n return vec2(sin(ra.y), cos(ra.y)) * ra.x;\n}\n\n\n//My tonemapping function. Does a pass through HSV and back to adjust hue, sat, & value\n\n//Hue/Sat params:\n//XY = Hue shift by value, X = exponent, Y = strength\n//ZW = Sat shift by value, Z = exponent, W = strength\n\n//Value params:\n//X = Contrast (value exponent)\n//Y = Intensity (value multiplier)\n//Z = Brightness (value gain)\n//W = Quantization (Number of colour steps)\n\nvec3 recolor(vec4 base, vec4 hs_params, vec4 v_params) {\n\n vec3 base_hsv = rgb_to_hsv(base.rgb);\n \n \n float value = quantize(pow(max(base.w * base_hsv.z +v_params.z, 0.),v_params.x)*v_params.y,v_params.w);\n \n \n float hueShiftLow = pow(max(0.5 - value * 0.5,0.), hs_params.x);\n float hueShiftHigh = -pow(max(value * 0.5 - 0.5, 0.), hs_params.x);\n float hueShiftDir = (base_hsv.x > .19 && base_hsv.x < .69) ? 1. : -1.; //Towards yellow / sunlight\n float hueShift = (hueShiftLow + hueShiftHigh) * hs_params.y * hueShiftDir;\n \n \n \n float hue = base_hsv.x + hueShift;\n\n \n float satShift = pow(max(0.5 - value * 0.5, 0.), hs_params.z) * hs_params.w * base_hsv.y;\n float sat = base_hsv.y + satShift;\n \n\n return hsv_to_rgb(vec3(hue,sat,value));\n \n}\n\nvec3 bezier(vec3 a, vec3 b, vec3 c, float v) {\n return mix(mix(a, b, v), mix(b, c, v), v);\n}\n\nvec3 bezier(vec3 a, vec3 b, vec3 c, vec3 d, float v) {\n return mix(bezier(a, b, c, v),bezier(b, c, d, v), v);\n}\n\nvec3 bezier(vec3 a, vec3 b, vec3 c, vec3 d, vec3 e, float v) {\n return mix(bezier(a, b, c, d, v),bezier(b, c, d, e, v), v);\n}\n\n\n//Custom refraction that ignores total internal reflection\n//Not at all physically realistic, but looks better for shaders.\nvec3 refract_abs(vec3 incident, vec3 normal, float refraction) {\n float ndi = dot(normal, incident);\n float k = 1. - pow(refraction, 2.) * (1. - pow(ndi,2.));\n k = max(abs(k),1e-4); //Negative K would be TIR\n return refraction * incident - (refraction * ndi + sqrt(k)) * normal;\n}\n\n\n//Quantization with a smoothed boundary between values.\nfloat smooth_quantize(float value, float steps, float smoothing, float sharpness) {\n float l = floor(value * steps) / steps,\n h = ceil(value * steps) / steps, \n s = (h - l),\n m = l + s * .5;\n return mix(l, h, pow(smoothstep(m - smoothing * s,m + smoothing * s, value), sharpness));\n}\n\nvec3 smooth_quantize(vec3 value, float steps, float smoothing, float sharpness) {\n vec3 l = floor(value * steps) / steps,\n h = ceil(value * steps) / steps, \n s = (h - l),\n m = l + s * .5;\n return mix(l, h, pow(smoothstep(m - smoothing * s,m + smoothing * s, value), vec3(sharpness)));\n}\n\n\n//Clamps a 0-1 range around..?\nfloat snip(float v, float w, float a) {\n return clamp(v - (a - w / 2.), 0., w) * (1. / w);\n}\n\n\n\n//SDF Maths\n\n//IQ's smooth min for SDFs\nfloat smooth_min(float a, float b, float smoothing) {\n float h = clamp(.5 + .5 * (b - a) / smoothing, 0., 1.);\n return mix(b, a, h) - smoothing * h * (1. - h);\n}\n\n\n//Range dividing for better and more dynamic domain repetition\nvec2 divide(vec2 range, float pos, float axis, inout float id) {\n float z = range.x + range.y * pos;\n if(z < axis) {\n range.y = range.x + range.y - z;\n range.x = z;\n id += 1.0;\n }\n else {\n range.y = z - range.x;\n id *= 1.5;\n }\n return range;\n}\n\n//Generates a sharp impulse designed for use as a normal offset to create an indent/bump line\nfloat normal_edge(vec2 vs, vec2 mm) {\n return mix(mix(mm.x, mm.y, smoothstep(.5 - vs.y, .5 + vs.y, vs.x)),0., abs(vs.x - .5) * 2.);\n}\n\n\n\n//3D Shapes\n\nfloat sdf_box(vec3 pos, vec3 size) {\n vec3 q = abs(pos) - size;\n return min(max(q.x, max(q.y, q.z)), 0.) + length(max(q, 0.));\n}\n\nfloat sdf_cylinder(vec3 pos, vec2 size) {\n vec2 w = vec2(length(pos.xy) - size.x, abs(pos.z) - size.y);\n return min(max(w.x, w.y), 0.) + length(max(w, 0.));\n}\n\nfloat sdf_torus(vec3 pos, vec2 size) {\n return length(vec2(length(pos.xz) - size.x, pos.y)) - size.y;\n}\n\nfloat sdf_gyroid(vec3 pos, vec3 size) {\n return abs(dot(sin(pos * size.x), cos((pos * size.y).zxy)) - size.z) / max(size.x, size.y) * 1.8;\n}\n\n\n//Params = offset for fbm A, offset for fbm B, and scaling\nfloat sdf_fluid(vec3 pos, vec3 params)\n{\n\tfloat v = pos.y;\n\tv -= fbm_sine(pos.z * .5, 1., 3, params.x)*params.z+.5;\n\tv -= fbm_sine(pos.x * .5, 1., 3, params.y)*params.z+.5;\n\treturn v;\n}\n\n\n//4D Shapes\n\nfloat sdf_hyper_cube(vec4 pos, vec4 size) {\n vec4 q = abs(pos) - size;\n return min(max(q.x, max(q.y, max(q.z, q.w))), 0.) + length(max(q, 0.));\n}\n\n\nfloat sdf_hyper_gyroid(vec4 pos, vec3 size) {\n return abs(dot(sin(pos * size.x), cos((pos * size.y).zxyw)) - size.z) / max(size.x, size.y) * 1.8;\n}\n\n\nfloat time; //Global time, usually modulo'd to loop ever few minutes\n\nstruct obj_data {\n\n int skips; //Number of surfaces to skip rendering after initial hit (for transparent objects)\n\n float refraction; //Index of refraction for transparent objects - set negative to do reflection\n float alpha; //Alpha of the object. 1 = opaque / matt, 0 = invisible / perfect mirror\n\n vec3 color; //Base colour for the object\n \n vec3 glow; //Glow accumulated over all objects\n \n vec3 normals; //Normal rotation to create normal mapped effects\n \n vec4 lighting; //Light position & ambient brightness\n \n vec2 subsurf; //Subsurface distance and intensity\n \n vec4 highlights; //Specular & Fresnel\n \n vec4 occlusion; //AO / Shadow intensity / Fog\n \n vec4 tone_huesat; //Tonemapping hue/sat data\n \n vec4 tone_value; //Tonemapping value data\n}\n\n\nobj = obj_data(\n 1, //Skips (Skip once)\n 1.0, //Refraction (None)\n 1.0, //Alpha (Opaque)\n vec3(1), //Color (White)\n vec3(0), //Glow (None)\n vec3(0), //Normal Offset (None)\n vec4(0,0,-100,0.), //Lighting data (Position 0, 0, -100, Ambient 0)\n vec2(1.5,0.), //Subsurf (1.5 distance, 0 intensity)\n vec4(1,3, 1., 5.), //Specular data (Intensity 1, Sharpness 3)\n vec4(1.,0.2,0.01,1.), //Occlusion & Fog (AO, Shadow, Fog distance, fog thickness)\n vec4(1.,0.,1.,0.), //Tonemap hue/sat data (No hue shift, no sat shift)\n vec4(1.,1.,0.,999.) //Tonemap value data (Full contrast, Full brightness, No boost, No quantization)\n ); //Default object properties\n\n\n\nvec3 mino_color(float index)\n{\n\tint num = int(mod(index,7.));\n\tswitch(num) {\n case 0: return vec3(0.5,0.2,0.8); //T\n case 1: return vec3(0.,0.2,0.7); //J\n case 2: return vec3(0.9,0.5,0.); //L\n case 3: return vec3(0.1,0.7,0.8); //I\n case 4: return vec3(0.8,0.7,0.1); //O\n case 5: return vec3(0.7,0.,0.); //Z\n case 6: return vec3(0.,0.7,0.); //S\n }\n\treturn vec3(0);\n}\n\nfloat sdf_mino(float index, vec3 pos, float size) {\n float num = floor(mod(index, 7.));\n\n //I started with a switch that set the 4 block offsets for each case\n //Then collapsed it to as little logic as possible by hand.\n\n vec3 o1 = vec3(-(step(6., num) - 0.5) * 2., 0., 0.);\n vec3 o2 = vec3((mod(num + 1., 2.) - 0.5) * 2. * step(0.5, num), 1., 0.);\n vec3 o3 = vec3(step(4., num) - 1., step(4., num), 0.);\n vec3 o4 = vec3(-0.5 * step(0.5, round(1.5 - abs(num - 3.5))), -0.5, 0.);\n \n if(num == 3.) //Special case for I blocks.\n {\n o2 = vec3(2., 0., 0.);\n o4.y = 0.;\n }\n\n vec3 cube_size = vec3(size / 2.);\n float d1 = sdf_box(pos + o4 * size, cube_size);\n float d2 = sdf_box(pos + (o1 + o4) * size, cube_size);\n float d3 = sdf_box(pos + (o2 + o4) * size, cube_size);\n float d4 = sdf_box(pos + (o3 + o4) * size, cube_size);\n \n return min(d1, min(d2, min(d3, d4)));\n}\n\n//Complete scene SDF. Also sets object data\nfloat scene(vec3 pos)\n{\t\t\n\n pos.xy *= angle(pos.z*0.01);\n\n vec3 orig_pos = pos;\n\n pos.z -= 10.;\n\n pos = rotate(pos, vec3(0.2*time,0.1*time,0.3*time));\n \n \n \n float pieceNow = hash11(floor(time) + 0.32895) * 7.;\n float pieceNext = hash11(floor(time + 1.) + 0.32895) * 7.;\n \n float blend = sharpen(fract(time), 10.);\n \n float scene_dist = mix(sdf_mino(pieceNow, pos, 4.), sdf_mino(pieceNext, pos, 4.), blend) - 0.3;\n \n vec3 color = mix(mino_color(pieceNow), mino_color(pieceNext), blend) * 2.;\n \n pos = orig_pos;\n \n pos.y = abs(pos.y) - 10.;\n \n float walls = sdf_box(pos, vec3(20., 1., 100.));\n\n pos.z += time;\n vec3 floor_pos = pos;\n floor_pos.z = repeat_inf(floor_pos.z, 10.);\n \n float floor_piece = sdf_mino(floor((pos.z+5.)/10.)+floor(orig_pos.y+0.5)*3., floor_pos.xzy, 2.5);\n \n walls = min(walls, floor_piece);\n\n pos.x = abs(pos.x) - 10.;\n \n walls = min(walls, sdf_box(pos, vec3(1., 15., 100.)));\n \n\n \n pos.z = repeat_inf((pos.z), 30.);\n pos.yz *= angle(time*0.1);\n \n \n walls = max(walls, -sdf_box(pos, vec3(5., 5., 12.)));\n \n scene_dist = min(scene_dist, walls);\n \n float refl = length(pos.x) < 3. && length(pos.y) < 4. ? 0.1 : 1.;\n \n pos = orig_pos;\n\n float deco = abs(sdf_box(pos+vec3(0.,0.,12.), vec3(9., 9., 0.1)))-0.001;\n\n \n scene_dist = min(scene_dist, deco);\n \n //Update object data\n \n obj.refraction = scene_dist == walls ? -1. : 1.1;\n \n obj.color = scene_dist == walls ? vec3(1.) : color;\n \n obj.alpha = scene_dist == walls ? refl : 0.2;\n \n obj.highlights = vec4(0.5,2., 0.7, 3.);\n \n obj.occlusion = vec4(1.,0., 0.01, 5.);\n \n obj.normals = vec3(0., 0., 0.);\n \n obj.lighting = vec4(0,0, -15., 0.5);\n \n obj.subsurf = vec2(1.,1.);\n \n obj.skips = 1;\n \n obj.tone_value = vec4(0.3,1.,0., 999.);\n \n obj.tone_huesat = vec4(1., 1.5, 1., 3.);\n \n if(obj.alpha < 1.) scene_dist = abs(scene_dist) - 0.001;\n \n\n\treturn scene_dist * 0.9;\n}\n\n//Calculates the normal for any position (Usually the hit/intersection/surface position)\nvec3 calc_normal(vec3 pos) {\n mat3 k = mat3(pos, pos, pos) - mat3(.001);\n return normalize(scene(pos) - vec3(scene(k[0]), scene(k[1]), scene(k[2])));\n}\n\n\n//Raymarches the scene and computes:\n//X - Distance raymarched\n//Y - Min surface distance detected\nvec2 raymarch(vec3 ray_origin, vec3 ray_dir, float surf_dist, float max_dist, int max_steps) {\n float current_dist = 0.;\n float min_dist = max_dist;\n \n for(int i = 0; i < max_steps; i++) {\n float scene_dist = scene(ray_origin + ray_dir * current_dist);\n current_dist += scene_dist;\n \n if(scene_dist < min_dist && current_dist < max_dist) min_dist = scene_dist;\n if(scene_dist < surf_dist || scene_dist > max_dist) break;\n }\n \n return vec2(current_dist, min_dist);\n}\n \n \nvec4 calc_color(obj_data hit, vec3 hit_pos, vec3 hit_norm, vec3 adj_norm, vec3 ray_dir, vec2 uv, float total_dist, bool is_bg)\n{\n\n vec3 background_col = vec3(1.5 - length(ray_dir.xy));\n \n \n \n //Color is defaulted to background\n vec4 color = vec4(background_col, hit.alpha);\n \n if(is_bg) return vec4(background_col, 1.);\n \n //Basic point light\n vec3 light_dir = normalize(hit_pos - hit.lighting.xyz);\n float diffuse = max(dot(adj_norm, -light_dir), hit.lighting.w);\n \n\n\n //Subsurface lighting - NOT ALWAYS CORRECT ON TRANSPARENT / ONIONED OBJECTS\n if(hit.subsurf.x > 0.) {\n float subsurf = min(scene(hit_pos - light_dir * hit.subsurf.x) / hit.subsurf.x, hit.subsurf.y);\n diffuse = max(diffuse, subsurf);\n }\n\n //AO\n if(hit.occlusion.x > 0.) {\n float dist = raymarch(hit_pos + hit_norm * 0.005, hit_norm, 1e-3, 24., 12).x; \n hit.tone_value.y -= (1. - pow(clamp(dist / 24., 0., 1.), 0.1)) * hit.occlusion.x;\n }\n \n //Shadows\n if(hit.occlusion.y > 0.) {\n float dist = raymarch(hit_pos + hit_norm * 0.05, -light_dir, 1e-3, 64., 128).y;\n dist /= 0.05;\n hit.tone_value.y -= max(pow(1. - clamp(dist, 0., 1.), 1.5), 0.) * hit.occlusion.y;\n }\n \n //Colour adjustment\n vec3 fresnel_col = mix(vec3(0.8), background_col.rgb, 0.1);\n float fresnel = max(pow(1. - abs(dot(ray_dir, -adj_norm)), hit.highlights.w), 1e-4) * hit.highlights.z;\n \n //Highlights\n vec3 light_cross = cross(ray_dir + light_dir, adj_norm); \n vec3 base_color = hit.color + pow(max(1. - length(light_cross), 0.), hit.highlights.y) * hit.highlights.x;\n \n color.rgb = recolor(vec4(base_color, diffuse), hit.tone_huesat, hit.tone_value);\n \n color.rgb = mix(color.rgb, fresnel_col, quantize(fresnel, hit.tone_value.w));\n \n //Glow, HDR expansion\n color.rgb += hit.glow;\n color.rgb *= max(max(color.r, max(color.g, color.b)), 1.);\n \n //Mix towards background by fog\n float fog = exp( -pow(hit.occlusion.z * total_dist, hit.occlusion.w));\n color.rgb = mix(background_col, color.rgb, fog); \n \n return color;\n}\n\n\n\nvec4 render(vec2 frag, vec2 res, float real_time)\n{\n \n vec2 uv = (frag.xy - .5 * res.xy) / res.y; //0,0 Centred and square aspect ratio UV coords\n time = mod(real_time, 100.); //Set global time\n \n \n //Setup camera\n vec3 ray_origin = vec3(0,0,-20);\n vec3 ray_dir = normalize(vec3(uv, 1));\n \n \n //Setup variables\n int skip_count = 0;\n float total_dist = 0.;\n vec4 final_color = vec4(0);\n \n //Transparency / Reflection iterations\n for(int i = 0; i < 10; i++)\n {\n\t \t//Raymarch surface\n float dist = raymarch(ray_origin, ray_dir, 1e-4, 128., 256).x;\n vec3 hit_pos = ray_origin + ray_dir * dist;\n total_dist += dist;\n \n obj_data hit = obj;\n \n //Calc normals\n vec3 norm = calc_normal(hit_pos);\n vec3 adj_norm = rotate(norm, hit.normals);\n adj_norm = dot(adj_norm, -ray_dir) > 0. ? adj_norm : reflect(adj_norm, ray_dir);\n \n \n //Attempt to refract or reflect\n float refraction = i % 2 == 0 ? 1. / hit.refraction : hit.refraction;\n vec3 new_ray = refract(ray_dir, adj_norm, refraction);\n if(hit.refraction < 0. || length(new_ray) == 0.) new_ray = reflect(ray_dir, adj_norm);\n \n //Calculate surface color\n vec4 color = calc_color(hit, hit_pos, norm, adj_norm, ray_dir, uv, total_dist, dist > 128.);\n \n //Update ray\n ray_origin = hit_pos - norm * (hit.refraction < 0. ? -0.01 : 0.01 );\n ray_dir=new_ray;\n \n //Alpha blend if not skipping this surface\n\t \tif(skip_count < 1) final_color += vec4(color.rgb * color.a, color.a) * (1. - final_color.a);\n\t \tif(final_color.a >= 1.) break;\n \n //Reset or decrement skip count if needed\n skip_count = skip_count == 0 ? hit.refraction < 0. ? 0 : hit.skips : skip_count - 1;\n }\n \n \n final_color /= final_color.a; //Fix any < 1. alphas\n\t \n final_color *= 1. - pow(length(uv), 5.) * 0.8; //Global vignette \n \n return pow(final_color, vec4(0.9)); //Slight gamma correction\n}\n\nvoid mainImage( out vec4 fragColor, in vec2 fragCoord )\n{\n //Artifical FPS limiter\n if(mod(float(iFrame), 60. / FPS) < 1. || iFrame < 5)\n fragColor = render(fragCoord.xy,iResolution.xy,iTime);\n else\n fragColor = texture(iChannel0, fragCoord / iResolution.xy);\n}\n\n","type":"Image"},{"class":"LastFrame","name":"LastFrame","ref":"Buffer A","type":"Image"}]}