From 2fcf8525d523eb2f6d8e5bccd68479df56a51350 Mon Sep 17 00:00:00 2001 From: Ben Coleman Date: Thu, 10 Aug 2023 16:31:53 +0100 Subject: [PATCH] HUD fixes --- .eslintrc.json | 67 +++++----- dist-bundle/gsots3d.js | 257 ++++++++++++++++++++----------------- dist-bundle/gsots3d.js.map | 2 +- examples/demo-2/main.mjs | 32 ++--- examples/demo/main.mjs | 3 + src/core/cache.ts | 4 +- src/core/context.ts | 37 +----- src/core/hud.ts | 62 +++++++-- src/core/stats.ts | 30 ++--- src/engine/camera.ts | 10 +- src/engine/material.ts | 2 +- src/engine/tuples.ts | 18 +-- src/models/instance.ts | 53 ++++---- src/models/model.ts | 6 +- src/models/types.ts | 4 +- src/parsers/mtl-parser.ts | 4 +- src/parsers/obj-parser.ts | 12 +- tsconfig.json | 1 + 18 files changed, 314 insertions(+), 290 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 6723504..0584b30 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,41 +1,38 @@ { - "env": { - "browser": true, - "es2021": true - }, - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended" - ], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "ecmaVersion": "latest", - "sourceType": "module" - }, - "plugins": [ - "@typescript-eslint" - ], - "rules": { - // Standard rules - "no-var": "error", - "prefer-const": "error", - "no-unused-vars": "off", - "no-undef": "error", + "env": { + "browser": true, + "es2021": true + }, + "extends": ["eslint:recommended", "plugin:@typescript-eslint/strict"], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": "latest", + "sourceType": "module" + }, + "plugins": ["@typescript-eslint"], + "rules": { + // Standard rules + "no-var": "error", + "prefer-const": "error", + "no-unused-vars": "off", + "no-undef": "error", - // Prevents duplicate imports - "no-duplicate-imports": "error", - - // Prevents return in constructor - "no-constructor-return": "error", + // Prevents duplicate imports + "no-duplicate-imports": "error", - // Prevents return in promise executor - "no-promise-executor-return": "error", + // Prevents return in constructor + "no-constructor-return": "error", - // disable string concatenation - "prefer-template": "error", + // Prevents return in promise executor + "no-promise-executor-return": "error", - // TypeScript specific - "@typescript-eslint/no-unused-vars" : "error", - "@typescript-eslint/no-explicit-any": "error" - } + // disable string concatenation + "prefer-template": "error", + + "dot-notation": "error", + "func-style": ["error", "declaration", { "allowArrowFunctions": true }], + "object-shorthand": "error", + "capitalized-comments": "error", + "spaced-comment": "error" + } } diff --git a/dist-bundle/gsots3d.js b/dist-bundle/gsots3d.js index 2205d35..ea3c87e 100644 --- a/dist-bundle/gsots3d.js +++ b/dist-bundle/gsots3d.js @@ -296,6 +296,9 @@ function setLogLevel(level) { import_loglevel2.default.setLevel(level); } +// src/core/context.ts +var import_loglevel7 = __toESM(require_loglevel(), 1); + // package.json var version = "0.0.4-alpha.2"; @@ -6052,9 +6055,6 @@ var forEach = function() { }; }(); -// src/core/context.ts -var import_loglevel7 = __toESM(require_loglevel(), 1); - // src/engine/tuples.ts function normalize2(tuple) { const [x, y, z] = tuple; @@ -6084,16 +6084,16 @@ function rgbColourHex(hexString) { const b = parseInt(hex.substring(4, 6), 16); return rgbColour255(r, g, b); } -var Colours = class { +var Colours = { + RED: [1, 0, 0], + GREEN: [0, 1, 0], + BLUE: [0, 0, 1], + YELLOW: [1, 1, 0], + CYAN: [0, 1, 1], + MAGENTA: [1, 0, 1], + BLACK: [0, 0, 0], + WHITE: [1, 1, 1] }; -Colours.RED = [1, 0, 0]; -Colours.GREEN = [0, 1, 0]; -Colours.BLUE = [0, 0, 1]; -Colours.YELLOW = [1, 1, 0]; -Colours.CYAN = [0, 1, 1]; -Colours.MAGENTA = [1, 0, 1]; -Colours.BLACK = [0, 0, 0]; -Colours.WHITE = [1, 1, 1]; var Tuples = { normalize: normalize2, scale: scale3, @@ -6623,7 +6623,8 @@ var LightDirectional = class { return cam; } /** - * Get the forward view matrix for the virtual camera used to render the shadow map + * Get the forward view matrix for the virtual camera used to render the shadow map. + * Returns undefined if shadows are not enabled */ get shadowMatrix() { if (!this._shadowOptions) { @@ -6641,15 +6642,33 @@ var LightDirectional = class { ); return shadowMatrix; } + /** + * Are shadows enabled for this light? + */ + get shadowsEnabled() { + return this._shadowOptions !== void 0; + } + /** + * Get the shadow map program, will be undefined if shadows are not enabled + */ get shadowMapProgram() { return this._shadowMapProgram; } + /** + * Get the shadow map framebuffer, will be undefined if shadows are not enabled + */ get shadowMapFrameBufffer() { return this._shadowMapFB; } + /** + * Get the shadow map texture, will be undefined if shadows are not enabled + */ get shadowMapTexture() { return this._shadowMapTex; } + /** + * Get the shadow map options, will be undefined if shadows are not enabled + */ get shadowMapOptions() { return this._shadowOptions; } @@ -6753,6 +6772,7 @@ var EnvironmentMap = class { setBuffersAndAttributes(this.gl, this.programInfo, this.cube); setUniforms(this.programInfo, uniforms); drawBufferInfo(this.gl, this.cube); + Stats.drawCallsPerFrame++; this.gl.enable(this.gl.DEPTH_TEST); } get texture() { @@ -6888,54 +6908,49 @@ var DynamicEnvironmentMap = class { // src/models/instance.ts var Instance = class { /** + * Create a new instace of a renderable thing * @param {Renderable} renderable - Renderable to use for this instance */ constructor(renderable) { + /** Should this instance be rendered and drawn */ this.enabled = true; - this.metadata = {}; + /** Should this instance cast a shadow */ this.castShadow = true; - /** - * Per instance texture flip flags, useful for flipping textures on a per instance basis - * @default false - */ + /** Flip all textures on this instance on the X axis */ this.flipTextureX = false; - /** - * Per instance texture flip flags, useful for flipping textures on a per instance basis - * @default false - */ + /** Flip all textures on this instance on the Y axis */ this.flipTextureY = false; + /** Metadata for this instance, can be used to store anything */ + this.metadata = {}; this.renderable = renderable; } - /** - * Rotate this instance around the X axis - */ + /** Rotate this instance around the X axis*/ rotateX(angle2) { if (!this.rotate) this.rotate = [0, 0, 0]; this.rotate[0] += angle2; } - /** - * Rotate this instance around the Y axis - */ + /** Rotate this instance around the Y axis*/ rotateY(angle2) { if (!this.rotate) this.rotate = [0, 0, 0]; this.rotate[1] += angle2; } - /** - * Rotate this instance around the Z axis - */ + /** Rotate this instance around the Z axis, in radians*/ rotateZ(angle2) { if (!this.rotate) this.rotate = [0, 0, 0]; this.rotate[2] += angle2; } + /** Rotate this instance around the X axis by a given angle in degrees */ rotateZDeg(angle2) { this.rotateZ(angle2 * Math.PI / 180); } + /** Rotate this instance around the Y axis by a given angle in degrees */ rotateYDeg(angle2) { this.rotateY(angle2 * Math.PI / 180); } + /** Rotate this instance around the Z axis by a given angle in degrees */ rotateXDeg(angle2) { this.rotateX(angle2 * Math.PI / 180); } @@ -6981,31 +6996,28 @@ var Instance = class { }; // src/core/stats.ts -var Stats = class { - constructor() { - this.prevTime = 0; - this.drawCallsPerFrame = 0; - this.instances = 0; - this.triangles = 0; - this.deltaTime = 0; - this.totalTime = 0; - } +var Stats = { + drawCallsPerFrame: 0, + instances: 0, + triangles: 0, + prevTime: 0, + deltaTime: 0, + totalTime: 0, resetPerFrame() { - this.drawCallsPerFrame = 0; - } + Stats.drawCallsPerFrame = 0; + }, updateTime(now) { - this.deltaTime = now - this.prevTime; - this.prevTime = now; - this.totalTime += this.deltaTime; - } + Stats.deltaTime = now - Stats.prevTime; + Stats.prevTime = now; + Stats.totalTime += Stats.deltaTime; + }, get FPS() { - return Math.round(1 / this.deltaTime); - } + return Math.round(1 / Stats.deltaTime); + }, get totalTimeRound() { - return Math.round(this.totalTime); + return Math.round(Stats.totalTime); } }; -var stats = new Stats(); // src/models/billboard.ts var BillboardType = /* @__PURE__ */ ((BillboardType2) => { @@ -7055,7 +7067,7 @@ var Billboard = class { setBuffersAndAttributes(gl, programInfo, this.bufferInfo); setUniforms(programInfo, uniforms); drawBufferInfo(gl, this.bufferInfo); - stats.drawCallsPerFrame++; + Stats.drawCallsPerFrame++; } }; @@ -7213,7 +7225,7 @@ var Primitive = class { setBuffersAndAttributes(gl, programInfo, this.bufferInfo); setUniforms(programInfo, uniforms); drawBufferInfo(gl, this.bufferInfo); - stats.drawCallsPerFrame++; + Stats.drawCallsPerFrame++; } }; var PrimitiveSphere = class extends Primitive { @@ -7361,11 +7373,11 @@ function parseOBJ(objFile, flipUV) { let triangles = 0; let webglVertexData = [ [], - // position + // Position [], - // texcoord + // Texcoord [] - // normal + // Normal ]; const geometries = Array(); let geometry = {}; @@ -7513,7 +7525,7 @@ var Model = class _Model { if (materialOverride === void 0) { let material = this.materials[part.materialName]; if (!material) { - material = this.materials["__default"]; + material = this.materials.__default; } material.apply(programInfo); } else { @@ -7522,7 +7534,7 @@ var Model = class _Model { setBuffersAndAttributes(gl, programInfo, bufferInfo); setUniforms(programInfo, uniforms); drawBufferInfo(gl, bufferInfo); - stats.drawCallsPerFrame++; + Stats.drawCallsPerFrame++; } } /** Simple getter for the number of triangles in the model */ @@ -7562,8 +7574,8 @@ var Model = class _Model { import_loglevel6.default.warn(`\u{1F4A5} Unable to load material library ${objData.matLibNames[0]}`); } } - model.materials["__default"] = new Material(); - model.materials["__default"].diffuse = [0.1, 0.6, 0.9]; + model.materials.__default = new Material(); + model.materials.__default.diffuse = [0.1, 0.6, 0.9]; const gl = getGl(); if (!gl) { throw new Error("\u{1F4A5} Unable to get WebGL context"); @@ -7628,19 +7640,40 @@ var ModelPart = class { // src/core/hud.ts var HUD = class { constructor(canvas) { + this.debug = false; const parent = canvas.parentElement; if (!parent) throw new Error("\u{1F4A5} Canvas must have a parent element"); this.canvas = canvas; this.hud = document.createElement("div"); this.hud.classList.add("gsots3d-hud"); - this.update = this.update.bind(this); - window.addEventListener("resize", this.update); - window.addEventListener("load", this.update); + this.hud.style.pointerEvents = "none"; + this.updateWithCanvas = this.updateWithCanvas.bind(this); + window.addEventListener("resize", this.updateWithCanvas); + window.addEventListener("load", this.updateWithCanvas); + this.debugDiv = document.createElement("div"); + this.debugDiv.classList.add("gsots3d-debug"); + this.debugDiv.style.fontSize = "min(1.5vw, 20px)"; + this.debugDiv.style.fontFamily = "monospace"; + this.debugDiv.style.color = "white"; + this.debugDiv.style.padding = "1vw"; + this.addHUDItem(this.debugDiv); + this.loadingDiv = document.createElement("div"); + this.loadingDiv.classList.add("gsots3d-loading"); + this.loadingDiv.innerHTML = `\u{1F4BE} Loading...`; + this.loadingDiv.innerHTML += `

GSOTS-3D v${version}
`; + this.loadingDiv.style.font = "normal 3vw sans-serif"; + this.loadingDiv.style.color = "#ccc"; + this.loadingDiv.style.position = "absolute"; + this.loadingDiv.style.top = "50%"; + this.loadingDiv.style.left = "50%"; + this.loadingDiv.style.textAlign = "center"; + this.loadingDiv.style.transform = "translate(-50%, -50%)"; + this.addHUDItem(this.loadingDiv); parent.appendChild(this.hud); - this.update(); + this.updateWithCanvas(); } - update() { + updateWithCanvas() { const canvasStyles = window.getComputedStyle(this.canvas, null); this.hud.style.position = canvasStyles.getPropertyValue("position"); this.hud.style.top = canvasStyles.getPropertyValue("top"); @@ -7648,13 +7681,26 @@ var HUD = class { this.hud.style.width = canvasStyles.getPropertyValue("width"); this.hud.style.height = canvasStyles.getPropertyValue("height"); this.hud.style.transform = canvasStyles.getPropertyValue("transform"); - this.hud.style.pointerEvents = "none"; } addHUDItem(item) { this.hud.appendChild(item); } - debug(msg) { - this.hud.innerHTML = msg; + render(debug = false, camera) { + if (debug) { + this.debugDiv.innerHTML = ` + GSOTS-3D v${version}

+ Camera: ${camera.toString()}
+ Instances: ${Stats.instances}
+ Draw calls: ${Stats.drawCallsPerFrame}
+ Triangles: ${Stats.triangles}
+ Render: FPS: ${Stats.FPS} / ${Stats.totalTimeRound}s
+ `; + } else { + this.debugDiv.innerHTML = ""; + } + } + hideLoading() { + this.loadingDiv.style.display = "none"; } }; @@ -7672,7 +7718,7 @@ var glsl_default8 = "#version 300 es\n\n// ===================================== // src/core/context.ts var MAX_LIGHTS = 16; -var Context = class _Context { +var Context2 = class _Context { /** Constructor is private, use init() to create a new context */ constructor(gl) { this.instances = []; @@ -7699,23 +7745,6 @@ var Context = class _Context { this._camera = defaultCamera; this.activeCameraName = "default"; this.hud = new HUD(gl.canvas); - this.debugDiv = document.createElement("div"); - this.debugDiv.classList.add("gsots3d-debug"); - this.debugDiv.style.fontSize = "min(1.5vw, 20px)"; - this.debugDiv.style.fontFamily = "monospace"; - this.debugDiv.style.color = "white"; - this.debugDiv.style.padding = "1vw"; - this.hud.addHUDItem(this.debugDiv); - this.loadingDiv = document.createElement("div"); - this.loadingDiv.classList.add("gsots3d-loading"); - this.loadingDiv.innerHTML = "\u{1F4BE} Loading..."; - this.loadingDiv.style.font = "normal 4vw sans-serif"; - this.loadingDiv.style.color = "white"; - this.loadingDiv.style.position = "absolute"; - this.loadingDiv.style.top = "50%"; - this.loadingDiv.style.left = "50%"; - this.loadingDiv.style.transform = "translate(-50%, -50%)"; - this.hud.addHUDItem(this.loadingDiv); import_loglevel7.default.info(`\u{1F451} GSOTS-3D context created, v${version}`); } // ==== Getters ============================================================= @@ -7760,35 +7789,25 @@ var Context = class _Context { async render(now) { if (!this.gl) return; - stats.updateTime(now * 1e-3); - this.update(stats.deltaTime); + Stats.updateTime(now * 1e-3); + this.update(Stats.deltaTime); if (this.dynamicEnvMap) { this.dynamicEnvMap.update(this.gl, this); } - const shadowCam = this.globalLight.getShadowCamera(); - if (shadowCam) { + if (this.globalLight.shadowsEnabled) { + const shadowCam = this.globalLight.getShadowCamera(); this.gl.cullFace(this.gl.FRONT); bindFramebufferInfo(this.gl, this.globalLight.shadowMapFrameBufffer); - this.renderWithCamera(shadowCam, this.globalLight.shadowMapProgram); + if (shadowCam) + this.renderWithCamera(shadowCam, this.globalLight.shadowMapProgram); this.gl.cullFace(this.gl.BACK); } bindFramebufferInfo(this.gl, null); this.renderWithCamera(this.camera); - if (this.debug) { - this.debugDiv.innerHTML = ` - GSOTS-3D v${version}

- Camera: ${this.camera.toString()}
- Instances: ${stats.instances}
- Draw calls: ${stats.drawCallsPerFrame}
- Triangles: ${stats.triangles}
- Render: FPS: ${stats.FPS} / ${stats.totalTimeRound}s
- `; - } else { - this.debugDiv.innerHTML = ""; - } + this.hud.render(this.debug, this.camera); if (this.started) requestAnimationFrame(this.render); - stats.resetPerFrame(); + Stats.resetPerFrame(); } /** * Render the scene from the given camera, used internally @@ -7858,7 +7877,7 @@ var Context = class _Context { * Start the rendering loop */ start() { - this.loadingDiv.style.display = "none"; + this.hud.hideLoading(); this.started = true; requestAnimationFrame(this.render); } @@ -7948,8 +7967,8 @@ var Context = class _Context { } const instance = new Instance(model); this.instances.push(instance); - stats.triangles += model.triangleCount; - stats.instances++; + Stats.triangles += model.triangleCount; + Stats.instances++; return instance; } /** @@ -7964,8 +7983,8 @@ var Context = class _Context { sphere.material = material; const instance = new Instance(sphere); this.addInstance(instance, material); - stats.triangles += sphere.triangleCount; - stats.instances++; + Stats.triangles += sphere.triangleCount; + Stats.instances++; import_loglevel7.default.debug(`\u{1F7E2} Created sphere instance, r:${radius}`); return instance; } @@ -7983,8 +8002,8 @@ var Context = class _Context { plane.material = material; const instance = new Instance(plane); this.addInstance(instance, material); - stats.triangles += plane.triangleCount; - stats.instances++; + Stats.triangles += plane.triangleCount; + Stats.instances++; import_loglevel7.default.debug(`\u{1F7E8} Created plane instance, w:${width} h:${height}`); return instance; } @@ -7996,8 +8015,8 @@ var Context = class _Context { cube.material = material; const instance = new Instance(cube); this.addInstance(instance, material); - stats.triangles += cube.triangleCount; - stats.instances++; + Stats.triangles += cube.triangleCount; + Stats.instances++; import_loglevel7.default.debug(`\u{1F4E6} Created cube instance, size:${size}`); return instance; } @@ -8009,8 +8028,8 @@ var Context = class _Context { cyl.material = material; const instance = new Instance(cyl); this.addInstance(instance, material); - stats.triangles += cyl.triangleCount; - stats.instances++; + Stats.triangles += cyl.triangleCount; + Stats.instances++; import_loglevel7.default.debug(`\u{1F6E2}\uFE0F Created cylinder instance, r:${r}`); return instance; } @@ -8025,8 +8044,8 @@ var Context = class _Context { const billboard = new Billboard(this.gl, type, material, size); const instance = new Instance(billboard); this.addInstance(instance, material); - stats.triangles += 2; - stats.instances++; + Stats.triangles += 2; + Stats.instances++; import_loglevel7.default.debug(`\u{1F6A7} Created billboard instance of type: ${type} size: ${size}`); return instance; } @@ -8084,7 +8103,7 @@ export { Camera, CameraType, Colours, - Context, + Context2 as Context, DynamicEnvironmentMap, EnvironmentMap, HUD, @@ -8103,11 +8122,11 @@ export { PrimitivePlane, PrimitiveSphere, ProgramCache, + Stats, TextureCache, Tuples, getGl, - setLogLevel, - stats + setLogLevel }; /*! Bundled license information: diff --git a/dist-bundle/gsots3d.js.map b/dist-bundle/gsots3d.js.map index 02fb97e..c8bd950 100644 --- a/dist-bundle/gsots3d.js.map +++ b/dist-bundle/gsots3d.js.map @@ -1 +1 @@ -{"version":3,"sources":["../node_modules/loglevel/lib/loglevel.js","../src/core/gl.ts","../src/core/logging.ts","../package.json","../node_modules/twgl.js/dist/5.x/twgl-full.module.js","../node_modules/gl-matrix/esm/common.js","../node_modules/gl-matrix/esm/mat4.js","../node_modules/gl-matrix/esm/vec3.js","../src/core/context.ts","../src/engine/tuples.ts","../src/core/cache.ts","../src/engine/camera.ts","../shaders/shadowmap/glsl.frag","../shaders/shadowmap/glsl.vert","../src/engine/lights.ts","../src/engine/envmap.ts","../shaders/envmap/glsl.frag","../shaders/envmap/glsl.vert","../src/models/instance.ts","../src/core/stats.ts","../src/models/billboard.ts","../src/engine/material.ts","../src/models/primitive.ts","../src/models/model.ts","../src/parsers/mtl-parser.ts","../src/parsers/obj-parser.ts","../src/core/files.ts","../src/core/hud.ts","../shaders/phong/glsl.frag","../shaders/phong/glsl.vert","../shaders/billboard/glsl.frag","../shaders/billboard/glsl.vert"],"sourcesContent":["/*\n* loglevel - https://github.com/pimterry/loglevel\n*\n* Copyright (c) 2013 Tim Perry\n* Licensed under the MIT license.\n*/\n(function (root, definition) {\n \"use strict\";\n if (typeof define === 'function' && define.amd) {\n define(definition);\n } else if (typeof module === 'object' && module.exports) {\n module.exports = definition();\n } else {\n root.log = definition();\n }\n}(this, function () {\n \"use strict\";\n\n // Slightly dubious tricks to cut down minimized file size\n var noop = function() {};\n var undefinedType = \"undefined\";\n var isIE = (typeof window !== undefinedType) && (typeof window.navigator !== undefinedType) && (\n /Trident\\/|MSIE /.test(window.navigator.userAgent)\n );\n\n var logMethods = [\n \"trace\",\n \"debug\",\n \"info\",\n \"warn\",\n \"error\"\n ];\n\n // Cross-browser bind equivalent that works at least back to IE6\n function bindMethod(obj, methodName) {\n var method = obj[methodName];\n if (typeof method.bind === 'function') {\n return method.bind(obj);\n } else {\n try {\n return Function.prototype.bind.call(method, obj);\n } catch (e) {\n // Missing bind shim or IE8 + Modernizr, fallback to wrapping\n return function() {\n return Function.prototype.apply.apply(method, [obj, arguments]);\n };\n }\n }\n }\n\n // Trace() doesn't print the message in IE, so for that case we need to wrap it\n function traceForIE() {\n if (console.log) {\n if (console.log.apply) {\n console.log.apply(console, arguments);\n } else {\n // In old IE, native console methods themselves don't have apply().\n Function.prototype.apply.apply(console.log, [console, arguments]);\n }\n }\n if (console.trace) console.trace();\n }\n\n // Build the best logging method possible for this env\n // Wherever possible we want to bind, not wrap, to preserve stack traces\n function realMethod(methodName) {\n if (methodName === 'debug') {\n methodName = 'log';\n }\n\n if (typeof console === undefinedType) {\n return false; // No method possible, for now - fixed later by enableLoggingWhenConsoleArrives\n } else if (methodName === 'trace' && isIE) {\n return traceForIE;\n } else if (console[methodName] !== undefined) {\n return bindMethod(console, methodName);\n } else if (console.log !== undefined) {\n return bindMethod(console, 'log');\n } else {\n return noop;\n }\n }\n\n // These private functions always need `this` to be set properly\n\n function replaceLoggingMethods(level, loggerName) {\n /*jshint validthis:true */\n for (var i = 0; i < logMethods.length; i++) {\n var methodName = logMethods[i];\n this[methodName] = (i < level) ?\n noop :\n this.methodFactory(methodName, level, loggerName);\n }\n\n // Define log.log as an alias for log.debug\n this.log = this.debug;\n }\n\n // In old IE versions, the console isn't present until you first open it.\n // We build realMethod() replacements here that regenerate logging methods\n function enableLoggingWhenConsoleArrives(methodName, level, loggerName) {\n return function () {\n if (typeof console !== undefinedType) {\n replaceLoggingMethods.call(this, level, loggerName);\n this[methodName].apply(this, arguments);\n }\n };\n }\n\n // By default, we use closely bound real methods wherever possible, and\n // otherwise we wait for a console to appear, and then try again.\n function defaultMethodFactory(methodName, level, loggerName) {\n /*jshint validthis:true */\n return realMethod(methodName) ||\n enableLoggingWhenConsoleArrives.apply(this, arguments);\n }\n\n function Logger(name, defaultLevel, factory) {\n var self = this;\n var currentLevel;\n defaultLevel = defaultLevel == null ? \"WARN\" : defaultLevel;\n\n var storageKey = \"loglevel\";\n if (typeof name === \"string\") {\n storageKey += \":\" + name;\n } else if (typeof name === \"symbol\") {\n storageKey = undefined;\n }\n\n function persistLevelIfPossible(levelNum) {\n var levelName = (logMethods[levelNum] || 'silent').toUpperCase();\n\n if (typeof window === undefinedType || !storageKey) return;\n\n // Use localStorage if available\n try {\n window.localStorage[storageKey] = levelName;\n return;\n } catch (ignore) {}\n\n // Use session cookie as fallback\n try {\n window.document.cookie =\n encodeURIComponent(storageKey) + \"=\" + levelName + \";\";\n } catch (ignore) {}\n }\n\n function getPersistedLevel() {\n var storedLevel;\n\n if (typeof window === undefinedType || !storageKey) return;\n\n try {\n storedLevel = window.localStorage[storageKey];\n } catch (ignore) {}\n\n // Fallback to cookies if local storage gives us nothing\n if (typeof storedLevel === undefinedType) {\n try {\n var cookie = window.document.cookie;\n var location = cookie.indexOf(\n encodeURIComponent(storageKey) + \"=\");\n if (location !== -1) {\n storedLevel = /^([^;]+)/.exec(cookie.slice(location))[1];\n }\n } catch (ignore) {}\n }\n\n // If the stored level is not valid, treat it as if nothing was stored.\n if (self.levels[storedLevel] === undefined) {\n storedLevel = undefined;\n }\n\n return storedLevel;\n }\n\n function clearPersistedLevel() {\n if (typeof window === undefinedType || !storageKey) return;\n\n // Use localStorage if available\n try {\n window.localStorage.removeItem(storageKey);\n return;\n } catch (ignore) {}\n\n // Use session cookie as fallback\n try {\n window.document.cookie =\n encodeURIComponent(storageKey) + \"=; expires=Thu, 01 Jan 1970 00:00:00 UTC\";\n } catch (ignore) {}\n }\n\n /*\n *\n * Public logger API - see https://github.com/pimterry/loglevel for details\n *\n */\n\n self.name = name;\n\n self.levels = { \"TRACE\": 0, \"DEBUG\": 1, \"INFO\": 2, \"WARN\": 3,\n \"ERROR\": 4, \"SILENT\": 5};\n\n self.methodFactory = factory || defaultMethodFactory;\n\n self.getLevel = function () {\n return currentLevel;\n };\n\n self.setLevel = function (level, persist) {\n if (typeof level === \"string\" && self.levels[level.toUpperCase()] !== undefined) {\n level = self.levels[level.toUpperCase()];\n }\n if (typeof level === \"number\" && level >= 0 && level <= self.levels.SILENT) {\n currentLevel = level;\n if (persist !== false) { // defaults to true\n persistLevelIfPossible(level);\n }\n replaceLoggingMethods.call(self, level, name);\n if (typeof console === undefinedType && level < self.levels.SILENT) {\n return \"No console available for logging\";\n }\n } else {\n throw \"log.setLevel() called with invalid level: \" + level;\n }\n };\n\n self.setDefaultLevel = function (level) {\n defaultLevel = level;\n if (!getPersistedLevel()) {\n self.setLevel(level, false);\n }\n };\n\n self.resetLevel = function () {\n self.setLevel(defaultLevel, false);\n clearPersistedLevel();\n };\n\n self.enableAll = function(persist) {\n self.setLevel(self.levels.TRACE, persist);\n };\n\n self.disableAll = function(persist) {\n self.setLevel(self.levels.SILENT, persist);\n };\n\n // Initialize with the right level\n var initialLevel = getPersistedLevel();\n if (initialLevel == null) {\n initialLevel = defaultLevel;\n }\n self.setLevel(initialLevel, false);\n }\n\n /*\n *\n * Top-level API\n *\n */\n\n var defaultLogger = new Logger();\n\n var _loggersByName = {};\n defaultLogger.getLogger = function getLogger(name) {\n if ((typeof name !== \"symbol\" && typeof name !== \"string\") || name === \"\") {\n throw new TypeError(\"You must supply a name when creating a logger.\");\n }\n\n var logger = _loggersByName[name];\n if (!logger) {\n logger = _loggersByName[name] = new Logger(\n name, defaultLogger.getLevel(), defaultLogger.methodFactory);\n }\n return logger;\n };\n\n // Grab the current global log variable in case of overwrite\n var _log = (typeof window !== undefinedType) ? window.log : undefined;\n defaultLogger.noConflict = function() {\n if (typeof window !== undefinedType &&\n window.log === defaultLogger) {\n window.log = _log;\n }\n\n return defaultLogger;\n };\n\n defaultLogger.getLoggers = function getLoggers() {\n return _loggersByName;\n };\n\n // ES6 default export, for compatibility\n defaultLogger['default'] = defaultLogger;\n\n return defaultLogger;\n}));\n","// ===== gl.ts ==========================================================\n// Interactions with the GL context, as a global singleton\n// Ben Coleman, 2023\n// ======================================================================\n\nimport { mat4 } from 'gl-matrix'\nimport log from 'loglevel'\n\n/** A map of uniforms that can be used when WebGL rendering, typically applied with twlg.setUniforms() */\nexport type UniformSet = { [key: string]: number | number[] | mat4 | WebGLTexture | null }\n\n// Memoized global WebGL2 context\nlet glContext: WebGL2RenderingContext | undefined\n\n/**\n * Get the WebGL2 context, if it doesn't exist create it\n *\n * @returns {WebGL2RenderingContext} - Global WebGL2 context\n * @param {boolean} aa - Enable antialiasing\n * @param {string} selector - CSS selector for locating the canvas element\n */\nexport function getGl(aa = true, selector = 'canvas') {\n if (glContext) {\n return glContext\n }\n\n log.info(`🖌️ Creating new WebGL2 context for: '${selector}'`)\n\n const canvasElement = document.querySelector(selector) as HTMLElement\n if (!canvasElement) {\n log.error(`💥 FATAL! Unable to find element with selector: '${selector}'`)\n return undefined\n }\n\n if (canvasElement && canvasElement.tagName !== 'CANVAS') {\n log.error(`💥 FATAL! Element with selector: '${selector}' is not a canvas element`)\n return undefined\n }\n\n const canvas = canvasElement as HTMLCanvasElement\n if (!canvas) {\n log.error(`💥 FATAL! Unable to find canvas element with selector: '${selector}'`)\n return undefined\n }\n\n glContext = canvas.getContext('webgl2', { antialias: aa }) ?? undefined\n\n if (!glContext) {\n log.error(`💥 Unable to create WebGL2 context, maybe it's not supported on this device`)\n return undefined\n }\n\n log.info(`📐 Internal: ${canvas.width} x ${canvas.height}, display: ${canvas.clientWidth} x ${canvas.clientHeight}`)\n\n return glContext\n}\n","// ===== logging.ts ===========================================================\n// Just a wrapper around loglevel\n// Ben Coleman, 2023\n// ============================================================================\n\nimport log from 'loglevel'\n\n/**\n * Wrapper around loglevel, so we can globally change the logging level\n * @param level - The log level to set, one of 'trace', 'debug', 'info', 'warn', 'error', 'silent'\n */\nexport function setLogLevel(level: log.LogLevelNames) {\n log.setLevel(level)\n}\n","{\n \"name\": \"@benc-uk/gsots3d\",\n \"version\": \"0.0.4-alpha.2\",\n \"description\": \"Getting S**t On The Screen in 3D. A library for doing 3D graphics in the browser.\",\n \"author\": \"Ben Coleman\",\n \"license\": \"MIT\",\n \"homepage\": \"https://code.benco.io/gsots3d/docs\",\n \"type\": \"module\",\n \"publishConfig\": {\n \"@benc-uk:registry\": \"https://npm.pkg.github.com\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/benc-uk/gsots3d.git\"\n },\n \"exports\": {\n \".\": \"./dist/index.js\",\n \"./parsers\": \"./dist/parsers/index.js\"\n },\n \"browser\": {\n \".\": \"./dist-bundle/gsots3d.js\"\n },\n \"files\": [\n \"dist/\",\n \"readme.md\"\n ],\n \"keywords\": [\n \"webgl\",\n \"graphics\",\n \"3d\",\n \"twgl\",\n \"typescript\"\n ],\n \"scripts\": {\n \"lint\": \"eslint --ext .ts src && prettier --check src && prettier --check shaders\",\n \"lint-fix\": \"eslint --ext .ts src --fix && prettier --write src && prettier --write shaders\",\n \"check\": \"tsc\",\n \"build\": \"tsc && tsup\",\n \"watch\": \"tsc && npm run build && run-when-changed --watch 'src/**' --watch 'shaders/**' --exec 'npm run build'\",\n \"build-bundle\": \"tsc && tsup --config tsup.config-bundle.js\",\n \"watch-bundle\": \"tsc && npm run build-bundle && run-when-changed --watch 'src/**' --watch 'shaders/**' --exec 'npm run build-bundle'\",\n \"clean\": \"rm -rf dist\",\n \"docs\": \"typedoc --out docs --gitRevision main ./src/\",\n \"examples\": \"vite --port 3000 ./examples/\"\n },\n \"devDependencies\": {\n \"@typescript-eslint/eslint-plugin\": \"^6.2.1\",\n \"@typescript-eslint/parser\": \"^6.2.1\",\n \"esbuild-plugin-glsl\": \"^1.2.1\",\n \"eslint\": \"^8.46.0\",\n \"prettier\": \"^2.8.8\",\n \"prettier-plugin-glsl\": \"^0.0.10\",\n \"run-when-changed\": \"^2.1.0\",\n \"tsup\": \"^7.2.0\",\n \"typedoc\": \"^0.24.8\",\n \"typescript\": \"^5.1.6\",\n \"vite\": \"^4.4.8\"\n },\n \"dependencies\": {\n \"gl-matrix\": \"^3.4.3\",\n \"loglevel\": \"^1.8.1\",\n \"twgl.js\": \"^5.5.1\"\n }\n}\n","/* @license twgl.js 5.5.1 Copyright (c) 2015, Gregg Tavares All Rights Reserved.\nAvailable via the MIT license.\nsee: http://github.com/greggman/twgl.js for details */\n/*\n * Copyright 2019 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\n/**\n *\n * Vec3 math math functions.\n *\n * Almost all functions take an optional `dst` argument. If it is not passed in the\n * functions will create a new Vec3. In other words you can do this\n *\n * var v = v3.cross(v1, v2); // Creates a new Vec3 with the cross product of v1 x v2.\n *\n * or\n *\n * var v = v3.create();\n * v3.cross(v1, v2, v); // Puts the cross product of v1 x v2 in v\n *\n * The first style is often easier but depending on where it's used it generates garbage where\n * as there is almost never allocation with the second style.\n *\n * It is always save to pass any vector as the destination. So for example\n *\n * v3.cross(v1, v2, v1); // Puts the cross product of v1 x v2 in v1\n *\n * @module twgl/v3\n */\n\nlet VecType = Float32Array;\n\n/**\n * A JavaScript array with 3 values or a Float32Array with 3 values.\n * When created by the library will create the default type which is `Float32Array`\n * but can be set by calling {@link module:twgl/v3.setDefaultType}.\n * @typedef {(number[]|Float32Array)} Vec3\n * @memberOf module:twgl/v3\n */\n\n/**\n * Sets the type this library creates for a Vec3\n * @param {constructor} ctor the constructor for the type. Either `Float32Array` or `Array`\n * @return {constructor} previous constructor for Vec3\n * @memberOf module:twgl/v3\n */\nfunction setDefaultType$1(ctor) {\n const oldType = VecType;\n VecType = ctor;\n return oldType;\n}\n\n/**\n * Creates a vec3; may be called with x, y, z to set initial values.\n * @param {number} [x] Initial x value.\n * @param {number} [y] Initial y value.\n * @param {number} [z] Initial z value.\n * @return {module:twgl/v3.Vec3} the created vector\n * @memberOf module:twgl/v3\n */\nfunction create$1(x, y, z) {\n const dst = new VecType(3);\n if (x) {\n dst[0] = x;\n }\n if (y) {\n dst[1] = y;\n }\n if (z) {\n dst[2] = z;\n }\n return dst;\n}\n\n/**\n * Adds two vectors; assumes a and b have the same dimension.\n * @param {module:twgl/v3.Vec3} a Operand vector.\n * @param {module:twgl/v3.Vec3} b Operand vector.\n * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created.\n * @return {module:twgl/v3.Vec3} A vector tha tis the sum of a and b.\n * @memberOf module:twgl/v3\n */\nfunction add(a, b, dst) {\n dst = dst || new VecType(3);\n\n dst[0] = a[0] + b[0];\n dst[1] = a[1] + b[1];\n dst[2] = a[2] + b[2];\n\n return dst;\n}\n\n/**\n * Subtracts two vectors.\n * @param {module:twgl/v3.Vec3} a Operand vector.\n * @param {module:twgl/v3.Vec3} b Operand vector.\n * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created.\n * @return {module:twgl/v3.Vec3} A vector that is the difference of a and b.\n * @memberOf module:twgl/v3\n */\nfunction subtract(a, b, dst) {\n dst = dst || new VecType(3);\n\n dst[0] = a[0] - b[0];\n dst[1] = a[1] - b[1];\n dst[2] = a[2] - b[2];\n\n return dst;\n}\n\n/**\n * Performs linear interpolation on two vectors.\n * Given vectors a and b and interpolation coefficient t, returns\n * a + t * (b - a).\n * @param {module:twgl/v3.Vec3} a Operand vector.\n * @param {module:twgl/v3.Vec3} b Operand vector.\n * @param {number} t Interpolation coefficient.\n * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created.\n * @return {module:twgl/v3.Vec3} The linear interpolated result.\n * @memberOf module:twgl/v3\n */\nfunction lerp(a, b, t, dst) {\n dst = dst || new VecType(3);\n\n dst[0] = a[0] + t * (b[0] - a[0]);\n dst[1] = a[1] + t * (b[1] - a[1]);\n dst[2] = a[2] + t * (b[2] - a[2]);\n\n return dst;\n}\n\n/**\n * Performs linear interpolation on two vectors.\n * Given vectors a and b and interpolation coefficient vector t, returns\n * a + t * (b - a).\n * @param {module:twgl/v3.Vec3} a Operand vector.\n * @param {module:twgl/v3.Vec3} b Operand vector.\n * @param {module:twgl/v3.Vec3} t Interpolation coefficients vector.\n * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created.\n * @return {module:twgl/v3.Vec3} the linear interpolated result.\n * @memberOf module:twgl/v3\n */\nfunction lerpV(a, b, t, dst) {\n dst = dst || new VecType(3);\n\n dst[0] = a[0] + t[0] * (b[0] - a[0]);\n dst[1] = a[1] + t[1] * (b[1] - a[1]);\n dst[2] = a[2] + t[2] * (b[2] - a[2]);\n\n return dst;\n}\n\n/**\n * Return max values of two vectors.\n * Given vectors a and b returns\n * [max(a[0], b[0]), max(a[1], b[1]), max(a[2], b[2])].\n * @param {module:twgl/v3.Vec3} a Operand vector.\n * @param {module:twgl/v3.Vec3} b Operand vector.\n * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created.\n * @return {module:twgl/v3.Vec3} The max components vector.\n * @memberOf module:twgl/v3\n */\nfunction max(a, b, dst) {\n dst = dst || new VecType(3);\n\n dst[0] = Math.max(a[0], b[0]);\n dst[1] = Math.max(a[1], b[1]);\n dst[2] = Math.max(a[2], b[2]);\n\n return dst;\n}\n\n/**\n * Return min values of two vectors.\n * Given vectors a and b returns\n * [min(a[0], b[0]), min(a[1], b[1]), min(a[2], b[2])].\n * @param {module:twgl/v3.Vec3} a Operand vector.\n * @param {module:twgl/v3.Vec3} b Operand vector.\n * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created.\n * @return {module:twgl/v3.Vec3} The min components vector.\n * @memberOf module:twgl/v3\n */\nfunction min(a, b, dst) {\n dst = dst || new VecType(3);\n\n dst[0] = Math.min(a[0], b[0]);\n dst[1] = Math.min(a[1], b[1]);\n dst[2] = Math.min(a[2], b[2]);\n\n return dst;\n}\n\n/**\n * Multiplies a vector by a scalar.\n * @param {module:twgl/v3.Vec3} v The vector.\n * @param {number} k The scalar.\n * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created.\n * @return {module:twgl/v3.Vec3} The scaled vector.\n * @memberOf module:twgl/v3\n */\nfunction mulScalar(v, k, dst) {\n dst = dst || new VecType(3);\n\n dst[0] = v[0] * k;\n dst[1] = v[1] * k;\n dst[2] = v[2] * k;\n\n return dst;\n}\n\n/**\n * Divides a vector by a scalar.\n * @param {module:twgl/v3.Vec3} v The vector.\n * @param {number} k The scalar.\n * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created.\n * @return {module:twgl/v3.Vec3} The scaled vector.\n * @memberOf module:twgl/v3\n */\nfunction divScalar(v, k, dst) {\n dst = dst || new VecType(3);\n\n dst[0] = v[0] / k;\n dst[1] = v[1] / k;\n dst[2] = v[2] / k;\n\n return dst;\n}\n\n/**\n * Computes the cross product of two vectors; assumes both vectors have\n * three entries.\n * @param {module:twgl/v3.Vec3} a Operand vector.\n * @param {module:twgl/v3.Vec3} b Operand vector.\n * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created.\n * @return {module:twgl/v3.Vec3} The vector of a cross b.\n * @memberOf module:twgl/v3\n */\nfunction cross(a, b, dst) {\n dst = dst || new VecType(3);\n\n const t1 = a[2] * b[0] - a[0] * b[2];\n const t2 = a[0] * b[1] - a[1] * b[0];\n dst[0] = a[1] * b[2] - a[2] * b[1];\n dst[1] = t1;\n dst[2] = t2;\n\n return dst;\n}\n\n/**\n * Computes the dot product of two vectors; assumes both vectors have\n * three entries.\n * @param {module:twgl/v3.Vec3} a Operand vector.\n * @param {module:twgl/v3.Vec3} b Operand vector.\n * @return {number} dot product\n * @memberOf module:twgl/v3\n */\nfunction dot(a, b) {\n return (a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]);\n}\n\n/**\n * Computes the length of vector\n * @param {module:twgl/v3.Vec3} v vector.\n * @return {number} length of vector.\n * @memberOf module:twgl/v3\n */\nfunction length$1(v) {\n return Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);\n}\n\n/**\n * Computes the square of the length of vector\n * @param {module:twgl/v3.Vec3} v vector.\n * @return {number} square of the length of vector.\n * @memberOf module:twgl/v3\n */\nfunction lengthSq(v) {\n return v[0] * v[0] + v[1] * v[1] + v[2] * v[2];\n}\n\n/**\n * Computes the distance between 2 points\n * @param {module:twgl/v3.Vec3} a vector.\n * @param {module:twgl/v3.Vec3} b vector.\n * @return {number} distance between a and b\n * @memberOf module:twgl/v3\n */\nfunction distance(a, b) {\n const dx = a[0] - b[0];\n const dy = a[1] - b[1];\n const dz = a[2] - b[2];\n return Math.sqrt(dx * dx + dy * dy + dz * dz);\n}\n\n/**\n * Computes the square of the distance between 2 points\n * @param {module:twgl/v3.Vec3} a vector.\n * @param {module:twgl/v3.Vec3} b vector.\n * @return {number} square of the distance between a and b\n * @memberOf module:twgl/v3\n */\nfunction distanceSq(a, b) {\n const dx = a[0] - b[0];\n const dy = a[1] - b[1];\n const dz = a[2] - b[2];\n return dx * dx + dy * dy + dz * dz;\n}\n\n/**\n * Divides a vector by its Euclidean length and returns the quotient.\n * @param {module:twgl/v3.Vec3} a The vector.\n * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created.\n * @return {module:twgl/v3.Vec3} The normalized vector.\n * @memberOf module:twgl/v3\n */\nfunction normalize(a, dst) {\n dst = dst || new VecType(3);\n\n const lenSq = a[0] * a[0] + a[1] * a[1] + a[2] * a[2];\n const len = Math.sqrt(lenSq);\n if (len > 0.00001) {\n dst[0] = a[0] / len;\n dst[1] = a[1] / len;\n dst[2] = a[2] / len;\n } else {\n dst[0] = 0;\n dst[1] = 0;\n dst[2] = 0;\n }\n\n return dst;\n}\n\n/**\n * Negates a vector.\n * @param {module:twgl/v3.Vec3} v The vector.\n * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created.\n * @return {module:twgl/v3.Vec3} -v.\n * @memberOf module:twgl/v3\n */\nfunction negate$1(v, dst) {\n dst = dst || new VecType(3);\n\n dst[0] = -v[0];\n dst[1] = -v[1];\n dst[2] = -v[2];\n\n return dst;\n}\n\n/**\n * Copies a vector.\n * @param {module:twgl/v3.Vec3} v The vector.\n * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created.\n * @return {module:twgl/v3.Vec3} A copy of v.\n * @memberOf module:twgl/v3\n */\nfunction copy$1(v, dst) {\n dst = dst || new VecType(3);\n\n dst[0] = v[0];\n dst[1] = v[1];\n dst[2] = v[2];\n\n return dst;\n}\n\n/**\n * Multiplies a vector by another vector (component-wise); assumes a and\n * b have the same length.\n * @param {module:twgl/v3.Vec3} a Operand vector.\n * @param {module:twgl/v3.Vec3} b Operand vector.\n * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created.\n * @return {module:twgl/v3.Vec3} The vector of products of entries of a and\n * b.\n * @memberOf module:twgl/v3\n */\nfunction multiply$1(a, b, dst) {\n dst = dst || new VecType(3);\n\n dst[0] = a[0] * b[0];\n dst[1] = a[1] * b[1];\n dst[2] = a[2] * b[2];\n\n return dst;\n}\n\n/**\n * Divides a vector by another vector (component-wise); assumes a and\n * b have the same length.\n * @param {module:twgl/v3.Vec3} a Operand vector.\n * @param {module:twgl/v3.Vec3} b Operand vector.\n * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created.\n * @return {module:twgl/v3.Vec3} The vector of quotients of entries of a and\n * b.\n * @memberOf module:twgl/v3\n */\nfunction divide(a, b, dst) {\n dst = dst || new VecType(3);\n\n dst[0] = a[0] / b[0];\n dst[1] = a[1] / b[1];\n dst[2] = a[2] / b[2];\n\n return dst;\n}\n\nvar v3 = /*#__PURE__*/Object.freeze({\n __proto__: null,\n add: add,\n copy: copy$1,\n create: create$1,\n cross: cross,\n distance: distance,\n distanceSq: distanceSq,\n divide: divide,\n divScalar: divScalar,\n dot: dot,\n lerp: lerp,\n lerpV: lerpV,\n length: length$1,\n lengthSq: lengthSq,\n max: max,\n min: min,\n mulScalar: mulScalar,\n multiply: multiply$1,\n negate: negate$1,\n normalize: normalize,\n setDefaultType: setDefaultType$1,\n subtract: subtract\n});\n\n/*\n * Copyright 2019 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\n/**\n * 4x4 Matrix math math functions.\n *\n * Almost all functions take an optional `dst` argument. If it is not passed in the\n * functions will create a new matrix. In other words you can do this\n *\n * const mat = m4.translation([1, 2, 3]); // Creates a new translation matrix\n *\n * or\n *\n * const mat = m4.create();\n * m4.translation([1, 2, 3], mat); // Puts translation matrix in mat.\n *\n * The first style is often easier but depending on where it's used it generates garbage where\n * as there is almost never allocation with the second style.\n *\n * It is always save to pass any matrix as the destination. So for example\n *\n * const mat = m4.identity();\n * const trans = m4.translation([1, 2, 3]);\n * m4.multiply(mat, trans, mat); // Multiplies mat * trans and puts result in mat.\n *\n * @module twgl/m4\n */\nlet MatType = Float32Array;\n\n/**\n * A JavaScript array with 16 values or a Float32Array with 16 values.\n * When created by the library will create the default type which is `Float32Array`\n * but can be set by calling {@link module:twgl/m4.setDefaultType}.\n * @typedef {(number[]|Float32Array)} Mat4\n * @memberOf module:twgl/m4\n */\n\n/**\n * Sets the type this library creates for a Mat4\n * @param {constructor} ctor the constructor for the type. Either `Float32Array` or `Array`\n * @return {constructor} previous constructor for Mat4\n * @memberOf module:twgl/m4\n */\nfunction setDefaultType(ctor) {\n const oldType = MatType;\n MatType = ctor;\n return oldType;\n}\n\n/**\n * Negates a matrix.\n * @param {module:twgl/m4.Mat4} m The matrix.\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} -m.\n * @memberOf module:twgl/m4\n */\nfunction negate(m, dst) {\n dst = dst || new MatType(16);\n\n dst[ 0] = -m[ 0];\n dst[ 1] = -m[ 1];\n dst[ 2] = -m[ 2];\n dst[ 3] = -m[ 3];\n dst[ 4] = -m[ 4];\n dst[ 5] = -m[ 5];\n dst[ 6] = -m[ 6];\n dst[ 7] = -m[ 7];\n dst[ 8] = -m[ 8];\n dst[ 9] = -m[ 9];\n dst[10] = -m[10];\n dst[11] = -m[11];\n dst[12] = -m[12];\n dst[13] = -m[13];\n dst[14] = -m[14];\n dst[15] = -m[15];\n\n return dst;\n}\n\n/**\n * Creates a matrix.\n * @return {module:twgl/m4.Mat4} A new matrix.\n * @memberOf module:twgl/m4\n */\nfunction create() {\n return new MatType(16).fill(0);\n}\n\n/**\n * Copies a matrix.\n * @param {module:twgl/m4.Mat4} m The matrix.\n * @param {module:twgl/m4.Mat4} [dst] The matrix. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} A copy of m.\n * @memberOf module:twgl/m4\n */\nfunction copy(m, dst) {\n dst = dst || new MatType(16);\n\n dst[ 0] = m[ 0];\n dst[ 1] = m[ 1];\n dst[ 2] = m[ 2];\n dst[ 3] = m[ 3];\n dst[ 4] = m[ 4];\n dst[ 5] = m[ 5];\n dst[ 6] = m[ 6];\n dst[ 7] = m[ 7];\n dst[ 8] = m[ 8];\n dst[ 9] = m[ 9];\n dst[10] = m[10];\n dst[11] = m[11];\n dst[12] = m[12];\n dst[13] = m[13];\n dst[14] = m[14];\n dst[15] = m[15];\n\n return dst;\n}\n\n/**\n * Creates an n-by-n identity matrix.\n *\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} An n-by-n identity matrix.\n * @memberOf module:twgl/m4\n */\nfunction identity(dst) {\n dst = dst || new MatType(16);\n\n dst[ 0] = 1;\n dst[ 1] = 0;\n dst[ 2] = 0;\n dst[ 3] = 0;\n dst[ 4] = 0;\n dst[ 5] = 1;\n dst[ 6] = 0;\n dst[ 7] = 0;\n dst[ 8] = 0;\n dst[ 9] = 0;\n dst[10] = 1;\n dst[11] = 0;\n dst[12] = 0;\n dst[13] = 0;\n dst[14] = 0;\n dst[15] = 1;\n\n return dst;\n}\n\n/**\n * Takes the transpose of a matrix.\n * @param {module:twgl/m4.Mat4} m The matrix.\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The transpose of m.\n * @memberOf module:twgl/m4\n */\n function transpose(m, dst) {\n dst = dst || new MatType(16);\n if (dst === m) {\n let t;\n\n t = m[1];\n m[1] = m[4];\n m[4] = t;\n\n t = m[2];\n m[2] = m[8];\n m[8] = t;\n\n t = m[3];\n m[3] = m[12];\n m[12] = t;\n\n t = m[6];\n m[6] = m[9];\n m[9] = t;\n\n t = m[7];\n m[7] = m[13];\n m[13] = t;\n\n t = m[11];\n m[11] = m[14];\n m[14] = t;\n return dst;\n }\n\n const m00 = m[0 * 4 + 0];\n const m01 = m[0 * 4 + 1];\n const m02 = m[0 * 4 + 2];\n const m03 = m[0 * 4 + 3];\n const m10 = m[1 * 4 + 0];\n const m11 = m[1 * 4 + 1];\n const m12 = m[1 * 4 + 2];\n const m13 = m[1 * 4 + 3];\n const m20 = m[2 * 4 + 0];\n const m21 = m[2 * 4 + 1];\n const m22 = m[2 * 4 + 2];\n const m23 = m[2 * 4 + 3];\n const m30 = m[3 * 4 + 0];\n const m31 = m[3 * 4 + 1];\n const m32 = m[3 * 4 + 2];\n const m33 = m[3 * 4 + 3];\n\n dst[ 0] = m00;\n dst[ 1] = m10;\n dst[ 2] = m20;\n dst[ 3] = m30;\n dst[ 4] = m01;\n dst[ 5] = m11;\n dst[ 6] = m21;\n dst[ 7] = m31;\n dst[ 8] = m02;\n dst[ 9] = m12;\n dst[10] = m22;\n dst[11] = m32;\n dst[12] = m03;\n dst[13] = m13;\n dst[14] = m23;\n dst[15] = m33;\n\n return dst;\n}\n\n/**\n * Computes the inverse of a 4-by-4 matrix.\n * @param {module:twgl/m4.Mat4} m The matrix.\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The inverse of m.\n * @memberOf module:twgl/m4\n */\nfunction inverse(m, dst) {\n dst = dst || new MatType(16);\n\n const m00 = m[0 * 4 + 0];\n const m01 = m[0 * 4 + 1];\n const m02 = m[0 * 4 + 2];\n const m03 = m[0 * 4 + 3];\n const m10 = m[1 * 4 + 0];\n const m11 = m[1 * 4 + 1];\n const m12 = m[1 * 4 + 2];\n const m13 = m[1 * 4 + 3];\n const m20 = m[2 * 4 + 0];\n const m21 = m[2 * 4 + 1];\n const m22 = m[2 * 4 + 2];\n const m23 = m[2 * 4 + 3];\n const m30 = m[3 * 4 + 0];\n const m31 = m[3 * 4 + 1];\n const m32 = m[3 * 4 + 2];\n const m33 = m[3 * 4 + 3];\n const tmp_0 = m22 * m33;\n const tmp_1 = m32 * m23;\n const tmp_2 = m12 * m33;\n const tmp_3 = m32 * m13;\n const tmp_4 = m12 * m23;\n const tmp_5 = m22 * m13;\n const tmp_6 = m02 * m33;\n const tmp_7 = m32 * m03;\n const tmp_8 = m02 * m23;\n const tmp_9 = m22 * m03;\n const tmp_10 = m02 * m13;\n const tmp_11 = m12 * m03;\n const tmp_12 = m20 * m31;\n const tmp_13 = m30 * m21;\n const tmp_14 = m10 * m31;\n const tmp_15 = m30 * m11;\n const tmp_16 = m10 * m21;\n const tmp_17 = m20 * m11;\n const tmp_18 = m00 * m31;\n const tmp_19 = m30 * m01;\n const tmp_20 = m00 * m21;\n const tmp_21 = m20 * m01;\n const tmp_22 = m00 * m11;\n const tmp_23 = m10 * m01;\n\n const t0 = (tmp_0 * m11 + tmp_3 * m21 + tmp_4 * m31) -\n (tmp_1 * m11 + tmp_2 * m21 + tmp_5 * m31);\n const t1 = (tmp_1 * m01 + tmp_6 * m21 + tmp_9 * m31) -\n (tmp_0 * m01 + tmp_7 * m21 + tmp_8 * m31);\n const t2 = (tmp_2 * m01 + tmp_7 * m11 + tmp_10 * m31) -\n (tmp_3 * m01 + tmp_6 * m11 + tmp_11 * m31);\n const t3 = (tmp_5 * m01 + tmp_8 * m11 + tmp_11 * m21) -\n (tmp_4 * m01 + tmp_9 * m11 + tmp_10 * m21);\n\n const d = 1.0 / (m00 * t0 + m10 * t1 + m20 * t2 + m30 * t3);\n\n dst[ 0] = d * t0;\n dst[ 1] = d * t1;\n dst[ 2] = d * t2;\n dst[ 3] = d * t3;\n dst[ 4] = d * ((tmp_1 * m10 + tmp_2 * m20 + tmp_5 * m30) -\n (tmp_0 * m10 + tmp_3 * m20 + tmp_4 * m30));\n dst[ 5] = d * ((tmp_0 * m00 + tmp_7 * m20 + tmp_8 * m30) -\n (tmp_1 * m00 + tmp_6 * m20 + tmp_9 * m30));\n dst[ 6] = d * ((tmp_3 * m00 + tmp_6 * m10 + tmp_11 * m30) -\n (tmp_2 * m00 + tmp_7 * m10 + tmp_10 * m30));\n dst[ 7] = d * ((tmp_4 * m00 + tmp_9 * m10 + tmp_10 * m20) -\n (tmp_5 * m00 + tmp_8 * m10 + tmp_11 * m20));\n dst[ 8] = d * ((tmp_12 * m13 + tmp_15 * m23 + tmp_16 * m33) -\n (tmp_13 * m13 + tmp_14 * m23 + tmp_17 * m33));\n dst[ 9] = d * ((tmp_13 * m03 + tmp_18 * m23 + tmp_21 * m33) -\n (tmp_12 * m03 + tmp_19 * m23 + tmp_20 * m33));\n dst[10] = d * ((tmp_14 * m03 + tmp_19 * m13 + tmp_22 * m33) -\n (tmp_15 * m03 + tmp_18 * m13 + tmp_23 * m33));\n dst[11] = d * ((tmp_17 * m03 + tmp_20 * m13 + tmp_23 * m23) -\n (tmp_16 * m03 + tmp_21 * m13 + tmp_22 * m23));\n dst[12] = d * ((tmp_14 * m22 + tmp_17 * m32 + tmp_13 * m12) -\n (tmp_16 * m32 + tmp_12 * m12 + tmp_15 * m22));\n dst[13] = d * ((tmp_20 * m32 + tmp_12 * m02 + tmp_19 * m22) -\n (tmp_18 * m22 + tmp_21 * m32 + tmp_13 * m02));\n dst[14] = d * ((tmp_18 * m12 + tmp_23 * m32 + tmp_15 * m02) -\n (tmp_22 * m32 + tmp_14 * m02 + tmp_19 * m12));\n dst[15] = d * ((tmp_22 * m22 + tmp_16 * m02 + tmp_21 * m12) -\n (tmp_20 * m12 + tmp_23 * m22 + tmp_17 * m02));\n\n return dst;\n}\n\n/**\n * Multiplies two 4-by-4 matrices with a on the left and b on the right\n * @param {module:twgl/m4.Mat4} a The matrix on the left.\n * @param {module:twgl/m4.Mat4} b The matrix on the right.\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The matrix product of a and b.\n * @memberOf module:twgl/m4\n */\nfunction multiply(a, b, dst) {\n dst = dst || new MatType(16);\n\n const a00 = a[0];\n const a01 = a[1];\n const a02 = a[2];\n const a03 = a[3];\n const a10 = a[ 4 + 0];\n const a11 = a[ 4 + 1];\n const a12 = a[ 4 + 2];\n const a13 = a[ 4 + 3];\n const a20 = a[ 8 + 0];\n const a21 = a[ 8 + 1];\n const a22 = a[ 8 + 2];\n const a23 = a[ 8 + 3];\n const a30 = a[12 + 0];\n const a31 = a[12 + 1];\n const a32 = a[12 + 2];\n const a33 = a[12 + 3];\n const b00 = b[0];\n const b01 = b[1];\n const b02 = b[2];\n const b03 = b[3];\n const b10 = b[ 4 + 0];\n const b11 = b[ 4 + 1];\n const b12 = b[ 4 + 2];\n const b13 = b[ 4 + 3];\n const b20 = b[ 8 + 0];\n const b21 = b[ 8 + 1];\n const b22 = b[ 8 + 2];\n const b23 = b[ 8 + 3];\n const b30 = b[12 + 0];\n const b31 = b[12 + 1];\n const b32 = b[12 + 2];\n const b33 = b[12 + 3];\n\n dst[ 0] = a00 * b00 + a10 * b01 + a20 * b02 + a30 * b03;\n dst[ 1] = a01 * b00 + a11 * b01 + a21 * b02 + a31 * b03;\n dst[ 2] = a02 * b00 + a12 * b01 + a22 * b02 + a32 * b03;\n dst[ 3] = a03 * b00 + a13 * b01 + a23 * b02 + a33 * b03;\n dst[ 4] = a00 * b10 + a10 * b11 + a20 * b12 + a30 * b13;\n dst[ 5] = a01 * b10 + a11 * b11 + a21 * b12 + a31 * b13;\n dst[ 6] = a02 * b10 + a12 * b11 + a22 * b12 + a32 * b13;\n dst[ 7] = a03 * b10 + a13 * b11 + a23 * b12 + a33 * b13;\n dst[ 8] = a00 * b20 + a10 * b21 + a20 * b22 + a30 * b23;\n dst[ 9] = a01 * b20 + a11 * b21 + a21 * b22 + a31 * b23;\n dst[10] = a02 * b20 + a12 * b21 + a22 * b22 + a32 * b23;\n dst[11] = a03 * b20 + a13 * b21 + a23 * b22 + a33 * b23;\n dst[12] = a00 * b30 + a10 * b31 + a20 * b32 + a30 * b33;\n dst[13] = a01 * b30 + a11 * b31 + a21 * b32 + a31 * b33;\n dst[14] = a02 * b30 + a12 * b31 + a22 * b32 + a32 * b33;\n dst[15] = a03 * b30 + a13 * b31 + a23 * b32 + a33 * b33;\n\n return dst;\n}\n\n/**\n * Sets the translation component of a 4-by-4 matrix to the given\n * vector.\n * @param {module:twgl/m4.Mat4} a The matrix.\n * @param {module:twgl/v3.Vec3} v The vector.\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The matrix with translation set.\n * @memberOf module:twgl/m4\n */\nfunction setTranslation(a, v, dst) {\n dst = dst || identity();\n if (a !== dst) {\n dst[ 0] = a[ 0];\n dst[ 1] = a[ 1];\n dst[ 2] = a[ 2];\n dst[ 3] = a[ 3];\n dst[ 4] = a[ 4];\n dst[ 5] = a[ 5];\n dst[ 6] = a[ 6];\n dst[ 7] = a[ 7];\n dst[ 8] = a[ 8];\n dst[ 9] = a[ 9];\n dst[10] = a[10];\n dst[11] = a[11];\n }\n dst[12] = v[0];\n dst[13] = v[1];\n dst[14] = v[2];\n dst[15] = 1;\n return dst;\n}\n\n/**\n * Returns the translation component of a 4-by-4 matrix as a vector with 3\n * entries.\n * @param {module:twgl/m4.Mat4} m The matrix.\n * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not passed a new one is created.\n * @return {module:twgl/v3.Vec3} The translation component of m.\n * @memberOf module:twgl/m4\n */\nfunction getTranslation(m, dst) {\n dst = dst || create$1();\n dst[0] = m[12];\n dst[1] = m[13];\n dst[2] = m[14];\n return dst;\n}\n\n/**\n * Returns an axis of a 4x4 matrix as a vector with 3 entries\n * @param {module:twgl/m4.Mat4} m The matrix.\n * @param {number} axis The axis 0 = x, 1 = y, 2 = z;\n * @return {module:twgl/v3.Vec3} [dst] vector.\n * @return {module:twgl/v3.Vec3} The axis component of m.\n * @memberOf module:twgl/m4\n */\nfunction getAxis(m, axis, dst) {\n dst = dst || create$1();\n const off = axis * 4;\n dst[0] = m[off + 0];\n dst[1] = m[off + 1];\n dst[2] = m[off + 2];\n return dst;\n}\n\n/**\n * Sets an axis of a 4x4 matrix as a vector with 3 entries\n * @param {module:twgl/m4.Mat4} m The matrix.\n * @param {module:twgl/v3.Vec3} v the axis vector\n * @param {number} axis The axis 0 = x, 1 = y, 2 = z;\n * @param {module:twgl/m4.Mat4} [dst] The matrix to set. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The matrix with axis set.\n * @memberOf module:twgl/m4\n */\nfunction setAxis(a, v, axis, dst) {\n if (dst !== a) {\n dst = copy(a, dst);\n }\n const off = axis * 4;\n dst[off + 0] = v[0];\n dst[off + 1] = v[1];\n dst[off + 2] = v[2];\n return dst;\n}\n\n/**\n * Computes a 4-by-4 perspective transformation matrix given the angular height\n * of the frustum, the aspect ratio, and the near and far clipping planes. The\n * arguments define a frustum extending in the negative z direction. The given\n * angle is the vertical angle of the frustum, and the horizontal angle is\n * determined to produce the given aspect ratio. The arguments near and far are\n * the distances to the near and far clipping planes. Note that near and far\n * are not z coordinates, but rather they are distances along the negative\n * z-axis. The matrix generated sends the viewing frustum to the unit box.\n * We assume a unit box extending from -1 to 1 in the x and y dimensions and\n * from 0 to 1 in the z dimension.\n * @param {number} fieldOfViewYInRadians The camera angle from top to bottom (in radians).\n * @param {number} aspect The aspect ratio width / height.\n * @param {number} zNear The depth (negative z coordinate)\n * of the near clipping plane.\n * @param {number} zFar The depth (negative z coordinate)\n * of the far clipping plane.\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The perspective matrix.\n * @memberOf module:twgl/m4\n */\nfunction perspective(fieldOfViewYInRadians, aspect, zNear, zFar, dst) {\n dst = dst || new MatType(16);\n\n const f = Math.tan(Math.PI * 0.5 - 0.5 * fieldOfViewYInRadians);\n const rangeInv = 1.0 / (zNear - zFar);\n\n dst[0] = f / aspect;\n dst[1] = 0;\n dst[2] = 0;\n dst[3] = 0;\n\n dst[4] = 0;\n dst[5] = f;\n dst[6] = 0;\n dst[7] = 0;\n\n dst[8] = 0;\n dst[9] = 0;\n dst[10] = (zNear + zFar) * rangeInv;\n dst[11] = -1;\n\n dst[12] = 0;\n dst[13] = 0;\n dst[14] = zNear * zFar * rangeInv * 2;\n dst[15] = 0;\n\n return dst;\n}\n\n/**\n * Computes a 4-by-4 orthogonal transformation matrix given the left, right,\n * bottom, and top dimensions of the near clipping plane as well as the\n * near and far clipping plane distances.\n * @param {number} left Left side of the near clipping plane viewport.\n * @param {number} right Right side of the near clipping plane viewport.\n * @param {number} bottom Bottom of the near clipping plane viewport.\n * @param {number} top Top of the near clipping plane viewport.\n * @param {number} near The depth (negative z coordinate)\n * of the near clipping plane.\n * @param {number} far The depth (negative z coordinate)\n * of the far clipping plane.\n * @param {module:twgl/m4.Mat4} [dst] Output matrix. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The perspective matrix.\n * @memberOf module:twgl/m4\n */\nfunction ortho(left, right, bottom, top, near, far, dst) {\n dst = dst || new MatType(16);\n\n dst[0] = 2 / (right - left);\n dst[1] = 0;\n dst[2] = 0;\n dst[3] = 0;\n\n dst[4] = 0;\n dst[5] = 2 / (top - bottom);\n dst[6] = 0;\n dst[7] = 0;\n\n dst[8] = 0;\n dst[9] = 0;\n dst[10] = 2 / (near - far);\n dst[11] = 0;\n\n dst[12] = (right + left) / (left - right);\n dst[13] = (top + bottom) / (bottom - top);\n dst[14] = (far + near) / (near - far);\n dst[15] = 1;\n\n return dst;\n}\n\n/**\n * Computes a 4-by-4 perspective transformation matrix given the left, right,\n * top, bottom, near and far clipping planes. The arguments define a frustum\n * extending in the negative z direction. The arguments near and far are the\n * distances to the near and far clipping planes. Note that near and far are not\n * z coordinates, but rather they are distances along the negative z-axis. The\n * matrix generated sends the viewing frustum to the unit box. We assume a unit\n * box extending from -1 to 1 in the x and y dimensions and from 0 to 1 in the z\n * dimension.\n * @param {number} left The x coordinate of the left plane of the box.\n * @param {number} right The x coordinate of the right plane of the box.\n * @param {number} bottom The y coordinate of the bottom plane of the box.\n * @param {number} top The y coordinate of the right plane of the box.\n * @param {number} near The negative z coordinate of the near plane of the box.\n * @param {number} far The negative z coordinate of the far plane of the box.\n * @param {module:twgl/m4.Mat4} [dst] Output matrix. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The perspective projection matrix.\n * @memberOf module:twgl/m4\n */\nfunction frustum(left, right, bottom, top, near, far, dst) {\n dst = dst || new MatType(16);\n\n const dx = (right - left);\n const dy = (top - bottom);\n const dz = (near - far);\n\n dst[ 0] = 2 * near / dx;\n dst[ 1] = 0;\n dst[ 2] = 0;\n dst[ 3] = 0;\n dst[ 4] = 0;\n dst[ 5] = 2 * near / dy;\n dst[ 6] = 0;\n dst[ 7] = 0;\n dst[ 8] = (left + right) / dx;\n dst[ 9] = (top + bottom) / dy;\n dst[10] = far / dz;\n dst[11] = -1;\n dst[12] = 0;\n dst[13] = 0;\n dst[14] = near * far / dz;\n dst[15] = 0;\n\n return dst;\n}\n\nlet xAxis;\nlet yAxis;\nlet zAxis;\n\n/**\n * Computes a 4-by-4 look-at transformation.\n *\n * This is a matrix which positions the camera itself. If you want\n * a view matrix (a matrix which moves things in front of the camera)\n * take the inverse of this.\n *\n * @param {module:twgl/v3.Vec3} eye The position of the eye.\n * @param {module:twgl/v3.Vec3} target The position meant to be viewed.\n * @param {module:twgl/v3.Vec3} up A vector pointing up.\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The look-at matrix.\n * @memberOf module:twgl/m4\n */\nfunction lookAt(eye, target, up, dst) {\n dst = dst || new MatType(16);\n\n xAxis = xAxis || create$1();\n yAxis = yAxis || create$1();\n zAxis = zAxis || create$1();\n\n normalize(\n subtract(eye, target, zAxis), zAxis);\n normalize(cross(up, zAxis, xAxis), xAxis);\n normalize(cross(zAxis, xAxis, yAxis), yAxis);\n\n dst[ 0] = xAxis[0];\n dst[ 1] = xAxis[1];\n dst[ 2] = xAxis[2];\n dst[ 3] = 0;\n dst[ 4] = yAxis[0];\n dst[ 5] = yAxis[1];\n dst[ 6] = yAxis[2];\n dst[ 7] = 0;\n dst[ 8] = zAxis[0];\n dst[ 9] = zAxis[1];\n dst[10] = zAxis[2];\n dst[11] = 0;\n dst[12] = eye[0];\n dst[13] = eye[1];\n dst[14] = eye[2];\n dst[15] = 1;\n\n return dst;\n}\n\n/**\n * Creates a 4-by-4 matrix which translates by the given vector v.\n * @param {module:twgl/v3.Vec3} v The vector by\n * which to translate.\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The translation matrix.\n * @memberOf module:twgl/m4\n */\nfunction translation(v, dst) {\n dst = dst || new MatType(16);\n\n dst[ 0] = 1;\n dst[ 1] = 0;\n dst[ 2] = 0;\n dst[ 3] = 0;\n dst[ 4] = 0;\n dst[ 5] = 1;\n dst[ 6] = 0;\n dst[ 7] = 0;\n dst[ 8] = 0;\n dst[ 9] = 0;\n dst[10] = 1;\n dst[11] = 0;\n dst[12] = v[0];\n dst[13] = v[1];\n dst[14] = v[2];\n dst[15] = 1;\n return dst;\n}\n\n/**\n * Translates the given 4-by-4 matrix by the given vector v.\n * @param {module:twgl/m4.Mat4} m The matrix.\n * @param {module:twgl/v3.Vec3} v The vector by\n * which to translate.\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The translated matrix.\n * @memberOf module:twgl/m4\n */\nfunction translate(m, v, dst) {\n dst = dst || new MatType(16);\n\n const v0 = v[0];\n const v1 = v[1];\n const v2 = v[2];\n const m00 = m[0];\n const m01 = m[1];\n const m02 = m[2];\n const m03 = m[3];\n const m10 = m[1 * 4 + 0];\n const m11 = m[1 * 4 + 1];\n const m12 = m[1 * 4 + 2];\n const m13 = m[1 * 4 + 3];\n const m20 = m[2 * 4 + 0];\n const m21 = m[2 * 4 + 1];\n const m22 = m[2 * 4 + 2];\n const m23 = m[2 * 4 + 3];\n const m30 = m[3 * 4 + 0];\n const m31 = m[3 * 4 + 1];\n const m32 = m[3 * 4 + 2];\n const m33 = m[3 * 4 + 3];\n\n if (m !== dst) {\n dst[ 0] = m00;\n dst[ 1] = m01;\n dst[ 2] = m02;\n dst[ 3] = m03;\n dst[ 4] = m10;\n dst[ 5] = m11;\n dst[ 6] = m12;\n dst[ 7] = m13;\n dst[ 8] = m20;\n dst[ 9] = m21;\n dst[10] = m22;\n dst[11] = m23;\n }\n\n dst[12] = m00 * v0 + m10 * v1 + m20 * v2 + m30;\n dst[13] = m01 * v0 + m11 * v1 + m21 * v2 + m31;\n dst[14] = m02 * v0 + m12 * v1 + m22 * v2 + m32;\n dst[15] = m03 * v0 + m13 * v1 + m23 * v2 + m33;\n\n return dst;\n}\n\n/**\n * Creates a 4-by-4 matrix which rotates around the x-axis by the given angle.\n * @param {number} angleInRadians The angle by which to rotate (in radians).\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The rotation matrix.\n * @memberOf module:twgl/m4\n */\nfunction rotationX(angleInRadians, dst) {\n dst = dst || new MatType(16);\n\n const c = Math.cos(angleInRadians);\n const s = Math.sin(angleInRadians);\n\n dst[ 0] = 1;\n dst[ 1] = 0;\n dst[ 2] = 0;\n dst[ 3] = 0;\n dst[ 4] = 0;\n dst[ 5] = c;\n dst[ 6] = s;\n dst[ 7] = 0;\n dst[ 8] = 0;\n dst[ 9] = -s;\n dst[10] = c;\n dst[11] = 0;\n dst[12] = 0;\n dst[13] = 0;\n dst[14] = 0;\n dst[15] = 1;\n\n return dst;\n}\n\n/**\n * Rotates the given 4-by-4 matrix around the x-axis by the given\n * angle.\n * @param {module:twgl/m4.Mat4} m The matrix.\n * @param {number} angleInRadians The angle by which to rotate (in radians).\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The rotated matrix.\n * @memberOf module:twgl/m4\n */\nfunction rotateX(m, angleInRadians, dst) {\n dst = dst || new MatType(16);\n\n const m10 = m[4];\n const m11 = m[5];\n const m12 = m[6];\n const m13 = m[7];\n const m20 = m[8];\n const m21 = m[9];\n const m22 = m[10];\n const m23 = m[11];\n const c = Math.cos(angleInRadians);\n const s = Math.sin(angleInRadians);\n\n dst[4] = c * m10 + s * m20;\n dst[5] = c * m11 + s * m21;\n dst[6] = c * m12 + s * m22;\n dst[7] = c * m13 + s * m23;\n dst[8] = c * m20 - s * m10;\n dst[9] = c * m21 - s * m11;\n dst[10] = c * m22 - s * m12;\n dst[11] = c * m23 - s * m13;\n\n if (m !== dst) {\n dst[ 0] = m[ 0];\n dst[ 1] = m[ 1];\n dst[ 2] = m[ 2];\n dst[ 3] = m[ 3];\n dst[12] = m[12];\n dst[13] = m[13];\n dst[14] = m[14];\n dst[15] = m[15];\n }\n\n return dst;\n}\n\n/**\n * Creates a 4-by-4 matrix which rotates around the y-axis by the given angle.\n * @param {number} angleInRadians The angle by which to rotate (in radians).\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The rotation matrix.\n * @memberOf module:twgl/m4\n */\nfunction rotationY(angleInRadians, dst) {\n dst = dst || new MatType(16);\n\n const c = Math.cos(angleInRadians);\n const s = Math.sin(angleInRadians);\n\n dst[ 0] = c;\n dst[ 1] = 0;\n dst[ 2] = -s;\n dst[ 3] = 0;\n dst[ 4] = 0;\n dst[ 5] = 1;\n dst[ 6] = 0;\n dst[ 7] = 0;\n dst[ 8] = s;\n dst[ 9] = 0;\n dst[10] = c;\n dst[11] = 0;\n dst[12] = 0;\n dst[13] = 0;\n dst[14] = 0;\n dst[15] = 1;\n\n return dst;\n}\n\n/**\n * Rotates the given 4-by-4 matrix around the y-axis by the given\n * angle.\n * @param {module:twgl/m4.Mat4} m The matrix.\n * @param {number} angleInRadians The angle by which to rotate (in radians).\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The rotated matrix.\n * @memberOf module:twgl/m4\n */\nfunction rotateY(m, angleInRadians, dst) {\n dst = dst || new MatType(16);\n\n const m00 = m[0 * 4 + 0];\n const m01 = m[0 * 4 + 1];\n const m02 = m[0 * 4 + 2];\n const m03 = m[0 * 4 + 3];\n const m20 = m[2 * 4 + 0];\n const m21 = m[2 * 4 + 1];\n const m22 = m[2 * 4 + 2];\n const m23 = m[2 * 4 + 3];\n const c = Math.cos(angleInRadians);\n const s = Math.sin(angleInRadians);\n\n dst[ 0] = c * m00 - s * m20;\n dst[ 1] = c * m01 - s * m21;\n dst[ 2] = c * m02 - s * m22;\n dst[ 3] = c * m03 - s * m23;\n dst[ 8] = c * m20 + s * m00;\n dst[ 9] = c * m21 + s * m01;\n dst[10] = c * m22 + s * m02;\n dst[11] = c * m23 + s * m03;\n\n if (m !== dst) {\n dst[ 4] = m[ 4];\n dst[ 5] = m[ 5];\n dst[ 6] = m[ 6];\n dst[ 7] = m[ 7];\n dst[12] = m[12];\n dst[13] = m[13];\n dst[14] = m[14];\n dst[15] = m[15];\n }\n\n return dst;\n}\n\n/**\n * Creates a 4-by-4 matrix which rotates around the z-axis by the given angle.\n * @param {number} angleInRadians The angle by which to rotate (in radians).\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The rotation matrix.\n * @memberOf module:twgl/m4\n */\nfunction rotationZ(angleInRadians, dst) {\n dst = dst || new MatType(16);\n\n const c = Math.cos(angleInRadians);\n const s = Math.sin(angleInRadians);\n\n dst[ 0] = c;\n dst[ 1] = s;\n dst[ 2] = 0;\n dst[ 3] = 0;\n dst[ 4] = -s;\n dst[ 5] = c;\n dst[ 6] = 0;\n dst[ 7] = 0;\n dst[ 8] = 0;\n dst[ 9] = 0;\n dst[10] = 1;\n dst[11] = 0;\n dst[12] = 0;\n dst[13] = 0;\n dst[14] = 0;\n dst[15] = 1;\n\n return dst;\n}\n\n/**\n * Rotates the given 4-by-4 matrix around the z-axis by the given\n * angle.\n * @param {module:twgl/m4.Mat4} m The matrix.\n * @param {number} angleInRadians The angle by which to rotate (in radians).\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The rotated matrix.\n * @memberOf module:twgl/m4\n */\nfunction rotateZ(m, angleInRadians, dst) {\n dst = dst || new MatType(16);\n\n const m00 = m[0 * 4 + 0];\n const m01 = m[0 * 4 + 1];\n const m02 = m[0 * 4 + 2];\n const m03 = m[0 * 4 + 3];\n const m10 = m[1 * 4 + 0];\n const m11 = m[1 * 4 + 1];\n const m12 = m[1 * 4 + 2];\n const m13 = m[1 * 4 + 3];\n const c = Math.cos(angleInRadians);\n const s = Math.sin(angleInRadians);\n\n dst[ 0] = c * m00 + s * m10;\n dst[ 1] = c * m01 + s * m11;\n dst[ 2] = c * m02 + s * m12;\n dst[ 3] = c * m03 + s * m13;\n dst[ 4] = c * m10 - s * m00;\n dst[ 5] = c * m11 - s * m01;\n dst[ 6] = c * m12 - s * m02;\n dst[ 7] = c * m13 - s * m03;\n\n if (m !== dst) {\n dst[ 8] = m[ 8];\n dst[ 9] = m[ 9];\n dst[10] = m[10];\n dst[11] = m[11];\n dst[12] = m[12];\n dst[13] = m[13];\n dst[14] = m[14];\n dst[15] = m[15];\n }\n\n return dst;\n}\n\n/**\n * Creates a 4-by-4 matrix which rotates around the given axis by the given\n * angle.\n * @param {module:twgl/v3.Vec3} axis The axis\n * about which to rotate.\n * @param {number} angleInRadians The angle by which to rotate (in radians).\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} A matrix which rotates angle radians\n * around the axis.\n * @memberOf module:twgl/m4\n */\nfunction axisRotation(axis, angleInRadians, dst) {\n dst = dst || new MatType(16);\n\n let x = axis[0];\n let y = axis[1];\n let z = axis[2];\n const n = Math.sqrt(x * x + y * y + z * z);\n x /= n;\n y /= n;\n z /= n;\n const xx = x * x;\n const yy = y * y;\n const zz = z * z;\n const c = Math.cos(angleInRadians);\n const s = Math.sin(angleInRadians);\n const oneMinusCosine = 1 - c;\n\n dst[ 0] = xx + (1 - xx) * c;\n dst[ 1] = x * y * oneMinusCosine + z * s;\n dst[ 2] = x * z * oneMinusCosine - y * s;\n dst[ 3] = 0;\n dst[ 4] = x * y * oneMinusCosine - z * s;\n dst[ 5] = yy + (1 - yy) * c;\n dst[ 6] = y * z * oneMinusCosine + x * s;\n dst[ 7] = 0;\n dst[ 8] = x * z * oneMinusCosine + y * s;\n dst[ 9] = y * z * oneMinusCosine - x * s;\n dst[10] = zz + (1 - zz) * c;\n dst[11] = 0;\n dst[12] = 0;\n dst[13] = 0;\n dst[14] = 0;\n dst[15] = 1;\n\n return dst;\n}\n\n/**\n * Rotates the given 4-by-4 matrix around the given axis by the\n * given angle.\n * @param {module:twgl/m4.Mat4} m The matrix.\n * @param {module:twgl/v3.Vec3} axis The axis\n * about which to rotate.\n * @param {number} angleInRadians The angle by which to rotate (in radians).\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The rotated matrix.\n * @memberOf module:twgl/m4\n */\nfunction axisRotate(m, axis, angleInRadians, dst) {\n dst = dst || new MatType(16);\n\n let x = axis[0];\n let y = axis[1];\n let z = axis[2];\n const n = Math.sqrt(x * x + y * y + z * z);\n x /= n;\n y /= n;\n z /= n;\n const xx = x * x;\n const yy = y * y;\n const zz = z * z;\n const c = Math.cos(angleInRadians);\n const s = Math.sin(angleInRadians);\n const oneMinusCosine = 1 - c;\n\n const r00 = xx + (1 - xx) * c;\n const r01 = x * y * oneMinusCosine + z * s;\n const r02 = x * z * oneMinusCosine - y * s;\n const r10 = x * y * oneMinusCosine - z * s;\n const r11 = yy + (1 - yy) * c;\n const r12 = y * z * oneMinusCosine + x * s;\n const r20 = x * z * oneMinusCosine + y * s;\n const r21 = y * z * oneMinusCosine - x * s;\n const r22 = zz + (1 - zz) * c;\n\n const m00 = m[0];\n const m01 = m[1];\n const m02 = m[2];\n const m03 = m[3];\n const m10 = m[4];\n const m11 = m[5];\n const m12 = m[6];\n const m13 = m[7];\n const m20 = m[8];\n const m21 = m[9];\n const m22 = m[10];\n const m23 = m[11];\n\n dst[ 0] = r00 * m00 + r01 * m10 + r02 * m20;\n dst[ 1] = r00 * m01 + r01 * m11 + r02 * m21;\n dst[ 2] = r00 * m02 + r01 * m12 + r02 * m22;\n dst[ 3] = r00 * m03 + r01 * m13 + r02 * m23;\n dst[ 4] = r10 * m00 + r11 * m10 + r12 * m20;\n dst[ 5] = r10 * m01 + r11 * m11 + r12 * m21;\n dst[ 6] = r10 * m02 + r11 * m12 + r12 * m22;\n dst[ 7] = r10 * m03 + r11 * m13 + r12 * m23;\n dst[ 8] = r20 * m00 + r21 * m10 + r22 * m20;\n dst[ 9] = r20 * m01 + r21 * m11 + r22 * m21;\n dst[10] = r20 * m02 + r21 * m12 + r22 * m22;\n dst[11] = r20 * m03 + r21 * m13 + r22 * m23;\n\n if (m !== dst) {\n dst[12] = m[12];\n dst[13] = m[13];\n dst[14] = m[14];\n dst[15] = m[15];\n }\n\n return dst;\n}\n\n/**\n * Creates a 4-by-4 matrix which scales in each dimension by an amount given by\n * the corresponding entry in the given vector; assumes the vector has three\n * entries.\n * @param {module:twgl/v3.Vec3} v A vector of\n * three entries specifying the factor by which to scale in each dimension.\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The scaling matrix.\n * @memberOf module:twgl/m4\n */\nfunction scaling(v, dst) {\n dst = dst || new MatType(16);\n\n dst[ 0] = v[0];\n dst[ 1] = 0;\n dst[ 2] = 0;\n dst[ 3] = 0;\n dst[ 4] = 0;\n dst[ 5] = v[1];\n dst[ 6] = 0;\n dst[ 7] = 0;\n dst[ 8] = 0;\n dst[ 9] = 0;\n dst[10] = v[2];\n dst[11] = 0;\n dst[12] = 0;\n dst[13] = 0;\n dst[14] = 0;\n dst[15] = 1;\n\n return dst;\n}\n\n/**\n * Scales the given 4-by-4 matrix in each dimension by an amount\n * given by the corresponding entry in the given vector; assumes the vector has\n * three entries.\n * @param {module:twgl/m4.Mat4} m The matrix to be modified.\n * @param {module:twgl/v3.Vec3} v A vector of three entries specifying the\n * factor by which to scale in each dimension.\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The scaled matrix.\n * @memberOf module:twgl/m4\n */\nfunction scale(m, v, dst) {\n dst = dst || new MatType(16);\n\n const v0 = v[0];\n const v1 = v[1];\n const v2 = v[2];\n\n dst[ 0] = v0 * m[0 * 4 + 0];\n dst[ 1] = v0 * m[0 * 4 + 1];\n dst[ 2] = v0 * m[0 * 4 + 2];\n dst[ 3] = v0 * m[0 * 4 + 3];\n dst[ 4] = v1 * m[1 * 4 + 0];\n dst[ 5] = v1 * m[1 * 4 + 1];\n dst[ 6] = v1 * m[1 * 4 + 2];\n dst[ 7] = v1 * m[1 * 4 + 3];\n dst[ 8] = v2 * m[2 * 4 + 0];\n dst[ 9] = v2 * m[2 * 4 + 1];\n dst[10] = v2 * m[2 * 4 + 2];\n dst[11] = v2 * m[2 * 4 + 3];\n\n if (m !== dst) {\n dst[12] = m[12];\n dst[13] = m[13];\n dst[14] = m[14];\n dst[15] = m[15];\n }\n\n return dst;\n}\n\n/**\n * Takes a 4-by-4 matrix and a vector with 3 entries,\n * interprets the vector as a point, transforms that point by the matrix, and\n * returns the result as a vector with 3 entries.\n * @param {module:twgl/m4.Mat4} m The matrix.\n * @param {module:twgl/v3.Vec3} v The point.\n * @param {module:twgl/v3.Vec3} [dst] optional vec3 to store result. If not passed a new one is created.\n * @return {module:twgl/v3.Vec3} The transformed point.\n * @memberOf module:twgl/m4\n */\nfunction transformPoint(m, v, dst) {\n dst = dst || create$1();\n const v0 = v[0];\n const v1 = v[1];\n const v2 = v[2];\n const d = v0 * m[0 * 4 + 3] + v1 * m[1 * 4 + 3] + v2 * m[2 * 4 + 3] + m[3 * 4 + 3];\n\n dst[0] = (v0 * m[0 * 4 + 0] + v1 * m[1 * 4 + 0] + v2 * m[2 * 4 + 0] + m[3 * 4 + 0]) / d;\n dst[1] = (v0 * m[0 * 4 + 1] + v1 * m[1 * 4 + 1] + v2 * m[2 * 4 + 1] + m[3 * 4 + 1]) / d;\n dst[2] = (v0 * m[0 * 4 + 2] + v1 * m[1 * 4 + 2] + v2 * m[2 * 4 + 2] + m[3 * 4 + 2]) / d;\n\n return dst;\n}\n\n/**\n * Takes a 4-by-4 matrix and a vector with 3 entries, interprets the vector as a\n * direction, transforms that direction by the matrix, and returns the result;\n * assumes the transformation of 3-dimensional space represented by the matrix\n * is parallel-preserving, i.e. any combination of rotation, scaling and\n * translation, but not a perspective distortion. Returns a vector with 3\n * entries.\n * @param {module:twgl/m4.Mat4} m The matrix.\n * @param {module:twgl/v3.Vec3} v The direction.\n * @param {module:twgl/v3.Vec3} [dst] optional Vec3 to store result. If not passed a new one is created.\n * @return {module:twgl/v3.Vec3} The transformed direction.\n * @memberOf module:twgl/m4\n */\nfunction transformDirection(m, v, dst) {\n dst = dst || create$1();\n\n const v0 = v[0];\n const v1 = v[1];\n const v2 = v[2];\n\n dst[0] = v0 * m[0 * 4 + 0] + v1 * m[1 * 4 + 0] + v2 * m[2 * 4 + 0];\n dst[1] = v0 * m[0 * 4 + 1] + v1 * m[1 * 4 + 1] + v2 * m[2 * 4 + 1];\n dst[2] = v0 * m[0 * 4 + 2] + v1 * m[1 * 4 + 2] + v2 * m[2 * 4 + 2];\n\n return dst;\n}\n\n/**\n * Takes a 4-by-4 matrix m and a vector v with 3 entries, interprets the vector\n * as a normal to a surface, and computes a vector which is normal upon\n * transforming that surface by the matrix. The effect of this function is the\n * same as transforming v (as a direction) by the inverse-transpose of m. This\n * function assumes the transformation of 3-dimensional space represented by the\n * matrix is parallel-preserving, i.e. any combination of rotation, scaling and\n * translation, but not a perspective distortion. Returns a vector with 3\n * entries.\n * @param {module:twgl/m4.Mat4} m The matrix.\n * @param {module:twgl/v3.Vec3} v The normal.\n * @param {module:twgl/v3.Vec3} [dst] The direction. If not passed a new one is created.\n * @return {module:twgl/v3.Vec3} The transformed normal.\n * @memberOf module:twgl/m4\n */\nfunction transformNormal$1(m, v, dst) {\n dst = dst || create$1();\n const mi = inverse(m);\n const v0 = v[0];\n const v1 = v[1];\n const v2 = v[2];\n\n dst[0] = v0 * mi[0 * 4 + 0] + v1 * mi[0 * 4 + 1] + v2 * mi[0 * 4 + 2];\n dst[1] = v0 * mi[1 * 4 + 0] + v1 * mi[1 * 4 + 1] + v2 * mi[1 * 4 + 2];\n dst[2] = v0 * mi[2 * 4 + 0] + v1 * mi[2 * 4 + 1] + v2 * mi[2 * 4 + 2];\n\n return dst;\n}\n\nvar m4 = /*#__PURE__*/Object.freeze({\n __proto__: null,\n axisRotate: axisRotate,\n axisRotation: axisRotation,\n copy: copy,\n create: create,\n frustum: frustum,\n getAxis: getAxis,\n getTranslation: getTranslation,\n identity: identity,\n inverse: inverse,\n lookAt: lookAt,\n multiply: multiply,\n negate: negate,\n ortho: ortho,\n perspective: perspective,\n rotateX: rotateX,\n rotateY: rotateY,\n rotateZ: rotateZ,\n rotationX: rotationX,\n rotationY: rotationY,\n rotationZ: rotationZ,\n scale: scale,\n scaling: scaling,\n setAxis: setAxis,\n setDefaultType: setDefaultType,\n setTranslation: setTranslation,\n transformDirection: transformDirection,\n transformNormal: transformNormal$1,\n transformPoint: transformPoint,\n translate: translate,\n translation: translation,\n transpose: transpose\n});\n\n/*\n * Copyright 2019 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\n/* DataType */\nconst BYTE$2 = 0x1400;\nconst UNSIGNED_BYTE$3 = 0x1401;\nconst SHORT$2 = 0x1402;\nconst UNSIGNED_SHORT$3 = 0x1403;\nconst INT$3 = 0x1404;\nconst UNSIGNED_INT$3 = 0x1405;\nconst FLOAT$3 = 0x1406;\nconst UNSIGNED_SHORT_4_4_4_4$1 = 0x8033;\nconst UNSIGNED_SHORT_5_5_5_1$1 = 0x8034;\nconst UNSIGNED_SHORT_5_6_5$1 = 0x8363;\nconst HALF_FLOAT$1 = 0x140B;\nconst UNSIGNED_INT_2_10_10_10_REV$1 = 0x8368;\nconst UNSIGNED_INT_10F_11F_11F_REV$1 = 0x8C3B;\nconst UNSIGNED_INT_5_9_9_9_REV$1 = 0x8C3E;\nconst FLOAT_32_UNSIGNED_INT_24_8_REV$1 = 0x8DAD;\nconst UNSIGNED_INT_24_8$1 = 0x84FA;\n\nconst glTypeToTypedArray = {};\n{\n const tt = glTypeToTypedArray;\n tt[BYTE$2] = Int8Array;\n tt[UNSIGNED_BYTE$3] = Uint8Array;\n tt[SHORT$2] = Int16Array;\n tt[UNSIGNED_SHORT$3] = Uint16Array;\n tt[INT$3] = Int32Array;\n tt[UNSIGNED_INT$3] = Uint32Array;\n tt[FLOAT$3] = Float32Array;\n tt[UNSIGNED_SHORT_4_4_4_4$1] = Uint16Array;\n tt[UNSIGNED_SHORT_5_5_5_1$1] = Uint16Array;\n tt[UNSIGNED_SHORT_5_6_5$1] = Uint16Array;\n tt[HALF_FLOAT$1] = Uint16Array;\n tt[UNSIGNED_INT_2_10_10_10_REV$1] = Uint32Array;\n tt[UNSIGNED_INT_10F_11F_11F_REV$1] = Uint32Array;\n tt[UNSIGNED_INT_5_9_9_9_REV$1] = Uint32Array;\n tt[FLOAT_32_UNSIGNED_INT_24_8_REV$1] = Uint32Array;\n tt[UNSIGNED_INT_24_8$1] = Uint32Array;\n}\n\n/**\n * Get the GL type for a typedArray\n * @param {ArrayBufferView} typedArray a typedArray\n * @return {number} the GL type for array. For example pass in an `Int8Array` and `gl.BYTE` will\n * be returned. Pass in a `Uint32Array` and `gl.UNSIGNED_INT` will be returned\n * @memberOf module:twgl/typedArray\n */\nfunction getGLTypeForTypedArray(typedArray) {\n if (typedArray instanceof Int8Array) { return BYTE$2; } // eslint-disable-line\n if (typedArray instanceof Uint8Array) { return UNSIGNED_BYTE$3; } // eslint-disable-line\n if (typedArray instanceof Uint8ClampedArray) { return UNSIGNED_BYTE$3; } // eslint-disable-line\n if (typedArray instanceof Int16Array) { return SHORT$2; } // eslint-disable-line\n if (typedArray instanceof Uint16Array) { return UNSIGNED_SHORT$3; } // eslint-disable-line\n if (typedArray instanceof Int32Array) { return INT$3; } // eslint-disable-line\n if (typedArray instanceof Uint32Array) { return UNSIGNED_INT$3; } // eslint-disable-line\n if (typedArray instanceof Float32Array) { return FLOAT$3; } // eslint-disable-line\n throw new Error('unsupported typed array type');\n}\n\n/**\n * Get the GL type for a typedArray type\n * @param {ArrayBufferView} typedArrayType a typedArray constructor\n * @return {number} the GL type for type. For example pass in `Int8Array` and `gl.BYTE` will\n * be returned. Pass in `Uint32Array` and `gl.UNSIGNED_INT` will be returned\n * @memberOf module:twgl/typedArray\n */\nfunction getGLTypeForTypedArrayType(typedArrayType) {\n if (typedArrayType === Int8Array) { return BYTE$2; } // eslint-disable-line\n if (typedArrayType === Uint8Array) { return UNSIGNED_BYTE$3; } // eslint-disable-line\n if (typedArrayType === Uint8ClampedArray) { return UNSIGNED_BYTE$3; } // eslint-disable-line\n if (typedArrayType === Int16Array) { return SHORT$2; } // eslint-disable-line\n if (typedArrayType === Uint16Array) { return UNSIGNED_SHORT$3; } // eslint-disable-line\n if (typedArrayType === Int32Array) { return INT$3; } // eslint-disable-line\n if (typedArrayType === Uint32Array) { return UNSIGNED_INT$3; } // eslint-disable-line\n if (typedArrayType === Float32Array) { return FLOAT$3; } // eslint-disable-line\n throw new Error('unsupported typed array type');\n}\n\n/**\n * Get the typed array constructor for a given GL type\n * @param {number} type the GL type. (eg: `gl.UNSIGNED_INT`)\n * @return {function} the constructor for a the corresponding typed array. (eg. `Uint32Array`).\n * @memberOf module:twgl/typedArray\n */\nfunction getTypedArrayTypeForGLType(type) {\n const CTOR = glTypeToTypedArray[type];\n if (!CTOR) {\n throw new Error('unknown gl type');\n }\n return CTOR;\n}\n\nconst isArrayBuffer$1 = typeof SharedArrayBuffer !== 'undefined'\n ? function isArrayBufferOrSharedArrayBuffer(a) {\n return a && a.buffer && (a.buffer instanceof ArrayBuffer || a.buffer instanceof SharedArrayBuffer);\n }\n : function isArrayBuffer(a) {\n return a && a.buffer && a.buffer instanceof ArrayBuffer;\n };\n\nvar typedarrays = /*#__PURE__*/Object.freeze({\n __proto__: null,\n getGLTypeForTypedArray: getGLTypeForTypedArray,\n getGLTypeForTypedArrayType: getGLTypeForTypedArrayType,\n getTypedArrayTypeForGLType: getTypedArrayTypeForGLType,\n isArrayBuffer: isArrayBuffer$1\n});\n\n/*\n * Copyright 2019 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\n/* eslint no-console: \"off\" */\n\n/**\n * Copy named properties\n *\n * @param {string[]} names names of properties to copy\n * @param {object} src object to copy properties from\n * @param {object} dst object to copy properties to\n * @private\n */\nfunction copyNamedProperties(names, src, dst) {\n names.forEach(function(name) {\n const value = src[name];\n if (value !== undefined) {\n dst[name] = value;\n }\n });\n}\n\n/**\n * Copies properties from source to dest only if a matching key is in dest\n *\n * @param {Object.} src the source\n * @param {Object.} dst the dest\n * @private\n */\nfunction copyExistingProperties(src, dst) {\n Object.keys(dst).forEach(function(key) {\n if (dst.hasOwnProperty(key) && src.hasOwnProperty(key)) { /* eslint no-prototype-builtins: 0 */\n dst[key] = src[key];\n }\n });\n}\n\nfunction error$1(...args) {\n console.error(...args);\n}\n\nfunction warn$1(...args) {\n console.warn(...args);\n}\n\nconst isTypeWeakMaps = new Map();\n\nfunction isType(object, type) {\n if (!object || typeof object !== 'object') {\n return false;\n }\n let weakMap = isTypeWeakMaps.get(type);\n if (!weakMap) {\n weakMap = new WeakMap();\n isTypeWeakMaps.set(type, weakMap);\n }\n let isOfType = weakMap.get(object);\n if (isOfType === undefined) {\n const s = Object.prototype.toString.call(object);\n isOfType = s.substring(8, s.length - 1) === type;\n weakMap.set(object, isOfType);\n }\n return isOfType;\n}\n\nfunction isBuffer(gl, t) {\n return typeof WebGLBuffer !== 'undefined' && isType(t, 'WebGLBuffer');\n}\n\nfunction isRenderbuffer(gl, t) {\n return typeof WebGLRenderbuffer !== 'undefined' && isType(t, 'WebGLRenderbuffer');\n}\n\nfunction isTexture(gl, t) {\n return typeof WebGLTexture !== 'undefined' && isType(t, 'WebGLTexture');\n}\n\nfunction isSampler(gl, t) {\n return typeof WebGLSampler !== 'undefined' && isType(t, 'WebGLSampler');\n}\n\n/*\n * Copyright 2019 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\nconst STATIC_DRAW = 0x88e4;\nconst ARRAY_BUFFER$1 = 0x8892;\nconst ELEMENT_ARRAY_BUFFER$2 = 0x8893;\nconst BUFFER_SIZE = 0x8764;\n\nconst BYTE$1 = 0x1400;\nconst UNSIGNED_BYTE$2 = 0x1401;\nconst SHORT$1 = 0x1402;\nconst UNSIGNED_SHORT$2 = 0x1403;\nconst INT$2 = 0x1404;\nconst UNSIGNED_INT$2 = 0x1405;\nconst FLOAT$2 = 0x1406;\nconst defaults$2 = {\n attribPrefix: \"\",\n};\n\n/**\n * Sets the default attrib prefix\n *\n * When writing shaders I prefer to name attributes with `a_`, uniforms with `u_` and varyings with `v_`\n * as it makes it clear where they came from. But, when building geometry I prefer using un-prefixed names.\n *\n * In other words I'll create arrays of geometry like this\n *\n * var arrays = {\n * position: ...\n * normal: ...\n * texcoord: ...\n * };\n *\n * But need those mapped to attributes and my attributes start with `a_`.\n *\n * @deprecated see {@link module:twgl.setDefaults}\n * @param {string} prefix prefix for attribs\n * @memberOf module:twgl/attributes\n */\nfunction setAttributePrefix(prefix) {\n defaults$2.attribPrefix = prefix;\n}\n\nfunction setDefaults$2(newDefaults) {\n copyExistingProperties(newDefaults, defaults$2);\n}\n\nfunction setBufferFromTypedArray(gl, type, buffer, array, drawType) {\n gl.bindBuffer(type, buffer);\n gl.bufferData(type, array, drawType || STATIC_DRAW);\n}\n\n/**\n * Given typed array creates a WebGLBuffer and copies the typed array\n * into it.\n *\n * @param {WebGLRenderingContext} gl A WebGLRenderingContext\n * @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\n * @param {number} [type] the GL bind type for the buffer. Default = `gl.ARRAY_BUFFER`.\n * @param {number} [drawType] the GL draw type for the buffer. Default = 'gl.STATIC_DRAW`.\n * @return {WebGLBuffer} the created WebGLBuffer\n * @memberOf module:twgl/attributes\n */\nfunction createBufferFromTypedArray(gl, typedArray, type, drawType) {\n if (isBuffer(gl, typedArray)) {\n return typedArray;\n }\n type = type || ARRAY_BUFFER$1;\n const buffer = gl.createBuffer();\n setBufferFromTypedArray(gl, type, buffer, typedArray, drawType);\n return buffer;\n}\n\nfunction isIndices(name) {\n return name === \"indices\";\n}\n\n// This is really just a guess. Though I can't really imagine using\n// anything else? Maybe for some compression?\nfunction getNormalizationForTypedArrayType(typedArrayType) {\n if (typedArrayType === Int8Array) { return true; } // eslint-disable-line\n if (typedArrayType === Uint8Array) { return true; } // eslint-disable-line\n return false;\n}\n\nfunction getArray$1(array) {\n return array.length ? array : array.data;\n}\n\nconst texcoordRE = /coord|texture/i;\nconst colorRE = /color|colour/i;\n\nfunction guessNumComponentsFromName(name, length) {\n let numComponents;\n if (texcoordRE.test(name)) {\n numComponents = 2;\n } else if (colorRE.test(name)) {\n numComponents = 4;\n } else {\n numComponents = 3; // position, normals, indices ...\n }\n\n if (length % numComponents > 0) {\n 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.`);\n }\n\n return numComponents;\n}\n\nfunction getNumComponents$1(array, arrayName, numValues) {\n return array.numComponents || array.size || guessNumComponentsFromName(arrayName, numValues || getArray$1(array).length);\n}\n\nfunction makeTypedArray(array, name) {\n if (isArrayBuffer$1(array)) {\n return array;\n }\n\n if (isArrayBuffer$1(array.data)) {\n return array.data;\n }\n\n if (Array.isArray(array)) {\n array = {\n data: array,\n };\n }\n\n let Type = array.type ? typedArrayTypeFromGLTypeOrTypedArrayCtor(array.type) : undefined;\n if (!Type) {\n if (isIndices(name)) {\n Type = Uint16Array;\n } else {\n Type = Float32Array;\n }\n }\n return new Type(array.data);\n}\n\nfunction glTypeFromGLTypeOrTypedArrayType(glTypeOrTypedArrayCtor) {\n return typeof glTypeOrTypedArrayCtor === 'number'\n ? glTypeOrTypedArrayCtor\n : glTypeOrTypedArrayCtor ? getGLTypeForTypedArrayType(glTypeOrTypedArrayCtor) : FLOAT$2;\n}\n\nfunction typedArrayTypeFromGLTypeOrTypedArrayCtor(glTypeOrTypedArrayCtor) {\n return typeof glTypeOrTypedArrayCtor === 'number'\n ? getTypedArrayTypeForGLType(glTypeOrTypedArrayCtor)\n : glTypeOrTypedArrayCtor || Float32Array;\n}\n\nfunction attribBufferFromBuffer(gl, array/*, arrayName */) {\n return {\n buffer: array.buffer,\n numValues: 2 * 3 * 4, // safely divided by 2, 3, 4\n type: glTypeFromGLTypeOrTypedArrayType(array.type),\n arrayType: typedArrayTypeFromGLTypeOrTypedArrayCtor(array.type),\n };\n}\n\nfunction attribBufferFromSize(gl, array/*, arrayName*/) {\n const numValues = array.data || array;\n const arrayType = typedArrayTypeFromGLTypeOrTypedArrayCtor(array.type);\n const numBytes = numValues * arrayType.BYTES_PER_ELEMENT;\n const buffer = gl.createBuffer();\n gl.bindBuffer(ARRAY_BUFFER$1, buffer);\n gl.bufferData(ARRAY_BUFFER$1, numBytes, array.drawType || STATIC_DRAW);\n return {\n buffer,\n numValues,\n type: getGLTypeForTypedArrayType(arrayType),\n arrayType,\n };\n}\n\nfunction attribBufferFromArrayLike(gl, array, arrayName) {\n const typedArray = makeTypedArray(array, arrayName);\n return {\n arrayType: typedArray.constructor,\n buffer: createBufferFromTypedArray(gl, typedArray, undefined, array.drawType),\n type: getGLTypeForTypedArray(typedArray),\n numValues: 0,\n };\n}\n\n/**\n * The info for an attribute. This is effectively just the arguments to `gl.vertexAttribPointer` plus the WebGLBuffer\n * for the attribute.\n *\n * @typedef {Object} AttribInfo\n * @property {number[]|ArrayBufferView} [value] a constant value for the attribute. Note: if this is set the attribute will be\n * disabled and set to this constant value and all other values will be ignored.\n * @property {number} [numComponents] the number of components for this attribute.\n * @property {number} [size] synonym for `numComponents`.\n * @property {number} [type] the type of the attribute (eg. `gl.FLOAT`, `gl.UNSIGNED_BYTE`, etc...) Default = `gl.FLOAT`\n * @property {boolean} [normalize] whether or not to normalize the data. Default = false\n * @property {number} [offset] offset into buffer in bytes. Default = 0\n * @property {number} [stride] the stride in bytes per element. Default = 0\n * @property {number} [divisor] the divisor in instances. Default = 0.\n * Requires WebGL2 or the ANGLE_instanced_arrays extension.\n * and, if you're using WebGL1 you must have called {@link module:twgl.addExtensionsToContext}\n * @property {WebGLBuffer} buffer the buffer that contains the data for this attribute\n * @property {number} [drawType] the draw type passed to gl.bufferData. Default = gl.STATIC_DRAW\n * @memberOf module:twgl\n */\n\n/**\n * @typedef {(Int8ArrayConstructor|Uint8ArrayConstructor|Int16ArrayConstructor|Uint16ArrayConstructor|Int32ArrayConstructor|Uint32ArrayConstructor|Float32ArrayConstructor)} TypedArrayConstructor\n */\n\n/**\n * Use this type of array spec when TWGL can't guess the type or number of components of an array\n * @typedef {Object} FullArraySpec\n * @property {number[]|ArrayBufferView} [value] a constant value for the attribute. Note: if this is set the attribute will be\n * disabled and set to this constant value and all other values will be ignored.\n * @property {(number|number[]|ArrayBufferView)} [data] The data of the array. A number alone becomes the number of elements of type.\n * @property {number} [numComponents] number of components for `vertexAttribPointer`. Default is based on the name of the array.\n * If `coord` is in the name assumes `numComponents = 2`.\n * If `color` is in the name assumes `numComponents = 4`.\n * otherwise assumes `numComponents = 3`\n * @property {number|TypedArrayConstructor} [type] type. This is used if `data` is a JavaScript array, or `buffer` is passed in, or `data` is a number.\n * It can either be the constructor for a typedarray. (eg. `Uint8Array`) OR a WebGL type, (eg `gl.UNSIGNED_BYTE`).\n * For example if you want colors in a `Uint8Array` you might have a `FullArraySpec` like `{ type: gl.UNSIGNED_BYTE, data: [255,0,255,255, ...], }`.\n * @property {number} [size] synonym for `numComponents`.\n * @property {boolean} [normalize] normalize for `vertexAttribPointer`. Default is true if type is `Int8Array` or `Uint8Array` otherwise false.\n * @property {number} [stride] stride for `vertexAttribPointer`. Default = 0\n * @property {number} [offset] offset for `vertexAttribPointer`. Default = 0\n * @property {number} [divisor] divisor for `vertexAttribDivisor`. Default = 0.\n * Requires WebGL2 or the ANGLE_instanced_arrays extension.\n * and, if you using WebGL1 you must have called {@link module:twgl.addExtensionsToContext}\n * @property {string} [attrib] name of attribute this array maps to. Defaults to same name as array prefixed by the default attribPrefix.\n * @property {string} [name] synonym for `attrib`.\n * @property {string} [attribName] synonym for `attrib`.\n * @property {WebGLBuffer} [buffer] Buffer to use for this attribute. This lets you use your own buffer\n * but you will need to supply `numComponents` and `type`. You can effectively pass an `AttribInfo`\n * to provide this. Example:\n *\n * const bufferInfo1 = twgl.createBufferInfoFromArrays(gl, {\n * position: [1, 2, 3, ... ],\n * });\n * const bufferInfo2 = twgl.createBufferInfoFromArrays(gl, {\n * position: bufferInfo1.attribs.position, // use the same buffer from bufferInfo1\n * });\n *\n * @property {number} [drawType] the draw type passed to gl.bufferData. Default = gl.STATIC_DRAW\n * @memberOf module:twgl\n */\n\n/**\n * An individual array in {@link module:twgl.Arrays}\n *\n * When passed to {@link module:twgl.createBufferInfoFromArrays} if an ArraySpec is `number[]` or `ArrayBufferView`\n * the types will be guessed based on the name. `indices` will be `Uint16Array`, everything else will\n * be `Float32Array`. If an ArraySpec is a number it's the number of floats for an empty (zeroed) buffer.\n *\n * @typedef {(number|number[]|ArrayBufferView|module:twgl.FullArraySpec)} ArraySpec\n * @memberOf module:twgl\n */\n\n/**\n * This is a JavaScript object of arrays by name. The names should match your shader's attributes. If your\n * attributes have a common prefix you can specify it by calling {@link module:twgl.setAttributePrefix}.\n *\n * Bare JavaScript Arrays\n *\n * var arrays = {\n * position: [-1, 1, 0],\n * normal: [0, 1, 0],\n * ...\n * }\n *\n * Bare TypedArrays\n *\n * var arrays = {\n * position: new Float32Array([-1, 1, 0]),\n * color: new Uint8Array([255, 128, 64, 255]),\n * ...\n * }\n *\n * * Will guess at `numComponents` if not specified based on name.\n *\n * If `coord` is in the name assumes `numComponents = 2`\n *\n * If `color` is in the name assumes `numComponents = 4`\n *\n * otherwise assumes `numComponents = 3`\n *\n * Objects with various fields. See {@link module:twgl.FullArraySpec}.\n *\n * var arrays = {\n * position: { numComponents: 3, data: [0, 0, 0, 10, 0, 0, 0, 10, 0, 10, 10, 0], },\n * texcoord: { numComponents: 2, data: [0, 0, 0, 1, 1, 0, 1, 1], },\n * normal: { numComponents: 3, data: [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1], },\n * indices: { numComponents: 3, data: [0, 1, 2, 1, 2, 3], },\n * };\n *\n * @typedef {Object.} Arrays\n * @memberOf module:twgl\n */\n\n\n/**\n * Creates a set of attribute data and WebGLBuffers from set of arrays\n *\n * Given\n *\n * var arrays = {\n * position: { numComponents: 3, data: [0, 0, 0, 10, 0, 0, 0, 10, 0, 10, 10, 0], },\n * texcoord: { numComponents: 2, data: [0, 0, 0, 1, 1, 0, 1, 1], },\n * normal: { numComponents: 3, data: [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1], },\n * color: { numComponents: 4, data: [255, 255, 255, 255, 255, 0, 0, 255, 0, 0, 255, 255], type: Uint8Array, },\n * indices: { numComponents: 3, data: [0, 1, 2, 1, 2, 3], },\n * };\n *\n * returns something like\n *\n * var attribs = {\n * position: { numComponents: 3, type: gl.FLOAT, normalize: false, buffer: WebGLBuffer, },\n * texcoord: { numComponents: 2, type: gl.FLOAT, normalize: false, buffer: WebGLBuffer, },\n * normal: { numComponents: 3, type: gl.FLOAT, normalize: false, buffer: WebGLBuffer, },\n * color: { numComponents: 4, type: gl.UNSIGNED_BYTE, normalize: true, buffer: WebGLBuffer, },\n * };\n *\n * notes:\n *\n * * Arrays can take various forms\n *\n * Bare JavaScript Arrays\n *\n * var arrays = {\n * position: [-1, 1, 0],\n * normal: [0, 1, 0],\n * ...\n * }\n *\n * Bare TypedArrays\n *\n * var arrays = {\n * position: new Float32Array([-1, 1, 0]),\n * color: new Uint8Array([255, 128, 64, 255]),\n * ...\n * }\n *\n * * Will guess at `numComponents` if not specified based on name.\n *\n * If `coord` is in the name assumes `numComponents = 2`\n *\n * If `color` is in the name assumes `numComponents = 4`\n *\n * otherwise assumes `numComponents = 3`\n *\n * @param {WebGLRenderingContext} gl The webgl rendering context.\n * @param {module:twgl.Arrays} arrays The arrays\n * @param {module:twgl.BufferInfo} [srcBufferInfo] a BufferInfo to copy from\n * This lets you share buffers. Any arrays you supply will override\n * the buffers from srcBufferInfo.\n * @return {Object.} the attribs\n * @memberOf module:twgl/attributes\n */\nfunction createAttribsFromArrays(gl, arrays) {\n const attribs = {};\n Object.keys(arrays).forEach(function(arrayName) {\n if (!isIndices(arrayName)) {\n const array = arrays[arrayName];\n const attribName = array.attrib || array.name || array.attribName || (defaults$2.attribPrefix + arrayName);\n if (array.value) {\n if (!Array.isArray(array.value) && !isArrayBuffer$1(array.value)) {\n throw new Error('array.value is not array or typedarray');\n }\n attribs[attribName] = {\n value: array.value,\n };\n } else {\n let fn;\n if (array.buffer && array.buffer instanceof WebGLBuffer) {\n fn = attribBufferFromBuffer;\n } else if (typeof array === \"number\" || typeof array.data === \"number\") {\n fn = attribBufferFromSize;\n } else {\n fn = attribBufferFromArrayLike;\n }\n const {buffer, type, numValues, arrayType} = fn(gl, array, arrayName);\n const normalization = array.normalize !== undefined ? array.normalize : getNormalizationForTypedArrayType(arrayType);\n const numComponents = getNumComponents$1(array, arrayName, numValues);\n attribs[attribName] = {\n buffer: buffer,\n numComponents: numComponents,\n type: type,\n normalize: normalization,\n stride: array.stride || 0,\n offset: array.offset || 0,\n divisor: array.divisor === undefined ? undefined : array.divisor,\n drawType: array.drawType,\n };\n }\n }\n });\n gl.bindBuffer(ARRAY_BUFFER$1, null);\n return attribs;\n}\n\n/**\n * Sets the contents of a buffer attached to an attribInfo\n *\n * This is helper function to dynamically update a buffer.\n *\n * Let's say you make a bufferInfo\n *\n * var arrays = {\n * position: new Float32Array([0, 0, 0, 10, 0, 0, 0, 10, 0, 10, 10, 0]),\n * texcoord: new Float32Array([0, 0, 0, 1, 1, 0, 1, 1]),\n * normal: new Float32Array([0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1]),\n * indices: new Uint16Array([0, 1, 2, 1, 2, 3]),\n * };\n * var bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);\n *\n * And you want to dynamically update the positions. You could do this\n *\n * // assuming arrays.position has already been updated with new data.\n * twgl.setAttribInfoBufferFromArray(gl, bufferInfo.attribs.position, arrays.position);\n *\n * @param {WebGLRenderingContext} gl\n * @param {AttribInfo} attribInfo The attribInfo who's buffer contents to set. NOTE: If you have an attribute prefix\n * the name of the attribute will include the prefix.\n * @param {ArraySpec} array Note: it is arguably inefficient to pass in anything but a typed array because anything\n * else will have to be converted to a typed array before it can be used by WebGL. During init time that\n * inefficiency is usually not important but if you're updating data dynamically best to be efficient.\n * @param {number} [offset] an optional offset into the buffer. This is only an offset into the WebGL buffer\n * not the array. To pass in an offset into the array itself use a typed array and create an `ArrayBufferView`\n * for the portion of the array you want to use.\n *\n * var someArray = new Float32Array(1000); // an array with 1000 floats\n * var someSubArray = new Float32Array(someArray.buffer, offsetInBytes, sizeInUnits); // a view into someArray\n *\n * Now you can pass `someSubArray` into setAttribInfoBufferFromArray`\n * @memberOf module:twgl/attributes\n */\nfunction setAttribInfoBufferFromArray(gl, attribInfo, array, offset) {\n array = makeTypedArray(array);\n if (offset !== undefined) {\n gl.bindBuffer(ARRAY_BUFFER$1, attribInfo.buffer);\n gl.bufferSubData(ARRAY_BUFFER$1, offset, array);\n } else {\n setBufferFromTypedArray(gl, ARRAY_BUFFER$1, attribInfo.buffer, array, attribInfo.drawType);\n }\n}\n\nfunction getBytesPerValueForGLType(gl, type) {\n if (type === BYTE$1) return 1; // eslint-disable-line\n if (type === UNSIGNED_BYTE$2) return 1; // eslint-disable-line\n if (type === SHORT$1) return 2; // eslint-disable-line\n if (type === UNSIGNED_SHORT$2) return 2; // eslint-disable-line\n if (type === INT$2) return 4; // eslint-disable-line\n if (type === UNSIGNED_INT$2) return 4; // eslint-disable-line\n if (type === FLOAT$2) return 4; // eslint-disable-line\n return 0;\n}\n\n// Tries to get the number of elements from a set of arrays.\nconst positionKeys = ['position', 'positions', 'a_position'];\nfunction getNumElementsFromNonIndexedArrays(arrays) {\n let key;\n let ii;\n for (ii = 0; ii < positionKeys.length; ++ii) {\n key = positionKeys[ii];\n if (key in arrays) {\n break;\n }\n }\n if (ii === positionKeys.length) {\n key = Object.keys(arrays)[0];\n }\n const array = arrays[key];\n const length = getArray$1(array).length;\n if (length === undefined) {\n return 1; // There's no arrays\n }\n const numComponents = getNumComponents$1(array, key);\n const numElements = length / numComponents;\n if (length % numComponents > 0) {\n throw new Error(`numComponents ${numComponents} not correct for length ${length}`);\n }\n return numElements;\n}\n\nfunction getNumElementsFromAttributes(gl, attribs) {\n let key;\n let ii;\n for (ii = 0; ii < positionKeys.length; ++ii) {\n key = positionKeys[ii];\n if (key in attribs) {\n break;\n }\n key = defaults$2.attribPrefix + key;\n if (key in attribs) {\n break;\n }\n }\n if (ii === positionKeys.length) {\n key = Object.keys(attribs)[0];\n }\n const attrib = attribs[key];\n if (!attrib.buffer) {\n return 1; // There's no buffer\n }\n gl.bindBuffer(ARRAY_BUFFER$1, attrib.buffer);\n const numBytes = gl.getBufferParameter(ARRAY_BUFFER$1, BUFFER_SIZE);\n gl.bindBuffer(ARRAY_BUFFER$1, null);\n\n const bytesPerValue = getBytesPerValueForGLType(gl, attrib.type);\n const totalElements = numBytes / bytesPerValue;\n const numComponents = attrib.numComponents || attrib.size;\n // TODO: check stride\n const numElements = totalElements / numComponents;\n if (numElements % 1 !== 0) {\n throw new Error(`numComponents ${numComponents} not correct for length ${length}`);\n }\n return numElements;\n}\n\n/**\n * @typedef {Object} BufferInfo\n * @property {number} numElements The number of elements to pass to `gl.drawArrays` or `gl.drawElements`.\n * @property {number} [elementType] The type of indices `UNSIGNED_BYTE`, `UNSIGNED_SHORT` etc..\n * @property {WebGLBuffer} [indices] The indices `ELEMENT_ARRAY_BUFFER` if any indices exist.\n * @property {Object.} [attribs] The attribs appropriate to call `setAttributes`\n * @memberOf module:twgl\n */\n\n/**\n * Creates a BufferInfo from an object of arrays.\n *\n * This can be passed to {@link module:twgl.setBuffersAndAttributes} and to\n * {@link module:twgl:drawBufferInfo}.\n *\n * Given an object like\n *\n * var arrays = {\n * position: { numComponents: 3, data: [0, 0, 0, 10, 0, 0, 0, 10, 0, 10, 10, 0], },\n * texcoord: { numComponents: 2, data: [0, 0, 0, 1, 1, 0, 1, 1], },\n * normal: { numComponents: 3, data: [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1], },\n * indices: { numComponents: 3, data: [0, 1, 2, 1, 2, 3], },\n * };\n *\n * Creates an BufferInfo like this\n *\n * bufferInfo = {\n * numElements: 4, // or whatever the number of elements is\n * indices: WebGLBuffer, // this property will not exist if there are no indices\n * attribs: {\n * position: { buffer: WebGLBuffer, numComponents: 3, },\n * normal: { buffer: WebGLBuffer, numComponents: 3, },\n * texcoord: { buffer: WebGLBuffer, numComponents: 2, },\n * },\n * };\n *\n * The properties of arrays can be JavaScript arrays in which case the number of components\n * will be guessed.\n *\n * var arrays = {\n * position: [0, 0, 0, 10, 0, 0, 0, 10, 0, 10, 10, 0],\n * texcoord: [0, 0, 0, 1, 1, 0, 1, 1],\n * normal: [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1],\n * indices: [0, 1, 2, 1, 2, 3],\n * };\n *\n * They can also be TypedArrays\n *\n * var arrays = {\n * position: new Float32Array([0, 0, 0, 10, 0, 0, 0, 10, 0, 10, 10, 0]),\n * texcoord: new Float32Array([0, 0, 0, 1, 1, 0, 1, 1]),\n * normal: new Float32Array([0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1]),\n * indices: new Uint16Array([0, 1, 2, 1, 2, 3]),\n * };\n *\n * Or AugmentedTypedArrays\n *\n * var positions = createAugmentedTypedArray(3, 4);\n * var texcoords = createAugmentedTypedArray(2, 4);\n * var normals = createAugmentedTypedArray(3, 4);\n * var indices = createAugmentedTypedArray(3, 2, Uint16Array);\n *\n * positions.push([0, 0, 0, 10, 0, 0, 0, 10, 0, 10, 10, 0]);\n * texcoords.push([0, 0, 0, 1, 1, 0, 1, 1]);\n * normals.push([0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1]);\n * indices.push([0, 1, 2, 1, 2, 3]);\n *\n * var arrays = {\n * position: positions,\n * texcoord: texcoords,\n * normal: normals,\n * indices: indices,\n * };\n *\n * For the last example it is equivalent to\n *\n * var bufferInfo = {\n * attribs: {\n * position: { numComponents: 3, buffer: gl.createBuffer(), },\n * texcoord: { numComponents: 2, buffer: gl.createBuffer(), },\n * normal: { numComponents: 3, buffer: gl.createBuffer(), },\n * },\n * indices: gl.createBuffer(),\n * numElements: 6,\n * };\n *\n * gl.bindBuffer(gl.ARRAY_BUFFER, bufferInfo.attribs.position.buffer);\n * gl.bufferData(gl.ARRAY_BUFFER, arrays.position, gl.STATIC_DRAW);\n * gl.bindBuffer(gl.ARRAY_BUFFER, bufferInfo.attribs.texcoord.buffer);\n * gl.bufferData(gl.ARRAY_BUFFER, arrays.texcoord, gl.STATIC_DRAW);\n * gl.bindBuffer(gl.ARRAY_BUFFER, bufferInfo.attribs.normal.buffer);\n * gl.bufferData(gl.ARRAY_BUFFER, arrays.normal, gl.STATIC_DRAW);\n * gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufferInfo.indices);\n * gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, arrays.indices, gl.STATIC_DRAW);\n *\n * @param {WebGLRenderingContext} gl A WebGLRenderingContext\n * @param {module:twgl.Arrays} arrays Your data\n * @param {module:twgl.BufferInfo} [srcBufferInfo] An existing\n * buffer info to start from. WebGLBuffers etc specified\n * in the srcBufferInfo will be used in a new BufferInfo\n * with any arrays specified overriding the ones in\n * srcBufferInfo.\n * @return {module:twgl.BufferInfo} A BufferInfo\n * @memberOf module:twgl/attributes\n */\nfunction createBufferInfoFromArrays(gl, arrays, srcBufferInfo) {\n const newAttribs = createAttribsFromArrays(gl, arrays);\n const bufferInfo = Object.assign({}, srcBufferInfo ? srcBufferInfo : {});\n bufferInfo.attribs = Object.assign({}, srcBufferInfo ? srcBufferInfo.attribs : {}, newAttribs);\n const indices = arrays.indices;\n if (indices) {\n const newIndices = makeTypedArray(indices, \"indices\");\n bufferInfo.indices = createBufferFromTypedArray(gl, newIndices, ELEMENT_ARRAY_BUFFER$2);\n bufferInfo.numElements = newIndices.length;\n bufferInfo.elementType = getGLTypeForTypedArray(newIndices);\n } else if (!bufferInfo.numElements) {\n bufferInfo.numElements = getNumElementsFromAttributes(gl, bufferInfo.attribs);\n }\n\n return bufferInfo;\n}\n\n/**\n * Creates a buffer from an array, typed array, or array spec\n *\n * Given something like this\n *\n * [1, 2, 3],\n *\n * or\n *\n * new Uint16Array([1,2,3]);\n *\n * or\n *\n * {\n * data: [1, 2, 3],\n * type: Uint8Array,\n * }\n *\n * returns a WebGLBuffer that contains the given data.\n *\n * @param {WebGLRenderingContext} gl A WebGLRenderingContext.\n * @param {module:twgl.ArraySpec} array an array, typed array, or array spec.\n * @param {string} arrayName name of array. Used to guess the type if type can not be derived otherwise.\n * @return {WebGLBuffer} a WebGLBuffer containing the data in array.\n * @memberOf module:twgl/attributes\n */\nfunction createBufferFromArray(gl, array, arrayName) {\n const type = arrayName === \"indices\" ? ELEMENT_ARRAY_BUFFER$2 : ARRAY_BUFFER$1;\n const typedArray = makeTypedArray(array, arrayName);\n return createBufferFromTypedArray(gl, typedArray, type);\n}\n\n/**\n * Creates buffers from arrays or typed arrays\n *\n * Given something like this\n *\n * var arrays = {\n * positions: [1, 2, 3],\n * normals: [0, 0, 1],\n * }\n *\n * returns something like\n *\n * buffers = {\n * positions: WebGLBuffer,\n * normals: WebGLBuffer,\n * }\n *\n * If the buffer is named 'indices' it will be made an ELEMENT_ARRAY_BUFFER.\n *\n * @param {WebGLRenderingContext} gl A WebGLRenderingContext.\n * @param {module:twgl.Arrays} arrays\n * @return {Object} returns an object with one WebGLBuffer per array\n * @memberOf module:twgl/attributes\n */\nfunction createBuffersFromArrays(gl, arrays) {\n const buffers = { };\n Object.keys(arrays).forEach(function(key) {\n buffers[key] = createBufferFromArray(gl, arrays[key], key);\n });\n\n // Ugh!\n if (arrays.indices) {\n buffers.numElements = arrays.indices.length;\n buffers.elementType = getGLTypeForTypedArray(makeTypedArray(arrays.indices));\n } else {\n buffers.numElements = getNumElementsFromNonIndexedArrays(arrays);\n }\n\n return buffers;\n}\n\nvar attributes = /*#__PURE__*/Object.freeze({\n __proto__: null,\n createAttribsFromArrays: createAttribsFromArrays,\n createBuffersFromArrays: createBuffersFromArrays,\n createBufferFromArray: createBufferFromArray,\n createBufferFromTypedArray: createBufferFromTypedArray,\n createBufferInfoFromArrays: createBufferInfoFromArrays,\n setAttribInfoBufferFromArray: setAttribInfoBufferFromArray,\n setAttributePrefix: setAttributePrefix,\n setAttributeDefaults_: setDefaults$2,\n getNumComponents_: getNumComponents$1,\n getArray_: getArray$1\n});\n\n/*\n * Copyright 2019 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\nconst getArray = getArray$1; // eslint-disable-line\nconst getNumComponents = getNumComponents$1; // eslint-disable-line\n\n/**\n * @typedef {(Int8Array|Uint8Array|Int16Array|Uint16Array|Int32Array|Uint32Array|Float32Array)} TypedArray\n */\n\n/**\n * Add `push` to a typed array. It just keeps a 'cursor'\n * and allows use to `push` values into the array so we\n * don't have to manually compute offsets\n * @param {TypedArray} typedArray TypedArray to augment\n * @param {number} numComponents number of components.\n * @private\n */\nfunction augmentTypedArray(typedArray, numComponents) {\n let cursor = 0;\n typedArray.push = function() {\n for (let ii = 0; ii < arguments.length; ++ii) {\n const value = arguments[ii];\n if (value instanceof Array || isArrayBuffer$1(value)) {\n for (let jj = 0; jj < value.length; ++jj) {\n typedArray[cursor++] = value[jj];\n }\n } else {\n typedArray[cursor++] = value;\n }\n }\n };\n typedArray.reset = function(opt_index) {\n cursor = opt_index || 0;\n };\n typedArray.numComponents = numComponents;\n Object.defineProperty(typedArray, 'numElements', {\n get: function() {\n return this.length / this.numComponents | 0;\n },\n });\n return typedArray;\n}\n\n/**\n * creates a typed array with a `push` function attached\n * so that you can easily *push* values.\n *\n * `push` can take multiple arguments. If an argument is an array each element\n * of the array will be added to the typed array.\n *\n * Example:\n *\n * const array = createAugmentedTypedArray(3, 2); // creates a Float32Array with 6 values\n * array.push(1, 2, 3);\n * array.push([4, 5, 6]);\n * // array now contains [1, 2, 3, 4, 5, 6]\n *\n * Also has `numComponents` and `numElements` properties.\n *\n * @param {number} numComponents number of components\n * @param {number} numElements number of elements. The total size of the array will be `numComponents * numElements`.\n * @param {constructor} opt_type A constructor for the type. Default = `Float32Array`.\n * @return {ArrayBufferView} A typed array.\n * @memberOf module:twgl/primitives\n */\nfunction createAugmentedTypedArray(numComponents, numElements, opt_type) {\n const Type = opt_type || Float32Array;\n return augmentTypedArray(new Type(numComponents * numElements), numComponents);\n}\n\nfunction allButIndices(name) {\n return name !== \"indices\";\n}\n\n/**\n * Given indexed vertices creates a new set of vertices un-indexed by expanding the indexed vertices.\n * @param {Object.} vertices The indexed vertices to deindex\n * @return {Object.} The deindexed vertices\n * @memberOf module:twgl/primitives\n */\nfunction deindexVertices(vertices) {\n const indices = vertices.indices;\n const newVertices = {};\n const numElements = indices.length;\n\n function expandToUnindexed(channel) {\n const srcBuffer = vertices[channel];\n const numComponents = srcBuffer.numComponents;\n const dstBuffer = createAugmentedTypedArray(numComponents, numElements, srcBuffer.constructor);\n for (let ii = 0; ii < numElements; ++ii) {\n const ndx = indices[ii];\n const offset = ndx * numComponents;\n for (let jj = 0; jj < numComponents; ++jj) {\n dstBuffer.push(srcBuffer[offset + jj]);\n }\n }\n newVertices[channel] = dstBuffer;\n }\n\n Object.keys(vertices).filter(allButIndices).forEach(expandToUnindexed);\n\n return newVertices;\n}\n\n/**\n * flattens the normals of deindexed vertices in place.\n * @param {Object.} vertices The deindexed vertices who's normals to flatten\n * @return {Object.} The flattened vertices (same as was passed in)\n * @memberOf module:twgl/primitives\n */\nfunction flattenNormals(vertices) {\n if (vertices.indices) {\n throw new Error('can not flatten normals of indexed vertices. deindex them first');\n }\n\n const normals = vertices.normal;\n const numNormals = normals.length;\n for (let ii = 0; ii < numNormals; ii += 9) {\n // pull out the 3 normals for this triangle\n const nax = normals[ii + 0];\n const nay = normals[ii + 1];\n const naz = normals[ii + 2];\n\n const nbx = normals[ii + 3];\n const nby = normals[ii + 4];\n const nbz = normals[ii + 5];\n\n const ncx = normals[ii + 6];\n const ncy = normals[ii + 7];\n const ncz = normals[ii + 8];\n\n // add them\n let nx = nax + nbx + ncx;\n let ny = nay + nby + ncy;\n let nz = naz + nbz + ncz;\n\n // normalize them\n const length = Math.sqrt(nx * nx + ny * ny + nz * nz);\n\n nx /= length;\n ny /= length;\n nz /= length;\n\n // copy them back in\n normals[ii + 0] = nx;\n normals[ii + 1] = ny;\n normals[ii + 2] = nz;\n\n normals[ii + 3] = nx;\n normals[ii + 4] = ny;\n normals[ii + 5] = nz;\n\n normals[ii + 6] = nx;\n normals[ii + 7] = ny;\n normals[ii + 8] = nz;\n }\n\n return vertices;\n}\n\nfunction applyFuncToV3Array(array, matrix, fn) {\n const len = array.length;\n const tmp = new Float32Array(3);\n for (let ii = 0; ii < len; ii += 3) {\n fn(matrix, [array[ii], array[ii + 1], array[ii + 2]], tmp);\n array[ii ] = tmp[0];\n array[ii + 1] = tmp[1];\n array[ii + 2] = tmp[2];\n }\n}\n\nfunction transformNormal(mi, v, dst) {\n dst = dst || create$1();\n const v0 = v[0];\n const v1 = v[1];\n const v2 = v[2];\n\n dst[0] = v0 * mi[0 * 4 + 0] + v1 * mi[0 * 4 + 1] + v2 * mi[0 * 4 + 2];\n dst[1] = v0 * mi[1 * 4 + 0] + v1 * mi[1 * 4 + 1] + v2 * mi[1 * 4 + 2];\n dst[2] = v0 * mi[2 * 4 + 0] + v1 * mi[2 * 4 + 1] + v2 * mi[2 * 4 + 2];\n\n return dst;\n}\n\n/**\n * Reorients directions by the given matrix..\n * @param {(number[]|TypedArray)} array The array. Assumes value floats per element.\n * @param {module:twgl/m4.Mat4} matrix A matrix to multiply by.\n * @return {(number[]|TypedArray)} the same array that was passed in\n * @memberOf module:twgl/primitives\n */\nfunction reorientDirections(array, matrix) {\n applyFuncToV3Array(array, matrix, transformDirection);\n return array;\n}\n\n/**\n * Reorients normals by the inverse-transpose of the given\n * matrix..\n * @param {(number[]|TypedArray)} array The array. Assumes value floats per element.\n * @param {module:twgl/m4.Mat4} matrix A matrix to multiply by.\n * @return {(number[]|TypedArray)} the same array that was passed in\n * @memberOf module:twgl/primitives\n */\nfunction reorientNormals(array, matrix) {\n applyFuncToV3Array(array, inverse(matrix), transformNormal);\n return array;\n}\n\n/**\n * Reorients positions by the given matrix. In other words, it\n * multiplies each vertex by the given matrix.\n * @param {(number[]|TypedArray)} array The array. Assumes value floats per element.\n * @param {module:twgl/m4.Mat4} matrix A matrix to multiply by.\n * @return {(number[]|TypedArray)} the same array that was passed in\n * @memberOf module:twgl/primitives\n */\nfunction reorientPositions(array, matrix) {\n applyFuncToV3Array(array, matrix, transformPoint);\n return array;\n}\n\n/**\n * @typedef {(number[]|TypedArray)} NativeArrayOrTypedArray\n */\n\n/**\n * Reorients arrays by the given matrix. Assumes arrays have\n * names that contains 'pos' could be reoriented as positions,\n * 'binorm' or 'tan' as directions, and 'norm' as normals.\n *\n * @param {Object.} arrays The vertices to reorient\n * @param {module:twgl/m4.Mat4} matrix matrix to reorient by.\n * @return {Object.} same arrays that were passed in.\n * @memberOf module:twgl/primitives\n */\nfunction reorientVertices(arrays, matrix) {\n Object.keys(arrays).forEach(function(name) {\n const array = arrays[name];\n if (name.indexOf(\"pos\") >= 0) {\n reorientPositions(array, matrix);\n } else if (name.indexOf(\"tan\") >= 0 || name.indexOf(\"binorm\") >= 0) {\n reorientDirections(array, matrix);\n } else if (name.indexOf(\"norm\") >= 0) {\n reorientNormals(array, matrix);\n }\n });\n return arrays;\n}\n\n/**\n * Creates XY quad BufferInfo\n *\n * The default with no parameters will return a 2x2 quad with values from -1 to +1.\n * If you want a unit quad with that goes from 0 to 1 you'd call it with\n *\n * twgl.primitives.createXYQuadBufferInfo(gl, 1, 0.5, 0.5);\n *\n * If you want a unit quad centered above 0,0 you'd call it with\n *\n * twgl.primitives.createXYQuadBufferInfo(gl, 1, 0, 0.5);\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} [size] the size across the quad. Defaults to 2 which means vertices will go from -1 to +1\n * @param {number} [xOffset] the amount to offset the quad in X\n * @param {number} [yOffset] the amount to offset the quad in Y\n * @return {Object.} the created XY Quad BufferInfo\n * @memberOf module:twgl/primitives\n * @function createXYQuadBuffers\n */\n\n/**\n * Creates XY quad Buffers\n *\n * The default with no parameters will return a 2x2 quad with values from -1 to +1.\n * If you want a unit quad with that goes from 0 to 1 you'd call it with\n *\n * twgl.primitives.createXYQuadBufferInfo(gl, 1, 0.5, 0.5);\n *\n * If you want a unit quad centered above 0,0 you'd call it with\n *\n * twgl.primitives.createXYQuadBufferInfo(gl, 1, 0, 0.5);\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} [size] the size across the quad. Defaults to 2 which means vertices will go from -1 to +1\n * @param {number} [xOffset] the amount to offset the quad in X\n * @param {number} [yOffset] the amount to offset the quad in Y\n * @return {module:twgl.BufferInfo} the created XY Quad buffers\n * @memberOf module:twgl/primitives\n * @function createXYQuadBufferInfo\n */\n\n/**\n * Creates XY quad vertices\n *\n * The default with no parameters will return a 2x2 quad with values from -1 to +1.\n * If you want a unit quad with that goes from 0 to 1 you'd call it with\n *\n * twgl.primitives.createXYQuadVertices(1, 0.5, 0.5);\n *\n * If you want a unit quad centered above 0,0 you'd call it with\n *\n * twgl.primitives.createXYQuadVertices(1, 0, 0.5);\n *\n * @param {number} [size] the size across the quad. Defaults to 2 which means vertices will go from -1 to +1\n * @param {number} [xOffset] the amount to offset the quad in X\n * @param {number} [yOffset] the amount to offset the quad in Y\n * @return {Object.} the created XY Quad vertices\n * @memberOf module:twgl/primitives\n */\nfunction createXYQuadVertices(size, xOffset, yOffset) {\n size = size || 2;\n xOffset = xOffset || 0;\n yOffset = yOffset || 0;\n size *= 0.5;\n return {\n position: {\n numComponents: 2,\n data: [\n xOffset + -1 * size, yOffset + -1 * size,\n xOffset + 1 * size, yOffset + -1 * size,\n xOffset + -1 * size, yOffset + 1 * size,\n xOffset + 1 * size, yOffset + 1 * size,\n ],\n },\n normal: [\n 0, 0, 1,\n 0, 0, 1,\n 0, 0, 1,\n 0, 0, 1,\n ],\n texcoord: [\n 0, 0,\n 1, 0,\n 0, 1,\n 1, 1,\n ],\n indices: [ 0, 1, 2, 2, 1, 3 ],\n };\n}\n\n/**\n * Creates XZ plane BufferInfo.\n *\n * The created plane has position, normal, and texcoord data\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} [width] Width of the plane. Default = 1\n * @param {number} [depth] Depth of the plane. Default = 1\n * @param {number} [subdivisionsWidth] Number of steps across the plane. Default = 1\n * @param {number} [subdivisionsDepth] Number of steps down the plane. Default = 1\n * @param {module:twgl/m4.Mat4} [matrix] A matrix by which to multiply all the vertices.\n * @return {module:twgl.BufferInfo} The created plane BufferInfo.\n * @memberOf module:twgl/primitives\n * @function createPlaneBufferInfo\n */\n\n/**\n * Creates XZ plane buffers.\n *\n * The created plane has position, normal, and texcoord data\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} [width] Width of the plane. Default = 1\n * @param {number} [depth] Depth of the plane. Default = 1\n * @param {number} [subdivisionsWidth] Number of steps across the plane. Default = 1\n * @param {number} [subdivisionsDepth] Number of steps down the plane. Default = 1\n * @param {module:twgl/m4.Mat4} [matrix] A matrix by which to multiply all the vertices.\n * @return {Object.} The created plane buffers.\n * @memberOf module:twgl/primitives\n * @function createPlaneBuffers\n */\n\n/**\n * Creates XZ plane vertices.\n *\n * The created plane has position, normal, and texcoord data\n *\n * @param {number} [width] Width of the plane. Default = 1\n * @param {number} [depth] Depth of the plane. Default = 1\n * @param {number} [subdivisionsWidth] Number of steps across the plane. Default = 1\n * @param {number} [subdivisionsDepth] Number of steps down the plane. Default = 1\n * @param {module:twgl/m4.Mat4} [matrix] A matrix by which to multiply all the vertices.\n * @return {Object.} The created plane vertices.\n * @memberOf module:twgl/primitives\n */\nfunction createPlaneVertices(\n width,\n depth,\n subdivisionsWidth,\n subdivisionsDepth,\n matrix) {\n width = width || 1;\n depth = depth || 1;\n subdivisionsWidth = subdivisionsWidth || 1;\n subdivisionsDepth = subdivisionsDepth || 1;\n matrix = matrix || identity();\n\n const numVertices = (subdivisionsWidth + 1) * (subdivisionsDepth + 1);\n const positions = createAugmentedTypedArray(3, numVertices);\n const normals = createAugmentedTypedArray(3, numVertices);\n const texcoords = createAugmentedTypedArray(2, numVertices);\n\n for (let z = 0; z <= subdivisionsDepth; z++) {\n for (let x = 0; x <= subdivisionsWidth; x++) {\n const u = x / subdivisionsWidth;\n const v = z / subdivisionsDepth;\n positions.push(\n width * u - width * 0.5,\n 0,\n depth * v - depth * 0.5);\n normals.push(0, 1, 0);\n texcoords.push(u, v);\n }\n }\n\n const numVertsAcross = subdivisionsWidth + 1;\n const indices = createAugmentedTypedArray(\n 3, subdivisionsWidth * subdivisionsDepth * 2, Uint16Array);\n\n for (let z = 0; z < subdivisionsDepth; z++) { // eslint-disable-line\n for (let x = 0; x < subdivisionsWidth; x++) { // eslint-disable-line\n // Make triangle 1 of quad.\n indices.push(\n (z + 0) * numVertsAcross + x,\n (z + 1) * numVertsAcross + x,\n (z + 0) * numVertsAcross + x + 1);\n\n // Make triangle 2 of quad.\n indices.push(\n (z + 1) * numVertsAcross + x,\n (z + 1) * numVertsAcross + x + 1,\n (z + 0) * numVertsAcross + x + 1);\n }\n }\n\n const arrays = reorientVertices({\n position: positions,\n normal: normals,\n texcoord: texcoords,\n indices: indices,\n }, matrix);\n return arrays;\n}\n\n/**\n * Creates sphere BufferInfo.\n *\n * The created sphere has position, normal, and texcoord data\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} radius radius of the sphere.\n * @param {number} subdivisionsAxis number of steps around the sphere.\n * @param {number} subdivisionsHeight number of vertically on the sphere.\n * @param {number} [opt_startLatitudeInRadians] where to start the\n * top of the sphere. Default = 0.\n * @param {number} [opt_endLatitudeInRadians] Where to end the\n * bottom of the sphere. Default = Math.PI.\n * @param {number} [opt_startLongitudeInRadians] where to start\n * wrapping the sphere. Default = 0.\n * @param {number} [opt_endLongitudeInRadians] where to end\n * wrapping the sphere. Default = 2 * Math.PI.\n * @return {module:twgl.BufferInfo} The created sphere BufferInfo.\n * @memberOf module:twgl/primitives\n * @function createSphereBufferInfo\n */\n\n/**\n * Creates sphere buffers.\n *\n * The created sphere has position, normal, and texcoord data\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} radius radius of the sphere.\n * @param {number} subdivisionsAxis number of steps around the sphere.\n * @param {number} subdivisionsHeight number of vertically on the sphere.\n * @param {number} [opt_startLatitudeInRadians] where to start the\n * top of the sphere. Default = 0.\n * @param {number} [opt_endLatitudeInRadians] Where to end the\n * bottom of the sphere. Default = Math.PI.\n * @param {number} [opt_startLongitudeInRadians] where to start\n * wrapping the sphere. Default = 0.\n * @param {number} [opt_endLongitudeInRadians] where to end\n * wrapping the sphere. Default = 2 * Math.PI.\n * @return {Object.} The created sphere buffers.\n * @memberOf module:twgl/primitives\n * @function createSphereBuffers\n */\n\n/**\n * Creates sphere vertices.\n *\n * The created sphere has position, normal, and texcoord data\n *\n * @param {number} radius radius of the sphere.\n * @param {number} subdivisionsAxis number of steps around the sphere.\n * @param {number} subdivisionsHeight number of vertically on the sphere.\n * @param {number} [opt_startLatitudeInRadians] where to start the\n * top of the sphere. Default = 0.\n * @param {number} [opt_endLatitudeInRadians] Where to end the\n * bottom of the sphere. Default = Math.PI.\n * @param {number} [opt_startLongitudeInRadians] where to start\n * wrapping the sphere. Default = 0.\n * @param {number} [opt_endLongitudeInRadians] where to end\n * wrapping the sphere. Default = 2 * Math.PI.\n * @return {Object.} The created sphere vertices.\n * @memberOf module:twgl/primitives\n */\nfunction createSphereVertices(\n radius,\n subdivisionsAxis,\n subdivisionsHeight,\n opt_startLatitudeInRadians,\n opt_endLatitudeInRadians,\n opt_startLongitudeInRadians,\n opt_endLongitudeInRadians) {\n if (subdivisionsAxis <= 0 || subdivisionsHeight <= 0) {\n throw new Error('subdivisionAxis and subdivisionHeight must be > 0');\n }\n\n opt_startLatitudeInRadians = opt_startLatitudeInRadians || 0;\n opt_endLatitudeInRadians = opt_endLatitudeInRadians || Math.PI;\n opt_startLongitudeInRadians = opt_startLongitudeInRadians || 0;\n opt_endLongitudeInRadians = opt_endLongitudeInRadians || (Math.PI * 2);\n\n const latRange = opt_endLatitudeInRadians - opt_startLatitudeInRadians;\n const longRange = opt_endLongitudeInRadians - opt_startLongitudeInRadians;\n\n // We are going to generate our sphere by iterating through its\n // spherical coordinates and generating 2 triangles for each quad on a\n // ring of the sphere.\n const numVertices = (subdivisionsAxis + 1) * (subdivisionsHeight + 1);\n const positions = createAugmentedTypedArray(3, numVertices);\n const normals = createAugmentedTypedArray(3, numVertices);\n const texcoords = createAugmentedTypedArray(2, numVertices);\n\n // Generate the individual vertices in our vertex buffer.\n for (let y = 0; y <= subdivisionsHeight; y++) {\n for (let x = 0; x <= subdivisionsAxis; x++) {\n // Generate a vertex based on its spherical coordinates\n const u = x / subdivisionsAxis;\n const v = y / subdivisionsHeight;\n const theta = longRange * u + opt_startLongitudeInRadians;\n const phi = latRange * v + opt_startLatitudeInRadians;\n const sinTheta = Math.sin(theta);\n const cosTheta = Math.cos(theta);\n const sinPhi = Math.sin(phi);\n const cosPhi = Math.cos(phi);\n const ux = cosTheta * sinPhi;\n const uy = cosPhi;\n const uz = sinTheta * sinPhi;\n positions.push(radius * ux, radius * uy, radius * uz);\n normals.push(ux, uy, uz);\n texcoords.push(1 - u, v);\n }\n }\n\n const numVertsAround = subdivisionsAxis + 1;\n const indices = createAugmentedTypedArray(3, subdivisionsAxis * subdivisionsHeight * 2, Uint16Array);\n for (let x = 0; x < subdivisionsAxis; x++) { // eslint-disable-line\n for (let y = 0; y < subdivisionsHeight; y++) { // eslint-disable-line\n // Make triangle 1 of quad.\n indices.push(\n (y + 0) * numVertsAround + x,\n (y + 0) * numVertsAround + x + 1,\n (y + 1) * numVertsAround + x);\n\n // Make triangle 2 of quad.\n indices.push(\n (y + 1) * numVertsAround + x,\n (y + 0) * numVertsAround + x + 1,\n (y + 1) * numVertsAround + x + 1);\n }\n }\n\n return {\n position: positions,\n normal: normals,\n texcoord: texcoords,\n indices: indices,\n };\n}\n\n/**\n * Array of the indices of corners of each face of a cube.\n * @type {Array.}\n * @private\n */\nconst CUBE_FACE_INDICES = [\n [3, 7, 5, 1], // right\n [6, 2, 0, 4], // left\n [6, 7, 3, 2], // ??\n [0, 1, 5, 4], // ??\n [7, 6, 4, 5], // front\n [2, 3, 1, 0], // back\n];\n\n/**\n * Creates a BufferInfo for a cube.\n *\n * The cube is created around the origin. (-size / 2, size / 2).\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} [size] width, height and depth of the cube.\n * @return {module:twgl.BufferInfo} The created BufferInfo.\n * @memberOf module:twgl/primitives\n * @function createCubeBufferInfo\n */\n\n/**\n * Creates the buffers and indices for a cube.\n *\n * The cube is created around the origin. (-size / 2, size / 2).\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} [size] width, height and depth of the cube.\n * @return {Object.} The created buffers.\n * @memberOf module:twgl/primitives\n * @function createCubeBuffers\n */\n\n/**\n * Creates the vertices and indices for a cube.\n *\n * The cube is created around the origin. (-size / 2, size / 2).\n *\n * @param {number} [size] width, height and depth of the cube.\n * @return {Object.} The created vertices.\n * @memberOf module:twgl/primitives\n */\nfunction createCubeVertices(size) {\n size = size || 1;\n const k = size / 2;\n\n const cornerVertices = [\n [-k, -k, -k],\n [+k, -k, -k],\n [-k, +k, -k],\n [+k, +k, -k],\n [-k, -k, +k],\n [+k, -k, +k],\n [-k, +k, +k],\n [+k, +k, +k],\n ];\n\n const faceNormals = [\n [+1, +0, +0],\n [-1, +0, +0],\n [+0, +1, +0],\n [+0, -1, +0],\n [+0, +0, +1],\n [+0, +0, -1],\n ];\n\n const uvCoords = [\n [1, 0],\n [0, 0],\n [0, 1],\n [1, 1],\n ];\n\n const numVertices = 6 * 4;\n const positions = createAugmentedTypedArray(3, numVertices);\n const normals = createAugmentedTypedArray(3, numVertices);\n const texcoords = createAugmentedTypedArray(2 , numVertices);\n const indices = createAugmentedTypedArray(3, 6 * 2, Uint16Array);\n\n for (let f = 0; f < 6; ++f) {\n const faceIndices = CUBE_FACE_INDICES[f];\n for (let v = 0; v < 4; ++v) {\n const position = cornerVertices[faceIndices[v]];\n const normal = faceNormals[f];\n const uv = uvCoords[v];\n\n // Each face needs all four vertices because the normals and texture\n // coordinates are not all the same.\n positions.push(position);\n normals.push(normal);\n texcoords.push(uv);\n\n }\n // Two triangles make a square face.\n const offset = 4 * f;\n indices.push(offset + 0, offset + 1, offset + 2);\n indices.push(offset + 0, offset + 2, offset + 3);\n }\n\n return {\n position: positions,\n normal: normals,\n texcoord: texcoords,\n indices: indices,\n };\n}\n\n/**\n * Creates a BufferInfo for a truncated cone, which is like a cylinder\n * except that it has different top and bottom radii. A truncated cone\n * can also be used to create cylinders and regular cones. The\n * truncated cone will be created centered about the origin, with the\n * y axis as its vertical axis.\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} bottomRadius Bottom radius of truncated cone.\n * @param {number} topRadius Top radius of truncated cone.\n * @param {number} height Height of truncated cone.\n * @param {number} radialSubdivisions The number of subdivisions around the\n * truncated cone.\n * @param {number} verticalSubdivisions The number of subdivisions down the\n * truncated cone.\n * @param {boolean} [opt_topCap] Create top cap. Default = true.\n * @param {boolean} [opt_bottomCap] Create bottom cap. Default = true.\n * @return {module:twgl.BufferInfo} The created cone BufferInfo.\n * @memberOf module:twgl/primitives\n * @function createTruncatedConeBufferInfo\n */\n\n/**\n * Creates buffers for a truncated cone, which is like a cylinder\n * except that it has different top and bottom radii. A truncated cone\n * can also be used to create cylinders and regular cones. The\n * truncated cone will be created centered about the origin, with the\n * y axis as its vertical axis.\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} bottomRadius Bottom radius of truncated cone.\n * @param {number} topRadius Top radius of truncated cone.\n * @param {number} height Height of truncated cone.\n * @param {number} radialSubdivisions The number of subdivisions around the\n * truncated cone.\n * @param {number} verticalSubdivisions The number of subdivisions down the\n * truncated cone.\n * @param {boolean} [opt_topCap] Create top cap. Default = true.\n * @param {boolean} [opt_bottomCap] Create bottom cap. Default = true.\n * @return {Object.} The created cone buffers.\n * @memberOf module:twgl/primitives\n * @function createTruncatedConeBuffers\n */\n\n/**\n * Creates vertices for a truncated cone, which is like a cylinder\n * except that it has different top and bottom radii. A truncated cone\n * can also be used to create cylinders and regular cones. The\n * truncated cone will be created centered about the origin, with the\n * y axis as its vertical axis. .\n *\n * @param {number} bottomRadius Bottom radius of truncated cone.\n * @param {number} topRadius Top radius of truncated cone.\n * @param {number} height Height of truncated cone.\n * @param {number} radialSubdivisions The number of subdivisions around the\n * truncated cone.\n * @param {number} verticalSubdivisions The number of subdivisions down the\n * truncated cone.\n * @param {boolean} [opt_topCap] Create top cap. Default = true.\n * @param {boolean} [opt_bottomCap] Create bottom cap. Default = true.\n * @return {Object.} The created cone vertices.\n * @memberOf module:twgl/primitives\n */\nfunction createTruncatedConeVertices(\n bottomRadius,\n topRadius,\n height,\n radialSubdivisions,\n verticalSubdivisions,\n opt_topCap,\n opt_bottomCap) {\n if (radialSubdivisions < 3) {\n throw new Error('radialSubdivisions must be 3 or greater');\n }\n\n if (verticalSubdivisions < 1) {\n throw new Error('verticalSubdivisions must be 1 or greater');\n }\n\n const topCap = (opt_topCap === undefined) ? true : opt_topCap;\n const bottomCap = (opt_bottomCap === undefined) ? true : opt_bottomCap;\n\n const extra = (topCap ? 2 : 0) + (bottomCap ? 2 : 0);\n\n const numVertices = (radialSubdivisions + 1) * (verticalSubdivisions + 1 + extra);\n const positions = createAugmentedTypedArray(3, numVertices);\n const normals = createAugmentedTypedArray(3, numVertices);\n const texcoords = createAugmentedTypedArray(2, numVertices);\n const indices = createAugmentedTypedArray(3, radialSubdivisions * (verticalSubdivisions + extra / 2) * 2, Uint16Array);\n\n const vertsAroundEdge = radialSubdivisions + 1;\n\n // The slant of the cone is constant across its surface\n const slant = Math.atan2(bottomRadius - topRadius, height);\n const cosSlant = Math.cos(slant);\n const sinSlant = Math.sin(slant);\n\n const start = topCap ? -2 : 0;\n const end = verticalSubdivisions + (bottomCap ? 2 : 0);\n\n for (let yy = start; yy <= end; ++yy) {\n let v = yy / verticalSubdivisions;\n let y = height * v;\n let ringRadius;\n if (yy < 0) {\n y = 0;\n v = 1;\n ringRadius = bottomRadius;\n } else if (yy > verticalSubdivisions) {\n y = height;\n v = 1;\n ringRadius = topRadius;\n } else {\n ringRadius = bottomRadius +\n (topRadius - bottomRadius) * (yy / verticalSubdivisions);\n }\n if (yy === -2 || yy === verticalSubdivisions + 2) {\n ringRadius = 0;\n v = 0;\n }\n y -= height / 2;\n for (let ii = 0; ii < vertsAroundEdge; ++ii) {\n const sin = Math.sin(ii * Math.PI * 2 / radialSubdivisions);\n const cos = Math.cos(ii * Math.PI * 2 / radialSubdivisions);\n positions.push(sin * ringRadius, y, cos * ringRadius);\n if (yy < 0) {\n normals.push(0, -1, 0);\n } else if (yy > verticalSubdivisions) {\n normals.push(0, 1, 0);\n } else if (ringRadius === 0.0) {\n normals.push(0, 0, 0);\n } else {\n normals.push(sin * cosSlant, sinSlant, cos * cosSlant);\n }\n texcoords.push((ii / radialSubdivisions), 1 - v);\n }\n }\n\n for (let yy = 0; yy < verticalSubdivisions + extra; ++yy) { // eslint-disable-line\n if (yy === 1 && topCap || yy === verticalSubdivisions + extra - 2 && bottomCap) {\n continue;\n }\n for (let ii = 0; ii < radialSubdivisions; ++ii) { // eslint-disable-line\n indices.push(vertsAroundEdge * (yy + 0) + 0 + ii,\n vertsAroundEdge * (yy + 0) + 1 + ii,\n vertsAroundEdge * (yy + 1) + 1 + ii);\n indices.push(vertsAroundEdge * (yy + 0) + 0 + ii,\n vertsAroundEdge * (yy + 1) + 1 + ii,\n vertsAroundEdge * (yy + 1) + 0 + ii);\n }\n }\n\n return {\n position: positions,\n normal: normals,\n texcoord: texcoords,\n indices: indices,\n };\n}\n\n/**\n * Expands RLE data\n * @param {number[]} rleData data in format of run-length, x, y, z, run-length, x, y, z\n * @param {number[]} [padding] value to add each entry with.\n * @return {number[]} the expanded rleData\n * @private\n */\nfunction expandRLEData(rleData, padding) {\n padding = padding || [];\n const data = [];\n for (let ii = 0; ii < rleData.length; ii += 4) {\n const runLength = rleData[ii];\n const element = rleData.slice(ii + 1, ii + 4);\n element.push.apply(element, padding);\n for (let jj = 0; jj < runLength; ++jj) {\n data.push.apply(data, element);\n }\n }\n return data;\n}\n\n/**\n * Creates 3D 'F' BufferInfo.\n * An 'F' is useful because you can easily tell which way it is oriented.\n * The created 'F' has position, normal, texcoord, and color buffers.\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @return {module:twgl.BufferInfo} The created BufferInfo.\n * @memberOf module:twgl/primitives\n * @function create3DFBufferInfo\n */\n\n/**\n * Creates 3D 'F' buffers.\n * An 'F' is useful because you can easily tell which way it is oriented.\n * The created 'F' has position, normal, texcoord, and color buffers.\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @return {Object.} The created buffers.\n * @memberOf module:twgl/primitives\n * @function create3DFBuffers\n */\n\n/**\n * Creates 3D 'F' vertices.\n * An 'F' is useful because you can easily tell which way it is oriented.\n * The created 'F' has position, normal, texcoord, and color arrays.\n *\n * @return {Object.} The created vertices.\n * @memberOf module:twgl/primitives\n */\nfunction create3DFVertices() {\n\n const positions = [\n // left column front\n 0, 0, 0,\n 0, 150, 0,\n 30, 0, 0,\n 0, 150, 0,\n 30, 150, 0,\n 30, 0, 0,\n\n // top rung front\n 30, 0, 0,\n 30, 30, 0,\n 100, 0, 0,\n 30, 30, 0,\n 100, 30, 0,\n 100, 0, 0,\n\n // middle rung front\n 30, 60, 0,\n 30, 90, 0,\n 67, 60, 0,\n 30, 90, 0,\n 67, 90, 0,\n 67, 60, 0,\n\n // left column back\n 0, 0, 30,\n 30, 0, 30,\n 0, 150, 30,\n 0, 150, 30,\n 30, 0, 30,\n 30, 150, 30,\n\n // top rung back\n 30, 0, 30,\n 100, 0, 30,\n 30, 30, 30,\n 30, 30, 30,\n 100, 0, 30,\n 100, 30, 30,\n\n // middle rung back\n 30, 60, 30,\n 67, 60, 30,\n 30, 90, 30,\n 30, 90, 30,\n 67, 60, 30,\n 67, 90, 30,\n\n // top\n 0, 0, 0,\n 100, 0, 0,\n 100, 0, 30,\n 0, 0, 0,\n 100, 0, 30,\n 0, 0, 30,\n\n // top rung front\n 100, 0, 0,\n 100, 30, 0,\n 100, 30, 30,\n 100, 0, 0,\n 100, 30, 30,\n 100, 0, 30,\n\n // under top rung\n 30, 30, 0,\n 30, 30, 30,\n 100, 30, 30,\n 30, 30, 0,\n 100, 30, 30,\n 100, 30, 0,\n\n // between top rung and middle\n 30, 30, 0,\n 30, 60, 30,\n 30, 30, 30,\n 30, 30, 0,\n 30, 60, 0,\n 30, 60, 30,\n\n // top of middle rung\n 30, 60, 0,\n 67, 60, 30,\n 30, 60, 30,\n 30, 60, 0,\n 67, 60, 0,\n 67, 60, 30,\n\n // front of middle rung\n 67, 60, 0,\n 67, 90, 30,\n 67, 60, 30,\n 67, 60, 0,\n 67, 90, 0,\n 67, 90, 30,\n\n // bottom of middle rung.\n 30, 90, 0,\n 30, 90, 30,\n 67, 90, 30,\n 30, 90, 0,\n 67, 90, 30,\n 67, 90, 0,\n\n // front of bottom\n 30, 90, 0,\n 30, 150, 30,\n 30, 90, 30,\n 30, 90, 0,\n 30, 150, 0,\n 30, 150, 30,\n\n // bottom\n 0, 150, 0,\n 0, 150, 30,\n 30, 150, 30,\n 0, 150, 0,\n 30, 150, 30,\n 30, 150, 0,\n\n // left side\n 0, 0, 0,\n 0, 0, 30,\n 0, 150, 30,\n 0, 0, 0,\n 0, 150, 30,\n 0, 150, 0,\n ];\n\n const texcoords = [\n // left column front\n 0.22, 0.19,\n 0.22, 0.79,\n 0.34, 0.19,\n 0.22, 0.79,\n 0.34, 0.79,\n 0.34, 0.19,\n\n // top rung front\n 0.34, 0.19,\n 0.34, 0.31,\n 0.62, 0.19,\n 0.34, 0.31,\n 0.62, 0.31,\n 0.62, 0.19,\n\n // middle rung front\n 0.34, 0.43,\n 0.34, 0.55,\n 0.49, 0.43,\n 0.34, 0.55,\n 0.49, 0.55,\n 0.49, 0.43,\n\n // left column back\n 0, 0,\n 1, 0,\n 0, 1,\n 0, 1,\n 1, 0,\n 1, 1,\n\n // top rung back\n 0, 0,\n 1, 0,\n 0, 1,\n 0, 1,\n 1, 0,\n 1, 1,\n\n // middle rung back\n 0, 0,\n 1, 0,\n 0, 1,\n 0, 1,\n 1, 0,\n 1, 1,\n\n // top\n 0, 0,\n 1, 0,\n 1, 1,\n 0, 0,\n 1, 1,\n 0, 1,\n\n // top rung front\n 0, 0,\n 1, 0,\n 1, 1,\n 0, 0,\n 1, 1,\n 0, 1,\n\n // under top rung\n 0, 0,\n 0, 1,\n 1, 1,\n 0, 0,\n 1, 1,\n 1, 0,\n\n // between top rung and middle\n 0, 0,\n 1, 1,\n 0, 1,\n 0, 0,\n 1, 0,\n 1, 1,\n\n // top of middle rung\n 0, 0,\n 1, 1,\n 0, 1,\n 0, 0,\n 1, 0,\n 1, 1,\n\n // front of middle rung\n 0, 0,\n 1, 1,\n 0, 1,\n 0, 0,\n 1, 0,\n 1, 1,\n\n // bottom of middle rung.\n 0, 0,\n 0, 1,\n 1, 1,\n 0, 0,\n 1, 1,\n 1, 0,\n\n // front of bottom\n 0, 0,\n 1, 1,\n 0, 1,\n 0, 0,\n 1, 0,\n 1, 1,\n\n // bottom\n 0, 0,\n 0, 1,\n 1, 1,\n 0, 0,\n 1, 1,\n 1, 0,\n\n // left side\n 0, 0,\n 0, 1,\n 1, 1,\n 0, 0,\n 1, 1,\n 1, 0,\n ];\n\n const normals = expandRLEData([\n // left column front\n // top rung front\n // middle rung front\n 18, 0, 0, 1,\n\n // left column back\n // top rung back\n // middle rung back\n 18, 0, 0, -1,\n\n // top\n 6, 0, 1, 0,\n\n // top rung front\n 6, 1, 0, 0,\n\n // under top rung\n 6, 0, -1, 0,\n\n // between top rung and middle\n 6, 1, 0, 0,\n\n // top of middle rung\n 6, 0, 1, 0,\n\n // front of middle rung\n 6, 1, 0, 0,\n\n // bottom of middle rung.\n 6, 0, -1, 0,\n\n // front of bottom\n 6, 1, 0, 0,\n\n // bottom\n 6, 0, -1, 0,\n\n // left side\n 6, -1, 0, 0,\n ]);\n\n const colors = expandRLEData([\n // left column front\n // top rung front\n // middle rung front\n 18, 200, 70, 120,\n\n // left column back\n // top rung back\n // middle rung back\n 18, 80, 70, 200,\n\n // top\n 6, 70, 200, 210,\n\n // top rung front\n 6, 200, 200, 70,\n\n // under top rung\n 6, 210, 100, 70,\n\n // between top rung and middle\n 6, 210, 160, 70,\n\n // top of middle rung\n 6, 70, 180, 210,\n\n // front of middle rung\n 6, 100, 70, 210,\n\n // bottom of middle rung.\n 6, 76, 210, 100,\n\n // front of bottom\n 6, 140, 210, 80,\n\n // bottom\n 6, 90, 130, 110,\n\n // left side\n 6, 160, 160, 220,\n ], [255]);\n\n const numVerts = positions.length / 3;\n\n const arrays = {\n position: createAugmentedTypedArray(3, numVerts),\n texcoord: createAugmentedTypedArray(2, numVerts),\n normal: createAugmentedTypedArray(3, numVerts),\n color: createAugmentedTypedArray(4, numVerts, Uint8Array),\n indices: createAugmentedTypedArray(3, numVerts / 3, Uint16Array),\n };\n\n arrays.position.push(positions);\n arrays.texcoord.push(texcoords);\n arrays.normal.push(normals);\n arrays.color.push(colors);\n\n for (let ii = 0; ii < numVerts; ++ii) {\n arrays.indices.push(ii);\n }\n\n return arrays;\n}\n\n/**\n * Creates crescent BufferInfo.\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} verticalRadius The vertical radius of the crescent.\n * @param {number} outerRadius The outer radius of the crescent.\n * @param {number} innerRadius The inner radius of the crescent.\n * @param {number} thickness The thickness of the crescent.\n * @param {number} subdivisionsDown number of steps around the crescent.\n * @param {number} [startOffset] Where to start arc. Default 0.\n * @param {number} [endOffset] Where to end arg. Default 1.\n * @return {module:twgl.BufferInfo} The created BufferInfo.\n * @memberOf module:twgl/primitives\n * @function createCresentBufferInfo\n */\n\n/**\n * Creates crescent buffers.\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} verticalRadius The vertical radius of the crescent.\n * @param {number} outerRadius The outer radius of the crescent.\n * @param {number} innerRadius The inner radius of the crescent.\n * @param {number} thickness The thickness of the crescent.\n * @param {number} subdivisionsDown number of steps around the crescent.\n * @param {number} [startOffset] Where to start arc. Default 0.\n * @param {number} [endOffset] Where to end arg. Default 1.\n * @return {Object.} The created buffers.\n * @memberOf module:twgl/primitives\n * @function createCresentBuffers\n */\n\n/**\n * Creates crescent vertices.\n *\n * @param {number} verticalRadius The vertical radius of the crescent.\n * @param {number} outerRadius The outer radius of the crescent.\n * @param {number} innerRadius The inner radius of the crescent.\n * @param {number} thickness The thickness of the crescent.\n * @param {number} subdivisionsDown number of steps around the crescent.\n * @param {number} [startOffset] Where to start arc. Default 0.\n * @param {number} [endOffset] Where to end arg. Default 1.\n * @return {Object.} The created vertices.\n * @memberOf module:twgl/primitives\n * @function createCresentBuffers\n */\n\n/**\n * Creates crescent BufferInfo.\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} verticalRadius The vertical radius of the crescent.\n * @param {number} outerRadius The outer radius of the crescent.\n * @param {number} innerRadius The inner radius of the crescent.\n * @param {number} thickness The thickness of the crescent.\n * @param {number} subdivisionsDown number of steps around the crescent.\n * @param {number} [startOffset] Where to start arc. Default 0.\n * @param {number} [endOffset] Where to end arg. Default 1.\n * @return {module:twgl.BufferInfo} The created BufferInfo.\n * @memberOf module:twgl/primitives\n * @function createCrescentBufferInfo\n */\n\n/**\n * Creates crescent buffers.\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} verticalRadius The vertical radius of the crescent.\n * @param {number} outerRadius The outer radius of the crescent.\n * @param {number} innerRadius The inner radius of the crescent.\n * @param {number} thickness The thickness of the crescent.\n * @param {number} subdivisionsDown number of steps around the crescent.\n * @param {number} [startOffset] Where to start arc. Default 0.\n * @param {number} [endOffset] Where to end arg. Default 1.\n * @return {Object.} The created buffers.\n * @memberOf module:twgl/primitives\n * @function createCrescentBuffers\n */\n\n/**\n * Creates crescent vertices.\n *\n * @param {number} verticalRadius The vertical radius of the crescent.\n * @param {number} outerRadius The outer radius of the crescent.\n * @param {number} innerRadius The inner radius of the crescent.\n * @param {number} thickness The thickness of the crescent.\n * @param {number} subdivisionsDown number of steps around the crescent.\n * @param {number} [startOffset] Where to start arc. Default 0.\n * @param {number} [endOffset] Where to end arg. Default 1.\n * @return {Object.} The created vertices.\n * @memberOf module:twgl/primitives\n */\n function createCrescentVertices(\n verticalRadius,\n outerRadius,\n innerRadius,\n thickness,\n subdivisionsDown,\n startOffset,\n endOffset) {\n if (subdivisionsDown <= 0) {\n throw new Error('subdivisionDown must be > 0');\n }\n\n startOffset = startOffset || 0;\n endOffset = endOffset || 1;\n\n const subdivisionsThick = 2;\n\n const offsetRange = endOffset - startOffset;\n const numVertices = (subdivisionsDown + 1) * 2 * (2 + subdivisionsThick);\n const positions = createAugmentedTypedArray(3, numVertices);\n const normals = createAugmentedTypedArray(3, numVertices);\n const texcoords = createAugmentedTypedArray(2, numVertices);\n\n function lerp(a, b, s) {\n return a + (b - a) * s;\n }\n\n function createArc(arcRadius, x, normalMult, normalAdd, uMult, uAdd) {\n for (let z = 0; z <= subdivisionsDown; z++) {\n const uBack = x / (subdivisionsThick - 1);\n const v = z / subdivisionsDown;\n const xBack = (uBack - 0.5) * 2;\n const angle = (startOffset + (v * offsetRange)) * Math.PI;\n const s = Math.sin(angle);\n const c = Math.cos(angle);\n const radius = lerp(verticalRadius, arcRadius, s);\n const px = xBack * thickness;\n const py = c * verticalRadius;\n const pz = s * radius;\n positions.push(px, py, pz);\n const n = add(multiply$1([0, s, c], normalMult), normalAdd);\n normals.push(n);\n texcoords.push(uBack * uMult + uAdd, v);\n }\n }\n\n // Generate the individual vertices in our vertex buffer.\n for (let x = 0; x < subdivisionsThick; x++) {\n const uBack = (x / (subdivisionsThick - 1) - 0.5) * 2;\n createArc(outerRadius, x, [1, 1, 1], [0, 0, 0], 1, 0);\n createArc(outerRadius, x, [0, 0, 0], [uBack, 0, 0], 0, 0);\n createArc(innerRadius, x, [1, 1, 1], [0, 0, 0], 1, 0);\n createArc(innerRadius, x, [0, 0, 0], [uBack, 0, 0], 0, 1);\n }\n\n // Do outer surface.\n const indices = createAugmentedTypedArray(3, (subdivisionsDown * 2) * (2 + subdivisionsThick), Uint16Array);\n\n function createSurface(leftArcOffset, rightArcOffset) {\n for (let z = 0; z < subdivisionsDown; ++z) {\n // Make triangle 1 of quad.\n indices.push(\n leftArcOffset + z + 0,\n leftArcOffset + z + 1,\n rightArcOffset + z + 0);\n\n // Make triangle 2 of quad.\n indices.push(\n leftArcOffset + z + 1,\n rightArcOffset + z + 1,\n rightArcOffset + z + 0);\n }\n }\n\n const numVerticesDown = subdivisionsDown + 1;\n // front\n createSurface(numVerticesDown * 0, numVerticesDown * 4);\n // right\n createSurface(numVerticesDown * 5, numVerticesDown * 7);\n // back\n createSurface(numVerticesDown * 6, numVerticesDown * 2);\n // left\n createSurface(numVerticesDown * 3, numVerticesDown * 1);\n\n return {\n position: positions,\n normal: normals,\n texcoord: texcoords,\n indices: indices,\n };\n}\n\n/**\n * Creates cylinder BufferInfo. The cylinder will be created around the origin\n * along the y-axis.\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} radius Radius of cylinder.\n * @param {number} height Height of cylinder.\n * @param {number} radialSubdivisions The number of subdivisions around the cylinder.\n * @param {number} verticalSubdivisions The number of subdivisions down the cylinder.\n * @param {boolean} [topCap] Create top cap. Default = true.\n * @param {boolean} [bottomCap] Create bottom cap. Default = true.\n * @return {module:twgl.BufferInfo} The created BufferInfo.\n * @memberOf module:twgl/primitives\n * @function createCylinderBufferInfo\n */\n\n /**\n * Creates cylinder buffers. The cylinder will be created around the origin\n * along the y-axis.\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} radius Radius of cylinder.\n * @param {number} height Height of cylinder.\n * @param {number} radialSubdivisions The number of subdivisions around the cylinder.\n * @param {number} verticalSubdivisions The number of subdivisions down the cylinder.\n * @param {boolean} [topCap] Create top cap. Default = true.\n * @param {boolean} [bottomCap] Create bottom cap. Default = true.\n * @return {Object.} The created buffers.\n * @memberOf module:twgl/primitives\n * @function createCylinderBuffers\n */\n\n /**\n * Creates cylinder vertices. The cylinder will be created around the origin\n * along the y-axis.\n *\n * @param {number} radius Radius of cylinder.\n * @param {number} height Height of cylinder.\n * @param {number} radialSubdivisions The number of subdivisions around the cylinder.\n * @param {number} verticalSubdivisions The number of subdivisions down the cylinder.\n * @param {boolean} [topCap] Create top cap. Default = true.\n * @param {boolean} [bottomCap] Create bottom cap. Default = true.\n * @return {Object.} The created vertices.\n * @memberOf module:twgl/primitives\n */\nfunction createCylinderVertices(\n radius,\n height,\n radialSubdivisions,\n verticalSubdivisions,\n topCap,\n bottomCap) {\n return createTruncatedConeVertices(\n radius,\n radius,\n height,\n radialSubdivisions,\n verticalSubdivisions,\n topCap,\n bottomCap);\n}\n\n/**\n * Creates BufferInfo for a torus\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} radius radius of center of torus circle.\n * @param {number} thickness radius of torus ring.\n * @param {number} radialSubdivisions The number of subdivisions around the torus.\n * @param {number} bodySubdivisions The number of subdivisions around the body torus.\n * @param {boolean} [startAngle] start angle in radians. Default = 0.\n * @param {boolean} [endAngle] end angle in radians. Default = Math.PI * 2.\n * @return {module:twgl.BufferInfo} The created BufferInfo.\n * @memberOf module:twgl/primitives\n * @function createTorusBufferInfo\n */\n\n/**\n * Creates buffers for a torus\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} radius radius of center of torus circle.\n * @param {number} thickness radius of torus ring.\n * @param {number} radialSubdivisions The number of subdivisions around the torus.\n * @param {number} bodySubdivisions The number of subdivisions around the body torus.\n * @param {boolean} [startAngle] start angle in radians. Default = 0.\n * @param {boolean} [endAngle] end angle in radians. Default = Math.PI * 2.\n * @return {Object.} The created buffers.\n * @memberOf module:twgl/primitives\n * @function createTorusBuffers\n */\n\n/**\n * Creates vertices for a torus\n *\n * @param {number} radius radius of center of torus circle.\n * @param {number} thickness radius of torus ring.\n * @param {number} radialSubdivisions The number of subdivisions around the torus.\n * @param {number} bodySubdivisions The number of subdivisions around the body torus.\n * @param {boolean} [startAngle] start angle in radians. Default = 0.\n * @param {boolean} [endAngle] end angle in radians. Default = Math.PI * 2.\n * @return {Object.} The created vertices.\n * @memberOf module:twgl/primitives\n */\nfunction createTorusVertices(\n radius,\n thickness,\n radialSubdivisions,\n bodySubdivisions,\n startAngle,\n endAngle) {\n if (radialSubdivisions < 3) {\n throw new Error('radialSubdivisions must be 3 or greater');\n }\n\n if (bodySubdivisions < 3) {\n throw new Error('verticalSubdivisions must be 3 or greater');\n }\n\n startAngle = startAngle || 0;\n endAngle = endAngle || Math.PI * 2;\n const range = endAngle - startAngle;\n\n const radialParts = radialSubdivisions + 1;\n const bodyParts = bodySubdivisions + 1;\n const numVertices = radialParts * bodyParts;\n const positions = createAugmentedTypedArray(3, numVertices);\n const normals = createAugmentedTypedArray(3, numVertices);\n const texcoords = createAugmentedTypedArray(2, numVertices);\n const indices = createAugmentedTypedArray(3, (radialSubdivisions) * (bodySubdivisions) * 2, Uint16Array);\n\n for (let slice = 0; slice < bodyParts; ++slice) {\n const v = slice / bodySubdivisions;\n const sliceAngle = v * Math.PI * 2;\n const sliceSin = Math.sin(sliceAngle);\n const ringRadius = radius + sliceSin * thickness;\n const ny = Math.cos(sliceAngle);\n const y = ny * thickness;\n for (let ring = 0; ring < radialParts; ++ring) {\n const u = ring / radialSubdivisions;\n const ringAngle = startAngle + u * range;\n const xSin = Math.sin(ringAngle);\n const zCos = Math.cos(ringAngle);\n const x = xSin * ringRadius;\n const z = zCos * ringRadius;\n const nx = xSin * sliceSin;\n const nz = zCos * sliceSin;\n positions.push(x, y, z);\n normals.push(nx, ny, nz);\n texcoords.push(u, 1 - v);\n }\n }\n\n for (let slice = 0; slice < bodySubdivisions; ++slice) { // eslint-disable-line\n for (let ring = 0; ring < radialSubdivisions; ++ring) { // eslint-disable-line\n const nextRingIndex = 1 + ring;\n const nextSliceIndex = 1 + slice;\n indices.push(radialParts * slice + ring,\n radialParts * nextSliceIndex + ring,\n radialParts * slice + nextRingIndex);\n indices.push(radialParts * nextSliceIndex + ring,\n radialParts * nextSliceIndex + nextRingIndex,\n radialParts * slice + nextRingIndex);\n }\n }\n\n return {\n position: positions,\n normal: normals,\n texcoord: texcoords,\n indices: indices,\n };\n}\n\n\n/**\n * Creates a disc BufferInfo. The disc will be in the xz plane, centered at\n * the origin. When creating, at least 3 divisions, or pie\n * pieces, need to be specified, otherwise the triangles making\n * up the disc will be degenerate. You can also specify the\n * number of radial pieces `stacks`. A value of 1 for\n * stacks will give you a simple disc of pie pieces. If you\n * want to create an annulus you can set `innerRadius` to a\n * value > 0. Finally, `stackPower` allows you to have the widths\n * increase or decrease as you move away from the center. This\n * is particularly useful when using the disc as a ground plane\n * with a fixed camera such that you don't need the resolution\n * of small triangles near the perimeter. For example, a value\n * of 2 will produce stacks whose outside radius increases with\n * the square of the stack index. A value of 1 will give uniform\n * stacks.\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} radius Radius of the ground plane.\n * @param {number} divisions Number of triangles in the ground plane (at least 3).\n * @param {number} [stacks] Number of radial divisions (default=1).\n * @param {number} [innerRadius] Default 0.\n * @param {number} [stackPower] Power to raise stack size to for decreasing width.\n * @return {module:twgl.BufferInfo} The created BufferInfo.\n * @memberOf module:twgl/primitives\n * @function createDiscBufferInfo\n */\n\n/**\n * Creates disc buffers. The disc will be in the xz plane, centered at\n * the origin. When creating, at least 3 divisions, or pie\n * pieces, need to be specified, otherwise the triangles making\n * up the disc will be degenerate. You can also specify the\n * number of radial pieces `stacks`. A value of 1 for\n * stacks will give you a simple disc of pie pieces. If you\n * want to create an annulus you can set `innerRadius` to a\n * value > 0. Finally, `stackPower` allows you to have the widths\n * increase or decrease as you move away from the center. This\n * is particularly useful when using the disc as a ground plane\n * with a fixed camera such that you don't need the resolution\n * of small triangles near the perimeter. For example, a value\n * of 2 will produce stacks whose outside radius increases with\n * the square of the stack index. A value of 1 will give uniform\n * stacks.\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} radius Radius of the ground plane.\n * @param {number} divisions Number of triangles in the ground plane (at least 3).\n * @param {number} [stacks] Number of radial divisions (default=1).\n * @param {number} [innerRadius] Default 0.\n * @param {number} [stackPower] Power to raise stack size to for decreasing width.\n * @return {Object.} The created buffers.\n * @memberOf module:twgl/primitives\n * @function createDiscBuffers\n */\n\n/**\n * Creates disc vertices. The disc will be in the xz plane, centered at\n * the origin. When creating, at least 3 divisions, or pie\n * pieces, need to be specified, otherwise the triangles making\n * up the disc will be degenerate. You can also specify the\n * number of radial pieces `stacks`. A value of 1 for\n * stacks will give you a simple disc of pie pieces. If you\n * want to create an annulus you can set `innerRadius` to a\n * value > 0. Finally, `stackPower` allows you to have the widths\n * increase or decrease as you move away from the center. This\n * is particularly useful when using the disc as a ground plane\n * with a fixed camera such that you don't need the resolution\n * of small triangles near the perimeter. For example, a value\n * of 2 will produce stacks whose outside radius increases with\n * the square of the stack index. A value of 1 will give uniform\n * stacks.\n *\n * @param {number} radius Radius of the ground plane.\n * @param {number} divisions Number of triangles in the ground plane (at least 3).\n * @param {number} [stacks] Number of radial divisions (default=1).\n * @param {number} [innerRadius] Default 0.\n * @param {number} [stackPower] Power to raise stack size to for decreasing width.\n * @return {Object.} The created vertices.\n * @memberOf module:twgl/primitives\n */\nfunction createDiscVertices(\n radius,\n divisions,\n stacks,\n innerRadius,\n stackPower) {\n if (divisions < 3) {\n throw new Error('divisions must be at least 3');\n }\n\n stacks = stacks ? stacks : 1;\n stackPower = stackPower ? stackPower : 1;\n innerRadius = innerRadius ? innerRadius : 0;\n\n // Note: We don't share the center vertex because that would\n // mess up texture coordinates.\n const numVertices = (divisions + 1) * (stacks + 1);\n\n const positions = createAugmentedTypedArray(3, numVertices);\n const normals = createAugmentedTypedArray(3, numVertices);\n const texcoords = createAugmentedTypedArray(2, numVertices);\n const indices = createAugmentedTypedArray(3, stacks * divisions * 2, Uint16Array);\n\n let firstIndex = 0;\n const radiusSpan = radius - innerRadius;\n const pointsPerStack = divisions + 1;\n\n // Build the disk one stack at a time.\n for (let stack = 0; stack <= stacks; ++stack) {\n const stackRadius = innerRadius + radiusSpan * Math.pow(stack / stacks, stackPower);\n\n for (let i = 0; i <= divisions; ++i) {\n const theta = 2.0 * Math.PI * i / divisions;\n const x = stackRadius * Math.cos(theta);\n const z = stackRadius * Math.sin(theta);\n\n positions.push(x, 0, z);\n normals.push(0, 1, 0);\n texcoords.push(1 - (i / divisions), stack / stacks);\n if (stack > 0 && i !== divisions) {\n // a, b, c and d are the indices of the vertices of a quad. unless\n // the current stack is the one closest to the center, in which case\n // the vertices a and b connect to the center vertex.\n const a = firstIndex + (i + 1);\n const b = firstIndex + i;\n const c = firstIndex + i - pointsPerStack;\n const d = firstIndex + (i + 1) - pointsPerStack;\n\n // Make a quad of the vertices a, b, c, d.\n indices.push(a, b, c);\n indices.push(a, c, d);\n }\n }\n\n firstIndex += divisions + 1;\n }\n\n return {\n position: positions,\n normal: normals,\n texcoord: texcoords,\n indices: indices,\n };\n}\n\n/**\n * creates a random integer between 0 and range - 1 inclusive.\n * @param {number} range\n * @return {number} random value between 0 and range - 1 inclusive.\n * @private\n */\nfunction randInt(range) {\n return Math.random() * range | 0;\n}\n\n/**\n * Used to supply random colors\n * @callback RandomColorFunc\n * @param {number} ndx index of triangle/quad if unindexed or index of vertex if indexed\n * @param {number} channel 0 = red, 1 = green, 2 = blue, 3 = alpha\n * @return {number} a number from 0 to 255\n * @memberOf module:twgl/primitives\n */\n\n/**\n * @typedef {Object} RandomVerticesOptions\n * @property {number} [vertsPerColor] Defaults to 3 for non-indexed vertices\n * @property {module:twgl/primitives.RandomColorFunc} [rand] A function to generate random numbers\n * @memberOf module:twgl/primitives\n */\n\n/**\n * Creates an augmentedTypedArray of random vertex colors.\n * If the vertices are indexed (have an indices array) then will\n * just make random colors. Otherwise assumes they are triangles\n * and makes one random color for every 3 vertices.\n * @param {Object.} vertices Vertices as returned from one of the createXXXVertices functions.\n * @param {module:twgl/primitives.RandomVerticesOptions} [options] options.\n * @return {Object.} same vertices as passed in with `color` added.\n * @memberOf module:twgl/primitives\n */\nfunction makeRandomVertexColors(vertices, options) {\n options = options || {};\n const numElements = vertices.position.numElements;\n const vColors = createAugmentedTypedArray(4, numElements, Uint8Array);\n const rand = options.rand || function(ndx, channel) {\n return channel < 3 ? randInt(256) : 255;\n };\n vertices.color = vColors;\n if (vertices.indices) {\n // just make random colors if index\n for (let ii = 0; ii < numElements; ++ii) {\n vColors.push(rand(ii, 0), rand(ii, 1), rand(ii, 2), rand(ii, 3));\n }\n } else {\n // make random colors per triangle\n const numVertsPerColor = options.vertsPerColor || 3;\n const numSets = numElements / numVertsPerColor;\n for (let ii = 0; ii < numSets; ++ii) { // eslint-disable-line\n const color = [rand(ii, 0), rand(ii, 1), rand(ii, 2), rand(ii, 3)];\n for (let jj = 0; jj < numVertsPerColor; ++jj) {\n vColors.push(color);\n }\n }\n }\n return vertices;\n}\n\n/**\n * creates a function that calls fn to create vertices and then\n * creates a buffers for them\n * @private\n */\nfunction createBufferFunc(fn) {\n return function(gl) {\n const arrays = fn.apply(this, Array.prototype.slice.call(arguments, 1));\n return createBuffersFromArrays(gl, arrays);\n };\n}\n\n/**\n * creates a function that calls fn to create vertices and then\n * creates a bufferInfo object for them\n * @private\n */\nfunction createBufferInfoFunc(fn) {\n return function(gl) {\n const arrays = fn.apply(null, Array.prototype.slice.call(arguments, 1));\n return createBufferInfoFromArrays(gl, arrays);\n };\n}\n\nconst arraySpecPropertyNames = [\n \"numComponents\",\n \"size\",\n \"type\",\n \"normalize\",\n \"stride\",\n \"offset\",\n \"attrib\",\n \"name\",\n \"attribName\",\n];\n\n/**\n * Copy elements from one array to another\n *\n * @param {Array|TypedArray} src source array\n * @param {Array|TypedArray} dst dest array\n * @param {number} dstNdx index in dest to copy src\n * @param {number} [offset] offset to add to copied values\n * @private\n */\nfunction copyElements(src, dst, dstNdx, offset) {\n offset = offset || 0;\n const length = src.length;\n for (let ii = 0; ii < length; ++ii) {\n dst[dstNdx + ii] = src[ii] + offset;\n }\n}\n\n/**\n * Creates an array of the same time\n *\n * @param {(number[]|ArrayBufferView|module:twgl.FullArraySpec)} srcArray array who's type to copy\n * @param {number} length size of new array\n * @return {(number[]|ArrayBufferView|module:twgl.FullArraySpec)} array with same type as srcArray\n * @private\n */\nfunction createArrayOfSameType(srcArray, length) {\n const arraySrc = getArray(srcArray);\n const newArray = new arraySrc.constructor(length);\n let newArraySpec = newArray;\n // If it appears to have been augmented make new one augmented\n if (arraySrc.numComponents && arraySrc.numElements) {\n augmentTypedArray(newArray, arraySrc.numComponents);\n }\n // If it was a full spec make new one a full spec\n if (srcArray.data) {\n newArraySpec = {\n data: newArray,\n };\n copyNamedProperties(arraySpecPropertyNames, srcArray, newArraySpec);\n }\n return newArraySpec;\n}\n\n/**\n * Concatenates sets of vertices\n *\n * Assumes the vertices match in composition. For example\n * if one set of vertices has positions, normals, and indices\n * all sets of vertices must have positions, normals, and indices\n * and of the same type.\n *\n * Example:\n *\n * const cubeVertices = twgl.primitives.createCubeVertices(2);\n * const sphereVertices = twgl.primitives.createSphereVertices(1, 10, 10);\n * // move the sphere 2 units up\n * twgl.primitives.reorientVertices(\n * sphereVertices, twgl.m4.translation([0, 2, 0]));\n * // merge the sphere with the cube\n * const cubeSphereVertices = twgl.primitives.concatVertices(\n * [cubeVertices, sphereVertices]);\n * // turn them into WebGL buffers and attrib data\n * const bufferInfo = twgl.createBufferInfoFromArrays(gl, cubeSphereVertices);\n *\n * @param {module:twgl.Arrays[]} arrays Array of arrays of vertices\n * @return {module:twgl.Arrays} The concatenated vertices.\n * @memberOf module:twgl/primitives\n */\nfunction concatVertices(arrayOfArrays) {\n const names = {};\n let baseName;\n // get names of all arrays.\n // and numElements for each set of vertices\n for (let ii = 0; ii < arrayOfArrays.length; ++ii) {\n const arrays = arrayOfArrays[ii];\n Object.keys(arrays).forEach(function(name) { // eslint-disable-line\n if (!names[name]) {\n names[name] = [];\n }\n if (!baseName && name !== 'indices') {\n baseName = name;\n }\n const arrayInfo = arrays[name];\n const numComponents = getNumComponents(arrayInfo, name);\n const array = getArray(arrayInfo);\n const numElements = array.length / numComponents;\n names[name].push(numElements);\n });\n }\n\n // compute length of combined array\n // and return one for reference\n function getLengthOfCombinedArrays(name) {\n let length = 0;\n let arraySpec;\n for (let ii = 0; ii < arrayOfArrays.length; ++ii) {\n const arrays = arrayOfArrays[ii];\n const arrayInfo = arrays[name];\n const array = getArray(arrayInfo);\n length += array.length;\n if (!arraySpec || arrayInfo.data) {\n arraySpec = arrayInfo;\n }\n }\n return {\n length: length,\n spec: arraySpec,\n };\n }\n\n function copyArraysToNewArray(name, base, newArray) {\n let baseIndex = 0;\n let offset = 0;\n for (let ii = 0; ii < arrayOfArrays.length; ++ii) {\n const arrays = arrayOfArrays[ii];\n const arrayInfo = arrays[name];\n const array = getArray(arrayInfo);\n if (name === 'indices') {\n copyElements(array, newArray, offset, baseIndex);\n baseIndex += base[ii];\n } else {\n copyElements(array, newArray, offset);\n }\n offset += array.length;\n }\n }\n\n const base = names[baseName];\n\n const newArrays = {};\n Object.keys(names).forEach(function(name) {\n const info = getLengthOfCombinedArrays(name);\n const newArraySpec = createArrayOfSameType(info.spec, info.length);\n copyArraysToNewArray(name, base, getArray(newArraySpec));\n newArrays[name] = newArraySpec;\n });\n return newArrays;\n}\n\n/**\n * Creates a duplicate set of vertices\n *\n * This is useful for calling reorientVertices when you\n * also want to keep the original available\n *\n * @param {module:twgl.Arrays} arrays of vertices\n * @return {module:twgl.Arrays} The duplicated vertices.\n * @memberOf module:twgl/primitives\n */\nfunction duplicateVertices(arrays) {\n const newArrays = {};\n Object.keys(arrays).forEach(function(name) {\n const arraySpec = arrays[name];\n const srcArray = getArray(arraySpec);\n const newArraySpec = createArrayOfSameType(arraySpec, srcArray.length);\n copyElements(srcArray, getArray(newArraySpec), 0);\n newArrays[name] = newArraySpec;\n });\n return newArrays;\n}\n\nconst create3DFBufferInfo = createBufferInfoFunc(create3DFVertices);\nconst create3DFBuffers = createBufferFunc(create3DFVertices);\nconst createCubeBufferInfo = createBufferInfoFunc(createCubeVertices);\nconst createCubeBuffers = createBufferFunc(createCubeVertices);\nconst createPlaneBufferInfo = createBufferInfoFunc(createPlaneVertices);\nconst createPlaneBuffers = createBufferFunc(createPlaneVertices);\nconst createSphereBufferInfo = createBufferInfoFunc(createSphereVertices);\nconst createSphereBuffers = createBufferFunc(createSphereVertices);\nconst createTruncatedConeBufferInfo = createBufferInfoFunc(createTruncatedConeVertices);\nconst createTruncatedConeBuffers = createBufferFunc(createTruncatedConeVertices);\nconst createXYQuadBufferInfo = createBufferInfoFunc(createXYQuadVertices);\nconst createXYQuadBuffers = createBufferFunc(createXYQuadVertices);\nconst createCrescentBufferInfo = createBufferInfoFunc(createCrescentVertices);\nconst createCrescentBuffers = createBufferFunc(createCrescentVertices);\nconst createCylinderBufferInfo = createBufferInfoFunc(createCylinderVertices);\nconst createCylinderBuffers = createBufferFunc(createCylinderVertices);\nconst createTorusBufferInfo = createBufferInfoFunc(createTorusVertices);\nconst createTorusBuffers = createBufferFunc(createTorusVertices);\nconst createDiscBufferInfo = createBufferInfoFunc(createDiscVertices);\nconst createDiscBuffers = createBufferFunc(createDiscVertices);\n\n// these were mis-spelled until 4.12\nconst createCresentBufferInfo = createCrescentBufferInfo;\nconst createCresentBuffers = createCrescentBuffers;\nconst createCresentVertices = createCrescentVertices;\n\nvar primitives = /*#__PURE__*/Object.freeze({\n __proto__: null,\n create3DFBufferInfo: create3DFBufferInfo,\n create3DFBuffers: create3DFBuffers,\n create3DFVertices: create3DFVertices,\n createAugmentedTypedArray: createAugmentedTypedArray,\n createCubeBufferInfo: createCubeBufferInfo,\n createCubeBuffers: createCubeBuffers,\n createCubeVertices: createCubeVertices,\n createPlaneBufferInfo: createPlaneBufferInfo,\n createPlaneBuffers: createPlaneBuffers,\n createPlaneVertices: createPlaneVertices,\n createSphereBufferInfo: createSphereBufferInfo,\n createSphereBuffers: createSphereBuffers,\n createSphereVertices: createSphereVertices,\n createTruncatedConeBufferInfo: createTruncatedConeBufferInfo,\n createTruncatedConeBuffers: createTruncatedConeBuffers,\n createTruncatedConeVertices: createTruncatedConeVertices,\n createXYQuadBufferInfo: createXYQuadBufferInfo,\n createXYQuadBuffers: createXYQuadBuffers,\n createXYQuadVertices: createXYQuadVertices,\n createCresentBufferInfo: createCresentBufferInfo,\n createCresentBuffers: createCresentBuffers,\n createCresentVertices: createCresentVertices,\n createCrescentBufferInfo: createCrescentBufferInfo,\n createCrescentBuffers: createCrescentBuffers,\n createCrescentVertices: createCrescentVertices,\n createCylinderBufferInfo: createCylinderBufferInfo,\n createCylinderBuffers: createCylinderBuffers,\n createCylinderVertices: createCylinderVertices,\n createTorusBufferInfo: createTorusBufferInfo,\n createTorusBuffers: createTorusBuffers,\n createTorusVertices: createTorusVertices,\n createDiscBufferInfo: createDiscBufferInfo,\n createDiscBuffers: createDiscBuffers,\n createDiscVertices: createDiscVertices,\n deindexVertices: deindexVertices,\n flattenNormals: flattenNormals,\n makeRandomVertexColors: makeRandomVertexColors,\n reorientDirections: reorientDirections,\n reorientNormals: reorientNormals,\n reorientPositions: reorientPositions,\n reorientVertices: reorientVertices,\n concatVertices: concatVertices,\n duplicateVertices: duplicateVertices\n});\n\n/*\n * Copyright 2019 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\n/**\n * Gets the gl version as a number\n * @param {WebGLRenderingContext} gl A WebGLRenderingContext\n * @return {number} version of gl\n * @private\n */\n//function getVersionAsNumber(gl) {\n// return parseFloat(gl.getParameter(gl.VERSION).substr(6));\n//}\n\n/**\n * Check if context is WebGL 2.0\n * @param {WebGLRenderingContext} gl A WebGLRenderingContext\n * @return {bool} true if it's WebGL 2.0\n * @memberOf module:twgl\n */\nfunction isWebGL2(gl) {\n // This is the correct check but it's slow\n // return gl.getParameter(gl.VERSION).indexOf(\"WebGL 2.0\") === 0;\n // This might also be the correct check but I'm assuming it's slow-ish\n // return gl instanceof WebGL2RenderingContext;\n return !!gl.texStorage2D;\n}\n\n/**\n * Check if context is WebGL 1.0\n * @param {WebGLRenderingContext} gl A WebGLRenderingContext\n * @return {bool} true if it's WebGL 1.0\n * @memberOf module:twgl\n */\nfunction isWebGL1(gl) {\n // This is the correct check but it's slow\n // const version = getVersionAsNumber(gl);\n // return version <= 1.0 && version > 0.0; // because as of 2016/5 Edge returns 0.96\n // This might also be the correct check but I'm assuming it's slow-ish\n // return gl instanceof WebGLRenderingContext;\n return !gl.texStorage2D;\n}\n\n/**\n * Gets a string for WebGL enum\n *\n * Note: Several enums are the same. Without more\n * context (which function) it's impossible to always\n * give the correct enum. As it is, for matching values\n * it gives all enums. Checking the WebGL2RenderingContext\n * that means\n *\n * 0 = ZERO | POINT | NONE | NO_ERROR\n * 1 = ONE | LINES | SYNC_FLUSH_COMMANDS_BIT\n * 32777 = BLEND_EQUATION_RGB | BLEND_EQUATION_RGB\n * 36662 = COPY_READ_BUFFER | COPY_READ_BUFFER_BINDING\n * 36663 = COPY_WRITE_BUFFER | COPY_WRITE_BUFFER_BINDING\n * 36006 = FRAMEBUFFER_BINDING | DRAW_FRAMEBUFFER_BINDING\n *\n * It's also not useful for bits really unless you pass in individual bits.\n * In other words\n *\n * const bits = gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT;\n * twgl.glEnumToString(gl, bits); // not going to work\n *\n * Note that some enums only exist on extensions. If you\n * want them to show up you need to pass the extension at least\n * once. For example\n *\n * const ext = gl.getExtension('WEBGL_compressed_texture_s3tc');\n * if (ext) {\n * twgl.glEnumToString(ext, 0); // just prime the function\n *\n * ..later..\n *\n * const internalFormat = ext.COMPRESSED_RGB_S3TC_DXT1_EXT;\n * console.log(twgl.glEnumToString(gl, internalFormat));\n *\n * Notice I didn't have to pass the extension the second time. This means\n * you can have place that generically gets an enum for texture formats for example.\n * and as long as you primed the function with the extensions\n *\n * If you're using `twgl.addExtensionsToContext` to enable your extensions\n * then twgl will automatically get the extension's enums.\n *\n * @param {WebGLRenderingContext} gl A WebGLRenderingContext or any extension object\n * @param {number} value the value of the enum you want to look up.\n * @return {string} enum string or hex value\n * @memberOf module:twgl\n * @function glEnumToString\n */\nconst glEnumToString = (function() {\n const haveEnumsForType = {};\n const enums = {};\n\n function addEnums(gl) {\n const type = gl.constructor.name;\n if (!haveEnumsForType[type]) {\n for (const key in gl) {\n if (typeof gl[key] === 'number') {\n const existing = enums[gl[key]];\n enums[gl[key]] = existing ? `${existing} | ${key}` : key;\n }\n }\n haveEnumsForType[type] = true;\n }\n }\n\n return function glEnumToString(gl, value) {\n addEnums(gl);\n return enums[value] || (typeof value === 'number' ? `0x${value.toString(16)}` : value);\n };\n}());\n\nvar utils = /*#__PURE__*/Object.freeze({\n __proto__: null,\n glEnumToString: glEnumToString,\n isWebGL1: isWebGL1,\n isWebGL2: isWebGL2\n});\n\n/*\n * Copyright 2019 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\nconst defaults$1 = {\n textureColor: new Uint8Array([128, 192, 255, 255]),\n textureOptions: {},\n crossOrigin: undefined,\n};\nconst isArrayBuffer = isArrayBuffer$1;\n\n// Should we make this on demand?\nconst getShared2DContext = function() {\n let s_ctx;\n return function getShared2DContext() {\n s_ctx = s_ctx ||\n ((typeof document !== 'undefined' && document.createElement)\n ? document.createElement(\"canvas\").getContext(\"2d\")\n : null);\n return s_ctx;\n };\n}();\n\n// NOTE: Chrome supports 2D canvas in a Worker (behind flag as of v64 but\n// not only does Firefox NOT support it but Firefox freezes immediately\n// if you try to create one instead of just returning null and continuing.\n// : (global.OffscreenCanvas && (new global.OffscreenCanvas(1, 1)).getContext(\"2d\")); // OffscreenCanvas may not support 2d\n\n// NOTE: We can maybe remove some of the need for the 2d canvas. In WebGL2\n// we can use the various unpack settings. Otherwise we could try using\n// the ability of an ImageBitmap to be cut. Unfortunately cutting an ImageBitmap\n// is async and the current TWGL code expects a non-Async result though that\n// might not be a problem. ImageBitmap though is not available in Edge or Safari\n// as of 2018-01-02\n\n/* PixelFormat */\nconst ALPHA = 0x1906;\nconst RGB = 0x1907;\nconst RGBA$1 = 0x1908;\nconst LUMINANCE = 0x1909;\nconst LUMINANCE_ALPHA = 0x190A;\nconst DEPTH_COMPONENT$1 = 0x1902;\nconst DEPTH_STENCIL$1 = 0x84F9;\n\n/* TextureWrapMode */\n// const REPEAT = 0x2901;\n// const MIRRORED_REPEAT = 0x8370;\nconst CLAMP_TO_EDGE$1 = 0x812f;\n\n/* TextureMagFilter */\nconst NEAREST = 0x2600;\nconst LINEAR$1 = 0x2601;\n\n/* TextureMinFilter */\n// const NEAREST_MIPMAP_NEAREST = 0x2700;\n// const LINEAR_MIPMAP_NEAREST = 0x2701;\n// const NEAREST_MIPMAP_LINEAR = 0x2702;\n// const LINEAR_MIPMAP_LINEAR = 0x2703;\n\n/* Texture Target */\nconst TEXTURE_2D$2 = 0x0de1;\nconst TEXTURE_CUBE_MAP$1 = 0x8513;\nconst TEXTURE_3D$1 = 0x806f;\nconst TEXTURE_2D_ARRAY$1 = 0x8c1a;\n\n/* Cubemap Targets */\nconst TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515;\nconst TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516;\nconst TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517;\nconst TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518;\nconst TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519;\nconst TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851a;\n\n/* Texture Parameters */\nconst TEXTURE_MIN_FILTER = 0x2801;\nconst TEXTURE_MAG_FILTER = 0x2800;\nconst TEXTURE_WRAP_S = 0x2802;\nconst TEXTURE_WRAP_T = 0x2803;\nconst TEXTURE_WRAP_R = 0x8072;\nconst TEXTURE_MIN_LOD = 0x813a;\nconst TEXTURE_MAX_LOD = 0x813b;\nconst TEXTURE_BASE_LEVEL = 0x813c;\nconst TEXTURE_MAX_LEVEL = 0x813d;\nconst TEXTURE_COMPARE_MODE = 0x884C;\nconst TEXTURE_COMPARE_FUNC = 0x884D;\n\n/* Pixel store */\nconst UNPACK_ALIGNMENT = 0x0cf5;\nconst UNPACK_ROW_LENGTH = 0x0cf2;\nconst UNPACK_IMAGE_HEIGHT = 0x806e;\nconst UNPACK_SKIP_PIXELS = 0x0cf4;\nconst UNPACK_SKIP_ROWS = 0x0cf3;\nconst UNPACK_SKIP_IMAGES = 0x806d;\nconst UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243;\nconst UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241;\nconst UNPACK_FLIP_Y_WEBGL = 0x9240;\n\nconst R8 = 0x8229;\nconst R8_SNORM = 0x8F94;\nconst R16F = 0x822D;\nconst R32F = 0x822E;\nconst R8UI = 0x8232;\nconst R8I = 0x8231;\nconst RG16UI = 0x823A;\nconst RG16I = 0x8239;\nconst RG32UI = 0x823C;\nconst RG32I = 0x823B;\nconst RG8 = 0x822B;\nconst RG8_SNORM = 0x8F95;\nconst RG16F = 0x822F;\nconst RG32F = 0x8230;\nconst RG8UI = 0x8238;\nconst RG8I = 0x8237;\nconst R16UI = 0x8234;\nconst R16I = 0x8233;\nconst R32UI = 0x8236;\nconst R32I = 0x8235;\nconst RGB8 = 0x8051;\nconst SRGB8 = 0x8C41;\nconst RGB565$1 = 0x8D62;\nconst RGB8_SNORM = 0x8F96;\nconst R11F_G11F_B10F = 0x8C3A;\nconst RGB9_E5 = 0x8C3D;\nconst RGB16F = 0x881B;\nconst RGB32F = 0x8815;\nconst RGB8UI = 0x8D7D;\nconst RGB8I = 0x8D8F;\nconst RGB16UI = 0x8D77;\nconst RGB16I = 0x8D89;\nconst RGB32UI = 0x8D71;\nconst RGB32I = 0x8D83;\nconst RGBA8 = 0x8058;\nconst SRGB8_ALPHA8 = 0x8C43;\nconst RGBA8_SNORM = 0x8F97;\nconst RGB5_A1$1 = 0x8057;\nconst RGBA4$1 = 0x8056;\nconst RGB10_A2 = 0x8059;\nconst RGBA16F = 0x881A;\nconst RGBA32F = 0x8814;\nconst RGBA8UI = 0x8D7C;\nconst RGBA8I = 0x8D8E;\nconst RGB10_A2UI = 0x906F;\nconst RGBA16UI = 0x8D76;\nconst RGBA16I = 0x8D88;\nconst RGBA32I = 0x8D82;\nconst RGBA32UI = 0x8D70;\n\nconst DEPTH_COMPONENT16$1 = 0x81A5;\nconst DEPTH_COMPONENT24$1 = 0x81A6;\nconst DEPTH_COMPONENT32F$1 = 0x8CAC;\nconst DEPTH32F_STENCIL8$1 = 0x8CAD;\nconst DEPTH24_STENCIL8$1 = 0x88F0;\n\n/* DataType */\nconst BYTE = 0x1400;\nconst UNSIGNED_BYTE$1 = 0x1401;\nconst SHORT = 0x1402;\nconst UNSIGNED_SHORT$1 = 0x1403;\nconst INT$1 = 0x1404;\nconst UNSIGNED_INT$1 = 0x1405;\nconst FLOAT$1 = 0x1406;\nconst UNSIGNED_SHORT_4_4_4_4 = 0x8033;\nconst UNSIGNED_SHORT_5_5_5_1 = 0x8034;\nconst UNSIGNED_SHORT_5_6_5 = 0x8363;\nconst HALF_FLOAT = 0x140B;\nconst HALF_FLOAT_OES = 0x8D61; // Thanks Khronos for making this different >:(\nconst UNSIGNED_INT_2_10_10_10_REV = 0x8368;\nconst UNSIGNED_INT_10F_11F_11F_REV = 0x8C3B;\nconst UNSIGNED_INT_5_9_9_9_REV = 0x8C3E;\nconst FLOAT_32_UNSIGNED_INT_24_8_REV = 0x8DAD;\nconst UNSIGNED_INT_24_8 = 0x84FA;\n\nconst RG = 0x8227;\nconst RG_INTEGER = 0x8228;\nconst RED = 0x1903;\nconst RED_INTEGER = 0x8D94;\nconst RGB_INTEGER = 0x8D98;\nconst RGBA_INTEGER = 0x8D99;\n\nconst formatInfo = {};\n{\n // NOTE: this is named `numColorComponents` vs `numComponents` so we can let Uglify mangle\n // the name.\n const f = formatInfo;\n f[ALPHA] = { numColorComponents: 1, };\n f[LUMINANCE] = { numColorComponents: 1, };\n f[LUMINANCE_ALPHA] = { numColorComponents: 2, };\n f[RGB] = { numColorComponents: 3, };\n f[RGBA$1] = { numColorComponents: 4, };\n f[RED] = { numColorComponents: 1, };\n f[RED_INTEGER] = { numColorComponents: 1, };\n f[RG] = { numColorComponents: 2, };\n f[RG_INTEGER] = { numColorComponents: 2, };\n f[RGB] = { numColorComponents: 3, };\n f[RGB_INTEGER] = { numColorComponents: 3, };\n f[RGBA$1] = { numColorComponents: 4, };\n f[RGBA_INTEGER] = { numColorComponents: 4, };\n f[DEPTH_COMPONENT$1] = { numColorComponents: 1, };\n f[DEPTH_STENCIL$1] = { numColorComponents: 2, };\n}\n\n/**\n * @typedef {Object} TextureFormatDetails\n * @property {number} textureFormat format to pass texImage2D and similar functions.\n * @property {boolean} colorRenderable true if you can render to this format of texture.\n * @property {boolean} textureFilterable true if you can filter the texture, false if you can ony use `NEAREST`.\n * @property {number[]} type Array of possible types you can pass to texImage2D and similar function\n * @property {Object.} bytesPerElementMap A map of types to bytes per element\n * @private\n */\n\nlet s_textureInternalFormatInfo;\nfunction getTextureInternalFormatInfo(internalFormat) {\n if (!s_textureInternalFormatInfo) {\n // NOTE: these properties need unique names so we can let Uglify mangle the name.\n const t = {};\n // unsized formats\n t[ALPHA] = { textureFormat: ALPHA, colorRenderable: true, textureFilterable: true, bytesPerElement: [1, 2, 2, 4], type: [UNSIGNED_BYTE$1, HALF_FLOAT, HALF_FLOAT_OES, FLOAT$1], };\n t[LUMINANCE] = { textureFormat: LUMINANCE, colorRenderable: true, textureFilterable: true, bytesPerElement: [1, 2, 2, 4], type: [UNSIGNED_BYTE$1, HALF_FLOAT, HALF_FLOAT_OES, FLOAT$1], };\n 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], };\n 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], };\n 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], };\n t[DEPTH_COMPONENT$1] = { textureFormat: DEPTH_COMPONENT$1, colorRenderable: true, textureFilterable: false, bytesPerElement: [2, 4], type: [UNSIGNED_INT$1, UNSIGNED_SHORT$1], };\n\n // sized formats\n t[R8] = { textureFormat: RED, colorRenderable: true, textureFilterable: true, bytesPerElement: [1], type: [UNSIGNED_BYTE$1], };\n t[R8_SNORM] = { textureFormat: RED, colorRenderable: false, textureFilterable: true, bytesPerElement: [1], type: [BYTE], };\n t[R16F] = { textureFormat: RED, colorRenderable: false, textureFilterable: true, bytesPerElement: [4, 2], type: [FLOAT$1, HALF_FLOAT], };\n t[R32F] = { textureFormat: RED, colorRenderable: false, textureFilterable: false, bytesPerElement: [4], type: [FLOAT$1], };\n t[R8UI] = { textureFormat: RED_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [1], type: [UNSIGNED_BYTE$1], };\n t[R8I] = { textureFormat: RED_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [1], type: [BYTE], };\n t[R16UI] = { textureFormat: RED_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [2], type: [UNSIGNED_SHORT$1], };\n t[R16I] = { textureFormat: RED_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [2], type: [SHORT], };\n t[R32UI] = { textureFormat: RED_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [UNSIGNED_INT$1], };\n t[R32I] = { textureFormat: RED_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [INT$1], };\n t[RG8] = { textureFormat: RG, colorRenderable: true, textureFilterable: true, bytesPerElement: [2], type: [UNSIGNED_BYTE$1], };\n t[RG8_SNORM] = { textureFormat: RG, colorRenderable: false, textureFilterable: true, bytesPerElement: [2], type: [BYTE], };\n t[RG16F] = { textureFormat: RG, colorRenderable: false, textureFilterable: true, bytesPerElement: [8, 4], type: [FLOAT$1, HALF_FLOAT], };\n t[RG32F] = { textureFormat: RG, colorRenderable: false, textureFilterable: false, bytesPerElement: [8], type: [FLOAT$1], };\n t[RG8UI] = { textureFormat: RG_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [2], type: [UNSIGNED_BYTE$1], };\n t[RG8I] = { textureFormat: RG_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [2], type: [BYTE], };\n t[RG16UI] = { textureFormat: RG_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [UNSIGNED_SHORT$1], };\n t[RG16I] = { textureFormat: RG_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [SHORT], };\n t[RG32UI] = { textureFormat: RG_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [8], type: [UNSIGNED_INT$1], };\n t[RG32I] = { textureFormat: RG_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [8], type: [INT$1], };\n t[RGB8] = { textureFormat: RGB, colorRenderable: true, textureFilterable: true, bytesPerElement: [3], type: [UNSIGNED_BYTE$1], };\n t[SRGB8] = { textureFormat: RGB, colorRenderable: false, textureFilterable: true, bytesPerElement: [3], type: [UNSIGNED_BYTE$1], };\n t[RGB565$1] = { textureFormat: RGB, colorRenderable: true, textureFilterable: true, bytesPerElement: [3, 2], type: [UNSIGNED_BYTE$1, UNSIGNED_SHORT_5_6_5], };\n t[RGB8_SNORM] = { textureFormat: RGB, colorRenderable: false, textureFilterable: true, bytesPerElement: [3], type: [BYTE], };\n 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], };\n 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], };\n t[RGB16F] = { textureFormat: RGB, colorRenderable: false, textureFilterable: true, bytesPerElement: [12, 6], type: [FLOAT$1, HALF_FLOAT], };\n t[RGB32F] = { textureFormat: RGB, colorRenderable: false, textureFilterable: false, bytesPerElement: [12], type: [FLOAT$1], };\n t[RGB8UI] = { textureFormat: RGB_INTEGER, colorRenderable: false, textureFilterable: false, bytesPerElement: [3], type: [UNSIGNED_BYTE$1], };\n t[RGB8I] = { textureFormat: RGB_INTEGER, colorRenderable: false, textureFilterable: false, bytesPerElement: [3], type: [BYTE], };\n t[RGB16UI] = { textureFormat: RGB_INTEGER, colorRenderable: false, textureFilterable: false, bytesPerElement: [6], type: [UNSIGNED_SHORT$1], };\n t[RGB16I] = { textureFormat: RGB_INTEGER, colorRenderable: false, textureFilterable: false, bytesPerElement: [6], type: [SHORT], };\n t[RGB32UI] = { textureFormat: RGB_INTEGER, colorRenderable: false, textureFilterable: false, bytesPerElement: [12], type: [UNSIGNED_INT$1], };\n t[RGB32I] = { textureFormat: RGB_INTEGER, colorRenderable: false, textureFilterable: false, bytesPerElement: [12], type: [INT$1], };\n t[RGBA8] = { textureFormat: RGBA$1, colorRenderable: true, textureFilterable: true, bytesPerElement: [4], type: [UNSIGNED_BYTE$1], };\n t[SRGB8_ALPHA8] = { textureFormat: RGBA$1, colorRenderable: true, textureFilterable: true, bytesPerElement: [4], type: [UNSIGNED_BYTE$1], };\n t[RGBA8_SNORM] = { textureFormat: RGBA$1, colorRenderable: false, textureFilterable: true, bytesPerElement: [4], type: [BYTE], };\n 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], };\n t[RGBA4$1] = { textureFormat: RGBA$1, colorRenderable: true, textureFilterable: true, bytesPerElement: [4, 2], type: [UNSIGNED_BYTE$1, UNSIGNED_SHORT_4_4_4_4], };\n t[RGB10_A2] = { textureFormat: RGBA$1, colorRenderable: true, textureFilterable: true, bytesPerElement: [4], type: [UNSIGNED_INT_2_10_10_10_REV], };\n t[RGBA16F] = { textureFormat: RGBA$1, colorRenderable: false, textureFilterable: true, bytesPerElement: [16, 8], type: [FLOAT$1, HALF_FLOAT], };\n t[RGBA32F] = { textureFormat: RGBA$1, colorRenderable: false, textureFilterable: false, bytesPerElement: [16], type: [FLOAT$1], };\n t[RGBA8UI] = { textureFormat: RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [UNSIGNED_BYTE$1], };\n t[RGBA8I] = { textureFormat: RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [BYTE], };\n t[RGB10_A2UI] = { textureFormat: RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [UNSIGNED_INT_2_10_10_10_REV], };\n t[RGBA16UI] = { textureFormat: RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [8], type: [UNSIGNED_SHORT$1], };\n t[RGBA16I] = { textureFormat: RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [8], type: [SHORT], };\n t[RGBA32I] = { textureFormat: RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [16], type: [INT$1], };\n t[RGBA32UI] = { textureFormat: RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [16], type: [UNSIGNED_INT$1], };\n // Sized Internal\n t[DEPTH_COMPONENT16$1] = { textureFormat: DEPTH_COMPONENT$1, colorRenderable: true, textureFilterable: false, bytesPerElement: [2, 4], type: [UNSIGNED_SHORT$1, UNSIGNED_INT$1], };\n t[DEPTH_COMPONENT24$1] = { textureFormat: DEPTH_COMPONENT$1, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [UNSIGNED_INT$1], };\n t[DEPTH_COMPONENT32F$1] = { textureFormat: DEPTH_COMPONENT$1, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [FLOAT$1], };\n t[DEPTH24_STENCIL8$1] = { textureFormat: DEPTH_STENCIL$1, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [UNSIGNED_INT_24_8], };\n t[DEPTH32F_STENCIL8$1] = { textureFormat: DEPTH_STENCIL$1, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [FLOAT_32_UNSIGNED_INT_24_8_REV], };\n\n Object.keys(t).forEach(function(internalFormat) {\n const info = t[internalFormat];\n info.bytesPerElementMap = {};\n info.bytesPerElement.forEach(function(bytesPerElement, ndx) {\n const type = info.type[ndx];\n info.bytesPerElementMap[type] = bytesPerElement;\n });\n });\n s_textureInternalFormatInfo = t;\n }\n return s_textureInternalFormatInfo[internalFormat];\n}\n\n/**\n * Gets the number of bytes per element for a given internalFormat / type\n * @param {number} internalFormat The internalFormat parameter from texImage2D etc..\n * @param {number} type The type parameter for texImage2D etc..\n * @return {number} the number of bytes per element for the given internalFormat, type combo\n * @memberOf module:twgl/textures\n */\nfunction getBytesPerElementForInternalFormat(internalFormat, type) {\n const info = getTextureInternalFormatInfo(internalFormat);\n if (!info) {\n throw \"unknown internal format\";\n }\n const bytesPerElement = info.bytesPerElementMap[type];\n if (bytesPerElement === undefined) {\n throw \"unknown internal format\";\n }\n return bytesPerElement;\n}\n\n/**\n * Info related to a specific texture internalFormat as returned\n * from {@link module:twgl/textures.getFormatAndTypeForInternalFormat}.\n *\n * @typedef {Object} TextureFormatInfo\n * @property {number} format Format to pass to texImage2D and related functions\n * @property {number} type Type to pass to texImage2D and related functions\n * @memberOf module:twgl/textures\n */\n\n/**\n * Gets the format and type for a given internalFormat\n *\n * @param {number} internalFormat The internal format\n * @return {module:twgl/textures.TextureFormatInfo} the corresponding format and type,\n * @memberOf module:twgl/textures\n */\nfunction getFormatAndTypeForInternalFormat(internalFormat) {\n const info = getTextureInternalFormatInfo(internalFormat);\n if (!info) {\n throw \"unknown internal format\";\n }\n return {\n format: info.textureFormat,\n type: info.type[0],\n };\n}\n\n/**\n * Returns true if value is power of 2\n * @param {number} value number to check.\n * @return true if value is power of 2\n * @private\n */\nfunction isPowerOf2(value) {\n return (value & (value - 1)) === 0;\n}\n\n/**\n * Gets whether or not we can generate mips for the given\n * internal format.\n *\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {number} width The width parameter from texImage2D etc..\n * @param {number} height The height parameter from texImage2D etc..\n * @param {number} internalFormat The internalFormat parameter from texImage2D etc..\n * @return {boolean} true if we can generate mips\n * @memberOf module:twgl/textures\n */\nfunction canGenerateMipmap(gl, width, height, internalFormat) {\n if (!isWebGL2(gl)) {\n return isPowerOf2(width) && isPowerOf2(height);\n }\n const info = getTextureInternalFormatInfo(internalFormat);\n if (!info) {\n throw \"unknown internal format\";\n }\n return info.colorRenderable && info.textureFilterable;\n}\n\n/**\n * Gets whether or not we can generate mips for the given format\n * @param {number} internalFormat The internalFormat parameter from texImage2D etc..\n * @return {boolean} true if we can generate mips\n * @memberOf module:twgl/textures\n */\nfunction canFilter(internalFormat) {\n const info = getTextureInternalFormatInfo(internalFormat);\n if (!info) {\n throw \"unknown internal format\";\n }\n return info.textureFilterable;\n}\n\n/**\n * Gets the number of components for a given image format.\n * @param {number} format the format.\n * @return {number} the number of components for the format.\n * @memberOf module:twgl/textures\n */\nfunction getNumComponentsForFormat(format) {\n const info = formatInfo[format];\n if (!info) {\n throw \"unknown format: \" + format;\n }\n return info.numColorComponents;\n}\n\n/**\n * Gets the texture type for a given array type.\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @return {number} the gl texture type\n * @private\n */\nfunction getTextureTypeForArrayType(gl, src, defaultType) {\n if (isArrayBuffer(src)) {\n return getGLTypeForTypedArray(src);\n }\n return defaultType || UNSIGNED_BYTE$1;\n}\n\nfunction guessDimensions(gl, target, width, height, numElements) {\n if (numElements % 1 !== 0) {\n throw \"can't guess dimensions\";\n }\n if (!width && !height) {\n const size = Math.sqrt(numElements / (target === TEXTURE_CUBE_MAP$1 ? 6 : 1));\n if (size % 1 === 0) {\n width = size;\n height = size;\n } else {\n width = numElements;\n height = 1;\n }\n } else if (!height) {\n height = numElements / width;\n if (height % 1) {\n throw \"can't guess dimensions\";\n }\n } else if (!width) {\n width = numElements / height;\n if (width % 1) {\n throw \"can't guess dimensions\";\n }\n }\n return {\n width: width,\n height: height,\n };\n}\n\n/**\n * Sets the default texture color.\n *\n * The default texture color is used when loading textures from\n * urls. Because the URL will be loaded async we'd like to be\n * able to use the texture immediately. By putting a 1x1 pixel\n * color in the texture we can start using the texture before\n * the URL has loaded.\n *\n * @param {number[]} color Array of 4 values in the range 0 to 1\n * @deprecated see {@link module:twgl.setDefaults}\n * @memberOf module:twgl/textures\n */\nfunction setDefaultTextureColor(color) {\n defaults$1.textureColor = new Uint8Array([color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255]);\n}\n\nfunction setDefaults$1(newDefaults) {\n copyExistingProperties(newDefaults, defaults$1);\n if (newDefaults.textureColor) {\n setDefaultTextureColor(newDefaults.textureColor);\n }\n}\n\n/**\n * A function to generate the source for a texture.\n * @callback TextureFunc\n * @param {WebGLRenderingContext} gl A WebGLRenderingContext\n * @param {module:twgl.TextureOptions} options the texture options\n * @return {*} Returns any of the things documented for `src` for {@link module:twgl.TextureOptions}.\n * @memberOf module:twgl\n */\n\n/**\n * Texture options passed to most texture functions. Each function will use whatever options\n * are appropriate for its needs. This lets you pass the same options to all functions.\n *\n * Note: A `TexImageSource` is defined in the WebGL spec as a `HTMLImageElement`, `HTMLVideoElement`,\n * `HTMLCanvasElement`, `ImageBitmap`, or `ImageData`.\n *\n * @typedef {Object} TextureOptions\n * @property {number} [target] the type of texture `gl.TEXTURE_2D` or `gl.TEXTURE_CUBE_MAP`. Defaults to `gl.TEXTURE_2D`.\n * @property {number} [level] the mip level to affect. Defaults to 0. Note, if set auto will be considered false unless explicitly set to true.\n * @property {number} [width] the width of the texture. Only used if src is an array or typed array or null.\n * @property {number} [height] the height of a texture. Only used if src is an array or typed array or null.\n * @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` .\n * @property {number} [min] the min filter setting (eg. `gl.LINEAR`). Defaults to `gl.NEAREST_MIPMAP_LINEAR`\n * or if texture is not a power of 2 on both dimensions then defaults to `gl.LINEAR`.\n * @property {number} [mag] the mag filter setting (eg. `gl.LINEAR`). Defaults to `gl.LINEAR`\n * @property {number} [minMag] both the min and mag filter settings.\n * @property {number} [internalFormat] internal format for texture. Defaults to `gl.RGBA`\n * @property {number} [format] format for texture. Defaults to `gl.RGBA`.\n * @property {number} [type] type for texture. Defaults to `gl.UNSIGNED_BYTE` unless `src` is ArrayBufferView. If `src`\n * is ArrayBufferView defaults to type that matches ArrayBufferView type.\n * @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\n * @property {number} [wrapS] Texture wrapping for S. Defaults to `gl.REPEAT` and `gl.CLAMP_TO_EDGE` for cube. If set takes precedence over `wrap`.\n * @property {number} [wrapT] Texture wrapping for T. Defaults to `gl.REPEAT` and `gl.CLAMP_TO_EDGE` for cube. If set takes precedence over `wrap`.\n * @property {number} [wrapR] Texture wrapping for R. Defaults to `gl.REPEAT` and `gl.CLAMP_TO_EDGE` for cube. If set takes precedence over `wrap`.\n * @property {number} [minLod] TEXTURE_MIN_LOD setting\n * @property {number} [maxLod] TEXTURE_MAX_LOD setting\n * @property {number} [baseLevel] TEXTURE_BASE_LEVEL setting\n * @property {number} [maxLevel] TEXTURE_MAX_LEVEL setting\n * @property {number} [compareFunc] TEXTURE_COMPARE_FUNC setting\n * @property {number} [compareMode] TEXTURE_COMPARE_MODE setting\n * @property {number} [unpackAlignment] The `gl.UNPACK_ALIGNMENT` used when uploading an array. Defaults to 1.\n * @property {number[]|ArrayBufferView} [color] Color to initialize this texture with if loading an image asynchronously.\n * The default use a blue 1x1 pixel texture. You can set another default by calling `twgl.setDefaults`\n * or you can set an individual texture's initial color by setting this property. Example: `[1, .5, .5, 1]` = pink\n * @property {number} [premultiplyAlpha] Whether or not to premultiply alpha. Defaults to whatever the current setting is.\n * This lets you set it once before calling `twgl.createTexture` or `twgl.createTextures` and only override\n * the current setting for specific textures.\n * @property {number} [flipY] Whether or not to flip the texture vertically on upload. Defaults to whatever the current setting is.\n * This lets you set it once before calling `twgl.createTexture` or `twgl.createTextures` and only override\n * the current setting for specific textures.\n * @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.\n * This lets you set it once before calling `twgl.createTexture` or `twgl.createTextures` and only override\n * the current setting for specific textures.\n * @property {boolean} [auto] If `undefined` or `true`, in WebGL1, texture filtering is set automatically for non-power of 2 images and\n * mips are generated for power of 2 images. In WebGL2 mips are generated if they can be. Note: if `level` is set above\n * then then `auto` is assumed to be `false` unless explicity set to `true`.\n * @property {number[]} [cubeFaceOrder] The order that cube faces are pulled out of an img or set of images. The default is\n *\n * [gl.TEXTURE_CUBE_MAP_POSITIVE_X,\n * gl.TEXTURE_CUBE_MAP_NEGATIVE_X,\n * gl.TEXTURE_CUBE_MAP_POSITIVE_Y,\n * gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,\n * gl.TEXTURE_CUBE_MAP_POSITIVE_Z,\n * gl.TEXTURE_CUBE_MAP_NEGATIVE_Z]\n *\n * @property {(number[]|ArrayBufferView|TexImageSource|TexImageSource[]|string|string[]|module:twgl.TextureFunc)} [src] source for texture\n *\n * If `string` then it's assumed to be a URL to an image. The image will be downloaded async. A usable\n * 1x1 pixel texture will be returned immediately. The texture will be updated once the image has downloaded.\n * If `target` is `gl.TEXTURE_CUBE_MAP` will attempt to divide image into 6 square pieces. 1x6, 6x1, 3x2, 2x3.\n * The pieces will be uploaded in `cubeFaceOrder`\n *\n * 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.\n *\n * If `string[]` or `TexImageSource[]` and target is `gl.TEXTURE_2D_ARRAY` then each entry is a slice of the a 2d array texture\n * and will be scaled to the specified width and height OR to the size of the first image that loads.\n *\n * If `TexImageSource` then it wil be used immediately to create the contents of the texture. Examples `HTMLImageElement`,\n * `HTMLCanvasElement`, `HTMLVideoElement`.\n *\n * If `number[]` or `ArrayBufferView` it's assumed to be data for a texture. If `width` or `height` is\n * not specified it is guessed as follows. First the number of elements is computed by `src.length / numComponents`\n * where `numComponents` is derived from `format`. If `target` is `gl.TEXTURE_CUBE_MAP` then `numElements` is divided\n * by 6. Then\n *\n * * If neither `width` nor `height` are specified and `sqrt(numElements)` is an integer then width and height\n * are set to `sqrt(numElements)`. Otherwise `width = numElements` and `height = 1`.\n *\n * * If only one of `width` or `height` is specified then the other equals `numElements / specifiedDimension`.\n *\n * If `number[]` will be converted to `type`.\n *\n * If `src` is a function it will be called with a `WebGLRenderingContext` and these options.\n * Whatever it returns is subject to these rules. So it can return a string url, an `HTMLElement`\n * an array etc...\n *\n * If `src` is undefined then an empty texture will be created of size `width` by `height`.\n *\n * @property {string} [crossOrigin] What to set the crossOrigin property of images when they are downloaded.\n * default: undefined. Also see {@link module:twgl.setDefaults}.\n *\n * @memberOf module:twgl\n */\n\n/**\n * Sets any packing state that will be set based on the options.\n * @param {module:twgl.TextureOptions} options A TextureOptions object with whatever parameters you want set.\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @private\n */\nfunction setPackState(gl, options) {\n if (options.colorspaceConversion !== undefined) {\n gl.pixelStorei(UNPACK_COLORSPACE_CONVERSION_WEBGL, options.colorspaceConversion);\n }\n if (options.premultiplyAlpha !== undefined) {\n gl.pixelStorei(UNPACK_PREMULTIPLY_ALPHA_WEBGL, options.premultiplyAlpha);\n }\n if (options.flipY !== undefined) {\n gl.pixelStorei(UNPACK_FLIP_Y_WEBGL, options.flipY);\n }\n}\n\n/**\n * Set skip state to defaults\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @private\n */\nfunction setSkipStateToDefault(gl) {\n gl.pixelStorei(UNPACK_ALIGNMENT, 4);\n if (isWebGL2(gl)) {\n gl.pixelStorei(UNPACK_ROW_LENGTH, 0);\n gl.pixelStorei(UNPACK_IMAGE_HEIGHT, 0);\n gl.pixelStorei(UNPACK_SKIP_PIXELS, 0);\n gl.pixelStorei(UNPACK_SKIP_ROWS, 0);\n gl.pixelStorei(UNPACK_SKIP_IMAGES, 0);\n }\n}\n\n/**\n * Sets the parameters of a texture or sampler\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {number|WebGLSampler} target texture target or sampler\n * @param {function()} parameteriFn texParameteri or samplerParameteri fn\n * @param {WebGLTexture} tex the WebGLTexture to set parameters for\n * @param {module:twgl.TextureOptions} options A TextureOptions object with whatever parameters you want set.\n * This is often the same options you passed in when you created the texture.\n * @private\n */\nfunction setTextureSamplerParameters(gl, target, parameteriFn, options) {\n if (options.minMag) {\n parameteriFn.call(gl, target, TEXTURE_MIN_FILTER, options.minMag);\n parameteriFn.call(gl, target, TEXTURE_MAG_FILTER, options.minMag);\n }\n if (options.min) {\n parameteriFn.call(gl, target, TEXTURE_MIN_FILTER, options.min);\n }\n if (options.mag) {\n parameteriFn.call(gl, target, TEXTURE_MAG_FILTER, options.mag);\n }\n if (options.wrap) {\n parameteriFn.call(gl, target, TEXTURE_WRAP_S, options.wrap);\n parameteriFn.call(gl, target, TEXTURE_WRAP_T, options.wrap);\n if (target === TEXTURE_3D$1 || isSampler(gl, target)) {\n parameteriFn.call(gl, target, TEXTURE_WRAP_R, options.wrap);\n }\n }\n if (options.wrapR) {\n parameteriFn.call(gl, target, TEXTURE_WRAP_R, options.wrapR);\n }\n if (options.wrapS) {\n parameteriFn.call(gl, target, TEXTURE_WRAP_S, options.wrapS);\n }\n if (options.wrapT) {\n parameteriFn.call(gl, target, TEXTURE_WRAP_T, options.wrapT);\n }\n if (options.minLod !== undefined) {\n parameteriFn.call(gl, target, TEXTURE_MIN_LOD, options.minLod);\n }\n if (options.maxLod !== undefined) {\n parameteriFn.call(gl, target, TEXTURE_MAX_LOD, options.maxLod);\n }\n if (options.baseLevel !== undefined) {\n parameteriFn.call(gl, target, TEXTURE_BASE_LEVEL, options.baseLevel);\n }\n if (options.maxLevel !== undefined) {\n parameteriFn.call(gl, target, TEXTURE_MAX_LEVEL, options.maxLevel);\n }\n if (options.compareFunc !== undefined) {\n parameteriFn.call(gl, target, TEXTURE_COMPARE_FUNC, options.compareFunc);\n }\n if (options.compareMode !== undefined) {\n parameteriFn.call(gl, target, TEXTURE_COMPARE_MODE, options.compareMode);\n }\n}\n\n/**\n * Sets the texture parameters of a texture.\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {WebGLTexture} tex the WebGLTexture to set parameters for\n * @param {module:twgl.TextureOptions} options A TextureOptions object with whatever parameters you want set.\n * This is often the same options you passed in when you created the texture.\n * @memberOf module:twgl/textures\n */\nfunction setTextureParameters(gl, tex, options) {\n const target = options.target || TEXTURE_2D$2;\n gl.bindTexture(target, tex);\n setTextureSamplerParameters(gl, target, gl.texParameteri, options);\n}\n\n/**\n * Sets the sampler parameters of a sampler.\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {WebGLSampler} sampler the WebGLSampler to set parameters for\n * @param {module:twgl.TextureOptions} options A TextureOptions object with whatever parameters you want set.\n * @memberOf module:twgl/textures\n */\nfunction setSamplerParameters(gl, sampler, options) {\n setTextureSamplerParameters(gl, sampler, gl.samplerParameteri, options);\n}\n\n/**\n * Creates a new sampler object and sets parameters.\n *\n * Example:\n *\n * const sampler = twgl.createSampler(gl, {\n * minMag: gl.NEAREST, // sets both TEXTURE_MIN_FILTER and TEXTURE_MAG_FILTER\n * wrap: gl.CLAMP_TO_NEAREST, // sets both TEXTURE_WRAP_S and TEXTURE_WRAP_T and TEXTURE_WRAP_R\n * });\n *\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {Object.} options A object of TextureOptions one per sampler.\n * @return {Object.} the created samplers by name\n * @private\n */\nfunction createSampler(gl, options) {\n const sampler = gl.createSampler();\n setSamplerParameters(gl, sampler, options);\n return sampler;\n}\n\n/**\n * Creates a multiple sampler objects and sets parameters on each.\n *\n * Example:\n *\n * const samplers = twgl.createSamplers(gl, {\n * nearest: {\n * minMag: gl.NEAREST,\n * },\n * nearestClampS: {\n * minMag: gl.NEAREST,\n * wrapS: gl.CLAMP_TO_NEAREST,\n * },\n * linear: {\n * minMag: gl.LINEAR,\n * },\n * nearestClamp: {\n * minMag: gl.NEAREST,\n * wrap: gl.CLAMP_TO_EDGE,\n * },\n * linearClamp: {\n * minMag: gl.LINEAR,\n * wrap: gl.CLAMP_TO_EDGE,\n * },\n * linearClampT: {\n * minMag: gl.LINEAR,\n * wrapT: gl.CLAMP_TO_EDGE,\n * },\n * });\n *\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {module:twgl.TextureOptions} [options] A TextureOptions object with whatever parameters you want set on the sampler\n * @private\n */\nfunction createSamplers(gl, samplerOptions) {\n const samplers = {};\n Object.keys(samplerOptions).forEach(function(name) {\n samplers[name] = createSampler(gl, samplerOptions[name]);\n });\n return samplers;\n}\n\n/**\n * Makes a 1x1 pixel\n * If no color is passed in uses the default color which can be set by calling `setDefaultTextureColor`.\n * @param {(number[]|ArrayBufferView)} [color] The color using 0-1 values\n * @return {Uint8Array} Unit8Array with color.\n * @private\n */\nfunction make1Pixel(color) {\n color = color || defaults$1.textureColor;\n if (isArrayBuffer(color)) {\n return color;\n }\n return new Uint8Array([color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255]);\n}\n\n/**\n * Sets filtering or generates mips for texture based on width or height\n * If width or height is not passed in uses `options.width` and//or `options.height`\n *\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {WebGLTexture} tex the WebGLTexture to set parameters for\n * @param {module:twgl.TextureOptions} [options] A TextureOptions object with whatever parameters you want set.\n * This is often the same options you passed in when you created the texture.\n * @param {number} [width] width of texture\n * @param {number} [height] height of texture\n * @param {number} [internalFormat] The internalFormat parameter from texImage2D etc..\n * @memberOf module:twgl/textures\n */\nfunction setTextureFilteringForSize(gl, tex, options, width, height, internalFormat) {\n options = options || defaults$1.textureOptions;\n internalFormat = internalFormat || RGBA$1;\n const target = options.target || TEXTURE_2D$2;\n width = width || options.width;\n height = height || options.height;\n gl.bindTexture(target, tex);\n if (canGenerateMipmap(gl, width, height, internalFormat)) {\n gl.generateMipmap(target);\n } else {\n const filtering = canFilter(internalFormat) ? LINEAR$1 : NEAREST;\n gl.texParameteri(target, TEXTURE_MIN_FILTER, filtering);\n gl.texParameteri(target, TEXTURE_MAG_FILTER, filtering);\n gl.texParameteri(target, TEXTURE_WRAP_S, CLAMP_TO_EDGE$1);\n gl.texParameteri(target, TEXTURE_WRAP_T, CLAMP_TO_EDGE$1);\n }\n}\n\nfunction shouldAutomaticallySetTextureFilteringForSize(options) {\n return options.auto === true || (options.auto === undefined && options.level === undefined);\n}\n\n/**\n * Gets an array of cubemap face enums\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {module:twgl.TextureOptions} options A TextureOptions object with whatever parameters you want set.\n * This is often the same options you passed in when you created the texture.\n * @return {number[]} cubemap face enums\n * @private\n */\nfunction getCubeFaceOrder(gl, options) {\n options = options || {};\n return options.cubeFaceOrder || [\n TEXTURE_CUBE_MAP_POSITIVE_X,\n TEXTURE_CUBE_MAP_NEGATIVE_X,\n TEXTURE_CUBE_MAP_POSITIVE_Y,\n TEXTURE_CUBE_MAP_NEGATIVE_Y,\n TEXTURE_CUBE_MAP_POSITIVE_Z,\n TEXTURE_CUBE_MAP_NEGATIVE_Z,\n ];\n}\n\n/**\n * @typedef {Object} FaceInfo\n * @property {number} face gl enum for texImage2D\n * @property {number} ndx face index (0 - 5) into source data\n * @ignore\n */\n\n/**\n * Gets an array of FaceInfos\n * There's a bug in some NVidia drivers that will crash the driver if\n * `gl.TEXTURE_CUBE_MAP_POSITIVE_X` is not uploaded first. So, we take\n * the user's desired order from his faces to WebGL and make sure we\n * do the faces in WebGL order\n *\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {module:twgl.TextureOptions} options A TextureOptions object with whatever parameters you want set.\n * @return {FaceInfo[]} cubemap face infos. Arguably the `face` property of each element is redundant but\n * it's needed internally to sort the array of `ndx` properties by `face`.\n * @private\n */\nfunction getCubeFacesWithNdx(gl, options) {\n const faces = getCubeFaceOrder(gl, options);\n // work around bug in NVidia drivers. We have to upload the first face first else the driver crashes :(\n const facesWithNdx = faces.map(function(face, ndx) {\n return { face: face, ndx: ndx };\n });\n facesWithNdx.sort(function(a, b) {\n return a.face - b.face;\n });\n return facesWithNdx;\n}\n\n/**\n * Set a texture from the contents of an element. Will also set\n * texture filtering or generate mips based on the dimensions of the element\n * unless `options.auto === false`. If `target === gl.TEXTURE_CUBE_MAP` will\n * attempt to slice image into 1x6, 2x3, 3x2, or 6x1 images, one for each face.\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {WebGLTexture} tex the WebGLTexture to set parameters for\n * @param {HTMLElement} element a canvas, img, or video element.\n * @param {module:twgl.TextureOptions} [options] A TextureOptions object with whatever parameters you want set.\n * This is often the same options you passed in when you created the texture.\n * @memberOf module:twgl/textures\n * @kind function\n */\nfunction setTextureFromElement(gl, tex, element, options) {\n options = options || defaults$1.textureOptions;\n const target = options.target || TEXTURE_2D$2;\n const level = options.level || 0;\n let width = element.width;\n let height = element.height;\n const internalFormat = options.internalFormat || options.format || RGBA$1;\n const formatType = getFormatAndTypeForInternalFormat(internalFormat);\n const format = options.format || formatType.format;\n const type = options.type || formatType.type;\n setPackState(gl, options);\n gl.bindTexture(target, tex);\n if (target === TEXTURE_CUBE_MAP$1) {\n // guess the parts\n const imgWidth = element.width;\n const imgHeight = element.height;\n let size;\n let slices;\n if (imgWidth / 6 === imgHeight) {\n // It's 6x1\n size = imgHeight;\n slices = [0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0];\n } else if (imgHeight / 6 === imgWidth) {\n // It's 1x6\n size = imgWidth;\n slices = [0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5];\n } else if (imgWidth / 3 === imgHeight / 2) {\n // It's 3x2\n size = imgWidth / 3;\n slices = [0, 0, 1, 0, 2, 0, 0, 1, 1, 1, 2, 1];\n } else if (imgWidth / 2 === imgHeight / 3) {\n // It's 2x3\n size = imgWidth / 2;\n slices = [0, 0, 1, 0, 0, 1, 1, 1, 0, 2, 1, 2];\n } else {\n throw \"can't figure out cube map from element: \" + (element.src ? element.src : element.nodeName);\n }\n const ctx = getShared2DContext();\n if (ctx) {\n ctx.canvas.width = size;\n ctx.canvas.height = size;\n width = size;\n height = size;\n getCubeFacesWithNdx(gl, options).forEach(function(f) {\n const xOffset = slices[f.ndx * 2 + 0] * size;\n const yOffset = slices[f.ndx * 2 + 1] * size;\n ctx.drawImage(element, xOffset, yOffset, size, size, 0, 0, size, size);\n gl.texImage2D(f.face, level, internalFormat, format, type, ctx.canvas);\n });\n // Free up the canvas memory\n ctx.canvas.width = 1;\n ctx.canvas.height = 1;\n } else if (typeof createImageBitmap !== 'undefined') {\n // NOTE: It seems like we should prefer ImageBitmap because unlike canvas it's\n // note lossy? (alpha is not premultiplied? although I'm not sure what\n width = size;\n height = size;\n getCubeFacesWithNdx(gl, options).forEach(function(f) {\n const xOffset = slices[f.ndx * 2 + 0] * size;\n const yOffset = slices[f.ndx * 2 + 1] * size;\n // We can't easily use a default texture color here as it would have to match\n // the type across all faces where as with a 2D one there's only one face\n // so we're replacing everything all at once. It also has to be the correct size.\n // On the other hand we need all faces to be the same size so as one face loads\n // the rest match else the texture will be un-renderable.\n gl.texImage2D(f.face, level, internalFormat, size, size, 0, format, type, null);\n createImageBitmap(element, xOffset, yOffset, size, size, {\n premultiplyAlpha: 'none',\n colorSpaceConversion: 'none',\n })\n .then(function(imageBitmap) {\n setPackState(gl, options);\n gl.bindTexture(target, tex);\n gl.texImage2D(f.face, level, internalFormat, format, type, imageBitmap);\n if (shouldAutomaticallySetTextureFilteringForSize(options)) {\n setTextureFilteringForSize(gl, tex, options, width, height, internalFormat);\n }\n });\n });\n }\n } else if (target === TEXTURE_3D$1 || target === TEXTURE_2D_ARRAY$1) {\n const smallest = Math.min(element.width, element.height);\n const largest = Math.max(element.width, element.height);\n const depth = largest / smallest;\n if (depth % 1 !== 0) {\n throw \"can not compute 3D dimensions of element\";\n }\n const xMult = element.width === largest ? 1 : 0;\n const yMult = element.height === largest ? 1 : 0;\n gl.pixelStorei(UNPACK_ALIGNMENT, 1);\n gl.pixelStorei(UNPACK_ROW_LENGTH, element.width);\n gl.pixelStorei(UNPACK_IMAGE_HEIGHT, 0);\n gl.pixelStorei(UNPACK_SKIP_IMAGES, 0);\n gl.texImage3D(target, level, internalFormat, smallest, smallest, smallest, 0, format, type, null);\n for (let d = 0; d < depth; ++d) {\n const srcX = d * smallest * xMult;\n const srcY = d * smallest * yMult;\n gl.pixelStorei(UNPACK_SKIP_PIXELS, srcX);\n gl.pixelStorei(UNPACK_SKIP_ROWS, srcY);\n gl.texSubImage3D(target, level, 0, 0, d, smallest, smallest, 1, format, type, element);\n }\n setSkipStateToDefault(gl);\n } else {\n gl.texImage2D(target, level, internalFormat, format, type, element);\n }\n if (shouldAutomaticallySetTextureFilteringForSize(options)) {\n setTextureFilteringForSize(gl, tex, options, width, height, internalFormat);\n }\n setTextureParameters(gl, tex, options);\n}\n\nfunction noop() {\n}\n\n/**\n * Checks whether the url's origin is the same so that we can set the `crossOrigin`\n * @param {string} url url to image\n * @returns {boolean} true if the window's origin is the same as image's url\n * @private\n */\nfunction urlIsSameOrigin(url) {\n if (typeof document !== 'undefined') {\n // for IE really\n const a = document.createElement('a');\n a.href = url;\n return a.hostname === location.hostname &&\n a.port === location.port &&\n a.protocol === location.protocol;\n } else {\n const localOrigin = (new URL(location.href)).origin;\n const urlOrigin = (new URL(url, location.href)).origin;\n return urlOrigin === localOrigin;\n }\n}\n\nfunction setToAnonymousIfUndefinedAndURLIsNotSameOrigin(url, crossOrigin) {\n return crossOrigin === undefined && !urlIsSameOrigin(url)\n ? 'anonymous'\n : crossOrigin;\n}\n\n/**\n * Loads an image\n * @param {string} url url to image\n * @param {string} crossOrigin\n * @param {function(err, img)} [callback] a callback that's passed an error and the image. The error will be non-null\n * if there was an error\n * @return {HTMLImageElement} the image being loaded.\n * @private\n */\nfunction loadImage(url, crossOrigin, callback) {\n callback = callback || noop;\n let img;\n crossOrigin = crossOrigin !== undefined ? crossOrigin : defaults$1.crossOrigin;\n crossOrigin = setToAnonymousIfUndefinedAndURLIsNotSameOrigin(url, crossOrigin);\n if (typeof Image !== 'undefined') {\n img = new Image();\n if (crossOrigin !== undefined) {\n img.crossOrigin = crossOrigin;\n }\n\n const clearEventHandlers = function clearEventHandlers() {\n img.removeEventListener('error', onError); // eslint-disable-line\n img.removeEventListener('load', onLoad); // eslint-disable-line\n img = null;\n };\n\n const onError = function onError() {\n const msg = \"couldn't load image: \" + url;\n error$1(msg);\n callback(msg, img);\n clearEventHandlers();\n };\n\n const onLoad = function onLoad() {\n callback(null, img);\n clearEventHandlers();\n };\n\n img.addEventListener('error', onError);\n img.addEventListener('load', onLoad);\n img.src = url;\n return img;\n } else if (typeof ImageBitmap !== 'undefined') {\n let err;\n let bm;\n const cb = function cb() {\n callback(err, bm);\n };\n\n const options = {};\n if (crossOrigin) {\n options.mode = 'cors'; // TODO: not sure how to translate image.crossOrigin\n }\n fetch(url, options).then(function(response) {\n if (!response.ok) {\n throw response;\n }\n return response.blob();\n }).then(function(blob) {\n return createImageBitmap(blob, {\n premultiplyAlpha: 'none',\n colorSpaceConversion: 'none',\n });\n }).then(function(bitmap) {\n // not sure if this works. We don't want\n // to catch the user's error. So, call\n // the callback in a timeout so we're\n // not in this scope inside the promise.\n bm = bitmap;\n setTimeout(cb);\n }).catch(function(e) {\n err = e;\n setTimeout(cb);\n });\n img = null;\n }\n return img;\n}\n\n/**\n * check if object is a TexImageSource\n *\n * @param {Object} obj Object to test\n * @return {boolean} true if object is a TexImageSource\n * @private\n */\nfunction isTexImageSource(obj) {\n return (typeof ImageBitmap !== 'undefined' && obj instanceof ImageBitmap) ||\n (typeof ImageData !== 'undefined' && obj instanceof ImageData) ||\n (typeof HTMLElement !== 'undefined' && obj instanceof HTMLElement);\n}\n\n/**\n * if obj is an TexImageSource then just\n * uses it otherwise if obj is a string\n * then load it first.\n *\n * @param {string|TexImageSource} obj\n * @param {string} crossOrigin\n * @param {function(err, img)} [callback] a callback that's passed an error and the image. The error will be non-null\n * if there was an error\n * @private\n */\nfunction loadAndUseImage(obj, crossOrigin, callback) {\n if (isTexImageSource(obj)) {\n setTimeout(function() {\n callback(null, obj);\n });\n return obj;\n }\n\n return loadImage(obj, crossOrigin, callback);\n}\n\n/**\n * Sets a texture to a 1x1 pixel color. If `options.color === false` is nothing happens. If it's not set\n * the default texture color is used which can be set by calling `setDefaultTextureColor`.\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {WebGLTexture} tex the WebGLTexture to set parameters for\n * @param {module:twgl.TextureOptions} [options] A TextureOptions object with whatever parameters you want set.\n * This is often the same options you passed in when you created the texture.\n * @memberOf module:twgl/textures\n * @private\n */\nfunction setTextureTo1PixelColor(gl, tex, options) {\n options = options || defaults$1.textureOptions;\n const target = options.target || TEXTURE_2D$2;\n gl.bindTexture(target, tex);\n if (options.color === false) {\n return;\n }\n // Assume it's a URL\n // Put 1x1 pixels in texture. That makes it renderable immediately regardless of filtering.\n const color = make1Pixel(options.color);\n if (target === TEXTURE_CUBE_MAP$1) {\n for (let ii = 0; ii < 6; ++ii) {\n gl.texImage2D(TEXTURE_CUBE_MAP_POSITIVE_X + ii, 0, RGBA$1, 1, 1, 0, RGBA$1, UNSIGNED_BYTE$1, color);\n }\n } else if (target === TEXTURE_3D$1 || target === TEXTURE_2D_ARRAY$1) {\n gl.texImage3D(target, 0, RGBA$1, 1, 1, 1, 0, RGBA$1, UNSIGNED_BYTE$1, color);\n } else {\n gl.texImage2D(target, 0, RGBA$1, 1, 1, 0, RGBA$1, UNSIGNED_BYTE$1, color);\n }\n}\n\n/**\n * The src image(s) used to create a texture.\n *\n * When you call {@link module:twgl.createTexture} or {@link module:twgl.createTextures}\n * you can pass in urls for images to load into the textures. If it's a single url\n * then this will be a single HTMLImageElement. If it's an array of urls used for a cubemap\n * this will be a corresponding array of images for the cubemap.\n *\n * @typedef {HTMLImageElement|HTMLImageElement[]} TextureSrc\n * @memberOf module:twgl\n */\n\n/**\n * A callback for when an image finished downloading and been uploaded into a texture\n * @callback TextureReadyCallback\n * @param {*} err If truthy there was an error.\n * @param {WebGLTexture} texture the texture.\n * @param {module:twgl.TextureSrc} source image(s) used to as the src for the texture\n * @memberOf module:twgl\n */\n\n/**\n * A callback for when all images have finished downloading and been uploaded into their respective textures\n * @callback TexturesReadyCallback\n * @param {*} err If truthy there was an error.\n * @param {Object.} textures the created textures by name. Same as returned by {@link module:twgl.createTextures}.\n * @param {Object.} sources the image(s) used for the texture by name.\n * @memberOf module:twgl\n */\n\n/**\n * A callback for when an image finished downloading and been uploaded into a texture\n * @callback CubemapReadyCallback\n * @param {*} err If truthy there was an error.\n * @param {WebGLTexture} tex the texture.\n * @param {HTMLImageElement[]} imgs the images for each face.\n * @memberOf module:twgl\n */\n\n/**\n * A callback for when an image finished downloading and been uploaded into a texture\n * @callback ThreeDReadyCallback\n * @param {*} err If truthy there was an error.\n * @param {WebGLTexture} tex the texture.\n * @param {HTMLImageElement[]} imgs the images for each slice.\n * @memberOf module:twgl\n */\n\n/**\n * Loads a texture from an image from a Url as specified in `options.src`\n * If `options.color !== false` will set the texture to a 1x1 pixel color so that the texture is\n * immediately useable. It will be updated with the contents of the image once the image has finished\n * downloading. Filtering options will be set as appropriate for image unless `options.auto === false`.\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {WebGLTexture} tex the WebGLTexture to set parameters for\n * @param {module:twgl.TextureOptions} [options] A TextureOptions object with whatever parameters you want set.\n * @param {module:twgl.TextureReadyCallback} [callback] A function to be called when the image has finished loading. err will\n * be non null if there was an error.\n * @return {HTMLImageElement} the image being downloaded.\n * @memberOf module:twgl/textures\n */\nfunction loadTextureFromUrl(gl, tex, options, callback) {\n callback = callback || noop;\n options = options || defaults$1.textureOptions;\n setTextureTo1PixelColor(gl, tex, options);\n // Because it's async we need to copy the options.\n options = Object.assign({}, options);\n const img = loadAndUseImage(options.src, options.crossOrigin, function(err, img) {\n if (err) {\n callback(err, tex, img);\n } else {\n setTextureFromElement(gl, tex, img, options);\n callback(null, tex, img);\n }\n });\n return img;\n}\n\n/**\n * Loads a cubemap from 6 urls or TexImageSources as specified in `options.src`. Will set the cubemap to a 1x1 pixel color\n * so that it is usable immediately unless `option.color === false`.\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {WebGLTexture} tex the WebGLTexture to set parameters for\n * @param {module:twgl.TextureOptions} options A TextureOptions object with whatever parameters you want set.\n * @param {module:twgl.CubemapReadyCallback} [callback] A function to be called when all the images have finished loading. err will\n * be non null if there was an error.\n * @memberOf module:twgl/textures\n * @private\n */\nfunction loadCubemapFromUrls(gl, tex, options, callback) {\n callback = callback || noop;\n const urls = options.src;\n if (urls.length !== 6) {\n throw \"there must be 6 urls for a cubemap\";\n }\n const level = options.level || 0;\n const internalFormat = options.internalFormat || options.format || RGBA$1;\n const formatType = getFormatAndTypeForInternalFormat(internalFormat);\n const format = options.format || formatType.format;\n const type = options.type || UNSIGNED_BYTE$1;\n const target = options.target || TEXTURE_2D$2;\n if (target !== TEXTURE_CUBE_MAP$1) {\n throw \"target must be TEXTURE_CUBE_MAP\";\n }\n setTextureTo1PixelColor(gl, tex, options);\n // Because it's async we need to copy the options.\n options = Object.assign({}, options);\n let numToLoad = 6;\n const errors = [];\n const faces = getCubeFaceOrder(gl, options);\n let imgs; // eslint-disable-line\n\n function uploadImg(faceTarget) {\n return function(err, img) {\n --numToLoad;\n if (err) {\n errors.push(err);\n } else {\n if (img.width !== img.height) {\n errors.push(\"cubemap face img is not a square: \" + img.src);\n } else {\n setPackState(gl, options);\n gl.bindTexture(target, tex);\n\n // So assuming this is the first image we now have one face that's img sized\n // and 5 faces that are 1x1 pixel so size the other faces\n if (numToLoad === 5) {\n // use the default order\n getCubeFaceOrder().forEach(function(otherTarget) {\n // Should we re-use the same face or a color?\n gl.texImage2D(otherTarget, level, internalFormat, format, type, img);\n });\n } else {\n gl.texImage2D(faceTarget, level, internalFormat, format, type, img);\n }\n\n if (shouldAutomaticallySetTextureFilteringForSize(options)) {\n gl.generateMipmap(target);\n }\n }\n }\n\n if (numToLoad === 0) {\n callback(errors.length ? errors : undefined, tex, imgs);\n }\n };\n }\n\n imgs = urls.map(function(url, ndx) {\n return loadAndUseImage(url, options.crossOrigin, uploadImg(faces[ndx]));\n });\n}\n\n/**\n * Loads a 2d array or 3d texture from urls OR TexImageSources as specified in `options.src`.\n * Will set the texture to a 1x1 pixel color\n * so that it is usable immediately unless `option.color === false`.\n *\n * If the width and height is not specified the width and height of the first\n * image loaded will be used. Note that since images are loaded async\n * which image downloads first is unknown.\n *\n * If an image is not the same size as the width and height it will be scaled\n * to that width and height.\n *\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {WebGLTexture} tex the WebGLTexture to set parameters for\n * @param {module:twgl.TextureOptions} options A TextureOptions object with whatever parameters you want set.\n * @param {module:twgl.ThreeDReadyCallback} [callback] A function to be called when all the images have finished loading. err will\n * be non null if there was an error.\n * @memberOf module:twgl/textures\n * @private\n */\nfunction loadSlicesFromUrls(gl, tex, options, callback) {\n callback = callback || noop;\n const urls = options.src;\n const internalFormat = options.internalFormat || options.format || RGBA$1;\n const formatType = getFormatAndTypeForInternalFormat(internalFormat);\n const format = options.format || formatType.format;\n const type = options.type || UNSIGNED_BYTE$1;\n const target = options.target || TEXTURE_2D_ARRAY$1;\n if (target !== TEXTURE_3D$1 && target !== TEXTURE_2D_ARRAY$1) {\n throw \"target must be TEXTURE_3D or TEXTURE_2D_ARRAY\";\n }\n setTextureTo1PixelColor(gl, tex, options);\n // Because it's async we need to copy the options.\n options = Object.assign({}, options);\n let numToLoad = urls.length;\n const errors = [];\n let imgs; // eslint-disable-line\n const level = options.level || 0;\n let width = options.width;\n let height = options.height;\n const depth = urls.length;\n let firstImage = true;\n\n function uploadImg(slice) {\n return function(err, img) {\n --numToLoad;\n if (err) {\n errors.push(err);\n } else {\n setPackState(gl, options);\n gl.bindTexture(target, tex);\n\n if (firstImage) {\n firstImage = false;\n width = options.width || img.width;\n height = options.height || img.height;\n gl.texImage3D(target, level, internalFormat, width, height, depth, 0, format, type, null);\n\n // put it in every slice otherwise some slices will be 0,0,0,0\n for (let s = 0; s < depth; ++s) {\n gl.texSubImage3D(target, level, 0, 0, s, width, height, 1, format, type, img);\n }\n } else {\n let src = img;\n let ctx;\n if (img.width !== width || img.height !== height) {\n // Size the image to fix\n ctx = getShared2DContext();\n src = ctx.canvas;\n ctx.canvas.width = width;\n ctx.canvas.height = height;\n ctx.drawImage(img, 0, 0, width, height);\n }\n\n gl.texSubImage3D(target, level, 0, 0, slice, width, height, 1, format, type, src);\n\n // free the canvas memory\n if (ctx && src === ctx.canvas) {\n ctx.canvas.width = 0;\n ctx.canvas.height = 0;\n }\n }\n\n if (shouldAutomaticallySetTextureFilteringForSize(options)) {\n gl.generateMipmap(target);\n }\n }\n\n if (numToLoad === 0) {\n callback(errors.length ? errors : undefined, tex, imgs);\n }\n };\n }\n\n imgs = urls.map(function(url, ndx) {\n return loadAndUseImage(url, options.crossOrigin, uploadImg(ndx));\n });\n}\n\n/**\n * Sets a texture from an array or typed array. If the width or height is not provided will attempt to\n * guess the size. See {@link module:twgl.TextureOptions}.\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {WebGLTexture} tex the WebGLTexture to set parameters for\n * @param {(number[]|ArrayBufferView)} src An array or typed arry with texture data.\n * @param {module:twgl.TextureOptions} [options] A TextureOptions object with whatever parameters you want set.\n * This is often the same options you passed in when you created the texture.\n * @memberOf module:twgl/textures\n */\nfunction setTextureFromArray(gl, tex, src, options) {\n options = options || defaults$1.textureOptions;\n const target = options.target || TEXTURE_2D$2;\n gl.bindTexture(target, tex);\n let width = options.width;\n let height = options.height;\n let depth = options.depth;\n const level = options.level || 0;\n const internalFormat = options.internalFormat || options.format || RGBA$1;\n const formatType = getFormatAndTypeForInternalFormat(internalFormat);\n const format = options.format || formatType.format;\n const type = options.type || getTextureTypeForArrayType(gl, src, formatType.type);\n if (!isArrayBuffer(src)) {\n const Type = getTypedArrayTypeForGLType(type);\n src = new Type(src);\n } else if (src instanceof Uint8ClampedArray) {\n src = new Uint8Array(src.buffer);\n }\n\n const bytesPerElement = getBytesPerElementForInternalFormat(internalFormat, type);\n const numElements = src.byteLength / bytesPerElement; // TODO: check UNPACK_ALIGNMENT?\n if (numElements % 1) {\n throw \"length wrong size for format: \" + glEnumToString(gl, format);\n }\n let dimensions;\n if (target === TEXTURE_3D$1 || target === TEXTURE_2D_ARRAY$1) {\n if (!width && !height && !depth) {\n const size = Math.cbrt(numElements);\n if (size % 1 !== 0) {\n throw \"can't guess cube size of array of numElements: \" + numElements;\n }\n width = size;\n height = size;\n depth = size;\n } else if (width && (!height || !depth)) {\n dimensions = guessDimensions(gl, target, height, depth, numElements / width);\n height = dimensions.width;\n depth = dimensions.height;\n } else if (height && (!width || !depth)) {\n dimensions = guessDimensions(gl, target, width, depth, numElements / height);\n width = dimensions.width;\n depth = dimensions.height;\n } else {\n dimensions = guessDimensions(gl, target, width, height, numElements / depth);\n width = dimensions.width;\n height = dimensions.height;\n }\n } else {\n dimensions = guessDimensions(gl, target, width, height, numElements);\n width = dimensions.width;\n height = dimensions.height;\n }\n setSkipStateToDefault(gl);\n gl.pixelStorei(UNPACK_ALIGNMENT, options.unpackAlignment || 1);\n setPackState(gl, options);\n if (target === TEXTURE_CUBE_MAP$1) {\n const elementsPerElement = bytesPerElement / src.BYTES_PER_ELEMENT;\n const faceSize = numElements / 6 * elementsPerElement;\n\n getCubeFacesWithNdx(gl, options).forEach(f => {\n const offset = faceSize * f.ndx;\n const data = src.subarray(offset, offset + faceSize);\n gl.texImage2D(f.face, level, internalFormat, width, height, 0, format, type, data);\n });\n } else if (target === TEXTURE_3D$1 || target === TEXTURE_2D_ARRAY$1) {\n gl.texImage3D(target, level, internalFormat, width, height, depth, 0, format, type, src);\n } else {\n gl.texImage2D(target, level, internalFormat, width, height, 0, format, type, src);\n }\n return {\n width: width,\n height: height,\n depth: depth,\n type: type,\n };\n}\n\n/**\n * Sets a texture with no contents of a certain size. In other words calls `gl.texImage2D` with `null`.\n * You must set `options.width` and `options.height`.\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {WebGLTexture} tex the WebGLTexture to set parameters for\n * @param {module:twgl.TextureOptions} options A TextureOptions object with whatever parameters you want set.\n * @memberOf module:twgl/textures\n */\nfunction setEmptyTexture(gl, tex, options) {\n const target = options.target || TEXTURE_2D$2;\n gl.bindTexture(target, tex);\n const level = options.level || 0;\n const internalFormat = options.internalFormat || options.format || RGBA$1;\n const formatType = getFormatAndTypeForInternalFormat(internalFormat);\n const format = options.format || formatType.format;\n const type = options.type || formatType.type;\n setPackState(gl, options);\n if (target === TEXTURE_CUBE_MAP$1) {\n for (let ii = 0; ii < 6; ++ii) {\n gl.texImage2D(TEXTURE_CUBE_MAP_POSITIVE_X + ii, level, internalFormat, options.width, options.height, 0, format, type, null);\n }\n } else if (target === TEXTURE_3D$1 || target === TEXTURE_2D_ARRAY$1) {\n gl.texImage3D(target, level, internalFormat, options.width, options.height, options.depth, 0, format, type, null);\n } else {\n gl.texImage2D(target, level, internalFormat, options.width, options.height, 0, format, type, null);\n }\n}\n\n/**\n * Creates a texture based on the options passed in.\n *\n * Note: may reset UNPACK_ALIGNMENT, UNPACK_ROW_LENGTH, UNPACK_IMAGE_HEIGHT, UNPACK_SKIP_IMAGES\n * UNPACK_SKIP_PIXELS, and UNPACK_SKIP_ROWS\n *\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {module:twgl.TextureOptions} [options] A TextureOptions object with whatever parameters you want set.\n * @param {module:twgl.TextureReadyCallback} [callback] A callback called when an image has been downloaded and uploaded to the texture.\n * @return {WebGLTexture} the created texture.\n * @memberOf module:twgl/textures\n */\nfunction createTexture(gl, options, callback) {\n callback = callback || noop;\n options = options || defaults$1.textureOptions;\n const tex = gl.createTexture();\n const target = options.target || TEXTURE_2D$2;\n let width = options.width || 1;\n let height = options.height || 1;\n const internalFormat = options.internalFormat || RGBA$1;\n gl.bindTexture(target, tex);\n if (target === TEXTURE_CUBE_MAP$1) {\n // this should have been the default for cubemaps :(\n gl.texParameteri(target, TEXTURE_WRAP_S, CLAMP_TO_EDGE$1);\n gl.texParameteri(target, TEXTURE_WRAP_T, CLAMP_TO_EDGE$1);\n }\n let src = options.src;\n if (src) {\n if (typeof src === \"function\") {\n src = src(gl, options);\n }\n if (typeof (src) === \"string\") {\n loadTextureFromUrl(gl, tex, options, callback);\n } else if (isArrayBuffer(src) ||\n (Array.isArray(src) && (\n typeof src[0] === 'number' ||\n Array.isArray(src[0]) ||\n isArrayBuffer(src[0]))\n )\n ) {\n const dimensions = setTextureFromArray(gl, tex, src, options);\n width = dimensions.width;\n height = dimensions.height;\n } else if (Array.isArray(src) && (typeof (src[0]) === 'string' || isTexImageSource(src[0]))) {\n if (target === TEXTURE_CUBE_MAP$1) {\n loadCubemapFromUrls(gl, tex, options, callback);\n } else {\n loadSlicesFromUrls(gl, tex, options, callback);\n }\n } else { // if (isTexImageSource(src))\n setTextureFromElement(gl, tex, src, options);\n width = src.width;\n height = src.height;\n }\n } else {\n setEmptyTexture(gl, tex, options);\n }\n if (shouldAutomaticallySetTextureFilteringForSize(options)) {\n setTextureFilteringForSize(gl, tex, options, width, height, internalFormat);\n }\n setTextureParameters(gl, tex, options);\n return tex;\n}\n\n/**\n * Resizes a texture based on the options passed in.\n *\n * Note: This is not a generic resize anything function.\n * It's mostly used by {@link module:twgl.resizeFramebufferInfo}\n * It will use `options.src` if it exists to try to determine a `type`\n * otherwise it will assume `gl.UNSIGNED_BYTE`. No data is provided\n * for the texture. Texture parameters will be set accordingly\n *\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {WebGLTexture} tex the texture to resize\n * @param {module:twgl.TextureOptions} options A TextureOptions object with whatever parameters you want set.\n * @param {number} [width] the new width. If not passed in will use `options.width`\n * @param {number} [height] the new height. If not passed in will use `options.height`\n * @param {number} [depth] the new depth. If not passed in will use `options.depth`\n * @memberOf module:twgl/textures\n */\nfunction resizeTexture(gl, tex, options, width, height, depth) {\n width = width || options.width;\n height = height || options.height;\n depth = depth || options.depth;\n const target = options.target || TEXTURE_2D$2;\n gl.bindTexture(target, tex);\n const level = options.level || 0;\n const internalFormat = options.internalFormat || options.format || RGBA$1;\n const formatType = getFormatAndTypeForInternalFormat(internalFormat);\n const format = options.format || formatType.format;\n let type;\n const src = options.src;\n if (!src) {\n type = options.type || formatType.type;\n } else if (isArrayBuffer(src) || (Array.isArray(src) && typeof (src[0]) === 'number')) {\n type = options.type || getTextureTypeForArrayType(gl, src, formatType.type);\n } else {\n type = options.type || formatType.type;\n }\n if (target === TEXTURE_CUBE_MAP$1) {\n for (let ii = 0; ii < 6; ++ii) {\n gl.texImage2D(TEXTURE_CUBE_MAP_POSITIVE_X + ii, level, internalFormat, width, height, 0, format, type, null);\n }\n } else if (target === TEXTURE_3D$1 || target === TEXTURE_2D_ARRAY$1) {\n gl.texImage3D(target, level, internalFormat, width, height, depth, 0, format, type, null);\n } else {\n gl.texImage2D(target, level, internalFormat, width, height, 0, format, type, null);\n }\n}\n\n/**\n * Check if a src is an async request.\n * if src is a string we're going to download an image\n * if src is an array of strings we're going to download cubemap images\n * @param {*} src The src from a TextureOptions\n * @returns {bool} true if src is async.\n * @private\n */\nfunction isAsyncSrc(src) {\n return typeof src === 'string' ||\n (Array.isArray(src) && typeof src[0] === 'string');\n}\n\n/**\n * Creates a bunch of textures based on the passed in options.\n *\n * Example:\n *\n * const textures = twgl.createTextures(gl, {\n * // a power of 2 image\n * hftIcon: { src: \"images/hft-icon-16.png\", mag: gl.NEAREST },\n * // a non-power of 2 image\n * clover: { src: \"images/clover.jpg\" },\n * // From a canvas\n * fromCanvas: { src: ctx.canvas },\n * // A cubemap from 6 images\n * yokohama: {\n * target: gl.TEXTURE_CUBE_MAP,\n * src: [\n * 'images/yokohama/posx.jpg',\n * 'images/yokohama/negx.jpg',\n * 'images/yokohama/posy.jpg',\n * 'images/yokohama/negy.jpg',\n * 'images/yokohama/posz.jpg',\n * 'images/yokohama/negz.jpg',\n * ],\n * },\n * // A cubemap from 1 image (can be 1x6, 2x3, 3x2, 6x1)\n * goldengate: {\n * target: gl.TEXTURE_CUBE_MAP,\n * src: 'images/goldengate.jpg',\n * },\n * // A 2x2 pixel texture from a JavaScript array\n * checker: {\n * mag: gl.NEAREST,\n * min: gl.LINEAR,\n * src: [\n * 255,255,255,255,\n * 192,192,192,255,\n * 192,192,192,255,\n * 255,255,255,255,\n * ],\n * },\n * // a 1x2 pixel texture from a typed array.\n * stripe: {\n * mag: gl.NEAREST,\n * min: gl.LINEAR,\n * format: gl.LUMINANCE,\n * src: new Uint8Array([\n * 255,\n * 128,\n * 255,\n * 128,\n * 255,\n * 128,\n * 255,\n * 128,\n * ]),\n * width: 1,\n * },\n * });\n *\n * Now\n *\n * * `textures.hftIcon` will be a 2d texture\n * * `textures.clover` will be a 2d texture\n * * `textures.fromCanvas` will be a 2d texture\n * * `textures.yohohama` will be a cubemap texture\n * * `textures.goldengate` will be a cubemap texture\n * * `textures.checker` will be a 2d texture\n * * `textures.stripe` will be a 2d texture\n *\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {Object.} options A object of TextureOptions one per texture.\n * @param {module:twgl.TexturesReadyCallback} [callback] A callback called when all textures have been downloaded.\n * @return {Object.} the created textures by name\n * @memberOf module:twgl/textures\n */\nfunction createTextures(gl, textureOptions, callback) {\n callback = callback || noop;\n let numDownloading = 0;\n const errors = [];\n const textures = {};\n const images = {};\n\n function callCallbackIfReady() {\n if (numDownloading === 0) {\n setTimeout(function() {\n callback(errors.length ? errors : undefined, textures, images);\n }, 0);\n }\n }\n\n Object.keys(textureOptions).forEach(function(name) {\n const options = textureOptions[name];\n let onLoadFn;\n if (isAsyncSrc(options.src)) {\n onLoadFn = function(err, tex, img) {\n images[name] = img;\n --numDownloading;\n if (err) {\n errors.push(err);\n }\n callCallbackIfReady();\n };\n ++numDownloading;\n }\n textures[name] = createTexture(gl, options, onLoadFn);\n });\n\n // queue the callback if there are no images to download.\n // We do this because if your code is structured to wait for\n // images to download but then you comment out all the async\n // images your code would break.\n callCallbackIfReady();\n\n return textures;\n}\n\nvar textures = /*#__PURE__*/Object.freeze({\n __proto__: null,\n setTextureDefaults_: setDefaults$1,\n createSampler: createSampler,\n createSamplers: createSamplers,\n setSamplerParameters: setSamplerParameters,\n createTexture: createTexture,\n setEmptyTexture: setEmptyTexture,\n setTextureFromArray: setTextureFromArray,\n loadTextureFromUrl: loadTextureFromUrl,\n setTextureFromElement: setTextureFromElement,\n setTextureFilteringForSize: setTextureFilteringForSize,\n setTextureParameters: setTextureParameters,\n setDefaultTextureColor: setDefaultTextureColor,\n createTextures: createTextures,\n resizeTexture: resizeTexture,\n canGenerateMipmap: canGenerateMipmap,\n canFilter: canFilter,\n getNumComponentsForFormat: getNumComponentsForFormat,\n getBytesPerElementForInternalFormat: getBytesPerElementForInternalFormat,\n getFormatAndTypeForInternalFormat: getFormatAndTypeForInternalFormat\n});\n\n/*\n * Copyright 2019 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\n/**\n * Low level shader program related functions\n *\n * You should generally not need to use these functions. They are provided\n * for those cases where you're doing something out of the ordinary\n * and you need lower level access.\n *\n * For backward compatibility they are available at both `twgl.programs` and `twgl`\n * itself\n *\n * See {@link module:twgl} for core functions\n *\n * @module twgl/programs\n */\n\nconst error = error$1;\nconst warn = warn$1;\nfunction getElementById(id) {\n return (typeof document !== 'undefined' && document.getElementById)\n ? document.getElementById(id)\n : null;\n}\n\nconst TEXTURE0 = 0x84c0;\nconst DYNAMIC_DRAW = 0x88e8;\n\nconst ARRAY_BUFFER = 0x8892;\nconst ELEMENT_ARRAY_BUFFER$1 = 0x8893;\nconst UNIFORM_BUFFER = 0x8a11;\nconst TRANSFORM_FEEDBACK_BUFFER = 0x8c8e;\n\nconst TRANSFORM_FEEDBACK = 0x8e22;\n\nconst COMPILE_STATUS = 0x8b81;\nconst LINK_STATUS = 0x8b82;\nconst FRAGMENT_SHADER = 0x8b30;\nconst VERTEX_SHADER = 0x8b31;\nconst SEPARATE_ATTRIBS = 0x8c8d;\n\nconst ACTIVE_UNIFORMS = 0x8b86;\nconst ACTIVE_ATTRIBUTES = 0x8b89;\nconst TRANSFORM_FEEDBACK_VARYINGS = 0x8c83;\nconst ACTIVE_UNIFORM_BLOCKS = 0x8a36;\nconst UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER = 0x8a44;\nconst UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER = 0x8a46;\nconst UNIFORM_BLOCK_DATA_SIZE = 0x8a40;\nconst UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES = 0x8a43;\n\nconst FLOAT = 0x1406;\nconst FLOAT_VEC2 = 0x8B50;\nconst FLOAT_VEC3 = 0x8B51;\nconst FLOAT_VEC4 = 0x8B52;\nconst INT = 0x1404;\nconst INT_VEC2 = 0x8B53;\nconst INT_VEC3 = 0x8B54;\nconst INT_VEC4 = 0x8B55;\nconst BOOL = 0x8B56;\nconst BOOL_VEC2 = 0x8B57;\nconst BOOL_VEC3 = 0x8B58;\nconst BOOL_VEC4 = 0x8B59;\nconst FLOAT_MAT2 = 0x8B5A;\nconst FLOAT_MAT3 = 0x8B5B;\nconst FLOAT_MAT4 = 0x8B5C;\nconst SAMPLER_2D = 0x8B5E;\nconst SAMPLER_CUBE = 0x8B60;\nconst SAMPLER_3D = 0x8B5F;\nconst SAMPLER_2D_SHADOW = 0x8B62;\nconst FLOAT_MAT2x3 = 0x8B65;\nconst FLOAT_MAT2x4 = 0x8B66;\nconst FLOAT_MAT3x2 = 0x8B67;\nconst FLOAT_MAT3x4 = 0x8B68;\nconst FLOAT_MAT4x2 = 0x8B69;\nconst FLOAT_MAT4x3 = 0x8B6A;\nconst SAMPLER_2D_ARRAY = 0x8DC1;\nconst SAMPLER_2D_ARRAY_SHADOW = 0x8DC4;\nconst SAMPLER_CUBE_SHADOW = 0x8DC5;\nconst UNSIGNED_INT = 0x1405;\nconst UNSIGNED_INT_VEC2 = 0x8DC6;\nconst UNSIGNED_INT_VEC3 = 0x8DC7;\nconst UNSIGNED_INT_VEC4 = 0x8DC8;\nconst INT_SAMPLER_2D = 0x8DCA;\nconst INT_SAMPLER_3D = 0x8DCB;\nconst INT_SAMPLER_CUBE = 0x8DCC;\nconst INT_SAMPLER_2D_ARRAY = 0x8DCF;\nconst UNSIGNED_INT_SAMPLER_2D = 0x8DD2;\nconst UNSIGNED_INT_SAMPLER_3D = 0x8DD3;\nconst UNSIGNED_INT_SAMPLER_CUBE = 0x8DD4;\nconst UNSIGNED_INT_SAMPLER_2D_ARRAY = 0x8DD7;\n\nconst TEXTURE_2D$1 = 0x0DE1;\nconst TEXTURE_CUBE_MAP = 0x8513;\nconst TEXTURE_3D = 0x806F;\nconst TEXTURE_2D_ARRAY = 0x8C1A;\n\nconst typeMap = {};\n\n/**\n * Returns the corresponding bind point for a given sampler type\n * @private\n */\nfunction getBindPointForSamplerType(gl, type) {\n return typeMap[type].bindPoint;\n}\n\n// This kind of sucks! If you could compose functions as in `var fn = gl[name];`\n// this code could be a lot smaller but that is sadly really slow (T_T)\n\nfunction floatSetter(gl, location) {\n return function(v) {\n gl.uniform1f(location, v);\n };\n}\n\nfunction floatArraySetter(gl, location) {\n return function(v) {\n gl.uniform1fv(location, v);\n };\n}\n\nfunction floatVec2Setter(gl, location) {\n return function(v) {\n gl.uniform2fv(location, v);\n };\n}\n\nfunction floatVec3Setter(gl, location) {\n return function(v) {\n gl.uniform3fv(location, v);\n };\n}\n\nfunction floatVec4Setter(gl, location) {\n return function(v) {\n gl.uniform4fv(location, v);\n };\n}\n\nfunction intSetter(gl, location) {\n return function(v) {\n gl.uniform1i(location, v);\n };\n}\n\nfunction intArraySetter(gl, location) {\n return function(v) {\n gl.uniform1iv(location, v);\n };\n}\n\nfunction intVec2Setter(gl, location) {\n return function(v) {\n gl.uniform2iv(location, v);\n };\n}\n\nfunction intVec3Setter(gl, location) {\n return function(v) {\n gl.uniform3iv(location, v);\n };\n}\n\nfunction intVec4Setter(gl, location) {\n return function(v) {\n gl.uniform4iv(location, v);\n };\n}\n\nfunction uintSetter(gl, location) {\n return function(v) {\n gl.uniform1ui(location, v);\n };\n}\n\nfunction uintArraySetter(gl, location) {\n return function(v) {\n gl.uniform1uiv(location, v);\n };\n}\n\nfunction uintVec2Setter(gl, location) {\n return function(v) {\n gl.uniform2uiv(location, v);\n };\n}\n\nfunction uintVec3Setter(gl, location) {\n return function(v) {\n gl.uniform3uiv(location, v);\n };\n}\n\nfunction uintVec4Setter(gl, location) {\n return function(v) {\n gl.uniform4uiv(location, v);\n };\n}\n\nfunction floatMat2Setter(gl, location) {\n return function(v) {\n gl.uniformMatrix2fv(location, false, v);\n };\n}\n\nfunction floatMat3Setter(gl, location) {\n return function(v) {\n gl.uniformMatrix3fv(location, false, v);\n };\n}\n\nfunction floatMat4Setter(gl, location) {\n return function(v) {\n gl.uniformMatrix4fv(location, false, v);\n };\n}\n\nfunction floatMat23Setter(gl, location) {\n return function(v) {\n gl.uniformMatrix2x3fv(location, false, v);\n };\n}\n\nfunction floatMat32Setter(gl, location) {\n return function(v) {\n gl.uniformMatrix3x2fv(location, false, v);\n };\n}\n\nfunction floatMat24Setter(gl, location) {\n return function(v) {\n gl.uniformMatrix2x4fv(location, false, v);\n };\n}\n\nfunction floatMat42Setter(gl, location) {\n return function(v) {\n gl.uniformMatrix4x2fv(location, false, v);\n };\n}\n\nfunction floatMat34Setter(gl, location) {\n return function(v) {\n gl.uniformMatrix3x4fv(location, false, v);\n };\n}\n\nfunction floatMat43Setter(gl, location) {\n return function(v) {\n gl.uniformMatrix4x3fv(location, false, v);\n };\n}\n\nfunction samplerSetter(gl, type, unit, location) {\n const bindPoint = getBindPointForSamplerType(gl, type);\n return isWebGL2(gl) ? function(textureOrPair) {\n let texture;\n let sampler;\n if (!textureOrPair || isTexture(gl, textureOrPair)) {\n texture = textureOrPair;\n sampler = null;\n } else {\n texture = textureOrPair.texture;\n sampler = textureOrPair.sampler;\n }\n gl.uniform1i(location, unit);\n gl.activeTexture(TEXTURE0 + unit);\n gl.bindTexture(bindPoint, texture);\n gl.bindSampler(unit, sampler);\n } : function(texture) {\n gl.uniform1i(location, unit);\n gl.activeTexture(TEXTURE0 + unit);\n gl.bindTexture(bindPoint, texture);\n };\n}\n\nfunction samplerArraySetter(gl, type, unit, location, size) {\n const bindPoint = getBindPointForSamplerType(gl, type);\n const units = new Int32Array(size);\n for (let ii = 0; ii < size; ++ii) {\n units[ii] = unit + ii;\n }\n\n return isWebGL2(gl) ? function(textures) {\n gl.uniform1iv(location, units);\n textures.forEach(function(textureOrPair, index) {\n gl.activeTexture(TEXTURE0 + units[index]);\n let texture;\n let sampler;\n if (!textureOrPair || isTexture(gl, textureOrPair)) {\n texture = textureOrPair;\n sampler = null;\n } else {\n texture = textureOrPair.texture;\n sampler = textureOrPair.sampler;\n }\n gl.bindSampler(unit, sampler);\n gl.bindTexture(bindPoint, texture);\n });\n } : function(textures) {\n gl.uniform1iv(location, units);\n textures.forEach(function(texture, index) {\n gl.activeTexture(TEXTURE0 + units[index]);\n gl.bindTexture(bindPoint, texture);\n });\n };\n}\n\ntypeMap[FLOAT] = { Type: Float32Array, size: 4, setter: floatSetter, arraySetter: floatArraySetter, };\ntypeMap[FLOAT_VEC2] = { Type: Float32Array, size: 8, setter: floatVec2Setter, cols: 2, };\ntypeMap[FLOAT_VEC3] = { Type: Float32Array, size: 12, setter: floatVec3Setter, cols: 3, };\ntypeMap[FLOAT_VEC4] = { Type: Float32Array, size: 16, setter: floatVec4Setter, cols: 4, };\ntypeMap[INT] = { Type: Int32Array, size: 4, setter: intSetter, arraySetter: intArraySetter, };\ntypeMap[INT_VEC2] = { Type: Int32Array, size: 8, setter: intVec2Setter, cols: 2, };\ntypeMap[INT_VEC3] = { Type: Int32Array, size: 12, setter: intVec3Setter, cols: 3, };\ntypeMap[INT_VEC4] = { Type: Int32Array, size: 16, setter: intVec4Setter, cols: 4, };\ntypeMap[UNSIGNED_INT] = { Type: Uint32Array, size: 4, setter: uintSetter, arraySetter: uintArraySetter, };\ntypeMap[UNSIGNED_INT_VEC2] = { Type: Uint32Array, size: 8, setter: uintVec2Setter, cols: 2, };\ntypeMap[UNSIGNED_INT_VEC3] = { Type: Uint32Array, size: 12, setter: uintVec3Setter, cols: 3, };\ntypeMap[UNSIGNED_INT_VEC4] = { Type: Uint32Array, size: 16, setter: uintVec4Setter, cols: 4, };\ntypeMap[BOOL] = { Type: Uint32Array, size: 4, setter: intSetter, arraySetter: intArraySetter, };\ntypeMap[BOOL_VEC2] = { Type: Uint32Array, size: 8, setter: intVec2Setter, cols: 2, };\ntypeMap[BOOL_VEC3] = { Type: Uint32Array, size: 12, setter: intVec3Setter, cols: 3, };\ntypeMap[BOOL_VEC4] = { Type: Uint32Array, size: 16, setter: intVec4Setter, cols: 4, };\ntypeMap[FLOAT_MAT2] = { Type: Float32Array, size: 32, setter: floatMat2Setter, rows: 2, cols: 2, };\ntypeMap[FLOAT_MAT3] = { Type: Float32Array, size: 48, setter: floatMat3Setter, rows: 3, cols: 3, };\ntypeMap[FLOAT_MAT4] = { Type: Float32Array, size: 64, setter: floatMat4Setter, rows: 4, cols: 4, };\ntypeMap[FLOAT_MAT2x3] = { Type: Float32Array, size: 32, setter: floatMat23Setter, rows: 2, cols: 3, };\ntypeMap[FLOAT_MAT2x4] = { Type: Float32Array, size: 32, setter: floatMat24Setter, rows: 2, cols: 4, };\ntypeMap[FLOAT_MAT3x2] = { Type: Float32Array, size: 48, setter: floatMat32Setter, rows: 3, cols: 2, };\ntypeMap[FLOAT_MAT3x4] = { Type: Float32Array, size: 48, setter: floatMat34Setter, rows: 3, cols: 4, };\ntypeMap[FLOAT_MAT4x2] = { Type: Float32Array, size: 64, setter: floatMat42Setter, rows: 4, cols: 2, };\ntypeMap[FLOAT_MAT4x3] = { Type: Float32Array, size: 64, setter: floatMat43Setter, rows: 4, cols: 3, };\ntypeMap[SAMPLER_2D] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D$1, };\ntypeMap[SAMPLER_CUBE] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_CUBE_MAP, };\ntypeMap[SAMPLER_3D] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_3D, };\ntypeMap[SAMPLER_2D_SHADOW] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D$1, };\ntypeMap[SAMPLER_2D_ARRAY] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D_ARRAY, };\ntypeMap[SAMPLER_2D_ARRAY_SHADOW] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D_ARRAY, };\ntypeMap[SAMPLER_CUBE_SHADOW] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_CUBE_MAP, };\ntypeMap[INT_SAMPLER_2D] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D$1, };\ntypeMap[INT_SAMPLER_3D] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_3D, };\ntypeMap[INT_SAMPLER_CUBE] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_CUBE_MAP, };\ntypeMap[INT_SAMPLER_2D_ARRAY] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D_ARRAY, };\ntypeMap[UNSIGNED_INT_SAMPLER_2D] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D$1, };\ntypeMap[UNSIGNED_INT_SAMPLER_3D] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_3D, };\ntypeMap[UNSIGNED_INT_SAMPLER_CUBE] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_CUBE_MAP, };\ntypeMap[UNSIGNED_INT_SAMPLER_2D_ARRAY] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D_ARRAY, };\n\nfunction floatAttribSetter(gl, index) {\n return function(b) {\n if (b.value) {\n gl.disableVertexAttribArray(index);\n switch (b.value.length) {\n case 4:\n gl.vertexAttrib4fv(index, b.value);\n break;\n case 3:\n gl.vertexAttrib3fv(index, b.value);\n break;\n case 2:\n gl.vertexAttrib2fv(index, b.value);\n break;\n case 1:\n gl.vertexAttrib1fv(index, b.value);\n break;\n default:\n throw new Error('the length of a float constant value must be between 1 and 4!');\n }\n } else {\n gl.bindBuffer(ARRAY_BUFFER, b.buffer);\n gl.enableVertexAttribArray(index);\n gl.vertexAttribPointer(\n index, b.numComponents || b.size, b.type || FLOAT, b.normalize || false, b.stride || 0, b.offset || 0);\n if (gl.vertexAttribDivisor) {\n gl.vertexAttribDivisor(index, b.divisor || 0);\n }\n }\n };\n}\n\nfunction intAttribSetter(gl, index) {\n return function(b) {\n if (b.value) {\n gl.disableVertexAttribArray(index);\n if (b.value.length === 4) {\n gl.vertexAttrib4iv(index, b.value);\n } else {\n throw new Error('The length of an integer constant value must be 4!');\n }\n } else {\n gl.bindBuffer(ARRAY_BUFFER, b.buffer);\n gl.enableVertexAttribArray(index);\n gl.vertexAttribIPointer(\n index, b.numComponents || b.size, b.type || INT, b.stride || 0, b.offset || 0);\n if (gl.vertexAttribDivisor) {\n gl.vertexAttribDivisor(index, b.divisor || 0);\n }\n }\n };\n}\n\nfunction uintAttribSetter(gl, index) {\n return function(b) {\n if (b.value) {\n gl.disableVertexAttribArray(index);\n if (b.value.length === 4) {\n gl.vertexAttrib4uiv(index, b.value);\n } else {\n throw new Error('The length of an unsigned integer constant value must be 4!');\n }\n } else {\n gl.bindBuffer(ARRAY_BUFFER, b.buffer);\n gl.enableVertexAttribArray(index);\n gl.vertexAttribIPointer(\n index, b.numComponents || b.size, b.type || UNSIGNED_INT, b.stride || 0, b.offset || 0);\n if (gl.vertexAttribDivisor) {\n gl.vertexAttribDivisor(index, b.divisor || 0);\n }\n }\n };\n}\n\nfunction matAttribSetter(gl, index, typeInfo) {\n const defaultSize = typeInfo.size;\n const count = typeInfo.count;\n\n return function(b) {\n gl.bindBuffer(ARRAY_BUFFER, b.buffer);\n const numComponents = b.size || b.numComponents || defaultSize;\n const size = numComponents / count;\n const type = b.type || FLOAT;\n const typeInfo = typeMap[type];\n const stride = typeInfo.size * numComponents;\n const normalize = b.normalize || false;\n const offset = b.offset || 0;\n const rowOffset = stride / count;\n for (let i = 0; i < count; ++i) {\n gl.enableVertexAttribArray(index + i);\n gl.vertexAttribPointer(\n index + i, size, type, normalize, stride, offset + rowOffset * i);\n if (gl.vertexAttribDivisor) {\n gl.vertexAttribDivisor(index + i, b.divisor || 0);\n }\n }\n };\n}\n\n\n\nconst attrTypeMap = {};\nattrTypeMap[FLOAT] = { size: 4, setter: floatAttribSetter, };\nattrTypeMap[FLOAT_VEC2] = { size: 8, setter: floatAttribSetter, };\nattrTypeMap[FLOAT_VEC3] = { size: 12, setter: floatAttribSetter, };\nattrTypeMap[FLOAT_VEC4] = { size: 16, setter: floatAttribSetter, };\nattrTypeMap[INT] = { size: 4, setter: intAttribSetter, };\nattrTypeMap[INT_VEC2] = { size: 8, setter: intAttribSetter, };\nattrTypeMap[INT_VEC3] = { size: 12, setter: intAttribSetter, };\nattrTypeMap[INT_VEC4] = { size: 16, setter: intAttribSetter, };\nattrTypeMap[UNSIGNED_INT] = { size: 4, setter: uintAttribSetter, };\nattrTypeMap[UNSIGNED_INT_VEC2] = { size: 8, setter: uintAttribSetter, };\nattrTypeMap[UNSIGNED_INT_VEC3] = { size: 12, setter: uintAttribSetter, };\nattrTypeMap[UNSIGNED_INT_VEC4] = { size: 16, setter: uintAttribSetter, };\nattrTypeMap[BOOL] = { size: 4, setter: intAttribSetter, };\nattrTypeMap[BOOL_VEC2] = { size: 8, setter: intAttribSetter, };\nattrTypeMap[BOOL_VEC3] = { size: 12, setter: intAttribSetter, };\nattrTypeMap[BOOL_VEC4] = { size: 16, setter: intAttribSetter, };\nattrTypeMap[FLOAT_MAT2] = { size: 4, setter: matAttribSetter, count: 2, };\nattrTypeMap[FLOAT_MAT3] = { size: 9, setter: matAttribSetter, count: 3, };\nattrTypeMap[FLOAT_MAT4] = { size: 16, setter: matAttribSetter, count: 4, };\n\nconst errorRE = /ERROR:\\s*\\d+:(\\d+)/gi;\nfunction addLineNumbersWithError(src, log = '', lineOffset = 0) {\n // Note: Error message formats are not defined by any spec so this may or may not work.\n const matches = [...log.matchAll(errorRE)];\n const lineNoToErrorMap = new Map(matches.map((m, ndx) => {\n const lineNo = parseInt(m[1]);\n const next = matches[ndx + 1];\n const end = next ? next.index : log.length;\n const msg = log.substring(m.index, end);\n return [lineNo - 1, msg];\n }));\n return src.split('\\n').map((line, lineNo) => {\n const err = lineNoToErrorMap.get(lineNo);\n return `${lineNo + 1 + lineOffset}: ${line}${err ? `\\n\\n^^^ ${err}` : ''}`;\n }).join('\\n');\n}\n\n/**\n * Error Callback\n * @callback ErrorCallback\n * @param {string} msg error message.\n * @param {number} [lineOffset] amount to add to line number\n * @memberOf module:twgl\n */\n\n/**\n * Program Callback\n * @callback ProgramCallback\n * @param {string} [err] error message, falsy if no error\n * @param {WebGLProgram|module:twgl.ProgramInfo} [result] the program or programInfo\n */\n\nconst spaceRE = /^[ \\t]*\\n/;\n\n/**\n * Remove the first end of line because WebGL 2.0 requires\n * #version 300 es\n * as the first line. No whitespace allowed before that line\n * so\n *\n * \n *\n * Has one line before it which is invalid according to GLSL ES 3.00\n *\n * @param {string} shaderSource The source of the shader\n * @returns {{shaderSource: string, lineOffset: number}}\n * @private\n */\nfunction prepShaderSource(shaderSource) {\n let lineOffset = 0;\n if (spaceRE.test(shaderSource)) {\n lineOffset = 1;\n shaderSource = shaderSource.replace(spaceRE, '');\n }\n return {lineOffset, shaderSource};\n}\n\n/**\n * @param {module:twgl.ProgramOptions} progOptions\n * @param {string} msg\n * @return null\n * @private\n */\nfunction reportError(progOptions, msg) {\n progOptions.errorCallback(msg);\n if (progOptions.callback) {\n setTimeout(() => {\n progOptions.callback(`${msg}\\n${progOptions.errors.join('\\n')}`);\n });\n }\n return null;\n}\n\n/**\n * Check Shader status\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use.\n * @param {number} shaderType The shader type\n * @param {WebGLShader} shader The shader\n * @param {ErrorCallback} [errFn] function to receive error message.\n * @return {string} errors or empty string\n * @private\n */\nfunction checkShaderStatus(gl, shaderType, shader, errFn) {\n errFn = errFn || error;\n // Check the compile status\n const compiled = gl.getShaderParameter(shader, COMPILE_STATUS);\n if (!compiled) {\n // Something went wrong during compilation; get the error\n const lastError = gl.getShaderInfoLog(shader);\n const {lineOffset, shaderSource} = prepShaderSource(gl.getShaderSource(shader));\n const error = `${addLineNumbersWithError(shaderSource, lastError, lineOffset)}\\nError compiling ${glEnumToString(gl, shaderType)}: ${lastError}`;\n errFn(error);\n return error;\n }\n return '';\n}\n\n/**\n * @typedef {Object} FullProgramSpec\n * @property {string[]} shaders the shader source or element ids.\n * @property {function(string)} [errorCallback] callback for errors\n * @property {Object.|string[]} [attribLocations] a attribute name to location map, or array of attribute names where index = location.\n * @property {(module:twgl.BufferInfo|Object.|string[])} [transformFeedbackVaryings] If passed\n * a BufferInfo will use the attribs names inside. If passed an object of AttribInfos will use the names from that object. Otherwise\n * you can pass an array of names.\n * @property {number} [transformFeedbackMode] the mode to pass `gl.transformFeedbackVaryings`. Defaults to `SEPARATE_ATTRIBS`.\n * @property {ProgramCallback} [callback] callback for async program compilation.\n * @memberOf module:twgl\n */\n\n/**\n * @typedef {string[]|module:twgl.FullProgramSpec} ProgramSpec\n * @memberOf module:twgl\n */\n\n/**\n * @typedef {Object} ProgramOptions\n * @property {function(string)} [errorCallback] callback for errors\n * @property {Object.|string[]} [attribLocations] a attribute name to location map, or array of attribute names where index = location.\n * @property {(module:twgl.BufferInfo|Object.|string[])} [transformFeedbackVaryings] If passed\n * a BufferInfo will use the attribs names inside. If passed an object of AttribInfos will use the names from that object. Otherwise\n * you can pass an array of names.\n * @property {number} [transformFeedbackMode] the mode to pass `gl.transformFeedbackVaryings`. Defaults to `SEPARATE_ATTRIBS`.\n * @property {ProgramCallback} [callback] callback for async program compilation.\n * @memberOf module:twgl\n */\n\n/**\n * Gets the program options based on all these optional arguments\n * @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\n * @param {number[]} [opt_locations] The locations for the. A parallel array to opt_attribs letting you assign locations.\n * @param {module:twgl.ErrorCallback} [opt_errorCallback] callback for errors. By default it just prints an error to the console\n * on error. If you want something else pass an callback. It's passed an error message.\n * @return {module:twgl.ProgramOptions} an instance of ProgramOptions based on the arguments passed in\n * @private\n */\nfunction getProgramOptions(opt_attribs, opt_locations, opt_errorCallback) {\n let transformFeedbackVaryings;\n let transformFeedbackMode;\n let callback;\n if (typeof opt_locations === 'function') {\n opt_errorCallback = opt_locations;\n opt_locations = undefined;\n }\n if (typeof opt_attribs === 'function') {\n opt_errorCallback = opt_attribs;\n opt_attribs = undefined;\n } else if (opt_attribs && !Array.isArray(opt_attribs)) {\n const opt = opt_attribs;\n opt_errorCallback = opt.errorCallback;\n opt_attribs = opt.attribLocations;\n transformFeedbackVaryings = opt.transformFeedbackVaryings;\n transformFeedbackMode = opt.transformFeedbackMode;\n callback = opt.callback;\n }\n\n const errorCallback = opt_errorCallback || error;\n const errors = [];\n const options = {\n errorCallback(msg, ...args) {\n errors.push(msg);\n errorCallback(msg, ...args);\n },\n transformFeedbackVaryings,\n transformFeedbackMode,\n callback,\n errors,\n };\n\n {\n let attribLocations = {};\n if (Array.isArray(opt_attribs)) {\n opt_attribs.forEach(function(attrib, ndx) {\n attribLocations[attrib] = opt_locations ? opt_locations[ndx] : ndx;\n });\n } else {\n attribLocations = opt_attribs || {};\n }\n options.attribLocations = attribLocations;\n }\n\n return options;\n}\n\nconst defaultShaderType = [\n \"VERTEX_SHADER\",\n \"FRAGMENT_SHADER\",\n];\n\nfunction getShaderTypeFromScriptType(gl, scriptType) {\n if (scriptType.indexOf(\"frag\") >= 0) {\n return FRAGMENT_SHADER;\n } else if (scriptType.indexOf(\"vert\") >= 0) {\n return VERTEX_SHADER;\n }\n return undefined;\n}\n\nfunction deleteProgramAndShaders(gl, program, notThese) {\n const shaders = gl.getAttachedShaders(program);\n for (const shader of shaders) {\n if (notThese.has(shader)) {\n gl.deleteShader(shader);\n }\n }\n gl.deleteProgram(program);\n}\n\nconst wait = (ms = 0) => new Promise(resolve => setTimeout(resolve, ms));\n\nfunction createProgramNoCheck(gl, shaders, programOptions) {\n const program = gl.createProgram();\n const {\n attribLocations,\n transformFeedbackVaryings,\n transformFeedbackMode,\n } = getProgramOptions(programOptions);\n\n for (let ndx = 0; ndx < shaders.length; ++ndx) {\n let shader = shaders[ndx];\n if (typeof shader === 'string') {\n const elem = getElementById(shader);\n const src = elem ? elem.text : shader;\n let type = gl[defaultShaderType[ndx]];\n if (elem && elem.type) {\n type = getShaderTypeFromScriptType(gl, elem.type) || type;\n }\n shader = gl.createShader(type);\n gl.shaderSource(shader, prepShaderSource(src).shaderSource);\n gl.compileShader(shader);\n gl.attachShader(program, shader);\n }\n }\n\n Object.entries(attribLocations).forEach(([attrib, loc]) => gl.bindAttribLocation(program, loc, attrib));\n\n {\n let varyings = transformFeedbackVaryings;\n if (varyings) {\n if (varyings.attribs) {\n varyings = varyings.attribs;\n }\n if (!Array.isArray(varyings)) {\n varyings = Object.keys(varyings);\n }\n gl.transformFeedbackVaryings(program, varyings, transformFeedbackMode || SEPARATE_ATTRIBS);\n }\n }\n\n gl.linkProgram(program);\n return program;\n}\n\n/**\n * Creates a program, attaches (and/or compiles) shaders, binds attrib locations, links the\n * program.\n *\n * NOTE: There are 4 signatures for this function\n *\n * twgl.createProgram(gl, [vs, fs], options);\n * twgl.createProgram(gl, [vs, fs], opt_errFunc);\n * twgl.createProgram(gl, [vs, fs], opt_attribs, opt_errFunc);\n * twgl.createProgram(gl, [vs, fs], opt_attribs, opt_locations, opt_errFunc);\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use.\n * @param {WebGLShader[]|string[]} shaders The shaders to attach, or element ids for their source, or strings that contain their source\n * @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\n * @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.\n * @param {module:twgl.ErrorCallback} [opt_errorCallback] callback for errors. By default it just prints an error to the console\n * on error. If you want something else pass an callback. It's passed an error message.\n * @return {WebGLProgram?} the created program or null if error of a callback was provided.\n * @memberOf module:twgl/programs\n */\nfunction createProgram(\n gl, shaders, opt_attribs, opt_locations, opt_errorCallback) {\n // This code is really convoluted, because it may or may not be async\n // Maybe it would be better to have a separate function\n const progOptions = getProgramOptions(opt_attribs, opt_locations, opt_errorCallback);\n const shaderSet = new Set(shaders);\n const program = createProgramNoCheck(gl, shaders, progOptions);\n\n function hasErrors(gl, program) {\n const errors = getProgramErrors(gl, program, progOptions.errorCallback);\n if (errors) {\n deleteProgramAndShaders(gl, program, shaderSet);\n }\n return errors;\n }\n\n if (progOptions.callback) {\n waitForProgramLinkCompletionAsync(gl, program).then(() => {\n const errors = hasErrors(gl, program);\n progOptions.callback(errors, errors ? undefined : program);\n });\n return undefined;\n }\n\n return hasErrors(gl, program) ? undefined : program;\n}\n\n/**\n * This only works because the functions it wraps the first 2 arguments\n * are gl and any, followed by things that become programOptions\n * @private\n */\nfunction wrapCallbackFnToAsyncFn(fn) {\n return function(gl, arg1, ...args) {\n return new Promise((resolve, reject) => {\n const programOptions = getProgramOptions(...args);\n programOptions.callback = (err, program) => {\n if (err) {\n reject(err);\n } else {\n resolve(program);\n }\n };\n fn(gl, arg1, programOptions);\n });\n };\n}\n\n/**\n * Same as createProgram but returns a promise\n *\n * NOTE: There are 4 signatures for this function\n *\n * twgl.createProgramAsync(gl, [vs, fs], options);\n * twgl.createProgramAsync(gl, [vs, fs], opt_errFunc);\n * twgl.createProgramAsync(gl, [vs, fs], opt_attribs, opt_errFunc);\n * twgl.createProgramAsync(gl, [vs, fs], opt_attribs, opt_locations, opt_errFunc);\n *\n * @function\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use.\n * @param {WebGLShader[]|string[]} shaders The shaders to attach, or element ids for their source, or strings that contain their source\n * @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\n * @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.\n * @param {module:twgl.ErrorCallback} [opt_errorCallback] callback for errors. By default it just prints an error to the console\n * on error. If you want something else pass an callback. It's passed an error message.\n * @return {Promise} The created program\n * @memberOf module:twgl/programs\n */\nconst createProgramAsync = wrapCallbackFnToAsyncFn(createProgram);\n\n/**\n * Same as createProgramInfo but returns a promise\n * @function\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext\n * to use.\n * @param {string[]} shaderSources Array of sources for the\n * shaders or ids. The first is assumed to be the vertex shader,\n * the second the fragment shader.\n * @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\n * @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.\n * @param {module:twgl.ErrorCallback} [opt_errorCallback] callback for errors. By default it just prints an error to the console\n * on error. If you want something else pass an callback. It's passed an error message.\n * @return {Promise} The created ProgramInfo\n * @memberOf module:twgl/programs\n */\nconst createProgramInfoAsync = wrapCallbackFnToAsyncFn(createProgramInfo);\n\nasync function waitForProgramLinkCompletionAsync(gl, program) {\n const ext = gl.getExtension('KHR_parallel_shader_compile');\n const checkFn = ext\n ? (gl, program) => gl.getProgramParameter(program, ext.COMPLETION_STATUS_KHR)\n : () => true;\n\n let waitTime = 0;\n do {\n await wait(waitTime); // must wait at least once\n waitTime = 1000 / 60;\n } while (!checkFn(gl, program));\n}\n\nasync function waitForAllProgramsLinkCompletionAsync(gl, programs) {\n for (const program of Object.values(programs)) {\n await waitForProgramLinkCompletionAsync(gl, program);\n }\n}\n\n/**\n * Check a program's link status\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use.\n * @param {WebGLProgram} program Program to check\n * @param {ErrorCallback} [errFn] func for errors\n * @return {string?} errors if program is failed, else undefined\n * @private\n */\nfunction getProgramErrors(gl, program, errFn) {\n errFn = errFn || error;\n // Check the link status\n const linked = gl.getProgramParameter(program, LINK_STATUS);\n if (!linked) {\n // something went wrong with the link\n const lastError = gl.getProgramInfoLog(program);\n errFn(`Error in program linking: ${lastError}`);\n // print any errors from these shaders\n const shaders = gl.getAttachedShaders(program);\n const errors = shaders.map(shader => checkShaderStatus(gl, gl.getShaderParameter(shader, gl.SHADER_TYPE), shader, errFn));\n return `${lastError}\\n${errors.filter(_ => _).join('\\n')}`;\n }\n return undefined;\n}\n\n/**\n * Creates a program from 2 script tags.\n *\n * NOTE: There are 4 signatures for this function\n *\n * twgl.createProgramFromScripts(gl, [vs, fs], opt_options);\n * twgl.createProgramFromScripts(gl, [vs, fs], opt_errFunc);\n * twgl.createProgramFromScripts(gl, [vs, fs], opt_attribs, opt_errFunc);\n * twgl.createProgramFromScripts(gl, [vs, fs], opt_attribs, opt_locations, opt_errFunc);\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext\n * to use.\n * @param {string[]} shaderScriptIds Array of ids of the script\n * tags for the shaders. The first is assumed to be the\n * vertex shader, the second the fragment shader.\n * @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\n * @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.\n * @param {module:twgl.ErrorCallback} [opt_errorCallback] callback for errors. By default it just prints an error to the console\n * on error. If you want something else pass an callback. It's passed an error message.\n * @return {WebGLProgram?} the created program or null if error or a callback was provided.\n * @memberOf module:twgl/programs\n */\nfunction createProgramFromScripts(\n gl, shaderScriptIds, opt_attribs, opt_locations, opt_errorCallback) {\n const progOptions = getProgramOptions(opt_attribs, opt_locations, opt_errorCallback);\n const shaders = [];\n for (const scriptId of shaderScriptIds) {\n const shaderScript = getElementById(scriptId);\n if (!shaderScript) {\n return reportError(progOptions, `unknown script element: ${scriptId}`);\n }\n shaders.push(shaderScript.text);\n }\n return createProgram(gl, shaders, progOptions);\n}\n\n/**\n * Creates a program from 2 sources.\n *\n * NOTE: There are 4 signatures for this function\n *\n * twgl.createProgramFromSource(gl, [vs, fs], opt_options);\n * twgl.createProgramFromSource(gl, [vs, fs], opt_errFunc);\n * twgl.createProgramFromSource(gl, [vs, fs], opt_attribs, opt_errFunc);\n * twgl.createProgramFromSource(gl, [vs, fs], opt_attribs, opt_locations, opt_errFunc);\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext\n * to use.\n * @param {string[]} shaderSources Array of sources for the\n * shaders. The first is assumed to be the vertex shader,\n * the second the fragment shader.\n * @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\n * @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.\n * @param {module:twgl.ErrorCallback} [opt_errorCallback] callback for errors. By default it just prints an error to the console\n * on error. If you want something else pass an callback. It's passed an error message.\n * @return {WebGLProgram?} the created program or null if error or a callback was provided.\n * @memberOf module:twgl/programs\n */\nfunction createProgramFromSources(\n gl, shaderSources, opt_attribs, opt_locations, opt_errorCallback) {\n return createProgram(gl, shaderSources, opt_attribs, opt_locations, opt_errorCallback);\n}\n\n/**\n * Returns true if attribute/uniform is a reserved/built in\n *\n * It makes no sense to me why GL returns these because it's\n * illegal to call `gl.getUniformLocation` and `gl.getAttribLocation`\n * with names that start with `gl_` (and `webgl_` in WebGL)\n *\n * I can only assume they are there because they might count\n * when computing the number of uniforms/attributes used when you want to\n * know if you are near the limit. That doesn't really make sense\n * to me but the fact that these get returned are in the spec.\n *\n * @param {WebGLActiveInfo} info As returned from `gl.getActiveUniform` or\n * `gl.getActiveAttrib`.\n * @return {bool} true if it's reserved\n * @private\n */\nfunction isBuiltIn(info) {\n const name = info.name;\n return name.startsWith(\"gl_\") || name.startsWith(\"webgl_\");\n}\n\nconst tokenRE = /(\\.|\\[|]|\\w+)/g;\nconst isDigit = s => s >= '0' && s <= '9';\nfunction addSetterToUniformTree(fullPath, setter, node, uniformSetters) {\n const tokens = fullPath.split(tokenRE).filter(s => s !== '');\n let tokenNdx = 0;\n let path = '';\n\n for (;;) {\n const token = tokens[tokenNdx++]; // has to be name or number\n path += token;\n const isArrayIndex = isDigit(token[0]);\n const accessor = isArrayIndex\n ? parseInt(token)\n : token;\n if (isArrayIndex) {\n path += tokens[tokenNdx++]; // skip ']'\n }\n const isLastToken = tokenNdx === tokens.length;\n if (isLastToken) {\n node[accessor] = setter;\n break;\n } else {\n const token = tokens[tokenNdx++]; // has to be . or [\n const isArray = token === '[';\n const child = node[accessor] || (isArray ? [] : {});\n node[accessor] = child;\n node = child;\n uniformSetters[path] = uniformSetters[path] || function(node) {\n return function(value) {\n setUniformTree(node, value);\n };\n }(child);\n path += token;\n }\n }\n}\n\n/**\n * Creates setter functions for all uniforms of a shader\n * program.\n *\n * @see {@link module:twgl.setUniforms}\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use.\n * @param {WebGLProgram} program the program to create setters for.\n * @returns {Object.} an object with a setter by name for each uniform\n * @memberOf module:twgl/programs\n */\nfunction createUniformSetters(gl, program) {\n let textureUnit = 0;\n\n /**\n * Creates a setter for a uniform of the given program with it's\n * location embedded in the setter.\n * @param {WebGLProgram} program\n * @param {WebGLUniformInfo} uniformInfo\n * @returns {function} the created setter.\n */\n function createUniformSetter(program, uniformInfo, location) {\n const isArray = uniformInfo.name.endsWith(\"[0]\");\n const type = uniformInfo.type;\n const typeInfo = typeMap[type];\n if (!typeInfo) {\n throw new Error(`unknown type: 0x${type.toString(16)}`); // we should never get here.\n }\n let setter;\n if (typeInfo.bindPoint) {\n // it's a sampler\n const unit = textureUnit;\n textureUnit += uniformInfo.size;\n if (isArray) {\n setter = typeInfo.arraySetter(gl, type, unit, location, uniformInfo.size);\n } else {\n setter = typeInfo.setter(gl, type, unit, location, uniformInfo.size);\n }\n } else {\n if (typeInfo.arraySetter && isArray) {\n setter = typeInfo.arraySetter(gl, location);\n } else {\n setter = typeInfo.setter(gl, location);\n }\n }\n setter.location = location;\n return setter;\n }\n\n const uniformSetters = {};\n const uniformTree = {};\n const numUniforms = gl.getProgramParameter(program, ACTIVE_UNIFORMS);\n\n for (let ii = 0; ii < numUniforms; ++ii) {\n const uniformInfo = gl.getActiveUniform(program, ii);\n if (isBuiltIn(uniformInfo)) {\n continue;\n }\n let name = uniformInfo.name;\n // remove the array suffix.\n if (name.endsWith(\"[0]\")) {\n name = name.substr(0, name.length - 3);\n }\n const location = gl.getUniformLocation(program, uniformInfo.name);\n // the uniform will have no location if it's in a uniform block\n if (location) {\n const setter = createUniformSetter(program, uniformInfo, location);\n uniformSetters[name] = setter;\n addSetterToUniformTree(name, setter, uniformTree, uniformSetters);\n }\n }\n\n return uniformSetters;\n}\n\n/**\n * @typedef {Object} TransformFeedbackInfo\n * @property {number} index index of transform feedback\n * @property {number} type GL type\n * @property {number} size 1 - 4\n * @memberOf module:twgl\n */\n\n/**\n * Create TransformFeedbackInfo for passing to bindTransformFeedbackInfo.\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use.\n * @param {WebGLProgram} program an existing WebGLProgram.\n * @return {Object}\n * @memberOf module:twgl\n */\nfunction createTransformFeedbackInfo(gl, program) {\n const info = {};\n const numVaryings = gl.getProgramParameter(program, TRANSFORM_FEEDBACK_VARYINGS);\n for (let ii = 0; ii < numVaryings; ++ii) {\n const varying = gl.getTransformFeedbackVarying(program, ii);\n info[varying.name] = {\n index: ii,\n type: varying.type,\n size: varying.size,\n };\n }\n return info;\n}\n\n/**\n * Binds buffers for transform feedback.\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use.\n * @param {(module:twgl.ProgramInfo|Object)} transformFeedbackInfo A ProgramInfo or TransformFeedbackInfo.\n * @param {(module:twgl.BufferInfo|Object)} [bufferInfo] A BufferInfo or set of AttribInfos.\n * @memberOf module:twgl\n */\nfunction bindTransformFeedbackInfo(gl, transformFeedbackInfo, bufferInfo) {\n if (transformFeedbackInfo.transformFeedbackInfo) {\n transformFeedbackInfo = transformFeedbackInfo.transformFeedbackInfo;\n }\n if (bufferInfo.attribs) {\n bufferInfo = bufferInfo.attribs;\n }\n for (const name in bufferInfo) {\n const varying = transformFeedbackInfo[name];\n if (varying) {\n const buf = bufferInfo[name];\n if (buf.offset) {\n gl.bindBufferRange(TRANSFORM_FEEDBACK_BUFFER, varying.index, buf.buffer, buf.offset, buf.size);\n } else {\n gl.bindBufferBase(TRANSFORM_FEEDBACK_BUFFER, varying.index, buf.buffer);\n }\n }\n }\n}\n\n/**\n * Creates a transform feedback and sets the buffers\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use.\n * @param {module:twgl.ProgramInfo} programInfo A ProgramInfo as returned from {@link module:twgl.createProgramInfo}\n * @param {(module:twgl.BufferInfo|Object)} [bufferInfo] A BufferInfo or set of AttribInfos.\n * @return {WebGLTransformFeedback} the created transform feedback\n * @memberOf module:twgl\n */\nfunction createTransformFeedback(gl, programInfo, bufferInfo) {\n const tf = gl.createTransformFeedback();\n gl.bindTransformFeedback(TRANSFORM_FEEDBACK, tf);\n gl.useProgram(programInfo.program);\n bindTransformFeedbackInfo(gl, programInfo, bufferInfo);\n gl.bindTransformFeedback(TRANSFORM_FEEDBACK, null);\n return tf;\n}\n\n/**\n * @typedef {Object} UniformData\n * @property {string} name The name of the uniform\n * @property {number} type The WebGL type enum for this uniform\n * @property {number} size The number of elements for this uniform\n * @property {number} blockNdx The block index this uniform appears in\n * @property {number} offset The byte offset in the block for this uniform's value\n * @memberOf module:twgl\n */\n\n/**\n * The specification for one UniformBlockObject\n *\n * @typedef {Object} BlockSpec\n * @property {number} index The index of the block.\n * @property {number} size The size in bytes needed for the block\n * @property {number[]} uniformIndices The indices of the uniforms used by the block. These indices\n * correspond to entries in a UniformData array in the {@link module:twgl.UniformBlockSpec}.\n * @property {bool} usedByVertexShader Self explanatory\n * @property {bool} usedByFragmentShader Self explanatory\n * @property {bool} used Self explanatory\n * @memberOf module:twgl\n */\n\n/**\n * A `UniformBlockSpec` represents the data needed to create and bind\n * UniformBlockObjects for a given program\n *\n * @typedef {Object} UniformBlockSpec\n * @property {Object.} blockSpecs The BlockSpec for each block by block name\n * @property {UniformData[]} uniformData An array of data for each uniform by uniform index.\n * @memberOf module:twgl\n */\n\n/**\n * Creates a UniformBlockSpec for the given program.\n *\n * A UniformBlockSpec represents the data needed to create and bind\n * UniformBlockObjects\n *\n * @param {WebGL2RenderingContext} gl A WebGL2 Rendering Context\n * @param {WebGLProgram} program A WebGLProgram for a successfully linked program\n * @return {module:twgl.UniformBlockSpec} The created UniformBlockSpec\n * @memberOf module:twgl/programs\n */\nfunction createUniformBlockSpecFromProgram(gl, program) {\n const numUniforms = gl.getProgramParameter(program, ACTIVE_UNIFORMS);\n const uniformData = [];\n const uniformIndices = [];\n\n for (let ii = 0; ii < numUniforms; ++ii) {\n uniformIndices.push(ii);\n uniformData.push({});\n const uniformInfo = gl.getActiveUniform(program, ii);\n uniformData[ii].name = uniformInfo.name;\n }\n\n [\n [ \"UNIFORM_TYPE\", \"type\" ],\n [ \"UNIFORM_SIZE\", \"size\" ], // num elements\n [ \"UNIFORM_BLOCK_INDEX\", \"blockNdx\" ],\n [ \"UNIFORM_OFFSET\", \"offset\", ],\n ].forEach(function(pair) {\n const pname = pair[0];\n const key = pair[1];\n gl.getActiveUniforms(program, uniformIndices, gl[pname]).forEach(function(value, ndx) {\n uniformData[ndx][key] = value;\n });\n });\n\n const blockSpecs = {};\n\n const numUniformBlocks = gl.getProgramParameter(program, ACTIVE_UNIFORM_BLOCKS);\n for (let ii = 0; ii < numUniformBlocks; ++ii) {\n const name = gl.getActiveUniformBlockName(program, ii);\n const blockSpec = {\n index: gl.getUniformBlockIndex(program, name),\n usedByVertexShader: gl.getActiveUniformBlockParameter(program, ii, UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER),\n usedByFragmentShader: gl.getActiveUniformBlockParameter(program, ii, UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER),\n size: gl.getActiveUniformBlockParameter(program, ii, UNIFORM_BLOCK_DATA_SIZE),\n uniformIndices: gl.getActiveUniformBlockParameter(program, ii, UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES),\n };\n blockSpec.used = blockSpec.usedByVertexShader || blockSpec.usedByFragmentShader;\n blockSpecs[name] = blockSpec;\n }\n\n return {\n blockSpecs: blockSpecs,\n uniformData: uniformData,\n };\n}\n\nconst arraySuffixRE = /\\[\\d+\\]\\.$/; // better way to check?\n\nconst pad = (v, padding) => ((v + (padding - 1)) / padding | 0) * padding;\n\nfunction createUniformBlockUniformSetter(view, isArray, rows, cols) {\n if (isArray || rows) {\n cols = cols || 1;\n const numElements = view.length;\n const totalRows = numElements / 4;\n return function(value) {\n let dst = 0;\n let src = 0;\n for (let row = 0; row < totalRows; ++row) {\n for (let col = 0; col < cols; ++col) {\n view[dst++] = value[src++];\n }\n dst += 4 - cols;\n }\n };\n } else {\n return function(value) {\n if (value.length) {\n view.set(value);\n } else {\n view[0] = value;\n }\n };\n }\n}\n\n/**\n * Represents a UniformBlockObject including an ArrayBuffer with all the uniform values\n * and a corresponding WebGLBuffer to hold those values on the GPU\n *\n * @typedef {Object} UniformBlockInfo\n * @property {string} name The name of the block\n * @property {ArrayBuffer} array The array buffer that contains the uniform values\n * @property {Float32Array} asFloat A float view on the array buffer. This is useful\n * inspecting the contents of the buffer in the debugger.\n * @property {WebGLBuffer} buffer A WebGL buffer that will hold a copy of the uniform values for rendering.\n * @property {number} [offset] offset into buffer\n * @property {Object} uniforms A uniform name to ArrayBufferView map.\n * each Uniform has a correctly typed `ArrayBufferView` into array at the correct offset\n * and length of that uniform. So for example a float uniform would have a 1 float `Float32Array`\n * view. A single mat4 would have a 16 element `Float32Array` view. An ivec2 would have an\n * `Int32Array` view, etc.\n * @property {Object} setters A setter for this uniform.\n * The reason to use setters is elements of arrays are padded to vec4 sizes which\n * means if you want to set an array of 4 floats you'd need to set 16 values\n * (or set elements 0, 4, 8, 12). In other words\n * `someBlockInfo.uniforms.some4FloatArrayUniform.set([0, , , , 1, , , , 2, , , , 3])`\n * where as the setter handles just passing in [0, 1, 2, 3] either directly as in\n * `someBlockInfo.setter.some4FloatArrayUniform.set([0, 1, 2, 3])` (not recommended)\n * or via {@link module:twgl.setBlockUniforms}\n * @memberOf module:twgl\n */\n\n/**\n * Creates a `UniformBlockInfo` for the specified block\n *\n * Note: **If the blockName matches no existing blocks a warning is printed to the console and a dummy\n * `UniformBlockInfo` is returned**. This is because when debugging GLSL\n * it is common to comment out large portions of a shader or for example set\n * the final output to a constant. When that happens blocks get optimized out.\n * If this function did not create dummy blocks your code would crash when debugging.\n *\n * @param {WebGL2RenderingContext} gl A WebGL2RenderingContext\n * @param {WebGLProgram} program A WebGLProgram\n * @param {module:twgl.UniformBlockSpec} uniformBlockSpec. A UniformBlockSpec as returned\n * from {@link module:twgl.createUniformBlockSpecFromProgram}.\n * @param {string} blockName The name of the block.\n * @return {module:twgl.UniformBlockInfo} The created UniformBlockInfo\n * @memberOf module:twgl/programs\n */\nfunction createUniformBlockInfoFromProgram(gl, program, uniformBlockSpec, blockName) {\n const blockSpecs = uniformBlockSpec.blockSpecs;\n const uniformData = uniformBlockSpec.uniformData;\n const blockSpec = blockSpecs[blockName];\n if (!blockSpec) {\n warn(\"no uniform block object named:\", blockName);\n return {\n name: blockName,\n uniforms: {},\n };\n }\n const array = new ArrayBuffer(blockSpec.size);\n const buffer = gl.createBuffer();\n const uniformBufferIndex = blockSpec.index;\n gl.bindBuffer(UNIFORM_BUFFER, buffer);\n gl.uniformBlockBinding(program, blockSpec.index, uniformBufferIndex);\n\n let prefix = blockName + \".\";\n if (arraySuffixRE.test(prefix)) {\n prefix = prefix.replace(arraySuffixRE, \".\");\n }\n const uniforms = {};\n const setters = {};\n const setterTree = {};\n blockSpec.uniformIndices.forEach(function(uniformNdx) {\n const data = uniformData[uniformNdx];\n let name = data.name;\n if (name.startsWith(prefix)) {\n name = name.substr(prefix.length);\n }\n const isArray = name.endsWith('[0]');\n if (isArray) {\n name = name.substr(0, name.length - 3);\n }\n const typeInfo = typeMap[data.type];\n const Type = typeInfo.Type;\n const byteLength = isArray\n ? pad(typeInfo.size, 16) * data.size\n : typeInfo.size * data.size;\n const uniformView = new Type(array, data.offset, byteLength / Type.BYTES_PER_ELEMENT);\n uniforms[name] = uniformView;\n // Note: I'm not sure what to do here. The original\n // idea was to create TypedArray views into each part\n // of the block. This is useful, for example if you have\n // a block with { mat4: model; mat4 view; mat4 projection; }\n // you'll get a Float32Array for each one suitable for\n // passing to most JS math libraries including twgl's and glMatrix.js.\n //\n // But, if you have a an array of structures, especially if that\n // array is large, you get a whole bunch of TypedArray views.\n // Every one of them has overhead and switching between them all\n // is probably a cache miss. In that case it would really be better\n // to just have one view (asFloat) and have all the setters\n // just reference the correct portion. But, then you can't easily\n // treat a matrix, or a vec4, as a standalone thing like you can\n // with all the views.\n //\n // Another problem with the views is they are not shared. With\n // uniforms you have one set of setters. With UniformBlockInfo\n // you have a set of setters *pre block instance*. That's because\n // TypedArray views can't be mapped to different buffers.\n //\n // My gut right now is if you really want the speed and compactness\n // then you should probably roll your own solution. TWGL's goal\n // here is ease of use as AFAICT there is no simple generic efficient\n // solution.\n const setter = createUniformBlockUniformSetter(uniformView, isArray, typeInfo.rows, typeInfo.cols);\n setters[name] = setter;\n addSetterToUniformTree(name, setter, setterTree, setters);\n });\n return {\n name: blockName,\n array,\n asFloat: new Float32Array(array), // for debugging\n buffer,\n uniforms,\n setters,\n };\n}\n\n/**\n * Creates a `UniformBlockInfo` for the specified block\n *\n * Note: **If the blockName matches no existing blocks a warning is printed to the console and a dummy\n * `UniformBlockInfo` is returned**. This is because when debugging GLSL\n * it is common to comment out large portions of a shader or for example set\n * the final output to a constant. When that happens blocks get optimized out.\n * If this function did not create dummy blocks your code would crash when debugging.\n *\n * @param {WebGL2RenderingContext} gl A WebGL2RenderingContext\n * @param {module:twgl.ProgramInfo} programInfo a `ProgramInfo`\n * as returned from {@link module:twgl.createProgramInfo}\n * @param {string} blockName The name of the block.\n * @return {module:twgl.UniformBlockInfo} The created UniformBlockInfo\n * @memberOf module:twgl/programs\n */\nfunction createUniformBlockInfo(gl, programInfo, blockName) {\n return createUniformBlockInfoFromProgram(gl, programInfo.program, programInfo.uniformBlockSpec, blockName);\n}\n\n/**\n * Binds a uniform block to the matching uniform block point.\n * Matches by blocks by name so blocks must have the same name not just the same\n * structure.\n *\n * If you have changed any values and you upload the values into the corresponding WebGLBuffer\n * call {@link module:twgl.setUniformBlock} instead.\n *\n * @param {WebGL2RenderingContext} gl A WebGL 2 rendering context.\n * @param {(module:twgl.ProgramInfo|module:twgl.UniformBlockSpec)} programInfo a `ProgramInfo`\n * as returned from {@link module:twgl.createProgramInfo} or or `UniformBlockSpec` as\n * returned from {@link module:twgl.createUniformBlockSpecFromProgram}.\n * @param {module:twgl.UniformBlockInfo} uniformBlockInfo a `UniformBlockInfo` as returned from\n * {@link module:twgl.createUniformBlockInfo}.\n * @return {bool} true if buffer was bound. If the programInfo has no block with the same block name\n * no buffer is bound.\n * @memberOf module:twgl/programs\n */\nfunction bindUniformBlock(gl, programInfo, uniformBlockInfo) {\n const uniformBlockSpec = programInfo.uniformBlockSpec || programInfo;\n const blockSpec = uniformBlockSpec.blockSpecs[uniformBlockInfo.name];\n if (blockSpec) {\n const bufferBindIndex = blockSpec.index;\n gl.bindBufferRange(UNIFORM_BUFFER, bufferBindIndex, uniformBlockInfo.buffer, uniformBlockInfo.offset || 0, uniformBlockInfo.array.byteLength);\n return true;\n }\n return false;\n}\n\n/**\n * Uploads the current uniform values to the corresponding WebGLBuffer\n * and binds that buffer to the program's corresponding bind point for the uniform block object.\n *\n * If you haven't changed any values and you only need to bind the uniform block object\n * call {@link module:twgl.bindUniformBlock} instead.\n *\n * @param {WebGL2RenderingContext} gl A WebGL 2 rendering context.\n * @param {(module:twgl.ProgramInfo|module:twgl.UniformBlockSpec)} programInfo a `ProgramInfo`\n * as returned from {@link module:twgl.createProgramInfo} or or `UniformBlockSpec` as\n * returned from {@link module:twgl.createUniformBlockSpecFromProgram}.\n * @param {module:twgl.UniformBlockInfo} uniformBlockInfo a `UniformBlockInfo` as returned from\n * {@link module:twgl.createUniformBlockInfo}.\n * @memberOf module:twgl/programs\n */\nfunction setUniformBlock(gl, programInfo, uniformBlockInfo) {\n if (bindUniformBlock(gl, programInfo, uniformBlockInfo)) {\n gl.bufferData(UNIFORM_BUFFER, uniformBlockInfo.array, DYNAMIC_DRAW);\n }\n}\n\n/**\n * Sets values of a uniform block object\n *\n * @param {module:twgl.UniformBlockInfo} uniformBlockInfo A UniformBlockInfo as returned by {@link module:twgl.createUniformBlockInfo}.\n * @param {Object.} values A uniform name to value map where the value is correct for the given\n * type of uniform. So for example given a block like\n *\n * uniform SomeBlock {\n * float someFloat;\n * vec2 someVec2;\n * vec3 someVec3Array[2];\n * int someInt;\n * }\n *\n * You can set the values of the uniform block with\n *\n * twgl.setBlockUniforms(someBlockInfo, {\n * someFloat: 12.3,\n * someVec2: [1, 2],\n * someVec3Array: [1, 2, 3, 4, 5, 6],\n * someInt: 5,\n * }\n *\n * Arrays can be JavaScript arrays or typed arrays\n *\n * You can also fill out structure and array values either via\n * shortcut. Example\n *\n * // -- in shader --\n * struct Light {\n * float intensity;\n * vec4 color;\n * float nearFar[2];\n * };\n * uniform Lights {\n * Light lights[2];\n * };\n *\n * // in JavaScript\n *\n * twgl.setBlockUniforms(someBlockInfo, {\n * lights: [\n * { intensity: 5.0, color: [1, 0, 0, 1], nearFar[0.1, 10] },\n * { intensity: 2.0, color: [0, 0, 1, 1], nearFar[0.2, 15] },\n * ],\n * });\n *\n * or the more traditional way\n *\n * twgl.setBlockUniforms(someBlockInfo, {\n * \"lights[0].intensity\": 5.0,\n * \"lights[0].color\": [1, 0, 0, 1],\n * \"lights[0].nearFar\": [0.1, 10],\n * \"lights[1].intensity\": 2.0,\n * \"lights[1].color\": [0, 0, 1, 1],\n * \"lights[1].nearFar\": [0.2, 15],\n * });\n *\n * You can also specify partial paths\n *\n * twgl.setBlockUniforms(someBlockInfo, {\n * 'lights[1]': { intensity: 5.0, color: [1, 0, 0, 1], nearFar[0.2, 15] },\n * });\n *\n * But you can not specify leaf array indices.\n *\n * twgl.setBlockUniforms(someBlockInfo, {\n * 'lights[1].nearFar[1]': 15, // BAD! nearFar is a leaf\n * 'lights[1].nearFar': [0.2, 15], // GOOD\n * });\n *\n * **IMPORTANT!**, packing in a UniformBlock is unintuitive.\n * For example the actual layout of `someVec3Array` above in memory\n * is `1, 2, 3, unused, 4, 5, 6, unused`. twgl takes in 6 values\n * as shown about and copies them, skipping the padding. This might\n * be confusing if you're already familiar with Uniform blocks.\n *\n * If you want to deal with the padding yourself you can access the array\n * buffer views directly. eg:\n *\n * someBlockInfo.someVec3Array.set([1, 2, 3, 0, 4, 5, 6, 0]);\n *\n * Any name that doesn't match will be ignored\n * @memberOf module:twgl/programs\n */\nfunction setBlockUniforms(uniformBlockInfo, values) {\n const setters = uniformBlockInfo.setters;\n for (const name in values) {\n const setter = setters[name];\n if (setter) {\n const value = values[name];\n setter(value);\n }\n }\n}\n\nfunction setUniformTree(tree, values) {\n for (const name in values) {\n const prop = tree[name];\n if (typeof prop === 'function') {\n prop(values[name]);\n } else {\n setUniformTree(tree[name], values[name]);\n }\n }\n}\n\n/**\n * Set uniforms and binds related textures.\n *\n * example:\n *\n * const programInfo = createProgramInfo(\n * gl, [\"some-vs\", \"some-fs\"]);\n *\n * const tex1 = gl.createTexture();\n * const tex2 = gl.createTexture();\n *\n * ... assume we setup the textures with data ...\n *\n * const uniforms = {\n * u_someSampler: tex1,\n * u_someOtherSampler: tex2,\n * u_someColor: [1,0,0,1],\n * u_somePosition: [0,1,1],\n * u_someMatrix: [\n * 1,0,0,0,\n * 0,1,0,0,\n * 0,0,1,0,\n * 0,0,0,0,\n * ],\n * };\n *\n * gl.useProgram(programInfo.program);\n *\n * This will automatically bind the textures AND set the\n * uniforms.\n *\n * twgl.setUniforms(programInfo, uniforms);\n *\n * For the example above it is equivalent to\n *\n * let texUnit = 0;\n * gl.activeTexture(gl.TEXTURE0 + texUnit);\n * gl.bindTexture(gl.TEXTURE_2D, tex1);\n * gl.uniform1i(u_someSamplerLocation, texUnit++);\n * gl.activeTexture(gl.TEXTURE0 + texUnit);\n * gl.bindTexture(gl.TEXTURE_2D, tex2);\n * gl.uniform1i(u_someSamplerLocation, texUnit++);\n * gl.uniform4fv(u_someColorLocation, [1, 0, 0, 1]);\n * gl.uniform3fv(u_somePositionLocation, [0, 1, 1]);\n * gl.uniformMatrix4fv(u_someMatrix, false, [\n * 1,0,0,0,\n * 0,1,0,0,\n * 0,0,1,0,\n * 0,0,0,0,\n * ]);\n *\n * Note it is perfectly reasonable to call `setUniforms` multiple times. For example\n *\n * const uniforms = {\n * u_someSampler: tex1,\n * u_someOtherSampler: tex2,\n * };\n *\n * const moreUniforms {\n * u_someColor: [1,0,0,1],\n * u_somePosition: [0,1,1],\n * u_someMatrix: [\n * 1,0,0,0,\n * 0,1,0,0,\n * 0,0,1,0,\n * 0,0,0,0,\n * ],\n * };\n *\n * twgl.setUniforms(programInfo, uniforms);\n * twgl.setUniforms(programInfo, moreUniforms);\n *\n * You can also add WebGLSamplers to uniform samplers as in\n *\n * const uniforms = {\n * u_someSampler: {\n * texture: someWebGLTexture,\n * sampler: someWebGLSampler,\n * },\n * };\n *\n * In which case both the sampler and texture will be bound to the\n * same unit.\n *\n * @param {(module:twgl.ProgramInfo|Object.)} setters a `ProgramInfo` as returned from `createProgramInfo` or the setters returned from\n * `createUniformSetters`.\n * @param {Object.} values an object with values for the\n * uniforms.\n * You can pass multiple objects by putting them in an array or by calling with more arguments.For example\n *\n * const sharedUniforms = {\n * u_fogNear: 10,\n * u_projection: ...\n * ...\n * };\n *\n * const localUniforms = {\n * u_world: ...\n * u_diffuseColor: ...\n * };\n *\n * twgl.setUniforms(programInfo, sharedUniforms, localUniforms);\n *\n * // is the same as\n *\n * twgl.setUniforms(programInfo, [sharedUniforms, localUniforms]);\n *\n * // is the same as\n *\n * twgl.setUniforms(programInfo, sharedUniforms);\n * twgl.setUniforms(programInfo, localUniforms};\n *\n * You can also fill out structure and array values either via\n * shortcut. Example\n *\n * // -- in shader --\n * struct Light {\n * float intensity;\n * vec4 color;\n * float nearFar[2];\n * };\n * uniform Light lights[2];\n *\n * // in JavaScript\n *\n * twgl.setUniforms(programInfo, {\n * lights: [\n * { intensity: 5.0, color: [1, 0, 0, 1], nearFar[0.1, 10] },\n * { intensity: 2.0, color: [0, 0, 1, 1], nearFar[0.2, 15] },\n * ],\n * });\n *\n * or the more traditional way\n *\n * twgl.setUniforms(programInfo, {\n * \"lights[0].intensity\": 5.0,\n * \"lights[0].color\": [1, 0, 0, 1],\n * \"lights[0].nearFar\": [0.1, 10],\n * \"lights[1].intensity\": 2.0,\n * \"lights[1].color\": [0, 0, 1, 1],\n * \"lights[1].nearFar\": [0.2, 15],\n * });\n *\n * You can also specify partial paths\n *\n * twgl.setUniforms(programInfo, {\n * 'lights[1]': { intensity: 5.0, color: [1, 0, 0, 1], nearFar[0.2, 15] },\n * });\n *\n * But you can not specify leaf array indices\n *\n * twgl.setUniforms(programInfo, {\n * 'lights[1].nearFar[1]': 15, // BAD! nearFar is a leaf\n * 'lights[1].nearFar': [0.2, 15], // GOOD\n * });\n *\n * @memberOf module:twgl/programs\n */\nfunction setUniforms(setters, ...args) { // eslint-disable-line\n const actualSetters = setters.uniformSetters || setters;\n const numArgs = args.length;\n for (let aNdx = 0; aNdx < numArgs; ++aNdx) {\n const values = args[aNdx];\n if (Array.isArray(values)) {\n const numValues = values.length;\n for (let ii = 0; ii < numValues; ++ii) {\n setUniforms(actualSetters, values[ii]);\n }\n } else {\n for (const name in values) {\n const setter = actualSetters[name];\n if (setter) {\n setter(values[name]);\n }\n }\n }\n }\n}\n\n/**\n * Alias for `setUniforms`\n * @function\n * @param {(module:twgl.ProgramInfo|Object.)} setters a `ProgramInfo` as returned from `createProgramInfo` or the setters returned from\n * `createUniformSetters`.\n * @param {Object.} values an object with values for the\n * @memberOf module:twgl/programs\n */\nconst setUniformsAndBindTextures = setUniforms;\n\n/**\n * Creates setter functions for all attributes of a shader\n * program. You can pass this to {@link module:twgl.setBuffersAndAttributes} to set all your buffers and attributes.\n *\n * @see {@link module:twgl.setAttributes} for example\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use.\n * @param {WebGLProgram} program the program to create setters for.\n * @return {Object.} an object with a setter for each attribute by name.\n * @memberOf module:twgl/programs\n */\nfunction createAttributeSetters(gl, program) {\n const attribSetters = {\n };\n\n const numAttribs = gl.getProgramParameter(program, ACTIVE_ATTRIBUTES);\n for (let ii = 0; ii < numAttribs; ++ii) {\n const attribInfo = gl.getActiveAttrib(program, ii);\n if (isBuiltIn(attribInfo)) {\n continue;\n }\n const index = gl.getAttribLocation(program, attribInfo.name);\n const typeInfo = attrTypeMap[attribInfo.type];\n const setter = typeInfo.setter(gl, index, typeInfo);\n setter.location = index;\n attribSetters[attribInfo.name] = setter;\n }\n\n return attribSetters;\n}\n\n/**\n * Sets attributes and binds buffers (deprecated... use {@link module:twgl.setBuffersAndAttributes})\n *\n * Example:\n *\n * const program = createProgramFromScripts(\n * gl, [\"some-vs\", \"some-fs\");\n *\n * const attribSetters = createAttributeSetters(program);\n *\n * const positionBuffer = gl.createBuffer();\n * const texcoordBuffer = gl.createBuffer();\n *\n * const attribs = {\n * a_position: {buffer: positionBuffer, numComponents: 3},\n * a_texcoord: {buffer: texcoordBuffer, numComponents: 2},\n * };\n *\n * gl.useProgram(program);\n *\n * This will automatically bind the buffers AND set the\n * attributes.\n *\n * setAttributes(attribSetters, attribs);\n *\n * Properties of attribs. For each attrib you can add\n * properties:\n *\n * * type: the type of data in the buffer. Default = gl.FLOAT\n * * normalize: whether or not to normalize the data. Default = false\n * * stride: the stride. Default = 0\n * * offset: offset into the buffer. Default = 0\n * * divisor: the divisor for instances. Default = undefined\n *\n * For example if you had 3 value float positions, 2 value\n * float texcoord and 4 value uint8 colors you'd setup your\n * attribs like this\n *\n * const attribs = {\n * a_position: {buffer: positionBuffer, numComponents: 3},\n * a_texcoord: {buffer: texcoordBuffer, numComponents: 2},\n * a_color: {\n * buffer: colorBuffer,\n * numComponents: 4,\n * type: gl.UNSIGNED_BYTE,\n * normalize: true,\n * },\n * };\n *\n * @param {Object.} setters Attribute setters as returned from createAttributeSetters\n * @param {Object.} buffers AttribInfos mapped by attribute name.\n * @memberOf module:twgl/programs\n * @deprecated use {@link module:twgl.setBuffersAndAttributes}\n * @private\n */\nfunction setAttributes(setters, buffers) {\n for (const name in buffers) {\n const setter = setters[name];\n if (setter) {\n setter(buffers[name]);\n }\n }\n}\n\n/**\n * Sets attributes and buffers including the `ELEMENT_ARRAY_BUFFER` if appropriate\n *\n * Example:\n *\n * const programInfo = createProgramInfo(\n * gl, [\"some-vs\", \"some-fs\");\n *\n * const arrays = {\n * position: { numComponents: 3, data: [0, 0, 0, 10, 0, 0, 0, 10, 0, 10, 10, 0], },\n * texcoord: { numComponents: 2, data: [0, 0, 0, 1, 1, 0, 1, 1], },\n * };\n *\n * const bufferInfo = createBufferInfoFromArrays(gl, arrays);\n *\n * gl.useProgram(programInfo.program);\n *\n * This will automatically bind the buffers AND set the\n * attributes.\n *\n * setBuffersAndAttributes(gl, programInfo, bufferInfo);\n *\n * For the example above it is equivalent to\n *\n * gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);\n * gl.enableVertexAttribArray(a_positionLocation);\n * gl.vertexAttribPointer(a_positionLocation, 3, gl.FLOAT, false, 0, 0);\n * gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);\n * gl.enableVertexAttribArray(a_texcoordLocation);\n * gl.vertexAttribPointer(a_texcoordLocation, 4, gl.FLOAT, false, 0, 0);\n *\n * @param {WebGLRenderingContext} gl A WebGLRenderingContext.\n * @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}\n * @param {(module:twgl.BufferInfo|module:twgl.VertexArrayInfo)} buffers a `BufferInfo` as returned from {@link module:twgl.createBufferInfoFromArrays}.\n * or a `VertexArrayInfo` as returned from {@link module:twgl.createVertexArrayInfo}\n * @memberOf module:twgl/programs\n */\nfunction setBuffersAndAttributes(gl, programInfo, buffers) {\n if (buffers.vertexArrayObject) {\n gl.bindVertexArray(buffers.vertexArrayObject);\n } else {\n setAttributes(programInfo.attribSetters || programInfo, buffers.attribs);\n if (buffers.indices) {\n gl.bindBuffer(ELEMENT_ARRAY_BUFFER$1, buffers.indices);\n }\n }\n}\n\n/**\n * @typedef {Object} ProgramInfo\n * @property {WebGLProgram} program A shader program\n * @property {Object} uniformSetters object of setters as returned from createUniformSetters,\n * @property {Object} attribSetters object of setters as returned from createAttribSetters,\n * @property {module:twgl.UniformBlockSpec} [uniformBlockSpec] a uniform block spec for making UniformBlockInfos with createUniformBlockInfo etc..\n * @property {Object} [transformFeedbackInfo] info for transform feedbacks\n * @memberOf module:twgl\n */\n\n/**\n * Creates a ProgramInfo from an existing program.\n *\n * A ProgramInfo contains\n *\n * programInfo = {\n * program: WebGLProgram,\n * uniformSetters: object of setters as returned from createUniformSetters,\n * attribSetters: object of setters as returned from createAttribSetters,\n * }\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext\n * to use.\n * @param {WebGLProgram} program an existing WebGLProgram.\n * @return {module:twgl.ProgramInfo} The created ProgramInfo.\n * @memberOf module:twgl/programs\n */\nfunction createProgramInfoFromProgram(gl, program) {\n const uniformSetters = createUniformSetters(gl, program);\n const attribSetters = createAttributeSetters(gl, program);\n const programInfo = {\n program,\n uniformSetters,\n attribSetters,\n };\n\n if (isWebGL2(gl)) {\n programInfo.uniformBlockSpec = createUniformBlockSpecFromProgram(gl, program);\n programInfo.transformFeedbackInfo = createTransformFeedbackInfo(gl, program);\n }\n\n return programInfo;\n}\n\nconst notIdRE = /\\s|{|}|;/;\n\n/**\n * Creates a ProgramInfo from 2 sources.\n *\n * A ProgramInfo contains\n *\n * programInfo = {\n * program: WebGLProgram,\n * uniformSetters: object of setters as returned from createUniformSetters,\n * attribSetters: object of setters as returned from createAttribSetters,\n * }\n *\n * NOTE: There are 4 signatures for this function\n *\n * twgl.createProgramInfo(gl, [vs, fs], options);\n * twgl.createProgramInfo(gl, [vs, fs], opt_errFunc);\n * twgl.createProgramInfo(gl, [vs, fs], opt_attribs, opt_errFunc);\n * twgl.createProgramInfo(gl, [vs, fs], opt_attribs, opt_locations, opt_errFunc);\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext\n * to use.\n * @param {string[]} shaderSources Array of sources for the\n * shaders or ids. The first is assumed to be the vertex shader,\n * the second the fragment shader.\n * @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\n * @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.\n * @param {module:twgl.ErrorCallback} [opt_errorCallback] callback for errors. By default it just prints an error to the console\n * on error. If you want something else pass an callback. It's passed an error message.\n * @return {module:twgl.ProgramInfo?} The created ProgramInfo or null if it failed to link or compile\n * @memberOf module:twgl/programs\n */\nfunction createProgramInfo(\n gl, shaderSources, opt_attribs, opt_locations, opt_errorCallback) {\n const progOptions = getProgramOptions(opt_attribs, opt_locations, opt_errorCallback);\n const errors = [];\n shaderSources = shaderSources.map(function(source) {\n // Lets assume if there is no \\n it's an id\n if (!notIdRE.test(source)) {\n const script = getElementById(source);\n if (!script) {\n const err = `no element with id: ${source}`;\n progOptions.errorCallback(err);\n errors.push(err);\n } else {\n source = script.text;\n }\n }\n return source;\n });\n\n if (errors.length) {\n return reportError(progOptions, '');\n }\n\n const origCallback = progOptions.callback;\n if (origCallback) {\n progOptions.callback = (err, program) => {\n origCallback(err, err ? undefined : createProgramInfoFromProgram(gl, program));\n };\n }\n\n const program = createProgramFromSources(gl, shaderSources, progOptions);\n if (!program) {\n return null;\n }\n\n return createProgramInfoFromProgram(gl, program);\n}\n\nfunction checkAllPrograms(gl, programs, programSpecs, noDeleteShadersSet, programOptions) {\n // check errors for everything.\n for (const [name, program] of Object.entries(programs)) {\n const options = {...programOptions};\n const spec = programSpecs[name];\n if (!Array.isArray(spec)) {\n Object.assign(options, spec);\n }\n const errors = getProgramErrors(gl, program, options.errorCallback);\n if (errors) {\n // delete everything we created\n for (const program of Object.values(programs)) {\n const shaders = gl.getAttachedShaders(program);\n gl.deleteProgram(program);\n for (const shader of shaders) {\n // Don't delete it if we didn't create it.\n if (!noDeleteShadersSet.has(shader)) {\n gl.deleteShader(shader);\n }\n }\n }\n return errors;\n }\n }\n\n return undefined;\n}\n\n/**\n * Creates multiple programs\n *\n * Note: the reason this function exists is because the fastest way to create multiple\n * programs in WebGL is to create and compile all shaders and link all programs and only\n * afterwards check if they succeeded. In that way, giving all your shaders\n *\n * @see {@link module:twgl.createProgram}\n *\n * Example:\n *\n * const programs = twgl.createPrograms(gl, {\n * lambert: [lambertVS, lambertFS],\n * phong: [phongVS, phoneFS],\n * particles: {\n * shaders: [particlesVS, particlesFS],\n * transformFeedbackVaryings: ['position', 'velocity'],\n * },\n * });\n *\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {Object.} programSpecs An object of ProgramSpecs, one per program.\n * @param {module:twgl.ProgramOptions} [programOptions] options to apply to all programs\n * @return {Object.?} the created programInfos by name\n */\nfunction createPrograms(gl, programSpecs, programOptions = {}) {\n // Remember existing shaders so that if there is an error we don't delete them\n const noDeleteShadersSet = new Set();\n\n // compile and link everything\n const programs = Object.fromEntries(Object.entries(programSpecs).map(([name, spec]) => {\n const options = {...programOptions};\n const shaders = Array.isArray(spec) ? spec : spec.shaders;\n if (!Array.isArray(spec)) {\n Object.assign(options, spec);\n }\n shaders.forEach(noDeleteShadersSet.add, noDeleteShadersSet);\n return [name, createProgramNoCheck(gl, shaders, options)];\n }));\n\n if (programOptions.callback) {\n waitForAllProgramsLinkCompletionAsync(gl, programs).then(() => {\n const errors = checkAllPrograms(gl, programs, programSpecs, noDeleteShadersSet, programOptions);\n programOptions.callback(errors, errors ? undefined : programs);\n });\n return undefined;\n }\n\n const errors = checkAllPrograms(gl, programs, programSpecs, noDeleteShadersSet, programOptions);\n return errors ? undefined : programs;\n}\n\n/**\n * Creates multiple programInfos\n *\n * Note: the reason this function exists is because the fastest way to create multiple\n * programs in WebGL is to create and compile all shaders and link all programs and only\n * afterwards check if they succeeded. In that way, giving all your shaders\n *\n * @see {@link module:twgl.createProgramInfo}\n *\n * Examples:\n *\n * const programInfos = twgl.createProgramInfos(gl, {\n * lambert: [lambertVS, lambertFS],\n * phong: [phongVS, phoneFS],\n * particles: {\n * shaders: [particlesVS, particlesFS],\n * transformFeedbackVaryings: ['position', 'velocity'],\n * },\n * });\n *\n * or\n *\n * const {lambert, phong, particles} = twgl.createProgramInfos(gl, {\n * lambert: [lambertVS, lambertFS],\n * phong: [phongVS, phoneFS],\n * particles: {\n * shaders: [particlesVS, particlesFS],\n * transformFeedbackVaryings: ['position', 'velocity'],\n * },\n * });\n *\n *\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {Object.} programSpecs An object of ProgramSpecs, one per program.\n * @param {module:twgl.ProgramOptions} [programOptions] options to apply to all programs\n * @return {Object.?} the created programInfos by name\n */\nfunction createProgramInfos(gl, programSpecs, programOptions) {\n programOptions = getProgramOptions(programOptions);\n\n function createProgramInfosForPrograms(gl, programs) {\n return Object.fromEntries(Object.entries(programs).map(([name, program]) =>\n [name, createProgramInfoFromProgram(gl, program)]\n ));\n }\n\n const origCallback = programOptions.callback;\n if (origCallback) {\n programOptions.callback = (err, programs) => {\n origCallback(err, err ? undefined : createProgramInfosForPrograms(gl, programs));\n };\n }\n\n const programs = createPrograms(gl, programSpecs, programOptions);\n if (origCallback || !programs) {\n return undefined;\n }\n\n return createProgramInfosForPrograms(gl, programs);\n}\n\n/**\n * Creates multiple programs asynchronously\n *\n * @see {@link module:twgl.createProgramAsync}\n *\n * Example:\n *\n * const programs = await twgl.createProgramsAsync(gl, {\n * lambert: [lambertVS, lambertFS],\n * phong: [phongVS, phoneFS],\n * particles: {\n * shaders: [particlesVS, particlesFS],\n * transformFeedbackVaryings: ['position', 'velocity'],\n * },\n * });\n *\n * @function\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {Object.} programSpecs An object of ProgramSpecs, one per program.\n * @param {module:twgl.ProgramOptions} [programOptions] options to apply to all programs\n * @return {Object.?} the created programInfos by name\n */\nconst createProgramsAsync = wrapCallbackFnToAsyncFn(createPrograms);\n\n/**\n * Creates multiple programInfos asynchronously\n *\n * @see {@link module:twgl.createProgramInfoAsync}\n *\n * Example:\n *\n * const programInfos = await twgl.createProgramInfosAsync(gl, {\n * lambert: [lambertVS, lambertFS],\n * phong: [phongVS, phoneFS],\n * particles: {\n * shaders: [particlesVS, particlesFS],\n * transformFeedbackVaryings: ['position', 'velocity'],\n * },\n * });\n *\n * @function\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {Object.} programSpecs An object of ProgramSpecs, one per program.\n * @param {module:twgl.ProgramOptions} [programOptions] options to apply to all programs\n * @return {Promise>} the created programInfos by name\n */\nconst createProgramInfosAsync = wrapCallbackFnToAsyncFn(createProgramInfos);\n\nvar programs = /*#__PURE__*/Object.freeze({\n __proto__: null,\n createAttributeSetters: createAttributeSetters,\n createProgram: createProgram,\n createProgramAsync: createProgramAsync,\n createPrograms: createPrograms,\n createProgramsAsync: createProgramsAsync,\n createProgramFromScripts: createProgramFromScripts,\n createProgramFromSources: createProgramFromSources,\n createProgramInfo: createProgramInfo,\n createProgramInfoAsync: createProgramInfoAsync,\n createProgramInfos: createProgramInfos,\n createProgramInfosAsync: createProgramInfosAsync,\n createProgramInfoFromProgram: createProgramInfoFromProgram,\n createUniformSetters: createUniformSetters,\n createUniformBlockSpecFromProgram: createUniformBlockSpecFromProgram,\n createUniformBlockInfoFromProgram: createUniformBlockInfoFromProgram,\n createUniformBlockInfo: createUniformBlockInfo,\n createTransformFeedback: createTransformFeedback,\n createTransformFeedbackInfo: createTransformFeedbackInfo,\n bindTransformFeedbackInfo: bindTransformFeedbackInfo,\n setAttributes: setAttributes,\n setBuffersAndAttributes: setBuffersAndAttributes,\n setUniforms: setUniforms,\n setUniformsAndBindTextures: setUniformsAndBindTextures,\n setUniformBlock: setUniformBlock,\n setBlockUniforms: setBlockUniforms,\n bindUniformBlock: bindUniformBlock\n});\n\n/*\n * Copyright 2019 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\nconst TRIANGLES = 0x0004;\nconst UNSIGNED_SHORT = 0x1403;\n\n/**\n * Drawing related functions\n *\n * For backward compatibility they are available at both `twgl.draw` and `twgl`\n * itself\n *\n * See {@link module:twgl} for core functions\n *\n * @module twgl/draw\n */\n\n/**\n * Calls `gl.drawElements` or `gl.drawArrays`, whichever is appropriate\n *\n * normally you'd call `gl.drawElements` or `gl.drawArrays` yourself\n * but calling this means if you switch from indexed data to non-indexed\n * data you don't have to remember to update your draw call.\n *\n * @param {WebGLRenderingContext} gl A WebGLRenderingContext\n * @param {(module:twgl.BufferInfo|module:twgl.VertexArrayInfo)} bufferInfo A BufferInfo as returned from {@link module:twgl.createBufferInfoFromArrays} or\n * a VertexArrayInfo as returned from {@link module:twgl.createVertexArrayInfo}\n * @param {number} [type] eg (gl.TRIANGLES, gl.LINES, gl.POINTS, gl.TRIANGLE_STRIP, ...). Defaults to `gl.TRIANGLES`\n * @param {number} [count] An optional count. Defaults to bufferInfo.numElements\n * @param {number} [offset] An optional offset. Defaults to 0.\n * @param {number} [instanceCount] An optional instanceCount. if set then `drawArraysInstanced` or `drawElementsInstanced` will be called\n * @memberOf module:twgl/draw\n */\nfunction drawBufferInfo(gl, bufferInfo, type, count, offset, instanceCount) {\n type = type === undefined ? TRIANGLES : type;\n const indices = bufferInfo.indices;\n const elementType = bufferInfo.elementType;\n const numElements = count === undefined ? bufferInfo.numElements : count;\n offset = offset === undefined ? 0 : offset;\n if (elementType || indices) {\n if (instanceCount !== undefined) {\n gl.drawElementsInstanced(type, numElements, elementType === undefined ? UNSIGNED_SHORT : bufferInfo.elementType, offset, instanceCount);\n } else {\n gl.drawElements(type, numElements, elementType === undefined ? UNSIGNED_SHORT : bufferInfo.elementType, offset);\n }\n } else {\n if (instanceCount !== undefined) {\n gl.drawArraysInstanced(type, offset, numElements, instanceCount);\n } else {\n gl.drawArrays(type, offset, numElements);\n }\n }\n}\n\n/**\n * A DrawObject is useful for putting objects in to an array and passing them to {@link module:twgl.drawObjectList}.\n *\n * You need either a `BufferInfo` or a `VertexArrayInfo`.\n *\n * @typedef {Object} DrawObject\n * @property {boolean} [active] whether or not to draw. Default = `true` (must be `false` to be not true). In other words `undefined` = `true`\n * @property {number} [type] type to draw eg. `gl.TRIANGLES`, `gl.LINES`, etc...\n * @property {module:twgl.ProgramInfo} programInfo A ProgramInfo as returned from {@link module:twgl.createProgramInfo}\n * @property {module:twgl.BufferInfo} [bufferInfo] A BufferInfo as returned from {@link module:twgl.createBufferInfoFromArrays}\n * @property {module:twgl.VertexArrayInfo} [vertexArrayInfo] A VertexArrayInfo as returned from {@link module:twgl.createVertexArrayInfo}\n * @property {Object} uniforms The values for the uniforms.\n * You can pass multiple objects by putting them in an array. For example\n *\n * var sharedUniforms = {\n * u_fogNear: 10,\n * u_projection: ...\n * ...\n * };\n *\n * var localUniforms = {\n * u_world: ...\n * u_diffuseColor: ...\n * };\n *\n * var drawObj = {\n * ...\n * uniforms: [sharedUniforms, localUniforms],\n * };\n *\n * @property {number} [offset] the offset to pass to `gl.drawArrays` or `gl.drawElements`. Defaults to 0.\n * @property {number} [count] the count to pass to `gl.drawArrays` or `gl.drawElements`. Defaults to bufferInfo.numElements.\n * @property {number} [instanceCount] the number of instances. Defaults to undefined.\n * @memberOf module:twgl\n */\n\n/**\n * Draws a list of objects\n * @param {WebGLRenderingContext} gl A WebGLRenderingContext\n * @param {DrawObject[]} objectsToDraw an array of objects to draw.\n * @memberOf module:twgl/draw\n */\nfunction drawObjectList(gl, objectsToDraw) {\n let lastUsedProgramInfo = null;\n let lastUsedBufferInfo = null;\n\n objectsToDraw.forEach(function(object) {\n if (object.active === false) {\n return;\n }\n\n const programInfo = object.programInfo;\n const bufferInfo = object.vertexArrayInfo || object.bufferInfo;\n let bindBuffers = false;\n const type = object.type === undefined ? TRIANGLES : object.type;\n\n if (programInfo !== lastUsedProgramInfo) {\n lastUsedProgramInfo = programInfo;\n gl.useProgram(programInfo.program);\n\n // We have to rebind buffers when changing programs because we\n // only bind buffers the program uses. So if 2 programs use the same\n // bufferInfo but the 1st one uses only positions the when the\n // we switch to the 2nd one some of the attributes will not be on.\n bindBuffers = true;\n }\n\n // Setup all the needed attributes.\n if (bindBuffers || bufferInfo !== lastUsedBufferInfo) {\n if (lastUsedBufferInfo && lastUsedBufferInfo.vertexArrayObject && !bufferInfo.vertexArrayObject) {\n gl.bindVertexArray(null);\n }\n lastUsedBufferInfo = bufferInfo;\n setBuffersAndAttributes(gl, programInfo, bufferInfo);\n }\n\n // Set the uniforms.\n setUniforms(programInfo, object.uniforms);\n\n // Draw\n drawBufferInfo(gl, bufferInfo, type, object.count, object.offset, object.instanceCount);\n });\n\n if (lastUsedBufferInfo && lastUsedBufferInfo.vertexArrayObject) {\n gl.bindVertexArray(null);\n }\n}\n\nvar draw = /*#__PURE__*/Object.freeze({\n __proto__: null,\n drawBufferInfo: drawBufferInfo,\n drawObjectList: drawObjectList\n});\n\n/*\n * Copyright 2019 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\nconst FRAMEBUFFER = 0x8d40;\nconst RENDERBUFFER = 0x8d41;\nconst TEXTURE_2D = 0x0de1;\n\nconst UNSIGNED_BYTE = 0x1401;\n\n/* PixelFormat */\nconst DEPTH_COMPONENT = 0x1902;\nconst RGBA = 0x1908;\nconst DEPTH_COMPONENT24 = 0x81a6;\nconst DEPTH_COMPONENT32F = 0x8cac;\nconst DEPTH24_STENCIL8 = 0x88f0;\nconst DEPTH32F_STENCIL8 = 0x8cad;\n\n/* Framebuffer Object. */\nconst RGBA4 = 0x8056;\nconst RGB5_A1 = 0x8057;\nconst RGB565 = 0x8D62;\nconst DEPTH_COMPONENT16 = 0x81A5;\nconst STENCIL_INDEX = 0x1901;\nconst STENCIL_INDEX8 = 0x8D48;\nconst DEPTH_STENCIL = 0x84F9;\nconst COLOR_ATTACHMENT0 = 0x8CE0;\nconst DEPTH_ATTACHMENT = 0x8D00;\nconst STENCIL_ATTACHMENT = 0x8D20;\nconst DEPTH_STENCIL_ATTACHMENT = 0x821A;\n\n/* TextureWrapMode */\nconst CLAMP_TO_EDGE = 0x812F;\n\n/* TextureMagFilter */\nconst LINEAR = 0x2601;\n\n/**\n * The options for a framebuffer attachment.\n *\n * Note: For a `format` that is a texture include all the texture\n * options from {@link module:twgl.TextureOptions} for example\n * `min`, `mag`, `clamp`, etc... Note that unlike {@link module:twgl.TextureOptions}\n * `auto` defaults to `false` for attachment textures but `min` and `mag` default\n * to `gl.LINEAR` and `wrap` defaults to `CLAMP_TO_EDGE`\n *\n * @typedef {Object} AttachmentOptions\n * @property {number} [attachmentPoint] The attachment point. Defaults\n * to `gl.COLOR_ATTACHMENT0 + ndx` unless type is a depth or stencil type\n * then it's gl.DEPTH_ATTACHMENT or `gl.DEPTH_STENCIL_ATTACHMENT` depending\n * on the format or attachment type.\n * @property {number} [format] The format. If one of `gl.RGBA4`,\n * `gl.RGB565`, `gl.RGB5_A1`, `gl.DEPTH_COMPONENT16`,\n * `gl.STENCIL_INDEX8` or `gl.DEPTH_STENCIL` then will create a\n * renderbuffer. Otherwise will create a texture. Default = `gl.RGBA`\n * @property {number} [type] The type. Used for texture. Default = `gl.UNSIGNED_BYTE`.\n * @property {number} [target] The texture target for `gl.framebufferTexture2D`.\n * Defaults to `gl.TEXTURE_2D`. Set to appropriate face for cube maps.\n * @property {number} [samples] The number of samples. Default = 1\n * @property {number} [level] level for `gl.framebufferTexture2D`. Defaults to 0.\n * @property {number} [layer] layer for `gl.framebufferTextureLayer`. Defaults to undefined.\n * If set then `gl.framebufferTextureLayer` is called, if not then `gl.framebufferTexture2D`\n * @property {(WebGLRenderbuffer | WebGLTexture)} [attachment] An existing renderbuffer or texture.\n * If provided will attach this Object. This allows you to share\n * attachments across framebuffers.\n * @memberOf module:twgl\n * @mixes module:twgl.TextureOptions\n */\n\nconst defaultAttachments = [\n { format: RGBA, type: UNSIGNED_BYTE, min: LINEAR, wrap: CLAMP_TO_EDGE, },\n { format: DEPTH_STENCIL, },\n];\n\nconst attachmentsByFormat = {};\nattachmentsByFormat[DEPTH_STENCIL] = DEPTH_STENCIL_ATTACHMENT;\nattachmentsByFormat[STENCIL_INDEX] = STENCIL_ATTACHMENT;\nattachmentsByFormat[STENCIL_INDEX8] = STENCIL_ATTACHMENT;\nattachmentsByFormat[DEPTH_COMPONENT] = DEPTH_ATTACHMENT;\nattachmentsByFormat[DEPTH_COMPONENT16] = DEPTH_ATTACHMENT;\nattachmentsByFormat[DEPTH_COMPONENT24] = DEPTH_ATTACHMENT;\nattachmentsByFormat[DEPTH_COMPONENT32F] = DEPTH_ATTACHMENT;\nattachmentsByFormat[DEPTH24_STENCIL8] = DEPTH_STENCIL_ATTACHMENT;\nattachmentsByFormat[DEPTH32F_STENCIL8] = DEPTH_STENCIL_ATTACHMENT;\n\nfunction getAttachmentPointForFormat(format, internalFormat) {\n return attachmentsByFormat[format] || attachmentsByFormat[internalFormat];\n}\n\nconst renderbufferFormats = {};\nrenderbufferFormats[RGBA4] = true;\nrenderbufferFormats[RGB5_A1] = true;\nrenderbufferFormats[RGB565] = true;\nrenderbufferFormats[DEPTH_STENCIL] = true;\nrenderbufferFormats[DEPTH_COMPONENT16] = true;\nrenderbufferFormats[STENCIL_INDEX] = true;\nrenderbufferFormats[STENCIL_INDEX8] = true;\n\nfunction isRenderbufferFormat(format) {\n return renderbufferFormats[format];\n}\n\nconst MAX_COLOR_ATTACHMENT_POINTS = 32; // even an 3090 only supports 8 but WebGL/OpenGL ES define constants for 32\n\nfunction isColorAttachmentPoint(attachmentPoint) {\n return attachmentPoint >= COLOR_ATTACHMENT0 && attachmentPoint < COLOR_ATTACHMENT0 + MAX_COLOR_ATTACHMENT_POINTS;\n}\n\n/**\n * @typedef {Object} FramebufferInfo\n * @property {WebGLFramebuffer} framebuffer The WebGLFramebuffer for this framebufferInfo\n * @property {Array.<(WebGLRenderbuffer | WebGLTexture)>} attachments The created attachments in the same order as passed in to {@link module:twgl.createFramebufferInfo}.\n * @property {number} width The width of the framebuffer and its attachments\n * @property {number} height The width of the framebuffer and its attachments\n * @memberOf module:twgl\n */\n\n/**\n * Creates a framebuffer and attachments.\n *\n * This returns a {@link module:twgl.FramebufferInfo} because it needs to return the attachments as well as the framebuffer.\n * It also leaves the framebuffer it just created as the currently bound `FRAMEBUFFER`.\n * Note: If this is WebGL2 or if you called {@link module:twgl.addExtensionsToContext} then it will set the drawBuffers\n * to `[COLOR_ATTACHMENT0, COLOR_ATTACHMENT1, ...]` for how ever many color attachments were created.\n *\n * The simplest usage\n *\n * // create an RGBA/UNSIGNED_BYTE texture and DEPTH_STENCIL renderbuffer\n * const fbi = twgl.createFramebufferInfo(gl);\n *\n * More complex usage\n *\n * // create an RGB565 renderbuffer and a STENCIL_INDEX8 renderbuffer\n * const attachments = [\n * { format: RGB565, mag: NEAREST },\n * { format: STENCIL_INDEX8 },\n * ]\n * const fbi = twgl.createFramebufferInfo(gl, attachments);\n *\n * Passing in a specific size\n *\n * const width = 256;\n * const height = 256;\n * const fbi = twgl.createFramebufferInfo(gl, attachments, width, height);\n *\n * **Note!!** It is up to you to check if the framebuffer is renderable by calling `gl.checkFramebufferStatus`.\n * [WebGL1 only guarantees 3 combinations of attachments work](https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.6).\n *\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {module:twgl.AttachmentOptions[]} [attachments] which attachments to create. If not provided the default is a framebuffer with an\n * `RGBA`, `UNSIGNED_BYTE` texture `COLOR_ATTACHMENT0` and a `DEPTH_STENCIL` renderbuffer `DEPTH_STENCIL_ATTACHMENT`.\n * @param {number} [width] the width for the attachments. Default = size of drawingBuffer\n * @param {number} [height] the height for the attachments. Default = size of drawingBuffer\n * @return {module:twgl.FramebufferInfo} the framebuffer and attachments.\n * @memberOf module:twgl/framebuffers\n */\nfunction createFramebufferInfo(gl, attachments, width, height) {\n const target = FRAMEBUFFER;\n const fb = gl.createFramebuffer();\n gl.bindFramebuffer(target, fb);\n width = width || gl.drawingBufferWidth;\n height = height || gl.drawingBufferHeight;\n attachments = attachments || defaultAttachments;\n const usedColorAttachmentsPoints = [];\n const framebufferInfo = {\n framebuffer: fb,\n attachments: [],\n width: width,\n height: height,\n };\n\n attachments.forEach(function(attachmentOptions, i) {\n let attachment = attachmentOptions.attachment;\n const samples = attachmentOptions.samples;\n const format = attachmentOptions.format;\n let attachmentPoint = attachmentOptions.attachmentPoint || getAttachmentPointForFormat(format, attachmentOptions.internalFormat);\n if (!attachmentPoint) {\n attachmentPoint = COLOR_ATTACHMENT0 + i;\n }\n if (isColorAttachmentPoint(attachmentPoint)) {\n usedColorAttachmentsPoints.push(attachmentPoint);\n }\n if (!attachment) {\n if (samples !== undefined || isRenderbufferFormat(format)) {\n attachment = gl.createRenderbuffer();\n gl.bindRenderbuffer(RENDERBUFFER, attachment);\n if (samples > 1) {\n gl.renderbufferStorageMultisample(RENDERBUFFER, samples, format, width, height);\n } else {\n gl.renderbufferStorage(RENDERBUFFER, format, width, height);\n }\n } else {\n const textureOptions = Object.assign({}, attachmentOptions);\n textureOptions.width = width;\n textureOptions.height = height;\n if (textureOptions.auto === undefined) {\n textureOptions.auto = false;\n textureOptions.min = textureOptions.min || textureOptions.minMag || LINEAR;\n textureOptions.mag = textureOptions.mag || textureOptions.minMag || LINEAR;\n textureOptions.wrapS = textureOptions.wrapS || textureOptions.wrap || CLAMP_TO_EDGE;\n textureOptions.wrapT = textureOptions.wrapT || textureOptions.wrap || CLAMP_TO_EDGE;\n }\n attachment = createTexture(gl, textureOptions);\n }\n }\n if (isRenderbuffer(gl, attachment)) {\n gl.framebufferRenderbuffer(target, attachmentPoint, RENDERBUFFER, attachment);\n } else if (isTexture(gl, attachment)) {\n if (attachmentOptions.layer !== undefined) {\n gl.framebufferTextureLayer(\n target,\n attachmentPoint,\n attachment,\n attachmentOptions.level || 0,\n attachmentOptions.layer);\n } else {\n gl.framebufferTexture2D(\n target,\n attachmentPoint,\n attachmentOptions.target || TEXTURE_2D,\n attachment,\n attachmentOptions.level || 0);\n }\n } else {\n throw new Error('unknown attachment type');\n }\n framebufferInfo.attachments.push(attachment);\n });\n if (gl.drawBuffers) {\n gl.drawBuffers(usedColorAttachmentsPoints);\n }\n return framebufferInfo;\n}\n\n/**\n * Resizes the attachments of a framebuffer.\n *\n * You need to pass in the same `attachments` as you passed in {@link module:twgl.createFramebufferInfo}\n * because TWGL has no idea the format/type of each attachment.\n *\n * The simplest usage\n *\n * // create an RGBA/UNSIGNED_BYTE texture and DEPTH_STENCIL renderbuffer\n * const fbi = twgl.createFramebufferInfo(gl);\n *\n * ...\n *\n * function render() {\n * if (twgl.resizeCanvasToDisplaySize(gl.canvas)) {\n * // resize the attachments\n * twgl.resizeFramebufferInfo(gl, fbi);\n * }\n *\n * More complex usage\n *\n * // create an RGB565 renderbuffer and a STENCIL_INDEX8 renderbuffer\n * const attachments = [\n * { format: RGB565, mag: NEAREST },\n * { format: STENCIL_INDEX8 },\n * ]\n * const fbi = twgl.createFramebufferInfo(gl, attachments);\n *\n * ...\n *\n * function render() {\n * if (twgl.resizeCanvasToDisplaySize(gl.canvas)) {\n * // resize the attachments to match\n * twgl.resizeFramebufferInfo(gl, fbi, attachments);\n * }\n *\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {module:twgl.FramebufferInfo} framebufferInfo a framebufferInfo as returned from {@link module:twgl.createFramebufferInfo}.\n * @param {module:twgl.AttachmentOptions[]} [attachments] the same attachments options as passed to {@link module:twgl.createFramebufferInfo}.\n * @param {number} [width] the width for the attachments. Default = size of drawingBuffer\n * @param {number} [height] the height for the attachments. Default = size of drawingBuffer\n * @memberOf module:twgl/framebuffers\n */\nfunction resizeFramebufferInfo(gl, framebufferInfo, attachments, width, height) {\n width = width || gl.drawingBufferWidth;\n height = height || gl.drawingBufferHeight;\n framebufferInfo.width = width;\n framebufferInfo.height = height;\n attachments = attachments || defaultAttachments;\n attachments.forEach(function(attachmentOptions, ndx) {\n const attachment = framebufferInfo.attachments[ndx];\n const format = attachmentOptions.format;\n const samples = attachmentOptions.samples;\n if (samples !== undefined || isRenderbuffer(gl, attachment)) {\n gl.bindRenderbuffer(RENDERBUFFER, attachment);\n if (samples > 1) {\n gl.renderbufferStorageMultisample(RENDERBUFFER, samples, format, width, height);\n } else {\n gl.renderbufferStorage(RENDERBUFFER, format, width, height);\n }\n } else if (isTexture(gl, attachment)) {\n resizeTexture(gl, attachment, attachmentOptions, width, height);\n } else {\n throw new Error('unknown attachment type');\n }\n });\n}\n\n/**\n * Binds a framebuffer\n *\n * This function pretty much solely exists because I spent hours\n * trying to figure out why something I wrote wasn't working only\n * to realize I forget to set the viewport dimensions.\n * My hope is this function will fix that.\n *\n * It is effectively the same as\n *\n * gl.bindFramebuffer(gl.FRAMEBUFFER, someFramebufferInfo.framebuffer);\n * gl.viewport(0, 0, someFramebufferInfo.width, someFramebufferInfo.height);\n *\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {module:twgl.FramebufferInfo|null} [framebufferInfo] a framebufferInfo as returned from {@link module:twgl.createFramebufferInfo}.\n * If falsy will bind the canvas.\n * @param {number} [target] The target. If not passed `gl.FRAMEBUFFER` will be used.\n * @memberOf module:twgl/framebuffers\n */\n\nfunction bindFramebufferInfo(gl, framebufferInfo, target) {\n target = target || FRAMEBUFFER;\n if (framebufferInfo) {\n gl.bindFramebuffer(target, framebufferInfo.framebuffer);\n gl.viewport(0, 0, framebufferInfo.width, framebufferInfo.height);\n } else {\n gl.bindFramebuffer(target, null);\n gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);\n }\n}\n\nvar framebuffers = /*#__PURE__*/Object.freeze({\n __proto__: null,\n bindFramebufferInfo: bindFramebufferInfo,\n createFramebufferInfo: createFramebufferInfo,\n resizeFramebufferInfo: resizeFramebufferInfo\n});\n\n/*\n * Copyright 2019 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\n/**\n * vertex array object related functions\n *\n * You should generally not need to use these functions. They are provided\n * for those cases where you're doing something out of the ordinary\n * and you need lower level access.\n *\n * For backward compatibility they are available at both `twgl.attributes` and `twgl`\n * itself\n *\n * See {@link module:twgl} for core functions\n *\n * @module twgl/vertexArrays\n */\n\nconst ELEMENT_ARRAY_BUFFER = 0x8893;\n\n/**\n * @typedef {Object} VertexArrayInfo\n * @property {number} numElements The number of elements to pass to `gl.drawArrays` or `gl.drawElements`.\n * @property {number} [elementType] The type of indices `UNSIGNED_BYTE`, `UNSIGNED_SHORT` etc..\n * @property {WebGLVertexArrayObject} [vertexArrayObject] a vertex array object\n * @memberOf module:twgl\n */\n\n/**\n * Creates a VertexArrayInfo from a BufferInfo and one or more ProgramInfos\n *\n * This can be passed to {@link module:twgl.setBuffersAndAttributes} and to\n * {@link module:twgl:drawBufferInfo}.\n *\n * > **IMPORTANT:** Vertex Array Objects are **not** a direct analog for a BufferInfo. Vertex Array Objects\n * assign buffers to specific attributes at creation time. That means they can only be used with programs\n * who's attributes use the same attribute locations for the same purposes.\n *\n * > Bind your attribute locations by passing an array of attribute names to {@link module:twgl.createProgramInfo}\n * or use WebGL 2's GLSL ES 3's `layout(location = )` to make sure locations match.\n *\n * also\n *\n * > **IMPORTANT:** After calling twgl.setBuffersAndAttribute with a BufferInfo that uses a Vertex Array Object\n * that Vertex Array Object will be bound. That means **ANY MANIPULATION OF ELEMENT_ARRAY_BUFFER or ATTRIBUTES**\n * will affect the Vertex Array Object state.\n *\n * > Call `gl.bindVertexArray(null)` to get back manipulating the global attributes and ELEMENT_ARRAY_BUFFER.\n *\n * @param {WebGLRenderingContext} gl A WebGLRenderingContext\n * @param {module:twgl.ProgramInfo|module:twgl.ProgramInfo[]} programInfo a programInfo or array of programInfos\n * @param {module:twgl.BufferInfo} bufferInfo BufferInfo as returned from createBufferInfoFromArrays etc...\n *\n * You need to make sure every attribute that will be used is bound. So for example assume shader 1\n * uses attributes A, B, C and shader 2 uses attributes A, B, D. If you only pass in the programInfo\n * for shader 1 then only attributes A, B, and C will have their attributes set because TWGL doesn't\n * now attribute D's location.\n *\n * So, you can pass in both shader 1 and shader 2's programInfo\n *\n * @return {module:twgl.VertexArrayInfo} The created VertexArrayInfo\n *\n * @memberOf module:twgl/vertexArrays\n */\nfunction createVertexArrayInfo(gl, programInfos, bufferInfo) {\n const vao = gl.createVertexArray();\n gl.bindVertexArray(vao);\n if (!programInfos.length) {\n programInfos = [programInfos];\n }\n programInfos.forEach(function(programInfo) {\n setBuffersAndAttributes(gl, programInfo, bufferInfo);\n });\n gl.bindVertexArray(null);\n return {\n numElements: bufferInfo.numElements,\n elementType: bufferInfo.elementType,\n vertexArrayObject: vao,\n };\n}\n\n/**\n * Creates a vertex array object and then sets the attributes on it\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use.\n * @param {Object.} setters Attribute setters as returned from createAttributeSetters\n * @param {Object.} attribs AttribInfos mapped by attribute name.\n * @param {WebGLBuffer} [indices] an optional ELEMENT_ARRAY_BUFFER of indices\n *\n * @return {WebGLVertexArrayObject|null} The created WebGLVertexArrayObject\n *\n * @memberOf module:twgl/vertexArrays\n */\nfunction createVAOAndSetAttributes(gl, setters, attribs, indices) {\n const vao = gl.createVertexArray();\n gl.bindVertexArray(vao);\n setAttributes(setters, attribs);\n if (indices) {\n gl.bindBuffer(ELEMENT_ARRAY_BUFFER, indices);\n }\n // We unbind this because otherwise any change to ELEMENT_ARRAY_BUFFER\n // like when creating buffers for other stuff will mess up this VAO's binding\n gl.bindVertexArray(null);\n return vao;\n}\n\n/**\n * Creates a vertex array object and then sets the attributes\n * on it\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext\n * to use.\n * @param {Object.| module:twgl.ProgramInfo} programInfo as returned from createProgramInfo or Attribute setters as returned from createAttributeSetters\n * @param {module:twgl.BufferInfo} bufferInfo BufferInfo as returned from createBufferInfoFromArrays etc...\n * @param {WebGLBuffer} [indices] an optional ELEMENT_ARRAY_BUFFER of indices\n *\n * @return {WebGLVertexArrayObject|null} The created WebGLVertexArrayObject\n *\n * @memberOf module:twgl/vertexArrays\n */\nfunction createVAOFromBufferInfo(gl, programInfo, bufferInfo) {\n return createVAOAndSetAttributes(gl, programInfo.attribSetters || programInfo, bufferInfo.attribs, bufferInfo.indices);\n}\n\nvar vertexArrays = /*#__PURE__*/Object.freeze({\n __proto__: null,\n createVertexArrayInfo: createVertexArrayInfo,\n createVAOAndSetAttributes: createVAOAndSetAttributes,\n createVAOFromBufferInfo: createVAOFromBufferInfo\n});\n\n/*\n * Copyright 2019 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\nconst defaults = {\n addExtensionsToContext: true,\n};\n\n/**\n * Various default settings for twgl.\n *\n * Note: You can call this any number of times. Example:\n *\n * twgl.setDefaults({ textureColor: [1, 0, 0, 1] });\n * twgl.setDefaults({ attribPrefix: 'a_' });\n *\n * is equivalent to\n *\n * twgl.setDefaults({\n * textureColor: [1, 0, 0, 1],\n * attribPrefix: 'a_',\n * });\n *\n * @typedef {Object} Defaults\n * @property {string} [attribPrefix] The prefix to stick on attributes\n *\n * When writing shaders I prefer to name attributes with `a_`, uniforms with `u_` and varyings with `v_`\n * as it makes it clear where they came from. But, when building geometry I prefer using un-prefixed names.\n *\n * In other words I'll create arrays of geometry like this\n *\n * const arrays = {\n * position: ...\n * normal: ...\n * texcoord: ...\n * };\n *\n * But need those mapped to attributes and my attributes start with `a_`.\n *\n * Default: `\"\"`\n *\n * @property {number[]} [textureColor] Array of 4 values in the range 0 to 1\n *\n * The default texture color is used when loading textures from\n * urls. Because the URL will be loaded async we'd like to be\n * able to use the texture immediately. By putting a 1x1 pixel\n * color in the texture we can start using the texture before\n * the URL has loaded.\n *\n * Default: `[0.5, 0.75, 1, 1]`\n *\n * @property {string} [crossOrigin]\n *\n * If not undefined sets the crossOrigin attribute on images\n * that twgl creates when downloading images for textures.\n *\n * Also see {@link module:twgl.TextureOptions}.\n *\n * @property {bool} [addExtensionsToContext]\n *\n * If true, then, when twgl will try to add any supported WebGL extensions\n * directly to the context under their normal GL names. For example\n * if ANGLE_instances_arrays exists then twgl would enable it,\n * add the functions `vertexAttribDivisor`, `drawArraysInstanced`,\n * `drawElementsInstanced`, and the constant `VERTEX_ATTRIB_ARRAY_DIVISOR`\n * to the `WebGLRenderingContext`.\n *\n * @memberOf module:twgl\n */\n\n/**\n * Sets various defaults for twgl.\n *\n * In the interest of terseness which is kind of the point\n * of twgl I've integrated a few of the older functions here\n *\n * @param {module:twgl.Defaults} newDefaults The default settings.\n * @memberOf module:twgl\n */\nfunction setDefaults(newDefaults) {\n copyExistingProperties(newDefaults, defaults);\n setDefaults$2(newDefaults); // eslint-disable-line\n setDefaults$1(newDefaults); // eslint-disable-line\n}\n\nconst prefixRE = /^(.*?)_/;\nfunction addExtensionToContext(gl, extensionName) {\n glEnumToString(gl, 0);\n const ext = gl.getExtension(extensionName);\n if (ext) {\n const enums = {};\n const fnSuffix = prefixRE.exec(extensionName)[1];\n const enumSuffix = '_' + fnSuffix;\n for (const key in ext) {\n const value = ext[key];\n const isFunc = typeof (value) === 'function';\n const suffix = isFunc ? fnSuffix : enumSuffix;\n let name = key;\n // examples of where this is not true are WEBGL_compressed_texture_s3tc\n // and WEBGL_compressed_texture_pvrtc\n if (key.endsWith(suffix)) {\n name = key.substring(0, key.length - suffix.length);\n }\n if (gl[name] !== undefined) {\n if (!isFunc && gl[name] !== value) {\n warn$1(name, gl[name], value, key);\n }\n } else {\n if (isFunc) {\n gl[name] = function(origFn) {\n return function() {\n return origFn.apply(ext, arguments);\n };\n }(value);\n } else {\n gl[name] = value;\n enums[name] = value;\n }\n }\n }\n // pass the modified enums to glEnumToString\n enums.constructor = {\n name: ext.constructor.name,\n };\n glEnumToString(enums, 0);\n }\n return ext;\n}\n\n/*\n * If you're wondering why the code doesn't just iterate\n * over all extensions using `gl.getExtensions` is that it's possible\n * some future extension is incompatible with this code. Rather than\n * have thing suddenly break it seems better to manually add to this\n * list.\n *\n */\nconst supportedExtensions = [\n 'ANGLE_instanced_arrays',\n 'EXT_blend_minmax',\n 'EXT_color_buffer_float',\n 'EXT_color_buffer_half_float',\n 'EXT_disjoint_timer_query',\n 'EXT_disjoint_timer_query_webgl2',\n 'EXT_frag_depth',\n 'EXT_sRGB',\n 'EXT_shader_texture_lod',\n 'EXT_texture_filter_anisotropic',\n 'OES_element_index_uint',\n 'OES_standard_derivatives',\n 'OES_texture_float',\n 'OES_texture_float_linear',\n 'OES_texture_half_float',\n 'OES_texture_half_float_linear',\n 'OES_vertex_array_object',\n 'WEBGL_color_buffer_float',\n 'WEBGL_compressed_texture_atc',\n 'WEBGL_compressed_texture_etc1',\n 'WEBGL_compressed_texture_pvrtc',\n 'WEBGL_compressed_texture_s3tc',\n 'WEBGL_compressed_texture_s3tc_srgb',\n 'WEBGL_depth_texture',\n 'WEBGL_draw_buffers',\n];\n\n/**\n * Attempts to enable all of the following extensions\n * and add their functions and constants to the\n * `WebGLRenderingContext` using their normal non-extension like names.\n *\n * ANGLE_instanced_arrays\n * EXT_blend_minmax\n * EXT_color_buffer_float\n * EXT_color_buffer_half_float\n * EXT_disjoint_timer_query\n * EXT_disjoint_timer_query_webgl2\n * EXT_frag_depth\n * EXT_sRGB\n * EXT_shader_texture_lod\n * EXT_texture_filter_anisotropic\n * OES_element_index_uint\n * OES_standard_derivatives\n * OES_texture_float\n * OES_texture_float_linear\n * OES_texture_half_float\n * OES_texture_half_float_linear\n * OES_vertex_array_object\n * WEBGL_color_buffer_float\n * WEBGL_compressed_texture_atc\n * WEBGL_compressed_texture_etc1\n * WEBGL_compressed_texture_pvrtc\n * WEBGL_compressed_texture_s3tc\n * WEBGL_compressed_texture_s3tc_srgb\n * WEBGL_depth_texture\n * WEBGL_draw_buffers\n *\n * For example if `ANGLE_instanced_arrays` exists then the functions\n * `drawArraysInstanced`, `drawElementsInstanced`, `vertexAttribDivisor`\n * and the constant `VERTEX_ATTRIB_ARRAY_DIVISOR` are added to the\n * `WebGLRenderingContext`.\n *\n * Note that if you want to know if the extension exists you should\n * probably call `gl.getExtension` for each extension. Alternatively\n * you can check for the existence of the functions or constants that\n * are expected to be added. For example\n *\n * if (gl.drawBuffers) {\n * // Either WEBGL_draw_buffers was enabled OR you're running in WebGL2\n * ....\n *\n * @param {WebGLRenderingContext} gl A WebGLRenderingContext\n * @memberOf module:twgl\n */\nfunction addExtensionsToContext(gl) {\n for (let ii = 0; ii < supportedExtensions.length; ++ii) {\n addExtensionToContext(gl, supportedExtensions[ii]);\n }\n}\n\n/**\n * Creates a webgl context.\n * @param {HTMLCanvasElement} canvas The canvas tag to get\n * context from. If one is not passed in one will be\n * created.\n * @return {WebGLRenderingContext} The created context.\n * @private\n */\nfunction create3DContext(canvas, opt_attribs) {\n const names = [\"webgl\", \"experimental-webgl\"];\n let context = null;\n for (let ii = 0; ii < names.length; ++ii) {\n context = canvas.getContext(names[ii], opt_attribs);\n if (context) {\n if (defaults.addExtensionsToContext) {\n addExtensionsToContext(context);\n }\n break;\n }\n }\n return context;\n}\n\n/**\n * Gets a WebGL1 context.\n *\n * Note: Will attempt to enable Vertex Array Objects\n * and add WebGL2 entry points. (unless you first set defaults with\n * `twgl.setDefaults({enableVertexArrayObjects: false})`;\n *\n * @param {HTMLCanvasElement} canvas a canvas element.\n * @param {WebGLContextAttributes} [opt_attribs] optional webgl context creation attributes\n * @return {WebGLRenderingContext} The created context.\n * @memberOf module:twgl\n * @deprecated\n * @private\n */\nfunction getWebGLContext(canvas, opt_attribs) {\n const gl = create3DContext(canvas, opt_attribs);\n return gl;\n}\n\n/**\n * Creates a webgl context.\n *\n * Will return a WebGL2 context if possible.\n *\n * You can check if it's WebGL2 with\n *\n * twgl.isWebGL2(gl);\n *\n * @param {HTMLCanvasElement} canvas The canvas tag to get\n * context from. If one is not passed in one will be\n * created.\n * @return {WebGLRenderingContext} The created context.\n */\nfunction createContext(canvas, opt_attribs) {\n const names = [\"webgl2\", \"webgl\", \"experimental-webgl\"];\n let context = null;\n for (let ii = 0; ii < names.length; ++ii) {\n context = canvas.getContext(names[ii], opt_attribs);\n if (context) {\n if (defaults.addExtensionsToContext) {\n addExtensionsToContext(context);\n }\n break;\n }\n }\n return context;\n}\n\n/**\n * Gets a WebGL context. Will create a WebGL2 context if possible.\n *\n * You can check if it's WebGL2 with\n *\n * function isWebGL2(gl) {\n * return gl.getParameter(gl.VERSION).indexOf(\"WebGL 2.0 \") == 0;\n * }\n *\n * Note: For a WebGL1 context will attempt to enable Vertex Array Objects\n * and add WebGL2 entry points. (unless you first set defaults with\n * `twgl.setDefaults({enableVertexArrayObjects: false})`;\n *\n * @param {HTMLCanvasElement} canvas a canvas element.\n * @param {WebGLContextAttributes} [opt_attribs] optional webgl context creation attributes\n * @return {WebGLRenderingContext} The created context.\n * @memberOf module:twgl\n */\nfunction getContext(canvas, opt_attribs) {\n const gl = createContext(canvas, opt_attribs);\n return gl;\n}\n\n/**\n * Resize a canvas to match the size it's displayed.\n * @param {HTMLCanvasElement} canvas The canvas to resize.\n * @param {number} [multiplier] So you can pass in `window.devicePixelRatio` or other scale value if you want to.\n * @return {boolean} true if the canvas was resized.\n * @memberOf module:twgl\n */\nfunction resizeCanvasToDisplaySize(canvas, multiplier) {\n multiplier = multiplier || 1;\n multiplier = Math.max(0, multiplier);\n const width = canvas.clientWidth * multiplier | 0;\n const height = canvas.clientHeight * multiplier | 0;\n if (canvas.width !== width || canvas.height !== height) {\n canvas.width = width;\n canvas.height = height;\n return true;\n }\n return false;\n}\n\nexport { 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 };\n","/**\n * Common utilities\n * @module glMatrix\n */\n// Configuration Constants\nexport var EPSILON = 0.000001;\nexport var ARRAY_TYPE = typeof Float32Array !== 'undefined' ? Float32Array : Array;\nexport var RANDOM = Math.random;\n/**\n * Sets the type of array used when creating new vectors and matrices\n *\n * @param {Float32ArrayConstructor | ArrayConstructor} type Array type, such as Float32Array or Array\n */\n\nexport function setMatrixArrayType(type) {\n ARRAY_TYPE = type;\n}\nvar degree = Math.PI / 180;\n/**\n * Convert Degree To Radian\n *\n * @param {Number} a Angle in Degrees\n */\n\nexport function toRadian(a) {\n return a * degree;\n}\n/**\n * Tests whether or not the arguments have approximately the same value, within an absolute\n * or relative tolerance of glMatrix.EPSILON (an absolute tolerance is used for values less\n * than or equal to 1.0, and a relative tolerance is used for larger values)\n *\n * @param {Number} a The first number to test.\n * @param {Number} b The second number to test.\n * @returns {Boolean} True if the numbers are approximately equal, false otherwise.\n */\n\nexport function equals(a, b) {\n return Math.abs(a - b) <= EPSILON * Math.max(1.0, Math.abs(a), Math.abs(b));\n}\nif (!Math.hypot) Math.hypot = function () {\n var y = 0,\n i = arguments.length;\n\n while (i--) {\n y += arguments[i] * arguments[i];\n }\n\n return Math.sqrt(y);\n};","import * as glMatrix from \"./common.js\";\n/**\n * 4x4 Matrix
Format: column-major, when typed out it looks like row-major
The matrices are being post multiplied.\n * @module mat4\n */\n\n/**\n * Creates a new identity mat4\n *\n * @returns {mat4} a new 4x4 matrix\n */\n\nexport function create() {\n var out = new glMatrix.ARRAY_TYPE(16);\n\n if (glMatrix.ARRAY_TYPE != Float32Array) {\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n }\n\n out[0] = 1;\n out[5] = 1;\n out[10] = 1;\n out[15] = 1;\n return out;\n}\n/**\n * Creates a new mat4 initialized with values from an existing matrix\n *\n * @param {ReadonlyMat4} a matrix to clone\n * @returns {mat4} a new 4x4 matrix\n */\n\nexport function clone(a) {\n var out = new glMatrix.ARRAY_TYPE(16);\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n out[4] = a[4];\n out[5] = a[5];\n out[6] = a[6];\n out[7] = a[7];\n out[8] = a[8];\n out[9] = a[9];\n out[10] = a[10];\n out[11] = a[11];\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n return out;\n}\n/**\n * Copy the values from one mat4 to another\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the source matrix\n * @returns {mat4} out\n */\n\nexport function copy(out, a) {\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n out[4] = a[4];\n out[5] = a[5];\n out[6] = a[6];\n out[7] = a[7];\n out[8] = a[8];\n out[9] = a[9];\n out[10] = a[10];\n out[11] = a[11];\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n return out;\n}\n/**\n * Create a new mat4 with the given values\n *\n * @param {Number} m00 Component in column 0, row 0 position (index 0)\n * @param {Number} m01 Component in column 0, row 1 position (index 1)\n * @param {Number} m02 Component in column 0, row 2 position (index 2)\n * @param {Number} m03 Component in column 0, row 3 position (index 3)\n * @param {Number} m10 Component in column 1, row 0 position (index 4)\n * @param {Number} m11 Component in column 1, row 1 position (index 5)\n * @param {Number} m12 Component in column 1, row 2 position (index 6)\n * @param {Number} m13 Component in column 1, row 3 position (index 7)\n * @param {Number} m20 Component in column 2, row 0 position (index 8)\n * @param {Number} m21 Component in column 2, row 1 position (index 9)\n * @param {Number} m22 Component in column 2, row 2 position (index 10)\n * @param {Number} m23 Component in column 2, row 3 position (index 11)\n * @param {Number} m30 Component in column 3, row 0 position (index 12)\n * @param {Number} m31 Component in column 3, row 1 position (index 13)\n * @param {Number} m32 Component in column 3, row 2 position (index 14)\n * @param {Number} m33 Component in column 3, row 3 position (index 15)\n * @returns {mat4} A new mat4\n */\n\nexport function fromValues(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {\n var out = new glMatrix.ARRAY_TYPE(16);\n out[0] = m00;\n out[1] = m01;\n out[2] = m02;\n out[3] = m03;\n out[4] = m10;\n out[5] = m11;\n out[6] = m12;\n out[7] = m13;\n out[8] = m20;\n out[9] = m21;\n out[10] = m22;\n out[11] = m23;\n out[12] = m30;\n out[13] = m31;\n out[14] = m32;\n out[15] = m33;\n return out;\n}\n/**\n * Set the components of a mat4 to the given values\n *\n * @param {mat4} out the receiving matrix\n * @param {Number} m00 Component in column 0, row 0 position (index 0)\n * @param {Number} m01 Component in column 0, row 1 position (index 1)\n * @param {Number} m02 Component in column 0, row 2 position (index 2)\n * @param {Number} m03 Component in column 0, row 3 position (index 3)\n * @param {Number} m10 Component in column 1, row 0 position (index 4)\n * @param {Number} m11 Component in column 1, row 1 position (index 5)\n * @param {Number} m12 Component in column 1, row 2 position (index 6)\n * @param {Number} m13 Component in column 1, row 3 position (index 7)\n * @param {Number} m20 Component in column 2, row 0 position (index 8)\n * @param {Number} m21 Component in column 2, row 1 position (index 9)\n * @param {Number} m22 Component in column 2, row 2 position (index 10)\n * @param {Number} m23 Component in column 2, row 3 position (index 11)\n * @param {Number} m30 Component in column 3, row 0 position (index 12)\n * @param {Number} m31 Component in column 3, row 1 position (index 13)\n * @param {Number} m32 Component in column 3, row 2 position (index 14)\n * @param {Number} m33 Component in column 3, row 3 position (index 15)\n * @returns {mat4} out\n */\n\nexport function set(out, m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {\n out[0] = m00;\n out[1] = m01;\n out[2] = m02;\n out[3] = m03;\n out[4] = m10;\n out[5] = m11;\n out[6] = m12;\n out[7] = m13;\n out[8] = m20;\n out[9] = m21;\n out[10] = m22;\n out[11] = m23;\n out[12] = m30;\n out[13] = m31;\n out[14] = m32;\n out[15] = m33;\n return out;\n}\n/**\n * Set a mat4 to the identity matrix\n *\n * @param {mat4} out the receiving matrix\n * @returns {mat4} out\n */\n\nexport function identity(out) {\n out[0] = 1;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = 1;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = 1;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n/**\n * Transpose the values of a mat4\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the source matrix\n * @returns {mat4} out\n */\n\nexport function transpose(out, a) {\n // If we are transposing ourselves we can skip a few steps but have to cache some values\n if (out === a) {\n var a01 = a[1],\n a02 = a[2],\n a03 = a[3];\n var a12 = a[6],\n a13 = a[7];\n var a23 = a[11];\n out[1] = a[4];\n out[2] = a[8];\n out[3] = a[12];\n out[4] = a01;\n out[6] = a[9];\n out[7] = a[13];\n out[8] = a02;\n out[9] = a12;\n out[11] = a[14];\n out[12] = a03;\n out[13] = a13;\n out[14] = a23;\n } else {\n out[0] = a[0];\n out[1] = a[4];\n out[2] = a[8];\n out[3] = a[12];\n out[4] = a[1];\n out[5] = a[5];\n out[6] = a[9];\n out[7] = a[13];\n out[8] = a[2];\n out[9] = a[6];\n out[10] = a[10];\n out[11] = a[14];\n out[12] = a[3];\n out[13] = a[7];\n out[14] = a[11];\n out[15] = a[15];\n }\n\n return out;\n}\n/**\n * Inverts a mat4\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the source matrix\n * @returns {mat4} out\n */\n\nexport function invert(out, a) {\n var a00 = a[0],\n a01 = a[1],\n a02 = a[2],\n a03 = a[3];\n var a10 = a[4],\n a11 = a[5],\n a12 = a[6],\n a13 = a[7];\n var a20 = a[8],\n a21 = a[9],\n a22 = a[10],\n a23 = a[11];\n var a30 = a[12],\n a31 = a[13],\n a32 = a[14],\n a33 = a[15];\n var b00 = a00 * a11 - a01 * a10;\n var b01 = a00 * a12 - a02 * a10;\n var b02 = a00 * a13 - a03 * a10;\n var b03 = a01 * a12 - a02 * a11;\n var b04 = a01 * a13 - a03 * a11;\n var b05 = a02 * a13 - a03 * a12;\n var b06 = a20 * a31 - a21 * a30;\n var b07 = a20 * a32 - a22 * a30;\n var b08 = a20 * a33 - a23 * a30;\n var b09 = a21 * a32 - a22 * a31;\n var b10 = a21 * a33 - a23 * a31;\n var b11 = a22 * a33 - a23 * a32; // Calculate the determinant\n\n var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;\n\n if (!det) {\n return null;\n }\n\n det = 1.0 / det;\n out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;\n out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;\n out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;\n out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;\n out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;\n out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;\n out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;\n out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;\n out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;\n out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;\n out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;\n out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;\n out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;\n out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;\n out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;\n out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;\n return out;\n}\n/**\n * Calculates the adjugate of a mat4\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the source matrix\n * @returns {mat4} out\n */\n\nexport function adjoint(out, a) {\n var a00 = a[0],\n a01 = a[1],\n a02 = a[2],\n a03 = a[3];\n var a10 = a[4],\n a11 = a[5],\n a12 = a[6],\n a13 = a[7];\n var a20 = a[8],\n a21 = a[9],\n a22 = a[10],\n a23 = a[11];\n var a30 = a[12],\n a31 = a[13],\n a32 = a[14],\n a33 = a[15];\n out[0] = a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22);\n out[1] = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22));\n out[2] = a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12);\n out[3] = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12));\n out[4] = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22));\n out[5] = a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22);\n out[6] = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12));\n out[7] = a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12);\n out[8] = a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21);\n out[9] = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21));\n out[10] = a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11);\n out[11] = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11));\n out[12] = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21));\n out[13] = a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21);\n out[14] = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11));\n out[15] = a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11);\n return out;\n}\n/**\n * Calculates the determinant of a mat4\n *\n * @param {ReadonlyMat4} a the source matrix\n * @returns {Number} determinant of a\n */\n\nexport function determinant(a) {\n var a00 = a[0],\n a01 = a[1],\n a02 = a[2],\n a03 = a[3];\n var a10 = a[4],\n a11 = a[5],\n a12 = a[6],\n a13 = a[7];\n var a20 = a[8],\n a21 = a[9],\n a22 = a[10],\n a23 = a[11];\n var a30 = a[12],\n a31 = a[13],\n a32 = a[14],\n a33 = a[15];\n var b00 = a00 * a11 - a01 * a10;\n var b01 = a00 * a12 - a02 * a10;\n var b02 = a00 * a13 - a03 * a10;\n var b03 = a01 * a12 - a02 * a11;\n var b04 = a01 * a13 - a03 * a11;\n var b05 = a02 * a13 - a03 * a12;\n var b06 = a20 * a31 - a21 * a30;\n var b07 = a20 * a32 - a22 * a30;\n var b08 = a20 * a33 - a23 * a30;\n var b09 = a21 * a32 - a22 * a31;\n var b10 = a21 * a33 - a23 * a31;\n var b11 = a22 * a33 - a23 * a32; // Calculate the determinant\n\n return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;\n}\n/**\n * Multiplies two mat4s\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the first operand\n * @param {ReadonlyMat4} b the second operand\n * @returns {mat4} out\n */\n\nexport function multiply(out, a, b) {\n var a00 = a[0],\n a01 = a[1],\n a02 = a[2],\n a03 = a[3];\n var a10 = a[4],\n a11 = a[5],\n a12 = a[6],\n a13 = a[7];\n var a20 = a[8],\n a21 = a[9],\n a22 = a[10],\n a23 = a[11];\n var a30 = a[12],\n a31 = a[13],\n a32 = a[14],\n a33 = a[15]; // Cache only the current line of the second matrix\n\n var b0 = b[0],\n b1 = b[1],\n b2 = b[2],\n b3 = b[3];\n out[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n out[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n out[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n out[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n b0 = b[4];\n b1 = b[5];\n b2 = b[6];\n b3 = b[7];\n out[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n out[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n out[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n out[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n b0 = b[8];\n b1 = b[9];\n b2 = b[10];\n b3 = b[11];\n out[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n out[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n out[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n out[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n b0 = b[12];\n b1 = b[13];\n b2 = b[14];\n b3 = b[15];\n out[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n out[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n out[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n out[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n return out;\n}\n/**\n * Translate a mat4 by the given vector\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to translate\n * @param {ReadonlyVec3} v vector to translate by\n * @returns {mat4} out\n */\n\nexport function translate(out, a, v) {\n var x = v[0],\n y = v[1],\n z = v[2];\n var a00, a01, a02, a03;\n var a10, a11, a12, a13;\n var a20, a21, a22, a23;\n\n if (a === out) {\n out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];\n out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];\n out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];\n out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];\n } else {\n a00 = a[0];\n a01 = a[1];\n a02 = a[2];\n a03 = a[3];\n a10 = a[4];\n a11 = a[5];\n a12 = a[6];\n a13 = a[7];\n a20 = a[8];\n a21 = a[9];\n a22 = a[10];\n a23 = a[11];\n out[0] = a00;\n out[1] = a01;\n out[2] = a02;\n out[3] = a03;\n out[4] = a10;\n out[5] = a11;\n out[6] = a12;\n out[7] = a13;\n out[8] = a20;\n out[9] = a21;\n out[10] = a22;\n out[11] = a23;\n out[12] = a00 * x + a10 * y + a20 * z + a[12];\n out[13] = a01 * x + a11 * y + a21 * z + a[13];\n out[14] = a02 * x + a12 * y + a22 * z + a[14];\n out[15] = a03 * x + a13 * y + a23 * z + a[15];\n }\n\n return out;\n}\n/**\n * Scales the mat4 by the dimensions in the given vec3 not using vectorization\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to scale\n * @param {ReadonlyVec3} v the vec3 to scale the matrix by\n * @returns {mat4} out\n **/\n\nexport function scale(out, a, v) {\n var x = v[0],\n y = v[1],\n z = v[2];\n out[0] = a[0] * x;\n out[1] = a[1] * x;\n out[2] = a[2] * x;\n out[3] = a[3] * x;\n out[4] = a[4] * y;\n out[5] = a[5] * y;\n out[6] = a[6] * y;\n out[7] = a[7] * y;\n out[8] = a[8] * z;\n out[9] = a[9] * z;\n out[10] = a[10] * z;\n out[11] = a[11] * z;\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n return out;\n}\n/**\n * Rotates a mat4 by the given angle around the given axis\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to rotate\n * @param {Number} rad the angle to rotate the matrix by\n * @param {ReadonlyVec3} axis the axis to rotate around\n * @returns {mat4} out\n */\n\nexport function rotate(out, a, rad, axis) {\n var x = axis[0],\n y = axis[1],\n z = axis[2];\n var len = Math.hypot(x, y, z);\n var s, c, t;\n var a00, a01, a02, a03;\n var a10, a11, a12, a13;\n var a20, a21, a22, a23;\n var b00, b01, b02;\n var b10, b11, b12;\n var b20, b21, b22;\n\n if (len < glMatrix.EPSILON) {\n return null;\n }\n\n len = 1 / len;\n x *= len;\n y *= len;\n z *= len;\n s = Math.sin(rad);\n c = Math.cos(rad);\n t = 1 - c;\n a00 = a[0];\n a01 = a[1];\n a02 = a[2];\n a03 = a[3];\n a10 = a[4];\n a11 = a[5];\n a12 = a[6];\n a13 = a[7];\n a20 = a[8];\n a21 = a[9];\n a22 = a[10];\n a23 = a[11]; // Construct the elements of the rotation matrix\n\n b00 = x * x * t + c;\n b01 = y * x * t + z * s;\n b02 = z * x * t - y * s;\n b10 = x * y * t - z * s;\n b11 = y * y * t + c;\n b12 = z * y * t + x * s;\n b20 = x * z * t + y * s;\n b21 = y * z * t - x * s;\n b22 = z * z * t + c; // Perform rotation-specific matrix multiplication\n\n out[0] = a00 * b00 + a10 * b01 + a20 * b02;\n out[1] = a01 * b00 + a11 * b01 + a21 * b02;\n out[2] = a02 * b00 + a12 * b01 + a22 * b02;\n out[3] = a03 * b00 + a13 * b01 + a23 * b02;\n out[4] = a00 * b10 + a10 * b11 + a20 * b12;\n out[5] = a01 * b10 + a11 * b11 + a21 * b12;\n out[6] = a02 * b10 + a12 * b11 + a22 * b12;\n out[7] = a03 * b10 + a13 * b11 + a23 * b12;\n out[8] = a00 * b20 + a10 * b21 + a20 * b22;\n out[9] = a01 * b20 + a11 * b21 + a21 * b22;\n out[10] = a02 * b20 + a12 * b21 + a22 * b22;\n out[11] = a03 * b20 + a13 * b21 + a23 * b22;\n\n if (a !== out) {\n // If the source and destination differ, copy the unchanged last row\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n }\n\n return out;\n}\n/**\n * Rotates a matrix by the given angle around the X axis\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to rotate\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat4} out\n */\n\nexport function rotateX(out, a, rad) {\n var s = Math.sin(rad);\n var c = Math.cos(rad);\n var a10 = a[4];\n var a11 = a[5];\n var a12 = a[6];\n var a13 = a[7];\n var a20 = a[8];\n var a21 = a[9];\n var a22 = a[10];\n var a23 = a[11];\n\n if (a !== out) {\n // If the source and destination differ, copy the unchanged rows\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n } // Perform axis-specific matrix multiplication\n\n\n out[4] = a10 * c + a20 * s;\n out[5] = a11 * c + a21 * s;\n out[6] = a12 * c + a22 * s;\n out[7] = a13 * c + a23 * s;\n out[8] = a20 * c - a10 * s;\n out[9] = a21 * c - a11 * s;\n out[10] = a22 * c - a12 * s;\n out[11] = a23 * c - a13 * s;\n return out;\n}\n/**\n * Rotates a matrix by the given angle around the Y axis\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to rotate\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat4} out\n */\n\nexport function rotateY(out, a, rad) {\n var s = Math.sin(rad);\n var c = Math.cos(rad);\n var a00 = a[0];\n var a01 = a[1];\n var a02 = a[2];\n var a03 = a[3];\n var a20 = a[8];\n var a21 = a[9];\n var a22 = a[10];\n var a23 = a[11];\n\n if (a !== out) {\n // If the source and destination differ, copy the unchanged rows\n out[4] = a[4];\n out[5] = a[5];\n out[6] = a[6];\n out[7] = a[7];\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n } // Perform axis-specific matrix multiplication\n\n\n out[0] = a00 * c - a20 * s;\n out[1] = a01 * c - a21 * s;\n out[2] = a02 * c - a22 * s;\n out[3] = a03 * c - a23 * s;\n out[8] = a00 * s + a20 * c;\n out[9] = a01 * s + a21 * c;\n out[10] = a02 * s + a22 * c;\n out[11] = a03 * s + a23 * c;\n return out;\n}\n/**\n * Rotates a matrix by the given angle around the Z axis\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to rotate\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat4} out\n */\n\nexport function rotateZ(out, a, rad) {\n var s = Math.sin(rad);\n var c = Math.cos(rad);\n var a00 = a[0];\n var a01 = a[1];\n var a02 = a[2];\n var a03 = a[3];\n var a10 = a[4];\n var a11 = a[5];\n var a12 = a[6];\n var a13 = a[7];\n\n if (a !== out) {\n // If the source and destination differ, copy the unchanged last row\n out[8] = a[8];\n out[9] = a[9];\n out[10] = a[10];\n out[11] = a[11];\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n } // Perform axis-specific matrix multiplication\n\n\n out[0] = a00 * c + a10 * s;\n out[1] = a01 * c + a11 * s;\n out[2] = a02 * c + a12 * s;\n out[3] = a03 * c + a13 * s;\n out[4] = a10 * c - a00 * s;\n out[5] = a11 * c - a01 * s;\n out[6] = a12 * c - a02 * s;\n out[7] = a13 * c - a03 * s;\n return out;\n}\n/**\n * Creates a matrix from a vector translation\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.translate(dest, dest, vec);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {ReadonlyVec3} v Translation vector\n * @returns {mat4} out\n */\n\nexport function fromTranslation(out, v) {\n out[0] = 1;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = 1;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = 1;\n out[11] = 0;\n out[12] = v[0];\n out[13] = v[1];\n out[14] = v[2];\n out[15] = 1;\n return out;\n}\n/**\n * Creates a matrix from a vector scaling\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.scale(dest, dest, vec);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {ReadonlyVec3} v Scaling vector\n * @returns {mat4} out\n */\n\nexport function fromScaling(out, v) {\n out[0] = v[0];\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = v[1];\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = v[2];\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n/**\n * Creates a matrix from a given angle around a given axis\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.rotate(dest, dest, rad, axis);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {Number} rad the angle to rotate the matrix by\n * @param {ReadonlyVec3} axis the axis to rotate around\n * @returns {mat4} out\n */\n\nexport function fromRotation(out, rad, axis) {\n var x = axis[0],\n y = axis[1],\n z = axis[2];\n var len = Math.hypot(x, y, z);\n var s, c, t;\n\n if (len < glMatrix.EPSILON) {\n return null;\n }\n\n len = 1 / len;\n x *= len;\n y *= len;\n z *= len;\n s = Math.sin(rad);\n c = Math.cos(rad);\n t = 1 - c; // Perform rotation-specific matrix multiplication\n\n out[0] = x * x * t + c;\n out[1] = y * x * t + z * s;\n out[2] = z * x * t - y * s;\n out[3] = 0;\n out[4] = x * y * t - z * s;\n out[5] = y * y * t + c;\n out[6] = z * y * t + x * s;\n out[7] = 0;\n out[8] = x * z * t + y * s;\n out[9] = y * z * t - x * s;\n out[10] = z * z * t + c;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n/**\n * Creates a matrix from the given angle around the X axis\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.rotateX(dest, dest, rad);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat4} out\n */\n\nexport function fromXRotation(out, rad) {\n var s = Math.sin(rad);\n var c = Math.cos(rad); // Perform axis-specific matrix multiplication\n\n out[0] = 1;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = c;\n out[6] = s;\n out[7] = 0;\n out[8] = 0;\n out[9] = -s;\n out[10] = c;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n/**\n * Creates a matrix from the given angle around the Y axis\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.rotateY(dest, dest, rad);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat4} out\n */\n\nexport function fromYRotation(out, rad) {\n var s = Math.sin(rad);\n var c = Math.cos(rad); // Perform axis-specific matrix multiplication\n\n out[0] = c;\n out[1] = 0;\n out[2] = -s;\n out[3] = 0;\n out[4] = 0;\n out[5] = 1;\n out[6] = 0;\n out[7] = 0;\n out[8] = s;\n out[9] = 0;\n out[10] = c;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n/**\n * Creates a matrix from the given angle around the Z axis\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.rotateZ(dest, dest, rad);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat4} out\n */\n\nexport function fromZRotation(out, rad) {\n var s = Math.sin(rad);\n var c = Math.cos(rad); // Perform axis-specific matrix multiplication\n\n out[0] = c;\n out[1] = s;\n out[2] = 0;\n out[3] = 0;\n out[4] = -s;\n out[5] = c;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = 1;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n/**\n * Creates a matrix from a quaternion rotation and vector translation\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.translate(dest, vec);\n * let quatMat = mat4.create();\n * quat4.toMat4(quat, quatMat);\n * mat4.multiply(dest, quatMat);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {quat4} q Rotation quaternion\n * @param {ReadonlyVec3} v Translation vector\n * @returns {mat4} out\n */\n\nexport function fromRotationTranslation(out, q, v) {\n // Quaternion math\n var x = q[0],\n y = q[1],\n z = q[2],\n w = q[3];\n var x2 = x + x;\n var y2 = y + y;\n var z2 = z + z;\n var xx = x * x2;\n var xy = x * y2;\n var xz = x * z2;\n var yy = y * y2;\n var yz = y * z2;\n var zz = z * z2;\n var wx = w * x2;\n var wy = w * y2;\n var wz = w * z2;\n out[0] = 1 - (yy + zz);\n out[1] = xy + wz;\n out[2] = xz - wy;\n out[3] = 0;\n out[4] = xy - wz;\n out[5] = 1 - (xx + zz);\n out[6] = yz + wx;\n out[7] = 0;\n out[8] = xz + wy;\n out[9] = yz - wx;\n out[10] = 1 - (xx + yy);\n out[11] = 0;\n out[12] = v[0];\n out[13] = v[1];\n out[14] = v[2];\n out[15] = 1;\n return out;\n}\n/**\n * Creates a new mat4 from a dual quat.\n *\n * @param {mat4} out Matrix\n * @param {ReadonlyQuat2} a Dual Quaternion\n * @returns {mat4} mat4 receiving operation result\n */\n\nexport function fromQuat2(out, a) {\n var translation = new glMatrix.ARRAY_TYPE(3);\n var bx = -a[0],\n by = -a[1],\n bz = -a[2],\n bw = a[3],\n ax = a[4],\n ay = a[5],\n az = a[6],\n aw = a[7];\n var magnitude = bx * bx + by * by + bz * bz + bw * bw; //Only scale if it makes sense\n\n if (magnitude > 0) {\n translation[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2 / magnitude;\n translation[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2 / magnitude;\n translation[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2 / magnitude;\n } else {\n translation[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2;\n translation[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2;\n translation[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2;\n }\n\n fromRotationTranslation(out, a, translation);\n return out;\n}\n/**\n * Returns the translation vector component of a transformation\n * matrix. If a matrix is built with fromRotationTranslation,\n * the returned vector will be the same as the translation vector\n * originally supplied.\n * @param {vec3} out Vector to receive translation component\n * @param {ReadonlyMat4} mat Matrix to be decomposed (input)\n * @return {vec3} out\n */\n\nexport function getTranslation(out, mat) {\n out[0] = mat[12];\n out[1] = mat[13];\n out[2] = mat[14];\n return out;\n}\n/**\n * Returns the scaling factor component of a transformation\n * matrix. If a matrix is built with fromRotationTranslationScale\n * with a normalized Quaternion paramter, the returned vector will be\n * the same as the scaling vector\n * originally supplied.\n * @param {vec3} out Vector to receive scaling factor component\n * @param {ReadonlyMat4} mat Matrix to be decomposed (input)\n * @return {vec3} out\n */\n\nexport function getScaling(out, mat) {\n var m11 = mat[0];\n var m12 = mat[1];\n var m13 = mat[2];\n var m21 = mat[4];\n var m22 = mat[5];\n var m23 = mat[6];\n var m31 = mat[8];\n var m32 = mat[9];\n var m33 = mat[10];\n out[0] = Math.hypot(m11, m12, m13);\n out[1] = Math.hypot(m21, m22, m23);\n out[2] = Math.hypot(m31, m32, m33);\n return out;\n}\n/**\n * Returns a quaternion representing the rotational component\n * of a transformation matrix. If a matrix is built with\n * fromRotationTranslation, the returned quaternion will be the\n * same as the quaternion originally supplied.\n * @param {quat} out Quaternion to receive the rotation component\n * @param {ReadonlyMat4} mat Matrix to be decomposed (input)\n * @return {quat} out\n */\n\nexport function getRotation(out, mat) {\n var scaling = new glMatrix.ARRAY_TYPE(3);\n getScaling(scaling, mat);\n var is1 = 1 / scaling[0];\n var is2 = 1 / scaling[1];\n var is3 = 1 / scaling[2];\n var sm11 = mat[0] * is1;\n var sm12 = mat[1] * is2;\n var sm13 = mat[2] * is3;\n var sm21 = mat[4] * is1;\n var sm22 = mat[5] * is2;\n var sm23 = mat[6] * is3;\n var sm31 = mat[8] * is1;\n var sm32 = mat[9] * is2;\n var sm33 = mat[10] * is3;\n var trace = sm11 + sm22 + sm33;\n var S = 0;\n\n if (trace > 0) {\n S = Math.sqrt(trace + 1.0) * 2;\n out[3] = 0.25 * S;\n out[0] = (sm23 - sm32) / S;\n out[1] = (sm31 - sm13) / S;\n out[2] = (sm12 - sm21) / S;\n } else if (sm11 > sm22 && sm11 > sm33) {\n S = Math.sqrt(1.0 + sm11 - sm22 - sm33) * 2;\n out[3] = (sm23 - sm32) / S;\n out[0] = 0.25 * S;\n out[1] = (sm12 + sm21) / S;\n out[2] = (sm31 + sm13) / S;\n } else if (sm22 > sm33) {\n S = Math.sqrt(1.0 + sm22 - sm11 - sm33) * 2;\n out[3] = (sm31 - sm13) / S;\n out[0] = (sm12 + sm21) / S;\n out[1] = 0.25 * S;\n out[2] = (sm23 + sm32) / S;\n } else {\n S = Math.sqrt(1.0 + sm33 - sm11 - sm22) * 2;\n out[3] = (sm12 - sm21) / S;\n out[0] = (sm31 + sm13) / S;\n out[1] = (sm23 + sm32) / S;\n out[2] = 0.25 * S;\n }\n\n return out;\n}\n/**\n * Creates a matrix from a quaternion rotation, vector translation and vector scale\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.translate(dest, vec);\n * let quatMat = mat4.create();\n * quat4.toMat4(quat, quatMat);\n * mat4.multiply(dest, quatMat);\n * mat4.scale(dest, scale)\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {quat4} q Rotation quaternion\n * @param {ReadonlyVec3} v Translation vector\n * @param {ReadonlyVec3} s Scaling vector\n * @returns {mat4} out\n */\n\nexport function fromRotationTranslationScale(out, q, v, s) {\n // Quaternion math\n var x = q[0],\n y = q[1],\n z = q[2],\n w = q[3];\n var x2 = x + x;\n var y2 = y + y;\n var z2 = z + z;\n var xx = x * x2;\n var xy = x * y2;\n var xz = x * z2;\n var yy = y * y2;\n var yz = y * z2;\n var zz = z * z2;\n var wx = w * x2;\n var wy = w * y2;\n var wz = w * z2;\n var sx = s[0];\n var sy = s[1];\n var sz = s[2];\n out[0] = (1 - (yy + zz)) * sx;\n out[1] = (xy + wz) * sx;\n out[2] = (xz - wy) * sx;\n out[3] = 0;\n out[4] = (xy - wz) * sy;\n out[5] = (1 - (xx + zz)) * sy;\n out[6] = (yz + wx) * sy;\n out[7] = 0;\n out[8] = (xz + wy) * sz;\n out[9] = (yz - wx) * sz;\n out[10] = (1 - (xx + yy)) * sz;\n out[11] = 0;\n out[12] = v[0];\n out[13] = v[1];\n out[14] = v[2];\n out[15] = 1;\n return out;\n}\n/**\n * Creates a matrix from a quaternion rotation, vector translation and vector scale, rotating and scaling around the given origin\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.translate(dest, vec);\n * mat4.translate(dest, origin);\n * let quatMat = mat4.create();\n * quat4.toMat4(quat, quatMat);\n * mat4.multiply(dest, quatMat);\n * mat4.scale(dest, scale)\n * mat4.translate(dest, negativeOrigin);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {quat4} q Rotation quaternion\n * @param {ReadonlyVec3} v Translation vector\n * @param {ReadonlyVec3} s Scaling vector\n * @param {ReadonlyVec3} o The origin vector around which to scale and rotate\n * @returns {mat4} out\n */\n\nexport function fromRotationTranslationScaleOrigin(out, q, v, s, o) {\n // Quaternion math\n var x = q[0],\n y = q[1],\n z = q[2],\n w = q[3];\n var x2 = x + x;\n var y2 = y + y;\n var z2 = z + z;\n var xx = x * x2;\n var xy = x * y2;\n var xz = x * z2;\n var yy = y * y2;\n var yz = y * z2;\n var zz = z * z2;\n var wx = w * x2;\n var wy = w * y2;\n var wz = w * z2;\n var sx = s[0];\n var sy = s[1];\n var sz = s[2];\n var ox = o[0];\n var oy = o[1];\n var oz = o[2];\n var out0 = (1 - (yy + zz)) * sx;\n var out1 = (xy + wz) * sx;\n var out2 = (xz - wy) * sx;\n var out4 = (xy - wz) * sy;\n var out5 = (1 - (xx + zz)) * sy;\n var out6 = (yz + wx) * sy;\n var out8 = (xz + wy) * sz;\n var out9 = (yz - wx) * sz;\n var out10 = (1 - (xx + yy)) * sz;\n out[0] = out0;\n out[1] = out1;\n out[2] = out2;\n out[3] = 0;\n out[4] = out4;\n out[5] = out5;\n out[6] = out6;\n out[7] = 0;\n out[8] = out8;\n out[9] = out9;\n out[10] = out10;\n out[11] = 0;\n out[12] = v[0] + ox - (out0 * ox + out4 * oy + out8 * oz);\n out[13] = v[1] + oy - (out1 * ox + out5 * oy + out9 * oz);\n out[14] = v[2] + oz - (out2 * ox + out6 * oy + out10 * oz);\n out[15] = 1;\n return out;\n}\n/**\n * Calculates a 4x4 matrix from the given quaternion\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {ReadonlyQuat} q Quaternion to create matrix from\n *\n * @returns {mat4} out\n */\n\nexport function fromQuat(out, q) {\n var x = q[0],\n y = q[1],\n z = q[2],\n w = q[3];\n var x2 = x + x;\n var y2 = y + y;\n var z2 = z + z;\n var xx = x * x2;\n var yx = y * x2;\n var yy = y * y2;\n var zx = z * x2;\n var zy = z * y2;\n var zz = z * z2;\n var wx = w * x2;\n var wy = w * y2;\n var wz = w * z2;\n out[0] = 1 - yy - zz;\n out[1] = yx + wz;\n out[2] = zx - wy;\n out[3] = 0;\n out[4] = yx - wz;\n out[5] = 1 - xx - zz;\n out[6] = zy + wx;\n out[7] = 0;\n out[8] = zx + wy;\n out[9] = zy - wx;\n out[10] = 1 - xx - yy;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n/**\n * Generates a frustum matrix with the given bounds\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {Number} left Left bound of the frustum\n * @param {Number} right Right bound of the frustum\n * @param {Number} bottom Bottom bound of the frustum\n * @param {Number} top Top bound of the frustum\n * @param {Number} near Near bound of the frustum\n * @param {Number} far Far bound of the frustum\n * @returns {mat4} out\n */\n\nexport function frustum(out, left, right, bottom, top, near, far) {\n var rl = 1 / (right - left);\n var tb = 1 / (top - bottom);\n var nf = 1 / (near - far);\n out[0] = near * 2 * rl;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = near * 2 * tb;\n out[6] = 0;\n out[7] = 0;\n out[8] = (right + left) * rl;\n out[9] = (top + bottom) * tb;\n out[10] = (far + near) * nf;\n out[11] = -1;\n out[12] = 0;\n out[13] = 0;\n out[14] = far * near * 2 * nf;\n out[15] = 0;\n return out;\n}\n/**\n * Generates a perspective projection matrix with the given bounds.\n * The near/far clip planes correspond to a normalized device coordinate Z range of [-1, 1],\n * which matches WebGL/OpenGL's clip volume.\n * Passing null/undefined/no value for far will generate infinite projection matrix.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {number} fovy Vertical field of view in radians\n * @param {number} aspect Aspect ratio. typically viewport width/height\n * @param {number} near Near bound of the frustum\n * @param {number} far Far bound of the frustum, can be null or Infinity\n * @returns {mat4} out\n */\n\nexport function perspectiveNO(out, fovy, aspect, near, far) {\n var f = 1.0 / Math.tan(fovy / 2),\n nf;\n out[0] = f / aspect;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = f;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[11] = -1;\n out[12] = 0;\n out[13] = 0;\n out[15] = 0;\n\n if (far != null && far !== Infinity) {\n nf = 1 / (near - far);\n out[10] = (far + near) * nf;\n out[14] = 2 * far * near * nf;\n } else {\n out[10] = -1;\n out[14] = -2 * near;\n }\n\n return out;\n}\n/**\n * Alias for {@link mat4.perspectiveNO}\n * @function\n */\n\nexport var perspective = perspectiveNO;\n/**\n * Generates a perspective projection matrix suitable for WebGPU with the given bounds.\n * The near/far clip planes correspond to a normalized device coordinate Z range of [0, 1],\n * which matches WebGPU/Vulkan/DirectX/Metal's clip volume.\n * Passing null/undefined/no value for far will generate infinite projection matrix.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {number} fovy Vertical field of view in radians\n * @param {number} aspect Aspect ratio. typically viewport width/height\n * @param {number} near Near bound of the frustum\n * @param {number} far Far bound of the frustum, can be null or Infinity\n * @returns {mat4} out\n */\n\nexport function perspectiveZO(out, fovy, aspect, near, far) {\n var f = 1.0 / Math.tan(fovy / 2),\n nf;\n out[0] = f / aspect;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = f;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[11] = -1;\n out[12] = 0;\n out[13] = 0;\n out[15] = 0;\n\n if (far != null && far !== Infinity) {\n nf = 1 / (near - far);\n out[10] = far * nf;\n out[14] = far * near * nf;\n } else {\n out[10] = -1;\n out[14] = -near;\n }\n\n return out;\n}\n/**\n * Generates a perspective projection matrix with the given field of view.\n * This is primarily useful for generating projection matrices to be used\n * with the still experiemental WebVR API.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {Object} fov Object containing the following values: upDegrees, downDegrees, leftDegrees, rightDegrees\n * @param {number} near Near bound of the frustum\n * @param {number} far Far bound of the frustum\n * @returns {mat4} out\n */\n\nexport function perspectiveFromFieldOfView(out, fov, near, far) {\n var upTan = Math.tan(fov.upDegrees * Math.PI / 180.0);\n var downTan = Math.tan(fov.downDegrees * Math.PI / 180.0);\n var leftTan = Math.tan(fov.leftDegrees * Math.PI / 180.0);\n var rightTan = Math.tan(fov.rightDegrees * Math.PI / 180.0);\n var xScale = 2.0 / (leftTan + rightTan);\n var yScale = 2.0 / (upTan + downTan);\n out[0] = xScale;\n out[1] = 0.0;\n out[2] = 0.0;\n out[3] = 0.0;\n out[4] = 0.0;\n out[5] = yScale;\n out[6] = 0.0;\n out[7] = 0.0;\n out[8] = -((leftTan - rightTan) * xScale * 0.5);\n out[9] = (upTan - downTan) * yScale * 0.5;\n out[10] = far / (near - far);\n out[11] = -1.0;\n out[12] = 0.0;\n out[13] = 0.0;\n out[14] = far * near / (near - far);\n out[15] = 0.0;\n return out;\n}\n/**\n * Generates a orthogonal projection matrix with the given bounds.\n * The near/far clip planes correspond to a normalized device coordinate Z range of [-1, 1],\n * which matches WebGL/OpenGL's clip volume.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {number} left Left bound of the frustum\n * @param {number} right Right bound of the frustum\n * @param {number} bottom Bottom bound of the frustum\n * @param {number} top Top bound of the frustum\n * @param {number} near Near bound of the frustum\n * @param {number} far Far bound of the frustum\n * @returns {mat4} out\n */\n\nexport function orthoNO(out, left, right, bottom, top, near, far) {\n var lr = 1 / (left - right);\n var bt = 1 / (bottom - top);\n var nf = 1 / (near - far);\n out[0] = -2 * lr;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = -2 * bt;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = 2 * nf;\n out[11] = 0;\n out[12] = (left + right) * lr;\n out[13] = (top + bottom) * bt;\n out[14] = (far + near) * nf;\n out[15] = 1;\n return out;\n}\n/**\n * Alias for {@link mat4.orthoNO}\n * @function\n */\n\nexport var ortho = orthoNO;\n/**\n * Generates a orthogonal projection matrix with the given bounds.\n * The near/far clip planes correspond to a normalized device coordinate Z range of [0, 1],\n * which matches WebGPU/Vulkan/DirectX/Metal's clip volume.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {number} left Left bound of the frustum\n * @param {number} right Right bound of the frustum\n * @param {number} bottom Bottom bound of the frustum\n * @param {number} top Top bound of the frustum\n * @param {number} near Near bound of the frustum\n * @param {number} far Far bound of the frustum\n * @returns {mat4} out\n */\n\nexport function orthoZO(out, left, right, bottom, top, near, far) {\n var lr = 1 / (left - right);\n var bt = 1 / (bottom - top);\n var nf = 1 / (near - far);\n out[0] = -2 * lr;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = -2 * bt;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = nf;\n out[11] = 0;\n out[12] = (left + right) * lr;\n out[13] = (top + bottom) * bt;\n out[14] = near * nf;\n out[15] = 1;\n return out;\n}\n/**\n * Generates a look-at matrix with the given eye position, focal point, and up axis.\n * If you want a matrix that actually makes an object look at another object, you should use targetTo instead.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {ReadonlyVec3} eye Position of the viewer\n * @param {ReadonlyVec3} center Point the viewer is looking at\n * @param {ReadonlyVec3} up vec3 pointing up\n * @returns {mat4} out\n */\n\nexport function lookAt(out, eye, center, up) {\n var x0, x1, x2, y0, y1, y2, z0, z1, z2, len;\n var eyex = eye[0];\n var eyey = eye[1];\n var eyez = eye[2];\n var upx = up[0];\n var upy = up[1];\n var upz = up[2];\n var centerx = center[0];\n var centery = center[1];\n var centerz = center[2];\n\n if (Math.abs(eyex - centerx) < glMatrix.EPSILON && Math.abs(eyey - centery) < glMatrix.EPSILON && Math.abs(eyez - centerz) < glMatrix.EPSILON) {\n return identity(out);\n }\n\n z0 = eyex - centerx;\n z1 = eyey - centery;\n z2 = eyez - centerz;\n len = 1 / Math.hypot(z0, z1, z2);\n z0 *= len;\n z1 *= len;\n z2 *= len;\n x0 = upy * z2 - upz * z1;\n x1 = upz * z0 - upx * z2;\n x2 = upx * z1 - upy * z0;\n len = Math.hypot(x0, x1, x2);\n\n if (!len) {\n x0 = 0;\n x1 = 0;\n x2 = 0;\n } else {\n len = 1 / len;\n x0 *= len;\n x1 *= len;\n x2 *= len;\n }\n\n y0 = z1 * x2 - z2 * x1;\n y1 = z2 * x0 - z0 * x2;\n y2 = z0 * x1 - z1 * x0;\n len = Math.hypot(y0, y1, y2);\n\n if (!len) {\n y0 = 0;\n y1 = 0;\n y2 = 0;\n } else {\n len = 1 / len;\n y0 *= len;\n y1 *= len;\n y2 *= len;\n }\n\n out[0] = x0;\n out[1] = y0;\n out[2] = z0;\n out[3] = 0;\n out[4] = x1;\n out[5] = y1;\n out[6] = z1;\n out[7] = 0;\n out[8] = x2;\n out[9] = y2;\n out[10] = z2;\n out[11] = 0;\n out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);\n out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);\n out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);\n out[15] = 1;\n return out;\n}\n/**\n * Generates a matrix that makes something look at something else.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {ReadonlyVec3} eye Position of the viewer\n * @param {ReadonlyVec3} center Point the viewer is looking at\n * @param {ReadonlyVec3} up vec3 pointing up\n * @returns {mat4} out\n */\n\nexport function targetTo(out, eye, target, up) {\n var eyex = eye[0],\n eyey = eye[1],\n eyez = eye[2],\n upx = up[0],\n upy = up[1],\n upz = up[2];\n var z0 = eyex - target[0],\n z1 = eyey - target[1],\n z2 = eyez - target[2];\n var len = z0 * z0 + z1 * z1 + z2 * z2;\n\n if (len > 0) {\n len = 1 / Math.sqrt(len);\n z0 *= len;\n z1 *= len;\n z2 *= len;\n }\n\n var x0 = upy * z2 - upz * z1,\n x1 = upz * z0 - upx * z2,\n x2 = upx * z1 - upy * z0;\n len = x0 * x0 + x1 * x1 + x2 * x2;\n\n if (len > 0) {\n len = 1 / Math.sqrt(len);\n x0 *= len;\n x1 *= len;\n x2 *= len;\n }\n\n out[0] = x0;\n out[1] = x1;\n out[2] = x2;\n out[3] = 0;\n out[4] = z1 * x2 - z2 * x1;\n out[5] = z2 * x0 - z0 * x2;\n out[6] = z0 * x1 - z1 * x0;\n out[7] = 0;\n out[8] = z0;\n out[9] = z1;\n out[10] = z2;\n out[11] = 0;\n out[12] = eyex;\n out[13] = eyey;\n out[14] = eyez;\n out[15] = 1;\n return out;\n}\n/**\n * Returns a string representation of a mat4\n *\n * @param {ReadonlyMat4} a matrix to represent as a string\n * @returns {String} string representation of the matrix\n */\n\nexport function str(a) {\n return \"mat4(\" + a[0] + \", \" + a[1] + \", \" + a[2] + \", \" + a[3] + \", \" + a[4] + \", \" + a[5] + \", \" + a[6] + \", \" + a[7] + \", \" + a[8] + \", \" + a[9] + \", \" + a[10] + \", \" + a[11] + \", \" + a[12] + \", \" + a[13] + \", \" + a[14] + \", \" + a[15] + \")\";\n}\n/**\n * Returns Frobenius norm of a mat4\n *\n * @param {ReadonlyMat4} a the matrix to calculate Frobenius norm of\n * @returns {Number} Frobenius norm\n */\n\nexport function frob(a) {\n return Math.hypot(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]);\n}\n/**\n * Adds two mat4's\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the first operand\n * @param {ReadonlyMat4} b the second operand\n * @returns {mat4} out\n */\n\nexport function add(out, a, b) {\n out[0] = a[0] + b[0];\n out[1] = a[1] + b[1];\n out[2] = a[2] + b[2];\n out[3] = a[3] + b[3];\n out[4] = a[4] + b[4];\n out[5] = a[5] + b[5];\n out[6] = a[6] + b[6];\n out[7] = a[7] + b[7];\n out[8] = a[8] + b[8];\n out[9] = a[9] + b[9];\n out[10] = a[10] + b[10];\n out[11] = a[11] + b[11];\n out[12] = a[12] + b[12];\n out[13] = a[13] + b[13];\n out[14] = a[14] + b[14];\n out[15] = a[15] + b[15];\n return out;\n}\n/**\n * Subtracts matrix b from matrix a\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the first operand\n * @param {ReadonlyMat4} b the second operand\n * @returns {mat4} out\n */\n\nexport function subtract(out, a, b) {\n out[0] = a[0] - b[0];\n out[1] = a[1] - b[1];\n out[2] = a[2] - b[2];\n out[3] = a[3] - b[3];\n out[4] = a[4] - b[4];\n out[5] = a[5] - b[5];\n out[6] = a[6] - b[6];\n out[7] = a[7] - b[7];\n out[8] = a[8] - b[8];\n out[9] = a[9] - b[9];\n out[10] = a[10] - b[10];\n out[11] = a[11] - b[11];\n out[12] = a[12] - b[12];\n out[13] = a[13] - b[13];\n out[14] = a[14] - b[14];\n out[15] = a[15] - b[15];\n return out;\n}\n/**\n * Multiply each element of the matrix by a scalar.\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to scale\n * @param {Number} b amount to scale the matrix's elements by\n * @returns {mat4} out\n */\n\nexport function multiplyScalar(out, a, b) {\n out[0] = a[0] * b;\n out[1] = a[1] * b;\n out[2] = a[2] * b;\n out[3] = a[3] * b;\n out[4] = a[4] * b;\n out[5] = a[5] * b;\n out[6] = a[6] * b;\n out[7] = a[7] * b;\n out[8] = a[8] * b;\n out[9] = a[9] * b;\n out[10] = a[10] * b;\n out[11] = a[11] * b;\n out[12] = a[12] * b;\n out[13] = a[13] * b;\n out[14] = a[14] * b;\n out[15] = a[15] * b;\n return out;\n}\n/**\n * Adds two mat4's after multiplying each element of the second operand by a scalar value.\n *\n * @param {mat4} out the receiving vector\n * @param {ReadonlyMat4} a the first operand\n * @param {ReadonlyMat4} b the second operand\n * @param {Number} scale the amount to scale b's elements by before adding\n * @returns {mat4} out\n */\n\nexport function multiplyScalarAndAdd(out, a, b, scale) {\n out[0] = a[0] + b[0] * scale;\n out[1] = a[1] + b[1] * scale;\n out[2] = a[2] + b[2] * scale;\n out[3] = a[3] + b[3] * scale;\n out[4] = a[4] + b[4] * scale;\n out[5] = a[5] + b[5] * scale;\n out[6] = a[6] + b[6] * scale;\n out[7] = a[7] + b[7] * scale;\n out[8] = a[8] + b[8] * scale;\n out[9] = a[9] + b[9] * scale;\n out[10] = a[10] + b[10] * scale;\n out[11] = a[11] + b[11] * scale;\n out[12] = a[12] + b[12] * scale;\n out[13] = a[13] + b[13] * scale;\n out[14] = a[14] + b[14] * scale;\n out[15] = a[15] + b[15] * scale;\n return out;\n}\n/**\n * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)\n *\n * @param {ReadonlyMat4} a The first matrix.\n * @param {ReadonlyMat4} b The second matrix.\n * @returns {Boolean} True if the matrices are equal, false otherwise.\n */\n\nexport function exactEquals(a, b) {\n return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] && a[4] === b[4] && a[5] === b[5] && a[6] === b[6] && a[7] === b[7] && a[8] === b[8] && a[9] === b[9] && a[10] === b[10] && a[11] === b[11] && a[12] === b[12] && a[13] === b[13] && a[14] === b[14] && a[15] === b[15];\n}\n/**\n * Returns whether or not the matrices have approximately the same elements in the same position.\n *\n * @param {ReadonlyMat4} a The first matrix.\n * @param {ReadonlyMat4} b The second matrix.\n * @returns {Boolean} True if the matrices are equal, false otherwise.\n */\n\nexport function equals(a, b) {\n var a0 = a[0],\n a1 = a[1],\n a2 = a[2],\n a3 = a[3];\n var a4 = a[4],\n a5 = a[5],\n a6 = a[6],\n a7 = a[7];\n var a8 = a[8],\n a9 = a[9],\n a10 = a[10],\n a11 = a[11];\n var a12 = a[12],\n a13 = a[13],\n a14 = a[14],\n a15 = a[15];\n var b0 = b[0],\n b1 = b[1],\n b2 = b[2],\n b3 = b[3];\n var b4 = b[4],\n b5 = b[5],\n b6 = b[6],\n b7 = b[7];\n var b8 = b[8],\n b9 = b[9],\n b10 = b[10],\n b11 = b[11];\n var b12 = b[12],\n b13 = b[13],\n b14 = b[14],\n b15 = b[15];\n return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && Math.abs(a4 - b4) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && Math.abs(a5 - b5) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && Math.abs(a6 - b6) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && Math.abs(a7 - b7) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7)) && Math.abs(a8 - b8) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a8), Math.abs(b8)) && Math.abs(a9 - b9) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a9), Math.abs(b9)) && Math.abs(a10 - b10) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a10), Math.abs(b10)) && Math.abs(a11 - b11) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a11), Math.abs(b11)) && Math.abs(a12 - b12) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a12), Math.abs(b12)) && Math.abs(a13 - b13) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a13), Math.abs(b13)) && Math.abs(a14 - b14) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a14), Math.abs(b14)) && Math.abs(a15 - b15) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a15), Math.abs(b15));\n}\n/**\n * Alias for {@link mat4.multiply}\n * @function\n */\n\nexport var mul = multiply;\n/**\n * Alias for {@link mat4.subtract}\n * @function\n */\n\nexport var sub = subtract;","import * as glMatrix from \"./common.js\";\n/**\n * 3 Dimensional Vector\n * @module vec3\n */\n\n/**\n * Creates a new, empty vec3\n *\n * @returns {vec3} a new 3D vector\n */\n\nexport function create() {\n var out = new glMatrix.ARRAY_TYPE(3);\n\n if (glMatrix.ARRAY_TYPE != Float32Array) {\n out[0] = 0;\n out[1] = 0;\n out[2] = 0;\n }\n\n return out;\n}\n/**\n * Creates a new vec3 initialized with values from an existing vector\n *\n * @param {ReadonlyVec3} a vector to clone\n * @returns {vec3} a new 3D vector\n */\n\nexport function clone(a) {\n var out = new glMatrix.ARRAY_TYPE(3);\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n return out;\n}\n/**\n * Calculates the length of a vec3\n *\n * @param {ReadonlyVec3} a vector to calculate length of\n * @returns {Number} length of a\n */\n\nexport function length(a) {\n var x = a[0];\n var y = a[1];\n var z = a[2];\n return Math.hypot(x, y, z);\n}\n/**\n * Creates a new vec3 initialized with the given values\n *\n * @param {Number} x X component\n * @param {Number} y Y component\n * @param {Number} z Z component\n * @returns {vec3} a new 3D vector\n */\n\nexport function fromValues(x, y, z) {\n var out = new glMatrix.ARRAY_TYPE(3);\n out[0] = x;\n out[1] = y;\n out[2] = z;\n return out;\n}\n/**\n * Copy the values from one vec3 to another\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the source vector\n * @returns {vec3} out\n */\n\nexport function copy(out, a) {\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n return out;\n}\n/**\n * Set the components of a vec3 to the given values\n *\n * @param {vec3} out the receiving vector\n * @param {Number} x X component\n * @param {Number} y Y component\n * @param {Number} z Z component\n * @returns {vec3} out\n */\n\nexport function set(out, x, y, z) {\n out[0] = x;\n out[1] = y;\n out[2] = z;\n return out;\n}\n/**\n * Adds two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\n\nexport function add(out, a, b) {\n out[0] = a[0] + b[0];\n out[1] = a[1] + b[1];\n out[2] = a[2] + b[2];\n return out;\n}\n/**\n * Subtracts vector b from vector a\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\n\nexport function subtract(out, a, b) {\n out[0] = a[0] - b[0];\n out[1] = a[1] - b[1];\n out[2] = a[2] - b[2];\n return out;\n}\n/**\n * Multiplies two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\n\nexport function multiply(out, a, b) {\n out[0] = a[0] * b[0];\n out[1] = a[1] * b[1];\n out[2] = a[2] * b[2];\n return out;\n}\n/**\n * Divides two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\n\nexport function divide(out, a, b) {\n out[0] = a[0] / b[0];\n out[1] = a[1] / b[1];\n out[2] = a[2] / b[2];\n return out;\n}\n/**\n * Math.ceil the components of a vec3\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a vector to ceil\n * @returns {vec3} out\n */\n\nexport function ceil(out, a) {\n out[0] = Math.ceil(a[0]);\n out[1] = Math.ceil(a[1]);\n out[2] = Math.ceil(a[2]);\n return out;\n}\n/**\n * Math.floor the components of a vec3\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a vector to floor\n * @returns {vec3} out\n */\n\nexport function floor(out, a) {\n out[0] = Math.floor(a[0]);\n out[1] = Math.floor(a[1]);\n out[2] = Math.floor(a[2]);\n return out;\n}\n/**\n * Returns the minimum of two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\n\nexport function min(out, a, b) {\n out[0] = Math.min(a[0], b[0]);\n out[1] = Math.min(a[1], b[1]);\n out[2] = Math.min(a[2], b[2]);\n return out;\n}\n/**\n * Returns the maximum of two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\n\nexport function max(out, a, b) {\n out[0] = Math.max(a[0], b[0]);\n out[1] = Math.max(a[1], b[1]);\n out[2] = Math.max(a[2], b[2]);\n return out;\n}\n/**\n * Math.round the components of a vec3\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a vector to round\n * @returns {vec3} out\n */\n\nexport function round(out, a) {\n out[0] = Math.round(a[0]);\n out[1] = Math.round(a[1]);\n out[2] = Math.round(a[2]);\n return out;\n}\n/**\n * Scales a vec3 by a scalar number\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the vector to scale\n * @param {Number} b amount to scale the vector by\n * @returns {vec3} out\n */\n\nexport function scale(out, a, b) {\n out[0] = a[0] * b;\n out[1] = a[1] * b;\n out[2] = a[2] * b;\n return out;\n}\n/**\n * Adds two vec3's after scaling the second operand by a scalar value\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @param {Number} scale the amount to scale b by before adding\n * @returns {vec3} out\n */\n\nexport function scaleAndAdd(out, a, b, scale) {\n out[0] = a[0] + b[0] * scale;\n out[1] = a[1] + b[1] * scale;\n out[2] = a[2] + b[2] * scale;\n return out;\n}\n/**\n * Calculates the euclidian distance between two vec3's\n *\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {Number} distance between a and b\n */\n\nexport function distance(a, b) {\n var x = b[0] - a[0];\n var y = b[1] - a[1];\n var z = b[2] - a[2];\n return Math.hypot(x, y, z);\n}\n/**\n * Calculates the squared euclidian distance between two vec3's\n *\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {Number} squared distance between a and b\n */\n\nexport function squaredDistance(a, b) {\n var x = b[0] - a[0];\n var y = b[1] - a[1];\n var z = b[2] - a[2];\n return x * x + y * y + z * z;\n}\n/**\n * Calculates the squared length of a vec3\n *\n * @param {ReadonlyVec3} a vector to calculate squared length of\n * @returns {Number} squared length of a\n */\n\nexport function squaredLength(a) {\n var x = a[0];\n var y = a[1];\n var z = a[2];\n return x * x + y * y + z * z;\n}\n/**\n * Negates the components of a vec3\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a vector to negate\n * @returns {vec3} out\n */\n\nexport function negate(out, a) {\n out[0] = -a[0];\n out[1] = -a[1];\n out[2] = -a[2];\n return out;\n}\n/**\n * Returns the inverse of the components of a vec3\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a vector to invert\n * @returns {vec3} out\n */\n\nexport function inverse(out, a) {\n out[0] = 1.0 / a[0];\n out[1] = 1.0 / a[1];\n out[2] = 1.0 / a[2];\n return out;\n}\n/**\n * Normalize a vec3\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a vector to normalize\n * @returns {vec3} out\n */\n\nexport function normalize(out, a) {\n var x = a[0];\n var y = a[1];\n var z = a[2];\n var len = x * x + y * y + z * z;\n\n if (len > 0) {\n //TODO: evaluate use of glm_invsqrt here?\n len = 1 / Math.sqrt(len);\n }\n\n out[0] = a[0] * len;\n out[1] = a[1] * len;\n out[2] = a[2] * len;\n return out;\n}\n/**\n * Calculates the dot product of two vec3's\n *\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {Number} dot product of a and b\n */\n\nexport function dot(a, b) {\n return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];\n}\n/**\n * Computes the cross product of two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\n\nexport function cross(out, a, b) {\n var ax = a[0],\n ay = a[1],\n az = a[2];\n var bx = b[0],\n by = b[1],\n bz = b[2];\n out[0] = ay * bz - az * by;\n out[1] = az * bx - ax * bz;\n out[2] = ax * by - ay * bx;\n return out;\n}\n/**\n * Performs a linear interpolation between two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\n * @returns {vec3} out\n */\n\nexport function lerp(out, a, b, t) {\n var ax = a[0];\n var ay = a[1];\n var az = a[2];\n out[0] = ax + t * (b[0] - ax);\n out[1] = ay + t * (b[1] - ay);\n out[2] = az + t * (b[2] - az);\n return out;\n}\n/**\n * Performs a hermite interpolation with two control points\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @param {ReadonlyVec3} c the third operand\n * @param {ReadonlyVec3} d the fourth operand\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\n * @returns {vec3} out\n */\n\nexport function hermite(out, a, b, c, d, t) {\n var factorTimes2 = t * t;\n var factor1 = factorTimes2 * (2 * t - 3) + 1;\n var factor2 = factorTimes2 * (t - 2) + t;\n var factor3 = factorTimes2 * (t - 1);\n var factor4 = factorTimes2 * (3 - 2 * t);\n out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;\n out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;\n out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;\n return out;\n}\n/**\n * Performs a bezier interpolation with two control points\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @param {ReadonlyVec3} c the third operand\n * @param {ReadonlyVec3} d the fourth operand\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\n * @returns {vec3} out\n */\n\nexport function bezier(out, a, b, c, d, t) {\n var inverseFactor = 1 - t;\n var inverseFactorTimesTwo = inverseFactor * inverseFactor;\n var factorTimes2 = t * t;\n var factor1 = inverseFactorTimesTwo * inverseFactor;\n var factor2 = 3 * t * inverseFactorTimesTwo;\n var factor3 = 3 * factorTimes2 * inverseFactor;\n var factor4 = factorTimes2 * t;\n out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;\n out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;\n out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;\n return out;\n}\n/**\n * Generates a random vector with the given scale\n *\n * @param {vec3} out the receiving vector\n * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned\n * @returns {vec3} out\n */\n\nexport function random(out, scale) {\n scale = scale || 1.0;\n var r = glMatrix.RANDOM() * 2.0 * Math.PI;\n var z = glMatrix.RANDOM() * 2.0 - 1.0;\n var zScale = Math.sqrt(1.0 - z * z) * scale;\n out[0] = Math.cos(r) * zScale;\n out[1] = Math.sin(r) * zScale;\n out[2] = z * scale;\n return out;\n}\n/**\n * Transforms the vec3 with a mat4.\n * 4th vector component is implicitly '1'\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the vector to transform\n * @param {ReadonlyMat4} m matrix to transform with\n * @returns {vec3} out\n */\n\nexport function transformMat4(out, a, m) {\n var x = a[0],\n y = a[1],\n z = a[2];\n var w = m[3] * x + m[7] * y + m[11] * z + m[15];\n w = w || 1.0;\n out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w;\n out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w;\n out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w;\n return out;\n}\n/**\n * Transforms the vec3 with a mat3.\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the vector to transform\n * @param {ReadonlyMat3} m the 3x3 matrix to transform with\n * @returns {vec3} out\n */\n\nexport function transformMat3(out, a, m) {\n var x = a[0],\n y = a[1],\n z = a[2];\n out[0] = x * m[0] + y * m[3] + z * m[6];\n out[1] = x * m[1] + y * m[4] + z * m[7];\n out[2] = x * m[2] + y * m[5] + z * m[8];\n return out;\n}\n/**\n * Transforms the vec3 with a quat\n * Can also be used for dual quaternions. (Multiply it with the real part)\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the vector to transform\n * @param {ReadonlyQuat} q quaternion to transform with\n * @returns {vec3} out\n */\n\nexport function transformQuat(out, a, q) {\n // benchmarks: https://jsperf.com/quaternion-transform-vec3-implementations-fixed\n var qx = q[0],\n qy = q[1],\n qz = q[2],\n qw = q[3];\n var x = a[0],\n y = a[1],\n z = a[2]; // var qvec = [qx, qy, qz];\n // var uv = vec3.cross([], qvec, a);\n\n var uvx = qy * z - qz * y,\n uvy = qz * x - qx * z,\n uvz = qx * y - qy * x; // var uuv = vec3.cross([], qvec, uv);\n\n var uuvx = qy * uvz - qz * uvy,\n uuvy = qz * uvx - qx * uvz,\n uuvz = qx * uvy - qy * uvx; // vec3.scale(uv, uv, 2 * w);\n\n var w2 = qw * 2;\n uvx *= w2;\n uvy *= w2;\n uvz *= w2; // vec3.scale(uuv, uuv, 2);\n\n uuvx *= 2;\n uuvy *= 2;\n uuvz *= 2; // return vec3.add(out, a, vec3.add(out, uv, uuv));\n\n out[0] = x + uvx + uuvx;\n out[1] = y + uvy + uuvy;\n out[2] = z + uvz + uuvz;\n return out;\n}\n/**\n * Rotate a 3D vector around the x-axis\n * @param {vec3} out The receiving vec3\n * @param {ReadonlyVec3} a The vec3 point to rotate\n * @param {ReadonlyVec3} b The origin of the rotation\n * @param {Number} rad The angle of rotation in radians\n * @returns {vec3} out\n */\n\nexport function rotateX(out, a, b, rad) {\n var p = [],\n r = []; //Translate point to the origin\n\n p[0] = a[0] - b[0];\n p[1] = a[1] - b[1];\n p[2] = a[2] - b[2]; //perform rotation\n\n r[0] = p[0];\n r[1] = p[1] * Math.cos(rad) - p[2] * Math.sin(rad);\n r[2] = p[1] * Math.sin(rad) + p[2] * Math.cos(rad); //translate to correct position\n\n out[0] = r[0] + b[0];\n out[1] = r[1] + b[1];\n out[2] = r[2] + b[2];\n return out;\n}\n/**\n * Rotate a 3D vector around the y-axis\n * @param {vec3} out The receiving vec3\n * @param {ReadonlyVec3} a The vec3 point to rotate\n * @param {ReadonlyVec3} b The origin of the rotation\n * @param {Number} rad The angle of rotation in radians\n * @returns {vec3} out\n */\n\nexport function rotateY(out, a, b, rad) {\n var p = [],\n r = []; //Translate point to the origin\n\n p[0] = a[0] - b[0];\n p[1] = a[1] - b[1];\n p[2] = a[2] - b[2]; //perform rotation\n\n r[0] = p[2] * Math.sin(rad) + p[0] * Math.cos(rad);\n r[1] = p[1];\n r[2] = p[2] * Math.cos(rad) - p[0] * Math.sin(rad); //translate to correct position\n\n out[0] = r[0] + b[0];\n out[1] = r[1] + b[1];\n out[2] = r[2] + b[2];\n return out;\n}\n/**\n * Rotate a 3D vector around the z-axis\n * @param {vec3} out The receiving vec3\n * @param {ReadonlyVec3} a The vec3 point to rotate\n * @param {ReadonlyVec3} b The origin of the rotation\n * @param {Number} rad The angle of rotation in radians\n * @returns {vec3} out\n */\n\nexport function rotateZ(out, a, b, rad) {\n var p = [],\n r = []; //Translate point to the origin\n\n p[0] = a[0] - b[0];\n p[1] = a[1] - b[1];\n p[2] = a[2] - b[2]; //perform rotation\n\n r[0] = p[0] * Math.cos(rad) - p[1] * Math.sin(rad);\n r[1] = p[0] * Math.sin(rad) + p[1] * Math.cos(rad);\n r[2] = p[2]; //translate to correct position\n\n out[0] = r[0] + b[0];\n out[1] = r[1] + b[1];\n out[2] = r[2] + b[2];\n return out;\n}\n/**\n * Get the angle between two 3D vectors\n * @param {ReadonlyVec3} a The first operand\n * @param {ReadonlyVec3} b The second operand\n * @returns {Number} The angle in radians\n */\n\nexport function angle(a, b) {\n var ax = a[0],\n ay = a[1],\n az = a[2],\n bx = b[0],\n by = b[1],\n bz = b[2],\n mag1 = Math.sqrt(ax * ax + ay * ay + az * az),\n mag2 = Math.sqrt(bx * bx + by * by + bz * bz),\n mag = mag1 * mag2,\n cosine = mag && dot(a, b) / mag;\n return Math.acos(Math.min(Math.max(cosine, -1), 1));\n}\n/**\n * Set the components of a vec3 to zero\n *\n * @param {vec3} out the receiving vector\n * @returns {vec3} out\n */\n\nexport function zero(out) {\n out[0] = 0.0;\n out[1] = 0.0;\n out[2] = 0.0;\n return out;\n}\n/**\n * Returns a string representation of a vector\n *\n * @param {ReadonlyVec3} a vector to represent as a string\n * @returns {String} string representation of the vector\n */\n\nexport function str(a) {\n return \"vec3(\" + a[0] + \", \" + a[1] + \", \" + a[2] + \")\";\n}\n/**\n * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===)\n *\n * @param {ReadonlyVec3} a The first vector.\n * @param {ReadonlyVec3} b The second vector.\n * @returns {Boolean} True if the vectors are equal, false otherwise.\n */\n\nexport function exactEquals(a, b) {\n return a[0] === b[0] && a[1] === b[1] && a[2] === b[2];\n}\n/**\n * Returns whether or not the vectors have approximately the same elements in the same position.\n *\n * @param {ReadonlyVec3} a The first vector.\n * @param {ReadonlyVec3} b The second vector.\n * @returns {Boolean} True if the vectors are equal, false otherwise.\n */\n\nexport function equals(a, b) {\n var a0 = a[0],\n a1 = a[1],\n a2 = a[2];\n var b0 = b[0],\n b1 = b[1],\n b2 = b[2];\n return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2));\n}\n/**\n * Alias for {@link vec3.subtract}\n * @function\n */\n\nexport var sub = subtract;\n/**\n * Alias for {@link vec3.multiply}\n * @function\n */\n\nexport var mul = multiply;\n/**\n * Alias for {@link vec3.divide}\n * @function\n */\n\nexport var div = divide;\n/**\n * Alias for {@link vec3.distance}\n * @function\n */\n\nexport var dist = distance;\n/**\n * Alias for {@link vec3.squaredDistance}\n * @function\n */\n\nexport var sqrDist = squaredDistance;\n/**\n * Alias for {@link vec3.length}\n * @function\n */\n\nexport var len = length;\n/**\n * Alias for {@link vec3.squaredLength}\n * @function\n */\n\nexport var sqrLen = squaredLength;\n/**\n * Perform some operation over an array of vec3s.\n *\n * @param {Array} a the array of vectors to iterate over\n * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed\n * @param {Number} offset Number of elements to skip at the beginning of the array\n * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array\n * @param {Function} fn Function to call for each vector in the array\n * @param {Object} [arg] additional argument to pass to fn\n * @returns {Array} a\n * @function\n */\n\nexport var forEach = function () {\n var vec = create();\n return function (a, stride, offset, count, fn, arg) {\n var i, l;\n\n if (!stride) {\n stride = 3;\n }\n\n if (!offset) {\n offset = 0;\n }\n\n if (count) {\n l = Math.min(count * stride + offset, a.length);\n } else {\n l = a.length;\n }\n\n for (i = offset; i < l; i += stride) {\n vec[0] = a[i];\n vec[1] = a[i + 1];\n vec[2] = a[i + 2];\n fn(vec, vec, arg);\n a[i] = vec[0];\n a[i + 1] = vec[1];\n a[i + 2] = vec[2];\n }\n\n return a;\n };\n}();","// ===== context.ts ===========================================================\n// Main rendering context, guts of the library\n// Ben Coleman, 2023\n// ============================================================================\n\nimport { version } from '../../package.json'\nimport { bindFramebufferInfo, createProgramInfo, ProgramInfo, resizeCanvasToDisplaySize } from 'twgl.js'\nimport { mat4, vec3 } from 'gl-matrix'\nimport log from 'loglevel'\n\nimport { getGl, UniformSet } from './gl.ts'\nimport { RGB, XYZ, Tuples } from '../engine/tuples.ts'\nimport { ModelCache, ProgramCache, TextureCache } from './cache.ts'\nimport { LightDirectional, LightPoint } from '../engine/lights.ts'\nimport { Camera, CameraType } from '../engine/camera.ts'\nimport { Material } from '../engine/material.ts'\nimport { DynamicEnvironmentMap, EnvironmentMap } from '../engine/envmap.ts'\nimport { Instance } from '../models/instance.ts'\nimport { Billboard, BillboardType } from '../models/billboard.ts'\nimport { PrimitiveCube, PrimitivePlane, PrimitiveSphere, PrimitiveCylinder } from '../models/primitive.ts'\nimport { Model } from '../models/model.ts'\nimport { HUD } from './hud.ts'\nimport { stats } from './stats.ts'\n\n// Import shaders, tsup will inline these as text strings\nimport fragShaderPhong from '../../shaders/phong/glsl.frag'\nimport vertShaderPhong from '../../shaders/phong/glsl.vert'\nimport fragShaderBill from '../../shaders/billboard/glsl.frag'\nimport vertShaderBill from '../../shaders/billboard/glsl.vert'\n\n/** @ignore Total max dynamic lights */\nconst MAX_LIGHTS = 16\n\n/**\n * The main rendering context. This is the effectively main entry point for the library.\n * Typically you will create a single instance of this class using init() and use it to render your scene.\n */\nexport class Context {\n private gl: WebGL2RenderingContext\n private started: boolean\n private instances: Instance[] = []\n private instancesTrans: Instance[] = []\n private debugDiv: HTMLDivElement\n private loadingDiv: HTMLDivElement\n private cameras: Map = new Map()\n private activeCameraName: string\n private envmap?: EnvironmentMap\n private dynamicEnvMap?: DynamicEnvironmentMap\n\n /** Global directional light */\n public globalLight: LightDirectional\n\n /** All the dynamic point lights in the scene */\n public lights: LightPoint[] = []\n\n /** Main camera for this context */\n private _camera: Camera\n\n /** Show extra debug details on the canvas */\n public debug: boolean\n\n /**\n * The pre-render update function, called every frame.\n * Hook in your custom logic and processing here\n */\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n public update: (delta: number) => void = () => {}\n\n /** A HUD you can use to render HTML elements over the canvas */\n public readonly hud: HUD\n\n /** Gamma correction value, default 1.0 */\n public gamma = 1.0\n\n // ==== Getters =============================================================\n\n /** Get the active camera */\n get camera() {\n return this._camera\n }\n\n /** Get the name of the active camera */\n get cameraName() {\n return this.activeCameraName\n }\n\n /** Constructor is private, use init() to create a new context */\n private constructor(gl: WebGL2RenderingContext) {\n this.gl = gl\n this.started = false\n this.debug = false\n\n // Main global light\n this.globalLight = new LightDirectional()\n this.globalLight.setAsPosition(20, 50, 30)\n\n const defaultCamera = new Camera(CameraType.PERSPECTIVE)\n this.cameras.set('default', defaultCamera)\n this._camera = defaultCamera\n this.activeCameraName = 'default'\n\n this.hud = new HUD(gl.canvas)\n\n this.debugDiv = document.createElement('div')\n this.debugDiv.classList.add('gsots3d-debug')\n this.debugDiv.style.fontSize = 'min(1.5vw, 20px)'\n this.debugDiv.style.fontFamily = 'monospace'\n this.debugDiv.style.color = 'white'\n this.debugDiv.style.padding = '1vw'\n this.hud.addHUDItem(this.debugDiv)\n\n this.loadingDiv = document.createElement('div')\n this.loadingDiv.classList.add('gsots3d-loading')\n this.loadingDiv.innerHTML = '💾 Loading...'\n this.loadingDiv.style.font = 'normal 4vw sans-serif'\n this.loadingDiv.style.color = 'white'\n this.loadingDiv.style.position = 'absolute'\n this.loadingDiv.style.top = '50%'\n this.loadingDiv.style.left = '50%'\n this.loadingDiv.style.transform = 'translate(-50%, -50%)'\n this.hud.addHUDItem(this.loadingDiv)\n\n log.info(`👑 GSOTS-3D context created, v${version}`)\n }\n\n /**\n * Create & initialize a new Context which will render into provided canvas selector. This is where you start when using the library.\n * @param canvasSelector CSS selector for canvas element, default is 'canvas'\n * @param antiAlias Enable anti-aliasing in GL, default is true\n */\n static async init(canvasSelector = 'canvas', antiAlias = true) {\n const gl = getGl(antiAlias, canvasSelector)\n\n if (!gl) {\n log.error('💥 Failed to create WebGL context, this is extremely bad news')\n throw new Error('Failed to get WebGL context')\n }\n\n // Create the context around the WebGL2 context\n const ctx = new Context(gl)\n\n const canvas = gl.canvas\n ctx.camera.aspectRatio = canvas.clientWidth / canvas.clientHeight\n\n // Load shaders and put into global cache\n const phongProgInfo = createProgramInfo(gl, [vertShaderPhong, fragShaderPhong])\n ProgramCache.init(phongProgInfo)\n ProgramCache.instance.add(ProgramCache.PROG_PHONG, phongProgInfo)\n ProgramCache.instance.add(ProgramCache.PROG_BILLBOARD, createProgramInfo(gl, [vertShaderBill, fragShaderBill]))\n log.info(`🎨 Loaded all shaders & programs, GL is ready`)\n\n gl.enable(gl.DEPTH_TEST)\n gl.enable(gl.BLEND)\n gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)\n\n // Bind to the render function\n ctx.render = ctx.render.bind(ctx)\n\n // Global texture cache, needs to be initialized after GL context is ready\n TextureCache.init(gl)\n\n return ctx\n }\n\n /**\n * Main render loop, called every frame\n * @param now Current time in milliseconds\n */\n private async render(now: number) {\n if (!this.gl) return\n\n stats.updateTime(now * 0.001)\n\n // Call the external update function\n this.update(stats.deltaTime)\n\n // RENDERING - Render into the dynamic environment map(s) if any\n if (this.dynamicEnvMap) {\n // This is a rare case of passing the context to the object, but it's needed for the dynamic env map\n this.dynamicEnvMap.update(this.gl, this)\n }\n\n // RENDERING - Render the shadow map from the global light\n const shadowCam = this.globalLight.getShadowCamera()\n if (shadowCam) {\n // Switch to front face culling for shadow map, yeah it's weird but it works!\n this.gl.cullFace(this.gl.FRONT)\n\n // Bind the shadow map framebuffer and render the scene from the light's POV\n // Using the special shadow map program as an override for the whole rendering pass\n bindFramebufferInfo(this.gl, this.globalLight.shadowMapFrameBufffer)\n this.renderWithCamera(shadowCam, this.globalLight.shadowMapProgram)\n\n // Switch back to back face culling\n this.gl.cullFace(this.gl.BACK)\n }\n\n // RENDERING - Render the scene from active camera into the main framebuffer\n bindFramebufferInfo(this.gl, null)\n this.renderWithCamera(this.camera)\n\n // Draw the debug HUD\n if (this.debug) {\n this.debugDiv.innerHTML = `\n GSOTS-3D v${version}

\n Camera: ${this.camera.toString()}
\n Instances: ${stats.instances}
\n Draw calls: ${stats.drawCallsPerFrame}
\n Triangles: ${stats.triangles}
\n Render: FPS: ${stats.FPS} / ${stats.totalTimeRound}s
\n `\n } else {\n this.debugDiv.innerHTML = ''\n }\n\n // Loop forever or stop if not started\n if (this.started) requestAnimationFrame(this.render)\n\n // Reset stats for next frame\n stats.resetPerFrame()\n }\n\n /**\n * Render the scene from the given camera, used internally\n * @param camera\n */\n renderWithCamera(camera: Camera, programOverride?: ProgramInfo) {\n if (!this.gl) return\n\n // Clear the framebuffer and depth buffer\n this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT)\n\n // Update the camera\n camera.update()\n\n // Do this in every frame since camera can move\n const camMatrix = camera.matrix\n\n // Work out what reflection map to use, if any\n // NOTE: This *not* part of the material because it's too hard to dynamically change\n let reflectMap: WebGLTexture | null = this.envmap?.texture ?? null\n\n // As there is only one dynamic reflection envmap, we can use it across all instances\n // But ONLY set this when the camera is NOT rendering into it!\n if (this.dynamicEnvMap) {\n if (!camera.usedForEnvMap) {\n reflectMap = this.dynamicEnvMap.texture\n }\n }\n\n // The uniforms that are the same for all instances\n const uniforms = {\n u_gamma: this.gamma,\n\n u_worldInverseTranspose: mat4.create(), // Updated per instance\n u_worldViewProjection: mat4.create(), // Updated per instance\n u_view: mat4.invert(mat4.create(), camMatrix),\n u_proj: camera.projectionMatrix,\n u_camPos: camera.position,\n\n u_reflectionMap: reflectMap,\n\n u_shadowMap: this.globalLight.shadowMapTexture,\n u_shadowMatrix: this.globalLight.shadowMatrix ?? mat4.create(),\n u_shadowScatter: this.globalLight.shadowMapOptions?.scatter ?? 0.2,\n } as UniformSet\n\n // RENDERING - Draw envmap around the scene first\n if (this.envmap) {\n this.envmap.render(uniforms.u_view, uniforms.u_proj, camera)\n }\n\n // RENDERING - Process lighting\n\n // Apply global light to the two programs\n uniforms.u_lightDirGlobal = this.globalLight.uniforms\n\n // Only sort lights if we have more than MAX_LIGHTS, it's expensive!\n if (this.lights.length > MAX_LIGHTS) {\n // Sort lights by distance to camera so we can use the closest ones\n this.lights.sort((lightA, lightB) => {\n const ad = vec3.distance(lightA.position, this.camera.position)\n const bd = vec3.distance(lightB.position, this.camera.position)\n return ad - bd\n })\n }\n\n // Add the point lights into u_lightsPos array up to MAX_LIGHTS\n let lightCount = 0\n for (const light of this.lights) {\n if (lightCount >= MAX_LIGHTS) break\n if (!light.enabled) continue\n\n uniforms[`u_lightsPos[${lightCount++}]`] = light.uniforms\n }\n\n uniforms.u_lightsPosCount = lightCount\n\n // RENDERING - Draw all opaque instances\n this.gl.enable(this.gl.CULL_FACE)\n for (const instance of this.instances) {\n instance.render(this.gl, uniforms, programOverride)\n }\n\n // RENDERING - Draw all transparent instances\n this.gl.disable(this.gl.CULL_FACE)\n\n // Sort transparent instances by distance to camera\n // Maybe remove this in scenes with lots of transparent instances?\n this.instancesTrans.sort((a, b) => {\n const ad = Tuples.distance(a.position ?? [0, 0, 0], this.camera.position)\n const bd = Tuples.distance(b.position ?? [0, 0, 0], this.camera.position)\n return bd - ad\n })\n\n for (const instance of this.instancesTrans) {\n instance.render(this.gl, uniforms, programOverride)\n }\n }\n\n /**\n * Start the rendering loop\n */\n start() {\n this.loadingDiv.style.display = 'none'\n this.started = true\n // Restart the render loop\n requestAnimationFrame(this.render)\n }\n\n /**\n * Stop the rendering loop\n */\n stop() {\n this.started = false\n }\n\n /**\n * Resize the canvas to match the size of the element it's in\n * @param viewportOnly - Only resize the viewport, not the canvas\n */\n resize(viewportOnly = false) {\n const canvas = this.gl.canvas\n\n if (!viewportOnly) resizeCanvasToDisplaySize(canvas)\n\n this.gl.viewport(0, 0, canvas.width, canvas.height)\n this.camera.aspectRatio = canvas.width / canvas.height\n\n log.info(\n `📐 RESIZE Internal: ${canvas.width} x ${canvas.height}, display: ${canvas.clientWidth} x ${canvas.clientHeight}`\n )\n }\n\n /**\n * Internal function to add an instance to the scene\n */\n private addInstance(instance: Instance, material: Material) {\n if (material.opacity !== undefined && material.opacity < 1) {\n this.instancesTrans.push(instance)\n } else {\n this.instances.push(instance)\n }\n }\n\n /**\n * Model loader, loads an OBJ model from a file via URL or path and adds it to the cache\n * This is preferred over calling Model.parse() directly\n * @param path Base path to the model file, e.g. './models/'\n * @param fileName Name of the model file, e.g 'teapot.obj'\n * @param filterTextures Apply texture filtering as materials are loaded\n * @param flipTextureY Flip the Y coordinate of the texture\n */\n public async loadModel(path: string, fileName: string, filterTextures = true, flipY = false) {\n const modelName = fileName.split('.')[0]\n\n // Check if model is already loaded\n if (ModelCache.instance.get(modelName, false)) {\n log.warn(`⚠️ Model '${modelName}' already loaded, skipping`)\n return\n }\n\n // Load the model and always flip the UV\n const model = await Model.parse(path, fileName, filterTextures, flipY, true)\n\n ModelCache.instance.add(model)\n }\n\n /**\n * Add a new camera to the scene\n * @param name Name of the camera\n * @param camera Camera instance\n */\n public addCamera(name: string, camera: Camera) {\n this.cameras.set(name, camera)\n }\n\n public getCamera(name: string) {\n return this.cameras.get(name)\n }\n\n /**\n * Set the active camera\n * @param name Name of the camera to set as active\n */\n public setActiveCamera(name: string) {\n const camera = this.cameras.get(name)\n if (!camera) {\n throw new Error(`💥 Unable to set active camera to '${name}', camera not found`)\n }\n\n this.camera.active = false\n this._camera = camera\n this.camera.active = true\n this.activeCameraName = name\n }\n\n // ==========================================================================\n // Methods to create new instances of renderable objects & things\n // ==========================================================================\n\n /**\n * Create a new model instance, which should have been previously loaded into the cache\n * @param modelName - Name of the model previously loaded into the cache, don't include the file extension\n */\n createModelInstance(modelName: string) {\n const model = ModelCache.instance.get(modelName)\n if (!model) {\n throw new Error(`💥 Unable to create model instance for ${modelName}`)\n }\n\n const instance = new Instance(model)\n this.instances.push(instance)\n stats.triangles += model.triangleCount\n stats.instances++\n\n return instance\n }\n\n /**\n * Create an instance of a primitive sphere\n * @param material - Material to apply to the sphere\n * @param radius - Radius of the sphere\n * @param subdivisionsH - Number of subdivisions along the horizontal\n * @param subdivisionsV - Number of subdivisions along the vertical\n */\n createSphereInstance(material: Material, radius = 5, subdivisionsH = 16, subdivisionsV = 8) {\n const sphere = new PrimitiveSphere(this.gl, radius, subdivisionsH, subdivisionsV)\n sphere.material = material\n\n const instance = new Instance(sphere)\n this.addInstance(instance, material)\n stats.triangles += sphere.triangleCount\n stats.instances++\n\n log.debug(`🟢 Created sphere instance, r:${radius}`)\n\n return instance\n }\n\n /**\n * Create an instance of a primitive plane\n * @param material - Material to apply to the plane\n * @param width - Width of the plane\n * @param height - Height of the plane\n * @param subdivisionsW - Number of subdivisions along the width\n * @param subdivisionsH - Number of subdivisions along the height\n * @param tiling - Number of times to tile the texture over the plane\n */\n createPlaneInstance(material: Material, width = 5, height = 5, subdivisionsW = 1, subdivisionsH = 1, tiling = 1) {\n const plane = new PrimitivePlane(this.gl, width, height, subdivisionsW, subdivisionsH, tiling)\n plane.material = material\n\n const instance = new Instance(plane)\n this.addInstance(instance, material)\n stats.triangles += plane.triangleCount\n stats.instances++\n\n log.debug(`🟨 Created plane instance, w:${width} h:${height}`)\n\n return instance\n }\n\n /**\n * Create an instance of a primitive cube\n */\n createCubeInstance(material: Material, size = 5) {\n const cube = new PrimitiveCube(this.gl, size)\n cube.material = material\n\n const instance = new Instance(cube)\n this.addInstance(instance, material)\n stats.triangles += cube.triangleCount\n stats.instances++\n\n log.debug(`📦 Created cube instance, size:${size}`)\n\n return instance\n }\n\n /**\n * Create an instance of a primitive cylinder\n */\n createCylinderInstance(material: Material, r = 2, h = 5, subdivisionsR = 16, subdivisionsH = 1, caps = true) {\n const cyl = new PrimitiveCylinder(this.gl, r, h, subdivisionsR, subdivisionsH, caps)\n cyl.material = material\n\n const instance = new Instance(cyl)\n this.addInstance(instance, material)\n stats.triangles += cyl.triangleCount\n stats.instances++\n\n log.debug(`🛢️ Created cylinder instance, r:${r}`)\n\n return instance\n }\n\n /**\n * Create an instance of a billboard/sprite in the scene\n * @param textureUrl - Path to the texture image file to use for the billboard\n * @param width - Width of the billboard (default: 5)\n * @param height - Height of the billboard (default: 5)\n * @param type - Type of billboard to create (default: CYLINDRICAL)\n */\n createBillboardInstance(material: Material, size = 5, type = BillboardType.CYLINDRICAL) {\n const billboard = new Billboard(this.gl, type, material, size)\n\n const instance = new Instance(billboard)\n\n this.addInstance(instance, material)\n\n stats.triangles += 2\n stats.instances++\n\n log.debug(`🚧 Created billboard instance of type: ${type} size: ${size}`)\n\n return instance\n }\n\n /**\n * Create a new point light in the scene\n * @param position - Position of the light\n * @param colour - Colour of the light, defaults to white\n * @param intensity - Intensity of the light\n * @returns The new light object\n */\n createPointLight(position: XYZ, colour: RGB = [1, 1, 1], intensity = 1) {\n const light = new LightPoint(position, colour)\n light.position = position\n light.colour = colour\n\n // A very simple scaling of the light attenuation\n // Users can still set the attenuation manually if they want\n light.constant /= intensity\n light.linear /= intensity\n light.quad /= intensity\n\n this.lights.push(light)\n\n log.debug(`🔆 Created point light, pos:${position} col:${colour} int:${intensity}`)\n\n return light\n }\n\n /**\n * Set the EnvironmentMap for the scene, will overwrite any existing envmap.\n * This will enable static reflections and create a 'skybox' around the scene\n * @param textureURLs - Array of 6 texture URLs to use for the map, in the order: +X, -X, +Y, -Y, +Z, -Z\n */\n setEnvmap(renderAsBackground = false, ...textureURLs: string[]) {\n this.envmap = new EnvironmentMap(this.gl, textureURLs)\n this.envmap.renderAsBackground = renderAsBackground\n }\n\n /**\n * Remove any current EnvironmentMap from the scene\n */\n removeEnvmap() {\n this.envmap = undefined\n }\n\n /**\n * Get the current EnvironmentMap for the scene\n */\n getEnvmap() {\n return this.envmap\n }\n\n /**\n * Set and create a dynamic environment map which will enable dynamic/realtime reflections\n * @param position - Position to render reflections from\n * @param size - Size of the map to render, note higher sizes will come with a big performance hit\n */\n setDynamicEnvmap(position: XYZ, size = 128, renderDistance = 500) {\n this.dynamicEnvMap = new DynamicEnvironmentMap(this.gl, size, position, renderDistance)\n }\n}\n","// ===== tuples.ts ======================================================\n// Types & helpers for 3-tuples, used for positions, vectors and colours\n// Ben Coleman, 2023\n// ======================================================================\n\nimport { vec3 } from 'gl-matrix'\n\n/** A simple 3D position or vector tuple */\nexport type XYZ = [number, number, number]\n\n/** A simple RGB colour tuple */\nexport type RGB = [number, number, number]\n\n/** A simple RGBA colour tuple */\nexport type RGBA = [number, number, number, number]\n\n// ============================================================================\n// Tuple helpers\n// ============================================================================\n\n/**\n * Normalizes a 3-tuple to a unit vector.\n * @param tuple The tuple to normalize\n */\nfunction normalize(tuple: XYZ | RGB | number[]) {\n const [x, y, z] = tuple\n const len = Math.sqrt(x * x + y * y + z * z)\n\n return tuple.map((v) => v / len) as XYZ\n}\n\n/**\n * Scales a 3-tuple by a scalar.\n * @param tuple The tuple to scale\n * @param scale The scalar to scale by\n */\nfunction scale(tuple: XYZ | RGB | RGBA | number[], amount: number) {\n return tuple.map((v) => v * amount) as XYZ\n}\n\n/**\n * Scales a 3-tuple by a scalar, clamping the result to 0-1.\n * @param tuple The tuple to scale\n * @param scale The scalar to scale by\n */\nfunction scaleClamped(colour: RGB | RGBA, amount: number) {\n scale(colour, amount)\n\n // Clamp to 0-1\n return colour.map((v) => Math.min(Math.max(v, 0), 1)) as RGB | RGBA\n}\n\n/**\n * Converts a 3-tuple to a gl-matrix vec3\n * @param tuple The tuple to convert\n */\nfunction toVec3(tuple: XYZ) {\n return vec3.fromValues(tuple[0], tuple[1], tuple[2])\n}\n\n/**\n * Calculates the distance between two 3-tuples\n * @param a First tuple\n * @param b Second tuple\n */\nfunction distance(a: XYZ, b: XYZ) {\n return (a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2 + (a[2] - b[2]) ** 2\n}\n\n// ============================================================================\n// Colour helpers\n// ============================================================================\n\n/**\n * Creates a RGB 3-tuple from 0-255 values.\n * @param r Red value (0-255)\n * @param g Green value (0-255)\n * @param b Blue value (0-255)\n */\nfunction rgbColour255(r: number, g: number, b: number) {\n return [r / 255, g / 255, b / 255] as RGB\n}\n\n/**\n * Converts a hex string to an RGB 3-tuple.\n * @param hexString\n */\nfunction rgbColourHex(hexString: string) {\n const hex = hexString.replace('#', '')\n const r = parseInt(hex.substring(0, 2), 16)\n const g = parseInt(hex.substring(2, 4), 16)\n const b = parseInt(hex.substring(4, 6), 16)\n\n return rgbColour255(r, g, b)\n}\n\n/**\n * A set of common colours as RGB tuples\n */\nexport class Colours {\n static readonly RED = [1, 0, 0] as RGB\n static readonly GREEN = [0, 1, 0] as RGB\n static readonly BLUE = [0, 0, 1] as RGB\n static readonly YELLOW = [1, 1, 0] as RGB\n static readonly CYAN = [0, 1, 1] as RGB\n static readonly MAGENTA = [1, 0, 1] as RGB\n static readonly BLACK = [0, 0, 0] as RGB\n static readonly WHITE = [1, 1, 1] as RGB\n}\n\n// ============================================================================\n// Exports\n// ============================================================================\n\nexport const Tuples = {\n normalize,\n scale,\n scaleClamped,\n rgbColour255,\n rgbColourHex,\n toVec3,\n distance,\n}\n","// ===== cache.ts =============================================================\n// Caches and managers for models and textures\n// Ben Coleman, 2023\n// ============================================================================\n\nimport log from 'loglevel'\nimport { Model } from '../models/model.ts'\nimport { ProgramInfo, createTexture } from 'twgl.js'\n\nexport const PROG_DEFAULT = 'phong'\nexport const PROG_BILLBOARD = 'billboard'\n\n/**\n * A singleton cache for parsed and loaded models, indexed by name\n */\nexport class ModelCache {\n private cache: Map\n private static _instance: ModelCache\n\n private constructor() {\n this.cache = new Map()\n }\n\n /**\n * Return the singleton instance of the model cache\n */\n static get instance() {\n if (!ModelCache._instance) {\n ModelCache._instance = new ModelCache()\n }\n\n return ModelCache._instance\n }\n\n /**\n * Return a model from the cache by name\n * @param name Name of model without extension\n * @param warn If true, log a warning if model not found\n */\n get(name: string, warn = true) {\n if (!this.cache.has(name) && warn) {\n log.warn(`⚠️ Model '${name}' not found, please load it first`)\n return undefined\n }\n\n return this.cache.get(name)\n }\n\n /**\n * Add a model to the cache, using the model name as key\n */\n add(model: Model) {\n log.debug(`🧰 Adding model '${model.name}' to cache`)\n\n this.cache.set(model.name, model)\n }\n}\n\n/**\n * A caching texture manager\n * It is instantiated with a WebGL context and then used to load and cache textures\n */\nexport class TextureCache {\n private cache: Map\n private gl: WebGL2RenderingContext\n private static _instance: TextureCache\n private static initialized = false\n\n private constructor() {\n this.cache = new Map()\n this.gl = {} as WebGL2RenderingContext\n }\n\n // Create a new texture cache\n static init(gl: WebGL2RenderingContext) {\n this._instance = new TextureCache()\n this._instance.gl = gl\n\n // Add default textures\n\n // 1 pixel white texture used as base for materials\n const white1pixel = createTexture(gl, {\n min: gl.NEAREST,\n mag: gl.NEAREST,\n src: [255, 255, 255, 255],\n })\n\n // 1 pixel texture used for normal mapping is sort of blue-violet colour\n const normal1pixel = createTexture(gl, {\n min: gl.NEAREST,\n mag: gl.NEAREST,\n src: [128, 128, 255, 255],\n })\n\n this._instance.add('_defaults/white', white1pixel)\n this._instance.add('_defaults/normal', normal1pixel)\n\n TextureCache.initialized = true\n }\n\n static get instance() {\n if (!TextureCache.initialized) {\n throw new Error('TextureCache not initialized, call TextureCache.init() first')\n }\n\n return this._instance\n }\n\n /**\n * Return a texture from the cache by name\n * @param key Key of texture, this is usually the URL or filename path\n */\n get(key: string) {\n if (!this.cache.has(key)) {\n log.warn(`💥 Texture ${key} not found in cache`)\n return undefined\n }\n\n log.trace(`👍 Returning texture '${key}' from cache, nice!`)\n return this.cache.get(key)\n }\n\n /**\n * Add a texture to the cache\n * @param key Key of texture, this is usually the URL or filename path\n * @param texture WebGL texture\n */\n add(key: string, texture: WebGLTexture) {\n if (this.cache.has(key)) {\n log.warn(`🤔 Texture '${key}' already in cache, not adding again`)\n return\n }\n\n log.debug(`🧰 Adding texture '${key}' to cache`)\n\n this.cache.set(key, texture)\n }\n\n /**\n * Create or return a texture from the cache by name\n * @param src URL or filename path of texture image\n * @param filter Enable texture filtering and mipmaps (default true)\n * @param flipY Flip the texture vertically (default true)\n */\n getCreate(src: string, filter = true, flipY = false) {\n // check if texture already exists, if so return it\n if (this.cache.has(src)) {\n log.trace(`👍 Returning texture '${src}' from cache, nice!`, flipY)\n return this.get(src)\n }\n\n // Create texture and add to cache\n // NOTE. Catching errors here is very hard, as twgl.createTexture() doesn't throw errors\n const texture = createTexture(\n this.gl,\n {\n min: filter ? this.gl.LINEAR_MIPMAP_LINEAR : this.gl.NEAREST,\n mag: filter ? this.gl.LINEAR : this.gl.NEAREST,\n src: src,\n flipY: flipY ? 1 : 0,\n },\n (err) => {\n if (err) {\n // There's not much we can do here, but log the error\n log.error('💥 Error loading texture', err)\n }\n }\n )\n\n this.add(src, texture)\n return texture\n }\n}\n\n/**\n * Singleton cache for parsed and loaded GL programs, indexed by name\n */\nexport class ProgramCache {\n private cache: Map\n private _default: ProgramInfo\n private static _instance: ProgramCache\n private static initialized = false\n\n public static PROG_PHONG = 'phong'\n public static PROG_BILLBOARD = 'billboard'\n public static PROG_SHADOWMAP = 'shadowmap'\n\n /**\n * Create a new program cache, needs a default program to be set\n * @param defaultProg The default program that can be used by most things\n */\n private constructor() {\n this.cache = new Map()\n // This is pretty nasty, but we really trust people to call init() first\n this._default = {} as ProgramInfo\n }\n\n /**\n * Initialise the program cache with a default program.\n * This MUST be called before using the cache\n * @param defaultProg The default program that can be used by most things\n */\n public static init(defaultProg: ProgramInfo) {\n if (ProgramCache._instance) {\n log.warn('🤔 Program cache already initialised, not doing it again')\n return\n }\n\n ProgramCache._instance = new ProgramCache()\n ProgramCache._instance._default = defaultProg\n ProgramCache.initialized = true\n }\n\n /**\n * Return the singleton instance of the program cache\n */\n static get instance() {\n if (!ProgramCache.initialized) {\n throw new Error('💥 Program cache not initialised, call init() first')\n }\n\n return ProgramCache._instance\n }\n\n /**\n * Return a program from the cache by name\n * @param name Name of program\n */\n get(name: string): ProgramInfo {\n const prog = this.cache.get(name)\n\n if (!prog) {\n log.warn(`⚠️ Program '${name}' not found, returning default`)\n return this._default\n }\n\n return prog\n }\n\n add(name: string, program: ProgramInfo) {\n log.debug(`🧰 Adding program '${name}' to cache`)\n\n this.cache.set(name, program)\n }\n\n get default() {\n return this._default\n }\n}\n","// ===== camera.ts ============================================================\n// Represents a camera in 3D space\n// Ben Coleman, 2023\n// ============================================================================\n\nimport { mat4 } from 'gl-matrix'\nimport { XYZ } from './tuples.ts'\nimport { getGl } from '../core/gl.ts'\n\nimport log from 'loglevel'\n\nexport enum CameraType {\n PERSPECTIVE,\n ORTHOGRAPHIC,\n}\n\nexport class Camera {\n /** Camera position */\n public position: XYZ\n\n /** Camera look at point, default: [0, 0, 0] */\n public lookAt: XYZ\n\n /** Field of view in degrees, default: 45 */\n public fov: number\n\n /** Near clipping plane, default: 0.1 */\n public near: number\n\n /** Far clipping plane, default: 100 */\n public far: number\n\n /** Camera up vector, default: [0, 1, 0] */\n public up: XYZ\n\n /** Change camera projection, default: CameraType.PERSPECTIVE */\n public type: CameraType\n\n /** Is this camera active, default: true */\n public active: boolean\n\n /** Orthographic zoom level, only used when type is orthographic, default: 20 */\n public orthoZoom: number\n\n /** Is this camera used for a dynamic environment map, default: false */\n public usedForEnvMap: boolean\n\n /** Is this camera used for a shadow map, default: false */\n public usedForShadowMap: boolean\n\n /** Aspect ratio of the camera, default: 1 */\n public aspectRatio: number\n\n // Used for first person mode\n private fpAngleY: number\n private fpAngleX: number\n private fpMode: boolean\n private fpHandlersAdded: boolean\n private fpTurnSpeed: number\n private fpMoveSpeed: number\n\n // Used to clamp first person up/down angle\n private maxAngleUp: number = Math.PI / 2 - 0.01\n private maxAngleDown: number = -Math.PI / 2 + 0.01\n\n // Used to track keys pressed in FP mode for better movement\n private keysDown: Set\n private touches: Touch[] = []\n\n /**\n * Create a new default camera\n */\n constructor(type = CameraType.PERSPECTIVE, aspectRatio = 1) {\n this.type = type\n this.active = true\n\n this.position = [0, 0, 30]\n this.lookAt = [0, 0, 0]\n this.up = [0, 1, 0]\n this.near = 0.1\n this.far = 100\n this.fov = 45\n this.aspectRatio = aspectRatio\n this.orthoZoom = 20\n this.usedForEnvMap = false\n this.usedForShadowMap = false\n\n this.fpMode = false\n this.fpAngleY = 0\n this.fpAngleX = 0\n this.fpTurnSpeed = 0.001\n this.fpMoveSpeed = 1.0\n this.fpHandlersAdded = false\n\n this.keysDown = new Set()\n }\n\n /**\n * Get the current view matrix for the camera\n */\n get matrix() {\n // Standard view matrix with position and lookAt for non-FPS camera\n if (!this.fpMode) {\n const camView = mat4.targetTo(mat4.create(), this.position, this.lookAt, this.up)\n return camView\n }\n\n // FPS camera is handled different, we need to rotate the camera around the Y axis\n const camView = mat4.targetTo(mat4.create(), [0, 0, 0], [0, 0, -1], this.up)\n mat4.translate(camView, camView, this.position)\n mat4.rotateY(camView, camView, this.fpAngleY)\n mat4.rotateX(camView, camView, this.fpAngleX)\n return camView\n }\n\n /**\n * Get the projection matrix for this camera\n * @param aspectRatio Aspect ratio of the canvas\n */\n get projectionMatrix() {\n if (this.type === CameraType.ORTHOGRAPHIC) {\n const camProj = mat4.ortho(\n mat4.create(),\n -this.aspectRatio * this.orthoZoom,\n this.aspectRatio * this.orthoZoom,\n -this.orthoZoom,\n this.orthoZoom,\n this.near,\n this.far\n )\n\n return camProj\n } else {\n const camProj = mat4.perspective(mat4.create(), this.fov * (Math.PI / 180), this.aspectRatio, this.near, this.far)\n return camProj\n }\n }\n\n /**\n * Get the camera position as a string for debugging\n */\n toString() {\n const pos = this.position.map((p) => p.toFixed(2))\n return `position: [${pos}]`\n }\n\n /**\n * Switches the camera to first person mode, where the camera is controlled by\n * the mouse and keyboard. The mouse controls look direction and the keyboard\n * controls movement.\n * @param angleY Starting look up/down angle in radians, default 0\n * @param angleX Starting look left/right angle in radians, default 0\n * @param turnSpeed Speed of looking in radians, default 0.001\n * @param moveSpeed Speed of moving in units, default 1.0\n */\n enableFPControls(angleY = 0, angleX = 0, turnSpeed = 0.001, moveSpeed = 1.0) {\n this.fpMode = true\n this.fpAngleY = angleY\n this.fpAngleX = angleX\n this.fpTurnSpeed = turnSpeed\n this.fpMoveSpeed = moveSpeed\n\n if (this.fpHandlersAdded) return // prevent multiple event listeners being added\n\n // Handle enable/disable for pointer lock on main canvas\n // See: https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API\n const gl = getGl()\n gl?.canvas.addEventListener('click', async () => {\n if (!this.fpMode || !this.active) return\n\n if (document.pointerLockElement) {\n document.exitPointerLock()\n } else {\n await (gl?.canvas).requestPointerLock()\n }\n })\n\n // Handle mouse movement for looking around\n window.addEventListener('mousemove', (e) => {\n if (!document.pointerLockElement) {\n return\n }\n\n if (!this.fpMode || !this.active) return\n this.fpAngleY += e.movementX * -this.fpTurnSpeed\n this.fpAngleX += e.movementY * -this.fpTurnSpeed\n\n // Clamp up/down angle\n if (this.fpAngleX > this.maxAngleUp) this.fpAngleX = this.maxAngleUp\n if (this.fpAngleX < this.maxAngleDown) this.fpAngleX = this.maxAngleDown\n })\n\n // Track keys pressed for movement\n window.addEventListener('keydown', (e) => {\n if (!this.fpMode || !this.active) return\n this.keysDown.add(e.key)\n })\n\n window.addEventListener('keyup', (e) => {\n if (!this.fpMode || !this.active) return\n this.keysDown.delete(e.key)\n })\n\n window.addEventListener('touchstart', (e) => {\n if (!this.fpMode || !this.active) return\n\n // If the touch is on the right side of the screen, it's for looking\n if (e.touches[0].clientX > window.innerWidth / 2) {\n this.touches[0] = e.touches[0]\n }\n\n // If the touch is on the left side of the screen, it's for moving\n if (e.touches[0].clientX < window.innerWidth / 2) {\n // top half of screen is forward, bottom half is backward\n if (e.touches[0].clientY < window.innerHeight / 2) {\n this.keysDown.add('w')\n }\n if (e.touches[0].clientY > window.innerHeight / 2) {\n this.keysDown.add('s')\n }\n }\n })\n\n window.addEventListener('touchend', () => {\n if (!this.fpMode || !this.active) return\n\n this.touches = []\n this.keysDown.clear()\n })\n\n window.addEventListener('touchmove', (e) => {\n if (!this.fpMode || !this.active) return\n\n if (this.touches.length === 0) return\n\n const touch = e.touches[0]\n\n const dx = touch.clientX - this.touches[0].clientX\n const dy = touch.clientY - this.touches[0].clientY\n\n this.fpAngleY += dx * -this.fpTurnSpeed * touch.force * 4\n this.fpAngleX += dy * -this.fpTurnSpeed * touch.force * 4\n\n // Clamp up/down angle\n if (this.fpAngleX > this.maxAngleUp) this.fpAngleX = this.maxAngleUp\n if (this.fpAngleX < this.maxAngleDown) this.fpAngleX = this.maxAngleDown\n\n this.touches[0] = touch\n })\n\n this.fpHandlersAdded = true\n log.info('🎥 Camera: first person mode & controls enabled')\n }\n\n /**\n * Disable FP mode\n */\n disableFPControls() {\n this.fpMode = false\n document.exitPointerLock()\n log.debug('🎥 Camera: FPS mode disabled')\n }\n\n /**\n * Get FP mode state\n */\n get fpModeEnabled() {\n return this.fpMode\n }\n\n /**\n * Called every frame to update the camera, currently only used for movement in FP mode\n */\n update() {\n if (!this.fpMode || !this.active) return\n if (this.keysDown.size === 0) return\n\n // use fpAngleY to calculate the direction we are facing\n const dZ = -Math.cos(this.fpAngleY) * this.fpMoveSpeed\n const dX = -Math.sin(this.fpAngleY) * this.fpMoveSpeed\n\n // use keysDown to move the camera\n for (const key of this.keysDown.values()) {\n switch (key) {\n case 'ArrowUp':\n case 'w':\n this.position[0] += dX\n this.position[2] += dZ\n this.lookAt[0] += dX\n this.lookAt[2] += dZ\n break\n\n case 'ArrowDown':\n case 's':\n this.position[0] -= dX\n this.position[2] -= dZ\n this.lookAt[0] -= dX\n this.lookAt[2] -= dZ\n break\n\n case 'ArrowLeft':\n case 'a':\n this.position[0] += dZ\n this.position[2] -= dX\n this.lookAt[0] += dZ\n this.lookAt[2] -= dX\n break\n\n case 'ArrowRight':\n case 'd':\n // move right\n this.position[0] -= dZ\n this.position[2] += dX\n this.lookAt[0] -= dZ\n this.lookAt[2] += dX\n break\n }\n }\n }\n}\n","#version 300 es\n\n// ============================================================================\n// Shadow map fragment shader\n// Ben Coleman, 2023\n// ============================================================================\n\nprecision highp float;\n\nvoid main() {\n // Yeah I don't understand this either, but it works\n}\n","#version 300 es\n\n// ============================================================================\n// Shadow map vertex shader\n// Ben Coleman, 2023\n// ============================================================================\n\nprecision highp float;\n\nin vec4 position;\n\nuniform mat4 u_worldViewProjection;\n\nvoid main() {\n gl_Position = u_worldViewProjection * position;\n}\n","// ===== light.ts =============================================================\n// All light types directional and point\n// Ben Coleman, 2023\n// ============================================================================\n\nimport { mat4 } from 'gl-matrix'\nimport { FramebufferInfo, ProgramInfo, createFramebufferInfo, createProgramInfo, createTexture } from 'twgl.js'\n\nimport { UniformSet, getGl } from '../core/gl.ts'\nimport { Camera, CameraType } from './camera.ts'\nimport { Colours, Tuples, XYZ, RGB } from './tuples.ts'\n\nimport fragShaderShadow from '../../shaders/shadowmap/glsl.frag'\nimport vertShaderShadow from '../../shaders/shadowmap/glsl.vert'\n\n/**\n * Options to configure how shadows are calculated & rendered\n */\nexport type ShadowOptions = {\n /** Size of the shadow map texture. Default: 512 */\n mapSize: number\n\n /**\n * Zoom level of the shadow map camera, larger will cover more of the scene,\n * but results in more blocky shadows. Default 120\n */\n zoom: number\n\n /** Far clipping pane of shadow map camera, default 1000 */\n distance: number\n\n /** Blur the edges of shadows, higher values them more random, default 0.2 */\n scatter: number\n}\n\n/**\n * A directional light source, typically global with the context having only a single instance\n * Having multiple directional lights is not supported\n */\nexport class LightDirectional {\n private _direction: XYZ\n private _shadowMapProgram?: ProgramInfo\n private _shadowMapFB?: FramebufferInfo\n private _shadowMapTex?: WebGLTexture\n private _shadowOptions?: ShadowOptions\n\n /** Colour of the light, used for both diffuse and specular. Default: [0, 0, 0] */\n public colour: RGB\n\n /** Ambient colour of the light. Default: [0, 0, 0] */\n public ambient: RGB\n\n /** Is this light enabled. Default: true */\n public enabled: boolean\n\n /** Create a default directional light, pointing downward */\n constructor() {\n this._direction = [0, -1, 0]\n this.colour = Colours.WHITE\n this.ambient = Colours.BLACK\n this.enabled = true\n\n const gl = getGl()\n if (!gl) {\n throw new Error('💥 LightDirectional: Cannot create shadow map shader, no GL context')\n }\n\n this._shadowMapProgram = createProgramInfo(gl, [vertShaderShadow, fragShaderShadow], ['shadowProgram'])\n }\n\n /**\n * Set the direction of the light ensuring it is normalized\n * @param direction - Direction vector\n */\n set direction(direction: XYZ) {\n // Ensure direction is normalized\n this._direction = Tuples.normalize(direction)\n }\n\n /**\n * Get the direction of the light\n */\n get direction() {\n return this._direction\n }\n\n /**\n * Convenience method allows setting the direction as a point relative to the world origin\n * Values are always converted to a normalized unit direction vector\n * @param x - X position\n * @param y - Y position\n * @param z - Z position\n */\n setAsPosition(x: number, y: number, z: number) {\n this._direction = Tuples.normalize([0 - x, 0 - y, 0 - z])\n }\n\n /**\n * Return the base set of uniforms for this light\n */\n get uniforms() {\n return {\n direction: this.direction,\n colour: this.enabled ? this.colour : [0, 0, 0],\n ambient: this.ambient ? this.ambient : [0, 0, 0],\n } as UniformSet\n }\n\n /**\n * Enable shadows for this light, this will create a shadow map texture and framebuffer\n * There is no way to disabled shadows once enabled\n * @param options A set of ShadowOptions to configure how shadows are calculated\n */\n enableShadows(options?: ShadowOptions) {\n this._shadowOptions = options ?? ({} as ShadowOptions)\n if (!this._shadowOptions.mapSize) {\n this._shadowOptions.mapSize = 512\n }\n if (!this._shadowOptions.zoom) {\n this._shadowOptions.zoom = 120\n }\n if (!this._shadowOptions.distance) {\n this._shadowOptions.distance = 1000\n }\n if (!this._shadowOptions.scatter) {\n this._shadowOptions.scatter = 0.2\n }\n\n const gl = getGl()\n if (!gl) {\n throw new Error('💥 LightDirectional: Cannot create shadow map, no GL context')\n }\n\n // This is a special type of texture, used for depth comparison and shadow mapping\n this._shadowMapTex = createTexture(gl, {\n width: this._shadowOptions.mapSize,\n height: this._shadowOptions.mapSize,\n internalFormat: gl.DEPTH_COMPONENT32F, // Makes this a depth texture\n compareMode: gl.COMPARE_REF_TO_TEXTURE, // Becomes a shadow map, e.g. sampler2DShadow\n minMag: gl.LINEAR, // Can be linear sampled only if compare mode is set\n })\n\n // Framebuffer to render the shadow map into\n this._shadowMapFB = createFramebufferInfo(\n gl,\n [{ attachment: this._shadowMapTex, attachmentPoint: gl.DEPTH_ATTACHMENT }],\n this._shadowOptions.mapSize,\n this._shadowOptions.mapSize\n )\n }\n\n /**\n * Get a virtual camera that can be used to render a shadow map for this light\n * @param zoomLevel - Zoom level of the camera, default: 30\n * @param aspectRatio - Aspect ratio of the camera, default: 1\n */\n getShadowCamera() {\n if (!this._shadowOptions) {\n return undefined\n }\n\n const moveDist = this._shadowOptions.distance * 0.2\n\n const cam = new Camera(CameraType.ORTHOGRAPHIC, 1.0)\n cam.orthoZoom = this._shadowOptions.zoom\n cam.lookAt = [0, 0, 0]\n cam.position = [-this.direction[0] * moveDist, -this.direction[1] * moveDist, -this.direction[2] * moveDist]\n cam.usedForShadowMap = true\n cam.far = this._shadowOptions.distance\n\n return cam\n }\n\n /**\n * Get the forward view matrix for the virtual camera used to render the shadow map\n */\n get shadowMatrix() {\n if (!this._shadowOptions) {\n return undefined\n }\n\n const shadowCam = this.getShadowCamera()\n if (!shadowCam) {\n return undefined\n }\n\n const camViewMatrix = shadowCam.matrix\n const shadowMatrix = mat4.multiply(\n mat4.create(),\n shadowCam.projectionMatrix,\n mat4.invert(mat4.create(), camViewMatrix)\n )\n\n return shadowMatrix\n }\n\n get shadowMapProgram() {\n return this._shadowMapProgram\n }\n\n get shadowMapFrameBufffer() {\n return this._shadowMapFB\n }\n\n get shadowMapTexture() {\n return this._shadowMapTex\n }\n\n get shadowMapOptions() {\n return this._shadowOptions\n }\n}\n\n/*\n * A point light source, doesn't cast shadows but does attenuate with distance\n */\nexport class LightPoint {\n /*\n * Position of the light in world space\n * @default [0, 100, 0]\n */\n public position: XYZ\n\n /*\n * Colour of the light\n * @default [1, 1, 1]\n */\n public colour: RGB\n\n /**\n * Ambient colour of the light\n * @default [0, 0, 0]\n */\n public ambient: RGB\n\n /*\n * Attenuation constant drop off rate\n * @default 1.0\n */\n public constant: number\n\n /*\n * Attenuation linear drop off rate\n * @default 0.07\n */\n public linear: number\n\n /*\n * Attenuation quadratic drop off rate\n * @default 0.017\n */\n public quad: number\n\n /**\n * Is this light enabled\n * @default true\n */\n public enabled: boolean\n\n /**\n * Create a default point light, positioned at the world origin\n * @param position - Position of the light in world space\n * @param colour - Colour of the light\n * @param constant - Attenuation constant drop off rate, default 0.5\n * @param linear - Attenuation linear drop off rate, default 0.018\n * @param quad - Attenuation quadratic drop off rate, default 0.0003\n */\n constructor(position: XYZ, colour: RGB, constant = 0.5, linear = 0.018, quad = 0.0003) {\n this.position = position\n this.colour = colour\n this.constant = constant\n this.linear = linear\n this.quad = quad\n\n // No ambient contribution by default, this can get messy otherwise\n this.ambient = Colours.BLACK\n this.enabled = true\n }\n\n /**\n * Return the base set of uniforms for this light\n */\n public get uniforms() {\n return {\n enabled: this.enabled,\n quad: this.quad,\n position: this.position,\n colour: this.colour,\n ambient: this.ambient,\n constant: this.constant,\n linear: this.linear,\n } as UniformSet\n }\n}\n","// ===== envmap.ts ==========================================================\n// EnvironmentMap class, for rendering reflections\n// Ben Coleman, 2023\n// ============================================================================\n\nimport {\n BufferInfo,\n FramebufferInfo,\n ProgramInfo,\n bindFramebufferInfo,\n createFramebufferInfo,\n createProgramInfo,\n createTexture,\n drawBufferInfo,\n primitives,\n setBuffersAndAttributes,\n setUniforms,\n} from 'twgl.js'\nimport { mat4 } from 'gl-matrix'\nimport log from 'loglevel'\n\nimport { Camera, CameraType } from './camera.ts'\n\nimport fragShaderEnvmap from '../../shaders/envmap/glsl.frag'\nimport vertShaderEnvmap from '../../shaders/envmap/glsl.vert'\nimport { XYZ } from './tuples.ts'\nimport { Context } from '../index.ts'\n\nexport class EnvironmentMap {\n private programInfo: ProgramInfo\n private gl: WebGL2RenderingContext\n private _texture: WebGLTexture\n private cube: BufferInfo\n\n /**\n * Render the environment map as a background, like a skybox\n */\n public renderAsBackground: boolean\n\n /**\n * Create a new environment map with 6 textures for each side\n * @param gl GL context\n * @param textureURLs Array of 6 texture URLs, in order: +x, -x, +y, -y, +z, -z\n */\n constructor(gl: WebGL2RenderingContext, textureURLs: string[]) {\n this.gl = gl\n\n // Create shader program for special envmap rendering\n this.programInfo = createProgramInfo(gl, [vertShaderEnvmap, fragShaderEnvmap])\n\n // Create the cube\n this.cube = primitives.createCubeBufferInfo(gl, 1)\n this.renderAsBackground = true\n\n log.info(`🏔️ EnvironmentMap created!`)\n\n // Don't go via the texture cache, as cube maps are a special case\n if (textureURLs.length !== 6) {\n throw new Error('💥 Cubemap requires 6 textures')\n }\n\n this._texture = createTexture(gl, {\n target: gl.TEXTURE_CUBE_MAP,\n src: textureURLs,\n min: gl.LINEAR_MIPMAP_LINEAR,\n mag: gl.LINEAR,\n cubeFaceOrder: [\n gl.TEXTURE_CUBE_MAP_POSITIVE_X,\n gl.TEXTURE_CUBE_MAP_NEGATIVE_X,\n gl.TEXTURE_CUBE_MAP_POSITIVE_Y,\n gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,\n gl.TEXTURE_CUBE_MAP_POSITIVE_Z,\n gl.TEXTURE_CUBE_MAP_NEGATIVE_Z,\n ],\n flipY: 0,\n })\n }\n\n /**\n * Render this envmap as a cube in, around the given camera & matrices\n * This is used for rendering the envmap as a background and skybox around the scene\n * @param viewMatrix View matrix\n * @param projMatrix Projection matrix\n * @param camera Camera\n */\n render(viewMatrix: mat4, projMatrix: mat4, camera: Camera) {\n if (!this.renderAsBackground) return\n\n this.gl.useProgram(this.programInfo.program)\n // Note: Disable depth test so envmap is always drawn behind everything else\n this.gl.disable(this.gl.DEPTH_TEST)\n\n const uniforms = {\n u_envMapTex: this._texture,\n u_worldViewProjection: mat4.create(),\n }\n\n const world = mat4.create()\n // Envmap magic 1 - translate envmap is always centered on camera\n mat4.translate(world, world, camera.position)\n // Envmap magic 2 - scale the envmap to be the same size as the camera far plane\n // This means it will always be drawn\n mat4.scale(world, world, [camera.far, camera.far, camera.far])\n\n // Create worldView matrix, used for positioning\n const worldView = mat4.multiply(mat4.create(), viewMatrix, world)\n\n mat4.multiply(uniforms.u_worldViewProjection, projMatrix, worldView)\n\n setBuffersAndAttributes(this.gl, this.programInfo, this.cube)\n setUniforms(this.programInfo, uniforms)\n drawBufferInfo(this.gl, this.cube)\n\n this.gl.enable(this.gl.DEPTH_TEST)\n }\n\n get texture(): WebGLTexture {\n return this._texture\n }\n}\n\n/**\n * Used for rendering a dynamic environment map, to create realtime reflections\n * For performance reasons, there is only one dynamic envmap per scene context\n */\nexport class DynamicEnvironmentMap {\n private _texture: WebGLTexture\n private facings: DynamicEnvMapFace[] = []\n private camera: Camera\n\n /**\n * Create a new dynamic environment map\n * @param gl GL context\n * @param size Size of each face of the cube map\n * @param position Position of the center of the cube map, reflections will be rendered from here\n */\n constructor(gl: WebGL2RenderingContext, size: number, position: XYZ, far: number) {\n // The main texture cubemap\n this._texture = createTexture(gl, {\n target: gl.TEXTURE_CUBE_MAP,\n width: size,\n height: size,\n minMag: gl.LINEAR,\n cubeFaceOrder: [\n gl.TEXTURE_CUBE_MAP_POSITIVE_X,\n gl.TEXTURE_CUBE_MAP_NEGATIVE_X,\n gl.TEXTURE_CUBE_MAP_POSITIVE_Y,\n gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,\n gl.TEXTURE_CUBE_MAP_POSITIVE_Z,\n gl.TEXTURE_CUBE_MAP_NEGATIVE_Z,\n ],\n })\n\n // This array holds the 6 faces of the cube map and the framebuffer info plus direction\n this.facings = [\n {\n face: gl.TEXTURE_CUBE_MAP_POSITIVE_X,\n direction: [1, 0, 0],\n buffer: createFramebufferInfo(\n gl,\n [{ attachment: this._texture, target: gl.TEXTURE_CUBE_MAP_POSITIVE_X }, { format: gl.DEPTH_COMPONENT16 }],\n size,\n size\n ),\n },\n {\n face: gl.TEXTURE_CUBE_MAP_NEGATIVE_X,\n direction: [-1, 0, 0],\n buffer: createFramebufferInfo(\n gl,\n [{ attachment: this._texture, target: gl.TEXTURE_CUBE_MAP_NEGATIVE_X }, { format: gl.DEPTH_COMPONENT16 }],\n size,\n size\n ),\n },\n {\n face: gl.TEXTURE_CUBE_MAP_POSITIVE_Y,\n direction: [0, 1, 0],\n buffer: createFramebufferInfo(\n gl,\n [{ attachment: this._texture, target: gl.TEXTURE_CUBE_MAP_POSITIVE_Y }, { format: gl.DEPTH_COMPONENT16 }],\n size,\n size\n ),\n },\n {\n face: gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,\n direction: [0, -1, 0],\n buffer: createFramebufferInfo(\n gl,\n [{ attachment: this._texture, target: gl.TEXTURE_CUBE_MAP_NEGATIVE_Y }, { format: gl.DEPTH_COMPONENT16 }],\n size,\n size\n ),\n },\n {\n face: gl.TEXTURE_CUBE_MAP_POSITIVE_Z,\n direction: [0, 0, 1],\n buffer: createFramebufferInfo(\n gl,\n [{ attachment: this._texture, target: gl.TEXTURE_CUBE_MAP_POSITIVE_Z }, { format: gl.DEPTH_COMPONENT16 }],\n size,\n size\n ),\n },\n {\n face: gl.TEXTURE_CUBE_MAP_NEGATIVE_Z,\n direction: [0, 0, -1],\n buffer: createFramebufferInfo(\n gl,\n [{ attachment: this._texture, target: gl.TEXTURE_CUBE_MAP_NEGATIVE_Z }, { format: gl.DEPTH_COMPONENT16 }],\n size,\n size\n ),\n },\n ]\n\n this.camera = new Camera(CameraType.PERSPECTIVE)\n this.camera.position = position\n this.camera.fov = 90 // 90 degree FOV for cubemap to work properly\n\n // IMPORTANT: Mark this as a special camera used for envmaps\n this.camera.usedForEnvMap = true\n\n this.camera.far = far\n }\n\n /** Get the texture of the environment cubemap */\n get texture(): WebGLTexture {\n return this._texture\n }\n\n /**\n * This is used to position the camera for creating the reflection map\n * @param position Position of the center of the cube map\n */\n set position(pos: XYZ) {\n this.camera.position = pos\n }\n\n /**\n * Update the environment map, by rendering the scene from the given position into the cubemap texture\n * @param ctx GSOTS Context\n */\n update(gl: WebGL2RenderingContext, ctx: Context) {\n // Render each face of the cubemap into the texture & framebuffer\n // NOTE: This requires SIX calls to renderWithCamera!\n for (const facing of this.facings) {\n // Update the camera to look in the direction of the face\n this.camera.lookAt = [\n this.camera.position[0] + facing.direction[0],\n this.camera.position[1] + facing.direction[1],\n this.camera.position[2] + facing.direction[2],\n ]\n\n // Stops the camera from flipping upside down and other weirdness\n this.camera.up = [0, -1, 0]\n if (facing.face === gl.TEXTURE_CUBE_MAP_NEGATIVE_Y) {\n this.camera.up = [0, 0, -1]\n }\n if (facing.face === gl.TEXTURE_CUBE_MAP_POSITIVE_Y) {\n this.camera.up = [0, 0, 1]\n }\n\n bindFramebufferInfo(gl, facing.buffer)\n ctx.renderWithCamera(this.camera)\n }\n }\n}\n\n/**\n * Internal type for storing a dynamic envmap facing info\n */\nexport type DynamicEnvMapFace = {\n face: number\n direction: XYZ\n buffer: FramebufferInfo\n}\n","#version 300 es\n\n// ============================================================================\n// Environment map fragment shader\n// Ben Coleman, 2023\n// ============================================================================\n\nprecision highp float;\n\nin vec3 v_texCoord;\n\nuniform samplerCube u_envMapTex;\n\nout vec4 outColour;\n\nvoid main() {\n // Use the texture cube map as the colour\n // Note: We don't need to do any lighting calculations here\n outColour = texture(u_envMapTex, v_texCoord);\n}\n","#version 300 es\n\n// ============================================================================\n// Environment map vertex shader\n// Ben Coleman, 2023\n// ============================================================================\n\nprecision highp float;\n\nin vec4 position;\n\nuniform mat4 u_worldViewProjection;\n\nout vec3 v_texCoord;\n\nvoid main() {\n // This essentially is what makes the envmap work, texCoords\n // are taken from the vertex position\n v_texCoord = position.xyz;\n\n gl_Position = u_worldViewProjection * position;\n}\n","// ===== instance.ts ==========================================================\n// Instance class, holds position, rotation, scale etc for a renderable\n// Ben Coleman, 2023\n// ============================================================================\n\nimport { mat4 } from 'gl-matrix'\nimport { UniformSet } from '../core/gl.ts'\nimport { Renderable } from './types.ts'\nimport { Material } from '../engine/material.ts'\nimport { XYZ } from '../engine/tuples.ts'\nimport { ProgramInfo } from 'twgl.js'\n\n/**\n * An instance of thing in the world to be rendered, with position, rotation, scale etc\n */\nexport class Instance {\n public readonly renderable: Renderable | undefined\n public position: XYZ | undefined\n public scale: XYZ | undefined\n public rotate: XYZ | undefined\n public enabled = true\n public metadata: Record = {}\n public castShadow = true\n\n /**\n * Material to use for this instance, this will override ALL the materials on the model!\n * Really only useful for simple untextured models without a MTL file\n */\n public material?: Material\n\n /**\n * Per instance texture flip flags, useful for flipping textures on a per instance basis\n * @default false\n */\n public flipTextureX = false\n\n /**\n * Per instance texture flip flags, useful for flipping textures on a per instance basis\n * @default false\n */\n public flipTextureY = false\n\n /**\n * @param {Renderable} renderable - Renderable to use for this instance\n */\n constructor(renderable: Renderable) {\n this.renderable = renderable\n }\n\n /**\n * Rotate this instance around the X axis\n */\n rotateX(angle: number) {\n if (!this.rotate) this.rotate = [0, 0, 0]\n this.rotate[0] += angle\n }\n\n /**\n * Rotate this instance around the Y axis\n */\n rotateY(angle: number) {\n if (!this.rotate) this.rotate = [0, 0, 0]\n this.rotate[1] += angle\n }\n\n /**\n * Rotate this instance around the Z axis\n */\n rotateZ(angle: number) {\n if (!this.rotate) this.rotate = [0, 0, 0]\n this.rotate[2] += angle\n }\n\n rotateZDeg(angle: number) {\n this.rotateZ((angle * Math.PI) / 180)\n }\n\n rotateYDeg(angle: number) {\n this.rotateY((angle * Math.PI) / 180)\n }\n\n rotateXDeg(angle: number) {\n this.rotateX((angle * Math.PI) / 180)\n }\n\n /**\n * Render this instance in the world\n * @param {WebGL2RenderingContext} gl - WebGL context to render into\n * @param {UniformSet} uniforms - Map of uniforms to pass to shader\n */\n render(gl: WebGL2RenderingContext, uniforms: UniformSet, programOverride?: ProgramInfo) {\n if (!this.enabled) return\n if (!this.renderable) return\n if (!gl) return\n\n // HACK: As programOverride is CURRENTLY only used for shadow map rendering\n // We need a better way to to know if we are rendering a shadow map!!\n if (programOverride && !this.castShadow) {\n return\n }\n\n // Local instance transforms are applied in this order to form the world matrix\n const scale = mat4.create()\n const rotate = mat4.create()\n const translate = mat4.create()\n\n // Apply scale, rotate, translate in that order\n if (this.scale) mat4.scale(scale, scale, this.scale)\n if (this.rotate) {\n mat4.rotateX(rotate, rotate, this.rotate[0])\n mat4.rotateY(rotate, rotate, this.rotate[1])\n mat4.rotateZ(rotate, rotate, this.rotate[2])\n }\n if (this.position) mat4.translate(translate, translate, this.position)\n\n // Combine all transforms into world matrix, in reverse order\n const world = translate\n mat4.multiply(world, world, rotate)\n mat4.multiply(world, world, scale)\n\n // Populate u_world - used for normals & shading\n uniforms.u_world = world\n\n // Populate u_worldInverseTranspose - used for normals & shading\n mat4.invert(uniforms.u_worldInverseTranspose, world)\n mat4.transpose(uniforms.u_worldInverseTranspose, uniforms.u_worldInverseTranspose)\n\n // Create worldView matrix, used for positioning\n const worldView = mat4.multiply(mat4.create(), uniforms.u_view, world)\n\n // Finally populate u_worldViewProjection used for rendering\n mat4.multiply(uniforms.u_worldViewProjection, uniforms.u_proj, worldView)\n\n // Apply per instance texture flip flags\n uniforms.u_flipTextureX = this.flipTextureX\n uniforms.u_flipTextureY = this.flipTextureY\n\n // Render the renderable thing wrapped by this instance\n this.renderable.render(gl, uniforms, this.material, programOverride)\n }\n}\n","// ===== stats.ts =======================================================\n// Global singleton for keeping track of stats, timers performance\n// Ben Coleman, 2023\n// ======================================================================\n\nclass Stats {\n private prevTime = 0\n\n public drawCallsPerFrame = 0\n\n public instances = 0\n public triangles = 0\n\n public deltaTime = 0\n public totalTime = 0\n\n resetPerFrame() {\n this.drawCallsPerFrame = 0\n }\n\n updateTime(now: number) {\n this.deltaTime = now - this.prevTime // Get smoothed time difference\n this.prevTime = now\n this.totalTime += this.deltaTime\n }\n\n get FPS() {\n return Math.round(1 / this.deltaTime)\n }\n\n get totalTimeRound() {\n return Math.round(this.totalTime)\n }\n}\n\n// Export a global singleton\n/** @ignore */\nexport const stats = new Stats()\n","// ===== billboard.ts =========================================================\n// For drawing 2D billboards, like trees, grass, etc\n// Ben Coleman, 2023\n// ============================================================================\n\nimport {\n ProgramInfo,\n drawBufferInfo,\n setBuffersAndAttributes,\n setUniforms,\n primitives,\n BufferInfo,\n createBufferInfoFromArrays,\n} from 'twgl.js'\nimport { UniformSet } from '../core/gl.ts'\nimport { Renderable } from './types.ts'\nimport { Material } from '../engine/material.ts'\nimport { stats } from '../core/stats.ts'\nimport { ProgramCache } from '../index.ts'\nimport { mat4, vec3 } from 'gl-matrix'\n\n/** Billboarding modes, most things will ue NONE */\nexport enum BillboardType {\n SPHERICAL,\n CYLINDRICAL,\n}\n\n/**\n * A simple 2D billboard, like a tree or grass. These are square by default, but can be scaled XY if needed.\n * Both cylindrical and spherical billboards are supported. You must assign material with a texture\n * to be rendered as a sprite on the billboard\n * @see http://www.opengl-tutorial.org/intermediate-tutorials/billboards-particles/billboards/\n */\nexport class Billboard implements Renderable {\n protected bufferInfo: BufferInfo\n private programInfo: ProgramInfo\n public material: Material\n public tex: WebGLTexture | undefined\n public type: BillboardType = BillboardType.CYLINDRICAL\n\n /** Creates a square billboard */\n constructor(gl: WebGL2RenderingContext, type: BillboardType, material: Material, size: number) {\n this.material = material\n this.type = type\n\n // Create quad vertices\n const verts = primitives.createXYQuadVertices(size, 0, size / 2)\n\n // Flip Y axis, so texture is not upside down\n for (let i = 1; i < verts.texcoord.length; i += 2) {\n verts.texcoord[i] = 1 - verts.texcoord[i]\n }\n\n this.bufferInfo = createBufferInfoFromArrays(gl, verts)\n\n // Use the billboard shader for this renderable\n this.programInfo = ProgramCache.instance.get(ProgramCache.PROG_BILLBOARD)\n }\n\n /**\n * Render is used draw this billboard, this is called from the Instance that wraps\n * this renderable\n */\n render(gl: WebGL2RenderingContext, uniforms: UniformSet, materialOverride?: Material): void {\n // We ignore programOverride here, as we always use the billboard shader\n const programInfo = this.programInfo\n\n gl.useProgram(programInfo.program)\n\n if (materialOverride === undefined) {\n this.material.apply(programInfo)\n } else {\n materialOverride.apply(programInfo)\n }\n\n // We're doubling up on work done in the Instance class here, hard to get around this\n const worldView = mat4.multiply(mat4.create(), uniforms.u_view, uniforms.u_world)\n\n // Extract scale from worldView matrix, before we zap it\n const scale = mat4.getScaling(vec3.create(), worldView)\n\n // For CYLINDRICAL billboarding, we need to remove some parts of the worldView matrix\n // See: https://www.geeks3d.com/20140807/billboarding-vertex-shader-glsl/\n worldView[0] = scale[0]\n worldView[1] = 0\n worldView[2] = 0\n worldView[8] = 0\n worldView[9] = 0\n worldView[10] = scale[2]\n\n if (this.type == BillboardType.SPHERICAL) {\n // For SPHERICAL billboarding, we remove some more\n worldView[4] = 0\n worldView[5] = scale[1]\n worldView[6] = 0\n }\n\n // We're doubling up on work again :/\n mat4.multiply(uniforms.u_worldViewProjection, uniforms.u_proj, worldView)\n\n setBuffersAndAttributes(gl, programInfo, this.bufferInfo)\n setUniforms(programInfo, uniforms)\n\n drawBufferInfo(gl, this.bufferInfo)\n stats.drawCallsPerFrame++\n }\n}\n","// ===== material.ts ==========================================================\n// Represents a material, with all the properties from the MTL file\n// Ben Coleman, 2023\n// ============================================================================\n\nimport { ProgramInfo, setUniforms } from 'twgl.js'\nimport { RGB } from './tuples.ts'\nimport { MtlMaterial } from '../parsers/mtl-parser.ts'\nimport { UniformSet } from '../core/gl.ts'\nimport { TextureCache } from '../core/cache.ts'\n\nexport class Material {\n /**\n * Ambient colour will be multiplied with the ambient light level & colour\n */\n public ambient: RGB\n\n /**\n * Diffuse colour will be multiplied with the diffuse texture\n * @default [1, 1, 1]\n */\n public diffuse: RGB\n\n /**\n * Specular colour will be multiplied with the specular texture\n * @default [0, 0, 0]\n */\n public specular: RGB\n\n /**\n * Emissive colour will be added to the final colour, use for glowing materials\n */\n public emissive: RGB\n\n /**\n * Shininess, for size of specular highlights\n * @default 20\n */\n public shininess: number\n\n /**\n * Opacity, 0.0 to 1.0\n * @default 1.0\n */\n public opacity: number\n\n /**\n * Reflectivity, 0.0 to 1.0\n * @default 0.0\n */\n public reflectivity: number\n\n /**\n * Diffuse texture map\n * @default \"1 pixel white texture\"\n */\n public diffuseTex?: WebGLTexture\n\n /**\n * Specular texture map\n * @default \"1 pixel white texture\"\n */\n public specularTex?: WebGLTexture\n\n /**\n * Normal texture map\n * @default \"1 pixel white texture\"\n */\n public normalTex?: WebGLTexture\n\n /**\n * Create a new material with default diffuse white colour\n */\n constructor() {\n this.ambient = [1, 1, 1]\n this.diffuse = [1, 1, 1]\n this.specular = [0, 0, 0]\n this.emissive = [0, 0, 0]\n\n this.shininess = 20\n this.opacity = 1.0\n this.reflectivity = 0.0\n\n // 1 pixel white texture allows for solid colour & flat materials\n this.diffuseTex = TextureCache.instance.get('_defaults/white')\n this.specularTex = TextureCache.instance.get('_defaults/white')\n }\n\n /**\n * Create a new material from a raw MTL material\n * @param rawMtl Raw MTL material\n * @param basePath Base path for locating & loading textures in MTL file\n * @param filter Apply texture filtering to textures, default: true\n * @param flipY Flip the Y axis of textures, default: false\n */\n static fromMtl(rawMtl: MtlMaterial, basePath: string, filter = true, flipY = false) {\n const m = new Material()\n\n m.ambient = rawMtl.ka ? rawMtl.ka : [1, 1, 1]\n m.diffuse = rawMtl.kd ? rawMtl.kd : [1, 1, 1]\n m.specular = rawMtl.ks ? rawMtl.ks : [0, 0, 0]\n m.emissive = rawMtl.ke ? rawMtl.ke : [0, 0, 0]\n m.shininess = rawMtl.ns ? rawMtl.ns : 0\n m.opacity = rawMtl.d ? rawMtl.d : 1.0\n\n if (rawMtl.texDiffuse) {\n m.diffuseTex = TextureCache.instance.getCreate(`${basePath}/${rawMtl.texDiffuse}`, filter, flipY)\n }\n\n if (rawMtl.texSpecular) {\n m.specularTex = TextureCache.instance.getCreate(`${basePath}/${rawMtl.texSpecular}`, filter, flipY)\n }\n\n if (rawMtl.texNormal) {\n m.normalTex = TextureCache.instance.getCreate(`${basePath}/${rawMtl.texNormal}`, filter, flipY)\n }\n\n // This is a kludge, a guess; if illum is 3 or more and Ks is set, then we have\n // a reflective material of some kind\n if (rawMtl.illum && rawMtl.illum > 2) {\n m.reflectivity = (m.specular[0] + m.specular[1] + m.specular[2]) / 3\n }\n\n return m\n }\n\n /**\n * Create a basic Material with a solid diffuse colour\n */\n static createSolidColour(r: number, g: number, b: number) {\n const m = new Material()\n m.diffuse = [r, g, b]\n\n return m\n }\n\n /**\n * Create a new Material with a texture map loaded from a URL\n */\n static createBasicTexture(url: string, filter = true, flipY = false) {\n const m = new Material()\n\n m.diffuseTex = TextureCache.instance.getCreate(url, filter, flipY)\n\n return m\n }\n\n /**\n * Add a specular texture map to existing material, probably created with createBasicTexture\n * @param url\n * @param filter\n */\n addSpecularTexture(url: string, filter = true, flipY = false) {\n this.specularTex = TextureCache.instance.getCreate(url, filter, flipY)\n this.specular = [1, 1, 1]\n this.shininess = 20\n }\n\n /**\n * Add a normal texture map to existing material, probably created with createBasicTexture\n * @param url\n * @param filter\n */\n addNormalTexture(url: string, filter = true, flipY = false) {\n this.normalTex = TextureCache.instance.getCreate(url, filter, flipY)\n }\n\n /** Create a simple RED Material */\n static get RED() {\n const m = Material.createSolidColour(1.0, 0.0, 0.0)\n return m\n }\n\n /** Create a simple GREEN Material */\n static get GREEN() {\n return Material.createSolidColour(0.0, 1.0, 0.0)\n }\n\n /** Create a simple BLUE Material */\n static get BLUE() {\n const m = Material.createSolidColour(0.0, 0.0, 1.0)\n\n return m\n }\n\n /** Create a simple BLUE Material */\n static get WHITE() {\n const m = Material.createSolidColour(1.0, 1.0, 1.0)\n\n return m\n }\n\n /**\n * Applies the material to the given program as a uniform struct\n */\n apply(programInfo: ProgramInfo, uniformSuffix = '') {\n const uni = {\n [`u_mat${uniformSuffix}`]: this.uniforms,\n }\n\n setUniforms(programInfo, uni)\n }\n\n /**\n * Return the base set of uniforms for this material\n */\n get uniforms(): UniformSet {\n return {\n ambient: this.ambient,\n diffuse: this.diffuse,\n specular: this.specular,\n emissive: this.emissive,\n shininess: this.shininess,\n opacity: this.opacity,\n reflectivity: this.reflectivity,\n diffuseTex: this.diffuseTex ? this.diffuseTex : null,\n specularTex: this.specularTex ? this.specularTex : null,\n normalTex: this.normalTex ? this.normalTex : null,\n hasNormalTex: this.normalTex ? true : false,\n } as UniformSet\n }\n}\n","// ======== primitive.ts ======================================================\n// Main model class, holds a list of parts, each with a material\n// Models are parsed from OBJ files\n// Ben Coleman, 2023\n// ============================================================================\n\nimport {\n ProgramInfo,\n drawBufferInfo,\n setBuffersAndAttributes,\n setUniforms,\n primitives,\n BufferInfo,\n createBufferInfoFromArrays,\n} from 'twgl.js'\nimport { UniformSet } from '../core/gl.ts'\nimport { Renderable } from './types.ts'\nimport { Material } from '../engine/material.ts'\nimport { stats } from '../core/stats.ts'\nimport { ProgramCache } from '../core/cache.ts'\n\n/**\n * A simple primitive 3D object, like a sphere or cube\n */\nexport abstract class Primitive implements Renderable {\n protected bufferInfo: BufferInfo | undefined\n private programInfo: ProgramInfo\n public material: Material\n public tex: WebGLTexture | undefined\n protected triangles: number\n\n constructor() {\n this.material = new Material()\n this.triangles = 0\n this.programInfo = ProgramCache.instance.default\n }\n\n get triangleCount(): number {\n return this.triangles\n }\n\n /**\n * Render is used draw this primitive, this is called from the Instance that wraps\n * this renderable.\n */\n render(\n gl: WebGL2RenderingContext,\n uniforms: UniformSet,\n materialOverride?: Material,\n programOverride?: ProgramInfo\n ): void {\n if (!this.bufferInfo) return\n\n const programInfo = programOverride || this.programInfo\n gl.useProgram(programInfo.program)\n\n if (materialOverride === undefined) {\n this.material.apply(programInfo)\n } else {\n materialOverride.apply(programInfo)\n }\n\n setBuffersAndAttributes(gl, programInfo, this.bufferInfo)\n setUniforms(programInfo, uniforms)\n\n drawBufferInfo(gl, this.bufferInfo)\n stats.drawCallsPerFrame++\n }\n}\n\n/**\n * A simple sphere primitive with a given radius and subdivisions\n */\nexport class PrimitiveSphere extends Primitive {\n /**\n * Create a new sphere primitive\n * @param gl WebGL2RenderingContext\n * @param radius Radius of the sphere\n * @param subdivisionsH Number of horizontal subdivisions\n * @param subdivisionsV Number of vertical subdivisions\n */\n constructor(gl: WebGL2RenderingContext, radius: number, subdivisionsH: number, subdivisionsV: number) {\n super()\n\n this.bufferInfo = primitives.createSphereBufferInfo(gl, radius, subdivisionsH, subdivisionsV)\n\n this.triangles += this.bufferInfo.numElements / 3\n }\n}\n\n/**\n * A simple cube primitive with a given size\n */\nexport class PrimitiveCube extends Primitive {\n /**\n * Create a new cube primitive\n * @param gl WebGL2RenderingContext\n * @param size Size of the cube\n */\n constructor(gl: WebGL2RenderingContext, size: number) {\n super()\n\n this.bufferInfo = primitives.createCubeBufferInfo(gl, size)\n\n this.triangles += this.bufferInfo.numElements / 3\n }\n}\n\n/**\n * A simple plane primitive with a given size, subdivisions & tiling factor\n */\nexport class PrimitivePlane extends Primitive {\n /**\n * Create a new plane primitive\n * @param gl WebGL2RenderingContext\n * @param width Width of the plane\n * @param height Height of the plane\n * @param subdivisionsW Number of horizontal subdivisions\n * @param subdivisionsH Number of vertical subdivisions\n * @param tilingFactor Number of times to tile the texture across the plane\n */\n constructor(\n gl: WebGL2RenderingContext,\n width: number,\n height: number,\n subdivisionsW: number,\n subdivisionsH: number,\n tilingFactor: number\n ) {\n super()\n\n const verts = primitives.createPlaneVertices(width, height, subdivisionsW, subdivisionsH)\n\n // Mutate the texture coords to tile the texture\n for (let i = 0; i < verts.texcoord.length; i++) {\n verts.texcoord[i] = verts.texcoord[i] * tilingFactor\n }\n\n this.bufferInfo = createBufferInfoFromArrays(gl, verts)\n this.triangles += this.bufferInfo.numElements / 3\n }\n}\n\n/**\n * A simple cylinder primitive with a given radius, height and subdivisions\n */\nexport class PrimitiveCylinder extends Primitive {\n /**\n * Create a new cylinder primitive\n * @param gl WebGL2RenderingContext\n * @param radius Radius of the cylinder\n * @param height Height of the cylinder\n * @param subdivisionsR Subdivisions around the cylinder\n * @param subdivisionsV Subdivisions vertically\n * @param caps Should the cylinder have caps\n */\n constructor(\n gl: WebGL2RenderingContext,\n radius: number,\n height: number,\n subdivisionsR: number,\n subdivisionsV: number,\n caps: boolean\n ) {\n super()\n\n this.bufferInfo = primitives.createCylinderBufferInfo(gl, radius, height, subdivisionsR, subdivisionsV, caps, caps)\n\n this.triangles += this.bufferInfo.numElements / 3\n }\n}\n","// ===== model.ts =============================================================\n// Main model class, holds a list of parts, each with a material\n// Models are parsed from OBJ files\n// Ben Coleman, 2023\n// ============================================================================\n\nimport {\n BufferInfo,\n ProgramInfo,\n createBufferInfoFromArrays,\n drawBufferInfo,\n setBuffersAndAttributes,\n setUniforms,\n} from 'twgl.js'\nimport log from 'loglevel'\n\nimport { Material } from '../engine/material.ts'\nimport { parseMTL } from '../parsers/mtl-parser.ts'\nimport { parseOBJ } from '../parsers/obj-parser.ts'\nimport { fetchFile } from '../core/files.ts'\nimport { getGl, UniformSet } from '../core/gl.ts'\nimport { Renderable } from './types.ts'\nimport { stats } from '../core/stats.ts'\nimport { ProgramCache } from '../core/cache.ts'\n\n/**\n * Holds a 3D model, as a list of parts, each with a material\n * Plus map of named materials\n */\nexport class Model implements Renderable {\n private programInfo: ProgramInfo\n private readonly parts = [] as ModelPart[]\n private readonly materials = {} as Record\n private triangles: number\n\n /** Name of the model, usually the filename without the extension */\n public readonly name: string\n\n /**\n * Constructor is private, use static `parse()` method instead\n */\n private constructor(name: string) {\n this.name = name\n this.triangles = 0\n this.programInfo = ProgramCache.instance.default\n }\n\n /**\n * Render is used draw this model, this is called from the Instance that wraps\n * this renderable.\n */\n render(\n gl: WebGL2RenderingContext,\n uniforms: UniformSet,\n materialOverride?: Material,\n programOverride?: ProgramInfo\n ): void {\n const programInfo = programOverride || this.programInfo\n gl.useProgram(programInfo.program)\n\n // Render each part of the model\n for (const part of this.parts) {\n const bufferInfo = part.bufferInfo\n\n if (materialOverride === undefined) {\n // Get the named material for this part\n let material = this.materials[part.materialName]\n\n // Fall back to default material if not found\n if (!material) {\n material = this.materials['__default']\n }\n\n material.apply(programInfo)\n } else {\n materialOverride.apply(programInfo)\n }\n\n setBuffersAndAttributes(gl, programInfo, bufferInfo)\n setUniforms(programInfo, uniforms)\n\n drawBufferInfo(gl, bufferInfo)\n stats.drawCallsPerFrame++\n }\n }\n\n /** Simple getter for the number of triangles in the model */\n get triangleCount(): number {\n return this.triangles\n }\n\n /**\n * Parse an OBJ file & MTL material libraries, returns a new Model\n * @param {string} path - The path to the OBJ file\n * @param {string} objFilename - The name of the OBJ file\n * @param {boolean} filterTextures - Apply texture filtering to textures, default: true\n * @param {boolean} flipTextureY - Flip the Y axis of textures as they are loaded, default: false\n * @param {boolean} flipUV - Flip the UV coords of the model in the vertex/mesh data, default: true\n */\n static async parse(path = '.', objFilename: string, filterTextures = true, flipTextureY = false, flipUV = true) {\n const startTime = performance.now()\n\n // Create a new model with the name of the file\n const name = objFilename.split('.')[0]\n const model = new Model(name)\n\n // Load the OBJ file from URL\n let objFile: string\n try {\n objFile = await fetchFile(`${path}/${objFilename}`)\n } catch (err) {\n throw new Error(`💥 Unable to load file '${path}/${objFilename}'`)\n }\n\n // Try to parse the OBJ file\n // NOTE: We flip texture coords by default, this is because most OBJ files don't work with OpenGL\n const objData = parseOBJ(objFile, flipUV)\n\n if (!objData.geometries || objData.geometries.length === 0) {\n throw new Error(`💥 Error parsing '${objFilename}', might not be a OBJ file`)\n }\n\n // We assume that the OBJ file has a SINGLE material library\n // This is a good assumption for nearly all files I've seen\n if (objData.matLibNames && objData.matLibNames.length > 0) {\n try {\n const mtlFile = await fetchFile(`${path}/${objData.matLibNames[0]}`)\n const materialsRawList = parseMTL(mtlFile)\n\n for (const [matName, matRaw] of materialsRawList) {\n model.materials[matName] = Material.fromMtl(matRaw, path, filterTextures, flipTextureY)\n }\n } catch (err) {\n log.warn(`💥 Unable to load material library ${objData.matLibNames[0]}`)\n }\n }\n\n // Fall back default material\n model.materials['__default'] = new Material()\n model.materials['__default'].diffuse = [0.1, 0.6, 0.9]\n\n // This really should already been memoized by the context at this point\n const gl = getGl()\n\n if (!gl) {\n throw new Error('💥 Unable to get WebGL context')\n }\n\n for (const g of objData.geometries) {\n // TODO: One day add tangent generation\n const bufferInfo = createBufferInfoFromArrays(gl, g.data)\n model.parts.push(new ModelPart(bufferInfo, g.material))\n }\n\n log.debug(\n `♟️ Model '${objFilename}' loaded with ${model.parts.length} parts, ${\n Object.keys(model.materials).length\n } materials in ${((performance.now() - startTime) / 1000).toFixed(2)}s`\n )\n\n model.triangles = objData.triangles\n return model\n }\n\n /**\n * Get list of all material names in this model used by all parts\n * @returns {string[]} - List of material names\n */\n get materialNames(): string[] {\n return Object.keys(this.materials)\n }\n\n /**\n * Get number of parts in this model\n */\n get partsCount(): number {\n return this.parts.length\n }\n\n /**\n * Get list of parts in this model, names are the material names\n * @returns {string[]} - List of part material names\n */\n get partList(): string[] {\n return this.parts.map((p) => p.materialName)\n }\n\n /**\n * Can modify & override an existing named material\n * @param {string} name - Name of the material to modify\n * @param {Material} material - New material to use\n */\n setNamedMaterial(name: string, material: Material): void {\n this.materials[name] = material\n }\n\n /**\n * Get a named material\n * @param {string} name - Name of the material to get\n */\n getNamedMaterial(name: string): Material {\n return this.materials[name]\n }\n}\n\n/**\n * Holds part of a model, as the WebGL buffers needed to render it\n * Plus the material name associated with this part\n */\nexport class ModelPart {\n public readonly bufferInfo: BufferInfo\n public readonly materialName: string\n\n /**\n * @param {twgl.BufferInfo} bufferInfo - WebGL buffer info for this model part\n * @param {string} materialName - Name of the material associated with this part\n */\n constructor(bufferInfo: BufferInfo, materialName: string) {\n this.bufferInfo = bufferInfo\n this.materialName = materialName\n }\n}\n","// ===== mtl-parser.mjs ==========================================================\n// A simple MTL parser\n// Taken from https://webglfundamentals.org/webgl/lessons/webgl-load-obj-w-mtl.html\n// Ben Coleman, 2023\n// ===============================================================================\n\n/**\n * A \"raw\" material fetched from the MTL parser, don't use this directly\n */\nexport type MtlMaterial = {\n illum?: number\n\n ns?: number\n d?: number\n\n ka?: [number, number, number]\n kd?: [number, number, number]\n ks?: [number, number, number]\n ke?: [number, number, number]\n\n texDiffuse?: string\n texSpecular?: string\n texNormal?: string\n}\n\n/**\n * Parse an MTL file returning a map of materials.\n * The returned {@link typescript!MtlMaterial} should be passed to new Material() to create a material\n * @param {string} mtlFile - The MTL file as a string\n * @returns {Map} - A map of materials\n */\nexport function parseMTL(mtlFile: string): Map {\n const materials = new Map()\n let material = {} as MtlMaterial\n\n const keywords = {\n newmtl(_: string[], unparsedArgs: string) {\n material = {} as MtlMaterial\n materials.set(unparsedArgs, material)\n },\n\n Ns(parts: string[]) {\n material.ns = parseFloat(parts[0])\n },\n Ka(parts: string[]) {\n material.ka = <[number, number, number]>parts.map(parseFloat)\n },\n Kd(parts: string[]) {\n material.kd = <[number, number, number]>parts.map(parseFloat)\n },\n Ks(parts: string[]) {\n material.ks = <[number, number, number]>parts.map(parseFloat)\n },\n // This is a non-standard addition, but semi-official\n Ke(parts: string[]) {\n material.ke = <[number, number, number]>parts.map(parseFloat)\n },\n Ni() {\n // Not used\n //material.ni = parseFloat(parts[0])\n },\n d(parts: string[]) {\n material.d = parseFloat(parts[0])\n },\n illum(parts: string[]) {\n material.illum = parseInt(parts[0])\n },\n map_Kd(_: string[], unparsedArgs: string) {\n material.texDiffuse = unparsedArgs\n },\n map_Ks(_: string[], unparsedArgs: string) {\n material.texSpecular = unparsedArgs\n },\n map_bump(_: string[], unparsedArgs: string) {\n material.texNormal = unparsedArgs\n },\n map_Bump(_: string[], unparsedArgs: string) {\n material.texNormal = unparsedArgs\n },\n } as Record void>\n\n const keywordRE = /(\\w*)(?: )*(.*)/\n const lines = mtlFile.split('\\n')\n\n for (let lineNo = 0; lineNo < lines.length; ++lineNo) {\n const line = lines[lineNo].trim()\n if (line === '' || line.startsWith('#')) {\n continue\n }\n\n const m = keywordRE.exec(line)\n if (!m) {\n continue\n }\n\n const [, keyword, unparsedArgs] = m\n const parts = line.split(/\\s+/).slice(1)\n\n const handler = keywords[keyword]\n if (!handler) {\n //console.warn('unhandled keyword:', keyword)\n continue\n }\n\n handler(parts, unparsedArgs)\n }\n\n return materials\n}\n","// ===== obj-parser.mjs ==========================================================\n// A simple OBJ parser, works well, but FAR from comprehensive\n// Taken from https://webglfundamentals.org/webgl/lessons/webgl-obj-loader.html\n// Ben Coleman, 2023\n// ===============================================================================\n\nconst keywordRE = /(\\w*)(?: )*(.*)/\n\n/**\n * ParseResult is the result of parsing an OBJ file\n */\nexport type ParseResult = {\n /** List of material libs (MTL files) */\n matLibNames: string[]\n\n /** List of geometries, each with a material name and vertex data */\n geometries: Geometry[]\n\n /** Total number of triangles in the OBJ file */\n triangles: number\n}\n\n/**\n * Each OBJ file is made up of a list of geometries, each with a material name.\n * These can be thought of as parts of the overall model.\n */\nexport type Geometry = {\n /** Name of the material for this geometry part */\n material: string\n\n /** Vertex data for this geometry part, ready for turning into an BufferInfo in twgl.js */\n data: {\n position: number[]\n texcoord?: number[]\n normal: number[]\n tangent?: number[]\n }\n}\n\n/**\n * Parse an OBJ file returning a list of geometries and materials libs\n * @param {string} objFile - The OBJ file as a string\n * @param {boolean} flipUV - Flip the V texcoord axis, for OpenGL\n */\nexport function parseOBJ(objFile: string, flipUV: boolean) {\n const lines = objFile.split('\\n')\n\n const objPositions = [[0, 0, 0]]\n const objTexcoords = [[0, 0]]\n const objNormals = [[0, 0, 0]]\n\n // same order as `f` indices\n const objVertexData = [objPositions, objTexcoords, objNormals]\n\n let triangles = 0\n\n // same order as `f` indices\n let webglVertexData = [\n [], // position\n [], // texcoord\n [], // normal\n ] as number[][]\n\n const geometries = Array()\n let geometry = {} as Geometry\n let material = '__default'\n const materialLibs = Array()\n\n const keywords = {\n v(parts: string[]) {\n objPositions.push(parts.map(parseFloat))\n },\n\n vn(parts: string[]) {\n objNormals.push(parts.map(parseFloat))\n },\n\n vt(parts: string[]) {\n // Only 2D texcoords supported, so ignore the 3rd if present\n // Also handle UV flip in the V direction (Y axis) for OpenGL\n if (flipUV) {\n objTexcoords.push([parseFloat(parts[0]), 1.0 - parseFloat(parts[1])])\n } else {\n objTexcoords.push([parseFloat(parts[0]), parseFloat(parts[1])])\n }\n },\n\n f(parts: string[]) {\n triangles++\n setGeometry()\n const numTriangles = parts.length - 2\n for (let tri = 0; tri < numTriangles; ++tri) {\n addVertex(parts[0])\n addVertex(parts[tri + 1])\n addVertex(parts[tri + 2])\n }\n },\n\n usemtl(_: string[], unparsedArgs: string) {\n material = unparsedArgs\n newGeometry()\n },\n\n mtllib(_: string[], unparsedArgs: string) {\n materialLibs.push(unparsedArgs)\n },\n\n // Not used, but suppress warnings\n s() {\n return\n },\n\n o() {\n return\n },\n\n g() {\n return\n },\n\n l() {\n return\n },\n } as Record void>\n\n /**\n * Updates webglVertexData per vertex\n * @param {string} vert - String in the form of \"v/vt/vn\" as per OBJ spec\n */\n function addVertex(vert: string) {\n const ptn = vert.split('/')\n\n ptn.forEach((objIndexStr, i) => {\n if (!objIndexStr) {\n return\n }\n\n const objIndex = parseInt(objIndexStr)\n const index = objIndex + (objIndex >= 0 ? 0 : objVertexData[i].length)\n\n webglVertexData[i].push(...objVertexData[i][index])\n })\n }\n\n /**\n * Start a new geometry object\n */\n function newGeometry() {\n // If there is an existing geometry and it's not empty then start a new one.\n if (geometry.material) {\n geometry = {} as Geometry\n }\n }\n\n /**\n * Set the geometry for the current material/part\n */\n function setGeometry() {\n if (!geometry.material) {\n const position = [] as number[]\n const texcoord = [] as number[]\n const normal = [] as number[]\n\n webglVertexData = [position, texcoord, normal]\n\n /** @type {Geometry} */\n geometry = {\n material,\n data: {\n position,\n texcoord,\n normal,\n },\n }\n\n geometries.push(geometry)\n }\n }\n\n // Parse the OBJ file line by line\n for (let lineNo = 0; lineNo < lines.length; ++lineNo) {\n const line = lines[lineNo].trim()\n if (line === '' || line.startsWith('#')) {\n continue\n }\n\n const m = keywordRE.exec(line)\n if (!m) {\n continue\n }\n\n const [, keyword, unparsedArgs] = m\n const parts = line.split(/\\s+/).slice(1)\n\n const handler = keywords[keyword]\n if (!handler) {\n console.warn('unhandled keyword:', keyword, 'at line', lineNo + 1)\n continue\n }\n\n handler(parts, unparsedArgs)\n }\n\n // FIX: For those OBJ files that don't have texcoord data\n for (const g of geometries) {\n if (g.data.texcoord && g.data.texcoord.length <= 0) {\n delete g.data.texcoord\n }\n }\n\n // Return the list of geometries and material libs, plus triangle count\n return {\n matLibNames: materialLibs,\n geometries: geometries,\n triangles,\n } as ParseResult\n}\n","// ===== files.ts =============================================================\n// File loading utilities\n// Ben Coleman, 2023\n// ============================================================================\n\ntype Shader = {\n vertex: string\n fragment: string\n}\n\n/**\n * Fetch a file from the server\n *\n * @param {string} path - URL path to file\n * @returns {Promise} File contents as a string\n */\nexport async function fetchFile(filePath: string) {\n const resp = await fetch(filePath)\n\n if (!resp.ok) {\n throw new Error(`💥 File fetch failed: ${resp.statusText}`)\n }\n\n const text = await resp.text()\n return text\n}\n\n/**\n * Fetch a pair of shaders from the server\n *\n * @param {string} vertPath - URL path to vertex shader\n * @param {string} fragPath - URL path to fragment shader\n * @returns {Promise} Pair of shaders as strings\n */\nexport async function fetchShaders(vertPath: string, fragPath: string) {\n const vsResp = await fetch(vertPath)\n const fsResp = await fetch(fragPath)\n\n if (!vsResp.ok || !fsResp.ok) {\n throw new Error(`💥 Fetch failed - vertex: ${vsResp.statusText}, fragment: ${fsResp.statusText}`)\n }\n\n const vsText = await vsResp.text()\n const fsText = await fsResp.text()\n\n return { vertex: vsText, fragment: fsText } as Shader\n}\n","// ===== hud.ts =========================================================\n// A HTML based HUD for the game, this is a simple div for now\n// Ben Coleman, 2023\n// ======================================================================\n\nexport class HUD {\n private hud: HTMLDivElement\n private canvas: HTMLCanvasElement\n\n constructor(canvas: HTMLCanvasElement) {\n const parent = canvas.parentElement\n if (!parent) throw new Error('💥 Canvas must have a parent element')\n\n this.canvas = canvas\n\n this.hud = document.createElement('div')\n this.hud.classList.add('gsots3d-hud')\n\n this.update = this.update.bind(this)\n window.addEventListener('resize', this.update)\n window.addEventListener('load', this.update)\n\n parent.appendChild(this.hud)\n this.update()\n }\n\n update() {\n const canvasStyles = window.getComputedStyle(this.canvas, null)\n this.hud.style.position = canvasStyles.getPropertyValue('position')\n this.hud.style.top = canvasStyles.getPropertyValue('top')\n this.hud.style.left = canvasStyles.getPropertyValue('left')\n this.hud.style.width = canvasStyles.getPropertyValue('width')\n this.hud.style.height = canvasStyles.getPropertyValue('height')\n this.hud.style.transform = canvasStyles.getPropertyValue('transform')\n\n // IMPORTANT: This is needed to make the canvas clickable for pointer lock\n this.hud.style.pointerEvents = 'none'\n }\n\n addHUDItem(item: HTMLElement) {\n this.hud.appendChild(item)\n }\n\n debug(msg: string) {\n this.hud.innerHTML = msg\n }\n}\n","#version 300 es\n\n// ============================================================================\n// Phong fragment shader\n// Ben Coleman, 2023\n// ============================================================================\n\nprecision highp float;\n\n// ===== Constants ============================================================\n\nconst int MAX_LIGHTS = 16;\n\n// Got this from http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-16-shadow-mapping/#poisson-sampling\nvec3 poissonDisk[4] = vec3[](\n vec3(-0.94201624, -0.39906216, 0.0),\n vec3(0.94558609, -0.76890725, 0.0),\n vec3(-0.094184101, -0.9293887, 0.0),\n vec3(0.34495938, 0.2938776, 0.0)\n);\n\n// ===== Structs ==============================================================\n\nstruct LightDir {\n vec3 direction;\n vec3 colour;\n vec3 ambient;\n};\n\nstruct LightPos {\n vec3 position;\n vec3 colour;\n vec3 ambient;\n float constant;\n float linear;\n float quad;\n bool enabled;\n};\n\nstruct Material {\n vec3 ambient;\n vec3 diffuse;\n vec3 specular;\n vec3 emissive;\n float shininess;\n float opacity;\n float reflectivity;\n sampler2D diffuseTex;\n sampler2D specularTex;\n sampler2D normalTex;\n bool hasNormalTex;\n};\n\n// Inputs from vertex shader\nin vec3 v_normal;\nin vec2 v_texCoord;\nin vec4 v_position;\nin vec4 v_shadowCoord;\n\n// Some global uniforms\nuniform vec3 u_camPos;\nuniform float u_gamma;\nuniform bool u_flipTextureX;\nuniform bool u_flipTextureY;\n\n// Main lights and material uniforms\nuniform Material u_mat;\nuniform LightDir u_lightDirGlobal;\nuniform LightPos u_lightsPos[MAX_LIGHTS];\nuniform int u_lightsPosCount;\n// Reflection map isn't part of the material struct for complex reasons\nuniform samplerCube u_reflectionMap;\n// Shadows\nuniform highp sampler2DShadow u_shadowMap;\nuniform float u_shadowScatter;\n\n// Global texture coords shared between functions\nvec2 texCoord;\n\n// Output colour of this pixel/fragment\nout vec4 outColour;\n\n// ===== Helper functions =====================================================\n\n// Simple mixer\nvec4 mix4(vec4 a, vec4 b, float mix) {\n return a * (1.0 - mix) + b * mix;\n}\n\n// Function to help with get values from the shadow map\nfloat shadowMapSample(highp sampler2DShadow map, vec3 coord) {\n // As WebGL 2 does not support GL_CLAMP_TO_BORDER or GL_TEXTURE_BORDER_COLOR, we need to do this :(\n if (coord.x < 0.0 || coord.x > 1.0 || coord.y < 0.0 || coord.y > 1.0) {\n return 1.0;\n }\n\n return texture(map, coord);\n}\n\n// Shade a fragment using a directional light source\nvec4 shadeDirLight(LightDir light, Material mat, vec3 N, vec3 V) {\n vec3 L = normalize(-light.direction);\n vec3 H = normalize(L + V);\n\n vec3 diffuseCol = vec3(texture(mat.diffuseTex, texCoord)) * mat.diffuse;\n vec3 specularCol = vec3(texture(mat.specularTex, texCoord)) * mat.specular;\n\n float diff = dot(N, L);\n float spec = diff > 0.0 ? pow(max(dot(N, H), 0.0), mat.shininess) : 0.0;\n\n // Shadow map lookup\n vec3 projCoords = v_shadowCoord.xyz / v_shadowCoord.w * 0.5 + 0.5;\n float shadow = 0.0;\n\n // Carry out PCF for shadows using 4 samples of a poisson disk\n for (int i = 0; i < 4; i++) {\n vec3 offset = poissonDisk[i] * (u_shadowScatter / 100.0);\n shadow += shadowMapSample(u_shadowMap, projCoords + offset) * 0.25;\n }\n\n vec3 ambient = light.ambient * mat.ambient * diffuseCol;\n vec3 diffuse = light.colour * max(diff, 0.0) * diffuseCol * shadow;\n vec3 specular = light.colour * spec * specularCol * shadow;\n\n // Return a vec4 to support transparency, note specular is not affected by opacity\n return vec4(ambient + diffuse, mat.opacity / float(u_lightsPosCount + 1)) + vec4(specular, spec);\n}\n\n// Shade a fragment using a positional light source\nvec4 shadePosLight(LightPos light, Material mat, vec3 N, vec3 V) {\n vec3 L = normalize(light.position - v_position.xyz);\n vec3 H = normalize(L + V);\n\n vec3 diffuseCol = vec3(texture(mat.diffuseTex, texCoord)) * mat.diffuse;\n vec3 specularCol = vec3(texture(mat.specularTex, texCoord)) * mat.specular;\n\n float diff = dot(N, L);\n float spec = diff > 0.0 ? pow(max(dot(N, H), 0.0), mat.shininess) : 0.0;\n\n // Light attenuation, see: https://learnopengl.com/Lighting/Light-casters\n float dist = length(light.position - v_position.xyz);\n float attenuation = 1.0 / (light.constant + light.linear * dist + light.quad * (dist * dist));\n\n vec3 ambient = light.ambient * mat.ambient * diffuseCol * attenuation;\n vec3 diffuse = light.colour * max(diff, 0.0) * diffuseCol * attenuation;\n vec3 specular = light.colour * spec * specularCol * attenuation;\n\n // Return a vec4 to support transparency, note specular is not affected by opacity\n return vec4(ambient + diffuse, mat.opacity / float(u_lightsPosCount + 1)) + vec4(specular, spec);\n}\n\n// ===== Main shader ==========================================================\n\nvoid main() {\n vec3 V = normalize(u_camPos - v_position.xyz);\n\n // Flip texture coords if needed\n texCoord = u_flipTextureY ? vec2(v_texCoord.x, 1.0 - v_texCoord.y) : v_texCoord;\n texCoord = u_flipTextureX ? vec2(1.0 - texCoord.x, texCoord.y) : texCoord;\n\n vec3 N = normalize(v_normal);\n\n // Normal mapping, this is expensive so only do it if we have a normal map\n if (u_mat.hasNormalTex) {\n vec3 normMap = texture(u_mat.normalTex, texCoord).xyz * 2.0 - 1.0;\n\n vec3 Q1 = dFdx(v_position.xyz);\n vec3 Q2 = dFdy(v_position.xyz);\n vec2 st1 = dFdx(texCoord);\n vec2 st2 = dFdy(texCoord);\n\n vec3 T = -normalize(Q1 * st2.t - Q2 * st1.t);\n vec3 B = normalize(cross(N, T));\n mat3 TBN = mat3(T, B, N);\n\n N = normalize(TBN * normMap);\n }\n\n // Handle the main directional light, only one of these\n vec4 outColorPart = shadeDirLight(u_lightDirGlobal, u_mat, N, V);\n\n // Add positional lights\n for (int i = 0; i < u_lightsPosCount; i++) {\n outColorPart += shadePosLight(u_lightsPos[i], u_mat, N, V);\n }\n\n // Add emissive component\n float emissiveAlpha = u_mat.emissive.r + u_mat.emissive.g + u_mat.emissive.b > 0.0 ? 1.0 : 0.0;\n outColorPart += vec4(u_mat.emissive, emissiveAlpha);\n\n // Get reflection vector and sample reflection texture\n vec3 R = reflect(-V, N);\n vec4 reflectCol = vec4(texture(u_reflectionMap, R).rgb, 1.0);\n\n // Add reflection component, not sure if this is correct, looks ok\n outColorPart = mix4(outColorPart, reflectCol, u_mat.reflectivity);\n\n // Gamma correction, as GL_FRAMEBUFFER_SRGB is not supported on WebGL\n outColorPart.rgb = pow(outColorPart.rgb, vec3(1.0 / u_gamma));\n\n outColour = outColorPart;\n}\n","#version 300 es\n\n// ============================================================================\n// Phong vertex shader\n// Ben Coleman, 2023\n// ============================================================================\n\nprecision highp float;\n\n// Input attributes from buffers\nin vec4 position;\nin vec3 normal;\nin vec2 texcoord;\n\nuniform mat4 u_worldViewProjection;\nuniform mat4 u_worldInverseTranspose;\nuniform mat4 u_world;\nuniform mat4 u_shadowMatrix;\n\n// Output varying's to pass to fragment shader\nout vec2 v_texCoord;\nout vec3 v_normal;\nout vec4 v_position;\nout vec4 v_shadowCoord;\n\nvoid main() {\n v_texCoord = texcoord;\n v_normal = (u_worldInverseTranspose * vec4(normal, 0)).xyz;\n v_position = u_world * position;\n v_shadowCoord = u_shadowMatrix * v_position;\n\n gl_Position = u_worldViewProjection * position;\n}\n","#version 300 es\n\n// ============================================================================\n// Billboard fragment shader\n// Ben Coleman, 2023\n// ============================================================================\n\nprecision highp float;\n\nstruct Material {\n vec3 ambient;\n vec3 diffuse;\n vec3 specular;\n vec3 emissive;\n float shininess;\n float opacity;\n float reflectivity;\n sampler2D diffuseTex;\n sampler2D specularTex;\n sampler2D normalTex;\n bool hasNormalTex;\n};\n\n// From vertex shader\nin vec2 v_texCoord;\nin vec3 v_lighting;\n\n// Main lights and material uniforms\nuniform Material u_mat;\nuniform float u_gamma;\n\n// Output colour of this pixel/fragment\nout vec4 outColour;\n\nvoid main() {\n vec4 texel = texture(u_mat.diffuseTex, v_texCoord);\n\n // Magic to make transparent sprites work, without blending\n // Somehow this also works with the shadow map render pass, which is a bonus\n if (texel.a < 0.75) {\n discard;\n }\n\n vec3 colour = texel.rgb * u_mat.diffuse * v_lighting;\n\n // Gamma correction, as GL_FRAMEBUFFER_SRGB is not supported on WebGL\n colour = pow(colour, vec3(1.0 / u_gamma));\n\n outColour = vec4(colour, u_mat.opacity);\n}\n","#version 300 es\n\n// ============================================================================\n// Billboard vertex shader\n// Ben Coleman, 2023\n// ============================================================================\n\nprecision highp float;\n\nconst int MAX_LIGHTS = 16;\n\nstruct LightDir {\n vec3 direction;\n vec3 colour;\n vec3 ambient;\n};\n\nstruct LightPos {\n vec3 position;\n vec3 colour;\n vec3 ambient;\n float constant;\n float linear;\n float quad;\n bool enabled;\n};\n\n// Input attributes from buffers\nin vec4 position;\nin vec2 texcoord;\n\nuniform mat4 u_worldViewProjection;\nuniform mat4 u_world;\nuniform int u_lightsPosCount;\nuniform vec3 u_camPos;\nuniform LightDir u_lightDirGlobal;\nuniform LightPos u_lightsPos[MAX_LIGHTS];\n\n// Output varying's to pass to fragment shader\nout vec2 v_texCoord;\nout vec3 v_lighting;\n\n/*\n * Legacy lighting calc\n * Returns vec2(diffuse, specular)\n */\nvec2 lightCalc(vec3 N, vec3 L, vec3 H, float shininess) {\n float diff = dot(N, L);\n float spec = diff > 0.0 ? pow(max(dot(N, H), 0.0), shininess) : 0.0;\n return vec2(diff, spec);\n}\n\nvoid main() {\n v_texCoord = texcoord;\n gl_Position = u_worldViewProjection * position;\n vec3 worldPos = (u_world * position).xyz;\n\n // Normal for a billboard always points at camera\n vec3 worldNormal = normalize(u_camPos - worldPos);\n\n vec3 V = normalize(u_camPos - worldPos);\n vec3 N = normalize(worldNormal);\n float fudge = 1.5;\n\n // Add point lights to lighting output\n for (int i = 0; i < u_lightsPosCount; i++) {\n LightPos light = u_lightsPos[i];\n vec3 L = normalize(light.position - worldPos.xyz);\n\n float diffuse = max(dot(N, L), 0.0);\n\n // Distance attenuation\n float distance = length(light.position - worldPos.xyz);\n float attenuation = 1.0 / (light.constant + light.linear * distance + light.quad * (distance * distance));\n\n // Note small hack here to fudge the light intensity\n v_lighting += light.colour * fudge * attenuation * diffuse;\n }\n\n // Add in global directional light\n // Approximate by using a fixed direction for the normal pointing up\n vec3 globalLightL = normalize(-u_lightDirGlobal.direction);\n float globalDiffuse = dot(vec3(0.0, 1.0, 0.0), globalLightL);\n\n v_lighting += u_lightDirGlobal.colour * globalDiffuse;\n v_lighting += u_lightDirGlobal.ambient;\n}\n"],"mappings":"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AAM;AAAA;AAAA,IAGN;AAAA,IAAM;AAAA,IACN;AAAA,IAAM;AAAA,IACN;AAAA,IAAM;AAAA,IACN;AAAA,IAAM;AAAA,IACN;AAAA,IAAM;AAAA,IACN;AAAA,IAAM;AAAA;AAAA,IAGN;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA;AAAA,IAGH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA;AAAA,IAGH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA;AAAA,IAGH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA;AAAA,IAGH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA;AAAA,IAGH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA;AAAA,IAGH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA;AAAA,IAGH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA;AAAA,IAGH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,I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,KAAK,IAAI,EAAE,CAAC,KAAK,KAAK,IAAI,KAAK,EAAE,KAAc,UAAU,KAAK,IAAI,GAAK,KAAK,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,CAAC,KAAK,KAAK,IAAI,KAAK,EAAE,KAAc,UAAU,KAAK,IAAI,GAAK,KAAK,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,CAAC,KAAK,KAAK,IAAI,KAAK,EAAE,KAAc,UAAU,KAAK,IAAI,GAAK,KAAK,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,CAAC,KAAK,KAAK,IAAI,KAAK,EAAE,KAAc,UAAU,KAAK,IAAI,GAAK,KAAK,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,CAAC,KAAK,KAAK,IAAI,KAAK,EAAE,KAAc,UAAU,KAAK,IAAI,GAAK,KAAK,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,CAAC,KAAK,KAAK,IAAI,KAAK,EAAE,KAAc,UAAU,KAAK,IAAI,GAAK,KAAK,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,CAAC,KAAK,KAAK,IAAI,KAAK,EAAE,KAAc,UAAU,KAAK,IAAI,GAAK,KAAK,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,CAAC,KAAK,KAAK,IAAI,KAAK,EAAE,KAAc,UAAU,KAAK,IAAI,GAAK,KAAK,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,CAAC,KAAK,KAAK,IAAI,KAAK,EAAE,KAAc,UAAU,KAAK,IAAI,GAAK,KAAK,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,CAAC,KAAK,KAAK,IAAI,MAAM,GAAG,KAAc,UAAU,KAAK,IAAI,GAAK,KAAK,IAAI,GAAG,GAAG,KAAK,IAAI,GAAG,CAAC,KAAK,KAAK,IAAI,MAAM,GAAG,KAAc,UAAU,KAAK,IAAI,GAAK,KAAK,IAAI,GAAG,GAAG,KAAK,IAAI,GAAG,CAAC,KAAK,KAAK,IAAI,MAAM,GAAG,KAAc,UAAU,KAAK,IAAI,GAAK,KAAK,IAAI,GAAG,GAAG,KAAK,IAAI,GAAG,CAAC,KAAK,KAAK,IAAI,MAAM,GAAG,KAAc,UAAU,KAAK,IAAI,GAAK,KAAK,IAAI,GAAG,GAAG,KAAK,IAAI,GAAG,CAAC,KAAK,KAAK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","names":["noop","location","log","import_loglevel","log","length","length","length","len","lerp","angle","base","glEnumToString","isArrayBuffer","getShared2DContext","internalFormat","isArrayBuffer","isArrayBuffer","clearEventHandlers","onError","onLoad","cb","img","location","typeInfo","normalize","log","error","gl","program","token","node","program","location","program","errors","gl","programs","add","identity","identity","len","add","scale","add","clone","copy","create","equals","exactEquals","fromValues","inverse","length","mul","multiply","rotateX","rotateY","rotateZ","scale","set","str","sub","subtract","create","clone","length","fromValues","copy","set","add","subtract","multiply","scale","inverse","len","rotateX","rotateY","rotateZ","str","exactEquals","equals","sub","mul","import_loglevel","normalize","len","scale","distance","import_loglevel","log","import_loglevel","CameraType","camView","log","glsl_default","glsl_default","import_loglevel","glsl_default","glsl_default","glsl_default","log","angle","scale","rotate","translate","BillboardType","scale","import_loglevel","keywordRE","log","glsl_default","glsl_default","glsl_default","glsl_default","log","glsl_default"]} \ No newline at end of file +{"version":3,"sources":["../node_modules/loglevel/lib/loglevel.js","../src/core/gl.ts","../src/core/logging.ts","../src/core/context.ts","../package.json","../node_modules/twgl.js/dist/5.x/twgl-full.module.js","../node_modules/gl-matrix/esm/common.js","../node_modules/gl-matrix/esm/mat4.js","../node_modules/gl-matrix/esm/vec3.js","../src/engine/tuples.ts","../src/core/cache.ts","../src/engine/camera.ts","../shaders/shadowmap/glsl.frag","../shaders/shadowmap/glsl.vert","../src/engine/lights.ts","../src/engine/envmap.ts","../shaders/envmap/glsl.frag","../shaders/envmap/glsl.vert","../src/models/instance.ts","../src/core/stats.ts","../src/models/billboard.ts","../src/engine/material.ts","../src/models/primitive.ts","../src/models/model.ts","../src/parsers/mtl-parser.ts","../src/parsers/obj-parser.ts","../src/core/files.ts","../src/core/hud.ts","../shaders/phong/glsl.frag","../shaders/phong/glsl.vert","../shaders/billboard/glsl.frag","../shaders/billboard/glsl.vert"],"sourcesContent":["/*\n* loglevel - https://github.com/pimterry/loglevel\n*\n* Copyright (c) 2013 Tim Perry\n* Licensed under the MIT license.\n*/\n(function (root, definition) {\n \"use strict\";\n if (typeof define === 'function' && define.amd) {\n define(definition);\n } else if (typeof module === 'object' && module.exports) {\n module.exports = definition();\n } else {\n root.log = definition();\n }\n}(this, function () {\n \"use strict\";\n\n // Slightly dubious tricks to cut down minimized file size\n var noop = function() {};\n var undefinedType = \"undefined\";\n var isIE = (typeof window !== undefinedType) && (typeof window.navigator !== undefinedType) && (\n /Trident\\/|MSIE /.test(window.navigator.userAgent)\n );\n\n var logMethods = [\n \"trace\",\n \"debug\",\n \"info\",\n \"warn\",\n \"error\"\n ];\n\n // Cross-browser bind equivalent that works at least back to IE6\n function bindMethod(obj, methodName) {\n var method = obj[methodName];\n if (typeof method.bind === 'function') {\n return method.bind(obj);\n } else {\n try {\n return Function.prototype.bind.call(method, obj);\n } catch (e) {\n // Missing bind shim or IE8 + Modernizr, fallback to wrapping\n return function() {\n return Function.prototype.apply.apply(method, [obj, arguments]);\n };\n }\n }\n }\n\n // Trace() doesn't print the message in IE, so for that case we need to wrap it\n function traceForIE() {\n if (console.log) {\n if (console.log.apply) {\n console.log.apply(console, arguments);\n } else {\n // In old IE, native console methods themselves don't have apply().\n Function.prototype.apply.apply(console.log, [console, arguments]);\n }\n }\n if (console.trace) console.trace();\n }\n\n // Build the best logging method possible for this env\n // Wherever possible we want to bind, not wrap, to preserve stack traces\n function realMethod(methodName) {\n if (methodName === 'debug') {\n methodName = 'log';\n }\n\n if (typeof console === undefinedType) {\n return false; // No method possible, for now - fixed later by enableLoggingWhenConsoleArrives\n } else if (methodName === 'trace' && isIE) {\n return traceForIE;\n } else if (console[methodName] !== undefined) {\n return bindMethod(console, methodName);\n } else if (console.log !== undefined) {\n return bindMethod(console, 'log');\n } else {\n return noop;\n }\n }\n\n // These private functions always need `this` to be set properly\n\n function replaceLoggingMethods(level, loggerName) {\n /*jshint validthis:true */\n for (var i = 0; i < logMethods.length; i++) {\n var methodName = logMethods[i];\n this[methodName] = (i < level) ?\n noop :\n this.methodFactory(methodName, level, loggerName);\n }\n\n // Define log.log as an alias for log.debug\n this.log = this.debug;\n }\n\n // In old IE versions, the console isn't present until you first open it.\n // We build realMethod() replacements here that regenerate logging methods\n function enableLoggingWhenConsoleArrives(methodName, level, loggerName) {\n return function () {\n if (typeof console !== undefinedType) {\n replaceLoggingMethods.call(this, level, loggerName);\n this[methodName].apply(this, arguments);\n }\n };\n }\n\n // By default, we use closely bound real methods wherever possible, and\n // otherwise we wait for a console to appear, and then try again.\n function defaultMethodFactory(methodName, level, loggerName) {\n /*jshint validthis:true */\n return realMethod(methodName) ||\n enableLoggingWhenConsoleArrives.apply(this, arguments);\n }\n\n function Logger(name, defaultLevel, factory) {\n var self = this;\n var currentLevel;\n defaultLevel = defaultLevel == null ? \"WARN\" : defaultLevel;\n\n var storageKey = \"loglevel\";\n if (typeof name === \"string\") {\n storageKey += \":\" + name;\n } else if (typeof name === \"symbol\") {\n storageKey = undefined;\n }\n\n function persistLevelIfPossible(levelNum) {\n var levelName = (logMethods[levelNum] || 'silent').toUpperCase();\n\n if (typeof window === undefinedType || !storageKey) return;\n\n // Use localStorage if available\n try {\n window.localStorage[storageKey] = levelName;\n return;\n } catch (ignore) {}\n\n // Use session cookie as fallback\n try {\n window.document.cookie =\n encodeURIComponent(storageKey) + \"=\" + levelName + \";\";\n } catch (ignore) {}\n }\n\n function getPersistedLevel() {\n var storedLevel;\n\n if (typeof window === undefinedType || !storageKey) return;\n\n try {\n storedLevel = window.localStorage[storageKey];\n } catch (ignore) {}\n\n // Fallback to cookies if local storage gives us nothing\n if (typeof storedLevel === undefinedType) {\n try {\n var cookie = window.document.cookie;\n var location = cookie.indexOf(\n encodeURIComponent(storageKey) + \"=\");\n if (location !== -1) {\n storedLevel = /^([^;]+)/.exec(cookie.slice(location))[1];\n }\n } catch (ignore) {}\n }\n\n // If the stored level is not valid, treat it as if nothing was stored.\n if (self.levels[storedLevel] === undefined) {\n storedLevel = undefined;\n }\n\n return storedLevel;\n }\n\n function clearPersistedLevel() {\n if (typeof window === undefinedType || !storageKey) return;\n\n // Use localStorage if available\n try {\n window.localStorage.removeItem(storageKey);\n return;\n } catch (ignore) {}\n\n // Use session cookie as fallback\n try {\n window.document.cookie =\n encodeURIComponent(storageKey) + \"=; expires=Thu, 01 Jan 1970 00:00:00 UTC\";\n } catch (ignore) {}\n }\n\n /*\n *\n * Public logger API - see https://github.com/pimterry/loglevel for details\n *\n */\n\n self.name = name;\n\n self.levels = { \"TRACE\": 0, \"DEBUG\": 1, \"INFO\": 2, \"WARN\": 3,\n \"ERROR\": 4, \"SILENT\": 5};\n\n self.methodFactory = factory || defaultMethodFactory;\n\n self.getLevel = function () {\n return currentLevel;\n };\n\n self.setLevel = function (level, persist) {\n if (typeof level === \"string\" && self.levels[level.toUpperCase()] !== undefined) {\n level = self.levels[level.toUpperCase()];\n }\n if (typeof level === \"number\" && level >= 0 && level <= self.levels.SILENT) {\n currentLevel = level;\n if (persist !== false) { // defaults to true\n persistLevelIfPossible(level);\n }\n replaceLoggingMethods.call(self, level, name);\n if (typeof console === undefinedType && level < self.levels.SILENT) {\n return \"No console available for logging\";\n }\n } else {\n throw \"log.setLevel() called with invalid level: \" + level;\n }\n };\n\n self.setDefaultLevel = function (level) {\n defaultLevel = level;\n if (!getPersistedLevel()) {\n self.setLevel(level, false);\n }\n };\n\n self.resetLevel = function () {\n self.setLevel(defaultLevel, false);\n clearPersistedLevel();\n };\n\n self.enableAll = function(persist) {\n self.setLevel(self.levels.TRACE, persist);\n };\n\n self.disableAll = function(persist) {\n self.setLevel(self.levels.SILENT, persist);\n };\n\n // Initialize with the right level\n var initialLevel = getPersistedLevel();\n if (initialLevel == null) {\n initialLevel = defaultLevel;\n }\n self.setLevel(initialLevel, false);\n }\n\n /*\n *\n * Top-level API\n *\n */\n\n var defaultLogger = new Logger();\n\n var _loggersByName = {};\n defaultLogger.getLogger = function getLogger(name) {\n if ((typeof name !== \"symbol\" && typeof name !== \"string\") || name === \"\") {\n throw new TypeError(\"You must supply a name when creating a logger.\");\n }\n\n var logger = _loggersByName[name];\n if (!logger) {\n logger = _loggersByName[name] = new Logger(\n name, defaultLogger.getLevel(), defaultLogger.methodFactory);\n }\n return logger;\n };\n\n // Grab the current global log variable in case of overwrite\n var _log = (typeof window !== undefinedType) ? window.log : undefined;\n defaultLogger.noConflict = function() {\n if (typeof window !== undefinedType &&\n window.log === defaultLogger) {\n window.log = _log;\n }\n\n return defaultLogger;\n };\n\n defaultLogger.getLoggers = function getLoggers() {\n return _loggersByName;\n };\n\n // ES6 default export, for compatibility\n defaultLogger['default'] = defaultLogger;\n\n return defaultLogger;\n}));\n","// ===== gl.ts ==========================================================\n// Interactions with the GL context, as a global singleton\n// Ben Coleman, 2023\n// ======================================================================\n\nimport { mat4 } from 'gl-matrix'\nimport log from 'loglevel'\n\n/** A map of uniforms that can be used when WebGL rendering, typically applied with twlg.setUniforms() */\nexport type UniformSet = { [key: string]: number | number[] | mat4 | WebGLTexture | null }\n\n// Memoized global WebGL2 context\nlet glContext: WebGL2RenderingContext | undefined\n\n/**\n * Get the WebGL2 context, if it doesn't exist create it\n *\n * @returns {WebGL2RenderingContext} - Global WebGL2 context\n * @param {boolean} aa - Enable antialiasing\n * @param {string} selector - CSS selector for locating the canvas element\n */\nexport function getGl(aa = true, selector = 'canvas') {\n if (glContext) {\n return glContext\n }\n\n log.info(`🖌️ Creating new WebGL2 context for: '${selector}'`)\n\n const canvasElement = document.querySelector(selector) as HTMLElement\n if (!canvasElement) {\n log.error(`💥 FATAL! Unable to find element with selector: '${selector}'`)\n return undefined\n }\n\n if (canvasElement && canvasElement.tagName !== 'CANVAS') {\n log.error(`💥 FATAL! Element with selector: '${selector}' is not a canvas element`)\n return undefined\n }\n\n const canvas = canvasElement as HTMLCanvasElement\n if (!canvas) {\n log.error(`💥 FATAL! Unable to find canvas element with selector: '${selector}'`)\n return undefined\n }\n\n glContext = canvas.getContext('webgl2', { antialias: aa }) ?? undefined\n\n if (!glContext) {\n log.error(`💥 Unable to create WebGL2 context, maybe it's not supported on this device`)\n return undefined\n }\n\n log.info(`📐 Internal: ${canvas.width} x ${canvas.height}, display: ${canvas.clientWidth} x ${canvas.clientHeight}`)\n\n return glContext\n}\n","// ===== logging.ts ===========================================================\n// Just a wrapper around loglevel\n// Ben Coleman, 2023\n// ============================================================================\n\nimport log from 'loglevel'\n\n/**\n * Wrapper around loglevel, so we can globally change the logging level\n * @param level - The log level to set, one of 'trace', 'debug', 'info', 'warn', 'error', 'silent'\n */\nexport function setLogLevel(level: log.LogLevelNames) {\n log.setLevel(level)\n}\n","// ===== context.ts ===========================================================\n// Main rendering context, this is the core of the library\n// Ben Coleman, 2023\n// ============================================================================\n\nimport log from 'loglevel'\nimport { version } from '../../package.json'\nimport { bindFramebufferInfo, createProgramInfo, ProgramInfo, resizeCanvasToDisplaySize } from 'twgl.js'\nimport { mat4, vec3 } from 'gl-matrix'\n\nimport { getGl, UniformSet } from './gl.ts'\nimport { RGB, XYZ, Tuples } from '../engine/tuples.ts'\nimport { ModelCache, ProgramCache, TextureCache } from './cache.ts'\nimport { LightDirectional, LightPoint } from '../engine/lights.ts'\nimport { Camera, CameraType } from '../engine/camera.ts'\nimport { Material } from '../engine/material.ts'\nimport { DynamicEnvironmentMap, EnvironmentMap } from '../engine/envmap.ts'\nimport { Instance } from '../models/instance.ts'\nimport { Billboard, BillboardType } from '../models/billboard.ts'\nimport { PrimitiveCube, PrimitivePlane, PrimitiveSphere, PrimitiveCylinder } from '../models/primitive.ts'\nimport { Model } from '../models/model.ts'\nimport { HUD } from './hud.ts'\nimport { Stats } from './stats.ts'\n\n// Import shaders, tsup will inline these as text strings\nimport fragShaderPhong from '../../shaders/phong/glsl.frag'\nimport vertShaderPhong from '../../shaders/phong/glsl.vert'\nimport fragShaderBill from '../../shaders/billboard/glsl.frag'\nimport vertShaderBill from '../../shaders/billboard/glsl.vert'\n\n/** @ignore Total max dynamic lights */\nconst MAX_LIGHTS = 16\n\n/**\n * The main rendering context. This is the effectively main entry point for the library.\n * Typically you will create a single instance of this class using init() and use it to render your scene.\n */\nexport class Context {\n private gl: WebGL2RenderingContext\n private started: boolean\n private instances: Instance[] = []\n private instancesTrans: Instance[] = []\n private cameras: Map = new Map()\n private activeCameraName: string\n private envmap?: EnvironmentMap\n private dynamicEnvMap?: DynamicEnvironmentMap\n\n /** Global directional light */\n public globalLight: LightDirectional\n\n /** All the dynamic point lights in the scene */\n public lights: LightPoint[] = []\n\n /** Main camera for this context */\n private _camera: Camera\n\n /** Show extra debug details on the canvas */\n public debug: boolean\n\n /**\n * The pre-render update function, called every frame.\n * Hook in your custom logic and processing here\n */\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n public update: (delta: number) => void = () => {}\n\n /** A HUD you can use to render HTML elements over the canvas */\n public readonly hud: HUD\n\n /** Gamma correction value, default 1.0 */\n public gamma = 1.0\n\n // ==== Getters =============================================================\n\n /** Get the active camera */\n get camera() {\n return this._camera\n }\n\n /** Get the name of the active camera */\n get cameraName() {\n return this.activeCameraName\n }\n\n /** Constructor is private, use init() to create a new context */\n private constructor(gl: WebGL2RenderingContext) {\n this.gl = gl\n this.started = false\n this.debug = false\n\n // Main global light\n this.globalLight = new LightDirectional()\n this.globalLight.setAsPosition(20, 50, 30)\n\n const defaultCamera = new Camera(CameraType.PERSPECTIVE)\n this.cameras.set('default', defaultCamera)\n this._camera = defaultCamera\n this.activeCameraName = 'default'\n\n this.hud = new HUD(gl.canvas)\n\n log.info(`👑 GSOTS-3D context created, v${version}`)\n }\n\n /**\n * Create & initialize a new Context which will render into provided canvas selector. This is where you start when using the library.\n * @param canvasSelector CSS selector for canvas element, default is 'canvas'\n * @param antiAlias Enable anti-aliasing in GL, default is true\n */\n static async init(canvasSelector = 'canvas', antiAlias = true) {\n const gl = getGl(antiAlias, canvasSelector)\n\n if (!gl) {\n log.error('💥 Failed to create WebGL context, this is extremely bad news')\n throw new Error('Failed to get WebGL context')\n }\n\n // Create the context around the WebGL2 context\n const ctx = new Context(gl)\n\n const canvas = gl.canvas\n ctx.camera.aspectRatio = canvas.clientWidth / canvas.clientHeight\n\n // Load shaders and put into global cache\n const phongProgInfo = createProgramInfo(gl, [vertShaderPhong, fragShaderPhong])\n ProgramCache.init(phongProgInfo)\n ProgramCache.instance.add(ProgramCache.PROG_PHONG, phongProgInfo)\n ProgramCache.instance.add(ProgramCache.PROG_BILLBOARD, createProgramInfo(gl, [vertShaderBill, fragShaderBill]))\n log.info(`🎨 Loaded all shaders & programs, GL is ready`)\n\n gl.enable(gl.DEPTH_TEST)\n gl.enable(gl.BLEND)\n gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)\n\n // Bind to the render function\n ctx.render = ctx.render.bind(ctx)\n\n // Global texture cache, needs to be initialized after GL context is ready\n TextureCache.init(gl)\n\n return ctx\n }\n\n /**\n * Main render loop, called every frame\n * @param now Current time in milliseconds\n */\n private async render(now: number) {\n if (!this.gl) return\n\n Stats.updateTime(now * 0.001)\n\n // Call the external update function\n this.update(Stats.deltaTime)\n\n // RENDERING - Render into the dynamic environment map(s) if any\n if (this.dynamicEnvMap) {\n // This is a rare case of passing the context to the object, but it's needed for the dynamic env map\n this.dynamicEnvMap.update(this.gl, this)\n }\n\n // RENDERING - Render the shadow map from the global light\n if (this.globalLight.shadowsEnabled) {\n const shadowCam = this.globalLight.getShadowCamera()\n // Switch to front face culling for shadow map, yeah it's weird but it works!\n this.gl.cullFace(this.gl.FRONT)\n\n // Bind the shadow map framebuffer and render the scene from the light's POV\n // Using the special shadow map program as an override for the whole rendering pass\n bindFramebufferInfo(this.gl, this.globalLight.shadowMapFrameBufffer)\n if (shadowCam) this.renderWithCamera(shadowCam, this.globalLight.shadowMapProgram)\n\n // Switch back to back face culling\n this.gl.cullFace(this.gl.BACK)\n }\n\n // RENDERING - Render the scene from active camera into the main framebuffer\n bindFramebufferInfo(this.gl, null)\n this.renderWithCamera(this.camera)\n\n this.hud.render(this.debug, this.camera)\n\n // Loop forever or stop if not started\n if (this.started) requestAnimationFrame(this.render)\n\n // Reset stats for next frame\n Stats.resetPerFrame()\n }\n\n /**\n * Render the scene from the given camera, used internally\n * @param camera\n */\n renderWithCamera(camera: Camera, programOverride?: ProgramInfo) {\n if (!this.gl) return\n\n // Clear the framebuffer and depth buffer\n this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT)\n\n // Update the camera\n camera.update()\n\n // Do this in every frame since camera can move\n const camMatrix = camera.matrix\n\n // Work out what reflection map to use, if any\n // NOTE: This *not* part of the material because it's too hard to dynamically change\n let reflectMap: WebGLTexture | null = this.envmap?.texture ?? null\n\n // As there is only one dynamic reflection envmap, we can use it across all instances\n // But ONLY set this when the camera is NOT rendering into it!\n if (this.dynamicEnvMap) {\n if (!camera.usedForEnvMap) {\n reflectMap = this.dynamicEnvMap.texture\n }\n }\n\n // The uniforms that are the same for all instances\n const uniforms = {\n u_gamma: this.gamma,\n\n u_worldInverseTranspose: mat4.create(), // Updated per instance\n u_worldViewProjection: mat4.create(), // Updated per instance\n u_view: mat4.invert(mat4.create(), camMatrix),\n u_proj: camera.projectionMatrix,\n u_camPos: camera.position,\n\n u_reflectionMap: reflectMap,\n\n u_shadowMap: this.globalLight.shadowMapTexture,\n u_shadowMatrix: this.globalLight.shadowMatrix ?? mat4.create(),\n u_shadowScatter: this.globalLight.shadowMapOptions?.scatter ?? 0.2,\n } as UniformSet\n\n // RENDERING - Draw envmap around the scene first\n if (this.envmap) {\n this.envmap.render(uniforms.u_view, uniforms.u_proj, camera)\n }\n\n // RENDERING - Process lighting\n\n // Apply global light to the two programs\n uniforms.u_lightDirGlobal = this.globalLight.uniforms\n\n // Only sort lights if we have more than MAX_LIGHTS, it's expensive!\n if (this.lights.length > MAX_LIGHTS) {\n // Sort lights by distance to camera so we can use the closest ones\n this.lights.sort((lightA, lightB) => {\n const ad = vec3.distance(lightA.position, this.camera.position)\n const bd = vec3.distance(lightB.position, this.camera.position)\n return ad - bd\n })\n }\n\n // Add the point lights into u_lightsPos array up to MAX_LIGHTS\n let lightCount = 0\n for (const light of this.lights) {\n if (lightCount >= MAX_LIGHTS) break\n if (!light.enabled) continue\n\n uniforms[`u_lightsPos[${lightCount++}]`] = light.uniforms\n }\n\n uniforms.u_lightsPosCount = lightCount\n\n // RENDERING - Draw all opaque instances\n this.gl.enable(this.gl.CULL_FACE)\n for (const instance of this.instances) {\n instance.render(this.gl, uniforms, programOverride)\n }\n\n // RENDERING - Draw all transparent instances\n this.gl.disable(this.gl.CULL_FACE)\n\n // Sort transparent instances by distance to camera\n // Maybe remove this in scenes with lots of transparent instances?\n this.instancesTrans.sort((a, b) => {\n const ad = Tuples.distance(a.position ?? [0, 0, 0], this.camera.position)\n const bd = Tuples.distance(b.position ?? [0, 0, 0], this.camera.position)\n return bd - ad\n })\n\n for (const instance of this.instancesTrans) {\n instance.render(this.gl, uniforms, programOverride)\n }\n }\n\n /**\n * Start the rendering loop\n */\n start() {\n this.hud.hideLoading()\n this.started = true\n // Restart the render loop\n requestAnimationFrame(this.render)\n }\n\n /**\n * Stop the rendering loop\n */\n stop() {\n this.started = false\n }\n\n /**\n * Resize the canvas to match the size of the element it's in\n * @param viewportOnly - Only resize the viewport, not the canvas\n */\n resize(viewportOnly = false) {\n const canvas = this.gl.canvas\n\n if (!viewportOnly) resizeCanvasToDisplaySize(canvas)\n\n this.gl.viewport(0, 0, canvas.width, canvas.height)\n this.camera.aspectRatio = canvas.width / canvas.height\n\n log.info(\n `📐 RESIZE Internal: ${canvas.width} x ${canvas.height}, display: ${canvas.clientWidth} x ${canvas.clientHeight}`\n )\n }\n\n /**\n * Internal function to add an instance to the scene\n */\n private addInstance(instance: Instance, material: Material) {\n if (material.opacity !== undefined && material.opacity < 1) {\n this.instancesTrans.push(instance)\n } else {\n this.instances.push(instance)\n }\n }\n\n /**\n * Model loader, loads an OBJ model from a file via URL or path and adds it to the cache\n * This is preferred over calling Model.parse() directly\n * @param path Base path to the model file, e.g. './models/'\n * @param fileName Name of the model file, e.g 'teapot.obj'\n * @param filterTextures Apply texture filtering as materials are loaded\n * @param flipTextureY Flip the Y coordinate of the texture\n */\n public async loadModel(path: string, fileName: string, filterTextures = true, flipY = false) {\n const modelName = fileName.split('.')[0]\n\n // Check if model is already loaded\n if (ModelCache.instance.get(modelName, false)) {\n log.warn(`⚠️ Model '${modelName}' already loaded, skipping`)\n return\n }\n\n // Load the model and always flip the UV\n const model = await Model.parse(path, fileName, filterTextures, flipY, true)\n\n ModelCache.instance.add(model)\n }\n\n /**\n * Add a new camera to the scene\n * @param name Name of the camera\n * @param camera Camera instance\n */\n public addCamera(name: string, camera: Camera) {\n this.cameras.set(name, camera)\n }\n\n public getCamera(name: string) {\n return this.cameras.get(name)\n }\n\n /**\n * Set the active camera\n * @param name Name of the camera to set as active\n */\n public setActiveCamera(name: string) {\n const camera = this.cameras.get(name)\n if (!camera) {\n throw new Error(`💥 Unable to set active camera to '${name}', camera not found`)\n }\n\n this.camera.active = false\n this._camera = camera\n this.camera.active = true\n this.activeCameraName = name\n }\n\n // ==========================================================================\n // Methods to create new instances of renderable objects & things\n // ==========================================================================\n\n /**\n * Create a new model instance, which should have been previously loaded into the cache\n * @param modelName - Name of the model previously loaded into the cache, don't include the file extension\n */\n createModelInstance(modelName: string) {\n const model = ModelCache.instance.get(modelName)\n if (!model) {\n throw new Error(`💥 Unable to create model instance for ${modelName}`)\n }\n\n const instance = new Instance(model)\n this.instances.push(instance)\n Stats.triangles += model.triangleCount\n Stats.instances++\n\n return instance\n }\n\n /**\n * Create an instance of a primitive sphere\n * @param material - Material to apply to the sphere\n * @param radius - Radius of the sphere\n * @param subdivisionsH - Number of subdivisions along the horizontal\n * @param subdivisionsV - Number of subdivisions along the vertical\n */\n createSphereInstance(material: Material, radius = 5, subdivisionsH = 16, subdivisionsV = 8) {\n const sphere = new PrimitiveSphere(this.gl, radius, subdivisionsH, subdivisionsV)\n sphere.material = material\n\n const instance = new Instance(sphere)\n this.addInstance(instance, material)\n Stats.triangles += sphere.triangleCount\n Stats.instances++\n\n log.debug(`🟢 Created sphere instance, r:${radius}`)\n\n return instance\n }\n\n /**\n * Create an instance of a primitive plane\n * @param material - Material to apply to the plane\n * @param width - Width of the plane\n * @param height - Height of the plane\n * @param subdivisionsW - Number of subdivisions along the width\n * @param subdivisionsH - Number of subdivisions along the height\n * @param tiling - Number of times to tile the texture over the plane\n */\n createPlaneInstance(material: Material, width = 5, height = 5, subdivisionsW = 1, subdivisionsH = 1, tiling = 1) {\n const plane = new PrimitivePlane(this.gl, width, height, subdivisionsW, subdivisionsH, tiling)\n plane.material = material\n\n const instance = new Instance(plane)\n this.addInstance(instance, material)\n Stats.triangles += plane.triangleCount\n Stats.instances++\n\n log.debug(`🟨 Created plane instance, w:${width} h:${height}`)\n\n return instance\n }\n\n /**\n * Create an instance of a primitive cube\n */\n createCubeInstance(material: Material, size = 5) {\n const cube = new PrimitiveCube(this.gl, size)\n cube.material = material\n\n const instance = new Instance(cube)\n this.addInstance(instance, material)\n Stats.triangles += cube.triangleCount\n Stats.instances++\n\n log.debug(`📦 Created cube instance, size:${size}`)\n\n return instance\n }\n\n /**\n * Create an instance of a primitive cylinder\n */\n createCylinderInstance(material: Material, r = 2, h = 5, subdivisionsR = 16, subdivisionsH = 1, caps = true) {\n const cyl = new PrimitiveCylinder(this.gl, r, h, subdivisionsR, subdivisionsH, caps)\n cyl.material = material\n\n const instance = new Instance(cyl)\n this.addInstance(instance, material)\n Stats.triangles += cyl.triangleCount\n Stats.instances++\n\n log.debug(`🛢️ Created cylinder instance, r:${r}`)\n\n return instance\n }\n\n /**\n * Create an instance of a billboard/sprite in the scene\n * @param textureUrl - Path to the texture image file to use for the billboard\n * @param width - Width of the billboard (default: 5)\n * @param height - Height of the billboard (default: 5)\n * @param type - Type of billboard to create (default: CYLINDRICAL)\n */\n createBillboardInstance(material: Material, size = 5, type = BillboardType.CYLINDRICAL) {\n const billboard = new Billboard(this.gl, type, material, size)\n\n const instance = new Instance(billboard)\n\n this.addInstance(instance, material)\n\n Stats.triangles += 2\n Stats.instances++\n\n log.debug(`🚧 Created billboard instance of type: ${type} size: ${size}`)\n\n return instance\n }\n\n /**\n * Create a new point light in the scene\n * @param position - Position of the light\n * @param colour - Colour of the light, defaults to white\n * @param intensity - Intensity of the light\n * @returns The new light object\n */\n createPointLight(position: XYZ, colour: RGB = [1, 1, 1], intensity = 1) {\n const light = new LightPoint(position, colour)\n light.position = position\n light.colour = colour\n\n // A very simple scaling of the light attenuation\n // Users can still set the attenuation manually if they want\n light.constant /= intensity\n light.linear /= intensity\n light.quad /= intensity\n\n this.lights.push(light)\n\n log.debug(`🔆 Created point light, pos:${position} col:${colour} int:${intensity}`)\n\n return light\n }\n\n /**\n * Set the EnvironmentMap for the scene, will overwrite any existing envmap.\n * This will enable static reflections and create a 'skybox' around the scene\n * @param textureURLs - Array of 6 texture URLs to use for the map, in the order: +X, -X, +Y, -Y, +Z, -Z\n */\n setEnvmap(renderAsBackground = false, ...textureURLs: string[]) {\n this.envmap = new EnvironmentMap(this.gl, textureURLs)\n this.envmap.renderAsBackground = renderAsBackground\n }\n\n /**\n * Remove any current EnvironmentMap from the scene\n */\n removeEnvmap() {\n this.envmap = undefined\n }\n\n /**\n * Get the current EnvironmentMap for the scene\n */\n getEnvmap() {\n return this.envmap\n }\n\n /**\n * Set and create a dynamic environment map which will enable dynamic/realtime reflections\n * @param position - Position to render reflections from\n * @param size - Size of the map to render, note higher sizes will come with a big performance hit\n */\n setDynamicEnvmap(position: XYZ, size = 128, renderDistance = 500) {\n this.dynamicEnvMap = new DynamicEnvironmentMap(this.gl, size, position, renderDistance)\n }\n}\n","{\n \"name\": \"@benc-uk/gsots3d\",\n \"version\": \"0.0.4-alpha.2\",\n \"description\": \"Getting S**t On The Screen in 3D. A library for doing 3D graphics in the browser.\",\n \"author\": \"Ben Coleman\",\n \"license\": \"MIT\",\n \"homepage\": \"https://code.benco.io/gsots3d/docs\",\n \"type\": \"module\",\n \"publishConfig\": {\n \"@benc-uk:registry\": \"https://npm.pkg.github.com\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/benc-uk/gsots3d.git\"\n },\n \"exports\": {\n \".\": \"./dist/index.js\",\n \"./parsers\": \"./dist/parsers/index.js\"\n },\n \"browser\": {\n \".\": \"./dist-bundle/gsots3d.js\"\n },\n \"files\": [\n \"dist/\",\n \"readme.md\"\n ],\n \"keywords\": [\n \"webgl\",\n \"graphics\",\n \"3d\",\n \"twgl\",\n \"typescript\"\n ],\n \"scripts\": {\n \"lint\": \"eslint --ext .ts src && prettier --check src && prettier --check shaders\",\n \"lint-fix\": \"eslint --ext .ts src --fix && prettier --write src && prettier --write shaders\",\n \"check\": \"tsc\",\n \"build\": \"tsc && tsup\",\n \"watch\": \"tsc && npm run build && run-when-changed --watch 'src/**' --watch 'shaders/**' --exec 'npm run build'\",\n \"build-bundle\": \"tsc && tsup --config tsup.config-bundle.js\",\n \"watch-bundle\": \"tsc && npm run build-bundle && run-when-changed --watch 'src/**' --watch 'shaders/**' --exec 'npm run build-bundle'\",\n \"clean\": \"rm -rf dist\",\n \"docs\": \"typedoc --out docs --gitRevision main ./src/\",\n \"examples\": \"vite --port 3000 ./examples/\"\n },\n \"devDependencies\": {\n \"@typescript-eslint/eslint-plugin\": \"^6.2.1\",\n \"@typescript-eslint/parser\": \"^6.2.1\",\n \"esbuild-plugin-glsl\": \"^1.2.1\",\n \"eslint\": \"^8.46.0\",\n \"prettier\": \"^2.8.8\",\n \"prettier-plugin-glsl\": \"^0.0.10\",\n \"run-when-changed\": \"^2.1.0\",\n \"tsup\": \"^7.2.0\",\n \"typedoc\": \"^0.24.8\",\n \"typescript\": \"^5.1.6\",\n \"vite\": \"^4.4.8\"\n },\n \"dependencies\": {\n \"gl-matrix\": \"^3.4.3\",\n \"loglevel\": \"^1.8.1\",\n \"twgl.js\": \"^5.5.1\"\n }\n}\n","/* @license twgl.js 5.5.1 Copyright (c) 2015, Gregg Tavares All Rights Reserved.\nAvailable via the MIT license.\nsee: http://github.com/greggman/twgl.js for details */\n/*\n * Copyright 2019 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\n/**\n *\n * Vec3 math math functions.\n *\n * Almost all functions take an optional `dst` argument. If it is not passed in the\n * functions will create a new Vec3. In other words you can do this\n *\n * var v = v3.cross(v1, v2); // Creates a new Vec3 with the cross product of v1 x v2.\n *\n * or\n *\n * var v = v3.create();\n * v3.cross(v1, v2, v); // Puts the cross product of v1 x v2 in v\n *\n * The first style is often easier but depending on where it's used it generates garbage where\n * as there is almost never allocation with the second style.\n *\n * It is always save to pass any vector as the destination. So for example\n *\n * v3.cross(v1, v2, v1); // Puts the cross product of v1 x v2 in v1\n *\n * @module twgl/v3\n */\n\nlet VecType = Float32Array;\n\n/**\n * A JavaScript array with 3 values or a Float32Array with 3 values.\n * When created by the library will create the default type which is `Float32Array`\n * but can be set by calling {@link module:twgl/v3.setDefaultType}.\n * @typedef {(number[]|Float32Array)} Vec3\n * @memberOf module:twgl/v3\n */\n\n/**\n * Sets the type this library creates for a Vec3\n * @param {constructor} ctor the constructor for the type. Either `Float32Array` or `Array`\n * @return {constructor} previous constructor for Vec3\n * @memberOf module:twgl/v3\n */\nfunction setDefaultType$1(ctor) {\n const oldType = VecType;\n VecType = ctor;\n return oldType;\n}\n\n/**\n * Creates a vec3; may be called with x, y, z to set initial values.\n * @param {number} [x] Initial x value.\n * @param {number} [y] Initial y value.\n * @param {number} [z] Initial z value.\n * @return {module:twgl/v3.Vec3} the created vector\n * @memberOf module:twgl/v3\n */\nfunction create$1(x, y, z) {\n const dst = new VecType(3);\n if (x) {\n dst[0] = x;\n }\n if (y) {\n dst[1] = y;\n }\n if (z) {\n dst[2] = z;\n }\n return dst;\n}\n\n/**\n * Adds two vectors; assumes a and b have the same dimension.\n * @param {module:twgl/v3.Vec3} a Operand vector.\n * @param {module:twgl/v3.Vec3} b Operand vector.\n * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created.\n * @return {module:twgl/v3.Vec3} A vector tha tis the sum of a and b.\n * @memberOf module:twgl/v3\n */\nfunction add(a, b, dst) {\n dst = dst || new VecType(3);\n\n dst[0] = a[0] + b[0];\n dst[1] = a[1] + b[1];\n dst[2] = a[2] + b[2];\n\n return dst;\n}\n\n/**\n * Subtracts two vectors.\n * @param {module:twgl/v3.Vec3} a Operand vector.\n * @param {module:twgl/v3.Vec3} b Operand vector.\n * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created.\n * @return {module:twgl/v3.Vec3} A vector that is the difference of a and b.\n * @memberOf module:twgl/v3\n */\nfunction subtract(a, b, dst) {\n dst = dst || new VecType(3);\n\n dst[0] = a[0] - b[0];\n dst[1] = a[1] - b[1];\n dst[2] = a[2] - b[2];\n\n return dst;\n}\n\n/**\n * Performs linear interpolation on two vectors.\n * Given vectors a and b and interpolation coefficient t, returns\n * a + t * (b - a).\n * @param {module:twgl/v3.Vec3} a Operand vector.\n * @param {module:twgl/v3.Vec3} b Operand vector.\n * @param {number} t Interpolation coefficient.\n * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created.\n * @return {module:twgl/v3.Vec3} The linear interpolated result.\n * @memberOf module:twgl/v3\n */\nfunction lerp(a, b, t, dst) {\n dst = dst || new VecType(3);\n\n dst[0] = a[0] + t * (b[0] - a[0]);\n dst[1] = a[1] + t * (b[1] - a[1]);\n dst[2] = a[2] + t * (b[2] - a[2]);\n\n return dst;\n}\n\n/**\n * Performs linear interpolation on two vectors.\n * Given vectors a and b and interpolation coefficient vector t, returns\n * a + t * (b - a).\n * @param {module:twgl/v3.Vec3} a Operand vector.\n * @param {module:twgl/v3.Vec3} b Operand vector.\n * @param {module:twgl/v3.Vec3} t Interpolation coefficients vector.\n * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created.\n * @return {module:twgl/v3.Vec3} the linear interpolated result.\n * @memberOf module:twgl/v3\n */\nfunction lerpV(a, b, t, dst) {\n dst = dst || new VecType(3);\n\n dst[0] = a[0] + t[0] * (b[0] - a[0]);\n dst[1] = a[1] + t[1] * (b[1] - a[1]);\n dst[2] = a[2] + t[2] * (b[2] - a[2]);\n\n return dst;\n}\n\n/**\n * Return max values of two vectors.\n * Given vectors a and b returns\n * [max(a[0], b[0]), max(a[1], b[1]), max(a[2], b[2])].\n * @param {module:twgl/v3.Vec3} a Operand vector.\n * @param {module:twgl/v3.Vec3} b Operand vector.\n * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created.\n * @return {module:twgl/v3.Vec3} The max components vector.\n * @memberOf module:twgl/v3\n */\nfunction max(a, b, dst) {\n dst = dst || new VecType(3);\n\n dst[0] = Math.max(a[0], b[0]);\n dst[1] = Math.max(a[1], b[1]);\n dst[2] = Math.max(a[2], b[2]);\n\n return dst;\n}\n\n/**\n * Return min values of two vectors.\n * Given vectors a and b returns\n * [min(a[0], b[0]), min(a[1], b[1]), min(a[2], b[2])].\n * @param {module:twgl/v3.Vec3} a Operand vector.\n * @param {module:twgl/v3.Vec3} b Operand vector.\n * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created.\n * @return {module:twgl/v3.Vec3} The min components vector.\n * @memberOf module:twgl/v3\n */\nfunction min(a, b, dst) {\n dst = dst || new VecType(3);\n\n dst[0] = Math.min(a[0], b[0]);\n dst[1] = Math.min(a[1], b[1]);\n dst[2] = Math.min(a[2], b[2]);\n\n return dst;\n}\n\n/**\n * Multiplies a vector by a scalar.\n * @param {module:twgl/v3.Vec3} v The vector.\n * @param {number} k The scalar.\n * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created.\n * @return {module:twgl/v3.Vec3} The scaled vector.\n * @memberOf module:twgl/v3\n */\nfunction mulScalar(v, k, dst) {\n dst = dst || new VecType(3);\n\n dst[0] = v[0] * k;\n dst[1] = v[1] * k;\n dst[2] = v[2] * k;\n\n return dst;\n}\n\n/**\n * Divides a vector by a scalar.\n * @param {module:twgl/v3.Vec3} v The vector.\n * @param {number} k The scalar.\n * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created.\n * @return {module:twgl/v3.Vec3} The scaled vector.\n * @memberOf module:twgl/v3\n */\nfunction divScalar(v, k, dst) {\n dst = dst || new VecType(3);\n\n dst[0] = v[0] / k;\n dst[1] = v[1] / k;\n dst[2] = v[2] / k;\n\n return dst;\n}\n\n/**\n * Computes the cross product of two vectors; assumes both vectors have\n * three entries.\n * @param {module:twgl/v3.Vec3} a Operand vector.\n * @param {module:twgl/v3.Vec3} b Operand vector.\n * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created.\n * @return {module:twgl/v3.Vec3} The vector of a cross b.\n * @memberOf module:twgl/v3\n */\nfunction cross(a, b, dst) {\n dst = dst || new VecType(3);\n\n const t1 = a[2] * b[0] - a[0] * b[2];\n const t2 = a[0] * b[1] - a[1] * b[0];\n dst[0] = a[1] * b[2] - a[2] * b[1];\n dst[1] = t1;\n dst[2] = t2;\n\n return dst;\n}\n\n/**\n * Computes the dot product of two vectors; assumes both vectors have\n * three entries.\n * @param {module:twgl/v3.Vec3} a Operand vector.\n * @param {module:twgl/v3.Vec3} b Operand vector.\n * @return {number} dot product\n * @memberOf module:twgl/v3\n */\nfunction dot(a, b) {\n return (a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]);\n}\n\n/**\n * Computes the length of vector\n * @param {module:twgl/v3.Vec3} v vector.\n * @return {number} length of vector.\n * @memberOf module:twgl/v3\n */\nfunction length$1(v) {\n return Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);\n}\n\n/**\n * Computes the square of the length of vector\n * @param {module:twgl/v3.Vec3} v vector.\n * @return {number} square of the length of vector.\n * @memberOf module:twgl/v3\n */\nfunction lengthSq(v) {\n return v[0] * v[0] + v[1] * v[1] + v[2] * v[2];\n}\n\n/**\n * Computes the distance between 2 points\n * @param {module:twgl/v3.Vec3} a vector.\n * @param {module:twgl/v3.Vec3} b vector.\n * @return {number} distance between a and b\n * @memberOf module:twgl/v3\n */\nfunction distance(a, b) {\n const dx = a[0] - b[0];\n const dy = a[1] - b[1];\n const dz = a[2] - b[2];\n return Math.sqrt(dx * dx + dy * dy + dz * dz);\n}\n\n/**\n * Computes the square of the distance between 2 points\n * @param {module:twgl/v3.Vec3} a vector.\n * @param {module:twgl/v3.Vec3} b vector.\n * @return {number} square of the distance between a and b\n * @memberOf module:twgl/v3\n */\nfunction distanceSq(a, b) {\n const dx = a[0] - b[0];\n const dy = a[1] - b[1];\n const dz = a[2] - b[2];\n return dx * dx + dy * dy + dz * dz;\n}\n\n/**\n * Divides a vector by its Euclidean length and returns the quotient.\n * @param {module:twgl/v3.Vec3} a The vector.\n * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created.\n * @return {module:twgl/v3.Vec3} The normalized vector.\n * @memberOf module:twgl/v3\n */\nfunction normalize(a, dst) {\n dst = dst || new VecType(3);\n\n const lenSq = a[0] * a[0] + a[1] * a[1] + a[2] * a[2];\n const len = Math.sqrt(lenSq);\n if (len > 0.00001) {\n dst[0] = a[0] / len;\n dst[1] = a[1] / len;\n dst[2] = a[2] / len;\n } else {\n dst[0] = 0;\n dst[1] = 0;\n dst[2] = 0;\n }\n\n return dst;\n}\n\n/**\n * Negates a vector.\n * @param {module:twgl/v3.Vec3} v The vector.\n * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created.\n * @return {module:twgl/v3.Vec3} -v.\n * @memberOf module:twgl/v3\n */\nfunction negate$1(v, dst) {\n dst = dst || new VecType(3);\n\n dst[0] = -v[0];\n dst[1] = -v[1];\n dst[2] = -v[2];\n\n return dst;\n}\n\n/**\n * Copies a vector.\n * @param {module:twgl/v3.Vec3} v The vector.\n * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created.\n * @return {module:twgl/v3.Vec3} A copy of v.\n * @memberOf module:twgl/v3\n */\nfunction copy$1(v, dst) {\n dst = dst || new VecType(3);\n\n dst[0] = v[0];\n dst[1] = v[1];\n dst[2] = v[2];\n\n return dst;\n}\n\n/**\n * Multiplies a vector by another vector (component-wise); assumes a and\n * b have the same length.\n * @param {module:twgl/v3.Vec3} a Operand vector.\n * @param {module:twgl/v3.Vec3} b Operand vector.\n * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created.\n * @return {module:twgl/v3.Vec3} The vector of products of entries of a and\n * b.\n * @memberOf module:twgl/v3\n */\nfunction multiply$1(a, b, dst) {\n dst = dst || new VecType(3);\n\n dst[0] = a[0] * b[0];\n dst[1] = a[1] * b[1];\n dst[2] = a[2] * b[2];\n\n return dst;\n}\n\n/**\n * Divides a vector by another vector (component-wise); assumes a and\n * b have the same length.\n * @param {module:twgl/v3.Vec3} a Operand vector.\n * @param {module:twgl/v3.Vec3} b Operand vector.\n * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not new one is created.\n * @return {module:twgl/v3.Vec3} The vector of quotients of entries of a and\n * b.\n * @memberOf module:twgl/v3\n */\nfunction divide(a, b, dst) {\n dst = dst || new VecType(3);\n\n dst[0] = a[0] / b[0];\n dst[1] = a[1] / b[1];\n dst[2] = a[2] / b[2];\n\n return dst;\n}\n\nvar v3 = /*#__PURE__*/Object.freeze({\n __proto__: null,\n add: add,\n copy: copy$1,\n create: create$1,\n cross: cross,\n distance: distance,\n distanceSq: distanceSq,\n divide: divide,\n divScalar: divScalar,\n dot: dot,\n lerp: lerp,\n lerpV: lerpV,\n length: length$1,\n lengthSq: lengthSq,\n max: max,\n min: min,\n mulScalar: mulScalar,\n multiply: multiply$1,\n negate: negate$1,\n normalize: normalize,\n setDefaultType: setDefaultType$1,\n subtract: subtract\n});\n\n/*\n * Copyright 2019 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\n/**\n * 4x4 Matrix math math functions.\n *\n * Almost all functions take an optional `dst` argument. If it is not passed in the\n * functions will create a new matrix. In other words you can do this\n *\n * const mat = m4.translation([1, 2, 3]); // Creates a new translation matrix\n *\n * or\n *\n * const mat = m4.create();\n * m4.translation([1, 2, 3], mat); // Puts translation matrix in mat.\n *\n * The first style is often easier but depending on where it's used it generates garbage where\n * as there is almost never allocation with the second style.\n *\n * It is always save to pass any matrix as the destination. So for example\n *\n * const mat = m4.identity();\n * const trans = m4.translation([1, 2, 3]);\n * m4.multiply(mat, trans, mat); // Multiplies mat * trans and puts result in mat.\n *\n * @module twgl/m4\n */\nlet MatType = Float32Array;\n\n/**\n * A JavaScript array with 16 values or a Float32Array with 16 values.\n * When created by the library will create the default type which is `Float32Array`\n * but can be set by calling {@link module:twgl/m4.setDefaultType}.\n * @typedef {(number[]|Float32Array)} Mat4\n * @memberOf module:twgl/m4\n */\n\n/**\n * Sets the type this library creates for a Mat4\n * @param {constructor} ctor the constructor for the type. Either `Float32Array` or `Array`\n * @return {constructor} previous constructor for Mat4\n * @memberOf module:twgl/m4\n */\nfunction setDefaultType(ctor) {\n const oldType = MatType;\n MatType = ctor;\n return oldType;\n}\n\n/**\n * Negates a matrix.\n * @param {module:twgl/m4.Mat4} m The matrix.\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} -m.\n * @memberOf module:twgl/m4\n */\nfunction negate(m, dst) {\n dst = dst || new MatType(16);\n\n dst[ 0] = -m[ 0];\n dst[ 1] = -m[ 1];\n dst[ 2] = -m[ 2];\n dst[ 3] = -m[ 3];\n dst[ 4] = -m[ 4];\n dst[ 5] = -m[ 5];\n dst[ 6] = -m[ 6];\n dst[ 7] = -m[ 7];\n dst[ 8] = -m[ 8];\n dst[ 9] = -m[ 9];\n dst[10] = -m[10];\n dst[11] = -m[11];\n dst[12] = -m[12];\n dst[13] = -m[13];\n dst[14] = -m[14];\n dst[15] = -m[15];\n\n return dst;\n}\n\n/**\n * Creates a matrix.\n * @return {module:twgl/m4.Mat4} A new matrix.\n * @memberOf module:twgl/m4\n */\nfunction create() {\n return new MatType(16).fill(0);\n}\n\n/**\n * Copies a matrix.\n * @param {module:twgl/m4.Mat4} m The matrix.\n * @param {module:twgl/m4.Mat4} [dst] The matrix. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} A copy of m.\n * @memberOf module:twgl/m4\n */\nfunction copy(m, dst) {\n dst = dst || new MatType(16);\n\n dst[ 0] = m[ 0];\n dst[ 1] = m[ 1];\n dst[ 2] = m[ 2];\n dst[ 3] = m[ 3];\n dst[ 4] = m[ 4];\n dst[ 5] = m[ 5];\n dst[ 6] = m[ 6];\n dst[ 7] = m[ 7];\n dst[ 8] = m[ 8];\n dst[ 9] = m[ 9];\n dst[10] = m[10];\n dst[11] = m[11];\n dst[12] = m[12];\n dst[13] = m[13];\n dst[14] = m[14];\n dst[15] = m[15];\n\n return dst;\n}\n\n/**\n * Creates an n-by-n identity matrix.\n *\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} An n-by-n identity matrix.\n * @memberOf module:twgl/m4\n */\nfunction identity(dst) {\n dst = dst || new MatType(16);\n\n dst[ 0] = 1;\n dst[ 1] = 0;\n dst[ 2] = 0;\n dst[ 3] = 0;\n dst[ 4] = 0;\n dst[ 5] = 1;\n dst[ 6] = 0;\n dst[ 7] = 0;\n dst[ 8] = 0;\n dst[ 9] = 0;\n dst[10] = 1;\n dst[11] = 0;\n dst[12] = 0;\n dst[13] = 0;\n dst[14] = 0;\n dst[15] = 1;\n\n return dst;\n}\n\n/**\n * Takes the transpose of a matrix.\n * @param {module:twgl/m4.Mat4} m The matrix.\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The transpose of m.\n * @memberOf module:twgl/m4\n */\n function transpose(m, dst) {\n dst = dst || new MatType(16);\n if (dst === m) {\n let t;\n\n t = m[1];\n m[1] = m[4];\n m[4] = t;\n\n t = m[2];\n m[2] = m[8];\n m[8] = t;\n\n t = m[3];\n m[3] = m[12];\n m[12] = t;\n\n t = m[6];\n m[6] = m[9];\n m[9] = t;\n\n t = m[7];\n m[7] = m[13];\n m[13] = t;\n\n t = m[11];\n m[11] = m[14];\n m[14] = t;\n return dst;\n }\n\n const m00 = m[0 * 4 + 0];\n const m01 = m[0 * 4 + 1];\n const m02 = m[0 * 4 + 2];\n const m03 = m[0 * 4 + 3];\n const m10 = m[1 * 4 + 0];\n const m11 = m[1 * 4 + 1];\n const m12 = m[1 * 4 + 2];\n const m13 = m[1 * 4 + 3];\n const m20 = m[2 * 4 + 0];\n const m21 = m[2 * 4 + 1];\n const m22 = m[2 * 4 + 2];\n const m23 = m[2 * 4 + 3];\n const m30 = m[3 * 4 + 0];\n const m31 = m[3 * 4 + 1];\n const m32 = m[3 * 4 + 2];\n const m33 = m[3 * 4 + 3];\n\n dst[ 0] = m00;\n dst[ 1] = m10;\n dst[ 2] = m20;\n dst[ 3] = m30;\n dst[ 4] = m01;\n dst[ 5] = m11;\n dst[ 6] = m21;\n dst[ 7] = m31;\n dst[ 8] = m02;\n dst[ 9] = m12;\n dst[10] = m22;\n dst[11] = m32;\n dst[12] = m03;\n dst[13] = m13;\n dst[14] = m23;\n dst[15] = m33;\n\n return dst;\n}\n\n/**\n * Computes the inverse of a 4-by-4 matrix.\n * @param {module:twgl/m4.Mat4} m The matrix.\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The inverse of m.\n * @memberOf module:twgl/m4\n */\nfunction inverse(m, dst) {\n dst = dst || new MatType(16);\n\n const m00 = m[0 * 4 + 0];\n const m01 = m[0 * 4 + 1];\n const m02 = m[0 * 4 + 2];\n const m03 = m[0 * 4 + 3];\n const m10 = m[1 * 4 + 0];\n const m11 = m[1 * 4 + 1];\n const m12 = m[1 * 4 + 2];\n const m13 = m[1 * 4 + 3];\n const m20 = m[2 * 4 + 0];\n const m21 = m[2 * 4 + 1];\n const m22 = m[2 * 4 + 2];\n const m23 = m[2 * 4 + 3];\n const m30 = m[3 * 4 + 0];\n const m31 = m[3 * 4 + 1];\n const m32 = m[3 * 4 + 2];\n const m33 = m[3 * 4 + 3];\n const tmp_0 = m22 * m33;\n const tmp_1 = m32 * m23;\n const tmp_2 = m12 * m33;\n const tmp_3 = m32 * m13;\n const tmp_4 = m12 * m23;\n const tmp_5 = m22 * m13;\n const tmp_6 = m02 * m33;\n const tmp_7 = m32 * m03;\n const tmp_8 = m02 * m23;\n const tmp_9 = m22 * m03;\n const tmp_10 = m02 * m13;\n const tmp_11 = m12 * m03;\n const tmp_12 = m20 * m31;\n const tmp_13 = m30 * m21;\n const tmp_14 = m10 * m31;\n const tmp_15 = m30 * m11;\n const tmp_16 = m10 * m21;\n const tmp_17 = m20 * m11;\n const tmp_18 = m00 * m31;\n const tmp_19 = m30 * m01;\n const tmp_20 = m00 * m21;\n const tmp_21 = m20 * m01;\n const tmp_22 = m00 * m11;\n const tmp_23 = m10 * m01;\n\n const t0 = (tmp_0 * m11 + tmp_3 * m21 + tmp_4 * m31) -\n (tmp_1 * m11 + tmp_2 * m21 + tmp_5 * m31);\n const t1 = (tmp_1 * m01 + tmp_6 * m21 + tmp_9 * m31) -\n (tmp_0 * m01 + tmp_7 * m21 + tmp_8 * m31);\n const t2 = (tmp_2 * m01 + tmp_7 * m11 + tmp_10 * m31) -\n (tmp_3 * m01 + tmp_6 * m11 + tmp_11 * m31);\n const t3 = (tmp_5 * m01 + tmp_8 * m11 + tmp_11 * m21) -\n (tmp_4 * m01 + tmp_9 * m11 + tmp_10 * m21);\n\n const d = 1.0 / (m00 * t0 + m10 * t1 + m20 * t2 + m30 * t3);\n\n dst[ 0] = d * t0;\n dst[ 1] = d * t1;\n dst[ 2] = d * t2;\n dst[ 3] = d * t3;\n dst[ 4] = d * ((tmp_1 * m10 + tmp_2 * m20 + tmp_5 * m30) -\n (tmp_0 * m10 + tmp_3 * m20 + tmp_4 * m30));\n dst[ 5] = d * ((tmp_0 * m00 + tmp_7 * m20 + tmp_8 * m30) -\n (tmp_1 * m00 + tmp_6 * m20 + tmp_9 * m30));\n dst[ 6] = d * ((tmp_3 * m00 + tmp_6 * m10 + tmp_11 * m30) -\n (tmp_2 * m00 + tmp_7 * m10 + tmp_10 * m30));\n dst[ 7] = d * ((tmp_4 * m00 + tmp_9 * m10 + tmp_10 * m20) -\n (tmp_5 * m00 + tmp_8 * m10 + tmp_11 * m20));\n dst[ 8] = d * ((tmp_12 * m13 + tmp_15 * m23 + tmp_16 * m33) -\n (tmp_13 * m13 + tmp_14 * m23 + tmp_17 * m33));\n dst[ 9] = d * ((tmp_13 * m03 + tmp_18 * m23 + tmp_21 * m33) -\n (tmp_12 * m03 + tmp_19 * m23 + tmp_20 * m33));\n dst[10] = d * ((tmp_14 * m03 + tmp_19 * m13 + tmp_22 * m33) -\n (tmp_15 * m03 + tmp_18 * m13 + tmp_23 * m33));\n dst[11] = d * ((tmp_17 * m03 + tmp_20 * m13 + tmp_23 * m23) -\n (tmp_16 * m03 + tmp_21 * m13 + tmp_22 * m23));\n dst[12] = d * ((tmp_14 * m22 + tmp_17 * m32 + tmp_13 * m12) -\n (tmp_16 * m32 + tmp_12 * m12 + tmp_15 * m22));\n dst[13] = d * ((tmp_20 * m32 + tmp_12 * m02 + tmp_19 * m22) -\n (tmp_18 * m22 + tmp_21 * m32 + tmp_13 * m02));\n dst[14] = d * ((tmp_18 * m12 + tmp_23 * m32 + tmp_15 * m02) -\n (tmp_22 * m32 + tmp_14 * m02 + tmp_19 * m12));\n dst[15] = d * ((tmp_22 * m22 + tmp_16 * m02 + tmp_21 * m12) -\n (tmp_20 * m12 + tmp_23 * m22 + tmp_17 * m02));\n\n return dst;\n}\n\n/**\n * Multiplies two 4-by-4 matrices with a on the left and b on the right\n * @param {module:twgl/m4.Mat4} a The matrix on the left.\n * @param {module:twgl/m4.Mat4} b The matrix on the right.\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The matrix product of a and b.\n * @memberOf module:twgl/m4\n */\nfunction multiply(a, b, dst) {\n dst = dst || new MatType(16);\n\n const a00 = a[0];\n const a01 = a[1];\n const a02 = a[2];\n const a03 = a[3];\n const a10 = a[ 4 + 0];\n const a11 = a[ 4 + 1];\n const a12 = a[ 4 + 2];\n const a13 = a[ 4 + 3];\n const a20 = a[ 8 + 0];\n const a21 = a[ 8 + 1];\n const a22 = a[ 8 + 2];\n const a23 = a[ 8 + 3];\n const a30 = a[12 + 0];\n const a31 = a[12 + 1];\n const a32 = a[12 + 2];\n const a33 = a[12 + 3];\n const b00 = b[0];\n const b01 = b[1];\n const b02 = b[2];\n const b03 = b[3];\n const b10 = b[ 4 + 0];\n const b11 = b[ 4 + 1];\n const b12 = b[ 4 + 2];\n const b13 = b[ 4 + 3];\n const b20 = b[ 8 + 0];\n const b21 = b[ 8 + 1];\n const b22 = b[ 8 + 2];\n const b23 = b[ 8 + 3];\n const b30 = b[12 + 0];\n const b31 = b[12 + 1];\n const b32 = b[12 + 2];\n const b33 = b[12 + 3];\n\n dst[ 0] = a00 * b00 + a10 * b01 + a20 * b02 + a30 * b03;\n dst[ 1] = a01 * b00 + a11 * b01 + a21 * b02 + a31 * b03;\n dst[ 2] = a02 * b00 + a12 * b01 + a22 * b02 + a32 * b03;\n dst[ 3] = a03 * b00 + a13 * b01 + a23 * b02 + a33 * b03;\n dst[ 4] = a00 * b10 + a10 * b11 + a20 * b12 + a30 * b13;\n dst[ 5] = a01 * b10 + a11 * b11 + a21 * b12 + a31 * b13;\n dst[ 6] = a02 * b10 + a12 * b11 + a22 * b12 + a32 * b13;\n dst[ 7] = a03 * b10 + a13 * b11 + a23 * b12 + a33 * b13;\n dst[ 8] = a00 * b20 + a10 * b21 + a20 * b22 + a30 * b23;\n dst[ 9] = a01 * b20 + a11 * b21 + a21 * b22 + a31 * b23;\n dst[10] = a02 * b20 + a12 * b21 + a22 * b22 + a32 * b23;\n dst[11] = a03 * b20 + a13 * b21 + a23 * b22 + a33 * b23;\n dst[12] = a00 * b30 + a10 * b31 + a20 * b32 + a30 * b33;\n dst[13] = a01 * b30 + a11 * b31 + a21 * b32 + a31 * b33;\n dst[14] = a02 * b30 + a12 * b31 + a22 * b32 + a32 * b33;\n dst[15] = a03 * b30 + a13 * b31 + a23 * b32 + a33 * b33;\n\n return dst;\n}\n\n/**\n * Sets the translation component of a 4-by-4 matrix to the given\n * vector.\n * @param {module:twgl/m4.Mat4} a The matrix.\n * @param {module:twgl/v3.Vec3} v The vector.\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The matrix with translation set.\n * @memberOf module:twgl/m4\n */\nfunction setTranslation(a, v, dst) {\n dst = dst || identity();\n if (a !== dst) {\n dst[ 0] = a[ 0];\n dst[ 1] = a[ 1];\n dst[ 2] = a[ 2];\n dst[ 3] = a[ 3];\n dst[ 4] = a[ 4];\n dst[ 5] = a[ 5];\n dst[ 6] = a[ 6];\n dst[ 7] = a[ 7];\n dst[ 8] = a[ 8];\n dst[ 9] = a[ 9];\n dst[10] = a[10];\n dst[11] = a[11];\n }\n dst[12] = v[0];\n dst[13] = v[1];\n dst[14] = v[2];\n dst[15] = 1;\n return dst;\n}\n\n/**\n * Returns the translation component of a 4-by-4 matrix as a vector with 3\n * entries.\n * @param {module:twgl/m4.Mat4} m The matrix.\n * @param {module:twgl/v3.Vec3} [dst] vector to hold result. If not passed a new one is created.\n * @return {module:twgl/v3.Vec3} The translation component of m.\n * @memberOf module:twgl/m4\n */\nfunction getTranslation(m, dst) {\n dst = dst || create$1();\n dst[0] = m[12];\n dst[1] = m[13];\n dst[2] = m[14];\n return dst;\n}\n\n/**\n * Returns an axis of a 4x4 matrix as a vector with 3 entries\n * @param {module:twgl/m4.Mat4} m The matrix.\n * @param {number} axis The axis 0 = x, 1 = y, 2 = z;\n * @return {module:twgl/v3.Vec3} [dst] vector.\n * @return {module:twgl/v3.Vec3} The axis component of m.\n * @memberOf module:twgl/m4\n */\nfunction getAxis(m, axis, dst) {\n dst = dst || create$1();\n const off = axis * 4;\n dst[0] = m[off + 0];\n dst[1] = m[off + 1];\n dst[2] = m[off + 2];\n return dst;\n}\n\n/**\n * Sets an axis of a 4x4 matrix as a vector with 3 entries\n * @param {module:twgl/m4.Mat4} m The matrix.\n * @param {module:twgl/v3.Vec3} v the axis vector\n * @param {number} axis The axis 0 = x, 1 = y, 2 = z;\n * @param {module:twgl/m4.Mat4} [dst] The matrix to set. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The matrix with axis set.\n * @memberOf module:twgl/m4\n */\nfunction setAxis(a, v, axis, dst) {\n if (dst !== a) {\n dst = copy(a, dst);\n }\n const off = axis * 4;\n dst[off + 0] = v[0];\n dst[off + 1] = v[1];\n dst[off + 2] = v[2];\n return dst;\n}\n\n/**\n * Computes a 4-by-4 perspective transformation matrix given the angular height\n * of the frustum, the aspect ratio, and the near and far clipping planes. The\n * arguments define a frustum extending in the negative z direction. The given\n * angle is the vertical angle of the frustum, and the horizontal angle is\n * determined to produce the given aspect ratio. The arguments near and far are\n * the distances to the near and far clipping planes. Note that near and far\n * are not z coordinates, but rather they are distances along the negative\n * z-axis. The matrix generated sends the viewing frustum to the unit box.\n * We assume a unit box extending from -1 to 1 in the x and y dimensions and\n * from 0 to 1 in the z dimension.\n * @param {number} fieldOfViewYInRadians The camera angle from top to bottom (in radians).\n * @param {number} aspect The aspect ratio width / height.\n * @param {number} zNear The depth (negative z coordinate)\n * of the near clipping plane.\n * @param {number} zFar The depth (negative z coordinate)\n * of the far clipping plane.\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The perspective matrix.\n * @memberOf module:twgl/m4\n */\nfunction perspective(fieldOfViewYInRadians, aspect, zNear, zFar, dst) {\n dst = dst || new MatType(16);\n\n const f = Math.tan(Math.PI * 0.5 - 0.5 * fieldOfViewYInRadians);\n const rangeInv = 1.0 / (zNear - zFar);\n\n dst[0] = f / aspect;\n dst[1] = 0;\n dst[2] = 0;\n dst[3] = 0;\n\n dst[4] = 0;\n dst[5] = f;\n dst[6] = 0;\n dst[7] = 0;\n\n dst[8] = 0;\n dst[9] = 0;\n dst[10] = (zNear + zFar) * rangeInv;\n dst[11] = -1;\n\n dst[12] = 0;\n dst[13] = 0;\n dst[14] = zNear * zFar * rangeInv * 2;\n dst[15] = 0;\n\n return dst;\n}\n\n/**\n * Computes a 4-by-4 orthogonal transformation matrix given the left, right,\n * bottom, and top dimensions of the near clipping plane as well as the\n * near and far clipping plane distances.\n * @param {number} left Left side of the near clipping plane viewport.\n * @param {number} right Right side of the near clipping plane viewport.\n * @param {number} bottom Bottom of the near clipping plane viewport.\n * @param {number} top Top of the near clipping plane viewport.\n * @param {number} near The depth (negative z coordinate)\n * of the near clipping plane.\n * @param {number} far The depth (negative z coordinate)\n * of the far clipping plane.\n * @param {module:twgl/m4.Mat4} [dst] Output matrix. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The perspective matrix.\n * @memberOf module:twgl/m4\n */\nfunction ortho(left, right, bottom, top, near, far, dst) {\n dst = dst || new MatType(16);\n\n dst[0] = 2 / (right - left);\n dst[1] = 0;\n dst[2] = 0;\n dst[3] = 0;\n\n dst[4] = 0;\n dst[5] = 2 / (top - bottom);\n dst[6] = 0;\n dst[7] = 0;\n\n dst[8] = 0;\n dst[9] = 0;\n dst[10] = 2 / (near - far);\n dst[11] = 0;\n\n dst[12] = (right + left) / (left - right);\n dst[13] = (top + bottom) / (bottom - top);\n dst[14] = (far + near) / (near - far);\n dst[15] = 1;\n\n return dst;\n}\n\n/**\n * Computes a 4-by-4 perspective transformation matrix given the left, right,\n * top, bottom, near and far clipping planes. The arguments define a frustum\n * extending in the negative z direction. The arguments near and far are the\n * distances to the near and far clipping planes. Note that near and far are not\n * z coordinates, but rather they are distances along the negative z-axis. The\n * matrix generated sends the viewing frustum to the unit box. We assume a unit\n * box extending from -1 to 1 in the x and y dimensions and from 0 to 1 in the z\n * dimension.\n * @param {number} left The x coordinate of the left plane of the box.\n * @param {number} right The x coordinate of the right plane of the box.\n * @param {number} bottom The y coordinate of the bottom plane of the box.\n * @param {number} top The y coordinate of the right plane of the box.\n * @param {number} near The negative z coordinate of the near plane of the box.\n * @param {number} far The negative z coordinate of the far plane of the box.\n * @param {module:twgl/m4.Mat4} [dst] Output matrix. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The perspective projection matrix.\n * @memberOf module:twgl/m4\n */\nfunction frustum(left, right, bottom, top, near, far, dst) {\n dst = dst || new MatType(16);\n\n const dx = (right - left);\n const dy = (top - bottom);\n const dz = (near - far);\n\n dst[ 0] = 2 * near / dx;\n dst[ 1] = 0;\n dst[ 2] = 0;\n dst[ 3] = 0;\n dst[ 4] = 0;\n dst[ 5] = 2 * near / dy;\n dst[ 6] = 0;\n dst[ 7] = 0;\n dst[ 8] = (left + right) / dx;\n dst[ 9] = (top + bottom) / dy;\n dst[10] = far / dz;\n dst[11] = -1;\n dst[12] = 0;\n dst[13] = 0;\n dst[14] = near * far / dz;\n dst[15] = 0;\n\n return dst;\n}\n\nlet xAxis;\nlet yAxis;\nlet zAxis;\n\n/**\n * Computes a 4-by-4 look-at transformation.\n *\n * This is a matrix which positions the camera itself. If you want\n * a view matrix (a matrix which moves things in front of the camera)\n * take the inverse of this.\n *\n * @param {module:twgl/v3.Vec3} eye The position of the eye.\n * @param {module:twgl/v3.Vec3} target The position meant to be viewed.\n * @param {module:twgl/v3.Vec3} up A vector pointing up.\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The look-at matrix.\n * @memberOf module:twgl/m4\n */\nfunction lookAt(eye, target, up, dst) {\n dst = dst || new MatType(16);\n\n xAxis = xAxis || create$1();\n yAxis = yAxis || create$1();\n zAxis = zAxis || create$1();\n\n normalize(\n subtract(eye, target, zAxis), zAxis);\n normalize(cross(up, zAxis, xAxis), xAxis);\n normalize(cross(zAxis, xAxis, yAxis), yAxis);\n\n dst[ 0] = xAxis[0];\n dst[ 1] = xAxis[1];\n dst[ 2] = xAxis[2];\n dst[ 3] = 0;\n dst[ 4] = yAxis[0];\n dst[ 5] = yAxis[1];\n dst[ 6] = yAxis[2];\n dst[ 7] = 0;\n dst[ 8] = zAxis[0];\n dst[ 9] = zAxis[1];\n dst[10] = zAxis[2];\n dst[11] = 0;\n dst[12] = eye[0];\n dst[13] = eye[1];\n dst[14] = eye[2];\n dst[15] = 1;\n\n return dst;\n}\n\n/**\n * Creates a 4-by-4 matrix which translates by the given vector v.\n * @param {module:twgl/v3.Vec3} v The vector by\n * which to translate.\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The translation matrix.\n * @memberOf module:twgl/m4\n */\nfunction translation(v, dst) {\n dst = dst || new MatType(16);\n\n dst[ 0] = 1;\n dst[ 1] = 0;\n dst[ 2] = 0;\n dst[ 3] = 0;\n dst[ 4] = 0;\n dst[ 5] = 1;\n dst[ 6] = 0;\n dst[ 7] = 0;\n dst[ 8] = 0;\n dst[ 9] = 0;\n dst[10] = 1;\n dst[11] = 0;\n dst[12] = v[0];\n dst[13] = v[1];\n dst[14] = v[2];\n dst[15] = 1;\n return dst;\n}\n\n/**\n * Translates the given 4-by-4 matrix by the given vector v.\n * @param {module:twgl/m4.Mat4} m The matrix.\n * @param {module:twgl/v3.Vec3} v The vector by\n * which to translate.\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The translated matrix.\n * @memberOf module:twgl/m4\n */\nfunction translate(m, v, dst) {\n dst = dst || new MatType(16);\n\n const v0 = v[0];\n const v1 = v[1];\n const v2 = v[2];\n const m00 = m[0];\n const m01 = m[1];\n const m02 = m[2];\n const m03 = m[3];\n const m10 = m[1 * 4 + 0];\n const m11 = m[1 * 4 + 1];\n const m12 = m[1 * 4 + 2];\n const m13 = m[1 * 4 + 3];\n const m20 = m[2 * 4 + 0];\n const m21 = m[2 * 4 + 1];\n const m22 = m[2 * 4 + 2];\n const m23 = m[2 * 4 + 3];\n const m30 = m[3 * 4 + 0];\n const m31 = m[3 * 4 + 1];\n const m32 = m[3 * 4 + 2];\n const m33 = m[3 * 4 + 3];\n\n if (m !== dst) {\n dst[ 0] = m00;\n dst[ 1] = m01;\n dst[ 2] = m02;\n dst[ 3] = m03;\n dst[ 4] = m10;\n dst[ 5] = m11;\n dst[ 6] = m12;\n dst[ 7] = m13;\n dst[ 8] = m20;\n dst[ 9] = m21;\n dst[10] = m22;\n dst[11] = m23;\n }\n\n dst[12] = m00 * v0 + m10 * v1 + m20 * v2 + m30;\n dst[13] = m01 * v0 + m11 * v1 + m21 * v2 + m31;\n dst[14] = m02 * v0 + m12 * v1 + m22 * v2 + m32;\n dst[15] = m03 * v0 + m13 * v1 + m23 * v2 + m33;\n\n return dst;\n}\n\n/**\n * Creates a 4-by-4 matrix which rotates around the x-axis by the given angle.\n * @param {number} angleInRadians The angle by which to rotate (in radians).\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The rotation matrix.\n * @memberOf module:twgl/m4\n */\nfunction rotationX(angleInRadians, dst) {\n dst = dst || new MatType(16);\n\n const c = Math.cos(angleInRadians);\n const s = Math.sin(angleInRadians);\n\n dst[ 0] = 1;\n dst[ 1] = 0;\n dst[ 2] = 0;\n dst[ 3] = 0;\n dst[ 4] = 0;\n dst[ 5] = c;\n dst[ 6] = s;\n dst[ 7] = 0;\n dst[ 8] = 0;\n dst[ 9] = -s;\n dst[10] = c;\n dst[11] = 0;\n dst[12] = 0;\n dst[13] = 0;\n dst[14] = 0;\n dst[15] = 1;\n\n return dst;\n}\n\n/**\n * Rotates the given 4-by-4 matrix around the x-axis by the given\n * angle.\n * @param {module:twgl/m4.Mat4} m The matrix.\n * @param {number} angleInRadians The angle by which to rotate (in radians).\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The rotated matrix.\n * @memberOf module:twgl/m4\n */\nfunction rotateX(m, angleInRadians, dst) {\n dst = dst || new MatType(16);\n\n const m10 = m[4];\n const m11 = m[5];\n const m12 = m[6];\n const m13 = m[7];\n const m20 = m[8];\n const m21 = m[9];\n const m22 = m[10];\n const m23 = m[11];\n const c = Math.cos(angleInRadians);\n const s = Math.sin(angleInRadians);\n\n dst[4] = c * m10 + s * m20;\n dst[5] = c * m11 + s * m21;\n dst[6] = c * m12 + s * m22;\n dst[7] = c * m13 + s * m23;\n dst[8] = c * m20 - s * m10;\n dst[9] = c * m21 - s * m11;\n dst[10] = c * m22 - s * m12;\n dst[11] = c * m23 - s * m13;\n\n if (m !== dst) {\n dst[ 0] = m[ 0];\n dst[ 1] = m[ 1];\n dst[ 2] = m[ 2];\n dst[ 3] = m[ 3];\n dst[12] = m[12];\n dst[13] = m[13];\n dst[14] = m[14];\n dst[15] = m[15];\n }\n\n return dst;\n}\n\n/**\n * Creates a 4-by-4 matrix which rotates around the y-axis by the given angle.\n * @param {number} angleInRadians The angle by which to rotate (in radians).\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The rotation matrix.\n * @memberOf module:twgl/m4\n */\nfunction rotationY(angleInRadians, dst) {\n dst = dst || new MatType(16);\n\n const c = Math.cos(angleInRadians);\n const s = Math.sin(angleInRadians);\n\n dst[ 0] = c;\n dst[ 1] = 0;\n dst[ 2] = -s;\n dst[ 3] = 0;\n dst[ 4] = 0;\n dst[ 5] = 1;\n dst[ 6] = 0;\n dst[ 7] = 0;\n dst[ 8] = s;\n dst[ 9] = 0;\n dst[10] = c;\n dst[11] = 0;\n dst[12] = 0;\n dst[13] = 0;\n dst[14] = 0;\n dst[15] = 1;\n\n return dst;\n}\n\n/**\n * Rotates the given 4-by-4 matrix around the y-axis by the given\n * angle.\n * @param {module:twgl/m4.Mat4} m The matrix.\n * @param {number} angleInRadians The angle by which to rotate (in radians).\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The rotated matrix.\n * @memberOf module:twgl/m4\n */\nfunction rotateY(m, angleInRadians, dst) {\n dst = dst || new MatType(16);\n\n const m00 = m[0 * 4 + 0];\n const m01 = m[0 * 4 + 1];\n const m02 = m[0 * 4 + 2];\n const m03 = m[0 * 4 + 3];\n const m20 = m[2 * 4 + 0];\n const m21 = m[2 * 4 + 1];\n const m22 = m[2 * 4 + 2];\n const m23 = m[2 * 4 + 3];\n const c = Math.cos(angleInRadians);\n const s = Math.sin(angleInRadians);\n\n dst[ 0] = c * m00 - s * m20;\n dst[ 1] = c * m01 - s * m21;\n dst[ 2] = c * m02 - s * m22;\n dst[ 3] = c * m03 - s * m23;\n dst[ 8] = c * m20 + s * m00;\n dst[ 9] = c * m21 + s * m01;\n dst[10] = c * m22 + s * m02;\n dst[11] = c * m23 + s * m03;\n\n if (m !== dst) {\n dst[ 4] = m[ 4];\n dst[ 5] = m[ 5];\n dst[ 6] = m[ 6];\n dst[ 7] = m[ 7];\n dst[12] = m[12];\n dst[13] = m[13];\n dst[14] = m[14];\n dst[15] = m[15];\n }\n\n return dst;\n}\n\n/**\n * Creates a 4-by-4 matrix which rotates around the z-axis by the given angle.\n * @param {number} angleInRadians The angle by which to rotate (in radians).\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The rotation matrix.\n * @memberOf module:twgl/m4\n */\nfunction rotationZ(angleInRadians, dst) {\n dst = dst || new MatType(16);\n\n const c = Math.cos(angleInRadians);\n const s = Math.sin(angleInRadians);\n\n dst[ 0] = c;\n dst[ 1] = s;\n dst[ 2] = 0;\n dst[ 3] = 0;\n dst[ 4] = -s;\n dst[ 5] = c;\n dst[ 6] = 0;\n dst[ 7] = 0;\n dst[ 8] = 0;\n dst[ 9] = 0;\n dst[10] = 1;\n dst[11] = 0;\n dst[12] = 0;\n dst[13] = 0;\n dst[14] = 0;\n dst[15] = 1;\n\n return dst;\n}\n\n/**\n * Rotates the given 4-by-4 matrix around the z-axis by the given\n * angle.\n * @param {module:twgl/m4.Mat4} m The matrix.\n * @param {number} angleInRadians The angle by which to rotate (in radians).\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The rotated matrix.\n * @memberOf module:twgl/m4\n */\nfunction rotateZ(m, angleInRadians, dst) {\n dst = dst || new MatType(16);\n\n const m00 = m[0 * 4 + 0];\n const m01 = m[0 * 4 + 1];\n const m02 = m[0 * 4 + 2];\n const m03 = m[0 * 4 + 3];\n const m10 = m[1 * 4 + 0];\n const m11 = m[1 * 4 + 1];\n const m12 = m[1 * 4 + 2];\n const m13 = m[1 * 4 + 3];\n const c = Math.cos(angleInRadians);\n const s = Math.sin(angleInRadians);\n\n dst[ 0] = c * m00 + s * m10;\n dst[ 1] = c * m01 + s * m11;\n dst[ 2] = c * m02 + s * m12;\n dst[ 3] = c * m03 + s * m13;\n dst[ 4] = c * m10 - s * m00;\n dst[ 5] = c * m11 - s * m01;\n dst[ 6] = c * m12 - s * m02;\n dst[ 7] = c * m13 - s * m03;\n\n if (m !== dst) {\n dst[ 8] = m[ 8];\n dst[ 9] = m[ 9];\n dst[10] = m[10];\n dst[11] = m[11];\n dst[12] = m[12];\n dst[13] = m[13];\n dst[14] = m[14];\n dst[15] = m[15];\n }\n\n return dst;\n}\n\n/**\n * Creates a 4-by-4 matrix which rotates around the given axis by the given\n * angle.\n * @param {module:twgl/v3.Vec3} axis The axis\n * about which to rotate.\n * @param {number} angleInRadians The angle by which to rotate (in radians).\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} A matrix which rotates angle radians\n * around the axis.\n * @memberOf module:twgl/m4\n */\nfunction axisRotation(axis, angleInRadians, dst) {\n dst = dst || new MatType(16);\n\n let x = axis[0];\n let y = axis[1];\n let z = axis[2];\n const n = Math.sqrt(x * x + y * y + z * z);\n x /= n;\n y /= n;\n z /= n;\n const xx = x * x;\n const yy = y * y;\n const zz = z * z;\n const c = Math.cos(angleInRadians);\n const s = Math.sin(angleInRadians);\n const oneMinusCosine = 1 - c;\n\n dst[ 0] = xx + (1 - xx) * c;\n dst[ 1] = x * y * oneMinusCosine + z * s;\n dst[ 2] = x * z * oneMinusCosine - y * s;\n dst[ 3] = 0;\n dst[ 4] = x * y * oneMinusCosine - z * s;\n dst[ 5] = yy + (1 - yy) * c;\n dst[ 6] = y * z * oneMinusCosine + x * s;\n dst[ 7] = 0;\n dst[ 8] = x * z * oneMinusCosine + y * s;\n dst[ 9] = y * z * oneMinusCosine - x * s;\n dst[10] = zz + (1 - zz) * c;\n dst[11] = 0;\n dst[12] = 0;\n dst[13] = 0;\n dst[14] = 0;\n dst[15] = 1;\n\n return dst;\n}\n\n/**\n * Rotates the given 4-by-4 matrix around the given axis by the\n * given angle.\n * @param {module:twgl/m4.Mat4} m The matrix.\n * @param {module:twgl/v3.Vec3} axis The axis\n * about which to rotate.\n * @param {number} angleInRadians The angle by which to rotate (in radians).\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The rotated matrix.\n * @memberOf module:twgl/m4\n */\nfunction axisRotate(m, axis, angleInRadians, dst) {\n dst = dst || new MatType(16);\n\n let x = axis[0];\n let y = axis[1];\n let z = axis[2];\n const n = Math.sqrt(x * x + y * y + z * z);\n x /= n;\n y /= n;\n z /= n;\n const xx = x * x;\n const yy = y * y;\n const zz = z * z;\n const c = Math.cos(angleInRadians);\n const s = Math.sin(angleInRadians);\n const oneMinusCosine = 1 - c;\n\n const r00 = xx + (1 - xx) * c;\n const r01 = x * y * oneMinusCosine + z * s;\n const r02 = x * z * oneMinusCosine - y * s;\n const r10 = x * y * oneMinusCosine - z * s;\n const r11 = yy + (1 - yy) * c;\n const r12 = y * z * oneMinusCosine + x * s;\n const r20 = x * z * oneMinusCosine + y * s;\n const r21 = y * z * oneMinusCosine - x * s;\n const r22 = zz + (1 - zz) * c;\n\n const m00 = m[0];\n const m01 = m[1];\n const m02 = m[2];\n const m03 = m[3];\n const m10 = m[4];\n const m11 = m[5];\n const m12 = m[6];\n const m13 = m[7];\n const m20 = m[8];\n const m21 = m[9];\n const m22 = m[10];\n const m23 = m[11];\n\n dst[ 0] = r00 * m00 + r01 * m10 + r02 * m20;\n dst[ 1] = r00 * m01 + r01 * m11 + r02 * m21;\n dst[ 2] = r00 * m02 + r01 * m12 + r02 * m22;\n dst[ 3] = r00 * m03 + r01 * m13 + r02 * m23;\n dst[ 4] = r10 * m00 + r11 * m10 + r12 * m20;\n dst[ 5] = r10 * m01 + r11 * m11 + r12 * m21;\n dst[ 6] = r10 * m02 + r11 * m12 + r12 * m22;\n dst[ 7] = r10 * m03 + r11 * m13 + r12 * m23;\n dst[ 8] = r20 * m00 + r21 * m10 + r22 * m20;\n dst[ 9] = r20 * m01 + r21 * m11 + r22 * m21;\n dst[10] = r20 * m02 + r21 * m12 + r22 * m22;\n dst[11] = r20 * m03 + r21 * m13 + r22 * m23;\n\n if (m !== dst) {\n dst[12] = m[12];\n dst[13] = m[13];\n dst[14] = m[14];\n dst[15] = m[15];\n }\n\n return dst;\n}\n\n/**\n * Creates a 4-by-4 matrix which scales in each dimension by an amount given by\n * the corresponding entry in the given vector; assumes the vector has three\n * entries.\n * @param {module:twgl/v3.Vec3} v A vector of\n * three entries specifying the factor by which to scale in each dimension.\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The scaling matrix.\n * @memberOf module:twgl/m4\n */\nfunction scaling(v, dst) {\n dst = dst || new MatType(16);\n\n dst[ 0] = v[0];\n dst[ 1] = 0;\n dst[ 2] = 0;\n dst[ 3] = 0;\n dst[ 4] = 0;\n dst[ 5] = v[1];\n dst[ 6] = 0;\n dst[ 7] = 0;\n dst[ 8] = 0;\n dst[ 9] = 0;\n dst[10] = v[2];\n dst[11] = 0;\n dst[12] = 0;\n dst[13] = 0;\n dst[14] = 0;\n dst[15] = 1;\n\n return dst;\n}\n\n/**\n * Scales the given 4-by-4 matrix in each dimension by an amount\n * given by the corresponding entry in the given vector; assumes the vector has\n * three entries.\n * @param {module:twgl/m4.Mat4} m The matrix to be modified.\n * @param {module:twgl/v3.Vec3} v A vector of three entries specifying the\n * factor by which to scale in each dimension.\n * @param {module:twgl/m4.Mat4} [dst] matrix to hold result. If not passed a new one is created.\n * @return {module:twgl/m4.Mat4} The scaled matrix.\n * @memberOf module:twgl/m4\n */\nfunction scale(m, v, dst) {\n dst = dst || new MatType(16);\n\n const v0 = v[0];\n const v1 = v[1];\n const v2 = v[2];\n\n dst[ 0] = v0 * m[0 * 4 + 0];\n dst[ 1] = v0 * m[0 * 4 + 1];\n dst[ 2] = v0 * m[0 * 4 + 2];\n dst[ 3] = v0 * m[0 * 4 + 3];\n dst[ 4] = v1 * m[1 * 4 + 0];\n dst[ 5] = v1 * m[1 * 4 + 1];\n dst[ 6] = v1 * m[1 * 4 + 2];\n dst[ 7] = v1 * m[1 * 4 + 3];\n dst[ 8] = v2 * m[2 * 4 + 0];\n dst[ 9] = v2 * m[2 * 4 + 1];\n dst[10] = v2 * m[2 * 4 + 2];\n dst[11] = v2 * m[2 * 4 + 3];\n\n if (m !== dst) {\n dst[12] = m[12];\n dst[13] = m[13];\n dst[14] = m[14];\n dst[15] = m[15];\n }\n\n return dst;\n}\n\n/**\n * Takes a 4-by-4 matrix and a vector with 3 entries,\n * interprets the vector as a point, transforms that point by the matrix, and\n * returns the result as a vector with 3 entries.\n * @param {module:twgl/m4.Mat4} m The matrix.\n * @param {module:twgl/v3.Vec3} v The point.\n * @param {module:twgl/v3.Vec3} [dst] optional vec3 to store result. If not passed a new one is created.\n * @return {module:twgl/v3.Vec3} The transformed point.\n * @memberOf module:twgl/m4\n */\nfunction transformPoint(m, v, dst) {\n dst = dst || create$1();\n const v0 = v[0];\n const v1 = v[1];\n const v2 = v[2];\n const d = v0 * m[0 * 4 + 3] + v1 * m[1 * 4 + 3] + v2 * m[2 * 4 + 3] + m[3 * 4 + 3];\n\n dst[0] = (v0 * m[0 * 4 + 0] + v1 * m[1 * 4 + 0] + v2 * m[2 * 4 + 0] + m[3 * 4 + 0]) / d;\n dst[1] = (v0 * m[0 * 4 + 1] + v1 * m[1 * 4 + 1] + v2 * m[2 * 4 + 1] + m[3 * 4 + 1]) / d;\n dst[2] = (v0 * m[0 * 4 + 2] + v1 * m[1 * 4 + 2] + v2 * m[2 * 4 + 2] + m[3 * 4 + 2]) / d;\n\n return dst;\n}\n\n/**\n * Takes a 4-by-4 matrix and a vector with 3 entries, interprets the vector as a\n * direction, transforms that direction by the matrix, and returns the result;\n * assumes the transformation of 3-dimensional space represented by the matrix\n * is parallel-preserving, i.e. any combination of rotation, scaling and\n * translation, but not a perspective distortion. Returns a vector with 3\n * entries.\n * @param {module:twgl/m4.Mat4} m The matrix.\n * @param {module:twgl/v3.Vec3} v The direction.\n * @param {module:twgl/v3.Vec3} [dst] optional Vec3 to store result. If not passed a new one is created.\n * @return {module:twgl/v3.Vec3} The transformed direction.\n * @memberOf module:twgl/m4\n */\nfunction transformDirection(m, v, dst) {\n dst = dst || create$1();\n\n const v0 = v[0];\n const v1 = v[1];\n const v2 = v[2];\n\n dst[0] = v0 * m[0 * 4 + 0] + v1 * m[1 * 4 + 0] + v2 * m[2 * 4 + 0];\n dst[1] = v0 * m[0 * 4 + 1] + v1 * m[1 * 4 + 1] + v2 * m[2 * 4 + 1];\n dst[2] = v0 * m[0 * 4 + 2] + v1 * m[1 * 4 + 2] + v2 * m[2 * 4 + 2];\n\n return dst;\n}\n\n/**\n * Takes a 4-by-4 matrix m and a vector v with 3 entries, interprets the vector\n * as a normal to a surface, and computes a vector which is normal upon\n * transforming that surface by the matrix. The effect of this function is the\n * same as transforming v (as a direction) by the inverse-transpose of m. This\n * function assumes the transformation of 3-dimensional space represented by the\n * matrix is parallel-preserving, i.e. any combination of rotation, scaling and\n * translation, but not a perspective distortion. Returns a vector with 3\n * entries.\n * @param {module:twgl/m4.Mat4} m The matrix.\n * @param {module:twgl/v3.Vec3} v The normal.\n * @param {module:twgl/v3.Vec3} [dst] The direction. If not passed a new one is created.\n * @return {module:twgl/v3.Vec3} The transformed normal.\n * @memberOf module:twgl/m4\n */\nfunction transformNormal$1(m, v, dst) {\n dst = dst || create$1();\n const mi = inverse(m);\n const v0 = v[0];\n const v1 = v[1];\n const v2 = v[2];\n\n dst[0] = v0 * mi[0 * 4 + 0] + v1 * mi[0 * 4 + 1] + v2 * mi[0 * 4 + 2];\n dst[1] = v0 * mi[1 * 4 + 0] + v1 * mi[1 * 4 + 1] + v2 * mi[1 * 4 + 2];\n dst[2] = v0 * mi[2 * 4 + 0] + v1 * mi[2 * 4 + 1] + v2 * mi[2 * 4 + 2];\n\n return dst;\n}\n\nvar m4 = /*#__PURE__*/Object.freeze({\n __proto__: null,\n axisRotate: axisRotate,\n axisRotation: axisRotation,\n copy: copy,\n create: create,\n frustum: frustum,\n getAxis: getAxis,\n getTranslation: getTranslation,\n identity: identity,\n inverse: inverse,\n lookAt: lookAt,\n multiply: multiply,\n negate: negate,\n ortho: ortho,\n perspective: perspective,\n rotateX: rotateX,\n rotateY: rotateY,\n rotateZ: rotateZ,\n rotationX: rotationX,\n rotationY: rotationY,\n rotationZ: rotationZ,\n scale: scale,\n scaling: scaling,\n setAxis: setAxis,\n setDefaultType: setDefaultType,\n setTranslation: setTranslation,\n transformDirection: transformDirection,\n transformNormal: transformNormal$1,\n transformPoint: transformPoint,\n translate: translate,\n translation: translation,\n transpose: transpose\n});\n\n/*\n * Copyright 2019 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\n/* DataType */\nconst BYTE$2 = 0x1400;\nconst UNSIGNED_BYTE$3 = 0x1401;\nconst SHORT$2 = 0x1402;\nconst UNSIGNED_SHORT$3 = 0x1403;\nconst INT$3 = 0x1404;\nconst UNSIGNED_INT$3 = 0x1405;\nconst FLOAT$3 = 0x1406;\nconst UNSIGNED_SHORT_4_4_4_4$1 = 0x8033;\nconst UNSIGNED_SHORT_5_5_5_1$1 = 0x8034;\nconst UNSIGNED_SHORT_5_6_5$1 = 0x8363;\nconst HALF_FLOAT$1 = 0x140B;\nconst UNSIGNED_INT_2_10_10_10_REV$1 = 0x8368;\nconst UNSIGNED_INT_10F_11F_11F_REV$1 = 0x8C3B;\nconst UNSIGNED_INT_5_9_9_9_REV$1 = 0x8C3E;\nconst FLOAT_32_UNSIGNED_INT_24_8_REV$1 = 0x8DAD;\nconst UNSIGNED_INT_24_8$1 = 0x84FA;\n\nconst glTypeToTypedArray = {};\n{\n const tt = glTypeToTypedArray;\n tt[BYTE$2] = Int8Array;\n tt[UNSIGNED_BYTE$3] = Uint8Array;\n tt[SHORT$2] = Int16Array;\n tt[UNSIGNED_SHORT$3] = Uint16Array;\n tt[INT$3] = Int32Array;\n tt[UNSIGNED_INT$3] = Uint32Array;\n tt[FLOAT$3] = Float32Array;\n tt[UNSIGNED_SHORT_4_4_4_4$1] = Uint16Array;\n tt[UNSIGNED_SHORT_5_5_5_1$1] = Uint16Array;\n tt[UNSIGNED_SHORT_5_6_5$1] = Uint16Array;\n tt[HALF_FLOAT$1] = Uint16Array;\n tt[UNSIGNED_INT_2_10_10_10_REV$1] = Uint32Array;\n tt[UNSIGNED_INT_10F_11F_11F_REV$1] = Uint32Array;\n tt[UNSIGNED_INT_5_9_9_9_REV$1] = Uint32Array;\n tt[FLOAT_32_UNSIGNED_INT_24_8_REV$1] = Uint32Array;\n tt[UNSIGNED_INT_24_8$1] = Uint32Array;\n}\n\n/**\n * Get the GL type for a typedArray\n * @param {ArrayBufferView} typedArray a typedArray\n * @return {number} the GL type for array. For example pass in an `Int8Array` and `gl.BYTE` will\n * be returned. Pass in a `Uint32Array` and `gl.UNSIGNED_INT` will be returned\n * @memberOf module:twgl/typedArray\n */\nfunction getGLTypeForTypedArray(typedArray) {\n if (typedArray instanceof Int8Array) { return BYTE$2; } // eslint-disable-line\n if (typedArray instanceof Uint8Array) { return UNSIGNED_BYTE$3; } // eslint-disable-line\n if (typedArray instanceof Uint8ClampedArray) { return UNSIGNED_BYTE$3; } // eslint-disable-line\n if (typedArray instanceof Int16Array) { return SHORT$2; } // eslint-disable-line\n if (typedArray instanceof Uint16Array) { return UNSIGNED_SHORT$3; } // eslint-disable-line\n if (typedArray instanceof Int32Array) { return INT$3; } // eslint-disable-line\n if (typedArray instanceof Uint32Array) { return UNSIGNED_INT$3; } // eslint-disable-line\n if (typedArray instanceof Float32Array) { return FLOAT$3; } // eslint-disable-line\n throw new Error('unsupported typed array type');\n}\n\n/**\n * Get the GL type for a typedArray type\n * @param {ArrayBufferView} typedArrayType a typedArray constructor\n * @return {number} the GL type for type. For example pass in `Int8Array` and `gl.BYTE` will\n * be returned. Pass in `Uint32Array` and `gl.UNSIGNED_INT` will be returned\n * @memberOf module:twgl/typedArray\n */\nfunction getGLTypeForTypedArrayType(typedArrayType) {\n if (typedArrayType === Int8Array) { return BYTE$2; } // eslint-disable-line\n if (typedArrayType === Uint8Array) { return UNSIGNED_BYTE$3; } // eslint-disable-line\n if (typedArrayType === Uint8ClampedArray) { return UNSIGNED_BYTE$3; } // eslint-disable-line\n if (typedArrayType === Int16Array) { return SHORT$2; } // eslint-disable-line\n if (typedArrayType === Uint16Array) { return UNSIGNED_SHORT$3; } // eslint-disable-line\n if (typedArrayType === Int32Array) { return INT$3; } // eslint-disable-line\n if (typedArrayType === Uint32Array) { return UNSIGNED_INT$3; } // eslint-disable-line\n if (typedArrayType === Float32Array) { return FLOAT$3; } // eslint-disable-line\n throw new Error('unsupported typed array type');\n}\n\n/**\n * Get the typed array constructor for a given GL type\n * @param {number} type the GL type. (eg: `gl.UNSIGNED_INT`)\n * @return {function} the constructor for a the corresponding typed array. (eg. `Uint32Array`).\n * @memberOf module:twgl/typedArray\n */\nfunction getTypedArrayTypeForGLType(type) {\n const CTOR = glTypeToTypedArray[type];\n if (!CTOR) {\n throw new Error('unknown gl type');\n }\n return CTOR;\n}\n\nconst isArrayBuffer$1 = typeof SharedArrayBuffer !== 'undefined'\n ? function isArrayBufferOrSharedArrayBuffer(a) {\n return a && a.buffer && (a.buffer instanceof ArrayBuffer || a.buffer instanceof SharedArrayBuffer);\n }\n : function isArrayBuffer(a) {\n return a && a.buffer && a.buffer instanceof ArrayBuffer;\n };\n\nvar typedarrays = /*#__PURE__*/Object.freeze({\n __proto__: null,\n getGLTypeForTypedArray: getGLTypeForTypedArray,\n getGLTypeForTypedArrayType: getGLTypeForTypedArrayType,\n getTypedArrayTypeForGLType: getTypedArrayTypeForGLType,\n isArrayBuffer: isArrayBuffer$1\n});\n\n/*\n * Copyright 2019 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\n/* eslint no-console: \"off\" */\n\n/**\n * Copy named properties\n *\n * @param {string[]} names names of properties to copy\n * @param {object} src object to copy properties from\n * @param {object} dst object to copy properties to\n * @private\n */\nfunction copyNamedProperties(names, src, dst) {\n names.forEach(function(name) {\n const value = src[name];\n if (value !== undefined) {\n dst[name] = value;\n }\n });\n}\n\n/**\n * Copies properties from source to dest only if a matching key is in dest\n *\n * @param {Object.} src the source\n * @param {Object.} dst the dest\n * @private\n */\nfunction copyExistingProperties(src, dst) {\n Object.keys(dst).forEach(function(key) {\n if (dst.hasOwnProperty(key) && src.hasOwnProperty(key)) { /* eslint no-prototype-builtins: 0 */\n dst[key] = src[key];\n }\n });\n}\n\nfunction error$1(...args) {\n console.error(...args);\n}\n\nfunction warn$1(...args) {\n console.warn(...args);\n}\n\nconst isTypeWeakMaps = new Map();\n\nfunction isType(object, type) {\n if (!object || typeof object !== 'object') {\n return false;\n }\n let weakMap = isTypeWeakMaps.get(type);\n if (!weakMap) {\n weakMap = new WeakMap();\n isTypeWeakMaps.set(type, weakMap);\n }\n let isOfType = weakMap.get(object);\n if (isOfType === undefined) {\n const s = Object.prototype.toString.call(object);\n isOfType = s.substring(8, s.length - 1) === type;\n weakMap.set(object, isOfType);\n }\n return isOfType;\n}\n\nfunction isBuffer(gl, t) {\n return typeof WebGLBuffer !== 'undefined' && isType(t, 'WebGLBuffer');\n}\n\nfunction isRenderbuffer(gl, t) {\n return typeof WebGLRenderbuffer !== 'undefined' && isType(t, 'WebGLRenderbuffer');\n}\n\nfunction isTexture(gl, t) {\n return typeof WebGLTexture !== 'undefined' && isType(t, 'WebGLTexture');\n}\n\nfunction isSampler(gl, t) {\n return typeof WebGLSampler !== 'undefined' && isType(t, 'WebGLSampler');\n}\n\n/*\n * Copyright 2019 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\nconst STATIC_DRAW = 0x88e4;\nconst ARRAY_BUFFER$1 = 0x8892;\nconst ELEMENT_ARRAY_BUFFER$2 = 0x8893;\nconst BUFFER_SIZE = 0x8764;\n\nconst BYTE$1 = 0x1400;\nconst UNSIGNED_BYTE$2 = 0x1401;\nconst SHORT$1 = 0x1402;\nconst UNSIGNED_SHORT$2 = 0x1403;\nconst INT$2 = 0x1404;\nconst UNSIGNED_INT$2 = 0x1405;\nconst FLOAT$2 = 0x1406;\nconst defaults$2 = {\n attribPrefix: \"\",\n};\n\n/**\n * Sets the default attrib prefix\n *\n * When writing shaders I prefer to name attributes with `a_`, uniforms with `u_` and varyings with `v_`\n * as it makes it clear where they came from. But, when building geometry I prefer using un-prefixed names.\n *\n * In other words I'll create arrays of geometry like this\n *\n * var arrays = {\n * position: ...\n * normal: ...\n * texcoord: ...\n * };\n *\n * But need those mapped to attributes and my attributes start with `a_`.\n *\n * @deprecated see {@link module:twgl.setDefaults}\n * @param {string} prefix prefix for attribs\n * @memberOf module:twgl/attributes\n */\nfunction setAttributePrefix(prefix) {\n defaults$2.attribPrefix = prefix;\n}\n\nfunction setDefaults$2(newDefaults) {\n copyExistingProperties(newDefaults, defaults$2);\n}\n\nfunction setBufferFromTypedArray(gl, type, buffer, array, drawType) {\n gl.bindBuffer(type, buffer);\n gl.bufferData(type, array, drawType || STATIC_DRAW);\n}\n\n/**\n * Given typed array creates a WebGLBuffer and copies the typed array\n * into it.\n *\n * @param {WebGLRenderingContext} gl A WebGLRenderingContext\n * @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\n * @param {number} [type] the GL bind type for the buffer. Default = `gl.ARRAY_BUFFER`.\n * @param {number} [drawType] the GL draw type for the buffer. Default = 'gl.STATIC_DRAW`.\n * @return {WebGLBuffer} the created WebGLBuffer\n * @memberOf module:twgl/attributes\n */\nfunction createBufferFromTypedArray(gl, typedArray, type, drawType) {\n if (isBuffer(gl, typedArray)) {\n return typedArray;\n }\n type = type || ARRAY_BUFFER$1;\n const buffer = gl.createBuffer();\n setBufferFromTypedArray(gl, type, buffer, typedArray, drawType);\n return buffer;\n}\n\nfunction isIndices(name) {\n return name === \"indices\";\n}\n\n// This is really just a guess. Though I can't really imagine using\n// anything else? Maybe for some compression?\nfunction getNormalizationForTypedArrayType(typedArrayType) {\n if (typedArrayType === Int8Array) { return true; } // eslint-disable-line\n if (typedArrayType === Uint8Array) { return true; } // eslint-disable-line\n return false;\n}\n\nfunction getArray$1(array) {\n return array.length ? array : array.data;\n}\n\nconst texcoordRE = /coord|texture/i;\nconst colorRE = /color|colour/i;\n\nfunction guessNumComponentsFromName(name, length) {\n let numComponents;\n if (texcoordRE.test(name)) {\n numComponents = 2;\n } else if (colorRE.test(name)) {\n numComponents = 4;\n } else {\n numComponents = 3; // position, normals, indices ...\n }\n\n if (length % numComponents > 0) {\n 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.`);\n }\n\n return numComponents;\n}\n\nfunction getNumComponents$1(array, arrayName, numValues) {\n return array.numComponents || array.size || guessNumComponentsFromName(arrayName, numValues || getArray$1(array).length);\n}\n\nfunction makeTypedArray(array, name) {\n if (isArrayBuffer$1(array)) {\n return array;\n }\n\n if (isArrayBuffer$1(array.data)) {\n return array.data;\n }\n\n if (Array.isArray(array)) {\n array = {\n data: array,\n };\n }\n\n let Type = array.type ? typedArrayTypeFromGLTypeOrTypedArrayCtor(array.type) : undefined;\n if (!Type) {\n if (isIndices(name)) {\n Type = Uint16Array;\n } else {\n Type = Float32Array;\n }\n }\n return new Type(array.data);\n}\n\nfunction glTypeFromGLTypeOrTypedArrayType(glTypeOrTypedArrayCtor) {\n return typeof glTypeOrTypedArrayCtor === 'number'\n ? glTypeOrTypedArrayCtor\n : glTypeOrTypedArrayCtor ? getGLTypeForTypedArrayType(glTypeOrTypedArrayCtor) : FLOAT$2;\n}\n\nfunction typedArrayTypeFromGLTypeOrTypedArrayCtor(glTypeOrTypedArrayCtor) {\n return typeof glTypeOrTypedArrayCtor === 'number'\n ? getTypedArrayTypeForGLType(glTypeOrTypedArrayCtor)\n : glTypeOrTypedArrayCtor || Float32Array;\n}\n\nfunction attribBufferFromBuffer(gl, array/*, arrayName */) {\n return {\n buffer: array.buffer,\n numValues: 2 * 3 * 4, // safely divided by 2, 3, 4\n type: glTypeFromGLTypeOrTypedArrayType(array.type),\n arrayType: typedArrayTypeFromGLTypeOrTypedArrayCtor(array.type),\n };\n}\n\nfunction attribBufferFromSize(gl, array/*, arrayName*/) {\n const numValues = array.data || array;\n const arrayType = typedArrayTypeFromGLTypeOrTypedArrayCtor(array.type);\n const numBytes = numValues * arrayType.BYTES_PER_ELEMENT;\n const buffer = gl.createBuffer();\n gl.bindBuffer(ARRAY_BUFFER$1, buffer);\n gl.bufferData(ARRAY_BUFFER$1, numBytes, array.drawType || STATIC_DRAW);\n return {\n buffer,\n numValues,\n type: getGLTypeForTypedArrayType(arrayType),\n arrayType,\n };\n}\n\nfunction attribBufferFromArrayLike(gl, array, arrayName) {\n const typedArray = makeTypedArray(array, arrayName);\n return {\n arrayType: typedArray.constructor,\n buffer: createBufferFromTypedArray(gl, typedArray, undefined, array.drawType),\n type: getGLTypeForTypedArray(typedArray),\n numValues: 0,\n };\n}\n\n/**\n * The info for an attribute. This is effectively just the arguments to `gl.vertexAttribPointer` plus the WebGLBuffer\n * for the attribute.\n *\n * @typedef {Object} AttribInfo\n * @property {number[]|ArrayBufferView} [value] a constant value for the attribute. Note: if this is set the attribute will be\n * disabled and set to this constant value and all other values will be ignored.\n * @property {number} [numComponents] the number of components for this attribute.\n * @property {number} [size] synonym for `numComponents`.\n * @property {number} [type] the type of the attribute (eg. `gl.FLOAT`, `gl.UNSIGNED_BYTE`, etc...) Default = `gl.FLOAT`\n * @property {boolean} [normalize] whether or not to normalize the data. Default = false\n * @property {number} [offset] offset into buffer in bytes. Default = 0\n * @property {number} [stride] the stride in bytes per element. Default = 0\n * @property {number} [divisor] the divisor in instances. Default = 0.\n * Requires WebGL2 or the ANGLE_instanced_arrays extension.\n * and, if you're using WebGL1 you must have called {@link module:twgl.addExtensionsToContext}\n * @property {WebGLBuffer} buffer the buffer that contains the data for this attribute\n * @property {number} [drawType] the draw type passed to gl.bufferData. Default = gl.STATIC_DRAW\n * @memberOf module:twgl\n */\n\n/**\n * @typedef {(Int8ArrayConstructor|Uint8ArrayConstructor|Int16ArrayConstructor|Uint16ArrayConstructor|Int32ArrayConstructor|Uint32ArrayConstructor|Float32ArrayConstructor)} TypedArrayConstructor\n */\n\n/**\n * Use this type of array spec when TWGL can't guess the type or number of components of an array\n * @typedef {Object} FullArraySpec\n * @property {number[]|ArrayBufferView} [value] a constant value for the attribute. Note: if this is set the attribute will be\n * disabled and set to this constant value and all other values will be ignored.\n * @property {(number|number[]|ArrayBufferView)} [data] The data of the array. A number alone becomes the number of elements of type.\n * @property {number} [numComponents] number of components for `vertexAttribPointer`. Default is based on the name of the array.\n * If `coord` is in the name assumes `numComponents = 2`.\n * If `color` is in the name assumes `numComponents = 4`.\n * otherwise assumes `numComponents = 3`\n * @property {number|TypedArrayConstructor} [type] type. This is used if `data` is a JavaScript array, or `buffer` is passed in, or `data` is a number.\n * It can either be the constructor for a typedarray. (eg. `Uint8Array`) OR a WebGL type, (eg `gl.UNSIGNED_BYTE`).\n * For example if you want colors in a `Uint8Array` you might have a `FullArraySpec` like `{ type: gl.UNSIGNED_BYTE, data: [255,0,255,255, ...], }`.\n * @property {number} [size] synonym for `numComponents`.\n * @property {boolean} [normalize] normalize for `vertexAttribPointer`. Default is true if type is `Int8Array` or `Uint8Array` otherwise false.\n * @property {number} [stride] stride for `vertexAttribPointer`. Default = 0\n * @property {number} [offset] offset for `vertexAttribPointer`. Default = 0\n * @property {number} [divisor] divisor for `vertexAttribDivisor`. Default = 0.\n * Requires WebGL2 or the ANGLE_instanced_arrays extension.\n * and, if you using WebGL1 you must have called {@link module:twgl.addExtensionsToContext}\n * @property {string} [attrib] name of attribute this array maps to. Defaults to same name as array prefixed by the default attribPrefix.\n * @property {string} [name] synonym for `attrib`.\n * @property {string} [attribName] synonym for `attrib`.\n * @property {WebGLBuffer} [buffer] Buffer to use for this attribute. This lets you use your own buffer\n * but you will need to supply `numComponents` and `type`. You can effectively pass an `AttribInfo`\n * to provide this. Example:\n *\n * const bufferInfo1 = twgl.createBufferInfoFromArrays(gl, {\n * position: [1, 2, 3, ... ],\n * });\n * const bufferInfo2 = twgl.createBufferInfoFromArrays(gl, {\n * position: bufferInfo1.attribs.position, // use the same buffer from bufferInfo1\n * });\n *\n * @property {number} [drawType] the draw type passed to gl.bufferData. Default = gl.STATIC_DRAW\n * @memberOf module:twgl\n */\n\n/**\n * An individual array in {@link module:twgl.Arrays}\n *\n * When passed to {@link module:twgl.createBufferInfoFromArrays} if an ArraySpec is `number[]` or `ArrayBufferView`\n * the types will be guessed based on the name. `indices` will be `Uint16Array`, everything else will\n * be `Float32Array`. If an ArraySpec is a number it's the number of floats for an empty (zeroed) buffer.\n *\n * @typedef {(number|number[]|ArrayBufferView|module:twgl.FullArraySpec)} ArraySpec\n * @memberOf module:twgl\n */\n\n/**\n * This is a JavaScript object of arrays by name. The names should match your shader's attributes. If your\n * attributes have a common prefix you can specify it by calling {@link module:twgl.setAttributePrefix}.\n *\n * Bare JavaScript Arrays\n *\n * var arrays = {\n * position: [-1, 1, 0],\n * normal: [0, 1, 0],\n * ...\n * }\n *\n * Bare TypedArrays\n *\n * var arrays = {\n * position: new Float32Array([-1, 1, 0]),\n * color: new Uint8Array([255, 128, 64, 255]),\n * ...\n * }\n *\n * * Will guess at `numComponents` if not specified based on name.\n *\n * If `coord` is in the name assumes `numComponents = 2`\n *\n * If `color` is in the name assumes `numComponents = 4`\n *\n * otherwise assumes `numComponents = 3`\n *\n * Objects with various fields. See {@link module:twgl.FullArraySpec}.\n *\n * var arrays = {\n * position: { numComponents: 3, data: [0, 0, 0, 10, 0, 0, 0, 10, 0, 10, 10, 0], },\n * texcoord: { numComponents: 2, data: [0, 0, 0, 1, 1, 0, 1, 1], },\n * normal: { numComponents: 3, data: [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1], },\n * indices: { numComponents: 3, data: [0, 1, 2, 1, 2, 3], },\n * };\n *\n * @typedef {Object.} Arrays\n * @memberOf module:twgl\n */\n\n\n/**\n * Creates a set of attribute data and WebGLBuffers from set of arrays\n *\n * Given\n *\n * var arrays = {\n * position: { numComponents: 3, data: [0, 0, 0, 10, 0, 0, 0, 10, 0, 10, 10, 0], },\n * texcoord: { numComponents: 2, data: [0, 0, 0, 1, 1, 0, 1, 1], },\n * normal: { numComponents: 3, data: [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1], },\n * color: { numComponents: 4, data: [255, 255, 255, 255, 255, 0, 0, 255, 0, 0, 255, 255], type: Uint8Array, },\n * indices: { numComponents: 3, data: [0, 1, 2, 1, 2, 3], },\n * };\n *\n * returns something like\n *\n * var attribs = {\n * position: { numComponents: 3, type: gl.FLOAT, normalize: false, buffer: WebGLBuffer, },\n * texcoord: { numComponents: 2, type: gl.FLOAT, normalize: false, buffer: WebGLBuffer, },\n * normal: { numComponents: 3, type: gl.FLOAT, normalize: false, buffer: WebGLBuffer, },\n * color: { numComponents: 4, type: gl.UNSIGNED_BYTE, normalize: true, buffer: WebGLBuffer, },\n * };\n *\n * notes:\n *\n * * Arrays can take various forms\n *\n * Bare JavaScript Arrays\n *\n * var arrays = {\n * position: [-1, 1, 0],\n * normal: [0, 1, 0],\n * ...\n * }\n *\n * Bare TypedArrays\n *\n * var arrays = {\n * position: new Float32Array([-1, 1, 0]),\n * color: new Uint8Array([255, 128, 64, 255]),\n * ...\n * }\n *\n * * Will guess at `numComponents` if not specified based on name.\n *\n * If `coord` is in the name assumes `numComponents = 2`\n *\n * If `color` is in the name assumes `numComponents = 4`\n *\n * otherwise assumes `numComponents = 3`\n *\n * @param {WebGLRenderingContext} gl The webgl rendering context.\n * @param {module:twgl.Arrays} arrays The arrays\n * @param {module:twgl.BufferInfo} [srcBufferInfo] a BufferInfo to copy from\n * This lets you share buffers. Any arrays you supply will override\n * the buffers from srcBufferInfo.\n * @return {Object.} the attribs\n * @memberOf module:twgl/attributes\n */\nfunction createAttribsFromArrays(gl, arrays) {\n const attribs = {};\n Object.keys(arrays).forEach(function(arrayName) {\n if (!isIndices(arrayName)) {\n const array = arrays[arrayName];\n const attribName = array.attrib || array.name || array.attribName || (defaults$2.attribPrefix + arrayName);\n if (array.value) {\n if (!Array.isArray(array.value) && !isArrayBuffer$1(array.value)) {\n throw new Error('array.value is not array or typedarray');\n }\n attribs[attribName] = {\n value: array.value,\n };\n } else {\n let fn;\n if (array.buffer && array.buffer instanceof WebGLBuffer) {\n fn = attribBufferFromBuffer;\n } else if (typeof array === \"number\" || typeof array.data === \"number\") {\n fn = attribBufferFromSize;\n } else {\n fn = attribBufferFromArrayLike;\n }\n const {buffer, type, numValues, arrayType} = fn(gl, array, arrayName);\n const normalization = array.normalize !== undefined ? array.normalize : getNormalizationForTypedArrayType(arrayType);\n const numComponents = getNumComponents$1(array, arrayName, numValues);\n attribs[attribName] = {\n buffer: buffer,\n numComponents: numComponents,\n type: type,\n normalize: normalization,\n stride: array.stride || 0,\n offset: array.offset || 0,\n divisor: array.divisor === undefined ? undefined : array.divisor,\n drawType: array.drawType,\n };\n }\n }\n });\n gl.bindBuffer(ARRAY_BUFFER$1, null);\n return attribs;\n}\n\n/**\n * Sets the contents of a buffer attached to an attribInfo\n *\n * This is helper function to dynamically update a buffer.\n *\n * Let's say you make a bufferInfo\n *\n * var arrays = {\n * position: new Float32Array([0, 0, 0, 10, 0, 0, 0, 10, 0, 10, 10, 0]),\n * texcoord: new Float32Array([0, 0, 0, 1, 1, 0, 1, 1]),\n * normal: new Float32Array([0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1]),\n * indices: new Uint16Array([0, 1, 2, 1, 2, 3]),\n * };\n * var bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);\n *\n * And you want to dynamically update the positions. You could do this\n *\n * // assuming arrays.position has already been updated with new data.\n * twgl.setAttribInfoBufferFromArray(gl, bufferInfo.attribs.position, arrays.position);\n *\n * @param {WebGLRenderingContext} gl\n * @param {AttribInfo} attribInfo The attribInfo who's buffer contents to set. NOTE: If you have an attribute prefix\n * the name of the attribute will include the prefix.\n * @param {ArraySpec} array Note: it is arguably inefficient to pass in anything but a typed array because anything\n * else will have to be converted to a typed array before it can be used by WebGL. During init time that\n * inefficiency is usually not important but if you're updating data dynamically best to be efficient.\n * @param {number} [offset] an optional offset into the buffer. This is only an offset into the WebGL buffer\n * not the array. To pass in an offset into the array itself use a typed array and create an `ArrayBufferView`\n * for the portion of the array you want to use.\n *\n * var someArray = new Float32Array(1000); // an array with 1000 floats\n * var someSubArray = new Float32Array(someArray.buffer, offsetInBytes, sizeInUnits); // a view into someArray\n *\n * Now you can pass `someSubArray` into setAttribInfoBufferFromArray`\n * @memberOf module:twgl/attributes\n */\nfunction setAttribInfoBufferFromArray(gl, attribInfo, array, offset) {\n array = makeTypedArray(array);\n if (offset !== undefined) {\n gl.bindBuffer(ARRAY_BUFFER$1, attribInfo.buffer);\n gl.bufferSubData(ARRAY_BUFFER$1, offset, array);\n } else {\n setBufferFromTypedArray(gl, ARRAY_BUFFER$1, attribInfo.buffer, array, attribInfo.drawType);\n }\n}\n\nfunction getBytesPerValueForGLType(gl, type) {\n if (type === BYTE$1) return 1; // eslint-disable-line\n if (type === UNSIGNED_BYTE$2) return 1; // eslint-disable-line\n if (type === SHORT$1) return 2; // eslint-disable-line\n if (type === UNSIGNED_SHORT$2) return 2; // eslint-disable-line\n if (type === INT$2) return 4; // eslint-disable-line\n if (type === UNSIGNED_INT$2) return 4; // eslint-disable-line\n if (type === FLOAT$2) return 4; // eslint-disable-line\n return 0;\n}\n\n// Tries to get the number of elements from a set of arrays.\nconst positionKeys = ['position', 'positions', 'a_position'];\nfunction getNumElementsFromNonIndexedArrays(arrays) {\n let key;\n let ii;\n for (ii = 0; ii < positionKeys.length; ++ii) {\n key = positionKeys[ii];\n if (key in arrays) {\n break;\n }\n }\n if (ii === positionKeys.length) {\n key = Object.keys(arrays)[0];\n }\n const array = arrays[key];\n const length = getArray$1(array).length;\n if (length === undefined) {\n return 1; // There's no arrays\n }\n const numComponents = getNumComponents$1(array, key);\n const numElements = length / numComponents;\n if (length % numComponents > 0) {\n throw new Error(`numComponents ${numComponents} not correct for length ${length}`);\n }\n return numElements;\n}\n\nfunction getNumElementsFromAttributes(gl, attribs) {\n let key;\n let ii;\n for (ii = 0; ii < positionKeys.length; ++ii) {\n key = positionKeys[ii];\n if (key in attribs) {\n break;\n }\n key = defaults$2.attribPrefix + key;\n if (key in attribs) {\n break;\n }\n }\n if (ii === positionKeys.length) {\n key = Object.keys(attribs)[0];\n }\n const attrib = attribs[key];\n if (!attrib.buffer) {\n return 1; // There's no buffer\n }\n gl.bindBuffer(ARRAY_BUFFER$1, attrib.buffer);\n const numBytes = gl.getBufferParameter(ARRAY_BUFFER$1, BUFFER_SIZE);\n gl.bindBuffer(ARRAY_BUFFER$1, null);\n\n const bytesPerValue = getBytesPerValueForGLType(gl, attrib.type);\n const totalElements = numBytes / bytesPerValue;\n const numComponents = attrib.numComponents || attrib.size;\n // TODO: check stride\n const numElements = totalElements / numComponents;\n if (numElements % 1 !== 0) {\n throw new Error(`numComponents ${numComponents} not correct for length ${length}`);\n }\n return numElements;\n}\n\n/**\n * @typedef {Object} BufferInfo\n * @property {number} numElements The number of elements to pass to `gl.drawArrays` or `gl.drawElements`.\n * @property {number} [elementType] The type of indices `UNSIGNED_BYTE`, `UNSIGNED_SHORT` etc..\n * @property {WebGLBuffer} [indices] The indices `ELEMENT_ARRAY_BUFFER` if any indices exist.\n * @property {Object.} [attribs] The attribs appropriate to call `setAttributes`\n * @memberOf module:twgl\n */\n\n/**\n * Creates a BufferInfo from an object of arrays.\n *\n * This can be passed to {@link module:twgl.setBuffersAndAttributes} and to\n * {@link module:twgl:drawBufferInfo}.\n *\n * Given an object like\n *\n * var arrays = {\n * position: { numComponents: 3, data: [0, 0, 0, 10, 0, 0, 0, 10, 0, 10, 10, 0], },\n * texcoord: { numComponents: 2, data: [0, 0, 0, 1, 1, 0, 1, 1], },\n * normal: { numComponents: 3, data: [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1], },\n * indices: { numComponents: 3, data: [0, 1, 2, 1, 2, 3], },\n * };\n *\n * Creates an BufferInfo like this\n *\n * bufferInfo = {\n * numElements: 4, // or whatever the number of elements is\n * indices: WebGLBuffer, // this property will not exist if there are no indices\n * attribs: {\n * position: { buffer: WebGLBuffer, numComponents: 3, },\n * normal: { buffer: WebGLBuffer, numComponents: 3, },\n * texcoord: { buffer: WebGLBuffer, numComponents: 2, },\n * },\n * };\n *\n * The properties of arrays can be JavaScript arrays in which case the number of components\n * will be guessed.\n *\n * var arrays = {\n * position: [0, 0, 0, 10, 0, 0, 0, 10, 0, 10, 10, 0],\n * texcoord: [0, 0, 0, 1, 1, 0, 1, 1],\n * normal: [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1],\n * indices: [0, 1, 2, 1, 2, 3],\n * };\n *\n * They can also be TypedArrays\n *\n * var arrays = {\n * position: new Float32Array([0, 0, 0, 10, 0, 0, 0, 10, 0, 10, 10, 0]),\n * texcoord: new Float32Array([0, 0, 0, 1, 1, 0, 1, 1]),\n * normal: new Float32Array([0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1]),\n * indices: new Uint16Array([0, 1, 2, 1, 2, 3]),\n * };\n *\n * Or AugmentedTypedArrays\n *\n * var positions = createAugmentedTypedArray(3, 4);\n * var texcoords = createAugmentedTypedArray(2, 4);\n * var normals = createAugmentedTypedArray(3, 4);\n * var indices = createAugmentedTypedArray(3, 2, Uint16Array);\n *\n * positions.push([0, 0, 0, 10, 0, 0, 0, 10, 0, 10, 10, 0]);\n * texcoords.push([0, 0, 0, 1, 1, 0, 1, 1]);\n * normals.push([0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1]);\n * indices.push([0, 1, 2, 1, 2, 3]);\n *\n * var arrays = {\n * position: positions,\n * texcoord: texcoords,\n * normal: normals,\n * indices: indices,\n * };\n *\n * For the last example it is equivalent to\n *\n * var bufferInfo = {\n * attribs: {\n * position: { numComponents: 3, buffer: gl.createBuffer(), },\n * texcoord: { numComponents: 2, buffer: gl.createBuffer(), },\n * normal: { numComponents: 3, buffer: gl.createBuffer(), },\n * },\n * indices: gl.createBuffer(),\n * numElements: 6,\n * };\n *\n * gl.bindBuffer(gl.ARRAY_BUFFER, bufferInfo.attribs.position.buffer);\n * gl.bufferData(gl.ARRAY_BUFFER, arrays.position, gl.STATIC_DRAW);\n * gl.bindBuffer(gl.ARRAY_BUFFER, bufferInfo.attribs.texcoord.buffer);\n * gl.bufferData(gl.ARRAY_BUFFER, arrays.texcoord, gl.STATIC_DRAW);\n * gl.bindBuffer(gl.ARRAY_BUFFER, bufferInfo.attribs.normal.buffer);\n * gl.bufferData(gl.ARRAY_BUFFER, arrays.normal, gl.STATIC_DRAW);\n * gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufferInfo.indices);\n * gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, arrays.indices, gl.STATIC_DRAW);\n *\n * @param {WebGLRenderingContext} gl A WebGLRenderingContext\n * @param {module:twgl.Arrays} arrays Your data\n * @param {module:twgl.BufferInfo} [srcBufferInfo] An existing\n * buffer info to start from. WebGLBuffers etc specified\n * in the srcBufferInfo will be used in a new BufferInfo\n * with any arrays specified overriding the ones in\n * srcBufferInfo.\n * @return {module:twgl.BufferInfo} A BufferInfo\n * @memberOf module:twgl/attributes\n */\nfunction createBufferInfoFromArrays(gl, arrays, srcBufferInfo) {\n const newAttribs = createAttribsFromArrays(gl, arrays);\n const bufferInfo = Object.assign({}, srcBufferInfo ? srcBufferInfo : {});\n bufferInfo.attribs = Object.assign({}, srcBufferInfo ? srcBufferInfo.attribs : {}, newAttribs);\n const indices = arrays.indices;\n if (indices) {\n const newIndices = makeTypedArray(indices, \"indices\");\n bufferInfo.indices = createBufferFromTypedArray(gl, newIndices, ELEMENT_ARRAY_BUFFER$2);\n bufferInfo.numElements = newIndices.length;\n bufferInfo.elementType = getGLTypeForTypedArray(newIndices);\n } else if (!bufferInfo.numElements) {\n bufferInfo.numElements = getNumElementsFromAttributes(gl, bufferInfo.attribs);\n }\n\n return bufferInfo;\n}\n\n/**\n * Creates a buffer from an array, typed array, or array spec\n *\n * Given something like this\n *\n * [1, 2, 3],\n *\n * or\n *\n * new Uint16Array([1,2,3]);\n *\n * or\n *\n * {\n * data: [1, 2, 3],\n * type: Uint8Array,\n * }\n *\n * returns a WebGLBuffer that contains the given data.\n *\n * @param {WebGLRenderingContext} gl A WebGLRenderingContext.\n * @param {module:twgl.ArraySpec} array an array, typed array, or array spec.\n * @param {string} arrayName name of array. Used to guess the type if type can not be derived otherwise.\n * @return {WebGLBuffer} a WebGLBuffer containing the data in array.\n * @memberOf module:twgl/attributes\n */\nfunction createBufferFromArray(gl, array, arrayName) {\n const type = arrayName === \"indices\" ? ELEMENT_ARRAY_BUFFER$2 : ARRAY_BUFFER$1;\n const typedArray = makeTypedArray(array, arrayName);\n return createBufferFromTypedArray(gl, typedArray, type);\n}\n\n/**\n * Creates buffers from arrays or typed arrays\n *\n * Given something like this\n *\n * var arrays = {\n * positions: [1, 2, 3],\n * normals: [0, 0, 1],\n * }\n *\n * returns something like\n *\n * buffers = {\n * positions: WebGLBuffer,\n * normals: WebGLBuffer,\n * }\n *\n * If the buffer is named 'indices' it will be made an ELEMENT_ARRAY_BUFFER.\n *\n * @param {WebGLRenderingContext} gl A WebGLRenderingContext.\n * @param {module:twgl.Arrays} arrays\n * @return {Object} returns an object with one WebGLBuffer per array\n * @memberOf module:twgl/attributes\n */\nfunction createBuffersFromArrays(gl, arrays) {\n const buffers = { };\n Object.keys(arrays).forEach(function(key) {\n buffers[key] = createBufferFromArray(gl, arrays[key], key);\n });\n\n // Ugh!\n if (arrays.indices) {\n buffers.numElements = arrays.indices.length;\n buffers.elementType = getGLTypeForTypedArray(makeTypedArray(arrays.indices));\n } else {\n buffers.numElements = getNumElementsFromNonIndexedArrays(arrays);\n }\n\n return buffers;\n}\n\nvar attributes = /*#__PURE__*/Object.freeze({\n __proto__: null,\n createAttribsFromArrays: createAttribsFromArrays,\n createBuffersFromArrays: createBuffersFromArrays,\n createBufferFromArray: createBufferFromArray,\n createBufferFromTypedArray: createBufferFromTypedArray,\n createBufferInfoFromArrays: createBufferInfoFromArrays,\n setAttribInfoBufferFromArray: setAttribInfoBufferFromArray,\n setAttributePrefix: setAttributePrefix,\n setAttributeDefaults_: setDefaults$2,\n getNumComponents_: getNumComponents$1,\n getArray_: getArray$1\n});\n\n/*\n * Copyright 2019 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\nconst getArray = getArray$1; // eslint-disable-line\nconst getNumComponents = getNumComponents$1; // eslint-disable-line\n\n/**\n * @typedef {(Int8Array|Uint8Array|Int16Array|Uint16Array|Int32Array|Uint32Array|Float32Array)} TypedArray\n */\n\n/**\n * Add `push` to a typed array. It just keeps a 'cursor'\n * and allows use to `push` values into the array so we\n * don't have to manually compute offsets\n * @param {TypedArray} typedArray TypedArray to augment\n * @param {number} numComponents number of components.\n * @private\n */\nfunction augmentTypedArray(typedArray, numComponents) {\n let cursor = 0;\n typedArray.push = function() {\n for (let ii = 0; ii < arguments.length; ++ii) {\n const value = arguments[ii];\n if (value instanceof Array || isArrayBuffer$1(value)) {\n for (let jj = 0; jj < value.length; ++jj) {\n typedArray[cursor++] = value[jj];\n }\n } else {\n typedArray[cursor++] = value;\n }\n }\n };\n typedArray.reset = function(opt_index) {\n cursor = opt_index || 0;\n };\n typedArray.numComponents = numComponents;\n Object.defineProperty(typedArray, 'numElements', {\n get: function() {\n return this.length / this.numComponents | 0;\n },\n });\n return typedArray;\n}\n\n/**\n * creates a typed array with a `push` function attached\n * so that you can easily *push* values.\n *\n * `push` can take multiple arguments. If an argument is an array each element\n * of the array will be added to the typed array.\n *\n * Example:\n *\n * const array = createAugmentedTypedArray(3, 2); // creates a Float32Array with 6 values\n * array.push(1, 2, 3);\n * array.push([4, 5, 6]);\n * // array now contains [1, 2, 3, 4, 5, 6]\n *\n * Also has `numComponents` and `numElements` properties.\n *\n * @param {number} numComponents number of components\n * @param {number} numElements number of elements. The total size of the array will be `numComponents * numElements`.\n * @param {constructor} opt_type A constructor for the type. Default = `Float32Array`.\n * @return {ArrayBufferView} A typed array.\n * @memberOf module:twgl/primitives\n */\nfunction createAugmentedTypedArray(numComponents, numElements, opt_type) {\n const Type = opt_type || Float32Array;\n return augmentTypedArray(new Type(numComponents * numElements), numComponents);\n}\n\nfunction allButIndices(name) {\n return name !== \"indices\";\n}\n\n/**\n * Given indexed vertices creates a new set of vertices un-indexed by expanding the indexed vertices.\n * @param {Object.} vertices The indexed vertices to deindex\n * @return {Object.} The deindexed vertices\n * @memberOf module:twgl/primitives\n */\nfunction deindexVertices(vertices) {\n const indices = vertices.indices;\n const newVertices = {};\n const numElements = indices.length;\n\n function expandToUnindexed(channel) {\n const srcBuffer = vertices[channel];\n const numComponents = srcBuffer.numComponents;\n const dstBuffer = createAugmentedTypedArray(numComponents, numElements, srcBuffer.constructor);\n for (let ii = 0; ii < numElements; ++ii) {\n const ndx = indices[ii];\n const offset = ndx * numComponents;\n for (let jj = 0; jj < numComponents; ++jj) {\n dstBuffer.push(srcBuffer[offset + jj]);\n }\n }\n newVertices[channel] = dstBuffer;\n }\n\n Object.keys(vertices).filter(allButIndices).forEach(expandToUnindexed);\n\n return newVertices;\n}\n\n/**\n * flattens the normals of deindexed vertices in place.\n * @param {Object.} vertices The deindexed vertices who's normals to flatten\n * @return {Object.} The flattened vertices (same as was passed in)\n * @memberOf module:twgl/primitives\n */\nfunction flattenNormals(vertices) {\n if (vertices.indices) {\n throw new Error('can not flatten normals of indexed vertices. deindex them first');\n }\n\n const normals = vertices.normal;\n const numNormals = normals.length;\n for (let ii = 0; ii < numNormals; ii += 9) {\n // pull out the 3 normals for this triangle\n const nax = normals[ii + 0];\n const nay = normals[ii + 1];\n const naz = normals[ii + 2];\n\n const nbx = normals[ii + 3];\n const nby = normals[ii + 4];\n const nbz = normals[ii + 5];\n\n const ncx = normals[ii + 6];\n const ncy = normals[ii + 7];\n const ncz = normals[ii + 8];\n\n // add them\n let nx = nax + nbx + ncx;\n let ny = nay + nby + ncy;\n let nz = naz + nbz + ncz;\n\n // normalize them\n const length = Math.sqrt(nx * nx + ny * ny + nz * nz);\n\n nx /= length;\n ny /= length;\n nz /= length;\n\n // copy them back in\n normals[ii + 0] = nx;\n normals[ii + 1] = ny;\n normals[ii + 2] = nz;\n\n normals[ii + 3] = nx;\n normals[ii + 4] = ny;\n normals[ii + 5] = nz;\n\n normals[ii + 6] = nx;\n normals[ii + 7] = ny;\n normals[ii + 8] = nz;\n }\n\n return vertices;\n}\n\nfunction applyFuncToV3Array(array, matrix, fn) {\n const len = array.length;\n const tmp = new Float32Array(3);\n for (let ii = 0; ii < len; ii += 3) {\n fn(matrix, [array[ii], array[ii + 1], array[ii + 2]], tmp);\n array[ii ] = tmp[0];\n array[ii + 1] = tmp[1];\n array[ii + 2] = tmp[2];\n }\n}\n\nfunction transformNormal(mi, v, dst) {\n dst = dst || create$1();\n const v0 = v[0];\n const v1 = v[1];\n const v2 = v[2];\n\n dst[0] = v0 * mi[0 * 4 + 0] + v1 * mi[0 * 4 + 1] + v2 * mi[0 * 4 + 2];\n dst[1] = v0 * mi[1 * 4 + 0] + v1 * mi[1 * 4 + 1] + v2 * mi[1 * 4 + 2];\n dst[2] = v0 * mi[2 * 4 + 0] + v1 * mi[2 * 4 + 1] + v2 * mi[2 * 4 + 2];\n\n return dst;\n}\n\n/**\n * Reorients directions by the given matrix..\n * @param {(number[]|TypedArray)} array The array. Assumes value floats per element.\n * @param {module:twgl/m4.Mat4} matrix A matrix to multiply by.\n * @return {(number[]|TypedArray)} the same array that was passed in\n * @memberOf module:twgl/primitives\n */\nfunction reorientDirections(array, matrix) {\n applyFuncToV3Array(array, matrix, transformDirection);\n return array;\n}\n\n/**\n * Reorients normals by the inverse-transpose of the given\n * matrix..\n * @param {(number[]|TypedArray)} array The array. Assumes value floats per element.\n * @param {module:twgl/m4.Mat4} matrix A matrix to multiply by.\n * @return {(number[]|TypedArray)} the same array that was passed in\n * @memberOf module:twgl/primitives\n */\nfunction reorientNormals(array, matrix) {\n applyFuncToV3Array(array, inverse(matrix), transformNormal);\n return array;\n}\n\n/**\n * Reorients positions by the given matrix. In other words, it\n * multiplies each vertex by the given matrix.\n * @param {(number[]|TypedArray)} array The array. Assumes value floats per element.\n * @param {module:twgl/m4.Mat4} matrix A matrix to multiply by.\n * @return {(number[]|TypedArray)} the same array that was passed in\n * @memberOf module:twgl/primitives\n */\nfunction reorientPositions(array, matrix) {\n applyFuncToV3Array(array, matrix, transformPoint);\n return array;\n}\n\n/**\n * @typedef {(number[]|TypedArray)} NativeArrayOrTypedArray\n */\n\n/**\n * Reorients arrays by the given matrix. Assumes arrays have\n * names that contains 'pos' could be reoriented as positions,\n * 'binorm' or 'tan' as directions, and 'norm' as normals.\n *\n * @param {Object.} arrays The vertices to reorient\n * @param {module:twgl/m4.Mat4} matrix matrix to reorient by.\n * @return {Object.} same arrays that were passed in.\n * @memberOf module:twgl/primitives\n */\nfunction reorientVertices(arrays, matrix) {\n Object.keys(arrays).forEach(function(name) {\n const array = arrays[name];\n if (name.indexOf(\"pos\") >= 0) {\n reorientPositions(array, matrix);\n } else if (name.indexOf(\"tan\") >= 0 || name.indexOf(\"binorm\") >= 0) {\n reorientDirections(array, matrix);\n } else if (name.indexOf(\"norm\") >= 0) {\n reorientNormals(array, matrix);\n }\n });\n return arrays;\n}\n\n/**\n * Creates XY quad BufferInfo\n *\n * The default with no parameters will return a 2x2 quad with values from -1 to +1.\n * If you want a unit quad with that goes from 0 to 1 you'd call it with\n *\n * twgl.primitives.createXYQuadBufferInfo(gl, 1, 0.5, 0.5);\n *\n * If you want a unit quad centered above 0,0 you'd call it with\n *\n * twgl.primitives.createXYQuadBufferInfo(gl, 1, 0, 0.5);\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} [size] the size across the quad. Defaults to 2 which means vertices will go from -1 to +1\n * @param {number} [xOffset] the amount to offset the quad in X\n * @param {number} [yOffset] the amount to offset the quad in Y\n * @return {Object.} the created XY Quad BufferInfo\n * @memberOf module:twgl/primitives\n * @function createXYQuadBuffers\n */\n\n/**\n * Creates XY quad Buffers\n *\n * The default with no parameters will return a 2x2 quad with values from -1 to +1.\n * If you want a unit quad with that goes from 0 to 1 you'd call it with\n *\n * twgl.primitives.createXYQuadBufferInfo(gl, 1, 0.5, 0.5);\n *\n * If you want a unit quad centered above 0,0 you'd call it with\n *\n * twgl.primitives.createXYQuadBufferInfo(gl, 1, 0, 0.5);\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} [size] the size across the quad. Defaults to 2 which means vertices will go from -1 to +1\n * @param {number} [xOffset] the amount to offset the quad in X\n * @param {number} [yOffset] the amount to offset the quad in Y\n * @return {module:twgl.BufferInfo} the created XY Quad buffers\n * @memberOf module:twgl/primitives\n * @function createXYQuadBufferInfo\n */\n\n/**\n * Creates XY quad vertices\n *\n * The default with no parameters will return a 2x2 quad with values from -1 to +1.\n * If you want a unit quad with that goes from 0 to 1 you'd call it with\n *\n * twgl.primitives.createXYQuadVertices(1, 0.5, 0.5);\n *\n * If you want a unit quad centered above 0,0 you'd call it with\n *\n * twgl.primitives.createXYQuadVertices(1, 0, 0.5);\n *\n * @param {number} [size] the size across the quad. Defaults to 2 which means vertices will go from -1 to +1\n * @param {number} [xOffset] the amount to offset the quad in X\n * @param {number} [yOffset] the amount to offset the quad in Y\n * @return {Object.} the created XY Quad vertices\n * @memberOf module:twgl/primitives\n */\nfunction createXYQuadVertices(size, xOffset, yOffset) {\n size = size || 2;\n xOffset = xOffset || 0;\n yOffset = yOffset || 0;\n size *= 0.5;\n return {\n position: {\n numComponents: 2,\n data: [\n xOffset + -1 * size, yOffset + -1 * size,\n xOffset + 1 * size, yOffset + -1 * size,\n xOffset + -1 * size, yOffset + 1 * size,\n xOffset + 1 * size, yOffset + 1 * size,\n ],\n },\n normal: [\n 0, 0, 1,\n 0, 0, 1,\n 0, 0, 1,\n 0, 0, 1,\n ],\n texcoord: [\n 0, 0,\n 1, 0,\n 0, 1,\n 1, 1,\n ],\n indices: [ 0, 1, 2, 2, 1, 3 ],\n };\n}\n\n/**\n * Creates XZ plane BufferInfo.\n *\n * The created plane has position, normal, and texcoord data\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} [width] Width of the plane. Default = 1\n * @param {number} [depth] Depth of the plane. Default = 1\n * @param {number} [subdivisionsWidth] Number of steps across the plane. Default = 1\n * @param {number} [subdivisionsDepth] Number of steps down the plane. Default = 1\n * @param {module:twgl/m4.Mat4} [matrix] A matrix by which to multiply all the vertices.\n * @return {module:twgl.BufferInfo} The created plane BufferInfo.\n * @memberOf module:twgl/primitives\n * @function createPlaneBufferInfo\n */\n\n/**\n * Creates XZ plane buffers.\n *\n * The created plane has position, normal, and texcoord data\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} [width] Width of the plane. Default = 1\n * @param {number} [depth] Depth of the plane. Default = 1\n * @param {number} [subdivisionsWidth] Number of steps across the plane. Default = 1\n * @param {number} [subdivisionsDepth] Number of steps down the plane. Default = 1\n * @param {module:twgl/m4.Mat4} [matrix] A matrix by which to multiply all the vertices.\n * @return {Object.} The created plane buffers.\n * @memberOf module:twgl/primitives\n * @function createPlaneBuffers\n */\n\n/**\n * Creates XZ plane vertices.\n *\n * The created plane has position, normal, and texcoord data\n *\n * @param {number} [width] Width of the plane. Default = 1\n * @param {number} [depth] Depth of the plane. Default = 1\n * @param {number} [subdivisionsWidth] Number of steps across the plane. Default = 1\n * @param {number} [subdivisionsDepth] Number of steps down the plane. Default = 1\n * @param {module:twgl/m4.Mat4} [matrix] A matrix by which to multiply all the vertices.\n * @return {Object.} The created plane vertices.\n * @memberOf module:twgl/primitives\n */\nfunction createPlaneVertices(\n width,\n depth,\n subdivisionsWidth,\n subdivisionsDepth,\n matrix) {\n width = width || 1;\n depth = depth || 1;\n subdivisionsWidth = subdivisionsWidth || 1;\n subdivisionsDepth = subdivisionsDepth || 1;\n matrix = matrix || identity();\n\n const numVertices = (subdivisionsWidth + 1) * (subdivisionsDepth + 1);\n const positions = createAugmentedTypedArray(3, numVertices);\n const normals = createAugmentedTypedArray(3, numVertices);\n const texcoords = createAugmentedTypedArray(2, numVertices);\n\n for (let z = 0; z <= subdivisionsDepth; z++) {\n for (let x = 0; x <= subdivisionsWidth; x++) {\n const u = x / subdivisionsWidth;\n const v = z / subdivisionsDepth;\n positions.push(\n width * u - width * 0.5,\n 0,\n depth * v - depth * 0.5);\n normals.push(0, 1, 0);\n texcoords.push(u, v);\n }\n }\n\n const numVertsAcross = subdivisionsWidth + 1;\n const indices = createAugmentedTypedArray(\n 3, subdivisionsWidth * subdivisionsDepth * 2, Uint16Array);\n\n for (let z = 0; z < subdivisionsDepth; z++) { // eslint-disable-line\n for (let x = 0; x < subdivisionsWidth; x++) { // eslint-disable-line\n // Make triangle 1 of quad.\n indices.push(\n (z + 0) * numVertsAcross + x,\n (z + 1) * numVertsAcross + x,\n (z + 0) * numVertsAcross + x + 1);\n\n // Make triangle 2 of quad.\n indices.push(\n (z + 1) * numVertsAcross + x,\n (z + 1) * numVertsAcross + x + 1,\n (z + 0) * numVertsAcross + x + 1);\n }\n }\n\n const arrays = reorientVertices({\n position: positions,\n normal: normals,\n texcoord: texcoords,\n indices: indices,\n }, matrix);\n return arrays;\n}\n\n/**\n * Creates sphere BufferInfo.\n *\n * The created sphere has position, normal, and texcoord data\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} radius radius of the sphere.\n * @param {number} subdivisionsAxis number of steps around the sphere.\n * @param {number} subdivisionsHeight number of vertically on the sphere.\n * @param {number} [opt_startLatitudeInRadians] where to start the\n * top of the sphere. Default = 0.\n * @param {number} [opt_endLatitudeInRadians] Where to end the\n * bottom of the sphere. Default = Math.PI.\n * @param {number} [opt_startLongitudeInRadians] where to start\n * wrapping the sphere. Default = 0.\n * @param {number} [opt_endLongitudeInRadians] where to end\n * wrapping the sphere. Default = 2 * Math.PI.\n * @return {module:twgl.BufferInfo} The created sphere BufferInfo.\n * @memberOf module:twgl/primitives\n * @function createSphereBufferInfo\n */\n\n/**\n * Creates sphere buffers.\n *\n * The created sphere has position, normal, and texcoord data\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} radius radius of the sphere.\n * @param {number} subdivisionsAxis number of steps around the sphere.\n * @param {number} subdivisionsHeight number of vertically on the sphere.\n * @param {number} [opt_startLatitudeInRadians] where to start the\n * top of the sphere. Default = 0.\n * @param {number} [opt_endLatitudeInRadians] Where to end the\n * bottom of the sphere. Default = Math.PI.\n * @param {number} [opt_startLongitudeInRadians] where to start\n * wrapping the sphere. Default = 0.\n * @param {number} [opt_endLongitudeInRadians] where to end\n * wrapping the sphere. Default = 2 * Math.PI.\n * @return {Object.} The created sphere buffers.\n * @memberOf module:twgl/primitives\n * @function createSphereBuffers\n */\n\n/**\n * Creates sphere vertices.\n *\n * The created sphere has position, normal, and texcoord data\n *\n * @param {number} radius radius of the sphere.\n * @param {number} subdivisionsAxis number of steps around the sphere.\n * @param {number} subdivisionsHeight number of vertically on the sphere.\n * @param {number} [opt_startLatitudeInRadians] where to start the\n * top of the sphere. Default = 0.\n * @param {number} [opt_endLatitudeInRadians] Where to end the\n * bottom of the sphere. Default = Math.PI.\n * @param {number} [opt_startLongitudeInRadians] where to start\n * wrapping the sphere. Default = 0.\n * @param {number} [opt_endLongitudeInRadians] where to end\n * wrapping the sphere. Default = 2 * Math.PI.\n * @return {Object.} The created sphere vertices.\n * @memberOf module:twgl/primitives\n */\nfunction createSphereVertices(\n radius,\n subdivisionsAxis,\n subdivisionsHeight,\n opt_startLatitudeInRadians,\n opt_endLatitudeInRadians,\n opt_startLongitudeInRadians,\n opt_endLongitudeInRadians) {\n if (subdivisionsAxis <= 0 || subdivisionsHeight <= 0) {\n throw new Error('subdivisionAxis and subdivisionHeight must be > 0');\n }\n\n opt_startLatitudeInRadians = opt_startLatitudeInRadians || 0;\n opt_endLatitudeInRadians = opt_endLatitudeInRadians || Math.PI;\n opt_startLongitudeInRadians = opt_startLongitudeInRadians || 0;\n opt_endLongitudeInRadians = opt_endLongitudeInRadians || (Math.PI * 2);\n\n const latRange = opt_endLatitudeInRadians - opt_startLatitudeInRadians;\n const longRange = opt_endLongitudeInRadians - opt_startLongitudeInRadians;\n\n // We are going to generate our sphere by iterating through its\n // spherical coordinates and generating 2 triangles for each quad on a\n // ring of the sphere.\n const numVertices = (subdivisionsAxis + 1) * (subdivisionsHeight + 1);\n const positions = createAugmentedTypedArray(3, numVertices);\n const normals = createAugmentedTypedArray(3, numVertices);\n const texcoords = createAugmentedTypedArray(2, numVertices);\n\n // Generate the individual vertices in our vertex buffer.\n for (let y = 0; y <= subdivisionsHeight; y++) {\n for (let x = 0; x <= subdivisionsAxis; x++) {\n // Generate a vertex based on its spherical coordinates\n const u = x / subdivisionsAxis;\n const v = y / subdivisionsHeight;\n const theta = longRange * u + opt_startLongitudeInRadians;\n const phi = latRange * v + opt_startLatitudeInRadians;\n const sinTheta = Math.sin(theta);\n const cosTheta = Math.cos(theta);\n const sinPhi = Math.sin(phi);\n const cosPhi = Math.cos(phi);\n const ux = cosTheta * sinPhi;\n const uy = cosPhi;\n const uz = sinTheta * sinPhi;\n positions.push(radius * ux, radius * uy, radius * uz);\n normals.push(ux, uy, uz);\n texcoords.push(1 - u, v);\n }\n }\n\n const numVertsAround = subdivisionsAxis + 1;\n const indices = createAugmentedTypedArray(3, subdivisionsAxis * subdivisionsHeight * 2, Uint16Array);\n for (let x = 0; x < subdivisionsAxis; x++) { // eslint-disable-line\n for (let y = 0; y < subdivisionsHeight; y++) { // eslint-disable-line\n // Make triangle 1 of quad.\n indices.push(\n (y + 0) * numVertsAround + x,\n (y + 0) * numVertsAround + x + 1,\n (y + 1) * numVertsAround + x);\n\n // Make triangle 2 of quad.\n indices.push(\n (y + 1) * numVertsAround + x,\n (y + 0) * numVertsAround + x + 1,\n (y + 1) * numVertsAround + x + 1);\n }\n }\n\n return {\n position: positions,\n normal: normals,\n texcoord: texcoords,\n indices: indices,\n };\n}\n\n/**\n * Array of the indices of corners of each face of a cube.\n * @type {Array.}\n * @private\n */\nconst CUBE_FACE_INDICES = [\n [3, 7, 5, 1], // right\n [6, 2, 0, 4], // left\n [6, 7, 3, 2], // ??\n [0, 1, 5, 4], // ??\n [7, 6, 4, 5], // front\n [2, 3, 1, 0], // back\n];\n\n/**\n * Creates a BufferInfo for a cube.\n *\n * The cube is created around the origin. (-size / 2, size / 2).\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} [size] width, height and depth of the cube.\n * @return {module:twgl.BufferInfo} The created BufferInfo.\n * @memberOf module:twgl/primitives\n * @function createCubeBufferInfo\n */\n\n/**\n * Creates the buffers and indices for a cube.\n *\n * The cube is created around the origin. (-size / 2, size / 2).\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} [size] width, height and depth of the cube.\n * @return {Object.} The created buffers.\n * @memberOf module:twgl/primitives\n * @function createCubeBuffers\n */\n\n/**\n * Creates the vertices and indices for a cube.\n *\n * The cube is created around the origin. (-size / 2, size / 2).\n *\n * @param {number} [size] width, height and depth of the cube.\n * @return {Object.} The created vertices.\n * @memberOf module:twgl/primitives\n */\nfunction createCubeVertices(size) {\n size = size || 1;\n const k = size / 2;\n\n const cornerVertices = [\n [-k, -k, -k],\n [+k, -k, -k],\n [-k, +k, -k],\n [+k, +k, -k],\n [-k, -k, +k],\n [+k, -k, +k],\n [-k, +k, +k],\n [+k, +k, +k],\n ];\n\n const faceNormals = [\n [+1, +0, +0],\n [-1, +0, +0],\n [+0, +1, +0],\n [+0, -1, +0],\n [+0, +0, +1],\n [+0, +0, -1],\n ];\n\n const uvCoords = [\n [1, 0],\n [0, 0],\n [0, 1],\n [1, 1],\n ];\n\n const numVertices = 6 * 4;\n const positions = createAugmentedTypedArray(3, numVertices);\n const normals = createAugmentedTypedArray(3, numVertices);\n const texcoords = createAugmentedTypedArray(2 , numVertices);\n const indices = createAugmentedTypedArray(3, 6 * 2, Uint16Array);\n\n for (let f = 0; f < 6; ++f) {\n const faceIndices = CUBE_FACE_INDICES[f];\n for (let v = 0; v < 4; ++v) {\n const position = cornerVertices[faceIndices[v]];\n const normal = faceNormals[f];\n const uv = uvCoords[v];\n\n // Each face needs all four vertices because the normals and texture\n // coordinates are not all the same.\n positions.push(position);\n normals.push(normal);\n texcoords.push(uv);\n\n }\n // Two triangles make a square face.\n const offset = 4 * f;\n indices.push(offset + 0, offset + 1, offset + 2);\n indices.push(offset + 0, offset + 2, offset + 3);\n }\n\n return {\n position: positions,\n normal: normals,\n texcoord: texcoords,\n indices: indices,\n };\n}\n\n/**\n * Creates a BufferInfo for a truncated cone, which is like a cylinder\n * except that it has different top and bottom radii. A truncated cone\n * can also be used to create cylinders and regular cones. The\n * truncated cone will be created centered about the origin, with the\n * y axis as its vertical axis.\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} bottomRadius Bottom radius of truncated cone.\n * @param {number} topRadius Top radius of truncated cone.\n * @param {number} height Height of truncated cone.\n * @param {number} radialSubdivisions The number of subdivisions around the\n * truncated cone.\n * @param {number} verticalSubdivisions The number of subdivisions down the\n * truncated cone.\n * @param {boolean} [opt_topCap] Create top cap. Default = true.\n * @param {boolean} [opt_bottomCap] Create bottom cap. Default = true.\n * @return {module:twgl.BufferInfo} The created cone BufferInfo.\n * @memberOf module:twgl/primitives\n * @function createTruncatedConeBufferInfo\n */\n\n/**\n * Creates buffers for a truncated cone, which is like a cylinder\n * except that it has different top and bottom radii. A truncated cone\n * can also be used to create cylinders and regular cones. The\n * truncated cone will be created centered about the origin, with the\n * y axis as its vertical axis.\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} bottomRadius Bottom radius of truncated cone.\n * @param {number} topRadius Top radius of truncated cone.\n * @param {number} height Height of truncated cone.\n * @param {number} radialSubdivisions The number of subdivisions around the\n * truncated cone.\n * @param {number} verticalSubdivisions The number of subdivisions down the\n * truncated cone.\n * @param {boolean} [opt_topCap] Create top cap. Default = true.\n * @param {boolean} [opt_bottomCap] Create bottom cap. Default = true.\n * @return {Object.} The created cone buffers.\n * @memberOf module:twgl/primitives\n * @function createTruncatedConeBuffers\n */\n\n/**\n * Creates vertices for a truncated cone, which is like a cylinder\n * except that it has different top and bottom radii. A truncated cone\n * can also be used to create cylinders and regular cones. The\n * truncated cone will be created centered about the origin, with the\n * y axis as its vertical axis. .\n *\n * @param {number} bottomRadius Bottom radius of truncated cone.\n * @param {number} topRadius Top radius of truncated cone.\n * @param {number} height Height of truncated cone.\n * @param {number} radialSubdivisions The number of subdivisions around the\n * truncated cone.\n * @param {number} verticalSubdivisions The number of subdivisions down the\n * truncated cone.\n * @param {boolean} [opt_topCap] Create top cap. Default = true.\n * @param {boolean} [opt_bottomCap] Create bottom cap. Default = true.\n * @return {Object.} The created cone vertices.\n * @memberOf module:twgl/primitives\n */\nfunction createTruncatedConeVertices(\n bottomRadius,\n topRadius,\n height,\n radialSubdivisions,\n verticalSubdivisions,\n opt_topCap,\n opt_bottomCap) {\n if (radialSubdivisions < 3) {\n throw new Error('radialSubdivisions must be 3 or greater');\n }\n\n if (verticalSubdivisions < 1) {\n throw new Error('verticalSubdivisions must be 1 or greater');\n }\n\n const topCap = (opt_topCap === undefined) ? true : opt_topCap;\n const bottomCap = (opt_bottomCap === undefined) ? true : opt_bottomCap;\n\n const extra = (topCap ? 2 : 0) + (bottomCap ? 2 : 0);\n\n const numVertices = (radialSubdivisions + 1) * (verticalSubdivisions + 1 + extra);\n const positions = createAugmentedTypedArray(3, numVertices);\n const normals = createAugmentedTypedArray(3, numVertices);\n const texcoords = createAugmentedTypedArray(2, numVertices);\n const indices = createAugmentedTypedArray(3, radialSubdivisions * (verticalSubdivisions + extra / 2) * 2, Uint16Array);\n\n const vertsAroundEdge = radialSubdivisions + 1;\n\n // The slant of the cone is constant across its surface\n const slant = Math.atan2(bottomRadius - topRadius, height);\n const cosSlant = Math.cos(slant);\n const sinSlant = Math.sin(slant);\n\n const start = topCap ? -2 : 0;\n const end = verticalSubdivisions + (bottomCap ? 2 : 0);\n\n for (let yy = start; yy <= end; ++yy) {\n let v = yy / verticalSubdivisions;\n let y = height * v;\n let ringRadius;\n if (yy < 0) {\n y = 0;\n v = 1;\n ringRadius = bottomRadius;\n } else if (yy > verticalSubdivisions) {\n y = height;\n v = 1;\n ringRadius = topRadius;\n } else {\n ringRadius = bottomRadius +\n (topRadius - bottomRadius) * (yy / verticalSubdivisions);\n }\n if (yy === -2 || yy === verticalSubdivisions + 2) {\n ringRadius = 0;\n v = 0;\n }\n y -= height / 2;\n for (let ii = 0; ii < vertsAroundEdge; ++ii) {\n const sin = Math.sin(ii * Math.PI * 2 / radialSubdivisions);\n const cos = Math.cos(ii * Math.PI * 2 / radialSubdivisions);\n positions.push(sin * ringRadius, y, cos * ringRadius);\n if (yy < 0) {\n normals.push(0, -1, 0);\n } else if (yy > verticalSubdivisions) {\n normals.push(0, 1, 0);\n } else if (ringRadius === 0.0) {\n normals.push(0, 0, 0);\n } else {\n normals.push(sin * cosSlant, sinSlant, cos * cosSlant);\n }\n texcoords.push((ii / radialSubdivisions), 1 - v);\n }\n }\n\n for (let yy = 0; yy < verticalSubdivisions + extra; ++yy) { // eslint-disable-line\n if (yy === 1 && topCap || yy === verticalSubdivisions + extra - 2 && bottomCap) {\n continue;\n }\n for (let ii = 0; ii < radialSubdivisions; ++ii) { // eslint-disable-line\n indices.push(vertsAroundEdge * (yy + 0) + 0 + ii,\n vertsAroundEdge * (yy + 0) + 1 + ii,\n vertsAroundEdge * (yy + 1) + 1 + ii);\n indices.push(vertsAroundEdge * (yy + 0) + 0 + ii,\n vertsAroundEdge * (yy + 1) + 1 + ii,\n vertsAroundEdge * (yy + 1) + 0 + ii);\n }\n }\n\n return {\n position: positions,\n normal: normals,\n texcoord: texcoords,\n indices: indices,\n };\n}\n\n/**\n * Expands RLE data\n * @param {number[]} rleData data in format of run-length, x, y, z, run-length, x, y, z\n * @param {number[]} [padding] value to add each entry with.\n * @return {number[]} the expanded rleData\n * @private\n */\nfunction expandRLEData(rleData, padding) {\n padding = padding || [];\n const data = [];\n for (let ii = 0; ii < rleData.length; ii += 4) {\n const runLength = rleData[ii];\n const element = rleData.slice(ii + 1, ii + 4);\n element.push.apply(element, padding);\n for (let jj = 0; jj < runLength; ++jj) {\n data.push.apply(data, element);\n }\n }\n return data;\n}\n\n/**\n * Creates 3D 'F' BufferInfo.\n * An 'F' is useful because you can easily tell which way it is oriented.\n * The created 'F' has position, normal, texcoord, and color buffers.\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @return {module:twgl.BufferInfo} The created BufferInfo.\n * @memberOf module:twgl/primitives\n * @function create3DFBufferInfo\n */\n\n/**\n * Creates 3D 'F' buffers.\n * An 'F' is useful because you can easily tell which way it is oriented.\n * The created 'F' has position, normal, texcoord, and color buffers.\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @return {Object.} The created buffers.\n * @memberOf module:twgl/primitives\n * @function create3DFBuffers\n */\n\n/**\n * Creates 3D 'F' vertices.\n * An 'F' is useful because you can easily tell which way it is oriented.\n * The created 'F' has position, normal, texcoord, and color arrays.\n *\n * @return {Object.} The created vertices.\n * @memberOf module:twgl/primitives\n */\nfunction create3DFVertices() {\n\n const positions = [\n // left column front\n 0, 0, 0,\n 0, 150, 0,\n 30, 0, 0,\n 0, 150, 0,\n 30, 150, 0,\n 30, 0, 0,\n\n // top rung front\n 30, 0, 0,\n 30, 30, 0,\n 100, 0, 0,\n 30, 30, 0,\n 100, 30, 0,\n 100, 0, 0,\n\n // middle rung front\n 30, 60, 0,\n 30, 90, 0,\n 67, 60, 0,\n 30, 90, 0,\n 67, 90, 0,\n 67, 60, 0,\n\n // left column back\n 0, 0, 30,\n 30, 0, 30,\n 0, 150, 30,\n 0, 150, 30,\n 30, 0, 30,\n 30, 150, 30,\n\n // top rung back\n 30, 0, 30,\n 100, 0, 30,\n 30, 30, 30,\n 30, 30, 30,\n 100, 0, 30,\n 100, 30, 30,\n\n // middle rung back\n 30, 60, 30,\n 67, 60, 30,\n 30, 90, 30,\n 30, 90, 30,\n 67, 60, 30,\n 67, 90, 30,\n\n // top\n 0, 0, 0,\n 100, 0, 0,\n 100, 0, 30,\n 0, 0, 0,\n 100, 0, 30,\n 0, 0, 30,\n\n // top rung front\n 100, 0, 0,\n 100, 30, 0,\n 100, 30, 30,\n 100, 0, 0,\n 100, 30, 30,\n 100, 0, 30,\n\n // under top rung\n 30, 30, 0,\n 30, 30, 30,\n 100, 30, 30,\n 30, 30, 0,\n 100, 30, 30,\n 100, 30, 0,\n\n // between top rung and middle\n 30, 30, 0,\n 30, 60, 30,\n 30, 30, 30,\n 30, 30, 0,\n 30, 60, 0,\n 30, 60, 30,\n\n // top of middle rung\n 30, 60, 0,\n 67, 60, 30,\n 30, 60, 30,\n 30, 60, 0,\n 67, 60, 0,\n 67, 60, 30,\n\n // front of middle rung\n 67, 60, 0,\n 67, 90, 30,\n 67, 60, 30,\n 67, 60, 0,\n 67, 90, 0,\n 67, 90, 30,\n\n // bottom of middle rung.\n 30, 90, 0,\n 30, 90, 30,\n 67, 90, 30,\n 30, 90, 0,\n 67, 90, 30,\n 67, 90, 0,\n\n // front of bottom\n 30, 90, 0,\n 30, 150, 30,\n 30, 90, 30,\n 30, 90, 0,\n 30, 150, 0,\n 30, 150, 30,\n\n // bottom\n 0, 150, 0,\n 0, 150, 30,\n 30, 150, 30,\n 0, 150, 0,\n 30, 150, 30,\n 30, 150, 0,\n\n // left side\n 0, 0, 0,\n 0, 0, 30,\n 0, 150, 30,\n 0, 0, 0,\n 0, 150, 30,\n 0, 150, 0,\n ];\n\n const texcoords = [\n // left column front\n 0.22, 0.19,\n 0.22, 0.79,\n 0.34, 0.19,\n 0.22, 0.79,\n 0.34, 0.79,\n 0.34, 0.19,\n\n // top rung front\n 0.34, 0.19,\n 0.34, 0.31,\n 0.62, 0.19,\n 0.34, 0.31,\n 0.62, 0.31,\n 0.62, 0.19,\n\n // middle rung front\n 0.34, 0.43,\n 0.34, 0.55,\n 0.49, 0.43,\n 0.34, 0.55,\n 0.49, 0.55,\n 0.49, 0.43,\n\n // left column back\n 0, 0,\n 1, 0,\n 0, 1,\n 0, 1,\n 1, 0,\n 1, 1,\n\n // top rung back\n 0, 0,\n 1, 0,\n 0, 1,\n 0, 1,\n 1, 0,\n 1, 1,\n\n // middle rung back\n 0, 0,\n 1, 0,\n 0, 1,\n 0, 1,\n 1, 0,\n 1, 1,\n\n // top\n 0, 0,\n 1, 0,\n 1, 1,\n 0, 0,\n 1, 1,\n 0, 1,\n\n // top rung front\n 0, 0,\n 1, 0,\n 1, 1,\n 0, 0,\n 1, 1,\n 0, 1,\n\n // under top rung\n 0, 0,\n 0, 1,\n 1, 1,\n 0, 0,\n 1, 1,\n 1, 0,\n\n // between top rung and middle\n 0, 0,\n 1, 1,\n 0, 1,\n 0, 0,\n 1, 0,\n 1, 1,\n\n // top of middle rung\n 0, 0,\n 1, 1,\n 0, 1,\n 0, 0,\n 1, 0,\n 1, 1,\n\n // front of middle rung\n 0, 0,\n 1, 1,\n 0, 1,\n 0, 0,\n 1, 0,\n 1, 1,\n\n // bottom of middle rung.\n 0, 0,\n 0, 1,\n 1, 1,\n 0, 0,\n 1, 1,\n 1, 0,\n\n // front of bottom\n 0, 0,\n 1, 1,\n 0, 1,\n 0, 0,\n 1, 0,\n 1, 1,\n\n // bottom\n 0, 0,\n 0, 1,\n 1, 1,\n 0, 0,\n 1, 1,\n 1, 0,\n\n // left side\n 0, 0,\n 0, 1,\n 1, 1,\n 0, 0,\n 1, 1,\n 1, 0,\n ];\n\n const normals = expandRLEData([\n // left column front\n // top rung front\n // middle rung front\n 18, 0, 0, 1,\n\n // left column back\n // top rung back\n // middle rung back\n 18, 0, 0, -1,\n\n // top\n 6, 0, 1, 0,\n\n // top rung front\n 6, 1, 0, 0,\n\n // under top rung\n 6, 0, -1, 0,\n\n // between top rung and middle\n 6, 1, 0, 0,\n\n // top of middle rung\n 6, 0, 1, 0,\n\n // front of middle rung\n 6, 1, 0, 0,\n\n // bottom of middle rung.\n 6, 0, -1, 0,\n\n // front of bottom\n 6, 1, 0, 0,\n\n // bottom\n 6, 0, -1, 0,\n\n // left side\n 6, -1, 0, 0,\n ]);\n\n const colors = expandRLEData([\n // left column front\n // top rung front\n // middle rung front\n 18, 200, 70, 120,\n\n // left column back\n // top rung back\n // middle rung back\n 18, 80, 70, 200,\n\n // top\n 6, 70, 200, 210,\n\n // top rung front\n 6, 200, 200, 70,\n\n // under top rung\n 6, 210, 100, 70,\n\n // between top rung and middle\n 6, 210, 160, 70,\n\n // top of middle rung\n 6, 70, 180, 210,\n\n // front of middle rung\n 6, 100, 70, 210,\n\n // bottom of middle rung.\n 6, 76, 210, 100,\n\n // front of bottom\n 6, 140, 210, 80,\n\n // bottom\n 6, 90, 130, 110,\n\n // left side\n 6, 160, 160, 220,\n ], [255]);\n\n const numVerts = positions.length / 3;\n\n const arrays = {\n position: createAugmentedTypedArray(3, numVerts),\n texcoord: createAugmentedTypedArray(2, numVerts),\n normal: createAugmentedTypedArray(3, numVerts),\n color: createAugmentedTypedArray(4, numVerts, Uint8Array),\n indices: createAugmentedTypedArray(3, numVerts / 3, Uint16Array),\n };\n\n arrays.position.push(positions);\n arrays.texcoord.push(texcoords);\n arrays.normal.push(normals);\n arrays.color.push(colors);\n\n for (let ii = 0; ii < numVerts; ++ii) {\n arrays.indices.push(ii);\n }\n\n return arrays;\n}\n\n/**\n * Creates crescent BufferInfo.\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} verticalRadius The vertical radius of the crescent.\n * @param {number} outerRadius The outer radius of the crescent.\n * @param {number} innerRadius The inner radius of the crescent.\n * @param {number} thickness The thickness of the crescent.\n * @param {number} subdivisionsDown number of steps around the crescent.\n * @param {number} [startOffset] Where to start arc. Default 0.\n * @param {number} [endOffset] Where to end arg. Default 1.\n * @return {module:twgl.BufferInfo} The created BufferInfo.\n * @memberOf module:twgl/primitives\n * @function createCresentBufferInfo\n */\n\n/**\n * Creates crescent buffers.\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} verticalRadius The vertical radius of the crescent.\n * @param {number} outerRadius The outer radius of the crescent.\n * @param {number} innerRadius The inner radius of the crescent.\n * @param {number} thickness The thickness of the crescent.\n * @param {number} subdivisionsDown number of steps around the crescent.\n * @param {number} [startOffset] Where to start arc. Default 0.\n * @param {number} [endOffset] Where to end arg. Default 1.\n * @return {Object.} The created buffers.\n * @memberOf module:twgl/primitives\n * @function createCresentBuffers\n */\n\n/**\n * Creates crescent vertices.\n *\n * @param {number} verticalRadius The vertical radius of the crescent.\n * @param {number} outerRadius The outer radius of the crescent.\n * @param {number} innerRadius The inner radius of the crescent.\n * @param {number} thickness The thickness of the crescent.\n * @param {number} subdivisionsDown number of steps around the crescent.\n * @param {number} [startOffset] Where to start arc. Default 0.\n * @param {number} [endOffset] Where to end arg. Default 1.\n * @return {Object.} The created vertices.\n * @memberOf module:twgl/primitives\n * @function createCresentBuffers\n */\n\n/**\n * Creates crescent BufferInfo.\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} verticalRadius The vertical radius of the crescent.\n * @param {number} outerRadius The outer radius of the crescent.\n * @param {number} innerRadius The inner radius of the crescent.\n * @param {number} thickness The thickness of the crescent.\n * @param {number} subdivisionsDown number of steps around the crescent.\n * @param {number} [startOffset] Where to start arc. Default 0.\n * @param {number} [endOffset] Where to end arg. Default 1.\n * @return {module:twgl.BufferInfo} The created BufferInfo.\n * @memberOf module:twgl/primitives\n * @function createCrescentBufferInfo\n */\n\n/**\n * Creates crescent buffers.\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} verticalRadius The vertical radius of the crescent.\n * @param {number} outerRadius The outer radius of the crescent.\n * @param {number} innerRadius The inner radius of the crescent.\n * @param {number} thickness The thickness of the crescent.\n * @param {number} subdivisionsDown number of steps around the crescent.\n * @param {number} [startOffset] Where to start arc. Default 0.\n * @param {number} [endOffset] Where to end arg. Default 1.\n * @return {Object.} The created buffers.\n * @memberOf module:twgl/primitives\n * @function createCrescentBuffers\n */\n\n/**\n * Creates crescent vertices.\n *\n * @param {number} verticalRadius The vertical radius of the crescent.\n * @param {number} outerRadius The outer radius of the crescent.\n * @param {number} innerRadius The inner radius of the crescent.\n * @param {number} thickness The thickness of the crescent.\n * @param {number} subdivisionsDown number of steps around the crescent.\n * @param {number} [startOffset] Where to start arc. Default 0.\n * @param {number} [endOffset] Where to end arg. Default 1.\n * @return {Object.} The created vertices.\n * @memberOf module:twgl/primitives\n */\n function createCrescentVertices(\n verticalRadius,\n outerRadius,\n innerRadius,\n thickness,\n subdivisionsDown,\n startOffset,\n endOffset) {\n if (subdivisionsDown <= 0) {\n throw new Error('subdivisionDown must be > 0');\n }\n\n startOffset = startOffset || 0;\n endOffset = endOffset || 1;\n\n const subdivisionsThick = 2;\n\n const offsetRange = endOffset - startOffset;\n const numVertices = (subdivisionsDown + 1) * 2 * (2 + subdivisionsThick);\n const positions = createAugmentedTypedArray(3, numVertices);\n const normals = createAugmentedTypedArray(3, numVertices);\n const texcoords = createAugmentedTypedArray(2, numVertices);\n\n function lerp(a, b, s) {\n return a + (b - a) * s;\n }\n\n function createArc(arcRadius, x, normalMult, normalAdd, uMult, uAdd) {\n for (let z = 0; z <= subdivisionsDown; z++) {\n const uBack = x / (subdivisionsThick - 1);\n const v = z / subdivisionsDown;\n const xBack = (uBack - 0.5) * 2;\n const angle = (startOffset + (v * offsetRange)) * Math.PI;\n const s = Math.sin(angle);\n const c = Math.cos(angle);\n const radius = lerp(verticalRadius, arcRadius, s);\n const px = xBack * thickness;\n const py = c * verticalRadius;\n const pz = s * radius;\n positions.push(px, py, pz);\n const n = add(multiply$1([0, s, c], normalMult), normalAdd);\n normals.push(n);\n texcoords.push(uBack * uMult + uAdd, v);\n }\n }\n\n // Generate the individual vertices in our vertex buffer.\n for (let x = 0; x < subdivisionsThick; x++) {\n const uBack = (x / (subdivisionsThick - 1) - 0.5) * 2;\n createArc(outerRadius, x, [1, 1, 1], [0, 0, 0], 1, 0);\n createArc(outerRadius, x, [0, 0, 0], [uBack, 0, 0], 0, 0);\n createArc(innerRadius, x, [1, 1, 1], [0, 0, 0], 1, 0);\n createArc(innerRadius, x, [0, 0, 0], [uBack, 0, 0], 0, 1);\n }\n\n // Do outer surface.\n const indices = createAugmentedTypedArray(3, (subdivisionsDown * 2) * (2 + subdivisionsThick), Uint16Array);\n\n function createSurface(leftArcOffset, rightArcOffset) {\n for (let z = 0; z < subdivisionsDown; ++z) {\n // Make triangle 1 of quad.\n indices.push(\n leftArcOffset + z + 0,\n leftArcOffset + z + 1,\n rightArcOffset + z + 0);\n\n // Make triangle 2 of quad.\n indices.push(\n leftArcOffset + z + 1,\n rightArcOffset + z + 1,\n rightArcOffset + z + 0);\n }\n }\n\n const numVerticesDown = subdivisionsDown + 1;\n // front\n createSurface(numVerticesDown * 0, numVerticesDown * 4);\n // right\n createSurface(numVerticesDown * 5, numVerticesDown * 7);\n // back\n createSurface(numVerticesDown * 6, numVerticesDown * 2);\n // left\n createSurface(numVerticesDown * 3, numVerticesDown * 1);\n\n return {\n position: positions,\n normal: normals,\n texcoord: texcoords,\n indices: indices,\n };\n}\n\n/**\n * Creates cylinder BufferInfo. The cylinder will be created around the origin\n * along the y-axis.\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} radius Radius of cylinder.\n * @param {number} height Height of cylinder.\n * @param {number} radialSubdivisions The number of subdivisions around the cylinder.\n * @param {number} verticalSubdivisions The number of subdivisions down the cylinder.\n * @param {boolean} [topCap] Create top cap. Default = true.\n * @param {boolean} [bottomCap] Create bottom cap. Default = true.\n * @return {module:twgl.BufferInfo} The created BufferInfo.\n * @memberOf module:twgl/primitives\n * @function createCylinderBufferInfo\n */\n\n /**\n * Creates cylinder buffers. The cylinder will be created around the origin\n * along the y-axis.\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} radius Radius of cylinder.\n * @param {number} height Height of cylinder.\n * @param {number} radialSubdivisions The number of subdivisions around the cylinder.\n * @param {number} verticalSubdivisions The number of subdivisions down the cylinder.\n * @param {boolean} [topCap] Create top cap. Default = true.\n * @param {boolean} [bottomCap] Create bottom cap. Default = true.\n * @return {Object.} The created buffers.\n * @memberOf module:twgl/primitives\n * @function createCylinderBuffers\n */\n\n /**\n * Creates cylinder vertices. The cylinder will be created around the origin\n * along the y-axis.\n *\n * @param {number} radius Radius of cylinder.\n * @param {number} height Height of cylinder.\n * @param {number} radialSubdivisions The number of subdivisions around the cylinder.\n * @param {number} verticalSubdivisions The number of subdivisions down the cylinder.\n * @param {boolean} [topCap] Create top cap. Default = true.\n * @param {boolean} [bottomCap] Create bottom cap. Default = true.\n * @return {Object.} The created vertices.\n * @memberOf module:twgl/primitives\n */\nfunction createCylinderVertices(\n radius,\n height,\n radialSubdivisions,\n verticalSubdivisions,\n topCap,\n bottomCap) {\n return createTruncatedConeVertices(\n radius,\n radius,\n height,\n radialSubdivisions,\n verticalSubdivisions,\n topCap,\n bottomCap);\n}\n\n/**\n * Creates BufferInfo for a torus\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} radius radius of center of torus circle.\n * @param {number} thickness radius of torus ring.\n * @param {number} radialSubdivisions The number of subdivisions around the torus.\n * @param {number} bodySubdivisions The number of subdivisions around the body torus.\n * @param {boolean} [startAngle] start angle in radians. Default = 0.\n * @param {boolean} [endAngle] end angle in radians. Default = Math.PI * 2.\n * @return {module:twgl.BufferInfo} The created BufferInfo.\n * @memberOf module:twgl/primitives\n * @function createTorusBufferInfo\n */\n\n/**\n * Creates buffers for a torus\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} radius radius of center of torus circle.\n * @param {number} thickness radius of torus ring.\n * @param {number} radialSubdivisions The number of subdivisions around the torus.\n * @param {number} bodySubdivisions The number of subdivisions around the body torus.\n * @param {boolean} [startAngle] start angle in radians. Default = 0.\n * @param {boolean} [endAngle] end angle in radians. Default = Math.PI * 2.\n * @return {Object.} The created buffers.\n * @memberOf module:twgl/primitives\n * @function createTorusBuffers\n */\n\n/**\n * Creates vertices for a torus\n *\n * @param {number} radius radius of center of torus circle.\n * @param {number} thickness radius of torus ring.\n * @param {number} radialSubdivisions The number of subdivisions around the torus.\n * @param {number} bodySubdivisions The number of subdivisions around the body torus.\n * @param {boolean} [startAngle] start angle in radians. Default = 0.\n * @param {boolean} [endAngle] end angle in radians. Default = Math.PI * 2.\n * @return {Object.} The created vertices.\n * @memberOf module:twgl/primitives\n */\nfunction createTorusVertices(\n radius,\n thickness,\n radialSubdivisions,\n bodySubdivisions,\n startAngle,\n endAngle) {\n if (radialSubdivisions < 3) {\n throw new Error('radialSubdivisions must be 3 or greater');\n }\n\n if (bodySubdivisions < 3) {\n throw new Error('verticalSubdivisions must be 3 or greater');\n }\n\n startAngle = startAngle || 0;\n endAngle = endAngle || Math.PI * 2;\n const range = endAngle - startAngle;\n\n const radialParts = radialSubdivisions + 1;\n const bodyParts = bodySubdivisions + 1;\n const numVertices = radialParts * bodyParts;\n const positions = createAugmentedTypedArray(3, numVertices);\n const normals = createAugmentedTypedArray(3, numVertices);\n const texcoords = createAugmentedTypedArray(2, numVertices);\n const indices = createAugmentedTypedArray(3, (radialSubdivisions) * (bodySubdivisions) * 2, Uint16Array);\n\n for (let slice = 0; slice < bodyParts; ++slice) {\n const v = slice / bodySubdivisions;\n const sliceAngle = v * Math.PI * 2;\n const sliceSin = Math.sin(sliceAngle);\n const ringRadius = radius + sliceSin * thickness;\n const ny = Math.cos(sliceAngle);\n const y = ny * thickness;\n for (let ring = 0; ring < radialParts; ++ring) {\n const u = ring / radialSubdivisions;\n const ringAngle = startAngle + u * range;\n const xSin = Math.sin(ringAngle);\n const zCos = Math.cos(ringAngle);\n const x = xSin * ringRadius;\n const z = zCos * ringRadius;\n const nx = xSin * sliceSin;\n const nz = zCos * sliceSin;\n positions.push(x, y, z);\n normals.push(nx, ny, nz);\n texcoords.push(u, 1 - v);\n }\n }\n\n for (let slice = 0; slice < bodySubdivisions; ++slice) { // eslint-disable-line\n for (let ring = 0; ring < radialSubdivisions; ++ring) { // eslint-disable-line\n const nextRingIndex = 1 + ring;\n const nextSliceIndex = 1 + slice;\n indices.push(radialParts * slice + ring,\n radialParts * nextSliceIndex + ring,\n radialParts * slice + nextRingIndex);\n indices.push(radialParts * nextSliceIndex + ring,\n radialParts * nextSliceIndex + nextRingIndex,\n radialParts * slice + nextRingIndex);\n }\n }\n\n return {\n position: positions,\n normal: normals,\n texcoord: texcoords,\n indices: indices,\n };\n}\n\n\n/**\n * Creates a disc BufferInfo. The disc will be in the xz plane, centered at\n * the origin. When creating, at least 3 divisions, or pie\n * pieces, need to be specified, otherwise the triangles making\n * up the disc will be degenerate. You can also specify the\n * number of radial pieces `stacks`. A value of 1 for\n * stacks will give you a simple disc of pie pieces. If you\n * want to create an annulus you can set `innerRadius` to a\n * value > 0. Finally, `stackPower` allows you to have the widths\n * increase or decrease as you move away from the center. This\n * is particularly useful when using the disc as a ground plane\n * with a fixed camera such that you don't need the resolution\n * of small triangles near the perimeter. For example, a value\n * of 2 will produce stacks whose outside radius increases with\n * the square of the stack index. A value of 1 will give uniform\n * stacks.\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} radius Radius of the ground plane.\n * @param {number} divisions Number of triangles in the ground plane (at least 3).\n * @param {number} [stacks] Number of radial divisions (default=1).\n * @param {number} [innerRadius] Default 0.\n * @param {number} [stackPower] Power to raise stack size to for decreasing width.\n * @return {module:twgl.BufferInfo} The created BufferInfo.\n * @memberOf module:twgl/primitives\n * @function createDiscBufferInfo\n */\n\n/**\n * Creates disc buffers. The disc will be in the xz plane, centered at\n * the origin. When creating, at least 3 divisions, or pie\n * pieces, need to be specified, otherwise the triangles making\n * up the disc will be degenerate. You can also specify the\n * number of radial pieces `stacks`. A value of 1 for\n * stacks will give you a simple disc of pie pieces. If you\n * want to create an annulus you can set `innerRadius` to a\n * value > 0. Finally, `stackPower` allows you to have the widths\n * increase or decrease as you move away from the center. This\n * is particularly useful when using the disc as a ground plane\n * with a fixed camera such that you don't need the resolution\n * of small triangles near the perimeter. For example, a value\n * of 2 will produce stacks whose outside radius increases with\n * the square of the stack index. A value of 1 will give uniform\n * stacks.\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext.\n * @param {number} radius Radius of the ground plane.\n * @param {number} divisions Number of triangles in the ground plane (at least 3).\n * @param {number} [stacks] Number of radial divisions (default=1).\n * @param {number} [innerRadius] Default 0.\n * @param {number} [stackPower] Power to raise stack size to for decreasing width.\n * @return {Object.} The created buffers.\n * @memberOf module:twgl/primitives\n * @function createDiscBuffers\n */\n\n/**\n * Creates disc vertices. The disc will be in the xz plane, centered at\n * the origin. When creating, at least 3 divisions, or pie\n * pieces, need to be specified, otherwise the triangles making\n * up the disc will be degenerate. You can also specify the\n * number of radial pieces `stacks`. A value of 1 for\n * stacks will give you a simple disc of pie pieces. If you\n * want to create an annulus you can set `innerRadius` to a\n * value > 0. Finally, `stackPower` allows you to have the widths\n * increase or decrease as you move away from the center. This\n * is particularly useful when using the disc as a ground plane\n * with a fixed camera such that you don't need the resolution\n * of small triangles near the perimeter. For example, a value\n * of 2 will produce stacks whose outside radius increases with\n * the square of the stack index. A value of 1 will give uniform\n * stacks.\n *\n * @param {number} radius Radius of the ground plane.\n * @param {number} divisions Number of triangles in the ground plane (at least 3).\n * @param {number} [stacks] Number of radial divisions (default=1).\n * @param {number} [innerRadius] Default 0.\n * @param {number} [stackPower] Power to raise stack size to for decreasing width.\n * @return {Object.} The created vertices.\n * @memberOf module:twgl/primitives\n */\nfunction createDiscVertices(\n radius,\n divisions,\n stacks,\n innerRadius,\n stackPower) {\n if (divisions < 3) {\n throw new Error('divisions must be at least 3');\n }\n\n stacks = stacks ? stacks : 1;\n stackPower = stackPower ? stackPower : 1;\n innerRadius = innerRadius ? innerRadius : 0;\n\n // Note: We don't share the center vertex because that would\n // mess up texture coordinates.\n const numVertices = (divisions + 1) * (stacks + 1);\n\n const positions = createAugmentedTypedArray(3, numVertices);\n const normals = createAugmentedTypedArray(3, numVertices);\n const texcoords = createAugmentedTypedArray(2, numVertices);\n const indices = createAugmentedTypedArray(3, stacks * divisions * 2, Uint16Array);\n\n let firstIndex = 0;\n const radiusSpan = radius - innerRadius;\n const pointsPerStack = divisions + 1;\n\n // Build the disk one stack at a time.\n for (let stack = 0; stack <= stacks; ++stack) {\n const stackRadius = innerRadius + radiusSpan * Math.pow(stack / stacks, stackPower);\n\n for (let i = 0; i <= divisions; ++i) {\n const theta = 2.0 * Math.PI * i / divisions;\n const x = stackRadius * Math.cos(theta);\n const z = stackRadius * Math.sin(theta);\n\n positions.push(x, 0, z);\n normals.push(0, 1, 0);\n texcoords.push(1 - (i / divisions), stack / stacks);\n if (stack > 0 && i !== divisions) {\n // a, b, c and d are the indices of the vertices of a quad. unless\n // the current stack is the one closest to the center, in which case\n // the vertices a and b connect to the center vertex.\n const a = firstIndex + (i + 1);\n const b = firstIndex + i;\n const c = firstIndex + i - pointsPerStack;\n const d = firstIndex + (i + 1) - pointsPerStack;\n\n // Make a quad of the vertices a, b, c, d.\n indices.push(a, b, c);\n indices.push(a, c, d);\n }\n }\n\n firstIndex += divisions + 1;\n }\n\n return {\n position: positions,\n normal: normals,\n texcoord: texcoords,\n indices: indices,\n };\n}\n\n/**\n * creates a random integer between 0 and range - 1 inclusive.\n * @param {number} range\n * @return {number} random value between 0 and range - 1 inclusive.\n * @private\n */\nfunction randInt(range) {\n return Math.random() * range | 0;\n}\n\n/**\n * Used to supply random colors\n * @callback RandomColorFunc\n * @param {number} ndx index of triangle/quad if unindexed or index of vertex if indexed\n * @param {number} channel 0 = red, 1 = green, 2 = blue, 3 = alpha\n * @return {number} a number from 0 to 255\n * @memberOf module:twgl/primitives\n */\n\n/**\n * @typedef {Object} RandomVerticesOptions\n * @property {number} [vertsPerColor] Defaults to 3 for non-indexed vertices\n * @property {module:twgl/primitives.RandomColorFunc} [rand] A function to generate random numbers\n * @memberOf module:twgl/primitives\n */\n\n/**\n * Creates an augmentedTypedArray of random vertex colors.\n * If the vertices are indexed (have an indices array) then will\n * just make random colors. Otherwise assumes they are triangles\n * and makes one random color for every 3 vertices.\n * @param {Object.} vertices Vertices as returned from one of the createXXXVertices functions.\n * @param {module:twgl/primitives.RandomVerticesOptions} [options] options.\n * @return {Object.} same vertices as passed in with `color` added.\n * @memberOf module:twgl/primitives\n */\nfunction makeRandomVertexColors(vertices, options) {\n options = options || {};\n const numElements = vertices.position.numElements;\n const vColors = createAugmentedTypedArray(4, numElements, Uint8Array);\n const rand = options.rand || function(ndx, channel) {\n return channel < 3 ? randInt(256) : 255;\n };\n vertices.color = vColors;\n if (vertices.indices) {\n // just make random colors if index\n for (let ii = 0; ii < numElements; ++ii) {\n vColors.push(rand(ii, 0), rand(ii, 1), rand(ii, 2), rand(ii, 3));\n }\n } else {\n // make random colors per triangle\n const numVertsPerColor = options.vertsPerColor || 3;\n const numSets = numElements / numVertsPerColor;\n for (let ii = 0; ii < numSets; ++ii) { // eslint-disable-line\n const color = [rand(ii, 0), rand(ii, 1), rand(ii, 2), rand(ii, 3)];\n for (let jj = 0; jj < numVertsPerColor; ++jj) {\n vColors.push(color);\n }\n }\n }\n return vertices;\n}\n\n/**\n * creates a function that calls fn to create vertices and then\n * creates a buffers for them\n * @private\n */\nfunction createBufferFunc(fn) {\n return function(gl) {\n const arrays = fn.apply(this, Array.prototype.slice.call(arguments, 1));\n return createBuffersFromArrays(gl, arrays);\n };\n}\n\n/**\n * creates a function that calls fn to create vertices and then\n * creates a bufferInfo object for them\n * @private\n */\nfunction createBufferInfoFunc(fn) {\n return function(gl) {\n const arrays = fn.apply(null, Array.prototype.slice.call(arguments, 1));\n return createBufferInfoFromArrays(gl, arrays);\n };\n}\n\nconst arraySpecPropertyNames = [\n \"numComponents\",\n \"size\",\n \"type\",\n \"normalize\",\n \"stride\",\n \"offset\",\n \"attrib\",\n \"name\",\n \"attribName\",\n];\n\n/**\n * Copy elements from one array to another\n *\n * @param {Array|TypedArray} src source array\n * @param {Array|TypedArray} dst dest array\n * @param {number} dstNdx index in dest to copy src\n * @param {number} [offset] offset to add to copied values\n * @private\n */\nfunction copyElements(src, dst, dstNdx, offset) {\n offset = offset || 0;\n const length = src.length;\n for (let ii = 0; ii < length; ++ii) {\n dst[dstNdx + ii] = src[ii] + offset;\n }\n}\n\n/**\n * Creates an array of the same time\n *\n * @param {(number[]|ArrayBufferView|module:twgl.FullArraySpec)} srcArray array who's type to copy\n * @param {number} length size of new array\n * @return {(number[]|ArrayBufferView|module:twgl.FullArraySpec)} array with same type as srcArray\n * @private\n */\nfunction createArrayOfSameType(srcArray, length) {\n const arraySrc = getArray(srcArray);\n const newArray = new arraySrc.constructor(length);\n let newArraySpec = newArray;\n // If it appears to have been augmented make new one augmented\n if (arraySrc.numComponents && arraySrc.numElements) {\n augmentTypedArray(newArray, arraySrc.numComponents);\n }\n // If it was a full spec make new one a full spec\n if (srcArray.data) {\n newArraySpec = {\n data: newArray,\n };\n copyNamedProperties(arraySpecPropertyNames, srcArray, newArraySpec);\n }\n return newArraySpec;\n}\n\n/**\n * Concatenates sets of vertices\n *\n * Assumes the vertices match in composition. For example\n * if one set of vertices has positions, normals, and indices\n * all sets of vertices must have positions, normals, and indices\n * and of the same type.\n *\n * Example:\n *\n * const cubeVertices = twgl.primitives.createCubeVertices(2);\n * const sphereVertices = twgl.primitives.createSphereVertices(1, 10, 10);\n * // move the sphere 2 units up\n * twgl.primitives.reorientVertices(\n * sphereVertices, twgl.m4.translation([0, 2, 0]));\n * // merge the sphere with the cube\n * const cubeSphereVertices = twgl.primitives.concatVertices(\n * [cubeVertices, sphereVertices]);\n * // turn them into WebGL buffers and attrib data\n * const bufferInfo = twgl.createBufferInfoFromArrays(gl, cubeSphereVertices);\n *\n * @param {module:twgl.Arrays[]} arrays Array of arrays of vertices\n * @return {module:twgl.Arrays} The concatenated vertices.\n * @memberOf module:twgl/primitives\n */\nfunction concatVertices(arrayOfArrays) {\n const names = {};\n let baseName;\n // get names of all arrays.\n // and numElements for each set of vertices\n for (let ii = 0; ii < arrayOfArrays.length; ++ii) {\n const arrays = arrayOfArrays[ii];\n Object.keys(arrays).forEach(function(name) { // eslint-disable-line\n if (!names[name]) {\n names[name] = [];\n }\n if (!baseName && name !== 'indices') {\n baseName = name;\n }\n const arrayInfo = arrays[name];\n const numComponents = getNumComponents(arrayInfo, name);\n const array = getArray(arrayInfo);\n const numElements = array.length / numComponents;\n names[name].push(numElements);\n });\n }\n\n // compute length of combined array\n // and return one for reference\n function getLengthOfCombinedArrays(name) {\n let length = 0;\n let arraySpec;\n for (let ii = 0; ii < arrayOfArrays.length; ++ii) {\n const arrays = arrayOfArrays[ii];\n const arrayInfo = arrays[name];\n const array = getArray(arrayInfo);\n length += array.length;\n if (!arraySpec || arrayInfo.data) {\n arraySpec = arrayInfo;\n }\n }\n return {\n length: length,\n spec: arraySpec,\n };\n }\n\n function copyArraysToNewArray(name, base, newArray) {\n let baseIndex = 0;\n let offset = 0;\n for (let ii = 0; ii < arrayOfArrays.length; ++ii) {\n const arrays = arrayOfArrays[ii];\n const arrayInfo = arrays[name];\n const array = getArray(arrayInfo);\n if (name === 'indices') {\n copyElements(array, newArray, offset, baseIndex);\n baseIndex += base[ii];\n } else {\n copyElements(array, newArray, offset);\n }\n offset += array.length;\n }\n }\n\n const base = names[baseName];\n\n const newArrays = {};\n Object.keys(names).forEach(function(name) {\n const info = getLengthOfCombinedArrays(name);\n const newArraySpec = createArrayOfSameType(info.spec, info.length);\n copyArraysToNewArray(name, base, getArray(newArraySpec));\n newArrays[name] = newArraySpec;\n });\n return newArrays;\n}\n\n/**\n * Creates a duplicate set of vertices\n *\n * This is useful for calling reorientVertices when you\n * also want to keep the original available\n *\n * @param {module:twgl.Arrays} arrays of vertices\n * @return {module:twgl.Arrays} The duplicated vertices.\n * @memberOf module:twgl/primitives\n */\nfunction duplicateVertices(arrays) {\n const newArrays = {};\n Object.keys(arrays).forEach(function(name) {\n const arraySpec = arrays[name];\n const srcArray = getArray(arraySpec);\n const newArraySpec = createArrayOfSameType(arraySpec, srcArray.length);\n copyElements(srcArray, getArray(newArraySpec), 0);\n newArrays[name] = newArraySpec;\n });\n return newArrays;\n}\n\nconst create3DFBufferInfo = createBufferInfoFunc(create3DFVertices);\nconst create3DFBuffers = createBufferFunc(create3DFVertices);\nconst createCubeBufferInfo = createBufferInfoFunc(createCubeVertices);\nconst createCubeBuffers = createBufferFunc(createCubeVertices);\nconst createPlaneBufferInfo = createBufferInfoFunc(createPlaneVertices);\nconst createPlaneBuffers = createBufferFunc(createPlaneVertices);\nconst createSphereBufferInfo = createBufferInfoFunc(createSphereVertices);\nconst createSphereBuffers = createBufferFunc(createSphereVertices);\nconst createTruncatedConeBufferInfo = createBufferInfoFunc(createTruncatedConeVertices);\nconst createTruncatedConeBuffers = createBufferFunc(createTruncatedConeVertices);\nconst createXYQuadBufferInfo = createBufferInfoFunc(createXYQuadVertices);\nconst createXYQuadBuffers = createBufferFunc(createXYQuadVertices);\nconst createCrescentBufferInfo = createBufferInfoFunc(createCrescentVertices);\nconst createCrescentBuffers = createBufferFunc(createCrescentVertices);\nconst createCylinderBufferInfo = createBufferInfoFunc(createCylinderVertices);\nconst createCylinderBuffers = createBufferFunc(createCylinderVertices);\nconst createTorusBufferInfo = createBufferInfoFunc(createTorusVertices);\nconst createTorusBuffers = createBufferFunc(createTorusVertices);\nconst createDiscBufferInfo = createBufferInfoFunc(createDiscVertices);\nconst createDiscBuffers = createBufferFunc(createDiscVertices);\n\n// these were mis-spelled until 4.12\nconst createCresentBufferInfo = createCrescentBufferInfo;\nconst createCresentBuffers = createCrescentBuffers;\nconst createCresentVertices = createCrescentVertices;\n\nvar primitives = /*#__PURE__*/Object.freeze({\n __proto__: null,\n create3DFBufferInfo: create3DFBufferInfo,\n create3DFBuffers: create3DFBuffers,\n create3DFVertices: create3DFVertices,\n createAugmentedTypedArray: createAugmentedTypedArray,\n createCubeBufferInfo: createCubeBufferInfo,\n createCubeBuffers: createCubeBuffers,\n createCubeVertices: createCubeVertices,\n createPlaneBufferInfo: createPlaneBufferInfo,\n createPlaneBuffers: createPlaneBuffers,\n createPlaneVertices: createPlaneVertices,\n createSphereBufferInfo: createSphereBufferInfo,\n createSphereBuffers: createSphereBuffers,\n createSphereVertices: createSphereVertices,\n createTruncatedConeBufferInfo: createTruncatedConeBufferInfo,\n createTruncatedConeBuffers: createTruncatedConeBuffers,\n createTruncatedConeVertices: createTruncatedConeVertices,\n createXYQuadBufferInfo: createXYQuadBufferInfo,\n createXYQuadBuffers: createXYQuadBuffers,\n createXYQuadVertices: createXYQuadVertices,\n createCresentBufferInfo: createCresentBufferInfo,\n createCresentBuffers: createCresentBuffers,\n createCresentVertices: createCresentVertices,\n createCrescentBufferInfo: createCrescentBufferInfo,\n createCrescentBuffers: createCrescentBuffers,\n createCrescentVertices: createCrescentVertices,\n createCylinderBufferInfo: createCylinderBufferInfo,\n createCylinderBuffers: createCylinderBuffers,\n createCylinderVertices: createCylinderVertices,\n createTorusBufferInfo: createTorusBufferInfo,\n createTorusBuffers: createTorusBuffers,\n createTorusVertices: createTorusVertices,\n createDiscBufferInfo: createDiscBufferInfo,\n createDiscBuffers: createDiscBuffers,\n createDiscVertices: createDiscVertices,\n deindexVertices: deindexVertices,\n flattenNormals: flattenNormals,\n makeRandomVertexColors: makeRandomVertexColors,\n reorientDirections: reorientDirections,\n reorientNormals: reorientNormals,\n reorientPositions: reorientPositions,\n reorientVertices: reorientVertices,\n concatVertices: concatVertices,\n duplicateVertices: duplicateVertices\n});\n\n/*\n * Copyright 2019 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\n/**\n * Gets the gl version as a number\n * @param {WebGLRenderingContext} gl A WebGLRenderingContext\n * @return {number} version of gl\n * @private\n */\n//function getVersionAsNumber(gl) {\n// return parseFloat(gl.getParameter(gl.VERSION).substr(6));\n//}\n\n/**\n * Check if context is WebGL 2.0\n * @param {WebGLRenderingContext} gl A WebGLRenderingContext\n * @return {bool} true if it's WebGL 2.0\n * @memberOf module:twgl\n */\nfunction isWebGL2(gl) {\n // This is the correct check but it's slow\n // return gl.getParameter(gl.VERSION).indexOf(\"WebGL 2.0\") === 0;\n // This might also be the correct check but I'm assuming it's slow-ish\n // return gl instanceof WebGL2RenderingContext;\n return !!gl.texStorage2D;\n}\n\n/**\n * Check if context is WebGL 1.0\n * @param {WebGLRenderingContext} gl A WebGLRenderingContext\n * @return {bool} true if it's WebGL 1.0\n * @memberOf module:twgl\n */\nfunction isWebGL1(gl) {\n // This is the correct check but it's slow\n // const version = getVersionAsNumber(gl);\n // return version <= 1.0 && version > 0.0; // because as of 2016/5 Edge returns 0.96\n // This might also be the correct check but I'm assuming it's slow-ish\n // return gl instanceof WebGLRenderingContext;\n return !gl.texStorage2D;\n}\n\n/**\n * Gets a string for WebGL enum\n *\n * Note: Several enums are the same. Without more\n * context (which function) it's impossible to always\n * give the correct enum. As it is, for matching values\n * it gives all enums. Checking the WebGL2RenderingContext\n * that means\n *\n * 0 = ZERO | POINT | NONE | NO_ERROR\n * 1 = ONE | LINES | SYNC_FLUSH_COMMANDS_BIT\n * 32777 = BLEND_EQUATION_RGB | BLEND_EQUATION_RGB\n * 36662 = COPY_READ_BUFFER | COPY_READ_BUFFER_BINDING\n * 36663 = COPY_WRITE_BUFFER | COPY_WRITE_BUFFER_BINDING\n * 36006 = FRAMEBUFFER_BINDING | DRAW_FRAMEBUFFER_BINDING\n *\n * It's also not useful for bits really unless you pass in individual bits.\n * In other words\n *\n * const bits = gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT;\n * twgl.glEnumToString(gl, bits); // not going to work\n *\n * Note that some enums only exist on extensions. If you\n * want them to show up you need to pass the extension at least\n * once. For example\n *\n * const ext = gl.getExtension('WEBGL_compressed_texture_s3tc');\n * if (ext) {\n * twgl.glEnumToString(ext, 0); // just prime the function\n *\n * ..later..\n *\n * const internalFormat = ext.COMPRESSED_RGB_S3TC_DXT1_EXT;\n * console.log(twgl.glEnumToString(gl, internalFormat));\n *\n * Notice I didn't have to pass the extension the second time. This means\n * you can have place that generically gets an enum for texture formats for example.\n * and as long as you primed the function with the extensions\n *\n * If you're using `twgl.addExtensionsToContext` to enable your extensions\n * then twgl will automatically get the extension's enums.\n *\n * @param {WebGLRenderingContext} gl A WebGLRenderingContext or any extension object\n * @param {number} value the value of the enum you want to look up.\n * @return {string} enum string or hex value\n * @memberOf module:twgl\n * @function glEnumToString\n */\nconst glEnumToString = (function() {\n const haveEnumsForType = {};\n const enums = {};\n\n function addEnums(gl) {\n const type = gl.constructor.name;\n if (!haveEnumsForType[type]) {\n for (const key in gl) {\n if (typeof gl[key] === 'number') {\n const existing = enums[gl[key]];\n enums[gl[key]] = existing ? `${existing} | ${key}` : key;\n }\n }\n haveEnumsForType[type] = true;\n }\n }\n\n return function glEnumToString(gl, value) {\n addEnums(gl);\n return enums[value] || (typeof value === 'number' ? `0x${value.toString(16)}` : value);\n };\n}());\n\nvar utils = /*#__PURE__*/Object.freeze({\n __proto__: null,\n glEnumToString: glEnumToString,\n isWebGL1: isWebGL1,\n isWebGL2: isWebGL2\n});\n\n/*\n * Copyright 2019 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\nconst defaults$1 = {\n textureColor: new Uint8Array([128, 192, 255, 255]),\n textureOptions: {},\n crossOrigin: undefined,\n};\nconst isArrayBuffer = isArrayBuffer$1;\n\n// Should we make this on demand?\nconst getShared2DContext = function() {\n let s_ctx;\n return function getShared2DContext() {\n s_ctx = s_ctx ||\n ((typeof document !== 'undefined' && document.createElement)\n ? document.createElement(\"canvas\").getContext(\"2d\")\n : null);\n return s_ctx;\n };\n}();\n\n// NOTE: Chrome supports 2D canvas in a Worker (behind flag as of v64 but\n// not only does Firefox NOT support it but Firefox freezes immediately\n// if you try to create one instead of just returning null and continuing.\n// : (global.OffscreenCanvas && (new global.OffscreenCanvas(1, 1)).getContext(\"2d\")); // OffscreenCanvas may not support 2d\n\n// NOTE: We can maybe remove some of the need for the 2d canvas. In WebGL2\n// we can use the various unpack settings. Otherwise we could try using\n// the ability of an ImageBitmap to be cut. Unfortunately cutting an ImageBitmap\n// is async and the current TWGL code expects a non-Async result though that\n// might not be a problem. ImageBitmap though is not available in Edge or Safari\n// as of 2018-01-02\n\n/* PixelFormat */\nconst ALPHA = 0x1906;\nconst RGB = 0x1907;\nconst RGBA$1 = 0x1908;\nconst LUMINANCE = 0x1909;\nconst LUMINANCE_ALPHA = 0x190A;\nconst DEPTH_COMPONENT$1 = 0x1902;\nconst DEPTH_STENCIL$1 = 0x84F9;\n\n/* TextureWrapMode */\n// const REPEAT = 0x2901;\n// const MIRRORED_REPEAT = 0x8370;\nconst CLAMP_TO_EDGE$1 = 0x812f;\n\n/* TextureMagFilter */\nconst NEAREST = 0x2600;\nconst LINEAR$1 = 0x2601;\n\n/* TextureMinFilter */\n// const NEAREST_MIPMAP_NEAREST = 0x2700;\n// const LINEAR_MIPMAP_NEAREST = 0x2701;\n// const NEAREST_MIPMAP_LINEAR = 0x2702;\n// const LINEAR_MIPMAP_LINEAR = 0x2703;\n\n/* Texture Target */\nconst TEXTURE_2D$2 = 0x0de1;\nconst TEXTURE_CUBE_MAP$1 = 0x8513;\nconst TEXTURE_3D$1 = 0x806f;\nconst TEXTURE_2D_ARRAY$1 = 0x8c1a;\n\n/* Cubemap Targets */\nconst TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515;\nconst TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516;\nconst TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517;\nconst TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518;\nconst TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519;\nconst TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851a;\n\n/* Texture Parameters */\nconst TEXTURE_MIN_FILTER = 0x2801;\nconst TEXTURE_MAG_FILTER = 0x2800;\nconst TEXTURE_WRAP_S = 0x2802;\nconst TEXTURE_WRAP_T = 0x2803;\nconst TEXTURE_WRAP_R = 0x8072;\nconst TEXTURE_MIN_LOD = 0x813a;\nconst TEXTURE_MAX_LOD = 0x813b;\nconst TEXTURE_BASE_LEVEL = 0x813c;\nconst TEXTURE_MAX_LEVEL = 0x813d;\nconst TEXTURE_COMPARE_MODE = 0x884C;\nconst TEXTURE_COMPARE_FUNC = 0x884D;\n\n/* Pixel store */\nconst UNPACK_ALIGNMENT = 0x0cf5;\nconst UNPACK_ROW_LENGTH = 0x0cf2;\nconst UNPACK_IMAGE_HEIGHT = 0x806e;\nconst UNPACK_SKIP_PIXELS = 0x0cf4;\nconst UNPACK_SKIP_ROWS = 0x0cf3;\nconst UNPACK_SKIP_IMAGES = 0x806d;\nconst UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243;\nconst UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241;\nconst UNPACK_FLIP_Y_WEBGL = 0x9240;\n\nconst R8 = 0x8229;\nconst R8_SNORM = 0x8F94;\nconst R16F = 0x822D;\nconst R32F = 0x822E;\nconst R8UI = 0x8232;\nconst R8I = 0x8231;\nconst RG16UI = 0x823A;\nconst RG16I = 0x8239;\nconst RG32UI = 0x823C;\nconst RG32I = 0x823B;\nconst RG8 = 0x822B;\nconst RG8_SNORM = 0x8F95;\nconst RG16F = 0x822F;\nconst RG32F = 0x8230;\nconst RG8UI = 0x8238;\nconst RG8I = 0x8237;\nconst R16UI = 0x8234;\nconst R16I = 0x8233;\nconst R32UI = 0x8236;\nconst R32I = 0x8235;\nconst RGB8 = 0x8051;\nconst SRGB8 = 0x8C41;\nconst RGB565$1 = 0x8D62;\nconst RGB8_SNORM = 0x8F96;\nconst R11F_G11F_B10F = 0x8C3A;\nconst RGB9_E5 = 0x8C3D;\nconst RGB16F = 0x881B;\nconst RGB32F = 0x8815;\nconst RGB8UI = 0x8D7D;\nconst RGB8I = 0x8D8F;\nconst RGB16UI = 0x8D77;\nconst RGB16I = 0x8D89;\nconst RGB32UI = 0x8D71;\nconst RGB32I = 0x8D83;\nconst RGBA8 = 0x8058;\nconst SRGB8_ALPHA8 = 0x8C43;\nconst RGBA8_SNORM = 0x8F97;\nconst RGB5_A1$1 = 0x8057;\nconst RGBA4$1 = 0x8056;\nconst RGB10_A2 = 0x8059;\nconst RGBA16F = 0x881A;\nconst RGBA32F = 0x8814;\nconst RGBA8UI = 0x8D7C;\nconst RGBA8I = 0x8D8E;\nconst RGB10_A2UI = 0x906F;\nconst RGBA16UI = 0x8D76;\nconst RGBA16I = 0x8D88;\nconst RGBA32I = 0x8D82;\nconst RGBA32UI = 0x8D70;\n\nconst DEPTH_COMPONENT16$1 = 0x81A5;\nconst DEPTH_COMPONENT24$1 = 0x81A6;\nconst DEPTH_COMPONENT32F$1 = 0x8CAC;\nconst DEPTH32F_STENCIL8$1 = 0x8CAD;\nconst DEPTH24_STENCIL8$1 = 0x88F0;\n\n/* DataType */\nconst BYTE = 0x1400;\nconst UNSIGNED_BYTE$1 = 0x1401;\nconst SHORT = 0x1402;\nconst UNSIGNED_SHORT$1 = 0x1403;\nconst INT$1 = 0x1404;\nconst UNSIGNED_INT$1 = 0x1405;\nconst FLOAT$1 = 0x1406;\nconst UNSIGNED_SHORT_4_4_4_4 = 0x8033;\nconst UNSIGNED_SHORT_5_5_5_1 = 0x8034;\nconst UNSIGNED_SHORT_5_6_5 = 0x8363;\nconst HALF_FLOAT = 0x140B;\nconst HALF_FLOAT_OES = 0x8D61; // Thanks Khronos for making this different >:(\nconst UNSIGNED_INT_2_10_10_10_REV = 0x8368;\nconst UNSIGNED_INT_10F_11F_11F_REV = 0x8C3B;\nconst UNSIGNED_INT_5_9_9_9_REV = 0x8C3E;\nconst FLOAT_32_UNSIGNED_INT_24_8_REV = 0x8DAD;\nconst UNSIGNED_INT_24_8 = 0x84FA;\n\nconst RG = 0x8227;\nconst RG_INTEGER = 0x8228;\nconst RED = 0x1903;\nconst RED_INTEGER = 0x8D94;\nconst RGB_INTEGER = 0x8D98;\nconst RGBA_INTEGER = 0x8D99;\n\nconst formatInfo = {};\n{\n // NOTE: this is named `numColorComponents` vs `numComponents` so we can let Uglify mangle\n // the name.\n const f = formatInfo;\n f[ALPHA] = { numColorComponents: 1, };\n f[LUMINANCE] = { numColorComponents: 1, };\n f[LUMINANCE_ALPHA] = { numColorComponents: 2, };\n f[RGB] = { numColorComponents: 3, };\n f[RGBA$1] = { numColorComponents: 4, };\n f[RED] = { numColorComponents: 1, };\n f[RED_INTEGER] = { numColorComponents: 1, };\n f[RG] = { numColorComponents: 2, };\n f[RG_INTEGER] = { numColorComponents: 2, };\n f[RGB] = { numColorComponents: 3, };\n f[RGB_INTEGER] = { numColorComponents: 3, };\n f[RGBA$1] = { numColorComponents: 4, };\n f[RGBA_INTEGER] = { numColorComponents: 4, };\n f[DEPTH_COMPONENT$1] = { numColorComponents: 1, };\n f[DEPTH_STENCIL$1] = { numColorComponents: 2, };\n}\n\n/**\n * @typedef {Object} TextureFormatDetails\n * @property {number} textureFormat format to pass texImage2D and similar functions.\n * @property {boolean} colorRenderable true if you can render to this format of texture.\n * @property {boolean} textureFilterable true if you can filter the texture, false if you can ony use `NEAREST`.\n * @property {number[]} type Array of possible types you can pass to texImage2D and similar function\n * @property {Object.} bytesPerElementMap A map of types to bytes per element\n * @private\n */\n\nlet s_textureInternalFormatInfo;\nfunction getTextureInternalFormatInfo(internalFormat) {\n if (!s_textureInternalFormatInfo) {\n // NOTE: these properties need unique names so we can let Uglify mangle the name.\n const t = {};\n // unsized formats\n t[ALPHA] = { textureFormat: ALPHA, colorRenderable: true, textureFilterable: true, bytesPerElement: [1, 2, 2, 4], type: [UNSIGNED_BYTE$1, HALF_FLOAT, HALF_FLOAT_OES, FLOAT$1], };\n t[LUMINANCE] = { textureFormat: LUMINANCE, colorRenderable: true, textureFilterable: true, bytesPerElement: [1, 2, 2, 4], type: [UNSIGNED_BYTE$1, HALF_FLOAT, HALF_FLOAT_OES, FLOAT$1], };\n 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], };\n 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], };\n 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], };\n t[DEPTH_COMPONENT$1] = { textureFormat: DEPTH_COMPONENT$1, colorRenderable: true, textureFilterable: false, bytesPerElement: [2, 4], type: [UNSIGNED_INT$1, UNSIGNED_SHORT$1], };\n\n // sized formats\n t[R8] = { textureFormat: RED, colorRenderable: true, textureFilterable: true, bytesPerElement: [1], type: [UNSIGNED_BYTE$1], };\n t[R8_SNORM] = { textureFormat: RED, colorRenderable: false, textureFilterable: true, bytesPerElement: [1], type: [BYTE], };\n t[R16F] = { textureFormat: RED, colorRenderable: false, textureFilterable: true, bytesPerElement: [4, 2], type: [FLOAT$1, HALF_FLOAT], };\n t[R32F] = { textureFormat: RED, colorRenderable: false, textureFilterable: false, bytesPerElement: [4], type: [FLOAT$1], };\n t[R8UI] = { textureFormat: RED_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [1], type: [UNSIGNED_BYTE$1], };\n t[R8I] = { textureFormat: RED_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [1], type: [BYTE], };\n t[R16UI] = { textureFormat: RED_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [2], type: [UNSIGNED_SHORT$1], };\n t[R16I] = { textureFormat: RED_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [2], type: [SHORT], };\n t[R32UI] = { textureFormat: RED_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [UNSIGNED_INT$1], };\n t[R32I] = { textureFormat: RED_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [INT$1], };\n t[RG8] = { textureFormat: RG, colorRenderable: true, textureFilterable: true, bytesPerElement: [2], type: [UNSIGNED_BYTE$1], };\n t[RG8_SNORM] = { textureFormat: RG, colorRenderable: false, textureFilterable: true, bytesPerElement: [2], type: [BYTE], };\n t[RG16F] = { textureFormat: RG, colorRenderable: false, textureFilterable: true, bytesPerElement: [8, 4], type: [FLOAT$1, HALF_FLOAT], };\n t[RG32F] = { textureFormat: RG, colorRenderable: false, textureFilterable: false, bytesPerElement: [8], type: [FLOAT$1], };\n t[RG8UI] = { textureFormat: RG_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [2], type: [UNSIGNED_BYTE$1], };\n t[RG8I] = { textureFormat: RG_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [2], type: [BYTE], };\n t[RG16UI] = { textureFormat: RG_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [UNSIGNED_SHORT$1], };\n t[RG16I] = { textureFormat: RG_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [SHORT], };\n t[RG32UI] = { textureFormat: RG_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [8], type: [UNSIGNED_INT$1], };\n t[RG32I] = { textureFormat: RG_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [8], type: [INT$1], };\n t[RGB8] = { textureFormat: RGB, colorRenderable: true, textureFilterable: true, bytesPerElement: [3], type: [UNSIGNED_BYTE$1], };\n t[SRGB8] = { textureFormat: RGB, colorRenderable: false, textureFilterable: true, bytesPerElement: [3], type: [UNSIGNED_BYTE$1], };\n t[RGB565$1] = { textureFormat: RGB, colorRenderable: true, textureFilterable: true, bytesPerElement: [3, 2], type: [UNSIGNED_BYTE$1, UNSIGNED_SHORT_5_6_5], };\n t[RGB8_SNORM] = { textureFormat: RGB, colorRenderable: false, textureFilterable: true, bytesPerElement: [3], type: [BYTE], };\n 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], };\n 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], };\n t[RGB16F] = { textureFormat: RGB, colorRenderable: false, textureFilterable: true, bytesPerElement: [12, 6], type: [FLOAT$1, HALF_FLOAT], };\n t[RGB32F] = { textureFormat: RGB, colorRenderable: false, textureFilterable: false, bytesPerElement: [12], type: [FLOAT$1], };\n t[RGB8UI] = { textureFormat: RGB_INTEGER, colorRenderable: false, textureFilterable: false, bytesPerElement: [3], type: [UNSIGNED_BYTE$1], };\n t[RGB8I] = { textureFormat: RGB_INTEGER, colorRenderable: false, textureFilterable: false, bytesPerElement: [3], type: [BYTE], };\n t[RGB16UI] = { textureFormat: RGB_INTEGER, colorRenderable: false, textureFilterable: false, bytesPerElement: [6], type: [UNSIGNED_SHORT$1], };\n t[RGB16I] = { textureFormat: RGB_INTEGER, colorRenderable: false, textureFilterable: false, bytesPerElement: [6], type: [SHORT], };\n t[RGB32UI] = { textureFormat: RGB_INTEGER, colorRenderable: false, textureFilterable: false, bytesPerElement: [12], type: [UNSIGNED_INT$1], };\n t[RGB32I] = { textureFormat: RGB_INTEGER, colorRenderable: false, textureFilterable: false, bytesPerElement: [12], type: [INT$1], };\n t[RGBA8] = { textureFormat: RGBA$1, colorRenderable: true, textureFilterable: true, bytesPerElement: [4], type: [UNSIGNED_BYTE$1], };\n t[SRGB8_ALPHA8] = { textureFormat: RGBA$1, colorRenderable: true, textureFilterable: true, bytesPerElement: [4], type: [UNSIGNED_BYTE$1], };\n t[RGBA8_SNORM] = { textureFormat: RGBA$1, colorRenderable: false, textureFilterable: true, bytesPerElement: [4], type: [BYTE], };\n 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], };\n t[RGBA4$1] = { textureFormat: RGBA$1, colorRenderable: true, textureFilterable: true, bytesPerElement: [4, 2], type: [UNSIGNED_BYTE$1, UNSIGNED_SHORT_4_4_4_4], };\n t[RGB10_A2] = { textureFormat: RGBA$1, colorRenderable: true, textureFilterable: true, bytesPerElement: [4], type: [UNSIGNED_INT_2_10_10_10_REV], };\n t[RGBA16F] = { textureFormat: RGBA$1, colorRenderable: false, textureFilterable: true, bytesPerElement: [16, 8], type: [FLOAT$1, HALF_FLOAT], };\n t[RGBA32F] = { textureFormat: RGBA$1, colorRenderable: false, textureFilterable: false, bytesPerElement: [16], type: [FLOAT$1], };\n t[RGBA8UI] = { textureFormat: RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [UNSIGNED_BYTE$1], };\n t[RGBA8I] = { textureFormat: RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [BYTE], };\n t[RGB10_A2UI] = { textureFormat: RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [UNSIGNED_INT_2_10_10_10_REV], };\n t[RGBA16UI] = { textureFormat: RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [8], type: [UNSIGNED_SHORT$1], };\n t[RGBA16I] = { textureFormat: RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [8], type: [SHORT], };\n t[RGBA32I] = { textureFormat: RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [16], type: [INT$1], };\n t[RGBA32UI] = { textureFormat: RGBA_INTEGER, colorRenderable: true, textureFilterable: false, bytesPerElement: [16], type: [UNSIGNED_INT$1], };\n // Sized Internal\n t[DEPTH_COMPONENT16$1] = { textureFormat: DEPTH_COMPONENT$1, colorRenderable: true, textureFilterable: false, bytesPerElement: [2, 4], type: [UNSIGNED_SHORT$1, UNSIGNED_INT$1], };\n t[DEPTH_COMPONENT24$1] = { textureFormat: DEPTH_COMPONENT$1, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [UNSIGNED_INT$1], };\n t[DEPTH_COMPONENT32F$1] = { textureFormat: DEPTH_COMPONENT$1, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [FLOAT$1], };\n t[DEPTH24_STENCIL8$1] = { textureFormat: DEPTH_STENCIL$1, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [UNSIGNED_INT_24_8], };\n t[DEPTH32F_STENCIL8$1] = { textureFormat: DEPTH_STENCIL$1, colorRenderable: true, textureFilterable: false, bytesPerElement: [4], type: [FLOAT_32_UNSIGNED_INT_24_8_REV], };\n\n Object.keys(t).forEach(function(internalFormat) {\n const info = t[internalFormat];\n info.bytesPerElementMap = {};\n info.bytesPerElement.forEach(function(bytesPerElement, ndx) {\n const type = info.type[ndx];\n info.bytesPerElementMap[type] = bytesPerElement;\n });\n });\n s_textureInternalFormatInfo = t;\n }\n return s_textureInternalFormatInfo[internalFormat];\n}\n\n/**\n * Gets the number of bytes per element for a given internalFormat / type\n * @param {number} internalFormat The internalFormat parameter from texImage2D etc..\n * @param {number} type The type parameter for texImage2D etc..\n * @return {number} the number of bytes per element for the given internalFormat, type combo\n * @memberOf module:twgl/textures\n */\nfunction getBytesPerElementForInternalFormat(internalFormat, type) {\n const info = getTextureInternalFormatInfo(internalFormat);\n if (!info) {\n throw \"unknown internal format\";\n }\n const bytesPerElement = info.bytesPerElementMap[type];\n if (bytesPerElement === undefined) {\n throw \"unknown internal format\";\n }\n return bytesPerElement;\n}\n\n/**\n * Info related to a specific texture internalFormat as returned\n * from {@link module:twgl/textures.getFormatAndTypeForInternalFormat}.\n *\n * @typedef {Object} TextureFormatInfo\n * @property {number} format Format to pass to texImage2D and related functions\n * @property {number} type Type to pass to texImage2D and related functions\n * @memberOf module:twgl/textures\n */\n\n/**\n * Gets the format and type for a given internalFormat\n *\n * @param {number} internalFormat The internal format\n * @return {module:twgl/textures.TextureFormatInfo} the corresponding format and type,\n * @memberOf module:twgl/textures\n */\nfunction getFormatAndTypeForInternalFormat(internalFormat) {\n const info = getTextureInternalFormatInfo(internalFormat);\n if (!info) {\n throw \"unknown internal format\";\n }\n return {\n format: info.textureFormat,\n type: info.type[0],\n };\n}\n\n/**\n * Returns true if value is power of 2\n * @param {number} value number to check.\n * @return true if value is power of 2\n * @private\n */\nfunction isPowerOf2(value) {\n return (value & (value - 1)) === 0;\n}\n\n/**\n * Gets whether or not we can generate mips for the given\n * internal format.\n *\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {number} width The width parameter from texImage2D etc..\n * @param {number} height The height parameter from texImage2D etc..\n * @param {number} internalFormat The internalFormat parameter from texImage2D etc..\n * @return {boolean} true if we can generate mips\n * @memberOf module:twgl/textures\n */\nfunction canGenerateMipmap(gl, width, height, internalFormat) {\n if (!isWebGL2(gl)) {\n return isPowerOf2(width) && isPowerOf2(height);\n }\n const info = getTextureInternalFormatInfo(internalFormat);\n if (!info) {\n throw \"unknown internal format\";\n }\n return info.colorRenderable && info.textureFilterable;\n}\n\n/**\n * Gets whether or not we can generate mips for the given format\n * @param {number} internalFormat The internalFormat parameter from texImage2D etc..\n * @return {boolean} true if we can generate mips\n * @memberOf module:twgl/textures\n */\nfunction canFilter(internalFormat) {\n const info = getTextureInternalFormatInfo(internalFormat);\n if (!info) {\n throw \"unknown internal format\";\n }\n return info.textureFilterable;\n}\n\n/**\n * Gets the number of components for a given image format.\n * @param {number} format the format.\n * @return {number} the number of components for the format.\n * @memberOf module:twgl/textures\n */\nfunction getNumComponentsForFormat(format) {\n const info = formatInfo[format];\n if (!info) {\n throw \"unknown format: \" + format;\n }\n return info.numColorComponents;\n}\n\n/**\n * Gets the texture type for a given array type.\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @return {number} the gl texture type\n * @private\n */\nfunction getTextureTypeForArrayType(gl, src, defaultType) {\n if (isArrayBuffer(src)) {\n return getGLTypeForTypedArray(src);\n }\n return defaultType || UNSIGNED_BYTE$1;\n}\n\nfunction guessDimensions(gl, target, width, height, numElements) {\n if (numElements % 1 !== 0) {\n throw \"can't guess dimensions\";\n }\n if (!width && !height) {\n const size = Math.sqrt(numElements / (target === TEXTURE_CUBE_MAP$1 ? 6 : 1));\n if (size % 1 === 0) {\n width = size;\n height = size;\n } else {\n width = numElements;\n height = 1;\n }\n } else if (!height) {\n height = numElements / width;\n if (height % 1) {\n throw \"can't guess dimensions\";\n }\n } else if (!width) {\n width = numElements / height;\n if (width % 1) {\n throw \"can't guess dimensions\";\n }\n }\n return {\n width: width,\n height: height,\n };\n}\n\n/**\n * Sets the default texture color.\n *\n * The default texture color is used when loading textures from\n * urls. Because the URL will be loaded async we'd like to be\n * able to use the texture immediately. By putting a 1x1 pixel\n * color in the texture we can start using the texture before\n * the URL has loaded.\n *\n * @param {number[]} color Array of 4 values in the range 0 to 1\n * @deprecated see {@link module:twgl.setDefaults}\n * @memberOf module:twgl/textures\n */\nfunction setDefaultTextureColor(color) {\n defaults$1.textureColor = new Uint8Array([color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255]);\n}\n\nfunction setDefaults$1(newDefaults) {\n copyExistingProperties(newDefaults, defaults$1);\n if (newDefaults.textureColor) {\n setDefaultTextureColor(newDefaults.textureColor);\n }\n}\n\n/**\n * A function to generate the source for a texture.\n * @callback TextureFunc\n * @param {WebGLRenderingContext} gl A WebGLRenderingContext\n * @param {module:twgl.TextureOptions} options the texture options\n * @return {*} Returns any of the things documented for `src` for {@link module:twgl.TextureOptions}.\n * @memberOf module:twgl\n */\n\n/**\n * Texture options passed to most texture functions. Each function will use whatever options\n * are appropriate for its needs. This lets you pass the same options to all functions.\n *\n * Note: A `TexImageSource` is defined in the WebGL spec as a `HTMLImageElement`, `HTMLVideoElement`,\n * `HTMLCanvasElement`, `ImageBitmap`, or `ImageData`.\n *\n * @typedef {Object} TextureOptions\n * @property {number} [target] the type of texture `gl.TEXTURE_2D` or `gl.TEXTURE_CUBE_MAP`. Defaults to `gl.TEXTURE_2D`.\n * @property {number} [level] the mip level to affect. Defaults to 0. Note, if set auto will be considered false unless explicitly set to true.\n * @property {number} [width] the width of the texture. Only used if src is an array or typed array or null.\n * @property {number} [height] the height of a texture. Only used if src is an array or typed array or null.\n * @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` .\n * @property {number} [min] the min filter setting (eg. `gl.LINEAR`). Defaults to `gl.NEAREST_MIPMAP_LINEAR`\n * or if texture is not a power of 2 on both dimensions then defaults to `gl.LINEAR`.\n * @property {number} [mag] the mag filter setting (eg. `gl.LINEAR`). Defaults to `gl.LINEAR`\n * @property {number} [minMag] both the min and mag filter settings.\n * @property {number} [internalFormat] internal format for texture. Defaults to `gl.RGBA`\n * @property {number} [format] format for texture. Defaults to `gl.RGBA`.\n * @property {number} [type] type for texture. Defaults to `gl.UNSIGNED_BYTE` unless `src` is ArrayBufferView. If `src`\n * is ArrayBufferView defaults to type that matches ArrayBufferView type.\n * @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\n * @property {number} [wrapS] Texture wrapping for S. Defaults to `gl.REPEAT` and `gl.CLAMP_TO_EDGE` for cube. If set takes precedence over `wrap`.\n * @property {number} [wrapT] Texture wrapping for T. Defaults to `gl.REPEAT` and `gl.CLAMP_TO_EDGE` for cube. If set takes precedence over `wrap`.\n * @property {number} [wrapR] Texture wrapping for R. Defaults to `gl.REPEAT` and `gl.CLAMP_TO_EDGE` for cube. If set takes precedence over `wrap`.\n * @property {number} [minLod] TEXTURE_MIN_LOD setting\n * @property {number} [maxLod] TEXTURE_MAX_LOD setting\n * @property {number} [baseLevel] TEXTURE_BASE_LEVEL setting\n * @property {number} [maxLevel] TEXTURE_MAX_LEVEL setting\n * @property {number} [compareFunc] TEXTURE_COMPARE_FUNC setting\n * @property {number} [compareMode] TEXTURE_COMPARE_MODE setting\n * @property {number} [unpackAlignment] The `gl.UNPACK_ALIGNMENT` used when uploading an array. Defaults to 1.\n * @property {number[]|ArrayBufferView} [color] Color to initialize this texture with if loading an image asynchronously.\n * The default use a blue 1x1 pixel texture. You can set another default by calling `twgl.setDefaults`\n * or you can set an individual texture's initial color by setting this property. Example: `[1, .5, .5, 1]` = pink\n * @property {number} [premultiplyAlpha] Whether or not to premultiply alpha. Defaults to whatever the current setting is.\n * This lets you set it once before calling `twgl.createTexture` or `twgl.createTextures` and only override\n * the current setting for specific textures.\n * @property {number} [flipY] Whether or not to flip the texture vertically on upload. Defaults to whatever the current setting is.\n * This lets you set it once before calling `twgl.createTexture` or `twgl.createTextures` and only override\n * the current setting for specific textures.\n * @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.\n * This lets you set it once before calling `twgl.createTexture` or `twgl.createTextures` and only override\n * the current setting for specific textures.\n * @property {boolean} [auto] If `undefined` or `true`, in WebGL1, texture filtering is set automatically for non-power of 2 images and\n * mips are generated for power of 2 images. In WebGL2 mips are generated if they can be. Note: if `level` is set above\n * then then `auto` is assumed to be `false` unless explicity set to `true`.\n * @property {number[]} [cubeFaceOrder] The order that cube faces are pulled out of an img or set of images. The default is\n *\n * [gl.TEXTURE_CUBE_MAP_POSITIVE_X,\n * gl.TEXTURE_CUBE_MAP_NEGATIVE_X,\n * gl.TEXTURE_CUBE_MAP_POSITIVE_Y,\n * gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,\n * gl.TEXTURE_CUBE_MAP_POSITIVE_Z,\n * gl.TEXTURE_CUBE_MAP_NEGATIVE_Z]\n *\n * @property {(number[]|ArrayBufferView|TexImageSource|TexImageSource[]|string|string[]|module:twgl.TextureFunc)} [src] source for texture\n *\n * If `string` then it's assumed to be a URL to an image. The image will be downloaded async. A usable\n * 1x1 pixel texture will be returned immediately. The texture will be updated once the image has downloaded.\n * If `target` is `gl.TEXTURE_CUBE_MAP` will attempt to divide image into 6 square pieces. 1x6, 6x1, 3x2, 2x3.\n * The pieces will be uploaded in `cubeFaceOrder`\n *\n * 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.\n *\n * If `string[]` or `TexImageSource[]` and target is `gl.TEXTURE_2D_ARRAY` then each entry is a slice of the a 2d array texture\n * and will be scaled to the specified width and height OR to the size of the first image that loads.\n *\n * If `TexImageSource` then it wil be used immediately to create the contents of the texture. Examples `HTMLImageElement`,\n * `HTMLCanvasElement`, `HTMLVideoElement`.\n *\n * If `number[]` or `ArrayBufferView` it's assumed to be data for a texture. If `width` or `height` is\n * not specified it is guessed as follows. First the number of elements is computed by `src.length / numComponents`\n * where `numComponents` is derived from `format`. If `target` is `gl.TEXTURE_CUBE_MAP` then `numElements` is divided\n * by 6. Then\n *\n * * If neither `width` nor `height` are specified and `sqrt(numElements)` is an integer then width and height\n * are set to `sqrt(numElements)`. Otherwise `width = numElements` and `height = 1`.\n *\n * * If only one of `width` or `height` is specified then the other equals `numElements / specifiedDimension`.\n *\n * If `number[]` will be converted to `type`.\n *\n * If `src` is a function it will be called with a `WebGLRenderingContext` and these options.\n * Whatever it returns is subject to these rules. So it can return a string url, an `HTMLElement`\n * an array etc...\n *\n * If `src` is undefined then an empty texture will be created of size `width` by `height`.\n *\n * @property {string} [crossOrigin] What to set the crossOrigin property of images when they are downloaded.\n * default: undefined. Also see {@link module:twgl.setDefaults}.\n *\n * @memberOf module:twgl\n */\n\n/**\n * Sets any packing state that will be set based on the options.\n * @param {module:twgl.TextureOptions} options A TextureOptions object with whatever parameters you want set.\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @private\n */\nfunction setPackState(gl, options) {\n if (options.colorspaceConversion !== undefined) {\n gl.pixelStorei(UNPACK_COLORSPACE_CONVERSION_WEBGL, options.colorspaceConversion);\n }\n if (options.premultiplyAlpha !== undefined) {\n gl.pixelStorei(UNPACK_PREMULTIPLY_ALPHA_WEBGL, options.premultiplyAlpha);\n }\n if (options.flipY !== undefined) {\n gl.pixelStorei(UNPACK_FLIP_Y_WEBGL, options.flipY);\n }\n}\n\n/**\n * Set skip state to defaults\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @private\n */\nfunction setSkipStateToDefault(gl) {\n gl.pixelStorei(UNPACK_ALIGNMENT, 4);\n if (isWebGL2(gl)) {\n gl.pixelStorei(UNPACK_ROW_LENGTH, 0);\n gl.pixelStorei(UNPACK_IMAGE_HEIGHT, 0);\n gl.pixelStorei(UNPACK_SKIP_PIXELS, 0);\n gl.pixelStorei(UNPACK_SKIP_ROWS, 0);\n gl.pixelStorei(UNPACK_SKIP_IMAGES, 0);\n }\n}\n\n/**\n * Sets the parameters of a texture or sampler\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {number|WebGLSampler} target texture target or sampler\n * @param {function()} parameteriFn texParameteri or samplerParameteri fn\n * @param {WebGLTexture} tex the WebGLTexture to set parameters for\n * @param {module:twgl.TextureOptions} options A TextureOptions object with whatever parameters you want set.\n * This is often the same options you passed in when you created the texture.\n * @private\n */\nfunction setTextureSamplerParameters(gl, target, parameteriFn, options) {\n if (options.minMag) {\n parameteriFn.call(gl, target, TEXTURE_MIN_FILTER, options.minMag);\n parameteriFn.call(gl, target, TEXTURE_MAG_FILTER, options.minMag);\n }\n if (options.min) {\n parameteriFn.call(gl, target, TEXTURE_MIN_FILTER, options.min);\n }\n if (options.mag) {\n parameteriFn.call(gl, target, TEXTURE_MAG_FILTER, options.mag);\n }\n if (options.wrap) {\n parameteriFn.call(gl, target, TEXTURE_WRAP_S, options.wrap);\n parameteriFn.call(gl, target, TEXTURE_WRAP_T, options.wrap);\n if (target === TEXTURE_3D$1 || isSampler(gl, target)) {\n parameteriFn.call(gl, target, TEXTURE_WRAP_R, options.wrap);\n }\n }\n if (options.wrapR) {\n parameteriFn.call(gl, target, TEXTURE_WRAP_R, options.wrapR);\n }\n if (options.wrapS) {\n parameteriFn.call(gl, target, TEXTURE_WRAP_S, options.wrapS);\n }\n if (options.wrapT) {\n parameteriFn.call(gl, target, TEXTURE_WRAP_T, options.wrapT);\n }\n if (options.minLod !== undefined) {\n parameteriFn.call(gl, target, TEXTURE_MIN_LOD, options.minLod);\n }\n if (options.maxLod !== undefined) {\n parameteriFn.call(gl, target, TEXTURE_MAX_LOD, options.maxLod);\n }\n if (options.baseLevel !== undefined) {\n parameteriFn.call(gl, target, TEXTURE_BASE_LEVEL, options.baseLevel);\n }\n if (options.maxLevel !== undefined) {\n parameteriFn.call(gl, target, TEXTURE_MAX_LEVEL, options.maxLevel);\n }\n if (options.compareFunc !== undefined) {\n parameteriFn.call(gl, target, TEXTURE_COMPARE_FUNC, options.compareFunc);\n }\n if (options.compareMode !== undefined) {\n parameteriFn.call(gl, target, TEXTURE_COMPARE_MODE, options.compareMode);\n }\n}\n\n/**\n * Sets the texture parameters of a texture.\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {WebGLTexture} tex the WebGLTexture to set parameters for\n * @param {module:twgl.TextureOptions} options A TextureOptions object with whatever parameters you want set.\n * This is often the same options you passed in when you created the texture.\n * @memberOf module:twgl/textures\n */\nfunction setTextureParameters(gl, tex, options) {\n const target = options.target || TEXTURE_2D$2;\n gl.bindTexture(target, tex);\n setTextureSamplerParameters(gl, target, gl.texParameteri, options);\n}\n\n/**\n * Sets the sampler parameters of a sampler.\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {WebGLSampler} sampler the WebGLSampler to set parameters for\n * @param {module:twgl.TextureOptions} options A TextureOptions object with whatever parameters you want set.\n * @memberOf module:twgl/textures\n */\nfunction setSamplerParameters(gl, sampler, options) {\n setTextureSamplerParameters(gl, sampler, gl.samplerParameteri, options);\n}\n\n/**\n * Creates a new sampler object and sets parameters.\n *\n * Example:\n *\n * const sampler = twgl.createSampler(gl, {\n * minMag: gl.NEAREST, // sets both TEXTURE_MIN_FILTER and TEXTURE_MAG_FILTER\n * wrap: gl.CLAMP_TO_NEAREST, // sets both TEXTURE_WRAP_S and TEXTURE_WRAP_T and TEXTURE_WRAP_R\n * });\n *\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {Object.} options A object of TextureOptions one per sampler.\n * @return {Object.} the created samplers by name\n * @private\n */\nfunction createSampler(gl, options) {\n const sampler = gl.createSampler();\n setSamplerParameters(gl, sampler, options);\n return sampler;\n}\n\n/**\n * Creates a multiple sampler objects and sets parameters on each.\n *\n * Example:\n *\n * const samplers = twgl.createSamplers(gl, {\n * nearest: {\n * minMag: gl.NEAREST,\n * },\n * nearestClampS: {\n * minMag: gl.NEAREST,\n * wrapS: gl.CLAMP_TO_NEAREST,\n * },\n * linear: {\n * minMag: gl.LINEAR,\n * },\n * nearestClamp: {\n * minMag: gl.NEAREST,\n * wrap: gl.CLAMP_TO_EDGE,\n * },\n * linearClamp: {\n * minMag: gl.LINEAR,\n * wrap: gl.CLAMP_TO_EDGE,\n * },\n * linearClampT: {\n * minMag: gl.LINEAR,\n * wrapT: gl.CLAMP_TO_EDGE,\n * },\n * });\n *\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {module:twgl.TextureOptions} [options] A TextureOptions object with whatever parameters you want set on the sampler\n * @private\n */\nfunction createSamplers(gl, samplerOptions) {\n const samplers = {};\n Object.keys(samplerOptions).forEach(function(name) {\n samplers[name] = createSampler(gl, samplerOptions[name]);\n });\n return samplers;\n}\n\n/**\n * Makes a 1x1 pixel\n * If no color is passed in uses the default color which can be set by calling `setDefaultTextureColor`.\n * @param {(number[]|ArrayBufferView)} [color] The color using 0-1 values\n * @return {Uint8Array} Unit8Array with color.\n * @private\n */\nfunction make1Pixel(color) {\n color = color || defaults$1.textureColor;\n if (isArrayBuffer(color)) {\n return color;\n }\n return new Uint8Array([color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255]);\n}\n\n/**\n * Sets filtering or generates mips for texture based on width or height\n * If width or height is not passed in uses `options.width` and//or `options.height`\n *\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {WebGLTexture} tex the WebGLTexture to set parameters for\n * @param {module:twgl.TextureOptions} [options] A TextureOptions object with whatever parameters you want set.\n * This is often the same options you passed in when you created the texture.\n * @param {number} [width] width of texture\n * @param {number} [height] height of texture\n * @param {number} [internalFormat] The internalFormat parameter from texImage2D etc..\n * @memberOf module:twgl/textures\n */\nfunction setTextureFilteringForSize(gl, tex, options, width, height, internalFormat) {\n options = options || defaults$1.textureOptions;\n internalFormat = internalFormat || RGBA$1;\n const target = options.target || TEXTURE_2D$2;\n width = width || options.width;\n height = height || options.height;\n gl.bindTexture(target, tex);\n if (canGenerateMipmap(gl, width, height, internalFormat)) {\n gl.generateMipmap(target);\n } else {\n const filtering = canFilter(internalFormat) ? LINEAR$1 : NEAREST;\n gl.texParameteri(target, TEXTURE_MIN_FILTER, filtering);\n gl.texParameteri(target, TEXTURE_MAG_FILTER, filtering);\n gl.texParameteri(target, TEXTURE_WRAP_S, CLAMP_TO_EDGE$1);\n gl.texParameteri(target, TEXTURE_WRAP_T, CLAMP_TO_EDGE$1);\n }\n}\n\nfunction shouldAutomaticallySetTextureFilteringForSize(options) {\n return options.auto === true || (options.auto === undefined && options.level === undefined);\n}\n\n/**\n * Gets an array of cubemap face enums\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {module:twgl.TextureOptions} options A TextureOptions object with whatever parameters you want set.\n * This is often the same options you passed in when you created the texture.\n * @return {number[]} cubemap face enums\n * @private\n */\nfunction getCubeFaceOrder(gl, options) {\n options = options || {};\n return options.cubeFaceOrder || [\n TEXTURE_CUBE_MAP_POSITIVE_X,\n TEXTURE_CUBE_MAP_NEGATIVE_X,\n TEXTURE_CUBE_MAP_POSITIVE_Y,\n TEXTURE_CUBE_MAP_NEGATIVE_Y,\n TEXTURE_CUBE_MAP_POSITIVE_Z,\n TEXTURE_CUBE_MAP_NEGATIVE_Z,\n ];\n}\n\n/**\n * @typedef {Object} FaceInfo\n * @property {number} face gl enum for texImage2D\n * @property {number} ndx face index (0 - 5) into source data\n * @ignore\n */\n\n/**\n * Gets an array of FaceInfos\n * There's a bug in some NVidia drivers that will crash the driver if\n * `gl.TEXTURE_CUBE_MAP_POSITIVE_X` is not uploaded first. So, we take\n * the user's desired order from his faces to WebGL and make sure we\n * do the faces in WebGL order\n *\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {module:twgl.TextureOptions} options A TextureOptions object with whatever parameters you want set.\n * @return {FaceInfo[]} cubemap face infos. Arguably the `face` property of each element is redundant but\n * it's needed internally to sort the array of `ndx` properties by `face`.\n * @private\n */\nfunction getCubeFacesWithNdx(gl, options) {\n const faces = getCubeFaceOrder(gl, options);\n // work around bug in NVidia drivers. We have to upload the first face first else the driver crashes :(\n const facesWithNdx = faces.map(function(face, ndx) {\n return { face: face, ndx: ndx };\n });\n facesWithNdx.sort(function(a, b) {\n return a.face - b.face;\n });\n return facesWithNdx;\n}\n\n/**\n * Set a texture from the contents of an element. Will also set\n * texture filtering or generate mips based on the dimensions of the element\n * unless `options.auto === false`. If `target === gl.TEXTURE_CUBE_MAP` will\n * attempt to slice image into 1x6, 2x3, 3x2, or 6x1 images, one for each face.\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {WebGLTexture} tex the WebGLTexture to set parameters for\n * @param {HTMLElement} element a canvas, img, or video element.\n * @param {module:twgl.TextureOptions} [options] A TextureOptions object with whatever parameters you want set.\n * This is often the same options you passed in when you created the texture.\n * @memberOf module:twgl/textures\n * @kind function\n */\nfunction setTextureFromElement(gl, tex, element, options) {\n options = options || defaults$1.textureOptions;\n const target = options.target || TEXTURE_2D$2;\n const level = options.level || 0;\n let width = element.width;\n let height = element.height;\n const internalFormat = options.internalFormat || options.format || RGBA$1;\n const formatType = getFormatAndTypeForInternalFormat(internalFormat);\n const format = options.format || formatType.format;\n const type = options.type || formatType.type;\n setPackState(gl, options);\n gl.bindTexture(target, tex);\n if (target === TEXTURE_CUBE_MAP$1) {\n // guess the parts\n const imgWidth = element.width;\n const imgHeight = element.height;\n let size;\n let slices;\n if (imgWidth / 6 === imgHeight) {\n // It's 6x1\n size = imgHeight;\n slices = [0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0];\n } else if (imgHeight / 6 === imgWidth) {\n // It's 1x6\n size = imgWidth;\n slices = [0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5];\n } else if (imgWidth / 3 === imgHeight / 2) {\n // It's 3x2\n size = imgWidth / 3;\n slices = [0, 0, 1, 0, 2, 0, 0, 1, 1, 1, 2, 1];\n } else if (imgWidth / 2 === imgHeight / 3) {\n // It's 2x3\n size = imgWidth / 2;\n slices = [0, 0, 1, 0, 0, 1, 1, 1, 0, 2, 1, 2];\n } else {\n throw \"can't figure out cube map from element: \" + (element.src ? element.src : element.nodeName);\n }\n const ctx = getShared2DContext();\n if (ctx) {\n ctx.canvas.width = size;\n ctx.canvas.height = size;\n width = size;\n height = size;\n getCubeFacesWithNdx(gl, options).forEach(function(f) {\n const xOffset = slices[f.ndx * 2 + 0] * size;\n const yOffset = slices[f.ndx * 2 + 1] * size;\n ctx.drawImage(element, xOffset, yOffset, size, size, 0, 0, size, size);\n gl.texImage2D(f.face, level, internalFormat, format, type, ctx.canvas);\n });\n // Free up the canvas memory\n ctx.canvas.width = 1;\n ctx.canvas.height = 1;\n } else if (typeof createImageBitmap !== 'undefined') {\n // NOTE: It seems like we should prefer ImageBitmap because unlike canvas it's\n // note lossy? (alpha is not premultiplied? although I'm not sure what\n width = size;\n height = size;\n getCubeFacesWithNdx(gl, options).forEach(function(f) {\n const xOffset = slices[f.ndx * 2 + 0] * size;\n const yOffset = slices[f.ndx * 2 + 1] * size;\n // We can't easily use a default texture color here as it would have to match\n // the type across all faces where as with a 2D one there's only one face\n // so we're replacing everything all at once. It also has to be the correct size.\n // On the other hand we need all faces to be the same size so as one face loads\n // the rest match else the texture will be un-renderable.\n gl.texImage2D(f.face, level, internalFormat, size, size, 0, format, type, null);\n createImageBitmap(element, xOffset, yOffset, size, size, {\n premultiplyAlpha: 'none',\n colorSpaceConversion: 'none',\n })\n .then(function(imageBitmap) {\n setPackState(gl, options);\n gl.bindTexture(target, tex);\n gl.texImage2D(f.face, level, internalFormat, format, type, imageBitmap);\n if (shouldAutomaticallySetTextureFilteringForSize(options)) {\n setTextureFilteringForSize(gl, tex, options, width, height, internalFormat);\n }\n });\n });\n }\n } else if (target === TEXTURE_3D$1 || target === TEXTURE_2D_ARRAY$1) {\n const smallest = Math.min(element.width, element.height);\n const largest = Math.max(element.width, element.height);\n const depth = largest / smallest;\n if (depth % 1 !== 0) {\n throw \"can not compute 3D dimensions of element\";\n }\n const xMult = element.width === largest ? 1 : 0;\n const yMult = element.height === largest ? 1 : 0;\n gl.pixelStorei(UNPACK_ALIGNMENT, 1);\n gl.pixelStorei(UNPACK_ROW_LENGTH, element.width);\n gl.pixelStorei(UNPACK_IMAGE_HEIGHT, 0);\n gl.pixelStorei(UNPACK_SKIP_IMAGES, 0);\n gl.texImage3D(target, level, internalFormat, smallest, smallest, smallest, 0, format, type, null);\n for (let d = 0; d < depth; ++d) {\n const srcX = d * smallest * xMult;\n const srcY = d * smallest * yMult;\n gl.pixelStorei(UNPACK_SKIP_PIXELS, srcX);\n gl.pixelStorei(UNPACK_SKIP_ROWS, srcY);\n gl.texSubImage3D(target, level, 0, 0, d, smallest, smallest, 1, format, type, element);\n }\n setSkipStateToDefault(gl);\n } else {\n gl.texImage2D(target, level, internalFormat, format, type, element);\n }\n if (shouldAutomaticallySetTextureFilteringForSize(options)) {\n setTextureFilteringForSize(gl, tex, options, width, height, internalFormat);\n }\n setTextureParameters(gl, tex, options);\n}\n\nfunction noop() {\n}\n\n/**\n * Checks whether the url's origin is the same so that we can set the `crossOrigin`\n * @param {string} url url to image\n * @returns {boolean} true if the window's origin is the same as image's url\n * @private\n */\nfunction urlIsSameOrigin(url) {\n if (typeof document !== 'undefined') {\n // for IE really\n const a = document.createElement('a');\n a.href = url;\n return a.hostname === location.hostname &&\n a.port === location.port &&\n a.protocol === location.protocol;\n } else {\n const localOrigin = (new URL(location.href)).origin;\n const urlOrigin = (new URL(url, location.href)).origin;\n return urlOrigin === localOrigin;\n }\n}\n\nfunction setToAnonymousIfUndefinedAndURLIsNotSameOrigin(url, crossOrigin) {\n return crossOrigin === undefined && !urlIsSameOrigin(url)\n ? 'anonymous'\n : crossOrigin;\n}\n\n/**\n * Loads an image\n * @param {string} url url to image\n * @param {string} crossOrigin\n * @param {function(err, img)} [callback] a callback that's passed an error and the image. The error will be non-null\n * if there was an error\n * @return {HTMLImageElement} the image being loaded.\n * @private\n */\nfunction loadImage(url, crossOrigin, callback) {\n callback = callback || noop;\n let img;\n crossOrigin = crossOrigin !== undefined ? crossOrigin : defaults$1.crossOrigin;\n crossOrigin = setToAnonymousIfUndefinedAndURLIsNotSameOrigin(url, crossOrigin);\n if (typeof Image !== 'undefined') {\n img = new Image();\n if (crossOrigin !== undefined) {\n img.crossOrigin = crossOrigin;\n }\n\n const clearEventHandlers = function clearEventHandlers() {\n img.removeEventListener('error', onError); // eslint-disable-line\n img.removeEventListener('load', onLoad); // eslint-disable-line\n img = null;\n };\n\n const onError = function onError() {\n const msg = \"couldn't load image: \" + url;\n error$1(msg);\n callback(msg, img);\n clearEventHandlers();\n };\n\n const onLoad = function onLoad() {\n callback(null, img);\n clearEventHandlers();\n };\n\n img.addEventListener('error', onError);\n img.addEventListener('load', onLoad);\n img.src = url;\n return img;\n } else if (typeof ImageBitmap !== 'undefined') {\n let err;\n let bm;\n const cb = function cb() {\n callback(err, bm);\n };\n\n const options = {};\n if (crossOrigin) {\n options.mode = 'cors'; // TODO: not sure how to translate image.crossOrigin\n }\n fetch(url, options).then(function(response) {\n if (!response.ok) {\n throw response;\n }\n return response.blob();\n }).then(function(blob) {\n return createImageBitmap(blob, {\n premultiplyAlpha: 'none',\n colorSpaceConversion: 'none',\n });\n }).then(function(bitmap) {\n // not sure if this works. We don't want\n // to catch the user's error. So, call\n // the callback in a timeout so we're\n // not in this scope inside the promise.\n bm = bitmap;\n setTimeout(cb);\n }).catch(function(e) {\n err = e;\n setTimeout(cb);\n });\n img = null;\n }\n return img;\n}\n\n/**\n * check if object is a TexImageSource\n *\n * @param {Object} obj Object to test\n * @return {boolean} true if object is a TexImageSource\n * @private\n */\nfunction isTexImageSource(obj) {\n return (typeof ImageBitmap !== 'undefined' && obj instanceof ImageBitmap) ||\n (typeof ImageData !== 'undefined' && obj instanceof ImageData) ||\n (typeof HTMLElement !== 'undefined' && obj instanceof HTMLElement);\n}\n\n/**\n * if obj is an TexImageSource then just\n * uses it otherwise if obj is a string\n * then load it first.\n *\n * @param {string|TexImageSource} obj\n * @param {string} crossOrigin\n * @param {function(err, img)} [callback] a callback that's passed an error and the image. The error will be non-null\n * if there was an error\n * @private\n */\nfunction loadAndUseImage(obj, crossOrigin, callback) {\n if (isTexImageSource(obj)) {\n setTimeout(function() {\n callback(null, obj);\n });\n return obj;\n }\n\n return loadImage(obj, crossOrigin, callback);\n}\n\n/**\n * Sets a texture to a 1x1 pixel color. If `options.color === false` is nothing happens. If it's not set\n * the default texture color is used which can be set by calling `setDefaultTextureColor`.\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {WebGLTexture} tex the WebGLTexture to set parameters for\n * @param {module:twgl.TextureOptions} [options] A TextureOptions object with whatever parameters you want set.\n * This is often the same options you passed in when you created the texture.\n * @memberOf module:twgl/textures\n * @private\n */\nfunction setTextureTo1PixelColor(gl, tex, options) {\n options = options || defaults$1.textureOptions;\n const target = options.target || TEXTURE_2D$2;\n gl.bindTexture(target, tex);\n if (options.color === false) {\n return;\n }\n // Assume it's a URL\n // Put 1x1 pixels in texture. That makes it renderable immediately regardless of filtering.\n const color = make1Pixel(options.color);\n if (target === TEXTURE_CUBE_MAP$1) {\n for (let ii = 0; ii < 6; ++ii) {\n gl.texImage2D(TEXTURE_CUBE_MAP_POSITIVE_X + ii, 0, RGBA$1, 1, 1, 0, RGBA$1, UNSIGNED_BYTE$1, color);\n }\n } else if (target === TEXTURE_3D$1 || target === TEXTURE_2D_ARRAY$1) {\n gl.texImage3D(target, 0, RGBA$1, 1, 1, 1, 0, RGBA$1, UNSIGNED_BYTE$1, color);\n } else {\n gl.texImage2D(target, 0, RGBA$1, 1, 1, 0, RGBA$1, UNSIGNED_BYTE$1, color);\n }\n}\n\n/**\n * The src image(s) used to create a texture.\n *\n * When you call {@link module:twgl.createTexture} or {@link module:twgl.createTextures}\n * you can pass in urls for images to load into the textures. If it's a single url\n * then this will be a single HTMLImageElement. If it's an array of urls used for a cubemap\n * this will be a corresponding array of images for the cubemap.\n *\n * @typedef {HTMLImageElement|HTMLImageElement[]} TextureSrc\n * @memberOf module:twgl\n */\n\n/**\n * A callback for when an image finished downloading and been uploaded into a texture\n * @callback TextureReadyCallback\n * @param {*} err If truthy there was an error.\n * @param {WebGLTexture} texture the texture.\n * @param {module:twgl.TextureSrc} source image(s) used to as the src for the texture\n * @memberOf module:twgl\n */\n\n/**\n * A callback for when all images have finished downloading and been uploaded into their respective textures\n * @callback TexturesReadyCallback\n * @param {*} err If truthy there was an error.\n * @param {Object.} textures the created textures by name. Same as returned by {@link module:twgl.createTextures}.\n * @param {Object.} sources the image(s) used for the texture by name.\n * @memberOf module:twgl\n */\n\n/**\n * A callback for when an image finished downloading and been uploaded into a texture\n * @callback CubemapReadyCallback\n * @param {*} err If truthy there was an error.\n * @param {WebGLTexture} tex the texture.\n * @param {HTMLImageElement[]} imgs the images for each face.\n * @memberOf module:twgl\n */\n\n/**\n * A callback for when an image finished downloading and been uploaded into a texture\n * @callback ThreeDReadyCallback\n * @param {*} err If truthy there was an error.\n * @param {WebGLTexture} tex the texture.\n * @param {HTMLImageElement[]} imgs the images for each slice.\n * @memberOf module:twgl\n */\n\n/**\n * Loads a texture from an image from a Url as specified in `options.src`\n * If `options.color !== false` will set the texture to a 1x1 pixel color so that the texture is\n * immediately useable. It will be updated with the contents of the image once the image has finished\n * downloading. Filtering options will be set as appropriate for image unless `options.auto === false`.\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {WebGLTexture} tex the WebGLTexture to set parameters for\n * @param {module:twgl.TextureOptions} [options] A TextureOptions object with whatever parameters you want set.\n * @param {module:twgl.TextureReadyCallback} [callback] A function to be called when the image has finished loading. err will\n * be non null if there was an error.\n * @return {HTMLImageElement} the image being downloaded.\n * @memberOf module:twgl/textures\n */\nfunction loadTextureFromUrl(gl, tex, options, callback) {\n callback = callback || noop;\n options = options || defaults$1.textureOptions;\n setTextureTo1PixelColor(gl, tex, options);\n // Because it's async we need to copy the options.\n options = Object.assign({}, options);\n const img = loadAndUseImage(options.src, options.crossOrigin, function(err, img) {\n if (err) {\n callback(err, tex, img);\n } else {\n setTextureFromElement(gl, tex, img, options);\n callback(null, tex, img);\n }\n });\n return img;\n}\n\n/**\n * Loads a cubemap from 6 urls or TexImageSources as specified in `options.src`. Will set the cubemap to a 1x1 pixel color\n * so that it is usable immediately unless `option.color === false`.\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {WebGLTexture} tex the WebGLTexture to set parameters for\n * @param {module:twgl.TextureOptions} options A TextureOptions object with whatever parameters you want set.\n * @param {module:twgl.CubemapReadyCallback} [callback] A function to be called when all the images have finished loading. err will\n * be non null if there was an error.\n * @memberOf module:twgl/textures\n * @private\n */\nfunction loadCubemapFromUrls(gl, tex, options, callback) {\n callback = callback || noop;\n const urls = options.src;\n if (urls.length !== 6) {\n throw \"there must be 6 urls for a cubemap\";\n }\n const level = options.level || 0;\n const internalFormat = options.internalFormat || options.format || RGBA$1;\n const formatType = getFormatAndTypeForInternalFormat(internalFormat);\n const format = options.format || formatType.format;\n const type = options.type || UNSIGNED_BYTE$1;\n const target = options.target || TEXTURE_2D$2;\n if (target !== TEXTURE_CUBE_MAP$1) {\n throw \"target must be TEXTURE_CUBE_MAP\";\n }\n setTextureTo1PixelColor(gl, tex, options);\n // Because it's async we need to copy the options.\n options = Object.assign({}, options);\n let numToLoad = 6;\n const errors = [];\n const faces = getCubeFaceOrder(gl, options);\n let imgs; // eslint-disable-line\n\n function uploadImg(faceTarget) {\n return function(err, img) {\n --numToLoad;\n if (err) {\n errors.push(err);\n } else {\n if (img.width !== img.height) {\n errors.push(\"cubemap face img is not a square: \" + img.src);\n } else {\n setPackState(gl, options);\n gl.bindTexture(target, tex);\n\n // So assuming this is the first image we now have one face that's img sized\n // and 5 faces that are 1x1 pixel so size the other faces\n if (numToLoad === 5) {\n // use the default order\n getCubeFaceOrder().forEach(function(otherTarget) {\n // Should we re-use the same face or a color?\n gl.texImage2D(otherTarget, level, internalFormat, format, type, img);\n });\n } else {\n gl.texImage2D(faceTarget, level, internalFormat, format, type, img);\n }\n\n if (shouldAutomaticallySetTextureFilteringForSize(options)) {\n gl.generateMipmap(target);\n }\n }\n }\n\n if (numToLoad === 0) {\n callback(errors.length ? errors : undefined, tex, imgs);\n }\n };\n }\n\n imgs = urls.map(function(url, ndx) {\n return loadAndUseImage(url, options.crossOrigin, uploadImg(faces[ndx]));\n });\n}\n\n/**\n * Loads a 2d array or 3d texture from urls OR TexImageSources as specified in `options.src`.\n * Will set the texture to a 1x1 pixel color\n * so that it is usable immediately unless `option.color === false`.\n *\n * If the width and height is not specified the width and height of the first\n * image loaded will be used. Note that since images are loaded async\n * which image downloads first is unknown.\n *\n * If an image is not the same size as the width and height it will be scaled\n * to that width and height.\n *\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {WebGLTexture} tex the WebGLTexture to set parameters for\n * @param {module:twgl.TextureOptions} options A TextureOptions object with whatever parameters you want set.\n * @param {module:twgl.ThreeDReadyCallback} [callback] A function to be called when all the images have finished loading. err will\n * be non null if there was an error.\n * @memberOf module:twgl/textures\n * @private\n */\nfunction loadSlicesFromUrls(gl, tex, options, callback) {\n callback = callback || noop;\n const urls = options.src;\n const internalFormat = options.internalFormat || options.format || RGBA$1;\n const formatType = getFormatAndTypeForInternalFormat(internalFormat);\n const format = options.format || formatType.format;\n const type = options.type || UNSIGNED_BYTE$1;\n const target = options.target || TEXTURE_2D_ARRAY$1;\n if (target !== TEXTURE_3D$1 && target !== TEXTURE_2D_ARRAY$1) {\n throw \"target must be TEXTURE_3D or TEXTURE_2D_ARRAY\";\n }\n setTextureTo1PixelColor(gl, tex, options);\n // Because it's async we need to copy the options.\n options = Object.assign({}, options);\n let numToLoad = urls.length;\n const errors = [];\n let imgs; // eslint-disable-line\n const level = options.level || 0;\n let width = options.width;\n let height = options.height;\n const depth = urls.length;\n let firstImage = true;\n\n function uploadImg(slice) {\n return function(err, img) {\n --numToLoad;\n if (err) {\n errors.push(err);\n } else {\n setPackState(gl, options);\n gl.bindTexture(target, tex);\n\n if (firstImage) {\n firstImage = false;\n width = options.width || img.width;\n height = options.height || img.height;\n gl.texImage3D(target, level, internalFormat, width, height, depth, 0, format, type, null);\n\n // put it in every slice otherwise some slices will be 0,0,0,0\n for (let s = 0; s < depth; ++s) {\n gl.texSubImage3D(target, level, 0, 0, s, width, height, 1, format, type, img);\n }\n } else {\n let src = img;\n let ctx;\n if (img.width !== width || img.height !== height) {\n // Size the image to fix\n ctx = getShared2DContext();\n src = ctx.canvas;\n ctx.canvas.width = width;\n ctx.canvas.height = height;\n ctx.drawImage(img, 0, 0, width, height);\n }\n\n gl.texSubImage3D(target, level, 0, 0, slice, width, height, 1, format, type, src);\n\n // free the canvas memory\n if (ctx && src === ctx.canvas) {\n ctx.canvas.width = 0;\n ctx.canvas.height = 0;\n }\n }\n\n if (shouldAutomaticallySetTextureFilteringForSize(options)) {\n gl.generateMipmap(target);\n }\n }\n\n if (numToLoad === 0) {\n callback(errors.length ? errors : undefined, tex, imgs);\n }\n };\n }\n\n imgs = urls.map(function(url, ndx) {\n return loadAndUseImage(url, options.crossOrigin, uploadImg(ndx));\n });\n}\n\n/**\n * Sets a texture from an array or typed array. If the width or height is not provided will attempt to\n * guess the size. See {@link module:twgl.TextureOptions}.\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {WebGLTexture} tex the WebGLTexture to set parameters for\n * @param {(number[]|ArrayBufferView)} src An array or typed arry with texture data.\n * @param {module:twgl.TextureOptions} [options] A TextureOptions object with whatever parameters you want set.\n * This is often the same options you passed in when you created the texture.\n * @memberOf module:twgl/textures\n */\nfunction setTextureFromArray(gl, tex, src, options) {\n options = options || defaults$1.textureOptions;\n const target = options.target || TEXTURE_2D$2;\n gl.bindTexture(target, tex);\n let width = options.width;\n let height = options.height;\n let depth = options.depth;\n const level = options.level || 0;\n const internalFormat = options.internalFormat || options.format || RGBA$1;\n const formatType = getFormatAndTypeForInternalFormat(internalFormat);\n const format = options.format || formatType.format;\n const type = options.type || getTextureTypeForArrayType(gl, src, formatType.type);\n if (!isArrayBuffer(src)) {\n const Type = getTypedArrayTypeForGLType(type);\n src = new Type(src);\n } else if (src instanceof Uint8ClampedArray) {\n src = new Uint8Array(src.buffer);\n }\n\n const bytesPerElement = getBytesPerElementForInternalFormat(internalFormat, type);\n const numElements = src.byteLength / bytesPerElement; // TODO: check UNPACK_ALIGNMENT?\n if (numElements % 1) {\n throw \"length wrong size for format: \" + glEnumToString(gl, format);\n }\n let dimensions;\n if (target === TEXTURE_3D$1 || target === TEXTURE_2D_ARRAY$1) {\n if (!width && !height && !depth) {\n const size = Math.cbrt(numElements);\n if (size % 1 !== 0) {\n throw \"can't guess cube size of array of numElements: \" + numElements;\n }\n width = size;\n height = size;\n depth = size;\n } else if (width && (!height || !depth)) {\n dimensions = guessDimensions(gl, target, height, depth, numElements / width);\n height = dimensions.width;\n depth = dimensions.height;\n } else if (height && (!width || !depth)) {\n dimensions = guessDimensions(gl, target, width, depth, numElements / height);\n width = dimensions.width;\n depth = dimensions.height;\n } else {\n dimensions = guessDimensions(gl, target, width, height, numElements / depth);\n width = dimensions.width;\n height = dimensions.height;\n }\n } else {\n dimensions = guessDimensions(gl, target, width, height, numElements);\n width = dimensions.width;\n height = dimensions.height;\n }\n setSkipStateToDefault(gl);\n gl.pixelStorei(UNPACK_ALIGNMENT, options.unpackAlignment || 1);\n setPackState(gl, options);\n if (target === TEXTURE_CUBE_MAP$1) {\n const elementsPerElement = bytesPerElement / src.BYTES_PER_ELEMENT;\n const faceSize = numElements / 6 * elementsPerElement;\n\n getCubeFacesWithNdx(gl, options).forEach(f => {\n const offset = faceSize * f.ndx;\n const data = src.subarray(offset, offset + faceSize);\n gl.texImage2D(f.face, level, internalFormat, width, height, 0, format, type, data);\n });\n } else if (target === TEXTURE_3D$1 || target === TEXTURE_2D_ARRAY$1) {\n gl.texImage3D(target, level, internalFormat, width, height, depth, 0, format, type, src);\n } else {\n gl.texImage2D(target, level, internalFormat, width, height, 0, format, type, src);\n }\n return {\n width: width,\n height: height,\n depth: depth,\n type: type,\n };\n}\n\n/**\n * Sets a texture with no contents of a certain size. In other words calls `gl.texImage2D` with `null`.\n * You must set `options.width` and `options.height`.\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {WebGLTexture} tex the WebGLTexture to set parameters for\n * @param {module:twgl.TextureOptions} options A TextureOptions object with whatever parameters you want set.\n * @memberOf module:twgl/textures\n */\nfunction setEmptyTexture(gl, tex, options) {\n const target = options.target || TEXTURE_2D$2;\n gl.bindTexture(target, tex);\n const level = options.level || 0;\n const internalFormat = options.internalFormat || options.format || RGBA$1;\n const formatType = getFormatAndTypeForInternalFormat(internalFormat);\n const format = options.format || formatType.format;\n const type = options.type || formatType.type;\n setPackState(gl, options);\n if (target === TEXTURE_CUBE_MAP$1) {\n for (let ii = 0; ii < 6; ++ii) {\n gl.texImage2D(TEXTURE_CUBE_MAP_POSITIVE_X + ii, level, internalFormat, options.width, options.height, 0, format, type, null);\n }\n } else if (target === TEXTURE_3D$1 || target === TEXTURE_2D_ARRAY$1) {\n gl.texImage3D(target, level, internalFormat, options.width, options.height, options.depth, 0, format, type, null);\n } else {\n gl.texImage2D(target, level, internalFormat, options.width, options.height, 0, format, type, null);\n }\n}\n\n/**\n * Creates a texture based on the options passed in.\n *\n * Note: may reset UNPACK_ALIGNMENT, UNPACK_ROW_LENGTH, UNPACK_IMAGE_HEIGHT, UNPACK_SKIP_IMAGES\n * UNPACK_SKIP_PIXELS, and UNPACK_SKIP_ROWS\n *\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {module:twgl.TextureOptions} [options] A TextureOptions object with whatever parameters you want set.\n * @param {module:twgl.TextureReadyCallback} [callback] A callback called when an image has been downloaded and uploaded to the texture.\n * @return {WebGLTexture} the created texture.\n * @memberOf module:twgl/textures\n */\nfunction createTexture(gl, options, callback) {\n callback = callback || noop;\n options = options || defaults$1.textureOptions;\n const tex = gl.createTexture();\n const target = options.target || TEXTURE_2D$2;\n let width = options.width || 1;\n let height = options.height || 1;\n const internalFormat = options.internalFormat || RGBA$1;\n gl.bindTexture(target, tex);\n if (target === TEXTURE_CUBE_MAP$1) {\n // this should have been the default for cubemaps :(\n gl.texParameteri(target, TEXTURE_WRAP_S, CLAMP_TO_EDGE$1);\n gl.texParameteri(target, TEXTURE_WRAP_T, CLAMP_TO_EDGE$1);\n }\n let src = options.src;\n if (src) {\n if (typeof src === \"function\") {\n src = src(gl, options);\n }\n if (typeof (src) === \"string\") {\n loadTextureFromUrl(gl, tex, options, callback);\n } else if (isArrayBuffer(src) ||\n (Array.isArray(src) && (\n typeof src[0] === 'number' ||\n Array.isArray(src[0]) ||\n isArrayBuffer(src[0]))\n )\n ) {\n const dimensions = setTextureFromArray(gl, tex, src, options);\n width = dimensions.width;\n height = dimensions.height;\n } else if (Array.isArray(src) && (typeof (src[0]) === 'string' || isTexImageSource(src[0]))) {\n if (target === TEXTURE_CUBE_MAP$1) {\n loadCubemapFromUrls(gl, tex, options, callback);\n } else {\n loadSlicesFromUrls(gl, tex, options, callback);\n }\n } else { // if (isTexImageSource(src))\n setTextureFromElement(gl, tex, src, options);\n width = src.width;\n height = src.height;\n }\n } else {\n setEmptyTexture(gl, tex, options);\n }\n if (shouldAutomaticallySetTextureFilteringForSize(options)) {\n setTextureFilteringForSize(gl, tex, options, width, height, internalFormat);\n }\n setTextureParameters(gl, tex, options);\n return tex;\n}\n\n/**\n * Resizes a texture based on the options passed in.\n *\n * Note: This is not a generic resize anything function.\n * It's mostly used by {@link module:twgl.resizeFramebufferInfo}\n * It will use `options.src` if it exists to try to determine a `type`\n * otherwise it will assume `gl.UNSIGNED_BYTE`. No data is provided\n * for the texture. Texture parameters will be set accordingly\n *\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {WebGLTexture} tex the texture to resize\n * @param {module:twgl.TextureOptions} options A TextureOptions object with whatever parameters you want set.\n * @param {number} [width] the new width. If not passed in will use `options.width`\n * @param {number} [height] the new height. If not passed in will use `options.height`\n * @param {number} [depth] the new depth. If not passed in will use `options.depth`\n * @memberOf module:twgl/textures\n */\nfunction resizeTexture(gl, tex, options, width, height, depth) {\n width = width || options.width;\n height = height || options.height;\n depth = depth || options.depth;\n const target = options.target || TEXTURE_2D$2;\n gl.bindTexture(target, tex);\n const level = options.level || 0;\n const internalFormat = options.internalFormat || options.format || RGBA$1;\n const formatType = getFormatAndTypeForInternalFormat(internalFormat);\n const format = options.format || formatType.format;\n let type;\n const src = options.src;\n if (!src) {\n type = options.type || formatType.type;\n } else if (isArrayBuffer(src) || (Array.isArray(src) && typeof (src[0]) === 'number')) {\n type = options.type || getTextureTypeForArrayType(gl, src, formatType.type);\n } else {\n type = options.type || formatType.type;\n }\n if (target === TEXTURE_CUBE_MAP$1) {\n for (let ii = 0; ii < 6; ++ii) {\n gl.texImage2D(TEXTURE_CUBE_MAP_POSITIVE_X + ii, level, internalFormat, width, height, 0, format, type, null);\n }\n } else if (target === TEXTURE_3D$1 || target === TEXTURE_2D_ARRAY$1) {\n gl.texImage3D(target, level, internalFormat, width, height, depth, 0, format, type, null);\n } else {\n gl.texImage2D(target, level, internalFormat, width, height, 0, format, type, null);\n }\n}\n\n/**\n * Check if a src is an async request.\n * if src is a string we're going to download an image\n * if src is an array of strings we're going to download cubemap images\n * @param {*} src The src from a TextureOptions\n * @returns {bool} true if src is async.\n * @private\n */\nfunction isAsyncSrc(src) {\n return typeof src === 'string' ||\n (Array.isArray(src) && typeof src[0] === 'string');\n}\n\n/**\n * Creates a bunch of textures based on the passed in options.\n *\n * Example:\n *\n * const textures = twgl.createTextures(gl, {\n * // a power of 2 image\n * hftIcon: { src: \"images/hft-icon-16.png\", mag: gl.NEAREST },\n * // a non-power of 2 image\n * clover: { src: \"images/clover.jpg\" },\n * // From a canvas\n * fromCanvas: { src: ctx.canvas },\n * // A cubemap from 6 images\n * yokohama: {\n * target: gl.TEXTURE_CUBE_MAP,\n * src: [\n * 'images/yokohama/posx.jpg',\n * 'images/yokohama/negx.jpg',\n * 'images/yokohama/posy.jpg',\n * 'images/yokohama/negy.jpg',\n * 'images/yokohama/posz.jpg',\n * 'images/yokohama/negz.jpg',\n * ],\n * },\n * // A cubemap from 1 image (can be 1x6, 2x3, 3x2, 6x1)\n * goldengate: {\n * target: gl.TEXTURE_CUBE_MAP,\n * src: 'images/goldengate.jpg',\n * },\n * // A 2x2 pixel texture from a JavaScript array\n * checker: {\n * mag: gl.NEAREST,\n * min: gl.LINEAR,\n * src: [\n * 255,255,255,255,\n * 192,192,192,255,\n * 192,192,192,255,\n * 255,255,255,255,\n * ],\n * },\n * // a 1x2 pixel texture from a typed array.\n * stripe: {\n * mag: gl.NEAREST,\n * min: gl.LINEAR,\n * format: gl.LUMINANCE,\n * src: new Uint8Array([\n * 255,\n * 128,\n * 255,\n * 128,\n * 255,\n * 128,\n * 255,\n * 128,\n * ]),\n * width: 1,\n * },\n * });\n *\n * Now\n *\n * * `textures.hftIcon` will be a 2d texture\n * * `textures.clover` will be a 2d texture\n * * `textures.fromCanvas` will be a 2d texture\n * * `textures.yohohama` will be a cubemap texture\n * * `textures.goldengate` will be a cubemap texture\n * * `textures.checker` will be a 2d texture\n * * `textures.stripe` will be a 2d texture\n *\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {Object.} options A object of TextureOptions one per texture.\n * @param {module:twgl.TexturesReadyCallback} [callback] A callback called when all textures have been downloaded.\n * @return {Object.} the created textures by name\n * @memberOf module:twgl/textures\n */\nfunction createTextures(gl, textureOptions, callback) {\n callback = callback || noop;\n let numDownloading = 0;\n const errors = [];\n const textures = {};\n const images = {};\n\n function callCallbackIfReady() {\n if (numDownloading === 0) {\n setTimeout(function() {\n callback(errors.length ? errors : undefined, textures, images);\n }, 0);\n }\n }\n\n Object.keys(textureOptions).forEach(function(name) {\n const options = textureOptions[name];\n let onLoadFn;\n if (isAsyncSrc(options.src)) {\n onLoadFn = function(err, tex, img) {\n images[name] = img;\n --numDownloading;\n if (err) {\n errors.push(err);\n }\n callCallbackIfReady();\n };\n ++numDownloading;\n }\n textures[name] = createTexture(gl, options, onLoadFn);\n });\n\n // queue the callback if there are no images to download.\n // We do this because if your code is structured to wait for\n // images to download but then you comment out all the async\n // images your code would break.\n callCallbackIfReady();\n\n return textures;\n}\n\nvar textures = /*#__PURE__*/Object.freeze({\n __proto__: null,\n setTextureDefaults_: setDefaults$1,\n createSampler: createSampler,\n createSamplers: createSamplers,\n setSamplerParameters: setSamplerParameters,\n createTexture: createTexture,\n setEmptyTexture: setEmptyTexture,\n setTextureFromArray: setTextureFromArray,\n loadTextureFromUrl: loadTextureFromUrl,\n setTextureFromElement: setTextureFromElement,\n setTextureFilteringForSize: setTextureFilteringForSize,\n setTextureParameters: setTextureParameters,\n setDefaultTextureColor: setDefaultTextureColor,\n createTextures: createTextures,\n resizeTexture: resizeTexture,\n canGenerateMipmap: canGenerateMipmap,\n canFilter: canFilter,\n getNumComponentsForFormat: getNumComponentsForFormat,\n getBytesPerElementForInternalFormat: getBytesPerElementForInternalFormat,\n getFormatAndTypeForInternalFormat: getFormatAndTypeForInternalFormat\n});\n\n/*\n * Copyright 2019 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\n/**\n * Low level shader program related functions\n *\n * You should generally not need to use these functions. They are provided\n * for those cases where you're doing something out of the ordinary\n * and you need lower level access.\n *\n * For backward compatibility they are available at both `twgl.programs` and `twgl`\n * itself\n *\n * See {@link module:twgl} for core functions\n *\n * @module twgl/programs\n */\n\nconst error = error$1;\nconst warn = warn$1;\nfunction getElementById(id) {\n return (typeof document !== 'undefined' && document.getElementById)\n ? document.getElementById(id)\n : null;\n}\n\nconst TEXTURE0 = 0x84c0;\nconst DYNAMIC_DRAW = 0x88e8;\n\nconst ARRAY_BUFFER = 0x8892;\nconst ELEMENT_ARRAY_BUFFER$1 = 0x8893;\nconst UNIFORM_BUFFER = 0x8a11;\nconst TRANSFORM_FEEDBACK_BUFFER = 0x8c8e;\n\nconst TRANSFORM_FEEDBACK = 0x8e22;\n\nconst COMPILE_STATUS = 0x8b81;\nconst LINK_STATUS = 0x8b82;\nconst FRAGMENT_SHADER = 0x8b30;\nconst VERTEX_SHADER = 0x8b31;\nconst SEPARATE_ATTRIBS = 0x8c8d;\n\nconst ACTIVE_UNIFORMS = 0x8b86;\nconst ACTIVE_ATTRIBUTES = 0x8b89;\nconst TRANSFORM_FEEDBACK_VARYINGS = 0x8c83;\nconst ACTIVE_UNIFORM_BLOCKS = 0x8a36;\nconst UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER = 0x8a44;\nconst UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER = 0x8a46;\nconst UNIFORM_BLOCK_DATA_SIZE = 0x8a40;\nconst UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES = 0x8a43;\n\nconst FLOAT = 0x1406;\nconst FLOAT_VEC2 = 0x8B50;\nconst FLOAT_VEC3 = 0x8B51;\nconst FLOAT_VEC4 = 0x8B52;\nconst INT = 0x1404;\nconst INT_VEC2 = 0x8B53;\nconst INT_VEC3 = 0x8B54;\nconst INT_VEC4 = 0x8B55;\nconst BOOL = 0x8B56;\nconst BOOL_VEC2 = 0x8B57;\nconst BOOL_VEC3 = 0x8B58;\nconst BOOL_VEC4 = 0x8B59;\nconst FLOAT_MAT2 = 0x8B5A;\nconst FLOAT_MAT3 = 0x8B5B;\nconst FLOAT_MAT4 = 0x8B5C;\nconst SAMPLER_2D = 0x8B5E;\nconst SAMPLER_CUBE = 0x8B60;\nconst SAMPLER_3D = 0x8B5F;\nconst SAMPLER_2D_SHADOW = 0x8B62;\nconst FLOAT_MAT2x3 = 0x8B65;\nconst FLOAT_MAT2x4 = 0x8B66;\nconst FLOAT_MAT3x2 = 0x8B67;\nconst FLOAT_MAT3x4 = 0x8B68;\nconst FLOAT_MAT4x2 = 0x8B69;\nconst FLOAT_MAT4x3 = 0x8B6A;\nconst SAMPLER_2D_ARRAY = 0x8DC1;\nconst SAMPLER_2D_ARRAY_SHADOW = 0x8DC4;\nconst SAMPLER_CUBE_SHADOW = 0x8DC5;\nconst UNSIGNED_INT = 0x1405;\nconst UNSIGNED_INT_VEC2 = 0x8DC6;\nconst UNSIGNED_INT_VEC3 = 0x8DC7;\nconst UNSIGNED_INT_VEC4 = 0x8DC8;\nconst INT_SAMPLER_2D = 0x8DCA;\nconst INT_SAMPLER_3D = 0x8DCB;\nconst INT_SAMPLER_CUBE = 0x8DCC;\nconst INT_SAMPLER_2D_ARRAY = 0x8DCF;\nconst UNSIGNED_INT_SAMPLER_2D = 0x8DD2;\nconst UNSIGNED_INT_SAMPLER_3D = 0x8DD3;\nconst UNSIGNED_INT_SAMPLER_CUBE = 0x8DD4;\nconst UNSIGNED_INT_SAMPLER_2D_ARRAY = 0x8DD7;\n\nconst TEXTURE_2D$1 = 0x0DE1;\nconst TEXTURE_CUBE_MAP = 0x8513;\nconst TEXTURE_3D = 0x806F;\nconst TEXTURE_2D_ARRAY = 0x8C1A;\n\nconst typeMap = {};\n\n/**\n * Returns the corresponding bind point for a given sampler type\n * @private\n */\nfunction getBindPointForSamplerType(gl, type) {\n return typeMap[type].bindPoint;\n}\n\n// This kind of sucks! If you could compose functions as in `var fn = gl[name];`\n// this code could be a lot smaller but that is sadly really slow (T_T)\n\nfunction floatSetter(gl, location) {\n return function(v) {\n gl.uniform1f(location, v);\n };\n}\n\nfunction floatArraySetter(gl, location) {\n return function(v) {\n gl.uniform1fv(location, v);\n };\n}\n\nfunction floatVec2Setter(gl, location) {\n return function(v) {\n gl.uniform2fv(location, v);\n };\n}\n\nfunction floatVec3Setter(gl, location) {\n return function(v) {\n gl.uniform3fv(location, v);\n };\n}\n\nfunction floatVec4Setter(gl, location) {\n return function(v) {\n gl.uniform4fv(location, v);\n };\n}\n\nfunction intSetter(gl, location) {\n return function(v) {\n gl.uniform1i(location, v);\n };\n}\n\nfunction intArraySetter(gl, location) {\n return function(v) {\n gl.uniform1iv(location, v);\n };\n}\n\nfunction intVec2Setter(gl, location) {\n return function(v) {\n gl.uniform2iv(location, v);\n };\n}\n\nfunction intVec3Setter(gl, location) {\n return function(v) {\n gl.uniform3iv(location, v);\n };\n}\n\nfunction intVec4Setter(gl, location) {\n return function(v) {\n gl.uniform4iv(location, v);\n };\n}\n\nfunction uintSetter(gl, location) {\n return function(v) {\n gl.uniform1ui(location, v);\n };\n}\n\nfunction uintArraySetter(gl, location) {\n return function(v) {\n gl.uniform1uiv(location, v);\n };\n}\n\nfunction uintVec2Setter(gl, location) {\n return function(v) {\n gl.uniform2uiv(location, v);\n };\n}\n\nfunction uintVec3Setter(gl, location) {\n return function(v) {\n gl.uniform3uiv(location, v);\n };\n}\n\nfunction uintVec4Setter(gl, location) {\n return function(v) {\n gl.uniform4uiv(location, v);\n };\n}\n\nfunction floatMat2Setter(gl, location) {\n return function(v) {\n gl.uniformMatrix2fv(location, false, v);\n };\n}\n\nfunction floatMat3Setter(gl, location) {\n return function(v) {\n gl.uniformMatrix3fv(location, false, v);\n };\n}\n\nfunction floatMat4Setter(gl, location) {\n return function(v) {\n gl.uniformMatrix4fv(location, false, v);\n };\n}\n\nfunction floatMat23Setter(gl, location) {\n return function(v) {\n gl.uniformMatrix2x3fv(location, false, v);\n };\n}\n\nfunction floatMat32Setter(gl, location) {\n return function(v) {\n gl.uniformMatrix3x2fv(location, false, v);\n };\n}\n\nfunction floatMat24Setter(gl, location) {\n return function(v) {\n gl.uniformMatrix2x4fv(location, false, v);\n };\n}\n\nfunction floatMat42Setter(gl, location) {\n return function(v) {\n gl.uniformMatrix4x2fv(location, false, v);\n };\n}\n\nfunction floatMat34Setter(gl, location) {\n return function(v) {\n gl.uniformMatrix3x4fv(location, false, v);\n };\n}\n\nfunction floatMat43Setter(gl, location) {\n return function(v) {\n gl.uniformMatrix4x3fv(location, false, v);\n };\n}\n\nfunction samplerSetter(gl, type, unit, location) {\n const bindPoint = getBindPointForSamplerType(gl, type);\n return isWebGL2(gl) ? function(textureOrPair) {\n let texture;\n let sampler;\n if (!textureOrPair || isTexture(gl, textureOrPair)) {\n texture = textureOrPair;\n sampler = null;\n } else {\n texture = textureOrPair.texture;\n sampler = textureOrPair.sampler;\n }\n gl.uniform1i(location, unit);\n gl.activeTexture(TEXTURE0 + unit);\n gl.bindTexture(bindPoint, texture);\n gl.bindSampler(unit, sampler);\n } : function(texture) {\n gl.uniform1i(location, unit);\n gl.activeTexture(TEXTURE0 + unit);\n gl.bindTexture(bindPoint, texture);\n };\n}\n\nfunction samplerArraySetter(gl, type, unit, location, size) {\n const bindPoint = getBindPointForSamplerType(gl, type);\n const units = new Int32Array(size);\n for (let ii = 0; ii < size; ++ii) {\n units[ii] = unit + ii;\n }\n\n return isWebGL2(gl) ? function(textures) {\n gl.uniform1iv(location, units);\n textures.forEach(function(textureOrPair, index) {\n gl.activeTexture(TEXTURE0 + units[index]);\n let texture;\n let sampler;\n if (!textureOrPair || isTexture(gl, textureOrPair)) {\n texture = textureOrPair;\n sampler = null;\n } else {\n texture = textureOrPair.texture;\n sampler = textureOrPair.sampler;\n }\n gl.bindSampler(unit, sampler);\n gl.bindTexture(bindPoint, texture);\n });\n } : function(textures) {\n gl.uniform1iv(location, units);\n textures.forEach(function(texture, index) {\n gl.activeTexture(TEXTURE0 + units[index]);\n gl.bindTexture(bindPoint, texture);\n });\n };\n}\n\ntypeMap[FLOAT] = { Type: Float32Array, size: 4, setter: floatSetter, arraySetter: floatArraySetter, };\ntypeMap[FLOAT_VEC2] = { Type: Float32Array, size: 8, setter: floatVec2Setter, cols: 2, };\ntypeMap[FLOAT_VEC3] = { Type: Float32Array, size: 12, setter: floatVec3Setter, cols: 3, };\ntypeMap[FLOAT_VEC4] = { Type: Float32Array, size: 16, setter: floatVec4Setter, cols: 4, };\ntypeMap[INT] = { Type: Int32Array, size: 4, setter: intSetter, arraySetter: intArraySetter, };\ntypeMap[INT_VEC2] = { Type: Int32Array, size: 8, setter: intVec2Setter, cols: 2, };\ntypeMap[INT_VEC3] = { Type: Int32Array, size: 12, setter: intVec3Setter, cols: 3, };\ntypeMap[INT_VEC4] = { Type: Int32Array, size: 16, setter: intVec4Setter, cols: 4, };\ntypeMap[UNSIGNED_INT] = { Type: Uint32Array, size: 4, setter: uintSetter, arraySetter: uintArraySetter, };\ntypeMap[UNSIGNED_INT_VEC2] = { Type: Uint32Array, size: 8, setter: uintVec2Setter, cols: 2, };\ntypeMap[UNSIGNED_INT_VEC3] = { Type: Uint32Array, size: 12, setter: uintVec3Setter, cols: 3, };\ntypeMap[UNSIGNED_INT_VEC4] = { Type: Uint32Array, size: 16, setter: uintVec4Setter, cols: 4, };\ntypeMap[BOOL] = { Type: Uint32Array, size: 4, setter: intSetter, arraySetter: intArraySetter, };\ntypeMap[BOOL_VEC2] = { Type: Uint32Array, size: 8, setter: intVec2Setter, cols: 2, };\ntypeMap[BOOL_VEC3] = { Type: Uint32Array, size: 12, setter: intVec3Setter, cols: 3, };\ntypeMap[BOOL_VEC4] = { Type: Uint32Array, size: 16, setter: intVec4Setter, cols: 4, };\ntypeMap[FLOAT_MAT2] = { Type: Float32Array, size: 32, setter: floatMat2Setter, rows: 2, cols: 2, };\ntypeMap[FLOAT_MAT3] = { Type: Float32Array, size: 48, setter: floatMat3Setter, rows: 3, cols: 3, };\ntypeMap[FLOAT_MAT4] = { Type: Float32Array, size: 64, setter: floatMat4Setter, rows: 4, cols: 4, };\ntypeMap[FLOAT_MAT2x3] = { Type: Float32Array, size: 32, setter: floatMat23Setter, rows: 2, cols: 3, };\ntypeMap[FLOAT_MAT2x4] = { Type: Float32Array, size: 32, setter: floatMat24Setter, rows: 2, cols: 4, };\ntypeMap[FLOAT_MAT3x2] = { Type: Float32Array, size: 48, setter: floatMat32Setter, rows: 3, cols: 2, };\ntypeMap[FLOAT_MAT3x4] = { Type: Float32Array, size: 48, setter: floatMat34Setter, rows: 3, cols: 4, };\ntypeMap[FLOAT_MAT4x2] = { Type: Float32Array, size: 64, setter: floatMat42Setter, rows: 4, cols: 2, };\ntypeMap[FLOAT_MAT4x3] = { Type: Float32Array, size: 64, setter: floatMat43Setter, rows: 4, cols: 3, };\ntypeMap[SAMPLER_2D] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D$1, };\ntypeMap[SAMPLER_CUBE] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_CUBE_MAP, };\ntypeMap[SAMPLER_3D] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_3D, };\ntypeMap[SAMPLER_2D_SHADOW] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D$1, };\ntypeMap[SAMPLER_2D_ARRAY] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D_ARRAY, };\ntypeMap[SAMPLER_2D_ARRAY_SHADOW] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D_ARRAY, };\ntypeMap[SAMPLER_CUBE_SHADOW] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_CUBE_MAP, };\ntypeMap[INT_SAMPLER_2D] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D$1, };\ntypeMap[INT_SAMPLER_3D] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_3D, };\ntypeMap[INT_SAMPLER_CUBE] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_CUBE_MAP, };\ntypeMap[INT_SAMPLER_2D_ARRAY] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D_ARRAY, };\ntypeMap[UNSIGNED_INT_SAMPLER_2D] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D$1, };\ntypeMap[UNSIGNED_INT_SAMPLER_3D] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_3D, };\ntypeMap[UNSIGNED_INT_SAMPLER_CUBE] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_CUBE_MAP, };\ntypeMap[UNSIGNED_INT_SAMPLER_2D_ARRAY] = { Type: null, size: 0, setter: samplerSetter, arraySetter: samplerArraySetter, bindPoint: TEXTURE_2D_ARRAY, };\n\nfunction floatAttribSetter(gl, index) {\n return function(b) {\n if (b.value) {\n gl.disableVertexAttribArray(index);\n switch (b.value.length) {\n case 4:\n gl.vertexAttrib4fv(index, b.value);\n break;\n case 3:\n gl.vertexAttrib3fv(index, b.value);\n break;\n case 2:\n gl.vertexAttrib2fv(index, b.value);\n break;\n case 1:\n gl.vertexAttrib1fv(index, b.value);\n break;\n default:\n throw new Error('the length of a float constant value must be between 1 and 4!');\n }\n } else {\n gl.bindBuffer(ARRAY_BUFFER, b.buffer);\n gl.enableVertexAttribArray(index);\n gl.vertexAttribPointer(\n index, b.numComponents || b.size, b.type || FLOAT, b.normalize || false, b.stride || 0, b.offset || 0);\n if (gl.vertexAttribDivisor) {\n gl.vertexAttribDivisor(index, b.divisor || 0);\n }\n }\n };\n}\n\nfunction intAttribSetter(gl, index) {\n return function(b) {\n if (b.value) {\n gl.disableVertexAttribArray(index);\n if (b.value.length === 4) {\n gl.vertexAttrib4iv(index, b.value);\n } else {\n throw new Error('The length of an integer constant value must be 4!');\n }\n } else {\n gl.bindBuffer(ARRAY_BUFFER, b.buffer);\n gl.enableVertexAttribArray(index);\n gl.vertexAttribIPointer(\n index, b.numComponents || b.size, b.type || INT, b.stride || 0, b.offset || 0);\n if (gl.vertexAttribDivisor) {\n gl.vertexAttribDivisor(index, b.divisor || 0);\n }\n }\n };\n}\n\nfunction uintAttribSetter(gl, index) {\n return function(b) {\n if (b.value) {\n gl.disableVertexAttribArray(index);\n if (b.value.length === 4) {\n gl.vertexAttrib4uiv(index, b.value);\n } else {\n throw new Error('The length of an unsigned integer constant value must be 4!');\n }\n } else {\n gl.bindBuffer(ARRAY_BUFFER, b.buffer);\n gl.enableVertexAttribArray(index);\n gl.vertexAttribIPointer(\n index, b.numComponents || b.size, b.type || UNSIGNED_INT, b.stride || 0, b.offset || 0);\n if (gl.vertexAttribDivisor) {\n gl.vertexAttribDivisor(index, b.divisor || 0);\n }\n }\n };\n}\n\nfunction matAttribSetter(gl, index, typeInfo) {\n const defaultSize = typeInfo.size;\n const count = typeInfo.count;\n\n return function(b) {\n gl.bindBuffer(ARRAY_BUFFER, b.buffer);\n const numComponents = b.size || b.numComponents || defaultSize;\n const size = numComponents / count;\n const type = b.type || FLOAT;\n const typeInfo = typeMap[type];\n const stride = typeInfo.size * numComponents;\n const normalize = b.normalize || false;\n const offset = b.offset || 0;\n const rowOffset = stride / count;\n for (let i = 0; i < count; ++i) {\n gl.enableVertexAttribArray(index + i);\n gl.vertexAttribPointer(\n index + i, size, type, normalize, stride, offset + rowOffset * i);\n if (gl.vertexAttribDivisor) {\n gl.vertexAttribDivisor(index + i, b.divisor || 0);\n }\n }\n };\n}\n\n\n\nconst attrTypeMap = {};\nattrTypeMap[FLOAT] = { size: 4, setter: floatAttribSetter, };\nattrTypeMap[FLOAT_VEC2] = { size: 8, setter: floatAttribSetter, };\nattrTypeMap[FLOAT_VEC3] = { size: 12, setter: floatAttribSetter, };\nattrTypeMap[FLOAT_VEC4] = { size: 16, setter: floatAttribSetter, };\nattrTypeMap[INT] = { size: 4, setter: intAttribSetter, };\nattrTypeMap[INT_VEC2] = { size: 8, setter: intAttribSetter, };\nattrTypeMap[INT_VEC3] = { size: 12, setter: intAttribSetter, };\nattrTypeMap[INT_VEC4] = { size: 16, setter: intAttribSetter, };\nattrTypeMap[UNSIGNED_INT] = { size: 4, setter: uintAttribSetter, };\nattrTypeMap[UNSIGNED_INT_VEC2] = { size: 8, setter: uintAttribSetter, };\nattrTypeMap[UNSIGNED_INT_VEC3] = { size: 12, setter: uintAttribSetter, };\nattrTypeMap[UNSIGNED_INT_VEC4] = { size: 16, setter: uintAttribSetter, };\nattrTypeMap[BOOL] = { size: 4, setter: intAttribSetter, };\nattrTypeMap[BOOL_VEC2] = { size: 8, setter: intAttribSetter, };\nattrTypeMap[BOOL_VEC3] = { size: 12, setter: intAttribSetter, };\nattrTypeMap[BOOL_VEC4] = { size: 16, setter: intAttribSetter, };\nattrTypeMap[FLOAT_MAT2] = { size: 4, setter: matAttribSetter, count: 2, };\nattrTypeMap[FLOAT_MAT3] = { size: 9, setter: matAttribSetter, count: 3, };\nattrTypeMap[FLOAT_MAT4] = { size: 16, setter: matAttribSetter, count: 4, };\n\nconst errorRE = /ERROR:\\s*\\d+:(\\d+)/gi;\nfunction addLineNumbersWithError(src, log = '', lineOffset = 0) {\n // Note: Error message formats are not defined by any spec so this may or may not work.\n const matches = [...log.matchAll(errorRE)];\n const lineNoToErrorMap = new Map(matches.map((m, ndx) => {\n const lineNo = parseInt(m[1]);\n const next = matches[ndx + 1];\n const end = next ? next.index : log.length;\n const msg = log.substring(m.index, end);\n return [lineNo - 1, msg];\n }));\n return src.split('\\n').map((line, lineNo) => {\n const err = lineNoToErrorMap.get(lineNo);\n return `${lineNo + 1 + lineOffset}: ${line}${err ? `\\n\\n^^^ ${err}` : ''}`;\n }).join('\\n');\n}\n\n/**\n * Error Callback\n * @callback ErrorCallback\n * @param {string} msg error message.\n * @param {number} [lineOffset] amount to add to line number\n * @memberOf module:twgl\n */\n\n/**\n * Program Callback\n * @callback ProgramCallback\n * @param {string} [err] error message, falsy if no error\n * @param {WebGLProgram|module:twgl.ProgramInfo} [result] the program or programInfo\n */\n\nconst spaceRE = /^[ \\t]*\\n/;\n\n/**\n * Remove the first end of line because WebGL 2.0 requires\n * #version 300 es\n * as the first line. No whitespace allowed before that line\n * so\n *\n * \n *\n * Has one line before it which is invalid according to GLSL ES 3.00\n *\n * @param {string} shaderSource The source of the shader\n * @returns {{shaderSource: string, lineOffset: number}}\n * @private\n */\nfunction prepShaderSource(shaderSource) {\n let lineOffset = 0;\n if (spaceRE.test(shaderSource)) {\n lineOffset = 1;\n shaderSource = shaderSource.replace(spaceRE, '');\n }\n return {lineOffset, shaderSource};\n}\n\n/**\n * @param {module:twgl.ProgramOptions} progOptions\n * @param {string} msg\n * @return null\n * @private\n */\nfunction reportError(progOptions, msg) {\n progOptions.errorCallback(msg);\n if (progOptions.callback) {\n setTimeout(() => {\n progOptions.callback(`${msg}\\n${progOptions.errors.join('\\n')}`);\n });\n }\n return null;\n}\n\n/**\n * Check Shader status\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use.\n * @param {number} shaderType The shader type\n * @param {WebGLShader} shader The shader\n * @param {ErrorCallback} [errFn] function to receive error message.\n * @return {string} errors or empty string\n * @private\n */\nfunction checkShaderStatus(gl, shaderType, shader, errFn) {\n errFn = errFn || error;\n // Check the compile status\n const compiled = gl.getShaderParameter(shader, COMPILE_STATUS);\n if (!compiled) {\n // Something went wrong during compilation; get the error\n const lastError = gl.getShaderInfoLog(shader);\n const {lineOffset, shaderSource} = prepShaderSource(gl.getShaderSource(shader));\n const error = `${addLineNumbersWithError(shaderSource, lastError, lineOffset)}\\nError compiling ${glEnumToString(gl, shaderType)}: ${lastError}`;\n errFn(error);\n return error;\n }\n return '';\n}\n\n/**\n * @typedef {Object} FullProgramSpec\n * @property {string[]} shaders the shader source or element ids.\n * @property {function(string)} [errorCallback] callback for errors\n * @property {Object.|string[]} [attribLocations] a attribute name to location map, or array of attribute names where index = location.\n * @property {(module:twgl.BufferInfo|Object.|string[])} [transformFeedbackVaryings] If passed\n * a BufferInfo will use the attribs names inside. If passed an object of AttribInfos will use the names from that object. Otherwise\n * you can pass an array of names.\n * @property {number} [transformFeedbackMode] the mode to pass `gl.transformFeedbackVaryings`. Defaults to `SEPARATE_ATTRIBS`.\n * @property {ProgramCallback} [callback] callback for async program compilation.\n * @memberOf module:twgl\n */\n\n/**\n * @typedef {string[]|module:twgl.FullProgramSpec} ProgramSpec\n * @memberOf module:twgl\n */\n\n/**\n * @typedef {Object} ProgramOptions\n * @property {function(string)} [errorCallback] callback for errors\n * @property {Object.|string[]} [attribLocations] a attribute name to location map, or array of attribute names where index = location.\n * @property {(module:twgl.BufferInfo|Object.|string[])} [transformFeedbackVaryings] If passed\n * a BufferInfo will use the attribs names inside. If passed an object of AttribInfos will use the names from that object. Otherwise\n * you can pass an array of names.\n * @property {number} [transformFeedbackMode] the mode to pass `gl.transformFeedbackVaryings`. Defaults to `SEPARATE_ATTRIBS`.\n * @property {ProgramCallback} [callback] callback for async program compilation.\n * @memberOf module:twgl\n */\n\n/**\n * Gets the program options based on all these optional arguments\n * @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\n * @param {number[]} [opt_locations] The locations for the. A parallel array to opt_attribs letting you assign locations.\n * @param {module:twgl.ErrorCallback} [opt_errorCallback] callback for errors. By default it just prints an error to the console\n * on error. If you want something else pass an callback. It's passed an error message.\n * @return {module:twgl.ProgramOptions} an instance of ProgramOptions based on the arguments passed in\n * @private\n */\nfunction getProgramOptions(opt_attribs, opt_locations, opt_errorCallback) {\n let transformFeedbackVaryings;\n let transformFeedbackMode;\n let callback;\n if (typeof opt_locations === 'function') {\n opt_errorCallback = opt_locations;\n opt_locations = undefined;\n }\n if (typeof opt_attribs === 'function') {\n opt_errorCallback = opt_attribs;\n opt_attribs = undefined;\n } else if (opt_attribs && !Array.isArray(opt_attribs)) {\n const opt = opt_attribs;\n opt_errorCallback = opt.errorCallback;\n opt_attribs = opt.attribLocations;\n transformFeedbackVaryings = opt.transformFeedbackVaryings;\n transformFeedbackMode = opt.transformFeedbackMode;\n callback = opt.callback;\n }\n\n const errorCallback = opt_errorCallback || error;\n const errors = [];\n const options = {\n errorCallback(msg, ...args) {\n errors.push(msg);\n errorCallback(msg, ...args);\n },\n transformFeedbackVaryings,\n transformFeedbackMode,\n callback,\n errors,\n };\n\n {\n let attribLocations = {};\n if (Array.isArray(opt_attribs)) {\n opt_attribs.forEach(function(attrib, ndx) {\n attribLocations[attrib] = opt_locations ? opt_locations[ndx] : ndx;\n });\n } else {\n attribLocations = opt_attribs || {};\n }\n options.attribLocations = attribLocations;\n }\n\n return options;\n}\n\nconst defaultShaderType = [\n \"VERTEX_SHADER\",\n \"FRAGMENT_SHADER\",\n];\n\nfunction getShaderTypeFromScriptType(gl, scriptType) {\n if (scriptType.indexOf(\"frag\") >= 0) {\n return FRAGMENT_SHADER;\n } else if (scriptType.indexOf(\"vert\") >= 0) {\n return VERTEX_SHADER;\n }\n return undefined;\n}\n\nfunction deleteProgramAndShaders(gl, program, notThese) {\n const shaders = gl.getAttachedShaders(program);\n for (const shader of shaders) {\n if (notThese.has(shader)) {\n gl.deleteShader(shader);\n }\n }\n gl.deleteProgram(program);\n}\n\nconst wait = (ms = 0) => new Promise(resolve => setTimeout(resolve, ms));\n\nfunction createProgramNoCheck(gl, shaders, programOptions) {\n const program = gl.createProgram();\n const {\n attribLocations,\n transformFeedbackVaryings,\n transformFeedbackMode,\n } = getProgramOptions(programOptions);\n\n for (let ndx = 0; ndx < shaders.length; ++ndx) {\n let shader = shaders[ndx];\n if (typeof shader === 'string') {\n const elem = getElementById(shader);\n const src = elem ? elem.text : shader;\n let type = gl[defaultShaderType[ndx]];\n if (elem && elem.type) {\n type = getShaderTypeFromScriptType(gl, elem.type) || type;\n }\n shader = gl.createShader(type);\n gl.shaderSource(shader, prepShaderSource(src).shaderSource);\n gl.compileShader(shader);\n gl.attachShader(program, shader);\n }\n }\n\n Object.entries(attribLocations).forEach(([attrib, loc]) => gl.bindAttribLocation(program, loc, attrib));\n\n {\n let varyings = transformFeedbackVaryings;\n if (varyings) {\n if (varyings.attribs) {\n varyings = varyings.attribs;\n }\n if (!Array.isArray(varyings)) {\n varyings = Object.keys(varyings);\n }\n gl.transformFeedbackVaryings(program, varyings, transformFeedbackMode || SEPARATE_ATTRIBS);\n }\n }\n\n gl.linkProgram(program);\n return program;\n}\n\n/**\n * Creates a program, attaches (and/or compiles) shaders, binds attrib locations, links the\n * program.\n *\n * NOTE: There are 4 signatures for this function\n *\n * twgl.createProgram(gl, [vs, fs], options);\n * twgl.createProgram(gl, [vs, fs], opt_errFunc);\n * twgl.createProgram(gl, [vs, fs], opt_attribs, opt_errFunc);\n * twgl.createProgram(gl, [vs, fs], opt_attribs, opt_locations, opt_errFunc);\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use.\n * @param {WebGLShader[]|string[]} shaders The shaders to attach, or element ids for their source, or strings that contain their source\n * @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\n * @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.\n * @param {module:twgl.ErrorCallback} [opt_errorCallback] callback for errors. By default it just prints an error to the console\n * on error. If you want something else pass an callback. It's passed an error message.\n * @return {WebGLProgram?} the created program or null if error of a callback was provided.\n * @memberOf module:twgl/programs\n */\nfunction createProgram(\n gl, shaders, opt_attribs, opt_locations, opt_errorCallback) {\n // This code is really convoluted, because it may or may not be async\n // Maybe it would be better to have a separate function\n const progOptions = getProgramOptions(opt_attribs, opt_locations, opt_errorCallback);\n const shaderSet = new Set(shaders);\n const program = createProgramNoCheck(gl, shaders, progOptions);\n\n function hasErrors(gl, program) {\n const errors = getProgramErrors(gl, program, progOptions.errorCallback);\n if (errors) {\n deleteProgramAndShaders(gl, program, shaderSet);\n }\n return errors;\n }\n\n if (progOptions.callback) {\n waitForProgramLinkCompletionAsync(gl, program).then(() => {\n const errors = hasErrors(gl, program);\n progOptions.callback(errors, errors ? undefined : program);\n });\n return undefined;\n }\n\n return hasErrors(gl, program) ? undefined : program;\n}\n\n/**\n * This only works because the functions it wraps the first 2 arguments\n * are gl and any, followed by things that become programOptions\n * @private\n */\nfunction wrapCallbackFnToAsyncFn(fn) {\n return function(gl, arg1, ...args) {\n return new Promise((resolve, reject) => {\n const programOptions = getProgramOptions(...args);\n programOptions.callback = (err, program) => {\n if (err) {\n reject(err);\n } else {\n resolve(program);\n }\n };\n fn(gl, arg1, programOptions);\n });\n };\n}\n\n/**\n * Same as createProgram but returns a promise\n *\n * NOTE: There are 4 signatures for this function\n *\n * twgl.createProgramAsync(gl, [vs, fs], options);\n * twgl.createProgramAsync(gl, [vs, fs], opt_errFunc);\n * twgl.createProgramAsync(gl, [vs, fs], opt_attribs, opt_errFunc);\n * twgl.createProgramAsync(gl, [vs, fs], opt_attribs, opt_locations, opt_errFunc);\n *\n * @function\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use.\n * @param {WebGLShader[]|string[]} shaders The shaders to attach, or element ids for their source, or strings that contain their source\n * @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\n * @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.\n * @param {module:twgl.ErrorCallback} [opt_errorCallback] callback for errors. By default it just prints an error to the console\n * on error. If you want something else pass an callback. It's passed an error message.\n * @return {Promise} The created program\n * @memberOf module:twgl/programs\n */\nconst createProgramAsync = wrapCallbackFnToAsyncFn(createProgram);\n\n/**\n * Same as createProgramInfo but returns a promise\n * @function\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext\n * to use.\n * @param {string[]} shaderSources Array of sources for the\n * shaders or ids. The first is assumed to be the vertex shader,\n * the second the fragment shader.\n * @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\n * @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.\n * @param {module:twgl.ErrorCallback} [opt_errorCallback] callback for errors. By default it just prints an error to the console\n * on error. If you want something else pass an callback. It's passed an error message.\n * @return {Promise} The created ProgramInfo\n * @memberOf module:twgl/programs\n */\nconst createProgramInfoAsync = wrapCallbackFnToAsyncFn(createProgramInfo);\n\nasync function waitForProgramLinkCompletionAsync(gl, program) {\n const ext = gl.getExtension('KHR_parallel_shader_compile');\n const checkFn = ext\n ? (gl, program) => gl.getProgramParameter(program, ext.COMPLETION_STATUS_KHR)\n : () => true;\n\n let waitTime = 0;\n do {\n await wait(waitTime); // must wait at least once\n waitTime = 1000 / 60;\n } while (!checkFn(gl, program));\n}\n\nasync function waitForAllProgramsLinkCompletionAsync(gl, programs) {\n for (const program of Object.values(programs)) {\n await waitForProgramLinkCompletionAsync(gl, program);\n }\n}\n\n/**\n * Check a program's link status\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use.\n * @param {WebGLProgram} program Program to check\n * @param {ErrorCallback} [errFn] func for errors\n * @return {string?} errors if program is failed, else undefined\n * @private\n */\nfunction getProgramErrors(gl, program, errFn) {\n errFn = errFn || error;\n // Check the link status\n const linked = gl.getProgramParameter(program, LINK_STATUS);\n if (!linked) {\n // something went wrong with the link\n const lastError = gl.getProgramInfoLog(program);\n errFn(`Error in program linking: ${lastError}`);\n // print any errors from these shaders\n const shaders = gl.getAttachedShaders(program);\n const errors = shaders.map(shader => checkShaderStatus(gl, gl.getShaderParameter(shader, gl.SHADER_TYPE), shader, errFn));\n return `${lastError}\\n${errors.filter(_ => _).join('\\n')}`;\n }\n return undefined;\n}\n\n/**\n * Creates a program from 2 script tags.\n *\n * NOTE: There are 4 signatures for this function\n *\n * twgl.createProgramFromScripts(gl, [vs, fs], opt_options);\n * twgl.createProgramFromScripts(gl, [vs, fs], opt_errFunc);\n * twgl.createProgramFromScripts(gl, [vs, fs], opt_attribs, opt_errFunc);\n * twgl.createProgramFromScripts(gl, [vs, fs], opt_attribs, opt_locations, opt_errFunc);\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext\n * to use.\n * @param {string[]} shaderScriptIds Array of ids of the script\n * tags for the shaders. The first is assumed to be the\n * vertex shader, the second the fragment shader.\n * @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\n * @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.\n * @param {module:twgl.ErrorCallback} [opt_errorCallback] callback for errors. By default it just prints an error to the console\n * on error. If you want something else pass an callback. It's passed an error message.\n * @return {WebGLProgram?} the created program or null if error or a callback was provided.\n * @memberOf module:twgl/programs\n */\nfunction createProgramFromScripts(\n gl, shaderScriptIds, opt_attribs, opt_locations, opt_errorCallback) {\n const progOptions = getProgramOptions(opt_attribs, opt_locations, opt_errorCallback);\n const shaders = [];\n for (const scriptId of shaderScriptIds) {\n const shaderScript = getElementById(scriptId);\n if (!shaderScript) {\n return reportError(progOptions, `unknown script element: ${scriptId}`);\n }\n shaders.push(shaderScript.text);\n }\n return createProgram(gl, shaders, progOptions);\n}\n\n/**\n * Creates a program from 2 sources.\n *\n * NOTE: There are 4 signatures for this function\n *\n * twgl.createProgramFromSource(gl, [vs, fs], opt_options);\n * twgl.createProgramFromSource(gl, [vs, fs], opt_errFunc);\n * twgl.createProgramFromSource(gl, [vs, fs], opt_attribs, opt_errFunc);\n * twgl.createProgramFromSource(gl, [vs, fs], opt_attribs, opt_locations, opt_errFunc);\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext\n * to use.\n * @param {string[]} shaderSources Array of sources for the\n * shaders. The first is assumed to be the vertex shader,\n * the second the fragment shader.\n * @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\n * @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.\n * @param {module:twgl.ErrorCallback} [opt_errorCallback] callback for errors. By default it just prints an error to the console\n * on error. If you want something else pass an callback. It's passed an error message.\n * @return {WebGLProgram?} the created program or null if error or a callback was provided.\n * @memberOf module:twgl/programs\n */\nfunction createProgramFromSources(\n gl, shaderSources, opt_attribs, opt_locations, opt_errorCallback) {\n return createProgram(gl, shaderSources, opt_attribs, opt_locations, opt_errorCallback);\n}\n\n/**\n * Returns true if attribute/uniform is a reserved/built in\n *\n * It makes no sense to me why GL returns these because it's\n * illegal to call `gl.getUniformLocation` and `gl.getAttribLocation`\n * with names that start with `gl_` (and `webgl_` in WebGL)\n *\n * I can only assume they are there because they might count\n * when computing the number of uniforms/attributes used when you want to\n * know if you are near the limit. That doesn't really make sense\n * to me but the fact that these get returned are in the spec.\n *\n * @param {WebGLActiveInfo} info As returned from `gl.getActiveUniform` or\n * `gl.getActiveAttrib`.\n * @return {bool} true if it's reserved\n * @private\n */\nfunction isBuiltIn(info) {\n const name = info.name;\n return name.startsWith(\"gl_\") || name.startsWith(\"webgl_\");\n}\n\nconst tokenRE = /(\\.|\\[|]|\\w+)/g;\nconst isDigit = s => s >= '0' && s <= '9';\nfunction addSetterToUniformTree(fullPath, setter, node, uniformSetters) {\n const tokens = fullPath.split(tokenRE).filter(s => s !== '');\n let tokenNdx = 0;\n let path = '';\n\n for (;;) {\n const token = tokens[tokenNdx++]; // has to be name or number\n path += token;\n const isArrayIndex = isDigit(token[0]);\n const accessor = isArrayIndex\n ? parseInt(token)\n : token;\n if (isArrayIndex) {\n path += tokens[tokenNdx++]; // skip ']'\n }\n const isLastToken = tokenNdx === tokens.length;\n if (isLastToken) {\n node[accessor] = setter;\n break;\n } else {\n const token = tokens[tokenNdx++]; // has to be . or [\n const isArray = token === '[';\n const child = node[accessor] || (isArray ? [] : {});\n node[accessor] = child;\n node = child;\n uniformSetters[path] = uniformSetters[path] || function(node) {\n return function(value) {\n setUniformTree(node, value);\n };\n }(child);\n path += token;\n }\n }\n}\n\n/**\n * Creates setter functions for all uniforms of a shader\n * program.\n *\n * @see {@link module:twgl.setUniforms}\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use.\n * @param {WebGLProgram} program the program to create setters for.\n * @returns {Object.} an object with a setter by name for each uniform\n * @memberOf module:twgl/programs\n */\nfunction createUniformSetters(gl, program) {\n let textureUnit = 0;\n\n /**\n * Creates a setter for a uniform of the given program with it's\n * location embedded in the setter.\n * @param {WebGLProgram} program\n * @param {WebGLUniformInfo} uniformInfo\n * @returns {function} the created setter.\n */\n function createUniformSetter(program, uniformInfo, location) {\n const isArray = uniformInfo.name.endsWith(\"[0]\");\n const type = uniformInfo.type;\n const typeInfo = typeMap[type];\n if (!typeInfo) {\n throw new Error(`unknown type: 0x${type.toString(16)}`); // we should never get here.\n }\n let setter;\n if (typeInfo.bindPoint) {\n // it's a sampler\n const unit = textureUnit;\n textureUnit += uniformInfo.size;\n if (isArray) {\n setter = typeInfo.arraySetter(gl, type, unit, location, uniformInfo.size);\n } else {\n setter = typeInfo.setter(gl, type, unit, location, uniformInfo.size);\n }\n } else {\n if (typeInfo.arraySetter && isArray) {\n setter = typeInfo.arraySetter(gl, location);\n } else {\n setter = typeInfo.setter(gl, location);\n }\n }\n setter.location = location;\n return setter;\n }\n\n const uniformSetters = {};\n const uniformTree = {};\n const numUniforms = gl.getProgramParameter(program, ACTIVE_UNIFORMS);\n\n for (let ii = 0; ii < numUniforms; ++ii) {\n const uniformInfo = gl.getActiveUniform(program, ii);\n if (isBuiltIn(uniformInfo)) {\n continue;\n }\n let name = uniformInfo.name;\n // remove the array suffix.\n if (name.endsWith(\"[0]\")) {\n name = name.substr(0, name.length - 3);\n }\n const location = gl.getUniformLocation(program, uniformInfo.name);\n // the uniform will have no location if it's in a uniform block\n if (location) {\n const setter = createUniformSetter(program, uniformInfo, location);\n uniformSetters[name] = setter;\n addSetterToUniformTree(name, setter, uniformTree, uniformSetters);\n }\n }\n\n return uniformSetters;\n}\n\n/**\n * @typedef {Object} TransformFeedbackInfo\n * @property {number} index index of transform feedback\n * @property {number} type GL type\n * @property {number} size 1 - 4\n * @memberOf module:twgl\n */\n\n/**\n * Create TransformFeedbackInfo for passing to bindTransformFeedbackInfo.\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use.\n * @param {WebGLProgram} program an existing WebGLProgram.\n * @return {Object}\n * @memberOf module:twgl\n */\nfunction createTransformFeedbackInfo(gl, program) {\n const info = {};\n const numVaryings = gl.getProgramParameter(program, TRANSFORM_FEEDBACK_VARYINGS);\n for (let ii = 0; ii < numVaryings; ++ii) {\n const varying = gl.getTransformFeedbackVarying(program, ii);\n info[varying.name] = {\n index: ii,\n type: varying.type,\n size: varying.size,\n };\n }\n return info;\n}\n\n/**\n * Binds buffers for transform feedback.\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use.\n * @param {(module:twgl.ProgramInfo|Object)} transformFeedbackInfo A ProgramInfo or TransformFeedbackInfo.\n * @param {(module:twgl.BufferInfo|Object)} [bufferInfo] A BufferInfo or set of AttribInfos.\n * @memberOf module:twgl\n */\nfunction bindTransformFeedbackInfo(gl, transformFeedbackInfo, bufferInfo) {\n if (transformFeedbackInfo.transformFeedbackInfo) {\n transformFeedbackInfo = transformFeedbackInfo.transformFeedbackInfo;\n }\n if (bufferInfo.attribs) {\n bufferInfo = bufferInfo.attribs;\n }\n for (const name in bufferInfo) {\n const varying = transformFeedbackInfo[name];\n if (varying) {\n const buf = bufferInfo[name];\n if (buf.offset) {\n gl.bindBufferRange(TRANSFORM_FEEDBACK_BUFFER, varying.index, buf.buffer, buf.offset, buf.size);\n } else {\n gl.bindBufferBase(TRANSFORM_FEEDBACK_BUFFER, varying.index, buf.buffer);\n }\n }\n }\n}\n\n/**\n * Creates a transform feedback and sets the buffers\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use.\n * @param {module:twgl.ProgramInfo} programInfo A ProgramInfo as returned from {@link module:twgl.createProgramInfo}\n * @param {(module:twgl.BufferInfo|Object)} [bufferInfo] A BufferInfo or set of AttribInfos.\n * @return {WebGLTransformFeedback} the created transform feedback\n * @memberOf module:twgl\n */\nfunction createTransformFeedback(gl, programInfo, bufferInfo) {\n const tf = gl.createTransformFeedback();\n gl.bindTransformFeedback(TRANSFORM_FEEDBACK, tf);\n gl.useProgram(programInfo.program);\n bindTransformFeedbackInfo(gl, programInfo, bufferInfo);\n gl.bindTransformFeedback(TRANSFORM_FEEDBACK, null);\n return tf;\n}\n\n/**\n * @typedef {Object} UniformData\n * @property {string} name The name of the uniform\n * @property {number} type The WebGL type enum for this uniform\n * @property {number} size The number of elements for this uniform\n * @property {number} blockNdx The block index this uniform appears in\n * @property {number} offset The byte offset in the block for this uniform's value\n * @memberOf module:twgl\n */\n\n/**\n * The specification for one UniformBlockObject\n *\n * @typedef {Object} BlockSpec\n * @property {number} index The index of the block.\n * @property {number} size The size in bytes needed for the block\n * @property {number[]} uniformIndices The indices of the uniforms used by the block. These indices\n * correspond to entries in a UniformData array in the {@link module:twgl.UniformBlockSpec}.\n * @property {bool} usedByVertexShader Self explanatory\n * @property {bool} usedByFragmentShader Self explanatory\n * @property {bool} used Self explanatory\n * @memberOf module:twgl\n */\n\n/**\n * A `UniformBlockSpec` represents the data needed to create and bind\n * UniformBlockObjects for a given program\n *\n * @typedef {Object} UniformBlockSpec\n * @property {Object.} blockSpecs The BlockSpec for each block by block name\n * @property {UniformData[]} uniformData An array of data for each uniform by uniform index.\n * @memberOf module:twgl\n */\n\n/**\n * Creates a UniformBlockSpec for the given program.\n *\n * A UniformBlockSpec represents the data needed to create and bind\n * UniformBlockObjects\n *\n * @param {WebGL2RenderingContext} gl A WebGL2 Rendering Context\n * @param {WebGLProgram} program A WebGLProgram for a successfully linked program\n * @return {module:twgl.UniformBlockSpec} The created UniformBlockSpec\n * @memberOf module:twgl/programs\n */\nfunction createUniformBlockSpecFromProgram(gl, program) {\n const numUniforms = gl.getProgramParameter(program, ACTIVE_UNIFORMS);\n const uniformData = [];\n const uniformIndices = [];\n\n for (let ii = 0; ii < numUniforms; ++ii) {\n uniformIndices.push(ii);\n uniformData.push({});\n const uniformInfo = gl.getActiveUniform(program, ii);\n uniformData[ii].name = uniformInfo.name;\n }\n\n [\n [ \"UNIFORM_TYPE\", \"type\" ],\n [ \"UNIFORM_SIZE\", \"size\" ], // num elements\n [ \"UNIFORM_BLOCK_INDEX\", \"blockNdx\" ],\n [ \"UNIFORM_OFFSET\", \"offset\", ],\n ].forEach(function(pair) {\n const pname = pair[0];\n const key = pair[1];\n gl.getActiveUniforms(program, uniformIndices, gl[pname]).forEach(function(value, ndx) {\n uniformData[ndx][key] = value;\n });\n });\n\n const blockSpecs = {};\n\n const numUniformBlocks = gl.getProgramParameter(program, ACTIVE_UNIFORM_BLOCKS);\n for (let ii = 0; ii < numUniformBlocks; ++ii) {\n const name = gl.getActiveUniformBlockName(program, ii);\n const blockSpec = {\n index: gl.getUniformBlockIndex(program, name),\n usedByVertexShader: gl.getActiveUniformBlockParameter(program, ii, UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER),\n usedByFragmentShader: gl.getActiveUniformBlockParameter(program, ii, UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER),\n size: gl.getActiveUniformBlockParameter(program, ii, UNIFORM_BLOCK_DATA_SIZE),\n uniformIndices: gl.getActiveUniformBlockParameter(program, ii, UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES),\n };\n blockSpec.used = blockSpec.usedByVertexShader || blockSpec.usedByFragmentShader;\n blockSpecs[name] = blockSpec;\n }\n\n return {\n blockSpecs: blockSpecs,\n uniformData: uniformData,\n };\n}\n\nconst arraySuffixRE = /\\[\\d+\\]\\.$/; // better way to check?\n\nconst pad = (v, padding) => ((v + (padding - 1)) / padding | 0) * padding;\n\nfunction createUniformBlockUniformSetter(view, isArray, rows, cols) {\n if (isArray || rows) {\n cols = cols || 1;\n const numElements = view.length;\n const totalRows = numElements / 4;\n return function(value) {\n let dst = 0;\n let src = 0;\n for (let row = 0; row < totalRows; ++row) {\n for (let col = 0; col < cols; ++col) {\n view[dst++] = value[src++];\n }\n dst += 4 - cols;\n }\n };\n } else {\n return function(value) {\n if (value.length) {\n view.set(value);\n } else {\n view[0] = value;\n }\n };\n }\n}\n\n/**\n * Represents a UniformBlockObject including an ArrayBuffer with all the uniform values\n * and a corresponding WebGLBuffer to hold those values on the GPU\n *\n * @typedef {Object} UniformBlockInfo\n * @property {string} name The name of the block\n * @property {ArrayBuffer} array The array buffer that contains the uniform values\n * @property {Float32Array} asFloat A float view on the array buffer. This is useful\n * inspecting the contents of the buffer in the debugger.\n * @property {WebGLBuffer} buffer A WebGL buffer that will hold a copy of the uniform values for rendering.\n * @property {number} [offset] offset into buffer\n * @property {Object} uniforms A uniform name to ArrayBufferView map.\n * each Uniform has a correctly typed `ArrayBufferView` into array at the correct offset\n * and length of that uniform. So for example a float uniform would have a 1 float `Float32Array`\n * view. A single mat4 would have a 16 element `Float32Array` view. An ivec2 would have an\n * `Int32Array` view, etc.\n * @property {Object} setters A setter for this uniform.\n * The reason to use setters is elements of arrays are padded to vec4 sizes which\n * means if you want to set an array of 4 floats you'd need to set 16 values\n * (or set elements 0, 4, 8, 12). In other words\n * `someBlockInfo.uniforms.some4FloatArrayUniform.set([0, , , , 1, , , , 2, , , , 3])`\n * where as the setter handles just passing in [0, 1, 2, 3] either directly as in\n * `someBlockInfo.setter.some4FloatArrayUniform.set([0, 1, 2, 3])` (not recommended)\n * or via {@link module:twgl.setBlockUniforms}\n * @memberOf module:twgl\n */\n\n/**\n * Creates a `UniformBlockInfo` for the specified block\n *\n * Note: **If the blockName matches no existing blocks a warning is printed to the console and a dummy\n * `UniformBlockInfo` is returned**. This is because when debugging GLSL\n * it is common to comment out large portions of a shader or for example set\n * the final output to a constant. When that happens blocks get optimized out.\n * If this function did not create dummy blocks your code would crash when debugging.\n *\n * @param {WebGL2RenderingContext} gl A WebGL2RenderingContext\n * @param {WebGLProgram} program A WebGLProgram\n * @param {module:twgl.UniformBlockSpec} uniformBlockSpec. A UniformBlockSpec as returned\n * from {@link module:twgl.createUniformBlockSpecFromProgram}.\n * @param {string} blockName The name of the block.\n * @return {module:twgl.UniformBlockInfo} The created UniformBlockInfo\n * @memberOf module:twgl/programs\n */\nfunction createUniformBlockInfoFromProgram(gl, program, uniformBlockSpec, blockName) {\n const blockSpecs = uniformBlockSpec.blockSpecs;\n const uniformData = uniformBlockSpec.uniformData;\n const blockSpec = blockSpecs[blockName];\n if (!blockSpec) {\n warn(\"no uniform block object named:\", blockName);\n return {\n name: blockName,\n uniforms: {},\n };\n }\n const array = new ArrayBuffer(blockSpec.size);\n const buffer = gl.createBuffer();\n const uniformBufferIndex = blockSpec.index;\n gl.bindBuffer(UNIFORM_BUFFER, buffer);\n gl.uniformBlockBinding(program, blockSpec.index, uniformBufferIndex);\n\n let prefix = blockName + \".\";\n if (arraySuffixRE.test(prefix)) {\n prefix = prefix.replace(arraySuffixRE, \".\");\n }\n const uniforms = {};\n const setters = {};\n const setterTree = {};\n blockSpec.uniformIndices.forEach(function(uniformNdx) {\n const data = uniformData[uniformNdx];\n let name = data.name;\n if (name.startsWith(prefix)) {\n name = name.substr(prefix.length);\n }\n const isArray = name.endsWith('[0]');\n if (isArray) {\n name = name.substr(0, name.length - 3);\n }\n const typeInfo = typeMap[data.type];\n const Type = typeInfo.Type;\n const byteLength = isArray\n ? pad(typeInfo.size, 16) * data.size\n : typeInfo.size * data.size;\n const uniformView = new Type(array, data.offset, byteLength / Type.BYTES_PER_ELEMENT);\n uniforms[name] = uniformView;\n // Note: I'm not sure what to do here. The original\n // idea was to create TypedArray views into each part\n // of the block. This is useful, for example if you have\n // a block with { mat4: model; mat4 view; mat4 projection; }\n // you'll get a Float32Array for each one suitable for\n // passing to most JS math libraries including twgl's and glMatrix.js.\n //\n // But, if you have a an array of structures, especially if that\n // array is large, you get a whole bunch of TypedArray views.\n // Every one of them has overhead and switching between them all\n // is probably a cache miss. In that case it would really be better\n // to just have one view (asFloat) and have all the setters\n // just reference the correct portion. But, then you can't easily\n // treat a matrix, or a vec4, as a standalone thing like you can\n // with all the views.\n //\n // Another problem with the views is they are not shared. With\n // uniforms you have one set of setters. With UniformBlockInfo\n // you have a set of setters *pre block instance*. That's because\n // TypedArray views can't be mapped to different buffers.\n //\n // My gut right now is if you really want the speed and compactness\n // then you should probably roll your own solution. TWGL's goal\n // here is ease of use as AFAICT there is no simple generic efficient\n // solution.\n const setter = createUniformBlockUniformSetter(uniformView, isArray, typeInfo.rows, typeInfo.cols);\n setters[name] = setter;\n addSetterToUniformTree(name, setter, setterTree, setters);\n });\n return {\n name: blockName,\n array,\n asFloat: new Float32Array(array), // for debugging\n buffer,\n uniforms,\n setters,\n };\n}\n\n/**\n * Creates a `UniformBlockInfo` for the specified block\n *\n * Note: **If the blockName matches no existing blocks a warning is printed to the console and a dummy\n * `UniformBlockInfo` is returned**. This is because when debugging GLSL\n * it is common to comment out large portions of a shader or for example set\n * the final output to a constant. When that happens blocks get optimized out.\n * If this function did not create dummy blocks your code would crash when debugging.\n *\n * @param {WebGL2RenderingContext} gl A WebGL2RenderingContext\n * @param {module:twgl.ProgramInfo} programInfo a `ProgramInfo`\n * as returned from {@link module:twgl.createProgramInfo}\n * @param {string} blockName The name of the block.\n * @return {module:twgl.UniformBlockInfo} The created UniformBlockInfo\n * @memberOf module:twgl/programs\n */\nfunction createUniformBlockInfo(gl, programInfo, blockName) {\n return createUniformBlockInfoFromProgram(gl, programInfo.program, programInfo.uniformBlockSpec, blockName);\n}\n\n/**\n * Binds a uniform block to the matching uniform block point.\n * Matches by blocks by name so blocks must have the same name not just the same\n * structure.\n *\n * If you have changed any values and you upload the values into the corresponding WebGLBuffer\n * call {@link module:twgl.setUniformBlock} instead.\n *\n * @param {WebGL2RenderingContext} gl A WebGL 2 rendering context.\n * @param {(module:twgl.ProgramInfo|module:twgl.UniformBlockSpec)} programInfo a `ProgramInfo`\n * as returned from {@link module:twgl.createProgramInfo} or or `UniformBlockSpec` as\n * returned from {@link module:twgl.createUniformBlockSpecFromProgram}.\n * @param {module:twgl.UniformBlockInfo} uniformBlockInfo a `UniformBlockInfo` as returned from\n * {@link module:twgl.createUniformBlockInfo}.\n * @return {bool} true if buffer was bound. If the programInfo has no block with the same block name\n * no buffer is bound.\n * @memberOf module:twgl/programs\n */\nfunction bindUniformBlock(gl, programInfo, uniformBlockInfo) {\n const uniformBlockSpec = programInfo.uniformBlockSpec || programInfo;\n const blockSpec = uniformBlockSpec.blockSpecs[uniformBlockInfo.name];\n if (blockSpec) {\n const bufferBindIndex = blockSpec.index;\n gl.bindBufferRange(UNIFORM_BUFFER, bufferBindIndex, uniformBlockInfo.buffer, uniformBlockInfo.offset || 0, uniformBlockInfo.array.byteLength);\n return true;\n }\n return false;\n}\n\n/**\n * Uploads the current uniform values to the corresponding WebGLBuffer\n * and binds that buffer to the program's corresponding bind point for the uniform block object.\n *\n * If you haven't changed any values and you only need to bind the uniform block object\n * call {@link module:twgl.bindUniformBlock} instead.\n *\n * @param {WebGL2RenderingContext} gl A WebGL 2 rendering context.\n * @param {(module:twgl.ProgramInfo|module:twgl.UniformBlockSpec)} programInfo a `ProgramInfo`\n * as returned from {@link module:twgl.createProgramInfo} or or `UniformBlockSpec` as\n * returned from {@link module:twgl.createUniformBlockSpecFromProgram}.\n * @param {module:twgl.UniformBlockInfo} uniformBlockInfo a `UniformBlockInfo` as returned from\n * {@link module:twgl.createUniformBlockInfo}.\n * @memberOf module:twgl/programs\n */\nfunction setUniformBlock(gl, programInfo, uniformBlockInfo) {\n if (bindUniformBlock(gl, programInfo, uniformBlockInfo)) {\n gl.bufferData(UNIFORM_BUFFER, uniformBlockInfo.array, DYNAMIC_DRAW);\n }\n}\n\n/**\n * Sets values of a uniform block object\n *\n * @param {module:twgl.UniformBlockInfo} uniformBlockInfo A UniformBlockInfo as returned by {@link module:twgl.createUniformBlockInfo}.\n * @param {Object.} values A uniform name to value map where the value is correct for the given\n * type of uniform. So for example given a block like\n *\n * uniform SomeBlock {\n * float someFloat;\n * vec2 someVec2;\n * vec3 someVec3Array[2];\n * int someInt;\n * }\n *\n * You can set the values of the uniform block with\n *\n * twgl.setBlockUniforms(someBlockInfo, {\n * someFloat: 12.3,\n * someVec2: [1, 2],\n * someVec3Array: [1, 2, 3, 4, 5, 6],\n * someInt: 5,\n * }\n *\n * Arrays can be JavaScript arrays or typed arrays\n *\n * You can also fill out structure and array values either via\n * shortcut. Example\n *\n * // -- in shader --\n * struct Light {\n * float intensity;\n * vec4 color;\n * float nearFar[2];\n * };\n * uniform Lights {\n * Light lights[2];\n * };\n *\n * // in JavaScript\n *\n * twgl.setBlockUniforms(someBlockInfo, {\n * lights: [\n * { intensity: 5.0, color: [1, 0, 0, 1], nearFar[0.1, 10] },\n * { intensity: 2.0, color: [0, 0, 1, 1], nearFar[0.2, 15] },\n * ],\n * });\n *\n * or the more traditional way\n *\n * twgl.setBlockUniforms(someBlockInfo, {\n * \"lights[0].intensity\": 5.0,\n * \"lights[0].color\": [1, 0, 0, 1],\n * \"lights[0].nearFar\": [0.1, 10],\n * \"lights[1].intensity\": 2.0,\n * \"lights[1].color\": [0, 0, 1, 1],\n * \"lights[1].nearFar\": [0.2, 15],\n * });\n *\n * You can also specify partial paths\n *\n * twgl.setBlockUniforms(someBlockInfo, {\n * 'lights[1]': { intensity: 5.0, color: [1, 0, 0, 1], nearFar[0.2, 15] },\n * });\n *\n * But you can not specify leaf array indices.\n *\n * twgl.setBlockUniforms(someBlockInfo, {\n * 'lights[1].nearFar[1]': 15, // BAD! nearFar is a leaf\n * 'lights[1].nearFar': [0.2, 15], // GOOD\n * });\n *\n * **IMPORTANT!**, packing in a UniformBlock is unintuitive.\n * For example the actual layout of `someVec3Array` above in memory\n * is `1, 2, 3, unused, 4, 5, 6, unused`. twgl takes in 6 values\n * as shown about and copies them, skipping the padding. This might\n * be confusing if you're already familiar with Uniform blocks.\n *\n * If you want to deal with the padding yourself you can access the array\n * buffer views directly. eg:\n *\n * someBlockInfo.someVec3Array.set([1, 2, 3, 0, 4, 5, 6, 0]);\n *\n * Any name that doesn't match will be ignored\n * @memberOf module:twgl/programs\n */\nfunction setBlockUniforms(uniformBlockInfo, values) {\n const setters = uniformBlockInfo.setters;\n for (const name in values) {\n const setter = setters[name];\n if (setter) {\n const value = values[name];\n setter(value);\n }\n }\n}\n\nfunction setUniformTree(tree, values) {\n for (const name in values) {\n const prop = tree[name];\n if (typeof prop === 'function') {\n prop(values[name]);\n } else {\n setUniformTree(tree[name], values[name]);\n }\n }\n}\n\n/**\n * Set uniforms and binds related textures.\n *\n * example:\n *\n * const programInfo = createProgramInfo(\n * gl, [\"some-vs\", \"some-fs\"]);\n *\n * const tex1 = gl.createTexture();\n * const tex2 = gl.createTexture();\n *\n * ... assume we setup the textures with data ...\n *\n * const uniforms = {\n * u_someSampler: tex1,\n * u_someOtherSampler: tex2,\n * u_someColor: [1,0,0,1],\n * u_somePosition: [0,1,1],\n * u_someMatrix: [\n * 1,0,0,0,\n * 0,1,0,0,\n * 0,0,1,0,\n * 0,0,0,0,\n * ],\n * };\n *\n * gl.useProgram(programInfo.program);\n *\n * This will automatically bind the textures AND set the\n * uniforms.\n *\n * twgl.setUniforms(programInfo, uniforms);\n *\n * For the example above it is equivalent to\n *\n * let texUnit = 0;\n * gl.activeTexture(gl.TEXTURE0 + texUnit);\n * gl.bindTexture(gl.TEXTURE_2D, tex1);\n * gl.uniform1i(u_someSamplerLocation, texUnit++);\n * gl.activeTexture(gl.TEXTURE0 + texUnit);\n * gl.bindTexture(gl.TEXTURE_2D, tex2);\n * gl.uniform1i(u_someSamplerLocation, texUnit++);\n * gl.uniform4fv(u_someColorLocation, [1, 0, 0, 1]);\n * gl.uniform3fv(u_somePositionLocation, [0, 1, 1]);\n * gl.uniformMatrix4fv(u_someMatrix, false, [\n * 1,0,0,0,\n * 0,1,0,0,\n * 0,0,1,0,\n * 0,0,0,0,\n * ]);\n *\n * Note it is perfectly reasonable to call `setUniforms` multiple times. For example\n *\n * const uniforms = {\n * u_someSampler: tex1,\n * u_someOtherSampler: tex2,\n * };\n *\n * const moreUniforms {\n * u_someColor: [1,0,0,1],\n * u_somePosition: [0,1,1],\n * u_someMatrix: [\n * 1,0,0,0,\n * 0,1,0,0,\n * 0,0,1,0,\n * 0,0,0,0,\n * ],\n * };\n *\n * twgl.setUniforms(programInfo, uniforms);\n * twgl.setUniforms(programInfo, moreUniforms);\n *\n * You can also add WebGLSamplers to uniform samplers as in\n *\n * const uniforms = {\n * u_someSampler: {\n * texture: someWebGLTexture,\n * sampler: someWebGLSampler,\n * },\n * };\n *\n * In which case both the sampler and texture will be bound to the\n * same unit.\n *\n * @param {(module:twgl.ProgramInfo|Object.)} setters a `ProgramInfo` as returned from `createProgramInfo` or the setters returned from\n * `createUniformSetters`.\n * @param {Object.} values an object with values for the\n * uniforms.\n * You can pass multiple objects by putting them in an array or by calling with more arguments.For example\n *\n * const sharedUniforms = {\n * u_fogNear: 10,\n * u_projection: ...\n * ...\n * };\n *\n * const localUniforms = {\n * u_world: ...\n * u_diffuseColor: ...\n * };\n *\n * twgl.setUniforms(programInfo, sharedUniforms, localUniforms);\n *\n * // is the same as\n *\n * twgl.setUniforms(programInfo, [sharedUniforms, localUniforms]);\n *\n * // is the same as\n *\n * twgl.setUniforms(programInfo, sharedUniforms);\n * twgl.setUniforms(programInfo, localUniforms};\n *\n * You can also fill out structure and array values either via\n * shortcut. Example\n *\n * // -- in shader --\n * struct Light {\n * float intensity;\n * vec4 color;\n * float nearFar[2];\n * };\n * uniform Light lights[2];\n *\n * // in JavaScript\n *\n * twgl.setUniforms(programInfo, {\n * lights: [\n * { intensity: 5.0, color: [1, 0, 0, 1], nearFar[0.1, 10] },\n * { intensity: 2.0, color: [0, 0, 1, 1], nearFar[0.2, 15] },\n * ],\n * });\n *\n * or the more traditional way\n *\n * twgl.setUniforms(programInfo, {\n * \"lights[0].intensity\": 5.0,\n * \"lights[0].color\": [1, 0, 0, 1],\n * \"lights[0].nearFar\": [0.1, 10],\n * \"lights[1].intensity\": 2.0,\n * \"lights[1].color\": [0, 0, 1, 1],\n * \"lights[1].nearFar\": [0.2, 15],\n * });\n *\n * You can also specify partial paths\n *\n * twgl.setUniforms(programInfo, {\n * 'lights[1]': { intensity: 5.0, color: [1, 0, 0, 1], nearFar[0.2, 15] },\n * });\n *\n * But you can not specify leaf array indices\n *\n * twgl.setUniforms(programInfo, {\n * 'lights[1].nearFar[1]': 15, // BAD! nearFar is a leaf\n * 'lights[1].nearFar': [0.2, 15], // GOOD\n * });\n *\n * @memberOf module:twgl/programs\n */\nfunction setUniforms(setters, ...args) { // eslint-disable-line\n const actualSetters = setters.uniformSetters || setters;\n const numArgs = args.length;\n for (let aNdx = 0; aNdx < numArgs; ++aNdx) {\n const values = args[aNdx];\n if (Array.isArray(values)) {\n const numValues = values.length;\n for (let ii = 0; ii < numValues; ++ii) {\n setUniforms(actualSetters, values[ii]);\n }\n } else {\n for (const name in values) {\n const setter = actualSetters[name];\n if (setter) {\n setter(values[name]);\n }\n }\n }\n }\n}\n\n/**\n * Alias for `setUniforms`\n * @function\n * @param {(module:twgl.ProgramInfo|Object.)} setters a `ProgramInfo` as returned from `createProgramInfo` or the setters returned from\n * `createUniformSetters`.\n * @param {Object.} values an object with values for the\n * @memberOf module:twgl/programs\n */\nconst setUniformsAndBindTextures = setUniforms;\n\n/**\n * Creates setter functions for all attributes of a shader\n * program. You can pass this to {@link module:twgl.setBuffersAndAttributes} to set all your buffers and attributes.\n *\n * @see {@link module:twgl.setAttributes} for example\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use.\n * @param {WebGLProgram} program the program to create setters for.\n * @return {Object.} an object with a setter for each attribute by name.\n * @memberOf module:twgl/programs\n */\nfunction createAttributeSetters(gl, program) {\n const attribSetters = {\n };\n\n const numAttribs = gl.getProgramParameter(program, ACTIVE_ATTRIBUTES);\n for (let ii = 0; ii < numAttribs; ++ii) {\n const attribInfo = gl.getActiveAttrib(program, ii);\n if (isBuiltIn(attribInfo)) {\n continue;\n }\n const index = gl.getAttribLocation(program, attribInfo.name);\n const typeInfo = attrTypeMap[attribInfo.type];\n const setter = typeInfo.setter(gl, index, typeInfo);\n setter.location = index;\n attribSetters[attribInfo.name] = setter;\n }\n\n return attribSetters;\n}\n\n/**\n * Sets attributes and binds buffers (deprecated... use {@link module:twgl.setBuffersAndAttributes})\n *\n * Example:\n *\n * const program = createProgramFromScripts(\n * gl, [\"some-vs\", \"some-fs\");\n *\n * const attribSetters = createAttributeSetters(program);\n *\n * const positionBuffer = gl.createBuffer();\n * const texcoordBuffer = gl.createBuffer();\n *\n * const attribs = {\n * a_position: {buffer: positionBuffer, numComponents: 3},\n * a_texcoord: {buffer: texcoordBuffer, numComponents: 2},\n * };\n *\n * gl.useProgram(program);\n *\n * This will automatically bind the buffers AND set the\n * attributes.\n *\n * setAttributes(attribSetters, attribs);\n *\n * Properties of attribs. For each attrib you can add\n * properties:\n *\n * * type: the type of data in the buffer. Default = gl.FLOAT\n * * normalize: whether or not to normalize the data. Default = false\n * * stride: the stride. Default = 0\n * * offset: offset into the buffer. Default = 0\n * * divisor: the divisor for instances. Default = undefined\n *\n * For example if you had 3 value float positions, 2 value\n * float texcoord and 4 value uint8 colors you'd setup your\n * attribs like this\n *\n * const attribs = {\n * a_position: {buffer: positionBuffer, numComponents: 3},\n * a_texcoord: {buffer: texcoordBuffer, numComponents: 2},\n * a_color: {\n * buffer: colorBuffer,\n * numComponents: 4,\n * type: gl.UNSIGNED_BYTE,\n * normalize: true,\n * },\n * };\n *\n * @param {Object.} setters Attribute setters as returned from createAttributeSetters\n * @param {Object.} buffers AttribInfos mapped by attribute name.\n * @memberOf module:twgl/programs\n * @deprecated use {@link module:twgl.setBuffersAndAttributes}\n * @private\n */\nfunction setAttributes(setters, buffers) {\n for (const name in buffers) {\n const setter = setters[name];\n if (setter) {\n setter(buffers[name]);\n }\n }\n}\n\n/**\n * Sets attributes and buffers including the `ELEMENT_ARRAY_BUFFER` if appropriate\n *\n * Example:\n *\n * const programInfo = createProgramInfo(\n * gl, [\"some-vs\", \"some-fs\");\n *\n * const arrays = {\n * position: { numComponents: 3, data: [0, 0, 0, 10, 0, 0, 0, 10, 0, 10, 10, 0], },\n * texcoord: { numComponents: 2, data: [0, 0, 0, 1, 1, 0, 1, 1], },\n * };\n *\n * const bufferInfo = createBufferInfoFromArrays(gl, arrays);\n *\n * gl.useProgram(programInfo.program);\n *\n * This will automatically bind the buffers AND set the\n * attributes.\n *\n * setBuffersAndAttributes(gl, programInfo, bufferInfo);\n *\n * For the example above it is equivalent to\n *\n * gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);\n * gl.enableVertexAttribArray(a_positionLocation);\n * gl.vertexAttribPointer(a_positionLocation, 3, gl.FLOAT, false, 0, 0);\n * gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);\n * gl.enableVertexAttribArray(a_texcoordLocation);\n * gl.vertexAttribPointer(a_texcoordLocation, 4, gl.FLOAT, false, 0, 0);\n *\n * @param {WebGLRenderingContext} gl A WebGLRenderingContext.\n * @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}\n * @param {(module:twgl.BufferInfo|module:twgl.VertexArrayInfo)} buffers a `BufferInfo` as returned from {@link module:twgl.createBufferInfoFromArrays}.\n * or a `VertexArrayInfo` as returned from {@link module:twgl.createVertexArrayInfo}\n * @memberOf module:twgl/programs\n */\nfunction setBuffersAndAttributes(gl, programInfo, buffers) {\n if (buffers.vertexArrayObject) {\n gl.bindVertexArray(buffers.vertexArrayObject);\n } else {\n setAttributes(programInfo.attribSetters || programInfo, buffers.attribs);\n if (buffers.indices) {\n gl.bindBuffer(ELEMENT_ARRAY_BUFFER$1, buffers.indices);\n }\n }\n}\n\n/**\n * @typedef {Object} ProgramInfo\n * @property {WebGLProgram} program A shader program\n * @property {Object} uniformSetters object of setters as returned from createUniformSetters,\n * @property {Object} attribSetters object of setters as returned from createAttribSetters,\n * @property {module:twgl.UniformBlockSpec} [uniformBlockSpec] a uniform block spec for making UniformBlockInfos with createUniformBlockInfo etc..\n * @property {Object} [transformFeedbackInfo] info for transform feedbacks\n * @memberOf module:twgl\n */\n\n/**\n * Creates a ProgramInfo from an existing program.\n *\n * A ProgramInfo contains\n *\n * programInfo = {\n * program: WebGLProgram,\n * uniformSetters: object of setters as returned from createUniformSetters,\n * attribSetters: object of setters as returned from createAttribSetters,\n * }\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext\n * to use.\n * @param {WebGLProgram} program an existing WebGLProgram.\n * @return {module:twgl.ProgramInfo} The created ProgramInfo.\n * @memberOf module:twgl/programs\n */\nfunction createProgramInfoFromProgram(gl, program) {\n const uniformSetters = createUniformSetters(gl, program);\n const attribSetters = createAttributeSetters(gl, program);\n const programInfo = {\n program,\n uniformSetters,\n attribSetters,\n };\n\n if (isWebGL2(gl)) {\n programInfo.uniformBlockSpec = createUniformBlockSpecFromProgram(gl, program);\n programInfo.transformFeedbackInfo = createTransformFeedbackInfo(gl, program);\n }\n\n return programInfo;\n}\n\nconst notIdRE = /\\s|{|}|;/;\n\n/**\n * Creates a ProgramInfo from 2 sources.\n *\n * A ProgramInfo contains\n *\n * programInfo = {\n * program: WebGLProgram,\n * uniformSetters: object of setters as returned from createUniformSetters,\n * attribSetters: object of setters as returned from createAttribSetters,\n * }\n *\n * NOTE: There are 4 signatures for this function\n *\n * twgl.createProgramInfo(gl, [vs, fs], options);\n * twgl.createProgramInfo(gl, [vs, fs], opt_errFunc);\n * twgl.createProgramInfo(gl, [vs, fs], opt_attribs, opt_errFunc);\n * twgl.createProgramInfo(gl, [vs, fs], opt_attribs, opt_locations, opt_errFunc);\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext\n * to use.\n * @param {string[]} shaderSources Array of sources for the\n * shaders or ids. The first is assumed to be the vertex shader,\n * the second the fragment shader.\n * @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\n * @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.\n * @param {module:twgl.ErrorCallback} [opt_errorCallback] callback for errors. By default it just prints an error to the console\n * on error. If you want something else pass an callback. It's passed an error message.\n * @return {module:twgl.ProgramInfo?} The created ProgramInfo or null if it failed to link or compile\n * @memberOf module:twgl/programs\n */\nfunction createProgramInfo(\n gl, shaderSources, opt_attribs, opt_locations, opt_errorCallback) {\n const progOptions = getProgramOptions(opt_attribs, opt_locations, opt_errorCallback);\n const errors = [];\n shaderSources = shaderSources.map(function(source) {\n // Lets assume if there is no \\n it's an id\n if (!notIdRE.test(source)) {\n const script = getElementById(source);\n if (!script) {\n const err = `no element with id: ${source}`;\n progOptions.errorCallback(err);\n errors.push(err);\n } else {\n source = script.text;\n }\n }\n return source;\n });\n\n if (errors.length) {\n return reportError(progOptions, '');\n }\n\n const origCallback = progOptions.callback;\n if (origCallback) {\n progOptions.callback = (err, program) => {\n origCallback(err, err ? undefined : createProgramInfoFromProgram(gl, program));\n };\n }\n\n const program = createProgramFromSources(gl, shaderSources, progOptions);\n if (!program) {\n return null;\n }\n\n return createProgramInfoFromProgram(gl, program);\n}\n\nfunction checkAllPrograms(gl, programs, programSpecs, noDeleteShadersSet, programOptions) {\n // check errors for everything.\n for (const [name, program] of Object.entries(programs)) {\n const options = {...programOptions};\n const spec = programSpecs[name];\n if (!Array.isArray(spec)) {\n Object.assign(options, spec);\n }\n const errors = getProgramErrors(gl, program, options.errorCallback);\n if (errors) {\n // delete everything we created\n for (const program of Object.values(programs)) {\n const shaders = gl.getAttachedShaders(program);\n gl.deleteProgram(program);\n for (const shader of shaders) {\n // Don't delete it if we didn't create it.\n if (!noDeleteShadersSet.has(shader)) {\n gl.deleteShader(shader);\n }\n }\n }\n return errors;\n }\n }\n\n return undefined;\n}\n\n/**\n * Creates multiple programs\n *\n * Note: the reason this function exists is because the fastest way to create multiple\n * programs in WebGL is to create and compile all shaders and link all programs and only\n * afterwards check if they succeeded. In that way, giving all your shaders\n *\n * @see {@link module:twgl.createProgram}\n *\n * Example:\n *\n * const programs = twgl.createPrograms(gl, {\n * lambert: [lambertVS, lambertFS],\n * phong: [phongVS, phoneFS],\n * particles: {\n * shaders: [particlesVS, particlesFS],\n * transformFeedbackVaryings: ['position', 'velocity'],\n * },\n * });\n *\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {Object.} programSpecs An object of ProgramSpecs, one per program.\n * @param {module:twgl.ProgramOptions} [programOptions] options to apply to all programs\n * @return {Object.?} the created programInfos by name\n */\nfunction createPrograms(gl, programSpecs, programOptions = {}) {\n // Remember existing shaders so that if there is an error we don't delete them\n const noDeleteShadersSet = new Set();\n\n // compile and link everything\n const programs = Object.fromEntries(Object.entries(programSpecs).map(([name, spec]) => {\n const options = {...programOptions};\n const shaders = Array.isArray(spec) ? spec : spec.shaders;\n if (!Array.isArray(spec)) {\n Object.assign(options, spec);\n }\n shaders.forEach(noDeleteShadersSet.add, noDeleteShadersSet);\n return [name, createProgramNoCheck(gl, shaders, options)];\n }));\n\n if (programOptions.callback) {\n waitForAllProgramsLinkCompletionAsync(gl, programs).then(() => {\n const errors = checkAllPrograms(gl, programs, programSpecs, noDeleteShadersSet, programOptions);\n programOptions.callback(errors, errors ? undefined : programs);\n });\n return undefined;\n }\n\n const errors = checkAllPrograms(gl, programs, programSpecs, noDeleteShadersSet, programOptions);\n return errors ? undefined : programs;\n}\n\n/**\n * Creates multiple programInfos\n *\n * Note: the reason this function exists is because the fastest way to create multiple\n * programs in WebGL is to create and compile all shaders and link all programs and only\n * afterwards check if they succeeded. In that way, giving all your shaders\n *\n * @see {@link module:twgl.createProgramInfo}\n *\n * Examples:\n *\n * const programInfos = twgl.createProgramInfos(gl, {\n * lambert: [lambertVS, lambertFS],\n * phong: [phongVS, phoneFS],\n * particles: {\n * shaders: [particlesVS, particlesFS],\n * transformFeedbackVaryings: ['position', 'velocity'],\n * },\n * });\n *\n * or\n *\n * const {lambert, phong, particles} = twgl.createProgramInfos(gl, {\n * lambert: [lambertVS, lambertFS],\n * phong: [phongVS, phoneFS],\n * particles: {\n * shaders: [particlesVS, particlesFS],\n * transformFeedbackVaryings: ['position', 'velocity'],\n * },\n * });\n *\n *\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {Object.} programSpecs An object of ProgramSpecs, one per program.\n * @param {module:twgl.ProgramOptions} [programOptions] options to apply to all programs\n * @return {Object.?} the created programInfos by name\n */\nfunction createProgramInfos(gl, programSpecs, programOptions) {\n programOptions = getProgramOptions(programOptions);\n\n function createProgramInfosForPrograms(gl, programs) {\n return Object.fromEntries(Object.entries(programs).map(([name, program]) =>\n [name, createProgramInfoFromProgram(gl, program)]\n ));\n }\n\n const origCallback = programOptions.callback;\n if (origCallback) {\n programOptions.callback = (err, programs) => {\n origCallback(err, err ? undefined : createProgramInfosForPrograms(gl, programs));\n };\n }\n\n const programs = createPrograms(gl, programSpecs, programOptions);\n if (origCallback || !programs) {\n return undefined;\n }\n\n return createProgramInfosForPrograms(gl, programs);\n}\n\n/**\n * Creates multiple programs asynchronously\n *\n * @see {@link module:twgl.createProgramAsync}\n *\n * Example:\n *\n * const programs = await twgl.createProgramsAsync(gl, {\n * lambert: [lambertVS, lambertFS],\n * phong: [phongVS, phoneFS],\n * particles: {\n * shaders: [particlesVS, particlesFS],\n * transformFeedbackVaryings: ['position', 'velocity'],\n * },\n * });\n *\n * @function\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {Object.} programSpecs An object of ProgramSpecs, one per program.\n * @param {module:twgl.ProgramOptions} [programOptions] options to apply to all programs\n * @return {Object.?} the created programInfos by name\n */\nconst createProgramsAsync = wrapCallbackFnToAsyncFn(createPrograms);\n\n/**\n * Creates multiple programInfos asynchronously\n *\n * @see {@link module:twgl.createProgramInfoAsync}\n *\n * Example:\n *\n * const programInfos = await twgl.createProgramInfosAsync(gl, {\n * lambert: [lambertVS, lambertFS],\n * phong: [phongVS, phoneFS],\n * particles: {\n * shaders: [particlesVS, particlesFS],\n * transformFeedbackVaryings: ['position', 'velocity'],\n * },\n * });\n *\n * @function\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {Object.} programSpecs An object of ProgramSpecs, one per program.\n * @param {module:twgl.ProgramOptions} [programOptions] options to apply to all programs\n * @return {Promise>} the created programInfos by name\n */\nconst createProgramInfosAsync = wrapCallbackFnToAsyncFn(createProgramInfos);\n\nvar programs = /*#__PURE__*/Object.freeze({\n __proto__: null,\n createAttributeSetters: createAttributeSetters,\n createProgram: createProgram,\n createProgramAsync: createProgramAsync,\n createPrograms: createPrograms,\n createProgramsAsync: createProgramsAsync,\n createProgramFromScripts: createProgramFromScripts,\n createProgramFromSources: createProgramFromSources,\n createProgramInfo: createProgramInfo,\n createProgramInfoAsync: createProgramInfoAsync,\n createProgramInfos: createProgramInfos,\n createProgramInfosAsync: createProgramInfosAsync,\n createProgramInfoFromProgram: createProgramInfoFromProgram,\n createUniformSetters: createUniformSetters,\n createUniformBlockSpecFromProgram: createUniformBlockSpecFromProgram,\n createUniformBlockInfoFromProgram: createUniformBlockInfoFromProgram,\n createUniformBlockInfo: createUniformBlockInfo,\n createTransformFeedback: createTransformFeedback,\n createTransformFeedbackInfo: createTransformFeedbackInfo,\n bindTransformFeedbackInfo: bindTransformFeedbackInfo,\n setAttributes: setAttributes,\n setBuffersAndAttributes: setBuffersAndAttributes,\n setUniforms: setUniforms,\n setUniformsAndBindTextures: setUniformsAndBindTextures,\n setUniformBlock: setUniformBlock,\n setBlockUniforms: setBlockUniforms,\n bindUniformBlock: bindUniformBlock\n});\n\n/*\n * Copyright 2019 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\nconst TRIANGLES = 0x0004;\nconst UNSIGNED_SHORT = 0x1403;\n\n/**\n * Drawing related functions\n *\n * For backward compatibility they are available at both `twgl.draw` and `twgl`\n * itself\n *\n * See {@link module:twgl} for core functions\n *\n * @module twgl/draw\n */\n\n/**\n * Calls `gl.drawElements` or `gl.drawArrays`, whichever is appropriate\n *\n * normally you'd call `gl.drawElements` or `gl.drawArrays` yourself\n * but calling this means if you switch from indexed data to non-indexed\n * data you don't have to remember to update your draw call.\n *\n * @param {WebGLRenderingContext} gl A WebGLRenderingContext\n * @param {(module:twgl.BufferInfo|module:twgl.VertexArrayInfo)} bufferInfo A BufferInfo as returned from {@link module:twgl.createBufferInfoFromArrays} or\n * a VertexArrayInfo as returned from {@link module:twgl.createVertexArrayInfo}\n * @param {number} [type] eg (gl.TRIANGLES, gl.LINES, gl.POINTS, gl.TRIANGLE_STRIP, ...). Defaults to `gl.TRIANGLES`\n * @param {number} [count] An optional count. Defaults to bufferInfo.numElements\n * @param {number} [offset] An optional offset. Defaults to 0.\n * @param {number} [instanceCount] An optional instanceCount. if set then `drawArraysInstanced` or `drawElementsInstanced` will be called\n * @memberOf module:twgl/draw\n */\nfunction drawBufferInfo(gl, bufferInfo, type, count, offset, instanceCount) {\n type = type === undefined ? TRIANGLES : type;\n const indices = bufferInfo.indices;\n const elementType = bufferInfo.elementType;\n const numElements = count === undefined ? bufferInfo.numElements : count;\n offset = offset === undefined ? 0 : offset;\n if (elementType || indices) {\n if (instanceCount !== undefined) {\n gl.drawElementsInstanced(type, numElements, elementType === undefined ? UNSIGNED_SHORT : bufferInfo.elementType, offset, instanceCount);\n } else {\n gl.drawElements(type, numElements, elementType === undefined ? UNSIGNED_SHORT : bufferInfo.elementType, offset);\n }\n } else {\n if (instanceCount !== undefined) {\n gl.drawArraysInstanced(type, offset, numElements, instanceCount);\n } else {\n gl.drawArrays(type, offset, numElements);\n }\n }\n}\n\n/**\n * A DrawObject is useful for putting objects in to an array and passing them to {@link module:twgl.drawObjectList}.\n *\n * You need either a `BufferInfo` or a `VertexArrayInfo`.\n *\n * @typedef {Object} DrawObject\n * @property {boolean} [active] whether or not to draw. Default = `true` (must be `false` to be not true). In other words `undefined` = `true`\n * @property {number} [type] type to draw eg. `gl.TRIANGLES`, `gl.LINES`, etc...\n * @property {module:twgl.ProgramInfo} programInfo A ProgramInfo as returned from {@link module:twgl.createProgramInfo}\n * @property {module:twgl.BufferInfo} [bufferInfo] A BufferInfo as returned from {@link module:twgl.createBufferInfoFromArrays}\n * @property {module:twgl.VertexArrayInfo} [vertexArrayInfo] A VertexArrayInfo as returned from {@link module:twgl.createVertexArrayInfo}\n * @property {Object} uniforms The values for the uniforms.\n * You can pass multiple objects by putting them in an array. For example\n *\n * var sharedUniforms = {\n * u_fogNear: 10,\n * u_projection: ...\n * ...\n * };\n *\n * var localUniforms = {\n * u_world: ...\n * u_diffuseColor: ...\n * };\n *\n * var drawObj = {\n * ...\n * uniforms: [sharedUniforms, localUniforms],\n * };\n *\n * @property {number} [offset] the offset to pass to `gl.drawArrays` or `gl.drawElements`. Defaults to 0.\n * @property {number} [count] the count to pass to `gl.drawArrays` or `gl.drawElements`. Defaults to bufferInfo.numElements.\n * @property {number} [instanceCount] the number of instances. Defaults to undefined.\n * @memberOf module:twgl\n */\n\n/**\n * Draws a list of objects\n * @param {WebGLRenderingContext} gl A WebGLRenderingContext\n * @param {DrawObject[]} objectsToDraw an array of objects to draw.\n * @memberOf module:twgl/draw\n */\nfunction drawObjectList(gl, objectsToDraw) {\n let lastUsedProgramInfo = null;\n let lastUsedBufferInfo = null;\n\n objectsToDraw.forEach(function(object) {\n if (object.active === false) {\n return;\n }\n\n const programInfo = object.programInfo;\n const bufferInfo = object.vertexArrayInfo || object.bufferInfo;\n let bindBuffers = false;\n const type = object.type === undefined ? TRIANGLES : object.type;\n\n if (programInfo !== lastUsedProgramInfo) {\n lastUsedProgramInfo = programInfo;\n gl.useProgram(programInfo.program);\n\n // We have to rebind buffers when changing programs because we\n // only bind buffers the program uses. So if 2 programs use the same\n // bufferInfo but the 1st one uses only positions the when the\n // we switch to the 2nd one some of the attributes will not be on.\n bindBuffers = true;\n }\n\n // Setup all the needed attributes.\n if (bindBuffers || bufferInfo !== lastUsedBufferInfo) {\n if (lastUsedBufferInfo && lastUsedBufferInfo.vertexArrayObject && !bufferInfo.vertexArrayObject) {\n gl.bindVertexArray(null);\n }\n lastUsedBufferInfo = bufferInfo;\n setBuffersAndAttributes(gl, programInfo, bufferInfo);\n }\n\n // Set the uniforms.\n setUniforms(programInfo, object.uniforms);\n\n // Draw\n drawBufferInfo(gl, bufferInfo, type, object.count, object.offset, object.instanceCount);\n });\n\n if (lastUsedBufferInfo && lastUsedBufferInfo.vertexArrayObject) {\n gl.bindVertexArray(null);\n }\n}\n\nvar draw = /*#__PURE__*/Object.freeze({\n __proto__: null,\n drawBufferInfo: drawBufferInfo,\n drawObjectList: drawObjectList\n});\n\n/*\n * Copyright 2019 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\nconst FRAMEBUFFER = 0x8d40;\nconst RENDERBUFFER = 0x8d41;\nconst TEXTURE_2D = 0x0de1;\n\nconst UNSIGNED_BYTE = 0x1401;\n\n/* PixelFormat */\nconst DEPTH_COMPONENT = 0x1902;\nconst RGBA = 0x1908;\nconst DEPTH_COMPONENT24 = 0x81a6;\nconst DEPTH_COMPONENT32F = 0x8cac;\nconst DEPTH24_STENCIL8 = 0x88f0;\nconst DEPTH32F_STENCIL8 = 0x8cad;\n\n/* Framebuffer Object. */\nconst RGBA4 = 0x8056;\nconst RGB5_A1 = 0x8057;\nconst RGB565 = 0x8D62;\nconst DEPTH_COMPONENT16 = 0x81A5;\nconst STENCIL_INDEX = 0x1901;\nconst STENCIL_INDEX8 = 0x8D48;\nconst DEPTH_STENCIL = 0x84F9;\nconst COLOR_ATTACHMENT0 = 0x8CE0;\nconst DEPTH_ATTACHMENT = 0x8D00;\nconst STENCIL_ATTACHMENT = 0x8D20;\nconst DEPTH_STENCIL_ATTACHMENT = 0x821A;\n\n/* TextureWrapMode */\nconst CLAMP_TO_EDGE = 0x812F;\n\n/* TextureMagFilter */\nconst LINEAR = 0x2601;\n\n/**\n * The options for a framebuffer attachment.\n *\n * Note: For a `format` that is a texture include all the texture\n * options from {@link module:twgl.TextureOptions} for example\n * `min`, `mag`, `clamp`, etc... Note that unlike {@link module:twgl.TextureOptions}\n * `auto` defaults to `false` for attachment textures but `min` and `mag` default\n * to `gl.LINEAR` and `wrap` defaults to `CLAMP_TO_EDGE`\n *\n * @typedef {Object} AttachmentOptions\n * @property {number} [attachmentPoint] The attachment point. Defaults\n * to `gl.COLOR_ATTACHMENT0 + ndx` unless type is a depth or stencil type\n * then it's gl.DEPTH_ATTACHMENT or `gl.DEPTH_STENCIL_ATTACHMENT` depending\n * on the format or attachment type.\n * @property {number} [format] The format. If one of `gl.RGBA4`,\n * `gl.RGB565`, `gl.RGB5_A1`, `gl.DEPTH_COMPONENT16`,\n * `gl.STENCIL_INDEX8` or `gl.DEPTH_STENCIL` then will create a\n * renderbuffer. Otherwise will create a texture. Default = `gl.RGBA`\n * @property {number} [type] The type. Used for texture. Default = `gl.UNSIGNED_BYTE`.\n * @property {number} [target] The texture target for `gl.framebufferTexture2D`.\n * Defaults to `gl.TEXTURE_2D`. Set to appropriate face for cube maps.\n * @property {number} [samples] The number of samples. Default = 1\n * @property {number} [level] level for `gl.framebufferTexture2D`. Defaults to 0.\n * @property {number} [layer] layer for `gl.framebufferTextureLayer`. Defaults to undefined.\n * If set then `gl.framebufferTextureLayer` is called, if not then `gl.framebufferTexture2D`\n * @property {(WebGLRenderbuffer | WebGLTexture)} [attachment] An existing renderbuffer or texture.\n * If provided will attach this Object. This allows you to share\n * attachments across framebuffers.\n * @memberOf module:twgl\n * @mixes module:twgl.TextureOptions\n */\n\nconst defaultAttachments = [\n { format: RGBA, type: UNSIGNED_BYTE, min: LINEAR, wrap: CLAMP_TO_EDGE, },\n { format: DEPTH_STENCIL, },\n];\n\nconst attachmentsByFormat = {};\nattachmentsByFormat[DEPTH_STENCIL] = DEPTH_STENCIL_ATTACHMENT;\nattachmentsByFormat[STENCIL_INDEX] = STENCIL_ATTACHMENT;\nattachmentsByFormat[STENCIL_INDEX8] = STENCIL_ATTACHMENT;\nattachmentsByFormat[DEPTH_COMPONENT] = DEPTH_ATTACHMENT;\nattachmentsByFormat[DEPTH_COMPONENT16] = DEPTH_ATTACHMENT;\nattachmentsByFormat[DEPTH_COMPONENT24] = DEPTH_ATTACHMENT;\nattachmentsByFormat[DEPTH_COMPONENT32F] = DEPTH_ATTACHMENT;\nattachmentsByFormat[DEPTH24_STENCIL8] = DEPTH_STENCIL_ATTACHMENT;\nattachmentsByFormat[DEPTH32F_STENCIL8] = DEPTH_STENCIL_ATTACHMENT;\n\nfunction getAttachmentPointForFormat(format, internalFormat) {\n return attachmentsByFormat[format] || attachmentsByFormat[internalFormat];\n}\n\nconst renderbufferFormats = {};\nrenderbufferFormats[RGBA4] = true;\nrenderbufferFormats[RGB5_A1] = true;\nrenderbufferFormats[RGB565] = true;\nrenderbufferFormats[DEPTH_STENCIL] = true;\nrenderbufferFormats[DEPTH_COMPONENT16] = true;\nrenderbufferFormats[STENCIL_INDEX] = true;\nrenderbufferFormats[STENCIL_INDEX8] = true;\n\nfunction isRenderbufferFormat(format) {\n return renderbufferFormats[format];\n}\n\nconst MAX_COLOR_ATTACHMENT_POINTS = 32; // even an 3090 only supports 8 but WebGL/OpenGL ES define constants for 32\n\nfunction isColorAttachmentPoint(attachmentPoint) {\n return attachmentPoint >= COLOR_ATTACHMENT0 && attachmentPoint < COLOR_ATTACHMENT0 + MAX_COLOR_ATTACHMENT_POINTS;\n}\n\n/**\n * @typedef {Object} FramebufferInfo\n * @property {WebGLFramebuffer} framebuffer The WebGLFramebuffer for this framebufferInfo\n * @property {Array.<(WebGLRenderbuffer | WebGLTexture)>} attachments The created attachments in the same order as passed in to {@link module:twgl.createFramebufferInfo}.\n * @property {number} width The width of the framebuffer and its attachments\n * @property {number} height The width of the framebuffer and its attachments\n * @memberOf module:twgl\n */\n\n/**\n * Creates a framebuffer and attachments.\n *\n * This returns a {@link module:twgl.FramebufferInfo} because it needs to return the attachments as well as the framebuffer.\n * It also leaves the framebuffer it just created as the currently bound `FRAMEBUFFER`.\n * Note: If this is WebGL2 or if you called {@link module:twgl.addExtensionsToContext} then it will set the drawBuffers\n * to `[COLOR_ATTACHMENT0, COLOR_ATTACHMENT1, ...]` for how ever many color attachments were created.\n *\n * The simplest usage\n *\n * // create an RGBA/UNSIGNED_BYTE texture and DEPTH_STENCIL renderbuffer\n * const fbi = twgl.createFramebufferInfo(gl);\n *\n * More complex usage\n *\n * // create an RGB565 renderbuffer and a STENCIL_INDEX8 renderbuffer\n * const attachments = [\n * { format: RGB565, mag: NEAREST },\n * { format: STENCIL_INDEX8 },\n * ]\n * const fbi = twgl.createFramebufferInfo(gl, attachments);\n *\n * Passing in a specific size\n *\n * const width = 256;\n * const height = 256;\n * const fbi = twgl.createFramebufferInfo(gl, attachments, width, height);\n *\n * **Note!!** It is up to you to check if the framebuffer is renderable by calling `gl.checkFramebufferStatus`.\n * [WebGL1 only guarantees 3 combinations of attachments work](https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.6).\n *\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {module:twgl.AttachmentOptions[]} [attachments] which attachments to create. If not provided the default is a framebuffer with an\n * `RGBA`, `UNSIGNED_BYTE` texture `COLOR_ATTACHMENT0` and a `DEPTH_STENCIL` renderbuffer `DEPTH_STENCIL_ATTACHMENT`.\n * @param {number} [width] the width for the attachments. Default = size of drawingBuffer\n * @param {number} [height] the height for the attachments. Default = size of drawingBuffer\n * @return {module:twgl.FramebufferInfo} the framebuffer and attachments.\n * @memberOf module:twgl/framebuffers\n */\nfunction createFramebufferInfo(gl, attachments, width, height) {\n const target = FRAMEBUFFER;\n const fb = gl.createFramebuffer();\n gl.bindFramebuffer(target, fb);\n width = width || gl.drawingBufferWidth;\n height = height || gl.drawingBufferHeight;\n attachments = attachments || defaultAttachments;\n const usedColorAttachmentsPoints = [];\n const framebufferInfo = {\n framebuffer: fb,\n attachments: [],\n width: width,\n height: height,\n };\n\n attachments.forEach(function(attachmentOptions, i) {\n let attachment = attachmentOptions.attachment;\n const samples = attachmentOptions.samples;\n const format = attachmentOptions.format;\n let attachmentPoint = attachmentOptions.attachmentPoint || getAttachmentPointForFormat(format, attachmentOptions.internalFormat);\n if (!attachmentPoint) {\n attachmentPoint = COLOR_ATTACHMENT0 + i;\n }\n if (isColorAttachmentPoint(attachmentPoint)) {\n usedColorAttachmentsPoints.push(attachmentPoint);\n }\n if (!attachment) {\n if (samples !== undefined || isRenderbufferFormat(format)) {\n attachment = gl.createRenderbuffer();\n gl.bindRenderbuffer(RENDERBUFFER, attachment);\n if (samples > 1) {\n gl.renderbufferStorageMultisample(RENDERBUFFER, samples, format, width, height);\n } else {\n gl.renderbufferStorage(RENDERBUFFER, format, width, height);\n }\n } else {\n const textureOptions = Object.assign({}, attachmentOptions);\n textureOptions.width = width;\n textureOptions.height = height;\n if (textureOptions.auto === undefined) {\n textureOptions.auto = false;\n textureOptions.min = textureOptions.min || textureOptions.minMag || LINEAR;\n textureOptions.mag = textureOptions.mag || textureOptions.minMag || LINEAR;\n textureOptions.wrapS = textureOptions.wrapS || textureOptions.wrap || CLAMP_TO_EDGE;\n textureOptions.wrapT = textureOptions.wrapT || textureOptions.wrap || CLAMP_TO_EDGE;\n }\n attachment = createTexture(gl, textureOptions);\n }\n }\n if (isRenderbuffer(gl, attachment)) {\n gl.framebufferRenderbuffer(target, attachmentPoint, RENDERBUFFER, attachment);\n } else if (isTexture(gl, attachment)) {\n if (attachmentOptions.layer !== undefined) {\n gl.framebufferTextureLayer(\n target,\n attachmentPoint,\n attachment,\n attachmentOptions.level || 0,\n attachmentOptions.layer);\n } else {\n gl.framebufferTexture2D(\n target,\n attachmentPoint,\n attachmentOptions.target || TEXTURE_2D,\n attachment,\n attachmentOptions.level || 0);\n }\n } else {\n throw new Error('unknown attachment type');\n }\n framebufferInfo.attachments.push(attachment);\n });\n if (gl.drawBuffers) {\n gl.drawBuffers(usedColorAttachmentsPoints);\n }\n return framebufferInfo;\n}\n\n/**\n * Resizes the attachments of a framebuffer.\n *\n * You need to pass in the same `attachments` as you passed in {@link module:twgl.createFramebufferInfo}\n * because TWGL has no idea the format/type of each attachment.\n *\n * The simplest usage\n *\n * // create an RGBA/UNSIGNED_BYTE texture and DEPTH_STENCIL renderbuffer\n * const fbi = twgl.createFramebufferInfo(gl);\n *\n * ...\n *\n * function render() {\n * if (twgl.resizeCanvasToDisplaySize(gl.canvas)) {\n * // resize the attachments\n * twgl.resizeFramebufferInfo(gl, fbi);\n * }\n *\n * More complex usage\n *\n * // create an RGB565 renderbuffer and a STENCIL_INDEX8 renderbuffer\n * const attachments = [\n * { format: RGB565, mag: NEAREST },\n * { format: STENCIL_INDEX8 },\n * ]\n * const fbi = twgl.createFramebufferInfo(gl, attachments);\n *\n * ...\n *\n * function render() {\n * if (twgl.resizeCanvasToDisplaySize(gl.canvas)) {\n * // resize the attachments to match\n * twgl.resizeFramebufferInfo(gl, fbi, attachments);\n * }\n *\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {module:twgl.FramebufferInfo} framebufferInfo a framebufferInfo as returned from {@link module:twgl.createFramebufferInfo}.\n * @param {module:twgl.AttachmentOptions[]} [attachments] the same attachments options as passed to {@link module:twgl.createFramebufferInfo}.\n * @param {number} [width] the width for the attachments. Default = size of drawingBuffer\n * @param {number} [height] the height for the attachments. Default = size of drawingBuffer\n * @memberOf module:twgl/framebuffers\n */\nfunction resizeFramebufferInfo(gl, framebufferInfo, attachments, width, height) {\n width = width || gl.drawingBufferWidth;\n height = height || gl.drawingBufferHeight;\n framebufferInfo.width = width;\n framebufferInfo.height = height;\n attachments = attachments || defaultAttachments;\n attachments.forEach(function(attachmentOptions, ndx) {\n const attachment = framebufferInfo.attachments[ndx];\n const format = attachmentOptions.format;\n const samples = attachmentOptions.samples;\n if (samples !== undefined || isRenderbuffer(gl, attachment)) {\n gl.bindRenderbuffer(RENDERBUFFER, attachment);\n if (samples > 1) {\n gl.renderbufferStorageMultisample(RENDERBUFFER, samples, format, width, height);\n } else {\n gl.renderbufferStorage(RENDERBUFFER, format, width, height);\n }\n } else if (isTexture(gl, attachment)) {\n resizeTexture(gl, attachment, attachmentOptions, width, height);\n } else {\n throw new Error('unknown attachment type');\n }\n });\n}\n\n/**\n * Binds a framebuffer\n *\n * This function pretty much solely exists because I spent hours\n * trying to figure out why something I wrote wasn't working only\n * to realize I forget to set the viewport dimensions.\n * My hope is this function will fix that.\n *\n * It is effectively the same as\n *\n * gl.bindFramebuffer(gl.FRAMEBUFFER, someFramebufferInfo.framebuffer);\n * gl.viewport(0, 0, someFramebufferInfo.width, someFramebufferInfo.height);\n *\n * @param {WebGLRenderingContext} gl the WebGLRenderingContext\n * @param {module:twgl.FramebufferInfo|null} [framebufferInfo] a framebufferInfo as returned from {@link module:twgl.createFramebufferInfo}.\n * If falsy will bind the canvas.\n * @param {number} [target] The target. If not passed `gl.FRAMEBUFFER` will be used.\n * @memberOf module:twgl/framebuffers\n */\n\nfunction bindFramebufferInfo(gl, framebufferInfo, target) {\n target = target || FRAMEBUFFER;\n if (framebufferInfo) {\n gl.bindFramebuffer(target, framebufferInfo.framebuffer);\n gl.viewport(0, 0, framebufferInfo.width, framebufferInfo.height);\n } else {\n gl.bindFramebuffer(target, null);\n gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);\n }\n}\n\nvar framebuffers = /*#__PURE__*/Object.freeze({\n __proto__: null,\n bindFramebufferInfo: bindFramebufferInfo,\n createFramebufferInfo: createFramebufferInfo,\n resizeFramebufferInfo: resizeFramebufferInfo\n});\n\n/*\n * Copyright 2019 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\n/**\n * vertex array object related functions\n *\n * You should generally not need to use these functions. They are provided\n * for those cases where you're doing something out of the ordinary\n * and you need lower level access.\n *\n * For backward compatibility they are available at both `twgl.attributes` and `twgl`\n * itself\n *\n * See {@link module:twgl} for core functions\n *\n * @module twgl/vertexArrays\n */\n\nconst ELEMENT_ARRAY_BUFFER = 0x8893;\n\n/**\n * @typedef {Object} VertexArrayInfo\n * @property {number} numElements The number of elements to pass to `gl.drawArrays` or `gl.drawElements`.\n * @property {number} [elementType] The type of indices `UNSIGNED_BYTE`, `UNSIGNED_SHORT` etc..\n * @property {WebGLVertexArrayObject} [vertexArrayObject] a vertex array object\n * @memberOf module:twgl\n */\n\n/**\n * Creates a VertexArrayInfo from a BufferInfo and one or more ProgramInfos\n *\n * This can be passed to {@link module:twgl.setBuffersAndAttributes} and to\n * {@link module:twgl:drawBufferInfo}.\n *\n * > **IMPORTANT:** Vertex Array Objects are **not** a direct analog for a BufferInfo. Vertex Array Objects\n * assign buffers to specific attributes at creation time. That means they can only be used with programs\n * who's attributes use the same attribute locations for the same purposes.\n *\n * > Bind your attribute locations by passing an array of attribute names to {@link module:twgl.createProgramInfo}\n * or use WebGL 2's GLSL ES 3's `layout(location = )` to make sure locations match.\n *\n * also\n *\n * > **IMPORTANT:** After calling twgl.setBuffersAndAttribute with a BufferInfo that uses a Vertex Array Object\n * that Vertex Array Object will be bound. That means **ANY MANIPULATION OF ELEMENT_ARRAY_BUFFER or ATTRIBUTES**\n * will affect the Vertex Array Object state.\n *\n * > Call `gl.bindVertexArray(null)` to get back manipulating the global attributes and ELEMENT_ARRAY_BUFFER.\n *\n * @param {WebGLRenderingContext} gl A WebGLRenderingContext\n * @param {module:twgl.ProgramInfo|module:twgl.ProgramInfo[]} programInfo a programInfo or array of programInfos\n * @param {module:twgl.BufferInfo} bufferInfo BufferInfo as returned from createBufferInfoFromArrays etc...\n *\n * You need to make sure every attribute that will be used is bound. So for example assume shader 1\n * uses attributes A, B, C and shader 2 uses attributes A, B, D. If you only pass in the programInfo\n * for shader 1 then only attributes A, B, and C will have their attributes set because TWGL doesn't\n * now attribute D's location.\n *\n * So, you can pass in both shader 1 and shader 2's programInfo\n *\n * @return {module:twgl.VertexArrayInfo} The created VertexArrayInfo\n *\n * @memberOf module:twgl/vertexArrays\n */\nfunction createVertexArrayInfo(gl, programInfos, bufferInfo) {\n const vao = gl.createVertexArray();\n gl.bindVertexArray(vao);\n if (!programInfos.length) {\n programInfos = [programInfos];\n }\n programInfos.forEach(function(programInfo) {\n setBuffersAndAttributes(gl, programInfo, bufferInfo);\n });\n gl.bindVertexArray(null);\n return {\n numElements: bufferInfo.numElements,\n elementType: bufferInfo.elementType,\n vertexArrayObject: vao,\n };\n}\n\n/**\n * Creates a vertex array object and then sets the attributes on it\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext to use.\n * @param {Object.} setters Attribute setters as returned from createAttributeSetters\n * @param {Object.} attribs AttribInfos mapped by attribute name.\n * @param {WebGLBuffer} [indices] an optional ELEMENT_ARRAY_BUFFER of indices\n *\n * @return {WebGLVertexArrayObject|null} The created WebGLVertexArrayObject\n *\n * @memberOf module:twgl/vertexArrays\n */\nfunction createVAOAndSetAttributes(gl, setters, attribs, indices) {\n const vao = gl.createVertexArray();\n gl.bindVertexArray(vao);\n setAttributes(setters, attribs);\n if (indices) {\n gl.bindBuffer(ELEMENT_ARRAY_BUFFER, indices);\n }\n // We unbind this because otherwise any change to ELEMENT_ARRAY_BUFFER\n // like when creating buffers for other stuff will mess up this VAO's binding\n gl.bindVertexArray(null);\n return vao;\n}\n\n/**\n * Creates a vertex array object and then sets the attributes\n * on it\n *\n * @param {WebGLRenderingContext} gl The WebGLRenderingContext\n * to use.\n * @param {Object.| module:twgl.ProgramInfo} programInfo as returned from createProgramInfo or Attribute setters as returned from createAttributeSetters\n * @param {module:twgl.BufferInfo} bufferInfo BufferInfo as returned from createBufferInfoFromArrays etc...\n * @param {WebGLBuffer} [indices] an optional ELEMENT_ARRAY_BUFFER of indices\n *\n * @return {WebGLVertexArrayObject|null} The created WebGLVertexArrayObject\n *\n * @memberOf module:twgl/vertexArrays\n */\nfunction createVAOFromBufferInfo(gl, programInfo, bufferInfo) {\n return createVAOAndSetAttributes(gl, programInfo.attribSetters || programInfo, bufferInfo.attribs, bufferInfo.indices);\n}\n\nvar vertexArrays = /*#__PURE__*/Object.freeze({\n __proto__: null,\n createVertexArrayInfo: createVertexArrayInfo,\n createVAOAndSetAttributes: createVAOAndSetAttributes,\n createVAOFromBufferInfo: createVAOFromBufferInfo\n});\n\n/*\n * Copyright 2019 Gregg Tavares\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\nconst defaults = {\n addExtensionsToContext: true,\n};\n\n/**\n * Various default settings for twgl.\n *\n * Note: You can call this any number of times. Example:\n *\n * twgl.setDefaults({ textureColor: [1, 0, 0, 1] });\n * twgl.setDefaults({ attribPrefix: 'a_' });\n *\n * is equivalent to\n *\n * twgl.setDefaults({\n * textureColor: [1, 0, 0, 1],\n * attribPrefix: 'a_',\n * });\n *\n * @typedef {Object} Defaults\n * @property {string} [attribPrefix] The prefix to stick on attributes\n *\n * When writing shaders I prefer to name attributes with `a_`, uniforms with `u_` and varyings with `v_`\n * as it makes it clear where they came from. But, when building geometry I prefer using un-prefixed names.\n *\n * In other words I'll create arrays of geometry like this\n *\n * const arrays = {\n * position: ...\n * normal: ...\n * texcoord: ...\n * };\n *\n * But need those mapped to attributes and my attributes start with `a_`.\n *\n * Default: `\"\"`\n *\n * @property {number[]} [textureColor] Array of 4 values in the range 0 to 1\n *\n * The default texture color is used when loading textures from\n * urls. Because the URL will be loaded async we'd like to be\n * able to use the texture immediately. By putting a 1x1 pixel\n * color in the texture we can start using the texture before\n * the URL has loaded.\n *\n * Default: `[0.5, 0.75, 1, 1]`\n *\n * @property {string} [crossOrigin]\n *\n * If not undefined sets the crossOrigin attribute on images\n * that twgl creates when downloading images for textures.\n *\n * Also see {@link module:twgl.TextureOptions}.\n *\n * @property {bool} [addExtensionsToContext]\n *\n * If true, then, when twgl will try to add any supported WebGL extensions\n * directly to the context under their normal GL names. For example\n * if ANGLE_instances_arrays exists then twgl would enable it,\n * add the functions `vertexAttribDivisor`, `drawArraysInstanced`,\n * `drawElementsInstanced`, and the constant `VERTEX_ATTRIB_ARRAY_DIVISOR`\n * to the `WebGLRenderingContext`.\n *\n * @memberOf module:twgl\n */\n\n/**\n * Sets various defaults for twgl.\n *\n * In the interest of terseness which is kind of the point\n * of twgl I've integrated a few of the older functions here\n *\n * @param {module:twgl.Defaults} newDefaults The default settings.\n * @memberOf module:twgl\n */\nfunction setDefaults(newDefaults) {\n copyExistingProperties(newDefaults, defaults);\n setDefaults$2(newDefaults); // eslint-disable-line\n setDefaults$1(newDefaults); // eslint-disable-line\n}\n\nconst prefixRE = /^(.*?)_/;\nfunction addExtensionToContext(gl, extensionName) {\n glEnumToString(gl, 0);\n const ext = gl.getExtension(extensionName);\n if (ext) {\n const enums = {};\n const fnSuffix = prefixRE.exec(extensionName)[1];\n const enumSuffix = '_' + fnSuffix;\n for (const key in ext) {\n const value = ext[key];\n const isFunc = typeof (value) === 'function';\n const suffix = isFunc ? fnSuffix : enumSuffix;\n let name = key;\n // examples of where this is not true are WEBGL_compressed_texture_s3tc\n // and WEBGL_compressed_texture_pvrtc\n if (key.endsWith(suffix)) {\n name = key.substring(0, key.length - suffix.length);\n }\n if (gl[name] !== undefined) {\n if (!isFunc && gl[name] !== value) {\n warn$1(name, gl[name], value, key);\n }\n } else {\n if (isFunc) {\n gl[name] = function(origFn) {\n return function() {\n return origFn.apply(ext, arguments);\n };\n }(value);\n } else {\n gl[name] = value;\n enums[name] = value;\n }\n }\n }\n // pass the modified enums to glEnumToString\n enums.constructor = {\n name: ext.constructor.name,\n };\n glEnumToString(enums, 0);\n }\n return ext;\n}\n\n/*\n * If you're wondering why the code doesn't just iterate\n * over all extensions using `gl.getExtensions` is that it's possible\n * some future extension is incompatible with this code. Rather than\n * have thing suddenly break it seems better to manually add to this\n * list.\n *\n */\nconst supportedExtensions = [\n 'ANGLE_instanced_arrays',\n 'EXT_blend_minmax',\n 'EXT_color_buffer_float',\n 'EXT_color_buffer_half_float',\n 'EXT_disjoint_timer_query',\n 'EXT_disjoint_timer_query_webgl2',\n 'EXT_frag_depth',\n 'EXT_sRGB',\n 'EXT_shader_texture_lod',\n 'EXT_texture_filter_anisotropic',\n 'OES_element_index_uint',\n 'OES_standard_derivatives',\n 'OES_texture_float',\n 'OES_texture_float_linear',\n 'OES_texture_half_float',\n 'OES_texture_half_float_linear',\n 'OES_vertex_array_object',\n 'WEBGL_color_buffer_float',\n 'WEBGL_compressed_texture_atc',\n 'WEBGL_compressed_texture_etc1',\n 'WEBGL_compressed_texture_pvrtc',\n 'WEBGL_compressed_texture_s3tc',\n 'WEBGL_compressed_texture_s3tc_srgb',\n 'WEBGL_depth_texture',\n 'WEBGL_draw_buffers',\n];\n\n/**\n * Attempts to enable all of the following extensions\n * and add their functions and constants to the\n * `WebGLRenderingContext` using their normal non-extension like names.\n *\n * ANGLE_instanced_arrays\n * EXT_blend_minmax\n * EXT_color_buffer_float\n * EXT_color_buffer_half_float\n * EXT_disjoint_timer_query\n * EXT_disjoint_timer_query_webgl2\n * EXT_frag_depth\n * EXT_sRGB\n * EXT_shader_texture_lod\n * EXT_texture_filter_anisotropic\n * OES_element_index_uint\n * OES_standard_derivatives\n * OES_texture_float\n * OES_texture_float_linear\n * OES_texture_half_float\n * OES_texture_half_float_linear\n * OES_vertex_array_object\n * WEBGL_color_buffer_float\n * WEBGL_compressed_texture_atc\n * WEBGL_compressed_texture_etc1\n * WEBGL_compressed_texture_pvrtc\n * WEBGL_compressed_texture_s3tc\n * WEBGL_compressed_texture_s3tc_srgb\n * WEBGL_depth_texture\n * WEBGL_draw_buffers\n *\n * For example if `ANGLE_instanced_arrays` exists then the functions\n * `drawArraysInstanced`, `drawElementsInstanced`, `vertexAttribDivisor`\n * and the constant `VERTEX_ATTRIB_ARRAY_DIVISOR` are added to the\n * `WebGLRenderingContext`.\n *\n * Note that if you want to know if the extension exists you should\n * probably call `gl.getExtension` for each extension. Alternatively\n * you can check for the existence of the functions or constants that\n * are expected to be added. For example\n *\n * if (gl.drawBuffers) {\n * // Either WEBGL_draw_buffers was enabled OR you're running in WebGL2\n * ....\n *\n * @param {WebGLRenderingContext} gl A WebGLRenderingContext\n * @memberOf module:twgl\n */\nfunction addExtensionsToContext(gl) {\n for (let ii = 0; ii < supportedExtensions.length; ++ii) {\n addExtensionToContext(gl, supportedExtensions[ii]);\n }\n}\n\n/**\n * Creates a webgl context.\n * @param {HTMLCanvasElement} canvas The canvas tag to get\n * context from. If one is not passed in one will be\n * created.\n * @return {WebGLRenderingContext} The created context.\n * @private\n */\nfunction create3DContext(canvas, opt_attribs) {\n const names = [\"webgl\", \"experimental-webgl\"];\n let context = null;\n for (let ii = 0; ii < names.length; ++ii) {\n context = canvas.getContext(names[ii], opt_attribs);\n if (context) {\n if (defaults.addExtensionsToContext) {\n addExtensionsToContext(context);\n }\n break;\n }\n }\n return context;\n}\n\n/**\n * Gets a WebGL1 context.\n *\n * Note: Will attempt to enable Vertex Array Objects\n * and add WebGL2 entry points. (unless you first set defaults with\n * `twgl.setDefaults({enableVertexArrayObjects: false})`;\n *\n * @param {HTMLCanvasElement} canvas a canvas element.\n * @param {WebGLContextAttributes} [opt_attribs] optional webgl context creation attributes\n * @return {WebGLRenderingContext} The created context.\n * @memberOf module:twgl\n * @deprecated\n * @private\n */\nfunction getWebGLContext(canvas, opt_attribs) {\n const gl = create3DContext(canvas, opt_attribs);\n return gl;\n}\n\n/**\n * Creates a webgl context.\n *\n * Will return a WebGL2 context if possible.\n *\n * You can check if it's WebGL2 with\n *\n * twgl.isWebGL2(gl);\n *\n * @param {HTMLCanvasElement} canvas The canvas tag to get\n * context from. If one is not passed in one will be\n * created.\n * @return {WebGLRenderingContext} The created context.\n */\nfunction createContext(canvas, opt_attribs) {\n const names = [\"webgl2\", \"webgl\", \"experimental-webgl\"];\n let context = null;\n for (let ii = 0; ii < names.length; ++ii) {\n context = canvas.getContext(names[ii], opt_attribs);\n if (context) {\n if (defaults.addExtensionsToContext) {\n addExtensionsToContext(context);\n }\n break;\n }\n }\n return context;\n}\n\n/**\n * Gets a WebGL context. Will create a WebGL2 context if possible.\n *\n * You can check if it's WebGL2 with\n *\n * function isWebGL2(gl) {\n * return gl.getParameter(gl.VERSION).indexOf(\"WebGL 2.0 \") == 0;\n * }\n *\n * Note: For a WebGL1 context will attempt to enable Vertex Array Objects\n * and add WebGL2 entry points. (unless you first set defaults with\n * `twgl.setDefaults({enableVertexArrayObjects: false})`;\n *\n * @param {HTMLCanvasElement} canvas a canvas element.\n * @param {WebGLContextAttributes} [opt_attribs] optional webgl context creation attributes\n * @return {WebGLRenderingContext} The created context.\n * @memberOf module:twgl\n */\nfunction getContext(canvas, opt_attribs) {\n const gl = createContext(canvas, opt_attribs);\n return gl;\n}\n\n/**\n * Resize a canvas to match the size it's displayed.\n * @param {HTMLCanvasElement} canvas The canvas to resize.\n * @param {number} [multiplier] So you can pass in `window.devicePixelRatio` or other scale value if you want to.\n * @return {boolean} true if the canvas was resized.\n * @memberOf module:twgl\n */\nfunction resizeCanvasToDisplaySize(canvas, multiplier) {\n multiplier = multiplier || 1;\n multiplier = Math.max(0, multiplier);\n const width = canvas.clientWidth * multiplier | 0;\n const height = canvas.clientHeight * multiplier | 0;\n if (canvas.width !== width || canvas.height !== height) {\n canvas.width = width;\n canvas.height = height;\n return true;\n }\n return false;\n}\n\nexport { 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 };\n","/**\n * Common utilities\n * @module glMatrix\n */\n// Configuration Constants\nexport var EPSILON = 0.000001;\nexport var ARRAY_TYPE = typeof Float32Array !== 'undefined' ? Float32Array : Array;\nexport var RANDOM = Math.random;\n/**\n * Sets the type of array used when creating new vectors and matrices\n *\n * @param {Float32ArrayConstructor | ArrayConstructor} type Array type, such as Float32Array or Array\n */\n\nexport function setMatrixArrayType(type) {\n ARRAY_TYPE = type;\n}\nvar degree = Math.PI / 180;\n/**\n * Convert Degree To Radian\n *\n * @param {Number} a Angle in Degrees\n */\n\nexport function toRadian(a) {\n return a * degree;\n}\n/**\n * Tests whether or not the arguments have approximately the same value, within an absolute\n * or relative tolerance of glMatrix.EPSILON (an absolute tolerance is used for values less\n * than or equal to 1.0, and a relative tolerance is used for larger values)\n *\n * @param {Number} a The first number to test.\n * @param {Number} b The second number to test.\n * @returns {Boolean} True if the numbers are approximately equal, false otherwise.\n */\n\nexport function equals(a, b) {\n return Math.abs(a - b) <= EPSILON * Math.max(1.0, Math.abs(a), Math.abs(b));\n}\nif (!Math.hypot) Math.hypot = function () {\n var y = 0,\n i = arguments.length;\n\n while (i--) {\n y += arguments[i] * arguments[i];\n }\n\n return Math.sqrt(y);\n};","import * as glMatrix from \"./common.js\";\n/**\n * 4x4 Matrix
Format: column-major, when typed out it looks like row-major
The matrices are being post multiplied.\n * @module mat4\n */\n\n/**\n * Creates a new identity mat4\n *\n * @returns {mat4} a new 4x4 matrix\n */\n\nexport function create() {\n var out = new glMatrix.ARRAY_TYPE(16);\n\n if (glMatrix.ARRAY_TYPE != Float32Array) {\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n }\n\n out[0] = 1;\n out[5] = 1;\n out[10] = 1;\n out[15] = 1;\n return out;\n}\n/**\n * Creates a new mat4 initialized with values from an existing matrix\n *\n * @param {ReadonlyMat4} a matrix to clone\n * @returns {mat4} a new 4x4 matrix\n */\n\nexport function clone(a) {\n var out = new glMatrix.ARRAY_TYPE(16);\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n out[4] = a[4];\n out[5] = a[5];\n out[6] = a[6];\n out[7] = a[7];\n out[8] = a[8];\n out[9] = a[9];\n out[10] = a[10];\n out[11] = a[11];\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n return out;\n}\n/**\n * Copy the values from one mat4 to another\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the source matrix\n * @returns {mat4} out\n */\n\nexport function copy(out, a) {\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n out[4] = a[4];\n out[5] = a[5];\n out[6] = a[6];\n out[7] = a[7];\n out[8] = a[8];\n out[9] = a[9];\n out[10] = a[10];\n out[11] = a[11];\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n return out;\n}\n/**\n * Create a new mat4 with the given values\n *\n * @param {Number} m00 Component in column 0, row 0 position (index 0)\n * @param {Number} m01 Component in column 0, row 1 position (index 1)\n * @param {Number} m02 Component in column 0, row 2 position (index 2)\n * @param {Number} m03 Component in column 0, row 3 position (index 3)\n * @param {Number} m10 Component in column 1, row 0 position (index 4)\n * @param {Number} m11 Component in column 1, row 1 position (index 5)\n * @param {Number} m12 Component in column 1, row 2 position (index 6)\n * @param {Number} m13 Component in column 1, row 3 position (index 7)\n * @param {Number} m20 Component in column 2, row 0 position (index 8)\n * @param {Number} m21 Component in column 2, row 1 position (index 9)\n * @param {Number} m22 Component in column 2, row 2 position (index 10)\n * @param {Number} m23 Component in column 2, row 3 position (index 11)\n * @param {Number} m30 Component in column 3, row 0 position (index 12)\n * @param {Number} m31 Component in column 3, row 1 position (index 13)\n * @param {Number} m32 Component in column 3, row 2 position (index 14)\n * @param {Number} m33 Component in column 3, row 3 position (index 15)\n * @returns {mat4} A new mat4\n */\n\nexport function fromValues(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {\n var out = new glMatrix.ARRAY_TYPE(16);\n out[0] = m00;\n out[1] = m01;\n out[2] = m02;\n out[3] = m03;\n out[4] = m10;\n out[5] = m11;\n out[6] = m12;\n out[7] = m13;\n out[8] = m20;\n out[9] = m21;\n out[10] = m22;\n out[11] = m23;\n out[12] = m30;\n out[13] = m31;\n out[14] = m32;\n out[15] = m33;\n return out;\n}\n/**\n * Set the components of a mat4 to the given values\n *\n * @param {mat4} out the receiving matrix\n * @param {Number} m00 Component in column 0, row 0 position (index 0)\n * @param {Number} m01 Component in column 0, row 1 position (index 1)\n * @param {Number} m02 Component in column 0, row 2 position (index 2)\n * @param {Number} m03 Component in column 0, row 3 position (index 3)\n * @param {Number} m10 Component in column 1, row 0 position (index 4)\n * @param {Number} m11 Component in column 1, row 1 position (index 5)\n * @param {Number} m12 Component in column 1, row 2 position (index 6)\n * @param {Number} m13 Component in column 1, row 3 position (index 7)\n * @param {Number} m20 Component in column 2, row 0 position (index 8)\n * @param {Number} m21 Component in column 2, row 1 position (index 9)\n * @param {Number} m22 Component in column 2, row 2 position (index 10)\n * @param {Number} m23 Component in column 2, row 3 position (index 11)\n * @param {Number} m30 Component in column 3, row 0 position (index 12)\n * @param {Number} m31 Component in column 3, row 1 position (index 13)\n * @param {Number} m32 Component in column 3, row 2 position (index 14)\n * @param {Number} m33 Component in column 3, row 3 position (index 15)\n * @returns {mat4} out\n */\n\nexport function set(out, m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {\n out[0] = m00;\n out[1] = m01;\n out[2] = m02;\n out[3] = m03;\n out[4] = m10;\n out[5] = m11;\n out[6] = m12;\n out[7] = m13;\n out[8] = m20;\n out[9] = m21;\n out[10] = m22;\n out[11] = m23;\n out[12] = m30;\n out[13] = m31;\n out[14] = m32;\n out[15] = m33;\n return out;\n}\n/**\n * Set a mat4 to the identity matrix\n *\n * @param {mat4} out the receiving matrix\n * @returns {mat4} out\n */\n\nexport function identity(out) {\n out[0] = 1;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = 1;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = 1;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n/**\n * Transpose the values of a mat4\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the source matrix\n * @returns {mat4} out\n */\n\nexport function transpose(out, a) {\n // If we are transposing ourselves we can skip a few steps but have to cache some values\n if (out === a) {\n var a01 = a[1],\n a02 = a[2],\n a03 = a[3];\n var a12 = a[6],\n a13 = a[7];\n var a23 = a[11];\n out[1] = a[4];\n out[2] = a[8];\n out[3] = a[12];\n out[4] = a01;\n out[6] = a[9];\n out[7] = a[13];\n out[8] = a02;\n out[9] = a12;\n out[11] = a[14];\n out[12] = a03;\n out[13] = a13;\n out[14] = a23;\n } else {\n out[0] = a[0];\n out[1] = a[4];\n out[2] = a[8];\n out[3] = a[12];\n out[4] = a[1];\n out[5] = a[5];\n out[6] = a[9];\n out[7] = a[13];\n out[8] = a[2];\n out[9] = a[6];\n out[10] = a[10];\n out[11] = a[14];\n out[12] = a[3];\n out[13] = a[7];\n out[14] = a[11];\n out[15] = a[15];\n }\n\n return out;\n}\n/**\n * Inverts a mat4\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the source matrix\n * @returns {mat4} out\n */\n\nexport function invert(out, a) {\n var a00 = a[0],\n a01 = a[1],\n a02 = a[2],\n a03 = a[3];\n var a10 = a[4],\n a11 = a[5],\n a12 = a[6],\n a13 = a[7];\n var a20 = a[8],\n a21 = a[9],\n a22 = a[10],\n a23 = a[11];\n var a30 = a[12],\n a31 = a[13],\n a32 = a[14],\n a33 = a[15];\n var b00 = a00 * a11 - a01 * a10;\n var b01 = a00 * a12 - a02 * a10;\n var b02 = a00 * a13 - a03 * a10;\n var b03 = a01 * a12 - a02 * a11;\n var b04 = a01 * a13 - a03 * a11;\n var b05 = a02 * a13 - a03 * a12;\n var b06 = a20 * a31 - a21 * a30;\n var b07 = a20 * a32 - a22 * a30;\n var b08 = a20 * a33 - a23 * a30;\n var b09 = a21 * a32 - a22 * a31;\n var b10 = a21 * a33 - a23 * a31;\n var b11 = a22 * a33 - a23 * a32; // Calculate the determinant\n\n var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;\n\n if (!det) {\n return null;\n }\n\n det = 1.0 / det;\n out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;\n out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;\n out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;\n out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;\n out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;\n out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;\n out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;\n out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;\n out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;\n out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;\n out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;\n out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;\n out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;\n out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;\n out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;\n out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;\n return out;\n}\n/**\n * Calculates the adjugate of a mat4\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the source matrix\n * @returns {mat4} out\n */\n\nexport function adjoint(out, a) {\n var a00 = a[0],\n a01 = a[1],\n a02 = a[2],\n a03 = a[3];\n var a10 = a[4],\n a11 = a[5],\n a12 = a[6],\n a13 = a[7];\n var a20 = a[8],\n a21 = a[9],\n a22 = a[10],\n a23 = a[11];\n var a30 = a[12],\n a31 = a[13],\n a32 = a[14],\n a33 = a[15];\n out[0] = a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22);\n out[1] = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22));\n out[2] = a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12);\n out[3] = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12));\n out[4] = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22));\n out[5] = a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22);\n out[6] = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12));\n out[7] = a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12);\n out[8] = a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21);\n out[9] = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21));\n out[10] = a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11);\n out[11] = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11));\n out[12] = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21));\n out[13] = a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21);\n out[14] = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11));\n out[15] = a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11);\n return out;\n}\n/**\n * Calculates the determinant of a mat4\n *\n * @param {ReadonlyMat4} a the source matrix\n * @returns {Number} determinant of a\n */\n\nexport function determinant(a) {\n var a00 = a[0],\n a01 = a[1],\n a02 = a[2],\n a03 = a[3];\n var a10 = a[4],\n a11 = a[5],\n a12 = a[6],\n a13 = a[7];\n var a20 = a[8],\n a21 = a[9],\n a22 = a[10],\n a23 = a[11];\n var a30 = a[12],\n a31 = a[13],\n a32 = a[14],\n a33 = a[15];\n var b00 = a00 * a11 - a01 * a10;\n var b01 = a00 * a12 - a02 * a10;\n var b02 = a00 * a13 - a03 * a10;\n var b03 = a01 * a12 - a02 * a11;\n var b04 = a01 * a13 - a03 * a11;\n var b05 = a02 * a13 - a03 * a12;\n var b06 = a20 * a31 - a21 * a30;\n var b07 = a20 * a32 - a22 * a30;\n var b08 = a20 * a33 - a23 * a30;\n var b09 = a21 * a32 - a22 * a31;\n var b10 = a21 * a33 - a23 * a31;\n var b11 = a22 * a33 - a23 * a32; // Calculate the determinant\n\n return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;\n}\n/**\n * Multiplies two mat4s\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the first operand\n * @param {ReadonlyMat4} b the second operand\n * @returns {mat4} out\n */\n\nexport function multiply(out, a, b) {\n var a00 = a[0],\n a01 = a[1],\n a02 = a[2],\n a03 = a[3];\n var a10 = a[4],\n a11 = a[5],\n a12 = a[6],\n a13 = a[7];\n var a20 = a[8],\n a21 = a[9],\n a22 = a[10],\n a23 = a[11];\n var a30 = a[12],\n a31 = a[13],\n a32 = a[14],\n a33 = a[15]; // Cache only the current line of the second matrix\n\n var b0 = b[0],\n b1 = b[1],\n b2 = b[2],\n b3 = b[3];\n out[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n out[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n out[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n out[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n b0 = b[4];\n b1 = b[5];\n b2 = b[6];\n b3 = b[7];\n out[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n out[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n out[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n out[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n b0 = b[8];\n b1 = b[9];\n b2 = b[10];\n b3 = b[11];\n out[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n out[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n out[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n out[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n b0 = b[12];\n b1 = b[13];\n b2 = b[14];\n b3 = b[15];\n out[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n out[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n out[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n out[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n return out;\n}\n/**\n * Translate a mat4 by the given vector\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to translate\n * @param {ReadonlyVec3} v vector to translate by\n * @returns {mat4} out\n */\n\nexport function translate(out, a, v) {\n var x = v[0],\n y = v[1],\n z = v[2];\n var a00, a01, a02, a03;\n var a10, a11, a12, a13;\n var a20, a21, a22, a23;\n\n if (a === out) {\n out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];\n out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];\n out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];\n out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];\n } else {\n a00 = a[0];\n a01 = a[1];\n a02 = a[2];\n a03 = a[3];\n a10 = a[4];\n a11 = a[5];\n a12 = a[6];\n a13 = a[7];\n a20 = a[8];\n a21 = a[9];\n a22 = a[10];\n a23 = a[11];\n out[0] = a00;\n out[1] = a01;\n out[2] = a02;\n out[3] = a03;\n out[4] = a10;\n out[5] = a11;\n out[6] = a12;\n out[7] = a13;\n out[8] = a20;\n out[9] = a21;\n out[10] = a22;\n out[11] = a23;\n out[12] = a00 * x + a10 * y + a20 * z + a[12];\n out[13] = a01 * x + a11 * y + a21 * z + a[13];\n out[14] = a02 * x + a12 * y + a22 * z + a[14];\n out[15] = a03 * x + a13 * y + a23 * z + a[15];\n }\n\n return out;\n}\n/**\n * Scales the mat4 by the dimensions in the given vec3 not using vectorization\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to scale\n * @param {ReadonlyVec3} v the vec3 to scale the matrix by\n * @returns {mat4} out\n **/\n\nexport function scale(out, a, v) {\n var x = v[0],\n y = v[1],\n z = v[2];\n out[0] = a[0] * x;\n out[1] = a[1] * x;\n out[2] = a[2] * x;\n out[3] = a[3] * x;\n out[4] = a[4] * y;\n out[5] = a[5] * y;\n out[6] = a[6] * y;\n out[7] = a[7] * y;\n out[8] = a[8] * z;\n out[9] = a[9] * z;\n out[10] = a[10] * z;\n out[11] = a[11] * z;\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n return out;\n}\n/**\n * Rotates a mat4 by the given angle around the given axis\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to rotate\n * @param {Number} rad the angle to rotate the matrix by\n * @param {ReadonlyVec3} axis the axis to rotate around\n * @returns {mat4} out\n */\n\nexport function rotate(out, a, rad, axis) {\n var x = axis[0],\n y = axis[1],\n z = axis[2];\n var len = Math.hypot(x, y, z);\n var s, c, t;\n var a00, a01, a02, a03;\n var a10, a11, a12, a13;\n var a20, a21, a22, a23;\n var b00, b01, b02;\n var b10, b11, b12;\n var b20, b21, b22;\n\n if (len < glMatrix.EPSILON) {\n return null;\n }\n\n len = 1 / len;\n x *= len;\n y *= len;\n z *= len;\n s = Math.sin(rad);\n c = Math.cos(rad);\n t = 1 - c;\n a00 = a[0];\n a01 = a[1];\n a02 = a[2];\n a03 = a[3];\n a10 = a[4];\n a11 = a[5];\n a12 = a[6];\n a13 = a[7];\n a20 = a[8];\n a21 = a[9];\n a22 = a[10];\n a23 = a[11]; // Construct the elements of the rotation matrix\n\n b00 = x * x * t + c;\n b01 = y * x * t + z * s;\n b02 = z * x * t - y * s;\n b10 = x * y * t - z * s;\n b11 = y * y * t + c;\n b12 = z * y * t + x * s;\n b20 = x * z * t + y * s;\n b21 = y * z * t - x * s;\n b22 = z * z * t + c; // Perform rotation-specific matrix multiplication\n\n out[0] = a00 * b00 + a10 * b01 + a20 * b02;\n out[1] = a01 * b00 + a11 * b01 + a21 * b02;\n out[2] = a02 * b00 + a12 * b01 + a22 * b02;\n out[3] = a03 * b00 + a13 * b01 + a23 * b02;\n out[4] = a00 * b10 + a10 * b11 + a20 * b12;\n out[5] = a01 * b10 + a11 * b11 + a21 * b12;\n out[6] = a02 * b10 + a12 * b11 + a22 * b12;\n out[7] = a03 * b10 + a13 * b11 + a23 * b12;\n out[8] = a00 * b20 + a10 * b21 + a20 * b22;\n out[9] = a01 * b20 + a11 * b21 + a21 * b22;\n out[10] = a02 * b20 + a12 * b21 + a22 * b22;\n out[11] = a03 * b20 + a13 * b21 + a23 * b22;\n\n if (a !== out) {\n // If the source and destination differ, copy the unchanged last row\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n }\n\n return out;\n}\n/**\n * Rotates a matrix by the given angle around the X axis\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to rotate\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat4} out\n */\n\nexport function rotateX(out, a, rad) {\n var s = Math.sin(rad);\n var c = Math.cos(rad);\n var a10 = a[4];\n var a11 = a[5];\n var a12 = a[6];\n var a13 = a[7];\n var a20 = a[8];\n var a21 = a[9];\n var a22 = a[10];\n var a23 = a[11];\n\n if (a !== out) {\n // If the source and destination differ, copy the unchanged rows\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n } // Perform axis-specific matrix multiplication\n\n\n out[4] = a10 * c + a20 * s;\n out[5] = a11 * c + a21 * s;\n out[6] = a12 * c + a22 * s;\n out[7] = a13 * c + a23 * s;\n out[8] = a20 * c - a10 * s;\n out[9] = a21 * c - a11 * s;\n out[10] = a22 * c - a12 * s;\n out[11] = a23 * c - a13 * s;\n return out;\n}\n/**\n * Rotates a matrix by the given angle around the Y axis\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to rotate\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat4} out\n */\n\nexport function rotateY(out, a, rad) {\n var s = Math.sin(rad);\n var c = Math.cos(rad);\n var a00 = a[0];\n var a01 = a[1];\n var a02 = a[2];\n var a03 = a[3];\n var a20 = a[8];\n var a21 = a[9];\n var a22 = a[10];\n var a23 = a[11];\n\n if (a !== out) {\n // If the source and destination differ, copy the unchanged rows\n out[4] = a[4];\n out[5] = a[5];\n out[6] = a[6];\n out[7] = a[7];\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n } // Perform axis-specific matrix multiplication\n\n\n out[0] = a00 * c - a20 * s;\n out[1] = a01 * c - a21 * s;\n out[2] = a02 * c - a22 * s;\n out[3] = a03 * c - a23 * s;\n out[8] = a00 * s + a20 * c;\n out[9] = a01 * s + a21 * c;\n out[10] = a02 * s + a22 * c;\n out[11] = a03 * s + a23 * c;\n return out;\n}\n/**\n * Rotates a matrix by the given angle around the Z axis\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to rotate\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat4} out\n */\n\nexport function rotateZ(out, a, rad) {\n var s = Math.sin(rad);\n var c = Math.cos(rad);\n var a00 = a[0];\n var a01 = a[1];\n var a02 = a[2];\n var a03 = a[3];\n var a10 = a[4];\n var a11 = a[5];\n var a12 = a[6];\n var a13 = a[7];\n\n if (a !== out) {\n // If the source and destination differ, copy the unchanged last row\n out[8] = a[8];\n out[9] = a[9];\n out[10] = a[10];\n out[11] = a[11];\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n } // Perform axis-specific matrix multiplication\n\n\n out[0] = a00 * c + a10 * s;\n out[1] = a01 * c + a11 * s;\n out[2] = a02 * c + a12 * s;\n out[3] = a03 * c + a13 * s;\n out[4] = a10 * c - a00 * s;\n out[5] = a11 * c - a01 * s;\n out[6] = a12 * c - a02 * s;\n out[7] = a13 * c - a03 * s;\n return out;\n}\n/**\n * Creates a matrix from a vector translation\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.translate(dest, dest, vec);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {ReadonlyVec3} v Translation vector\n * @returns {mat4} out\n */\n\nexport function fromTranslation(out, v) {\n out[0] = 1;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = 1;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = 1;\n out[11] = 0;\n out[12] = v[0];\n out[13] = v[1];\n out[14] = v[2];\n out[15] = 1;\n return out;\n}\n/**\n * Creates a matrix from a vector scaling\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.scale(dest, dest, vec);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {ReadonlyVec3} v Scaling vector\n * @returns {mat4} out\n */\n\nexport function fromScaling(out, v) {\n out[0] = v[0];\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = v[1];\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = v[2];\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n/**\n * Creates a matrix from a given angle around a given axis\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.rotate(dest, dest, rad, axis);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {Number} rad the angle to rotate the matrix by\n * @param {ReadonlyVec3} axis the axis to rotate around\n * @returns {mat4} out\n */\n\nexport function fromRotation(out, rad, axis) {\n var x = axis[0],\n y = axis[1],\n z = axis[2];\n var len = Math.hypot(x, y, z);\n var s, c, t;\n\n if (len < glMatrix.EPSILON) {\n return null;\n }\n\n len = 1 / len;\n x *= len;\n y *= len;\n z *= len;\n s = Math.sin(rad);\n c = Math.cos(rad);\n t = 1 - c; // Perform rotation-specific matrix multiplication\n\n out[0] = x * x * t + c;\n out[1] = y * x * t + z * s;\n out[2] = z * x * t - y * s;\n out[3] = 0;\n out[4] = x * y * t - z * s;\n out[5] = y * y * t + c;\n out[6] = z * y * t + x * s;\n out[7] = 0;\n out[8] = x * z * t + y * s;\n out[9] = y * z * t - x * s;\n out[10] = z * z * t + c;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n/**\n * Creates a matrix from the given angle around the X axis\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.rotateX(dest, dest, rad);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat4} out\n */\n\nexport function fromXRotation(out, rad) {\n var s = Math.sin(rad);\n var c = Math.cos(rad); // Perform axis-specific matrix multiplication\n\n out[0] = 1;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = c;\n out[6] = s;\n out[7] = 0;\n out[8] = 0;\n out[9] = -s;\n out[10] = c;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n/**\n * Creates a matrix from the given angle around the Y axis\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.rotateY(dest, dest, rad);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat4} out\n */\n\nexport function fromYRotation(out, rad) {\n var s = Math.sin(rad);\n var c = Math.cos(rad); // Perform axis-specific matrix multiplication\n\n out[0] = c;\n out[1] = 0;\n out[2] = -s;\n out[3] = 0;\n out[4] = 0;\n out[5] = 1;\n out[6] = 0;\n out[7] = 0;\n out[8] = s;\n out[9] = 0;\n out[10] = c;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n/**\n * Creates a matrix from the given angle around the Z axis\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.rotateZ(dest, dest, rad);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {Number} rad the angle to rotate the matrix by\n * @returns {mat4} out\n */\n\nexport function fromZRotation(out, rad) {\n var s = Math.sin(rad);\n var c = Math.cos(rad); // Perform axis-specific matrix multiplication\n\n out[0] = c;\n out[1] = s;\n out[2] = 0;\n out[3] = 0;\n out[4] = -s;\n out[5] = c;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = 1;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n/**\n * Creates a matrix from a quaternion rotation and vector translation\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.translate(dest, vec);\n * let quatMat = mat4.create();\n * quat4.toMat4(quat, quatMat);\n * mat4.multiply(dest, quatMat);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {quat4} q Rotation quaternion\n * @param {ReadonlyVec3} v Translation vector\n * @returns {mat4} out\n */\n\nexport function fromRotationTranslation(out, q, v) {\n // Quaternion math\n var x = q[0],\n y = q[1],\n z = q[2],\n w = q[3];\n var x2 = x + x;\n var y2 = y + y;\n var z2 = z + z;\n var xx = x * x2;\n var xy = x * y2;\n var xz = x * z2;\n var yy = y * y2;\n var yz = y * z2;\n var zz = z * z2;\n var wx = w * x2;\n var wy = w * y2;\n var wz = w * z2;\n out[0] = 1 - (yy + zz);\n out[1] = xy + wz;\n out[2] = xz - wy;\n out[3] = 0;\n out[4] = xy - wz;\n out[5] = 1 - (xx + zz);\n out[6] = yz + wx;\n out[7] = 0;\n out[8] = xz + wy;\n out[9] = yz - wx;\n out[10] = 1 - (xx + yy);\n out[11] = 0;\n out[12] = v[0];\n out[13] = v[1];\n out[14] = v[2];\n out[15] = 1;\n return out;\n}\n/**\n * Creates a new mat4 from a dual quat.\n *\n * @param {mat4} out Matrix\n * @param {ReadonlyQuat2} a Dual Quaternion\n * @returns {mat4} mat4 receiving operation result\n */\n\nexport function fromQuat2(out, a) {\n var translation = new glMatrix.ARRAY_TYPE(3);\n var bx = -a[0],\n by = -a[1],\n bz = -a[2],\n bw = a[3],\n ax = a[4],\n ay = a[5],\n az = a[6],\n aw = a[7];\n var magnitude = bx * bx + by * by + bz * bz + bw * bw; //Only scale if it makes sense\n\n if (magnitude > 0) {\n translation[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2 / magnitude;\n translation[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2 / magnitude;\n translation[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2 / magnitude;\n } else {\n translation[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2;\n translation[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2;\n translation[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2;\n }\n\n fromRotationTranslation(out, a, translation);\n return out;\n}\n/**\n * Returns the translation vector component of a transformation\n * matrix. If a matrix is built with fromRotationTranslation,\n * the returned vector will be the same as the translation vector\n * originally supplied.\n * @param {vec3} out Vector to receive translation component\n * @param {ReadonlyMat4} mat Matrix to be decomposed (input)\n * @return {vec3} out\n */\n\nexport function getTranslation(out, mat) {\n out[0] = mat[12];\n out[1] = mat[13];\n out[2] = mat[14];\n return out;\n}\n/**\n * Returns the scaling factor component of a transformation\n * matrix. If a matrix is built with fromRotationTranslationScale\n * with a normalized Quaternion paramter, the returned vector will be\n * the same as the scaling vector\n * originally supplied.\n * @param {vec3} out Vector to receive scaling factor component\n * @param {ReadonlyMat4} mat Matrix to be decomposed (input)\n * @return {vec3} out\n */\n\nexport function getScaling(out, mat) {\n var m11 = mat[0];\n var m12 = mat[1];\n var m13 = mat[2];\n var m21 = mat[4];\n var m22 = mat[5];\n var m23 = mat[6];\n var m31 = mat[8];\n var m32 = mat[9];\n var m33 = mat[10];\n out[0] = Math.hypot(m11, m12, m13);\n out[1] = Math.hypot(m21, m22, m23);\n out[2] = Math.hypot(m31, m32, m33);\n return out;\n}\n/**\n * Returns a quaternion representing the rotational component\n * of a transformation matrix. If a matrix is built with\n * fromRotationTranslation, the returned quaternion will be the\n * same as the quaternion originally supplied.\n * @param {quat} out Quaternion to receive the rotation component\n * @param {ReadonlyMat4} mat Matrix to be decomposed (input)\n * @return {quat} out\n */\n\nexport function getRotation(out, mat) {\n var scaling = new glMatrix.ARRAY_TYPE(3);\n getScaling(scaling, mat);\n var is1 = 1 / scaling[0];\n var is2 = 1 / scaling[1];\n var is3 = 1 / scaling[2];\n var sm11 = mat[0] * is1;\n var sm12 = mat[1] * is2;\n var sm13 = mat[2] * is3;\n var sm21 = mat[4] * is1;\n var sm22 = mat[5] * is2;\n var sm23 = mat[6] * is3;\n var sm31 = mat[8] * is1;\n var sm32 = mat[9] * is2;\n var sm33 = mat[10] * is3;\n var trace = sm11 + sm22 + sm33;\n var S = 0;\n\n if (trace > 0) {\n S = Math.sqrt(trace + 1.0) * 2;\n out[3] = 0.25 * S;\n out[0] = (sm23 - sm32) / S;\n out[1] = (sm31 - sm13) / S;\n out[2] = (sm12 - sm21) / S;\n } else if (sm11 > sm22 && sm11 > sm33) {\n S = Math.sqrt(1.0 + sm11 - sm22 - sm33) * 2;\n out[3] = (sm23 - sm32) / S;\n out[0] = 0.25 * S;\n out[1] = (sm12 + sm21) / S;\n out[2] = (sm31 + sm13) / S;\n } else if (sm22 > sm33) {\n S = Math.sqrt(1.0 + sm22 - sm11 - sm33) * 2;\n out[3] = (sm31 - sm13) / S;\n out[0] = (sm12 + sm21) / S;\n out[1] = 0.25 * S;\n out[2] = (sm23 + sm32) / S;\n } else {\n S = Math.sqrt(1.0 + sm33 - sm11 - sm22) * 2;\n out[3] = (sm12 - sm21) / S;\n out[0] = (sm31 + sm13) / S;\n out[1] = (sm23 + sm32) / S;\n out[2] = 0.25 * S;\n }\n\n return out;\n}\n/**\n * Creates a matrix from a quaternion rotation, vector translation and vector scale\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.translate(dest, vec);\n * let quatMat = mat4.create();\n * quat4.toMat4(quat, quatMat);\n * mat4.multiply(dest, quatMat);\n * mat4.scale(dest, scale)\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {quat4} q Rotation quaternion\n * @param {ReadonlyVec3} v Translation vector\n * @param {ReadonlyVec3} s Scaling vector\n * @returns {mat4} out\n */\n\nexport function fromRotationTranslationScale(out, q, v, s) {\n // Quaternion math\n var x = q[0],\n y = q[1],\n z = q[2],\n w = q[3];\n var x2 = x + x;\n var y2 = y + y;\n var z2 = z + z;\n var xx = x * x2;\n var xy = x * y2;\n var xz = x * z2;\n var yy = y * y2;\n var yz = y * z2;\n var zz = z * z2;\n var wx = w * x2;\n var wy = w * y2;\n var wz = w * z2;\n var sx = s[0];\n var sy = s[1];\n var sz = s[2];\n out[0] = (1 - (yy + zz)) * sx;\n out[1] = (xy + wz) * sx;\n out[2] = (xz - wy) * sx;\n out[3] = 0;\n out[4] = (xy - wz) * sy;\n out[5] = (1 - (xx + zz)) * sy;\n out[6] = (yz + wx) * sy;\n out[7] = 0;\n out[8] = (xz + wy) * sz;\n out[9] = (yz - wx) * sz;\n out[10] = (1 - (xx + yy)) * sz;\n out[11] = 0;\n out[12] = v[0];\n out[13] = v[1];\n out[14] = v[2];\n out[15] = 1;\n return out;\n}\n/**\n * Creates a matrix from a quaternion rotation, vector translation and vector scale, rotating and scaling around the given origin\n * This is equivalent to (but much faster than):\n *\n * mat4.identity(dest);\n * mat4.translate(dest, vec);\n * mat4.translate(dest, origin);\n * let quatMat = mat4.create();\n * quat4.toMat4(quat, quatMat);\n * mat4.multiply(dest, quatMat);\n * mat4.scale(dest, scale)\n * mat4.translate(dest, negativeOrigin);\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {quat4} q Rotation quaternion\n * @param {ReadonlyVec3} v Translation vector\n * @param {ReadonlyVec3} s Scaling vector\n * @param {ReadonlyVec3} o The origin vector around which to scale and rotate\n * @returns {mat4} out\n */\n\nexport function fromRotationTranslationScaleOrigin(out, q, v, s, o) {\n // Quaternion math\n var x = q[0],\n y = q[1],\n z = q[2],\n w = q[3];\n var x2 = x + x;\n var y2 = y + y;\n var z2 = z + z;\n var xx = x * x2;\n var xy = x * y2;\n var xz = x * z2;\n var yy = y * y2;\n var yz = y * z2;\n var zz = z * z2;\n var wx = w * x2;\n var wy = w * y2;\n var wz = w * z2;\n var sx = s[0];\n var sy = s[1];\n var sz = s[2];\n var ox = o[0];\n var oy = o[1];\n var oz = o[2];\n var out0 = (1 - (yy + zz)) * sx;\n var out1 = (xy + wz) * sx;\n var out2 = (xz - wy) * sx;\n var out4 = (xy - wz) * sy;\n var out5 = (1 - (xx + zz)) * sy;\n var out6 = (yz + wx) * sy;\n var out8 = (xz + wy) * sz;\n var out9 = (yz - wx) * sz;\n var out10 = (1 - (xx + yy)) * sz;\n out[0] = out0;\n out[1] = out1;\n out[2] = out2;\n out[3] = 0;\n out[4] = out4;\n out[5] = out5;\n out[6] = out6;\n out[7] = 0;\n out[8] = out8;\n out[9] = out9;\n out[10] = out10;\n out[11] = 0;\n out[12] = v[0] + ox - (out0 * ox + out4 * oy + out8 * oz);\n out[13] = v[1] + oy - (out1 * ox + out5 * oy + out9 * oz);\n out[14] = v[2] + oz - (out2 * ox + out6 * oy + out10 * oz);\n out[15] = 1;\n return out;\n}\n/**\n * Calculates a 4x4 matrix from the given quaternion\n *\n * @param {mat4} out mat4 receiving operation result\n * @param {ReadonlyQuat} q Quaternion to create matrix from\n *\n * @returns {mat4} out\n */\n\nexport function fromQuat(out, q) {\n var x = q[0],\n y = q[1],\n z = q[2],\n w = q[3];\n var x2 = x + x;\n var y2 = y + y;\n var z2 = z + z;\n var xx = x * x2;\n var yx = y * x2;\n var yy = y * y2;\n var zx = z * x2;\n var zy = z * y2;\n var zz = z * z2;\n var wx = w * x2;\n var wy = w * y2;\n var wz = w * z2;\n out[0] = 1 - yy - zz;\n out[1] = yx + wz;\n out[2] = zx - wy;\n out[3] = 0;\n out[4] = yx - wz;\n out[5] = 1 - xx - zz;\n out[6] = zy + wx;\n out[7] = 0;\n out[8] = zx + wy;\n out[9] = zy - wx;\n out[10] = 1 - xx - yy;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n}\n/**\n * Generates a frustum matrix with the given bounds\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {Number} left Left bound of the frustum\n * @param {Number} right Right bound of the frustum\n * @param {Number} bottom Bottom bound of the frustum\n * @param {Number} top Top bound of the frustum\n * @param {Number} near Near bound of the frustum\n * @param {Number} far Far bound of the frustum\n * @returns {mat4} out\n */\n\nexport function frustum(out, left, right, bottom, top, near, far) {\n var rl = 1 / (right - left);\n var tb = 1 / (top - bottom);\n var nf = 1 / (near - far);\n out[0] = near * 2 * rl;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = near * 2 * tb;\n out[6] = 0;\n out[7] = 0;\n out[8] = (right + left) * rl;\n out[9] = (top + bottom) * tb;\n out[10] = (far + near) * nf;\n out[11] = -1;\n out[12] = 0;\n out[13] = 0;\n out[14] = far * near * 2 * nf;\n out[15] = 0;\n return out;\n}\n/**\n * Generates a perspective projection matrix with the given bounds.\n * The near/far clip planes correspond to a normalized device coordinate Z range of [-1, 1],\n * which matches WebGL/OpenGL's clip volume.\n * Passing null/undefined/no value for far will generate infinite projection matrix.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {number} fovy Vertical field of view in radians\n * @param {number} aspect Aspect ratio. typically viewport width/height\n * @param {number} near Near bound of the frustum\n * @param {number} far Far bound of the frustum, can be null or Infinity\n * @returns {mat4} out\n */\n\nexport function perspectiveNO(out, fovy, aspect, near, far) {\n var f = 1.0 / Math.tan(fovy / 2),\n nf;\n out[0] = f / aspect;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = f;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[11] = -1;\n out[12] = 0;\n out[13] = 0;\n out[15] = 0;\n\n if (far != null && far !== Infinity) {\n nf = 1 / (near - far);\n out[10] = (far + near) * nf;\n out[14] = 2 * far * near * nf;\n } else {\n out[10] = -1;\n out[14] = -2 * near;\n }\n\n return out;\n}\n/**\n * Alias for {@link mat4.perspectiveNO}\n * @function\n */\n\nexport var perspective = perspectiveNO;\n/**\n * Generates a perspective projection matrix suitable for WebGPU with the given bounds.\n * The near/far clip planes correspond to a normalized device coordinate Z range of [0, 1],\n * which matches WebGPU/Vulkan/DirectX/Metal's clip volume.\n * Passing null/undefined/no value for far will generate infinite projection matrix.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {number} fovy Vertical field of view in radians\n * @param {number} aspect Aspect ratio. typically viewport width/height\n * @param {number} near Near bound of the frustum\n * @param {number} far Far bound of the frustum, can be null or Infinity\n * @returns {mat4} out\n */\n\nexport function perspectiveZO(out, fovy, aspect, near, far) {\n var f = 1.0 / Math.tan(fovy / 2),\n nf;\n out[0] = f / aspect;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = f;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[11] = -1;\n out[12] = 0;\n out[13] = 0;\n out[15] = 0;\n\n if (far != null && far !== Infinity) {\n nf = 1 / (near - far);\n out[10] = far * nf;\n out[14] = far * near * nf;\n } else {\n out[10] = -1;\n out[14] = -near;\n }\n\n return out;\n}\n/**\n * Generates a perspective projection matrix with the given field of view.\n * This is primarily useful for generating projection matrices to be used\n * with the still experiemental WebVR API.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {Object} fov Object containing the following values: upDegrees, downDegrees, leftDegrees, rightDegrees\n * @param {number} near Near bound of the frustum\n * @param {number} far Far bound of the frustum\n * @returns {mat4} out\n */\n\nexport function perspectiveFromFieldOfView(out, fov, near, far) {\n var upTan = Math.tan(fov.upDegrees * Math.PI / 180.0);\n var downTan = Math.tan(fov.downDegrees * Math.PI / 180.0);\n var leftTan = Math.tan(fov.leftDegrees * Math.PI / 180.0);\n var rightTan = Math.tan(fov.rightDegrees * Math.PI / 180.0);\n var xScale = 2.0 / (leftTan + rightTan);\n var yScale = 2.0 / (upTan + downTan);\n out[0] = xScale;\n out[1] = 0.0;\n out[2] = 0.0;\n out[3] = 0.0;\n out[4] = 0.0;\n out[5] = yScale;\n out[6] = 0.0;\n out[7] = 0.0;\n out[8] = -((leftTan - rightTan) * xScale * 0.5);\n out[9] = (upTan - downTan) * yScale * 0.5;\n out[10] = far / (near - far);\n out[11] = -1.0;\n out[12] = 0.0;\n out[13] = 0.0;\n out[14] = far * near / (near - far);\n out[15] = 0.0;\n return out;\n}\n/**\n * Generates a orthogonal projection matrix with the given bounds.\n * The near/far clip planes correspond to a normalized device coordinate Z range of [-1, 1],\n * which matches WebGL/OpenGL's clip volume.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {number} left Left bound of the frustum\n * @param {number} right Right bound of the frustum\n * @param {number} bottom Bottom bound of the frustum\n * @param {number} top Top bound of the frustum\n * @param {number} near Near bound of the frustum\n * @param {number} far Far bound of the frustum\n * @returns {mat4} out\n */\n\nexport function orthoNO(out, left, right, bottom, top, near, far) {\n var lr = 1 / (left - right);\n var bt = 1 / (bottom - top);\n var nf = 1 / (near - far);\n out[0] = -2 * lr;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = -2 * bt;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = 2 * nf;\n out[11] = 0;\n out[12] = (left + right) * lr;\n out[13] = (top + bottom) * bt;\n out[14] = (far + near) * nf;\n out[15] = 1;\n return out;\n}\n/**\n * Alias for {@link mat4.orthoNO}\n * @function\n */\n\nexport var ortho = orthoNO;\n/**\n * Generates a orthogonal projection matrix with the given bounds.\n * The near/far clip planes correspond to a normalized device coordinate Z range of [0, 1],\n * which matches WebGPU/Vulkan/DirectX/Metal's clip volume.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {number} left Left bound of the frustum\n * @param {number} right Right bound of the frustum\n * @param {number} bottom Bottom bound of the frustum\n * @param {number} top Top bound of the frustum\n * @param {number} near Near bound of the frustum\n * @param {number} far Far bound of the frustum\n * @returns {mat4} out\n */\n\nexport function orthoZO(out, left, right, bottom, top, near, far) {\n var lr = 1 / (left - right);\n var bt = 1 / (bottom - top);\n var nf = 1 / (near - far);\n out[0] = -2 * lr;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = -2 * bt;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = nf;\n out[11] = 0;\n out[12] = (left + right) * lr;\n out[13] = (top + bottom) * bt;\n out[14] = near * nf;\n out[15] = 1;\n return out;\n}\n/**\n * Generates a look-at matrix with the given eye position, focal point, and up axis.\n * If you want a matrix that actually makes an object look at another object, you should use targetTo instead.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {ReadonlyVec3} eye Position of the viewer\n * @param {ReadonlyVec3} center Point the viewer is looking at\n * @param {ReadonlyVec3} up vec3 pointing up\n * @returns {mat4} out\n */\n\nexport function lookAt(out, eye, center, up) {\n var x0, x1, x2, y0, y1, y2, z0, z1, z2, len;\n var eyex = eye[0];\n var eyey = eye[1];\n var eyez = eye[2];\n var upx = up[0];\n var upy = up[1];\n var upz = up[2];\n var centerx = center[0];\n var centery = center[1];\n var centerz = center[2];\n\n if (Math.abs(eyex - centerx) < glMatrix.EPSILON && Math.abs(eyey - centery) < glMatrix.EPSILON && Math.abs(eyez - centerz) < glMatrix.EPSILON) {\n return identity(out);\n }\n\n z0 = eyex - centerx;\n z1 = eyey - centery;\n z2 = eyez - centerz;\n len = 1 / Math.hypot(z0, z1, z2);\n z0 *= len;\n z1 *= len;\n z2 *= len;\n x0 = upy * z2 - upz * z1;\n x1 = upz * z0 - upx * z2;\n x2 = upx * z1 - upy * z0;\n len = Math.hypot(x0, x1, x2);\n\n if (!len) {\n x0 = 0;\n x1 = 0;\n x2 = 0;\n } else {\n len = 1 / len;\n x0 *= len;\n x1 *= len;\n x2 *= len;\n }\n\n y0 = z1 * x2 - z2 * x1;\n y1 = z2 * x0 - z0 * x2;\n y2 = z0 * x1 - z1 * x0;\n len = Math.hypot(y0, y1, y2);\n\n if (!len) {\n y0 = 0;\n y1 = 0;\n y2 = 0;\n } else {\n len = 1 / len;\n y0 *= len;\n y1 *= len;\n y2 *= len;\n }\n\n out[0] = x0;\n out[1] = y0;\n out[2] = z0;\n out[3] = 0;\n out[4] = x1;\n out[5] = y1;\n out[6] = z1;\n out[7] = 0;\n out[8] = x2;\n out[9] = y2;\n out[10] = z2;\n out[11] = 0;\n out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);\n out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);\n out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);\n out[15] = 1;\n return out;\n}\n/**\n * Generates a matrix that makes something look at something else.\n *\n * @param {mat4} out mat4 frustum matrix will be written into\n * @param {ReadonlyVec3} eye Position of the viewer\n * @param {ReadonlyVec3} center Point the viewer is looking at\n * @param {ReadonlyVec3} up vec3 pointing up\n * @returns {mat4} out\n */\n\nexport function targetTo(out, eye, target, up) {\n var eyex = eye[0],\n eyey = eye[1],\n eyez = eye[2],\n upx = up[0],\n upy = up[1],\n upz = up[2];\n var z0 = eyex - target[0],\n z1 = eyey - target[1],\n z2 = eyez - target[2];\n var len = z0 * z0 + z1 * z1 + z2 * z2;\n\n if (len > 0) {\n len = 1 / Math.sqrt(len);\n z0 *= len;\n z1 *= len;\n z2 *= len;\n }\n\n var x0 = upy * z2 - upz * z1,\n x1 = upz * z0 - upx * z2,\n x2 = upx * z1 - upy * z0;\n len = x0 * x0 + x1 * x1 + x2 * x2;\n\n if (len > 0) {\n len = 1 / Math.sqrt(len);\n x0 *= len;\n x1 *= len;\n x2 *= len;\n }\n\n out[0] = x0;\n out[1] = x1;\n out[2] = x2;\n out[3] = 0;\n out[4] = z1 * x2 - z2 * x1;\n out[5] = z2 * x0 - z0 * x2;\n out[6] = z0 * x1 - z1 * x0;\n out[7] = 0;\n out[8] = z0;\n out[9] = z1;\n out[10] = z2;\n out[11] = 0;\n out[12] = eyex;\n out[13] = eyey;\n out[14] = eyez;\n out[15] = 1;\n return out;\n}\n/**\n * Returns a string representation of a mat4\n *\n * @param {ReadonlyMat4} a matrix to represent as a string\n * @returns {String} string representation of the matrix\n */\n\nexport function str(a) {\n return \"mat4(\" + a[0] + \", \" + a[1] + \", \" + a[2] + \", \" + a[3] + \", \" + a[4] + \", \" + a[5] + \", \" + a[6] + \", \" + a[7] + \", \" + a[8] + \", \" + a[9] + \", \" + a[10] + \", \" + a[11] + \", \" + a[12] + \", \" + a[13] + \", \" + a[14] + \", \" + a[15] + \")\";\n}\n/**\n * Returns Frobenius norm of a mat4\n *\n * @param {ReadonlyMat4} a the matrix to calculate Frobenius norm of\n * @returns {Number} Frobenius norm\n */\n\nexport function frob(a) {\n return Math.hypot(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]);\n}\n/**\n * Adds two mat4's\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the first operand\n * @param {ReadonlyMat4} b the second operand\n * @returns {mat4} out\n */\n\nexport function add(out, a, b) {\n out[0] = a[0] + b[0];\n out[1] = a[1] + b[1];\n out[2] = a[2] + b[2];\n out[3] = a[3] + b[3];\n out[4] = a[4] + b[4];\n out[5] = a[5] + b[5];\n out[6] = a[6] + b[6];\n out[7] = a[7] + b[7];\n out[8] = a[8] + b[8];\n out[9] = a[9] + b[9];\n out[10] = a[10] + b[10];\n out[11] = a[11] + b[11];\n out[12] = a[12] + b[12];\n out[13] = a[13] + b[13];\n out[14] = a[14] + b[14];\n out[15] = a[15] + b[15];\n return out;\n}\n/**\n * Subtracts matrix b from matrix a\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the first operand\n * @param {ReadonlyMat4} b the second operand\n * @returns {mat4} out\n */\n\nexport function subtract(out, a, b) {\n out[0] = a[0] - b[0];\n out[1] = a[1] - b[1];\n out[2] = a[2] - b[2];\n out[3] = a[3] - b[3];\n out[4] = a[4] - b[4];\n out[5] = a[5] - b[5];\n out[6] = a[6] - b[6];\n out[7] = a[7] - b[7];\n out[8] = a[8] - b[8];\n out[9] = a[9] - b[9];\n out[10] = a[10] - b[10];\n out[11] = a[11] - b[11];\n out[12] = a[12] - b[12];\n out[13] = a[13] - b[13];\n out[14] = a[14] - b[14];\n out[15] = a[15] - b[15];\n return out;\n}\n/**\n * Multiply each element of the matrix by a scalar.\n *\n * @param {mat4} out the receiving matrix\n * @param {ReadonlyMat4} a the matrix to scale\n * @param {Number} b amount to scale the matrix's elements by\n * @returns {mat4} out\n */\n\nexport function multiplyScalar(out, a, b) {\n out[0] = a[0] * b;\n out[1] = a[1] * b;\n out[2] = a[2] * b;\n out[3] = a[3] * b;\n out[4] = a[4] * b;\n out[5] = a[5] * b;\n out[6] = a[6] * b;\n out[7] = a[7] * b;\n out[8] = a[8] * b;\n out[9] = a[9] * b;\n out[10] = a[10] * b;\n out[11] = a[11] * b;\n out[12] = a[12] * b;\n out[13] = a[13] * b;\n out[14] = a[14] * b;\n out[15] = a[15] * b;\n return out;\n}\n/**\n * Adds two mat4's after multiplying each element of the second operand by a scalar value.\n *\n * @param {mat4} out the receiving vector\n * @param {ReadonlyMat4} a the first operand\n * @param {ReadonlyMat4} b the second operand\n * @param {Number} scale the amount to scale b's elements by before adding\n * @returns {mat4} out\n */\n\nexport function multiplyScalarAndAdd(out, a, b, scale) {\n out[0] = a[0] + b[0] * scale;\n out[1] = a[1] + b[1] * scale;\n out[2] = a[2] + b[2] * scale;\n out[3] = a[3] + b[3] * scale;\n out[4] = a[4] + b[4] * scale;\n out[5] = a[5] + b[5] * scale;\n out[6] = a[6] + b[6] * scale;\n out[7] = a[7] + b[7] * scale;\n out[8] = a[8] + b[8] * scale;\n out[9] = a[9] + b[9] * scale;\n out[10] = a[10] + b[10] * scale;\n out[11] = a[11] + b[11] * scale;\n out[12] = a[12] + b[12] * scale;\n out[13] = a[13] + b[13] * scale;\n out[14] = a[14] + b[14] * scale;\n out[15] = a[15] + b[15] * scale;\n return out;\n}\n/**\n * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)\n *\n * @param {ReadonlyMat4} a The first matrix.\n * @param {ReadonlyMat4} b The second matrix.\n * @returns {Boolean} True if the matrices are equal, false otherwise.\n */\n\nexport function exactEquals(a, b) {\n return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] && a[4] === b[4] && a[5] === b[5] && a[6] === b[6] && a[7] === b[7] && a[8] === b[8] && a[9] === b[9] && a[10] === b[10] && a[11] === b[11] && a[12] === b[12] && a[13] === b[13] && a[14] === b[14] && a[15] === b[15];\n}\n/**\n * Returns whether or not the matrices have approximately the same elements in the same position.\n *\n * @param {ReadonlyMat4} a The first matrix.\n * @param {ReadonlyMat4} b The second matrix.\n * @returns {Boolean} True if the matrices are equal, false otherwise.\n */\n\nexport function equals(a, b) {\n var a0 = a[0],\n a1 = a[1],\n a2 = a[2],\n a3 = a[3];\n var a4 = a[4],\n a5 = a[5],\n a6 = a[6],\n a7 = a[7];\n var a8 = a[8],\n a9 = a[9],\n a10 = a[10],\n a11 = a[11];\n var a12 = a[12],\n a13 = a[13],\n a14 = a[14],\n a15 = a[15];\n var b0 = b[0],\n b1 = b[1],\n b2 = b[2],\n b3 = b[3];\n var b4 = b[4],\n b5 = b[5],\n b6 = b[6],\n b7 = b[7];\n var b8 = b[8],\n b9 = b[9],\n b10 = b[10],\n b11 = b[11];\n var b12 = b[12],\n b13 = b[13],\n b14 = b[14],\n b15 = b[15];\n return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && Math.abs(a4 - b4) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && Math.abs(a5 - b5) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && Math.abs(a6 - b6) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && Math.abs(a7 - b7) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7)) && Math.abs(a8 - b8) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a8), Math.abs(b8)) && Math.abs(a9 - b9) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a9), Math.abs(b9)) && Math.abs(a10 - b10) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a10), Math.abs(b10)) && Math.abs(a11 - b11) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a11), Math.abs(b11)) && Math.abs(a12 - b12) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a12), Math.abs(b12)) && Math.abs(a13 - b13) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a13), Math.abs(b13)) && Math.abs(a14 - b14) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a14), Math.abs(b14)) && Math.abs(a15 - b15) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a15), Math.abs(b15));\n}\n/**\n * Alias for {@link mat4.multiply}\n * @function\n */\n\nexport var mul = multiply;\n/**\n * Alias for {@link mat4.subtract}\n * @function\n */\n\nexport var sub = subtract;","import * as glMatrix from \"./common.js\";\n/**\n * 3 Dimensional Vector\n * @module vec3\n */\n\n/**\n * Creates a new, empty vec3\n *\n * @returns {vec3} a new 3D vector\n */\n\nexport function create() {\n var out = new glMatrix.ARRAY_TYPE(3);\n\n if (glMatrix.ARRAY_TYPE != Float32Array) {\n out[0] = 0;\n out[1] = 0;\n out[2] = 0;\n }\n\n return out;\n}\n/**\n * Creates a new vec3 initialized with values from an existing vector\n *\n * @param {ReadonlyVec3} a vector to clone\n * @returns {vec3} a new 3D vector\n */\n\nexport function clone(a) {\n var out = new glMatrix.ARRAY_TYPE(3);\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n return out;\n}\n/**\n * Calculates the length of a vec3\n *\n * @param {ReadonlyVec3} a vector to calculate length of\n * @returns {Number} length of a\n */\n\nexport function length(a) {\n var x = a[0];\n var y = a[1];\n var z = a[2];\n return Math.hypot(x, y, z);\n}\n/**\n * Creates a new vec3 initialized with the given values\n *\n * @param {Number} x X component\n * @param {Number} y Y component\n * @param {Number} z Z component\n * @returns {vec3} a new 3D vector\n */\n\nexport function fromValues(x, y, z) {\n var out = new glMatrix.ARRAY_TYPE(3);\n out[0] = x;\n out[1] = y;\n out[2] = z;\n return out;\n}\n/**\n * Copy the values from one vec3 to another\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the source vector\n * @returns {vec3} out\n */\n\nexport function copy(out, a) {\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n return out;\n}\n/**\n * Set the components of a vec3 to the given values\n *\n * @param {vec3} out the receiving vector\n * @param {Number} x X component\n * @param {Number} y Y component\n * @param {Number} z Z component\n * @returns {vec3} out\n */\n\nexport function set(out, x, y, z) {\n out[0] = x;\n out[1] = y;\n out[2] = z;\n return out;\n}\n/**\n * Adds two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\n\nexport function add(out, a, b) {\n out[0] = a[0] + b[0];\n out[1] = a[1] + b[1];\n out[2] = a[2] + b[2];\n return out;\n}\n/**\n * Subtracts vector b from vector a\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\n\nexport function subtract(out, a, b) {\n out[0] = a[0] - b[0];\n out[1] = a[1] - b[1];\n out[2] = a[2] - b[2];\n return out;\n}\n/**\n * Multiplies two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\n\nexport function multiply(out, a, b) {\n out[0] = a[0] * b[0];\n out[1] = a[1] * b[1];\n out[2] = a[2] * b[2];\n return out;\n}\n/**\n * Divides two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\n\nexport function divide(out, a, b) {\n out[0] = a[0] / b[0];\n out[1] = a[1] / b[1];\n out[2] = a[2] / b[2];\n return out;\n}\n/**\n * Math.ceil the components of a vec3\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a vector to ceil\n * @returns {vec3} out\n */\n\nexport function ceil(out, a) {\n out[0] = Math.ceil(a[0]);\n out[1] = Math.ceil(a[1]);\n out[2] = Math.ceil(a[2]);\n return out;\n}\n/**\n * Math.floor the components of a vec3\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a vector to floor\n * @returns {vec3} out\n */\n\nexport function floor(out, a) {\n out[0] = Math.floor(a[0]);\n out[1] = Math.floor(a[1]);\n out[2] = Math.floor(a[2]);\n return out;\n}\n/**\n * Returns the minimum of two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\n\nexport function min(out, a, b) {\n out[0] = Math.min(a[0], b[0]);\n out[1] = Math.min(a[1], b[1]);\n out[2] = Math.min(a[2], b[2]);\n return out;\n}\n/**\n * Returns the maximum of two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\n\nexport function max(out, a, b) {\n out[0] = Math.max(a[0], b[0]);\n out[1] = Math.max(a[1], b[1]);\n out[2] = Math.max(a[2], b[2]);\n return out;\n}\n/**\n * Math.round the components of a vec3\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a vector to round\n * @returns {vec3} out\n */\n\nexport function round(out, a) {\n out[0] = Math.round(a[0]);\n out[1] = Math.round(a[1]);\n out[2] = Math.round(a[2]);\n return out;\n}\n/**\n * Scales a vec3 by a scalar number\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the vector to scale\n * @param {Number} b amount to scale the vector by\n * @returns {vec3} out\n */\n\nexport function scale(out, a, b) {\n out[0] = a[0] * b;\n out[1] = a[1] * b;\n out[2] = a[2] * b;\n return out;\n}\n/**\n * Adds two vec3's after scaling the second operand by a scalar value\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @param {Number} scale the amount to scale b by before adding\n * @returns {vec3} out\n */\n\nexport function scaleAndAdd(out, a, b, scale) {\n out[0] = a[0] + b[0] * scale;\n out[1] = a[1] + b[1] * scale;\n out[2] = a[2] + b[2] * scale;\n return out;\n}\n/**\n * Calculates the euclidian distance between two vec3's\n *\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {Number} distance between a and b\n */\n\nexport function distance(a, b) {\n var x = b[0] - a[0];\n var y = b[1] - a[1];\n var z = b[2] - a[2];\n return Math.hypot(x, y, z);\n}\n/**\n * Calculates the squared euclidian distance between two vec3's\n *\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {Number} squared distance between a and b\n */\n\nexport function squaredDistance(a, b) {\n var x = b[0] - a[0];\n var y = b[1] - a[1];\n var z = b[2] - a[2];\n return x * x + y * y + z * z;\n}\n/**\n * Calculates the squared length of a vec3\n *\n * @param {ReadonlyVec3} a vector to calculate squared length of\n * @returns {Number} squared length of a\n */\n\nexport function squaredLength(a) {\n var x = a[0];\n var y = a[1];\n var z = a[2];\n return x * x + y * y + z * z;\n}\n/**\n * Negates the components of a vec3\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a vector to negate\n * @returns {vec3} out\n */\n\nexport function negate(out, a) {\n out[0] = -a[0];\n out[1] = -a[1];\n out[2] = -a[2];\n return out;\n}\n/**\n * Returns the inverse of the components of a vec3\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a vector to invert\n * @returns {vec3} out\n */\n\nexport function inverse(out, a) {\n out[0] = 1.0 / a[0];\n out[1] = 1.0 / a[1];\n out[2] = 1.0 / a[2];\n return out;\n}\n/**\n * Normalize a vec3\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a vector to normalize\n * @returns {vec3} out\n */\n\nexport function normalize(out, a) {\n var x = a[0];\n var y = a[1];\n var z = a[2];\n var len = x * x + y * y + z * z;\n\n if (len > 0) {\n //TODO: evaluate use of glm_invsqrt here?\n len = 1 / Math.sqrt(len);\n }\n\n out[0] = a[0] * len;\n out[1] = a[1] * len;\n out[2] = a[2] * len;\n return out;\n}\n/**\n * Calculates the dot product of two vec3's\n *\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {Number} dot product of a and b\n */\n\nexport function dot(a, b) {\n return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];\n}\n/**\n * Computes the cross product of two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @returns {vec3} out\n */\n\nexport function cross(out, a, b) {\n var ax = a[0],\n ay = a[1],\n az = a[2];\n var bx = b[0],\n by = b[1],\n bz = b[2];\n out[0] = ay * bz - az * by;\n out[1] = az * bx - ax * bz;\n out[2] = ax * by - ay * bx;\n return out;\n}\n/**\n * Performs a linear interpolation between two vec3's\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\n * @returns {vec3} out\n */\n\nexport function lerp(out, a, b, t) {\n var ax = a[0];\n var ay = a[1];\n var az = a[2];\n out[0] = ax + t * (b[0] - ax);\n out[1] = ay + t * (b[1] - ay);\n out[2] = az + t * (b[2] - az);\n return out;\n}\n/**\n * Performs a hermite interpolation with two control points\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @param {ReadonlyVec3} c the third operand\n * @param {ReadonlyVec3} d the fourth operand\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\n * @returns {vec3} out\n */\n\nexport function hermite(out, a, b, c, d, t) {\n var factorTimes2 = t * t;\n var factor1 = factorTimes2 * (2 * t - 3) + 1;\n var factor2 = factorTimes2 * (t - 2) + t;\n var factor3 = factorTimes2 * (t - 1);\n var factor4 = factorTimes2 * (3 - 2 * t);\n out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;\n out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;\n out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;\n return out;\n}\n/**\n * Performs a bezier interpolation with two control points\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the first operand\n * @param {ReadonlyVec3} b the second operand\n * @param {ReadonlyVec3} c the third operand\n * @param {ReadonlyVec3} d the fourth operand\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\n * @returns {vec3} out\n */\n\nexport function bezier(out, a, b, c, d, t) {\n var inverseFactor = 1 - t;\n var inverseFactorTimesTwo = inverseFactor * inverseFactor;\n var factorTimes2 = t * t;\n var factor1 = inverseFactorTimesTwo * inverseFactor;\n var factor2 = 3 * t * inverseFactorTimesTwo;\n var factor3 = 3 * factorTimes2 * inverseFactor;\n var factor4 = factorTimes2 * t;\n out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;\n out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;\n out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;\n return out;\n}\n/**\n * Generates a random vector with the given scale\n *\n * @param {vec3} out the receiving vector\n * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned\n * @returns {vec3} out\n */\n\nexport function random(out, scale) {\n scale = scale || 1.0;\n var r = glMatrix.RANDOM() * 2.0 * Math.PI;\n var z = glMatrix.RANDOM() * 2.0 - 1.0;\n var zScale = Math.sqrt(1.0 - z * z) * scale;\n out[0] = Math.cos(r) * zScale;\n out[1] = Math.sin(r) * zScale;\n out[2] = z * scale;\n return out;\n}\n/**\n * Transforms the vec3 with a mat4.\n * 4th vector component is implicitly '1'\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the vector to transform\n * @param {ReadonlyMat4} m matrix to transform with\n * @returns {vec3} out\n */\n\nexport function transformMat4(out, a, m) {\n var x = a[0],\n y = a[1],\n z = a[2];\n var w = m[3] * x + m[7] * y + m[11] * z + m[15];\n w = w || 1.0;\n out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w;\n out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w;\n out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w;\n return out;\n}\n/**\n * Transforms the vec3 with a mat3.\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the vector to transform\n * @param {ReadonlyMat3} m the 3x3 matrix to transform with\n * @returns {vec3} out\n */\n\nexport function transformMat3(out, a, m) {\n var x = a[0],\n y = a[1],\n z = a[2];\n out[0] = x * m[0] + y * m[3] + z * m[6];\n out[1] = x * m[1] + y * m[4] + z * m[7];\n out[2] = x * m[2] + y * m[5] + z * m[8];\n return out;\n}\n/**\n * Transforms the vec3 with a quat\n * Can also be used for dual quaternions. (Multiply it with the real part)\n *\n * @param {vec3} out the receiving vector\n * @param {ReadonlyVec3} a the vector to transform\n * @param {ReadonlyQuat} q quaternion to transform with\n * @returns {vec3} out\n */\n\nexport function transformQuat(out, a, q) {\n // benchmarks: https://jsperf.com/quaternion-transform-vec3-implementations-fixed\n var qx = q[0],\n qy = q[1],\n qz = q[2],\n qw = q[3];\n var x = a[0],\n y = a[1],\n z = a[2]; // var qvec = [qx, qy, qz];\n // var uv = vec3.cross([], qvec, a);\n\n var uvx = qy * z - qz * y,\n uvy = qz * x - qx * z,\n uvz = qx * y - qy * x; // var uuv = vec3.cross([], qvec, uv);\n\n var uuvx = qy * uvz - qz * uvy,\n uuvy = qz * uvx - qx * uvz,\n uuvz = qx * uvy - qy * uvx; // vec3.scale(uv, uv, 2 * w);\n\n var w2 = qw * 2;\n uvx *= w2;\n uvy *= w2;\n uvz *= w2; // vec3.scale(uuv, uuv, 2);\n\n uuvx *= 2;\n uuvy *= 2;\n uuvz *= 2; // return vec3.add(out, a, vec3.add(out, uv, uuv));\n\n out[0] = x + uvx + uuvx;\n out[1] = y + uvy + uuvy;\n out[2] = z + uvz + uuvz;\n return out;\n}\n/**\n * Rotate a 3D vector around the x-axis\n * @param {vec3} out The receiving vec3\n * @param {ReadonlyVec3} a The vec3 point to rotate\n * @param {ReadonlyVec3} b The origin of the rotation\n * @param {Number} rad The angle of rotation in radians\n * @returns {vec3} out\n */\n\nexport function rotateX(out, a, b, rad) {\n var p = [],\n r = []; //Translate point to the origin\n\n p[0] = a[0] - b[0];\n p[1] = a[1] - b[1];\n p[2] = a[2] - b[2]; //perform rotation\n\n r[0] = p[0];\n r[1] = p[1] * Math.cos(rad) - p[2] * Math.sin(rad);\n r[2] = p[1] * Math.sin(rad) + p[2] * Math.cos(rad); //translate to correct position\n\n out[0] = r[0] + b[0];\n out[1] = r[1] + b[1];\n out[2] = r[2] + b[2];\n return out;\n}\n/**\n * Rotate a 3D vector around the y-axis\n * @param {vec3} out The receiving vec3\n * @param {ReadonlyVec3} a The vec3 point to rotate\n * @param {ReadonlyVec3} b The origin of the rotation\n * @param {Number} rad The angle of rotation in radians\n * @returns {vec3} out\n */\n\nexport function rotateY(out, a, b, rad) {\n var p = [],\n r = []; //Translate point to the origin\n\n p[0] = a[0] - b[0];\n p[1] = a[1] - b[1];\n p[2] = a[2] - b[2]; //perform rotation\n\n r[0] = p[2] * Math.sin(rad) + p[0] * Math.cos(rad);\n r[1] = p[1];\n r[2] = p[2] * Math.cos(rad) - p[0] * Math.sin(rad); //translate to correct position\n\n out[0] = r[0] + b[0];\n out[1] = r[1] + b[1];\n out[2] = r[2] + b[2];\n return out;\n}\n/**\n * Rotate a 3D vector around the z-axis\n * @param {vec3} out The receiving vec3\n * @param {ReadonlyVec3} a The vec3 point to rotate\n * @param {ReadonlyVec3} b The origin of the rotation\n * @param {Number} rad The angle of rotation in radians\n * @returns {vec3} out\n */\n\nexport function rotateZ(out, a, b, rad) {\n var p = [],\n r = []; //Translate point to the origin\n\n p[0] = a[0] - b[0];\n p[1] = a[1] - b[1];\n p[2] = a[2] - b[2]; //perform rotation\n\n r[0] = p[0] * Math.cos(rad) - p[1] * Math.sin(rad);\n r[1] = p[0] * Math.sin(rad) + p[1] * Math.cos(rad);\n r[2] = p[2]; //translate to correct position\n\n out[0] = r[0] + b[0];\n out[1] = r[1] + b[1];\n out[2] = r[2] + b[2];\n return out;\n}\n/**\n * Get the angle between two 3D vectors\n * @param {ReadonlyVec3} a The first operand\n * @param {ReadonlyVec3} b The second operand\n * @returns {Number} The angle in radians\n */\n\nexport function angle(a, b) {\n var ax = a[0],\n ay = a[1],\n az = a[2],\n bx = b[0],\n by = b[1],\n bz = b[2],\n mag1 = Math.sqrt(ax * ax + ay * ay + az * az),\n mag2 = Math.sqrt(bx * bx + by * by + bz * bz),\n mag = mag1 * mag2,\n cosine = mag && dot(a, b) / mag;\n return Math.acos(Math.min(Math.max(cosine, -1), 1));\n}\n/**\n * Set the components of a vec3 to zero\n *\n * @param {vec3} out the receiving vector\n * @returns {vec3} out\n */\n\nexport function zero(out) {\n out[0] = 0.0;\n out[1] = 0.0;\n out[2] = 0.0;\n return out;\n}\n/**\n * Returns a string representation of a vector\n *\n * @param {ReadonlyVec3} a vector to represent as a string\n * @returns {String} string representation of the vector\n */\n\nexport function str(a) {\n return \"vec3(\" + a[0] + \", \" + a[1] + \", \" + a[2] + \")\";\n}\n/**\n * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===)\n *\n * @param {ReadonlyVec3} a The first vector.\n * @param {ReadonlyVec3} b The second vector.\n * @returns {Boolean} True if the vectors are equal, false otherwise.\n */\n\nexport function exactEquals(a, b) {\n return a[0] === b[0] && a[1] === b[1] && a[2] === b[2];\n}\n/**\n * Returns whether or not the vectors have approximately the same elements in the same position.\n *\n * @param {ReadonlyVec3} a The first vector.\n * @param {ReadonlyVec3} b The second vector.\n * @returns {Boolean} True if the vectors are equal, false otherwise.\n */\n\nexport function equals(a, b) {\n var a0 = a[0],\n a1 = a[1],\n a2 = a[2];\n var b0 = b[0],\n b1 = b[1],\n b2 = b[2];\n return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2));\n}\n/**\n * Alias for {@link vec3.subtract}\n * @function\n */\n\nexport var sub = subtract;\n/**\n * Alias for {@link vec3.multiply}\n * @function\n */\n\nexport var mul = multiply;\n/**\n * Alias for {@link vec3.divide}\n * @function\n */\n\nexport var div = divide;\n/**\n * Alias for {@link vec3.distance}\n * @function\n */\n\nexport var dist = distance;\n/**\n * Alias for {@link vec3.squaredDistance}\n * @function\n */\n\nexport var sqrDist = squaredDistance;\n/**\n * Alias for {@link vec3.length}\n * @function\n */\n\nexport var len = length;\n/**\n * Alias for {@link vec3.squaredLength}\n * @function\n */\n\nexport var sqrLen = squaredLength;\n/**\n * Perform some operation over an array of vec3s.\n *\n * @param {Array} a the array of vectors to iterate over\n * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed\n * @param {Number} offset Number of elements to skip at the beginning of the array\n * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array\n * @param {Function} fn Function to call for each vector in the array\n * @param {Object} [arg] additional argument to pass to fn\n * @returns {Array} a\n * @function\n */\n\nexport var forEach = function () {\n var vec = create();\n return function (a, stride, offset, count, fn, arg) {\n var i, l;\n\n if (!stride) {\n stride = 3;\n }\n\n if (!offset) {\n offset = 0;\n }\n\n if (count) {\n l = Math.min(count * stride + offset, a.length);\n } else {\n l = a.length;\n }\n\n for (i = offset; i < l; i += stride) {\n vec[0] = a[i];\n vec[1] = a[i + 1];\n vec[2] = a[i + 2];\n fn(vec, vec, arg);\n a[i] = vec[0];\n a[i + 1] = vec[1];\n a[i + 2] = vec[2];\n }\n\n return a;\n };\n}();","// ===== tuples.ts ======================================================\n// Types & helpers for 3-tuples, used for positions, vectors and colours\n// Ben Coleman, 2023\n// ======================================================================\n\nimport { vec3 } from 'gl-matrix'\n\n/** A simple 3D position or vector tuple */\nexport type XYZ = [number, number, number]\n\n/** A simple RGB colour tuple */\nexport type RGB = [number, number, number]\n\n/** A simple RGBA colour tuple */\nexport type RGBA = [number, number, number, number]\n\n// ============================================================================\n// Tuple helpers\n// ============================================================================\n\n/**\n * Normalizes a 3-tuple to a unit vector.\n * @param tuple The tuple to normalize\n */\nfunction normalize(tuple: XYZ | RGB | number[]) {\n const [x, y, z] = tuple\n const len = Math.sqrt(x * x + y * y + z * z)\n\n return tuple.map((v) => v / len) as XYZ\n}\n\n/**\n * Scales a 3-tuple by a scalar.\n * @param tuple The tuple to scale\n * @param scale The scalar to scale by\n */\nfunction scale(tuple: XYZ | RGB | RGBA | number[], amount: number) {\n return tuple.map((v) => v * amount) as XYZ\n}\n\n/**\n * Scales a 3-tuple by a scalar, clamping the result to 0-1.\n * @param tuple The tuple to scale\n * @param scale The scalar to scale by\n */\nfunction scaleClamped(colour: RGB | RGBA, amount: number) {\n scale(colour, amount)\n\n // Clamp to 0-1\n return colour.map((v) => Math.min(Math.max(v, 0), 1)) as RGB | RGBA\n}\n\n/**\n * Converts a 3-tuple to a gl-matrix vec3\n * @param tuple The tuple to convert\n */\nfunction toVec3(tuple: XYZ) {\n return vec3.fromValues(tuple[0], tuple[1], tuple[2])\n}\n\n/**\n * Calculates the distance between two 3-tuples\n * @param a First tuple\n * @param b Second tuple\n */\nfunction distance(a: XYZ, b: XYZ) {\n return (a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2 + (a[2] - b[2]) ** 2\n}\n\n// ============================================================================\n// Colour helpers\n// ============================================================================\n\n/**\n * Creates a RGB 3-tuple from 0-255 values.\n * @param r Red value (0-255)\n * @param g Green value (0-255)\n * @param b Blue value (0-255)\n */\nfunction rgbColour255(r: number, g: number, b: number) {\n return [r / 255, g / 255, b / 255] as RGB\n}\n\n/**\n * Converts a hex string to an RGB 3-tuple.\n * @param hexString\n */\nfunction rgbColourHex(hexString: string) {\n const hex = hexString.replace('#', '')\n const r = parseInt(hex.substring(0, 2), 16)\n const g = parseInt(hex.substring(2, 4), 16)\n const b = parseInt(hex.substring(4, 6), 16)\n\n return rgbColour255(r, g, b)\n}\n\n/**\n * A set of common colours as RGB tuples\n */\nexport const Colours = {\n RED: [1, 0, 0] as RGB,\n GREEN: [0, 1, 0] as RGB,\n BLUE: [0, 0, 1] as RGB,\n YELLOW: [1, 1, 0] as RGB,\n CYAN: [0, 1, 1] as RGB,\n MAGENTA: [1, 0, 1] as RGB,\n BLACK: [0, 0, 0] as RGB,\n WHITE: [1, 1, 1] as RGB,\n}\n\n// ============================================================================\n// Exports\n// ============================================================================\n\nexport const Tuples = {\n normalize,\n scale,\n scaleClamped,\n rgbColour255,\n rgbColourHex,\n toVec3,\n distance,\n}\n","// ===== cache.ts =============================================================\n// Caches and managers for models and textures\n// Ben Coleman, 2023\n// ============================================================================\n\nimport log from 'loglevel'\nimport { Model } from '../models/model.ts'\nimport { ProgramInfo, createTexture } from 'twgl.js'\n\nexport const PROG_DEFAULT = 'phong'\nexport const PROG_BILLBOARD = 'billboard'\n\n/**\n * A singleton cache for parsed and loaded models, indexed by name\n */\nexport class ModelCache {\n private cache: Map\n private static _instance: ModelCache\n\n private constructor() {\n this.cache = new Map()\n }\n\n /**\n * Return the singleton instance of the model cache\n */\n static get instance() {\n if (!ModelCache._instance) {\n ModelCache._instance = new ModelCache()\n }\n\n return ModelCache._instance\n }\n\n /**\n * Return a model from the cache by name\n * @param name Name of model without extension\n * @param warn If true, log a warning if model not found\n */\n get(name: string, warn = true) {\n if (!this.cache.has(name) && warn) {\n log.warn(`⚠️ Model '${name}' not found, please load it first`)\n return undefined\n }\n\n return this.cache.get(name)\n }\n\n /**\n * Add a model to the cache, using the model name as key\n */\n add(model: Model) {\n log.debug(`🧰 Adding model '${model.name}' to cache`)\n\n this.cache.set(model.name, model)\n }\n}\n\n/**\n * A caching texture manager\n * It is instantiated with a WebGL context and then used to load and cache textures\n */\nexport class TextureCache {\n private cache: Map\n private gl: WebGL2RenderingContext\n private static _instance: TextureCache\n private static initialized = false\n\n private constructor() {\n this.cache = new Map()\n this.gl = {} as WebGL2RenderingContext\n }\n\n // Create a new texture cache\n static init(gl: WebGL2RenderingContext) {\n this._instance = new TextureCache()\n this._instance.gl = gl\n\n // Add default textures\n\n // 1 pixel white texture used as base for materials\n const white1pixel = createTexture(gl, {\n min: gl.NEAREST,\n mag: gl.NEAREST,\n src: [255, 255, 255, 255],\n })\n\n // 1 pixel texture used for normal mapping is sort of blue-violet colour\n const normal1pixel = createTexture(gl, {\n min: gl.NEAREST,\n mag: gl.NEAREST,\n src: [128, 128, 255, 255],\n })\n\n this._instance.add('_defaults/white', white1pixel)\n this._instance.add('_defaults/normal', normal1pixel)\n\n TextureCache.initialized = true\n }\n\n static get instance() {\n if (!TextureCache.initialized) {\n throw new Error('TextureCache not initialized, call TextureCache.init() first')\n }\n\n return this._instance\n }\n\n /**\n * Return a texture from the cache by name\n * @param key Key of texture, this is usually the URL or filename path\n */\n get(key: string) {\n if (!this.cache.has(key)) {\n log.warn(`💥 Texture ${key} not found in cache`)\n return undefined\n }\n\n log.trace(`👍 Returning texture '${key}' from cache, nice!`)\n return this.cache.get(key)\n }\n\n /**\n * Add a texture to the cache\n * @param key Key of texture, this is usually the URL or filename path\n * @param texture WebGL texture\n */\n add(key: string, texture: WebGLTexture) {\n if (this.cache.has(key)) {\n log.warn(`🤔 Texture '${key}' already in cache, not adding again`)\n return\n }\n\n log.debug(`🧰 Adding texture '${key}' to cache`)\n\n this.cache.set(key, texture)\n }\n\n /**\n * Create or return a texture from the cache by name\n * @param src URL or filename path of texture image\n * @param filter Enable texture filtering and mipmaps (default true)\n * @param flipY Flip the texture vertically (default true)\n */\n getCreate(src: string, filter = true, flipY = false) {\n // Check if texture already exists, if so return it\n if (this.cache.has(src)) {\n log.trace(`👍 Returning texture '${src}' from cache, nice!`, flipY)\n return this.get(src)\n }\n\n // Create texture and add to cache\n // NOTE. Catching errors here is very hard, as twgl.createTexture() doesn't throw errors\n const texture = createTexture(\n this.gl,\n {\n min: filter ? this.gl.LINEAR_MIPMAP_LINEAR : this.gl.NEAREST,\n mag: filter ? this.gl.LINEAR : this.gl.NEAREST,\n src,\n flipY: flipY ? 1 : 0,\n },\n (err) => {\n if (err) {\n // There's not much we can do here, but log the error\n log.error('💥 Error loading texture', err)\n }\n }\n )\n\n this.add(src, texture)\n return texture\n }\n}\n\n/**\n * Singleton cache for parsed and loaded GL programs, indexed by name\n */\nexport class ProgramCache {\n private cache: Map\n private _default: ProgramInfo\n private static _instance: ProgramCache\n private static initialized = false\n\n public static PROG_PHONG = 'phong'\n public static PROG_BILLBOARD = 'billboard'\n public static PROG_SHADOWMAP = 'shadowmap'\n\n /**\n * Create a new program cache, needs a default program to be set\n * @param defaultProg The default program that can be used by most things\n */\n private constructor() {\n this.cache = new Map()\n // This is pretty nasty, but we really trust people to call init() first\n this._default = {} as ProgramInfo\n }\n\n /**\n * Initialise the program cache with a default program.\n * This MUST be called before using the cache\n * @param defaultProg The default program that can be used by most things\n */\n public static init(defaultProg: ProgramInfo) {\n if (ProgramCache._instance) {\n log.warn('🤔 Program cache already initialised, not doing it again')\n return\n }\n\n ProgramCache._instance = new ProgramCache()\n ProgramCache._instance._default = defaultProg\n ProgramCache.initialized = true\n }\n\n /**\n * Return the singleton instance of the program cache\n */\n static get instance() {\n if (!ProgramCache.initialized) {\n throw new Error('💥 Program cache not initialised, call init() first')\n }\n\n return ProgramCache._instance\n }\n\n /**\n * Return a program from the cache by name\n * @param name Name of program\n */\n get(name: string): ProgramInfo {\n const prog = this.cache.get(name)\n\n if (!prog) {\n log.warn(`⚠️ Program '${name}' not found, returning default`)\n return this._default\n }\n\n return prog\n }\n\n add(name: string, program: ProgramInfo) {\n log.debug(`🧰 Adding program '${name}' to cache`)\n\n this.cache.set(name, program)\n }\n\n get default() {\n return this._default\n }\n}\n","// ===== camera.ts ============================================================\n// Represents a camera in 3D space\n// Ben Coleman, 2023\n// ============================================================================\n\nimport { mat4 } from 'gl-matrix'\nimport { XYZ } from './tuples.ts'\nimport { getGl } from '../core/gl.ts'\n\nimport log from 'loglevel'\n\nexport enum CameraType {\n PERSPECTIVE,\n ORTHOGRAPHIC,\n}\n\nexport class Camera {\n /** Camera position */\n public position: XYZ\n\n /** Camera look at point, default: [0, 0, 0] */\n public lookAt: XYZ\n\n /** Field of view in degrees, default: 45 */\n public fov: number\n\n /** Near clipping plane, default: 0.1 */\n public near: number\n\n /** Far clipping plane, default: 100 */\n public far: number\n\n /** Camera up vector, default: [0, 1, 0] */\n public up: XYZ\n\n /** Change camera projection, default: CameraType.PERSPECTIVE */\n public type: CameraType\n\n /** Is this camera active, default: true */\n public active: boolean\n\n /** Orthographic zoom level, only used when type is orthographic, default: 20 */\n public orthoZoom: number\n\n /** Is this camera used for a dynamic environment map, default: false */\n public usedForEnvMap: boolean\n\n /** Is this camera used for a shadow map, default: false */\n public usedForShadowMap: boolean\n\n /** Aspect ratio of the camera, default: 1 */\n public aspectRatio: number\n\n // Used for first person mode\n private fpAngleY: number\n private fpAngleX: number\n private fpMode: boolean\n private fpHandlersAdded: boolean\n private fpTurnSpeed: number\n private fpMoveSpeed: number\n\n // Used to clamp first person up/down angle\n private maxAngleUp: number = Math.PI / 2 - 0.01\n private maxAngleDown: number = -Math.PI / 2 + 0.01\n\n // Used to track keys pressed in FP mode for better movement\n private keysDown: Set\n private touches: Touch[] = []\n\n /**\n * Create a new default camera\n */\n constructor(type = CameraType.PERSPECTIVE, aspectRatio = 1) {\n this.type = type\n this.active = true\n\n this.position = [0, 0, 30]\n this.lookAt = [0, 0, 0]\n this.up = [0, 1, 0]\n this.near = 0.1\n this.far = 100\n this.fov = 45\n this.aspectRatio = aspectRatio\n this.orthoZoom = 20\n this.usedForEnvMap = false\n this.usedForShadowMap = false\n\n this.fpMode = false\n this.fpAngleY = 0\n this.fpAngleX = 0\n this.fpTurnSpeed = 0.001\n this.fpMoveSpeed = 1.0\n this.fpHandlersAdded = false\n\n this.keysDown = new Set()\n }\n\n /**\n * Get the current view matrix for the camera\n */\n get matrix() {\n // Standard view matrix with position and lookAt for non-FPS camera\n if (!this.fpMode) {\n const camView = mat4.targetTo(mat4.create(), this.position, this.lookAt, this.up)\n return camView\n }\n\n // FPS camera is handled different, we need to rotate the camera around the Y axis\n const camView = mat4.targetTo(mat4.create(), [0, 0, 0], [0, 0, -1], this.up)\n mat4.translate(camView, camView, this.position)\n mat4.rotateY(camView, camView, this.fpAngleY)\n mat4.rotateX(camView, camView, this.fpAngleX)\n return camView\n }\n\n /**\n * Get the projection matrix for this camera\n * @param aspectRatio Aspect ratio of the canvas\n */\n get projectionMatrix() {\n if (this.type === CameraType.ORTHOGRAPHIC) {\n const camProj = mat4.ortho(\n mat4.create(),\n -this.aspectRatio * this.orthoZoom,\n this.aspectRatio * this.orthoZoom,\n -this.orthoZoom,\n this.orthoZoom,\n this.near,\n this.far\n )\n\n return camProj\n } else {\n const camProj = mat4.perspective(mat4.create(), this.fov * (Math.PI / 180), this.aspectRatio, this.near, this.far)\n return camProj\n }\n }\n\n /**\n * Get the camera position as a string for debugging\n */\n toString() {\n const pos = this.position.map((p) => p.toFixed(2))\n return `position: [${pos}]`\n }\n\n /**\n * Switches the camera to first person mode, where the camera is controlled by\n * the mouse and keyboard. The mouse controls look direction and the keyboard\n * controls movement.\n * @param angleY Starting look up/down angle in radians, default 0\n * @param angleX Starting look left/right angle in radians, default 0\n * @param turnSpeed Speed of looking in radians, default 0.001\n * @param moveSpeed Speed of moving in units, default 1.0\n */\n enableFPControls(angleY = 0, angleX = 0, turnSpeed = 0.001, moveSpeed = 1.0) {\n this.fpMode = true\n this.fpAngleY = angleY\n this.fpAngleX = angleX\n this.fpTurnSpeed = turnSpeed\n this.fpMoveSpeed = moveSpeed\n\n if (this.fpHandlersAdded) return // Prevent multiple event listeners being added\n\n // Handle enable/disable for pointer lock on main canvas\n // See: https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API\n const gl = getGl()\n gl?.canvas.addEventListener('click', async () => {\n if (!this.fpMode || !this.active) return\n\n if (document.pointerLockElement) {\n document.exitPointerLock()\n } else {\n await (gl?.canvas).requestPointerLock()\n }\n })\n\n // Handle mouse movement for looking around\n window.addEventListener('mousemove', (e) => {\n if (!document.pointerLockElement) {\n return\n }\n\n if (!this.fpMode || !this.active) return\n this.fpAngleY += e.movementX * -this.fpTurnSpeed\n this.fpAngleX += e.movementY * -this.fpTurnSpeed\n\n // Clamp up/down angle\n if (this.fpAngleX > this.maxAngleUp) this.fpAngleX = this.maxAngleUp\n if (this.fpAngleX < this.maxAngleDown) this.fpAngleX = this.maxAngleDown\n })\n\n // Track keys pressed for movement\n window.addEventListener('keydown', (e) => {\n if (!this.fpMode || !this.active) return\n this.keysDown.add(e.key)\n })\n\n window.addEventListener('keyup', (e) => {\n if (!this.fpMode || !this.active) return\n this.keysDown.delete(e.key)\n })\n\n window.addEventListener('touchstart', (e) => {\n if (!this.fpMode || !this.active) return\n\n // If the touch is on the right side of the screen, it's for looking\n if (e.touches[0].clientX > window.innerWidth / 2) {\n this.touches[0] = e.touches[0]\n }\n\n // If the touch is on the left side of the screen, it's for moving\n if (e.touches[0].clientX < window.innerWidth / 2) {\n // Top half of screen is forward, bottom half is backward\n if (e.touches[0].clientY < window.innerHeight / 2) {\n this.keysDown.add('w')\n }\n if (e.touches[0].clientY > window.innerHeight / 2) {\n this.keysDown.add('s')\n }\n }\n })\n\n window.addEventListener('touchend', () => {\n if (!this.fpMode || !this.active) return\n\n this.touches = []\n this.keysDown.clear()\n })\n\n window.addEventListener('touchmove', (e) => {\n if (!this.fpMode || !this.active) return\n\n if (this.touches.length === 0) return\n\n const touch = e.touches[0]\n\n const dx = touch.clientX - this.touches[0].clientX\n const dy = touch.clientY - this.touches[0].clientY\n\n this.fpAngleY += dx * -this.fpTurnSpeed * touch.force * 4\n this.fpAngleX += dy * -this.fpTurnSpeed * touch.force * 4\n\n // Clamp up/down angle\n if (this.fpAngleX > this.maxAngleUp) this.fpAngleX = this.maxAngleUp\n if (this.fpAngleX < this.maxAngleDown) this.fpAngleX = this.maxAngleDown\n\n this.touches[0] = touch\n })\n\n this.fpHandlersAdded = true\n log.info('🎥 Camera: first person mode & controls enabled')\n }\n\n /**\n * Disable FP mode\n */\n disableFPControls() {\n this.fpMode = false\n document.exitPointerLock()\n log.debug('🎥 Camera: FPS mode disabled')\n }\n\n /**\n * Get FP mode state\n */\n get fpModeEnabled() {\n return this.fpMode\n }\n\n /**\n * Called every frame to update the camera, currently only used for movement in FP mode\n */\n update() {\n if (!this.fpMode || !this.active) return\n if (this.keysDown.size === 0) return\n\n // Use fpAngleY to calculate the direction we are facing\n const dZ = -Math.cos(this.fpAngleY) * this.fpMoveSpeed\n const dX = -Math.sin(this.fpAngleY) * this.fpMoveSpeed\n\n // Use keysDown to move the camera\n for (const key of this.keysDown.values()) {\n switch (key) {\n case 'ArrowUp':\n case 'w':\n this.position[0] += dX\n this.position[2] += dZ\n this.lookAt[0] += dX\n this.lookAt[2] += dZ\n break\n\n case 'ArrowDown':\n case 's':\n this.position[0] -= dX\n this.position[2] -= dZ\n this.lookAt[0] -= dX\n this.lookAt[2] -= dZ\n break\n\n case 'ArrowLeft':\n case 'a':\n this.position[0] += dZ\n this.position[2] -= dX\n this.lookAt[0] += dZ\n this.lookAt[2] -= dX\n break\n\n case 'ArrowRight':\n case 'd':\n // Move right\n this.position[0] -= dZ\n this.position[2] += dX\n this.lookAt[0] -= dZ\n this.lookAt[2] += dX\n break\n }\n }\n }\n}\n","#version 300 es\n\n// ============================================================================\n// Shadow map fragment shader\n// Ben Coleman, 2023\n// ============================================================================\n\nprecision highp float;\n\nvoid main() {\n // Yeah I don't understand this either, but it works\n}\n","#version 300 es\n\n// ============================================================================\n// Shadow map vertex shader\n// Ben Coleman, 2023\n// ============================================================================\n\nprecision highp float;\n\nin vec4 position;\n\nuniform mat4 u_worldViewProjection;\n\nvoid main() {\n gl_Position = u_worldViewProjection * position;\n}\n","// ===== light.ts =============================================================\n// All light types, including directional and point\n// Ben Coleman, 2023\n// ============================================================================\n\nimport { mat4 } from 'gl-matrix'\nimport { FramebufferInfo, ProgramInfo, createFramebufferInfo, createProgramInfo, createTexture } from 'twgl.js'\n\nimport { UniformSet, getGl } from '../core/gl.ts'\nimport { Camera, CameraType } from './camera.ts'\nimport { Colours, Tuples, XYZ, RGB } from './tuples.ts'\n\nimport fragShaderShadow from '../../shaders/shadowmap/glsl.frag'\nimport vertShaderShadow from '../../shaders/shadowmap/glsl.vert'\n\n/**\n * Options to configure how shadows are calculated & rendered\n */\nexport type ShadowOptions = {\n /** Size of the shadow map texture. Default: 512 */\n mapSize: number\n\n /**\n * Zoom level of the shadow map camera, larger will cover more of the scene,\n * but results in more blocky shadows. Default 120\n */\n zoom: number\n\n /** Far clipping pane of shadow map camera, default 1000 */\n distance: number\n\n /** Blur the edges of shadows, higher values them more random, default 0.2 */\n scatter: number\n}\n\n/**\n * A directional light source, typically global with the context having only a single instance\n * Having multiple directional lights is not supported\n */\nexport class LightDirectional {\n private _direction: XYZ\n private _shadowMapProgram?: ProgramInfo\n private _shadowMapFB?: FramebufferInfo\n private _shadowMapTex?: WebGLTexture\n private _shadowOptions?: ShadowOptions\n\n /** Colour of the light, used for both diffuse and specular. Default: [0, 0, 0] */\n public colour: RGB\n\n /** Ambient colour of the light. Default: [0, 0, 0] */\n public ambient: RGB\n\n /** Is this light enabled. Default: true */\n public enabled: boolean\n\n /** Create a default directional light, pointing downward */\n constructor() {\n this._direction = [0, -1, 0]\n this.colour = Colours.WHITE\n this.ambient = Colours.BLACK\n this.enabled = true\n\n const gl = getGl()\n if (!gl) {\n throw new Error('💥 LightDirectional: Cannot create shadow map shader, no GL context')\n }\n\n this._shadowMapProgram = createProgramInfo(gl, [vertShaderShadow, fragShaderShadow], ['shadowProgram'])\n }\n\n /**\n * Set the direction of the light ensuring it is normalized\n * @param direction - Direction vector\n */\n set direction(direction: XYZ) {\n // Ensure direction is normalized\n this._direction = Tuples.normalize(direction)\n }\n\n /**\n * Get the direction of the light\n */\n get direction() {\n return this._direction\n }\n\n /**\n * Convenience method allows setting the direction as a point relative to the world origin\n * Values are always converted to a normalized unit direction vector\n * @param x - X position\n * @param y - Y position\n * @param z - Z position\n */\n setAsPosition(x: number, y: number, z: number) {\n this._direction = Tuples.normalize([0 - x, 0 - y, 0 - z])\n }\n\n /**\n * Return the base set of uniforms for this light\n */\n get uniforms() {\n return {\n direction: this.direction,\n colour: this.enabled ? this.colour : [0, 0, 0],\n ambient: this.ambient ? this.ambient : [0, 0, 0],\n } as UniformSet\n }\n\n /**\n * Enable shadows for this light, this will create a shadow map texture and framebuffer\n * There is no way to disabled shadows once enabled\n * @param options A set of ShadowOptions to configure how shadows are calculated\n */\n enableShadows(options?: ShadowOptions) {\n this._shadowOptions = options ?? ({} as ShadowOptions)\n if (!this._shadowOptions.mapSize) {\n this._shadowOptions.mapSize = 512\n }\n if (!this._shadowOptions.zoom) {\n this._shadowOptions.zoom = 120\n }\n if (!this._shadowOptions.distance) {\n this._shadowOptions.distance = 1000\n }\n if (!this._shadowOptions.scatter) {\n this._shadowOptions.scatter = 0.2\n }\n\n const gl = getGl()\n if (!gl) {\n throw new Error('💥 LightDirectional: Cannot create shadow map, no GL context')\n }\n\n // This is a special type of texture, used for depth comparison and shadow mapping\n this._shadowMapTex = createTexture(gl, {\n width: this._shadowOptions.mapSize,\n height: this._shadowOptions.mapSize,\n internalFormat: gl.DEPTH_COMPONENT32F, // Makes this a depth texture\n compareMode: gl.COMPARE_REF_TO_TEXTURE, // Becomes a shadow map, e.g. sampler2DShadow\n minMag: gl.LINEAR, // Can be linear sampled only if compare mode is set\n })\n\n // Framebuffer to render the shadow map into\n this._shadowMapFB = createFramebufferInfo(\n gl,\n [{ attachment: this._shadowMapTex, attachmentPoint: gl.DEPTH_ATTACHMENT }],\n this._shadowOptions.mapSize,\n this._shadowOptions.mapSize\n )\n }\n\n /**\n * Get a virtual camera that can be used to render a shadow map for this light\n * @param zoomLevel - Zoom level of the camera, default: 30\n * @param aspectRatio - Aspect ratio of the camera, default: 1\n */\n getShadowCamera() {\n if (!this._shadowOptions) {\n return undefined\n }\n\n const moveDist = this._shadowOptions.distance * 0.2\n\n const cam = new Camera(CameraType.ORTHOGRAPHIC, 1.0)\n cam.orthoZoom = this._shadowOptions.zoom\n cam.lookAt = [0, 0, 0]\n cam.position = [-this.direction[0] * moveDist, -this.direction[1] * moveDist, -this.direction[2] * moveDist]\n cam.usedForShadowMap = true\n cam.far = this._shadowOptions.distance\n\n return cam\n }\n\n /**\n * Get the forward view matrix for the virtual camera used to render the shadow map.\n * Returns undefined if shadows are not enabled\n */\n get shadowMatrix() {\n if (!this._shadowOptions) {\n return undefined\n }\n\n const shadowCam = this.getShadowCamera()\n if (!shadowCam) {\n return undefined\n }\n\n const camViewMatrix = shadowCam.matrix\n const shadowMatrix = mat4.multiply(\n mat4.create(),\n shadowCam.projectionMatrix,\n mat4.invert(mat4.create(), camViewMatrix)\n )\n\n return shadowMatrix\n }\n\n /**\n * Are shadows enabled for this light?\n */\n get shadowsEnabled() {\n return this._shadowOptions !== undefined\n }\n\n /**\n * Get the shadow map program, will be undefined if shadows are not enabled\n */\n get shadowMapProgram() {\n return this._shadowMapProgram\n }\n\n /**\n * Get the shadow map framebuffer, will be undefined if shadows are not enabled\n */\n get shadowMapFrameBufffer() {\n return this._shadowMapFB\n }\n\n /**\n * Get the shadow map texture, will be undefined if shadows are not enabled\n */\n get shadowMapTexture() {\n return this._shadowMapTex\n }\n\n /**\n * Get the shadow map options, will be undefined if shadows are not enabled\n */\n get shadowMapOptions() {\n return this._shadowOptions\n }\n}\n\n/*\n * A point light source, doesn't cast shadows but does attenuate with distance\n */\nexport class LightPoint {\n /** Position of the light in world space. */\n public position: XYZ\n\n /** Colour of the light. Default: [1, 1, 1] */\n public colour: RGB\n\n /** Ambient colour of the light. Normally none for point lights. Default [0, 0, 0] */\n public ambient: RGB\n\n /** Light attenuation parameter for constant drop off rate. Default: 0.5 */\n public constant: number\n\n /** Light attenuation parameter for linear drop off rate. Default: 0.018 */\n public linear: number\n\n /** Light attenuation parameter for quadratic drop off rate. Default: 0.0003 */\n public quad: number\n\n /** Is this light enabled? Default: true */\n public enabled: boolean\n\n /**\n * Create a default point light, positioned at the world origin\n * @param position - Position of the light in world space\n * @param colour - Colour of the light\n * @param constant - Attenuation constant drop off rate, default 0.5\n * @param linear - Attenuation linear drop off rate, default 0.018\n * @param quad - Attenuation quadratic drop off rate, default 0.0003\n */\n constructor(position: XYZ, colour: RGB, constant = 0.5, linear = 0.018, quad = 0.0003) {\n this.position = position\n this.colour = colour\n this.constant = constant\n this.linear = linear\n this.quad = quad\n\n // No ambient contribution by default, this can get messy otherwise\n this.ambient = Colours.BLACK\n this.enabled = true\n }\n\n /**\n * Return the base set of uniforms for this light\n */\n public get uniforms() {\n return {\n enabled: this.enabled,\n quad: this.quad,\n position: this.position,\n colour: this.colour,\n ambient: this.ambient,\n constant: this.constant,\n linear: this.linear,\n } as UniformSet\n }\n}\n","// ===== envmap.ts ==========================================================\n// EnvironmentMap class, for rendering reflections\n// Ben Coleman, 2023\n// ============================================================================\n\nimport {\n BufferInfo,\n FramebufferInfo,\n ProgramInfo,\n bindFramebufferInfo,\n createFramebufferInfo,\n createProgramInfo,\n createTexture,\n drawBufferInfo,\n primitives,\n setBuffersAndAttributes,\n setUniforms,\n} from 'twgl.js'\nimport { mat4 } from 'gl-matrix'\nimport log from 'loglevel'\n\nimport { Camera, CameraType } from './camera.ts'\n\nimport fragShaderEnvmap from '../../shaders/envmap/glsl.frag'\nimport vertShaderEnvmap from '../../shaders/envmap/glsl.vert'\nimport { XYZ } from './tuples.ts'\nimport { Context, Stats } from '../index.ts'\n\nexport class EnvironmentMap {\n private programInfo: ProgramInfo\n private gl: WebGL2RenderingContext\n private _texture: WebGLTexture\n private cube: BufferInfo\n\n /**\n * Render the environment map as a background, like a skybox\n */\n public renderAsBackground: boolean\n\n /**\n * Create a new environment map with 6 textures for each side\n * @param gl GL context\n * @param textureURLs Array of 6 texture URLs, in order: +x, -x, +y, -y, +z, -z\n */\n constructor(gl: WebGL2RenderingContext, textureURLs: string[]) {\n this.gl = gl\n\n // Create shader program for special envmap rendering\n this.programInfo = createProgramInfo(gl, [vertShaderEnvmap, fragShaderEnvmap])\n\n // Create the cube\n this.cube = primitives.createCubeBufferInfo(gl, 1)\n this.renderAsBackground = true\n\n log.info(`🏔️ EnvironmentMap created!`)\n\n // Don't go via the texture cache, as cube maps are a special case\n if (textureURLs.length !== 6) {\n throw new Error('💥 Cubemap requires 6 textures')\n }\n\n this._texture = createTexture(gl, {\n target: gl.TEXTURE_CUBE_MAP,\n src: textureURLs,\n min: gl.LINEAR_MIPMAP_LINEAR,\n mag: gl.LINEAR,\n cubeFaceOrder: [\n gl.TEXTURE_CUBE_MAP_POSITIVE_X,\n gl.TEXTURE_CUBE_MAP_NEGATIVE_X,\n gl.TEXTURE_CUBE_MAP_POSITIVE_Y,\n gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,\n gl.TEXTURE_CUBE_MAP_POSITIVE_Z,\n gl.TEXTURE_CUBE_MAP_NEGATIVE_Z,\n ],\n flipY: 0,\n })\n }\n\n /**\n * Render this envmap as a cube in, around the given camera & matrices\n * This is used for rendering the envmap as a background and skybox around the scene\n * @param viewMatrix View matrix\n * @param projMatrix Projection matrix\n * @param camera Camera\n */\n render(viewMatrix: mat4, projMatrix: mat4, camera: Camera) {\n if (!this.renderAsBackground) return\n\n this.gl.useProgram(this.programInfo.program)\n // Note: Disable depth test so envmap is always drawn behind everything else\n this.gl.disable(this.gl.DEPTH_TEST)\n\n const uniforms = {\n u_envMapTex: this._texture,\n u_worldViewProjection: mat4.create(),\n }\n\n const world = mat4.create()\n // Envmap magic 1 - translate envmap is always centered on camera\n mat4.translate(world, world, camera.position)\n // Envmap magic 2 - scale the envmap to be the same size as the camera far plane\n // This means it will always be drawn\n mat4.scale(world, world, [camera.far, camera.far, camera.far])\n\n // Create worldView matrix, used for positioning\n const worldView = mat4.multiply(mat4.create(), viewMatrix, world)\n\n mat4.multiply(uniforms.u_worldViewProjection, projMatrix, worldView)\n\n setBuffersAndAttributes(this.gl, this.programInfo, this.cube)\n setUniforms(this.programInfo, uniforms)\n drawBufferInfo(this.gl, this.cube)\n Stats.drawCallsPerFrame++\n\n this.gl.enable(this.gl.DEPTH_TEST)\n }\n\n get texture(): WebGLTexture {\n return this._texture\n }\n}\n\n/**\n * Used for rendering a dynamic environment map, to create realtime reflections\n * For performance reasons, there is only one dynamic envmap per scene context\n */\nexport class DynamicEnvironmentMap {\n private _texture: WebGLTexture\n private facings: DynamicEnvMapFace[] = []\n private camera: Camera\n\n /**\n * Create a new dynamic environment map\n * @param gl GL context\n * @param size Size of each face of the cube map\n * @param position Position of the center of the cube map, reflections will be rendered from here\n */\n constructor(gl: WebGL2RenderingContext, size: number, position: XYZ, far: number) {\n // The main texture cubemap\n this._texture = createTexture(gl, {\n target: gl.TEXTURE_CUBE_MAP,\n width: size,\n height: size,\n minMag: gl.LINEAR,\n cubeFaceOrder: [\n gl.TEXTURE_CUBE_MAP_POSITIVE_X,\n gl.TEXTURE_CUBE_MAP_NEGATIVE_X,\n gl.TEXTURE_CUBE_MAP_POSITIVE_Y,\n gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,\n gl.TEXTURE_CUBE_MAP_POSITIVE_Z,\n gl.TEXTURE_CUBE_MAP_NEGATIVE_Z,\n ],\n })\n\n // This array holds the 6 faces of the cube map and the framebuffer info plus direction\n this.facings = [\n {\n face: gl.TEXTURE_CUBE_MAP_POSITIVE_X,\n direction: [1, 0, 0],\n buffer: createFramebufferInfo(\n gl,\n [{ attachment: this._texture, target: gl.TEXTURE_CUBE_MAP_POSITIVE_X }, { format: gl.DEPTH_COMPONENT16 }],\n size,\n size\n ),\n },\n {\n face: gl.TEXTURE_CUBE_MAP_NEGATIVE_X,\n direction: [-1, 0, 0],\n buffer: createFramebufferInfo(\n gl,\n [{ attachment: this._texture, target: gl.TEXTURE_CUBE_MAP_NEGATIVE_X }, { format: gl.DEPTH_COMPONENT16 }],\n size,\n size\n ),\n },\n {\n face: gl.TEXTURE_CUBE_MAP_POSITIVE_Y,\n direction: [0, 1, 0],\n buffer: createFramebufferInfo(\n gl,\n [{ attachment: this._texture, target: gl.TEXTURE_CUBE_MAP_POSITIVE_Y }, { format: gl.DEPTH_COMPONENT16 }],\n size,\n size\n ),\n },\n {\n face: gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,\n direction: [0, -1, 0],\n buffer: createFramebufferInfo(\n gl,\n [{ attachment: this._texture, target: gl.TEXTURE_CUBE_MAP_NEGATIVE_Y }, { format: gl.DEPTH_COMPONENT16 }],\n size,\n size\n ),\n },\n {\n face: gl.TEXTURE_CUBE_MAP_POSITIVE_Z,\n direction: [0, 0, 1],\n buffer: createFramebufferInfo(\n gl,\n [{ attachment: this._texture, target: gl.TEXTURE_CUBE_MAP_POSITIVE_Z }, { format: gl.DEPTH_COMPONENT16 }],\n size,\n size\n ),\n },\n {\n face: gl.TEXTURE_CUBE_MAP_NEGATIVE_Z,\n direction: [0, 0, -1],\n buffer: createFramebufferInfo(\n gl,\n [{ attachment: this._texture, target: gl.TEXTURE_CUBE_MAP_NEGATIVE_Z }, { format: gl.DEPTH_COMPONENT16 }],\n size,\n size\n ),\n },\n ]\n\n this.camera = new Camera(CameraType.PERSPECTIVE)\n this.camera.position = position\n this.camera.fov = 90 // 90 degree FOV for cubemap to work properly\n\n // IMPORTANT: Mark this as a special camera used for envmaps\n this.camera.usedForEnvMap = true\n\n this.camera.far = far\n }\n\n /** Get the texture of the environment cubemap */\n get texture(): WebGLTexture {\n return this._texture\n }\n\n /**\n * This is used to position the camera for creating the reflection map\n * @param position Position of the center of the cube map\n */\n set position(pos: XYZ) {\n this.camera.position = pos\n }\n\n /**\n * Update the environment map, by rendering the scene from the given position into the cubemap texture\n * @param ctx GSOTS Context\n */\n update(gl: WebGL2RenderingContext, ctx: Context) {\n // Render each face of the cubemap into the texture & framebuffer\n // NOTE: This requires SIX calls to renderWithCamera!\n for (const facing of this.facings) {\n // Update the camera to look in the direction of the face\n this.camera.lookAt = [\n this.camera.position[0] + facing.direction[0],\n this.camera.position[1] + facing.direction[1],\n this.camera.position[2] + facing.direction[2],\n ]\n\n // Stops the camera from flipping upside down and other weirdness\n this.camera.up = [0, -1, 0]\n if (facing.face === gl.TEXTURE_CUBE_MAP_NEGATIVE_Y) {\n this.camera.up = [0, 0, -1]\n }\n if (facing.face === gl.TEXTURE_CUBE_MAP_POSITIVE_Y) {\n this.camera.up = [0, 0, 1]\n }\n\n bindFramebufferInfo(gl, facing.buffer)\n ctx.renderWithCamera(this.camera)\n }\n }\n}\n\n/**\n * Internal type for storing a dynamic envmap facing info\n */\nexport type DynamicEnvMapFace = {\n face: number\n direction: XYZ\n buffer: FramebufferInfo\n}\n","#version 300 es\n\n// ============================================================================\n// Environment map fragment shader\n// Ben Coleman, 2023\n// ============================================================================\n\nprecision highp float;\n\nin vec3 v_texCoord;\n\nuniform samplerCube u_envMapTex;\n\nout vec4 outColour;\n\nvoid main() {\n // Use the texture cube map as the colour\n // Note: We don't need to do any lighting calculations here\n outColour = texture(u_envMapTex, v_texCoord);\n}\n","#version 300 es\n\n// ============================================================================\n// Environment map vertex shader\n// Ben Coleman, 2023\n// ============================================================================\n\nprecision highp float;\n\nin vec4 position;\n\nuniform mat4 u_worldViewProjection;\n\nout vec3 v_texCoord;\n\nvoid main() {\n // This essentially is what makes the envmap work, texCoords\n // are taken from the vertex position\n v_texCoord = position.xyz;\n\n gl_Position = u_worldViewProjection * position;\n}\n","// ===== instance.ts ==========================================================\n// Instance class, holds position, rotation, scale etc for a renderable\n// Ben Coleman, 2023\n// ============================================================================\n\nimport { mat4 } from 'gl-matrix'\nimport { UniformSet } from '../core/gl.ts'\nimport { Renderable } from './types.ts'\nimport { Material } from '../engine/material.ts'\nimport { XYZ } from '../engine/tuples.ts'\nimport { ProgramInfo } from 'twgl.js'\n\n/**\n * An instance of thing in the world to be rendered, with position, rotation, scale etc\n */\nexport class Instance {\n /** Main renderable thing this instance represents */\n public readonly renderable: Renderable | undefined\n\n /** Position in world space */\n public position: XYZ | undefined\n\n /** Scale in world space */\n public scale: XYZ | undefined\n\n /** Should this instance be rendered and drawn */\n public enabled = true\n\n /** Should this instance cast a shadow */\n public castShadow = true\n\n /** Flip all textures on this instance on the X axis */\n public flipTextureX = false\n\n /** Flip all textures on this instance on the Y axis */\n public flipTextureY = false\n\n /** Material override. This will override the renderable's material.\n * This is only useful on simple models that probably consist of one surface */\n public material?: Material\n\n /** Metadata for this instance, can be used to store anything */\n public metadata: Record = {}\n\n /** Rotation in radians around X, Y, Z axis */\n private rotate: XYZ | undefined\n\n /**\n * Create a new instace of a renderable thing\n * @param {Renderable} renderable - Renderable to use for this instance\n */\n constructor(renderable: Renderable) {\n this.renderable = renderable\n }\n\n /** Rotate this instance around the X axis*/\n rotateX(angle: number) {\n if (!this.rotate) this.rotate = [0, 0, 0]\n this.rotate[0] += angle\n }\n\n /** Rotate this instance around the Y axis*/\n rotateY(angle: number) {\n if (!this.rotate) this.rotate = [0, 0, 0]\n this.rotate[1] += angle\n }\n\n /** Rotate this instance around the Z axis, in radians*/\n rotateZ(angle: number) {\n if (!this.rotate) this.rotate = [0, 0, 0]\n this.rotate[2] += angle\n }\n\n /** Rotate this instance around the X axis by a given angle in degrees */\n rotateZDeg(angle: number) {\n this.rotateZ((angle * Math.PI) / 180)\n }\n\n /** Rotate this instance around the Y axis by a given angle in degrees */\n rotateYDeg(angle: number) {\n this.rotateY((angle * Math.PI) / 180)\n }\n\n /** Rotate this instance around the Z axis by a given angle in degrees */\n rotateXDeg(angle: number) {\n this.rotateX((angle * Math.PI) / 180)\n }\n\n /**\n * Render this instance in the world\n * @param {WebGL2RenderingContext} gl - WebGL context to render into\n * @param {UniformSet} uniforms - Map of uniforms to pass to shader\n */\n render(gl: WebGL2RenderingContext, uniforms: UniformSet, programOverride?: ProgramInfo) {\n if (!this.enabled) return\n if (!this.renderable) return\n if (!gl) return\n\n // HACK: As programOverride is CURRENTLY only used for shadow map rendering\n // We need a better way to to know if we are rendering a shadow map!!\n if (programOverride && !this.castShadow) {\n return\n }\n\n // Local instance transforms are applied in this order to form the world matrix\n const scale = mat4.create()\n const rotate = mat4.create()\n const translate = mat4.create()\n\n // Apply scale, rotate, translate in that order\n if (this.scale) mat4.scale(scale, scale, this.scale)\n if (this.rotate) {\n mat4.rotateX(rotate, rotate, this.rotate[0])\n mat4.rotateY(rotate, rotate, this.rotate[1])\n mat4.rotateZ(rotate, rotate, this.rotate[2])\n }\n if (this.position) mat4.translate(translate, translate, this.position)\n\n // Combine all transforms into world matrix, in reverse order\n const world = translate\n mat4.multiply(world, world, rotate)\n mat4.multiply(world, world, scale)\n\n // Populate u_world - used for normals & shading\n uniforms.u_world = world\n\n // Populate u_worldInverseTranspose - used for normals & shading\n mat4.invert(uniforms.u_worldInverseTranspose, world)\n mat4.transpose(uniforms.u_worldInverseTranspose, uniforms.u_worldInverseTranspose)\n\n // Create worldView matrix, used for positioning\n const worldView = mat4.multiply(mat4.create(), uniforms.u_view, world)\n\n // Finally populate u_worldViewProjection used for rendering\n mat4.multiply(uniforms.u_worldViewProjection, uniforms.u_proj, worldView)\n\n // Apply per instance texture flip flags\n uniforms.u_flipTextureX = this.flipTextureX\n uniforms.u_flipTextureY = this.flipTextureY\n\n // Render the renderable thing wrapped by this instance\n this.renderable.render(gl, uniforms, this.material, programOverride)\n }\n}\n","// ===== stats.ts =======================================================\n// Global singleton for keeping track of stats, timers performance\n// Ben Coleman, 2023\n// ======================================================================\n\nexport const Stats = {\n drawCallsPerFrame: 0,\n instances: 0,\n triangles: 0,\n\n prevTime: 0,\n deltaTime: 0,\n totalTime: 0,\n\n resetPerFrame() {\n Stats.drawCallsPerFrame = 0\n },\n\n updateTime(now: number) {\n Stats.deltaTime = now - Stats.prevTime // Get smoothed time difference\n Stats.prevTime = now\n Stats.totalTime += Stats.deltaTime\n },\n\n get FPS() {\n return Math.round(1 / Stats.deltaTime)\n },\n\n get totalTimeRound() {\n return Math.round(Stats.totalTime)\n },\n}\n","// ===== billboard.ts =========================================================\n// For drawing 2D billboards, like trees, grass, etc\n// Ben Coleman, 2023\n// ============================================================================\n\nimport {\n ProgramInfo,\n drawBufferInfo,\n setBuffersAndAttributes,\n setUniforms,\n primitives,\n BufferInfo,\n createBufferInfoFromArrays,\n} from 'twgl.js'\nimport { UniformSet } from '../core/gl.ts'\nimport { Renderable } from './types.ts'\nimport { Material } from '../engine/material.ts'\nimport { Stats } from '../core/stats.ts'\nimport { ProgramCache } from '../index.ts'\nimport { mat4, vec3 } from 'gl-matrix'\n\n/** Billboarding modes, most things will ue NONE */\nexport enum BillboardType {\n SPHERICAL,\n CYLINDRICAL,\n}\n\n/**\n * A simple 2D billboard, like a tree or grass. These are square by default, but can be scaled XY if needed.\n * Both cylindrical and spherical billboards are supported. You must assign material with a texture\n * to be rendered as a sprite on the billboard\n * @see http://www.opengl-tutorial.org/intermediate-tutorials/billboards-particles/billboards/\n */\nexport class Billboard implements Renderable {\n protected bufferInfo: BufferInfo\n private programInfo: ProgramInfo\n public material: Material\n public tex: WebGLTexture | undefined\n public type: BillboardType = BillboardType.CYLINDRICAL\n\n /** Creates a square billboard */\n constructor(gl: WebGL2RenderingContext, type: BillboardType, material: Material, size: number) {\n this.material = material\n this.type = type\n\n // Create quad vertices\n const verts = primitives.createXYQuadVertices(size, 0, size / 2)\n\n // Flip Y axis, so texture is not upside down\n for (let i = 1; i < verts.texcoord.length; i += 2) {\n verts.texcoord[i] = 1 - verts.texcoord[i]\n }\n\n this.bufferInfo = createBufferInfoFromArrays(gl, verts)\n\n // Use the billboard shader for this renderable\n this.programInfo = ProgramCache.instance.get(ProgramCache.PROG_BILLBOARD)\n }\n\n /**\n * Render is used draw this billboard, this is called from the Instance that wraps\n * this renderable\n */\n render(gl: WebGL2RenderingContext, uniforms: UniformSet, materialOverride?: Material): void {\n // We ignore programOverride here, as we always use the billboard shader\n const programInfo = this.programInfo\n\n gl.useProgram(programInfo.program)\n\n if (materialOverride === undefined) {\n this.material.apply(programInfo)\n } else {\n materialOverride.apply(programInfo)\n }\n\n // We're doubling up on work done in the Instance class here, hard to get around this\n const worldView = mat4.multiply(mat4.create(), uniforms.u_view, uniforms.u_world)\n\n // Extract scale from worldView matrix, before we zap it\n const scale = mat4.getScaling(vec3.create(), worldView)\n\n // For CYLINDRICAL billboarding, we need to remove some parts of the worldView matrix\n // See: https://www.geeks3d.com/20140807/billboarding-vertex-shader-glsl/\n worldView[0] = scale[0]\n worldView[1] = 0\n worldView[2] = 0\n worldView[8] = 0\n worldView[9] = 0\n worldView[10] = scale[2]\n\n if (this.type == BillboardType.SPHERICAL) {\n // For SPHERICAL billboarding, we remove some more\n worldView[4] = 0\n worldView[5] = scale[1]\n worldView[6] = 0\n }\n\n // We're doubling up on work again :/\n mat4.multiply(uniforms.u_worldViewProjection, uniforms.u_proj, worldView)\n\n setBuffersAndAttributes(gl, programInfo, this.bufferInfo)\n setUniforms(programInfo, uniforms)\n\n drawBufferInfo(gl, this.bufferInfo)\n Stats.drawCallsPerFrame++\n }\n}\n","// ===== material.ts ==========================================================\n// Represents a material, with all the properties from the MTL file\n// Ben Coleman, 2023\n// ============================================================================\n\nimport { ProgramInfo, setUniforms } from 'twgl.js'\nimport { RGB } from './tuples.ts'\nimport { MtlMaterial } from '../parsers/mtl-parser.ts'\nimport { UniformSet } from '../core/gl.ts'\nimport { TextureCache } from '../core/cache.ts'\n\nexport class Material {\n /**\n * Ambient colour will be multiplied with the ambient light level & colour\n */\n public ambient: RGB\n\n /**\n * Diffuse colour will be multiplied with the diffuse texture\n * @default [1, 1, 1]\n */\n public diffuse: RGB\n\n /**\n * Specular colour will be multiplied with the specular texture\n * @default [0, 0, 0]\n */\n public specular: RGB\n\n /**\n * Emissive colour will be added to the final colour, use for glowing materials\n */\n public emissive: RGB\n\n /**\n * Shininess, for size of specular highlights\n * @default 20\n */\n public shininess: number\n\n /**\n * Opacity, 0.0 to 1.0\n * @default 1.0\n */\n public opacity: number\n\n /**\n * Reflectivity, 0.0 to 1.0\n * @default 0.0\n */\n public reflectivity: number\n\n /**\n * Diffuse texture map\n * @default \"1 pixel white texture\"\n */\n public diffuseTex?: WebGLTexture\n\n /**\n * Specular texture map\n * @default \"1 pixel white texture\"\n */\n public specularTex?: WebGLTexture\n\n /**\n * Normal texture map\n * @default \"1 pixel white texture\"\n */\n public normalTex?: WebGLTexture\n\n /**\n * Create a new material with default diffuse white colour\n */\n constructor() {\n this.ambient = [1, 1, 1]\n this.diffuse = [1, 1, 1]\n this.specular = [0, 0, 0]\n this.emissive = [0, 0, 0]\n\n this.shininess = 20\n this.opacity = 1.0\n this.reflectivity = 0.0\n\n // 1 pixel white texture allows for solid colour & flat materials\n this.diffuseTex = TextureCache.instance.get('_defaults/white')\n this.specularTex = TextureCache.instance.get('_defaults/white')\n }\n\n /**\n * Create a new material from a raw MTL material\n * @param rawMtl Raw MTL material\n * @param basePath Base path for locating & loading textures in MTL file\n * @param filter Apply texture filtering to textures, default: true\n * @param flipY Flip the Y axis of textures, default: false\n */\n static fromMtl(rawMtl: MtlMaterial, basePath: string, filter = true, flipY = false) {\n const m = new Material()\n\n m.ambient = rawMtl.ka ? rawMtl.ka : [1, 1, 1]\n m.diffuse = rawMtl.kd ? rawMtl.kd : [1, 1, 1]\n m.specular = rawMtl.ks ? rawMtl.ks : [0, 0, 0]\n m.emissive = rawMtl.ke ? rawMtl.ke : [0, 0, 0]\n m.shininess = rawMtl.ns ? rawMtl.ns : 0\n m.opacity = rawMtl.d ? rawMtl.d : 1.0\n\n if (rawMtl.texDiffuse) {\n m.diffuseTex = TextureCache.instance.getCreate(`${basePath}/${rawMtl.texDiffuse}`, filter, flipY)\n }\n\n if (rawMtl.texSpecular) {\n m.specularTex = TextureCache.instance.getCreate(`${basePath}/${rawMtl.texSpecular}`, filter, flipY)\n }\n\n if (rawMtl.texNormal) {\n m.normalTex = TextureCache.instance.getCreate(`${basePath}/${rawMtl.texNormal}`, filter, flipY)\n }\n\n // This is a kludge, a guess; if illum is 3 or more and Ks is set, then we have\n // A reflective material of some kind\n if (rawMtl.illum && rawMtl.illum > 2) {\n m.reflectivity = (m.specular[0] + m.specular[1] + m.specular[2]) / 3\n }\n\n return m\n }\n\n /**\n * Create a basic Material with a solid diffuse colour\n */\n static createSolidColour(r: number, g: number, b: number) {\n const m = new Material()\n m.diffuse = [r, g, b]\n\n return m\n }\n\n /**\n * Create a new Material with a texture map loaded from a URL\n */\n static createBasicTexture(url: string, filter = true, flipY = false) {\n const m = new Material()\n\n m.diffuseTex = TextureCache.instance.getCreate(url, filter, flipY)\n\n return m\n }\n\n /**\n * Add a specular texture map to existing material, probably created with createBasicTexture\n * @param url\n * @param filter\n */\n addSpecularTexture(url: string, filter = true, flipY = false) {\n this.specularTex = TextureCache.instance.getCreate(url, filter, flipY)\n this.specular = [1, 1, 1]\n this.shininess = 20\n }\n\n /**\n * Add a normal texture map to existing material, probably created with createBasicTexture\n * @param url\n * @param filter\n */\n addNormalTexture(url: string, filter = true, flipY = false) {\n this.normalTex = TextureCache.instance.getCreate(url, filter, flipY)\n }\n\n /** Create a simple RED Material */\n static get RED() {\n const m = Material.createSolidColour(1.0, 0.0, 0.0)\n return m\n }\n\n /** Create a simple GREEN Material */\n static get GREEN() {\n return Material.createSolidColour(0.0, 1.0, 0.0)\n }\n\n /** Create a simple BLUE Material */\n static get BLUE() {\n const m = Material.createSolidColour(0.0, 0.0, 1.0)\n\n return m\n }\n\n /** Create a simple BLUE Material */\n static get WHITE() {\n const m = Material.createSolidColour(1.0, 1.0, 1.0)\n\n return m\n }\n\n /**\n * Applies the material to the given program as a uniform struct\n */\n apply(programInfo: ProgramInfo, uniformSuffix = '') {\n const uni = {\n [`u_mat${uniformSuffix}`]: this.uniforms,\n }\n\n setUniforms(programInfo, uni)\n }\n\n /**\n * Return the base set of uniforms for this material\n */\n get uniforms(): UniformSet {\n return {\n ambient: this.ambient,\n diffuse: this.diffuse,\n specular: this.specular,\n emissive: this.emissive,\n shininess: this.shininess,\n opacity: this.opacity,\n reflectivity: this.reflectivity,\n diffuseTex: this.diffuseTex ? this.diffuseTex : null,\n specularTex: this.specularTex ? this.specularTex : null,\n normalTex: this.normalTex ? this.normalTex : null,\n hasNormalTex: this.normalTex ? true : false,\n } as UniformSet\n }\n}\n","// ======== primitive.ts ======================================================\n// Main model class, holds a list of parts, each with a material\n// Models are parsed from OBJ files\n// Ben Coleman, 2023\n// ============================================================================\n\nimport {\n ProgramInfo,\n drawBufferInfo,\n setBuffersAndAttributes,\n setUniforms,\n primitives,\n BufferInfo,\n createBufferInfoFromArrays,\n} from 'twgl.js'\nimport { UniformSet } from '../core/gl.ts'\nimport { Renderable } from './types.ts'\nimport { Material } from '../engine/material.ts'\nimport { Stats } from '../core/stats.ts'\nimport { ProgramCache } from '../core/cache.ts'\n\n/**\n * A simple primitive 3D object, like a sphere or cube\n */\nexport abstract class Primitive implements Renderable {\n protected bufferInfo: BufferInfo | undefined\n private programInfo: ProgramInfo\n public material: Material\n public tex: WebGLTexture | undefined\n protected triangles: number\n\n constructor() {\n this.material = new Material()\n this.triangles = 0\n this.programInfo = ProgramCache.instance.default\n }\n\n get triangleCount(): number {\n return this.triangles\n }\n\n /**\n * Render is used draw this primitive, this is called from the Instance that wraps\n * this renderable.\n */\n render(\n gl: WebGL2RenderingContext,\n uniforms: UniformSet,\n materialOverride?: Material,\n programOverride?: ProgramInfo\n ): void {\n if (!this.bufferInfo) return\n\n const programInfo = programOverride || this.programInfo\n gl.useProgram(programInfo.program)\n\n if (materialOverride === undefined) {\n this.material.apply(programInfo)\n } else {\n materialOverride.apply(programInfo)\n }\n\n setBuffersAndAttributes(gl, programInfo, this.bufferInfo)\n setUniforms(programInfo, uniforms)\n\n drawBufferInfo(gl, this.bufferInfo)\n Stats.drawCallsPerFrame++\n }\n}\n\n/**\n * A simple sphere primitive with a given radius and subdivisions\n */\nexport class PrimitiveSphere extends Primitive {\n /**\n * Create a new sphere primitive\n * @param gl WebGL2RenderingContext\n * @param radius Radius of the sphere\n * @param subdivisionsH Number of horizontal subdivisions\n * @param subdivisionsV Number of vertical subdivisions\n */\n constructor(gl: WebGL2RenderingContext, radius: number, subdivisionsH: number, subdivisionsV: number) {\n super()\n\n this.bufferInfo = primitives.createSphereBufferInfo(gl, radius, subdivisionsH, subdivisionsV)\n\n this.triangles += this.bufferInfo.numElements / 3\n }\n}\n\n/**\n * A simple cube primitive with a given size\n */\nexport class PrimitiveCube extends Primitive {\n /**\n * Create a new cube primitive\n * @param gl WebGL2RenderingContext\n * @param size Size of the cube\n */\n constructor(gl: WebGL2RenderingContext, size: number) {\n super()\n\n this.bufferInfo = primitives.createCubeBufferInfo(gl, size)\n\n this.triangles += this.bufferInfo.numElements / 3\n }\n}\n\n/**\n * A simple plane primitive with a given size, subdivisions & tiling factor\n */\nexport class PrimitivePlane extends Primitive {\n /**\n * Create a new plane primitive\n * @param gl WebGL2RenderingContext\n * @param width Width of the plane\n * @param height Height of the plane\n * @param subdivisionsW Number of horizontal subdivisions\n * @param subdivisionsH Number of vertical subdivisions\n * @param tilingFactor Number of times to tile the texture across the plane\n */\n constructor(\n gl: WebGL2RenderingContext,\n width: number,\n height: number,\n subdivisionsW: number,\n subdivisionsH: number,\n tilingFactor: number\n ) {\n super()\n\n const verts = primitives.createPlaneVertices(width, height, subdivisionsW, subdivisionsH)\n\n // Mutate the texture coords to tile the texture\n for (let i = 0; i < verts.texcoord.length; i++) {\n verts.texcoord[i] = verts.texcoord[i] * tilingFactor\n }\n\n this.bufferInfo = createBufferInfoFromArrays(gl, verts)\n this.triangles += this.bufferInfo.numElements / 3\n }\n}\n\n/**\n * A simple cylinder primitive with a given radius, height and subdivisions\n */\nexport class PrimitiveCylinder extends Primitive {\n /**\n * Create a new cylinder primitive\n * @param gl WebGL2RenderingContext\n * @param radius Radius of the cylinder\n * @param height Height of the cylinder\n * @param subdivisionsR Subdivisions around the cylinder\n * @param subdivisionsV Subdivisions vertically\n * @param caps Should the cylinder have caps\n */\n constructor(\n gl: WebGL2RenderingContext,\n radius: number,\n height: number,\n subdivisionsR: number,\n subdivisionsV: number,\n caps: boolean\n ) {\n super()\n\n this.bufferInfo = primitives.createCylinderBufferInfo(gl, radius, height, subdivisionsR, subdivisionsV, caps, caps)\n\n this.triangles += this.bufferInfo.numElements / 3\n }\n}\n","// ===== model.ts =============================================================\n// Main model class, holds a list of parts, each with a material\n// Models are parsed from OBJ files\n// Ben Coleman, 2023\n// ============================================================================\n\nimport {\n BufferInfo,\n ProgramInfo,\n createBufferInfoFromArrays,\n drawBufferInfo,\n setBuffersAndAttributes,\n setUniforms,\n} from 'twgl.js'\nimport log from 'loglevel'\n\nimport { Material } from '../engine/material.ts'\nimport { parseMTL } from '../parsers/mtl-parser.ts'\nimport { parseOBJ } from '../parsers/obj-parser.ts'\nimport { fetchFile } from '../core/files.ts'\nimport { getGl, UniformSet } from '../core/gl.ts'\nimport { Renderable } from './types.ts'\nimport { Stats } from '../core/stats.ts'\nimport { ProgramCache } from '../core/cache.ts'\n\n/**\n * Holds a 3D model, as a list of parts, each with a material\n * Plus map of named materials\n */\nexport class Model implements Renderable {\n private programInfo: ProgramInfo\n private readonly parts = [] as ModelPart[]\n private readonly materials = {} as Record\n private triangles: number\n\n /** Name of the model, usually the filename without the extension */\n public readonly name: string\n\n /**\n * Constructor is private, use static `parse()` method instead\n */\n private constructor(name: string) {\n this.name = name\n this.triangles = 0\n this.programInfo = ProgramCache.instance.default\n }\n\n /**\n * Render is used draw this model, this is called from the Instance that wraps\n * this renderable.\n */\n render(\n gl: WebGL2RenderingContext,\n uniforms: UniformSet,\n materialOverride?: Material,\n programOverride?: ProgramInfo\n ): void {\n const programInfo = programOverride || this.programInfo\n gl.useProgram(programInfo.program)\n\n // Render each part of the model\n for (const part of this.parts) {\n const bufferInfo = part.bufferInfo\n\n if (materialOverride === undefined) {\n // Get the named material for this part\n let material = this.materials[part.materialName]\n\n // Fall back to default material if not found\n if (!material) {\n material = this.materials.__default\n }\n\n material.apply(programInfo)\n } else {\n materialOverride.apply(programInfo)\n }\n\n setBuffersAndAttributes(gl, programInfo, bufferInfo)\n setUniforms(programInfo, uniforms)\n\n drawBufferInfo(gl, bufferInfo)\n Stats.drawCallsPerFrame++\n }\n }\n\n /** Simple getter for the number of triangles in the model */\n get triangleCount(): number {\n return this.triangles\n }\n\n /**\n * Parse an OBJ file & MTL material libraries, returns a new Model\n * @param {string} path - The path to the OBJ file\n * @param {string} objFilename - The name of the OBJ file\n * @param {boolean} filterTextures - Apply texture filtering to textures, default: true\n * @param {boolean} flipTextureY - Flip the Y axis of textures as they are loaded, default: false\n * @param {boolean} flipUV - Flip the UV coords of the model in the vertex/mesh data, default: true\n */\n static async parse(path = '.', objFilename: string, filterTextures = true, flipTextureY = false, flipUV = true) {\n const startTime = performance.now()\n\n // Create a new model with the name of the file\n const name = objFilename.split('.')[0]\n const model = new Model(name)\n\n // Load the OBJ file from URL\n let objFile: string\n try {\n objFile = await fetchFile(`${path}/${objFilename}`)\n } catch (err) {\n throw new Error(`💥 Unable to load file '${path}/${objFilename}'`)\n }\n\n // Try to parse the OBJ file\n // NOTE: We flip texture coords by default, this is because most OBJ files don't work with OpenGL\n const objData = parseOBJ(objFile, flipUV)\n\n if (!objData.geometries || objData.geometries.length === 0) {\n throw new Error(`💥 Error parsing '${objFilename}', might not be a OBJ file`)\n }\n\n // We assume that the OBJ file has a SINGLE material library\n // This is a good assumption for nearly all files I've seen\n if (objData.matLibNames && objData.matLibNames.length > 0) {\n try {\n const mtlFile = await fetchFile(`${path}/${objData.matLibNames[0]}`)\n const materialsRawList = parseMTL(mtlFile)\n\n for (const [matName, matRaw] of materialsRawList) {\n model.materials[matName] = Material.fromMtl(matRaw, path, filterTextures, flipTextureY)\n }\n } catch (err) {\n log.warn(`💥 Unable to load material library ${objData.matLibNames[0]}`)\n }\n }\n\n // Fall back default material\n model.materials.__default = new Material()\n model.materials.__default.diffuse = [0.1, 0.6, 0.9]\n\n // This really should already been memoized by the context at this point\n const gl = getGl()\n\n if (!gl) {\n throw new Error('💥 Unable to get WebGL context')\n }\n\n for (const g of objData.geometries) {\n // TODO: One day add tangent generation\n const bufferInfo = createBufferInfoFromArrays(gl, g.data)\n model.parts.push(new ModelPart(bufferInfo, g.material))\n }\n\n log.debug(\n `♟️ Model '${objFilename}' loaded with ${model.parts.length} parts, ${\n Object.keys(model.materials).length\n } materials in ${((performance.now() - startTime) / 1000).toFixed(2)}s`\n )\n\n model.triangles = objData.triangles\n return model\n }\n\n /**\n * Get list of all material names in this model used by all parts\n * @returns {string[]} - List of material names\n */\n get materialNames(): string[] {\n return Object.keys(this.materials)\n }\n\n /**\n * Get number of parts in this model\n */\n get partsCount(): number {\n return this.parts.length\n }\n\n /**\n * Get list of parts in this model, names are the material names\n * @returns {string[]} - List of part material names\n */\n get partList(): string[] {\n return this.parts.map((p) => p.materialName)\n }\n\n /**\n * Can modify & override an existing named material\n * @param {string} name - Name of the material to modify\n * @param {Material} material - New material to use\n */\n setNamedMaterial(name: string, material: Material): void {\n this.materials[name] = material\n }\n\n /**\n * Get a named material\n * @param {string} name - Name of the material to get\n */\n getNamedMaterial(name: string): Material {\n return this.materials[name]\n }\n}\n\n/**\n * Holds part of a model, as the WebGL buffers needed to render it\n * Plus the material name associated with this part\n */\nexport class ModelPart {\n public readonly bufferInfo: BufferInfo\n public readonly materialName: string\n\n /**\n * @param {twgl.BufferInfo} bufferInfo - WebGL buffer info for this model part\n * @param {string} materialName - Name of the material associated with this part\n */\n constructor(bufferInfo: BufferInfo, materialName: string) {\n this.bufferInfo = bufferInfo\n this.materialName = materialName\n }\n}\n","// ===== mtl-parser.mjs ==========================================================\n// A simple MTL parser\n// Taken from https://webglfundamentals.org/webgl/lessons/webgl-load-obj-w-mtl.html\n// Ben Coleman, 2023\n// ===============================================================================\n\n/**\n * A \"raw\" material fetched from the MTL parser, don't use this directly\n */\nexport type MtlMaterial = {\n illum?: number\n\n ns?: number\n d?: number\n\n ka?: [number, number, number]\n kd?: [number, number, number]\n ks?: [number, number, number]\n ke?: [number, number, number]\n\n texDiffuse?: string\n texSpecular?: string\n texNormal?: string\n}\n\n/**\n * Parse an MTL file returning a map of materials.\n * The returned {@link typescript!MtlMaterial} should be passed to new Material() to create a material\n * @param {string} mtlFile - The MTL file as a string\n * @returns {Map} - A map of materials\n */\nexport function parseMTL(mtlFile: string): Map {\n const materials = new Map()\n let material = {} as MtlMaterial\n\n const keywords = {\n newmtl(_: string[], unparsedArgs: string) {\n material = {} as MtlMaterial\n materials.set(unparsedArgs, material)\n },\n\n Ns(parts: string[]) {\n material.ns = parseFloat(parts[0])\n },\n Ka(parts: string[]) {\n material.ka = <[number, number, number]>parts.map(parseFloat)\n },\n Kd(parts: string[]) {\n material.kd = <[number, number, number]>parts.map(parseFloat)\n },\n Ks(parts: string[]) {\n material.ks = <[number, number, number]>parts.map(parseFloat)\n },\n // This is a non-standard addition, but semi-official\n Ke(parts: string[]) {\n material.ke = <[number, number, number]>parts.map(parseFloat)\n },\n Ni() {\n // Not used\n // Material.ni = parseFloat(parts[0])\n },\n d(parts: string[]) {\n material.d = parseFloat(parts[0])\n },\n illum(parts: string[]) {\n material.illum = parseInt(parts[0])\n },\n map_Kd(_: string[], unparsedArgs: string) {\n material.texDiffuse = unparsedArgs\n },\n map_Ks(_: string[], unparsedArgs: string) {\n material.texSpecular = unparsedArgs\n },\n map_bump(_: string[], unparsedArgs: string) {\n material.texNormal = unparsedArgs\n },\n map_Bump(_: string[], unparsedArgs: string) {\n material.texNormal = unparsedArgs\n },\n } as Record void>\n\n const keywordRE = /(\\w*)(?: )*(.*)/\n const lines = mtlFile.split('\\n')\n\n for (let lineNo = 0; lineNo < lines.length; ++lineNo) {\n const line = lines[lineNo].trim()\n if (line === '' || line.startsWith('#')) {\n continue\n }\n\n const m = keywordRE.exec(line)\n if (!m) {\n continue\n }\n\n const [, keyword, unparsedArgs] = m\n const parts = line.split(/\\s+/).slice(1)\n\n const handler = keywords[keyword]\n if (!handler) {\n // Console.warn('unhandled keyword:', keyword)\n continue\n }\n\n handler(parts, unparsedArgs)\n }\n\n return materials\n}\n","// ===== obj-parser.mjs ==========================================================\n// A simple OBJ parser, works well, but FAR from comprehensive\n// Taken from https://webglfundamentals.org/webgl/lessons/webgl-obj-loader.html\n// Ben Coleman, 2023\n// ===============================================================================\n\nconst keywordRE = /(\\w*)(?: )*(.*)/\n\n/**\n * ParseResult is the result of parsing an OBJ file\n */\nexport type ParseResult = {\n /** List of material libs (MTL files) */\n matLibNames: string[]\n\n /** List of geometries, each with a material name and vertex data */\n geometries: Geometry[]\n\n /** Total number of triangles in the OBJ file */\n triangles: number\n}\n\n/**\n * Each OBJ file is made up of a list of geometries, each with a material name.\n * These can be thought of as parts of the overall model.\n */\nexport type Geometry = {\n /** Name of the material for this geometry part */\n material: string\n\n /** Vertex data for this geometry part, ready for turning into an BufferInfo in twgl.js */\n data: {\n position: number[]\n texcoord?: number[]\n normal: number[]\n tangent?: number[]\n }\n}\n\n/**\n * Parse an OBJ file returning a list of geometries and materials libs\n * @param {string} objFile - The OBJ file as a string\n * @param {boolean} flipUV - Flip the V texcoord axis, for OpenGL\n */\nexport function parseOBJ(objFile: string, flipUV: boolean) {\n const lines = objFile.split('\\n')\n\n const objPositions = [[0, 0, 0]]\n const objTexcoords = [[0, 0]]\n const objNormals = [[0, 0, 0]]\n\n // Same order as `f` indices\n const objVertexData = [objPositions, objTexcoords, objNormals]\n\n let triangles = 0\n\n // Same order as `f` indices\n let webglVertexData = [\n [], // Position\n [], // Texcoord\n [], // Normal\n ] as number[][]\n\n const geometries = Array()\n let geometry = {} as Geometry\n let material = '__default'\n const materialLibs = Array()\n\n const keywords = {\n v(parts: string[]) {\n objPositions.push(parts.map(parseFloat))\n },\n\n vn(parts: string[]) {\n objNormals.push(parts.map(parseFloat))\n },\n\n vt(parts: string[]) {\n // Only 2D texcoords supported, so ignore the 3rd if present\n // Also handle UV flip in the V direction (Y axis) for OpenGL\n if (flipUV) {\n objTexcoords.push([parseFloat(parts[0]), 1.0 - parseFloat(parts[1])])\n } else {\n objTexcoords.push([parseFloat(parts[0]), parseFloat(parts[1])])\n }\n },\n\n f(parts: string[]) {\n triangles++\n setGeometry()\n const numTriangles = parts.length - 2\n for (let tri = 0; tri < numTriangles; ++tri) {\n addVertex(parts[0])\n addVertex(parts[tri + 1])\n addVertex(parts[tri + 2])\n }\n },\n\n usemtl(_: string[], unparsedArgs: string) {\n material = unparsedArgs\n newGeometry()\n },\n\n mtllib(_: string[], unparsedArgs: string) {\n materialLibs.push(unparsedArgs)\n },\n\n // Not used, but suppress warnings\n s() {\n return\n },\n\n o() {\n return\n },\n\n g() {\n return\n },\n\n l() {\n return\n },\n } as Record void>\n\n /**\n * Updates webglVertexData per vertex\n * @param {string} vert - String in the form of \"v/vt/vn\" as per OBJ spec\n */\n function addVertex(vert: string) {\n const ptn = vert.split('/')\n\n ptn.forEach((objIndexStr, i) => {\n if (!objIndexStr) {\n return\n }\n\n const objIndex = parseInt(objIndexStr)\n const index = objIndex + (objIndex >= 0 ? 0 : objVertexData[i].length)\n\n webglVertexData[i].push(...objVertexData[i][index])\n })\n }\n\n /**\n * Start a new geometry object\n */\n function newGeometry() {\n // If there is an existing geometry and it's not empty then start a new one.\n if (geometry.material) {\n geometry = {} as Geometry\n }\n }\n\n /**\n * Set the geometry for the current material/part\n */\n function setGeometry() {\n if (!geometry.material) {\n const position = [] as number[]\n const texcoord = [] as number[]\n const normal = [] as number[]\n\n webglVertexData = [position, texcoord, normal]\n\n /** @type {Geometry} */\n geometry = {\n material,\n data: {\n position,\n texcoord,\n normal,\n },\n }\n\n geometries.push(geometry)\n }\n }\n\n // Parse the OBJ file line by line\n for (let lineNo = 0; lineNo < lines.length; ++lineNo) {\n const line = lines[lineNo].trim()\n if (line === '' || line.startsWith('#')) {\n continue\n }\n\n const m = keywordRE.exec(line)\n if (!m) {\n continue\n }\n\n const [, keyword, unparsedArgs] = m\n const parts = line.split(/\\s+/).slice(1)\n\n const handler = keywords[keyword]\n if (!handler) {\n console.warn('unhandled keyword:', keyword, 'at line', lineNo + 1)\n continue\n }\n\n handler(parts, unparsedArgs)\n }\n\n // FIX: For those OBJ files that don't have texcoord data\n for (const g of geometries) {\n if (g.data.texcoord && g.data.texcoord.length <= 0) {\n delete g.data.texcoord\n }\n }\n\n // Return the list of geometries and material libs, plus triangle count\n return {\n matLibNames: materialLibs,\n geometries,\n triangles,\n } as ParseResult\n}\n","// ===== files.ts =============================================================\n// File loading utilities\n// Ben Coleman, 2023\n// ============================================================================\n\ntype Shader = {\n vertex: string\n fragment: string\n}\n\n/**\n * Fetch a file from the server\n *\n * @param {string} path - URL path to file\n * @returns {Promise} File contents as a string\n */\nexport async function fetchFile(filePath: string) {\n const resp = await fetch(filePath)\n\n if (!resp.ok) {\n throw new Error(`💥 File fetch failed: ${resp.statusText}`)\n }\n\n const text = await resp.text()\n return text\n}\n\n/**\n * Fetch a pair of shaders from the server\n *\n * @param {string} vertPath - URL path to vertex shader\n * @param {string} fragPath - URL path to fragment shader\n * @returns {Promise} Pair of shaders as strings\n */\nexport async function fetchShaders(vertPath: string, fragPath: string) {\n const vsResp = await fetch(vertPath)\n const fsResp = await fetch(fragPath)\n\n if (!vsResp.ok || !fsResp.ok) {\n throw new Error(`💥 Fetch failed - vertex: ${vsResp.statusText}, fragment: ${fsResp.statusText}`)\n }\n\n const vsText = await vsResp.text()\n const fsText = await fsResp.text()\n\n return { vertex: vsText, fragment: fsText } as Shader\n}\n","// ===== hud.ts =========================================================\n// A HTML based HUD for the game, this is a simple div for now\n// Ben Coleman, 2023\n// ======================================================================\n\nimport { Stats } from './stats.ts'\nimport { version } from '../../package.json'\nimport { Camera } from '../index.ts'\n\nexport class HUD {\n private hud: HTMLDivElement\n private canvas: HTMLCanvasElement\n private debugDiv: HTMLDivElement\n private loadingDiv: HTMLDivElement\n public debug = false\n\n constructor(canvas: HTMLCanvasElement) {\n const parent = canvas.parentElement\n if (!parent) throw new Error('💥 Canvas must have a parent element')\n\n this.canvas = canvas\n\n this.hud = document.createElement('div')\n this.hud.classList.add('gsots3d-hud')\n this.hud.style.pointerEvents = 'none'\n\n this.updateWithCanvas = this.updateWithCanvas.bind(this)\n window.addEventListener('resize', this.updateWithCanvas)\n window.addEventListener('load', this.updateWithCanvas)\n\n this.debugDiv = document.createElement('div')\n this.debugDiv.classList.add('gsots3d-debug')\n this.debugDiv.style.fontSize = 'min(1.5vw, 20px)'\n this.debugDiv.style.fontFamily = 'monospace'\n this.debugDiv.style.color = 'white'\n this.debugDiv.style.padding = '1vw'\n this.addHUDItem(this.debugDiv)\n\n this.loadingDiv = document.createElement('div')\n this.loadingDiv.classList.add('gsots3d-loading')\n this.loadingDiv.innerHTML = `💾 Loading...`\n this.loadingDiv.innerHTML += `

GSOTS-3D v${version}
`\n this.loadingDiv.style.font = 'normal 3vw sans-serif'\n this.loadingDiv.style.color = '#ccc'\n this.loadingDiv.style.position = 'absolute'\n this.loadingDiv.style.top = '50%'\n this.loadingDiv.style.left = '50%'\n this.loadingDiv.style.textAlign = 'center'\n this.loadingDiv.style.transform = 'translate(-50%, -50%)'\n this.addHUDItem(this.loadingDiv)\n\n parent.appendChild(this.hud)\n this.updateWithCanvas()\n }\n\n private updateWithCanvas() {\n const canvasStyles = window.getComputedStyle(this.canvas, null)\n this.hud.style.position = canvasStyles.getPropertyValue('position')\n this.hud.style.top = canvasStyles.getPropertyValue('top')\n this.hud.style.left = canvasStyles.getPropertyValue('left')\n this.hud.style.width = canvasStyles.getPropertyValue('width')\n this.hud.style.height = canvasStyles.getPropertyValue('height')\n this.hud.style.transform = canvasStyles.getPropertyValue('transform')\n }\n\n addHUDItem(item: HTMLElement) {\n this.hud.appendChild(item)\n }\n\n render(debug = false, camera: Camera) {\n // Draw the debug HUD\n if (debug) {\n this.debugDiv.innerHTML = `\n GSOTS-3D v${version}

\n Camera: ${camera.toString()}
\n Instances: ${Stats.instances}
\n Draw calls: ${Stats.drawCallsPerFrame}
\n Triangles: ${Stats.triangles}
\n Render: FPS: ${Stats.FPS} / ${Stats.totalTimeRound}s
\n `\n } else {\n this.debugDiv.innerHTML = ''\n }\n }\n\n hideLoading() {\n this.loadingDiv.style.display = 'none'\n }\n}\n","#version 300 es\n\n// ============================================================================\n// Phong fragment shader\n// Ben Coleman, 2023\n// ============================================================================\n\nprecision highp float;\n\n// ===== Constants ============================================================\n\nconst int MAX_LIGHTS = 16;\n\n// Got this from http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-16-shadow-mapping/#poisson-sampling\nvec3 poissonDisk[4] = vec3[](\n vec3(-0.94201624, -0.39906216, 0.0),\n vec3(0.94558609, -0.76890725, 0.0),\n vec3(-0.094184101, -0.9293887, 0.0),\n vec3(0.34495938, 0.2938776, 0.0)\n);\n\n// ===== Structs ==============================================================\n\nstruct LightDir {\n vec3 direction;\n vec3 colour;\n vec3 ambient;\n};\n\nstruct LightPos {\n vec3 position;\n vec3 colour;\n vec3 ambient;\n float constant;\n float linear;\n float quad;\n bool enabled;\n};\n\nstruct Material {\n vec3 ambient;\n vec3 diffuse;\n vec3 specular;\n vec3 emissive;\n float shininess;\n float opacity;\n float reflectivity;\n sampler2D diffuseTex;\n sampler2D specularTex;\n sampler2D normalTex;\n bool hasNormalTex;\n};\n\n// Inputs from vertex shader\nin vec3 v_normal;\nin vec2 v_texCoord;\nin vec4 v_position;\nin vec4 v_shadowCoord;\n\n// Some global uniforms\nuniform vec3 u_camPos;\nuniform float u_gamma;\nuniform bool u_flipTextureX;\nuniform bool u_flipTextureY;\n\n// Main lights and material uniforms\nuniform Material u_mat;\nuniform LightDir u_lightDirGlobal;\nuniform LightPos u_lightsPos[MAX_LIGHTS];\nuniform int u_lightsPosCount;\n// Reflection map isn't part of the material struct for complex reasons\nuniform samplerCube u_reflectionMap;\n// Shadows\nuniform highp sampler2DShadow u_shadowMap;\nuniform float u_shadowScatter;\n\n// Global texture coords shared between functions\nvec2 texCoord;\n\n// Output colour of this pixel/fragment\nout vec4 outColour;\n\n// ===== Helper functions =====================================================\n\n// Simple mixer\nvec4 mix4(vec4 a, vec4 b, float mix) {\n return a * (1.0 - mix) + b * mix;\n}\n\n// Function to help with get values from the shadow map\nfloat shadowMapSample(highp sampler2DShadow map, vec3 coord) {\n // As WebGL 2 does not support GL_CLAMP_TO_BORDER or GL_TEXTURE_BORDER_COLOR, we need to do this :(\n if (coord.x < 0.0 || coord.x > 1.0 || coord.y < 0.0 || coord.y > 1.0) {\n return 1.0;\n }\n\n return texture(map, coord);\n}\n\n// Shade a fragment using a directional light source\nvec4 shadeDirLight(LightDir light, Material mat, vec3 N, vec3 V) {\n vec3 L = normalize(-light.direction);\n vec3 H = normalize(L + V);\n\n vec3 diffuseCol = vec3(texture(mat.diffuseTex, texCoord)) * mat.diffuse;\n vec3 specularCol = vec3(texture(mat.specularTex, texCoord)) * mat.specular;\n\n float diff = dot(N, L);\n float spec = diff > 0.0 ? pow(max(dot(N, H), 0.0), mat.shininess) : 0.0;\n\n // Shadow map lookup\n vec3 projCoords = v_shadowCoord.xyz / v_shadowCoord.w * 0.5 + 0.5;\n float shadow = 0.0;\n\n // Carry out PCF for shadows using 4 samples of a poisson disk\n for (int i = 0; i < 4; i++) {\n vec3 offset = poissonDisk[i] * (u_shadowScatter / 100.0);\n shadow += shadowMapSample(u_shadowMap, projCoords + offset) * 0.25;\n }\n\n vec3 ambient = light.ambient * mat.ambient * diffuseCol;\n vec3 diffuse = light.colour * max(diff, 0.0) * diffuseCol * shadow;\n vec3 specular = light.colour * spec * specularCol * shadow;\n\n // Return a vec4 to support transparency, note specular is not affected by opacity\n return vec4(ambient + diffuse, mat.opacity / float(u_lightsPosCount + 1)) + vec4(specular, spec);\n}\n\n// Shade a fragment using a positional light source\nvec4 shadePosLight(LightPos light, Material mat, vec3 N, vec3 V) {\n vec3 L = normalize(light.position - v_position.xyz);\n vec3 H = normalize(L + V);\n\n vec3 diffuseCol = vec3(texture(mat.diffuseTex, texCoord)) * mat.diffuse;\n vec3 specularCol = vec3(texture(mat.specularTex, texCoord)) * mat.specular;\n\n float diff = dot(N, L);\n float spec = diff > 0.0 ? pow(max(dot(N, H), 0.0), mat.shininess) : 0.0;\n\n // Light attenuation, see: https://learnopengl.com/Lighting/Light-casters\n float dist = length(light.position - v_position.xyz);\n float attenuation = 1.0 / (light.constant + light.linear * dist + light.quad * (dist * dist));\n\n vec3 ambient = light.ambient * mat.ambient * diffuseCol * attenuation;\n vec3 diffuse = light.colour * max(diff, 0.0) * diffuseCol * attenuation;\n vec3 specular = light.colour * spec * specularCol * attenuation;\n\n // Return a vec4 to support transparency, note specular is not affected by opacity\n return vec4(ambient + diffuse, mat.opacity / float(u_lightsPosCount + 1)) + vec4(specular, spec);\n}\n\n// ===== Main shader ==========================================================\n\nvoid main() {\n vec3 V = normalize(u_camPos - v_position.xyz);\n\n // Flip texture coords if needed\n texCoord = u_flipTextureY ? vec2(v_texCoord.x, 1.0 - v_texCoord.y) : v_texCoord;\n texCoord = u_flipTextureX ? vec2(1.0 - texCoord.x, texCoord.y) : texCoord;\n\n vec3 N = normalize(v_normal);\n\n // Normal mapping, this is expensive so only do it if we have a normal map\n if (u_mat.hasNormalTex) {\n vec3 normMap = texture(u_mat.normalTex, texCoord).xyz * 2.0 - 1.0;\n\n vec3 Q1 = dFdx(v_position.xyz);\n vec3 Q2 = dFdy(v_position.xyz);\n vec2 st1 = dFdx(texCoord);\n vec2 st2 = dFdy(texCoord);\n\n vec3 T = -normalize(Q1 * st2.t - Q2 * st1.t);\n vec3 B = normalize(cross(N, T));\n mat3 TBN = mat3(T, B, N);\n\n N = normalize(TBN * normMap);\n }\n\n // Handle the main directional light, only one of these\n vec4 outColorPart = shadeDirLight(u_lightDirGlobal, u_mat, N, V);\n\n // Add positional lights\n for (int i = 0; i < u_lightsPosCount; i++) {\n outColorPart += shadePosLight(u_lightsPos[i], u_mat, N, V);\n }\n\n // Add emissive component\n float emissiveAlpha = u_mat.emissive.r + u_mat.emissive.g + u_mat.emissive.b > 0.0 ? 1.0 : 0.0;\n outColorPart += vec4(u_mat.emissive, emissiveAlpha);\n\n // Get reflection vector and sample reflection texture\n vec3 R = reflect(-V, N);\n vec4 reflectCol = vec4(texture(u_reflectionMap, R).rgb, 1.0);\n\n // Add reflection component, not sure if this is correct, looks ok\n outColorPart = mix4(outColorPart, reflectCol, u_mat.reflectivity);\n\n // Gamma correction, as GL_FRAMEBUFFER_SRGB is not supported on WebGL\n outColorPart.rgb = pow(outColorPart.rgb, vec3(1.0 / u_gamma));\n\n outColour = outColorPart;\n}\n","#version 300 es\n\n// ============================================================================\n// Phong vertex shader\n// Ben Coleman, 2023\n// ============================================================================\n\nprecision highp float;\n\n// Input attributes from buffers\nin vec4 position;\nin vec3 normal;\nin vec2 texcoord;\n\nuniform mat4 u_worldViewProjection;\nuniform mat4 u_worldInverseTranspose;\nuniform mat4 u_world;\nuniform mat4 u_shadowMatrix;\n\n// Output varying's to pass to fragment shader\nout vec2 v_texCoord;\nout vec3 v_normal;\nout vec4 v_position;\nout vec4 v_shadowCoord;\n\nvoid main() {\n v_texCoord = texcoord;\n v_normal = (u_worldInverseTranspose * vec4(normal, 0)).xyz;\n v_position = u_world * position;\n v_shadowCoord = u_shadowMatrix * v_position;\n\n gl_Position = u_worldViewProjection * position;\n}\n","#version 300 es\n\n// ============================================================================\n// Billboard fragment shader\n// Ben Coleman, 2023\n// ============================================================================\n\nprecision highp float;\n\nstruct Material {\n vec3 ambient;\n vec3 diffuse;\n vec3 specular;\n vec3 emissive;\n float shininess;\n float opacity;\n float reflectivity;\n sampler2D diffuseTex;\n sampler2D specularTex;\n sampler2D normalTex;\n bool hasNormalTex;\n};\n\n// From vertex shader\nin vec2 v_texCoord;\nin vec3 v_lighting;\n\n// Main lights and material uniforms\nuniform Material u_mat;\nuniform float u_gamma;\n\n// Output colour of this pixel/fragment\nout vec4 outColour;\n\nvoid main() {\n vec4 texel = texture(u_mat.diffuseTex, v_texCoord);\n\n // Magic to make transparent sprites work, without blending\n // Somehow this also works with the shadow map render pass, which is a bonus\n if (texel.a < 0.75) {\n discard;\n }\n\n vec3 colour = texel.rgb * u_mat.diffuse * v_lighting;\n\n // Gamma correction, as GL_FRAMEBUFFER_SRGB is not supported on WebGL\n colour = pow(colour, vec3(1.0 / u_gamma));\n\n outColour = vec4(colour, u_mat.opacity);\n}\n","#version 300 es\n\n// ============================================================================\n// Billboard vertex shader\n// Ben Coleman, 2023\n// ============================================================================\n\nprecision highp float;\n\nconst int MAX_LIGHTS = 16;\n\nstruct LightDir {\n vec3 direction;\n vec3 colour;\n vec3 ambient;\n};\n\nstruct LightPos {\n vec3 position;\n vec3 colour;\n vec3 ambient;\n float constant;\n float linear;\n float quad;\n bool enabled;\n};\n\n// Input attributes from buffers\nin vec4 position;\nin vec2 texcoord;\n\nuniform mat4 u_worldViewProjection;\nuniform mat4 u_world;\nuniform int u_lightsPosCount;\nuniform vec3 u_camPos;\nuniform LightDir u_lightDirGlobal;\nuniform LightPos u_lightsPos[MAX_LIGHTS];\n\n// Output varying's to pass to fragment shader\nout vec2 v_texCoord;\nout vec3 v_lighting;\n\n/*\n * Legacy lighting calc\n * Returns vec2(diffuse, specular)\n */\nvec2 lightCalc(vec3 N, vec3 L, vec3 H, float shininess) {\n float diff = dot(N, L);\n float spec = diff > 0.0 ? pow(max(dot(N, H), 0.0), shininess) : 0.0;\n return vec2(diff, spec);\n}\n\nvoid main() {\n v_texCoord = texcoord;\n gl_Position = u_worldViewProjection * position;\n vec3 worldPos = (u_world * position).xyz;\n\n // Normal for a billboard always points at camera\n vec3 worldNormal = normalize(u_camPos - worldPos);\n\n vec3 V = normalize(u_camPos - worldPos);\n vec3 N = normalize(worldNormal);\n float fudge = 1.5;\n\n // Add point lights to lighting output\n for (int i = 0; i < u_lightsPosCount; i++) {\n LightPos light = u_lightsPos[i];\n vec3 L = normalize(light.position - worldPos.xyz);\n\n float diffuse = max(dot(N, L), 0.0);\n\n // Distance attenuation\n float distance = length(light.position - worldPos.xyz);\n float attenuation = 1.0 / (light.constant + light.linear * distance + light.quad * (distance * distance));\n\n // Note small hack here to fudge the light intensity\n v_lighting += light.colour * fudge * attenuation * diffuse;\n }\n\n // Add in global directional light\n // Approximate by using a fixed direction for the normal pointing up\n vec3 globalLightL = normalize(-u_lightDirGlobal.direction);\n float globalDiffuse = dot(vec3(0.0, 1.0, 0.0), globalLightL);\n\n v_lighting += u_lightDirGlobal.colour * globalDiffuse;\n v_lighting += u_lightDirGlobal.ambient;\n}\n"],"mappings":"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AAM;AAAA,IACN;AAAA,IAAM;AAAA;AAAA,IAGN;AAAA,IAAM;AAAA,IACN;AAAA,IAAM;AAAA,IACN;AAAA,IAAM;AAAA,IACN;AAAA,IAAM;AAAA,IACN;AAAA,IAAM;AAAA,IACN;AAAA,IAAM;AAAA;AAAA,IAGN;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA;AAAA,IAGH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA;AAAA,IAGH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA;AAAA,IAGH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA;AAAA,IAGH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA;AAAA,IAGH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA;AAAA,IAGH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA;AAAA,IAGH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA;AAAA,IAGH;AAAA,IAAG;AAAA,IACH;AAAA,IAAG;AAAA,I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,KAAK,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,CAAC,KAAK,KAAK,IAAI,KAAK,EAAE,KAAc,UAAU,KAAK,IAAI,GAAK,KAAK,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,CAAC,KAAK,KAAK,IAAI,KAAK,EAAE,KAAc,UAAU,KAAK,IAAI,GAAK,KAAK,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,CAAC,KAAK,KAAK,IAAI,KAAK,EAAE,KAAc,UAAU,KAAK,IAAI,GAAK,KAAK,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,CAAC,KAAK,KAAK,IAAI,KAAK,EAAE,KAAc,UAAU,KAAK,IAAI,GAAK,KAAK,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,CAAC,KAAK,KAAK,IAAI,KAAK,EAAE,KAAc,UAAU,KAAK,IAAI,GAAK,KAAK,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,CAAC,KAAK,KAAK,IAAI,KAAK,EAAE,KAAc,UAAU,KAAK,IAAI,GAAK,KAAK,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,CAAC,KAAK,KAAK,IAAI,KAAK,EAAE,KAAc,UAAU,KAAK,IAAI,GAAK,KAAK,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,CAAC,KAAK,KAAK,IAAI,KAAK,EAAE,KAAc,UAAU,KAAK,IAAI,GAAK,KAAK,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,CAAC,KAAK,KAAK,IAAI,KAAK,EAAE,KAAc,UAAU,KAAK,IAAI,GAAK,KAAK,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,CAAC,KAAK,KAAK,IAAI,MAAM,GAAG,KAAc,UAAU,KAAK,IAAI,GAAK,KAAK,IAAI,GAAG,GAAG,KAAK,IAAI,GAAG,CAAC,KAAK,KAAK,IAAI,MAAM,GAAG,KAAc,UAAU,KAAK,IAAI,GAAK,KAAK,IAAI,GAAG,GAAG,KAAK,IAAI,GAAG,CAAC,KAAK,KAAK,IAAI,MAAM,GAAG,KAAc,UAAU,KAAK,IAAI,GAAK,KAAK,IAAI,GAAG,GAAG,KAAK,IAAI,GAAG,CAAC,KAAK,KAAK,IAAI,MAAM,GAAG,KAAc,UAAU,KAAK,IAAI,GAAK,KAAK,IAAI,GAAG,GAAG,KAAK,IAAI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","names":["noop","location","log","import_loglevel","log","import_loglevel","length","length","length","len","lerp","angle","base","glEnumToString","isArrayBuffer","getShared2DContext","internalFormat","isArrayBuffer","isArrayBuffer","clearEventHandlers","onError","onLoad","cb","img","location","typeInfo","normalize","log","error","gl","program","token","node","program","location","program","errors","gl","programs","add","identity","identity","len","add","scale","add","clone","copy","create","equals","exactEquals","fromValues","inverse","length","mul","multiply","rotateX","rotateY","rotateZ","scale","set","str","sub","subtract","create","clone","length","fromValues","copy","set","add","subtract","multiply","scale","inverse","len","rotateX","rotateY","rotateZ","str","exactEquals","equals","sub","mul","normalize","len","scale","distance","import_loglevel","log","import_loglevel","CameraType","camView","log","glsl_default","glsl_default","import_loglevel","glsl_default","glsl_default","glsl_default","log","angle","scale","rotate","translate","BillboardType","scale","import_loglevel","keywordRE","log","glsl_default","glsl_default","glsl_default","glsl_default","Context","log","glsl_default"]} \ No newline at end of file diff --git a/examples/demo-2/main.mjs b/examples/demo-2/main.mjs index 1e3cf79..04112be 100644 --- a/examples/demo-2/main.mjs +++ b/examples/demo-2/main.mjs @@ -29,7 +29,7 @@ wallMat.shininess = 300 const wall = ctx.createPlaneInstance(wallMat, 200, 200, 12, 12, 6) wall.rotateXDeg(90) -wall.position = [3, -50, -100] +wall.position = [3, -30, -100] ctx.createPlaneInstance(wallMat, 200, 200, 12, 12, 6) @@ -61,8 +61,7 @@ laptop.scale = [12.2, 12.2, 12.2] const teapot = ctx.createModelInstance('teapot') teapot.position = [-15, 20, 35] teapot.scale = [6, 6, 6] -teapot.metadata.special = 1 -const teapotMaterial = Material.createSolidColour(0.7, 0.7, 0.7) +const teapotMaterial = Material.createSolidColour(0.7, 0.7, 1.0) teapotMaterial.specular = [0.7, 0.7, 0.7] teapotMaterial.shininess = 50 teapotMaterial.reflectivity = 0.5 @@ -84,41 +83,36 @@ mirrorMat.shininess = 100 mirrorMat.specular = [1, 1, 1] const mirrorBall = ctx.createSphereInstance(mirrorMat, 20, 24, 24) mirrorBall.position = [-25, 25, -35] -mirrorBall.metadata['special'] = 1 +mirrorBall.metadata.special = 1 -const light = ctx.createPointLight([0, 0, 0], Colours.WHITE, 3) -const lightBallMat = Material.createSolidColour(Colours.WHITE) -lightBallMat.emissive = [1, 1, 1] -lightBallMat.diffuse = [1, 1, 1] -lightBallMat.shininess = 100 -const lightBall = ctx.createSphereInstance(lightBallMat, 0.5, 24, 24) - -// red ball +// Red ball const redBallMat = Material.createSolidColour(0.8, 0.2, 0.1) redBallMat.specular = [0.7, 0.7, 0.7] redBallMat.shininess = 50 redBallMat.reflectivity = 0.5 const redBall = ctx.createSphereInstance(redBallMat, 8, 32, 32) redBall.position = [25, 8, 20] - let redBallDir = 1 +// Lights that follows the camera +const light = ctx.createPointLight([0, 0, 0], Colours.WHITE, 3) + ctx.update = () => { light.position[0] = ctx.camera.position[0] - 40 light.position[1] = ctx.camera.position[1] + 10 light.position[2] = ctx.camera.position[2] - 40 - lightBall.position = light.position teapot.rotateYDeg(0.6) cube2.rotateYDeg(-0.4) - if (redBall.position[2] > 50) { - redBallDir = -1.7 + if (redBall.position[2] > 80) { + redBallDir = -1 } - if (redBall.position[2] < -50) { - redBallDir = 1.7 + if (redBall.position[2] < -80) { + redBallDir = 1 } - redBall.position[2] += redBallDir * 0.5 + redBall.position[2] += redBallDir * 0.65 + redBall.position[0] += redBallDir * 0.25 } ctx.setEnvmap( diff --git a/examples/demo/main.mjs b/examples/demo/main.mjs index 29bf483..211daac 100644 --- a/examples/demo/main.mjs +++ b/examples/demo/main.mjs @@ -236,7 +236,10 @@ ctx.update = (delta) => { scifiCube.rotateYDeg(delta * 25) } +// Dynamic reflections, big performance hit ctx.setDynamicEnvmap([0, 15, 0], 256) + +// Shadows ctx.globalLight.enableShadows({ mapSize: 1024, zoom: 100, diff --git a/src/core/cache.ts b/src/core/cache.ts index d802706..bc4066e 100644 --- a/src/core/cache.ts +++ b/src/core/cache.ts @@ -143,7 +143,7 @@ export class TextureCache { * @param flipY Flip the texture vertically (default true) */ getCreate(src: string, filter = true, flipY = false) { - // check if texture already exists, if so return it + // Check if texture already exists, if so return it if (this.cache.has(src)) { log.trace(`👍 Returning texture '${src}' from cache, nice!`, flipY) return this.get(src) @@ -156,7 +156,7 @@ export class TextureCache { { min: filter ? this.gl.LINEAR_MIPMAP_LINEAR : this.gl.NEAREST, mag: filter ? this.gl.LINEAR : this.gl.NEAREST, - src: src, + src, flipY: flipY ? 1 : 0, }, (err) => { diff --git a/src/core/context.ts b/src/core/context.ts index a02e90d..a995a5c 100644 --- a/src/core/context.ts +++ b/src/core/context.ts @@ -40,8 +40,6 @@ export class Context { private started: boolean private instances: Instance[] = [] private instancesTrans: Instance[] = [] - private debugDiv: HTMLDivElement - private loadingDiv: HTMLDivElement private cameras: Map = new Map() private activeCameraName: string private envmap?: EnvironmentMap @@ -101,25 +99,6 @@ export class Context { this.hud = new HUD(gl.canvas) - this.debugDiv = document.createElement('div') - this.debugDiv.classList.add('gsots3d-debug') - this.debugDiv.style.fontSize = 'min(1.5vw, 20px)' - this.debugDiv.style.fontFamily = 'monospace' - this.debugDiv.style.color = 'white' - this.debugDiv.style.padding = '1vw' - this.hud.addHUDItem(this.debugDiv) - - this.loadingDiv = document.createElement('div') - this.loadingDiv.classList.add('gsots3d-loading') - this.loadingDiv.innerHTML = '💾 Loading...' - this.loadingDiv.style.font = 'normal 4vw sans-serif' - this.loadingDiv.style.color = 'white' - this.loadingDiv.style.position = 'absolute' - this.loadingDiv.style.top = '50%' - this.loadingDiv.style.left = '50%' - this.loadingDiv.style.transform = 'translate(-50%, -50%)' - this.hud.addHUDItem(this.loadingDiv) - log.info(`👑 GSOTS-3D context created, v${version}`) } @@ -199,19 +178,7 @@ export class Context { bindFramebufferInfo(this.gl, null) this.renderWithCamera(this.camera) - // Draw the debug HUD - if (this.debug) { - this.debugDiv.innerHTML = ` - GSOTS-3D v${version}

- Camera: ${this.camera.toString()}
- Instances: ${Stats.instances}
- Draw calls: ${Stats.drawCallsPerFrame}
- Triangles: ${Stats.triangles}
- Render: FPS: ${Stats.FPS} / ${Stats.totalTimeRound}s
- ` - } else { - this.debugDiv.innerHTML = '' - } + this.hud.render(this.debug, this.camera) // Loop forever or stop if not started if (this.started) requestAnimationFrame(this.render) @@ -322,7 +289,7 @@ export class Context { * Start the rendering loop */ start() { - this.loadingDiv.style.display = 'none' + this.hud.hideLoading() this.started = true // Restart the render loop requestAnimationFrame(this.render) diff --git a/src/core/hud.ts b/src/core/hud.ts index 1727fc7..58315e2 100644 --- a/src/core/hud.ts +++ b/src/core/hud.ts @@ -3,9 +3,16 @@ // Ben Coleman, 2023 // ====================================================================== +import { Stats } from './stats.ts' +import { version } from '../../package.json' +import { Camera } from '../index.ts' + export class HUD { private hud: HTMLDivElement private canvas: HTMLCanvasElement + private debugDiv: HTMLDivElement + private loadingDiv: HTMLDivElement + public debug = false constructor(canvas: HTMLCanvasElement) { const parent = canvas.parentElement @@ -15,16 +22,38 @@ export class HUD { this.hud = document.createElement('div') this.hud.classList.add('gsots3d-hud') + this.hud.style.pointerEvents = 'none' + + this.updateWithCanvas = this.updateWithCanvas.bind(this) + window.addEventListener('resize', this.updateWithCanvas) + window.addEventListener('load', this.updateWithCanvas) + + this.debugDiv = document.createElement('div') + this.debugDiv.classList.add('gsots3d-debug') + this.debugDiv.style.fontSize = 'min(1.5vw, 20px)' + this.debugDiv.style.fontFamily = 'monospace' + this.debugDiv.style.color = 'white' + this.debugDiv.style.padding = '1vw' + this.addHUDItem(this.debugDiv) - this.update = this.update.bind(this) - window.addEventListener('resize', this.update) - window.addEventListener('load', this.update) + this.loadingDiv = document.createElement('div') + this.loadingDiv.classList.add('gsots3d-loading') + this.loadingDiv.innerHTML = `💾 Loading...` + this.loadingDiv.innerHTML += `

GSOTS-3D v${version}
` + this.loadingDiv.style.font = 'normal 3vw sans-serif' + this.loadingDiv.style.color = '#ccc' + this.loadingDiv.style.position = 'absolute' + this.loadingDiv.style.top = '50%' + this.loadingDiv.style.left = '50%' + this.loadingDiv.style.textAlign = 'center' + this.loadingDiv.style.transform = 'translate(-50%, -50%)' + this.addHUDItem(this.loadingDiv) parent.appendChild(this.hud) - this.update() + this.updateWithCanvas() } - update() { + private updateWithCanvas() { const canvasStyles = window.getComputedStyle(this.canvas, null) this.hud.style.position = canvasStyles.getPropertyValue('position') this.hud.style.top = canvasStyles.getPropertyValue('top') @@ -32,16 +61,29 @@ export class HUD { this.hud.style.width = canvasStyles.getPropertyValue('width') this.hud.style.height = canvasStyles.getPropertyValue('height') this.hud.style.transform = canvasStyles.getPropertyValue('transform') - - // IMPORTANT: This is needed to make the canvas clickable for pointer lock - this.hud.style.pointerEvents = 'none' } addHUDItem(item: HTMLElement) { this.hud.appendChild(item) } - debug(msg: string) { - this.hud.innerHTML = msg + render(debug = false, camera: Camera) { + // Draw the debug HUD + if (debug) { + this.debugDiv.innerHTML = ` + GSOTS-3D v${version}

+ Camera: ${camera.toString()}
+ Instances: ${Stats.instances}
+ Draw calls: ${Stats.drawCallsPerFrame}
+ Triangles: ${Stats.triangles}
+ Render: FPS: ${Stats.FPS} / ${Stats.totalTimeRound}s
+ ` + } else { + this.debugDiv.innerHTML = '' + } + } + + hideLoading() { + this.loadingDiv.style.display = 'none' } } diff --git a/src/core/stats.ts b/src/core/stats.ts index 2d9bcc2..cb7c6ca 100644 --- a/src/core/stats.ts +++ b/src/core/stats.ts @@ -3,30 +3,30 @@ // Ben Coleman, 2023 // ====================================================================== -export class Stats { - public static drawCallsPerFrame = 0 - public static instances = 0 - public static triangles = 0 +export const Stats = { + drawCallsPerFrame: 0, + instances: 0, + triangles: 0, - private static prevTime = 0 - public static deltaTime = 0 - public static totalTime = 0 + prevTime: 0, + deltaTime: 0, + totalTime: 0, - static resetPerFrame() { + resetPerFrame() { Stats.drawCallsPerFrame = 0 - } + }, - static updateTime(now: number) { + updateTime(now: number) { Stats.deltaTime = now - Stats.prevTime // Get smoothed time difference Stats.prevTime = now Stats.totalTime += Stats.deltaTime - } + }, - static get FPS() { + get FPS() { return Math.round(1 / Stats.deltaTime) - } + }, - static get totalTimeRound() { + get totalTimeRound() { return Math.round(Stats.totalTime) - } + }, } diff --git a/src/engine/camera.ts b/src/engine/camera.ts index 5e06f7b..f29e38e 100644 --- a/src/engine/camera.ts +++ b/src/engine/camera.ts @@ -160,7 +160,7 @@ export class Camera { this.fpTurnSpeed = turnSpeed this.fpMoveSpeed = moveSpeed - if (this.fpHandlersAdded) return // prevent multiple event listeners being added + if (this.fpHandlersAdded) return // Prevent multiple event listeners being added // Handle enable/disable for pointer lock on main canvas // See: https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API @@ -211,7 +211,7 @@ export class Camera { // If the touch is on the left side of the screen, it's for moving if (e.touches[0].clientX < window.innerWidth / 2) { - // top half of screen is forward, bottom half is backward + // Top half of screen is forward, bottom half is backward if (e.touches[0].clientY < window.innerHeight / 2) { this.keysDown.add('w') } @@ -275,11 +275,11 @@ export class Camera { if (!this.fpMode || !this.active) return if (this.keysDown.size === 0) return - // use fpAngleY to calculate the direction we are facing + // Use fpAngleY to calculate the direction we are facing const dZ = -Math.cos(this.fpAngleY) * this.fpMoveSpeed const dX = -Math.sin(this.fpAngleY) * this.fpMoveSpeed - // use keysDown to move the camera + // Use keysDown to move the camera for (const key of this.keysDown.values()) { switch (key) { case 'ArrowUp': @@ -308,7 +308,7 @@ export class Camera { case 'ArrowRight': case 'd': - // move right + // Move right this.position[0] -= dZ this.position[2] += dX this.lookAt[0] -= dZ diff --git a/src/engine/material.ts b/src/engine/material.ts index b026a9c..de50b1f 100644 --- a/src/engine/material.ts +++ b/src/engine/material.ts @@ -116,7 +116,7 @@ export class Material { } // This is a kludge, a guess; if illum is 3 or more and Ks is set, then we have - // a reflective material of some kind + // A reflective material of some kind if (rawMtl.illum && rawMtl.illum > 2) { m.reflectivity = (m.specular[0] + m.specular[1] + m.specular[2]) / 3 } diff --git a/src/engine/tuples.ts b/src/engine/tuples.ts index ad60bef..6cfab2f 100644 --- a/src/engine/tuples.ts +++ b/src/engine/tuples.ts @@ -97,15 +97,15 @@ function rgbColourHex(hexString: string) { /** * A set of common colours as RGB tuples */ -export class Colours { - static readonly RED = [1, 0, 0] as RGB - static readonly GREEN = [0, 1, 0] as RGB - static readonly BLUE = [0, 0, 1] as RGB - static readonly YELLOW = [1, 1, 0] as RGB - static readonly CYAN = [0, 1, 1] as RGB - static readonly MAGENTA = [1, 0, 1] as RGB - static readonly BLACK = [0, 0, 0] as RGB - static readonly WHITE = [1, 1, 1] as RGB +export const Colours = { + RED: [1, 0, 0] as RGB, + GREEN: [0, 1, 0] as RGB, + BLUE: [0, 0, 1] as RGB, + YELLOW: [1, 1, 0] as RGB, + CYAN: [0, 1, 1] as RGB, + MAGENTA: [1, 0, 1] as RGB, + BLACK: [0, 0, 0] as RGB, + WHITE: [1, 1, 1] as RGB, } // ============================================================================ diff --git a/src/models/instance.ts b/src/models/instance.ts index b1d96da..55d3163 100644 --- a/src/models/instance.ts +++ b/src/models/instance.ts @@ -14,71 +14,74 @@ import { ProgramInfo } from 'twgl.js' * An instance of thing in the world to be rendered, with position, rotation, scale etc */ export class Instance { + /** Main renderable thing this instance represents */ public readonly renderable: Renderable | undefined + + /** Position in world space */ public position: XYZ | undefined + + /** Scale in world space */ public scale: XYZ | undefined - public rotate: XYZ | undefined + + /** Should this instance be rendered and drawn */ public enabled = true - public metadata: Record = {} - public castShadow = true - /** - * Material to use for this instance, this will override ALL the materials on the model! - * Really only useful for simple untextured models without a MTL file - */ - public material?: Material + /** Should this instance cast a shadow */ + public castShadow = true - /** - * Per instance texture flip flags, useful for flipping textures on a per instance basis - * @default false - */ + /** Flip all textures on this instance on the X axis */ public flipTextureX = false - /** - * Per instance texture flip flags, useful for flipping textures on a per instance basis - * @default false - */ + /** Flip all textures on this instance on the Y axis */ public flipTextureY = false + /** Material override. This will override the renderable's material. + * This is only useful on simple models that probably consist of one surface */ + public material?: Material + + /** Metadata for this instance, can be used to store anything */ + public metadata: Record = {} + + /** Rotation in radians around X, Y, Z axis */ + private rotate: XYZ | undefined + /** + * Create a new instace of a renderable thing * @param {Renderable} renderable - Renderable to use for this instance */ constructor(renderable: Renderable) { this.renderable = renderable } - /** - * Rotate this instance around the X axis - */ + /** Rotate this instance around the X axis*/ rotateX(angle: number) { if (!this.rotate) this.rotate = [0, 0, 0] this.rotate[0] += angle } - /** - * Rotate this instance around the Y axis - */ + /** Rotate this instance around the Y axis*/ rotateY(angle: number) { if (!this.rotate) this.rotate = [0, 0, 0] this.rotate[1] += angle } - /** - * Rotate this instance around the Z axis - */ + /** Rotate this instance around the Z axis, in radians*/ rotateZ(angle: number) { if (!this.rotate) this.rotate = [0, 0, 0] this.rotate[2] += angle } + /** Rotate this instance around the X axis by a given angle in degrees */ rotateZDeg(angle: number) { this.rotateZ((angle * Math.PI) / 180) } + /** Rotate this instance around the Y axis by a given angle in degrees */ rotateYDeg(angle: number) { this.rotateY((angle * Math.PI) / 180) } + /** Rotate this instance around the Z axis by a given angle in degrees */ rotateXDeg(angle: number) { this.rotateX((angle * Math.PI) / 180) } diff --git a/src/models/model.ts b/src/models/model.ts index 6c79027..4c08b00 100644 --- a/src/models/model.ts +++ b/src/models/model.ts @@ -68,7 +68,7 @@ export class Model implements Renderable { // Fall back to default material if not found if (!material) { - material = this.materials['__default'] + material = this.materials.__default } material.apply(programInfo) @@ -136,8 +136,8 @@ export class Model implements Renderable { } // Fall back default material - model.materials['__default'] = new Material() - model.materials['__default'].diffuse = [0.1, 0.6, 0.9] + model.materials.__default = new Material() + model.materials.__default.diffuse = [0.1, 0.6, 0.9] // This really should already been memoized by the context at this point const gl = getGl() diff --git a/src/models/types.ts b/src/models/types.ts index 9b4f982..e322f90 100644 --- a/src/models/types.ts +++ b/src/models/types.ts @@ -6,9 +6,7 @@ import { Material } from '../engine/material.ts' * Models and primitives implement this interface to be rendered */ export interface Renderable { - /** - * Called to render this render-able thing - */ + /** Called to render this render-able thing */ render( gl: WebGL2RenderingContext, uniforms: UniformSet, diff --git a/src/parsers/mtl-parser.ts b/src/parsers/mtl-parser.ts index a53eadd..85438c8 100644 --- a/src/parsers/mtl-parser.ts +++ b/src/parsers/mtl-parser.ts @@ -57,7 +57,7 @@ export function parseMTL(mtlFile: string): Map { }, Ni() { // Not used - //material.ni = parseFloat(parts[0]) + // Material.ni = parseFloat(parts[0]) }, d(parts: string[]) { material.d = parseFloat(parts[0]) @@ -98,7 +98,7 @@ export function parseMTL(mtlFile: string): Map { const handler = keywords[keyword] if (!handler) { - //console.warn('unhandled keyword:', keyword) + // Console.warn('unhandled keyword:', keyword) continue } diff --git a/src/parsers/obj-parser.ts b/src/parsers/obj-parser.ts index a8f47d1..27fbd3f 100644 --- a/src/parsers/obj-parser.ts +++ b/src/parsers/obj-parser.ts @@ -49,16 +49,16 @@ export function parseOBJ(objFile: string, flipUV: boolean) { const objTexcoords = [[0, 0]] const objNormals = [[0, 0, 0]] - // same order as `f` indices + // Same order as `f` indices const objVertexData = [objPositions, objTexcoords, objNormals] let triangles = 0 - // same order as `f` indices + // Same order as `f` indices let webglVertexData = [ - [], // position - [], // texcoord - [], // normal + [], // Position + [], // Texcoord + [], // Normal ] as number[][] const geometries = Array() @@ -211,7 +211,7 @@ export function parseOBJ(objFile: string, flipUV: boolean) { // Return the list of geometries and material libs, plus triangle count return { matLibNames: materialLibs, - geometries: geometries, + geometries, triangles, } as ParseResult } diff --git a/tsconfig.json b/tsconfig.json index 8a8b0a8..6723731 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,6 +10,7 @@ "noUnusedParameters": true, "noUnusedLocals": true, "noImplicitReturns": true, + "strictNullChecks": true, // Stops tsc from complaining about ESM "target": "es2020",