0x06dc474f…f7cesent to0x0a1bbd57…3676·#17,192,534·view on Etherscan
function t(t){return new URL(window.location.href).searchParams.get(t)}console.log("Made by Lars Wander https://larswander.com"),console.log("Licensed under CC BY-NC-SA 4.0");const e=t("hash")??tokenData.hash,r=window.devicePixelRatio??1;console.log(tokenData.hash);class n{constructor(){this.useA=!1;let t=function(t){let e=parseInt(t.substring(0,8),16),r=parseInt(t.substring(8,16),16),n=parseInt(t.substring(16,24),16),i=parseInt(t.substring(24,32),16);return function(){e|=0,r|=0,n|=0,i|=0;let t=(e+r|0)+i|0;return i=i+1|0,e=r^r>>>9,r=n+(n<<3)|0,n=n<<21|n>>>11,n=n+t|0,(t>>>0)/4294967296}};this.prngA=new t(e.substring(2,34)),this.prngB=new t(e.substring(34,66));for(let t=0;t<1e6;t+=2)this.prngA(),this.prngB()}random(){return this.useA=!this.useA,this.useA?this.prngA():this.prngB()}}const i=new n,o=()=>i.random();function s(t,e){null==e&&(e=t,t=0),null==e&&(e=1);const r=e-t;return o()*r+t}function l(t){return null==t&&(t=.5),o()<t}const a=[.01,.1312,1.5806,7.7489,19.1068,27.2789,40.2367,43.3749,35.6146,22.4668,9.3318,1.7627,.4155,4.0426,12.3338,25.4684,39.3398,55.1236,70.52,84.6489,97.1482,99.1948,101.167,92.3319,75.0964,53.9294,36.1246,21.4712,12.2407,6.6892,3.2018,1.3875,.6874,.342,.1355,.0699,.0375,.0191],u=[0,.0164,.1655,.8051,1.9994,3.3546,6.5121,10.4722,15.1035,21.2723,29.3981,36.8978,50.3903,65.4035,79.829,94.2494,100.4376,103.1928,99.73,92.057,83.2302,68.9442,59.2511,47.3083,34.9129,23.6123,15.0491,8.6109,4.8369,2.6164,1.2447,.5369,.265,.1338,.0493,.028,.015,.0064],c=[.035,.5738,7.1169,35.6246,90.8624,134.661,206.3009,233.4076,205.6291,151.3409,89.5041,45.1892,23.8938,12.0738,6.3608,3.2845,1.4303,.4162,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],f=a.length,h=s(),d=s(),x=s(),_=s(),m=s(),v=l(.1)&&m>.4,y=s(),p=s(),w=s(),T=s(),g=s(),A=8,b=4,E=lt(.01,.07,h),R=E*lt(.1,.6,d),S=lt(.18,.3,_),M=180*lt(1,.7,_),z=lt(-.4,.14,m),P=lt(.01,.15,g),L=3/f,N=.02,I=lt(.09,lt(.13,.11,x),y),U=0,$=.16,F=t=>Math.pow(t,.25),B=lt(.21,.45,p),D=lt(.4,.55,p),X=Math.round(lt(20,38,x)),C=2,k=1,O=lt(.75,lt(.55,.59,y),w),G=.85,Y=.75,q=lt(3.5,4.5,T),H=Number(t("Dpx")??500),W=(t("T")??"1,1").split(",").map((t=>Number(t))),V=(t("i")??"0,0").split(",").map((t=>Number(t)));console.table({RAY_EXTEND_T:h,RAY_NORMAL_T:d,SPECTRAL_SEPARATION_T:_,SPECTRAL_BIAS_T:m,SKEW_Z_T:T,SPECTRAL_LIGHT_SPREAD_T:g,SPHERE_COUNT:X,SPHERE_COUNT_T:x,MAX_SPHERE_SIZE_T:y,SECONDARY_RADIUS_MAX:I,DESAT_T:p,ZOOM_T:w});const Z="#version 300 es\nprecision highp float;\n\nin vec2 a_coord;\n\nout vec2 v_tex;\n\nvoid main() {\n vec2 pos = (a_coord * 2.0) - 1.0;\n gl_Position = vec4(pos, 0.0, 1.0);\n v_tex = a_coord;\n}\n";function K(t){const e=t.getContext("webgl2",{preserveDrawingBuffer:!0});if(e){if(e.getExtension("EXT_color_buffer_float"))return e.pixelStorei(e.UNPACK_ALIGNMENT,1),e;alert("Unable to render to F16 buffer")}else alert("Unable to create webgl context")}function j(t,e,r){const n=t.createShader(e);return t.shaderSource(n,r),t.compileShader(n),n}function J(t,e,r){const n=t.createProgram();return t.attachShader(n,e),t.attachShader(n,r),t.linkProgram(n),n}function Q(t){const e=Array(t[0].length*t.length);for(let r=0;r<t[0].length;r++)for(let n=0;n<t.length;n++)e[r*t.length+n]=t[n][r];return e}class tt{constructor(t,e,r,n){this.gl=t,this.width=e,this.height=r,this.texture=t.createTexture(),t.bindTexture(t.TEXTURE_2D,this.texture),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texImage2D(t.TEXTURE_2D,0,t.RGBA16F,e,r,0,t.RGBA,t.FLOAT,n),this.framebuffer=t.createFramebuffer(),t.bindFramebuffer(t.FRAMEBUFFER,this.framebuffer),t.framebufferTexture2D(t.FRAMEBUFFER,t.COLOR_ATTACHMENT0,t.TEXTURE_2D,this.texture,0)}read(){return this.texture}write(){return this.framebuffer}}class et{constructor(t,e){this.pool=t,this.id=e}read(){return this.pool.getRead(this.id).read()}write(){return this.pool.getWrite(this.id).write()}flip(){this.pool.flip()}}class rt{constructor(t,e,r){this.gl=t,this.width=e,this.height=r,this.buffers=[new tt(t,e,r,null)],this.writeIndex=0,this.owners=[],this.onLease=-1}add(t){return this.buffers.push(new tt(this.gl,this.width,this.height,t)),this.owners.push(this.buffers.length-1),new et(this,this.owners.length-1)}getRead(t){return this.buffers[this.owners[t]]}getWrite(t){if(this.onLease>=0)throw new Error(`Illegal state: already on lease to ${this.onLease}`);return this.onLease=t,this.buffers[this.writeIndex]}flip(){if(this.onLease<0)throw new Error("Can't flip: no lease open");const t=this.owners[this.onLease];this.owners[this.onLease]=this.writeIndex,this.writeIndex=t,this.onLease=-1}}function nt(t,e,r,n){const{vertShader:i,width:o,height:s,coordBuffer:l}=n,a=J(t,i,j(t,t.FRAGMENT_SHADER,e)),u=t.createVertexArray();t.bindVertexArray(u);const c=t.getAttribLocation(a,"a_coord"),f=l;t.bindBuffer(t.ARRAY_BUFFER,f),t.enableVertexAttribArray(c);var h=t.FLOAT;t.vertexAttribPointer(c,2,h,!1,0,0);const d={program:a,width:o,height:s,vertexArray:u};for(const e of r)d[e]=t.getUniformLocation(a,e);return d}function it(t,e,r,n,i){const o=j(t,t.VERTEX_SHADER,Z),s=t.createBuffer();return t.bindBuffer(t.ARRAY_BUFFER,s),t.bufferData(t.ARRAY_BUFFER,new Float32Array([n.x,n.y,i.x,n.y,n.x,i.y,n.x,i.y,i.x,n.y,i.x,i.y]),t.STATIC_DRAW),{vertShader:o,width:e,height:r,coordBuffer:s}}function ot(t,e,r,n,i){t.bindFramebuffer(t.FRAMEBUFFER,n),t.viewport(0,0,e.width,e.height),t.clearColor(0,0,0,0),t.clear(t.COLOR_BUFFER_BIT),t.useProgram(e.program),t.bindVertexArray(e.vertexArray),t.uniform2f(e.u_r,e.width,e.height),t.uniform1i(e.u_S0,0),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,r),i&&i(),t.drawArrays(t.TRIANGLES,0,6)}function st(t,e,r){return Math.max(t,Math.min(e,r))}function lt(t,e,r){return"number"==typeof t?t*(1-r)+e*r:t.lerpT(e,r)}function at(t,e=2){const r=10**e;return Math.round(t*r)/r}class ut{constructor(t,e){isNaN(t)?null==t&&(this.x=0,this.y=0):(this.x=t,this.y=e)}dot(t){return this.x*t.x+this.y*t.y}lerpT(t,e){return this.mul(1-e).add(t.mul(e))}add(t){return new ut(this.x+t.x,this.y+t.y)}sub(t){return new ut(this.x-t.x,this.y-t.y)}mul(t){return new ut(this.x*t,this.y*t)}div(t){return new ut(this.x/t,this.y/t)}floor(){return new ut(Math.floor(this.x),Math.floor(this.y))}dist(t){if(null==t)return Math.sqrt(this.x*this.x+this.y*this.y);{const e=this.x-t.x,r=this.y-t.y;return Math.sqrt(e*e+r*r)}}normalize(){const t=Math.sqrt(this.dot(this));return new ut(this.x/t,this.y/t)}}function ct(t=null,e=null,n="main"){var i=document.createElement("canvas");return i.id=n,i.width=t*r,i.height=e*r,i.style.width=t,i.style.height=e,document.body.appendChild(i),i}function ft(t,e="download"){const r=document.createElement("a");r.setAttribute("download",e),t.toBlob((function(t){r.setAttribute("href",URL.createObjectURL(t)),r.click()}))}class ht{constructor(t,e,r){this.x=t,this.y=e,this.z=r}dot(t){return this.x*t.x+this.y*t.y+this.z*t.z}cross(t){return new ht(this.y*t.z-this.z*t.y,this.x*t.z-this.z*t.x,this.x*t.y-this.y*t.x)}lerpT(t,e){return this.mul(1-e).add(t.mul(e))}add(t){return new ht(this.x+t.x,this.y+t.y,this.z+t.z)}sub(t){return new ht(this.x-t.x,this.y-t.y,this.z-t.z)}mul(t){return new ht(this.x*t,this.y*t,this.z*t)}mul3(t){return new ht(this.x*t.x,this.y*t.y,this.z*t.z)}div(t){return new ht(this.x/t,this.y/t,this.z/t)}rotateX(t){const e=Math.cos(t),r=Math.sin(t);return new ht(this.x,this.y*e-this.z*r,this.y*r+this.z*e)}rotateY(t){const e=Math.cos(t),r=Math.sin(t);return new ht(this.x*e+this.z*r,this.y,-this.x*r+this.z*e)}rotateZ(t){const e=Math.cos(t),r=Math.sin(t);return new ht(this.x*e-this.y*r,this.x*r+this.z*e,this.z)}dist(t){if(null==t)return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z);{const e=this.x-t.x,r=this.y-t.y,n=this.z-t.z;return Math.sqrt(e*e+r*r+n*n)}}normalize(){const t=this.dist();return 0===t?new ht(0,0,0):this.div(t)}toString(){return`(${at(this.x)}, ${at(this.y)}, ${at(this.z)})`}}const dt=Q([a,u,c]),xt=new ht(0,0,-2);let _t=!0,mt=!1,vt=Number(t("N")??130);const yt=`#version 300 es\nprecision highp float; uniform sampler2D u_S0; uniform vec2 u_r; in vec2 v_tex; out vec4 o_col; vec3 aces_film(vec3 x) { float a = 2.4; float b = 0.03; float c = 2.4; float d = 0.59; float e = 0.14f; return clamp((x*(a*x+b))/(x*(c*x+d)+e), 0.0, 1.0); } vec3 desat(vec3 c, float t) { float avg = dot(c, vec3(1.0)) / 3.0; return mix(c, vec3(avg), t); } void main(void) { vec3 c = texture(u_S0, v_tex).xyz; float mag = length(aces_film(c)) / sqrt(3.0); float sat = mix(float(${B}), float(${D}), mag); o_col = vec4(aces_film(desat(c, sat)), 1.0); }\n`,pt=` const mat3 C = mat3( 3.2404542, -1.5371385, -0.4985314, -0.9692660, 1.8760108, 0.0415560, 0.0556434, -0.2040259, 1.0572252) / 2323.8695; const float N_AIR = 1.0; const float N_GLASS = 2.0; const float MAX_T = 10000.0; uniform sampler2D u_S0; uniform vec2 u_r; uniform vec3 u_obs[${f}]; uniform vec2 u_Ts; uniform vec2 u_Ti; uniform float u_st; uniform float u_t; uniform float u_s; uniform vec2 u_sxy; uniform vec3 u_eye; uniform float u_fov; uniform vec3 u_s_c[${X}]; uniform float u_s_r[${X}]; uniform vec4 u_ls[${C}]; in vec2 v_tex; out vec4 o_col; float PHI = 1.61803398; float PI = 3.14159265; float GN(in vec2 xy, in float seed) { return fract(tan(distance(xy * PHI, xy) * seed) * xy.x); } float N(in vec2 xy, inout float seed) { xy += u_sxy; xy *= u_r; seed = GN(xy, seed); return GN(xy, seed); } vec2 N2(in vec2 xy, inout float seed) { return vec2(N(xy, seed), N(xy, seed)); } vec3 col(in float S[${f}]) { vec3 T[${f}]; for (int f = 0; f < ${f}; f++) { T[f] = S[f] * u_obs[f]; } vec3 res = vec3(0.0); for (int f = 0; f < ${f} - 1; f++) { res += T[f] + T[f + 1]; } return res * C; } float cbp(float c, float w, float x) { x = abs(x - c); if (x > w) { return 0.0; } x /= w; return 1.0 - x * x * (3.0 - 2.0 * x); } vec2 sr(in vec3 ro, in vec3 rd, in vec3 ce, in float ra) { vec3 oc = ro - ce; float b = dot(oc, rd); float c = dot(oc, oc) - ra * ra; float h = b * b - c; if (h < 0.0) { return vec2(-1.0); } h = sqrt(h); return vec2(-b - h, -b + h); } vec3 sn(in vec3 p, in vec3 ce) { return normalize(p - ce); } vec2 gv() { return (u_Ti + v_tex) / u_Ts; } vec2 gm() { float a = float(0.75); float sd = float(0.85); vec2 ideal; if (u_r.x > u_r.y * a) { ideal = vec2(u_r.y * a, u_r.y); } else { ideal = vec2(u_r.x, u_r.x / a); } ideal *= sd; return (u_r - ideal) / 2.0; } void rord(in vec2 tex, out vec3 ro, out vec3 rd, out vec2 res) { ro = u_eye; res = u_r; float fov = u_fov; float scale = min(u_r.x, u_r.y); vec2 disp = tex * vec2(u_r.x / scale, u_r.y / scale); disp -= vec2(u_r.x / scale, u_r.y / scale) * 0.5; float z = 1.0 / tan(fov * 0.5); rd = vec3(disp, z); } float pr(in vec3 ro, in vec3 rd, in vec4 p) { return -(dot(ro, p.xyz) + p.w) / dot(rd, p.xyz); } vec3 pn(in vec4 p) { return p.xyz; } `,wt=`#version 300 es\nprecision highp float; ${pt} float ss(in vec2 v) { if (v.x >= 0.0) { return v.x; } else { return v.y; } } float its(in vec3 ro, in vec3 rd, in vec3 lpt, out vec3 pt, out vec3 norm, out float mat) { float mt = MAX_T; for (int i = 0; i < ${X}; i++) { float r = u_s_r[i]; if (r < 0.0) { break; } vec3 ce = u_s_c[i]; float it = ss(sr(ro, rd, ce, r)); if (it > 0.0 && it < mt) { mt = it; norm = sn(lpt, ce); mat = 1.0 + float(i); } } for (int i = 0; i < ${C}; i++) { vec4 l = u_ls[i]; if (length(l) == 0.0) { break; } float it = pr(ro, rd, l); if (it > 0.0 && it < mt) { mt = it; norm = pn(l); mat = -1.0; } } pt = ro + rd * mt; return mt; } float gior(in vec3 pt) { for (int i = ${X} - 1; i >= 0; i--) { float r = u_s_r[i]; if (r < 0.0) { break; } vec3 ce = u_s_c[i]; if (length(ce - pt) < r) { return N_GLASS + float(i); } } return N_AIR; } float cast_ray(in vec3 ro, in vec3 rd, in float nm, inout vec3 lpt) { float ior = N_AIR; for (int i = 0; i < 8; i++) { rd = normalize(rd); ro = ro + float(${E}) * rd; float mat; vec3 norm; vec3 pt; float d = its(ro, rd, lpt, pt, norm, mat); if (d >= MAX_T || d < 0.0) { return 0.0; } if (mat < 0.0) { float A = max(0.0, dot(norm, rd)); float c = 1.0 * float(i) / float(8); float lt = mat / -float(${C} - 1); float light_c = A + mix(-float(${P}), float(${P}), lt); return cbp(light_c, float(${S}), nm + float(${z}) + c) * A; } ro = pt; lpt = pt; float nior = gior(pt + 0.001 * rd); vec3 nrd = refract(rd, norm, ior / nior); if (dot(nrd, nrd) != 0.0) { rd = nrd; } ro = ro + float(${R}) * norm; ior = nior; } return 0.0; } void main(void) { float S[${f}]; for (int c = 0; c < ${f}; c++) { S[c] = 0.0; } vec3 ro; vec3 rd; vec2 res; vec2 tex = gv(); vec2 px = tex * u_r; vec2 margin = gm(); vec2 to_edge = vec2(min(u_r.x - px.x, px.x), min(u_r.y - px.y, px.y)) - margin; if (to_edge.x < 0.0 || to_edge.y < 0.0) { o_col = vec4(100.0, 100.0, 100.0, 1.0); return; } rord(tex, ro, rd, res); float seed = u_s; int casts = 4; float w = float(${M}) / float(casts); vec3 lp = vec3(0.0); for (int i = 0; i < casts; i++) { vec2 aa = N2(tex, seed) / (u_r * u_Ts); vec3 trd = normalize(rd + vec3(aa, 0.0)); float nm = N(tex, seed); float A = cast_ray(ro, trd, nm, lp) * w; for (int c = 0; c < ${f}; c++) { float t = (float(c) + 0.5) / float(${f}); S[c] += cbp(${v?"1.0 - nm":"nm"}, float(${L}), t) * A; } } vec4 l_col = texture(u_S0, v_tex); vec4 n_col = vec4(col(S), 1.0); float t = 1.0 / u_st; o_col = l_col * (1.0 - t) + max(n_col * t, 0.0); }\n`;function Tt(t,e,r,n,i,o){t.fillStyle="white",t.fillRect(0,0,e,r),t.font="9pt Arial";const s=new ut(Math.sqrt(3)/2,.5).normalize(),l=new ut(0,-1).normalize(),a=new ut(-Math.sqrt(3)/2,.5).normalize(),u=r/4,c=new ut(e/2,r/2);let f=t=>s.mul(t.x).add(l.mul(t.y)).add(a.mul(t.z)).mul(u).add(c);const h=f(new ht(0,0,0)),d=[f(new ht(1.1,0,0)),f(new ht(0,1.1,0)),f(new ht(0,0,1.1))],x=["X","Y","Z"];for(let e=0;e<d.length;e++){const r=d[e],n=x[e];t.beginPath(),t.strokeStyle="#aaa",t.moveTo(r.x,r.y),t.lineTo(h.x,h.y),t.stroke(),t.fillStyle="#777",t.textBaseline="middle";const i=h.lerpT(r,1.15);let o=t.measureText(n).width;t.fillText(n,i.x-o/2,i.y)}const _=f(xt);t.fillStyle="red",t.fillRect(_.x-2,_.y-2,4,4);let m=t.measureText(xt.toString()).width;t.textBaseline="top",t.fillText(xt.toString(),_.x-m/2,_.y+6);const v=Math.min(o.x,o.y),y=o.div(v).mul(.5),p=1/Math.tan(.5*O),w=new ht(y.x,y.y,p).normalize(),T=Math.abs(xt.z/w.z),g=f(new ht(w.x,w.y,0).mul(T)),A=f(new ht(-w.x,w.y,0).mul(T)),b=f(new ht(-w.x,-w.y,0).mul(T)),E=f(new ht(w.x,-w.y,0).mul(T));t.fillStyle="#ee7777";for(const e of[g,A,b,E])t.fillRect(e.x-2,e.y-2,4,4);let R=!0;t.beginPath(),t.strokeStyle="#ee9999",t.lineWidth=1;for(const e of[g,A,b,E])R?t.moveTo(e.x,e.y):t.lineTo(e.x,e.y),R=!1;t.closePath(),t.stroke();for(let e=0;e<n.length;e++){const{center:r,radius:i}=n[e],o=f(r),s=i*u;t.beginPath(),t.strokeStyle="black",t.arc(o.x,o.y,s,0,2*Math.PI),t.stroke()}for(let e=0;e<i.length;e++){const{norm:r}=i[e],n=f(r.mul(1.1));t.fillStyle="blue",t.fillRect(n.x-2,n.y-2,4,4);const o=r.toString(),s=t.measureText(o);m=s.width;const l=s.fontBoundingBoxAscent+s.fontBoundingBoxDescent;t.fillStyle="#ffffff99",t.fillRect(n.x-m/2,n.y+3,m,l),t.textBaseline="top",t.fillStyle="blue",t.fillText(o,n.x-m/2,n.y+6)}t.textBaseline="top",t.fillStyle="red",t.fillText("EYE",10,4),t.fillRect(4,7,4,4),t.fillStyle="blue",t.fillText("LIGHTS",10,18),t.fillRect(4,21,4,4),t.fillStyle="black",t.fillText("OPTICS",10,32),t.fillRect(4,35,4,4),t.fillStyle="#ee9999",t.fillText("VIEWPORT",10,46),t.fillRect(4,49,4,4)}function gt(t,e,r){const n=it(t,e,r,new ut,new ut(1,1)),i=new rt(t,e,r),o=i.add();return{spectralShader:nt(t,wt,["u_r","u_obs","u_S0","u_st","u_t","u_s","u_sxy","u_s_r","u_s_c","u_eye","u_fov","u_ls","u_Ts","u_Ti"],n,!0),displayShader:nt(t,yt,["u_r","u_S0"],n,!0),bufferPool:i,buffer:o,width:e,height:r}}function At(t,e,r,n,i,o){const l=i.map((t=>[t.center.x,t.center.y,t.center.z])).flat(),a=i.map((t=>t.radius));a.length<X&&a.push(-1);const u=o.map((t=>[t.norm.x,t.norm.y,t.norm.z,t.offset])).flat();for(;u.length<4*C;)u.push(0);ot(t,e,r.read(),r.write(),(()=>{t.uniform3fv(e.u_obs,dt),t.uniform1f(e.u_st,n),t.uniform1f(e.u_t,n/vt),t.uniform1f(e.u_s,s(-1,1)),t.uniform2f(e.u_sxy,s(-1,1),s(-1,1)),t.uniform3fv(e.u_s_c,l),t.uniform1fv(e.u_s_r,a),t.uniform3f(e.u_eye,xt.x,xt.y,xt.z),t.uniform1f(e.u_fov,O),t.uniform4fv(e.u_ls,u),t.uniform2f(e.u_Ts,W[1],W[0]),t.uniform2f(e.u_Ti,V[1],W[0]-V[0]-1)}))}function bt(t,e,r,n,i){t.canvas.width=e.width,t.canvas.height=e.height,At(t,e.spectralShader,e.buffer,r,n,i),e.buffer.flip(),ot(t,e.displayShader,e.buffer.read(),null,null)}class Et{constructor(t,e,r=3,n=[]){this.gen=t,this.rank=e,this.N=r,this.samples=n}sample(){let t=Number.MAX_VALUE,e=null;for(let r=0;r<this.N;r++){const r=this.gen(),n=this.samples.map((t=>this.rank(t,r))).reduce(((t,e)=>t+e),0);n<t&&(t=n,e=r)}return this.samples.push(e),e}}class Rt{constructor(t,e,r=[]){this.gen=t,this.filter=e,this.samples=r}sample(){let t=!1,e=null;for(;!t;)e=this.gen(),t=this.filter(e)&&this.samples.every((t=>this.filter(e,t)));return this.samples.push(e),e}}function St(){let n=window.innerWidth,i=window.innerHeight;new ut(0,0);const o=new ut(n,i).floor(),[a,u]=[o.x,o.y],c=ct(a,u,"display"),f=K(c);if(!f)return;const h=gt(f,a*r,u*r);let d=null,x=null;d=ct(H,H,"scene"),d.style.position="absolute",d.style.top="0",d.style.left="0",x=d.getContext("2d");let _=t("v")??!1;const m=()=>{d.style.zIndex=_?"10":"-10"};m();new ht(0,1,0).cross(xt.normalize());const v=new ht(1,1.5,q),y=[{radius:1,center:(t=>{let e=s(.2,1),r=s(.2,1);const n=1*e/30*Math.PI*(l()?-1:1),i=1*r/15*Math.PI*(l()?-1:1);return new ht(0,0,t).rotateY(n).rotateX(i)})(.001)}],p=new Et((()=>{const t=y.length/(X-1),e=lt(I,N,(r=t,Math.pow(r,.25)));var r;const n=(t=>{let e=s(),r=s();const n=e*Math.PI*2,i=r*Math.PI*2;return new ht(0,0,t).rotateY(n).rotateX(i)})(lt(0,$-e,Math.sqrt(s()))).mul3(v);return{center:n,radius:e}}),((t,e)=>{const r=t.center.x-e.center.x,n=t.center.y-e.center.y;return-1*(r*r+n*n)}),Math.floor(s(6,10)),[]);for(;y.length<X;)y.push(p.sample());const w=[xt.normalize()],T=new Rt((()=>new ht(0,0,1).rotateX(s(2*Math.PI)).rotateY(s(2*Math.PI))),((t,e)=>null==e?t.z<.49:t.dot(e)<.8),w),g=Array(C).fill(null).map((()=>({norm:T.sample().rotateX(0),offset:-50})));Tt(x,H,H,y,g,o);let A=1;!function t(){A>=vt+1?document.title="FULL_SPECTRUM":(bt(f,h,A,y,g),A++,document.title=`FULL_SPECTRUM (${at(A/vt*100,1)}%)`,window.requestAnimationFrame(t))}(),window.addEventListener("keydown",(t=>{if("v"==t.key)_=!_,m();else if("d"==t.key){const t=V[0].toString().padStart(2,"0"),r=V[1].toString().padStart(2,"0");ft(c,`FULL_SPECTRUM_${e}_${t}x${r}`)}}))}St();