Comparing version 0.4.0 to 0.5.0
@@ -5,16 +5,51 @@ # Release notes | ||
* Add a mechanism for requiring/selectively disabling extensions | ||
* Upgrade vertex pointer format, allow for implicit conversion from arrays | ||
* Improve validation of vertex attributes | ||
* Refactor attributeState, some names are inconsistent and code is too complex | ||
* Change buffer and texture APIs to separate data from rest of options (or maybe not?) | ||
* Add in place update methods to buffers and textures | ||
* Add support for polling buffers and animated GIFs (useful for web audio) | ||
* Cubic framebuffer objects | ||
* More unit tests, improve code coverage | ||
* Support fixed scopes as arguments | ||
* Support directly constructing elements and attributes from arrays | ||
* Code generation rewrite | ||
+ per-batch contexts | ||
+ Allow for batch scopes | ||
+ Stop using stacks for managing states, save state locally in command | ||
* Error reporting | ||
+ All error messages should link to command/resource declaration | ||
+ Improve validation of vertex attributes | ||
+ Improve validation of dynamic properties | ||
* Resource API improvements | ||
+ Add in place update methods to buffers and textures | ||
+ Add support for polling buffers and animated GIFs (useful for web audio) | ||
* Implement a standard method for handling context creation errors | ||
* Add a mechanism for managing webgl extensions | ||
+ Should be able to report errors when extensions are missing | ||
+ Allow users to disable extensions for testing/mocking | ||
* Cubic frame buffer objects | ||
* WebVR support and integration (need to think how this will work) | ||
* Documentation | ||
+ Write "regl for react programmers" | ||
+ Rewrite resource section, bring individual resources to the top | ||
* Code quality and management | ||
+ Refactor attributeState, some names are inconsistent and code is too complex | ||
+ Update development documentation | ||
+ Add contributing guidelines and code of conduct | ||
* Testing | ||
+ Instancing | ||
+ Texture generation | ||
+ Framebuffers | ||
+ Element buffer rendering primitives | ||
+ Constant attributes | ||
+ Viewport change notifications | ||
+ RAF/frame behavior | ||
+ Complete coverage for all code generation pathways | ||
+ Test weird invocation sequences | ||
* Benchmark suite | ||
* Optimize generated code | ||
* Optimize bundle size, remove string constants | ||
+ Dashboard for test cases and benchmarks | ||
+ Create some more typical drawing examples | ||
* Optimization | ||
+ Save environment and this variables across batch mode invocations | ||
+ Kill all VM bailouts on all major platforms | ||
+ Kill all garbage collection | ||
+ Optimize generated code | ||
+ Optimize bundle size, remove string constants | ||
* Support more DDS texture formats (HDR, PVRTC, etc.) | ||
* Build a website (@freeman-lab is on it!) | ||
* Render to glTF (maybe?), could be useful for dumping previews | ||
* Recipe book/example set | ||
@@ -33,2 +68,11 @@ + Minecraft example | ||
## 0.5.0 | ||
* Context variables | ||
* Use `this` argument effectively | ||
* Should pass this to dynamic attributes and scope | ||
* Make scopes and dynamic attributes take same argument | ||
* Combine batchId with stats argument | ||
* Pass `this` to draw commands so that they can be stored as members | ||
## 0.4.0 | ||
@@ -35,0 +79,0 @@ |
@@ -5,42 +5,50 @@ # Build environment | ||
`regl` uses [standard](https://github.com/feross/standard) style | ||
* `regl` ahderes to the [standard](https://github.com/feross/standard) style. | ||
* Write all test cases, benchmarks and library code using strict ES5 style. | ||
* Write examples using ES6 | ||
## Testing | ||
## Development set up | ||
regl uses [tape](https://www.npmjs.com/package/tape) | ||
* To set up the development environment for regl, you first need to install [nodejs](https://nodejs.org/en/). Any version >0.10 is supported. | ||
* Once this is done, you can install regl's development dependencies using the following npm command: | ||
### Running tests | ||
``` | ||
npm install | ||
``` | ||
#### In node | ||
With headless-gl, you can just do: | ||
## Testing and benchmarks | ||
* regl uses [tape](https://www.npmjs.com/package/tape) for unit testing | ||
* To run the test cases in node, use the following command: | ||
``` | ||
npm run test | ||
``` | ||
Which should run all test cases | ||
#### In the browser | ||
* To run the test cases in your web browser, use: | ||
``` | ||
npm run test-browser | ||
``` | ||
### Adding tests | ||
### Test coverage | ||
* To add a test case, create a new file in the `test/` folder and then add a reference to it in `test/util/index.js` | ||
* To generate a code coverage report, you can run the following command. A report webpage will the be generated in `coverage/lcov-report/index.html` | ||
``` | ||
npm run coverage | ||
``` | ||
* To run benchmarks, use this command: | ||
``` | ||
npm run bench | ||
``` | ||
* The easiest way to add a new benchmark is to copy an existing benchmark (see for example `bench/clear.js`), modify it, and add an entry to `bench/list.js` | ||
## Benchmarks | ||
## Building | ||
### Running benchmarks | ||
* To rebuild all redistributable assets and the static website, use the command: | ||
``` | ||
npm run bench | ||
npm run build | ||
``` | ||
* If you just want to modify the examples, you can do | ||
``` | ||
npm run build-gallery | ||
``` | ||
### Adding benchmarks | ||
Copy an existing benchmark (see for example `bench/clear.js`) and add it to `bench/list.js` | ||
## How to help out | ||
Check out the [change log](CHANGES.md) for planned features and tasks. Alternatively, if you want to propose a new feature or report a bug, you should open an issue on GitHub. |
@@ -43,3 +43,3 @@ var glTypes = require('./constants/dtypes.json') | ||
left.normalized === right.normalized && | ||
left.type === right.type && | ||
left.type === (right.type || right.buffer.dtype || GL_FLOAT) && | ||
left.offset === right.offset && | ||
@@ -57,3 +57,3 @@ left.stride === right.stride && | ||
left.normalized = right.normalized | ||
left.type = right.type | ||
left.type = right.type || right.buffer.dtype || GL_FLOAT | ||
left.offset = right.offset | ||
@@ -95,17 +95,11 @@ left.stride = right.stride | ||
if (!next.pointer) { | ||
if (current.pointer) { | ||
gl.disableVertexAttribArray(index) | ||
} | ||
gl.disableVertexAttribArray(index) | ||
gl.vertexAttrib4f(index, next.x, next.y, next.z, next.w) | ||
} else { | ||
if (!current.pointer) { | ||
gl.enableVertexAttribArray(index) | ||
} | ||
if (current.buffer !== next.buffer) { | ||
next.buffer.bind() | ||
} | ||
gl.enableVertexAttribArray(index) | ||
next.buffer.bind() | ||
gl.vertexAttribPointer( | ||
index, | ||
size, | ||
next.type, | ||
next.type || next.buffer.dtype || GL_FLOAT, | ||
next.normalized, | ||
@@ -168,3 +162,3 @@ next.stride, | ||
var normalized = false | ||
var type = GL_FLOAT | ||
var type = 0 | ||
if (!buffer) { | ||
@@ -179,8 +173,6 @@ buffer = bufferState.getBuffer(data.buffer) | ||
normalized = data.normalized || false | ||
type = buffer.dtype | ||
type = 0 | ||
if ('type' in data) { | ||
type = glTypes[data.type] | ||
} | ||
} else { | ||
type = buffer.dtype | ||
} | ||
@@ -187,0 +179,0 @@ box.pointer = true |
@@ -70,3 +70,3 @@ // Array and element buffer creation | ||
module.exports = function wrapBufferState (gl) { | ||
module.exports = function wrapBufferState (gl, unbindBuffer) { | ||
var bufferCount = 0 | ||
@@ -91,2 +91,3 @@ var bufferSet = {} | ||
function refresh (buffer) { | ||
unbindBuffer(buffer) | ||
if (!gl.isBuffer(buffer.buffer)) { | ||
@@ -102,2 +103,3 @@ buffer.buffer = gl.createBuffer() | ||
check(handle, 'buffer must not be deleted already') | ||
unbindBuffer(buffer) | ||
if (gl.isBuffer(handle)) { | ||
@@ -104,0 +106,0 @@ gl.deleteBuffer(handle) |
@@ -50,2 +50,7 @@ var check = require('./util/check') | ||
var DYN_FUNC = 0 | ||
var DYN_PROP = 1 | ||
var DYN_CONTEXT = 2 | ||
var DYN_STATE = 3 | ||
var blendFuncs = { | ||
@@ -203,3 +208,3 @@ '0': 0, | ||
drawState, | ||
frameState, | ||
context, | ||
reglPoll) { | ||
@@ -357,3 +362,3 @@ var contextState = glState.contextState | ||
var BIND_ATTRIBUTE_RECORD = link(attributeState.bindRecord) | ||
var FRAME_STATE = link(frameState) | ||
var CONTEXT = link(context) | ||
var FRAMEBUFFER_STATE = link(framebufferState) | ||
@@ -408,8 +413,19 @@ var DRAW_STATE = { | ||
} | ||
if (x.func) { | ||
result = batch.def( | ||
link(x.data), '(', ARG, ',', BATCH_ID, ',', FRAME_STATE, ')') | ||
} else { | ||
result = batch.def(ARG, '.', x.data) | ||
switch (x.type) { | ||
case DYN_FUNC: | ||
result = batch.def( | ||
link(x.data), '.call(this,', ARG, ',', CONTEXT, ')') | ||
break | ||
case DYN_PROP: | ||
result = batch.def(ARG, x.data) | ||
break | ||
case DYN_CONTEXT: | ||
result = batch.def(CONTEXT, x.data) | ||
break | ||
case DYN_STATE: | ||
result = batch.def('this', x.data) | ||
break | ||
} | ||
dynamicVars[id] = result | ||
@@ -485,3 +501,4 @@ return result | ||
'for(', BATCH_ID, '=0;', BATCH_ID, '<', NUM_ARGS, ';++', BATCH_ID, '){', | ||
ARG, '=', ARGS, '[', BATCH_ID, '];') | ||
ARG, '=', ARGS, '[', BATCH_ID, '];', | ||
CONTEXT, '.batchId=', BATCH_ID, ';') | ||
@@ -818,11 +835,11 @@ // ------------------------------- | ||
// =================================================== | ||
// =================================================== | ||
// =========================================================================== | ||
// =========================================================================== | ||
// MAIN DRAW COMMAND | ||
// =================================================== | ||
// =================================================== | ||
// =========================================================================== | ||
// =========================================================================== | ||
function compileCommand ( | ||
staticOptions, staticUniforms, staticAttributes, | ||
dynamicOptions, dynamicUniforms, dynamicAttributes, | ||
hasDynamic) { | ||
contextVars, hasDynamic) { | ||
// Create code generation environment | ||
@@ -852,2 +869,3 @@ var env = createEnvironment() | ||
var STENCIL_OPS = link(stencilOps) | ||
var CONTEXT = link(context) | ||
@@ -871,3 +889,46 @@ var CONTEXT_STATE = {} | ||
var DYNARGS | ||
if (hasDynamic) { | ||
DYNARGS = entry.def() | ||
} | ||
// ------------------------------- | ||
// update context variables | ||
// ------------------------------- | ||
// Initialize batch id | ||
entry(CONTEXT, '.batchId=0;') | ||
var contextEnter = block() | ||
Object.keys(contextVars.static).forEach(function (contextVar) { | ||
var PREV_VALUE = entry.def(CONTEXT, '.', contextVar) | ||
contextEnter(CONTEXT, '.', contextVar, '=', | ||
link(contextVars.static[contextVar]), ';') | ||
exit(CONTEXT, '.', contextVar, '=', PREV_VALUE, ';') | ||
}) | ||
Object.keys(contextVars.dynamic).forEach(function (contextVar) { | ||
var PREV_VALUE = entry.def(CONTEXT, '.', contextVar) | ||
var NEXT_VALUE = entry.def() | ||
var x = contextVars.dynamic[contextVar] | ||
contextEnter(CONTEXT, '.', contextVar, '=', NEXT_VALUE, ';') | ||
switch (x.type) { | ||
case DYN_FUNC: | ||
entry(NEXT_VALUE, '=', link(x.data), '.call(this,', DYNARGS, ',', CONTEXT, ');') | ||
break | ||
case DYN_PROP: | ||
entry(NEXT_VALUE, '=', DYNARGS, x.data, ';') | ||
break | ||
case DYN_CONTEXT: | ||
entry(NEXT_VALUE, '=', CONTEXT, x.data, ';') | ||
break | ||
case DYN_STATE: | ||
entry(NEXT_VALUE, '=', 'this', x.data, ';') | ||
break | ||
} | ||
exit(CONTEXT, '.', contextVar, '=', PREV_VALUE, ';') | ||
}) | ||
entry(contextEnter) | ||
// ------------------------------- | ||
// update default context state variables | ||
@@ -1227,9 +1288,2 @@ // ------------------------------- | ||
var FRAMESTATE | ||
var DYNARGS | ||
if (hasDynamic) { | ||
FRAMESTATE = link(frameState) | ||
DYNARGS = entry.def() | ||
} | ||
var dynamicVars = {} | ||
@@ -1242,7 +1296,16 @@ function dyn (x) { | ||
} | ||
if (x.func) { | ||
result = dynamicEntry.def( | ||
link(x.data), '(', DYNARGS, ',0,', FRAMESTATE, ')') | ||
} else { | ||
result = dynamicEntry.def(DYNARGS, '.', x.data) | ||
switch (x.type) { | ||
case DYN_FUNC: | ||
result = dynamicEntry.def( | ||
link(x.data), '.call(this,', DYNARGS, ',', CONTEXT, ')') | ||
break | ||
case DYN_PROP: | ||
result = dynamicEntry.def(DYNARGS, x.data) | ||
break | ||
case DYN_CONTEXT: | ||
result = dynamicEntry.def(CONTEXT, x.data) | ||
break | ||
case DYN_STATE: | ||
result = dynamicEntry.def('this', x.data) | ||
break | ||
} | ||
@@ -1498,10 +1561,11 @@ dynamicVars[id] = result | ||
var SCOPE_BODY = scope.arg() | ||
if (hasDynamic) { | ||
scope(DYNARGS, '=', SCOPE_ARGS, ';') | ||
} | ||
scope(entry) | ||
if (hasDynamic) { | ||
scope( | ||
DYNARGS, '=', SCOPE_ARGS, ';', | ||
dynamicEntry) | ||
scope(dynamicEntry) | ||
} | ||
scope( | ||
SCOPE_BODY, '();', | ||
SCOPE_BODY, '(', SCOPE_ARGS, ',', CONTEXT, ');', | ||
hasDynamic ? dynamicExit : '', | ||
@@ -1533,7 +1597,8 @@ exit) | ||
var draw = proc('draw') | ||
if (hasDynamic) { | ||
draw(DYNARGS, '=', draw.arg(), ';') | ||
} | ||
draw(entry, commonDraw) | ||
if (hasDynamic) { | ||
draw( | ||
DYNARGS, '=', draw.arg(), ';', | ||
dynamicEntry) | ||
draw(dynamicEntry) | ||
} | ||
@@ -1543,3 +1608,3 @@ draw( | ||
'if(', CURRENT_PROGRAM, ')', | ||
CURRENT_PROGRAM, '.draw(', hasDynamic ? DYNARGS : '', ');', | ||
CURRENT_PROGRAM, '.draw.call(this', hasDynamic ? ',' + DYNARGS : '', ');', | ||
hasDynamic ? dynamicExit : '', | ||
@@ -1552,2 +1617,7 @@ exit) | ||
var batch = proc('batch') | ||
var BATCH_COUNT = batch.arg() | ||
var BATCH_ARGS = batch.arg() | ||
if (hasDynamic) { | ||
batch(DYNARGS, '=', BATCH_ARGS, '[0];') | ||
} | ||
batch(entry, commonDraw) | ||
@@ -1561,3 +1631,3 @@ var EXEC_BATCH = link(function (program, count, args) { | ||
} | ||
return proc(count, args) | ||
return proc.call(this, count, args) | ||
}) | ||
@@ -1567,6 +1637,6 @@ batch( | ||
GL_POLL, '();', | ||
EXEC_BATCH, '(', | ||
EXEC_BATCH, '.call(this,', | ||
CURRENT_PROGRAM, ',', | ||
batch.arg(), ',', | ||
batch.arg(), ');') | ||
BATCH_COUNT, ',', | ||
BATCH_ARGS, ');') | ||
// Set dirty on all dynamic flags | ||
@@ -1573,0 +1643,0 @@ Object.keys(dynamicOptions).forEach(function (option) { |
@@ -0,10 +1,58 @@ | ||
var check = require('./util/check') | ||
var VARIABLE_COUNTER = 0 | ||
function DynamicVariable (isFunc, data) { | ||
var DYN_FUNC = 0 | ||
var DYN_PENDING_FLAG = 128 | ||
function DynamicVariable (type, data) { | ||
this.id = (VARIABLE_COUNTER++) | ||
this.func = isFunc | ||
this.type = type | ||
this.data = data | ||
} | ||
function defineDynamic (data, path) { | ||
function escapeStr (str) { | ||
return str.replace(/\\/g, '\\\\').replace(/"/g, '\\"') | ||
} | ||
function splitParts (str) { | ||
if (str.length === 0) { | ||
return [] | ||
} | ||
var firstChar = str.charAt(0) | ||
var lastChar = str.charAt(str.length - 1) | ||
if (str.length > 1 && | ||
firstChar === lastChar && | ||
(firstChar === '"' || firstChar === "'")) { | ||
return ['"' + escapeStr(str.substr(1, str.length - 2)) + '"'] | ||
} | ||
var parts = /\[(false|true|null|\d+|'[^']*'|"[^"]*")\]/.exec(str) | ||
if (parts) { | ||
return ( | ||
splitParts(str.substr(0, parts.index)) | ||
.concat(splitParts(parts[1])) | ||
.concat(splitParts(str.substr(parts.index + parts[0].length))) | ||
) | ||
} | ||
var subparts = str.split('.') | ||
if (subparts.length === 1) { | ||
return ['"' + escapeStr(str) + '"'] | ||
} | ||
var result = [] | ||
for (var i = 0; i < subparts.length; ++i) { | ||
result = result.concat(splitParts(subparts[i])) | ||
} | ||
return result | ||
} | ||
function toAccessorString (str) { | ||
return '[' + splitParts(str).join('][') + ']' | ||
} | ||
function defineDynamic (type, data) { | ||
switch (typeof data) { | ||
@@ -14,7 +62,9 @@ case 'boolean': | ||
case 'string': | ||
return new DynamicVariable(false, data) | ||
case 'function': | ||
return new DynamicVariable(true, data) | ||
return new DynamicVariable(type, toAccessorString(data + '')) | ||
case 'undefined': | ||
return new DynamicVariable(type | DYN_PENDING_FLAG, null) | ||
default: | ||
return defineDynamic | ||
check.raise('invalid property type') | ||
} | ||
@@ -30,8 +80,11 @@ } | ||
if (x instanceof DynamicVariable) { | ||
return x | ||
} else if (typeof x === 'function' && | ||
x !== defineDynamic) { | ||
return new DynamicVariable(true, x) | ||
if (x.type & DYN_PENDING_FLAG) { | ||
return new DynamicVariable( | ||
x.type & ~DYN_PENDING_FLAG, | ||
toAccessorString(path)) | ||
} | ||
} else if (typeof x === 'function') { | ||
return new DynamicVariable(DYN_FUNC, x) | ||
} | ||
return new DynamicVariable(false, path) | ||
return x | ||
} | ||
@@ -42,3 +95,4 @@ | ||
isDynamic: isDynamic, | ||
unbox: unbox | ||
unbox: unbox, | ||
accessor: toAccessorString | ||
} |
@@ -5,2 +5,3 @@ var isTypedArray = require('./is-typed-array') | ||
return ( | ||
!!obj && | ||
typeof obj === 'object' && | ||
@@ -7,0 +8,0 @@ Array.isArray(obj.shape) && |
{ | ||
"name": "regl", | ||
"version": "0.4.0", | ||
"version": "0.5.0", | ||
"description": "WebGL", | ||
@@ -19,3 +19,3 @@ "main": "regl.js", | ||
"canvas-orbit-camera": "^1.0.2", | ||
"coverify": "^1.4.1", | ||
"codacy-coverage": "^1.1.3", | ||
"falafel": "^1.2.0", | ||
@@ -29,2 +29,3 @@ "faucet": "0.0.1", | ||
"indexhtmlify": "^1.2.1", | ||
"istanbul": "^0.4.3", | ||
"mkdirp": "^0.5.1", | ||
@@ -34,3 +35,2 @@ "mouse-change": "^1.3.0", | ||
"runscript": "^1.1.0", | ||
"smokestack": "^3.4.1", | ||
"snazzy": "^3.0.0", | ||
@@ -44,5 +44,5 @@ "standard": "^6.0.7", | ||
"scripts": { | ||
"test": "standard | snazzy && tape test/*.js | faucet", | ||
"test": "standard | snazzy && tape test/util/index.js | faucet", | ||
"test-browser": "budo test/util/browser.js --open", | ||
"coverage": "browserify test/util/browser.js -t coverify | smokestack | coverify", | ||
"cover": "istanbul cover test/util/index.js", | ||
"bench": "budo bench/index.js --open", | ||
@@ -49,0 +49,0 @@ "build": "npm run build-script && npm run build-min && npm run build-bench && npm run build-gallery", |
# regl | ||
[![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/) | ||
[![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=shield)](https://circleci.com/gh/mikolalysenko/regl) [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/) | ||
[![npm version](https://badge.fury.io/js/regl.svg)](https://badge.fury.io/js/regl) ![file size](https://badge-size.herokuapp.com/mikolalysenko/regl/gh-pages/dist/regl.min.js.svg?compression=gzip) | ||
@@ -191,3 +192,3 @@ 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). | ||
Development supported by the [Freeman Lab](https://www.janelia.org/lab/freeman-lab) and the Howard Hughes Medical Institute (@freeman-lab on GitHub) | ||
Development supported by the [Freeman Lab](https://www.janelia.org/lab/freeman-lab) and the Howard Hughes Medical Institute ([@freeman-lab](https://github.com/freeman-lab) on GitHub) | ||
@@ -199,4 +200,4 @@ ### Asset licenses | ||
* 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) | ||
* Environment map of Oregon (ogd-oregon-360.jpg) due to Max Ogden ([@maxogd](https://github.com/maxogden) 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) | ||
* Tile set for tile mapping demo (tiles.png) from CC0 licensed [cobblestone paths pack](http://opengameart.org/content/rpg-tiles-cobble-stone-paths-town-objects) |
77
regl.js
var check = require('./lib/util/check') | ||
var extend = require('./lib/util/extend') | ||
var getContext = require('./lib/context') | ||
var initWebGL = require('./lib/webgl') | ||
var createStringStore = require('./lib/strings') | ||
@@ -34,4 +34,8 @@ var wrapExtensions = require('./lib/extension') | ||
var DYN_PROP = 1 | ||
var DYN_CONTEXT = 2 | ||
var DYN_STATE = 3 | ||
module.exports = function wrapREGL () { | ||
var args = getContext(Array.prototype.slice.call(arguments)) | ||
var args = initWebGL(Array.prototype.slice.call(arguments)) | ||
var gl = args.gl | ||
@@ -54,3 +58,3 @@ var options = args.options | ||
var bufferState = wrapBuffers(gl) | ||
var bufferState = wrapBuffers(gl, unbindBuffer) | ||
@@ -104,7 +108,9 @@ var elementState = wrapElements( | ||
var startTime = clock() | ||
var frameState = { | ||
count: 0, | ||
start: clock(), | ||
start: startTime, | ||
dt: 0, | ||
t: clock(), | ||
t: startTime, | ||
renderTime: 0, | ||
@@ -116,2 +122,14 @@ width: gl.drawingBufferWidth, | ||
var context = { | ||
count: 0, | ||
batchId: 0, | ||
deltaTime: 0, | ||
time: 0, | ||
viewportWidth: frameState.width, | ||
viewportHeight: frameState.height, | ||
drawingBufferWidth: frameState.width, | ||
drawingBufferHeight: frameState.height, | ||
pixelRatio: frameState.pixelRatio | ||
} | ||
var glState = wrapContext( | ||
@@ -138,5 +156,17 @@ gl, | ||
drawState, | ||
frameState, | ||
context, | ||
poll) | ||
function unbindBuffer (buffer) { | ||
for (var i = 0; i < attributeState.bindings.length; ++i) { | ||
var attr = attributeState.bindings[i] | ||
if (attr.pointer && attr.buffer === buffer) { | ||
attr.pointer = false | ||
attr.buffer = null | ||
attr.x = attr.y = attr.z = attr.w = NaN | ||
gl.disableVertexAttribArray(i) | ||
} | ||
} | ||
} | ||
var canvas = gl.canvas | ||
@@ -149,7 +179,12 @@ | ||
frameState.count += 1 | ||
context.count = frameState.count | ||
if (frameState.width !== gl.drawingBufferWidth || | ||
frameState.height !== gl.drawingBufferHeight) { | ||
frameState.width = gl.drawingBufferWidth | ||
frameState.height = gl.drawingBufferHeight | ||
context.viewportWidth = | ||
context.drawingBufferWidth = | ||
frameState.width = gl.drawingBufferWidth | ||
context.viewportHeight = | ||
context.drawingBufferHeight = | ||
frameState.height = gl.drawingBufferHeight | ||
glState.notifyViewportChanged() | ||
@@ -162,2 +197,5 @@ } | ||
context.deltaTime = frameState.dt / 1000.0 | ||
context.time = (now - startTime) / 1000.0 | ||
textureState.poll() | ||
@@ -167,3 +205,3 @@ | ||
var cb = rafCallbacks[i] | ||
cb(frameState.count, frameState.t, frameState.dt) | ||
cb(null, context) | ||
} | ||
@@ -243,2 +281,3 @@ frameState.renderTime = clock() - now | ||
delete result.attributes | ||
delete result.context | ||
@@ -283,2 +322,4 @@ function merge (name) { | ||
// Treat context variables separate from other dynamic variables | ||
var context = separateDynamic(options.context || {}) | ||
var uniforms = separateDynamic(options.uniforms || {}) | ||
@@ -291,3 +332,3 @@ var attributes = separateDynamic(options.attributes || {}) | ||
opts.dynamic, uniforms.dynamic, attributes.dynamic, | ||
hasDynamic) | ||
context, hasDynamic) | ||
@@ -310,5 +351,5 @@ var draw = compiled.draw | ||
if (typeof args === 'function') { | ||
return scope(null, args) | ||
return scope.call(this, null, args) | ||
} else if (typeof body === 'function') { | ||
return scope(args, body) | ||
return scope.call(this, args, body) | ||
} | ||
@@ -330,7 +371,7 @@ | ||
if (typeof args === 'number') { | ||
return batch(args | 0, reserve(args | 0)) | ||
return batch.call(this, args | 0, reserve(args | 0)) | ||
} else if (Array.isArray(args)) { | ||
return batch(args.length, args) | ||
return batch.call(this, args.length, args) | ||
} | ||
return draw(args) | ||
return draw.call(this, args) | ||
} | ||
@@ -396,4 +437,6 @@ | ||
// Short cut for prop binding | ||
prop: dynamic.define, | ||
// Short cuts for dynamic variables | ||
prop: dynamic.define.bind(null, DYN_PROP), | ||
context: dynamic.define.bind(null, DYN_CONTEXT), | ||
this: dynamic.define.bind(null, DYN_STATE), | ||
@@ -400,0 +443,0 @@ // executes an empty draw command |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1744177
83
12531
202