0x85582125…5972sent to0x96a83b48…d253·#22,583,587·view on Etherscan
(e,t){const n=e-t;return Math.abs(n)<this.epsilon||n<0?-1:1}insertRec(e,t,n){return e?((0===e.axis?this.compareCoord(t.point.x,e.point.point.x):this.compareCoord(t.point.y,e.point.point.y))<0?e.left=this.insertRec(e.left,t,n+1):e.right=this.insertRec(e.right,t,n+1),e):{point:t,axis:n%2,left:null,right:null}}remove(e){this.wasRemoved=!1,this.root=this.removeRec(this.root,e,0),this.wasRemoved&&this.count--}removeRec(e,t,n){if(!e)return null;const i=e.axis;if(this.equals(e.point,t)){if(this.wasRemoved=!0,e.right){const t=this.findMin(e.right,i,n+1);e.point=t.point,e.right=this.removeRec(e.right,t.point,n+1)}else{if(!e.left)return null;{const t=this.findMin(e.left,i,n+1);e.point=t.point,e.right=this.removeRec(e.left,t.point,n+1),e.left=null}}return e}{let l;l=0===i?this.compareCoord(t.point.x,e.point.point.x):this.compareCoord(t.point.y,e.point.point.y),l<0?e.left=this.removeRec(e.left,t,n+1):e.right=this.removeRec(e.right,t,n+1)}return e}findMin(e,t,n){if(!e)throw Error("Empty subtree when finding min.");if(e.axis===t)return e.left?this.findMin(e.left,t,n+1):e;const i=e.left?this.findMin(e.left,t,n+1):e,l=e.right?this.findMin(e.right,t,n+1):e;let a=e;return this.compareAxis(i.point,a.point,t)<0&&(a=i),this.compareAxis(l.point,a.point,t)<0&&(a=l),a}findNearest(e){return this.root?this.findNearestRec(this.root,e,this.root.point,0):null}findNearestRec(e,t,n,i){if(!e)return n;let l=n;this.distanceSq(e.point,t)<this.distanceSq(l,t)&&(l=e.point);const a=0===e.axis?t.point.x-e.point.point.x:t.point.y-e.point.point.y;let s,o;return a<-this.epsilon?(s=e.left,o=e.right):a>this.epsilon?(s=e.right,o=e.left):(s=e.left,o=e.right),l=this.findNearestRec(s,t,l,i+1),a**2<this.distanceSq(l,t)&&(l=this.findNearestRec(o,t,l,i+1)),l}findKNearest(e,t){if(!this.root)return[];const n=new Oi(t,(e=>e.dist));return this.findKNearestRec(this.root,e,t,n),n.toArray().map((e=>e.point))}getTotalNodes(){return this.count}*pointsWithinDistanceGenerator(e,t){const n=t*t;yield*this.pointsWithinDistanceRecGen(this.root,e,n)}*pointsWithinDistanceRecGen(e,t,n,i=0){if(!e)return;this.distanceSq(e.point,t)<=n&&(yield e.point);const l=0===e.axis?t.point.x-e.point.point.x:t.point.y-e.point.point.y;let a,s;l<-this.epsilon?(a=e.left,s=e.right):(a=e.right,s=e.left),yield*this.pointsWithinDistanceRecGen(a,t,n,i+1),l**2<=n&&(yield*this.pointsWithinDistanceRecGen(s,t,n,i+1))}findKNearestRec(e,t,n,i,l=0){if(!e)return;const a=e.axis,s=this.distanceSq(e.point,t);if(i.size()<n)i.push({dist:s,point:e.point});else{const t=i.peek();t&&s<t.dist&&i.replaceTop({dist:s,point:e.point})}const o=0===a?t.point.x-e.point.point.x:t.point.y-e.point.point.y;let r,c;o<-this.epsilon?(r=e.left,c=e.right):o>this.epsilon?(r=e.right,c=e.left):(r=e.left,c=e.right),this.findKNearestRec(r,t,n,i,l+1);const d=i.peek();d&&o**2<d.dist&&this.findKNearestRec(c,t,n,i,l+1)}distanceSq(e,t){const n=e.point.x-t.point.x,i=e.point.y-t.point.y;return n*n+i*i}compareAxis(e,t,n){const i=0===n?e.point.x-t.point.x:e.point.y-t.point.y;return Math.abs(i)<this.epsilon?0:i}equals(e,t){const n=e.point.x-t.point.x,i=e.point.y-t.point.y;return n*n+i*i<this.epsilon*this.epsilon}}class ul{opts;kTree=new dl;activeList=[];random;epsilon=b;maxDist;constructor(e){this.opts=e,this.random=e.random||J,this.maxDist=e.maxDist||1}*generate(){const{bounds:e,noiseField:t,initialCount:n=1,k:i=50}=this.opts;if(this.opts.seedPoints&&this.opts.seedPoints.length>0)for(let e of this.opts.seedPoints){const n={point:e,minDist:t(e.x,e.y)};this.placePoint(n),this.activeList.push(n),yield n}else for(let i=0;i<n;i++){const n=this.random.num(e.topLeft[0],e.bottomRight[0]),i=this.random.num(e.topLeft[1],e.bottomRight[1]),l=t(n,i),a={point:new zt(n,i),minDist:l};this.placePoint(a),this.activeList.push(a),yield a}for(;this.activeList.length>0;){const n=0,l=this.activeList[n];let a=!1;for(let n=1;n<i;n++){const s=l.minDist*(.5+i/n),o=this.random.dec()*Math.PI*2,r=l.point.x+Math.cos(o)*s,c=l.point.y+Math.sin(o)*s;if(r<e.topLeft[0]||r>e.bottomRight[0]||c<e.topLeft[1]||c>e.bottomRight[1])continue;const d=t(r,c),u={point:new zt(r,c),minDist:d};if(this.canPlace(u)){this.placePoint(u),this.activeList.push(u),yield u,a=!0;break}}a||this.activeList.splice(n,1)}}canPlace(e){for(let t of this.kTree.pointsWithinDistanceGenerator(e,this.maxDist+b))if(t.point.distanceTo(e.point)+this.epsilon<Math.max(t.minDist,e.minDist))return!1;return!0}placePoint(e){this.kTree.insert(e)}}const hl=function(e,t,n){const i=1/t,l=1/n;return Math.min(4,((3-i)*i**2*e+l**3)/(i**3*e+(3-l)*l**2))},ml=(e,t,n,i,l)=>Math.min(4,(2+Math.sqrt(2)*(e-n/16)*(n-e/16)*(t-i))/(1.5*l*(2+(Math.sqrt(5)-1)*t+(3-Math.sqrt(5))*i))),pl=(e,t)=>{const n=Math.sin(e.theta),i=Math.cos(e.theta),l=Math.sin(t.phi),a=Math.cos(t.phi),s=t.leftY,o=e.rightY,r=ml(n,i,l,a,s),c=ml(l,a,n,i,o);e.rightX=e.x+(e.deltaX*i-e.deltaY*n)*r,e.rightY=e.y+(e.deltaY*i+e.deltaX*n)*r,t.leftX=t.x-(e.deltaX*a+e.deltaY*l)*c,t.leftY=t.y-(e.deltaY*a-e.deltaX*l)*c},gl=(e,{tension:t=1,cyclic:n=!1}={})=>{const i=((e,t=1,n=!1)=>{const i=e.map((({x:e,y:n})=>((e,t,n)=>({x:e,y:t,leftY:n,rightY:n,leftX:n,rightX:n,deltaX:0,deltaY:0,delta:0,theta:0,phi:0,psi:0}))(e,n,t))),l=i[0],a=i[i.length-1];for(let e=0;e<i.length;e++)i[e].next=i[e+1]??l,i[e].prev=i[e-1]??a;if(((e,t)=>{const n=t?e.length:e.length-1;for(let t=0;t<n;t++){const n=e[t],i=e[t+1]??e[0];n.deltaX=i.x-n.x,n.deltaY=i.y-n.y,n.delta=Math.hypot(n.deltaX,n.deltaY)}})(i,n),2===e.length&&!n)return((e,t)=>{let n=1/(3*e.rightY);e.rightX=e.x+e.deltaX*n,e.rightY=e.y+e.deltaY*n,n=1/(3*t.leftY),t.leftX=t.x-e.deltaX*n,t.leftY=t.y-e.deltaY*n})(l,a),i;((e,t)=>{const[n,i]=t?[0,e.length]:[1,e.length-1];for(let t=n;t<i;t++){const n=e[t],i=n.prev,l=i.deltaY/i.delta,a=i.deltaX/i.delta;n.psi=Math.atan2(n.deltaY*a-n.deltaX*l,n.deltaX*a+n.deltaY*l)}})(i,n),function(e,t){const n=[],i=[],l=[],a=e[0],s=e[1],o=e[e.length-1],r=t?e.length+1:e.length;if(t)n[0]=0,l[0]=0,i[0]=1;else{const e=a.next,t=a.rightX,o=Math.abs(e.leftY),r=Math.abs(a.rightY);n[0]=hl(t,r,o),l[0]=-s.psi*n[0],i[0]=0}for(let s=1;s<r;s++){const c=e[s]??a,d=c.next,u=c.prev,h=s===r-1;if(!t&&h){const e=c.leftX,t=Math.abs(c.leftY),i=Math.abs(u.rightY),a=hl(e,t,i);o.theta=-l[r-2]*a/(1-a*n[r-2]);break}{let e=1/(3*Math.abs(u.rightY)-1),o=c.delta*(3-1/Math.abs(u.rightY)),m=1/(3*Math.abs(d.leftY)-1),p=u.delta*(3-1/Math.abs(d.leftY));const g=1-n[s-1]*e;o*=g;const b=Math.abs(c.leftY),f=Math.abs(c.rightY);b<f?o*=(b/f)**2:p*=(f/b)**2;let x=p/(p+o);n[s]=x*m;let Z=-d.psi*n[s];if(x=(1-x)/g,Z-=c.psi*x,x*=e,l[s]=Z-l[s-1]*x,i[s]=-i[s-1]*x,t&&h){let e=0,t=1;for(let a=s-1;a>=0;a--){const s=0===a?r-1:a;e=l[s]-e*n[s],t=i[s]-t*n[s]}e/=1-t,a.theta=e,l[0]=e;for(let t=1;t<r-1;t++)l[t]=l[t]+e*i[t];break}}}for(let t=r-2;t>=0;t-=1)e[t].theta=l[t]-e[t].next.theta*n[t]}(i,n),(e=>{for(let t=0;t<e.length;t++){const n=e[t];n.phi=-n.psi-n.theta}})(i);const s=n?i.length:i.length-1;for(let e=0;e<s;e++)pl(i[e],i[e].next);return i})(e,t,n),l=[],a=n?i.length:i.length-1;for(let e=0;e<a;e++){const t=i[e];l.push({startControl:{x:t.rightX,y:t.rightY},endControl:{x:t.next.leftX,y:t.next.leftY},point:{x:t.next.x,y:t.next.y}})}return l};function bl(e,t,n=!1,i=.01){const l=[],a=e.length;if(a<2)return l;const s=n?a:a-1;let o=null;for(let n=1;n<=s;n++){const s=n%a,r=e[(n-1)%a].point,c=e[s].startControl,d=e[s].endControl,u=e[s].point;let h=0;for(;h<=1;){const e=1-h,n={x:e**3*r.x+3*e**2*h*c.x+3*e*h**2*d.x+h**3*u.x,y:e**3*r.y+3*e**2*h*c.y+3*e*h**2*d.y+h**3*u.y};if(o){const e=n.x-o.x,i=n.y-o.y;e*e+i*i>=t*t&&(l.push(n),o=n)}else l.push(n),o=n;h+=i}const m={x:u.x,y:u.y};!o||o.x===m.x&&o.y===m.y||(l.push(m),o=m)}if(!n){const t=e[a-1].point,n=l[l.length-1];n.x===t.x&&n.y===t.y||l.push(t)}return l}let fl,xl,Zl,yl,Gl,Wl=[],vl=[],Ll=[],Sl=[],Xl=new class{cells=new Map;polygons=new Map;polygonMeta=new Map;nextPolygonId=0;cellSize;constructor(e,t){this.cellSize=e,t&&this.addPolygons(t)}getCellIndex(e,t){return`${f(e)},${f(t)}`}clear(){this.cells.clear(),this.polygons.clear(),this.polygonMeta.clear()}getCellTestVertices(e,t){let{cellSize:n}=this;return[new zt(e*n,t*n),new zt((e+1)*n,t*n),new zt((e+1)*n,(t+1)*n),new zt(e*n,(t+1)*n)]}addPolygons(e){e.forEach((e=>this.addPolygon(e.verts,e.meta)))}getPolygonsAtPoint(e){let{cellSize:t}=this,n=f(e[0]/t),i=f(e[1]/t);const l=this.getCellIndex(n,i);let a=new Set;return this.cells.has(l)&&Array.from(this.cells.get(l)).map((t=>{Tn(this.polygons.get(t).map((e=>(new zt).fromArray(e))),new zt(e[0],e[1]))&&a.add(t)})),Array.from(a).map((e=>({verts:this.polygons.get(e),meta:this.polygonMeta.get(e)})))}addPolygon(e,t){let{cellSize:n}=this;const i=this.nextPolygonId++;this.polygons.set(i,e),this.polygonMeta.set(i,t);let l=e.map((e=>(new zt).fromArray(e))),a=new nn;a.expands(l);const s=f(a.minX/n),o=x(a.maxX/n)-1,r=f(a.minY/n),c=x(a.maxY/n)-1;for(let e=s;e<=o;e++)for(let t=r;t<=c;t++){const n=this.getCellIndex(e,t),a=this.getCellTestVertices(e,t);if(a.some((e=>Tn(l,e))))this.cells.has(n)||this.cells.set(n,new Set),this.cells.get(n).add(i);else for(let e=0;e<a.length;e++)if(Hn([a[e],a[(e+1)%a.length]],l)){this.cells.has(n)||this.cells.set(n,new Set),this.cells.get(n).add(i);break}}return i}checkIntersections(e){let{cellSize:t}=this,n=e.map((e=>(new zt).fromArray(e))),i=new nn;i.expands(n);const l=f(i.minX/t),a=x(i.maxX/t)-1,s=f(i.minY/t),o=x(i.maxY/t)-1;let r=new Set;for(let e=l;e<=a;e++)for(let t=s;t<=o;t++){const i=this.getCellIndex(e,t),l=this.getCellTestVertices(e,t);this.cells.has(i)&&this.cells.get(i).forEach((e=>{if(l.some((e=>Tn(n,e))))r.add(e);else for(let t=0;t<l.length;t++)if(Hn([l[t],l[(t+1)%l.length]],n)){r.add(e);break}}))}return Array.from(r).map((e=>({verts:this.polygons.get(e),meta:this.polygonMeta.get(e)})))}getAllPolygons(){return Array.from(this.polygons).map((([e,t])=>({verts:t,meta:this.polygonMeta.get(e)})))}}(10),Cl=[],Vl=[[function*(){hn()}],[function*(){let e=ve.bg[0][0]>=.5,t=e?1:1.008,n=e?1:1.02;si=si.length?si:he.filter((e=>e!==ve)).map((e=>[...e.accent,...e.base,...e.line])).flat().map((e=>(e[0]*=n,e[1]*=t,e))),[...ve.accent,...ve.base,...ve.line].forEach((e=>{e[0]*=n,e[1]*=t}));let i=[...ve.accent,...ve.base,...ve.line];li=i,ai=[...ve.base].sort(((e,t)=>t[0]-e[0])),li=[...li].sort(((e,t)=>t[2]-e[2])),An([...li]),An([...ai])}],[function*(){let t=w?e.LinearFilter:e.NearestFilter,n={anisotropy:V,colorSpace:e.LinearDisplayP3ColorSpace,minFilter:t,magFilter:t,type:e.FloatType};Xt=new St(B,Q,{stencilBuffer:!1,depthBuffer:!1}),Ct={paperTexture:{target:new e.WebGLRenderTarget(B,Q,{...n,format:e.RedFormat,internalFormat:"R32F"}),pass:()=>{let t=new e.ShaderMaterial({uniforms:{resolution:{value:new e.Vector2(B,Q)},noiseOffset:{value:new e.Vector2(We[0],We[1])},...ce()},colorWrite:!0,depthWrite:!1,depthTest:!1,glslVersion:e.GLSL3,vertexShader:ie,fragmentShader:`\n precision highp float;\n precision highp int;\n \n uniform highp sampler2D tTex;\n uniform vec2 resolution;\n uniform vec2 uTileOffset;\n uniform vec2 uTileSize;\n uniform vec3 backgroundColor;\n uniform vec3 lineColor;\n uniform vec2 noiseOffset;\n\n ${ee}\n ${te}\n\n varying vec2 vUv;\n out vec4 outColor;\n\n #include <packing>\n\n ${ne}\n\n vec4 render(vec2 uv) {\n\n float noiseTex1 = fbm(uv - noiseOffset, 5, 300., 0.9) - 0.5;\n float noiseTex2 = fbm(uv - noiseOffset, 3, 400., 0.9) - 0.5;\n float texCombined = step(0.001, -(noiseTex1 * noiseTex2)) * .05;\n\n float noiseTexDark1 = fbm(uv + noiseOffset + 1., 5, 280., 0.9) - 0.5;\n float noiseTexDark2 = fbm(uv + noiseOffset + 1., 3, 300., 0.9) - 0.5;\n float texDarkCombined = step(0.0001, -(noiseTexDark1 * noiseTexDark2)) * .05;\n\n float smoothNoise1 = smoothstep(0., 0.6, fbm(uv, 3, 420., 0.9)) * 0.03;\n\n // vec3 lchColor = vec3(0., 0.5, 0.5);\n float result;\n result += texCombined;\n result -= texDarkCombined;\n result += smoothNoise1;\n \n // vec3 colorRGB = OKLCHtoP3LRGB(lchColor);\n // float canvasTexture = fbm(uv, 6, 120., 0.7);\n return vec4(vec3(result), 1.);\n }\n\n \n\n void main() {\n // A pseudo-random distribution for multi-sample\n const vec2 H2 = vec2(0.56984029, 0.75487766);\n // We do sub-pixel offsets relative to tile size, \n // because each tile is scaled to fill the entire local canvas\n vec2 px = 1.0 / resolution.xy;\n px *= 1.25;\n\n // We'll accumulate color across multiple samples\n const float samples = 6.0;\n vec4 sumColour = vec4(0.0);\n \n // Vary the random offset per pixel\n vec2 d0 = vec2(randomNonDet(vUv), randomNonDet(vUv + 1.0));\n\n for (float i = 0.0; i < samples; i++) {\n vec2 d = fract(i * H2 + d0) - 0.5;\n // localCoord in [0..1] in the local canvas\n vec2 sampleCoord = vUv + d * px;\n\n // Now map that to the large “full” coordinate space \n // subregion given by uTileOffset..uTileOffset+uTileSize\n vec2 screenCoord = uTileOffset + sampleCoord * uTileSize;\n\n // Next convert to [0..1] over the entire original geometry\n vec2 globalUV = screenCoord / resolution;\n\n vec4 sampleColor = render(globalUV);\n sumColour += sampleColor;\n }\n\n vec4 finalColor = clamp(sumColour / samples, 0.0, 1.0);\n outColor = finalColor;\n }\n `});re(t),Vt.material=t,X.setRenderTarget(Ct.paperTexture.target),Vt.render(X)}},displacementMap:{target:new e.WebGLRenderTarget(B,Q,{...n,format:e.RGFormat,internalFormat:"RG32F"}),pass:()=>{let e=ft();re(e),Vt.material=e,X.setRenderTarget(Ct.displacementMap.target),Vt.render(X)}},displacementMapWarped:{target:new e.WebGLRenderTarget(B,Q,{...n,format:e.RGFormat,internalFormat:"RG32F"}),pass:()=>{let e=ft();re(e),e.uniforms.uWarpEnabled.value=!0,Vt.material=e,X.setRenderTarget(Ct.displacementMapWarped.target),Vt.render(X)}},polyEdgeDistance:{target:new e.WebGLRenderTarget(B,Q,{...n,format:e.RedFormat,internalFormat:"R32F"}),skipSetup:!0}};let i=function*(){for(let e of Object.keys(Ct)){const t=Ct[e];t.skipSetup||t.pass&&t.pass()}return X.shadowMap.enabled=!0,void X.setRenderTarget(null)}();for(;!i.next().done;)yield}],[function*(){let e=yt();Vt.material=e;for(let t of Object.keys(Ct)){if(!Ct[t].debug)continue;let n=Ct[t].target.texture;e.uniforms.tTex.value=n,X.setRenderTarget(null),Vt.render(X),ta(),yield}}],[function*(){let t=(n=Ct.paperTexture.target.texture,new e.ShaderMaterial({uniforms:{grid:{value:{...ze}},...ce(),tWarpTex:{value:Ct.displacementMap.target.texture},resolution:{value:new e.Vector2(B,Q)},coordsResolution:{value:new e.Vector2(Y,P)},noiseOffset:{value:new e.Vector2(0,0)},tPaperTexture:{value:n},backgroundColor:{value:new e.Vector3(0,0,0)},lineColor:{value:new e.Vector3(0,0,0)},uGridStrength:{value:.3}},colorWrite:!0,depthWrite:!1,depthTest:!1,glslVersion:e.GLSL3,vertexShader:ie,fragmentShader:`\n precision highp float;\n\t\t\tprecision highp int;\n \n // uniform highp sampler2D tTex;\n uniform vec2 resolution;\n uniform vec2 uTileOffset;\n uniform vec2 uTileSize;\n uniform vec2 coordsResolution;\n uniform vec3 backgroundColor;\n uniform vec3 lineColor;\n uniform vec2 noiseOffset;\n uniform float uGridStrength;\n uniform highp sampler2D tPaperTexture;\n uniform highp sampler2D tWarpTex;\n\n struct Grid {\n float countX;\n float countY;\n float marginX;\n float marginY;\n float w;\n float h;\n float scale;\n };\n uniform Grid grid;\n\n ${ee}\n ${Dt}\n ${te}\n \n float drawGridLines(vec2 uv, float lineWeight, float gridScale) {\n vec2 scale = resolution / coordsResolution;\n // This should be the desired line width in pixels\n float lineWeightNoise = snoise2D(uv * 200.f) * .09f;\n float gridLineWeight = (lineWeight + lineWeightNoise) * scale.y; // Width of the grid lines in pixels\n\n vec2 offset = vec2(grid.marginX, grid.marginY) * scale; // Applying scale to margins\n\n // Compute UVs for grid lines based on actual screen resolution and grid scaling\n vec2 gridUV = (uv * resolution - offset);\n\n // Convert grid dimensions from whatever space they are in to pixel space directly\n float gridWidthInPixelsX = grid.w * (resolution.x / coordsResolution.x) * 1.;\n float gridWidthInPixelsY = grid.h * (resolution.y / coordsResolution.y) * 1.;\n\n // Calculate the distance to the nearest grid line in pixels\n float lineDistX = min(mod(gridUV.x, gridWidthInPixelsX / gridScale), gridWidthInPixelsX - mod(gridUV.x, gridWidthInPixelsX / gridScale));\n float lineDistY = min(mod(gridUV.y, gridWidthInPixelsY / gridScale), gridWidthInPixelsY - mod(gridUV.y, gridWidthInPixelsY / gridScale));\n float lineDist = min(lineDistX, lineDistY);\n\n // Use smoothstep to create anti-aliased lines with a specified pixel width\n float lineFactor = 1.0 - smoothstep(gridLineWeight - 0.1, gridLineWeight + 0.1, lineDist);\n\n return lineFactor;\n }\n\n float drawGridBlocks(vec2 uv, float gridScale ) {\n vec2 scale = resolution / coordsResolution;\n vec2 offset = vec2(grid.marginX, grid.marginY) * scale; // Applying scale to margins\n vec2 gridUV = (uv * resolution - offset); // Apply resolution scaling to UV, then subtract offset\n\n float tileX = floor(gridUV.x / (grid.w * scale.x));\n float tileY = floor(gridUV.y / (grid.h * scale.y));\n\n vec2 centerUV = (vec2(tileX, tileY)) * vec2(grid.w, grid.h) / resolution;\n\n float noiseValue = clamp(fbm(centerUV, 3, 300., 0.5) + .5, 0.0, 1.); // Adjust for correct scaling if necessary\n\n return noiseValue;\n\n // float checker = mod(tileX + tileY, 2.0);\n \n // return checker == 0.0;\n }\n\n ${gt}\n\n varying vec2 vUv;\n out vec4 outColor;\n\n #include <packing>\n\n ${ne}\n ${Ut}\n\n vec4 render(vec2 uv, vec2 texUv, vec2 msaaOffset) {\n\n // vec2 uvOffset = lookupWarpSample(uv).xy;\n\n // vec2 offsetUV = uv + uvOffset;\n vec2 offsetUV = uv;\n\n float gridNoise = fbm(uv, 3, 10., 0.9);\n float gridNoise2 = fbm(uv + 2., 3, 600., 0.9);\n\n float tileScaleFactor = resolution.x / uTileSize.x;\n\n // float gridFactor = clamp(0., .12, drawGridLines(uv, 38.));\n float aspectRatio = resolution.x / resolution.y;\n vec2 uvNormalised = offsetUV * vec2(aspectRatio, 1.);\n\n const float gridDarkness = 0.3;\n\n float gridDivisor = 1.;\n float edgeFactor = smoothstep(0.2f, 1.f, screenEdgeDist(uvNormalised, 0.22 - (gridNoise * .06)));\n \n float gridFactor = clamp(0., gridDarkness, drawGridLines(offsetUV, .3 , 5.) * edgeFactor);\n float gridFactor2 = clamp(0., gridDarkness + 0.025, drawGridLines(offsetUV, .5 , 1.) * edgeFactor);\n \n vec3 lineCol = lineColor;\n \n lineCol.x += (step(0.6, gridNoise - gridNoise2) * 0.4);\n \n float gridTextureNoise = fbm(uv + noiseOffset, 6, 700., 0.7) * 0.5;\n vec3 lchColor = mix(backgroundColor, lineCol, clamp((gridFactor2 - gridTextureNoise) * uGridStrength, 0., 1.));\n \n float smoothNoise1 = texture(tPaperTexture, texUv + msaaOffset).x * 0.8;\n\n float colourNoise = fbm(uv + noiseOffset, 12, 5., 0.7) * 0.001;\n float colourNoise2 = fbm(uv - noiseOffset + 1., 12, 3., 0.7) * 0.001;\n\n lchColor.x += smoothNoise1 - colourNoise + colourNoise2;\n\n float edgeFactorVignette = smoothstep(0.2f, 1.f, screenEdgeDist(uvNormalised, 0.5));\n lchColor.x -= (1. - edgeFactorVignette) * 0.005;\n lchColor.y += (1. - edgeFactorVignette) * 0.005;\n // lchColor.y *= colourNoise;\n \n\n // lchColor = vec3(lchColor.x, lchColor.y, lchColor.z);\n\n vec3 colorRGB = OKLCHtoP3LRGB(lchColor);\n\n vec3 lightDir = normalize(vec3(.6f, 1.6f, 1.6f));\n vec3 lightColor = vec3(1.0f) * 1.7f;\n\n vec3 paperTextureNormals = calculateNormals(texUv + msaaOffset, 0.0002 * tileScaleFactor, 2.);\n vec3 diffuse = calculateDiffuse(paperTextureNormals, lightDir, lightColor);\n\n colorRGB *= diffuse;\n \n // float canvasTexture = fbm(uv, 6, 120., 0.7);\n return vec4(colorRGB, 1.);\n }\n\n \n\n void main() {\n // A pseudo-random distribution for multi-sample\n const vec2 H2 = vec2(0.56984029, 0.75487766);\n // We do sub-pixel offsets relative to tile size, \n // because each tile is scaled to fill the entire local canvas\n vec2 px = 1.0 / resolution.xy;\n px *= 1.25;\n\n // We'll accumulate color across multiple samples\n const float samples = 16.0;\n vec4 sumColour = vec4(0.0);\n \n // Vary the random offset per pixel\n vec2 d0 = vec2(randomNonDet(vUv), randomNonDet(vUv + 1.0));\n\n for (float i = 0.0; i < samples; i++) {\n vec2 d = fract(i * H2 + d0) - 0.5;\n // localCoord in [0..1] in the local canvas\n vec2 sampleCoord = vUv + d * px;\n\n // Now map that to the large “full” coordinate space \n // subregion given by uTileOffset..uTileOffset+uTileSize\n vec2 screenCoord = uTileOffset + sampleCoord * uTileSize;\n\n // Next convert to [0..1] over the entire original geometry\n vec2 globalUV = screenCoord / resolution;\n\n vec4 sampleColor = render(globalUV, vUv, d * px);\n sumColour += sampleColor;\n }\n\n vec4 finalColor = clamp(sumColour / samples, 0.0, 1.0);\n outColor = finalColor;\n }\n `}));var n;Vt.material=t,re(t);let i=Ht(J.choice(ve.bg)),l=Ht(J.choice(ve.line));t.uniforms.backgroundColor.value=(new e.Vector3).fromArray(i),t.uniforms.lineColor.value=(new e.Vector3).fromArray(l),t.uniforms.noiseOffset.value=new e.Vector2(We[0],We[1]),t.uniforms.uGridStrength.value=.2,X.setRenderTarget(Xt.getWriteBuffer()),Vt.render(X),Xt.copyAndSwapBuffers(),Xt.copyBufferToScreen()}],[function*(){let e=He.margin+ze.marginX,n=He.margin+ze.marginY,i=new zt(e,n),l=new zt(Y-e,P-n);(function(e,t,n=0){let i=[],l=[],a=J.weightedChoice([0,J.easedNum(ti,He.HVariance.min,He.HVariance.max)]),s=J.weightedChoice([0,J.easedNum(ti,He.VVariance.min,He.VVariance.max)]);for(let l=e.y;l<t.y;l+=ze.scale/2)J.gaussianBool(He.HVariance.threshold,He.HVariance.mean,He.HVariance.stdDev)||i.push({id:Nn(),meta:{lineCategory:be.horizontal},line:[[e.x-ze.scale*n,l+J.num(-ze.scale*a,ze.scale*a)],[t.x+ze.scale*n,l+J.num(-ze.scale*a,ze.scale*a)]]