From fec36034d5988a8f83d473e111923931a47c0353 Mon Sep 17 00:00:00 2001 From: Brian Chirls Date: Sun, 19 Jan 2014 19:33:16 -0500 Subject: [PATCH 01/45] Effect nodes are now more inspectable #41 - `inputs` method added for reporting details on all inputs - effect type and title are available properties - removed useless `original` property from effect nodes --- seriously.js | 71 +++++++++++++++++++++++++++++++++++++----- test/seriously.unit.js | 62 ++++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+), 8 deletions(-) diff --git a/seriously.js b/seriously.js index 0ec6712..f0e8907 100644 --- a/seriously.js +++ b/seriously.js @@ -1631,22 +1631,18 @@ } Object.defineProperties(this, { - inputs: { + effect: { enumerable: true, configurable: true, get: function () { - return { - source: { - type: 'image' - } - }; + return me.hook; } }, - original: { + title: { enumerable: true, configurable: true, get: function () { - return me.source; + return me.effect.title || me.hook; } }, width: { @@ -1689,6 +1685,65 @@ me.off(eventName, callback); }; + this.inputs = function (name) { + var result, + input, + inputs, + enumOption, + i, + key; + + inputs = me.effect.inputs; + + if (name) { + input = inputs[name]; + if (!input) { + return null; + } + + result = { + type: input.type, + defaultValue: input.defaultValue, + title: input.title || name + }; + + if (input.type === 'number') { + result.min = input.min; + result.max = input.max; + result.step = input.step; + } else if (input.type === 'enum') { + //make a deep copy + result.options = []; + if (options) { + for (i = 0; i < input.options.length; i++) { + enumOption = input.options[i]; + if (Array.isArray(enumOption)) { + result.options.push(enumOption.slice(0)); + } else { + result.options.push(enumOption); + } + } + } + } else if (input.type === 'vector') { + result.dimensions = input.dimensions; + } + + if (input.description) { + result.description = input.description; + } + + return result; + } + + result = {}; + for (key in inputs) { + if (inputs.hasOwnProperty(key)) { + result[key] = this.inputs(key); + } + } + return result; + }; + this.alias = function (inputName, aliasName) { me.alias(inputName, aliasName); return this; diff --git a/test/seriously.unit.js b/test/seriously.unit.js index fbafa1e..df7e94f 100644 --- a/test/seriously.unit.js +++ b/test/seriously.unit.js @@ -412,6 +412,68 @@ Seriously.removePlugin('removeme'); }); + test('Effect Info', 14, function () { + var inputs, + input, + seriously, + effect; + + Seriously.plugin('test', { + inputs: { + number: { + type: 'number', + min: -4, + max: 100, + step: 2, + defaultValue: 8, + description: 'this is a number', + title: 'Number' + }, + vector: { + type: 'vector', + dimensions: 3 + }, + e: { + type: 'enum', + options: [ + ['one', 'One'], + ['two', 'Two'] + ] + } + }, + title: 'Test' + }); + + seriously = new Seriously(); + effect = seriously.effect('test'); + + equal(effect.effect, 'test', 'Effect name reported'); + equal(effect.title, 'Test', 'Effect title reported'); + ok(effect.id >= 0, 'Effect id reported'); + + //Check inputs + inputs = effect.inputs(); + ok(inputs.number && inputs.vector && inputs.e, 'All inputs are present'); + equal(Object.keys(inputs).length, 3, 'No extra properties'); + + equal(inputs.number.min, -4, 'Number minimum reported'); + equal(inputs.number.max, 100, 'Number maximum reported'); + equal(inputs.number.step, 2, 'Number step reported'); + equal(inputs.number.defaultValue, 8, 'Number default value reported'); + equal(inputs.number.title, 'Number', 'Node title reported'); + equal(inputs.number.description, 'this is a number', 'Node description reported'); + + equal(inputs.vector.dimensions, 3, 'Vector dimensions reported'); + + ok(Array.isArray(inputs.e.options), 'Enum options reported'); + + inputs.e.options[1][0] = 'three'; + equal(effect.inputs('e').options[1][0], 'two', 'Enum options fully copied, cannot be tampered with'); + + seriously.destroy; + Seriously.removePlugin('test'); + }); + module('Source'); /* * create source: all different types From 3ed200dd86870d472b7a856f90464e0da56a9be8 Mon Sep 17 00:00:00 2001 From: Brian Chirls Date: Tue, 21 Jan 2014 20:27:49 -0500 Subject: [PATCH 02/45] Added width and height read-only properties to Source nodes --- seriously.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/seriously.js b/seriously.js index f0e8907..613c09c 100644 --- a/seriously.js +++ b/seriously.js @@ -2668,6 +2668,20 @@ get: function () { return me.id; } + }, + width: { + enumerable: true, + configurable: true, + get: function () { + return me.width; + } + }, + height: { + enumerable: true, + configurable: true, + get: function () { + return me.height; + } } }); From e68336bafa1a5664c9fdb14735ea87df533763c7 Mon Sep 17 00:00:00 2001 From: Brian Chirls Date: Tue, 21 Jan 2014 20:28:44 -0500 Subject: [PATCH 03/45] Added Freeze Frame effect --- effects/seriously.freeze.js | 40 +++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 effects/seriously.freeze.js diff --git a/effects/seriously.freeze.js b/effects/seriously.freeze.js new file mode 100644 index 0000000..76080b4 --- /dev/null +++ b/effects/seriously.freeze.js @@ -0,0 +1,40 @@ +/* global define, require */ +(function (root, factory) { + 'use strict'; + + if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); + } else if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['seriously'], factory); + } else { + if (!root.Seriously) { + root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; + } + factory(root.Seriously); + } +}(this, function (Seriously, undefined) { + 'use strict'; + + Seriously.plugin('freeze', { + draw: function (shader, model, uniforms, frameBuffer, draw) { + if (!this.inputs.frozen) { + draw(shader, model, uniforms, frameBuffer); + } + }, + inPlace: true, + inputs: { + source: { + type: 'image', + uniform: 'source' + }, + frozen: { + type: 'boolean', + defaultValue: false + } + }, + title: 'Freeze', + description: 'Freeze Frame' + }); +})); From 8af7070a1538206cac46517017653629ce6e6a52 Mon Sep 17 00:00:00 2001 From: Brian Chirls Date: Thu, 23 Jan 2014 00:10:45 -0500 Subject: [PATCH 04/45] Camera source accepts constraints --- sources/seriously.camera.js | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/sources/seriously.camera.js b/sources/seriously.camera.js index 8c1b301..8ac4a52 100644 --- a/sources/seriously.camera.js +++ b/sources/seriously.camera.js @@ -28,6 +28,8 @@ Seriously.source('camera', function (source, options, force) { var me = this, video, + key, + opts, destroyed = false, stream; @@ -66,11 +68,22 @@ throw 'Camera source type unavailable. Browser does not support getUserMedia'; } + opts = {}; + if (source) { + //copy over constraints + for (key in source) { + if (source.hasOwnProperty(key)) { + opts[key] = source[key]; + } + } + } + if (!opts.video) { + opts.video = true; + } + video = document.createElement('video'); - getUserMedia.call(navigator, { - video: true - }, function (s) { + getUserMedia.call(navigator, opts, function (s) { stream = s; if (destroyed) { From 16ac2c08b32d3da15a427024d30bbf75353ba811 Mon Sep 17 00:00:00 2001 From: Brian Chirls Date: Fri, 28 Feb 2014 11:23:08 -0500 Subject: [PATCH 05/45] checkSource returns false if image/video has not loaded checkSource unit test still runs but skips drawImage if image fails to load, usually due to network disconnection. --- seriously.js | 10 ++++++++++ test/seriously.unit.js | 11 +++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/seriously.js b/seriously.js index 613c09c..3088791 100644 --- a/seriously.js +++ b/seriously.js @@ -429,6 +429,16 @@ return false; } + if (element.naturalWidth === 0 && element.tagName === 'IMG') { + console.log('Image not loaded'); + return false; + } + + if (element.readyState === 0 && element.videoWidth === 0 && element.tagName === 'VIDEO') { + console.log('Video not loaded'); + return false; + } + ctx = getTestContext(); if (ctx) { diff --git a/test/seriously.unit.js b/test/seriously.unit.js index df7e94f..b0efd93 100644 --- a/test/seriously.unit.js +++ b/test/seriously.unit.js @@ -1387,8 +1387,12 @@ canvas = document.createElement('canvas'); ctx = canvas.getContext('2d'); - ctx.drawImage(img, 0, 0); - ok(!Seriously.util.checkSource(canvas), 'Cross-origin canvas checks false'); + if (img.naturalWidth) { + ctx.drawImage(img, 0, 0); + ok(!Seriously.util.checkSource(canvas), 'Cross-origin canvas checks false'); + } else { + expect(3); + } tests--; if (!tests) { @@ -1410,6 +1414,9 @@ fail.addEventListener('load', function() { checkImageFail(this); }, false); + fail.addEventListener('error', function() { + checkImageFail(this); + }, false); }); /* From fa57eb3c42961be0049e4fa48a3fc8784a7c5775 Mon Sep 17 00:00:00 2001 From: Brian Chirls Date: Fri, 28 Feb 2014 12:50:23 -0500 Subject: [PATCH 06/45] Improved debug logging - Use .warn and .error where appropriate - Allow overriding of logging methods - Add some unit tests for logging --- seriously.js | 62 ++++++++++++++++++++++++++++++++---------- test/seriously.unit.js | 25 +++++++++++++++-- 2 files changed, 70 insertions(+), 17 deletions(-) diff --git a/seriously.js b/seriously.js index 3088791..d3b0023 100644 --- a/seriously.js +++ b/seriously.js @@ -293,6 +293,29 @@ return dest; } + function consoleMethod(name) { + var method; + if (!console) { + return nop; + } + + if (typeof console[name] === 'function') { + method = console[name]; + } else if (typeof console.log === 'function') { + method = console.log; + } else { + return nop; + } + + if (method.bind) { + return method.bind(console); + } + + return function () { + method.apply(console, arguments); + }; + } + //http://www.w3.org/TR/css3-color/#hsl-color function hslToRgb(h, s, l, a, out) { function hueToRgb(m1, m2, h) { @@ -408,7 +431,7 @@ } }, false); } else { - console.log('Unable to access WebGL.'); + Seriously.logger.warn('Unable to access WebGL.'); } return testContext; @@ -425,17 +448,17 @@ canvas = document.createElement('canvas'); if (!canvas) { - console.log('Browser does not support canvas or Seriously.js'); + Seriously.logger.warn('Browser does not support canvas or Seriously.js'); return false; } if (element.naturalWidth === 0 && element.tagName === 'IMG') { - console.log('Image not loaded'); + Seriously.logger.warn('Image not loaded'); return false; } if (element.readyState === 0 && element.videoWidth === 0 && element.tagName === 'VIDEO') { - console.log('Video not loaded'); + Seriously.logger.warn('Video not loaded'); return false; } @@ -449,9 +472,9 @@ ctx.texImage2D(ctx.TEXTURE_2D, 0, ctx.RGBA, ctx.RGBA, ctx.UNSIGNED_BYTE, element); } catch (textureError) { if (textureError.code === window.DOMException.SECURITY_ERR) { - console.log('Unable to access cross-domain image'); + Seriously.logger.log('Unable to access cross-domain image'); } else { - console.log('Error: ' + textureError.message); + Seriously.logger.error('Error storing image to texture: ' + textureError.message); } ctx.deleteTexture(texture); return false; @@ -464,9 +487,9 @@ ctx.getImageData(0, 0, 1, 1); } catch (drawImageError) { if (drawImageError.code === window.DOMException.SECURITY_ERR) { - console.log('Unable to access cross-domain image'); + Seriously.logger.log('Unable to access cross-domain image'); } else { - console.log('Error: ' + drawImageError.message); + Seriously.logger.error('Error drawing image to canvas: ' + drawImageError.message); } return false; } @@ -723,7 +746,8 @@ for (i = 0; i < source.length; i++) { source[i] = (i + 1) + ":\t" + source[i]; } - console.log(source.join('\n')); + source.unshift('Error compiling ' + (fragment ? 'fragment' : 'vertex') + ' shader:'); + Seriously.logger.error(source.join('\n')); throw 'Shader error: ' + gl.getShaderInfoLog(shader); } @@ -3083,7 +3107,7 @@ } catch (securityError) { if (securityError.code === window.DOMException.SECURITY_ERR) { this.allowRefresh = false; - console.log('Unable to access cross-domain image'); + Seriously.logger.error('Unable to access cross-domain image'); } } @@ -3122,7 +3146,7 @@ } catch (securityError) { if (securityError.code === window.DOMException.SECURITY_ERR) { this.allowRefresh = false; - console.log('Unable to access cross-domain image'); + Seriously.logger.error('Unable to access cross-domain image'); } } @@ -4523,7 +4547,7 @@ var effect; if (seriousEffects[hook]) { - console.log('Effect [' + hook + '] already loaded'); + Seriously.logger.warn('Effect [' + hook + '] already loaded'); return; } @@ -4592,7 +4616,7 @@ var source; if (seriousSources[hook]) { - console.log('Source [' + hook + '] already loaded'); + Seriously.logger.warn('Source [' + hook + '] already loaded'); return; } @@ -4652,7 +4676,7 @@ var transform; if (seriousTransforms[hook]) { - console.log('Transform [' + hook + '] already loaded'); + Seriously.logger.warn('Transform [' + hook + '] already loaded'); return; } @@ -4999,6 +5023,16 @@ } } + /* + + */ + Seriously.logger = { + log: consoleMethod('log'), + info: consoleMethod('info'), + warn: consoleMethod('warn'), + error: consoleMethod('error') + }; + //expose Seriously to the global object Seriously.util = { mat4: mat4, diff --git a/test/seriously.unit.js b/test/seriously.unit.js index b0efd93..d080318 100644 --- a/test/seriously.unit.js +++ b/test/seriously.unit.js @@ -19,6 +19,15 @@ return true; } + function nop() {} + + Seriously.logger = { + log: nop, + info: nop, + warn: nop, + error: nop + }; + module('Core'); test('Core', function () { var p, props = 0, @@ -180,8 +189,11 @@ test('Define plugin with duplicate name', function () { var p, allEffects; - expect(3); + expect(4); + Seriously.logger.warn = function (s) { + equal(s, 'Effect [pluginDuplicate] already loaded', 'Warning logged to console'); + }; p = Seriously.plugin('pluginDuplicate', { title: 'Original' }); @@ -196,6 +208,7 @@ allEffects = Seriously.effects(); equal(allEffects.pluginDuplicate.title, 'Original', 'Original plugin remains'); + Seriously.logger.warn = nop; Seriously.removePlugin('pluginDuplicate'); }); @@ -1361,7 +1374,7 @@ var pass, fail, tests = 2; - expect(4); + expect(6); function checkImagePass(img) { var canvas, ctx; @@ -1383,6 +1396,10 @@ function checkImageFail(img) { var canvas, ctx; + Seriously.logger.log = function (s) { + equal(s, 'Unable to access cross-domain image', 'Warning logged to console'); + }; + ok(!Seriously.util.checkSource(img), 'Cross-origin image checks false'); canvas = document.createElement('canvas'); @@ -1391,9 +1408,11 @@ ctx.drawImage(img, 0, 0); ok(!Seriously.util.checkSource(canvas), 'Cross-origin canvas checks false'); } else { - expect(3); + expect(4); } + Seriously.logger.log = nop; + tests--; if (!tests) { start(); From a18d6719b180b1ae0fdda55cb7d6e9e6d30b80ab Mon Sep 17 00:00:00 2001 From: Brian Chirls Date: Fri, 28 Feb 2014 17:21:26 -0500 Subject: [PATCH 07/45] Fix color names - Added pre-computed values for CSS1 color names not reported by Chrome - Unit tests now check all of CSS3 color names - Fixed value for 'green' - Fixed some small white space issues --- seriously.js | 22 +++-- test/seriously.unit.js | 193 +++++++++++++++++++++++++++++++++++------ 2 files changed, 184 insertions(+), 31 deletions(-) diff --git a/seriously.js b/seriously.js index d3b0023..510ed78 100644 --- a/seriously.js +++ b/seriously.js @@ -57,9 +57,21 @@ transparent: [0, 0, 0, 0], black: [0, 0, 0, 1], red: [1, 0, 0, 1], - green: [0, 1, 0, 1], + green: [0, 128 / 255, 0, 1], blue: [0, 0, 1, 1], - white: [1, 1, 1, 1] + white: [1, 1, 1, 1], + silver: [192 / 255, 192 / 255, 192 / 255, 1], + gray: [128 / 255, 128 / 255, 128 / 255, 1], + maroon: [128 / 255, 0, 0, 1], + purple: [128 / 255, 0, 128 / 255, 1], + fuchsia: [1, 0, 1, 1], + lime: [0, 1, 0, 1], + olive: [128 / 255, 128 / 255, 0, 1], + yellow: [1, 1, 0, 1], + navy: [0, 0, 128 / 255, 1], + teal: [0, 128 / 255, 128 / 255, 1], + aqua: [0, 1, 1, 1], + orange: [1, 165 / 255, 0, 1] }, vectorFields = ['x', 'y', 'z', 'w'], @@ -5892,10 +5904,10 @@ ' i0.z += isYZ.z;\n' + ' i0.w += 1.0 - isYZ.z;\n' + '\n' + - // i0 now contains the unique values 0,1,2,3 in each channel + // i0 now contains the unique values 0, 1, 2, 3 in each channel ' vec4 i3 = clamp(i0, 0.0, 1.0);\n' + - ' vec4 i2 = clamp(i0-1.0, 0.0, 1.0);\n' + - ' vec4 i1 = clamp(i0-2.0, 0.0, 1.0);\n' + + ' vec4 i2 = clamp(i0 - 1.0, 0.0, 1.0);\n' + + ' vec4 i1 = clamp(i0 - 2.0, 0.0, 1.0);\n' + '\n' + ' vec4 x1 = x0 - i1 + C.xxxx;\n' + ' vec4 x2 = x0 - i2 + C.yyyy;\n' + diff --git a/test/seriously.unit.js b/test/seriously.unit.js index d080318..cf9ed23 100644 --- a/test/seriously.unit.js +++ b/test/seriously.unit.js @@ -781,10 +781,156 @@ Seriously.removePlugin('testNumberInput'); }); - test('Color', function () { - var e, s, val; - - expect(18); + test('Color', 159, function () { + var e, s, val, + name, + colorNames = { + black: [0 / 255, 0 / 255, 0 / 255, 1], + silver: [192 / 255, 192 / 255, 192 / 255, 1], + gray: [128 / 255, 128 / 255, 128 / 255, 1], + white: [1, 1, 1, 1], + maroon: [128 / 255, 0 / 255, 0 / 255, 1], + red: [1, 0 / 255, 0 / 255, 1], + purple: [128 / 255, 0 / 255, 128 / 255, 1], + fuchsia: [1, 0 / 255, 1, 1], + green: [0 / 255, 128 / 255, 0 / 255, 1], + lime: [0 / 255, 1, 0 / 255, 1], + olive: [128 / 255, 128 / 255, 0 / 255, 1], + yellow: [1, 1, 0 / 255, 1], + navy: [0 / 255, 0 / 255, 128 / 255, 1], + blue: [0 / 255, 0 / 255, 1, 1], + teal: [0 / 255, 128 / 255, 128 / 255, 1], + aqua: [0 / 255, 1, 1, 1], + orange: [1, 165 / 255, 0 / 255, 1], + aliceblue: [240 / 255, 248 / 255, 1, 1], + antiquewhite: [250 / 255, 235 / 255, 215 / 255, 1], + aquamarine: [127 / 255, 1, 212 / 255, 1], + azure: [240 / 255, 1, 1, 1], + beige: [245 / 255, 245 / 255, 220 / 255, 1], + bisque: [1, 228 / 255, 196 / 255, 1], + blanchedalmond: [1, 235 / 255, 205 / 255, 1], + blueviolet: [138 / 255, 43 / 255, 226 / 255, 1], + brown: [165 / 255, 42 / 255, 42 / 255, 1], + burlywood: [222 / 255, 184 / 255, 135 / 255, 1], + cadetblue: [95 / 255, 158 / 255, 160 / 255, 1], + chartreuse: [127 / 255, 1, 0 / 255, 1], + chocolate: [210 / 255, 105 / 255, 30 / 255, 1], + coral: [1, 127 / 255, 80 / 255, 1], + cornflowerblue: [100 / 255, 149 / 255, 237 / 255, 1], + cornsilk: [1, 248 / 255, 220 / 255, 1], + crimson: [220 / 255, 20 / 255, 60 / 255, 1], + darkblue: [0 / 255, 0 / 255, 139 / 255, 1], + darkcyan: [0 / 255, 139 / 255, 139 / 255, 1], + darkgoldenrod: [184 / 255, 134 / 255, 11 / 255, 1], + darkgray: [169 / 255, 169 / 255, 169 / 255, 1], + darkgreen: [0 / 255, 100 / 255, 0 / 255, 1], + darkgrey: [169 / 255, 169 / 255, 169 / 255, 1], + darkkhaki: [189 / 255, 183 / 255, 107 / 255, 1], + darkmagenta: [139 / 255, 0 / 255, 139 / 255, 1], + darkolivegreen: [85 / 255, 107 / 255, 47 / 255, 1], + darkorange: [1, 140 / 255, 0 / 255, 1], + darkorchid: [153 / 255, 50 / 255, 204 / 255, 1], + darkred: [139 / 255, 0 / 255, 0 / 255, 1], + darksalmon: [233 / 255, 150 / 255, 122 / 255, 1], + darkseagreen: [143 / 255, 188 / 255, 143 / 255, 1], + darkslateblue: [72 / 255, 61 / 255, 139 / 255, 1], + darkslategray: [47 / 255, 79 / 255, 79 / 255, 1], + darkslategrey: [47 / 255, 79 / 255, 79 / 255, 1], + darkturquoise: [0 / 255, 206 / 255, 209 / 255, 1], + darkviolet: [148 / 255, 0 / 255, 211 / 255, 1], + deeppink: [1, 20 / 255, 147 / 255, 1], + deepskyblue: [0 / 255, 191 / 255, 1, 1], + dimgray: [105 / 255, 105 / 255, 105 / 255, 1], + dimgrey: [105 / 255, 105 / 255, 105 / 255, 1], + dodgerblue: [30 / 255, 144 / 255, 1, 1], + firebrick: [178 / 255, 34 / 255, 34 / 255, 1], + floralwhite: [1, 250 / 255, 240 / 255, 1], + forestgreen: [34 / 255, 139 / 255, 34 / 255, 1], + gainsboro: [220 / 255, 220 / 255, 220 / 255, 1], + ghostwhite: [248 / 255, 248 / 255, 1, 1], + gold: [1, 215 / 255, 0 / 255, 1], + goldenrod: [218 / 255, 165 / 255, 32 / 255, 1], + greenyellow: [173 / 255, 1, 47 / 255, 1], + grey: [128 / 255, 128 / 255, 128 / 255, 1], + honeydew: [240 / 255, 1, 240 / 255, 1], + hotpink: [1, 105 / 255, 180 / 255, 1], + indianred: [205 / 255, 92 / 255, 92 / 255, 1], + indigo: [75 / 255, 0 / 255, 130 / 255, 1], + ivory: [1, 1, 240 / 255, 1], + khaki: [240 / 255, 230 / 255, 140 / 255, 1], + lavender: [230 / 255, 230 / 255, 250 / 255, 1], + lavenderblush: [1, 240 / 255, 245 / 255, 1], + lawngreen: [124 / 255, 252 / 255, 0 / 255, 1], + lemonchiffon: [1, 250 / 255, 205 / 255, 1], + lightblue: [173 / 255, 216 / 255, 230 / 255, 1], + lightcoral: [240 / 255, 128 / 255, 128 / 255, 1], + lightcyan: [224 / 255, 1, 1, 1], + lightgoldenrodyellow: [250 / 255, 250 / 255, 210 / 255, 1], + lightgray: [211 / 255, 211 / 255, 211 / 255, 1], + lightgreen: [144 / 255, 238 / 255, 144 / 255, 1], + lightgrey: [211 / 255, 211 / 255, 211 / 255, 1], + lightpink: [1, 182 / 255, 193 / 255, 1], + lightsalmon: [1, 160 / 255, 122 / 255, 1], + lightseagreen: [32 / 255, 178 / 255, 170 / 255, 1], + lightskyblue: [135 / 255, 206 / 255, 250 / 255, 1], + lightslategray: [119 / 255, 136 / 255, 153 / 255, 1], + lightslategrey: [119 / 255, 136 / 255, 153 / 255, 1], + lightsteelblue: [176 / 255, 196 / 255, 222 / 255, 1], + lightyellow: [1, 1, 224 / 255, 1], + limegreen: [50 / 255, 205 / 255, 50 / 255, 1], + linen: [250 / 255, 240 / 255, 230 / 255, 1], + mediumaquamarine: [102 / 255, 205 / 255, 170 / 255, 1], + mediumblue: [0 / 255, 0 / 255, 205 / 255, 1], + mediumorchid: [186 / 255, 85 / 255, 211 / 255, 1], + mediumpurple: [147 / 255, 112 / 255, 219 / 255, 1], + mediumseagreen: [60 / 255, 179 / 255, 113 / 255, 1], + mediumslateblue: [123 / 255, 104 / 255, 238 / 255, 1], + mediumspringgreen: [0 / 255, 250 / 255, 154 / 255, 1], + mediumturquoise: [72 / 255, 209 / 255, 204 / 255, 1], + mediumvioletred: [199 / 255, 21 / 255, 133 / 255, 1], + midnightblue: [25 / 255, 25 / 255, 112 / 255, 1], + mintcream: [245 / 255, 1, 250 / 255, 1], + mistyrose: [1, 228 / 255, 225 / 255, 1], + moccasin: [1, 228 / 255, 181 / 255, 1], + navajowhite: [1, 222 / 255, 173 / 255, 1], + oldlace: [253 / 255, 245 / 255, 230 / 255, 1], + olivedrab: [107 / 255, 142 / 255, 35 / 255, 1], + orangered: [1, 69 / 255, 0 / 255, 1], + orchid: [218 / 255, 112 / 255, 214 / 255, 1], + palegoldenrod: [238 / 255, 232 / 255, 170 / 255, 1], + palegreen: [152 / 255, 251 / 255, 152 / 255, 1], + paleturquoise: [175 / 255, 238 / 255, 238 / 255, 1], + palevioletred: [219 / 255, 112 / 255, 147 / 255, 1], + papayawhip: [1, 239 / 255, 213 / 255, 1], + peachpuff: [1, 218 / 255, 185 / 255, 1], + peru: [205 / 255, 133 / 255, 63 / 255, 1], + pink: [1, 192 / 255, 203 / 255, 1], + plum: [221 / 255, 160 / 255, 221 / 255, 1], + powderblue: [176 / 255, 224 / 255, 230 / 255, 1], + rosybrown: [188 / 255, 143 / 255, 143 / 255, 1], + royalblue: [65 / 255, 105 / 255, 225 / 255, 1], + saddlebrown: [139 / 255, 69 / 255, 19 / 255, 1], + salmon: [250 / 255, 128 / 255, 114 / 255, 1], + sandybrown: [244 / 255, 164 / 255, 96 / 255, 1], + seagreen: [46 / 255, 139 / 255, 87 / 255, 1], + seashell: [1, 245 / 255, 238 / 255, 1], + sienna: [160 / 255, 82 / 255, 45 / 255, 1], + skyblue: [135 / 255, 206 / 255, 235 / 255, 1], + slateblue: [106 / 255, 90 / 255, 205 / 255, 1], + slategray: [112 / 255, 128 / 255, 144 / 255, 1], + slategrey: [112 / 255, 128 / 255, 144 / 255, 1], + snow: [1, 250 / 255, 250 / 255, 1], + springgreen: [0 / 255, 1, 127 / 255, 1], + steelblue: [70 / 255, 130 / 255, 180 / 255, 1], + tan: [210 / 255, 180 / 255, 140 / 255, 1], + thistle: [216 / 255, 191 / 255, 216 / 255, 1], + tomato: [1, 99 / 255, 71 / 255, 1], + turquoise: [64 / 255, 224 / 255, 208 / 255, 1], + violet: [238 / 255, 130 / 255, 238 / 255, 1], + wheat: [245 / 255, 222 / 255, 179 / 255, 1], + whitesmoke: [245 / 255, 245 / 255, 245 / 255, 1], + yellowgreen: [154 / 255, 205 / 255, 50 / 255, 1] + }; Seriously.plugin('testColorInput', { inputs: { @@ -800,51 +946,35 @@ e.color = 'rgb(10, 20, 30)'; val = e.color; - ok(compare(val, [10/255, 20/255, 30/255, 1]), 'Set color by rgb'); + ok(compare(val, [10 / 255, 20 / 255, 30 / 255, 1]), 'Set color by rgb'); e.color = 'rgba(30, 20, 10, 0.8)'; val = e.color; - ok(compare(val, [30/255, 20/255, 10/255, 0.8]), 'Set color by rgba'); + ok(compare(val, [30 / 255, 20 / 255, 10 / 255, 0.8]), 'Set color by rgba'); //todo: test rgb percentages //todo: test hsl/hsla e.color = '#123'; val = e.color; - ok(compare(val, [1/15, 2/15, 3/15, 1]), 'Set color by 3-character hex'); + ok(compare(val, [1 / 15, 2 / 15, 3 / 15, 1]), 'Set color by 3-character hex'); e.color = '#1234'; val = e.color; - ok(compare(val, [0x1/15, 0x2/15, 0x3/15, 0x4/15]), 'Set color by 4-character hex'); + ok(compare(val, [0x1 / 15, 0x2 / 15, 0x3 / 15, 0x4 / 15]), 'Set color by 4-character hex'); e.color = '#123456'; val = e.color; - ok(compare(val, [0x12/255, 0x34/255, 0x56/255, 1]), 'Set color by 6-character hex'); + ok(compare(val, [0x12 / 255, 0x34 / 255, 0x56 / 255, 1]), 'Set color by 6-character hex'); e.color = '#654321AA'; val = e.color; - ok(compare(val, [0x65/255, 0x43/255, 0x21/255, 0xAA/255]), 'Set color by 8-character hex'); + ok(compare(val, [0x65 / 255, 0x43 / 255, 0x21 / 255, 0xAA/255]), 'Set color by 8-character hex'); e.color = '#fffff'; val = e.color; ok(compare(val, [0, 0, 0, 0]), 'Set color by bad hex is transparent black'); - e.color = 'lightcyan'; - val = e.color; - ok(compare(val, [224/255, 1, 1, 1]), 'Set color by name (lightcyan)'); - - e.color = 'lightblue'; - val = e.color; - ok(compare(val, [173/255, 216/255, 230/255, 1]), 'Set color by name (lightblue)'); - - e.color = 'red'; - val = e.color; - ok(compare(val, [1, 0, 0, 1]), 'Set color by name (red)'); - - e.color = 'white'; - val = e.color; - ok(compare(val, [1, 1, 1, 1]), 'Set color by name (white)'); - e.color = 'transparent'; val = e.color; ok(compare(val, [0, 0, 0, 0]), 'Set color by name (transparent)'); @@ -853,6 +983,17 @@ val = e.color; ok(compare(val, [0, 0, 0, 0]), 'Set color by unknown name is transparent black'); + for (name in colorNames) { + if (colorNames.hasOwnProperty(name)) { + e.color = name; + val = e.color; + ok(compare(val, colorNames[name]), 'Set color by name (' + name + ')'); + if (!compare(val, colorNames[name])) { + console.log(name + ': ' + JSON.stringify(colorNames[name].map(function (val) { return val * 255; })) + ','); + } + } + } + e.color = 0.3; val = e.color; ok(compare(val, [0.3, 0.3, 0.3, 1]), 'Set color by single number'); From 352bf186b98af6358bee5588d5c3b8a9c558d347 Mon Sep 17 00:00:00 2001 From: Brian Chirls Date: Tue, 4 Mar 2014 11:20:25 -0500 Subject: [PATCH 08/45] Fixed checkSource logging test when offline --- test/seriously.unit.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/seriously.unit.js b/test/seriously.unit.js index cf9ed23..5665901 100644 --- a/test/seriously.unit.js +++ b/test/seriously.unit.js @@ -1541,6 +1541,10 @@ equal(s, 'Unable to access cross-domain image', 'Warning logged to console'); }; + Seriously.logger.warn = function (s) { + equal(s, 'Image not loaded', 'Warning logged to console'); + }; + ok(!Seriously.util.checkSource(img), 'Cross-origin image checks false'); canvas = document.createElement('canvas'); From 80b69e50afd9d01d0c32acc8aab507e7d02e2f57 Mon Sep 17 00:00:00 2001 From: Brian Chirls Date: Tue, 4 Mar 2014 11:35:10 -0500 Subject: [PATCH 09/45] Added unit tests for Target getters --- test/seriously.unit.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/seriously.unit.js b/test/seriously.unit.js index 5665901..c4b7cd3 100644 --- a/test/seriously.unit.js +++ b/test/seriously.unit.js @@ -1300,6 +1300,29 @@ seriously.destroy(); }); + module('Target'); + test('Canvas Target', function () { + var seriously, + canvas, + target; + + seriously = new Seriously(); + canvas = document.createElement('canvas'); + canvas.width = 17; + canvas.height = 19; + target = seriously.target(canvas); + + equal(target.width, 17, 'target.width'); + equal(target.height, 19, 'target.height'); + equal(target.original, canvas, 'target.original'); + equal(target.inputs.source.type, 'image', 'target.inputs.source'); + + target.width = 29; + ok(canvas.width === 29 && canvas.height === 19, 'target.width modifies canvas width, but not height'); + target.height = 31; + ok(canvas.width === 29 && canvas.height === 31, 'target.height modifies canvas height, but not width'); + }); + module('Destroy'); test('Destroy things', function() { var seriously, source, target, effect, transform, canvas; From 5161134d5dc43b7dbb39a7b099ab71b525641cf6 Mon Sep 17 00:00:00 2001 From: Brian Chirls Date: Tue, 4 Mar 2014 12:12:15 -0500 Subject: [PATCH 10/45] Throw proper Error objects, not strings - unit tests check messages on expected errors - no more double quotes anywhere --- seriously.js | 62 +++++++++++++++++++++--------------------- test/seriously.unit.js | 16 +++++------ 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/seriously.js b/seriously.js index 510ed78..c63a148 100644 --- a/seriously.js +++ b/seriously.js @@ -384,7 +384,7 @@ } if (typeof fn !== 'function') { - throw 'setTimeoutZero argument is not a function'; + throw new Error('setTimeoutZero argument is not a function'); } timeouts.push(fn); @@ -526,7 +526,7 @@ for (name in effect.inputs) { if (effect.inputs.hasOwnProperty(name)) { if (reserved.indexOf(name) >= 0 || Object.prototype[name]) { - throw 'Reserved effect input name: ' + name; + throw new Error('Reserved effect input name: ' + name); } input = effect.inputs[name]; @@ -607,7 +607,7 @@ status, useFloat = options === true ? options : (options && options.useFloat); - useFloat = false;//useFloat && !!gl.getExtension("OES_texture_float"); //useFloat is not ready! + useFloat = false;//useFloat && !!gl.getExtension('OES_texture_float'); //useFloat is not ready! if (useFloat) { this.type = gl.FLOAT; } else { @@ -657,23 +657,23 @@ status = gl.checkFramebufferStatus(gl.FRAMEBUFFER); if (status === gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT) { - throw('Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_ATTACHMENT'); + throw new Error('Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_ATTACHMENT'); } if (status === gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT) { - throw('Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT'); + throw new Error('Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT'); } if (status === gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS) { - throw('Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_DIMENSIONS'); + throw new Error('Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_DIMENSIONS'); } if (status === gl.FRAMEBUFFER_UNSUPPORTED) { - throw('Incomplete framebuffer: FRAMEBUFFER_UNSUPPORTED'); + throw new Error('Incomplete framebuffer: FRAMEBUFFER_UNSUPPORTED'); } if (status !== gl.FRAMEBUFFER_COMPLETE) { - throw('Incomplete framebuffer: ' + status); + throw new Error('Incomplete framebuffer: ' + status); } //clean up @@ -756,11 +756,11 @@ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { source = source.split(/[\n\r]/); for (i = 0; i < source.length; i++) { - source[i] = (i + 1) + ":\t" + source[i]; + source[i] = (i + 1) + ':\t' + source[i]; } source.unshift('Error compiling ' + (fragment ? 'fragment' : 'vertex') + ' shader:'); Seriously.logger.error(source.join('\n')); - throw 'Shader error: ' + gl.getShaderInfoLog(shader); + throw new Error('Shader error: ' + gl.getShaderInfoLog(shader)); } return shader; @@ -828,7 +828,7 @@ }; } - throw "Unknown shader uniform type: " + info.type; + throw new Error('Unknown shader uniform type: ' + info.type); } function makeShaderGetter(loc) { @@ -844,12 +844,12 @@ gl.attachShader(program, vertexShader); shaderError = gl.getShaderInfoLog(vertexShader); if (shaderError) { - programError += 'Vertex shader error: ' + shaderError + "\n"; + programError += 'Vertex shader error: ' + shaderError + '\n'; } gl.attachShader(program, fragmentShader); shaderError = gl.getShaderInfoLog(fragmentShader); if (shaderError) { - programError += 'Fragment shader error: ' + shaderError + "\n"; + programError += 'Fragment shader error: ' + shaderError + '\n'; } gl.linkProgram(program); @@ -858,7 +858,7 @@ gl.deleteProgram(program); gl.deleteShader(vertexShader); gl.deleteShader(fragmentShader); - throw 'Could not initialise shader: ' + programError; + throw new Error('Could not initialise shader: ' + programError); } gl.useProgram(program); @@ -1232,7 +1232,7 @@ node = nodesById[source.id]; if (!node) { - throw 'Cannot connect a foreign node'; + throw new Error('Cannot connect a foreign node'); } } else { if (typeof source === 'string' && isNaN(source)) { @@ -1359,7 +1359,7 @@ if (!gl) { //todo: is this the best approach? - throw 'Cannot read pixels until a canvas is connected'; + throw new Error('Cannot read pixels until a canvas is connected'); } //todo: check on x, y, width, height @@ -1375,7 +1375,7 @@ if (dest === undefined) { dest = new Uint8Array(width * height * 4); } else if (!dest instanceof Uint8Array) { - throw 'Incompatible array type'; + throw new Error('Incompatible array type'); } gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer.frameBuffer); //todo: are we sure about this? @@ -1671,7 +1671,7 @@ } } else { //todo: this is temporary. get rid of it. - throw 'Cannot overwrite Seriously.' + name; + throw new Error('Cannot overwrite Seriously.' + name); } } } @@ -2141,7 +2141,7 @@ } if (traceSources(value, this)) { - throw 'Attempt to make cyclical connection.'; + throw new Error('Attempt to make cyclical connection.'); } this.sources[name] = value; @@ -2202,7 +2202,7 @@ var that = this; if (reservedNames.indexOf(aliasName) >= 0) { - throw aliasName + ' is a reserved name and cannot be used as an alias.'; + throw new Error(aliasName + ' is a reserved name and cannot be used as an alias.'); } if (this.effect.inputs.hasOwnProperty(inputName)) { @@ -2901,7 +2901,7 @@ } } else if (!plugin && source instanceof WebGLTexture) { if (gl && !gl.isTexture(source)) { - throw 'Not a valid WebGL texture.'; + throw new Error('Not a valid WebGL texture.'); } //different defaults @@ -2913,7 +2913,7 @@ width = height; }/* else { //todo: guess based on dimensions of target canvas - //throw 'Must specify width and height when using a WebGL texture as a source'; + //throw new Error('Must specify width and height when using a WebGL texture as a source'); }*/ this.width = width; @@ -2952,7 +2952,7 @@ } if (!matchedType) { - throw 'Unknown source type'; + throw new Error('Unknown source type'); } this.source = source; @@ -3387,7 +3387,7 @@ } if (i >= elements.length) { - throw 'not a valid HTML element (must be image, video or canvas)'; + throw new Error('not a valid HTML element (must be image, video or canvas)'); } target = element; @@ -3405,7 +3405,7 @@ target = opts.context.canvas; } else { //todo: search all canvases for matching contexts? - throw 'Must provide a canvas with WebGLFramebuffer target'; + throw new Error('Must provide a canvas with WebGLFramebuffer target'); } } @@ -3494,7 +3494,7 @@ } if (!matchedType) { - throw 'Unknown target type'; + throw new Error('Unknown target type'); } this.target = target; @@ -4024,7 +4024,7 @@ } if (traceSources(newSource, this)) { - throw 'Attempt to make cyclical connection.'; + throw new Error('Attempt to make cyclical connection.'); } if (this.source) { @@ -4069,7 +4069,7 @@ def; if (reservedNames.indexOf(aliasName) >= 0) { - throw aliasName + ' is a reserved name and cannot be used as an alias.'; + throw new Error(aliasName + ' is a reserved name and cannot be used as an alias.'); } if (this.plugin.inputs.hasOwnProperty(inputName)) { @@ -4261,7 +4261,7 @@ */ this.effect = function (hook, options) { if (!seriousEffects[hook]) { - throw 'Unknown effect: ' + hook; + throw new Error('Unknown effect: ' + hook); } var effectNode = new EffectNode(hook, options); @@ -4283,12 +4283,12 @@ if (hook) { if (!seriousTransforms[hook]) { - throw 'Unknown transforms: ' + hook; + throw new Error('Unknown transforms: ' + hook); } } else { hook = options && options.defaultTransform || '2d'; if (!seriousTransforms[hook]) { - throw 'No transform specified'; + throw new Error('No transform specified'); } } diff --git a/test/seriously.unit.js b/test/seriously.unit.js index c4b7cd3..b5a212e 100644 --- a/test/seriously.unit.js +++ b/test/seriously.unit.js @@ -178,10 +178,10 @@ try { s.effect('removeme'); } catch (ee) { - error = true; + error = ee; } - ok(error, 'Plugin doesn\'t exist; using throws error'); + equal(error && error.message, 'Unknown effect: removeme', 'Plugin doesn\'t exist; throws error'); s.destroy(); }); @@ -226,19 +226,19 @@ } }); } catch (e) { - error1 = true; + error1 = e; } - ok(error1, 'Defining plugin throws error'); + equal(error1 && error1.message, 'Reserved effect input name: initialize', 'Defining plugin throws error'); try { s = new Seriously(); s.effect('badPlugin'); } catch (ee) { - error2 = true; + error2 = ee; } - ok(error2, 'Plugin doesn\'t exist; using throws error'); + equal(error2 && error2.message, 'Unknown effect: badPlugin', 'Plugin doesn\'t exist; using throws error'); s.destroy(); Seriously.removePlugin('badPlugin'); @@ -416,10 +416,10 @@ try { effect.source = effect; } catch (e) { - error = true; + error = e; } - ok(error, 'Setting effect source to itself throws an error'); + equal(error && error.message, 'Attempt to make cyclical connection.', 'Setting effect source to itself throws an error'); seriously.destroy(); Seriously.removePlugin('removeme'); From f253ef836bcc492b2c60cced74bb999d9e9faf9f Mon Sep 17 00:00:00 2001 From: Brian Chirls Date: Tue, 4 Mar 2014 12:46:49 -0500 Subject: [PATCH 11/45] Unit tests pass without WebGL --- test/seriously.unit.js | 189 ++++++++++++++++++++++++++--------------- 1 file changed, 120 insertions(+), 69 deletions(-) diff --git a/test/seriously.unit.js b/test/seriously.unit.js index b5a212e..69e9a0d 100644 --- a/test/seriously.unit.js +++ b/test/seriously.unit.js @@ -29,14 +29,12 @@ }; module('Core'); - test('Core', function () { + test('Core', 5, function () { var p, props = 0, newGlobals = [], skipIds = false, s; - expect(5); - ok(window.Seriously, 'Seriously exists'); equal(typeof window.Seriously, 'function', 'Seriously is a function'); @@ -155,11 +153,9 @@ * define plugin */ - test('Remove Plugin', function () { + test('Remove Plugin', 3, function () { var p, s, error, e, allEffects; - expect(3); - p = Seriously.plugin('removeme', {}); ok(p && p.title === 'removeme', 'First plugin loaded'); @@ -186,11 +182,9 @@ s.destroy(); }); - test('Define plugin with duplicate name', function () { + test('Define plugin with duplicate name', 4, function () { var p, allEffects; - expect(4); - Seriously.logger.warn = function (s) { equal(s, 'Effect [pluginDuplicate] already loaded', 'Warning logged to console'); }; @@ -212,11 +206,9 @@ Seriously.removePlugin('pluginDuplicate'); }); - test('Define plugin with reserved input name', function () { + test('Define plugin with reserved input name', 2, function () { var p, s, error1 = false, error2 = false; - expect(2); - try { p = Seriously.plugin('badPlugin', { inputs: { @@ -251,7 +243,7 @@ canvas, target; - expect(4); + expect(Seriously.incompatible() ? 2 : 4); Seriously.plugin('removeme', function (options) { var id = options.id; @@ -289,11 +281,9 @@ Seriously.removePlugin('removeme'); }); - asyncTest('Plugin loaded before Seriously', function () { + asyncTest('Plugin loaded before Seriously', 3, function () { var iframe; - expect(3); - iframe = document.createElement('iframe'); iframe.style.display = 'none'; iframe.addEventListener('load', function () { @@ -371,12 +361,10 @@ Seriously.removePlugin('removeme'); }); - test('Effect alias', function () { + test('Effect alias', 2, function () { var seriously, effect; - expect(2); - Seriously.plugin('removeme', { inputs: { input: { @@ -494,8 +482,10 @@ * checkSource on cross-origin image, dirty canvas */ - asyncTest('Source Types', function () { + asyncTest('Source Types', 17, function () { var seriously, source, target, + incompatible, + error, sourceCanvas, targetCanvas, img, ctx, pixels, imagedata, @@ -507,7 +497,7 @@ 0, 255, 0, 255 ]; - expect(11); + incompatible = Seriously.incompatible(); targetCanvas = document.createElement('canvas'); targetCanvas.width = 2; @@ -533,10 +523,16 @@ img = document.createElement('img'); img.addEventListener('load', function () { + var error; source = seriously.source(img); ok(source, 'Created source from image'); - pixels = source.readPixels(0, 0, 2, 2); - ok(pixels && compare(pixels, comparison), 'Image source rendered accurately.'); + try { + pixels = source.readPixels(0, 0, 2, 2); + } catch (e) { + error = e; + } + ok(incompatible ? error : !error, 'readPixels throws error iff incompatible'); + ok(incompatible || pixels && compare(pixels, comparison), 'Image source rendered accurately.'); source.destroy(); asyncDone = true; @@ -549,13 +545,25 @@ source = seriously.source(sourceCanvas); ok(source, 'Created source from canvas'); - pixels = source.readPixels(0, 0, 2, 2); - ok(pixels && compare(pixels, comparison), 'Canvas source rendered accurately.'); + error = false; + try { + pixels = source.readPixels(0, 0, 2, 2); + } catch (e) { + error = e; + } + ok(incompatible ? error : !error, 'readPixels throws error iff incompatible'); + ok(incompatible || pixels && compare(pixels, comparison), 'Canvas source rendered accurately.'); ctx.fillRect(0, 0, 2, 2); source.update(); - pixels = source.readPixels(0, 0, 2, 2); - ok(pixels && compare(pixels, [ //image is upside down + error = false; + try { + pixels = source.readPixels(0, 0, 2, 2); + } catch (e) { + error = e; + } + ok(incompatible ? error : !error, 'readPixels throws error iff incompatible'); + ok(incompatible || pixels && compare(pixels, [ //image is upside down 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, @@ -564,8 +572,14 @@ source = seriously.source(imagedata); ok(source, 'Created source from ImageData'); - pixels = source.readPixels(0, 0, 2, 2); - ok(pixels && compare(pixels, comparison), 'ImageData source rendered accurately.'); + error = false; + try { + pixels = source.readPixels(0, 0, 2, 2); + } catch (e) { + error = e; + } + ok(incompatible ? error : !error, 'readPixels throws error iff incompatible'); + ok(incompatible || pixels && compare(pixels, comparison), 'ImageData source rendered accurately.'); source.destroy(); source = seriously.source(new Uint8Array(comparison), { @@ -573,8 +587,14 @@ height: 2 }); ok(source, 'Created source from Typed Array'); - pixels = source.readPixels(0, 0, 2, 2); - ok(pixels && compare(pixels, comparison), 'Typed Array source rendered accurately.'); + error = false; + try { + pixels = source.readPixels(0, 0, 2, 2); + } catch (e) { + error = e; + } + ok(incompatible ? error : !error, 'readPixels throws error iff incompatible'); + ok(incompatible || pixels && compare(pixels, comparison), 'Typed Array source rendered accurately.'); source.destroy(); source = seriously.source(comparison, { @@ -582,8 +602,14 @@ height: 2 }); ok(source, 'Created source from Array'); - pixels = source.readPixels(0, 0, 2, 2); - ok(pixels && compare(pixels, comparison), 'Array source rendered accurately.'); + error = false; + try { + pixels = source.readPixels(0, 0, 2, 2); + } catch (e) { + error = e; + } + ok(incompatible ? error : !error, 'readPixels throws error iff incompatible'); + ok(incompatible || pixels && compare(pixels, comparison), 'Array source rendered accurately.'); source.destroy(); //todo: implement and test WebGLTexture source @@ -593,7 +619,6 @@ seriously.destroy(); start(); } - return; }); test('Create two Source objects on identical sources', function () { @@ -632,7 +657,7 @@ Seriously.removePlugin('test'); }); - test('Source Plugins', 7, function () { + test('Source Plugins', function () { var seriously, funcSource, objSource, @@ -642,6 +667,9 @@ canvas, target; + //render methods don't run without WebGL + expect(Seriously.incompatible() ? 5 : 7); + Seriously.plugin('temp', { inputs: { a: { @@ -724,9 +752,8 @@ * all different types * test html elements as inputs (with overwriting) */ - test('Number', function () { + test('Number', 6, function () { var s, e, val, input; - expect(6); Seriously.plugin('testNumberInput', { inputs: { @@ -1027,9 +1054,8 @@ Seriously.removePlugin('testColorInput'); }); - test('Enum', function() { + test('Enum', 4, function() { var s, e, val; - expect(4); Seriously.plugin('testEnumInput', { inputs: { @@ -1126,15 +1152,17 @@ }); module('Transform'); - test('Basic Transformations', function () { + test('Basic Transformations', 8, function () { var seriously, source, target, transform, flip, sourceCanvas, targetCanvas, ctx, - pixels = new Uint8Array(16); + pixels = new Uint8Array(16), + incompatible, + error; - expect(4); + incompatible = Seriously.incompatible(); targetCanvas = document.createElement('canvas'); targetCanvas.width = 2; @@ -1164,8 +1192,14 @@ target.source = transform; transform.rotation = -90; //90 degrees counter-clockwise - target.readPixels(0, 0, 2, 2, pixels); - ok(compare(pixels, [ + error = false; + try { + target.readPixels(0, 0, 2, 2, pixels); + } catch (e) { + error = e; + } + ok(incompatible ? error : !error, 'readPixels throws error iff incompatible'); + ok(incompatible || compare(pixels, [ 255, 0, 0, 255, 0, 0, 255, 255, 0, 255, 0, 255, @@ -1175,8 +1209,14 @@ target.source = flip; flip.direction = 'vertical'; - target.readPixels(0, 0, 2, 2, pixels); - ok(compare(pixels, [ //image is upside down + error = false; + try { + target.readPixels(0, 0, 2, 2, pixels); + } catch (e) { + error = e; + } + ok(incompatible ? error : !error, 'readPixels throws error iff incompatible'); + ok(incompatible || compare(pixels, [ //image is upside down 255, 0, 0, 255, 0, 255, 0, 255, 0, 0, 255, 255, @@ -1185,8 +1225,14 @@ target.source = flip; flip.direction = 'horizontal'; - target.readPixels(0, 0, 2, 2, pixels); - ok(compare(pixels, [ //image is upside down + error = false; + try { + target.readPixels(0, 0, 2, 2, pixels); + } catch (e) { + error = e; + } + ok(incompatible ? error : !error, 'readPixels throws error iff incompatible'); + ok(incompatible || compare(pixels, [ //image is upside down 255, 255, 255, 255, 0, 0, 255, 255, 0, 255, 0, 255, @@ -1196,8 +1242,14 @@ target.source = transform; transform.translate(1, 0); target.render(); - target.readPixels(0, 0, 2, 2, pixels); - ok(compare(pixels, [ //image is upside down + error = false; + try { + target.readPixels(0, 0, 2, 2, pixels); + } catch (e) { + error = e; + } + ok(incompatible ? error : !error, 'readPixels throws error iff incompatible'); + ok(incompatible || compare(pixels, [ //image is upside down 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, @@ -1208,15 +1260,13 @@ return; }); - test('Transform definition function', function () { + test('Transform definition function', 5, function () { var seriously, transform1, transform2, canvas, target; - expect(5); - Seriously.transform('removeme', function (options) { var id = options.id, prop = 0; @@ -1275,12 +1325,10 @@ Seriously.removePlugin('removeme'); }); - test('Transform alias', function () { + test('Transform alias', 5, function () { var seriously, transform; - expect(5); - seriously = new Seriously(); transform = seriously.transform('2d'); @@ -1324,11 +1372,9 @@ }); module('Destroy'); - test('Destroy things', function() { + test('Destroy things', 15, function() { var seriously, source, target, effect, transform, canvas; - expect(15); - Seriously.plugin('test', {}); canvas = document.createElement('canvas'); @@ -1373,12 +1419,10 @@ Seriously.removePlugin('test'); }); - test('Connect after nodes destroyed', function() { + test('Connect after nodes destroyed', 2, function() { var source, target, seriously, canvas; - expect(2); - seriously = new Seriously(); //create and destroy source twice source = seriously.source('#colorbars'); @@ -1517,11 +1561,9 @@ module('Utilities'); - asyncTest('setTimeoutZero', function() { + asyncTest('setTimeoutZero', 2, function() { var countdown = 2, startTime = Date.now(); - expect(2); - Seriously.util.setTimeoutZero(function() { countdown--; ok(countdown === 1, 'First callback runs first after ' + (Date.now() - startTime) + 'ms'); @@ -1610,7 +1652,7 @@ use require for loading plugins */ module('Effect Plugins'); - asyncTest('invert', 2, function () { + asyncTest('invert', 3, function () { require([ 'seriously', 'effects/seriously.invert', @@ -1621,7 +1663,11 @@ target, canvas, source, - pixels; + pixels, + error, + incompatible; + + incompatible = Seriously.incompatible(); seriously = new Seriously(); source = seriously.source([255, 128, 100, 200], { @@ -1640,8 +1686,13 @@ target.source = effect; effect.source = source; - pixels = target.readPixels(0, 0, 1, 1); - ok(pixels && compare(pixels, [0, 127, 155, 200]), 'Invert effect rendered accurately.'); + try { + pixels = target.readPixels(0, 0, 1, 1); + } catch (e) { + error = e; + } + ok(incompatible ? error : !error, 'readPixels throws error iff incompatible'); + ok(incompatible || pixels && compare(pixels, [0, 127, 155, 200]), 'Invert effect rendered accurately.'); seriously.destroy(); Seriously.removePlugin('invert'); From 1a6032b1fc127961c12df34b75f8e365131e2049 Mon Sep 17 00:00:00 2001 From: Brian Chirls Date: Wed, 5 Mar 2014 13:08:15 -0500 Subject: [PATCH 12/45] Resizing target node fires resize event - Unit test for resize events on source, effect, target nodes --- seriously.js | 2 + test/seriously.unit.js | 94 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/seriously.js b/seriously.js index c63a148..0bc2b46 100644 --- a/seriously.js +++ b/seriously.js @@ -3256,6 +3256,7 @@ me.target.width = value; me.setTransformDirty(); + me.emit('resize'); /* if (this.source && this.source.resize) { this.source.resize(value); @@ -3281,6 +3282,7 @@ me.target.height = value; me.setTransformDirty(); + me.emit('resize'); /* if (this.source && this.source.resize) { diff --git a/test/seriously.unit.js b/test/seriously.unit.js index 69e9a0d..7b83dc9 100644 --- a/test/seriously.unit.js +++ b/test/seriously.unit.js @@ -1557,6 +1557,100 @@ }); }); + asyncTest('resize event', 3, function () { + var seriously, + source, + deferred, + effect, + target, + + deferredResized = false, + effectResized = false, + targetResized = false; + + function proceed() { + if (deferredResized && effectResized && targetResized) { + seriously.destroy(); + Seriously.removeSource('size'); + start(); + } + } + + function fail() { + ok(false, 'Removed event listener should not run'); + } + + Seriously.source('immediate', function (source) { + this.width = source.width; + this.height = source.height; + return { + render: function () {} + }; + }, { + title: 'delete me' + }); + + Seriously.source('deferred', function (source) { + var that = this; + this.width = 1; + this.height = 1; + setTimeout(function () { + that.width = source.width; + that.height = source.height; + that.resize(); + }, 0); + + return { + render: function () {} + }; + }, { + title: 'delete me' + }); + + Seriously.plugin('test', { + title: 'Test Effect', + inputs: { + source: { + type: 'image' + } + } + }); + + seriously = new Seriously(); + source = seriously.source('size', { + width: 17, + height: 19 + }); + + effect = seriously.effect('test'); + effect.on('resize', function () { + effectResized = true; + ok(true, 'Effect resize event runs when connected to a source'); + proceed(); + }); + effect.source = source; + + target = seriously.target(document.createElement('canvas')); + target.on('resize', function () { + targetResized = true; + ok(true, 'Target resize event runs when dimensions changed explicitly'); + proceed(); + }); + target.width = 60; + + deferred = seriously.source('deferred', { + width: 17, + height: 19 + }); + deferred.on('resize', function () { + deferredResized = true; + ok(true, 'Source resize event runs when set by internal asynchronous code'); + proceed(); + }); + deferred.on('resize', fail); + deferred.off('resize', fail); + }); + module('Alias'); module('Utilities'); From a73602341dfd47c018bd45ce495ebf3abb94fa08 Mon Sep 17 00:00:00 2001 From: Brian Chirls Date: Wed, 5 Mar 2014 13:18:44 -0500 Subject: [PATCH 13/45] Added transform resize event to unit test --- test/seriously.unit.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/test/seriously.unit.js b/test/seriously.unit.js index 7b83dc9..82a4fde 100644 --- a/test/seriously.unit.js +++ b/test/seriously.unit.js @@ -1557,19 +1557,21 @@ }); }); - asyncTest('resize event', 3, function () { + asyncTest('resize event', 4, function () { var seriously, source, deferred, effect, + transform, target, deferredResized = false, effectResized = false, + transformResized = false, targetResized = false; function proceed() { - if (deferredResized && effectResized && targetResized) { + if (deferredResized && effectResized && transformResized && targetResized) { seriously.destroy(); Seriously.removeSource('size'); start(); @@ -1630,6 +1632,14 @@ }); effect.source = source; + transform = seriously.transform('2d'); + transform.on('resize', function () { + transformResized = true; + ok(true, 'Transform resize event runs when connected to a source'); + proceed(); + }); + transform.source = effect; + target = seriously.target(document.createElement('canvas')); target.on('resize', function () { targetResized = true; From ce49a42bdadde782a640ed5d07b616f611e1ab7d Mon Sep 17 00:00:00 2001 From: Brian Chirls Date: Sun, 9 Mar 2014 01:53:22 -0500 Subject: [PATCH 14/45] Extra thorough checking on Seriously as constructor without new --- seriously.js | 2 +- test/seriously.unit.js | 26 ++++++++++++++++++-------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/seriously.js b/seriously.js index 0bc2b46..34daa9b 100644 --- a/seriously.js +++ b/seriously.js @@ -932,7 +932,7 @@ function Seriously(options) { //if called without 'new', make a new object and return that - if (window === this || !(this instanceof Seriously)) { + if (window === this || !(this instanceof Seriously) || this.id !== undefined) { return new Seriously(options); } diff --git a/test/seriously.unit.js b/test/seriously.unit.js index 82a4fde..8d8e21f 100644 --- a/test/seriously.unit.js +++ b/test/seriously.unit.js @@ -29,11 +29,13 @@ }; module('Core'); - test('Core', 5, function () { + test('Core', 6, function () { var p, props = 0, newGlobals = [], skipIds = false, - s; + s1, + s2, + s3; ok(window.Seriously, 'Seriously exists'); @@ -67,15 +69,23 @@ newGlobals.join(', ') + ']'; equal(props, 1, p); - s = new Seriously(); - ok(s instanceof Seriously, 'Create Seriously instance with new'); - s.destroy(); + s1 = new Seriously(); + ok(s1 instanceof Seriously, 'Create Seriously instance with new'); /*jshint ignore:start*/ - s = Seriously(); + s2 = Seriously(); /*jshint ignore:end*/ - ok(s instanceof Seriously, 'Create Seriously instance without new'); - s.destroy(); + ok(s2 instanceof Seriously && s2 !== s1, 'Create Seriously instance without new'); + + //not sure why this would ever happen, but couldn't hurt to have the safety check + /*jshint ignore:start*/ + s3 = Seriously.bind(s2)(); + /*jshint ignore:end*/ + ok(s3 instanceof Seriously && s3 !== s2, 'Create Seriously instance without new, `this` bound to another instance'); + + s1.destroy(); + s2.destroy(); + s3.destroy(); }); test('Incompatible', 4, function () { From c1f8c5b5e35ca4edb2e225f85f66a8485d75c3e4 Mon Sep 17 00:00:00 2001 From: Brian Chirls Date: Sun, 16 Mar 2014 15:55:38 -0400 Subject: [PATCH 15/45] Update UMD wrapper for all modules - put the AMD definitions before commonjs - based on https://github.com/umdjs/umd/commit/992cc0d071b7ebcd7feaad2a5349bdbeab09a0fe --- effects/seriously.ascii.js | 8 ++++---- effects/seriously.bleach-bypass.js | 8 ++++---- effects/seriously.blend.js | 8 ++++---- effects/seriously.blur.js | 8 ++++---- effects/seriously.brightness-contrast.js | 8 ++++---- effects/seriously.channels.js | 8 ++++---- effects/seriously.checkerboard.js | 8 ++++---- effects/seriously.chroma.js | 8 ++++---- effects/seriously.color.js | 8 ++++---- effects/seriously.colorcomplements.js | 8 ++++---- effects/seriously.colorcube.js | 8 ++++---- effects/seriously.daltonize.js | 8 ++++---- effects/seriously.directionblur.js | 8 ++++---- effects/seriously.dither.js | 8 ++++---- effects/seriously.edge.js | 8 ++++---- effects/seriously.emboss.js | 8 ++++---- effects/seriously.exposure.js | 8 ++++---- effects/seriously.expression.js | 8 ++++---- effects/seriously.fader.js | 8 ++++---- effects/seriously.falsecolor.js | 8 ++++---- effects/seriously.filmgrain.js | 8 ++++---- effects/seriously.freeze.js | 8 ++++---- effects/seriously.hex.js | 8 ++++---- effects/seriously.highlights-shadows.js | 8 ++++---- effects/seriously.hue-saturation.js | 8 ++++---- effects/seriously.invert.js | 8 ++++---- effects/seriously.kaleidoscope.js | 8 ++++---- effects/seriously.layers.js | 8 ++++---- effects/seriously.linear-transfer.js | 8 ++++---- effects/seriously.lumakey.js | 8 ++++---- effects/seriously.nightvision.js | 8 ++++---- effects/seriously.noise.js | 8 ++++---- effects/seriously.polar.js | 8 ++++---- effects/seriously.repeat.js | 8 ++++---- effects/seriously.ripple.js | 8 ++++---- effects/seriously.scanlines.js | 8 ++++---- effects/seriously.select.js | 8 ++++---- effects/seriously.sepia.js | 8 ++++---- effects/seriously.simplex.js | 8 ++++---- effects/seriously.sketch.js | 8 ++++---- effects/seriously.split.js | 8 ++++---- effects/seriously.tone.js | 8 ++++---- effects/seriously.tvglitch.js | 8 ++++---- effects/seriously.vignette.js | 8 ++++---- effects/seriously.whitebalance.js | 8 ++++---- seriously.js | 12 ++++++------ sources/seriously.array.js | 8 ++++---- sources/seriously.camera.js | 8 ++++---- sources/seriously.imagedata.js | 8 ++++---- transforms/seriously.camerashake.js | 8 ++++---- transforms/seriously.transform3d.js | 8 ++++---- 51 files changed, 206 insertions(+), 206 deletions(-) diff --git a/effects/seriously.ascii.js b/effects/seriously.ascii.js index abb95fa..728ad57 100644 --- a/effects/seriously.ascii.js +++ b/effects/seriously.ascii.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.bleach-bypass.js b/effects/seriously.bleach-bypass.js index f771276..43ec499 100644 --- a/effects/seriously.bleach-bypass.js +++ b/effects/seriously.bleach-bypass.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.blend.js b/effects/seriously.blend.js index b81045d..117787e 100644 --- a/effects/seriously.blend.js +++ b/effects/seriously.blend.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.blur.js b/effects/seriously.blur.js index 17cfe0d..ed96ed2 100644 --- a/effects/seriously.blur.js +++ b/effects/seriously.blur.js @@ -11,12 +11,12 @@ http://v002.info/plugins/v002-blurs/ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.brightness-contrast.js b/effects/seriously.brightness-contrast.js index d1f99b4..a0fd18a 100644 --- a/effects/seriously.brightness-contrast.js +++ b/effects/seriously.brightness-contrast.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.channels.js b/effects/seriously.channels.js index b454b6d..46fe5d4 100644 --- a/effects/seriously.channels.js +++ b/effects/seriously.channels.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.checkerboard.js b/effects/seriously.checkerboard.js index 258c1b7..64cf214 100644 --- a/effects/seriously.checkerboard.js +++ b/effects/seriously.checkerboard.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.chroma.js b/effects/seriously.chroma.js index d206a30..4b9561f 100644 --- a/effects/seriously.chroma.js +++ b/effects/seriously.chroma.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.color.js b/effects/seriously.color.js index c0396ed..e4e0473 100644 --- a/effects/seriously.color.js +++ b/effects/seriously.color.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.colorcomplements.js b/effects/seriously.colorcomplements.js index 7de300d..3531915 100644 --- a/effects/seriously.colorcomplements.js +++ b/effects/seriously.colorcomplements.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.colorcube.js b/effects/seriously.colorcube.js index 82a3aff..97666f4 100644 --- a/effects/seriously.colorcube.js +++ b/effects/seriously.colorcube.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.daltonize.js b/effects/seriously.daltonize.js index d6d3ced..d1997ad 100644 --- a/effects/seriously.daltonize.js +++ b/effects/seriously.daltonize.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { var Seriously = root.Seriously; if (!Seriously) { diff --git a/effects/seriously.directionblur.js b/effects/seriously.directionblur.js index d9f94be..0205f9e 100644 --- a/effects/seriously.directionblur.js +++ b/effects/seriously.directionblur.js @@ -11,12 +11,12 @@ http://v002.info/plugins/v002-blurs/ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.dither.js b/effects/seriously.dither.js index 56e1cf3..b54e1b4 100644 --- a/effects/seriously.dither.js +++ b/effects/seriously.dither.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.edge.js b/effects/seriously.edge.js index 74a0e96..9dee8f0 100644 --- a/effects/seriously.edge.js +++ b/effects/seriously.edge.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.emboss.js b/effects/seriously.emboss.js index 36b5b1f..d2a2a55 100644 --- a/effects/seriously.emboss.js +++ b/effects/seriously.emboss.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.exposure.js b/effects/seriously.exposure.js index d189208..764fd18 100644 --- a/effects/seriously.exposure.js +++ b/effects/seriously.exposure.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.expression.js b/effects/seriously.expression.js index ebf6857..4cb94c4 100644 --- a/effects/seriously.expression.js +++ b/effects/seriously.expression.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.fader.js b/effects/seriously.fader.js index 47ecd6f..ad2e312 100644 --- a/effects/seriously.fader.js +++ b/effects/seriously.fader.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.falsecolor.js b/effects/seriously.falsecolor.js index a8a609f..bec0c53 100644 --- a/effects/seriously.falsecolor.js +++ b/effects/seriously.falsecolor.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.filmgrain.js b/effects/seriously.filmgrain.js index 1acaf83..a6e7132 100644 --- a/effects/seriously.filmgrain.js +++ b/effects/seriously.filmgrain.js @@ -13,12 +13,12 @@ Modified to preserve alpha (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.freeze.js b/effects/seriously.freeze.js index 76080b4..cc81342 100644 --- a/effects/seriously.freeze.js +++ b/effects/seriously.freeze.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.hex.js b/effects/seriously.hex.js index ff132e5..9aca193 100644 --- a/effects/seriously.hex.js +++ b/effects/seriously.hex.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.highlights-shadows.js b/effects/seriously.highlights-shadows.js index 5afa48c..a7de679 100644 --- a/effects/seriously.highlights-shadows.js +++ b/effects/seriously.highlights-shadows.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.hue-saturation.js b/effects/seriously.hue-saturation.js index d60c861..19e5c67 100644 --- a/effects/seriously.hue-saturation.js +++ b/effects/seriously.hue-saturation.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.invert.js b/effects/seriously.invert.js index e49818d..b4e8d5f 100644 --- a/effects/seriously.invert.js +++ b/effects/seriously.invert.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.kaleidoscope.js b/effects/seriously.kaleidoscope.js index 843fe1b..489a4de 100644 --- a/effects/seriously.kaleidoscope.js +++ b/effects/seriously.kaleidoscope.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.layers.js b/effects/seriously.layers.js index c1c7e77..6ea50e6 100644 --- a/effects/seriously.layers.js +++ b/effects/seriously.layers.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.linear-transfer.js b/effects/seriously.linear-transfer.js index d036ac8..5038de2 100644 --- a/effects/seriously.linear-transfer.js +++ b/effects/seriously.linear-transfer.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.lumakey.js b/effects/seriously.lumakey.js index 0e020be..bfcd3fe 100644 --- a/effects/seriously.lumakey.js +++ b/effects/seriously.lumakey.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.nightvision.js b/effects/seriously.nightvision.js index 1161c35..03a0cce 100644 --- a/effects/seriously.nightvision.js +++ b/effects/seriously.nightvision.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.noise.js b/effects/seriously.noise.js index 4957ac2..b1fef99 100644 --- a/effects/seriously.noise.js +++ b/effects/seriously.noise.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.polar.js b/effects/seriously.polar.js index eb4d10a..d539390 100644 --- a/effects/seriously.polar.js +++ b/effects/seriously.polar.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.repeat.js b/effects/seriously.repeat.js index 3796545..b9ad07b 100644 --- a/effects/seriously.repeat.js +++ b/effects/seriously.repeat.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.ripple.js b/effects/seriously.ripple.js index 65bf4e7..12df33b 100644 --- a/effects/seriously.ripple.js +++ b/effects/seriously.ripple.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.scanlines.js b/effects/seriously.scanlines.js index a02c984..c8d922d 100644 --- a/effects/seriously.scanlines.js +++ b/effects/seriously.scanlines.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.select.js b/effects/seriously.select.js index 847bb72..3a455a5 100644 --- a/effects/seriously.select.js +++ b/effects/seriously.select.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.sepia.js b/effects/seriously.sepia.js index 324057e..ee066c5 100644 --- a/effects/seriously.sepia.js +++ b/effects/seriously.sepia.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.simplex.js b/effects/seriously.simplex.js index 5ee4661..fea8544 100644 --- a/effects/seriously.simplex.js +++ b/effects/seriously.simplex.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.sketch.js b/effects/seriously.sketch.js index 223838f..571bd55 100644 --- a/effects/seriously.sketch.js +++ b/effects/seriously.sketch.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.split.js b/effects/seriously.split.js index 9e1d34d..8689402 100644 --- a/effects/seriously.split.js +++ b/effects/seriously.split.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.tone.js b/effects/seriously.tone.js index 6b4ad34..25d1252 100644 --- a/effects/seriously.tone.js +++ b/effects/seriously.tone.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.tvglitch.js b/effects/seriously.tvglitch.js index f061dac..9a1c20b 100644 --- a/effects/seriously.tvglitch.js +++ b/effects/seriously.tvglitch.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.vignette.js b/effects/seriously.vignette.js index 159d4fd..bd45e4e 100644 --- a/effects/seriously.vignette.js +++ b/effects/seriously.vignette.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/effects/seriously.whitebalance.js b/effects/seriously.whitebalance.js index 02c33e6..679378a 100644 --- a/effects/seriously.whitebalance.js +++ b/effects/seriously.whitebalance.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/seriously.js b/seriously.js index 34daa9b..360e246 100644 --- a/seriously.js +++ b/seriously.js @@ -2,12 +2,7 @@ /*global Float32Array, Uint8Array, Uint16Array, WebGLTexture, HTMLInputElement, HTMLSelectElement, HTMLElement, WebGLFramebuffer, HTMLCanvasElement, WebGLRenderingContext, define, module, exports */ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node. Does not work with strict CommonJS, but - // only CommonJS-like enviroments that support module.exports, - // like Node. - module.exports = factory(root); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define('seriously', function () { var Seriously = factory(root); @@ -16,6 +11,11 @@ } return Seriously; }); + } else if (typeof exports === 'object') { + // Node. Does not work with strict CommonJS, but + // only CommonJS-like enviroments that support module.exports, + // like Node. + module.exports = factory(root); } else if (typeof root.Seriously !== 'function') { // Browser globals root.Seriously = factory(root); diff --git a/sources/seriously.array.js b/sources/seriously.array.js index 13a670c..93fd12b 100644 --- a/sources/seriously.array.js +++ b/sources/seriously.array.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { /* todo: build out-of-order loading for sources and transforms or remove this diff --git a/sources/seriously.camera.js b/sources/seriously.camera.js index 8ac4a52..2a673a2 100644 --- a/sources/seriously.camera.js +++ b/sources/seriously.camera.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { /* todo: build out-of-order loading for sources and transforms or remove this diff --git a/sources/seriously.imagedata.js b/sources/seriously.imagedata.js index 2ffb5e6..f4507f3 100644 --- a/sources/seriously.imagedata.js +++ b/sources/seriously.imagedata.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { /* todo: build out-of-order loading for sources and transforms or remove this diff --git a/transforms/seriously.camerashake.js b/transforms/seriously.camerashake.js index e35fd52..6174b87 100644 --- a/transforms/seriously.camerashake.js +++ b/transforms/seriously.camerashake.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { if (!root.Seriously) { root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; diff --git a/transforms/seriously.transform3d.js b/transforms/seriously.transform3d.js index 6134130..8a55528 100644 --- a/transforms/seriously.transform3d.js +++ b/transforms/seriously.transform3d.js @@ -2,12 +2,12 @@ (function (root, factory) { 'use strict'; - if (typeof exports === 'object') { - // Node/CommonJS - factory(require('seriously')); - } else if (typeof define === 'function' && define.amd) { + if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); } else { /* todo: build out-of-order loading for sources and transforms or remove this From 2331cdf65a9084bccc2864e4e7478a92bb2177d4 Mon Sep 17 00:00:00 2001 From: Brian Chirls Date: Mon, 31 Mar 2014 22:24:09 -0400 Subject: [PATCH 16/45] Added 'none' scaling mode to reformat transform --- seriously.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/seriously.js b/seriously.js index 360e246..9fa762d 100644 --- a/seriously.js +++ b/seriously.js @@ -5568,7 +5568,10 @@ aspectOut = width / height; - if (mode === 'width' || mode === 'contain' && aspectOut <= aspectIn) { + if (mode === 'none') { + scaleX = sourceWidth / width; + scaleY = sourceHeight / height; + } else if (mode === 'width' || mode === 'contain' && aspectOut <= aspectIn) { scaleX = 1; scaleY = aspectOut / aspectIn; } else if (mode === 'height' || mode === 'contain' && aspectOut > aspectIn) { @@ -5701,7 +5704,8 @@ 'contain', 'distort', 'width', - 'height' + 'height', + 'none' ] } } From 7c456ddbd904092d9eb32010debd07876c72c279 Mon Sep 17 00:00:00 2001 From: Brian Chirls Date: Tue, 1 Apr 2014 00:25:32 -0400 Subject: [PATCH 17/45] Fix some blend modes that were causing shader to fail compilation --- effects/seriously.blend.js | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/effects/seriously.blend.js b/effects/seriously.blend.js index 117787e..fcb4134 100644 --- a/effects/seriously.blend.js +++ b/effects/seriously.blend.js @@ -18,14 +18,12 @@ 'use strict'; /* - todo: for prototype version, blend only handles two layers. this should handle multiple layers? todo: if transforms are used, do multiple passes and enable depth testing? todo: for now, only supporting float blend modes. Add complex ones todo: apply proper credit and license - ** Romain Dura | Romz - ** Blog: http://blog.mouaif.org - ** Post: http://blog.mouaif.org/?p=94 + Blend mode shader by Romain Dura + http://mouaif.wordpress.com/2009/01/05/photoshop-math-with-glsl-shaders/ */ var modes = { @@ -279,17 +277,21 @@ '#define BlendGlow(base, blend) BlendReflect(blend, base)\n' + '#define BlendPhoenix(base, blend) (min(base, blend) - max(base, blend) + vec3(1.0))\n' + //'#define BlendOpacity(base, blend, F, O) (F(base, blend) * O + blend * (1.0 - O))\n' + - '#define BlendOpacity(base, blend, BlendFn, Opacity, Alpha) ((BlendFn(base.rgb * blend.a * Opacity, blend.rgb * blend.a * Opacity) + base.rgb * base.a * (1.0 - blend.a * Opacity)) / Alpha)\n' + - '\n' + + //'#define BlendOpacity(base, blend, BlendFn, Opacity, Alpha) ((BlendFn(base.rgb * blend.a * Opacity, blend.rgb * blend.a * Opacity) + base.rgb * base.a * (1.0 - blend.a * Opacity)) / Alpha)\n' + + 'varying vec2 vTexCoord;\n' + 'varying vec4 vPosition;\n' + - '\n' + + 'uniform sampler2D top;\n' + - '\n' + 'uniform sampler2D bottom;\n' + - '\n' + 'uniform float opacity;\n' + - '\n' + + + 'vec3 BlendOpacity(vec4 base, vec4 blend, float opacity, float alpha) {\n' + + ' vec3 baseRGB = base.rgb * blend.a * opacity;\n' + + ' vec3 blendRGB = blend.rgb * blend.a * opacity;\n' + + ' return (BlendFunction(baseRGB, blendRGB) + base.rgb * base.a * (1.0 - blend.a * opacity)) / alpha;\n' + + '}\n' + + 'void main(void) {\n' + ' vec3 color;\n' + ' vec4 topPixel = texture2D(top, vTexCoord);\n' + @@ -299,7 +301,7 @@ ' if (alpha == 0.0) {\n' + ' color = vec3(0.0);\n' + ' } else {\n' + - ' color = BlendOpacity(bottomPixel, topPixel, BlendFunction, opacity, alpha);\n' + + ' color = BlendOpacity(bottomPixel, topPixel, opacity, alpha);\n' + ' }\n' + ' gl_FragColor = vec4(color, alpha);\n' + '}\n'; From d77727fbfba6dba05595860209aa08c7f2eb2dfb Mon Sep 17 00:00:00 2001 From: Brian Chirls Date: Tue, 1 Apr 2014 00:28:09 -0400 Subject: [PATCH 18/45] Accumulator Effect #23 - Accumulator example - "Drunk" demo --- effects/seriously.accumulator.js | 219 +++++++++++++++++++++++++++++++ examples/accumulator/index.html | 99 ++++++++++++++ examples/demo/drunk.html | 90 +++++++++++++ examples/index.html | 2 + 4 files changed, 410 insertions(+) create mode 100644 effects/seriously.accumulator.js create mode 100644 examples/accumulator/index.html create mode 100644 examples/demo/drunk.html diff --git a/effects/seriously.accumulator.js b/effects/seriously.accumulator.js new file mode 100644 index 0000000..b9fa32f --- /dev/null +++ b/effects/seriously.accumulator.js @@ -0,0 +1,219 @@ +/* global define, require */ +(function (root, factory) { + 'use strict'; + + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); + } else { + if (!root.Seriously) { + root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; + } + factory(root.Seriously); + } +}(this, function (Seriously, undefined) { + 'use strict'; + + /* + Blend mode shader by Romain Dura + http://mouaif.wordpress.com/2009/01/05/photoshop-math-with-glsl-shaders/ + */ + + Seriously.plugin('accumulator', function () { + var modes = { + normal: 'BlendNormal', + lighten: 'BlendLighten', + darken: 'BlendDarken', + multiply: 'BlendMultiply', + average: 'BlendAverage', + add: 'BlendAdd', + subtract: 'BlendSubtract', + difference: 'BlendDifference', + negation: 'BlendNegation', + exclusion: 'BlendExclusion', + screen: 'BlendScreen', + overlay: 'BlendOverlay', + softlight: 'BlendSoftLight', + hardlight: 'BlendHardLight', + colordodge: 'BlendColorDodge', + colorburn: 'BlendColorBurn', + lineardodge: 'BlendLinearDodge', + linearburn: 'BlendLinearBurn', + linearlight: 'BlendLinearLight', + vividlight: 'BlendVividLight', + pinlight: 'BlendPinLight', + hardmix: 'BlendHardMix', + reflect: 'BlendReflect', + glow: 'BlendGlow', + phoenix: 'BlendPhoenix' + }, + drawOpts = { + clear: false + }; + + return { + initialize: function (initialize) { + initialize(); + this.uniforms.previous = this.frameBuffer.texture; + }, + shader: function (inputs, shaderSource) { + var mode = inputs.blendMode || 'normal'; + mode = mode.toLowerCase(); + mode = modes[mode] || 'BlendNormal'; + + shaderSource.fragment = [ + '#define BlendFunction ' + mode, + '#ifdef GL_ES', + 'precision mediump float;', + '#endif', + + '#define BlendLinearDodgef BlendAddf', + '#define BlendLinearBurnf BlendSubtractf', + '#define BlendAddf(base, blend) min(base + blend, 1.0)', + '#define BlendSubtractf(base, blend) max(base + blend - 1.0, 0.0)', + '#define BlendLightenf(base, blend) max(blend, base)', + '#define BlendDarkenf(base, blend) min(blend, base)', + '#define BlendLinearLightf(base, blend) (blend < 0.5 ? BlendLinearBurnf(base, (2.0 * blend)) : BlendLinearDodgef(base, (2.0 * (blend - 0.5))))', + '#define BlendScreenf(base, blend) (1.0 - ((1.0 - base) * (1.0 - blend)))', + '#define BlendOverlayf(base, blend) (base < 0.5 ? (2.0 * base * blend) : (1.0 - 2.0 * (1.0 - base) * (1.0 - blend)))', + '#define BlendSoftLightf(base, blend) ((blend < 0.5) ? (2.0 * base * blend + base * base * (1.0 - 2.0 * blend)) : (sqrt(base) * (2.0 * blend - 1.0) + 2.0 * base * (1.0 - blend)))', + '#define BlendColorDodgef(base, blend) ((blend == 1.0) ? blend : min(base / (1.0 - blend), 1.0))', + '#define BlendColorBurnf(base, blend) ((blend == 0.0) ? blend : max((1.0 - ((1.0 - base) / blend)), 0.0))', + '#define BlendVividLightf(base, blend) ((blend < 0.5) ? BlendColorBurnf(base, (2.0 * blend)) : BlendColorDodgef(base, (2.0 * (blend - 0.5))))', + '#define BlendPinLightf(base, blend) ((blend < 0.5) ? BlendDarkenf(base, (2.0 * blend)) : BlendLightenf(base, (2.0 *(blend - 0.5))))', + '#define BlendHardMixf(base, blend) ((BlendVividLightf(base, blend) < 0.5) ? 0.0 : 1.0)', + '#define BlendReflectf(base, blend) ((blend == 1.0) ? blend : min(base * base / (1.0 - blend), 1.0))', + /* + ** Vector3 blending modes + */ + + // Component wise blending + '#define Blend(base, blend, funcf) vec3(funcf(base.r, blend.r), funcf(base.g, blend.g), funcf(base.b, blend.b))', + '#define BlendNormal(base, blend) (blend)', + '#define BlendLighten BlendLightenf', + '#define BlendDarken BlendDarkenf', + '#define BlendMultiply(base, blend) (base * blend)', + '#define BlendAverage(base, blend) ((base + blend) / 2.0)', + '#define BlendAdd(base, blend) min(base + blend, vec3(1.0))', + '#define BlendSubtract(base, blend) max(base + blend - vec3(1.0), vec3(0.0))', + '#define BlendDifference(base, blend) abs(base - blend)', + '#define BlendNegation(base, blend) (vec3(1.0) - abs(vec3(1.0) - base - blend))', + '#define BlendExclusion(base, blend) (base + blend - 2.0 * base * blend)', + '#define BlendScreen(base, blend) Blend(base, blend, BlendScreenf)', + '#define BlendOverlay(base, blend) Blend(base, blend, BlendOverlayf)', + '#define BlendSoftLight(base, blend) Blend(base, blend, BlendSoftLightf)', + '#define BlendHardLight(base, blend) BlendOverlay(blend, base)', + '#define BlendColorDodge(base, blend) Blend(base, blend, BlendColorDodgef)', + '#define BlendColorBurn(base, blend) Blend(base, blend, BlendColorBurnf)', + '#define BlendLinearDodge BlendAdd', + '#define BlendLinearBurn BlendSubtract', + // Linear Light is another contrast-increasing mode + // If the blend color is darker than midgray, Linear Light darkens the image by decreasing the brightness. If the blend color is lighter than midgray, the result is a brighter image due to increased brightness. + '#define BlendLinearLight(base, blend) Blend(base, blend, BlendLinearLightf)', + '#define BlendVividLight(base, blend) Blend(base, blend, BlendVividLightf)', + '#define BlendPinLight(base, blend) Blend(base, blend, BlendPinLightf)', + '#define BlendHardMix(base, blend) Blend(base, blend, BlendHardMixf)', + '#define BlendReflect(base, blend) Blend(base, blend, BlendReflectf)', + '#define BlendGlow(base, blend) BlendReflect(blend, base)', + '#define BlendPhoenix(base, blend) (min(base, blend) - max(base, blend) + vec3(1.0))', + //'#define BlendOpacity(base, blend, F, O) (F(base, blend) * O + blend * (1.0 - O))', + //'#define BlendOpacity(base, blend, BlendFn, Opacity, Alpha) ((BlendFn(base.rgb * blend.a * Opacity, blend.rgb * blend.a * Opacity) + base.rgb * base.a * (1.0 - blend.a * Opacity)) / Alpha)', + + 'varying vec2 vTexCoord;', + 'varying vec4 vPosition;', + + 'uniform sampler2D source;', + 'uniform sampler2D previous;', + + 'uniform float opacity;', + + 'vec3 BlendOpacity(vec4 base, vec4 blend, float opacity, float alpha) {', + ' vec3 baseRGB = base.rgb * blend.a * opacity;', + ' vec3 blendRGB = blend.rgb * blend.a * opacity;', + ' return (BlendFunction(baseRGB, blendRGB) + base.rgb * base.a * (1.0 - blend.a * opacity)) / alpha;', + '}', + + 'void main(void) {', + ' vec3 color;', + ' vec4 topPixel = texture2D(source, vTexCoord);', + ' vec4 bottomPixel = texture2D(previous, vTexCoord);', + + ' float alpha = topPixel.a + bottomPixel.a * (1.0 - topPixel.a);', + ' if (alpha == 0.0) {', + ' color = vec3(0.0);', + ' } else {', + ' color = BlendOpacity(bottomPixel, topPixel, opacity, alpha);', + ' }', + ' gl_FragColor = vec4(color, alpha);', + '}' + ].join('\n'); + + return shaderSource; + }, + draw: function (shader, model, uniforms, frameBuffer, draw) { + if (this.inputs.clear) { + draw(this.baseShader, model, uniforms, frameBuffer, null); + return; + } + + draw(shader, model, uniforms, frameBuffer, null, drawOpts); + }, + inputs: { + source: { + type: 'image', + uniform: 'source' + }, + clear: { + type: 'boolean', + defaultValue: false + }, + opacity: { + type: 'number', + uniform: 'opacity', + defaultValue: 1, + min: 0, + max: 1 + }, + blendMode: { + type: 'enum', + shaderDirty: true, + defaultValue: 'normal', + options: [ + ['normal', 'Normal'], + ['lighten', 'Lighten'], + ['darken', 'Darken'], + ['multiply', 'Multiply'], + ['average', 'Average'], + ['add', 'Add'], + ['substract', 'Substract'], + ['difference', 'Difference'], + ['negation', 'Negation'], + ['exclusion', 'Exclusion'], + ['screen', 'Screen'], + ['overlay', 'Overlay'], + ['softlight', 'Soft Light'], + ['hardlight', 'Hard Light'], + ['colordodge', 'Color Dodge'], + ['colorburn', 'Color Burn'], + ['lineardodge', 'Linear Dodge'], + ['linearburn', 'Linear Burn'], + ['linearlight', 'Linear Light'], + ['vividlight', 'Vivid Light'], + ['pinlight', 'Pin Light'], + ['hardmix', 'Hard Mix'], + ['reflect', 'Reflect'], + ['glow', 'Glow'], + ['phoenix', 'Phoenix'] + ] + } + } + }; + }, { + inPlace: false, + title: 'Accumulator', + description: 'Draw on top of previous frame' + }); +})); diff --git a/examples/accumulator/index.html b/examples/accumulator/index.html new file mode 100644 index 0000000..ed17ee8 --- /dev/null +++ b/examples/accumulator/index.html @@ -0,0 +1,99 @@ + + + + Shake Them Heads + + + + + + + + + diff --git a/examples/demo/drunk.html b/examples/demo/drunk.html new file mode 100644 index 0000000..98a43aa --- /dev/null +++ b/examples/demo/drunk.html @@ -0,0 +1,90 @@ + + + + Shake Them Heads + + + + + + + + diff --git a/examples/index.html b/examples/index.html index 80db84f..4747d71 100644 --- a/examples/index.html +++ b/examples/index.html @@ -7,6 +7,7 @@
  • Loading with AMD/Require.js
  • Animation with seriously.go()
  • +
  • Accumulator
  • Blur
    • Gaussian Blur
    • @@ -24,6 +25,7 @@
    • Channel Mapping
    • Linear Color Transfer
    • Select
    • +
    • Drunk
    • Transforms
      • Reformat
      • From d0a2d151cf8a8f02c83cf12d81d673558e965a7e Mon Sep 17 00:00:00 2001 From: Brian Chirls Date: Tue, 1 Apr 2014 23:40:45 -0400 Subject: [PATCH 19/45] Return accumulator inputs metadata earlier; add to index.html --- effects/seriously.accumulator.js | 100 +++++++++++++++---------------- index.html | 1 + 2 files changed, 51 insertions(+), 50 deletions(-) diff --git a/effects/seriously.accumulator.js b/effects/seriously.accumulator.js index b9fa32f..5485c4b 100644 --- a/effects/seriously.accumulator.js +++ b/effects/seriously.accumulator.js @@ -160,60 +160,60 @@ } draw(shader, model, uniforms, frameBuffer, null, drawOpts); - }, - inputs: { - source: { - type: 'image', - uniform: 'source' - }, - clear: { - type: 'boolean', - defaultValue: false - }, - opacity: { - type: 'number', - uniform: 'opacity', - defaultValue: 1, - min: 0, - max: 1 - }, - blendMode: { - type: 'enum', - shaderDirty: true, - defaultValue: 'normal', - options: [ - ['normal', 'Normal'], - ['lighten', 'Lighten'], - ['darken', 'Darken'], - ['multiply', 'Multiply'], - ['average', 'Average'], - ['add', 'Add'], - ['substract', 'Substract'], - ['difference', 'Difference'], - ['negation', 'Negation'], - ['exclusion', 'Exclusion'], - ['screen', 'Screen'], - ['overlay', 'Overlay'], - ['softlight', 'Soft Light'], - ['hardlight', 'Hard Light'], - ['colordodge', 'Color Dodge'], - ['colorburn', 'Color Burn'], - ['lineardodge', 'Linear Dodge'], - ['linearburn', 'Linear Burn'], - ['linearlight', 'Linear Light'], - ['vividlight', 'Vivid Light'], - ['pinlight', 'Pin Light'], - ['hardmix', 'Hard Mix'], - ['reflect', 'Reflect'], - ['glow', 'Glow'], - ['phoenix', 'Phoenix'] - ] - } } }; }, { inPlace: false, title: 'Accumulator', - description: 'Draw on top of previous frame' + description: 'Draw on top of previous frame', + inputs: { + source: { + type: 'image', + uniform: 'source' + }, + clear: { + type: 'boolean', + defaultValue: false + }, + opacity: { + type: 'number', + uniform: 'opacity', + defaultValue: 1, + min: 0, + max: 1 + }, + blendMode: { + type: 'enum', + shaderDirty: true, + defaultValue: 'normal', + options: [ + ['normal', 'Normal'], + ['lighten', 'Lighten'], + ['darken', 'Darken'], + ['multiply', 'Multiply'], + ['average', 'Average'], + ['add', 'Add'], + ['substract', 'Substract'], + ['difference', 'Difference'], + ['negation', 'Negation'], + ['exclusion', 'Exclusion'], + ['screen', 'Screen'], + ['overlay', 'Overlay'], + ['softlight', 'Soft Light'], + ['hardlight', 'Hard Light'], + ['colordodge', 'Color Dodge'], + ['colorburn', 'Color Burn'], + ['lineardodge', 'Linear Dodge'], + ['linearburn', 'Linear Burn'], + ['linearlight', 'Linear Light'], + ['vividlight', 'Vivid Light'], + ['pinlight', 'Pin Light'], + ['hardmix', 'Hard Mix'], + ['reflect', 'Reflect'], + ['glow', 'Glow'], + ['phoenix', 'Phoenix'] + ] + } + } }); })); diff --git a/index.html b/index.html index 399dd45..3b1537d 100644 --- a/index.html +++ b/index.html @@ -6,6 +6,7 @@ + From 931e7ada6572991f9490b7552b1ef93f46cee9bf Mon Sep 17 00:00:00 2001 From: Brian Chirls Date: Tue, 1 Apr 2014 23:52:37 -0400 Subject: [PATCH 20/45] Make drunk demo more drunk --- examples/demo/drunk.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/demo/drunk.html b/examples/demo/drunk.html index 98a43aa..f5fac5f 100644 --- a/examples/demo/drunk.html +++ b/examples/demo/drunk.html @@ -73,7 +73,7 @@ shake.amplitudeX = 16; shake.amplitudeY = 8; - accumulator.opacity = 0.15; + accumulator.opacity = 0.05; scale.source = seriously.source('camera'); shake.source = scale; From a081258c48eb8f24a93b8b681020231d081a2824 Mon Sep 17 00:00:00 2001 From: Brian Chirls Date: Tue, 1 Apr 2014 23:53:04 -0400 Subject: [PATCH 21/45] Added Throttle effect for capping frame rate --- effects/seriously.throttle.js | 55 +++++++++++++++++++++++++++++++++++ index.html | 1 + 2 files changed, 56 insertions(+) create mode 100644 effects/seriously.throttle.js diff --git a/effects/seriously.throttle.js b/effects/seriously.throttle.js new file mode 100644 index 0000000..c849571 --- /dev/null +++ b/effects/seriously.throttle.js @@ -0,0 +1,55 @@ +/* global define, require */ +(function (root, factory) { + 'use strict'; + + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['seriously'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('seriously')); + } else { + if (!root.Seriously) { + root.Seriously = { plugin: function (name, opt) { this[name] = opt; } }; + } + factory(root.Seriously); + } +}(this, function (Seriously, undefined) { + 'use strict'; + + Seriously.plugin('throttle', function () { + var lastDrawTime = 0; + return { + draw: function (shader, model, uniforms, frameBuffer, draw) { + if (this.inputs.frameRate && Date.now() - lastDrawTime >= 1000 / this.inputs.frameRate) { + draw(shader, model, uniforms, frameBuffer); + lastDrawTime = Date.now(); + } + }, + requires: function (sourceName, inputs) { + if (inputs.frameRate && Date.now() - lastDrawTime >= 1000 / inputs.frameRate) { + return true; + } + + return false; + } + }; + }, { + inPlace: true, + commonShader: true, + title: 'Throttle', + description: 'Throttle frame rate', + inputs: { + source: { + type: 'image', + uniform: 'source' + }, + frameRate: { + type: 'number', + uniform: 'opacity', + defaultValue: 15, + min: 0 + } + } + }); +})); diff --git a/index.html b/index.html index 3b1537d..f64df78 100644 --- a/index.html +++ b/index.html @@ -38,6 +38,7 @@ + From 96d454be463772217b81ad40f32750524d3e15b9 Mon Sep 17 00:00:00 2001 From: Brian Chirls Date: Wed, 2 Apr 2014 16:06:09 -0400 Subject: [PATCH 22/45] Avoid read/write to same texture in Accumulator effect. #23 --- effects/seriously.accumulator.js | 37 +++++++++++++++++++++++++++----- examples/accumulator/index.html | 2 +- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/effects/seriously.accumulator.js b/effects/seriously.accumulator.js index 5485c4b..8ed45c1 100644 --- a/effects/seriously.accumulator.js +++ b/effects/seriously.accumulator.js @@ -52,12 +52,17 @@ }, drawOpts = { clear: false - }; + }, + frameBuffers, + fbIndex = 0; return { - initialize: function (initialize) { + initialize: function (initialize, gl) { initialize(); - this.uniforms.previous = this.frameBuffer.texture; + frameBuffers = [ + this.frameBuffer, + new Seriously.util.FrameBuffer(gl, this.width, this.height) + ]; }, shader: function (inputs, shaderSource) { var mode = inputs.blendMode || 'normal'; @@ -153,13 +158,35 @@ return shaderSource; }, + resize: function () { + if (frameBuffers) { + frameBuffers[0].resize(this.width, this.height); + frameBuffers[1].resize(this.width, this.height); + } + }, draw: function (shader, model, uniforms, frameBuffer, draw) { + var fb; + + // ping-pong textures + this.uniforms.previous = this.frameBuffer.texture; + fbIndex = (fbIndex + 1) % 2; + fb = frameBuffers[fbIndex]; + this.frameBuffer = fb; + this.texture = fb.texture; + if (this.inputs.clear) { - draw(this.baseShader, model, uniforms, frameBuffer, null); + draw(this.baseShader, model, uniforms, fb.frameBuffer, null); return; } - draw(shader, model, uniforms, frameBuffer, null, drawOpts); + draw(shader, model, uniforms, fb.frameBuffer, null, drawOpts); + }, + destroy: function () { + if (frameBuffers) { + frameBuffers[0].destroy(); + frameBuffers[1].destroy(); + frameBuffers.length = 0; + } } }; }, { diff --git a/examples/accumulator/index.html b/examples/accumulator/index.html index ed17ee8..f219599 100644 --- a/examples/accumulator/index.html +++ b/examples/accumulator/index.html @@ -1,7 +1,7 @@ - Shake Them Heads + Seriously.js Accumulator Effect Example +
        +
        + + +
        +
        +
        + + + diff --git a/examples/images/monochromebars.png b/examples/images/monochromebars.png new file mode 100644 index 0000000000000000000000000000000000000000..1600347301faa859ee11200b4fd9cc4e188de59c GIT binary patch literal 7880 zcmeHLi9eM4_kYN~D$jgf6^sgyMmqKrg~a3e*8Y>~3o zwPnv%LLpg_?+m(Ee%;?6aJ%z5&+GNfd7t;^e9n2!=W{;KbIDL&i<3==4FCX69c@ix z0ALOQ07ig?ssO@9c_sjWO%sPg8S0==AVVU-3FnRl0Bz12i9V)$9RhXzuiPPpClkTg z_hm(lnX+ZtSH;<0PSNXHwPOVyC~7i-BQCO-@0YND<|46OD#Mb6h5sWREBH9aG2We5 zUp*K8^7YVx#TETNQ6IJ0z^`dOV|~j_y8sEgz4REa9N@@fLvYO8SEuK-2cVzJ04B|l zZ3=*A@so@ei3*pHyd$;>2m$Z-&$jIJ17Bo9P5^n<4CfHng5R%BqvE8t>jEKFt-v9X z!%30Ey$x22+vCs_&1-4#k`99V9AGJ+hHSY0a?NP)64~Bh*KEOgl{Z?64=*M)UO6q$ zuzNO>oDj#85IMu}jhsM8&!LDl@~3}e!ul&vuCN0az^}!~cw|Gngh@?noO{9;{gL#{ zz*LPZf9qHL>;_qsG-qqS#)xKS3b?i%QDy8iEF2}N!;m`1)<}~%FG)Q++C**{_43HyP zs9;_0B6*0;#hN?hLoX!dyBaXePUkYY{2@TFz)vShTT|BDd~tCxkzTFC*u15AA{a@Y z{}!MTUa+ESR0J9l?maFc^tk z)R?;~NNQlHk}K@hNIL?q=Y=y?RZM)U;8;G$yelZhjnBnfluq@5y~>ZMigB^s=$5KdEAuIv9GIztC#`!+|H(*nJ_H;5Ip6@)reWgs6N(fmGs*$ zGn3Mp3PVJoO#ILImFO%6Sjp-^LRp#q8KSxw0!y88QnU z*`dVL{Y=M`%Z9e%&o-1DpUSo?1MF;dBl z0hN`Wa!+~m!vv~z2Q_>VHjEurS_9?_!sMOhtlX8&1Ck6N$8(|MAbu8h%sz}ZeSE~l zxU1SQ<4bSAdfLow(KcEaF0&5HFooa5Bnz@fNr?jp(dt_1=Q%YA_Svv-Xl}CXEALlO zr|q-6y0xx$jSplykGKmfaHht}RGHgPe`mN zclQg6Ul-@#dCr2+WXzyzJui4{m^X>%0_2}&sA{k!6Nv|BSd+JuaE-n&E! zB~j+$(c%;FH(u~M()r0hi6AGCFR7q|bd55SjXM)GBN7U(5ib)HiQzNx$FqctRqwHy zvU(#Ph5Dy0U0ymCBkn9IAW?V4TFhc!$3aEVSDQ2m0%%&SLObXlIqTc$MYTm%#*DK! z>8(R=Jutp`Z17xFdQ}2guk{!V4YSTS{rq4ETYKQRuNX?qRxHi0rgM0V9GV^dmweCJiW#bC`M-M@LwLV4Yx* z;Iyfn*;CVngQ=z|rc9={&BpHfXU~{Lnx&c%vdc{zvKO|wImE7{S^m<#$LF{aKH`hPS<<;6{rdmoiFmT=E$ z`%9OZma&!Tm+1t0tQfA0EJZK*a9(7R4kLx_Vd`aiec{-J{0qA|-f~a`?+Gyq$;i9P zl@QSK^Uzc7Hg4o<2IngH3%M>2Vk4h|H&jnC7dD9qYZPu|a4KzFYRn&P8r7IRF{{oV zaX#s2+RWG(A;C+Vsx#qp*qPcr=9_CEsOm|6iF?8iTdjDXtxBX3` zo3%qgb&Ttnb5TQH@6`FSYpVT0u`3?TDX6>EOyT-Tna@%5Vk>rx@=w zMtlaBR$0t^jBI4NV!v-WDabjBjJ8LkUXgMP-2FZpUN`HBD8B#s!{@UL^9*DSv_@dn z8~T36w*pb($o>3ceJ5NBAJ`3!9Q_bkz<=X-yur}^JqFLk>%>L%gPK|2y&>K057br;E!jx;VDP2qV!orl zXh&yFWL5i3`N{hcW*lZ>1th3jmw#fiY*(S9`@Q})LJ}tNbdtAhhgG@L;wQF0b}n0J zNST({_V*d@F4C_gL(t!l&gOLVbnX2~owpE+Zi}g2_3pjBFw>pJf0mmBk0suizW@3@q20Gb zZn~}W5w2qn-!~Pinih~U?>Z&ZwT!3O^-r#RU$%DRbd%y9;2PfJYa?LNu_80^_JaSH zrT8Uo=JU+qTt`JdxO%#}DCL|k&f&!;D8z{Bs1PR)QKq|7rBmh=5h=PcXK%ILGN>^4 z{=Geaz~M%nRb6TjbOB?*o|{#?)AeKdHt>t$@>VG)&kUIn8G zGxrK!XTCmv$GKTr72$18Ix}R`{Uoj_vngQgT~q&f#Q29Y9`az@(Td2i(z23f8)7MG zrr_ns4hu_*?mXlvkIB>HxWyNPcM?z4^|hOd}y%~M1^2`c&YjxE*h4pq$S zyYBOFwf&oQ5%Uh_aQrO(@RKXvW3|0cOA%kq`|J83LFu2;XKp^P?xyGk;YEnTNcoS5 zo>_?xt!2DZ^$%@{!G4ENEF>=#6VU-VgO?_+TzMDtt|Lv>7rBI*me{K2h)EB|A z!M0y2hf#HP1F>J7A38g)0^5>jzwvUl+EI^{te)CdUI4KFJ?)}1+&{Je01R30v<#g7h_NGCaHqKG)I5^*5^sW zIsNSk@3j#YH9!arfxu*;kYCZTzPNv&(U5h{HplsG{wYU7+jT&4Iy2042-O4Z^ z;;_{0(sh`704EwEo?o4BhJb17i>8w5~{Gy-ej|d zz2=)hG$jz+)zoPV8?=^MFBgI*2xX!GlF-9A;P51Zmy6`4iEI!y#!`XMmfEJJx4y2| zwA6*I#ztlS*d)~0Je7K>FS6VnI-2UHzTK05=5sy+aU4~T3OOI2wh~UC!EspuKQ+u+ zE?p)ud~x9TD81gySUzt^Ze*`e#O$7(NRl~S_mK2j5qc~=|&=$L52AV?D)JDMB` zp`*$M@H=DcN%?hNeh+NDAhy=TdhEXowgU(OwowJ3=b#A-lqR5OG+76JXKW)Wzs$>T zf~^LYXATM literal 0 HcmV?d00001 diff --git a/examples/index.html b/examples/index.html index 4747d71..e3a2ef3 100644 --- a/examples/index.html +++ b/examples/index.html @@ -8,6 +8,7 @@
      • Loading with AMD/Require.js
      • Animation with seriously.go()
      • Accumulator
      • +
      • Blend Modes
      • Blur
        • Gaussian Blur
        • From 644cc1355b599475e4d8a5b821ce43c83a5edfb1 Mon Sep 17 00:00:00 2001 From: Brian Chirls Date: Mon, 7 Apr 2014 15:27:33 -0400 Subject: [PATCH 41/45] Fix: Blend effect in normal mode now renders correctly with low opacity (#50) Also: - separate blend equations supported by draw function - removed some commented code --- effects/seriously.accumulator.js | 1 - effects/seriously.blend.js | 33 +++++++++++++++++++++++++------- seriously.js | 8 ++++---- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/effects/seriously.accumulator.js b/effects/seriously.accumulator.js index dbae1be..58f3f29 100644 --- a/effects/seriously.accumulator.js +++ b/effects/seriously.accumulator.js @@ -61,7 +61,6 @@ hardlight: vectorBlendFormula('base < 0.5 ? (2.0 * base * blend) : (1.0 - 2.0 * (1.0 - base) * (1.0 - blend))', 'blend', 'base'), colordodge: vectorBlendFormula('blend == 1.0 ? blend : min(base / (1.0 - blend), 1.0)'), colorburn: vectorBlendFormula('blend == 0.0 ? blend : max((1.0 - ((1.0 - base) / blend)), 0.0)'), - //linearlight: vectorBlendFormula('blend < 0.5 ? max(base + 2.0 * blend - 1.0, 0.0) : min(base + (2.0 * (blend - 0.5)), 1.0)'), linearlight: vectorBlendFormula('BlendLinearLightf(base, blend)'), vividlight: vectorBlendFormula('BlendVividLightf(base, blend)'), pinlight: vectorBlendFormula('BlendPinLightf(base, blend)'), diff --git a/effects/seriously.blend.js b/effects/seriously.blend.js index 9215ef4..cadc276 100644 --- a/effects/seriously.blend.js +++ b/effects/seriously.blend.js @@ -1,4 +1,4 @@ -/* global define, require */ +/* global define, require, exports, Float32Array */ (function (root, factory) { 'use strict'; @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously, undefined) { +}(this, function (Seriously) { 'use strict'; /* @@ -65,7 +65,6 @@ hardlight: vectorBlendFormula('base < 0.5 ? (2.0 * base * blend) : (1.0 - 2.0 * (1.0 - base) * (1.0 - blend))', 'blend', 'base'), colordodge: vectorBlendFormula('blend == 1.0 ? blend : min(base / (1.0 - blend), 1.0)'), colorburn: vectorBlendFormula('blend == 0.0 ? blend : max((1.0 - ((1.0 - base) / blend)), 0.0)'), - //linearlight: vectorBlendFormula('blend < 0.5 ? max(base + 2.0 * blend - 1.0, 0.0) : min(base + (2.0 * (blend - 0.5)), 1.0)'), linearlight: vectorBlendFormula('BlendLinearLightf(base, blend)'), vividlight: vectorBlendFormula('BlendVividLightf(base, blend)'), pinlight: vectorBlendFormula('BlendPinLightf(base, blend)'), @@ -89,7 +88,20 @@ bottomUniforms, topOpts = { clear: false - }; + }, + inputs, + gl; + + function updateDrawFunction() { + var nativeMode = inputs && nativeBlendModes[inputs.mode]; + if (nativeMode && gl) { + topOpts.blendEquation = gl[nativeMode[0]]; + topOpts.srcRGB = gl[nativeMode[1]]; + topOpts.destRGB = gl[nativeMode[2]]; + topOpts.srcAlpha = gl[nativeMode[3]]; + topOpts.destAlpha = gl[nativeMode[4]]; + } + } // custom resize method this.resize = function () { @@ -162,6 +174,12 @@ }; return { + initialize: function (initialize) { + inputs = this.inputs; + initialize(); + gl = this.gl; + updateDrawFunction(); + }, shader: function (inputs, shaderSource) { var mode = inputs.mode || 'normal', node; @@ -306,13 +324,11 @@ return shaderSource; }, draw: function (shader, model, uniforms, frameBuffer, draw) { - var gl; if (nativeBlendModes[this.inputs.mode]) { if (this.inputs.bottom) { draw(shader, model, bottomUniforms, frameBuffer); } else { //just clear - gl = this.gl; gl.viewport(0, 0, this.width, this.height); gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer); gl.clearColor(0.0, 0.0, 0.0, 0.0); @@ -404,7 +420,10 @@ ['reflect', 'Reflect'], ['glow', 'Glow'], ['phoenix', 'Phoenix'] - ] + ], + update: function () { + updateDrawFunction(); + } } } }; diff --git a/seriously.js b/seriously.js index 8b109f9..ff7ad70 100644 --- a/seriously.js +++ b/seriously.js @@ -1150,19 +1150,19 @@ //default for blend is enable if (!options || options.blend === undefined || options.blend) { gl.enable(gl.BLEND); + /* gl.blendFunc( options && options.srcRGB || gl.ONE, options && options.dstRGB || gl.ONE_MINUS_SRC_ALPHA ); + */ - /* gl.blendFuncSeparate( options && options.srcRGB || gl.ONE, options && options.dstRGB || gl.ONE_MINUS_SRC_ALPHA, - options && options.srcAlpha || gl.SRC_ALPHA, - options && options.dstAlpha || gl.DST_ALPHA + options && (options.srcAlpha || options.srcRGB) || gl.SRC_ALPHA, + options && (options.dstAlpha || options.dstRGB) || gl.ONE ); - */ gl.blendEquation(options && options.blendEquation || gl.FUNC_ADD); } else { gl.disable(gl.BLEND); From 9a5f35b9f17e3f58f93f6fbcc95369efd5699495 Mon Sep 17 00:00:00 2001 From: Brian Chirls Date: Mon, 7 Apr 2014 15:44:42 -0400 Subject: [PATCH 42/45] Make Channels example more fun by swapping red and green This example was actually displaying incorrectly prior to the fix for --- examples/channels/index.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/channels/index.html b/examples/channels/index.html index fbc3bbf..bd0942b 100644 --- a/examples/channels/index.html +++ b/examples/channels/index.html @@ -73,6 +73,8 @@ channels.source = scaleRobot; channels.alphaSource = moveMask; channels.alpha = 'red'; + channels.blue = 'green'; + channels.green = 'blue'; blend.bottom = scalePencils; blend.top = channels; From ae9dbb67595900cf6b51ad49964f3ff1e22c6b55 Mon Sep 17 00:00:00 2001 From: Brian Chirls Date: Mon, 7 Apr 2014 15:58:02 -0400 Subject: [PATCH 43/45] Fixed: Blend effect was losing opacity when switching back to Normal mode --- effects/seriously.blend.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/effects/seriously.blend.js b/effects/seriously.blend.js index cadc276..fc914c8 100644 --- a/effects/seriously.blend.js +++ b/effects/seriously.blend.js @@ -197,7 +197,7 @@ targetRes: this.uniforms.resolution, source: node, transform: node && node.cumulativeMatrix || identity, - opacity: 1 + opacity: this.inputs.opacity }; node = this.inputs.bottom; From b2d13172289dd195dc4c104ad9b8e90449c4c894 Mon Sep 17 00:00:00 2001 From: Brian Chirls Date: Mon, 7 Apr 2014 19:12:59 -0400 Subject: [PATCH 44/45] Fixed blend effect rendering sources at wrong size (#51) --- effects/seriously.accumulator.js | 1 - effects/seriously.blend.js | 46 +++++++++++++++++++++++++++----- examples/blend/index.html | 9 ++++++- 3 files changed, 47 insertions(+), 9 deletions(-) diff --git a/effects/seriously.accumulator.js b/effects/seriously.accumulator.js index 58f3f29..15b5306 100644 --- a/effects/seriously.accumulator.js +++ b/effects/seriously.accumulator.js @@ -123,7 +123,6 @@ '#define BlendFunction(base, blend) ' + blendModes[mode], 'varying vec2 vTexCoord;', - 'varying vec4 vPosition;', 'uniform sampler2D source;', 'uniform sampler2D previous;', diff --git a/effects/seriously.blend.js b/effects/seriously.blend.js index fc914c8..4e692a9 100644 --- a/effects/seriously.blend.js +++ b/effects/seriously.blend.js @@ -157,6 +157,11 @@ this.setDirty(); } + this.uniforms.resBottom[0] = bottom.width; + this.uniforms.resBottom[1] = bottom.height; + this.uniforms.resTop[0] = top.width; + this.uniforms.resTop[1] = top.height; + if (topUniforms) { if (bottom) { bottomUniforms.resolution[0] = bottom.width; @@ -173,6 +178,9 @@ } }; + this.uniforms.resTop = [1, 1]; + this.uniforms.resBottom = [1, 1]; + return { initialize: function (initialize) { inputs = this.inputs; @@ -224,7 +232,6 @@ 'uniform mat4 transform;', 'varying vec2 vTexCoord;', - 'varying vec4 vPosition;', 'void main(void) {', // first convert to screen space @@ -237,14 +244,12 @@ ' gl_Position.xy *= resolution / targetRes;', ' gl_Position.w = screenPosition.w;', ' vTexCoord = texCoord;', - ' vPosition = gl_Position;', '}\n' ].join('\n'); shaderSource.fragment = [ 'precision mediump float;', 'varying vec2 vTexCoord;', - 'varying vec4 vPosition;', 'uniform sampler2D source;', 'uniform float opacity;', 'void main(void) {', @@ -259,6 +264,33 @@ topUniforms = null; bottomUniforms = null; + //todo: need separate texture coords for different size top/bottom images + shaderSource.vertex = [ + 'precision mediump float;', + + 'attribute vec4 position;', + 'attribute vec2 texCoord;', + + 'uniform vec2 resolution;', + 'uniform vec2 resBottom;', + 'uniform vec2 resTop;', + + 'varying vec2 texCoordBottom;', + 'varying vec2 texCoordTop;', + + 'const vec2 HALF = vec2(0.5);', + + 'void main(void) {', + //we don't need to do a transform in this shader, since this effect is not "inPlace" + ' gl_Position = position;', + + ' vec2 adjusted = (texCoord - HALF) * resolution;', + + ' texCoordBottom = adjusted / resBottom + HALF;', + ' texCoordTop = adjusted / resTop + HALF;', + '}\n' + ].join('\n'); + shaderSource.fragment = [ 'precision mediump float;', @@ -293,8 +325,8 @@ '#define BlendFunction(base, blend) ' + blendModes[mode], - 'varying vec2 vTexCoord;', - 'varying vec4 vPosition;', + 'varying vec2 texCoordBottom;', + 'varying vec2 texCoordTop;', 'uniform sampler2D top;', 'uniform sampler2D bottom;', @@ -308,8 +340,8 @@ 'void main(void) {', ' vec3 color;', - ' vec4 topPixel = texture2D(top, vTexCoord);', - ' vec4 bottomPixel = texture2D(bottom, vTexCoord);', + ' vec4 topPixel = texture2D(top, texCoordTop);', + ' vec4 bottomPixel = texture2D(bottom, texCoordBottom);', ' float alpha = topPixel.a + bottomPixel.a * (1.0 - topPixel.a);', ' if (alpha == 0.0) {', diff --git a/examples/blend/index.html b/examples/blend/index.html index 07e84fb..46ff621 100644 --- a/examples/blend/index.html +++ b/examples/blend/index.html @@ -68,19 +68,26 @@ var seriously, // the main object that holds the entire composition blend, reformat, + reformatRobot, target; // a wrapper object for our target canvas seriously = new Seriously(); target = seriously.target('#canvas'); blend = seriously.effect('blend'); reformat = seriously.transform('reformat'); + reformatRobot = seriously.transform('reformat'); + + reformatRobot.source = '#robot'; + reformatRobot.mode = 'cover'; + reformatRobot.width = 640; + reformatRobot.height = 619; reformat.source = '#bars'; reformat.mode = 'distort'; reformat.width = 640; reformat.height = 619; - blend.bottom = '#robot'; + blend.bottom = reformatRobot; blend.top = reformat; blend.opacity = '#opacity'; blend.mode = '#mode'; From d94dfeba2e3666c36fe0afdba58d56866cdd27ed Mon Sep 17 00:00:00 2001 From: Brian Chirls Date: Tue, 8 Apr 2014 12:22:44 -0400 Subject: [PATCH 45/45] Fixed non-normal blend modes in Blend (#50) and Accumulator (#23) --- effects/seriously.accumulator.js | 35 +++++++++++++++++++++++--------- effects/seriously.blend.js | 17 +++++++--------- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/effects/seriously.accumulator.js b/effects/seriously.accumulator.js index 15b5306..4951fc6 100644 --- a/effects/seriously.accumulator.js +++ b/effects/seriously.accumulator.js @@ -67,6 +67,16 @@ hardmix: vectorBlendFormula('BlendHardMixf(base, blend)'), reflect: vectorBlendFormula('BlendReflectf(base, blend)'), glow: vectorBlendFormula('BlendReflectf(blend, base)') + }, + + /* + All blend modes other than "normal" effectively act as adjustment layers, + so the alpha channel of the resulting image is just a copy of the "bottom" + or "destination" layer. The "top" or "source" alpha is only used to dampen + the color effect. + */ + mixAlpha = { + normal: true }; Seriously.plugin('accumulator', function () { @@ -121,6 +131,7 @@ */ '#define BlendFunction(base, blend) ' + blendModes[mode], + (mixAlpha[mode] ? '#define MIX_ALPHA' : ''), 'varying vec2 vTexCoord;', @@ -129,24 +140,28 @@ 'uniform float opacity;', - 'vec3 BlendOpacity(vec4 base, vec4 blend, float opacity, float alpha) {', - ' vec3 baseRGB = base.rgb * blend.a * opacity;', - ' vec3 blendRGB = blend.rgb * blend.a * opacity;', - ' return (BlendFunction(baseRGB, blendRGB) + base.rgb * base.a * (1.0 - blend.a * opacity)) / alpha;', + 'vec3 BlendOpacity(vec4 base, vec4 blend, float opacity) {', + //apply blend, then mix by (opacity * blend.a) + ' vec3 blendedColor = BlendFunction(base.rgb, blend.rgb);', + ' return mix(base.rgb, blendedColor, opacity * blend.a);', '}', 'void main(void) {', - ' vec3 color;', ' vec4 topPixel = texture2D(source, vTexCoord);', ' vec4 bottomPixel = texture2D(previous, vTexCoord);', - ' float alpha = topPixel.a + bottomPixel.a * (1.0 - topPixel.a);', - ' if (alpha == 0.0) {', - ' color = vec3(0.0);', + ' if (topPixel.a == 0.0) {', + ' gl_FragColor = bottomPixel;', ' } else {', - ' color = BlendOpacity(bottomPixel, topPixel, opacity, alpha);', + ' float alpha;', + '#ifdef MIX_ALPHA', + ' alpha = topPixel.a * opacity;', + ' alpha = alpha + bottomPixel.a * (1.0 - alpha);', + '#else', + ' alpha = bottomPixel.a;', + '#endif', + ' gl_FragColor = vec4(BlendOpacity(bottomPixel, topPixel, opacity), alpha);', ' }', - ' gl_FragColor = vec4(color, alpha);', '}' ].join('\n'); diff --git a/effects/seriously.blend.js b/effects/seriously.blend.js index 4e692a9..a8cd16b 100644 --- a/effects/seriously.blend.js +++ b/effects/seriously.blend.js @@ -332,24 +332,21 @@ 'uniform sampler2D bottom;', 'uniform float opacity;', - 'vec3 BlendOpacity(vec4 base, vec4 blend, float opacity, float alpha) {', - ' vec3 baseRGB = base.rgb * blend.a * opacity;', - ' vec3 blendRGB = blend.rgb * blend.a * opacity;', - ' return (BlendFunction(baseRGB, blendRGB) + base.rgb * base.a * (1.0 - blend.a * opacity)) / alpha;', + 'vec3 BlendOpacity(vec4 base, vec4 blend, float opacity) {', + //apply blend, then mix by (opacity * blend.a) + ' vec3 blendedColor = BlendFunction(base.rgb, blend.rgb);', + ' return mix(base.rgb, blendedColor, opacity * blend.a);', '}', 'void main(void) {', - ' vec3 color;', ' vec4 topPixel = texture2D(top, texCoordTop);', ' vec4 bottomPixel = texture2D(bottom, texCoordBottom);', - ' float alpha = topPixel.a + bottomPixel.a * (1.0 - topPixel.a);', - ' if (alpha == 0.0) {', - ' color = vec3(0.0);', + ' if (topPixel.a == 0.0) {', + ' gl_FragColor = bottomPixel;', ' } else {', - ' color = BlendOpacity(bottomPixel, topPixel, opacity, alpha);', + ' gl_FragColor = vec4(BlendOpacity(bottomPixel, topPixel, opacity), bottomPixel.a);', ' }', - ' gl_FragColor = vec4(color, alpha);', '}' ].join('\n');