From 227200b2d54bfbe455eafbbfffd33fb8c7e53445 Mon Sep 17 00:00:00 2001 From: atbrakhi Date: Mon, 29 May 2023 14:42:06 +0200 Subject: [PATCH 1/4] add twgl tunnel example --- experiments.json | 6 + experiments/twgl-tunnel/dist/chroma.min.js | 58 + experiments/twgl-tunnel/dist/require.js | 36 + experiments/twgl-tunnel/dist/twgl-full.min.js | 6 + .../twgl-tunnel/dist/twgl-full.module.js | 10076 ++++++++++++++++ experiments/twgl-tunnel/index.html | 355 + experiments/twgl-tunnel/js/amd-compiled.js | 114 + 7 files changed, 10651 insertions(+) create mode 100644 experiments/twgl-tunnel/dist/chroma.min.js create mode 100644 experiments/twgl-tunnel/dist/require.js create mode 100644 experiments/twgl-tunnel/dist/twgl-full.min.js create mode 100644 experiments/twgl-tunnel/dist/twgl-full.module.js create mode 100644 experiments/twgl-tunnel/index.html create mode 100644 experiments/twgl-tunnel/js/amd-compiled.js diff --git a/experiments.json b/experiments.json index 8d0ebad..8ba26ed 100644 --- a/experiments.json +++ b/experiments.json @@ -32,6 +32,12 @@ "desc": "

Benchmark your browser with Doges.

", "href": "experiments/dogemania/", "long_description":"" + }, + { + "name": "TWGL-Tunnel", + "desc": "

TWGL.

", + "href": "experiments/twgl-tunnel/", + "long_description":"" } ] diff --git a/experiments/twgl-tunnel/dist/chroma.min.js b/experiments/twgl-tunnel/dist/chroma.min.js new file mode 100644 index 0000000..9465d54 --- /dev/null +++ b/experiments/twgl-tunnel/dist/chroma.min.js @@ -0,0 +1,58 @@ +/** + * chroma.js - JavaScript library for color conversions + * + * Copyright (c) 2011-2019, Gregor Aisch + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name Gregor Aisch may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL GREGOR AISCH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ------------------------------------------------------- + * + * chroma.js includes colors from colorbrewer2.org, which are released under + * the following license: + * + * Copyright (c) 2002 Cynthia Brewer, Mark Harrower, + * and The Pennsylvania State University. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + * ------------------------------------------------------ + * + * Named colors are taken from X11 Color Names. + * http://www.w3.org/TR/css3-color/#svg-color + * + * @preserve + */ + +!function(r,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):r.chroma=e()}(this,function(){"use strict";for(var n=function(r,e,n){return void 0===e&&(e=0),void 0===n&&(n=1),r>16,e>>8&255,255&e,1]}if(r.match(fr)){5!==r.length&&9!==r.length||(r=r.substr(1)),4===r.length&&(r=(r=r.split(""))[0]+r[0]+r[1]+r[1]+r[2]+r[2]+r[3]+r[3]);var n=parseInt(r,16);return[n>>24&255,n>>16&255,n>>8&255,Math.round((255&n)/255*100)/100]}throw new Error("unknown hex color: "+r)},ur=o.type;A.prototype.hex=function(r){return tr(this._rgb,r)},_.hex=function(){for(var r=[],e=arguments.length;e--;)r[e]=arguments[e];return new(Function.prototype.bind.apply(A,[null].concat(r,["hex"])))},b.format.hex=or,b.autodetect.push({p:4,test:function(r){for(var e=[],n=arguments.length-1;0>16,r>>8&255,255&r,1];throw new Error("unknown num color: "+r)},xe=o.type;A.prototype.num=function(){return Me(this._rgb)},_.num=function(){for(var r=[],e=arguments.length;e--;)r[e]=arguments[e];return new(Function.prototype.bind.apply(A,[null].concat(r,["num"])))},b.format.num=_e,b.autodetect.push({p:5,test:function(){for(var r=[],e=arguments.length;e--;)r[e]=arguments[e];if(1===r.length&&"number"===xe(r[0])&&0<=r[0]&&r[0]<=16777215)return"num"}});var Ae=o.unpack,Ee=o.type,Pe=Math.round;A.prototype.rgb=function(r){return void 0===r&&(r=!0),!1===r?this._rgb.slice(0,3):this._rgb.slice(0,3).map(Pe)},A.prototype.rgba=function(n){return void 0===n&&(n=!0),this._rgb.slice(0,4).map(function(r,e){return e<3?!1===n?r:Pe(r):r})},_.rgb=function(){for(var r=[],e=arguments.length;e--;)r[e]=arguments[e];return new(Function.prototype.bind.apply(A,[null].concat(r,["rgb"])))},b.format.rgb=function(){for(var r=[],e=arguments.length;e--;)r[e]=arguments[e];var n=Ae(r,"rgba");return void 0===n[3]&&(n[3]=1),n},b.autodetect.push({p:3,test:function(){for(var r=[],e=arguments.length;e--;)r[e]=arguments[e];if(r=Ae(r,"rgba"),"array"===Ee(r)&&(3===r.length||4===r.length&&"number"==Ee(r[3])&&0<=r[3]&&r[3]<=1))return"rgb"}});var Fe=Math.log,Oe=function(r){var e,n,t,a=r/100;return t=a<66?(e=255,n=-155.25485562709179-.44596950469579133*(n=a-2)+104.49216199393888*Fe(n),a<20?0:.8274096064007395*(t=a-10)-254.76935184120902+115.67994401066147*Fe(t)):(e=351.97690566805693+.114206453784165*(e=a-55)-40.25366309332127*Fe(e),n=325.4494125711974+.07943456536662342*(n=a-50)-28.0852963507957*Fe(n),255),[e,n,t,1]},je=o.unpack,Ge=Math.round,qe=function(){for(var r=[],e=arguments.length;e--;)r[e]=arguments[e];for(var n,t=je(r,"rgb"),a=t[0],f=t[2],o=1e3,u=4e4;.4=f/a?u=n:o=n}return Ge(n)};A.prototype.temp=A.prototype.kelvin=A.prototype.temperature=function(){return qe(this._rgb)},_.temp=_.kelvin=_.temperature=function(){for(var r=[],e=arguments.length;e--;)r[e]=arguments[e];return new(Function.prototype.bind.apply(A,[null].concat(r,["temp"])))},b.format.temp=b.format.kelvin=b.format.temperature=Oe;var Le=o.type;A.prototype.alpha=function(r,e){return void 0===e&&(e=!1),void 0!==r&&"number"===Le(r)?e?(this._rgb[3]=r,this):new A([this._rgb[0],this._rgb[1],this._rgb[2],r],"rgb"):this._rgb[3]},A.prototype.clipped=function(){return this._rgb._clipped||!1},A.prototype.darken=function(r){void 0===r&&(r=1);var e=this.lab();return e[0]-=qr*r,new A(e,"lab").alpha(this.alpha(),!0)},A.prototype.brighten=function(r){return void 0===r&&(r=1),this.darken(-r)},A.prototype.darker=A.prototype.darken,A.prototype.brighter=A.prototype.brighten,A.prototype.get=function(r){var e=r.split("."),n=e[0],t=e[1],a=this[n]();if(t){var f=n.indexOf(t);if(-1=s[n];)n++;return n-1}(r)/(s.length-2):g!==p?(r-p)/(g-p):1;t=k(t),e||(t=w(t)),1!==y&&(t=nn(t,y)),t=d[0]+t*(1-d[0]-d[1]),t=Math.min(1,Math.max(0,t));var a=Math.floor(1e4*t);if(m&&v[a])n=v[a];else{if("array"===en(b))for(var f=0;f=u[e+1];)e++;var n=(r-u[e])/(u[e+1]-u[e]);return o[e]+n*(o[e+1]-o[e])})}}return l=[p,g],N},N.mode=function(r){return arguments.length?(u=r,f(),N):u},N.range=function(r,e){return a(r),N},N.out=function(r){return n=r,N},N.spread=function(r){return arguments.length?(e=r,N):e},N.correctLightness=function(r){return null==r&&(r=!0),t=r,f(),w=t?function(r){for(var e=M(0,!0).lab()[0],n=M(1,!0).lab()[0],t=nn.max&&(n.max=r),n.count+=1)}),n.domain=[n.min,n.max],n.limits=function(r,e){return Nn(n,r,e)},n},Nn=function(r,e,n){void 0===e&&(e="equal"),void 0===n&&(n=7),"array"==Y(r)&&(r=Mn(r));var t=r.min,a=r.max,f=r.values.sort(function(r,e){return r-e});if(1===n)return[t,a];var o=[];if("c"===e.substr(0,1)&&(o.push(t),o.push(a)),"e"===e.substr(0,1)){o.push(t);for(var u=1;u 0");var c=Math.LOG10E*mn(t),i=Math.LOG10E*mn(a);o.push(t);for(var l=1;lthis.depCount&&!this.defined){if(G(c)){if(this.events.error&&this.map.isDefine||h.onError!==da)try{f=i.execCb(b,c,e,f)}catch(d){a=d}else f=i.execCb(b,c,e,f);this.map.isDefine&&void 0===f&&((e=this.module)?f=e.exports:this.usingExports&& +(f=this.exports));if(a)return a.requireMap=this.map,a.requireModules=this.map.isDefine?[this.map.id]:null,a.requireType=this.map.isDefine?"define":"require",w(this.error=a)}else f=c;this.exports=f;if(this.map.isDefine&&!this.ignore&&(p[b]=f,h.onResourceLoad))h.onResourceLoad(i,this.map,this.depMaps);y(b);this.defined=!0}this.defining=!1;this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete=!0)}}else this.fetch()}},callPlugin:function(){var a= +this.map,b=a.id,d=m(a.prefix);this.depMaps.push(d);r(d,"defined",t(this,function(f){var d,g;g=j(ba,this.map.id);var J=this.map.name,u=this.map.parentMap?this.map.parentMap.name:null,p=i.makeRequire(a.parentMap,{enableBuildCallback:!0});if(this.map.unnormalized){if(f.normalize&&(J=f.normalize(J,function(a){return c(a,u,!0)})||""),f=m(a.prefix+"!"+J,this.map.parentMap),r(f,"defined",t(this,function(a){this.init([],function(){return a},null,{enabled:!0,ignore:!0})})),g=j(k,f.id)){this.depMaps.push(f); +if(this.events.error)g.on("error",t(this,function(a){this.emit("error",a)}));g.enable()}}else g?(this.map.url=i.nameToUrl(g),this.load()):(d=t(this,function(a){this.init([],function(){return a},null,{enabled:!0})}),d.error=t(this,function(a){this.inited=!0;this.error=a;a.requireModules=[b];B(k,function(a){0===a.map.id.indexOf(b+"_unnormalized")&&y(a.map.id)});w(a)}),d.fromText=t(this,function(f,c){var g=a.name,J=m(g),k=O;c&&(f=c);k&&(O=!1);q(J);s(l.config,b)&&(l.config[g]=l.config[b]);try{h.exec(f)}catch(j){return w(C("fromtexteval", +"fromText eval for "+b+" failed: "+j,j,[b]))}k&&(O=!0);this.depMaps.push(J);i.completeLoad(g);p([g],d)}),f.load(a.name,p,d,l))}));i.enable(d,this);this.pluginMaps[d.id]=d},enable:function(){W[this.map.id]=this;this.enabling=this.enabled=!0;v(this.depMaps,t(this,function(a,b){var c,f;if("string"===typeof a){a=m(a,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap);this.depMaps[b]=a;if(c=j(N,a.id)){this.depExports[b]=c(this);return}this.depCount+=1;r(a,"defined",t(this,function(a){this.defineDep(b, +a);this.check()}));this.errback&&r(a,"error",t(this,this.errback))}c=a.id;f=k[c];!s(N,c)&&(f&&!f.enabled)&&i.enable(a,this)}));B(this.pluginMaps,t(this,function(a){var b=j(k,a.id);b&&!b.enabled&&i.enable(a,this)}));this.enabling=!1;this.check()},on:function(a,b){var c=this.events[a];c||(c=this.events[a]=[]);c.push(b)},emit:function(a,b){v(this.events[a],function(a){a(b)});"error"===a&&delete this.events[a]}};i={config:l,contextName:b,registry:k,defined:p,urlFetched:T,defQueue:A,Module:$,makeModuleMap:m, +nextTick:h.nextTick,onError:w,configure:function(a){a.baseUrl&&"/"!==a.baseUrl.charAt(a.baseUrl.length-1)&&(a.baseUrl+="/");var b=l.shim,c={paths:!0,bundles:!0,config:!0,map:!0};B(a,function(a,b){c[b]?(l[b]||(l[b]={}),V(l[b],a,!0,!0)):l[b]=a});a.bundles&&B(a.bundles,function(a,b){v(a,function(a){a!==b&&(ba[a]=b)})});a.shim&&(B(a.shim,function(a,c){H(a)&&(a={deps:a});if((a.exports||a.init)&&!a.exportsFn)a.exportsFn=i.makeShimExports(a);b[c]=a}),l.shim=b);a.packages&&v(a.packages,function(a){var b, +a="string"===typeof a?{name:a}:a;b=a.name;a.location&&(l.paths[b]=a.location);l.pkgs[b]=a.name+"/"+(a.main||"main").replace(ja,"").replace(R,"")});B(k,function(a,b){!a.inited&&!a.map.unnormalized&&(a.map=m(b))});if(a.deps||a.callback)i.require(a.deps||[],a.callback)},makeShimExports:function(a){return function(){var b;a.init&&(b=a.init.apply(ca,arguments));return b||a.exports&&ea(a.exports)}},makeRequire:function(a,e){function g(f,c,d){var j,l;e.enableBuildCallback&&(c&&G(c))&&(c.__requireJsBuild= +!0);if("string"===typeof f){if(G(c))return w(C("requireargs","Invalid require call"),d);if(a&&s(N,f))return N[f](k[a.id]);if(h.get)return h.get(i,f,a,g);j=m(f,a,!1,!0);j=j.id;return!s(p,j)?w(C("notloaded",'Module name "'+j+'" has not been loaded yet for context: '+b+(a?"":". Use require([])"))):p[j]}L();i.nextTick(function(){L();l=q(m(null,a));l.skipMap=e.skipMap;l.init(f,c,d,{enabled:!0});D()});return g}e=e||{};V(g,{isBrowser:z,toUrl:function(b){var e,d=b.lastIndexOf("."),g=b.split("/")[0];if(-1!== +d&&(!("."===g||".."===g)||1g.attachEvent.toString().indexOf("[native code"))&&!Z?(O=!0,g.attachEvent("onreadystatechange",b.onScriptLoad)): +(g.addEventListener("load",b.onScriptLoad,!1),g.addEventListener("error",b.onScriptError,!1)),g.src=d,L=g,D?y.insertBefore(g,D):y.appendChild(g),L=null,g;if(fa)try{importScripts(d),b.completeLoad(c)}catch(j){b.onError(C("importscripts","importScripts failed for "+c+" at "+d,j,[c]))}};z&&!r.skipDataMain&&U(document.getElementsByTagName("script"),function(b){y||(y=b.parentNode);if(K=b.getAttribute("data-main"))return q=K,r.baseUrl||(E=q.split("/"),q=E.pop(),Q=E.length?E.join("/")+"/":"./",r.baseUrl= +Q),q=q.replace(R,""),h.jsExtRegExp.test(q)&&(q=K),r.deps=r.deps?r.deps.concat(q):[q],!0});define=function(b,c,d){var g,h;"string"!==typeof b&&(d=c,c=b,b=null);H(c)||(d=c,c=null);!c&&G(d)&&(c=[],d.length&&(d.toString().replace(la,"").replace(ma,function(b,d){c.push(d)}),c=(1===d.length?["require"]:["require","exports","module"]).concat(c)));if(O){if(!(g=L))P&&"interactive"===P.readyState||U(document.getElementsByTagName("script"),function(b){if("interactive"===b.readyState)return P=b}),g=P;g&&(b|| +(b=g.getAttribute("data-requiremodule")),h=F[g.getAttribute("data-requirecontext")])}(h?h.defQueue:S).push([b,c,d])};define.amd={jQuery:!0};h.exec=function(b){return eval(b)};h(r)}})(this); \ No newline at end of file diff --git a/experiments/twgl-tunnel/dist/twgl-full.min.js b/experiments/twgl-tunnel/dist/twgl-full.min.js new file mode 100644 index 0000000..a4dacca --- /dev/null +++ b/experiments/twgl-tunnel/dist/twgl-full.min.js @@ -0,0 +1,6 @@ +/*! + * @license twgl.js 5.3.1 Copyright (c) 2015, Gregg Tavares All Rights Reserved. + * Available via the MIT license. + * see: http://github.com/greggman/twgl.js for details + */ +!function(t,r){"object"==typeof exports&&"object"==typeof module?module.exports=r():"function"==typeof define&&define.amd?define([],r):"object"==typeof exports?exports.twgl=r():t.twgl=r()}("undefined"!=typeof self?self:this,(function(){return function(t){var r={};function e(n){if(r[n])return r[n].exports;var o=r[n]={i:n,l:!1,exports:{}};return t[n].call(o.exports,o,o.exports,e),o.l=!0,o.exports}return e.m=t,e.c=r,e.d=function(t,r,n){e.o(t,r)||Object.defineProperty(t,r,{enumerable:!0,get:n})},e.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},e.t=function(t,r){if(1&r&&(t=e(t)),8&r)return t;if(4&r&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(e.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&r&&"string"!=typeof t)for(var o in t)e.d(n,o,function(r){return t[r]}.bind(null,o));return n},e.n=function(t){var r=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(r,"a",r),r},e.o=function(t,r){return Object.prototype.hasOwnProperty.call(t,r)},e.p="",e(e.s=8)}([function(t,r,e){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}r.__esModule=!0,r.copyExistingProperties=function(t,r){Object.keys(r).forEach((function(e){r.hasOwnProperty(e)&&t.hasOwnProperty(e)&&(r[e]=t[e])}))},r.copyNamedProperties=function(t,r,e){t.forEach((function(t){var n=r[t];void 0!==n&&(e[t]=n)}))},r.error=function(){var t;(t=console).error.apply(t,arguments)},r.isBuffer=function(t,r){return"undefined"!=typeof WebGLBuffer&&u(r,"WebGLBuffer")},r.isRenderbuffer=function(t,r){return"undefined"!=typeof WebGLRenderbuffer&&u(r,"WebGLRenderbuffer")},r.isSampler=function(t,r){return"undefined"!=typeof WebGLSampler&&u(r,"WebGLSampler")},r.isShader=function(t,r){return"undefined"!=typeof WebGLShader&&u(r,"WebGLShader")},r.isTexture=function(t,r){return"undefined"!=typeof WebGLTexture&&u(r,"WebGLTexture")},r.warn=function(){var t;(t=console).warn.apply(t,arguments)};var o=new Map;function u(t,r){if(!t||"object"!==n(t))return!1;var e=o.get(r);e||(e=new WeakMap,o.set(r,e));var u=e.get(t);if(void 0===u){var i=Object.prototype.toString.call(t);u=i.substring(8,i.length-1)===r,e.set(t,u)}return u}},function(t,r,e){"use strict";r.__esModule=!0,r.getGLTypeForTypedArray=function(t){if(t instanceof Int8Array)return n;if(t instanceof Uint8Array)return o;if(t instanceof Uint8ClampedArray)return o;if(t instanceof Int16Array)return u;if(t instanceof Uint16Array)return i;if(t instanceof Int32Array)return a;if(t instanceof Uint32Array)return f;if(t instanceof Float32Array)return c;throw new Error("unsupported typed array type")},r.getGLTypeForTypedArrayType=function(t){if(t===Int8Array)return n;if(t===Uint8Array)return o;if(t===Uint8ClampedArray)return o;if(t===Int16Array)return u;if(t===Uint16Array)return i;if(t===Int32Array)return a;if(t===Uint32Array)return f;if(t===Float32Array)return c;throw new Error("unsupported typed array type")},r.getTypedArrayTypeForGLType=function(t){var r=l[t];if(!r)throw new Error("unknown gl type");return r},r.isArrayBuffer=void 0;var n=5120,o=5121,u=5122,i=5123,a=5124,f=5125,c=5126,l={},s=l;s[n]=Int8Array,s[5121]=Uint8Array,s[5122]=Int16Array,s[5123]=Uint16Array,s[a]=Int32Array,s[5125]=Uint32Array,s[5126]=Float32Array,s[32819]=Uint16Array,s[32820]=Uint16Array,s[33635]=Uint16Array,s[5131]=Uint16Array,s[33640]=Uint32Array,s[35899]=Uint32Array,s[35902]=Uint32Array,s[36269]=Uint32Array,s[34042]=Uint32Array;var v="undefined"!=typeof SharedArrayBuffer?function(t){return t&&t.buffer&&(t.buffer instanceof ArrayBuffer||t.buffer instanceof SharedArrayBuffer)}:function(t){return t&&t.buffer&&t.buffer instanceof ArrayBuffer};r.isArrayBuffer=v},function(t,r,e){"use strict";r.__esModule=!0,r.add=function(t,r,e){return(e=e||new n(3))[0]=t[0]+r[0],e[1]=t[1]+r[1],e[2]=t[2]+r[2],e},r.copy=function(t,r){return(r=r||new n(3))[0]=t[0],r[1]=t[1],r[2]=t[2],r},r.create=function(t,r,e){var o=new n(3);t&&(o[0]=t);r&&(o[1]=r);e&&(o[2]=e);return o},r.cross=function(t,r,e){e=e||new n(3);var o=t[2]*r[0]-t[0]*r[2],u=t[0]*r[1]-t[1]*r[0];return e[0]=t[1]*r[2]-t[2]*r[1],e[1]=o,e[2]=u,e},r.distance=function(t,r){var e=t[0]-r[0],n=t[1]-r[1],o=t[2]-r[2];return Math.sqrt(e*e+n*n+o*o)},r.distanceSq=function(t,r){var e=t[0]-r[0],n=t[1]-r[1],o=t[2]-r[2];return e*e+n*n+o*o},r.divScalar=function(t,r,e){return(e=e||new n(3))[0]=t[0]/r,e[1]=t[1]/r,e[2]=t[2]/r,e},r.divide=function(t,r,e){return(e=e||new n(3))[0]=t[0]/r[0],e[1]=t[1]/r[1],e[2]=t[2]/r[2],e},r.dot=function(t,r){return t[0]*r[0]+t[1]*r[1]+t[2]*r[2]},r.length=function(t){return Math.sqrt(t[0]*t[0]+t[1]*t[1]+t[2]*t[2])},r.lengthSq=function(t){return t[0]*t[0]+t[1]*t[1]+t[2]*t[2]},r.lerp=function(t,r,e,o){return(o=o||new n(3))[0]=t[0]+e*(r[0]-t[0]),o[1]=t[1]+e*(r[1]-t[1]),o[2]=t[2]+e*(r[2]-t[2]),o},r.lerpV=function(t,r,e,o){return(o=o||new n(3))[0]=t[0]+e[0]*(r[0]-t[0]),o[1]=t[1]+e[1]*(r[1]-t[1]),o[2]=t[2]+e[2]*(r[2]-t[2]),o},r.max=function(t,r,e){return(e=e||new n(3))[0]=Math.max(t[0],r[0]),e[1]=Math.max(t[1],r[1]),e[2]=Math.max(t[2],r[2]),e},r.min=function(t,r,e){return(e=e||new n(3))[0]=Math.min(t[0],r[0]),e[1]=Math.min(t[1],r[1]),e[2]=Math.min(t[2],r[2]),e},r.mulScalar=function(t,r,e){return(e=e||new n(3))[0]=t[0]*r,e[1]=t[1]*r,e[2]=t[2]*r,e},r.multiply=function(t,r,e){return(e=e||new n(3))[0]=t[0]*r[0],e[1]=t[1]*r[1],e[2]=t[2]*r[2],e},r.negate=function(t,r){return(r=r||new n(3))[0]=-t[0],r[1]=-t[1],r[2]=-t[2],r},r.normalize=function(t,r){r=r||new n(3);var e=t[0]*t[0]+t[1]*t[1]+t[2]*t[2],o=Math.sqrt(e);o>1e-5?(r[0]=t[0]/o,r[1]=t[1]/o,r[2]=t[2]/o):(r[0]=0,r[1]=0,r[2]=0);return r},r.setDefaultType=function(t){var r=n;return n=t,r},r.subtract=function(t,r,e){return(e=e||new n(3))[0]=t[0]-r[0],e[1]=t[1]-r[1],e[2]=t[2]-r[2],e};var n=Float32Array},function(t,r,e){"use strict";r.__esModule=!0,r.glEnumToString=void 0,r.isWebGL1=function(t){return!t.texStorage2D},r.isWebGL2=function(t){return!!t.texStorage2D};var n,o,u=(n={},o={},function(t,r){return function(t){var r=t.constructor.name;if(!n[r]){for(var e in t)if("number"==typeof t[e]){var u=o[t[e]];o[t[e]]=u?"".concat(u," | ").concat(e):e}n[r]=!0}}(t),o[r]||("number"==typeof r?"0x".concat(r.toString(16)):r)});r.glEnumToString=u},function(t,r,e){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}r.__esModule=!0,r.bindTransformFeedbackInfo=dt,r.bindUniformBlock=xt,r.createAttributeSetters=Et,r.createProgram=rt,r.createProgramAsync=void 0,r.createProgramFromScripts=function(t,r,e,n,o){var u,i=Z(e,n,o),a=[],f=m(r);try{for(f.s();!(u=f.n()).done;){var c=u.value,l=F(c);if(!l)return K(i,"unknown script element: ".concat(c));a.push(l.text)}}catch(t){f.e(t)}finally{f.f()}return rt(t,a,i)},r.createProgramFromSources=lt,r.createProgramInfo=_t,r.createProgramInfoAsync=void 0,r.createProgramInfoFromProgram=St,r.createProgramInfos=Pt,r.createProgramInfosAsync=void 0,r.createPrograms=gt,r.createProgramsAsync=void 0,r.createTransformFeedback=function(t,r,e){var n=t.createTransformFeedback();return t.bindTransformFeedback(36386,n),t.useProgram(r.program),dt(t,r,e),t.bindTransformFeedback(36386,null),n},r.createTransformFeedbackInfo=mt,r.createUniformBlockInfo=function(t,r,e){return wt(t,r.program,r.uniformBlockSpec,e)},r.createUniformBlockInfoFromProgram=wt,r.createUniformBlockSpecFromProgram=pt,r.createUniformSetters=bt,r.setAttributes=At,r.setBlockUniforms=function(t,r){var e=t.setters;for(var n in r){var o=e[n];if(o){var u=r[n];o(u)}}},r.setBuffersAndAttributes=function(t,r,e){e.vertexArrayObject?t.bindVertexArray(e.vertexArrayObject):(At(r.attribSetters||r,e.attribs),e.indices&&t.bindBuffer(34963,e.indices))},r.setUniformBlock=function(t,r,e){xt(t,r,e)&&t.bufferData(E,e.array,35048)},r.setUniforms=jt,r.setUniformsAndBindTextures=void 0;var o=a(e(3)),u=a(e(0));function i(t){if("function"!=typeof WeakMap)return null;var r=new WeakMap,e=new WeakMap;return(i=function(t){return t?e:r})(t)}function a(t,r){if(!r&&t&&t.__esModule)return t;if(null===t||"object"!==n(t)&&"function"!=typeof t)return{default:t};var e=i(r);if(e&&e.has(t))return e.get(t);var o={},u=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in t)if("default"!==a&&Object.prototype.hasOwnProperty.call(t,a)){var f=u?Object.getOwnPropertyDescriptor(t,a):null;f&&(f.get||f.set)?Object.defineProperty(o,a,f):o[a]=t[a]}return o.default=t,e&&e.set(t,o),o}function f(){f=function(){return t};var t={},r=Object.prototype,e=r.hasOwnProperty,o="function"==typeof Symbol?Symbol:{},u=o.iterator||"@@iterator",i=o.asyncIterator||"@@asyncIterator",a=o.toStringTag||"@@toStringTag";function c(t,r,e){return Object.defineProperty(t,r,{value:e,enumerable:!0,configurable:!0,writable:!0}),t[r]}try{c({},"")}catch(t){c=function(t,r,e){return t[r]=e}}function l(t,r,e,n){var o=r&&r.prototype instanceof y?r:y,u=Object.create(o.prototype),i=new A(n||[]);return u._invoke=function(t,r,e){var n="suspendedStart";return function(o,u){if("executing"===n)throw new Error("Generator is already running");if("completed"===n){if("throw"===o)throw u;return M()}for(e.method=o,e.arg=u;;){var i=e.delegate;if(i){var a=j(i,e);if(a){if(a===v)continue;return a}}if("next"===e.method)e.sent=e._sent=e.arg;else if("throw"===e.method){if("suspendedStart"===n)throw n="completed",e.arg;e.dispatchException(e.arg)}else"return"===e.method&&e.abrupt("return",e.arg);n="executing";var f=s(t,r,e);if("normal"===f.type){if(n=e.done?"completed":"suspendedYield",f.arg===v)continue;return{value:f.arg,done:e.done}}"throw"===f.type&&(n="completed",e.method="throw",e.arg=f.arg)}}}(t,e,i),u}function s(t,r,e){try{return{type:"normal",arg:t.call(r,e)}}catch(t){return{type:"throw",arg:t}}}t.wrap=l;var v={};function y(){}function b(){}function m(){}var d={};c(d,u,(function(){return this}));var p=Object.getPrototypeOf,h=p&&p(p(S([])));h&&h!==r&&e.call(h,u)&&(d=h);var w=m.prototype=y.prototype=Object.create(d);function x(t){["next","throw","return"].forEach((function(r){c(t,r,(function(t){return this._invoke(r,t)}))}))}function F(t,r){function o(u,i,a,f){var c=s(t[u],t,i);if("throw"!==c.type){var l=c.arg,v=l.value;return v&&"object"==n(v)&&e.call(v,"__await")?r.resolve(v.__await).then((function(t){o("next",t,a,f)}),(function(t){o("throw",t,a,f)})):r.resolve(v).then((function(t){l.value=t,a(l)}),(function(t){return o("throw",t,a,f)}))}f(c.arg)}var u;this._invoke=function(t,e){function n(){return new r((function(r,n){o(t,e,r,n)}))}return u=u?u.then(n,n):n()}}function j(t,r){var e=t.iterator[r.method];if(void 0===e){if(r.delegate=null,"throw"===r.method){if(t.iterator.return&&(r.method="return",r.arg=void 0,j(t,r),"throw"===r.method))return v;r.method="throw",r.arg=new TypeError("The iterator does not provide a 'throw' method")}return v}var n=s(e,t.iterator,r.arg);if("throw"===n.type)return r.method="throw",r.arg=n.arg,r.delegate=null,v;var o=n.arg;return o?o.done?(r[t.resultName]=o.value,r.next=t.nextLoc,"return"!==r.method&&(r.method="next",r.arg=void 0),r.delegate=null,v):o:(r.method="throw",r.arg=new TypeError("iterator result is not an object"),r.delegate=null,v)}function O(t){var r={tryLoc:t[0]};1 in t&&(r.catchLoc=t[1]),2 in t&&(r.finallyLoc=t[2],r.afterLoc=t[3]),this.tryEntries.push(r)}function E(t){var r=t.completion||{};r.type="normal",delete r.arg,t.completion=r}function A(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(O,this),this.reset(!0)}function S(t){if(t){var r=t[u];if(r)return r.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var n=-1,o=function r(){for(;++n=0;--o){var u=this.tryEntries[o],i=u.completion;if("root"===u.tryLoc)return n("end");if(u.tryLoc<=this.prev){var a=e.call(u,"catchLoc"),f=e.call(u,"finallyLoc");if(a&&f){if(this.prev=0;--n){var o=this.tryEntries[n];if(o.tryLoc<=this.prev&&e.call(o,"finallyLoc")&&this.prev=0;--r){var e=this.tryEntries[r];if(e.finallyLoc===t)return this.complete(e.completion,e.afterLoc),E(e),v}},catch:function(t){for(var r=this.tryEntries.length-1;r>=0;--r){var e=this.tryEntries[r];if(e.tryLoc===t){var n=e.completion;if("throw"===n.type){var o=n.arg;E(e)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(t,r,e){return this.delegate={iterator:S(t),resultName:r,nextLoc:e},"next"===this.method&&(this.arg=void 0),v}},t}function c(t,r){var e=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(t,r).enumerable}))),e.push.apply(e,n)}return e}function l(t){for(var r=1;r=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var u,i=!0,a=!1;return{s:function(){e=e.call(t)},n:function(){var t=e.next();return i=t.done,t},e:function(t){a=!0,u=t},f:function(){try{i||null==e.return||e.return()}finally{if(a)throw u}}}}function d(t){return function(t){if(Array.isArray(t))return h(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||p(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function p(t,r){if(t){if("string"==typeof t)return h(t,r);var e=Object.prototype.toString.call(t).slice(8,-1);return"Object"===e&&t.constructor&&(e=t.constructor.name),"Map"===e||"Set"===e?Array.from(t):"Arguments"===e||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(e)?h(t,r):void 0}}function h(t,r){(null==r||r>t.length)&&(r=t.length);for(var e=0,n=new Array(r);e1&&void 0!==arguments[1]?arguments[1]:"",e=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,n=d(r.matchAll(V)),o=new Map(n.map((function(t,e){var o=parseInt(t[1]),u=n[e+1],i=u?u.index:r.length;return[o-1,r.substring(t.index,i)]})));return t.split("\n").map((function(t,r){var n=o.get(r);return"".concat(r+1+e,": ").concat(t).concat(n?"\n\n^^^ ".concat(n):"")})).join("\n")}(f,u,a),"\nError compiling ").concat(o.glEnumToString(t,r),": ").concat(u);return n(c),c}return""}function Z(t,r,e){var n,o,u;if("function"==typeof r&&(e=r,r=void 0),"function"==typeof t)e=t,t=void 0;else if(t&&!Array.isArray(t)){var i=t;e=i.errorCallback,t=i.attribLocations,n=i.transformFeedbackVaryings,o=i.transformFeedbackMode,u=i.callback}var a=e||w,f=[],c={errorCallback:function(t){f.push(t);for(var r=arguments.length,e=new Array(r>1?r-1:0),n=1;n0&&void 0!==arguments[0]?arguments[0]:0;return new Promise((function(r){return setTimeout(r,t)}))};function tt(t,r,e){for(var n,o=t.createProgram(),u=Z(e),i=u.attribLocations,a=u.transformFeedbackVaryings,f=u.transformFeedbackMode,c=0;c=0?35632:n.indexOf("vert")>=0?35633:void 0)||y),l=t.createShader(y),t.shaderSource(l,q(v).shaderSource),t.compileShader(l),t.attachShader(o,l)}}Object.entries(i).forEach((function(r){var e=b(r,2),n=e[0],u=e[1];return t.bindAttribLocation(o,u,n)}));var m=a;return m&&(m.attribs&&(m=m.attribs),Array.isArray(m)||(m=Object.keys(m)),t.transformFeedbackVaryings(o,m,f||35981)),t.linkProgram(o),o}function rt(t,r,e,n,o){var u=Z(e,n,o),i=new Set(r),a=tt(t,r,u);function f(t,r){var e=ct(t,r,u.errorCallback);return e&&function(t,r,e){var n,o=m(t.getAttachedShaders(r));try{for(o.s();!(n=o.n()).done;){var u=n.value;e.has(u)&&t.deleteShader(u)}}catch(t){o.e(t)}finally{o.f()}t.deleteProgram(r)}(t,r,i),e}if(!u.callback)return f(t,a)?void 0:a;ut(t,a).then((function(){var r=f(t,a);u.callback(r,r?void 0:a)}))}function et(t){return function(r,e){for(var n=arguments.length,o=new Array(n>2?n-2:0),u=2;u="0"&&o<="9",l=c?parseInt(f):f;if(c&&(a+=u[i++]),i===u.length){e[l]=r;break}var s=u[i++],v="["===s,y=e[l]||(v?[]:{});e[l]=y,e=y,n[a]=n[a]||function(t){return function(r){Ft(t,r)}}(y),a+=s}}function bt(t,r){var e=0;function n(r,n,o){var u,i=n.name.endsWith("[0]"),a=n.type,f=R[a];if(!f)throw new Error("unknown type: 0x".concat(a.toString(16)));if(f.bindPoint){var c=e;e+=n.size,u=i?f.arraySetter(t,a,c,o,n.size):f.setter(t,a,c,o,n.size)}else u=f.arraySetter&&i?f.arraySetter(t,o):f.setter(t,o);return u.location=o,u}for(var o={},u={},i=t.getProgramParameter(r,35718),a=0;a2&&void 0!==arguments[2]?arguments[2]:{},n=new Set,o=Object.fromEntries(Object.entries(r).map((function(r){var o=b(r,2),u=o[0],i=o[1],a=l({},e),f=Array.isArray(i)?i:i.shaders;return Array.isArray(i)||Object.assign(a,i),f.forEach(n.add,n),[u,tt(t,f,a)]})));if(!e.callback){var u=Tt(t,o,r,n,e);return u?void 0:o}at(t,o).then((function(){var u=Tt(t,o,r,n,e);e.callback(u,u?void 0:o)}))}function Pt(t,r,e){function n(t,r){return Object.fromEntries(Object.entries(r).map((function(r){var e=b(r,2),n=e[0],o=e[1];return[n,St(t,o)]})))}var o=(e=Z(e)).callback;o&&(e.callback=function(r,e){o(r,r?void 0:n(t,e))});var u=gt(t,r,e);if(!o&&u)return n(t,u)}var Rt=et(gt);r.createProgramsAsync=Rt;var zt=et(Pt);r.createProgramInfosAsync=zt},function(t,r,e){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}r.__esModule=!0,r.axisRotate=function(t,r,e,n){n=n||new c(16);var o=r[0],u=r[1],i=r[2],a=Math.sqrt(o*o+u*u+i*i),f=(o/=a)*o,l=(u/=a)*u,s=(i/=a)*i,v=Math.cos(e),y=Math.sin(e),b=1-v,m=f+(1-f)*v,d=o*u*b+i*y,p=o*i*b-u*y,h=o*u*b-i*y,w=l+(1-l)*v,x=u*i*b+o*y,F=o*i*b+u*y,j=u*i*b-o*y,O=s+(1-s)*v,E=t[0],A=t[1],S=t[2],M=t[3],_=t[4],T=t[5],g=t[6],P=t[7],R=t[8],z=t[9],k=t[10],U=t[11];n[0]=m*E+d*_+p*R,n[1]=m*A+d*T+p*z,n[2]=m*S+d*g+p*k,n[3]=m*M+d*P+p*U,n[4]=h*E+w*_+x*R,n[5]=h*A+w*T+x*z,n[6]=h*S+w*g+x*k,n[7]=h*M+w*P+x*U,n[8]=F*E+j*_+O*R,n[9]=F*A+j*T+O*z,n[10]=F*S+j*g+O*k,n[11]=F*M+j*P+O*U,t!==n&&(n[12]=t[12],n[13]=t[13],n[14]=t[14],n[15]=t[15]);return n},r.axisRotation=function(t,r,e){e=e||new c(16);var n=t[0],o=t[1],u=t[2],i=Math.sqrt(n*n+o*o+u*u),a=(n/=i)*n,f=(o/=i)*o,l=(u/=i)*u,s=Math.cos(r),v=Math.sin(r),y=1-s;return e[0]=a+(1-a)*s,e[1]=n*o*y+u*v,e[2]=n*u*y-o*v,e[3]=0,e[4]=n*o*y-u*v,e[5]=f+(1-f)*s,e[6]=o*u*y+n*v,e[7]=0,e[8]=n*u*y+o*v,e[9]=o*u*y-n*v,e[10]=l+(1-l)*s,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,e},r.copy=l,r.create=function(){return new c(16).fill(0)},r.frustum=function(t,r,e,n,o,u,i){i=i||new c(16);var a=r-t,f=n-e,l=o-u;return i[0]=2*o/a,i[1]=0,i[2]=0,i[3]=0,i[4]=0,i[5]=2*o/f,i[6]=0,i[7]=0,i[8]=(t+r)/a,i[9]=(n+e)/f,i[10]=u/l,i[11]=-1,i[12]=0,i[13]=0,i[14]=o*u/l,i[15]=0,i},r.getAxis=function(t,r,e){e=e||o.create();var n=4*r;return e[0]=t[n+0],e[1]=t[n+1],e[2]=t[n+2],e},r.getTranslation=function(t,r){return(r=r||o.create())[0]=t[12],r[1]=t[13],r[2]=t[14],r},r.identity=s,r.inverse=v,r.lookAt=function(t,r,e,n){return n=n||new c(16),i=i||o.create(),a=a||o.create(),f=f||o.create(),o.normalize(o.subtract(t,r,f),f),o.normalize(o.cross(e,f,i),i),o.normalize(o.cross(f,i,a),a),n[0]=i[0],n[1]=i[1],n[2]=i[2],n[3]=0,n[4]=a[0],n[5]=a[1],n[6]=a[2],n[7]=0,n[8]=f[0],n[9]=f[1],n[10]=f[2],n[11]=0,n[12]=t[0],n[13]=t[1],n[14]=t[2],n[15]=1,n},r.multiply=function(t,r,e){e=e||new c(16);var n=t[0],o=t[1],u=t[2],i=t[3],a=t[4],f=t[5],l=t[6],s=t[7],v=t[8],y=t[9],b=t[10],m=t[11],d=t[12],p=t[13],h=t[14],w=t[15],x=r[0],F=r[1],j=r[2],O=r[3],E=r[4],A=r[5],S=r[6],M=r[7],_=r[8],T=r[9],g=r[10],P=r[11],R=r[12],z=r[13],k=r[14],U=r[15];return e[0]=n*x+a*F+v*j+d*O,e[1]=o*x+f*F+y*j+p*O,e[2]=u*x+l*F+b*j+h*O,e[3]=i*x+s*F+m*j+w*O,e[4]=n*E+a*A+v*S+d*M,e[5]=o*E+f*A+y*S+p*M,e[6]=u*E+l*A+b*S+h*M,e[7]=i*E+s*A+m*S+w*M,e[8]=n*_+a*T+v*g+d*P,e[9]=o*_+f*T+y*g+p*P,e[10]=u*_+l*T+b*g+h*P,e[11]=i*_+s*T+m*g+w*P,e[12]=n*R+a*z+v*k+d*U,e[13]=o*R+f*z+y*k+p*U,e[14]=u*R+l*z+b*k+h*U,e[15]=i*R+s*z+m*k+w*U,e},r.negate=function(t,r){return(r=r||new c(16))[0]=-t[0],r[1]=-t[1],r[2]=-t[2],r[3]=-t[3],r[4]=-t[4],r[5]=-t[5],r[6]=-t[6],r[7]=-t[7],r[8]=-t[8],r[9]=-t[9],r[10]=-t[10],r[11]=-t[11],r[12]=-t[12],r[13]=-t[13],r[14]=-t[14],r[15]=-t[15],r},r.ortho=function(t,r,e,n,o,u,i){return(i=i||new c(16))[0]=2/(r-t),i[1]=0,i[2]=0,i[3]=0,i[4]=0,i[5]=2/(n-e),i[6]=0,i[7]=0,i[8]=0,i[9]=0,i[10]=2/(o-u),i[11]=0,i[12]=(r+t)/(t-r),i[13]=(n+e)/(e-n),i[14]=(u+o)/(o-u),i[15]=1,i},r.perspective=function(t,r,e,n,o){o=o||new c(16);var u=Math.tan(.5*Math.PI-.5*t),i=1/(e-n);return o[0]=u/r,o[1]=0,o[2]=0,o[3]=0,o[4]=0,o[5]=u,o[6]=0,o[7]=0,o[8]=0,o[9]=0,o[10]=(e+n)*i,o[11]=-1,o[12]=0,o[13]=0,o[14]=e*n*i*2,o[15]=0,o},r.rotateX=function(t,r,e){e=e||new c(16);var n=t[4],o=t[5],u=t[6],i=t[7],a=t[8],f=t[9],l=t[10],s=t[11],v=Math.cos(r),y=Math.sin(r);e[4]=v*n+y*a,e[5]=v*o+y*f,e[6]=v*u+y*l,e[7]=v*i+y*s,e[8]=v*a-y*n,e[9]=v*f-y*o,e[10]=v*l-y*u,e[11]=v*s-y*i,t!==e&&(e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15]);return e},r.rotateY=function(t,r,e){e=e||new c(16);var n=t[0],o=t[1],u=t[2],i=t[3],a=t[8],f=t[9],l=t[10],s=t[11],v=Math.cos(r),y=Math.sin(r);e[0]=v*n-y*a,e[1]=v*o-y*f,e[2]=v*u-y*l,e[3]=v*i-y*s,e[8]=v*a+y*n,e[9]=v*f+y*o,e[10]=v*l+y*u,e[11]=v*s+y*i,t!==e&&(e[4]=t[4],e[5]=t[5],e[6]=t[6],e[7]=t[7],e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15]);return e},r.rotateZ=function(t,r,e){e=e||new c(16);var n=t[0],o=t[1],u=t[2],i=t[3],a=t[4],f=t[5],l=t[6],s=t[7],v=Math.cos(r),y=Math.sin(r);e[0]=v*n+y*a,e[1]=v*o+y*f,e[2]=v*u+y*l,e[3]=v*i+y*s,e[4]=v*a-y*n,e[5]=v*f-y*o,e[6]=v*l-y*u,e[7]=v*s-y*i,t!==e&&(e[8]=t[8],e[9]=t[9],e[10]=t[10],e[11]=t[11],e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15]);return e},r.rotationX=function(t,r){r=r||new c(16);var e=Math.cos(t),n=Math.sin(t);return r[0]=1,r[1]=0,r[2]=0,r[3]=0,r[4]=0,r[5]=e,r[6]=n,r[7]=0,r[8]=0,r[9]=-n,r[10]=e,r[11]=0,r[12]=0,r[13]=0,r[14]=0,r[15]=1,r},r.rotationY=function(t,r){r=r||new c(16);var e=Math.cos(t),n=Math.sin(t);return r[0]=e,r[1]=0,r[2]=-n,r[3]=0,r[4]=0,r[5]=1,r[6]=0,r[7]=0,r[8]=n,r[9]=0,r[10]=e,r[11]=0,r[12]=0,r[13]=0,r[14]=0,r[15]=1,r},r.rotationZ=function(t,r){r=r||new c(16);var e=Math.cos(t),n=Math.sin(t);return r[0]=e,r[1]=n,r[2]=0,r[3]=0,r[4]=-n,r[5]=e,r[6]=0,r[7]=0,r[8]=0,r[9]=0,r[10]=1,r[11]=0,r[12]=0,r[13]=0,r[14]=0,r[15]=1,r},r.scale=function(t,r,e){e=e||new c(16);var n=r[0],o=r[1],u=r[2];e[0]=n*t[0],e[1]=n*t[1],e[2]=n*t[2],e[3]=n*t[3],e[4]=o*t[4],e[5]=o*t[5],e[6]=o*t[6],e[7]=o*t[7],e[8]=u*t[8],e[9]=u*t[9],e[10]=u*t[10],e[11]=u*t[11],t!==e&&(e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15]);return e},r.scaling=function(t,r){return(r=r||new c(16))[0]=t[0],r[1]=0,r[2]=0,r[3]=0,r[4]=0,r[5]=t[1],r[6]=0,r[7]=0,r[8]=0,r[9]=0,r[10]=t[2],r[11]=0,r[12]=0,r[13]=0,r[14]=0,r[15]=1,r},r.setAxis=function(t,r,e,n){n!==t&&(n=l(t,n));var o=4*e;return n[o+0]=r[0],n[o+1]=r[1],n[o+2]=r[2],n},r.setDefaultType=function(t){var r=c;return c=t,r},r.setTranslation=function(t,r,e){e=e||s(),t!==e&&(e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],e[4]=t[4],e[5]=t[5],e[6]=t[6],e[7]=t[7],e[8]=t[8],e[9]=t[9],e[10]=t[10],e[11]=t[11]);return e[12]=r[0],e[13]=r[1],e[14]=r[2],e[15]=1,e},r.transformDirection=function(t,r,e){e=e||o.create();var n=r[0],u=r[1],i=r[2];return e[0]=n*t[0]+u*t[4]+i*t[8],e[1]=n*t[1]+u*t[5]+i*t[9],e[2]=n*t[2]+u*t[6]+i*t[10],e},r.transformNormal=function(t,r,e){e=e||o.create();var n=v(t),u=r[0],i=r[1],a=r[2];return e[0]=u*n[0]+i*n[1]+a*n[2],e[1]=u*n[4]+i*n[5]+a*n[6],e[2]=u*n[8]+i*n[9]+a*n[10],e},r.transformPoint=function(t,r,e){e=e||o.create();var n=r[0],u=r[1],i=r[2],a=n*t[3]+u*t[7]+i*t[11]+t[15];return e[0]=(n*t[0]+u*t[4]+i*t[8]+t[12])/a,e[1]=(n*t[1]+u*t[5]+i*t[9]+t[13])/a,e[2]=(n*t[2]+u*t[6]+i*t[10]+t[14])/a,e},r.translate=function(t,r,e){e=e||new c(16);var n=r[0],o=r[1],u=r[2],i=t[0],a=t[1],f=t[2],l=t[3],s=t[4],v=t[5],y=t[6],b=t[7],m=t[8],d=t[9],p=t[10],h=t[11],w=t[12],x=t[13],F=t[14],j=t[15];t!==e&&(e[0]=i,e[1]=a,e[2]=f,e[3]=l,e[4]=s,e[5]=v,e[6]=y,e[7]=b,e[8]=m,e[9]=d,e[10]=p,e[11]=h);return e[12]=i*n+s*o+m*u+w,e[13]=a*n+v*o+d*u+x,e[14]=f*n+y*o+p*u+F,e[15]=l*n+b*o+h*u+j,e},r.translation=function(t,r){return(r=r||new c(16))[0]=1,r[1]=0,r[2]=0,r[3]=0,r[4]=0,r[5]=1,r[6]=0,r[7]=0,r[8]=0,r[9]=0,r[10]=1,r[11]=0,r[12]=t[0],r[13]=t[1],r[14]=t[2],r[15]=1,r},r.transpose=function(t,r){if((r=r||new c(16))===t){var e;return e=t[1],t[1]=t[4],t[4]=e,e=t[2],t[2]=t[8],t[8]=e,e=t[3],t[3]=t[12],t[12]=e,e=t[6],t[6]=t[9],t[9]=e,e=t[7],t[7]=t[13],t[13]=e,e=t[11],t[11]=t[14],t[14]=e,r}var n=t[0],o=t[1],u=t[2],i=t[3],a=t[4],f=t[5],l=t[6],s=t[7],v=t[8],y=t[9],b=t[10],m=t[11],d=t[12],p=t[13],h=t[14],w=t[15];return r[0]=n,r[1]=a,r[2]=v,r[3]=d,r[4]=o,r[5]=f,r[6]=y,r[7]=p,r[8]=u,r[9]=l,r[10]=b,r[11]=h,r[12]=i,r[13]=s,r[14]=m,r[15]=w,r};var o=function(t,r){if(!r&&t&&t.__esModule)return t;if(null===t||"object"!==n(t)&&"function"!=typeof t)return{default:t};var e=u(r);if(e&&e.has(t))return e.get(t);var o={},i=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in t)if("default"!==a&&Object.prototype.hasOwnProperty.call(t,a)){var f=i?Object.getOwnPropertyDescriptor(t,a):null;f&&(f.get||f.set)?Object.defineProperty(o,a,f):o[a]=t[a]}o.default=t,e&&e.set(t,o);return o}(e(2));function u(t){if("function"!=typeof WeakMap)return null;var r=new WeakMap,e=new WeakMap;return(u=function(t){return t?e:r})(t)}var i,a,f,c=Float32Array;function l(t,r){return(r=r||new c(16))[0]=t[0],r[1]=t[1],r[2]=t[2],r[3]=t[3],r[4]=t[4],r[5]=t[5],r[6]=t[6],r[7]=t[7],r[8]=t[8],r[9]=t[9],r[10]=t[10],r[11]=t[11],r[12]=t[12],r[13]=t[13],r[14]=t[14],r[15]=t[15],r}function s(t){return(t=t||new c(16))[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=1,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=1,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t}function v(t,r){r=r||new c(16);var e=t[0],n=t[1],o=t[2],u=t[3],i=t[4],a=t[5],f=t[6],l=t[7],s=t[8],v=t[9],y=t[10],b=t[11],m=t[12],d=t[13],p=t[14],h=t[15],w=y*h,x=p*b,F=f*h,j=p*l,O=f*b,E=y*l,A=o*h,S=p*u,M=o*b,_=y*u,T=o*l,g=f*u,P=s*d,R=m*v,z=i*d,k=m*a,U=i*v,C=s*a,W=e*d,I=m*n,L=e*v,G=s*n,B=e*a,N=i*n,X=w*a+j*v+O*d-(x*a+F*v+E*d),D=x*n+A*v+_*d-(w*n+S*v+M*d),H=F*n+S*a+T*d-(j*n+A*a+g*d),V=E*n+M*a+g*v-(O*n+_*a+T*v),Y=1/(e*X+i*D+s*H+m*V);return r[0]=Y*X,r[1]=Y*D,r[2]=Y*H,r[3]=Y*V,r[4]=Y*(x*i+F*s+E*m-(w*i+j*s+O*m)),r[5]=Y*(w*e+S*s+M*m-(x*e+A*s+_*m)),r[6]=Y*(j*e+A*i+g*m-(F*e+S*i+T*m)),r[7]=Y*(O*e+_*i+T*s-(E*e+M*i+g*s)),r[8]=Y*(P*l+k*b+U*h-(R*l+z*b+C*h)),r[9]=Y*(R*u+W*b+G*h-(P*u+I*b+L*h)),r[10]=Y*(z*u+I*l+B*h-(k*u+W*l+N*h)),r[11]=Y*(C*u+L*l+N*b-(U*u+G*l+B*b)),r[12]=Y*(z*y+C*p+R*f-(U*p+P*f+k*y)),r[13]=Y*(L*p+P*o+I*y-(W*y+G*p+R*o)),r[14]=Y*(W*f+N*p+k*o-(B*p+z*o+I*f)),r[15]=Y*(B*y+U*o+G*f-(L*f+N*y+C*o)),r}},function(t,r,e){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}r.__esModule=!0,r.createAttribsFromArrays=O,r.createBufferFromArray=A,r.createBufferFromTypedArray=v,r.createBufferInfoFromArrays=function(t,r,e){var n=O(t,r),u=Object.assign({},e||{});u.attribs=Object.assign({},e?e.attribs:{},n);var i=r.indices;if(i){var a=h(i,"indices");u.indices=v(t,a,34963),u.numElements=a.length,u.elementType=o.getGLTypeForTypedArray(a)}else u.numElements||(u.numElements=function(t,r){var e,n;for(n=0;n0)throw new Error("numComponents ".concat(u," not correct for length ").concat(o));return i}(r);return e},r.getArray_=b,r.getNumComponents_=p,r.setAttribInfoBufferFromArray=function(t,r,e,n){e=h(e),void 0!==n?(t.bindBuffer(f,r.buffer),t.bufferSubData(f,n,e)):s(t,f,r.buffer,e,r.drawType)},r.setAttributeDefaults_=function(t){u.copyExistingProperties(t,l)},r.setAttributePrefix=function(t){l.attribPrefix=t};var o=a(e(1)),u=a(e(0));function i(t){if("function"!=typeof WeakMap)return null;var r=new WeakMap,e=new WeakMap;return(i=function(t){return t?e:r})(t)}function a(t,r){if(!r&&t&&t.__esModule)return t;if(null===t||"object"!==n(t)&&"function"!=typeof t)return{default:t};var e=i(r);if(e&&e.has(t))return e.get(t);var o={},u=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in t)if("default"!==a&&Object.prototype.hasOwnProperty.call(t,a)){var f=u?Object.getOwnPropertyDescriptor(t,a):null;f&&(f.get||f.set)?Object.defineProperty(o,a,f):o[a]=t[a]}return o.default=t,e&&e.set(t,o),o}var f=34962,c=5126,l={attribPrefix:""};function s(t,r,e,n,o){t.bindBuffer(r,e),t.bufferData(r,n,o||35044)}function v(t,r,e,n){if(u.isBuffer(t,r))return r;e=e||f;var o=t.createBuffer();return s(t,e,o,r,n),o}function y(t){return"indices"===t}function b(t){return t.length?t:t.data}var m=/coord|texture/i,d=/color|colour/i;function p(t,r,e){return t.numComponents||t.size||function(t,r){var e;if(r%(e=m.test(t)?2:d.test(t)?4:3)>0)throw new Error("Can not guess numComponents for attribute '".concat(t,"'. Tried ").concat(e," but ").concat(r," values is not evenly divisible by ").concat(e,". You should specify it."));return e}(r,e||b(t).length)}function h(t,r){if(o.isArrayBuffer(t))return t;if(o.isArrayBuffer(t.data))return t.data;Array.isArray(t)&&(t={data:t});var e=t.type?w(t.type):void 0;return e||(e=y(r)?Uint16Array:Float32Array),new e(t.data)}function w(t){return"number"==typeof t?o.getTypedArrayTypeForGLType(t):t||Float32Array}function x(t,r){return{buffer:r.buffer,numValues:24,type:(e=r.type,"number"==typeof e?e:e?o.getGLTypeForTypedArrayType(e):c),arrayType:w(r.type)};var e}function F(t,r){var e=r.data||r,n=w(r.type),u=e*n.BYTES_PER_ELEMENT,i=t.createBuffer();return t.bindBuffer(f,i),t.bufferData(f,u,r.drawType||35044),{buffer:i,numValues:e,type:o.getGLTypeForTypedArrayType(n),arrayType:n}}function j(t,r,e){var n=h(r,e);return{arrayType:n.constructor,buffer:v(t,n,void 0,r.drawType),type:o.getGLTypeForTypedArray(n),numValues:0}}function O(t,r){var e={};return Object.keys(r).forEach((function(n){if(!y(n)){var u=r[n],i=u.attrib||u.name||u.attribName||l.attribPrefix+n;if(u.value){if(!Array.isArray(u.value)&&!o.isArrayBuffer(u.value))throw new Error("array.value is not array or typedarray");e[i]={value:u.value}}else{var a=(u.buffer&&u.buffer instanceof WebGLBuffer?x:"number"==typeof u||"number"==typeof u.data?F:j)(t,u,n),f=a.buffer,c=a.type,s=a.numValues,v=a.arrayType,b=void 0!==u.normalize?u.normalize:(d=v)===Int8Array||d===Uint8Array,m=p(u,n,s);e[i]={buffer:f,numComponents:m,type:c,normalize:b,stride:u.stride||0,offset:u.offset||0,divisor:void 0===u.divisor?void 0:u.divisor,drawType:u.drawType}}}var d})),t.bindBuffer(f,null),e}var E=["position","positions","a_position"];function A(t,r,e){var n="indices"===e?34963:f;return v(t,h(r,e),n)}},function(t,r,e){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}r.__esModule=!0,r.canFilter=rt,r.canGenerateMipmap=tt,r.createSampler=lt,r.createSamplers=function(t,r){var e={};return Object.keys(r).forEach((function(n){e[n]=lt(t,r[n])})),e},r.createTexture=St,r.createTextures=function(t,r,e){e=e||dt;var n=0,o=[],u={},i={};function a(){0===n&&setTimeout((function(){e(o.length?o:void 0,u,i)}),0)}return Object.keys(r).forEach((function(e){var f,c,l=r[e];("string"==typeof(c=l.src)||Array.isArray(c)&&"string"==typeof c[0])&&(f=function(t,r,u){i[e]=u,--n,t&&o.push(t),a()},++n),u[e]=St(t,l,f)})),a(),u},r.getBytesPerElementForInternalFormat=Z,r.getFormatAndTypeForInternalFormat=J,r.getNumComponentsForFormat=function(t){var r=q[t];if(!r)throw"unknown format: "+t;return r.u},r.loadTextureFromUrl=Ft,r.resizeTexture=function(t,r,e,n,o,u){n=n||e.width,o=o||e.height,u=u||e.depth;var i=e.target||j;t.bindTexture(i,r);var a,f=e.level||0,c=e.internalFormat||e.format||d,l=J(c),s=e.format||l.format,y=e.src;a=y&&(v(y)||Array.isArray(y)&&"number"==typeof y[0])?e.type||et(t,y,l.type):e.type||l.type;if(i===O)for(var b=0;b<6;++b)t.texImage2D(S+b,f,c,n,o,0,s,a,null);else i===E||i===A?t.texImage3D(i,f,c,n,o,u,0,s,a,null):t.texImage2D(i,f,c,n,o,0,s,a,null)},r.setDefaultTextureColor=ot,r.setEmptyTexture=At,r.setSamplerParameters=ct,r.setTextureDefaults_=function(t){i.copyExistingProperties(t,s),t.textureColor&&ot(t.textureColor)},r.setTextureFilteringForSize=st,r.setTextureFromArray=Et,r.setTextureFromElement=mt,r.setTextureParameters=ft;var o=f(e(3)),u=f(e(1)),i=f(e(0));function a(t){if("function"!=typeof WeakMap)return null;var r=new WeakMap,e=new WeakMap;return(a=function(t){return t?e:r})(t)}function f(t,r){if(!r&&t&&t.__esModule)return t;if(null===t||"object"!==n(t)&&"function"!=typeof t)return{default:t};var e=a(r);if(e&&e.has(t))return e.get(t);var o={},u=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var i in t)if("default"!==i&&Object.prototype.hasOwnProperty.call(t,i)){var f=u?Object.getOwnPropertyDescriptor(t,i):null;f&&(f.get||f.set)?Object.defineProperty(o,i,f):o[i]=t[i]}return o.default=t,e&&e.set(t,o),o}var c,l,s={textureColor:new Uint8Array([128,192,255,255]),textureOptions:{},crossOrigin:void 0},v=u.isArrayBuffer,y=function(){return c=c||("undefined"!=typeof document&&document.createElement?document.createElement("canvas").getContext("2d"):null)},b=6406,m=6407,d=6408,p=6409,h=6410,w=6402,x=34041,F=33071,j=3553,O=34067,E=32879,A=35866,S=34069,M=10241,_=10240,T=10242,g=10243,P=3317,R=5120,z=5121,k=5122,U=5123,C=5124,W=5125,I=5126,L=5131,G=36193,B=33640,N=33319,X=33320,D=6403,H=36244,V=36248,Y=36249,q={},K=q;function $(t){if(!l){var r={};r[6406]={v:b,h:!0,F:!0,j:[1,2,2,4],type:[z,L,G,I]},r[6409]={v:p,h:!0,F:!0,j:[1,2,2,4],type:[z,L,G,I]},r[6410]={v:h,h:!0,F:!0,j:[2,4,4,8],type:[z,L,G,I]},r[m]={v:m,h:!0,F:!0,j:[3,6,6,12,2],type:[z,L,G,I,33635]},r[d]={v:d,h:!0,F:!0,j:[4,8,8,16,2,2],type:[z,L,G,I,32819,32820]},r[6402]={v:w,h:!0,F:!1,j:[2,4],type:[W,U]},r[33321]={v:D,h:!0,F:!0,j:[1],type:[z]},r[36756]={v:D,h:!1,F:!0,j:[1],type:[R]},r[33325]={v:D,h:!1,F:!0,j:[4,2],type:[I,L]},r[33326]={v:D,h:!1,F:!1,j:[4],type:[I]},r[33330]={v:H,h:!0,F:!1,j:[1],type:[z]},r[33329]={v:H,h:!0,F:!1,j:[1],type:[R]},r[33332]={v:H,h:!0,F:!1,j:[2],type:[U]},r[33331]={v:H,h:!0,F:!1,j:[2],type:[k]},r[33334]={v:H,h:!0,F:!1,j:[4],type:[W]},r[33333]={v:H,h:!0,F:!1,j:[4],type:[C]},r[33323]={v:N,h:!0,F:!0,j:[2],type:[z]},r[36757]={v:N,h:!1,F:!0,j:[2],type:[R]},r[33327]={v:N,h:!1,F:!0,j:[8,4],type:[I,L]},r[33328]={v:N,h:!1,F:!1,j:[8],type:[I]},r[33336]={v:X,h:!0,F:!1,j:[2],type:[z]},r[33335]={v:X,h:!0,F:!1,j:[2],type:[R]},r[33338]={v:X,h:!0,F:!1,j:[4],type:[U]},r[33337]={v:X,h:!0,F:!1,j:[4],type:[k]},r[33340]={v:X,h:!0,F:!1,j:[8],type:[W]},r[33339]={v:X,h:!0,F:!1,j:[8],type:[C]},r[32849]={v:m,h:!0,F:!0,j:[3],type:[z]},r[35905]={v:m,h:!1,F:!0,j:[3],type:[z]},r[36194]={v:m,h:!0,F:!0,j:[3,2],type:[z,33635]},r[36758]={v:m,h:!1,F:!0,j:[3],type:[R]},r[35898]={v:m,h:!1,F:!0,j:[12,6,4],type:[I,L,35899]},r[35901]={v:m,h:!1,F:!0,j:[12,6,4],type:[I,L,35902]},r[34843]={v:m,h:!1,F:!0,j:[12,6],type:[I,L]},r[34837]={v:m,h:!1,F:!1,j:[12],type:[I]},r[36221]={v:V,h:!1,F:!1,j:[3],type:[z]},r[36239]={v:V,h:!1,F:!1,j:[3],type:[R]},r[36215]={v:V,h:!1,F:!1,j:[6],type:[U]},r[36233]={v:V,h:!1,F:!1,j:[6],type:[k]},r[36209]={v:V,h:!1,F:!1,j:[12],type:[W]},r[36227]={v:V,h:!1,F:!1,j:[12],type:[C]},r[32856]={v:d,h:!0,F:!0,j:[4],type:[z]},r[35907]={v:d,h:!0,F:!0,j:[4],type:[z]},r[36759]={v:d,h:!1,F:!0,j:[4],type:[R]},r[32855]={v:d,h:!0,F:!0,j:[4,2,4],type:[z,32820,B]},r[32854]={v:d,h:!0,F:!0,j:[4,2],type:[z,32819]},r[32857]={v:d,h:!0,F:!0,j:[4],type:[B]},r[34842]={v:d,h:!1,F:!0,j:[16,8],type:[I,L]},r[34836]={v:d,h:!1,F:!1,j:[16],type:[I]},r[36220]={v:Y,h:!0,F:!1,j:[4],type:[z]},r[36238]={v:Y,h:!0,F:!1,j:[4],type:[R]},r[36975]={v:Y,h:!0,F:!1,j:[4],type:[B]},r[36214]={v:Y,h:!0,F:!1,j:[8],type:[U]},r[36232]={v:Y,h:!0,F:!1,j:[8],type:[k]},r[36226]={v:Y,h:!0,F:!1,j:[16],type:[C]},r[36208]={v:Y,h:!0,F:!1,j:[16],type:[W]},r[33189]={v:w,h:!0,F:!1,j:[2,4],type:[U,W]},r[33190]={v:w,h:!0,F:!1,j:[4],type:[W]},r[36012]={v:w,h:!0,F:!1,j:[4],type:[I]},r[35056]={v:x,h:!0,F:!1,j:[4],type:[34042]},r[36013]={v:x,h:!0,F:!1,j:[4],type:[36269]},Object.keys(r).forEach((function(t){var e=r[t];e.bytesPerElementMap={},e.j.forEach((function(t,r){var n=e.type[r];e.bytesPerElementMap[n]=t}))})),l=r}return l[t]}function Z(t,r){var e=$(t);if(!e)throw"unknown internal format";var n=e.bytesPerElementMap[r];if(void 0===n)throw"unknown internal format";return n}function J(t){var r=$(t);if(!r)throw"unknown internal format";return{format:r.v,type:r.type[0]}}function Q(t){return 0==(t&t-1)}function tt(t,r,e,n){if(!o.isWebGL2(t))return Q(r)&&Q(e);var u=$(n);if(!u)throw"unknown internal format";return u.h&&u.F}function rt(t){var r=$(t);if(!r)throw"unknown internal format";return r.F}function et(t,r,e){return v(r)?u.getGLTypeForTypedArray(r):e||z}function nt(t,r,e,n,o){if(o%1!=0)throw"can't guess dimensions";if(e||n){if(n){if(!e&&(e=o/n)%1)throw"can't guess dimensions"}else if((n=o/e)%1)throw"can't guess dimensions"}else{var u=Math.sqrt(o/(r===O?6:1));u%1==0?(e=u,n=u):(e=o,n=1)}return{width:e,height:n}}function ot(t){s.textureColor=new Uint8Array([255*t[0],255*t[1],255*t[2],255*t[3]])}function ut(t,r){void 0!==r.colorspaceConversion&&t.pixelStorei(37443,r.colorspaceConversion),void 0!==r.premultiplyAlpha&&t.pixelStorei(37441,r.premultiplyAlpha),void 0!==r.flipY&&t.pixelStorei(37440,r.flipY)}function it(t){t.pixelStorei(P,4),o.isWebGL2(t)&&(t.pixelStorei(3314,0),t.pixelStorei(32878,0),t.pixelStorei(3316,0),t.pixelStorei(3315,0),t.pixelStorei(32877,0))}function at(t,r,e,n){n.minMag&&(e.call(t,r,M,n.minMag),e.call(t,r,_,n.minMag)),n.min&&e.call(t,r,M,n.min),n.mag&&e.call(t,r,_,n.mag),n.wrap&&(e.call(t,r,T,n.wrap),e.call(t,r,g,n.wrap),(r===E||i.isSampler(t,r))&&e.call(t,r,32882,n.wrap)),n.wrapR&&e.call(t,r,32882,n.wrapR),n.wrapS&&e.call(t,r,T,n.wrapS),n.wrapT&&e.call(t,r,g,n.wrapT),n.minLod&&e.call(t,r,33082,n.minLod),n.maxLod&&e.call(t,r,33083,n.maxLod),n.baseLevel&&e.call(t,r,33084,n.baseLevel),n.maxLevel&&e.call(t,r,33085,n.maxLevel)}function ft(t,r,e){var n=e.target||j;t.bindTexture(n,r),at(t,n,t.texParameteri,e)}function ct(t,r,e){at(t,r,t.samplerParameteri,e)}function lt(t,r){var e=t.createSampler();return ct(t,e,r),e}function st(t,r,e,n,o,u){e=e||s.textureOptions,u=u||d;var i=e.target||j;if(n=n||e.width,o=o||e.height,t.bindTexture(i,r),tt(t,n,o,u))t.generateMipmap(i);else{var a=rt(u)?9729:9728;t.texParameteri(i,M,a),t.texParameteri(i,_,a),t.texParameteri(i,T,F),t.texParameteri(i,g,F)}}function vt(t){return!0===t.auto||void 0===t.auto&&void 0===t.level}function yt(t,r){return(r=r||{}).cubeFaceOrder||[S,34070,34071,34072,34073,34074]}function bt(t,r){var e=yt(0,r).map((function(t,r){return{face:t,ndx:r}}));return e.sort((function(t,r){return t.face-r.face})),e}function mt(t,r,e,n){var o=(n=n||s.textureOptions).target||j,u=n.level||0,i=e.width,a=e.height,f=n.internalFormat||n.format||d,c=J(f),l=n.format||c.format,v=n.type||c.type;if(ut(t,n),t.bindTexture(o,r),o===O){var b,m,p=e.width,h=e.height;if(p/6===h)b=h,m=[0,0,1,0,2,0,3,0,4,0,5,0];else if(h/6===p)b=p,m=[0,0,0,1,0,2,0,3,0,4,0,5];else if(p/3==h/2)b=p/3,m=[0,0,1,0,2,0,0,1,1,1,2,1];else{if(p/2!=h/3)throw"can't figure out cube map from element: "+(e.src?e.src:e.nodeName);b=p/2,m=[0,0,1,0,0,1,1,1,0,2,1,2]}var w=y();w?(w.canvas.width=b,w.canvas.height=b,i=b,a=b,bt(0,n).forEach((function(r){var n=m[2*r.ndx+0]*b,o=m[2*r.ndx+1]*b;w.drawImage(e,n,o,b,b,0,0,b,b),t.texImage2D(r.face,u,f,l,v,w.canvas)})),w.canvas.width=1,w.canvas.height=1):"undefined"!=typeof createImageBitmap&&(i=b,a=b,bt(0,n).forEach((function(c){var s=m[2*c.ndx+0]*b,y=m[2*c.ndx+1]*b;t.texImage2D(c.face,u,f,b,b,0,l,v,null),createImageBitmap(e,s,y,b,b,{premultiplyAlpha:"none",colorSpaceConversion:"none"}).then((function(e){ut(t,n),t.bindTexture(o,r),t.texImage2D(c.face,u,f,l,v,e),vt(n)&&st(t,r,n,i,a,f)}))})))}else if(o===E||o===A){var x=Math.min(e.width,e.height),F=Math.max(e.width,e.height),S=F/x;if(S%1!=0)throw"can not compute 3D dimensions of element";var M=e.width===F?1:0,_=e.height===F?1:0;t.pixelStorei(P,1),t.pixelStorei(3314,e.width),t.pixelStorei(32878,0),t.pixelStorei(32877,0),t.texImage3D(o,u,f,x,x,x,0,l,v,null);for(var T=0;T=0?x(n,r):e.indexOf("tan")>=0||e.indexOf("binorm")>=0?h(n,r):e.indexOf("norm")>=0&&w(n,r)})),t}function j(t,r,e){return t=t||2,{position:{numComponents:2,data:[(r=r||0)+-1*(t*=.5),(e=e||0)+-1*t,r+1*t,e+-1*t,r+-1*t,e+1*t,r+1*t,e+1*t]},normal:[0,0,1,0,0,1,0,0,1,0,0,1],texcoord:[0,0,1,0,0,1,1,1],indices:[0,1,2,2,1,3]}}function O(t,r,e,n,o){t=t||1,r=r||1,e=e||1,n=n||1,o=o||a.identity();for(var u=(e+1)*(n+1),i=b(3,u),f=b(3,u),c=b(2,u),l=0;l<=n;l++)for(var s=0;s<=e;s++){var v=s/e,y=l/n;i.push(t*v-.5*t,0,r*y-.5*r),f.push(0,1,0),c.push(v,y)}for(var m=e+1,d=b(3,e*n*2,Uint16Array),p=0;p 0");n=n||0,u=u||0;for(var a=(o=o||Math.PI)-n,f=(i=i||2*Math.PI)-u,c=(r+1)*(e+1),l=b(3,c),s=b(3,c),v=b(2,c),y=0;y<=e;y++)for(var m=0;m<=r;m++){var d=m/r,p=y/e,h=f*d+u,w=a*p+n,x=Math.sin(h),F=Math.cos(h),j=Math.sin(w),O=F*j,E=Math.cos(w),A=x*j;l.push(t*O,t*E,t*A),s.push(O,E,A),v.push(1-d,p)}for(var S=r+1,M=b(3,r*e*2,Uint16Array),_=0;_o?(O=e,j=1,E=r):E=t+F/o*(r-t),-2!==F&&F!==o+2||(E=0,j=0),O-=e/2;for(var A=0;Ao?v.push(0,1,0):0===E?v.push(0,0,0):v.push(S*h,w,M*h),y.push(A/n,1-j)}}for(var _=0;_ 0");var a=(i=i||1)-(u=u||0),c=2*(o+1)*4,l=b(3,c),s=b(3,c),v=b(2,c);function y(t,r,e){return t+(r-t)*e}function m(r,e,i,c,b,m){for(var d=0;d<=o;d++){var p=e/1,h=d/o,w=2*(p-.5),x=(u+h*a)*Math.PI,F=Math.sin(x),j=Math.cos(x),O=y(t,r,F),E=w*n,A=j*t,S=F*O;l.push(E,A,S);var M=f.add(f.multiply([0,F,j],i),c);s.push(M),v.push(p*b+m,h)}}for(var d=0;d<2;d++){var p=2*(d/1-.5);m(r,d,[1,1,1],[0,0,0],1,0),m(r,d,[0,0,0],[p,0,0],0,0),m(e,d,[1,1,1],[0,0,0],1,0),m(e,d,[0,0,0],[p,0,0],0,1)}var h=b(3,2*o*4,Uint16Array);function w(t,r){for(var e=0;e0&&d!==r){var x=l+(d+1),F=l+d,j=l+d-v,O=l+(d+1)-v;c.push(x,F,j),c.push(x,j,O)}}l+=r+1}return{position:i,normal:a,texcoord:f,indices:c}}function k(t){return function(r){var e=t.apply(this,Array.prototype.slice.call(arguments,1));return o.createBuffersFromArrays(r,e)}}function U(t){return function(r){var e=t.apply(null,Array.prototype.slice.call(arguments,1));return o.createBufferInfoFromArrays(r,e)}}var C=["numComponents","size","type","normalize","stride","offset","attrib","name","attribName"];function W(t,r,e,n){n=n||0;for(var o=t.length,u=0;u=l&&t<36096}(w)&&c.push(w),!v)if(void 0!==m||function(t){return p[t]}(h))v=t.createRenderbuffer(),t.bindRenderbuffer(f,v),m>1?t.renderbufferStorageMultisample(f,m,h,e,n):t.renderbufferStorage(f,h,e,n);else{var x=Object.assign({},r);x.width=e,x.height=n,void 0===x.auto&&(x.auto=!1,x.min=x.min||x.minMag||b,x.mag=x.mag||x.minMag||b,x.wrapS=x.wrapS||x.wrap||y,x.wrapT=x.wrapT||x.wrap||y),v=o.createTexture(t,x)}if(u.isRenderbuffer(t,v))t.framebufferRenderbuffer(i,w,f,v);else{if(!u.isTexture(t,v))throw new Error("unknown attachment type");void 0!==r.layer?t.framebufferTextureLayer(i,w,v,r.level||0,r.layer):t.framebufferTexture2D(i,w,r.target||3553,v,r.level||0)}s.attachments.push(v)})),t.drawBuffers&&t.drawBuffers(c);return s},r.resizeFramebufferInfo=function(t,r,e,n,i){n=n||t.drawingBufferWidth,i=i||t.drawingBufferHeight,r.width=n,r.height=i,(e=e||m).forEach((function(e,a){var c=r.attachments[a],l=e.format,s=e.samples;if(void 0!==s||u.isRenderbuffer(t,c))t.bindRenderbuffer(f,c),s>1?t.renderbufferStorageMultisample(f,s,l,n,i):t.renderbufferStorage(f,l,n,i);else{if(!u.isTexture(t,c))throw new Error("unknown attachment type");o.resizeTexture(t,c,e,n,i)}}))};var o=a(e(7)),u=a(e(0));function i(t){if("function"!=typeof WeakMap)return null;var r=new WeakMap,e=new WeakMap;return(i=function(t){return t?e:r})(t)}function a(t,r){if(!r&&t&&t.__esModule)return t;if(null===t||"object"!==n(t)&&"function"!=typeof t)return{default:t};var e=i(r);if(e&&e.has(t))return e.get(t);var o={},u=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in t)if("default"!==a&&Object.prototype.hasOwnProperty.call(t,a)){var f=u?Object.getOwnPropertyDescriptor(t,a):null;f&&(f.get||f.set)?Object.defineProperty(o,a,f):o[a]=t[a]}return o.default=t,e&&e.set(t,o),o}var f=36161,c=34041,l=36064,s=36096,v=33306,y=33071,b=9729,m=[{format:6408,type:5121,min:b,wrap:y},{format:c}],d={};d[34041]=v,d[6401]=36128,d[36168]=36128,d[6402]=s,d[33189]=s,d[33190]=s,d[36012]=s,d[35056]=v,d[36013]=v;var p={};p[32854]=!0,p[32855]=!0,p[36194]=!0,p[34041]=!0,p[33189]=!0,p[6401]=!0,p[36168]=!0},function(t,r,e){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}r.__esModule=!0,r.createVAOAndSetAttributes=i,r.createVAOFromBufferInfo=function(t,r,e){return i(t,r.attribSetters||r,e.attribs,e.indices)},r.createVertexArrayInfo=function(t,r,e){var n=t.createVertexArray();t.bindVertexArray(n),r.length||(r=[r]);return r.forEach((function(r){o.setBuffersAndAttributes(t,r,e)})),t.bindVertexArray(null),{numElements:e.numElements,elementType:e.elementType,vertexArrayObject:n}};var o=function(t,r){if(!r&&t&&t.__esModule)return t;if(null===t||"object"!==n(t)&&"function"!=typeof t)return{default:t};var e=u(r);if(e&&e.has(t))return e.get(t);var o={},i=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in t)if("default"!==a&&Object.prototype.hasOwnProperty.call(t,a)){var f=i?Object.getOwnPropertyDescriptor(t,a):null;f&&(f.get||f.set)?Object.defineProperty(o,a,f):o[a]=t[a]}o.default=t,e&&e.set(t,o);return o}(e(4));function u(t){if("function"!=typeof WeakMap)return null;var r=new WeakMap,e=new WeakMap;return(u=function(t){return t?e:r})(t)}function i(t,r,e,n){var u=t.createVertexArray();return t.bindVertexArray(u),o.setAttributes(r,e),n&&t.bindBuffer(34963,n),t.bindVertexArray(null),u}}])})); \ No newline at end of file diff --git a/experiments/twgl-tunnel/dist/twgl-full.module.js b/experiments/twgl-tunnel/dist/twgl-full.module.js new file mode 100644 index 0000000..1fb42da --- /dev/null +++ b/experiments/twgl-tunnel/dist/twgl-full.module.js @@ -0,0 +1,10076 @@ +/* @license twgl.js 5.3.1 Copyright (c) 2015, Gregg Tavares All Rights Reserved. +Available via the MIT license. +see: http://github.com/greggman/twgl.js for details */ +/* + * Copyright 2019 Gregg Tavares + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * + * Vec3 math math functions. + * + * Almost all functions take an optional `dst` argument. If it is not passed in the + * functions will create a new Vec3. In other words you can do this + * + * var v = v3.cross(v1, v2); // Creates a new Vec3 with the cross product of v1 x v2. + * + * or + * + * var v = v3.create(); + * v3.cross(v1, v2, v); // Puts the cross product of v1 x v2 in v + * + * The first style is often easier but depending on where it's used it generates garbage where + * as there is almost never allocation with the second style. + * + * It is always save to pass any vector as the destination. So for example + * + * v3.cross(v1, v2, v1); // Puts the cross product of v1 x v2 in v1 + * + * @module twgl/v3 + */ + +let VecType = Float32Array; + +/** + * A JavaScript array with 3 values or a Float32Array with 3 values. + * When created by the library will create the default type which is `Float32Array` + * but can be set by calling {@link module:twgl/v3.setDefaultType}. + * @typedef {(number[]|Float32Array)} Vec3 + * @memberOf module:twgl/v3 + */ + +/** + * Sets the type this library creates for a Vec3 + * @param {constructor} ctor the constructor for the type. Either `Float32Array` or `Array` + * @return {constructor} previous constructor for Vec3 + * @memberOf module:twgl/v3 + */ +function setDefaultType$1(ctor) { + const oldType = VecType; + VecType = ctor; + return oldType; +} + +/** + * Creates a vec3; may be called with x, y, z to set initial values. + * @param {number} [x] Initial x value. + * @param {number} [y] Initial y value. + * @param {number} [z] Initial z value. + * @return {module:twgl/v3.Vec3} the created vector + * @memberOf module:twgl/v3 + */ +function create$1(x, y, z) { + const dst = new VecType(3); + if (x) { + dst[0] = x; + } + if (y) { + dst[1] = y; + } + if (z) { + dst[2] = z; + } + return dst; +} + +/** + * Adds two vectors; assumes a and b have the same dimension. + * @param {module:twgl/v3.Vec3} a Operand vector. + * @param {module:twgl/v3.Vec3} b Operand vector. + * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created. + * @return {module:twgl/v3.Vec3} A vector tha tis the sum of a and b. + * @memberOf module:twgl/v3 + */ +function add(a, b, dst) { + dst = dst || new VecType(3); + + dst[0] = a[0] + b[0]; + dst[1] = a[1] + b[1]; + dst[2] = a[2] + b[2]; + + return dst; +} + +/** + * Subtracts two vectors. + * @param {module:twgl/v3.Vec3} a Operand vector. + * @param {module:twgl/v3.Vec3} b Operand vector. + * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created. + * @return {module:twgl/v3.Vec3} A vector that is the difference of a and b. + * @memberOf module:twgl/v3 + */ +function subtract(a, b, dst) { + dst = dst || new VecType(3); + + dst[0] = a[0] - b[0]; + dst[1] = a[1] - b[1]; + dst[2] = a[2] - b[2]; + + return dst; +} + +/** + * Performs linear interpolation on two vectors. + * Given vectors a and b and interpolation coefficient t, returns + * a + t * (b - a). + * @param {module:twgl/v3.Vec3} a Operand vector. + * @param {module:twgl/v3.Vec3} b Operand vector. + * @param {number} t Interpolation coefficient. + * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created. + * @return {module:twgl/v3.Vec3} The linear interpolated result. + * @memberOf module:twgl/v3 + */ +function lerp(a, b, t, dst) { + dst = dst || new VecType(3); + + dst[0] = a[0] + t * (b[0] - a[0]); + dst[1] = a[1] + t * (b[1] - a[1]); + dst[2] = a[2] + t * (b[2] - a[2]); + + return dst; +} + +/** + * Performs linear interpolation on two vectors. + * Given vectors a and b and interpolation coefficient vector t, returns + * a + t * (b - a). + * @param {module:twgl/v3.Vec3} a Operand vector. + * @param {module:twgl/v3.Vec3} b Operand vector. + * @param {module:twgl/v3.Vec3} t Interpolation coefficients vector. + * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created. + * @return {module:twgl/v3.Vec3} the linear interpolated result. + * @memberOf module:twgl/v3 + */ +function lerpV(a, b, t, dst) { + dst = dst || new VecType(3); + + dst[0] = a[0] + t[0] * (b[0] - a[0]); + dst[1] = a[1] + t[1] * (b[1] - a[1]); + dst[2] = a[2] + t[2] * (b[2] - a[2]); + + return dst; +} + +/** + * Return max values of two vectors. + * Given vectors a and b returns + * [max(a[0], b[0]), max(a[1], b[1]), max(a[2], b[2])]. + * @param {module:twgl/v3.Vec3} a Operand vector. + * @param {module:twgl/v3.Vec3} b Operand vector. + * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created. + * @return {module:twgl/v3.Vec3} The max components vector. + * @memberOf module:twgl/v3 + */ +function max(a, b, dst) { + dst = dst || new VecType(3); + + dst[0] = Math.max(a[0], b[0]); + dst[1] = Math.max(a[1], b[1]); + dst[2] = Math.max(a[2], b[2]); + + return dst; +} + +/** + * Return min values of two vectors. + * Given vectors a and b returns + * [min(a[0], b[0]), min(a[1], b[1]), min(a[2], b[2])]. + * @param {module:twgl/v3.Vec3} a Operand vector. + * @param {module:twgl/v3.Vec3} b Operand vector. + * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created. + * @return {module:twgl/v3.Vec3} The min components vector. + * @memberOf module:twgl/v3 + */ +function min(a, b, dst) { + dst = dst || new VecType(3); + + dst[0] = Math.min(a[0], b[0]); + dst[1] = Math.min(a[1], b[1]); + dst[2] = Math.min(a[2], b[2]); + + return dst; +} + +/** + * Multiplies a vector by a scalar. + * @param {module:twgl/v3.Vec3} v The vector. + * @param {number} k The scalar. + * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created. + * @return {module:twgl/v3.Vec3} The scaled vector. + * @memberOf module:twgl/v3 + */ +function mulScalar(v, k, dst) { + dst = dst || new VecType(3); + + dst[0] = v[0] * k; + dst[1] = v[1] * k; + dst[2] = v[2] * k; + + return dst; +} + +/** + * Divides a vector by a scalar. + * @param {module:twgl/v3.Vec3} v The vector. + * @param {number} k The scalar. + * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created. + * @return {module:twgl/v3.Vec3} The scaled vector. + * @memberOf module:twgl/v3 + */ +function divScalar(v, k, dst) { + dst = dst || new VecType(3); + + dst[0] = v[0] / k; + dst[1] = v[1] / k; + dst[2] = v[2] / k; + + return dst; +} + +/** + * Computes the cross product of two vectors; assumes both vectors have + * three entries. + * @param {module:twgl/v3.Vec3} a Operand vector. + * @param {module:twgl/v3.Vec3} b Operand vector. + * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created. + * @return {module:twgl/v3.Vec3} The vector of a cross b. + * @memberOf module:twgl/v3 + */ +function cross(a, b, dst) { + dst = dst || new VecType(3); + + const t1 = a[2] * b[0] - a[0] * b[2]; + const t2 = a[0] * b[1] - a[1] * b[0]; + dst[0] = a[1] * b[2] - a[2] * b[1]; + dst[1] = t1; + dst[2] = t2; + + return dst; +} + +/** + * Computes the dot product of two vectors; assumes both vectors have + * three entries. + * @param {module:twgl/v3.Vec3} a Operand vector. + * @param {module:twgl/v3.Vec3} b Operand vector. + * @return {number} dot product + * @memberOf module:twgl/v3 + */ +function dot(a, b) { + return (a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]); +} + +/** + * Computes the length of vector + * @param {module:twgl/v3.Vec3} v vector. + * @return {number} length of vector. + * @memberOf module:twgl/v3 + */ +function length$1(v) { + return Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); +} + +/** + * Computes the square of the length of vector + * @param {module:twgl/v3.Vec3} v vector. + * @return {number} square of the length of vector. + * @memberOf module:twgl/v3 + */ +function lengthSq(v) { + return v[0] * v[0] + v[1] * v[1] + v[2] * v[2]; +} + +/** + * Computes the distance between 2 points + * @param {module:twgl/v3.Vec3} a vector. + * @param {module:twgl/v3.Vec3} b vector. + * @return {number} distance between a and b + * @memberOf module:twgl/v3 + */ +function distance(a, b) { + const dx = a[0] - b[0]; + const dy = a[1] - b[1]; + const dz = a[2] - b[2]; + return Math.sqrt(dx * dx + dy * dy + dz * dz); +} + +/** + * Computes the square of the distance between 2 points + * @param {module:twgl/v3.Vec3} a vector. + * @param {module:twgl/v3.Vec3} b vector. + * @return {number} square of the distance between a and b + * @memberOf module:twgl/v3 + */ +function distanceSq(a, b) { + const dx = a[0] - b[0]; + const dy = a[1] - b[1]; + const dz = a[2] - b[2]; + return dx * dx + dy * dy + dz * dz; +} + +/** + * Divides a vector by its Euclidean length and returns the quotient. + * @param {module:twgl/v3.Vec3} a The vector. + * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created. + * @return {module:twgl/v3.Vec3} The normalized vector. + * @memberOf module:twgl/v3 + */ +function normalize(a, dst) { + dst = dst || new VecType(3); + + const lenSq = a[0] * a[0] + a[1] * a[1] + a[2] * a[2]; + const len = Math.sqrt(lenSq); + if (len > 0.00001) { + dst[0] = a[0] / len; + dst[1] = a[1] / len; + dst[2] = a[2] / len; + } else { + dst[0] = 0; + dst[1] = 0; + dst[2] = 0; + } + + return dst; +} + +/** + * Negates a vector. + * @param {module:twgl/v3.Vec3} v The vector. + * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created. + * @return {module:twgl/v3.Vec3} -v. + * @memberOf module:twgl/v3 + */ +function negate$1(v, dst) { + dst = dst || new VecType(3); + + dst[0] = -v[0]; + dst[1] = -v[1]; + dst[2] = -v[2]; + + return dst; +} + +/** + * Copies a vector. + * @param {module:twgl/v3.Vec3} v The vector. + * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created. + * @return {module:twgl/v3.Vec3} A copy of v. + * @memberOf module:twgl/v3 + */ +function copy$1(v, dst) { + dst = dst || new VecType(3); + + dst[0] = v[0]; + dst[1] = v[1]; + dst[2] = v[2]; + + return dst; +} + +/** + * Multiplies a vector by another vector (component-wise); assumes a and + * b have the same length. + * @param {module:twgl/v3.Vec3} a Operand vector. + * @param {module:twgl/v3.Vec3} b Operand vector. + * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created. + * @return {module:twgl/v3.Vec3} The vector of products of entries of a and + * b. + * @memberOf module:twgl/v3 + */ +function multiply$1(a, b, dst) { + dst = dst || new VecType(3); + + dst[0] = a[0] * b[0]; + dst[1] = a[1] * b[1]; + dst[2] = a[2] * b[2]; + + return dst; +} + +/** + * Divides a vector by another vector (component-wise); assumes a and + * b have the same length. + * @param {module:twgl/v3.Vec3} a Operand vector. + * @param {module:twgl/v3.Vec3} b Operand vector. + * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created. + * @return {module:twgl/v3.Vec3} The vector of quotients of entries of a and + * b. + * @memberOf module:twgl/v3 + */ +function divide(a, b, dst) { + dst = dst || new VecType(3); + + dst[0] = a[0] / b[0]; + dst[1] = a[1] / b[1]; + dst[2] = a[2] / b[2]; + + return dst; +} + +var v3 = /*#__PURE__*/Object.freeze({ + __proto__: null, + add: add, + copy: copy$1, + create: create$1, + cross: cross, + distance: distance, + distanceSq: distanceSq, + divide: divide, + divScalar: divScalar, + dot: dot, + lerp: lerp, + lerpV: lerpV, + length: length$1, + lengthSq: lengthSq, + max: max, + min: min, + mulScalar: mulScalar, + multiply: multiply$1, + negate: negate$1, + normalize: normalize, + setDefaultType: setDefaultType$1, + subtract: subtract +}); + +/* + * Copyright 2019 Gregg Tavares + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * 4x4 Matrix math math functions. + * + * Almost all functions take an optional `dst` argument. If it is not passed in the + * functions will create a new matrix. In other words you can do this + * + * const mat = m4.translation([1, 2, 3]); // Creates a new translation matrix + * + * or + * + * const mat = m4.create(); + * m4.translation([1, 2, 3], mat); // Puts translation matrix in mat. + * + * The first style is often easier but depending on where it's used it generates garbage where + * as there is almost never allocation with the second style. + * + * It is always save to pass any matrix as the destination. So for example + * + * const mat = m4.identity(); + * const trans = m4.translation([1, 2, 3]); + * m4.multiply(mat, trans, mat); // Multiplies mat * trans and puts result in mat. + * + * @module twgl/m4 + */ +let MatType = Float32Array; + +/** + * A JavaScript array with 16 values or a Float32Array with 16 values. + * When created by the library will create the default type which is `Float32Array` + * but can be set by calling {@link module:twgl/m4.setDefaultType}. + * @typedef {(number[]|Float32Array)} Mat4 + * @memberOf module:twgl/m4 + */ + +/** + * Sets the type this library creates for a Mat4 + * @param {constructor} ctor the constructor for the type. Either `Float32Array` or `Array` + * @return {constructor} previous constructor for Mat4 + * @memberOf module:twgl/m4 + */ +function setDefaultType(ctor) { + const oldType = MatType; + MatType = ctor; + return oldType; +} + +/** + * Negates a matrix. + * @param {module:twgl/m4.Mat4} m The matrix. + * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created. + * @return {module:twgl/m4.Mat4} -m. + * @memberOf module:twgl/m4 + */ +function negate(m, dst) { + dst = dst || new MatType(16); + + dst[ 0] = -m[ 0]; + dst[ 1] = -m[ 1]; + dst[ 2] = -m[ 2]; + dst[ 3] = -m[ 3]; + dst[ 4] = -m[ 4]; + dst[ 5] = -m[ 5]; + dst[ 6] = -m[ 6]; + dst[ 7] = -m[ 7]; + dst[ 8] = -m[ 8]; + dst[ 9] = -m[ 9]; + dst[10] = -m[10]; + dst[11] = -m[11]; + dst[12] = -m[12]; + dst[13] = -m[13]; + dst[14] = -m[14]; + dst[15] = -m[15]; + + return dst; +} + +/** + * Creates a matrix. + * @return {module:twgl/m4.Mat4} A new matrix. + * @memberOf module:twgl/m4 + */ +function create() { + return new MatType(16).fill(0); +} + +/** + * Copies a matrix. + * @param {module:twgl/m4.Mat4} m The matrix. + * @param {module:twgl/m4.Mat4} [dst] The matrix. If not passed a new one is created. + * @return {module:twgl/m4.Mat4} A copy of m. + * @memberOf module:twgl/m4 + */ +function copy(m, dst) { + dst = dst || new MatType(16); + + dst[ 0] = m[ 0]; + dst[ 1] = m[ 1]; + dst[ 2] = m[ 2]; + dst[ 3] = m[ 3]; + dst[ 4] = m[ 4]; + dst[ 5] = m[ 5]; + dst[ 6] = m[ 6]; + dst[ 7] = m[ 7]; + dst[ 8] = m[ 8]; + dst[ 9] = m[ 9]; + dst[10] = m[10]; + dst[11] = m[11]; + dst[12] = m[12]; + dst[13] = m[13]; + dst[14] = m[14]; + dst[15] = m[15]; + + return dst; +} + +/** + * Creates an n-by-n identity matrix. + * + * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created. + * @return {module:twgl/m4.Mat4} An n-by-n identity matrix. + * @memberOf module:twgl/m4 + */ +function identity(dst) { + dst = dst || new MatType(16); + + dst[ 0] = 1; + dst[ 1] = 0; + dst[ 2] = 0; + dst[ 3] = 0; + dst[ 4] = 0; + dst[ 5] = 1; + dst[ 6] = 0; + dst[ 7] = 0; + dst[ 8] = 0; + dst[ 9] = 0; + dst[10] = 1; + dst[11] = 0; + dst[12] = 0; + dst[13] = 0; + dst[14] = 0; + dst[15] = 1; + + return dst; +} + +/** + * Takes the transpose of a matrix. + * @param {module:twgl/m4.Mat4} m The matrix. + * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created. + * @return {module:twgl/m4.Mat4} The transpose of m. + * @memberOf module:twgl/m4 + */ + function transpose(m, dst) { + dst = dst || new MatType(16); + if (dst === m) { + let t; + + t = m[1]; + m[1] = m[4]; + m[4] = t; + + t = m[2]; + m[2] = m[8]; + m[8] = t; + + t = m[3]; + m[3] = m[12]; + m[12] = t; + + t = m[6]; + m[6] = m[9]; + m[9] = t; + + t = m[7]; + m[7] = m[13]; + m[13] = t; + + t = m[11]; + m[11] = m[14]; + m[14] = t; + return dst; + } + + const m00 = m[0 * 4 + 0]; + const m01 = m[0 * 4 + 1]; + const m02 = m[0 * 4 + 2]; + const m03 = m[0 * 4 + 3]; + const m10 = m[1 * 4 + 0]; + const m11 = m[1 * 4 + 1]; + const m12 = m[1 * 4 + 2]; + const m13 = m[1 * 4 + 3]; + const m20 = m[2 * 4 + 0]; + const m21 = m[2 * 4 + 1]; + const m22 = m[2 * 4 + 2]; + const m23 = m[2 * 4 + 3]; + const m30 = m[3 * 4 + 0]; + const m31 = m[3 * 4 + 1]; + const m32 = m[3 * 4 + 2]; + const m33 = m[3 * 4 + 3]; + + dst[ 0] = m00; + dst[ 1] = m10; + dst[ 2] = m20; + dst[ 3] = m30; + dst[ 4] = m01; + dst[ 5] = m11; + dst[ 6] = m21; + dst[ 7] = m31; + dst[ 8] = m02; + dst[ 9] = m12; + dst[10] = m22; + dst[11] = m32; + dst[12] = m03; + dst[13] = m13; + dst[14] = m23; + dst[15] = m33; + + return dst; +} + +/** + * Computes the inverse of a 4-by-4 matrix. + * @param {module:twgl/m4.Mat4} m The matrix. + * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created. + * @return {module:twgl/m4.Mat4} The inverse of m. + * @memberOf module:twgl/m4 + */ +function inverse(m, dst) { + dst = dst || new MatType(16); + + const m00 = m[0 * 4 + 0]; + const m01 = m[0 * 4 + 1]; + const m02 = m[0 * 4 + 2]; + const m03 = m[0 * 4 + 3]; + const m10 = m[1 * 4 + 0]; + const m11 = m[1 * 4 + 1]; + const m12 = m[1 * 4 + 2]; + const m13 = m[1 * 4 + 3]; + const m20 = m[2 * 4 + 0]; + const m21 = m[2 * 4 + 1]; + const m22 = m[2 * 4 + 2]; + const m23 = m[2 * 4 + 3]; + const m30 = m[3 * 4 + 0]; + const m31 = m[3 * 4 + 1]; + const m32 = m[3 * 4 + 2]; + const m33 = m[3 * 4 + 3]; + const tmp_0 = m22 * m33; + const tmp_1 = m32 * m23; + const tmp_2 = m12 * m33; + const tmp_3 = m32 * m13; + const tmp_4 = m12 * m23; + const tmp_5 = m22 * m13; + const tmp_6 = m02 * m33; + const tmp_7 = m32 * m03; + const tmp_8 = m02 * m23; + const tmp_9 = m22 * m03; + const tmp_10 = m02 * m13; + const tmp_11 = m12 * m03; + const tmp_12 = m20 * m31; + const tmp_13 = m30 * m21; + const tmp_14 = m10 * m31; + const tmp_15 = m30 * m11; + const tmp_16 = m10 * m21; + const tmp_17 = m20 * m11; + const tmp_18 = m00 * m31; + const tmp_19 = m30 * m01; + const tmp_20 = m00 * m21; + const tmp_21 = m20 * m01; + const tmp_22 = m00 * m11; + const tmp_23 = m10 * m01; + + const t0 = (tmp_0 * m11 + tmp_3 * m21 + tmp_4 * m31) - + (tmp_1 * m11 + tmp_2 * m21 + tmp_5 * m31); + const t1 = (tmp_1 * m01 + tmp_6 * m21 + tmp_9 * m31) - + (tmp_0 * m01 + tmp_7 * m21 + tmp_8 * m31); + const t2 = (tmp_2 * m01 + tmp_7 * m11 + tmp_10 * m31) - + (tmp_3 * m01 + tmp_6 * m11 + tmp_11 * m31); + const t3 = (tmp_5 * m01 + tmp_8 * m11 + tmp_11 * m21) - + (tmp_4 * m01 + tmp_9 * m11 + tmp_10 * m21); + + const d = 1.0 / (m00 * t0 + m10 * t1 + m20 * t2 + m30 * t3); + + dst[ 0] = d * t0; + dst[ 1] = d * t1; + dst[ 2] = d * t2; + dst[ 3] = d * t3; + dst[ 4] = d * ((tmp_1 * m10 + tmp_2 * m20 + tmp_5 * m30) - + (tmp_0 * m10 + tmp_3 * m20 + tmp_4 * m30)); + dst[ 5] = d * ((tmp_0 * m00 + tmp_7 * m20 + tmp_8 * m30) - + (tmp_1 * m00 + tmp_6 * m20 + tmp_9 * m30)); + dst[ 6] = d * ((tmp_3 * m00 + tmp_6 * m10 + tmp_11 * m30) - + (tmp_2 * m00 + tmp_7 * m10 + tmp_10 * m30)); + dst[ 7] = d * ((tmp_4 * m00 + tmp_9 * m10 + tmp_10 * m20) - + (tmp_5 * m00 + tmp_8 * m10 + tmp_11 * m20)); + dst[ 8] = d * ((tmp_12 * m13 + tmp_15 * m23 + tmp_16 * m33) - + (tmp_13 * m13 + tmp_14 * m23 + tmp_17 * m33)); + dst[ 9] = d * ((tmp_13 * m03 + tmp_18 * m23 + tmp_21 * m33) - + (tmp_12 * m03 + tmp_19 * m23 + tmp_20 * m33)); + dst[10] = d * ((tmp_14 * m03 + tmp_19 * m13 + tmp_22 * m33) - + (tmp_15 * m03 + tmp_18 * m13 + tmp_23 * m33)); + dst[11] = d * ((tmp_17 * m03 + tmp_20 * m13 + tmp_23 * m23) - + (tmp_16 * m03 + tmp_21 * m13 + tmp_22 * m23)); + dst[12] = d * ((tmp_14 * m22 + tmp_17 * m32 + tmp_13 * m12) - + (tmp_16 * m32 + tmp_12 * m12 + tmp_15 * m22)); + dst[13] = d * ((tmp_20 * m32 + tmp_12 * m02 + tmp_19 * m22) - + (tmp_18 * m22 + tmp_21 * m32 + tmp_13 * m02)); + dst[14] = d * ((tmp_18 * m12 + tmp_23 * m32 + tmp_15 * m02) - + (tmp_22 * m32 + tmp_14 * m02 + tmp_19 * m12)); + dst[15] = d * ((tmp_22 * m22 + tmp_16 * m02 + tmp_21 * m12) - + (tmp_20 * m12 + tmp_23 * m22 + tmp_17 * m02)); + + return dst; +} + +/** + * Multiplies two 4-by-4 matrices with a on the left and b on the right + * @param {module:twgl/m4.Mat4} a The matrix on the left. + * @param {module:twgl/m4.Mat4} b The matrix on the right. + * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created. + * @return {module:twgl/m4.Mat4} The matrix product of a and b. + * @memberOf module:twgl/m4 + */ +function multiply(a, b, dst) { + dst = dst || new MatType(16); + + const a00 = a[0]; + const a01 = a[1]; + const a02 = a[2]; + const a03 = a[3]; + const a10 = a[ 4 + 0]; + const a11 = a[ 4 + 1]; + const a12 = a[ 4 + 2]; + const a13 = a[ 4 + 3]; + const a20 = a[ 8 + 0]; + const a21 = a[ 8 + 1]; + const a22 = a[ 8 + 2]; + const a23 = a[ 8 + 3]; + const a30 = a[12 + 0]; + const a31 = a[12 + 1]; + const a32 = a[12 + 2]; + const a33 = a[12 + 3]; + const b00 = b[0]; + const b01 = b[1]; + const b02 = b[2]; + const b03 = b[3]; + const b10 = b[ 4 + 0]; + const b11 = b[ 4 + 1]; + const b12 = b[ 4 + 2]; + const b13 = b[ 4 + 3]; + const b20 = b[ 8 + 0]; + const b21 = b[ 8 + 1]; + const b22 = b[ 8 + 2]; + const b23 = b[ 8 + 3]; + const b30 = b[12 + 0]; + const b31 = b[12 + 1]; + const b32 = b[12 + 2]; + const b33 = b[12 + 3]; + + dst[ 0] = a00 * b00 + a10 * b01 + a20 * b02 + a30 * b03; + dst[ 1] = a01 * b00 + a11 * b01 + a21 * b02 + a31 * b03; + dst[ 2] = a02 * b00 + a12 * b01 + a22 * b02 + a32 * b03; + dst[ 3] = a03 * b00 + a13 * b01 + a23 * b02 + a33 * b03; + dst[ 4] = a00 * b10 + a10 * b11 + a20 * b12 + a30 * b13; + dst[ 5] = a01 * b10 + a11 * b11 + a21 * b12 + a31 * b13; + dst[ 6] = a02 * b10 + a12 * b11 + a22 * b12 + a32 * b13; + dst[ 7] = a03 * b10 + a13 * b11 + a23 * b12 + a33 * b13; + dst[ 8] = a00 * b20 + a10 * b21 + a20 * b22 + a30 * b23; + dst[ 9] = a01 * b20 + a11 * b21 + a21 * b22 + a31 * b23; + dst[10] = a02 * b20 + a12 * b21 + a22 * b22 + a32 * b23; + dst[11] = a03 * b20 + a13 * b21 + a23 * b22 + a33 * b23; + dst[12] = a00 * b30 + a10 * b31 + a20 * b32 + a30 * b33; + dst[13] = a01 * b30 + a11 * b31 + a21 * b32 + a31 * b33; + dst[14] = a02 * b30 + a12 * b31 + a22 * b32 + a32 * b33; + dst[15] = a03 * b30 + a13 * b31 + a23 * b32 + a33 * b33; + + return dst; +} + +/** + * Sets the translation component of a 4-by-4 matrix to the given + * vector. + * @param {module:twgl/m4.Mat4} a The matrix. + * @param {module:twgl/v3.Vec3} v The vector. + * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created. + * @return {module:twgl/m4.Mat4} The matrix with translation set. + * @memberOf module:twgl/m4 + */ +function setTranslation(a, v, dst) { + dst = dst || identity(); + if (a !== dst) { + dst[ 0] = a[ 0]; + dst[ 1] = a[ 1]; + dst[ 2] = a[ 2]; + dst[ 3] = a[ 3]; + dst[ 4] = a[ 4]; + dst[ 5] = a[ 5]; + dst[ 6] = a[ 6]; + dst[ 7] = a[ 7]; + dst[ 8] = a[ 8]; + dst[ 9] = a[ 9]; + dst[10] = a[10]; + dst[11] = a[11]; + } + dst[12] = v[0]; + dst[13] = v[1]; + dst[14] = v[2]; + dst[15] = 1; + return dst; +} + +/** + * Returns the translation component of a 4-by-4 matrix as a vector with 3 + * entries. + * @param {module:twgl/m4.Mat4} m The matrix. + * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not passed a new one is created. + * @return {module:twgl/v3.Vec3} The translation component of m. + * @memberOf module:twgl/m4 + */ +function getTranslation(m, dst) { + dst = dst || create$1(); + dst[0] = m[12]; + dst[1] = m[13]; + dst[2] = m[14]; + return dst; +} + +/** + * Returns an axis of a 4x4 matrix as a vector with 3 entries + * @param {module:twgl/m4.Mat4} m The matrix. + * @param {number} axis The axis 0 = x, 1 = y, 2 = z; + * @return {module:twgl/v3.Vec3} [dst] vector. + * @return {module:twgl/v3.Vec3} The axis component of m. + * @memberOf module:twgl/m4 + */ +function getAxis(m, axis, dst) { + dst = dst || create$1(); + const off = axis * 4; + dst[0] = m[off + 0]; + dst[1] = m[off + 1]; + dst[2] = m[off + 2]; + return dst; +} + +/** + * Sets an axis of a 4x4 matrix as a vector with 3 entries + * @param {module:twgl/m4.Mat4} m The matrix. + * @param {module:twgl/v3.Vec3} v the axis vector + * @param {number} axis The axis 0 = x, 1 = y, 2 = z; + * @param {module:twgl/m4.Mat4} [dst] The matrix to set. If not passed a new one is created. + * @return {module:twgl/m4.Mat4} The matrix with axis set. + * @memberOf module:twgl/m4 + */ +function setAxis(a, v, axis, dst) { + if (dst !== a) { + dst = copy(a, dst); + } + const off = axis * 4; + dst[off + 0] = v[0]; + dst[off + 1] = v[1]; + dst[off + 2] = v[2]; + return dst; +} + +/** + * Computes a 4-by-4 perspective transformation matrix given the angular height + * of the frustum, the aspect ratio, and the near and far clipping planes. The + * arguments define a frustum extending in the negative z direction. The given + * angle is the vertical angle of the frustum, and the horizontal angle is + * determined to produce the given aspect ratio. The arguments near and far are + * the distances to the near and far clipping planes. Note that near and far + * are not z coordinates, but rather they are distances along the negative + * z-axis. The matrix generated sends the viewing frustum to the unit box. + * We assume a unit box extending from -1 to 1 in the x and y dimensions and + * from 0 to 1 in the z dimension. + * @param {number} fieldOfViewYInRadians The camera angle from top to bottom (in radians). + * @param {number} aspect The aspect ratio width / height. + * @param {number} zNear The depth (negative z coordinate) + * of the near clipping plane. + * @param {number} zFar The depth (negative z coordinate) + * of the far clipping plane. + * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created. + * @return {module:twgl/m4.Mat4} The perspective matrix. + * @memberOf module:twgl/m4 + */ +function perspective(fieldOfViewYInRadians, aspect, zNear, zFar, dst) { + dst = dst || new MatType(16); + + const f = Math.tan(Math.PI * 0.5 - 0.5 * fieldOfViewYInRadians); + const rangeInv = 1.0 / (zNear - zFar); + + dst[0] = f / aspect; + dst[1] = 0; + dst[2] = 0; + dst[3] = 0; + + dst[4] = 0; + dst[5] = f; + dst[6] = 0; + dst[7] = 0; + + dst[8] = 0; + dst[9] = 0; + dst[10] = (zNear + zFar) * rangeInv; + dst[11] = -1; + + dst[12] = 0; + dst[13] = 0; + dst[14] = zNear * zFar * rangeInv * 2; + dst[15] = 0; + + return dst; +} + +/** + * Computes a 4-by-4 orthogonal transformation matrix given the left, right, + * bottom, and top dimensions of the near clipping plane as well as the + * near and far clipping plane distances. + * @param {number} left Left side of the near clipping plane viewport. + * @param {number} right Right side of the near clipping plane viewport. + * @param {number} bottom Bottom of the near clipping plane viewport. + * @param {number} top Top of the near clipping plane viewport. + * @param {number} near The depth (negative z coordinate) + * of the near clipping plane. + * @param {number} far The depth (negative z coordinate) + * of the far clipping plane. + * @param {module:twgl/m4.Mat4} [dst] Output matrix. If not passed a new one is created. + * @return {module:twgl/m4.Mat4} The perspective matrix. + * @memberOf module:twgl/m4 + */ +function ortho(left, right, bottom, top, near, far, dst) { + dst = dst || new MatType(16); + + dst[0] = 2 / (right - left); + dst[1] = 0; + dst[2] = 0; + dst[3] = 0; + + dst[4] = 0; + dst[5] = 2 / (top - bottom); + dst[6] = 0; + dst[7] = 0; + + dst[8] = 0; + dst[9] = 0; + dst[10] = 2 / (near - far); + dst[11] = 0; + + dst[12] = (right + left) / (left - right); + dst[13] = (top + bottom) / (bottom - top); + dst[14] = (far + near) / (near - far); + dst[15] = 1; + + return dst; +} + +/** + * Computes a 4-by-4 perspective transformation matrix given the left, right, + * top, bottom, near and far clipping planes. The arguments define a frustum + * extending in the negative z direction. The arguments near and far are the + * distances to the near and far clipping planes. Note that near and far are not + * z coordinates, but rather they are distances along the negative z-axis. The + * matrix generated sends the viewing frustum to the unit box. We assume a unit + * box extending from -1 to 1 in the x and y dimensions and from 0 to 1 in the z + * dimension. + * @param {number} left The x coordinate of the left plane of the box. + * @param {number} right The x coordinate of the right plane of the box. + * @param {number} bottom The y coordinate of the bottom plane of the box. + * @param {number} top The y coordinate of the right plane of the box. + * @param {number} near The negative z coordinate of the near plane of the box. + * @param {number} far The negative z coordinate of the far plane of the box. + * @param {module:twgl/m4.Mat4} [dst] Output matrix. If not passed a new one is created. + * @return {module:twgl/m4.Mat4} The perspective projection matrix. + * @memberOf module:twgl/m4 + */ +function frustum(left, right, bottom, top, near, far, dst) { + dst = dst || new MatType(16); + + const dx = (right - left); + const dy = (top - bottom); + const dz = (near - far); + + dst[ 0] = 2 * near / dx; + dst[ 1] = 0; + dst[ 2] = 0; + dst[ 3] = 0; + dst[ 4] = 0; + dst[ 5] = 2 * near / dy; + dst[ 6] = 0; + dst[ 7] = 0; + dst[ 8] = (left + right) / dx; + dst[ 9] = (top + bottom) / dy; + dst[10] = far / dz; + dst[11] = -1; + dst[12] = 0; + dst[13] = 0; + dst[14] = near * far / dz; + dst[15] = 0; + + return dst; +} + +let xAxis; +let yAxis; +let zAxis; + +/** + * Computes a 4-by-4 look-at transformation. + * + * This is a matrix which positions the camera itself. If you want + * a view matrix (a matrix which moves things in front of the camera) + * take the inverse of this. + * + * @param {module:twgl/v3.Vec3} eye The position of the eye. + * @param {module:twgl/v3.Vec3} target The position meant to be viewed. + * @param {module:twgl/v3.Vec3} up A vector pointing up. + * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created. + * @return {module:twgl/m4.Mat4} The look-at matrix. + * @memberOf module:twgl/m4 + */ +function lookAt(eye, target, up, dst) { + dst = dst || new MatType(16); + + xAxis = xAxis || create$1(); + yAxis = yAxis || create$1(); + zAxis = zAxis || create$1(); + + normalize( + subtract(eye, target, zAxis), zAxis); + normalize(cross(up, zAxis, xAxis), xAxis); + normalize(cross(zAxis, xAxis, yAxis), yAxis); + + dst[ 0] = xAxis[0]; + dst[ 1] = xAxis[1]; + dst[ 2] = xAxis[2]; + dst[ 3] = 0; + dst[ 4] = yAxis[0]; + dst[ 5] = yAxis[1]; + dst[ 6] = yAxis[2]; + dst[ 7] = 0; + dst[ 8] = zAxis[0]; + dst[ 9] = zAxis[1]; + dst[10] = zAxis[2]; + dst[11] = 0; + dst[12] = eye[0]; + dst[13] = eye[1]; + dst[14] = eye[2]; + dst[15] = 1; + + return dst; +} + +/** + * Creates a 4-by-4 matrix which translates by the given vector v. + * @param {module:twgl/v3.Vec3} v The vector by + * which to translate. + * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created. + * @return {module:twgl/m4.Mat4} The translation matrix. + * @memberOf module:twgl/m4 + */ +function translation(v, dst) { + dst = dst || new MatType(16); + + dst[ 0] = 1; + dst[ 1] = 0; + dst[ 2] = 0; + dst[ 3] = 0; + dst[ 4] = 0; + dst[ 5] = 1; + dst[ 6] = 0; + dst[ 7] = 0; + dst[ 8] = 0; + dst[ 9] = 0; + dst[10] = 1; + dst[11] = 0; + dst[12] = v[0]; + dst[13] = v[1]; + dst[14] = v[2]; + dst[15] = 1; + return dst; +} + +/** + * Translates the given 4-by-4 matrix by the given vector v. + * @param {module:twgl/m4.Mat4} m The matrix. + * @param {module:twgl/v3.Vec3} v The vector by + * which to translate. + * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created. + * @return {module:twgl/m4.Mat4} The translated matrix. + * @memberOf module:twgl/m4 + */ +function translate(m, v, dst) { + dst = dst || new MatType(16); + + const v0 = v[0]; + const v1 = v[1]; + const v2 = v[2]; + const m00 = m[0]; + const m01 = m[1]; + const m02 = m[2]; + const m03 = m[3]; + const m10 = m[1 * 4 + 0]; + const m11 = m[1 * 4 + 1]; + const m12 = m[1 * 4 + 2]; + const m13 = m[1 * 4 + 3]; + const m20 = m[2 * 4 + 0]; + const m21 = m[2 * 4 + 1]; + const m22 = m[2 * 4 + 2]; + const m23 = m[2 * 4 + 3]; + const m30 = m[3 * 4 + 0]; + const m31 = m[3 * 4 + 1]; + const m32 = m[3 * 4 + 2]; + const m33 = m[3 * 4 + 3]; + + if (m !== dst) { + dst[ 0] = m00; + dst[ 1] = m01; + dst[ 2] = m02; + dst[ 3] = m03; + dst[ 4] = m10; + dst[ 5] = m11; + dst[ 6] = m12; + dst[ 7] = m13; + dst[ 8] = m20; + dst[ 9] = m21; + dst[10] = m22; + dst[11] = m23; + } + + dst[12] = m00 * v0 + m10 * v1 + m20 * v2 + m30; + dst[13] = m01 * v0 + m11 * v1 + m21 * v2 + m31; + dst[14] = m02 * v0 + m12 * v1 + m22 * v2 + m32; + dst[15] = m03 * v0 + m13 * v1 + m23 * v2 + m33; + + return dst; +} + +/** + * Creates a 4-by-4 matrix which rotates around the x-axis by the given angle. + * @param {number} angleInRadians The angle by which to rotate (in radians). + * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created. + * @return {module:twgl/m4.Mat4} The rotation matrix. + * @memberOf module:twgl/m4 + */ +function rotationX(angleInRadians, dst) { + dst = dst || new MatType(16); + + const c = Math.cos(angleInRadians); + const s = Math.sin(angleInRadians); + + dst[ 0] = 1; + dst[ 1] = 0; + dst[ 2] = 0; + dst[ 3] = 0; + dst[ 4] = 0; + dst[ 5] = c; + dst[ 6] = s; + dst[ 7] = 0; + dst[ 8] = 0; + dst[ 9] = -s; + dst[10] = c; + dst[11] = 0; + dst[12] = 0; + dst[13] = 0; + dst[14] = 0; + dst[15] = 1; + + return dst; +} + +/** + * Rotates the given 4-by-4 matrix around the x-axis by the given + * angle. + * @param {module:twgl/m4.Mat4} m The matrix. + * @param {number} angleInRadians The angle by which to rotate (in radians). + * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created. + * @return {module:twgl/m4.Mat4} The rotated matrix. + * @memberOf module:twgl/m4 + */ +function rotateX(m, angleInRadians, dst) { + dst = dst || new MatType(16); + + const m10 = m[4]; + const m11 = m[5]; + const m12 = m[6]; + const m13 = m[7]; + const m20 = m[8]; + const m21 = m[9]; + const m22 = m[10]; + const m23 = m[11]; + const c = Math.cos(angleInRadians); + const s = Math.sin(angleInRadians); + + dst[4] = c * m10 + s * m20; + dst[5] = c * m11 + s * m21; + dst[6] = c * m12 + s * m22; + dst[7] = c * m13 + s * m23; + dst[8] = c * m20 - s * m10; + dst[9] = c * m21 - s * m11; + dst[10] = c * m22 - s * m12; + dst[11] = c * m23 - s * m13; + + if (m !== dst) { + dst[ 0] = m[ 0]; + dst[ 1] = m[ 1]; + dst[ 2] = m[ 2]; + dst[ 3] = m[ 3]; + dst[12] = m[12]; + dst[13] = m[13]; + dst[14] = m[14]; + dst[15] = m[15]; + } + + return dst; +} + +/** + * Creates a 4-by-4 matrix which rotates around the y-axis by the given angle. + * @param {number} angleInRadians The angle by which to rotate (in radians). + * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created. + * @return {module:twgl/m4.Mat4} The rotation matrix. + * @memberOf module:twgl/m4 + */ +function rotationY(angleInRadians, dst) { + dst = dst || new MatType(16); + + const c = Math.cos(angleInRadians); + const s = Math.sin(angleInRadians); + + dst[ 0] = c; + dst[ 1] = 0; + dst[ 2] = -s; + dst[ 3] = 0; + dst[ 4] = 0; + dst[ 5] = 1; + dst[ 6] = 0; + dst[ 7] = 0; + dst[ 8] = s; + dst[ 9] = 0; + dst[10] = c; + dst[11] = 0; + dst[12] = 0; + dst[13] = 0; + dst[14] = 0; + dst[15] = 1; + + return dst; +} + +/** + * Rotates the given 4-by-4 matrix around the y-axis by the given + * angle. + * @param {module:twgl/m4.Mat4} m The matrix. + * @param {number} angleInRadians The angle by which to rotate (in radians). + * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created. + * @return {module:twgl/m4.Mat4} The rotated matrix. + * @memberOf module:twgl/m4 + */ +function rotateY(m, angleInRadians, dst) { + dst = dst || new MatType(16); + + const m00 = m[0 * 4 + 0]; + const m01 = m[0 * 4 + 1]; + const m02 = m[0 * 4 + 2]; + const m03 = m[0 * 4 + 3]; + const m20 = m[2 * 4 + 0]; + const m21 = m[2 * 4 + 1]; + const m22 = m[2 * 4 + 2]; + const m23 = m[2 * 4 + 3]; + const c = Math.cos(angleInRadians); + const s = Math.sin(angleInRadians); + + dst[ 0] = c * m00 - s * m20; + dst[ 1] = c * m01 - s * m21; + dst[ 2] = c * m02 - s * m22; + dst[ 3] = c * m03 - s * m23; + dst[ 8] = c * m20 + s * m00; + dst[ 9] = c * m21 + s * m01; + dst[10] = c * m22 + s * m02; + dst[11] = c * m23 + s * m03; + + if (m !== dst) { + dst[ 4] = m[ 4]; + dst[ 5] = m[ 5]; + dst[ 6] = m[ 6]; + dst[ 7] = m[ 7]; + dst[12] = m[12]; + dst[13] = m[13]; + dst[14] = m[14]; + dst[15] = m[15]; + } + + return dst; +} + +/** + * Creates a 4-by-4 matrix which rotates around the z-axis by the given angle. + * @param {number} angleInRadians The angle by which to rotate (in radians). + * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created. + * @return {module:twgl/m4.Mat4} The rotation matrix. + * @memberOf module:twgl/m4 + */ +function rotationZ(angleInRadians, dst) { + dst = dst || new MatType(16); + + const c = Math.cos(angleInRadians); + const s = Math.sin(angleInRadians); + + dst[ 0] = c; + dst[ 1] = s; + dst[ 2] = 0; + dst[ 3] = 0; + dst[ 4] = -s; + dst[ 5] = c; + dst[ 6] = 0; + dst[ 7] = 0; + dst[ 8] = 0; + dst[ 9] = 0; + dst[10] = 1; + dst[11] = 0; + dst[12] = 0; + dst[13] = 0; + dst[14] = 0; + dst[15] = 1; + + return dst; +} + +/** + * Rotates the given 4-by-4 matrix around the z-axis by the given + * angle. + * @param {module:twgl/m4.Mat4} m The matrix. + * @param {number} angleInRadians The angle by which to rotate (in radians). + * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created. + * @return {module:twgl/m4.Mat4} The rotated matrix. + * @memberOf module:twgl/m4 + */ +function rotateZ(m, angleInRadians, dst) { + dst = dst || new MatType(16); + + const m00 = m[0 * 4 + 0]; + const m01 = m[0 * 4 + 1]; + const m02 = m[0 * 4 + 2]; + const m03 = m[0 * 4 + 3]; + const m10 = m[1 * 4 + 0]; + const m11 = m[1 * 4 + 1]; + const m12 = m[1 * 4 + 2]; + const m13 = m[1 * 4 + 3]; + const c = Math.cos(angleInRadians); + const s = Math.sin(angleInRadians); + + dst[ 0] = c * m00 + s * m10; + dst[ 1] = c * m01 + s * m11; + dst[ 2] = c * m02 + s * m12; + dst[ 3] = c * m03 + s * m13; + dst[ 4] = c * m10 - s * m00; + dst[ 5] = c * m11 - s * m01; + dst[ 6] = c * m12 - s * m02; + dst[ 7] = c * m13 - s * m03; + + if (m !== dst) { + dst[ 8] = m[ 8]; + dst[ 9] = m[ 9]; + dst[10] = m[10]; + dst[11] = m[11]; + dst[12] = m[12]; + dst[13] = m[13]; + dst[14] = m[14]; + dst[15] = m[15]; + } + + return dst; +} + +/** + * Creates a 4-by-4 matrix which rotates around the given axis by the given + * angle. + * @param {module:twgl/v3.Vec3} axis The axis + * about which to rotate. + * @param {number} angleInRadians The angle by which to rotate (in radians). + * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created. + * @return {module:twgl/m4.Mat4} A matrix which rotates angle radians + * around the axis. + * @memberOf module:twgl/m4 + */ +function axisRotation(axis, angleInRadians, dst) { + dst = dst || new MatType(16); + + let x = axis[0]; + let y = axis[1]; + let z = axis[2]; + const n = Math.sqrt(x * x + y * y + z * z); + x /= n; + y /= n; + z /= n; + const xx = x * x; + const yy = y * y; + const zz = z * z; + const c = Math.cos(angleInRadians); + const s = Math.sin(angleInRadians); + const oneMinusCosine = 1 - c; + + dst[ 0] = xx + (1 - xx) * c; + dst[ 1] = x * y * oneMinusCosine + z * s; + dst[ 2] = x * z * oneMinusCosine - y * s; + dst[ 3] = 0; + dst[ 4] = x * y * oneMinusCosine - z * s; + dst[ 5] = yy + (1 - yy) * c; + dst[ 6] = y * z * oneMinusCosine + x * s; + dst[ 7] = 0; + dst[ 8] = x * z * oneMinusCosine + y * s; + dst[ 9] = y * z * oneMinusCosine - x * s; + dst[10] = zz + (1 - zz) * c; + dst[11] = 0; + dst[12] = 0; + dst[13] = 0; + dst[14] = 0; + dst[15] = 1; + + return dst; +} + +/** + * Rotates the given 4-by-4 matrix around the given axis by the + * given angle. + * @param {module:twgl/m4.Mat4} m The matrix. + * @param {module:twgl/v3.Vec3} axis The axis + * about which to rotate. + * @param {number} angleInRadians The angle by which to rotate (in radians). + * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created. + * @return {module:twgl/m4.Mat4} The rotated matrix. + * @memberOf module:twgl/m4 + */ +function axisRotate(m, axis, angleInRadians, dst) { + dst = dst || new MatType(16); + + let x = axis[0]; + let y = axis[1]; + let z = axis[2]; + const n = Math.sqrt(x * x + y * y + z * z); + x /= n; + y /= n; + z /= n; + const xx = x * x; + const yy = y * y; + const zz = z * z; + const c = Math.cos(angleInRadians); + const s = Math.sin(angleInRadians); + const oneMinusCosine = 1 - c; + + const r00 = xx + (1 - xx) * c; + const r01 = x * y * oneMinusCosine + z * s; + const r02 = x * z * oneMinusCosine - y * s; + const r10 = x * y * oneMinusCosine - z * s; + const r11 = yy + (1 - yy) * c; + const r12 = y * z * oneMinusCosine + x * s; + const r20 = x * z * oneMinusCosine + y * s; + const r21 = y * z * oneMinusCosine - x * s; + const r22 = zz + (1 - zz) * c; + + const m00 = m[0]; + const m01 = m[1]; + const m02 = m[2]; + const m03 = m[3]; + const m10 = m[4]; + const m11 = m[5]; + const m12 = m[6]; + const m13 = m[7]; + const m20 = m[8]; + const m21 = m[9]; + const m22 = m[10]; + const m23 = m[11]; + + dst[ 0] = r00 * m00 + r01 * m10 + r02 * m20; + dst[ 1] = r00 * m01 + r01 * m11 + r02 * m21; + dst[ 2] = r00 * m02 + r01 * m12 + r02 * m22; + dst[ 3] = r00 * m03 + r01 * m13 + r02 * m23; + dst[ 4] = r10 * m00 + r11 * m10 + r12 * m20; + dst[ 5] = r10 * m01 + r11 * m11 + r12 * m21; + dst[ 6] = r10 * m02 + r11 * m12 + r12 * m22; + dst[ 7] = r10 * m03 + r11 * m13 + r12 * m23; + dst[ 8] = r20 * m00 + r21 * m10 + r22 * m20; + dst[ 9] = r20 * m01 + r21 * m11 + r22 * m21; + dst[10] = r20 * m02 + r21 * m12 + r22 * m22; + dst[11] = r20 * m03 + r21 * m13 + r22 * m23; + + if (m !== dst) { + dst[12] = m[12]; + dst[13] = m[13]; + dst[14] = m[14]; + dst[15] = m[15]; + } + + return dst; +} + +/** + * Creates a 4-by-4 matrix which scales in each dimension by an amount given by + * the corresponding entry in the given vector; assumes the vector has three + * entries. + * @param {module:twgl/v3.Vec3} v A vector of + * three entries specifying the factor by which to scale in each dimension. + * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created. + * @return {module:twgl/m4.Mat4} The scaling matrix. + * @memberOf module:twgl/m4 + */ +function scaling(v, dst) { + dst = dst || new MatType(16); + + dst[ 0] = v[0]; + dst[ 1] = 0; + dst[ 2] = 0; + dst[ 3] = 0; + dst[ 4] = 0; + dst[ 5] = v[1]; + dst[ 6] = 0; + dst[ 7] = 0; + dst[ 8] = 0; + dst[ 9] = 0; + dst[10] = v[2]; + dst[11] = 0; + dst[12] = 0; + dst[13] = 0; + dst[14] = 0; + dst[15] = 1; + + return dst; +} + +/** + * Scales the given 4-by-4 matrix in each dimension by an amount + * given by the corresponding entry in the given vector; assumes the vector has + * three entries. + * @param {module:twgl/m4.Mat4} m The matrix to be modified. + * @param {module:twgl/v3.Vec3} v A vector of three entries specifying the + * factor by which to scale in each dimension. + * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created. + * @return {module:twgl/m4.Mat4} The scaled matrix. + * @memberOf module:twgl/m4 + */ +function scale(m, v, dst) { + dst = dst || new MatType(16); + + const v0 = v[0]; + const v1 = v[1]; + const v2 = v[2]; + + dst[ 0] = v0 * m[0 * 4 + 0]; + dst[ 1] = v0 * m[0 * 4 + 1]; + dst[ 2] = v0 * m[0 * 4 + 2]; + dst[ 3] = v0 * m[0 * 4 + 3]; + dst[ 4] = v1 * m[1 * 4 + 0]; + dst[ 5] = v1 * m[1 * 4 + 1]; + dst[ 6] = v1 * m[1 * 4 + 2]; + dst[ 7] = v1 * m[1 * 4 + 3]; + dst[ 8] = v2 * m[2 * 4 + 0]; + dst[ 9] = v2 * m[2 * 4 + 1]; + dst[10] = v2 * m[2 * 4 + 2]; + dst[11] = v2 * m[2 * 4 + 3]; + + if (m !== dst) { + dst[12] = m[12]; + dst[13] = m[13]; + dst[14] = m[14]; + dst[15] = m[15]; + } + + return dst; +} + +/** + * Takes a 4-by-4 matrix and a vector with 3 entries, + * interprets the vector as a point, transforms that point by the matrix, and + * returns the result as a vector with 3 entries. + * @param {module:twgl/m4.Mat4} m The matrix. + * @param {module:twgl/v3.Vec3} v The point. + * @param {module:twgl/v3.Vec3} [dst] optional vec3 to store result. If not passed a new one is created. + * @return {module:twgl/v3.Vec3} The transformed point. + * @memberOf module:twgl/m4 + */ +function transformPoint(m, v, dst) { + dst = dst || create$1(); + const v0 = v[0]; + const v1 = v[1]; + const v2 = v[2]; + const d = v0 * m[0 * 4 + 3] + v1 * m[1 * 4 + 3] + v2 * m[2 * 4 + 3] + m[3 * 4 + 3]; + + dst[0] = (v0 * m[0 * 4 + 0] + v1 * m[1 * 4 + 0] + v2 * m[2 * 4 + 0] + m[3 * 4 + 0]) / d; + dst[1] = (v0 * m[0 * 4 + 1] + v1 * m[1 * 4 + 1] + v2 * m[2 * 4 + 1] + m[3 * 4 + 1]) / d; + dst[2] = (v0 * m[0 * 4 + 2] + v1 * m[1 * 4 + 2] + v2 * m[2 * 4 + 2] + m[3 * 4 + 2]) / d; + + return dst; +} + +/** + * Takes a 4-by-4 matrix and a vector with 3 entries, interprets the vector as a + * direction, transforms that direction by the matrix, and returns the result; + * assumes the transformation of 3-dimensional space represented by the matrix + * is parallel-preserving, i.e. any combination of rotation, scaling and + * translation, but not a perspective distortion. Returns a vector with 3 + * entries. + * @param {module:twgl/m4.Mat4} m The matrix. + * @param {module:twgl/v3.Vec3} v The direction. + * @param {module:twgl/v3.Vec3} [dst] optional Vec3 to store result. If not passed a new one is created. + * @return {module:twgl/v3.Vec3} The transformed direction. + * @memberOf module:twgl/m4 + */ +function transformDirection(m, v, dst) { + dst = dst || create$1(); + + const v0 = v[0]; + const v1 = v[1]; + const v2 = v[2]; + + dst[0] = v0 * m[0 * 4 + 0] + v1 * m[1 * 4 + 0] + v2 * m[2 * 4 + 0]; + dst[1] = v0 * m[0 * 4 + 1] + v1 * m[1 * 4 + 1] + v2 * m[2 * 4 + 1]; + dst[2] = v0 * m[0 * 4 + 2] + v1 * m[1 * 4 + 2] + v2 * m[2 * 4 + 2]; + + return dst; +} + +/** + * Takes a 4-by-4 matrix m and a vector v with 3 entries, interprets the vector + * as a normal to a surface, and computes a vector which is normal upon + * transforming that surface by the matrix. The effect of this function is the + * same as transforming v (as a direction) by the inverse-transpose of m. This + * function assumes the transformation of 3-dimensional space represented by the + * matrix is parallel-preserving, i.e. any combination of rotation, scaling and + * translation, but not a perspective distortion. Returns a vector with 3 + * entries. + * @param {module:twgl/m4.Mat4} m The matrix. + * @param {module:twgl/v3.Vec3} v The normal. + * @param {module:twgl/v3.Vec3} [dst] The direction. If not passed a new one is created. + * @return {module:twgl/v3.Vec3} The transformed normal. + * @memberOf module:twgl/m4 + */ +function transformNormal$1(m, v, dst) { + dst = dst || create$1(); + const mi = inverse(m); + const v0 = v[0]; + const v1 = v[1]; + const v2 = v[2]; + + dst[0] = v0 * mi[0 * 4 + 0] + v1 * mi[0 * 4 + 1] + v2 * mi[0 * 4 + 2]; + dst[1] = v0 * mi[1 * 4 + 0] + v1 * mi[1 * 4 + 1] + v2 * mi[1 * 4 + 2]; + dst[2] = v0 * mi[2 * 4 + 0] + v1 * mi[2 * 4 + 1] + v2 * mi[2 * 4 + 2]; + + return dst; +} + +var m4 = /*#__PURE__*/Object.freeze({ + __proto__: null, + axisRotate: axisRotate, + axisRotation: axisRotation, + copy: copy, + create: create, + frustum: frustum, + getAxis: getAxis, + getTranslation: getTranslation, + identity: identity, + inverse: inverse, + lookAt: lookAt, + multiply: multiply, + negate: negate, + ortho: ortho, + perspective: perspective, + rotateX: rotateX, + rotateY: rotateY, + rotateZ: rotateZ, + rotationX: rotationX, + rotationY: rotationY, + rotationZ: rotationZ, + scale: scale, + scaling: scaling, + setAxis: setAxis, + setDefaultType: setDefaultType, + setTranslation: setTranslation, + transformDirection: transformDirection, + transformNormal: transformNormal$1, + transformPoint: transformPoint, + translate: translate, + translation: translation, + transpose: transpose +}); + +/* + * Copyright 2019 Gregg Tavares + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/* DataType */ +const BYTE$2 = 0x1400; +const UNSIGNED_BYTE$3 = 0x1401; +const SHORT$2 = 0x1402; +const UNSIGNED_SHORT$3 = 0x1403; +const INT$3 = 0x1404; +const UNSIGNED_INT$3 = 0x1405; +const FLOAT$3 = 0x1406; +const UNSIGNED_SHORT_4_4_4_4$1 = 0x8033; +const UNSIGNED_SHORT_5_5_5_1$1 = 0x8034; +const UNSIGNED_SHORT_5_6_5$1 = 0x8363; +const HALF_FLOAT$1 = 0x140B; +const UNSIGNED_INT_2_10_10_10_REV$1 = 0x8368; +const UNSIGNED_INT_10F_11F_11F_REV$1 = 0x8C3B; +const UNSIGNED_INT_5_9_9_9_REV$1 = 0x8C3E; +const FLOAT_32_UNSIGNED_INT_24_8_REV$1 = 0x8DAD; +const UNSIGNED_INT_24_8$1 = 0x84FA; + +const glTypeToTypedArray = {}; +{ + const tt = glTypeToTypedArray; + tt[BYTE$2] = Int8Array; + tt[UNSIGNED_BYTE$3] = Uint8Array; + tt[SHORT$2] = Int16Array; + tt[UNSIGNED_SHORT$3] = Uint16Array; + tt[INT$3] = Int32Array; + tt[UNSIGNED_INT$3] = Uint32Array; + tt[FLOAT$3] = Float32Array; + tt[UNSIGNED_SHORT_4_4_4_4$1] = Uint16Array; + tt[UNSIGNED_SHORT_5_5_5_1$1] = Uint16Array; + tt[UNSIGNED_SHORT_5_6_5$1] = Uint16Array; + tt[HALF_FLOAT$1] = Uint16Array; + tt[UNSIGNED_INT_2_10_10_10_REV$1] = Uint32Array; + tt[UNSIGNED_INT_10F_11F_11F_REV$1] = Uint32Array; + tt[UNSIGNED_INT_5_9_9_9_REV$1] = Uint32Array; + tt[FLOAT_32_UNSIGNED_INT_24_8_REV$1] = Uint32Array; + tt[UNSIGNED_INT_24_8$1] = Uint32Array; +} + +/** + * Get the GL type for a typedArray + * @param {ArrayBufferView} typedArray a typedArray + * @return {number} the GL type for array. For example pass in an `Int8Array` and `gl.BYTE` will + * be returned. Pass in a `Uint32Array` and `gl.UNSIGNED_INT` will be returned + * @memberOf module:twgl/typedArray + */ +function getGLTypeForTypedArray(typedArray) { + if (typedArray instanceof Int8Array) { return BYTE$2; } // eslint-disable-line + if (typedArray instanceof Uint8Array) { return UNSIGNED_BYTE$3; } // eslint-disable-line + if (typedArray instanceof Uint8ClampedArray) { return UNSIGNED_BYTE$3; } // eslint-disable-line + if (typedArray instanceof Int16Array) { return SHORT$2; } // eslint-disable-line + if (typedArray instanceof Uint16Array) { return UNSIGNED_SHORT$3; } // eslint-disable-line + if (typedArray instanceof Int32Array) { return INT$3; } // eslint-disable-line + if (typedArray instanceof Uint32Array) { return UNSIGNED_INT$3; } // eslint-disable-line + if (typedArray instanceof Float32Array) { return FLOAT$3; } // eslint-disable-line + throw new Error('unsupported typed array type'); +} + +/** + * Get the GL type for a typedArray type + * @param {ArrayBufferView} typedArrayType a typedArray constructor + * @return {number} the GL type for type. For example pass in `Int8Array` and `gl.BYTE` will + * be returned. Pass in `Uint32Array` and `gl.UNSIGNED_INT` will be returned + * @memberOf module:twgl/typedArray + */ +function getGLTypeForTypedArrayType(typedArrayType) { + if (typedArrayType === Int8Array) { return BYTE$2; } // eslint-disable-line + if (typedArrayType === Uint8Array) { return UNSIGNED_BYTE$3; } // eslint-disable-line + if (typedArrayType === Uint8ClampedArray) { return UNSIGNED_BYTE$3; } // eslint-disable-line + if (typedArrayType === Int16Array) { return SHORT$2; } // eslint-disable-line + if (typedArrayType === Uint16Array) { return UNSIGNED_SHORT$3; } // eslint-disable-line + if (typedArrayType === Int32Array) { return INT$3; } // eslint-disable-line + if (typedArrayType === Uint32Array) { return UNSIGNED_INT$3; } // eslint-disable-line + if (typedArrayType === Float32Array) { return FLOAT$3; } // eslint-disable-line + throw new Error('unsupported typed array type'); +} + +/** + * Get the typed array constructor for a given GL type + * @param {number} type the GL type. (eg: `gl.UNSIGNED_INT`) + * @return {function} the constructor for a the corresponding typed array. (eg. `Uint32Array`). + * @memberOf module:twgl/typedArray + */ +function getTypedArrayTypeForGLType(type) { + const CTOR = glTypeToTypedArray[type]; + if (!CTOR) { + throw new Error('unknown gl type'); + } + return CTOR; +} + +const isArrayBuffer$1 = typeof SharedArrayBuffer !== 'undefined' + ? function isArrayBufferOrSharedArrayBuffer(a) { + return a && a.buffer && (a.buffer instanceof ArrayBuffer || a.buffer instanceof SharedArrayBuffer); + } + : function isArrayBuffer(a) { + return a && a.buffer && a.buffer instanceof ArrayBuffer; + }; + +var typedarrays = /*#__PURE__*/Object.freeze({ + __proto__: null, + getGLTypeForTypedArray: getGLTypeForTypedArray, + getGLTypeForTypedArrayType: getGLTypeForTypedArrayType, + getTypedArrayTypeForGLType: getTypedArrayTypeForGLType, + isArrayBuffer: isArrayBuffer$1 +}); + +/* + * Copyright 2019 Gregg Tavares + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/* eslint no-console: "off" */ + +/** + * Copy named properties + * + * @param {string[]} names names of properties to copy + * @param {object} src object to copy properties from + * @param {object} dst object to copy properties to + * @private + */ +function copyNamedProperties(names, src, dst) { + names.forEach(function(name) { + const value = src[name]; + if (value !== undefined) { + dst[name] = value; + } + }); +} + +/** + * Copies properties from source to dest only if a matching key is in dest + * + * @param {Object.} src the source + * @param {Object.} dst the dest + * @private + */ +function copyExistingProperties(src, dst) { + Object.keys(dst).forEach(function(key) { + if (dst.hasOwnProperty(key) && src.hasOwnProperty(key)) { /* eslint no-prototype-builtins: 0 */ + dst[key] = src[key]; + } + }); +} + +function error$1(...args) { + console.error(...args); +} + +function warn$1(...args) { + console.warn(...args); +} + +const isTypeWeakMaps = new Map(); + +function isType(object, type) { + if (!object || typeof object !== 'object') { + return false; + } + let weakMap = isTypeWeakMaps.get(type); + if (!weakMap) { + weakMap = new WeakMap(); + isTypeWeakMaps.set(type, weakMap); + } + let isOfType = weakMap.get(object); + if (isOfType === undefined) { + const s = Object.prototype.toString.call(object); + isOfType = s.substring(8, s.length - 1) === type; + weakMap.set(object, isOfType); + } + return isOfType; +} + +function isBuffer(gl, t) { + return typeof WebGLBuffer !== 'undefined' && isType(t, 'WebGLBuffer'); +} + +function isRenderbuffer(gl, t) { + return typeof WebGLRenderbuffer !== 'undefined' && isType(t, 'WebGLRenderbuffer'); +} + +function isTexture(gl, t) { + return typeof WebGLTexture !== 'undefined' && isType(t, 'WebGLTexture'); +} + +function isSampler(gl, t) { + return typeof WebGLSampler !== 'undefined' && isType(t, 'WebGLSampler'); +} + +/* + * Copyright 2019 Gregg Tavares + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +const STATIC_DRAW = 0x88e4; +const ARRAY_BUFFER$1 = 0x8892; +const ELEMENT_ARRAY_BUFFER$2 = 0x8893; +const BUFFER_SIZE = 0x8764; + +const BYTE$1 = 0x1400; +const UNSIGNED_BYTE$2 = 0x1401; +const SHORT$1 = 0x1402; +const UNSIGNED_SHORT$2 = 0x1403; +const INT$2 = 0x1404; +const UNSIGNED_INT$2 = 0x1405; +const FLOAT$2 = 0x1406; +const defaults$2 = { + attribPrefix: "", +}; + +/** + * Sets the default attrib prefix + * + * When writing shaders I prefer to name attributes with `a_`, uniforms with `u_` and varyings with `v_` + * as it makes it clear where they came from. But, when building geometry I prefer using un-prefixed names. + * + * In other words I'll create arrays of geometry like this + * + * var arrays = { + * position: ... + * normal: ... + * texcoord: ... + * }; + * + * But need those mapped to attributes and my attributes start with `a_`. + * + * @deprecated see {@link module:twgl.setDefaults} + * @param {string} prefix prefix for attribs + * @memberOf module:twgl/attributes + */ +function setAttributePrefix(prefix) { + defaults$2.attribPrefix = prefix; +} + +function setDefaults$2(newDefaults) { + copyExistingProperties(newDefaults, defaults$2); +} + +function setBufferFromTypedArray(gl, type, buffer, array, drawType) { + gl.bindBuffer(type, buffer); + gl.bufferData(type, array, drawType || STATIC_DRAW); +} + +/** + * Given typed array creates a WebGLBuffer and copies the typed array + * into it. + * + * @param {WebGLRenderingContext} gl A WebGLRenderingContext + * @param {ArrayBuffer|SharedArrayBuffer|ArrayBufferView|WebGLBuffer} typedArray the typed array. Note: If a WebGLBuffer is passed in it will just be returned. No action will be taken + * @param {number} [type] the GL bind type for the buffer. Default = `gl.ARRAY_BUFFER`. + * @param {number} [drawType] the GL draw type for the buffer. Default = 'gl.STATIC_DRAW`. + * @return {WebGLBuffer} the created WebGLBuffer + * @memberOf module:twgl/attributes + */ +function createBufferFromTypedArray(gl, typedArray, type, drawType) { + if (isBuffer(gl, typedArray)) { + return typedArray; + } + type = type || ARRAY_BUFFER$1; + const buffer = gl.createBuffer(); + setBufferFromTypedArray(gl, type, buffer, typedArray, drawType); + return buffer; +} + +function isIndices(name) { + return name === "indices"; +} + +// This is really just a guess. Though I can't really imagine using +// anything else? Maybe for some compression? +function getNormalizationForTypedArrayType(typedArrayType) { + if (typedArrayType === Int8Array) { return true; } // eslint-disable-line + if (typedArrayType === Uint8Array) { return true; } // eslint-disable-line + return false; +} + +function getArray$1(array) { + return array.length ? array : array.data; +} + +const texcoordRE = /coord|texture/i; +const colorRE = /color|colour/i; + +function guessNumComponentsFromName(name, length) { + let numComponents; + if (texcoordRE.test(name)) { + numComponents = 2; + } else if (colorRE.test(name)) { + numComponents = 4; + } else { + numComponents = 3; // position, normals, indices ... + } + + if (length % numComponents > 0) { + throw new Error(`Can not guess numComponents for attribute '${name}'. Tried ${numComponents} but ${length} values is not evenly divisible by ${numComponents}. You should specify it.`); + } + + return numComponents; +} + +function getNumComponents$1(array, arrayName, numValues) { + return array.numComponents || array.size || guessNumComponentsFromName(arrayName, numValues || getArray$1(array).length); +} + +function makeTypedArray(array, name) { + if (isArrayBuffer$1(array)) { + return array; + } + + if (isArrayBuffer$1(array.data)) { + return array.data; + } + + if (Array.isArray(array)) { + array = { + data: array, + }; + } + + let Type = array.type ? typedArrayTypeFromGLTypeOrTypedArrayCtor(array.type) : undefined; + if (!Type) { + if (isIndices(name)) { + Type = Uint16Array; + } else { + Type = Float32Array; + } + } + return new Type(array.data); +} + +function glTypeFromGLTypeOrTypedArrayType(glTypeOrTypedArrayCtor) { + return typeof glTypeOrTypedArrayCtor === 'number' + ? glTypeOrTypedArrayCtor + : glTypeOrTypedArrayCtor ? getGLTypeForTypedArrayType(glTypeOrTypedArrayCtor) : FLOAT$2; +} + +function typedArrayTypeFromGLTypeOrTypedArrayCtor(glTypeOrTypedArrayCtor) { + return typeof glTypeOrTypedArrayCtor === 'number' + ? getTypedArrayTypeForGLType(glTypeOrTypedArrayCtor) + : glTypeOrTypedArrayCtor || Float32Array; +} + +function attribBufferFromBuffer(gl, array/*, arrayName */) { + return { + buffer: array.buffer, + numValues: 2 * 3 * 4, // safely divided by 2, 3, 4 + type: glTypeFromGLTypeOrTypedArrayType(array.type), + arrayType: typedArrayTypeFromGLTypeOrTypedArrayCtor(array.type), + }; +} + +function attribBufferFromSize(gl, array/*, arrayName*/) { + const numValues = array.data || array; + const arrayType = typedArrayTypeFromGLTypeOrTypedArrayCtor(array.type); + const numBytes = numValues * arrayType.BYTES_PER_ELEMENT; + const buffer = gl.createBuffer(); + gl.bindBuffer(ARRAY_BUFFER$1, buffer); + gl.bufferData(ARRAY_BUFFER$1, numBytes, array.drawType || STATIC_DRAW); + return { + buffer, + numValues, + type: getGLTypeForTypedArrayType(arrayType), + arrayType, + }; +} + +function attribBufferFromArrayLike(gl, array, arrayName) { + const typedArray = makeTypedArray(array, arrayName); + return { + arrayType: typedArray.constructor, + buffer: createBufferFromTypedArray(gl, typedArray, undefined, array.drawType), + type: getGLTypeForTypedArray(typedArray), + numValues: 0, + }; +} + +/** + * The info for an attribute. This is effectively just the arguments to `gl.vertexAttribPointer` plus the WebGLBuffer + * for the attribute. + * + * @typedef {Object} AttribInfo + * @property {number[]|ArrayBufferView} [value] a constant value for the attribute. Note: if this is set the attribute will be + * disabled and set to this constant value and all other values will be ignored. + * @property {number} [numComponents] the number of components for this attribute. + * @property {number} [size] synonym for `numComponents`. + * @property {number} [type] the type of the attribute (eg. `gl.FLOAT`, `gl.UNSIGNED_BYTE`, etc...) Default = `gl.FLOAT` + * @property {boolean} [normalize] whether or not to normalize the data. Default = false + * @property {number} [offset] offset into buffer in bytes. Default = 0 + * @property {number} [stride] the stride in bytes per element. Default = 0 + * @property {number} [divisor] the divisor in instances. Default = 0. + * Requires WebGL2 or the ANGLE_instanced_arrays extension. + * and, if you're using WebGL1 you must have called {@link module:twgl.addExtensionsToContext} + * @property {WebGLBuffer} buffer the buffer that contains the data for this attribute + * @property {number} [drawType] the draw type passed to gl.bufferData. Default = gl.STATIC_DRAW + * @memberOf module:twgl + */ + +/** + * @typedef {(Int8ArrayConstructor|Uint8ArrayConstructor|Int16ArrayConstructor|Uint16ArrayConstructor|Int32ArrayConstructor|Uint32ArrayConstructor|Float32ArrayConstructor)} TypedArrayConstructor + */ + +/** + * Use this type of array spec when TWGL can't guess the type or number of components of an array + * @typedef {Object} FullArraySpec + * @property {number[]|ArrayBufferView} [value] a constant value for the attribute. Note: if this is set the attribute will be + * disabled and set to this constant value and all other values will be ignored. + * @property {(number|number[]|ArrayBufferView)} [data] The data of the array. A number alone becomes the number of elements of type. + * @property {number} [numComponents] number of components for `vertexAttribPointer`. Default is based on the name of the array. + * If `coord` is in the name assumes `numComponents = 2`. + * If `color` is in the name assumes `numComponents = 4`. + * otherwise assumes `numComponents = 3` + * @property {number|TypedArrayConstructor} [type] type. This is used if `data` is a JavaScript array, or `buffer` is passed in, or `data` is a number. + * It can either be the constructor for a typedarray. (eg. `Uint8Array`) OR a WebGL type, (eg `gl.UNSIGNED_BYTE`). + * For example if you want colors in a `Uint8Array` you might have a `FullArraySpec` like `{ type: gl.UNSIGNED_BYTE, data: [255,0,255,255, ...], }`. + * @property {number} [size] synonym for `numComponents`. + * @property {boolean} [normalize] normalize for `vertexAttribPointer`. Default is true if type is `Int8Array` or `Uint8Array` otherwise false. + * @property {number} [stride] stride for `vertexAttribPointer`. Default = 0 + * @property {number} [offset] offset for `vertexAttribPointer`. Default = 0 + * @property {number} [divisor] divisor for `vertexAttribDivisor`. Default = 0. + * Requires WebGL2 or the ANGLE_instanced_arrays extension. + * and, if you using WebGL1 you must have called {@link module:twgl.addExtensionsToContext} + * @property {string} [attrib] name of attribute this array maps to. Defaults to same name as array prefixed by the default attribPrefix. + * @property {string} [name] synonym for `attrib`. + * @property {string} [attribName] synonym for `attrib`. + * @property {WebGLBuffer} [buffer] Buffer to use for this attribute. This lets you use your own buffer + * but you will need to supply `numComponents` and `type`. You can effectively pass an `AttribInfo` + * to provide this. Example: + * + * const bufferInfo1 = twgl.createBufferInfoFromArrays(gl, { + * position: [1, 2, 3, ... ], + * }); + * const bufferInfo2 = twgl.createBufferInfoFromArrays(gl, { + * position: bufferInfo1.attribs.position, // use the same buffer from bufferInfo1 + * }); + * + * @property {number} [drawType] the draw type passed to gl.bufferData. Default = gl.STATIC_DRAW + * @memberOf module:twgl + */ + +/** + * An individual array in {@link module:twgl.Arrays} + * + * When passed to {@link module:twgl.createBufferInfoFromArrays} if an ArraySpec is `number[]` or `ArrayBufferView` + * the types will be guessed based on the name. `indices` will be `Uint16Array`, everything else will + * be `Float32Array`. If an ArraySpec is a number it's the number of floats for an empty (zeroed) buffer. + * + * @typedef {(number|number[]|ArrayBufferView|module:twgl.FullArraySpec)} ArraySpec + * @memberOf module:twgl + */ + +/** + * This is a JavaScript object of arrays by name. The names should match your shader's attributes. If your + * attributes have a common prefix you can specify it by calling {@link module:twgl.setAttributePrefix}. + * + * Bare JavaScript Arrays + * + * var arrays = { + * position: [-1, 1, 0], + * normal: [0, 1, 0], + * ... + * } + * + * Bare TypedArrays + * + * var arrays = { + * position: new Float32Array([-1, 1, 0]), + * color: new Uint8Array([255, 128, 64, 255]), + * ... + * } + * + * * Will guess at `numComponents` if not specified based on name. + * + * If `coord` is in the name assumes `numComponents = 2` + * + * If `color` is in the name assumes `numComponents = 4` + * + * otherwise assumes `numComponents = 3` + * + * Objects with various fields. See {@link module:twgl.FullArraySpec}. + * + * var arrays = { + * position: { numComponents: 3, data: [0, 0, 0, 10, 0, 0, 0, 10, 0, 10, 10, 0], }, + * texcoord: { numComponents: 2, data: [0, 0, 0, 1, 1, 0, 1, 1], }, + * normal: { numComponents: 3, data: [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1], }, + * indices: { numComponents: 3, data: [0, 1, 2, 1, 2, 3], }, + * }; + * + * @typedef {Object.} Arrays + * @memberOf module:twgl + */ + + +/** + * Creates a set of attribute data and WebGLBuffers from set of arrays + * + * Given + * + * var arrays = { + * position: { numComponents: 3, data: [0, 0, 0, 10, 0, 0, 0, 10, 0, 10, 10, 0], }, + * texcoord: { numComponents: 2, data: [0, 0, 0, 1, 1, 0, 1, 1], }, + * normal: { numComponents: 3, data: [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1], }, + * color: { numComponents: 4, data: [255, 255, 255, 255, 255, 0, 0, 255, 0, 0, 255, 255], type: Uint8Array, }, + * indices: { numComponents: 3, data: [0, 1, 2, 1, 2, 3], }, + * }; + * + * returns something like + * + * var attribs = { + * position: { numComponents: 3, type: gl.FLOAT, normalize: false, buffer: WebGLBuffer, }, + * texcoord: { numComponents: 2, type: gl.FLOAT, normalize: false, buffer: WebGLBuffer, }, + * normal: { numComponents: 3, type: gl.FLOAT, normalize: false, buffer: WebGLBuffer, }, + * color: { numComponents: 4, type: gl.UNSIGNED_BYTE, normalize: true, buffer: WebGLBuffer, }, + * }; + * + * notes: + * + * * Arrays can take various forms + * + * Bare JavaScript Arrays + * + * var arrays = { + * position: [-1, 1, 0], + * normal: [0, 1, 0], + * ... + * } + * + * Bare TypedArrays + * + * var arrays = { + * position: new Float32Array([-1, 1, 0]), + * color: new Uint8Array([255, 128, 64, 255]), + * ... + * } + * + * * Will guess at `numComponents` if not specified based on name. + * + * If `coord` is in the name assumes `numComponents = 2` + * + * If `color` is in the name assumes `numComponents = 4` + * + * otherwise assumes `numComponents = 3` + * + * @param {WebGLRenderingContext} gl The webgl rendering context. + * @param {module:twgl.Arrays} arrays The arrays + * @param {module:twgl.BufferInfo} [srcBufferInfo] a BufferInfo to copy from + * This lets you share buffers. Any arrays you supply will override + * the buffers from srcBufferInfo. + * @return {Object.} the attribs + * @memberOf module:twgl/attributes + */ +function createAttribsFromArrays(gl, arrays) { + const attribs = {}; + Object.keys(arrays).forEach(function(arrayName) { + if (!isIndices(arrayName)) { + const array = arrays[arrayName]; + const attribName = array.attrib || array.name || array.attribName || (defaults$2.attribPrefix + arrayName); + if (array.value) { + if (!Array.isArray(array.value) && !isArrayBuffer$1(array.value)) { + throw new Error('array.value is not array or typedarray'); + } + attribs[attribName] = { + value: array.value, + }; + } else { + let fn; + if (array.buffer && array.buffer instanceof WebGLBuffer) { + fn = attribBufferFromBuffer; + } else if (typeof array === "number" || typeof array.data === "number") { + fn = attribBufferFromSize; + } else { + fn = attribBufferFromArrayLike; + } + const {buffer, type, numValues, arrayType} = fn(gl, array, arrayName); + const normalization = array.normalize !== undefined ? array.normalize : getNormalizationForTypedArrayType(arrayType); + const numComponents = getNumComponents$1(array, arrayName, numValues); + attribs[attribName] = { + buffer: buffer, + numComponents: numComponents, + type: type, + normalize: normalization, + stride: array.stride || 0, + offset: array.offset || 0, + divisor: array.divisor === undefined ? undefined : array.divisor, + drawType: array.drawType, + }; + } + } + }); + gl.bindBuffer(ARRAY_BUFFER$1, null); + return attribs; +} + +/** + * Sets the contents of a buffer attached to an attribInfo + * + * This is helper function to dynamically update a buffer. + * + * Let's say you make a bufferInfo + * + * var arrays = { + * position: new Float32Array([0, 0, 0, 10, 0, 0, 0, 10, 0, 10, 10, 0]), + * texcoord: new Float32Array([0, 0, 0, 1, 1, 0, 1, 1]), + * normal: new Float32Array([0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1]), + * indices: new Uint16Array([0, 1, 2, 1, 2, 3]), + * }; + * var bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays); + * + * And you want to dynamically update the positions. You could do this + * + * // assuming arrays.position has already been updated with new data. + * twgl.setAttribInfoBufferFromArray(gl, bufferInfo.attribs.position, arrays.position); + * + * @param {WebGLRenderingContext} gl + * @param {AttribInfo} attribInfo The attribInfo who's buffer contents to set. NOTE: If you have an attribute prefix + * the name of the attribute will include the prefix. + * @param {ArraySpec} array Note: it is arguably inefficient to pass in anything but a typed array because anything + * else will have to be converted to a typed array before it can be used by WebGL. During init time that + * inefficiency is usually not important but if you're updating data dynamically best to be efficient. + * @param {number} [offset] an optional offset into the buffer. This is only an offset into the WebGL buffer + * not the array. To pass in an offset into the array itself use a typed array and create an `ArrayBufferView` + * for the portion of the array you want to use. + * + * var someArray = new Float32Array(1000); // an array with 1000 floats + * var someSubArray = new Float32Array(someArray.buffer, offsetInBytes, sizeInUnits); // a view into someArray + * + * Now you can pass `someSubArray` into setAttribInfoBufferFromArray` + * @memberOf module:twgl/attributes + */ +function setAttribInfoBufferFromArray(gl, attribInfo, array, offset) { + array = makeTypedArray(array); + if (offset !== undefined) { + gl.bindBuffer(ARRAY_BUFFER$1, attribInfo.buffer); + gl.bufferSubData(ARRAY_BUFFER$1, offset, array); + } else { + setBufferFromTypedArray(gl, ARRAY_BUFFER$1, attribInfo.buffer, array, attribInfo.drawType); + } +} + +function getBytesPerValueForGLType(gl, type) { + if (type === BYTE$1) return 1; // eslint-disable-line + if (type === UNSIGNED_BYTE$2) return 1; // eslint-disable-line + if (type === SHORT$1) return 2; // eslint-disable-line + if (type === UNSIGNED_SHORT$2) return 2; // eslint-disable-line + if (type === INT$2) return 4; // eslint-disable-line + if (type === UNSIGNED_INT$2) return 4; // eslint-disable-line + if (type === FLOAT$2) return 4; // eslint-disable-line + return 0; +} + +// Tries to get the number of elements from a set of arrays. +const positionKeys = ['position', 'positions', 'a_position']; +function getNumElementsFromNonIndexedArrays(arrays) { + let key; + let ii; + for (ii = 0; ii < positionKeys.length; ++ii) { + key = positionKeys[ii]; + if (key in arrays) { + break; + } + } + if (ii === positionKeys.length) { + key = Object.keys(arrays)[0]; + } + const array = arrays[key]; + const length = getArray$1(array).length; + if (length === undefined) { + return 1; // There's no arrays + } + const numComponents = getNumComponents$1(array, key); + const numElements = length / numComponents; + if (length % numComponents > 0) { + throw new Error(`numComponents ${numComponents} not correct for length ${length}`); + } + return numElements; +} + +function getNumElementsFromAttributes(gl, attribs) { + let key; + let ii; + for (ii = 0; ii < positionKeys.length; ++ii) { + key = positionKeys[ii]; + if (key in attribs) { + break; + } + key = defaults$2.attribPrefix + key; + if (key in attribs) { + break; + } + } + if (ii === positionKeys.length) { + key = Object.keys(attribs)[0]; + } + const attrib = attribs[key]; + if (!attrib.buffer) { + return 1; // There's no buffer + } + gl.bindBuffer(ARRAY_BUFFER$1, attrib.buffer); + const numBytes = gl.getBufferParameter(ARRAY_BUFFER$1, BUFFER_SIZE); + gl.bindBuffer(ARRAY_BUFFER$1, null); + + const bytesPerValue = getBytesPerValueForGLType(gl, attrib.type); + const totalElements = numBytes / bytesPerValue; + const numComponents = attrib.numComponents || attrib.size; + // TODO: check stride + const numElements = totalElements / numComponents; + if (numElements % 1 !== 0) { + throw new Error(`numComponents ${numComponents} not correct for length ${length}`); + } + return numElements; +} + +/** + * @typedef {Object} BufferInfo + * @property {number} numElements The number of elements to pass to `gl.drawArrays` or `gl.drawElements`. + * @property {number} [elementType] The type of indices `UNSIGNED_BYTE`, `UNSIGNED_SHORT` etc.. + * @property {WebGLBuffer} [indices] The indices `ELEMENT_ARRAY_BUFFER` if any indices exist. + * @property {Object.} [attribs] The attribs appropriate to call `setAttributes` + * @memberOf module:twgl + */ + +/** + * Creates a BufferInfo from an object of arrays. + * + * This can be passed to {@link module:twgl.setBuffersAndAttributes} and to + * {@link module:twgl:drawBufferInfo}. + * + * Given an object like + * + * var arrays = { + * position: { numComponents: 3, data: [0, 0, 0, 10, 0, 0, 0, 10, 0, 10, 10, 0], }, + * texcoord: { numComponents: 2, data: [0, 0, 0, 1, 1, 0, 1, 1], }, + * normal: { numComponents: 3, data: [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1], }, + * indices: { numComponents: 3, data: [0, 1, 2, 1, 2, 3], }, + * }; + * + * Creates an BufferInfo like this + * + * bufferInfo = { + * numElements: 4, // or whatever the number of elements is + * indices: WebGLBuffer, // this property will not exist if there are no indices + * attribs: { + * position: { buffer: WebGLBuffer, numComponents: 3, }, + * normal: { buffer: WebGLBuffer, numComponents: 3, }, + * texcoord: { buffer: WebGLBuffer, numComponents: 2, }, + * }, + * }; + * + * The properties of arrays can be JavaScript arrays in which case the number of components + * will be guessed. + * + * var arrays = { + * position: [0, 0, 0, 10, 0, 0, 0, 10, 0, 10, 10, 0], + * texcoord: [0, 0, 0, 1, 1, 0, 1, 1], + * normal: [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1], + * indices: [0, 1, 2, 1, 2, 3], + * }; + * + * They can also be TypedArrays + * + * var arrays = { + * position: new Float32Array([0, 0, 0, 10, 0, 0, 0, 10, 0, 10, 10, 0]), + * texcoord: new Float32Array([0, 0, 0, 1, 1, 0, 1, 1]), + * normal: new Float32Array([0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1]), + * indices: new Uint16Array([0, 1, 2, 1, 2, 3]), + * }; + * + * Or AugmentedTypedArrays + * + * var positions = createAugmentedTypedArray(3, 4); + * var texcoords = createAugmentedTypedArray(2, 4); + * var normals = createAugmentedTypedArray(3, 4); + * var indices = createAugmentedTypedArray(3, 2, Uint16Array); + * + * positions.push([0, 0, 0, 10, 0, 0, 0, 10, 0, 10, 10, 0]); + * texcoords.push([0, 0, 0, 1, 1, 0, 1, 1]); + * normals.push([0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1]); + * indices.push([0, 1, 2, 1, 2, 3]); + * + * var arrays = { + * position: positions, + * texcoord: texcoords, + * normal: normals, + * indices: indices, + * }; + * + * For the last example it is equivalent to + * + * var bufferInfo = { + * attribs: { + * position: { numComponents: 3, buffer: gl.createBuffer(), }, + * texcoord: { numComponents: 2, buffer: gl.createBuffer(), }, + * normal: { numComponents: 3, buffer: gl.createBuffer(), }, + * }, + * indices: gl.createBuffer(), + * numElements: 6, + * }; + * + * gl.bindBuffer(gl.ARRAY_BUFFER, bufferInfo.attribs.position.buffer); + * gl.bufferData(gl.ARRAY_BUFFER, arrays.position, gl.STATIC_DRAW); + * gl.bindBuffer(gl.ARRAY_BUFFER, bufferInfo.attribs.texcoord.buffer); + * gl.bufferData(gl.ARRAY_BUFFER, arrays.texcoord, gl.STATIC_DRAW); + * gl.bindBuffer(gl.ARRAY_BUFFER, bufferInfo.attribs.normal.buffer); + * gl.bufferData(gl.ARRAY_BUFFER, arrays.normal, gl.STATIC_DRAW); + * gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufferInfo.indices); + * gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, arrays.indices, gl.STATIC_DRAW); + * + * @param {WebGLRenderingContext} gl A WebGLRenderingContext + * @param {module:twgl.Arrays} arrays Your data + * @param {module:twgl.BufferInfo} [srcBufferInfo] An existing + * buffer info to start from. WebGLBuffers etc specified + * in the srcBufferInfo will be used in a new BufferInfo + * with any arrays specified overriding the ones in + * srcBufferInfo. + * @return {module:twgl.BufferInfo} A BufferInfo + * @memberOf module:twgl/attributes + */ +function createBufferInfoFromArrays(gl, arrays, srcBufferInfo) { + const newAttribs = createAttribsFromArrays(gl, arrays); + const bufferInfo = Object.assign({}, srcBufferInfo ? srcBufferInfo : {}); + bufferInfo.attribs = Object.assign({}, srcBufferInfo ? srcBufferInfo.attribs : {}, newAttribs); + const indices = arrays.indices; + if (indices) { + const newIndices = makeTypedArray(indices, "indices"); + bufferInfo.indices = createBufferFromTypedArray(gl, newIndices, ELEMENT_ARRAY_BUFFER$2); + bufferInfo.numElements = newIndices.length; + bufferInfo.elementType = getGLTypeForTypedArray(newIndices); + } else if (!bufferInfo.numElements) { + bufferInfo.numElements = getNumElementsFromAttributes(gl, bufferInfo.attribs); + } + + return bufferInfo; +} + +/** + * Creates a buffer from an array, typed array, or array spec + * + * Given something like this + * + * [1, 2, 3], + * + * or + * + * new Uint16Array([1,2,3]); + * + * or + * + * { + * data: [1, 2, 3], + * type: Uint8Array, + * } + * + * returns a WebGLBuffer that contains the given data. + * + * @param {WebGLRenderingContext} gl A WebGLRenderingContext. + * @param {module:twgl.ArraySpec} array an array, typed array, or array spec. + * @param {string} arrayName name of array. Used to guess the type if type can not be derived otherwise. + * @return {WebGLBuffer} a WebGLBuffer containing the data in array. + * @memberOf module:twgl/attributes + */ +function createBufferFromArray(gl, array, arrayName) { + const type = arrayName === "indices" ? ELEMENT_ARRAY_BUFFER$2 : ARRAY_BUFFER$1; + const typedArray = makeTypedArray(array, arrayName); + return createBufferFromTypedArray(gl, typedArray, type); +} + +/** + * Creates buffers from arrays or typed arrays + * + * Given something like this + * + * var arrays = { + * positions: [1, 2, 3], + * normals: [0, 0, 1], + * } + * + * returns something like + * + * buffers = { + * positions: WebGLBuffer, + * normals: WebGLBuffer, + * } + * + * If the buffer is named 'indices' it will be made an ELEMENT_ARRAY_BUFFER. + * + * @param {WebGLRenderingContext} gl A WebGLRenderingContext. + * @param {module:twgl.Arrays} arrays + * @return {Object} returns an object with one WebGLBuffer per array + * @memberOf module:twgl/attributes + */ +function createBuffersFromArrays(gl, arrays) { + const buffers = { }; + Object.keys(arrays).forEach(function(key) { + buffers[key] = createBufferFromArray(gl, arrays[key], key); + }); + + // Ugh! + if (arrays.indices) { + buffers.numElements = arrays.indices.length; + buffers.elementType = getGLTypeForTypedArray(makeTypedArray(arrays.indices)); + } else { + buffers.numElements = getNumElementsFromNonIndexedArrays(arrays); + } + + return buffers; +} + +var attributes = /*#__PURE__*/Object.freeze({ + __proto__: null, + createAttribsFromArrays: createAttribsFromArrays, + createBuffersFromArrays: createBuffersFromArrays, + createBufferFromArray: createBufferFromArray, + createBufferFromTypedArray: createBufferFromTypedArray, + createBufferInfoFromArrays: createBufferInfoFromArrays, + setAttribInfoBufferFromArray: setAttribInfoBufferFromArray, + setAttributePrefix: setAttributePrefix, + setAttributeDefaults_: setDefaults$2, + getNumComponents_: getNumComponents$1, + getArray_: getArray$1 +}); + +/* + * Copyright 2019 Gregg Tavares + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +const getArray = getArray$1; // eslint-disable-line +const getNumComponents = getNumComponents$1; // eslint-disable-line + +/** + * @typedef {(Int8Array|Uint8Array|Int16Array|Uint16Array|Int32Array|Uint32Array|Float32Array)} TypedArray + */ + +/** + * Add `push` to a typed array. It just keeps a 'cursor' + * and allows use to `push` values into the array so we + * don't have to manually compute offsets + * @param {TypedArray} typedArray TypedArray to augment + * @param {number} numComponents number of components. + * @private + */ +function augmentTypedArray(typedArray, numComponents) { + let cursor = 0; + typedArray.push = function() { + for (let ii = 0; ii < arguments.length; ++ii) { + const value = arguments[ii]; + if (value instanceof Array || isArrayBuffer$1(value)) { + for (let jj = 0; jj < value.length; ++jj) { + typedArray[cursor++] = value[jj]; + } + } else { + typedArray[cursor++] = value; + } + } + }; + typedArray.reset = function(opt_index) { + cursor = opt_index || 0; + }; + typedArray.numComponents = numComponents; + Object.defineProperty(typedArray, 'numElements', { + get: function() { + return this.length / this.numComponents | 0; + }, + }); + return typedArray; +} + +/** + * creates a typed array with a `push` function attached + * so that you can easily *push* values. + * + * `push` can take multiple arguments. If an argument is an array each element + * of the array will be added to the typed array. + * + * Example: + * + * const array = createAugmentedTypedArray(3, 2); // creates a Float32Array with 6 values + * array.push(1, 2, 3); + * array.push([4, 5, 6]); + * // array now contains [1, 2, 3, 4, 5, 6] + * + * Also has `numComponents` and `numElements` properties. + * + * @param {number} numComponents number of components + * @param {number} numElements number of elements. The total size of the array will be `numComponents * numElements`. + * @param {constructor} opt_type A constructor for the type. Default = `Float32Array`. + * @return {ArrayBufferView} A typed array. + * @memberOf module:twgl/primitives + */ +function createAugmentedTypedArray(numComponents, numElements, opt_type) { + const Type = opt_type || Float32Array; + return augmentTypedArray(new Type(numComponents * numElements), numComponents); +} + +function allButIndices(name) { + return name !== "indices"; +} + +/** + * Given indexed vertices creates a new set of vertices un-indexed by expanding the indexed vertices. + * @param {Object.} vertices The indexed vertices to deindex + * @return {Object.} The deindexed vertices + * @memberOf module:twgl/primitives + */ +function deindexVertices(vertices) { + const indices = vertices.indices; + const newVertices = {}; + const numElements = indices.length; + + function expandToUnindexed(channel) { + const srcBuffer = vertices[channel]; + const numComponents = srcBuffer.numComponents; + const dstBuffer = createAugmentedTypedArray(numComponents, numElements, srcBuffer.constructor); + for (let ii = 0; ii < numElements; ++ii) { + const ndx = indices[ii]; + const offset = ndx * numComponents; + for (let jj = 0; jj < numComponents; ++jj) { + dstBuffer.push(srcBuffer[offset + jj]); + } + } + newVertices[channel] = dstBuffer; + } + + Object.keys(vertices).filter(allButIndices).forEach(expandToUnindexed); + + return newVertices; +} + +/** + * flattens the normals of deindexed vertices in place. + * @param {Object.} vertices The deindexed vertices who's normals to flatten + * @return {Object.} The flattened vertices (same as was passed in) + * @memberOf module:twgl/primitives + */ +function flattenNormals(vertices) { + if (vertices.indices) { + throw new Error('can not flatten normals of indexed vertices. deindex them first'); + } + + const normals = vertices.normal; + const numNormals = normals.length; + for (let ii = 0; ii < numNormals; ii += 9) { + // pull out the 3 normals for this triangle + const nax = normals[ii + 0]; + const nay = normals[ii + 1]; + const naz = normals[ii + 2]; + + const nbx = normals[ii + 3]; + const nby = normals[ii + 4]; + const nbz = normals[ii + 5]; + + const ncx = normals[ii + 6]; + const ncy = normals[ii + 7]; + const ncz = normals[ii + 8]; + + // add them + let nx = nax + nbx + ncx; + let ny = nay + nby + ncy; + let nz = naz + nbz + ncz; + + // normalize them + const length = Math.sqrt(nx * nx + ny * ny + nz * nz); + + nx /= length; + ny /= length; + nz /= length; + + // copy them back in + normals[ii + 0] = nx; + normals[ii + 1] = ny; + normals[ii + 2] = nz; + + normals[ii + 3] = nx; + normals[ii + 4] = ny; + normals[ii + 5] = nz; + + normals[ii + 6] = nx; + normals[ii + 7] = ny; + normals[ii + 8] = nz; + } + + return vertices; +} + +function applyFuncToV3Array(array, matrix, fn) { + const len = array.length; + const tmp = new Float32Array(3); + for (let ii = 0; ii < len; ii += 3) { + fn(matrix, [array[ii], array[ii + 1], array[ii + 2]], tmp); + array[ii ] = tmp[0]; + array[ii + 1] = tmp[1]; + array[ii + 2] = tmp[2]; + } +} + +function transformNormal(mi, v, dst) { + dst = dst || create$1(); + const v0 = v[0]; + const v1 = v[1]; + const v2 = v[2]; + + dst[0] = v0 * mi[0 * 4 + 0] + v1 * mi[0 * 4 + 1] + v2 * mi[0 * 4 + 2]; + dst[1] = v0 * mi[1 * 4 + 0] + v1 * mi[1 * 4 + 1] + v2 * mi[1 * 4 + 2]; + dst[2] = v0 * mi[2 * 4 + 0] + v1 * mi[2 * 4 + 1] + v2 * mi[2 * 4 + 2]; + + return dst; +} + +/** + * Reorients directions by the given matrix.. + * @param {(number[]|TypedArray)} array The array. Assumes value floats per element. + * @param {module:twgl/m4.Mat4} matrix A matrix to multiply by. + * @return {(number[]|TypedArray)} the same array that was passed in + * @memberOf module:twgl/primitives + */ +function reorientDirections(array, matrix) { + applyFuncToV3Array(array, matrix, transformDirection); + return array; +} + +/** + * Reorients normals by the inverse-transpose of the given + * matrix.. + * @param {(number[]|TypedArray)} array The array. Assumes value floats per element. + * @param {module:twgl/m4.Mat4} matrix A matrix to multiply by. + * @return {(number[]|TypedArray)} the same array that was passed in + * @memberOf module:twgl/primitives + */ +function reorientNormals(array, matrix) { + applyFuncToV3Array(array, inverse(matrix), transformNormal); + return array; +} + +/** + * Reorients positions by the given matrix. In other words, it + * multiplies each vertex by the given matrix. + * @param {(number[]|TypedArray)} array The array. Assumes value floats per element. + * @param {module:twgl/m4.Mat4} matrix A matrix to multiply by. + * @return {(number[]|TypedArray)} the same array that was passed in + * @memberOf module:twgl/primitives + */ +function reorientPositions(array, matrix) { + applyFuncToV3Array(array, matrix, transformPoint); + return array; +} + +/** + * @typedef {(number[]|TypedArray)} NativeArrayOrTypedArray + */ + +/** + * Reorients arrays by the given matrix. Assumes arrays have + * names that contains 'pos' could be reoriented as positions, + * 'binorm' or 'tan' as directions, and 'norm' as normals. + * + * @param {Object.} arrays The vertices to reorient + * @param {module:twgl/m4.Mat4} matrix matrix to reorient by. + * @return {Object.} same arrays that were passed in. + * @memberOf module:twgl/primitives + */ +function reorientVertices(arrays, matrix) { + Object.keys(arrays).forEach(function(name) { + const array = arrays[name]; + if (name.indexOf("pos") >= 0) { + reorientPositions(array, matrix); + } else if (name.indexOf("tan") >= 0 || name.indexOf("binorm") >= 0) { + reorientDirections(array, matrix); + } else if (name.indexOf("norm") >= 0) { + reorientNormals(array, matrix); + } + }); + return arrays; +} + +/** + * Creates XY quad BufferInfo + * + * The default with no parameters will return a 2x2 quad with values from -1 to +1. + * If you want a unit quad with that goes from 0 to 1 you'd call it with + * + * twgl.primitives.createXYQuadBufferInfo(gl, 1, 0.5, 0.5); + * + * If you want a unit quad centered above 0,0 you'd call it with + * + * twgl.primitives.createXYQuadBufferInfo(gl, 1, 0, 0.5); + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext. + * @param {number} [size] the size across the quad. Defaults to 2 which means vertices will go from -1 to +1 + * @param {number} [xOffset] the amount to offset the quad in X + * @param {number} [yOffset] the amount to offset the quad in Y + * @return {Object.} the created XY Quad BufferInfo + * @memberOf module:twgl/primitives + * @function createXYQuadBuffers + */ + +/** + * Creates XY quad Buffers + * + * The default with no parameters will return a 2x2 quad with values from -1 to +1. + * If you want a unit quad with that goes from 0 to 1 you'd call it with + * + * twgl.primitives.createXYQuadBufferInfo(gl, 1, 0.5, 0.5); + * + * If you want a unit quad centered above 0,0 you'd call it with + * + * twgl.primitives.createXYQuadBufferInfo(gl, 1, 0, 0.5); + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext. + * @param {number} [size] the size across the quad. Defaults to 2 which means vertices will go from -1 to +1 + * @param {number} [xOffset] the amount to offset the quad in X + * @param {number} [yOffset] the amount to offset the quad in Y + * @return {module:twgl.BufferInfo} the created XY Quad buffers + * @memberOf module:twgl/primitives + * @function createXYQuadBufferInfo + */ + +/** + * Creates XY quad vertices + * + * The default with no parameters will return a 2x2 quad with values from -1 to +1. + * If you want a unit quad with that goes from 0 to 1 you'd call it with + * + * twgl.primitives.createXYQuadVertices(1, 0.5, 0.5); + * + * If you want a unit quad centered above 0,0 you'd call it with + * + * twgl.primitives.createXYQuadVertices(1, 0, 0.5); + * + * @param {number} [size] the size across the quad. Defaults to 2 which means vertices will go from -1 to +1 + * @param {number} [xOffset] the amount to offset the quad in X + * @param {number} [yOffset] the amount to offset the quad in Y + * @return {Object.} the created XY Quad vertices + * @memberOf module:twgl/primitives + */ +function createXYQuadVertices(size, xOffset, yOffset) { + size = size || 2; + xOffset = xOffset || 0; + yOffset = yOffset || 0; + size *= 0.5; + return { + position: { + numComponents: 2, + data: [ + xOffset + -1 * size, yOffset + -1 * size, + xOffset + 1 * size, yOffset + -1 * size, + xOffset + -1 * size, yOffset + 1 * size, + xOffset + 1 * size, yOffset + 1 * size, + ], + }, + normal: [ + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + ], + texcoord: [ + 0, 0, + 1, 0, + 0, 1, + 1, 1, + ], + indices: [ 0, 1, 2, 2, 1, 3 ], + }; +} + +/** + * Creates XZ plane BufferInfo. + * + * The created plane has position, normal, and texcoord data + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext. + * @param {number} [width] Width of the plane. Default = 1 + * @param {number} [depth] Depth of the plane. Default = 1 + * @param {number} [subdivisionsWidth] Number of steps across the plane. Default = 1 + * @param {number} [subdivisionsDepth] Number of steps down the plane. Default = 1 + * @param {module:twgl/m4.Mat4} [matrix] A matrix by which to multiply all the vertices. + * @return {module:twgl.BufferInfo} The created plane BufferInfo. + * @memberOf module:twgl/primitives + * @function createPlaneBufferInfo + */ + +/** + * Creates XZ plane buffers. + * + * The created plane has position, normal, and texcoord data + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext. + * @param {number} [width] Width of the plane. Default = 1 + * @param {number} [depth] Depth of the plane. Default = 1 + * @param {number} [subdivisionsWidth] Number of steps across the plane. Default = 1 + * @param {number} [subdivisionsDepth] Number of steps down the plane. Default = 1 + * @param {module:twgl/m4.Mat4} [matrix] A matrix by which to multiply all the vertices. + * @return {Object.} The created plane buffers. + * @memberOf module:twgl/primitives + * @function createPlaneBuffers + */ + +/** + * Creates XZ plane vertices. + * + * The created plane has position, normal, and texcoord data + * + * @param {number} [width] Width of the plane. Default = 1 + * @param {number} [depth] Depth of the plane. Default = 1 + * @param {number} [subdivisionsWidth] Number of steps across the plane. Default = 1 + * @param {number} [subdivisionsDepth] Number of steps down the plane. Default = 1 + * @param {module:twgl/m4.Mat4} [matrix] A matrix by which to multiply all the vertices. + * @return {Object.} The created plane vertices. + * @memberOf module:twgl/primitives + */ +function createPlaneVertices( + width, + depth, + subdivisionsWidth, + subdivisionsDepth, + matrix) { + width = width || 1; + depth = depth || 1; + subdivisionsWidth = subdivisionsWidth || 1; + subdivisionsDepth = subdivisionsDepth || 1; + matrix = matrix || identity(); + + const numVertices = (subdivisionsWidth + 1) * (subdivisionsDepth + 1); + const positions = createAugmentedTypedArray(3, numVertices); + const normals = createAugmentedTypedArray(3, numVertices); + const texcoords = createAugmentedTypedArray(2, numVertices); + + for (let z = 0; z <= subdivisionsDepth; z++) { + for (let x = 0; x <= subdivisionsWidth; x++) { + const u = x / subdivisionsWidth; + const v = z / subdivisionsDepth; + positions.push( + width * u - width * 0.5, + 0, + depth * v - depth * 0.5); + normals.push(0, 1, 0); + texcoords.push(u, v); + } + } + + const numVertsAcross = subdivisionsWidth + 1; + const indices = createAugmentedTypedArray( + 3, subdivisionsWidth * subdivisionsDepth * 2, Uint16Array); + + for (let z = 0; z < subdivisionsDepth; z++) { // eslint-disable-line + for (let x = 0; x < subdivisionsWidth; x++) { // eslint-disable-line + // Make triangle 1 of quad. + indices.push( + (z + 0) * numVertsAcross + x, + (z + 1) * numVertsAcross + x, + (z + 0) * numVertsAcross + x + 1); + + // Make triangle 2 of quad. + indices.push( + (z + 1) * numVertsAcross + x, + (z + 1) * numVertsAcross + x + 1, + (z + 0) * numVertsAcross + x + 1); + } + } + + const arrays = reorientVertices({ + position: positions, + normal: normals, + texcoord: texcoords, + indices: indices, + }, matrix); + return arrays; +} + +/** + * Creates sphere BufferInfo. + * + * The created sphere has position, normal, and texcoord data + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext. + * @param {number} radius radius of the sphere. + * @param {number} subdivisionsAxis number of steps around the sphere. + * @param {number} subdivisionsHeight number of vertically on the sphere. + * @param {number} [opt_startLatitudeInRadians] where to start the + * top of the sphere. Default = 0. + * @param {number} [opt_endLatitudeInRadians] Where to end the + * bottom of the sphere. Default = Math.PI. + * @param {number} [opt_startLongitudeInRadians] where to start + * wrapping the sphere. Default = 0. + * @param {number} [opt_endLongitudeInRadians] where to end + * wrapping the sphere. Default = 2 * Math.PI. + * @return {module:twgl.BufferInfo} The created sphere BufferInfo. + * @memberOf module:twgl/primitives + * @function createSphereBufferInfo + */ + +/** + * Creates sphere buffers. + * + * The created sphere has position, normal, and texcoord data + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext. + * @param {number} radius radius of the sphere. + * @param {number} subdivisionsAxis number of steps around the sphere. + * @param {number} subdivisionsHeight number of vertically on the sphere. + * @param {number} [opt_startLatitudeInRadians] where to start the + * top of the sphere. Default = 0. + * @param {number} [opt_endLatitudeInRadians] Where to end the + * bottom of the sphere. Default = Math.PI. + * @param {number} [opt_startLongitudeInRadians] where to start + * wrapping the sphere. Default = 0. + * @param {number} [opt_endLongitudeInRadians] where to end + * wrapping the sphere. Default = 2 * Math.PI. + * @return {Object.} The created sphere buffers. + * @memberOf module:twgl/primitives + * @function createSphereBuffers + */ + +/** + * Creates sphere vertices. + * + * The created sphere has position, normal, and texcoord data + * + * @param {number} radius radius of the sphere. + * @param {number} subdivisionsAxis number of steps around the sphere. + * @param {number} subdivisionsHeight number of vertically on the sphere. + * @param {number} [opt_startLatitudeInRadians] where to start the + * top of the sphere. Default = 0. + * @param {number} [opt_endLatitudeInRadians] Where to end the + * bottom of the sphere. Default = Math.PI. + * @param {number} [opt_startLongitudeInRadians] where to start + * wrapping the sphere. Default = 0. + * @param {number} [opt_endLongitudeInRadians] where to end + * wrapping the sphere. Default = 2 * Math.PI. + * @return {Object.} The created sphere vertices. + * @memberOf module:twgl/primitives + */ +function createSphereVertices( + radius, + subdivisionsAxis, + subdivisionsHeight, + opt_startLatitudeInRadians, + opt_endLatitudeInRadians, + opt_startLongitudeInRadians, + opt_endLongitudeInRadians) { + if (subdivisionsAxis <= 0 || subdivisionsHeight <= 0) { + throw new Error('subdivisionAxis and subdivisionHeight must be > 0'); + } + + opt_startLatitudeInRadians = opt_startLatitudeInRadians || 0; + opt_endLatitudeInRadians = opt_endLatitudeInRadians || Math.PI; + opt_startLongitudeInRadians = opt_startLongitudeInRadians || 0; + opt_endLongitudeInRadians = opt_endLongitudeInRadians || (Math.PI * 2); + + const latRange = opt_endLatitudeInRadians - opt_startLatitudeInRadians; + const longRange = opt_endLongitudeInRadians - opt_startLongitudeInRadians; + + // We are going to generate our sphere by iterating through its + // spherical coordinates and generating 2 triangles for each quad on a + // ring of the sphere. + const numVertices = (subdivisionsAxis + 1) * (subdivisionsHeight + 1); + const positions = createAugmentedTypedArray(3, numVertices); + const normals = createAugmentedTypedArray(3, numVertices); + const texcoords = createAugmentedTypedArray(2, numVertices); + + // Generate the individual vertices in our vertex buffer. + for (let y = 0; y <= subdivisionsHeight; y++) { + for (let x = 0; x <= subdivisionsAxis; x++) { + // Generate a vertex based on its spherical coordinates + const u = x / subdivisionsAxis; + const v = y / subdivisionsHeight; + const theta = longRange * u + opt_startLongitudeInRadians; + const phi = latRange * v + opt_startLatitudeInRadians; + const sinTheta = Math.sin(theta); + const cosTheta = Math.cos(theta); + const sinPhi = Math.sin(phi); + const cosPhi = Math.cos(phi); + const ux = cosTheta * sinPhi; + const uy = cosPhi; + const uz = sinTheta * sinPhi; + positions.push(radius * ux, radius * uy, radius * uz); + normals.push(ux, uy, uz); + texcoords.push(1 - u, v); + } + } + + const numVertsAround = subdivisionsAxis + 1; + const indices = createAugmentedTypedArray(3, subdivisionsAxis * subdivisionsHeight * 2, Uint16Array); + for (let x = 0; x < subdivisionsAxis; x++) { // eslint-disable-line + for (let y = 0; y < subdivisionsHeight; y++) { // eslint-disable-line + // Make triangle 1 of quad. + indices.push( + (y + 0) * numVertsAround + x, + (y + 0) * numVertsAround + x + 1, + (y + 1) * numVertsAround + x); + + // Make triangle 2 of quad. + indices.push( + (y + 1) * numVertsAround + x, + (y + 0) * numVertsAround + x + 1, + (y + 1) * numVertsAround + x + 1); + } + } + + return { + position: positions, + normal: normals, + texcoord: texcoords, + indices: indices, + }; +} + +/** + * Array of the indices of corners of each face of a cube. + * @type {Array.} + * @private + */ +const CUBE_FACE_INDICES = [ + [3, 7, 5, 1], // right + [6, 2, 0, 4], // left + [6, 7, 3, 2], // ?? + [0, 1, 5, 4], // ?? + [7, 6, 4, 5], // front + [2, 3, 1, 0], // back +]; + +/** + * Creates a BufferInfo for a cube. + * + * The cube is created around the origin. (-size / 2, size / 2). + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext. + * @param {number} [size] width, height and depth of the cube. + * @return {module:twgl.BufferInfo} The created BufferInfo. + * @memberOf module:twgl/primitives + * @function createCubeBufferInfo + */ + +/** + * Creates the buffers and indices for a cube. + * + * The cube is created around the origin. (-size / 2, size / 2). + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext. + * @param {number} [size] width, height and depth of the cube. + * @return {Object.} The created buffers. + * @memberOf module:twgl/primitives + * @function createCubeBuffers + */ + +/** + * Creates the vertices and indices for a cube. + * + * The cube is created around the origin. (-size / 2, size / 2). + * + * @param {number} [size] width, height and depth of the cube. + * @return {Object.} The created vertices. + * @memberOf module:twgl/primitives + */ +function createCubeVertices(size) { + size = size || 1; + const k = size / 2; + + const cornerVertices = [ + [-k, -k, -k], + [+k, -k, -k], + [-k, +k, -k], + [+k, +k, -k], + [-k, -k, +k], + [+k, -k, +k], + [-k, +k, +k], + [+k, +k, +k], + ]; + + const faceNormals = [ + [+1, +0, +0], + [-1, +0, +0], + [+0, +1, +0], + [+0, -1, +0], + [+0, +0, +1], + [+0, +0, -1], + ]; + + const uvCoords = [ + [1, 0], + [0, 0], + [0, 1], + [1, 1], + ]; + + const numVertices = 6 * 4; + const positions = createAugmentedTypedArray(3, numVertices); + const normals = createAugmentedTypedArray(3, numVertices); + const texcoords = createAugmentedTypedArray(2 , numVertices); + const indices = createAugmentedTypedArray(3, 6 * 2, Uint16Array); + + for (let f = 0; f < 6; ++f) { + const faceIndices = CUBE_FACE_INDICES[f]; + for (let v = 0; v < 4; ++v) { + const position = cornerVertices[faceIndices[v]]; + const normal = faceNormals[f]; + const uv = uvCoords[v]; + + // Each face needs all four vertices because the normals and texture + // coordinates are not all the same. + positions.push(position); + normals.push(normal); + texcoords.push(uv); + + } + // Two triangles make a square face. + const offset = 4 * f; + indices.push(offset + 0, offset + 1, offset + 2); + indices.push(offset + 0, offset + 2, offset + 3); + } + + return { + position: positions, + normal: normals, + texcoord: texcoords, + indices: indices, + }; +} + +/** + * Creates a BufferInfo for a truncated cone, which is like a cylinder + * except that it has different top and bottom radii. A truncated cone + * can also be used to create cylinders and regular cones. The + * truncated cone will be created centered about the origin, with the + * y axis as its vertical axis. + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext. + * @param {number} bottomRadius Bottom radius of truncated cone. + * @param {number} topRadius Top radius of truncated cone. + * @param {number} height Height of truncated cone. + * @param {number} radialSubdivisions The number of subdivisions around the + * truncated cone. + * @param {number} verticalSubdivisions The number of subdivisions down the + * truncated cone. + * @param {boolean} [opt_topCap] Create top cap. Default = true. + * @param {boolean} [opt_bottomCap] Create bottom cap. Default = true. + * @return {module:twgl.BufferInfo} The created cone BufferInfo. + * @memberOf module:twgl/primitives + * @function createTruncatedConeBufferInfo + */ + +/** + * Creates buffers for a truncated cone, which is like a cylinder + * except that it has different top and bottom radii. A truncated cone + * can also be used to create cylinders and regular cones. The + * truncated cone will be created centered about the origin, with the + * y axis as its vertical axis. + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext. + * @param {number} bottomRadius Bottom radius of truncated cone. + * @param {number} topRadius Top radius of truncated cone. + * @param {number} height Height of truncated cone. + * @param {number} radialSubdivisions The number of subdivisions around the + * truncated cone. + * @param {number} verticalSubdivisions The number of subdivisions down the + * truncated cone. + * @param {boolean} [opt_topCap] Create top cap. Default = true. + * @param {boolean} [opt_bottomCap] Create bottom cap. Default = true. + * @return {Object.} The created cone buffers. + * @memberOf module:twgl/primitives + * @function createTruncatedConeBuffers + */ + +/** + * Creates vertices for a truncated cone, which is like a cylinder + * except that it has different top and bottom radii. A truncated cone + * can also be used to create cylinders and regular cones. The + * truncated cone will be created centered about the origin, with the + * y axis as its vertical axis. . + * + * @param {number} bottomRadius Bottom radius of truncated cone. + * @param {number} topRadius Top radius of truncated cone. + * @param {number} height Height of truncated cone. + * @param {number} radialSubdivisions The number of subdivisions around the + * truncated cone. + * @param {number} verticalSubdivisions The number of subdivisions down the + * truncated cone. + * @param {boolean} [opt_topCap] Create top cap. Default = true. + * @param {boolean} [opt_bottomCap] Create bottom cap. Default = true. + * @return {Object.} The created cone vertices. + * @memberOf module:twgl/primitives + */ +function createTruncatedConeVertices( + bottomRadius, + topRadius, + height, + radialSubdivisions, + verticalSubdivisions, + opt_topCap, + opt_bottomCap) { + if (radialSubdivisions < 3) { + throw new Error('radialSubdivisions must be 3 or greater'); + } + + if (verticalSubdivisions < 1) { + throw new Error('verticalSubdivisions must be 1 or greater'); + } + + const topCap = (opt_topCap === undefined) ? true : opt_topCap; + const bottomCap = (opt_bottomCap === undefined) ? true : opt_bottomCap; + + const extra = (topCap ? 2 : 0) + (bottomCap ? 2 : 0); + + const numVertices = (radialSubdivisions + 1) * (verticalSubdivisions + 1 + extra); + const positions = createAugmentedTypedArray(3, numVertices); + const normals = createAugmentedTypedArray(3, numVertices); + const texcoords = createAugmentedTypedArray(2, numVertices); + const indices = createAugmentedTypedArray(3, radialSubdivisions * (verticalSubdivisions + extra / 2) * 2, Uint16Array); + + const vertsAroundEdge = radialSubdivisions + 1; + + // The slant of the cone is constant across its surface + const slant = Math.atan2(bottomRadius - topRadius, height); + const cosSlant = Math.cos(slant); + const sinSlant = Math.sin(slant); + + const start = topCap ? -2 : 0; + const end = verticalSubdivisions + (bottomCap ? 2 : 0); + + for (let yy = start; yy <= end; ++yy) { + let v = yy / verticalSubdivisions; + let y = height * v; + let ringRadius; + if (yy < 0) { + y = 0; + v = 1; + ringRadius = bottomRadius; + } else if (yy > verticalSubdivisions) { + y = height; + v = 1; + ringRadius = topRadius; + } else { + ringRadius = bottomRadius + + (topRadius - bottomRadius) * (yy / verticalSubdivisions); + } + if (yy === -2 || yy === verticalSubdivisions + 2) { + ringRadius = 0; + v = 0; + } + y -= height / 2; + for (let ii = 0; ii < vertsAroundEdge; ++ii) { + const sin = Math.sin(ii * Math.PI * 2 / radialSubdivisions); + const cos = Math.cos(ii * Math.PI * 2 / radialSubdivisions); + positions.push(sin * ringRadius, y, cos * ringRadius); + if (yy < 0) { + normals.push(0, -1, 0); + } else if (yy > verticalSubdivisions) { + normals.push(0, 1, 0); + } else if (ringRadius === 0.0) { + normals.push(0, 0, 0); + } else { + normals.push(sin * cosSlant, sinSlant, cos * cosSlant); + } + texcoords.push((ii / radialSubdivisions), 1 - v); + } + } + + for (let yy = 0; yy < verticalSubdivisions + extra; ++yy) { // eslint-disable-line + if (yy === 1 && topCap || yy === verticalSubdivisions + extra - 2 && bottomCap) { + continue; + } + for (let ii = 0; ii < radialSubdivisions; ++ii) { // eslint-disable-line + indices.push(vertsAroundEdge * (yy + 0) + 0 + ii, + vertsAroundEdge * (yy + 0) + 1 + ii, + vertsAroundEdge * (yy + 1) + 1 + ii); + indices.push(vertsAroundEdge * (yy + 0) + 0 + ii, + vertsAroundEdge * (yy + 1) + 1 + ii, + vertsAroundEdge * (yy + 1) + 0 + ii); + } + } + + return { + position: positions, + normal: normals, + texcoord: texcoords, + indices: indices, + }; +} + +/** + * Expands RLE data + * @param {number[]} rleData data in format of run-length, x, y, z, run-length, x, y, z + * @param {number[]} [padding] value to add each entry with. + * @return {number[]} the expanded rleData + * @private + */ +function expandRLEData(rleData, padding) { + padding = padding || []; + const data = []; + for (let ii = 0; ii < rleData.length; ii += 4) { + const runLength = rleData[ii]; + const element = rleData.slice(ii + 1, ii + 4); + element.push.apply(element, padding); + for (let jj = 0; jj < runLength; ++jj) { + data.push.apply(data, element); + } + } + return data; +} + +/** + * Creates 3D 'F' BufferInfo. + * An 'F' is useful because you can easily tell which way it is oriented. + * The created 'F' has position, normal, texcoord, and color buffers. + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext. + * @return {module:twgl.BufferInfo} The created BufferInfo. + * @memberOf module:twgl/primitives + * @function create3DFBufferInfo + */ + +/** + * Creates 3D 'F' buffers. + * An 'F' is useful because you can easily tell which way it is oriented. + * The created 'F' has position, normal, texcoord, and color buffers. + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext. + * @return {Object.} The created buffers. + * @memberOf module:twgl/primitives + * @function create3DFBuffers + */ + +/** + * Creates 3D 'F' vertices. + * An 'F' is useful because you can easily tell which way it is oriented. + * The created 'F' has position, normal, texcoord, and color arrays. + * + * @return {Object.} The created vertices. + * @memberOf module:twgl/primitives + */ +function create3DFVertices() { + + const positions = [ + // left column front + 0, 0, 0, + 0, 150, 0, + 30, 0, 0, + 0, 150, 0, + 30, 150, 0, + 30, 0, 0, + + // top rung front + 30, 0, 0, + 30, 30, 0, + 100, 0, 0, + 30, 30, 0, + 100, 30, 0, + 100, 0, 0, + + // middle rung front + 30, 60, 0, + 30, 90, 0, + 67, 60, 0, + 30, 90, 0, + 67, 90, 0, + 67, 60, 0, + + // left column back + 0, 0, 30, + 30, 0, 30, + 0, 150, 30, + 0, 150, 30, + 30, 0, 30, + 30, 150, 30, + + // top rung back + 30, 0, 30, + 100, 0, 30, + 30, 30, 30, + 30, 30, 30, + 100, 0, 30, + 100, 30, 30, + + // middle rung back + 30, 60, 30, + 67, 60, 30, + 30, 90, 30, + 30, 90, 30, + 67, 60, 30, + 67, 90, 30, + + // top + 0, 0, 0, + 100, 0, 0, + 100, 0, 30, + 0, 0, 0, + 100, 0, 30, + 0, 0, 30, + + // top rung front + 100, 0, 0, + 100, 30, 0, + 100, 30, 30, + 100, 0, 0, + 100, 30, 30, + 100, 0, 30, + + // under top rung + 30, 30, 0, + 30, 30, 30, + 100, 30, 30, + 30, 30, 0, + 100, 30, 30, + 100, 30, 0, + + // between top rung and middle + 30, 30, 0, + 30, 60, 30, + 30, 30, 30, + 30, 30, 0, + 30, 60, 0, + 30, 60, 30, + + // top of middle rung + 30, 60, 0, + 67, 60, 30, + 30, 60, 30, + 30, 60, 0, + 67, 60, 0, + 67, 60, 30, + + // front of middle rung + 67, 60, 0, + 67, 90, 30, + 67, 60, 30, + 67, 60, 0, + 67, 90, 0, + 67, 90, 30, + + // bottom of middle rung. + 30, 90, 0, + 30, 90, 30, + 67, 90, 30, + 30, 90, 0, + 67, 90, 30, + 67, 90, 0, + + // front of bottom + 30, 90, 0, + 30, 150, 30, + 30, 90, 30, + 30, 90, 0, + 30, 150, 0, + 30, 150, 30, + + // bottom + 0, 150, 0, + 0, 150, 30, + 30, 150, 30, + 0, 150, 0, + 30, 150, 30, + 30, 150, 0, + + // left side + 0, 0, 0, + 0, 0, 30, + 0, 150, 30, + 0, 0, 0, + 0, 150, 30, + 0, 150, 0, + ]; + + const texcoords = [ + // left column front + 0.22, 0.19, + 0.22, 0.79, + 0.34, 0.19, + 0.22, 0.79, + 0.34, 0.79, + 0.34, 0.19, + + // top rung front + 0.34, 0.19, + 0.34, 0.31, + 0.62, 0.19, + 0.34, 0.31, + 0.62, 0.31, + 0.62, 0.19, + + // middle rung front + 0.34, 0.43, + 0.34, 0.55, + 0.49, 0.43, + 0.34, 0.55, + 0.49, 0.55, + 0.49, 0.43, + + // left column back + 0, 0, + 1, 0, + 0, 1, + 0, 1, + 1, 0, + 1, 1, + + // top rung back + 0, 0, + 1, 0, + 0, 1, + 0, 1, + 1, 0, + 1, 1, + + // middle rung back + 0, 0, + 1, 0, + 0, 1, + 0, 1, + 1, 0, + 1, 1, + + // top + 0, 0, + 1, 0, + 1, 1, + 0, 0, + 1, 1, + 0, 1, + + // top rung front + 0, 0, + 1, 0, + 1, 1, + 0, 0, + 1, 1, + 0, 1, + + // under top rung + 0, 0, + 0, 1, + 1, 1, + 0, 0, + 1, 1, + 1, 0, + + // between top rung and middle + 0, 0, + 1, 1, + 0, 1, + 0, 0, + 1, 0, + 1, 1, + + // top of middle rung + 0, 0, + 1, 1, + 0, 1, + 0, 0, + 1, 0, + 1, 1, + + // front of middle rung + 0, 0, + 1, 1, + 0, 1, + 0, 0, + 1, 0, + 1, 1, + + // bottom of middle rung. + 0, 0, + 0, 1, + 1, 1, + 0, 0, + 1, 1, + 1, 0, + + // front of bottom + 0, 0, + 1, 1, + 0, 1, + 0, 0, + 1, 0, + 1, 1, + + // bottom + 0, 0, + 0, 1, + 1, 1, + 0, 0, + 1, 1, + 1, 0, + + // left side + 0, 0, + 0, 1, + 1, 1, + 0, 0, + 1, 1, + 1, 0, + ]; + + const normals = expandRLEData([ + // left column front + // top rung front + // middle rung front + 18, 0, 0, 1, + + // left column back + // top rung back + // middle rung back + 18, 0, 0, -1, + + // top + 6, 0, 1, 0, + + // top rung front + 6, 1, 0, 0, + + // under top rung + 6, 0, -1, 0, + + // between top rung and middle + 6, 1, 0, 0, + + // top of middle rung + 6, 0, 1, 0, + + // front of middle rung + 6, 1, 0, 0, + + // bottom of middle rung. + 6, 0, -1, 0, + + // front of bottom + 6, 1, 0, 0, + + // bottom + 6, 0, -1, 0, + + // left side + 6, -1, 0, 0, + ]); + + const colors = expandRLEData([ + // left column front + // top rung front + // middle rung front + 18, 200, 70, 120, + + // left column back + // top rung back + // middle rung back + 18, 80, 70, 200, + + // top + 6, 70, 200, 210, + + // top rung front + 6, 200, 200, 70, + + // under top rung + 6, 210, 100, 70, + + // between top rung and middle + 6, 210, 160, 70, + + // top of middle rung + 6, 70, 180, 210, + + // front of middle rung + 6, 100, 70, 210, + + // bottom of middle rung. + 6, 76, 210, 100, + + // front of bottom + 6, 140, 210, 80, + + // bottom + 6, 90, 130, 110, + + // left side + 6, 160, 160, 220, + ], [255]); + + const numVerts = positions.length / 3; + + const arrays = { + position: createAugmentedTypedArray(3, numVerts), + texcoord: createAugmentedTypedArray(2, numVerts), + normal: createAugmentedTypedArray(3, numVerts), + color: createAugmentedTypedArray(4, numVerts, Uint8Array), + indices: createAugmentedTypedArray(3, numVerts / 3, Uint16Array), + }; + + arrays.position.push(positions); + arrays.texcoord.push(texcoords); + arrays.normal.push(normals); + arrays.color.push(colors); + + for (let ii = 0; ii < numVerts; ++ii) { + arrays.indices.push(ii); + } + + return arrays; +} + +/** + * Creates crescent BufferInfo. + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext. + * @param {number} verticalRadius The vertical radius of the crescent. + * @param {number} outerRadius The outer radius of the crescent. + * @param {number} innerRadius The inner radius of the crescent. + * @param {number} thickness The thickness of the crescent. + * @param {number} subdivisionsDown number of steps around the crescent. + * @param {number} [startOffset] Where to start arc. Default 0. + * @param {number} [endOffset] Where to end arg. Default 1. + * @return {module:twgl.BufferInfo} The created BufferInfo. + * @memberOf module:twgl/primitives + * @function createCresentBufferInfo + */ + +/** + * Creates crescent buffers. + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext. + * @param {number} verticalRadius The vertical radius of the crescent. + * @param {number} outerRadius The outer radius of the crescent. + * @param {number} innerRadius The inner radius of the crescent. + * @param {number} thickness The thickness of the crescent. + * @param {number} subdivisionsDown number of steps around the crescent. + * @param {number} [startOffset] Where to start arc. Default 0. + * @param {number} [endOffset] Where to end arg. Default 1. + * @return {Object.} The created buffers. + * @memberOf module:twgl/primitives + * @function createCresentBuffers + */ + +/** + * Creates crescent vertices. + * + * @param {number} verticalRadius The vertical radius of the crescent. + * @param {number} outerRadius The outer radius of the crescent. + * @param {number} innerRadius The inner radius of the crescent. + * @param {number} thickness The thickness of the crescent. + * @param {number} subdivisionsDown number of steps around the crescent. + * @param {number} [startOffset] Where to start arc. Default 0. + * @param {number} [endOffset] Where to end arg. Default 1. + * @return {Object.} The created vertices. + * @memberOf module:twgl/primitives + * @function createCresentBuffers + */ + +/** + * Creates crescent BufferInfo. + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext. + * @param {number} verticalRadius The vertical radius of the crescent. + * @param {number} outerRadius The outer radius of the crescent. + * @param {number} innerRadius The inner radius of the crescent. + * @param {number} thickness The thickness of the crescent. + * @param {number} subdivisionsDown number of steps around the crescent. + * @param {number} [startOffset] Where to start arc. Default 0. + * @param {number} [endOffset] Where to end arg. Default 1. + * @return {module:twgl.BufferInfo} The created BufferInfo. + * @memberOf module:twgl/primitives + * @function createCrescentBufferInfo + */ + +/** + * Creates crescent buffers. + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext. + * @param {number} verticalRadius The vertical radius of the crescent. + * @param {number} outerRadius The outer radius of the crescent. + * @param {number} innerRadius The inner radius of the crescent. + * @param {number} thickness The thickness of the crescent. + * @param {number} subdivisionsDown number of steps around the crescent. + * @param {number} [startOffset] Where to start arc. Default 0. + * @param {number} [endOffset] Where to end arg. Default 1. + * @return {Object.} The created buffers. + * @memberOf module:twgl/primitives + * @function createCrescentBuffers + */ + +/** + * Creates crescent vertices. + * + * @param {number} verticalRadius The vertical radius of the crescent. + * @param {number} outerRadius The outer radius of the crescent. + * @param {number} innerRadius The inner radius of the crescent. + * @param {number} thickness The thickness of the crescent. + * @param {number} subdivisionsDown number of steps around the crescent. + * @param {number} [startOffset] Where to start arc. Default 0. + * @param {number} [endOffset] Where to end arg. Default 1. + * @return {Object.} The created vertices. + * @memberOf module:twgl/primitives + */ + function createCrescentVertices( + verticalRadius, + outerRadius, + innerRadius, + thickness, + subdivisionsDown, + startOffset, + endOffset) { + if (subdivisionsDown <= 0) { + throw new Error('subdivisionDown must be > 0'); + } + + startOffset = startOffset || 0; + endOffset = endOffset || 1; + + const subdivisionsThick = 2; + + const offsetRange = endOffset - startOffset; + const numVertices = (subdivisionsDown + 1) * 2 * (2 + subdivisionsThick); + const positions = createAugmentedTypedArray(3, numVertices); + const normals = createAugmentedTypedArray(3, numVertices); + const texcoords = createAugmentedTypedArray(2, numVertices); + + function lerp(a, b, s) { + return a + (b - a) * s; + } + + function createArc(arcRadius, x, normalMult, normalAdd, uMult, uAdd) { + for (let z = 0; z <= subdivisionsDown; z++) { + const uBack = x / (subdivisionsThick - 1); + const v = z / subdivisionsDown; + const xBack = (uBack - 0.5) * 2; + const angle = (startOffset + (v * offsetRange)) * Math.PI; + const s = Math.sin(angle); + const c = Math.cos(angle); + const radius = lerp(verticalRadius, arcRadius, s); + const px = xBack * thickness; + const py = c * verticalRadius; + const pz = s * radius; + positions.push(px, py, pz); + const n = add(multiply$1([0, s, c], normalMult), normalAdd); + normals.push(n); + texcoords.push(uBack * uMult + uAdd, v); + } + } + + // Generate the individual vertices in our vertex buffer. + for (let x = 0; x < subdivisionsThick; x++) { + const uBack = (x / (subdivisionsThick - 1) - 0.5) * 2; + createArc(outerRadius, x, [1, 1, 1], [0, 0, 0], 1, 0); + createArc(outerRadius, x, [0, 0, 0], [uBack, 0, 0], 0, 0); + createArc(innerRadius, x, [1, 1, 1], [0, 0, 0], 1, 0); + createArc(innerRadius, x, [0, 0, 0], [uBack, 0, 0], 0, 1); + } + + // Do outer surface. + const indices = createAugmentedTypedArray(3, (subdivisionsDown * 2) * (2 + subdivisionsThick), Uint16Array); + + function createSurface(leftArcOffset, rightArcOffset) { + for (let z = 0; z < subdivisionsDown; ++z) { + // Make triangle 1 of quad. + indices.push( + leftArcOffset + z + 0, + leftArcOffset + z + 1, + rightArcOffset + z + 0); + + // Make triangle 2 of quad. + indices.push( + leftArcOffset + z + 1, + rightArcOffset + z + 1, + rightArcOffset + z + 0); + } + } + + const numVerticesDown = subdivisionsDown + 1; + // front + createSurface(numVerticesDown * 0, numVerticesDown * 4); + // right + createSurface(numVerticesDown * 5, numVerticesDown * 7); + // back + createSurface(numVerticesDown * 6, numVerticesDown * 2); + // left + createSurface(numVerticesDown * 3, numVerticesDown * 1); + + return { + position: positions, + normal: normals, + texcoord: texcoords, + indices: indices, + }; +} + +/** + * Creates cylinder BufferInfo. The cylinder will be created around the origin + * along the y-axis. + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext. + * @param {number} radius Radius of cylinder. + * @param {number} height Height of cylinder. + * @param {number} radialSubdivisions The number of subdivisions around the cylinder. + * @param {number} verticalSubdivisions The number of subdivisions down the cylinder. + * @param {boolean} [topCap] Create top cap. Default = true. + * @param {boolean} [bottomCap] Create bottom cap. Default = true. + * @return {module:twgl.BufferInfo} The created BufferInfo. + * @memberOf module:twgl/primitives + * @function createCylinderBufferInfo + */ + + /** + * Creates cylinder buffers. The cylinder will be created around the origin + * along the y-axis. + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext. + * @param {number} radius Radius of cylinder. + * @param {number} height Height of cylinder. + * @param {number} radialSubdivisions The number of subdivisions around the cylinder. + * @param {number} verticalSubdivisions The number of subdivisions down the cylinder. + * @param {boolean} [topCap] Create top cap. Default = true. + * @param {boolean} [bottomCap] Create bottom cap. Default = true. + * @return {Object.} The created buffers. + * @memberOf module:twgl/primitives + * @function createCylinderBuffers + */ + + /** + * Creates cylinder vertices. The cylinder will be created around the origin + * along the y-axis. + * + * @param {number} radius Radius of cylinder. + * @param {number} height Height of cylinder. + * @param {number} radialSubdivisions The number of subdivisions around the cylinder. + * @param {number} verticalSubdivisions The number of subdivisions down the cylinder. + * @param {boolean} [topCap] Create top cap. Default = true. + * @param {boolean} [bottomCap] Create bottom cap. Default = true. + * @return {Object.} The created vertices. + * @memberOf module:twgl/primitives + */ +function createCylinderVertices( + radius, + height, + radialSubdivisions, + verticalSubdivisions, + topCap, + bottomCap) { + return createTruncatedConeVertices( + radius, + radius, + height, + radialSubdivisions, + verticalSubdivisions, + topCap, + bottomCap); +} + +/** + * Creates BufferInfo for a torus + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext. + * @param {number} radius radius of center of torus circle. + * @param {number} thickness radius of torus ring. + * @param {number} radialSubdivisions The number of subdivisions around the torus. + * @param {number} bodySubdivisions The number of subdivisions around the body torus. + * @param {boolean} [startAngle] start angle in radians. Default = 0. + * @param {boolean} [endAngle] end angle in radians. Default = Math.PI * 2. + * @return {module:twgl.BufferInfo} The created BufferInfo. + * @memberOf module:twgl/primitives + * @function createTorusBufferInfo + */ + +/** + * Creates buffers for a torus + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext. + * @param {number} radius radius of center of torus circle. + * @param {number} thickness radius of torus ring. + * @param {number} radialSubdivisions The number of subdivisions around the torus. + * @param {number} bodySubdivisions The number of subdivisions around the body torus. + * @param {boolean} [startAngle] start angle in radians. Default = 0. + * @param {boolean} [endAngle] end angle in radians. Default = Math.PI * 2. + * @return {Object.} The created buffers. + * @memberOf module:twgl/primitives + * @function createTorusBuffers + */ + +/** + * Creates vertices for a torus + * + * @param {number} radius radius of center of torus circle. + * @param {number} thickness radius of torus ring. + * @param {number} radialSubdivisions The number of subdivisions around the torus. + * @param {number} bodySubdivisions The number of subdivisions around the body torus. + * @param {boolean} [startAngle] start angle in radians. Default = 0. + * @param {boolean} [endAngle] end angle in radians. Default = Math.PI * 2. + * @return {Object.} The created vertices. + * @memberOf module:twgl/primitives + */ +function createTorusVertices( + radius, + thickness, + radialSubdivisions, + bodySubdivisions, + startAngle, + endAngle) { + if (radialSubdivisions < 3) { + throw new Error('radialSubdivisions must be 3 or greater'); + } + + if (bodySubdivisions < 3) { + throw new Error('verticalSubdivisions must be 3 or greater'); + } + + startAngle = startAngle || 0; + endAngle = endAngle || Math.PI * 2; + const range = endAngle - startAngle; + + const radialParts = radialSubdivisions + 1; + const bodyParts = bodySubdivisions + 1; + const numVertices = radialParts * bodyParts; + const positions = createAugmentedTypedArray(3, numVertices); + const normals = createAugmentedTypedArray(3, numVertices); + const texcoords = createAugmentedTypedArray(2, numVertices); + const indices = createAugmentedTypedArray(3, (radialSubdivisions) * (bodySubdivisions) * 2, Uint16Array); + + for (let slice = 0; slice < bodyParts; ++slice) { + const v = slice / bodySubdivisions; + const sliceAngle = v * Math.PI * 2; + const sliceSin = Math.sin(sliceAngle); + const ringRadius = radius + sliceSin * thickness; + const ny = Math.cos(sliceAngle); + const y = ny * thickness; + for (let ring = 0; ring < radialParts; ++ring) { + const u = ring / radialSubdivisions; + const ringAngle = startAngle + u * range; + const xSin = Math.sin(ringAngle); + const zCos = Math.cos(ringAngle); + const x = xSin * ringRadius; + const z = zCos * ringRadius; + const nx = xSin * sliceSin; + const nz = zCos * sliceSin; + positions.push(x, y, z); + normals.push(nx, ny, nz); + texcoords.push(u, 1 - v); + } + } + + for (let slice = 0; slice < bodySubdivisions; ++slice) { // eslint-disable-line + for (let ring = 0; ring < radialSubdivisions; ++ring) { // eslint-disable-line + const nextRingIndex = 1 + ring; + const nextSliceIndex = 1 + slice; + indices.push(radialParts * slice + ring, + radialParts * nextSliceIndex + ring, + radialParts * slice + nextRingIndex); + indices.push(radialParts * nextSliceIndex + ring, + radialParts * nextSliceIndex + nextRingIndex, + radialParts * slice + nextRingIndex); + } + } + + return { + position: positions, + normal: normals, + texcoord: texcoords, + indices: indices, + }; +} + + +/** + * Creates a disc BufferInfo. The disc will be in the xz plane, centered at + * the origin. When creating, at least 3 divisions, or pie + * pieces, need to be specified, otherwise the triangles making + * up the disc will be degenerate. You can also specify the + * number of radial pieces `stacks`. A value of 1 for + * stacks will give you a simple disc of pie pieces. If you + * want to create an annulus you can set `innerRadius` to a + * value > 0. Finally, `stackPower` allows you to have the widths + * increase or decrease as you move away from the center. This + * is particularly useful when using the disc as a ground plane + * with a fixed camera such that you don't need the resolution + * of small triangles near the perimeter. For example, a value + * of 2 will produce stacks whose outside radius increases with + * the square of the stack index. A value of 1 will give uniform + * stacks. + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext. + * @param {number} radius Radius of the ground plane. + * @param {number} divisions Number of triangles in the ground plane (at least 3). + * @param {number} [stacks] Number of radial divisions (default=1). + * @param {number} [innerRadius] Default 0. + * @param {number} [stackPower] Power to raise stack size to for decreasing width. + * @return {module:twgl.BufferInfo} The created BufferInfo. + * @memberOf module:twgl/primitives + * @function createDiscBufferInfo + */ + +/** + * Creates disc buffers. The disc will be in the xz plane, centered at + * the origin. When creating, at least 3 divisions, or pie + * pieces, need to be specified, otherwise the triangles making + * up the disc will be degenerate. You can also specify the + * number of radial pieces `stacks`. A value of 1 for + * stacks will give you a simple disc of pie pieces. If you + * want to create an annulus you can set `innerRadius` to a + * value > 0. Finally, `stackPower` allows you to have the widths + * increase or decrease as you move away from the center. This + * is particularly useful when using the disc as a ground plane + * with a fixed camera such that you don't need the resolution + * of small triangles near the perimeter. For example, a value + * of 2 will produce stacks whose outside radius increases with + * the square of the stack index. A value of 1 will give uniform + * stacks. + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext. + * @param {number} radius Radius of the ground plane. + * @param {number} divisions Number of triangles in the ground plane (at least 3). + * @param {number} [stacks] Number of radial divisions (default=1). + * @param {number} [innerRadius] Default 0. + * @param {number} [stackPower] Power to raise stack size to for decreasing width. + * @return {Object.} The created buffers. + * @memberOf module:twgl/primitives + * @function createDiscBuffers + */ + +/** + * Creates disc vertices. The disc will be in the xz plane, centered at + * the origin. When creating, at least 3 divisions, or pie + * pieces, need to be specified, otherwise the triangles making + * up the disc will be degenerate. You can also specify the + * number of radial pieces `stacks`. A value of 1 for + * stacks will give you a simple disc of pie pieces. If you + * want to create an annulus you can set `innerRadius` to a + * value > 0. Finally, `stackPower` allows you to have the widths + * increase or decrease as you move away from the center. This + * is particularly useful when using the disc as a ground plane + * with a fixed camera such that you don't need the resolution + * of small triangles near the perimeter. For example, a value + * of 2 will produce stacks whose outside radius increases with + * the square of the stack index. A value of 1 will give uniform + * stacks. + * + * @param {number} radius Radius of the ground plane. + * @param {number} divisions Number of triangles in the ground plane (at least 3). + * @param {number} [stacks] Number of radial divisions (default=1). + * @param {number} [innerRadius] Default 0. + * @param {number} [stackPower] Power to raise stack size to for decreasing width. + * @return {Object.} The created vertices. + * @memberOf module:twgl/primitives + */ +function createDiscVertices( + radius, + divisions, + stacks, + innerRadius, + stackPower) { + if (divisions < 3) { + throw new Error('divisions must be at least 3'); + } + + stacks = stacks ? stacks : 1; + stackPower = stackPower ? stackPower : 1; + innerRadius = innerRadius ? innerRadius : 0; + + // Note: We don't share the center vertex because that would + // mess up texture coordinates. + const numVertices = (divisions + 1) * (stacks + 1); + + const positions = createAugmentedTypedArray(3, numVertices); + const normals = createAugmentedTypedArray(3, numVertices); + const texcoords = createAugmentedTypedArray(2, numVertices); + const indices = createAugmentedTypedArray(3, stacks * divisions * 2, Uint16Array); + + let firstIndex = 0; + const radiusSpan = radius - innerRadius; + const pointsPerStack = divisions + 1; + + // Build the disk one stack at a time. + for (let stack = 0; stack <= stacks; ++stack) { + const stackRadius = innerRadius + radiusSpan * Math.pow(stack / stacks, stackPower); + + for (let i = 0; i <= divisions; ++i) { + const theta = 2.0 * Math.PI * i / divisions; + const x = stackRadius * Math.cos(theta); + const z = stackRadius * Math.sin(theta); + + positions.push(x, 0, z); + normals.push(0, 1, 0); + texcoords.push(1 - (i / divisions), stack / stacks); + if (stack > 0 && i !== divisions) { + // a, b, c and d are the indices of the vertices of a quad. unless + // the current stack is the one closest to the center, in which case + // the vertices a and b connect to the center vertex. + const a = firstIndex + (i + 1); + const b = firstIndex + i; + const c = firstIndex + i - pointsPerStack; + const d = firstIndex + (i + 1) - pointsPerStack; + + // Make a quad of the vertices a, b, c, d. + indices.push(a, b, c); + indices.push(a, c, d); + } + } + + firstIndex += divisions + 1; + } + + return { + position: positions, + normal: normals, + texcoord: texcoords, + indices: indices, + }; +} + +/** + * creates a random integer between 0 and range - 1 inclusive. + * @param {number} range + * @return {number} random value between 0 and range - 1 inclusive. + * @private + */ +function randInt(range) { + return Math.random() * range | 0; +} + +/** + * Used to supply random colors + * @callback RandomColorFunc + * @param {number} ndx index of triangle/quad if unindexed or index of vertex if indexed + * @param {number} channel 0 = red, 1 = green, 2 = blue, 3 = alpha + * @return {number} a number from 0 to 255 + * @memberOf module:twgl/primitives + */ + +/** + * @typedef {Object} RandomVerticesOptions + * @property {number} [vertsPerColor] Defaults to 3 for non-indexed vertices + * @property {module:twgl/primitives.RandomColorFunc} [rand] A function to generate random numbers + * @memberOf module:twgl/primitives + */ + +/** + * Creates an augmentedTypedArray of random vertex colors. + * If the vertices are indexed (have an indices array) then will + * just make random colors. Otherwise assumes they are triangles + * and makes one random color for every 3 vertices. + * @param {Object.} vertices Vertices as returned from one of the createXXXVertices functions. + * @param {module:twgl/primitives.RandomVerticesOptions} [options] options. + * @return {Object.} same vertices as passed in with `color` added. + * @memberOf module:twgl/primitives + */ +function makeRandomVertexColors(vertices, options) { + options = options || {}; + const numElements = vertices.position.numElements; + const vColors = createAugmentedTypedArray(4, numElements, Uint8Array); + const rand = options.rand || function(ndx, channel) { + return channel < 3 ? randInt(256) : 255; + }; + vertices.color = vColors; + if (vertices.indices) { + // just make random colors if index + for (let ii = 0; ii < numElements; ++ii) { + vColors.push(rand(ii, 0), rand(ii, 1), rand(ii, 2), rand(ii, 3)); + } + } else { + // make random colors per triangle + const numVertsPerColor = options.vertsPerColor || 3; + const numSets = numElements / numVertsPerColor; + for (let ii = 0; ii < numSets; ++ii) { // eslint-disable-line + const color = [rand(ii, 0), rand(ii, 1), rand(ii, 2), rand(ii, 3)]; + for (let jj = 0; jj < numVertsPerColor; ++jj) { + vColors.push(color); + } + } + } + return vertices; +} + +/** + * creates a function that calls fn to create vertices and then + * creates a buffers for them + * @private + */ +function createBufferFunc(fn) { + return function(gl) { + const arrays = fn.apply(this, Array.prototype.slice.call(arguments, 1)); + return createBuffersFromArrays(gl, arrays); + }; +} + +/** + * creates a function that calls fn to create vertices and then + * creates a bufferInfo object for them + * @private + */ +function createBufferInfoFunc(fn) { + return function(gl) { + const arrays = fn.apply(null, Array.prototype.slice.call(arguments, 1)); + return createBufferInfoFromArrays(gl, arrays); + }; +} + +const arraySpecPropertyNames = [ + "numComponents", + "size", + "type", + "normalize", + "stride", + "offset", + "attrib", + "name", + "attribName", +]; + +/** + * Copy elements from one array to another + * + * @param {Array|TypedArray} src source array + * @param {Array|TypedArray} dst dest array + * @param {number} dstNdx index in dest to copy src + * @param {number} [offset] offset to add to copied values + * @private + */ +function copyElements(src, dst, dstNdx, offset) { + offset = offset || 0; + const length = src.length; + for (let ii = 0; ii < length; ++ii) { + dst[dstNdx + ii] = src[ii] + offset; + } +} + +/** + * Creates an array of the same time + * + * @param {(number[]|ArrayBufferView|module:twgl.FullArraySpec)} srcArray array who's type to copy + * @param {number} length size of new array + * @return {(number[]|ArrayBufferView|module:twgl.FullArraySpec)} array with same type as srcArray + * @private + */ +function createArrayOfSameType(srcArray, length) { + const arraySrc = getArray(srcArray); + const newArray = new arraySrc.constructor(length); + let newArraySpec = newArray; + // If it appears to have been augmented make new one augmented + if (arraySrc.numComponents && arraySrc.numElements) { + augmentTypedArray(newArray, arraySrc.numComponents); + } + // If it was a full spec make new one a full spec + if (srcArray.data) { + newArraySpec = { + data: newArray, + }; + copyNamedProperties(arraySpecPropertyNames, srcArray, newArraySpec); + } + return newArraySpec; +} + +/** + * Concatenates sets of vertices + * + * Assumes the vertices match in composition. For example + * if one set of vertices has positions, normals, and indices + * all sets of vertices must have positions, normals, and indices + * and of the same type. + * + * Example: + * + * const cubeVertices = twgl.primitives.createCubeVertices(2); + * const sphereVertices = twgl.primitives.createSphereVertices(1, 10, 10); + * // move the sphere 2 units up + * twgl.primitives.reorientVertices( + * sphereVertices, twgl.m4.translation([0, 2, 0])); + * // merge the sphere with the cube + * const cubeSphereVertices = twgl.primitives.concatVertices( + * [cubeVertices, sphereVertices]); + * // turn them into WebGL buffers and attrib data + * const bufferInfo = twgl.createBufferInfoFromArrays(gl, cubeSphereVertices); + * + * @param {module:twgl.Arrays[]} arrays Array of arrays of vertices + * @return {module:twgl.Arrays} The concatenated vertices. + * @memberOf module:twgl/primitives + */ +function concatVertices(arrayOfArrays) { + const names = {}; + let baseName; + // get names of all arrays. + // and numElements for each set of vertices + for (let ii = 0; ii < arrayOfArrays.length; ++ii) { + const arrays = arrayOfArrays[ii]; + Object.keys(arrays).forEach(function(name) { // eslint-disable-line + if (!names[name]) { + names[name] = []; + } + if (!baseName && name !== 'indices') { + baseName = name; + } + const arrayInfo = arrays[name]; + const numComponents = getNumComponents(arrayInfo, name); + const array = getArray(arrayInfo); + const numElements = array.length / numComponents; + names[name].push(numElements); + }); + } + + // compute length of combined array + // and return one for reference + function getLengthOfCombinedArrays(name) { + let length = 0; + let arraySpec; + for (let ii = 0; ii < arrayOfArrays.length; ++ii) { + const arrays = arrayOfArrays[ii]; + const arrayInfo = arrays[name]; + const array = getArray(arrayInfo); + length += array.length; + if (!arraySpec || arrayInfo.data) { + arraySpec = arrayInfo; + } + } + return { + length: length, + spec: arraySpec, + }; + } + + function copyArraysToNewArray(name, base, newArray) { + let baseIndex = 0; + let offset = 0; + for (let ii = 0; ii < arrayOfArrays.length; ++ii) { + const arrays = arrayOfArrays[ii]; + const arrayInfo = arrays[name]; + const array = getArray(arrayInfo); + if (name === 'indices') { + copyElements(array, newArray, offset, baseIndex); + baseIndex += base[ii]; + } else { + copyElements(array, newArray, offset); + } + offset += array.length; + } + } + + const base = names[baseName]; + + const newArrays = {}; + Object.keys(names).forEach(function(name) { + const info = getLengthOfCombinedArrays(name); + const newArraySpec = createArrayOfSameType(info.spec, info.length); + copyArraysToNewArray(name, base, getArray(newArraySpec)); + newArrays[name] = newArraySpec; + }); + return newArrays; +} + +/** + * Creates a duplicate set of vertices + * + * This is useful for calling reorientVertices when you + * also want to keep the original available + * + * @param {module:twgl.Arrays} arrays of vertices + * @return {module:twgl.Arrays} The duplicated vertices. + * @memberOf module:twgl/primitives + */ +function duplicateVertices(arrays) { + const newArrays = {}; + Object.keys(arrays).forEach(function(name) { + const arraySpec = arrays[name]; + const srcArray = getArray(arraySpec); + const newArraySpec = createArrayOfSameType(arraySpec, srcArray.length); + copyElements(srcArray, getArray(newArraySpec), 0); + newArrays[name] = newArraySpec; + }); + return newArrays; +} + +const create3DFBufferInfo = createBufferInfoFunc(create3DFVertices); +const create3DFBuffers = createBufferFunc(create3DFVertices); +const createCubeBufferInfo = createBufferInfoFunc(createCubeVertices); +const createCubeBuffers = createBufferFunc(createCubeVertices); +const createPlaneBufferInfo = createBufferInfoFunc(createPlaneVertices); +const createPlaneBuffers = createBufferFunc(createPlaneVertices); +const createSphereBufferInfo = createBufferInfoFunc(createSphereVertices); +const createSphereBuffers = createBufferFunc(createSphereVertices); +const createTruncatedConeBufferInfo = createBufferInfoFunc(createTruncatedConeVertices); +const createTruncatedConeBuffers = createBufferFunc(createTruncatedConeVertices); +const createXYQuadBufferInfo = createBufferInfoFunc(createXYQuadVertices); +const createXYQuadBuffers = createBufferFunc(createXYQuadVertices); +const createCrescentBufferInfo = createBufferInfoFunc(createCrescentVertices); +const createCrescentBuffers = createBufferFunc(createCrescentVertices); +const createCylinderBufferInfo = createBufferInfoFunc(createCylinderVertices); +const createCylinderBuffers = createBufferFunc(createCylinderVertices); +const createTorusBufferInfo = createBufferInfoFunc(createTorusVertices); +const createTorusBuffers = createBufferFunc(createTorusVertices); +const createDiscBufferInfo = createBufferInfoFunc(createDiscVertices); +const createDiscBuffers = createBufferFunc(createDiscVertices); + +// these were mis-spelled until 4.12 +const createCresentBufferInfo = createCrescentBufferInfo; +const createCresentBuffers = createCrescentBuffers; +const createCresentVertices = createCrescentVertices; + +var primitives = /*#__PURE__*/Object.freeze({ + __proto__: null, + create3DFBufferInfo: create3DFBufferInfo, + create3DFBuffers: create3DFBuffers, + create3DFVertices: create3DFVertices, + createAugmentedTypedArray: createAugmentedTypedArray, + createCubeBufferInfo: createCubeBufferInfo, + createCubeBuffers: createCubeBuffers, + createCubeVertices: createCubeVertices, + createPlaneBufferInfo: createPlaneBufferInfo, + createPlaneBuffers: createPlaneBuffers, + createPlaneVertices: createPlaneVertices, + createSphereBufferInfo: createSphereBufferInfo, + createSphereBuffers: createSphereBuffers, + createSphereVertices: createSphereVertices, + createTruncatedConeBufferInfo: createTruncatedConeBufferInfo, + createTruncatedConeBuffers: createTruncatedConeBuffers, + createTruncatedConeVertices: createTruncatedConeVertices, + createXYQuadBufferInfo: createXYQuadBufferInfo, + createXYQuadBuffers: createXYQuadBuffers, + createXYQuadVertices: createXYQuadVertices, + createCresentBufferInfo: createCresentBufferInfo, + createCresentBuffers: createCresentBuffers, + createCresentVertices: createCresentVertices, + createCrescentBufferInfo: createCrescentBufferInfo, + createCrescentBuffers: createCrescentBuffers, + createCrescentVertices: createCrescentVertices, + createCylinderBufferInfo: createCylinderBufferInfo, + createCylinderBuffers: createCylinderBuffers, + createCylinderVertices: createCylinderVertices, + createTorusBufferInfo: createTorusBufferInfo, + createTorusBuffers: createTorusBuffers, + createTorusVertices: createTorusVertices, + createDiscBufferInfo: createDiscBufferInfo, + createDiscBuffers: createDiscBuffers, + createDiscVertices: createDiscVertices, + deindexVertices: deindexVertices, + flattenNormals: flattenNormals, + makeRandomVertexColors: makeRandomVertexColors, + reorientDirections: reorientDirections, + reorientNormals: reorientNormals, + reorientPositions: reorientPositions, + reorientVertices: reorientVertices, + concatVertices: concatVertices, + duplicateVertices: duplicateVertices +}); + +/* + * Copyright 2019 Gregg Tavares + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * Gets the gl version as a number + * @param {WebGLRenderingContext} gl A WebGLRenderingContext + * @return {number} version of gl + * @private + */ +//function getVersionAsNumber(gl) { +// return parseFloat(gl.getParameter(gl.VERSION).substr(6)); +//} + +/** + * Check if context is WebGL 2.0 + * @param {WebGLRenderingContext} gl A WebGLRenderingContext + * @return {bool} true if it's WebGL 2.0 + * @memberOf module:twgl + */ +function isWebGL2(gl) { + // This is the correct check but it's slow + // return gl.getParameter(gl.VERSION).indexOf("WebGL 2.0") === 0; + // This might also be the correct check but I'm assuming it's slow-ish + // return gl instanceof WebGL2RenderingContext; + return !!gl.texStorage2D; +} + +/** + * Check if context is WebGL 1.0 + * @param {WebGLRenderingContext} gl A WebGLRenderingContext + * @return {bool} true if it's WebGL 1.0 + * @memberOf module:twgl + */ +function isWebGL1(gl) { + // This is the correct check but it's slow + // const version = getVersionAsNumber(gl); + // return version <= 1.0 && version > 0.0; // because as of 2016/5 Edge returns 0.96 + // This might also be the correct check but I'm assuming it's slow-ish + // return gl instanceof WebGLRenderingContext; + return !gl.texStorage2D; +} + +/** + * Gets a string for WebGL enum + * + * Note: Several enums are the same. Without more + * context (which function) it's impossible to always + * give the correct enum. As it is, for matching values + * it gives all enums. Checking the WebGL2RenderingContext + * that means + * + * 0 = ZERO | POINT | NONE | NO_ERROR + * 1 = ONE | LINES | SYNC_FLUSH_COMMANDS_BIT + * 32777 = BLEND_EQUATION_RGB | BLEND_EQUATION_RGB + * 36662 = COPY_READ_BUFFER | COPY_READ_BUFFER_BINDING + * 36663 = COPY_WRITE_BUFFER | COPY_WRITE_BUFFER_BINDING + * 36006 = FRAMEBUFFER_BINDING | DRAW_FRAMEBUFFER_BINDING + * + * It's also not useful for bits really unless you pass in individual bits. + * In other words + * + * const bits = gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT; + * twgl.glEnumToString(gl, bits); // not going to work + * + * Note that some enums only exist on extensions. If you + * want them to show up you need to pass the extension at least + * once. For example + * + * const ext = gl.getExtension('WEBGL_compressed_texture_s3tc'); + * if (ext) { + * twgl.glEnumToString(ext, 0); // just prime the function + * + * ..later.. + * + * const internalFormat = ext.COMPRESSED_RGB_S3TC_DXT1_EXT; + * console.log(twgl.glEnumToString(gl, internalFormat)); + * + * Notice I didn't have to pass the extension the second time. This means + * you can have place that generically gets an enum for texture formats for example. + * and as long as you primed the function with the extensions + * + * If you're using `twgl.addExtensionsToContext` to enable your extensions + * then twgl will automatically get the extension's enums. + * + * @param {WebGLRenderingContext} gl A WebGLRenderingContext or any extension object + * @param {number} value the value of the enum you want to look up. + * @return {string} enum string or hex value + * @memberOf module:twgl + * @function glEnumToString + */ +const glEnumToString = (function() { + const haveEnumsForType = {}; + const enums = {}; + + function addEnums(gl) { + const type = gl.constructor.name; + if (!haveEnumsForType[type]) { + for (const key in gl) { + if (typeof gl[key] === 'number') { + const existing = enums[gl[key]]; + enums[gl[key]] = existing ? `${existing} | ${key}` : key; + } + } + haveEnumsForType[type] = true; + } + } + + return function glEnumToString(gl, value) { + addEnums(gl); + return enums[value] || (typeof value === 'number' ? `0x${value.toString(16)}` : value); + }; +}()); + +var utils = /*#__PURE__*/Object.freeze({ + __proto__: null, + glEnumToString: glEnumToString, + isWebGL1: isWebGL1, + isWebGL2: isWebGL2 +}); + +/* + * Copyright 2019 Gregg Tavares + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +const defaults$1 = { + textureColor: new Uint8Array([128, 192, 255, 255]), + textureOptions: {}, + crossOrigin: undefined, +}; +const isArrayBuffer = isArrayBuffer$1; + +// Should we make this on demand? +const getShared2DContext = function() { + let s_ctx; + return function getShared2DContext() { + s_ctx = s_ctx || + ((typeof document !== 'undefined' && document.createElement) + ? document.createElement("canvas").getContext("2d") + : null); + return s_ctx; + }; +}(); + +// NOTE: Chrome supports 2D canvas in a Worker (behind flag as of v64 but +// not only does Firefox NOT support it but Firefox freezes immediately +// if you try to create one instead of just returning null and continuing. +// : (global.OffscreenCanvas && (new global.OffscreenCanvas(1, 1)).getContext("2d")); // OffscreenCanvas may not support 2d + +// NOTE: We can maybe remove some of the need for the 2d canvas. In WebGL2 +// we can use the various unpack settings. Otherwise we could try using +// the ability of an ImageBitmap to be cut. Unfortunately cutting an ImageBitmap +// is async and the current TWGL code expects a non-Async result though that +// might not be a problem. ImageBitmap though is not available in Edge or Safari +// as of 2018-01-02 + +/* PixelFormat */ +const ALPHA = 0x1906; +const RGB = 0x1907; +const RGBA$1 = 0x1908; +const LUMINANCE = 0x1909; +const LUMINANCE_ALPHA = 0x190A; +const DEPTH_COMPONENT$1 = 0x1902; +const DEPTH_STENCIL$1 = 0x84F9; + +/* TextureWrapMode */ +// const REPEAT = 0x2901; +// const MIRRORED_REPEAT = 0x8370; +const CLAMP_TO_EDGE$1 = 0x812f; + +/* TextureMagFilter */ +const NEAREST = 0x2600; +const LINEAR$1 = 0x2601; + +/* TextureMinFilter */ +// const NEAREST_MIPMAP_NEAREST = 0x2700; +// const LINEAR_MIPMAP_NEAREST = 0x2701; +// const NEAREST_MIPMAP_LINEAR = 0x2702; +// const LINEAR_MIPMAP_LINEAR = 0x2703; + +/* Texture Target */ +const TEXTURE_2D$2 = 0x0de1; +const TEXTURE_CUBE_MAP$1 = 0x8513; +const TEXTURE_3D$1 = 0x806f; +const TEXTURE_2D_ARRAY$1 = 0x8c1a; + +/* Cubemap Targets */ +const TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515; +const TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516; +const TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517; +const TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518; +const TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519; +const TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851a; + +/* Texture Parameters */ +const TEXTURE_MIN_FILTER = 0x2801; +const TEXTURE_MAG_FILTER = 0x2800; +const TEXTURE_WRAP_S = 0x2802; +const TEXTURE_WRAP_T = 0x2803; +const TEXTURE_WRAP_R = 0x8072; +const TEXTURE_MIN_LOD = 0x813a; +const TEXTURE_MAX_LOD = 0x813b; +const TEXTURE_BASE_LEVEL = 0x813c; +const TEXTURE_MAX_LEVEL = 0x813d; + + +/* Pixel store */ +const UNPACK_ALIGNMENT = 0x0cf5; +const UNPACK_ROW_LENGTH = 0x0cf2; +const UNPACK_IMAGE_HEIGHT = 0x806e; +const UNPACK_SKIP_PIXELS = 0x0cf4; +const UNPACK_SKIP_ROWS = 0x0cf3; +const UNPACK_SKIP_IMAGES = 0x806d; +const UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243; +const UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241; +const UNPACK_FLIP_Y_WEBGL = 0x9240; + +const R8 = 0x8229; +const R8_SNORM = 0x8F94; +const R16F = 0x822D; +const R32F = 0x822E; +const R8UI = 0x8232; +const R8I = 0x8231; +const RG16UI = 0x823A; +const RG16I = 0x8239; +const RG32UI = 0x823C; +const RG32I = 0x823B; +const RG8 = 0x822B; +const RG8_SNORM = 0x8F95; +const RG16F = 0x822F; +const RG32F = 0x8230; +const RG8UI = 0x8238; +const RG8I = 0x8237; +const R16UI = 0x8234; +const R16I = 0x8233; +const R32UI = 0x8236; +const R32I = 0x8235; +const RGB8 = 0x8051; +const SRGB8 = 0x8C41; +const RGB565$1 = 0x8D62; +const RGB8_SNORM = 0x8F96; +const R11F_G11F_B10F = 0x8C3A; +const RGB9_E5 = 0x8C3D; +const RGB16F = 0x881B; +const RGB32F = 0x8815; +const RGB8UI = 0x8D7D; +const RGB8I = 0x8D8F; +const RGB16UI = 0x8D77; +const RGB16I = 0x8D89; +const RGB32UI = 0x8D71; +const RGB32I = 0x8D83; +const RGBA8 = 0x8058; +const SRGB8_ALPHA8 = 0x8C43; +const RGBA8_SNORM = 0x8F97; +const RGB5_A1$1 = 0x8057; +const RGBA4$1 = 0x8056; +const RGB10_A2 = 0x8059; +const RGBA16F = 0x881A; +const RGBA32F = 0x8814; +const RGBA8UI = 0x8D7C; +const RGBA8I = 0x8D8E; +const RGB10_A2UI = 0x906F; +const RGBA16UI = 0x8D76; +const RGBA16I = 0x8D88; +const RGBA32I = 0x8D82; +const RGBA32UI = 0x8D70; + +const DEPTH_COMPONENT16$1 = 0x81A5; +const DEPTH_COMPONENT24$1 = 0x81A6; +const DEPTH_COMPONENT32F$1 = 0x8CAC; +const DEPTH32F_STENCIL8$1 = 0x8CAD; +const DEPTH24_STENCIL8$1 = 0x88F0; + +/* DataType */ +const BYTE = 0x1400; +const UNSIGNED_BYTE$1 = 0x1401; +const SHORT = 0x1402; +const UNSIGNED_SHORT$1 = 0x1403; +const INT$1 = 0x1404; +const UNSIGNED_INT$1 = 0x1405; +const FLOAT$1 = 0x1406; +const UNSIGNED_SHORT_4_4_4_4 = 0x8033; +const UNSIGNED_SHORT_5_5_5_1 = 0x8034; +const UNSIGNED_SHORT_5_6_5 = 0x8363; +const HALF_FLOAT = 0x140B; +const HALF_FLOAT_OES = 0x8D61; // Thanks Khronos for making this different >:( +const UNSIGNED_INT_2_10_10_10_REV = 0x8368; +const UNSIGNED_INT_10F_11F_11F_REV = 0x8C3B; +const UNSIGNED_INT_5_9_9_9_REV = 0x8C3E; +const FLOAT_32_UNSIGNED_INT_24_8_REV = 0x8DAD; +const UNSIGNED_INT_24_8 = 0x84FA; + +const RG = 0x8227; +const RG_INTEGER = 0x8228; +const RED = 0x1903; +const RED_INTEGER = 0x8D94; +const RGB_INTEGER = 0x8D98; +const RGBA_INTEGER = 0x8D99; + +const formatInfo = {}; +{ + // NOTE: this is named `numColorComponents` vs `numComponents` so we can let Uglify mangle + // the name. + const f = formatInfo; + f[ALPHA] = { numColorComponents: 1, }; + f[LUMINANCE] = { numColorComponents: 1, }; + f[LUMINANCE_ALPHA] = { numColorComponents: 2, }; + f[RGB] = { numColorComponents: 3, }; + f[RGBA$1] = { numColorComponents: 4, }; + f[RED] = { numColorComponents: 1, }; + f[RED_INTEGER] = { numColorComponents: 1, }; + f[RG] = { numColorComponents: 2, }; + f[RG_INTEGER] = { numColorComponents: 2, }; + f[RGB] = { numColorComponents: 3, }; + f[RGB_INTEGER] = { numColorComponents: 3, }; + f[RGBA$1] = { numColorComponents: 4, }; + f[RGBA_INTEGER] = { numColorComponents: 4, }; + f[DEPTH_COMPONENT$1] = { numColorComponents: 1, }; + f[DEPTH_STENCIL$1] = { numColorComponents: 2, }; +} + +/** + * @typedef {Object} TextureFormatDetails + * @property {number} textureFormat format to pass texImage2D and similar functions. + * @property {boolean} colorRenderable true if you can render to this format of texture. + * @property {boolean} textureFilterable true if you can filter the texture, false if you can ony use `NEAREST`. + * @property {number[]} type Array of possible types you can pass to texImage2D and similar function + * @property {Object.} bytesPerElementMap A map of types to bytes per element + * @private + */ + +let s_textureInternalFormatInfo; +function getTextureInternalFormatInfo(internalFormat) { + if (!s_textureInternalFormatInfo) { + // NOTE: these properties need unique names so we can let Uglify mangle the name. + const t = {}; + // unsized formats + t[ALPHA] = { textureFormat: ALPHA, colorRenderable: true, textureFilterable: true, bytesPerElement: [1, 2, 2, 4], type: [UNSIGNED_BYTE$1, HALF_FLOAT, HALF_FLOAT_OES, FLOAT$1], }; + t[LUMINANCE] = { textureFormat: LUMINANCE, colorRenderable: true, textureFilterable: true, bytesPerElement: [1, 2, 2, 4], type: [UNSIGNED_BYTE$1, HALF_FLOAT, HALF_FLOAT_OES, FLOAT$1], }; + t[LUMINANCE_ALPHA] = { textureFormat: LUMINANCE_ALPHA, colorRenderable: true, textureFilterable: true, bytesPerElement: [2, 4, 4, 8], type: [UNSIGNED_BYTE$1, HALF_FLOAT, HALF_FLOAT_OES, FLOAT$1], }; + t[RGB] = { textureFormat: RGB, colorRenderable: true, textureFilterable: true, bytesPerElement: [3, 6, 6, 12, 2], type: [UNSIGNED_BYTE$1, HALF_FLOAT, HALF_FLOAT_OES, FLOAT$1, UNSIGNED_SHORT_5_6_5], }; + t[RGBA$1] = { textureFormat: RGBA$1, colorRenderable: true, textureFilterable: true, bytesPerElement: [4, 8, 8, 16, 2, 2], type: [UNSIGNED_BYTE$1, HALF_FLOAT, HALF_FLOAT_OES, FLOAT$1, UNSIGNED_SHORT_4_4_4_4, UNSIGNED_SHORT_5_5_5_1], }; + t[DEPTH_COMPONENT$1] = { textureFormat: DEPTH_COMPONENT$1, colorRenderable: true, textureFilterable: false, bytesPerElement: [2, 4], type: [UNSIGNED_INT$1, UNSIGNED_SHORT$1], }; + + // sized formats + t[R8] = { textureFormat: RED, colorRenderable: true, textureFilterable: true, bytesPerElement: [1], type: [UNSIGNED_BYTE$1], }; + t[R8_SNORM] = { textureFormat: RED, colorRenderable: false, textureFilterable: true, bytesPerElement: [1], type: [BYTE], }; + t[R16F] = { textureFormat: RED, colorRenderable: false, textureFilterable: true, bytesPerElement: [4, 2], type: [FLOAT$1, HALF_FLOAT], }; + t[R32F] = { textureFormat: RED, colorRenderable: false, textureFilterable: false, bytesPerElement: [4], type: [FLOAT$1], }; + t[R8UI] = { textureFormat: RED_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [1], type: [UNSIGNED_BYTE$1], }; + t[R8I] = { textureFormat: RED_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [1], type: [BYTE], }; + t[R16UI] = { textureFormat: RED_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [2], type: [UNSIGNED_SHORT$1], }; + t[R16I] = { textureFormat: RED_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [2], type: [SHORT], }; + t[R32UI] = { textureFormat: RED_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [UNSIGNED_INT$1], }; + t[R32I] = { textureFormat: RED_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [INT$1], }; + t[RG8] = { textureFormat: RG, colorRenderable: true, textureFilterable: true, bytesPerElement: [2], type: [UNSIGNED_BYTE$1], }; + t[RG8_SNORM] = { textureFormat: RG, colorRenderable: false, textureFilterable: true, bytesPerElement: [2], type: [BYTE], }; + t[RG16F] = { textureFormat: RG, colorRenderable: false, textureFilterable: true, bytesPerElement: [8, 4], type: [FLOAT$1, HALF_FLOAT], }; + t[RG32F] = { textureFormat: RG, colorRenderable: false, textureFilterable: false, bytesPerElement: [8], type: [FLOAT$1], }; + t[RG8UI] = { textureFormat: RG_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [2], type: [UNSIGNED_BYTE$1], }; + t[RG8I] = { textureFormat: RG_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [2], type: [BYTE], }; + t[RG16UI] = { textureFormat: RG_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [UNSIGNED_SHORT$1], }; + t[RG16I] = { textureFormat: RG_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [SHORT], }; + t[RG32UI] = { textureFormat: RG_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [8], type: [UNSIGNED_INT$1], }; + t[RG32I] = { textureFormat: RG_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [8], type: [INT$1], }; + t[RGB8] = { textureFormat: RGB, colorRenderable: true, textureFilterable: true, bytesPerElement: [3], type: [UNSIGNED_BYTE$1], }; + t[SRGB8] = { textureFormat: RGB, colorRenderable: false, textureFilterable: true, bytesPerElement: [3], type: [UNSIGNED_BYTE$1], }; + t[RGB565$1] = { textureFormat: RGB, colorRenderable: true, textureFilterable: true, bytesPerElement: [3, 2], type: [UNSIGNED_BYTE$1, UNSIGNED_SHORT_5_6_5], }; + t[RGB8_SNORM] = { textureFormat: RGB, colorRenderable: false, textureFilterable: true, bytesPerElement: [3], type: [BYTE], }; + t[R11F_G11F_B10F] = { textureFormat: RGB, colorRenderable: false, textureFilterable: true, bytesPerElement: [12, 6, 4], type: [FLOAT$1, HALF_FLOAT, UNSIGNED_INT_10F_11F_11F_REV], }; + t[RGB9_E5] = { textureFormat: RGB, colorRenderable: false, textureFilterable: true, bytesPerElement: [12, 6, 4], type: [FLOAT$1, HALF_FLOAT, UNSIGNED_INT_5_9_9_9_REV], }; + t[RGB16F] = { textureFormat: RGB, colorRenderable: false, textureFilterable: true, bytesPerElement: [12, 6], type: [FLOAT$1, HALF_FLOAT], }; + t[RGB32F] = { textureFormat: RGB, colorRenderable: false, textureFilterable: false, bytesPerElement: [12], type: [FLOAT$1], }; + t[RGB8UI] = { textureFormat: RGB_INTEGER, colorRenderable: false, textureFilterable: false, bytesPerElement: [3], type: [UNSIGNED_BYTE$1], }; + t[RGB8I] = { textureFormat: RGB_INTEGER, colorRenderable: false, textureFilterable: false, bytesPerElement: [3], type: [BYTE], }; + t[RGB16UI] = { textureFormat: RGB_INTEGER, colorRenderable: false, textureFilterable: false, bytesPerElement: [6], type: [UNSIGNED_SHORT$1], }; + t[RGB16I] = { textureFormat: RGB_INTEGER, colorRenderable: false, textureFilterable: false, bytesPerElement: [6], type: [SHORT], }; + t[RGB32UI] = { textureFormat: RGB_INTEGER, colorRenderable: false, textureFilterable: false, bytesPerElement: [12], type: [UNSIGNED_INT$1], }; + t[RGB32I] = { textureFormat: RGB_INTEGER, colorRenderable: false, textureFilterable: false, bytesPerElement: [12], type: [INT$1], }; + t[RGBA8] = { textureFormat: RGBA$1, colorRenderable: true, textureFilterable: true, bytesPerElement: [4], type: [UNSIGNED_BYTE$1], }; + t[SRGB8_ALPHA8] = { textureFormat: RGBA$1, colorRenderable: true, textureFilterable: true, bytesPerElement: [4], type: [UNSIGNED_BYTE$1], }; + t[RGBA8_SNORM] = { textureFormat: RGBA$1, colorRenderable: false, textureFilterable: true, bytesPerElement: [4], type: [BYTE], }; + t[RGB5_A1$1] = { textureFormat: RGBA$1, colorRenderable: true, textureFilterable: true, bytesPerElement: [4, 2, 4], type: [UNSIGNED_BYTE$1, UNSIGNED_SHORT_5_5_5_1, UNSIGNED_INT_2_10_10_10_REV], }; + t[RGBA4$1] = { textureFormat: RGBA$1, colorRenderable: true, textureFilterable: true, bytesPerElement: [4, 2], type: [UNSIGNED_BYTE$1, UNSIGNED_SHORT_4_4_4_4], }; + t[RGB10_A2] = { textureFormat: RGBA$1, colorRenderable: true, textureFilterable: true, bytesPerElement: [4], type: [UNSIGNED_INT_2_10_10_10_REV], }; + t[RGBA16F] = { textureFormat: RGBA$1, colorRenderable: false, textureFilterable: true, bytesPerElement: [16, 8], type: [FLOAT$1, HALF_FLOAT], }; + t[RGBA32F] = { textureFormat: RGBA$1, colorRenderable: false, textureFilterable: false, bytesPerElement: [16], type: [FLOAT$1], }; + t[RGBA8UI] = { textureFormat: RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [UNSIGNED_BYTE$1], }; + t[RGBA8I] = { textureFormat: RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [BYTE], }; + t[RGB10_A2UI] = { textureFormat: RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [UNSIGNED_INT_2_10_10_10_REV], }; + t[RGBA16UI] = { textureFormat: RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [8], type: [UNSIGNED_SHORT$1], }; + t[RGBA16I] = { textureFormat: RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [8], type: [SHORT], }; + t[RGBA32I] = { textureFormat: RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [16], type: [INT$1], }; + t[RGBA32UI] = { textureFormat: RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [16], type: [UNSIGNED_INT$1], }; + // Sized Internal + t[DEPTH_COMPONENT16$1] = { textureFormat: DEPTH_COMPONENT$1, colorRenderable: true, textureFilterable: false, bytesPerElement: [2, 4], type: [UNSIGNED_SHORT$1, UNSIGNED_INT$1], }; + t[DEPTH_COMPONENT24$1] = { textureFormat: DEPTH_COMPONENT$1, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [UNSIGNED_INT$1], }; + t[DEPTH_COMPONENT32F$1] = { textureFormat: DEPTH_COMPONENT$1, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [FLOAT$1], }; + t[DEPTH24_STENCIL8$1] = { textureFormat: DEPTH_STENCIL$1, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [UNSIGNED_INT_24_8], }; + t[DEPTH32F_STENCIL8$1] = { textureFormat: DEPTH_STENCIL$1, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [FLOAT_32_UNSIGNED_INT_24_8_REV], }; + + Object.keys(t).forEach(function(internalFormat) { + const info = t[internalFormat]; + info.bytesPerElementMap = {}; + info.bytesPerElement.forEach(function(bytesPerElement, ndx) { + const type = info.type[ndx]; + info.bytesPerElementMap[type] = bytesPerElement; + }); + }); + s_textureInternalFormatInfo = t; + } + return s_textureInternalFormatInfo[internalFormat]; +} + +/** + * Gets the number of bytes per element for a given internalFormat / type + * @param {number} internalFormat The internalFormat parameter from texImage2D etc.. + * @param {number} type The type parameter for texImage2D etc.. + * @return {number} the number of bytes per element for the given internalFormat, type combo + * @memberOf module:twgl/textures + */ +function getBytesPerElementForInternalFormat(internalFormat, type) { + const info = getTextureInternalFormatInfo(internalFormat); + if (!info) { + throw "unknown internal format"; + } + const bytesPerElement = info.bytesPerElementMap[type]; + if (bytesPerElement === undefined) { + throw "unknown internal format"; + } + return bytesPerElement; +} + +/** + * Info related to a specific texture internalFormat as returned + * from {@link module:twgl/textures.getFormatAndTypeForInternalFormat}. + * + * @typedef {Object} TextureFormatInfo + * @property {number} format Format to pass to texImage2D and related functions + * @property {number} type Type to pass to texImage2D and related functions + * @memberOf module:twgl/textures + */ + +/** + * Gets the format and type for a given internalFormat + * + * @param {number} internalFormat The internal format + * @return {module:twgl/textures.TextureFormatInfo} the corresponding format and type, + * @memberOf module:twgl/textures + */ +function getFormatAndTypeForInternalFormat(internalFormat) { + const info = getTextureInternalFormatInfo(internalFormat); + if (!info) { + throw "unknown internal format"; + } + return { + format: info.textureFormat, + type: info.type[0], + }; +} + +/** + * Returns true if value is power of 2 + * @param {number} value number to check. + * @return true if value is power of 2 + * @private + */ +function isPowerOf2(value) { + return (value & (value - 1)) === 0; +} + +/** + * Gets whether or not we can generate mips for the given + * internal format. + * + * @param {WebGLRenderingContext} gl the WebGLRenderingContext + * @param {number} width The width parameter from texImage2D etc.. + * @param {number} height The height parameter from texImage2D etc.. + * @param {number} internalFormat The internalFormat parameter from texImage2D etc.. + * @return {boolean} true if we can generate mips + * @memberOf module:twgl/textures + */ +function canGenerateMipmap(gl, width, height, internalFormat) { + if (!isWebGL2(gl)) { + return isPowerOf2(width) && isPowerOf2(height); + } + const info = getTextureInternalFormatInfo(internalFormat); + if (!info) { + throw "unknown internal format"; + } + return info.colorRenderable && info.textureFilterable; +} + +/** + * Gets whether or not we can generate mips for the given format + * @param {number} internalFormat The internalFormat parameter from texImage2D etc.. + * @return {boolean} true if we can generate mips + * @memberOf module:twgl/textures + */ +function canFilter(internalFormat) { + const info = getTextureInternalFormatInfo(internalFormat); + if (!info) { + throw "unknown internal format"; + } + return info.textureFilterable; +} + +/** + * Gets the number of components for a given image format. + * @param {number} format the format. + * @return {number} the number of components for the format. + * @memberOf module:twgl/textures + */ +function getNumComponentsForFormat(format) { + const info = formatInfo[format]; + if (!info) { + throw "unknown format: " + format; + } + return info.numColorComponents; +} + +/** + * Gets the texture type for a given array type. + * @param {WebGLRenderingContext} gl the WebGLRenderingContext + * @return {number} the gl texture type + * @private + */ +function getTextureTypeForArrayType(gl, src, defaultType) { + if (isArrayBuffer(src)) { + return getGLTypeForTypedArray(src); + } + return defaultType || UNSIGNED_BYTE$1; +} + +function guessDimensions(gl, target, width, height, numElements) { + if (numElements % 1 !== 0) { + throw "can't guess dimensions"; + } + if (!width && !height) { + const size = Math.sqrt(numElements / (target === TEXTURE_CUBE_MAP$1 ? 6 : 1)); + if (size % 1 === 0) { + width = size; + height = size; + } else { + width = numElements; + height = 1; + } + } else if (!height) { + height = numElements / width; + if (height % 1) { + throw "can't guess dimensions"; + } + } else if (!width) { + width = numElements / height; + if (width % 1) { + throw "can't guess dimensions"; + } + } + return { + width: width, + height: height, + }; +} + +/** + * Sets the default texture color. + * + * The default texture color is used when loading textures from + * urls. Because the URL will be loaded async we'd like to be + * able to use the texture immediately. By putting a 1x1 pixel + * color in the texture we can start using the texture before + * the URL has loaded. + * + * @param {number[]} color Array of 4 values in the range 0 to 1 + * @deprecated see {@link module:twgl.setDefaults} + * @memberOf module:twgl/textures + */ +function setDefaultTextureColor(color) { + defaults$1.textureColor = new Uint8Array([color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255]); +} + +function setDefaults$1(newDefaults) { + copyExistingProperties(newDefaults, defaults$1); + if (newDefaults.textureColor) { + setDefaultTextureColor(newDefaults.textureColor); + } +} + +/** + * A function to generate the source for a texture. + * @callback TextureFunc + * @param {WebGLRenderingContext} gl A WebGLRenderingContext + * @param {module:twgl.TextureOptions} options the texture options + * @return {*} Returns any of the things documented for `src` for {@link module:twgl.TextureOptions}. + * @memberOf module:twgl + */ + +/** + * Texture options passed to most texture functions. Each function will use whatever options + * are appropriate for its needs. This lets you pass the same options to all functions. + * + * Note: A `TexImageSource` is defined in the WebGL spec as a `HTMLImageElement`, `HTMLVideoElement`, + * `HTMLCanvasElement`, `ImageBitmap`, or `ImageData`. + * + * @typedef {Object} TextureOptions + * @property {number} [target] the type of texture `gl.TEXTURE_2D` or `gl.TEXTURE_CUBE_MAP`. Defaults to `gl.TEXTURE_2D`. + * @property {number} [level] the mip level to affect. Defaults to 0. Note, if set auto will be considered false unless explicitly set to true. + * @property {number} [width] the width of the texture. Only used if src is an array or typed array or null. + * @property {number} [height] the height of a texture. Only used if src is an array or typed array or null. + * @property {number} [depth] the depth of a texture. Only used if src is an array or type array or null and target is `TEXTURE_3D` . + * @property {number} [min] the min filter setting (eg. `gl.LINEAR`). Defaults to `gl.NEAREST_MIPMAP_LINEAR` + * or if texture is not a power of 2 on both dimensions then defaults to `gl.LINEAR`. + * @property {number} [mag] the mag filter setting (eg. `gl.LINEAR`). Defaults to `gl.LINEAR` + * @property {number} [minMag] both the min and mag filter settings. + * @property {number} [internalFormat] internal format for texture. Defaults to `gl.RGBA` + * @property {number} [format] format for texture. Defaults to `gl.RGBA`. + * @property {number} [type] type for texture. Defaults to `gl.UNSIGNED_BYTE` unless `src` is ArrayBufferView. If `src` + * is ArrayBufferView defaults to type that matches ArrayBufferView type. + * @property {number} [wrap] Texture wrapping for both S and T (and R if TEXTURE_3D or WebGLSampler). Defaults to `gl.REPEAT` for 2D unless src is WebGL1 and src not npot and `gl.CLAMP_TO_EDGE` for cube + * @property {number} [wrapS] Texture wrapping for S. Defaults to `gl.REPEAT` and `gl.CLAMP_TO_EDGE` for cube. If set takes precedence over `wrap`. + * @property {number} [wrapT] Texture wrapping for T. Defaults to `gl.REPEAT` and `gl.CLAMP_TO_EDGE` for cube. If set takes precedence over `wrap`. + * @property {number} [wrapR] Texture wrapping for R. Defaults to `gl.REPEAT` and `gl.CLAMP_TO_EDGE` for cube. If set takes precedence over `wrap`. + * @property {number} [minLod] TEXTURE_MIN_LOD setting + * @property {number} [maxLod] TEXTURE_MAX_LOD setting + * @property {number} [baseLevel] TEXTURE_BASE_LEVEL setting + * @property {number} [maxLevel] TEXTURE_MAX_LEVEL setting + * @property {number} [unpackAlignment] The `gl.UNPACK_ALIGNMENT` used when uploading an array. Defaults to 1. + * @property {number[]|ArrayBufferView} [color] Color to initialize this texture with if loading an image asynchronously. + * The default use a blue 1x1 pixel texture. You can set another default by calling `twgl.setDefaults` + * or you can set an individual texture's initial color by setting this property. Example: `[1, .5, .5, 1]` = pink + * @property {number} [premultiplyAlpha] Whether or not to premultiply alpha. Defaults to whatever the current setting is. + * This lets you set it once before calling `twgl.createTexture` or `twgl.createTextures` and only override + * the current setting for specific textures. + * @property {number} [flipY] Whether or not to flip the texture vertically on upload. Defaults to whatever the current setting is. + * This lets you set it once before calling `twgl.createTexture` or `twgl.createTextures` and only override + * the current setting for specific textures. + * @property {number} [colorspaceConversion] Whether or not to let the browser do colorspace conversion of the texture on upload. Defaults to whatever the current setting is. + * This lets you set it once before calling `twgl.createTexture` or `twgl.createTextures` and only override + * the current setting for specific textures. + * @property {boolean} [auto] If `undefined` or `true`, in WebGL1, texture filtering is set automatically for non-power of 2 images and + * mips are generated for power of 2 images. In WebGL2 mips are generated if they can be. Note: if `level` is set above + * then then `auto` is assumed to be `false` unless explicity set to `true`. + * @property {number[]} [cubeFaceOrder] The order that cube faces are pulled out of an img or set of images. The default is + * + * [gl.TEXTURE_CUBE_MAP_POSITIVE_X, + * gl.TEXTURE_CUBE_MAP_NEGATIVE_X, + * gl.TEXTURE_CUBE_MAP_POSITIVE_Y, + * gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, + * gl.TEXTURE_CUBE_MAP_POSITIVE_Z, + * gl.TEXTURE_CUBE_MAP_NEGATIVE_Z] + * + * @property {(number[]|ArrayBufferView|TexImageSource|TexImageSource[]|string|string[]|module:twgl.TextureFunc)} [src] source for texture + * + * If `string` then it's assumed to be a URL to an image. The image will be downloaded async. A usable + * 1x1 pixel texture will be returned immediately. The texture will be updated once the image has downloaded. + * If `target` is `gl.TEXTURE_CUBE_MAP` will attempt to divide image into 6 square pieces. 1x6, 6x1, 3x2, 2x3. + * The pieces will be uploaded in `cubeFaceOrder` + * + * If `string[]` or `TexImageSource[]` and target is `gl.TEXTURE_CUBE_MAP` then it must have 6 entries, one for each face of a cube map. + * + * If `string[]` or `TexImageSource[]` and target is `gl.TEXTURE_2D_ARRAY` then each entry is a slice of the a 2d array texture + * and will be scaled to the specified width and height OR to the size of the first image that loads. + * + * If `TexImageSource` then it wil be used immediately to create the contents of the texture. Examples `HTMLImageElement`, + * `HTMLCanvasElement`, `HTMLVideoElement`. + * + * If `number[]` or `ArrayBufferView` it's assumed to be data for a texture. If `width` or `height` is + * not specified it is guessed as follows. First the number of elements is computed by `src.length / numComponents` + * where `numComponents` is derived from `format`. If `target` is `gl.TEXTURE_CUBE_MAP` then `numElements` is divided + * by 6. Then + * + * * If neither `width` nor `height` are specified and `sqrt(numElements)` is an integer then width and height + * are set to `sqrt(numElements)`. Otherwise `width = numElements` and `height = 1`. + * + * * If only one of `width` or `height` is specified then the other equals `numElements / specifiedDimension`. + * + * If `number[]` will be converted to `type`. + * + * If `src` is a function it will be called with a `WebGLRenderingContext` and these options. + * Whatever it returns is subject to these rules. So it can return a string url, an `HTMLElement` + * an array etc... + * + * If `src` is undefined then an empty texture will be created of size `width` by `height`. + * + * @property {string} [crossOrigin] What to set the crossOrigin property of images when they are downloaded. + * default: undefined. Also see {@link module:twgl.setDefaults}. + * + * @memberOf module:twgl + */ + +/** + * Sets any packing state that will be set based on the options. + * @param {module:twgl.TextureOptions} options A TextureOptions object with whatever parameters you want set. + * @param {WebGLRenderingContext} gl the WebGLRenderingContext + * @private + */ +function setPackState(gl, options) { + if (options.colorspaceConversion !== undefined) { + gl.pixelStorei(UNPACK_COLORSPACE_CONVERSION_WEBGL, options.colorspaceConversion); + } + if (options.premultiplyAlpha !== undefined) { + gl.pixelStorei(UNPACK_PREMULTIPLY_ALPHA_WEBGL, options.premultiplyAlpha); + } + if (options.flipY !== undefined) { + gl.pixelStorei(UNPACK_FLIP_Y_WEBGL, options.flipY); + } +} + +/** + * Set skip state to defaults + * @param {WebGLRenderingContext} gl the WebGLRenderingContext + * @private + */ +function setSkipStateToDefault(gl) { + gl.pixelStorei(UNPACK_ALIGNMENT, 4); + if (isWebGL2(gl)) { + gl.pixelStorei(UNPACK_ROW_LENGTH, 0); + gl.pixelStorei(UNPACK_IMAGE_HEIGHT, 0); + gl.pixelStorei(UNPACK_SKIP_PIXELS, 0); + gl.pixelStorei(UNPACK_SKIP_ROWS, 0); + gl.pixelStorei(UNPACK_SKIP_IMAGES, 0); + } +} + +/** + * Sets the parameters of a texture or sampler + * @param {WebGLRenderingContext} gl the WebGLRenderingContext + * @param {number|WebGLSampler} target texture target or sampler + * @param {function()} parameteriFn texParameteri or samplerParameteri fn + * @param {WebGLTexture} tex the WebGLTexture to set parameters for + * @param {module:twgl.TextureOptions} options A TextureOptions object with whatever parameters you want set. + * This is often the same options you passed in when you created the texture. + * @private + */ +function setTextureSamplerParameters(gl, target, parameteriFn, options) { + if (options.minMag) { + parameteriFn.call(gl, target, TEXTURE_MIN_FILTER, options.minMag); + parameteriFn.call(gl, target, TEXTURE_MAG_FILTER, options.minMag); + } + if (options.min) { + parameteriFn.call(gl, target, TEXTURE_MIN_FILTER, options.min); + } + if (options.mag) { + parameteriFn.call(gl, target, TEXTURE_MAG_FILTER, options.mag); + } + if (options.wrap) { + parameteriFn.call(gl, target, TEXTURE_WRAP_S, options.wrap); + parameteriFn.call(gl, target, TEXTURE_WRAP_T, options.wrap); + if (target === TEXTURE_3D$1 || isSampler(gl, target)) { + parameteriFn.call(gl, target, TEXTURE_WRAP_R, options.wrap); + } + } + if (options.wrapR) { + parameteriFn.call(gl, target, TEXTURE_WRAP_R, options.wrapR); + } + if (options.wrapS) { + parameteriFn.call(gl, target, TEXTURE_WRAP_S, options.wrapS); + } + if (options.wrapT) { + parameteriFn.call(gl, target, TEXTURE_WRAP_T, options.wrapT); + } + if (options.minLod) { + parameteriFn.call(gl, target, TEXTURE_MIN_LOD, options.minLod); + } + if (options.maxLod) { + parameteriFn.call(gl, target, TEXTURE_MAX_LOD, options.maxLod); + } + if (options.baseLevel) { + parameteriFn.call(gl, target, TEXTURE_BASE_LEVEL, options.baseLevel); + } + if (options.maxLevel) { + parameteriFn.call(gl, target, TEXTURE_MAX_LEVEL, options.maxLevel); + } +} + +/** + * Sets the texture parameters of a texture. + * @param {WebGLRenderingContext} gl the WebGLRenderingContext + * @param {WebGLTexture} tex the WebGLTexture to set parameters for + * @param {module:twgl.TextureOptions} options A TextureOptions object with whatever parameters you want set. + * This is often the same options you passed in when you created the texture. + * @memberOf module:twgl/textures + */ +function setTextureParameters(gl, tex, options) { + const target = options.target || TEXTURE_2D$2; + gl.bindTexture(target, tex); + setTextureSamplerParameters(gl, target, gl.texParameteri, options); +} + +/** + * Sets the sampler parameters of a sampler. + * @param {WebGLRenderingContext} gl the WebGLRenderingContext + * @param {WebGLSampler} sampler the WebGLSampler to set parameters for + * @param {module:twgl.TextureOptions} options A TextureOptions object with whatever parameters you want set. + * @memberOf module:twgl/textures + */ +function setSamplerParameters(gl, sampler, options) { + setTextureSamplerParameters(gl, sampler, gl.samplerParameteri, options); +} + +/** + * Creates a new sampler object and sets parameters. + * + * Example: + * + * const sampler = twgl.createSampler(gl, { + * minMag: gl.NEAREST, // sets both TEXTURE_MIN_FILTER and TEXTURE_MAG_FILTER + * wrap: gl.CLAMP_TO_NEAREST, // sets both TEXTURE_WRAP_S and TEXTURE_WRAP_T and TEXTURE_WRAP_R + * }); + * + * @param {WebGLRenderingContext} gl the WebGLRenderingContext + * @param {Object.} options A object of TextureOptions one per sampler. + * @return {Object.} the created samplers by name + * @private + */ +function createSampler(gl, options) { + const sampler = gl.createSampler(); + setSamplerParameters(gl, sampler, options); + return sampler; +} + +/** + * Creates a multiple sampler objects and sets parameters on each. + * + * Example: + * + * const samplers = twgl.createSamplers(gl, { + * nearest: { + * minMag: gl.NEAREST, + * }, + * nearestClampS: { + * minMag: gl.NEAREST, + * wrapS: gl.CLAMP_TO_NEAREST, + * }, + * linear: { + * minMag: gl.LINEAR, + * }, + * nearestClamp: { + * minMag: gl.NEAREST, + * wrap: gl.CLAMP_TO_EDGE, + * }, + * linearClamp: { + * minMag: gl.LINEAR, + * wrap: gl.CLAMP_TO_EDGE, + * }, + * linearClampT: { + * minMag: gl.LINEAR, + * wrapT: gl.CLAMP_TO_EDGE, + * }, + * }); + * + * @param {WebGLRenderingContext} gl the WebGLRenderingContext + * @param {module:twgl.TextureOptions} [options] A TextureOptions object with whatever parameters you want set on the sampler + * @private + */ +function createSamplers(gl, samplerOptions) { + const samplers = {}; + Object.keys(samplerOptions).forEach(function(name) { + samplers[name] = createSampler(gl, samplerOptions[name]); + }); + return samplers; +} + +/** + * Makes a 1x1 pixel + * If no color is passed in uses the default color which can be set by calling `setDefaultTextureColor`. + * @param {(number[]|ArrayBufferView)} [color] The color using 0-1 values + * @return {Uint8Array} Unit8Array with color. + * @private + */ +function make1Pixel(color) { + color = color || defaults$1.textureColor; + if (isArrayBuffer(color)) { + return color; + } + return new Uint8Array([color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255]); +} + +/** + * Sets filtering or generates mips for texture based on width or height + * If width or height is not passed in uses `options.width` and//or `options.height` + * + * @param {WebGLRenderingContext} gl the WebGLRenderingContext + * @param {WebGLTexture} tex the WebGLTexture to set parameters for + * @param {module:twgl.TextureOptions} [options] A TextureOptions object with whatever parameters you want set. + * This is often the same options you passed in when you created the texture. + * @param {number} [width] width of texture + * @param {number} [height] height of texture + * @param {number} [internalFormat] The internalFormat parameter from texImage2D etc.. + * @memberOf module:twgl/textures + */ +function setTextureFilteringForSize(gl, tex, options, width, height, internalFormat) { + options = options || defaults$1.textureOptions; + internalFormat = internalFormat || RGBA$1; + const target = options.target || TEXTURE_2D$2; + width = width || options.width; + height = height || options.height; + gl.bindTexture(target, tex); + if (canGenerateMipmap(gl, width, height, internalFormat)) { + gl.generateMipmap(target); + } else { + const filtering = canFilter(internalFormat) ? LINEAR$1 : NEAREST; + gl.texParameteri(target, TEXTURE_MIN_FILTER, filtering); + gl.texParameteri(target, TEXTURE_MAG_FILTER, filtering); + gl.texParameteri(target, TEXTURE_WRAP_S, CLAMP_TO_EDGE$1); + gl.texParameteri(target, TEXTURE_WRAP_T, CLAMP_TO_EDGE$1); + } +} + +function shouldAutomaticallySetTextureFilteringForSize(options) { + return options.auto === true || (options.auto === undefined && options.level === undefined); +} + +/** + * Gets an array of cubemap face enums + * @param {WebGLRenderingContext} gl the WebGLRenderingContext + * @param {module:twgl.TextureOptions} options A TextureOptions object with whatever parameters you want set. + * This is often the same options you passed in when you created the texture. + * @return {number[]} cubemap face enums + * @private + */ +function getCubeFaceOrder(gl, options) { + options = options || {}; + return options.cubeFaceOrder || [ + TEXTURE_CUBE_MAP_POSITIVE_X, + TEXTURE_CUBE_MAP_NEGATIVE_X, + TEXTURE_CUBE_MAP_POSITIVE_Y, + TEXTURE_CUBE_MAP_NEGATIVE_Y, + TEXTURE_CUBE_MAP_POSITIVE_Z, + TEXTURE_CUBE_MAP_NEGATIVE_Z, + ]; +} + +/** + * @typedef {Object} FaceInfo + * @property {number} face gl enum for texImage2D + * @property {number} ndx face index (0 - 5) into source data + * @ignore + */ + +/** + * Gets an array of FaceInfos + * There's a bug in some NVidia drivers that will crash the driver if + * `gl.TEXTURE_CUBE_MAP_POSITIVE_X` is not uploaded first. So, we take + * the user's desired order from his faces to WebGL and make sure we + * do the faces in WebGL order + * + * @param {WebGLRenderingContext} gl the WebGLRenderingContext + * @param {module:twgl.TextureOptions} options A TextureOptions object with whatever parameters you want set. + * @return {FaceInfo[]} cubemap face infos. Arguably the `face` property of each element is redundant but + * it's needed internally to sort the array of `ndx` properties by `face`. + * @private + */ +function getCubeFacesWithNdx(gl, options) { + const faces = getCubeFaceOrder(gl, options); + // work around bug in NVidia drivers. We have to upload the first face first else the driver crashes :( + const facesWithNdx = faces.map(function(face, ndx) { + return { face: face, ndx: ndx }; + }); + facesWithNdx.sort(function(a, b) { + return a.face - b.face; + }); + return facesWithNdx; +} + +/** + * Set a texture from the contents of an element. Will also set + * texture filtering or generate mips based on the dimensions of the element + * unless `options.auto === false`. If `target === gl.TEXTURE_CUBE_MAP` will + * attempt to slice image into 1x6, 2x3, 3x2, or 6x1 images, one for each face. + * @param {WebGLRenderingContext} gl the WebGLRenderingContext + * @param {WebGLTexture} tex the WebGLTexture to set parameters for + * @param {HTMLElement} element a canvas, img, or video element. + * @param {module:twgl.TextureOptions} [options] A TextureOptions object with whatever parameters you want set. + * This is often the same options you passed in when you created the texture. + * @memberOf module:twgl/textures + * @kind function + */ +function setTextureFromElement(gl, tex, element, options) { + options = options || defaults$1.textureOptions; + const target = options.target || TEXTURE_2D$2; + const level = options.level || 0; + let width = element.width; + let height = element.height; + const internalFormat = options.internalFormat || options.format || RGBA$1; + const formatType = getFormatAndTypeForInternalFormat(internalFormat); + const format = options.format || formatType.format; + const type = options.type || formatType.type; + setPackState(gl, options); + gl.bindTexture(target, tex); + if (target === TEXTURE_CUBE_MAP$1) { + // guess the parts + const imgWidth = element.width; + const imgHeight = element.height; + let size; + let slices; + if (imgWidth / 6 === imgHeight) { + // It's 6x1 + size = imgHeight; + slices = [0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0]; + } else if (imgHeight / 6 === imgWidth) { + // It's 1x6 + size = imgWidth; + slices = [0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5]; + } else if (imgWidth / 3 === imgHeight / 2) { + // It's 3x2 + size = imgWidth / 3; + slices = [0, 0, 1, 0, 2, 0, 0, 1, 1, 1, 2, 1]; + } else if (imgWidth / 2 === imgHeight / 3) { + // It's 2x3 + size = imgWidth / 2; + slices = [0, 0, 1, 0, 0, 1, 1, 1, 0, 2, 1, 2]; + } else { + throw "can't figure out cube map from element: " + (element.src ? element.src : element.nodeName); + } + const ctx = getShared2DContext(); + if (ctx) { + ctx.canvas.width = size; + ctx.canvas.height = size; + width = size; + height = size; + getCubeFacesWithNdx(gl, options).forEach(function(f) { + const xOffset = slices[f.ndx * 2 + 0] * size; + const yOffset = slices[f.ndx * 2 + 1] * size; + ctx.drawImage(element, xOffset, yOffset, size, size, 0, 0, size, size); + gl.texImage2D(f.face, level, internalFormat, format, type, ctx.canvas); + }); + // Free up the canvas memory + ctx.canvas.width = 1; + ctx.canvas.height = 1; + } else if (typeof createImageBitmap !== 'undefined') { + // NOTE: It seems like we should prefer ImageBitmap because unlike canvas it's + // note lossy? (alpha is not premultiplied? although I'm not sure what + width = size; + height = size; + getCubeFacesWithNdx(gl, options).forEach(function(f) { + const xOffset = slices[f.ndx * 2 + 0] * size; + const yOffset = slices[f.ndx * 2 + 1] * size; + // We can't easily use a default texture color here as it would have to match + // the type across all faces where as with a 2D one there's only one face + // so we're replacing everything all at once. It also has to be the correct size. + // On the other hand we need all faces to be the same size so as one face loads + // the rest match else the texture will be un-renderable. + gl.texImage2D(f.face, level, internalFormat, size, size, 0, format, type, null); + createImageBitmap(element, xOffset, yOffset, size, size, { + premultiplyAlpha: 'none', + colorSpaceConversion: 'none', + }) + .then(function(imageBitmap) { + setPackState(gl, options); + gl.bindTexture(target, tex); + gl.texImage2D(f.face, level, internalFormat, format, type, imageBitmap); + if (shouldAutomaticallySetTextureFilteringForSize(options)) { + setTextureFilteringForSize(gl, tex, options, width, height, internalFormat); + } + }); + }); + } + } else if (target === TEXTURE_3D$1 || target === TEXTURE_2D_ARRAY$1) { + const smallest = Math.min(element.width, element.height); + const largest = Math.max(element.width, element.height); + const depth = largest / smallest; + if (depth % 1 !== 0) { + throw "can not compute 3D dimensions of element"; + } + const xMult = element.width === largest ? 1 : 0; + const yMult = element.height === largest ? 1 : 0; + gl.pixelStorei(UNPACK_ALIGNMENT, 1); + gl.pixelStorei(UNPACK_ROW_LENGTH, element.width); + gl.pixelStorei(UNPACK_IMAGE_HEIGHT, 0); + gl.pixelStorei(UNPACK_SKIP_IMAGES, 0); + gl.texImage3D(target, level, internalFormat, smallest, smallest, smallest, 0, format, type, null); + for (let d = 0; d < depth; ++d) { + const srcX = d * smallest * xMult; + const srcY = d * smallest * yMult; + gl.pixelStorei(UNPACK_SKIP_PIXELS, srcX); + gl.pixelStorei(UNPACK_SKIP_ROWS, srcY); + gl.texSubImage3D(target, level, 0, 0, d, smallest, smallest, 1, format, type, element); + } + setSkipStateToDefault(gl); + } else { + gl.texImage2D(target, level, internalFormat, format, type, element); + } + if (shouldAutomaticallySetTextureFilteringForSize(options)) { + setTextureFilteringForSize(gl, tex, options, width, height, internalFormat); + } + setTextureParameters(gl, tex, options); +} + +function noop() { +} + +/** + * Checks whether the url's origin is the same so that we can set the `crossOrigin` + * @param {string} url url to image + * @returns {boolean} true if the window's origin is the same as image's url + * @private + */ +function urlIsSameOrigin(url) { + if (typeof document !== 'undefined') { + // for IE really + const a = document.createElement('a'); + a.href = url; + return a.hostname === location.hostname && + a.port === location.port && + a.protocol === location.protocol; + } else { + const localOrigin = (new URL(location.href)).origin; + const urlOrigin = (new URL(url, location.href)).origin; + return urlOrigin === localOrigin; + } +} + +function setToAnonymousIfUndefinedAndURLIsNotSameOrigin(url, crossOrigin) { + return crossOrigin === undefined && !urlIsSameOrigin(url) + ? 'anonymous' + : crossOrigin; +} + +/** + * Loads an image + * @param {string} url url to image + * @param {string} crossOrigin + * @param {function(err, img)} [callback] a callback that's passed an error and the image. The error will be non-null + * if there was an error + * @return {HTMLImageElement} the image being loaded. + * @private + */ +function loadImage(url, crossOrigin, callback) { + callback = callback || noop; + let img; + crossOrigin = crossOrigin !== undefined ? crossOrigin : defaults$1.crossOrigin; + crossOrigin = setToAnonymousIfUndefinedAndURLIsNotSameOrigin(url, crossOrigin); + if (typeof Image !== 'undefined') { + img = new Image(); + if (crossOrigin !== undefined) { + img.crossOrigin = crossOrigin; + } + + const clearEventHandlers = function clearEventHandlers() { + img.removeEventListener('error', onError); // eslint-disable-line + img.removeEventListener('load', onLoad); // eslint-disable-line + img = null; + }; + + const onError = function onError() { + const msg = "couldn't load image: " + url; + error$1(msg); + callback(msg, img); + clearEventHandlers(); + }; + + const onLoad = function onLoad() { + callback(null, img); + clearEventHandlers(); + }; + + img.addEventListener('error', onError); + img.addEventListener('load', onLoad); + img.src = url; + return img; + } else if (typeof ImageBitmap !== 'undefined') { + let err; + let bm; + const cb = function cb() { + callback(err, bm); + }; + + const options = {}; + if (crossOrigin) { + options.mode = 'cors'; // TODO: not sure how to translate image.crossOrigin + } + fetch(url, options).then(function(response) { + if (!response.ok) { + throw response; + } + return response.blob(); + }).then(function(blob) { + return createImageBitmap(blob, { + premultiplyAlpha: 'none', + colorSpaceConversion: 'none', + }); + }).then(function(bitmap) { + // not sure if this works. We don't want + // to catch the user's error. So, call + // the callback in a timeout so we're + // not in this scope inside the promise. + bm = bitmap; + setTimeout(cb); + }).catch(function(e) { + err = e; + setTimeout(cb); + }); + img = null; + } + return img; +} + +/** + * check if object is a TexImageSource + * + * @param {Object} obj Object to test + * @return {boolean} true if object is a TexImageSource + * @private + */ +function isTexImageSource(obj) { + return (typeof ImageBitmap !== 'undefined' && obj instanceof ImageBitmap) || + (typeof ImageData !== 'undefined' && obj instanceof ImageData) || + (typeof HTMLElement !== 'undefined' && obj instanceof HTMLElement); +} + +/** + * if obj is an TexImageSource then just + * uses it otherwise if obj is a string + * then load it first. + * + * @param {string|TexImageSource} obj + * @param {string} crossOrigin + * @param {function(err, img)} [callback] a callback that's passed an error and the image. The error will be non-null + * if there was an error + * @private + */ +function loadAndUseImage(obj, crossOrigin, callback) { + if (isTexImageSource(obj)) { + setTimeout(function() { + callback(null, obj); + }); + return obj; + } + + return loadImage(obj, crossOrigin, callback); +} + +/** + * Sets a texture to a 1x1 pixel color. If `options.color === false` is nothing happens. If it's not set + * the default texture color is used which can be set by calling `setDefaultTextureColor`. + * @param {WebGLRenderingContext} gl the WebGLRenderingContext + * @param {WebGLTexture} tex the WebGLTexture to set parameters for + * @param {module:twgl.TextureOptions} [options] A TextureOptions object with whatever parameters you want set. + * This is often the same options you passed in when you created the texture. + * @memberOf module:twgl/textures + * @private + */ +function setTextureTo1PixelColor(gl, tex, options) { + options = options || defaults$1.textureOptions; + const target = options.target || TEXTURE_2D$2; + gl.bindTexture(target, tex); + if (options.color === false) { + return; + } + // Assume it's a URL + // Put 1x1 pixels in texture. That makes it renderable immediately regardless of filtering. + const color = make1Pixel(options.color); + if (target === TEXTURE_CUBE_MAP$1) { + for (let ii = 0; ii < 6; ++ii) { + gl.texImage2D(TEXTURE_CUBE_MAP_POSITIVE_X + ii, 0, RGBA$1, 1, 1, 0, RGBA$1, UNSIGNED_BYTE$1, color); + } + } else if (target === TEXTURE_3D$1 || target === TEXTURE_2D_ARRAY$1) { + gl.texImage3D(target, 0, RGBA$1, 1, 1, 1, 0, RGBA$1, UNSIGNED_BYTE$1, color); + } else { + gl.texImage2D(target, 0, RGBA$1, 1, 1, 0, RGBA$1, UNSIGNED_BYTE$1, color); + } +} + +/** + * The src image(s) used to create a texture. + * + * When you call {@link module:twgl.createTexture} or {@link module:twgl.createTextures} + * you can pass in urls for images to load into the textures. If it's a single url + * then this will be a single HTMLImageElement. If it's an array of urls used for a cubemap + * this will be a corresponding array of images for the cubemap. + * + * @typedef {HTMLImageElement|HTMLImageElement[]} TextureSrc + * @memberOf module:twgl + */ + +/** + * A callback for when an image finished downloading and been uploaded into a texture + * @callback TextureReadyCallback + * @param {*} err If truthy there was an error. + * @param {WebGLTexture} texture the texture. + * @param {module:twgl.TextureSrc} source image(s) used to as the src for the texture + * @memberOf module:twgl + */ + +/** + * A callback for when all images have finished downloading and been uploaded into their respective textures + * @callback TexturesReadyCallback + * @param {*} err If truthy there was an error. + * @param {Object.} textures the created textures by name. Same as returned by {@link module:twgl.createTextures}. + * @param {Object.} sources the image(s) used for the texture by name. + * @memberOf module:twgl + */ + +/** + * A callback for when an image finished downloading and been uploaded into a texture + * @callback CubemapReadyCallback + * @param {*} err If truthy there was an error. + * @param {WebGLTexture} tex the texture. + * @param {HTMLImageElement[]} imgs the images for each face. + * @memberOf module:twgl + */ + +/** + * A callback for when an image finished downloading and been uploaded into a texture + * @callback ThreeDReadyCallback + * @param {*} err If truthy there was an error. + * @param {WebGLTexture} tex the texture. + * @param {HTMLImageElement[]} imgs the images for each slice. + * @memberOf module:twgl + */ + +/** + * Loads a texture from an image from a Url as specified in `options.src` + * If `options.color !== false` will set the texture to a 1x1 pixel color so that the texture is + * immediately useable. It will be updated with the contents of the image once the image has finished + * downloading. Filtering options will be set as appropriate for image unless `options.auto === false`. + * @param {WebGLRenderingContext} gl the WebGLRenderingContext + * @param {WebGLTexture} tex the WebGLTexture to set parameters for + * @param {module:twgl.TextureOptions} [options] A TextureOptions object with whatever parameters you want set. + * @param {module:twgl.TextureReadyCallback} [callback] A function to be called when the image has finished loading. err will + * be non null if there was an error. + * @return {HTMLImageElement} the image being downloaded. + * @memberOf module:twgl/textures + */ +function loadTextureFromUrl(gl, tex, options, callback) { + callback = callback || noop; + options = options || defaults$1.textureOptions; + setTextureTo1PixelColor(gl, tex, options); + // Because it's async we need to copy the options. + options = Object.assign({}, options); + const img = loadAndUseImage(options.src, options.crossOrigin, function(err, img) { + if (err) { + callback(err, tex, img); + } else { + setTextureFromElement(gl, tex, img, options); + callback(null, tex, img); + } + }); + return img; +} + +/** + * Loads a cubemap from 6 urls or TexImageSources as specified in `options.src`. Will set the cubemap to a 1x1 pixel color + * so that it is usable immediately unless `option.color === false`. + * @param {WebGLRenderingContext} gl the WebGLRenderingContext + * @param {WebGLTexture} tex the WebGLTexture to set parameters for + * @param {module:twgl.TextureOptions} options A TextureOptions object with whatever parameters you want set. + * @param {module:twgl.CubemapReadyCallback} [callback] A function to be called when all the images have finished loading. err will + * be non null if there was an error. + * @memberOf module:twgl/textures + * @private + */ +function loadCubemapFromUrls(gl, tex, options, callback) { + callback = callback || noop; + const urls = options.src; + if (urls.length !== 6) { + throw "there must be 6 urls for a cubemap"; + } + const level = options.level || 0; + const internalFormat = options.internalFormat || options.format || RGBA$1; + const formatType = getFormatAndTypeForInternalFormat(internalFormat); + const format = options.format || formatType.format; + const type = options.type || UNSIGNED_BYTE$1; + const target = options.target || TEXTURE_2D$2; + if (target !== TEXTURE_CUBE_MAP$1) { + throw "target must be TEXTURE_CUBE_MAP"; + } + setTextureTo1PixelColor(gl, tex, options); + // Because it's async we need to copy the options. + options = Object.assign({}, options); + let numToLoad = 6; + const errors = []; + const faces = getCubeFaceOrder(gl, options); + let imgs; // eslint-disable-line + + function uploadImg(faceTarget) { + return function(err, img) { + --numToLoad; + if (err) { + errors.push(err); + } else { + if (img.width !== img.height) { + errors.push("cubemap face img is not a square: " + img.src); + } else { + setPackState(gl, options); + gl.bindTexture(target, tex); + + // So assuming this is the first image we now have one face that's img sized + // and 5 faces that are 1x1 pixel so size the other faces + if (numToLoad === 5) { + // use the default order + getCubeFaceOrder().forEach(function(otherTarget) { + // Should we re-use the same face or a color? + gl.texImage2D(otherTarget, level, internalFormat, format, type, img); + }); + } else { + gl.texImage2D(faceTarget, level, internalFormat, format, type, img); + } + + if (shouldAutomaticallySetTextureFilteringForSize(options)) { + gl.generateMipmap(target); + } + } + } + + if (numToLoad === 0) { + callback(errors.length ? errors : undefined, tex, imgs); + } + }; + } + + imgs = urls.map(function(url, ndx) { + return loadAndUseImage(url, options.crossOrigin, uploadImg(faces[ndx])); + }); +} + +/** + * Loads a 2d array or 3d texture from urls OR TexImageSources as specified in `options.src`. + * Will set the texture to a 1x1 pixel color + * so that it is usable immediately unless `option.color === false`. + * + * If the width and height is not specified the width and height of the first + * image loaded will be used. Note that since images are loaded async + * which image downloads first is unknown. + * + * If an image is not the same size as the width and height it will be scaled + * to that width and height. + * + * @param {WebGLRenderingContext} gl the WebGLRenderingContext + * @param {WebGLTexture} tex the WebGLTexture to set parameters for + * @param {module:twgl.TextureOptions} options A TextureOptions object with whatever parameters you want set. + * @param {module:twgl.ThreeDReadyCallback} [callback] A function to be called when all the images have finished loading. err will + * be non null if there was an error. + * @memberOf module:twgl/textures + * @private + */ +function loadSlicesFromUrls(gl, tex, options, callback) { + callback = callback || noop; + const urls = options.src; + const internalFormat = options.internalFormat || options.format || RGBA$1; + const formatType = getFormatAndTypeForInternalFormat(internalFormat); + const format = options.format || formatType.format; + const type = options.type || UNSIGNED_BYTE$1; + const target = options.target || TEXTURE_2D_ARRAY$1; + if (target !== TEXTURE_3D$1 && target !== TEXTURE_2D_ARRAY$1) { + throw "target must be TEXTURE_3D or TEXTURE_2D_ARRAY"; + } + setTextureTo1PixelColor(gl, tex, options); + // Because it's async we need to copy the options. + options = Object.assign({}, options); + let numToLoad = urls.length; + const errors = []; + let imgs; // eslint-disable-line + const level = options.level || 0; + let width = options.width; + let height = options.height; + const depth = urls.length; + let firstImage = true; + + function uploadImg(slice) { + return function(err, img) { + --numToLoad; + if (err) { + errors.push(err); + } else { + setPackState(gl, options); + gl.bindTexture(target, tex); + + if (firstImage) { + firstImage = false; + width = options.width || img.width; + height = options.height || img.height; + gl.texImage3D(target, level, internalFormat, width, height, depth, 0, format, type, null); + + // put it in every slice otherwise some slices will be 0,0,0,0 + for (let s = 0; s < depth; ++s) { + gl.texSubImage3D(target, level, 0, 0, s, width, height, 1, format, type, img); + } + } else { + let src = img; + let ctx; + if (img.width !== width || img.height !== height) { + // Size the image to fix + ctx = getShared2DContext(); + src = ctx.canvas; + ctx.canvas.width = width; + ctx.canvas.height = height; + ctx.drawImage(img, 0, 0, width, height); + } + + gl.texSubImage3D(target, level, 0, 0, slice, width, height, 1, format, type, src); + + // free the canvas memory + if (ctx && src === ctx.canvas) { + ctx.canvas.width = 0; + ctx.canvas.height = 0; + } + } + + if (shouldAutomaticallySetTextureFilteringForSize(options)) { + gl.generateMipmap(target); + } + } + + if (numToLoad === 0) { + callback(errors.length ? errors : undefined, tex, imgs); + } + }; + } + + imgs = urls.map(function(url, ndx) { + return loadAndUseImage(url, options.crossOrigin, uploadImg(ndx)); + }); +} + +/** + * Sets a texture from an array or typed array. If the width or height is not provided will attempt to + * guess the size. See {@link module:twgl.TextureOptions}. + * @param {WebGLRenderingContext} gl the WebGLRenderingContext + * @param {WebGLTexture} tex the WebGLTexture to set parameters for + * @param {(number[]|ArrayBufferView)} src An array or typed arry with texture data. + * @param {module:twgl.TextureOptions} [options] A TextureOptions object with whatever parameters you want set. + * This is often the same options you passed in when you created the texture. + * @memberOf module:twgl/textures + */ +function setTextureFromArray(gl, tex, src, options) { + options = options || defaults$1.textureOptions; + const target = options.target || TEXTURE_2D$2; + gl.bindTexture(target, tex); + let width = options.width; + let height = options.height; + let depth = options.depth; + const level = options.level || 0; + const internalFormat = options.internalFormat || options.format || RGBA$1; + const formatType = getFormatAndTypeForInternalFormat(internalFormat); + const format = options.format || formatType.format; + const type = options.type || getTextureTypeForArrayType(gl, src, formatType.type); + if (!isArrayBuffer(src)) { + const Type = getTypedArrayTypeForGLType(type); + src = new Type(src); + } else if (src instanceof Uint8ClampedArray) { + src = new Uint8Array(src.buffer); + } + + const bytesPerElement = getBytesPerElementForInternalFormat(internalFormat, type); + const numElements = src.byteLength / bytesPerElement; // TODO: check UNPACK_ALIGNMENT? + if (numElements % 1) { + throw "length wrong size for format: " + glEnumToString(gl, format); + } + let dimensions; + if (target === TEXTURE_3D$1 || target === TEXTURE_2D_ARRAY$1) { + if (!width && !height && !depth) { + const size = Math.cbrt(numElements); + if (size % 1 !== 0) { + throw "can't guess cube size of array of numElements: " + numElements; + } + width = size; + height = size; + depth = size; + } else if (width && (!height || !depth)) { + dimensions = guessDimensions(gl, target, height, depth, numElements / width); + height = dimensions.width; + depth = dimensions.height; + } else if (height && (!width || !depth)) { + dimensions = guessDimensions(gl, target, width, depth, numElements / height); + width = dimensions.width; + depth = dimensions.height; + } else { + dimensions = guessDimensions(gl, target, width, height, numElements / depth); + width = dimensions.width; + height = dimensions.height; + } + } else { + dimensions = guessDimensions(gl, target, width, height, numElements); + width = dimensions.width; + height = dimensions.height; + } + setSkipStateToDefault(gl); + gl.pixelStorei(UNPACK_ALIGNMENT, options.unpackAlignment || 1); + setPackState(gl, options); + if (target === TEXTURE_CUBE_MAP$1) { + const elementsPerElement = bytesPerElement / src.BYTES_PER_ELEMENT; + const faceSize = numElements / 6 * elementsPerElement; + + getCubeFacesWithNdx(gl, options).forEach(f => { + const offset = faceSize * f.ndx; + const data = src.subarray(offset, offset + faceSize); + gl.texImage2D(f.face, level, internalFormat, width, height, 0, format, type, data); + }); + } else if (target === TEXTURE_3D$1 || target === TEXTURE_2D_ARRAY$1) { + gl.texImage3D(target, level, internalFormat, width, height, depth, 0, format, type, src); + } else { + gl.texImage2D(target, level, internalFormat, width, height, 0, format, type, src); + } + return { + width: width, + height: height, + depth: depth, + type: type, + }; +} + +/** + * Sets a texture with no contents of a certain size. In other words calls `gl.texImage2D` with `null`. + * You must set `options.width` and `options.height`. + * @param {WebGLRenderingContext} gl the WebGLRenderingContext + * @param {WebGLTexture} tex the WebGLTexture to set parameters for + * @param {module:twgl.TextureOptions} options A TextureOptions object with whatever parameters you want set. + * @memberOf module:twgl/textures + */ +function setEmptyTexture(gl, tex, options) { + const target = options.target || TEXTURE_2D$2; + gl.bindTexture(target, tex); + const level = options.level || 0; + const internalFormat = options.internalFormat || options.format || RGBA$1; + const formatType = getFormatAndTypeForInternalFormat(internalFormat); + const format = options.format || formatType.format; + const type = options.type || formatType.type; + setPackState(gl, options); + if (target === TEXTURE_CUBE_MAP$1) { + for (let ii = 0; ii < 6; ++ii) { + gl.texImage2D(TEXTURE_CUBE_MAP_POSITIVE_X + ii, level, internalFormat, options.width, options.height, 0, format, type, null); + } + } else if (target === TEXTURE_3D$1 || target === TEXTURE_2D_ARRAY$1) { + gl.texImage3D(target, level, internalFormat, options.width, options.height, options.depth, 0, format, type, null); + } else { + gl.texImage2D(target, level, internalFormat, options.width, options.height, 0, format, type, null); + } +} + +/** + * Creates a texture based on the options passed in. + * + * Note: may reset UNPACK_ALIGNMENT, UNPACK_ROW_LENGTH, UNPACK_IMAGE_HEIGHT, UNPACK_SKIP_IMAGES + * UNPACK_SKIP_PIXELS, and UNPACK_SKIP_ROWS + * + * @param {WebGLRenderingContext} gl the WebGLRenderingContext + * @param {module:twgl.TextureOptions} [options] A TextureOptions object with whatever parameters you want set. + * @param {module:twgl.TextureReadyCallback} [callback] A callback called when an image has been downloaded and uploaded to the texture. + * @return {WebGLTexture} the created texture. + * @memberOf module:twgl/textures + */ +function createTexture(gl, options, callback) { + callback = callback || noop; + options = options || defaults$1.textureOptions; + const tex = gl.createTexture(); + const target = options.target || TEXTURE_2D$2; + let width = options.width || 1; + let height = options.height || 1; + const internalFormat = options.internalFormat || RGBA$1; + gl.bindTexture(target, tex); + if (target === TEXTURE_CUBE_MAP$1) { + // this should have been the default for cubemaps :( + gl.texParameteri(target, TEXTURE_WRAP_S, CLAMP_TO_EDGE$1); + gl.texParameteri(target, TEXTURE_WRAP_T, CLAMP_TO_EDGE$1); + } + let src = options.src; + if (src) { + if (typeof src === "function") { + src = src(gl, options); + } + if (typeof (src) === "string") { + loadTextureFromUrl(gl, tex, options, callback); + } else if (isArrayBuffer(src) || + (Array.isArray(src) && ( + typeof src[0] === 'number' || + Array.isArray(src[0]) || + isArrayBuffer(src[0])) + ) + ) { + const dimensions = setTextureFromArray(gl, tex, src, options); + width = dimensions.width; + height = dimensions.height; + } else if (Array.isArray(src) && (typeof (src[0]) === 'string' || isTexImageSource(src[0]))) { + if (target === TEXTURE_CUBE_MAP$1) { + loadCubemapFromUrls(gl, tex, options, callback); + } else { + loadSlicesFromUrls(gl, tex, options, callback); + } + } else { // if (isTexImageSource(src)) + setTextureFromElement(gl, tex, src, options); + width = src.width; + height = src.height; + } + } else { + setEmptyTexture(gl, tex, options); + } + if (shouldAutomaticallySetTextureFilteringForSize(options)) { + setTextureFilteringForSize(gl, tex, options, width, height, internalFormat); + } + setTextureParameters(gl, tex, options); + return tex; +} + +/** + * Resizes a texture based on the options passed in. + * + * Note: This is not a generic resize anything function. + * It's mostly used by {@link module:twgl.resizeFramebufferInfo} + * It will use `options.src` if it exists to try to determine a `type` + * otherwise it will assume `gl.UNSIGNED_BYTE`. No data is provided + * for the texture. Texture parameters will be set accordingly + * + * @param {WebGLRenderingContext} gl the WebGLRenderingContext + * @param {WebGLTexture} tex the texture to resize + * @param {module:twgl.TextureOptions} options A TextureOptions object with whatever parameters you want set. + * @param {number} [width] the new width. If not passed in will use `options.width` + * @param {number} [height] the new height. If not passed in will use `options.height` + * @param {number} [depth] the new depth. If not passed in will use `options.depth` + * @memberOf module:twgl/textures + */ +function resizeTexture(gl, tex, options, width, height, depth) { + width = width || options.width; + height = height || options.height; + depth = depth || options.depth; + const target = options.target || TEXTURE_2D$2; + gl.bindTexture(target, tex); + const level = options.level || 0; + const internalFormat = options.internalFormat || options.format || RGBA$1; + const formatType = getFormatAndTypeForInternalFormat(internalFormat); + const format = options.format || formatType.format; + let type; + const src = options.src; + if (!src) { + type = options.type || formatType.type; + } else if (isArrayBuffer(src) || (Array.isArray(src) && typeof (src[0]) === 'number')) { + type = options.type || getTextureTypeForArrayType(gl, src, formatType.type); + } else { + type = options.type || formatType.type; + } + if (target === TEXTURE_CUBE_MAP$1) { + for (let ii = 0; ii < 6; ++ii) { + gl.texImage2D(TEXTURE_CUBE_MAP_POSITIVE_X + ii, level, internalFormat, width, height, 0, format, type, null); + } + } else if (target === TEXTURE_3D$1 || target === TEXTURE_2D_ARRAY$1) { + gl.texImage3D(target, level, internalFormat, width, height, depth, 0, format, type, null); + } else { + gl.texImage2D(target, level, internalFormat, width, height, 0, format, type, null); + } +} + +/** + * Check if a src is an async request. + * if src is a string we're going to download an image + * if src is an array of strings we're going to download cubemap images + * @param {*} src The src from a TextureOptions + * @returns {bool} true if src is async. + * @private + */ +function isAsyncSrc(src) { + return typeof src === 'string' || + (Array.isArray(src) && typeof src[0] === 'string'); +} + +/** + * Creates a bunch of textures based on the passed in options. + * + * Example: + * + * const textures = twgl.createTextures(gl, { + * // a power of 2 image + * hftIcon: { src: "images/hft-icon-16.png", mag: gl.NEAREST }, + * // a non-power of 2 image + * clover: { src: "images/clover.jpg" }, + * // From a canvas + * fromCanvas: { src: ctx.canvas }, + * // A cubemap from 6 images + * yokohama: { + * target: gl.TEXTURE_CUBE_MAP, + * src: [ + * 'images/yokohama/posx.jpg', + * 'images/yokohama/negx.jpg', + * 'images/yokohama/posy.jpg', + * 'images/yokohama/negy.jpg', + * 'images/yokohama/posz.jpg', + * 'images/yokohama/negz.jpg', + * ], + * }, + * // A cubemap from 1 image (can be 1x6, 2x3, 3x2, 6x1) + * goldengate: { + * target: gl.TEXTURE_CUBE_MAP, + * src: 'images/goldengate.jpg', + * }, + * // A 2x2 pixel texture from a JavaScript array + * checker: { + * mag: gl.NEAREST, + * min: gl.LINEAR, + * src: [ + * 255,255,255,255, + * 192,192,192,255, + * 192,192,192,255, + * 255,255,255,255, + * ], + * }, + * // a 1x2 pixel texture from a typed array. + * stripe: { + * mag: gl.NEAREST, + * min: gl.LINEAR, + * format: gl.LUMINANCE, + * src: new Uint8Array([ + * 255, + * 128, + * 255, + * 128, + * 255, + * 128, + * 255, + * 128, + * ]), + * width: 1, + * }, + * }); + * + * Now + * + * * `textures.hftIcon` will be a 2d texture + * * `textures.clover` will be a 2d texture + * * `textures.fromCanvas` will be a 2d texture + * * `textures.yohohama` will be a cubemap texture + * * `textures.goldengate` will be a cubemap texture + * * `textures.checker` will be a 2d texture + * * `textures.stripe` will be a 2d texture + * + * @param {WebGLRenderingContext} gl the WebGLRenderingContext + * @param {Object.} options A object of TextureOptions one per texture. + * @param {module:twgl.TexturesReadyCallback} [callback] A callback called when all textures have been downloaded. + * @return {Object.} the created textures by name + * @memberOf module:twgl/textures + */ +function createTextures(gl, textureOptions, callback) { + callback = callback || noop; + let numDownloading = 0; + const errors = []; + const textures = {}; + const images = {}; + + function callCallbackIfReady() { + if (numDownloading === 0) { + setTimeout(function() { + callback(errors.length ? errors : undefined, textures, images); + }, 0); + } + } + + Object.keys(textureOptions).forEach(function(name) { + const options = textureOptions[name]; + let onLoadFn; + if (isAsyncSrc(options.src)) { + onLoadFn = function(err, tex, img) { + images[name] = img; + --numDownloading; + if (err) { + errors.push(err); + } + callCallbackIfReady(); + }; + ++numDownloading; + } + textures[name] = createTexture(gl, options, onLoadFn); + }); + + // queue the callback if there are no images to download. + // We do this because if your code is structured to wait for + // images to download but then you comment out all the async + // images your code would break. + callCallbackIfReady(); + + return textures; +} + +var textures = /*#__PURE__*/Object.freeze({ + __proto__: null, + setTextureDefaults_: setDefaults$1, + createSampler: createSampler, + createSamplers: createSamplers, + setSamplerParameters: setSamplerParameters, + createTexture: createTexture, + setEmptyTexture: setEmptyTexture, + setTextureFromArray: setTextureFromArray, + loadTextureFromUrl: loadTextureFromUrl, + setTextureFromElement: setTextureFromElement, + setTextureFilteringForSize: setTextureFilteringForSize, + setTextureParameters: setTextureParameters, + setDefaultTextureColor: setDefaultTextureColor, + createTextures: createTextures, + resizeTexture: resizeTexture, + canGenerateMipmap: canGenerateMipmap, + canFilter: canFilter, + getNumComponentsForFormat: getNumComponentsForFormat, + getBytesPerElementForInternalFormat: getBytesPerElementForInternalFormat, + getFormatAndTypeForInternalFormat: getFormatAndTypeForInternalFormat +}); + +/* + * Copyright 2019 Gregg Tavares + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * Low level shader program related functions + * + * You should generally not need to use these functions. They are provided + * for those cases where you're doing something out of the ordinary + * and you need lower level access. + * + * For backward compatibility they are available at both `twgl.programs` and `twgl` + * itself + * + * See {@link module:twgl} for core functions + * + * @module twgl/programs + */ + +const error = error$1; +const warn = warn$1; +function getElementById(id) { + return (typeof document !== 'undefined' && document.getElementById) + ? document.getElementById(id) + : null; +} + +const TEXTURE0 = 0x84c0; +const DYNAMIC_DRAW = 0x88e8; + +const ARRAY_BUFFER = 0x8892; +const ELEMENT_ARRAY_BUFFER$1 = 0x8893; +const UNIFORM_BUFFER = 0x8a11; +const TRANSFORM_FEEDBACK_BUFFER = 0x8c8e; + +const TRANSFORM_FEEDBACK = 0x8e22; + +const COMPILE_STATUS = 0x8b81; +const LINK_STATUS = 0x8b82; +const FRAGMENT_SHADER = 0x8b30; +const VERTEX_SHADER = 0x8b31; +const SEPARATE_ATTRIBS = 0x8c8d; + +const ACTIVE_UNIFORMS = 0x8b86; +const ACTIVE_ATTRIBUTES = 0x8b89; +const TRANSFORM_FEEDBACK_VARYINGS = 0x8c83; +const ACTIVE_UNIFORM_BLOCKS = 0x8a36; +const UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER = 0x8a44; +const UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER = 0x8a46; +const UNIFORM_BLOCK_DATA_SIZE = 0x8a40; +const UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES = 0x8a43; + +const FLOAT = 0x1406; +const FLOAT_VEC2 = 0x8B50; +const FLOAT_VEC3 = 0x8B51; +const FLOAT_VEC4 = 0x8B52; +const INT = 0x1404; +const INT_VEC2 = 0x8B53; +const INT_VEC3 = 0x8B54; +const INT_VEC4 = 0x8B55; +const BOOL = 0x8B56; +const BOOL_VEC2 = 0x8B57; +const BOOL_VEC3 = 0x8B58; +const BOOL_VEC4 = 0x8B59; +const FLOAT_MAT2 = 0x8B5A; +const FLOAT_MAT3 = 0x8B5B; +const FLOAT_MAT4 = 0x8B5C; +const SAMPLER_2D = 0x8B5E; +const SAMPLER_CUBE = 0x8B60; +const SAMPLER_3D = 0x8B5F; +const SAMPLER_2D_SHADOW = 0x8B62; +const FLOAT_MAT2x3 = 0x8B65; +const FLOAT_MAT2x4 = 0x8B66; +const FLOAT_MAT3x2 = 0x8B67; +const FLOAT_MAT3x4 = 0x8B68; +const FLOAT_MAT4x2 = 0x8B69; +const FLOAT_MAT4x3 = 0x8B6A; +const SAMPLER_2D_ARRAY = 0x8DC1; +const SAMPLER_2D_ARRAY_SHADOW = 0x8DC4; +const SAMPLER_CUBE_SHADOW = 0x8DC5; +const UNSIGNED_INT = 0x1405; +const UNSIGNED_INT_VEC2 = 0x8DC6; +const UNSIGNED_INT_VEC3 = 0x8DC7; +const UNSIGNED_INT_VEC4 = 0x8DC8; +const INT_SAMPLER_2D = 0x8DCA; +const INT_SAMPLER_3D = 0x8DCB; +const INT_SAMPLER_CUBE = 0x8DCC; +const INT_SAMPLER_2D_ARRAY = 0x8DCF; +const UNSIGNED_INT_SAMPLER_2D = 0x8DD2; +const UNSIGNED_INT_SAMPLER_3D = 0x8DD3; +const UNSIGNED_INT_SAMPLER_CUBE = 0x8DD4; +const UNSIGNED_INT_SAMPLER_2D_ARRAY = 0x8DD7; + +const TEXTURE_2D$1 = 0x0DE1; +const TEXTURE_CUBE_MAP = 0x8513; +const TEXTURE_3D = 0x806F; +const TEXTURE_2D_ARRAY = 0x8C1A; + +const typeMap = {}; + +/** + * Returns the corresponding bind point for a given sampler type + * @private + */ +function getBindPointForSamplerType(gl, type) { + return typeMap[type].bindPoint; +} + +// This kind of sucks! If you could compose functions as in `var fn = gl[name];` +// this code could be a lot smaller but that is sadly really slow (T_T) + +function floatSetter(gl, location) { + return function(v) { + gl.uniform1f(location, v); + }; +} + +function floatArraySetter(gl, location) { + return function(v) { + gl.uniform1fv(location, v); + }; +} + +function floatVec2Setter(gl, location) { + return function(v) { + gl.uniform2fv(location, v); + }; +} + +function floatVec3Setter(gl, location) { + return function(v) { + gl.uniform3fv(location, v); + }; +} + +function floatVec4Setter(gl, location) { + return function(v) { + gl.uniform4fv(location, v); + }; +} + +function intSetter(gl, location) { + return function(v) { + gl.uniform1i(location, v); + }; +} + +function intArraySetter(gl, location) { + return function(v) { + gl.uniform1iv(location, v); + }; +} + +function intVec2Setter(gl, location) { + return function(v) { + gl.uniform2iv(location, v); + }; +} + +function intVec3Setter(gl, location) { + return function(v) { + gl.uniform3iv(location, v); + }; +} + +function intVec4Setter(gl, location) { + return function(v) { + gl.uniform4iv(location, v); + }; +} + +function uintSetter(gl, location) { + return function(v) { + gl.uniform1ui(location, v); + }; +} + +function uintArraySetter(gl, location) { + return function(v) { + gl.uniform1uiv(location, v); + }; +} + +function uintVec2Setter(gl, location) { + return function(v) { + gl.uniform2uiv(location, v); + }; +} + +function uintVec3Setter(gl, location) { + return function(v) { + gl.uniform3uiv(location, v); + }; +} + +function uintVec4Setter(gl, location) { + return function(v) { + gl.uniform4uiv(location, v); + }; +} + +function floatMat2Setter(gl, location) { + return function(v) { + gl.uniformMatrix2fv(location, false, v); + }; +} + +function floatMat3Setter(gl, location) { + return function(v) { + gl.uniformMatrix3fv(location, false, v); + }; +} + +function floatMat4Setter(gl, location) { + return function(v) { + gl.uniformMatrix4fv(location, false, v); + }; +} + +function floatMat23Setter(gl, location) { + return function(v) { + gl.uniformMatrix2x3fv(location, false, v); + }; +} + +function floatMat32Setter(gl, location) { + return function(v) { + gl.uniformMatrix3x2fv(location, false, v); + }; +} + +function floatMat24Setter(gl, location) { + return function(v) { + gl.uniformMatrix2x4fv(location, false, v); + }; +} + +function floatMat42Setter(gl, location) { + return function(v) { + gl.uniformMatrix4x2fv(location, false, v); + }; +} + +function floatMat34Setter(gl, location) { + return function(v) { + gl.uniformMatrix3x4fv(location, false, v); + }; +} + +function floatMat43Setter(gl, location) { + return function(v) { + gl.uniformMatrix4x3fv(location, false, v); + }; +} + +function samplerSetter(gl, type, unit, location) { + const bindPoint = getBindPointForSamplerType(gl, type); + return isWebGL2(gl) ? function(textureOrPair) { + let texture; + let sampler; + if (!textureOrPair || isTexture(gl, textureOrPair)) { + texture = textureOrPair; + sampler = null; + } else { + texture = textureOrPair.texture; + sampler = textureOrPair.sampler; + } + gl.uniform1i(location, unit); + gl.activeTexture(TEXTURE0 + unit); + gl.bindTexture(bindPoint, texture); + gl.bindSampler(unit, sampler); + } : function(texture) { + gl.uniform1i(location, unit); + gl.activeTexture(TEXTURE0 + unit); + gl.bindTexture(bindPoint, texture); + }; +} + +function samplerArraySetter(gl, type, unit, location, size) { + const bindPoint = getBindPointForSamplerType(gl, type); + const units = new Int32Array(size); + for (let ii = 0; ii < size; ++ii) { + units[ii] = unit + ii; + } + + return isWebGL2(gl) ? function(textures) { + gl.uniform1iv(location, units); + textures.forEach(function(textureOrPair, index) { + gl.activeTexture(TEXTURE0 + units[index]); + let texture; + let sampler; + if (!textureOrPair || isTexture(gl, textureOrPair)) { + texture = textureOrPair; + sampler = null; + } else { + texture = textureOrPair.texture; + sampler = textureOrPair.sampler; + } + gl.bindSampler(unit, sampler); + gl.bindTexture(bindPoint, texture); + }); + } : function(textures) { + gl.uniform1iv(location, units); + textures.forEach(function(texture, index) { + gl.activeTexture(TEXTURE0 + units[index]); + gl.bindTexture(bindPoint, texture); + }); + }; +} + +typeMap[FLOAT] = { Type: Float32Array, size: 4, setter: floatSetter, arraySetter: floatArraySetter, }; +typeMap[FLOAT_VEC2] = { Type: Float32Array, size: 8, setter: floatVec2Setter, cols: 2, }; +typeMap[FLOAT_VEC3] = { Type: Float32Array, size: 12, setter: floatVec3Setter, cols: 3, }; +typeMap[FLOAT_VEC4] = { Type: Float32Array, size: 16, setter: floatVec4Setter, cols: 4, }; +typeMap[INT] = { Type: Int32Array, size: 4, setter: intSetter, arraySetter: intArraySetter, }; +typeMap[INT_VEC2] = { Type: Int32Array, size: 8, setter: intVec2Setter, cols: 2, }; +typeMap[INT_VEC3] = { Type: Int32Array, size: 12, setter: intVec3Setter, cols: 3, }; +typeMap[INT_VEC4] = { Type: Int32Array, size: 16, setter: intVec4Setter, cols: 4, }; +typeMap[UNSIGNED_INT] = { Type: Uint32Array, size: 4, setter: uintSetter, arraySetter: uintArraySetter, }; +typeMap[UNSIGNED_INT_VEC2] = { Type: Uint32Array, size: 8, setter: uintVec2Setter, cols: 2, }; +typeMap[UNSIGNED_INT_VEC3] = { Type: Uint32Array, size: 12, setter: uintVec3Setter, cols: 3, }; +typeMap[UNSIGNED_INT_VEC4] = { Type: Uint32Array, size: 16, setter: uintVec4Setter, cols: 4, }; +typeMap[BOOL] = { Type: Uint32Array, size: 4, setter: intSetter, arraySetter: intArraySetter, }; +typeMap[BOOL_VEC2] = { Type: Uint32Array, size: 8, setter: intVec2Setter, cols: 2, }; +typeMap[BOOL_VEC3] = { Type: Uint32Array, size: 12, setter: intVec3Setter, cols: 3, }; +typeMap[BOOL_VEC4] = { Type: Uint32Array, size: 16, setter: intVec4Setter, cols: 4, }; +typeMap[FLOAT_MAT2] = { Type: Float32Array, size: 32, setter: floatMat2Setter, rows: 2, cols: 2, }; +typeMap[FLOAT_MAT3] = { Type: Float32Array, size: 48, setter: floatMat3Setter, rows: 3, cols: 3, }; +typeMap[FLOAT_MAT4] = { Type: Float32Array, size: 64, setter: floatMat4Setter, rows: 4, cols: 4, }; +typeMap[FLOAT_MAT2x3] = { Type: Float32Array, size: 32, setter: floatMat23Setter, rows: 2, cols: 3, }; +typeMap[FLOAT_MAT2x4] = { Type: Float32Array, size: 32, setter: floatMat24Setter, rows: 2, cols: 4, }; +typeMap[FLOAT_MAT3x2] = { Type: Float32Array, size: 48, setter: floatMat32Setter, rows: 3, cols: 2, }; +typeMap[FLOAT_MAT3x4] = { Type: Float32Array, size: 48, setter: floatMat34Setter, rows: 3, cols: 4, }; +typeMap[FLOAT_MAT4x2] = { Type: Float32Array, size: 64, setter: floatMat42Setter, rows: 4, cols: 2, }; +typeMap[FLOAT_MAT4x3] = { Type: Float32Array, size: 64, setter: floatMat43Setter, rows: 4, cols: 3, }; +typeMap[SAMPLER_2D] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D$1, }; +typeMap[SAMPLER_CUBE] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_CUBE_MAP, }; +typeMap[SAMPLER_3D] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_3D, }; +typeMap[SAMPLER_2D_SHADOW] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D$1, }; +typeMap[SAMPLER_2D_ARRAY] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D_ARRAY, }; +typeMap[SAMPLER_2D_ARRAY_SHADOW] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D_ARRAY, }; +typeMap[SAMPLER_CUBE_SHADOW] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_CUBE_MAP, }; +typeMap[INT_SAMPLER_2D] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D$1, }; +typeMap[INT_SAMPLER_3D] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_3D, }; +typeMap[INT_SAMPLER_CUBE] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_CUBE_MAP, }; +typeMap[INT_SAMPLER_2D_ARRAY] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D_ARRAY, }; +typeMap[UNSIGNED_INT_SAMPLER_2D] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D$1, }; +typeMap[UNSIGNED_INT_SAMPLER_3D] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_3D, }; +typeMap[UNSIGNED_INT_SAMPLER_CUBE] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_CUBE_MAP, }; +typeMap[UNSIGNED_INT_SAMPLER_2D_ARRAY] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D_ARRAY, }; + +function floatAttribSetter(gl, index) { + return function(b) { + if (b.value) { + gl.disableVertexAttribArray(index); + switch (b.value.length) { + case 4: + gl.vertexAttrib4fv(index, b.value); + break; + case 3: + gl.vertexAttrib3fv(index, b.value); + break; + case 2: + gl.vertexAttrib2fv(index, b.value); + break; + case 1: + gl.vertexAttrib1fv(index, b.value); + break; + default: + throw new Error('the length of a float constant value must be between 1 and 4!'); + } + } else { + gl.bindBuffer(ARRAY_BUFFER, b.buffer); + gl.enableVertexAttribArray(index); + gl.vertexAttribPointer( + index, b.numComponents || b.size, b.type || FLOAT, b.normalize || false, b.stride || 0, b.offset || 0); + if (gl.vertexAttribDivisor) { + gl.vertexAttribDivisor(index, b.divisor || 0); + } + } + }; +} + +function intAttribSetter(gl, index) { + return function(b) { + if (b.value) { + gl.disableVertexAttribArray(index); + if (b.value.length === 4) { + gl.vertexAttrib4iv(index, b.value); + } else { + throw new Error('The length of an integer constant value must be 4!'); + } + } else { + gl.bindBuffer(ARRAY_BUFFER, b.buffer); + gl.enableVertexAttribArray(index); + gl.vertexAttribIPointer( + index, b.numComponents || b.size, b.type || INT, b.stride || 0, b.offset || 0); + if (gl.vertexAttribDivisor) { + gl.vertexAttribDivisor(index, b.divisor || 0); + } + } + }; +} + +function uintAttribSetter(gl, index) { + return function(b) { + if (b.value) { + gl.disableVertexAttribArray(index); + if (b.value.length === 4) { + gl.vertexAttrib4uiv(index, b.value); + } else { + throw new Error('The length of an unsigned integer constant value must be 4!'); + } + } else { + gl.bindBuffer(ARRAY_BUFFER, b.buffer); + gl.enableVertexAttribArray(index); + gl.vertexAttribIPointer( + index, b.numComponents || b.size, b.type || UNSIGNED_INT, b.stride || 0, b.offset || 0); + if (gl.vertexAttribDivisor) { + gl.vertexAttribDivisor(index, b.divisor || 0); + } + } + }; +} + +function matAttribSetter(gl, index, typeInfo) { + const defaultSize = typeInfo.size; + const count = typeInfo.count; + + return function(b) { + gl.bindBuffer(ARRAY_BUFFER, b.buffer); + const numComponents = b.size || b.numComponents || defaultSize; + const size = numComponents / count; + const type = b.type || FLOAT; + const typeInfo = typeMap[type]; + const stride = typeInfo.size * numComponents; + const normalize = b.normalize || false; + const offset = b.offset || 0; + const rowOffset = stride / count; + for (let i = 0; i < count; ++i) { + gl.enableVertexAttribArray(index + i); + gl.vertexAttribPointer( + index + i, size, type, normalize, stride, offset + rowOffset * i); + if (gl.vertexAttribDivisor) { + gl.vertexAttribDivisor(index + i, b.divisor || 0); + } + } + }; +} + + + +const attrTypeMap = {}; +attrTypeMap[FLOAT] = { size: 4, setter: floatAttribSetter, }; +attrTypeMap[FLOAT_VEC2] = { size: 8, setter: floatAttribSetter, }; +attrTypeMap[FLOAT_VEC3] = { size: 12, setter: floatAttribSetter, }; +attrTypeMap[FLOAT_VEC4] = { size: 16, setter: floatAttribSetter, }; +attrTypeMap[INT] = { size: 4, setter: intAttribSetter, }; +attrTypeMap[INT_VEC2] = { size: 8, setter: intAttribSetter, }; +attrTypeMap[INT_VEC3] = { size: 12, setter: intAttribSetter, }; +attrTypeMap[INT_VEC4] = { size: 16, setter: intAttribSetter, }; +attrTypeMap[UNSIGNED_INT] = { size: 4, setter: uintAttribSetter, }; +attrTypeMap[UNSIGNED_INT_VEC2] = { size: 8, setter: uintAttribSetter, }; +attrTypeMap[UNSIGNED_INT_VEC3] = { size: 12, setter: uintAttribSetter, }; +attrTypeMap[UNSIGNED_INT_VEC4] = { size: 16, setter: uintAttribSetter, }; +attrTypeMap[BOOL] = { size: 4, setter: intAttribSetter, }; +attrTypeMap[BOOL_VEC2] = { size: 8, setter: intAttribSetter, }; +attrTypeMap[BOOL_VEC3] = { size: 12, setter: intAttribSetter, }; +attrTypeMap[BOOL_VEC4] = { size: 16, setter: intAttribSetter, }; +attrTypeMap[FLOAT_MAT2] = { size: 4, setter: matAttribSetter, count: 2, }; +attrTypeMap[FLOAT_MAT3] = { size: 9, setter: matAttribSetter, count: 3, }; +attrTypeMap[FLOAT_MAT4] = { size: 16, setter: matAttribSetter, count: 4, }; + +const errorRE = /ERROR:\s*\d+:(\d+)/gi; +function addLineNumbersWithError(src, log = '', lineOffset = 0) { + // Note: Error message formats are not defined by any spec so this may or may not work. + const matches = [...log.matchAll(errorRE)]; + const lineNoToErrorMap = new Map(matches.map((m, ndx) => { + const lineNo = parseInt(m[1]); + const next = matches[ndx + 1]; + const end = next ? next.index : log.length; + const msg = log.substring(m.index, end); + return [lineNo - 1, msg]; + })); + return src.split('\n').map((line, lineNo) => { + const err = lineNoToErrorMap.get(lineNo); + return `${lineNo + 1 + lineOffset}: ${line}${err ? `\n\n^^^ ${err}` : ''}`; + }).join('\n'); +} + +/** + * Error Callback + * @callback ErrorCallback + * @param {string} msg error message. + * @param {number} [lineOffset] amount to add to line number + * @memberOf module:twgl + */ + +/** + * Program Callback + * @callback ProgramCallback + * @param {string} [err] error message, falsy if no error + * @param {WebGLProgram|module:twgl.ProgramInfo} [result] the program or programInfo + */ + +const spaceRE = /^[ \t]*\n/; + +/** + * Remove the first end of line because WebGL 2.0 requires + * #version 300 es + * as the first line. No whitespace allowed before that line + * so + * + * + * + * Has one line before it which is invalid according to GLSL ES 3.00 + * + * @param {string} shaderSource The source of the shader + * @returns {{shaderSource: string, lineOffset: number}} + * @private + */ +function prepShaderSource(shaderSource) { + let lineOffset = 0; + if (spaceRE.test(shaderSource)) { + lineOffset = 1; + shaderSource = shaderSource.replace(spaceRE, ''); + } + return {lineOffset, shaderSource}; +} + +/** + * @param {module:twgl.ProgramOptions} progOptions + * @param {string} msg + * @return null + * @private + */ +function reportError(progOptions, msg) { + progOptions.errorCallback(msg); + if (progOptions.callback) { + setTimeout(() => { + progOptions.callback(`${msg}\n${progOptions.errors.join('\n')}`); + }); + } + return null; +} + +/** + * Check Shader status + * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @param {number} shaderType The shader type + * @param {WebGLShader} shader The shader + * @param {ErrorCallback} [errFn] function to receive error message. + * @return {string} errors or empty string + * @private + */ +function checkShaderStatus(gl, shaderType, shader, errFn) { + errFn = errFn || error; + // Check the compile status + const compiled = gl.getShaderParameter(shader, COMPILE_STATUS); + if (!compiled) { + // Something went wrong during compilation; get the error + const lastError = gl.getShaderInfoLog(shader); + const {lineOffset, shaderSource} = prepShaderSource(gl.getShaderSource(shader)); + const error = `${addLineNumbersWithError(shaderSource, lastError, lineOffset)}\nError compiling ${glEnumToString(gl, shaderType)}: ${lastError}`; + errFn(error); + return error; + } + return ''; +} + +/** + * @typedef {Object} FullProgramSpec + * @property {string[]} shaders the shader source or element ids. + * @property {function(string)} [errorCallback] callback for errors + * @property {Object.|string[]} [attribLocations] a attribute name to location map, or array of attribute names where index = location. + * @property {(module:twgl.BufferInfo|Object.|string[])} [transformFeedbackVaryings] If passed + * a BufferInfo will use the attribs names inside. If passed an object of AttribInfos will use the names from that object. Otherwise + * you can pass an array of names. + * @property {number} [transformFeedbackMode] the mode to pass `gl.transformFeedbackVaryings`. Defaults to `SEPARATE_ATTRIBS`. + * @property {ProgramCallback} [callback] callback for async program compilation. + * @memberOf module:twgl + */ + +/** + * @typedef {string[]|module:twgl.FullProgramSpec} ProgramSpec + * @memberOf module:twgl + */ + +/** + * @typedef {Object} ProgramOptions + * @property {function(string)} [errorCallback] callback for errors + * @property {Object.|string[]} [attribLocations] a attribute name to location map, or array of attribute names where index = location. + * @property {(module:twgl.BufferInfo|Object.|string[])} [transformFeedbackVaryings] If passed + * a BufferInfo will use the attribs names inside. If passed an object of AttribInfos will use the names from that object. Otherwise + * you can pass an array of names. + * @property {number} [transformFeedbackMode] the mode to pass `gl.transformFeedbackVaryings`. Defaults to `SEPARATE_ATTRIBS`. + * @property {ProgramCallback} [callback] callback for async program compilation. + * @memberOf module:twgl + */ + +/** + * Gets the program options based on all these optional arguments + * @param {module:twgl.ProgramOptions|string[]} [opt_attribs] Options for the program or an array of attribs names. Locations will be assigned by index if not passed in + * @param {number[]} [opt_locations] The locations for the. A parallel array to opt_attribs letting you assign locations. + * @param {module:twgl.ErrorCallback} [opt_errorCallback] callback for errors. By default it just prints an error to the console + * on error. If you want something else pass an callback. It's passed an error message. + * @return {module:twgl.ProgramOptions} an instance of ProgramOptions based on the arguments passed in + * @private + */ +function getProgramOptions(opt_attribs, opt_locations, opt_errorCallback) { + let transformFeedbackVaryings; + let transformFeedbackMode; + let callback; + if (typeof opt_locations === 'function') { + opt_errorCallback = opt_locations; + opt_locations = undefined; + } + if (typeof opt_attribs === 'function') { + opt_errorCallback = opt_attribs; + opt_attribs = undefined; + } else if (opt_attribs && !Array.isArray(opt_attribs)) { + const opt = opt_attribs; + opt_errorCallback = opt.errorCallback; + opt_attribs = opt.attribLocations; + transformFeedbackVaryings = opt.transformFeedbackVaryings; + transformFeedbackMode = opt.transformFeedbackMode; + callback = opt.callback; + } + + const errorCallback = opt_errorCallback || error; + const errors = []; + const options = { + errorCallback(msg, ...args) { + errors.push(msg); + errorCallback(msg, ...args); + }, + transformFeedbackVaryings, + transformFeedbackMode, + callback, + errors, + }; + + { + let attribLocations = {}; + if (Array.isArray(opt_attribs)) { + opt_attribs.forEach(function(attrib, ndx) { + attribLocations[attrib] = opt_locations ? opt_locations[ndx] : ndx; + }); + } else { + attribLocations = opt_attribs || {}; + } + options.attribLocations = attribLocations; + } + + return options; +} + +const defaultShaderType = [ + "VERTEX_SHADER", + "FRAGMENT_SHADER", +]; + +function getShaderTypeFromScriptType(gl, scriptType) { + if (scriptType.indexOf("frag") >= 0) { + return FRAGMENT_SHADER; + } else if (scriptType.indexOf("vert") >= 0) { + return VERTEX_SHADER; + } + return undefined; +} + +function deleteProgramAndShaders(gl, program, notThese) { + const shaders = gl.getAttachedShaders(program); + for (const shader of shaders) { + if (notThese.has(shader)) { + gl.deleteShader(shader); + } + } + gl.deleteProgram(program); +} + +const wait = (ms = 0) => new Promise(resolve => setTimeout(resolve, ms)); + +function createProgramNoCheck(gl, shaders, programOptions) { + const program = gl.createProgram(); + const { + attribLocations, + transformFeedbackVaryings, + transformFeedbackMode, + } = getProgramOptions(programOptions); + + for (let ndx = 0; ndx < shaders.length; ++ndx) { + let shader = shaders[ndx]; + if (typeof shader === 'string') { + const elem = getElementById(shader); + const src = elem ? elem.text : shader; + let type = gl[defaultShaderType[ndx]]; + if (elem && elem.type) { + type = getShaderTypeFromScriptType(gl, elem.type) || type; + } + shader = gl.createShader(type); + gl.shaderSource(shader, prepShaderSource(src).shaderSource); + gl.compileShader(shader); + gl.attachShader(program, shader); + } + } + + Object.entries(attribLocations).forEach(([attrib, loc]) => gl.bindAttribLocation(program, loc, attrib)); + + { + let varyings = transformFeedbackVaryings; + if (varyings) { + if (varyings.attribs) { + varyings = varyings.attribs; + } + if (!Array.isArray(varyings)) { + varyings = Object.keys(varyings); + } + gl.transformFeedbackVaryings(program, varyings, transformFeedbackMode || SEPARATE_ATTRIBS); + } + } + + gl.linkProgram(program); + return program; +} + +/** + * Creates a program, attaches (and/or compiles) shaders, binds attrib locations, links the + * program. + * + * NOTE: There are 4 signatures for this function + * + * twgl.createProgram(gl, [vs, fs], options); + * twgl.createProgram(gl, [vs, fs], opt_errFunc); + * twgl.createProgram(gl, [vs, fs], opt_attribs, opt_errFunc); + * twgl.createProgram(gl, [vs, fs], opt_attribs, opt_locations, opt_errFunc); + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @param {WebGLShader[]|string[]} shaders The shaders to attach, or element ids for their source, or strings that contain their source + * @param {module:twgl.ProgramOptions|string[]|module:twgl.ErrorCallback} [opt_attribs] Options for the program or an array of attribs names or an error callback. Locations will be assigned by index if not passed in + * @param {number[]} [opt_locations|module:twgl.ErrorCallback] The locations for the. A parallel array to opt_attribs letting you assign locations or an error callback. + * @param {module:twgl.ErrorCallback} [opt_errorCallback] callback for errors. By default it just prints an error to the console + * on error. If you want something else pass an callback. It's passed an error message. + * @return {WebGLProgram?} the created program or null if error of a callback was provided. + * @memberOf module:twgl/programs + */ +function createProgram( + gl, shaders, opt_attribs, opt_locations, opt_errorCallback) { + // This code is really convoluted, because it may or may not be async + // Maybe it would be better to have a separate function + const progOptions = getProgramOptions(opt_attribs, opt_locations, opt_errorCallback); + const shaderSet = new Set(shaders); + const program = createProgramNoCheck(gl, shaders, progOptions); + + function hasErrors(gl, program) { + const errors = getProgramErrors(gl, program, progOptions.errorCallback); + if (errors) { + deleteProgramAndShaders(gl, program, shaderSet); + } + return errors; + } + + if (progOptions.callback) { + waitForProgramLinkCompletionAsync(gl, program).then(() => { + const errors = hasErrors(gl, program); + progOptions.callback(errors, errors ? undefined : program); + }); + return undefined; + } + + return hasErrors(gl, program) ? undefined : program; +} + +/** + * This only works because the functions it wraps the first 2 arguments + * are gl and any, followed by things that become programOptions + * @private + */ +function wrapCallbackFnToAsyncFn(fn) { + return function(gl, arg1, ...args) { + return new Promise((resolve, reject) => { + const programOptions = getProgramOptions(...args); + programOptions.callback = (err, program) => { + if (err) { + reject(err); + } else { + resolve(program); + } + }; + fn(gl, arg1, programOptions); + }); + }; +} + +/** + * Same as createProgram but returns a promise + * + * NOTE: There are 4 signatures for this function + * + * twgl.createProgramAsync(gl, [vs, fs], options); + * twgl.createProgramAsync(gl, [vs, fs], opt_errFunc); + * twgl.createProgramAsync(gl, [vs, fs], opt_attribs, opt_errFunc); + * twgl.createProgramAsync(gl, [vs, fs], opt_attribs, opt_locations, opt_errFunc); + * + * @function + * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @param {WebGLShader[]|string[]} shaders The shaders to attach, or element ids for their source, or strings that contain their source + * @param {module:twgl.ProgramOptions|string[]|module:twgl.ErrorCallback} [opt_attribs] Options for the program or an array of attribs names or an error callback. Locations will be assigned by index if not passed in + * @param {number[]} [opt_locations|module:twgl.ErrorCallback] The locations for the. A parallel array to opt_attribs letting you assign locations or an error callback. + * @param {module:twgl.ErrorCallback} [opt_errorCallback] callback for errors. By default it just prints an error to the console + * on error. If you want something else pass an callback. It's passed an error message. + * @return {Promise} The created program + * @memberOf module:twgl/programs + */ +const createProgramAsync = wrapCallbackFnToAsyncFn(createProgram); + +/** + * Same as createProgramInfo but returns a promise + * @function + * @param {WebGLRenderingContext} gl The WebGLRenderingContext + * to use. + * @param {string[]} shaderSources Array of sources for the + * shaders or ids. The first is assumed to be the vertex shader, + * the second the fragment shader. + * @param {module:twgl.ProgramOptions|string[]|module:twgl.ErrorCallback} [opt_attribs] Options for the program or an array of attribs names or an error callback. Locations will be assigned by index if not passed in + * @param {number[]} [opt_locations|module:twgl.ErrorCallback] The locations for the. A parallel array to opt_attribs letting you assign locations or an error callback. + * @param {module:twgl.ErrorCallback} [opt_errorCallback] callback for errors. By default it just prints an error to the console + * on error. If you want something else pass an callback. It's passed an error message. + * @return {Promise} The created ProgramInfo + * @memberOf module:twgl/programs + */ +const createProgramInfoAsync = wrapCallbackFnToAsyncFn(createProgramInfo); + +async function waitForProgramLinkCompletionAsync(gl, program) { + const ext = gl.getExtension('KHR_parallel_shader_compile'); + const checkFn = ext + ? (gl, program) => gl.getProgramParameter(program, ext.COMPLETION_STATUS_KHR) + : () => true; + + let waitTime = 0; + do { + await wait(waitTime); // must wait at least once + waitTime = 1000 / 60; + } while (!checkFn(gl, program)); +} + +async function waitForAllProgramsLinkCompletionAsync(gl, programs) { + for (const program of Object.values(programs)) { + await waitForProgramLinkCompletionAsync(gl, program); + } +} + +/** + * Check a program's link status + * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @param {WebGLProgram} program Program to check + * @param {ErrorCallback} [errFn] func for errors + * @return {string?} errors if program is failed, else undefined + * @private + */ +function getProgramErrors(gl, program, errFn) { + errFn = errFn || error; + // Check the link status + const linked = gl.getProgramParameter(program, LINK_STATUS); + if (!linked) { + // something went wrong with the link + const lastError = gl.getProgramInfoLog(program); + errFn(`Error in program linking: ${lastError}`); + // print any errors from these shaders + const shaders = gl.getAttachedShaders(program); + const errors = shaders.map(shader => checkShaderStatus(gl, gl.getShaderParameter(shader, gl.SHADER_TYPE), shader, errFn)); + return `${lastError}\n${errors.filter(_ => _).join('\n')}`; + } + return undefined; +} + +/** + * Creates a program from 2 script tags. + * + * NOTE: There are 4 signatures for this function + * + * twgl.createProgramFromScripts(gl, [vs, fs], opt_options); + * twgl.createProgramFromScripts(gl, [vs, fs], opt_errFunc); + * twgl.createProgramFromScripts(gl, [vs, fs], opt_attribs, opt_errFunc); + * twgl.createProgramFromScripts(gl, [vs, fs], opt_attribs, opt_locations, opt_errFunc); + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext + * to use. + * @param {string[]} shaderScriptIds Array of ids of the script + * tags for the shaders. The first is assumed to be the + * vertex shader, the second the fragment shader. + * @param {module:twgl.ProgramOptions|string[]|module:twgl.ErrorCallback} [opt_attribs] Options for the program or an array of attribs names or an error callback. Locations will be assigned by index if not passed in + * @param {number[]} [opt_locations|module:twgl.ErrorCallback] The locations for the. A parallel array to opt_attribs letting you assign locations or an error callback. + * @param {module:twgl.ErrorCallback} [opt_errorCallback] callback for errors. By default it just prints an error to the console + * on error. If you want something else pass an callback. It's passed an error message. + * @return {WebGLProgram?} the created program or null if error or a callback was provided. + * @memberOf module:twgl/programs + */ +function createProgramFromScripts( + gl, shaderScriptIds, opt_attribs, opt_locations, opt_errorCallback) { + const progOptions = getProgramOptions(opt_attribs, opt_locations, opt_errorCallback); + const shaders = []; + for (const scriptId of shaderScriptIds) { + const shaderScript = getElementById(scriptId); + if (!shaderScript) { + return reportError(progOptions, `unknown script element: ${scriptId}`); + } + shaders.push(shaderScript.text); + } + return createProgram(gl, shaders, progOptions); +} + +/** + * Creates a program from 2 sources. + * + * NOTE: There are 4 signatures for this function + * + * twgl.createProgramFromSource(gl, [vs, fs], opt_options); + * twgl.createProgramFromSource(gl, [vs, fs], opt_errFunc); + * twgl.createProgramFromSource(gl, [vs, fs], opt_attribs, opt_errFunc); + * twgl.createProgramFromSource(gl, [vs, fs], opt_attribs, opt_locations, opt_errFunc); + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext + * to use. + * @param {string[]} shaderSources Array of sources for the + * shaders. The first is assumed to be the vertex shader, + * the second the fragment shader. + * @param {module:twgl.ProgramOptions|string[]|module:twgl.ErrorCallback} [opt_attribs] Options for the program or an array of attribs names or an error callback. Locations will be assigned by index if not passed in + * @param {number[]} [opt_locations|module:twgl.ErrorCallback] The locations for the. A parallel array to opt_attribs letting you assign locations or an error callback. + * @param {module:twgl.ErrorCallback} [opt_errorCallback] callback for errors. By default it just prints an error to the console + * on error. If you want something else pass an callback. It's passed an error message. + * @return {WebGLProgram?} the created program or null if error or a callback was provided. + * @memberOf module:twgl/programs + */ +function createProgramFromSources( + gl, shaderSources, opt_attribs, opt_locations, opt_errorCallback) { + return createProgram(gl, shaderSources, opt_attribs, opt_locations, opt_errorCallback); +} + +/** + * Returns true if attribute/uniform is a reserved/built in + * + * It makes no sense to me why GL returns these because it's + * illegal to call `gl.getUniformLocation` and `gl.getAttribLocation` + * with names that start with `gl_` (and `webgl_` in WebGL) + * + * I can only assume they are there because they might count + * when computing the number of uniforms/attributes used when you want to + * know if you are near the limit. That doesn't really make sense + * to me but the fact that these get returned are in the spec. + * + * @param {WebGLActiveInfo} info As returned from `gl.getActiveUniform` or + * `gl.getActiveAttrib`. + * @return {bool} true if it's reserved + * @private + */ +function isBuiltIn(info) { + const name = info.name; + return name.startsWith("gl_") || name.startsWith("webgl_"); +} + +const tokenRE = /(\.|\[|]|\w+)/g; +const isDigit = s => s >= '0' && s <= '9'; +function addSetterToUniformTree(fullPath, setter, node, uniformSetters) { + const tokens = fullPath.split(tokenRE).filter(s => s !== ''); + let tokenNdx = 0; + let path = ''; + + for (;;) { + const token = tokens[tokenNdx++]; // has to be name or number + path += token; + const isArrayIndex = isDigit(token[0]); + const accessor = isArrayIndex + ? parseInt(token) + : token; + if (isArrayIndex) { + path += tokens[tokenNdx++]; // skip ']' + } + const isLastToken = tokenNdx === tokens.length; + if (isLastToken) { + node[accessor] = setter; + break; + } else { + const token = tokens[tokenNdx++]; // has to be . or [ + const isArray = token === '['; + const child = node[accessor] || (isArray ? [] : {}); + node[accessor] = child; + node = child; + uniformSetters[path] = uniformSetters[path] || function(node) { + return function(value) { + setUniformTree(node, value); + }; + }(child); + path += token; + } + } +} + +/** + * Creates setter functions for all uniforms of a shader + * program. + * + * @see {@link module:twgl.setUniforms} + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @param {WebGLProgram} program the program to create setters for. + * @returns {Object.} an object with a setter by name for each uniform + * @memberOf module:twgl/programs + */ +function createUniformSetters(gl, program) { + let textureUnit = 0; + + /** + * Creates a setter for a uniform of the given program with it's + * location embedded in the setter. + * @param {WebGLProgram} program + * @param {WebGLUniformInfo} uniformInfo + * @returns {function} the created setter. + */ + function createUniformSetter(program, uniformInfo, location) { + const isArray = uniformInfo.name.endsWith("[0]"); + const type = uniformInfo.type; + const typeInfo = typeMap[type]; + if (!typeInfo) { + throw new Error(`unknown type: 0x${type.toString(16)}`); // we should never get here. + } + let setter; + if (typeInfo.bindPoint) { + // it's a sampler + const unit = textureUnit; + textureUnit += uniformInfo.size; + if (isArray) { + setter = typeInfo.arraySetter(gl, type, unit, location, uniformInfo.size); + } else { + setter = typeInfo.setter(gl, type, unit, location, uniformInfo.size); + } + } else { + if (typeInfo.arraySetter && isArray) { + setter = typeInfo.arraySetter(gl, location); + } else { + setter = typeInfo.setter(gl, location); + } + } + setter.location = location; + return setter; + } + + const uniformSetters = {}; + const uniformTree = {}; + const numUniforms = gl.getProgramParameter(program, ACTIVE_UNIFORMS); + + for (let ii = 0; ii < numUniforms; ++ii) { + const uniformInfo = gl.getActiveUniform(program, ii); + if (isBuiltIn(uniformInfo)) { + continue; + } + let name = uniformInfo.name; + // remove the array suffix. + if (name.endsWith("[0]")) { + name = name.substr(0, name.length - 3); + } + const location = gl.getUniformLocation(program, uniformInfo.name); + // the uniform will have no location if it's in a uniform block + if (location) { + const setter = createUniformSetter(program, uniformInfo, location); + uniformSetters[name] = setter; + addSetterToUniformTree(name, setter, uniformTree, uniformSetters); + } + } + + return uniformSetters; +} + +/** + * @typedef {Object} TransformFeedbackInfo + * @property {number} index index of transform feedback + * @property {number} type GL type + * @property {number} size 1 - 4 + * @memberOf module:twgl + */ + +/** + * Create TransformFeedbackInfo for passing to bindTransformFeedbackInfo. + * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @param {WebGLProgram} program an existing WebGLProgram. + * @return {Object} + * @memberOf module:twgl + */ +function createTransformFeedbackInfo(gl, program) { + const info = {}; + const numVaryings = gl.getProgramParameter(program, TRANSFORM_FEEDBACK_VARYINGS); + for (let ii = 0; ii < numVaryings; ++ii) { + const varying = gl.getTransformFeedbackVarying(program, ii); + info[varying.name] = { + index: ii, + type: varying.type, + size: varying.size, + }; + } + return info; +} + +/** + * Binds buffers for transform feedback. + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @param {(module:twgl.ProgramInfo|Object)} transformFeedbackInfo A ProgramInfo or TransformFeedbackInfo. + * @param {(module:twgl.BufferInfo|Object)} [bufferInfo] A BufferInfo or set of AttribInfos. + * @memberOf module:twgl + */ +function bindTransformFeedbackInfo(gl, transformFeedbackInfo, bufferInfo) { + if (transformFeedbackInfo.transformFeedbackInfo) { + transformFeedbackInfo = transformFeedbackInfo.transformFeedbackInfo; + } + if (bufferInfo.attribs) { + bufferInfo = bufferInfo.attribs; + } + for (const name in bufferInfo) { + const varying = transformFeedbackInfo[name]; + if (varying) { + const buf = bufferInfo[name]; + if (buf.offset) { + gl.bindBufferRange(TRANSFORM_FEEDBACK_BUFFER, varying.index, buf.buffer, buf.offset, buf.size); + } else { + gl.bindBufferBase(TRANSFORM_FEEDBACK_BUFFER, varying.index, buf.buffer); + } + } + } +} + +/** + * Creates a transform feedback and sets the buffers + * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @param {module:twgl.ProgramInfo} programInfo A ProgramInfo as returned from {@link module:twgl.createProgramInfo} + * @param {(module:twgl.BufferInfo|Object)} [bufferInfo] A BufferInfo or set of AttribInfos. + * @return {WebGLTransformFeedback} the created transform feedback + * @memberOf module:twgl + */ +function createTransformFeedback(gl, programInfo, bufferInfo) { + const tf = gl.createTransformFeedback(); + gl.bindTransformFeedback(TRANSFORM_FEEDBACK, tf); + gl.useProgram(programInfo.program); + bindTransformFeedbackInfo(gl, programInfo, bufferInfo); + gl.bindTransformFeedback(TRANSFORM_FEEDBACK, null); + return tf; +} + +/** + * @typedef {Object} UniformData + * @property {string} name The name of the uniform + * @property {number} type The WebGL type enum for this uniform + * @property {number} size The number of elements for this uniform + * @property {number} blockNdx The block index this uniform appears in + * @property {number} offset The byte offset in the block for this uniform's value + * @memberOf module:twgl + */ + +/** + * The specification for one UniformBlockObject + * + * @typedef {Object} BlockSpec + * @property {number} index The index of the block. + * @property {number} size The size in bytes needed for the block + * @property {number[]} uniformIndices The indices of the uniforms used by the block. These indices + * correspond to entries in a UniformData array in the {@link module:twgl.UniformBlockSpec}. + * @property {bool} usedByVertexShader Self explanatory + * @property {bool} usedByFragmentShader Self explanatory + * @property {bool} used Self explanatory + * @memberOf module:twgl + */ + +/** + * A `UniformBlockSpec` represents the data needed to create and bind + * UniformBlockObjects for a given program + * + * @typedef {Object} UniformBlockSpec + * @property {Object.} blockSpecs The BlockSpec for each block by block name + * @property {UniformData[]} uniformData An array of data for each uniform by uniform index. + * @memberOf module:twgl + */ + +/** + * Creates a UniformBlockSpec for the given program. + * + * A UniformBlockSpec represents the data needed to create and bind + * UniformBlockObjects + * + * @param {WebGL2RenderingContext} gl A WebGL2 Rendering Context + * @param {WebGLProgram} program A WebGLProgram for a successfully linked program + * @return {module:twgl.UniformBlockSpec} The created UniformBlockSpec + * @memberOf module:twgl/programs + */ +function createUniformBlockSpecFromProgram(gl, program) { + const numUniforms = gl.getProgramParameter(program, ACTIVE_UNIFORMS); + const uniformData = []; + const uniformIndices = []; + + for (let ii = 0; ii < numUniforms; ++ii) { + uniformIndices.push(ii); + uniformData.push({}); + const uniformInfo = gl.getActiveUniform(program, ii); + uniformData[ii].name = uniformInfo.name; + } + + [ + [ "UNIFORM_TYPE", "type" ], + [ "UNIFORM_SIZE", "size" ], // num elements + [ "UNIFORM_BLOCK_INDEX", "blockNdx" ], + [ "UNIFORM_OFFSET", "offset", ], + ].forEach(function(pair) { + const pname = pair[0]; + const key = pair[1]; + gl.getActiveUniforms(program, uniformIndices, gl[pname]).forEach(function(value, ndx) { + uniformData[ndx][key] = value; + }); + }); + + const blockSpecs = {}; + + const numUniformBlocks = gl.getProgramParameter(program, ACTIVE_UNIFORM_BLOCKS); + for (let ii = 0; ii < numUniformBlocks; ++ii) { + const name = gl.getActiveUniformBlockName(program, ii); + const blockSpec = { + index: gl.getUniformBlockIndex(program, name), + usedByVertexShader: gl.getActiveUniformBlockParameter(program, ii, UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER), + usedByFragmentShader: gl.getActiveUniformBlockParameter(program, ii, UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER), + size: gl.getActiveUniformBlockParameter(program, ii, UNIFORM_BLOCK_DATA_SIZE), + uniformIndices: gl.getActiveUniformBlockParameter(program, ii, UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES), + }; + blockSpec.used = blockSpec.usedByVertexShader || blockSpec.usedByFragmentShader; + blockSpecs[name] = blockSpec; + } + + return { + blockSpecs: blockSpecs, + uniformData: uniformData, + }; +} + +const arraySuffixRE = /\[\d+\]\.$/; // better way to check? + +const pad = (v, padding) => ((v + (padding - 1)) / padding | 0) * padding; + +function createUniformBlockUniformSetter(view, isArray, rows, cols) { + if (isArray || rows) { + cols = cols || 1; + const numElements = view.length; + const totalRows = numElements / 4; + return function(value) { + let dst = 0; + let src = 0; + for (let row = 0; row < totalRows; ++row) { + for (let col = 0; col < cols; ++col) { + view[dst++] = value[src++]; + } + dst += 4 - cols; + } + }; + } else { + return function(value) { + if (value.length) { + view.set(value); + } else { + view[0] = value; + } + }; + } +} + +/** + * Represents a UniformBlockObject including an ArrayBuffer with all the uniform values + * and a corresponding WebGLBuffer to hold those values on the GPU + * + * @typedef {Object} UniformBlockInfo + * @property {string} name The name of the block + * @property {ArrayBuffer} array The array buffer that contains the uniform values + * @property {Float32Array} asFloat A float view on the array buffer. This is useful + * inspecting the contents of the buffer in the debugger. + * @property {WebGLBuffer} buffer A WebGL buffer that will hold a copy of the uniform values for rendering. + * @property {number} [offset] offset into buffer + * @property {Object} uniforms A uniform name to ArrayBufferView map. + * each Uniform has a correctly typed `ArrayBufferView` into array at the correct offset + * and length of that uniform. So for example a float uniform would have a 1 float `Float32Array` + * view. A single mat4 would have a 16 element `Float32Array` view. An ivec2 would have an + * `Int32Array` view, etc. + * @property {Object} setters A setter for this uniform. + * The reason to use setters is elements of arrays are padded to vec4 sizes which + * means if you want to set an array of 4 floats you'd need to set 16 values + * (or set elements 0, 4, 8, 12). In other words + * `someBlockInfo.uniforms.some4FloatArrayUniform.set([0, , , , 1, , , , 2, , , , 3])` + * where as the setter handles just passing in [0, 1, 2, 3] either directly as in + * `someBlockInfo.setter.some4FloatArrayUniform.set([0, 1, 2, 3])` (not recommended) + * or via {@link module:twgl.setBlockUniforms} + * @memberOf module:twgl + */ + +/** + * Creates a `UniformBlockInfo` for the specified block + * + * Note: **If the blockName matches no existing blocks a warning is printed to the console and a dummy + * `UniformBlockInfo` is returned**. This is because when debugging GLSL + * it is common to comment out large portions of a shader or for example set + * the final output to a constant. When that happens blocks get optimized out. + * If this function did not create dummy blocks your code would crash when debugging. + * + * @param {WebGL2RenderingContext} gl A WebGL2RenderingContext + * @param {WebGLProgram} program A WebGLProgram + * @param {module:twgl.UniformBlockSpec} uniformBlockSpec. A UniformBlockSpec as returned + * from {@link module:twgl.createUniformBlockSpecFromProgram}. + * @param {string} blockName The name of the block. + * @return {module:twgl.UniformBlockInfo} The created UniformBlockInfo + * @memberOf module:twgl/programs + */ +function createUniformBlockInfoFromProgram(gl, program, uniformBlockSpec, blockName) { + const blockSpecs = uniformBlockSpec.blockSpecs; + const uniformData = uniformBlockSpec.uniformData; + const blockSpec = blockSpecs[blockName]; + if (!blockSpec) { + warn("no uniform block object named:", blockName); + return { + name: blockName, + uniforms: {}, + }; + } + const array = new ArrayBuffer(blockSpec.size); + const buffer = gl.createBuffer(); + const uniformBufferIndex = blockSpec.index; + gl.bindBuffer(UNIFORM_BUFFER, buffer); + gl.uniformBlockBinding(program, blockSpec.index, uniformBufferIndex); + + let prefix = blockName + "."; + if (arraySuffixRE.test(prefix)) { + prefix = prefix.replace(arraySuffixRE, "."); + } + const uniforms = {}; + const setters = {}; + const setterTree = {}; + blockSpec.uniformIndices.forEach(function(uniformNdx) { + const data = uniformData[uniformNdx]; + let name = data.name; + if (name.startsWith(prefix)) { + name = name.substr(prefix.length); + } + const isArray = name.endsWith('[0]'); + if (isArray) { + name = name.substr(0, name.length - 3); + } + const typeInfo = typeMap[data.type]; + const Type = typeInfo.Type; + const byteLength = isArray + ? pad(typeInfo.size, 16) * data.size + : typeInfo.size * data.size; + const uniformView = new Type(array, data.offset, byteLength / Type.BYTES_PER_ELEMENT); + uniforms[name] = uniformView; + // Note: I'm not sure what to do here. The original + // idea was to create TypedArray views into each part + // of the block. This is useful, for example if you have + // a block with { mat4: model; mat4 view; mat4 projection; } + // you'll get a Float32Array for each one suitable for + // passing to most JS math libraries including twgl's and glMatrix.js. + // + // But, if you have a an array of structures, especially if that + // array is large, you get a whole bunch of TypedArray views. + // Every one of them has overhead and switching between them all + // is probably a cache miss. In that case it would really be better + // to just have one view (asFloat) and have all the setters + // just reference the correct portion. But, then you can't easily + // treat a matrix, or a vec4, as a standalone thing like you can + // with all the views. + // + // Another problem with the views is they are not shared. With + // uniforms you have one set of setters. With UniformBlockInfo + // you have a set of setters *pre block instance*. That's because + // TypedArray views can't be mapped to different buffers. + // + // My gut right now is if you really want the speed and compactness + // then you should probably roll your own solution. TWGL's goal + // here is ease of use as AFAICT there is no simple generic efficient + // solution. + const setter = createUniformBlockUniformSetter(uniformView, isArray, typeInfo.rows, typeInfo.cols); + setters[name] = setter; + addSetterToUniformTree(name, setter, setterTree, setters); + }); + return { + name: blockName, + array, + asFloat: new Float32Array(array), // for debugging + buffer, + uniforms, + setters, + }; +} + +/** + * Creates a `UniformBlockInfo` for the specified block + * + * Note: **If the blockName matches no existing blocks a warning is printed to the console and a dummy + * `UniformBlockInfo` is returned**. This is because when debugging GLSL + * it is common to comment out large portions of a shader or for example set + * the final output to a constant. When that happens blocks get optimized out. + * If this function did not create dummy blocks your code would crash when debugging. + * + * @param {WebGL2RenderingContext} gl A WebGL2RenderingContext + * @param {module:twgl.ProgramInfo} programInfo a `ProgramInfo` + * as returned from {@link module:twgl.createProgramInfo} + * @param {string} blockName The name of the block. + * @return {module:twgl.UniformBlockInfo} The created UniformBlockInfo + * @memberOf module:twgl/programs + */ +function createUniformBlockInfo(gl, programInfo, blockName) { + return createUniformBlockInfoFromProgram(gl, programInfo.program, programInfo.uniformBlockSpec, blockName); +} + +/** + * Binds a uniform block to the matching uniform block point. + * Matches by blocks by name so blocks must have the same name not just the same + * structure. + * + * If you have changed any values and you upload the values into the corresponding WebGLBuffer + * call {@link module:twgl.setUniformBlock} instead. + * + * @param {WebGL2RenderingContext} gl A WebGL 2 rendering context. + * @param {(module:twgl.ProgramInfo|module:twgl.UniformBlockSpec)} programInfo a `ProgramInfo` + * as returned from {@link module:twgl.createProgramInfo} or or `UniformBlockSpec` as + * returned from {@link module:twgl.createUniformBlockSpecFromProgram}. + * @param {module:twgl.UniformBlockInfo} uniformBlockInfo a `UniformBlockInfo` as returned from + * {@link module:twgl.createUniformBlockInfo}. + * @return {bool} true if buffer was bound. If the programInfo has no block with the same block name + * no buffer is bound. + * @memberOf module:twgl/programs + */ +function bindUniformBlock(gl, programInfo, uniformBlockInfo) { + const uniformBlockSpec = programInfo.uniformBlockSpec || programInfo; + const blockSpec = uniformBlockSpec.blockSpecs[uniformBlockInfo.name]; + if (blockSpec) { + const bufferBindIndex = blockSpec.index; + gl.bindBufferRange(UNIFORM_BUFFER, bufferBindIndex, uniformBlockInfo.buffer, uniformBlockInfo.offset || 0, uniformBlockInfo.array.byteLength); + return true; + } + return false; +} + +/** + * Uploads the current uniform values to the corresponding WebGLBuffer + * and binds that buffer to the program's corresponding bind point for the uniform block object. + * + * If you haven't changed any values and you only need to bind the uniform block object + * call {@link module:twgl.bindUniformBlock} instead. + * + * @param {WebGL2RenderingContext} gl A WebGL 2 rendering context. + * @param {(module:twgl.ProgramInfo|module:twgl.UniformBlockSpec)} programInfo a `ProgramInfo` + * as returned from {@link module:twgl.createProgramInfo} or or `UniformBlockSpec` as + * returned from {@link module:twgl.createUniformBlockSpecFromProgram}. + * @param {module:twgl.UniformBlockInfo} uniformBlockInfo a `UniformBlockInfo` as returned from + * {@link module:twgl.createUniformBlockInfo}. + * @memberOf module:twgl/programs + */ +function setUniformBlock(gl, programInfo, uniformBlockInfo) { + if (bindUniformBlock(gl, programInfo, uniformBlockInfo)) { + gl.bufferData(UNIFORM_BUFFER, uniformBlockInfo.array, DYNAMIC_DRAW); + } +} + +/** + * Sets values of a uniform block object + * + * @param {module:twgl.UniformBlockInfo} uniformBlockInfo A UniformBlockInfo as returned by {@link module:twgl.createUniformBlockInfo}. + * @param {Object.} values A uniform name to value map where the value is correct for the given + * type of uniform. So for example given a block like + * + * uniform SomeBlock { + * float someFloat; + * vec2 someVec2; + * vec3 someVec3Array[2]; + * int someInt; + * } + * + * You can set the values of the uniform block with + * + * twgl.setBlockUniforms(someBlockInfo, { + * someFloat: 12.3, + * someVec2: [1, 2], + * someVec3Array: [1, 2, 3, 4, 5, 6], + * someInt: 5, + * } + * + * Arrays can be JavaScript arrays or typed arrays + * + * You can also fill out structure and array values either via + * shortcut. Example + * + * // -- in shader -- + * struct Light { + * float intensity; + * vec4 color; + * float nearFar[2]; + * }; + * uniform Lights { + * Light lights[2]; + * }; + * + * // in JavaScript + * + * twgl.setBlockUniforms(someBlockInfo, { + * lights: [ + * { intensity: 5.0, color: [1, 0, 0, 1], nearFar[0.1, 10] }, + * { intensity: 2.0, color: [0, 0, 1, 1], nearFar[0.2, 15] }, + * ], + * }); + * + * or the more traditional way + * + * twgl.setBlockUniforms(someBlockInfo, { + * "lights[0].intensity": 5.0, + * "lights[0].color": [1, 0, 0, 1], + * "lights[0].nearFar": [0.1, 10], + * "lights[1].intensity": 2.0, + * "lights[1].color": [0, 0, 1, 1], + * "lights[1].nearFar": [0.2, 15], + * }); + * + * You can also specify partial paths + * + * twgl.setBlockUniforms(someBlockInfo, { + * 'lights[1]': { intensity: 5.0, color: [1, 0, 0, 1], nearFar[0.2, 15] }, + * }); + * + * But you can not specify leaf array indices. + * + * twgl.setBlockUniforms(someBlockInfo, { + * 'lights[1].nearFar[1]': 15, // BAD! nearFar is a leaf + * 'lights[1].nearFar': [0.2, 15], // GOOD + * }); + * + * **IMPORTANT!**, packing in a UniformBlock is unintuitive. + * For example the actual layout of `someVec3Array` above in memory + * is `1, 2, 3, unused, 4, 5, 6, unused`. twgl takes in 6 values + * as shown about and copies them, skipping the padding. This might + * be confusing if you're already familiar with Uniform blocks. + * + * If you want to deal with the padding yourself you can access the array + * buffer views directly. eg: + * + * someBlockInfo.someVec3Array.set([1, 2, 3, 0, 4, 5, 6, 0]); + * + * Any name that doesn't match will be ignored + * @memberOf module:twgl/programs + */ +function setBlockUniforms(uniformBlockInfo, values) { + const setters = uniformBlockInfo.setters; + for (const name in values) { + const setter = setters[name]; + if (setter) { + const value = values[name]; + setter(value); + } + } +} + +function setUniformTree(tree, values) { + for (const name in values) { + const prop = tree[name]; + if (typeof prop === 'function') { + prop(values[name]); + } else { + setUniformTree(tree[name], values[name]); + } + } +} + +/** + * Set uniforms and binds related textures. + * + * example: + * + * const programInfo = createProgramInfo( + * gl, ["some-vs", "some-fs"]); + * + * const tex1 = gl.createTexture(); + * const tex2 = gl.createTexture(); + * + * ... assume we setup the textures with data ... + * + * const uniforms = { + * u_someSampler: tex1, + * u_someOtherSampler: tex2, + * u_someColor: [1,0,0,1], + * u_somePosition: [0,1,1], + * u_someMatrix: [ + * 1,0,0,0, + * 0,1,0,0, + * 0,0,1,0, + * 0,0,0,0, + * ], + * }; + * + * gl.useProgram(programInfo.program); + * + * This will automatically bind the textures AND set the + * uniforms. + * + * twgl.setUniforms(programInfo, uniforms); + * + * For the example above it is equivalent to + * + * let texUnit = 0; + * gl.activeTexture(gl.TEXTURE0 + texUnit); + * gl.bindTexture(gl.TEXTURE_2D, tex1); + * gl.uniform1i(u_someSamplerLocation, texUnit++); + * gl.activeTexture(gl.TEXTURE0 + texUnit); + * gl.bindTexture(gl.TEXTURE_2D, tex2); + * gl.uniform1i(u_someSamplerLocation, texUnit++); + * gl.uniform4fv(u_someColorLocation, [1, 0, 0, 1]); + * gl.uniform3fv(u_somePositionLocation, [0, 1, 1]); + * gl.uniformMatrix4fv(u_someMatrix, false, [ + * 1,0,0,0, + * 0,1,0,0, + * 0,0,1,0, + * 0,0,0,0, + * ]); + * + * Note it is perfectly reasonable to call `setUniforms` multiple times. For example + * + * const uniforms = { + * u_someSampler: tex1, + * u_someOtherSampler: tex2, + * }; + * + * const moreUniforms { + * u_someColor: [1,0,0,1], + * u_somePosition: [0,1,1], + * u_someMatrix: [ + * 1,0,0,0, + * 0,1,0,0, + * 0,0,1,0, + * 0,0,0,0, + * ], + * }; + * + * twgl.setUniforms(programInfo, uniforms); + * twgl.setUniforms(programInfo, moreUniforms); + * + * You can also add WebGLSamplers to uniform samplers as in + * + * const uniforms = { + * u_someSampler: { + * texture: someWebGLTexture, + * sampler: someWebGLSampler, + * }, + * }; + * + * In which case both the sampler and texture will be bound to the + * same unit. + * + * @param {(module:twgl.ProgramInfo|Object.)} setters a `ProgramInfo` as returned from `createProgramInfo` or the setters returned from + * `createUniformSetters`. + * @param {Object.} values an object with values for the + * uniforms. + * You can pass multiple objects by putting them in an array or by calling with more arguments.For example + * + * const sharedUniforms = { + * u_fogNear: 10, + * u_projection: ... + * ... + * }; + * + * const localUniforms = { + * u_world: ... + * u_diffuseColor: ... + * }; + * + * twgl.setUniforms(programInfo, sharedUniforms, localUniforms); + * + * // is the same as + * + * twgl.setUniforms(programInfo, [sharedUniforms, localUniforms]); + * + * // is the same as + * + * twgl.setUniforms(programInfo, sharedUniforms); + * twgl.setUniforms(programInfo, localUniforms}; + * + * You can also fill out structure and array values either via + * shortcut. Example + * + * // -- in shader -- + * struct Light { + * float intensity; + * vec4 color; + * float nearFar[2]; + * }; + * uniform Light lights[2]; + * + * // in JavaScript + * + * twgl.setUniforms(programInfo, { + * lights: [ + * { intensity: 5.0, color: [1, 0, 0, 1], nearFar[0.1, 10] }, + * { intensity: 2.0, color: [0, 0, 1, 1], nearFar[0.2, 15] }, + * ], + * }); + * + * or the more traditional way + * + * twgl.setUniforms(programInfo, { + * "lights[0].intensity": 5.0, + * "lights[0].color": [1, 0, 0, 1], + * "lights[0].nearFar": [0.1, 10], + * "lights[1].intensity": 2.0, + * "lights[1].color": [0, 0, 1, 1], + * "lights[1].nearFar": [0.2, 15], + * }); + * + * You can also specify partial paths + * + * twgl.setUniforms(programInfo, { + * 'lights[1]': { intensity: 5.0, color: [1, 0, 0, 1], nearFar[0.2, 15] }, + * }); + * + * But you can not specify leaf array indices + * + * twgl.setUniforms(programInfo, { + * 'lights[1].nearFar[1]': 15, // BAD! nearFar is a leaf + * 'lights[1].nearFar': [0.2, 15], // GOOD + * }); + * + * @memberOf module:twgl/programs + */ +function setUniforms(setters, ...args) { // eslint-disable-line + const actualSetters = setters.uniformSetters || setters; + const numArgs = args.length; + for (let aNdx = 0; aNdx < numArgs; ++aNdx) { + const values = args[aNdx]; + if (Array.isArray(values)) { + const numValues = values.length; + for (let ii = 0; ii < numValues; ++ii) { + setUniforms(actualSetters, values[ii]); + } + } else { + for (const name in values) { + const setter = actualSetters[name]; + if (setter) { + setter(values[name]); + } + } + } + } +} + +/** + * Alias for `setUniforms` + * @function + * @param {(module:twgl.ProgramInfo|Object.)} setters a `ProgramInfo` as returned from `createProgramInfo` or the setters returned from + * `createUniformSetters`. + * @param {Object.} values an object with values for the + * @memberOf module:twgl/programs + */ +const setUniformsAndBindTextures = setUniforms; + +/** + * Creates setter functions for all attributes of a shader + * program. You can pass this to {@link module:twgl.setBuffersAndAttributes} to set all your buffers and attributes. + * + * @see {@link module:twgl.setAttributes} for example + * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @param {WebGLProgram} program the program to create setters for. + * @return {Object.} an object with a setter for each attribute by name. + * @memberOf module:twgl/programs + */ +function createAttributeSetters(gl, program) { + const attribSetters = { + }; + + const numAttribs = gl.getProgramParameter(program, ACTIVE_ATTRIBUTES); + for (let ii = 0; ii < numAttribs; ++ii) { + const attribInfo = gl.getActiveAttrib(program, ii); + if (isBuiltIn(attribInfo)) { + continue; + } + const index = gl.getAttribLocation(program, attribInfo.name); + const typeInfo = attrTypeMap[attribInfo.type]; + const setter = typeInfo.setter(gl, index, typeInfo); + setter.location = index; + attribSetters[attribInfo.name] = setter; + } + + return attribSetters; +} + +/** + * Sets attributes and binds buffers (deprecated... use {@link module:twgl.setBuffersAndAttributes}) + * + * Example: + * + * const program = createProgramFromScripts( + * gl, ["some-vs", "some-fs"); + * + * const attribSetters = createAttributeSetters(program); + * + * const positionBuffer = gl.createBuffer(); + * const texcoordBuffer = gl.createBuffer(); + * + * const attribs = { + * a_position: {buffer: positionBuffer, numComponents: 3}, + * a_texcoord: {buffer: texcoordBuffer, numComponents: 2}, + * }; + * + * gl.useProgram(program); + * + * This will automatically bind the buffers AND set the + * attributes. + * + * setAttributes(attribSetters, attribs); + * + * Properties of attribs. For each attrib you can add + * properties: + * + * * type: the type of data in the buffer. Default = gl.FLOAT + * * normalize: whether or not to normalize the data. Default = false + * * stride: the stride. Default = 0 + * * offset: offset into the buffer. Default = 0 + * * divisor: the divisor for instances. Default = undefined + * + * For example if you had 3 value float positions, 2 value + * float texcoord and 4 value uint8 colors you'd setup your + * attribs like this + * + * const attribs = { + * a_position: {buffer: positionBuffer, numComponents: 3}, + * a_texcoord: {buffer: texcoordBuffer, numComponents: 2}, + * a_color: { + * buffer: colorBuffer, + * numComponents: 4, + * type: gl.UNSIGNED_BYTE, + * normalize: true, + * }, + * }; + * + * @param {Object.} setters Attribute setters as returned from createAttributeSetters + * @param {Object.} buffers AttribInfos mapped by attribute name. + * @memberOf module:twgl/programs + * @deprecated use {@link module:twgl.setBuffersAndAttributes} + * @private + */ +function setAttributes(setters, buffers) { + for (const name in buffers) { + const setter = setters[name]; + if (setter) { + setter(buffers[name]); + } + } +} + +/** + * Sets attributes and buffers including the `ELEMENT_ARRAY_BUFFER` if appropriate + * + * Example: + * + * const programInfo = createProgramInfo( + * gl, ["some-vs", "some-fs"); + * + * const arrays = { + * position: { numComponents: 3, data: [0, 0, 0, 10, 0, 0, 0, 10, 0, 10, 10, 0], }, + * texcoord: { numComponents: 2, data: [0, 0, 0, 1, 1, 0, 1, 1], }, + * }; + * + * const bufferInfo = createBufferInfoFromArrays(gl, arrays); + * + * gl.useProgram(programInfo.program); + * + * This will automatically bind the buffers AND set the + * attributes. + * + * setBuffersAndAttributes(gl, programInfo, bufferInfo); + * + * For the example above it is equivalent to + * + * gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); + * gl.enableVertexAttribArray(a_positionLocation); + * gl.vertexAttribPointer(a_positionLocation, 3, gl.FLOAT, false, 0, 0); + * gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer); + * gl.enableVertexAttribArray(a_texcoordLocation); + * gl.vertexAttribPointer(a_texcoordLocation, 4, gl.FLOAT, false, 0, 0); + * + * @param {WebGLRenderingContext} gl A WebGLRenderingContext. + * @param {(module:twgl.ProgramInfo|Object.)} setters A `ProgramInfo` as returned from {@link module:twgl.createProgramInfo} or Attribute setters as returned from {@link module:twgl.createAttributeSetters} + * @param {(module:twgl.BufferInfo|module:twgl.VertexArrayInfo)} buffers a `BufferInfo` as returned from {@link module:twgl.createBufferInfoFromArrays}. + * or a `VertexArrayInfo` as returned from {@link module:twgl.createVertexArrayInfo} + * @memberOf module:twgl/programs + */ +function setBuffersAndAttributes(gl, programInfo, buffers) { + if (buffers.vertexArrayObject) { + gl.bindVertexArray(buffers.vertexArrayObject); + } else { + setAttributes(programInfo.attribSetters || programInfo, buffers.attribs); + if (buffers.indices) { + gl.bindBuffer(ELEMENT_ARRAY_BUFFER$1, buffers.indices); + } + } +} + +/** + * @typedef {Object} ProgramInfo + * @property {WebGLProgram} program A shader program + * @property {Object} uniformSetters object of setters as returned from createUniformSetters, + * @property {Object} attribSetters object of setters as returned from createAttribSetters, + * @property {module:twgl.UniformBlockSpec} [uniformBlockSpec] a uniform block spec for making UniformBlockInfos with createUniformBlockInfo etc.. + * @property {Object} [transformFeedbackInfo] info for transform feedbacks + * @memberOf module:twgl + */ + +/** + * Creates a ProgramInfo from an existing program. + * + * A ProgramInfo contains + * + * programInfo = { + * program: WebGLProgram, + * uniformSetters: object of setters as returned from createUniformSetters, + * attribSetters: object of setters as returned from createAttribSetters, + * } + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext + * to use. + * @param {WebGLProgram} program an existing WebGLProgram. + * @return {module:twgl.ProgramInfo} The created ProgramInfo. + * @memberOf module:twgl/programs + */ +function createProgramInfoFromProgram(gl, program) { + const uniformSetters = createUniformSetters(gl, program); + const attribSetters = createAttributeSetters(gl, program); + const programInfo = { + program, + uniformSetters, + attribSetters, + }; + + if (isWebGL2(gl)) { + programInfo.uniformBlockSpec = createUniformBlockSpecFromProgram(gl, program); + programInfo.transformFeedbackInfo = createTransformFeedbackInfo(gl, program); + } + + return programInfo; +} + +const notIdRE = /\s|{|}|;/; + +/** + * Creates a ProgramInfo from 2 sources. + * + * A ProgramInfo contains + * + * programInfo = { + * program: WebGLProgram, + * uniformSetters: object of setters as returned from createUniformSetters, + * attribSetters: object of setters as returned from createAttribSetters, + * } + * + * NOTE: There are 4 signatures for this function + * + * twgl.createProgramInfo(gl, [vs, fs], options); + * twgl.createProgramInfo(gl, [vs, fs], opt_errFunc); + * twgl.createProgramInfo(gl, [vs, fs], opt_attribs, opt_errFunc); + * twgl.createProgramInfo(gl, [vs, fs], opt_attribs, opt_locations, opt_errFunc); + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext + * to use. + * @param {string[]} shaderSources Array of sources for the + * shaders or ids. The first is assumed to be the vertex shader, + * the second the fragment shader. + * @param {module:twgl.ProgramOptions|string[]|module:twgl.ErrorCallback} [opt_attribs] Options for the program or an array of attribs names or an error callback. Locations will be assigned by index if not passed in + * @param {number[]} [opt_locations|module:twgl.ErrorCallback] The locations for the. A parallel array to opt_attribs letting you assign locations or an error callback. + * @param {module:twgl.ErrorCallback} [opt_errorCallback] callback for errors. By default it just prints an error to the console + * on error. If you want something else pass an callback. It's passed an error message. + * @return {module:twgl.ProgramInfo?} The created ProgramInfo or null if it failed to link or compile + * @memberOf module:twgl/programs + */ +function createProgramInfo( + gl, shaderSources, opt_attribs, opt_locations, opt_errorCallback) { + const progOptions = getProgramOptions(opt_attribs, opt_locations, opt_errorCallback); + const errors = []; + shaderSources = shaderSources.map(function(source) { + // Lets assume if there is no \n it's an id + if (!notIdRE.test(source)) { + const script = getElementById(source); + if (!script) { + const err = `no element with id: ${source}`; + progOptions.errorCallback(err); + errors.push(err); + } else { + source = script.text; + } + } + return source; + }); + + if (errors.length) { + return reportError(progOptions, ''); + } + + const origCallback = progOptions.callback; + if (origCallback) { + progOptions.callback = (err, program) => { + origCallback(err, err ? undefined : createProgramInfoFromProgram(gl, program)); + }; + } + + const program = createProgramFromSources(gl, shaderSources, progOptions); + if (!program) { + return null; + } + + return createProgramInfoFromProgram(gl, program); +} + +function checkAllPrograms(gl, programs, programSpecs, noDeleteShadersSet, programOptions) { + // check errors for everything. + for (const [name, program] of Object.entries(programs)) { + const options = {...programOptions}; + const spec = programSpecs[name]; + if (!Array.isArray(spec)) { + Object.assign(options, spec); + } + const errors = getProgramErrors(gl, program, options.errorCallback); + if (errors) { + // delete everything we created + for (const program of Object.values(programs)) { + const shaders = gl.getAttachedShaders(program); + gl.deleteProgram(program); + for (const shader of shaders) { + // Don't delete it if we didn't create it. + if (!noDeleteShadersSet.has(shader)) { + gl.deleteShader(shader); + } + } + } + return errors; + } + } + + return undefined; +} + +/** + * Creates multiple programs + * + * Note: the reason this function exists is because the fastest way to create multiple + * programs in WebGL is to create and compile all shaders and link all programs and only + * afterwards check if they succeeded. In that way, giving all your shaders + * + * @see {@link module:twgl.createProgram} + * + * Example: + * + * const programs = twgl.createPrograms(gl, { + * lambert: [lambertVS, lambertFS], + * phong: [phongVS, phoneFS], + * particles: { + * shaders: [particlesVS, particlesFS], + * transformFeedbackVaryings: ['position', 'velocity'], + * }, + * }); + * + * @param {WebGLRenderingContext} gl the WebGLRenderingContext + * @param {Object.} programSpecs An object of ProgramSpecs, one per program. + * @param {module:twgl.ProgramOptions} [programOptions] options to apply to all programs + * @return {Object.?} the created programInfos by name + */ +function createPrograms(gl, programSpecs, programOptions = {}) { + // Remember existing shaders so that if there is an error we don't delete them + const noDeleteShadersSet = new Set(); + + // compile and link everything + const programs = Object.fromEntries(Object.entries(programSpecs).map(([name, spec]) => { + const options = {...programOptions}; + const shaders = Array.isArray(spec) ? spec : spec.shaders; + if (!Array.isArray(spec)) { + Object.assign(options, spec); + } + shaders.forEach(noDeleteShadersSet.add, noDeleteShadersSet); + return [name, createProgramNoCheck(gl, shaders, options)]; + })); + + if (programOptions.callback) { + waitForAllProgramsLinkCompletionAsync(gl, programs).then(() => { + const errors = checkAllPrograms(gl, programs, programSpecs, noDeleteShadersSet, programOptions); + programOptions.callback(errors, errors ? undefined : programs); + }); + return undefined; + } + + const errors = checkAllPrograms(gl, programs, programSpecs, noDeleteShadersSet, programOptions); + return errors ? undefined : programs; +} + +/** + * Creates multiple programInfos + * + * Note: the reason this function exists is because the fastest way to create multiple + * programs in WebGL is to create and compile all shaders and link all programs and only + * afterwards check if they succeeded. In that way, giving all your shaders + * + * @see {@link module:twgl.createProgramInfo} + * + * Examples: + * + * const programInfos = twgl.createProgramInfos(gl, { + * lambert: [lambertVS, lambertFS], + * phong: [phongVS, phoneFS], + * particles: { + * shaders: [particlesVS, particlesFS], + * transformFeedbackVaryings: ['position', 'velocity'], + * }, + * }); + * + * or + * + * const {lambert, phong, particles} = twgl.createProgramInfos(gl, { + * lambert: [lambertVS, lambertFS], + * phong: [phongVS, phoneFS], + * particles: { + * shaders: [particlesVS, particlesFS], + * transformFeedbackVaryings: ['position', 'velocity'], + * }, + * }); + * + * + * @param {WebGLRenderingContext} gl the WebGLRenderingContext + * @param {Object.} programSpecs An object of ProgramSpecs, one per program. + * @param {module:twgl.ProgramOptions} [programOptions] options to apply to all programs + * @return {Object.?} the created programInfos by name + */ +function createProgramInfos(gl, programSpecs, programOptions) { + programOptions = getProgramOptions(programOptions); + + function createProgramInfosForPrograms(gl, programs) { + return Object.fromEntries(Object.entries(programs).map(([name, program]) => + [name, createProgramInfoFromProgram(gl, program)] + )); + } + + const origCallback = programOptions.callback; + if (origCallback) { + programOptions.callback = (err, programs) => { + origCallback(err, err ? undefined : createProgramInfosForPrograms(gl, programs)); + }; + } + + const programs = createPrograms(gl, programSpecs, programOptions); + if (origCallback || !programs) { + return undefined; + } + + return createProgramInfosForPrograms(gl, programs); +} + +/** + * Creates multiple programs asynchronously + * + * @see {@link module:twgl.createProgramAsync} + * + * Example: + * + * const programs = await twgl.createProgramsAsync(gl, { + * lambert: [lambertVS, lambertFS], + * phong: [phongVS, phoneFS], + * particles: { + * shaders: [particlesVS, particlesFS], + * transformFeedbackVaryings: ['position', 'velocity'], + * }, + * }); + * + * @function + * @param {WebGLRenderingContext} gl the WebGLRenderingContext + * @param {Object.} programSpecs An object of ProgramSpecs, one per program. + * @param {module:twgl.ProgramOptions} [programOptions] options to apply to all programs + * @return {Object.?} the created programInfos by name + */ +const createProgramsAsync = wrapCallbackFnToAsyncFn(createPrograms); + +/** + * Creates multiple programInfos asynchronously + * + * @see {@link module:twgl.createProgramInfoAsync} + * + * Example: + * + * const programInfos = await twgl.createProgramInfosAsync(gl, { + * lambert: [lambertVS, lambertFS], + * phong: [phongVS, phoneFS], + * particles: { + * shaders: [particlesVS, particlesFS], + * transformFeedbackVaryings: ['position', 'velocity'], + * }, + * }); + * + * @function + * @param {WebGLRenderingContext} gl the WebGLRenderingContext + * @param {Object.} programSpecs An object of ProgramSpecs, one per program. + * @param {module:twgl.ProgramOptions} [programOptions] options to apply to all programs + * @return {Promise>} the created programInfos by name + */ +const createProgramInfosAsync = wrapCallbackFnToAsyncFn(createProgramInfos); + +var programs = /*#__PURE__*/Object.freeze({ + __proto__: null, + createAttributeSetters: createAttributeSetters, + createProgram: createProgram, + createProgramAsync: createProgramAsync, + createPrograms: createPrograms, + createProgramsAsync: createProgramsAsync, + createProgramFromScripts: createProgramFromScripts, + createProgramFromSources: createProgramFromSources, + createProgramInfo: createProgramInfo, + createProgramInfoAsync: createProgramInfoAsync, + createProgramInfos: createProgramInfos, + createProgramInfosAsync: createProgramInfosAsync, + createProgramInfoFromProgram: createProgramInfoFromProgram, + createUniformSetters: createUniformSetters, + createUniformBlockSpecFromProgram: createUniformBlockSpecFromProgram, + createUniformBlockInfoFromProgram: createUniformBlockInfoFromProgram, + createUniformBlockInfo: createUniformBlockInfo, + createTransformFeedback: createTransformFeedback, + createTransformFeedbackInfo: createTransformFeedbackInfo, + bindTransformFeedbackInfo: bindTransformFeedbackInfo, + setAttributes: setAttributes, + setBuffersAndAttributes: setBuffersAndAttributes, + setUniforms: setUniforms, + setUniformsAndBindTextures: setUniformsAndBindTextures, + setUniformBlock: setUniformBlock, + setBlockUniforms: setBlockUniforms, + bindUniformBlock: bindUniformBlock +}); + +/* + * Copyright 2019 Gregg Tavares + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +const TRIANGLES = 0x0004; +const UNSIGNED_SHORT = 0x1403; + +/** + * Drawing related functions + * + * For backward compatibility they are available at both `twgl.draw` and `twgl` + * itself + * + * See {@link module:twgl} for core functions + * + * @module twgl/draw + */ + +/** + * Calls `gl.drawElements` or `gl.drawArrays`, whichever is appropriate + * + * normally you'd call `gl.drawElements` or `gl.drawArrays` yourself + * but calling this means if you switch from indexed data to non-indexed + * data you don't have to remember to update your draw call. + * + * @param {WebGLRenderingContext} gl A WebGLRenderingContext + * @param {(module:twgl.BufferInfo|module:twgl.VertexArrayInfo)} bufferInfo A BufferInfo as returned from {@link module:twgl.createBufferInfoFromArrays} or + * a VertexArrayInfo as returned from {@link module:twgl.createVertexArrayInfo} + * @param {number} [type] eg (gl.TRIANGLES, gl.LINES, gl.POINTS, gl.TRIANGLE_STRIP, ...). Defaults to `gl.TRIANGLES` + * @param {number} [count] An optional count. Defaults to bufferInfo.numElements + * @param {number} [offset] An optional offset. Defaults to 0. + * @param {number} [instanceCount] An optional instanceCount. if set then `drawArraysInstanced` or `drawElementsInstanced` will be called + * @memberOf module:twgl/draw + */ +function drawBufferInfo(gl, bufferInfo, type, count, offset, instanceCount) { + type = type === undefined ? TRIANGLES : type; + const indices = bufferInfo.indices; + const elementType = bufferInfo.elementType; + const numElements = count === undefined ? bufferInfo.numElements : count; + offset = offset === undefined ? 0 : offset; + if (elementType || indices) { + if (instanceCount !== undefined) { + gl.drawElementsInstanced(type, numElements, elementType === undefined ? UNSIGNED_SHORT : bufferInfo.elementType, offset, instanceCount); + } else { + gl.drawElements(type, numElements, elementType === undefined ? UNSIGNED_SHORT : bufferInfo.elementType, offset); + } + } else { + if (instanceCount !== undefined) { + gl.drawArraysInstanced(type, offset, numElements, instanceCount); + } else { + gl.drawArrays(type, offset, numElements); + } + } +} + +/** + * A DrawObject is useful for putting objects in to an array and passing them to {@link module:twgl.drawObjectList}. + * + * You need either a `BufferInfo` or a `VertexArrayInfo`. + * + * @typedef {Object} DrawObject + * @property {boolean} [active] whether or not to draw. Default = `true` (must be `false` to be not true). In other words `undefined` = `true` + * @property {number} [type] type to draw eg. `gl.TRIANGLES`, `gl.LINES`, etc... + * @property {module:twgl.ProgramInfo} programInfo A ProgramInfo as returned from {@link module:twgl.createProgramInfo} + * @property {module:twgl.BufferInfo} [bufferInfo] A BufferInfo as returned from {@link module:twgl.createBufferInfoFromArrays} + * @property {module:twgl.VertexArrayInfo} [vertexArrayInfo] A VertexArrayInfo as returned from {@link module:twgl.createVertexArrayInfo} + * @property {Object} uniforms The values for the uniforms. + * You can pass multiple objects by putting them in an array. For example + * + * var sharedUniforms = { + * u_fogNear: 10, + * u_projection: ... + * ... + * }; + * + * var localUniforms = { + * u_world: ... + * u_diffuseColor: ... + * }; + * + * var drawObj = { + * ... + * uniforms: [sharedUniforms, localUniforms], + * }; + * + * @property {number} [offset] the offset to pass to `gl.drawArrays` or `gl.drawElements`. Defaults to 0. + * @property {number} [count] the count to pass to `gl.drawArrays` or `gl.drawElements`. Defaults to bufferInfo.numElements. + * @property {number} [instanceCount] the number of instances. Defaults to undefined. + * @memberOf module:twgl + */ + +/** + * Draws a list of objects + * @param {WebGLRenderingContext} gl A WebGLRenderingContext + * @param {DrawObject[]} objectsToDraw an array of objects to draw. + * @memberOf module:twgl/draw + */ +function drawObjectList(gl, objectsToDraw) { + let lastUsedProgramInfo = null; + let lastUsedBufferInfo = null; + + objectsToDraw.forEach(function(object) { + if (object.active === false) { + return; + } + + const programInfo = object.programInfo; + const bufferInfo = object.vertexArrayInfo || object.bufferInfo; + let bindBuffers = false; + const type = object.type === undefined ? TRIANGLES : object.type; + + if (programInfo !== lastUsedProgramInfo) { + lastUsedProgramInfo = programInfo; + gl.useProgram(programInfo.program); + + // We have to rebind buffers when changing programs because we + // only bind buffers the program uses. So if 2 programs use the same + // bufferInfo but the 1st one uses only positions the when the + // we switch to the 2nd one some of the attributes will not be on. + bindBuffers = true; + } + + // Setup all the needed attributes. + if (bindBuffers || bufferInfo !== lastUsedBufferInfo) { + if (lastUsedBufferInfo && lastUsedBufferInfo.vertexArrayObject && !bufferInfo.vertexArrayObject) { + gl.bindVertexArray(null); + } + lastUsedBufferInfo = bufferInfo; + setBuffersAndAttributes(gl, programInfo, bufferInfo); + } + + // Set the uniforms. + setUniforms(programInfo, object.uniforms); + + // Draw + drawBufferInfo(gl, bufferInfo, type, object.count, object.offset, object.instanceCount); + }); + + if (lastUsedBufferInfo && lastUsedBufferInfo.vertexArrayObject) { + gl.bindVertexArray(null); + } +} + +var draw = /*#__PURE__*/Object.freeze({ + __proto__: null, + drawBufferInfo: drawBufferInfo, + drawObjectList: drawObjectList +}); + +/* + * Copyright 2019 Gregg Tavares + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +const FRAMEBUFFER = 0x8d40; +const RENDERBUFFER = 0x8d41; +const TEXTURE_2D = 0x0de1; + +const UNSIGNED_BYTE = 0x1401; + +/* PixelFormat */ +const DEPTH_COMPONENT = 0x1902; +const RGBA = 0x1908; +const DEPTH_COMPONENT24 = 0x81a6; +const DEPTH_COMPONENT32F = 0x8cac; +const DEPTH24_STENCIL8 = 0x88f0; +const DEPTH32F_STENCIL8 = 0x8cad; + +/* Framebuffer Object. */ +const RGBA4 = 0x8056; +const RGB5_A1 = 0x8057; +const RGB565 = 0x8D62; +const DEPTH_COMPONENT16 = 0x81A5; +const STENCIL_INDEX = 0x1901; +const STENCIL_INDEX8 = 0x8D48; +const DEPTH_STENCIL = 0x84F9; +const COLOR_ATTACHMENT0 = 0x8CE0; +const DEPTH_ATTACHMENT = 0x8D00; +const STENCIL_ATTACHMENT = 0x8D20; +const DEPTH_STENCIL_ATTACHMENT = 0x821A; + +/* TextureWrapMode */ +const CLAMP_TO_EDGE = 0x812F; + +/* TextureMagFilter */ +const LINEAR = 0x2601; + +/** + * The options for a framebuffer attachment. + * + * Note: For a `format` that is a texture include all the texture + * options from {@link module:twgl.TextureOptions} for example + * `min`, `mag`, `clamp`, etc... Note that unlike {@link module:twgl.TextureOptions} + * `auto` defaults to `false` for attachment textures but `min` and `mag` default + * to `gl.LINEAR` and `wrap` defaults to `CLAMP_TO_EDGE` + * + * @typedef {Object} AttachmentOptions + * @property {number} [attachmentPoint] The attachment point. Defaults + * to `gl.COLOR_ATTACHMENT0 + ndx` unless type is a depth or stencil type + * then it's gl.DEPTH_ATTACHMENT or `gl.DEPTH_STENCIL_ATTACHMENT` depending + * on the format or attachment type. + * @property {number} [format] The format. If one of `gl.RGBA4`, + * `gl.RGB565`, `gl.RGB5_A1`, `gl.DEPTH_COMPONENT16`, + * `gl.STENCIL_INDEX8` or `gl.DEPTH_STENCIL` then will create a + * renderbuffer. Otherwise will create a texture. Default = `gl.RGBA` + * @property {number} [type] The type. Used for texture. Default = `gl.UNSIGNED_BYTE`. + * @property {number} [target] The texture target for `gl.framebufferTexture2D`. + * Defaults to `gl.TEXTURE_2D`. Set to appropriate face for cube maps. + * @property {number} [samples] The number of samples. Default = 1 + * @property {number} [level] level for `gl.framebufferTexture2D`. Defaults to 0. + * @property {number} [layer] layer for `gl.framebufferTextureLayer`. Defaults to undefined. + * If set then `gl.framebufferTextureLayer` is called, if not then `gl.framebufferTexture2D` + * @property {(WebGLRenderbuffer | WebGLTexture)} [attachment] An existing renderbuffer or texture. + * If provided will attach this Object. This allows you to share + * attachments across framebuffers. + * @memberOf module:twgl + * @mixes module:twgl.TextureOptions + */ + +const defaultAttachments = [ + { format: RGBA, type: UNSIGNED_BYTE, min: LINEAR, wrap: CLAMP_TO_EDGE, }, + { format: DEPTH_STENCIL, }, +]; + +const attachmentsByFormat = {}; +attachmentsByFormat[DEPTH_STENCIL] = DEPTH_STENCIL_ATTACHMENT; +attachmentsByFormat[STENCIL_INDEX] = STENCIL_ATTACHMENT; +attachmentsByFormat[STENCIL_INDEX8] = STENCIL_ATTACHMENT; +attachmentsByFormat[DEPTH_COMPONENT] = DEPTH_ATTACHMENT; +attachmentsByFormat[DEPTH_COMPONENT16] = DEPTH_ATTACHMENT; +attachmentsByFormat[DEPTH_COMPONENT24] = DEPTH_ATTACHMENT; +attachmentsByFormat[DEPTH_COMPONENT32F] = DEPTH_ATTACHMENT; +attachmentsByFormat[DEPTH24_STENCIL8] = DEPTH_STENCIL_ATTACHMENT; +attachmentsByFormat[DEPTH32F_STENCIL8] = DEPTH_STENCIL_ATTACHMENT; + +function getAttachmentPointForFormat(format, internalFormat) { + return attachmentsByFormat[format] || attachmentsByFormat[internalFormat]; +} + +const renderbufferFormats = {}; +renderbufferFormats[RGBA4] = true; +renderbufferFormats[RGB5_A1] = true; +renderbufferFormats[RGB565] = true; +renderbufferFormats[DEPTH_STENCIL] = true; +renderbufferFormats[DEPTH_COMPONENT16] = true; +renderbufferFormats[STENCIL_INDEX] = true; +renderbufferFormats[STENCIL_INDEX8] = true; + +function isRenderbufferFormat(format) { + return renderbufferFormats[format]; +} + +const MAX_COLOR_ATTACHMENT_POINTS = 32; // even an 3090 only supports 8 but WebGL/OpenGL ES define constants for 32 + +function isColorAttachmentPoint(attachmentPoint) { + return attachmentPoint >= COLOR_ATTACHMENT0 && attachmentPoint < COLOR_ATTACHMENT0 + MAX_COLOR_ATTACHMENT_POINTS; +} + +/** + * @typedef {Object} FramebufferInfo + * @property {WebGLFramebuffer} framebuffer The WebGLFramebuffer for this framebufferInfo + * @property {Array.<(WebGLRenderbuffer | WebGLTexture)>} attachments The created attachments in the same order as passed in to {@link module:twgl.createFramebufferInfo}. + * @property {number} width The width of the framebuffer and its attachments + * @property {number} height The width of the framebuffer and its attachments + * @memberOf module:twgl + */ + +/** + * Creates a framebuffer and attachments. + * + * This returns a {@link module:twgl.FramebufferInfo} because it needs to return the attachments as well as the framebuffer. + * It also leaves the framebuffer it just created as the currently bound `FRAMEBUFFER`. + * Note: If this is WebGL2 or if you called {@link module:twgl.addExtensionsToContext} then it will set the drawBuffers + * to `[COLOR_ATTACHMENT0, COLOR_ATTACHMENT1, ...]` for how ever many color attachments were created. + * + * The simplest usage + * + * // create an RGBA/UNSIGNED_BYTE texture and DEPTH_STENCIL renderbuffer + * const fbi = twgl.createFramebufferInfo(gl); + * + * More complex usage + * + * // create an RGB565 renderbuffer and a STENCIL_INDEX8 renderbuffer + * const attachments = [ + * { format: RGB565, mag: NEAREST }, + * { format: STENCIL_INDEX8 }, + * ] + * const fbi = twgl.createFramebufferInfo(gl, attachments); + * + * Passing in a specific size + * + * const width = 256; + * const height = 256; + * const fbi = twgl.createFramebufferInfo(gl, attachments, width, height); + * + * **Note!!** It is up to you to check if the framebuffer is renderable by calling `gl.checkFramebufferStatus`. + * [WebGL1 only guarantees 3 combinations of attachments work](https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.6). + * + * @param {WebGLRenderingContext} gl the WebGLRenderingContext + * @param {module:twgl.AttachmentOptions[]} [attachments] which attachments to create. If not provided the default is a framebuffer with an + * `RGBA`, `UNSIGNED_BYTE` texture `COLOR_ATTACHMENT0` and a `DEPTH_STENCIL` renderbuffer `DEPTH_STENCIL_ATTACHMENT`. + * @param {number} [width] the width for the attachments. Default = size of drawingBuffer + * @param {number} [height] the height for the attachments. Default = size of drawingBuffer + * @return {module:twgl.FramebufferInfo} the framebuffer and attachments. + * @memberOf module:twgl/framebuffers + */ +function createFramebufferInfo(gl, attachments, width, height) { + const target = FRAMEBUFFER; + const fb = gl.createFramebuffer(); + gl.bindFramebuffer(target, fb); + width = width || gl.drawingBufferWidth; + height = height || gl.drawingBufferHeight; + attachments = attachments || defaultAttachments; + const usedColorAttachmentsPoints = []; + const framebufferInfo = { + framebuffer: fb, + attachments: [], + width: width, + height: height, + }; + + attachments.forEach(function(attachmentOptions, i) { + let attachment = attachmentOptions.attachment; + const samples = attachmentOptions.samples; + const format = attachmentOptions.format; + let attachmentPoint = attachmentOptions.attachmentPoint || getAttachmentPointForFormat(format, attachmentOptions.internalFormat); + if (!attachmentPoint) { + attachmentPoint = COLOR_ATTACHMENT0 + i; + } + if (isColorAttachmentPoint(attachmentPoint)) { + usedColorAttachmentsPoints.push(attachmentPoint); + } + if (!attachment) { + if (samples !== undefined || isRenderbufferFormat(format)) { + attachment = gl.createRenderbuffer(); + gl.bindRenderbuffer(RENDERBUFFER, attachment); + if (samples > 1) { + gl.renderbufferStorageMultisample(RENDERBUFFER, samples, format, width, height); + } else { + gl.renderbufferStorage(RENDERBUFFER, format, width, height); + } + } else { + const textureOptions = Object.assign({}, attachmentOptions); + textureOptions.width = width; + textureOptions.height = height; + if (textureOptions.auto === undefined) { + textureOptions.auto = false; + textureOptions.min = textureOptions.min || textureOptions.minMag || LINEAR; + textureOptions.mag = textureOptions.mag || textureOptions.minMag || LINEAR; + textureOptions.wrapS = textureOptions.wrapS || textureOptions.wrap || CLAMP_TO_EDGE; + textureOptions.wrapT = textureOptions.wrapT || textureOptions.wrap || CLAMP_TO_EDGE; + } + attachment = createTexture(gl, textureOptions); + } + } + if (isRenderbuffer(gl, attachment)) { + gl.framebufferRenderbuffer(target, attachmentPoint, RENDERBUFFER, attachment); + } else if (isTexture(gl, attachment)) { + if (attachmentOptions.layer !== undefined) { + gl.framebufferTextureLayer( + target, + attachmentPoint, + attachment, + attachmentOptions.level || 0, + attachmentOptions.layer); + } else { + gl.framebufferTexture2D( + target, + attachmentPoint, + attachmentOptions.target || TEXTURE_2D, + attachment, + attachmentOptions.level || 0); + } + } else { + throw new Error('unknown attachment type'); + } + framebufferInfo.attachments.push(attachment); + }); + if (gl.drawBuffers) { + gl.drawBuffers(usedColorAttachmentsPoints); + } + return framebufferInfo; +} + +/** + * Resizes the attachments of a framebuffer. + * + * You need to pass in the same `attachments` as you passed in {@link module:twgl.createFramebufferInfo} + * because TWGL has no idea the format/type of each attachment. + * + * The simplest usage + * + * // create an RGBA/UNSIGNED_BYTE texture and DEPTH_STENCIL renderbuffer + * const fbi = twgl.createFramebufferInfo(gl); + * + * ... + * + * function render() { + * if (twgl.resizeCanvasToDisplaySize(gl.canvas)) { + * // resize the attachments + * twgl.resizeFramebufferInfo(gl, fbi); + * } + * + * More complex usage + * + * // create an RGB565 renderbuffer and a STENCIL_INDEX8 renderbuffer + * const attachments = [ + * { format: RGB565, mag: NEAREST }, + * { format: STENCIL_INDEX8 }, + * ] + * const fbi = twgl.createFramebufferInfo(gl, attachments); + * + * ... + * + * function render() { + * if (twgl.resizeCanvasToDisplaySize(gl.canvas)) { + * // resize the attachments to match + * twgl.resizeFramebufferInfo(gl, fbi, attachments); + * } + * + * @param {WebGLRenderingContext} gl the WebGLRenderingContext + * @param {module:twgl.FramebufferInfo} framebufferInfo a framebufferInfo as returned from {@link module:twgl.createFramebufferInfo}. + * @param {module:twgl.AttachmentOptions[]} [attachments] the same attachments options as passed to {@link module:twgl.createFramebufferInfo}. + * @param {number} [width] the width for the attachments. Default = size of drawingBuffer + * @param {number} [height] the height for the attachments. Default = size of drawingBuffer + * @memberOf module:twgl/framebuffers + */ +function resizeFramebufferInfo(gl, framebufferInfo, attachments, width, height) { + width = width || gl.drawingBufferWidth; + height = height || gl.drawingBufferHeight; + framebufferInfo.width = width; + framebufferInfo.height = height; + attachments = attachments || defaultAttachments; + attachments.forEach(function(attachmentOptions, ndx) { + const attachment = framebufferInfo.attachments[ndx]; + const format = attachmentOptions.format; + const samples = attachmentOptions.samples; + if (samples !== undefined || isRenderbuffer(gl, attachment)) { + gl.bindRenderbuffer(RENDERBUFFER, attachment); + if (samples > 1) { + gl.renderbufferStorageMultisample(RENDERBUFFER, samples, format, width, height); + } else { + gl.renderbufferStorage(RENDERBUFFER, format, width, height); + } + } else if (isTexture(gl, attachment)) { + resizeTexture(gl, attachment, attachmentOptions, width, height); + } else { + throw new Error('unknown attachment type'); + } + }); +} + +/** + * Binds a framebuffer + * + * This function pretty much solely exists because I spent hours + * trying to figure out why something I wrote wasn't working only + * to realize I forget to set the viewport dimensions. + * My hope is this function will fix that. + * + * It is effectively the same as + * + * gl.bindFramebuffer(gl.FRAMEBUFFER, someFramebufferInfo.framebuffer); + * gl.viewport(0, 0, someFramebufferInfo.width, someFramebufferInfo.height); + * + * @param {WebGLRenderingContext} gl the WebGLRenderingContext + * @param {module:twgl.FramebufferInfo|null} [framebufferInfo] a framebufferInfo as returned from {@link module:twgl.createFramebufferInfo}. + * If falsy will bind the canvas. + * @param {number} [target] The target. If not passed `gl.FRAMEBUFFER` will be used. + * @memberOf module:twgl/framebuffers + */ + +function bindFramebufferInfo(gl, framebufferInfo, target) { + target = target || FRAMEBUFFER; + if (framebufferInfo) { + gl.bindFramebuffer(target, framebufferInfo.framebuffer); + gl.viewport(0, 0, framebufferInfo.width, framebufferInfo.height); + } else { + gl.bindFramebuffer(target, null); + gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); + } +} + +var framebuffers = /*#__PURE__*/Object.freeze({ + __proto__: null, + bindFramebufferInfo: bindFramebufferInfo, + createFramebufferInfo: createFramebufferInfo, + resizeFramebufferInfo: resizeFramebufferInfo +}); + +/* + * Copyright 2019 Gregg Tavares + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * vertex array object related functions + * + * You should generally not need to use these functions. They are provided + * for those cases where you're doing something out of the ordinary + * and you need lower level access. + * + * For backward compatibility they are available at both `twgl.attributes` and `twgl` + * itself + * + * See {@link module:twgl} for core functions + * + * @module twgl/vertexArrays + */ + +const ELEMENT_ARRAY_BUFFER = 0x8893; + +/** + * @typedef {Object} VertexArrayInfo + * @property {number} numElements The number of elements to pass to `gl.drawArrays` or `gl.drawElements`. + * @property {number} [elementType] The type of indices `UNSIGNED_BYTE`, `UNSIGNED_SHORT` etc.. + * @property {WebGLVertexArrayObject} [vertexArrayObject] a vertex array object + * @memberOf module:twgl + */ + +/** + * Creates a VertexArrayInfo from a BufferInfo and one or more ProgramInfos + * + * This can be passed to {@link module:twgl.setBuffersAndAttributes} and to + * {@link module:twgl:drawBufferInfo}. + * + * > **IMPORTANT:** Vertex Array Objects are **not** a direct analog for a BufferInfo. Vertex Array Objects + * assign buffers to specific attributes at creation time. That means they can only be used with programs + * who's attributes use the same attribute locations for the same purposes. + * + * > Bind your attribute locations by passing an array of attribute names to {@link module:twgl.createProgramInfo} + * or use WebGL 2's GLSL ES 3's `layout(location = )` to make sure locations match. + * + * also + * + * > **IMPORTANT:** After calling twgl.setBuffersAndAttribute with a BufferInfo that uses a Vertex Array Object + * that Vertex Array Object will be bound. That means **ANY MANIPULATION OF ELEMENT_ARRAY_BUFFER or ATTRIBUTES** + * will affect the Vertex Array Object state. + * + * > Call `gl.bindVertexArray(null)` to get back manipulating the global attributes and ELEMENT_ARRAY_BUFFER. + * + * @param {WebGLRenderingContext} gl A WebGLRenderingContext + * @param {module:twgl.ProgramInfo|module:twgl.ProgramInfo[]} programInfo a programInfo or array of programInfos + * @param {module:twgl.BufferInfo} bufferInfo BufferInfo as returned from createBufferInfoFromArrays etc... + * + * You need to make sure every attribute that will be used is bound. So for example assume shader 1 + * uses attributes A, B, C and shader 2 uses attributes A, B, D. If you only pass in the programInfo + * for shader 1 then only attributes A, B, and C will have their attributes set because TWGL doesn't + * now attribute D's location. + * + * So, you can pass in both shader 1 and shader 2's programInfo + * + * @return {module:twgl.VertexArrayInfo} The created VertexArrayInfo + * + * @memberOf module:twgl/vertexArrays + */ +function createVertexArrayInfo(gl, programInfos, bufferInfo) { + const vao = gl.createVertexArray(); + gl.bindVertexArray(vao); + if (!programInfos.length) { + programInfos = [programInfos]; + } + programInfos.forEach(function(programInfo) { + setBuffersAndAttributes(gl, programInfo, bufferInfo); + }); + gl.bindVertexArray(null); + return { + numElements: bufferInfo.numElements, + elementType: bufferInfo.elementType, + vertexArrayObject: vao, + }; +} + +/** + * Creates a vertex array object and then sets the attributes on it + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @param {Object.} setters Attribute setters as returned from createAttributeSetters + * @param {Object.} attribs AttribInfos mapped by attribute name. + * @param {WebGLBuffer} [indices] an optional ELEMENT_ARRAY_BUFFER of indices + * + * @return {WebGLVertexArrayObject|null} The created WebGLVertexArrayObject + * + * @memberOf module:twgl/vertexArrays + */ +function createVAOAndSetAttributes(gl, setters, attribs, indices) { + const vao = gl.createVertexArray(); + gl.bindVertexArray(vao); + setAttributes(setters, attribs); + if (indices) { + gl.bindBuffer(ELEMENT_ARRAY_BUFFER, indices); + } + // We unbind this because otherwise any change to ELEMENT_ARRAY_BUFFER + // like when creating buffers for other stuff will mess up this VAO's binding + gl.bindVertexArray(null); + return vao; +} + +/** + * Creates a vertex array object and then sets the attributes + * on it + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext + * to use. + * @param {Object.| module:twgl.ProgramInfo} programInfo as returned from createProgramInfo or Attribute setters as returned from createAttributeSetters + * @param {module:twgl.BufferInfo} bufferInfo BufferInfo as returned from createBufferInfoFromArrays etc... + * @param {WebGLBuffer} [indices] an optional ELEMENT_ARRAY_BUFFER of indices + * + * @return {WebGLVertexArrayObject|null} The created WebGLVertexArrayObject + * + * @memberOf module:twgl/vertexArrays + */ +function createVAOFromBufferInfo(gl, programInfo, bufferInfo) { + return createVAOAndSetAttributes(gl, programInfo.attribSetters || programInfo, bufferInfo.attribs, bufferInfo.indices); +} + +var vertexArrays = /*#__PURE__*/Object.freeze({ + __proto__: null, + createVertexArrayInfo: createVertexArrayInfo, + createVAOAndSetAttributes: createVAOAndSetAttributes, + createVAOFromBufferInfo: createVAOFromBufferInfo +}); + +/* + * Copyright 2019 Gregg Tavares + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +const defaults = { + addExtensionsToContext: true, +}; + +/** + * Various default settings for twgl. + * + * Note: You can call this any number of times. Example: + * + * twgl.setDefaults({ textureColor: [1, 0, 0, 1] }); + * twgl.setDefaults({ attribPrefix: 'a_' }); + * + * is equivalent to + * + * twgl.setDefaults({ + * textureColor: [1, 0, 0, 1], + * attribPrefix: 'a_', + * }); + * + * @typedef {Object} Defaults + * @property {string} [attribPrefix] The prefix to stick on attributes + * + * When writing shaders I prefer to name attributes with `a_`, uniforms with `u_` and varyings with `v_` + * as it makes it clear where they came from. But, when building geometry I prefer using un-prefixed names. + * + * In other words I'll create arrays of geometry like this + * + * const arrays = { + * position: ... + * normal: ... + * texcoord: ... + * }; + * + * But need those mapped to attributes and my attributes start with `a_`. + * + * Default: `""` + * + * @property {number[]} [textureColor] Array of 4 values in the range 0 to 1 + * + * The default texture color is used when loading textures from + * urls. Because the URL will be loaded async we'd like to be + * able to use the texture immediately. By putting a 1x1 pixel + * color in the texture we can start using the texture before + * the URL has loaded. + * + * Default: `[0.5, 0.75, 1, 1]` + * + * @property {string} [crossOrigin] + * + * If not undefined sets the crossOrigin attribute on images + * that twgl creates when downloading images for textures. + * + * Also see {@link module:twgl.TextureOptions}. + * + * @property {bool} [addExtensionsToContext] + * + * If true, then, when twgl will try to add any supported WebGL extensions + * directly to the context under their normal GL names. For example + * if ANGLE_instances_arrays exists then twgl would enable it, + * add the functions `vertexAttribDivisor`, `drawArraysInstanced`, + * `drawElementsInstanced`, and the constant `VERTEX_ATTRIB_ARRAY_DIVISOR` + * to the `WebGLRenderingContext`. + * + * @memberOf module:twgl + */ + +/** + * Sets various defaults for twgl. + * + * In the interest of terseness which is kind of the point + * of twgl I've integrated a few of the older functions here + * + * @param {module:twgl.Defaults} newDefaults The default settings. + * @memberOf module:twgl + */ +function setDefaults(newDefaults) { + copyExistingProperties(newDefaults, defaults); + setDefaults$2(newDefaults); // eslint-disable-line + setDefaults$1(newDefaults); // eslint-disable-line +} + +const prefixRE = /^(.*?)_/; +function addExtensionToContext(gl, extensionName) { + glEnumToString(gl, 0); + const ext = gl.getExtension(extensionName); + if (ext) { + const enums = {}; + const fnSuffix = prefixRE.exec(extensionName)[1]; + const enumSuffix = '_' + fnSuffix; + for (const key in ext) { + const value = ext[key]; + const isFunc = typeof (value) === 'function'; + const suffix = isFunc ? fnSuffix : enumSuffix; + let name = key; + // examples of where this is not true are WEBGL_compressed_texture_s3tc + // and WEBGL_compressed_texture_pvrtc + if (key.endsWith(suffix)) { + name = key.substring(0, key.length - suffix.length); + } + if (gl[name] !== undefined) { + if (!isFunc && gl[name] !== value) { + warn$1(name, gl[name], value, key); + } + } else { + if (isFunc) { + gl[name] = function(origFn) { + return function() { + return origFn.apply(ext, arguments); + }; + }(value); + } else { + gl[name] = value; + enums[name] = value; + } + } + } + // pass the modified enums to glEnumToString + enums.constructor = { + name: ext.constructor.name, + }; + glEnumToString(enums, 0); + } + return ext; +} + +/* + * If you're wondering why the code doesn't just iterate + * over all extensions using `gl.getExtensions` is that it's possible + * some future extension is incompatible with this code. Rather than + * have thing suddenly break it seems better to manually add to this + * list. + * + */ +const supportedExtensions = [ + 'ANGLE_instanced_arrays', + 'EXT_blend_minmax', + 'EXT_color_buffer_float', + 'EXT_color_buffer_half_float', + 'EXT_disjoint_timer_query', + 'EXT_disjoint_timer_query_webgl2', + 'EXT_frag_depth', + 'EXT_sRGB', + 'EXT_shader_texture_lod', + 'EXT_texture_filter_anisotropic', + 'OES_element_index_uint', + 'OES_standard_derivatives', + 'OES_texture_float', + 'OES_texture_float_linear', + 'OES_texture_half_float', + 'OES_texture_half_float_linear', + 'OES_vertex_array_object', + 'WEBGL_color_buffer_float', + 'WEBGL_compressed_texture_atc', + 'WEBGL_compressed_texture_etc1', + 'WEBGL_compressed_texture_pvrtc', + 'WEBGL_compressed_texture_s3tc', + 'WEBGL_compressed_texture_s3tc_srgb', + 'WEBGL_depth_texture', + 'WEBGL_draw_buffers', +]; + +/** + * Attempts to enable all of the following extensions + * and add their functions and constants to the + * `WebGLRenderingContext` using their normal non-extension like names. + * + * ANGLE_instanced_arrays + * EXT_blend_minmax + * EXT_color_buffer_float + * EXT_color_buffer_half_float + * EXT_disjoint_timer_query + * EXT_disjoint_timer_query_webgl2 + * EXT_frag_depth + * EXT_sRGB + * EXT_shader_texture_lod + * EXT_texture_filter_anisotropic + * OES_element_index_uint + * OES_standard_derivatives + * OES_texture_float + * OES_texture_float_linear + * OES_texture_half_float + * OES_texture_half_float_linear + * OES_vertex_array_object + * WEBGL_color_buffer_float + * WEBGL_compressed_texture_atc + * WEBGL_compressed_texture_etc1 + * WEBGL_compressed_texture_pvrtc + * WEBGL_compressed_texture_s3tc + * WEBGL_compressed_texture_s3tc_srgb + * WEBGL_depth_texture + * WEBGL_draw_buffers + * + * For example if `ANGLE_instanced_arrays` exists then the functions + * `drawArraysInstanced`, `drawElementsInstanced`, `vertexAttribDivisor` + * and the constant `VERTEX_ATTRIB_ARRAY_DIVISOR` are added to the + * `WebGLRenderingContext`. + * + * Note that if you want to know if the extension exists you should + * probably call `gl.getExtension` for each extension. Alternatively + * you can check for the existence of the functions or constants that + * are expected to be added. For example + * + * if (gl.drawBuffers) { + * // Either WEBGL_draw_buffers was enabled OR you're running in WebGL2 + * .... + * + * @param {WebGLRenderingContext} gl A WebGLRenderingContext + * @memberOf module:twgl + */ +function addExtensionsToContext(gl) { + for (let ii = 0; ii < supportedExtensions.length; ++ii) { + addExtensionToContext(gl, supportedExtensions[ii]); + } +} + +/** + * Creates a webgl context. + * @param {HTMLCanvasElement} canvas The canvas tag to get + * context from. If one is not passed in one will be + * created. + * @return {WebGLRenderingContext} The created context. + * @private + */ +function create3DContext(canvas, opt_attribs) { + const names = ["webgl", "experimental-webgl"]; + let context = null; + for (let ii = 0; ii < names.length; ++ii) { + context = canvas.getContext(names[ii], opt_attribs); + if (context) { + if (defaults.addExtensionsToContext) { + addExtensionsToContext(context); + } + break; + } + } + return context; +} + +/** + * Gets a WebGL1 context. + * + * Note: Will attempt to enable Vertex Array Objects + * and add WebGL2 entry points. (unless you first set defaults with + * `twgl.setDefaults({enableVertexArrayObjects: false})`; + * + * @param {HTMLCanvasElement} canvas a canvas element. + * @param {WebGLContextAttributes} [opt_attribs] optional webgl context creation attributes + * @return {WebGLRenderingContext} The created context. + * @memberOf module:twgl + * @deprecated + * @private + */ +function getWebGLContext(canvas, opt_attribs) { + const gl = create3DContext(canvas, opt_attribs); + return gl; +} + +/** + * Creates a webgl context. + * + * Will return a WebGL2 context if possible. + * + * You can check if it's WebGL2 with + * + * twgl.isWebGL2(gl); + * + * @param {HTMLCanvasElement} canvas The canvas tag to get + * context from. If one is not passed in one will be + * created. + * @return {WebGLRenderingContext} The created context. + */ +function createContext(canvas, opt_attribs) { + const names = ["webgl2", "webgl", "experimental-webgl"]; + let context = null; + for (let ii = 0; ii < names.length; ++ii) { + context = canvas.getContext(names[ii], opt_attribs); + if (context) { + if (defaults.addExtensionsToContext) { + addExtensionsToContext(context); + } + break; + } + } + return context; +} + +/** + * Gets a WebGL context. Will create a WebGL2 context if possible. + * + * You can check if it's WebGL2 with + * + * function isWebGL2(gl) { + * return gl.getParameter(gl.VERSION).indexOf("WebGL 2.0 ") == 0; + * } + * + * Note: For a WebGL1 context will attempt to enable Vertex Array Objects + * and add WebGL2 entry points. (unless you first set defaults with + * `twgl.setDefaults({enableVertexArrayObjects: false})`; + * + * @param {HTMLCanvasElement} canvas a canvas element. + * @param {WebGLContextAttributes} [opt_attribs] optional webgl context creation attributes + * @return {WebGLRenderingContext} The created context. + * @memberOf module:twgl + */ +function getContext(canvas, opt_attribs) { + const gl = createContext(canvas, opt_attribs); + return gl; +} + +/** + * Resize a canvas to match the size it's displayed. + * @param {HTMLCanvasElement} canvas The canvas to resize. + * @param {number} [multiplier] So you can pass in `window.devicePixelRatio` or other scale value if you want to. + * @return {boolean} true if the canvas was resized. + * @memberOf module:twgl + */ +function resizeCanvasToDisplaySize(canvas, multiplier) { + multiplier = multiplier || 1; + multiplier = Math.max(0, multiplier); + const width = canvas.clientWidth * multiplier | 0; + const height = canvas.clientHeight * multiplier | 0; + if (canvas.width !== width || canvas.height !== height) { + canvas.width = width; + canvas.height = height; + return true; + } + return false; +} + +export { addExtensionsToContext, attributes, bindFramebufferInfo, bindTransformFeedbackInfo, bindUniformBlock, canFilter, canGenerateMipmap, createAttribsFromArrays, createAttributeSetters, createBufferFromArray, createBufferFromTypedArray, createBufferInfoFromArrays, createBuffersFromArrays, createFramebufferInfo, createProgram, createProgramAsync, createProgramFromScripts, createProgramFromSources, createProgramInfo, createProgramInfoAsync, createProgramInfoFromProgram, createProgramInfos, createProgramInfosAsync, createPrograms, createProgramsAsync, createSampler, createSamplers, createTexture, createTextures, createTransformFeedback, createTransformFeedbackInfo, createUniformBlockInfo, createUniformBlockInfoFromProgram, createUniformBlockSpecFromProgram, createUniformSetters, createVAOAndSetAttributes, createVAOFromBufferInfo, createVertexArrayInfo, draw, drawBufferInfo, drawObjectList, framebuffers, getArray$1 as getArray_, getBytesPerElementForInternalFormat, getContext, getFormatAndTypeForInternalFormat, getGLTypeForTypedArray, getGLTypeForTypedArrayType, getNumComponentsForFormat, getNumComponents$1 as getNumComponents_, getTypedArrayTypeForGLType, getWebGLContext, glEnumToString, isArrayBuffer$1 as isArrayBuffer, isWebGL1, isWebGL2, loadTextureFromUrl, m4, primitives, programs, resizeCanvasToDisplaySize, resizeFramebufferInfo, resizeTexture, setAttribInfoBufferFromArray, setDefaults$2 as setAttributeDefaults_, setAttributePrefix, setAttributes, setBlockUniforms, setBuffersAndAttributes, setDefaultTextureColor, setDefaults, setEmptyTexture, setSamplerParameters, setDefaults$1 as setTextureDefaults_, setTextureFilteringForSize, setTextureFromArray, setTextureFromElement, setTextureParameters, setUniformBlock, setUniforms, setUniformsAndBindTextures, textures, typedarrays, utils, v3, vertexArrays }; \ No newline at end of file diff --git a/experiments/twgl-tunnel/index.html b/experiments/twgl-tunnel/index.html new file mode 100644 index 0000000..95de90e --- /dev/null +++ b/experiments/twgl-tunnel/index.html @@ -0,0 +1,355 @@ + + + + + + + + + + + + + + + + + diff --git a/experiments/twgl-tunnel/js/amd-compiled.js b/experiments/twgl-tunnel/js/amd-compiled.js new file mode 100644 index 0000000..3944c59 --- /dev/null +++ b/experiments/twgl-tunnel/js/amd-compiled.js @@ -0,0 +1,114 @@ +"use strict"; + +/* global require */ + +require([ + '../../dist/5.x/twgl-full.min', + '../../3rdparty/chroma.min', + ], function( + twgl, + chroma) { + const m4 = twgl.m4; + const primitives = twgl.primitives; + + twgl.setDefaults({attribPrefix: "a_"}); + const gl = document.querySelector("#c").getContext("webgl"); + const programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]); + + const shapes = [ + primitives.createCubeBufferInfo(gl, 2), + primitives.createSphereBufferInfo(gl, 1, 24, 12), + primitives.createPlaneBufferInfo(gl, 2, 2), + primitives.createTruncatedConeBufferInfo(gl, 1, 0, 2, 24, 1), + ]; + + function rand(min, max) { + return min + Math.random() * (max - min); + } + + // Shared values + const lightWorldPosition = [1, 8, -10]; + const lightColor = [1, 1, 1, 1]; + const camera = m4.identity(); + const view = m4.identity(); + const viewProjection = m4.identity(); + + const tex = twgl.createTexture(gl, { + min: gl.NEAREST, + mag: gl.NEAREST, + src: [ + 255, 255, 255, 255, + 192, 192, 192, 255, + 192, 192, 192, 255, + 255, 255, 255, 255, + ], + }); + + const objects = []; + const drawObjects = []; + const numObjects = 100; + const baseHue = rand(0, 360); + for (let ii = 0; ii < numObjects; ++ii) { + const uniforms = { + u_lightWorldPos: lightWorldPosition, + u_lightColor: lightColor, + u_diffuseMult: chroma.hsv((baseHue + rand(0, 60)) % 360, 0.4, 0.8).gl(), + u_specular: [1, 1, 1, 1], + u_shininess: 50, + u_specularFactor: 1, + u_diffuse: tex, + u_viewInverse: camera, + u_world: m4.identity(), + u_worldInverseTranspose: m4.identity(), + u_worldViewProjection: m4.identity(), + }; + drawObjects.push({ + programInfo: programInfo, + bufferInfo: shapes[ii % shapes.length], + uniforms: uniforms, + }); + objects.push({ + translation: [rand(-10, 10), rand(-10, 10), rand(-10, 10)], + ySpeed: rand(0.1, 0.3), + zSpeed: rand(0.1, 0.3), + uniforms: uniforms, + }); + } + + function render(time) { + time *= 0.001; + twgl.resizeCanvasToDisplaySize(gl.canvas); + gl.viewport(0, 0, gl.canvas.width, gl.canvas.height); + + gl.enable(gl.DEPTH_TEST); + gl.enable(gl.CULL_FACE); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + + const projection = m4.perspective(30 * Math.PI / 180, gl.canvas.clientWidth / gl.canvas.clientHeight, 0.5, 100); + const eye = [1, 4, -20]; + const target = [0, 0, 0]; + const up = [0, 1, 0]; + + m4.lookAt(eye, target, up, camera); + m4.inverse(camera, view); + m4.multiply(projection, view, viewProjection); + + objects.forEach(function(obj) { + const uni = obj.uniforms; + const world = uni.u_world; + m4.identity(world); + m4.rotateY(world, time * obj.ySpeed, world); + m4.rotateZ(world, time * obj.zSpeed, world); + m4.translate(world, obj.translation, world); + m4.rotateX(world, time, world); + m4.transpose(m4.inverse(world, uni.u_worldInverseTranspose), uni.u_worldInverseTranspose); + m4.multiply(viewProjection, uni.u_world, uni.u_worldViewProjection); + }); + + twgl.drawObjectList(gl, drawObjects); + + requestAnimationFrame(render); + } + requestAnimationFrame(render); +}); + From 6f2a46a9221188a644a2915d917d0ea9d893fce9 Mon Sep 17 00:00:00 2001 From: atbrakhi Date: Mon, 29 May 2023 14:53:25 +0200 Subject: [PATCH 2/4] add desc and thumb image --- experiments.json | 2 +- experiments/twgl-tunnel/thumb.png | Bin 0 -> 591156 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 experiments/twgl-tunnel/thumb.png diff --git a/experiments.json b/experiments.json index 8ba26ed..35c857d 100644 --- a/experiments.json +++ b/experiments.json @@ -35,7 +35,7 @@ }, { "name": "TWGL-Tunnel", - "desc": "

TWGL.

", + "desc": "

Showing WebGL Capabilites of servo

", "href": "experiments/twgl-tunnel/", "long_description":"" } diff --git a/experiments/twgl-tunnel/thumb.png b/experiments/twgl-tunnel/thumb.png new file mode 100644 index 0000000000000000000000000000000000000000..380a5ad50c9ebd42baa5c34a132d1fa1f2adb211 GIT binary patch literal 591156 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 >n*%{^4tPTF#VohHL_JW)%mmU;zlQ6^S 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 z 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 O5{ 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 IQx04{2b(h%Du!0tP#C{`f0Ji$!&hJXM#{ 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 aKmE&mRZ9Iovs=S}e{xdFk~Pl_gZ>XOc=<^H literal 0 HcmV?d00001 From dd03c9767b5c8968dcf9dfaf49627ef9c59abe44 Mon Sep 17 00:00:00 2001 From: atbrakhi Date: Mon, 29 May 2023 16:45:17 +0200 Subject: [PATCH 3/4] add descrption --- experiments.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/experiments.json b/experiments.json index dfc3471..9cddce8 100644 --- a/experiments.json +++ b/experiments.json @@ -34,10 +34,10 @@ "long_description":"

This experiment provides a visual representation of the browser's activity through the servo-logo image and measures the performance using the FPS count.

You can benchmark your browser with servo-doges

" }, { - "name": "TWGL-Tunnel", - "desc": "

Showing WebGL Capabilites of servo

", + "name": "TWGL Tunnel", + "desc": "

Tunnel effect using WebGL and the TWGL library.

", "href": "experiments/twgl-tunnel/", - "long_description":"" + "long_description":"

This experiment demonstrates the WebGL capabilities of servo. The tunnel effect is created by manipulating vertices and applying transformations to create the illusion of depth and movement.

The demo serves as a demonstration of WebGL capabilities and showcases dynamic and interactive 3D graphics using TWGL

" } ] From 3064199a6453d36fe0a1b1cecdbe3d22522b652f Mon Sep 17 00:00:00 2001 From: atbrakhi Date: Mon, 29 May 2023 16:48:55 +0200 Subject: [PATCH 4/4] format code --- .prettierrc | 3 +- experiments.json | 16 +- experiments/twgl-tunnel/dist/chroma.min.js | 2733 +++- experiments/twgl-tunnel/dist/require.js | 1099 +- experiments/twgl-tunnel/dist/twgl-full.min.js | 6270 ++++++++- .../twgl-tunnel/dist/twgl-full.module.js | 11397 +++++++++------- experiments/twgl-tunnel/index.html | 745 +- experiments/twgl-tunnel/js/amd-compiled.js | 221 +- 8 files changed, 16980 insertions(+), 5504 deletions(-) diff --git a/.prettierrc b/.prettierrc index 711b22e..46fc1ea 100644 --- a/.prettierrc +++ b/.prettierrc @@ -6,4 +6,5 @@ "singleQuote": true, "tabWidth": 4, "trailingComma": "es5" - } \ No newline at end of file + } + \ No newline at end of file diff --git a/experiments.json b/experiments.json index 9cddce8..bbe3972 100644 --- a/experiments.json +++ b/experiments.json @@ -1,29 +1,28 @@ { "experiments": [ - { "name": "DIVMosaics", "desc": "

Mosaic effect using DIV's

", "href": "experiments/divMosaics/", - "long_description":"

In this experiment each mosaic tile is animated using transtions on the top and left properties.

The mosaic effect shows Servo's ability to deal with many DOM elements aswell as their transitions. The transitions in particular perform very well in Servo thanks to the hardware acceleration provided by Servo's rendering engine, WebRender.

" + "long_description": "

In this experiment each mosaic tile is animated using transtions on the top and left properties.

The mosaic effect shows Servo's ability to deal with many DOM elements aswell as their transitions. The transitions in particular perform very well in Servo thanks to the hardware acceleration provided by Servo's rendering engine, WebRender.

" }, { "name": "Mosaic Gallery", "desc": "

A gallery of generated DIV mosaics. ", "href": "experiments/tiles/", - "long_description":"

This experiment features a gallery of generated DIV mosaics, where each pixel is represented by a static position and has transitions on their background color property.

On the page, the mosaic gallery is created by dividing the image into smaller units (pixels) represented by individual DIV elements. Each DIV element is positioned statically to form a mosaic-like grid.

" + "long_description": "

This experiment features a gallery of generated DIV mosaics, where each pixel is represented by a static position and has transitions on their background color property.

On the page, the mosaic gallery is created by dividing the image into smaller units (pixels) represented by individual DIV elements. Each DIV element is positioned statically to form a mosaic-like grid.

" }, { "name": "DIV Rain", "desc": "

Animated rain effect using DIVs.

", "href": "experiments/swirly/", - "long_description":"

This experiment demonstrates an animated rain effect using HTML div elements. This experiment specifically focuses on testing the rendering and animation capabilities of Servo by creating a rain effect using CSS and HTML.

It provides a visually interactive demonstration of how Servo handles complex animations and effects in a web browser context.

" + "long_description": "

This experiment demonstrates an animated rain effect using HTML div elements. This experiment specifically focuses on testing the rendering and animation capabilities of Servo by creating a rain effect using CSS and HTML.

It provides a visually interactive demonstration of how Servo handles complex animations and effects in a web browser context.

" }, { "name": "DIV Waves", "desc": "

Animated wave effect using DIVs.

", "href": "experiments/divWaves/", - "long_description":"This experiment specifically focuses on testing the rendering and animation capabilities of Servo by creating a visually dynamic and colorful wave effect. The wave animation is achieved by manipulating the position, size, and color of the HTML
elements.

This experiment helps evaluating and showcasing its ability to handle and render complex visual effects in a performant manner." + "long_description": "This experiment specifically focuses on testing the rendering and animation capabilities of Servo by creating a visually dynamic and colorful wave effect. The wave animation is achieved by manipulating the position, size, and color of the HTML

elements.

This experiment helps evaluating and showcasing its ability to handle and render complex visual effects in a performant manner." } ], "tests": [ @@ -31,14 +30,13 @@ "name": "Dogemania Benchmark", "desc": "

Benchmark your browser with Doges.

", "href": "experiments/dogemania/", - "long_description":"

This experiment provides a visual representation of the browser's activity through the servo-logo image and measures the performance using the FPS count.

You can benchmark your browser with servo-doges

" + "long_description": "

This experiment provides a visual representation of the browser's activity through the servo-logo image and measures the performance using the FPS count.

You can benchmark your browser with servo-doges

" }, { "name": "TWGL Tunnel", "desc": "

Tunnel effect using WebGL and the TWGL library.

", "href": "experiments/twgl-tunnel/", - "long_description":"

This experiment demonstrates the WebGL capabilities of servo. The tunnel effect is created by manipulating vertices and applying transformations to create the illusion of depth and movement.

The demo serves as a demonstration of WebGL capabilities and showcases dynamic and interactive 3D graphics using TWGL

" + "long_description": "

This experiment demonstrates the WebGL capabilities of servo. The tunnel effect is created by manipulating vertices and applying transformations to create the illusion of depth and movement.

The demo serves as a demonstration of WebGL capabilities and showcases dynamic and interactive 3D graphics using TWGL

" } ] - -} \ No newline at end of file +} diff --git a/experiments/twgl-tunnel/dist/chroma.min.js b/experiments/twgl-tunnel/dist/chroma.min.js index 9465d54..8e68e1f 100644 --- a/experiments/twgl-tunnel/dist/chroma.min.js +++ b/experiments/twgl-tunnel/dist/chroma.min.js @@ -55,4 +55,2735 @@ * @preserve */ -!function(r,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):r.chroma=e()}(this,function(){"use strict";for(var n=function(r,e,n){return void 0===e&&(e=0),void 0===n&&(n=1),r>16,e>>8&255,255&e,1]}if(r.match(fr)){5!==r.length&&9!==r.length||(r=r.substr(1)),4===r.length&&(r=(r=r.split(""))[0]+r[0]+r[1]+r[1]+r[2]+r[2]+r[3]+r[3]);var n=parseInt(r,16);return[n>>24&255,n>>16&255,n>>8&255,Math.round((255&n)/255*100)/100]}throw new Error("unknown hex color: "+r)},ur=o.type;A.prototype.hex=function(r){return tr(this._rgb,r)},_.hex=function(){for(var r=[],e=arguments.length;e--;)r[e]=arguments[e];return new(Function.prototype.bind.apply(A,[null].concat(r,["hex"])))},b.format.hex=or,b.autodetect.push({p:4,test:function(r){for(var e=[],n=arguments.length-1;0>16,r>>8&255,255&r,1];throw new Error("unknown num color: "+r)},xe=o.type;A.prototype.num=function(){return Me(this._rgb)},_.num=function(){for(var r=[],e=arguments.length;e--;)r[e]=arguments[e];return new(Function.prototype.bind.apply(A,[null].concat(r,["num"])))},b.format.num=_e,b.autodetect.push({p:5,test:function(){for(var r=[],e=arguments.length;e--;)r[e]=arguments[e];if(1===r.length&&"number"===xe(r[0])&&0<=r[0]&&r[0]<=16777215)return"num"}});var Ae=o.unpack,Ee=o.type,Pe=Math.round;A.prototype.rgb=function(r){return void 0===r&&(r=!0),!1===r?this._rgb.slice(0,3):this._rgb.slice(0,3).map(Pe)},A.prototype.rgba=function(n){return void 0===n&&(n=!0),this._rgb.slice(0,4).map(function(r,e){return e<3?!1===n?r:Pe(r):r})},_.rgb=function(){for(var r=[],e=arguments.length;e--;)r[e]=arguments[e];return new(Function.prototype.bind.apply(A,[null].concat(r,["rgb"])))},b.format.rgb=function(){for(var r=[],e=arguments.length;e--;)r[e]=arguments[e];var n=Ae(r,"rgba");return void 0===n[3]&&(n[3]=1),n},b.autodetect.push({p:3,test:function(){for(var r=[],e=arguments.length;e--;)r[e]=arguments[e];if(r=Ae(r,"rgba"),"array"===Ee(r)&&(3===r.length||4===r.length&&"number"==Ee(r[3])&&0<=r[3]&&r[3]<=1))return"rgb"}});var Fe=Math.log,Oe=function(r){var e,n,t,a=r/100;return t=a<66?(e=255,n=-155.25485562709179-.44596950469579133*(n=a-2)+104.49216199393888*Fe(n),a<20?0:.8274096064007395*(t=a-10)-254.76935184120902+115.67994401066147*Fe(t)):(e=351.97690566805693+.114206453784165*(e=a-55)-40.25366309332127*Fe(e),n=325.4494125711974+.07943456536662342*(n=a-50)-28.0852963507957*Fe(n),255),[e,n,t,1]},je=o.unpack,Ge=Math.round,qe=function(){for(var r=[],e=arguments.length;e--;)r[e]=arguments[e];for(var n,t=je(r,"rgb"),a=t[0],f=t[2],o=1e3,u=4e4;.4=f/a?u=n:o=n}return Ge(n)};A.prototype.temp=A.prototype.kelvin=A.prototype.temperature=function(){return qe(this._rgb)},_.temp=_.kelvin=_.temperature=function(){for(var r=[],e=arguments.length;e--;)r[e]=arguments[e];return new(Function.prototype.bind.apply(A,[null].concat(r,["temp"])))},b.format.temp=b.format.kelvin=b.format.temperature=Oe;var Le=o.type;A.prototype.alpha=function(r,e){return void 0===e&&(e=!1),void 0!==r&&"number"===Le(r)?e?(this._rgb[3]=r,this):new A([this._rgb[0],this._rgb[1],this._rgb[2],r],"rgb"):this._rgb[3]},A.prototype.clipped=function(){return this._rgb._clipped||!1},A.prototype.darken=function(r){void 0===r&&(r=1);var e=this.lab();return e[0]-=qr*r,new A(e,"lab").alpha(this.alpha(),!0)},A.prototype.brighten=function(r){return void 0===r&&(r=1),this.darken(-r)},A.prototype.darker=A.prototype.darken,A.prototype.brighter=A.prototype.brighten,A.prototype.get=function(r){var e=r.split("."),n=e[0],t=e[1],a=this[n]();if(t){var f=n.indexOf(t);if(-1=s[n];)n++;return n-1}(r)/(s.length-2):g!==p?(r-p)/(g-p):1;t=k(t),e||(t=w(t)),1!==y&&(t=nn(t,y)),t=d[0]+t*(1-d[0]-d[1]),t=Math.min(1,Math.max(0,t));var a=Math.floor(1e4*t);if(m&&v[a])n=v[a];else{if("array"===en(b))for(var f=0;f=u[e+1];)e++;var n=(r-u[e])/(u[e+1]-u[e]);return o[e]+n*(o[e+1]-o[e])})}}return l=[p,g],N},N.mode=function(r){return arguments.length?(u=r,f(),N):u},N.range=function(r,e){return a(r),N},N.out=function(r){return n=r,N},N.spread=function(r){return arguments.length?(e=r,N):e},N.correctLightness=function(r){return null==r&&(r=!0),t=r,f(),w=t?function(r){for(var e=M(0,!0).lab()[0],n=M(1,!0).lab()[0],t=nn.max&&(n.max=r),n.count+=1)}),n.domain=[n.min,n.max],n.limits=function(r,e){return Nn(n,r,e)},n},Nn=function(r,e,n){void 0===e&&(e="equal"),void 0===n&&(n=7),"array"==Y(r)&&(r=Mn(r));var t=r.min,a=r.max,f=r.values.sort(function(r,e){return r-e});if(1===n)return[t,a];var o=[];if("c"===e.substr(0,1)&&(o.push(t),o.push(a)),"e"===e.substr(0,1)){o.push(t);for(var u=1;u 0");var c=Math.LOG10E*mn(t),i=Math.LOG10E*mn(a);o.push(t);for(var l=1;l> 16, (e >> 8) & 255, 255 & e, 1] + } + if (r.match(fr)) { + ;(5 !== r.length && 9 !== r.length) || (r = r.substr(1)), + 4 === r.length && + (r = + (r = r.split(''))[0] + + r[0] + + r[1] + + r[1] + + r[2] + + r[2] + + r[3] + + r[3]) + var n = parseInt(r, 16) + return [ + (n >> 24) & 255, + (n >> 16) & 255, + (n >> 8) & 255, + Math.round(((255 & n) / 255) * 100) / 100, + ] + } + throw new Error('unknown hex color: ' + r) + }, + ur = o.type + ;(A.prototype.hex = function (r) { + return tr(this._rgb, r) + }), + (_.hex = function () { + for (var r = [], e = arguments.length; e--; ) r[e] = arguments[e] + return new (Function.prototype.bind.apply( + A, + [null].concat(r, ['hex']) + ))() + }), + (b.format.hex = or), + b.autodetect.push({ + p: 4, + test: function (r) { + for (var e = [], n = arguments.length - 1; 0 < n--; ) + e[n] = arguments[n + 1] + if ( + !e.length && + 'string' === ur(r) && + 0 <= [3, 4, 5, 6, 7, 8, 9].indexOf(r.length) + ) + return 'hex' + }, + }) + var cr = o.unpack, + ir = o.TWOPI, + lr = Math.min, + hr = Math.sqrt, + dr = Math.acos, + sr = function () { + for (var r = [], e = arguments.length; e--; ) r[e] = arguments[e] + var n, + t = cr(r, 'rgb'), + a = t[0], + f = t[1], + o = t[2], + u = lr((a /= 255), (f /= 255), (o /= 255)), + c = (a + f + o) / 3, + i = 0 < c ? 1 - u / c : 0 + return ( + 0 === i + ? (n = NaN) + : ((n = (a - f + (a - o)) / 2), + (n /= hr((a - f) * (a - f) + (a - o) * (f - o))), + (n = dr(n)), + f < o && (n = ir - n), + (n /= ir)), + [360 * n, i, c] + ) + }, + br = o.unpack, + pr = o.limit, + gr = o.TWOPI, + vr = o.PITHIRD, + mr = Math.cos, + yr = function () { + for (var r = [], e = arguments.length; e--; ) r[e] = arguments[e] + var n, + t, + a, + f = (r = br(r, 'hsi'))[0], + o = r[1], + u = r[2] + return ( + isNaN(f) && (f = 0), + isNaN(o) && (o = 0), + 360 < f && (f -= 360), + f < 0 && (f += 360), + (f /= 360) < 1 / 3 + ? (t = + 1 - + ((a = (1 - o) / 3) + + (n = + (1 + (o * mr(gr * f)) / mr(vr - gr * f)) / + 3))) + : f < 2 / 3 + ? (a = + 1 - + ((n = (1 - o) / 3) + + (t = + (1 + + (o * mr(gr * (f -= 1 / 3))) / + mr(vr - gr * f)) / + 3))) + : (n = + 1 - + ((t = (1 - o) / 3) + + (a = + (1 + + (o * mr(gr * (f -= 2 / 3))) / + mr(vr - gr * f)) / + 3))), + [ + 255 * (n = pr(u * n * 3)), + 255 * (t = pr(u * t * 3)), + 255 * (a = pr(u * a * 3)), + 3 < r.length ? r[3] : 1, + ] + ) + }, + wr = o.unpack, + kr = o.type + ;(A.prototype.hsi = function () { + return sr(this._rgb) + }), + (_.hsi = function () { + for (var r = [], e = arguments.length; e--; ) r[e] = arguments[e] + return new (Function.prototype.bind.apply( + A, + [null].concat(r, ['hsi']) + ))() + }), + (b.format.hsi = yr), + b.autodetect.push({ + p: 2, + test: function () { + for (var r = [], e = arguments.length; e--; ) + r[e] = arguments[e] + if (((r = wr(r, 'hsi')), 'array' === kr(r) && 3 === r.length)) + return 'hsi' + }, + }) + var Mr = o.unpack, + Nr = o.type + ;(A.prototype.hsl = function () { + return E(this._rgb) + }), + (_.hsl = function () { + for (var r = [], e = arguments.length; e--; ) r[e] = arguments[e] + return new (Function.prototype.bind.apply( + A, + [null].concat(r, ['hsl']) + ))() + }), + (b.format.hsl = L), + b.autodetect.push({ + p: 2, + test: function () { + for (var r = [], e = arguments.length; e--; ) + r[e] = arguments[e] + if (((r = Mr(r, 'hsl')), 'array' === Nr(r) && 3 === r.length)) + return 'hsl' + }, + }) + var _r = o.unpack, + xr = Math.min, + Ar = Math.max, + Er = function () { + for (var r = [], e = arguments.length; e--; ) r[e] = arguments[e] + var n, + t, + a, + f = (r = _r(r, 'rgb'))[0], + o = r[1], + u = r[2], + c = xr(f, o, u), + i = Ar(f, o, u), + l = i - c + return ( + (a = i / 255), + 0 === i + ? ((n = Number.NaN), (t = 0)) + : ((t = l / i), + f === i && (n = (o - u) / l), + o === i && (n = 2 + (u - f) / l), + u === i && (n = 4 + (f - o) / l), + (n *= 60) < 0 && (n += 360)), + [n, t, a] + ) + }, + Pr = o.unpack, + Fr = Math.floor, + Or = function () { + for (var r, e, n, t, a, f, o = [], u = arguments.length; u--; ) + o[u] = arguments[u] + var c, + i, + l, + h = (o = Pr(o, 'hsv'))[0], + d = o[1], + s = o[2] + if (((s *= 255), 0 === d)) c = i = l = s + else { + 360 === h && (h = 0), 360 < h && (h -= 360), h < 0 && (h += 360) + var b = Fr((h /= 60)), + p = h - b, + g = s * (1 - d), + v = s * (1 - d * p), + m = s * (1 - d * (1 - p)) + switch (b) { + case 0: + ;(c = (r = [s, m, g])[0]), (i = r[1]), (l = r[2]) + break + case 1: + ;(c = (e = [v, s, g])[0]), (i = e[1]), (l = e[2]) + break + case 2: + ;(c = (n = [g, s, m])[0]), (i = n[1]), (l = n[2]) + break + case 3: + ;(c = (t = [g, v, s])[0]), (i = t[1]), (l = t[2]) + break + case 4: + ;(c = (a = [m, g, s])[0]), (i = a[1]), (l = a[2]) + break + case 5: + ;(c = (f = [s, g, v])[0]), (i = f[1]), (l = f[2]) + } + } + return [c, i, l, 3 < o.length ? o[3] : 1] + }, + jr = o.unpack, + Gr = o.type + ;(A.prototype.hsv = function () { + return Er(this._rgb) + }), + (_.hsv = function () { + for (var r = [], e = arguments.length; e--; ) r[e] = arguments[e] + return new (Function.prototype.bind.apply( + A, + [null].concat(r, ['hsv']) + ))() + }), + (b.format.hsv = Or), + b.autodetect.push({ + p: 2, + test: function () { + for (var r = [], e = arguments.length; e--; ) + r[e] = arguments[e] + if (((r = jr(r, 'hsv')), 'array' === Gr(r) && 3 === r.length)) + return 'hsv' + }, + }) + var qr = 18, + Lr = 0.95047, + Rr = 1, + Ir = 1.08883, + Br = 0.137931034, + Cr = 0.206896552, + Dr = 0.12841855, + Sr = 0.008856452, + $r = o.unpack, + Yr = Math.pow, + zr = function (r) { + return (r /= 255) <= 0.04045 + ? r / 12.92 + : Yr((r + 0.055) / 1.055, 2.4) + }, + Tr = function (r) { + return Sr < r ? Yr(r, 1 / 3) : r / Dr + Br + }, + Ur = function (r, e, n) { + return ( + (r = zr(r)), + (e = zr(e)), + (n = zr(n)), + [ + Tr((0.4124564 * r + 0.3575761 * e + 0.1804375 * n) / Lr), + Tr((0.2126729 * r + 0.7151522 * e + 0.072175 * n) / Rr), + Tr((0.0193339 * r + 0.119192 * e + 0.9503041 * n) / Ir), + ] + ) + }, + Vr = function () { + for (var r = [], e = arguments.length; e--; ) r[e] = arguments[e] + var n = $r(r, 'rgb'), + t = n[0], + a = n[1], + f = n[2], + o = Ur(t, a, f), + u = o[0], + c = o[1], + i = 116 * c - 16 + return [i < 0 ? 0 : i, 500 * (u - c), 200 * (c - o[2])] + }, + Wr = o.unpack, + Xr = Math.pow, + Hr = function (r) { + return ( + 255 * + (r <= 0.00304 ? 12.92 * r : 1.055 * Xr(r, 1 / 2.4) - 0.055) + ) + }, + Jr = function (r) { + return Cr < r ? r * r * r : Dr * (r - Br) + }, + Kr = function () { + for (var r = [], e = arguments.length; e--; ) r[e] = arguments[e] + var n, + t, + a, + f = (r = Wr(r, 'lab'))[0], + o = r[1], + u = r[2] + return ( + (t = (f + 16) / 116), + (n = isNaN(o) ? t : t + o / 500), + (a = isNaN(u) ? t : t - u / 200), + (t = Rr * Jr(t)), + (n = Lr * Jr(n)), + (a = Ir * Jr(a)), + [ + Hr(3.2404542 * n - 1.5371385 * t - 0.4985314 * a), + Hr(-0.969266 * n + 1.8760108 * t + 0.041556 * a), + Hr(0.0556434 * n - 0.2040259 * t + 1.0572252 * a), + 3 < r.length ? r[3] : 1, + ] + ) + }, + Qr = o.unpack, + Zr = o.type + ;(A.prototype.lab = function () { + return Vr(this._rgb) + }), + (_.lab = function () { + for (var r = [], e = arguments.length; e--; ) r[e] = arguments[e] + return new (Function.prototype.bind.apply( + A, + [null].concat(r, ['lab']) + ))() + }), + (b.format.lab = Kr), + b.autodetect.push({ + p: 2, + test: function () { + for (var r = [], e = arguments.length; e--; ) + r[e] = arguments[e] + if (((r = Qr(r, 'lab')), 'array' === Zr(r) && 3 === r.length)) + return 'lab' + }, + }) + var re = o.unpack, + ee = o.RAD2DEG, + ne = Math.sqrt, + te = Math.atan2, + ae = Math.round, + fe = function () { + for (var r = [], e = arguments.length; e--; ) r[e] = arguments[e] + var n = re(r, 'lab'), + t = n[0], + a = n[1], + f = n[2], + o = ne(a * a + f * f), + u = (te(f, a) * ee + 360) % 360 + return 0 === ae(1e4 * o) && (u = Number.NaN), [t, o, u] + }, + oe = o.unpack, + ue = function () { + for (var r = [], e = arguments.length; e--; ) r[e] = arguments[e] + var n = oe(r, 'rgb'), + t = n[0], + a = n[1], + f = n[2], + o = Vr(t, a, f), + u = o[0], + c = o[1], + i = o[2] + return fe(u, c, i) + }, + ce = o.unpack, + ie = o.DEG2RAD, + le = Math.sin, + he = Math.cos, + de = function () { + for (var r = [], e = arguments.length; e--; ) r[e] = arguments[e] + var n = ce(r, 'lch'), + t = n[0], + a = n[1], + f = n[2] + return isNaN(f) && (f = 0), [t, he((f *= ie)) * a, le(f) * a] + }, + se = o.unpack, + be = function () { + for (var r = [], e = arguments.length; e--; ) r[e] = arguments[e] + var n = (r = se(r, 'lch'))[0], + t = r[1], + a = r[2], + f = de(n, t, a), + o = f[0], + u = f[1], + c = f[2], + i = Kr(o, u, c) + return [i[0], i[1], i[2], 3 < r.length ? r[3] : 1] + }, + pe = o.unpack, + ge = function () { + for (var r = [], e = arguments.length; e--; ) r[e] = arguments[e] + var n = pe(r, 'hcl').reverse() + return be.apply(void 0, n) + }, + ve = o.unpack, + me = o.type + ;(A.prototype.lch = function () { + return ue(this._rgb) + }), + (A.prototype.hcl = function () { + return ue(this._rgb).reverse() + }), + (_.lch = function () { + for (var r = [], e = arguments.length; e--; ) r[e] = arguments[e] + return new (Function.prototype.bind.apply( + A, + [null].concat(r, ['lch']) + ))() + }), + (_.hcl = function () { + for (var r = [], e = arguments.length; e--; ) r[e] = arguments[e] + return new (Function.prototype.bind.apply( + A, + [null].concat(r, ['hcl']) + ))() + }), + (b.format.lch = be), + (b.format.hcl = ge), + ['lch', 'hcl'].forEach(function (n) { + return b.autodetect.push({ + p: 2, + test: function () { + for (var r = [], e = arguments.length; e--; ) + r[e] = arguments[e] + if (((r = ve(r, n)), 'array' === me(r) && 3 === r.length)) + return n + }, + }) + }) + var ye = { + aliceblue: '#f0f8ff', + antiquewhite: '#faebd7', + aqua: '#00ffff', + aquamarine: '#7fffd4', + azure: '#f0ffff', + beige: '#f5f5dc', + bisque: '#ffe4c4', + black: '#000000', + blanchedalmond: '#ffebcd', + blue: '#0000ff', + blueviolet: '#8a2be2', + brown: '#a52a2a', + burlywood: '#deb887', + cadetblue: '#5f9ea0', + chartreuse: '#7fff00', + chocolate: '#d2691e', + coral: '#ff7f50', + cornflower: '#6495ed', + cornflowerblue: '#6495ed', + cornsilk: '#fff8dc', + crimson: '#dc143c', + cyan: '#00ffff', + darkblue: '#00008b', + darkcyan: '#008b8b', + darkgoldenrod: '#b8860b', + darkgray: '#a9a9a9', + darkgreen: '#006400', + darkgrey: '#a9a9a9', + darkkhaki: '#bdb76b', + darkmagenta: '#8b008b', + darkolivegreen: '#556b2f', + darkorange: '#ff8c00', + darkorchid: '#9932cc', + darkred: '#8b0000', + darksalmon: '#e9967a', + darkseagreen: '#8fbc8f', + darkslateblue: '#483d8b', + darkslategray: '#2f4f4f', + darkslategrey: '#2f4f4f', + darkturquoise: '#00ced1', + darkviolet: '#9400d3', + deeppink: '#ff1493', + deepskyblue: '#00bfff', + dimgray: '#696969', + dimgrey: '#696969', + dodgerblue: '#1e90ff', + firebrick: '#b22222', + floralwhite: '#fffaf0', + forestgreen: '#228b22', + fuchsia: '#ff00ff', + gainsboro: '#dcdcdc', + ghostwhite: '#f8f8ff', + gold: '#ffd700', + goldenrod: '#daa520', + gray: '#808080', + green: '#008000', + greenyellow: '#adff2f', + grey: '#808080', + honeydew: '#f0fff0', + hotpink: '#ff69b4', + indianred: '#cd5c5c', + indigo: '#4b0082', + ivory: '#fffff0', + khaki: '#f0e68c', + laserlemon: '#ffff54', + lavender: '#e6e6fa', + lavenderblush: '#fff0f5', + lawngreen: '#7cfc00', + lemonchiffon: '#fffacd', + lightblue: '#add8e6', + lightcoral: '#f08080', + lightcyan: '#e0ffff', + lightgoldenrod: '#fafad2', + lightgoldenrodyellow: '#fafad2', + lightgray: '#d3d3d3', + lightgreen: '#90ee90', + lightgrey: '#d3d3d3', + lightpink: '#ffb6c1', + lightsalmon: '#ffa07a', + lightseagreen: '#20b2aa', + lightskyblue: '#87cefa', + lightslategray: '#778899', + lightslategrey: '#778899', + lightsteelblue: '#b0c4de', + lightyellow: '#ffffe0', + lime: '#00ff00', + limegreen: '#32cd32', + linen: '#faf0e6', + magenta: '#ff00ff', + maroon: '#800000', + maroon2: '#7f0000', + maroon3: '#b03060', + mediumaquamarine: '#66cdaa', + mediumblue: '#0000cd', + mediumorchid: '#ba55d3', + mediumpurple: '#9370db', + mediumseagreen: '#3cb371', + mediumslateblue: '#7b68ee', + mediumspringgreen: '#00fa9a', + mediumturquoise: '#48d1cc', + mediumvioletred: '#c71585', + midnightblue: '#191970', + mintcream: '#f5fffa', + mistyrose: '#ffe4e1', + moccasin: '#ffe4b5', + navajowhite: '#ffdead', + navy: '#000080', + oldlace: '#fdf5e6', + olive: '#808000', + olivedrab: '#6b8e23', + orange: '#ffa500', + orangered: '#ff4500', + orchid: '#da70d6', + palegoldenrod: '#eee8aa', + palegreen: '#98fb98', + paleturquoise: '#afeeee', + palevioletred: '#db7093', + papayawhip: '#ffefd5', + peachpuff: '#ffdab9', + peru: '#cd853f', + pink: '#ffc0cb', + plum: '#dda0dd', + powderblue: '#b0e0e6', + purple: '#800080', + purple2: '#7f007f', + purple3: '#a020f0', + rebeccapurple: '#663399', + red: '#ff0000', + rosybrown: '#bc8f8f', + royalblue: '#4169e1', + saddlebrown: '#8b4513', + salmon: '#fa8072', + sandybrown: '#f4a460', + seagreen: '#2e8b57', + seashell: '#fff5ee', + sienna: '#a0522d', + silver: '#c0c0c0', + skyblue: '#87ceeb', + slateblue: '#6a5acd', + slategray: '#708090', + slategrey: '#708090', + snow: '#fffafa', + springgreen: '#00ff7f', + steelblue: '#4682b4', + tan: '#d2b48c', + teal: '#008080', + thistle: '#d8bfd8', + tomato: '#ff6347', + turquoise: '#40e0d0', + violet: '#ee82ee', + wheat: '#f5deb3', + white: '#ffffff', + whitesmoke: '#f5f5f5', + yellow: '#ffff00', + yellowgreen: '#9acd32', + }, + we = o.type + ;(A.prototype.name = function () { + for ( + var r = tr(this._rgb, 'rgb'), e = 0, n = Object.keys(ye); + e < n.length; + e += 1 + ) { + var t = n[e] + if (ye[t] === r) return t.toLowerCase() + } + return r + }), + (b.format.named = function (r) { + if (((r = r.toLowerCase()), ye[r])) return or(ye[r]) + throw new Error('unknown color name: ' + r) + }), + b.autodetect.push({ + p: 5, + test: function (r) { + for (var e = [], n = arguments.length - 1; 0 < n--; ) + e[n] = arguments[n + 1] + if (!e.length && 'string' === we(r) && ye[r.toLowerCase()]) + return 'named' + }, + }) + var ke = o.unpack, + Me = function () { + for (var r = [], e = arguments.length; e--; ) r[e] = arguments[e] + var n = ke(r, 'rgb') + return (n[0] << 16) + (n[1] << 8) + n[2] + }, + Ne = o.type, + _e = function (r) { + if ('number' == Ne(r) && 0 <= r && r <= 16777215) + return [r >> 16, (r >> 8) & 255, 255 & r, 1] + throw new Error('unknown num color: ' + r) + }, + xe = o.type + ;(A.prototype.num = function () { + return Me(this._rgb) + }), + (_.num = function () { + for (var r = [], e = arguments.length; e--; ) r[e] = arguments[e] + return new (Function.prototype.bind.apply( + A, + [null].concat(r, ['num']) + ))() + }), + (b.format.num = _e), + b.autodetect.push({ + p: 5, + test: function () { + for (var r = [], e = arguments.length; e--; ) + r[e] = arguments[e] + if ( + 1 === r.length && + 'number' === xe(r[0]) && + 0 <= r[0] && + r[0] <= 16777215 + ) + return 'num' + }, + }) + var Ae = o.unpack, + Ee = o.type, + Pe = Math.round + ;(A.prototype.rgb = function (r) { + return ( + void 0 === r && (r = !0), + !1 === r ? this._rgb.slice(0, 3) : this._rgb.slice(0, 3).map(Pe) + ) + }), + (A.prototype.rgba = function (n) { + return ( + void 0 === n && (n = !0), + this._rgb.slice(0, 4).map(function (r, e) { + return e < 3 ? (!1 === n ? r : Pe(r)) : r + }) + ) + }), + (_.rgb = function () { + for (var r = [], e = arguments.length; e--; ) r[e] = arguments[e] + return new (Function.prototype.bind.apply( + A, + [null].concat(r, ['rgb']) + ))() + }), + (b.format.rgb = function () { + for (var r = [], e = arguments.length; e--; ) r[e] = arguments[e] + var n = Ae(r, 'rgba') + return void 0 === n[3] && (n[3] = 1), n + }), + b.autodetect.push({ + p: 3, + test: function () { + for (var r = [], e = arguments.length; e--; ) + r[e] = arguments[e] + if ( + ((r = Ae(r, 'rgba')), + 'array' === Ee(r) && + (3 === r.length || + (4 === r.length && + 'number' == Ee(r[3]) && + 0 <= r[3] && + r[3] <= 1))) + ) + return 'rgb' + }, + }) + var Fe = Math.log, + Oe = function (r) { + var e, + n, + t, + a = r / 100 + return ( + (t = + a < 66 + ? ((e = 255), + (n = + -155.25485562709179 - + 0.44596950469579133 * (n = a - 2) + + 104.49216199393888 * Fe(n)), + a < 20 + ? 0 + : 0.8274096064007395 * (t = a - 10) - + 254.76935184120902 + + 115.67994401066147 * Fe(t)) + : ((e = + 351.97690566805693 + + 0.114206453784165 * (e = a - 55) - + 40.25366309332127 * Fe(e)), + (n = + 325.4494125711974 + + 0.07943456536662342 * (n = a - 50) - + 28.0852963507957 * Fe(n)), + 255)), + [e, n, t, 1] + ) + }, + je = o.unpack, + Ge = Math.round, + qe = function () { + for (var r = [], e = arguments.length; e--; ) r[e] = arguments[e] + for ( + var n, t = je(r, 'rgb'), a = t[0], f = t[2], o = 1e3, u = 4e4; + 0.4 < u - o; + + ) { + var c = Oe((n = 0.5 * (u + o))) + c[2] / c[0] >= f / a ? (u = n) : (o = n) + } + return Ge(n) + } + ;(A.prototype.temp = + A.prototype.kelvin = + A.prototype.temperature = + function () { + return qe(this._rgb) + }), + (_.temp = + _.kelvin = + _.temperature = + function () { + for (var r = [], e = arguments.length; e--; ) + r[e] = arguments[e] + return new (Function.prototype.bind.apply( + A, + [null].concat(r, ['temp']) + ))() + }), + (b.format.temp = b.format.kelvin = b.format.temperature = Oe) + var Le = o.type + ;(A.prototype.alpha = function (r, e) { + return ( + void 0 === e && (e = !1), + void 0 !== r && 'number' === Le(r) + ? e + ? ((this._rgb[3] = r), this) + : new A( + [this._rgb[0], this._rgb[1], this._rgb[2], r], + 'rgb' + ) + : this._rgb[3] + ) + }), + (A.prototype.clipped = function () { + return this._rgb._clipped || !1 + }), + (A.prototype.darken = function (r) { + void 0 === r && (r = 1) + var e = this.lab() + return (e[0] -= qr * r), new A(e, 'lab').alpha(this.alpha(), !0) + }), + (A.prototype.brighten = function (r) { + return void 0 === r && (r = 1), this.darken(-r) + }), + (A.prototype.darker = A.prototype.darken), + (A.prototype.brighter = A.prototype.brighten), + (A.prototype.get = function (r) { + var e = r.split('.'), + n = e[0], + t = e[1], + a = this[n]() + if (t) { + var f = n.indexOf(t) + if (-1 < f) return a[f] + throw new Error('unknown channel ' + t + ' in mode ' + n) + } + return a + }) + var Re = o.type, + Ie = Math.pow + A.prototype.luminance = function (a) { + if (void 0 === a || 'number' !== Re(a)) + return Be.apply(void 0, this._rgb.slice(0, 3)) + if (0 === a) return new A([0, 0, 0, this._rgb[3]], 'rgb') + if (1 === a) return new A([255, 255, 255, this._rgb[3]], 'rgb') + var r = this.luminance(), + f = 20, + o = function (r, e) { + var n = r.interpolate(e, 0.5, 'rgb'), + t = n.luminance() + return Math.abs(a - t) < 1e-7 || !f-- + ? n + : a < t + ? o(r, n) + : o(n, e) + }, + e = ( + a < r + ? o(new A([0, 0, 0]), this) + : o(this, new A([255, 255, 255])) + ).rgb() + return new A(e.concat([this._rgb[3]])) + } + var Be = function (r, e, n) { + return ( + 0.2126 * (r = Ce(r)) + + 0.7152 * (e = Ce(e)) + + 0.0722 * (n = Ce(n)) + ) + }, + Ce = function (r) { + return (r /= 255) <= 0.03928 + ? r / 12.92 + : Ie((r + 0.055) / 1.055, 2.4) + }, + De = {}, + Se = o.type, + $e = function (r, e, n) { + void 0 === n && (n = 0.5) + for (var t = [], a = arguments.length - 3; 0 < a--; ) + t[a] = arguments[a + 3] + var f = t[0] || 'lrgb' + if ((De[f] || t.length || (f = Object.keys(De)[0]), !De[f])) + throw new Error('interpolation mode ' + f + ' is not defined') + return ( + 'object' !== Se(r) && (r = new A(r)), + 'object' !== Se(e) && (e = new A(e)), + De[f](r, e, n).alpha(r.alpha() + n * (e.alpha() - r.alpha())) + ) + } + ;(A.prototype.mix = A.prototype.interpolate = + function (r, e) { + void 0 === e && (e = 0.5) + for (var n = [], t = arguments.length - 2; 0 < t--; ) + n[t] = arguments[t + 2] + return $e.apply(void 0, [this, r, e].concat(n)) + }), + (A.prototype.premultiply = function (r) { + void 0 === r && (r = !1) + var e = this._rgb, + n = e[3] + return r + ? ((this._rgb = [e[0] * n, e[1] * n, e[2] * n, n]), this) + : new A([e[0] * n, e[1] * n, e[2] * n, n], 'rgb') + }), + (A.prototype.saturate = function (r) { + void 0 === r && (r = 1) + var e = this.lch() + return ( + (e[1] += qr * r), + e[1] < 0 && (e[1] = 0), + new A(e, 'lch').alpha(this.alpha(), !0) + ) + }), + (A.prototype.desaturate = function (r) { + return void 0 === r && (r = 1), this.saturate(-r) + }) + var Ye = o.type + A.prototype.set = function (r, e, n) { + void 0 === n && (n = !1) + var t = r.split('.'), + a = t[0], + f = t[1], + o = this[a]() + if (f) { + var u = a.indexOf(f) + if (-1 < u) { + if ('string' == Ye(e)) + switch (e.charAt(0)) { + case '+': + case '-': + o[u] += +e + break + case '*': + o[u] *= +e.substr(1) + break + case '/': + o[u] /= +e.substr(1) + break + default: + o[u] = +e + } + else { + if ('number' !== Ye(e)) + throw new Error('unsupported value for Color.set') + o[u] = e + } + var c = new A(o, a) + return n ? ((this._rgb = c._rgb), this) : c + } + throw new Error('unknown channel ' + f + ' in mode ' + a) + } + return o + } + De.rgb = function (r, e, n) { + var t = r._rgb, + a = e._rgb + return new A( + t[0] + n * (a[0] - t[0]), + t[1] + n * (a[1] - t[1]), + t[2] + n * (a[2] - t[2]), + 'rgb' + ) + } + var ze = Math.sqrt, + Te = Math.pow + De.lrgb = function (r, e, n) { + var t = r._rgb, + a = t[0], + f = t[1], + o = t[2], + u = e._rgb, + c = u[0], + i = u[1], + l = u[2] + return new A( + ze(Te(a, 2) * (1 - n) + Te(c, 2) * n), + ze(Te(f, 2) * (1 - n) + Te(i, 2) * n), + ze(Te(o, 2) * (1 - n) + Te(l, 2) * n), + 'rgb' + ) + } + De.lab = function (r, e, n) { + var t = r.lab(), + a = e.lab() + return new A( + t[0] + n * (a[0] - t[0]), + t[1] + n * (a[1] - t[1]), + t[2] + n * (a[2] - t[2]), + 'lab' + ) + } + var Ue = function (r, e, n, t) { + var a, f, o, u, c, i, l, h, d, s, b, p + return ( + 'hsl' === t + ? ((o = r.hsl()), (u = e.hsl())) + : 'hsv' === t + ? ((o = r.hsv()), (u = e.hsv())) + : 'hcg' === t + ? ((o = r.hcg()), (u = e.hcg())) + : 'hsi' === t + ? ((o = r.hsi()), (u = e.hsi())) + : ('lch' !== t && 'hcl' !== t) || + ((t = 'hcl'), (o = r.hcl()), (u = e.hcl())), + 'h' === t.substr(0, 1) && + ((c = (a = o)[0]), + (l = a[1]), + (d = a[2]), + (i = (f = u)[0]), + (h = f[1]), + (s = f[2])), + isNaN(c) || isNaN(i) + ? isNaN(c) + ? isNaN(i) + ? (p = Number.NaN) + : ((p = i), + (1 != d && 0 != d) || 'hsv' == t || (b = h)) + : ((p = c), (1 != s && 0 != s) || 'hsv' == t || (b = l)) + : (p = + c + + n * + (c < i && 180 < i - c + ? i - (c + 360) + : i < c && 180 < c - i + ? i + 360 - c + : i - c)), + void 0 === b && (b = l + n * (h - l)), + new A([p, b, d + n * (s - d)], t) + ) + }, + Ve = function (r, e, n) { + return Ue(r, e, n, 'lch') + } + ;(De.lch = Ve), (De.hcl = Ve) + De.num = function (r, e, n) { + var t = r.num(), + a = e.num() + return new A(t + n * (a - t), 'num') + } + De.hcg = function (r, e, n) { + return Ue(r, e, n, 'hcg') + } + De.hsi = function (r, e, n) { + return Ue(r, e, n, 'hsi') + } + De.hsl = function (r, e, n) { + return Ue(r, e, n, 'hsl') + } + De.hsv = function (r, e, n) { + return Ue(r, e, n, 'hsv') + } + var We = o.clip_rgb, + Xe = Math.pow, + He = Math.sqrt, + Je = Math.PI, + Ke = Math.cos, + Qe = Math.sin, + Ze = Math.atan2, + rn = function (r, e) { + for (var n = r.length, t = [0, 0, 0, 0], a = 0; a < r.length; a++) { + var f = r[a], + o = e[a] / n, + u = f._rgb + ;(t[0] += Xe(u[0], 2) * o), + (t[1] += Xe(u[1], 2) * o), + (t[2] += Xe(u[2], 2) * o), + (t[3] += u[3] * o) + } + return ( + (t[0] = He(t[0])), + (t[1] = He(t[1])), + (t[2] = He(t[2])), + 0.9999999 < t[3] && (t[3] = 1), + new A(We(t)) + ) + }, + en = o.type, + nn = Math.pow, + tn = function (i) { + var u = 'rgb', + c = _('#ccc'), + e = 0, + l = [0, 1], + h = [], + d = [0, 0], + s = !1, + b = [], + n = !1, + p = 0, + g = 1, + t = !1, + v = {}, + m = !0, + y = 1, + a = function (r) { + if ( + ((r = r || ['#fff', '#000']) && + 'string' === en(r) && + _.brewer && + _.brewer[r.toLowerCase()] && + (r = _.brewer[r.toLowerCase()]), + 'array' === en(r)) + ) { + 1 === r.length && (r = [r[0], r[0]]), (r = r.slice(0)) + for (var e = 0; e < r.length; e++) r[e] = _(r[e]) + for (var n = (h.length = 0); n < r.length; n++) + h.push(n / (r.length - 1)) + } + return f(), (b = r) + }, + w = function (r) { + return r + }, + k = function (r) { + return r + }, + M = function (r, e) { + var n, t + if ((null == e && (e = !1), isNaN(r) || null === r)) + return c + e + ? (t = r) + : (t = + s && 2 < s.length + ? (function (r) { + if (null == s) return 0 + for ( + var e = s.length - 1, n = 0; + n < e && r >= s[n]; + + ) + n++ + return n - 1 + })(r) / + (s.length - 2) + : g !== p + ? (r - p) / (g - p) + : 1) + ;(t = k(t)), + e || (t = w(t)), + 1 !== y && (t = nn(t, y)), + (t = d[0] + t * (1 - d[0] - d[1])), + (t = Math.min(1, Math.max(0, t))) + var a = Math.floor(1e4 * t) + if (m && v[a]) n = v[a] + else { + if ('array' === en(b)) + for (var f = 0; f < h.length; f++) { + var o = h[f] + if (t <= o) { + n = b[f] + break + } + if (o <= t && f === h.length - 1) { + n = b[f] + break + } + if (o < t && t < h[f + 1]) { + ;(t = (t - o) / (h[f + 1] - o)), + (n = _.interpolate( + b[f], + b[f + 1], + t, + u + )) + break + } + } + else 'function' === en(b) && (n = b(t)) + m && (v[a] = n) + } + return n + }, + f = function () { + return (v = {}) + } + a(i) + var N = function (r) { + var e = _(M(r)) + return n && e[n] ? e[n]() : e + } + return ( + (N.classes = function (r) { + if (null == r) return s + if ('array' === en(r)) l = [(s = r)[0], r[r.length - 1]] + else { + var e = _.analyze(l) + s = 0 === r ? [e.min, e.max] : _.limits(e, 'e', r) + } + return N + }), + (N.domain = function (n) { + if (!arguments.length) return l + ;(p = n[0]), (g = n[n.length - 1]), (h = []) + var r = b.length + if (n.length === r && p !== g) + for ( + var e = 0, t = Array.from(n); + e < t.length; + e += 1 + ) { + var a = t[e] + h.push((a - p) / (g - p)) + } + else { + for (var f = 0; f < r; f++) h.push(f / (r - 1)) + if (2 < n.length) { + var o = n.map(function (r, e) { + return e / (n.length - 1) + }), + u = n.map(function (r) { + return (r - p) / (g - p) + }) + u.every(function (r, e) { + return o[e] === r + }) || + (k = function (r) { + if (r <= 0 || 1 <= r) return r + for (var e = 0; r >= u[e + 1]; ) e++ + var n = (r - u[e]) / (u[e + 1] - u[e]) + return o[e] + n * (o[e + 1] - o[e]) + }) + } + } + return (l = [p, g]), N + }), + (N.mode = function (r) { + return arguments.length ? ((u = r), f(), N) : u + }), + (N.range = function (r, e) { + return a(r), N + }), + (N.out = function (r) { + return (n = r), N + }), + (N.spread = function (r) { + return arguments.length ? ((e = r), N) : e + }), + (N.correctLightness = function (r) { + return ( + null == r && (r = !0), + (t = r), + f(), + (w = t + ? function (r) { + for ( + var e = M(0, !0).lab()[0], + n = M(1, !0).lab()[0], + t = n < e, + a = M(r, !0).lab()[0], + f = e + (n - e) * r, + o = a - f, + u = 0, + c = 1, + i = 20; + 0.01 < Math.abs(o) && 0 < i--; + + ) + t && (o *= -1), + (r += + o < 0 + ? 0.5 * (c - (u = r)) + : 0.5 * (u - (c = r))), + (a = M(r, !0).lab()[0]), + (o = a - f) + return r + } + : function (r) { + return r + }), + N + ) + }), + (N.padding = function (r) { + return null != r + ? ('number' === en(r) && (r = [r, r]), (d = r), N) + : d + }), + (N.colors = function (e, n) { + arguments.length < 2 && (n = 'hex') + var r = [] + if (0 === arguments.length) r = b.slice(0) + else if (1 === e) r = [N(0.5)] + else if (1 < e) { + var t = l[0], + a = l[1] - t + r = (function (r, e, n) { + for ( + var t = [], + a = r < e, + f = n ? (a ? e + 1 : e - 1) : e, + o = r; + a ? o < f : f < o; + a ? o++ : o-- + ) + t.push(o) + return t + })(0, e, !1).map(function (r) { + return N(t + (r / (e - 1)) * a) + }) + } else { + i = [] + var f = [] + if (s && 2 < s.length) + for ( + var o = 1, u = s.length, c = 1 <= u; + c ? o < u : u < o; + c ? o++ : o-- + ) + f.push(0.5 * (s[o - 1] + s[o])) + else f = l + r = f.map(function (r) { + return N(r) + }) + } + return ( + _[n] && + (r = r.map(function (r) { + return r[n]() + })), + r + ) + }), + (N.cache = function (r) { + return null != r ? ((m = r), N) : m + }), + (N.gamma = function (r) { + return null != r ? ((y = r), N) : y + }), + (N.nodata = function (r) { + return null != r ? ((c = _(r)), N) : c + }), + N + ) + } + var an = function (r) { + var e, n, t, a, f, o, u + if ( + 2 === + (r = r.map(function (r) { + return new A(r) + })).length + ) + (e = r.map(function (r) { + return r.lab() + })), + (f = e[0]), + (o = e[1]), + (a = function (e) { + var r = [0, 1, 2].map(function (r) { + return f[r] + e * (o[r] - f[r]) + }) + return new A(r, 'lab') + }) + else if (3 === r.length) + (n = r.map(function (r) { + return r.lab() + })), + (f = n[0]), + (o = n[1]), + (u = n[2]), + (a = function (e) { + var r = [0, 1, 2].map(function (r) { + return ( + (1 - e) * (1 - e) * f[r] + + 2 * (1 - e) * e * o[r] + + e * e * u[r] + ) + }) + return new A(r, 'lab') + }) + else if (4 === r.length) { + var c + ;(t = r.map(function (r) { + return r.lab() + })), + (f = t[0]), + (o = t[1]), + (u = t[2]), + (c = t[3]), + (a = function (e) { + var r = [0, 1, 2].map(function (r) { + return ( + (1 - e) * (1 - e) * (1 - e) * f[r] + + 3 * (1 - e) * (1 - e) * e * o[r] + + 3 * (1 - e) * e * e * u[r] + + e * e * e * c[r] + ) + }) + return new A(r, 'lab') + }) + } else if (5 === r.length) { + var i = an(r.slice(0, 3)), + l = an(r.slice(2, 5)) + a = function (r) { + return r < 0.5 ? i(2 * r) : l(2 * (r - 0.5)) + } + } + return a + }, + fn = function (r, e, n) { + if (!fn[n]) throw new Error('unknown blend mode ' + n) + return fn[n](r, e) + }, + on = function (a) { + return function (r, e) { + var n = _(e).rgb(), + t = _(r).rgb() + return _.rgb(a(n, t)) + } + }, + un = function (t) { + return function (r, e) { + var n = [] + return ( + (n[0] = t(r[0], e[0])), + (n[1] = t(r[1], e[1])), + (n[2] = t(r[2], e[2])), + n + ) + } + } + ;(fn.normal = on( + un(function (r) { + return r + }) + )), + (fn.multiply = on( + un(function (r, e) { + return (r * e) / 255 + }) + )), + (fn.screen = on( + un(function (r, e) { + return 255 * (1 - (1 - r / 255) * (1 - e / 255)) + }) + )), + (fn.overlay = on( + un(function (r, e) { + return e < 128 + ? (2 * r * e) / 255 + : 255 * (1 - 2 * (1 - r / 255) * (1 - e / 255)) + }) + )), + (fn.darken = on( + un(function (r, e) { + return e < r ? e : r + }) + )), + (fn.lighten = on( + un(function (r, e) { + return e < r ? r : e + }) + )), + (fn.dodge = on( + un(function (r, e) { + return 255 === r + ? 255 + : 255 < (r = ((e / 255) * 255) / (1 - r / 255)) + ? 255 + : r + }) + )), + (fn.burn = on( + un(function (r, e) { + return 255 * (1 - (1 - e / 255) / (r / 255)) + }) + )) + for ( + var cn = fn, + ln = o.type, + hn = o.clip_rgb, + dn = o.TWOPI, + sn = Math.pow, + bn = Math.sin, + pn = Math.cos, + gn = Math.floor, + vn = Math.random, + mn = Math.log, + yn = Math.pow, + wn = Math.floor, + kn = Math.abs, + Mn = function (r, e) { + void 0 === e && (e = null) + var n = { + min: Number.MAX_VALUE, + max: -1 * Number.MAX_VALUE, + sum: 0, + values: [], + count: 0, + } + return ( + 'object' === Y(r) && (r = Object.values(r)), + r.forEach(function (r) { + e && 'object' === Y(r) && (r = r[e]), + null == r || + isNaN(r) || + (n.values.push(r), + (n.sum += r), + r < n.min && (n.min = r), + r > n.max && (n.max = r), + (n.count += 1)) + }), + (n.domain = [n.min, n.max]), + (n.limits = function (r, e) { + return Nn(n, r, e) + }), + n + ) + }, + Nn = function (r, e, n) { + void 0 === e && (e = 'equal'), + void 0 === n && (n = 7), + 'array' == Y(r) && (r = Mn(r)) + var t = r.min, + a = r.max, + f = r.values.sort(function (r, e) { + return r - e + }) + if (1 === n) return [t, a] + var o = [] + if ( + ('c' === e.substr(0, 1) && (o.push(t), o.push(a)), + 'e' === e.substr(0, 1)) + ) { + o.push(t) + for (var u = 1; u < n; u++) o.push(t + (u / n) * (a - t)) + o.push(a) + } else if ('l' === e.substr(0, 1)) { + if (t <= 0) + throw new Error( + 'Logarithmic scales are only possible for values > 0' + ) + var c = Math.LOG10E * mn(t), + i = Math.LOG10E * mn(a) + o.push(t) + for (var l = 1; l < n; l++) + o.push(yn(10, c + (l / n) * (i - c))) + o.push(a) + } else if ('q' === e.substr(0, 1)) { + o.push(t) + for (var h = 1; h < n; h++) { + var d = ((f.length - 1) * h) / n, + s = wn(d) + if (s === d) o.push(f[s]) + else { + var b = d - s + o.push(f[s] * (1 - b) + f[s + 1] * b) + } + } + o.push(a) + } else if ('k' === e.substr(0, 1)) { + var p, + g = f.length, + v = new Array(g), + m = new Array(n), + y = !0, + w = 0, + k = null + ;(k = []).push(t) + for (var M = 1; M < n; M++) k.push(t + (M / n) * (a - t)) + for (k.push(a); y; ) { + for (var N = 0; N < n; N++) m[N] = 0 + for (var _ = 0; _ < g; _++) + for ( + var x = f[_], + A = Number.MAX_VALUE, + E = void 0, + P = 0; + P < n; + P++ + ) { + var F = kn(k[P] - x) + F < A && ((A = F), (E = P)), m[E]++, (v[_] = E) + } + for (var O = new Array(n), j = 0; j < n; j++) + O[j] = null + for (var G = 0; G < g; G++) + null === O[(p = v[G])] + ? (O[p] = f[G]) + : (O[p] += f[G]) + for (var q = 0; q < n; q++) O[q] *= 1 / m[q] + y = !1 + for (var L = 0; L < n; L++) + if (O[L] !== k[L]) { + y = !0 + break + } + ;(k = O), 200 < ++w && (y = !1) + } + for (var R = {}, I = 0; I < n; I++) R[I] = [] + for (var B = 0; B < g; B++) R[(p = v[B])].push(f[B]) + for (var C = [], D = 0; D < n; D++) + C.push(R[D][0]), C.push(R[D][R[D].length - 1]) + ;(C = C.sort(function (r, e) { + return r - e + })), + o.push(C[0]) + for (var S = 1; S < C.length; S += 2) { + var $ = C[S] + isNaN($) || -1 !== o.indexOf($) || o.push($) + } + } + return o + }, + _n = { analyze: Mn, limits: Nn }, + xn = Math.sqrt, + An = Math.atan2, + En = Math.abs, + Pn = Math.cos, + Fn = Math.PI, + On = { + cool: function () { + return tn([_.hsl(180, 1, 0.9), _.hsl(250, 0.7, 0.4)]) + }, + hot: function () { + return tn(['#000', '#f00', '#ff0', '#fff']).mode('rgb') + }, + }, + jn = { + OrRd: [ + '#fff7ec', + '#fee8c8', + '#fdd49e', + '#fdbb84', + '#fc8d59', + '#ef6548', + '#d7301f', + '#b30000', + '#7f0000', + ], + PuBu: [ + '#fff7fb', + '#ece7f2', + '#d0d1e6', + '#a6bddb', + '#74a9cf', + '#3690c0', + '#0570b0', + '#045a8d', + '#023858', + ], + BuPu: [ + '#f7fcfd', + '#e0ecf4', + '#bfd3e6', + '#9ebcda', + '#8c96c6', + '#8c6bb1', + '#88419d', + '#810f7c', + '#4d004b', + ], + Oranges: [ + '#fff5eb', + '#fee6ce', + '#fdd0a2', + '#fdae6b', + '#fd8d3c', + '#f16913', + '#d94801', + '#a63603', + '#7f2704', + ], + BuGn: [ + '#f7fcfd', + '#e5f5f9', + '#ccece6', + '#99d8c9', + '#66c2a4', + '#41ae76', + '#238b45', + '#006d2c', + '#00441b', + ], + YlOrBr: [ + '#ffffe5', + '#fff7bc', + '#fee391', + '#fec44f', + '#fe9929', + '#ec7014', + '#cc4c02', + '#993404', + '#662506', + ], + YlGn: [ + '#ffffe5', + '#f7fcb9', + '#d9f0a3', + '#addd8e', + '#78c679', + '#41ab5d', + '#238443', + '#006837', + '#004529', + ], + Reds: [ + '#fff5f0', + '#fee0d2', + '#fcbba1', + '#fc9272', + '#fb6a4a', + '#ef3b2c', + '#cb181d', + '#a50f15', + '#67000d', + ], + RdPu: [ + '#fff7f3', + '#fde0dd', + '#fcc5c0', + '#fa9fb5', + '#f768a1', + '#dd3497', + '#ae017e', + '#7a0177', + '#49006a', + ], + Greens: [ + '#f7fcf5', + '#e5f5e0', + '#c7e9c0', + '#a1d99b', + '#74c476', + '#41ab5d', + '#238b45', + '#006d2c', + '#00441b', + ], + YlGnBu: [ + '#ffffd9', + '#edf8b1', + '#c7e9b4', + '#7fcdbb', + '#41b6c4', + '#1d91c0', + '#225ea8', + '#253494', + '#081d58', + ], + Purples: [ + '#fcfbfd', + '#efedf5', + '#dadaeb', + '#bcbddc', + '#9e9ac8', + '#807dba', + '#6a51a3', + '#54278f', + '#3f007d', + ], + GnBu: [ + '#f7fcf0', + '#e0f3db', + '#ccebc5', + '#a8ddb5', + '#7bccc4', + '#4eb3d3', + '#2b8cbe', + '#0868ac', + '#084081', + ], + Greys: [ + '#ffffff', + '#f0f0f0', + '#d9d9d9', + '#bdbdbd', + '#969696', + '#737373', + '#525252', + '#252525', + '#000000', + ], + YlOrRd: [ + '#ffffcc', + '#ffeda0', + '#fed976', + '#feb24c', + '#fd8d3c', + '#fc4e2a', + '#e31a1c', + '#bd0026', + '#800026', + ], + PuRd: [ + '#f7f4f9', + '#e7e1ef', + '#d4b9da', + '#c994c7', + '#df65b0', + '#e7298a', + '#ce1256', + '#980043', + '#67001f', + ], + Blues: [ + '#f7fbff', + '#deebf7', + '#c6dbef', + '#9ecae1', + '#6baed6', + '#4292c6', + '#2171b5', + '#08519c', + '#08306b', + ], + PuBuGn: [ + '#fff7fb', + '#ece2f0', + '#d0d1e6', + '#a6bddb', + '#67a9cf', + '#3690c0', + '#02818a', + '#016c59', + '#014636', + ], + Viridis: [ + '#440154', + '#482777', + '#3f4a8a', + '#31678e', + '#26838f', + '#1f9d8a', + '#6cce5a', + '#b6de2b', + '#fee825', + ], + Spectral: [ + '#9e0142', + '#d53e4f', + '#f46d43', + '#fdae61', + '#fee08b', + '#ffffbf', + '#e6f598', + '#abdda4', + '#66c2a5', + '#3288bd', + '#5e4fa2', + ], + RdYlGn: [ + '#a50026', + '#d73027', + '#f46d43', + '#fdae61', + '#fee08b', + '#ffffbf', + '#d9ef8b', + '#a6d96a', + '#66bd63', + '#1a9850', + '#006837', + ], + RdBu: [ + '#67001f', + '#b2182b', + '#d6604d', + '#f4a582', + '#fddbc7', + '#f7f7f7', + '#d1e5f0', + '#92c5de', + '#4393c3', + '#2166ac', + '#053061', + ], + PiYG: [ + '#8e0152', + '#c51b7d', + '#de77ae', + '#f1b6da', + '#fde0ef', + '#f7f7f7', + '#e6f5d0', + '#b8e186', + '#7fbc41', + '#4d9221', + '#276419', + ], + PRGn: [ + '#40004b', + '#762a83', + '#9970ab', + '#c2a5cf', + '#e7d4e8', + '#f7f7f7', + '#d9f0d3', + '#a6dba0', + '#5aae61', + '#1b7837', + '#00441b', + ], + RdYlBu: [ + '#a50026', + '#d73027', + '#f46d43', + '#fdae61', + '#fee090', + '#ffffbf', + '#e0f3f8', + '#abd9e9', + '#74add1', + '#4575b4', + '#313695', + ], + BrBG: [ + '#543005', + '#8c510a', + '#bf812d', + '#dfc27d', + '#f6e8c3', + '#f5f5f5', + '#c7eae5', + '#80cdc1', + '#35978f', + '#01665e', + '#003c30', + ], + RdGy: [ + '#67001f', + '#b2182b', + '#d6604d', + '#f4a582', + '#fddbc7', + '#ffffff', + '#e0e0e0', + '#bababa', + '#878787', + '#4d4d4d', + '#1a1a1a', + ], + PuOr: [ + '#7f3b08', + '#b35806', + '#e08214', + '#fdb863', + '#fee0b6', + '#f7f7f7', + '#d8daeb', + '#b2abd2', + '#8073ac', + '#542788', + '#2d004b', + ], + Set2: [ + '#66c2a5', + '#fc8d62', + '#8da0cb', + '#e78ac3', + '#a6d854', + '#ffd92f', + '#e5c494', + '#b3b3b3', + ], + Accent: [ + '#7fc97f', + '#beaed4', + '#fdc086', + '#ffff99', + '#386cb0', + '#f0027f', + '#bf5b17', + '#666666', + ], + Set1: [ + '#e41a1c', + '#377eb8', + '#4daf4a', + '#984ea3', + '#ff7f00', + '#ffff33', + '#a65628', + '#f781bf', + '#999999', + ], + Set3: [ + '#8dd3c7', + '#ffffb3', + '#bebada', + '#fb8072', + '#80b1d3', + '#fdb462', + '#b3de69', + '#fccde5', + '#d9d9d9', + '#bc80bd', + '#ccebc5', + '#ffed6f', + ], + Dark2: [ + '#1b9e77', + '#d95f02', + '#7570b3', + '#e7298a', + '#66a61e', + '#e6ab02', + '#a6761d', + '#666666', + ], + Paired: [ + '#a6cee3', + '#1f78b4', + '#b2df8a', + '#33a02c', + '#fb9a99', + '#e31a1c', + '#fdbf6f', + '#ff7f00', + '#cab2d6', + '#6a3d9a', + '#ffff99', + '#b15928', + ], + Pastel2: [ + '#b3e2cd', + '#fdcdac', + '#cbd5e8', + '#f4cae4', + '#e6f5c9', + '#fff2ae', + '#f1e2cc', + '#cccccc', + ], + Pastel1: [ + '#fbb4ae', + '#b3cde3', + '#ccebc5', + '#decbe4', + '#fed9a6', + '#ffffcc', + '#e5d8bd', + '#fddaec', + '#f2f2f2', + ], + }, + Gn = 0, + qn = Object.keys(jn); + Gn < qn.length; + Gn += 1 + ) { + var Ln = qn[Gn] + jn[Ln.toLowerCase()] = jn[Ln] + } + var Rn = jn + return ( + (_.average = function (r, f, o) { + void 0 === f && (f = 'lrgb'), void 0 === o && (o = null) + var e = r.length + o || + (o = Array.from(new Array(e)).map(function () { + return 1 + })) + var n = + e / + o.reduce(function (r, e) { + return r + e + }) + if ( + (o.forEach(function (r, e) { + o[e] *= n + }), + (r = r.map(function (r) { + return new A(r) + })), + 'lrgb' === f) + ) + return rn(r, o) + for ( + var t = r.shift(), u = t.get(f), c = [], i = 0, l = 0, a = 0; + a < u.length; + a++ + ) + if ( + ((u[a] = (u[a] || 0) * o[0]), + c.push(isNaN(u[a]) ? 0 : o[0]), + 'h' === f.charAt(a) && !isNaN(u[a])) + ) { + var h = (u[a] / 180) * Je + ;(i += Ke(h) * o[0]), (l += Qe(h) * o[0]) + } + var d = t.alpha() * o[0] + r.forEach(function (r, e) { + var n = r.get(f) + d += r.alpha() * o[e + 1] + for (var t = 0; t < u.length; t++) + if (!isNaN(n[t])) + if (((c[t] += o[e + 1]), 'h' === f.charAt(t))) { + var a = (n[t] / 180) * Je + ;(i += Ke(a) * o[e + 1]), (l += Qe(a) * o[e + 1]) + } else u[t] += n[t] * o[e + 1] + }) + for (var s = 0; s < u.length; s++) + if ('h' === f.charAt(s)) { + for (var b = (Ze(l / c[s], i / c[s]) / Je) * 180; b < 0; ) + b += 360 + for (; 360 <= b; ) b -= 360 + u[s] = b + } else u[s] = u[s] / c[s] + return (d /= e), new A(u, f).alpha(0.99999 < d ? 1 : d, !0) + }), + (_.bezier = function (r) { + var e = an(r) + return ( + (e.scale = function () { + return tn(e) + }), + e + ) + }), + (_.blend = cn), + (_.cubehelix = function (o, u, c, i, l) { + void 0 === o && (o = 300), + void 0 === u && (u = -1.5), + void 0 === c && (c = 1), + void 0 === i && (i = 1), + void 0 === l && (l = [0, 1]) + var h, + d = 0 + 'array' === ln(l) ? (h = l[1] - l[0]) : ((h = 0), (l = [l, l])) + var e = function (r) { + var e = dn * ((o + 120) / 360 + u * r), + n = sn(l[0] + h * r, i), + t = ((0 !== d ? c[0] + r * d : c) * n * (1 - n)) / 2, + a = pn(e), + f = bn(e) + return _( + hn([ + 255 * (n + t * (-0.14861 * a + 1.78277 * f)), + 255 * (n + t * (-0.29227 * a - 0.90649 * f)), + 255 * (n + t * (1.97294 * a)), + 1, + ]) + ) + } + return ( + (e.start = function (r) { + return null == r ? o : ((o = r), e) + }), + (e.rotations = function (r) { + return null == r ? u : ((u = r), e) + }), + (e.gamma = function (r) { + return null == r ? i : ((i = r), e) + }), + (e.hue = function (r) { + return null == r + ? c + : ('array' === ln((c = r)) + ? 0 == (d = c[1] - c[0]) && (c = c[1]) + : (d = 0), + e) + }), + (e.lightness = function (r) { + return null == r + ? l + : ((h = + 'array' === ln(r) + ? (l = r)[1] - r[0] + : ((l = [r, r]), 0)), + e) + }), + (e.scale = function () { + return _.scale(e) + }), + e.hue(c), + e + ) + }), + (_.mix = _.interpolate = $e), + (_.random = function () { + for (var r = '#', e = 0; e < 6; e++) + r += '0123456789abcdef'.charAt(gn(16 * vn())) + return new A(r, 'hex') + }), + (_.scale = tn), + (_.analyze = _n.analyze), + (_.contrast = function (r, e) { + ;(r = new A(r)), (e = new A(e)) + var n = r.luminance(), + t = e.luminance() + return t < n ? (n + 0.05) / (t + 0.05) : (t + 0.05) / (n + 0.05) + }), + (_.deltaE = function (r, e, n, t) { + void 0 === n && (n = 1), + void 0 === t && (t = 1), + (r = new A(r)), + (e = new A(e)) + for ( + var a = Array.from(r.lab()), + f = a[0], + o = a[1], + u = a[2], + c = Array.from(e.lab()), + i = c[0], + l = c[1], + h = c[2], + d = xn(o * o + u * u), + s = xn(l * l + h * h), + b = f < 16 ? 0.511 : (0.040975 * f) / (1 + 0.01765 * f), + p = (0.0638 * d) / (1 + 0.0131 * d) + 0.638, + g = d < 1e-6 ? 0 : (180 * An(u, o)) / Fn; + g < 0; + + ) + g += 360 + for (; 360 <= g; ) g -= 360 + var v = + 164 <= g && g <= 345 + ? 0.56 + En(0.2 * Pn((Fn * (g + 168)) / 180)) + : 0.36 + En(0.4 * Pn((Fn * (g + 35)) / 180)), + m = d * d * d * d, + y = xn(m / (m + 1900)), + w = p * (y * v + 1 - y), + k = d - s, + M = o - l, + N = u - h, + _ = (f - i) / (n * b), + x = k / (t * p) + return xn(_ * _ + x * x + (M * M + N * N - k * k) / (w * w)) + }), + (_.distance = function (r, e, n) { + void 0 === n && (n = 'lab'), (r = new A(r)), (e = new A(e)) + var t = r.get(n), + a = e.get(n), + f = 0 + for (var o in t) { + var u = (t[o] || 0) - (a[o] || 0) + f += u * u + } + return Math.sqrt(f) + }), + (_.limits = _n.limits), + (_.valid = function () { + for (var r = [], e = arguments.length; e--; ) r[e] = arguments[e] + try { + return ( + new (Function.prototype.bind.apply(A, [null].concat(r)))(), + !0 + ) + } catch (r) { + return !1 + } + }), + (_.scales = On), + (_.colors = ye), + (_.brewer = Rn), + _ + ) +}) diff --git a/experiments/twgl-tunnel/dist/require.js b/experiments/twgl-tunnel/dist/require.js index 5360d3b..c6a29cb 100644 --- a/experiments/twgl-tunnel/dist/require.js +++ b/experiments/twgl-tunnel/dist/require.js @@ -3,34 +3,1071 @@ Available via the MIT or new BSD license. see: http://github.com/jrburke/requirejs for details */ -var requirejs,require,define; -(function(ca){function G(b){return"[object Function]"===M.call(b)}function H(b){return"[object Array]"===M.call(b)}function v(b,c){if(b){var d;for(d=0;dthis.depCount&&!this.defined){if(G(c)){if(this.events.error&&this.map.isDefine||h.onError!==da)try{f=i.execCb(b,c,e,f)}catch(d){a=d}else f=i.execCb(b,c,e,f);this.map.isDefine&&void 0===f&&((e=this.module)?f=e.exports:this.usingExports&& -(f=this.exports));if(a)return a.requireMap=this.map,a.requireModules=this.map.isDefine?[this.map.id]:null,a.requireType=this.map.isDefine?"define":"require",w(this.error=a)}else f=c;this.exports=f;if(this.map.isDefine&&!this.ignore&&(p[b]=f,h.onResourceLoad))h.onResourceLoad(i,this.map,this.depMaps);y(b);this.defined=!0}this.defining=!1;this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete=!0)}}else this.fetch()}},callPlugin:function(){var a= -this.map,b=a.id,d=m(a.prefix);this.depMaps.push(d);r(d,"defined",t(this,function(f){var d,g;g=j(ba,this.map.id);var J=this.map.name,u=this.map.parentMap?this.map.parentMap.name:null,p=i.makeRequire(a.parentMap,{enableBuildCallback:!0});if(this.map.unnormalized){if(f.normalize&&(J=f.normalize(J,function(a){return c(a,u,!0)})||""),f=m(a.prefix+"!"+J,this.map.parentMap),r(f,"defined",t(this,function(a){this.init([],function(){return a},null,{enabled:!0,ignore:!0})})),g=j(k,f.id)){this.depMaps.push(f); -if(this.events.error)g.on("error",t(this,function(a){this.emit("error",a)}));g.enable()}}else g?(this.map.url=i.nameToUrl(g),this.load()):(d=t(this,function(a){this.init([],function(){return a},null,{enabled:!0})}),d.error=t(this,function(a){this.inited=!0;this.error=a;a.requireModules=[b];B(k,function(a){0===a.map.id.indexOf(b+"_unnormalized")&&y(a.map.id)});w(a)}),d.fromText=t(this,function(f,c){var g=a.name,J=m(g),k=O;c&&(f=c);k&&(O=!1);q(J);s(l.config,b)&&(l.config[g]=l.config[b]);try{h.exec(f)}catch(j){return w(C("fromtexteval", -"fromText eval for "+b+" failed: "+j,j,[b]))}k&&(O=!0);this.depMaps.push(J);i.completeLoad(g);p([g],d)}),f.load(a.name,p,d,l))}));i.enable(d,this);this.pluginMaps[d.id]=d},enable:function(){W[this.map.id]=this;this.enabling=this.enabled=!0;v(this.depMaps,t(this,function(a,b){var c,f;if("string"===typeof a){a=m(a,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap);this.depMaps[b]=a;if(c=j(N,a.id)){this.depExports[b]=c(this);return}this.depCount+=1;r(a,"defined",t(this,function(a){this.defineDep(b, -a);this.check()}));this.errback&&r(a,"error",t(this,this.errback))}c=a.id;f=k[c];!s(N,c)&&(f&&!f.enabled)&&i.enable(a,this)}));B(this.pluginMaps,t(this,function(a){var b=j(k,a.id);b&&!b.enabled&&i.enable(a,this)}));this.enabling=!1;this.check()},on:function(a,b){var c=this.events[a];c||(c=this.events[a]=[]);c.push(b)},emit:function(a,b){v(this.events[a],function(a){a(b)});"error"===a&&delete this.events[a]}};i={config:l,contextName:b,registry:k,defined:p,urlFetched:T,defQueue:A,Module:$,makeModuleMap:m, -nextTick:h.nextTick,onError:w,configure:function(a){a.baseUrl&&"/"!==a.baseUrl.charAt(a.baseUrl.length-1)&&(a.baseUrl+="/");var b=l.shim,c={paths:!0,bundles:!0,config:!0,map:!0};B(a,function(a,b){c[b]?(l[b]||(l[b]={}),V(l[b],a,!0,!0)):l[b]=a});a.bundles&&B(a.bundles,function(a,b){v(a,function(a){a!==b&&(ba[a]=b)})});a.shim&&(B(a.shim,function(a,c){H(a)&&(a={deps:a});if((a.exports||a.init)&&!a.exportsFn)a.exportsFn=i.makeShimExports(a);b[c]=a}),l.shim=b);a.packages&&v(a.packages,function(a){var b, -a="string"===typeof a?{name:a}:a;b=a.name;a.location&&(l.paths[b]=a.location);l.pkgs[b]=a.name+"/"+(a.main||"main").replace(ja,"").replace(R,"")});B(k,function(a,b){!a.inited&&!a.map.unnormalized&&(a.map=m(b))});if(a.deps||a.callback)i.require(a.deps||[],a.callback)},makeShimExports:function(a){return function(){var b;a.init&&(b=a.init.apply(ca,arguments));return b||a.exports&&ea(a.exports)}},makeRequire:function(a,e){function g(f,c,d){var j,l;e.enableBuildCallback&&(c&&G(c))&&(c.__requireJsBuild= -!0);if("string"===typeof f){if(G(c))return w(C("requireargs","Invalid require call"),d);if(a&&s(N,f))return N[f](k[a.id]);if(h.get)return h.get(i,f,a,g);j=m(f,a,!1,!0);j=j.id;return!s(p,j)?w(C("notloaded",'Module name "'+j+'" has not been loaded yet for context: '+b+(a?"":". Use require([])"))):p[j]}L();i.nextTick(function(){L();l=q(m(null,a));l.skipMap=e.skipMap;l.init(f,c,d,{enabled:!0});D()});return g}e=e||{};V(g,{isBrowser:z,toUrl:function(b){var e,d=b.lastIndexOf("."),g=b.split("/")[0];if(-1!== -d&&(!("."===g||".."===g)||1g.attachEvent.toString().indexOf("[native code"))&&!Z?(O=!0,g.attachEvent("onreadystatechange",b.onScriptLoad)): -(g.addEventListener("load",b.onScriptLoad,!1),g.addEventListener("error",b.onScriptError,!1)),g.src=d,L=g,D?y.insertBefore(g,D):y.appendChild(g),L=null,g;if(fa)try{importScripts(d),b.completeLoad(c)}catch(j){b.onError(C("importscripts","importScripts failed for "+c+" at "+d,j,[c]))}};z&&!r.skipDataMain&&U(document.getElementsByTagName("script"),function(b){y||(y=b.parentNode);if(K=b.getAttribute("data-main"))return q=K,r.baseUrl||(E=q.split("/"),q=E.pop(),Q=E.length?E.join("/")+"/":"./",r.baseUrl= -Q),q=q.replace(R,""),h.jsExtRegExp.test(q)&&(q=K),r.deps=r.deps?r.deps.concat(q):[q],!0});define=function(b,c,d){var g,h;"string"!==typeof b&&(d=c,c=b,b=null);H(c)||(d=c,c=null);!c&&G(d)&&(c=[],d.length&&(d.toString().replace(la,"").replace(ma,function(b,d){c.push(d)}),c=(1===d.length?["require"]:["require","exports","module"]).concat(c)));if(O){if(!(g=L))P&&"interactive"===P.readyState||U(document.getElementsByTagName("script"),function(b){if("interactive"===b.readyState)return P=b}),g=P;g&&(b|| -(b=g.getAttribute("data-requiremodule")),h=F[g.getAttribute("data-requirecontext")])}(h?h.defQueue:S).push([b,c,d])};define.amd={jQuery:!0};h.exec=function(b){return eval(b)};h(r)}})(this); \ No newline at end of file +var requirejs, require, define +;(function (ca) { + function G(b) { + return '[object Function]' === M.call(b) + } + function H(b) { + return '[object Array]' === M.call(b) + } + function v(b, c) { + if (b) { + var d + for (d = 0; d < b.length && (!b[d] || !c(b[d], d, b)); d += 1); + } + } + function U(b, c) { + if (b) { + var d + for (d = b.length - 1; -1 < d && (!b[d] || !c(b[d], d, b)); d -= 1); + } + } + function s(b, c) { + return ga.call(b, c) + } + function j(b, c) { + return s(b, c) && b[c] + } + function B(b, c) { + for (var d in b) if (s(b, d) && c(b[d], d)) break + } + function V(b, c, d, g) { + c && + B(c, function (c, h) { + if (d || !s(b, h)) + g && + 'object' === typeof c && + c && + !H(c) && + !G(c) && + !(c instanceof RegExp) + ? (b[h] || (b[h] = {}), V(b[h], c, d, g)) + : (b[h] = c) + }) + return b + } + function t(b, c) { + return function () { + return c.apply(b, arguments) + } + } + function da(b) { + throw b + } + function ea(b) { + if (!b) return b + var c = ca + v(b.split('.'), function (b) { + c = c[b] + }) + return c + } + function C(b, c, d, g) { + c = Error(c + '\nhttp://requirejs.org/docs/errors.html#' + b) + c.requireType = b + c.requireModules = g + d && (c.originalError = d) + return c + } + function ha(b) { + function c(a, e, b) { + var f, + n, + c, + d, + g, + h, + i, + I = e && e.split('/') + n = I + var m = l.map, + k = m && m['*'] + if (a && '.' === a.charAt(0)) + if (e) { + n = I.slice(0, I.length - 1) + a = a.split('/') + e = a.length - 1 + l.nodeIdCompat && + R.test(a[e]) && + (a[e] = a[e].replace(R, '')) + n = a = n.concat(a) + d = n.length + for (e = 0; e < d; e++) + if (((c = n[e]), '.' === c)) n.splice(e, 1), (e -= 1) + else if ('..' === c) + if (1 === e && ('..' === n[2] || '..' === n[0])) + break + else 0 < e && (n.splice(e - 1, 2), (e -= 2)) + a = a.join('/') + } else 0 === a.indexOf('./') && (a = a.substring(2)) + if (b && m && (I || k)) { + n = a.split('/') + e = n.length + a: for (; 0 < e; e -= 1) { + d = n.slice(0, e).join('/') + if (I) + for (c = I.length; 0 < c; c -= 1) + if ((b = j(m, I.slice(0, c).join('/')))) + if ((b = j(b, d))) { + f = b + g = e + break a + } + !h && k && j(k, d) && ((h = j(k, d)), (i = e)) + } + !f && h && ((f = h), (g = i)) + f && (n.splice(0, g, f), (a = n.join('/'))) + } + return (f = j(l.pkgs, a)) ? f : a + } + function d(a) { + z && + v(document.getElementsByTagName('script'), function (e) { + if ( + e.getAttribute('data-requiremodule') === a && + e.getAttribute('data-requirecontext') === i.contextName + ) + return e.parentNode.removeChild(e), !0 + }) + } + function g(a) { + var e = j(l.paths, a) + if (e && H(e) && 1 < e.length) + return e.shift(), i.require.undef(a), i.require([a]), !0 + } + function u(a) { + var e, + b = a ? a.indexOf('!') : -1 + ;-1 < b && + ((e = a.substring(0, b)), (a = a.substring(b + 1, a.length))) + return [e, a] + } + function m(a, e, b, f) { + var n, + d, + g = null, + h = e ? e.name : null, + l = a, + m = !0, + k = '' + a || ((m = !1), (a = '_@r' + (M += 1))) + a = u(a) + g = a[0] + a = a[1] + g && ((g = c(g, h, f)), (d = j(p, g))) + a && + (g + ? (k = + d && d.normalize + ? d.normalize(a, function (a) { + return c(a, h, f) + }) + : c(a, h, f)) + : ((k = c(a, h, f)), + (a = u(k)), + (g = a[0]), + (k = a[1]), + (b = !0), + (n = i.nameToUrl(k)))) + b = g && !d && !b ? '_unnormalized' + (Q += 1) : '' + return { + prefix: g, + name: k, + parentMap: e, + unnormalized: !!b, + url: n, + originalName: l, + isDefine: m, + id: (g ? g + '!' + k : k) + b, + } + } + function q(a) { + var e = a.id, + b = j(k, e) + b || (b = k[e] = new i.Module(a)) + return b + } + function r(a, e, b) { + var f = a.id, + n = j(k, f) + if (s(p, f) && (!n || n.defineEmitComplete)) + 'defined' === e && b(p[f]) + else if (((n = q(a)), n.error && 'error' === e)) b(n.error) + else n.on(e, b) + } + function w(a, e) { + var b = a.requireModules, + f = !1 + if (e) e(a) + else if ( + (v(b, function (e) { + if ((e = j(k, e))) + (e.error = a), + e.events.error && ((f = !0), e.emit('error', a)) + }), + !f) + ) + h.onError(a) + } + function x() { + S.length && (ia.apply(A, [A.length, 0].concat(S)), (S = [])) + } + function y(a) { + delete k[a] + delete W[a] + } + function F(a, e, b) { + var f = a.map.id + a.error + ? a.emit('error', a.error) + : ((e[f] = !0), + v(a.depMaps, function (f, c) { + var d = f.id, + g = j(k, d) + g && + !a.depMatched[c] && + !b[d] && + (j(e, d) + ? (a.defineDep(c, p[d]), a.check()) + : F(g, e, b)) + }), + (b[f] = !0)) + } + function D() { + var a, + e, + b = + (a = 1e3 * l.waitSeconds) && + i.startTime + a < new Date().getTime(), + f = [], + c = [], + h = !1, + k = !0 + if (!X) { + X = !0 + B(W, function (a) { + var i = a.map, + m = i.id + if (a.enabled && (i.isDefine || c.push(a), !a.error)) + if (!a.inited && b) + g(m) ? (h = e = !0) : (f.push(m), d(m)) + else if ( + !a.inited && + a.fetched && + i.isDefine && + ((h = !0), !i.prefix) + ) + return (k = !1) + }) + if (b && f.length) + return ( + (a = C( + 'timeout', + 'Load timeout for modules: ' + f, + null, + f + )), + (a.contextName = i.contextName), + w(a) + ) + k && + v(c, function (a) { + F(a, {}, {}) + }) + if ((!b || e) && h) + if ((z || fa) && !Y) + Y = setTimeout(function () { + Y = 0 + D() + }, 50) + X = !1 + } + } + function E(a) { + s(p, a[0]) || q(m(a[0], null, !0)).init(a[1], a[2]) + } + function K(a) { + var a = a.currentTarget || a.srcElement, + e = i.onScriptLoad + a.detachEvent && !Z + ? a.detachEvent('onreadystatechange', e) + : a.removeEventListener('load', e, !1) + e = i.onScriptError + ;(!a.detachEvent || Z) && a.removeEventListener('error', e, !1) + return { node: a, id: a && a.getAttribute('data-requiremodule') } + } + function L() { + var a + for (x(); A.length; ) { + a = A.shift() + if (null === a[0]) + return w( + C( + 'mismatch', + 'Mismatched anonymous define() module: ' + + a[a.length - 1] + ) + ) + E(a) + } + } + var X, + $, + i, + N, + Y, + l = { + waitSeconds: 7, + baseUrl: './', + paths: {}, + bundles: {}, + pkgs: {}, + shim: {}, + config: {}, + }, + k = {}, + W = {}, + aa = {}, + A = [], + p = {}, + T = {}, + ba = {}, + M = 1, + Q = 1 + N = { + require: function (a) { + return a.require + ? a.require + : (a.require = i.makeRequire(a.map)) + }, + exports: function (a) { + a.usingExports = !0 + if (a.map.isDefine) + return a.exports + ? (p[a.map.id] = a.exports) + : (a.exports = p[a.map.id] = {}) + }, + module: function (a) { + return a.module + ? a.module + : (a.module = { + id: a.map.id, + uri: a.map.url, + config: function () { + return j(l.config, a.map.id) || {} + }, + exports: a.exports || (a.exports = {}), + }) + }, + } + $ = function (a) { + this.events = j(aa, a.id) || {} + this.map = a + this.shim = j(l.shim, a.id) + this.depExports = [] + this.depMaps = [] + this.depMatched = [] + this.pluginMaps = {} + this.depCount = 0 + } + $.prototype = { + init: function (a, e, b, f) { + f = f || {} + if (!this.inited) { + this.factory = e + if (b) this.on('error', b) + else + this.events.error && + (b = t(this, function (a) { + this.emit('error', a) + })) + this.depMaps = a && a.slice(0) + this.errback = b + this.inited = !0 + this.ignore = f.ignore + f.enabled || this.enabled ? this.enable() : this.check() + } + }, + defineDep: function (a, e) { + this.depMatched[a] || + ((this.depMatched[a] = !0), + (this.depCount -= 1), + (this.depExports[a] = e)) + }, + fetch: function () { + if (!this.fetched) { + this.fetched = !0 + i.startTime = new Date().getTime() + var a = this.map + if (this.shim) + i.makeRequire(this.map, { enableBuildCallback: !0 })( + this.shim.deps || [], + t(this, function () { + return a.prefix + ? this.callPlugin() + : this.load() + }) + ) + else return a.prefix ? this.callPlugin() : this.load() + } + }, + load: function () { + var a = this.map.url + T[a] || ((T[a] = !0), i.load(this.map.id, a)) + }, + check: function () { + if (this.enabled && !this.enabling) { + var a, + e, + b = this.map.id + e = this.depExports + var f = this.exports, + c = this.factory + if (this.inited) + if (this.error) this.emit('error', this.error) + else { + if (!this.defining) { + this.defining = !0 + if (1 > this.depCount && !this.defined) { + if (G(c)) { + if ( + (this.events.error && + this.map.isDefine) || + h.onError !== da + ) + try { + f = i.execCb(b, c, e, f) + } catch (d) { + a = d + } + else f = i.execCb(b, c, e, f) + this.map.isDefine && + void 0 === f && + ((e = this.module) + ? (f = e.exports) + : this.usingExports && + (f = this.exports)) + if (a) + return ( + (a.requireMap = this.map), + (a.requireModules = this.map + .isDefine + ? [this.map.id] + : null), + (a.requireType = this.map + .isDefine + ? 'define' + : 'require'), + w((this.error = a)) + ) + } else f = c + this.exports = f + if ( + this.map.isDefine && + !this.ignore && + ((p[b] = f), h.onResourceLoad) + ) + h.onResourceLoad( + i, + this.map, + this.depMaps + ) + y(b) + this.defined = !0 + } + this.defining = !1 + this.defined && + !this.defineEmitted && + ((this.defineEmitted = !0), + this.emit('defined', this.exports), + (this.defineEmitComplete = !0)) + } + } + else this.fetch() + } + }, + callPlugin: function () { + var a = this.map, + b = a.id, + d = m(a.prefix) + this.depMaps.push(d) + r( + d, + 'defined', + t(this, function (f) { + var d, g + g = j(ba, this.map.id) + var J = this.map.name, + u = this.map.parentMap + ? this.map.parentMap.name + : null, + p = i.makeRequire(a.parentMap, { + enableBuildCallback: !0, + }) + if (this.map.unnormalized) { + if ( + (f.normalize && + (J = + f.normalize(J, function (a) { + return c(a, u, !0) + }) || ''), + (f = m(a.prefix + '!' + J, this.map.parentMap)), + r( + f, + 'defined', + t(this, function (a) { + this.init( + [], + function () { + return a + }, + null, + { enabled: !0, ignore: !0 } + ) + }) + ), + (g = j(k, f.id))) + ) { + this.depMaps.push(f) + if (this.events.error) + g.on( + 'error', + t(this, function (a) { + this.emit('error', a) + }) + ) + g.enable() + } + } else + g + ? ((this.map.url = i.nameToUrl(g)), this.load()) + : ((d = t(this, function (a) { + this.init( + [], + function () { + return a + }, + null, + { enabled: !0 } + ) + })), + (d.error = t(this, function (a) { + this.inited = !0 + this.error = a + a.requireModules = [b] + B(k, function (a) { + 0 === + a.map.id.indexOf( + b + '_unnormalized' + ) && y(a.map.id) + }) + w(a) + })), + (d.fromText = t(this, function (f, c) { + var g = a.name, + J = m(g), + k = O + c && (f = c) + k && (O = !1) + q(J) + s(l.config, b) && + (l.config[g] = l.config[b]) + try { + h.exec(f) + } catch (j) { + return w( + C( + 'fromtexteval', + 'fromText eval for ' + + b + + ' failed: ' + + j, + j, + [b] + ) + ) + } + k && (O = !0) + this.depMaps.push(J) + i.completeLoad(g) + p([g], d) + })), + f.load(a.name, p, d, l)) + }) + ) + i.enable(d, this) + this.pluginMaps[d.id] = d + }, + enable: function () { + W[this.map.id] = this + this.enabling = this.enabled = !0 + v( + this.depMaps, + t(this, function (a, b) { + var c, f + if ('string' === typeof a) { + a = m( + a, + this.map.isDefine + ? this.map + : this.map.parentMap, + !1, + !this.skipMap + ) + this.depMaps[b] = a + if ((c = j(N, a.id))) { + this.depExports[b] = c(this) + return + } + this.depCount += 1 + r( + a, + 'defined', + t(this, function (a) { + this.defineDep(b, a) + this.check() + }) + ) + this.errback && r(a, 'error', t(this, this.errback)) + } + c = a.id + f = k[c] + !s(N, c) && f && !f.enabled && i.enable(a, this) + }) + ) + B( + this.pluginMaps, + t(this, function (a) { + var b = j(k, a.id) + b && !b.enabled && i.enable(a, this) + }) + ) + this.enabling = !1 + this.check() + }, + on: function (a, b) { + var c = this.events[a] + c || (c = this.events[a] = []) + c.push(b) + }, + emit: function (a, b) { + v(this.events[a], function (a) { + a(b) + }) + 'error' === a && delete this.events[a] + }, + } + i = { + config: l, + contextName: b, + registry: k, + defined: p, + urlFetched: T, + defQueue: A, + Module: $, + makeModuleMap: m, + nextTick: h.nextTick, + onError: w, + configure: function (a) { + a.baseUrl && + '/' !== a.baseUrl.charAt(a.baseUrl.length - 1) && + (a.baseUrl += '/') + var b = l.shim, + c = { paths: !0, bundles: !0, config: !0, map: !0 } + B(a, function (a, b) { + c[b] + ? (l[b] || (l[b] = {}), V(l[b], a, !0, !0)) + : (l[b] = a) + }) + a.bundles && + B(a.bundles, function (a, b) { + v(a, function (a) { + a !== b && (ba[a] = b) + }) + }) + a.shim && + (B(a.shim, function (a, c) { + H(a) && (a = { deps: a }) + if ((a.exports || a.init) && !a.exportsFn) + a.exportsFn = i.makeShimExports(a) + b[c] = a + }), + (l.shim = b)) + a.packages && + v(a.packages, function (a) { + var b, + a = 'string' === typeof a ? { name: a } : a + b = a.name + a.location && (l.paths[b] = a.location) + l.pkgs[b] = + a.name + + '/' + + (a.main || 'main').replace(ja, '').replace(R, '') + }) + B(k, function (a, b) { + !a.inited && !a.map.unnormalized && (a.map = m(b)) + }) + if (a.deps || a.callback) i.require(a.deps || [], a.callback) + }, + makeShimExports: function (a) { + return function () { + var b + a.init && (b = a.init.apply(ca, arguments)) + return b || (a.exports && ea(a.exports)) + } + }, + makeRequire: function (a, e) { + function g(f, c, d) { + var j, l + e.enableBuildCallback && + c && + G(c) && + (c.__requireJsBuild = !0) + if ('string' === typeof f) { + if (G(c)) + return w( + C('requireargs', 'Invalid require call'), + d + ) + if (a && s(N, f)) return N[f](k[a.id]) + if (h.get) return h.get(i, f, a, g) + j = m(f, a, !1, !0) + j = j.id + return !s(p, j) + ? w( + C( + 'notloaded', + 'Module name "' + + j + + '" has not been loaded yet for context: ' + + b + + (a ? '' : '. Use require([])') + ) + ) + : p[j] + } + L() + i.nextTick(function () { + L() + l = q(m(null, a)) + l.skipMap = e.skipMap + l.init(f, c, d, { enabled: !0 }) + D() + }) + return g + } + e = e || {} + V(g, { + isBrowser: z, + toUrl: function (b) { + var e, + d = b.lastIndexOf('.'), + g = b.split('/')[0] + if (-1 !== d && (!('.' === g || '..' === g) || 1 < d)) + (e = b.substring(d, b.length)), + (b = b.substring(0, d)) + return i.nameToUrl(c(b, a && a.id, !0), e, !0) + }, + defined: function (b) { + return s(p, m(b, a, !1, !0).id) + }, + specified: function (b) { + b = m(b, a, !1, !0).id + return s(p, b) || s(k, b) + }, + }) + a || + (g.undef = function (b) { + x() + var c = m(b, a, !0), + e = j(k, b) + d(b) + delete p[b] + delete T[c.url] + delete aa[b] + U(A, function (a, c) { + a[0] === b && A.splice(c, 1) + }) + e && (e.events.defined && (aa[b] = e.events), y(b)) + }) + return g + }, + enable: function (a) { + j(k, a.id) && q(a).enable() + }, + completeLoad: function (a) { + var b, + c, + f = j(l.shim, a) || {}, + d = f.exports + for (x(); A.length; ) { + c = A.shift() + if (null === c[0]) { + c[0] = a + if (b) break + b = !0 + } else c[0] === a && (b = !0) + E(c) + } + c = j(k, a) + if (!b && !s(p, a) && c && !c.inited) { + if (l.enforceDefine && (!d || !ea(d))) + return g(a) + ? void 0 + : w( + C( + 'nodefine', + 'No define call for ' + a, + null, + [a] + ) + ) + E([a, f.deps || [], f.exportsFn]) + } + D() + }, + nameToUrl: function (a, b, c) { + var f, d, g + ;(f = j(l.pkgs, a)) && (a = f) + if ((f = j(ba, a))) return i.nameToUrl(f, b, c) + if (h.jsExtRegExp.test(a)) f = a + (b || '') + else { + f = l.paths + a = a.split('/') + for (d = a.length; 0 < d; d -= 1) + if (((g = a.slice(0, d).join('/')), (g = j(f, g)))) { + H(g) && (g = g[0]) + a.splice(0, d, g) + break + } + f = a.join('/') + f += b || (/^data\:|\?/.test(f) || c ? '' : '.js') + f = + ('/' === f.charAt(0) || f.match(/^[\w\+\.\-]+:/) + ? '' + : l.baseUrl) + f + } + return l.urlArgs + ? f + ((-1 === f.indexOf('?') ? '?' : '&') + l.urlArgs) + : f + }, + load: function (a, b) { + h.load(i, a, b) + }, + execCb: function (a, b, c, d) { + return b.apply(d, c) + }, + onScriptLoad: function (a) { + if ( + 'load' === a.type || + ka.test((a.currentTarget || a.srcElement).readyState) + ) + (P = null), (a = K(a)), i.completeLoad(a.id) + }, + onScriptError: function (a) { + var b = K(a) + if (!g(b.id)) + return w( + C('scripterror', 'Script error for: ' + b.id, a, [b.id]) + ) + }, + } + i.require = i.makeRequire() + return i + } + var h, + x, + y, + D, + K, + E, + P, + L, + q, + Q, + la = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/gm, + ma = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g, + R = /\.js$/, + ja = /^\.\// + x = Object.prototype + var M = x.toString, + ga = x.hasOwnProperty, + ia = Array.prototype.splice, + z = !!( + 'undefined' !== typeof window && + 'undefined' !== typeof navigator && + window.document + ), + fa = !z && 'undefined' !== typeof importScripts, + ka = + z && 'PLAYSTATION 3' === navigator.platform + ? /^complete$/ + : /^(complete|loaded)$/, + Z = + 'undefined' !== typeof opera && + '[object Opera]' === opera.toString(), + F = {}, + r = {}, + S = [], + O = !1 + if ('undefined' === typeof define) { + if ('undefined' !== typeof requirejs) { + if (G(requirejs)) return + r = requirejs + requirejs = void 0 + } + 'undefined' !== typeof require && + !G(require) && + ((r = require), (require = void 0)) + h = requirejs = function (b, c, d, g) { + var u, + m = '_' + !H(b) && + 'string' !== typeof b && + ((u = b), H(c) ? ((b = c), (c = d), (d = g)) : (b = [])) + u && u.context && (m = u.context) + ;(g = j(F, m)) || (g = F[m] = h.s.newContext(m)) + u && g.configure(u) + return g.require(b, c, d) + } + h.config = function (b) { + return h(b) + } + h.nextTick = + 'undefined' !== typeof setTimeout + ? function (b) { + setTimeout(b, 4) + } + : function (b) { + b() + } + require || (require = h) + h.version = '2.1.11' + h.jsExtRegExp = /^\/|:|\?|\.js$/ + h.isBrowser = z + x = h.s = { contexts: F, newContext: ha } + h({}) + v(['toUrl', 'undef', 'defined', 'specified'], function (b) { + h[b] = function () { + var c = F._ + return c.require[b].apply(c, arguments) + } + }) + if ( + z && + ((y = x.head = document.getElementsByTagName('head')[0]), + (D = document.getElementsByTagName('base')[0])) + ) + y = x.head = D.parentNode + h.onError = da + h.createNode = function (b) { + var c = b.xhtml + ? document.createElementNS( + 'http://www.w3.org/1999/xhtml', + 'html:script' + ) + : document.createElement('script') + c.type = b.scriptType || 'text/javascript' + c.charset = 'utf-8' + c.async = !0 + return c + } + h.load = function (b, c, d) { + var g = (b && b.config) || {} + if (z) + return ( + (g = h.createNode(g, c, d)), + g.setAttribute('data-requirecontext', b.contextName), + g.setAttribute('data-requiremodule', c), + g.attachEvent && + !( + g.attachEvent.toString && + 0 > g.attachEvent.toString().indexOf('[native code') + ) && + !Z + ? ((O = !0), + g.attachEvent('onreadystatechange', b.onScriptLoad)) + : (g.addEventListener('load', b.onScriptLoad, !1), + g.addEventListener('error', b.onScriptError, !1)), + (g.src = d), + (L = g), + D ? y.insertBefore(g, D) : y.appendChild(g), + (L = null), + g + ) + if (fa) + try { + importScripts(d), b.completeLoad(c) + } catch (j) { + b.onError( + C( + 'importscripts', + 'importScripts failed for ' + c + ' at ' + d, + j, + [c] + ) + ) + } + } + z && + !r.skipDataMain && + U(document.getElementsByTagName('script'), function (b) { + y || (y = b.parentNode) + if ((K = b.getAttribute('data-main'))) + return ( + (q = K), + r.baseUrl || + ((E = q.split('/')), + (q = E.pop()), + (Q = E.length ? E.join('/') + '/' : './'), + (r.baseUrl = Q)), + (q = q.replace(R, '')), + h.jsExtRegExp.test(q) && (q = K), + (r.deps = r.deps ? r.deps.concat(q) : [q]), + !0 + ) + }) + define = function (b, c, d) { + var g, h + 'string' !== typeof b && ((d = c), (c = b), (b = null)) + H(c) || ((d = c), (c = null)) + !c && + G(d) && + ((c = []), + d.length && + (d + .toString() + .replace(la, '') + .replace(ma, function (b, d) { + c.push(d) + }), + (c = ( + 1 === d.length + ? ['require'] + : ['require', 'exports', 'module'] + ).concat(c)))) + if (O) { + if (!(g = L)) + (P && 'interactive' === P.readyState) || + U( + document.getElementsByTagName('script'), + function (b) { + if ('interactive' === b.readyState) + return (P = b) + } + ), + (g = P) + g && + (b || (b = g.getAttribute('data-requiremodule')), + (h = F[g.getAttribute('data-requirecontext')])) + } + ;(h ? h.defQueue : S).push([b, c, d]) + } + define.amd = { jQuery: !0 } + h.exec = function (b) { + return eval(b) + } + h(r) + } +})(this) diff --git a/experiments/twgl-tunnel/dist/twgl-full.min.js b/experiments/twgl-tunnel/dist/twgl-full.min.js index a4dacca..3dd86e0 100644 --- a/experiments/twgl-tunnel/dist/twgl-full.min.js +++ b/experiments/twgl-tunnel/dist/twgl-full.min.js @@ -3,4 +3,6272 @@ * Available via the MIT license. * see: http://github.com/greggman/twgl.js for details */ -!function(t,r){"object"==typeof exports&&"object"==typeof module?module.exports=r():"function"==typeof define&&define.amd?define([],r):"object"==typeof exports?exports.twgl=r():t.twgl=r()}("undefined"!=typeof self?self:this,(function(){return function(t){var r={};function e(n){if(r[n])return r[n].exports;var o=r[n]={i:n,l:!1,exports:{}};return t[n].call(o.exports,o,o.exports,e),o.l=!0,o.exports}return e.m=t,e.c=r,e.d=function(t,r,n){e.o(t,r)||Object.defineProperty(t,r,{enumerable:!0,get:n})},e.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},e.t=function(t,r){if(1&r&&(t=e(t)),8&r)return t;if(4&r&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(e.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&r&&"string"!=typeof t)for(var o in t)e.d(n,o,function(r){return t[r]}.bind(null,o));return n},e.n=function(t){var r=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(r,"a",r),r},e.o=function(t,r){return Object.prototype.hasOwnProperty.call(t,r)},e.p="",e(e.s=8)}([function(t,r,e){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}r.__esModule=!0,r.copyExistingProperties=function(t,r){Object.keys(r).forEach((function(e){r.hasOwnProperty(e)&&t.hasOwnProperty(e)&&(r[e]=t[e])}))},r.copyNamedProperties=function(t,r,e){t.forEach((function(t){var n=r[t];void 0!==n&&(e[t]=n)}))},r.error=function(){var t;(t=console).error.apply(t,arguments)},r.isBuffer=function(t,r){return"undefined"!=typeof WebGLBuffer&&u(r,"WebGLBuffer")},r.isRenderbuffer=function(t,r){return"undefined"!=typeof WebGLRenderbuffer&&u(r,"WebGLRenderbuffer")},r.isSampler=function(t,r){return"undefined"!=typeof WebGLSampler&&u(r,"WebGLSampler")},r.isShader=function(t,r){return"undefined"!=typeof WebGLShader&&u(r,"WebGLShader")},r.isTexture=function(t,r){return"undefined"!=typeof WebGLTexture&&u(r,"WebGLTexture")},r.warn=function(){var t;(t=console).warn.apply(t,arguments)};var o=new Map;function u(t,r){if(!t||"object"!==n(t))return!1;var e=o.get(r);e||(e=new WeakMap,o.set(r,e));var u=e.get(t);if(void 0===u){var i=Object.prototype.toString.call(t);u=i.substring(8,i.length-1)===r,e.set(t,u)}return u}},function(t,r,e){"use strict";r.__esModule=!0,r.getGLTypeForTypedArray=function(t){if(t instanceof Int8Array)return n;if(t instanceof Uint8Array)return o;if(t instanceof Uint8ClampedArray)return o;if(t instanceof Int16Array)return u;if(t instanceof Uint16Array)return i;if(t instanceof Int32Array)return a;if(t instanceof Uint32Array)return f;if(t instanceof Float32Array)return c;throw new Error("unsupported typed array type")},r.getGLTypeForTypedArrayType=function(t){if(t===Int8Array)return n;if(t===Uint8Array)return o;if(t===Uint8ClampedArray)return o;if(t===Int16Array)return u;if(t===Uint16Array)return i;if(t===Int32Array)return a;if(t===Uint32Array)return f;if(t===Float32Array)return c;throw new Error("unsupported typed array type")},r.getTypedArrayTypeForGLType=function(t){var r=l[t];if(!r)throw new Error("unknown gl type");return r},r.isArrayBuffer=void 0;var n=5120,o=5121,u=5122,i=5123,a=5124,f=5125,c=5126,l={},s=l;s[n]=Int8Array,s[5121]=Uint8Array,s[5122]=Int16Array,s[5123]=Uint16Array,s[a]=Int32Array,s[5125]=Uint32Array,s[5126]=Float32Array,s[32819]=Uint16Array,s[32820]=Uint16Array,s[33635]=Uint16Array,s[5131]=Uint16Array,s[33640]=Uint32Array,s[35899]=Uint32Array,s[35902]=Uint32Array,s[36269]=Uint32Array,s[34042]=Uint32Array;var v="undefined"!=typeof SharedArrayBuffer?function(t){return t&&t.buffer&&(t.buffer instanceof ArrayBuffer||t.buffer instanceof SharedArrayBuffer)}:function(t){return t&&t.buffer&&t.buffer instanceof ArrayBuffer};r.isArrayBuffer=v},function(t,r,e){"use strict";r.__esModule=!0,r.add=function(t,r,e){return(e=e||new n(3))[0]=t[0]+r[0],e[1]=t[1]+r[1],e[2]=t[2]+r[2],e},r.copy=function(t,r){return(r=r||new n(3))[0]=t[0],r[1]=t[1],r[2]=t[2],r},r.create=function(t,r,e){var o=new n(3);t&&(o[0]=t);r&&(o[1]=r);e&&(o[2]=e);return o},r.cross=function(t,r,e){e=e||new n(3);var o=t[2]*r[0]-t[0]*r[2],u=t[0]*r[1]-t[1]*r[0];return e[0]=t[1]*r[2]-t[2]*r[1],e[1]=o,e[2]=u,e},r.distance=function(t,r){var e=t[0]-r[0],n=t[1]-r[1],o=t[2]-r[2];return Math.sqrt(e*e+n*n+o*o)},r.distanceSq=function(t,r){var e=t[0]-r[0],n=t[1]-r[1],o=t[2]-r[2];return e*e+n*n+o*o},r.divScalar=function(t,r,e){return(e=e||new n(3))[0]=t[0]/r,e[1]=t[1]/r,e[2]=t[2]/r,e},r.divide=function(t,r,e){return(e=e||new n(3))[0]=t[0]/r[0],e[1]=t[1]/r[1],e[2]=t[2]/r[2],e},r.dot=function(t,r){return t[0]*r[0]+t[1]*r[1]+t[2]*r[2]},r.length=function(t){return Math.sqrt(t[0]*t[0]+t[1]*t[1]+t[2]*t[2])},r.lengthSq=function(t){return t[0]*t[0]+t[1]*t[1]+t[2]*t[2]},r.lerp=function(t,r,e,o){return(o=o||new n(3))[0]=t[0]+e*(r[0]-t[0]),o[1]=t[1]+e*(r[1]-t[1]),o[2]=t[2]+e*(r[2]-t[2]),o},r.lerpV=function(t,r,e,o){return(o=o||new n(3))[0]=t[0]+e[0]*(r[0]-t[0]),o[1]=t[1]+e[1]*(r[1]-t[1]),o[2]=t[2]+e[2]*(r[2]-t[2]),o},r.max=function(t,r,e){return(e=e||new n(3))[0]=Math.max(t[0],r[0]),e[1]=Math.max(t[1],r[1]),e[2]=Math.max(t[2],r[2]),e},r.min=function(t,r,e){return(e=e||new n(3))[0]=Math.min(t[0],r[0]),e[1]=Math.min(t[1],r[1]),e[2]=Math.min(t[2],r[2]),e},r.mulScalar=function(t,r,e){return(e=e||new n(3))[0]=t[0]*r,e[1]=t[1]*r,e[2]=t[2]*r,e},r.multiply=function(t,r,e){return(e=e||new n(3))[0]=t[0]*r[0],e[1]=t[1]*r[1],e[2]=t[2]*r[2],e},r.negate=function(t,r){return(r=r||new n(3))[0]=-t[0],r[1]=-t[1],r[2]=-t[2],r},r.normalize=function(t,r){r=r||new n(3);var e=t[0]*t[0]+t[1]*t[1]+t[2]*t[2],o=Math.sqrt(e);o>1e-5?(r[0]=t[0]/o,r[1]=t[1]/o,r[2]=t[2]/o):(r[0]=0,r[1]=0,r[2]=0);return r},r.setDefaultType=function(t){var r=n;return n=t,r},r.subtract=function(t,r,e){return(e=e||new n(3))[0]=t[0]-r[0],e[1]=t[1]-r[1],e[2]=t[2]-r[2],e};var n=Float32Array},function(t,r,e){"use strict";r.__esModule=!0,r.glEnumToString=void 0,r.isWebGL1=function(t){return!t.texStorage2D},r.isWebGL2=function(t){return!!t.texStorage2D};var n,o,u=(n={},o={},function(t,r){return function(t){var r=t.constructor.name;if(!n[r]){for(var e in t)if("number"==typeof t[e]){var u=o[t[e]];o[t[e]]=u?"".concat(u," | ").concat(e):e}n[r]=!0}}(t),o[r]||("number"==typeof r?"0x".concat(r.toString(16)):r)});r.glEnumToString=u},function(t,r,e){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}r.__esModule=!0,r.bindTransformFeedbackInfo=dt,r.bindUniformBlock=xt,r.createAttributeSetters=Et,r.createProgram=rt,r.createProgramAsync=void 0,r.createProgramFromScripts=function(t,r,e,n,o){var u,i=Z(e,n,o),a=[],f=m(r);try{for(f.s();!(u=f.n()).done;){var c=u.value,l=F(c);if(!l)return K(i,"unknown script element: ".concat(c));a.push(l.text)}}catch(t){f.e(t)}finally{f.f()}return rt(t,a,i)},r.createProgramFromSources=lt,r.createProgramInfo=_t,r.createProgramInfoAsync=void 0,r.createProgramInfoFromProgram=St,r.createProgramInfos=Pt,r.createProgramInfosAsync=void 0,r.createPrograms=gt,r.createProgramsAsync=void 0,r.createTransformFeedback=function(t,r,e){var n=t.createTransformFeedback();return t.bindTransformFeedback(36386,n),t.useProgram(r.program),dt(t,r,e),t.bindTransformFeedback(36386,null),n},r.createTransformFeedbackInfo=mt,r.createUniformBlockInfo=function(t,r,e){return wt(t,r.program,r.uniformBlockSpec,e)},r.createUniformBlockInfoFromProgram=wt,r.createUniformBlockSpecFromProgram=pt,r.createUniformSetters=bt,r.setAttributes=At,r.setBlockUniforms=function(t,r){var e=t.setters;for(var n in r){var o=e[n];if(o){var u=r[n];o(u)}}},r.setBuffersAndAttributes=function(t,r,e){e.vertexArrayObject?t.bindVertexArray(e.vertexArrayObject):(At(r.attribSetters||r,e.attribs),e.indices&&t.bindBuffer(34963,e.indices))},r.setUniformBlock=function(t,r,e){xt(t,r,e)&&t.bufferData(E,e.array,35048)},r.setUniforms=jt,r.setUniformsAndBindTextures=void 0;var o=a(e(3)),u=a(e(0));function i(t){if("function"!=typeof WeakMap)return null;var r=new WeakMap,e=new WeakMap;return(i=function(t){return t?e:r})(t)}function a(t,r){if(!r&&t&&t.__esModule)return t;if(null===t||"object"!==n(t)&&"function"!=typeof t)return{default:t};var e=i(r);if(e&&e.has(t))return e.get(t);var o={},u=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in t)if("default"!==a&&Object.prototype.hasOwnProperty.call(t,a)){var f=u?Object.getOwnPropertyDescriptor(t,a):null;f&&(f.get||f.set)?Object.defineProperty(o,a,f):o[a]=t[a]}return o.default=t,e&&e.set(t,o),o}function f(){f=function(){return t};var t={},r=Object.prototype,e=r.hasOwnProperty,o="function"==typeof Symbol?Symbol:{},u=o.iterator||"@@iterator",i=o.asyncIterator||"@@asyncIterator",a=o.toStringTag||"@@toStringTag";function c(t,r,e){return Object.defineProperty(t,r,{value:e,enumerable:!0,configurable:!0,writable:!0}),t[r]}try{c({},"")}catch(t){c=function(t,r,e){return t[r]=e}}function l(t,r,e,n){var o=r&&r.prototype instanceof y?r:y,u=Object.create(o.prototype),i=new A(n||[]);return u._invoke=function(t,r,e){var n="suspendedStart";return function(o,u){if("executing"===n)throw new Error("Generator is already running");if("completed"===n){if("throw"===o)throw u;return M()}for(e.method=o,e.arg=u;;){var i=e.delegate;if(i){var a=j(i,e);if(a){if(a===v)continue;return a}}if("next"===e.method)e.sent=e._sent=e.arg;else if("throw"===e.method){if("suspendedStart"===n)throw n="completed",e.arg;e.dispatchException(e.arg)}else"return"===e.method&&e.abrupt("return",e.arg);n="executing";var f=s(t,r,e);if("normal"===f.type){if(n=e.done?"completed":"suspendedYield",f.arg===v)continue;return{value:f.arg,done:e.done}}"throw"===f.type&&(n="completed",e.method="throw",e.arg=f.arg)}}}(t,e,i),u}function s(t,r,e){try{return{type:"normal",arg:t.call(r,e)}}catch(t){return{type:"throw",arg:t}}}t.wrap=l;var v={};function y(){}function b(){}function m(){}var d={};c(d,u,(function(){return this}));var p=Object.getPrototypeOf,h=p&&p(p(S([])));h&&h!==r&&e.call(h,u)&&(d=h);var w=m.prototype=y.prototype=Object.create(d);function x(t){["next","throw","return"].forEach((function(r){c(t,r,(function(t){return this._invoke(r,t)}))}))}function F(t,r){function o(u,i,a,f){var c=s(t[u],t,i);if("throw"!==c.type){var l=c.arg,v=l.value;return v&&"object"==n(v)&&e.call(v,"__await")?r.resolve(v.__await).then((function(t){o("next",t,a,f)}),(function(t){o("throw",t,a,f)})):r.resolve(v).then((function(t){l.value=t,a(l)}),(function(t){return o("throw",t,a,f)}))}f(c.arg)}var u;this._invoke=function(t,e){function n(){return new r((function(r,n){o(t,e,r,n)}))}return u=u?u.then(n,n):n()}}function j(t,r){var e=t.iterator[r.method];if(void 0===e){if(r.delegate=null,"throw"===r.method){if(t.iterator.return&&(r.method="return",r.arg=void 0,j(t,r),"throw"===r.method))return v;r.method="throw",r.arg=new TypeError("The iterator does not provide a 'throw' method")}return v}var n=s(e,t.iterator,r.arg);if("throw"===n.type)return r.method="throw",r.arg=n.arg,r.delegate=null,v;var o=n.arg;return o?o.done?(r[t.resultName]=o.value,r.next=t.nextLoc,"return"!==r.method&&(r.method="next",r.arg=void 0),r.delegate=null,v):o:(r.method="throw",r.arg=new TypeError("iterator result is not an object"),r.delegate=null,v)}function O(t){var r={tryLoc:t[0]};1 in t&&(r.catchLoc=t[1]),2 in t&&(r.finallyLoc=t[2],r.afterLoc=t[3]),this.tryEntries.push(r)}function E(t){var r=t.completion||{};r.type="normal",delete r.arg,t.completion=r}function A(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(O,this),this.reset(!0)}function S(t){if(t){var r=t[u];if(r)return r.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var n=-1,o=function r(){for(;++n=0;--o){var u=this.tryEntries[o],i=u.completion;if("root"===u.tryLoc)return n("end");if(u.tryLoc<=this.prev){var a=e.call(u,"catchLoc"),f=e.call(u,"finallyLoc");if(a&&f){if(this.prev=0;--n){var o=this.tryEntries[n];if(o.tryLoc<=this.prev&&e.call(o,"finallyLoc")&&this.prev=0;--r){var e=this.tryEntries[r];if(e.finallyLoc===t)return this.complete(e.completion,e.afterLoc),E(e),v}},catch:function(t){for(var r=this.tryEntries.length-1;r>=0;--r){var e=this.tryEntries[r];if(e.tryLoc===t){var n=e.completion;if("throw"===n.type){var o=n.arg;E(e)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(t,r,e){return this.delegate={iterator:S(t),resultName:r,nextLoc:e},"next"===this.method&&(this.arg=void 0),v}},t}function c(t,r){var e=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(t,r).enumerable}))),e.push.apply(e,n)}return e}function l(t){for(var r=1;r=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var u,i=!0,a=!1;return{s:function(){e=e.call(t)},n:function(){var t=e.next();return i=t.done,t},e:function(t){a=!0,u=t},f:function(){try{i||null==e.return||e.return()}finally{if(a)throw u}}}}function d(t){return function(t){if(Array.isArray(t))return h(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||p(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function p(t,r){if(t){if("string"==typeof t)return h(t,r);var e=Object.prototype.toString.call(t).slice(8,-1);return"Object"===e&&t.constructor&&(e=t.constructor.name),"Map"===e||"Set"===e?Array.from(t):"Arguments"===e||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(e)?h(t,r):void 0}}function h(t,r){(null==r||r>t.length)&&(r=t.length);for(var e=0,n=new Array(r);e1&&void 0!==arguments[1]?arguments[1]:"",e=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,n=d(r.matchAll(V)),o=new Map(n.map((function(t,e){var o=parseInt(t[1]),u=n[e+1],i=u?u.index:r.length;return[o-1,r.substring(t.index,i)]})));return t.split("\n").map((function(t,r){var n=o.get(r);return"".concat(r+1+e,": ").concat(t).concat(n?"\n\n^^^ ".concat(n):"")})).join("\n")}(f,u,a),"\nError compiling ").concat(o.glEnumToString(t,r),": ").concat(u);return n(c),c}return""}function Z(t,r,e){var n,o,u;if("function"==typeof r&&(e=r,r=void 0),"function"==typeof t)e=t,t=void 0;else if(t&&!Array.isArray(t)){var i=t;e=i.errorCallback,t=i.attribLocations,n=i.transformFeedbackVaryings,o=i.transformFeedbackMode,u=i.callback}var a=e||w,f=[],c={errorCallback:function(t){f.push(t);for(var r=arguments.length,e=new Array(r>1?r-1:0),n=1;n0&&void 0!==arguments[0]?arguments[0]:0;return new Promise((function(r){return setTimeout(r,t)}))};function tt(t,r,e){for(var n,o=t.createProgram(),u=Z(e),i=u.attribLocations,a=u.transformFeedbackVaryings,f=u.transformFeedbackMode,c=0;c=0?35632:n.indexOf("vert")>=0?35633:void 0)||y),l=t.createShader(y),t.shaderSource(l,q(v).shaderSource),t.compileShader(l),t.attachShader(o,l)}}Object.entries(i).forEach((function(r){var e=b(r,2),n=e[0],u=e[1];return t.bindAttribLocation(o,u,n)}));var m=a;return m&&(m.attribs&&(m=m.attribs),Array.isArray(m)||(m=Object.keys(m)),t.transformFeedbackVaryings(o,m,f||35981)),t.linkProgram(o),o}function rt(t,r,e,n,o){var u=Z(e,n,o),i=new Set(r),a=tt(t,r,u);function f(t,r){var e=ct(t,r,u.errorCallback);return e&&function(t,r,e){var n,o=m(t.getAttachedShaders(r));try{for(o.s();!(n=o.n()).done;){var u=n.value;e.has(u)&&t.deleteShader(u)}}catch(t){o.e(t)}finally{o.f()}t.deleteProgram(r)}(t,r,i),e}if(!u.callback)return f(t,a)?void 0:a;ut(t,a).then((function(){var r=f(t,a);u.callback(r,r?void 0:a)}))}function et(t){return function(r,e){for(var n=arguments.length,o=new Array(n>2?n-2:0),u=2;u="0"&&o<="9",l=c?parseInt(f):f;if(c&&(a+=u[i++]),i===u.length){e[l]=r;break}var s=u[i++],v="["===s,y=e[l]||(v?[]:{});e[l]=y,e=y,n[a]=n[a]||function(t){return function(r){Ft(t,r)}}(y),a+=s}}function bt(t,r){var e=0;function n(r,n,o){var u,i=n.name.endsWith("[0]"),a=n.type,f=R[a];if(!f)throw new Error("unknown type: 0x".concat(a.toString(16)));if(f.bindPoint){var c=e;e+=n.size,u=i?f.arraySetter(t,a,c,o,n.size):f.setter(t,a,c,o,n.size)}else u=f.arraySetter&&i?f.arraySetter(t,o):f.setter(t,o);return u.location=o,u}for(var o={},u={},i=t.getProgramParameter(r,35718),a=0;a2&&void 0!==arguments[2]?arguments[2]:{},n=new Set,o=Object.fromEntries(Object.entries(r).map((function(r){var o=b(r,2),u=o[0],i=o[1],a=l({},e),f=Array.isArray(i)?i:i.shaders;return Array.isArray(i)||Object.assign(a,i),f.forEach(n.add,n),[u,tt(t,f,a)]})));if(!e.callback){var u=Tt(t,o,r,n,e);return u?void 0:o}at(t,o).then((function(){var u=Tt(t,o,r,n,e);e.callback(u,u?void 0:o)}))}function Pt(t,r,e){function n(t,r){return Object.fromEntries(Object.entries(r).map((function(r){var e=b(r,2),n=e[0],o=e[1];return[n,St(t,o)]})))}var o=(e=Z(e)).callback;o&&(e.callback=function(r,e){o(r,r?void 0:n(t,e))});var u=gt(t,r,e);if(!o&&u)return n(t,u)}var Rt=et(gt);r.createProgramsAsync=Rt;var zt=et(Pt);r.createProgramInfosAsync=zt},function(t,r,e){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}r.__esModule=!0,r.axisRotate=function(t,r,e,n){n=n||new c(16);var o=r[0],u=r[1],i=r[2],a=Math.sqrt(o*o+u*u+i*i),f=(o/=a)*o,l=(u/=a)*u,s=(i/=a)*i,v=Math.cos(e),y=Math.sin(e),b=1-v,m=f+(1-f)*v,d=o*u*b+i*y,p=o*i*b-u*y,h=o*u*b-i*y,w=l+(1-l)*v,x=u*i*b+o*y,F=o*i*b+u*y,j=u*i*b-o*y,O=s+(1-s)*v,E=t[0],A=t[1],S=t[2],M=t[3],_=t[4],T=t[5],g=t[6],P=t[7],R=t[8],z=t[9],k=t[10],U=t[11];n[0]=m*E+d*_+p*R,n[1]=m*A+d*T+p*z,n[2]=m*S+d*g+p*k,n[3]=m*M+d*P+p*U,n[4]=h*E+w*_+x*R,n[5]=h*A+w*T+x*z,n[6]=h*S+w*g+x*k,n[7]=h*M+w*P+x*U,n[8]=F*E+j*_+O*R,n[9]=F*A+j*T+O*z,n[10]=F*S+j*g+O*k,n[11]=F*M+j*P+O*U,t!==n&&(n[12]=t[12],n[13]=t[13],n[14]=t[14],n[15]=t[15]);return n},r.axisRotation=function(t,r,e){e=e||new c(16);var n=t[0],o=t[1],u=t[2],i=Math.sqrt(n*n+o*o+u*u),a=(n/=i)*n,f=(o/=i)*o,l=(u/=i)*u,s=Math.cos(r),v=Math.sin(r),y=1-s;return e[0]=a+(1-a)*s,e[1]=n*o*y+u*v,e[2]=n*u*y-o*v,e[3]=0,e[4]=n*o*y-u*v,e[5]=f+(1-f)*s,e[6]=o*u*y+n*v,e[7]=0,e[8]=n*u*y+o*v,e[9]=o*u*y-n*v,e[10]=l+(1-l)*s,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,e},r.copy=l,r.create=function(){return new c(16).fill(0)},r.frustum=function(t,r,e,n,o,u,i){i=i||new c(16);var a=r-t,f=n-e,l=o-u;return i[0]=2*o/a,i[1]=0,i[2]=0,i[3]=0,i[4]=0,i[5]=2*o/f,i[6]=0,i[7]=0,i[8]=(t+r)/a,i[9]=(n+e)/f,i[10]=u/l,i[11]=-1,i[12]=0,i[13]=0,i[14]=o*u/l,i[15]=0,i},r.getAxis=function(t,r,e){e=e||o.create();var n=4*r;return e[0]=t[n+0],e[1]=t[n+1],e[2]=t[n+2],e},r.getTranslation=function(t,r){return(r=r||o.create())[0]=t[12],r[1]=t[13],r[2]=t[14],r},r.identity=s,r.inverse=v,r.lookAt=function(t,r,e,n){return n=n||new c(16),i=i||o.create(),a=a||o.create(),f=f||o.create(),o.normalize(o.subtract(t,r,f),f),o.normalize(o.cross(e,f,i),i),o.normalize(o.cross(f,i,a),a),n[0]=i[0],n[1]=i[1],n[2]=i[2],n[3]=0,n[4]=a[0],n[5]=a[1],n[6]=a[2],n[7]=0,n[8]=f[0],n[9]=f[1],n[10]=f[2],n[11]=0,n[12]=t[0],n[13]=t[1],n[14]=t[2],n[15]=1,n},r.multiply=function(t,r,e){e=e||new c(16);var n=t[0],o=t[1],u=t[2],i=t[3],a=t[4],f=t[5],l=t[6],s=t[7],v=t[8],y=t[9],b=t[10],m=t[11],d=t[12],p=t[13],h=t[14],w=t[15],x=r[0],F=r[1],j=r[2],O=r[3],E=r[4],A=r[5],S=r[6],M=r[7],_=r[8],T=r[9],g=r[10],P=r[11],R=r[12],z=r[13],k=r[14],U=r[15];return e[0]=n*x+a*F+v*j+d*O,e[1]=o*x+f*F+y*j+p*O,e[2]=u*x+l*F+b*j+h*O,e[3]=i*x+s*F+m*j+w*O,e[4]=n*E+a*A+v*S+d*M,e[5]=o*E+f*A+y*S+p*M,e[6]=u*E+l*A+b*S+h*M,e[7]=i*E+s*A+m*S+w*M,e[8]=n*_+a*T+v*g+d*P,e[9]=o*_+f*T+y*g+p*P,e[10]=u*_+l*T+b*g+h*P,e[11]=i*_+s*T+m*g+w*P,e[12]=n*R+a*z+v*k+d*U,e[13]=o*R+f*z+y*k+p*U,e[14]=u*R+l*z+b*k+h*U,e[15]=i*R+s*z+m*k+w*U,e},r.negate=function(t,r){return(r=r||new c(16))[0]=-t[0],r[1]=-t[1],r[2]=-t[2],r[3]=-t[3],r[4]=-t[4],r[5]=-t[5],r[6]=-t[6],r[7]=-t[7],r[8]=-t[8],r[9]=-t[9],r[10]=-t[10],r[11]=-t[11],r[12]=-t[12],r[13]=-t[13],r[14]=-t[14],r[15]=-t[15],r},r.ortho=function(t,r,e,n,o,u,i){return(i=i||new c(16))[0]=2/(r-t),i[1]=0,i[2]=0,i[3]=0,i[4]=0,i[5]=2/(n-e),i[6]=0,i[7]=0,i[8]=0,i[9]=0,i[10]=2/(o-u),i[11]=0,i[12]=(r+t)/(t-r),i[13]=(n+e)/(e-n),i[14]=(u+o)/(o-u),i[15]=1,i},r.perspective=function(t,r,e,n,o){o=o||new c(16);var u=Math.tan(.5*Math.PI-.5*t),i=1/(e-n);return o[0]=u/r,o[1]=0,o[2]=0,o[3]=0,o[4]=0,o[5]=u,o[6]=0,o[7]=0,o[8]=0,o[9]=0,o[10]=(e+n)*i,o[11]=-1,o[12]=0,o[13]=0,o[14]=e*n*i*2,o[15]=0,o},r.rotateX=function(t,r,e){e=e||new c(16);var n=t[4],o=t[5],u=t[6],i=t[7],a=t[8],f=t[9],l=t[10],s=t[11],v=Math.cos(r),y=Math.sin(r);e[4]=v*n+y*a,e[5]=v*o+y*f,e[6]=v*u+y*l,e[7]=v*i+y*s,e[8]=v*a-y*n,e[9]=v*f-y*o,e[10]=v*l-y*u,e[11]=v*s-y*i,t!==e&&(e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15]);return e},r.rotateY=function(t,r,e){e=e||new c(16);var n=t[0],o=t[1],u=t[2],i=t[3],a=t[8],f=t[9],l=t[10],s=t[11],v=Math.cos(r),y=Math.sin(r);e[0]=v*n-y*a,e[1]=v*o-y*f,e[2]=v*u-y*l,e[3]=v*i-y*s,e[8]=v*a+y*n,e[9]=v*f+y*o,e[10]=v*l+y*u,e[11]=v*s+y*i,t!==e&&(e[4]=t[4],e[5]=t[5],e[6]=t[6],e[7]=t[7],e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15]);return e},r.rotateZ=function(t,r,e){e=e||new c(16);var n=t[0],o=t[1],u=t[2],i=t[3],a=t[4],f=t[5],l=t[6],s=t[7],v=Math.cos(r),y=Math.sin(r);e[0]=v*n+y*a,e[1]=v*o+y*f,e[2]=v*u+y*l,e[3]=v*i+y*s,e[4]=v*a-y*n,e[5]=v*f-y*o,e[6]=v*l-y*u,e[7]=v*s-y*i,t!==e&&(e[8]=t[8],e[9]=t[9],e[10]=t[10],e[11]=t[11],e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15]);return e},r.rotationX=function(t,r){r=r||new c(16);var e=Math.cos(t),n=Math.sin(t);return r[0]=1,r[1]=0,r[2]=0,r[3]=0,r[4]=0,r[5]=e,r[6]=n,r[7]=0,r[8]=0,r[9]=-n,r[10]=e,r[11]=0,r[12]=0,r[13]=0,r[14]=0,r[15]=1,r},r.rotationY=function(t,r){r=r||new c(16);var e=Math.cos(t),n=Math.sin(t);return r[0]=e,r[1]=0,r[2]=-n,r[3]=0,r[4]=0,r[5]=1,r[6]=0,r[7]=0,r[8]=n,r[9]=0,r[10]=e,r[11]=0,r[12]=0,r[13]=0,r[14]=0,r[15]=1,r},r.rotationZ=function(t,r){r=r||new c(16);var e=Math.cos(t),n=Math.sin(t);return r[0]=e,r[1]=n,r[2]=0,r[3]=0,r[4]=-n,r[5]=e,r[6]=0,r[7]=0,r[8]=0,r[9]=0,r[10]=1,r[11]=0,r[12]=0,r[13]=0,r[14]=0,r[15]=1,r},r.scale=function(t,r,e){e=e||new c(16);var n=r[0],o=r[1],u=r[2];e[0]=n*t[0],e[1]=n*t[1],e[2]=n*t[2],e[3]=n*t[3],e[4]=o*t[4],e[5]=o*t[5],e[6]=o*t[6],e[7]=o*t[7],e[8]=u*t[8],e[9]=u*t[9],e[10]=u*t[10],e[11]=u*t[11],t!==e&&(e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15]);return e},r.scaling=function(t,r){return(r=r||new c(16))[0]=t[0],r[1]=0,r[2]=0,r[3]=0,r[4]=0,r[5]=t[1],r[6]=0,r[7]=0,r[8]=0,r[9]=0,r[10]=t[2],r[11]=0,r[12]=0,r[13]=0,r[14]=0,r[15]=1,r},r.setAxis=function(t,r,e,n){n!==t&&(n=l(t,n));var o=4*e;return n[o+0]=r[0],n[o+1]=r[1],n[o+2]=r[2],n},r.setDefaultType=function(t){var r=c;return c=t,r},r.setTranslation=function(t,r,e){e=e||s(),t!==e&&(e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],e[4]=t[4],e[5]=t[5],e[6]=t[6],e[7]=t[7],e[8]=t[8],e[9]=t[9],e[10]=t[10],e[11]=t[11]);return e[12]=r[0],e[13]=r[1],e[14]=r[2],e[15]=1,e},r.transformDirection=function(t,r,e){e=e||o.create();var n=r[0],u=r[1],i=r[2];return e[0]=n*t[0]+u*t[4]+i*t[8],e[1]=n*t[1]+u*t[5]+i*t[9],e[2]=n*t[2]+u*t[6]+i*t[10],e},r.transformNormal=function(t,r,e){e=e||o.create();var n=v(t),u=r[0],i=r[1],a=r[2];return e[0]=u*n[0]+i*n[1]+a*n[2],e[1]=u*n[4]+i*n[5]+a*n[6],e[2]=u*n[8]+i*n[9]+a*n[10],e},r.transformPoint=function(t,r,e){e=e||o.create();var n=r[0],u=r[1],i=r[2],a=n*t[3]+u*t[7]+i*t[11]+t[15];return e[0]=(n*t[0]+u*t[4]+i*t[8]+t[12])/a,e[1]=(n*t[1]+u*t[5]+i*t[9]+t[13])/a,e[2]=(n*t[2]+u*t[6]+i*t[10]+t[14])/a,e},r.translate=function(t,r,e){e=e||new c(16);var n=r[0],o=r[1],u=r[2],i=t[0],a=t[1],f=t[2],l=t[3],s=t[4],v=t[5],y=t[6],b=t[7],m=t[8],d=t[9],p=t[10],h=t[11],w=t[12],x=t[13],F=t[14],j=t[15];t!==e&&(e[0]=i,e[1]=a,e[2]=f,e[3]=l,e[4]=s,e[5]=v,e[6]=y,e[7]=b,e[8]=m,e[9]=d,e[10]=p,e[11]=h);return e[12]=i*n+s*o+m*u+w,e[13]=a*n+v*o+d*u+x,e[14]=f*n+y*o+p*u+F,e[15]=l*n+b*o+h*u+j,e},r.translation=function(t,r){return(r=r||new c(16))[0]=1,r[1]=0,r[2]=0,r[3]=0,r[4]=0,r[5]=1,r[6]=0,r[7]=0,r[8]=0,r[9]=0,r[10]=1,r[11]=0,r[12]=t[0],r[13]=t[1],r[14]=t[2],r[15]=1,r},r.transpose=function(t,r){if((r=r||new c(16))===t){var e;return e=t[1],t[1]=t[4],t[4]=e,e=t[2],t[2]=t[8],t[8]=e,e=t[3],t[3]=t[12],t[12]=e,e=t[6],t[6]=t[9],t[9]=e,e=t[7],t[7]=t[13],t[13]=e,e=t[11],t[11]=t[14],t[14]=e,r}var n=t[0],o=t[1],u=t[2],i=t[3],a=t[4],f=t[5],l=t[6],s=t[7],v=t[8],y=t[9],b=t[10],m=t[11],d=t[12],p=t[13],h=t[14],w=t[15];return r[0]=n,r[1]=a,r[2]=v,r[3]=d,r[4]=o,r[5]=f,r[6]=y,r[7]=p,r[8]=u,r[9]=l,r[10]=b,r[11]=h,r[12]=i,r[13]=s,r[14]=m,r[15]=w,r};var o=function(t,r){if(!r&&t&&t.__esModule)return t;if(null===t||"object"!==n(t)&&"function"!=typeof t)return{default:t};var e=u(r);if(e&&e.has(t))return e.get(t);var o={},i=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in t)if("default"!==a&&Object.prototype.hasOwnProperty.call(t,a)){var f=i?Object.getOwnPropertyDescriptor(t,a):null;f&&(f.get||f.set)?Object.defineProperty(o,a,f):o[a]=t[a]}o.default=t,e&&e.set(t,o);return o}(e(2));function u(t){if("function"!=typeof WeakMap)return null;var r=new WeakMap,e=new WeakMap;return(u=function(t){return t?e:r})(t)}var i,a,f,c=Float32Array;function l(t,r){return(r=r||new c(16))[0]=t[0],r[1]=t[1],r[2]=t[2],r[3]=t[3],r[4]=t[4],r[5]=t[5],r[6]=t[6],r[7]=t[7],r[8]=t[8],r[9]=t[9],r[10]=t[10],r[11]=t[11],r[12]=t[12],r[13]=t[13],r[14]=t[14],r[15]=t[15],r}function s(t){return(t=t||new c(16))[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=1,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=1,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t}function v(t,r){r=r||new c(16);var e=t[0],n=t[1],o=t[2],u=t[3],i=t[4],a=t[5],f=t[6],l=t[7],s=t[8],v=t[9],y=t[10],b=t[11],m=t[12],d=t[13],p=t[14],h=t[15],w=y*h,x=p*b,F=f*h,j=p*l,O=f*b,E=y*l,A=o*h,S=p*u,M=o*b,_=y*u,T=o*l,g=f*u,P=s*d,R=m*v,z=i*d,k=m*a,U=i*v,C=s*a,W=e*d,I=m*n,L=e*v,G=s*n,B=e*a,N=i*n,X=w*a+j*v+O*d-(x*a+F*v+E*d),D=x*n+A*v+_*d-(w*n+S*v+M*d),H=F*n+S*a+T*d-(j*n+A*a+g*d),V=E*n+M*a+g*v-(O*n+_*a+T*v),Y=1/(e*X+i*D+s*H+m*V);return r[0]=Y*X,r[1]=Y*D,r[2]=Y*H,r[3]=Y*V,r[4]=Y*(x*i+F*s+E*m-(w*i+j*s+O*m)),r[5]=Y*(w*e+S*s+M*m-(x*e+A*s+_*m)),r[6]=Y*(j*e+A*i+g*m-(F*e+S*i+T*m)),r[7]=Y*(O*e+_*i+T*s-(E*e+M*i+g*s)),r[8]=Y*(P*l+k*b+U*h-(R*l+z*b+C*h)),r[9]=Y*(R*u+W*b+G*h-(P*u+I*b+L*h)),r[10]=Y*(z*u+I*l+B*h-(k*u+W*l+N*h)),r[11]=Y*(C*u+L*l+N*b-(U*u+G*l+B*b)),r[12]=Y*(z*y+C*p+R*f-(U*p+P*f+k*y)),r[13]=Y*(L*p+P*o+I*y-(W*y+G*p+R*o)),r[14]=Y*(W*f+N*p+k*o-(B*p+z*o+I*f)),r[15]=Y*(B*y+U*o+G*f-(L*f+N*y+C*o)),r}},function(t,r,e){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}r.__esModule=!0,r.createAttribsFromArrays=O,r.createBufferFromArray=A,r.createBufferFromTypedArray=v,r.createBufferInfoFromArrays=function(t,r,e){var n=O(t,r),u=Object.assign({},e||{});u.attribs=Object.assign({},e?e.attribs:{},n);var i=r.indices;if(i){var a=h(i,"indices");u.indices=v(t,a,34963),u.numElements=a.length,u.elementType=o.getGLTypeForTypedArray(a)}else u.numElements||(u.numElements=function(t,r){var e,n;for(n=0;n0)throw new Error("numComponents ".concat(u," not correct for length ").concat(o));return i}(r);return e},r.getArray_=b,r.getNumComponents_=p,r.setAttribInfoBufferFromArray=function(t,r,e,n){e=h(e),void 0!==n?(t.bindBuffer(f,r.buffer),t.bufferSubData(f,n,e)):s(t,f,r.buffer,e,r.drawType)},r.setAttributeDefaults_=function(t){u.copyExistingProperties(t,l)},r.setAttributePrefix=function(t){l.attribPrefix=t};var o=a(e(1)),u=a(e(0));function i(t){if("function"!=typeof WeakMap)return null;var r=new WeakMap,e=new WeakMap;return(i=function(t){return t?e:r})(t)}function a(t,r){if(!r&&t&&t.__esModule)return t;if(null===t||"object"!==n(t)&&"function"!=typeof t)return{default:t};var e=i(r);if(e&&e.has(t))return e.get(t);var o={},u=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in t)if("default"!==a&&Object.prototype.hasOwnProperty.call(t,a)){var f=u?Object.getOwnPropertyDescriptor(t,a):null;f&&(f.get||f.set)?Object.defineProperty(o,a,f):o[a]=t[a]}return o.default=t,e&&e.set(t,o),o}var f=34962,c=5126,l={attribPrefix:""};function s(t,r,e,n,o){t.bindBuffer(r,e),t.bufferData(r,n,o||35044)}function v(t,r,e,n){if(u.isBuffer(t,r))return r;e=e||f;var o=t.createBuffer();return s(t,e,o,r,n),o}function y(t){return"indices"===t}function b(t){return t.length?t:t.data}var m=/coord|texture/i,d=/color|colour/i;function p(t,r,e){return t.numComponents||t.size||function(t,r){var e;if(r%(e=m.test(t)?2:d.test(t)?4:3)>0)throw new Error("Can not guess numComponents for attribute '".concat(t,"'. Tried ").concat(e," but ").concat(r," values is not evenly divisible by ").concat(e,". You should specify it."));return e}(r,e||b(t).length)}function h(t,r){if(o.isArrayBuffer(t))return t;if(o.isArrayBuffer(t.data))return t.data;Array.isArray(t)&&(t={data:t});var e=t.type?w(t.type):void 0;return e||(e=y(r)?Uint16Array:Float32Array),new e(t.data)}function w(t){return"number"==typeof t?o.getTypedArrayTypeForGLType(t):t||Float32Array}function x(t,r){return{buffer:r.buffer,numValues:24,type:(e=r.type,"number"==typeof e?e:e?o.getGLTypeForTypedArrayType(e):c),arrayType:w(r.type)};var e}function F(t,r){var e=r.data||r,n=w(r.type),u=e*n.BYTES_PER_ELEMENT,i=t.createBuffer();return t.bindBuffer(f,i),t.bufferData(f,u,r.drawType||35044),{buffer:i,numValues:e,type:o.getGLTypeForTypedArrayType(n),arrayType:n}}function j(t,r,e){var n=h(r,e);return{arrayType:n.constructor,buffer:v(t,n,void 0,r.drawType),type:o.getGLTypeForTypedArray(n),numValues:0}}function O(t,r){var e={};return Object.keys(r).forEach((function(n){if(!y(n)){var u=r[n],i=u.attrib||u.name||u.attribName||l.attribPrefix+n;if(u.value){if(!Array.isArray(u.value)&&!o.isArrayBuffer(u.value))throw new Error("array.value is not array or typedarray");e[i]={value:u.value}}else{var a=(u.buffer&&u.buffer instanceof WebGLBuffer?x:"number"==typeof u||"number"==typeof u.data?F:j)(t,u,n),f=a.buffer,c=a.type,s=a.numValues,v=a.arrayType,b=void 0!==u.normalize?u.normalize:(d=v)===Int8Array||d===Uint8Array,m=p(u,n,s);e[i]={buffer:f,numComponents:m,type:c,normalize:b,stride:u.stride||0,offset:u.offset||0,divisor:void 0===u.divisor?void 0:u.divisor,drawType:u.drawType}}}var d})),t.bindBuffer(f,null),e}var E=["position","positions","a_position"];function A(t,r,e){var n="indices"===e?34963:f;return v(t,h(r,e),n)}},function(t,r,e){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}r.__esModule=!0,r.canFilter=rt,r.canGenerateMipmap=tt,r.createSampler=lt,r.createSamplers=function(t,r){var e={};return Object.keys(r).forEach((function(n){e[n]=lt(t,r[n])})),e},r.createTexture=St,r.createTextures=function(t,r,e){e=e||dt;var n=0,o=[],u={},i={};function a(){0===n&&setTimeout((function(){e(o.length?o:void 0,u,i)}),0)}return Object.keys(r).forEach((function(e){var f,c,l=r[e];("string"==typeof(c=l.src)||Array.isArray(c)&&"string"==typeof c[0])&&(f=function(t,r,u){i[e]=u,--n,t&&o.push(t),a()},++n),u[e]=St(t,l,f)})),a(),u},r.getBytesPerElementForInternalFormat=Z,r.getFormatAndTypeForInternalFormat=J,r.getNumComponentsForFormat=function(t){var r=q[t];if(!r)throw"unknown format: "+t;return r.u},r.loadTextureFromUrl=Ft,r.resizeTexture=function(t,r,e,n,o,u){n=n||e.width,o=o||e.height,u=u||e.depth;var i=e.target||j;t.bindTexture(i,r);var a,f=e.level||0,c=e.internalFormat||e.format||d,l=J(c),s=e.format||l.format,y=e.src;a=y&&(v(y)||Array.isArray(y)&&"number"==typeof y[0])?e.type||et(t,y,l.type):e.type||l.type;if(i===O)for(var b=0;b<6;++b)t.texImage2D(S+b,f,c,n,o,0,s,a,null);else i===E||i===A?t.texImage3D(i,f,c,n,o,u,0,s,a,null):t.texImage2D(i,f,c,n,o,0,s,a,null)},r.setDefaultTextureColor=ot,r.setEmptyTexture=At,r.setSamplerParameters=ct,r.setTextureDefaults_=function(t){i.copyExistingProperties(t,s),t.textureColor&&ot(t.textureColor)},r.setTextureFilteringForSize=st,r.setTextureFromArray=Et,r.setTextureFromElement=mt,r.setTextureParameters=ft;var o=f(e(3)),u=f(e(1)),i=f(e(0));function a(t){if("function"!=typeof WeakMap)return null;var r=new WeakMap,e=new WeakMap;return(a=function(t){return t?e:r})(t)}function f(t,r){if(!r&&t&&t.__esModule)return t;if(null===t||"object"!==n(t)&&"function"!=typeof t)return{default:t};var e=a(r);if(e&&e.has(t))return e.get(t);var o={},u=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var i in t)if("default"!==i&&Object.prototype.hasOwnProperty.call(t,i)){var f=u?Object.getOwnPropertyDescriptor(t,i):null;f&&(f.get||f.set)?Object.defineProperty(o,i,f):o[i]=t[i]}return o.default=t,e&&e.set(t,o),o}var c,l,s={textureColor:new Uint8Array([128,192,255,255]),textureOptions:{},crossOrigin:void 0},v=u.isArrayBuffer,y=function(){return c=c||("undefined"!=typeof document&&document.createElement?document.createElement("canvas").getContext("2d"):null)},b=6406,m=6407,d=6408,p=6409,h=6410,w=6402,x=34041,F=33071,j=3553,O=34067,E=32879,A=35866,S=34069,M=10241,_=10240,T=10242,g=10243,P=3317,R=5120,z=5121,k=5122,U=5123,C=5124,W=5125,I=5126,L=5131,G=36193,B=33640,N=33319,X=33320,D=6403,H=36244,V=36248,Y=36249,q={},K=q;function $(t){if(!l){var r={};r[6406]={v:b,h:!0,F:!0,j:[1,2,2,4],type:[z,L,G,I]},r[6409]={v:p,h:!0,F:!0,j:[1,2,2,4],type:[z,L,G,I]},r[6410]={v:h,h:!0,F:!0,j:[2,4,4,8],type:[z,L,G,I]},r[m]={v:m,h:!0,F:!0,j:[3,6,6,12,2],type:[z,L,G,I,33635]},r[d]={v:d,h:!0,F:!0,j:[4,8,8,16,2,2],type:[z,L,G,I,32819,32820]},r[6402]={v:w,h:!0,F:!1,j:[2,4],type:[W,U]},r[33321]={v:D,h:!0,F:!0,j:[1],type:[z]},r[36756]={v:D,h:!1,F:!0,j:[1],type:[R]},r[33325]={v:D,h:!1,F:!0,j:[4,2],type:[I,L]},r[33326]={v:D,h:!1,F:!1,j:[4],type:[I]},r[33330]={v:H,h:!0,F:!1,j:[1],type:[z]},r[33329]={v:H,h:!0,F:!1,j:[1],type:[R]},r[33332]={v:H,h:!0,F:!1,j:[2],type:[U]},r[33331]={v:H,h:!0,F:!1,j:[2],type:[k]},r[33334]={v:H,h:!0,F:!1,j:[4],type:[W]},r[33333]={v:H,h:!0,F:!1,j:[4],type:[C]},r[33323]={v:N,h:!0,F:!0,j:[2],type:[z]},r[36757]={v:N,h:!1,F:!0,j:[2],type:[R]},r[33327]={v:N,h:!1,F:!0,j:[8,4],type:[I,L]},r[33328]={v:N,h:!1,F:!1,j:[8],type:[I]},r[33336]={v:X,h:!0,F:!1,j:[2],type:[z]},r[33335]={v:X,h:!0,F:!1,j:[2],type:[R]},r[33338]={v:X,h:!0,F:!1,j:[4],type:[U]},r[33337]={v:X,h:!0,F:!1,j:[4],type:[k]},r[33340]={v:X,h:!0,F:!1,j:[8],type:[W]},r[33339]={v:X,h:!0,F:!1,j:[8],type:[C]},r[32849]={v:m,h:!0,F:!0,j:[3],type:[z]},r[35905]={v:m,h:!1,F:!0,j:[3],type:[z]},r[36194]={v:m,h:!0,F:!0,j:[3,2],type:[z,33635]},r[36758]={v:m,h:!1,F:!0,j:[3],type:[R]},r[35898]={v:m,h:!1,F:!0,j:[12,6,4],type:[I,L,35899]},r[35901]={v:m,h:!1,F:!0,j:[12,6,4],type:[I,L,35902]},r[34843]={v:m,h:!1,F:!0,j:[12,6],type:[I,L]},r[34837]={v:m,h:!1,F:!1,j:[12],type:[I]},r[36221]={v:V,h:!1,F:!1,j:[3],type:[z]},r[36239]={v:V,h:!1,F:!1,j:[3],type:[R]},r[36215]={v:V,h:!1,F:!1,j:[6],type:[U]},r[36233]={v:V,h:!1,F:!1,j:[6],type:[k]},r[36209]={v:V,h:!1,F:!1,j:[12],type:[W]},r[36227]={v:V,h:!1,F:!1,j:[12],type:[C]},r[32856]={v:d,h:!0,F:!0,j:[4],type:[z]},r[35907]={v:d,h:!0,F:!0,j:[4],type:[z]},r[36759]={v:d,h:!1,F:!0,j:[4],type:[R]},r[32855]={v:d,h:!0,F:!0,j:[4,2,4],type:[z,32820,B]},r[32854]={v:d,h:!0,F:!0,j:[4,2],type:[z,32819]},r[32857]={v:d,h:!0,F:!0,j:[4],type:[B]},r[34842]={v:d,h:!1,F:!0,j:[16,8],type:[I,L]},r[34836]={v:d,h:!1,F:!1,j:[16],type:[I]},r[36220]={v:Y,h:!0,F:!1,j:[4],type:[z]},r[36238]={v:Y,h:!0,F:!1,j:[4],type:[R]},r[36975]={v:Y,h:!0,F:!1,j:[4],type:[B]},r[36214]={v:Y,h:!0,F:!1,j:[8],type:[U]},r[36232]={v:Y,h:!0,F:!1,j:[8],type:[k]},r[36226]={v:Y,h:!0,F:!1,j:[16],type:[C]},r[36208]={v:Y,h:!0,F:!1,j:[16],type:[W]},r[33189]={v:w,h:!0,F:!1,j:[2,4],type:[U,W]},r[33190]={v:w,h:!0,F:!1,j:[4],type:[W]},r[36012]={v:w,h:!0,F:!1,j:[4],type:[I]},r[35056]={v:x,h:!0,F:!1,j:[4],type:[34042]},r[36013]={v:x,h:!0,F:!1,j:[4],type:[36269]},Object.keys(r).forEach((function(t){var e=r[t];e.bytesPerElementMap={},e.j.forEach((function(t,r){var n=e.type[r];e.bytesPerElementMap[n]=t}))})),l=r}return l[t]}function Z(t,r){var e=$(t);if(!e)throw"unknown internal format";var n=e.bytesPerElementMap[r];if(void 0===n)throw"unknown internal format";return n}function J(t){var r=$(t);if(!r)throw"unknown internal format";return{format:r.v,type:r.type[0]}}function Q(t){return 0==(t&t-1)}function tt(t,r,e,n){if(!o.isWebGL2(t))return Q(r)&&Q(e);var u=$(n);if(!u)throw"unknown internal format";return u.h&&u.F}function rt(t){var r=$(t);if(!r)throw"unknown internal format";return r.F}function et(t,r,e){return v(r)?u.getGLTypeForTypedArray(r):e||z}function nt(t,r,e,n,o){if(o%1!=0)throw"can't guess dimensions";if(e||n){if(n){if(!e&&(e=o/n)%1)throw"can't guess dimensions"}else if((n=o/e)%1)throw"can't guess dimensions"}else{var u=Math.sqrt(o/(r===O?6:1));u%1==0?(e=u,n=u):(e=o,n=1)}return{width:e,height:n}}function ot(t){s.textureColor=new Uint8Array([255*t[0],255*t[1],255*t[2],255*t[3]])}function ut(t,r){void 0!==r.colorspaceConversion&&t.pixelStorei(37443,r.colorspaceConversion),void 0!==r.premultiplyAlpha&&t.pixelStorei(37441,r.premultiplyAlpha),void 0!==r.flipY&&t.pixelStorei(37440,r.flipY)}function it(t){t.pixelStorei(P,4),o.isWebGL2(t)&&(t.pixelStorei(3314,0),t.pixelStorei(32878,0),t.pixelStorei(3316,0),t.pixelStorei(3315,0),t.pixelStorei(32877,0))}function at(t,r,e,n){n.minMag&&(e.call(t,r,M,n.minMag),e.call(t,r,_,n.minMag)),n.min&&e.call(t,r,M,n.min),n.mag&&e.call(t,r,_,n.mag),n.wrap&&(e.call(t,r,T,n.wrap),e.call(t,r,g,n.wrap),(r===E||i.isSampler(t,r))&&e.call(t,r,32882,n.wrap)),n.wrapR&&e.call(t,r,32882,n.wrapR),n.wrapS&&e.call(t,r,T,n.wrapS),n.wrapT&&e.call(t,r,g,n.wrapT),n.minLod&&e.call(t,r,33082,n.minLod),n.maxLod&&e.call(t,r,33083,n.maxLod),n.baseLevel&&e.call(t,r,33084,n.baseLevel),n.maxLevel&&e.call(t,r,33085,n.maxLevel)}function ft(t,r,e){var n=e.target||j;t.bindTexture(n,r),at(t,n,t.texParameteri,e)}function ct(t,r,e){at(t,r,t.samplerParameteri,e)}function lt(t,r){var e=t.createSampler();return ct(t,e,r),e}function st(t,r,e,n,o,u){e=e||s.textureOptions,u=u||d;var i=e.target||j;if(n=n||e.width,o=o||e.height,t.bindTexture(i,r),tt(t,n,o,u))t.generateMipmap(i);else{var a=rt(u)?9729:9728;t.texParameteri(i,M,a),t.texParameteri(i,_,a),t.texParameteri(i,T,F),t.texParameteri(i,g,F)}}function vt(t){return!0===t.auto||void 0===t.auto&&void 0===t.level}function yt(t,r){return(r=r||{}).cubeFaceOrder||[S,34070,34071,34072,34073,34074]}function bt(t,r){var e=yt(0,r).map((function(t,r){return{face:t,ndx:r}}));return e.sort((function(t,r){return t.face-r.face})),e}function mt(t,r,e,n){var o=(n=n||s.textureOptions).target||j,u=n.level||0,i=e.width,a=e.height,f=n.internalFormat||n.format||d,c=J(f),l=n.format||c.format,v=n.type||c.type;if(ut(t,n),t.bindTexture(o,r),o===O){var b,m,p=e.width,h=e.height;if(p/6===h)b=h,m=[0,0,1,0,2,0,3,0,4,0,5,0];else if(h/6===p)b=p,m=[0,0,0,1,0,2,0,3,0,4,0,5];else if(p/3==h/2)b=p/3,m=[0,0,1,0,2,0,0,1,1,1,2,1];else{if(p/2!=h/3)throw"can't figure out cube map from element: "+(e.src?e.src:e.nodeName);b=p/2,m=[0,0,1,0,0,1,1,1,0,2,1,2]}var w=y();w?(w.canvas.width=b,w.canvas.height=b,i=b,a=b,bt(0,n).forEach((function(r){var n=m[2*r.ndx+0]*b,o=m[2*r.ndx+1]*b;w.drawImage(e,n,o,b,b,0,0,b,b),t.texImage2D(r.face,u,f,l,v,w.canvas)})),w.canvas.width=1,w.canvas.height=1):"undefined"!=typeof createImageBitmap&&(i=b,a=b,bt(0,n).forEach((function(c){var s=m[2*c.ndx+0]*b,y=m[2*c.ndx+1]*b;t.texImage2D(c.face,u,f,b,b,0,l,v,null),createImageBitmap(e,s,y,b,b,{premultiplyAlpha:"none",colorSpaceConversion:"none"}).then((function(e){ut(t,n),t.bindTexture(o,r),t.texImage2D(c.face,u,f,l,v,e),vt(n)&&st(t,r,n,i,a,f)}))})))}else if(o===E||o===A){var x=Math.min(e.width,e.height),F=Math.max(e.width,e.height),S=F/x;if(S%1!=0)throw"can not compute 3D dimensions of element";var M=e.width===F?1:0,_=e.height===F?1:0;t.pixelStorei(P,1),t.pixelStorei(3314,e.width),t.pixelStorei(32878,0),t.pixelStorei(32877,0),t.texImage3D(o,u,f,x,x,x,0,l,v,null);for(var T=0;T=0?x(n,r):e.indexOf("tan")>=0||e.indexOf("binorm")>=0?h(n,r):e.indexOf("norm")>=0&&w(n,r)})),t}function j(t,r,e){return t=t||2,{position:{numComponents:2,data:[(r=r||0)+-1*(t*=.5),(e=e||0)+-1*t,r+1*t,e+-1*t,r+-1*t,e+1*t,r+1*t,e+1*t]},normal:[0,0,1,0,0,1,0,0,1,0,0,1],texcoord:[0,0,1,0,0,1,1,1],indices:[0,1,2,2,1,3]}}function O(t,r,e,n,o){t=t||1,r=r||1,e=e||1,n=n||1,o=o||a.identity();for(var u=(e+1)*(n+1),i=b(3,u),f=b(3,u),c=b(2,u),l=0;l<=n;l++)for(var s=0;s<=e;s++){var v=s/e,y=l/n;i.push(t*v-.5*t,0,r*y-.5*r),f.push(0,1,0),c.push(v,y)}for(var m=e+1,d=b(3,e*n*2,Uint16Array),p=0;p 0");n=n||0,u=u||0;for(var a=(o=o||Math.PI)-n,f=(i=i||2*Math.PI)-u,c=(r+1)*(e+1),l=b(3,c),s=b(3,c),v=b(2,c),y=0;y<=e;y++)for(var m=0;m<=r;m++){var d=m/r,p=y/e,h=f*d+u,w=a*p+n,x=Math.sin(h),F=Math.cos(h),j=Math.sin(w),O=F*j,E=Math.cos(w),A=x*j;l.push(t*O,t*E,t*A),s.push(O,E,A),v.push(1-d,p)}for(var S=r+1,M=b(3,r*e*2,Uint16Array),_=0;_o?(O=e,j=1,E=r):E=t+F/o*(r-t),-2!==F&&F!==o+2||(E=0,j=0),O-=e/2;for(var A=0;Ao?v.push(0,1,0):0===E?v.push(0,0,0):v.push(S*h,w,M*h),y.push(A/n,1-j)}}for(var _=0;_ 0");var a=(i=i||1)-(u=u||0),c=2*(o+1)*4,l=b(3,c),s=b(3,c),v=b(2,c);function y(t,r,e){return t+(r-t)*e}function m(r,e,i,c,b,m){for(var d=0;d<=o;d++){var p=e/1,h=d/o,w=2*(p-.5),x=(u+h*a)*Math.PI,F=Math.sin(x),j=Math.cos(x),O=y(t,r,F),E=w*n,A=j*t,S=F*O;l.push(E,A,S);var M=f.add(f.multiply([0,F,j],i),c);s.push(M),v.push(p*b+m,h)}}for(var d=0;d<2;d++){var p=2*(d/1-.5);m(r,d,[1,1,1],[0,0,0],1,0),m(r,d,[0,0,0],[p,0,0],0,0),m(e,d,[1,1,1],[0,0,0],1,0),m(e,d,[0,0,0],[p,0,0],0,1)}var h=b(3,2*o*4,Uint16Array);function w(t,r){for(var e=0;e0&&d!==r){var x=l+(d+1),F=l+d,j=l+d-v,O=l+(d+1)-v;c.push(x,F,j),c.push(x,j,O)}}l+=r+1}return{position:i,normal:a,texcoord:f,indices:c}}function k(t){return function(r){var e=t.apply(this,Array.prototype.slice.call(arguments,1));return o.createBuffersFromArrays(r,e)}}function U(t){return function(r){var e=t.apply(null,Array.prototype.slice.call(arguments,1));return o.createBufferInfoFromArrays(r,e)}}var C=["numComponents","size","type","normalize","stride","offset","attrib","name","attribName"];function W(t,r,e,n){n=n||0;for(var o=t.length,u=0;u=l&&t<36096}(w)&&c.push(w),!v)if(void 0!==m||function(t){return p[t]}(h))v=t.createRenderbuffer(),t.bindRenderbuffer(f,v),m>1?t.renderbufferStorageMultisample(f,m,h,e,n):t.renderbufferStorage(f,h,e,n);else{var x=Object.assign({},r);x.width=e,x.height=n,void 0===x.auto&&(x.auto=!1,x.min=x.min||x.minMag||b,x.mag=x.mag||x.minMag||b,x.wrapS=x.wrapS||x.wrap||y,x.wrapT=x.wrapT||x.wrap||y),v=o.createTexture(t,x)}if(u.isRenderbuffer(t,v))t.framebufferRenderbuffer(i,w,f,v);else{if(!u.isTexture(t,v))throw new Error("unknown attachment type");void 0!==r.layer?t.framebufferTextureLayer(i,w,v,r.level||0,r.layer):t.framebufferTexture2D(i,w,r.target||3553,v,r.level||0)}s.attachments.push(v)})),t.drawBuffers&&t.drawBuffers(c);return s},r.resizeFramebufferInfo=function(t,r,e,n,i){n=n||t.drawingBufferWidth,i=i||t.drawingBufferHeight,r.width=n,r.height=i,(e=e||m).forEach((function(e,a){var c=r.attachments[a],l=e.format,s=e.samples;if(void 0!==s||u.isRenderbuffer(t,c))t.bindRenderbuffer(f,c),s>1?t.renderbufferStorageMultisample(f,s,l,n,i):t.renderbufferStorage(f,l,n,i);else{if(!u.isTexture(t,c))throw new Error("unknown attachment type");o.resizeTexture(t,c,e,n,i)}}))};var o=a(e(7)),u=a(e(0));function i(t){if("function"!=typeof WeakMap)return null;var r=new WeakMap,e=new WeakMap;return(i=function(t){return t?e:r})(t)}function a(t,r){if(!r&&t&&t.__esModule)return t;if(null===t||"object"!==n(t)&&"function"!=typeof t)return{default:t};var e=i(r);if(e&&e.has(t))return e.get(t);var o={},u=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in t)if("default"!==a&&Object.prototype.hasOwnProperty.call(t,a)){var f=u?Object.getOwnPropertyDescriptor(t,a):null;f&&(f.get||f.set)?Object.defineProperty(o,a,f):o[a]=t[a]}return o.default=t,e&&e.set(t,o),o}var f=36161,c=34041,l=36064,s=36096,v=33306,y=33071,b=9729,m=[{format:6408,type:5121,min:b,wrap:y},{format:c}],d={};d[34041]=v,d[6401]=36128,d[36168]=36128,d[6402]=s,d[33189]=s,d[33190]=s,d[36012]=s,d[35056]=v,d[36013]=v;var p={};p[32854]=!0,p[32855]=!0,p[36194]=!0,p[34041]=!0,p[33189]=!0,p[6401]=!0,p[36168]=!0},function(t,r,e){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}r.__esModule=!0,r.createVAOAndSetAttributes=i,r.createVAOFromBufferInfo=function(t,r,e){return i(t,r.attribSetters||r,e.attribs,e.indices)},r.createVertexArrayInfo=function(t,r,e){var n=t.createVertexArray();t.bindVertexArray(n),r.length||(r=[r]);return r.forEach((function(r){o.setBuffersAndAttributes(t,r,e)})),t.bindVertexArray(null),{numElements:e.numElements,elementType:e.elementType,vertexArrayObject:n}};var o=function(t,r){if(!r&&t&&t.__esModule)return t;if(null===t||"object"!==n(t)&&"function"!=typeof t)return{default:t};var e=u(r);if(e&&e.has(t))return e.get(t);var o={},i=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in t)if("default"!==a&&Object.prototype.hasOwnProperty.call(t,a)){var f=i?Object.getOwnPropertyDescriptor(t,a):null;f&&(f.get||f.set)?Object.defineProperty(o,a,f):o[a]=t[a]}o.default=t,e&&e.set(t,o);return o}(e(4));function u(t){if("function"!=typeof WeakMap)return null;var r=new WeakMap,e=new WeakMap;return(u=function(t){return t?e:r})(t)}function i(t,r,e,n){var u=t.createVertexArray();return t.bindVertexArray(u),o.setAttributes(r,e),n&&t.bindBuffer(34963,n),t.bindVertexArray(null),u}}])})); \ No newline at end of file +!(function (t, r) { + 'object' == typeof exports && 'object' == typeof module + ? (module.exports = r()) + : 'function' == typeof define && define.amd + ? define([], r) + : 'object' == typeof exports + ? (exports.twgl = r()) + : (t.twgl = r()) +})('undefined' != typeof self ? self : this, function () { + return (function (t) { + var r = {} + function e(n) { + if (r[n]) return r[n].exports + var o = (r[n] = { i: n, l: !1, exports: {} }) + return t[n].call(o.exports, o, o.exports, e), (o.l = !0), o.exports + } + return ( + (e.m = t), + (e.c = r), + (e.d = function (t, r, n) { + e.o(t, r) || + Object.defineProperty(t, r, { enumerable: !0, get: n }) + }), + (e.r = function (t) { + 'undefined' != typeof Symbol && + Symbol.toStringTag && + Object.defineProperty(t, Symbol.toStringTag, { + value: 'Module', + }), + Object.defineProperty(t, '__esModule', { value: !0 }) + }), + (e.t = function (t, r) { + if ((1 & r && (t = e(t)), 8 & r)) return t + if (4 & r && 'object' == typeof t && t && t.__esModule) return t + var n = Object.create(null) + if ( + (e.r(n), + Object.defineProperty(n, 'default', { + enumerable: !0, + value: t, + }), + 2 & r && 'string' != typeof t) + ) + for (var o in t) + e.d( + n, + o, + function (r) { + return t[r] + }.bind(null, o) + ) + return n + }), + (e.n = function (t) { + var r = + t && t.__esModule + ? function () { + return t.default + } + : function () { + return t + } + return e.d(r, 'a', r), r + }), + (e.o = function (t, r) { + return Object.prototype.hasOwnProperty.call(t, r) + }), + (e.p = ''), + e((e.s = 8)) + ) + })([ + function (t, r, e) { + 'use strict' + function n(t) { + return (n = + 'function' == typeof Symbol && + 'symbol' == typeof Symbol.iterator + ? function (t) { + return typeof t + } + : function (t) { + return t && + 'function' == typeof Symbol && + t.constructor === Symbol && + t !== Symbol.prototype + ? 'symbol' + : typeof t + })(t) + } + ;(r.__esModule = !0), + (r.copyExistingProperties = function (t, r) { + Object.keys(r).forEach(function (e) { + r.hasOwnProperty(e) && + t.hasOwnProperty(e) && + (r[e] = t[e]) + }) + }), + (r.copyNamedProperties = function (t, r, e) { + t.forEach(function (t) { + var n = r[t] + void 0 !== n && (e[t] = n) + }) + }), + (r.error = function () { + var t + ;(t = console).error.apply(t, arguments) + }), + (r.isBuffer = function (t, r) { + return ( + 'undefined' != typeof WebGLBuffer && u(r, 'WebGLBuffer') + ) + }), + (r.isRenderbuffer = function (t, r) { + return ( + 'undefined' != typeof WebGLRenderbuffer && + u(r, 'WebGLRenderbuffer') + ) + }), + (r.isSampler = function (t, r) { + return ( + 'undefined' != typeof WebGLSampler && + u(r, 'WebGLSampler') + ) + }), + (r.isShader = function (t, r) { + return ( + 'undefined' != typeof WebGLShader && u(r, 'WebGLShader') + ) + }), + (r.isTexture = function (t, r) { + return ( + 'undefined' != typeof WebGLTexture && + u(r, 'WebGLTexture') + ) + }), + (r.warn = function () { + var t + ;(t = console).warn.apply(t, arguments) + }) + var o = new Map() + function u(t, r) { + if (!t || 'object' !== n(t)) return !1 + var e = o.get(r) + e || ((e = new WeakMap()), o.set(r, e)) + var u = e.get(t) + if (void 0 === u) { + var i = Object.prototype.toString.call(t) + ;(u = i.substring(8, i.length - 1) === r), e.set(t, u) + } + return u + } + }, + function (t, r, e) { + 'use strict' + ;(r.__esModule = !0), + (r.getGLTypeForTypedArray = function (t) { + if (t instanceof Int8Array) return n + if (t instanceof Uint8Array) return o + if (t instanceof Uint8ClampedArray) return o + if (t instanceof Int16Array) return u + if (t instanceof Uint16Array) return i + if (t instanceof Int32Array) return a + if (t instanceof Uint32Array) return f + if (t instanceof Float32Array) return c + throw new Error('unsupported typed array type') + }), + (r.getGLTypeForTypedArrayType = function (t) { + if (t === Int8Array) return n + if (t === Uint8Array) return o + if (t === Uint8ClampedArray) return o + if (t === Int16Array) return u + if (t === Uint16Array) return i + if (t === Int32Array) return a + if (t === Uint32Array) return f + if (t === Float32Array) return c + throw new Error('unsupported typed array type') + }), + (r.getTypedArrayTypeForGLType = function (t) { + var r = l[t] + if (!r) throw new Error('unknown gl type') + return r + }), + (r.isArrayBuffer = void 0) + var n = 5120, + o = 5121, + u = 5122, + i = 5123, + a = 5124, + f = 5125, + c = 5126, + l = {}, + s = l + ;(s[n] = Int8Array), + (s[5121] = Uint8Array), + (s[5122] = Int16Array), + (s[5123] = Uint16Array), + (s[a] = Int32Array), + (s[5125] = Uint32Array), + (s[5126] = Float32Array), + (s[32819] = Uint16Array), + (s[32820] = Uint16Array), + (s[33635] = Uint16Array), + (s[5131] = Uint16Array), + (s[33640] = Uint32Array), + (s[35899] = Uint32Array), + (s[35902] = Uint32Array), + (s[36269] = Uint32Array), + (s[34042] = Uint32Array) + var v = + 'undefined' != typeof SharedArrayBuffer + ? function (t) { + return ( + t && + t.buffer && + (t.buffer instanceof ArrayBuffer || + t.buffer instanceof SharedArrayBuffer) + ) + } + : function (t) { + return ( + t && t.buffer && t.buffer instanceof ArrayBuffer + ) + } + r.isArrayBuffer = v + }, + function (t, r, e) { + 'use strict' + ;(r.__esModule = !0), + (r.add = function (t, r, e) { + return ( + ((e = e || new n(3))[0] = t[0] + r[0]), + (e[1] = t[1] + r[1]), + (e[2] = t[2] + r[2]), + e + ) + }), + (r.copy = function (t, r) { + return ( + ((r = r || new n(3))[0] = t[0]), + (r[1] = t[1]), + (r[2] = t[2]), + r + ) + }), + (r.create = function (t, r, e) { + var o = new n(3) + t && (o[0] = t) + r && (o[1] = r) + e && (o[2] = e) + return o + }), + (r.cross = function (t, r, e) { + e = e || new n(3) + var o = t[2] * r[0] - t[0] * r[2], + u = t[0] * r[1] - t[1] * r[0] + return ( + (e[0] = t[1] * r[2] - t[2] * r[1]), + (e[1] = o), + (e[2] = u), + e + ) + }), + (r.distance = function (t, r) { + var e = t[0] - r[0], + n = t[1] - r[1], + o = t[2] - r[2] + return Math.sqrt(e * e + n * n + o * o) + }), + (r.distanceSq = function (t, r) { + var e = t[0] - r[0], + n = t[1] - r[1], + o = t[2] - r[2] + return e * e + n * n + o * o + }), + (r.divScalar = function (t, r, e) { + return ( + ((e = e || new n(3))[0] = t[0] / r), + (e[1] = t[1] / r), + (e[2] = t[2] / r), + e + ) + }), + (r.divide = function (t, r, e) { + return ( + ((e = e || new n(3))[0] = t[0] / r[0]), + (e[1] = t[1] / r[1]), + (e[2] = t[2] / r[2]), + e + ) + }), + (r.dot = function (t, r) { + return t[0] * r[0] + t[1] * r[1] + t[2] * r[2] + }), + (r.length = function (t) { + return Math.sqrt(t[0] * t[0] + t[1] * t[1] + t[2] * t[2]) + }), + (r.lengthSq = function (t) { + return t[0] * t[0] + t[1] * t[1] + t[2] * t[2] + }), + (r.lerp = function (t, r, e, o) { + return ( + ((o = o || new n(3))[0] = t[0] + e * (r[0] - t[0])), + (o[1] = t[1] + e * (r[1] - t[1])), + (o[2] = t[2] + e * (r[2] - t[2])), + o + ) + }), + (r.lerpV = function (t, r, e, o) { + return ( + ((o = o || new n(3))[0] = t[0] + e[0] * (r[0] - t[0])), + (o[1] = t[1] + e[1] * (r[1] - t[1])), + (o[2] = t[2] + e[2] * (r[2] - t[2])), + o + ) + }), + (r.max = function (t, r, e) { + return ( + ((e = e || new n(3))[0] = Math.max(t[0], r[0])), + (e[1] = Math.max(t[1], r[1])), + (e[2] = Math.max(t[2], r[2])), + e + ) + }), + (r.min = function (t, r, e) { + return ( + ((e = e || new n(3))[0] = Math.min(t[0], r[0])), + (e[1] = Math.min(t[1], r[1])), + (e[2] = Math.min(t[2], r[2])), + e + ) + }), + (r.mulScalar = function (t, r, e) { + return ( + ((e = e || new n(3))[0] = t[0] * r), + (e[1] = t[1] * r), + (e[2] = t[2] * r), + e + ) + }), + (r.multiply = function (t, r, e) { + return ( + ((e = e || new n(3))[0] = t[0] * r[0]), + (e[1] = t[1] * r[1]), + (e[2] = t[2] * r[2]), + e + ) + }), + (r.negate = function (t, r) { + return ( + ((r = r || new n(3))[0] = -t[0]), + (r[1] = -t[1]), + (r[2] = -t[2]), + r + ) + }), + (r.normalize = function (t, r) { + r = r || new n(3) + var e = t[0] * t[0] + t[1] * t[1] + t[2] * t[2], + o = Math.sqrt(e) + o > 1e-5 + ? ((r[0] = t[0] / o), + (r[1] = t[1] / o), + (r[2] = t[2] / o)) + : ((r[0] = 0), (r[1] = 0), (r[2] = 0)) + return r + }), + (r.setDefaultType = function (t) { + var r = n + return (n = t), r + }), + (r.subtract = function (t, r, e) { + return ( + ((e = e || new n(3))[0] = t[0] - r[0]), + (e[1] = t[1] - r[1]), + (e[2] = t[2] - r[2]), + e + ) + }) + var n = Float32Array + }, + function (t, r, e) { + 'use strict' + ;(r.__esModule = !0), + (r.glEnumToString = void 0), + (r.isWebGL1 = function (t) { + return !t.texStorage2D + }), + (r.isWebGL2 = function (t) { + return !!t.texStorage2D + }) + var n, + o, + u = + ((n = {}), + (o = {}), + function (t, r) { + return ( + (function (t) { + var r = t.constructor.name + if (!n[r]) { + for (var e in t) + if ('number' == typeof t[e]) { + var u = o[t[e]] + o[t[e]] = u + ? ''.concat(u, ' | ').concat(e) + : e + } + n[r] = !0 + } + })(t), + o[r] || + ('number' == typeof r + ? '0x'.concat(r.toString(16)) + : r) + ) + }) + r.glEnumToString = u + }, + function (t, r, e) { + 'use strict' + function n(t) { + return (n = + 'function' == typeof Symbol && + 'symbol' == typeof Symbol.iterator + ? function (t) { + return typeof t + } + : function (t) { + return t && + 'function' == typeof Symbol && + t.constructor === Symbol && + t !== Symbol.prototype + ? 'symbol' + : typeof t + })(t) + } + ;(r.__esModule = !0), + (r.bindTransformFeedbackInfo = dt), + (r.bindUniformBlock = xt), + (r.createAttributeSetters = Et), + (r.createProgram = rt), + (r.createProgramAsync = void 0), + (r.createProgramFromScripts = function (t, r, e, n, o) { + var u, + i = Z(e, n, o), + a = [], + f = m(r) + try { + for (f.s(); !(u = f.n()).done; ) { + var c = u.value, + l = F(c) + if (!l) + return K( + i, + 'unknown script element: '.concat(c) + ) + a.push(l.text) + } + } catch (t) { + f.e(t) + } finally { + f.f() + } + return rt(t, a, i) + }), + (r.createProgramFromSources = lt), + (r.createProgramInfo = _t), + (r.createProgramInfoAsync = void 0), + (r.createProgramInfoFromProgram = St), + (r.createProgramInfos = Pt), + (r.createProgramInfosAsync = void 0), + (r.createPrograms = gt), + (r.createProgramsAsync = void 0), + (r.createTransformFeedback = function (t, r, e) { + var n = t.createTransformFeedback() + return ( + t.bindTransformFeedback(36386, n), + t.useProgram(r.program), + dt(t, r, e), + t.bindTransformFeedback(36386, null), + n + ) + }), + (r.createTransformFeedbackInfo = mt), + (r.createUniformBlockInfo = function (t, r, e) { + return wt(t, r.program, r.uniformBlockSpec, e) + }), + (r.createUniformBlockInfoFromProgram = wt), + (r.createUniformBlockSpecFromProgram = pt), + (r.createUniformSetters = bt), + (r.setAttributes = At), + (r.setBlockUniforms = function (t, r) { + var e = t.setters + for (var n in r) { + var o = e[n] + if (o) { + var u = r[n] + o(u) + } + } + }), + (r.setBuffersAndAttributes = function (t, r, e) { + e.vertexArrayObject + ? t.bindVertexArray(e.vertexArrayObject) + : (At(r.attribSetters || r, e.attribs), + e.indices && t.bindBuffer(34963, e.indices)) + }), + (r.setUniformBlock = function (t, r, e) { + xt(t, r, e) && t.bufferData(E, e.array, 35048) + }), + (r.setUniforms = jt), + (r.setUniformsAndBindTextures = void 0) + var o = a(e(3)), + u = a(e(0)) + function i(t) { + if ('function' != typeof WeakMap) return null + var r = new WeakMap(), + e = new WeakMap() + return (i = function (t) { + return t ? e : r + })(t) + } + function a(t, r) { + if (!r && t && t.__esModule) return t + if (null === t || ('object' !== n(t) && 'function' != typeof t)) + return { default: t } + var e = i(r) + if (e && e.has(t)) return e.get(t) + var o = {}, + u = Object.defineProperty && Object.getOwnPropertyDescriptor + for (var a in t) + if ( + 'default' !== a && + Object.prototype.hasOwnProperty.call(t, a) + ) { + var f = u ? Object.getOwnPropertyDescriptor(t, a) : null + f && (f.get || f.set) + ? Object.defineProperty(o, a, f) + : (o[a] = t[a]) + } + return (o.default = t), e && e.set(t, o), o + } + function f() { + f = function () { + return t + } + var t = {}, + r = Object.prototype, + e = r.hasOwnProperty, + o = 'function' == typeof Symbol ? Symbol : {}, + u = o.iterator || '@@iterator', + i = o.asyncIterator || '@@asyncIterator', + a = o.toStringTag || '@@toStringTag' + function c(t, r, e) { + return ( + Object.defineProperty(t, r, { + value: e, + enumerable: !0, + configurable: !0, + writable: !0, + }), + t[r] + ) + } + try { + c({}, '') + } catch (t) { + c = function (t, r, e) { + return (t[r] = e) + } + } + function l(t, r, e, n) { + var o = r && r.prototype instanceof y ? r : y, + u = Object.create(o.prototype), + i = new A(n || []) + return ( + (u._invoke = (function (t, r, e) { + var n = 'suspendedStart' + return function (o, u) { + if ('executing' === n) + throw new Error( + 'Generator is already running' + ) + if ('completed' === n) { + if ('throw' === o) throw u + return M() + } + for (e.method = o, e.arg = u; ; ) { + var i = e.delegate + if (i) { + var a = j(i, e) + if (a) { + if (a === v) continue + return a + } + } + if ('next' === e.method) + e.sent = e._sent = e.arg + else if ('throw' === e.method) { + if ('suspendedStart' === n) + throw ((n = 'completed'), e.arg) + e.dispatchException(e.arg) + } else + 'return' === e.method && + e.abrupt('return', e.arg) + n = 'executing' + var f = s(t, r, e) + if ('normal' === f.type) { + if ( + ((n = e.done + ? 'completed' + : 'suspendedYield'), + f.arg === v) + ) + continue + return { value: f.arg, done: e.done } + } + 'throw' === f.type && + ((n = 'completed'), + (e.method = 'throw'), + (e.arg = f.arg)) + } + } + })(t, e, i)), + u + ) + } + function s(t, r, e) { + try { + return { type: 'normal', arg: t.call(r, e) } + } catch (t) { + return { type: 'throw', arg: t } + } + } + t.wrap = l + var v = {} + function y() {} + function b() {} + function m() {} + var d = {} + c(d, u, function () { + return this + }) + var p = Object.getPrototypeOf, + h = p && p(p(S([]))) + h && h !== r && e.call(h, u) && (d = h) + var w = (m.prototype = y.prototype = Object.create(d)) + function x(t) { + ;['next', 'throw', 'return'].forEach(function (r) { + c(t, r, function (t) { + return this._invoke(r, t) + }) + }) + } + function F(t, r) { + function o(u, i, a, f) { + var c = s(t[u], t, i) + if ('throw' !== c.type) { + var l = c.arg, + v = l.value + return v && 'object' == n(v) && e.call(v, '__await') + ? r.resolve(v.__await).then( + function (t) { + o('next', t, a, f) + }, + function (t) { + o('throw', t, a, f) + } + ) + : r.resolve(v).then( + function (t) { + ;(l.value = t), a(l) + }, + function (t) { + return o('throw', t, a, f) + } + ) + } + f(c.arg) + } + var u + this._invoke = function (t, e) { + function n() { + return new r(function (r, n) { + o(t, e, r, n) + }) + } + return (u = u ? u.then(n, n) : n()) + } + } + function j(t, r) { + var e = t.iterator[r.method] + if (void 0 === e) { + if (((r.delegate = null), 'throw' === r.method)) { + if ( + t.iterator.return && + ((r.method = 'return'), + (r.arg = void 0), + j(t, r), + 'throw' === r.method) + ) + return v + ;(r.method = 'throw'), + (r.arg = new TypeError( + "The iterator does not provide a 'throw' method" + )) + } + return v + } + var n = s(e, t.iterator, r.arg) + if ('throw' === n.type) + return ( + (r.method = 'throw'), + (r.arg = n.arg), + (r.delegate = null), + v + ) + var o = n.arg + return o + ? o.done + ? ((r[t.resultName] = o.value), + (r.next = t.nextLoc), + 'return' !== r.method && + ((r.method = 'next'), (r.arg = void 0)), + (r.delegate = null), + v) + : o + : ((r.method = 'throw'), + (r.arg = new TypeError( + 'iterator result is not an object' + )), + (r.delegate = null), + v) + } + function O(t) { + var r = { tryLoc: t[0] } + 1 in t && (r.catchLoc = t[1]), + 2 in t && ((r.finallyLoc = t[2]), (r.afterLoc = t[3])), + this.tryEntries.push(r) + } + function E(t) { + var r = t.completion || {} + ;(r.type = 'normal'), delete r.arg, (t.completion = r) + } + function A(t) { + ;(this.tryEntries = [{ tryLoc: 'root' }]), + t.forEach(O, this), + this.reset(!0) + } + function S(t) { + if (t) { + var r = t[u] + if (r) return r.call(t) + if ('function' == typeof t.next) return t + if (!isNaN(t.length)) { + var n = -1, + o = function r() { + for (; ++n < t.length; ) + if (e.call(t, n)) + return ( + (r.value = t[n]), + (r.done = !1), + r + ) + return (r.value = void 0), (r.done = !0), r + } + return (o.next = o) + } + } + return { next: M } + } + function M() { + return { value: void 0, done: !0 } + } + return ( + (b.prototype = m), + c(w, 'constructor', m), + c(m, 'constructor', b), + (b.displayName = c(m, a, 'GeneratorFunction')), + (t.isGeneratorFunction = function (t) { + var r = 'function' == typeof t && t.constructor + return ( + !!r && + (r === b || + 'GeneratorFunction' === + (r.displayName || r.name)) + ) + }), + (t.mark = function (t) { + return ( + Object.setPrototypeOf + ? Object.setPrototypeOf(t, m) + : ((t.__proto__ = m), + c(t, a, 'GeneratorFunction')), + (t.prototype = Object.create(w)), + t + ) + }), + (t.awrap = function (t) { + return { __await: t } + }), + x(F.prototype), + c(F.prototype, i, function () { + return this + }), + (t.AsyncIterator = F), + (t.async = function (r, e, n, o, u) { + void 0 === u && (u = Promise) + var i = new F(l(r, e, n, o), u) + return t.isGeneratorFunction(e) + ? i + : i.next().then(function (t) { + return t.done ? t.value : i.next() + }) + }), + x(w), + c(w, a, 'Generator'), + c(w, u, function () { + return this + }), + c(w, 'toString', function () { + return '[object Generator]' + }), + (t.keys = function (t) { + var r = [] + for (var e in t) r.push(e) + return ( + r.reverse(), + function e() { + for (; r.length; ) { + var n = r.pop() + if (n in t) + return (e.value = n), (e.done = !1), e + } + return (e.done = !0), e + } + ) + }), + (t.values = S), + (A.prototype = { + constructor: A, + reset: function (t) { + if ( + ((this.prev = 0), + (this.next = 0), + (this.sent = this._sent = void 0), + (this.done = !1), + (this.delegate = null), + (this.method = 'next'), + (this.arg = void 0), + this.tryEntries.forEach(E), + !t) + ) + for (var r in this) + 't' === r.charAt(0) && + e.call(this, r) && + !isNaN(+r.slice(1)) && + (this[r] = void 0) + }, + stop: function () { + this.done = !0 + var t = this.tryEntries[0].completion + if ('throw' === t.type) throw t.arg + return this.rval + }, + dispatchException: function (t) { + if (this.done) throw t + var r = this + function n(e, n) { + return ( + (i.type = 'throw'), + (i.arg = t), + (r.next = e), + n && + ((r.method = 'next'), (r.arg = void 0)), + !!n + ) + } + for ( + var o = this.tryEntries.length - 1; + o >= 0; + --o + ) { + var u = this.tryEntries[o], + i = u.completion + if ('root' === u.tryLoc) return n('end') + if (u.tryLoc <= this.prev) { + var a = e.call(u, 'catchLoc'), + f = e.call(u, 'finallyLoc') + if (a && f) { + if (this.prev < u.catchLoc) + return n(u.catchLoc, !0) + if (this.prev < u.finallyLoc) + return n(u.finallyLoc) + } else if (a) { + if (this.prev < u.catchLoc) + return n(u.catchLoc, !0) + } else { + if (!f) + throw new Error( + 'try statement without catch or finally' + ) + if (this.prev < u.finallyLoc) + return n(u.finallyLoc) + } + } + } + }, + abrupt: function (t, r) { + for ( + var n = this.tryEntries.length - 1; + n >= 0; + --n + ) { + var o = this.tryEntries[n] + if ( + o.tryLoc <= this.prev && + e.call(o, 'finallyLoc') && + this.prev < o.finallyLoc + ) { + var u = o + break + } + } + u && + ('break' === t || 'continue' === t) && + u.tryLoc <= r && + r <= u.finallyLoc && + (u = null) + var i = u ? u.completion : {} + return ( + (i.type = t), + (i.arg = r), + u + ? ((this.method = 'next'), + (this.next = u.finallyLoc), + v) + : this.complete(i) + ) + }, + complete: function (t, r) { + if ('throw' === t.type) throw t.arg + return ( + 'break' === t.type || 'continue' === t.type + ? (this.next = t.arg) + : 'return' === t.type + ? ((this.rval = this.arg = t.arg), + (this.method = 'return'), + (this.next = 'end')) + : 'normal' === t.type && + r && + (this.next = r), + v + ) + }, + finish: function (t) { + for ( + var r = this.tryEntries.length - 1; + r >= 0; + --r + ) { + var e = this.tryEntries[r] + if (e.finallyLoc === t) + return ( + this.complete(e.completion, e.afterLoc), + E(e), + v + ) + } + }, + catch: function (t) { + for ( + var r = this.tryEntries.length - 1; + r >= 0; + --r + ) { + var e = this.tryEntries[r] + if (e.tryLoc === t) { + var n = e.completion + if ('throw' === n.type) { + var o = n.arg + E(e) + } + return o + } + } + throw new Error('illegal catch attempt') + }, + delegateYield: function (t, r, e) { + return ( + (this.delegate = { + iterator: S(t), + resultName: r, + nextLoc: e, + }), + 'next' === this.method && (this.arg = void 0), + v + ) + }, + }), + t + ) + } + function c(t, r) { + var e = Object.keys(t) + if (Object.getOwnPropertySymbols) { + var n = Object.getOwnPropertySymbols(t) + r && + (n = n.filter(function (r) { + return Object.getOwnPropertyDescriptor( + t, + r + ).enumerable + })), + e.push.apply(e, n) + } + return e + } + function l(t) { + for (var r = 1; r < arguments.length; r++) { + var e = null != arguments[r] ? arguments[r] : {} + r % 2 + ? c(Object(e), !0).forEach(function (r) { + s(t, r, e[r]) + }) + : Object.getOwnPropertyDescriptors + ? Object.defineProperties( + t, + Object.getOwnPropertyDescriptors(e) + ) + : c(Object(e)).forEach(function (r) { + Object.defineProperty( + t, + r, + Object.getOwnPropertyDescriptor(e, r) + ) + }) + } + return t + } + function s(t, r, e) { + return ( + r in t + ? Object.defineProperty(t, r, { + value: e, + enumerable: !0, + configurable: !0, + writable: !0, + }) + : (t[r] = e), + t + ) + } + function v(t, r, e, n, o, u, i) { + try { + var a = t[u](i), + f = a.value + } catch (t) { + return void e(t) + } + a.done ? r(f) : Promise.resolve(f).then(n, o) + } + function y(t) { + return function () { + var r = this, + e = arguments + return new Promise(function (n, o) { + var u = t.apply(r, e) + function i(t) { + v(u, n, o, i, a, 'next', t) + } + function a(t) { + v(u, n, o, i, a, 'throw', t) + } + i(void 0) + }) + } + } + function b(t, r) { + return ( + (function (t) { + if (Array.isArray(t)) return t + })(t) || + (function (t, r) { + var e = + null == t + ? null + : ('undefined' != typeof Symbol && + t[Symbol.iterator]) || + t['@@iterator'] + if (null == e) return + var n, + o, + u = [], + i = !0, + a = !1 + try { + for ( + e = e.call(t); + !(i = (n = e.next()).done) && + (u.push(n.value), !r || u.length !== r); + i = !0 + ); + } catch (t) { + ;(a = !0), (o = t) + } finally { + try { + i || null == e.return || e.return() + } finally { + if (a) throw o + } + } + return u + })(t, r) || + p(t, r) || + (function () { + throw new TypeError( + 'Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.' + ) + })() + ) + } + function m(t, r) { + var e = + ('undefined' != typeof Symbol && t[Symbol.iterator]) || + t['@@iterator'] + if (!e) { + if ( + Array.isArray(t) || + (e = p(t)) || + (r && t && 'number' == typeof t.length) + ) { + e && (t = e) + var n = 0, + o = function () {} + return { + s: o, + n: function () { + return n >= t.length + ? { done: !0 } + : { done: !1, value: t[n++] } + }, + e: function (t) { + throw t + }, + f: o, + } + } + throw new TypeError( + 'Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.' + ) + } + var u, + i = !0, + a = !1 + return { + s: function () { + e = e.call(t) + }, + n: function () { + var t = e.next() + return (i = t.done), t + }, + e: function (t) { + ;(a = !0), (u = t) + }, + f: function () { + try { + i || null == e.return || e.return() + } finally { + if (a) throw u + } + }, + } + } + function d(t) { + return ( + (function (t) { + if (Array.isArray(t)) return h(t) + })(t) || + (function (t) { + if ( + ('undefined' != typeof Symbol && + null != t[Symbol.iterator]) || + null != t['@@iterator'] + ) + return Array.from(t) + })(t) || + p(t) || + (function () { + throw new TypeError( + 'Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.' + ) + })() + ) + } + function p(t, r) { + if (t) { + if ('string' == typeof t) return h(t, r) + var e = Object.prototype.toString.call(t).slice(8, -1) + return ( + 'Object' === e && + t.constructor && + (e = t.constructor.name), + 'Map' === e || 'Set' === e + ? Array.from(t) + : 'Arguments' === e || + /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(e) + ? h(t, r) + : void 0 + ) + } + } + function h(t, r) { + ;(null == r || r > t.length) && (r = t.length) + for (var e = 0, n = new Array(r); e < r; e++) n[e] = t[e] + return n + } + var w = u.error, + x = u.warn + function F(t) { + return 'undefined' != typeof document && document.getElementById + ? document.getElementById(t) + : null + } + var j = 33984, + O = 34962, + E = 35345, + A = 5126, + S = 5124, + M = 5125, + _ = 3553, + T = 34067, + g = 32879, + P = 35866, + R = {} + function z(t, r) { + return R[r].bindPoint + } + function k(t, r) { + return function (e) { + t.uniform1i(r, e) + } + } + function U(t, r) { + return function (e) { + t.uniform1iv(r, e) + } + } + function C(t, r) { + return function (e) { + t.uniform2iv(r, e) + } + } + function W(t, r) { + return function (e) { + t.uniform3iv(r, e) + } + } + function I(t, r) { + return function (e) { + t.uniform4iv(r, e) + } + } + function L(t, r, e, n) { + var i = z(0, r) + return o.isWebGL2(t) + ? function (r) { + var o, a + !r || u.isTexture(t, r) + ? ((o = r), (a = null)) + : ((o = r.texture), (a = r.sampler)), + t.uniform1i(n, e), + t.activeTexture(j + e), + t.bindTexture(i, o), + t.bindSampler(e, a) + } + : function (r) { + t.uniform1i(n, e), + t.activeTexture(j + e), + t.bindTexture(i, r) + } + } + function G(t, r, e, n, i) { + for (var a = z(0, r), f = new Int32Array(i), c = 0; c < i; ++c) + f[c] = e + c + return o.isWebGL2(t) + ? function (r) { + t.uniform1iv(n, f), + r.forEach(function (r, n) { + var o, i + t.activeTexture(j + f[n]), + !r || u.isTexture(t, r) + ? ((o = r), (i = null)) + : ((o = r.texture), (i = r.sampler)), + t.bindSampler(e, i), + t.bindTexture(a, o) + }) + } + : function (r) { + t.uniform1iv(n, f), + r.forEach(function (r, e) { + t.activeTexture(j + f[e]), t.bindTexture(a, r) + }) + } + } + function B(t, r) { + return function (e) { + if (e.value) + switch ( + (t.disableVertexAttribArray(r), e.value.length) + ) { + case 4: + t.vertexAttrib4fv(r, e.value) + break + case 3: + t.vertexAttrib3fv(r, e.value) + break + case 2: + t.vertexAttrib2fv(r, e.value) + break + case 1: + t.vertexAttrib1fv(r, e.value) + break + default: + throw new Error( + 'the length of a float constant value must be between 1 and 4!' + ) + } + else + t.bindBuffer(O, e.buffer), + t.enableVertexAttribArray(r), + t.vertexAttribPointer( + r, + e.numComponents || e.size, + e.type || A, + e.normalize || !1, + e.stride || 0, + e.offset || 0 + ), + t.vertexAttribDivisor && + t.vertexAttribDivisor(r, e.divisor || 0) + } + } + function N(t, r) { + return function (e) { + if (e.value) { + if ( + (t.disableVertexAttribArray(r), + 4 !== e.value.length) + ) + throw new Error( + 'The length of an integer constant value must be 4!' + ) + t.vertexAttrib4iv(r, e.value) + } else + t.bindBuffer(O, e.buffer), + t.enableVertexAttribArray(r), + t.vertexAttribIPointer( + r, + e.numComponents || e.size, + e.type || S, + e.stride || 0, + e.offset || 0 + ), + t.vertexAttribDivisor && + t.vertexAttribDivisor(r, e.divisor || 0) + } + } + function X(t, r) { + return function (e) { + if (e.value) { + if ( + (t.disableVertexAttribArray(r), + 4 !== e.value.length) + ) + throw new Error( + 'The length of an unsigned integer constant value must be 4!' + ) + t.vertexAttrib4uiv(r, e.value) + } else + t.bindBuffer(O, e.buffer), + t.enableVertexAttribArray(r), + t.vertexAttribIPointer( + r, + e.numComponents || e.size, + e.type || M, + e.stride || 0, + e.offset || 0 + ), + t.vertexAttribDivisor && + t.vertexAttribDivisor(r, e.divisor || 0) + } + } + function D(t, r, e) { + var n = e.size, + o = e.count + return function (e) { + t.bindBuffer(O, e.buffer) + for ( + var u = e.size || e.numComponents || n, + i = u / o, + a = e.type || A, + f = R[a].size * u, + c = e.normalize || !1, + l = e.offset || 0, + s = f / o, + v = 0; + v < o; + ++v + ) + t.enableVertexAttribArray(r + v), + t.vertexAttribPointer(r + v, i, a, c, f, l + s * v), + t.vertexAttribDivisor && + t.vertexAttribDivisor(r + v, e.divisor || 0) + } + } + ;(R[5126] = { + Type: Float32Array, + size: 4, + setter: function (t, r) { + return function (e) { + t.uniform1f(r, e) + } + }, + arraySetter: function (t, r) { + return function (e) { + t.uniform1fv(r, e) + } + }, + }), + (R[35664] = { + Type: Float32Array, + size: 8, + setter: function (t, r) { + return function (e) { + t.uniform2fv(r, e) + } + }, + cols: 2, + }), + (R[35665] = { + Type: Float32Array, + size: 12, + setter: function (t, r) { + return function (e) { + t.uniform3fv(r, e) + } + }, + cols: 3, + }), + (R[35666] = { + Type: Float32Array, + size: 16, + setter: function (t, r) { + return function (e) { + t.uniform4fv(r, e) + } + }, + cols: 4, + }), + (R[S] = { + Type: Int32Array, + size: 4, + setter: k, + arraySetter: U, + }), + (R[35667] = { Type: Int32Array, size: 8, setter: C, cols: 2 }), + (R[35668] = { Type: Int32Array, size: 12, setter: W, cols: 3 }), + (R[35669] = { Type: Int32Array, size: 16, setter: I, cols: 4 }), + (R[5125] = { + Type: Uint32Array, + size: 4, + setter: function (t, r) { + return function (e) { + t.uniform1ui(r, e) + } + }, + arraySetter: function (t, r) { + return function (e) { + t.uniform1uiv(r, e) + } + }, + }), + (R[36294] = { + Type: Uint32Array, + size: 8, + setter: function (t, r) { + return function (e) { + t.uniform2uiv(r, e) + } + }, + cols: 2, + }), + (R[36295] = { + Type: Uint32Array, + size: 12, + setter: function (t, r) { + return function (e) { + t.uniform3uiv(r, e) + } + }, + cols: 3, + }), + (R[36296] = { + Type: Uint32Array, + size: 16, + setter: function (t, r) { + return function (e) { + t.uniform4uiv(r, e) + } + }, + cols: 4, + }), + (R[35670] = { + Type: Uint32Array, + size: 4, + setter: k, + arraySetter: U, + }), + (R[35671] = { Type: Uint32Array, size: 8, setter: C, cols: 2 }), + (R[35672] = { + Type: Uint32Array, + size: 12, + setter: W, + cols: 3, + }), + (R[35673] = { + Type: Uint32Array, + size: 16, + setter: I, + cols: 4, + }), + (R[35674] = { + Type: Float32Array, + size: 32, + setter: function (t, r) { + return function (e) { + t.uniformMatrix2fv(r, !1, e) + } + }, + rows: 2, + cols: 2, + }), + (R[35675] = { + Type: Float32Array, + size: 48, + setter: function (t, r) { + return function (e) { + t.uniformMatrix3fv(r, !1, e) + } + }, + rows: 3, + cols: 3, + }), + (R[35676] = { + Type: Float32Array, + size: 64, + setter: function (t, r) { + return function (e) { + t.uniformMatrix4fv(r, !1, e) + } + }, + rows: 4, + cols: 4, + }), + (R[35685] = { + Type: Float32Array, + size: 32, + setter: function (t, r) { + return function (e) { + t.uniformMatrix2x3fv(r, !1, e) + } + }, + rows: 2, + cols: 3, + }), + (R[35686] = { + Type: Float32Array, + size: 32, + setter: function (t, r) { + return function (e) { + t.uniformMatrix2x4fv(r, !1, e) + } + }, + rows: 2, + cols: 4, + }), + (R[35687] = { + Type: Float32Array, + size: 48, + setter: function (t, r) { + return function (e) { + t.uniformMatrix3x2fv(r, !1, e) + } + }, + rows: 3, + cols: 2, + }), + (R[35688] = { + Type: Float32Array, + size: 48, + setter: function (t, r) { + return function (e) { + t.uniformMatrix3x4fv(r, !1, e) + } + }, + rows: 3, + cols: 4, + }), + (R[35689] = { + Type: Float32Array, + size: 64, + setter: function (t, r) { + return function (e) { + t.uniformMatrix4x2fv(r, !1, e) + } + }, + rows: 4, + cols: 2, + }), + (R[35690] = { + Type: Float32Array, + size: 64, + setter: function (t, r) { + return function (e) { + t.uniformMatrix4x3fv(r, !1, e) + } + }, + rows: 4, + cols: 3, + }), + (R[35678] = { + Type: null, + size: 0, + setter: L, + arraySetter: G, + bindPoint: _, + }), + (R[35680] = { + Type: null, + size: 0, + setter: L, + arraySetter: G, + bindPoint: T, + }), + (R[35679] = { + Type: null, + size: 0, + setter: L, + arraySetter: G, + bindPoint: g, + }), + (R[35682] = { + Type: null, + size: 0, + setter: L, + arraySetter: G, + bindPoint: _, + }), + (R[36289] = { + Type: null, + size: 0, + setter: L, + arraySetter: G, + bindPoint: P, + }), + (R[36292] = { + Type: null, + size: 0, + setter: L, + arraySetter: G, + bindPoint: P, + }), + (R[36293] = { + Type: null, + size: 0, + setter: L, + arraySetter: G, + bindPoint: T, + }), + (R[36298] = { + Type: null, + size: 0, + setter: L, + arraySetter: G, + bindPoint: _, + }), + (R[36299] = { + Type: null, + size: 0, + setter: L, + arraySetter: G, + bindPoint: g, + }), + (R[36300] = { + Type: null, + size: 0, + setter: L, + arraySetter: G, + bindPoint: T, + }), + (R[36303] = { + Type: null, + size: 0, + setter: L, + arraySetter: G, + bindPoint: P, + }), + (R[36306] = { + Type: null, + size: 0, + setter: L, + arraySetter: G, + bindPoint: _, + }), + (R[36307] = { + Type: null, + size: 0, + setter: L, + arraySetter: G, + bindPoint: g, + }), + (R[36308] = { + Type: null, + size: 0, + setter: L, + arraySetter: G, + bindPoint: T, + }), + (R[36311] = { + Type: null, + size: 0, + setter: L, + arraySetter: G, + bindPoint: P, + }) + var H = {} + ;(H[5126] = { size: 4, setter: B }), + (H[35664] = { size: 8, setter: B }), + (H[35665] = { size: 12, setter: B }), + (H[35666] = { size: 16, setter: B }), + (H[S] = { size: 4, setter: N }), + (H[35667] = { size: 8, setter: N }), + (H[35668] = { size: 12, setter: N }), + (H[35669] = { size: 16, setter: N }), + (H[5125] = { size: 4, setter: X }), + (H[36294] = { size: 8, setter: X }), + (H[36295] = { size: 12, setter: X }), + (H[36296] = { size: 16, setter: X }), + (H[35670] = { size: 4, setter: N }), + (H[35671] = { size: 8, setter: N }), + (H[35672] = { size: 12, setter: N }), + (H[35673] = { size: 16, setter: N }), + (H[35674] = { size: 4, setter: D, count: 2 }), + (H[35675] = { size: 9, setter: D, count: 3 }), + (H[35676] = { size: 16, setter: D, count: 4 }) + var V = /ERROR:\s*\d+:(\d+)/gi + var Y = /^[ \t]*\n/ + function q(t) { + var r = 0 + return ( + Y.test(t) && ((r = 1), (t = t.replace(Y, ''))), + { lineOffset: r, shaderSource: t } + ) + } + function K(t, r) { + return ( + t.errorCallback(r), + t.callback && + setTimeout(function () { + t.callback( + ''.concat(r, '\n').concat(t.errors.join('\n')) + ) + }), + null + ) + } + function $(t, r, e, n) { + if (((n = n || w), !t.getShaderParameter(e, 35713))) { + var u = t.getShaderInfoLog(e), + i = q(t.getShaderSource(e)), + a = i.lineOffset, + f = i.shaderSource, + c = '' + .concat( + (function (t) { + var r = + arguments.length > 1 && + void 0 !== arguments[1] + ? arguments[1] + : '', + e = + arguments.length > 2 && + void 0 !== arguments[2] + ? arguments[2] + : 0, + n = d(r.matchAll(V)), + o = new Map( + n.map(function (t, e) { + var o = parseInt(t[1]), + u = n[e + 1], + i = u ? u.index : r.length + return [ + o - 1, + r.substring(t.index, i), + ] + }) + ) + return t + .split('\n') + .map(function (t, r) { + var n = o.get(r) + return '' + .concat(r + 1 + e, ': ') + .concat(t) + .concat( + n + ? '\n\n^^^ '.concat(n) + : '' + ) + }) + .join('\n') + })(f, u, a), + '\nError compiling ' + ) + .concat(o.glEnumToString(t, r), ': ') + .concat(u) + return n(c), c + } + return '' + } + function Z(t, r, e) { + var n, o, u + if ( + ('function' == typeof r && ((e = r), (r = void 0)), + 'function' == typeof t) + ) + (e = t), (t = void 0) + else if (t && !Array.isArray(t)) { + var i = t + ;(e = i.errorCallback), + (t = i.attribLocations), + (n = i.transformFeedbackVaryings), + (o = i.transformFeedbackMode), + (u = i.callback) + } + var a = e || w, + f = [], + c = { + errorCallback: function (t) { + f.push(t) + for ( + var r = arguments.length, + e = new Array(r > 1 ? r - 1 : 0), + n = 1; + n < r; + n++ + ) + e[n - 1] = arguments[n] + a.apply(void 0, [t].concat(e)) + }, + transformFeedbackVaryings: n, + transformFeedbackMode: o, + callback: u, + errors: f, + }, + l = {} + return ( + Array.isArray(t) + ? t.forEach(function (t, e) { + l[t] = r ? r[e] : e + }) + : (l = t || {}), + (c.attribLocations = l), + c + ) + } + var J = ['VERTEX_SHADER', 'FRAGMENT_SHADER'] + var Q = function () { + var t = + arguments.length > 0 && void 0 !== arguments[0] + ? arguments[0] + : 0 + return new Promise(function (r) { + return setTimeout(r, t) + }) + } + function tt(t, r, e) { + for ( + var n, + o = t.createProgram(), + u = Z(e), + i = u.attribLocations, + a = u.transformFeedbackVaryings, + f = u.transformFeedbackMode, + c = 0; + c < r.length; + ++c + ) { + var l = r[c] + if ('string' == typeof l) { + var s = F(l), + v = s ? s.text : l, + y = t[J[c]] + s && + s.type && + (y = + ((n = s.type).indexOf('frag') >= 0 + ? 35632 + : n.indexOf('vert') >= 0 + ? 35633 + : void 0) || y), + (l = t.createShader(y)), + t.shaderSource(l, q(v).shaderSource), + t.compileShader(l), + t.attachShader(o, l) + } + } + Object.entries(i).forEach(function (r) { + var e = b(r, 2), + n = e[0], + u = e[1] + return t.bindAttribLocation(o, u, n) + }) + var m = a + return ( + m && + (m.attribs && (m = m.attribs), + Array.isArray(m) || (m = Object.keys(m)), + t.transformFeedbackVaryings(o, m, f || 35981)), + t.linkProgram(o), + o + ) + } + function rt(t, r, e, n, o) { + var u = Z(e, n, o), + i = new Set(r), + a = tt(t, r, u) + function f(t, r) { + var e = ct(t, r, u.errorCallback) + return ( + e && + (function (t, r, e) { + var n, + o = m(t.getAttachedShaders(r)) + try { + for (o.s(); !(n = o.n()).done; ) { + var u = n.value + e.has(u) && t.deleteShader(u) + } + } catch (t) { + o.e(t) + } finally { + o.f() + } + t.deleteProgram(r) + })(t, r, i), + e + ) + } + if (!u.callback) return f(t, a) ? void 0 : a + ut(t, a).then(function () { + var r = f(t, a) + u.callback(r, r ? void 0 : a) + }) + } + function et(t) { + return function (r, e) { + for ( + var n = arguments.length, + o = new Array(n > 2 ? n - 2 : 0), + u = 2; + u < n; + u++ + ) + o[u - 2] = arguments[u] + return new Promise(function (n, u) { + var i = Z.apply(void 0, o) + ;(i.callback = function (t, r) { + t ? u(t) : n(r) + }), + t(r, e, i) + }) + } + } + var nt = et(rt) + r.createProgramAsync = nt + var ot = et(_t) + function ut(t, r) { + return it.apply(this, arguments) + } + function it() { + return (it = y( + f().mark(function t(r, e) { + var n, o, u + return f().wrap(function (t) { + for (;;) + switch ((t.prev = t.next)) { + case 0: + ;(n = r.getExtension( + 'KHR_parallel_shader_compile' + )), + (o = n + ? function (t, r) { + return t.getProgramParameter( + r, + n.COMPLETION_STATUS_KHR + ) + } + : function () { + return !0 + }), + (u = 0) + case 3: + return (t.next = 5), Q(u) + case 5: + u = 1e3 / 60 + case 6: + if (!o(r, e)) { + t.next = 3 + break + } + case 7: + case 'end': + return t.stop() + } + }, t) + }) + )).apply(this, arguments) + } + function at(t, r) { + return ft.apply(this, arguments) + } + function ft() { + return (ft = y( + f().mark(function t(r, e) { + var n, o, u + return f().wrap(function (t) { + for (;;) + switch ((t.prev = t.next)) { + case 0: + ;(n = 0), (o = Object.values(e)) + case 1: + if (!(n < o.length)) { + t.next = 8 + break + } + return ( + (u = o[n]), (t.next = 5), ut(r, u) + ) + case 5: + n++, (t.next = 1) + break + case 8: + case 'end': + return t.stop() + } + }, t) + }) + )).apply(this, arguments) + } + function ct(t, r, e) { + if (((e = e || w), !t.getProgramParameter(r, 35714))) { + var n = t.getProgramInfoLog(r) + e('Error in program linking: '.concat(n)) + var o = t.getAttachedShaders(r).map(function (r) { + return $( + t, + t.getShaderParameter(r, t.SHADER_TYPE), + r, + e + ) + }) + return ''.concat(n, '\n').concat( + o + .filter(function (t) { + return t + }) + .join('\n') + ) + } + } + function lt(t, r, e, n, o) { + return rt(t, r, e, n, o) + } + function st(t) { + var r = t.name + return r.startsWith('gl_') || r.startsWith('webgl_') + } + r.createProgramInfoAsync = ot + var vt = /(\.|\[|]|\w+)/g + function yt(t, r, e, n) { + for ( + var o, + u = t.split(vt).filter(function (t) { + return '' !== t + }), + i = 0, + a = ''; + ; + + ) { + var f = u[i++] + a += f + var c = (o = f[0]) >= '0' && o <= '9', + l = c ? parseInt(f) : f + if ((c && (a += u[i++]), i === u.length)) { + e[l] = r + break + } + var s = u[i++], + v = '[' === s, + y = e[l] || (v ? [] : {}) + ;(e[l] = y), + (e = y), + (n[a] = + n[a] || + (function (t) { + return function (r) { + Ft(t, r) + } + })(y)), + (a += s) + } + } + function bt(t, r) { + var e = 0 + function n(r, n, o) { + var u, + i = n.name.endsWith('[0]'), + a = n.type, + f = R[a] + if (!f) + throw new Error( + 'unknown type: 0x'.concat(a.toString(16)) + ) + if (f.bindPoint) { + var c = e + ;(e += n.size), + (u = i + ? f.arraySetter(t, a, c, o, n.size) + : f.setter(t, a, c, o, n.size)) + } else + u = + f.arraySetter && i + ? f.arraySetter(t, o) + : f.setter(t, o) + return (u.location = o), u + } + for ( + var o = {}, + u = {}, + i = t.getProgramParameter(r, 35718), + a = 0; + a < i; + ++a + ) { + var f = t.getActiveUniform(r, a) + if (!st(f)) { + var c = f.name + c.endsWith('[0]') && (c = c.substr(0, c.length - 3)) + var l = t.getUniformLocation(r, f.name) + if (l) { + var s = n(0, f, l) + ;(o[c] = s), yt(c, s, u, o) + } + } + } + return o + } + function mt(t, r) { + for ( + var e = {}, n = t.getProgramParameter(r, 35971), o = 0; + o < n; + ++o + ) { + var u = t.getTransformFeedbackVarying(r, o) + e[u.name] = { index: o, type: u.type, size: u.size } + } + return e + } + function dt(t, r, e) { + for (var n in (r.transformFeedbackInfo && + (r = r.transformFeedbackInfo), + e.attribs && (e = e.attribs), + e)) { + var o = r[n] + if (o) { + var u = e[n] + u.offset + ? t.bindBufferRange( + 35982, + o.index, + u.buffer, + u.offset, + u.size + ) + : t.bindBufferBase(35982, o.index, u.buffer) + } + } + } + function pt(t, r) { + for ( + var e = t.getProgramParameter(r, 35718), + n = [], + o = [], + u = 0; + u < e; + ++u + ) { + o.push(u), n.push({}) + var i = t.getActiveUniform(r, u) + n[u].name = i.name + } + ;[ + ['UNIFORM_TYPE', 'type'], + ['UNIFORM_SIZE', 'size'], + ['UNIFORM_BLOCK_INDEX', 'blockNdx'], + ['UNIFORM_OFFSET', 'offset'], + ].forEach(function (e) { + var u = e[0], + i = e[1] + t.getActiveUniforms(r, o, t[u]).forEach(function (t, r) { + n[r][i] = t + }) + }) + for ( + var a = {}, f = t.getProgramParameter(r, 35382), c = 0; + c < f; + ++c + ) { + var l = t.getActiveUniformBlockName(r, c), + s = { + index: t.getUniformBlockIndex(r, l), + usedByVertexShader: + t.getActiveUniformBlockParameter(r, c, 35396), + usedByFragmentShader: + t.getActiveUniformBlockParameter(r, c, 35398), + size: t.getActiveUniformBlockParameter(r, c, 35392), + uniformIndices: t.getActiveUniformBlockParameter( + r, + c, + 35395 + ), + } + ;(s.used = s.usedByVertexShader || s.usedByFragmentShader), + (a[l] = s) + } + return { blockSpecs: a, uniformData: n } + } + var ht = /\[\d+\]\.$/ + function wt(t, r, e, n) { + var o = e.blockSpecs, + u = e.uniformData, + i = o[n] + if (!i) + return ( + x('no uniform block object named:', n), + { name: n, uniforms: {} } + ) + var a = new ArrayBuffer(i.size), + f = t.createBuffer(), + c = i.index + t.bindBuffer(E, f), t.uniformBlockBinding(r, i.index, c) + var l = n + '.' + ht.test(l) && (l = l.replace(ht, '.')) + var s = {}, + v = {}, + y = {} + return ( + i.uniformIndices.forEach(function (t) { + var r = u[t], + e = r.name + e.startsWith(l) && (e = e.substr(l.length)) + var n = e.endsWith('[0]') + n && (e = e.substr(0, e.length - 3)) + var o, + i = R[r.type], + f = i.Type, + c = n + ? (((i.size + ((o = 16) - 1)) / o) | 0) * + o * + r.size + : i.size * r.size, + b = new f(a, r.offset, c / f.BYTES_PER_ELEMENT) + s[e] = b + var m = (function (t, r, e, n) { + if (r || e) { + n = n || 1 + var o = t.length / 4 + return function (r) { + for (var e = 0, u = 0, i = 0; i < o; ++i) { + for (var a = 0; a < n; ++a) + t[e++] = r[u++] + e += 4 - n + } + } + } + return function (r) { + r.length ? t.set(r) : (t[0] = r) + } + })(b, n, i.rows, i.cols) + ;(v[e] = m), yt(e, m, y, v) + }), + { + name: n, + array: a, + asFloat: new Float32Array(a), + buffer: f, + uniforms: s, + setters: v, + } + ) + } + function xt(t, r, e) { + var n = (r.uniformBlockSpec || r).blockSpecs[e.name] + if (n) { + var o = n.index + return ( + t.bindBufferRange( + E, + o, + e.buffer, + e.offset || 0, + e.array.byteLength + ), + !0 + ) + } + return !1 + } + function Ft(t, r) { + for (var e in r) { + var n = t[e] + 'function' == typeof n ? n(r[e]) : Ft(t[e], r[e]) + } + } + function jt(t) { + for ( + var r = t.uniformSetters || t, + e = arguments.length <= 1 ? 0 : arguments.length - 1, + n = 0; + n < e; + ++n + ) { + var o = + n + 1 < 1 || arguments.length <= n + 1 + ? void 0 + : arguments[n + 1] + if (Array.isArray(o)) + for (var u = o.length, i = 0; i < u; ++i) jt(r, o[i]) + else + for (var a in o) { + var f = r[a] + f && f(o[a]) + } + } + } + var Ot = jt + function Et(t, r) { + for ( + var e = {}, n = t.getProgramParameter(r, 35721), o = 0; + o < n; + ++o + ) { + var u = t.getActiveAttrib(r, o) + if (!st(u)) { + var i = t.getAttribLocation(r, u.name), + a = H[u.type], + f = a.setter(t, i, a) + ;(f.location = i), (e[u.name] = f) + } + } + return e + } + function At(t, r) { + for (var e in r) { + var n = t[e] + n && n(r[e]) + } + } + function St(t, r) { + var e = { + program: r, + uniformSetters: bt(t, r), + attribSetters: Et(t, r), + } + return ( + o.isWebGL2(t) && + ((e.uniformBlockSpec = pt(t, r)), + (e.transformFeedbackInfo = mt(t, r))), + e + ) + } + r.setUniformsAndBindTextures = Ot + var Mt = /\s|{|}|;/ + function _t(t, r, e, n, o) { + var u = Z(e, n, o), + i = [] + if ( + ((r = r.map(function (t) { + if (!Mt.test(t)) { + var r = F(t) + if (r) t = r.text + else { + var e = 'no element with id: '.concat(t) + u.errorCallback(e), i.push(e) + } + } + return t + })), + i.length) + ) + return K(u, '') + var a = u.callback + a && + (u.callback = function (r, e) { + a(r, r ? void 0 : St(t, e)) + }) + var f = lt(t, r, u) + return f ? St(t, f) : null + } + function Tt(t, r, e, n, o) { + for (var u = 0, i = Object.entries(r); u < i.length; u++) { + var a = b(i[u], 2), + f = a[0], + c = a[1], + s = l({}, o), + v = e[f] + Array.isArray(v) || Object.assign(s, v) + var y = ct(t, c, s.errorCallback) + if (y) { + for ( + var d = 0, p = Object.values(r); + d < p.length; + d++ + ) { + var h = p[d], + w = t.getAttachedShaders(h) + t.deleteProgram(h) + var x, + F = m(w) + try { + for (F.s(); !(x = F.n()).done; ) { + var j = x.value + n.has(j) || t.deleteShader(j) + } + } catch (t) { + F.e(t) + } finally { + F.f() + } + } + return y + } + } + } + function gt(t, r) { + var e = + arguments.length > 2 && void 0 !== arguments[2] + ? arguments[2] + : {}, + n = new Set(), + o = Object.fromEntries( + Object.entries(r).map(function (r) { + var o = b(r, 2), + u = o[0], + i = o[1], + a = l({}, e), + f = Array.isArray(i) ? i : i.shaders + return ( + Array.isArray(i) || Object.assign(a, i), + f.forEach(n.add, n), + [u, tt(t, f, a)] + ) + }) + ) + if (!e.callback) { + var u = Tt(t, o, r, n, e) + return u ? void 0 : o + } + at(t, o).then(function () { + var u = Tt(t, o, r, n, e) + e.callback(u, u ? void 0 : o) + }) + } + function Pt(t, r, e) { + function n(t, r) { + return Object.fromEntries( + Object.entries(r).map(function (r) { + var e = b(r, 2), + n = e[0], + o = e[1] + return [n, St(t, o)] + }) + ) + } + var o = (e = Z(e)).callback + o && + (e.callback = function (r, e) { + o(r, r ? void 0 : n(t, e)) + }) + var u = gt(t, r, e) + if (!o && u) return n(t, u) + } + var Rt = et(gt) + r.createProgramsAsync = Rt + var zt = et(Pt) + r.createProgramInfosAsync = zt + }, + function (t, r, e) { + 'use strict' + function n(t) { + return (n = + 'function' == typeof Symbol && + 'symbol' == typeof Symbol.iterator + ? function (t) { + return typeof t + } + : function (t) { + return t && + 'function' == typeof Symbol && + t.constructor === Symbol && + t !== Symbol.prototype + ? 'symbol' + : typeof t + })(t) + } + ;(r.__esModule = !0), + (r.axisRotate = function (t, r, e, n) { + n = n || new c(16) + var o = r[0], + u = r[1], + i = r[2], + a = Math.sqrt(o * o + u * u + i * i), + f = (o /= a) * o, + l = (u /= a) * u, + s = (i /= a) * i, + v = Math.cos(e), + y = Math.sin(e), + b = 1 - v, + m = f + (1 - f) * v, + d = o * u * b + i * y, + p = o * i * b - u * y, + h = o * u * b - i * y, + w = l + (1 - l) * v, + x = u * i * b + o * y, + F = o * i * b + u * y, + j = u * i * b - o * y, + O = s + (1 - s) * v, + E = t[0], + A = t[1], + S = t[2], + M = t[3], + _ = t[4], + T = t[5], + g = t[6], + P = t[7], + R = t[8], + z = t[9], + k = t[10], + U = t[11] + ;(n[0] = m * E + d * _ + p * R), + (n[1] = m * A + d * T + p * z), + (n[2] = m * S + d * g + p * k), + (n[3] = m * M + d * P + p * U), + (n[4] = h * E + w * _ + x * R), + (n[5] = h * A + w * T + x * z), + (n[6] = h * S + w * g + x * k), + (n[7] = h * M + w * P + x * U), + (n[8] = F * E + j * _ + O * R), + (n[9] = F * A + j * T + O * z), + (n[10] = F * S + j * g + O * k), + (n[11] = F * M + j * P + O * U), + t !== n && + ((n[12] = t[12]), + (n[13] = t[13]), + (n[14] = t[14]), + (n[15] = t[15])) + return n + }), + (r.axisRotation = function (t, r, e) { + e = e || new c(16) + var n = t[0], + o = t[1], + u = t[2], + i = Math.sqrt(n * n + o * o + u * u), + a = (n /= i) * n, + f = (o /= i) * o, + l = (u /= i) * u, + s = Math.cos(r), + v = Math.sin(r), + y = 1 - s + return ( + (e[0] = a + (1 - a) * s), + (e[1] = n * o * y + u * v), + (e[2] = n * u * y - o * v), + (e[3] = 0), + (e[4] = n * o * y - u * v), + (e[5] = f + (1 - f) * s), + (e[6] = o * u * y + n * v), + (e[7] = 0), + (e[8] = n * u * y + o * v), + (e[9] = o * u * y - n * v), + (e[10] = l + (1 - l) * s), + (e[11] = 0), + (e[12] = 0), + (e[13] = 0), + (e[14] = 0), + (e[15] = 1), + e + ) + }), + (r.copy = l), + (r.create = function () { + return new c(16).fill(0) + }), + (r.frustum = function (t, r, e, n, o, u, i) { + i = i || new c(16) + var a = r - t, + f = n - e, + l = o - u + return ( + (i[0] = (2 * o) / a), + (i[1] = 0), + (i[2] = 0), + (i[3] = 0), + (i[4] = 0), + (i[5] = (2 * o) / f), + (i[6] = 0), + (i[7] = 0), + (i[8] = (t + r) / a), + (i[9] = (n + e) / f), + (i[10] = u / l), + (i[11] = -1), + (i[12] = 0), + (i[13] = 0), + (i[14] = (o * u) / l), + (i[15] = 0), + i + ) + }), + (r.getAxis = function (t, r, e) { + e = e || o.create() + var n = 4 * r + return ( + (e[0] = t[n + 0]), + (e[1] = t[n + 1]), + (e[2] = t[n + 2]), + e + ) + }), + (r.getTranslation = function (t, r) { + return ( + ((r = r || o.create())[0] = t[12]), + (r[1] = t[13]), + (r[2] = t[14]), + r + ) + }), + (r.identity = s), + (r.inverse = v), + (r.lookAt = function (t, r, e, n) { + return ( + (n = n || new c(16)), + (i = i || o.create()), + (a = a || o.create()), + (f = f || o.create()), + o.normalize(o.subtract(t, r, f), f), + o.normalize(o.cross(e, f, i), i), + o.normalize(o.cross(f, i, a), a), + (n[0] = i[0]), + (n[1] = i[1]), + (n[2] = i[2]), + (n[3] = 0), + (n[4] = a[0]), + (n[5] = a[1]), + (n[6] = a[2]), + (n[7] = 0), + (n[8] = f[0]), + (n[9] = f[1]), + (n[10] = f[2]), + (n[11] = 0), + (n[12] = t[0]), + (n[13] = t[1]), + (n[14] = t[2]), + (n[15] = 1), + n + ) + }), + (r.multiply = function (t, r, e) { + e = e || new c(16) + var n = t[0], + o = t[1], + u = t[2], + i = t[3], + a = t[4], + f = t[5], + l = t[6], + s = t[7], + v = t[8], + y = t[9], + b = t[10], + m = t[11], + d = t[12], + p = t[13], + h = t[14], + w = t[15], + x = r[0], + F = r[1], + j = r[2], + O = r[3], + E = r[4], + A = r[5], + S = r[6], + M = r[7], + _ = r[8], + T = r[9], + g = r[10], + P = r[11], + R = r[12], + z = r[13], + k = r[14], + U = r[15] + return ( + (e[0] = n * x + a * F + v * j + d * O), + (e[1] = o * x + f * F + y * j + p * O), + (e[2] = u * x + l * F + b * j + h * O), + (e[3] = i * x + s * F + m * j + w * O), + (e[4] = n * E + a * A + v * S + d * M), + (e[5] = o * E + f * A + y * S + p * M), + (e[6] = u * E + l * A + b * S + h * M), + (e[7] = i * E + s * A + m * S + w * M), + (e[8] = n * _ + a * T + v * g + d * P), + (e[9] = o * _ + f * T + y * g + p * P), + (e[10] = u * _ + l * T + b * g + h * P), + (e[11] = i * _ + s * T + m * g + w * P), + (e[12] = n * R + a * z + v * k + d * U), + (e[13] = o * R + f * z + y * k + p * U), + (e[14] = u * R + l * z + b * k + h * U), + (e[15] = i * R + s * z + m * k + w * U), + e + ) + }), + (r.negate = function (t, r) { + return ( + ((r = r || new c(16))[0] = -t[0]), + (r[1] = -t[1]), + (r[2] = -t[2]), + (r[3] = -t[3]), + (r[4] = -t[4]), + (r[5] = -t[5]), + (r[6] = -t[6]), + (r[7] = -t[7]), + (r[8] = -t[8]), + (r[9] = -t[9]), + (r[10] = -t[10]), + (r[11] = -t[11]), + (r[12] = -t[12]), + (r[13] = -t[13]), + (r[14] = -t[14]), + (r[15] = -t[15]), + r + ) + }), + (r.ortho = function (t, r, e, n, o, u, i) { + return ( + ((i = i || new c(16))[0] = 2 / (r - t)), + (i[1] = 0), + (i[2] = 0), + (i[3] = 0), + (i[4] = 0), + (i[5] = 2 / (n - e)), + (i[6] = 0), + (i[7] = 0), + (i[8] = 0), + (i[9] = 0), + (i[10] = 2 / (o - u)), + (i[11] = 0), + (i[12] = (r + t) / (t - r)), + (i[13] = (n + e) / (e - n)), + (i[14] = (u + o) / (o - u)), + (i[15] = 1), + i + ) + }), + (r.perspective = function (t, r, e, n, o) { + o = o || new c(16) + var u = Math.tan(0.5 * Math.PI - 0.5 * t), + i = 1 / (e - n) + return ( + (o[0] = u / r), + (o[1] = 0), + (o[2] = 0), + (o[3] = 0), + (o[4] = 0), + (o[5] = u), + (o[6] = 0), + (o[7] = 0), + (o[8] = 0), + (o[9] = 0), + (o[10] = (e + n) * i), + (o[11] = -1), + (o[12] = 0), + (o[13] = 0), + (o[14] = e * n * i * 2), + (o[15] = 0), + o + ) + }), + (r.rotateX = function (t, r, e) { + e = e || new c(16) + var n = t[4], + o = t[5], + u = t[6], + i = t[7], + a = t[8], + f = t[9], + l = t[10], + s = t[11], + v = Math.cos(r), + y = Math.sin(r) + ;(e[4] = v * n + y * a), + (e[5] = v * o + y * f), + (e[6] = v * u + y * l), + (e[7] = v * i + y * s), + (e[8] = v * a - y * n), + (e[9] = v * f - y * o), + (e[10] = v * l - y * u), + (e[11] = v * s - y * i), + t !== e && + ((e[0] = t[0]), + (e[1] = t[1]), + (e[2] = t[2]), + (e[3] = t[3]), + (e[12] = t[12]), + (e[13] = t[13]), + (e[14] = t[14]), + (e[15] = t[15])) + return e + }), + (r.rotateY = function (t, r, e) { + e = e || new c(16) + var n = t[0], + o = t[1], + u = t[2], + i = t[3], + a = t[8], + f = t[9], + l = t[10], + s = t[11], + v = Math.cos(r), + y = Math.sin(r) + ;(e[0] = v * n - y * a), + (e[1] = v * o - y * f), + (e[2] = v * u - y * l), + (e[3] = v * i - y * s), + (e[8] = v * a + y * n), + (e[9] = v * f + y * o), + (e[10] = v * l + y * u), + (e[11] = v * s + y * i), + t !== e && + ((e[4] = t[4]), + (e[5] = t[5]), + (e[6] = t[6]), + (e[7] = t[7]), + (e[12] = t[12]), + (e[13] = t[13]), + (e[14] = t[14]), + (e[15] = t[15])) + return e + }), + (r.rotateZ = function (t, r, e) { + e = e || new c(16) + var n = t[0], + o = t[1], + u = t[2], + i = t[3], + a = t[4], + f = t[5], + l = t[6], + s = t[7], + v = Math.cos(r), + y = Math.sin(r) + ;(e[0] = v * n + y * a), + (e[1] = v * o + y * f), + (e[2] = v * u + y * l), + (e[3] = v * i + y * s), + (e[4] = v * a - y * n), + (e[5] = v * f - y * o), + (e[6] = v * l - y * u), + (e[7] = v * s - y * i), + t !== e && + ((e[8] = t[8]), + (e[9] = t[9]), + (e[10] = t[10]), + (e[11] = t[11]), + (e[12] = t[12]), + (e[13] = t[13]), + (e[14] = t[14]), + (e[15] = t[15])) + return e + }), + (r.rotationX = function (t, r) { + r = r || new c(16) + var e = Math.cos(t), + n = Math.sin(t) + return ( + (r[0] = 1), + (r[1] = 0), + (r[2] = 0), + (r[3] = 0), + (r[4] = 0), + (r[5] = e), + (r[6] = n), + (r[7] = 0), + (r[8] = 0), + (r[9] = -n), + (r[10] = e), + (r[11] = 0), + (r[12] = 0), + (r[13] = 0), + (r[14] = 0), + (r[15] = 1), + r + ) + }), + (r.rotationY = function (t, r) { + r = r || new c(16) + var e = Math.cos(t), + n = Math.sin(t) + return ( + (r[0] = e), + (r[1] = 0), + (r[2] = -n), + (r[3] = 0), + (r[4] = 0), + (r[5] = 1), + (r[6] = 0), + (r[7] = 0), + (r[8] = n), + (r[9] = 0), + (r[10] = e), + (r[11] = 0), + (r[12] = 0), + (r[13] = 0), + (r[14] = 0), + (r[15] = 1), + r + ) + }), + (r.rotationZ = function (t, r) { + r = r || new c(16) + var e = Math.cos(t), + n = Math.sin(t) + return ( + (r[0] = e), + (r[1] = n), + (r[2] = 0), + (r[3] = 0), + (r[4] = -n), + (r[5] = e), + (r[6] = 0), + (r[7] = 0), + (r[8] = 0), + (r[9] = 0), + (r[10] = 1), + (r[11] = 0), + (r[12] = 0), + (r[13] = 0), + (r[14] = 0), + (r[15] = 1), + r + ) + }), + (r.scale = function (t, r, e) { + e = e || new c(16) + var n = r[0], + o = r[1], + u = r[2] + ;(e[0] = n * t[0]), + (e[1] = n * t[1]), + (e[2] = n * t[2]), + (e[3] = n * t[3]), + (e[4] = o * t[4]), + (e[5] = o * t[5]), + (e[6] = o * t[6]), + (e[7] = o * t[7]), + (e[8] = u * t[8]), + (e[9] = u * t[9]), + (e[10] = u * t[10]), + (e[11] = u * t[11]), + t !== e && + ((e[12] = t[12]), + (e[13] = t[13]), + (e[14] = t[14]), + (e[15] = t[15])) + return e + }), + (r.scaling = function (t, r) { + return ( + ((r = r || new c(16))[0] = t[0]), + (r[1] = 0), + (r[2] = 0), + (r[3] = 0), + (r[4] = 0), + (r[5] = t[1]), + (r[6] = 0), + (r[7] = 0), + (r[8] = 0), + (r[9] = 0), + (r[10] = t[2]), + (r[11] = 0), + (r[12] = 0), + (r[13] = 0), + (r[14] = 0), + (r[15] = 1), + r + ) + }), + (r.setAxis = function (t, r, e, n) { + n !== t && (n = l(t, n)) + var o = 4 * e + return ( + (n[o + 0] = r[0]), + (n[o + 1] = r[1]), + (n[o + 2] = r[2]), + n + ) + }), + (r.setDefaultType = function (t) { + var r = c + return (c = t), r + }), + (r.setTranslation = function (t, r, e) { + ;(e = e || s()), + t !== e && + ((e[0] = t[0]), + (e[1] = t[1]), + (e[2] = t[2]), + (e[3] = t[3]), + (e[4] = t[4]), + (e[5] = t[5]), + (e[6] = t[6]), + (e[7] = t[7]), + (e[8] = t[8]), + (e[9] = t[9]), + (e[10] = t[10]), + (e[11] = t[11])) + return ( + (e[12] = r[0]), + (e[13] = r[1]), + (e[14] = r[2]), + (e[15] = 1), + e + ) + }), + (r.transformDirection = function (t, r, e) { + e = e || o.create() + var n = r[0], + u = r[1], + i = r[2] + return ( + (e[0] = n * t[0] + u * t[4] + i * t[8]), + (e[1] = n * t[1] + u * t[5] + i * t[9]), + (e[2] = n * t[2] + u * t[6] + i * t[10]), + e + ) + }), + (r.transformNormal = function (t, r, e) { + e = e || o.create() + var n = v(t), + u = r[0], + i = r[1], + a = r[2] + return ( + (e[0] = u * n[0] + i * n[1] + a * n[2]), + (e[1] = u * n[4] + i * n[5] + a * n[6]), + (e[2] = u * n[8] + i * n[9] + a * n[10]), + e + ) + }), + (r.transformPoint = function (t, r, e) { + e = e || o.create() + var n = r[0], + u = r[1], + i = r[2], + a = n * t[3] + u * t[7] + i * t[11] + t[15] + return ( + (e[0] = (n * t[0] + u * t[4] + i * t[8] + t[12]) / a), + (e[1] = (n * t[1] + u * t[5] + i * t[9] + t[13]) / a), + (e[2] = (n * t[2] + u * t[6] + i * t[10] + t[14]) / a), + e + ) + }), + (r.translate = function (t, r, e) { + e = e || new c(16) + var n = r[0], + o = r[1], + u = r[2], + i = t[0], + a = t[1], + f = t[2], + l = t[3], + s = t[4], + v = t[5], + y = t[6], + b = t[7], + m = t[8], + d = t[9], + p = t[10], + h = t[11], + w = t[12], + x = t[13], + F = t[14], + j = t[15] + t !== e && + ((e[0] = i), + (e[1] = a), + (e[2] = f), + (e[3] = l), + (e[4] = s), + (e[5] = v), + (e[6] = y), + (e[7] = b), + (e[8] = m), + (e[9] = d), + (e[10] = p), + (e[11] = h)) + return ( + (e[12] = i * n + s * o + m * u + w), + (e[13] = a * n + v * o + d * u + x), + (e[14] = f * n + y * o + p * u + F), + (e[15] = l * n + b * o + h * u + j), + e + ) + }), + (r.translation = function (t, r) { + return ( + ((r = r || new c(16))[0] = 1), + (r[1] = 0), + (r[2] = 0), + (r[3] = 0), + (r[4] = 0), + (r[5] = 1), + (r[6] = 0), + (r[7] = 0), + (r[8] = 0), + (r[9] = 0), + (r[10] = 1), + (r[11] = 0), + (r[12] = t[0]), + (r[13] = t[1]), + (r[14] = t[2]), + (r[15] = 1), + r + ) + }), + (r.transpose = function (t, r) { + if ((r = r || new c(16)) === t) { + var e + return ( + (e = t[1]), + (t[1] = t[4]), + (t[4] = e), + (e = t[2]), + (t[2] = t[8]), + (t[8] = e), + (e = t[3]), + (t[3] = t[12]), + (t[12] = e), + (e = t[6]), + (t[6] = t[9]), + (t[9] = e), + (e = t[7]), + (t[7] = t[13]), + (t[13] = e), + (e = t[11]), + (t[11] = t[14]), + (t[14] = e), + r + ) + } + var n = t[0], + o = t[1], + u = t[2], + i = t[3], + a = t[4], + f = t[5], + l = t[6], + s = t[7], + v = t[8], + y = t[9], + b = t[10], + m = t[11], + d = t[12], + p = t[13], + h = t[14], + w = t[15] + return ( + (r[0] = n), + (r[1] = a), + (r[2] = v), + (r[3] = d), + (r[4] = o), + (r[5] = f), + (r[6] = y), + (r[7] = p), + (r[8] = u), + (r[9] = l), + (r[10] = b), + (r[11] = h), + (r[12] = i), + (r[13] = s), + (r[14] = m), + (r[15] = w), + r + ) + }) + var o = (function (t, r) { + if (!r && t && t.__esModule) return t + if (null === t || ('object' !== n(t) && 'function' != typeof t)) + return { default: t } + var e = u(r) + if (e && e.has(t)) return e.get(t) + var o = {}, + i = Object.defineProperty && Object.getOwnPropertyDescriptor + for (var a in t) + if ( + 'default' !== a && + Object.prototype.hasOwnProperty.call(t, a) + ) { + var f = i ? Object.getOwnPropertyDescriptor(t, a) : null + f && (f.get || f.set) + ? Object.defineProperty(o, a, f) + : (o[a] = t[a]) + } + ;(o.default = t), e && e.set(t, o) + return o + })(e(2)) + function u(t) { + if ('function' != typeof WeakMap) return null + var r = new WeakMap(), + e = new WeakMap() + return (u = function (t) { + return t ? e : r + })(t) + } + var i, + a, + f, + c = Float32Array + function l(t, r) { + return ( + ((r = r || new c(16))[0] = t[0]), + (r[1] = t[1]), + (r[2] = t[2]), + (r[3] = t[3]), + (r[4] = t[4]), + (r[5] = t[5]), + (r[6] = t[6]), + (r[7] = t[7]), + (r[8] = t[8]), + (r[9] = t[9]), + (r[10] = t[10]), + (r[11] = t[11]), + (r[12] = t[12]), + (r[13] = t[13]), + (r[14] = t[14]), + (r[15] = t[15]), + r + ) + } + function s(t) { + return ( + ((t = t || new c(16))[0] = 1), + (t[1] = 0), + (t[2] = 0), + (t[3] = 0), + (t[4] = 0), + (t[5] = 1), + (t[6] = 0), + (t[7] = 0), + (t[8] = 0), + (t[9] = 0), + (t[10] = 1), + (t[11] = 0), + (t[12] = 0), + (t[13] = 0), + (t[14] = 0), + (t[15] = 1), + t + ) + } + function v(t, r) { + r = r || new c(16) + var e = t[0], + n = t[1], + o = t[2], + u = t[3], + i = t[4], + a = t[5], + f = t[6], + l = t[7], + s = t[8], + v = t[9], + y = t[10], + b = t[11], + m = t[12], + d = t[13], + p = t[14], + h = t[15], + w = y * h, + x = p * b, + F = f * h, + j = p * l, + O = f * b, + E = y * l, + A = o * h, + S = p * u, + M = o * b, + _ = y * u, + T = o * l, + g = f * u, + P = s * d, + R = m * v, + z = i * d, + k = m * a, + U = i * v, + C = s * a, + W = e * d, + I = m * n, + L = e * v, + G = s * n, + B = e * a, + N = i * n, + X = w * a + j * v + O * d - (x * a + F * v + E * d), + D = x * n + A * v + _ * d - (w * n + S * v + M * d), + H = F * n + S * a + T * d - (j * n + A * a + g * d), + V = E * n + M * a + g * v - (O * n + _ * a + T * v), + Y = 1 / (e * X + i * D + s * H + m * V) + return ( + (r[0] = Y * X), + (r[1] = Y * D), + (r[2] = Y * H), + (r[3] = Y * V), + (r[4] = + Y * (x * i + F * s + E * m - (w * i + j * s + O * m))), + (r[5] = + Y * (w * e + S * s + M * m - (x * e + A * s + _ * m))), + (r[6] = + Y * (j * e + A * i + g * m - (F * e + S * i + T * m))), + (r[7] = + Y * (O * e + _ * i + T * s - (E * e + M * i + g * s))), + (r[8] = + Y * (P * l + k * b + U * h - (R * l + z * b + C * h))), + (r[9] = + Y * (R * u + W * b + G * h - (P * u + I * b + L * h))), + (r[10] = + Y * (z * u + I * l + B * h - (k * u + W * l + N * h))), + (r[11] = + Y * (C * u + L * l + N * b - (U * u + G * l + B * b))), + (r[12] = + Y * (z * y + C * p + R * f - (U * p + P * f + k * y))), + (r[13] = + Y * (L * p + P * o + I * y - (W * y + G * p + R * o))), + (r[14] = + Y * (W * f + N * p + k * o - (B * p + z * o + I * f))), + (r[15] = + Y * (B * y + U * o + G * f - (L * f + N * y + C * o))), + r + ) + } + }, + function (t, r, e) { + 'use strict' + function n(t) { + return (n = + 'function' == typeof Symbol && + 'symbol' == typeof Symbol.iterator + ? function (t) { + return typeof t + } + : function (t) { + return t && + 'function' == typeof Symbol && + t.constructor === Symbol && + t !== Symbol.prototype + ? 'symbol' + : typeof t + })(t) + } + ;(r.__esModule = !0), + (r.createAttribsFromArrays = O), + (r.createBufferFromArray = A), + (r.createBufferFromTypedArray = v), + (r.createBufferInfoFromArrays = function (t, r, e) { + var n = O(t, r), + u = Object.assign({}, e || {}) + u.attribs = Object.assign({}, e ? e.attribs : {}, n) + var i = r.indices + if (i) { + var a = h(i, 'indices') + ;(u.indices = v(t, a, 34963)), + (u.numElements = a.length), + (u.elementType = o.getGLTypeForTypedArray(a)) + } else + u.numElements || + (u.numElements = (function (t, r) { + var e, n + for ( + n = 0; + n < E.length && + !((e = E[n]) in r) && + !((e = l.attribPrefix + e) in r); + ++n + ); + n === E.length && (e = Object.keys(r)[0]) + var o = r[e] + if (!o.buffer) return 1 + t.bindBuffer(f, o.buffer) + var u = t.getBufferParameter(f, 34660) + t.bindBuffer(f, null) + var i = + ((y = o.type), + 5120 === y || 5121 === y + ? 1 + : 5122 === y || 5123 === y + ? 2 + : 5124 === y || + 5125 === y || + y === c + ? 4 + : 0), + a = u / i, + s = o.numComponents || o.size, + v = a / s + var y + if (v % 1 != 0) + throw new Error( + 'numComponents ' + .concat( + s, + ' not correct for length ' + ) + .concat(length) + ) + return v + })(t, u.attribs)) + return u + }), + (r.createBuffersFromArrays = function (t, r) { + var e = {} + Object.keys(r).forEach(function (n) { + e[n] = A(t, r[n], n) + }), + r.indices + ? ((e.numElements = r.indices.length), + (e.elementType = o.getGLTypeForTypedArray( + h(r.indices), + 'indices' + ))) + : (e.numElements = (function (t) { + var r, e + for ( + e = 0; + e < E.length && !((r = E[e]) in t); + ++e + ); + e === E.length && (r = Object.keys(t)[0]) + var n = t[r], + o = b(n).length + if (void 0 === o) return 1 + var u = p(n, r), + i = o / u + if (o % u > 0) + throw new Error( + 'numComponents ' + .concat( + u, + ' not correct for length ' + ) + .concat(o) + ) + return i + })(r)) + return e + }), + (r.getArray_ = b), + (r.getNumComponents_ = p), + (r.setAttribInfoBufferFromArray = function (t, r, e, n) { + ;(e = h(e)), + void 0 !== n + ? (t.bindBuffer(f, r.buffer), + t.bufferSubData(f, n, e)) + : s(t, f, r.buffer, e, r.drawType) + }), + (r.setAttributeDefaults_ = function (t) { + u.copyExistingProperties(t, l) + }), + (r.setAttributePrefix = function (t) { + l.attribPrefix = t + }) + var o = a(e(1)), + u = a(e(0)) + function i(t) { + if ('function' != typeof WeakMap) return null + var r = new WeakMap(), + e = new WeakMap() + return (i = function (t) { + return t ? e : r + })(t) + } + function a(t, r) { + if (!r && t && t.__esModule) return t + if (null === t || ('object' !== n(t) && 'function' != typeof t)) + return { default: t } + var e = i(r) + if (e && e.has(t)) return e.get(t) + var o = {}, + u = Object.defineProperty && Object.getOwnPropertyDescriptor + for (var a in t) + if ( + 'default' !== a && + Object.prototype.hasOwnProperty.call(t, a) + ) { + var f = u ? Object.getOwnPropertyDescriptor(t, a) : null + f && (f.get || f.set) + ? Object.defineProperty(o, a, f) + : (o[a] = t[a]) + } + return (o.default = t), e && e.set(t, o), o + } + var f = 34962, + c = 5126, + l = { attribPrefix: '' } + function s(t, r, e, n, o) { + t.bindBuffer(r, e), t.bufferData(r, n, o || 35044) + } + function v(t, r, e, n) { + if (u.isBuffer(t, r)) return r + e = e || f + var o = t.createBuffer() + return s(t, e, o, r, n), o + } + function y(t) { + return 'indices' === t + } + function b(t) { + return t.length ? t : t.data + } + var m = /coord|texture/i, + d = /color|colour/i + function p(t, r, e) { + return ( + t.numComponents || + t.size || + (function (t, r) { + var e + if (r % (e = m.test(t) ? 2 : d.test(t) ? 4 : 3) > 0) + throw new Error( + "Can not guess numComponents for attribute '" + .concat(t, "'. Tried ") + .concat(e, ' but ') + .concat( + r, + ' values is not evenly divisible by ' + ) + .concat(e, '. You should specify it.') + ) + return e + })(r, e || b(t).length) + ) + } + function h(t, r) { + if (o.isArrayBuffer(t)) return t + if (o.isArrayBuffer(t.data)) return t.data + Array.isArray(t) && (t = { data: t }) + var e = t.type ? w(t.type) : void 0 + return ( + e || (e = y(r) ? Uint16Array : Float32Array), new e(t.data) + ) + } + function w(t) { + return 'number' == typeof t + ? o.getTypedArrayTypeForGLType(t) + : t || Float32Array + } + function x(t, r) { + return { + buffer: r.buffer, + numValues: 24, + type: + ((e = r.type), + 'number' == typeof e + ? e + : e + ? o.getGLTypeForTypedArrayType(e) + : c), + arrayType: w(r.type), + } + var e + } + function F(t, r) { + var e = r.data || r, + n = w(r.type), + u = e * n.BYTES_PER_ELEMENT, + i = t.createBuffer() + return ( + t.bindBuffer(f, i), + t.bufferData(f, u, r.drawType || 35044), + { + buffer: i, + numValues: e, + type: o.getGLTypeForTypedArrayType(n), + arrayType: n, + } + ) + } + function j(t, r, e) { + var n = h(r, e) + return { + arrayType: n.constructor, + buffer: v(t, n, void 0, r.drawType), + type: o.getGLTypeForTypedArray(n), + numValues: 0, + } + } + function O(t, r) { + var e = {} + return ( + Object.keys(r).forEach(function (n) { + if (!y(n)) { + var u = r[n], + i = + u.attrib || + u.name || + u.attribName || + l.attribPrefix + n + if (u.value) { + if ( + !Array.isArray(u.value) && + !o.isArrayBuffer(u.value) + ) + throw new Error( + 'array.value is not array or typedarray' + ) + e[i] = { value: u.value } + } else { + var a = ( + u.buffer && + u.buffer instanceof WebGLBuffer + ? x + : 'number' == typeof u || + 'number' == typeof u.data + ? F + : j + )(t, u, n), + f = a.buffer, + c = a.type, + s = a.numValues, + v = a.arrayType, + b = + void 0 !== u.normalize + ? u.normalize + : (d = v) === Int8Array || + d === Uint8Array, + m = p(u, n, s) + e[i] = { + buffer: f, + numComponents: m, + type: c, + normalize: b, + stride: u.stride || 0, + offset: u.offset || 0, + divisor: + void 0 === u.divisor + ? void 0 + : u.divisor, + drawType: u.drawType, + } + } + } + var d + }), + t.bindBuffer(f, null), + e + ) + } + var E = ['position', 'positions', 'a_position'] + function A(t, r, e) { + var n = 'indices' === e ? 34963 : f + return v(t, h(r, e), n) + } + }, + function (t, r, e) { + 'use strict' + function n(t) { + return (n = + 'function' == typeof Symbol && + 'symbol' == typeof Symbol.iterator + ? function (t) { + return typeof t + } + : function (t) { + return t && + 'function' == typeof Symbol && + t.constructor === Symbol && + t !== Symbol.prototype + ? 'symbol' + : typeof t + })(t) + } + ;(r.__esModule = !0), + (r.canFilter = rt), + (r.canGenerateMipmap = tt), + (r.createSampler = lt), + (r.createSamplers = function (t, r) { + var e = {} + return ( + Object.keys(r).forEach(function (n) { + e[n] = lt(t, r[n]) + }), + e + ) + }), + (r.createTexture = St), + (r.createTextures = function (t, r, e) { + e = e || dt + var n = 0, + o = [], + u = {}, + i = {} + function a() { + 0 === n && + setTimeout(function () { + e(o.length ? o : void 0, u, i) + }, 0) + } + return ( + Object.keys(r).forEach(function (e) { + var f, + c, + l = r[e] + ;('string' == typeof (c = l.src) || + (Array.isArray(c) && + 'string' == typeof c[0])) && + ((f = function (t, r, u) { + ;(i[e] = u), --n, t && o.push(t), a() + }), + ++n), + (u[e] = St(t, l, f)) + }), + a(), + u + ) + }), + (r.getBytesPerElementForInternalFormat = Z), + (r.getFormatAndTypeForInternalFormat = J), + (r.getNumComponentsForFormat = function (t) { + var r = q[t] + if (!r) throw 'unknown format: ' + t + return r.u + }), + (r.loadTextureFromUrl = Ft), + (r.resizeTexture = function (t, r, e, n, o, u) { + ;(n = n || e.width), (o = o || e.height), (u = u || e.depth) + var i = e.target || j + t.bindTexture(i, r) + var a, + f = e.level || 0, + c = e.internalFormat || e.format || d, + l = J(c), + s = e.format || l.format, + y = e.src + a = + y && + (v(y) || (Array.isArray(y) && 'number' == typeof y[0])) + ? e.type || et(t, y, l.type) + : e.type || l.type + if (i === O) + for (var b = 0; b < 6; ++b) + t.texImage2D(S + b, f, c, n, o, 0, s, a, null) + else + i === E || i === A + ? t.texImage3D(i, f, c, n, o, u, 0, s, a, null) + : t.texImage2D(i, f, c, n, o, 0, s, a, null) + }), + (r.setDefaultTextureColor = ot), + (r.setEmptyTexture = At), + (r.setSamplerParameters = ct), + (r.setTextureDefaults_ = function (t) { + i.copyExistingProperties(t, s), + t.textureColor && ot(t.textureColor) + }), + (r.setTextureFilteringForSize = st), + (r.setTextureFromArray = Et), + (r.setTextureFromElement = mt), + (r.setTextureParameters = ft) + var o = f(e(3)), + u = f(e(1)), + i = f(e(0)) + function a(t) { + if ('function' != typeof WeakMap) return null + var r = new WeakMap(), + e = new WeakMap() + return (a = function (t) { + return t ? e : r + })(t) + } + function f(t, r) { + if (!r && t && t.__esModule) return t + if (null === t || ('object' !== n(t) && 'function' != typeof t)) + return { default: t } + var e = a(r) + if (e && e.has(t)) return e.get(t) + var o = {}, + u = Object.defineProperty && Object.getOwnPropertyDescriptor + for (var i in t) + if ( + 'default' !== i && + Object.prototype.hasOwnProperty.call(t, i) + ) { + var f = u ? Object.getOwnPropertyDescriptor(t, i) : null + f && (f.get || f.set) + ? Object.defineProperty(o, i, f) + : (o[i] = t[i]) + } + return (o.default = t), e && e.set(t, o), o + } + var c, + l, + s = { + textureColor: new Uint8Array([128, 192, 255, 255]), + textureOptions: {}, + crossOrigin: void 0, + }, + v = u.isArrayBuffer, + y = function () { + return (c = + c || + ('undefined' != typeof document && + document.createElement + ? document.createElement('canvas').getContext('2d') + : null)) + }, + b = 6406, + m = 6407, + d = 6408, + p = 6409, + h = 6410, + w = 6402, + x = 34041, + F = 33071, + j = 3553, + O = 34067, + E = 32879, + A = 35866, + S = 34069, + M = 10241, + _ = 10240, + T = 10242, + g = 10243, + P = 3317, + R = 5120, + z = 5121, + k = 5122, + U = 5123, + C = 5124, + W = 5125, + I = 5126, + L = 5131, + G = 36193, + B = 33640, + N = 33319, + X = 33320, + D = 6403, + H = 36244, + V = 36248, + Y = 36249, + q = {}, + K = q + function $(t) { + if (!l) { + var r = {} + ;(r[6406] = { + v: b, + h: !0, + F: !0, + j: [1, 2, 2, 4], + type: [z, L, G, I], + }), + (r[6409] = { + v: p, + h: !0, + F: !0, + j: [1, 2, 2, 4], + type: [z, L, G, I], + }), + (r[6410] = { + v: h, + h: !0, + F: !0, + j: [2, 4, 4, 8], + type: [z, L, G, I], + }), + (r[m] = { + v: m, + h: !0, + F: !0, + j: [3, 6, 6, 12, 2], + type: [z, L, G, I, 33635], + }), + (r[d] = { + v: d, + h: !0, + F: !0, + j: [4, 8, 8, 16, 2, 2], + type: [z, L, G, I, 32819, 32820], + }), + (r[6402] = { + v: w, + h: !0, + F: !1, + j: [2, 4], + type: [W, U], + }), + (r[33321] = { v: D, h: !0, F: !0, j: [1], type: [z] }), + (r[36756] = { v: D, h: !1, F: !0, j: [1], type: [R] }), + (r[33325] = { + v: D, + h: !1, + F: !0, + j: [4, 2], + type: [I, L], + }), + (r[33326] = { v: D, h: !1, F: !1, j: [4], type: [I] }), + (r[33330] = { v: H, h: !0, F: !1, j: [1], type: [z] }), + (r[33329] = { v: H, h: !0, F: !1, j: [1], type: [R] }), + (r[33332] = { v: H, h: !0, F: !1, j: [2], type: [U] }), + (r[33331] = { v: H, h: !0, F: !1, j: [2], type: [k] }), + (r[33334] = { v: H, h: !0, F: !1, j: [4], type: [W] }), + (r[33333] = { v: H, h: !0, F: !1, j: [4], type: [C] }), + (r[33323] = { v: N, h: !0, F: !0, j: [2], type: [z] }), + (r[36757] = { v: N, h: !1, F: !0, j: [2], type: [R] }), + (r[33327] = { + v: N, + h: !1, + F: !0, + j: [8, 4], + type: [I, L], + }), + (r[33328] = { v: N, h: !1, F: !1, j: [8], type: [I] }), + (r[33336] = { v: X, h: !0, F: !1, j: [2], type: [z] }), + (r[33335] = { v: X, h: !0, F: !1, j: [2], type: [R] }), + (r[33338] = { v: X, h: !0, F: !1, j: [4], type: [U] }), + (r[33337] = { v: X, h: !0, F: !1, j: [4], type: [k] }), + (r[33340] = { v: X, h: !0, F: !1, j: [8], type: [W] }), + (r[33339] = { v: X, h: !0, F: !1, j: [8], type: [C] }), + (r[32849] = { v: m, h: !0, F: !0, j: [3], type: [z] }), + (r[35905] = { v: m, h: !1, F: !0, j: [3], type: [z] }), + (r[36194] = { + v: m, + h: !0, + F: !0, + j: [3, 2], + type: [z, 33635], + }), + (r[36758] = { v: m, h: !1, F: !0, j: [3], type: [R] }), + (r[35898] = { + v: m, + h: !1, + F: !0, + j: [12, 6, 4], + type: [I, L, 35899], + }), + (r[35901] = { + v: m, + h: !1, + F: !0, + j: [12, 6, 4], + type: [I, L, 35902], + }), + (r[34843] = { + v: m, + h: !1, + F: !0, + j: [12, 6], + type: [I, L], + }), + (r[34837] = { v: m, h: !1, F: !1, j: [12], type: [I] }), + (r[36221] = { v: V, h: !1, F: !1, j: [3], type: [z] }), + (r[36239] = { v: V, h: !1, F: !1, j: [3], type: [R] }), + (r[36215] = { v: V, h: !1, F: !1, j: [6], type: [U] }), + (r[36233] = { v: V, h: !1, F: !1, j: [6], type: [k] }), + (r[36209] = { v: V, h: !1, F: !1, j: [12], type: [W] }), + (r[36227] = { v: V, h: !1, F: !1, j: [12], type: [C] }), + (r[32856] = { v: d, h: !0, F: !0, j: [4], type: [z] }), + (r[35907] = { v: d, h: !0, F: !0, j: [4], type: [z] }), + (r[36759] = { v: d, h: !1, F: !0, j: [4], type: [R] }), + (r[32855] = { + v: d, + h: !0, + F: !0, + j: [4, 2, 4], + type: [z, 32820, B], + }), + (r[32854] = { + v: d, + h: !0, + F: !0, + j: [4, 2], + type: [z, 32819], + }), + (r[32857] = { v: d, h: !0, F: !0, j: [4], type: [B] }), + (r[34842] = { + v: d, + h: !1, + F: !0, + j: [16, 8], + type: [I, L], + }), + (r[34836] = { v: d, h: !1, F: !1, j: [16], type: [I] }), + (r[36220] = { v: Y, h: !0, F: !1, j: [4], type: [z] }), + (r[36238] = { v: Y, h: !0, F: !1, j: [4], type: [R] }), + (r[36975] = { v: Y, h: !0, F: !1, j: [4], type: [B] }), + (r[36214] = { v: Y, h: !0, F: !1, j: [8], type: [U] }), + (r[36232] = { v: Y, h: !0, F: !1, j: [8], type: [k] }), + (r[36226] = { v: Y, h: !0, F: !1, j: [16], type: [C] }), + (r[36208] = { v: Y, h: !0, F: !1, j: [16], type: [W] }), + (r[33189] = { + v: w, + h: !0, + F: !1, + j: [2, 4], + type: [U, W], + }), + (r[33190] = { v: w, h: !0, F: !1, j: [4], type: [W] }), + (r[36012] = { v: w, h: !0, F: !1, j: [4], type: [I] }), + (r[35056] = { + v: x, + h: !0, + F: !1, + j: [4], + type: [34042], + }), + (r[36013] = { + v: x, + h: !0, + F: !1, + j: [4], + type: [36269], + }), + Object.keys(r).forEach(function (t) { + var e = r[t] + ;(e.bytesPerElementMap = {}), + e.j.forEach(function (t, r) { + var n = e.type[r] + e.bytesPerElementMap[n] = t + }) + }), + (l = r) + } + return l[t] + } + function Z(t, r) { + var e = $(t) + if (!e) throw 'unknown internal format' + var n = e.bytesPerElementMap[r] + if (void 0 === n) throw 'unknown internal format' + return n + } + function J(t) { + var r = $(t) + if (!r) throw 'unknown internal format' + return { format: r.v, type: r.type[0] } + } + function Q(t) { + return 0 == (t & (t - 1)) + } + function tt(t, r, e, n) { + if (!o.isWebGL2(t)) return Q(r) && Q(e) + var u = $(n) + if (!u) throw 'unknown internal format' + return u.h && u.F + } + function rt(t) { + var r = $(t) + if (!r) throw 'unknown internal format' + return r.F + } + function et(t, r, e) { + return v(r) ? u.getGLTypeForTypedArray(r) : e || z + } + function nt(t, r, e, n, o) { + if (o % 1 != 0) throw "can't guess dimensions" + if (e || n) { + if (n) { + if (!e && (e = o / n) % 1) + throw "can't guess dimensions" + } else if ((n = o / e) % 1) throw "can't guess dimensions" + } else { + var u = Math.sqrt(o / (r === O ? 6 : 1)) + u % 1 == 0 ? ((e = u), (n = u)) : ((e = o), (n = 1)) + } + return { width: e, height: n } + } + function ot(t) { + s.textureColor = new Uint8Array([ + 255 * t[0], + 255 * t[1], + 255 * t[2], + 255 * t[3], + ]) + } + function ut(t, r) { + void 0 !== r.colorspaceConversion && + t.pixelStorei(37443, r.colorspaceConversion), + void 0 !== r.premultiplyAlpha && + t.pixelStorei(37441, r.premultiplyAlpha), + void 0 !== r.flipY && t.pixelStorei(37440, r.flipY) + } + function it(t) { + t.pixelStorei(P, 4), + o.isWebGL2(t) && + (t.pixelStorei(3314, 0), + t.pixelStorei(32878, 0), + t.pixelStorei(3316, 0), + t.pixelStorei(3315, 0), + t.pixelStorei(32877, 0)) + } + function at(t, r, e, n) { + n.minMag && + (e.call(t, r, M, n.minMag), e.call(t, r, _, n.minMag)), + n.min && e.call(t, r, M, n.min), + n.mag && e.call(t, r, _, n.mag), + n.wrap && + (e.call(t, r, T, n.wrap), + e.call(t, r, g, n.wrap), + (r === E || i.isSampler(t, r)) && + e.call(t, r, 32882, n.wrap)), + n.wrapR && e.call(t, r, 32882, n.wrapR), + n.wrapS && e.call(t, r, T, n.wrapS), + n.wrapT && e.call(t, r, g, n.wrapT), + n.minLod && e.call(t, r, 33082, n.minLod), + n.maxLod && e.call(t, r, 33083, n.maxLod), + n.baseLevel && e.call(t, r, 33084, n.baseLevel), + n.maxLevel && e.call(t, r, 33085, n.maxLevel) + } + function ft(t, r, e) { + var n = e.target || j + t.bindTexture(n, r), at(t, n, t.texParameteri, e) + } + function ct(t, r, e) { + at(t, r, t.samplerParameteri, e) + } + function lt(t, r) { + var e = t.createSampler() + return ct(t, e, r), e + } + function st(t, r, e, n, o, u) { + ;(e = e || s.textureOptions), (u = u || d) + var i = e.target || j + if ( + ((n = n || e.width), + (o = o || e.height), + t.bindTexture(i, r), + tt(t, n, o, u)) + ) + t.generateMipmap(i) + else { + var a = rt(u) ? 9729 : 9728 + t.texParameteri(i, M, a), + t.texParameteri(i, _, a), + t.texParameteri(i, T, F), + t.texParameteri(i, g, F) + } + } + function vt(t) { + return ( + !0 === t.auto || (void 0 === t.auto && void 0 === t.level) + ) + } + function yt(t, r) { + return ( + (r = r || {}).cubeFaceOrder || [ + S, + 34070, + 34071, + 34072, + 34073, + 34074, + ] + ) + } + function bt(t, r) { + var e = yt(0, r).map(function (t, r) { + return { face: t, ndx: r } + }) + return ( + e.sort(function (t, r) { + return t.face - r.face + }), + e + ) + } + function mt(t, r, e, n) { + var o = (n = n || s.textureOptions).target || j, + u = n.level || 0, + i = e.width, + a = e.height, + f = n.internalFormat || n.format || d, + c = J(f), + l = n.format || c.format, + v = n.type || c.type + if ((ut(t, n), t.bindTexture(o, r), o === O)) { + var b, + m, + p = e.width, + h = e.height + if (p / 6 === h) + (b = h), (m = [0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0]) + else if (h / 6 === p) + (b = p), (m = [0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5]) + else if (p / 3 == h / 2) + (b = p / 3), (m = [0, 0, 1, 0, 2, 0, 0, 1, 1, 1, 2, 1]) + else { + if (p / 2 != h / 3) + throw ( + "can't figure out cube map from element: " + + (e.src ? e.src : e.nodeName) + ) + ;(b = p / 2), (m = [0, 0, 1, 0, 0, 1, 1, 1, 0, 2, 1, 2]) + } + var w = y() + w + ? ((w.canvas.width = b), + (w.canvas.height = b), + (i = b), + (a = b), + bt(0, n).forEach(function (r) { + var n = m[2 * r.ndx + 0] * b, + o = m[2 * r.ndx + 1] * b + w.drawImage(e, n, o, b, b, 0, 0, b, b), + t.texImage2D(r.face, u, f, l, v, w.canvas) + }), + (w.canvas.width = 1), + (w.canvas.height = 1)) + : 'undefined' != typeof createImageBitmap && + ((i = b), + (a = b), + bt(0, n).forEach(function (c) { + var s = m[2 * c.ndx + 0] * b, + y = m[2 * c.ndx + 1] * b + t.texImage2D(c.face, u, f, b, b, 0, l, v, null), + createImageBitmap(e, s, y, b, b, { + premultiplyAlpha: 'none', + colorSpaceConversion: 'none', + }).then(function (e) { + ut(t, n), + t.bindTexture(o, r), + t.texImage2D(c.face, u, f, l, v, e), + vt(n) && st(t, r, n, i, a, f) + }) + })) + } else if (o === E || o === A) { + var x = Math.min(e.width, e.height), + F = Math.max(e.width, e.height), + S = F / x + if (S % 1 != 0) + throw 'can not compute 3D dimensions of element' + var M = e.width === F ? 1 : 0, + _ = e.height === F ? 1 : 0 + t.pixelStorei(P, 1), + t.pixelStorei(3314, e.width), + t.pixelStorei(32878, 0), + t.pixelStorei(32877, 0), + t.texImage3D(o, u, f, x, x, x, 0, l, v, null) + for (var T = 0; T < S; ++T) { + var g = T * x * M, + R = T * x * _ + t.pixelStorei(3316, g), + t.pixelStorei(3315, R), + t.texSubImage3D(o, u, 0, 0, T, x, x, 1, l, v, e) + } + it(t) + } else t.texImage2D(o, u, f, l, v, e) + vt(n) && st(t, r, n, i, a, f), ft(t, r, n) + } + function dt() {} + function pt(t, r) { + return void 0 !== r || + (function (t) { + if ('undefined' != typeof document) { + var r = document.createElement('a') + return ( + (r.href = t), + r.hostname === location.hostname && + r.port === location.port && + r.protocol === location.protocol + ) + } + var e = new URL(location.href).origin + return new URL(t, location.href).origin === e + })(t) + ? r + : 'anonymous' + } + function ht(t) { + return ( + ('undefined' != typeof ImageBitmap && + t instanceof ImageBitmap) || + ('undefined' != typeof ImageData && + t instanceof ImageData) || + ('undefined' != typeof HTMLElement && + t instanceof HTMLElement) + ) + } + function wt(t, r, e) { + return ht(t) + ? (setTimeout(function () { + e(null, t) + }), + t) + : (function (t, r, e) { + var n + if ( + ((e = e || dt), + (r = void 0 !== r ? r : s.crossOrigin), + (r = pt(t, r)), + 'undefined' != typeof Image) + ) { + ;(n = new Image()), + void 0 !== r && (n.crossOrigin = r) + var o = function () { + n.removeEventListener('error', u), + n.removeEventListener('load', a), + (n = null) + }, + u = function () { + var r = "couldn't load image: " + t + i.error(r), e(r, n), o() + }, + a = function () { + e(null, n), o() + } + return ( + n.addEventListener('error', u), + n.addEventListener('load', a), + (n.src = t), + n + ) + } + if ('undefined' != typeof ImageBitmap) { + var f, + c, + l = function () { + e(f, c) + }, + v = {} + r && (v.mode = 'cors'), + fetch(t, v) + .then(function (t) { + if (!t.ok) throw t + return t.blob() + }) + .then(function (t) { + return createImageBitmap(t, { + premultiplyAlpha: 'none', + colorSpaceConversion: 'none', + }) + }) + .then(function (t) { + ;(c = t), setTimeout(l) + }) + .catch(function (t) { + ;(f = t), setTimeout(l) + }), + (n = null) + } + return n + })(t, r, e) + } + function xt(t, r, e) { + var n = (e = e || s.textureOptions).target || j + if ((t.bindTexture(n, r), !1 !== e.color)) { + var o = (function (t) { + return ( + (t = t || s.textureColor), + v(t) + ? t + : new Uint8Array([ + 255 * t[0], + 255 * t[1], + 255 * t[2], + 255 * t[3], + ]) + ) + })(e.color) + if (n === O) + for (var u = 0; u < 6; ++u) + t.texImage2D(S + u, 0, d, 1, 1, 0, d, z, o) + else + n === E || n === A + ? t.texImage3D(n, 0, d, 1, 1, 1, 0, d, z, o) + : t.texImage2D(n, 0, d, 1, 1, 0, d, z, o) + } + } + function Ft(t, r, e, n) { + return ( + (n = n || dt), + (e = e || s.textureOptions), + xt(t, r, e), + wt( + (e = Object.assign({}, e)).src, + e.crossOrigin, + function (o, u) { + o ? n(o, r, u) : (mt(t, r, u, e), n(null, r, u)) + } + ) + ) + } + function jt(t, r, e, n) { + n = n || dt + var o = e.src + if (6 !== o.length) throw 'there must be 6 urls for a cubemap' + var u = e.level || 0, + i = e.internalFormat || e.format || d, + a = J(i), + f = e.format || a.format, + c = e.type || z, + l = e.target || j + if (l !== O) throw 'target must be TEXTURE_CUBE_MAP' + xt(t, r, e), (e = Object.assign({}, e)) + var s, + v = 6, + y = [], + b = yt(0, e) + s = o.map(function (o, a) { + return wt( + o, + e.crossOrigin, + ((m = b[a]), + function (o, a) { + --v, + o + ? y.push(o) + : a.width !== a.height + ? y.push( + 'cubemap face img is not a square: ' + + a.src + ) + : (ut(t, e), + t.bindTexture(l, r), + 5 === v + ? yt().forEach(function (r) { + t.texImage2D(r, u, i, f, c, a) + }) + : t.texImage2D(m, u, i, f, c, a), + vt(e) && t.generateMipmap(l)), + 0 === v && n(y.length ? y : void 0, r, s) + }) + ) + var m + }) + } + function Ot(t, r, e, n) { + n = n || dt + var o = e.src, + u = e.internalFormat || e.format || d, + i = J(u), + a = e.format || i.format, + f = e.type || z, + c = e.target || A + if (c !== E && c !== A) + throw 'target must be TEXTURE_3D or TEXTURE_2D_ARRAY' + xt(t, r, e), (e = Object.assign({}, e)) + var l, + s = o.length, + v = [], + b = e.level || 0, + m = e.width, + p = e.height, + h = o.length, + w = !0 + l = o.map(function (o, i) { + return wt( + o, + e.crossOrigin, + ((d = i), + function (o, i) { + if ((--s, o)) v.push(o) + else { + if ((ut(t, e), t.bindTexture(c, r), w)) { + ;(w = !1), + (m = e.width || i.width), + (p = e.height || i.height), + t.texImage3D( + c, + b, + u, + m, + p, + h, + 0, + a, + f, + null + ) + for (var x = 0; x < h; ++x) + t.texSubImage3D( + c, + b, + 0, + 0, + x, + m, + p, + 1, + a, + f, + i + ) + } else { + var F, + j = i + ;(i.width === m && i.height === p) || + ((j = (F = y()).canvas), + (F.canvas.width = m), + (F.canvas.height = p), + F.drawImage(i, 0, 0, m, p)), + t.texSubImage3D( + c, + b, + 0, + 0, + d, + m, + p, + 1, + a, + f, + j + ), + F && + j === F.canvas && + ((F.canvas.width = 0), + (F.canvas.height = 0)) + } + vt(e) && t.generateMipmap(c) + } + 0 === s && n(v.length ? v : void 0, r, l) + }) + ) + var d + }) + } + function Et(t, r, e, n) { + var i = (n = n || s.textureOptions).target || j + t.bindTexture(i, r) + var a = n.width, + f = n.height, + c = n.depth, + l = n.level || 0, + y = n.internalFormat || n.format || d, + b = J(y), + m = n.format || b.format, + p = n.type || et(0, e, b.type) + if (v(e)) + e instanceof Uint8ClampedArray && + (e = new Uint8Array(e.buffer)) + else { + var h = u.getTypedArrayTypeForGLType(p) + e = new h(e) + } + var w, + x = Z(y, p), + F = e.byteLength / x + if (F % 1) + throw ( + 'length wrong size for format: ' + + o.glEnumToString(t, m) + ) + if (i === E || i === A) + if (a || f || c) + !a || (f && c) + ? !f || (a && c) + ? ((w = nt(0, i, a, f, F / c)), + (a = w.width), + (f = w.height)) + : ((w = nt(0, i, a, c, F / f)), + (a = w.width), + (c = w.height)) + : ((w = nt(0, i, f, c, F / a)), + (f = w.width), + (c = w.height)) + else { + var S = Math.cbrt(F) + if (S % 1 != 0) + throw ( + "can't guess cube size of array of numElements: " + + F + ) + ;(a = S), (f = S), (c = S) + } + else (w = nt(0, i, a, f, F)), (a = w.width), (f = w.height) + if ( + (it(t), + t.pixelStorei(P, n.unpackAlignment || 1), + ut(t, n), + i === O) + ) { + var M = (F / 6) * (x / e.BYTES_PER_ELEMENT) + bt(0, n).forEach(function (r) { + var n = M * r.ndx, + o = e.subarray(n, n + M) + t.texImage2D(r.face, l, y, a, f, 0, m, p, o) + }) + } else + i === E || i === A + ? t.texImage3D(i, l, y, a, f, c, 0, m, p, e) + : t.texImage2D(i, l, y, a, f, 0, m, p, e) + return { width: a, height: f, depth: c, type: p } + } + function At(t, r, e) { + var n = e.target || j + t.bindTexture(n, r) + var o = e.level || 0, + u = e.internalFormat || e.format || d, + i = J(u), + a = e.format || i.format, + f = e.type || i.type + if ((ut(t, e), n === O)) + for (var c = 0; c < 6; ++c) + t.texImage2D( + S + c, + o, + u, + e.width, + e.height, + 0, + a, + f, + null + ) + else + n === E || n === A + ? t.texImage3D( + n, + o, + u, + e.width, + e.height, + e.depth, + 0, + a, + f, + null + ) + : t.texImage2D( + n, + o, + u, + e.width, + e.height, + 0, + a, + f, + null + ) + } + function St(t, r, e) { + ;(e = e || dt), (r = r || s.textureOptions) + var n = t.createTexture(), + o = r.target || j, + u = r.width || 1, + i = r.height || 1, + a = r.internalFormat || d + t.bindTexture(o, n), + o === O && + (t.texParameteri(o, T, F), t.texParameteri(o, g, F)) + var f = r.src + if (f) + if ( + ('function' == typeof f && (f = f(t, r)), + 'string' == typeof f) + ) + Ft(t, n, r, e) + else if ( + v(f) || + (Array.isArray(f) && + ('number' == typeof f[0] || + Array.isArray(f[0]) || + v(f[0]))) + ) { + var c = Et(t, n, f, r) + ;(u = c.width), (i = c.height) + } else + Array.isArray(f) && + ('string' == typeof f[0] || ht(f[0])) + ? o === O + ? jt(t, n, r, e) + : Ot(t, n, r, e) + : (mt(t, n, f, r), (u = f.width), (i = f.height)) + else At(t, n, r) + return vt(r) && st(t, n, r, u, i, a), ft(t, n, r), n + } + ;(K[6406] = { u: 1 }), + (K[6409] = { u: 1 }), + (K[6410] = { u: 2 }), + (K[m] = { u: 3 }), + (K[d] = { u: 4 }), + (K[D] = { u: 1 }), + (K[36244] = { u: 1 }), + (K[N] = { u: 2 }), + (K[33320] = { u: 2 }), + (K[m] = { u: 3 }), + (K[36248] = { u: 3 }), + (K[d] = { u: 4 }), + (K[36249] = { u: 4 }), + (K[6402] = { u: 1 }), + (K[34041] = { u: 2 }) + }, + function (t, r, e) { + 'use strict' + function n(t) { + return (n = + 'function' == typeof Symbol && + 'symbol' == typeof Symbol.iterator + ? function (t) { + return typeof t + } + : function (t) { + return t && + 'function' == typeof Symbol && + t.constructor === Symbol && + t !== Symbol.prototype + ? 'symbol' + : typeof t + })(t) + } + r.__esModule = !0 + var o = { m4: !0, v3: !0, primitives: !0 } + r.v3 = r.primitives = r.m4 = void 0 + var u = l(e(5)) + r.m4 = u + var i = l(e(2)) + r.v3 = i + var a = l(e(9)) + r.primitives = a + var f = e(10) + function c(t) { + if ('function' != typeof WeakMap) return null + var r = new WeakMap(), + e = new WeakMap() + return (c = function (t) { + return t ? e : r + })(t) + } + function l(t, r) { + if (!r && t && t.__esModule) return t + if (null === t || ('object' !== n(t) && 'function' != typeof t)) + return { default: t } + var e = c(r) + if (e && e.has(t)) return e.get(t) + var o = {}, + u = Object.defineProperty && Object.getOwnPropertyDescriptor + for (var i in t) + if ( + 'default' !== i && + Object.prototype.hasOwnProperty.call(t, i) + ) { + var a = u ? Object.getOwnPropertyDescriptor(t, i) : null + a && (a.get || a.set) + ? Object.defineProperty(o, i, a) + : (o[i] = t[i]) + } + return (o.default = t), e && e.set(t, o), o + } + Object.keys(f).forEach(function (t) { + 'default' !== t && + '__esModule' !== t && + (Object.prototype.hasOwnProperty.call(o, t) || + (t in r && r[t] === f[t]) || + (r[t] = f[t])) + }) + }, + function (t, r, e) { + 'use strict' + function n(t) { + return (n = + 'function' == typeof Symbol && + 'symbol' == typeof Symbol.iterator + ? function (t) { + return typeof t + } + : function (t) { + return t && + 'function' == typeof Symbol && + t.constructor === Symbol && + t !== Symbol.prototype + ? 'symbol' + : typeof t + })(t) + } + ;(r.__esModule = !0), + (r.concatVertices = function (t) { + for ( + var r, + e = {}, + n = function (n) { + var o = t[n] + Object.keys(o).forEach(function (t) { + e[t] || (e[t] = []), + r || 'indices' === t || (r = t) + var n = o[t], + u = v(n, t), + i = s(n).length / u + e[t].push(i) + }) + }, + o = 0; + o < t.length; + ++o + ) + n(o) + var u = e[r], + i = {} + return ( + Object.keys(e).forEach(function (r) { + var e = (function (r) { + for ( + var e, n = 0, o = 0; + o < t.length; + ++o + ) { + var u = t[o][r] + ;(n += s(u).length), + (e && !u.data) || (e = u) + } + return { length: n, spec: e } + })(r), + n = I(e.spec, e.length) + !(function (r, e, n) { + for ( + var o = 0, u = 0, i = 0; + i < t.length; + ++i + ) { + var a = t[i][r], + f = s(a) + 'indices' === r + ? (W(f, n, u, o), (o += e[i])) + : W(f, n, u), + (u += f.length) + } + })(r, u, s(n)), + (i[r] = n) + }), + i + ) + }), + (r.create3DFBuffers = r.create3DFBufferInfo = void 0), + (r.create3DFVertices = T), + (r.createAugmentedTypedArray = b), + (r.createCrescentBuffers = r.createCrescentBufferInfo = void 0), + (r.createCrescentVertices = g), + (r.createCubeBuffers = + r.createCubeBufferInfo = + r.createCresentVertices = + r.createCresentBuffers = + r.createCresentBufferInfo = + void 0), + (r.createCubeVertices = S), + (r.createCylinderBuffers = r.createCylinderBufferInfo = void 0), + (r.createCylinderVertices = P), + (r.createDiscBuffers = r.createDiscBufferInfo = void 0), + (r.createDiscVertices = z), + (r.createPlaneBuffers = r.createPlaneBufferInfo = void 0), + (r.createPlaneVertices = O), + (r.createSphereBuffers = r.createSphereBufferInfo = void 0), + (r.createSphereVertices = E), + (r.createTorusBuffers = r.createTorusBufferInfo = void 0), + (r.createTorusVertices = R), + (r.createTruncatedConeBuffers = + r.createTruncatedConeBufferInfo = + void 0), + (r.createTruncatedConeVertices = M), + (r.createXYQuadBuffers = r.createXYQuadBufferInfo = void 0), + (r.createXYQuadVertices = j), + (r.deindexVertices = function (t) { + var r = t.indices, + e = {}, + n = r.length + return ( + Object.keys(t) + .filter(m) + .forEach(function (o) { + for ( + var u = t[o], + i = u.numComponents, + a = b(i, n, u.constructor), + f = 0; + f < n; + ++f + ) + for (var c = r[f] * i, l = 0; l < i; ++l) + a.push(u[c + l]) + e[o] = a + }), + e + ) + }), + (r.duplicateVertices = function (t) { + var r = {} + return ( + Object.keys(t).forEach(function (e) { + var n = t[e], + o = s(n), + u = I(n, o.length) + W(o, s(u), 0), (r[e] = u) + }), + r + ) + }), + (r.flattenNormals = function (t) { + if (t.indices) + throw new Error( + 'can not flatten normals of indexed vertices. deindex them first' + ) + for (var r = t.normal, e = r.length, n = 0; n < e; n += 9) { + var o = r[n + 0], + u = r[n + 1], + i = r[n + 2], + a = r[n + 3], + f = r[n + 4], + c = r[n + 5], + l = r[n + 6], + s = r[n + 7], + v = r[n + 8], + y = o + a + l, + b = u + f + s, + m = i + c + v, + d = Math.sqrt(y * y + b * b + m * m) + ;(y /= d), + (b /= d), + (m /= d), + (r[n + 0] = y), + (r[n + 1] = b), + (r[n + 2] = m), + (r[n + 3] = y), + (r[n + 4] = b), + (r[n + 5] = m), + (r[n + 6] = y), + (r[n + 7] = b), + (r[n + 8] = m) + } + return t + }), + (r.makeRandomVertexColors = function (t, r) { + r = r || {} + var e = t.position.numElements, + n = b(4, e, Uint8Array), + o = + r.rand || + function (t, r) { + return r < 3 + ? ((e = 256), (Math.random() * e) | 0) + : 255 + var e + } + if (((t.color = n), t.indices)) + for (var u = 0; u < e; ++u) + n.push(o(u, 0), o(u, 1), o(u, 2), o(u, 3)) + else + for ( + var i = r.vertsPerColor || 3, a = e / i, f = 0; + f < a; + ++f + ) + for ( + var c = [o(f, 0), o(f, 1), o(f, 2), o(f, 3)], + l = 0; + l < i; + ++l + ) + n.push(c) + return t + }), + (r.reorientDirections = h), + (r.reorientNormals = w), + (r.reorientPositions = x), + (r.reorientVertices = F) + var o = l(e(6)), + u = l(e(0)), + i = l(e(1)), + a = l(e(5)), + f = l(e(2)) + function c(t) { + if ('function' != typeof WeakMap) return null + var r = new WeakMap(), + e = new WeakMap() + return (c = function (t) { + return t ? e : r + })(t) + } + function l(t, r) { + if (!r && t && t.__esModule) return t + if (null === t || ('object' !== n(t) && 'function' != typeof t)) + return { default: t } + var e = c(r) + if (e && e.has(t)) return e.get(t) + var o = {}, + u = Object.defineProperty && Object.getOwnPropertyDescriptor + for (var i in t) + if ( + 'default' !== i && + Object.prototype.hasOwnProperty.call(t, i) + ) { + var a = u ? Object.getOwnPropertyDescriptor(t, i) : null + a && (a.get || a.set) + ? Object.defineProperty(o, i, a) + : (o[i] = t[i]) + } + return (o.default = t), e && e.set(t, o), o + } + var s = o.getArray_, + v = o.getNumComponents_ + function y(t, r) { + var e = 0 + return ( + (t.push = function () { + for (var r = 0; r < arguments.length; ++r) { + var n = arguments[r] + if (n instanceof Array || i.isArrayBuffer(n)) + for (var o = 0; o < n.length; ++o) t[e++] = n[o] + else t[e++] = n + } + }), + (t.reset = function (t) { + e = t || 0 + }), + (t.numComponents = r), + Object.defineProperty(t, 'numElements', { + get: function () { + return (this.length / this.numComponents) | 0 + }, + }), + t + ) + } + function b(t, r, e) { + return y(new (e || Float32Array)(t * r), t) + } + function m(t) { + return 'indices' !== t + } + function d(t, r, e) { + for ( + var n = t.length, o = new Float32Array(3), u = 0; + u < n; + u += 3 + ) + e(r, [t[u], t[u + 1], t[u + 2]], o), + (t[u] = o[0]), + (t[u + 1] = o[1]), + (t[u + 2] = o[2]) + } + function p(t, r, e) { + e = e || f.create() + var n = r[0], + o = r[1], + u = r[2] + return ( + (e[0] = n * t[0] + o * t[1] + u * t[2]), + (e[1] = n * t[4] + o * t[5] + u * t[6]), + (e[2] = n * t[8] + o * t[9] + u * t[10]), + e + ) + } + function h(t, r) { + return d(t, r, a.transformDirection), t + } + function w(t, r) { + return d(t, a.inverse(r), p), t + } + function x(t, r) { + return d(t, r, a.transformPoint), t + } + function F(t, r) { + return ( + Object.keys(t).forEach(function (e) { + var n = t[e] + e.indexOf('pos') >= 0 + ? x(n, r) + : e.indexOf('tan') >= 0 || e.indexOf('binorm') >= 0 + ? h(n, r) + : e.indexOf('norm') >= 0 && w(n, r) + }), + t + ) + } + function j(t, r, e) { + return ( + (t = t || 2), + { + position: { + numComponents: 2, + data: [ + (r = r || 0) + -1 * (t *= 0.5), + (e = e || 0) + -1 * t, + r + 1 * t, + e + -1 * t, + r + -1 * t, + e + 1 * t, + r + 1 * t, + e + 1 * t, + ], + }, + normal: [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1], + texcoord: [0, 0, 1, 0, 0, 1, 1, 1], + indices: [0, 1, 2, 2, 1, 3], + } + ) + } + function O(t, r, e, n, o) { + ;(t = t || 1), + (r = r || 1), + (e = e || 1), + (n = n || 1), + (o = o || a.identity()) + for ( + var u = (e + 1) * (n + 1), + i = b(3, u), + f = b(3, u), + c = b(2, u), + l = 0; + l <= n; + l++ + ) + for (var s = 0; s <= e; s++) { + var v = s / e, + y = l / n + i.push(t * v - 0.5 * t, 0, r * y - 0.5 * r), + f.push(0, 1, 0), + c.push(v, y) + } + for ( + var m = e + 1, d = b(3, e * n * 2, Uint16Array), p = 0; + p < n; + p++ + ) + for (var h = 0; h < e; h++) + d.push( + (p + 0) * m + h, + (p + 1) * m + h, + (p + 0) * m + h + 1 + ), + d.push( + (p + 1) * m + h, + (p + 1) * m + h + 1, + (p + 0) * m + h + 1 + ) + return F({ position: i, normal: f, texcoord: c, indices: d }, o) + } + function E(t, r, e, n, o, u, i) { + if (r <= 0 || e <= 0) + throw new Error( + 'subdivisionAxis and subdivisionHeight must be > 0' + ) + ;(n = n || 0), (u = u || 0) + for ( + var a = (o = o || Math.PI) - n, + f = (i = i || 2 * Math.PI) - u, + c = (r + 1) * (e + 1), + l = b(3, c), + s = b(3, c), + v = b(2, c), + y = 0; + y <= e; + y++ + ) + for (var m = 0; m <= r; m++) { + var d = m / r, + p = y / e, + h = f * d + u, + w = a * p + n, + x = Math.sin(h), + F = Math.cos(h), + j = Math.sin(w), + O = F * j, + E = Math.cos(w), + A = x * j + l.push(t * O, t * E, t * A), + s.push(O, E, A), + v.push(1 - d, p) + } + for ( + var S = r + 1, M = b(3, r * e * 2, Uint16Array), _ = 0; + _ < r; + _++ + ) + for (var T = 0; T < e; T++) + M.push( + (T + 0) * S + _, + (T + 0) * S + _ + 1, + (T + 1) * S + _ + ), + M.push( + (T + 1) * S + _, + (T + 0) * S + _ + 1, + (T + 1) * S + _ + 1 + ) + return { position: l, normal: s, texcoord: v, indices: M } + } + var A = [ + [3, 7, 5, 1], + [6, 2, 0, 4], + [6, 7, 3, 2], + [0, 1, 5, 4], + [7, 6, 4, 5], + [2, 3, 1, 0], + ] + function S(t) { + for ( + var r = (t = t || 1) / 2, + e = [ + [-r, -r, -r], + [+r, -r, -r], + [-r, +r, -r], + [+r, +r, -r], + [-r, -r, +r], + [+r, -r, +r], + [-r, +r, +r], + [+r, +r, +r], + ], + n = [ + [1, 0, 0], + [-1, 0, 0], + [0, 1, 0], + [0, -1, 0], + [0, 0, 1], + [0, 0, -1], + ], + o = [ + [1, 0], + [0, 0], + [0, 1], + [1, 1], + ], + u = b(3, 24), + i = b(3, 24), + a = b(2, 24), + f = b(3, 12, Uint16Array), + c = 0; + c < 6; + ++c + ) { + for (var l = A[c], s = 0; s < 4; ++s) { + var v = e[l[s]], + y = n[c], + m = o[s] + u.push(v), i.push(y), a.push(m) + } + var d = 4 * c + f.push(d + 0, d + 1, d + 2), f.push(d + 0, d + 2, d + 3) + } + return { position: u, normal: i, texcoord: a, indices: f } + } + function M(t, r, e, n, o, u, i) { + if (n < 3) + throw new Error('radialSubdivisions must be 3 or greater') + if (o < 1) + throw new Error('verticalSubdivisions must be 1 or greater') + for ( + var a = void 0 === u || u, + f = void 0 === i || i, + c = (a ? 2 : 0) + (f ? 2 : 0), + l = (n + 1) * (o + 1 + c), + s = b(3, l), + v = b(3, l), + y = b(2, l), + m = b(3, n * (o + c / 2) * 2, Uint16Array), + d = n + 1, + p = Math.atan2(t - r, e), + h = Math.cos(p), + w = Math.sin(p), + x = o + (f ? 2 : 0), + F = a ? -2 : 0; + F <= x; + ++F + ) { + var j = F / o, + O = e * j, + E = void 0 + F < 0 + ? ((O = 0), (j = 1), (E = t)) + : F > o + ? ((O = e), (j = 1), (E = r)) + : (E = t + (F / o) * (r - t)), + (-2 !== F && F !== o + 2) || ((E = 0), (j = 0)), + (O -= e / 2) + for (var A = 0; A < d; ++A) { + var S = Math.sin((A * Math.PI * 2) / n), + M = Math.cos((A * Math.PI * 2) / n) + s.push(S * E, O, M * E), + F < 0 + ? v.push(0, -1, 0) + : F > o + ? v.push(0, 1, 0) + : 0 === E + ? v.push(0, 0, 0) + : v.push(S * h, w, M * h), + y.push(A / n, 1 - j) + } + } + for (var _ = 0; _ < o + c; ++_) + if (!((1 === _ && a) || (_ === o + c - 2 && f))) + for (var T = 0; T < n; ++T) + m.push( + d * (_ + 0) + 0 + T, + d * (_ + 0) + 1 + T, + d * (_ + 1) + 1 + T + ), + m.push( + d * (_ + 0) + 0 + T, + d * (_ + 1) + 1 + T, + d * (_ + 1) + 0 + T + ) + return { position: s, normal: v, texcoord: y, indices: m } + } + function _(t, r) { + r = r || [] + for (var e = [], n = 0; n < t.length; n += 4) { + var o = t[n], + u = t.slice(n + 1, n + 4) + u.push.apply(u, r) + for (var i = 0; i < o; ++i) e.push.apply(e, u) + } + return e + } + function T() { + var t = [ + 0, 0, 0, 0, 150, 0, 30, 0, 0, 0, 150, 0, 30, 150, 0, 30, + 0, 0, 30, 0, 0, 30, 30, 0, 100, 0, 0, 30, 30, 0, 100, + 30, 0, 100, 0, 0, 30, 60, 0, 30, 90, 0, 67, 60, 0, 30, + 90, 0, 67, 90, 0, 67, 60, 0, 0, 0, 30, 30, 0, 30, 0, + 150, 30, 0, 150, 30, 30, 0, 30, 30, 150, 30, 30, 0, 30, + 100, 0, 30, 30, 30, 30, 30, 30, 30, 100, 0, 30, 100, 30, + 30, 30, 60, 30, 67, 60, 30, 30, 90, 30, 30, 90, 30, 67, + 60, 30, 67, 90, 30, 0, 0, 0, 100, 0, 0, 100, 0, 30, 0, + 0, 0, 100, 0, 30, 0, 0, 30, 100, 0, 0, 100, 30, 0, 100, + 30, 30, 100, 0, 0, 100, 30, 30, 100, 0, 30, 30, 30, 0, + 30, 30, 30, 100, 30, 30, 30, 30, 0, 100, 30, 30, 100, + 30, 0, 30, 30, 0, 30, 60, 30, 30, 30, 30, 30, 30, 0, 30, + 60, 0, 30, 60, 30, 30, 60, 0, 67, 60, 30, 30, 60, 30, + 30, 60, 0, 67, 60, 0, 67, 60, 30, 67, 60, 0, 67, 90, 30, + 67, 60, 30, 67, 60, 0, 67, 90, 0, 67, 90, 30, 30, 90, 0, + 30, 90, 30, 67, 90, 30, 30, 90, 0, 67, 90, 30, 67, 90, + 0, 30, 90, 0, 30, 150, 30, 30, 90, 30, 30, 90, 0, 30, + 150, 0, 30, 150, 30, 0, 150, 0, 0, 150, 30, 30, 150, 30, + 0, 150, 0, 30, 150, 30, 30, 150, 0, 0, 0, 0, 0, 0, 30, + 0, 150, 30, 0, 0, 0, 0, 150, 30, 0, 150, 0, + ], + r = _([ + 18, 0, 0, 1, 18, 0, 0, -1, 6, 0, 1, 0, 6, 1, 0, 0, 6, 0, + -1, 0, 6, 1, 0, 0, 6, 0, 1, 0, 6, 1, 0, 0, 6, 0, -1, 0, + 6, 1, 0, 0, 6, 0, -1, 0, 6, -1, 0, 0, + ]), + e = _( + [ + 18, 200, 70, 120, 18, 80, 70, 200, 6, 70, 200, 210, + 6, 200, 200, 70, 6, 210, 100, 70, 6, 210, 160, 70, + 6, 70, 180, 210, 6, 100, 70, 210, 6, 76, 210, 100, + 6, 140, 210, 80, 6, 90, 130, 110, 6, 160, 160, 220, + ], + [255] + ), + n = t.length / 3, + o = { + position: b(3, n), + texcoord: b(2, n), + normal: b(3, n), + color: b(4, n, Uint8Array), + indices: b(3, n / 3, Uint16Array), + } + o.position.push(t), + o.texcoord.push([ + 0.22, 0.19, 0.22, 0.79, 0.34, 0.19, 0.22, 0.79, 0.34, + 0.79, 0.34, 0.19, 0.34, 0.19, 0.34, 0.31, 0.62, 0.19, + 0.34, 0.31, 0.62, 0.31, 0.62, 0.19, 0.34, 0.43, 0.34, + 0.55, 0.49, 0.43, 0.34, 0.55, 0.49, 0.55, 0.49, 0.43, 0, + 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, + 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, + 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, + 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, + 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, + 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, + 1, 1, 0, + ]), + o.normal.push(r), + o.color.push(e) + for (var u = 0; u < n; ++u) o.indices.push(u) + return o + } + function g(t, r, e, n, o, u, i) { + if (o <= 0) throw new Error('subdivisionDown must be > 0') + var a = (i = i || 1) - (u = u || 0), + c = 2 * (o + 1) * 4, + l = b(3, c), + s = b(3, c), + v = b(2, c) + function y(t, r, e) { + return t + (r - t) * e + } + function m(r, e, i, c, b, m) { + for (var d = 0; d <= o; d++) { + var p = e / 1, + h = d / o, + w = 2 * (p - 0.5), + x = (u + h * a) * Math.PI, + F = Math.sin(x), + j = Math.cos(x), + O = y(t, r, F), + E = w * n, + A = j * t, + S = F * O + l.push(E, A, S) + var M = f.add(f.multiply([0, F, j], i), c) + s.push(M), v.push(p * b + m, h) + } + } + for (var d = 0; d < 2; d++) { + var p = 2 * (d / 1 - 0.5) + m(r, d, [1, 1, 1], [0, 0, 0], 1, 0), + m(r, d, [0, 0, 0], [p, 0, 0], 0, 0), + m(e, d, [1, 1, 1], [0, 0, 0], 1, 0), + m(e, d, [0, 0, 0], [p, 0, 0], 0, 1) + } + var h = b(3, 2 * o * 4, Uint16Array) + function w(t, r) { + for (var e = 0; e < o; ++e) + h.push(t + e + 0, t + e + 1, r + e + 0), + h.push(t + e + 1, r + e + 1, r + e + 0) + } + var x = o + 1 + return ( + w(0 * x, 4 * x), + w(5 * x, 7 * x), + w(6 * x, 2 * x), + w(3 * x, 1 * x), + { position: l, normal: s, texcoord: v, indices: h } + ) + } + function P(t, r, e, n, o, u) { + return M(t, t, r, e, n, o, u) + } + function R(t, r, e, n, o, u) { + if (e < 3) + throw new Error('radialSubdivisions must be 3 or greater') + if (n < 3) + throw new Error('verticalSubdivisions must be 3 or greater') + o = o || 0 + for ( + var i = (u = u || 2 * Math.PI) - o, + a = e + 1, + f = n + 1, + c = a * f, + l = b(3, c), + s = b(3, c), + v = b(2, c), + y = b(3, e * n * 2, Uint16Array), + m = 0; + m < f; + ++m + ) + for ( + var d = m / n, + p = d * Math.PI * 2, + h = Math.sin(p), + w = t + h * r, + x = Math.cos(p), + F = x * r, + j = 0; + j < a; + ++j + ) { + var O = j / e, + E = o + O * i, + A = Math.sin(E), + S = Math.cos(E), + M = A * w, + _ = S * w, + T = A * h, + g = S * h + l.push(M, F, _), s.push(T, x, g), v.push(O, 1 - d) + } + for (var P = 0; P < n; ++P) + for (var R = 0; R < e; ++R) { + var z = 1 + R, + k = 1 + P + y.push(a * P + R, a * k + R, a * P + z), + y.push(a * k + R, a * k + z, a * P + z) + } + return { position: l, normal: s, texcoord: v, indices: y } + } + function z(t, r, e, n, o) { + if (r < 3) throw new Error('divisions must be at least 3') + ;(o = o || 1), (n = n || 0) + for ( + var u = (r + 1) * ((e = e || 1) + 1), + i = b(3, u), + a = b(3, u), + f = b(2, u), + c = b(3, e * r * 2, Uint16Array), + l = 0, + s = t - n, + v = r + 1, + y = 0; + y <= e; + ++y + ) { + for ( + var m = n + s * Math.pow(y / e, o), d = 0; + d <= r; + ++d + ) { + var p = (2 * Math.PI * d) / r, + h = m * Math.cos(p), + w = m * Math.sin(p) + if ( + (i.push(h, 0, w), + a.push(0, 1, 0), + f.push(1 - d / r, y / e), + y > 0 && d !== r) + ) { + var x = l + (d + 1), + F = l + d, + j = l + d - v, + O = l + (d + 1) - v + c.push(x, F, j), c.push(x, j, O) + } + } + l += r + 1 + } + return { position: i, normal: a, texcoord: f, indices: c } + } + function k(t) { + return function (r) { + var e = t.apply( + this, + Array.prototype.slice.call(arguments, 1) + ) + return o.createBuffersFromArrays(r, e) + } + } + function U(t) { + return function (r) { + var e = t.apply( + null, + Array.prototype.slice.call(arguments, 1) + ) + return o.createBufferInfoFromArrays(r, e) + } + } + var C = [ + 'numComponents', + 'size', + 'type', + 'normalize', + 'stride', + 'offset', + 'attrib', + 'name', + 'attribName', + ] + function W(t, r, e, n) { + n = n || 0 + for (var o = t.length, u = 0; u < o; ++u) r[e + u] = t[u] + n + } + function I(t, r) { + var e = s(t), + n = new e.constructor(r), + o = n + return ( + e.numComponents && e.numElements && y(n, e.numComponents), + t.data && + ((o = { data: n }), u.copyNamedProperties(C, t, o)), + o + ) + } + var L = U(T) + r.create3DFBufferInfo = L + var G = k(T) + r.create3DFBuffers = G + var B = U(S) + r.createCubeBufferInfo = B + var N = k(S) + r.createCubeBuffers = N + var X = U(O) + r.createPlaneBufferInfo = X + var D = k(O) + r.createPlaneBuffers = D + var H = U(E) + r.createSphereBufferInfo = H + var V = k(E) + r.createSphereBuffers = V + var Y = U(M) + r.createTruncatedConeBufferInfo = Y + var q = k(M) + r.createTruncatedConeBuffers = q + var K = U(j) + r.createXYQuadBufferInfo = K + var $ = k(j) + r.createXYQuadBuffers = $ + var Z = U(g) + r.createCrescentBufferInfo = Z + var J = k(g) + r.createCrescentBuffers = J + var Q = U(P) + r.createCylinderBufferInfo = Q + var tt = k(P) + r.createCylinderBuffers = tt + var rt = U(R) + r.createTorusBufferInfo = rt + var et = k(R) + r.createTorusBuffers = et + var nt = U(z) + r.createDiscBufferInfo = nt + var ot = k(z) + r.createDiscBuffers = ot + var ut = Z + r.createCresentBufferInfo = ut + var it = J + r.createCresentBuffers = it + var at = g + r.createCresentVertices = at + }, + function (t, r, e) { + 'use strict' + function n(t) { + return (n = + 'function' == typeof Symbol && + 'symbol' == typeof Symbol.iterator + ? function (t) { + return typeof t + } + : function (t) { + return t && + 'function' == typeof Symbol && + t.constructor === Symbol && + t !== Symbol.prototype + ? 'symbol' + : typeof t + })(t) + } + r.__esModule = !0 + var o = { + addExtensionsToContext: !0, + getContext: !0, + getWebGLContext: !0, + resizeCanvasToDisplaySize: !0, + setDefaults: !0, + attributes: !0, + textures: !0, + utils: !0, + draw: !0, + framebuffers: !0, + programs: !0, + typedarrays: !0, + vertexArrays: !0, + } + ;(r.addExtensionsToContext = x), + (r.framebuffers = r.draw = r.attributes = void 0), + (r.getContext = function (t, r) { + return (function (t, r) { + for ( + var e = ['webgl2', 'webgl', 'experimental-webgl'], + n = null, + o = 0; + o < e.length; + ++o + ) + if ((n = t.getContext(e[o], r))) { + d.addExtensionsToContext && x(n) + break + } + return n + })(t, r) + }), + (r.getWebGLContext = function (t, r) { + return (function (t, r) { + for ( + var e = ['webgl', 'experimental-webgl'], + n = null, + o = 0; + o < e.length; + ++o + ) + if ((n = t.getContext(e[o], r))) { + d.addExtensionsToContext && x(n) + break + } + return n + })(t, r) + }), + (r.programs = void 0), + (r.resizeCanvasToDisplaySize = function (t, r) { + ;(r = r || 1), (r = Math.max(0, r)) + var e = (t.clientWidth * r) | 0, + n = (t.clientHeight * r) | 0 + if (t.width !== e || t.height !== n) + return (t.width = e), (t.height = n), !0 + return !1 + }), + (r.setDefaults = function (t) { + a.copyExistingProperties(t, d), + u.setAttributeDefaults_(t), + i.setTextureDefaults_(t) + }), + (r.vertexArrays = r.utils = r.typedarrays = r.textures = void 0) + var u = m(e(6)) + ;(r.attributes = u), + Object.keys(u).forEach(function (t) { + 'default' !== t && + '__esModule' !== t && + (Object.prototype.hasOwnProperty.call(o, t) || + (t in r && r[t] === u[t]) || + (r[t] = u[t])) + }) + var i = m(e(7)) + ;(r.textures = i), + Object.keys(i).forEach(function (t) { + 'default' !== t && + '__esModule' !== t && + (Object.prototype.hasOwnProperty.call(o, t) || + (t in r && r[t] === i[t]) || + (r[t] = i[t])) + }) + var a = m(e(0)), + f = m(e(3)) + ;(r.utils = f), + Object.keys(f).forEach(function (t) { + 'default' !== t && + '__esModule' !== t && + (Object.prototype.hasOwnProperty.call(o, t) || + (t in r && r[t] === f[t]) || + (r[t] = f[t])) + }) + var c = m(e(11)) + ;(r.draw = c), + Object.keys(c).forEach(function (t) { + 'default' !== t && + '__esModule' !== t && + (Object.prototype.hasOwnProperty.call(o, t) || + (t in r && r[t] === c[t]) || + (r[t] = c[t])) + }) + var l = m(e(12)) + ;(r.framebuffers = l), + Object.keys(l).forEach(function (t) { + 'default' !== t && + '__esModule' !== t && + (Object.prototype.hasOwnProperty.call(o, t) || + (t in r && r[t] === l[t]) || + (r[t] = l[t])) + }) + var s = m(e(4)) + ;(r.programs = s), + Object.keys(s).forEach(function (t) { + 'default' !== t && + '__esModule' !== t && + (Object.prototype.hasOwnProperty.call(o, t) || + (t in r && r[t] === s[t]) || + (r[t] = s[t])) + }) + var v = m(e(1)) + ;(r.typedarrays = v), + Object.keys(v).forEach(function (t) { + 'default' !== t && + '__esModule' !== t && + (Object.prototype.hasOwnProperty.call(o, t) || + (t in r && r[t] === v[t]) || + (r[t] = v[t])) + }) + var y = m(e(13)) + function b(t) { + if ('function' != typeof WeakMap) return null + var r = new WeakMap(), + e = new WeakMap() + return (b = function (t) { + return t ? e : r + })(t) + } + function m(t, r) { + if (!r && t && t.__esModule) return t + if (null === t || ('object' !== n(t) && 'function' != typeof t)) + return { default: t } + var e = b(r) + if (e && e.has(t)) return e.get(t) + var o = {}, + u = Object.defineProperty && Object.getOwnPropertyDescriptor + for (var i in t) + if ( + 'default' !== i && + Object.prototype.hasOwnProperty.call(t, i) + ) { + var a = u ? Object.getOwnPropertyDescriptor(t, i) : null + a && (a.get || a.set) + ? Object.defineProperty(o, i, a) + : (o[i] = t[i]) + } + return (o.default = t), e && e.set(t, o), o + } + ;(r.vertexArrays = y), + Object.keys(y).forEach(function (t) { + 'default' !== t && + '__esModule' !== t && + (Object.prototype.hasOwnProperty.call(o, t) || + (t in r && r[t] === y[t]) || + (r[t] = y[t])) + }) + var d = { addExtensionsToContext: !0 } + var p = /^(.*?)_/ + function h(t, r) { + f.glEnumToString(t, 0) + var e = t.getExtension(r) + if (e) { + var n = {}, + o = p.exec(r)[1], + u = '_' + o + for (var i in e) { + var c = e[i], + l = 'function' == typeof c, + s = l ? o : u, + v = i + i.endsWith(s) && + (v = i.substring(0, i.length - s.length)), + void 0 !== t[v] + ? l || t[v] === c || a.warn(v, t[v], c, i) + : l + ? (t[v] = (function (t) { + return function () { + return t.apply(e, arguments) + } + })(c)) + : ((t[v] = c), (n[v] = c)) + } + ;(n.constructor = { name: e.constructor.name }), + f.glEnumToString(n, 0) + } + return e + } + var w = [ + 'ANGLE_instanced_arrays', + 'EXT_blend_minmax', + 'EXT_color_buffer_float', + 'EXT_color_buffer_half_float', + 'EXT_disjoint_timer_query', + 'EXT_disjoint_timer_query_webgl2', + 'EXT_frag_depth', + 'EXT_sRGB', + 'EXT_shader_texture_lod', + 'EXT_texture_filter_anisotropic', + 'OES_element_index_uint', + 'OES_standard_derivatives', + 'OES_texture_float', + 'OES_texture_float_linear', + 'OES_texture_half_float', + 'OES_texture_half_float_linear', + 'OES_vertex_array_object', + 'WEBGL_color_buffer_float', + 'WEBGL_compressed_texture_atc', + 'WEBGL_compressed_texture_etc1', + 'WEBGL_compressed_texture_pvrtc', + 'WEBGL_compressed_texture_s3tc', + 'WEBGL_compressed_texture_s3tc_srgb', + 'WEBGL_depth_texture', + 'WEBGL_draw_buffers', + ] + function x(t) { + for (var r = 0; r < w.length; ++r) h(t, w[r]) + } + }, + function (t, r, e) { + 'use strict' + function n(t) { + return (n = + 'function' == typeof Symbol && + 'symbol' == typeof Symbol.iterator + ? function (t) { + return typeof t + } + : function (t) { + return t && + 'function' == typeof Symbol && + t.constructor === Symbol && + t !== Symbol.prototype + ? 'symbol' + : typeof t + })(t) + } + ;(r.__esModule = !0), + (r.drawBufferInfo = i), + (r.drawObjectList = function (t, r) { + var e = null, + n = null + r.forEach(function (r) { + if (!1 !== r.active) { + var u = r.programInfo, + a = r.vertexArrayInfo || r.bufferInfo, + f = !1, + c = void 0 === r.type ? 4 : r.type + u !== e && + ((e = u), t.useProgram(u.program), (f = !0)), + (f || a !== n) && + (n && + n.vertexArrayObject && + !a.vertexArrayObject && + t.bindVertexArray(null), + (n = a), + o.setBuffersAndAttributes(t, u, a)), + o.setUniforms(u, r.uniforms), + i(t, a, c, r.count, r.offset, r.instanceCount) + } + }), + n && n.vertexArrayObject && t.bindVertexArray(null) + }) + var o = (function (t, r) { + if (!r && t && t.__esModule) return t + if (null === t || ('object' !== n(t) && 'function' != typeof t)) + return { default: t } + var e = u(r) + if (e && e.has(t)) return e.get(t) + var o = {}, + i = Object.defineProperty && Object.getOwnPropertyDescriptor + for (var a in t) + if ( + 'default' !== a && + Object.prototype.hasOwnProperty.call(t, a) + ) { + var f = i ? Object.getOwnPropertyDescriptor(t, a) : null + f && (f.get || f.set) + ? Object.defineProperty(o, a, f) + : (o[a] = t[a]) + } + ;(o.default = t), e && e.set(t, o) + return o + })(e(4)) + function u(t) { + if ('function' != typeof WeakMap) return null + var r = new WeakMap(), + e = new WeakMap() + return (u = function (t) { + return t ? e : r + })(t) + } + function i(t, r, e, n, o, u) { + e = void 0 === e ? 4 : e + var i = r.indices, + a = r.elementType, + f = void 0 === n ? r.numElements : n + ;(o = void 0 === o ? 0 : o), + a || i + ? void 0 !== u + ? t.drawElementsInstanced( + e, + f, + void 0 === a ? 5123 : r.elementType, + o, + u + ) + : t.drawElements( + e, + f, + void 0 === a ? 5123 : r.elementType, + o + ) + : void 0 !== u + ? t.drawArraysInstanced(e, o, f, u) + : t.drawArrays(e, o, f) + } + }, + function (t, r, e) { + 'use strict' + function n(t) { + return (n = + 'function' == typeof Symbol && + 'symbol' == typeof Symbol.iterator + ? function (t) { + return typeof t + } + : function (t) { + return t && + 'function' == typeof Symbol && + t.constructor === Symbol && + t !== Symbol.prototype + ? 'symbol' + : typeof t + })(t) + } + ;(r.__esModule = !0), + (r.bindFramebufferInfo = function (t, r, e) { + ;(e = e || 36160), + r + ? (t.bindFramebuffer(e, r.framebuffer), + t.viewport(0, 0, r.width, r.height)) + : (t.bindFramebuffer(e, null), + t.viewport( + 0, + 0, + t.drawingBufferWidth, + t.drawingBufferHeight + )) + }), + (r.createFramebufferInfo = function (t, r, e, n) { + var i = 36160, + a = t.createFramebuffer() + t.bindFramebuffer(i, a), + (e = e || t.drawingBufferWidth), + (n = n || t.drawingBufferHeight) + var c = [], + s = { + framebuffer: a, + attachments: [], + width: e, + height: n, + } + ;(r = r || m).forEach(function (r, a) { + var v = r.attachment, + m = r.samples, + h = r.format, + w = + r.attachmentPoint || + (function (t, r) { + return d[t] || d[r] + })(h, r.internalFormat) + if ( + (w || (w = l + a), + (function (t) { + return t >= l && t < 36096 + })(w) && c.push(w), + !v) + ) + if ( + void 0 !== m || + (function (t) { + return p[t] + })(h) + ) + (v = t.createRenderbuffer()), + t.bindRenderbuffer(f, v), + m > 1 + ? t.renderbufferStorageMultisample( + f, + m, + h, + e, + n + ) + : t.renderbufferStorage(f, h, e, n) + else { + var x = Object.assign({}, r) + ;(x.width = e), + (x.height = n), + void 0 === x.auto && + ((x.auto = !1), + (x.min = x.min || x.minMag || b), + (x.mag = x.mag || x.minMag || b), + (x.wrapS = x.wrapS || x.wrap || y), + (x.wrapT = x.wrapT || x.wrap || y)), + (v = o.createTexture(t, x)) + } + if (u.isRenderbuffer(t, v)) + t.framebufferRenderbuffer(i, w, f, v) + else { + if (!u.isTexture(t, v)) + throw new Error('unknown attachment type') + void 0 !== r.layer + ? t.framebufferTextureLayer( + i, + w, + v, + r.level || 0, + r.layer + ) + : t.framebufferTexture2D( + i, + w, + r.target || 3553, + v, + r.level || 0 + ) + } + s.attachments.push(v) + }), + t.drawBuffers && t.drawBuffers(c) + return s + }), + (r.resizeFramebufferInfo = function (t, r, e, n, i) { + ;(n = n || t.drawingBufferWidth), + (i = i || t.drawingBufferHeight), + (r.width = n), + (r.height = i), + (e = e || m).forEach(function (e, a) { + var c = r.attachments[a], + l = e.format, + s = e.samples + if (void 0 !== s || u.isRenderbuffer(t, c)) + t.bindRenderbuffer(f, c), + s > 1 + ? t.renderbufferStorageMultisample( + f, + s, + l, + n, + i + ) + : t.renderbufferStorage(f, l, n, i) + else { + if (!u.isTexture(t, c)) + throw new Error('unknown attachment type') + o.resizeTexture(t, c, e, n, i) + } + }) + }) + var o = a(e(7)), + u = a(e(0)) + function i(t) { + if ('function' != typeof WeakMap) return null + var r = new WeakMap(), + e = new WeakMap() + return (i = function (t) { + return t ? e : r + })(t) + } + function a(t, r) { + if (!r && t && t.__esModule) return t + if (null === t || ('object' !== n(t) && 'function' != typeof t)) + return { default: t } + var e = i(r) + if (e && e.has(t)) return e.get(t) + var o = {}, + u = Object.defineProperty && Object.getOwnPropertyDescriptor + for (var a in t) + if ( + 'default' !== a && + Object.prototype.hasOwnProperty.call(t, a) + ) { + var f = u ? Object.getOwnPropertyDescriptor(t, a) : null + f && (f.get || f.set) + ? Object.defineProperty(o, a, f) + : (o[a] = t[a]) + } + return (o.default = t), e && e.set(t, o), o + } + var f = 36161, + c = 34041, + l = 36064, + s = 36096, + v = 33306, + y = 33071, + b = 9729, + m = [ + { format: 6408, type: 5121, min: b, wrap: y }, + { format: c }, + ], + d = {} + ;(d[34041] = v), + (d[6401] = 36128), + (d[36168] = 36128), + (d[6402] = s), + (d[33189] = s), + (d[33190] = s), + (d[36012] = s), + (d[35056] = v), + (d[36013] = v) + var p = {} + ;(p[32854] = !0), + (p[32855] = !0), + (p[36194] = !0), + (p[34041] = !0), + (p[33189] = !0), + (p[6401] = !0), + (p[36168] = !0) + }, + function (t, r, e) { + 'use strict' + function n(t) { + return (n = + 'function' == typeof Symbol && + 'symbol' == typeof Symbol.iterator + ? function (t) { + return typeof t + } + : function (t) { + return t && + 'function' == typeof Symbol && + t.constructor === Symbol && + t !== Symbol.prototype + ? 'symbol' + : typeof t + })(t) + } + ;(r.__esModule = !0), + (r.createVAOAndSetAttributes = i), + (r.createVAOFromBufferInfo = function (t, r, e) { + return i(t, r.attribSetters || r, e.attribs, e.indices) + }), + (r.createVertexArrayInfo = function (t, r, e) { + var n = t.createVertexArray() + t.bindVertexArray(n), r.length || (r = [r]) + return ( + r.forEach(function (r) { + o.setBuffersAndAttributes(t, r, e) + }), + t.bindVertexArray(null), + { + numElements: e.numElements, + elementType: e.elementType, + vertexArrayObject: n, + } + ) + }) + var o = (function (t, r) { + if (!r && t && t.__esModule) return t + if (null === t || ('object' !== n(t) && 'function' != typeof t)) + return { default: t } + var e = u(r) + if (e && e.has(t)) return e.get(t) + var o = {}, + i = Object.defineProperty && Object.getOwnPropertyDescriptor + for (var a in t) + if ( + 'default' !== a && + Object.prototype.hasOwnProperty.call(t, a) + ) { + var f = i ? Object.getOwnPropertyDescriptor(t, a) : null + f && (f.get || f.set) + ? Object.defineProperty(o, a, f) + : (o[a] = t[a]) + } + ;(o.default = t), e && e.set(t, o) + return o + })(e(4)) + function u(t) { + if ('function' != typeof WeakMap) return null + var r = new WeakMap(), + e = new WeakMap() + return (u = function (t) { + return t ? e : r + })(t) + } + function i(t, r, e, n) { + var u = t.createVertexArray() + return ( + t.bindVertexArray(u), + o.setAttributes(r, e), + n && t.bindBuffer(34963, n), + t.bindVertexArray(null), + u + ) + } + }, + ]) +}) diff --git a/experiments/twgl-tunnel/dist/twgl-full.module.js b/experiments/twgl-tunnel/dist/twgl-full.module.js index 1fb42da..7ca2ff3 100644 --- a/experiments/twgl-tunnel/dist/twgl-full.module.js +++ b/experiments/twgl-tunnel/dist/twgl-full.module.js @@ -47,7 +47,7 @@ see: http://github.com/greggman/twgl.js for details */ * @module twgl/v3 */ -let VecType = Float32Array; +let VecType = Float32Array /** * A JavaScript array with 3 values or a Float32Array with 3 values. @@ -64,9 +64,9 @@ let VecType = Float32Array; * @memberOf module:twgl/v3 */ function setDefaultType$1(ctor) { - const oldType = VecType; - VecType = ctor; - return oldType; + const oldType = VecType + VecType = ctor + return oldType } /** @@ -78,17 +78,17 @@ function setDefaultType$1(ctor) { * @memberOf module:twgl/v3 */ function create$1(x, y, z) { - const dst = new VecType(3); - if (x) { - dst[0] = x; - } - if (y) { - dst[1] = y; - } - if (z) { - dst[2] = z; - } - return dst; + const dst = new VecType(3) + if (x) { + dst[0] = x + } + if (y) { + dst[1] = y + } + if (z) { + dst[2] = z + } + return dst } /** @@ -100,13 +100,13 @@ function create$1(x, y, z) { * @memberOf module:twgl/v3 */ function add(a, b, dst) { - dst = dst || new VecType(3); + dst = dst || new VecType(3) - dst[0] = a[0] + b[0]; - dst[1] = a[1] + b[1]; - dst[2] = a[2] + b[2]; + dst[0] = a[0] + b[0] + dst[1] = a[1] + b[1] + dst[2] = a[2] + b[2] - return dst; + return dst } /** @@ -118,13 +118,13 @@ function add(a, b, dst) { * @memberOf module:twgl/v3 */ function subtract(a, b, dst) { - dst = dst || new VecType(3); + dst = dst || new VecType(3) - dst[0] = a[0] - b[0]; - dst[1] = a[1] - b[1]; - dst[2] = a[2] - b[2]; + dst[0] = a[0] - b[0] + dst[1] = a[1] - b[1] + dst[2] = a[2] - b[2] - return dst; + return dst } /** @@ -139,13 +139,13 @@ function subtract(a, b, dst) { * @memberOf module:twgl/v3 */ function lerp(a, b, t, dst) { - dst = dst || new VecType(3); + dst = dst || new VecType(3) - dst[0] = a[0] + t * (b[0] - a[0]); - dst[1] = a[1] + t * (b[1] - a[1]); - dst[2] = a[2] + t * (b[2] - a[2]); + dst[0] = a[0] + t * (b[0] - a[0]) + dst[1] = a[1] + t * (b[1] - a[1]) + dst[2] = a[2] + t * (b[2] - a[2]) - return dst; + return dst } /** @@ -160,13 +160,13 @@ function lerp(a, b, t, dst) { * @memberOf module:twgl/v3 */ function lerpV(a, b, t, dst) { - dst = dst || new VecType(3); + dst = dst || new VecType(3) - dst[0] = a[0] + t[0] * (b[0] - a[0]); - dst[1] = a[1] + t[1] * (b[1] - a[1]); - dst[2] = a[2] + t[2] * (b[2] - a[2]); + dst[0] = a[0] + t[0] * (b[0] - a[0]) + dst[1] = a[1] + t[1] * (b[1] - a[1]) + dst[2] = a[2] + t[2] * (b[2] - a[2]) - return dst; + return dst } /** @@ -180,13 +180,13 @@ function lerpV(a, b, t, dst) { * @memberOf module:twgl/v3 */ function max(a, b, dst) { - dst = dst || new VecType(3); + dst = dst || new VecType(3) - dst[0] = Math.max(a[0], b[0]); - dst[1] = Math.max(a[1], b[1]); - dst[2] = Math.max(a[2], b[2]); + dst[0] = Math.max(a[0], b[0]) + dst[1] = Math.max(a[1], b[1]) + dst[2] = Math.max(a[2], b[2]) - return dst; + return dst } /** @@ -200,13 +200,13 @@ function max(a, b, dst) { * @memberOf module:twgl/v3 */ function min(a, b, dst) { - dst = dst || new VecType(3); + dst = dst || new VecType(3) - dst[0] = Math.min(a[0], b[0]); - dst[1] = Math.min(a[1], b[1]); - dst[2] = Math.min(a[2], b[2]); + dst[0] = Math.min(a[0], b[0]) + dst[1] = Math.min(a[1], b[1]) + dst[2] = Math.min(a[2], b[2]) - return dst; + return dst } /** @@ -218,13 +218,13 @@ function min(a, b, dst) { * @memberOf module:twgl/v3 */ function mulScalar(v, k, dst) { - dst = dst || new VecType(3); + dst = dst || new VecType(3) - dst[0] = v[0] * k; - dst[1] = v[1] * k; - dst[2] = v[2] * k; + dst[0] = v[0] * k + dst[1] = v[1] * k + dst[2] = v[2] * k - return dst; + return dst } /** @@ -236,13 +236,13 @@ function mulScalar(v, k, dst) { * @memberOf module:twgl/v3 */ function divScalar(v, k, dst) { - dst = dst || new VecType(3); + dst = dst || new VecType(3) - dst[0] = v[0] / k; - dst[1] = v[1] / k; - dst[2] = v[2] / k; + dst[0] = v[0] / k + dst[1] = v[1] / k + dst[2] = v[2] / k - return dst; + return dst } /** @@ -255,15 +255,15 @@ function divScalar(v, k, dst) { * @memberOf module:twgl/v3 */ function cross(a, b, dst) { - dst = dst || new VecType(3); + dst = dst || new VecType(3) - const t1 = a[2] * b[0] - a[0] * b[2]; - const t2 = a[0] * b[1] - a[1] * b[0]; - dst[0] = a[1] * b[2] - a[2] * b[1]; - dst[1] = t1; - dst[2] = t2; + const t1 = a[2] * b[0] - a[0] * b[2] + const t2 = a[0] * b[1] - a[1] * b[0] + dst[0] = a[1] * b[2] - a[2] * b[1] + dst[1] = t1 + dst[2] = t2 - return dst; + return dst } /** @@ -275,7 +275,7 @@ function cross(a, b, dst) { * @memberOf module:twgl/v3 */ function dot(a, b) { - return (a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]); + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] } /** @@ -285,7 +285,7 @@ function dot(a, b) { * @memberOf module:twgl/v3 */ function length$1(v) { - return Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); + return Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]) } /** @@ -295,7 +295,7 @@ function length$1(v) { * @memberOf module:twgl/v3 */ function lengthSq(v) { - return v[0] * v[0] + v[1] * v[1] + v[2] * v[2]; + return v[0] * v[0] + v[1] * v[1] + v[2] * v[2] } /** @@ -306,10 +306,10 @@ function lengthSq(v) { * @memberOf module:twgl/v3 */ function distance(a, b) { - const dx = a[0] - b[0]; - const dy = a[1] - b[1]; - const dz = a[2] - b[2]; - return Math.sqrt(dx * dx + dy * dy + dz * dz); + const dx = a[0] - b[0] + const dy = a[1] - b[1] + const dz = a[2] - b[2] + return Math.sqrt(dx * dx + dy * dy + dz * dz) } /** @@ -320,10 +320,10 @@ function distance(a, b) { * @memberOf module:twgl/v3 */ function distanceSq(a, b) { - const dx = a[0] - b[0]; - const dy = a[1] - b[1]; - const dz = a[2] - b[2]; - return dx * dx + dy * dy + dz * dz; + const dx = a[0] - b[0] + const dy = a[1] - b[1] + const dz = a[2] - b[2] + return dx * dx + dy * dy + dz * dz } /** @@ -334,21 +334,21 @@ function distanceSq(a, b) { * @memberOf module:twgl/v3 */ function normalize(a, dst) { - dst = dst || new VecType(3); - - const lenSq = a[0] * a[0] + a[1] * a[1] + a[2] * a[2]; - const len = Math.sqrt(lenSq); - if (len > 0.00001) { - dst[0] = a[0] / len; - dst[1] = a[1] / len; - dst[2] = a[2] / len; - } else { - dst[0] = 0; - dst[1] = 0; - dst[2] = 0; - } + dst = dst || new VecType(3) + + const lenSq = a[0] * a[0] + a[1] * a[1] + a[2] * a[2] + const len = Math.sqrt(lenSq) + if (len > 0.00001) { + dst[0] = a[0] / len + dst[1] = a[1] / len + dst[2] = a[2] / len + } else { + dst[0] = 0 + dst[1] = 0 + dst[2] = 0 + } - return dst; + return dst } /** @@ -359,13 +359,13 @@ function normalize(a, dst) { * @memberOf module:twgl/v3 */ function negate$1(v, dst) { - dst = dst || new VecType(3); + dst = dst || new VecType(3) - dst[0] = -v[0]; - dst[1] = -v[1]; - dst[2] = -v[2]; + dst[0] = -v[0] + dst[1] = -v[1] + dst[2] = -v[2] - return dst; + return dst } /** @@ -376,13 +376,13 @@ function negate$1(v, dst) { * @memberOf module:twgl/v3 */ function copy$1(v, dst) { - dst = dst || new VecType(3); + dst = dst || new VecType(3) - dst[0] = v[0]; - dst[1] = v[1]; - dst[2] = v[2]; + dst[0] = v[0] + dst[1] = v[1] + dst[2] = v[2] - return dst; + return dst } /** @@ -396,13 +396,13 @@ function copy$1(v, dst) { * @memberOf module:twgl/v3 */ function multiply$1(a, b, dst) { - dst = dst || new VecType(3); + dst = dst || new VecType(3) - dst[0] = a[0] * b[0]; - dst[1] = a[1] * b[1]; - dst[2] = a[2] * b[2]; + dst[0] = a[0] * b[0] + dst[1] = a[1] * b[1] + dst[2] = a[2] * b[2] - return dst; + return dst } /** @@ -416,39 +416,39 @@ function multiply$1(a, b, dst) { * @memberOf module:twgl/v3 */ function divide(a, b, dst) { - dst = dst || new VecType(3); - - dst[0] = a[0] / b[0]; - dst[1] = a[1] / b[1]; - dst[2] = a[2] / b[2]; - - return dst; -} - -var v3 = /*#__PURE__*/Object.freeze({ - __proto__: null, - add: add, - copy: copy$1, - create: create$1, - cross: cross, - distance: distance, - distanceSq: distanceSq, - divide: divide, - divScalar: divScalar, - dot: dot, - lerp: lerp, - lerpV: lerpV, - length: length$1, - lengthSq: lengthSq, - max: max, - min: min, - mulScalar: mulScalar, - multiply: multiply$1, - negate: negate$1, - normalize: normalize, - setDefaultType: setDefaultType$1, - subtract: subtract -}); + dst = dst || new VecType(3) + + dst[0] = a[0] / b[0] + dst[1] = a[1] / b[1] + dst[2] = a[2] / b[2] + + return dst +} + +var v3 = /*#__PURE__*/ Object.freeze({ + __proto__: null, + add: add, + copy: copy$1, + create: create$1, + cross: cross, + distance: distance, + distanceSq: distanceSq, + divide: divide, + divScalar: divScalar, + dot: dot, + lerp: lerp, + lerpV: lerpV, + length: length$1, + lengthSq: lengthSq, + max: max, + min: min, + mulScalar: mulScalar, + multiply: multiply$1, + negate: negate$1, + normalize: normalize, + setDefaultType: setDefaultType$1, + subtract: subtract, +}) /* * Copyright 2019 Gregg Tavares @@ -496,7 +496,7 @@ var v3 = /*#__PURE__*/Object.freeze({ * * @module twgl/m4 */ -let MatType = Float32Array; +let MatType = Float32Array /** * A JavaScript array with 16 values or a Float32Array with 16 values. @@ -513,9 +513,9 @@ let MatType = Float32Array; * @memberOf module:twgl/m4 */ function setDefaultType(ctor) { - const oldType = MatType; - MatType = ctor; - return oldType; + const oldType = MatType + MatType = ctor + return oldType } /** @@ -526,26 +526,26 @@ function setDefaultType(ctor) { * @memberOf module:twgl/m4 */ function negate(m, dst) { - dst = dst || new MatType(16); + dst = dst || new MatType(16) - dst[ 0] = -m[ 0]; - dst[ 1] = -m[ 1]; - dst[ 2] = -m[ 2]; - dst[ 3] = -m[ 3]; - dst[ 4] = -m[ 4]; - dst[ 5] = -m[ 5]; - dst[ 6] = -m[ 6]; - dst[ 7] = -m[ 7]; - dst[ 8] = -m[ 8]; - dst[ 9] = -m[ 9]; - dst[10] = -m[10]; - dst[11] = -m[11]; - dst[12] = -m[12]; - dst[13] = -m[13]; - dst[14] = -m[14]; - dst[15] = -m[15]; + dst[0] = -m[0] + dst[1] = -m[1] + dst[2] = -m[2] + dst[3] = -m[3] + dst[4] = -m[4] + dst[5] = -m[5] + dst[6] = -m[6] + dst[7] = -m[7] + dst[8] = -m[8] + dst[9] = -m[9] + dst[10] = -m[10] + dst[11] = -m[11] + dst[12] = -m[12] + dst[13] = -m[13] + dst[14] = -m[14] + dst[15] = -m[15] - return dst; + return dst } /** @@ -554,7 +554,7 @@ function negate(m, dst) { * @memberOf module:twgl/m4 */ function create() { - return new MatType(16).fill(0); + return new MatType(16).fill(0) } /** @@ -565,26 +565,26 @@ function create() { * @memberOf module:twgl/m4 */ function copy(m, dst) { - dst = dst || new MatType(16); + dst = dst || new MatType(16) - dst[ 0] = m[ 0]; - dst[ 1] = m[ 1]; - dst[ 2] = m[ 2]; - dst[ 3] = m[ 3]; - dst[ 4] = m[ 4]; - dst[ 5] = m[ 5]; - dst[ 6] = m[ 6]; - dst[ 7] = m[ 7]; - dst[ 8] = m[ 8]; - dst[ 9] = m[ 9]; - dst[10] = m[10]; - dst[11] = m[11]; - dst[12] = m[12]; - dst[13] = m[13]; - dst[14] = m[14]; - dst[15] = m[15]; + dst[0] = m[0] + dst[1] = m[1] + dst[2] = m[2] + dst[3] = m[3] + dst[4] = m[4] + dst[5] = m[5] + dst[6] = m[6] + dst[7] = m[7] + dst[8] = m[8] + dst[9] = m[9] + dst[10] = m[10] + dst[11] = m[11] + dst[12] = m[12] + dst[13] = m[13] + dst[14] = m[14] + dst[15] = m[15] - return dst; + return dst } /** @@ -595,26 +595,26 @@ function copy(m, dst) { * @memberOf module:twgl/m4 */ function identity(dst) { - dst = dst || new MatType(16); + dst = dst || new MatType(16) - dst[ 0] = 1; - dst[ 1] = 0; - dst[ 2] = 0; - dst[ 3] = 0; - dst[ 4] = 0; - dst[ 5] = 1; - dst[ 6] = 0; - dst[ 7] = 0; - dst[ 8] = 0; - dst[ 9] = 0; - dst[10] = 1; - dst[11] = 0; - dst[12] = 0; - dst[13] = 0; - dst[14] = 0; - dst[15] = 1; + dst[0] = 1 + dst[1] = 0 + dst[2] = 0 + dst[3] = 0 + dst[4] = 0 + dst[5] = 1 + dst[6] = 0 + dst[7] = 0 + dst[8] = 0 + dst[9] = 0 + dst[10] = 1 + dst[11] = 0 + dst[12] = 0 + dst[13] = 0 + dst[14] = 0 + dst[15] = 1 - return dst; + return dst } /** @@ -624,72 +624,72 @@ function identity(dst) { * @return {module:twgl/m4.Mat4} The transpose of m. * @memberOf module:twgl/m4 */ - function transpose(m, dst) { - dst = dst || new MatType(16); - if (dst === m) { - let t; - - t = m[1]; - m[1] = m[4]; - m[4] = t; - - t = m[2]; - m[2] = m[8]; - m[8] = t; - - t = m[3]; - m[3] = m[12]; - m[12] = t; - - t = m[6]; - m[6] = m[9]; - m[9] = t; - - t = m[7]; - m[7] = m[13]; - m[13] = t; - - t = m[11]; - m[11] = m[14]; - m[14] = t; - return dst; - } - - const m00 = m[0 * 4 + 0]; - const m01 = m[0 * 4 + 1]; - const m02 = m[0 * 4 + 2]; - const m03 = m[0 * 4 + 3]; - const m10 = m[1 * 4 + 0]; - const m11 = m[1 * 4 + 1]; - const m12 = m[1 * 4 + 2]; - const m13 = m[1 * 4 + 3]; - const m20 = m[2 * 4 + 0]; - const m21 = m[2 * 4 + 1]; - const m22 = m[2 * 4 + 2]; - const m23 = m[2 * 4 + 3]; - const m30 = m[3 * 4 + 0]; - const m31 = m[3 * 4 + 1]; - const m32 = m[3 * 4 + 2]; - const m33 = m[3 * 4 + 3]; - - dst[ 0] = m00; - dst[ 1] = m10; - dst[ 2] = m20; - dst[ 3] = m30; - dst[ 4] = m01; - dst[ 5] = m11; - dst[ 6] = m21; - dst[ 7] = m31; - dst[ 8] = m02; - dst[ 9] = m12; - dst[10] = m22; - dst[11] = m32; - dst[12] = m03; - dst[13] = m13; - dst[14] = m23; - dst[15] = m33; - - return dst; +function transpose(m, dst) { + dst = dst || new MatType(16) + if (dst === m) { + let t + + t = m[1] + m[1] = m[4] + m[4] = t + + t = m[2] + m[2] = m[8] + m[8] = t + + t = m[3] + m[3] = m[12] + m[12] = t + + t = m[6] + m[6] = m[9] + m[9] = t + + t = m[7] + m[7] = m[13] + m[13] = t + + t = m[11] + m[11] = m[14] + m[14] = t + return dst + } + + const m00 = m[0 * 4 + 0] + const m01 = m[0 * 4 + 1] + const m02 = m[0 * 4 + 2] + const m03 = m[0 * 4 + 3] + const m10 = m[1 * 4 + 0] + const m11 = m[1 * 4 + 1] + const m12 = m[1 * 4 + 2] + const m13 = m[1 * 4 + 3] + const m20 = m[2 * 4 + 0] + const m21 = m[2 * 4 + 1] + const m22 = m[2 * 4 + 2] + const m23 = m[2 * 4 + 3] + const m30 = m[3 * 4 + 0] + const m31 = m[3 * 4 + 1] + const m32 = m[3 * 4 + 2] + const m33 = m[3 * 4 + 3] + + dst[0] = m00 + dst[1] = m10 + dst[2] = m20 + dst[3] = m30 + dst[4] = m01 + dst[5] = m11 + dst[6] = m21 + dst[7] = m31 + dst[8] = m02 + dst[9] = m12 + dst[10] = m22 + dst[11] = m32 + dst[12] = m03 + dst[13] = m13 + dst[14] = m23 + dst[15] = m33 + + return dst } /** @@ -700,90 +700,150 @@ function identity(dst) { * @memberOf module:twgl/m4 */ function inverse(m, dst) { - dst = dst || new MatType(16); - - const m00 = m[0 * 4 + 0]; - const m01 = m[0 * 4 + 1]; - const m02 = m[0 * 4 + 2]; - const m03 = m[0 * 4 + 3]; - const m10 = m[1 * 4 + 0]; - const m11 = m[1 * 4 + 1]; - const m12 = m[1 * 4 + 2]; - const m13 = m[1 * 4 + 3]; - const m20 = m[2 * 4 + 0]; - const m21 = m[2 * 4 + 1]; - const m22 = m[2 * 4 + 2]; - const m23 = m[2 * 4 + 3]; - const m30 = m[3 * 4 + 0]; - const m31 = m[3 * 4 + 1]; - const m32 = m[3 * 4 + 2]; - const m33 = m[3 * 4 + 3]; - const tmp_0 = m22 * m33; - const tmp_1 = m32 * m23; - const tmp_2 = m12 * m33; - const tmp_3 = m32 * m13; - const tmp_4 = m12 * m23; - const tmp_5 = m22 * m13; - const tmp_6 = m02 * m33; - const tmp_7 = m32 * m03; - const tmp_8 = m02 * m23; - const tmp_9 = m22 * m03; - const tmp_10 = m02 * m13; - const tmp_11 = m12 * m03; - const tmp_12 = m20 * m31; - const tmp_13 = m30 * m21; - const tmp_14 = m10 * m31; - const tmp_15 = m30 * m11; - const tmp_16 = m10 * m21; - const tmp_17 = m20 * m11; - const tmp_18 = m00 * m31; - const tmp_19 = m30 * m01; - const tmp_20 = m00 * m21; - const tmp_21 = m20 * m01; - const tmp_22 = m00 * m11; - const tmp_23 = m10 * m01; - - const t0 = (tmp_0 * m11 + tmp_3 * m21 + tmp_4 * m31) - - (tmp_1 * m11 + tmp_2 * m21 + tmp_5 * m31); - const t1 = (tmp_1 * m01 + tmp_6 * m21 + tmp_9 * m31) - - (tmp_0 * m01 + tmp_7 * m21 + tmp_8 * m31); - const t2 = (tmp_2 * m01 + tmp_7 * m11 + tmp_10 * m31) - - (tmp_3 * m01 + tmp_6 * m11 + tmp_11 * m31); - const t3 = (tmp_5 * m01 + tmp_8 * m11 + tmp_11 * m21) - - (tmp_4 * m01 + tmp_9 * m11 + tmp_10 * m21); - - const d = 1.0 / (m00 * t0 + m10 * t1 + m20 * t2 + m30 * t3); - - dst[ 0] = d * t0; - dst[ 1] = d * t1; - dst[ 2] = d * t2; - dst[ 3] = d * t3; - dst[ 4] = d * ((tmp_1 * m10 + tmp_2 * m20 + tmp_5 * m30) - - (tmp_0 * m10 + tmp_3 * m20 + tmp_4 * m30)); - dst[ 5] = d * ((tmp_0 * m00 + tmp_7 * m20 + tmp_8 * m30) - - (tmp_1 * m00 + tmp_6 * m20 + tmp_9 * m30)); - dst[ 6] = d * ((tmp_3 * m00 + tmp_6 * m10 + tmp_11 * m30) - - (tmp_2 * m00 + tmp_7 * m10 + tmp_10 * m30)); - dst[ 7] = d * ((tmp_4 * m00 + tmp_9 * m10 + tmp_10 * m20) - - (tmp_5 * m00 + tmp_8 * m10 + tmp_11 * m20)); - dst[ 8] = d * ((tmp_12 * m13 + tmp_15 * m23 + tmp_16 * m33) - - (tmp_13 * m13 + tmp_14 * m23 + tmp_17 * m33)); - dst[ 9] = d * ((tmp_13 * m03 + tmp_18 * m23 + tmp_21 * m33) - - (tmp_12 * m03 + tmp_19 * m23 + tmp_20 * m33)); - dst[10] = d * ((tmp_14 * m03 + tmp_19 * m13 + tmp_22 * m33) - - (tmp_15 * m03 + tmp_18 * m13 + tmp_23 * m33)); - dst[11] = d * ((tmp_17 * m03 + tmp_20 * m13 + tmp_23 * m23) - - (tmp_16 * m03 + tmp_21 * m13 + tmp_22 * m23)); - dst[12] = d * ((tmp_14 * m22 + tmp_17 * m32 + tmp_13 * m12) - - (tmp_16 * m32 + tmp_12 * m12 + tmp_15 * m22)); - dst[13] = d * ((tmp_20 * m32 + tmp_12 * m02 + tmp_19 * m22) - - (tmp_18 * m22 + tmp_21 * m32 + tmp_13 * m02)); - dst[14] = d * ((tmp_18 * m12 + tmp_23 * m32 + tmp_15 * m02) - - (tmp_22 * m32 + tmp_14 * m02 + tmp_19 * m12)); - dst[15] = d * ((tmp_22 * m22 + tmp_16 * m02 + tmp_21 * m12) - - (tmp_20 * m12 + tmp_23 * m22 + tmp_17 * m02)); - - return dst; + dst = dst || new MatType(16) + + const m00 = m[0 * 4 + 0] + const m01 = m[0 * 4 + 1] + const m02 = m[0 * 4 + 2] + const m03 = m[0 * 4 + 3] + const m10 = m[1 * 4 + 0] + const m11 = m[1 * 4 + 1] + const m12 = m[1 * 4 + 2] + const m13 = m[1 * 4 + 3] + const m20 = m[2 * 4 + 0] + const m21 = m[2 * 4 + 1] + const m22 = m[2 * 4 + 2] + const m23 = m[2 * 4 + 3] + const m30 = m[3 * 4 + 0] + const m31 = m[3 * 4 + 1] + const m32 = m[3 * 4 + 2] + const m33 = m[3 * 4 + 3] + const tmp_0 = m22 * m33 + const tmp_1 = m32 * m23 + const tmp_2 = m12 * m33 + const tmp_3 = m32 * m13 + const tmp_4 = m12 * m23 + const tmp_5 = m22 * m13 + const tmp_6 = m02 * m33 + const tmp_7 = m32 * m03 + const tmp_8 = m02 * m23 + const tmp_9 = m22 * m03 + const tmp_10 = m02 * m13 + const tmp_11 = m12 * m03 + const tmp_12 = m20 * m31 + const tmp_13 = m30 * m21 + const tmp_14 = m10 * m31 + const tmp_15 = m30 * m11 + const tmp_16 = m10 * m21 + const tmp_17 = m20 * m11 + const tmp_18 = m00 * m31 + const tmp_19 = m30 * m01 + const tmp_20 = m00 * m21 + const tmp_21 = m20 * m01 + const tmp_22 = m00 * m11 + const tmp_23 = m10 * m01 + + const t0 = + tmp_0 * m11 + + tmp_3 * m21 + + tmp_4 * m31 - + (tmp_1 * m11 + tmp_2 * m21 + tmp_5 * m31) + const t1 = + tmp_1 * m01 + + tmp_6 * m21 + + tmp_9 * m31 - + (tmp_0 * m01 + tmp_7 * m21 + tmp_8 * m31) + const t2 = + tmp_2 * m01 + + tmp_7 * m11 + + tmp_10 * m31 - + (tmp_3 * m01 + tmp_6 * m11 + tmp_11 * m31) + const t3 = + tmp_5 * m01 + + tmp_8 * m11 + + tmp_11 * m21 - + (tmp_4 * m01 + tmp_9 * m11 + tmp_10 * m21) + + const d = 1.0 / (m00 * t0 + m10 * t1 + m20 * t2 + m30 * t3) + + dst[0] = d * t0 + dst[1] = d * t1 + dst[2] = d * t2 + dst[3] = d * t3 + dst[4] = + d * + (tmp_1 * m10 + + tmp_2 * m20 + + tmp_5 * m30 - + (tmp_0 * m10 + tmp_3 * m20 + tmp_4 * m30)) + dst[5] = + d * + (tmp_0 * m00 + + tmp_7 * m20 + + tmp_8 * m30 - + (tmp_1 * m00 + tmp_6 * m20 + tmp_9 * m30)) + dst[6] = + d * + (tmp_3 * m00 + + tmp_6 * m10 + + tmp_11 * m30 - + (tmp_2 * m00 + tmp_7 * m10 + tmp_10 * m30)) + dst[7] = + d * + (tmp_4 * m00 + + tmp_9 * m10 + + tmp_10 * m20 - + (tmp_5 * m00 + tmp_8 * m10 + tmp_11 * m20)) + dst[8] = + d * + (tmp_12 * m13 + + tmp_15 * m23 + + tmp_16 * m33 - + (tmp_13 * m13 + tmp_14 * m23 + tmp_17 * m33)) + dst[9] = + d * + (tmp_13 * m03 + + tmp_18 * m23 + + tmp_21 * m33 - + (tmp_12 * m03 + tmp_19 * m23 + tmp_20 * m33)) + dst[10] = + d * + (tmp_14 * m03 + + tmp_19 * m13 + + tmp_22 * m33 - + (tmp_15 * m03 + tmp_18 * m13 + tmp_23 * m33)) + dst[11] = + d * + (tmp_17 * m03 + + tmp_20 * m13 + + tmp_23 * m23 - + (tmp_16 * m03 + tmp_21 * m13 + tmp_22 * m23)) + dst[12] = + d * + (tmp_14 * m22 + + tmp_17 * m32 + + tmp_13 * m12 - + (tmp_16 * m32 + tmp_12 * m12 + tmp_15 * m22)) + dst[13] = + d * + (tmp_20 * m32 + + tmp_12 * m02 + + tmp_19 * m22 - + (tmp_18 * m22 + tmp_21 * m32 + tmp_13 * m02)) + dst[14] = + d * + (tmp_18 * m12 + + tmp_23 * m32 + + tmp_15 * m02 - + (tmp_22 * m32 + tmp_14 * m02 + tmp_19 * m12)) + dst[15] = + d * + (tmp_22 * m22 + + tmp_16 * m02 + + tmp_21 * m12 - + (tmp_20 * m12 + tmp_23 * m22 + tmp_17 * m02)) + + return dst } /** @@ -795,59 +855,59 @@ function inverse(m, dst) { * @memberOf module:twgl/m4 */ function multiply(a, b, dst) { - dst = dst || new MatType(16); - - const a00 = a[0]; - const a01 = a[1]; - const a02 = a[2]; - const a03 = a[3]; - const a10 = a[ 4 + 0]; - const a11 = a[ 4 + 1]; - const a12 = a[ 4 + 2]; - const a13 = a[ 4 + 3]; - const a20 = a[ 8 + 0]; - const a21 = a[ 8 + 1]; - const a22 = a[ 8 + 2]; - const a23 = a[ 8 + 3]; - const a30 = a[12 + 0]; - const a31 = a[12 + 1]; - const a32 = a[12 + 2]; - const a33 = a[12 + 3]; - const b00 = b[0]; - const b01 = b[1]; - const b02 = b[2]; - const b03 = b[3]; - const b10 = b[ 4 + 0]; - const b11 = b[ 4 + 1]; - const b12 = b[ 4 + 2]; - const b13 = b[ 4 + 3]; - const b20 = b[ 8 + 0]; - const b21 = b[ 8 + 1]; - const b22 = b[ 8 + 2]; - const b23 = b[ 8 + 3]; - const b30 = b[12 + 0]; - const b31 = b[12 + 1]; - const b32 = b[12 + 2]; - const b33 = b[12 + 3]; - - dst[ 0] = a00 * b00 + a10 * b01 + a20 * b02 + a30 * b03; - dst[ 1] = a01 * b00 + a11 * b01 + a21 * b02 + a31 * b03; - dst[ 2] = a02 * b00 + a12 * b01 + a22 * b02 + a32 * b03; - dst[ 3] = a03 * b00 + a13 * b01 + a23 * b02 + a33 * b03; - dst[ 4] = a00 * b10 + a10 * b11 + a20 * b12 + a30 * b13; - dst[ 5] = a01 * b10 + a11 * b11 + a21 * b12 + a31 * b13; - dst[ 6] = a02 * b10 + a12 * b11 + a22 * b12 + a32 * b13; - dst[ 7] = a03 * b10 + a13 * b11 + a23 * b12 + a33 * b13; - dst[ 8] = a00 * b20 + a10 * b21 + a20 * b22 + a30 * b23; - dst[ 9] = a01 * b20 + a11 * b21 + a21 * b22 + a31 * b23; - dst[10] = a02 * b20 + a12 * b21 + a22 * b22 + a32 * b23; - dst[11] = a03 * b20 + a13 * b21 + a23 * b22 + a33 * b23; - dst[12] = a00 * b30 + a10 * b31 + a20 * b32 + a30 * b33; - dst[13] = a01 * b30 + a11 * b31 + a21 * b32 + a31 * b33; - dst[14] = a02 * b30 + a12 * b31 + a22 * b32 + a32 * b33; - dst[15] = a03 * b30 + a13 * b31 + a23 * b32 + a33 * b33; - - return dst; + dst = dst || new MatType(16) + + const a00 = a[0] + const a01 = a[1] + const a02 = a[2] + const a03 = a[3] + const a10 = a[4 + 0] + const a11 = a[4 + 1] + const a12 = a[4 + 2] + const a13 = a[4 + 3] + const a20 = a[8 + 0] + const a21 = a[8 + 1] + const a22 = a[8 + 2] + const a23 = a[8 + 3] + const a30 = a[12 + 0] + const a31 = a[12 + 1] + const a32 = a[12 + 2] + const a33 = a[12 + 3] + const b00 = b[0] + const b01 = b[1] + const b02 = b[2] + const b03 = b[3] + const b10 = b[4 + 0] + const b11 = b[4 + 1] + const b12 = b[4 + 2] + const b13 = b[4 + 3] + const b20 = b[8 + 0] + const b21 = b[8 + 1] + const b22 = b[8 + 2] + const b23 = b[8 + 3] + const b30 = b[12 + 0] + const b31 = b[12 + 1] + const b32 = b[12 + 2] + const b33 = b[12 + 3] + + dst[0] = a00 * b00 + a10 * b01 + a20 * b02 + a30 * b03 + dst[1] = a01 * b00 + a11 * b01 + a21 * b02 + a31 * b03 + dst[2] = a02 * b00 + a12 * b01 + a22 * b02 + a32 * b03 + dst[3] = a03 * b00 + a13 * b01 + a23 * b02 + a33 * b03 + dst[4] = a00 * b10 + a10 * b11 + a20 * b12 + a30 * b13 + dst[5] = a01 * b10 + a11 * b11 + a21 * b12 + a31 * b13 + dst[6] = a02 * b10 + a12 * b11 + a22 * b12 + a32 * b13 + dst[7] = a03 * b10 + a13 * b11 + a23 * b12 + a33 * b13 + dst[8] = a00 * b20 + a10 * b21 + a20 * b22 + a30 * b23 + dst[9] = a01 * b20 + a11 * b21 + a21 * b22 + a31 * b23 + dst[10] = a02 * b20 + a12 * b21 + a22 * b22 + a32 * b23 + dst[11] = a03 * b20 + a13 * b21 + a23 * b22 + a33 * b23 + dst[12] = a00 * b30 + a10 * b31 + a20 * b32 + a30 * b33 + dst[13] = a01 * b30 + a11 * b31 + a21 * b32 + a31 * b33 + dst[14] = a02 * b30 + a12 * b31 + a22 * b32 + a32 * b33 + dst[15] = a03 * b30 + a13 * b31 + a23 * b32 + a33 * b33 + + return dst } /** @@ -860,26 +920,26 @@ function multiply(a, b, dst) { * @memberOf module:twgl/m4 */ function setTranslation(a, v, dst) { - dst = dst || identity(); - if (a !== dst) { - dst[ 0] = a[ 0]; - dst[ 1] = a[ 1]; - dst[ 2] = a[ 2]; - dst[ 3] = a[ 3]; - dst[ 4] = a[ 4]; - dst[ 5] = a[ 5]; - dst[ 6] = a[ 6]; - dst[ 7] = a[ 7]; - dst[ 8] = a[ 8]; - dst[ 9] = a[ 9]; - dst[10] = a[10]; - dst[11] = a[11]; - } - dst[12] = v[0]; - dst[13] = v[1]; - dst[14] = v[2]; - dst[15] = 1; - return dst; + dst = dst || identity() + if (a !== dst) { + dst[0] = a[0] + dst[1] = a[1] + dst[2] = a[2] + dst[3] = a[3] + dst[4] = a[4] + dst[5] = a[5] + dst[6] = a[6] + dst[7] = a[7] + dst[8] = a[8] + dst[9] = a[9] + dst[10] = a[10] + dst[11] = a[11] + } + dst[12] = v[0] + dst[13] = v[1] + dst[14] = v[2] + dst[15] = 1 + return dst } /** @@ -891,11 +951,11 @@ function setTranslation(a, v, dst) { * @memberOf module:twgl/m4 */ function getTranslation(m, dst) { - dst = dst || create$1(); - dst[0] = m[12]; - dst[1] = m[13]; - dst[2] = m[14]; - return dst; + dst = dst || create$1() + dst[0] = m[12] + dst[1] = m[13] + dst[2] = m[14] + return dst } /** @@ -907,12 +967,12 @@ function getTranslation(m, dst) { * @memberOf module:twgl/m4 */ function getAxis(m, axis, dst) { - dst = dst || create$1(); - const off = axis * 4; - dst[0] = m[off + 0]; - dst[1] = m[off + 1]; - dst[2] = m[off + 2]; - return dst; + dst = dst || create$1() + const off = axis * 4 + dst[0] = m[off + 0] + dst[1] = m[off + 1] + dst[2] = m[off + 2] + return dst } /** @@ -925,14 +985,14 @@ function getAxis(m, axis, dst) { * @memberOf module:twgl/m4 */ function setAxis(a, v, axis, dst) { - if (dst !== a) { - dst = copy(a, dst); - } - const off = axis * 4; - dst[off + 0] = v[0]; - dst[off + 1] = v[1]; - dst[off + 2] = v[2]; - return dst; + if (dst !== a) { + dst = copy(a, dst) + } + const off = axis * 4 + dst[off + 0] = v[0] + dst[off + 1] = v[1] + dst[off + 2] = v[2] + return dst } /** @@ -957,32 +1017,32 @@ function setAxis(a, v, axis, dst) { * @memberOf module:twgl/m4 */ function perspective(fieldOfViewYInRadians, aspect, zNear, zFar, dst) { - dst = dst || new MatType(16); + dst = dst || new MatType(16) - const f = Math.tan(Math.PI * 0.5 - 0.5 * fieldOfViewYInRadians); - const rangeInv = 1.0 / (zNear - zFar); + const f = Math.tan(Math.PI * 0.5 - 0.5 * fieldOfViewYInRadians) + const rangeInv = 1.0 / (zNear - zFar) - dst[0] = f / aspect; - dst[1] = 0; - dst[2] = 0; - dst[3] = 0; + dst[0] = f / aspect + dst[1] = 0 + dst[2] = 0 + dst[3] = 0 - dst[4] = 0; - dst[5] = f; - dst[6] = 0; - dst[7] = 0; + dst[4] = 0 + dst[5] = f + dst[6] = 0 + dst[7] = 0 - dst[8] = 0; - dst[9] = 0; - dst[10] = (zNear + zFar) * rangeInv; - dst[11] = -1; + dst[8] = 0 + dst[9] = 0 + dst[10] = (zNear + zFar) * rangeInv + dst[11] = -1 - dst[12] = 0; - dst[13] = 0; - dst[14] = zNear * zFar * rangeInv * 2; - dst[15] = 0; + dst[12] = 0 + dst[13] = 0 + dst[14] = zNear * zFar * rangeInv * 2 + dst[15] = 0 - return dst; + return dst } /** @@ -1002,29 +1062,29 @@ function perspective(fieldOfViewYInRadians, aspect, zNear, zFar, dst) { * @memberOf module:twgl/m4 */ function ortho(left, right, bottom, top, near, far, dst) { - dst = dst || new MatType(16); + dst = dst || new MatType(16) - dst[0] = 2 / (right - left); - dst[1] = 0; - dst[2] = 0; - dst[3] = 0; + dst[0] = 2 / (right - left) + dst[1] = 0 + dst[2] = 0 + dst[3] = 0 - dst[4] = 0; - dst[5] = 2 / (top - bottom); - dst[6] = 0; - dst[7] = 0; + dst[4] = 0 + dst[5] = 2 / (top - bottom) + dst[6] = 0 + dst[7] = 0 - dst[8] = 0; - dst[9] = 0; - dst[10] = 2 / (near - far); - dst[11] = 0; + dst[8] = 0 + dst[9] = 0 + dst[10] = 2 / (near - far) + dst[11] = 0 - dst[12] = (right + left) / (left - right); - dst[13] = (top + bottom) / (bottom - top); - dst[14] = (far + near) / (near - far); - dst[15] = 1; + dst[12] = (right + left) / (left - right) + dst[13] = (top + bottom) / (bottom - top) + dst[14] = (far + near) / (near - far) + dst[15] = 1 - return dst; + return dst } /** @@ -1047,35 +1107,35 @@ function ortho(left, right, bottom, top, near, far, dst) { * @memberOf module:twgl/m4 */ function frustum(left, right, bottom, top, near, far, dst) { - dst = dst || new MatType(16); + dst = dst || new MatType(16) - const dx = (right - left); - const dy = (top - bottom); - const dz = (near - far); + const dx = right - left + const dy = top - bottom + const dz = near - far - dst[ 0] = 2 * near / dx; - dst[ 1] = 0; - dst[ 2] = 0; - dst[ 3] = 0; - dst[ 4] = 0; - dst[ 5] = 2 * near / dy; - dst[ 6] = 0; - dst[ 7] = 0; - dst[ 8] = (left + right) / dx; - dst[ 9] = (top + bottom) / dy; - dst[10] = far / dz; - dst[11] = -1; - dst[12] = 0; - dst[13] = 0; - dst[14] = near * far / dz; - dst[15] = 0; + dst[0] = (2 * near) / dx + dst[1] = 0 + dst[2] = 0 + dst[3] = 0 + dst[4] = 0 + dst[5] = (2 * near) / dy + dst[6] = 0 + dst[7] = 0 + dst[8] = (left + right) / dx + dst[9] = (top + bottom) / dy + dst[10] = far / dz + dst[11] = -1 + dst[12] = 0 + dst[13] = 0 + dst[14] = (near * far) / dz + dst[15] = 0 - return dst; + return dst } -let xAxis; -let yAxis; -let zAxis; +let xAxis +let yAxis +let zAxis /** * Computes a 4-by-4 look-at transformation. @@ -1092,35 +1152,34 @@ let zAxis; * @memberOf module:twgl/m4 */ function lookAt(eye, target, up, dst) { - dst = dst || new MatType(16); - - xAxis = xAxis || create$1(); - yAxis = yAxis || create$1(); - zAxis = zAxis || create$1(); - - normalize( - subtract(eye, target, zAxis), zAxis); - normalize(cross(up, zAxis, xAxis), xAxis); - normalize(cross(zAxis, xAxis, yAxis), yAxis); - - dst[ 0] = xAxis[0]; - dst[ 1] = xAxis[1]; - dst[ 2] = xAxis[2]; - dst[ 3] = 0; - dst[ 4] = yAxis[0]; - dst[ 5] = yAxis[1]; - dst[ 6] = yAxis[2]; - dst[ 7] = 0; - dst[ 8] = zAxis[0]; - dst[ 9] = zAxis[1]; - dst[10] = zAxis[2]; - dst[11] = 0; - dst[12] = eye[0]; - dst[13] = eye[1]; - dst[14] = eye[2]; - dst[15] = 1; - - return dst; + dst = dst || new MatType(16) + + xAxis = xAxis || create$1() + yAxis = yAxis || create$1() + zAxis = zAxis || create$1() + + normalize(subtract(eye, target, zAxis), zAxis) + normalize(cross(up, zAxis, xAxis), xAxis) + normalize(cross(zAxis, xAxis, yAxis), yAxis) + + dst[0] = xAxis[0] + dst[1] = xAxis[1] + dst[2] = xAxis[2] + dst[3] = 0 + dst[4] = yAxis[0] + dst[5] = yAxis[1] + dst[6] = yAxis[2] + dst[7] = 0 + dst[8] = zAxis[0] + dst[9] = zAxis[1] + dst[10] = zAxis[2] + dst[11] = 0 + dst[12] = eye[0] + dst[13] = eye[1] + dst[14] = eye[2] + dst[15] = 1 + + return dst } /** @@ -1132,25 +1191,25 @@ function lookAt(eye, target, up, dst) { * @memberOf module:twgl/m4 */ function translation(v, dst) { - dst = dst || new MatType(16); - - dst[ 0] = 1; - dst[ 1] = 0; - dst[ 2] = 0; - dst[ 3] = 0; - dst[ 4] = 0; - dst[ 5] = 1; - dst[ 6] = 0; - dst[ 7] = 0; - dst[ 8] = 0; - dst[ 9] = 0; - dst[10] = 1; - dst[11] = 0; - dst[12] = v[0]; - dst[13] = v[1]; - dst[14] = v[2]; - dst[15] = 1; - return dst; + dst = dst || new MatType(16) + + dst[0] = 1 + dst[1] = 0 + dst[2] = 0 + dst[3] = 0 + dst[4] = 0 + dst[5] = 1 + dst[6] = 0 + dst[7] = 0 + dst[8] = 0 + dst[9] = 0 + dst[10] = 1 + dst[11] = 0 + dst[12] = v[0] + dst[13] = v[1] + dst[14] = v[2] + dst[15] = 1 + return dst } /** @@ -1163,49 +1222,49 @@ function translation(v, dst) { * @memberOf module:twgl/m4 */ function translate(m, v, dst) { - dst = dst || new MatType(16); - - const v0 = v[0]; - const v1 = v[1]; - const v2 = v[2]; - const m00 = m[0]; - const m01 = m[1]; - const m02 = m[2]; - const m03 = m[3]; - const m10 = m[1 * 4 + 0]; - const m11 = m[1 * 4 + 1]; - const m12 = m[1 * 4 + 2]; - const m13 = m[1 * 4 + 3]; - const m20 = m[2 * 4 + 0]; - const m21 = m[2 * 4 + 1]; - const m22 = m[2 * 4 + 2]; - const m23 = m[2 * 4 + 3]; - const m30 = m[3 * 4 + 0]; - const m31 = m[3 * 4 + 1]; - const m32 = m[3 * 4 + 2]; - const m33 = m[3 * 4 + 3]; - - if (m !== dst) { - dst[ 0] = m00; - dst[ 1] = m01; - dst[ 2] = m02; - dst[ 3] = m03; - dst[ 4] = m10; - dst[ 5] = m11; - dst[ 6] = m12; - dst[ 7] = m13; - dst[ 8] = m20; - dst[ 9] = m21; - dst[10] = m22; - dst[11] = m23; - } - - dst[12] = m00 * v0 + m10 * v1 + m20 * v2 + m30; - dst[13] = m01 * v0 + m11 * v1 + m21 * v2 + m31; - dst[14] = m02 * v0 + m12 * v1 + m22 * v2 + m32; - dst[15] = m03 * v0 + m13 * v1 + m23 * v2 + m33; - - return dst; + dst = dst || new MatType(16) + + const v0 = v[0] + const v1 = v[1] + const v2 = v[2] + const m00 = m[0] + const m01 = m[1] + const m02 = m[2] + const m03 = m[3] + const m10 = m[1 * 4 + 0] + const m11 = m[1 * 4 + 1] + const m12 = m[1 * 4 + 2] + const m13 = m[1 * 4 + 3] + const m20 = m[2 * 4 + 0] + const m21 = m[2 * 4 + 1] + const m22 = m[2 * 4 + 2] + const m23 = m[2 * 4 + 3] + const m30 = m[3 * 4 + 0] + const m31 = m[3 * 4 + 1] + const m32 = m[3 * 4 + 2] + const m33 = m[3 * 4 + 3] + + if (m !== dst) { + dst[0] = m00 + dst[1] = m01 + dst[2] = m02 + dst[3] = m03 + dst[4] = m10 + dst[5] = m11 + dst[6] = m12 + dst[7] = m13 + dst[8] = m20 + dst[9] = m21 + dst[10] = m22 + dst[11] = m23 + } + + dst[12] = m00 * v0 + m10 * v1 + m20 * v2 + m30 + dst[13] = m01 * v0 + m11 * v1 + m21 * v2 + m31 + dst[14] = m02 * v0 + m12 * v1 + m22 * v2 + m32 + dst[15] = m03 * v0 + m13 * v1 + m23 * v2 + m33 + + return dst } /** @@ -1216,29 +1275,29 @@ function translate(m, v, dst) { * @memberOf module:twgl/m4 */ function rotationX(angleInRadians, dst) { - dst = dst || new MatType(16); + dst = dst || new MatType(16) - const c = Math.cos(angleInRadians); - const s = Math.sin(angleInRadians); + const c = Math.cos(angleInRadians) + const s = Math.sin(angleInRadians) - dst[ 0] = 1; - dst[ 1] = 0; - dst[ 2] = 0; - dst[ 3] = 0; - dst[ 4] = 0; - dst[ 5] = c; - dst[ 6] = s; - dst[ 7] = 0; - dst[ 8] = 0; - dst[ 9] = -s; - dst[10] = c; - dst[11] = 0; - dst[12] = 0; - dst[13] = 0; - dst[14] = 0; - dst[15] = 1; + dst[0] = 1 + dst[1] = 0 + dst[2] = 0 + dst[3] = 0 + dst[4] = 0 + dst[5] = c + dst[6] = s + dst[7] = 0 + dst[8] = 0 + dst[9] = -s + dst[10] = c + dst[11] = 0 + dst[12] = 0 + dst[13] = 0 + dst[14] = 0 + dst[15] = 1 - return dst; + return dst } /** @@ -1251,40 +1310,40 @@ function rotationX(angleInRadians, dst) { * @memberOf module:twgl/m4 */ function rotateX(m, angleInRadians, dst) { - dst = dst || new MatType(16); - - const m10 = m[4]; - const m11 = m[5]; - const m12 = m[6]; - const m13 = m[7]; - const m20 = m[8]; - const m21 = m[9]; - const m22 = m[10]; - const m23 = m[11]; - const c = Math.cos(angleInRadians); - const s = Math.sin(angleInRadians); - - dst[4] = c * m10 + s * m20; - dst[5] = c * m11 + s * m21; - dst[6] = c * m12 + s * m22; - dst[7] = c * m13 + s * m23; - dst[8] = c * m20 - s * m10; - dst[9] = c * m21 - s * m11; - dst[10] = c * m22 - s * m12; - dst[11] = c * m23 - s * m13; - - if (m !== dst) { - dst[ 0] = m[ 0]; - dst[ 1] = m[ 1]; - dst[ 2] = m[ 2]; - dst[ 3] = m[ 3]; - dst[12] = m[12]; - dst[13] = m[13]; - dst[14] = m[14]; - dst[15] = m[15]; - } - - return dst; + dst = dst || new MatType(16) + + const m10 = m[4] + const m11 = m[5] + const m12 = m[6] + const m13 = m[7] + const m20 = m[8] + const m21 = m[9] + const m22 = m[10] + const m23 = m[11] + const c = Math.cos(angleInRadians) + const s = Math.sin(angleInRadians) + + dst[4] = c * m10 + s * m20 + dst[5] = c * m11 + s * m21 + dst[6] = c * m12 + s * m22 + dst[7] = c * m13 + s * m23 + dst[8] = c * m20 - s * m10 + dst[9] = c * m21 - s * m11 + dst[10] = c * m22 - s * m12 + dst[11] = c * m23 - s * m13 + + if (m !== dst) { + dst[0] = m[0] + dst[1] = m[1] + dst[2] = m[2] + dst[3] = m[3] + dst[12] = m[12] + dst[13] = m[13] + dst[14] = m[14] + dst[15] = m[15] + } + + return dst } /** @@ -1295,29 +1354,29 @@ function rotateX(m, angleInRadians, dst) { * @memberOf module:twgl/m4 */ function rotationY(angleInRadians, dst) { - dst = dst || new MatType(16); + dst = dst || new MatType(16) - const c = Math.cos(angleInRadians); - const s = Math.sin(angleInRadians); + const c = Math.cos(angleInRadians) + const s = Math.sin(angleInRadians) - dst[ 0] = c; - dst[ 1] = 0; - dst[ 2] = -s; - dst[ 3] = 0; - dst[ 4] = 0; - dst[ 5] = 1; - dst[ 6] = 0; - dst[ 7] = 0; - dst[ 8] = s; - dst[ 9] = 0; - dst[10] = c; - dst[11] = 0; - dst[12] = 0; - dst[13] = 0; - dst[14] = 0; - dst[15] = 1; + dst[0] = c + dst[1] = 0 + dst[2] = -s + dst[3] = 0 + dst[4] = 0 + dst[5] = 1 + dst[6] = 0 + dst[7] = 0 + dst[8] = s + dst[9] = 0 + dst[10] = c + dst[11] = 0 + dst[12] = 0 + dst[13] = 0 + dst[14] = 0 + dst[15] = 1 - return dst; + return dst } /** @@ -1330,40 +1389,40 @@ function rotationY(angleInRadians, dst) { * @memberOf module:twgl/m4 */ function rotateY(m, angleInRadians, dst) { - dst = dst || new MatType(16); - - const m00 = m[0 * 4 + 0]; - const m01 = m[0 * 4 + 1]; - const m02 = m[0 * 4 + 2]; - const m03 = m[0 * 4 + 3]; - const m20 = m[2 * 4 + 0]; - const m21 = m[2 * 4 + 1]; - const m22 = m[2 * 4 + 2]; - const m23 = m[2 * 4 + 3]; - const c = Math.cos(angleInRadians); - const s = Math.sin(angleInRadians); - - dst[ 0] = c * m00 - s * m20; - dst[ 1] = c * m01 - s * m21; - dst[ 2] = c * m02 - s * m22; - dst[ 3] = c * m03 - s * m23; - dst[ 8] = c * m20 + s * m00; - dst[ 9] = c * m21 + s * m01; - dst[10] = c * m22 + s * m02; - dst[11] = c * m23 + s * m03; - - if (m !== dst) { - dst[ 4] = m[ 4]; - dst[ 5] = m[ 5]; - dst[ 6] = m[ 6]; - dst[ 7] = m[ 7]; - dst[12] = m[12]; - dst[13] = m[13]; - dst[14] = m[14]; - dst[15] = m[15]; - } - - return dst; + dst = dst || new MatType(16) + + const m00 = m[0 * 4 + 0] + const m01 = m[0 * 4 + 1] + const m02 = m[0 * 4 + 2] + const m03 = m[0 * 4 + 3] + const m20 = m[2 * 4 + 0] + const m21 = m[2 * 4 + 1] + const m22 = m[2 * 4 + 2] + const m23 = m[2 * 4 + 3] + const c = Math.cos(angleInRadians) + const s = Math.sin(angleInRadians) + + dst[0] = c * m00 - s * m20 + dst[1] = c * m01 - s * m21 + dst[2] = c * m02 - s * m22 + dst[3] = c * m03 - s * m23 + dst[8] = c * m20 + s * m00 + dst[9] = c * m21 + s * m01 + dst[10] = c * m22 + s * m02 + dst[11] = c * m23 + s * m03 + + if (m !== dst) { + dst[4] = m[4] + dst[5] = m[5] + dst[6] = m[6] + dst[7] = m[7] + dst[12] = m[12] + dst[13] = m[13] + dst[14] = m[14] + dst[15] = m[15] + } + + return dst } /** @@ -1374,29 +1433,29 @@ function rotateY(m, angleInRadians, dst) { * @memberOf module:twgl/m4 */ function rotationZ(angleInRadians, dst) { - dst = dst || new MatType(16); + dst = dst || new MatType(16) - const c = Math.cos(angleInRadians); - const s = Math.sin(angleInRadians); + const c = Math.cos(angleInRadians) + const s = Math.sin(angleInRadians) - dst[ 0] = c; - dst[ 1] = s; - dst[ 2] = 0; - dst[ 3] = 0; - dst[ 4] = -s; - dst[ 5] = c; - dst[ 6] = 0; - dst[ 7] = 0; - dst[ 8] = 0; - dst[ 9] = 0; - dst[10] = 1; - dst[11] = 0; - dst[12] = 0; - dst[13] = 0; - dst[14] = 0; - dst[15] = 1; + dst[0] = c + dst[1] = s + dst[2] = 0 + dst[3] = 0 + dst[4] = -s + dst[5] = c + dst[6] = 0 + dst[7] = 0 + dst[8] = 0 + dst[9] = 0 + dst[10] = 1 + dst[11] = 0 + dst[12] = 0 + dst[13] = 0 + dst[14] = 0 + dst[15] = 1 - return dst; + return dst } /** @@ -1409,40 +1468,40 @@ function rotationZ(angleInRadians, dst) { * @memberOf module:twgl/m4 */ function rotateZ(m, angleInRadians, dst) { - dst = dst || new MatType(16); - - const m00 = m[0 * 4 + 0]; - const m01 = m[0 * 4 + 1]; - const m02 = m[0 * 4 + 2]; - const m03 = m[0 * 4 + 3]; - const m10 = m[1 * 4 + 0]; - const m11 = m[1 * 4 + 1]; - const m12 = m[1 * 4 + 2]; - const m13 = m[1 * 4 + 3]; - const c = Math.cos(angleInRadians); - const s = Math.sin(angleInRadians); - - dst[ 0] = c * m00 + s * m10; - dst[ 1] = c * m01 + s * m11; - dst[ 2] = c * m02 + s * m12; - dst[ 3] = c * m03 + s * m13; - dst[ 4] = c * m10 - s * m00; - dst[ 5] = c * m11 - s * m01; - dst[ 6] = c * m12 - s * m02; - dst[ 7] = c * m13 - s * m03; - - if (m !== dst) { - dst[ 8] = m[ 8]; - dst[ 9] = m[ 9]; - dst[10] = m[10]; - dst[11] = m[11]; - dst[12] = m[12]; - dst[13] = m[13]; - dst[14] = m[14]; - dst[15] = m[15]; - } - - return dst; + dst = dst || new MatType(16) + + const m00 = m[0 * 4 + 0] + const m01 = m[0 * 4 + 1] + const m02 = m[0 * 4 + 2] + const m03 = m[0 * 4 + 3] + const m10 = m[1 * 4 + 0] + const m11 = m[1 * 4 + 1] + const m12 = m[1 * 4 + 2] + const m13 = m[1 * 4 + 3] + const c = Math.cos(angleInRadians) + const s = Math.sin(angleInRadians) + + dst[0] = c * m00 + s * m10 + dst[1] = c * m01 + s * m11 + dst[2] = c * m02 + s * m12 + dst[3] = c * m03 + s * m13 + dst[4] = c * m10 - s * m00 + dst[5] = c * m11 - s * m01 + dst[6] = c * m12 - s * m02 + dst[7] = c * m13 - s * m03 + + if (m !== dst) { + dst[8] = m[8] + dst[9] = m[9] + dst[10] = m[10] + dst[11] = m[11] + dst[12] = m[12] + dst[13] = m[13] + dst[14] = m[14] + dst[15] = m[15] + } + + return dst } /** @@ -1457,40 +1516,40 @@ function rotateZ(m, angleInRadians, dst) { * @memberOf module:twgl/m4 */ function axisRotation(axis, angleInRadians, dst) { - dst = dst || new MatType(16); - - let x = axis[0]; - let y = axis[1]; - let z = axis[2]; - const n = Math.sqrt(x * x + y * y + z * z); - x /= n; - y /= n; - z /= n; - const xx = x * x; - const yy = y * y; - const zz = z * z; - const c = Math.cos(angleInRadians); - const s = Math.sin(angleInRadians); - const oneMinusCosine = 1 - c; - - dst[ 0] = xx + (1 - xx) * c; - dst[ 1] = x * y * oneMinusCosine + z * s; - dst[ 2] = x * z * oneMinusCosine - y * s; - dst[ 3] = 0; - dst[ 4] = x * y * oneMinusCosine - z * s; - dst[ 5] = yy + (1 - yy) * c; - dst[ 6] = y * z * oneMinusCosine + x * s; - dst[ 7] = 0; - dst[ 8] = x * z * oneMinusCosine + y * s; - dst[ 9] = y * z * oneMinusCosine - x * s; - dst[10] = zz + (1 - zz) * c; - dst[11] = 0; - dst[12] = 0; - dst[13] = 0; - dst[14] = 0; - dst[15] = 1; - - return dst; + dst = dst || new MatType(16) + + let x = axis[0] + let y = axis[1] + let z = axis[2] + const n = Math.sqrt(x * x + y * y + z * z) + x /= n + y /= n + z /= n + const xx = x * x + const yy = y * y + const zz = z * z + const c = Math.cos(angleInRadians) + const s = Math.sin(angleInRadians) + const oneMinusCosine = 1 - c + + dst[0] = xx + (1 - xx) * c + dst[1] = x * y * oneMinusCosine + z * s + dst[2] = x * z * oneMinusCosine - y * s + dst[3] = 0 + dst[4] = x * y * oneMinusCosine - z * s + dst[5] = yy + (1 - yy) * c + dst[6] = y * z * oneMinusCosine + x * s + dst[7] = 0 + dst[8] = x * z * oneMinusCosine + y * s + dst[9] = y * z * oneMinusCosine - x * s + dst[10] = zz + (1 - zz) * c + dst[11] = 0 + dst[12] = 0 + dst[13] = 0 + dst[14] = 0 + dst[15] = 1 + + return dst } /** @@ -1505,66 +1564,66 @@ function axisRotation(axis, angleInRadians, dst) { * @memberOf module:twgl/m4 */ function axisRotate(m, axis, angleInRadians, dst) { - dst = dst || new MatType(16); - - let x = axis[0]; - let y = axis[1]; - let z = axis[2]; - const n = Math.sqrt(x * x + y * y + z * z); - x /= n; - y /= n; - z /= n; - const xx = x * x; - const yy = y * y; - const zz = z * z; - const c = Math.cos(angleInRadians); - const s = Math.sin(angleInRadians); - const oneMinusCosine = 1 - c; - - const r00 = xx + (1 - xx) * c; - const r01 = x * y * oneMinusCosine + z * s; - const r02 = x * z * oneMinusCosine - y * s; - const r10 = x * y * oneMinusCosine - z * s; - const r11 = yy + (1 - yy) * c; - const r12 = y * z * oneMinusCosine + x * s; - const r20 = x * z * oneMinusCosine + y * s; - const r21 = y * z * oneMinusCosine - x * s; - const r22 = zz + (1 - zz) * c; - - const m00 = m[0]; - const m01 = m[1]; - const m02 = m[2]; - const m03 = m[3]; - const m10 = m[4]; - const m11 = m[5]; - const m12 = m[6]; - const m13 = m[7]; - const m20 = m[8]; - const m21 = m[9]; - const m22 = m[10]; - const m23 = m[11]; - - dst[ 0] = r00 * m00 + r01 * m10 + r02 * m20; - dst[ 1] = r00 * m01 + r01 * m11 + r02 * m21; - dst[ 2] = r00 * m02 + r01 * m12 + r02 * m22; - dst[ 3] = r00 * m03 + r01 * m13 + r02 * m23; - dst[ 4] = r10 * m00 + r11 * m10 + r12 * m20; - dst[ 5] = r10 * m01 + r11 * m11 + r12 * m21; - dst[ 6] = r10 * m02 + r11 * m12 + r12 * m22; - dst[ 7] = r10 * m03 + r11 * m13 + r12 * m23; - dst[ 8] = r20 * m00 + r21 * m10 + r22 * m20; - dst[ 9] = r20 * m01 + r21 * m11 + r22 * m21; - dst[10] = r20 * m02 + r21 * m12 + r22 * m22; - dst[11] = r20 * m03 + r21 * m13 + r22 * m23; - - if (m !== dst) { - dst[12] = m[12]; - dst[13] = m[13]; - dst[14] = m[14]; - dst[15] = m[15]; - } - - return dst; + dst = dst || new MatType(16) + + let x = axis[0] + let y = axis[1] + let z = axis[2] + const n = Math.sqrt(x * x + y * y + z * z) + x /= n + y /= n + z /= n + const xx = x * x + const yy = y * y + const zz = z * z + const c = Math.cos(angleInRadians) + const s = Math.sin(angleInRadians) + const oneMinusCosine = 1 - c + + const r00 = xx + (1 - xx) * c + const r01 = x * y * oneMinusCosine + z * s + const r02 = x * z * oneMinusCosine - y * s + const r10 = x * y * oneMinusCosine - z * s + const r11 = yy + (1 - yy) * c + const r12 = y * z * oneMinusCosine + x * s + const r20 = x * z * oneMinusCosine + y * s + const r21 = y * z * oneMinusCosine - x * s + const r22 = zz + (1 - zz) * c + + const m00 = m[0] + const m01 = m[1] + const m02 = m[2] + const m03 = m[3] + const m10 = m[4] + const m11 = m[5] + const m12 = m[6] + const m13 = m[7] + const m20 = m[8] + const m21 = m[9] + const m22 = m[10] + const m23 = m[11] + + dst[0] = r00 * m00 + r01 * m10 + r02 * m20 + dst[1] = r00 * m01 + r01 * m11 + r02 * m21 + dst[2] = r00 * m02 + r01 * m12 + r02 * m22 + dst[3] = r00 * m03 + r01 * m13 + r02 * m23 + dst[4] = r10 * m00 + r11 * m10 + r12 * m20 + dst[5] = r10 * m01 + r11 * m11 + r12 * m21 + dst[6] = r10 * m02 + r11 * m12 + r12 * m22 + dst[7] = r10 * m03 + r11 * m13 + r12 * m23 + dst[8] = r20 * m00 + r21 * m10 + r22 * m20 + dst[9] = r20 * m01 + r21 * m11 + r22 * m21 + dst[10] = r20 * m02 + r21 * m12 + r22 * m22 + dst[11] = r20 * m03 + r21 * m13 + r22 * m23 + + if (m !== dst) { + dst[12] = m[12] + dst[13] = m[13] + dst[14] = m[14] + dst[15] = m[15] + } + + return dst } /** @@ -1578,26 +1637,26 @@ function axisRotate(m, axis, angleInRadians, dst) { * @memberOf module:twgl/m4 */ function scaling(v, dst) { - dst = dst || new MatType(16); + dst = dst || new MatType(16) - dst[ 0] = v[0]; - dst[ 1] = 0; - dst[ 2] = 0; - dst[ 3] = 0; - dst[ 4] = 0; - dst[ 5] = v[1]; - dst[ 6] = 0; - dst[ 7] = 0; - dst[ 8] = 0; - dst[ 9] = 0; - dst[10] = v[2]; - dst[11] = 0; - dst[12] = 0; - dst[13] = 0; - dst[14] = 0; - dst[15] = 1; + dst[0] = v[0] + dst[1] = 0 + dst[2] = 0 + dst[3] = 0 + dst[4] = 0 + dst[5] = v[1] + dst[6] = 0 + dst[7] = 0 + dst[8] = 0 + dst[9] = 0 + dst[10] = v[2] + dst[11] = 0 + dst[12] = 0 + dst[13] = 0 + dst[14] = 0 + dst[15] = 1 - return dst; + return dst } /** @@ -1612,33 +1671,33 @@ function scaling(v, dst) { * @memberOf module:twgl/m4 */ function scale(m, v, dst) { - dst = dst || new MatType(16); - - const v0 = v[0]; - const v1 = v[1]; - const v2 = v[2]; - - dst[ 0] = v0 * m[0 * 4 + 0]; - dst[ 1] = v0 * m[0 * 4 + 1]; - dst[ 2] = v0 * m[0 * 4 + 2]; - dst[ 3] = v0 * m[0 * 4 + 3]; - dst[ 4] = v1 * m[1 * 4 + 0]; - dst[ 5] = v1 * m[1 * 4 + 1]; - dst[ 6] = v1 * m[1 * 4 + 2]; - dst[ 7] = v1 * m[1 * 4 + 3]; - dst[ 8] = v2 * m[2 * 4 + 0]; - dst[ 9] = v2 * m[2 * 4 + 1]; - dst[10] = v2 * m[2 * 4 + 2]; - dst[11] = v2 * m[2 * 4 + 3]; - - if (m !== dst) { - dst[12] = m[12]; - dst[13] = m[13]; - dst[14] = m[14]; - dst[15] = m[15]; - } + dst = dst || new MatType(16) + + const v0 = v[0] + const v1 = v[1] + const v2 = v[2] + + dst[0] = v0 * m[0 * 4 + 0] + dst[1] = v0 * m[0 * 4 + 1] + dst[2] = v0 * m[0 * 4 + 2] + dst[3] = v0 * m[0 * 4 + 3] + dst[4] = v1 * m[1 * 4 + 0] + dst[5] = v1 * m[1 * 4 + 1] + dst[6] = v1 * m[1 * 4 + 2] + dst[7] = v1 * m[1 * 4 + 3] + dst[8] = v2 * m[2 * 4 + 0] + dst[9] = v2 * m[2 * 4 + 1] + dst[10] = v2 * m[2 * 4 + 2] + dst[11] = v2 * m[2 * 4 + 3] + + if (m !== dst) { + dst[12] = m[12] + dst[13] = m[13] + dst[14] = m[14] + dst[15] = m[15] + } - return dst; + return dst } /** @@ -1652,17 +1711,33 @@ function scale(m, v, dst) { * @memberOf module:twgl/m4 */ function transformPoint(m, v, dst) { - dst = dst || create$1(); - const v0 = v[0]; - const v1 = v[1]; - const v2 = v[2]; - const d = v0 * m[0 * 4 + 3] + v1 * m[1 * 4 + 3] + v2 * m[2 * 4 + 3] + m[3 * 4 + 3]; - - dst[0] = (v0 * m[0 * 4 + 0] + v1 * m[1 * 4 + 0] + v2 * m[2 * 4 + 0] + m[3 * 4 + 0]) / d; - dst[1] = (v0 * m[0 * 4 + 1] + v1 * m[1 * 4 + 1] + v2 * m[2 * 4 + 1] + m[3 * 4 + 1]) / d; - dst[2] = (v0 * m[0 * 4 + 2] + v1 * m[1 * 4 + 2] + v2 * m[2 * 4 + 2] + m[3 * 4 + 2]) / d; - - return dst; + dst = dst || create$1() + const v0 = v[0] + const v1 = v[1] + const v2 = v[2] + const d = + v0 * m[0 * 4 + 3] + v1 * m[1 * 4 + 3] + v2 * m[2 * 4 + 3] + m[3 * 4 + 3] + + dst[0] = + (v0 * m[0 * 4 + 0] + + v1 * m[1 * 4 + 0] + + v2 * m[2 * 4 + 0] + + m[3 * 4 + 0]) / + d + dst[1] = + (v0 * m[0 * 4 + 1] + + v1 * m[1 * 4 + 1] + + v2 * m[2 * 4 + 1] + + m[3 * 4 + 1]) / + d + dst[2] = + (v0 * m[0 * 4 + 2] + + v1 * m[1 * 4 + 2] + + v2 * m[2 * 4 + 2] + + m[3 * 4 + 2]) / + d + + return dst } /** @@ -1679,17 +1754,17 @@ function transformPoint(m, v, dst) { * @memberOf module:twgl/m4 */ function transformDirection(m, v, dst) { - dst = dst || create$1(); + dst = dst || create$1() - const v0 = v[0]; - const v1 = v[1]; - const v2 = v[2]; + const v0 = v[0] + const v1 = v[1] + const v2 = v[2] - dst[0] = v0 * m[0 * 4 + 0] + v1 * m[1 * 4 + 0] + v2 * m[2 * 4 + 0]; - dst[1] = v0 * m[0 * 4 + 1] + v1 * m[1 * 4 + 1] + v2 * m[2 * 4 + 1]; - dst[2] = v0 * m[0 * 4 + 2] + v1 * m[1 * 4 + 2] + v2 * m[2 * 4 + 2]; + dst[0] = v0 * m[0 * 4 + 0] + v1 * m[1 * 4 + 0] + v2 * m[2 * 4 + 0] + dst[1] = v0 * m[0 * 4 + 1] + v1 * m[1 * 4 + 1] + v2 * m[2 * 4 + 1] + dst[2] = v0 * m[0 * 4 + 2] + v1 * m[1 * 4 + 2] + v2 * m[2 * 4 + 2] - return dst; + return dst } /** @@ -1708,53 +1783,53 @@ function transformDirection(m, v, dst) { * @memberOf module:twgl/m4 */ function transformNormal$1(m, v, dst) { - dst = dst || create$1(); - const mi = inverse(m); - const v0 = v[0]; - const v1 = v[1]; - const v2 = v[2]; - - dst[0] = v0 * mi[0 * 4 + 0] + v1 * mi[0 * 4 + 1] + v2 * mi[0 * 4 + 2]; - dst[1] = v0 * mi[1 * 4 + 0] + v1 * mi[1 * 4 + 1] + v2 * mi[1 * 4 + 2]; - dst[2] = v0 * mi[2 * 4 + 0] + v1 * mi[2 * 4 + 1] + v2 * mi[2 * 4 + 2]; - - return dst; -} - -var m4 = /*#__PURE__*/Object.freeze({ - __proto__: null, - axisRotate: axisRotate, - axisRotation: axisRotation, - copy: copy, - create: create, - frustum: frustum, - getAxis: getAxis, - getTranslation: getTranslation, - identity: identity, - inverse: inverse, - lookAt: lookAt, - multiply: multiply, - negate: negate, - ortho: ortho, - perspective: perspective, - rotateX: rotateX, - rotateY: rotateY, - rotateZ: rotateZ, - rotationX: rotationX, - rotationY: rotationY, - rotationZ: rotationZ, - scale: scale, - scaling: scaling, - setAxis: setAxis, - setDefaultType: setDefaultType, - setTranslation: setTranslation, - transformDirection: transformDirection, - transformNormal: transformNormal$1, - transformPoint: transformPoint, - translate: translate, - translation: translation, - transpose: transpose -}); + dst = dst || create$1() + const mi = inverse(m) + const v0 = v[0] + const v1 = v[1] + const v2 = v[2] + + dst[0] = v0 * mi[0 * 4 + 0] + v1 * mi[0 * 4 + 1] + v2 * mi[0 * 4 + 2] + dst[1] = v0 * mi[1 * 4 + 0] + v1 * mi[1 * 4 + 1] + v2 * mi[1 * 4 + 2] + dst[2] = v0 * mi[2 * 4 + 0] + v1 * mi[2 * 4 + 1] + v2 * mi[2 * 4 + 2] + + return dst +} + +var m4 = /*#__PURE__*/ Object.freeze({ + __proto__: null, + axisRotate: axisRotate, + axisRotation: axisRotation, + copy: copy, + create: create, + frustum: frustum, + getAxis: getAxis, + getTranslation: getTranslation, + identity: identity, + inverse: inverse, + lookAt: lookAt, + multiply: multiply, + negate: negate, + ortho: ortho, + perspective: perspective, + rotateX: rotateX, + rotateY: rotateY, + rotateZ: rotateZ, + rotationX: rotationX, + rotationY: rotationY, + rotationZ: rotationZ, + scale: scale, + scaling: scaling, + setAxis: setAxis, + setDefaultType: setDefaultType, + setTranslation: setTranslation, + transformDirection: transformDirection, + transformNormal: transformNormal$1, + transformPoint: transformPoint, + translate: translate, + translation: translation, + transpose: transpose, +}) /* * Copyright 2019 Gregg Tavares @@ -1779,42 +1854,42 @@ var m4 = /*#__PURE__*/Object.freeze({ */ /* DataType */ -const BYTE$2 = 0x1400; -const UNSIGNED_BYTE$3 = 0x1401; -const SHORT$2 = 0x1402; -const UNSIGNED_SHORT$3 = 0x1403; -const INT$3 = 0x1404; -const UNSIGNED_INT$3 = 0x1405; -const FLOAT$3 = 0x1406; -const UNSIGNED_SHORT_4_4_4_4$1 = 0x8033; -const UNSIGNED_SHORT_5_5_5_1$1 = 0x8034; -const UNSIGNED_SHORT_5_6_5$1 = 0x8363; -const HALF_FLOAT$1 = 0x140B; -const UNSIGNED_INT_2_10_10_10_REV$1 = 0x8368; -const UNSIGNED_INT_10F_11F_11F_REV$1 = 0x8C3B; -const UNSIGNED_INT_5_9_9_9_REV$1 = 0x8C3E; -const FLOAT_32_UNSIGNED_INT_24_8_REV$1 = 0x8DAD; -const UNSIGNED_INT_24_8$1 = 0x84FA; - -const glTypeToTypedArray = {}; +const BYTE$2 = 0x1400 +const UNSIGNED_BYTE$3 = 0x1401 +const SHORT$2 = 0x1402 +const UNSIGNED_SHORT$3 = 0x1403 +const INT$3 = 0x1404 +const UNSIGNED_INT$3 = 0x1405 +const FLOAT$3 = 0x1406 +const UNSIGNED_SHORT_4_4_4_4$1 = 0x8033 +const UNSIGNED_SHORT_5_5_5_1$1 = 0x8034 +const UNSIGNED_SHORT_5_6_5$1 = 0x8363 +const HALF_FLOAT$1 = 0x140b +const UNSIGNED_INT_2_10_10_10_REV$1 = 0x8368 +const UNSIGNED_INT_10F_11F_11F_REV$1 = 0x8c3b +const UNSIGNED_INT_5_9_9_9_REV$1 = 0x8c3e +const FLOAT_32_UNSIGNED_INT_24_8_REV$1 = 0x8dad +const UNSIGNED_INT_24_8$1 = 0x84fa + +const glTypeToTypedArray = {} { - const tt = glTypeToTypedArray; - tt[BYTE$2] = Int8Array; - tt[UNSIGNED_BYTE$3] = Uint8Array; - tt[SHORT$2] = Int16Array; - tt[UNSIGNED_SHORT$3] = Uint16Array; - tt[INT$3] = Int32Array; - tt[UNSIGNED_INT$3] = Uint32Array; - tt[FLOAT$3] = Float32Array; - tt[UNSIGNED_SHORT_4_4_4_4$1] = Uint16Array; - tt[UNSIGNED_SHORT_5_5_5_1$1] = Uint16Array; - tt[UNSIGNED_SHORT_5_6_5$1] = Uint16Array; - tt[HALF_FLOAT$1] = Uint16Array; - tt[UNSIGNED_INT_2_10_10_10_REV$1] = Uint32Array; - tt[UNSIGNED_INT_10F_11F_11F_REV$1] = Uint32Array; - tt[UNSIGNED_INT_5_9_9_9_REV$1] = Uint32Array; - tt[FLOAT_32_UNSIGNED_INT_24_8_REV$1] = Uint32Array; - tt[UNSIGNED_INT_24_8$1] = Uint32Array; + const tt = glTypeToTypedArray + tt[BYTE$2] = Int8Array + tt[UNSIGNED_BYTE$3] = Uint8Array + tt[SHORT$2] = Int16Array + tt[UNSIGNED_SHORT$3] = Uint16Array + tt[INT$3] = Int32Array + tt[UNSIGNED_INT$3] = Uint32Array + tt[FLOAT$3] = Float32Array + tt[UNSIGNED_SHORT_4_4_4_4$1] = Uint16Array + tt[UNSIGNED_SHORT_5_5_5_1$1] = Uint16Array + tt[UNSIGNED_SHORT_5_6_5$1] = Uint16Array + tt[HALF_FLOAT$1] = Uint16Array + tt[UNSIGNED_INT_2_10_10_10_REV$1] = Uint32Array + tt[UNSIGNED_INT_10F_11F_11F_REV$1] = Uint32Array + tt[UNSIGNED_INT_5_9_9_9_REV$1] = Uint32Array + tt[FLOAT_32_UNSIGNED_INT_24_8_REV$1] = Uint32Array + tt[UNSIGNED_INT_24_8$1] = Uint32Array } /** @@ -1825,15 +1900,31 @@ const glTypeToTypedArray = {}; * @memberOf module:twgl/typedArray */ function getGLTypeForTypedArray(typedArray) { - if (typedArray instanceof Int8Array) { return BYTE$2; } // eslint-disable-line - if (typedArray instanceof Uint8Array) { return UNSIGNED_BYTE$3; } // eslint-disable-line - if (typedArray instanceof Uint8ClampedArray) { return UNSIGNED_BYTE$3; } // eslint-disable-line - if (typedArray instanceof Int16Array) { return SHORT$2; } // eslint-disable-line - if (typedArray instanceof Uint16Array) { return UNSIGNED_SHORT$3; } // eslint-disable-line - if (typedArray instanceof Int32Array) { return INT$3; } // eslint-disable-line - if (typedArray instanceof Uint32Array) { return UNSIGNED_INT$3; } // eslint-disable-line - if (typedArray instanceof Float32Array) { return FLOAT$3; } // eslint-disable-line - throw new Error('unsupported typed array type'); + if (typedArray instanceof Int8Array) { + return BYTE$2 + } // eslint-disable-line + if (typedArray instanceof Uint8Array) { + return UNSIGNED_BYTE$3 + } // eslint-disable-line + if (typedArray instanceof Uint8ClampedArray) { + return UNSIGNED_BYTE$3 + } // eslint-disable-line + if (typedArray instanceof Int16Array) { + return SHORT$2 + } // eslint-disable-line + if (typedArray instanceof Uint16Array) { + return UNSIGNED_SHORT$3 + } // eslint-disable-line + if (typedArray instanceof Int32Array) { + return INT$3 + } // eslint-disable-line + if (typedArray instanceof Uint32Array) { + return UNSIGNED_INT$3 + } // eslint-disable-line + if (typedArray instanceof Float32Array) { + return FLOAT$3 + } // eslint-disable-line + throw new Error('unsupported typed array type') } /** @@ -1844,15 +1935,31 @@ function getGLTypeForTypedArray(typedArray) { * @memberOf module:twgl/typedArray */ function getGLTypeForTypedArrayType(typedArrayType) { - if (typedArrayType === Int8Array) { return BYTE$2; } // eslint-disable-line - if (typedArrayType === Uint8Array) { return UNSIGNED_BYTE$3; } // eslint-disable-line - if (typedArrayType === Uint8ClampedArray) { return UNSIGNED_BYTE$3; } // eslint-disable-line - if (typedArrayType === Int16Array) { return SHORT$2; } // eslint-disable-line - if (typedArrayType === Uint16Array) { return UNSIGNED_SHORT$3; } // eslint-disable-line - if (typedArrayType === Int32Array) { return INT$3; } // eslint-disable-line - if (typedArrayType === Uint32Array) { return UNSIGNED_INT$3; } // eslint-disable-line - if (typedArrayType === Float32Array) { return FLOAT$3; } // eslint-disable-line - throw new Error('unsupported typed array type'); + if (typedArrayType === Int8Array) { + return BYTE$2 + } // eslint-disable-line + if (typedArrayType === Uint8Array) { + return UNSIGNED_BYTE$3 + } // eslint-disable-line + if (typedArrayType === Uint8ClampedArray) { + return UNSIGNED_BYTE$3 + } // eslint-disable-line + if (typedArrayType === Int16Array) { + return SHORT$2 + } // eslint-disable-line + if (typedArrayType === Uint16Array) { + return UNSIGNED_SHORT$3 + } // eslint-disable-line + if (typedArrayType === Int32Array) { + return INT$3 + } // eslint-disable-line + if (typedArrayType === Uint32Array) { + return UNSIGNED_INT$3 + } // eslint-disable-line + if (typedArrayType === Float32Array) { + return FLOAT$3 + } // eslint-disable-line + throw new Error('unsupported typed array type') } /** @@ -1862,28 +1969,34 @@ function getGLTypeForTypedArrayType(typedArrayType) { * @memberOf module:twgl/typedArray */ function getTypedArrayTypeForGLType(type) { - const CTOR = glTypeToTypedArray[type]; - if (!CTOR) { - throw new Error('unknown gl type'); - } - return CTOR; -} - -const isArrayBuffer$1 = typeof SharedArrayBuffer !== 'undefined' - ? function isArrayBufferOrSharedArrayBuffer(a) { - return a && a.buffer && (a.buffer instanceof ArrayBuffer || a.buffer instanceof SharedArrayBuffer); - } - : function isArrayBuffer(a) { - return a && a.buffer && a.buffer instanceof ArrayBuffer; - }; - -var typedarrays = /*#__PURE__*/Object.freeze({ - __proto__: null, - getGLTypeForTypedArray: getGLTypeForTypedArray, - getGLTypeForTypedArrayType: getGLTypeForTypedArrayType, - getTypedArrayTypeForGLType: getTypedArrayTypeForGLType, - isArrayBuffer: isArrayBuffer$1 -}); + const CTOR = glTypeToTypedArray[type] + if (!CTOR) { + throw new Error('unknown gl type') + } + return CTOR +} + +const isArrayBuffer$1 = + typeof SharedArrayBuffer !== 'undefined' + ? function isArrayBufferOrSharedArrayBuffer(a) { + return ( + a && + a.buffer && + (a.buffer instanceof ArrayBuffer || + a.buffer instanceof SharedArrayBuffer) + ) + } + : function isArrayBuffer(a) { + return a && a.buffer && a.buffer instanceof ArrayBuffer + } + +var typedarrays = /*#__PURE__*/ Object.freeze({ + __proto__: null, + getGLTypeForTypedArray: getGLTypeForTypedArray, + getGLTypeForTypedArrayType: getGLTypeForTypedArrayType, + getTypedArrayTypeForGLType: getTypedArrayTypeForGLType, + isArrayBuffer: isArrayBuffer$1, +}) /* * Copyright 2019 Gregg Tavares @@ -1918,12 +2031,12 @@ var typedarrays = /*#__PURE__*/Object.freeze({ * @private */ function copyNamedProperties(names, src, dst) { - names.forEach(function(name) { - const value = src[name]; - if (value !== undefined) { - dst[name] = value; - } - }); + names.forEach(function (name) { + const value = src[name] + if (value !== undefined) { + dst[name] = value + } + }) } /** @@ -1934,55 +2047,59 @@ function copyNamedProperties(names, src, dst) { * @private */ function copyExistingProperties(src, dst) { - Object.keys(dst).forEach(function(key) { - if (dst.hasOwnProperty(key) && src.hasOwnProperty(key)) { /* eslint no-prototype-builtins: 0 */ - dst[key] = src[key]; - } - }); + Object.keys(dst).forEach(function (key) { + if (dst.hasOwnProperty(key) && src.hasOwnProperty(key)) { + /* eslint no-prototype-builtins: 0 */ + dst[key] = src[key] + } + }) } function error$1(...args) { - console.error(...args); + console.error(...args) } function warn$1(...args) { - console.warn(...args); + console.warn(...args) } -const isTypeWeakMaps = new Map(); +const isTypeWeakMaps = new Map() function isType(object, type) { - if (!object || typeof object !== 'object') { - return false; - } - let weakMap = isTypeWeakMaps.get(type); - if (!weakMap) { - weakMap = new WeakMap(); - isTypeWeakMaps.set(type, weakMap); - } - let isOfType = weakMap.get(object); - if (isOfType === undefined) { - const s = Object.prototype.toString.call(object); - isOfType = s.substring(8, s.length - 1) === type; - weakMap.set(object, isOfType); - } - return isOfType; + if (!object || typeof object !== 'object') { + return false + } + let weakMap = isTypeWeakMaps.get(type) + if (!weakMap) { + weakMap = new WeakMap() + isTypeWeakMaps.set(type, weakMap) + } + let isOfType = weakMap.get(object) + if (isOfType === undefined) { + const s = Object.prototype.toString.call(object) + isOfType = s.substring(8, s.length - 1) === type + weakMap.set(object, isOfType) + } + return isOfType } function isBuffer(gl, t) { - return typeof WebGLBuffer !== 'undefined' && isType(t, 'WebGLBuffer'); + return typeof WebGLBuffer !== 'undefined' && isType(t, 'WebGLBuffer') } function isRenderbuffer(gl, t) { - return typeof WebGLRenderbuffer !== 'undefined' && isType(t, 'WebGLRenderbuffer'); + return ( + typeof WebGLRenderbuffer !== 'undefined' && + isType(t, 'WebGLRenderbuffer') + ) } function isTexture(gl, t) { - return typeof WebGLTexture !== 'undefined' && isType(t, 'WebGLTexture'); + return typeof WebGLTexture !== 'undefined' && isType(t, 'WebGLTexture') } function isSampler(gl, t) { - return typeof WebGLSampler !== 'undefined' && isType(t, 'WebGLSampler'); + return typeof WebGLSampler !== 'undefined' && isType(t, 'WebGLSampler') } /* @@ -2007,21 +2124,21 @@ function isSampler(gl, t) { * DEALINGS IN THE SOFTWARE. */ -const STATIC_DRAW = 0x88e4; -const ARRAY_BUFFER$1 = 0x8892; -const ELEMENT_ARRAY_BUFFER$2 = 0x8893; -const BUFFER_SIZE = 0x8764; +const STATIC_DRAW = 0x88e4 +const ARRAY_BUFFER$1 = 0x8892 +const ELEMENT_ARRAY_BUFFER$2 = 0x8893 +const BUFFER_SIZE = 0x8764 -const BYTE$1 = 0x1400; -const UNSIGNED_BYTE$2 = 0x1401; -const SHORT$1 = 0x1402; -const UNSIGNED_SHORT$2 = 0x1403; -const INT$2 = 0x1404; -const UNSIGNED_INT$2 = 0x1405; -const FLOAT$2 = 0x1406; +const BYTE$1 = 0x1400 +const UNSIGNED_BYTE$2 = 0x1401 +const SHORT$1 = 0x1402 +const UNSIGNED_SHORT$2 = 0x1403 +const INT$2 = 0x1404 +const UNSIGNED_INT$2 = 0x1405 +const FLOAT$2 = 0x1406 const defaults$2 = { - attribPrefix: "", -}; + attribPrefix: '', +} /** * Sets the default attrib prefix @@ -2044,16 +2161,16 @@ const defaults$2 = { * @memberOf module:twgl/attributes */ function setAttributePrefix(prefix) { - defaults$2.attribPrefix = prefix; + defaults$2.attribPrefix = prefix } function setDefaults$2(newDefaults) { - copyExistingProperties(newDefaults, defaults$2); + copyExistingProperties(newDefaults, defaults$2) } function setBufferFromTypedArray(gl, type, buffer, array, drawType) { - gl.bindBuffer(type, buffer); - gl.bufferData(type, array, drawType || STATIC_DRAW); + gl.bindBuffer(type, buffer) + gl.bufferData(type, array, drawType || STATIC_DRAW) } /** @@ -2068,125 +2185,147 @@ function setBufferFromTypedArray(gl, type, buffer, array, drawType) { * @memberOf module:twgl/attributes */ function createBufferFromTypedArray(gl, typedArray, type, drawType) { - if (isBuffer(gl, typedArray)) { - return typedArray; - } - type = type || ARRAY_BUFFER$1; - const buffer = gl.createBuffer(); - setBufferFromTypedArray(gl, type, buffer, typedArray, drawType); - return buffer; + if (isBuffer(gl, typedArray)) { + return typedArray + } + type = type || ARRAY_BUFFER$1 + const buffer = gl.createBuffer() + setBufferFromTypedArray(gl, type, buffer, typedArray, drawType) + return buffer } function isIndices(name) { - return name === "indices"; + return name === 'indices' } // This is really just a guess. Though I can't really imagine using // anything else? Maybe for some compression? function getNormalizationForTypedArrayType(typedArrayType) { - if (typedArrayType === Int8Array) { return true; } // eslint-disable-line - if (typedArrayType === Uint8Array) { return true; } // eslint-disable-line - return false; + if (typedArrayType === Int8Array) { + return true + } // eslint-disable-line + if (typedArrayType === Uint8Array) { + return true + } // eslint-disable-line + return false } function getArray$1(array) { - return array.length ? array : array.data; + return array.length ? array : array.data } -const texcoordRE = /coord|texture/i; -const colorRE = /color|colour/i; +const texcoordRE = /coord|texture/i +const colorRE = /color|colour/i function guessNumComponentsFromName(name, length) { - let numComponents; - if (texcoordRE.test(name)) { - numComponents = 2; - } else if (colorRE.test(name)) { - numComponents = 4; - } else { - numComponents = 3; // position, normals, indices ... - } + let numComponents + if (texcoordRE.test(name)) { + numComponents = 2 + } else if (colorRE.test(name)) { + numComponents = 4 + } else { + numComponents = 3 // position, normals, indices ... + } - if (length % numComponents > 0) { - throw new Error(`Can not guess numComponents for attribute '${name}'. Tried ${numComponents} but ${length} values is not evenly divisible by ${numComponents}. You should specify it.`); - } + if (length % numComponents > 0) { + throw new Error( + `Can not guess numComponents for attribute '${name}'. Tried ${numComponents} but ${length} values is not evenly divisible by ${numComponents}. You should specify it.` + ) + } - return numComponents; + return numComponents } function getNumComponents$1(array, arrayName, numValues) { - return array.numComponents || array.size || guessNumComponentsFromName(arrayName, numValues || getArray$1(array).length); + return ( + array.numComponents || + array.size || + guessNumComponentsFromName( + arrayName, + numValues || getArray$1(array).length + ) + ) } function makeTypedArray(array, name) { - if (isArrayBuffer$1(array)) { - return array; - } - - if (isArrayBuffer$1(array.data)) { - return array.data; - } - - if (Array.isArray(array)) { - array = { - data: array, - }; - } - - let Type = array.type ? typedArrayTypeFromGLTypeOrTypedArrayCtor(array.type) : undefined; - if (!Type) { - if (isIndices(name)) { - Type = Uint16Array; - } else { - Type = Float32Array; + if (isArrayBuffer$1(array)) { + return array + } + + if (isArrayBuffer$1(array.data)) { + return array.data + } + + if (Array.isArray(array)) { + array = { + data: array, + } } - } - return new Type(array.data); + + let Type = array.type + ? typedArrayTypeFromGLTypeOrTypedArrayCtor(array.type) + : undefined + if (!Type) { + if (isIndices(name)) { + Type = Uint16Array + } else { + Type = Float32Array + } + } + return new Type(array.data) } function glTypeFromGLTypeOrTypedArrayType(glTypeOrTypedArrayCtor) { - return typeof glTypeOrTypedArrayCtor === 'number' - ? glTypeOrTypedArrayCtor - : glTypeOrTypedArrayCtor ? getGLTypeForTypedArrayType(glTypeOrTypedArrayCtor) : FLOAT$2; + return typeof glTypeOrTypedArrayCtor === 'number' + ? glTypeOrTypedArrayCtor + : glTypeOrTypedArrayCtor + ? getGLTypeForTypedArrayType(glTypeOrTypedArrayCtor) + : FLOAT$2 } function typedArrayTypeFromGLTypeOrTypedArrayCtor(glTypeOrTypedArrayCtor) { - return typeof glTypeOrTypedArrayCtor === 'number' - ? getTypedArrayTypeForGLType(glTypeOrTypedArrayCtor) - : glTypeOrTypedArrayCtor || Float32Array; -} - -function attribBufferFromBuffer(gl, array/*, arrayName */) { - return { - buffer: array.buffer, - numValues: 2 * 3 * 4, // safely divided by 2, 3, 4 - type: glTypeFromGLTypeOrTypedArrayType(array.type), - arrayType: typedArrayTypeFromGLTypeOrTypedArrayCtor(array.type), - }; -} - -function attribBufferFromSize(gl, array/*, arrayName*/) { - const numValues = array.data || array; - const arrayType = typedArrayTypeFromGLTypeOrTypedArrayCtor(array.type); - const numBytes = numValues * arrayType.BYTES_PER_ELEMENT; - const buffer = gl.createBuffer(); - gl.bindBuffer(ARRAY_BUFFER$1, buffer); - gl.bufferData(ARRAY_BUFFER$1, numBytes, array.drawType || STATIC_DRAW); - return { - buffer, - numValues, - type: getGLTypeForTypedArrayType(arrayType), - arrayType, - }; + return typeof glTypeOrTypedArrayCtor === 'number' + ? getTypedArrayTypeForGLType(glTypeOrTypedArrayCtor) + : glTypeOrTypedArrayCtor || Float32Array +} + +function attribBufferFromBuffer(gl, array /*, arrayName */) { + return { + buffer: array.buffer, + numValues: 2 * 3 * 4, // safely divided by 2, 3, 4 + type: glTypeFromGLTypeOrTypedArrayType(array.type), + arrayType: typedArrayTypeFromGLTypeOrTypedArrayCtor(array.type), + } +} + +function attribBufferFromSize(gl, array /*, arrayName*/) { + const numValues = array.data || array + const arrayType = typedArrayTypeFromGLTypeOrTypedArrayCtor(array.type) + const numBytes = numValues * arrayType.BYTES_PER_ELEMENT + const buffer = gl.createBuffer() + gl.bindBuffer(ARRAY_BUFFER$1, buffer) + gl.bufferData(ARRAY_BUFFER$1, numBytes, array.drawType || STATIC_DRAW) + return { + buffer, + numValues, + type: getGLTypeForTypedArrayType(arrayType), + arrayType, + } } function attribBufferFromArrayLike(gl, array, arrayName) { - const typedArray = makeTypedArray(array, arrayName); - return { - arrayType: typedArray.constructor, - buffer: createBufferFromTypedArray(gl, typedArray, undefined, array.drawType), - type: getGLTypeForTypedArray(typedArray), - numValues: 0, - }; + const typedArray = makeTypedArray(array, arrayName) + return { + arrayType: typedArray.constructor, + buffer: createBufferFromTypedArray( + gl, + typedArray, + undefined, + array.drawType + ), + type: getGLTypeForTypedArray(typedArray), + numValues: 0, + } } /** @@ -2304,7 +2443,6 @@ function attribBufferFromArrayLike(gl, array, arrayName) { * @memberOf module:twgl */ - /** * Creates a set of attribute data and WebGLBuffers from set of arrays * @@ -2364,45 +2502,67 @@ function attribBufferFromArrayLike(gl, array, arrayName) { * @memberOf module:twgl/attributes */ function createAttribsFromArrays(gl, arrays) { - const attribs = {}; - Object.keys(arrays).forEach(function(arrayName) { - if (!isIndices(arrayName)) { - const array = arrays[arrayName]; - const attribName = array.attrib || array.name || array.attribName || (defaults$2.attribPrefix + arrayName); - if (array.value) { - if (!Array.isArray(array.value) && !isArrayBuffer$1(array.value)) { - throw new Error('array.value is not array or typedarray'); - } - attribs[attribName] = { - value: array.value, - }; - } else { - let fn; - if (array.buffer && array.buffer instanceof WebGLBuffer) { - fn = attribBufferFromBuffer; - } else if (typeof array === "number" || typeof array.data === "number") { - fn = attribBufferFromSize; - } else { - fn = attribBufferFromArrayLike; + const attribs = {} + Object.keys(arrays).forEach(function (arrayName) { + if (!isIndices(arrayName)) { + const array = arrays[arrayName] + const attribName = + array.attrib || + array.name || + array.attribName || + defaults$2.attribPrefix + arrayName + if (array.value) { + if ( + !Array.isArray(array.value) && + !isArrayBuffer$1(array.value) + ) { + throw new Error('array.value is not array or typedarray') + } + attribs[attribName] = { + value: array.value, + } + } else { + let fn + if (array.buffer && array.buffer instanceof WebGLBuffer) { + fn = attribBufferFromBuffer + } else if ( + typeof array === 'number' || + typeof array.data === 'number' + ) { + fn = attribBufferFromSize + } else { + fn = attribBufferFromArrayLike + } + const { buffer, type, numValues, arrayType } = fn( + gl, + array, + arrayName + ) + const normalization = + array.normalize !== undefined + ? array.normalize + : getNormalizationForTypedArrayType(arrayType) + const numComponents = getNumComponents$1( + array, + arrayName, + numValues + ) + attribs[attribName] = { + buffer: buffer, + numComponents: numComponents, + type: type, + normalize: normalization, + stride: array.stride || 0, + offset: array.offset || 0, + divisor: + array.divisor === undefined ? undefined : array.divisor, + drawType: array.drawType, + } + } } - const {buffer, type, numValues, arrayType} = fn(gl, array, arrayName); - const normalization = array.normalize !== undefined ? array.normalize : getNormalizationForTypedArrayType(arrayType); - const numComponents = getNumComponents$1(array, arrayName, numValues); - attribs[attribName] = { - buffer: buffer, - numComponents: numComponents, - type: type, - normalize: normalization, - stride: array.stride || 0, - offset: array.offset || 0, - divisor: array.divisor === undefined ? undefined : array.divisor, - drawType: array.drawType, - }; - } - } - }); - gl.bindBuffer(ARRAY_BUFFER$1, null); - return attribs; + }) + gl.bindBuffer(ARRAY_BUFFER$1, null) + return attribs } /** @@ -2442,86 +2602,96 @@ function createAttribsFromArrays(gl, arrays) { * @memberOf module:twgl/attributes */ function setAttribInfoBufferFromArray(gl, attribInfo, array, offset) { - array = makeTypedArray(array); - if (offset !== undefined) { - gl.bindBuffer(ARRAY_BUFFER$1, attribInfo.buffer); - gl.bufferSubData(ARRAY_BUFFER$1, offset, array); - } else { - setBufferFromTypedArray(gl, ARRAY_BUFFER$1, attribInfo.buffer, array, attribInfo.drawType); - } + array = makeTypedArray(array) + if (offset !== undefined) { + gl.bindBuffer(ARRAY_BUFFER$1, attribInfo.buffer) + gl.bufferSubData(ARRAY_BUFFER$1, offset, array) + } else { + setBufferFromTypedArray( + gl, + ARRAY_BUFFER$1, + attribInfo.buffer, + array, + attribInfo.drawType + ) + } } function getBytesPerValueForGLType(gl, type) { - if (type === BYTE$1) return 1; // eslint-disable-line - if (type === UNSIGNED_BYTE$2) return 1; // eslint-disable-line - if (type === SHORT$1) return 2; // eslint-disable-line - if (type === UNSIGNED_SHORT$2) return 2; // eslint-disable-line - if (type === INT$2) return 4; // eslint-disable-line - if (type === UNSIGNED_INT$2) return 4; // eslint-disable-line - if (type === FLOAT$2) return 4; // eslint-disable-line - return 0; + if (type === BYTE$1) return 1 // eslint-disable-line + if (type === UNSIGNED_BYTE$2) return 1 // eslint-disable-line + if (type === SHORT$1) return 2 // eslint-disable-line + if (type === UNSIGNED_SHORT$2) return 2 // eslint-disable-line + if (type === INT$2) return 4 // eslint-disable-line + if (type === UNSIGNED_INT$2) return 4 // eslint-disable-line + if (type === FLOAT$2) return 4 // eslint-disable-line + return 0 } // Tries to get the number of elements from a set of arrays. -const positionKeys = ['position', 'positions', 'a_position']; +const positionKeys = ['position', 'positions', 'a_position'] function getNumElementsFromNonIndexedArrays(arrays) { - let key; - let ii; - for (ii = 0; ii < positionKeys.length; ++ii) { - key = positionKeys[ii]; - if (key in arrays) { - break; - } - } - if (ii === positionKeys.length) { - key = Object.keys(arrays)[0]; - } - const array = arrays[key]; - const length = getArray$1(array).length; - if (length === undefined) { - return 1; // There's no arrays - } - const numComponents = getNumComponents$1(array, key); - const numElements = length / numComponents; - if (length % numComponents > 0) { - throw new Error(`numComponents ${numComponents} not correct for length ${length}`); - } - return numElements; + let key + let ii + for (ii = 0; ii < positionKeys.length; ++ii) { + key = positionKeys[ii] + if (key in arrays) { + break + } + } + if (ii === positionKeys.length) { + key = Object.keys(arrays)[0] + } + const array = arrays[key] + const length = getArray$1(array).length + if (length === undefined) { + return 1 // There's no arrays + } + const numComponents = getNumComponents$1(array, key) + const numElements = length / numComponents + if (length % numComponents > 0) { + throw new Error( + `numComponents ${numComponents} not correct for length ${length}` + ) + } + return numElements } function getNumElementsFromAttributes(gl, attribs) { - let key; - let ii; - for (ii = 0; ii < positionKeys.length; ++ii) { - key = positionKeys[ii]; - if (key in attribs) { - break; - } - key = defaults$2.attribPrefix + key; - if (key in attribs) { - break; - } - } - if (ii === positionKeys.length) { - key = Object.keys(attribs)[0]; - } - const attrib = attribs[key]; - if (!attrib.buffer) { - return 1; // There's no buffer - } - gl.bindBuffer(ARRAY_BUFFER$1, attrib.buffer); - const numBytes = gl.getBufferParameter(ARRAY_BUFFER$1, BUFFER_SIZE); - gl.bindBuffer(ARRAY_BUFFER$1, null); - - const bytesPerValue = getBytesPerValueForGLType(gl, attrib.type); - const totalElements = numBytes / bytesPerValue; - const numComponents = attrib.numComponents || attrib.size; - // TODO: check stride - const numElements = totalElements / numComponents; - if (numElements % 1 !== 0) { - throw new Error(`numComponents ${numComponents} not correct for length ${length}`); - } - return numElements; + let key + let ii + for (ii = 0; ii < positionKeys.length; ++ii) { + key = positionKeys[ii] + if (key in attribs) { + break + } + key = defaults$2.attribPrefix + key + if (key in attribs) { + break + } + } + if (ii === positionKeys.length) { + key = Object.keys(attribs)[0] + } + const attrib = attribs[key] + if (!attrib.buffer) { + return 1 // There's no buffer + } + gl.bindBuffer(ARRAY_BUFFER$1, attrib.buffer) + const numBytes = gl.getBufferParameter(ARRAY_BUFFER$1, BUFFER_SIZE) + gl.bindBuffer(ARRAY_BUFFER$1, null) + + const bytesPerValue = getBytesPerValueForGLType(gl, attrib.type) + const totalElements = numBytes / bytesPerValue + const numComponents = attrib.numComponents || attrib.size + // TODO: check stride + const numElements = totalElements / numComponents + if (numElements % 1 !== 0) { + throw new Error( + `numComponents ${numComponents} not correct for length ${length}` + ) + } + return numElements } /** @@ -2630,20 +2800,31 @@ function getNumElementsFromAttributes(gl, attribs) { * @memberOf module:twgl/attributes */ function createBufferInfoFromArrays(gl, arrays, srcBufferInfo) { - const newAttribs = createAttribsFromArrays(gl, arrays); - const bufferInfo = Object.assign({}, srcBufferInfo ? srcBufferInfo : {}); - bufferInfo.attribs = Object.assign({}, srcBufferInfo ? srcBufferInfo.attribs : {}, newAttribs); - const indices = arrays.indices; - if (indices) { - const newIndices = makeTypedArray(indices, "indices"); - bufferInfo.indices = createBufferFromTypedArray(gl, newIndices, ELEMENT_ARRAY_BUFFER$2); - bufferInfo.numElements = newIndices.length; - bufferInfo.elementType = getGLTypeForTypedArray(newIndices); - } else if (!bufferInfo.numElements) { - bufferInfo.numElements = getNumElementsFromAttributes(gl, bufferInfo.attribs); - } + const newAttribs = createAttribsFromArrays(gl, arrays) + const bufferInfo = Object.assign({}, srcBufferInfo ? srcBufferInfo : {}) + bufferInfo.attribs = Object.assign( + {}, + srcBufferInfo ? srcBufferInfo.attribs : {}, + newAttribs + ) + const indices = arrays.indices + if (indices) { + const newIndices = makeTypedArray(indices, 'indices') + bufferInfo.indices = createBufferFromTypedArray( + gl, + newIndices, + ELEMENT_ARRAY_BUFFER$2 + ) + bufferInfo.numElements = newIndices.length + bufferInfo.elementType = getGLTypeForTypedArray(newIndices) + } else if (!bufferInfo.numElements) { + bufferInfo.numElements = getNumElementsFromAttributes( + gl, + bufferInfo.attribs + ) + } - return bufferInfo; + return bufferInfo } /** @@ -2673,9 +2854,10 @@ function createBufferInfoFromArrays(gl, arrays, srcBufferInfo) { * @memberOf module:twgl/attributes */ function createBufferFromArray(gl, array, arrayName) { - const type = arrayName === "indices" ? ELEMENT_ARRAY_BUFFER$2 : ARRAY_BUFFER$1; - const typedArray = makeTypedArray(array, arrayName); - return createBufferFromTypedArray(gl, typedArray, type); + const type = + arrayName === 'indices' ? ELEMENT_ARRAY_BUFFER$2 : ARRAY_BUFFER$1 + const typedArray = makeTypedArray(array, arrayName) + return createBufferFromTypedArray(gl, typedArray, type) } /** @@ -2703,35 +2885,37 @@ function createBufferFromArray(gl, array, arrayName) { * @memberOf module:twgl/attributes */ function createBuffersFromArrays(gl, arrays) { - const buffers = { }; - Object.keys(arrays).forEach(function(key) { - buffers[key] = createBufferFromArray(gl, arrays[key], key); - }); - - // Ugh! - if (arrays.indices) { - buffers.numElements = arrays.indices.length; - buffers.elementType = getGLTypeForTypedArray(makeTypedArray(arrays.indices)); - } else { - buffers.numElements = getNumElementsFromNonIndexedArrays(arrays); - } - - return buffers; -} - -var attributes = /*#__PURE__*/Object.freeze({ - __proto__: null, - createAttribsFromArrays: createAttribsFromArrays, - createBuffersFromArrays: createBuffersFromArrays, - createBufferFromArray: createBufferFromArray, - createBufferFromTypedArray: createBufferFromTypedArray, - createBufferInfoFromArrays: createBufferInfoFromArrays, - setAttribInfoBufferFromArray: setAttribInfoBufferFromArray, - setAttributePrefix: setAttributePrefix, - setAttributeDefaults_: setDefaults$2, - getNumComponents_: getNumComponents$1, - getArray_: getArray$1 -}); + const buffers = {} + Object.keys(arrays).forEach(function (key) { + buffers[key] = createBufferFromArray(gl, arrays[key], key) + }) + + // Ugh! + if (arrays.indices) { + buffers.numElements = arrays.indices.length + buffers.elementType = getGLTypeForTypedArray( + makeTypedArray(arrays.indices) + ) + } else { + buffers.numElements = getNumElementsFromNonIndexedArrays(arrays) + } + + return buffers +} + +var attributes = /*#__PURE__*/ Object.freeze({ + __proto__: null, + createAttribsFromArrays: createAttribsFromArrays, + createBuffersFromArrays: createBuffersFromArrays, + createBufferFromArray: createBufferFromArray, + createBufferFromTypedArray: createBufferFromTypedArray, + createBufferInfoFromArrays: createBufferInfoFromArrays, + setAttribInfoBufferFromArray: setAttribInfoBufferFromArray, + setAttributePrefix: setAttributePrefix, + setAttributeDefaults_: setDefaults$2, + getNumComponents_: getNumComponents$1, + getArray_: getArray$1, +}) /* * Copyright 2019 Gregg Tavares @@ -2755,8 +2939,8 @@ var attributes = /*#__PURE__*/Object.freeze({ * DEALINGS IN THE SOFTWARE. */ -const getArray = getArray$1; // eslint-disable-line -const getNumComponents = getNumComponents$1; // eslint-disable-line +const getArray = getArray$1 // eslint-disable-line +const getNumComponents = getNumComponents$1 // eslint-disable-line /** * @typedef {(Int8Array|Uint8Array|Int16Array|Uint16Array|Int32Array|Uint32Array|Float32Array)} TypedArray @@ -2771,29 +2955,29 @@ const getNumComponents = getNumComponents$1; // eslint-disable-line * @private */ function augmentTypedArray(typedArray, numComponents) { - let cursor = 0; - typedArray.push = function() { - for (let ii = 0; ii < arguments.length; ++ii) { - const value = arguments[ii]; - if (value instanceof Array || isArrayBuffer$1(value)) { - for (let jj = 0; jj < value.length; ++jj) { - typedArray[cursor++] = value[jj]; - } - } else { - typedArray[cursor++] = value; - } - } - }; - typedArray.reset = function(opt_index) { - cursor = opt_index || 0; - }; - typedArray.numComponents = numComponents; - Object.defineProperty(typedArray, 'numElements', { - get: function() { - return this.length / this.numComponents | 0; - }, - }); - return typedArray; + let cursor = 0 + typedArray.push = function () { + for (let ii = 0; ii < arguments.length; ++ii) { + const value = arguments[ii] + if (value instanceof Array || isArrayBuffer$1(value)) { + for (let jj = 0; jj < value.length; ++jj) { + typedArray[cursor++] = value[jj] + } + } else { + typedArray[cursor++] = value + } + } + } + typedArray.reset = function (opt_index) { + cursor = opt_index || 0 + } + typedArray.numComponents = numComponents + Object.defineProperty(typedArray, 'numElements', { + get: function () { + return (this.length / this.numComponents) | 0 + }, + }) + return typedArray } /** @@ -2819,12 +3003,15 @@ function augmentTypedArray(typedArray, numComponents) { * @memberOf module:twgl/primitives */ function createAugmentedTypedArray(numComponents, numElements, opt_type) { - const Type = opt_type || Float32Array; - return augmentTypedArray(new Type(numComponents * numElements), numComponents); + const Type = opt_type || Float32Array + return augmentTypedArray( + new Type(numComponents * numElements), + numComponents + ) } function allButIndices(name) { - return name !== "indices"; + return name !== 'indices' } /** @@ -2834,27 +3021,31 @@ function allButIndices(name) { * @memberOf module:twgl/primitives */ function deindexVertices(vertices) { - const indices = vertices.indices; - const newVertices = {}; - const numElements = indices.length; - - function expandToUnindexed(channel) { - const srcBuffer = vertices[channel]; - const numComponents = srcBuffer.numComponents; - const dstBuffer = createAugmentedTypedArray(numComponents, numElements, srcBuffer.constructor); - for (let ii = 0; ii < numElements; ++ii) { - const ndx = indices[ii]; - const offset = ndx * numComponents; - for (let jj = 0; jj < numComponents; ++jj) { - dstBuffer.push(srcBuffer[offset + jj]); - } + const indices = vertices.indices + const newVertices = {} + const numElements = indices.length + + function expandToUnindexed(channel) { + const srcBuffer = vertices[channel] + const numComponents = srcBuffer.numComponents + const dstBuffer = createAugmentedTypedArray( + numComponents, + numElements, + srcBuffer.constructor + ) + for (let ii = 0; ii < numElements; ++ii) { + const ndx = indices[ii] + const offset = ndx * numComponents + for (let jj = 0; jj < numComponents; ++jj) { + dstBuffer.push(srcBuffer[offset + jj]) + } + } + newVertices[channel] = dstBuffer } - newVertices[channel] = dstBuffer; - } - Object.keys(vertices).filter(allButIndices).forEach(expandToUnindexed); + Object.keys(vertices).filter(allButIndices).forEach(expandToUnindexed) - return newVertices; + return newVertices } /** @@ -2864,77 +3055,79 @@ function deindexVertices(vertices) { * @memberOf module:twgl/primitives */ function flattenNormals(vertices) { - if (vertices.indices) { - throw new Error('can not flatten normals of indexed vertices. deindex them first'); - } - - const normals = vertices.normal; - const numNormals = normals.length; - for (let ii = 0; ii < numNormals; ii += 9) { - // pull out the 3 normals for this triangle - const nax = normals[ii + 0]; - const nay = normals[ii + 1]; - const naz = normals[ii + 2]; - - const nbx = normals[ii + 3]; - const nby = normals[ii + 4]; - const nbz = normals[ii + 5]; - - const ncx = normals[ii + 6]; - const ncy = normals[ii + 7]; - const ncz = normals[ii + 8]; - - // add them - let nx = nax + nbx + ncx; - let ny = nay + nby + ncy; - let nz = naz + nbz + ncz; - - // normalize them - const length = Math.sqrt(nx * nx + ny * ny + nz * nz); - - nx /= length; - ny /= length; - nz /= length; - - // copy them back in - normals[ii + 0] = nx; - normals[ii + 1] = ny; - normals[ii + 2] = nz; - - normals[ii + 3] = nx; - normals[ii + 4] = ny; - normals[ii + 5] = nz; + if (vertices.indices) { + throw new Error( + 'can not flatten normals of indexed vertices. deindex them first' + ) + } - normals[ii + 6] = nx; - normals[ii + 7] = ny; - normals[ii + 8] = nz; - } + const normals = vertices.normal + const numNormals = normals.length + for (let ii = 0; ii < numNormals; ii += 9) { + // pull out the 3 normals for this triangle + const nax = normals[ii + 0] + const nay = normals[ii + 1] + const naz = normals[ii + 2] + + const nbx = normals[ii + 3] + const nby = normals[ii + 4] + const nbz = normals[ii + 5] + + const ncx = normals[ii + 6] + const ncy = normals[ii + 7] + const ncz = normals[ii + 8] + + // add them + let nx = nax + nbx + ncx + let ny = nay + nby + ncy + let nz = naz + nbz + ncz + + // normalize them + const length = Math.sqrt(nx * nx + ny * ny + nz * nz) + + nx /= length + ny /= length + nz /= length + + // copy them back in + normals[ii + 0] = nx + normals[ii + 1] = ny + normals[ii + 2] = nz + + normals[ii + 3] = nx + normals[ii + 4] = ny + normals[ii + 5] = nz + + normals[ii + 6] = nx + normals[ii + 7] = ny + normals[ii + 8] = nz + } - return vertices; + return vertices } function applyFuncToV3Array(array, matrix, fn) { - const len = array.length; - const tmp = new Float32Array(3); - for (let ii = 0; ii < len; ii += 3) { - fn(matrix, [array[ii], array[ii + 1], array[ii + 2]], tmp); - array[ii ] = tmp[0]; - array[ii + 1] = tmp[1]; - array[ii + 2] = tmp[2]; - } + const len = array.length + const tmp = new Float32Array(3) + for (let ii = 0; ii < len; ii += 3) { + fn(matrix, [array[ii], array[ii + 1], array[ii + 2]], tmp) + array[ii] = tmp[0] + array[ii + 1] = tmp[1] + array[ii + 2] = tmp[2] + } } function transformNormal(mi, v, dst) { - dst = dst || create$1(); - const v0 = v[0]; - const v1 = v[1]; - const v2 = v[2]; + dst = dst || create$1() + const v0 = v[0] + const v1 = v[1] + const v2 = v[2] - dst[0] = v0 * mi[0 * 4 + 0] + v1 * mi[0 * 4 + 1] + v2 * mi[0 * 4 + 2]; - dst[1] = v0 * mi[1 * 4 + 0] + v1 * mi[1 * 4 + 1] + v2 * mi[1 * 4 + 2]; - dst[2] = v0 * mi[2 * 4 + 0] + v1 * mi[2 * 4 + 1] + v2 * mi[2 * 4 + 2]; + dst[0] = v0 * mi[0 * 4 + 0] + v1 * mi[0 * 4 + 1] + v2 * mi[0 * 4 + 2] + dst[1] = v0 * mi[1 * 4 + 0] + v1 * mi[1 * 4 + 1] + v2 * mi[1 * 4 + 2] + dst[2] = v0 * mi[2 * 4 + 0] + v1 * mi[2 * 4 + 1] + v2 * mi[2 * 4 + 2] - return dst; + return dst } /** @@ -2945,8 +3138,8 @@ function transformNormal(mi, v, dst) { * @memberOf module:twgl/primitives */ function reorientDirections(array, matrix) { - applyFuncToV3Array(array, matrix, transformDirection); - return array; + applyFuncToV3Array(array, matrix, transformDirection) + return array } /** @@ -2958,8 +3151,8 @@ function reorientDirections(array, matrix) { * @memberOf module:twgl/primitives */ function reorientNormals(array, matrix) { - applyFuncToV3Array(array, inverse(matrix), transformNormal); - return array; + applyFuncToV3Array(array, inverse(matrix), transformNormal) + return array } /** @@ -2971,8 +3164,8 @@ function reorientNormals(array, matrix) { * @memberOf module:twgl/primitives */ function reorientPositions(array, matrix) { - applyFuncToV3Array(array, matrix, transformPoint); - return array; + applyFuncToV3Array(array, matrix, transformPoint) + return array } /** @@ -2990,17 +3183,17 @@ function reorientPositions(array, matrix) { * @memberOf module:twgl/primitives */ function reorientVertices(arrays, matrix) { - Object.keys(arrays).forEach(function(name) { - const array = arrays[name]; - if (name.indexOf("pos") >= 0) { - reorientPositions(array, matrix); - } else if (name.indexOf("tan") >= 0 || name.indexOf("binorm") >= 0) { - reorientDirections(array, matrix); - } else if (name.indexOf("norm") >= 0) { - reorientNormals(array, matrix); - } - }); - return arrays; + Object.keys(arrays).forEach(function (name) { + const array = arrays[name] + if (name.indexOf('pos') >= 0) { + reorientPositions(array, matrix) + } else if (name.indexOf('tan') >= 0 || name.indexOf('binorm') >= 0) { + reorientDirections(array, matrix) + } else if (name.indexOf('norm') >= 0) { + reorientNormals(array, matrix) + } + }) + return arrays } /** @@ -3064,34 +3257,28 @@ function reorientVertices(arrays, matrix) { * @memberOf module:twgl/primitives */ function createXYQuadVertices(size, xOffset, yOffset) { - size = size || 2; - xOffset = xOffset || 0; - yOffset = yOffset || 0; - size *= 0.5; - return { - position: { - numComponents: 2, - data: [ - xOffset + -1 * size, yOffset + -1 * size, - xOffset + 1 * size, yOffset + -1 * size, - xOffset + -1 * size, yOffset + 1 * size, - xOffset + 1 * size, yOffset + 1 * size, - ], - }, - normal: [ - 0, 0, 1, - 0, 0, 1, - 0, 0, 1, - 0, 0, 1, - ], - texcoord: [ - 0, 0, - 1, 0, - 0, 1, - 1, 1, - ], - indices: [ 0, 1, 2, 2, 1, 3 ], - }; + size = size || 2 + xOffset = xOffset || 0 + yOffset = yOffset || 0 + size *= 0.5 + return { + position: { + numComponents: 2, + data: [ + xOffset + -1 * size, + yOffset + -1 * size, + xOffset + 1 * size, + yOffset + -1 * size, + xOffset + -1 * size, + yOffset + 1 * size, + xOffset + 1 * size, + yOffset + 1 * size, + ], + }, + normal: [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1], + texcoord: [0, 0, 1, 0, 0, 1, 1, 1], + indices: [0, 1, 2, 2, 1, 3], + } } /** @@ -3144,58 +3331,66 @@ function createPlaneVertices( depth, subdivisionsWidth, subdivisionsDepth, - matrix) { - width = width || 1; - depth = depth || 1; - subdivisionsWidth = subdivisionsWidth || 1; - subdivisionsDepth = subdivisionsDepth || 1; - matrix = matrix || identity(); - - const numVertices = (subdivisionsWidth + 1) * (subdivisionsDepth + 1); - const positions = createAugmentedTypedArray(3, numVertices); - const normals = createAugmentedTypedArray(3, numVertices); - const texcoords = createAugmentedTypedArray(2, numVertices); - - for (let z = 0; z <= subdivisionsDepth; z++) { - for (let x = 0; x <= subdivisionsWidth; x++) { - const u = x / subdivisionsWidth; - const v = z / subdivisionsDepth; - positions.push( - width * u - width * 0.5, - 0, - depth * v - depth * 0.5); - normals.push(0, 1, 0); - texcoords.push(u, v); - } - } - - const numVertsAcross = subdivisionsWidth + 1; - const indices = createAugmentedTypedArray( - 3, subdivisionsWidth * subdivisionsDepth * 2, Uint16Array); - - for (let z = 0; z < subdivisionsDepth; z++) { // eslint-disable-line - for (let x = 0; x < subdivisionsWidth; x++) { // eslint-disable-line - // Make triangle 1 of quad. - indices.push( - (z + 0) * numVertsAcross + x, - (z + 1) * numVertsAcross + x, - (z + 0) * numVertsAcross + x + 1); - - // Make triangle 2 of quad. - indices.push( - (z + 1) * numVertsAcross + x, - (z + 1) * numVertsAcross + x + 1, - (z + 0) * numVertsAcross + x + 1); - } - } - - const arrays = reorientVertices({ - position: positions, - normal: normals, - texcoord: texcoords, - indices: indices, - }, matrix); - return arrays; + matrix +) { + width = width || 1 + depth = depth || 1 + subdivisionsWidth = subdivisionsWidth || 1 + subdivisionsDepth = subdivisionsDepth || 1 + matrix = matrix || identity() + + const numVertices = (subdivisionsWidth + 1) * (subdivisionsDepth + 1) + const positions = createAugmentedTypedArray(3, numVertices) + const normals = createAugmentedTypedArray(3, numVertices) + const texcoords = createAugmentedTypedArray(2, numVertices) + + for (let z = 0; z <= subdivisionsDepth; z++) { + for (let x = 0; x <= subdivisionsWidth; x++) { + const u = x / subdivisionsWidth + const v = z / subdivisionsDepth + positions.push(width * u - width * 0.5, 0, depth * v - depth * 0.5) + normals.push(0, 1, 0) + texcoords.push(u, v) + } + } + + const numVertsAcross = subdivisionsWidth + 1 + const indices = createAugmentedTypedArray( + 3, + subdivisionsWidth * subdivisionsDepth * 2, + Uint16Array + ) + + for (let z = 0; z < subdivisionsDepth; z++) { + // eslint-disable-line + for (let x = 0; x < subdivisionsWidth; x++) { + // eslint-disable-line + // Make triangle 1 of quad. + indices.push( + (z + 0) * numVertsAcross + x, + (z + 1) * numVertsAcross + x, + (z + 0) * numVertsAcross + x + 1 + ) + + // Make triangle 2 of quad. + indices.push( + (z + 1) * numVertsAcross + x, + (z + 1) * numVertsAcross + x + 1, + (z + 0) * numVertsAcross + x + 1 + ) + } + } + + const arrays = reorientVertices( + { + position: positions, + normal: normals, + texcoord: texcoords, + indices: indices, + }, + matrix + ) + return arrays } /** @@ -3268,72 +3463,81 @@ function createSphereVertices( opt_startLatitudeInRadians, opt_endLatitudeInRadians, opt_startLongitudeInRadians, - opt_endLongitudeInRadians) { - if (subdivisionsAxis <= 0 || subdivisionsHeight <= 0) { - throw new Error('subdivisionAxis and subdivisionHeight must be > 0'); - } - - opt_startLatitudeInRadians = opt_startLatitudeInRadians || 0; - opt_endLatitudeInRadians = opt_endLatitudeInRadians || Math.PI; - opt_startLongitudeInRadians = opt_startLongitudeInRadians || 0; - opt_endLongitudeInRadians = opt_endLongitudeInRadians || (Math.PI * 2); - - const latRange = opt_endLatitudeInRadians - opt_startLatitudeInRadians; - const longRange = opt_endLongitudeInRadians - opt_startLongitudeInRadians; - - // We are going to generate our sphere by iterating through its - // spherical coordinates and generating 2 triangles for each quad on a - // ring of the sphere. - const numVertices = (subdivisionsAxis + 1) * (subdivisionsHeight + 1); - const positions = createAugmentedTypedArray(3, numVertices); - const normals = createAugmentedTypedArray(3, numVertices); - const texcoords = createAugmentedTypedArray(2, numVertices); - - // Generate the individual vertices in our vertex buffer. - for (let y = 0; y <= subdivisionsHeight; y++) { - for (let x = 0; x <= subdivisionsAxis; x++) { - // Generate a vertex based on its spherical coordinates - const u = x / subdivisionsAxis; - const v = y / subdivisionsHeight; - const theta = longRange * u + opt_startLongitudeInRadians; - const phi = latRange * v + opt_startLatitudeInRadians; - const sinTheta = Math.sin(theta); - const cosTheta = Math.cos(theta); - const sinPhi = Math.sin(phi); - const cosPhi = Math.cos(phi); - const ux = cosTheta * sinPhi; - const uy = cosPhi; - const uz = sinTheta * sinPhi; - positions.push(radius * ux, radius * uy, radius * uz); - normals.push(ux, uy, uz); - texcoords.push(1 - u, v); - } - } - - const numVertsAround = subdivisionsAxis + 1; - const indices = createAugmentedTypedArray(3, subdivisionsAxis * subdivisionsHeight * 2, Uint16Array); - for (let x = 0; x < subdivisionsAxis; x++) { // eslint-disable-line - for (let y = 0; y < subdivisionsHeight; y++) { // eslint-disable-line - // Make triangle 1 of quad. - indices.push( - (y + 0) * numVertsAround + x, - (y + 0) * numVertsAround + x + 1, - (y + 1) * numVertsAround + x); - - // Make triangle 2 of quad. - indices.push( - (y + 1) * numVertsAround + x, - (y + 0) * numVertsAround + x + 1, - (y + 1) * numVertsAround + x + 1); - } - } - - return { - position: positions, - normal: normals, - texcoord: texcoords, - indices: indices, - }; + opt_endLongitudeInRadians +) { + if (subdivisionsAxis <= 0 || subdivisionsHeight <= 0) { + throw new Error('subdivisionAxis and subdivisionHeight must be > 0') + } + + opt_startLatitudeInRadians = opt_startLatitudeInRadians || 0 + opt_endLatitudeInRadians = opt_endLatitudeInRadians || Math.PI + opt_startLongitudeInRadians = opt_startLongitudeInRadians || 0 + opt_endLongitudeInRadians = opt_endLongitudeInRadians || Math.PI * 2 + + const latRange = opt_endLatitudeInRadians - opt_startLatitudeInRadians + const longRange = opt_endLongitudeInRadians - opt_startLongitudeInRadians + + // We are going to generate our sphere by iterating through its + // spherical coordinates and generating 2 triangles for each quad on a + // ring of the sphere. + const numVertices = (subdivisionsAxis + 1) * (subdivisionsHeight + 1) + const positions = createAugmentedTypedArray(3, numVertices) + const normals = createAugmentedTypedArray(3, numVertices) + const texcoords = createAugmentedTypedArray(2, numVertices) + + // Generate the individual vertices in our vertex buffer. + for (let y = 0; y <= subdivisionsHeight; y++) { + for (let x = 0; x <= subdivisionsAxis; x++) { + // Generate a vertex based on its spherical coordinates + const u = x / subdivisionsAxis + const v = y / subdivisionsHeight + const theta = longRange * u + opt_startLongitudeInRadians + const phi = latRange * v + opt_startLatitudeInRadians + const sinTheta = Math.sin(theta) + const cosTheta = Math.cos(theta) + const sinPhi = Math.sin(phi) + const cosPhi = Math.cos(phi) + const ux = cosTheta * sinPhi + const uy = cosPhi + const uz = sinTheta * sinPhi + positions.push(radius * ux, radius * uy, radius * uz) + normals.push(ux, uy, uz) + texcoords.push(1 - u, v) + } + } + + const numVertsAround = subdivisionsAxis + 1 + const indices = createAugmentedTypedArray( + 3, + subdivisionsAxis * subdivisionsHeight * 2, + Uint16Array + ) + for (let x = 0; x < subdivisionsAxis; x++) { + // eslint-disable-line + for (let y = 0; y < subdivisionsHeight; y++) { + // eslint-disable-line + // Make triangle 1 of quad. + indices.push( + (y + 0) * numVertsAround + x, + (y + 0) * numVertsAround + x + 1, + (y + 1) * numVertsAround + x + ) + + // Make triangle 2 of quad. + indices.push( + (y + 1) * numVertsAround + x, + (y + 0) * numVertsAround + x + 1, + (y + 1) * numVertsAround + x + 1 + ) + } + } + + return { + position: positions, + normal: normals, + texcoord: texcoords, + indices: indices, + } } /** @@ -3342,13 +3546,13 @@ function createSphereVertices( * @private */ const CUBE_FACE_INDICES = [ - [3, 7, 5, 1], // right - [6, 2, 0, 4], // left - [6, 7, 3, 2], // ?? - [0, 1, 5, 4], // ?? - [7, 6, 4, 5], // front - [2, 3, 1, 0], // back -]; + [3, 7, 5, 1], // right + [6, 2, 0, 4], // left + [6, 7, 3, 2], // ?? + [0, 1, 5, 4], // ?? + [7, 6, 4, 5], // front + [2, 3, 1, 0], // back +] /** * Creates a BufferInfo for a cube. @@ -3384,68 +3588,67 @@ const CUBE_FACE_INDICES = [ * @memberOf module:twgl/primitives */ function createCubeVertices(size) { - size = size || 1; - const k = size / 2; - - const cornerVertices = [ - [-k, -k, -k], - [+k, -k, -k], - [-k, +k, -k], - [+k, +k, -k], - [-k, -k, +k], - [+k, -k, +k], - [-k, +k, +k], - [+k, +k, +k], - ]; - - const faceNormals = [ - [+1, +0, +0], - [-1, +0, +0], - [+0, +1, +0], - [+0, -1, +0], - [+0, +0, +1], - [+0, +0, -1], - ]; - - const uvCoords = [ - [1, 0], - [0, 0], - [0, 1], - [1, 1], - ]; - - const numVertices = 6 * 4; - const positions = createAugmentedTypedArray(3, numVertices); - const normals = createAugmentedTypedArray(3, numVertices); - const texcoords = createAugmentedTypedArray(2 , numVertices); - const indices = createAugmentedTypedArray(3, 6 * 2, Uint16Array); - - for (let f = 0; f < 6; ++f) { - const faceIndices = CUBE_FACE_INDICES[f]; - for (let v = 0; v < 4; ++v) { - const position = cornerVertices[faceIndices[v]]; - const normal = faceNormals[f]; - const uv = uvCoords[v]; - - // Each face needs all four vertices because the normals and texture - // coordinates are not all the same. - positions.push(position); - normals.push(normal); - texcoords.push(uv); - - } - // Two triangles make a square face. - const offset = 4 * f; - indices.push(offset + 0, offset + 1, offset + 2); - indices.push(offset + 0, offset + 2, offset + 3); - } - - return { - position: positions, - normal: normals, - texcoord: texcoords, - indices: indices, - }; + size = size || 1 + const k = size / 2 + + const cornerVertices = [ + [-k, -k, -k], + [+k, -k, -k], + [-k, +k, -k], + [+k, +k, -k], + [-k, -k, +k], + [+k, -k, +k], + [-k, +k, +k], + [+k, +k, +k], + ] + + const faceNormals = [ + [+1, +0, +0], + [-1, +0, +0], + [+0, +1, +0], + [+0, -1, +0], + [+0, +0, +1], + [+0, +0, -1], + ] + + const uvCoords = [ + [1, 0], + [0, 0], + [0, 1], + [1, 1], + ] + + const numVertices = 6 * 4 + const positions = createAugmentedTypedArray(3, numVertices) + const normals = createAugmentedTypedArray(3, numVertices) + const texcoords = createAugmentedTypedArray(2, numVertices) + const indices = createAugmentedTypedArray(3, 6 * 2, Uint16Array) + + for (let f = 0; f < 6; ++f) { + const faceIndices = CUBE_FACE_INDICES[f] + for (let v = 0; v < 4; ++v) { + const position = cornerVertices[faceIndices[v]] + const normal = faceNormals[f] + const uv = uvCoords[v] + + // Each face needs all four vertices because the normals and texture + // coordinates are not all the same. + positions.push(position) + normals.push(normal) + texcoords.push(uv) + } + // Two triangles make a square face. + const offset = 4 * f + indices.push(offset + 0, offset + 1, offset + 2) + indices.push(offset + 0, offset + 2, offset + 3) + } + + return { + position: positions, + normal: normals, + texcoord: texcoords, + indices: indices, + } } /** @@ -3518,94 +3721,110 @@ function createTruncatedConeVertices( radialSubdivisions, verticalSubdivisions, opt_topCap, - opt_bottomCap) { - if (radialSubdivisions < 3) { - throw new Error('radialSubdivisions must be 3 or greater'); - } - - if (verticalSubdivisions < 1) { - throw new Error('verticalSubdivisions must be 1 or greater'); - } - - const topCap = (opt_topCap === undefined) ? true : opt_topCap; - const bottomCap = (opt_bottomCap === undefined) ? true : opt_bottomCap; - - const extra = (topCap ? 2 : 0) + (bottomCap ? 2 : 0); - - const numVertices = (radialSubdivisions + 1) * (verticalSubdivisions + 1 + extra); - const positions = createAugmentedTypedArray(3, numVertices); - const normals = createAugmentedTypedArray(3, numVertices); - const texcoords = createAugmentedTypedArray(2, numVertices); - const indices = createAugmentedTypedArray(3, radialSubdivisions * (verticalSubdivisions + extra / 2) * 2, Uint16Array); - - const vertsAroundEdge = radialSubdivisions + 1; - - // The slant of the cone is constant across its surface - const slant = Math.atan2(bottomRadius - topRadius, height); - const cosSlant = Math.cos(slant); - const sinSlant = Math.sin(slant); - - const start = topCap ? -2 : 0; - const end = verticalSubdivisions + (bottomCap ? 2 : 0); - - for (let yy = start; yy <= end; ++yy) { - let v = yy / verticalSubdivisions; - let y = height * v; - let ringRadius; - if (yy < 0) { - y = 0; - v = 1; - ringRadius = bottomRadius; - } else if (yy > verticalSubdivisions) { - y = height; - v = 1; - ringRadius = topRadius; - } else { - ringRadius = bottomRadius + - (topRadius - bottomRadius) * (yy / verticalSubdivisions); - } - if (yy === -2 || yy === verticalSubdivisions + 2) { - ringRadius = 0; - v = 0; - } - y -= height / 2; - for (let ii = 0; ii < vertsAroundEdge; ++ii) { - const sin = Math.sin(ii * Math.PI * 2 / radialSubdivisions); - const cos = Math.cos(ii * Math.PI * 2 / radialSubdivisions); - positions.push(sin * ringRadius, y, cos * ringRadius); - if (yy < 0) { - normals.push(0, -1, 0); - } else if (yy > verticalSubdivisions) { - normals.push(0, 1, 0); - } else if (ringRadius === 0.0) { - normals.push(0, 0, 0); - } else { - normals.push(sin * cosSlant, sinSlant, cos * cosSlant); - } - texcoords.push((ii / radialSubdivisions), 1 - v); - } - } - - for (let yy = 0; yy < verticalSubdivisions + extra; ++yy) { // eslint-disable-line - if (yy === 1 && topCap || yy === verticalSubdivisions + extra - 2 && bottomCap) { - continue; - } - for (let ii = 0; ii < radialSubdivisions; ++ii) { // eslint-disable-line - indices.push(vertsAroundEdge * (yy + 0) + 0 + ii, - vertsAroundEdge * (yy + 0) + 1 + ii, - vertsAroundEdge * (yy + 1) + 1 + ii); - indices.push(vertsAroundEdge * (yy + 0) + 0 + ii, - vertsAroundEdge * (yy + 1) + 1 + ii, - vertsAroundEdge * (yy + 1) + 0 + ii); - } - } - - return { - position: positions, - normal: normals, - texcoord: texcoords, - indices: indices, - }; + opt_bottomCap +) { + if (radialSubdivisions < 3) { + throw new Error('radialSubdivisions must be 3 or greater') + } + + if (verticalSubdivisions < 1) { + throw new Error('verticalSubdivisions must be 1 or greater') + } + + const topCap = opt_topCap === undefined ? true : opt_topCap + const bottomCap = opt_bottomCap === undefined ? true : opt_bottomCap + + const extra = (topCap ? 2 : 0) + (bottomCap ? 2 : 0) + + const numVertices = + (radialSubdivisions + 1) * (verticalSubdivisions + 1 + extra) + const positions = createAugmentedTypedArray(3, numVertices) + const normals = createAugmentedTypedArray(3, numVertices) + const texcoords = createAugmentedTypedArray(2, numVertices) + const indices = createAugmentedTypedArray( + 3, + radialSubdivisions * (verticalSubdivisions + extra / 2) * 2, + Uint16Array + ) + + const vertsAroundEdge = radialSubdivisions + 1 + + // The slant of the cone is constant across its surface + const slant = Math.atan2(bottomRadius - topRadius, height) + const cosSlant = Math.cos(slant) + const sinSlant = Math.sin(slant) + + const start = topCap ? -2 : 0 + const end = verticalSubdivisions + (bottomCap ? 2 : 0) + + for (let yy = start; yy <= end; ++yy) { + let v = yy / verticalSubdivisions + let y = height * v + let ringRadius + if (yy < 0) { + y = 0 + v = 1 + ringRadius = bottomRadius + } else if (yy > verticalSubdivisions) { + y = height + v = 1 + ringRadius = topRadius + } else { + ringRadius = + bottomRadius + + (topRadius - bottomRadius) * (yy / verticalSubdivisions) + } + if (yy === -2 || yy === verticalSubdivisions + 2) { + ringRadius = 0 + v = 0 + } + y -= height / 2 + for (let ii = 0; ii < vertsAroundEdge; ++ii) { + const sin = Math.sin((ii * Math.PI * 2) / radialSubdivisions) + const cos = Math.cos((ii * Math.PI * 2) / radialSubdivisions) + positions.push(sin * ringRadius, y, cos * ringRadius) + if (yy < 0) { + normals.push(0, -1, 0) + } else if (yy > verticalSubdivisions) { + normals.push(0, 1, 0) + } else if (ringRadius === 0.0) { + normals.push(0, 0, 0) + } else { + normals.push(sin * cosSlant, sinSlant, cos * cosSlant) + } + texcoords.push(ii / radialSubdivisions, 1 - v) + } + } + + for (let yy = 0; yy < verticalSubdivisions + extra; ++yy) { + // eslint-disable-line + if ( + (yy === 1 && topCap) || + (yy === verticalSubdivisions + extra - 2 && bottomCap) + ) { + continue + } + for (let ii = 0; ii < radialSubdivisions; ++ii) { + // eslint-disable-line + indices.push( + vertsAroundEdge * (yy + 0) + 0 + ii, + vertsAroundEdge * (yy + 0) + 1 + ii, + vertsAroundEdge * (yy + 1) + 1 + ii + ) + indices.push( + vertsAroundEdge * (yy + 0) + 0 + ii, + vertsAroundEdge * (yy + 1) + 1 + ii, + vertsAroundEdge * (yy + 1) + 0 + ii + ) + } + } + + return { + position: positions, + normal: normals, + texcoord: texcoords, + indices: indices, + } } /** @@ -3616,17 +3835,17 @@ function createTruncatedConeVertices( * @private */ function expandRLEData(rleData, padding) { - padding = padding || []; - const data = []; - for (let ii = 0; ii < rleData.length; ii += 4) { - const runLength = rleData[ii]; - const element = rleData.slice(ii + 1, ii + 4); - element.push.apply(element, padding); - for (let jj = 0; jj < runLength; ++jj) { - data.push.apply(data, element); + padding = padding || [] + const data = [] + for (let ii = 0; ii < rleData.length; ii += 4) { + const runLength = rleData[ii] + const element = rleData.slice(ii + 1, ii + 4) + element.push.apply(element, padding) + for (let jj = 0; jj < runLength; ++jj) { + data.push.apply(data, element) + } } - } - return data; + return data } /** @@ -3660,371 +3879,213 @@ function expandRLEData(rleData, padding) { * @memberOf module:twgl/primitives */ function create3DFVertices() { + const positions = [ + // left column front + 0, 0, 0, 0, 150, 0, 30, 0, 0, 0, 150, 0, 30, 150, 0, 30, 0, 0, + + // top rung front + 30, 0, 0, 30, 30, 0, 100, 0, 0, 30, 30, 0, 100, 30, 0, 100, 0, 0, + + // middle rung front + 30, 60, 0, 30, 90, 0, 67, 60, 0, 30, 90, 0, 67, 90, 0, 67, 60, 0, + + // left column back + 0, 0, 30, 30, 0, 30, 0, 150, 30, 0, 150, 30, 30, 0, 30, 30, 150, 30, + + // top rung back + 30, 0, 30, 100, 0, 30, 30, 30, 30, 30, 30, 30, 100, 0, 30, 100, 30, 30, + + // middle rung back + 30, 60, 30, 67, 60, 30, 30, 90, 30, 30, 90, 30, 67, 60, 30, 67, 90, 30, + + // top + 0, 0, 0, 100, 0, 0, 100, 0, 30, 0, 0, 0, 100, 0, 30, 0, 0, 30, + + // top rung front + 100, 0, 0, 100, 30, 0, 100, 30, 30, 100, 0, 0, 100, 30, 30, 100, 0, 30, + + // under top rung + 30, 30, 0, 30, 30, 30, 100, 30, 30, 30, 30, 0, 100, 30, 30, 100, 30, 0, + + // between top rung and middle + 30, 30, 0, 30, 60, 30, 30, 30, 30, 30, 30, 0, 30, 60, 0, 30, 60, 30, + + // top of middle rung + 30, 60, 0, 67, 60, 30, 30, 60, 30, 30, 60, 0, 67, 60, 0, 67, 60, 30, - const positions = [ - // left column front - 0, 0, 0, - 0, 150, 0, - 30, 0, 0, - 0, 150, 0, - 30, 150, 0, - 30, 0, 0, - - // top rung front - 30, 0, 0, - 30, 30, 0, - 100, 0, 0, - 30, 30, 0, - 100, 30, 0, - 100, 0, 0, - - // middle rung front - 30, 60, 0, - 30, 90, 0, - 67, 60, 0, - 30, 90, 0, - 67, 90, 0, - 67, 60, 0, - - // left column back - 0, 0, 30, - 30, 0, 30, - 0, 150, 30, - 0, 150, 30, - 30, 0, 30, - 30, 150, 30, - - // top rung back - 30, 0, 30, - 100, 0, 30, - 30, 30, 30, - 30, 30, 30, - 100, 0, 30, - 100, 30, 30, - - // middle rung back - 30, 60, 30, - 67, 60, 30, - 30, 90, 30, - 30, 90, 30, - 67, 60, 30, - 67, 90, 30, - - // top - 0, 0, 0, - 100, 0, 0, - 100, 0, 30, - 0, 0, 0, - 100, 0, 30, - 0, 0, 30, - - // top rung front - 100, 0, 0, - 100, 30, 0, - 100, 30, 30, - 100, 0, 0, - 100, 30, 30, - 100, 0, 30, - - // under top rung - 30, 30, 0, - 30, 30, 30, - 100, 30, 30, - 30, 30, 0, - 100, 30, 30, - 100, 30, 0, - - // between top rung and middle - 30, 30, 0, - 30, 60, 30, - 30, 30, 30, - 30, 30, 0, - 30, 60, 0, - 30, 60, 30, - - // top of middle rung - 30, 60, 0, - 67, 60, 30, - 30, 60, 30, - 30, 60, 0, - 67, 60, 0, - 67, 60, 30, - - // front of middle rung - 67, 60, 0, - 67, 90, 30, - 67, 60, 30, - 67, 60, 0, - 67, 90, 0, - 67, 90, 30, - - // bottom of middle rung. - 30, 90, 0, - 30, 90, 30, - 67, 90, 30, - 30, 90, 0, - 67, 90, 30, - 67, 90, 0, - - // front of bottom - 30, 90, 0, - 30, 150, 30, - 30, 90, 30, - 30, 90, 0, - 30, 150, 0, - 30, 150, 30, - - // bottom - 0, 150, 0, - 0, 150, 30, - 30, 150, 30, - 0, 150, 0, - 30, 150, 30, - 30, 150, 0, - - // left side - 0, 0, 0, - 0, 0, 30, - 0, 150, 30, - 0, 0, 0, - 0, 150, 30, - 0, 150, 0, - ]; - - const texcoords = [ - // left column front - 0.22, 0.19, - 0.22, 0.79, - 0.34, 0.19, - 0.22, 0.79, - 0.34, 0.79, - 0.34, 0.19, - - // top rung front - 0.34, 0.19, - 0.34, 0.31, - 0.62, 0.19, - 0.34, 0.31, - 0.62, 0.31, - 0.62, 0.19, - - // middle rung front - 0.34, 0.43, - 0.34, 0.55, - 0.49, 0.43, - 0.34, 0.55, - 0.49, 0.55, - 0.49, 0.43, - - // left column back - 0, 0, - 1, 0, - 0, 1, - 0, 1, - 1, 0, - 1, 1, - - // top rung back - 0, 0, - 1, 0, - 0, 1, - 0, 1, - 1, 0, - 1, 1, - - // middle rung back - 0, 0, - 1, 0, - 0, 1, - 0, 1, - 1, 0, - 1, 1, - - // top - 0, 0, - 1, 0, - 1, 1, - 0, 0, - 1, 1, - 0, 1, - - // top rung front - 0, 0, - 1, 0, - 1, 1, - 0, 0, - 1, 1, - 0, 1, - - // under top rung - 0, 0, - 0, 1, - 1, 1, - 0, 0, - 1, 1, - 1, 0, - - // between top rung and middle - 0, 0, - 1, 1, - 0, 1, - 0, 0, - 1, 0, - 1, 1, - - // top of middle rung - 0, 0, - 1, 1, - 0, 1, - 0, 0, - 1, 0, - 1, 1, - - // front of middle rung - 0, 0, - 1, 1, - 0, 1, - 0, 0, - 1, 0, - 1, 1, - - // bottom of middle rung. - 0, 0, - 0, 1, - 1, 1, - 0, 0, - 1, 1, - 1, 0, - - // front of bottom - 0, 0, - 1, 1, - 0, 1, - 0, 0, - 1, 0, - 1, 1, - - // bottom - 0, 0, - 0, 1, - 1, 1, - 0, 0, - 1, 1, - 1, 0, - - // left side - 0, 0, - 0, 1, - 1, 1, - 0, 0, - 1, 1, - 1, 0, - ]; - - const normals = expandRLEData([ - // left column front - // top rung front - // middle rung front - 18, 0, 0, 1, - - // left column back - // top rung back - // middle rung back - 18, 0, 0, -1, - - // top - 6, 0, 1, 0, - - // top rung front - 6, 1, 0, 0, - - // under top rung - 6, 0, -1, 0, - - // between top rung and middle - 6, 1, 0, 0, - - // top of middle rung - 6, 0, 1, 0, - - // front of middle rung - 6, 1, 0, 0, - - // bottom of middle rung. - 6, 0, -1, 0, - - // front of bottom - 6, 1, 0, 0, - - // bottom - 6, 0, -1, 0, - - // left side - 6, -1, 0, 0, - ]); - - const colors = expandRLEData([ + // front of middle rung + 67, 60, 0, 67, 90, 30, 67, 60, 30, 67, 60, 0, 67, 90, 0, 67, 90, 30, + + // bottom of middle rung. + 30, 90, 0, 30, 90, 30, 67, 90, 30, 30, 90, 0, 67, 90, 30, 67, 90, 0, + + // front of bottom + 30, 90, 0, 30, 150, 30, 30, 90, 30, 30, 90, 0, 30, 150, 0, 30, 150, 30, + + // bottom + 0, 150, 0, 0, 150, 30, 30, 150, 30, 0, 150, 0, 30, 150, 30, 30, 150, 0, + + // left side + 0, 0, 0, 0, 0, 30, 0, 150, 30, 0, 0, 0, 0, 150, 30, 0, 150, 0, + ] + + const texcoords = [ + // left column front + 0.22, 0.19, 0.22, 0.79, 0.34, 0.19, 0.22, 0.79, 0.34, 0.79, 0.34, 0.19, + + // top rung front + 0.34, 0.19, 0.34, 0.31, 0.62, 0.19, 0.34, 0.31, 0.62, 0.31, 0.62, 0.19, + + // middle rung front + 0.34, 0.43, 0.34, 0.55, 0.49, 0.43, 0.34, 0.55, 0.49, 0.55, 0.49, 0.43, + + // left column back + 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, + + // top rung back + 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, + + // middle rung back + 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, + + // top + 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, + + // top rung front + 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, + + // under top rung + 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, + + // between top rung and middle + 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, + + // top of middle rung + 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, + + // front of middle rung + 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, + + // bottom of middle rung. + 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, + + // front of bottom + 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, + + // bottom + 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, + + // left side + 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, + ] + + const normals = expandRLEData([ // left column front // top rung front // middle rung front - 18, 200, 70, 120, + 18, 0, 0, 1, // left column back // top rung back // middle rung back - 18, 80, 70, 200, + 18, 0, 0, -1, // top - 6, 70, 200, 210, + 6, 0, 1, 0, // top rung front - 6, 200, 200, 70, + 6, 1, 0, 0, // under top rung - 6, 210, 100, 70, + 6, 0, -1, 0, // between top rung and middle - 6, 210, 160, 70, + 6, 1, 0, 0, // top of middle rung - 6, 70, 180, 210, + 6, 0, 1, 0, // front of middle rung - 6, 100, 70, 210, + 6, 1, 0, 0, // bottom of middle rung. - 6, 76, 210, 100, + 6, 0, -1, 0, // front of bottom - 6, 140, 210, 80, + 6, 1, 0, 0, // bottom - 6, 90, 130, 110, + 6, 0, -1, 0, // left side - 6, 160, 160, 220, - ], [255]); + 6, -1, 0, 0, + ]) + + const colors = expandRLEData( + [ + // left column front + // top rung front + // middle rung front + 18, 200, 70, 120, + + // left column back + // top rung back + // middle rung back + 18, 80, 70, 200, - const numVerts = positions.length / 3; + // top + 6, 70, 200, 210, - const arrays = { - position: createAugmentedTypedArray(3, numVerts), - texcoord: createAugmentedTypedArray(2, numVerts), - normal: createAugmentedTypedArray(3, numVerts), - color: createAugmentedTypedArray(4, numVerts, Uint8Array), - indices: createAugmentedTypedArray(3, numVerts / 3, Uint16Array), - }; + // top rung front + 6, 200, 200, 70, - arrays.position.push(positions); - arrays.texcoord.push(texcoords); - arrays.normal.push(normals); - arrays.color.push(colors); + // under top rung + 6, 210, 100, 70, - for (let ii = 0; ii < numVerts; ++ii) { - arrays.indices.push(ii); - } + // between top rung and middle + 6, 210, 160, 70, - return arrays; + // top of middle rung + 6, 70, 180, 210, + + // front of middle rung + 6, 100, 70, 210, + + // bottom of middle rung. + 6, 76, 210, 100, + + // front of bottom + 6, 140, 210, 80, + + // bottom + 6, 90, 130, 110, + + // left side + 6, 160, 160, 220, + ], + [255] + ) + + const numVerts = positions.length / 3 + + const arrays = { + position: createAugmentedTypedArray(3, numVerts), + texcoord: createAugmentedTypedArray(2, numVerts), + normal: createAugmentedTypedArray(3, numVerts), + color: createAugmentedTypedArray(4, numVerts, Uint8Array), + indices: createAugmentedTypedArray(3, numVerts / 3, Uint16Array), + } + + arrays.position.push(positions) + arrays.texcoord.push(texcoords) + arrays.normal.push(normals) + arrays.color.push(colors) + + for (let ii = 0; ii < numVerts; ++ii) { + arrays.indices.push(ii) + } + + return arrays } /** @@ -4119,96 +4180,103 @@ function create3DFVertices() { * @return {Object.} The created vertices. * @memberOf module:twgl/primitives */ - function createCrescentVertices( +function createCrescentVertices( verticalRadius, outerRadius, innerRadius, thickness, subdivisionsDown, startOffset, - endOffset) { - if (subdivisionsDown <= 0) { - throw new Error('subdivisionDown must be > 0'); - } - - startOffset = startOffset || 0; - endOffset = endOffset || 1; - - const subdivisionsThick = 2; - - const offsetRange = endOffset - startOffset; - const numVertices = (subdivisionsDown + 1) * 2 * (2 + subdivisionsThick); - const positions = createAugmentedTypedArray(3, numVertices); - const normals = createAugmentedTypedArray(3, numVertices); - const texcoords = createAugmentedTypedArray(2, numVertices); - - function lerp(a, b, s) { - return a + (b - a) * s; - } - - function createArc(arcRadius, x, normalMult, normalAdd, uMult, uAdd) { - for (let z = 0; z <= subdivisionsDown; z++) { - const uBack = x / (subdivisionsThick - 1); - const v = z / subdivisionsDown; - const xBack = (uBack - 0.5) * 2; - const angle = (startOffset + (v * offsetRange)) * Math.PI; - const s = Math.sin(angle); - const c = Math.cos(angle); - const radius = lerp(verticalRadius, arcRadius, s); - const px = xBack * thickness; - const py = c * verticalRadius; - const pz = s * radius; - positions.push(px, py, pz); - const n = add(multiply$1([0, s, c], normalMult), normalAdd); - normals.push(n); - texcoords.push(uBack * uMult + uAdd, v); - } - } - - // Generate the individual vertices in our vertex buffer. - for (let x = 0; x < subdivisionsThick; x++) { - const uBack = (x / (subdivisionsThick - 1) - 0.5) * 2; - createArc(outerRadius, x, [1, 1, 1], [0, 0, 0], 1, 0); - createArc(outerRadius, x, [0, 0, 0], [uBack, 0, 0], 0, 0); - createArc(innerRadius, x, [1, 1, 1], [0, 0, 0], 1, 0); - createArc(innerRadius, x, [0, 0, 0], [uBack, 0, 0], 0, 1); - } - - // Do outer surface. - const indices = createAugmentedTypedArray(3, (subdivisionsDown * 2) * (2 + subdivisionsThick), Uint16Array); - - function createSurface(leftArcOffset, rightArcOffset) { - for (let z = 0; z < subdivisionsDown; ++z) { - // Make triangle 1 of quad. - indices.push( - leftArcOffset + z + 0, - leftArcOffset + z + 1, - rightArcOffset + z + 0); - - // Make triangle 2 of quad. - indices.push( - leftArcOffset + z + 1, - rightArcOffset + z + 1, - rightArcOffset + z + 0); - } - } - - const numVerticesDown = subdivisionsDown + 1; - // front - createSurface(numVerticesDown * 0, numVerticesDown * 4); - // right - createSurface(numVerticesDown * 5, numVerticesDown * 7); - // back - createSurface(numVerticesDown * 6, numVerticesDown * 2); - // left - createSurface(numVerticesDown * 3, numVerticesDown * 1); - - return { - position: positions, - normal: normals, - texcoord: texcoords, - indices: indices, - }; + endOffset +) { + if (subdivisionsDown <= 0) { + throw new Error('subdivisionDown must be > 0') + } + + startOffset = startOffset || 0 + endOffset = endOffset || 1 + + const subdivisionsThick = 2 + + const offsetRange = endOffset - startOffset + const numVertices = (subdivisionsDown + 1) * 2 * (2 + subdivisionsThick) + const positions = createAugmentedTypedArray(3, numVertices) + const normals = createAugmentedTypedArray(3, numVertices) + const texcoords = createAugmentedTypedArray(2, numVertices) + + function lerp(a, b, s) { + return a + (b - a) * s + } + + function createArc(arcRadius, x, normalMult, normalAdd, uMult, uAdd) { + for (let z = 0; z <= subdivisionsDown; z++) { + const uBack = x / (subdivisionsThick - 1) + const v = z / subdivisionsDown + const xBack = (uBack - 0.5) * 2 + const angle = (startOffset + v * offsetRange) * Math.PI + const s = Math.sin(angle) + const c = Math.cos(angle) + const radius = lerp(verticalRadius, arcRadius, s) + const px = xBack * thickness + const py = c * verticalRadius + const pz = s * radius + positions.push(px, py, pz) + const n = add(multiply$1([0, s, c], normalMult), normalAdd) + normals.push(n) + texcoords.push(uBack * uMult + uAdd, v) + } + } + + // Generate the individual vertices in our vertex buffer. + for (let x = 0; x < subdivisionsThick; x++) { + const uBack = (x / (subdivisionsThick - 1) - 0.5) * 2 + createArc(outerRadius, x, [1, 1, 1], [0, 0, 0], 1, 0) + createArc(outerRadius, x, [0, 0, 0], [uBack, 0, 0], 0, 0) + createArc(innerRadius, x, [1, 1, 1], [0, 0, 0], 1, 0) + createArc(innerRadius, x, [0, 0, 0], [uBack, 0, 0], 0, 1) + } + + // Do outer surface. + const indices = createAugmentedTypedArray( + 3, + subdivisionsDown * 2 * (2 + subdivisionsThick), + Uint16Array + ) + + function createSurface(leftArcOffset, rightArcOffset) { + for (let z = 0; z < subdivisionsDown; ++z) { + // Make triangle 1 of quad. + indices.push( + leftArcOffset + z + 0, + leftArcOffset + z + 1, + rightArcOffset + z + 0 + ) + + // Make triangle 2 of quad. + indices.push( + leftArcOffset + z + 1, + rightArcOffset + z + 1, + rightArcOffset + z + 0 + ) + } + } + + const numVerticesDown = subdivisionsDown + 1 + // front + createSurface(numVerticesDown * 0, numVerticesDown * 4) + // right + createSurface(numVerticesDown * 5, numVerticesDown * 7) + // back + createSurface(numVerticesDown * 6, numVerticesDown * 2) + // left + createSurface(numVerticesDown * 3, numVerticesDown * 1) + + return { + position: positions, + normal: normals, + texcoord: texcoords, + indices: indices, + } } /** @@ -4227,50 +4295,52 @@ function create3DFVertices() { * @function createCylinderBufferInfo */ - /** - * Creates cylinder buffers. The cylinder will be created around the origin - * along the y-axis. - * - * @param {WebGLRenderingContext} gl The WebGLRenderingContext. - * @param {number} radius Radius of cylinder. - * @param {number} height Height of cylinder. - * @param {number} radialSubdivisions The number of subdivisions around the cylinder. - * @param {number} verticalSubdivisions The number of subdivisions down the cylinder. - * @param {boolean} [topCap] Create top cap. Default = true. - * @param {boolean} [bottomCap] Create bottom cap. Default = true. - * @return {Object.} The created buffers. - * @memberOf module:twgl/primitives - * @function createCylinderBuffers - */ - - /** - * Creates cylinder vertices. The cylinder will be created around the origin - * along the y-axis. - * - * @param {number} radius Radius of cylinder. - * @param {number} height Height of cylinder. - * @param {number} radialSubdivisions The number of subdivisions around the cylinder. - * @param {number} verticalSubdivisions The number of subdivisions down the cylinder. - * @param {boolean} [topCap] Create top cap. Default = true. - * @param {boolean} [bottomCap] Create bottom cap. Default = true. - * @return {Object.} The created vertices. - * @memberOf module:twgl/primitives - */ +/** + * Creates cylinder buffers. The cylinder will be created around the origin + * along the y-axis. + * + * @param {WebGLRenderingContext} gl The WebGLRenderingContext. + * @param {number} radius Radius of cylinder. + * @param {number} height Height of cylinder. + * @param {number} radialSubdivisions The number of subdivisions around the cylinder. + * @param {number} verticalSubdivisions The number of subdivisions down the cylinder. + * @param {boolean} [topCap] Create top cap. Default = true. + * @param {boolean} [bottomCap] Create bottom cap. Default = true. + * @return {Object.} The created buffers. + * @memberOf module:twgl/primitives + * @function createCylinderBuffers + */ + +/** + * Creates cylinder vertices. The cylinder will be created around the origin + * along the y-axis. + * + * @param {number} radius Radius of cylinder. + * @param {number} height Height of cylinder. + * @param {number} radialSubdivisions The number of subdivisions around the cylinder. + * @param {number} verticalSubdivisions The number of subdivisions down the cylinder. + * @param {boolean} [topCap] Create top cap. Default = true. + * @param {boolean} [bottomCap] Create bottom cap. Default = true. + * @return {Object.} The created vertices. + * @memberOf module:twgl/primitives + */ function createCylinderVertices( radius, height, radialSubdivisions, verticalSubdivisions, topCap, - bottomCap) { - return createTruncatedConeVertices( - radius, - radius, - height, - radialSubdivisions, - verticalSubdivisions, - topCap, - bottomCap); + bottomCap +) { + return createTruncatedConeVertices( + radius, + radius, + height, + radialSubdivisions, + verticalSubdivisions, + topCap, + bottomCap + ) } /** @@ -4321,70 +4391,80 @@ function createTorusVertices( radialSubdivisions, bodySubdivisions, startAngle, - endAngle) { - if (radialSubdivisions < 3) { - throw new Error('radialSubdivisions must be 3 or greater'); - } - - if (bodySubdivisions < 3) { - throw new Error('verticalSubdivisions must be 3 or greater'); - } - - startAngle = startAngle || 0; - endAngle = endAngle || Math.PI * 2; - const range = endAngle - startAngle; - - const radialParts = radialSubdivisions + 1; - const bodyParts = bodySubdivisions + 1; - const numVertices = radialParts * bodyParts; - const positions = createAugmentedTypedArray(3, numVertices); - const normals = createAugmentedTypedArray(3, numVertices); - const texcoords = createAugmentedTypedArray(2, numVertices); - const indices = createAugmentedTypedArray(3, (radialSubdivisions) * (bodySubdivisions) * 2, Uint16Array); - - for (let slice = 0; slice < bodyParts; ++slice) { - const v = slice / bodySubdivisions; - const sliceAngle = v * Math.PI * 2; - const sliceSin = Math.sin(sliceAngle); - const ringRadius = radius + sliceSin * thickness; - const ny = Math.cos(sliceAngle); - const y = ny * thickness; - for (let ring = 0; ring < radialParts; ++ring) { - const u = ring / radialSubdivisions; - const ringAngle = startAngle + u * range; - const xSin = Math.sin(ringAngle); - const zCos = Math.cos(ringAngle); - const x = xSin * ringRadius; - const z = zCos * ringRadius; - const nx = xSin * sliceSin; - const nz = zCos * sliceSin; - positions.push(x, y, z); - normals.push(nx, ny, nz); - texcoords.push(u, 1 - v); - } - } - - for (let slice = 0; slice < bodySubdivisions; ++slice) { // eslint-disable-line - for (let ring = 0; ring < radialSubdivisions; ++ring) { // eslint-disable-line - const nextRingIndex = 1 + ring; - const nextSliceIndex = 1 + slice; - indices.push(radialParts * slice + ring, - radialParts * nextSliceIndex + ring, - radialParts * slice + nextRingIndex); - indices.push(radialParts * nextSliceIndex + ring, - radialParts * nextSliceIndex + nextRingIndex, - radialParts * slice + nextRingIndex); - } - } - - return { - position: positions, - normal: normals, - texcoord: texcoords, - indices: indices, - }; -} + endAngle +) { + if (radialSubdivisions < 3) { + throw new Error('radialSubdivisions must be 3 or greater') + } + if (bodySubdivisions < 3) { + throw new Error('verticalSubdivisions must be 3 or greater') + } + + startAngle = startAngle || 0 + endAngle = endAngle || Math.PI * 2 + const range = endAngle - startAngle + + const radialParts = radialSubdivisions + 1 + const bodyParts = bodySubdivisions + 1 + const numVertices = radialParts * bodyParts + const positions = createAugmentedTypedArray(3, numVertices) + const normals = createAugmentedTypedArray(3, numVertices) + const texcoords = createAugmentedTypedArray(2, numVertices) + const indices = createAugmentedTypedArray( + 3, + radialSubdivisions * bodySubdivisions * 2, + Uint16Array + ) + + for (let slice = 0; slice < bodyParts; ++slice) { + const v = slice / bodySubdivisions + const sliceAngle = v * Math.PI * 2 + const sliceSin = Math.sin(sliceAngle) + const ringRadius = radius + sliceSin * thickness + const ny = Math.cos(sliceAngle) + const y = ny * thickness + for (let ring = 0; ring < radialParts; ++ring) { + const u = ring / radialSubdivisions + const ringAngle = startAngle + u * range + const xSin = Math.sin(ringAngle) + const zCos = Math.cos(ringAngle) + const x = xSin * ringRadius + const z = zCos * ringRadius + const nx = xSin * sliceSin + const nz = zCos * sliceSin + positions.push(x, y, z) + normals.push(nx, ny, nz) + texcoords.push(u, 1 - v) + } + } + + for (let slice = 0; slice < bodySubdivisions; ++slice) { + // eslint-disable-line + for (let ring = 0; ring < radialSubdivisions; ++ring) { + // eslint-disable-line + const nextRingIndex = 1 + ring + const nextSliceIndex = 1 + slice + indices.push( + radialParts * slice + ring, + radialParts * nextSliceIndex + ring, + radialParts * slice + nextRingIndex + ) + indices.push( + radialParts * nextSliceIndex + ring, + radialParts * nextSliceIndex + nextRingIndex, + radialParts * slice + nextRingIndex + ) + } + } + + return { + position: positions, + normal: normals, + texcoord: texcoords, + indices: indices, + } +} /** * Creates a disc BufferInfo. The disc will be in the xz plane, centered at @@ -4472,64 +4552,70 @@ function createDiscVertices( divisions, stacks, innerRadius, - stackPower) { - if (divisions < 3) { - throw new Error('divisions must be at least 3'); - } - - stacks = stacks ? stacks : 1; - stackPower = stackPower ? stackPower : 1; - innerRadius = innerRadius ? innerRadius : 0; - - // Note: We don't share the center vertex because that would - // mess up texture coordinates. - const numVertices = (divisions + 1) * (stacks + 1); - - const positions = createAugmentedTypedArray(3, numVertices); - const normals = createAugmentedTypedArray(3, numVertices); - const texcoords = createAugmentedTypedArray(2, numVertices); - const indices = createAugmentedTypedArray(3, stacks * divisions * 2, Uint16Array); - - let firstIndex = 0; - const radiusSpan = radius - innerRadius; - const pointsPerStack = divisions + 1; - - // Build the disk one stack at a time. - for (let stack = 0; stack <= stacks; ++stack) { - const stackRadius = innerRadius + radiusSpan * Math.pow(stack / stacks, stackPower); - - for (let i = 0; i <= divisions; ++i) { - const theta = 2.0 * Math.PI * i / divisions; - const x = stackRadius * Math.cos(theta); - const z = stackRadius * Math.sin(theta); - - positions.push(x, 0, z); - normals.push(0, 1, 0); - texcoords.push(1 - (i / divisions), stack / stacks); - if (stack > 0 && i !== divisions) { - // a, b, c and d are the indices of the vertices of a quad. unless - // the current stack is the one closest to the center, in which case - // the vertices a and b connect to the center vertex. - const a = firstIndex + (i + 1); - const b = firstIndex + i; - const c = firstIndex + i - pointsPerStack; - const d = firstIndex + (i + 1) - pointsPerStack; - - // Make a quad of the vertices a, b, c, d. - indices.push(a, b, c); - indices.push(a, c, d); - } - } - - firstIndex += divisions + 1; - } - - return { - position: positions, - normal: normals, - texcoord: texcoords, - indices: indices, - }; + stackPower +) { + if (divisions < 3) { + throw new Error('divisions must be at least 3') + } + + stacks = stacks ? stacks : 1 + stackPower = stackPower ? stackPower : 1 + innerRadius = innerRadius ? innerRadius : 0 + + // Note: We don't share the center vertex because that would + // mess up texture coordinates. + const numVertices = (divisions + 1) * (stacks + 1) + + const positions = createAugmentedTypedArray(3, numVertices) + const normals = createAugmentedTypedArray(3, numVertices) + const texcoords = createAugmentedTypedArray(2, numVertices) + const indices = createAugmentedTypedArray( + 3, + stacks * divisions * 2, + Uint16Array + ) + + let firstIndex = 0 + const radiusSpan = radius - innerRadius + const pointsPerStack = divisions + 1 + + // Build the disk one stack at a time. + for (let stack = 0; stack <= stacks; ++stack) { + const stackRadius = + innerRadius + radiusSpan * Math.pow(stack / stacks, stackPower) + + for (let i = 0; i <= divisions; ++i) { + const theta = (2.0 * Math.PI * i) / divisions + const x = stackRadius * Math.cos(theta) + const z = stackRadius * Math.sin(theta) + + positions.push(x, 0, z) + normals.push(0, 1, 0) + texcoords.push(1 - i / divisions, stack / stacks) + if (stack > 0 && i !== divisions) { + // a, b, c and d are the indices of the vertices of a quad. unless + // the current stack is the one closest to the center, in which case + // the vertices a and b connect to the center vertex. + const a = firstIndex + (i + 1) + const b = firstIndex + i + const c = firstIndex + i - pointsPerStack + const d = firstIndex + (i + 1) - pointsPerStack + + // Make a quad of the vertices a, b, c, d. + indices.push(a, b, c) + indices.push(a, c, d) + } + } + + firstIndex += divisions + 1 + } + + return { + position: positions, + normal: normals, + texcoord: texcoords, + indices: indices, + } } /** @@ -4539,7 +4625,7 @@ function createDiscVertices( * @private */ function randInt(range) { - return Math.random() * range | 0; + return (Math.random() * range) | 0 } /** @@ -4569,30 +4655,33 @@ function randInt(range) { * @memberOf module:twgl/primitives */ function makeRandomVertexColors(vertices, options) { - options = options || {}; - const numElements = vertices.position.numElements; - const vColors = createAugmentedTypedArray(4, numElements, Uint8Array); - const rand = options.rand || function(ndx, channel) { - return channel < 3 ? randInt(256) : 255; - }; - vertices.color = vColors; - if (vertices.indices) { - // just make random colors if index - for (let ii = 0; ii < numElements; ++ii) { - vColors.push(rand(ii, 0), rand(ii, 1), rand(ii, 2), rand(ii, 3)); - } - } else { - // make random colors per triangle - const numVertsPerColor = options.vertsPerColor || 3; - const numSets = numElements / numVertsPerColor; - for (let ii = 0; ii < numSets; ++ii) { // eslint-disable-line - const color = [rand(ii, 0), rand(ii, 1), rand(ii, 2), rand(ii, 3)]; - for (let jj = 0; jj < numVertsPerColor; ++jj) { - vColors.push(color); - } - } - } - return vertices; + options = options || {} + const numElements = vertices.position.numElements + const vColors = createAugmentedTypedArray(4, numElements, Uint8Array) + const rand = + options.rand || + function (ndx, channel) { + return channel < 3 ? randInt(256) : 255 + } + vertices.color = vColors + if (vertices.indices) { + // just make random colors if index + for (let ii = 0; ii < numElements; ++ii) { + vColors.push(rand(ii, 0), rand(ii, 1), rand(ii, 2), rand(ii, 3)) + } + } else { + // make random colors per triangle + const numVertsPerColor = options.vertsPerColor || 3 + const numSets = numElements / numVertsPerColor + for (let ii = 0; ii < numSets; ++ii) { + // eslint-disable-line + const color = [rand(ii, 0), rand(ii, 1), rand(ii, 2), rand(ii, 3)] + for (let jj = 0; jj < numVertsPerColor; ++jj) { + vColors.push(color) + } + } + } + return vertices } /** @@ -4601,10 +4690,10 @@ function makeRandomVertexColors(vertices, options) { * @private */ function createBufferFunc(fn) { - return function(gl) { - const arrays = fn.apply(this, Array.prototype.slice.call(arguments, 1)); - return createBuffersFromArrays(gl, arrays); - }; + return function (gl) { + const arrays = fn.apply(this, Array.prototype.slice.call(arguments, 1)) + return createBuffersFromArrays(gl, arrays) + } } /** @@ -4613,23 +4702,23 @@ function createBufferFunc(fn) { * @private */ function createBufferInfoFunc(fn) { - return function(gl) { - const arrays = fn.apply(null, Array.prototype.slice.call(arguments, 1)); - return createBufferInfoFromArrays(gl, arrays); - }; + return function (gl) { + const arrays = fn.apply(null, Array.prototype.slice.call(arguments, 1)) + return createBufferInfoFromArrays(gl, arrays) + } } const arraySpecPropertyNames = [ - "numComponents", - "size", - "type", - "normalize", - "stride", - "offset", - "attrib", - "name", - "attribName", -]; + 'numComponents', + 'size', + 'type', + 'normalize', + 'stride', + 'offset', + 'attrib', + 'name', + 'attribName', +] /** * Copy elements from one array to another @@ -4641,11 +4730,11 @@ const arraySpecPropertyNames = [ * @private */ function copyElements(src, dst, dstNdx, offset) { - offset = offset || 0; - const length = src.length; - for (let ii = 0; ii < length; ++ii) { - dst[dstNdx + ii] = src[ii] + offset; - } + offset = offset || 0 + const length = src.length + for (let ii = 0; ii < length; ++ii) { + dst[dstNdx + ii] = src[ii] + offset + } } /** @@ -4657,21 +4746,21 @@ function copyElements(src, dst, dstNdx, offset) { * @private */ function createArrayOfSameType(srcArray, length) { - const arraySrc = getArray(srcArray); - const newArray = new arraySrc.constructor(length); - let newArraySpec = newArray; - // If it appears to have been augmented make new one augmented - if (arraySrc.numComponents && arraySrc.numElements) { - augmentTypedArray(newArray, arraySrc.numComponents); - } - // If it was a full spec make new one a full spec - if (srcArray.data) { - newArraySpec = { - data: newArray, - }; - copyNamedProperties(arraySpecPropertyNames, srcArray, newArraySpec); - } - return newArraySpec; + const arraySrc = getArray(srcArray) + const newArray = new arraySrc.constructor(length) + let newArraySpec = newArray + // If it appears to have been augmented make new one augmented + if (arraySrc.numComponents && arraySrc.numElements) { + augmentTypedArray(newArray, arraySrc.numComponents) + } + // If it was a full spec make new one a full spec + if (srcArray.data) { + newArraySpec = { + data: newArray, + } + copyNamedProperties(arraySpecPropertyNames, srcArray, newArraySpec) + } + return newArraySpec } /** @@ -4700,74 +4789,75 @@ function createArrayOfSameType(srcArray, length) { * @memberOf module:twgl/primitives */ function concatVertices(arrayOfArrays) { - const names = {}; - let baseName; - // get names of all arrays. - // and numElements for each set of vertices - for (let ii = 0; ii < arrayOfArrays.length; ++ii) { - const arrays = arrayOfArrays[ii]; - Object.keys(arrays).forEach(function(name) { // eslint-disable-line - if (!names[name]) { - names[name] = []; - } - if (!baseName && name !== 'indices') { - baseName = name; - } - const arrayInfo = arrays[name]; - const numComponents = getNumComponents(arrayInfo, name); - const array = getArray(arrayInfo); - const numElements = array.length / numComponents; - names[name].push(numElements); - }); - } - - // compute length of combined array - // and return one for reference - function getLengthOfCombinedArrays(name) { - let length = 0; - let arraySpec; + const names = {} + let baseName + // get names of all arrays. + // and numElements for each set of vertices for (let ii = 0; ii < arrayOfArrays.length; ++ii) { - const arrays = arrayOfArrays[ii]; - const arrayInfo = arrays[name]; - const array = getArray(arrayInfo); - length += array.length; - if (!arraySpec || arrayInfo.data) { - arraySpec = arrayInfo; - } + const arrays = arrayOfArrays[ii] + Object.keys(arrays).forEach(function (name) { + // eslint-disable-line + if (!names[name]) { + names[name] = [] + } + if (!baseName && name !== 'indices') { + baseName = name + } + const arrayInfo = arrays[name] + const numComponents = getNumComponents(arrayInfo, name) + const array = getArray(arrayInfo) + const numElements = array.length / numComponents + names[name].push(numElements) + }) } - return { - length: length, - spec: arraySpec, - }; - } - - function copyArraysToNewArray(name, base, newArray) { - let baseIndex = 0; - let offset = 0; - for (let ii = 0; ii < arrayOfArrays.length; ++ii) { - const arrays = arrayOfArrays[ii]; - const arrayInfo = arrays[name]; - const array = getArray(arrayInfo); - if (name === 'indices') { - copyElements(array, newArray, offset, baseIndex); - baseIndex += base[ii]; - } else { - copyElements(array, newArray, offset); - } - offset += array.length; + + // compute length of combined array + // and return one for reference + function getLengthOfCombinedArrays(name) { + let length = 0 + let arraySpec + for (let ii = 0; ii < arrayOfArrays.length; ++ii) { + const arrays = arrayOfArrays[ii] + const arrayInfo = arrays[name] + const array = getArray(arrayInfo) + length += array.length + if (!arraySpec || arrayInfo.data) { + arraySpec = arrayInfo + } + } + return { + length: length, + spec: arraySpec, + } } - } - const base = names[baseName]; + function copyArraysToNewArray(name, base, newArray) { + let baseIndex = 0 + let offset = 0 + for (let ii = 0; ii < arrayOfArrays.length; ++ii) { + const arrays = arrayOfArrays[ii] + const arrayInfo = arrays[name] + const array = getArray(arrayInfo) + if (name === 'indices') { + copyElements(array, newArray, offset, baseIndex) + baseIndex += base[ii] + } else { + copyElements(array, newArray, offset) + } + offset += array.length + } + } - const newArrays = {}; - Object.keys(names).forEach(function(name) { - const info = getLengthOfCombinedArrays(name); - const newArraySpec = createArrayOfSameType(info.spec, info.length); - copyArraysToNewArray(name, base, getArray(newArraySpec)); - newArrays[name] = newArraySpec; - }); - return newArrays; + const base = names[baseName] + + const newArrays = {} + Object.keys(names).forEach(function (name) { + const info = getLengthOfCombinedArrays(name) + const newArraySpec = createArrayOfSameType(info.spec, info.length) + copyArraysToNewArray(name, base, getArray(newArraySpec)) + newArrays[name] = newArraySpec + }) + return newArrays } /** @@ -4781,89 +4871,91 @@ function concatVertices(arrayOfArrays) { * @memberOf module:twgl/primitives */ function duplicateVertices(arrays) { - const newArrays = {}; - Object.keys(arrays).forEach(function(name) { - const arraySpec = arrays[name]; - const srcArray = getArray(arraySpec); - const newArraySpec = createArrayOfSameType(arraySpec, srcArray.length); - copyElements(srcArray, getArray(newArraySpec), 0); - newArrays[name] = newArraySpec; - }); - return newArrays; -} - -const create3DFBufferInfo = createBufferInfoFunc(create3DFVertices); -const create3DFBuffers = createBufferFunc(create3DFVertices); -const createCubeBufferInfo = createBufferInfoFunc(createCubeVertices); -const createCubeBuffers = createBufferFunc(createCubeVertices); -const createPlaneBufferInfo = createBufferInfoFunc(createPlaneVertices); -const createPlaneBuffers = createBufferFunc(createPlaneVertices); -const createSphereBufferInfo = createBufferInfoFunc(createSphereVertices); -const createSphereBuffers = createBufferFunc(createSphereVertices); -const createTruncatedConeBufferInfo = createBufferInfoFunc(createTruncatedConeVertices); -const createTruncatedConeBuffers = createBufferFunc(createTruncatedConeVertices); -const createXYQuadBufferInfo = createBufferInfoFunc(createXYQuadVertices); -const createXYQuadBuffers = createBufferFunc(createXYQuadVertices); -const createCrescentBufferInfo = createBufferInfoFunc(createCrescentVertices); -const createCrescentBuffers = createBufferFunc(createCrescentVertices); -const createCylinderBufferInfo = createBufferInfoFunc(createCylinderVertices); -const createCylinderBuffers = createBufferFunc(createCylinderVertices); -const createTorusBufferInfo = createBufferInfoFunc(createTorusVertices); -const createTorusBuffers = createBufferFunc(createTorusVertices); -const createDiscBufferInfo = createBufferInfoFunc(createDiscVertices); -const createDiscBuffers = createBufferFunc(createDiscVertices); + const newArrays = {} + Object.keys(arrays).forEach(function (name) { + const arraySpec = arrays[name] + const srcArray = getArray(arraySpec) + const newArraySpec = createArrayOfSameType(arraySpec, srcArray.length) + copyElements(srcArray, getArray(newArraySpec), 0) + newArrays[name] = newArraySpec + }) + return newArrays +} + +const create3DFBufferInfo = createBufferInfoFunc(create3DFVertices) +const create3DFBuffers = createBufferFunc(create3DFVertices) +const createCubeBufferInfo = createBufferInfoFunc(createCubeVertices) +const createCubeBuffers = createBufferFunc(createCubeVertices) +const createPlaneBufferInfo = createBufferInfoFunc(createPlaneVertices) +const createPlaneBuffers = createBufferFunc(createPlaneVertices) +const createSphereBufferInfo = createBufferInfoFunc(createSphereVertices) +const createSphereBuffers = createBufferFunc(createSphereVertices) +const createTruncatedConeBufferInfo = createBufferInfoFunc( + createTruncatedConeVertices +) +const createTruncatedConeBuffers = createBufferFunc(createTruncatedConeVertices) +const createXYQuadBufferInfo = createBufferInfoFunc(createXYQuadVertices) +const createXYQuadBuffers = createBufferFunc(createXYQuadVertices) +const createCrescentBufferInfo = createBufferInfoFunc(createCrescentVertices) +const createCrescentBuffers = createBufferFunc(createCrescentVertices) +const createCylinderBufferInfo = createBufferInfoFunc(createCylinderVertices) +const createCylinderBuffers = createBufferFunc(createCylinderVertices) +const createTorusBufferInfo = createBufferInfoFunc(createTorusVertices) +const createTorusBuffers = createBufferFunc(createTorusVertices) +const createDiscBufferInfo = createBufferInfoFunc(createDiscVertices) +const createDiscBuffers = createBufferFunc(createDiscVertices) // these were mis-spelled until 4.12 -const createCresentBufferInfo = createCrescentBufferInfo; -const createCresentBuffers = createCrescentBuffers; -const createCresentVertices = createCrescentVertices; - -var primitives = /*#__PURE__*/Object.freeze({ - __proto__: null, - create3DFBufferInfo: create3DFBufferInfo, - create3DFBuffers: create3DFBuffers, - create3DFVertices: create3DFVertices, - createAugmentedTypedArray: createAugmentedTypedArray, - createCubeBufferInfo: createCubeBufferInfo, - createCubeBuffers: createCubeBuffers, - createCubeVertices: createCubeVertices, - createPlaneBufferInfo: createPlaneBufferInfo, - createPlaneBuffers: createPlaneBuffers, - createPlaneVertices: createPlaneVertices, - createSphereBufferInfo: createSphereBufferInfo, - createSphereBuffers: createSphereBuffers, - createSphereVertices: createSphereVertices, - createTruncatedConeBufferInfo: createTruncatedConeBufferInfo, - createTruncatedConeBuffers: createTruncatedConeBuffers, - createTruncatedConeVertices: createTruncatedConeVertices, - createXYQuadBufferInfo: createXYQuadBufferInfo, - createXYQuadBuffers: createXYQuadBuffers, - createXYQuadVertices: createXYQuadVertices, - createCresentBufferInfo: createCresentBufferInfo, - createCresentBuffers: createCresentBuffers, - createCresentVertices: createCresentVertices, - createCrescentBufferInfo: createCrescentBufferInfo, - createCrescentBuffers: createCrescentBuffers, - createCrescentVertices: createCrescentVertices, - createCylinderBufferInfo: createCylinderBufferInfo, - createCylinderBuffers: createCylinderBuffers, - createCylinderVertices: createCylinderVertices, - createTorusBufferInfo: createTorusBufferInfo, - createTorusBuffers: createTorusBuffers, - createTorusVertices: createTorusVertices, - createDiscBufferInfo: createDiscBufferInfo, - createDiscBuffers: createDiscBuffers, - createDiscVertices: createDiscVertices, - deindexVertices: deindexVertices, - flattenNormals: flattenNormals, - makeRandomVertexColors: makeRandomVertexColors, - reorientDirections: reorientDirections, - reorientNormals: reorientNormals, - reorientPositions: reorientPositions, - reorientVertices: reorientVertices, - concatVertices: concatVertices, - duplicateVertices: duplicateVertices -}); +const createCresentBufferInfo = createCrescentBufferInfo +const createCresentBuffers = createCrescentBuffers +const createCresentVertices = createCrescentVertices + +var primitives = /*#__PURE__*/ Object.freeze({ + __proto__: null, + create3DFBufferInfo: create3DFBufferInfo, + create3DFBuffers: create3DFBuffers, + create3DFVertices: create3DFVertices, + createAugmentedTypedArray: createAugmentedTypedArray, + createCubeBufferInfo: createCubeBufferInfo, + createCubeBuffers: createCubeBuffers, + createCubeVertices: createCubeVertices, + createPlaneBufferInfo: createPlaneBufferInfo, + createPlaneBuffers: createPlaneBuffers, + createPlaneVertices: createPlaneVertices, + createSphereBufferInfo: createSphereBufferInfo, + createSphereBuffers: createSphereBuffers, + createSphereVertices: createSphereVertices, + createTruncatedConeBufferInfo: createTruncatedConeBufferInfo, + createTruncatedConeBuffers: createTruncatedConeBuffers, + createTruncatedConeVertices: createTruncatedConeVertices, + createXYQuadBufferInfo: createXYQuadBufferInfo, + createXYQuadBuffers: createXYQuadBuffers, + createXYQuadVertices: createXYQuadVertices, + createCresentBufferInfo: createCresentBufferInfo, + createCresentBuffers: createCresentBuffers, + createCresentVertices: createCresentVertices, + createCrescentBufferInfo: createCrescentBufferInfo, + createCrescentBuffers: createCrescentBuffers, + createCrescentVertices: createCrescentVertices, + createCylinderBufferInfo: createCylinderBufferInfo, + createCylinderBuffers: createCylinderBuffers, + createCylinderVertices: createCylinderVertices, + createTorusBufferInfo: createTorusBufferInfo, + createTorusBuffers: createTorusBuffers, + createTorusVertices: createTorusVertices, + createDiscBufferInfo: createDiscBufferInfo, + createDiscBuffers: createDiscBuffers, + createDiscVertices: createDiscVertices, + deindexVertices: deindexVertices, + flattenNormals: flattenNormals, + makeRandomVertexColors: makeRandomVertexColors, + reorientDirections: reorientDirections, + reorientNormals: reorientNormals, + reorientPositions: reorientPositions, + reorientVertices: reorientVertices, + concatVertices: concatVertices, + duplicateVertices: duplicateVertices, +}) /* * Copyright 2019 Gregg Tavares @@ -4904,11 +4996,11 @@ var primitives = /*#__PURE__*/Object.freeze({ * @memberOf module:twgl */ function isWebGL2(gl) { - // This is the correct check but it's slow - // return gl.getParameter(gl.VERSION).indexOf("WebGL 2.0") === 0; - // This might also be the correct check but I'm assuming it's slow-ish - // return gl instanceof WebGL2RenderingContext; - return !!gl.texStorage2D; + // This is the correct check but it's slow + // return gl.getParameter(gl.VERSION).indexOf("WebGL 2.0") === 0; + // This might also be the correct check but I'm assuming it's slow-ish + // return gl instanceof WebGL2RenderingContext; + return !!gl.texStorage2D } /** @@ -4918,12 +5010,12 @@ function isWebGL2(gl) { * @memberOf module:twgl */ function isWebGL1(gl) { - // This is the correct check but it's slow - // const version = getVersionAsNumber(gl); - // return version <= 1.0 && version > 0.0; // because as of 2016/5 Edge returns 0.96 - // This might also be the correct check but I'm assuming it's slow-ish - // return gl instanceof WebGLRenderingContext; - return !gl.texStorage2D; + // This is the correct check but it's slow + // const version = getVersionAsNumber(gl); + // return version <= 1.0 && version > 0.0; // because as of 2016/5 Edge returns 0.96 + // This might also be the correct check but I'm assuming it's slow-ish + // return gl instanceof WebGLRenderingContext; + return !gl.texStorage2D } /** @@ -4974,35 +5066,38 @@ function isWebGL1(gl) { * @memberOf module:twgl * @function glEnumToString */ -const glEnumToString = (function() { - const haveEnumsForType = {}; - const enums = {}; - - function addEnums(gl) { - const type = gl.constructor.name; - if (!haveEnumsForType[type]) { - for (const key in gl) { - if (typeof gl[key] === 'number') { - const existing = enums[gl[key]]; - enums[gl[key]] = existing ? `${existing} | ${key}` : key; +const glEnumToString = (function () { + const haveEnumsForType = {} + const enums = {} + + function addEnums(gl) { + const type = gl.constructor.name + if (!haveEnumsForType[type]) { + for (const key in gl) { + if (typeof gl[key] === 'number') { + const existing = enums[gl[key]] + enums[gl[key]] = existing ? `${existing} | ${key}` : key + } + } + haveEnumsForType[type] = true } - } - haveEnumsForType[type] = true; } - } - return function glEnumToString(gl, value) { - addEnums(gl); - return enums[value] || (typeof value === 'number' ? `0x${value.toString(16)}` : value); - }; -}()); + return function glEnumToString(gl, value) { + addEnums(gl) + return ( + enums[value] || + (typeof value === 'number' ? `0x${value.toString(16)}` : value) + ) + } +})() -var utils = /*#__PURE__*/Object.freeze({ - __proto__: null, - glEnumToString: glEnumToString, - isWebGL1: isWebGL1, - isWebGL2: isWebGL2 -}); +var utils = /*#__PURE__*/ Object.freeze({ + __proto__: null, + glEnumToString: glEnumToString, + isWebGL1: isWebGL1, + isWebGL2: isWebGL2, +}) /* * Copyright 2019 Gregg Tavares @@ -5026,23 +5121,24 @@ var utils = /*#__PURE__*/Object.freeze({ * DEALINGS IN THE SOFTWARE. */ const defaults$1 = { - textureColor: new Uint8Array([128, 192, 255, 255]), - textureOptions: {}, - crossOrigin: undefined, -}; -const isArrayBuffer = isArrayBuffer$1; + textureColor: new Uint8Array([128, 192, 255, 255]), + textureOptions: {}, + crossOrigin: undefined, +} +const isArrayBuffer = isArrayBuffer$1 // Should we make this on demand? -const getShared2DContext = function() { - let s_ctx; - return function getShared2DContext() { - s_ctx = s_ctx || - ((typeof document !== 'undefined' && document.createElement) - ? document.createElement("canvas").getContext("2d") - : null); - return s_ctx; - }; -}(); +const getShared2DContext = (function () { + let s_ctx + return function getShared2DContext() { + s_ctx = + s_ctx || + (typeof document !== 'undefined' && document.createElement + ? document.createElement('canvas').getContext('2d') + : null) + return s_ctx + } +})() // NOTE: Chrome supports 2D canvas in a Worker (behind flag as of v64 but // not only does Firefox NOT support it but Firefox freezes immediately @@ -5057,22 +5153,22 @@ const getShared2DContext = function() { // as of 2018-01-02 /* PixelFormat */ -const ALPHA = 0x1906; -const RGB = 0x1907; -const RGBA$1 = 0x1908; -const LUMINANCE = 0x1909; -const LUMINANCE_ALPHA = 0x190A; -const DEPTH_COMPONENT$1 = 0x1902; -const DEPTH_STENCIL$1 = 0x84F9; +const ALPHA = 0x1906 +const RGB = 0x1907 +const RGBA$1 = 0x1908 +const LUMINANCE = 0x1909 +const LUMINANCE_ALPHA = 0x190a +const DEPTH_COMPONENT$1 = 0x1902 +const DEPTH_STENCIL$1 = 0x84f9 /* TextureWrapMode */ // const REPEAT = 0x2901; // const MIRRORED_REPEAT = 0x8370; -const CLAMP_TO_EDGE$1 = 0x812f; +const CLAMP_TO_EDGE$1 = 0x812f /* TextureMagFilter */ -const NEAREST = 0x2600; -const LINEAR$1 = 0x2601; +const NEAREST = 0x2600 +const LINEAR$1 = 0x2601 /* TextureMinFilter */ // const NEAREST_MIPMAP_NEAREST = 0x2700; @@ -5081,144 +5177,143 @@ const LINEAR$1 = 0x2601; // const LINEAR_MIPMAP_LINEAR = 0x2703; /* Texture Target */ -const TEXTURE_2D$2 = 0x0de1; -const TEXTURE_CUBE_MAP$1 = 0x8513; -const TEXTURE_3D$1 = 0x806f; -const TEXTURE_2D_ARRAY$1 = 0x8c1a; +const TEXTURE_2D$2 = 0x0de1 +const TEXTURE_CUBE_MAP$1 = 0x8513 +const TEXTURE_3D$1 = 0x806f +const TEXTURE_2D_ARRAY$1 = 0x8c1a /* Cubemap Targets */ -const TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515; -const TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516; -const TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517; -const TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518; -const TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519; -const TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851a; +const TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515 +const TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516 +const TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517 +const TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518 +const TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519 +const TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851a /* Texture Parameters */ -const TEXTURE_MIN_FILTER = 0x2801; -const TEXTURE_MAG_FILTER = 0x2800; -const TEXTURE_WRAP_S = 0x2802; -const TEXTURE_WRAP_T = 0x2803; -const TEXTURE_WRAP_R = 0x8072; -const TEXTURE_MIN_LOD = 0x813a; -const TEXTURE_MAX_LOD = 0x813b; -const TEXTURE_BASE_LEVEL = 0x813c; -const TEXTURE_MAX_LEVEL = 0x813d; - +const TEXTURE_MIN_FILTER = 0x2801 +const TEXTURE_MAG_FILTER = 0x2800 +const TEXTURE_WRAP_S = 0x2802 +const TEXTURE_WRAP_T = 0x2803 +const TEXTURE_WRAP_R = 0x8072 +const TEXTURE_MIN_LOD = 0x813a +const TEXTURE_MAX_LOD = 0x813b +const TEXTURE_BASE_LEVEL = 0x813c +const TEXTURE_MAX_LEVEL = 0x813d /* Pixel store */ -const UNPACK_ALIGNMENT = 0x0cf5; -const UNPACK_ROW_LENGTH = 0x0cf2; -const UNPACK_IMAGE_HEIGHT = 0x806e; -const UNPACK_SKIP_PIXELS = 0x0cf4; -const UNPACK_SKIP_ROWS = 0x0cf3; -const UNPACK_SKIP_IMAGES = 0x806d; -const UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243; -const UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241; -const UNPACK_FLIP_Y_WEBGL = 0x9240; - -const R8 = 0x8229; -const R8_SNORM = 0x8F94; -const R16F = 0x822D; -const R32F = 0x822E; -const R8UI = 0x8232; -const R8I = 0x8231; -const RG16UI = 0x823A; -const RG16I = 0x8239; -const RG32UI = 0x823C; -const RG32I = 0x823B; -const RG8 = 0x822B; -const RG8_SNORM = 0x8F95; -const RG16F = 0x822F; -const RG32F = 0x8230; -const RG8UI = 0x8238; -const RG8I = 0x8237; -const R16UI = 0x8234; -const R16I = 0x8233; -const R32UI = 0x8236; -const R32I = 0x8235; -const RGB8 = 0x8051; -const SRGB8 = 0x8C41; -const RGB565$1 = 0x8D62; -const RGB8_SNORM = 0x8F96; -const R11F_G11F_B10F = 0x8C3A; -const RGB9_E5 = 0x8C3D; -const RGB16F = 0x881B; -const RGB32F = 0x8815; -const RGB8UI = 0x8D7D; -const RGB8I = 0x8D8F; -const RGB16UI = 0x8D77; -const RGB16I = 0x8D89; -const RGB32UI = 0x8D71; -const RGB32I = 0x8D83; -const RGBA8 = 0x8058; -const SRGB8_ALPHA8 = 0x8C43; -const RGBA8_SNORM = 0x8F97; -const RGB5_A1$1 = 0x8057; -const RGBA4$1 = 0x8056; -const RGB10_A2 = 0x8059; -const RGBA16F = 0x881A; -const RGBA32F = 0x8814; -const RGBA8UI = 0x8D7C; -const RGBA8I = 0x8D8E; -const RGB10_A2UI = 0x906F; -const RGBA16UI = 0x8D76; -const RGBA16I = 0x8D88; -const RGBA32I = 0x8D82; -const RGBA32UI = 0x8D70; - -const DEPTH_COMPONENT16$1 = 0x81A5; -const DEPTH_COMPONENT24$1 = 0x81A6; -const DEPTH_COMPONENT32F$1 = 0x8CAC; -const DEPTH32F_STENCIL8$1 = 0x8CAD; -const DEPTH24_STENCIL8$1 = 0x88F0; +const UNPACK_ALIGNMENT = 0x0cf5 +const UNPACK_ROW_LENGTH = 0x0cf2 +const UNPACK_IMAGE_HEIGHT = 0x806e +const UNPACK_SKIP_PIXELS = 0x0cf4 +const UNPACK_SKIP_ROWS = 0x0cf3 +const UNPACK_SKIP_IMAGES = 0x806d +const UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243 +const UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241 +const UNPACK_FLIP_Y_WEBGL = 0x9240 + +const R8 = 0x8229 +const R8_SNORM = 0x8f94 +const R16F = 0x822d +const R32F = 0x822e +const R8UI = 0x8232 +const R8I = 0x8231 +const RG16UI = 0x823a +const RG16I = 0x8239 +const RG32UI = 0x823c +const RG32I = 0x823b +const RG8 = 0x822b +const RG8_SNORM = 0x8f95 +const RG16F = 0x822f +const RG32F = 0x8230 +const RG8UI = 0x8238 +const RG8I = 0x8237 +const R16UI = 0x8234 +const R16I = 0x8233 +const R32UI = 0x8236 +const R32I = 0x8235 +const RGB8 = 0x8051 +const SRGB8 = 0x8c41 +const RGB565$1 = 0x8d62 +const RGB8_SNORM = 0x8f96 +const R11F_G11F_B10F = 0x8c3a +const RGB9_E5 = 0x8c3d +const RGB16F = 0x881b +const RGB32F = 0x8815 +const RGB8UI = 0x8d7d +const RGB8I = 0x8d8f +const RGB16UI = 0x8d77 +const RGB16I = 0x8d89 +const RGB32UI = 0x8d71 +const RGB32I = 0x8d83 +const RGBA8 = 0x8058 +const SRGB8_ALPHA8 = 0x8c43 +const RGBA8_SNORM = 0x8f97 +const RGB5_A1$1 = 0x8057 +const RGBA4$1 = 0x8056 +const RGB10_A2 = 0x8059 +const RGBA16F = 0x881a +const RGBA32F = 0x8814 +const RGBA8UI = 0x8d7c +const RGBA8I = 0x8d8e +const RGB10_A2UI = 0x906f +const RGBA16UI = 0x8d76 +const RGBA16I = 0x8d88 +const RGBA32I = 0x8d82 +const RGBA32UI = 0x8d70 + +const DEPTH_COMPONENT16$1 = 0x81a5 +const DEPTH_COMPONENT24$1 = 0x81a6 +const DEPTH_COMPONENT32F$1 = 0x8cac +const DEPTH32F_STENCIL8$1 = 0x8cad +const DEPTH24_STENCIL8$1 = 0x88f0 /* DataType */ -const BYTE = 0x1400; -const UNSIGNED_BYTE$1 = 0x1401; -const SHORT = 0x1402; -const UNSIGNED_SHORT$1 = 0x1403; -const INT$1 = 0x1404; -const UNSIGNED_INT$1 = 0x1405; -const FLOAT$1 = 0x1406; -const UNSIGNED_SHORT_4_4_4_4 = 0x8033; -const UNSIGNED_SHORT_5_5_5_1 = 0x8034; -const UNSIGNED_SHORT_5_6_5 = 0x8363; -const HALF_FLOAT = 0x140B; -const HALF_FLOAT_OES = 0x8D61; // Thanks Khronos for making this different >:( -const UNSIGNED_INT_2_10_10_10_REV = 0x8368; -const UNSIGNED_INT_10F_11F_11F_REV = 0x8C3B; -const UNSIGNED_INT_5_9_9_9_REV = 0x8C3E; -const FLOAT_32_UNSIGNED_INT_24_8_REV = 0x8DAD; -const UNSIGNED_INT_24_8 = 0x84FA; - -const RG = 0x8227; -const RG_INTEGER = 0x8228; -const RED = 0x1903; -const RED_INTEGER = 0x8D94; -const RGB_INTEGER = 0x8D98; -const RGBA_INTEGER = 0x8D99; - -const formatInfo = {}; +const BYTE = 0x1400 +const UNSIGNED_BYTE$1 = 0x1401 +const SHORT = 0x1402 +const UNSIGNED_SHORT$1 = 0x1403 +const INT$1 = 0x1404 +const UNSIGNED_INT$1 = 0x1405 +const FLOAT$1 = 0x1406 +const UNSIGNED_SHORT_4_4_4_4 = 0x8033 +const UNSIGNED_SHORT_5_5_5_1 = 0x8034 +const UNSIGNED_SHORT_5_6_5 = 0x8363 +const HALF_FLOAT = 0x140b +const HALF_FLOAT_OES = 0x8d61 // Thanks Khronos for making this different >:( +const UNSIGNED_INT_2_10_10_10_REV = 0x8368 +const UNSIGNED_INT_10F_11F_11F_REV = 0x8c3b +const UNSIGNED_INT_5_9_9_9_REV = 0x8c3e +const FLOAT_32_UNSIGNED_INT_24_8_REV = 0x8dad +const UNSIGNED_INT_24_8 = 0x84fa + +const RG = 0x8227 +const RG_INTEGER = 0x8228 +const RED = 0x1903 +const RED_INTEGER = 0x8d94 +const RGB_INTEGER = 0x8d98 +const RGBA_INTEGER = 0x8d99 + +const formatInfo = {} { - // NOTE: this is named `numColorComponents` vs `numComponents` so we can let Uglify mangle - // the name. - const f = formatInfo; - f[ALPHA] = { numColorComponents: 1, }; - f[LUMINANCE] = { numColorComponents: 1, }; - f[LUMINANCE_ALPHA] = { numColorComponents: 2, }; - f[RGB] = { numColorComponents: 3, }; - f[RGBA$1] = { numColorComponents: 4, }; - f[RED] = { numColorComponents: 1, }; - f[RED_INTEGER] = { numColorComponents: 1, }; - f[RG] = { numColorComponents: 2, }; - f[RG_INTEGER] = { numColorComponents: 2, }; - f[RGB] = { numColorComponents: 3, }; - f[RGB_INTEGER] = { numColorComponents: 3, }; - f[RGBA$1] = { numColorComponents: 4, }; - f[RGBA_INTEGER] = { numColorComponents: 4, }; - f[DEPTH_COMPONENT$1] = { numColorComponents: 1, }; - f[DEPTH_STENCIL$1] = { numColorComponents: 2, }; + // NOTE: this is named `numColorComponents` vs `numComponents` so we can let Uglify mangle + // the name. + const f = formatInfo + f[ALPHA] = { numColorComponents: 1 } + f[LUMINANCE] = { numColorComponents: 1 } + f[LUMINANCE_ALPHA] = { numColorComponents: 2 } + f[RGB] = { numColorComponents: 3 } + f[RGBA$1] = { numColorComponents: 4 } + f[RED] = { numColorComponents: 1 } + f[RED_INTEGER] = { numColorComponents: 1 } + f[RG] = { numColorComponents: 2 } + f[RG_INTEGER] = { numColorComponents: 2 } + f[RGB] = { numColorComponents: 3 } + f[RGB_INTEGER] = { numColorComponents: 3 } + f[RGBA$1] = { numColorComponents: 4 } + f[RGBA_INTEGER] = { numColorComponents: 4 } + f[DEPTH_COMPONENT$1] = { numColorComponents: 1 } + f[DEPTH_STENCIL$1] = { numColorComponents: 2 } } /** @@ -5231,87 +5326,464 @@ const formatInfo = {}; * @private */ -let s_textureInternalFormatInfo; +let s_textureInternalFormatInfo function getTextureInternalFormatInfo(internalFormat) { - if (!s_textureInternalFormatInfo) { - // NOTE: these properties need unique names so we can let Uglify mangle the name. - const t = {}; - // unsized formats - t[ALPHA] = { textureFormat: ALPHA, colorRenderable: true, textureFilterable: true, bytesPerElement: [1, 2, 2, 4], type: [UNSIGNED_BYTE$1, HALF_FLOAT, HALF_FLOAT_OES, FLOAT$1], }; - t[LUMINANCE] = { textureFormat: LUMINANCE, colorRenderable: true, textureFilterable: true, bytesPerElement: [1, 2, 2, 4], type: [UNSIGNED_BYTE$1, HALF_FLOAT, HALF_FLOAT_OES, FLOAT$1], }; - t[LUMINANCE_ALPHA] = { textureFormat: LUMINANCE_ALPHA, colorRenderable: true, textureFilterable: true, bytesPerElement: [2, 4, 4, 8], type: [UNSIGNED_BYTE$1, HALF_FLOAT, HALF_FLOAT_OES, FLOAT$1], }; - t[RGB] = { textureFormat: RGB, colorRenderable: true, textureFilterable: true, bytesPerElement: [3, 6, 6, 12, 2], type: [UNSIGNED_BYTE$1, HALF_FLOAT, HALF_FLOAT_OES, FLOAT$1, UNSIGNED_SHORT_5_6_5], }; - t[RGBA$1] = { textureFormat: RGBA$1, colorRenderable: true, textureFilterable: true, bytesPerElement: [4, 8, 8, 16, 2, 2], type: [UNSIGNED_BYTE$1, HALF_FLOAT, HALF_FLOAT_OES, FLOAT$1, UNSIGNED_SHORT_4_4_4_4, UNSIGNED_SHORT_5_5_5_1], }; - t[DEPTH_COMPONENT$1] = { textureFormat: DEPTH_COMPONENT$1, colorRenderable: true, textureFilterable: false, bytesPerElement: [2, 4], type: [UNSIGNED_INT$1, UNSIGNED_SHORT$1], }; - - // sized formats - t[R8] = { textureFormat: RED, colorRenderable: true, textureFilterable: true, bytesPerElement: [1], type: [UNSIGNED_BYTE$1], }; - t[R8_SNORM] = { textureFormat: RED, colorRenderable: false, textureFilterable: true, bytesPerElement: [1], type: [BYTE], }; - t[R16F] = { textureFormat: RED, colorRenderable: false, textureFilterable: true, bytesPerElement: [4, 2], type: [FLOAT$1, HALF_FLOAT], }; - t[R32F] = { textureFormat: RED, colorRenderable: false, textureFilterable: false, bytesPerElement: [4], type: [FLOAT$1], }; - t[R8UI] = { textureFormat: RED_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [1], type: [UNSIGNED_BYTE$1], }; - t[R8I] = { textureFormat: RED_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [1], type: [BYTE], }; - t[R16UI] = { textureFormat: RED_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [2], type: [UNSIGNED_SHORT$1], }; - t[R16I] = { textureFormat: RED_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [2], type: [SHORT], }; - t[R32UI] = { textureFormat: RED_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [UNSIGNED_INT$1], }; - t[R32I] = { textureFormat: RED_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [INT$1], }; - t[RG8] = { textureFormat: RG, colorRenderable: true, textureFilterable: true, bytesPerElement: [2], type: [UNSIGNED_BYTE$1], }; - t[RG8_SNORM] = { textureFormat: RG, colorRenderable: false, textureFilterable: true, bytesPerElement: [2], type: [BYTE], }; - t[RG16F] = { textureFormat: RG, colorRenderable: false, textureFilterable: true, bytesPerElement: [8, 4], type: [FLOAT$1, HALF_FLOAT], }; - t[RG32F] = { textureFormat: RG, colorRenderable: false, textureFilterable: false, bytesPerElement: [8], type: [FLOAT$1], }; - t[RG8UI] = { textureFormat: RG_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [2], type: [UNSIGNED_BYTE$1], }; - t[RG8I] = { textureFormat: RG_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [2], type: [BYTE], }; - t[RG16UI] = { textureFormat: RG_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [UNSIGNED_SHORT$1], }; - t[RG16I] = { textureFormat: RG_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [SHORT], }; - t[RG32UI] = { textureFormat: RG_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [8], type: [UNSIGNED_INT$1], }; - t[RG32I] = { textureFormat: RG_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [8], type: [INT$1], }; - t[RGB8] = { textureFormat: RGB, colorRenderable: true, textureFilterable: true, bytesPerElement: [3], type: [UNSIGNED_BYTE$1], }; - t[SRGB8] = { textureFormat: RGB, colorRenderable: false, textureFilterable: true, bytesPerElement: [3], type: [UNSIGNED_BYTE$1], }; - t[RGB565$1] = { textureFormat: RGB, colorRenderable: true, textureFilterable: true, bytesPerElement: [3, 2], type: [UNSIGNED_BYTE$1, UNSIGNED_SHORT_5_6_5], }; - t[RGB8_SNORM] = { textureFormat: RGB, colorRenderable: false, textureFilterable: true, bytesPerElement: [3], type: [BYTE], }; - t[R11F_G11F_B10F] = { textureFormat: RGB, colorRenderable: false, textureFilterable: true, bytesPerElement: [12, 6, 4], type: [FLOAT$1, HALF_FLOAT, UNSIGNED_INT_10F_11F_11F_REV], }; - t[RGB9_E5] = { textureFormat: RGB, colorRenderable: false, textureFilterable: true, bytesPerElement: [12, 6, 4], type: [FLOAT$1, HALF_FLOAT, UNSIGNED_INT_5_9_9_9_REV], }; - t[RGB16F] = { textureFormat: RGB, colorRenderable: false, textureFilterable: true, bytesPerElement: [12, 6], type: [FLOAT$1, HALF_FLOAT], }; - t[RGB32F] = { textureFormat: RGB, colorRenderable: false, textureFilterable: false, bytesPerElement: [12], type: [FLOAT$1], }; - t[RGB8UI] = { textureFormat: RGB_INTEGER, colorRenderable: false, textureFilterable: false, bytesPerElement: [3], type: [UNSIGNED_BYTE$1], }; - t[RGB8I] = { textureFormat: RGB_INTEGER, colorRenderable: false, textureFilterable: false, bytesPerElement: [3], type: [BYTE], }; - t[RGB16UI] = { textureFormat: RGB_INTEGER, colorRenderable: false, textureFilterable: false, bytesPerElement: [6], type: [UNSIGNED_SHORT$1], }; - t[RGB16I] = { textureFormat: RGB_INTEGER, colorRenderable: false, textureFilterable: false, bytesPerElement: [6], type: [SHORT], }; - t[RGB32UI] = { textureFormat: RGB_INTEGER, colorRenderable: false, textureFilterable: false, bytesPerElement: [12], type: [UNSIGNED_INT$1], }; - t[RGB32I] = { textureFormat: RGB_INTEGER, colorRenderable: false, textureFilterable: false, bytesPerElement: [12], type: [INT$1], }; - t[RGBA8] = { textureFormat: RGBA$1, colorRenderable: true, textureFilterable: true, bytesPerElement: [4], type: [UNSIGNED_BYTE$1], }; - t[SRGB8_ALPHA8] = { textureFormat: RGBA$1, colorRenderable: true, textureFilterable: true, bytesPerElement: [4], type: [UNSIGNED_BYTE$1], }; - t[RGBA8_SNORM] = { textureFormat: RGBA$1, colorRenderable: false, textureFilterable: true, bytesPerElement: [4], type: [BYTE], }; - t[RGB5_A1$1] = { textureFormat: RGBA$1, colorRenderable: true, textureFilterable: true, bytesPerElement: [4, 2, 4], type: [UNSIGNED_BYTE$1, UNSIGNED_SHORT_5_5_5_1, UNSIGNED_INT_2_10_10_10_REV], }; - t[RGBA4$1] = { textureFormat: RGBA$1, colorRenderable: true, textureFilterable: true, bytesPerElement: [4, 2], type: [UNSIGNED_BYTE$1, UNSIGNED_SHORT_4_4_4_4], }; - t[RGB10_A2] = { textureFormat: RGBA$1, colorRenderable: true, textureFilterable: true, bytesPerElement: [4], type: [UNSIGNED_INT_2_10_10_10_REV], }; - t[RGBA16F] = { textureFormat: RGBA$1, colorRenderable: false, textureFilterable: true, bytesPerElement: [16, 8], type: [FLOAT$1, HALF_FLOAT], }; - t[RGBA32F] = { textureFormat: RGBA$1, colorRenderable: false, textureFilterable: false, bytesPerElement: [16], type: [FLOAT$1], }; - t[RGBA8UI] = { textureFormat: RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [UNSIGNED_BYTE$1], }; - t[RGBA8I] = { textureFormat: RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [BYTE], }; - t[RGB10_A2UI] = { textureFormat: RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [UNSIGNED_INT_2_10_10_10_REV], }; - t[RGBA16UI] = { textureFormat: RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [8], type: [UNSIGNED_SHORT$1], }; - t[RGBA16I] = { textureFormat: RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [8], type: [SHORT], }; - t[RGBA32I] = { textureFormat: RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [16], type: [INT$1], }; - t[RGBA32UI] = { textureFormat: RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [16], type: [UNSIGNED_INT$1], }; - // Sized Internal - t[DEPTH_COMPONENT16$1] = { textureFormat: DEPTH_COMPONENT$1, colorRenderable: true, textureFilterable: false, bytesPerElement: [2, 4], type: [UNSIGNED_SHORT$1, UNSIGNED_INT$1], }; - t[DEPTH_COMPONENT24$1] = { textureFormat: DEPTH_COMPONENT$1, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [UNSIGNED_INT$1], }; - t[DEPTH_COMPONENT32F$1] = { textureFormat: DEPTH_COMPONENT$1, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [FLOAT$1], }; - t[DEPTH24_STENCIL8$1] = { textureFormat: DEPTH_STENCIL$1, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [UNSIGNED_INT_24_8], }; - t[DEPTH32F_STENCIL8$1] = { textureFormat: DEPTH_STENCIL$1, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [FLOAT_32_UNSIGNED_INT_24_8_REV], }; - - Object.keys(t).forEach(function(internalFormat) { - const info = t[internalFormat]; - info.bytesPerElementMap = {}; - info.bytesPerElement.forEach(function(bytesPerElement, ndx) { - const type = info.type[ndx]; - info.bytesPerElementMap[type] = bytesPerElement; - }); - }); - s_textureInternalFormatInfo = t; - } - return s_textureInternalFormatInfo[internalFormat]; + if (!s_textureInternalFormatInfo) { + // NOTE: these properties need unique names so we can let Uglify mangle the name. + const t = {} + // unsized formats + t[ALPHA] = { + textureFormat: ALPHA, + colorRenderable: true, + textureFilterable: true, + bytesPerElement: [1, 2, 2, 4], + type: [UNSIGNED_BYTE$1, HALF_FLOAT, HALF_FLOAT_OES, FLOAT$1], + } + t[LUMINANCE] = { + textureFormat: LUMINANCE, + colorRenderable: true, + textureFilterable: true, + bytesPerElement: [1, 2, 2, 4], + type: [UNSIGNED_BYTE$1, HALF_FLOAT, HALF_FLOAT_OES, FLOAT$1], + } + t[LUMINANCE_ALPHA] = { + textureFormat: LUMINANCE_ALPHA, + colorRenderable: true, + textureFilterable: true, + bytesPerElement: [2, 4, 4, 8], + type: [UNSIGNED_BYTE$1, HALF_FLOAT, HALF_FLOAT_OES, FLOAT$1], + } + t[RGB] = { + textureFormat: RGB, + colorRenderable: true, + textureFilterable: true, + bytesPerElement: [3, 6, 6, 12, 2], + type: [ + UNSIGNED_BYTE$1, + HALF_FLOAT, + HALF_FLOAT_OES, + FLOAT$1, + UNSIGNED_SHORT_5_6_5, + ], + } + t[RGBA$1] = { + textureFormat: RGBA$1, + colorRenderable: true, + textureFilterable: true, + bytesPerElement: [4, 8, 8, 16, 2, 2], + type: [ + UNSIGNED_BYTE$1, + HALF_FLOAT, + HALF_FLOAT_OES, + FLOAT$1, + UNSIGNED_SHORT_4_4_4_4, + UNSIGNED_SHORT_5_5_5_1, + ], + } + t[DEPTH_COMPONENT$1] = { + textureFormat: DEPTH_COMPONENT$1, + colorRenderable: true, + textureFilterable: false, + bytesPerElement: [2, 4], + type: [UNSIGNED_INT$1, UNSIGNED_SHORT$1], + } + + // sized formats + t[R8] = { + textureFormat: RED, + colorRenderable: true, + textureFilterable: true, + bytesPerElement: [1], + type: [UNSIGNED_BYTE$1], + } + t[R8_SNORM] = { + textureFormat: RED, + colorRenderable: false, + textureFilterable: true, + bytesPerElement: [1], + type: [BYTE], + } + t[R16F] = { + textureFormat: RED, + colorRenderable: false, + textureFilterable: true, + bytesPerElement: [4, 2], + type: [FLOAT$1, HALF_FLOAT], + } + t[R32F] = { + textureFormat: RED, + colorRenderable: false, + textureFilterable: false, + bytesPerElement: [4], + type: [FLOAT$1], + } + t[R8UI] = { + textureFormat: RED_INTEGER, + colorRenderable: true, + textureFilterable: false, + bytesPerElement: [1], + type: [UNSIGNED_BYTE$1], + } + t[R8I] = { + textureFormat: RED_INTEGER, + colorRenderable: true, + textureFilterable: false, + bytesPerElement: [1], + type: [BYTE], + } + t[R16UI] = { + textureFormat: RED_INTEGER, + colorRenderable: true, + textureFilterable: false, + bytesPerElement: [2], + type: [UNSIGNED_SHORT$1], + } + t[R16I] = { + textureFormat: RED_INTEGER, + colorRenderable: true, + textureFilterable: false, + bytesPerElement: [2], + type: [SHORT], + } + t[R32UI] = { + textureFormat: RED_INTEGER, + colorRenderable: true, + textureFilterable: false, + bytesPerElement: [4], + type: [UNSIGNED_INT$1], + } + t[R32I] = { + textureFormat: RED_INTEGER, + colorRenderable: true, + textureFilterable: false, + bytesPerElement: [4], + type: [INT$1], + } + t[RG8] = { + textureFormat: RG, + colorRenderable: true, + textureFilterable: true, + bytesPerElement: [2], + type: [UNSIGNED_BYTE$1], + } + t[RG8_SNORM] = { + textureFormat: RG, + colorRenderable: false, + textureFilterable: true, + bytesPerElement: [2], + type: [BYTE], + } + t[RG16F] = { + textureFormat: RG, + colorRenderable: false, + textureFilterable: true, + bytesPerElement: [8, 4], + type: [FLOAT$1, HALF_FLOAT], + } + t[RG32F] = { + textureFormat: RG, + colorRenderable: false, + textureFilterable: false, + bytesPerElement: [8], + type: [FLOAT$1], + } + t[RG8UI] = { + textureFormat: RG_INTEGER, + colorRenderable: true, + textureFilterable: false, + bytesPerElement: [2], + type: [UNSIGNED_BYTE$1], + } + t[RG8I] = { + textureFormat: RG_INTEGER, + colorRenderable: true, + textureFilterable: false, + bytesPerElement: [2], + type: [BYTE], + } + t[RG16UI] = { + textureFormat: RG_INTEGER, + colorRenderable: true, + textureFilterable: false, + bytesPerElement: [4], + type: [UNSIGNED_SHORT$1], + } + t[RG16I] = { + textureFormat: RG_INTEGER, + colorRenderable: true, + textureFilterable: false, + bytesPerElement: [4], + type: [SHORT], + } + t[RG32UI] = { + textureFormat: RG_INTEGER, + colorRenderable: true, + textureFilterable: false, + bytesPerElement: [8], + type: [UNSIGNED_INT$1], + } + t[RG32I] = { + textureFormat: RG_INTEGER, + colorRenderable: true, + textureFilterable: false, + bytesPerElement: [8], + type: [INT$1], + } + t[RGB8] = { + textureFormat: RGB, + colorRenderable: true, + textureFilterable: true, + bytesPerElement: [3], + type: [UNSIGNED_BYTE$1], + } + t[SRGB8] = { + textureFormat: RGB, + colorRenderable: false, + textureFilterable: true, + bytesPerElement: [3], + type: [UNSIGNED_BYTE$1], + } + t[RGB565$1] = { + textureFormat: RGB, + colorRenderable: true, + textureFilterable: true, + bytesPerElement: [3, 2], + type: [UNSIGNED_BYTE$1, UNSIGNED_SHORT_5_6_5], + } + t[RGB8_SNORM] = { + textureFormat: RGB, + colorRenderable: false, + textureFilterable: true, + bytesPerElement: [3], + type: [BYTE], + } + t[R11F_G11F_B10F] = { + textureFormat: RGB, + colorRenderable: false, + textureFilterable: true, + bytesPerElement: [12, 6, 4], + type: [FLOAT$1, HALF_FLOAT, UNSIGNED_INT_10F_11F_11F_REV], + } + t[RGB9_E5] = { + textureFormat: RGB, + colorRenderable: false, + textureFilterable: true, + bytesPerElement: [12, 6, 4], + type: [FLOAT$1, HALF_FLOAT, UNSIGNED_INT_5_9_9_9_REV], + } + t[RGB16F] = { + textureFormat: RGB, + colorRenderable: false, + textureFilterable: true, + bytesPerElement: [12, 6], + type: [FLOAT$1, HALF_FLOAT], + } + t[RGB32F] = { + textureFormat: RGB, + colorRenderable: false, + textureFilterable: false, + bytesPerElement: [12], + type: [FLOAT$1], + } + t[RGB8UI] = { + textureFormat: RGB_INTEGER, + colorRenderable: false, + textureFilterable: false, + bytesPerElement: [3], + type: [UNSIGNED_BYTE$1], + } + t[RGB8I] = { + textureFormat: RGB_INTEGER, + colorRenderable: false, + textureFilterable: false, + bytesPerElement: [3], + type: [BYTE], + } + t[RGB16UI] = { + textureFormat: RGB_INTEGER, + colorRenderable: false, + textureFilterable: false, + bytesPerElement: [6], + type: [UNSIGNED_SHORT$1], + } + t[RGB16I] = { + textureFormat: RGB_INTEGER, + colorRenderable: false, + textureFilterable: false, + bytesPerElement: [6], + type: [SHORT], + } + t[RGB32UI] = { + textureFormat: RGB_INTEGER, + colorRenderable: false, + textureFilterable: false, + bytesPerElement: [12], + type: [UNSIGNED_INT$1], + } + t[RGB32I] = { + textureFormat: RGB_INTEGER, + colorRenderable: false, + textureFilterable: false, + bytesPerElement: [12], + type: [INT$1], + } + t[RGBA8] = { + textureFormat: RGBA$1, + colorRenderable: true, + textureFilterable: true, + bytesPerElement: [4], + type: [UNSIGNED_BYTE$1], + } + t[SRGB8_ALPHA8] = { + textureFormat: RGBA$1, + colorRenderable: true, + textureFilterable: true, + bytesPerElement: [4], + type: [UNSIGNED_BYTE$1], + } + t[RGBA8_SNORM] = { + textureFormat: RGBA$1, + colorRenderable: false, + textureFilterable: true, + bytesPerElement: [4], + type: [BYTE], + } + t[RGB5_A1$1] = { + textureFormat: RGBA$1, + colorRenderable: true, + textureFilterable: true, + bytesPerElement: [4, 2, 4], + type: [ + UNSIGNED_BYTE$1, + UNSIGNED_SHORT_5_5_5_1, + UNSIGNED_INT_2_10_10_10_REV, + ], + } + t[RGBA4$1] = { + textureFormat: RGBA$1, + colorRenderable: true, + textureFilterable: true, + bytesPerElement: [4, 2], + type: [UNSIGNED_BYTE$1, UNSIGNED_SHORT_4_4_4_4], + } + t[RGB10_A2] = { + textureFormat: RGBA$1, + colorRenderable: true, + textureFilterable: true, + bytesPerElement: [4], + type: [UNSIGNED_INT_2_10_10_10_REV], + } + t[RGBA16F] = { + textureFormat: RGBA$1, + colorRenderable: false, + textureFilterable: true, + bytesPerElement: [16, 8], + type: [FLOAT$1, HALF_FLOAT], + } + t[RGBA32F] = { + textureFormat: RGBA$1, + colorRenderable: false, + textureFilterable: false, + bytesPerElement: [16], + type: [FLOAT$1], + } + t[RGBA8UI] = { + textureFormat: RGBA_INTEGER, + colorRenderable: true, + textureFilterable: false, + bytesPerElement: [4], + type: [UNSIGNED_BYTE$1], + } + t[RGBA8I] = { + textureFormat: RGBA_INTEGER, + colorRenderable: true, + textureFilterable: false, + bytesPerElement: [4], + type: [BYTE], + } + t[RGB10_A2UI] = { + textureFormat: RGBA_INTEGER, + colorRenderable: true, + textureFilterable: false, + bytesPerElement: [4], + type: [UNSIGNED_INT_2_10_10_10_REV], + } + t[RGBA16UI] = { + textureFormat: RGBA_INTEGER, + colorRenderable: true, + textureFilterable: false, + bytesPerElement: [8], + type: [UNSIGNED_SHORT$1], + } + t[RGBA16I] = { + textureFormat: RGBA_INTEGER, + colorRenderable: true, + textureFilterable: false, + bytesPerElement: [8], + type: [SHORT], + } + t[RGBA32I] = { + textureFormat: RGBA_INTEGER, + colorRenderable: true, + textureFilterable: false, + bytesPerElement: [16], + type: [INT$1], + } + t[RGBA32UI] = { + textureFormat: RGBA_INTEGER, + colorRenderable: true, + textureFilterable: false, + bytesPerElement: [16], + type: [UNSIGNED_INT$1], + } + // Sized Internal + t[DEPTH_COMPONENT16$1] = { + textureFormat: DEPTH_COMPONENT$1, + colorRenderable: true, + textureFilterable: false, + bytesPerElement: [2, 4], + type: [UNSIGNED_SHORT$1, UNSIGNED_INT$1], + } + t[DEPTH_COMPONENT24$1] = { + textureFormat: DEPTH_COMPONENT$1, + colorRenderable: true, + textureFilterable: false, + bytesPerElement: [4], + type: [UNSIGNED_INT$1], + } + t[DEPTH_COMPONENT32F$1] = { + textureFormat: DEPTH_COMPONENT$1, + colorRenderable: true, + textureFilterable: false, + bytesPerElement: [4], + type: [FLOAT$1], + } + t[DEPTH24_STENCIL8$1] = { + textureFormat: DEPTH_STENCIL$1, + colorRenderable: true, + textureFilterable: false, + bytesPerElement: [4], + type: [UNSIGNED_INT_24_8], + } + t[DEPTH32F_STENCIL8$1] = { + textureFormat: DEPTH_STENCIL$1, + colorRenderable: true, + textureFilterable: false, + bytesPerElement: [4], + type: [FLOAT_32_UNSIGNED_INT_24_8_REV], + } + + Object.keys(t).forEach(function (internalFormat) { + const info = t[internalFormat] + info.bytesPerElementMap = {} + info.bytesPerElement.forEach(function (bytesPerElement, ndx) { + const type = info.type[ndx] + info.bytesPerElementMap[type] = bytesPerElement + }) + }) + s_textureInternalFormatInfo = t + } + return s_textureInternalFormatInfo[internalFormat] } /** @@ -5322,15 +5794,15 @@ function getTextureInternalFormatInfo(internalFormat) { * @memberOf module:twgl/textures */ function getBytesPerElementForInternalFormat(internalFormat, type) { - const info = getTextureInternalFormatInfo(internalFormat); - if (!info) { - throw "unknown internal format"; - } - const bytesPerElement = info.bytesPerElementMap[type]; - if (bytesPerElement === undefined) { - throw "unknown internal format"; - } - return bytesPerElement; + const info = getTextureInternalFormatInfo(internalFormat) + if (!info) { + throw 'unknown internal format' + } + const bytesPerElement = info.bytesPerElementMap[type] + if (bytesPerElement === undefined) { + throw 'unknown internal format' + } + return bytesPerElement } /** @@ -5351,14 +5823,14 @@ function getBytesPerElementForInternalFormat(internalFormat, type) { * @memberOf module:twgl/textures */ function getFormatAndTypeForInternalFormat(internalFormat) { - const info = getTextureInternalFormatInfo(internalFormat); - if (!info) { - throw "unknown internal format"; - } - return { - format: info.textureFormat, - type: info.type[0], - }; + const info = getTextureInternalFormatInfo(internalFormat) + if (!info) { + throw 'unknown internal format' + } + return { + format: info.textureFormat, + type: info.type[0], + } } /** @@ -5368,7 +5840,7 @@ function getFormatAndTypeForInternalFormat(internalFormat) { * @private */ function isPowerOf2(value) { - return (value & (value - 1)) === 0; + return (value & (value - 1)) === 0 } /** @@ -5383,14 +5855,14 @@ function isPowerOf2(value) { * @memberOf module:twgl/textures */ function canGenerateMipmap(gl, width, height, internalFormat) { - if (!isWebGL2(gl)) { - return isPowerOf2(width) && isPowerOf2(height); - } - const info = getTextureInternalFormatInfo(internalFormat); - if (!info) { - throw "unknown internal format"; - } - return info.colorRenderable && info.textureFilterable; + if (!isWebGL2(gl)) { + return isPowerOf2(width) && isPowerOf2(height) + } + const info = getTextureInternalFormatInfo(internalFormat) + if (!info) { + throw 'unknown internal format' + } + return info.colorRenderable && info.textureFilterable } /** @@ -5400,11 +5872,11 @@ function canGenerateMipmap(gl, width, height, internalFormat) { * @memberOf module:twgl/textures */ function canFilter(internalFormat) { - const info = getTextureInternalFormatInfo(internalFormat); - if (!info) { - throw "unknown internal format"; - } - return info.textureFilterable; + const info = getTextureInternalFormatInfo(internalFormat) + if (!info) { + throw 'unknown internal format' + } + return info.textureFilterable } /** @@ -5414,11 +5886,11 @@ function canFilter(internalFormat) { * @memberOf module:twgl/textures */ function getNumComponentsForFormat(format) { - const info = formatInfo[format]; - if (!info) { - throw "unknown format: " + format; - } - return info.numColorComponents; + const info = formatInfo[format] + if (!info) { + throw 'unknown format: ' + format + } + return info.numColorComponents } /** @@ -5428,40 +5900,42 @@ function getNumComponentsForFormat(format) { * @private */ function getTextureTypeForArrayType(gl, src, defaultType) { - if (isArrayBuffer(src)) { - return getGLTypeForTypedArray(src); - } - return defaultType || UNSIGNED_BYTE$1; + if (isArrayBuffer(src)) { + return getGLTypeForTypedArray(src) + } + return defaultType || UNSIGNED_BYTE$1 } function guessDimensions(gl, target, width, height, numElements) { - if (numElements % 1 !== 0) { - throw "can't guess dimensions"; - } - if (!width && !height) { - const size = Math.sqrt(numElements / (target === TEXTURE_CUBE_MAP$1 ? 6 : 1)); - if (size % 1 === 0) { - width = size; - height = size; - } else { - width = numElements; - height = 1; + if (numElements % 1 !== 0) { + throw "can't guess dimensions" } - } else if (!height) { - height = numElements / width; - if (height % 1) { - throw "can't guess dimensions"; + if (!width && !height) { + const size = Math.sqrt( + numElements / (target === TEXTURE_CUBE_MAP$1 ? 6 : 1) + ) + if (size % 1 === 0) { + width = size + height = size + } else { + width = numElements + height = 1 + } + } else if (!height) { + height = numElements / width + if (height % 1) { + throw "can't guess dimensions" + } + } else if (!width) { + width = numElements / height + if (width % 1) { + throw "can't guess dimensions" + } } - } else if (!width) { - width = numElements / height; - if (width % 1) { - throw "can't guess dimensions"; + return { + width: width, + height: height, } - } - return { - width: width, - height: height, - }; } /** @@ -5478,14 +5952,19 @@ function guessDimensions(gl, target, width, height, numElements) { * @memberOf module:twgl/textures */ function setDefaultTextureColor(color) { - defaults$1.textureColor = new Uint8Array([color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255]); + defaults$1.textureColor = new Uint8Array([ + color[0] * 255, + color[1] * 255, + color[2] * 255, + color[3] * 255, + ]) } function setDefaults$1(newDefaults) { - copyExistingProperties(newDefaults, defaults$1); - if (newDefaults.textureColor) { - setDefaultTextureColor(newDefaults.textureColor); - } + copyExistingProperties(newDefaults, defaults$1) + if (newDefaults.textureColor) { + setDefaultTextureColor(newDefaults.textureColor) + } } /** @@ -5597,15 +6076,18 @@ function setDefaults$1(newDefaults) { * @private */ function setPackState(gl, options) { - if (options.colorspaceConversion !== undefined) { - gl.pixelStorei(UNPACK_COLORSPACE_CONVERSION_WEBGL, options.colorspaceConversion); - } - if (options.premultiplyAlpha !== undefined) { - gl.pixelStorei(UNPACK_PREMULTIPLY_ALPHA_WEBGL, options.premultiplyAlpha); - } - if (options.flipY !== undefined) { - gl.pixelStorei(UNPACK_FLIP_Y_WEBGL, options.flipY); - } + if (options.colorspaceConversion !== undefined) { + gl.pixelStorei( + UNPACK_COLORSPACE_CONVERSION_WEBGL, + options.colorspaceConversion + ) + } + if (options.premultiplyAlpha !== undefined) { + gl.pixelStorei(UNPACK_PREMULTIPLY_ALPHA_WEBGL, options.premultiplyAlpha) + } + if (options.flipY !== undefined) { + gl.pixelStorei(UNPACK_FLIP_Y_WEBGL, options.flipY) + } } /** @@ -5614,14 +6096,14 @@ function setPackState(gl, options) { * @private */ function setSkipStateToDefault(gl) { - gl.pixelStorei(UNPACK_ALIGNMENT, 4); - if (isWebGL2(gl)) { - gl.pixelStorei(UNPACK_ROW_LENGTH, 0); - gl.pixelStorei(UNPACK_IMAGE_HEIGHT, 0); - gl.pixelStorei(UNPACK_SKIP_PIXELS, 0); - gl.pixelStorei(UNPACK_SKIP_ROWS, 0); - gl.pixelStorei(UNPACK_SKIP_IMAGES, 0); - } + gl.pixelStorei(UNPACK_ALIGNMENT, 4) + if (isWebGL2(gl)) { + gl.pixelStorei(UNPACK_ROW_LENGTH, 0) + gl.pixelStorei(UNPACK_IMAGE_HEIGHT, 0) + gl.pixelStorei(UNPACK_SKIP_PIXELS, 0) + gl.pixelStorei(UNPACK_SKIP_ROWS, 0) + gl.pixelStorei(UNPACK_SKIP_IMAGES, 0) + } } /** @@ -5635,44 +6117,44 @@ function setSkipStateToDefault(gl) { * @private */ function setTextureSamplerParameters(gl, target, parameteriFn, options) { - if (options.minMag) { - parameteriFn.call(gl, target, TEXTURE_MIN_FILTER, options.minMag); - parameteriFn.call(gl, target, TEXTURE_MAG_FILTER, options.minMag); - } - if (options.min) { - parameteriFn.call(gl, target, TEXTURE_MIN_FILTER, options.min); - } - if (options.mag) { - parameteriFn.call(gl, target, TEXTURE_MAG_FILTER, options.mag); - } - if (options.wrap) { - parameteriFn.call(gl, target, TEXTURE_WRAP_S, options.wrap); - parameteriFn.call(gl, target, TEXTURE_WRAP_T, options.wrap); - if (target === TEXTURE_3D$1 || isSampler(gl, target)) { - parameteriFn.call(gl, target, TEXTURE_WRAP_R, options.wrap); - } - } - if (options.wrapR) { - parameteriFn.call(gl, target, TEXTURE_WRAP_R, options.wrapR); - } - if (options.wrapS) { - parameteriFn.call(gl, target, TEXTURE_WRAP_S, options.wrapS); - } - if (options.wrapT) { - parameteriFn.call(gl, target, TEXTURE_WRAP_T, options.wrapT); - } - if (options.minLod) { - parameteriFn.call(gl, target, TEXTURE_MIN_LOD, options.minLod); - } - if (options.maxLod) { - parameteriFn.call(gl, target, TEXTURE_MAX_LOD, options.maxLod); - } - if (options.baseLevel) { - parameteriFn.call(gl, target, TEXTURE_BASE_LEVEL, options.baseLevel); - } - if (options.maxLevel) { - parameteriFn.call(gl, target, TEXTURE_MAX_LEVEL, options.maxLevel); - } + if (options.minMag) { + parameteriFn.call(gl, target, TEXTURE_MIN_FILTER, options.minMag) + parameteriFn.call(gl, target, TEXTURE_MAG_FILTER, options.minMag) + } + if (options.min) { + parameteriFn.call(gl, target, TEXTURE_MIN_FILTER, options.min) + } + if (options.mag) { + parameteriFn.call(gl, target, TEXTURE_MAG_FILTER, options.mag) + } + if (options.wrap) { + parameteriFn.call(gl, target, TEXTURE_WRAP_S, options.wrap) + parameteriFn.call(gl, target, TEXTURE_WRAP_T, options.wrap) + if (target === TEXTURE_3D$1 || isSampler(gl, target)) { + parameteriFn.call(gl, target, TEXTURE_WRAP_R, options.wrap) + } + } + if (options.wrapR) { + parameteriFn.call(gl, target, TEXTURE_WRAP_R, options.wrapR) + } + if (options.wrapS) { + parameteriFn.call(gl, target, TEXTURE_WRAP_S, options.wrapS) + } + if (options.wrapT) { + parameteriFn.call(gl, target, TEXTURE_WRAP_T, options.wrapT) + } + if (options.minLod) { + parameteriFn.call(gl, target, TEXTURE_MIN_LOD, options.minLod) + } + if (options.maxLod) { + parameteriFn.call(gl, target, TEXTURE_MAX_LOD, options.maxLod) + } + if (options.baseLevel) { + parameteriFn.call(gl, target, TEXTURE_BASE_LEVEL, options.baseLevel) + } + if (options.maxLevel) { + parameteriFn.call(gl, target, TEXTURE_MAX_LEVEL, options.maxLevel) + } } /** @@ -5684,9 +6166,9 @@ function setTextureSamplerParameters(gl, target, parameteriFn, options) { * @memberOf module:twgl/textures */ function setTextureParameters(gl, tex, options) { - const target = options.target || TEXTURE_2D$2; - gl.bindTexture(target, tex); - setTextureSamplerParameters(gl, target, gl.texParameteri, options); + const target = options.target || TEXTURE_2D$2 + gl.bindTexture(target, tex) + setTextureSamplerParameters(gl, target, gl.texParameteri, options) } /** @@ -5697,7 +6179,7 @@ function setTextureParameters(gl, tex, options) { * @memberOf module:twgl/textures */ function setSamplerParameters(gl, sampler, options) { - setTextureSamplerParameters(gl, sampler, gl.samplerParameteri, options); + setTextureSamplerParameters(gl, sampler, gl.samplerParameteri, options) } /** @@ -5716,9 +6198,9 @@ function setSamplerParameters(gl, sampler, options) { * @private */ function createSampler(gl, options) { - const sampler = gl.createSampler(); - setSamplerParameters(gl, sampler, options); - return sampler; + const sampler = gl.createSampler() + setSamplerParameters(gl, sampler, options) + return sampler } /** @@ -5756,11 +6238,11 @@ function createSampler(gl, options) { * @private */ function createSamplers(gl, samplerOptions) { - const samplers = {}; - Object.keys(samplerOptions).forEach(function(name) { - samplers[name] = createSampler(gl, samplerOptions[name]); - }); - return samplers; + const samplers = {} + Object.keys(samplerOptions).forEach(function (name) { + samplers[name] = createSampler(gl, samplerOptions[name]) + }) + return samplers } /** @@ -5771,11 +6253,16 @@ function createSamplers(gl, samplerOptions) { * @private */ function make1Pixel(color) { - color = color || defaults$1.textureColor; - if (isArrayBuffer(color)) { - return color; - } - return new Uint8Array([color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255]); + color = color || defaults$1.textureColor + if (isArrayBuffer(color)) { + return color + } + return new Uint8Array([ + color[0] * 255, + color[1] * 255, + color[2] * 255, + color[3] * 255, + ]) } /** @@ -5791,26 +6278,36 @@ function make1Pixel(color) { * @param {number} [internalFormat] The internalFormat parameter from texImage2D etc.. * @memberOf module:twgl/textures */ -function setTextureFilteringForSize(gl, tex, options, width, height, internalFormat) { - options = options || defaults$1.textureOptions; - internalFormat = internalFormat || RGBA$1; - const target = options.target || TEXTURE_2D$2; - width = width || options.width; - height = height || options.height; - gl.bindTexture(target, tex); - if (canGenerateMipmap(gl, width, height, internalFormat)) { - gl.generateMipmap(target); - } else { - const filtering = canFilter(internalFormat) ? LINEAR$1 : NEAREST; - gl.texParameteri(target, TEXTURE_MIN_FILTER, filtering); - gl.texParameteri(target, TEXTURE_MAG_FILTER, filtering); - gl.texParameteri(target, TEXTURE_WRAP_S, CLAMP_TO_EDGE$1); - gl.texParameteri(target, TEXTURE_WRAP_T, CLAMP_TO_EDGE$1); - } +function setTextureFilteringForSize( + gl, + tex, + options, + width, + height, + internalFormat +) { + options = options || defaults$1.textureOptions + internalFormat = internalFormat || RGBA$1 + const target = options.target || TEXTURE_2D$2 + width = width || options.width + height = height || options.height + gl.bindTexture(target, tex) + if (canGenerateMipmap(gl, width, height, internalFormat)) { + gl.generateMipmap(target) + } else { + const filtering = canFilter(internalFormat) ? LINEAR$1 : NEAREST + gl.texParameteri(target, TEXTURE_MIN_FILTER, filtering) + gl.texParameteri(target, TEXTURE_MAG_FILTER, filtering) + gl.texParameteri(target, TEXTURE_WRAP_S, CLAMP_TO_EDGE$1) + gl.texParameteri(target, TEXTURE_WRAP_T, CLAMP_TO_EDGE$1) + } } function shouldAutomaticallySetTextureFilteringForSize(options) { - return options.auto === true || (options.auto === undefined && options.level === undefined); + return ( + options.auto === true || + (options.auto === undefined && options.level === undefined) + ) } /** @@ -5822,15 +6319,17 @@ function shouldAutomaticallySetTextureFilteringForSize(options) { * @private */ function getCubeFaceOrder(gl, options) { - options = options || {}; - return options.cubeFaceOrder || [ - TEXTURE_CUBE_MAP_POSITIVE_X, - TEXTURE_CUBE_MAP_NEGATIVE_X, - TEXTURE_CUBE_MAP_POSITIVE_Y, - TEXTURE_CUBE_MAP_NEGATIVE_Y, - TEXTURE_CUBE_MAP_POSITIVE_Z, - TEXTURE_CUBE_MAP_NEGATIVE_Z, - ]; + options = options || {} + return ( + options.cubeFaceOrder || [ + TEXTURE_CUBE_MAP_POSITIVE_X, + TEXTURE_CUBE_MAP_NEGATIVE_X, + TEXTURE_CUBE_MAP_POSITIVE_Y, + TEXTURE_CUBE_MAP_NEGATIVE_Y, + TEXTURE_CUBE_MAP_POSITIVE_Z, + TEXTURE_CUBE_MAP_NEGATIVE_Z, + ] + ) } /** @@ -5854,15 +6353,15 @@ function getCubeFaceOrder(gl, options) { * @private */ function getCubeFacesWithNdx(gl, options) { - const faces = getCubeFaceOrder(gl, options); - // work around bug in NVidia drivers. We have to upload the first face first else the driver crashes :( - const facesWithNdx = faces.map(function(face, ndx) { - return { face: face, ndx: ndx }; - }); - facesWithNdx.sort(function(a, b) { - return a.face - b.face; - }); - return facesWithNdx; + const faces = getCubeFaceOrder(gl, options) + // work around bug in NVidia drivers. We have to upload the first face first else the driver crashes :( + const facesWithNdx = faces.map(function (face, ndx) { + return { face: face, ndx: ndx } + }) + facesWithNdx.sort(function (a, b) { + return a.face - b.face + }) + return facesWithNdx } /** @@ -5879,119 +6378,193 @@ function getCubeFacesWithNdx(gl, options) { * @kind function */ function setTextureFromElement(gl, tex, element, options) { - options = options || defaults$1.textureOptions; - const target = options.target || TEXTURE_2D$2; - const level = options.level || 0; - let width = element.width; - let height = element.height; - const internalFormat = options.internalFormat || options.format || RGBA$1; - const formatType = getFormatAndTypeForInternalFormat(internalFormat); - const format = options.format || formatType.format; - const type = options.type || formatType.type; - setPackState(gl, options); - gl.bindTexture(target, tex); - if (target === TEXTURE_CUBE_MAP$1) { - // guess the parts - const imgWidth = element.width; - const imgHeight = element.height; - let size; - let slices; - if (imgWidth / 6 === imgHeight) { - // It's 6x1 - size = imgHeight; - slices = [0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0]; - } else if (imgHeight / 6 === imgWidth) { - // It's 1x6 - size = imgWidth; - slices = [0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5]; - } else if (imgWidth / 3 === imgHeight / 2) { - // It's 3x2 - size = imgWidth / 3; - slices = [0, 0, 1, 0, 2, 0, 0, 1, 1, 1, 2, 1]; - } else if (imgWidth / 2 === imgHeight / 3) { - // It's 2x3 - size = imgWidth / 2; - slices = [0, 0, 1, 0, 0, 1, 1, 1, 0, 2, 1, 2]; + options = options || defaults$1.textureOptions + const target = options.target || TEXTURE_2D$2 + const level = options.level || 0 + let width = element.width + let height = element.height + const internalFormat = options.internalFormat || options.format || RGBA$1 + const formatType = getFormatAndTypeForInternalFormat(internalFormat) + const format = options.format || formatType.format + const type = options.type || formatType.type + setPackState(gl, options) + gl.bindTexture(target, tex) + if (target === TEXTURE_CUBE_MAP$1) { + // guess the parts + const imgWidth = element.width + const imgHeight = element.height + let size + let slices + if (imgWidth / 6 === imgHeight) { + // It's 6x1 + size = imgHeight + slices = [0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0] + } else if (imgHeight / 6 === imgWidth) { + // It's 1x6 + size = imgWidth + slices = [0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5] + } else if (imgWidth / 3 === imgHeight / 2) { + // It's 3x2 + size = imgWidth / 3 + slices = [0, 0, 1, 0, 2, 0, 0, 1, 1, 1, 2, 1] + } else if (imgWidth / 2 === imgHeight / 3) { + // It's 2x3 + size = imgWidth / 2 + slices = [0, 0, 1, 0, 0, 1, 1, 1, 0, 2, 1, 2] + } else { + throw ( + "can't figure out cube map from element: " + + (element.src ? element.src : element.nodeName) + ) + } + const ctx = getShared2DContext() + if (ctx) { + ctx.canvas.width = size + ctx.canvas.height = size + width = size + height = size + getCubeFacesWithNdx(gl, options).forEach(function (f) { + const xOffset = slices[f.ndx * 2 + 0] * size + const yOffset = slices[f.ndx * 2 + 1] * size + ctx.drawImage( + element, + xOffset, + yOffset, + size, + size, + 0, + 0, + size, + size + ) + gl.texImage2D( + f.face, + level, + internalFormat, + format, + type, + ctx.canvas + ) + }) + // Free up the canvas memory + ctx.canvas.width = 1 + ctx.canvas.height = 1 + } else if (typeof createImageBitmap !== 'undefined') { + // NOTE: It seems like we should prefer ImageBitmap because unlike canvas it's + // note lossy? (alpha is not premultiplied? although I'm not sure what + width = size + height = size + getCubeFacesWithNdx(gl, options).forEach(function (f) { + const xOffset = slices[f.ndx * 2 + 0] * size + const yOffset = slices[f.ndx * 2 + 1] * size + // We can't easily use a default texture color here as it would have to match + // the type across all faces where as with a 2D one there's only one face + // so we're replacing everything all at once. It also has to be the correct size. + // On the other hand we need all faces to be the same size so as one face loads + // the rest match else the texture will be un-renderable. + gl.texImage2D( + f.face, + level, + internalFormat, + size, + size, + 0, + format, + type, + null + ) + createImageBitmap(element, xOffset, yOffset, size, size, { + premultiplyAlpha: 'none', + colorSpaceConversion: 'none', + }).then(function (imageBitmap) { + setPackState(gl, options) + gl.bindTexture(target, tex) + gl.texImage2D( + f.face, + level, + internalFormat, + format, + type, + imageBitmap + ) + if ( + shouldAutomaticallySetTextureFilteringForSize(options) + ) { + setTextureFilteringForSize( + gl, + tex, + options, + width, + height, + internalFormat + ) + } + }) + }) + } + } else if (target === TEXTURE_3D$1 || target === TEXTURE_2D_ARRAY$1) { + const smallest = Math.min(element.width, element.height) + const largest = Math.max(element.width, element.height) + const depth = largest / smallest + if (depth % 1 !== 0) { + throw 'can not compute 3D dimensions of element' + } + const xMult = element.width === largest ? 1 : 0 + const yMult = element.height === largest ? 1 : 0 + gl.pixelStorei(UNPACK_ALIGNMENT, 1) + gl.pixelStorei(UNPACK_ROW_LENGTH, element.width) + gl.pixelStorei(UNPACK_IMAGE_HEIGHT, 0) + gl.pixelStorei(UNPACK_SKIP_IMAGES, 0) + gl.texImage3D( + target, + level, + internalFormat, + smallest, + smallest, + smallest, + 0, + format, + type, + null + ) + for (let d = 0; d < depth; ++d) { + const srcX = d * smallest * xMult + const srcY = d * smallest * yMult + gl.pixelStorei(UNPACK_SKIP_PIXELS, srcX) + gl.pixelStorei(UNPACK_SKIP_ROWS, srcY) + gl.texSubImage3D( + target, + level, + 0, + 0, + d, + smallest, + smallest, + 1, + format, + type, + element + ) + } + setSkipStateToDefault(gl) } else { - throw "can't figure out cube map from element: " + (element.src ? element.src : element.nodeName); - } - const ctx = getShared2DContext(); - if (ctx) { - ctx.canvas.width = size; - ctx.canvas.height = size; - width = size; - height = size; - getCubeFacesWithNdx(gl, options).forEach(function(f) { - const xOffset = slices[f.ndx * 2 + 0] * size; - const yOffset = slices[f.ndx * 2 + 1] * size; - ctx.drawImage(element, xOffset, yOffset, size, size, 0, 0, size, size); - gl.texImage2D(f.face, level, internalFormat, format, type, ctx.canvas); - }); - // Free up the canvas memory - ctx.canvas.width = 1; - ctx.canvas.height = 1; - } else if (typeof createImageBitmap !== 'undefined') { - // NOTE: It seems like we should prefer ImageBitmap because unlike canvas it's - // note lossy? (alpha is not premultiplied? although I'm not sure what - width = size; - height = size; - getCubeFacesWithNdx(gl, options).forEach(function(f) { - const xOffset = slices[f.ndx * 2 + 0] * size; - const yOffset = slices[f.ndx * 2 + 1] * size; - // We can't easily use a default texture color here as it would have to match - // the type across all faces where as with a 2D one there's only one face - // so we're replacing everything all at once. It also has to be the correct size. - // On the other hand we need all faces to be the same size so as one face loads - // the rest match else the texture will be un-renderable. - gl.texImage2D(f.face, level, internalFormat, size, size, 0, format, type, null); - createImageBitmap(element, xOffset, yOffset, size, size, { - premultiplyAlpha: 'none', - colorSpaceConversion: 'none', - }) - .then(function(imageBitmap) { - setPackState(gl, options); - gl.bindTexture(target, tex); - gl.texImage2D(f.face, level, internalFormat, format, type, imageBitmap); - if (shouldAutomaticallySetTextureFilteringForSize(options)) { - setTextureFilteringForSize(gl, tex, options, width, height, internalFormat); - } - }); - }); - } - } else if (target === TEXTURE_3D$1 || target === TEXTURE_2D_ARRAY$1) { - const smallest = Math.min(element.width, element.height); - const largest = Math.max(element.width, element.height); - const depth = largest / smallest; - if (depth % 1 !== 0) { - throw "can not compute 3D dimensions of element"; - } - const xMult = element.width === largest ? 1 : 0; - const yMult = element.height === largest ? 1 : 0; - gl.pixelStorei(UNPACK_ALIGNMENT, 1); - gl.pixelStorei(UNPACK_ROW_LENGTH, element.width); - gl.pixelStorei(UNPACK_IMAGE_HEIGHT, 0); - gl.pixelStorei(UNPACK_SKIP_IMAGES, 0); - gl.texImage3D(target, level, internalFormat, smallest, smallest, smallest, 0, format, type, null); - for (let d = 0; d < depth; ++d) { - const srcX = d * smallest * xMult; - const srcY = d * smallest * yMult; - gl.pixelStorei(UNPACK_SKIP_PIXELS, srcX); - gl.pixelStorei(UNPACK_SKIP_ROWS, srcY); - gl.texSubImage3D(target, level, 0, 0, d, smallest, smallest, 1, format, type, element); - } - setSkipStateToDefault(gl); - } else { - gl.texImage2D(target, level, internalFormat, format, type, element); - } - if (shouldAutomaticallySetTextureFilteringForSize(options)) { - setTextureFilteringForSize(gl, tex, options, width, height, internalFormat); - } - setTextureParameters(gl, tex, options); -} - -function noop() { + gl.texImage2D(target, level, internalFormat, format, type, element) + } + if (shouldAutomaticallySetTextureFilteringForSize(options)) { + setTextureFilteringForSize( + gl, + tex, + options, + width, + height, + internalFormat + ) + } + setTextureParameters(gl, tex, options) } +function noop() {} + /** * Checks whether the url's origin is the same so that we can set the `crossOrigin` * @param {string} url url to image @@ -5999,24 +6572,26 @@ function noop() { * @private */ function urlIsSameOrigin(url) { - if (typeof document !== 'undefined') { - // for IE really - const a = document.createElement('a'); - a.href = url; - return a.hostname === location.hostname && - a.port === location.port && - a.protocol === location.protocol; - } else { - const localOrigin = (new URL(location.href)).origin; - const urlOrigin = (new URL(url, location.href)).origin; - return urlOrigin === localOrigin; - } + if (typeof document !== 'undefined') { + // for IE really + const a = document.createElement('a') + a.href = url + return ( + a.hostname === location.hostname && + a.port === location.port && + a.protocol === location.protocol + ) + } else { + const localOrigin = new URL(location.href).origin + const urlOrigin = new URL(url, location.href).origin + return urlOrigin === localOrigin + } } function setToAnonymousIfUndefinedAndURLIsNotSameOrigin(url, crossOrigin) { - return crossOrigin === undefined && !urlIsSameOrigin(url) - ? 'anonymous' - : crossOrigin; + return crossOrigin === undefined && !urlIsSameOrigin(url) + ? 'anonymous' + : crossOrigin } /** @@ -6029,73 +6604,81 @@ function setToAnonymousIfUndefinedAndURLIsNotSameOrigin(url, crossOrigin) { * @private */ function loadImage(url, crossOrigin, callback) { - callback = callback || noop; - let img; - crossOrigin = crossOrigin !== undefined ? crossOrigin : defaults$1.crossOrigin; - crossOrigin = setToAnonymousIfUndefinedAndURLIsNotSameOrigin(url, crossOrigin); - if (typeof Image !== 'undefined') { - img = new Image(); - if (crossOrigin !== undefined) { - img.crossOrigin = crossOrigin; - } - - const clearEventHandlers = function clearEventHandlers() { - img.removeEventListener('error', onError); // eslint-disable-line - img.removeEventListener('load', onLoad); // eslint-disable-line - img = null; - }; - - const onError = function onError() { - const msg = "couldn't load image: " + url; - error$1(msg); - callback(msg, img); - clearEventHandlers(); - }; - - const onLoad = function onLoad() { - callback(null, img); - clearEventHandlers(); - }; - - img.addEventListener('error', onError); - img.addEventListener('load', onLoad); - img.src = url; - return img; - } else if (typeof ImageBitmap !== 'undefined') { - let err; - let bm; - const cb = function cb() { - callback(err, bm); - }; - - const options = {}; - if (crossOrigin) { - options.mode = 'cors'; // TODO: not sure how to translate image.crossOrigin - } - fetch(url, options).then(function(response) { - if (!response.ok) { - throw response; - } - return response.blob(); - }).then(function(blob) { - return createImageBitmap(blob, { - premultiplyAlpha: 'none', - colorSpaceConversion: 'none', - }); - }).then(function(bitmap) { - // not sure if this works. We don't want - // to catch the user's error. So, call - // the callback in a timeout so we're - // not in this scope inside the promise. - bm = bitmap; - setTimeout(cb); - }).catch(function(e) { - err = e; - setTimeout(cb); - }); - img = null; - } - return img; + callback = callback || noop + let img + crossOrigin = + crossOrigin !== undefined ? crossOrigin : defaults$1.crossOrigin + crossOrigin = setToAnonymousIfUndefinedAndURLIsNotSameOrigin( + url, + crossOrigin + ) + if (typeof Image !== 'undefined') { + img = new Image() + if (crossOrigin !== undefined) { + img.crossOrigin = crossOrigin + } + + const clearEventHandlers = function clearEventHandlers() { + img.removeEventListener('error', onError) // eslint-disable-line + img.removeEventListener('load', onLoad) // eslint-disable-line + img = null + } + + const onError = function onError() { + const msg = "couldn't load image: " + url + error$1(msg) + callback(msg, img) + clearEventHandlers() + } + + const onLoad = function onLoad() { + callback(null, img) + clearEventHandlers() + } + + img.addEventListener('error', onError) + img.addEventListener('load', onLoad) + img.src = url + return img + } else if (typeof ImageBitmap !== 'undefined') { + let err + let bm + const cb = function cb() { + callback(err, bm) + } + + const options = {} + if (crossOrigin) { + options.mode = 'cors' // TODO: not sure how to translate image.crossOrigin + } + fetch(url, options) + .then(function (response) { + if (!response.ok) { + throw response + } + return response.blob() + }) + .then(function (blob) { + return createImageBitmap(blob, { + premultiplyAlpha: 'none', + colorSpaceConversion: 'none', + }) + }) + .then(function (bitmap) { + // not sure if this works. We don't want + // to catch the user's error. So, call + // the callback in a timeout so we're + // not in this scope inside the promise. + bm = bitmap + setTimeout(cb) + }) + .catch(function (e) { + err = e + setTimeout(cb) + }) + img = null + } + return img } /** @@ -6106,9 +6689,11 @@ function loadImage(url, crossOrigin, callback) { * @private */ function isTexImageSource(obj) { - return (typeof ImageBitmap !== 'undefined' && obj instanceof ImageBitmap) || - (typeof ImageData !== 'undefined' && obj instanceof ImageData) || - (typeof HTMLElement !== 'undefined' && obj instanceof HTMLElement); + return ( + (typeof ImageBitmap !== 'undefined' && obj instanceof ImageBitmap) || + (typeof ImageData !== 'undefined' && obj instanceof ImageData) || + (typeof HTMLElement !== 'undefined' && obj instanceof HTMLElement) + ) } /** @@ -6123,14 +6708,14 @@ function isTexImageSource(obj) { * @private */ function loadAndUseImage(obj, crossOrigin, callback) { - if (isTexImageSource(obj)) { - setTimeout(function() { - callback(null, obj); - }); - return obj; - } + if (isTexImageSource(obj)) { + setTimeout(function () { + callback(null, obj) + }) + return obj + } - return loadImage(obj, crossOrigin, callback); + return loadImage(obj, crossOrigin, callback) } /** @@ -6144,24 +6729,55 @@ function loadAndUseImage(obj, crossOrigin, callback) { * @private */ function setTextureTo1PixelColor(gl, tex, options) { - options = options || defaults$1.textureOptions; - const target = options.target || TEXTURE_2D$2; - gl.bindTexture(target, tex); - if (options.color === false) { - return; - } - // Assume it's a URL - // Put 1x1 pixels in texture. That makes it renderable immediately regardless of filtering. - const color = make1Pixel(options.color); - if (target === TEXTURE_CUBE_MAP$1) { - for (let ii = 0; ii < 6; ++ii) { - gl.texImage2D(TEXTURE_CUBE_MAP_POSITIVE_X + ii, 0, RGBA$1, 1, 1, 0, RGBA$1, UNSIGNED_BYTE$1, color); - } - } else if (target === TEXTURE_3D$1 || target === TEXTURE_2D_ARRAY$1) { - gl.texImage3D(target, 0, RGBA$1, 1, 1, 1, 0, RGBA$1, UNSIGNED_BYTE$1, color); - } else { - gl.texImage2D(target, 0, RGBA$1, 1, 1, 0, RGBA$1, UNSIGNED_BYTE$1, color); - } + options = options || defaults$1.textureOptions + const target = options.target || TEXTURE_2D$2 + gl.bindTexture(target, tex) + if (options.color === false) { + return + } + // Assume it's a URL + // Put 1x1 pixels in texture. That makes it renderable immediately regardless of filtering. + const color = make1Pixel(options.color) + if (target === TEXTURE_CUBE_MAP$1) { + for (let ii = 0; ii < 6; ++ii) { + gl.texImage2D( + TEXTURE_CUBE_MAP_POSITIVE_X + ii, + 0, + RGBA$1, + 1, + 1, + 0, + RGBA$1, + UNSIGNED_BYTE$1, + color + ) + } + } else if (target === TEXTURE_3D$1 || target === TEXTURE_2D_ARRAY$1) { + gl.texImage3D( + target, + 0, + RGBA$1, + 1, + 1, + 1, + 0, + RGBA$1, + UNSIGNED_BYTE$1, + color + ) + } else { + gl.texImage2D( + target, + 0, + RGBA$1, + 1, + 1, + 0, + RGBA$1, + UNSIGNED_BYTE$1, + color + ) + } } /** @@ -6226,20 +6842,24 @@ function setTextureTo1PixelColor(gl, tex, options) { * @memberOf module:twgl/textures */ function loadTextureFromUrl(gl, tex, options, callback) { - callback = callback || noop; - options = options || defaults$1.textureOptions; - setTextureTo1PixelColor(gl, tex, options); - // Because it's async we need to copy the options. - options = Object.assign({}, options); - const img = loadAndUseImage(options.src, options.crossOrigin, function(err, img) { - if (err) { - callback(err, tex, img); - } else { - setTextureFromElement(gl, tex, img, options); - callback(null, tex, img); - } - }); - return img; + callback = callback || noop + options = options || defaults$1.textureOptions + setTextureTo1PixelColor(gl, tex, options) + // Because it's async we need to copy the options. + options = Object.assign({}, options) + const img = loadAndUseImage( + options.src, + options.crossOrigin, + function (err, img) { + if (err) { + callback(err, tex, img) + } else { + setTextureFromElement(gl, tex, img, options) + callback(null, tex, img) + } + } + ) + return img } /** @@ -6252,69 +6872,85 @@ function loadTextureFromUrl(gl, tex, options, callback) { * be non null if there was an error. * @memberOf module:twgl/textures * @private - */ -function loadCubemapFromUrls(gl, tex, options, callback) { - callback = callback || noop; - const urls = options.src; - if (urls.length !== 6) { - throw "there must be 6 urls for a cubemap"; - } - const level = options.level || 0; - const internalFormat = options.internalFormat || options.format || RGBA$1; - const formatType = getFormatAndTypeForInternalFormat(internalFormat); - const format = options.format || formatType.format; - const type = options.type || UNSIGNED_BYTE$1; - const target = options.target || TEXTURE_2D$2; - if (target !== TEXTURE_CUBE_MAP$1) { - throw "target must be TEXTURE_CUBE_MAP"; - } - setTextureTo1PixelColor(gl, tex, options); - // Because it's async we need to copy the options. - options = Object.assign({}, options); - let numToLoad = 6; - const errors = []; - const faces = getCubeFaceOrder(gl, options); - let imgs; // eslint-disable-line - - function uploadImg(faceTarget) { - return function(err, img) { - --numToLoad; - if (err) { - errors.push(err); - } else { - if (img.width !== img.height) { - errors.push("cubemap face img is not a square: " + img.src); - } else { - setPackState(gl, options); - gl.bindTexture(target, tex); - - // So assuming this is the first image we now have one face that's img sized - // and 5 faces that are 1x1 pixel so size the other faces - if (numToLoad === 5) { - // use the default order - getCubeFaceOrder().forEach(function(otherTarget) { - // Should we re-use the same face or a color? - gl.texImage2D(otherTarget, level, internalFormat, format, type, img); - }); - } else { - gl.texImage2D(faceTarget, level, internalFormat, format, type, img); - } - - if (shouldAutomaticallySetTextureFilteringForSize(options)) { - gl.generateMipmap(target); - } + */ +function loadCubemapFromUrls(gl, tex, options, callback) { + callback = callback || noop + const urls = options.src + if (urls.length !== 6) { + throw 'there must be 6 urls for a cubemap' + } + const level = options.level || 0 + const internalFormat = options.internalFormat || options.format || RGBA$1 + const formatType = getFormatAndTypeForInternalFormat(internalFormat) + const format = options.format || formatType.format + const type = options.type || UNSIGNED_BYTE$1 + const target = options.target || TEXTURE_2D$2 + if (target !== TEXTURE_CUBE_MAP$1) { + throw 'target must be TEXTURE_CUBE_MAP' + } + setTextureTo1PixelColor(gl, tex, options) + // Because it's async we need to copy the options. + options = Object.assign({}, options) + let numToLoad = 6 + const errors = [] + const faces = getCubeFaceOrder(gl, options) + let imgs // eslint-disable-line + + function uploadImg(faceTarget) { + return function (err, img) { + --numToLoad + if (err) { + errors.push(err) + } else { + if (img.width !== img.height) { + errors.push('cubemap face img is not a square: ' + img.src) + } else { + setPackState(gl, options) + gl.bindTexture(target, tex) + + // So assuming this is the first image we now have one face that's img sized + // and 5 faces that are 1x1 pixel so size the other faces + if (numToLoad === 5) { + // use the default order + getCubeFaceOrder().forEach(function (otherTarget) { + // Should we re-use the same face or a color? + gl.texImage2D( + otherTarget, + level, + internalFormat, + format, + type, + img + ) + }) + } else { + gl.texImage2D( + faceTarget, + level, + internalFormat, + format, + type, + img + ) + } + + if ( + shouldAutomaticallySetTextureFilteringForSize(options) + ) { + gl.generateMipmap(target) + } + } + } + + if (numToLoad === 0) { + callback(errors.length ? errors : undefined, tex, imgs) + } } - } - - if (numToLoad === 0) { - callback(errors.length ? errors : undefined, tex, imgs); - } - }; - } + } - imgs = urls.map(function(url, ndx) { - return loadAndUseImage(url, options.crossOrigin, uploadImg(faces[ndx])); - }); + imgs = urls.map(function (url, ndx) { + return loadAndUseImage(url, options.crossOrigin, uploadImg(faces[ndx])) + }) } /** @@ -6338,82 +6974,117 @@ function loadCubemapFromUrls(gl, tex, options, callback) { * @private */ function loadSlicesFromUrls(gl, tex, options, callback) { - callback = callback || noop; - const urls = options.src; - const internalFormat = options.internalFormat || options.format || RGBA$1; - const formatType = getFormatAndTypeForInternalFormat(internalFormat); - const format = options.format || formatType.format; - const type = options.type || UNSIGNED_BYTE$1; - const target = options.target || TEXTURE_2D_ARRAY$1; - if (target !== TEXTURE_3D$1 && target !== TEXTURE_2D_ARRAY$1) { - throw "target must be TEXTURE_3D or TEXTURE_2D_ARRAY"; - } - setTextureTo1PixelColor(gl, tex, options); - // Because it's async we need to copy the options. - options = Object.assign({}, options); - let numToLoad = urls.length; - const errors = []; - let imgs; // eslint-disable-line - const level = options.level || 0; - let width = options.width; - let height = options.height; - const depth = urls.length; - let firstImage = true; - - function uploadImg(slice) { - return function(err, img) { - --numToLoad; - if (err) { - errors.push(err); - } else { - setPackState(gl, options); - gl.bindTexture(target, tex); - - if (firstImage) { - firstImage = false; - width = options.width || img.width; - height = options.height || img.height; - gl.texImage3D(target, level, internalFormat, width, height, depth, 0, format, type, null); - - // put it in every slice otherwise some slices will be 0,0,0,0 - for (let s = 0; s < depth; ++s) { - gl.texSubImage3D(target, level, 0, 0, s, width, height, 1, format, type, img); - } - } else { - let src = img; - let ctx; - if (img.width !== width || img.height !== height) { - // Size the image to fix - ctx = getShared2DContext(); - src = ctx.canvas; - ctx.canvas.width = width; - ctx.canvas.height = height; - ctx.drawImage(img, 0, 0, width, height); - } - - gl.texSubImage3D(target, level, 0, 0, slice, width, height, 1, format, type, src); - - // free the canvas memory - if (ctx && src === ctx.canvas) { - ctx.canvas.width = 0; - ctx.canvas.height = 0; - } - } - - if (shouldAutomaticallySetTextureFilteringForSize(options)) { - gl.generateMipmap(target); + callback = callback || noop + const urls = options.src + const internalFormat = options.internalFormat || options.format || RGBA$1 + const formatType = getFormatAndTypeForInternalFormat(internalFormat) + const format = options.format || formatType.format + const type = options.type || UNSIGNED_BYTE$1 + const target = options.target || TEXTURE_2D_ARRAY$1 + if (target !== TEXTURE_3D$1 && target !== TEXTURE_2D_ARRAY$1) { + throw 'target must be TEXTURE_3D or TEXTURE_2D_ARRAY' + } + setTextureTo1PixelColor(gl, tex, options) + // Because it's async we need to copy the options. + options = Object.assign({}, options) + let numToLoad = urls.length + const errors = [] + let imgs // eslint-disable-line + const level = options.level || 0 + let width = options.width + let height = options.height + const depth = urls.length + let firstImage = true + + function uploadImg(slice) { + return function (err, img) { + --numToLoad + if (err) { + errors.push(err) + } else { + setPackState(gl, options) + gl.bindTexture(target, tex) + + if (firstImage) { + firstImage = false + width = options.width || img.width + height = options.height || img.height + gl.texImage3D( + target, + level, + internalFormat, + width, + height, + depth, + 0, + format, + type, + null + ) + + // put it in every slice otherwise some slices will be 0,0,0,0 + for (let s = 0; s < depth; ++s) { + gl.texSubImage3D( + target, + level, + 0, + 0, + s, + width, + height, + 1, + format, + type, + img + ) + } + } else { + let src = img + let ctx + if (img.width !== width || img.height !== height) { + // Size the image to fix + ctx = getShared2DContext() + src = ctx.canvas + ctx.canvas.width = width + ctx.canvas.height = height + ctx.drawImage(img, 0, 0, width, height) + } + + gl.texSubImage3D( + target, + level, + 0, + 0, + slice, + width, + height, + 1, + format, + type, + src + ) + + // free the canvas memory + if (ctx && src === ctx.canvas) { + ctx.canvas.width = 0 + ctx.canvas.height = 0 + } + } + + if (shouldAutomaticallySetTextureFilteringForSize(options)) { + gl.generateMipmap(target) + } + } + + if (numToLoad === 0) { + callback(errors.length ? errors : undefined, tex, imgs) + } } - } - - if (numToLoad === 0) { - callback(errors.length ? errors : undefined, tex, imgs); - } - }; - } + } - imgs = urls.map(function(url, ndx) { - return loadAndUseImage(url, options.crossOrigin, uploadImg(ndx)); - }); + imgs = urls.map(function (url, ndx) { + return loadAndUseImage(url, options.crossOrigin, uploadImg(ndx)) + }) } /** @@ -6427,80 +7098,136 @@ function loadSlicesFromUrls(gl, tex, options, callback) { * @memberOf module:twgl/textures */ function setTextureFromArray(gl, tex, src, options) { - options = options || defaults$1.textureOptions; - const target = options.target || TEXTURE_2D$2; - gl.bindTexture(target, tex); - let width = options.width; - let height = options.height; - let depth = options.depth; - const level = options.level || 0; - const internalFormat = options.internalFormat || options.format || RGBA$1; - const formatType = getFormatAndTypeForInternalFormat(internalFormat); - const format = options.format || formatType.format; - const type = options.type || getTextureTypeForArrayType(gl, src, formatType.type); - if (!isArrayBuffer(src)) { - const Type = getTypedArrayTypeForGLType(type); - src = new Type(src); - } else if (src instanceof Uint8ClampedArray) { - src = new Uint8Array(src.buffer); - } - - const bytesPerElement = getBytesPerElementForInternalFormat(internalFormat, type); - const numElements = src.byteLength / bytesPerElement; // TODO: check UNPACK_ALIGNMENT? - if (numElements % 1) { - throw "length wrong size for format: " + glEnumToString(gl, format); - } - let dimensions; - if (target === TEXTURE_3D$1 || target === TEXTURE_2D_ARRAY$1) { - if (!width && !height && !depth) { - const size = Math.cbrt(numElements); - if (size % 1 !== 0) { - throw "can't guess cube size of array of numElements: " + numElements; - } - width = size; - height = size; - depth = size; - } else if (width && (!height || !depth)) { - dimensions = guessDimensions(gl, target, height, depth, numElements / width); - height = dimensions.width; - depth = dimensions.height; - } else if (height && (!width || !depth)) { - dimensions = guessDimensions(gl, target, width, depth, numElements / height); - width = dimensions.width; - depth = dimensions.height; + options = options || defaults$1.textureOptions + const target = options.target || TEXTURE_2D$2 + gl.bindTexture(target, tex) + let width = options.width + let height = options.height + let depth = options.depth + const level = options.level || 0 + const internalFormat = options.internalFormat || options.format || RGBA$1 + const formatType = getFormatAndTypeForInternalFormat(internalFormat) + const format = options.format || formatType.format + const type = + options.type || getTextureTypeForArrayType(gl, src, formatType.type) + if (!isArrayBuffer(src)) { + const Type = getTypedArrayTypeForGLType(type) + src = new Type(src) + } else if (src instanceof Uint8ClampedArray) { + src = new Uint8Array(src.buffer) + } + + const bytesPerElement = getBytesPerElementForInternalFormat( + internalFormat, + type + ) + const numElements = src.byteLength / bytesPerElement // TODO: check UNPACK_ALIGNMENT? + if (numElements % 1) { + throw 'length wrong size for format: ' + glEnumToString(gl, format) + } + let dimensions + if (target === TEXTURE_3D$1 || target === TEXTURE_2D_ARRAY$1) { + if (!width && !height && !depth) { + const size = Math.cbrt(numElements) + if (size % 1 !== 0) { + throw ( + "can't guess cube size of array of numElements: " + + numElements + ) + } + width = size + height = size + depth = size + } else if (width && (!height || !depth)) { + dimensions = guessDimensions( + gl, + target, + height, + depth, + numElements / width + ) + height = dimensions.width + depth = dimensions.height + } else if (height && (!width || !depth)) { + dimensions = guessDimensions( + gl, + target, + width, + depth, + numElements / height + ) + width = dimensions.width + depth = dimensions.height + } else { + dimensions = guessDimensions( + gl, + target, + width, + height, + numElements / depth + ) + width = dimensions.width + height = dimensions.height + } + } else { + dimensions = guessDimensions(gl, target, width, height, numElements) + width = dimensions.width + height = dimensions.height + } + setSkipStateToDefault(gl) + gl.pixelStorei(UNPACK_ALIGNMENT, options.unpackAlignment || 1) + setPackState(gl, options) + if (target === TEXTURE_CUBE_MAP$1) { + const elementsPerElement = bytesPerElement / src.BYTES_PER_ELEMENT + const faceSize = (numElements / 6) * elementsPerElement + + getCubeFacesWithNdx(gl, options).forEach(f => { + const offset = faceSize * f.ndx + const data = src.subarray(offset, offset + faceSize) + gl.texImage2D( + f.face, + level, + internalFormat, + width, + height, + 0, + format, + type, + data + ) + }) + } else if (target === TEXTURE_3D$1 || target === TEXTURE_2D_ARRAY$1) { + gl.texImage3D( + target, + level, + internalFormat, + width, + height, + depth, + 0, + format, + type, + src + ) } else { - dimensions = guessDimensions(gl, target, width, height, numElements / depth); - width = dimensions.width; - height = dimensions.height; - } - } else { - dimensions = guessDimensions(gl, target, width, height, numElements); - width = dimensions.width; - height = dimensions.height; - } - setSkipStateToDefault(gl); - gl.pixelStorei(UNPACK_ALIGNMENT, options.unpackAlignment || 1); - setPackState(gl, options); - if (target === TEXTURE_CUBE_MAP$1) { - const elementsPerElement = bytesPerElement / src.BYTES_PER_ELEMENT; - const faceSize = numElements / 6 * elementsPerElement; - - getCubeFacesWithNdx(gl, options).forEach(f => { - const offset = faceSize * f.ndx; - const data = src.subarray(offset, offset + faceSize); - gl.texImage2D(f.face, level, internalFormat, width, height, 0, format, type, data); - }); - } else if (target === TEXTURE_3D$1 || target === TEXTURE_2D_ARRAY$1) { - gl.texImage3D(target, level, internalFormat, width, height, depth, 0, format, type, src); - } else { - gl.texImage2D(target, level, internalFormat, width, height, 0, format, type, src); - } - return { - width: width, - height: height, - depth: depth, - type: type, - }; + gl.texImage2D( + target, + level, + internalFormat, + width, + height, + 0, + format, + type, + src + ) + } + return { + width: width, + height: height, + depth: depth, + type: type, + } } /** @@ -6512,23 +7239,54 @@ function setTextureFromArray(gl, tex, src, options) { * @memberOf module:twgl/textures */ function setEmptyTexture(gl, tex, options) { - const target = options.target || TEXTURE_2D$2; - gl.bindTexture(target, tex); - const level = options.level || 0; - const internalFormat = options.internalFormat || options.format || RGBA$1; - const formatType = getFormatAndTypeForInternalFormat(internalFormat); - const format = options.format || formatType.format; - const type = options.type || formatType.type; - setPackState(gl, options); - if (target === TEXTURE_CUBE_MAP$1) { - for (let ii = 0; ii < 6; ++ii) { - gl.texImage2D(TEXTURE_CUBE_MAP_POSITIVE_X + ii, level, internalFormat, options.width, options.height, 0, format, type, null); - } - } else if (target === TEXTURE_3D$1 || target === TEXTURE_2D_ARRAY$1) { - gl.texImage3D(target, level, internalFormat, options.width, options.height, options.depth, 0, format, type, null); - } else { - gl.texImage2D(target, level, internalFormat, options.width, options.height, 0, format, type, null); - } + const target = options.target || TEXTURE_2D$2 + gl.bindTexture(target, tex) + const level = options.level || 0 + const internalFormat = options.internalFormat || options.format || RGBA$1 + const formatType = getFormatAndTypeForInternalFormat(internalFormat) + const format = options.format || formatType.format + const type = options.type || formatType.type + setPackState(gl, options) + if (target === TEXTURE_CUBE_MAP$1) { + for (let ii = 0; ii < 6; ++ii) { + gl.texImage2D( + TEXTURE_CUBE_MAP_POSITIVE_X + ii, + level, + internalFormat, + options.width, + options.height, + 0, + format, + type, + null + ) + } + } else if (target === TEXTURE_3D$1 || target === TEXTURE_2D_ARRAY$1) { + gl.texImage3D( + target, + level, + internalFormat, + options.width, + options.height, + options.depth, + 0, + format, + type, + null + ) + } else { + gl.texImage2D( + target, + level, + internalFormat, + options.width, + options.height, + 0, + format, + type, + null + ) + } } /** @@ -6544,55 +7302,66 @@ function setEmptyTexture(gl, tex, options) { * @memberOf module:twgl/textures */ function createTexture(gl, options, callback) { - callback = callback || noop; - options = options || defaults$1.textureOptions; - const tex = gl.createTexture(); - const target = options.target || TEXTURE_2D$2; - let width = options.width || 1; - let height = options.height || 1; - const internalFormat = options.internalFormat || RGBA$1; - gl.bindTexture(target, tex); - if (target === TEXTURE_CUBE_MAP$1) { - // this should have been the default for cubemaps :( - gl.texParameteri(target, TEXTURE_WRAP_S, CLAMP_TO_EDGE$1); - gl.texParameteri(target, TEXTURE_WRAP_T, CLAMP_TO_EDGE$1); - } - let src = options.src; - if (src) { - if (typeof src === "function") { - src = src(gl, options); - } - if (typeof (src) === "string") { - loadTextureFromUrl(gl, tex, options, callback); - } else if (isArrayBuffer(src) || - (Array.isArray(src) && ( - typeof src[0] === 'number' || + callback = callback || noop + options = options || defaults$1.textureOptions + const tex = gl.createTexture() + const target = options.target || TEXTURE_2D$2 + let width = options.width || 1 + let height = options.height || 1 + const internalFormat = options.internalFormat || RGBA$1 + gl.bindTexture(target, tex) + if (target === TEXTURE_CUBE_MAP$1) { + // this should have been the default for cubemaps :( + gl.texParameteri(target, TEXTURE_WRAP_S, CLAMP_TO_EDGE$1) + gl.texParameteri(target, TEXTURE_WRAP_T, CLAMP_TO_EDGE$1) + } + let src = options.src + if (src) { + if (typeof src === 'function') { + src = src(gl, options) + } + if (typeof src === 'string') { + loadTextureFromUrl(gl, tex, options, callback) + } else if ( + isArrayBuffer(src) || + (Array.isArray(src) && + (typeof src[0] === 'number' || Array.isArray(src[0]) || - isArrayBuffer(src[0])) - ) - ) { - const dimensions = setTextureFromArray(gl, tex, src, options); - width = dimensions.width; - height = dimensions.height; - } else if (Array.isArray(src) && (typeof (src[0]) === 'string' || isTexImageSource(src[0]))) { - if (target === TEXTURE_CUBE_MAP$1) { - loadCubemapFromUrls(gl, tex, options, callback); - } else { - loadSlicesFromUrls(gl, tex, options, callback); - } - } else { // if (isTexImageSource(src)) - setTextureFromElement(gl, tex, src, options); - width = src.width; - height = src.height; - } - } else { - setEmptyTexture(gl, tex, options); - } - if (shouldAutomaticallySetTextureFilteringForSize(options)) { - setTextureFilteringForSize(gl, tex, options, width, height, internalFormat); - } - setTextureParameters(gl, tex, options); - return tex; + isArrayBuffer(src[0]))) + ) { + const dimensions = setTextureFromArray(gl, tex, src, options) + width = dimensions.width + height = dimensions.height + } else if ( + Array.isArray(src) && + (typeof src[0] === 'string' || isTexImageSource(src[0])) + ) { + if (target === TEXTURE_CUBE_MAP$1) { + loadCubemapFromUrls(gl, tex, options, callback) + } else { + loadSlicesFromUrls(gl, tex, options, callback) + } + } else { + // if (isTexImageSource(src)) + setTextureFromElement(gl, tex, src, options) + width = src.width + height = src.height + } + } else { + setEmptyTexture(gl, tex, options) + } + if (shouldAutomaticallySetTextureFilteringForSize(options)) { + setTextureFilteringForSize( + gl, + tex, + options, + width, + height, + internalFormat + ) + } + setTextureParameters(gl, tex, options) + return tex } /** @@ -6613,33 +7382,68 @@ function createTexture(gl, options, callback) { * @memberOf module:twgl/textures */ function resizeTexture(gl, tex, options, width, height, depth) { - width = width || options.width; - height = height || options.height; - depth = depth || options.depth; - const target = options.target || TEXTURE_2D$2; - gl.bindTexture(target, tex); - const level = options.level || 0; - const internalFormat = options.internalFormat || options.format || RGBA$1; - const formatType = getFormatAndTypeForInternalFormat(internalFormat); - const format = options.format || formatType.format; - let type; - const src = options.src; - if (!src) { - type = options.type || formatType.type; - } else if (isArrayBuffer(src) || (Array.isArray(src) && typeof (src[0]) === 'number')) { - type = options.type || getTextureTypeForArrayType(gl, src, formatType.type); - } else { - type = options.type || formatType.type; - } - if (target === TEXTURE_CUBE_MAP$1) { - for (let ii = 0; ii < 6; ++ii) { - gl.texImage2D(TEXTURE_CUBE_MAP_POSITIVE_X + ii, level, internalFormat, width, height, 0, format, type, null); - } - } else if (target === TEXTURE_3D$1 || target === TEXTURE_2D_ARRAY$1) { - gl.texImage3D(target, level, internalFormat, width, height, depth, 0, format, type, null); - } else { - gl.texImage2D(target, level, internalFormat, width, height, 0, format, type, null); - } + width = width || options.width + height = height || options.height + depth = depth || options.depth + const target = options.target || TEXTURE_2D$2 + gl.bindTexture(target, tex) + const level = options.level || 0 + const internalFormat = options.internalFormat || options.format || RGBA$1 + const formatType = getFormatAndTypeForInternalFormat(internalFormat) + const format = options.format || formatType.format + let type + const src = options.src + if (!src) { + type = options.type || formatType.type + } else if ( + isArrayBuffer(src) || + (Array.isArray(src) && typeof src[0] === 'number') + ) { + type = + options.type || getTextureTypeForArrayType(gl, src, formatType.type) + } else { + type = options.type || formatType.type + } + if (target === TEXTURE_CUBE_MAP$1) { + for (let ii = 0; ii < 6; ++ii) { + gl.texImage2D( + TEXTURE_CUBE_MAP_POSITIVE_X + ii, + level, + internalFormat, + width, + height, + 0, + format, + type, + null + ) + } + } else if (target === TEXTURE_3D$1 || target === TEXTURE_2D_ARRAY$1) { + gl.texImage3D( + target, + level, + internalFormat, + width, + height, + depth, + 0, + format, + type, + null + ) + } else { + gl.texImage2D( + target, + level, + internalFormat, + width, + height, + 0, + format, + type, + null + ) + } } /** @@ -6651,8 +7455,10 @@ function resizeTexture(gl, tex, options, width, height, depth) { * @private */ function isAsyncSrc(src) { - return typeof src === 'string' || - (Array.isArray(src) && typeof src[0] === 'string'); + return ( + typeof src === 'string' || + (Array.isArray(src) && typeof src[0] === 'string') + ) } /** @@ -6731,68 +7537,68 @@ function isAsyncSrc(src) { * @memberOf module:twgl/textures */ function createTextures(gl, textureOptions, callback) { - callback = callback || noop; - let numDownloading = 0; - const errors = []; - const textures = {}; - const images = {}; - - function callCallbackIfReady() { - if (numDownloading === 0) { - setTimeout(function() { - callback(errors.length ? errors : undefined, textures, images); - }, 0); - } - } - - Object.keys(textureOptions).forEach(function(name) { - const options = textureOptions[name]; - let onLoadFn; - if (isAsyncSrc(options.src)) { - onLoadFn = function(err, tex, img) { - images[name] = img; - --numDownloading; - if (err) { - errors.push(err); - } - callCallbackIfReady(); - }; - ++numDownloading; - } - textures[name] = createTexture(gl, options, onLoadFn); - }); - - // queue the callback if there are no images to download. - // We do this because if your code is structured to wait for - // images to download but then you comment out all the async - // images your code would break. - callCallbackIfReady(); - - return textures; -} - -var textures = /*#__PURE__*/Object.freeze({ - __proto__: null, - setTextureDefaults_: setDefaults$1, - createSampler: createSampler, - createSamplers: createSamplers, - setSamplerParameters: setSamplerParameters, - createTexture: createTexture, - setEmptyTexture: setEmptyTexture, - setTextureFromArray: setTextureFromArray, - loadTextureFromUrl: loadTextureFromUrl, - setTextureFromElement: setTextureFromElement, - setTextureFilteringForSize: setTextureFilteringForSize, - setTextureParameters: setTextureParameters, - setDefaultTextureColor: setDefaultTextureColor, - createTextures: createTextures, - resizeTexture: resizeTexture, - canGenerateMipmap: canGenerateMipmap, - canFilter: canFilter, - getNumComponentsForFormat: getNumComponentsForFormat, - getBytesPerElementForInternalFormat: getBytesPerElementForInternalFormat, - getFormatAndTypeForInternalFormat: getFormatAndTypeForInternalFormat -}); + callback = callback || noop + let numDownloading = 0 + const errors = [] + const textures = {} + const images = {} + + function callCallbackIfReady() { + if (numDownloading === 0) { + setTimeout(function () { + callback(errors.length ? errors : undefined, textures, images) + }, 0) + } + } + + Object.keys(textureOptions).forEach(function (name) { + const options = textureOptions[name] + let onLoadFn + if (isAsyncSrc(options.src)) { + onLoadFn = function (err, tex, img) { + images[name] = img + --numDownloading + if (err) { + errors.push(err) + } + callCallbackIfReady() + } + ++numDownloading + } + textures[name] = createTexture(gl, options, onLoadFn) + }) + + // queue the callback if there are no images to download. + // We do this because if your code is structured to wait for + // images to download but then you comment out all the async + // images your code would break. + callCallbackIfReady() + + return textures +} + +var textures = /*#__PURE__*/ Object.freeze({ + __proto__: null, + setTextureDefaults_: setDefaults$1, + createSampler: createSampler, + createSamplers: createSamplers, + setSamplerParameters: setSamplerParameters, + createTexture: createTexture, + setEmptyTexture: setEmptyTexture, + setTextureFromArray: setTextureFromArray, + loadTextureFromUrl: loadTextureFromUrl, + setTextureFromElement: setTextureFromElement, + setTextureFilteringForSize: setTextureFilteringForSize, + setTextureParameters: setTextureParameters, + setDefaultTextureColor: setDefaultTextureColor, + createTextures: createTextures, + resizeTexture: resizeTexture, + canGenerateMipmap: canGenerateMipmap, + canFilter: canFilter, + getNumComponentsForFormat: getNumComponentsForFormat, + getBytesPerElementForInternalFormat: getBytesPerElementForInternalFormat, + getFormatAndTypeForInternalFormat: getFormatAndTypeForInternalFormat, +}) /* * Copyright 2019 Gregg Tavares @@ -6831,475 +7637,736 @@ var textures = /*#__PURE__*/Object.freeze({ * @module twgl/programs */ -const error = error$1; -const warn = warn$1; +const error = error$1 +const warn = warn$1 function getElementById(id) { - return (typeof document !== 'undefined' && document.getElementById) - ? document.getElementById(id) - : null; -} - -const TEXTURE0 = 0x84c0; -const DYNAMIC_DRAW = 0x88e8; - -const ARRAY_BUFFER = 0x8892; -const ELEMENT_ARRAY_BUFFER$1 = 0x8893; -const UNIFORM_BUFFER = 0x8a11; -const TRANSFORM_FEEDBACK_BUFFER = 0x8c8e; - -const TRANSFORM_FEEDBACK = 0x8e22; - -const COMPILE_STATUS = 0x8b81; -const LINK_STATUS = 0x8b82; -const FRAGMENT_SHADER = 0x8b30; -const VERTEX_SHADER = 0x8b31; -const SEPARATE_ATTRIBS = 0x8c8d; - -const ACTIVE_UNIFORMS = 0x8b86; -const ACTIVE_ATTRIBUTES = 0x8b89; -const TRANSFORM_FEEDBACK_VARYINGS = 0x8c83; -const ACTIVE_UNIFORM_BLOCKS = 0x8a36; -const UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER = 0x8a44; -const UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER = 0x8a46; -const UNIFORM_BLOCK_DATA_SIZE = 0x8a40; -const UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES = 0x8a43; - -const FLOAT = 0x1406; -const FLOAT_VEC2 = 0x8B50; -const FLOAT_VEC3 = 0x8B51; -const FLOAT_VEC4 = 0x8B52; -const INT = 0x1404; -const INT_VEC2 = 0x8B53; -const INT_VEC3 = 0x8B54; -const INT_VEC4 = 0x8B55; -const BOOL = 0x8B56; -const BOOL_VEC2 = 0x8B57; -const BOOL_VEC3 = 0x8B58; -const BOOL_VEC4 = 0x8B59; -const FLOAT_MAT2 = 0x8B5A; -const FLOAT_MAT3 = 0x8B5B; -const FLOAT_MAT4 = 0x8B5C; -const SAMPLER_2D = 0x8B5E; -const SAMPLER_CUBE = 0x8B60; -const SAMPLER_3D = 0x8B5F; -const SAMPLER_2D_SHADOW = 0x8B62; -const FLOAT_MAT2x3 = 0x8B65; -const FLOAT_MAT2x4 = 0x8B66; -const FLOAT_MAT3x2 = 0x8B67; -const FLOAT_MAT3x4 = 0x8B68; -const FLOAT_MAT4x2 = 0x8B69; -const FLOAT_MAT4x3 = 0x8B6A; -const SAMPLER_2D_ARRAY = 0x8DC1; -const SAMPLER_2D_ARRAY_SHADOW = 0x8DC4; -const SAMPLER_CUBE_SHADOW = 0x8DC5; -const UNSIGNED_INT = 0x1405; -const UNSIGNED_INT_VEC2 = 0x8DC6; -const UNSIGNED_INT_VEC3 = 0x8DC7; -const UNSIGNED_INT_VEC4 = 0x8DC8; -const INT_SAMPLER_2D = 0x8DCA; -const INT_SAMPLER_3D = 0x8DCB; -const INT_SAMPLER_CUBE = 0x8DCC; -const INT_SAMPLER_2D_ARRAY = 0x8DCF; -const UNSIGNED_INT_SAMPLER_2D = 0x8DD2; -const UNSIGNED_INT_SAMPLER_3D = 0x8DD3; -const UNSIGNED_INT_SAMPLER_CUBE = 0x8DD4; -const UNSIGNED_INT_SAMPLER_2D_ARRAY = 0x8DD7; - -const TEXTURE_2D$1 = 0x0DE1; -const TEXTURE_CUBE_MAP = 0x8513; -const TEXTURE_3D = 0x806F; -const TEXTURE_2D_ARRAY = 0x8C1A; - -const typeMap = {}; + return typeof document !== 'undefined' && document.getElementById + ? document.getElementById(id) + : null +} + +const TEXTURE0 = 0x84c0 +const DYNAMIC_DRAW = 0x88e8 + +const ARRAY_BUFFER = 0x8892 +const ELEMENT_ARRAY_BUFFER$1 = 0x8893 +const UNIFORM_BUFFER = 0x8a11 +const TRANSFORM_FEEDBACK_BUFFER = 0x8c8e + +const TRANSFORM_FEEDBACK = 0x8e22 + +const COMPILE_STATUS = 0x8b81 +const LINK_STATUS = 0x8b82 +const FRAGMENT_SHADER = 0x8b30 +const VERTEX_SHADER = 0x8b31 +const SEPARATE_ATTRIBS = 0x8c8d + +const ACTIVE_UNIFORMS = 0x8b86 +const ACTIVE_ATTRIBUTES = 0x8b89 +const TRANSFORM_FEEDBACK_VARYINGS = 0x8c83 +const ACTIVE_UNIFORM_BLOCKS = 0x8a36 +const UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER = 0x8a44 +const UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER = 0x8a46 +const UNIFORM_BLOCK_DATA_SIZE = 0x8a40 +const UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES = 0x8a43 + +const FLOAT = 0x1406 +const FLOAT_VEC2 = 0x8b50 +const FLOAT_VEC3 = 0x8b51 +const FLOAT_VEC4 = 0x8b52 +const INT = 0x1404 +const INT_VEC2 = 0x8b53 +const INT_VEC3 = 0x8b54 +const INT_VEC4 = 0x8b55 +const BOOL = 0x8b56 +const BOOL_VEC2 = 0x8b57 +const BOOL_VEC3 = 0x8b58 +const BOOL_VEC4 = 0x8b59 +const FLOAT_MAT2 = 0x8b5a +const FLOAT_MAT3 = 0x8b5b +const FLOAT_MAT4 = 0x8b5c +const SAMPLER_2D = 0x8b5e +const SAMPLER_CUBE = 0x8b60 +const SAMPLER_3D = 0x8b5f +const SAMPLER_2D_SHADOW = 0x8b62 +const FLOAT_MAT2x3 = 0x8b65 +const FLOAT_MAT2x4 = 0x8b66 +const FLOAT_MAT3x2 = 0x8b67 +const FLOAT_MAT3x4 = 0x8b68 +const FLOAT_MAT4x2 = 0x8b69 +const FLOAT_MAT4x3 = 0x8b6a +const SAMPLER_2D_ARRAY = 0x8dc1 +const SAMPLER_2D_ARRAY_SHADOW = 0x8dc4 +const SAMPLER_CUBE_SHADOW = 0x8dc5 +const UNSIGNED_INT = 0x1405 +const UNSIGNED_INT_VEC2 = 0x8dc6 +const UNSIGNED_INT_VEC3 = 0x8dc7 +const UNSIGNED_INT_VEC4 = 0x8dc8 +const INT_SAMPLER_2D = 0x8dca +const INT_SAMPLER_3D = 0x8dcb +const INT_SAMPLER_CUBE = 0x8dcc +const INT_SAMPLER_2D_ARRAY = 0x8dcf +const UNSIGNED_INT_SAMPLER_2D = 0x8dd2 +const UNSIGNED_INT_SAMPLER_3D = 0x8dd3 +const UNSIGNED_INT_SAMPLER_CUBE = 0x8dd4 +const UNSIGNED_INT_SAMPLER_2D_ARRAY = 0x8dd7 + +const TEXTURE_2D$1 = 0x0de1 +const TEXTURE_CUBE_MAP = 0x8513 +const TEXTURE_3D = 0x806f +const TEXTURE_2D_ARRAY = 0x8c1a + +const typeMap = {} /** * Returns the corresponding bind point for a given sampler type * @private */ function getBindPointForSamplerType(gl, type) { - return typeMap[type].bindPoint; + return typeMap[type].bindPoint } // This kind of sucks! If you could compose functions as in `var fn = gl[name];` // this code could be a lot smaller but that is sadly really slow (T_T) function floatSetter(gl, location) { - return function(v) { - gl.uniform1f(location, v); - }; + return function (v) { + gl.uniform1f(location, v) + } } function floatArraySetter(gl, location) { - return function(v) { - gl.uniform1fv(location, v); - }; + return function (v) { + gl.uniform1fv(location, v) + } } function floatVec2Setter(gl, location) { - return function(v) { - gl.uniform2fv(location, v); - }; + return function (v) { + gl.uniform2fv(location, v) + } } function floatVec3Setter(gl, location) { - return function(v) { - gl.uniform3fv(location, v); - }; + return function (v) { + gl.uniform3fv(location, v) + } } function floatVec4Setter(gl, location) { - return function(v) { - gl.uniform4fv(location, v); - }; + return function (v) { + gl.uniform4fv(location, v) + } } function intSetter(gl, location) { - return function(v) { - gl.uniform1i(location, v); - }; + return function (v) { + gl.uniform1i(location, v) + } } function intArraySetter(gl, location) { - return function(v) { - gl.uniform1iv(location, v); - }; + return function (v) { + gl.uniform1iv(location, v) + } } function intVec2Setter(gl, location) { - return function(v) { - gl.uniform2iv(location, v); - }; + return function (v) { + gl.uniform2iv(location, v) + } } function intVec3Setter(gl, location) { - return function(v) { - gl.uniform3iv(location, v); - }; + return function (v) { + gl.uniform3iv(location, v) + } } function intVec4Setter(gl, location) { - return function(v) { - gl.uniform4iv(location, v); - }; + return function (v) { + gl.uniform4iv(location, v) + } } function uintSetter(gl, location) { - return function(v) { - gl.uniform1ui(location, v); - }; + return function (v) { + gl.uniform1ui(location, v) + } } function uintArraySetter(gl, location) { - return function(v) { - gl.uniform1uiv(location, v); - }; + return function (v) { + gl.uniform1uiv(location, v) + } } function uintVec2Setter(gl, location) { - return function(v) { - gl.uniform2uiv(location, v); - }; + return function (v) { + gl.uniform2uiv(location, v) + } } function uintVec3Setter(gl, location) { - return function(v) { - gl.uniform3uiv(location, v); - }; + return function (v) { + gl.uniform3uiv(location, v) + } } function uintVec4Setter(gl, location) { - return function(v) { - gl.uniform4uiv(location, v); - }; + return function (v) { + gl.uniform4uiv(location, v) + } } function floatMat2Setter(gl, location) { - return function(v) { - gl.uniformMatrix2fv(location, false, v); - }; + return function (v) { + gl.uniformMatrix2fv(location, false, v) + } } function floatMat3Setter(gl, location) { - return function(v) { - gl.uniformMatrix3fv(location, false, v); - }; + return function (v) { + gl.uniformMatrix3fv(location, false, v) + } } function floatMat4Setter(gl, location) { - return function(v) { - gl.uniformMatrix4fv(location, false, v); - }; + return function (v) { + gl.uniformMatrix4fv(location, false, v) + } } function floatMat23Setter(gl, location) { - return function(v) { - gl.uniformMatrix2x3fv(location, false, v); - }; + return function (v) { + gl.uniformMatrix2x3fv(location, false, v) + } } function floatMat32Setter(gl, location) { - return function(v) { - gl.uniformMatrix3x2fv(location, false, v); - }; + return function (v) { + gl.uniformMatrix3x2fv(location, false, v) + } } function floatMat24Setter(gl, location) { - return function(v) { - gl.uniformMatrix2x4fv(location, false, v); - }; + return function (v) { + gl.uniformMatrix2x4fv(location, false, v) + } } function floatMat42Setter(gl, location) { - return function(v) { - gl.uniformMatrix4x2fv(location, false, v); - }; + return function (v) { + gl.uniformMatrix4x2fv(location, false, v) + } } function floatMat34Setter(gl, location) { - return function(v) { - gl.uniformMatrix3x4fv(location, false, v); - }; + return function (v) { + gl.uniformMatrix3x4fv(location, false, v) + } } function floatMat43Setter(gl, location) { - return function(v) { - gl.uniformMatrix4x3fv(location, false, v); - }; + return function (v) { + gl.uniformMatrix4x3fv(location, false, v) + } } function samplerSetter(gl, type, unit, location) { - const bindPoint = getBindPointForSamplerType(gl, type); - return isWebGL2(gl) ? function(textureOrPair) { - let texture; - let sampler; - if (!textureOrPair || isTexture(gl, textureOrPair)) { - texture = textureOrPair; - sampler = null; - } else { - texture = textureOrPair.texture; - sampler = textureOrPair.sampler; - } - gl.uniform1i(location, unit); - gl.activeTexture(TEXTURE0 + unit); - gl.bindTexture(bindPoint, texture); - gl.bindSampler(unit, sampler); - } : function(texture) { - gl.uniform1i(location, unit); - gl.activeTexture(TEXTURE0 + unit); - gl.bindTexture(bindPoint, texture); - }; + const bindPoint = getBindPointForSamplerType(gl, type) + return isWebGL2(gl) + ? function (textureOrPair) { + let texture + let sampler + if (!textureOrPair || isTexture(gl, textureOrPair)) { + texture = textureOrPair + sampler = null + } else { + texture = textureOrPair.texture + sampler = textureOrPair.sampler + } + gl.uniform1i(location, unit) + gl.activeTexture(TEXTURE0 + unit) + gl.bindTexture(bindPoint, texture) + gl.bindSampler(unit, sampler) + } + : function (texture) { + gl.uniform1i(location, unit) + gl.activeTexture(TEXTURE0 + unit) + gl.bindTexture(bindPoint, texture) + } } function samplerArraySetter(gl, type, unit, location, size) { - const bindPoint = getBindPointForSamplerType(gl, type); - const units = new Int32Array(size); - for (let ii = 0; ii < size; ++ii) { - units[ii] = unit + ii; - } - - return isWebGL2(gl) ? function(textures) { - gl.uniform1iv(location, units); - textures.forEach(function(textureOrPair, index) { - gl.activeTexture(TEXTURE0 + units[index]); - let texture; - let sampler; - if (!textureOrPair || isTexture(gl, textureOrPair)) { - texture = textureOrPair; - sampler = null; - } else { - texture = textureOrPair.texture; - sampler = textureOrPair.sampler; - } - gl.bindSampler(unit, sampler); - gl.bindTexture(bindPoint, texture); - }); - } : function(textures) { - gl.uniform1iv(location, units); - textures.forEach(function(texture, index) { - gl.activeTexture(TEXTURE0 + units[index]); - gl.bindTexture(bindPoint, texture); - }); - }; -} - -typeMap[FLOAT] = { Type: Float32Array, size: 4, setter: floatSetter, arraySetter: floatArraySetter, }; -typeMap[FLOAT_VEC2] = { Type: Float32Array, size: 8, setter: floatVec2Setter, cols: 2, }; -typeMap[FLOAT_VEC3] = { Type: Float32Array, size: 12, setter: floatVec3Setter, cols: 3, }; -typeMap[FLOAT_VEC4] = { Type: Float32Array, size: 16, setter: floatVec4Setter, cols: 4, }; -typeMap[INT] = { Type: Int32Array, size: 4, setter: intSetter, arraySetter: intArraySetter, }; -typeMap[INT_VEC2] = { Type: Int32Array, size: 8, setter: intVec2Setter, cols: 2, }; -typeMap[INT_VEC3] = { Type: Int32Array, size: 12, setter: intVec3Setter, cols: 3, }; -typeMap[INT_VEC4] = { Type: Int32Array, size: 16, setter: intVec4Setter, cols: 4, }; -typeMap[UNSIGNED_INT] = { Type: Uint32Array, size: 4, setter: uintSetter, arraySetter: uintArraySetter, }; -typeMap[UNSIGNED_INT_VEC2] = { Type: Uint32Array, size: 8, setter: uintVec2Setter, cols: 2, }; -typeMap[UNSIGNED_INT_VEC3] = { Type: Uint32Array, size: 12, setter: uintVec3Setter, cols: 3, }; -typeMap[UNSIGNED_INT_VEC4] = { Type: Uint32Array, size: 16, setter: uintVec4Setter, cols: 4, }; -typeMap[BOOL] = { Type: Uint32Array, size: 4, setter: intSetter, arraySetter: intArraySetter, }; -typeMap[BOOL_VEC2] = { Type: Uint32Array, size: 8, setter: intVec2Setter, cols: 2, }; -typeMap[BOOL_VEC3] = { Type: Uint32Array, size: 12, setter: intVec3Setter, cols: 3, }; -typeMap[BOOL_VEC4] = { Type: Uint32Array, size: 16, setter: intVec4Setter, cols: 4, }; -typeMap[FLOAT_MAT2] = { Type: Float32Array, size: 32, setter: floatMat2Setter, rows: 2, cols: 2, }; -typeMap[FLOAT_MAT3] = { Type: Float32Array, size: 48, setter: floatMat3Setter, rows: 3, cols: 3, }; -typeMap[FLOAT_MAT4] = { Type: Float32Array, size: 64, setter: floatMat4Setter, rows: 4, cols: 4, }; -typeMap[FLOAT_MAT2x3] = { Type: Float32Array, size: 32, setter: floatMat23Setter, rows: 2, cols: 3, }; -typeMap[FLOAT_MAT2x4] = { Type: Float32Array, size: 32, setter: floatMat24Setter, rows: 2, cols: 4, }; -typeMap[FLOAT_MAT3x2] = { Type: Float32Array, size: 48, setter: floatMat32Setter, rows: 3, cols: 2, }; -typeMap[FLOAT_MAT3x4] = { Type: Float32Array, size: 48, setter: floatMat34Setter, rows: 3, cols: 4, }; -typeMap[FLOAT_MAT4x2] = { Type: Float32Array, size: 64, setter: floatMat42Setter, rows: 4, cols: 2, }; -typeMap[FLOAT_MAT4x3] = { Type: Float32Array, size: 64, setter: floatMat43Setter, rows: 4, cols: 3, }; -typeMap[SAMPLER_2D] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D$1, }; -typeMap[SAMPLER_CUBE] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_CUBE_MAP, }; -typeMap[SAMPLER_3D] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_3D, }; -typeMap[SAMPLER_2D_SHADOW] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D$1, }; -typeMap[SAMPLER_2D_ARRAY] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D_ARRAY, }; -typeMap[SAMPLER_2D_ARRAY_SHADOW] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D_ARRAY, }; -typeMap[SAMPLER_CUBE_SHADOW] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_CUBE_MAP, }; -typeMap[INT_SAMPLER_2D] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D$1, }; -typeMap[INT_SAMPLER_3D] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_3D, }; -typeMap[INT_SAMPLER_CUBE] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_CUBE_MAP, }; -typeMap[INT_SAMPLER_2D_ARRAY] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D_ARRAY, }; -typeMap[UNSIGNED_INT_SAMPLER_2D] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D$1, }; -typeMap[UNSIGNED_INT_SAMPLER_3D] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_3D, }; -typeMap[UNSIGNED_INT_SAMPLER_CUBE] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_CUBE_MAP, }; -typeMap[UNSIGNED_INT_SAMPLER_2D_ARRAY] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D_ARRAY, }; + const bindPoint = getBindPointForSamplerType(gl, type) + const units = new Int32Array(size) + for (let ii = 0; ii < size; ++ii) { + units[ii] = unit + ii + } + + return isWebGL2(gl) + ? function (textures) { + gl.uniform1iv(location, units) + textures.forEach(function (textureOrPair, index) { + gl.activeTexture(TEXTURE0 + units[index]) + let texture + let sampler + if (!textureOrPair || isTexture(gl, textureOrPair)) { + texture = textureOrPair + sampler = null + } else { + texture = textureOrPair.texture + sampler = textureOrPair.sampler + } + gl.bindSampler(unit, sampler) + gl.bindTexture(bindPoint, texture) + }) + } + : function (textures) { + gl.uniform1iv(location, units) + textures.forEach(function (texture, index) { + gl.activeTexture(TEXTURE0 + units[index]) + gl.bindTexture(bindPoint, texture) + }) + } +} + +typeMap[FLOAT] = { + Type: Float32Array, + size: 4, + setter: floatSetter, + arraySetter: floatArraySetter, +} +typeMap[FLOAT_VEC2] = { + Type: Float32Array, + size: 8, + setter: floatVec2Setter, + cols: 2, +} +typeMap[FLOAT_VEC3] = { + Type: Float32Array, + size: 12, + setter: floatVec3Setter, + cols: 3, +} +typeMap[FLOAT_VEC4] = { + Type: Float32Array, + size: 16, + setter: floatVec4Setter, + cols: 4, +} +typeMap[INT] = { + Type: Int32Array, + size: 4, + setter: intSetter, + arraySetter: intArraySetter, +} +typeMap[INT_VEC2] = { + Type: Int32Array, + size: 8, + setter: intVec2Setter, + cols: 2, +} +typeMap[INT_VEC3] = { + Type: Int32Array, + size: 12, + setter: intVec3Setter, + cols: 3, +} +typeMap[INT_VEC4] = { + Type: Int32Array, + size: 16, + setter: intVec4Setter, + cols: 4, +} +typeMap[UNSIGNED_INT] = { + Type: Uint32Array, + size: 4, + setter: uintSetter, + arraySetter: uintArraySetter, +} +typeMap[UNSIGNED_INT_VEC2] = { + Type: Uint32Array, + size: 8, + setter: uintVec2Setter, + cols: 2, +} +typeMap[UNSIGNED_INT_VEC3] = { + Type: Uint32Array, + size: 12, + setter: uintVec3Setter, + cols: 3, +} +typeMap[UNSIGNED_INT_VEC4] = { + Type: Uint32Array, + size: 16, + setter: uintVec4Setter, + cols: 4, +} +typeMap[BOOL] = { + Type: Uint32Array, + size: 4, + setter: intSetter, + arraySetter: intArraySetter, +} +typeMap[BOOL_VEC2] = { + Type: Uint32Array, + size: 8, + setter: intVec2Setter, + cols: 2, +} +typeMap[BOOL_VEC3] = { + Type: Uint32Array, + size: 12, + setter: intVec3Setter, + cols: 3, +} +typeMap[BOOL_VEC4] = { + Type: Uint32Array, + size: 16, + setter: intVec4Setter, + cols: 4, +} +typeMap[FLOAT_MAT2] = { + Type: Float32Array, + size: 32, + setter: floatMat2Setter, + rows: 2, + cols: 2, +} +typeMap[FLOAT_MAT3] = { + Type: Float32Array, + size: 48, + setter: floatMat3Setter, + rows: 3, + cols: 3, +} +typeMap[FLOAT_MAT4] = { + Type: Float32Array, + size: 64, + setter: floatMat4Setter, + rows: 4, + cols: 4, +} +typeMap[FLOAT_MAT2x3] = { + Type: Float32Array, + size: 32, + setter: floatMat23Setter, + rows: 2, + cols: 3, +} +typeMap[FLOAT_MAT2x4] = { + Type: Float32Array, + size: 32, + setter: floatMat24Setter, + rows: 2, + cols: 4, +} +typeMap[FLOAT_MAT3x2] = { + Type: Float32Array, + size: 48, + setter: floatMat32Setter, + rows: 3, + cols: 2, +} +typeMap[FLOAT_MAT3x4] = { + Type: Float32Array, + size: 48, + setter: floatMat34Setter, + rows: 3, + cols: 4, +} +typeMap[FLOAT_MAT4x2] = { + Type: Float32Array, + size: 64, + setter: floatMat42Setter, + rows: 4, + cols: 2, +} +typeMap[FLOAT_MAT4x3] = { + Type: Float32Array, + size: 64, + setter: floatMat43Setter, + rows: 4, + cols: 3, +} +typeMap[SAMPLER_2D] = { + Type: null, + size: 0, + setter: samplerSetter, + arraySetter: samplerArraySetter, + bindPoint: TEXTURE_2D$1, +} +typeMap[SAMPLER_CUBE] = { + Type: null, + size: 0, + setter: samplerSetter, + arraySetter: samplerArraySetter, + bindPoint: TEXTURE_CUBE_MAP, +} +typeMap[SAMPLER_3D] = { + Type: null, + size: 0, + setter: samplerSetter, + arraySetter: samplerArraySetter, + bindPoint: TEXTURE_3D, +} +typeMap[SAMPLER_2D_SHADOW] = { + Type: null, + size: 0, + setter: samplerSetter, + arraySetter: samplerArraySetter, + bindPoint: TEXTURE_2D$1, +} +typeMap[SAMPLER_2D_ARRAY] = { + Type: null, + size: 0, + setter: samplerSetter, + arraySetter: samplerArraySetter, + bindPoint: TEXTURE_2D_ARRAY, +} +typeMap[SAMPLER_2D_ARRAY_SHADOW] = { + Type: null, + size: 0, + setter: samplerSetter, + arraySetter: samplerArraySetter, + bindPoint: TEXTURE_2D_ARRAY, +} +typeMap[SAMPLER_CUBE_SHADOW] = { + Type: null, + size: 0, + setter: samplerSetter, + arraySetter: samplerArraySetter, + bindPoint: TEXTURE_CUBE_MAP, +} +typeMap[INT_SAMPLER_2D] = { + Type: null, + size: 0, + setter: samplerSetter, + arraySetter: samplerArraySetter, + bindPoint: TEXTURE_2D$1, +} +typeMap[INT_SAMPLER_3D] = { + Type: null, + size: 0, + setter: samplerSetter, + arraySetter: samplerArraySetter, + bindPoint: TEXTURE_3D, +} +typeMap[INT_SAMPLER_CUBE] = { + Type: null, + size: 0, + setter: samplerSetter, + arraySetter: samplerArraySetter, + bindPoint: TEXTURE_CUBE_MAP, +} +typeMap[INT_SAMPLER_2D_ARRAY] = { + Type: null, + size: 0, + setter: samplerSetter, + arraySetter: samplerArraySetter, + bindPoint: TEXTURE_2D_ARRAY, +} +typeMap[UNSIGNED_INT_SAMPLER_2D] = { + Type: null, + size: 0, + setter: samplerSetter, + arraySetter: samplerArraySetter, + bindPoint: TEXTURE_2D$1, +} +typeMap[UNSIGNED_INT_SAMPLER_3D] = { + Type: null, + size: 0, + setter: samplerSetter, + arraySetter: samplerArraySetter, + bindPoint: TEXTURE_3D, +} +typeMap[UNSIGNED_INT_SAMPLER_CUBE] = { + Type: null, + size: 0, + setter: samplerSetter, + arraySetter: samplerArraySetter, + bindPoint: TEXTURE_CUBE_MAP, +} +typeMap[UNSIGNED_INT_SAMPLER_2D_ARRAY] = { + Type: null, + size: 0, + setter: samplerSetter, + arraySetter: samplerArraySetter, + bindPoint: TEXTURE_2D_ARRAY, +} function floatAttribSetter(gl, index) { - return function(b) { - if (b.value) { - gl.disableVertexAttribArray(index); - switch (b.value.length) { - case 4: - gl.vertexAttrib4fv(index, b.value); - break; - case 3: - gl.vertexAttrib3fv(index, b.value); - break; - case 2: - gl.vertexAttrib2fv(index, b.value); - break; - case 1: - gl.vertexAttrib1fv(index, b.value); - break; - default: - throw new Error('the length of a float constant value must be between 1 and 4!'); - } - } else { - gl.bindBuffer(ARRAY_BUFFER, b.buffer); - gl.enableVertexAttribArray(index); - gl.vertexAttribPointer( - index, b.numComponents || b.size, b.type || FLOAT, b.normalize || false, b.stride || 0, b.offset || 0); - if (gl.vertexAttribDivisor) { - gl.vertexAttribDivisor(index, b.divisor || 0); - } + return function (b) { + if (b.value) { + gl.disableVertexAttribArray(index) + switch (b.value.length) { + case 4: + gl.vertexAttrib4fv(index, b.value) + break + case 3: + gl.vertexAttrib3fv(index, b.value) + break + case 2: + gl.vertexAttrib2fv(index, b.value) + break + case 1: + gl.vertexAttrib1fv(index, b.value) + break + default: + throw new Error( + 'the length of a float constant value must be between 1 and 4!' + ) + } + } else { + gl.bindBuffer(ARRAY_BUFFER, b.buffer) + gl.enableVertexAttribArray(index) + gl.vertexAttribPointer( + index, + b.numComponents || b.size, + b.type || FLOAT, + b.normalize || false, + b.stride || 0, + b.offset || 0 + ) + if (gl.vertexAttribDivisor) { + gl.vertexAttribDivisor(index, b.divisor || 0) + } + } } - }; } function intAttribSetter(gl, index) { - return function(b) { - if (b.value) { - gl.disableVertexAttribArray(index); - if (b.value.length === 4) { - gl.vertexAttrib4iv(index, b.value); - } else { - throw new Error('The length of an integer constant value must be 4!'); - } - } else { - gl.bindBuffer(ARRAY_BUFFER, b.buffer); - gl.enableVertexAttribArray(index); - gl.vertexAttribIPointer( - index, b.numComponents || b.size, b.type || INT, b.stride || 0, b.offset || 0); - if (gl.vertexAttribDivisor) { - gl.vertexAttribDivisor(index, b.divisor || 0); - } + return function (b) { + if (b.value) { + gl.disableVertexAttribArray(index) + if (b.value.length === 4) { + gl.vertexAttrib4iv(index, b.value) + } else { + throw new Error( + 'The length of an integer constant value must be 4!' + ) + } + } else { + gl.bindBuffer(ARRAY_BUFFER, b.buffer) + gl.enableVertexAttribArray(index) + gl.vertexAttribIPointer( + index, + b.numComponents || b.size, + b.type || INT, + b.stride || 0, + b.offset || 0 + ) + if (gl.vertexAttribDivisor) { + gl.vertexAttribDivisor(index, b.divisor || 0) + } + } } - }; } function uintAttribSetter(gl, index) { - return function(b) { - if (b.value) { - gl.disableVertexAttribArray(index); - if (b.value.length === 4) { - gl.vertexAttrib4uiv(index, b.value); - } else { - throw new Error('The length of an unsigned integer constant value must be 4!'); - } - } else { - gl.bindBuffer(ARRAY_BUFFER, b.buffer); - gl.enableVertexAttribArray(index); - gl.vertexAttribIPointer( - index, b.numComponents || b.size, b.type || UNSIGNED_INT, b.stride || 0, b.offset || 0); - if (gl.vertexAttribDivisor) { - gl.vertexAttribDivisor(index, b.divisor || 0); - } + return function (b) { + if (b.value) { + gl.disableVertexAttribArray(index) + if (b.value.length === 4) { + gl.vertexAttrib4uiv(index, b.value) + } else { + throw new Error( + 'The length of an unsigned integer constant value must be 4!' + ) + } + } else { + gl.bindBuffer(ARRAY_BUFFER, b.buffer) + gl.enableVertexAttribArray(index) + gl.vertexAttribIPointer( + index, + b.numComponents || b.size, + b.type || UNSIGNED_INT, + b.stride || 0, + b.offset || 0 + ) + if (gl.vertexAttribDivisor) { + gl.vertexAttribDivisor(index, b.divisor || 0) + } + } } - }; } function matAttribSetter(gl, index, typeInfo) { - const defaultSize = typeInfo.size; - const count = typeInfo.count; - - return function(b) { - gl.bindBuffer(ARRAY_BUFFER, b.buffer); - const numComponents = b.size || b.numComponents || defaultSize; - const size = numComponents / count; - const type = b.type || FLOAT; - const typeInfo = typeMap[type]; - const stride = typeInfo.size * numComponents; - const normalize = b.normalize || false; - const offset = b.offset || 0; - const rowOffset = stride / count; - for (let i = 0; i < count; ++i) { - gl.enableVertexAttribArray(index + i); - gl.vertexAttribPointer( - index + i, size, type, normalize, stride, offset + rowOffset * i); - if (gl.vertexAttribDivisor) { - gl.vertexAttribDivisor(index + i, b.divisor || 0); - } - } - }; -} - - - -const attrTypeMap = {}; -attrTypeMap[FLOAT] = { size: 4, setter: floatAttribSetter, }; -attrTypeMap[FLOAT_VEC2] = { size: 8, setter: floatAttribSetter, }; -attrTypeMap[FLOAT_VEC3] = { size: 12, setter: floatAttribSetter, }; -attrTypeMap[FLOAT_VEC4] = { size: 16, setter: floatAttribSetter, }; -attrTypeMap[INT] = { size: 4, setter: intAttribSetter, }; -attrTypeMap[INT_VEC2] = { size: 8, setter: intAttribSetter, }; -attrTypeMap[INT_VEC3] = { size: 12, setter: intAttribSetter, }; -attrTypeMap[INT_VEC4] = { size: 16, setter: intAttribSetter, }; -attrTypeMap[UNSIGNED_INT] = { size: 4, setter: uintAttribSetter, }; -attrTypeMap[UNSIGNED_INT_VEC2] = { size: 8, setter: uintAttribSetter, }; -attrTypeMap[UNSIGNED_INT_VEC3] = { size: 12, setter: uintAttribSetter, }; -attrTypeMap[UNSIGNED_INT_VEC4] = { size: 16, setter: uintAttribSetter, }; -attrTypeMap[BOOL] = { size: 4, setter: intAttribSetter, }; -attrTypeMap[BOOL_VEC2] = { size: 8, setter: intAttribSetter, }; -attrTypeMap[BOOL_VEC3] = { size: 12, setter: intAttribSetter, }; -attrTypeMap[BOOL_VEC4] = { size: 16, setter: intAttribSetter, }; -attrTypeMap[FLOAT_MAT2] = { size: 4, setter: matAttribSetter, count: 2, }; -attrTypeMap[FLOAT_MAT3] = { size: 9, setter: matAttribSetter, count: 3, }; -attrTypeMap[FLOAT_MAT4] = { size: 16, setter: matAttribSetter, count: 4, }; - -const errorRE = /ERROR:\s*\d+:(\d+)/gi; + const defaultSize = typeInfo.size + const count = typeInfo.count + + return function (b) { + gl.bindBuffer(ARRAY_BUFFER, b.buffer) + const numComponents = b.size || b.numComponents || defaultSize + const size = numComponents / count + const type = b.type || FLOAT + const typeInfo = typeMap[type] + const stride = typeInfo.size * numComponents + const normalize = b.normalize || false + const offset = b.offset || 0 + const rowOffset = stride / count + for (let i = 0; i < count; ++i) { + gl.enableVertexAttribArray(index + i) + gl.vertexAttribPointer( + index + i, + size, + type, + normalize, + stride, + offset + rowOffset * i + ) + if (gl.vertexAttribDivisor) { + gl.vertexAttribDivisor(index + i, b.divisor || 0) + } + } + } +} + +const attrTypeMap = {} +attrTypeMap[FLOAT] = { size: 4, setter: floatAttribSetter } +attrTypeMap[FLOAT_VEC2] = { size: 8, setter: floatAttribSetter } +attrTypeMap[FLOAT_VEC3] = { size: 12, setter: floatAttribSetter } +attrTypeMap[FLOAT_VEC4] = { size: 16, setter: floatAttribSetter } +attrTypeMap[INT] = { size: 4, setter: intAttribSetter } +attrTypeMap[INT_VEC2] = { size: 8, setter: intAttribSetter } +attrTypeMap[INT_VEC3] = { size: 12, setter: intAttribSetter } +attrTypeMap[INT_VEC4] = { size: 16, setter: intAttribSetter } +attrTypeMap[UNSIGNED_INT] = { size: 4, setter: uintAttribSetter } +attrTypeMap[UNSIGNED_INT_VEC2] = { size: 8, setter: uintAttribSetter } +attrTypeMap[UNSIGNED_INT_VEC3] = { size: 12, setter: uintAttribSetter } +attrTypeMap[UNSIGNED_INT_VEC4] = { size: 16, setter: uintAttribSetter } +attrTypeMap[BOOL] = { size: 4, setter: intAttribSetter } +attrTypeMap[BOOL_VEC2] = { size: 8, setter: intAttribSetter } +attrTypeMap[BOOL_VEC3] = { size: 12, setter: intAttribSetter } +attrTypeMap[BOOL_VEC4] = { size: 16, setter: intAttribSetter } +attrTypeMap[FLOAT_MAT2] = { size: 4, setter: matAttribSetter, count: 2 } +attrTypeMap[FLOAT_MAT3] = { size: 9, setter: matAttribSetter, count: 3 } +attrTypeMap[FLOAT_MAT4] = { size: 16, setter: matAttribSetter, count: 4 } + +const errorRE = /ERROR:\s*\d+:(\d+)/gi function addLineNumbersWithError(src, log = '', lineOffset = 0) { - // Note: Error message formats are not defined by any spec so this may or may not work. - const matches = [...log.matchAll(errorRE)]; - const lineNoToErrorMap = new Map(matches.map((m, ndx) => { - const lineNo = parseInt(m[1]); - const next = matches[ndx + 1]; - const end = next ? next.index : log.length; - const msg = log.substring(m.index, end); - return [lineNo - 1, msg]; - })); - return src.split('\n').map((line, lineNo) => { - const err = lineNoToErrorMap.get(lineNo); - return `${lineNo + 1 + lineOffset}: ${line}${err ? `\n\n^^^ ${err}` : ''}`; - }).join('\n'); + // Note: Error message formats are not defined by any spec so this may or may not work. + const matches = [...log.matchAll(errorRE)] + const lineNoToErrorMap = new Map( + matches.map((m, ndx) => { + const lineNo = parseInt(m[1]) + const next = matches[ndx + 1] + const end = next ? next.index : log.length + const msg = log.substring(m.index, end) + return [lineNo - 1, msg] + }) + ) + return src + .split('\n') + .map((line, lineNo) => { + const err = lineNoToErrorMap.get(lineNo) + return `${lineNo + 1 + lineOffset}: ${line}${ + err ? `\n\n^^^ ${err}` : '' + }` + }) + .join('\n') } /** @@ -7317,7 +8384,7 @@ function addLineNumbersWithError(src, log = '', lineOffset = 0) { * @param {WebGLProgram|module:twgl.ProgramInfo} [result] the program or programInfo */ -const spaceRE = /^[ \t]*\n/; +const spaceRE = /^[ \t]*\n/ /** * Remove the first end of line because WebGL 2.0 requires @@ -7336,12 +8403,12 @@ const spaceRE = /^[ \t]*\n/; * @private */ function prepShaderSource(shaderSource) { - let lineOffset = 0; - if (spaceRE.test(shaderSource)) { - lineOffset = 1; - shaderSource = shaderSource.replace(spaceRE, ''); - } - return {lineOffset, shaderSource}; + let lineOffset = 0 + if (spaceRE.test(shaderSource)) { + lineOffset = 1 + shaderSource = shaderSource.replace(spaceRE, '') + } + return { lineOffset, shaderSource } } /** @@ -7351,13 +8418,13 @@ function prepShaderSource(shaderSource) { * @private */ function reportError(progOptions, msg) { - progOptions.errorCallback(msg); - if (progOptions.callback) { - setTimeout(() => { - progOptions.callback(`${msg}\n${progOptions.errors.join('\n')}`); - }); - } - return null; + progOptions.errorCallback(msg) + if (progOptions.callback) { + setTimeout(() => { + progOptions.callback(`${msg}\n${progOptions.errors.join('\n')}`) + }) + } + return null } /** @@ -7370,18 +8437,24 @@ function reportError(progOptions, msg) { * @private */ function checkShaderStatus(gl, shaderType, shader, errFn) { - errFn = errFn || error; - // Check the compile status - const compiled = gl.getShaderParameter(shader, COMPILE_STATUS); - if (!compiled) { - // Something went wrong during compilation; get the error - const lastError = gl.getShaderInfoLog(shader); - const {lineOffset, shaderSource} = prepShaderSource(gl.getShaderSource(shader)); - const error = `${addLineNumbersWithError(shaderSource, lastError, lineOffset)}\nError compiling ${glEnumToString(gl, shaderType)}: ${lastError}`; - errFn(error); - return error; - } - return ''; + errFn = errFn || error + // Check the compile status + const compiled = gl.getShaderParameter(shader, COMPILE_STATUS) + if (!compiled) { + // Something went wrong during compilation; get the error + const lastError = gl.getShaderInfoLog(shader) + const { lineOffset, shaderSource } = prepShaderSource( + gl.getShaderSource(shader) + ) + const error = `${addLineNumbersWithError( + shaderSource, + lastError, + lineOffset + )}\nError compiling ${glEnumToString(gl, shaderType)}: ${lastError}` + errFn(error) + return error + } + return '' } /** @@ -7424,120 +8497,125 @@ function checkShaderStatus(gl, shaderType, shader, errFn) { * @private */ function getProgramOptions(opt_attribs, opt_locations, opt_errorCallback) { - let transformFeedbackVaryings; - let transformFeedbackMode; - let callback; - if (typeof opt_locations === 'function') { - opt_errorCallback = opt_locations; - opt_locations = undefined; - } - if (typeof opt_attribs === 'function') { - opt_errorCallback = opt_attribs; - opt_attribs = undefined; - } else if (opt_attribs && !Array.isArray(opt_attribs)) { - const opt = opt_attribs; - opt_errorCallback = opt.errorCallback; - opt_attribs = opt.attribLocations; - transformFeedbackVaryings = opt.transformFeedbackVaryings; - transformFeedbackMode = opt.transformFeedbackMode; - callback = opt.callback; - } - - const errorCallback = opt_errorCallback || error; - const errors = []; - const options = { - errorCallback(msg, ...args) { - errors.push(msg); - errorCallback(msg, ...args); - }, - transformFeedbackVaryings, - transformFeedbackMode, - callback, - errors, - }; - - { - let attribLocations = {}; - if (Array.isArray(opt_attribs)) { - opt_attribs.forEach(function(attrib, ndx) { - attribLocations[attrib] = opt_locations ? opt_locations[ndx] : ndx; - }); - } else { - attribLocations = opt_attribs || {}; + let transformFeedbackVaryings + let transformFeedbackMode + let callback + if (typeof opt_locations === 'function') { + opt_errorCallback = opt_locations + opt_locations = undefined + } + if (typeof opt_attribs === 'function') { + opt_errorCallback = opt_attribs + opt_attribs = undefined + } else if (opt_attribs && !Array.isArray(opt_attribs)) { + const opt = opt_attribs + opt_errorCallback = opt.errorCallback + opt_attribs = opt.attribLocations + transformFeedbackVaryings = opt.transformFeedbackVaryings + transformFeedbackMode = opt.transformFeedbackMode + callback = opt.callback + } + + const errorCallback = opt_errorCallback || error + const errors = [] + const options = { + errorCallback(msg, ...args) { + errors.push(msg) + errorCallback(msg, ...args) + }, + transformFeedbackVaryings, + transformFeedbackMode, + callback, + errors, + } + + { + let attribLocations = {} + if (Array.isArray(opt_attribs)) { + opt_attribs.forEach(function (attrib, ndx) { + attribLocations[attrib] = opt_locations + ? opt_locations[ndx] + : ndx + }) + } else { + attribLocations = opt_attribs || {} + } + options.attribLocations = attribLocations } - options.attribLocations = attribLocations; - } - return options; + return options } -const defaultShaderType = [ - "VERTEX_SHADER", - "FRAGMENT_SHADER", -]; +const defaultShaderType = ['VERTEX_SHADER', 'FRAGMENT_SHADER'] function getShaderTypeFromScriptType(gl, scriptType) { - if (scriptType.indexOf("frag") >= 0) { - return FRAGMENT_SHADER; - } else if (scriptType.indexOf("vert") >= 0) { - return VERTEX_SHADER; - } - return undefined; + if (scriptType.indexOf('frag') >= 0) { + return FRAGMENT_SHADER + } else if (scriptType.indexOf('vert') >= 0) { + return VERTEX_SHADER + } + return undefined } function deleteProgramAndShaders(gl, program, notThese) { - const shaders = gl.getAttachedShaders(program); - for (const shader of shaders) { - if (notThese.has(shader)) { - gl.deleteShader(shader); + const shaders = gl.getAttachedShaders(program) + for (const shader of shaders) { + if (notThese.has(shader)) { + gl.deleteShader(shader) + } } - } - gl.deleteProgram(program); + gl.deleteProgram(program) } -const wait = (ms = 0) => new Promise(resolve => setTimeout(resolve, ms)); +const wait = (ms = 0) => new Promise(resolve => setTimeout(resolve, ms)) function createProgramNoCheck(gl, shaders, programOptions) { - const program = gl.createProgram(); - const { - attribLocations, - transformFeedbackVaryings, - transformFeedbackMode, - } = getProgramOptions(programOptions); - - for (let ndx = 0; ndx < shaders.length; ++ndx) { - let shader = shaders[ndx]; - if (typeof shader === 'string') { - const elem = getElementById(shader); - const src = elem ? elem.text : shader; - let type = gl[defaultShaderType[ndx]]; - if (elem && elem.type) { - type = getShaderTypeFromScriptType(gl, elem.type) || type; - } - shader = gl.createShader(type); - gl.shaderSource(shader, prepShaderSource(src).shaderSource); - gl.compileShader(shader); - gl.attachShader(program, shader); - } - } - - Object.entries(attribLocations).forEach(([attrib, loc]) => gl.bindAttribLocation(program, loc, attrib)); - - { - let varyings = transformFeedbackVaryings; - if (varyings) { - if (varyings.attribs) { - varyings = varyings.attribs; - } - if (!Array.isArray(varyings)) { - varyings = Object.keys(varyings); - } - gl.transformFeedbackVaryings(program, varyings, transformFeedbackMode || SEPARATE_ATTRIBS); - } - } - - gl.linkProgram(program); - return program; + const program = gl.createProgram() + const { + attribLocations, + transformFeedbackVaryings, + transformFeedbackMode, + } = getProgramOptions(programOptions) + + for (let ndx = 0; ndx < shaders.length; ++ndx) { + let shader = shaders[ndx] + if (typeof shader === 'string') { + const elem = getElementById(shader) + const src = elem ? elem.text : shader + let type = gl[defaultShaderType[ndx]] + if (elem && elem.type) { + type = getShaderTypeFromScriptType(gl, elem.type) || type + } + shader = gl.createShader(type) + gl.shaderSource(shader, prepShaderSource(src).shaderSource) + gl.compileShader(shader) + gl.attachShader(program, shader) + } + } + + Object.entries(attribLocations).forEach(([attrib, loc]) => + gl.bindAttribLocation(program, loc, attrib) + ) + + { + let varyings = transformFeedbackVaryings + if (varyings) { + if (varyings.attribs) { + varyings = varyings.attribs + } + if (!Array.isArray(varyings)) { + varyings = Object.keys(varyings) + } + gl.transformFeedbackVaryings( + program, + varyings, + transformFeedbackMode || SEPARATE_ATTRIBS + ) + } + } + + gl.linkProgram(program) + return program } /** @@ -7561,30 +8639,39 @@ function createProgramNoCheck(gl, shaders, programOptions) { * @memberOf module:twgl/programs */ function createProgram( - gl, shaders, opt_attribs, opt_locations, opt_errorCallback) { - // This code is really convoluted, because it may or may not be async - // Maybe it would be better to have a separate function - const progOptions = getProgramOptions(opt_attribs, opt_locations, opt_errorCallback); - const shaderSet = new Set(shaders); - const program = createProgramNoCheck(gl, shaders, progOptions); - - function hasErrors(gl, program) { - const errors = getProgramErrors(gl, program, progOptions.errorCallback); - if (errors) { - deleteProgramAndShaders(gl, program, shaderSet); + gl, + shaders, + opt_attribs, + opt_locations, + opt_errorCallback +) { + // This code is really convoluted, because it may or may not be async + // Maybe it would be better to have a separate function + const progOptions = getProgramOptions( + opt_attribs, + opt_locations, + opt_errorCallback + ) + const shaderSet = new Set(shaders) + const program = createProgramNoCheck(gl, shaders, progOptions) + + function hasErrors(gl, program) { + const errors = getProgramErrors(gl, program, progOptions.errorCallback) + if (errors) { + deleteProgramAndShaders(gl, program, shaderSet) + } + return errors } - return errors; - } - if (progOptions.callback) { - waitForProgramLinkCompletionAsync(gl, program).then(() => { - const errors = hasErrors(gl, program); - progOptions.callback(errors, errors ? undefined : program); - }); - return undefined; - } + if (progOptions.callback) { + waitForProgramLinkCompletionAsync(gl, program).then(() => { + const errors = hasErrors(gl, program) + progOptions.callback(errors, errors ? undefined : program) + }) + return undefined + } - return hasErrors(gl, program) ? undefined : program; + return hasErrors(gl, program) ? undefined : program } /** @@ -7593,19 +8680,19 @@ function createProgram( * @private */ function wrapCallbackFnToAsyncFn(fn) { - return function(gl, arg1, ...args) { - return new Promise((resolve, reject) => { - const programOptions = getProgramOptions(...args); - programOptions.callback = (err, program) => { - if (err) { - reject(err); - } else { - resolve(program); - } - }; - fn(gl, arg1, programOptions); - }); - }; + return function (gl, arg1, ...args) { + return new Promise((resolve, reject) => { + const programOptions = getProgramOptions(...args) + programOptions.callback = (err, program) => { + if (err) { + reject(err) + } else { + resolve(program) + } + } + fn(gl, arg1, programOptions) + }) + } } /** @@ -7628,7 +8715,7 @@ function wrapCallbackFnToAsyncFn(fn) { * @return {Promise} The created program * @memberOf module:twgl/programs */ -const createProgramAsync = wrapCallbackFnToAsyncFn(createProgram); +const createProgramAsync = wrapCallbackFnToAsyncFn(createProgram) /** * Same as createProgramInfo but returns a promise @@ -7645,25 +8732,26 @@ const createProgramAsync = wrapCallbackFnToAsyncFn(createProgram); * @return {Promise} The created ProgramInfo * @memberOf module:twgl/programs */ -const createProgramInfoAsync = wrapCallbackFnToAsyncFn(createProgramInfo); +const createProgramInfoAsync = wrapCallbackFnToAsyncFn(createProgramInfo) async function waitForProgramLinkCompletionAsync(gl, program) { - const ext = gl.getExtension('KHR_parallel_shader_compile'); - const checkFn = ext - ? (gl, program) => gl.getProgramParameter(program, ext.COMPLETION_STATUS_KHR) - : () => true; + const ext = gl.getExtension('KHR_parallel_shader_compile') + const checkFn = ext + ? (gl, program) => + gl.getProgramParameter(program, ext.COMPLETION_STATUS_KHR) + : () => true - let waitTime = 0; - do { - await wait(waitTime); // must wait at least once - waitTime = 1000 / 60; - } while (!checkFn(gl, program)); + let waitTime = 0 + do { + await wait(waitTime) // must wait at least once + waitTime = 1000 / 60 + } while (!checkFn(gl, program)) } async function waitForAllProgramsLinkCompletionAsync(gl, programs) { - for (const program of Object.values(programs)) { - await waitForProgramLinkCompletionAsync(gl, program); - } + for (const program of Object.values(programs)) { + await waitForProgramLinkCompletionAsync(gl, program) + } } /** @@ -7675,19 +8763,26 @@ async function waitForAllProgramsLinkCompletionAsync(gl, programs) { * @private */ function getProgramErrors(gl, program, errFn) { - errFn = errFn || error; - // Check the link status - const linked = gl.getProgramParameter(program, LINK_STATUS); - if (!linked) { - // something went wrong with the link - const lastError = gl.getProgramInfoLog(program); - errFn(`Error in program linking: ${lastError}`); - // print any errors from these shaders - const shaders = gl.getAttachedShaders(program); - const errors = shaders.map(shader => checkShaderStatus(gl, gl.getShaderParameter(shader, gl.SHADER_TYPE), shader, errFn)); - return `${lastError}\n${errors.filter(_ => _).join('\n')}`; - } - return undefined; + errFn = errFn || error + // Check the link status + const linked = gl.getProgramParameter(program, LINK_STATUS) + if (!linked) { + // something went wrong with the link + const lastError = gl.getProgramInfoLog(program) + errFn(`Error in program linking: ${lastError}`) + // print any errors from these shaders + const shaders = gl.getAttachedShaders(program) + const errors = shaders.map(shader => + checkShaderStatus( + gl, + gl.getShaderParameter(shader, gl.SHADER_TYPE), + shader, + errFn + ) + ) + return `${lastError}\n${errors.filter(_ => _).join('\n')}` + } + return undefined } /** @@ -7713,17 +8808,29 @@ function getProgramErrors(gl, program, errFn) { * @memberOf module:twgl/programs */ function createProgramFromScripts( - gl, shaderScriptIds, opt_attribs, opt_locations, opt_errorCallback) { - const progOptions = getProgramOptions(opt_attribs, opt_locations, opt_errorCallback); - const shaders = []; - for (const scriptId of shaderScriptIds) { - const shaderScript = getElementById(scriptId); - if (!shaderScript) { - return reportError(progOptions, `unknown script element: ${scriptId}`); + gl, + shaderScriptIds, + opt_attribs, + opt_locations, + opt_errorCallback +) { + const progOptions = getProgramOptions( + opt_attribs, + opt_locations, + opt_errorCallback + ) + const shaders = [] + for (const scriptId of shaderScriptIds) { + const shaderScript = getElementById(scriptId) + if (!shaderScript) { + return reportError( + progOptions, + `unknown script element: ${scriptId}` + ) + } + shaders.push(shaderScript.text) } - shaders.push(shaderScript.text); - } - return createProgram(gl, shaders, progOptions); + return createProgram(gl, shaders, progOptions) } /** @@ -7749,8 +8856,19 @@ function createProgramFromScripts( * @memberOf module:twgl/programs */ function createProgramFromSources( - gl, shaderSources, opt_attribs, opt_locations, opt_errorCallback) { - return createProgram(gl, shaderSources, opt_attribs, opt_locations, opt_errorCallback); + gl, + shaderSources, + opt_attribs, + opt_locations, + opt_errorCallback +) { + return createProgram( + gl, + shaderSources, + opt_attribs, + opt_locations, + opt_errorCallback + ) } /** @@ -7771,45 +8889,45 @@ function createProgramFromSources( * @private */ function isBuiltIn(info) { - const name = info.name; - return name.startsWith("gl_") || name.startsWith("webgl_"); + const name = info.name + return name.startsWith('gl_') || name.startsWith('webgl_') } -const tokenRE = /(\.|\[|]|\w+)/g; -const isDigit = s => s >= '0' && s <= '9'; +const tokenRE = /(\.|\[|]|\w+)/g +const isDigit = s => s >= '0' && s <= '9' function addSetterToUniformTree(fullPath, setter, node, uniformSetters) { - const tokens = fullPath.split(tokenRE).filter(s => s !== ''); - let tokenNdx = 0; - let path = ''; - - for (;;) { - const token = tokens[tokenNdx++]; // has to be name or number - path += token; - const isArrayIndex = isDigit(token[0]); - const accessor = isArrayIndex - ? parseInt(token) - : token; - if (isArrayIndex) { - path += tokens[tokenNdx++]; // skip ']' - } - const isLastToken = tokenNdx === tokens.length; - if (isLastToken) { - node[accessor] = setter; - break; - } else { - const token = tokens[tokenNdx++]; // has to be . or [ - const isArray = token === '['; - const child = node[accessor] || (isArray ? [] : {}); - node[accessor] = child; - node = child; - uniformSetters[path] = uniformSetters[path] || function(node) { - return function(value) { - setUniformTree(node, value); - }; - }(child); - path += token; + const tokens = fullPath.split(tokenRE).filter(s => s !== '') + let tokenNdx = 0 + let path = '' + + for (;;) { + const token = tokens[tokenNdx++] // has to be name or number + path += token + const isArrayIndex = isDigit(token[0]) + const accessor = isArrayIndex ? parseInt(token) : token + if (isArrayIndex) { + path += tokens[tokenNdx++] // skip ']' + } + const isLastToken = tokenNdx === tokens.length + if (isLastToken) { + node[accessor] = setter + break + } else { + const token = tokens[tokenNdx++] // has to be . or [ + const isArray = token === '[' + const child = node[accessor] || (isArray ? [] : {}) + node[accessor] = child + node = child + uniformSetters[path] = + uniformSetters[path] || + (function (node) { + return function (value) { + setUniformTree(node, value) + } + })(child) + path += token + } } - } } /** @@ -7824,67 +8942,79 @@ function addSetterToUniformTree(fullPath, setter, node, uniformSetters) { * @memberOf module:twgl/programs */ function createUniformSetters(gl, program) { - let textureUnit = 0; - - /** - * Creates a setter for a uniform of the given program with it's - * location embedded in the setter. - * @param {WebGLProgram} program - * @param {WebGLUniformInfo} uniformInfo - * @returns {function} the created setter. - */ - function createUniformSetter(program, uniformInfo, location) { - const isArray = uniformInfo.name.endsWith("[0]"); - const type = uniformInfo.type; - const typeInfo = typeMap[type]; - if (!typeInfo) { - throw new Error(`unknown type: 0x${type.toString(16)}`); // we should never get here. - } - let setter; - if (typeInfo.bindPoint) { - // it's a sampler - const unit = textureUnit; - textureUnit += uniformInfo.size; - if (isArray) { - setter = typeInfo.arraySetter(gl, type, unit, location, uniformInfo.size); - } else { - setter = typeInfo.setter(gl, type, unit, location, uniformInfo.size); - } - } else { - if (typeInfo.arraySetter && isArray) { - setter = typeInfo.arraySetter(gl, location); - } else { - setter = typeInfo.setter(gl, location); - } + let textureUnit = 0 + + /** + * Creates a setter for a uniform of the given program with it's + * location embedded in the setter. + * @param {WebGLProgram} program + * @param {WebGLUniformInfo} uniformInfo + * @returns {function} the created setter. + */ + function createUniformSetter(program, uniformInfo, location) { + const isArray = uniformInfo.name.endsWith('[0]') + const type = uniformInfo.type + const typeInfo = typeMap[type] + if (!typeInfo) { + throw new Error(`unknown type: 0x${type.toString(16)}`) // we should never get here. + } + let setter + if (typeInfo.bindPoint) { + // it's a sampler + const unit = textureUnit + textureUnit += uniformInfo.size + if (isArray) { + setter = typeInfo.arraySetter( + gl, + type, + unit, + location, + uniformInfo.size + ) + } else { + setter = typeInfo.setter( + gl, + type, + unit, + location, + uniformInfo.size + ) + } + } else { + if (typeInfo.arraySetter && isArray) { + setter = typeInfo.arraySetter(gl, location) + } else { + setter = typeInfo.setter(gl, location) + } + } + setter.location = location + return setter } - setter.location = location; - return setter; - } - const uniformSetters = {}; - const uniformTree = {}; - const numUniforms = gl.getProgramParameter(program, ACTIVE_UNIFORMS); + const uniformSetters = {} + const uniformTree = {} + const numUniforms = gl.getProgramParameter(program, ACTIVE_UNIFORMS) - for (let ii = 0; ii < numUniforms; ++ii) { - const uniformInfo = gl.getActiveUniform(program, ii); - if (isBuiltIn(uniformInfo)) { - continue; - } - let name = uniformInfo.name; - // remove the array suffix. - if (name.endsWith("[0]")) { - name = name.substr(0, name.length - 3); - } - const location = gl.getUniformLocation(program, uniformInfo.name); - // the uniform will have no location if it's in a uniform block - if (location) { - const setter = createUniformSetter(program, uniformInfo, location); - uniformSetters[name] = setter; - addSetterToUniformTree(name, setter, uniformTree, uniformSetters); + for (let ii = 0; ii < numUniforms; ++ii) { + const uniformInfo = gl.getActiveUniform(program, ii) + if (isBuiltIn(uniformInfo)) { + continue + } + let name = uniformInfo.name + // remove the array suffix. + if (name.endsWith('[0]')) { + name = name.substr(0, name.length - 3) + } + const location = gl.getUniformLocation(program, uniformInfo.name) + // the uniform will have no location if it's in a uniform block + if (location) { + const setter = createUniformSetter(program, uniformInfo, location) + uniformSetters[name] = setter + addSetterToUniformTree(name, setter, uniformTree, uniformSetters) + } } - } - return uniformSetters; + return uniformSetters } /** @@ -7903,17 +9033,20 @@ function createUniformSetters(gl, program) { * @memberOf module:twgl */ function createTransformFeedbackInfo(gl, program) { - const info = {}; - const numVaryings = gl.getProgramParameter(program, TRANSFORM_FEEDBACK_VARYINGS); - for (let ii = 0; ii < numVaryings; ++ii) { - const varying = gl.getTransformFeedbackVarying(program, ii); - info[varying.name] = { - index: ii, - type: varying.type, - size: varying.size, - }; - } - return info; + const info = {} + const numVaryings = gl.getProgramParameter( + program, + TRANSFORM_FEEDBACK_VARYINGS + ) + for (let ii = 0; ii < numVaryings; ++ii) { + const varying = gl.getTransformFeedbackVarying(program, ii) + info[varying.name] = { + index: ii, + type: varying.type, + size: varying.size, + } + } + return info } /** @@ -7925,23 +9058,33 @@ function createTransformFeedbackInfo(gl, program) { * @memberOf module:twgl */ function bindTransformFeedbackInfo(gl, transformFeedbackInfo, bufferInfo) { - if (transformFeedbackInfo.transformFeedbackInfo) { - transformFeedbackInfo = transformFeedbackInfo.transformFeedbackInfo; - } - if (bufferInfo.attribs) { - bufferInfo = bufferInfo.attribs; - } - for (const name in bufferInfo) { - const varying = transformFeedbackInfo[name]; - if (varying) { - const buf = bufferInfo[name]; - if (buf.offset) { - gl.bindBufferRange(TRANSFORM_FEEDBACK_BUFFER, varying.index, buf.buffer, buf.offset, buf.size); - } else { - gl.bindBufferBase(TRANSFORM_FEEDBACK_BUFFER, varying.index, buf.buffer); - } - } - } + if (transformFeedbackInfo.transformFeedbackInfo) { + transformFeedbackInfo = transformFeedbackInfo.transformFeedbackInfo + } + if (bufferInfo.attribs) { + bufferInfo = bufferInfo.attribs + } + for (const name in bufferInfo) { + const varying = transformFeedbackInfo[name] + if (varying) { + const buf = bufferInfo[name] + if (buf.offset) { + gl.bindBufferRange( + TRANSFORM_FEEDBACK_BUFFER, + varying.index, + buf.buffer, + buf.offset, + buf.size + ) + } else { + gl.bindBufferBase( + TRANSFORM_FEEDBACK_BUFFER, + varying.index, + buf.buffer + ) + } + } + } } /** @@ -7953,12 +9096,12 @@ function bindTransformFeedbackInfo(gl, transformFeedbackInfo, bufferInfo) { * @memberOf module:twgl */ function createTransformFeedback(gl, programInfo, bufferInfo) { - const tf = gl.createTransformFeedback(); - gl.bindTransformFeedback(TRANSFORM_FEEDBACK, tf); - gl.useProgram(programInfo.program); - bindTransformFeedbackInfo(gl, programInfo, bufferInfo); - gl.bindTransformFeedback(TRANSFORM_FEEDBACK, null); - return tf; + const tf = gl.createTransformFeedback() + gl.bindTransformFeedback(TRANSFORM_FEEDBACK, tf) + gl.useProgram(programInfo.program) + bindTransformFeedbackInfo(gl, programInfo, bufferInfo) + gl.bindTransformFeedback(TRANSFORM_FEEDBACK, null) + return tf } /** @@ -8007,80 +9150,102 @@ function createTransformFeedback(gl, programInfo, bufferInfo) { * @memberOf module:twgl/programs */ function createUniformBlockSpecFromProgram(gl, program) { - const numUniforms = gl.getProgramParameter(program, ACTIVE_UNIFORMS); - const uniformData = []; - const uniformIndices = []; - - for (let ii = 0; ii < numUniforms; ++ii) { - uniformIndices.push(ii); - uniformData.push({}); - const uniformInfo = gl.getActiveUniform(program, ii); - uniformData[ii].name = uniformInfo.name; - } - - [ - [ "UNIFORM_TYPE", "type" ], - [ "UNIFORM_SIZE", "size" ], // num elements - [ "UNIFORM_BLOCK_INDEX", "blockNdx" ], - [ "UNIFORM_OFFSET", "offset", ], - ].forEach(function(pair) { - const pname = pair[0]; - const key = pair[1]; - gl.getActiveUniforms(program, uniformIndices, gl[pname]).forEach(function(value, ndx) { - uniformData[ndx][key] = value; - }); - }); - - const blockSpecs = {}; - - const numUniformBlocks = gl.getProgramParameter(program, ACTIVE_UNIFORM_BLOCKS); - for (let ii = 0; ii < numUniformBlocks; ++ii) { - const name = gl.getActiveUniformBlockName(program, ii); - const blockSpec = { - index: gl.getUniformBlockIndex(program, name), - usedByVertexShader: gl.getActiveUniformBlockParameter(program, ii, UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER), - usedByFragmentShader: gl.getActiveUniformBlockParameter(program, ii, UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER), - size: gl.getActiveUniformBlockParameter(program, ii, UNIFORM_BLOCK_DATA_SIZE), - uniformIndices: gl.getActiveUniformBlockParameter(program, ii, UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES), - }; - blockSpec.used = blockSpec.usedByVertexShader || blockSpec.usedByFragmentShader; - blockSpecs[name] = blockSpec; - } - - return { - blockSpecs: blockSpecs, - uniformData: uniformData, - }; -} - -const arraySuffixRE = /\[\d+\]\.$/; // better way to check? - -const pad = (v, padding) => ((v + (padding - 1)) / padding | 0) * padding; + const numUniforms = gl.getProgramParameter(program, ACTIVE_UNIFORMS) + const uniformData = [] + const uniformIndices = [] + + for (let ii = 0; ii < numUniforms; ++ii) { + uniformIndices.push(ii) + uniformData.push({}) + const uniformInfo = gl.getActiveUniform(program, ii) + uniformData[ii].name = uniformInfo.name + } + + ;[ + ['UNIFORM_TYPE', 'type'], + ['UNIFORM_SIZE', 'size'], // num elements + ['UNIFORM_BLOCK_INDEX', 'blockNdx'], + ['UNIFORM_OFFSET', 'offset'], + ].forEach(function (pair) { + const pname = pair[0] + const key = pair[1] + gl.getActiveUniforms(program, uniformIndices, gl[pname]).forEach( + function (value, ndx) { + uniformData[ndx][key] = value + } + ) + }) + + const blockSpecs = {} + + const numUniformBlocks = gl.getProgramParameter( + program, + ACTIVE_UNIFORM_BLOCKS + ) + for (let ii = 0; ii < numUniformBlocks; ++ii) { + const name = gl.getActiveUniformBlockName(program, ii) + const blockSpec = { + index: gl.getUniformBlockIndex(program, name), + usedByVertexShader: gl.getActiveUniformBlockParameter( + program, + ii, + UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER + ), + usedByFragmentShader: gl.getActiveUniformBlockParameter( + program, + ii, + UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER + ), + size: gl.getActiveUniformBlockParameter( + program, + ii, + UNIFORM_BLOCK_DATA_SIZE + ), + uniformIndices: gl.getActiveUniformBlockParameter( + program, + ii, + UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES + ), + } + blockSpec.used = + blockSpec.usedByVertexShader || blockSpec.usedByFragmentShader + blockSpecs[name] = blockSpec + } + + return { + blockSpecs: blockSpecs, + uniformData: uniformData, + } +} + +const arraySuffixRE = /\[\d+\]\.$/ // better way to check? + +const pad = (v, padding) => (((v + (padding - 1)) / padding) | 0) * padding function createUniformBlockUniformSetter(view, isArray, rows, cols) { - if (isArray || rows) { - cols = cols || 1; - const numElements = view.length; - const totalRows = numElements / 4; - return function(value) { - let dst = 0; - let src = 0; - for (let row = 0; row < totalRows; ++row) { - for (let col = 0; col < cols; ++col) { - view[dst++] = value[src++]; - } - dst += 4 - cols; - } - }; - } else { - return function(value) { - if (value.length) { - view.set(value); - } else { - view[0] = value; - } - }; - } + if (isArray || rows) { + cols = cols || 1 + const numElements = view.length + const totalRows = numElements / 4 + return function (value) { + let dst = 0 + let src = 0 + for (let row = 0; row < totalRows; ++row) { + for (let col = 0; col < cols; ++col) { + view[dst++] = value[src++] + } + dst += 4 - cols + } + } + } else { + return function (value) { + if (value.length) { + view.set(value) + } else { + view[0] = value + } + } + } } /** @@ -8127,84 +9292,98 @@ function createUniformBlockUniformSetter(view, isArray, rows, cols) { * @return {module:twgl.UniformBlockInfo} The created UniformBlockInfo * @memberOf module:twgl/programs */ -function createUniformBlockInfoFromProgram(gl, program, uniformBlockSpec, blockName) { - const blockSpecs = uniformBlockSpec.blockSpecs; - const uniformData = uniformBlockSpec.uniformData; - const blockSpec = blockSpecs[blockName]; - if (!blockSpec) { - warn("no uniform block object named:", blockName); +function createUniformBlockInfoFromProgram( + gl, + program, + uniformBlockSpec, + blockName +) { + const blockSpecs = uniformBlockSpec.blockSpecs + const uniformData = uniformBlockSpec.uniformData + const blockSpec = blockSpecs[blockName] + if (!blockSpec) { + warn('no uniform block object named:', blockName) + return { + name: blockName, + uniforms: {}, + } + } + const array = new ArrayBuffer(blockSpec.size) + const buffer = gl.createBuffer() + const uniformBufferIndex = blockSpec.index + gl.bindBuffer(UNIFORM_BUFFER, buffer) + gl.uniformBlockBinding(program, blockSpec.index, uniformBufferIndex) + + let prefix = blockName + '.' + if (arraySuffixRE.test(prefix)) { + prefix = prefix.replace(arraySuffixRE, '.') + } + const uniforms = {} + const setters = {} + const setterTree = {} + blockSpec.uniformIndices.forEach(function (uniformNdx) { + const data = uniformData[uniformNdx] + let name = data.name + if (name.startsWith(prefix)) { + name = name.substr(prefix.length) + } + const isArray = name.endsWith('[0]') + if (isArray) { + name = name.substr(0, name.length - 3) + } + const typeInfo = typeMap[data.type] + const Type = typeInfo.Type + const byteLength = isArray + ? pad(typeInfo.size, 16) * data.size + : typeInfo.size * data.size + const uniformView = new Type( + array, + data.offset, + byteLength / Type.BYTES_PER_ELEMENT + ) + uniforms[name] = uniformView + // Note: I'm not sure what to do here. The original + // idea was to create TypedArray views into each part + // of the block. This is useful, for example if you have + // a block with { mat4: model; mat4 view; mat4 projection; } + // you'll get a Float32Array for each one suitable for + // passing to most JS math libraries including twgl's and glMatrix.js. + // + // But, if you have a an array of structures, especially if that + // array is large, you get a whole bunch of TypedArray views. + // Every one of them has overhead and switching between them all + // is probably a cache miss. In that case it would really be better + // to just have one view (asFloat) and have all the setters + // just reference the correct portion. But, then you can't easily + // treat a matrix, or a vec4, as a standalone thing like you can + // with all the views. + // + // Another problem with the views is they are not shared. With + // uniforms you have one set of setters. With UniformBlockInfo + // you have a set of setters *pre block instance*. That's because + // TypedArray views can't be mapped to different buffers. + // + // My gut right now is if you really want the speed and compactness + // then you should probably roll your own solution. TWGL's goal + // here is ease of use as AFAICT there is no simple generic efficient + // solution. + const setter = createUniformBlockUniformSetter( + uniformView, + isArray, + typeInfo.rows, + typeInfo.cols + ) + setters[name] = setter + addSetterToUniformTree(name, setter, setterTree, setters) + }) return { - name: blockName, - uniforms: {}, - }; - } - const array = new ArrayBuffer(blockSpec.size); - const buffer = gl.createBuffer(); - const uniformBufferIndex = blockSpec.index; - gl.bindBuffer(UNIFORM_BUFFER, buffer); - gl.uniformBlockBinding(program, blockSpec.index, uniformBufferIndex); - - let prefix = blockName + "."; - if (arraySuffixRE.test(prefix)) { - prefix = prefix.replace(arraySuffixRE, "."); - } - const uniforms = {}; - const setters = {}; - const setterTree = {}; - blockSpec.uniformIndices.forEach(function(uniformNdx) { - const data = uniformData[uniformNdx]; - let name = data.name; - if (name.startsWith(prefix)) { - name = name.substr(prefix.length); - } - const isArray = name.endsWith('[0]'); - if (isArray) { - name = name.substr(0, name.length - 3); - } - const typeInfo = typeMap[data.type]; - const Type = typeInfo.Type; - const byteLength = isArray - ? pad(typeInfo.size, 16) * data.size - : typeInfo.size * data.size; - const uniformView = new Type(array, data.offset, byteLength / Type.BYTES_PER_ELEMENT); - uniforms[name] = uniformView; - // Note: I'm not sure what to do here. The original - // idea was to create TypedArray views into each part - // of the block. This is useful, for example if you have - // a block with { mat4: model; mat4 view; mat4 projection; } - // you'll get a Float32Array for each one suitable for - // passing to most JS math libraries including twgl's and glMatrix.js. - // - // But, if you have a an array of structures, especially if that - // array is large, you get a whole bunch of TypedArray views. - // Every one of them has overhead and switching between them all - // is probably a cache miss. In that case it would really be better - // to just have one view (asFloat) and have all the setters - // just reference the correct portion. But, then you can't easily - // treat a matrix, or a vec4, as a standalone thing like you can - // with all the views. - // - // Another problem with the views is they are not shared. With - // uniforms you have one set of setters. With UniformBlockInfo - // you have a set of setters *pre block instance*. That's because - // TypedArray views can't be mapped to different buffers. - // - // My gut right now is if you really want the speed and compactness - // then you should probably roll your own solution. TWGL's goal - // here is ease of use as AFAICT there is no simple generic efficient - // solution. - const setter = createUniformBlockUniformSetter(uniformView, isArray, typeInfo.rows, typeInfo.cols); - setters[name] = setter; - addSetterToUniformTree(name, setter, setterTree, setters); - }); - return { - name: blockName, - array, - asFloat: new Float32Array(array), // for debugging - buffer, - uniforms, - setters, - }; + name: blockName, + array, + asFloat: new Float32Array(array), // for debugging + buffer, + uniforms, + setters, + } } /** @@ -8224,7 +9403,12 @@ function createUniformBlockInfoFromProgram(gl, program, uniformBlockSpec, blockN * @memberOf module:twgl/programs */ function createUniformBlockInfo(gl, programInfo, blockName) { - return createUniformBlockInfoFromProgram(gl, programInfo.program, programInfo.uniformBlockSpec, blockName); + return createUniformBlockInfoFromProgram( + gl, + programInfo.program, + programInfo.uniformBlockSpec, + blockName + ) } /** @@ -8246,14 +9430,20 @@ function createUniformBlockInfo(gl, programInfo, blockName) { * @memberOf module:twgl/programs */ function bindUniformBlock(gl, programInfo, uniformBlockInfo) { - const uniformBlockSpec = programInfo.uniformBlockSpec || programInfo; - const blockSpec = uniformBlockSpec.blockSpecs[uniformBlockInfo.name]; - if (blockSpec) { - const bufferBindIndex = blockSpec.index; - gl.bindBufferRange(UNIFORM_BUFFER, bufferBindIndex, uniformBlockInfo.buffer, uniformBlockInfo.offset || 0, uniformBlockInfo.array.byteLength); - return true; - } - return false; + const uniformBlockSpec = programInfo.uniformBlockSpec || programInfo + const blockSpec = uniformBlockSpec.blockSpecs[uniformBlockInfo.name] + if (blockSpec) { + const bufferBindIndex = blockSpec.index + gl.bindBufferRange( + UNIFORM_BUFFER, + bufferBindIndex, + uniformBlockInfo.buffer, + uniformBlockInfo.offset || 0, + uniformBlockInfo.array.byteLength + ) + return true + } + return false } /** @@ -8272,9 +9462,9 @@ function bindUniformBlock(gl, programInfo, uniformBlockInfo) { * @memberOf module:twgl/programs */ function setUniformBlock(gl, programInfo, uniformBlockInfo) { - if (bindUniformBlock(gl, programInfo, uniformBlockInfo)) { - gl.bufferData(UNIFORM_BUFFER, uniformBlockInfo.array, DYNAMIC_DRAW); - } + if (bindUniformBlock(gl, programInfo, uniformBlockInfo)) { + gl.bufferData(UNIFORM_BUFFER, uniformBlockInfo.array, DYNAMIC_DRAW) + } } /** @@ -8363,25 +9553,25 @@ function setUniformBlock(gl, programInfo, uniformBlockInfo) { * @memberOf module:twgl/programs */ function setBlockUniforms(uniformBlockInfo, values) { - const setters = uniformBlockInfo.setters; - for (const name in values) { - const setter = setters[name]; - if (setter) { - const value = values[name]; - setter(value); + const setters = uniformBlockInfo.setters + for (const name in values) { + const setter = setters[name] + if (setter) { + const value = values[name] + setter(value) + } } - } } function setUniformTree(tree, values) { - for (const name in values) { - const prop = tree[name]; - if (typeof prop === 'function') { - prop(values[name]); - } else { - setUniformTree(tree[name], values[name]); + for (const name in values) { + const prop = tree[name] + if (typeof prop === 'function') { + prop(values[name]) + } else { + setUniformTree(tree[name], values[name]) + } } - } } /** @@ -8542,25 +9732,26 @@ function setUniformTree(tree, values) { * * @memberOf module:twgl/programs */ -function setUniforms(setters, ...args) { // eslint-disable-line - const actualSetters = setters.uniformSetters || setters; - const numArgs = args.length; - for (let aNdx = 0; aNdx < numArgs; ++aNdx) { - const values = args[aNdx]; - if (Array.isArray(values)) { - const numValues = values.length; - for (let ii = 0; ii < numValues; ++ii) { - setUniforms(actualSetters, values[ii]); - } - } else { - for (const name in values) { - const setter = actualSetters[name]; - if (setter) { - setter(values[name]); +function setUniforms(setters, ...args) { + // eslint-disable-line + const actualSetters = setters.uniformSetters || setters + const numArgs = args.length + for (let aNdx = 0; aNdx < numArgs; ++aNdx) { + const values = args[aNdx] + if (Array.isArray(values)) { + const numValues = values.length + for (let ii = 0; ii < numValues; ++ii) { + setUniforms(actualSetters, values[ii]) + } + } else { + for (const name in values) { + const setter = actualSetters[name] + if (setter) { + setter(values[name]) + } + } } - } } - } } /** @@ -8571,7 +9762,7 @@ function setUniforms(setters, ...args) { // eslint-disable-line * @param {Object.} values an object with values for the * @memberOf module:twgl/programs */ -const setUniformsAndBindTextures = setUniforms; +const setUniformsAndBindTextures = setUniforms /** * Creates setter functions for all attributes of a shader @@ -8584,23 +9775,22 @@ const setUniformsAndBindTextures = setUniforms; * @memberOf module:twgl/programs */ function createAttributeSetters(gl, program) { - const attribSetters = { - }; + const attribSetters = {} - const numAttribs = gl.getProgramParameter(program, ACTIVE_ATTRIBUTES); - for (let ii = 0; ii < numAttribs; ++ii) { - const attribInfo = gl.getActiveAttrib(program, ii); - if (isBuiltIn(attribInfo)) { - continue; + const numAttribs = gl.getProgramParameter(program, ACTIVE_ATTRIBUTES) + for (let ii = 0; ii < numAttribs; ++ii) { + const attribInfo = gl.getActiveAttrib(program, ii) + if (isBuiltIn(attribInfo)) { + continue + } + const index = gl.getAttribLocation(program, attribInfo.name) + const typeInfo = attrTypeMap[attribInfo.type] + const setter = typeInfo.setter(gl, index, typeInfo) + setter.location = index + attribSetters[attribInfo.name] = setter } - const index = gl.getAttribLocation(program, attribInfo.name); - const typeInfo = attrTypeMap[attribInfo.type]; - const setter = typeInfo.setter(gl, index, typeInfo); - setter.location = index; - attribSetters[attribInfo.name] = setter; - } - return attribSetters; + return attribSetters } /** @@ -8659,12 +9849,12 @@ function createAttributeSetters(gl, program) { * @private */ function setAttributes(setters, buffers) { - for (const name in buffers) { - const setter = setters[name]; - if (setter) { - setter(buffers[name]); + for (const name in buffers) { + const setter = setters[name] + if (setter) { + setter(buffers[name]) + } } - } } /** @@ -8705,14 +9895,14 @@ function setAttributes(setters, buffers) { * @memberOf module:twgl/programs */ function setBuffersAndAttributes(gl, programInfo, buffers) { - if (buffers.vertexArrayObject) { - gl.bindVertexArray(buffers.vertexArrayObject); - } else { - setAttributes(programInfo.attribSetters || programInfo, buffers.attribs); - if (buffers.indices) { - gl.bindBuffer(ELEMENT_ARRAY_BUFFER$1, buffers.indices); + if (buffers.vertexArrayObject) { + gl.bindVertexArray(buffers.vertexArrayObject) + } else { + setAttributes(programInfo.attribSetters || programInfo, buffers.attribs) + if (buffers.indices) { + gl.bindBuffer(ELEMENT_ARRAY_BUFFER$1, buffers.indices) + } } - } } /** @@ -8743,23 +9933,29 @@ function setBuffersAndAttributes(gl, programInfo, buffers) { * @memberOf module:twgl/programs */ function createProgramInfoFromProgram(gl, program) { - const uniformSetters = createUniformSetters(gl, program); - const attribSetters = createAttributeSetters(gl, program); - const programInfo = { - program, - uniformSetters, - attribSetters, - }; + const uniformSetters = createUniformSetters(gl, program) + const attribSetters = createAttributeSetters(gl, program) + const programInfo = { + program, + uniformSetters, + attribSetters, + } - if (isWebGL2(gl)) { - programInfo.uniformBlockSpec = createUniformBlockSpecFromProgram(gl, program); - programInfo.transformFeedbackInfo = createTransformFeedbackInfo(gl, program); - } + if (isWebGL2(gl)) { + programInfo.uniformBlockSpec = createUniformBlockSpecFromProgram( + gl, + program + ) + programInfo.transformFeedbackInfo = createTransformFeedbackInfo( + gl, + program + ) + } - return programInfo; + return programInfo } -const notIdRE = /\s|{|}|;/; +const notIdRE = /\s|{|}|;/ /** * Creates a ProgramInfo from 2 sources. @@ -8792,69 +9988,87 @@ const notIdRE = /\s|{|}|;/; * @memberOf module:twgl/programs */ function createProgramInfo( - gl, shaderSources, opt_attribs, opt_locations, opt_errorCallback) { - const progOptions = getProgramOptions(opt_attribs, opt_locations, opt_errorCallback); - const errors = []; - shaderSources = shaderSources.map(function(source) { - // Lets assume if there is no \n it's an id - if (!notIdRE.test(source)) { - const script = getElementById(source); - if (!script) { - const err = `no element with id: ${source}`; - progOptions.errorCallback(err); - errors.push(err); - } else { - source = script.text; - } - } - return source; - }); - - if (errors.length) { - return reportError(progOptions, ''); - } - - const origCallback = progOptions.callback; - if (origCallback) { - progOptions.callback = (err, program) => { - origCallback(err, err ? undefined : createProgramInfoFromProgram(gl, program)); - }; - } - - const program = createProgramFromSources(gl, shaderSources, progOptions); - if (!program) { - return null; - } - - return createProgramInfoFromProgram(gl, program); -} - -function checkAllPrograms(gl, programs, programSpecs, noDeleteShadersSet, programOptions) { - // check errors for everything. - for (const [name, program] of Object.entries(programs)) { - const options = {...programOptions}; - const spec = programSpecs[name]; - if (!Array.isArray(spec)) { - Object.assign(options, spec); - } - const errors = getProgramErrors(gl, program, options.errorCallback); - if (errors) { - // delete everything we created - for (const program of Object.values(programs)) { - const shaders = gl.getAttachedShaders(program); - gl.deleteProgram(program); - for (const shader of shaders) { - // Don't delete it if we didn't create it. - if (!noDeleteShadersSet.has(shader)) { - gl.deleteShader(shader); - } + gl, + shaderSources, + opt_attribs, + opt_locations, + opt_errorCallback +) { + const progOptions = getProgramOptions( + opt_attribs, + opt_locations, + opt_errorCallback + ) + const errors = [] + shaderSources = shaderSources.map(function (source) { + // Lets assume if there is no \n it's an id + if (!notIdRE.test(source)) { + const script = getElementById(source) + if (!script) { + const err = `no element with id: ${source}` + progOptions.errorCallback(err) + errors.push(err) + } else { + source = script.text + } + } + return source + }) + + if (errors.length) { + return reportError(progOptions, '') + } + + const origCallback = progOptions.callback + if (origCallback) { + progOptions.callback = (err, program) => { + origCallback( + err, + err ? undefined : createProgramInfoFromProgram(gl, program) + ) + } + } + + const program = createProgramFromSources(gl, shaderSources, progOptions) + if (!program) { + return null + } + + return createProgramInfoFromProgram(gl, program) +} + +function checkAllPrograms( + gl, + programs, + programSpecs, + noDeleteShadersSet, + programOptions +) { + // check errors for everything. + for (const [name, program] of Object.entries(programs)) { + const options = { ...programOptions } + const spec = programSpecs[name] + if (!Array.isArray(spec)) { + Object.assign(options, spec) + } + const errors = getProgramErrors(gl, program, options.errorCallback) + if (errors) { + // delete everything we created + for (const program of Object.values(programs)) { + const shaders = gl.getAttachedShaders(program) + gl.deleteProgram(program) + for (const shader of shaders) { + // Don't delete it if we didn't create it. + if (!noDeleteShadersSet.has(shader)) { + gl.deleteShader(shader) + } + } + } + return errors } - } - return errors; } - } - return undefined; + return undefined } /** @@ -8883,30 +10097,44 @@ function checkAllPrograms(gl, programs, programSpecs, noDeleteShadersSet, progra * @return {Object.?} the created programInfos by name */ function createPrograms(gl, programSpecs, programOptions = {}) { - // Remember existing shaders so that if there is an error we don't delete them - const noDeleteShadersSet = new Set(); - - // compile and link everything - const programs = Object.fromEntries(Object.entries(programSpecs).map(([name, spec]) => { - const options = {...programOptions}; - const shaders = Array.isArray(spec) ? spec : spec.shaders; - if (!Array.isArray(spec)) { - Object.assign(options, spec); + // Remember existing shaders so that if there is an error we don't delete them + const noDeleteShadersSet = new Set() + + // compile and link everything + const programs = Object.fromEntries( + Object.entries(programSpecs).map(([name, spec]) => { + const options = { ...programOptions } + const shaders = Array.isArray(spec) ? spec : spec.shaders + if (!Array.isArray(spec)) { + Object.assign(options, spec) + } + shaders.forEach(noDeleteShadersSet.add, noDeleteShadersSet) + return [name, createProgramNoCheck(gl, shaders, options)] + }) + ) + + if (programOptions.callback) { + waitForAllProgramsLinkCompletionAsync(gl, programs).then(() => { + const errors = checkAllPrograms( + gl, + programs, + programSpecs, + noDeleteShadersSet, + programOptions + ) + programOptions.callback(errors, errors ? undefined : programs) + }) + return undefined } - shaders.forEach(noDeleteShadersSet.add, noDeleteShadersSet); - return [name, createProgramNoCheck(gl, shaders, options)]; - })); - if (programOptions.callback) { - waitForAllProgramsLinkCompletionAsync(gl, programs).then(() => { - const errors = checkAllPrograms(gl, programs, programSpecs, noDeleteShadersSet, programOptions); - programOptions.callback(errors, errors ? undefined : programs); - }); - return undefined; - } - - const errors = checkAllPrograms(gl, programs, programSpecs, noDeleteShadersSet, programOptions); - return errors ? undefined : programs; + const errors = checkAllPrograms( + gl, + programs, + programSpecs, + noDeleteShadersSet, + programOptions + ) + return errors ? undefined : programs } /** @@ -8947,27 +10175,33 @@ function createPrograms(gl, programSpecs, programOptions = {}) { * @return {Object.?} the created programInfos by name */ function createProgramInfos(gl, programSpecs, programOptions) { - programOptions = getProgramOptions(programOptions); - - function createProgramInfosForPrograms(gl, programs) { - return Object.fromEntries(Object.entries(programs).map(([name, program]) => - [name, createProgramInfoFromProgram(gl, program)] - )); - } + programOptions = getProgramOptions(programOptions) + + function createProgramInfosForPrograms(gl, programs) { + return Object.fromEntries( + Object.entries(programs).map(([name, program]) => [ + name, + createProgramInfoFromProgram(gl, program), + ]) + ) + } - const origCallback = programOptions.callback; - if (origCallback) { - programOptions.callback = (err, programs) => { - origCallback(err, err ? undefined : createProgramInfosForPrograms(gl, programs)); - }; - } + const origCallback = programOptions.callback + if (origCallback) { + programOptions.callback = (err, programs) => { + origCallback( + err, + err ? undefined : createProgramInfosForPrograms(gl, programs) + ) + } + } - const programs = createPrograms(gl, programSpecs, programOptions); - if (origCallback || !programs) { - return undefined; - } + const programs = createPrograms(gl, programSpecs, programOptions) + if (origCallback || !programs) { + return undefined + } - return createProgramInfosForPrograms(gl, programs); + return createProgramInfosForPrograms(gl, programs) } /** @@ -8992,7 +10226,7 @@ function createProgramInfos(gl, programSpecs, programOptions) { * @param {module:twgl.ProgramOptions} [programOptions] options to apply to all programs * @return {Object.?} the created programInfos by name */ -const createProgramsAsync = wrapCallbackFnToAsyncFn(createPrograms); +const createProgramsAsync = wrapCallbackFnToAsyncFn(createPrograms) /** * Creates multiple programInfos asynchronously @@ -9016,37 +10250,37 @@ const createProgramsAsync = wrapCallbackFnToAsyncFn(createPrograms); * @param {module:twgl.ProgramOptions} [programOptions] options to apply to all programs * @return {Promise>} the created programInfos by name */ -const createProgramInfosAsync = wrapCallbackFnToAsyncFn(createProgramInfos); - -var programs = /*#__PURE__*/Object.freeze({ - __proto__: null, - createAttributeSetters: createAttributeSetters, - createProgram: createProgram, - createProgramAsync: createProgramAsync, - createPrograms: createPrograms, - createProgramsAsync: createProgramsAsync, - createProgramFromScripts: createProgramFromScripts, - createProgramFromSources: createProgramFromSources, - createProgramInfo: createProgramInfo, - createProgramInfoAsync: createProgramInfoAsync, - createProgramInfos: createProgramInfos, - createProgramInfosAsync: createProgramInfosAsync, - createProgramInfoFromProgram: createProgramInfoFromProgram, - createUniformSetters: createUniformSetters, - createUniformBlockSpecFromProgram: createUniformBlockSpecFromProgram, - createUniformBlockInfoFromProgram: createUniformBlockInfoFromProgram, - createUniformBlockInfo: createUniformBlockInfo, - createTransformFeedback: createTransformFeedback, - createTransformFeedbackInfo: createTransformFeedbackInfo, - bindTransformFeedbackInfo: bindTransformFeedbackInfo, - setAttributes: setAttributes, - setBuffersAndAttributes: setBuffersAndAttributes, - setUniforms: setUniforms, - setUniformsAndBindTextures: setUniformsAndBindTextures, - setUniformBlock: setUniformBlock, - setBlockUniforms: setBlockUniforms, - bindUniformBlock: bindUniformBlock -}); +const createProgramInfosAsync = wrapCallbackFnToAsyncFn(createProgramInfos) + +var programs = /*#__PURE__*/ Object.freeze({ + __proto__: null, + createAttributeSetters: createAttributeSetters, + createProgram: createProgram, + createProgramAsync: createProgramAsync, + createPrograms: createPrograms, + createProgramsAsync: createProgramsAsync, + createProgramFromScripts: createProgramFromScripts, + createProgramFromSources: createProgramFromSources, + createProgramInfo: createProgramInfo, + createProgramInfoAsync: createProgramInfoAsync, + createProgramInfos: createProgramInfos, + createProgramInfosAsync: createProgramInfosAsync, + createProgramInfoFromProgram: createProgramInfoFromProgram, + createUniformSetters: createUniformSetters, + createUniformBlockSpecFromProgram: createUniformBlockSpecFromProgram, + createUniformBlockInfoFromProgram: createUniformBlockInfoFromProgram, + createUniformBlockInfo: createUniformBlockInfo, + createTransformFeedback: createTransformFeedback, + createTransformFeedbackInfo: createTransformFeedbackInfo, + bindTransformFeedbackInfo: bindTransformFeedbackInfo, + setAttributes: setAttributes, + setBuffersAndAttributes: setBuffersAndAttributes, + setUniforms: setUniforms, + setUniformsAndBindTextures: setUniformsAndBindTextures, + setUniformBlock: setUniformBlock, + setBlockUniforms: setBlockUniforms, + bindUniformBlock: bindUniformBlock, +}) /* * Copyright 2019 Gregg Tavares @@ -9070,8 +10304,8 @@ var programs = /*#__PURE__*/Object.freeze({ * DEALINGS IN THE SOFTWARE. */ -const TRIANGLES = 0x0004; -const UNSIGNED_SHORT = 0x1403; +const TRIANGLES = 0x0004 +const UNSIGNED_SHORT = 0x1403 /** * Drawing related functions @@ -9101,24 +10335,39 @@ const UNSIGNED_SHORT = 0x1403; * @memberOf module:twgl/draw */ function drawBufferInfo(gl, bufferInfo, type, count, offset, instanceCount) { - type = type === undefined ? TRIANGLES : type; - const indices = bufferInfo.indices; - const elementType = bufferInfo.elementType; - const numElements = count === undefined ? bufferInfo.numElements : count; - offset = offset === undefined ? 0 : offset; - if (elementType || indices) { - if (instanceCount !== undefined) { - gl.drawElementsInstanced(type, numElements, elementType === undefined ? UNSIGNED_SHORT : bufferInfo.elementType, offset, instanceCount); - } else { - gl.drawElements(type, numElements, elementType === undefined ? UNSIGNED_SHORT : bufferInfo.elementType, offset); - } - } else { - if (instanceCount !== undefined) { - gl.drawArraysInstanced(type, offset, numElements, instanceCount); + type = type === undefined ? TRIANGLES : type + const indices = bufferInfo.indices + const elementType = bufferInfo.elementType + const numElements = count === undefined ? bufferInfo.numElements : count + offset = offset === undefined ? 0 : offset + if (elementType || indices) { + if (instanceCount !== undefined) { + gl.drawElementsInstanced( + type, + numElements, + elementType === undefined + ? UNSIGNED_SHORT + : bufferInfo.elementType, + offset, + instanceCount + ) + } else { + gl.drawElements( + type, + numElements, + elementType === undefined + ? UNSIGNED_SHORT + : bufferInfo.elementType, + offset + ) + } } else { - gl.drawArrays(type, offset, numElements); + if (instanceCount !== undefined) { + gl.drawArraysInstanced(type, offset, numElements, instanceCount) + } else { + gl.drawArrays(type, offset, numElements) + } } - } } /** @@ -9164,56 +10413,67 @@ function drawBufferInfo(gl, bufferInfo, type, count, offset, instanceCount) { * @memberOf module:twgl/draw */ function drawObjectList(gl, objectsToDraw) { - let lastUsedProgramInfo = null; - let lastUsedBufferInfo = null; - - objectsToDraw.forEach(function(object) { - if (object.active === false) { - return; - } + let lastUsedProgramInfo = null + let lastUsedBufferInfo = null - const programInfo = object.programInfo; - const bufferInfo = object.vertexArrayInfo || object.bufferInfo; - let bindBuffers = false; - const type = object.type === undefined ? TRIANGLES : object.type; - - if (programInfo !== lastUsedProgramInfo) { - lastUsedProgramInfo = programInfo; - gl.useProgram(programInfo.program); + objectsToDraw.forEach(function (object) { + if (object.active === false) { + return + } - // We have to rebind buffers when changing programs because we - // only bind buffers the program uses. So if 2 programs use the same - // bufferInfo but the 1st one uses only positions the when the - // we switch to the 2nd one some of the attributes will not be on. - bindBuffers = true; - } + const programInfo = object.programInfo + const bufferInfo = object.vertexArrayInfo || object.bufferInfo + let bindBuffers = false + const type = object.type === undefined ? TRIANGLES : object.type - // Setup all the needed attributes. - if (bindBuffers || bufferInfo !== lastUsedBufferInfo) { - if (lastUsedBufferInfo && lastUsedBufferInfo.vertexArrayObject && !bufferInfo.vertexArrayObject) { - gl.bindVertexArray(null); - } - lastUsedBufferInfo = bufferInfo; - setBuffersAndAttributes(gl, programInfo, bufferInfo); - } + if (programInfo !== lastUsedProgramInfo) { + lastUsedProgramInfo = programInfo + gl.useProgram(programInfo.program) - // Set the uniforms. - setUniforms(programInfo, object.uniforms); + // We have to rebind buffers when changing programs because we + // only bind buffers the program uses. So if 2 programs use the same + // bufferInfo but the 1st one uses only positions the when the + // we switch to the 2nd one some of the attributes will not be on. + bindBuffers = true + } - // Draw - drawBufferInfo(gl, bufferInfo, type, object.count, object.offset, object.instanceCount); - }); + // Setup all the needed attributes. + if (bindBuffers || bufferInfo !== lastUsedBufferInfo) { + if ( + lastUsedBufferInfo && + lastUsedBufferInfo.vertexArrayObject && + !bufferInfo.vertexArrayObject + ) { + gl.bindVertexArray(null) + } + lastUsedBufferInfo = bufferInfo + setBuffersAndAttributes(gl, programInfo, bufferInfo) + } - if (lastUsedBufferInfo && lastUsedBufferInfo.vertexArrayObject) { - gl.bindVertexArray(null); - } + // Set the uniforms. + setUniforms(programInfo, object.uniforms) + + // Draw + drawBufferInfo( + gl, + bufferInfo, + type, + object.count, + object.offset, + object.instanceCount + ) + }) + + if (lastUsedBufferInfo && lastUsedBufferInfo.vertexArrayObject) { + gl.bindVertexArray(null) + } } -var draw = /*#__PURE__*/Object.freeze({ - __proto__: null, - drawBufferInfo: drawBufferInfo, - drawObjectList: drawObjectList -}); +var draw = /*#__PURE__*/ Object.freeze({ + __proto__: null, + drawBufferInfo: drawBufferInfo, + drawObjectList: drawObjectList, +}) /* * Copyright 2019 Gregg Tavares @@ -9237,38 +10497,38 @@ var draw = /*#__PURE__*/Object.freeze({ * DEALINGS IN THE SOFTWARE. */ -const FRAMEBUFFER = 0x8d40; -const RENDERBUFFER = 0x8d41; -const TEXTURE_2D = 0x0de1; +const FRAMEBUFFER = 0x8d40 +const RENDERBUFFER = 0x8d41 +const TEXTURE_2D = 0x0de1 -const UNSIGNED_BYTE = 0x1401; +const UNSIGNED_BYTE = 0x1401 /* PixelFormat */ -const DEPTH_COMPONENT = 0x1902; -const RGBA = 0x1908; -const DEPTH_COMPONENT24 = 0x81a6; -const DEPTH_COMPONENT32F = 0x8cac; -const DEPTH24_STENCIL8 = 0x88f0; -const DEPTH32F_STENCIL8 = 0x8cad; +const DEPTH_COMPONENT = 0x1902 +const RGBA = 0x1908 +const DEPTH_COMPONENT24 = 0x81a6 +const DEPTH_COMPONENT32F = 0x8cac +const DEPTH24_STENCIL8 = 0x88f0 +const DEPTH32F_STENCIL8 = 0x8cad /* Framebuffer Object. */ -const RGBA4 = 0x8056; -const RGB5_A1 = 0x8057; -const RGB565 = 0x8D62; -const DEPTH_COMPONENT16 = 0x81A5; -const STENCIL_INDEX = 0x1901; -const STENCIL_INDEX8 = 0x8D48; -const DEPTH_STENCIL = 0x84F9; -const COLOR_ATTACHMENT0 = 0x8CE0; -const DEPTH_ATTACHMENT = 0x8D00; -const STENCIL_ATTACHMENT = 0x8D20; -const DEPTH_STENCIL_ATTACHMENT = 0x821A; +const RGBA4 = 0x8056 +const RGB5_A1 = 0x8057 +const RGB565 = 0x8d62 +const DEPTH_COMPONENT16 = 0x81a5 +const STENCIL_INDEX = 0x1901 +const STENCIL_INDEX8 = 0x8d48 +const DEPTH_STENCIL = 0x84f9 +const COLOR_ATTACHMENT0 = 0x8ce0 +const DEPTH_ATTACHMENT = 0x8d00 +const STENCIL_ATTACHMENT = 0x8d20 +const DEPTH_STENCIL_ATTACHMENT = 0x821a /* TextureWrapMode */ -const CLAMP_TO_EDGE = 0x812F; +const CLAMP_TO_EDGE = 0x812f /* TextureMagFilter */ -const LINEAR = 0x2601; +const LINEAR = 0x2601 /** * The options for a framebuffer attachment. @@ -9303,42 +10563,45 @@ const LINEAR = 0x2601; */ const defaultAttachments = [ - { format: RGBA, type: UNSIGNED_BYTE, min: LINEAR, wrap: CLAMP_TO_EDGE, }, - { format: DEPTH_STENCIL, }, -]; - -const attachmentsByFormat = {}; -attachmentsByFormat[DEPTH_STENCIL] = DEPTH_STENCIL_ATTACHMENT; -attachmentsByFormat[STENCIL_INDEX] = STENCIL_ATTACHMENT; -attachmentsByFormat[STENCIL_INDEX8] = STENCIL_ATTACHMENT; -attachmentsByFormat[DEPTH_COMPONENT] = DEPTH_ATTACHMENT; -attachmentsByFormat[DEPTH_COMPONENT16] = DEPTH_ATTACHMENT; -attachmentsByFormat[DEPTH_COMPONENT24] = DEPTH_ATTACHMENT; -attachmentsByFormat[DEPTH_COMPONENT32F] = DEPTH_ATTACHMENT; -attachmentsByFormat[DEPTH24_STENCIL8] = DEPTH_STENCIL_ATTACHMENT; -attachmentsByFormat[DEPTH32F_STENCIL8] = DEPTH_STENCIL_ATTACHMENT; + { format: RGBA, type: UNSIGNED_BYTE, min: LINEAR, wrap: CLAMP_TO_EDGE }, + { format: DEPTH_STENCIL }, +] + +const attachmentsByFormat = {} +attachmentsByFormat[DEPTH_STENCIL] = DEPTH_STENCIL_ATTACHMENT +attachmentsByFormat[STENCIL_INDEX] = STENCIL_ATTACHMENT +attachmentsByFormat[STENCIL_INDEX8] = STENCIL_ATTACHMENT +attachmentsByFormat[DEPTH_COMPONENT] = DEPTH_ATTACHMENT +attachmentsByFormat[DEPTH_COMPONENT16] = DEPTH_ATTACHMENT +attachmentsByFormat[DEPTH_COMPONENT24] = DEPTH_ATTACHMENT +attachmentsByFormat[DEPTH_COMPONENT32F] = DEPTH_ATTACHMENT +attachmentsByFormat[DEPTH24_STENCIL8] = DEPTH_STENCIL_ATTACHMENT +attachmentsByFormat[DEPTH32F_STENCIL8] = DEPTH_STENCIL_ATTACHMENT function getAttachmentPointForFormat(format, internalFormat) { - return attachmentsByFormat[format] || attachmentsByFormat[internalFormat]; + return attachmentsByFormat[format] || attachmentsByFormat[internalFormat] } -const renderbufferFormats = {}; -renderbufferFormats[RGBA4] = true; -renderbufferFormats[RGB5_A1] = true; -renderbufferFormats[RGB565] = true; -renderbufferFormats[DEPTH_STENCIL] = true; -renderbufferFormats[DEPTH_COMPONENT16] = true; -renderbufferFormats[STENCIL_INDEX] = true; -renderbufferFormats[STENCIL_INDEX8] = true; +const renderbufferFormats = {} +renderbufferFormats[RGBA4] = true +renderbufferFormats[RGB5_A1] = true +renderbufferFormats[RGB565] = true +renderbufferFormats[DEPTH_STENCIL] = true +renderbufferFormats[DEPTH_COMPONENT16] = true +renderbufferFormats[STENCIL_INDEX] = true +renderbufferFormats[STENCIL_INDEX8] = true function isRenderbufferFormat(format) { - return renderbufferFormats[format]; + return renderbufferFormats[format] } -const MAX_COLOR_ATTACHMENT_POINTS = 32; // even an 3090 only supports 8 but WebGL/OpenGL ES define constants for 32 +const MAX_COLOR_ATTACHMENT_POINTS = 32 // even an 3090 only supports 8 but WebGL/OpenGL ES define constants for 32 function isColorAttachmentPoint(attachmentPoint) { - return attachmentPoint >= COLOR_ATTACHMENT0 && attachmentPoint < COLOR_ATTACHMENT0 + MAX_COLOR_ATTACHMENT_POINTS; + return ( + attachmentPoint >= COLOR_ATTACHMENT0 && + attachmentPoint < COLOR_ATTACHMENT0 + MAX_COLOR_ATTACHMENT_POINTS + ) } /** @@ -9390,81 +10653,107 @@ function isColorAttachmentPoint(attachmentPoint) { * @memberOf module:twgl/framebuffers */ function createFramebufferInfo(gl, attachments, width, height) { - const target = FRAMEBUFFER; - const fb = gl.createFramebuffer(); - gl.bindFramebuffer(target, fb); - width = width || gl.drawingBufferWidth; - height = height || gl.drawingBufferHeight; - attachments = attachments || defaultAttachments; - const usedColorAttachmentsPoints = []; - const framebufferInfo = { - framebuffer: fb, - attachments: [], - width: width, - height: height, - }; - - attachments.forEach(function(attachmentOptions, i) { - let attachment = attachmentOptions.attachment; - const samples = attachmentOptions.samples; - const format = attachmentOptions.format; - let attachmentPoint = attachmentOptions.attachmentPoint || getAttachmentPointForFormat(format, attachmentOptions.internalFormat); - if (!attachmentPoint) { - attachmentPoint = COLOR_ATTACHMENT0 + i; - } - if (isColorAttachmentPoint(attachmentPoint)) { - usedColorAttachmentsPoints.push(attachmentPoint); - } - if (!attachment) { - if (samples !== undefined || isRenderbufferFormat(format)) { - attachment = gl.createRenderbuffer(); - gl.bindRenderbuffer(RENDERBUFFER, attachment); - if (samples > 1) { - gl.renderbufferStorageMultisample(RENDERBUFFER, samples, format, width, height); + const target = FRAMEBUFFER + const fb = gl.createFramebuffer() + gl.bindFramebuffer(target, fb) + width = width || gl.drawingBufferWidth + height = height || gl.drawingBufferHeight + attachments = attachments || defaultAttachments + const usedColorAttachmentsPoints = [] + const framebufferInfo = { + framebuffer: fb, + attachments: [], + width: width, + height: height, + } + + attachments.forEach(function (attachmentOptions, i) { + let attachment = attachmentOptions.attachment + const samples = attachmentOptions.samples + const format = attachmentOptions.format + let attachmentPoint = + attachmentOptions.attachmentPoint || + getAttachmentPointForFormat( + format, + attachmentOptions.internalFormat + ) + if (!attachmentPoint) { + attachmentPoint = COLOR_ATTACHMENT0 + i + } + if (isColorAttachmentPoint(attachmentPoint)) { + usedColorAttachmentsPoints.push(attachmentPoint) + } + if (!attachment) { + if (samples !== undefined || isRenderbufferFormat(format)) { + attachment = gl.createRenderbuffer() + gl.bindRenderbuffer(RENDERBUFFER, attachment) + if (samples > 1) { + gl.renderbufferStorageMultisample( + RENDERBUFFER, + samples, + format, + width, + height + ) + } else { + gl.renderbufferStorage(RENDERBUFFER, format, width, height) + } + } else { + const textureOptions = Object.assign({}, attachmentOptions) + textureOptions.width = width + textureOptions.height = height + if (textureOptions.auto === undefined) { + textureOptions.auto = false + textureOptions.min = + textureOptions.min || textureOptions.minMag || LINEAR + textureOptions.mag = + textureOptions.mag || textureOptions.minMag || LINEAR + textureOptions.wrapS = + textureOptions.wrapS || + textureOptions.wrap || + CLAMP_TO_EDGE + textureOptions.wrapT = + textureOptions.wrapT || + textureOptions.wrap || + CLAMP_TO_EDGE + } + attachment = createTexture(gl, textureOptions) + } + } + if (isRenderbuffer(gl, attachment)) { + gl.framebufferRenderbuffer( + target, + attachmentPoint, + RENDERBUFFER, + attachment + ) + } else if (isTexture(gl, attachment)) { + if (attachmentOptions.layer !== undefined) { + gl.framebufferTextureLayer( + target, + attachmentPoint, + attachment, + attachmentOptions.level || 0, + attachmentOptions.layer + ) + } else { + gl.framebufferTexture2D( + target, + attachmentPoint, + attachmentOptions.target || TEXTURE_2D, + attachment, + attachmentOptions.level || 0 + ) + } } else { - gl.renderbufferStorage(RENDERBUFFER, format, width, height); - } - } else { - const textureOptions = Object.assign({}, attachmentOptions); - textureOptions.width = width; - textureOptions.height = height; - if (textureOptions.auto === undefined) { - textureOptions.auto = false; - textureOptions.min = textureOptions.min || textureOptions.minMag || LINEAR; - textureOptions.mag = textureOptions.mag || textureOptions.minMag || LINEAR; - textureOptions.wrapS = textureOptions.wrapS || textureOptions.wrap || CLAMP_TO_EDGE; - textureOptions.wrapT = textureOptions.wrapT || textureOptions.wrap || CLAMP_TO_EDGE; - } - attachment = createTexture(gl, textureOptions); - } - } - if (isRenderbuffer(gl, attachment)) { - gl.framebufferRenderbuffer(target, attachmentPoint, RENDERBUFFER, attachment); - } else if (isTexture(gl, attachment)) { - if (attachmentOptions.layer !== undefined) { - gl.framebufferTextureLayer( - target, - attachmentPoint, - attachment, - attachmentOptions.level || 0, - attachmentOptions.layer); - } else { - gl.framebufferTexture2D( - target, - attachmentPoint, - attachmentOptions.target || TEXTURE_2D, - attachment, - attachmentOptions.level || 0); - } - } else { - throw new Error('unknown attachment type'); + throw new Error('unknown attachment type') + } + framebufferInfo.attachments.push(attachment) + }) + if (gl.drawBuffers) { + gl.drawBuffers(usedColorAttachmentsPoints) } - framebufferInfo.attachments.push(attachment); - }); - if (gl.drawBuffers) { - gl.drawBuffers(usedColorAttachmentsPoints); - } - return framebufferInfo; + return framebufferInfo } /** @@ -9510,29 +10799,41 @@ function createFramebufferInfo(gl, attachments, width, height) { * @param {number} [height] the height for the attachments. Default = size of drawingBuffer * @memberOf module:twgl/framebuffers */ -function resizeFramebufferInfo(gl, framebufferInfo, attachments, width, height) { - width = width || gl.drawingBufferWidth; - height = height || gl.drawingBufferHeight; - framebufferInfo.width = width; - framebufferInfo.height = height; - attachments = attachments || defaultAttachments; - attachments.forEach(function(attachmentOptions, ndx) { - const attachment = framebufferInfo.attachments[ndx]; - const format = attachmentOptions.format; - const samples = attachmentOptions.samples; - if (samples !== undefined || isRenderbuffer(gl, attachment)) { - gl.bindRenderbuffer(RENDERBUFFER, attachment); - if (samples > 1) { - gl.renderbufferStorageMultisample(RENDERBUFFER, samples, format, width, height); - } else { - gl.renderbufferStorage(RENDERBUFFER, format, width, height); - } - } else if (isTexture(gl, attachment)) { - resizeTexture(gl, attachment, attachmentOptions, width, height); - } else { - throw new Error('unknown attachment type'); - } - }); +function resizeFramebufferInfo( + gl, + framebufferInfo, + attachments, + width, + height +) { + width = width || gl.drawingBufferWidth + height = height || gl.drawingBufferHeight + framebufferInfo.width = width + framebufferInfo.height = height + attachments = attachments || defaultAttachments + attachments.forEach(function (attachmentOptions, ndx) { + const attachment = framebufferInfo.attachments[ndx] + const format = attachmentOptions.format + const samples = attachmentOptions.samples + if (samples !== undefined || isRenderbuffer(gl, attachment)) { + gl.bindRenderbuffer(RENDERBUFFER, attachment) + if (samples > 1) { + gl.renderbufferStorageMultisample( + RENDERBUFFER, + samples, + format, + width, + height + ) + } else { + gl.renderbufferStorage(RENDERBUFFER, format, width, height) + } + } else if (isTexture(gl, attachment)) { + resizeTexture(gl, attachment, attachmentOptions, width, height) + } else { + throw new Error('unknown attachment type') + } + }) } /** @@ -9556,22 +10857,22 @@ function resizeFramebufferInfo(gl, framebufferInfo, attachments, width, height) */ function bindFramebufferInfo(gl, framebufferInfo, target) { - target = target || FRAMEBUFFER; - if (framebufferInfo) { - gl.bindFramebuffer(target, framebufferInfo.framebuffer); - gl.viewport(0, 0, framebufferInfo.width, framebufferInfo.height); - } else { - gl.bindFramebuffer(target, null); - gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); - } -} - -var framebuffers = /*#__PURE__*/Object.freeze({ - __proto__: null, - bindFramebufferInfo: bindFramebufferInfo, - createFramebufferInfo: createFramebufferInfo, - resizeFramebufferInfo: resizeFramebufferInfo -}); + target = target || FRAMEBUFFER + if (framebufferInfo) { + gl.bindFramebuffer(target, framebufferInfo.framebuffer) + gl.viewport(0, 0, framebufferInfo.width, framebufferInfo.height) + } else { + gl.bindFramebuffer(target, null) + gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight) + } +} + +var framebuffers = /*#__PURE__*/ Object.freeze({ + __proto__: null, + bindFramebufferInfo: bindFramebufferInfo, + createFramebufferInfo: createFramebufferInfo, + resizeFramebufferInfo: resizeFramebufferInfo, +}) /* * Copyright 2019 Gregg Tavares @@ -9610,7 +10911,7 @@ var framebuffers = /*#__PURE__*/Object.freeze({ * @module twgl/vertexArrays */ -const ELEMENT_ARRAY_BUFFER = 0x8893; +const ELEMENT_ARRAY_BUFFER = 0x8893 /** * @typedef {Object} VertexArrayInfo @@ -9657,20 +10958,20 @@ const ELEMENT_ARRAY_BUFFER = 0x8893; * @memberOf module:twgl/vertexArrays */ function createVertexArrayInfo(gl, programInfos, bufferInfo) { - const vao = gl.createVertexArray(); - gl.bindVertexArray(vao); - if (!programInfos.length) { - programInfos = [programInfos]; - } - programInfos.forEach(function(programInfo) { - setBuffersAndAttributes(gl, programInfo, bufferInfo); - }); - gl.bindVertexArray(null); - return { - numElements: bufferInfo.numElements, - elementType: bufferInfo.elementType, - vertexArrayObject: vao, - }; + const vao = gl.createVertexArray() + gl.bindVertexArray(vao) + if (!programInfos.length) { + programInfos = [programInfos] + } + programInfos.forEach(function (programInfo) { + setBuffersAndAttributes(gl, programInfo, bufferInfo) + }) + gl.bindVertexArray(null) + return { + numElements: bufferInfo.numElements, + elementType: bufferInfo.elementType, + vertexArrayObject: vao, + } } /** @@ -9686,16 +10987,16 @@ function createVertexArrayInfo(gl, programInfos, bufferInfo) { * @memberOf module:twgl/vertexArrays */ function createVAOAndSetAttributes(gl, setters, attribs, indices) { - const vao = gl.createVertexArray(); - gl.bindVertexArray(vao); - setAttributes(setters, attribs); - if (indices) { - gl.bindBuffer(ELEMENT_ARRAY_BUFFER, indices); - } - // We unbind this because otherwise any change to ELEMENT_ARRAY_BUFFER - // like when creating buffers for other stuff will mess up this VAO's binding - gl.bindVertexArray(null); - return vao; + const vao = gl.createVertexArray() + gl.bindVertexArray(vao) + setAttributes(setters, attribs) + if (indices) { + gl.bindBuffer(ELEMENT_ARRAY_BUFFER, indices) + } + // We unbind this because otherwise any change to ELEMENT_ARRAY_BUFFER + // like when creating buffers for other stuff will mess up this VAO's binding + gl.bindVertexArray(null) + return vao } /** @@ -9713,15 +11014,20 @@ function createVAOAndSetAttributes(gl, setters, attribs, indices) { * @memberOf module:twgl/vertexArrays */ function createVAOFromBufferInfo(gl, programInfo, bufferInfo) { - return createVAOAndSetAttributes(gl, programInfo.attribSetters || programInfo, bufferInfo.attribs, bufferInfo.indices); + return createVAOAndSetAttributes( + gl, + programInfo.attribSetters || programInfo, + bufferInfo.attribs, + bufferInfo.indices + ) } -var vertexArrays = /*#__PURE__*/Object.freeze({ - __proto__: null, - createVertexArrayInfo: createVertexArrayInfo, - createVAOAndSetAttributes: createVAOAndSetAttributes, - createVAOFromBufferInfo: createVAOFromBufferInfo -}); +var vertexArrays = /*#__PURE__*/ Object.freeze({ + __proto__: null, + createVertexArrayInfo: createVertexArrayInfo, + createVAOAndSetAttributes: createVAOAndSetAttributes, + createVAOFromBufferInfo: createVAOFromBufferInfo, +}) /* * Copyright 2019 Gregg Tavares @@ -9745,8 +11051,8 @@ var vertexArrays = /*#__PURE__*/Object.freeze({ * DEALINGS IN THE SOFTWARE. */ const defaults = { - addExtensionsToContext: true, -}; + addExtensionsToContext: true, +} /** * Various default settings for twgl. @@ -9820,53 +11126,53 @@ const defaults = { * @memberOf module:twgl */ function setDefaults(newDefaults) { - copyExistingProperties(newDefaults, defaults); - setDefaults$2(newDefaults); // eslint-disable-line - setDefaults$1(newDefaults); // eslint-disable-line + copyExistingProperties(newDefaults, defaults) + setDefaults$2(newDefaults) // eslint-disable-line + setDefaults$1(newDefaults) // eslint-disable-line } -const prefixRE = /^(.*?)_/; +const prefixRE = /^(.*?)_/ function addExtensionToContext(gl, extensionName) { - glEnumToString(gl, 0); - const ext = gl.getExtension(extensionName); - if (ext) { - const enums = {}; - const fnSuffix = prefixRE.exec(extensionName)[1]; - const enumSuffix = '_' + fnSuffix; - for (const key in ext) { - const value = ext[key]; - const isFunc = typeof (value) === 'function'; - const suffix = isFunc ? fnSuffix : enumSuffix; - let name = key; - // examples of where this is not true are WEBGL_compressed_texture_s3tc - // and WEBGL_compressed_texture_pvrtc - if (key.endsWith(suffix)) { - name = key.substring(0, key.length - suffix.length); - } - if (gl[name] !== undefined) { - if (!isFunc && gl[name] !== value) { - warn$1(name, gl[name], value, key); - } - } else { - if (isFunc) { - gl[name] = function(origFn) { - return function() { - return origFn.apply(ext, arguments); - }; - }(value); - } else { - gl[name] = value; - enums[name] = value; + glEnumToString(gl, 0) + const ext = gl.getExtension(extensionName) + if (ext) { + const enums = {} + const fnSuffix = prefixRE.exec(extensionName)[1] + const enumSuffix = '_' + fnSuffix + for (const key in ext) { + const value = ext[key] + const isFunc = typeof value === 'function' + const suffix = isFunc ? fnSuffix : enumSuffix + let name = key + // examples of where this is not true are WEBGL_compressed_texture_s3tc + // and WEBGL_compressed_texture_pvrtc + if (key.endsWith(suffix)) { + name = key.substring(0, key.length - suffix.length) + } + if (gl[name] !== undefined) { + if (!isFunc && gl[name] !== value) { + warn$1(name, gl[name], value, key) + } + } else { + if (isFunc) { + gl[name] = (function (origFn) { + return function () { + return origFn.apply(ext, arguments) + } + })(value) + } else { + gl[name] = value + enums[name] = value + } + } } - } + // pass the modified enums to glEnumToString + enums.constructor = { + name: ext.constructor.name, + } + glEnumToString(enums, 0) } - // pass the modified enums to glEnumToString - enums.constructor = { - name: ext.constructor.name, - }; - glEnumToString(enums, 0); - } - return ext; + return ext } /* @@ -9878,32 +11184,32 @@ function addExtensionToContext(gl, extensionName) { * */ const supportedExtensions = [ - 'ANGLE_instanced_arrays', - 'EXT_blend_minmax', - 'EXT_color_buffer_float', - 'EXT_color_buffer_half_float', - 'EXT_disjoint_timer_query', - 'EXT_disjoint_timer_query_webgl2', - 'EXT_frag_depth', - 'EXT_sRGB', - 'EXT_shader_texture_lod', - 'EXT_texture_filter_anisotropic', - 'OES_element_index_uint', - 'OES_standard_derivatives', - 'OES_texture_float', - 'OES_texture_float_linear', - 'OES_texture_half_float', - 'OES_texture_half_float_linear', - 'OES_vertex_array_object', - 'WEBGL_color_buffer_float', - 'WEBGL_compressed_texture_atc', - 'WEBGL_compressed_texture_etc1', - 'WEBGL_compressed_texture_pvrtc', - 'WEBGL_compressed_texture_s3tc', - 'WEBGL_compressed_texture_s3tc_srgb', - 'WEBGL_depth_texture', - 'WEBGL_draw_buffers', -]; + 'ANGLE_instanced_arrays', + 'EXT_blend_minmax', + 'EXT_color_buffer_float', + 'EXT_color_buffer_half_float', + 'EXT_disjoint_timer_query', + 'EXT_disjoint_timer_query_webgl2', + 'EXT_frag_depth', + 'EXT_sRGB', + 'EXT_shader_texture_lod', + 'EXT_texture_filter_anisotropic', + 'OES_element_index_uint', + 'OES_standard_derivatives', + 'OES_texture_float', + 'OES_texture_float_linear', + 'OES_texture_half_float', + 'OES_texture_half_float_linear', + 'OES_vertex_array_object', + 'WEBGL_color_buffer_float', + 'WEBGL_compressed_texture_atc', + 'WEBGL_compressed_texture_etc1', + 'WEBGL_compressed_texture_pvrtc', + 'WEBGL_compressed_texture_s3tc', + 'WEBGL_compressed_texture_s3tc_srgb', + 'WEBGL_depth_texture', + 'WEBGL_draw_buffers', +] /** * Attempts to enable all of the following extensions @@ -9954,9 +11260,9 @@ const supportedExtensions = [ * @memberOf module:twgl */ function addExtensionsToContext(gl) { - for (let ii = 0; ii < supportedExtensions.length; ++ii) { - addExtensionToContext(gl, supportedExtensions[ii]); - } + for (let ii = 0; ii < supportedExtensions.length; ++ii) { + addExtensionToContext(gl, supportedExtensions[ii]) + } } /** @@ -9968,18 +11274,18 @@ function addExtensionsToContext(gl) { * @private */ function create3DContext(canvas, opt_attribs) { - const names = ["webgl", "experimental-webgl"]; - let context = null; - for (let ii = 0; ii < names.length; ++ii) { - context = canvas.getContext(names[ii], opt_attribs); - if (context) { - if (defaults.addExtensionsToContext) { - addExtensionsToContext(context); - } - break; + const names = ['webgl', 'experimental-webgl'] + let context = null + for (let ii = 0; ii < names.length; ++ii) { + context = canvas.getContext(names[ii], opt_attribs) + if (context) { + if (defaults.addExtensionsToContext) { + addExtensionsToContext(context) + } + break + } } - } - return context; + return context } /** @@ -9997,8 +11303,8 @@ function create3DContext(canvas, opt_attribs) { * @private */ function getWebGLContext(canvas, opt_attribs) { - const gl = create3DContext(canvas, opt_attribs); - return gl; + const gl = create3DContext(canvas, opt_attribs) + return gl } /** @@ -10016,18 +11322,18 @@ function getWebGLContext(canvas, opt_attribs) { * @return {WebGLRenderingContext} The created context. */ function createContext(canvas, opt_attribs) { - const names = ["webgl2", "webgl", "experimental-webgl"]; - let context = null; - for (let ii = 0; ii < names.length; ++ii) { - context = canvas.getContext(names[ii], opt_attribs); - if (context) { - if (defaults.addExtensionsToContext) { - addExtensionsToContext(context); - } - break; + const names = ['webgl2', 'webgl', 'experimental-webgl'] + let context = null + for (let ii = 0; ii < names.length; ++ii) { + context = canvas.getContext(names[ii], opt_attribs) + if (context) { + if (defaults.addExtensionsToContext) { + addExtensionsToContext(context) + } + break + } } - } - return context; + return context } /** @@ -10049,8 +11355,8 @@ function createContext(canvas, opt_attribs) { * @memberOf module:twgl */ function getContext(canvas, opt_attribs) { - const gl = createContext(canvas, opt_attribs); - return gl; + const gl = createContext(canvas, opt_attribs) + return gl } /** @@ -10061,16 +11367,103 @@ function getContext(canvas, opt_attribs) { * @memberOf module:twgl */ function resizeCanvasToDisplaySize(canvas, multiplier) { - multiplier = multiplier || 1; - multiplier = Math.max(0, multiplier); - const width = canvas.clientWidth * multiplier | 0; - const height = canvas.clientHeight * multiplier | 0; - if (canvas.width !== width || canvas.height !== height) { - canvas.width = width; - canvas.height = height; - return true; - } - return false; -} - -export { addExtensionsToContext, attributes, bindFramebufferInfo, bindTransformFeedbackInfo, bindUniformBlock, canFilter, canGenerateMipmap, createAttribsFromArrays, createAttributeSetters, createBufferFromArray, createBufferFromTypedArray, createBufferInfoFromArrays, createBuffersFromArrays, createFramebufferInfo, createProgram, createProgramAsync, createProgramFromScripts, createProgramFromSources, createProgramInfo, createProgramInfoAsync, createProgramInfoFromProgram, createProgramInfos, createProgramInfosAsync, createPrograms, createProgramsAsync, createSampler, createSamplers, createTexture, createTextures, createTransformFeedback, createTransformFeedbackInfo, createUniformBlockInfo, createUniformBlockInfoFromProgram, createUniformBlockSpecFromProgram, createUniformSetters, createVAOAndSetAttributes, createVAOFromBufferInfo, createVertexArrayInfo, draw, drawBufferInfo, drawObjectList, framebuffers, getArray$1 as getArray_, getBytesPerElementForInternalFormat, getContext, getFormatAndTypeForInternalFormat, getGLTypeForTypedArray, getGLTypeForTypedArrayType, getNumComponentsForFormat, getNumComponents$1 as getNumComponents_, getTypedArrayTypeForGLType, getWebGLContext, glEnumToString, isArrayBuffer$1 as isArrayBuffer, isWebGL1, isWebGL2, loadTextureFromUrl, m4, primitives, programs, resizeCanvasToDisplaySize, resizeFramebufferInfo, resizeTexture, setAttribInfoBufferFromArray, setDefaults$2 as setAttributeDefaults_, setAttributePrefix, setAttributes, setBlockUniforms, setBuffersAndAttributes, setDefaultTextureColor, setDefaults, setEmptyTexture, setSamplerParameters, setDefaults$1 as setTextureDefaults_, setTextureFilteringForSize, setTextureFromArray, setTextureFromElement, setTextureParameters, setUniformBlock, setUniforms, setUniformsAndBindTextures, textures, typedarrays, utils, v3, vertexArrays }; \ No newline at end of file + multiplier = multiplier || 1 + multiplier = Math.max(0, multiplier) + const width = (canvas.clientWidth * multiplier) | 0 + const height = (canvas.clientHeight * multiplier) | 0 + if (canvas.width !== width || canvas.height !== height) { + canvas.width = width + canvas.height = height + return true + } + return false +} + +export { + addExtensionsToContext, + attributes, + bindFramebufferInfo, + bindTransformFeedbackInfo, + bindUniformBlock, + canFilter, + canGenerateMipmap, + createAttribsFromArrays, + createAttributeSetters, + createBufferFromArray, + createBufferFromTypedArray, + createBufferInfoFromArrays, + createBuffersFromArrays, + createFramebufferInfo, + createProgram, + createProgramAsync, + createProgramFromScripts, + createProgramFromSources, + createProgramInfo, + createProgramInfoAsync, + createProgramInfoFromProgram, + createProgramInfos, + createProgramInfosAsync, + createPrograms, + createProgramsAsync, + createSampler, + createSamplers, + createTexture, + createTextures, + createTransformFeedback, + createTransformFeedbackInfo, + createUniformBlockInfo, + createUniformBlockInfoFromProgram, + createUniformBlockSpecFromProgram, + createUniformSetters, + createVAOAndSetAttributes, + createVAOFromBufferInfo, + createVertexArrayInfo, + draw, + drawBufferInfo, + drawObjectList, + framebuffers, + getArray$1 as getArray_, + getBytesPerElementForInternalFormat, + getContext, + getFormatAndTypeForInternalFormat, + getGLTypeForTypedArray, + getGLTypeForTypedArrayType, + getNumComponentsForFormat, + getNumComponents$1 as getNumComponents_, + getTypedArrayTypeForGLType, + getWebGLContext, + glEnumToString, + isArrayBuffer$1 as isArrayBuffer, + isWebGL1, + isWebGL2, + loadTextureFromUrl, + m4, + primitives, + programs, + resizeCanvasToDisplaySize, + resizeFramebufferInfo, + resizeTexture, + setAttribInfoBufferFromArray, + setDefaults$2 as setAttributeDefaults_, + setAttributePrefix, + setAttributes, + setBlockUniforms, + setBuffersAndAttributes, + setDefaultTextureColor, + setDefaults, + setEmptyTexture, + setSamplerParameters, + setDefaults$1 as setTextureDefaults_, + setTextureFilteringForSize, + setTextureFromArray, + setTextureFromElement, + setTextureParameters, + setUniformBlock, + setUniforms, + setUniformsAndBindTextures, + textures, + typedarrays, + utils, + v3, + vertexArrays, +} diff --git a/experiments/twgl-tunnel/index.html b/experiments/twgl-tunnel/index.html index 95de90e..1a22499 100644 --- a/experiments/twgl-tunnel/index.html +++ b/experiments/twgl-tunnel/index.html @@ -1,355 +1,398 @@ - - - - - - - - - - - - - + + + + + - + const segments = 20 + const cyAcross = 12 + const cyDown = 25 + const bufferInfo = twgl.primitives.createCubeBufferInfo(gl, 2) + const cylinderBufferInfo = twgl.primitives.createCylinderBufferInfo( + gl, + 1, + 200, + cyAcross, + cyDown, + false, + false + ) + + const fbSize = 1024 + const framebufferInfo = twgl.createFramebufferInfo( + gl, + undefined, + fbSize, + fbSize + ) + + const tex = twgl.createTexture(gl, { + min: gl.NEAREST, + mag: gl.NEAREST, + src: [ + 255, 255, 255, 255, 192, 192, 192, 255, 192, 192, 192, 255, 255, + 255, 255, 255, + ], + }) + + const uniforms = { + u_lightWorldPos: [1, 8, -10], + u_lightColor: [0.2, 0.5, 1.0, 1], + u_ambient: [0, 0, 0, 1], + u_specular: [1, 1, 1, 1], + u_shininess: 50, + u_specularFactor: 1, + u_diffuse: tex, + u_fogColor: [1, 1, 1, 1], + u_fogNear: 5, + u_fogFar: 25, + u_world: m4.identity(), + } + + const cylinderUniforms = { + u_texture: framebufferInfo.attachments[0], + u_matrix: m4.identity(), + u_color: [1, 1, 1, 1], + u_texMod: [1, 1], + u_texMatrix: m4.identity(), + u_fogColor: [1, 1, 1, 1], + u_fogNear: 0.1, + u_fogFar: 190, + } + + function lerp(a, b, t) { + return a + (b - a) * t + } + + let useFramebuffer = true + + function switchMode() { + useFramebuffer = !useFramebuffer + } + + window.addEventListener('keypress', switchMode, false) + window.addEventListener('click', switchMode, false) + window.addEventListener('touchstart', switchMode, false) + + let currentBaseColor + let targetBaseColor + let baseColorScale + const colorFadeDuration = 5 + const colorChangeDuration = 10 + let colorFadeTimer + let colorChangeTimer + + function pickNewColor() { + currentBaseColor = + targetBaseColor || chroma.hsv(Math.random() * 360, 1, 1) + targetBaseColor = chroma.hsv(Math.random() * 360, 1, 1) + baseColorScale = chroma + .scale([currentBaseColor, targetBaseColor]) + .mode('lab') + colorFadeTimer = colorFadeDuration + colorChangeTimer = colorChangeDuration + } + pickNewColor() + + let then = 0 + function render(time) { + time *= 0.001 + const deltaTime = time - then + then = time + + twgl.resizeCanvasToDisplaySize(gl.canvas) + + let aspect + if (useFramebuffer) { + twgl.bindFramebufferInfo(gl, framebufferInfo) + aspect = 1 + } else { + twgl.bindFramebufferInfo(gl, null) + aspect = gl.canvas.clientWidth / gl.canvas.clientHeight + } + + colorFadeTimer -= deltaTime + colorChangeTimer -= deltaTime + if (colorChangeTimer <= 0) { + pickNewColor() + } + + const colorLerp = + 1 - Math.max(0, colorFadeTimer / colorFadeDuration) + const fadeColor = baseColorScale(colorLerp) + uniforms.u_fogColor = fadeColor.gl() + const fc = uniforms.u_fogColor + cylinderUniforms.u_fogColor = fc + + gl.cullFace(gl.BACK) + gl.enable(gl.CULL_FACE) + gl.enable(gl.DEPTH_TEST) + gl.clearColor(fc[0], fc[1], fc[2], fc[3]) + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) + + const projection = m4.perspective( + (30 * Math.PI) / 180, + aspect, + 0.5, + 30 + ) + const eye = [1, 0, -16] + const target = [0, 0, 0] + const up = [0, 1, 0] + + const camera = m4.lookAt(eye, target, up) + const view = m4.inverse(camera) + const viewProjection = m4.multiply(projection, view) + uniforms.u_viewInverse = camera + + gl.useProgram(programInfo.program) + twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo) + for (let ii = 0; ii < 25; ++ii) { + const x = ii % 5 + const y = (ii / 5) | 0 + const world = uniforms.u_world + m4.identity(world) + m4.translate(world, [0, 0, 0], world) + m4.rotateY(world, time * 0.43, world) + m4.rotateZ(world, time * 0.37, world) + m4.translate(world, [x * 3 - 7 - 3, y * 3 - 5 - 3, 0], world) + m4.rotateX(world, time * 0.21 + ii, world) + m4.rotateY(world, time * 0.53 + ii, world) + + uniforms.u_world = world + uniforms.u_worldInverseTranspose = m4.transpose( + m4.inverse(world) + ) + uniforms.u_worldViewProjection = m4.multiply( + viewProjection, + world + ) + // uniforms.u_lightColor[0] = x / 4; + // uniforms.u_lightColor[1] = y / 4; + // uniforms.u_lightColor[2] = 1 - (x + y) / 8; + + // uniforms.u_lightColor[0] = Math.max(x, y) / 5; + // uniforms.u_lightColor[1] = Math.max(y, x) / 5; + // uniforms.u_lightColor[2] = 1;// - (x + y) / 8; + uniforms.u_lightColor = [2, 2, 2, 1] + + twgl.setUniforms(programInfo, uniforms) + twgl.drawBufferInfo(gl, bufferInfo) + } + + if (useFramebuffer) { + twgl.bindFramebufferInfo(gl, null) + + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) + gl.cullFace(gl.FRONT) + gl.useProgram(texProgramInfo.program) + + aspect = gl.canvas.clientWidth / gl.canvas.clientHeight + const mat = cylinderUniforms.u_matrix + m4.perspective((30 * Math.PI) / 180, aspect, 0.5, 190, mat) + m4.translate(mat, [0, 0, -100], mat) + m4.rotateZ(mat, -time * 0.1, mat) + m4.rotateX(mat, Math.PI * 0.5, mat) + + const cmat = cylinderUniforms.u_texMatrix + m4.identity(cmat) + m4.translate(cmat, [time * 1, time * 2, 0], cmat) + m4.scale( + cmat, + [lerp(6, cyAcross, Math.sin(time) * 0.5 + 0.5), cyDown, 1], + cmat + ) + m4.rotateZ(cmat, time * 0.1, cmat) + cylinderUniforms.u_texMod[0] = 0.5 + cylinderUniforms.u_texMod[1] = 0.5 + + twgl.setBuffersAndAttributes( + gl, + texProgramInfo, + cylinderBufferInfo + ) + twgl.setUniforms(texProgramInfo, cylinderUniforms) + twgl.drawBufferInfo(gl, cylinderBufferInfo) + } + + requestAnimationFrame(render) + } + requestAnimationFrame(render) + + diff --git a/experiments/twgl-tunnel/js/amd-compiled.js b/experiments/twgl-tunnel/js/amd-compiled.js index 3944c59..af6f55c 100644 --- a/experiments/twgl-tunnel/js/amd-compiled.js +++ b/experiments/twgl-tunnel/js/amd-compiled.js @@ -1,114 +1,119 @@ -"use strict"; +'use strict' /* global require */ require([ '../../dist/5.x/twgl-full.min', '../../3rdparty/chroma.min', - ], function( - twgl, - chroma) { - const m4 = twgl.m4; - const primitives = twgl.primitives; - - twgl.setDefaults({attribPrefix: "a_"}); - const gl = document.querySelector("#c").getContext("webgl"); - const programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]); - - const shapes = [ - primitives.createCubeBufferInfo(gl, 2), - primitives.createSphereBufferInfo(gl, 1, 24, 12), - primitives.createPlaneBufferInfo(gl, 2, 2), - primitives.createTruncatedConeBufferInfo(gl, 1, 0, 2, 24, 1), - ]; - - function rand(min, max) { - return min + Math.random() * (max - min); - } - - // Shared values - const lightWorldPosition = [1, 8, -10]; - const lightColor = [1, 1, 1, 1]; - const camera = m4.identity(); - const view = m4.identity(); - const viewProjection = m4.identity(); - - const tex = twgl.createTexture(gl, { - min: gl.NEAREST, - mag: gl.NEAREST, - src: [ - 255, 255, 255, 255, - 192, 192, 192, 255, - 192, 192, 192, 255, - 255, 255, 255, 255, - ], - }); - - const objects = []; - const drawObjects = []; - const numObjects = 100; - const baseHue = rand(0, 360); - for (let ii = 0; ii < numObjects; ++ii) { - const uniforms = { - u_lightWorldPos: lightWorldPosition, - u_lightColor: lightColor, - u_diffuseMult: chroma.hsv((baseHue + rand(0, 60)) % 360, 0.4, 0.8).gl(), - u_specular: [1, 1, 1, 1], - u_shininess: 50, - u_specularFactor: 1, - u_diffuse: tex, - u_viewInverse: camera, - u_world: m4.identity(), - u_worldInverseTranspose: m4.identity(), - u_worldViewProjection: m4.identity(), - }; - drawObjects.push({ - programInfo: programInfo, - bufferInfo: shapes[ii % shapes.length], - uniforms: uniforms, - }); - objects.push({ - translation: [rand(-10, 10), rand(-10, 10), rand(-10, 10)], - ySpeed: rand(0.1, 0.3), - zSpeed: rand(0.1, 0.3), - uniforms: uniforms, - }); - } - - function render(time) { - time *= 0.001; - twgl.resizeCanvasToDisplaySize(gl.canvas); - gl.viewport(0, 0, gl.canvas.width, gl.canvas.height); - - gl.enable(gl.DEPTH_TEST); - gl.enable(gl.CULL_FACE); - gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); - - const projection = m4.perspective(30 * Math.PI / 180, gl.canvas.clientWidth / gl.canvas.clientHeight, 0.5, 100); - const eye = [1, 4, -20]; - const target = [0, 0, 0]; - const up = [0, 1, 0]; - - m4.lookAt(eye, target, up, camera); - m4.inverse(camera, view); - m4.multiply(projection, view, viewProjection); - - objects.forEach(function(obj) { - const uni = obj.uniforms; - const world = uni.u_world; - m4.identity(world); - m4.rotateY(world, time * obj.ySpeed, world); - m4.rotateZ(world, time * obj.zSpeed, world); - m4.translate(world, obj.translation, world); - m4.rotateX(world, time, world); - m4.transpose(m4.inverse(world, uni.u_worldInverseTranspose), uni.u_worldInverseTranspose); - m4.multiply(viewProjection, uni.u_world, uni.u_worldViewProjection); - }); - - twgl.drawObjectList(gl, drawObjects); - - requestAnimationFrame(render); - } - requestAnimationFrame(render); -}); - +], function (twgl, chroma) { + const m4 = twgl.m4 + const primitives = twgl.primitives + + twgl.setDefaults({ attribPrefix: 'a_' }) + const gl = document.querySelector('#c').getContext('webgl') + const programInfo = twgl.createProgramInfo(gl, ['vs', 'fs']) + + const shapes = [ + primitives.createCubeBufferInfo(gl, 2), + primitives.createSphereBufferInfo(gl, 1, 24, 12), + primitives.createPlaneBufferInfo(gl, 2, 2), + primitives.createTruncatedConeBufferInfo(gl, 1, 0, 2, 24, 1), + ] + + function rand(min, max) { + return min + Math.random() * (max - min) + } + + // Shared values + const lightWorldPosition = [1, 8, -10] + const lightColor = [1, 1, 1, 1] + const camera = m4.identity() + const view = m4.identity() + const viewProjection = m4.identity() + + const tex = twgl.createTexture(gl, { + min: gl.NEAREST, + mag: gl.NEAREST, + src: [ + 255, 255, 255, 255, 192, 192, 192, 255, 192, 192, 192, 255, 255, + 255, 255, 255, + ], + }) + + const objects = [] + const drawObjects = [] + const numObjects = 100 + const baseHue = rand(0, 360) + for (let ii = 0; ii < numObjects; ++ii) { + const uniforms = { + u_lightWorldPos: lightWorldPosition, + u_lightColor: lightColor, + u_diffuseMult: chroma + .hsv((baseHue + rand(0, 60)) % 360, 0.4, 0.8) + .gl(), + u_specular: [1, 1, 1, 1], + u_shininess: 50, + u_specularFactor: 1, + u_diffuse: tex, + u_viewInverse: camera, + u_world: m4.identity(), + u_worldInverseTranspose: m4.identity(), + u_worldViewProjection: m4.identity(), + } + drawObjects.push({ + programInfo: programInfo, + bufferInfo: shapes[ii % shapes.length], + uniforms: uniforms, + }) + objects.push({ + translation: [rand(-10, 10), rand(-10, 10), rand(-10, 10)], + ySpeed: rand(0.1, 0.3), + zSpeed: rand(0.1, 0.3), + uniforms: uniforms, + }) + } + + function render(time) { + time *= 0.001 + twgl.resizeCanvasToDisplaySize(gl.canvas) + gl.viewport(0, 0, gl.canvas.width, gl.canvas.height) + + gl.enable(gl.DEPTH_TEST) + gl.enable(gl.CULL_FACE) + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) + + const projection = m4.perspective( + (30 * Math.PI) / 180, + gl.canvas.clientWidth / gl.canvas.clientHeight, + 0.5, + 100 + ) + const eye = [1, 4, -20] + const target = [0, 0, 0] + const up = [0, 1, 0] + + m4.lookAt(eye, target, up, camera) + m4.inverse(camera, view) + m4.multiply(projection, view, viewProjection) + + objects.forEach(function (obj) { + const uni = obj.uniforms + const world = uni.u_world + m4.identity(world) + m4.rotateY(world, time * obj.ySpeed, world) + m4.rotateZ(world, time * obj.zSpeed, world) + m4.translate(world, obj.translation, world) + m4.rotateX(world, time, world) + m4.transpose( + m4.inverse(world, uni.u_worldInverseTranspose), + uni.u_worldInverseTranspose + ) + m4.multiply(viewProjection, uni.u_world, uni.u_worldViewProjection) + }) + + twgl.drawObjectList(gl, drawObjects) + + requestAnimationFrame(render) + } + requestAnimationFrame(render) +})