@plotly/regl
Version:
regl is a fast functional WebGL framework.
1,988 lines (1,688 loc) • 252 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.createREGL = factory());
}(this, (function () { 'use strict';
var extend = function (base, opts) {
var keys = Object.keys(opts)
for (var i = 0; i < keys.length; ++i) {
base[keys[i]] = opts[keys[i]]
}
return base
}
var VARIABLE_COUNTER = 0
var DYN_FUNC = 0
var DYN_CONSTANT = 5
var DYN_ARRAY = 6
function DynamicVariable (type, data) {
this.id = (VARIABLE_COUNTER++)
this.type = type
this.data = data
}
function escapeStr (str) {
return str.replace(/\\/g, '\\\\').replace(/"/g, '\\"')
}
function splitParts (str) {
if (str.length === 0) {
return []
}
var firstChar = str.charAt(0)
var lastChar = str.charAt(str.length - 1)
if (str.length > 1 &&
firstChar === lastChar &&
(firstChar === '"' || firstChar === "'")) {
return ['"' + escapeStr(str.substr(1, str.length - 2)) + '"']
}
var parts = /\[(false|true|null|\d+|'[^']*'|"[^"]*")\]/.exec(str)
if (parts) {
return (
splitParts(str.substr(0, parts.index))
.concat(splitParts(parts[1]))
.concat(splitParts(str.substr(parts.index + parts[0].length)))
)
}
var subparts = str.split('.')
if (subparts.length === 1) {
return ['"' + escapeStr(str) + '"']
}
var result = []
for (var i = 0; i < subparts.length; ++i) {
result = result.concat(splitParts(subparts[i]))
}
return result
}
function toAccessorString (str) {
return '[' + splitParts(str).join('][') + ']'
}
function defineDynamic (type, data) {
return new DynamicVariable(type, toAccessorString(data + ''))
}
function isDynamic (x) {
return (typeof x === 'function' && !x._reglType) || (x instanceof DynamicVariable)
}
function unbox (x, path) {
if (typeof x === 'function') {
return new DynamicVariable(DYN_FUNC, x)
} else if (typeof x === 'number' || typeof x === 'boolean') {
return new DynamicVariable(DYN_CONSTANT, x)
} else if (Array.isArray(x)) {
return new DynamicVariable(DYN_ARRAY, x.map(function (y, i) { return unbox(y, path + '[' + i + ']') }))
} else if (x instanceof DynamicVariable) {
return x
}
}
var dynamic = {
DynamicVariable: DynamicVariable,
define: defineDynamic,
isDynamic: isDynamic,
unbox: unbox,
accessor: toAccessorString
};
/* globals requestAnimationFrame, cancelAnimationFrame */
var raf = {
next: typeof requestAnimationFrame === 'function'
? function (cb) { return requestAnimationFrame(cb) }
: function (cb) { return setTimeout(cb, 16) },
cancel: typeof cancelAnimationFrame === 'function'
? function (raf) { return cancelAnimationFrame(raf) }
: clearTimeout
};
/* globals performance */
var clock = (typeof performance !== 'undefined' && performance.now)
? function () { return performance.now() }
: function () { return +(new Date()) };
function createStringStore () {
var stringIds = { '': 0 }
var stringValues = ['']
return {
id: function (str) {
var result = stringIds[str]
if (result) {
return result
}
result = stringIds[str] = stringValues.length
stringValues.push(str)
return result
},
str: function (id) {
return stringValues[id]
}
}
}
// Context and canvas creation helper functions
function createCanvas (element, onDone, pixelRatio) {
var canvas = document.createElement('canvas')
extend(canvas.style, {
border: 0,
margin: 0,
padding: 0,
top: 0,
left: 0,
width: '100%',
height: '100%'
})
element.appendChild(canvas)
if (element === document.body) {
canvas.style.position = 'absolute'
extend(element.style, {
margin: 0,
padding: 0
})
}
function resize () {
var w = window.innerWidth
var h = window.innerHeight
if (element !== document.body) {
var bounds = canvas.getBoundingClientRect()
w = bounds.right - bounds.left
h = bounds.bottom - bounds.top
}
canvas.width = pixelRatio * w
canvas.height = pixelRatio * h
}
var resizeObserver
if (element !== document.body && typeof ResizeObserver === 'function') {
// ignore 'ResizeObserver' is not defined
// eslint-disable-next-line
resizeObserver = new ResizeObserver(function () {
// setTimeout to avoid flicker
setTimeout(resize)
})
resizeObserver.observe(element)
} else {
window.addEventListener('resize', resize, false)
}
function onDestroy () {
if (resizeObserver) {
resizeObserver.disconnect()
} else {
window.removeEventListener('resize', resize)
}
element.removeChild(canvas)
}
resize()
return {
canvas: canvas,
onDestroy: onDestroy
}
}
function createContext (canvas, contextAttributes) {
function get (name) {
try {
return canvas.getContext(name, contextAttributes)
} catch (e) {
return null
}
}
return (
get('webgl') ||
get('experimental-webgl') ||
get('webgl-experimental')
)
}
function isHTMLElement (obj) {
return (
typeof obj.nodeName === 'string' &&
typeof obj.appendChild === 'function' &&
typeof obj.getBoundingClientRect === 'function'
)
}
function isWebGLContext (obj) {
return (
typeof obj.drawArrays === 'function' ||
typeof obj.drawElements === 'function'
)
}
function parseExtensions (input) {
if (typeof input === 'string') {
return input.split()
}
return input
}
function getElement (desc) {
if (typeof desc === 'string') {
return document.querySelector(desc)
}
return desc
}
function parseArgs (args_) {
var args = args_ || {}
var element, container, canvas, gl
var contextAttributes = {}
var extensions = []
var optionalExtensions = []
var pixelRatio = (typeof window === 'undefined' ? 1 : window.devicePixelRatio)
var profile = false
var cachedCode = {}
var onDone = function (err) {
if (err) {
}
}
var onDestroy = function () {}
if (typeof args === 'string') {
element = document.querySelector(args)
} else if (typeof args === 'object') {
if (isHTMLElement(args)) {
element = args
} else if (isWebGLContext(args)) {
gl = args
canvas = gl.canvas
} else {
if ('gl' in args) {
gl = args.gl
} else if ('canvas' in args) {
canvas = getElement(args.canvas)
} else if ('container' in args) {
container = getElement(args.container)
}
if ('attributes' in args) {
contextAttributes = args.attributes
}
if ('extensions' in args) {
extensions = parseExtensions(args.extensions)
}
if ('optionalExtensions' in args) {
optionalExtensions = parseExtensions(args.optionalExtensions)
}
if ('onDone' in args) {
onDone = args.onDone
}
if ('profile' in args) {
profile = !!args.profile
}
if ('pixelRatio' in args) {
pixelRatio = +args.pixelRatio
}
if ('cachedCode' in args) {
cachedCode = args.cachedCode
}
}
} else {
}
if (element) {
if (element.nodeName.toLowerCase() === 'canvas') {
canvas = element
} else {
container = element
}
}
if (!gl) {
if (!canvas) {
var result = createCanvas(container || document.body, onDone, pixelRatio)
if (!result) {
return null
}
canvas = result.canvas
onDestroy = result.onDestroy
}
// workaround for chromium bug, premultiplied alpha value is platform dependent
if (contextAttributes.premultipliedAlpha === undefined) contextAttributes.premultipliedAlpha = true
gl = createContext(canvas, contextAttributes)
}
if (!gl) {
onDestroy()
onDone('webgl not supported, try upgrading your browser or graphics drivers http://get.webgl.org')
return null
}
return {
gl: gl,
canvas: canvas,
container: container,
extensions: extensions,
optionalExtensions: optionalExtensions,
pixelRatio: pixelRatio,
profile: profile,
cachedCode: cachedCode,
onDone: onDone,
onDestroy: onDestroy
}
}
function createExtensionCache (gl, config) {
var extensions = {}
function tryLoadExtension (name_) {
var name = name_.toLowerCase()
var ext
try {
ext = extensions[name] = gl.getExtension(name)
} catch (e) {}
return !!ext
}
for (var i = 0; i < config.extensions.length; ++i) {
var name = config.extensions[i]
if (!tryLoadExtension(name)) {
config.onDestroy()
config.onDone('"' + name + '" extension is not supported by the current WebGL context, try upgrading your system or a different browser')
return null
}
}
config.optionalExtensions.forEach(tryLoadExtension)
return {
extensions: extensions,
restore: function () {
Object.keys(extensions).forEach(function (name) {
if (extensions[name] && !tryLoadExtension(name)) {
throw new Error('(regl): error restoring extension ' + name)
}
})
}
}
}
function loop (n, f) {
var result = Array(n)
for (var i = 0; i < n; ++i) {
result[i] = f(i)
}
return result
}
var GL_BYTE = 5120
var GL_UNSIGNED_BYTE$1 = 5121
var GL_SHORT = 5122
var GL_UNSIGNED_SHORT = 5123
var GL_INT = 5124
var GL_UNSIGNED_INT = 5125
var GL_FLOAT$1 = 5126
function nextPow16 (v) {
for (var i = 16; i <= (1 << 28); i *= 16) {
if (v <= i) {
return i
}
}
return 0
}
function log2 (v) {
var r, shift
r = (v > 0xFFFF) << 4
v >>>= r
shift = (v > 0xFF) << 3
v >>>= shift; r |= shift
shift = (v > 0xF) << 2
v >>>= shift; r |= shift
shift = (v > 0x3) << 1
v >>>= shift; r |= shift
return r | (v >> 1)
}
function createPool () {
var bufferPool = loop(8, function () {
return []
})
function alloc (n) {
var sz = nextPow16(n)
var bin = bufferPool[log2(sz) >> 2]
if (bin.length > 0) {
return bin.pop()
}
return new ArrayBuffer(sz)
}
function free (buf) {
bufferPool[log2(buf.byteLength) >> 2].push(buf)
}
function allocType (type, n) {
var result = null
switch (type) {
case GL_BYTE:
result = new Int8Array(alloc(n), 0, n)
break
case GL_UNSIGNED_BYTE$1:
result = new Uint8Array(alloc(n), 0, n)
break
case GL_SHORT:
result = new Int16Array(alloc(2 * n), 0, n)
break
case GL_UNSIGNED_SHORT:
result = new Uint16Array(alloc(2 * n), 0, n)
break
case GL_INT:
result = new Int32Array(alloc(4 * n), 0, n)
break
case GL_UNSIGNED_INT:
result = new Uint32Array(alloc(4 * n), 0, n)
break
case GL_FLOAT$1:
result = new Float32Array(alloc(4 * n), 0, n)
break
default:
return null
}
if (result.length !== n) {
return result.subarray(0, n)
}
return result
}
function freeType (array) {
free(array.buffer)
}
return {
alloc: alloc,
free: free,
allocType: allocType,
freeType: freeType
}
}
var pool = createPool()
// zero pool for initial zero data
pool.zero = createPool()
var GL_SUBPIXEL_BITS = 0x0D50
var GL_RED_BITS = 0x0D52
var GL_GREEN_BITS = 0x0D53
var GL_BLUE_BITS = 0x0D54
var GL_ALPHA_BITS = 0x0D55
var GL_DEPTH_BITS = 0x0D56
var GL_STENCIL_BITS = 0x0D57
var GL_ALIASED_POINT_SIZE_RANGE = 0x846D
var GL_ALIASED_LINE_WIDTH_RANGE = 0x846E
var GL_MAX_TEXTURE_SIZE = 0x0D33
var GL_MAX_VIEWPORT_DIMS = 0x0D3A
var GL_MAX_VERTEX_ATTRIBS = 0x8869
var GL_MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB
var GL_MAX_VARYING_VECTORS = 0x8DFC
var GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS = 0x8B4D
var GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0x8B4C
var GL_MAX_TEXTURE_IMAGE_UNITS = 0x8872
var GL_MAX_FRAGMENT_UNIFORM_VECTORS = 0x8DFD
var GL_MAX_CUBE_MAP_TEXTURE_SIZE = 0x851C
var GL_MAX_RENDERBUFFER_SIZE = 0x84E8
var GL_VENDOR = 0x1F00
var GL_RENDERER = 0x1F01
var GL_VERSION = 0x1F02
var GL_SHADING_LANGUAGE_VERSION = 0x8B8C
var GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF
var GL_MAX_COLOR_ATTACHMENTS_WEBGL = 0x8CDF
var GL_MAX_DRAW_BUFFERS_WEBGL = 0x8824
var GL_TEXTURE_2D = 0x0DE1
var GL_TEXTURE_CUBE_MAP = 0x8513
var GL_TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515
var GL_TEXTURE0 = 0x84C0
var GL_RGBA = 0x1908
var GL_FLOAT = 0x1406
var GL_UNSIGNED_BYTE = 0x1401
var GL_FRAMEBUFFER = 0x8D40
var GL_FRAMEBUFFER_COMPLETE = 0x8CD5
var GL_COLOR_ATTACHMENT0 = 0x8CE0
var GL_COLOR_BUFFER_BIT$1 = 0x4000
var wrapLimits = function (gl, extensions) {
var maxAnisotropic = 1
if (extensions.ext_texture_filter_anisotropic) {
maxAnisotropic = gl.getParameter(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT)
}
var maxDrawbuffers = 1
var maxColorAttachments = 1
if (extensions.webgl_draw_buffers) {
maxDrawbuffers = gl.getParameter(GL_MAX_DRAW_BUFFERS_WEBGL)
maxColorAttachments = gl.getParameter(GL_MAX_COLOR_ATTACHMENTS_WEBGL)
}
// detect if reading float textures is available (Safari doesn't support)
var readFloat = !!extensions.oes_texture_float
if (readFloat) {
var readFloatTexture = gl.createTexture()
gl.bindTexture(GL_TEXTURE_2D, readFloatTexture)
gl.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_FLOAT, null)
var fbo = gl.createFramebuffer()
gl.bindFramebuffer(GL_FRAMEBUFFER, fbo)
gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, readFloatTexture, 0)
gl.bindTexture(GL_TEXTURE_2D, null)
if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) !== GL_FRAMEBUFFER_COMPLETE) readFloat = false
else {
gl.viewport(0, 0, 1, 1)
gl.clearColor(1.0, 0.0, 0.0, 1.0)
gl.clear(GL_COLOR_BUFFER_BIT$1)
var pixels = pool.allocType(GL_FLOAT, 4)
gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, pixels)
if (gl.getError()) readFloat = false
else {
gl.deleteFramebuffer(fbo)
gl.deleteTexture(readFloatTexture)
readFloat = pixels[0] === 1.0
}
pool.freeType(pixels)
}
}
// detect non power of two cube textures support (IE doesn't support)
var isIE = typeof navigator !== 'undefined' && (/MSIE/.test(navigator.userAgent) || /Trident\//.test(navigator.appVersion) || /Edge/.test(navigator.userAgent))
var npotTextureCube = true
if (!isIE) {
var cubeTexture = gl.createTexture()
var data = pool.allocType(GL_UNSIGNED_BYTE, 36)
gl.activeTexture(GL_TEXTURE0)
gl.bindTexture(GL_TEXTURE_CUBE_MAP, cubeTexture)
gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 3, 3, 0, GL_RGBA, GL_UNSIGNED_BYTE, data)
pool.freeType(data)
gl.bindTexture(GL_TEXTURE_CUBE_MAP, null)
gl.deleteTexture(cubeTexture)
npotTextureCube = !gl.getError()
}
return {
// drawing buffer bit depth
colorBits: [
gl.getParameter(GL_RED_BITS),
gl.getParameter(GL_GREEN_BITS),
gl.getParameter(GL_BLUE_BITS),
gl.getParameter(GL_ALPHA_BITS)
],
depthBits: gl.getParameter(GL_DEPTH_BITS),
stencilBits: gl.getParameter(GL_STENCIL_BITS),
subpixelBits: gl.getParameter(GL_SUBPIXEL_BITS),
// supported extensions
extensions: Object.keys(extensions).filter(function (ext) {
return !!extensions[ext]
}),
// max aniso samples
maxAnisotropic: maxAnisotropic,
// max draw buffers
maxDrawbuffers: maxDrawbuffers,
maxColorAttachments: maxColorAttachments,
// point and line size ranges
pointSizeDims: gl.getParameter(GL_ALIASED_POINT_SIZE_RANGE),
lineWidthDims: gl.getParameter(GL_ALIASED_LINE_WIDTH_RANGE),
maxViewportDims: gl.getParameter(GL_MAX_VIEWPORT_DIMS),
maxCombinedTextureUnits: gl.getParameter(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS),
maxCubeMapSize: gl.getParameter(GL_MAX_CUBE_MAP_TEXTURE_SIZE),
maxRenderbufferSize: gl.getParameter(GL_MAX_RENDERBUFFER_SIZE),
maxTextureUnits: gl.getParameter(GL_MAX_TEXTURE_IMAGE_UNITS),
maxTextureSize: gl.getParameter(GL_MAX_TEXTURE_SIZE),
maxAttributes: gl.getParameter(GL_MAX_VERTEX_ATTRIBS),
maxVertexUniforms: gl.getParameter(GL_MAX_VERTEX_UNIFORM_VECTORS),
maxVertexTextureUnits: gl.getParameter(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS),
maxVaryingVectors: gl.getParameter(GL_MAX_VARYING_VECTORS),
maxFragmentUniforms: gl.getParameter(GL_MAX_FRAGMENT_UNIFORM_VECTORS),
// vendor info
glsl: gl.getParameter(GL_SHADING_LANGUAGE_VERSION),
renderer: gl.getParameter(GL_RENDERER),
vendor: gl.getParameter(GL_VENDOR),
version: gl.getParameter(GL_VERSION),
// quirks
readFloat: readFloat,
npotTextureCube: npotTextureCube
}
}
var isTypedArray = function (x) {
return (
x instanceof Uint8Array ||
x instanceof Uint16Array ||
x instanceof Uint32Array ||
x instanceof Int8Array ||
x instanceof Int16Array ||
x instanceof Int32Array ||
x instanceof Float32Array ||
x instanceof Float64Array ||
x instanceof Uint8ClampedArray
)
}
function isNDArrayLike (obj) {
return (
!!obj &&
typeof obj === 'object' &&
Array.isArray(obj.shape) &&
Array.isArray(obj.stride) &&
typeof obj.offset === 'number' &&
obj.shape.length === obj.stride.length &&
(Array.isArray(obj.data) ||
isTypedArray(obj.data)))
}
var values = function (obj) {
return Object.keys(obj).map(function (key) { return obj[key] })
}
var flattenUtils = {
shape: arrayShape$1,
flatten: flattenArray
};
function flatten1D (array, nx, out) {
for (var i = 0; i < nx; ++i) {
out[i] = array[i]
}
}
function flatten2D (array, nx, ny, out) {
var ptr = 0
for (var i = 0; i < nx; ++i) {
var row = array[i]
for (var j = 0; j < ny; ++j) {
out[ptr++] = row[j]
}
}
}
function flatten3D (array, nx, ny, nz, out, ptr_) {
var ptr = ptr_
for (var i = 0; i < nx; ++i) {
var row = array[i]
for (var j = 0; j < ny; ++j) {
var col = row[j]
for (var k = 0; k < nz; ++k) {
out[ptr++] = col[k]
}
}
}
}
function flattenRec (array, shape, level, out, ptr) {
var stride = 1
for (var i = level + 1; i < shape.length; ++i) {
stride *= shape[i]
}
var n = shape[level]
if (shape.length - level === 4) {
var nx = shape[level + 1]
var ny = shape[level + 2]
var nz = shape[level + 3]
for (i = 0; i < n; ++i) {
flatten3D(array[i], nx, ny, nz, out, ptr)
ptr += stride
}
} else {
for (i = 0; i < n; ++i) {
flattenRec(array[i], shape, level + 1, out, ptr)
ptr += stride
}
}
}
function flattenArray (array, shape, type, out_) {
var sz = 1
if (shape.length) {
for (var i = 0; i < shape.length; ++i) {
sz *= shape[i]
}
} else {
sz = 0
}
var out = out_ || pool.allocType(type, sz)
switch (shape.length) {
case 0:
break
case 1:
flatten1D(array, shape[0], out)
break
case 2:
flatten2D(array, shape[0], shape[1], out)
break
case 3:
flatten3D(array, shape[0], shape[1], shape[2], out, 0)
break
default:
flattenRec(array, shape, 0, out, 0)
}
return out
}
function arrayShape$1 (array_) {
var shape = []
for (var array = array_; array.length; array = array[0]) {
shape.push(array.length)
}
return shape
}
var arrayTypes = {
"[object Int8Array]": 5120,
"[object Int16Array]": 5122,
"[object Int32Array]": 5124,
"[object Uint8Array]": 5121,
"[object Uint8ClampedArray]": 5121,
"[object Uint16Array]": 5123,
"[object Uint32Array]": 5125,
"[object Float32Array]": 5126,
"[object Float64Array]": 5121,
"[object ArrayBuffer]": 5121
};
var int8 = 5120;
var int16 = 5122;
var int32 = 5124;
var uint8 = 5121;
var uint16 = 5123;
var uint32 = 5125;
var float = 5126;
var float32 = 5126;
var glTypes = {
int8: int8,
int16: int16,
int32: int32,
uint8: uint8,
uint16: uint16,
uint32: uint32,
float: float,
float32: float32
};
var dynamic$1 = 35048;
var stream = 35040;
var usageTypes = {
dynamic: dynamic$1,
stream: stream,
"static": 35044
};
var arrayFlatten = flattenUtils.flatten
var arrayShape = flattenUtils.shape
var GL_STATIC_DRAW = 0x88E4
var GL_STREAM_DRAW = 0x88E0
var GL_UNSIGNED_BYTE$2 = 5121
var GL_FLOAT$2 = 5126
var DTYPES_SIZES = []
DTYPES_SIZES[5120] = 1 // int8
DTYPES_SIZES[5122] = 2 // int16
DTYPES_SIZES[5124] = 4 // int32
DTYPES_SIZES[5121] = 1 // uint8
DTYPES_SIZES[5123] = 2 // uint16
DTYPES_SIZES[5125] = 4 // uint32
DTYPES_SIZES[5126] = 4 // float32
function typedArrayCode (data) {
return arrayTypes[Object.prototype.toString.call(data)] | 0
}
function copyArray (out, inp) {
for (var i = 0; i < inp.length; ++i) {
out[i] = inp[i]
}
}
function transpose (
result, data, shapeX, shapeY, strideX, strideY, offset) {
var ptr = 0
for (var i = 0; i < shapeX; ++i) {
for (var j = 0; j < shapeY; ++j) {
result[ptr++] = data[strideX * i + strideY * j + offset]
}
}
}
function wrapBufferState (gl, stats, config, destroyBuffer) {
var bufferCount = 0
var bufferSet = {}
function REGLBuffer (type) {
this.id = bufferCount++
this.buffer = gl.createBuffer()
this.type = type
this.usage = GL_STATIC_DRAW
this.byteLength = 0
this.dimension = 1
this.dtype = GL_UNSIGNED_BYTE$2
this.persistentData = null
if (config.profile) {
this.stats = { size: 0 }
}
}
REGLBuffer.prototype.bind = function () {
gl.bindBuffer(this.type, this.buffer)
}
REGLBuffer.prototype.destroy = function () {
destroy(this)
}
var streamPool = []
function createStream (type, data) {
var buffer = streamPool.pop()
if (!buffer) {
buffer = new REGLBuffer(type)
}
buffer.bind()
initBufferFromData(buffer, data, GL_STREAM_DRAW, 0, 1, false)
return buffer
}
function destroyStream (stream$$1) {
streamPool.push(stream$$1)
}
function initBufferFromTypedArray (buffer, data, usage) {
buffer.byteLength = data.byteLength
gl.bufferData(buffer.type, data, usage)
}
function initBufferFromData (buffer, data, usage, dtype, dimension, persist) {
var shape
buffer.usage = usage
if (Array.isArray(data)) {
buffer.dtype = dtype || GL_FLOAT$2
if (data.length > 0) {
var flatData
if (Array.isArray(data[0])) {
shape = arrayShape(data)
var dim = 1
for (var i = 1; i < shape.length; ++i) {
dim *= shape[i]
}
buffer.dimension = dim
flatData = arrayFlatten(data, shape, buffer.dtype)
initBufferFromTypedArray(buffer, flatData, usage)
if (persist) {
buffer.persistentData = flatData
} else {
pool.freeType(flatData)
}
} else if (typeof data[0] === 'number') {
buffer.dimension = dimension
var typedData = pool.allocType(buffer.dtype, data.length)
copyArray(typedData, data)
initBufferFromTypedArray(buffer, typedData, usage)
if (persist) {
buffer.persistentData = typedData
} else {
pool.freeType(typedData)
}
} else if (isTypedArray(data[0])) {
buffer.dimension = data[0].length
buffer.dtype = dtype || typedArrayCode(data[0]) || GL_FLOAT$2
flatData = arrayFlatten(
data,
[data.length, data[0].length],
buffer.dtype)
initBufferFromTypedArray(buffer, flatData, usage)
if (persist) {
buffer.persistentData = flatData
} else {
pool.freeType(flatData)
}
} else {
}
}
} else if (isTypedArray(data)) {
buffer.dtype = dtype || typedArrayCode(data)
buffer.dimension = dimension
initBufferFromTypedArray(buffer, data, usage)
if (persist) {
buffer.persistentData = new Uint8Array(new Uint8Array(data.buffer))
}
} else if (isNDArrayLike(data)) {
shape = data.shape
var stride = data.stride
var offset = data.offset
var shapeX = 0
var shapeY = 0
var strideX = 0
var strideY = 0
if (shape.length === 1) {
shapeX = shape[0]
shapeY = 1
strideX = stride[0]
strideY = 0
} else if (shape.length === 2) {
shapeX = shape[0]
shapeY = shape[1]
strideX = stride[0]
strideY = stride[1]
} else {
}
buffer.dtype = dtype || typedArrayCode(data.data) || GL_FLOAT$2
buffer.dimension = shapeY
var transposeData = pool.allocType(buffer.dtype, shapeX * shapeY)
transpose(transposeData,
data.data,
shapeX, shapeY,
strideX, strideY,
offset)
initBufferFromTypedArray(buffer, transposeData, usage)
if (persist) {
buffer.persistentData = transposeData
} else {
pool.freeType(transposeData)
}
} else if (data instanceof ArrayBuffer) {
buffer.dtype = GL_UNSIGNED_BYTE$2
buffer.dimension = dimension
initBufferFromTypedArray(buffer, data, usage)
if (persist) {
buffer.persistentData = new Uint8Array(new Uint8Array(data))
}
} else {
}
}
function destroy (buffer) {
stats.bufferCount--
// remove attribute link
destroyBuffer(buffer)
var handle = buffer.buffer
gl.deleteBuffer(handle)
buffer.buffer = null
delete bufferSet[buffer.id]
}
function createBuffer (options, type, deferInit, persistent) {
stats.bufferCount++
var buffer = new REGLBuffer(type)
bufferSet[buffer.id] = buffer
function reglBuffer (options) {
var usage = GL_STATIC_DRAW
var data = null
var byteLength = 0
var dtype = 0
var dimension = 1
if (Array.isArray(options) ||
isTypedArray(options) ||
isNDArrayLike(options) ||
options instanceof ArrayBuffer) {
data = options
} else if (typeof options === 'number') {
byteLength = options | 0
} else if (options) {
if ('data' in options) {
data = options.data
}
if ('usage' in options) {
usage = usageTypes[options.usage]
}
if ('type' in options) {
dtype = glTypes[options.type]
}
if ('dimension' in options) {
dimension = options.dimension | 0
}
if ('length' in options) {
byteLength = options.length | 0
}
}
buffer.bind()
if (!data) {
// #475
if (byteLength) gl.bufferData(buffer.type, byteLength, usage)
buffer.dtype = dtype || GL_UNSIGNED_BYTE$2
buffer.usage = usage
buffer.dimension = dimension
buffer.byteLength = byteLength
} else {
initBufferFromData(buffer, data, usage, dtype, dimension, persistent)
}
if (config.profile) {
buffer.stats.size = buffer.byteLength * DTYPES_SIZES[buffer.dtype]
}
return reglBuffer
}
function setSubData (data, offset) {
gl.bufferSubData(buffer.type, offset, data)
}
function subdata (data, offset_) {
var offset = (offset_ || 0) | 0
var shape
buffer.bind()
if (isTypedArray(data) || data instanceof ArrayBuffer) {
setSubData(data, offset)
} else if (Array.isArray(data)) {
if (data.length > 0) {
if (typeof data[0] === 'number') {
var converted = pool.allocType(buffer.dtype, data.length)
copyArray(converted, data)
setSubData(converted, offset)
pool.freeType(converted)
} else if (Array.isArray(data[0]) || isTypedArray(data[0])) {
shape = arrayShape(data)
var flatData = arrayFlatten(data, shape, buffer.dtype)
setSubData(flatData, offset)
pool.freeType(flatData)
} else {
}
}
} else if (isNDArrayLike(data)) {
shape = data.shape
var stride = data.stride
var shapeX = 0
var shapeY = 0
var strideX = 0
var strideY = 0
if (shape.length === 1) {
shapeX = shape[0]
shapeY = 1
strideX = stride[0]
strideY = 0
} else if (shape.length === 2) {
shapeX = shape[0]
shapeY = shape[1]
strideX = stride[0]
strideY = stride[1]
} else {
}
var dtype = Array.isArray(data.data)
? buffer.dtype
: typedArrayCode(data.data)
var transposeData = pool.allocType(dtype, shapeX * shapeY)
transpose(transposeData,
data.data,
shapeX, shapeY,
strideX, strideY,
data.offset)
setSubData(transposeData, offset)
pool.freeType(transposeData)
} else {
}
return reglBuffer
}
if (!deferInit) {
reglBuffer(options)
}
reglBuffer._reglType = 'buffer'
reglBuffer._buffer = buffer
reglBuffer.subdata = subdata
if (config.profile) {
reglBuffer.stats = buffer.stats
}
reglBuffer.destroy = function () { destroy(buffer) }
return reglBuffer
}
function restoreBuffers () {
values(bufferSet).forEach(function (buffer) {
buffer.buffer = gl.createBuffer()
gl.bindBuffer(buffer.type, buffer.buffer)
gl.bufferData(
buffer.type, buffer.persistentData || buffer.byteLength, buffer.usage)
})
}
if (config.profile) {
stats.getTotalBufferSize = function () {
var total = 0
// TODO: Right now, the streams are not part of the total count.
Object.keys(bufferSet).forEach(function (key) {
total += bufferSet[key].stats.size
})
return total
}
}
return {
create: createBuffer,
createStream: createStream,
destroyStream: destroyStream,
clear: function () {
values(bufferSet).forEach(destroy)
streamPool.forEach(destroy)
},
getBuffer: function (wrapper) {
if (wrapper && wrapper._buffer instanceof REGLBuffer) {
return wrapper._buffer
}
return null
},
restore: restoreBuffers,
_initBuffer: initBufferFromData
}
}
var points = 0;
var point = 0;
var lines = 1;
var line = 1;
var triangles = 4;
var triangle = 4;
var primTypes = {
points: points,
point: point,
lines: lines,
line: line,
triangles: triangles,
triangle: triangle,
"line loop": 2,
"line strip": 3,
"triangle strip": 5,
"triangle fan": 6
};
var GL_POINTS = 0
var GL_LINES = 1
var GL_TRIANGLES = 4
var GL_BYTE$1 = 5120
var GL_UNSIGNED_BYTE$3 = 5121
var GL_SHORT$1 = 5122
var GL_UNSIGNED_SHORT$1 = 5123
var GL_INT$1 = 5124
var GL_UNSIGNED_INT$1 = 5125
var GL_ELEMENT_ARRAY_BUFFER = 34963
var GL_STREAM_DRAW$1 = 0x88E0
var GL_STATIC_DRAW$1 = 0x88E4
function wrapElementsState (gl, extensions, bufferState, stats) {
var elementSet = {}
var elementCount = 0
var elementTypes = {
'uint8': GL_UNSIGNED_BYTE$3,
'uint16': GL_UNSIGNED_SHORT$1
}
if (extensions.oes_element_index_uint) {
elementTypes.uint32 = GL_UNSIGNED_INT$1
}
function REGLElementBuffer (buffer) {
this.id = elementCount++
elementSet[this.id] = this
this.buffer = buffer
this.primType = GL_TRIANGLES
this.vertCount = 0
this.type = 0
}
REGLElementBuffer.prototype.bind = function () {
this.buffer.bind()
}
var bufferPool = []
function createElementStream (data) {
var result = bufferPool.pop()
if (!result) {
result = new REGLElementBuffer(bufferState.create(
null,
GL_ELEMENT_ARRAY_BUFFER,
true,
false)._buffer)
}
initElements(result, data, GL_STREAM_DRAW$1, -1, -1, 0, 0)
return result
}
function destroyElementStream (elements) {
bufferPool.push(elements)
}
function initElements (
elements,
data,
usage,
prim,
count,
byteLength,
type) {
elements.buffer.bind()
var dtype
if (data) {
var predictedType = type
if (!type && (
!isTypedArray(data) ||
(isNDArrayLike(data) && !isTypedArray(data.data)))) {
predictedType = extensions.oes_element_index_uint
? GL_UNSIGNED_INT$1
: GL_UNSIGNED_SHORT$1
}
bufferState._initBuffer(
elements.buffer,
data,
usage,
predictedType,
3)
} else {
gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, byteLength, usage)
elements.buffer.dtype = dtype || GL_UNSIGNED_BYTE$3
elements.buffer.usage = usage
elements.buffer.dimension = 3
elements.buffer.byteLength = byteLength
}
dtype = type
if (!type) {
switch (elements.buffer.dtype) {
case GL_UNSIGNED_BYTE$3:
case GL_BYTE$1:
dtype = GL_UNSIGNED_BYTE$3
break
case GL_UNSIGNED_SHORT$1:
case GL_SHORT$1:
dtype = GL_UNSIGNED_SHORT$1
break
case GL_UNSIGNED_INT$1:
case GL_INT$1:
dtype = GL_UNSIGNED_INT$1
break
default:
}
elements.buffer.dtype = dtype
}
elements.type = dtype
// Check oes_element_index_uint extension
// try to guess default primitive type and arguments
var vertCount = count
if (vertCount < 0) {
vertCount = elements.buffer.byteLength
if (dtype === GL_UNSIGNED_SHORT$1) {
vertCount >>= 1
} else if (dtype === GL_UNSIGNED_INT$1) {
vertCount >>= 2
}
}
elements.vertCount = vertCount
// try to guess primitive type from cell dimension
var primType = prim
if (prim < 0) {
primType = GL_TRIANGLES
var dimension = elements.buffer.dimension
if (dimension === 1) primType = GL_POINTS
if (dimension === 2) primType = GL_LINES
if (dimension === 3) primType = GL_TRIANGLES
}
elements.primType = primType
}
function destroyElements (elements) {
stats.elementsCount--
delete elementSet[elements.id]
elements.buffer.destroy()
elements.buffer = null
}
function createElements (options, persistent) {
var buffer = bufferState.create(null, GL_ELEMENT_ARRAY_BUFFER, true)
var elements = new REGLElementBuffer(buffer._buffer)
stats.elementsCount++
function reglElements (options) {
if (!options) {
buffer()
elements.primType = GL_TRIANGLES
elements.vertCount = 0
elements.type = GL_UNSIGNED_BYTE$3
} else if (typeof options === 'number') {
buffer(options)
elements.primType = GL_TRIANGLES
elements.vertCount = options | 0
elements.type = GL_UNSIGNED_BYTE$3
} else {
var data = null
var usage = GL_STATIC_DRAW$1
var primType = -1
var vertCount = -1
var byteLength = 0
var dtype = 0
if (Array.isArray(options) ||
isTypedArray(options) ||
isNDArrayLike(options)) {
data = options
} else {
if ('data' in options) {
data = options.data
}
if ('usage' in options) {
usage = usageTypes[options.usage]
}
if ('primitive' in options) {
primType = primTypes[options.primitive]
}
if ('count' in options) {
vertCount = options.count | 0
}
if ('type' in options) {
dtype = elementTypes[options.type]
}
if ('length' in options) {
byteLength = options.length | 0
} else {
byteLength = vertCount
if (dtype === GL_UNSIGNED_SHORT$1 || dtype === GL_SHORT$1) {
byteLength *= 2
} else if (dtype === GL_UNSIGNED_INT$1 || dtype === GL_INT$1) {
byteLength *= 4
}
}
}
initElements(
elements,
data,
usage,
primType,
vertCount,
byteLength,
dtype)
}
return reglElements
}
reglElements(options)
reglElements._reglType = 'elements'
reglElements._elements = elements
reglElements.subdata = function (data, offset) {
buffer.subdata(data, offset)
return reglElements
}
reglElements.destroy = function () {
destroyElements(elements)
}
return reglElements
}
return {
create: createElements,
createStream: createElementStream,
destroyStream: destroyElementStream,
getElements: function (elements) {
if (typeof elements === 'function' &&
elements._elements instanceof REGLElementBuffer) {
return elements._elements
}
return null
},
clear: function () {
values(elementSet).forEach(destroyElements)
}
}
}
var FLOAT = new Float32Array(1)
var INT = new Uint32Array(FLOAT.buffer)
var GL_UNSIGNED_SHORT$3 = 5123
function convertToHalfFloat (array) {
var ushorts = pool.allocType(GL_UNSIGNED_SHORT$3, array.length)
for (var i = 0; i < array.length; ++i) {
if (isNaN(array[i])) {
ushorts[i] = 0xffff
} else if (array[i] === Infinity) {
ushorts[i] = 0x7c00
} else if (array[i] === -Infinity) {
ushorts[i] = 0xfc00
} else {
FLOAT[0] = array[i]
var x = INT[0]
var sgn = (x >>> 31) << 15
var exp = ((x << 1) >>> 24) - 127
var frac = (x >> 13) & ((1 << 10) - 1)
if (exp < -24) {
// round non-representable denormals to 0
ushorts[i] = sgn
} else if (exp < -14) {
// handle denormals
var s = -14 - exp
ushorts[i] = sgn + ((frac + (1 << 10)) >> s)
} else if (exp > 15) {
// round overflow to +/- Infinity
ushorts[i] = sgn + 0x7c00
} else {
// otherwise convert directly
ushorts[i] = sgn + ((exp + 15) << 10) + frac
}
}
}
return ushorts
}
function isArrayLike (s) {
return Array.isArray(s) || isTypedArray(s)
}
var GL_COMPRESSED_TEXTURE_FORMATS = 0x86A3
var GL_TEXTURE_2D$1 = 0x0DE1
var GL_TEXTURE_CUBE_MAP$1 = 0x8513
var GL_TEXTURE_CUBE_MAP_POSITIVE_X$1 = 0x8515
var GL_RGBA$1 = 0x1908
var GL_ALPHA = 0x1906
var GL_RGB = 0x1907
var GL_LUMINANCE = 0x1909
var GL_LUMINANCE_ALPHA = 0x190A
var GL_RGBA4 = 0x8056
var GL_RGB5_A1 = 0x8057
var GL_RGB565 = 0x8D62
var GL_UNSIGNED_SHORT_4_4_4_4 = 0x8033
var GL_UNSIGNED_SHORT_5_5_5_1 = 0x8034
var GL_UNSIGNED_SHORT_5_6_5 = 0x8363
var GL_UNSIGNED_INT_24_8_WEBGL = 0x84FA
var GL_DEPTH_COMPONENT = 0x1902
var GL_DEPTH_STENCIL = 0x84F9
var GL_SRGB_EXT = 0x8C40
var GL_SRGB_ALPHA_EXT = 0x8C42
var GL_HALF_FLOAT_OES = 0x8D61
var GL_COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0
var GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1
var GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2
var GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3
var GL_COMPRESSED_RGB_ATC_WEBGL = 0x8C92
var GL_COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL = 0x8C93
var GL_COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL = 0x87EE
var GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00
var GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG = 0x8C01
var GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02
var GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG = 0x8C03
var GL_COMPRESSED_RGB_ETC1_WEBGL = 0x8D64
var GL_UNSIGNED_BYTE$4 = 0x1401
var GL_UNSIGNED_SHORT$2 = 0x1403
var GL_UNSIGNED_INT$2 = 0x1405
var GL_FLOAT$3 = 0x1406
var GL_TEXTURE_WRAP_S = 0x2802
var GL_TEXTURE_WRAP_T = 0x2803
var GL_REPEAT = 0x2901
var GL_CLAMP_TO_EDGE = 0x812F
var GL_MIRRORED_REPEAT = 0x8370
var GL_TEXTURE_MAG_FILTER = 0x2800
var GL_TEXTURE_MIN_FILTER = 0x2801
var GL_NEAREST = 0x2600
var GL_LINEAR = 0x2601
var GL_NEAREST_MIPMAP_NEAREST = 0x2700
var GL_LINEAR_MIPMAP_NEAREST = 0x2701
var GL_NEAREST_MIPMAP_LINEAR = 0x2702
var GL_LINEAR_MIPMAP_LINEAR = 0x2703
var GL_GENERATE_MIPMAP_HINT = 0x8192
var GL_DONT_CARE = 0x1100
var GL_FASTEST = 0x1101
var GL_NICEST = 0x1102
var GL_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FE
var GL_UNPACK_ALIGNMENT = 0x0CF5
var GL_UNPACK_FLIP_Y_WEBGL = 0x9240
var GL_UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241
var GL_UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243
var GL_BROWSER_DEFAULT_WEBGL = 0x9244
var GL_TEXTURE0$1 = 0x84C0
var MIPMAP_FILTERS = [
GL_NEAREST_MIPMAP_NEAREST,
GL_NEAREST_MIPMAP_LINEAR,
GL_LINEAR_MIPMAP_NEAREST,
GL_LINEAR_MIPMAP_LINEAR
]
var CHANNELS_FORMAT = [
0,
GL_LUMINANCE,
GL_LUMINANCE_ALPHA,
GL_RGB,
GL_RGBA$1
]
var FORMAT_CHANNELS = {}
FORMAT_CHANNELS[GL_LUMINANCE] =
FORMAT_CHANNELS[GL_ALPHA] =
FORMAT_CHANNELS[GL_DEPTH_COMPONENT] = 1
FORMAT_CHANNELS[GL_DEPTH_STENCIL] =
FORMAT_CHANNELS[GL_LUMINANCE_ALPHA] = 2
FORMAT_CHANNELS[GL_RGB] =
FORMAT_CHANNELS[GL_SRGB_EXT] = 3
FORMAT_CHANNELS[GL_RGBA$1] =
FORMAT_CHANNELS[GL_SRGB_ALPHA_EXT] = 4
function objectName (str) {
return '[object ' + str + ']'
}
var CANVAS_CLASS = objectName('HTMLCanvasElement')
var OFFSCREENCANVAS_CLASS = objectName('OffscreenCanvas')
var CONTEXT2D_CLASS = objectName('CanvasRenderingContext2D')
var BITMAP_CLASS = objectName('ImageBitmap')
var IMAGE_CLASS = objectName('HTMLImageElement')
var VIDEO_CLASS = objectName('HTMLVideoElement')
var PIXEL_CLASSES = Object.keys(arrayTypes).concat([
CANVAS_CLASS,
OFFSCREENCANVAS_CLASS,
CONTEXT2D_CLASS,
BITMAP_CLASS,
IMAGE_CLASS,
VIDEO_CLASS
])
// for every texture type, store
// the size in bytes.
var TYPE_SIZES = []
TYPE_SIZES[GL_UNSIGNED_BYTE$4] = 1
TYPE_SIZES[GL_FLOAT$3] = 4
TYPE_SIZES[GL_HALF_FLOAT_OES] = 2
TYPE_SIZES[GL_UNSIGNED_SHORT$2] = 2
TYPE_SIZES[GL_UNSIGNED_INT$2] = 4
var FORMAT_SIZES_SPECIAL = []
FORMAT_SIZES_SPECIAL[GL_RGBA4] = 2
FORMAT_SIZES_SPECIAL[GL_RGB5_A1] = 2
FORMAT_SIZES_SPECIAL[GL_RGB565] = 2
FORMAT_SIZES_SPECIAL[GL_DEPTH_STENCIL] = 4
FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGB_S3TC_DXT1_EXT] = 0.5
FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGBA_S3TC_DXT1_EXT] = 0.5
FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGBA_S3TC_DXT3_EXT] = 1
FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGBA_S3TC_DXT5_EXT] = 1
FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGB_ATC_WEBGL] = 0.5
FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL] = 1
FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL] = 1
FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG] = 0.5
FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG] = 0.25
FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG] = 0.5
FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG] = 0.25
FORMAT_SIZES_SPECIAL[GL_COMPRESSED_RGB_ETC1_WEBGL] = 0.5
function isNumericArray (arr) {
return (
Array.isArray(arr) &&
(arr.length === 0 ||
typeof arr[0] === 'number'))
}
function isRectArray (arr) {
if (!Array.isArray(arr)) {
return false
}
var width = arr.length
if (width === 0 || !isArrayLike(arr[0])) {
return false
}
return true
}
function classString (x) {
return Object.prototype.toString.call(x)
}
function isCanvasElement (object) {
return classString(object) === CANVAS_CLASS
}
function isOffscreenCanvas (object) {
return classString(object) === OFFSCREENCANVAS_CLASS
}
function isContext2D (object) {
return classString(object) === CONTEXT2D_CLASS
}
function isBitmap (object) {
return classString(object) === BITMAP_CLASS
}
function isImageElement (object) {
return classString(object) === IMAGE_CLASS
}
function isVideoElement (object) {
return classString(object) === VIDEO_CLASS
}
function isPixelData (object) {
if (!object) {
return false
}
var className = classString(object)
if (PIXEL_CLASSES.indexOf(className) >= 0) {
return true
}
return (
isNumericArray(object) ||
isRectArray(object) ||
isNDArrayLike(object))
}
function typedArrayCode$1 (data) {
return arrayTypes[Object.prototype.toString.call(data)] | 0
}
function convertData (result, data) {
var n = data.length
switch (result.type) {
case GL_UNSIGNED_BYTE$4:
case GL_UNSIGNED_SHORT$2:
case GL_UNSIGNED_INT$2:
case GL_FLOAT$3:
var converted = pool.allocType(result.type, n)
converted.set(data)
result.data = converted
break
case GL_HALF_FLOAT_OES:
result.data = convertToHalfFloat(data)
break
default:
}
}
function preConvert (image, n) {
return pool.allocType(
image.type === GL_HALF_FLOAT_OES
? GL_FLOAT$3
: image.type, n)
}
function postConvert (image, data) {
if (image.type === GL_HALF_FLOAT_OES) {
image.data = convertToHalfFloat(data)
pool.freeType(data)
} else {
image.data = data
}
}
function transposeData (image, array, strideX, strideY, strideC, offset) {
var w = image.width
var h = image.height
var c = image.channels
var n = w * h * c
var data = preConvert(image, n)
var p = 0
for (var i = 0; i < h; ++i) {
for (var j = 0; j < w; ++j) {
for (var k = 0; k < c; ++k) {
data[p++] = array[strideX * j + strideY * i + strideC * k + offset]
}
}
}
postConvert(image, data)
}
function getTextureSize (format, type, width, height, isMipmap, isCube) {
var s
if (typeof FORMAT_SIZES_SPECIAL[format] !== 'undefined') {
// we have a special array for dealing with weird color formats such as RGB5A1
s = FORMAT_SIZES_SPECIAL[format]
} else {
s = FORMAT_CHANNELS[format] * TYPE_SIZES[type]
}
if (isCube) {
s *= 6
}
if (isMipmap) {
// compute the total size of all the mipmaps.
var total = 0
var w = width
while (w >= 1) {
// we can only use mipmaps on a square image,
// so we can simply use the width and ignore the height:
total += s * w * w
w /= 2
}
return total
} else {
return s * width * height
}
}
function createTextureSet (
gl, extensions, limits, reglPoll, contextState, stats, config) {
// -------------------------------------------------------
// Initialize constants and parameter tables here
// -------------------------------------------------------
var mipmapHint = {
"don't care": GL_DONT_CARE,
'dont care': GL_DONT_CARE,
'nice': GL_NICEST,
'fast': GL_FASTEST
}
var wrapModes = {
'repeat': GL_REPEAT,
'clamp': GL_CLAMP_TO_EDGE,
'mirror': GL_MIRRORED_REPEAT
}
var magFilters = {
'nearest': GL_NEAREST,
'linear': GL_LINEAR
}
var minFilters = extend({
'mipmap': GL_LINEAR_MIPMAP_LINEAR,
'nearest mipmap nearest': GL_NEAREST_MIPMAP_NEAREST,
'linear mipmap nearest': GL_LINEAR_MIPMAP_NEAREST,
'nearest mipmap linear': GL_NEAREST_MIPMAP_LINEAR,
'linear mipmap linear': GL_LINEAR_MIPMAP_LINEAR
}, magFilters)
var colorSpace = {
'none': 0,
'browser': GL_BROWSER_DEFAULT_WEBGL
}
var textureTypes = {
'uint8': GL_UNSIGNED_BYTE$4,
'rgba4': GL_UNSIGNED_SHORT_4_4_4_4,
'rgb565': GL_UNSIGNED_SHORT_5_6_5,
'rgb5 a1': GL_UNSIGNED_SHORT_5_5_5_1
}
var textureFormats = {
'alpha': GL_ALPHA,
'luminance': GL_LUMINANCE,
'luminance alpha': GL_LUMINANCE_ALPHA,
'rgb': GL_RGB,
'rgba': GL_RGBA$1,
'rgba4': GL_RGBA4,
'rgb5 a1': GL_RGB5_A1,
'rgb565': GL_RGB565
}
var compressedTextureFormats = {}
if (extensions.ext_srgb) {
textureFormats.srgb = GL_SRGB_EXT
textureFormats.srgba = GL_SRGB_ALPHA_EXT
}
if (extensions.oes_texture_float) {
textureTypes.float32 = textureTypes.float = GL_FLOAT$3
}
if (extensions.oes_texture_half_float) {
textureTypes['float16'] = textureTypes['half float'] = GL_HALF_FLOAT_OES
}
if (extensions.webgl_depth_texture) {
extend(textureFormats, {
'depth': GL_DEPTH_COMPONENT,
'depth stencil': GL_DEPTH_STENCIL
})
extend(textureTypes, {
'uint16': GL_UNSIGNED_SHORT$2,
'uint32': GL_UNSIGNED_INT$2,
'depth stencil': GL_UNSIGNED_INT_24_8_WEBGL
})
}
if (extensions.webgl_compressed_texture_s3tc) {
extend(compressedTextureFormats, {
'rgb s3tc dxt1': GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
'rgba s3tc dxt1': GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
'rgba s3tc dxt3': GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
'rgba s3tc dxt5': GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
})
}
if (extensions.webgl_compressed_texture_atc) {
extend(compressedTextureFormats, {
'rgb atc': GL_COMPRESSED_RGB_ATC_WEBGL,
'rgba atc explicit alpha': GL_COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL,
'rgba atc interpolated alpha': GL_COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL
})
}
if (extensions.webgl_compressed_texture_pvrtc) {
extend(compressedTextureFormats, {
'rgb pvrtc 4bppv1': GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG,
'rgb pvrtc 2bppv1': GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG,
'rgba pvrtc 4bppv1': GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG,
'rgba pvrtc 2bppv1': GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
})
}
if (extensions.webgl_compressed_texture_etc1) {
compressedTextureFormats['rgb etc1'] = GL_COMPRESSED_RGB_ETC1_WEBGL
}
// Copy over all texture formats
var supportedCompressedFormats = Array.prototype.slice.call(
gl.getParameter(GL_COMPRESSED_TEXTURE_FORMATS))
Object.keys(compressedTextureFormats).forEach(function (name) {
var format = compressedTextureFormats[name]
if (supportedCompressedFormats.indexOf(format) >= 0) {
textureFormats[name] = format
}
})
var supportedFormats = Object.keys(textureFormats)
limits.textureFormats = supportedFormats
// associate with every format string its
// corresponding GL-value.
var textureFormatsInvert = []
Object.keys(textureFormats).forEach(function (key) {
var val = textureFormats[key]
textureFormatsInvert[val] = key
})
// associate with every type string its
// corresponding GL-value.
var textureTypesInvert = []
Object.keys(textureTypes).forEach(function (key) {
var val = textureTypes[key]
textureTyp