regl
Advanced tools
Comparing version 0.10.0 to 0.11.0
@@ -5,8 +5,2 @@ # Release notes | ||
* Cubic frame buffer objects | ||
* More performance monitoring hooks | ||
+ Track currently used resource requirements | ||
+ Output should be serializable -> works as input to constructor checks | ||
* Context loss | ||
@@ -16,5 +10,7 @@ | ||
* Comments for all core modules | ||
* Update contributing guidelines, make it easier for people to help out | ||
* Add a mechanism for users to specify minimum resource requirements (texture size, varying units, etc.) | ||
* More validation | ||
+ Should not be possible to write regl code that crashes on some systems | ||
@@ -31,3 +27,2 @@ * Benchmark suite | ||
+ Set up/quick start guides | ||
+ Examples on codepen/requirebin/regl.party | ||
+ Live coding videos on youtube | ||
@@ -38,10 +33,2 @@ + Talks? (what conferences can we present these results at?) | ||
* Testing | ||
+ Instancing | ||
+ Float textures / framebuffers and their filtering modes | ||
+ Constant attributes | ||
+ General code coverage | ||
* Build a website (preview at [regl.party](http://regl.party)) | ||
* Helper modules | ||
@@ -60,4 +47,12 @@ + A camera helper module to make getting started with 3D code easier | ||
## Next | ||
## 0.11.0 | ||
* Cubic frame buffer objects! | ||
* Can now use framebuffers as textures in uniforms. By default color attachment 0 is used. | ||
* Support for dynamic properties with nested objects like attributes | ||
* Alias `float16` for `half float` and `float32` for `float` | ||
* Many bug fixes and stability improvements | ||
* Website mostly works (preview at [regl.party](http://regl.party)) | ||
* Gallery of examples with movies | ||
## 0.10.0 | ||
@@ -64,0 +59,0 @@ |
@@ -17,2 +17,11 @@ var check = require('./util/check') | ||
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) { | ||
@@ -48,3 +57,3 @@ return arrayTypes[Object.prototype.toString.call(data)] | 0 | ||
module.exports = function wrapBufferState (gl, stats) { | ||
module.exports = function wrapBufferState (gl, stats, config) { | ||
var bufferCount = 0 | ||
@@ -61,2 +70,6 @@ var bufferSet = {} | ||
this.dtype = GL_UNSIGNED_BYTE | ||
if (config.profile) { | ||
this.stats = {size: 0} | ||
} | ||
} | ||
@@ -78,3 +91,2 @@ | ||
buffer = new REGLBuffer(type) | ||
buffer.buffer = gl.createBuffer() | ||
} | ||
@@ -246,2 +258,6 @@ buffer.bind() | ||
if (config.profile) { | ||
buffer.stats.size = buffer.byteLength * DTYPES_SIZES[buffer.dtype] | ||
} | ||
return reglBuffer | ||
@@ -325,2 +341,5 @@ } | ||
reglBuffer.subdata = subdata | ||
if (config.profile) { | ||
reglBuffer.stats = buffer.stats | ||
} | ||
reglBuffer.destroy = function () { destroy(buffer) } | ||
@@ -331,2 +350,13 @@ | ||
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 { | ||
@@ -340,2 +370,3 @@ create: createBuffer, | ||
values(bufferSet).forEach(destroy) | ||
streamPool.forEach(destroy) | ||
}, | ||
@@ -342,0 +373,0 @@ |
@@ -1,7 +0,4 @@ | ||
var check = require('./util/check') | ||
var VARIABLE_COUNTER = 0 | ||
var DYN_FUNC = 0 | ||
var DYN_PENDING_FLAG = 128 | ||
@@ -58,14 +55,3 @@ function DynamicVariable (type, data) { | ||
function defineDynamic (type, data) { | ||
switch (typeof data) { | ||
case 'boolean': | ||
case 'number': | ||
case 'string': | ||
return new DynamicVariable(type, toAccessorString(data + '')) | ||
case 'undefined': | ||
return new DynamicVariable(type | DYN_PENDING_FLAG, null) | ||
default: | ||
check.raise('invalid property type') | ||
} | ||
return new DynamicVariable(type, toAccessorString(data + '')) | ||
} | ||
@@ -79,9 +65,3 @@ | ||
function unbox (x, path) { | ||
if (x instanceof DynamicVariable) { | ||
if (x.type & DYN_PENDING_FLAG) { | ||
return new DynamicVariable( | ||
x.type & ~DYN_PENDING_FLAG, | ||
toAccessorString(path)) | ||
} | ||
} else if (typeof x === 'function') { | ||
if (typeof x === 'function') { | ||
return new DynamicVariable(DYN_FUNC, x) | ||
@@ -93,2 +73,3 @@ } | ||
module.exports = { | ||
DynamicVariable: DynamicVariable, | ||
define: defineDynamic, | ||
@@ -95,0 +76,0 @@ isDynamic: isDynamic, |
@@ -9,5 +9,2 @@ var check = require('./util/check') | ||
var name = name_.toLowerCase() | ||
if (name in extensions) { | ||
return true | ||
} | ||
var ext | ||
@@ -32,8 +29,4 @@ try { | ||
return { | ||
extensions: extensions, | ||
refresh: function () { | ||
config.extensions.forEach(tryLoadExtension) | ||
config.optionalExtensions.forEach(tryLoadExtension) | ||
} | ||
extensions: extensions | ||
} | ||
} |
@@ -28,6 +28,2 @@ var check = require('./util/check') | ||
var GL_RGBA = 0x1908 | ||
var GL_ALPHA = 0x1906 | ||
var GL_RGB = 0x1907 | ||
var GL_LUMINANCE = 0x1909 | ||
var GL_LUMINANCE_ALPHA = 0x190A | ||
@@ -37,6 +33,2 @@ var GL_DEPTH_COMPONENT = 0x1902 | ||
var colorTextureFormatEnums = [ | ||
GL_ALPHA, | ||
GL_LUMINANCE, | ||
GL_LUMINANCE_ALPHA, | ||
GL_RGB, | ||
GL_RGBA | ||
@@ -48,6 +40,2 @@ ] | ||
var textureFormatChannels = [] | ||
textureFormatChannels[GL_ALPHA] = 1 | ||
textureFormatChannels[GL_LUMINANCE] = 1 | ||
textureFormatChannels[GL_LUMINANCE_ALPHA] = 2 | ||
textureFormatChannels[GL_RGB] = 3 | ||
textureFormatChannels[GL_RGBA] = 4 | ||
@@ -101,3 +89,3 @@ | ||
var framebufferState = { | ||
current: null, | ||
cur: null, | ||
next: null, | ||
@@ -124,6 +112,6 @@ dirty: false | ||
if (extensions.oes_texture_half_float) { | ||
colorTypes.push('half float') | ||
colorTypes.push('half float', 'float16') | ||
} | ||
if (extensions.oes_texture_float) { | ||
colorTypes.push('float') | ||
colorTypes.push('float', 'float32') | ||
} | ||
@@ -215,3 +203,3 @@ | ||
if ('target' in attachment) { | ||
// target = attachment.target | 0 | ||
target = attachment.target | 0 | ||
} | ||
@@ -317,2 +305,3 @@ } | ||
var i | ||
gl.bindFramebuffer(GL_FRAMEBUFFER, framebuffer.framebuffer) | ||
@@ -338,3 +327,7 @@ var colorAttachments = framebuffer.colorAttachments | ||
gl.bindFramebuffer(GL_FRAMEBUFFER, framebufferState.next) | ||
framebufferState.current = framebufferState.next | ||
framebufferState.cur = framebufferState.next | ||
// FIXME: Clear error code here. This is a work around for a bug in | ||
// headless-gl | ||
gl.getError() | ||
} | ||
@@ -422,17 +415,22 @@ | ||
if ('colorType' in options) { | ||
check.oneOf( | ||
options.colorType, colorTypes, | ||
'invalid color type') | ||
colorType = options.colorType | ||
if (!colorTexture) { | ||
if (colorType === 'half float') { | ||
if (extensions.ext_color_buffer_half_float) { | ||
colorFormat = 'rgba16f' | ||
} | ||
} else if (colorType === 'float') { | ||
if (extensions.webgl_color_buffer_float) { | ||
colorFormat = 'rgba32f' | ||
} | ||
if (colorType === 'half float' || colorType === 'float16') { | ||
check(extensions.ext_color_buffer_half_float, | ||
'you must enable EXT_color_buffer_half_float to use 16-bit render buffers') | ||
colorFormat = 'rgba16f' | ||
} else if (colorType === 'float' || colorType === 'float32') { | ||
check(extensions.webgl_color_buffer_float, | ||
'you must enable WEBGL_color_buffer_float in order to use 32-bit floating point renderbuffers') | ||
colorFormat = 'rgba32f' | ||
} | ||
} else { | ||
check(extensions.oes_texture_float || | ||
!(colorType === 'float' || colorType === 'float32'), | ||
'you must enable OES_texture_float in order to use floating point framebuffer objects') | ||
check(extensions.oes_texture_half_float || | ||
!(colorType === 'half float' || colorType === 'float16'), | ||
'you must enable OES_texture_half_float in order to use 16-bit floating point framebuffer objects') | ||
} | ||
check.oneOf(colorType, colorTypes, 'invalid color type') | ||
} | ||
@@ -519,2 +517,4 @@ | ||
check(extensions.webgl_draw_buffers || colorAttachments.length <= 1, | ||
'you must enable the WEBGL_draw_buffers extension in order to use multiple color buffers.') | ||
check(colorAttachments.length <= limits.maxColorAttachments, | ||
@@ -663,11 +663,211 @@ 'too many color attachments, not supported') | ||
reglFramebuffer.resize = resize | ||
reglFramebuffer._reglType = 'framebuffer' | ||
reglFramebuffer._framebuffer = framebuffer | ||
reglFramebuffer.destroy = function () { | ||
destroy(framebuffer) | ||
decFBORefs(framebuffer) | ||
return extend(reglFramebuffer, { | ||
resize: resize, | ||
_reglType: 'framebuffer', | ||
_framebuffer: framebuffer, | ||
destroy: function () { | ||
destroy(framebuffer) | ||
decFBORefs(framebuffer) | ||
} | ||
}) | ||
} | ||
function createCubeFBO (options) { | ||
var faces = Array(6) | ||
function reglFramebufferCube (a) { | ||
var i | ||
check(faces.indexOf(framebufferState.next) < 0, | ||
'can not update framebuffer which is currently in use') | ||
var extDrawBuffers = extensions.webgl_draw_buffers | ||
var params = { | ||
color: null | ||
} | ||
var radius = 0 | ||
var colorBuffer = null | ||
var colorFormat = 'rgba' | ||
var colorType = 'uint8' | ||
var colorCount = 1 | ||
if (typeof a === 'number') { | ||
radius = a | 0 | ||
} else if (!a) { | ||
radius = 1 | ||
} else { | ||
check.type(a, 'object', 'invalid arguments for framebuffer') | ||
var options = a | ||
if ('shape' in options) { | ||
var shape = options.shape | ||
check( | ||
Array.isArray(shape) && shape.length >= 2, | ||
'invalid shape for framebuffer') | ||
check( | ||
shape[0] === shape[1], | ||
'cube framebuffer must be square') | ||
radius = shape[0] | ||
} else { | ||
if ('radius' in options) { | ||
radius = options.radius | 0 | ||
} | ||
if ('width' in options) { | ||
radius = options.width | 0 | ||
if ('height' in options) { | ||
check(options.height === radius, 'must be square') | ||
} | ||
} else if ('height' in options) { | ||
radius = options.height | 0 | ||
} | ||
} | ||
if ('color' in options || | ||
'colors' in options) { | ||
colorBuffer = | ||
options.color || | ||
options.colors | ||
if (Array.isArray(colorBuffer)) { | ||
check( | ||
colorBuffer.length === 1 || extDrawBuffers, | ||
'multiple render targets not supported') | ||
} | ||
} | ||
if (!colorBuffer) { | ||
if ('colorCount' in options) { | ||
colorCount = options.colorCount | 0 | ||
check(colorCount > 0, 'invalid color buffer count') | ||
} | ||
if ('colorType' in options) { | ||
check.oneOf( | ||
options.colorType, colorTypes, | ||
'invalid color type') | ||
colorType = options.colorType | ||
} | ||
if ('colorFormat' in options) { | ||
colorFormat = options.colorFormat | ||
check.oneOf( | ||
options.colorFormat, colorTextureFormats, | ||
'invalid color format for texture') | ||
} | ||
} | ||
if ('depth' in options) { | ||
params.depth = options.depth | ||
} | ||
if ('stencil' in options) { | ||
params.stencil = options.stencil | ||
} | ||
if ('depthStencil' in options) { | ||
params.depthStencil = options.depthStencil | ||
} | ||
} | ||
var colorCubes | ||
if (colorBuffer) { | ||
if (Array.isArray(colorBuffer)) { | ||
colorCubes = [] | ||
for (i = 0; i < colorBuffer.length; ++i) { | ||
colorCubes[i] = colorBuffer[i] | ||
} | ||
} else { | ||
colorCubes = [ colorBuffer ] | ||
} | ||
} else { | ||
colorCubes = Array(colorCount) | ||
var cubeMapParams = { | ||
radius: radius, | ||
format: colorFormat, | ||
type: colorType | ||
} | ||
for (i = 0; i < colorCount; ++i) { | ||
colorCubes[i] = textureState.createCube(cubeMapParams) | ||
} | ||
} | ||
// Check color cubes | ||
params.color = Array(colorCubes.length) | ||
for (i = 0; i < colorCubes.length; ++i) { | ||
var cube = colorCubes[i] | ||
check( | ||
typeof cube === 'function' && cube._reglType === 'textureCube', | ||
'invalid cube map') | ||
radius = radius || cube.width | ||
check( | ||
cube.width === radius && cube.height === radius, | ||
'invalid cube map shape') | ||
params.color[i] = { | ||
target: GL_TEXTURE_CUBE_MAP_POSITIVE_X, | ||
data: colorCubes[i] | ||
} | ||
} | ||
for (i = 0; i < 6; ++i) { | ||
for (var j = 0; j < colorCubes.length; ++j) { | ||
params.color[j].target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i | ||
} | ||
// reuse depth-stencil attachments across all cube maps | ||
if (i > 0) { | ||
params.depth = faces[0].depth | ||
params.stencil = faces[0].stencil | ||
params.depthStencil = faces[0].depthStencil | ||
} | ||
if (faces[i]) { | ||
(faces[i])(params) | ||
} else { | ||
faces[i] = createFBO(params) | ||
} | ||
} | ||
return extend(reglFramebufferCube, { | ||
width: radius, | ||
height: radius, | ||
color: colorCubes | ||
}) | ||
} | ||
return reglFramebuffer | ||
function resize (radius_) { | ||
var i | ||
var radius = radius_ | 0 | ||
check(radius > 0 && radius <= limits.maxCubeMapSize, | ||
'invalid radius for cube fbo') | ||
if (radius === reglFramebufferCube.width) { | ||
return reglFramebufferCube | ||
} | ||
var colors = reglFramebufferCube.color | ||
for (i = 0; i < colors.length; ++i) { | ||
colors[i].resize(radius) | ||
} | ||
for (i = 0; i < 6; ++i) { | ||
faces[i].resize(radius) | ||
} | ||
reglFramebufferCube.width = reglFramebufferCube.height = radius | ||
return reglFramebufferCube | ||
} | ||
reglFramebufferCube(options) | ||
return extend(reglFramebufferCube, { | ||
faces: faces, | ||
resize: resize, | ||
_reglType: 'framebufferCube', | ||
destroy: function () { | ||
faces.forEach(function (f) { | ||
f.destroy() | ||
}) | ||
} | ||
}) | ||
} | ||
@@ -686,2 +886,3 @@ | ||
create: createFBO, | ||
createCube: createCubeFBO, | ||
clear: function () { | ||
@@ -688,0 +889,0 @@ values(framebufferSet).forEach(destroy) |
@@ -7,2 +7,3 @@ var check = require('./util/check') | ||
var GL_PACK_ALIGNMENT = 0x0D05 | ||
var GL_FLOAT = 0x1406 // 5126 | ||
@@ -14,10 +15,26 @@ module.exports = function wrapReadPixels ( | ||
context, | ||
glAttributes) { | ||
glAttributes, | ||
extensions) { | ||
function readPixels (input) { | ||
if (framebufferState.current === null) { | ||
var type | ||
if (framebufferState.next === null) { | ||
check( | ||
glAttributes.preserveDrawingBuffer, | ||
'you must create a webgl context with "preserveDrawingBuffer":true in order to read pixels from the drawing buffer') | ||
type = GL_UNSIGNED_BYTE | ||
} else { | ||
// TODO check framebuffer supports read pixels | ||
check( | ||
framebufferState.next.colorAttachments[0].texture !== null, | ||
'You cannot read from a renderbuffer') | ||
type = framebufferState.next.colorAttachments[0].texture._texture.type | ||
if (extensions.oes_texture_float) { | ||
check( | ||
type === GL_UNSIGNED_BYTE || type === GL_FLOAT, | ||
'Reading from a framebuffer is only allowed for the types \'uint8\' and \'float\'') | ||
} else { | ||
check( | ||
type === GL_UNSIGNED_BYTE, | ||
'Reading from a framebuffer is only allowed for the type \'uint8\'') | ||
} | ||
} | ||
@@ -48,2 +65,15 @@ | ||
// sanity check input.data | ||
if (data) { | ||
if (type === GL_UNSIGNED_BYTE) { | ||
check( | ||
data instanceof Uint8Array, | ||
'buffer must be \'Uint8Array\' when reading from a framebuffer of type \'uint8\'') | ||
} else if (type === GL_FLOAT) { | ||
check( | ||
data instanceof Float32Array, | ||
'buffer must be \'Float32Array\' when reading from a framebuffer of type \'float\'') | ||
} | ||
} | ||
check( | ||
@@ -59,6 +89,2 @@ width > 0 && width + x <= context.framebufferWidth, | ||
// TODO: | ||
// float color buffers | ||
// implementation specific formats | ||
// Compute size | ||
@@ -68,3 +94,9 @@ var size = width * height * 4 | ||
// Allocate data | ||
data = data || new Uint8Array(size) | ||
if (!data) { | ||
if (type === GL_UNSIGNED_BYTE) { | ||
data = new Uint8Array(size) | ||
} else if (type === GL_FLOAT) { | ||
data = data || new Float32Array(size) | ||
} | ||
} | ||
@@ -77,3 +109,5 @@ // Type check | ||
gl.pixelStorei(GL_PACK_ALIGNMENT, 4) | ||
gl.readPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data) | ||
gl.readPixels(x, y, width, height, GL_RGBA, | ||
type, | ||
data) | ||
@@ -80,0 +114,0 @@ return data |
@@ -20,3 +20,22 @@ var check = require('./util/check') | ||
module.exports = function (gl, extensions, limits, stats) { | ||
var FORMAT_SIZES = [] | ||
FORMAT_SIZES[GL_RGBA4] = 2 | ||
FORMAT_SIZES[GL_RGB5_A1] = 2 | ||
FORMAT_SIZES[GL_RGB565] = 2 | ||
FORMAT_SIZES[GL_DEPTH_COMPONENT16] = 2 | ||
FORMAT_SIZES[GL_STENCIL_INDEX8] = 1 | ||
FORMAT_SIZES[GL_DEPTH_STENCIL] = 4 | ||
FORMAT_SIZES[GL_SRGB8_ALPHA8_EXT] = 4 | ||
FORMAT_SIZES[GL_RGBA32F_EXT] = 16 | ||
FORMAT_SIZES[GL_RGBA16F_EXT] = 8 | ||
FORMAT_SIZES[GL_RGB16F_EXT] = 6 | ||
function getRenderbufferSize (format, width, height) { | ||
return FORMAT_SIZES[format] * width * height | ||
} | ||
module.exports = function (gl, extensions, limits, stats, config) { | ||
var formatTypes = { | ||
@@ -56,2 +75,6 @@ 'rgba4': GL_RGBA4, | ||
this.height = 0 | ||
if (config.profile) { | ||
this.stats = {size: 0} | ||
} | ||
} | ||
@@ -142,2 +165,6 @@ | ||
if (config.profile) { | ||
renderbuffer.stats.size = getRenderbufferSize(renderbuffer.format, renderbuffer.width, renderbuffer.height) | ||
} | ||
return reglRenderbuffer | ||
@@ -166,2 +193,8 @@ } | ||
// also, recompute size. | ||
if (config.profile) { | ||
renderbuffer.stats.size = getRenderbufferSize( | ||
renderbuffer.format, renderbuffer.width, renderbuffer.height) | ||
} | ||
return reglRenderbuffer | ||
@@ -175,2 +208,5 @@ } | ||
reglRenderbuffer._renderbuffer = renderbuffer | ||
if (config.profile) { | ||
reglRenderbuffer.stats = renderbuffer.stats | ||
} | ||
reglRenderbuffer.destroy = function () { | ||
@@ -183,2 +219,12 @@ renderbuffer.decRef() | ||
if (config.profile) { | ||
stats.getTotalRenderbufferSize = function () { | ||
var total = 0 | ||
Object.keys(renderbufferSet).forEach(function (key) { | ||
total += renderbufferSet[key].stats.size | ||
}) | ||
return total | ||
} | ||
} | ||
return { | ||
@@ -185,0 +231,0 @@ create: createRenderbuffer, |
@@ -10,3 +10,3 @@ var check = require('./util/check') | ||
module.exports = function wrapShaderState (gl, stringStore, stats) { | ||
module.exports = function wrapShaderState (gl, stringStore, stats, config) { | ||
// =================================================== | ||
@@ -66,2 +66,9 @@ // glsl compilation and linking | ||
this.attributes = [] | ||
if (config.profile) { | ||
this.stats = { | ||
uniformsCount: 0, | ||
attributesCount: 0 | ||
} | ||
} | ||
} | ||
@@ -93,2 +100,5 @@ | ||
var numUniforms = gl.getProgramParameter(program, GL_ACTIVE_UNIFORMS) | ||
if (config.profile) { | ||
desc.stats.uniformsCount = numUniforms | ||
} | ||
var uniforms = desc.uniforms | ||
@@ -121,2 +131,6 @@ for (i = 0; i < numUniforms; ++i) { | ||
var numAttributes = gl.getProgramParameter(program, GL_ACTIVE_ATTRIBUTES) | ||
if (config.profile) { | ||
desc.stats.attributesCount = numAttributes | ||
} | ||
var attributes = desc.attributes | ||
@@ -135,2 +149,24 @@ for (i = 0; i < numAttributes; ++i) { | ||
if (config.profile) { | ||
stats.getMaxUniformsCount = function () { | ||
var m = 0 | ||
programList.forEach(function (desc) { | ||
if (desc.stats.uniformsCount > m) { | ||
m = desc.stats.uniformsCount | ||
} | ||
}) | ||
return m | ||
} | ||
stats.getMaxAttributesCount = function () { | ||
var m = 0 | ||
programList.forEach(function (desc) { | ||
if (desc.stats.attributesCount > m) { | ||
m = desc.stats.attributesCount | ||
} | ||
}) | ||
return m | ||
} | ||
} | ||
return { | ||
@@ -154,4 +190,4 @@ clear: function () { | ||
program: function (vertId, fragId, command) { | ||
check(vertId >= 0, 'missing vertex shader') | ||
check(fragId >= 0, 'missing fragment shader') | ||
check.command(vertId >= 0, 'missing vertex shader', command) | ||
check.command(fragId >= 0, 'missing fragment shader', command) | ||
@@ -176,5 +212,5 @@ stats.shaderCount++ | ||
frag: null, | ||
vert: null | ||
frag: -1, | ||
vert: -1 | ||
} | ||
} |
@@ -10,4 +10,6 @@ | ||
cubeCount: 0, | ||
renderbufferCount: 0 | ||
renderbufferCount: 0, | ||
maxTextureUnits: 0 | ||
} | ||
} |
@@ -117,4 +117,6 @@ var check = require('./util/check') | ||
FORMAT_CHANNELS[GL_LUMINANCE_ALPHA] = 2 | ||
FORMAT_CHANNELS[GL_RGB] = 3 | ||
FORMAT_CHANNELS[GL_RGBA] = 4 | ||
FORMAT_CHANNELS[GL_RGB] = | ||
FORMAT_CHANNELS[GL_SRGB_EXT] = 3 | ||
FORMAT_CHANNELS[GL_RGBA] = | ||
FORMAT_CHANNELS[GL_SRGB_ALPHA_EXT] = 4 | ||
@@ -144,2 +146,34 @@ var formatTypes = {} | ||
// for every texture type, store | ||
// the size in bytes. | ||
var TYPE_SIZES = [] | ||
TYPE_SIZES[GL_UNSIGNED_BYTE] = 1 | ||
TYPE_SIZES[GL_FLOAT] = 4 | ||
TYPE_SIZES[GL_HALF_FLOAT_OES] = 2 | ||
TYPE_SIZES[GL_UNSIGNED_SHORT] = 2 | ||
TYPE_SIZES[GL_UNSIGNED_INT] = 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) { | ||
@@ -292,4 +326,34 @@ return ( | ||
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 | ||
} | ||
} | ||
module.exports = function createTextureSet ( | ||
gl, extensions, limits, reglPoll, contextState, stats) { | ||
gl, extensions, limits, reglPoll, contextState, stats, config) { | ||
// ------------------------------------------------------- | ||
@@ -355,3 +419,3 @@ // Initialize constants and parameter tables here | ||
if (extensions.oes_texture_float) { | ||
textureTypes.float = GL_FLOAT | ||
textureTypes.float32 = textureTypes.float = GL_FLOAT | ||
} | ||
@@ -504,2 +568,11 @@ | ||
var type = options.type | ||
check(extensions.oes_texture_float || | ||
!(type === 'float' || type === 'float32'), | ||
'you must enable the OES_texture_float extension in order to use floating point textures.') | ||
check(extensions.oes_texture_half_float || | ||
!(type === 'half float' || type === 'float16'), | ||
'you must enable the OES_texture_half_float extension in order to use 16-bit floating point textures.') | ||
check(extensions.webgl_depth_texture || | ||
!(type === 'depth' || type === 'depth stencil'), | ||
'you must enable the WEBGL_depth_texture extension in order to use depth/stencil textures.') | ||
check.parameter(type, textureTypes, | ||
@@ -524,16 +597,16 @@ 'invalid texture type') | ||
} | ||
check(w > 0 && w <= limits.maxTextureSize, 'invalid width') | ||
check(h > 0 && h <= limits.maxTextureSize, 'invalid height') | ||
check(w >= 0 && w <= limits.maxTextureSize, 'invalid width') | ||
check(h >= 0 && h <= limits.maxTextureSize, 'invalid height') | ||
} else { | ||
if ('radius' in options) { | ||
w = h = options.radius | ||
check(w > 0 && w <= limits.maxTextureSize, 'invalid radius') | ||
check(w >= 0 && w <= limits.maxTextureSize, 'invalid radius') | ||
} | ||
if ('width' in options) { | ||
w = options.width | ||
check(w > 0 && w <= limits.maxTextureSize, 'invalid width') | ||
check(w >= 0 && w <= limits.maxTextureSize, 'invalid width') | ||
} | ||
if ('height' in options) { | ||
h = options.height | ||
check(h > 0 && h <= limits.maxTextureSize, 'invalid height') | ||
check(h >= 0 && h <= limits.maxTextureSize, 'invalid height') | ||
} | ||
@@ -553,2 +626,5 @@ if ('channels' in options) { | ||
var formatStr = options.format | ||
check(extensions.webgl_depth_texture || | ||
!(formatStr === 'depth' || formatStr === 'depth stencil'), | ||
'you must enable the WEBGL_depth_texture extension in order to use depth/stencil textures.') | ||
check.parameter(formatStr, textureFormats, | ||
@@ -726,2 +802,4 @@ 'invalid texture format') | ||
} | ||
// do compressed texture validation here. | ||
} | ||
@@ -842,2 +920,21 @@ | ||
copyFlags(mipmap, mipmap.images[0]) | ||
// For textures of the compressed format WEBGL_compressed_texture_s3tc | ||
// we must have that | ||
// | ||
// "When level equals zero width and height must be a multiple of 4. | ||
// When level is greater than 0 width and height must be 0, 1, 2 or a multiple of 4. " | ||
// | ||
// but we do not yet support having multiple mipmap levels for compressed textures, | ||
// so we only test for level zero. | ||
if (mipmap.compressed && | ||
(mipmap.internalformat === GL_COMPRESSED_RGB_S3TC_DXT1_EXT) || | ||
(mipmap.internalformat === GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) || | ||
(mipmap.internalformat === GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) || | ||
(mipmap.internalformat === GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)) { | ||
check(mipmap.width % 4 === 0 && | ||
mipmap.height % 4 === 0, | ||
'for compressed texture formats, mipmap level 0 must have width and height that are a multiple of 4') | ||
} | ||
} | ||
@@ -1026,2 +1123,6 @@ | ||
this.bindCount = 0 | ||
if (config.profile) { | ||
this.stats = {size: 0} | ||
} | ||
} | ||
@@ -1083,2 +1184,5 @@ | ||
} | ||
if (config.profile && stats.maxTextureUnits < (unit + 1)) { | ||
stats.maxTextureUnits = unit + 1 // +1, since the units are zero-based | ||
} | ||
texture.unit = unit | ||
@@ -1147,2 +1251,12 @@ gl.activeTexture(GL_TEXTURE0 + unit) | ||
if (config.profile) { | ||
texture.stats.size = getTextureSize( | ||
texture.internalformat, | ||
texture.type, | ||
mipData.width, | ||
mipData.height, | ||
texInfo.genMipmaps, | ||
false) | ||
} | ||
return reglTexture2D | ||
@@ -1203,14 +1317,27 @@ } | ||
tempBind(texture) | ||
gl.texImage2D( | ||
GL_TEXTURE_2D, | ||
0, | ||
texture.format, | ||
w, | ||
h, | ||
0, | ||
texture.format, | ||
texture.type, | ||
null) | ||
for (var i = 0; texture.mipmask >> i; ++i) { | ||
gl.texImage2D( | ||
GL_TEXTURE_2D, | ||
i, | ||
texture.format, | ||
w >> i, | ||
h >> i, | ||
0, | ||
texture.format, | ||
texture.type, | ||
null) | ||
} | ||
tempRestore() | ||
// also, recompute the texture size. | ||
if (config.profile) { | ||
texture.stats.size = getTextureSize( | ||
texture.internalformat, | ||
texture.type, | ||
w, | ||
h, | ||
false, | ||
false) | ||
} | ||
return reglTexture2D | ||
@@ -1225,2 +1352,5 @@ } | ||
reglTexture2D._texture = texture | ||
if (config.profile) { | ||
reglTexture2D.stats = texture.stats | ||
} | ||
reglTexture2D.destroy = function () { | ||
@@ -1303,2 +1433,12 @@ texture.decRef() | ||
if (config.profile) { | ||
texture.stats.size = getTextureSize( | ||
texture.internalformat, | ||
texture.type, | ||
reglTextureCube.width, | ||
reglTextureCube.height, | ||
texInfo.genMipmaps, | ||
true) | ||
} | ||
freeInfo(texInfo) | ||
@@ -1356,27 +1496,38 @@ | ||
function resize (w_, h_) { | ||
var w = w_ | 0 | ||
var h = (h_ | 0) || w | ||
if (w === texture.width && h === texture.height) { | ||
return reglTextureCube | ||
function resize (radius_) { | ||
var radius = radius_ | 0 | ||
if (radius === texture.width) { | ||
return | ||
} | ||
reglTextureCube.width = texture.width = w | ||
reglTextureCube.height = texture.height = h | ||
reglTextureCube.width = texture.width = radius | ||
reglTextureCube.height = texture.height = radius | ||
tempBind(texture) | ||
for (var i = 0; i < 6; ++i) { | ||
gl.texImage2D( | ||
GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, | ||
0, | ||
texture.format, | ||
w, | ||
h, | ||
0, | ||
texture.format, | ||
texture.type, | ||
null) | ||
for (var j = 0; texture.mipmask >> j; ++j) { | ||
gl.texImage2D( | ||
GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, | ||
j, | ||
texture.format, | ||
radius >> j, | ||
radius >> j, | ||
0, | ||
texture.format, | ||
texture.type, | ||
null) | ||
} | ||
} | ||
tempRestore() | ||
if (config.profile) { | ||
texture.stats.size = getTextureSize( | ||
texture.internalformat, | ||
texture.type, | ||
reglTextureCube.width, | ||
reglTextureCube.height, | ||
false, | ||
true) | ||
} | ||
return reglTextureCube | ||
@@ -1391,2 +1542,5 @@ } | ||
reglTextureCube._texture = texture | ||
if (config.profile) { | ||
reglTextureCube.stats = texture.stats | ||
} | ||
reglTextureCube.destroy = function () { | ||
@@ -1412,2 +1566,12 @@ texture.decRef() | ||
if (config.profile) { | ||
stats.getTotalTextureSize = function () { | ||
var total = 0 | ||
Object.keys(textureSet).forEach(function (key) { | ||
total += textureSet[key].stats.size | ||
}) | ||
return total | ||
} | ||
} | ||
return { | ||
@@ -1414,0 +1578,0 @@ create2D: createTexture2D, |
@@ -201,2 +201,5 @@ // Error checking and parameter validation. | ||
errLog.split('\n').forEach(function (errMsg) { | ||
if (errMsg.length < 5) { | ||
return | ||
} | ||
var parts = /^ERROR\:\s+(\d+)\:(\d+)\:\s*(.*)$/.exec(errMsg) | ||
@@ -203,0 +206,0 @@ if (parts) { |
@@ -76,3 +76,6 @@ var extend = require('./extend') | ||
return extend(entry, { | ||
return extend(function () { | ||
entry.apply(entry, slice(arguments)) | ||
}, { | ||
def: entry.def, | ||
entry: entry, | ||
@@ -168,3 +171,2 @@ exit: exit, | ||
var proc = Function.apply(null, linkedNames.concat(src)) | ||
// console.log('src: ', src) | ||
return proc.apply(null, linkedValues) | ||
@@ -171,0 +173,0 @@ } |
{ | ||
"name": "regl", | ||
"version": "0.10.0", | ||
"version": "0.11.0", | ||
"description": "Regl is a fast functional reactive abstraction for WebGL.", | ||
@@ -20,4 +20,7 @@ "main": "regl.js", | ||
"control-panel": "^1.2.0", | ||
"conway-hart": "^0.1.0", | ||
"disc": "^1.3.2", | ||
"falafel": "^1.2.0", | ||
"faucet": "0.0.1", | ||
"fuse-vertices": "^0.1.2", | ||
"getusermedia": "^1.3.7", | ||
@@ -47,4 +50,5 @@ "git-commits": "^1.2.0", | ||
"standard": "^6.0.7", | ||
"tap-browser-color": "^0.1.2", | ||
"tape": "^4.4.0", | ||
"teapot": "^1.0.0", | ||
"three": "^0.79.0", | ||
"through2": "^2.0.1", | ||
@@ -62,3 +66,4 @@ "vectorize-text": "^3.0.2" | ||
"bench-history": "node bench/bench-history", | ||
"build": "npm run build-script && npm run build-min && npm run build-bench && npm run build-gallery", | ||
"build": "npm run build-script && npm run build-min && npm run build-bench && npm run build-gallery && npm run size", | ||
"size": "browserify --full-paths --transform ./bin/remove-check.js regl.js | discify > www/size.html", | ||
"build-script": "browserify regl.js --standalone reglInit > dist/regl.js", | ||
@@ -65,0 +70,0 @@ "build-min": "node bin/build-min.js", |
280
README.md
@@ -84,3 +84,3 @@ # regl | ||
Check out the [gallery](http://regl.party/examples). | ||
Check out the [gallery](https://mikolalysenko.github.io/regl/www/gallery.html). The source code of all the gallery examples can be found [here](https://github.com/mikolalysenko/regl/tree/gh-pages/example). | ||
@@ -104,14 +104,30 @@ ## Setup | ||
#### Standalone script tag | ||
You can also use `regl` as a standalone script if you are really stubborn. The most recent versions can be found under the [releases tab](releases). To do this, add the following script tag to your HTML: | ||
You can also use `regl` as a standalone script if you are really stubborn. The most recent versions can be found in the `dist/` folder. Alternatively, you can directly import regl using npm cdn. | ||
* Unminified: | ||
```html | ||
<script src="[some cdn tbd]/regl.min.js"></script> | ||
<script src="https://npmcdn.com/regl/dist/regl.js"></script> | ||
``` | ||
* Minified: | ||
```html | ||
<script src="https://npmcdn.com/regl/dist/regl.min.js"></script> | ||
``` | ||
## Why use `regl`? | ||
`regl` is basically all of WebGL without all of the shared state. You can do anything you could in regular WebGL with little overhead and way less debugging. | ||
`regl` is basically all of WebGL without all of the shared state. You can do anything you could in regular WebGL with little overhead and way less debugging. Selling points of `regl` are: | ||
* `regl` makes it easy to load extensions and to adapt the program after the limits of the target device, and exposes many WebGL extensions for easy usage. See [API.md](API.md) for more info. | ||
* `regl`, in difference to many other WebGL frameworks, has support for easy usage of instanced rendering. See [this example](https://github.com/mikolalysenko/regl/blob/gh-pages/example/instance-triangle.js) for more details. | ||
* `regl` integrates easily with modules from `stack.gl`, such `gl-mat4` and `gl-vec3`. | ||
* `regl` is small and bloat-free; A minimized version of [`three.js`](http://threejs.org/) is ~500Kb, while a minimized version of `regl` is only `71Kb`. | ||
* `regl` has little overhead, and is near as fast as hand-optimized WebGL. You can compare the performance at the [interactive benchmarks](https://mikolalysenko.github.io/regl/www/bench.html). The benchmark `cube` measures the performance of rendering a textured cube in `regl`, and `cube-webgl` does the same thing, but in raw WebGL. And `cube-threejs` does the same thing, but in `three.js`. In particular, notice how much faster `regl` is than `three.js` | ||
* `regl` performs strong error validation and sanity checking in debug builds. But for production builds of `regl`, all validation will be stripped away. | ||
### Comparisons | ||
In this section, we show how you can implement a spinning textured cube in `regl`, and compare it with other WebGL frameworks. | ||
In this section, we show how you can implement a spinning textured cube in `regl`, and compare it with other WebGL frameworks. | ||
@@ -545,6 +561,79 @@ ![](images/cube_example.png) | ||
#### [three.js]() | ||
TODO | ||
#### [three.js](https://mikolalysenko.github.io/regl/compare/threejs_cube.html) | ||
```html | ||
<!doctype html> | ||
<html> | ||
<head> | ||
<title>threejs cube</title> | ||
<meta content="text/html;charset=utf-8" http-equiv="Content-Type"> | ||
<meta content="utf-8" http-equiv="encoding"> | ||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r79/three.min.js"></script> | ||
<script type="text/javascript"> | ||
var scene; | ||
var camera; | ||
var renderer; | ||
var mesh; | ||
var tick; | ||
function start() { | ||
init(); | ||
drawShape(); | ||
render(); | ||
} | ||
function drawShape() { | ||
var geo = new THREE.CubeGeometry(1.0, 1.0, 1.0); | ||
var texture = THREE.ImageUtils.loadTexture('../example/assets/lena.png'); | ||
var mats = []; | ||
for (var i = 0; i < 6; i++) { | ||
mats.push(new THREE.MeshBasicMaterial({map: texture})); | ||
} | ||
var mat = new THREE.MeshFaceMaterial(mats); | ||
mesh = new THREE.Mesh(geo, mat); | ||
scene.add(mesh); | ||
tick = 0; | ||
} | ||
function init() { | ||
scene = new THREE.Scene(); | ||
var canvas = document.getElementById('glcanvas'); | ||
renderer = new THREE.WebGLRenderer({canvas: canvas}); | ||
renderer.setPixelRatio( window.devicePixelRatio ); | ||
renderer.setSize( window.innerWidth, window.innerHeight ); | ||
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 100 ); | ||
} | ||
function rotateCube() { | ||
tick += 1 | ||
var t = tick * 0.01 | ||
camera.position.set(5 * Math.cos(t), 2.5 * Math.sin(t), 5 * Math.sin(t)) | ||
camera.up = new THREE.Vector3(0, 1, 0) | ||
camera.lookAt(new THREE.Vector3(0, 0, 0)) | ||
} | ||
function render() { | ||
requestAnimationFrame(render); | ||
rotateCube(); | ||
renderer.render(scene, camera); | ||
} | ||
</script> | ||
</head> | ||
<body onload="start()"> | ||
<canvas id="glcanvas" width="640" height="480"> | ||
Your browser doesn't appear to support the <code><canvas></code> element. | ||
</canvas> | ||
</body> | ||
</html> | ||
``` | ||
### Benchmarks | ||
@@ -555,82 +644,103 @@ You can run benchmarks locally using `npm run bench` or check them out here: | ||
## [API](API.md) | ||
You can also check out our benchmarking results for the last couple of days: | ||
* [Initialization](API.md#initialization) | ||
- [As a fullscreen canvas](API.md#as-a-fullscreen-canvas) | ||
- [From a container div](API.md#from-a-container-div) | ||
- [From a canvas](API.md#from-a-canvas) | ||
- [From a WebGL context](API.md#from-a-webgl-context) | ||
+ [Initialization options](API.md#initialization-options) | ||
* [Commands](API.md#commands) | ||
+ [Executing commands](API.md#executing-commands) | ||
- [One-shot rendering](API.md#one-shot-rendering) | ||
- [Batch rendering](API.md#batch-rendering) | ||
- [Scoped commands](API.md#scoped-commands) | ||
+ [Inputs](API.md#inputs) | ||
- [Context](API.md#context) | ||
- [Props](API.md#props) | ||
- [`this`](API.md#this) | ||
+ [Parameters](API.md#parameters) | ||
- [Shaders](API.md#shaders) | ||
- [Uniforms](API.md#uniforms) | ||
- [Attributes](API.md#attributes) | ||
- [Drawing](API.md#drawing) | ||
- [Render target](API.md#render-target) | ||
- [Profiling](API.md#profiling) | ||
- [Depth buffer](API.md#depth-buffer) | ||
- [Blending](API.md#blending) | ||
- [Stencil](API.md#stencil) | ||
- [Polygon offset](API.md#polygon-offset) | ||
- [Culling](API.md#culling) | ||
- [Front face](API.md#front-face) | ||
- [Dithering](API.md#dithering) | ||
- [Line width](API.md#line-width) | ||
- [Color mask](API.md#color-mask) | ||
- [Sample coverage](API.md#sample-coverage) | ||
- [Scissor](API.md#scissor) | ||
- [Viewport](API.md#viewport) | ||
* [Resources](API.md#resources) | ||
+ [Buffers](API.md#buffers) | ||
- [Constructor](API.md#constructor) | ||
- [Update](API.md#update) | ||
- [Destroy](API.md#destroy) | ||
+ [Elements](API.md#elements) | ||
- [Constructor](API.md#constructor-1) | ||
- [Update](API.md#update-1) | ||
- [Destroy](API.md#destroy-1) | ||
+ [Textures](API.md#textures) | ||
- [Constructor](API.md#constructor-2) | ||
- [Update](API.md#update-2) | ||
- [Destroy](API.md#destroy-2) | ||
+ [Cube maps](API.md#cube-maps) | ||
- [Constructor](API.md#constructor-3) | ||
- [Update](API.md#update-3) | ||
- [Destroy](API.md#destroy-3) | ||
+ [Render buffers](API.md#render-buffers) | ||
- [Constructor](API.md#constructor-4) | ||
- [Update](API.md#update-4) | ||
- [Destroy](API.md#destroy-4) | ||
+ [Framebuffers](API.md#framebuffers) | ||
- [Constructor](API.md#constructor-5) | ||
- [Update](API.md#update-5) | ||
- [Destroy](API.md#destroy-5) | ||
+ [Cubic frame buffers](API.md#cubic-frame-buffers) | ||
- [Constructor](API.md#constructor-6) | ||
- [Update](API.md#update-6) | ||
- [Destroy](API.md#destroy-6) | ||
* [Other features](API.md#other-features) | ||
+ [Clear the draw buffer](API.md#clear-the-draw-buffer) | ||
+ [Reading pixels](API.md#reading-pixels) | ||
+ [Per-frame callbacks](API.md#per-frame-callbacks) | ||
+ [Device capabilities and limits](API.md#device-capabilities-and-limits) | ||
+ [Performance metrics](API.md#performance-metrics) | ||
+ [Clean up](API.md#clean-up) | ||
+ [Context loss](API.md#context-loss) | ||
+ [Unsafe escape hatch](API.md#unsafe-escape-hatch) | ||
* [Tips](API.md#tips) | ||
+ [Reuse resources (API.mdbuffers, elements, textures, etc.)](API.md#reuse-resources--buffers--elements--textures--etc-) | ||
+ [Preallocate memory](API.md#preallocate-memory) | ||
+ [Debug vs release](API.md#debug-vs-release) | ||
+ [Context loss mitigation](API.md#context-loss-mitigation) | ||
* [Benchmarking Results](https://mikolalysenko.github.io/regl/www/bench-results/bench-result-8ea4a7e806beed0b9732) | ||
The benchmarking results were created by using our custom scripts `bench-history` and | ||
`bench-graph`. You can read more about them in [DEVELOPING.md](DEVELOPING.md). | ||
## [API](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md) | ||
* [Initialization](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#initialization) | ||
- [As a fullscreen canvas](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#as-a-fullscreen-canvas) | ||
- [From a container div](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#from-a-container-div) | ||
- [From a canvas](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#from-a-canvas) | ||
- [From a WebGL context](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#from-a-webgl-context) | ||
+ [All initialization options](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#all-initialization-options) | ||
* [Commands](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#commands) | ||
+ [Executing commands](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#executing-commands) | ||
- [One-shot rendering](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#one-shot-rendering) | ||
- [Batch rendering](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#batch-rendering) | ||
- [Scoped commands](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#scoped-commands) | ||
+ [Inputs](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#inputs) | ||
- [Example](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#example) | ||
- [Context](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#context) | ||
- [Props](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#props) | ||
- [`this`](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#-this-) | ||
+ [Parameters](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#parameters) | ||
- [Shaders](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#shaders) | ||
- [Uniforms](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#uniforms) | ||
- [Attributes](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#attributes) | ||
- [Drawing](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#drawing) | ||
- [Render target](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#render-target) | ||
- [Profiling](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#profiling) | ||
- [Depth buffer](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#depth-buffer) | ||
- [Blending](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#blending) | ||
- [Stencil](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#stencil) | ||
- [Polygon offset](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#polygon-offset) | ||
- [Culling](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#culling) | ||
- [Front face](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#front-face) | ||
- [Dithering](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#dithering) | ||
- [Line width](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#line-width) | ||
- [Color mask](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#color-mask) | ||
- [Sample coverage](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#sample-coverage) | ||
- [Scissor](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#scissor) | ||
- [Viewport](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#viewport) | ||
* [Resources](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#resources) | ||
+ [Buffers](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#buffers) | ||
- [Constructor](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#constructor) | ||
- [Update](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#update) | ||
* [In place update](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#in-place-update) | ||
- [Destroy](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#destroy) | ||
- [Profiling](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#profiling-1) | ||
+ [Elements](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#elements) | ||
- [Constructor](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#constructor-1) | ||
- [Update](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#update-1) | ||
* [In-place update](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#in-place-update) | ||
- [Destroy](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#destroy-1) | ||
+ [Textures](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#textures) | ||
- [Constructor](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#constructor-2) | ||
- [Update](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#update-2) | ||
* [Partial update](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#partial-update) | ||
* [Resize](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#resize) | ||
- [Destroy](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#destroy-2) | ||
- [Profiling](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#profiling-2) | ||
+ [Cube maps](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#cube-maps) | ||
- [Constructor](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#constructor-3) | ||
- [Update](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#update-3) | ||
* [In-place update](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#in-place-update-1) | ||
- [Profiling](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#profiling-3) | ||
- [Destroy](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#destroy-3) | ||
+ [Render buffers](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#render-buffers) | ||
- [Constructor](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#constructor-4) | ||
- [Update](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#update-4) | ||
* [Resizing](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#resizing) | ||
- [Destroy](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#destroy-4) | ||
- [Profiling](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#profiling-4) | ||
+ [Framebuffers](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#framebuffers) | ||
- [Constructor](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#constructor-5) | ||
- [Update](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#update-5) | ||
* [Resizing](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#resizing-1) | ||
- [Destroy](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#destroy-5) | ||
+ [Cubic frame buffers](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#cubic-frame-buffers) | ||
- [Constructor](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#constructor-6) | ||
- [Update](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#update-6) | ||
- [Destroy](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#destroy-6) | ||
* [Other features](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#other-features) | ||
+ [Clear the draw buffer](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#clear-the-draw-buffer) | ||
+ [Reading pixels](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#reading-pixels) | ||
+ [Per-frame callbacks](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#per-frame-callbacks) | ||
+ [Extensions](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#extensions) | ||
+ [Device capabilities and limits](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#device-capabilities-and-limits) | ||
+ [Performance metrics](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#performance-metrics) | ||
+ [Clean up](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#clean-up) | ||
+ [Context loss](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#context-loss) | ||
+ [Unsafe escape hatch](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#unsafe-escape-hatch) | ||
* [Tips](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#tips) | ||
+ [Reuse resources (buffers, elements, textures, etc.)](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#reuse-resources--buffers--elements--textures--etc-) | ||
+ [Preallocate memory](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#preallocate-memory) | ||
+ [Debug vs release](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#debug-vs-release) | ||
+ [Profiling](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#profiling-5) | ||
+ [Context loss mitigation](https://github.com/mikolalysenko/regl/blob/gh-pages/API.md#context-loss-mitigation) | ||
## Development | ||
@@ -637,0 +747,0 @@ The latest changes in `regl` can be found in the [CHANGELOG](CHANGES.md). |
17
regl.js
@@ -88,3 +88,3 @@ var check = require('./lib/util/check') | ||
var limits = wrapLimits(gl, extensions) | ||
var bufferState = wrapBuffers(gl, stats) | ||
var bufferState = wrapBuffers(gl, stats, config) | ||
var elementState = wrapElements(gl, extensions, bufferState, stats) | ||
@@ -97,3 +97,3 @@ var attributeState = wrapAttributes( | ||
stringStore) | ||
var shaderState = wrapShaders(gl, stringStore, stats) | ||
var shaderState = wrapShaders(gl, stringStore, stats, config) | ||
var textureState = wrapTextures( | ||
@@ -105,4 +105,5 @@ gl, | ||
contextState, | ||
stats) | ||
var renderbufferState = wrapRenderbuffers(gl, extensions, limits, stats) | ||
stats, | ||
config) | ||
var renderbufferState = wrapRenderbuffers(gl, extensions, limits, stats, config) | ||
var framebufferState = wrapFramebuffers( | ||
@@ -136,3 +137,3 @@ gl, | ||
contextState, | ||
glAttributes) | ||
glAttributes, extensions) | ||
@@ -290,2 +291,4 @@ var nextState = core.next | ||
// FIXME: we should modify code generation for batch commands so this | ||
// isn't necessary | ||
var EMPTY_ARRAY = [] | ||
@@ -444,5 +447,3 @@ function reserve (count) { | ||
framebuffer: framebufferState.create, | ||
framebufferCube: function (options) { | ||
check.raise('framebuffer cube not yet implemented') | ||
}, | ||
framebufferCube: framebufferState.createCube, | ||
@@ -449,0 +450,0 @@ // Expose context attributes |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
16022
761
643098
43
42