├── .gitignore
├── .prettierrc
├── LICENSE
├── README.md
├── dist
├── index.es.js
└── index.umd.js
├── index.html
├── package-lock.json
├── package.json
├── src
├── main.ts
├── new-2d
│ ├── bevel-join.ts
│ ├── caps.ts
│ ├── interleaved-strip.ts
│ ├── miter-join.ts
│ ├── new-2d.ts
│ ├── round-join.ts
│ └── self-overlapping.ts
└── old-2d
│ ├── interleaved-strip.ts
│ ├── old-2d.ts
│ └── round-cap-join.ts
├── tsconfig.json
└── vite.config.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "tabWidth": 2,
3 | "useTabs": false,
4 | "printWidth": 140
5 | }
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | This is free and unencumbered software released into the public domain.
2 |
3 | Anyone is free to copy, modify, publish, use, compile, sell, or
4 | distribute this software, either in source code form or as a compiled
5 | binary, for any purpose, commercial or non-commercial, and by any
6 | means.
7 |
8 | In jurisdictions that recognize copyright laws, the author or authors
9 | of this software dedicate any and all copyright interest in the
10 | software to the public domain. We make this dedication for the benefit
11 | of the public at large and to the detriment of our heirs and
12 | successors. We intend this dedication to be an overt act of
13 | relinquishment in perpetuity of all present and future rights to this
14 | software under copyright law.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
24 | For more information, please refer to
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | This is the source for the figures in [Instanced Line Rendering Part II: Alpha Blending](https://wwwtyro.net/2021/10/01/instanced-lines-part-2.html).
2 |
--------------------------------------------------------------------------------
/dist/index.umd.js:
--------------------------------------------------------------------------------
1 | (function(wt){typeof define=="function"&&define.amd?define(wt):wt()})(function(){"use strict";var wt=typeof globalThis!="undefined"?globalThis:typeof window!="undefined"?window:typeof global!="undefined"?global:typeof self!="undefined"?self:{},ca={exports:{}};(function(A,_e){(function(de,ae){A.exports=ae()})(wt,function(){var de=function(e){return e instanceof Uint8Array||e instanceof Uint16Array||e instanceof Uint32Array||e instanceof Int8Array||e instanceof Int16Array||e instanceof Int32Array||e instanceof Float32Array||e instanceof Float64Array||e instanceof Uint8ClampedArray},ae=function(e,t){for(var u=Object.keys(t),x=0;x=0&&(e|0)===e||Ve("invalid parameter type, ("+e+")"+Oe(t)+". must be a nonnegative integer")}function Hr(e,t,u){t.indexOf(e)<0&&Ve("invalid value"+Oe(u)+". must be one of: "+t)}var qe=["gl","canvas","container","attributes","pixelRatio","extensions","optionalExtensions","profile","onDone"];function ur(e){Object.keys(e).forEach(function(t){qe.indexOf(t)<0&&Ve('invalid regl constructor argument "'+t+'". must be one of '+qe)})}function or(e,t){for(e=e+"";e.length0&&t.push(new Ct("unknown",0,u))}}),t}function Xo(e,t){t.forEach(function(u){var x=e[u.file];if(x){var C=x.index[u.line];if(C){C.errors.push(u),x.hasErrors=!0;return}}e.unknown.hasErrors=!0,e.unknown.lines[0].errors.push(u)})}function Yo(e,t,u,x,C){if(!e.getShaderParameter(t,e.COMPILE_STATUS)){var E=e.getShaderInfoLog(t),S=x===e.FRAGMENT_SHADER?"fragment":"vertex";Aa(u,"string",S+" shader source must be a string",C);var D=zr(u,C),N=Ot(E);Xo(D,N),Object.keys(D).forEach(function(U){var V=D[U];if(!V.hasErrors)return;var j=[""],z=[""];function P(k,p){j.push(k),z.push(p||"")}P("file number "+U+": "+V.name+`
5 | `,"color:red;text-decoration:underline;font-weight:bold"),V.lines.forEach(function(k){if(k.errors.length>0){P(or(k.number,4)+"| ","background-color:yellow; font-weight:bold"),P(k.line+pe,"color:red; background-color:yellow; font-weight:bold");var p=0;k.errors.forEach(function(g){var M=g.message,Z=/^\s*'(.*)'\s*:\s*(.*)$/.exec(M);if(Z){var G=Z[1];switch(M=Z[2],G){case"assign":G="=";break}p=Math.max(k.line.indexOf(G,p),0)}else p=0;P(or("| ",6)),P(or("^^^",p+3)+pe,"font-weight:bold"),P(or("| ",6)),P(M+pe,"font-weight:bold")}),P(or("| ",6)+pe)}else P(or(k.number,4)+"| "),P(k.line+pe,"color:red")}),typeof document!="undefined"&&!window.chrome?(z[0]=j.join("%c"),console.log.apply(console,z)):console.log(j.join(""))}),ve.raise("Error compiling "+S+" shader, "+D[0].name)}}function Wo(e,t,u,x,C){if(!e.getProgramParameter(t,e.LINK_STATUS)){var E=e.getProgramInfoLog(t),S=zr(u,C),D=zr(x,C),N='Error linking program with vertex shader, "'+D[0].name+'", and fragment shader "'+S[0].name+'"';typeof document!="undefined"?console.log("%c"+N+pe+"%c"+E,"color:red;text-decoration:underline;font-weight:bold","color:red"):console.log(N+pe+E),ve.raise(N)}}function Ea(e){e._commandRef=Ie()}function qo(e,t,u,x){Ea(e);function C(N){return N?x.id(N):0}e._fragId=C(e.static.frag),e._vertId=C(e.static.vert);function E(N,U){Object.keys(U).forEach(function(V){N[x.id(V)]=!0})}var S=e._uniformSet={};E(S,t.static),E(S,t.dynamic);var D=e._attributeSet={};E(D,u.static),E(D,u.dynamic),e._hasCount="count"in e.static||"count"in e.dynamic||"elements"in e.static||"elements"in e.dynamic}function Bt(e,t){var u=ft();Ve(e+" in command "+(t||Ie())+(u==="unknown"?"":" called from "+u))}function Qo(e,t,u){e||Bt(t,u||Ie())}function Ko(e,t,u,x){e in t||Bt("unknown parameter ("+e+")"+Oe(u)+". possible values: "+Object.keys(t).join(),x||Ie())}function Aa(e,t,u,x){hr(e,t)||Bt("invalid parameter type"+Oe(u)+". expected "+t+", got "+typeof e,x||Ie())}function Zo(e){e()}function Jo(e,t,u){e.texture?Hr(e.texture._texture.internalformat,t,"unsupported texture format for attachment"):Hr(e.renderbuffer._renderbuffer.format,u,"unsupported renderbuffer format for attachment")}var Ft=33071,xa=9728,ef=9984,rf=9985,tf=9986,nf=9987,af=5120,of=5121,ff=5122,sf=5123,uf=5124,cf=5125,Ta=5126,ga=32819,Sa=32820,wa=33635,La=34042,lf=36193,Ze={};Ze[af]=Ze[of]=1,Ze[ff]=Ze[sf]=Ze[lf]=Ze[wa]=Ze[ga]=Ze[Sa]=2,Ze[uf]=Ze[cf]=Ze[Ta]=Ze[La]=4;function Ra(e,t){return e===Sa||e===ga||e===wa?2:e===La?4:Ze[e]*t}function Gt(e){return!(e&e-1)&&!!e}function df(e,t,u){var x,C=t.width,E=t.height,S=t.channels;ve(C>0&&C<=u.maxTextureSize&&E>0&&E<=u.maxTextureSize,"invalid texture shape"),(e.wrapS!==Ft||e.wrapT!==Ft)&&ve(Gt(C)&&Gt(E),"incompatible wrap mode for texture, both width and height must be power of 2"),t.mipmask===1?C!==1&&E!==1&&ve(e.minFilter!==ef&&e.minFilter!==tf&&e.minFilter!==rf&&e.minFilter!==nf,"min filter requires mipmap"):(ve(Gt(C)&&Gt(E),"texture must be a square power of 2 to support mipmapping"),ve(t.mipmask===(C<<1)-1,"missing or incomplete mipmap data")),t.type===Ta&&(u.extensions.indexOf("oes_texture_float_linear")<0&&ve(e.minFilter===xa&&e.magFilter===xa,"filter not supported, must enable oes_texture_float_linear"),ve(!e.genMipmaps,"mipmap generation not supported with float textures"));var D=t.images;for(x=0;x<16;++x)if(D[x]){var N=C>>x,U=E>>x;ve(t.mipmask&1<0&&C<=x.maxTextureSize&&E>0&&E<=x.maxTextureSize,"invalid texture shape"),ve(C===E,"cube map must be square"),ve(t.wrapS===Ft&&t.wrapT===Ft,"wrap mode not supported by cube map");for(var D=0;D>V,P=E>>V;ve(N.mipmask&1<1&&t===u&&(t==='"'||t==="'"))return['"'+Ca(e.substr(1,e.length-2))+'"'];var x=/\[(false|true|null|\d+|'[^']*'|"[^"]*")\]/.exec(e);if(x)return st(e.substr(0,x.index)).concat(st(x[1])).concat(st(e.substr(x.index+x[0].length)));var C=e.split(".");if(C.length===1)return['"'+Ca(e)+'"'];for(var E=[],S=0;S0,"invalid pixel ratio"))):n.raise("invalid arguments to regl"),u&&(u.nodeName.toLowerCase()==="canvas"?C=u:x=u),!E){if(!C){n(typeof document!="undefined","must manually specify webgl context outside of DOM environments");var P=Af(x||document.body,j,U);if(!P)return null;C=P.canvas,z=P.onDestroy}S.premultipliedAlpha===void 0&&(S.premultipliedAlpha=!0),E=xf(C,S)}return E?{gl:E,canvas:C,container:x,extensions:D,optionalExtensions:N,pixelRatio:U,profile:V,onDone:j,onDestroy:z}:(z(),j("webgl not supported, try upgrading your browser or graphics drivers http://get.webgl.org"),null)}function wf(e,t){var u={};function x(S){n.type(S,"string","extension name must be string");var D=S.toLowerCase(),N;try{N=u[D]=e.getExtension(D)}catch(U){}return!!N}for(var C=0;C65535)<<4,e>>>=t,u=(e>255)<<3,e>>>=u,t|=u,u=(e>15)<<2,e>>>=u,t|=u,u=(e>3)<<1,e>>>=u,t|=u,t|e>>1}function Pa(){var e=er(8,function(){return[]});function t(E){var S=Nf(E),D=e[Da(S)>>2];return D.length>0?D.pop():new ArrayBuffer(S)}function u(E){e[Da(E.byteLength)>>2].push(E)}function x(E,S){var D=null;switch(E){case Lf:D=new Int8Array(t(S),0,S);break;case Rf:D=new Uint8Array(t(S),0,S);break;case Cf:D=new Int16Array(t(2*S),0,S);break;case Of:D=new Uint16Array(t(2*S),0,S);break;case Bf:D=new Int32Array(t(4*S),0,S);break;case Ff:D=new Uint32Array(t(4*S),0,S);break;case Gf:D=new Float32Array(t(4*S),0,S);break;default:return null}return D.length!==S?D.subarray(0,S):D}function C(E){u(E.buffer)}return{alloc:t,free:u,allocType:x,freeType:C}}var Ne=Pa();Ne.zero=Pa();var Df=3408,Pf=3410,If=3411,Mf=3412,kf=3413,Uf=3414,jf=3415,Vf=33901,Hf=33902,zf=3379,$f=3386,Xf=34921,Yf=36347,Wf=36348,qf=35661,Qf=35660,Kf=34930,Zf=36349,Jf=34076,es=34024,rs=7936,ts=7937,ns=7938,as=35724,is=34047,os=36063,fs=34852,Nt=3553,Ia=34067,ss=34069,us=33984,ut=6408,hn=5126,Ma=5121,pn=36160,cs=36053,ls=36064,ds=16384,ms=function(e,t){var u=1;t.ext_texture_filter_anisotropic&&(u=e.getParameter(is));var x=1,C=1;t.webgl_draw_buffers&&(x=e.getParameter(fs),C=e.getParameter(os));var E=!!t.oes_texture_float;if(E){var S=e.createTexture();e.bindTexture(Nt,S),e.texImage2D(Nt,0,ut,1,1,0,ut,hn,null);var D=e.createFramebuffer();if(e.bindFramebuffer(pn,D),e.framebufferTexture2D(pn,ls,Nt,S,0),e.bindTexture(Nt,null),e.checkFramebufferStatus(pn)!==cs)E=!1;else{e.viewport(0,0,1,1),e.clearColor(1,0,0,1),e.clear(ds);var N=Ne.allocType(hn,4);e.readPixels(0,0,1,1,ut,hn,N),e.getError()?E=!1:(e.deleteFramebuffer(D),e.deleteTexture(S),E=N[0]===1),Ne.freeType(N)}}var U=typeof navigator!="undefined"&&(/MSIE/.test(navigator.userAgent)||/Trident\//.test(navigator.appVersion)||/Edge/.test(navigator.userAgent)),V=!0;if(!U){var j=e.createTexture(),z=Ne.allocType(Ma,36);e.activeTexture(us),e.bindTexture(Ia,j),e.texImage2D(ss,0,ut,3,3,0,ut,Ma,z),Ne.freeType(z),e.bindTexture(Ia,null),e.deleteTexture(j),V=!e.getError()}return{colorBits:[e.getParameter(Pf),e.getParameter(If),e.getParameter(Mf),e.getParameter(kf)],depthBits:e.getParameter(Uf),stencilBits:e.getParameter(jf),subpixelBits:e.getParameter(Df),extensions:Object.keys(t).filter(function(P){return!!t[P]}),maxAnisotropic:u,maxDrawbuffers:x,maxColorAttachments:C,pointSizeDims:e.getParameter(Vf),lineWidthDims:e.getParameter(Hf),maxViewportDims:e.getParameter($f),maxCombinedTextureUnits:e.getParameter(qf),maxCubeMapSize:e.getParameter(Jf),maxRenderbufferSize:e.getParameter(es),maxTextureUnits:e.getParameter(Kf),maxTextureSize:e.getParameter(zf),maxAttributes:e.getParameter(Xf),maxVertexUniforms:e.getParameter(Yf),maxVertexTextureUnits:e.getParameter(Qf),maxVaryingVectors:e.getParameter(Wf),maxFragmentUniforms:e.getParameter(Zf),glsl:e.getParameter(as),renderer:e.getParameter(ts),vendor:e.getParameter(rs),version:e.getParameter(ns),readFloat:E,npotTextureCube:V}};function fr(e){return!!e&&typeof e=="object"&&Array.isArray(e.shape)&&Array.isArray(e.stride)&&typeof e.offset=="number"&&e.shape.length===e.stride.length&&(Array.isArray(e.data)||de(e.data))}var rr=function(e){return Object.keys(e).map(function(t){return e[t]})},Dt={shape:bs,flatten:vs};function hs(e,t,u){for(var x=0;x0){var oe;if(Array.isArray(g[0])){W=ja(g);for(var O=1,R=1;R0)if(typeof O[0]=="number"){var I=Ne.allocType(G.dtype,O.length);Ha(I,O),W(I,re),Ne.freeType(I)}else if(Array.isArray(O[0])||de(O[0])){$=ja(O);var X=bn(O,$,G.dtype);W(X,re),Ne.freeType(X)}else n.raise("invalid buffer data")}else if(fr(O)){$=O.shape;var Y=O.stride,me=0,le=0,q=0,K=0;$.length===1?(me=$[0],le=1,q=Y[0],K=0):$.length===2?(me=$[0],le=$[1],q=Y[0],K=Y[1]):n.raise("invalid shape");var se=Array.isArray(O.data)?G.dtype:It(O.data),he=Ne.allocType(se,me*le);za(he,O.data,me,le,q,K,O.offset),W(he,re),Ne.freeType(he)}else n.raise("invalid data for buffer subdata");return Q}return M||Q(p),Q._reglType="buffer",Q._buffer=G,Q.subdata=oe,u.profile&&(Q.stats=G.stats),Q.destroy=function(){z(G)},Q}function k(){rr(E).forEach(function(p){p.buffer=e.createBuffer(),e.bindBuffer(p.type,p.buffer),e.bufferData(p.type,p.persistentData||p.byteLength,p.usage)})}return u.profile&&(t.getTotalBufferSize=function(){var p=0;return Object.keys(E).forEach(function(g){p+=E[g].stats.size}),p}),{create:P,createStream:N,destroyStream:U,clear:function(){rr(E).forEach(z),D.forEach(z)},getBuffer:function(p){return p&&p._buffer instanceof S?p._buffer:null},restore:k,_initBuffer:j}}var Os=0,Bs=0,Fs=1,Gs=1,Ns=4,Ds=4,Ar={points:Os,point:Bs,lines:Fs,line:Gs,triangles:Ns,triangle:Ds,"line loop":2,"line strip":3,"triangle strip":5,"triangle fan":6},Ps=0,Is=1,ct=4,Ms=5120,$r=5121,$a=5122,Xr=5123,Xa=5124,Cr=5125,En=34963,ks=35040,Us=35044;function js(e,t,u,x){var C={},E=0,S={uint8:$r,uint16:Xr};t.oes_element_index_uint&&(S.uint32=Cr);function D(k){this.id=E++,C[this.id]=this,this.buffer=k,this.primType=ct,this.vertCount=0,this.type=0}D.prototype.bind=function(){this.buffer.bind()};var N=[];function U(k){var p=N.pop();return p||(p=new D(u.create(null,En,!0,!1)._buffer)),j(p,k,ks,-1,-1,0,0),p}function V(k){N.push(k)}function j(k,p,g,M,Z,G,Q){k.buffer.bind();var W;if(p){var oe=Q;!Q&&(!de(p)||fr(p)&&!de(p.data))&&(oe=t.oes_element_index_uint?Cr:Xr),u._initBuffer(k.buffer,p,g,oe,3)}else e.bufferData(En,G,g),k.buffer.dtype=W||$r,k.buffer.usage=g,k.buffer.dimension=3,k.buffer.byteLength=G;if(W=Q,!Q){switch(k.buffer.dtype){case $r:case Ms:W=$r;break;case Xr:case $a:W=Xr;break;case Cr:case Xa:W=Cr;break;default:n.raise("unsupported type for element array")}k.buffer.dtype=W}k.type=W,n(W!==Cr||!!t.oes_element_index_uint,"32 bit element buffers not supported, enable oes_element_index_uint first");var O=Z;O<0&&(O=k.buffer.byteLength,W===Xr?O>>=1:W===Cr&&(O>>=2)),k.vertCount=O;var R=M;if(M<0){R=ct;var re=k.buffer.dimension;re===1&&(R=Ps),re===2&&(R=Is),re===3&&(R=ct)}k.primType=R}function z(k){x.elementsCount--,n(k.buffer!==null,"must not double destroy elements"),delete C[k.id],k.buffer.destroy(),k.buffer=null}function P(k,p){var g=u.create(null,En,!0),M=new D(g._buffer);x.elementsCount++;function Z(G){if(!G)g(),M.primType=ct,M.vertCount=0,M.type=$r;else if(typeof G=="number")g(G),M.primType=ct,M.vertCount=G|0,M.type=$r;else{var Q=null,W=Us,oe=-1,O=-1,R=0,re=0;Array.isArray(G)||de(G)||fr(G)?Q=G:(n.type(G,"object","invalid arguments for elements"),"data"in G&&(Q=G.data,n(Array.isArray(Q)||de(Q)||fr(Q),"invalid data for element buffer")),"usage"in G&&(n.parameter(G.usage,Pt,"invalid element buffer usage"),W=Pt[G.usage]),"primitive"in G&&(n.parameter(G.primitive,Ar,"invalid element buffer primitive"),oe=Ar[G.primitive]),"count"in G&&(n(typeof G.count=="number"&&G.count>=0,"invalid vertex count for elements"),O=G.count|0),"type"in G&&(n.parameter(G.type,S,"invalid buffer type"),re=S[G.type]),"length"in G?R=G.length|0:(R=O,re===Xr||re===$a?R*=2:(re===Cr||re===Xa)&&(R*=4))),j(M,Q,W,oe,O,R,re)}return Z}return Z(k),Z._reglType="elements",Z._elements=M,Z.subdata=function(G,Q){return g.subdata(G,Q),Z},Z.destroy=function(){z(M)},Z}return{create:P,createStream:U,destroyStream:V,getElements:function(k){return typeof k=="function"&&k._elements instanceof D?k._elements:null},clear:function(){rr(C).forEach(z)}}}var Ya=new Float32Array(1),Vs=new Uint32Array(Ya.buffer),Hs=5123;function Wa(e){for(var t=Ne.allocType(Hs,e.length),u=0;u>>31<<15,E=(x<<1>>>24)-127,S=x>>13&(1<<10)-1;if(E<-24)t[u]=C;else if(E<-14){var D=-14-E;t[u]=C+(S+(1<<10)>>D)}else E>15?t[u]=C+31744:t[u]=C+(E+15<<10)+S}return t}function Re(e){return Array.isArray(e)||de(e)}var qa=function(e){return!(e&e-1)&&!!e},zs=34467,cr=3553,An=34067,Mt=34069,Or=6408,xn=6406,kt=6407,lt=6409,Ut=6410,Qa=32854,Tn=32855,Ka=36194,$s=32819,Xs=32820,Ys=33635,Ws=34042,gn=6402,jt=34041,Sn=35904,wn=35906,Yr=36193,Ln=33776,Rn=33777,Cn=33778,On=33779,Za=35986,Ja=35987,ei=34798,ri=35840,ti=35841,ni=35842,ai=35843,ii=36196,Wr=5121,Bn=5123,Fn=5125,dt=5126,qs=10242,Qs=10243,Ks=10497,Gn=33071,Zs=33648,Js=10240,eu=10241,Nn=9728,ru=9729,Dn=9984,oi=9985,fi=9986,Pn=9987,tu=33170,Vt=4352,nu=4353,au=4354,iu=34046,ou=3317,fu=37440,su=37441,uu=37443,si=37444,mt=33984,cu=[Dn,fi,oi,Pn],Ht=[0,lt,Ut,kt,Or],nr={};nr[lt]=nr[xn]=nr[gn]=1,nr[jt]=nr[Ut]=2,nr[kt]=nr[Sn]=3,nr[Or]=nr[wn]=4;function qr(e){return"[object "+e+"]"}var ui=qr("HTMLCanvasElement"),ci=qr("OffscreenCanvas"),li=qr("CanvasRenderingContext2D"),di=qr("ImageBitmap"),mi=qr("HTMLImageElement"),hi=qr("HTMLVideoElement"),lu=Object.keys(vn).concat([ui,ci,li,di,mi,hi]),Qr=[];Qr[Wr]=1,Qr[dt]=4,Qr[Yr]=2,Qr[Bn]=2,Qr[Fn]=4;var ze=[];ze[Qa]=2,ze[Tn]=2,ze[Ka]=2,ze[jt]=4,ze[Ln]=.5,ze[Rn]=.5,ze[Cn]=1,ze[On]=1,ze[Za]=.5,ze[Ja]=1,ze[ei]=1,ze[ri]=.5,ze[ti]=.25,ze[ni]=.5,ze[ai]=.25,ze[ii]=.5;function pi(e){return Array.isArray(e)&&(e.length===0||typeof e[0]=="number")}function vi(e){if(!Array.isArray(e))return!1;var t=e.length;return!(t===0||!Re(e[0]))}function Br(e){return Object.prototype.toString.call(e)}function bi(e){return Br(e)===ui}function _i(e){return Br(e)===ci}function du(e){return Br(e)===li}function mu(e){return Br(e)===di}function hu(e){return Br(e)===mi}function pu(e){return Br(e)===hi}function In(e){if(!e)return!1;var t=Br(e);return lu.indexOf(t)>=0?!0:pi(e)||vi(e)||fr(e)}function yi(e){return vn[Object.prototype.toString.call(e)]|0}function vu(e,t){var u=t.length;switch(e.type){case Wr:case Bn:case Fn:case dt:var x=Ne.allocType(e.type,u);x.set(t),e.data=x;break;case Yr:e.data=Wa(t);break;default:n.raise("unsupported texture type, must specify a typed array")}}function Ei(e,t){return Ne.allocType(e.type===Yr?dt:e.type,t)}function Ai(e,t){e.type===Yr?(e.data=Wa(t),Ne.freeType(t)):e.data=t}function bu(e,t,u,x,C,E){for(var S=e.width,D=e.height,N=e.channels,U=S*D*N,V=Ei(e,U),j=0,z=0;z=1;)D+=S*N*N,N/=2;return D}else return S*u*x}function _u(e,t,u,x,C,E,S){var D={"don't care":Vt,"dont care":Vt,nice:au,fast:nu},N={repeat:Ks,clamp:Gn,mirror:Zs},U={nearest:Nn,linear:ru},V=ae({mipmap:Pn,"nearest mipmap nearest":Dn,"linear mipmap nearest":oi,"nearest mipmap linear":fi,"linear mipmap linear":Pn},U),j={none:0,browser:si},z={uint8:Wr,rgba4:$s,rgb565:Ys,"rgb5 a1":Xs},P={alpha:xn,luminance:lt,"luminance alpha":Ut,rgb:kt,rgba:Or,rgba4:Qa,"rgb5 a1":Tn,rgb565:Ka},k={};t.ext_srgb&&(P.srgb=Sn,P.srgba=wn),t.oes_texture_float&&(z.float32=z.float=dt),t.oes_texture_half_float&&(z.float16=z["half float"]=Yr),t.webgl_depth_texture&&(ae(P,{depth:gn,"depth stencil":jt}),ae(z,{uint16:Bn,uint32:Fn,"depth stencil":Ws})),t.webgl_compressed_texture_s3tc&&ae(k,{"rgb s3tc dxt1":Ln,"rgba s3tc dxt1":Rn,"rgba s3tc dxt3":Cn,"rgba s3tc dxt5":On}),t.webgl_compressed_texture_atc&&ae(k,{"rgb atc":Za,"rgba atc explicit alpha":Ja,"rgba atc interpolated alpha":ei}),t.webgl_compressed_texture_pvrtc&&ae(k,{"rgb pvrtc 4bppv1":ri,"rgb pvrtc 2bppv1":ti,"rgba pvrtc 4bppv1":ni,"rgba pvrtc 2bppv1":ai}),t.webgl_compressed_texture_etc1&&(k["rgb etc1"]=ii);var p=Array.prototype.slice.call(e.getParameter(zs));Object.keys(k).forEach(function(f){var T=k[f];p.indexOf(T)>=0&&(P[f]=T)});var g=Object.keys(P);u.textureFormats=g;var M=[];Object.keys(P).forEach(function(f){var T=P[f];M[T]=f});var Z=[];Object.keys(z).forEach(function(f){var T=z[f];Z[T]=f});var G=[];Object.keys(U).forEach(function(f){var T=U[f];G[T]=f});var Q=[];Object.keys(V).forEach(function(f){var T=V[f];Q[T]=f});var W=[];Object.keys(N).forEach(function(f){var T=N[f];W[T]=f});var oe=g.reduce(function(f,T){var y=P[T];return y===lt||y===xn||y===lt||y===Ut||y===gn||y===jt||t.ext_srgb&&(y===Sn||y===wn)?f[y]=y:y===Tn||T.indexOf("rgba")>=0?f[y]=Or:f[y]=kt,f},{});function O(){this.internalformat=Or,this.format=Or,this.type=Wr,this.compressed=!1,this.premultiplyAlpha=!1,this.flipY=!1,this.unpackAlignment=1,this.colorSpace=si,this.width=0,this.height=0,this.channels=0}function R(f,T){f.internalformat=T.internalformat,f.format=T.format,f.type=T.type,f.compressed=T.compressed,f.premultiplyAlpha=T.premultiplyAlpha,f.flipY=T.flipY,f.unpackAlignment=T.unpackAlignment,f.colorSpace=T.colorSpace,f.width=T.width,f.height=T.height,f.channels=T.channels}function re(f,T){if(!(typeof T!="object"||!T)){if("premultiplyAlpha"in T&&(n.type(T.premultiplyAlpha,"boolean","invalid premultiplyAlpha"),f.premultiplyAlpha=T.premultiplyAlpha),"flipY"in T&&(n.type(T.flipY,"boolean","invalid texture flip"),f.flipY=T.flipY),"alignment"in T&&(n.oneOf(T.alignment,[1,2,4,8],"invalid texture unpack alignment"),f.unpackAlignment=T.alignment),"colorSpace"in T&&(n.parameter(T.colorSpace,j,"invalid colorSpace"),f.colorSpace=j[T.colorSpace]),"type"in T){var y=T.type;n(t.oes_texture_float||!(y==="float"||y==="float32"),"you must enable the OES_texture_float extension in order to use floating point textures."),n(t.oes_texture_half_float||!(y==="half float"||y==="float16"),"you must enable the OES_texture_half_float extension in order to use 16-bit floating point textures."),n(t.webgl_depth_texture||!(y==="uint16"||y==="uint32"||y==="depth stencil"),"you must enable the WEBGL_depth_texture extension in order to use depth/stencil textures."),n.parameter(y,z,"invalid texture type"),f.type=z[y]}var ee=f.width,ye=f.height,a=f.channels,r=!1;"shape"in T?(n(Array.isArray(T.shape)&&T.shape.length>=2,"shape must be an array"),ee=T.shape[0],ye=T.shape[1],T.shape.length===3&&(a=T.shape[2],n(a>0&&a<=4,"invalid number of channels"),r=!0),n(ee>=0&&ee<=u.maxTextureSize,"invalid width"),n(ye>=0&&ye<=u.maxTextureSize,"invalid height")):("radius"in T&&(ee=ye=T.radius,n(ee>=0&&ee<=u.maxTextureSize,"invalid radius")),"width"in T&&(ee=T.width,n(ee>=0&&ee<=u.maxTextureSize,"invalid width")),"height"in T&&(ye=T.height,n(ye>=0&&ye<=u.maxTextureSize,"invalid height")),"channels"in T&&(a=T.channels,n(a>0&&a<=4,"invalid number of channels"),r=!0)),f.width=ee|0,f.height=ye|0,f.channels=a|0;var c=!1;if("format"in T){var h=T.format;n(t.webgl_depth_texture||!(h==="depth"||h==="depth stencil"),"you must enable the WEBGL_depth_texture extension in order to use depth/stencil textures."),n.parameter(h,P,"invalid texture format");var v=f.internalformat=P[h];f.format=oe[v],h in z&&("type"in T||(f.type=z[h])),h in k&&(f.compressed=!0),c=!0}!r&&c?f.channels=nr[f.format]:r&&!c?f.channels!==Ht[f.format]&&(f.format=f.internalformat=Ht[f.channels]):c&&r&&n(f.channels===nr[f.format],"number of channels inconsistent with specified format")}}function $(f){e.pixelStorei(fu,f.flipY),e.pixelStorei(su,f.premultiplyAlpha),e.pixelStorei(uu,f.colorSpace),e.pixelStorei(ou,f.unpackAlignment)}function I(){O.call(this),this.xOffset=0,this.yOffset=0,this.data=null,this.needsFree=!1,this.element=null,this.needsCopy=!1}function X(f,T){var y=null;if(In(T)?y=T:T&&(n.type(T,"object","invalid pixel data type"),re(f,T),"x"in T&&(f.xOffset=T.x|0),"y"in T&&(f.yOffset=T.y|0),In(T.data)&&(y=T.data)),n(!f.compressed||y instanceof Uint8Array,"compressed texture data must be stored in a uint8array"),T.copy){n(!y,"can not specify copy and data field for the same texture");var ee=C.viewportWidth,ye=C.viewportHeight;f.width=f.width||ee-f.xOffset,f.height=f.height||ye-f.yOffset,f.needsCopy=!0,n(f.xOffset>=0&&f.xOffset=0&&f.yOffset0&&f.width<=ee&&f.height>0&&f.height<=ye,"copy texture read out of bounds")}else if(!y)f.width=f.width||1,f.height=f.height||1,f.channels=f.channels||4;else if(de(y))f.channels=f.channels||4,f.data=y,!("type"in T)&&f.type===Wr&&(f.type=yi(y));else if(pi(y))f.channels=f.channels||4,vu(f,y),f.alignment=1,f.needsFree=!0;else if(fr(y)){var a=y.data;!Array.isArray(a)&&f.type===Wr&&(f.type=yi(a));var r=y.shape,c=y.stride,h,v,d,l,m,i;r.length===3?(d=r[2],i=c[2]):(n(r.length===2,"invalid ndarray pixel data, must be 2 or 3D"),d=1,i=1),h=r[0],v=r[1],l=c[0],m=c[1],f.alignment=1,f.width=h,f.height=v,f.channels=d,f.format=f.internalformat=Ht[d],f.needsFree=!0,bu(f,a,l,m,i,y.offset)}else if(bi(y)||_i(y)||du(y))bi(y)||_i(y)?f.element=y:f.element=y.canvas,f.width=f.element.width,f.height=f.element.height,f.channels=4;else if(mu(y))f.element=y,f.width=y.width,f.height=y.height,f.channels=4;else if(hu(y))f.element=y,f.width=y.naturalWidth,f.height=y.naturalHeight,f.channels=4;else if(pu(y))f.element=y,f.width=y.videoWidth,f.height=y.videoHeight,f.channels=4;else if(vi(y)){var s=f.width||y[0].length,o=f.height||y.length,_=f.channels;Re(y[0][0])?_=_||y[0][0].length:_=_||1;for(var b=Dt.shape(y),L=1,B=0;B=0,"oes_texture_float extension not enabled"):f.type===Yr&&n(u.extensions.indexOf("oes_texture_half_float")>=0,"oes_texture_half_float extension not enabled")}function Y(f,T,y){var ee=f.element,ye=f.data,a=f.internalformat,r=f.format,c=f.type,h=f.width,v=f.height;$(f),ee?e.texImage2D(T,y,r,r,c,ee):f.compressed?e.compressedTexImage2D(T,y,a,h,v,0,ye):f.needsCopy?(x(),e.copyTexImage2D(T,y,r,f.xOffset,f.yOffset,h,v,0)):e.texImage2D(T,y,r,h,v,0,r,c,ye||null)}function me(f,T,y,ee,ye){var a=f.element,r=f.data,c=f.internalformat,h=f.format,v=f.type,d=f.width,l=f.height;$(f),a?e.texSubImage2D(T,ye,y,ee,h,v,a):f.compressed?e.compressedTexSubImage2D(T,ye,y,ee,c,d,l,r):f.needsCopy?(x(),e.copyTexSubImage2D(T,ye,y,ee,f.xOffset,f.yOffset,d,l)):e.texSubImage2D(T,ye,y,ee,d,l,h,v,r)}var le=[];function q(){return le.pop()||new I}function K(f){f.needsFree&&Ne.freeType(f.data),I.call(f),le.push(f)}function se(){O.call(this),this.genMipmaps=!1,this.mipmapHint=Vt,this.mipmask=0,this.images=Array(16)}function he(f,T,y){var ee=f.images[0]=q();f.mipmask=1,ee.width=f.width=T,ee.height=f.height=y,ee.channels=f.channels=4}function Ee(f,T){var y=null;if(In(T))y=f.images[0]=q(),R(y,f),X(y,T),f.mipmask=1;else if(re(f,T),Array.isArray(T.mipmap))for(var ee=T.mipmap,ye=0;ye>=ye,y.height>>=ye,X(y,ee[ye]),f.mipmask|=1<=0&&!("faces"in T)&&(f.genMipmaps=!0)}if("mag"in T){var ee=T.mag;n.parameter(ee,U),f.magFilter=U[ee]}var ye=f.wrapS,a=f.wrapT;if("wrap"in T){var r=T.wrap;typeof r=="string"?(n.parameter(r,N),ye=a=N[r]):Array.isArray(r)&&(n.parameter(r[0],N),n.parameter(r[1],N),ye=N[r[0]],a=N[r[1]])}else{if("wrapS"in T){var c=T.wrapS;n.parameter(c,N),ye=N[c]}if("wrapT"in T){var h=T.wrapT;n.parameter(h,N),a=N[h]}}if(f.wrapS=ye,f.wrapT=a,"anisotropic"in T){var v=T.anisotropic;n(typeof v=="number"&&v>=1&&v<=u.maxAnisotropic,"aniso samples must be between 1 and "),f.anisotropic=T.anisotropic}if("mipmap"in T){var d=!1;switch(typeof T.mipmap){case"string":n.parameter(T.mipmap,D,"invalid mipmap hint"),f.mipmapHint=D[T.mipmap],f.genMipmaps=!0,d=!0;break;case"boolean":d=f.genMipmaps=T.mipmap;break;case"object":n(Array.isArray(T.mipmap),"invalid mipmap type"),f.genMipmaps=!1,d=!0;break;default:n.raise("invalid mipmap type")}d&&!("min"in T)&&(f.minFilter=Dn)}}function ke(f,T){e.texParameteri(T,eu,f.minFilter),e.texParameteri(T,Js,f.magFilter),e.texParameteri(T,qs,f.wrapS),e.texParameteri(T,Qs,f.wrapT),t.ext_texture_filter_anisotropic&&e.texParameteri(T,iu,f.anisotropic),f.genMipmaps&&(e.hint(tu,f.mipmapHint),e.generateMipmap(T))}var Ue=0,He={},$e=u.maxTextureUnits,Fe=Array($e).map(function(){return null});function be(f){O.call(this),this.mipmask=0,this.internalformat=Or,this.id=Ue++,this.refCount=1,this.target=f,this.texture=e.createTexture(),this.unit=-1,this.bindCount=0,this.texInfo=new Le,S.profile&&(this.stats={size:0})}function Xe(f){e.activeTexture(mt),e.bindTexture(f.target,f.texture)}function Se(){var f=Fe[0];f?e.bindTexture(f.target,f.texture):e.bindTexture(cr,null)}function fe(f){var T=f.texture;n(T,"must not double destroy texture");var y=f.unit,ee=f.target;y>=0&&(e.activeTexture(mt+y),e.bindTexture(ee,null),Fe[y]=null),e.deleteTexture(T),f.texture=null,f.params=null,f.pixels=null,f.refCount=0,delete He[f.id],E.textureCount--}ae(be.prototype,{bind:function(){var f=this;f.bindCount+=1;var T=f.unit;if(T<0){for(var y=0;y<$e;++y){var ee=Fe[y];if(ee){if(ee.bindCount>0)continue;ee.unit=-1}Fe[y]=f,T=y;break}T>=$e&&n.raise("insufficient number of texture units"),S.profile&&E.maxTextureUnits>m)-d,i.height=i.height||(y.height>>m)-l,n(y.type===i.type&&y.format===i.format&&y.internalformat===i.internalformat,"incompatible format for texture.subimage"),n(d>=0&&l>=0&&d+i.width<=y.width&&l+i.height<=y.height,"texture.subimage write out of bounds"),n(y.mipmask&1<>d;++d){var l=h>>d,m=v>>d;if(!l||!m)break;e.texImage2D(cr,d,y.format,l,m,0,y.format,y.type,null)}return Se(),S.profile&&(y.stats.size=zt(y.internalformat,y.type,h,v,!1,!1)),ee}return ee(f,T),ee.subimage=ye,ee.resize=a,ee._reglType="texture2d",ee._texture=y,S.profile&&(ee.stats=y.stats),ee.destroy=function(){y.decRef()},ee}function ge(f,T,y,ee,ye,a){var r=new be(An);He[r.id]=r,E.cubeCount++;var c=new Array(6);function h(l,m,i,s,o,_){var b,L=r.texInfo;for(Le.call(L),b=0;b<6;++b)c[b]=xe();if(typeof l=="number"||!l){var B=l|0||1;for(b=0;b<6;++b)he(c[b],B,B)}else if(typeof l=="object")if(m)Ee(c[0],l),Ee(c[1],m),Ee(c[2],i),Ee(c[3],s),Ee(c[4],o),Ee(c[5],_);else if(Pe(L,l),re(r,l),"faces"in l){var H=l.faces;for(n(Array.isArray(H)&&H.length===6,"cube faces must be a length 6 array"),b=0;b<6;++b)n(typeof H[b]=="object"&&!!H[b],"invalid input for cube map face"),R(c[b],r),Ee(c[b],H[b])}else for(b=0;b<6;++b)Ee(c[b],l);else n.raise("invalid arguments to cube map");for(R(r,c[0]),n.optional(function(){u.npotTextureCube||n(qa(r.width)&&qa(r.height),"your browser does not support non power or two texture dimensions")}),L.genMipmaps?r.mipmask=(c[0].width<<1)-1:r.mipmask=c[0].mipmask,n.textureCube(r,L,c,u),r.internalformat=c[0].internalformat,h.width=c[0].width,h.height=c[0].height,Xe(r),b=0;b<6;++b)Ce(c[b],Mt+b);for(ke(L,An),Se(),S.profile&&(r.stats.size=zt(r.internalformat,r.type,h.width,h.height,L.genMipmaps,!0)),h.format=M[r.internalformat],h.type=Z[r.type],h.mag=G[L.magFilter],h.min=Q[L.minFilter],h.wrapS=W[L.wrapS],h.wrapT=W[L.wrapT],b=0;b<6;++b)Me(c[b]);return h}function v(l,m,i,s,o){n(!!m,"must specify image data"),n(typeof l=="number"&&l===(l|0)&&l>=0&&l<6,"invalid face");var _=i|0,b=s|0,L=o|0,B=q();return R(B,r),B.width=0,B.height=0,X(B,m),B.width=B.width||(r.width>>L)-_,B.height=B.height||(r.height>>L)-b,n(r.type===B.type&&r.format===B.format&&r.internalformat===B.internalformat,"incompatible format for texture.subimage"),n(_>=0&&b>=0&&_+B.width<=r.width&&b+B.height<=r.height,"texture.subimage write out of bounds"),n(r.mipmask&1<>s;++s)e.texImage2D(Mt+i,s,r.format,m>>s,m>>s,0,r.format,r.type,null);return Se(),S.profile&&(r.stats.size=zt(r.internalformat,r.type,h.width,h.height,!1,!0)),h}}return h(f,T,y,ee,ye,a),h.subimage=v,h.resize=d,h._reglType="textureCube",h._texture=r,S.profile&&(h.stats=r.stats),h.destroy=function(){r.decRef()},h}function Ge(){for(var f=0;f<$e;++f)e.activeTexture(mt+f),e.bindTexture(cr,null),Fe[f]=null;rr(He).forEach(fe),E.cubeCount=0,E.textureCount=0}S.profile&&(E.getTotalTextureSize=function(){var f=0;return Object.keys(He).forEach(function(T){f+=He[T].stats.size}),f});function dr(){for(var f=0;f<$e;++f){var T=Fe[f];T&&(T.bindCount=0,T.unit=-1,Fe[f]=null)}rr(He).forEach(function(y){y.texture=e.createTexture(),e.bindTexture(y.target,y.texture);for(var ee=0;ee<32;++ee)if((y.mipmask&1<>ee,y.height>>ee,0,y.internalformat,y.type,null);else for(var ye=0;ye<6;++ye)e.texImage2D(Mt+ye,ee,y.internalformat,y.width>>ee,y.height>>ee,0,y.internalformat,y.type,null);ke(y.texInfo,y.target)})}function Mr(){for(var f=0;f<$e;++f){var T=Fe[f];T&&(T.bindCount=0,T.unit=-1,Fe[f]=null),e.activeTexture(mt+f),e.bindTexture(cr,null),e.bindTexture(An,null)}}return{create2D:Ae,createCube:ge,clear:Ge,getTexture:function(f){return null},restore:dr,refresh:Mr}}var xr=36161,$t=32854,xi=32855,Ti=36194,gi=33189,Si=36168,wi=34041,Li=35907,Ri=34836,Ci=34842,Oi=34843,sr=[];sr[$t]=2,sr[xi]=2,sr[Ti]=2,sr[gi]=2,sr[Si]=1,sr[wi]=4,sr[Li]=4,sr[Ri]=16,sr[Ci]=8,sr[Oi]=6;function Bi(e,t,u){return sr[e]*t*u}var yu=function(e,t,u,x,C){var E={rgba4:$t,rgb565:Ti,"rgb5 a1":xi,depth:gi,stencil:Si,"depth stencil":wi};t.ext_srgb&&(E.srgba=Li),t.ext_color_buffer_half_float&&(E.rgba16f=Ci,E.rgb16f=Oi),t.webgl_color_buffer_float&&(E.rgba32f=Ri);var S=[];Object.keys(E).forEach(function(P){var k=E[P];S[k]=P});var D=0,N={};function U(P){this.id=D++,this.refCount=1,this.renderbuffer=P,this.format=$t,this.width=0,this.height=0,C.profile&&(this.stats={size:0})}U.prototype.decRef=function(){--this.refCount<=0&&V(this)};function V(P){var k=P.renderbuffer;n(k,"must not double destroy renderbuffer"),e.bindRenderbuffer(xr,null),e.deleteRenderbuffer(k),P.renderbuffer=null,P.refCount=0,delete N[P.id],x.renderbufferCount--}function j(P,k){var p=new U(e.createRenderbuffer());N[p.id]=p,x.renderbufferCount++;function g(Z,G){var Q=0,W=0,oe=$t;if(typeof Z=="object"&&Z){var O=Z;if("shape"in O){var R=O.shape;n(Array.isArray(R)&&R.length>=2,"invalid renderbuffer shape"),Q=R[0]|0,W=R[1]|0}else"radius"in O&&(Q=W=O.radius|0),"width"in O&&(Q=O.width|0),"height"in O&&(W=O.height|0);"format"in O&&(n.parameter(O.format,E,"invalid renderbuffer format"),oe=E[O.format])}else typeof Z=="number"?(Q=Z|0,typeof G=="number"?W=G|0:W=Q):Z?n.raise("invalid arguments to renderbuffer constructor"):Q=W=1;if(n(Q>0&&W>0&&Q<=u.maxRenderbufferSize&&W<=u.maxRenderbufferSize,"invalid renderbuffer size"),!(Q===p.width&&W===p.height&&oe===p.format))return g.width=p.width=Q,g.height=p.height=W,p.format=oe,e.bindRenderbuffer(xr,p.renderbuffer),e.renderbufferStorage(xr,oe,Q,W),n(e.getError()===0,"invalid render buffer format"),C.profile&&(p.stats.size=Bi(p.format,p.width,p.height)),g.format=S[p.format],g}function M(Z,G){var Q=Z|0,W=G|0||Q;return Q===p.width&&W===p.height||(n(Q>0&&W>0&&Q<=u.maxRenderbufferSize&&W<=u.maxRenderbufferSize,"invalid renderbuffer size"),g.width=p.width=Q,g.height=p.height=W,e.bindRenderbuffer(xr,p.renderbuffer),e.renderbufferStorage(xr,p.format,Q,W),n(e.getError()===0,"invalid render buffer format"),C.profile&&(p.stats.size=Bi(p.format,p.width,p.height))),g}return g(P,k),g.resize=M,g._reglType="renderbuffer",g._renderbuffer=p,C.profile&&(g.stats=p.stats),g.destroy=function(){p.decRef()},g}C.profile&&(x.getTotalRenderbufferSize=function(){var P=0;return Object.keys(N).forEach(function(k){P+=N[k].stats.size}),P});function z(){rr(N).forEach(function(P){P.renderbuffer=e.createRenderbuffer(),e.bindRenderbuffer(xr,P.renderbuffer),e.renderbufferStorage(xr,P.format,P.width,P.height)}),e.bindRenderbuffer(xr,null)}return{create:j,clear:function(){rr(N).forEach(V)},restore:z}},pr=36160,Mn=36161,Fr=3553,Xt=34069,Fi=36064,Gi=36096,Ni=36128,Di=33306,Pi=36053,Eu=36054,Au=36055,xu=36057,Tu=36061,gu=36193,Su=5121,wu=5126,Ii=6407,Mi=6408,Lu=6402,Ru=[Ii,Mi],kn=[];kn[Mi]=4,kn[Ii]=3;var Yt=[];Yt[Su]=1,Yt[wu]=4,Yt[gu]=2;var Cu=32854,Ou=32855,Bu=36194,Fu=33189,Gu=36168,ki=34041,Nu=35907,Du=34836,Pu=34842,Iu=34843,Mu=[Cu,Ou,Bu,Nu,Pu,Iu,Du],Kr={};Kr[Pi]="complete",Kr[Eu]="incomplete attachment",Kr[xu]="incomplete dimensions",Kr[Au]="incomplete, missing attachment",Kr[Tu]="unsupported";function ku(e,t,u,x,C,E){var S={cur:null,next:null,dirty:!1,setFBO:null},D=["rgba"],N=["rgba4","rgb565","rgb5 a1"];t.ext_srgb&&N.push("srgba"),t.ext_color_buffer_half_float&&N.push("rgba16f","rgb16f"),t.webgl_color_buffer_float&&N.push("rgba32f");var U=["uint8"];t.oes_texture_half_float&&U.push("half float","float16"),t.oes_texture_float&&U.push("float","float32");function V(I,X,Y){this.target=I,this.texture=X,this.renderbuffer=Y;var me=0,le=0;X?(me=X.width,le=X.height):Y&&(me=Y.width,le=Y.height),this.width=me,this.height=le}function j(I){I&&(I.texture&&I.texture._texture.decRef(),I.renderbuffer&&I.renderbuffer._renderbuffer.decRef())}function z(I,X,Y){if(!!I)if(I.texture){var me=I.texture._texture,le=Math.max(1,me.width),q=Math.max(1,me.height);n(le===X&&q===Y,"inconsistent width/height for supplied texture"),me.refCount+=1}else{var K=I.renderbuffer._renderbuffer;n(K.width===X&&K.height===Y,"inconsistent width/height for renderbuffer"),K.refCount+=1}}function P(I,X){X&&(X.texture?e.framebufferTexture2D(pr,I,X.target,X.texture._texture.texture,0):e.framebufferRenderbuffer(pr,I,Mn,X.renderbuffer._renderbuffer.renderbuffer))}function k(I){var X=Fr,Y=null,me=null,le=I;typeof I=="object"&&(le=I.data,"target"in I&&(X=I.target|0)),n.type(le,"function","invalid attachment data");var q=le._reglType;return q==="texture2d"?(Y=le,n(X===Fr)):q==="textureCube"?(Y=le,n(X>=Xt&&X=2,"invalid shape for framebuffer"),he=Xe[0],Ee=Xe[1]}else"radius"in be&&(he=Ee=be.radius),"width"in be&&(he=be.width),"height"in be&&(Ee=be.height);("color"in be||"colors"in be)&&(xe=be.color||be.colors,Array.isArray(xe)&&n(xe.length===1||t.webgl_draw_buffers,"multiple render targets not supported")),xe||("colorCount"in be&&(ke=be.colorCount|0,n(ke>0,"invalid color buffer count")),"colorTexture"in be&&(Me=!!be.colorTexture,Le="rgba4"),"colorType"in be&&(Pe=be.colorType,Me?(n(t.oes_texture_float||!(Pe==="float"||Pe==="float32"),"you must enable OES_texture_float in order to use floating point framebuffer objects"),n(t.oes_texture_half_float||!(Pe==="half float"||Pe==="float16"),"you must enable OES_texture_half_float in order to use 16-bit floating point framebuffer objects")):Pe==="half float"||Pe==="float16"?(n(t.ext_color_buffer_half_float,"you must enable EXT_color_buffer_half_float to use 16-bit render buffers"),Le="rgba16f"):(Pe==="float"||Pe==="float32")&&(n(t.webgl_color_buffer_float,"you must enable WEBGL_color_buffer_float in order to use 32-bit floating point renderbuffers"),Le="rgba32f"),n.oneOf(Pe,U,"invalid color type")),"colorFormat"in be&&(Le=be.colorFormat,D.indexOf(Le)>=0?Me=!0:N.indexOf(Le)>=0?Me=!1:n.optional(function(){Me?n.oneOf(be.colorFormat,D,"invalid color format for texture"):n.oneOf(be.colorFormat,N,"invalid color format for renderbuffer")}))),("depthTexture"in be||"depthStencilTexture"in be)&&(Fe=!!(be.depthTexture||be.depthStencilTexture),n(!Fe||t.webgl_depth_texture,"webgl_depth_texture extension not supported")),"depth"in be&&(typeof be.depth=="boolean"?Ce=be.depth:(Ue=be.depth,Be=!1)),"stencil"in be&&(typeof be.stencil=="boolean"?Be=be.stencil:(He=be.stencil,Ce=!1)),"depthStencil"in be&&(typeof be.depthStencil=="boolean"?Ce=Be=be.depthStencil:($e=be.depthStencil,Ce=!1,Be=!1))}var Se=null,fe=null,Ae=null,ge=null;if(Array.isArray(xe))Se=xe.map(k);else if(xe)Se=[k(xe)];else for(Se=new Array(ke),se=0;se=0||Se[se].renderbuffer&&Mu.indexOf(Se[se].renderbuffer._renderbuffer.format)>=0,"framebuffer color attachment "+se+" is invalid"),Se[se]&&Se[se].texture){var dr=kn[Se[se].texture._texture.format]*Yt[Se[se].texture._texture.type];Ge===null?Ge=dr:n(Ge===dr,"all color attachments much have the same number of bits per pixel.")}return z(fe,he,Ee),n(!fe||fe.texture&&fe.texture._texture.format===Lu||fe.renderbuffer&&fe.renderbuffer._renderbuffer.format===Fu,"invalid depth attachment for framebuffer object"),z(Ae,he,Ee),n(!Ae||Ae.renderbuffer&&Ae.renderbuffer._renderbuffer.format===Gu,"invalid stencil attachment for framebuffer object"),z(ge,he,Ee),n(!ge||ge.texture&&ge.texture._texture.format===ki||ge.renderbuffer&&ge.renderbuffer._renderbuffer.format===ki,"invalid depth-stencil attachment for framebuffer object"),W(Y),Y.width=he,Y.height=Ee,Y.colorAttachments=Se,Y.depthAttachment=fe,Y.stencilAttachment=Ae,Y.depthStencilAttachment=ge,me.color=Se.map(g),me.depth=g(fe),me.stencil=g(Ae),me.depthStencil=g(ge),me.width=Y.width,me.height=Y.height,O(Y),me}function le(q,K){n(S.next!==Y,"can not resize a framebuffer which is currently in use");var se=Math.max(q|0,1),he=Math.max(K|0||se,1);if(se===Y.width&&he===Y.height)return me;for(var Ee=Y.colorAttachments,Ce=0;Ce=2,"invalid shape for framebuffer"),n(Me[0]===Me[1],"cube framebuffer must be square"),se=Me[0]}else"radius"in xe&&(se=xe.radius|0),"width"in xe?(se=xe.width|0,"height"in xe&&n(xe.height===se,"must be square")):"height"in xe&&(se=xe.height|0);("color"in xe||"colors"in xe)&&(he=xe.color||xe.colors,Array.isArray(he)&&n(he.length===1||t.webgl_draw_buffers,"multiple render targets not supported")),he||("colorCount"in xe&&(Be=xe.colorCount|0,n(Be>0,"invalid color buffer count")),"colorType"in xe&&(n.oneOf(xe.colorType,U,"invalid color type"),Ce=xe.colorType),"colorFormat"in xe&&(Ee=xe.colorFormat,n.oneOf(xe.colorFormat,D,"invalid color format for texture"))),"depth"in xe&&(K.depth=xe.depth),"stencil"in xe&&(K.stencil=xe.stencil),"depthStencil"in xe&&(K.depthStencil=xe.depthStencil)}var Le;if(he)if(Array.isArray(he))for(Le=[],q=0;q0&&(K.depth=X[0].depth,K.stencil=X[0].stencil,K.depthStencil=X[0].depthStencil),X[q]?X[q](K):X[q]=R(K)}return ae(Y,{width:se,height:se,color:Le})}function me(le){var q,K=le|0;if(n(K>0&&K<=u.maxCubeMapSize,"invalid radius for cube fbo"),K===Y.width)return Y;var se=Y.color;for(q=0;q{for(var Ce=Object.keys($),Be=0;Be=0,'invalid option for vao: "'+Ce[Be]+'" valid options are '+ji)}),n(Array.isArray(I),"attributes must be an array")}n(I.length0,"must specify at least one attribute");var Y={},me=R.attributes;me.length=I.length;for(var le=0;le=se.byteLength?he.subdata(se):(he.destroy(),R.buffers[le]=null)),R.buffers[le]||(he=R.buffers[le]=C.create(q,Ui,!1,!0)),K.buffer=C.getBuffer(he),K.size=K.buffer.dimension|0,K.normalized=!1,K.type=K.buffer.dtype,K.offset=0,K.stride=0,K.divisor=0,K.state=1,Y[le]=1}else C.getBuffer(q)?(K.buffer=C.getBuffer(q),K.size=K.buffer.dimension|0,K.normalized=!1,K.type=K.buffer.dtype,K.offset=0,K.stride=0,K.divisor=0,K.state=1):C.getBuffer(q.buffer)?(K.buffer=C.getBuffer(q.buffer),K.size=(+q.size||K.buffer.dimension)|0,K.normalized=!!q.normalized||!1,"type"in q?(n.parameter(q.type,Rr,"invalid buffer type"),K.type=Rr[q.type]):K.type=K.buffer.dtype,K.offset=(q.offset||0)|0,K.stride=(q.stride||0)|0,K.divisor=(q.divisor||0)|0,K.state=1,n(K.size>=1&&K.size<=4,"size must be between 1 and 4"),n(K.offset>=0,"invalid offset"),n(K.stride>=0&&K.stride<=255,"stride must be between 0 and 255"),n(K.divisor>=0,"divisor must be positive"),n(!K.divisor||!!t.angle_instanced_arrays,"ANGLE_instanced_arrays must be enabled to use divisor")):"x"in q?(n(le>0,"first attribute must not be a constant"),K.x=+q.x||0,K.y=+q.y||0,K.z=+q.z||0,K.w=+q.w||0,K.state=2):n(!1,"invalid attribute spec for location "+le)}for(var Ee=0;Ee1)for(var $=0;$1&&(X=X.replace("[0]","")),D(re,new S(X,t.id(X),e.getUniformLocation(oe,X),G))}var Y=e.getProgramParameter(oe,zu);x.profile&&(p.stats.attributesCount=Y);var me=p.attributes;for(Z=0;Zp&&(p=g.stats.uniformsCount)}),p},u.getMaxAttributesCount=function(){var p=0;return V.forEach(function(g){g.stats.attributesCount>p&&(p=g.stats.attributesCount)}),p});function k(){C={},E={};for(var p=0;p=0,"missing vertex shader",M),n.command(g>=0,"missing fragment shader",M);var G=U[g];G||(G=U[g]={});var Q=G[p];if(Q&&(Q.refCount++,!Z))return Q;var W=new z(g,p);return u.shaderCount++,P(W,M,Z),Q||(G[p]=W),V.push(W),ae(W,{destroy:function(){if(W.refCount--,W.refCount<=0){e.deleteProgram(W.program);var oe=V.indexOf(W);V.splice(oe,1),u.shaderCount--}G[W.vertId].refCount<=0&&(e.deleteShader(E[W.vertId]),delete E[W.vertId],delete U[W.fragId][W.vertId]),Object.keys(U[W.fragId]).length||(e.deleteShader(C[W.fragId]),delete C[W.fragId],delete U[W.fragId])}})},restore:k,shader:N,frag:-1,vert:-1}}var Xu=6408,ht=5121,Yu=3333,qt=5126;function Wu(e,t,u,x,C,E,S){function D(V){var j;t.next===null?(n(C.preserveDrawingBuffer,'you must create a webgl context with "preserveDrawingBuffer":true in order to read pixels from the drawing buffer'),j=ht):(n(t.next.colorAttachments[0].texture!==null,"You cannot read from a renderbuffer"),j=t.next.colorAttachments[0].texture._texture.type,n.optional(function(){E.oes_texture_float?(n(j===ht||j===qt,"Reading from a framebuffer is only allowed for the types 'uint8' and 'float'"),j===qt&&n(S.readFloat,"Reading 'float' values is not permitted in your browser. For a fallback, please see: https://www.npmjs.com/package/glsl-read-float")):n(j===ht,"Reading from a framebuffer is only allowed for the type 'uint8'")}));var z=0,P=0,k=x.framebufferWidth,p=x.framebufferHeight,g=null;de(V)?g=V:V&&(n.type(V,"object","invalid arguments to regl.read()"),z=V.x|0,P=V.y|0,n(z>=0&&z=0&&P0&&k+z<=x.framebufferWidth,"invalid width for read pixels"),n(p>0&&p+P<=x.framebufferHeight,"invalid height for read pixels"),u();var M=k*p*4;return g||(j===ht?g=new Uint8Array(M):j===qt&&(g=g||new Float32Array(M))),n.isTypedArray(g,"data buffer for regl.read() must be a typedarray"),n(g.byteLength>=M,"data buffer for regl.read() too small"),e.pixelStorei(Yu,4),e.readPixels(z,P,k,p,Xu,j,g),g}function N(V){var j;return t.setFBO({framebuffer:V.framebuffer},function(){j=D(V)}),j}function U(V){return!V||!("framebuffer"in V)?D(V):N(V)}return U}function Zr(e){return Array.prototype.slice.call(e)}function Jr(e){return Zr(e).join("")}function qu(){var e=0,t=[],u=[];function x(j){for(var z=0;z0&&(j.push(p,"="),j.push.apply(j,Zr(arguments)),j.push(";")),p}return ae(z,{def:k,toString:function(){return Jr([P.length>0?"var "+P.join(",")+";":"",Jr(j)])}})}function E(){var j=C(),z=C(),P=j.toString,k=z.toString;function p(g,M){z(g,M,"=",j.def(g,M),";")}return ae(function(){j.apply(j,Zr(arguments))},{def:j.def,entry:j,exit:z,save:p,set:function(g,M,Z){p(g,M),j(g,M,"=",Z,";")},toString:function(){return P()+k()}})}function S(){var j=Jr(arguments),z=E(),P=E(),k=z.toString,p=P.toString;return ae(z,{then:function(){return z.apply(z,Zr(arguments)),this},else:function(){return P.apply(P,Zr(arguments)),this},toString:function(){var g=p();return g&&(g="else{"+g+"}"),Jr(["if(",j,"){",k(),"}",g])}})}var D=C(),N={};function U(j,z){var P=[];function k(){var G="a"+P.length;return P.push(G),G}z=z||0;for(var p=0;p":516,notequal:517,"!=":517,"!==":517,gequal:518,">=":518,always:519},gr={"0":0,zero:0,keep:7680,replace:7681,increment:7682,decrement:7683,"increment wrap":34055,"decrement wrap":34056,invert:5386},_o={frag:Ju,vert:ec},ua={cw:lo,ccw:sa};function cn(e){return Array.isArray(e)||de(e)||fr(e)}function yo(e){return e.sort(function(t,u){return t===vr?-1:u===vr?1:t=1,x>=2,t)}else if(u===Qt){var C=e.data;return new je(C.thisDep,C.contextDep,C.propDep,t)}else{if(u===zi)return new je(!1,!1,!1,t);if(u===$i){for(var E=!1,S=!1,D=!1,N=0;N=1&&(S=!0),V>=2&&(D=!0)}else U.type===Qt&&(E=E||U.data.thisDep,S=S||U.data.contextDep,D=D||U.data.propDep)}return new je(E,S,D,t)}else return new je(u===$n,u===zn,u===Hn,t)}}var Eo=new je(!1,!1,!1,function(){});function vc(e,t,u,x,C,E,S,D,N,U,V,j,z,P,k){var p=U.Record,g={add:32774,subtract:32778,"reverse subtract":32779};u.ext_blend_minmax&&(g.min=lc,g.max=dc);var M=u.angle_instanced_arrays,Z=u.webgl_draw_buffers,G=u.oes_vertex_array_object,Q={dirty:!0,profile:k.profile},W={},oe=[],O={},R={};function re(a){return a.replace(".","_")}function $(a,r,c){var h=re(a);oe.push(a),W[h]=Q[h]=!!c,O[h]=r}function I(a,r,c){var h=re(a);oe.push(a),Array.isArray(c)?(Q[h]=c.slice(),W[h]=c.slice()):Q[h]=W[h]=c,R[h]=r}$(Xi,ac),$(Yi,nc),I(Wi,"blendColor",[0,0,0,0]),I(Xn,"blendEquationSeparate",[po,po]),I(Yn,"blendFuncSeparate",[ho,mo,ho,mo]),$(qi,oc,!0),I(Qi,"depthFunc",hc),I(Ki,"depthRange",[0,1]),I(Zi,"depthMask",!0),I(Wn,Wn,[!0,!0,!0,!0]),$(Ji,tc),I(eo,"cullFace",Ir),I(qn,qn,sa),I(Qn,Qn,1),$(ro,sc),I(Kn,"polygonOffset",[0,0]),$(to,uc),$(no,cc),I(Zn,"sampleCoverage",[1,!1]),$(ao,ic),I(io,"stencilMask",-1),I(Jn,"stencilFunc",[mc,0,-1]),I(ea,"stencilOpSeparate",[St,Tr,Tr,Tr]),I(pt,"stencilOpSeparate",[Ir,Tr,Tr,Tr]),$(oo,fc),I(Kt,"scissor",[0,0,e.drawingBufferWidth,e.drawingBufferHeight]),I(vr,vr,[0,0,e.drawingBufferWidth,e.drawingBufferHeight]);var X={gl:e,context:z,strings:t,next:W,current:Q,draw:j,elements:E,buffer:C,shader:V,attributes:U.state,vao:U,uniforms:N,framebuffer:D,extensions:u,timer:P,isBufferArgs:cn},Y={primTypes:Ar,compareFuncs:it,blendFuncs:lr,blendEquations:g,stencilOps:gr,glTypes:Rr,orientationType:ua};n.optional(function(){X.isArrayLike=Re}),Z&&(Y.backBuffer=[Ir],Y.drawBuffer=er(x.maxDrawbuffers,function(a){return a===0?[0]:er(a,function(r){return pc+r})}));var me=0;function le(){var a=qu(),r=a.link,c=a.global;a.id=me++,a.batchId="0";var h=r(X),v=a.shared={props:"a0"};Object.keys(X).forEach(function(s){v[s]=c.def(h,".",s)}),n.optional(function(){a.CHECK=r(n),a.commandStr=n.guessCommand(),a.command=r(a.commandStr),a.assert=function(s,o,_){s("if(!(",o,"))",this.CHECK,".commandRaise(",r(_),",",this.command,");")},Y.invalidBlendCombinations=bo});var d=a.next={},l=a.current={};Object.keys(R).forEach(function(s){Array.isArray(Q[s])&&(d[s]=c.def(v.next,".",s),l[s]=c.def(v.current,".",s))});var m=a.constants={};Object.keys(Y).forEach(function(s){m[s]=c.def(JSON.stringify(Y[s]))}),a.invoke=function(s,o){switch(o.type){case Vn:var _=["this",v.context,v.props,a.batchId];return s.def(r(o.data),".call(",_.slice(0,Math.max(o.data.length+1,4)),")");case Hn:return s.def(v.props,o.data);case zn:return s.def(v.context,o.data);case $n:return s.def("this",o.data);case Qt:return o.data.append(a,s),o.data.ref;case zi:return o.data.toString();case $i:return o.data.map(function(b){return a.invoke(s,b)})}},a.attribCache={};var i={};return a.scopeAttrib=function(s){var o=t.id(s);if(o in i)return i[o];var _=U.scope[o];_||(_=U.scope[o]=new p);var b=i[o]=r(_);return b},a}function q(a){var r=a.static,c=a.dynamic,h;if(vt in r){var v=!!r[vt];h=De(function(l,m){return v}),h.enable=v}else if(vt in c){var d=c[vt];h=Qe(d,function(l,m){return l.invoke(m,d)})}return h}function K(a,r){var c=a.static,h=a.dynamic;if(Gr in c){var v=c[Gr];return v?(v=D.getFramebuffer(v),n.command(v,"invalid framebuffer object"),De(function(l,m){var i=l.link(v),s=l.shared;m.set(s.framebuffer,".next",i);var o=s.context;return m.set(o,"."+tt,i+".width"),m.set(o,"."+nt,i+".height"),i})):De(function(l,m){var i=l.shared;m.set(i.framebuffer,".next","null");var s=i.context;return m.set(s,"."+tt,s+"."+so),m.set(s,"."+nt,s+"."+uo),"null"})}else if(Gr in h){var d=h[Gr];return Qe(d,function(l,m){var i=l.invoke(m,d),s=l.shared,o=s.framebuffer,_=m.def(o,".getFramebuffer(",i,")");n.optional(function(){l.assert(m,"!"+i+"||"+_,"invalid framebuffer object")}),m.set(o,".next",_);var b=s.context;return m.set(b,"."+tt,_+"?"+_+".width:"+b+"."+so),m.set(b,"."+nt,_+"?"+_+".height:"+b+"."+uo),_})}else return null}function se(a,r,c){var h=a.static,v=a.dynamic;function d(i){if(i in h){var s=h[i];n.commandType(s,"object","invalid "+i,c.commandStr);var o=!0,_=s.x|0,b=s.y|0,L,B;return"width"in s?(L=s.width|0,n.command(L>=0,"invalid "+i,c.commandStr)):o=!1,"height"in s?(B=s.height|0,n.command(B>=0,"invalid "+i,c.commandStr)):o=!1,new je(!o&&r&&r.thisDep,!o&&r&&r.contextDep,!o&&r&&r.propDep,function(ie,J){var F=ie.shared.context,w=L;"width"in s||(w=J.def(F,".",tt,"-",_));var ne=B;return"height"in s||(ne=J.def(F,".",nt,"-",b)),[_,b,w,ne]})}else if(i in v){var H=v[i],ce=Qe(H,function(ie,J){var F=ie.invoke(J,H);n.optional(function(){ie.assert(J,F+"&&typeof "+F+'==="object"',"invalid "+i)});var w=ie.shared.context,ne=J.def(F,".x|0"),te=J.def(F,".y|0"),ue=J.def('"width" in ',F,"?",F,".width|0:","(",w,".",tt,"-",ne,")"),we=J.def('"height" in ',F,"?",F,".height|0:","(",w,".",nt,"-",te,")");return n.optional(function(){ie.assert(J,ue+">=0&&"+we+">=0","invalid "+i)}),[ne,te,ue,we]});return r&&(ce.thisDep=ce.thisDep||r.thisDep,ce.contextDep=ce.contextDep||r.contextDep,ce.propDep=ce.propDep||r.propDep),ce}else return r?new je(r.thisDep,r.contextDep,r.propDep,function(ie,J){var F=ie.shared.context;return[0,0,J.def(F,".",tt),J.def(F,".",nt)]}):null}var l=d(vr);if(l){var m=l;l=new je(l.thisDep,l.contextDep,l.propDep,function(i,s){var o=m.append(i,s),_=i.shared.context;return s.set(_,"."+Qu,o[2]),s.set(_,"."+Ku,o[3]),o})}return{viewport:l,scissor_box:d(Kt)}}function he(a,r){var c=a.static,h=typeof c[_t]=="string"&&typeof c[bt]=="string";if(h){if(Object.keys(r.dynamic).length>0)return null;var v=r.static,d=Object.keys(v);if(d.length>0&&typeof v[d[0]]=="number"){for(var l=[],m=0;m=0,"invalid "+J,r.commandStr),De(function(te,ue){return F&&(te.OFFSET=w),w})}else if(J in h){var ne=h[J];return Qe(ne,function(te,ue){var we=te.invoke(ue,ne);return F&&(te.OFFSET=we,n.optional(function(){te.assert(ue,we+">=0","invalid "+J)})),we})}else if(F){if(i)return De(function(te,ue){return te.OFFSET=0,0});if(d)return new je(m.thisDep,m.contextDep,m.propDep,function(te,ue){return ue.def(te.shared.vao+".currentVAO?"+te.shared.vao+".currentVAO.offset:0")})}else if(d)return new je(m.thisDep,m.contextDep,m.propDep,function(te,ue){return ue.def(te.shared.vao+".currentVAO?"+te.shared.vao+".currentVAO.instances:-1")});return null}var L=b(Zt,!0);function B(){if(Pr in c){var J=c[Pr]|0;return v.count=J,n.command(typeof J=="number"&&J>=0,"invalid vertex count",r.commandStr),De(function(){return J})}else if(Pr in h){var F=h[Pr];return Qe(F,function(ue,we){var Ye=ue.invoke(we,F);return n.optional(function(){ue.assert(we,"typeof "+Ye+'==="number"&&'+Ye+">=0&&"+Ye+"===("+Ye+"|0)","invalid vertex count")}),Ye})}else if(i)if(Sr(o)){if(o)return L?new je(L.thisDep,L.contextDep,L.propDep,function(ue,we){var Ye=we.def(ue.ELEMENTS,".vertCount-",ue.OFFSET);return n.optional(function(){ue.assert(we,Ye+">=0","invalid vertex offset/element buffer too small")}),Ye}):De(function(ue,we){return we.def(ue.ELEMENTS,".vertCount")});var w=De(function(){return-1});return n.optional(function(){w.MISSING=!0}),w}else{var ne=new je(o.thisDep||L.thisDep,o.contextDep||L.contextDep,o.propDep||L.propDep,function(ue,we){var Ye=ue.ELEMENTS;return ue.OFFSET?we.def(Ye,"?",Ye,".vertCount-",ue.OFFSET,":-1"):we.def(Ye,"?",Ye,".vertCount:-1")});return n.optional(function(){ne.DYNAMIC=!0}),ne}else if(d){var te=new je(m.thisDep,m.contextDep,m.propDep,function(ue,we){return we.def(ue.shared.vao,".currentVAO?",ue.shared.vao,".currentVAO.count:-1")});return te}return null}var H=_(),ce=B(),ie=b(Jt,!1);return{elements:o,primitive:H,count:ce,instances:ie,offset:L,vao:m,vaoActive:d,elementsActive:i,static:v}}function Be(a,r){var c=a.static,h=a.dynamic,v={};return oe.forEach(function(d){var l=re(d);function m(i,s){if(d in c){var o=i(c[d]);v[l]=De(function(){return o})}else if(d in h){var _=h[d];v[l]=Qe(_,function(b,L){return s(b,L,b.invoke(L,_))})}}switch(d){case Ji:case Yi:case Xi:case ao:case qi:case oo:case ro:case to:case no:case Zi:return m(function(i){return n.commandType(i,"boolean",d,r.commandStr),i},function(i,s,o){return n.optional(function(){i.assert(s,"typeof "+o+'==="boolean"',"invalid flag "+d,i.commandStr)}),o});case Qi:return m(function(i){return n.commandParameter(i,it,"invalid "+d,r.commandStr),it[i]},function(i,s,o){var _=i.constants.compareFuncs;return n.optional(function(){i.assert(s,o+" in "+_,"invalid "+d+", must be one of "+Object.keys(it))}),s.def(_,"[",o,"]")});case Ki:return m(function(i){return n.command(Re(i)&&i.length===2&&typeof i[0]=="number"&&typeof i[1]=="number"&&i[0]<=i[1],"depth range is 2d array",r.commandStr),i},function(i,s,o){n.optional(function(){i.assert(s,i.shared.isArrayLike+"("+o+")&&"+o+".length===2&&typeof "+o+'[0]==="number"&&typeof '+o+'[1]==="number"&&'+o+"[0]<="+o+"[1]","depth range must be a 2d array")});var _=s.def("+",o,"[0]"),b=s.def("+",o,"[1]");return[_,b]});case Yn:return m(function(i){n.commandType(i,"object","blend.func",r.commandStr);var s="srcRGB"in i?i.srcRGB:i.src,o="srcAlpha"in i?i.srcAlpha:i.src,_="dstRGB"in i?i.dstRGB:i.dst,b="dstAlpha"in i?i.dstAlpha:i.dst;return n.commandParameter(s,lr,l+".srcRGB",r.commandStr),n.commandParameter(o,lr,l+".srcAlpha",r.commandStr),n.commandParameter(_,lr,l+".dstRGB",r.commandStr),n.commandParameter(b,lr,l+".dstAlpha",r.commandStr),n.command(bo.indexOf(s+", "+_)===-1,"unallowed blending combination (srcRGB, dstRGB) = ("+s+", "+_+")",r.commandStr),[lr[s],lr[_],lr[o],lr[b]]},function(i,s,o){var _=i.constants.blendFuncs;n.optional(function(){i.assert(s,o+"&&typeof "+o+'==="object"',"invalid blend func, must be an object")});function b(F,w){var ne=s.def('"',F,w,'" in ',o,"?",o,".",F,w,":",o,".",F);return n.optional(function(){i.assert(s,ne+" in "+_,"invalid "+d+"."+F+w+", must be one of "+Object.keys(lr))}),ne}var L=b("src","RGB"),B=b("dst","RGB");n.optional(function(){var F=i.constants.invalidBlendCombinations;i.assert(s,F+".indexOf("+L+'+", "+'+B+") === -1 ","unallowed blending combination for (srcRGB, dstRGB)")});var H=s.def(_,"[",L,"]"),ce=s.def(_,"[",b("src","Alpha"),"]"),ie=s.def(_,"[",B,"]"),J=s.def(_,"[",b("dst","Alpha"),"]");return[H,ie,ce,J]});case Xn:return m(function(i){if(typeof i=="string")return n.commandParameter(i,g,"invalid "+d,r.commandStr),[g[i],g[i]];if(typeof i=="object")return n.commandParameter(i.rgb,g,d+".rgb",r.commandStr),n.commandParameter(i.alpha,g,d+".alpha",r.commandStr),[g[i.rgb],g[i.alpha]];n.commandRaise("invalid blend.equation",r.commandStr)},function(i,s,o){var _=i.constants.blendEquations,b=s.def(),L=s.def(),B=i.cond("typeof ",o,'==="string"');return n.optional(function(){function H(ce,ie,J){i.assert(ce,J+" in "+_,"invalid "+ie+", must be one of "+Object.keys(g))}H(B.then,d,o),i.assert(B.else,o+"&&typeof "+o+'==="object"',"invalid "+d),H(B.else,d+".rgb",o+".rgb"),H(B.else,d+".alpha",o+".alpha")}),B.then(b,"=",L,"=",_,"[",o,"];"),B.else(b,"=",_,"[",o,".rgb];",L,"=",_,"[",o,".alpha];"),s(B),[b,L]});case Wi:return m(function(i){return n.command(Re(i)&&i.length===4,"blend.color must be a 4d array",r.commandStr),er(4,function(s){return+i[s]})},function(i,s,o){return n.optional(function(){i.assert(s,i.shared.isArrayLike+"("+o+")&&"+o+".length===4","blend.color must be a 4d array")}),er(4,function(_){return s.def("+",o,"[",_,"]")})});case io:return m(function(i){return n.commandType(i,"number",l,r.commandStr),i|0},function(i,s,o){return n.optional(function(){i.assert(s,"typeof "+o+'==="number"',"invalid stencil.mask")}),s.def(o,"|0")});case Jn:return m(function(i){n.commandType(i,"object",l,r.commandStr);var s=i.cmp||"keep",o=i.ref||0,_="mask"in i?i.mask:-1;return n.commandParameter(s,it,d+".cmp",r.commandStr),n.commandType(o,"number",d+".ref",r.commandStr),n.commandType(_,"number",d+".mask",r.commandStr),[it[s],o,_]},function(i,s,o){var _=i.constants.compareFuncs;n.optional(function(){function H(){i.assert(s,Array.prototype.join.call(arguments,""),"invalid stencil.func")}H(o+"&&typeof ",o,'==="object"'),H('!("cmp" in ',o,")||(",o,".cmp in ",_,")")});var b=s.def('"cmp" in ',o,"?",_,"[",o,".cmp]",":",Tr),L=s.def(o,".ref|0"),B=s.def('"mask" in ',o,"?",o,".mask|0:-1");return[b,L,B]});case ea:case pt:return m(function(i){n.commandType(i,"object",l,r.commandStr);var s=i.fail||"keep",o=i.zfail||"keep",_=i.zpass||"keep";return n.commandParameter(s,gr,d+".fail",r.commandStr),n.commandParameter(o,gr,d+".zfail",r.commandStr),n.commandParameter(_,gr,d+".zpass",r.commandStr),[d===pt?Ir:St,gr[s],gr[o],gr[_]]},function(i,s,o){var _=i.constants.stencilOps;n.optional(function(){i.assert(s,o+"&&typeof "+o+'==="object"',"invalid "+d)});function b(L){return n.optional(function(){i.assert(s,'!("'+L+'" in '+o+")||("+o+"."+L+" in "+_+")","invalid "+d+"."+L+", must be one of "+Object.keys(gr))}),s.def('"',L,'" in ',o,"?",_,"[",o,".",L,"]:",Tr)}return[d===pt?Ir:St,b("fail"),b("zfail"),b("zpass")]});case Kn:return m(function(i){n.commandType(i,"object",l,r.commandStr);var s=i.factor|0,o=i.units|0;return n.commandType(s,"number",l+".factor",r.commandStr),n.commandType(o,"number",l+".units",r.commandStr),[s,o]},function(i,s,o){n.optional(function(){i.assert(s,o+"&&typeof "+o+'==="object"',"invalid "+d)});var _=s.def(o,".factor|0"),b=s.def(o,".units|0");return[_,b]});case eo:return m(function(i){var s=0;return i==="front"?s=St:i==="back"&&(s=Ir),n.command(!!s,l,r.commandStr),s},function(i,s,o){return n.optional(function(){i.assert(s,o+'==="front"||'+o+'==="back"',"invalid cull.face")}),s.def(o,'==="front"?',St,":",Ir)});case Qn:return m(function(i){return n.command(typeof i=="number"&&i>=x.lineWidthDims[0]&&i<=x.lineWidthDims[1],"invalid line width, must be a positive number between "+x.lineWidthDims[0]+" and "+x.lineWidthDims[1],r.commandStr),i},function(i,s,o){return n.optional(function(){i.assert(s,"typeof "+o+'==="number"&&'+o+">="+x.lineWidthDims[0]+"&&"+o+"<="+x.lineWidthDims[1],"invalid line width")}),o});case qn:return m(function(i){return n.commandParameter(i,ua,l,r.commandStr),ua[i]},function(i,s,o){return n.optional(function(){i.assert(s,o+'==="cw"||'+o+'==="ccw"',"invalid frontFace, must be one of cw,ccw")}),s.def(o+'==="cw"?'+lo+":"+sa)});case Wn:return m(function(i){return n.command(Re(i)&&i.length===4,"color.mask must be length 4 array",r.commandStr),i.map(function(s){return!!s})},function(i,s,o){return n.optional(function(){i.assert(s,i.shared.isArrayLike+"("+o+")&&"+o+".length===4","invalid color.mask")}),er(4,function(_){return"!!"+o+"["+_+"]"})});case Zn:return m(function(i){n.command(typeof i=="object"&&i,l,r.commandStr);var s="value"in i?i.value:1,o=!!i.invert;return n.command(typeof s=="number"&&s>=0&&s<=1,"sample.coverage.value must be a number between 0 and 1",r.commandStr),[s,o]},function(i,s,o){n.optional(function(){i.assert(s,o+"&&typeof "+o+'==="object"',"invalid sample.coverage")});var _=s.def('"value" in ',o,"?+",o,".value:1"),b=s.def("!!",o,".invert");return[_,b]})}}),v}function xe(a,r){var c=a.static,h=a.dynamic,v={};return Object.keys(c).forEach(function(d){var l=c[d],m;if(typeof l=="number"||typeof l=="boolean")m=De(function(){return l});else if(typeof l=="function"){var i=l._reglType;i==="texture2d"||i==="textureCube"?m=De(function(s){return s.link(l)}):i==="framebuffer"||i==="framebufferCube"?(n.command(l.color.length>0,'missing color attachment for framebuffer sent to uniform "'+d+'"',r.commandStr),m=De(function(s){return s.link(l.color[0])})):n.commandRaise('invalid data for uniform "'+d+'"',r.commandStr)}else Re(l)?m=De(function(s){var o=s.global.def("[",er(l.length,function(_){return n.command(typeof l[_]=="number"||typeof l[_]=="boolean","invalid uniform "+d,s.commandStr),l[_]}),"]");return o}):n.commandRaise('invalid or missing data for uniform "'+d+'"',r.commandStr);m.value=l,v[d]=m}),Object.keys(h).forEach(function(d){var l=h[d];v[d]=Qe(l,function(m,i){return m.invoke(i,l)})}),v}function Me(a,r){var c=a.static,h=a.dynamic,v={};return Object.keys(c).forEach(function(d){var l=c[d],m=t.id(d),i=new p;if(cn(l))i.state=rt,i.buffer=C.getBuffer(C.create(l,at,!1,!0)),i.type=0;else{var s=C.getBuffer(l);if(s)i.state=rt,i.buffer=s,i.type=0;else if(n.command(typeof l=="object"&&l,"invalid data for attribute "+d,r.commandStr),"constant"in l){var o=l.constant;i.buffer="null",i.state=jn,typeof o=="number"?i.x=o:(n.command(Re(o)&&o.length>0&&o.length<=4,"invalid constant for attribute "+d,r.commandStr),et.forEach(function(ie,J){J=0,'invalid offset for attribute "'+d+'"',r.commandStr);var b=l.stride|0;n.command(b>=0&&b<256,'invalid stride for attribute "'+d+'", must be integer betweeen [0, 255]',r.commandStr);var L=l.size|0;n.command(!("size"in l)||L>0&&L<=4,'invalid size for attribute "'+d+'", must be 1,2,3,4',r.commandStr);var B=!!l.normalized,H=0;"type"in l&&(n.commandParameter(l.type,Rr,"invalid type for attribute "+d,r.commandStr),H=Rr[l.type]);var ce=l.divisor|0;n.optional(function(){"divisor"in l&&(n.command(ce===0||M,'cannot specify divisor for attribute "'+d+'", instancing not supported',r.commandStr),n.command(ce>=0,'invalid divisor for attribute "'+d+'"',r.commandStr));var ie=r.commandStr,J=["buffer","offset","divisor","normalized","type","size","stride"];Object.keys(l).forEach(function(F){n.command(J.indexOf(F)>=0,'unknown parameter "'+F+'" for attribute pointer "'+d+'" (valid parameters are '+J+")",ie)})}),i.buffer=s,i.state=rt,i.size=L,i.normalized=B,i.type=H||s.dtype,i.offset=_,i.stride=b,i.divisor=ce}}v[d]=De(function(ie,J){var F=ie.attribCache;if(m in F)return F[m];var w={isStream:!1};return Object.keys(i).forEach(function(ne){w[ne]=i[ne]}),i.buffer&&(w.buffer=ie.link(i.buffer),w.type=w.type||w.buffer+".dtype"),F[m]=w,w})}),Object.keys(h).forEach(function(d){var l=h[d];function m(i,s){var o=i.invoke(s,l),_=i.shared,b=i.constants,L=_.isBufferArgs,B=_.buffer;n.optional(function(){i.assert(s,o+"&&(typeof "+o+'==="object"||typeof '+o+'==="function")&&('+L+"("+o+")||"+B+".getBuffer("+o+")||"+B+".getBuffer("+o+".buffer)||"+L+"("+o+'.buffer)||("constant" in '+o+"&&(typeof "+o+'.constant==="number"||'+_.isArrayLike+"("+o+".constant))))",'invalid dynamic attribute "'+d+'"')});var H={isStream:s.def(!1)},ce=new p;ce.state=rt,Object.keys(ce).forEach(function(w){H[w]=s.def(""+ce[w])});var ie=H.buffer,J=H.type;s("if(",L,"(",o,")){",H.isStream,"=true;",ie,"=",B,".createStream(",at,",",o,");",J,"=",ie,".dtype;","}else{",ie,"=",B,".getBuffer(",o,");","if(",ie,"){",J,"=",ie,".dtype;",'}else if("constant" in ',o,"){",H.state,"=",jn,";","if(typeof "+o+'.constant === "number"){',H[et[0]],"=",o,".constant;",et.slice(1).map(function(w){return H[w]}).join("="),"=0;","}else{",et.map(function(w,ne){return H[w]+"="+o+".constant.length>"+ne+"?"+o+".constant["+ne+"]:0;"}).join(""),"}}else{","if(",L,"(",o,".buffer)){",ie,"=",B,".createStream(",at,",",o,".buffer);","}else{",ie,"=",B,".getBuffer(",o,".buffer);","}",J,'="type" in ',o,"?",b.glTypes,"[",o,".type]:",ie,".dtype;",H.normalized,"=!!",o,".normalized;");function F(w){s(H[w],"=",o,".",w,"|0;")}return F("size"),F("offset"),F("stride"),F("divisor"),s("}}"),s.exit("if(",H.isStream,"){",B,".destroyStream(",ie,");","}"),H}v[d]=Qe(l,m)}),v}function Le(a){var r=a.static,c=a.dynamic,h={};return Object.keys(r).forEach(function(v){var d=r[v];h[v]=De(function(l,m){return typeof d=="number"||typeof d=="boolean"?""+d:l.link(d)})}),Object.keys(c).forEach(function(v){var d=c[v];h[v]=Qe(d,function(l,m){return l.invoke(m,d)})}),h}function Pe(a,r,c,h,v){var d=a.static,l=a.dynamic;n.optional(function(){var F=[Gr,bt,_t,Nr,Dr,Zt,Pr,Jt,vt,yt].concat(oe);function w(ne){Object.keys(ne).forEach(function(te){n.command(F.indexOf(te)>=0,'unknown parameter "'+te+'"',v.commandStr)})}w(d),w(l)});var m=he(a,r),i=K(a),s=se(a,i,v),o=Ce(a,v),_=Be(a,v),b=Ee(a,v,m);function L(F){var w=s[F];w&&(_[F]=w)}L(vr),L(re(Kt));var B=Object.keys(_).length>0,H={framebuffer:i,draw:o,shader:b,state:_,dirty:B,scopeVAO:null,drawVAO:null,useVAO:!1,attributes:{}};if(H.profile=q(a),H.uniforms=xe(c,v),H.drawVAO=H.scopeVAO=o.vao,!H.drawVAO&&b.program&&!m&&u.angle_instanced_arrays&&o.static.elements){var ce=!0,ie=b.program.attributes.map(function(F){var w=r.static[F];return ce=ce&&!!w,w});if(ce&&ie.length>0){var J=U.getVAO(U.createVAO({attributes:ie,elements:o.static.elements}));H.drawVAO=new je(null,null,null,function(F,w){return F.link(J)}),H.useVAO=!0}}return m?H.useVAO=!0:H.attributes=Me(r,v),H.context=Le(h),H}function ke(a,r,c){var h=a.shared,v=h.context,d=a.scope();Object.keys(c).forEach(function(l){r.save(v,"."+l);var m=c[l],i=m.append(a,r);Array.isArray(i)?d(v,".",l,"=[",i.join(),"];"):d(v,".",l,"=",i,";")}),r(d)}function Ue(a,r,c,h){var v=a.shared,d=v.gl,l=v.framebuffer,m;Z&&(m=r.def(v.extensions,".webgl_draw_buffers"));var i=a.constants,s=i.drawBuffer,o=i.backBuffer,_;c?_=c.append(a,r):_=r.def(l,".next"),h||r("if(",_,"!==",l,".cur){"),r("if(",_,"){",d,".bindFramebuffer(",vo,",",_,".framebuffer);"),Z&&r(m,".drawBuffersWEBGL(",s,"[",_,".colorAttachments.length]);"),r("}else{",d,".bindFramebuffer(",vo,",null);"),Z&&r(m,".drawBuffersWEBGL(",o,");"),r("}",l,".cur=",_,";"),h||r("}")}function He(a,r,c){var h=a.shared,v=h.gl,d=a.current,l=a.next,m=h.current,i=h.next,s=a.cond(m,".dirty");oe.forEach(function(o){var _=re(o);if(!(_ in c.state)){var b,L;if(_ in l){b=l[_],L=d[_];var B=er(Q[_].length,function(ce){return s.def(b,"[",ce,"]")});s(a.cond(B.map(function(ce,ie){return ce+"!=="+L+"["+ie+"]"}).join("||")).then(v,".",R[_],"(",B,");",B.map(function(ce,ie){return L+"["+ie+"]="+ce}).join(";"),";"))}else{b=s.def(i,".",_);var H=a.cond(b,"!==",m,".",_);s(H),_ in O?H(a.cond(b).then(v,".enable(",O[_],");").else(v,".disable(",O[_],");"),m,".",_,"=",b,";"):H(v,".",R[_],"(",b,");",m,".",_,"=",b,";")}}}),Object.keys(c.state).length===0&&s(m,".dirty=false;"),r(s)}function $e(a,r,c,h){var v=a.shared,d=a.current,l=v.current,m=v.gl;yo(Object.keys(c)).forEach(function(i){var s=c[i];if(!(h&&!h(s))){var o=s.append(a,r);if(O[i]){var _=O[i];Sr(s)?o?r(m,".enable(",_,");"):r(m,".disable(",_,");"):r(a.cond(o).then(m,".enable(",_,");").else(m,".disable(",_,");")),r(l,".",i,"=",o,";")}else if(Re(o)){var b=d[i];r(m,".",R[i],"(",o,");",o.map(function(L,B){return b+"["+B+"]="+L}).join(";"),";")}else r(m,".",R[i],"(",o,");",l,".",i,"=",o,";")}})}function Fe(a,r){M&&(a.instancing=r.def(a.shared.extensions,".angle_instanced_arrays"))}function be(a,r,c,h,v){var d=a.shared,l=a.stats,m=d.current,i=d.timer,s=c.profile;function o(){return typeof performance=="undefined"?"Date.now()":"performance.now()"}var _,b;function L(F){_=r.def(),F(_,"=",o(),";"),typeof v=="string"?F(l,".count+=",v,";"):F(l,".count++;"),P&&(h?(b=r.def(),F(b,"=",i,".getNumPendingQueries();")):F(i,".beginQuery(",l,");"))}function B(F){F(l,".cpuTime+=",o(),"-",_,";"),P&&(h?F(i,".pushScopeStats(",b,",",i,".getNumPendingQueries(),",l,");"):F(i,".endQuery();"))}function H(F){var w=r.def(m,".profile");r(m,".profile=",F,";"),r.exit(m,".profile=",w,";")}var ce;if(s){if(Sr(s)){s.enable?(L(r),B(r.exit),H("true")):H("false");return}ce=s.append(a,r),H(ce)}else ce=r.def(m,".profile");var ie=a.block();L(ie),r("if(",ce,"){",ie,"}");var J=a.block();B(J),r.exit("if(",ce,"){",J,"}")}function Xe(a,r,c,h,v){var d=a.shared;function l(i){switch(i){case en:case nn:case fn:return 2;case rn:case an:case sn:return 3;case tn:case on:case un:return 4;default:return 1}}function m(i,s,o){var _=d.gl,b=r.def(i,".location"),L=r.def(d.attributes,"[",b,"]"),B=o.state,H=o.buffer,ce=[o.x,o.y,o.z,o.w],ie=["buffer","normalized","offset","stride"];function J(){r("if(!",L,".buffer){",_,".enableVertexAttribArray(",b,");}");var w=o.type,ne;if(o.size?ne=r.def(o.size,"||",s):ne=s,r("if(",L,".type!==",w,"||",L,".size!==",ne,"||",ie.map(function(ue){return L+"."+ue+"!=="+o[ue]}).join("||"),"){",_,".bindBuffer(",at,",",H,".buffer);",_,".vertexAttribPointer(",[b,ne,w,o.normalized,o.stride,o.offset],");",L,".type=",w,";",L,".size=",ne,";",ie.map(function(ue){return L+"."+ue+"="+o[ue]+";"}).join(""),"}"),M){var te=o.divisor;r("if(",L,".divisor!==",te,"){",a.instancing,".vertexAttribDivisorANGLE(",[b,te],");",L,".divisor=",te,";}")}}function F(){r("if(",L,".buffer){",_,".disableVertexAttribArray(",b,");",L,".buffer=null;","}if(",et.map(function(w,ne){return L+"."+w+"!=="+ce[ne]}).join("||"),"){",_,".vertexAttrib4f(",b,",",ce,");",et.map(function(w,ne){return L+"."+w+"="+ce[ne]+";"}).join(""),"}")}B===rt?J():B===jn?F():(r("if(",B,"===",rt,"){"),J(),r("}else{"),F(),r("}"))}h.forEach(function(i){var s=i.name,o=c.attributes[s],_;if(o){if(!v(o))return;_=o.append(a,r)}else{if(!v(Eo))return;var b=a.scopeAttrib(s);n.optional(function(){a.assert(r,b+".state","missing attribute "+s)}),_={},Object.keys(new p).forEach(function(L){_[L]=r.def(b,".",L)})}m(a.link(i),l(i.info.type),_)})}function Se(a,r,c,h,v,d){for(var l=a.shared,m=l.gl,i={},s,o=0;o1){if(!H)continue;var ce=b.replace("[0]","");if(i[ce])continue;i[ce]=1}var ie=a.link(_),J=ie+".location",F;if(H){if(!v(H))continue;if(Sr(H)){var w=H.value;if(n.command(w!==null&&typeof w!="undefined",'missing uniform "'+b+'"',a.commandStr),L===Tt||L===gt){n.command(typeof w=="function"&&(L===Tt&&(w._reglType==="texture2d"||w._reglType==="framebuffer")||L===gt&&(w._reglType==="textureCube"||w._reglType==="framebufferCube")),"invalid texture for uniform "+b,a.commandStr);var ne=a.link(w._texture||w.color[0]._texture);r(m,".uniform1i(",J,",",ne+".bind());"),r.exit(ne,".unbind();")}else if(L===Et||L===At||L===xt){n.optional(function(){n.command(Re(w),"invalid matrix for uniform "+b,a.commandStr),n.command(L===Et&&w.length===4||L===At&&w.length===9||L===xt&&w.length===16,"invalid length for matrix uniform "+b,a.commandStr)});var te=a.global.def("new Float32Array(["+Array.prototype.slice.call(w)+"])"),ue=2;L===At?ue=3:L===xt&&(ue=4),r(m,".uniformMatrix",ue,"fv(",J,",false,",te,");")}else{switch(L){case aa:B===1?n.commandType(w,"number","uniform "+b,a.commandStr):n.command(Re(w)&&w.length===B,"uniform "+b,a.commandStr),s="1f";break;case en:n.command(Re(w)&&w.length&&w.length%2==0&&w.length<=B*2,"uniform "+b,a.commandStr),s="2f";break;case rn:n.command(Re(w)&&w.length&&w.length%3==0&&w.length<=B*3,"uniform "+b,a.commandStr),s="3f";break;case tn:n.command(Re(w)&&w.length&&w.length%4==0&&w.length<=B*4,"uniform "+b,a.commandStr),s="4f";break;case oa:B===1?n.commandType(w,"boolean","uniform "+b,a.commandStr):n.command(Re(w)&&w.length===B,"uniform "+b,a.commandStr),s="1i";break;case ia:B===1?n.commandType(w,"number","uniform "+b,a.commandStr):n.command(Re(w)&&w.length===B,"uniform "+b,a.commandStr),s="1i";break;case fn:n.command(Re(w)&&w.length&&w.length%2==0&&w.length<=B*2,"uniform "+b,a.commandStr),s="2i";break;case nn:n.command(Re(w)&&w.length&&w.length%2==0&&w.length<=B*2,"uniform "+b,a.commandStr),s="2i";break;case sn:n.command(Re(w)&&w.length&&w.length%3==0&&w.length<=B*3,"uniform "+b,a.commandStr),s="3i";break;case an:n.command(Re(w)&&w.length&&w.length%3==0&&w.length<=B*3,"uniform "+b,a.commandStr),s="3i";break;case un:n.command(Re(w)&&w.length&&w.length%4==0&&w.length<=B*4,"uniform "+b,a.commandStr),s="4i";break;case on:n.command(Re(w)&&w.length&&w.length%4==0&&w.length<=B*4,"uniform "+b,a.commandStr),s="4i";break}B>1?(s+="v",w=a.global.def("["+Array.prototype.slice.call(w)+"]")):w=Re(w)?Array.prototype.slice.call(w):w,r(m,".uniform",s,"(",J,",",w,");")}continue}else F=H.append(a,r)}else{if(!v(Eo))continue;F=r.def(l.uniforms,"[",t.id(b),"]")}L===Tt?(n(!Array.isArray(F),"must specify a scalar prop for textures"),r("if(",F,"&&",F,'._reglType==="framebuffer"){',F,"=",F,".color[0];","}")):L===gt&&(n(!Array.isArray(F),"must specify a scalar prop for cube maps"),r("if(",F,"&&",F,'._reglType==="framebufferCube"){',F,"=",F,".color[0];","}")),n.optional(function(){function tr(Ke,ln){a.assert(r,Ke,'bad data or missing for uniform "'+b+'". '+ln)}function jr(Ke,ln){ln===1&&n(!Array.isArray(F),"must not specify an array type for uniform"),tr("Array.isArray("+F+") && typeof "+F+'[0]===" '+Ke+'" || typeof '+F+'==="'+Ke+'"',"invalid type, expected "+Ke)}function ar(Ke,ln,dn){Array.isArray(F)?n(F.length&&F.length%Ke==0&&F.length<=Ke*dn,"must have length of "+(dn===1?"":"n * ")+Ke):tr(l.isArrayLike+"("+F+")&&"+F+".length && "+F+".length % "+Ke+" === 0 && "+F+".length<="+Ke*dn,"invalid vector, should have length of "+(dn===1?"":"n * ")+Ke,a.commandStr)}function Lo(Ke){n(!Array.isArray(F),"must not specify a value type"),tr("typeof "+F+'==="function"&&'+F+'._reglType==="texture'+(Ke===co?"2d":"Cube")+'"',"invalid texture type",a.commandStr)}switch(L){case ia:jr("number",B);break;case nn:ar(2,"number",B);break;case an:ar(3,"number",B);break;case on:ar(4,"number",B);break;case aa:jr("number",B);break;case en:ar(2,"number",B);break;case rn:ar(3,"number",B);break;case tn:ar(4,"number",B);break;case oa:jr("boolean",B);break;case fn:ar(2,"boolean",B);break;case sn:ar(3,"boolean",B);break;case un:ar(4,"boolean",B);break;case Et:ar(4,"number",B);break;case At:ar(9,"number",B);break;case xt:ar(16,"number",B);break;case Tt:Lo(co);break;case gt:Lo(rc);break}});var we=1;switch(L){case Tt:case gt:var Ye=r.def(F,"._texture");r(m,".uniform1i(",J,",",Ye,".bind());"),r.exit(Ye,".unbind();");continue;case ia:case oa:s="1i";break;case nn:case fn:s="2i",we=2;break;case an:case sn:s="3i",we=3;break;case on:case un:s="4i",we=4;break;case aa:s="1f";break;case en:s="2f",we=2;break;case rn:s="3f",we=3;break;case tn:s="4f",we=4;break;case Et:s="Matrix2fv";break;case At:s="Matrix3fv";break;case xt:s="Matrix4fv";break}if(s.indexOf("Matrix")===-1&&B>1&&(s+="v",we=1),s.charAt(0)==="M"){r(m,".uniform",s,"(",J,",");var kr=Math.pow(L-Et+2,2),br=a.global.def("new Float32Array(",kr,")");Array.isArray(F)?r("false,(",er(kr,function(tr){return br+"["+tr+"]="+F[tr]}),",",br,")"):r("false,(Array.isArray(",F,")||",F," instanceof Float32Array)?",F,":(",er(kr,function(tr){return br+"["+tr+"]="+F+"["+tr+"]"}),",",br,")"),r(");")}else if(we>1){for(var mr=[],wr=[],Ur=0;Ur=0","missing vertex count")})):(te=ue.def(l,".",Pr),n.optional(function(){a.assert(ue,te+">=0","missing vertex count")})),te}var o=i();function _(ne){var te=m[ne];return te?te.contextDep&&h.contextDynamic||te.propDep?te.append(a,c):te.append(a,r):r.def(l,".",ne)}var b=_(Dr),L=_(Zt),B=s();if(typeof B=="number"){if(B===0)return}else c("if(",B,"){"),c.exit("}");var H,ce;M&&(H=_(Jt),ce=a.instancing);var ie=o+".type",J=m.elements&&Sr(m.elements)&&!m.vaoActive;function F(){function ne(){c(ce,".drawElementsInstancedANGLE(",[b,B,ie,L+"<<(("+ie+"-"+Hi+")>>1)",H],");")}function te(){c(ce,".drawArraysInstancedANGLE(",[b,L,B,H],");")}o&&o!=="null"?J?ne():(c("if(",o,"){"),ne(),c("}else{"),te(),c("}")):te()}function w(){function ne(){c(d+".drawElements("+[b,B,ie,L+"<<(("+ie+"-"+Hi+")>>1)"]+");")}function te(){c(d+".drawArrays("+[b,L,B]+");")}o&&o!=="null"?J?ne():(c("if(",o,"){"),ne(),c("}else{"),te(),c("}")):te()}M&&(typeof H!="number"||H>=0)?typeof H=="string"?(c("if(",H,">0){"),F(),c("}else if(",H,"<0){"),w(),c("}")):F():w()}function Ae(a,r,c,h,v){var d=le(),l=d.proc("body",v);return n.optional(function(){d.commandStr=r.commandStr,d.command=d.link(r.commandStr)}),M&&(d.instancing=l.def(d.shared.extensions,".angle_instanced_arrays")),a(d,l,c,h),d.compile().body}function ge(a,r,c,h){Fe(a,r),c.useVAO?c.drawVAO?r(a.shared.vao,".setVAO(",c.drawVAO.append(a,r),");"):r(a.shared.vao,".setVAO(",a.shared.vao,".targetVAO);"):(r(a.shared.vao,".setVAO(null);"),Xe(a,r,c,h.attributes,function(){return!0})),Se(a,r,c,h.uniforms,function(){return!0},!1),fe(a,r,r,c)}function Ge(a,r){var c=a.proc("draw",1);Fe(a,c),ke(a,c,r.context),Ue(a,c,r.framebuffer),He(a,c,r),$e(a,c,r.state),be(a,c,r,!1,!0);var h=r.shader.progVar.append(a,c);if(c(a.shared.gl,".useProgram(",h,".program);"),r.shader.program)ge(a,c,r,r.shader.program);else{c(a.shared.vao,".setVAO(null);");var v=a.global.def("{}"),d=c.def(h,".id"),l=c.def(v,"[",d,"]");c(a.cond(l).then(l,".call(this,a0);").else(l,"=",v,"[",d,"]=",a.link(function(m){return Ae(ge,a,r,m,1)}),"(",h,");",l,".call(this,a0);"))}Object.keys(r.state).length>0&&c(a.shared.current,".dirty=true;"),a.shared.vao&&c(a.shared.vao,".setVAO(null);")}function dr(a,r,c,h){a.batchId="a1",Fe(a,r);function v(){return!0}Xe(a,r,c,h.attributes,v),Se(a,r,c,h.uniforms,v,!1),fe(a,r,r,c)}function Mr(a,r,c,h){Fe(a,r);var v=c.contextDep,d=r.def(),l="a0",m="a1",i=r.def();a.shared.props=i,a.batchId=d;var s=a.scope(),o=a.scope();r(s.entry,"for(",d,"=0;",d,"<",m,";++",d,"){",i,"=",l,"[",d,"];",o,"}",s.exit);function _(ie){return ie.contextDep&&v||ie.propDep}function b(ie){return!_(ie)}if(c.needsContext&&ke(a,o,c.context),c.needsFramebuffer&&Ue(a,o,c.framebuffer),$e(a,o,c.state,_),c.profile&&_(c.profile)&&be(a,o,c,!1,!0),h)c.useVAO?c.drawVAO?_(c.drawVAO)?o(a.shared.vao,".setVAO(",c.drawVAO.append(a,o),");"):s(a.shared.vao,".setVAO(",c.drawVAO.append(a,s),");"):s(a.shared.vao,".setVAO(",a.shared.vao,".targetVAO);"):(s(a.shared.vao,".setVAO(null);"),Xe(a,s,c,h.attributes,b),Xe(a,o,c,h.attributes,_)),Se(a,s,c,h.uniforms,b,!1),Se(a,o,c,h.uniforms,_,!0),fe(a,s,o,c);else{var L=a.global.def("{}"),B=c.shader.progVar.append(a,o),H=o.def(B,".id"),ce=o.def(L,"[",H,"]");o(a.shared.gl,".useProgram(",B,".program);","if(!",ce,"){",ce,"=",L,"[",H,"]=",a.link(function(ie){return Ae(dr,a,c,ie,2)}),"(",B,");}",ce,".call(this,a0[",d,"],",d,");")}}function f(a,r){var c=a.proc("batch",2);a.batchId="0",Fe(a,c);var h=!1,v=!0;Object.keys(r.context).forEach(function(L){h=h||r.context[L].propDep}),h||(ke(a,c,r.context),v=!1);var d=r.framebuffer,l=!1;d?(d.propDep?h=l=!0:d.contextDep&&h&&(l=!0),l||Ue(a,c,d)):Ue(a,c,null),r.state.viewport&&r.state.viewport.propDep&&(h=!0);function m(L){return L.contextDep&&h||L.propDep}He(a,c,r),$e(a,c,r.state,function(L){return!m(L)}),(!r.profile||!m(r.profile))&&be(a,c,r,!1,"a1"),r.contextDep=h,r.needsContext=v,r.needsFramebuffer=l;var i=r.shader.progVar;if(i.contextDep&&h||i.propDep)Mr(a,c,r,null);else{var s=i.append(a,c);if(c(a.shared.gl,".useProgram(",s,".program);"),r.shader.program)Mr(a,c,r,r.shader.program);else{c(a.shared.vao,".setVAO(null);");var o=a.global.def("{}"),_=c.def(s,".id"),b=c.def(o,"[",_,"]");c(a.cond(b).then(b,".call(this,a0,a1);").else(b,"=",o,"[",_,"]=",a.link(function(L){return Ae(Mr,a,r,L,2)}),"(",s,");",b,".call(this,a0,a1);"))}}Object.keys(r.state).length>0&&c(a.shared.current,".dirty=true;"),a.shared.vao&&c(a.shared.vao,".setVAO(null);")}function T(a,r){var c=a.proc("scope",3);a.batchId="a2";var h=a.shared,v=h.current;ke(a,c,r.context),r.framebuffer&&r.framebuffer.append(a,c),yo(Object.keys(r.state)).forEach(function(l){var m=r.state[l],i=m.append(a,c);Re(i)?i.forEach(function(s,o){c.set(a.next[l],"["+o+"]",s)}):c.set(h.next,"."+l,i)}),be(a,c,r,!0,!0),[Nr,Zt,Pr,Jt,Dr].forEach(function(l){var m=r.draw[l];!m||c.set(h.draw,"."+l,""+m.append(a,c))}),Object.keys(r.uniforms).forEach(function(l){var m=r.uniforms[l].append(a,c);Array.isArray(m)&&(m="["+m.join()+"]"),c.set(h.uniforms,"["+t.id(l)+"]",m)}),Object.keys(r.attributes).forEach(function(l){var m=r.attributes[l].append(a,c),i=a.scopeAttrib(l);Object.keys(new p).forEach(function(s){c.set(i,"."+s,m[s])})}),r.scopeVAO&&c.set(h.vao,".targetVAO",r.scopeVAO.append(a,c));function d(l){var m=r.shader[l];m&&c.set(h.shader,"."+l,m.append(a,c))}d(bt),d(_t),Object.keys(r.state).length>0&&(c(v,".dirty=true;"),c.exit(v,".dirty=true;")),c("a1(",a.shared.context,",a0,",a.batchId,");")}function y(a){if(!(typeof a!="object"||Re(a))){for(var r=Object.keys(a),c=0;c=0;--fe){var Ae=Y[fe];Ae&&Ae(P,null,0)}u.flush(),U&&U.update()}function he(){!K&&Y.length>0&&(K=mn.next(se))}function Ee(){K&&(mn.cancel(se),K=null)}function Ce(fe){fe.preventDefault(),C=!0,Ee(),me.forEach(function(Ae){Ae()})}function Be(fe){u.getError(),C=!1,E.restore(),W.restore(),M.restore(),oe.restore(),O.restore(),R.restore(),G.restore(),U&&U.restore(),re.procs.refresh(),he(),le.forEach(function(Ae){Ae()})}X&&(X.addEventListener(xo,Ce,!1),X.addEventListener(To,Be,!1));function xe(){Y.length=0,Ee(),X&&(X.removeEventListener(xo,Ce),X.removeEventListener(To,Be)),W.clear(),R.clear(),O.clear(),G.clear(),oe.clear(),Z.clear(),M.clear(),U&&U.clear(),q.forEach(function(fe){fe()})}function Me(fe){n(!!fe,"invalid args to regl({...})"),n.type(fe,"object","invalid args to regl({...})");function Ae(v){var d=ae({},v);delete d.uniforms,delete d.attributes,delete d.context,delete d.vao,"stencil"in d&&d.stencil.op&&(d.stencil.opBack=d.stencil.opFront=d.stencil.op,delete d.stencil.op);function l(m){if(m in d){var i=d[m];delete d[m],Object.keys(i).forEach(function(s){d[m+"."+s]=i[s]})}}return l("blend"),l("depth"),l("cull"),l("stencil"),l("polygonOffset"),l("scissor"),l("sample"),"vao"in v&&(d.vao=v.vao),d}function ge(v,d){var l={},m={};return Object.keys(v).forEach(function(i){var s=v[i];if(Je.isDynamic(s)){m[i]=Je.unbox(s,i);return}else if(d&&Array.isArray(s)){for(var o=0;o0)return ye.call(this,c(v|0),v|0)}else if(Array.isArray(v)){if(v.length)return ye.call(this,v,v.length)}else return ee.call(this,v)}return ae(h,{stats:T,destroy:function(){y.destroy()}})}var Le=R.setFBO=Me({framebuffer:Je.define.call(null,go,"framebuffer")});function Pe(fe,Ae){var ge=0;re.procs.poll();var Ge=Ae.color;Ge&&(u.clearColor(+Ge[0]||0,+Ge[1]||0,+Ge[2]||0,+Ge[3]||0),ge|=Ac),"depth"in Ae&&(u.clearDepth(+Ae.depth),ge|=xc),"stencil"in Ae&&(u.clearStencil(Ae.stencil|0),ge|=Tc),n(!!ge,"called regl.clear with no buffer specified"),u.clear(ge)}function ke(fe){if(n(typeof fe=="object"&&fe,"regl.clear() takes an object as input"),"framebuffer"in fe)if(fe.framebuffer&&fe.framebuffer_reglType==="framebufferCube")for(var Ae=0;Ae<6;++Ae)Le(ae({framebuffer:fe.framebuffer.faces[Ae]},fe),Pe);else Le(fe,Pe);else Pe(null,fe)}function Ue(fe){n.type(fe,"function","regl.frame() callback must be a function"),Y.push(fe);function Ae(){var ge=So(Y,fe);n(ge>=0,"cannot cancel a frame twice");function Ge(){var dr=So(Y,Ge);Y[dr]=Y[Y.length-1],Y.length-=1,Y.length<=0&&Ee()}Y[ge]=Ge}return he(),{cancel:Ae}}function He(){var fe=I.viewport,Ae=I.scissor_box;fe[0]=fe[1]=Ae[0]=Ae[1]=0,P.viewportWidth=P.framebufferWidth=P.drawingBufferWidth=fe[2]=Ae[2]=u.drawingBufferWidth,P.viewportHeight=P.framebufferHeight=P.drawingBufferHeight=fe[3]=Ae[3]=u.drawingBufferHeight}function $e(){P.tick+=1,P.time=be(),He(),re.procs.poll()}function Fe(){oe.refresh(),He(),re.procs.refresh(),U&&U.update()}function be(){return(Fa()-V)/1e3}Fe();function Xe(fe,Ae){n.type(Ae,"function","listener callback must be a function");var ge;switch(fe){case"frame":return Ue(Ae);case"lost":ge=me;break;case"restore":ge=le;break;case"destroy":ge=q;break;default:n.raise("invalid event, must be one of frame,lost,restore,destroy")}return ge.push(Ae),{cancel:function(){for(var Ge=0;Ge=0},read:$,destroy:xe,_gl:u,_refresh:Fe,poll:function(){$e(),U&&U.update()},now:be,stats:D});return t.onDone(null,Se),Se}return Lc})})(ca);var Ro=ca.exports,la=typeof Float32Array!="undefined"?Float32Array:Array;Math.hypot||(Math.hypot=function(){for(var A=0,_e=arguments.length;_e--;)A+=arguments[_e]*arguments[_e];return Math.sqrt(A)});function da(){var A=new la(16);return la!=Float32Array&&(A[1]=0,A[2]=0,A[3]=0,A[4]=0,A[6]=0,A[7]=0,A[8]=0,A[9]=0,A[11]=0,A[12]=0,A[13]=0,A[14]=0),A[0]=1,A[5]=1,A[10]=1,A[15]=1,A}function ma(A,_e,de,ae,pe,Te,Ve){var ve=1/(_e-de),Oe=1/(ae-pe),_r=1/(Te-Ve);return A[0]=-2*ve,A[1]=0,A[2]=0,A[3]=0,A[4]=0,A[5]=-2*Oe,A[6]=0,A[7]=0,A[8]=0,A[9]=0,A[10]=2*_r,A[11]=0,A[12]=(_e+de)*ve,A[13]=(pe+ae)*Oe,A[14]=(Ve+Te)*_r,A[15]=1,A}const Lt={positions:[[0,-.5],[1,-.5],[1,.5],[0,.5]],cells:[[0,1,2],[0,2,3]]};function Co(A){return A({vert:`
9 | precision highp float;
10 | attribute vec2 position;
11 | attribute vec2 pA, pB, pC, pD;
12 | uniform float width;
13 | uniform mat4 projection;
14 |
15 | void main() {
16 | // Select the three points we'll use and adjust the vertex according to
17 | // the side of the segment the vertex is on and the order of the points.
18 | vec2 p0 = pA;
19 | vec2 p1 = pB;
20 | vec2 p2 = pC;
21 | vec2 pos = position;
22 | if (position.x == 1.0) {
23 | p0 = pD;
24 | p1 = pC;
25 | p2 = pB;
26 | pos = vec2(1.0 - position.x, -position.y);
27 | }
28 |
29 | // Find the normal vector.
30 | vec2 tangent = normalize(normalize(p2 - p1) + normalize(p1 - p0));
31 | vec2 normal = vec2(-tangent.y, tangent.x);
32 |
33 | // Find the perpendicular vectors.
34 | vec2 p01 = p1 - p0;
35 | vec2 p21 = p1 - p2;
36 | vec2 p01Norm = normalize(vec2(-p01.y, p01.x));
37 |
38 | // Determine the bend direction.
39 | float sigma = sign(dot(p01 + p21, normal));
40 |
41 | // If this is the intersecting vertex,
42 | if (sign(pos.y) == -sigma) {
43 | vec2 point = 0.5 * normal * -sigma * width / dot(normal, p01Norm);
44 | gl_Position = projection * vec4(p1 + point, 0, 1);
45 | } else {
46 | vec2 xBasis = p2 - p1;
47 | vec2 yBasis = normalize(vec2(-xBasis.y, xBasis.x));
48 | vec2 point = p1 + xBasis * pos.x + yBasis * width * pos.y;
49 | gl_Position = projection * vec4(point, 0, 1);
50 | }
51 | }`,frag:`
52 | precision highp float;
53 | uniform vec4 color;
54 | void main() {
55 | gl_FragColor = color;
56 | }`,attributes:{position:{buffer:A.buffer(Lt.positions),divisor:0},pA:{buffer:A.prop("points"),divisor:1,offset:Float32Array.BYTES_PER_ELEMENT*0},pB:{buffer:A.prop("points"),divisor:1,offset:Float32Array.BYTES_PER_ELEMENT*2},pC:{buffer:A.prop("points"),divisor:1,offset:Float32Array.BYTES_PER_ELEMENT*4},pD:{buffer:A.prop("points"),divisor:1,offset:Float32Array.BYTES_PER_ELEMENT*6}},uniforms:{width:A.prop("width"),color:A.prop("color"),projection:A.prop("projection")},blend:{enable:!0,func:{src:"src alpha",dst:"one minus src alpha"}},cull:{enable:!0,face:"back"},depth:{enable:!1},elements:A.elements(Lt.cells),instances:A.prop("segments"),viewport:A.prop("viewport")})}function Oo(A){return A({vert:`
57 | precision highp float;
58 | attribute vec2 position;
59 | attribute vec2 pA, pB, pC;
60 | uniform float width;
61 | uniform mat4 projection;
62 |
63 | void main() {
64 |
65 | if (position.x == 0.0) {
66 | vec2 xBasis = pB - pA;
67 | vec2 yBasis = normalize(vec2(-xBasis.y, xBasis.x));
68 | vec2 point = pA + xBasis * position.x + yBasis * width * position.y;
69 | gl_Position = projection * vec4(point, 0, 1);
70 | return;
71 | }
72 |
73 | // Find the normal vector.
74 | vec2 tangent = normalize(normalize(pC - pB) + normalize(pB - pA));
75 | vec2 normal = vec2(-tangent.y, tangent.x);
76 |
77 | // Find the perpendicular vectors.
78 | vec2 ab = pB - pA;
79 | vec2 cb = pB - pC;
80 | vec2 abNorm = normalize(vec2(-ab.y, ab.x));
81 |
82 | // Determine the bend direction.
83 | float sigma = sign(dot(ab + cb, normal));
84 |
85 | if (sign(position.y) == -sigma) {
86 | vec2 position = 0.5 * normal * -sigma * width / dot(normal, abNorm);
87 | gl_Position = projection * vec4(pB + position, 0, 1);
88 | } else {
89 | vec2 xBasis = pB - pA;
90 | vec2 yBasis = normalize(vec2(-xBasis.y, xBasis.x));
91 | vec2 point = pA + xBasis * position.x + yBasis * width * position.y;
92 | gl_Position = projection * vec4(point, 0, 1);
93 | }
94 | }`,frag:`
95 | precision highp float;
96 | uniform vec4 color;
97 | void main() {
98 | gl_FragColor = color;
99 | }`,attributes:{position:{buffer:A.buffer(Lt.positions),divisor:0},pA:{buffer:A.prop("points"),divisor:1,offset:Float32Array.BYTES_PER_ELEMENT*0,stride:Float32Array.BYTES_PER_ELEMENT*6},pB:{buffer:A.prop("points"),divisor:1,offset:Float32Array.BYTES_PER_ELEMENT*2,stride:Float32Array.BYTES_PER_ELEMENT*6},pC:{buffer:A.prop("points"),divisor:1,offset:Float32Array.BYTES_PER_ELEMENT*4,stride:Float32Array.BYTES_PER_ELEMENT*6}},uniforms:{width:A.prop("width"),color:A.prop("color"),projection:A.prop("projection")},blend:{enable:!0,func:{src:"src alpha",dst:"one minus src alpha"}},cull:{enable:!0,face:"back"},depth:{enable:!1},elements:A.elements(Lt.cells),instances:A.prop("segments"),viewport:A.prop("viewport")})}const ha={positions:[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],cells:[[0,1,2],[0,2,3]]};function Bo(A){return A({vert:`
100 | precision highp float;
101 | attribute vec2 pointA, pointB, pointC;
102 | attribute vec4 position;
103 | uniform float width;
104 | uniform mat4 projection;
105 |
106 | void main() {
107 | // Find the miter vector.
108 | vec2 tangent = normalize(normalize(pointC - pointB) + normalize(pointB - pointA));
109 | vec2 miter = vec2(-tangent.y, tangent.x);
110 |
111 | // Find the perpendicular vectors.
112 | vec2 ab = pointB - pointA;
113 | vec2 cb = pointB - pointC;
114 | vec2 abNorm = normalize(vec2(-ab.y, ab.x));
115 | vec2 cbNorm = -normalize(vec2(-cb.y, cb.x));
116 |
117 | // Determine the bend direction.
118 | float sigma = sign(dot(ab + cb, miter));
119 |
120 | // Calculate the basis vectors for the miter geometry.
121 | vec2 p0 = 0.5 * width * sigma * (sigma < 0.0 ? abNorm : cbNorm);
122 | vec2 p1 = 0.5 * miter * sigma * width / dot(miter, abNorm);
123 | vec2 p2 = 0.5 * width * sigma * (sigma < 0.0 ? cbNorm : abNorm);
124 | vec2 p3 = -0.5 * miter * sigma * width / dot(miter, abNorm);
125 |
126 | // Calculate the final point position.
127 | vec2 point = pointB + position.x * p0 + position.y * p1 + position.z * p2 + position.w * p3;
128 | gl_Position = projection * vec4(point, 0, 1);
129 | }`,frag:`
130 | precision highp float;
131 | uniform vec4 color;
132 | void main() {
133 | gl_FragColor = color;
134 | }`,depth:{enable:!1},attributes:{position:{buffer:A.buffer(ha.positions),divisor:0},pointA:{buffer:A.prop("points"),divisor:1,offset:Float32Array.BYTES_PER_ELEMENT*0},pointB:{buffer:A.prop("points"),divisor:1,offset:Float32Array.BYTES_PER_ELEMENT*2},pointC:{buffer:A.prop("points"),divisor:1,offset:Float32Array.BYTES_PER_ELEMENT*4}},uniforms:{width:A.prop("width"),color:A.prop("color"),projection:A.prop("projection")},blend:{enable:!0,func:{src:"src alpha",dst:"one minus src alpha"}},cull:{enable:!0,face:"back"},elements:A.elements(ha.cells),instances:A.prop("instances"),viewport:A.prop("viewport")})}const pa=[[1,0,0],[0,1,0],[0,0,1]];function Fo(A){return A({vert:`
135 | precision highp float;
136 | attribute vec2 pointA, pointB, pointC;
137 | attribute vec3 position;
138 | uniform float width;
139 | uniform mat4 projection;
140 |
141 | void main() {
142 | vec2 tangent = normalize(normalize(pointC - pointB) + normalize(pointB - pointA));
143 | vec2 normal = vec2(-tangent.y, tangent.x);
144 | vec2 ab = pointB - pointA;
145 | vec2 cb = pointB - pointC;
146 | float sigma = sign(dot(ab + cb, normal));
147 | vec2 abn = normalize(vec2(-ab.y, ab.x));
148 | vec2 cbn = -normalize(vec2(-cb.y, cb.x));
149 | vec2 p0 = 0.5 * sigma * width * (sigma < 0.0 ? abn : cbn);
150 | vec2 p1 = 0.5 * sigma * width * (sigma < 0.0 ? cbn : abn);
151 | vec2 p2 = -0.5 * normal * sigma * width / dot(normal, abn);
152 | vec2 point = pointB + position.x * p0 + position.y * p1 + position.z * p2;
153 | gl_Position = projection * vec4(point, 0, 1);
154 | }`,frag:`
155 | precision highp float;
156 | uniform vec4 color;
157 | void main() {
158 | gl_FragColor = color;
159 | }`,depth:{enable:!1},attributes:{position:{buffer:A.buffer(pa),divisor:0},pointA:{buffer:A.prop("points"),divisor:1,offset:Float32Array.BYTES_PER_ELEMENT*0},pointB:{buffer:A.prop("points"),divisor:1,offset:Float32Array.BYTES_PER_ELEMENT*2},pointC:{buffer:A.prop("points"),divisor:1,offset:Float32Array.BYTES_PER_ELEMENT*4}},uniforms:{width:A.prop("width"),color:A.prop("color"),projection:A.prop("projection")},blend:{enable:!0,func:{src:"src alpha",dst:"one minus src alpha"}},cull:{enable:!0,face:"back"},count:pa.length,instances:A.prop("instances"),viewport:A.prop("viewport")})}function Go(A){const _e=[],de=[];for(let ae=0;ae=0&&_e.top<=(window.innerHeight||document.documentElement.clientHeight)}const ir=document.createElement("canvas"),ya=Ro({canvas:ir,extensions:["ANGLE_instanced_arrays"]}),zo=Mo(ya);window.newStrip=function(A,_e,de,ae,pe,Te){function Ve(){requestAnimationFrame(Ve);const ve=document.getElementById(A);if(!_a(ve))return;(ve.width!==ve.clientWidth||ve.height!==ve.clientHeight)&&(ve.width=ve.clientWidth,ve.height=ve.clientHeight),(ir.width!==ve.clientWidth||ir.height!==ve.clientHeight)&&(ir.width=ve.clientWidth,ir.height=ve.clientHeight),zo(ve,_e,de,ae,pe,Te);const Oe=ve.getContext("2d");Oe==null||Oe.clearRect(0,0,ve.width,ve.height),Oe==null||Oe.drawImage(ir,0,0)}requestAnimationFrame(Ve)};const $o=Ho(ya);window.oldStrip=function(A,_e,de){function ae(){requestAnimationFrame(ae);const pe=document.getElementById(A);if(!_a(pe))return;(pe.width!==pe.clientWidth||pe.height!==pe.clientHeight)&&(pe.width=pe.clientWidth,pe.height=pe.clientHeight),(ir.width!==pe.clientWidth||ir.height!==pe.clientHeight)&&(ir.width=pe.clientWidth,ir.height=pe.clientHeight),$o(pe,_e,de);const Te=pe.getContext("2d");Te==null||Te.clearRect(0,0,pe.width,pe.height),Te==null||Te.drawImage(ir,0,0)}requestAnimationFrame(ae)}});
256 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Instanced Lines Part II
8 |
9 |
10 |
22 |
23 |
24 |
25 |
28 |
29 |
30 |
31 |
34 |
35 |
36 |
37 |
40 |
41 |
42 |
43 |
46 |
47 |
48 |
49 |
52 |
53 |
54 |
55 |
58 |
59 |
60 |
61 |
64 |
65 |
66 |
67 |
70 |
71 |
72 |
73 |
76 |
77 |
78 |
79 |
82 |
83 |
84 |
85 |
88 |
89 |
90 |
91 |
94 |
95 |
96 |
97 |
100 |
101 |
102 |
103 |
106 |
107 |
108 |
109 |
112 |
113 |
114 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "instanced-lines-2",
3 | "version": "0.0.0",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "@types/url-parse": {
8 | "version": "1.4.4",
9 | "resolved": "https://registry.npmjs.org/@types/url-parse/-/url-parse-1.4.4.tgz",
10 | "integrity": "sha512-KtQLad12+4T/NfSxpoDhmr22+fig3T7/08QCgmutYA6QSznSRmEtuL95GrhVV40/0otTEdFc+etRcCTqhh1q5Q==",
11 | "dev": true
12 | },
13 | "esbuild": {
14 | "version": "0.13.3",
15 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.13.3.tgz",
16 | "integrity": "sha512-98xovMLKnyhv3gcReUuAEi5Ig1rK6SIgvsJuBIcfwzqGSEHsV8UJjMlmkhHoHMf9XZybMpE9Zax8AA8f7i2hlQ==",
17 | "dev": true,
18 | "requires": {
19 | "esbuild-android-arm64": "0.13.3",
20 | "esbuild-darwin-64": "0.13.3",
21 | "esbuild-darwin-arm64": "0.13.3",
22 | "esbuild-freebsd-64": "0.13.3",
23 | "esbuild-freebsd-arm64": "0.13.3",
24 | "esbuild-linux-32": "0.13.3",
25 | "esbuild-linux-64": "0.13.3",
26 | "esbuild-linux-arm": "0.13.3",
27 | "esbuild-linux-arm64": "0.13.3",
28 | "esbuild-linux-mips64le": "0.13.3",
29 | "esbuild-linux-ppc64le": "0.13.3",
30 | "esbuild-openbsd-64": "0.13.3",
31 | "esbuild-sunos-64": "0.13.3",
32 | "esbuild-windows-32": "0.13.3",
33 | "esbuild-windows-64": "0.13.3",
34 | "esbuild-windows-arm64": "0.13.3"
35 | }
36 | },
37 | "esbuild-android-arm64": {
38 | "version": "0.13.3",
39 | "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.13.3.tgz",
40 | "integrity": "sha512-jc9E8vGTHkzb0Vwl74H8liANV9BWsqtzLHaKvcsRgf1M+aVCBSF0gUheduAKfDsbDMT0judeMLhwBP34EUesTA==",
41 | "dev": true,
42 | "optional": true
43 | },
44 | "esbuild-darwin-64": {
45 | "version": "0.13.3",
46 | "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.13.3.tgz",
47 | "integrity": "sha512-8bG3Zq+ZNuLlIJebOO2+weI7P2LVf33sOzaUfHj8MuJ+1Ixe4KtQxfYp7qhFnP6xP2ToJaYHxGUfLeiUCEz9hw==",
48 | "dev": true,
49 | "optional": true
50 | },
51 | "esbuild-darwin-arm64": {
52 | "version": "0.13.3",
53 | "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.13.3.tgz",
54 | "integrity": "sha512-5E81eImYtTgh8pY7Gq4WQHhWkR/LvYadUXmuYeZBiP+3ADZJZcG60UFceZrjqNPaFOWKr/xmh4aNocwagEubcA==",
55 | "dev": true,
56 | "optional": true
57 | },
58 | "esbuild-freebsd-64": {
59 | "version": "0.13.3",
60 | "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.13.3.tgz",
61 | "integrity": "sha512-ou+f91KkTGexi8HvF/BdtsITL6plbciQfZGys7QX6/QEwyE96PmL5KnU6ZQwoU7E99Ts6Sc9bUDq8HXJubKtBA==",
62 | "dev": true,
63 | "optional": true
64 | },
65 | "esbuild-freebsd-arm64": {
66 | "version": "0.13.3",
67 | "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.13.3.tgz",
68 | "integrity": "sha512-F1zV7nySjHswJuvIgjkiG5liZ63MeazDGXGKViTCeegjZ71sAhOChcaGhKcu6vq9+vqZxlfEi1fmXlx6Pc3coQ==",
69 | "dev": true,
70 | "optional": true
71 | },
72 | "esbuild-linux-32": {
73 | "version": "0.13.3",
74 | "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.13.3.tgz",
75 | "integrity": "sha512-mHHc2v6uLrHH4zaaq5RB/5IWzgimEJ1HGldzf1qtGI513KZWfH0HRRQ8p1di4notJgBn7tDzWQ1f34ZHy69viQ==",
76 | "dev": true,
77 | "optional": true
78 | },
79 | "esbuild-linux-64": {
80 | "version": "0.13.3",
81 | "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.13.3.tgz",
82 | "integrity": "sha512-FJ1De2O89mrOuqtaEXu41qIYJU6R41F+OA6vheNwcAQcX8fu0aiA13FJeLABq29BYJuTVgRj3cyC8q+tz19/dQ==",
83 | "dev": true,
84 | "optional": true
85 | },
86 | "esbuild-linux-arm": {
87 | "version": "0.13.3",
88 | "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.13.3.tgz",
89 | "integrity": "sha512-9BJNRtLwBh3OP22cln9g3AJdbAQUcjRHqA4BScx9k4RZpGqPokFr548zpeplxWhcwrIjT8qPebwH9CrRVy8Bsw==",
90 | "dev": true,
91 | "optional": true
92 | },
93 | "esbuild-linux-arm64": {
94 | "version": "0.13.3",
95 | "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.13.3.tgz",
96 | "integrity": "sha512-Cauhr45KSo+wRUojs+1qfycQqQCAXTOvsWvkZ6xmEMAXLAm+f8RQGDQeP8CAf8Yeelnegcn6UNdvzdzLHhWDFg==",
97 | "dev": true,
98 | "optional": true
99 | },
100 | "esbuild-linux-mips64le": {
101 | "version": "0.13.3",
102 | "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.13.3.tgz",
103 | "integrity": "sha512-YVzJUGCncuuLm2boYyVeuMFsak4ZAhdiBwi0xNDZCC8sy+tS6Boe2mzcrD2uubv5JKAUOrpN186S1DtU4WgBgw==",
104 | "dev": true,
105 | "optional": true
106 | },
107 | "esbuild-linux-ppc64le": {
108 | "version": "0.13.3",
109 | "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.13.3.tgz",
110 | "integrity": "sha512-GU6CqqKtJEoyxC2QWHiJtmuOz9wc/jMv8ZloK2WwiGY5yMvAmM3PI103Dj7xcjebNTHBqITTUw/aigY1wx5A3w==",
111 | "dev": true,
112 | "optional": true
113 | },
114 | "esbuild-openbsd-64": {
115 | "version": "0.13.3",
116 | "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.13.3.tgz",
117 | "integrity": "sha512-HVpkgpn4BQt4BPDAjTOpeMub6mzNWw6Y3gaLQJrpbO24pws6ZwYkY24OI3/Uo3LDCbH6856MM81JxECt92OWjA==",
118 | "dev": true,
119 | "optional": true
120 | },
121 | "esbuild-sunos-64": {
122 | "version": "0.13.3",
123 | "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.13.3.tgz",
124 | "integrity": "sha512-XncBVOtnEfUbPV4CaiFBxh38ychnBfwCxuTm9iAqcHzIwkmeNRN5qMzDyfE1jyfJje+Bbt6AvIfz6SdYt8/UEQ==",
125 | "dev": true,
126 | "optional": true
127 | },
128 | "esbuild-windows-32": {
129 | "version": "0.13.3",
130 | "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.13.3.tgz",
131 | "integrity": "sha512-ZlgDz7d1nk8wQACi+z8IDzNZVUlN9iprAme+1YSTsfFDlkyI8jeaGWPk9EQFNY7rJzsLVYm6eZ2mhPioc7uT5A==",
132 | "dev": true,
133 | "optional": true
134 | },
135 | "esbuild-windows-64": {
136 | "version": "0.13.3",
137 | "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.13.3.tgz",
138 | "integrity": "sha512-YX7KvRez3TR+GudlQm9tND/ssj2FsF9vb8ZWzAoZOLxpPzE3y+3SFJNrfDzzQKPzJ0Pnh9KBP4gsaMwJjKHDhw==",
139 | "dev": true,
140 | "optional": true
141 | },
142 | "esbuild-windows-arm64": {
143 | "version": "0.13.3",
144 | "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.13.3.tgz",
145 | "integrity": "sha512-nP7H0Y2a6OJd3Qi1Q8sehhyP4x4JoXK4S5y6FzH2vgaJgiyEurzFxjUufGdMaw+RxtxiwD/uRndUgwaZ2JD8lg==",
146 | "dev": true,
147 | "optional": true
148 | },
149 | "fsevents": {
150 | "version": "2.3.2",
151 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
152 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
153 | "dev": true,
154 | "optional": true
155 | },
156 | "function-bind": {
157 | "version": "1.1.1",
158 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
159 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
160 | "dev": true
161 | },
162 | "gl-matrix": {
163 | "version": "3.3.0",
164 | "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.3.0.tgz",
165 | "integrity": "sha512-COb7LDz+SXaHtl/h4LeaFcNdJdAQSDeVqjiIihSXNrkWObZLhDI4hIkZC11Aeqp7bcE72clzB0BnDXr2SmslRA=="
166 | },
167 | "has": {
168 | "version": "1.0.3",
169 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
170 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
171 | "dev": true,
172 | "requires": {
173 | "function-bind": "^1.1.1"
174 | }
175 | },
176 | "is-core-module": {
177 | "version": "2.7.0",
178 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.7.0.tgz",
179 | "integrity": "sha512-ByY+tjCciCr+9nLryBYcSD50EOGWt95c7tIsKTG1J2ixKKXPvF7Ej3AVd+UfDydAJom3biBGDBALaO79ktwgEQ==",
180 | "dev": true,
181 | "requires": {
182 | "has": "^1.0.3"
183 | }
184 | },
185 | "nanocolors": {
186 | "version": "0.2.12",
187 | "resolved": "https://registry.npmjs.org/nanocolors/-/nanocolors-0.2.12.tgz",
188 | "integrity": "sha512-SFNdALvzW+rVlzqexid6epYdt8H9Zol7xDoQarioEFcFN0JHo4CYNztAxmtfgGTVRCmFlEOqqhBpoFGKqSAMug==",
189 | "dev": true
190 | },
191 | "nanoid": {
192 | "version": "3.1.28",
193 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.28.tgz",
194 | "integrity": "sha512-gSu9VZ2HtmoKYe/lmyPFES5nknFrHa+/DT9muUFWFMi6Jh9E1I7bkvlQ8xxf1Kos9pi9o8lBnIOkatMhKX/YUw==",
195 | "dev": true
196 | },
197 | "path-parse": {
198 | "version": "1.0.7",
199 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
200 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
201 | "dev": true
202 | },
203 | "postcss": {
204 | "version": "8.3.8",
205 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.8.tgz",
206 | "integrity": "sha512-GT5bTjjZnwDifajzczOC+r3FI3Cu+PgPvrsjhQdRqa2kTJ4968/X9CUce9xttIB0xOs5c6xf0TCWZo/y9lF6bA==",
207 | "dev": true,
208 | "requires": {
209 | "nanocolors": "^0.2.2",
210 | "nanoid": "^3.1.25",
211 | "source-map-js": "^0.6.2"
212 | }
213 | },
214 | "querystringify": {
215 | "version": "2.2.0",
216 | "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
217 | "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ=="
218 | },
219 | "regl": {
220 | "version": "2.1.0",
221 | "resolved": "https://registry.npmjs.org/regl/-/regl-2.1.0.tgz",
222 | "integrity": "sha512-oWUce/aVoEvW5l2V0LK7O5KJMzUSKeiOwFuJehzpSFd43dO5spP9r+sSUfhKtsky4u6MCqWJaRL+abzExynfTg=="
223 | },
224 | "requires-port": {
225 | "version": "1.0.0",
226 | "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
227 | "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
228 | },
229 | "resolve": {
230 | "version": "1.20.0",
231 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
232 | "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
233 | "dev": true,
234 | "requires": {
235 | "is-core-module": "^2.2.0",
236 | "path-parse": "^1.0.6"
237 | }
238 | },
239 | "rollup": {
240 | "version": "2.57.0",
241 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.57.0.tgz",
242 | "integrity": "sha512-bKQIh1rWKofRee6mv8SrF2HdP6pea5QkwBZSMImJysFj39gQuiV8MEPBjXOCpzk3wSYp63M2v2wkWBmFC8O/rg==",
243 | "dev": true,
244 | "requires": {
245 | "fsevents": "~2.3.2"
246 | }
247 | },
248 | "source-map-js": {
249 | "version": "0.6.2",
250 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz",
251 | "integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==",
252 | "dev": true
253 | },
254 | "typescript": {
255 | "version": "4.4.3",
256 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.3.tgz",
257 | "integrity": "sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==",
258 | "dev": true
259 | },
260 | "url-parse": {
261 | "version": "1.5.3",
262 | "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.3.tgz",
263 | "integrity": "sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ==",
264 | "requires": {
265 | "querystringify": "^2.1.1",
266 | "requires-port": "^1.0.0"
267 | }
268 | },
269 | "vite": {
270 | "version": "2.6.2",
271 | "resolved": "https://registry.npmjs.org/vite/-/vite-2.6.2.tgz",
272 | "integrity": "sha512-HSIg9U15LOnbD3CUxX364Pdrm7DUjftuBljowGxvkFHgDZU/SKPqApg9t86MX/Qq1VCO7wS+mGJHlfuTF7c0Sg==",
273 | "dev": true,
274 | "requires": {
275 | "esbuild": "^0.13.2",
276 | "fsevents": "~2.3.2",
277 | "postcss": "^8.3.8",
278 | "resolve": "^1.20.0",
279 | "rollup": "^2.57.0"
280 | }
281 | }
282 | }
283 | }
284 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "instanced-lines-2",
3 | "version": "0.0.0",
4 | "scripts": {
5 | "dev": "vite --host 0.0.0.0",
6 | "build": "tsc && vite build",
7 | "serve": "vite preview"
8 | },
9 | "files": [
10 | "dist"
11 | ],
12 | "main": "./dist/index.umd.js",
13 | "module": "./dist/index.es.js",
14 | "exports": {
15 | ".": {
16 | "import": "./dist/index.es.js",
17 | "require": "./dist/index.umd.js"
18 | }
19 | },
20 | "devDependencies": {
21 | "@types/url-parse": "^1.4.4",
22 | "typescript": "^4.3.2",
23 | "vite": "^2.6.0"
24 | },
25 | "dependencies": {
26 | "gl-matrix": "^3.3.0",
27 | "regl": "^2.1.0",
28 | "url-parse": "^1.5.3"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import REGL from "regl";
2 | import { new2d } from "./new-2d/new-2d";
3 | import { old2d } from "./old-2d/old-2d";
4 |
5 | function visible(element: HTMLElement) {
6 | const rect = element.getBoundingClientRect();
7 | return rect.bottom >= 0 && rect.top <= (window.innerHeight || document.documentElement.clientHeight);
8 | }
9 |
10 | const canvas = document.createElement("canvas");
11 | const regl = REGL({ canvas, extensions: ["ANGLE_instanced_arrays"] });
12 |
13 | const renderNew = new2d(regl);
14 |
15 | (window as any).newStrip = function (
16 | canvasid: string,
17 | color: boolean,
18 | join: "miter" | "bevel" | "round" | "none",
19 | cap: "round" | "square" | "none",
20 | terminal: boolean,
21 | alpha: number
22 | ) {
23 | function loop() {
24 | requestAnimationFrame(loop);
25 | const targetcanvas = document.getElementById(canvasid)! as HTMLCanvasElement;
26 | if (!visible(targetcanvas)) return;
27 | if (targetcanvas.width !== targetcanvas.clientWidth || targetcanvas.height !== targetcanvas.clientHeight) {
28 | targetcanvas.width = targetcanvas.clientWidth;
29 | targetcanvas.height = targetcanvas.clientHeight;
30 | }
31 | if (canvas.width !== targetcanvas.clientWidth || canvas.height !== targetcanvas.clientHeight) {
32 | canvas.width = targetcanvas.clientWidth;
33 | canvas.height = targetcanvas.clientHeight;
34 | }
35 | renderNew(targetcanvas, color, join, cap, terminal, alpha);
36 | const ctx = targetcanvas.getContext("2d");
37 | ctx?.clearRect(0, 0, targetcanvas.width, targetcanvas.height);
38 | ctx?.drawImage(canvas, 0, 0);
39 | }
40 | requestAnimationFrame(loop);
41 | };
42 |
43 | const renderOld = old2d(regl);
44 |
45 | (window as any).oldStrip = function (canvasid: string, segments: boolean, alpha: number) {
46 | function loop() {
47 | requestAnimationFrame(loop);
48 | const targetcanvas = document.getElementById(canvasid)! as HTMLCanvasElement;
49 | if (!visible(targetcanvas)) return;
50 | if (targetcanvas.width !== targetcanvas.clientWidth || targetcanvas.height !== targetcanvas.clientHeight) {
51 | targetcanvas.width = targetcanvas.clientWidth;
52 | targetcanvas.height = targetcanvas.clientHeight;
53 | }
54 | if (canvas.width !== targetcanvas.clientWidth || canvas.height !== targetcanvas.clientHeight) {
55 | canvas.width = targetcanvas.clientWidth;
56 | canvas.height = targetcanvas.clientHeight;
57 | }
58 | renderOld(targetcanvas, segments, alpha);
59 | const ctx = targetcanvas.getContext("2d");
60 | ctx?.clearRect(0, 0, targetcanvas.width, targetcanvas.height);
61 | ctx?.drawImage(canvas, 0, 0);
62 | }
63 | requestAnimationFrame(loop);
64 | };
65 |
--------------------------------------------------------------------------------
/src/new-2d/bevel-join.ts:
--------------------------------------------------------------------------------
1 | import { Regl } from "regl";
2 |
3 | const geometry = [
4 | [1, 0, 0],
5 | [0, 1, 0],
6 | [0, 0, 1],
7 | ];
8 |
9 | export function bevelJoinCommand(regl: Regl) {
10 | return regl({
11 | vert: `
12 | precision highp float;
13 | attribute vec2 pointA, pointB, pointC;
14 | attribute vec3 position;
15 | uniform float width;
16 | uniform mat4 projection;
17 |
18 | void main() {
19 | vec2 tangent = normalize(normalize(pointC - pointB) + normalize(pointB - pointA));
20 | vec2 normal = vec2(-tangent.y, tangent.x);
21 | vec2 ab = pointB - pointA;
22 | vec2 cb = pointB - pointC;
23 | float sigma = sign(dot(ab + cb, normal));
24 | vec2 abn = normalize(vec2(-ab.y, ab.x));
25 | vec2 cbn = -normalize(vec2(-cb.y, cb.x));
26 | vec2 p0 = 0.5 * sigma * width * (sigma < 0.0 ? abn : cbn);
27 | vec2 p1 = 0.5 * sigma * width * (sigma < 0.0 ? cbn : abn);
28 | vec2 p2 = -0.5 * normal * sigma * width / dot(normal, abn);
29 | vec2 point = pointB + position.x * p0 + position.y * p1 + position.z * p2;
30 | gl_Position = projection * vec4(point, 0, 1);
31 | }`,
32 |
33 | frag: `
34 | precision highp float;
35 | uniform vec4 color;
36 | void main() {
37 | gl_FragColor = color;
38 | }`,
39 |
40 | depth: {
41 | enable: false,
42 | },
43 |
44 | attributes: {
45 | position: {
46 | buffer: regl.buffer(geometry),
47 | divisor: 0,
48 | },
49 | pointA: {
50 | buffer: regl.prop("points"),
51 | divisor: 1,
52 | offset: Float32Array.BYTES_PER_ELEMENT * 0,
53 | },
54 | pointB: {
55 | buffer: regl.prop("points"),
56 | divisor: 1,
57 | offset: Float32Array.BYTES_PER_ELEMENT * 2,
58 | },
59 | pointC: {
60 | buffer: regl.prop("points"),
61 | divisor: 1,
62 | offset: Float32Array.BYTES_PER_ELEMENT * 4,
63 | },
64 | },
65 |
66 | uniforms: {
67 | width: regl.prop("width"),
68 | color: regl.prop("color"),
69 | projection: regl.prop("projection"),
70 | },
71 |
72 | blend: {
73 | enable: true,
74 | func: {
75 | src: "src alpha",
76 | dst: "one minus src alpha",
77 | },
78 | },
79 |
80 | cull: {
81 | enable: true,
82 | face: "back",
83 | },
84 |
85 | count: geometry.length,
86 | instances: regl.prop("instances"),
87 | viewport: regl.prop("viewport"),
88 | });
89 | }
90 |
--------------------------------------------------------------------------------
/src/new-2d/caps.ts:
--------------------------------------------------------------------------------
1 | import { Regl } from "regl";
2 |
3 | interface Geometry {
4 | positions: number[][];
5 | cells: number[][];
6 | }
7 |
8 | export function roundCapGeometry(resolution: number) {
9 | const positions = [[0, 0]];
10 | for (let i = 0; i <= resolution; i++) {
11 | const theta = -0.5 * Math.PI + (Math.PI * i) / resolution;
12 | positions.push([0.5 * Math.cos(theta), 0.5 * Math.sin(theta)]);
13 | }
14 | const cells: number[][] = [];
15 | for (let i = 0; i < resolution; i++) {
16 | cells.push([0, i + 1, i + 2]);
17 | }
18 | return { positions, cells };
19 | }
20 |
21 | export function squareCapGeometry() {
22 | return {
23 | positions: [
24 | [0, 0.5],
25 | [0, -0.5],
26 | [0.5, -0.5],
27 | [0.5, 0.5],
28 | ],
29 | cells: [
30 | [0, 1, 2],
31 | [0, 2, 3],
32 | ],
33 | };
34 | }
35 |
36 | export function capCommand(regl: Regl, geometry: Geometry) {
37 | return regl({
38 | vert: `
39 | precision highp float;
40 | attribute vec2 position;
41 | attribute vec2 pA, pB;
42 | uniform float width;
43 | uniform mat4 projection;
44 |
45 | void main() {
46 | vec2 xBasis = normalize(pA - pB);
47 | vec2 yBasis = vec2(-xBasis.y, xBasis.x);
48 | vec2 point = pA + xBasis * width * position.x + yBasis * width * position.y;
49 | gl_Position = projection * vec4(point, 0, 1);
50 | }`,
51 |
52 | frag: `
53 | precision highp float;
54 | uniform vec4 color;
55 | void main() {
56 | gl_FragColor = color;
57 | }`,
58 |
59 | attributes: {
60 | position: {
61 | buffer: regl.buffer(geometry.positions),
62 | divisor: 0,
63 | },
64 | pA: {
65 | buffer: regl.prop("points"),
66 | divisor: 1,
67 | offset: Float32Array.BYTES_PER_ELEMENT * 0,
68 | stride: Float32Array.BYTES_PER_ELEMENT * 4,
69 | },
70 | pB: {
71 | buffer: regl.prop("points"),
72 | divisor: 1,
73 | offset: Float32Array.BYTES_PER_ELEMENT * 2,
74 | stride: Float32Array.BYTES_PER_ELEMENT * 4,
75 | },
76 | },
77 |
78 | uniforms: {
79 | width: regl.prop("width"),
80 | color: regl.prop("color"),
81 | projection: regl.prop("projection"),
82 | },
83 |
84 | blend: {
85 | enable: true,
86 | func: {
87 | src: "src alpha",
88 | dst: "one minus src alpha",
89 | },
90 | },
91 |
92 | cull: {
93 | enable: true,
94 | face: "back",
95 | },
96 |
97 | depth: {
98 | enable: false,
99 | },
100 |
101 | elements: regl.elements(geometry.cells),
102 | instances: regl.prop("instances"),
103 | viewport: regl.prop("viewport"),
104 | });
105 | }
106 |
--------------------------------------------------------------------------------
/src/new-2d/interleaved-strip.ts:
--------------------------------------------------------------------------------
1 | import { Regl } from "regl";
2 |
3 | const geometry = {
4 | positions: [
5 | [0, -0.5],
6 | [1, -0.5],
7 | [1, 0.5],
8 | [0, 0.5],
9 | ],
10 | cells: [
11 | [0, 1, 2],
12 | [0, 2, 3],
13 | ],
14 | };
15 |
16 | export function interleavedStripCommand(regl: Regl) {
17 | return regl({
18 | vert: `
19 | precision highp float;
20 | attribute vec2 position;
21 | attribute vec2 pA, pB, pC, pD;
22 | uniform float width;
23 | uniform mat4 projection;
24 |
25 | void main() {
26 | // Select the three points we'll use and adjust the vertex according to
27 | // the side of the segment the vertex is on and the order of the points.
28 | vec2 p0 = pA;
29 | vec2 p1 = pB;
30 | vec2 p2 = pC;
31 | vec2 pos = position;
32 | if (position.x == 1.0) {
33 | p0 = pD;
34 | p1 = pC;
35 | p2 = pB;
36 | pos = vec2(1.0 - position.x, -position.y);
37 | }
38 |
39 | // Find the normal vector.
40 | vec2 tangent = normalize(normalize(p2 - p1) + normalize(p1 - p0));
41 | vec2 normal = vec2(-tangent.y, tangent.x);
42 |
43 | // Find the perpendicular vectors.
44 | vec2 p01 = p1 - p0;
45 | vec2 p21 = p1 - p2;
46 | vec2 p01Norm = normalize(vec2(-p01.y, p01.x));
47 |
48 | // Determine the bend direction.
49 | float sigma = sign(dot(p01 + p21, normal));
50 |
51 | // If this is the intersecting vertex,
52 | if (sign(pos.y) == -sigma) {
53 | vec2 point = 0.5 * normal * -sigma * width / dot(normal, p01Norm);
54 | gl_Position = projection * vec4(p1 + point, 0, 1);
55 | } else {
56 | vec2 xBasis = p2 - p1;
57 | vec2 yBasis = normalize(vec2(-xBasis.y, xBasis.x));
58 | vec2 point = p1 + xBasis * pos.x + yBasis * width * pos.y;
59 | gl_Position = projection * vec4(point, 0, 1);
60 | }
61 | }`,
62 |
63 | frag: `
64 | precision highp float;
65 | uniform vec4 color;
66 | void main() {
67 | gl_FragColor = color;
68 | }`,
69 |
70 | attributes: {
71 | position: {
72 | buffer: regl.buffer(geometry.positions),
73 | divisor: 0,
74 | },
75 | pA: {
76 | buffer: regl.prop("points"),
77 | divisor: 1,
78 | offset: Float32Array.BYTES_PER_ELEMENT * 0,
79 | },
80 | pB: {
81 | buffer: regl.prop("points"),
82 | divisor: 1,
83 | offset: Float32Array.BYTES_PER_ELEMENT * 2,
84 | },
85 | pC: {
86 | buffer: regl.prop("points"),
87 | divisor: 1,
88 | offset: Float32Array.BYTES_PER_ELEMENT * 4,
89 | },
90 | pD: {
91 | buffer: regl.prop("points"),
92 | divisor: 1,
93 | offset: Float32Array.BYTES_PER_ELEMENT * 6,
94 | },
95 | },
96 |
97 | uniforms: {
98 | width: regl.prop("width"),
99 | color: regl.prop("color"),
100 | projection: regl.prop("projection"),
101 | },
102 |
103 | blend: {
104 | enable: true,
105 | func: {
106 | src: "src alpha",
107 | dst: "one minus src alpha",
108 | },
109 | },
110 |
111 | cull: {
112 | enable: true,
113 | face: "back",
114 | },
115 |
116 | depth: {
117 | enable: false,
118 | },
119 |
120 | elements: regl.elements(geometry.cells),
121 | instances: regl.prop("segments"),
122 | viewport: regl.prop("viewport"),
123 | });
124 | }
125 |
126 | export function interleavedStripTerminalCommand(regl: Regl) {
127 | return regl({
128 | vert: `
129 | precision highp float;
130 | attribute vec2 position;
131 | attribute vec2 pA, pB, pC;
132 | uniform float width;
133 | uniform mat4 projection;
134 |
135 | void main() {
136 |
137 | if (position.x == 0.0) {
138 | vec2 xBasis = pB - pA;
139 | vec2 yBasis = normalize(vec2(-xBasis.y, xBasis.x));
140 | vec2 point = pA + xBasis * position.x + yBasis * width * position.y;
141 | gl_Position = projection * vec4(point, 0, 1);
142 | return;
143 | }
144 |
145 | // Find the normal vector.
146 | vec2 tangent = normalize(normalize(pC - pB) + normalize(pB - pA));
147 | vec2 normal = vec2(-tangent.y, tangent.x);
148 |
149 | // Find the perpendicular vectors.
150 | vec2 ab = pB - pA;
151 | vec2 cb = pB - pC;
152 | vec2 abNorm = normalize(vec2(-ab.y, ab.x));
153 |
154 | // Determine the bend direction.
155 | float sigma = sign(dot(ab + cb, normal));
156 |
157 | if (sign(position.y) == -sigma) {
158 | vec2 position = 0.5 * normal * -sigma * width / dot(normal, abNorm);
159 | gl_Position = projection * vec4(pB + position, 0, 1);
160 | } else {
161 | vec2 xBasis = pB - pA;
162 | vec2 yBasis = normalize(vec2(-xBasis.y, xBasis.x));
163 | vec2 point = pA + xBasis * position.x + yBasis * width * position.y;
164 | gl_Position = projection * vec4(point, 0, 1);
165 | }
166 | }`,
167 |
168 | frag: `
169 | precision highp float;
170 | uniform vec4 color;
171 | void main() {
172 | gl_FragColor = color;
173 | }`,
174 |
175 | attributes: {
176 | position: {
177 | buffer: regl.buffer(geometry.positions),
178 | divisor: 0,
179 | },
180 | pA: {
181 | buffer: regl.prop("points"),
182 | divisor: 1,
183 | offset: Float32Array.BYTES_PER_ELEMENT * 0,
184 | stride: Float32Array.BYTES_PER_ELEMENT * 6,
185 | },
186 | pB: {
187 | buffer: regl.prop("points"),
188 | divisor: 1,
189 | offset: Float32Array.BYTES_PER_ELEMENT * 2,
190 | stride: Float32Array.BYTES_PER_ELEMENT * 6,
191 | },
192 | pC: {
193 | buffer: regl.prop("points"),
194 | divisor: 1,
195 | offset: Float32Array.BYTES_PER_ELEMENT * 4,
196 | stride: Float32Array.BYTES_PER_ELEMENT * 6,
197 | },
198 | },
199 |
200 | uniforms: {
201 | width: regl.prop("width"),
202 | color: regl.prop("color"),
203 | projection: regl.prop("projection"),
204 | },
205 |
206 | blend: {
207 | enable: true,
208 | func: {
209 | src: "src alpha",
210 | dst: "one minus src alpha",
211 | },
212 | },
213 |
214 | cull: {
215 | enable: true,
216 | face: "back",
217 | },
218 |
219 | depth: {
220 | enable: false,
221 | },
222 |
223 | elements: regl.elements(geometry.cells),
224 | instances: regl.prop("segments"),
225 | viewport: regl.prop("viewport"),
226 | });
227 | }
228 |
--------------------------------------------------------------------------------
/src/new-2d/miter-join.ts:
--------------------------------------------------------------------------------
1 | import { Regl } from "regl";
2 |
3 | const geometry = {
4 | positions: [
5 | [1, 0, 0, 0],
6 | [0, 1, 0, 0],
7 | [0, 0, 1, 0],
8 | [0, 0, 0, 1],
9 | ],
10 | cells: [
11 | [0, 1, 2],
12 | [0, 2, 3],
13 | ],
14 | };
15 |
16 | export function miterJoinCommand(regl: Regl) {
17 | return regl({
18 | vert: `
19 | precision highp float;
20 | attribute vec2 pointA, pointB, pointC;
21 | attribute vec4 position;
22 | uniform float width;
23 | uniform mat4 projection;
24 |
25 | void main() {
26 | // Find the miter vector.
27 | vec2 tangent = normalize(normalize(pointC - pointB) + normalize(pointB - pointA));
28 | vec2 miter = vec2(-tangent.y, tangent.x);
29 |
30 | // Find the perpendicular vectors.
31 | vec2 ab = pointB - pointA;
32 | vec2 cb = pointB - pointC;
33 | vec2 abNorm = normalize(vec2(-ab.y, ab.x));
34 | vec2 cbNorm = -normalize(vec2(-cb.y, cb.x));
35 |
36 | // Determine the bend direction.
37 | float sigma = sign(dot(ab + cb, miter));
38 |
39 | // Calculate the basis vectors for the miter geometry.
40 | vec2 p0 = 0.5 * width * sigma * (sigma < 0.0 ? abNorm : cbNorm);
41 | vec2 p1 = 0.5 * miter * sigma * width / dot(miter, abNorm);
42 | vec2 p2 = 0.5 * width * sigma * (sigma < 0.0 ? cbNorm : abNorm);
43 | vec2 p3 = -0.5 * miter * sigma * width / dot(miter, abNorm);
44 |
45 | // Calculate the final point position.
46 | vec2 point = pointB + position.x * p0 + position.y * p1 + position.z * p2 + position.w * p3;
47 | gl_Position = projection * vec4(point, 0, 1);
48 | }`,
49 |
50 | frag: `
51 | precision highp float;
52 | uniform vec4 color;
53 | void main() {
54 | gl_FragColor = color;
55 | }`,
56 |
57 | depth: {
58 | enable: false,
59 | },
60 |
61 | attributes: {
62 | position: {
63 | buffer: regl.buffer(geometry.positions),
64 | divisor: 0,
65 | },
66 | pointA: {
67 | buffer: regl.prop("points"),
68 | divisor: 1,
69 | offset: Float32Array.BYTES_PER_ELEMENT * 0,
70 | },
71 | pointB: {
72 | buffer: regl.prop("points"),
73 | divisor: 1,
74 | offset: Float32Array.BYTES_PER_ELEMENT * 2,
75 | },
76 | pointC: {
77 | buffer: regl.prop("points"),
78 | divisor: 1,
79 | offset: Float32Array.BYTES_PER_ELEMENT * 4,
80 | },
81 | },
82 |
83 | uniforms: {
84 | width: regl.prop("width"),
85 | color: regl.prop("color"),
86 | projection: regl.prop("projection"),
87 | },
88 |
89 | blend: {
90 | enable: true,
91 | func: {
92 | src: "src alpha",
93 | dst: "one minus src alpha",
94 | },
95 | },
96 |
97 | cull: {
98 | enable: true,
99 | face: "back",
100 | },
101 |
102 | elements: regl.elements(geometry.cells),
103 | instances: regl.prop("instances"),
104 | viewport: regl.prop("viewport"),
105 | });
106 | }
107 |
--------------------------------------------------------------------------------
/src/new-2d/new-2d.ts:
--------------------------------------------------------------------------------
1 | import { mat4 } from "gl-matrix";
2 | import { Regl } from "regl";
3 |
4 | import { interleavedStripCommand, interleavedStripTerminalCommand } from "./interleaved-strip";
5 | import { miterJoinCommand } from "./miter-join";
6 | import { bevelJoinCommand } from "./bevel-join";
7 | import { roundJoinCommand } from "./round-join";
8 | import { capCommand, roundCapGeometry, squareCapGeometry } from "./caps";
9 |
10 | function generateSamplePointsInterleaved(width: number, height: number) {
11 | const stepx = width / 9;
12 | const stepy = height / 10;
13 | const points = [];
14 | for (let x = 1; x < 9; x += 2) {
15 | points.push([(x + 0) * stepx - width / 2, 3 * stepy - height / 2]);
16 | points.push([(x + 1) * stepx - width / 2, 7 * stepy - height / 2]);
17 | }
18 | return points;
19 | }
20 |
21 | export function new2d(regl: Regl) {
22 | const bevelJoin = bevelJoinCommand(regl);
23 | const miterJoin = miterJoinCommand(regl);
24 | const roundJoin = roundJoinCommand(regl, 16);
25 |
26 | const roundCap = capCommand(regl, roundCapGeometry(16));
27 | const squareCap = capCommand(regl, squareCapGeometry());
28 |
29 | const interleavedStrip = interleavedStripCommand(regl);
30 | const interleavedStripTerminal = interleavedStripTerminalCommand(regl);
31 |
32 | const pointsBuffer = regl.buffer(0);
33 |
34 | function render(
35 | canvas: HTMLCanvasElement,
36 | color: boolean,
37 | join: "miter" | "bevel" | "round" | "none",
38 | cap: "round" | "square" | "none",
39 | terminal: boolean,
40 | alpha: number
41 | ) {
42 | const points = generateSamplePointsInterleaved(canvas.width, canvas.height);
43 | const projection = mat4.ortho(mat4.create(), -canvas.width / 2, canvas.width / 2, -canvas.height / 2, canvas.height / 2, 0, -1);
44 | const viewport = { x: 0, y: 0, width: canvas.width, height: canvas.height };
45 |
46 | const scaleX = 0.45 * Math.sin(performance.now() * 0.002) + 0.75;
47 | const scaleY = Math.sin(performance.now() * 0.0003);
48 | const scaledPoints = [];
49 | for (const point of points) {
50 | scaledPoints.push([point[0] * scaleX, point[1] * scaleY]);
51 | }
52 | regl.clear({ color: [0, 0, 0, 0] });
53 | interleavedStrip({
54 | points: pointsBuffer(scaledPoints),
55 | segments: points.length - 3,
56 | width: canvas.width * 0.05,
57 | color: color ? [1, 0, 0, alpha] : [0.25, 0.25, 0.25, alpha],
58 | projection,
59 | viewport,
60 | });
61 | if (terminal) {
62 | interleavedStripTerminal({
63 | points: pointsBuffer([
64 | scaledPoints[0],
65 | scaledPoints[1],
66 | scaledPoints[2],
67 | scaledPoints[points.length - 1],
68 | scaledPoints[points.length - 2],
69 | scaledPoints[points.length - 3],
70 | ]),
71 | segments: 2,
72 | width: canvas.width * 0.05,
73 | color: color ? [0, 0.5, 0, alpha] : [0.25, 0.25, 0.25, alpha],
74 | projection,
75 | viewport,
76 | });
77 | }
78 | const joinCommand = {
79 | miter: miterJoin,
80 | bevel: bevelJoin,
81 | round: roundJoin,
82 | none: undefined,
83 | }[join];
84 | if (joinCommand) {
85 | joinCommand({
86 | points: pointsBuffer(scaledPoints),
87 | instances: points.length - 2,
88 | width: canvas.width * 0.05,
89 | color: color ? [0, 0, 1, alpha] : [0.25, 0.25, 0.25, alpha],
90 | projection,
91 | viewport,
92 | });
93 | }
94 | const capCommand = {
95 | round: roundCap,
96 | square: squareCap,
97 | none: undefined,
98 | }[cap];
99 | if (capCommand) {
100 | capCommand({
101 | points: pointsBuffer([scaledPoints[0], scaledPoints[1], scaledPoints[points.length - 1], scaledPoints[points.length - 2]]),
102 | instances: 2,
103 | width: canvas.width * 0.05,
104 | color: color ? [1, 0, 1, alpha] : [0.25, 0.25, 0.25, alpha],
105 | projection,
106 | viewport,
107 | });
108 | }
109 | }
110 |
111 | return render;
112 | }
113 |
--------------------------------------------------------------------------------
/src/new-2d/round-join.ts:
--------------------------------------------------------------------------------
1 | import { Regl } from "regl";
2 |
3 | function roundGeometry(resolution: number) {
4 | const ids: number[] = [];
5 | const cells: number[][] = [];
6 |
7 | for (let i = 0; i < resolution + 2; i++) {
8 | ids.push(i);
9 | }
10 |
11 | for (let i = 0; i < resolution; i++) {
12 | cells.push([0, i + 1, i + 2]);
13 | }
14 |
15 | return {
16 | ids,
17 | cells,
18 | };
19 | }
20 |
21 | export function roundJoinCommand(regl: Regl, resolution: number) {
22 | const geometry = roundGeometry(resolution);
23 | return regl({
24 | vert: `
25 | precision highp float;
26 | attribute vec2 pointA, pointB, pointC;
27 | attribute float id;
28 | uniform float width;
29 | uniform mat4 projection;
30 |
31 | const float resolution = ${resolution.toExponential()};
32 |
33 | void main() {
34 | // Calculate the x- and y- basis vectors.
35 | vec2 xBasis = normalize(normalize(pointC - pointB) + normalize(pointB - pointA));
36 | vec2 yBasis = vec2(-xBasis.y, xBasis.x);
37 |
38 | // Calculate the normal vectors for each neighboring segment.
39 | vec2 ab = pointB - pointA;
40 | vec2 cb = pointB - pointC;
41 | vec2 abn = normalize(vec2(-ab.y, ab.x));
42 | vec2 cbn = -normalize(vec2(-cb.y, cb.x));
43 |
44 | // Determine the direction of the bend.
45 | float sigma = sign(dot(ab + cb, yBasis));
46 |
47 | // If this is the zeroth id, it's the center of our circle. Stretch it to meet the segments' intersection.
48 | if (id == 0.0) {
49 | gl_Position = projection * vec4(pointB + -0.5 * yBasis * sigma * width / dot(yBasis, abn), 0, 1);
50 | return;
51 | }
52 |
53 | // Otherwise find the angle for this vertex.
54 | float theta = acos(dot(abn, cbn));
55 | theta = (sigma * 0.5 * ${Math.PI}) + -0.5 * theta + theta * (id - 1.0) / resolution;
56 |
57 | // Find the vertex position from the angle and multiply it by our basis vectors.
58 | vec2 pos = 0.5 * width * vec2(cos(theta), sin(theta));
59 | pos = pointB + xBasis * pos.x + yBasis * pos.y;
60 |
61 | gl_Position = projection * vec4(pos, 0, 1);
62 | }`,
63 |
64 | frag: `
65 | precision highp float;
66 | uniform vec4 color;
67 | void main() {
68 | gl_FragColor = color;
69 | }`,
70 |
71 | depth: {
72 | enable: false,
73 | },
74 |
75 | attributes: {
76 | id: {
77 | buffer: regl.buffer(geometry.ids),
78 | divisor: 0,
79 | },
80 | pointA: {
81 | buffer: regl.prop("points"),
82 | divisor: 1,
83 | offset: Float32Array.BYTES_PER_ELEMENT * 0,
84 | },
85 | pointB: {
86 | buffer: regl.prop("points"),
87 | divisor: 1,
88 | offset: Float32Array.BYTES_PER_ELEMENT * 2,
89 | },
90 | pointC: {
91 | buffer: regl.prop("points"),
92 | divisor: 1,
93 | offset: Float32Array.BYTES_PER_ELEMENT * 4,
94 | },
95 | },
96 |
97 | uniforms: {
98 | width: regl.prop("width"),
99 | color: regl.prop("color"),
100 | projection: regl.prop("projection"),
101 | },
102 |
103 | blend: {
104 | enable: true,
105 | func: {
106 | src: "src alpha",
107 | dst: "one minus src alpha",
108 | },
109 | },
110 |
111 | cull: {
112 | enable: true,
113 | face: "back",
114 | },
115 |
116 | elements: regl.elements(geometry.cells),
117 | instances: regl.prop("instances"),
118 | viewport: regl.prop("viewport"),
119 | });
120 | }
121 |
--------------------------------------------------------------------------------
/src/new-2d/self-overlapping.ts:
--------------------------------------------------------------------------------
1 | import { mat4 } from "gl-matrix";
2 | import REGL, { DrawCommand } from "regl";
3 |
4 | import { interleavedStripCommand, interleavedStripTerminalCommand } from "./interleaved-strip";
5 | import { miterJoinCommand } from "./miter-join";
6 | import { bevelJoinCommand } from "./bevel-join";
7 | import { roundJoinCommand } from "./round-join";
8 | import { capCommand, roundCapGeometry, squareCapGeometry } from "./caps";
9 |
10 | export function selfOverlapping() {
11 | const regl = REGL({ extensions: ["ANGLE_instanced_arrays"] });
12 | const canvas = document.getElementsByTagName("canvas")[0];
13 | canvas.classList.add("grid");
14 |
15 | const projection = mat4.ortho(mat4.create(), -canvas.width / 2, canvas.width / 2, -canvas.height / 2, canvas.height / 2, 0, -1);
16 | const viewport = { x: 0, y: 0, width: canvas.width, height: canvas.height };
17 |
18 | function generateSamplePointsInterleaved(width: number, height: number) {
19 | const points = [];
20 | for (let i = 0; i < 1000; i++) {
21 | const theta = i * 0.1;
22 | const offset = -width / 3 + (i * width) / 1.5 / 1000;
23 | points.push([offset + height * 0.25 * Math.cos(theta), height * 0.25 * Math.sin(theta)]);
24 | }
25 | return points;
26 | }
27 |
28 | const points = generateSamplePointsInterleaved(canvas.width, canvas.height);
29 |
30 | const hash = window.location.hash;
31 | const colorCoded = hash.includes("color-coded");
32 | const alpha = hash.includes("alpha") ? 0.75 : 1.0;
33 |
34 | let join: DrawCommand;
35 | if (hash.includes("bevel-join")) {
36 | join = bevelJoinCommand(regl);
37 | } else if (hash.includes("miter-join")) {
38 | join = miterJoinCommand(regl);
39 | } else if (hash.includes("round-join")) {
40 | join = roundJoinCommand(regl, 16);
41 | }
42 |
43 | let cap: DrawCommand;
44 | if (hash.includes("round-cap")) {
45 | const roundCap = roundCapGeometry(16);
46 | cap = capCommand(regl, roundCap);
47 | } else if (hash.includes("square-cap")) {
48 | const squareCap = squareCapGeometry();
49 | cap = capCommand(regl, squareCap);
50 | }
51 |
52 | const interleavedStrip = interleavedStripCommand(regl);
53 | const interleavedStripTerminal = interleavedStripTerminalCommand(regl);
54 |
55 | function loop() {
56 | regl.clear({ color: [0, 0, 0, 0] });
57 | const width = 32 * (0.5 * Math.sin(performance.now() * 0.002) + 0.5) + 4;
58 | interleavedStrip({
59 | points: points,
60 | segments: points.length - 3,
61 | width,
62 | color: colorCoded ? [1, 0, 0, alpha] : [0.25, 0.25, 0.25, alpha],
63 | projection,
64 | viewport,
65 | });
66 | if (hash.includes("terminal")) {
67 | interleavedStripTerminal({
68 | points: [points[0], points[1], points[2], points[points.length - 1], points[points.length - 2], points[points.length - 3]],
69 | segments: 2,
70 | width,
71 | color: colorCoded ? [0, 0.5, 0, alpha] : [0.25, 0.25, 0.25, alpha],
72 | projection,
73 | viewport,
74 | });
75 | }
76 | if (join !== undefined) {
77 | join({
78 | points: points,
79 | instances: points.length - 2,
80 | width,
81 | color: colorCoded ? [0, 0, 1, alpha] : [0.25, 0.25, 0.25, alpha],
82 | projection,
83 | viewport,
84 | });
85 | }
86 | if (cap !== undefined) {
87 | cap({
88 | points: [points[0], points[1], points[points.length - 1], points[points.length - 2]],
89 | instances: 2,
90 | width,
91 | color: colorCoded ? [1, 0, 1, alpha] : [0.25, 0.25, 0.25, alpha],
92 | projection,
93 | viewport,
94 | });
95 | }
96 | requestAnimationFrame(loop);
97 | }
98 |
99 | loop();
100 | }
101 |
--------------------------------------------------------------------------------
/src/old-2d/interleaved-strip.ts:
--------------------------------------------------------------------------------
1 | import { Regl } from "regl";
2 |
3 | const geometry = [
4 | [0, -0.5],
5 | [1, -0.5],
6 | [1, 0.5],
7 | [0, -0.5],
8 | [1, 0.5],
9 | [0, 0.5],
10 | ];
11 |
12 | export function interleavedStripCommand(regl: Regl) {
13 | return regl({
14 | vert: `
15 | precision highp float;
16 | attribute vec2 position;
17 | attribute vec2 pointA, pointB;
18 | uniform float width;
19 | uniform mat4 projection;
20 |
21 | void main() {
22 | vec2 xBasis = pointB - pointA;
23 | vec2 yBasis = normalize(vec2(-xBasis.y, xBasis.x));
24 | vec2 point = pointA + xBasis * position.x + yBasis * width * position.y;
25 | gl_Position = projection * vec4(point, 0, 1);
26 | }`,
27 |
28 | frag: `
29 | precision highp float;
30 | uniform vec4 color;
31 | void main() {
32 | gl_FragColor = color;
33 | }`,
34 |
35 | attributes: {
36 | position: {
37 | buffer: regl.buffer(geometry),
38 | divisor: 0,
39 | },
40 | pointA: {
41 | buffer: regl.prop("points"),
42 | divisor: 1,
43 | offset: Float32Array.BYTES_PER_ELEMENT * 0,
44 | },
45 | pointB: {
46 | buffer: regl.prop("points"),
47 | divisor: 1,
48 | offset: Float32Array.BYTES_PER_ELEMENT * 2,
49 | },
50 | },
51 |
52 | uniforms: {
53 | width: regl.prop("width"),
54 | color: regl.prop("color"),
55 | projection: regl.prop("projection"),
56 | },
57 |
58 | cull: {
59 | enable: true,
60 | face: "back",
61 | },
62 |
63 | depth: {
64 | enable: false,
65 | },
66 |
67 | blend: {
68 | enable: true,
69 | func: {
70 | src: "src alpha",
71 | dst: "one minus src alpha",
72 | },
73 | },
74 |
75 | count: geometry.length,
76 | instances: regl.prop("segments"),
77 | viewport: regl.prop("viewport"),
78 | });
79 | }
80 |
--------------------------------------------------------------------------------
/src/old-2d/old-2d.ts:
--------------------------------------------------------------------------------
1 | import { mat4 } from "gl-matrix";
2 | import { Regl } from "regl";
3 | import { interleavedStripCommand } from "./interleaved-strip";
4 | import { interleavedStripRoundCapJoin } from "./round-cap-join";
5 |
6 | function generateSamplePointsInterleaved(width: number, height: number) {
7 | const stepx = width / 9;
8 | const stepy = height / 10;
9 | const points = [];
10 | for (let x = 1; x < 9; x += 2) {
11 | points.push([(x + 0) * stepx - width / 2, 3 * stepy - height / 2]);
12 | points.push([(x + 1) * stepx - width / 2, 7 * stepy - height / 2]);
13 | }
14 | return points;
15 | }
16 |
17 | export function old2d(regl: Regl) {
18 | const interleavedStrip = interleavedStripCommand(regl);
19 | const roundRound = interleavedStripRoundCapJoin(regl, 16);
20 |
21 | const pointsBuffer = regl.buffer(0);
22 |
23 | function render(canvas: HTMLCanvasElement, segments: boolean, alpha: number) {
24 | const points = generateSamplePointsInterleaved(canvas.width, canvas.height);
25 | const projection = mat4.ortho(mat4.create(), -canvas.width / 2, canvas.width / 2, -canvas.height / 2, canvas.height / 2, 0, -1);
26 | const viewport = { x: 0, y: 0, width: canvas.width, height: canvas.height };
27 | const scaleX = 0.45 * Math.sin(performance.now() * 0.002) + 0.75;
28 | const scaleY = Math.sin(performance.now() * 0.0003);
29 | const scaledData = [];
30 | for (const point of points) {
31 | scaledData.push([point[0] * scaleX, point[1] * scaleY]);
32 | }
33 | regl.clear({ color: [0, 0, 0, 0] });
34 | const command = segments ? interleavedStrip : roundRound;
35 | command({
36 | points: pointsBuffer(scaledData),
37 | segments: points.length - 1,
38 | width: canvas.width * 0.05,
39 | color: [0.25, 0.25, 0.25, alpha],
40 | projection,
41 | viewport,
42 | });
43 | }
44 | return render;
45 | }
46 |
--------------------------------------------------------------------------------
/src/old-2d/round-cap-join.ts:
--------------------------------------------------------------------------------
1 | import { Regl } from "regl";
2 |
3 | function roundCapJoinGeometry(regl: Regl, resolution: number) {
4 | const instanceRoundRound = [
5 | [0, -0.5, 0],
6 | [0, -0.5, 1],
7 | [0, 0.5, 1],
8 | [0, -0.5, 0],
9 | [0, 0.5, 1],
10 | [0, 0.5, 0],
11 | ];
12 | // Add the left cap.
13 | for (let step = 0; step < resolution; step++) {
14 | const theta0 = Math.PI / 2 + ((step + 0) * Math.PI) / resolution;
15 | const theta1 = Math.PI / 2 + ((step + 1) * Math.PI) / resolution;
16 | instanceRoundRound.push([0, 0, 0]);
17 | instanceRoundRound.push([0.5 * Math.cos(theta0), 0.5 * Math.sin(theta0), 0]);
18 | instanceRoundRound.push([0.5 * Math.cos(theta1), 0.5 * Math.sin(theta1), 0]);
19 | }
20 | // Add the right cap.
21 | for (let step = 0; step < resolution; step++) {
22 | const theta0 = (3 * Math.PI) / 2 + ((step + 0) * Math.PI) / resolution;
23 | const theta1 = (3 * Math.PI) / 2 + ((step + 1) * Math.PI) / resolution;
24 | instanceRoundRound.push([0, 0, 1]);
25 | instanceRoundRound.push([0.5 * Math.cos(theta0), 0.5 * Math.sin(theta0), 1]);
26 | instanceRoundRound.push([0.5 * Math.cos(theta1), 0.5 * Math.sin(theta1), 1]);
27 | }
28 | return {
29 | buffer: regl.buffer(instanceRoundRound),
30 | count: instanceRoundRound.length,
31 | };
32 | }
33 |
34 | export function interleavedStripRoundCapJoin(regl: Regl, resolution: number) {
35 | const roundCapJoin = roundCapJoinGeometry(regl, resolution);
36 | return regl({
37 | vert: `
38 | precision highp float;
39 | attribute vec3 position;
40 | attribute vec2 pointA, pointB;
41 | uniform float width;
42 | uniform mat4 projection;
43 |
44 | void main() {
45 | vec2 xBasis = normalize(pointB - pointA);
46 | vec2 yBasis = vec2(-xBasis.y, xBasis.x);
47 | vec2 offsetA = pointA + width * (position.x * xBasis + position.y * yBasis);
48 | vec2 offsetB = pointB + width * (position.x * xBasis + position.y * yBasis);
49 | vec2 point = mix(offsetA, offsetB, position.z);
50 | gl_Position = projection * vec4(point, 0, 1);
51 | }`,
52 |
53 | frag: `
54 | precision highp float;
55 | uniform vec4 color;
56 | void main() {
57 | gl_FragColor = color;
58 | }`,
59 |
60 | attributes: {
61 | position: {
62 | buffer: roundCapJoin.buffer,
63 | divisor: 0,
64 | },
65 | pointA: {
66 | buffer: regl.prop("points"),
67 | divisor: 1,
68 | offset: Float32Array.BYTES_PER_ELEMENT * 0,
69 | },
70 | pointB: {
71 | buffer: regl.prop("points"),
72 | divisor: 1,
73 | offset: Float32Array.BYTES_PER_ELEMENT * 2,
74 | },
75 | },
76 |
77 | uniforms: {
78 | width: regl.prop("width"),
79 | color: regl.prop("color"),
80 | projection: regl.prop("projection"),
81 | },
82 |
83 | depth: {
84 | enable: false,
85 | },
86 |
87 | blend: {
88 | enable: true,
89 | func: {
90 | src: "src alpha",
91 | dst: "one minus src alpha",
92 | },
93 | },
94 |
95 | cull: {
96 | enable: true,
97 | face: "back",
98 | },
99 |
100 | count: roundCapJoin.count,
101 | instances: regl.prop("segments"),
102 | viewport: regl.prop("viewport"),
103 | });
104 | }
105 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "useDefineForClassFields": true,
5 | "module": "ESNext",
6 | "lib": ["ESNext", "DOM"],
7 | "moduleResolution": "Node",
8 | "strict": true,
9 | "sourceMap": true,
10 | "resolveJsonModule": true,
11 | "esModuleInterop": true,
12 | "noEmit": true,
13 | "noUnusedLocals": true,
14 | "noUnusedParameters": true,
15 | "noImplicitReturns": true
16 | },
17 | "include": ["./src"]
18 | }
19 |
--------------------------------------------------------------------------------
/vite.config.js:
--------------------------------------------------------------------------------
1 | // vite.config.js
2 | const path = require("path");
3 | const { defineConfig } = require("vite");
4 |
5 | module.exports = defineConfig({
6 | build: {
7 | lib: {
8 | entry: path.resolve(__dirname, "src/main.ts"),
9 | name: "lib",
10 | fileName: (format) => `index.${format}.js`,
11 | },
12 | },
13 | });
14 |
--------------------------------------------------------------------------------