Socket
Socket
Sign inDemoInstall

regl

Package Overview
Dependencies
Maintainers
1
Versions
42
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

regl - npm Package Compare versions

Comparing version 0.1.0 to 0.2.0

lib/constants/blendequations.json

355

API.md

@@ -8,2 +8,3 @@ # REGL API

* [From a WebGL context](#from-a-webgl-context)
+ [Initialization options](#initialization-options)
* [Commands](#commands)

@@ -20,3 +21,3 @@ + [Dynamic properties](#dynamic-properties)

- [Drawing](#drawing)
- [Framebuffer](#framebuffer)
- [Render target](#render-target)
- [Depth buffer](#depth-buffer)

@@ -39,8 +40,8 @@ - [Blending](#blending)

+ [Types](#types)
- [`regl.buffer(options)`](#-reglbuffer-options--)
- [`regl.elements(options)`](#-reglelements-options--)
- [`regl.texture(options)`](#-regltexture-options--)
- [`regl.rbo(options)`](#-reglrbo-options--)
- [`regl.fbo(options)`](#-reglfbo-options--)
* [Other properties](#other-properties)
- [Buffers](#buffers)
- [Elements](#elements)
- [Textures](#textures)
- [Render buffers](#render-buffers)
- [Frame buffers](#frame-buffers)
* [Other features](#other-features)
+ [Clear the draw buffer](#clear-the-draw-buffer)

@@ -50,3 +51,3 @@ + [Reading pixels](#reading-pixels)

+ [Frame stats](#frame-stats)
+ [WebGL capabilities](#webgl-capabilities)
+ [Limits](#limits)
+ [Clean up](#clean-up)

@@ -93,2 +94,6 @@ + [Context loss](#context-loss)

### Initialization options
**TODO**
---------------------------------------

@@ -432,3 +437,3 @@ ## Commands

---------------------------------------
#### Framebuffer
#### Render target

@@ -526,3 +531,6 @@ TODO

| `'reverse subtract'` | `gl.FUNC_REVERSE_SUBTRACT` |
| `'min'` | `gl.MIN_EXT` |
| `'max'` | `gl.MAX_EXT` |
* `'min'` and `'max'` are only available if the `EXT_blend_minmax` extension is supported
* `func` can be an object with the fields `{src, dst}` or `{srcRGB, srcAlpha, dstRGB, dstAlpha}`, with the former corresponding to `gl.blendFunc` and the latter to `gl.blendFuncSeparate`

@@ -922,12 +930,60 @@ * The fields of `func` can take on the following values

#### Buffers
Examples,
```javascript
// Creates an empty length 100 buffer
var zeroBuffer = regl.buffer(100)
// A buffer with float data
var floatBuffer = regl.buffer(new Float32Array([1, 2, 3, 4]))
// A streaming buffer of bytes
var streamBuffer = regl.buffer({
usage: 'stream',
data: new Uint8Array([2, 4, 6, 8, 10])
})
// An unpacked buffer of position data
var positionBuffer = regl.buffer([
[1, 2, 3],
[4, 5, 6],
[2, 1, -2]
])
```
| Property | Description | Default |
|----------|-------------|---------|
| `data` | | `null` |
| `length` | | `0` |
| `usage` | | `'static'` |
| `data` | The data for the vertex buffer (see below) | `null` |
| `length` | If `data` is `null` or not present reserves space for the buffer | `0` |
| `usage` | Sets array buffer usage hint | `'static'` |
| Usage Hint | Description |
|------------|-------------|
| `'static'` | `gl.DRAW_STATIC` |
| `'dynamic'` | `gl.DYNAMIC_DRAW` |
| `'stream'` | `gl.STREAM_DRAW` |
**Relevant WebGL APIs**
* [`gl.createBuffer`](https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCreateBuffer.xml)
* [`gl.deleteBuffer`](https://www.khronos.org/opengles/sdk/docs/man/xhtml/glDeleteBuffer.xml)
* [`gl.bufferData`](https://www.khronos.org/opengles/sdk/docs/man/xhtml/glBufferData.xml)
---------------------------------------
#### Elements
Examples,
```javascript
var triElements = regl.elements([
[1, 2, 3],
[0, 2, 5]
])
var starElements = regl.elements({
primitive: 'line loop',
count: 5,
data: new Uint8Array([0, 2, 4, 1, 3])
})
```
| Property | Description | Default |

@@ -941,8 +997,231 @@ |----------|-------------|---------|

* `usage` must take on one of the following values
| Usage Hint | Description |
|------------|-------------|
| `'static'` | `gl.DRAW_STATIC` |
| `'dynamic'` | `gl.DYNAMIC_DRAW` |
| `'stream'` | `gl.STREAM_DRAW` |
* `primitive` can be one of the following primitive types
| Primitive type | Description |
|-------|-------------|
| `'points'` | `gl.POINTS` |
| `'lines'` | gl.LINES` |
| `'line strip'` | `gl.LINE_STRIP` |
| `'line loop` | `gl.LINE_LOOP` |
| `'triangles` | `gl.TRIANGLES` |
| `'triangle strip'` | `gl.TRIANGLE_STRIP` |
| `'triangle fan'` | `gl.TRIANGLE_FAN` |
**Relevant WebGL APIs**
* [`gl.createBuffer`](https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCreateBuffer.xml)
* [`gl.deleteBuffer`](https://www.khronos.org/opengles/sdk/docs/man/xhtml/glDeleteBuffer.xml)
* [`gl.bufferData`](https://www.khronos.org/opengles/sdk/docs/man/xhtml/glBufferData.xml)
* [`gl.drawElements`](https://www.khronos.org/opengles/sdk/docs/man/xhtml/glDrawElements.xml)
---------------------------------------
#### Textures
There are many ways to upload data to a texture in WebGL. As with drawing commands, regl consolidates all of these crazy configuration parameters into one function. Here are some examples of how to create a texture,
**NOT YET IMPLEMENTED**
```javascript
// From size parameters
var emptyTexture = regl.texture({
shape: [16, 16]
})
// From a flat array
var typedArrayTexture = regl.texture({
width: 2,
height: 2,
data: [
255, 255, 255, 255, 0, 0, 0, 0,
255, 0, 255, 255, 0, 0, 255, 255
]
})
// From a square array
var nestedArrayTexture = regl.texture([
[ [0, 255, 0], [255, 0, 0] ],
[ [0, 0, 255], [255, 255, 255] ]
])
// From an ndarray-like object
var ndarrayTexture = regl.texture(require('baboon-image'))
// Manual mipmap specification
var mipmapTexture = regl.texture({
minFilter: 'mipmap'
})
// From an image element
var image = new Image()
image.src = 'http://mydomain.com/myimage.png'
var imageTexture = regl.texture(image)
// From a canvas
var canvas = document.createElement(canvas)
var context2D = canvas.getContext('2d')
var canvasTexture = regl.texture(canvas)
var otherCanvasTexture = regl.texture(context2D)
// From a video element
var video = document.querySelector('video')
var videoTexture = regl.texture(video)
// From the pixels in the current frame buffer
var copyPixels = regl.texture({
x: 5,
y: 1,
width: 10,
height: 10,
copy: true
})
```
A data source from an image can be one of the following types:
| Data type | Description |
|-----------|-------------|
| Rectangular array of arrays | Interpreted as 2D array of arrays |
| Typed array | A binary array of pixel values |
| Array | Interpreted as array of pixel values with type based on the input type |
| `ndarray` | Any object with a `shape, stride, offset, data` |
| Image | An HTML image element |
| Video | An HTML video element |
| Canvas | A canvas element |
| Context 2D | A canvas 2D context |
| String | A URL to an image or video to load |
| Property | Description | Default |
|----------|-------------|---------|
| `width` | Width of texture | `0` |
| `height` | Height of texture | `0`
| `mag` | Sets magnification filter (see table) | `'nearest'` |
| `min` | Sets minification filter (see table) | `'nearest'` |
| `wrapS` | Sets wrap mode on S axis (see table) | `'repeat'` |
| `wrapT` | Sets wrap mode on T axis (see table) | `'repeat'` |
| `aniso` | Sets number of anisotropic samples, requires [EXT_texture_filter_anisotropic](https://www.khronos.org/registry/webgl/extensions/EXT_texture_filter_anisotropic/) | `0` |
| `format` | Texture format (see table) | `'rgba'` |
| `type` | Texture type (see table) | `'uint8'` |
| `data` | Input data (see below) | |
| `mipmap` | If set, regenerate mipmaps | `false` |
| `flipY` | Flips textures vertically when uploading | `false` |
| `alignment` | Sets unpack alignment per pixel | `1` |
| `premultiplyAlpha` | Premultiply alpha when unpacking | `false` |
| `colorSpace` | Sets colorspace conversion | `'browser'` |
| `poll` | If set, then each frame check if this texture needs to be reuploaded | Depends on the element type |
| `data` | Image data for the texture |
| `crossOrigin` | Cross origin resource sharing URL |
* `shape` can be used as an array shortcut for `[width, height, channels]` of image
* `radius` can be specified for square images and sets both `width` and `height`
* `data` can take one of the following values,
* If an image element is specified and not yet loaded, then regl will upload a temporary image and hook a callback on the image
* If a video element is specified, then regl will reupload a frame of the video element each tick unless `poll` is set to false
* `mag` sets `gl.MAG_FILTER` for the texture and can have one of the following values
| Mag filter | Description |
|------------|-------------|
| `'nearest'` | `gl.NEAREST` |
| `'linear'` | `gl.LINEAR` |
* `min` sets `gl.MIN_FILTER` for the texture, and can take on one of the following values,
| Min filter | Description |
|------------|-------------|
| `'nearest'` | `gl.NEAREST` |
| `'linear'` | `gl.LINEAR` |
| `'mipmap', 'linear mipmap linear'` | `gl.LINEAR_MIPMAP_LINEAR` |
| `'nearest mipmap linear'` | `gl.NEAREST_MIPMAP_LINEAR` |
| `'linear mipmap nearest'` | `gl.LINEAR_MIPMAP_NEAREST` |
| `'nearest mipmap nearest'` | `gl.NEAREST_MIPMAP_NEAREST` |
* `wrap` can be used as an array shortcut for `[wrapS, wrapT]`
* `wrapS` and `wrapT` can have any of the following values,
| Wrap mode | Description |
|-----------|-------------|
| `'repeat'` | `gl.REPEAT` |
| `'clamp'` | `gl.CLAMP_TO_EDGE` |
| `'mirror'` | `gl.MIRRORED_REPEAT` |
* `format` determines the format of the texture and possibly the type. Possible values for `format` include,
| Format | Description | Channels | Types | Compressed? | Extension? |
|--------|-------------|----------|-------|------|------------|
| `'alpha'` | `gl.ALPHA` | 1 | `'uint8','half float','float'` | ✖ | |
| `'luminance'` | `gl.LUMINANCE` | 1 | `'uint8','half float','float'` | ✖ | |
| `'luminance alpha'` | `gl.LUMINANCE_ALPHA` | 2 | `'uint8','half float','float'` | ✖ | |
| `'rgb'` | `gl.RGB` | 3 | `'uint8','half float','float'` | ✖ | |
| `'rgba'` | `gl.RGBA` | 4 | `'uint8','half float','float'`| ✖ | |
| `'rgba4'` | `gl.RGBA4` | 4 | `'rgba4'` | ✖ | |
| `'rgb5 a1'` | `gl.RGB5_A1` | 4 | `'rgb5 a1'` | ✖ | |
| `'rgb5'` | `gl.RGB5` | 3 | `'rgb5'` | ✖ | |
| `'srgb'` | `ext.SRGB` | 3 | `'uint8','half float','float'` | ✖ | [EXT_sRGB](https://www.khronos.org/registry/webgl/extensions/EXT_sRGB/) |
| `'srgba'` | `ext.RGBA` | 4 | `'uint8','half float','float'`| ✖ | [EXT_sRGB](https://www.khronos.org/registry/webgl/extensions/EXT_sRGB/) |
| `'depth'` | `gl.DEPTH_COMPONENT` | 1 | `'uint16','uint32'` | ✖ | [WEBGL_depth_texture](https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/) |
| `'depth stencil'` | `gl.DEPTH_STENCIL` | 2 | `'depth stencil'` | ✖ | [WEBGL_depth_texture](https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/) |
| `'rgb s3tc dxt1'` | `ext.COMPRESSED_RGB_S3TC_DXT1_EXT` | 3 | `'uint8'` | ✓ | [WEBGL_compressed_texture_s3tc](https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_s3tc/) |
| `'rgba s3tc dxt1'` | `ext.COMPRESSED_RGBA_S3TC_DXT1_EXT` | 4 | `'uint8'` | ✓ | [WEBGL_compressed_texture_s3tc](https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_s3tc/) |
| `'rgba s3tc dxt3'` | `ext.COMPRESSED_RGBA_S3TC_DXT3_EXT` | 4 | `'uint8'` | ✓ | [WEBGL_compressed_texture_s3tc](https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_s3tc/) |
| `'rgba s3tc dxt5'` | `ext.COMPRESSED_RGBA_S3TC_DXT5_EXT` | 4 | `'uint8'` | ✓ | [WEBGL_compressed_texture_s3tc](https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_s3tc/) |
| `'rgb arc'` | `ext.COMPRESSED_RGB_ATC_WEBGL` | 3 | `'uint8'` | ✓ | [WEBGL_compressed_texture_atc](https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_atc/) |
| `'rgba arc explicit alpha'` | `ext.COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL` | 4 | `'uint8'` | ✓ | [WEBGL_compressed_texture_atc](https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_atc/) |
| `'rgba arc interpolated alpha'` | `ext.COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL` | 4 | `'uint8'` | ✓ | [WEBGL_compressed_texture_atc](https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_atc/) |
| 'rgb pvrtc 4bppv1' | `ext.COMPRESSED_RGB_PVRTC_4BPPV1_IMG` | 3 | `'uint8'` | ✓ | [WEBGL_compressed_texture_pvrtc](https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_pvrtc/) |
| 'rgb pvrtc 2bppv1' | `ext.COMPRESSED_RGB_PVRTC_2BPPV1_IMG` | 3 | `'uint8'` | ✓ | [WEBGL_compressed_texture_pvrtc](https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_pvrtc/) |
| 'rgba pvrtc 4bppv1' | `ext.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG` | 4 | `'uint8'` | ✓ | [WEBGL_compressed_texture_pvrtc](https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_pvrtc/) |
| 'rgba pvrtc 2bppv1' | `ext.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG` | 4 | `'uint8'` | ✓ | [WEBGL_compressed_texture_pvrtc](https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_pvrtc/) |
| `'rgb etc1'` | `ext.COMPRESSED_RGB_ETC1_WEBGL` | 3 | `'uint8'` | ✓ | [WEBGL_compressed_texture_etc1](https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_etc1/) |
* In many cases `type` can be inferred from the format and other information in the texture. However, in some situations it may still be necessary to set it manually. In such an event, the following values are possible,
| Type | Description |
|------|-------------|
| `'uint8'` | `gl.UNSIGNED_BYTE` |
| `'uint16'` | `gl.UNSIGNED_SHORT` |
| `'uint32'` | `gl.UNSIGNED_INT` |
| `'float'` | `gl.FLOAT` |
| `'half float'` | `ext.HALF_FLOAT_OES` |
* `colorSpace` sets the WebGL color space flag for pixel unpacking
| Color space | Description |
|------------|-------------|
| `'none'` | `gl.NONE` |
| `'browser'` | `gl.BROWSER_DEFAULT_WEBGL` |
* `unpackAlignment` sets the pixel unpack alignment and must be one of `[1, 2, 4, 8]`
**Relevant WebGL APIs**
* [`gl.createTexture`](https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCreateTexture.xml)
* [`gl.deleteTexture`](https://www.khronos.org/opengles/sdk/docs/man/xhtml/glDeleteTexture.xml)
* [`gl.texParameter`](https://www.khronos.org/opengles/sdk/docs/man/xhtml/glTexParameter.xml)
* [`gl.pixelStorei`](https://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)
* [`gl.texImage2D`](https://www.khronos.org/opengles/sdk/docs/man/xhtml/glTexImage2D.xml)
* [`gl.texImage2D`](https://www.khronos.org/opengles/sdk/docs/man/xhtml/glTexImage2D.xml)
* [`gl.compressedTexImage2D`](https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCompressedTexImage2D.xml)
* [`gl.copyTexImage2D`](https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCopyTexImage2D.xml)
* [`gl.generateMipmap`](https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGenerateMipmap.xml)
---------------------------------------
#### Cube maps
Cube maps follow similar syntax to textures. They are created using `regl.cube()`
```javascript
var cubeMap = regl.cube(
'posx.jpg',
'negx.jpg',
'posy.jpg',
'negy.jpg',
'posz.jpg',
'negz.jpg')
```
---------------------------------------
#### Render buffers

@@ -969,3 +1248,3 @@

depth: 1,
stencil: 0xff
stencil: 0
})

@@ -977,7 +1256,14 @@ ```

| `color` | Sets the clear color |
| `depth` | |
| `stencil` | |
| `depth` | Sets the clear depth value |
| `stencil` | Sets the clear stencil value |
If an option is not present, then the corresponding buffer is not cleared
**Relevant WebGL APIs**
* [`gl.clearColor`](https://www.khronos.org/opengles/sdk/docs/man/xhtml/glClearColor.xml)
* [`gl.clearDepth`](https://www.khronos.org/opengles/sdk/docs/man/xhtml/glClearDepth.xml)
* [`gl.clearStencil`](https://www.khronos.org/opengles/sdk/docs/man/xhtml/glClearStencil.xml)
* [`gl.clear`](https://www.khronos.org/opengles/sdk/docs/man/xhtml/glClear.xml)
---------------------------------------

@@ -998,2 +1284,7 @@ ### Reading pixels

**Relevant WebGL APIs**
* [`gl.pixelStorei`](https://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)
* [`gl.readPixels`](https://www.khronos.org/opengles/sdk/docs/man/xhtml/glReadPixels.xml)
---------------------------------------

@@ -1028,4 +1319,34 @@ ### Per-frame callbacks

---------------------------------------
### WebGL capabilities
### Limits
regl exposes info about the WebGL context limits and capabilities via the `regl.limits` object. The following properties are supported,
| Property | Description |
|----------|-------------|
| `colorBits` | An array of bits depths for the red, green, blue and alpha channels |
| `depthBits` | Bit depth of drawing buffer |
| `stencilBits` | Bit depth of stencil buffer |
| `subpixelBits` | `gl.SUBPIXEL_BITS` |
| `extensions` | A list of all supported extensions |
| `pointSizeRange` | `gl.ALIASED_POINT_SIZE_RANGE` |
| `lineWidthRange` | `gl.ALIASED_LINE_WIDTH_RANGE` |
| `viewport` | `gl.MAX_VIEWPORT_DIMS` |
| `combinedTextureUnits` | `gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS` |
| `cubeMapSize` | `gl.MAX_CUBE_MAP_TEXTURE_SIZE` |
| `renderbufferSize` | `gl.MAX_RENDERBUFFER_SIZE` |
| `texUnits` | `gl.MAX_TEXTURE_IMAGE_UNITS` |
| `textureSize` | `gl.MAX_TEXTURE_SIZE` |
| `attributes` | `gl.MAX_VERTEX_ATTRIBS` |
| `vertexUniforms` | `gl.MAX_VERTEX_UNIFORM_VECTORS` |
| `vertexTextureUnits` | `gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS` |
| `varyingVectors` | `gl.MAX_VARYING_VECTORS` |
| `fragmentUniforms` | `gl.MAX_FRAGMENT_UNIFORM_VECTORS` |
| `glsl` | `gl.SHADING_LANGUAGE_VERSION` |
| `renderer` | `gl.RENDERER` |
| `vendor` | `gl.VENDOR` |
| `version` | `gl.VERSION` |
**Relevant WebGL APIs**
* [`gl.getParameter`](https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGetParameter.xml)
---------------------------------------

@@ -1032,0 +1353,0 @@ ### Clean up

# Release notes
## 0.2.0
* Texture support implemented, but not well tested
* Fix attribute binding bug
## 0.1.0

@@ -4,0 +9,0 @@

6

lib/attribute.js

@@ -24,4 +24,4 @@ var glTypes = require('./constants/dtypes.json')

equals: function (other, size) {
if (this.pointer) {
return other.pointer &&
if (!this.pointer) {
return !other.pointer &&
this.x === other.x &&

@@ -32,3 +32,3 @@ this.y === other.y &&

} else {
return !other.pointer &&
return other.pointer &&
this.buffer === other.buffer &&

@@ -35,0 +35,0 @@ this.size === size &&

// Array and element buffer creation
var check = require('./check')
var isTypedArray = require('./is-typed-array')
var usageTypes = require('./constants/usage.json')
var arrayTypes = require('./constants/arraytypes.json')

@@ -11,2 +10,8 @@

var usageTypes = {
'static': 35044,
'dynamic': 35048,
'stream': 35040
}
function flatten (data, dimension) {

@@ -126,12 +131,12 @@ var result = new Float32Array(data.length * dimension)

function updateBuffer (options) {
function reglBuffer (options) {
buffer.update(options || {})
return updateBuffer
return reglBuffer
}
updateBuffer._reglType = 'buffer'
updateBuffer._buffer = buffer
updateBuffer.destroy = function () { buffer.destroy() }
reglBuffer._reglType = 'buffer'
reglBuffer._buffer = buffer
reglBuffer.destroy = function () { buffer.destroy() }
return updateBuffer
return reglBuffer
}

@@ -138,0 +143,0 @@

@@ -5,4 +5,5 @@ // Error checking and parameter validation

function raise (message) {
console.error(message)
throw new Error(message)
var error = new Error('(regl) ' + message)
console.error(error)
throw error
}

@@ -9,0 +10,0 @@

@@ -6,6 +6,2 @@ var check = require('./check')

var glTypes = require('./constants/dtypes.json')
var compareFuncs = require('./constants/comparefuncs.json')
var blendFuncs = require('./constants/blendFuncs.json')
var blendEquations = require('./constants/blendEquations.json')
var stencilOps = require('./constants/stencil-ops.json')

@@ -29,2 +25,4 @@ var GL_ELEMENT_ARRAY_BUFFER = 34963

var GL_FLOAT_MAT4 = 35676
var GL_SAMPLER_2D = 35678
var GL_SAMPLER_CUBE = 35680

@@ -49,2 +47,57 @@ var GL_TRIANGLES = 4

var GL_MIN_EXT = 0x8007
var GL_MAX_EXT = 0x8008
var blendFuncs = {
'0': 0,
'1': 1,
'zero': 0,
'one': 1,
'src color': 768,
'one minus src color': 769,
'src alpha': 770,
'one minus src alpha': 771,
'dst color': 774,
'one minus dst color': 775,
'dst alpha': 772,
'one minus dst alpha': 773,
'constant color': 32769,
'one minus constant color': 32770,
'constant alpha': 32771,
'one minus constant alpha': 32772,
'src alpha saturate': 776
}
var compareFuncs = {
'never': 512,
'less': 513,
'<': 513,
'equal': 514,
'=': 514,
'==': 514,
'===': 514,
'lequal': 515,
'<=': 515,
'greater': 516,
'>': 516,
'notequal': 517,
'!=': 517,
'!==': 517,
'gequal': 518,
'>=': 518,
'always': 519
}
var stencilOps = {
'0': 0,
'zero': 0,
'keep': 7680,
'replace': 7681,
'increment': 7682,
'decrement': 7683,
'increment wrap': 34055,
'decrement wrap': 34056,
'invert': 5386
}
function typeLength (x) {

@@ -139,2 +192,12 @@ switch (x) {

var blendEquations = {
'add': 32774,
'subtract': 32778,
'reverse subtract': 32779
}
if (extensions.ext_blend_minmax) {
blendEquations.min = GL_MIN_EXT
blendEquations.max = GL_MAX_EXT
}
var drawCallCounter = 0

@@ -163,2 +226,3 @@

var ELEMENT_STATE = link(elementState.elements)
var TEXTURE_UNIFORMS = []

@@ -183,5 +247,17 @@ // bind the program

var TOP = STACK + '[' + STACK + '.length-1]'
draw(setUniformString(GL, uniform.info.type, LOCATION, TOP))
if (uniform.info.type === GL_SAMPLER_2D ||
uniform.info.type === GL_SAMPLER_CUBE) {
var TEX_VALUE = def(TOP + '._texture')
TEXTURE_UNIFORMS.push(TEX_VALUE)
draw(setUniformString(GL, GL_INT, LOCATION, TEX_VALUE + '.bind()'))
} else {
draw(setUniformString(GL, uniform.info.type, LOCATION, TOP))
}
})
// unbind textures immediately
TEXTURE_UNIFORMS.forEach(function (TEX_VALUE) {
draw(TEX_VALUE, '.unbind();')
})
// Execute draw command

@@ -339,3 +415,10 @@ var CUR_PRIMITIVE = def(stackTop(DRAW_STATE.primitive))

var TOP = STACK + '[' + STACK + '.length-1]'
batch(setUniformString(GL, uniform.info.type, LOCATION, TOP))
if (uniform.info.type === GL_SAMPLER_2D ||
uniform.info.type === GL_SAMPLER_CUBE) {
var TEX_VALUE = def(TOP + '._texture')
batch(setUniformString(GL, GL_INT, LOCATION, TEX_VALUE + '.bind()'))
exit(TEX_VALUE, '.unbind();')
} else {
batch(setUniformString(GL, uniform.info.type, LOCATION, TOP))
}
})

@@ -558,2 +641,3 @@

var programUniforms = program.uniforms
var DYNAMIC_TEXTURES = []
Object.keys(uniforms).forEach(function (uniform) {

@@ -567,4 +651,14 @@ var data = findInfo(programUniforms, uniform)

var VALUE = dyn(uniforms[uniform])
batch(setUniformString(GL, TYPE, LOCATION, VALUE))
if (data.info.type === GL_SAMPLER_2D ||
data.info.type === GL_SAMPLER_CUBE) {
var TEX_VALUE = def(VALUE + '._texture')
DYNAMIC_TEXTURES.push(TEX_VALUE)
batch(setUniformString(GL, GL_INT, LOCATION, TEX_VALUE + '.bind()'))
} else {
batch(setUniformString(GL, TYPE, LOCATION, VALUE))
}
})
DYNAMIC_TEXTURES.forEach(function (VALUE) {
batch(VALUE, '.unbind();')
})

@@ -1057,3 +1151,3 @@ // -------------------------------

PROGRAM_STATE, '.push(',
LINK_PROG, '(', FRAG_SRC, ',', VERT_SRC, '));')
LINK_PROG, '(', VERT_SRC, ',', FRAG_SRC, '));')
}

@@ -1071,3 +1165,5 @@ exit(PROGRAM_STATE, '.pop();')

var value = staticUniforms[uniform]
if (Array.isArray(value)) {
if (typeof value === 'function' && value._reglType) {
VALUE = link(value)
} else if (Array.isArray(value)) {
VALUE = link(value.slice())

@@ -1243,9 +1339,9 @@ } else {

'if(typeof ', variable, '==="string"){',
BLEND_EQUATION_STACK, '.push(',
BLEND_EQUATIONS, '[', variable, '],',
BLEND_EQUATIONS, '[', variable, ']);',
BLEND_EQUATION_STACK, '.push(',
BLEND_EQUATIONS, '[', variable, '],',
BLEND_EQUATIONS, '[', variable, ']);',
'}else{',
BLEND_EQUATION_STACK, '.push(',
BLEND_EQUATIONS, '[', variable, '.rgb],',
BLEND_EQUATIONS, '[', variable, '.alpha]);',
BLEND_EQUATION_STACK, '.push(',
BLEND_EQUATIONS, '[', variable, '.rgb],',
BLEND_EQUATIONS, '[', variable, '.alpha]);',
'}')

@@ -1343,9 +1439,9 @@ dynamicExit(BLEND_EQUATION_STACK, '.pop();')

var hasPrimitive =
!('primitive' in dynamicOptions) &&
!('primitive' in dynamicOptions) &&
!('primitive' in staticOptions)
var hasCount =
!('count' in dynamicOptions) &&
!('count' in dynamicOptions) &&
!('count' in staticOptions)
var hasOffset =
!('offset' in dynamicOptions) &&
!('offset' in dynamicOptions) &&
!('offset' in staticOptions)

@@ -1352,0 +1448,0 @@ var ELEMENTS = dynamicEntry.def()

@@ -27,3 +27,3 @@ // Context and canvas creation helper functions

var scale = +window.devicePixelRatio
var scale = +args.options.pixelRatio
function resize () {

@@ -62,3 +62,3 @@ var w = window.innerWidth

function getContext (canvas, options) {
var glOptions = options.glOptions
var glOptions = options.glOptions || {}

@@ -81,3 +81,5 @@ function get (name) {

gl: gl,
options: options
options: Object.assign({
pixelRatio: window.devicePixelRatio
}, options)
}

@@ -106,3 +108,5 @@ }

gl: args[0],
options: options
options: Object.assign({
pixelRatio: 1
}, options)
}

@@ -109,0 +113,0 @@ } else {

@@ -1,6 +0,2 @@

// Extension wrangling
var check = require('./check')
module.exports = function createExtensionCache (gl, required) {
module.exports = function createExtensionCache (gl) {
var extensions = {}

@@ -29,3 +25,8 @@

'angle_instanced_arrays'
'angle_instanced_arrays',
'webgl_compressed_texture_s3tc',
'webgl_compressed_texture_atc',
'webgl_compressed_texture_pvrtc',
'webgl_compressed_texture_etc1'
].forEach(function (ext) {

@@ -36,7 +37,2 @@ try {

})
required.forEach(function (ext) {
check(extensions[ext.toLowerCase()],
'required extension "' + ext + '" is unsupported')
})
}

@@ -43,0 +39,0 @@

@@ -156,3 +156,3 @@ var check = require('./check')

if (!cache) {
cache = programCache[vertSource] = {}
cache = programCache[fragSource] = {}
}

@@ -159,0 +159,0 @@ var program = cache[vertSource]

var check = require('./check')
var isTypedArray = require('./is-typed-array')
var loadTexture = require('./load-texture')
var convertToHalfFloat = require('./to-half-float')
var parseDDS = require('./parse-dds')
var GL_COMPRESSED_TEXTURE_FORMATS = 0x86A3
var GL_TEXTURE_2D = 0x0DE1
var GL_TEXTURE_CUBE_MAP = 0x8513
var GL_TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515
var GL_DEPTH_COMPONENT = 0x1902
var GL_RGBA = 0x1908
var GL_ALPHA = 0x1906
var GL_RGB = 0x1907
var GL_RGBA = 0x1908
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 = 0x1401
var GL_UNSIGNED_SHORT = 0x1403
var GL_UNSIGNED_INT = 0x1405
var GL_FLOAT = 0x1406

@@ -33,120 +74,1291 @@

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 wrapModes = {
'repeat': GL_REPEAT,
'clamp': GL_CLAMP_TO_EDGE,
'mirror': GL_MIRRORED_REPEAT
var GL_TEXTURE0 = 0x84C0
var MIPMAP_FILTERS = [
GL_NEAREST_MIPMAP_NEAREST,
GL_NEAREST_MIPMAP_LINEAR,
GL_LINEAR_MIPMAP_NEAREST,
GL_LINEAR_MIPMAP_LINEAR
]
function isPow2 (v) {
return !(v & (v - 1)) && (!!v)
}
var magFilters = {
'nearest': GL_NEAREST,
'linear': GL_LINEAR
function isNumericArray (arr) {
return (
Array.isArray(arr) &&
(arr.length === 0 ||
typeof arr[0] === 'number'))
}
var minFilters = Object.assign({
'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,
'mipmap': GL_LINEAR_MIPMAP_LINEAR
}, magFilters)
function isNDArrayLike (obj) {
return (
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)))
}
module.exports = function createTextureSet (gl, extensionState) {
function isRectArray (arr) {
if (!Array.isArray(arr)) {
return false
}
var width = arr.length
if (width === 0 || !Array.isArray(arr[0])) {
return false
}
var height = arr[0].length
for (var i = 1; i < width; ++i) {
if (!Array.isArray(arr[i]) || arr[i].length !== height) {
return false
}
}
return true
}
function classString (x) {
return Object.prototype.toString.call(x)
}
function isCanvasElement (object) {
return classString(object) === '[object HTMLCanvasElement]'
}
function isContext2D (object) {
return classString(object) === '[object CanvasRenderingContext2D]'
}
function isImageElement (object) {
return classString(object) === '[object HTMLImageElement]'
}
function isVideoElement (object) {
return classString(object) === '[object HTMLVideoElement]'
}
function isPendingXHR (object) {
return classString(object) === '[object XMLHttpRequest]'
}
function isPixelData (object) {
return (
typeof object === 'string' ||
(!!object && (
isTypedArray(object) ||
isNumericArray(object) ||
isNDArrayLike(object) ||
isCanvasElement(object) ||
isContext2D(object) ||
isImageElement(object) ||
isVideoElement(object) ||
isRectArray(object))))
}
// Transpose an array of pixels
function transposePixels (data, nx, ny, nc, sx, sy, sc, off) {
var result = new data.constructor(nx * ny * nc)
var ptr = 0
for (var i = 0; i < ny; ++i) {
for (var j = 0; j < nx; ++j) {
for (var k = 0; k < nc; ++k) {
result[ptr++] = data[sy * i + sx * j + sc * k + off]
}
}
}
return result
}
module.exports = function createTextureSet (gl, extensionState, limits, reglPoll, viewport) {
var extensions = extensionState.extensions
var textureCount = 0
var textureSet = {}
var mipmapHint = {
"don't care": GL_DONT_CARE,
'dont care': GL_DONT_CARE,
'nice': GL_NICEST,
'fast': GL_FASTEST
}
function REGLTexture () {
this.id = textureCount++
var wrapModes = {
'repeat': GL_REPEAT,
'clamp': GL_CLAMP_TO_EDGE,
'mirror': GL_MIRRORED_REPEAT
}
// Texture target
this.target = GL_TEXTURE_2D
var magFilters = {
'nearest': GL_NEAREST,
'linear': GL_LINEAR
}
// Texture handle
this.texture = null
var minFilters = Object.assign({
'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,
'mipmap': GL_LINEAR_MIPMAP_LINEAR
}, magFilters)
// Texture format
this.format = GL_RGBA
this.type = GL_UNSIGNED_BYTE
var colorSpace = {
'none': 0,
'browser': GL_BROWSER_DEFAULT_WEBGL
}
// Data
this.mipLevels = []
var textureTypes = {
'uint8': GL_UNSIGNED_BYTE,
'rgba4': GL_UNSIGNED_SHORT_4_4_4_4,
'rgb565': GL_UNSIGNED_SHORT_5_6_5,
'rgb5 a1': GL_UNSIGNED_SHORT_5_5_5_1
}
// Shape
this.width = 0
this.height = 0
var textureFormats = {
'alpha': GL_ALPHA,
'luminance': GL_LUMINANCE,
'luminance alpha': GL_LUMINANCE_ALPHA,
'rgb': GL_RGB,
'rgba': GL_RGBA,
'rgba4': GL_RGBA4,
'rgb5 a1': GL_RGB5_A1,
'rgb565': GL_RGB565
}
// Parameters
this.minFilter = GL_NEAREST
this.magFilter = GL_NEAREST
this.wrapS = GL_REPEAT
this.wrapT = GL_REPEAT
this.mipSamples = 0
var compressedTextureFormats = {}
// Storage flags
if (extensions.ext_srgb) {
textureFormats.srgb = GL_SRGB_EXT
textureFormats.srgba = GL_SRGB_ALPHA_EXT
}
if (extensions.oes_texture_float) {
textureTypes.float = GL_FLOAT
}
if (extensions.oes_texture_half_float) {
textureTypes['half float'] = GL_HALF_FLOAT_OES
}
if (extensions.webgl_depth_texture) {
Object.assign(textureFormats, {
'depth': GL_DEPTH_COMPONENT,
'depth stencil': GL_DEPTH_STENCIL
})
Object.assign(textureTypes, {
'uint16': GL_UNSIGNED_SHORT,
'uint32': GL_UNSIGNED_INT,
'depth stencil': GL_UNSIGNED_INT_24_8_WEBGL
})
}
if (extensions.webgl_compressed_texture_s3tc) {
Object.assign(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) {
Object.assign(compressedTextureFormats, {
'rgb arc': 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) {
Object.assign(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
var colorFormats = supportedFormats.reduce(function (color, key) {
var glenum = textureFormats[key]
if (glenum === GL_LUMINANCE ||
glenum === GL_ALPHA ||
glenum === GL_LUMINANCE ||
glenum === GL_LUMINANCE_ALPHA ||
glenum === GL_DEPTH_COMPONENT ||
glenum === GL_DEPTH_STENCIL) {
color[glenum] = glenum
} else if (glenum === GL_RGB5_A1 || key.indexOf('rgba') >= 0) {
color[glenum] = GL_RGBA
} else {
color[glenum] = GL_RGB
}
return color
}, {})
// Pixel storage parsing
function PixelInfo (target) {
// tex target
this.target = target
// pixelStorei info
this.flipY = false
this.premultiplyAlpha = false
this.unpackAlignment = 1
this.colorSpace = GL_BROWSER_DEFAULT_WEBGL
// shape
this.width = 0
this.height = 0
this.channels = 0
// format and type
this.format = 0
this.internalformat = 0
this.type = 0
this.compressed = false
// mip level
this.miplevel = 0
// ndarray-like parameters
this.strideX = 0
this.strideY = 0
this.strideC = 0
this.offset = 0
// copy pixels info
this.x = 0
this.y = 0
this.copy = false
// data sources
this.data = null
this.image = null
this.video = null
this.canvas = null
this.xhr = null
// CORS
this.crossOrigin = null
// horrible state flags
this.needsPoll = false
this.needsListeners = false
}
Object.assign(REGLTexture.prototype, {
bind: function () {
Object.assign(PixelInfo.prototype, {
parseFlags: function (options) {
if (typeof options !== 'object' || !options) {
return
}
if ('premultiplyAlpha' in options) {
check.type(options.premultiplyAlpha, 'boolean',
'invalid premultiplyAlpha')
this.premultiplyAlpha = options.premultiplyAlpha
}
if ('flipY' in options) {
check.type(options.flipY, 'boolean',
'invalid texture flip')
this.flipY = options.flipY
}
if ('alignment' in options) {
check.oneOf(options.alignment, [1, 2, 4, 8],
'invalid texture unpack alignment')
this.unpackAlignment = options.alignment
}
if ('colorSpace' in options) {
check.parameter(options.colorSpace, colorSpace,
'invalid colorSpace')
this.colorSpace = colorSpace[options.colorSpace]
}
if ('format' in options) {
var format = options.format
check.parameter(format, textureFormats,
'invalid texture format')
this.internalformat = textureFormats[format]
if (format in textureTypes) {
this.type = textureTypes[format]
}
if (format in compressedTextureFormats) {
this.compressed = true
}
}
if ('type' in options) {
var type = options.type
check.parameter(type, textureTypes,
'invalid texture type')
this.type = textureTypes[type]
}
var w = this.width
var h = this.height
var c = this.channels
if ('shape' in options) {
check(Array.isArray(options.shape) && options.shape.length >= 2,
'shape must be an array')
w = options.shape[0]
h = options.shape[1]
if (options.shape.length === 3) {
c = options.shape[2]
}
} else {
if ('radius' in options) {
w = h = options.radius
}
if ('width' in options) {
w = options.width
}
if ('height' in options) {
h = options.height
}
if ('channels' in options) {
c = options.channels
}
}
this.width = w | 0
this.height = h | 0
this.channels = c | 0
if ('stride' in options) {
var stride = options.stride
check(Array.isArray(stride) && stride.length >= 2,
'invalid stride vector')
this.strideX = stride[0]
this.strideY = stride[1]
if (stride.length === 3) {
this.strideC = stride[2]
} else {
this.strideC = 1
}
this.needsTranspose = true
} else {
this.strideC = 1
this.strideX = this.strideC * c
this.strideY = this.strideX * w
}
if ('offset' in options) {
this.offset = options.offset | 0
this.needsTranspose = true
}
if ('crossOrigin' in options) {
this.crossOrigin = options.crossOrigin
}
},
parse: function (options, miplevel) {
this.miplevel = miplevel
this.width = this.width >> miplevel
this.height = this.height >> miplevel
update: function (args) {
var options = args || {}
var data = options
switch (typeof options) {
case 'string':
break
case 'object':
if (!options) {
return
}
this.parseFlags(options)
if (isPixelData(options.data)) {
data = options.data
}
break
case 'undefined':
return
default:
check.raise('invalid pixel data type')
}
// Possible initialization pathways:
if (Array.isArray(args) ||
isTypedArray(args) ||
isHTMLElement(args)) {
options = {
data: args
if (typeof data === 'string') {
data = loadTexture(data, this.crossOrigin)
} else {
check(!data || isPixelData(data), 'invalid pixel data')
}
var array = null
var needsConvert = false
if (this.compressed) {
check(data instanceof Uint8Array || isPendingXHR(data),
'compressed texture data must be stored in a uint8array')
}
if (data === null) {
// TODO
} else if (isTypedArray(data)) {
this.data = data
} else if (isNumericArray(data)) {
array = data
needsConvert = true
} else if (isNDArrayLike(data)) {
if (Array.isArray(data.data)) {
array = data.data
needsConvert = true
} else {
this.data = data.data
}
var shape = data.shape
this.width = shape[0]
this.height = shape[1]
if (shape.length === 3) {
this.channels = shape[2]
} else {
this.channels = 1
}
var stride = data.stride
this.strideX = data.stride[0]
this.strideY = data.stride[1]
if (stride.length === 3) {
this.strideC = data.stride[2]
} else {
this.strideC = 1
}
this.offset = data.offset
this.needsTranspose = true
} else if (isCanvasElement(data) || isContext2D(data)) {
if (isCanvasElement(data)) {
this.canvas = data
} else {
this.canvas = data.canvas
}
this.width = this.canvas.width
this.height = this.canvas.height
this.setDefaultFormat()
} else if (isImageElement(data)) {
this.image = data
if (!data.complete) {
this.width = this.width || data.naturalWidth
this.height = this.height || data.naturalHeight
this.needsListeners = true
} else {
this.width = data.naturalWidth
this.height = data.naturalHeight
}
this.setDefaultFormat()
} else if (isVideoElement(data)) {
this.video = data
if (data.readyState > 1) {
this.width = data.width
this.height = data.height
} else {
this.width = this.width || data.width
this.height = this.height || data.height
this.needsListeners = true
}
this.needsPoll = true
this.setDefaultFormat()
} else if (isPendingXHR(data)) {
this.xhr = data
this.needsListeners = true
} else if (isRectArray(data)) {
var w = data.length
var h = data[0].length
var c = 1
var i, j, k, p
if (Array.isArray(data[0][0])) {
c = data[0][0].length
check(c >= 0 && c <= 4, 'invalid number of channels for image data')
array = Array(w * h * c)
p = 0
for (i = 0; i < w; ++i) {
for (j = 0; j < h; ++j) {
for (k = 0; k < c; ++k) {
array[p++] = data[i][j][k]
}
}
}
} else {
array = Array(w * h)
p = 0
for (i = 0; i < w; ++i) {
for (j = 0; j < h; ++j) {
array[p++] = data[i][j]
}
}
}
this.width = w
this.height = h
this.channels = c
needsConvert = true
} else if (options.copy) {
this.copy = true
this.x = this.x | 0
this.y = this.y | 0
this.width = (this.width || viewport.width) | 0
this.height = (this.height || viewport.height) | 0
this.setDefaultFormat()
}
var data = options.data || null
var width = options.width || 0
var height = options.height || 0
var format = options.format || 'rgba'
// Fix up missing type info for typed arrays
if (!this.type && this.data) {
if (this.format === GL_DEPTH_COMPONENT) {
if (this.data instanceof Uint16Array) {
this.type = GL_UNSIGNED_SHORT
} else if (this.data instanceof Uint32Array) {
this.type = GL_UNSIGNED_INT
}
} else if (this.data instanceof Float32Array) {
this.type = GL_FLOAT
}
}
this.minFilter = GL_NEAREST
// Infer default format
if (!this.internalformat) {
var channels = this.channels = this.channels || 4
this.internalformat = [
GL_LUMINANCE,
GL_LUMINANCE_ALPHA,
GL_RGB,
GL_RGBA][channels - 1]
check(this.internalformat, 'invalid number of channels')
}
var format = this.internalformat
if (format === GL_DEPTH_COMPONENT || format === GL_DEPTH_STENCIL) {
check(extensions.webgl_depth_texture,
'depth/stencil texture not supported')
if (format === GL_DEPTH_COMPONENT) {
check(this.type === GL_UNSIGNED_SHORT || GL_UNSIGNED_INT,
'depth texture type must be uint16 or uint32')
}
if (format === GL_DEPTH_STENCIL) {
check(this.type === GL_UNSIGNED_INT_24_8_WEBGL,
'depth stencil texture format must match type')
}
check(
!this.data && !array && !this.image && !this.video && !this.canvas,
'depth/stencil textures are for rendering only')
}
// Compute color format and number of channels
var colorFormat = this.format = colorFormats[format]
if (!this.channels) {
switch (colorFormat) {
case GL_LUMINANCE:
case GL_ALPHA:
case GL_DEPTH_COMPONENT:
this.channels = 1
break
case GL_DEPTH_STENCIL:
case GL_LUMINANCE_ALPHA:
this.channels = 2
break
case GL_RGB:
this.channels = 3
break
default:
this.channels = 4
}
}
// Check that texture type is supported
var type = this.type
if (type === GL_FLOAT) {
check(extensions.oes_texture_float,
'float texture not supported')
} else if (type === GL_HALF_FLOAT_OES) {
check(extensions.oes_texture_half_float,
'half float texture not supported')
} else if (!type) {
if (format === GL_DEPTH_COMPONENT) {
type = GL_UNSIGNED_INT
} else {
type = GL_UNSIGNED_BYTE
}
}
this.type = type
// apply conversion
if (needsConvert) {
switch (type) {
case GL_UNSIGNED_BYTE:
this.data = new Uint8Array(array)
break
case GL_UNSIGNED_SHORT:
this.data = new Uint16Array(array)
break
case GL_UNSIGNED_INT:
this.data = new Uint32Array(array)
break
case GL_FLOAT:
this.data = new Float32Array(array)
break
case GL_HALF_FLOAT_OES:
this.data = convertToHalfFloat(array)
break
case GL_UNSIGNED_SHORT_5_6_5:
case GL_UNSIGNED_SHORT_5_5_5_1:
case GL_UNSIGNED_SHORT_4_4_4_4:
case GL_UNSIGNED_INT_24_8_WEBGL:
check.raise('unsupported format for automatic conversion')
break
default:
check.raise('unsupported type conversion')
}
}
if (this.data) {
// apply transpose
if (this.needsTranspose) {
this.data = transposePixels(
this.data,
this.width,
this.height,
this.channels,
this.strideX,
this.strideY,
this.strideC,
this.offset)
}
// check data type
switch (type) {
case GL_UNSIGNED_BYTE:
check(this.data instanceof Uint8Array ||
this.data instanceof Uint8ClampedArray,
'incompatible pixel type')
break
case GL_UNSIGNED_SHORT_5_6_5:
case GL_UNSIGNED_SHORT_5_5_5_1:
case GL_UNSIGNED_SHORT_4_4_4_4:
case GL_UNSIGNED_SHORT:
case GL_HALF_FLOAT_OES:
check(this.data instanceof Uint16Array,
'incompatible pixel type')
break
case GL_UNSIGNED_INT:
check(this.data instanceof Uint32Array,
'incompatible pixel type')
break
case GL_FLOAT:
check(this.data instanceof Float32Array,
'incompatible pixel type')
break
default:
check.raise('bad or missing pixel type')
}
}
this.needsTranspose = false
},
setDefaultFormat: function () {
this.format = this.internalformat = GL_RGBA
this.type = GL_UNSIGNED_BYTE
this.channels = 4
this.compressed = false
},
upload: function (params) {
gl.pixelStorei(GL_UNPACK_FLIP_Y_WEBGL, this.flipY)
gl.pixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_WEBGL, this.premultiplyAlpha)
gl.pixelStorei(GL_UNPACK_COLORSPACE_CONVERSION_WEBGL, this.colorSpace)
gl.pixelStorei(GL_UNPACK_ALIGNMENT, this.unpackAlignment)
var target = this.target
var miplevel = this.miplevel
var image = this.image
var canvas = this.canvas
var video = this.video
var data = this.data
var internalformat = this.internalformat
var format = this.format
var type = this.type
var width = this.width || Math.max(1, params.width >> miplevel)
var height = this.height || Math.max(1, params.height >> miplevel)
if (video && video.readyState > 2) {
gl.texImage2D(target, miplevel, format, format, type, video)
} else if (image && image.complete) {
gl.texImage2D(target, miplevel, format, format, type, image)
} else if (canvas) {
gl.texImage2D(target, miplevel, format, format, type, canvas)
} else if (this.compressed) {
gl.compressedTexImage2D(target, miplevel, internalformat, width, height, 0, data)
} else if (this.copy) {
reglPoll()
gl.copyTexImage2D(target, miplevel, format, this.x, this.y, width, height, 0)
} else if (data) {
gl.texImage2D(target, miplevel, format, width, height, 0, format, type, data)
} else {
gl.texImage2D(target, miplevel, format, width || 1, height || 1, 0, format, type, null)
}
}
})
function TexParams (target) {
this.target = target
// Default image shape info
this.width = 0
this.height = 0
this.format = 0
this.internalformat = 0
this.type = 0
// wrap mode
this.wrapS = GL_CLAMP_TO_EDGE
this.wrapT = GL_CLAMP_TO_EDGE
// filtering
this.minFilter = 0
this.magFilter = GL_NEAREST
this.anisotropic = 1
// mipmaps
this.genMipmaps = false
this.mipmapHint = GL_DONT_CARE
}
Object.assign(TexParams.prototype, {
clear: function () {
TexParams.call(this, this.target)
},
parse: function (options) {
if (typeof options !== 'object' || !options) {
return
}
if ('min' in options) {
check.param(options.min, minFilters)
this.minFilter = minFilters[options.min]
var minFilter = options.min
check.parameter(minFilter, minFilters)
this.minFilter = minFilters[minFilter]
}
this.magFilter = GL_NEAREST
if ('mag' in options) {
check.param(options.mag, magFilters)
this.magFilter = magFilters(options.mag)
var magFilter = options.mag
check.parameter(magFilter, magFilters)
this.magFilter = magFilters[magFilter]
}
if (Array.isArray(data)) {
var wrapS = this.wrapS
var wrapT = this.wrapT
if ('wrap' in options) {
var wrap = options.wrap
if (typeof wrap === 'string') {
check.parameter(wrap, wrapModes)
wrapS = wrapT = wrapModes[wrap]
} else if (Array.isArray(wrap)) {
check.parameter(wrap[0], wrapModes)
check.parameter(wrap[1], wrapModes)
wrapS = wrapModes[wrap[0]]
wrapT = wrapModes[wrap[1]]
}
} else {
if ('wrapS' in options) {
var optWrapS = options.wrapS
check.parameter(optWrapS, wrapModes)
wrapS = wrapModes[optWrapS]
}
if ('wrapT' in options) {
var optWrapT = options.wrapT
check.parameter(optWrapT, wrapModes)
wrapT = wrapModes[optWrapT]
}
}
this.wrapS = wrapS
this.wrapT = wrapT
} else if (isTypedArray(data)) {
if ('anisotropic' in options) {
var anisotropic = options.anisotropic
check(typeof anisotropic === 'number' &&
anisotropic >= 1 && anisotropic <= limits.maxAnisotropic,
'aniso samples must be between 1 and ')
this.anisotropic = options.anisotropic
}
} else if (isHTMLElement(data)) {
if ('mipmap' in options) {
var mipmap = options.mipmap
switch (typeof mipmap) {
case 'string':
check.parameter(mipmap, mipmapHint,
'invalid mipmap hint')
this.mipmapHint = mipmapHint[mipmap]
this.genMipmaps = true
break
case 'boolean':
this.genMipmaps = !!mipmap
break
case 'object':
break
default:
check.raise('invalid mipmap type')
}
}
},
// Set tex image
upload: function () {
var target = this.target
gl.texParameteri(target, GL_TEXTURE_MIN_FILTER, this.minFilter)
gl.texParameteri(target, GL_TEXTURE_MAG_FILTER, this.magFilter)
gl.texParameteri(target, GL_TEXTURE_WRAP_S, this.wrapS)
gl.texParameteri(target, GL_TEXTURE_WRAP_T, this.wrapT)
if (extensions.ext_texture_filter_anisotropic) {
gl.texParameteri(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, this.anisotropic)
}
if (this.genMipmaps) {
gl.hint(GL_GENERATE_MIPMAP_HINT, this.mipmapHint)
gl.generateMipmap(target)
}
}
})
// Final pass to merge params and pixel data
function checkTextureComplete (params, pixels) {
var i, pixmap
var type = 0
var format = 0
var internalformat = 0
var width = 0
var height = 0
var channels = 0
var compressed = false
var needsPoll = false
var needsListeners = false
var mipMask2D = 0
var mipMaskCube = [0, 0, 0, 0, 0, 0]
var cubeMask = 0
var hasMip = false
for (i = 0; i < pixels.length; ++i) {
pixmap = pixels[i]
width = width || (pixmap.width << pixmap.miplevel)
height = height || (pixmap.height << pixmap.miplevel)
type = type || pixmap.type
format = format || pixmap.format
internalformat = internalformat || pixmap.internalformat
channels = channels || pixmap.channels
needsPoll = needsPoll || pixmap.needsPoll
needsListeners = needsListeners || pixmap.needsListeners
compressed = compressed || pixmap.compressed
var miplevel = pixmap.miplevel
var target = pixmap.target
hasMip = hasMip || (miplevel > 0)
if (target === GL_TEXTURE_2D) {
mipMask2D |= (1 << miplevel)
} else {
var face = target - GL_TEXTURE_CUBE_MAP_POSITIVE_X
mipMaskCube[face] |= (1 << miplevel)
cubeMask |= (1 << face)
}
}
params.needsPoll = needsPoll
params.needsListeners = needsListeners
params.width = width
params.height = height
params.format = format
params.internalformat = internalformat
params.type = type
var mipMask = hasMip ? (width << 1) - 1 : 1
if (params.target === GL_TEXTURE_2D) {
check(cubeMask === 0,
'pixmap type must not contain cubemap faces')
check(mipMask2D === mipMask, 'missing mip map data')
} else {
check(cubeMask === ((1 << 6) - 1), 'missing cubemap faces')
for (i = 0; i < 6; ++i) {
check(mipMaskCube[i] === mipMask, 'missing mip map data')
}
}
var mipFilter = (MIPMAP_FILTERS.indexOf(params.minFilter) >= 0)
params.genMipmaps = !hasMip && (params.genMipmaps || mipFilter)
var useMipmaps = hasMip || params.genMipmaps
if (!params.minFilter) {
params.minFilter = useMipmaps
? GL_LINEAR_MIPMAP_LINEAR
: GL_NEAREST
} else {
check(useMipmaps === mipFilter,
'min filter inconsistent with mipmap data')
}
if (useMipmaps) {
check(width === height && isPow2(width),
'must be a square power of 2 to support mipmaps')
}
if (params.genMipmaps) {
check(!compressed, 'mipmap generation not supported for compressed textures')
}
params.wrapS = params.wrapS || GL_CLAMP_TO_EDGE
params.wrapT = params.wrapT || GL_CLAMP_TO_EDGE
if (params.wrapS !== GL_CLAMP_TO_EDGE ||
params.wrapT !== GL_CLAMP_TO_EDGE) {
check(isPow2(width) && isPow2(height) && !cubeMask,
'incompatible size for wrap mode, image must be a power of 2')
}
if ((type === GL_FLOAT && !extensions.oes_texture_float_linear) ||
(type === GL_HALF_FLOAT_OES &&
!extensions.oes_texture_half_float_linear)) {
check(this.magFilter === GL_NEAREST && this.minFilter === GL_NEAREST,
'unsupported filter mode for float texture')
}
for (i = 0; i < pixels.length; ++i) {
pixmap = pixels[i]
var level = pixmap.miplevel
if (pixmap.width) {
check(pixmap.width << level === width, 'inconsistent width')
}
if (pixmap.height) {
check(pixmap.height << level === height, 'inconsistent width')
}
if (pixmap.channels) {
check(pixmap.channels === channels, 'inconsistent channels')
} else {
pixmap.channels = channels
}
if (pixmap.format) {
check(pixmap.format === format, 'inconsistent format')
} else {
pixmap.format = format
}
if (pixmap.internalformat) {
check(pixmap.internalformat === internalformat, 'inconsistent internalformat')
} else {
pixmap.internalformat = internalformat
}
if (pixmap.type) {
check(pixmap.type === type, 'inconsistent type')
} else {
pixmap.type = type
}
if (pixmap.copy) {
check(pixmap.type === GL_UNSIGNED_BYTE &&
pixmap.internalformat === GL_RGBA,
'incompatible format/type for copyTexImage2D')
}
}
}
var activeTexture = 0
var textureCount = 0
var textureSet = {}
var pollSet = []
var numTexUnits = limits.textureUnits
var textureUnits = Array(numTexUnits).map(function () {
return null
})
function REGLTexture (target, texture) {
this.id = textureCount++
this.target = target
this.texture = texture
this.pollId = -1
this.unit = -1
this.bindCount = 0
// cancels all pending callbacks
this.cancelPending = null
// parsed user inputs
this.params = new TexParams(target)
this.pixels = []
}
Object.assign(REGLTexture.prototype, {
bind: function () {
this.bindCount += 1
var unit = this.unit
if (unit < 0) {
// FIXME: should we use an LRU to allocate textures here?
for (var i = 0; i < numTexUnits; ++i) {
var other = textureUnits[i]
if (!other || other.bindCount <= 0) {
if (other) {
other.unit = -1
}
textureUnits[i] = this
unit = i
break
}
}
if (unit >= numTexUnits) {
check.raise('insufficient number of texture units')
}
this.unit = unit
gl.activeTexture(GL_TEXTURE0 + unit)
gl.bindTexture(this.target, this.texture)
activeTexture = unit
}
return unit
},
unbind: function () {
this.bindCount -= 1
},
refresh: function () {
gl.textureParameteri(GL_TEXTURE_MIN_FILTER, this.minFilter)
gl.textureParameteri(GL_TEXTURE_MAG_FILTER, this.magFilter)
gl.textureParameteri(GL_TEXTURE_WRAP_T, this.wrapT)
gl.textureParameteri(GL_TEXTURE_WRAP_S, this.wrapS)
// Lazy bind
var target = this.target
var unit = this.unit
if (unit >= 0) {
gl.activeTexture(GL_TEXTURE0 + unit)
activeTexture = unit
} else {
gl.bindTexture(target, this.texture)
}
// Upload
var pixels = this.pixels
var params = this.params
for (var i = 0; i < pixels.length; ++i) {
pixels[i].upload(params)
}
params.upload()
// Lazy unbind
if (unit < 0) {
var active = textureUnits[activeTexture]
if (active) {
// restore binding state
gl.bindTexture(active.target, active.texture)
} else {
// otherwise become new active
this.unit = activeTexture
textureUnits[activeTexture] = this
}
}
},
update: function (options) {
var i
this.clearListeners()
// Clear parameters and pixel data
var params = this.params
var pixels = this.pixels
params.clear()
pixels.length = 0
// parse parameters
params.parse(options)
// parse pixel data
function parseMip (target, data) {
var mipmap = data.mipmap
var pixmap
if (Array.isArray(mipmap)) {
for (var i = 0; i < mipmap.length; ++i) {
pixmap = new PixelInfo(target)
pixmap.parseFlags(options)
pixmap.parseFlags(data)
pixmap.parse(mipmap[i], i)
pixels.push(pixmap)
}
} else {
pixmap = new PixelInfo(target)
pixmap.parseFlags(options)
pixmap.parse(data, 0)
pixels.push(pixmap)
}
}
if (this.target === GL_TEXTURE_2D) {
parseMip(GL_TEXTURE_2D, options)
} else {
var faces = options.faces || options
if (Array.isArray(faces)) {
check(faces.length === 6,
'invalid number of faces in cube map')
for (i = 0; i < 6; ++i) {
parseMip(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, faces[i])
}
} else if (typeof faces === 'string') {
// TODO Read dds
} else {
// Initialize to all empty textures
for (i = 0; i < 6; ++i) {
parseMip(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, {})
}
}
}
// do a second pass to reconcile defaults
checkTextureComplete(params, pixels)
if (params.needsListeners) {
this.hookListeners()
}
if (params.needsPoll) {
this.pollId = pollSet.length
pollSet.push(this)
}
this.refresh()
},
hookListeners: function () {
var params = this.params
var pixels = this.pixels
var texture = this
// Appends all the texture data from the buffer to the current
function appendDDS (target, miplevel, buffer) {
var dds = parseDDS(buffer)
check(dds.format in colorFormats, 'unsupported dds texture format')
if (dds.cube) {
check(texture.target === GL_TEXTURE_CUBE_MAP)
// TODO handle cube map
} else {
check(texture.target === GL_TEXTURE_2D)
}
if (miplevel) {
check(dds.pixels.length === 1, 'number of mip levels inconsistent')
}
dds.pixels.forEach(function (pixmap) {
var info = new PixelInfo(dds.cube ? pixmap.target : target)
info.channels = dds.channels
info.compressed = dds.compressed
info.type = dds.type
info.internalformat = dds.format
info.format = colorFormats[dds.format]
info.width = pixmap.width
info.height = pixmap.height
info.miplevel = pixmap.miplevel || miplevel
info.data = pixmap.data
pixels.push(info)
})
}
function refresh () {
// Update size of any newly loaded pixels
for (var i = 0; i < pixels.length; ++i) {
var pixelData = pixels[i]
var image = pixelData.image
var video = pixelData.video
var xhr = pixelData.xhr
if (image && image.complete) {
pixelData.width = image.naturalWidth
pixelData.height = image.naturalHeight
} else if (video && video.readyState > 2) {
pixelData.width = video.width
pixelData.height = video.height
} else if (xhr && xhr.readyState === 4) {
pixels[i] = pixels[pixels.length - 1]
pixels.pop()
xhr.removeEventListener('readystatechange', refresh)
appendDDS(pixelData.target, pixelData.miplevel, xhr.response)
}
}
checkTextureComplete(params, pixels)
texture.refresh()
}
pixels.forEach(function (pixelData) {
if (pixelData.image && !pixelData.image.complete) {
pixelData.image.addEventListener('load', refresh)
} else if (pixelData.video && pixelData.readyState < 1) {
pixelData.video.addEventListener('progress', refresh)
} else if (pixelData.xhr) {
pixelData.xhr.addEventListener('readystatechange', refresh)
}
})
this.cancelPending = function detachListeners () {
pixels.forEach(function (pixelData) {
if (pixelData.image) {
pixelData.image.removeEventListener('load', refresh)
} else if (pixelData.video) {
pixelData.video.removeEventListener('progress', refresh)
}
})
}
},
clearListeners: function () {
if (this.cancelPending) {
this.cancelPending()
this.cancelPending = null
}
var id = this.pollId
if (id >= 0) {
var other = pollSet[id] = pollSet[pollSet.length - 1]
other.id = id
pollSet.pop()
this.pollId = -1
}
},
destroy: function () {
check(this.texture, 'must not double free texture')
if (this.unit >= 0) {
gl.activeTexture(GL_TEXTURE0 + this.unit)
activeTexture = this.unit
gl.bindTexture(this.target, null)
textureUnits[this.unit] = null
}
this.clearListeners()
gl.deleteTexture(this.texture)
this.texture = null
this.params = null
this.pixels = null
delete textureSet[this.id]

@@ -156,21 +1368,28 @@ }

function createTexture (options) {
var texture = new REGLTexture()
texture.texture = gl.createTexture()
texture.update(options)
function createTexture (options, target) {
var texture = new REGLTexture(target, gl.createTexture())
textureSet[texture.id] = texture
function updateTexture (options) {
function reglTexture (a0, a1, a2, a3, a4, a5) {
var options = a0 || {}
if (target === GL_TEXTURE_CUBE_MAP && arguments.length === 6) {
options = [a0, a1, a2, a3, a4, a5]
}
texture.update(options)
return updateTexture
}
updateTexture._texture = texture
updateTexture.destroy = function () {
texture.destroy()
}
reglTexture(options)
return updateTexture
Object.assign(reglTexture, {
_reglType: 'texture',
_texture: texture,
destroy: function () {
texture.destroy()
}
})
return reglTexture
}
// Called after context restore
function refreshTextures () {

@@ -180,5 +1399,18 @@ Object.keys(textureSet).forEach(function (texId) {

})
for (var i = 0; i < numTexUnits; ++i) {
textureUnits[i] = null
}
activeTexture = 0
gl.activeTexture(GL_TEXTURE0)
}
// Called when regl is destroyed
function destroyTextures () {
for (var i = 0; i < numTexUnits; ++i) {
gl.activeTexture(GL_TEXTURE0 + i)
gl.bindTexture(GL_TEXTURE_2D, null)
textureUnits[i] = null
}
gl.activeTexture(GL_TEXTURE0)
activeTexture = 0
Object.keys(textureSet).forEach(function (texId) {

@@ -189,2 +1421,9 @@ textureSet[texId].destroy()

// Called once per raf, updates video textures
function pollTextures () {
for (var i = 0; i < pollSet.length; ++i) {
pollSet[i].refresh()
}
}
return {

@@ -194,2 +1433,3 @@ create: createTexture,

clear: destroyTextures,
poll: pollTextures,
getTexture: function (wrapper) {

@@ -196,0 +1436,0 @@ return null

{
"name": "regl",
"version": "0.1.0",
"version": "0.2.0",
"description": "WebGL",

@@ -11,4 +11,8 @@ "main": "regl.js",

"devDependencies": {
"angle-normals": "^1.0.0",
"baboon-image": "^2.0.0",
"browserify": "^13.0.0",
"budo": "^8.1.0",
"bunny": "^1.0.1",
"canvas-fit": "^1.5.0",
"coverify": "^1.4.1",

@@ -18,3 +22,7 @@ "derequire": "^2.0.3",

"gl": "^3.0.3",
"gl-mat4": "^1.1.4",
"hsv2rgb": "^1.1.0",
"indexhtmlify": "^1.2.1",
"mouse-change": "^1.2.1",
"ncp": "^2.0.0",
"runscript": "^1.1.0",

@@ -21,0 +29,0 @@ "smokestack": "^3.4.1",

# regl
[![Circle CI](https://circleci.com/gh/mikolalysenko/regl.svg?style=svg)](https://circleci.com/gh/mikolalysenko/regl) [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/)
[![Join the chat at https://gitter.im/ark-lang/ark](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/mikolalysenko/regl) [![Circle CI](https://circleci.com/gh/mikolalysenko/regl.svg?style=svg)](https://circleci.com/gh/mikolalysenko/regl) [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/)

@@ -10,7 +10,8 @@ This repo is an attempt at building new functional abstractions for working with WebGL. It is still **experimental**, so expect things to change a lot in the near future! If you want to know more about why I am writing this thing and why it looks the way it does, take a look at the [rationale](RATIONALE.md).

* **Just one function**
* **Less state** Draw commands in regl are self contained, so you don't have to worry about some other weird subroutine breaking your rendering code
* **No `bind()`** In regl, shaders, buffers, textures and fbos are specified declaratively, so there is no need to ever `bind()` them or unbind them.
* **Fewer silent failure** If you pass incorrect parameters to some WebGL method, the default behavior is to set an error code and continue on. Because `regl` commands have more structure, we can do more validation up front without the run time performance cost.
* **Fewer silent failures** If you pass incorrect parameters to some WebGL method, the default behavior is to set an error code and continue on. Because `regl` commands have more structure, we can do more validation up front without the run time performance cost.
* **Sane defaults** Many WebGL APIs have redundant or outright broken parameters (for example `border` in `gl.texImage2D` or `transpose` in `gl.uniformMatrix4fv`). `regl` wraps these APIs in such a way that you will never have to see this mess.
* **Low overhead** regl uses caching and code generation to minimize overhead from
* **Still just WebGL** regl exposes the full power of the WebGL API, no features are removed or hidden.

@@ -134,2 +135,3 @@ ## Simple example

## [API](API.md)
* [Initialization](API.md#initialization)

@@ -140,2 +142,3 @@ * [As a fullscreen canvas](API.md#as-a-fullscreen-canvas)

* [From a WebGL context](API.md#from-a-webgl-context)
+ [Initialization options](API.md#initialization-options)
* [Commands](API.md#commands)

@@ -152,3 +155,3 @@ + [Dynamic properties](API.md#dynamic-properties)

- [Drawing](API.md#drawing)
- [Framebuffer](API.md#framebuffer)
- [Render target](API.md#render-target)
- [Depth buffer](API.md#depth-buffer)

@@ -171,5 +174,8 @@ - [Blending](API.md#blending)

+ [Types](API.md#types)
- [`regl.buffer(options)`](API.md#-reglbuffer-options--)
- [`regl.elements(options)`](API.md#-reglelements-options--)
* [Other features](API.md#other-properties)
- [Buffers](API.md#buffers)
- [Elements](API.md#elements)
- [Textures](API.md#textures)
- [Render buffers](API.md#render-buffers)
- [Frame buffers](API.md#frame-buffers)
* [Other features](API.md#other-features)
+ [Clear the draw buffer](API.md#clear-the-draw-buffer)

@@ -179,3 +185,3 @@ + [Reading pixels](API.md#reading-pixels)

+ [Frame stats](API.md#frame-stats)
+ [WebGL capabilities](API.md#webgl-capabilities)
+ [Limits](API.md#limits)
+ [Clean up](API.md#clean-up)

@@ -188,5 +194,13 @@ + [Context loss](API.md#context-loss)

## License
(c) 2016 MIT License
## Credits
All code (c) 2016 MIT License
Supported by the [Freeman Lab](https://www.janelia.org/lab/freeman-lab) and the Howard Hughes Medical Institute
Development supported by the [Freeman Lab](https://www.janelia.org/lab/freeman-lab) and the Howard Hughes Medical Institute (@freeman-lab on GitHub)
Test video (doggie-chromakey.ogv) by [L0ckergn0me](https://archive.org/details/L0ckergn0me-PixieGreenScreen446), used under creative commons license
Cube maps (posx.jpeg, negx.jpeg, posy.jpeg, negy.jpeg, posz.jpeg, negz.jpeg) by [Humus](http://www.humus.name/index.php?page=Textures), used under creative commons 3 license
Environment map of Oregon (ogd-oregon-360.jpg) due to Max Ogden (@ogd on GitHub)
DDS test images (alpine_cliff_a, alpine_cliff_a_norm, alpine_cliff_a_spec) taken from the CC0 license [0-AD texture pack by Wildfire games](http://opengameart.org/content/0-ad-textures)
var check = require('./lib/check')
var getContext = require('./lib/context')
var wrapExtensions = require('./lib/extension')
var wrapLimits = require('./lib/limits')
var wrapBuffers = require('./lib/buffer')

@@ -24,2 +25,4 @@ var wrapElements = require('./lib/elements')

var GL_ARRAY_BUFFER = 34962
var GL_TEXTURE_2D = 0x0DE1
var GL_TEXTURE_CUBE_MAP = 0x8513

@@ -34,7 +37,6 @@ var CONTEXT_LOST_EVENT = 'webglcontextlost'

var extensionState = wrapExtensions(gl, options.requiredExtensions || [])
var extensionState = wrapExtensions(gl)
var limits = wrapLimits(gl, extensionState)
var bufferState = wrapBuffers(gl)
var elementState = wrapElements(gl, extensionState, bufferState)
var textureState = wrapTextures(gl, extensionState)
var fboState = wrapFBOs(gl, extensionState, textureState)
var uniformState = wrapUniforms()

@@ -52,2 +54,9 @@ var attributeState = wrapAttributes(gl, extensionState, bufferState)

var glState = wrapContext(gl, shaderState)
var textureState = wrapTextures(
gl,
extensionState,
limits,
poll,
glState.viewport)
var fboState = wrapFBOs(gl, extensionState, textureState)
var frameState = {

@@ -60,3 +69,4 @@ count: 0,

width: gl.drawingBufferWidth,
height: gl.drawingBufferHeight
height: gl.drawingBufferHeight,
pixelRatio: options.pixelRatio
}

@@ -98,2 +108,5 @@ var readPixels = wrapRead(gl, glState)

frameState.t = now
textureState.poll()
for (var i = 0; i < rafCallbacks.length; ++i) {

@@ -165,8 +178,2 @@ var cb = rafCallbacks[i]

function create (cache) {
return function (options) {
return cache.create(options)
}
}
// Compiles a set of procedures for an object

@@ -260,2 +267,6 @@ function compileProcedure (options) {

function poll () {
glState.poll()
}
// Clears the currently bound frame buffer

@@ -320,8 +331,21 @@ function clear (options) {

// Object constructors
elements: create(elementState),
elements: function (options) {
return elementState.create(options)
},
buffer: function (options) {
return bufferState.create(options, GL_ARRAY_BUFFER)
},
texture: create(textureState),
fbo: create(fboState),
texture: function (options) {
return textureState.create(options, GL_TEXTURE_2D)
},
cube: function (options) {
if (arguments.length === 6) {
return textureState.create(
Array.prototype.slice.call(arguments),
GL_TEXTURE_CUBE_MAP)
} else {
return textureState.create(options, GL_TEXTURE_CUBE_MAP)
}
},
// fbo: create(fboState),

@@ -332,2 +356,5 @@ // Frame rendering

// System limits
limits: limits,
// Read pixels

@@ -334,0 +361,0 @@ read: readPixels,

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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc