├── .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 | --------------------------------------------------------------------------------