UNPKG

@absulit/points

Version:

A Generative Art library made in WebGPU

289 lines (231 loc) 130 kB
/* @ts-self-types="./points.d.ts" */ import{RenderPass as RenderPass$1,Uniform as Uniform$1,Storage as Storage$1,Constant as Constant$1}from"points";function getWGSLCoordinate(value,side,invert=false){const direction=invert?-1:1;const p=value/side;return(p*2-1)*direction}const BARYCENTRICS=[[1,0,0],[0,1,0],[0,0,1]];class PrimitiveTopology{static POINT_LIST="point-list";static LINE_LIST="line-list";static LINE_STRIP="line-strip";static TRIANGLE_LIST="triangle-list";static TRIANGLE_STRIP="triangle-strip"}class LoadOp{static CLEAR="clear";static LOAD="load"}class FrontFace{static CCW="ccw";static CW="cw"}class CullMode{static NONE="none";static FRONT="front";static BACK="back"}class RenderPass{#index=null;#vertexShader;#computeShader;#fragmentShader;#compiledShaders;#computePipeline=null;#renderPipeline=null;#name=null;#computeBindGroup=null;#fragmentBindGroup=null;#vertexBindGroup=null;#bindGroupLayoutFragment=null;#bindGroupLayoutVertex=null;#bindGroupLayoutCompute=null;#hasComputeShader;#hasVertexShader;#hasFragmentShader;#hasVertexAndFragmentShader;#workgroupCountX;#workgroupCountY;#workgroupCountZ;#callback=null;#required=null;#instanceCount=1;#internal=false;#params=null;#vertexArray=[];#vertexBuffer=null;#vertexBufferInfo=null;#depthWriteEnabled=false;#textureDepth=null;#loadOp=LoadOp.CLEAR;#clearValue={r:0,g:0,b:0,a:1};#meshCounter=0;#meshes=[];#topology=PrimitiveTopology.TRIANGLE_LIST;#cullMode=CullMode.BACK;#frontFace=FrontFace.CCW;#meshUpdated=CSSFontFeatureValuesRule;#descriptor={colorAttachments:[{clearValue:{r:0,g:0,b:0,a:1},loadOp:"clear",storeOp:"store"}]};#depthStencilAttachment={depthClearValue:1,depthLoadOp:"clear",depthStoreOp:"store"};#bundle=null;#device=null;#enabled=true;constructor(vertexShader,fragmentShader,computeShader,workgroupCountX,workgroupCountY,workgroupCountZ,init){this.#vertexShader=vertexShader;this.#computeShader=computeShader;this.#fragmentShader=fragmentShader;this.#callback=init;this.#internal=!!init;this.#compiledShaders={vertex:"",compute:"",fragment:""};this.#hasComputeShader=!!this.#computeShader;this.#hasVertexShader=!!this.#vertexShader;this.#hasFragmentShader=!!this.#fragmentShader;this.#hasVertexAndFragmentShader=this.#hasVertexShader&&this.#hasFragmentShader;this.#workgroupCountX=workgroupCountX||8;this.#workgroupCountY=workgroupCountY||8;this.#workgroupCountZ=workgroupCountZ||1;Object.seal(this)}get index(){return this.#index}set index(value){this.#index=value}get vertexShader(){return this.#vertexShader}get computeShader(){return this.#computeShader}get fragmentShader(){return this.#fragmentShader}set computePipeline(value){this.#computePipeline=value}get computePipeline(){return this.#computePipeline}set renderPipeline(value){this.#renderPipeline=value}get renderPipeline(){return this.#renderPipeline}set computeBindGroup(value){this.#computeBindGroup=value}get computeBindGroup(){return this.#computeBindGroup}set fragmentBindGroup(value){this.#fragmentBindGroup=value}get fragmentBindGroup(){return this.#fragmentBindGroup}set vertexBindGroup(value){this.#vertexBindGroup=value}get vertexBindGroup(){return this.#vertexBindGroup}set bindGroupLayoutFragment(value){this.#bindGroupLayoutFragment=value}get bindGroupLayoutFragment(){return this.#bindGroupLayoutFragment}set bindGroupLayoutVertex(value){this.#bindGroupLayoutVertex=value}get bindGroupLayoutVertex(){return this.#bindGroupLayoutVertex}set bindGroupLayoutCompute(value){this.#bindGroupLayoutCompute=value}get bindGroupLayoutCompute(){return this.#bindGroupLayoutCompute}get compiledShaders(){return this.#compiledShaders}get hasComputeShader(){return this.#hasComputeShader}get hasVertexShader(){return this.#hasVertexShader}get hasFragmentShader(){return this.#hasFragmentShader}get hasVertexAndFragmentShader(){return this.#hasVertexAndFragmentShader}get workgroupCountX(){return this.#workgroupCountX}set workgroupCountX(val){this.#workgroupCountX=val}get workgroupCountY(){return this.#workgroupCountY}set workgroupCountY(val){this.#workgroupCountY=val}get workgroupCountZ(){return this.#workgroupCountZ}set workgroupCountZ(val){this.#workgroupCountZ=val}init(points){this.#params||={};this.#callback?.(points,this.#params)}get required(){return this.#required}set required(val){this.#required=val}get instanceCount(){this.#instanceCount=this.#meshes.reduce((sum,mesh)=>sum+mesh.instanceCount,0);return this.#instanceCount}get name(){return this.#name}set name(val){this.#name=val}get internal(){return this.#internal}get params(){return this.#params}set params(val){this.#params=val}get vertexArray(){return new Float32Array(this.#vertexArray)}set vertexArray(val){this.#vertexArray=val}get vertexBufferInfo(){return this.#vertexBufferInfo}set vertexBufferInfo(val){this.#vertexBufferInfo=val}get vertexBuffer(){return this.#vertexBuffer}set vertexBuffer(val){this.#vertexBuffer=val}get depthWriteEnabled(){return this.#depthWriteEnabled}set depthWriteEnabled(val){if(val){this.#descriptor.depthStencilAttachment=this.#depthStencilAttachment}this.#depthWriteEnabled=val}get textureDepth(){return this.#textureDepth}set textureDepth(val){this.#textureDepth=val}get loadOp(){return this.#loadOp}set loadOp(val){this.#loadOp=val;this.#descriptor.colorAttachments[0].loadOp=this.#loadOp}get clearValue(){return this.#clearValue}set clearValue(val){this.#clearValue=val;this.#descriptor.colorAttachments[0].clearValue=this.#clearValue}get descriptor(){return this.#descriptor}get topology(){return this.#topology}set topology(val){this.#topology=val}get cullMode(){return this.#cullMode}set cullMode(val){this.#cullMode=val}get frontFace(){return this.#frontFace}set frontFace(val){this.#frontFace=val}get bundle(){return this.#bundle}set bundle(val){this.#bundle=val}get device(){return this.#device}set device(val){this.#device=val}get enabled(){return this.#enabled}set enabled(val){this.#enabled=val}get meshUpdated(){return this.#meshUpdated}set meshUpdated(val){this.#meshUpdated=val}addPoint(coordinate,width,height,colors,canvas,useTexture=false){const{x,y,z}=coordinate;const nx=getWGSLCoordinate(x,canvas.width);const ny=getWGSLCoordinate(y,canvas.height,true);const nw=getWGSLCoordinate(x+width,canvas.width);const nh=getWGSLCoordinate(y+height,canvas.height);const nz=z;const normals=[0,0,1];const id=this.#meshCounter;const{r:r0,g:g0,b:b0,a:a0}=colors[0];const{r:r1,g:g1,b:b1,a:a1}=colors[1];const{r:r2,g:g2,b:b2,a:a2}=colors[2];const{r:r3,g:g3,b:b3,a:a3}=colors[3];this.#vertexArray.push(+nx,+ny,nz,1,r0,g0,b0,a0,(+nx+1)*.5,(+ny+1)*.5,...normals,id,...BARYCENTRICS[0],+nx,-nh,nz,1,r1,g1,b1,a1,(+nx+1)*.5,(-nh+1)*.5,...normals,id,...BARYCENTRICS[1],+nw,+ny,nz,1,r2,g2,b2,a2,(+nw+1)*.5,(+ny+1)*.5,...normals,id,...BARYCENTRICS[2]);this.#vertexArray.push(+nx,-nh,nz,1,r1,g1,b1,a1,(+nx+1)*.5,(-nh+1)*.5,...normals,id,...BARYCENTRICS[0],+nw,-nh,nz,1,r3,g3,b3,a3,(+nw+1)*.5,(-nh+1)*.5,...normals,id,...BARYCENTRICS[1],+nw,+ny,nz,1,r2,g2,b2,a2,(+nw+1)*.5,(+ny+1)*.5,...normals,id,...BARYCENTRICS[2]);const mesh={name:"_plane_",id,instanceCount:1,verticesCount:6};this.#meshes.push(mesh);++this.#meshCounter;return mesh}addPlane(name,coordinate={x:0,y:0,z:0},dimensions={width:1,height:1},color={r:1,g:0,b:1,a:0},segments={x:1,y:1}){const{x,y,z}=coordinate;const{width,height}=dimensions;const{x:sx,y:sy}=segments;const hw=width/2;const hh=height/2;const{r,g,b,a}=color;const normal=[0,0,1];const id=this.#meshCounter;const grid=[];for(let iy=0;iy<=sy;iy++){const v=iy/sy;const posY=y-hh+v*height;for(let ix=0;ix<=sx;ix++){const u=ix/sx;const posX=x-hw+u*width;grid.push({position:[posX,posY,z],uv:[u,v]})}}for(let iy=0;iy<sy;iy++){for(let ix=0;ix<sx;ix++){const rowSize=sx+1;const i0=iy*rowSize+ix;const i1=i0+1;const i2=i0+rowSize;const i3=i2+1;const quad=[grid[i0],grid[i1],grid[i3],grid[i0],grid[i3],grid[i2]];quad.forEach(({position:[vx,vy,vz],uv:[u,v]},i)=>{this.#vertexArray.push(+vx,+vy,+vz,1,r,g,b,a,u,v,...normal,id,...BARYCENTRICS[i%3])})}}const mesh={name,id,instanceCount:1,verticesCount:sx*sy*6};this.#meshes.push(mesh);++this.#meshCounter;return mesh}setPlane(name,coordinate={x:0,y:0,z:0},dimensions={width:1,height:1},color={r:1,g:0,b:1,a:0},segments={x:1,y:1}){const meshExists=this.#nameExists(this.#meshes,name);const{x,y,z}=coordinate;const{width,height}=dimensions;const{x:sx,y:sy}=segments;const hw=width/2;const hh=height/2;const{r,g,b,a}=color;const normal=[0,0,1];const id=this.#meshCounter;const grid=[];for(let iy=0;iy<=sy;iy++){const v=iy/sy;const posY=y-hh+v*height;for(let ix=0;ix<=sx;ix++){const u=ix/sx;const posX=x-hw+u*width;grid.push({position:[posX,posY,z],uv:[u,v]})}}const vertexArray=[];for(let iy=0;iy<sy;iy++){for(let ix=0;ix<sx;ix++){const rowSize=sx+1;const i0=iy*rowSize+ix;const i1=i0+1;const i2=i0+rowSize;const i3=i2+1;const quad=[grid[i0],grid[i1],grid[i3],grid[i0],grid[i3],grid[i2]];quad.forEach(({position:[vx,vy,vz],uv:[u,v]},i)=>{vertexArray.push(+vx,+vy,+vz,1,r,g,b,a,u,v,...normal,id,...BARYCENTRICS[i%3])})}}if(meshExists){meshExists.vertexArray=vertexArray;meshExists.verticesCount=sx*sy*6;this.#updateVertexArray();this.#meshUpdated=true;return meshExists}const mesh={name,id,instanceCount:1,verticesCount:sx*sy*6,vertexArray};this.#meshes.push(mesh);++this.#meshCounter;this.#updateVertexArray();return mesh}addCube(name,coordinate={x:0,y:0,z:0},dimensions={width:1,height:1,depth:1},color={r:1,g:0,b:1,a:0}){const{x,y,z}=coordinate;const{width,height,depth}=dimensions;const hw=width/2;const hh=height/2;const hd=depth/2;const corners=[[x-hw,y-hh,z-hd],[x+hw,y-hh,z-hd],[x+hw,y+hh,z-hd],[x-hw,y+hh,z-hd],[x-hw,y-hh,z+hd],[x+hw,y-hh,z+hd],[x+hw,y+hh,z+hd],[x-hw,y+hh,z+hd]];const faceUVs=[[[0,0],[1,0],[1,1],[0,1]],[[0,0],[1,0],[1,1],[0,1]],[[0,0],[1,0],[1,1],[0,1]],[[0,0],[1,0],[1,1],[0,1]],[[0,0],[1,0],[1,1],[0,1]],[[0,0],[1,0],[1,1],[0,1]]];const faceNormals=[[0,0,-1],[0,0,1],[-1,0,0],[1,0,0],[0,1,0],[0,-1,0]];const faces=[[0,3,2,1],[4,5,6,7],[0,4,7,3],[5,1,2,6],[3,7,6,2],[0,1,5,4]];for(let i=0;i<6;i++){const[i0,i1,i2,i3]=faces[i];const{r,g,b,a}=color;const normals=faceNormals[i];const v=[corners[i0],corners[i1],corners[i2],corners[i3]];const uv=faceUVs[i];const verts=[[v[0],uv[0]],[v[1],uv[1]],[v[2],uv[2]],[v[0],uv[0]],[v[2],uv[2]],[v[3],uv[3]]];verts.forEach(([[vx,vy,vz],[u,v]],i)=>{this.#vertexArray.push(+vx,+vy,+vz,1,r,g,b,a,u,v,...normals,this.#meshCounter,...BARYCENTRICS[i%3])})}const mesh={name,id:this.#meshCounter,instanceCount:1,verticesCount:36};this.#meshes.push(mesh);++this.#meshCounter;return mesh}setCube(name,coordinate={x:0,y:0,z:0},dimensions={width:1,height:1,depth:1},color={r:1,g:0,b:1,a:0}){const meshExists=this.#nameExists(this.#meshes,name);const{x,y,z}=coordinate;const{width,height,depth}=dimensions;const hw=width/2;const hh=height/2;const hd=depth/2;const corners=[[x-hw,y-hh,z-hd],[x+hw,y-hh,z-hd],[x+hw,y+hh,z-hd],[x-hw,y+hh,z-hd],[x-hw,y-hh,z+hd],[x+hw,y-hh,z+hd],[x+hw,y+hh,z+hd],[x-hw,y+hh,z+hd]];const faceUVs=[[[0,0],[1,0],[1,1],[0,1]],[[0,0],[1,0],[1,1],[0,1]],[[0,0],[1,0],[1,1],[0,1]],[[0,0],[1,0],[1,1],[0,1]],[[0,0],[1,0],[1,1],[0,1]],[[0,0],[1,0],[1,1],[0,1]]];const faceNormals=[[0,0,-1],[0,0,1],[-1,0,0],[1,0,0],[0,1,0],[0,-1,0]];const faces=[[0,3,2,1],[4,5,6,7],[0,4,7,3],[5,1,2,6],[3,7,6,2],[0,1,5,4]];const vertexArray=[];const meshCounter=meshExists?meshExists.id:this.#meshCounter;for(let i=0;i<6;i++){const[i0,i1,i2,i3]=faces[i];const{r,g,b,a}=color;const normals=faceNormals[i];const v=[corners[i0],corners[i1],corners[i2],corners[i3]];const uv=faceUVs[i];const verts=[[v[0],uv[0]],[v[1],uv[1]],[v[2],uv[2]],[v[0],uv[0]],[v[2],uv[2]],[v[3],uv[3]]];verts.forEach(([[vx,vy,vz],[u,v]],i)=>{vertexArray.push(+vx,+vy,+vz,1,r,g,b,a,u,v,...normals,meshCounter,...BARYCENTRICS[i%3])})}if(meshExists){meshExists.vertexArray=vertexArray;meshExists.verticesCount=36;this.#updateVertexArray();this.#meshUpdated=true;return meshExists}const mesh={name,id:this.#meshCounter,instanceCount:1,verticesCount:36,vertexArray};this.#meshes.push(mesh);++this.#meshCounter;this.#updateVertexArray();return mesh}addSphere(name,coordinate={x:0,y:0,z:0},color={r:1,g:0,b:1,a:0},radius=1,segments=16,rings=12){const{x,y,z}=coordinate;const{r,g,b,a}=color;const vertexGrid=[];for(let lat=0;lat<=rings;lat++){const theta=lat*Math.PI/rings;const sinTheta=Math.sin(theta);const cosTheta=Math.cos(theta);vertexGrid[lat]=[];for(let lon=0;lon<=segments;lon++){const phi=lon*2*Math.PI/segments;const sinPhi=Math.sin(phi);const cosPhi=Math.cos(phi);const nx=cosPhi*sinTheta;const ny=cosTheta;const nz=sinPhi*sinTheta;const vx=x+radius*nx;const vy=y+radius*ny;const vz=z+radius*nz;const u=lon/segments;const v=lat/rings;vertexGrid[lat][lon]=[vx,vy,vz,1,r,g,b,a,u,v,nx,ny,nz,this.#meshCounter]}}const b0=BARYCENTRICS[0];const b1=BARYCENTRICS[1];const b2=BARYCENTRICS[2];for(let lat=0;lat<rings;lat++){for(let lon=0;lon<segments;lon++){const v1=vertexGrid[lat][lon];const v2=vertexGrid[lat+1][lon];const v3=vertexGrid[lat+1][lon+1];const v4=vertexGrid[lat][lon+1];this.#vertexArray.push(...v1,...b0,...v3,...b1,...v2,...b2);this.#vertexArray.push(...v1,...b0,...v4,...b1,...v3,...b2)}}const mesh={name,id:this.#meshCounter,instanceCount:1,verticesCount:rings*segments*6};this.#meshes.push(mesh);++this.#meshCounter;return mesh}setSphere(name,coordinate={x:0,y:0,z:0},color={r:1,g:0,b:1,a:0},radius=1,segments=16,rings=12){const meshExists=this.#nameExists(this.#meshes,name);const{x,y,z}=coordinate;const{r,g,b,a}=color;const vertexGrid=[];const meshCounter=meshExists?meshExists.id:this.#meshCounter;for(let lat=0;lat<=rings;lat++){const theta=lat*Math.PI/rings;const sinTheta=Math.sin(theta);const cosTheta=Math.cos(theta);vertexGrid[lat]=[];for(let lon=0;lon<=segments;lon++){const phi=lon*2*Math.PI/segments;const sinPhi=Math.sin(phi);const cosPhi=Math.cos(phi);const nx=cosPhi*sinTheta;const ny=cosTheta;const nz=sinPhi*sinTheta;const vx=x+radius*nx;const vy=y+radius*ny;const vz=z+radius*nz;const u=lon/segments;const v=lat/rings;vertexGrid[lat][lon]=[vx,vy,vz,1,r,g,b,a,u,v,nx,ny,nz,meshCounter]}}const b0=BARYCENTRICS[0];const b1=BARYCENTRICS[1];const b2=BARYCENTRICS[2];const vertexArray=[];for(let lat=0;lat<rings;lat++){for(let lon=0;lon<segments;lon++){const v1=vertexGrid[lat][lon];const v2=vertexGrid[lat+1][lon];const v3=vertexGrid[lat+1][lon+1];const v4=vertexGrid[lat][lon+1];vertexArray.push(...v1,...b0,...v3,...b1,...v2,...b2);vertexArray.push(...v1,...b0,...v4,...b1,...v3,...b2)}}if(meshExists){meshExists.vertexArray=vertexArray;meshExists.verticesCount=rings*segments*6;this.#updateVertexArray();this.#meshUpdated=true;return meshExists}const mesh={name,id:this.#meshCounter,instanceCount:1,verticesCount:rings*segments*6,vertexArray};this.#meshes.push(mesh);++this.#meshCounter;this.#updateVertexArray();return mesh}addTorus(name,coordinate={x:0,y:0,z:0},radius=1,tube=.4,radialSegments=32,tubularSegments=24,color={r:1,g:0,b:1,a:1}){const{x,y,z}=coordinate;const{r,g,b,a}=color;const vertices=[];const normals=[];const uvs=[];const indices=[];for(let k=0;k<=radialSegments;k++){const v=k/radialSegments*Math.PI*2;const cosV=Math.cos(v);const sinV=Math.sin(v);for(let i=0;i<=tubularSegments;i++){const u=i/tubularSegments*Math.PI*2;const cosU=Math.cos(u);const sinU=Math.sin(u);const tx=(radius+tube*cosV)*cosU+x;const ty=(radius+tube*cosV)*sinU+y;const tz=tube*sinV+z;const nx=cosV*cosU;const ny=cosV*sinU;const nz=sinV;vertices.push([tx,ty,tz]);normals.push([nx,ny,nz]);uvs.push([i/tubularSegments,k/radialSegments])}}for(let k=1;k<=radialSegments;k++){for(let i=1;i<=tubularSegments;i++){const a=(tubularSegments+1)*k+i-1;const b=(tubularSegments+1)*(k-1)+i-1;const c=(tubularSegments+1)*(k-1)+i;const d=(tubularSegments+1)*k+i;indices.push([a,b,d]);indices.push([b,c,d])}}for(const[i0,i1,i2]of indices){for(const i of[i0,i1,i2]){const[vx,vy,vz]=vertices[i];const[nx,ny,nz]=normals[i];const[u,v]=uvs[i];this.#vertexArray.push(vx,vy,vz,1,r,g,b,a,u,v,nx,ny,nz,this.#meshCounter,...BARYCENTRICS[i%3])}}const mesh={name,id:this.#meshCounter,instanceCount:1,verticesCount:indices.length*3};this.#meshes.push(mesh);++this.#meshCounter;return mesh}setTorus(name,coordinate={x:0,y:0,z:0},radius=1,tube=.4,radialSegments=32,tubularSegments=24,color={r:1,g:0,b:1,a:1}){const meshExists=this.#nameExists(this.#meshes,name);const{x,y,z}=coordinate;const{r,g,b,a}=color;const vertices=[];const normals=[];const uvs=[];const indices=[];for(let k=0;k<=radialSegments;k++){const v=k/radialSegments*Math.PI*2;const cosV=Math.cos(v);const sinV=Math.sin(v);for(let i=0;i<=tubularSegments;i++){const u=i/tubularSegments*Math.PI*2;const cosU=Math.cos(u);const sinU=Math.sin(u);const tx=(radius+tube*cosV)*cosU+x;const ty=(radius+tube*cosV)*sinU+y;const tz=tube*sinV+z;const nx=cosV*cosU;const ny=cosV*sinU;const nz=sinV;vertices.push([tx,ty,tz]);normals.push([nx,ny,nz]);uvs.push([i/tubularSegments,k/radialSegments])}}for(let k=1;k<=radialSegments;k++){for(let i=1;i<=tubularSegments;i++){const a=(tubularSegments+1)*k+i-1;const b=(tubularSegments+1)*(k-1)+i-1;const c=(tubularSegments+1)*(k-1)+i;const d=(tubularSegments+1)*k+i;indices.push([a,b,d]);indices.push([b,c,d])}}const vertexArray=[];const meshCounter=meshExists?meshExists.id:this.#meshCounter;for(const[i0,i1,i2]of indices){for(const i of[i0,i1,i2]){const[vx,vy,vz]=vertices[i];const[nx,ny,nz]=normals[i];const[u,v]=uvs[i];vertexArray.push(vx,vy,vz,1,r,g,b,a,u,v,nx,ny,nz,meshCounter,...BARYCENTRICS[i%3])}}if(meshExists){meshExists.vertexArray=vertexArray;meshExists.verticesCount=indices.length*3;this.#updateVertexArray();this.#meshUpdated=true;return meshExists}const mesh={name,id:this.#meshCounter,instanceCount:1,verticesCount:indices.length*3,vertexArray};this.#meshes.push(mesh);++this.#meshCounter;this.#updateVertexArray();return mesh}addCylinder(name,coordinate={x:0,y:0,z:0},radius=.5,height=1,radialSegments=32,cap=true,color={r:1,g:0,b:1,a:1}){const{x:cx,y:cy,z:cz}=coordinate;const{r,g,b,a}=color;const halfHeight=height/2;const vertices=[];const normals=[];const uvs=[];const indices=[];for(let i=0;i<=radialSegments;i++){const theta=i/radialSegments*Math.PI*2;const cosTheta=Math.cos(theta);const sinTheta=Math.sin(theta);const px=cx+radius*cosTheta;const pz=cz+radius*sinTheta;vertices.push([px,cy-halfHeight,pz]);normals.push([cosTheta,0,sinTheta]);uvs.push([i/radialSegments,0]);vertices.push([px,cy+halfHeight,pz]);normals.push([cosTheta,0,sinTheta]);uvs.push([i/radialSegments,1])}for(let i=0;i<radialSegments;i++){const base=i*2;indices.push([base,base+1,base+3]);indices.push([base,base+3,base+2])}if(cap){const bottomCenterIndex=vertices.length;vertices.push([cx,cy-halfHeight,cz]);normals.push([0,-1,0]);uvs.push([.5,.5]);const topCenterIndex=vertices.length;vertices.push([cx,cy+halfHeight,cz]);normals.push([0,1,0]);uvs.push([.5,.5]);for(let i=0;i<radialSegments;i++){const theta=i/radialSegments*Math.PI*2;const nextTheta=(i+1)/radialSegments*Math.PI*2;const x0=cx+radius*Math.cos(theta);const z0=cz+radius*Math.sin(theta);const x1=cx+radius*Math.cos(nextTheta);const z1=cz+radius*Math.sin(nextTheta);const bottomIdx0=vertices.length;vertices.push([x0,cy-halfHeight,z0]);normals.push([0,-1,0]);uvs.push([.5+.5*Math.cos(theta),.5+.5*Math.sin(theta)]);const bottomIdx1=vertices.length;vertices.push([x1,cy-halfHeight,z1]);normals.push([0,-1,0]);uvs.push([.5+.5*Math.cos(nextTheta),.5+.5*Math.sin(nextTheta)]);indices.push([bottomCenterIndex,bottomIdx0,bottomIdx1]);const topIdx0=vertices.length;vertices.push([x0,cy+halfHeight,z0]);normals.push([0,1,0]);uvs.push([.5+.5*Math.cos(theta),.5+.5*Math.sin(theta)]);const topIdx1=vertices.length;vertices.push([x1,cy+halfHeight,z1]);normals.push([0,1,0]);uvs.push([.5+.5*Math.cos(nextTheta),.5+.5*Math.sin(nextTheta)]);indices.push([topCenterIndex,topIdx1,topIdx0])}}for(const ii of indices){ii.forEach((i,k)=>{const[vx,vy,vz]=vertices[i];const[nx,ny,nz]=normals[i];const[u,v]=uvs[i];this.#vertexArray.push(vx,vy,vz,1,r,g,b,a,u,v,nx,ny,nz,this.#meshCounter,...BARYCENTRICS[k%3])})}const mesh={name,id:this.#meshCounter,instanceCount:1,verticesCount:indices.length*3};this.#meshes.push(mesh);++this.#meshCounter;return mesh}setCylinder(name,coordinate={x:0,y:0,z:0},radius=.5,height=1,radialSegments=32,cap=true,color={r:1,g:0,b:1,a:1}){const meshExists=this.#nameExists(this.#meshes,name);const{x:cx,y:cy,z:cz}=coordinate;const{r,g,b,a}=color;const halfHeight=height/2;const vertices=[];const normals=[];const uvs=[];const indices=[];for(let i=0;i<=radialSegments;i++){const theta=i/radialSegments*Math.PI*2;const cosTheta=Math.cos(theta);const sinTheta=Math.sin(theta);const px=cx+radius*cosTheta;const pz=cz+radius*sinTheta;vertices.push([px,cy-halfHeight,pz]);normals.push([cosTheta,0,sinTheta]);uvs.push([i/radialSegments,0]);vertices.push([px,cy+halfHeight,pz]);normals.push([cosTheta,0,sinTheta]);uvs.push([i/radialSegments,1])}for(let i=0;i<radialSegments;i++){const base=i*2;indices.push([base,base+1,base+3]);indices.push([base,base+3,base+2])}if(cap){const bottomCenterIndex=vertices.length;vertices.push([cx,cy-halfHeight,cz]);normals.push([0,-1,0]);uvs.push([.5,.5]);const topCenterIndex=vertices.length;vertices.push([cx,cy+halfHeight,cz]);normals.push([0,1,0]);uvs.push([.5,.5]);for(let i=0;i<radialSegments;i++){const theta=i/radialSegments*Math.PI*2;const nextTheta=(i+1)/radialSegments*Math.PI*2;const x0=cx+radius*Math.cos(theta);const z0=cz+radius*Math.sin(theta);const x1=cx+radius*Math.cos(nextTheta);const z1=cz+radius*Math.sin(nextTheta);const bottomIdx0=vertices.length;vertices.push([x0,cy-halfHeight,z0]);normals.push([0,-1,0]);uvs.push([.5+.5*Math.cos(theta),.5+.5*Math.sin(theta)]);const bottomIdx1=vertices.length;vertices.push([x1,cy-halfHeight,z1]);normals.push([0,-1,0]);uvs.push([.5+.5*Math.cos(nextTheta),.5+.5*Math.sin(nextTheta)]);indices.push([bottomCenterIndex,bottomIdx0,bottomIdx1]);const topIdx0=vertices.length;vertices.push([x0,cy+halfHeight,z0]);normals.push([0,1,0]);uvs.push([.5+.5*Math.cos(theta),.5+.5*Math.sin(theta)]);const topIdx1=vertices.length;vertices.push([x1,cy+halfHeight,z1]);normals.push([0,1,0]);uvs.push([.5+.5*Math.cos(nextTheta),.5+.5*Math.sin(nextTheta)]);indices.push([topCenterIndex,topIdx1,topIdx0])}}const vertexArray=[];const meshCounter=meshExists?meshExists.id:this.#meshCounter;for(const ii of indices){ii.forEach((i,k)=>{const[vx,vy,vz]=vertices[i];const[nx,ny,nz]=normals[i];const[u,v]=uvs[i];vertexArray.push(vx,vy,vz,1,r,g,b,a,u,v,nx,ny,nz,meshCounter,...BARYCENTRICS[k%3])})}if(meshExists){meshExists.vertexArray=vertexArray;meshExists.verticesCount=indices.length*3;this.#updateVertexArray();this.#meshUpdated=true;return meshExists}const mesh={name,id:this.#meshCounter,instanceCount:1,verticesCount:indices.length*3,vertexArray};this.#meshes.push(mesh);++this.#meshCounter;this.#updateVertexArray();return mesh}addMesh(name,vertices,colors,colorSize,uvs,normals,indices){const verticesCount=indices.length;for(let i=0;i<verticesCount;i++){const index=indices[i];const vertex=vertices.slice(index*3,index*3+3);const color=colors?.slice(index*colorSize,index*colorSize+colorSize);const uv=uvs.slice(index*2,index*2+2);const normal=normals.slice(index*3,index*3+3);const[x,y,z]=vertex;const[r,g,b]=color||[1,0,1];const[u,v]=uv;this.#vertexArray.push(+x,+y,+z,1,r,g,b,1,u,v,...normal,this.#meshCounter,...BARYCENTRICS[i%3])}const mesh={name,id:this.#meshCounter,instanceCount:1,verticesCount};this.#meshes.push(mesh);++this.#meshCounter;return mesh}#nameExists(arrayOfObjects,name){return arrayOfObjects.find(obj=>obj.name==name)}#updateVertexArray(){this.#vertexArray=[];this.#meshes.forEach(mesh=>{mesh.vertexArray.forEach(item=>this.#vertexArray.push(item))})}setMesh(name,vertices,colors,colorSize,uvs,normals,indices){const meshExists=this.#nameExists(this.#meshes,name);const verticesCount=indices.length;const vertexArray=[];const meshCounter=meshExists?meshExists.id:this.#meshCounter;for(let i=0;i<verticesCount;i++){const index=indices[i];const vertex=vertices.slice(index*3,index*3+3);const color=colors?.slice(index*colorSize,index*colorSize+colorSize);const uv=uvs.slice(index*2,index*2+2);const normal=normals.slice(index*3,index*3+3);const[x,y,z]=vertex;const[r,g,b]=color||[1,0,1];const[u,v]=uv;vertexArray.push(+x,+y,+z,1,r,g,b,1,u,v,...normal,meshCounter,...BARYCENTRICS[i%3])}if(meshExists){meshExists.vertexArray=vertexArray;meshExists.verticesCount=verticesCount;this.#updateVertexArray();this.#meshUpdated=true;return meshExists}const mesh={name,id:this.#meshCounter,instanceCount:1,verticesCount,vertexArray};this.#meshes.push(mesh);++this.#meshCounter;this.#updateVertexArray();return mesh}get meshes(){return this.#meshes}destroy(){this.#device=null;this.#textureDepth.destroy();this.#vertexBuffer.destroy();this.#compiledShaders={vertex:"",compute:"",fragment:""};this.#computeBindGroup=null;this.#fragmentBindGroup=null;this.#vertexBindGroup=null;this.#bindGroupLayoutFragment=null;this.#bindGroupLayoutVertex=null;this.#bindGroupLayoutCompute=null;this.#computePipeline=null;this.#renderPipeline=null;this.#bundle=null}}class ScaleMode{static FIT=1;static COVER=2;static WIDTH=4;static HEIGHT=8}const size_2_align_2={size:2,align:2};const size_4_align_4={size:4,align:4};const size_6_align_8={size:6,align:8};const size_8_align_4={size:8,align:4};const size_8_align_8={size:8,align:8};const size_12_align_4={size:12,align:4};const size_12_align_16={size:12,align:16};const size_16_align_4={size:16,align:4};const size_16_align_16={size:16,align:16};const size_16_align_8={size:16,align:8};const size_24_align_8={size:24,align:8};const size_32_align_8={size:32,align:8};const size_32_align_16={size:32,align:16};const size_48_align_16={size:48,align:16};const size_64_align_16={size:64,align:16};const typeSizes={"bool":size_4_align_4,"i32":size_4_align_4,"u32":size_4_align_4,"f32":size_4_align_4,"f16":size_2_align_2,"atomic<u32>":size_4_align_4,"atomic<i32>":size_4_align_4,"vec2<bool>":size_8_align_8,"vec2<i32>":size_8_align_8,"vec2<u32>":size_8_align_8,"vec2<f32>":size_8_align_8,"vec2i":size_8_align_8,"vec2u":size_8_align_8,"vec2f":size_8_align_8,"vec2<f16>":size_4_align_4,"vec2h":size_4_align_4,"vec3<bool>":size_12_align_16,"vec3<i32>":size_12_align_16,"vec3<u32>":size_12_align_16,"vec3<f32>":size_12_align_16,"vec3i":size_12_align_16,"vec3u":size_12_align_16,"vec3f":size_12_align_16,"vec3<f16>":size_6_align_8,"vec3h":size_6_align_8,"vec4<bool>":size_16_align_16,"vec4<i32>":size_16_align_16,"vec4<u32>":size_16_align_16,"vec4<f32>":size_16_align_16,"vec4i":size_16_align_16,"vec4u":size_16_align_16,"vec4f":size_16_align_16,"vec4<f16>":size_8_align_8,"vec4h":size_8_align_8,"mat2x2<f32>":size_16_align_8,"mat2x2f":size_16_align_8,"mat2x2<f16>":size_8_align_4,"mat2x2h":size_8_align_4,"mat3x2<f32>":size_24_align_8,"mat3x2f":size_24_align_8,"mat3x2<f16>":size_12_align_4,"mat3x2h":size_12_align_4,"mat4x2<f32>":size_32_align_8,"mat4x2f":size_32_align_8,"mat4x2<f16>":size_16_align_4,"mat4x2h":size_16_align_4,"mat2x3<f32>":size_32_align_16,"mat2x3f":size_32_align_16,"mat2x3<f16>":size_16_align_8,"mat2x3h":size_16_align_8,"mat3x3<f32>":size_48_align_16,"mat3x3f":size_48_align_16,"mat3x3<f16>":size_24_align_8,"mat3x3h":size_24_align_8,"mat4x3<f32>":size_64_align_16,"mat4x3f":size_64_align_16,"mat4x3<f16>":size_32_align_8,"mat4x3h":size_32_align_8,"mat2x4<f32>":size_32_align_16,"mat2x4f":size_32_align_16,"mat2x4<f16>":size_16_align_8,"mat2x4h":size_16_align_8,"mat3x4<f32>":size_48_align_16,"mat3x4f":size_48_align_16,"mat3x4<f16>":size_24_align_8,"mat3x4h":size_24_align_8,"mat4x4<f32>":size_64_align_16,"mat4x4f":size_64_align_16,"mat4x4<f16>":size_32_align_8,"mat4x4h":size_32_align_8};const removeCommentsRE=/\/\*[\s\S]*?\*\/|\/\/.*/gim;const getStructNameRE=/struct\s+?(\w+)\s*{[^}]+}\n?/g;const insideStructRE=/struct\s+?\w+\s*{([^}]+)}\n?/g;const arrayTypeAndAmountRE=/\s*<\s*([^,]+)\s*,?\s*(\d+)?\s*>/g;const arrayIntegrityRE=/\s*(array\s*<\s*\w+\s*(?:,\s*\d+)?\s*>)\s*,?/g;function removeComments(value){const matches=value.matchAll(removeCommentsRE);for(const match of matches){const captured=match[0];value=value.replace(captured,"")}return value}function getInsideStruct(value){const matches=value.matchAll(insideStructRE);let lines=null;for(const match of matches){lines=match[1].split("\n");lines=lines.map(element=>element.trim()).filter(e=>e!=="")}return lines}function getStructDataByName(value){const matches=value.matchAll(getStructNameRE);let result=new Map;for(const match of matches){const captured=match[0];const name=match[1];const lines=getInsideStruct(captured);const types=lines.map(l=>{const right=l.split(":")[1];let type="";if(isArray(right)){const arrayMatch=right.matchAll(arrayIntegrityRE);type=arrayMatch.next().value[1]}else{type=right.split(",")[0].trim()}return type});const names=lines.map(l=>{const left=l.split(":")[0];let name="";name=left.split(",")[0].trim();return name});result.set(name,{captured,lines,types,unique_types:[...new Set(types)],names})}return result}function getArrayTypeAndAmount(value){const matches=value.matchAll(arrayTypeAndAmountRE);let result=[];for(const match of matches){const type=match[1];const amount=match[2];result.push({type,amount:Number(amount)})}return result}function isArray(value){return value.indexOf("array")!=-1}function getArrayTypeData(currentType,structData){const[d]=getArrayTypeAndAmount(currentType);if(!d){throw`${currentType} seems to have an error, maybe a wrong amount?`}if(d.amount==0){throw new Error(`${currentType} has an amount of 0`)}let currentTypeData=typeSizes[d.type]||structData.get(d.type);if(!currentTypeData){throw`Struct or type '${d.type}' in ${currentType} is not defined.`}if(d.amount){const t=typeSizes[d.type];if(t){currentTypeData={size:t.align*d.amount,align:t.align}}else{const sd=structData.get(d.type);if(sd){currentTypeData={size:sd.bytes*d.amount,align:sd.maxAlign}}}}return currentTypeData}function getPadding(bytes,maxSize){const remainder=bytes%maxSize;let remainingBytes=0;if(remainder){remainingBytes=maxSize-remainder}return remainingBytes}const MAX_ROW_SIZE=16;const HALF=2;const dataSize=value=>{const noCommentsValue=removeComments(value);const structData=getStructDataByName(noCommentsValue);structData.forEach(sd=>{let bytes=0;let remainingBytes=0;sd.paddings={};sd.names.forEach((name,i)=>{const type=sd.types[i];let typeSize=typeSizes[type];let repeat=0;if(!typeSize){if(type){if(isArray(type)){const[innerType]=getArrayTypeAndAmount(type);typeSize=typeSizes[innerType.type];repeat=innerType.amount;innerType.align=MAX_ROW_SIZE}else{const sd=structData.get(type);if(!sd){throw`Type or struct ${type} doesn't exist.`}typeSize={size:sd.bytes,align:MAX_ROW_SIZE}}}}const{size,align}=typeSize;const prevName=sd.names[i-1];do{let aligned=bytes%align===0;while(!aligned){remainingBytes-=HALF;bytes+=HALF;sd.paddings[prevName]||=0;sd.paddings[prevName]+=HALF;aligned=bytes%align===0}if(remainingBytes&&size>remainingBytes){bytes+=remainingBytes;sd.paddings[prevName]=remainingBytes;remainingBytes=0}bytes+=size;repeat--}while(repeat>0)remainingBytes=getPadding(bytes,MAX_ROW_SIZE)});remainingBytes=getPadding(bytes,MAX_ROW_SIZE);bytes+=remainingBytes;sd.bytes=bytes});return structData};function getWGSLType(value){if(!value&&value!==0||(Number.isNaN(value)||value instanceof Object||typeof value==="string")&&!(value instanceof Array)){return""}const strValue=value.toString();if(value instanceof Array){return getArrayType$1(value)}const hasPeriod=strValue.indexOf(".")!=-1;if(hasPeriod){return"f32"}const hasSign=strValue.indexOf("-")!=-1;if(hasSign){return"i32"}return"u32"}function getArrayType$1(value){const isArray=Array.isArray(value);let type=null;if(isArray){const{length}=value;if(length<=4){type=`vec${length}f`}if(length>4){type=`array<f32, ${length}>`}}return type}class Uniform{#name;#value;#type;#size;constructor({name,value,type=null,size=null}){this.#validateName(name);this.#validateType(type);this.#validateValue(value);this.#name=name;this.#value=value;this.#type=type||this.#getArrayType(value)||"f32";this.#size=size;Object.seal(this)}get name(){return this.#name}set name(value){this.#validateName(value);this.#name=value}get value(){return this.#value}set value(value){this.#validateValue(value);this.#value=value}get type(){return this.#type}set type(value){this.#validateType(value);this.#type=value||this.#getArrayType(this.#value)||"f32"}get size(){return this.#size}set size(value){this.#size=value}serialize(){const isArray=Array.isArray(this.#value);const value=isArray?[...this.#value]:this.#value;return{name:this.#name,value,type:this.#type,size:this.#size}}setValue(value){this.#validateValue(value);this.#value=value;return this}setType(value){this.#validateType(value);this.#type=value||this.#getArrayType(this.#value)||"f32";return this}#validateValue(value){if(typeof value==="object"&&!Array.isArray(value)){throw`Uniform '${this.#name}' value:'${value}' can't be an Object.`}if(typeof value==="string"){throw`Uniform '${this.#name}' value: '${value}' can't be an String.`}const isArray=Array.isArray(value);if(isArray){const{length}=value;if(Array.isArray(this.#value)){if(length!=this.#value.length){throw`Uniform named '${this.#name}': Size of the array value has changed from ${this.#value.length} to ${length}.`}}if(length<2){throw`Uniform named '${this.#name}': Can't assign an Array smaller than a vec2f. Assign the Number directly.`}}}#validateName(value){if(typeof value==="number"){throw`Uniform name '${this.#name}' can't be an Number.`}if(typeof value==="string"){const valNumber=+value;if(!Number.isNaN(valNumber)&&typeof valNumber==="number"){throw`Uniform name '${this.#name}' can't be an Number.`}}}#validateType(value){if(value&&isArray(value)){throw`Uniform '${this.#name}' type: '${value}' is an array, which is currently not supported for Uniforms.`}}#getArrayType(value){const isArray=Array.isArray(value);let type=null;if(isArray){const{length}=value;if(length<=4){type=`vec${length}f`}}return type}valueOf(){return this.#value}}class Storage{#name;#mapped;#type;#shaderStage=GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT|GPUShaderStage.COMPUTE;#readable=false;#buffer=null;#bufferRead=null;#internal=false;#stream=false;#updated=false;#value;#size=null;constructor({name,value,type,readable,shaderStage,stream=false,updated=false,size=null}){this.#validateName(name);this.#validateType(type);this.#validateValue(value);this.#name=name;this.#mapped=!!value;this.#type=type||getWGSLType(value);this.#readable=readable||this.#readable;this.#shaderStage=shaderStage||this.#shaderStage;this.#value=value;this.#stream=stream;this.#updated=updated;this.#size=size;Object.seal(this)}#ifTypeVecGetVecValue(type,value){let newValue=value;if(type.startsWith("vec")){newValue=`vec${value.length}f(${value})`}return newValue}get name(){return this.#name}set name(value){this.#validateName(value);this.#name=value}get mapped(){return this.#mapped}set mapped(value){this.#mapped=value}get type(){return this.#type}set type(value){this.#validateType(value);this.#type=value||getArrayType(this.#value)||"f32"}get shaderStage(){return this.#shaderStage}set shaderStage(value){this.#shaderStage=value}get readable(){return this.#readable}set readable(value){this.#readable=value}get buffer(){return this.#buffer}set buffer(value){this.#buffer=value}get bufferRead(){return this.#bufferRead}set bufferRead(value){this.#bufferRead=value}get internal(){return this.#internal}set internal(value){this.#internal=value}get size(){return this.#size}set size(value){this.#size=value}get stream(){return this.#stream}set stream(value){this.#stream=value}get updated(){return this.#updated}set updated(value){this.#updated=value}get value(){let value=this.#value;if(value&&!Array.isArray(value)&&value.constructor!==Uint8Array){value=new Uint8Array([value])}return value}set value(value){this.#validateValue(value);this.#mapped=!!value;const type=this.#type||getWGSLType(value);this.#value=value;this.#type=type;this.#updated=true}setValue(value){this.#validateValue(value);this.#mapped=true;this.#updated=true;const type=this.#type||getWGSLType(value);this.#value=value;this.#type=type;return this}setReadable(value){this.#readable=value;return this}setShaderStage(value){this.#shaderStage=value;return this}setType(value){this.#validateType(value);this.#type=value||getArrayType(value)||"f32";return this}async read(){let arrayBufferCopy=null;if(this.#readable){try{await this.#bufferRead.mapAsync(GPUMapMode.READ);const arrayBuffer=this.#bufferRead.getMappedRange();arrayBufferCopy=new Float32Array(arrayBuffer.slice(0));this.#bufferRead.unmap();this.#value=arrayBufferCopy}catch(error){}}return arrayBufferCopy}#validateValue(value){if(value&&typeof value==="object"&&!Array.isArray(value)&&!(value instanceof Uint8Array)){throw`Storage '${this.#name}' value:'${value}' can't be an Object.`}if(typeof value==="string"){throw`Storage '${this.#name}' value: '${value}' can't be an String.`}const isArray=Array.isArray(value);if(isArray){const{length}=value;if(length<2){throw`Constant named '${this.#name}': Size of the array is lower than 2. There's no vec1`}if(Array.isArray(this.#value)){if(length!=this.#value.length){throw`Storage named '${this.#name}': Size of the array value has changed from ${this.#value.length} to ${length}.`}}}}#validateName(value){if(typeof value==="number"){throw`Storage name '${this.#name}' can't be an Number.`}if(typeof value==="string"){const valNumber=+value;if(!Number.isNaN(valNumber)&&typeof valNumber==="number"){throw`Storage name '${this.#name}' can't be an Number.`}}}#validateType(value){}valueOf(){return this.#value}}class Constant{#name;#value;#type;#override;#shaderStage=GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT|GPUShaderStage.COMPUTE;constructor({name,value,type,override=false}){this.#validateName(name);this.#validateType(type);this.#validateValue(value);this.#name=name;this.#type=type||getWGSLType(value);this.#value=this.#ifTypeVecGetVecValue(this.#type,value);this.#override=override}#ifTypeVecGetVecValue(type,value){let newValue=value;if(type.indexOf("vec")!==-1){newValue=`vec${value.length}f(${value})`}return newValue}get name(){return this.#name}set name(value){this.#validateName(value);this.#name=value}get value(){return this.#value}set value(value){this.#validateValue(value);const type=getWGSLType(value);this.#value=this.#ifTypeVecGetVecValue(type,value);this.#type=type}get type(){return this.#type}set type(value){this.#validateType(value);this.#type=value}get override(){return this.#override}set override(value){this.#override=value}get shaderStage(){return this.#shaderStage}set shaderStage(value){this.#shaderStage=value}setValue(value){this.#validateValue(value);const type=getWGSLType(value);this.#value=this.#ifTypeVecGetVecValue(type,value);this.#type=type;return this}setType(value){this.#validateType(value);this.#type=value;return this}setOverride(value){this.#override=value;return this}setShaderStage(value){this.#shaderStage=value;return this}#validateValue(value){if(this.#value){throw`Constant '${this.#name}': can't update a const after it has been set.`}if(value&&typeof value==="object"&&!Array.isArray(value)&&!(value instanceof Uint8Array)){throw`Constant '${this.#name}' value:'${value}' can't be an Object.`}if(typeof value==="string"){throw`Constant '${this.#name}' value: '${value}' can't be an String.`}const isArray=Array.isArray(value);if(isArray){const{length}=value;if(length<2){throw`Constant named '${this.#name}': Size of the array is lower than 2. There's no vec1`}if(Array.isArray(this.#value)){if(length!=this.#value.length){throw`Constant named '${this.#name}': Size of the array value has changed from ${this.#value.length} to ${length}.`}}}}#validateName(value){if(typeof value==="number"){throw`Constant name '${this.#name}' can't be an Number.`}if(typeof value==="string"){const valNumber=+value;if(!Number.isNaN(valNumber)&&typeof valNumber==="number"){throw`Constant name '${this.#name}' can't be an Number.`}}}#validateType(value){}}class PresentationFormat{static BGRA8UNORM="bgra8unorm";static RGBA8UNORM="rgba8unorm";static RGBA16FLOAT="rgba16float";static RGBA32FLOAT="rgba32float"}const vert$9=` @vertex fn main(in: VertexIn) -> FragmentIn { return defaultVertexBody(in.position, in.color, in.uv, in.normal); } `;const texture=` fn texture(texture:texture_2d<f32>, aSampler:sampler, uv:vec2f, crop:bool) -> vec4f { let flipTexture = vec2(1.,-1.); let flipTextureCoordinates = vec2(-1.,1.); let dims:vec2u = textureDimensions(texture, 0); let dimsF32 = vec2f(dims); let minScreenSize = params.screen.y; let imageRatio = dimsF32 / minScreenSize; let displaceImagePosition = vec2(0., 1.); let imageUV = uv / imageRatio * flipTexture + displaceImagePosition; var rgbaImage = textureSample(texture, aSampler, imageUV); // e.g. if uv.x < 0. OR uv.y < 0. || uv.x > imageRatio.x OR uv.y > imageRatio.y if (crop && (any(uv < vec2(0.0)) || any(uv > imageRatio))) { rgbaImage = vec4(0.); } return rgbaImage; } `;const texturePosition=` fn texturePosition(texture:texture_2d<f32>, aSampler:sampler, position:vec2f, uv:vec2f, crop:bool) -> vec4f { let flipTexture = vec2(1.,-1.); let flipTextureCoordinates = vec2(-1.,1.); let dims: vec2<u32> = textureDimensions(texture, 0); let dimsF32 = vec2f(dims); let minScreenSize = params.screen.y; let imageRatio = dimsF32 / minScreenSize; let displaceImagePosition = position * flipTextureCoordinates / imageRatio + vec2(0., 1.); let top = position + vec2(0, imageRatio.y); let imageUV = uv / imageRatio * flipTexture + displaceImagePosition; var rgbaImage = textureSample(texture, aSampler, imageUV); // e.g. if uv.x < 0. OR uv.y < 0. || uv.x > imageRatio.x OR uv.y > imageRatio.y if (crop && (any(uv < position) || any(uv > position + imageRatio))) { rgbaImage = vec4(0.); } return rgbaImage; } `;const pixelateTexturePosition=` fn pixelateTexturePosition(texture:texture_2d<f32>, textureSampler:sampler, position:vec2f, pixelsWidth:f32, pixelsHeight:f32, uv:vec2f) -> vec4f { let dx = pixelsWidth * (1. / params.screen.x); let dy = pixelsHeight * (1. / params.screen.y); let coord = vec2(dx*floor( uv.x / dx), dy * floor( uv.y / dy)); //texturePosition(texture:texture_2d<f32>, aSampler:sampler, position:vec2f, uv:vec2f, crop:bool) -> vec4f { return texturePosition(texture, textureSampler, position, coord, true); } `;const frag$9=` ${texture} @fragment fn main(in: FragmentIn) -> @location(0) vec4f { let imageColor = texture(renderpass_feedbackTexture, renderpass_feedbackSampler, in.uvr, true); let finalColor = (imageColor + params.color_color) * params.color_blendAmount; return finalColor; } `;const color$1=new RenderPass$1(vert$9,frag$9,null,8,8,1,(points,params)=>{points.setSampler("renderpass_feedbackSampler",null).internal=true;points.setTexture2d("renderpass_feedbackTexture",true).internal=true;points.setUniform("color_blendAmount",params.blendAmount||.5);points.setUniform("color_color",params.color||[1,.75,.79,1],"vec4f")});color$1.required=["color","blendAmount"];color$1.name="Color";const vert$8=` @vertex fn main(in: VertexIn) -> FragmentIn { return defaultVertexBody(in.position, in.color, in.uv, in.normal); } `;const fnusin=` fn fnusin(speed: f32) -> f32{ return (sin(params.time * speed) + 1.) * .5; } `;const RED=` const RED = vec4(1.,0.,0.,1.); `;const GREEN=` const GREEN = vec4(0.,1.,0.,1.); `;const BLUE=` const BLUE = vec4(0.,0.,1.,1.); `;const WHITE=` const WHITE = vec4(1.,1.,1.,1.); `;const bloom$1=` fn bloom(input:f32, iterations:i32, intensity:f32) -> f32 { var output = 0.; let iterationsF32 = f32(iterations); for (var k = 0; k < iterations; k++) { let kf32 = f32(k); for (var n = 0; n < iterations; n++) { let coef = cos(2. * PI * kf32 * f32(n) / iterationsF32 ); output += input * coef * intensity; } } return output; } `;const brightness=` fn brightness(color:vec4f) -> f32 { // // Standard // LuminanceA = (0.2126*R) + (0.7152*G) + (0.0722*B) // // Percieved A // LuminanceB = (0.299*R + 0.587*G + 0.114*B) // // Perceived B, slower to calculate // LuminanceC = sqrt(0.299*(R**2) + 0.587*(G**2) + 0.114*(B**2)) return (0.2126 * color.r) + (0.7152 * color.g) + (0.0722 * color.b); } `;const frag$8=` ${fnusin} ${texturePosition} ${brightness} ${WHITE} @fragment fn main(in: FragmentIn) -> @location(0) vec4f { let imageColor = texturePosition(renderpass_feedbackTexture, renderpass_feedbackSampler, vec2(0., 0), in.uvr, true); let finalColor:vec4f = brightness(imageColor) * WHITE; return finalColor; } `;const grayscale=new RenderPass$1(vert$8,frag$8,null,8,8,1,(points,params)=>{points.setSampler("renderpass_feedbackSampler",null).internal=true;points.setTexture2d("renderpass_feedbackTexture",true).internal=true});grayscale.name="Grayscale";const vert$7=` @vertex fn main(in: VertexIn) -> FragmentIn { return defaultVertexBody(in.position, in.color, in.uv, in.normal); } `;const frag$7=` ${texturePosition} @fragment fn main(in: FragmentIn) -> @location(0) vec4f { let imageColor = texturePosition(renderpass_feedbackTexture, renderpass_feedbackSampler, vec2(0., 0), in.uvr, true); // --------- chromatic displacement vector let cdv = vec2(params.chromaticAberration_distance, 0.); let d = distance(vec2(.5,.5), in.uvr); let imageColorR = texturePosition(renderpass_feedbackTexture, renderpass_feedbackSampler, vec2(0.) * in.ratio, in.uvr + cdv * d, true).r; let imageColorG = texturePosition(renderpass_feedbackTexture, renderpass_feedbackSampler, vec2(0.) * in.ratio, in.uvr, true).g; let imageColorB = texturePosition(renderpass_feedbackTexture, renderpass_feedbackSampler, vec2(0.) * in.ratio, in.uvr - cdv * d, true).b; let finalColor:vec4f = vec4(imageColorR, imageColorG, imageColorB, 1); return finalColor; } `;const chromaticAberration=new RenderPass$1(vert$7,frag$7,null,8,8,1,(points,params)=>{points.setSampler("renderpass_feedbackSampler",null).internal=true;points.setTexture2d("renderpass_feedbackTexture",true).internal=true;points.setUniform("chromaticAberration_distance",params.distance||.02)});chromaticAberration.required=["distance"];chromaticAberration.name="Chromatic Aberration";const vert$6=` @vertex fn main(in: VertexIn) -> FragmentIn { return defaultVertexBody(in.position, in.color, in.uv, in.normal); } `;const frag$6=` ${texturePosition} ${pixelateTexturePosition} @fragment fn main(in: FragmentIn) -> @location(0) vec4f { let pixelatedColor = pixelateTexturePosition( renderpass_feedbackTexture, renderpass_feedbackSampler, vec2(0.), params.pixelate_pixelDims.x, params.pixelate_pixelDims.y, in.uvr ); let finalColor:vec4f = pixelatedColor; return finalColor; } `;const pixelate=new RenderPass$1(vert$6,frag$6,null,8,8,1,(points,params)=>{points.setSampler("renderpass_feedbackSampler",null).internal=true;points.setTexture2d("renderpass_feedbackTexture",true).internal=true;points.setUniform("pixelate_pixelDims",params.pixelDimensions||[10,10],"vec2f")});pixelate.required=["pixelDimensions"];pixelate.name="Pixelate";const vert$5=` @vertex fn main(in: VertexIn) -> FragmentIn { return defaultVertexBody(in.position, in.color, in.uv, in.normal); } `;const PI=`const PI = 3.14159265;`;const polar=` fn polar(distance: f32, radians: f32) -> vec2f { return vec2f(distance * cos(radians), distance * sin(radians)); } `;const rotateVector=` fn rotateVector(p:vec2f, rads:f32 ) -> vec2f { let s = sin(rads); let c = cos(rads); let xnew = p.x * c - p.y * s; let ynew = p.x * s + p.y * c; return vec2(xnew, ynew); } `;const snoise=` fn mod289_v3(x: vec3f) -> vec3f { return x - floor(x * (1.0 / 289.0)) * 289.0; } fn mod289_v2(x: vec2f) -> vec2f { return x - floor(x * (1.0 / 289.0)) * 289.0; } fn permute(x: vec3f) -> vec3f { return mod289_v3(((x*34.0)+10.0)*x); } fn snoise(v:vec2f) -> f32 { let C = vec4(0.211324865405187, // (3.0-sqrt(3.0))/6.0 0.366025403784439, // 0.5*(sqrt(3.0)-1.0) -0.577350269189626, // -1.0 + 2.0 * C.x 0.024390243902439); // 1.0 / 41.0 // First corner var i = floor(v + dot(v, C.yy) ); var x0 = v - i + dot(i, C.xx); // Other corners var i1 = vec2(0.); //i1.x = step( x0.y, x0.x ); // x0.x > x0.y ? 1.0 : 0.0 //i1.y = 1.0 - i1.x; //i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); if(x0.x > x0.y){ i1 = vec2(1.0, 0.0); }else{ i1 = vec2(0.0, 1.0); } //x0 = x0 - 0.0 + 0.0 * C.xx ; // x1 = x0 - i1 + 1.0 * C.xx ; // x2 = x0 - 1.0 + 2.0 * C.xx ; var x12 = x0.xyxy + C.xxzz; //x12.xy -= i1; x12 = vec4(x12.xy - i1, x12.zw); // ?? fix // Permutations i = mod289_v2(i); // Avoid truncation effects in permutation let p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 )) + i.x + vec3(0.0, i1.x, 1.0 )); var m = max(vec3(0.5) - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), vec3(0.0)); m = m*m ; m = m*m ; // Gradients: 41 points uniformly over a line, mapped onto a diamond. // The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287) let x = 2.0 * fract(p * C.www) - 1.0; let h = abs(x) - 0.5; let ox = floor(x + 0.5); let a0 = x - ox; // Normalise gradients implicitly by scaling m // Approximation of: m *= inversesqrt( a0*a0 + h*h ); m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h ); // Compute final noise value at P var g = vec3(0.); g.x = a0.x * x0.x + h.x * x0.y; //g.yz = a0.yz * x12.xz + h.yz * x12.yw; g = vec3(g.x,a0.yz * x12.xz + h.yz * x12.yw); return 130.0 * dot(m, g); } `;const frag$5=` ${texture} ${rotateVector} ${snoise} ${PI} ${WHITE} ${polar} fn angle(p1:vec2f, p2:vec2f) -> f32 { let d = p1 - p2; return abs(atan2(d.y, d.x)) / PI; } @fragment fn main(in: Fragme