diff --git a/README.md b/README.md index a810dba..bd79a0f 100644 --- a/README.md +++ b/README.md @@ -31,9 +31,11 @@ Full documentation is in progress at the [wiki](https://github.com/brianchirls/S - Checkerboard Generator - Chroma Key - Color Complements -- Color Generator - [Color Cube](http://www.youtube.com/watch?v=rfQ8rKGTVlg&t=24m30s) +- Color Generator +- Color Look-Up Table - Color Select +- Color Temperature - Crop - [Daltonize](http://www.daltonize.org/p/about.html) - Directional Blur @@ -59,6 +61,7 @@ Full documentation is in progress at the [wiki](https://github.com/brianchirls/S - Luma Key - Mirror - Night Vision +- Optical Flow - Panorama - Pixelate - Polar Coordinates diff --git a/effects/seriously.accumulator.js b/effects/seriously.accumulator.js index 279d822..13d36d9 100644 --- a/effects/seriously.accumulator.js +++ b/effects/seriously.accumulator.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; /* @@ -92,7 +92,28 @@ clear: false }, frameBuffers, - fbIndex = 0; + fbIndex = 0, + me = this, + width = this.width, + height = this.height; + + function clear() { + var gl = me.gl, + width = me.width, + height = me.height, + color = me.inputs.startColor; + + if (gl && width && height) { + gl.viewport(0, 0, width, height); + gl.clearColor.apply(gl, color); + + gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffers[0].frameBuffer); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + + gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffers[1].frameBuffer); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + } + } return { initialize: function (initialize, gl) { @@ -101,12 +122,14 @@ this.frameBuffer, new Seriously.util.FrameBuffer(gl, this.width, this.height) ]; + clear(); }, shader: function (inputs, shaderSource) { var mode = inputs.blendMode || 'normal'; mode = mode.toLowerCase(); shaderSource.fragment = [ + '#define SHADER_NAME seriously.accumulator.' + mode, 'precision mediump float;', 'const vec3 ZERO = vec3(0.0);', @@ -266,6 +289,7 @@ 'uniform sampler2D previous;', 'uniform float opacity;', + 'uniform float blendGamma;', 'vec3 BlendOpacity(vec4 base, vec4 blend, float opacity) {', //apply blend, then mix by (opacity * blend.a) @@ -273,8 +297,13 @@ ' return mix(base.rgb, blendedColor, opacity * blend.a);', '}', + 'vec4 linear(vec4 color, vec3 gamma) {', + ' return vec4(pow(color.rgb, gamma), color.a);', + '}', + 'void main(void) {', - ' vec4 topPixel = texture2D(source, vTexCoord);', + ' vec3 exp = vec3(blendGamma);', + ' vec4 topPixel = linear(texture2D(source, vTexCoord), exp);', ' vec4 bottomPixel = texture2D(previous, vTexCoord);', ' if (topPixel.a == 0.0) {', @@ -287,7 +316,8 @@ '#else', ' alpha = bottomPixel.a;', '#endif', - ' gl_FragColor = vec4(BlendOpacity(bottomPixel, topPixel, opacity), alpha);', + ' bottomPixel = linear(bottomPixel, exp);', + ' gl_FragColor = vec4(pow(BlendOpacity(bottomPixel, topPixel, opacity), 1.0 / exp), alpha);', ' }', '}' ].join('\n'); @@ -295,9 +325,12 @@ return shaderSource; }, resize: function () { - if (frameBuffers) { - frameBuffers[0].resize(this.width, this.height); - frameBuffers[1].resize(this.width, this.height); + if (frameBuffers && (this.width !== width || this.height !== height)) { + width = this.width; + height = this.height; + frameBuffers[0].resize(width, height); + frameBuffers[1].resize(width, height); + clear(); } }, draw: function (shader, model, uniforms, frameBuffer, draw) { @@ -311,6 +344,7 @@ this.texture = fb.texture; if (this.inputs.clear) { + clear(); draw(this.baseShader, model, uniforms, fb.frameBuffer, null); return; } @@ -338,6 +372,10 @@ type: 'boolean', defaultValue: false }, + startColor: { + type: 'color', + defaultValue: [0, 0, 0, 0] + }, opacity: { type: 'number', uniform: 'opacity', @@ -345,6 +383,13 @@ min: 0, max: 1 }, + blendGamma: { + type: 'number', + uniform: 'blendGamma', + defaultValue: 2.2, + min: 0, + max: 4 + }, blendMode: { type: 'enum', shaderDirty: true, diff --git a/effects/seriously.ascii.js b/effects/seriously.ascii.js index fa06d7b..7fee535 100644 --- a/effects/seriously.ascii.js +++ b/effects/seriously.ascii.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; /* diff --git a/effects/seriously.bleach-bypass.js b/effects/seriously.bleach-bypass.js index 205165c..0c48380 100644 --- a/effects/seriously.bleach-bypass.js +++ b/effects/seriously.bleach-bypass.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; /* diff --git a/effects/seriously.blend.js b/effects/seriously.blend.js index d6ed228..24fc9ac 100644 --- a/effects/seriously.blend.js +++ b/effects/seriously.blend.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; /* @@ -81,9 +81,9 @@ glow: vectorBlendFormula('BlendReflectf(blend, base)') }, nativeBlendModes = { - normal: ['FUNC_ADD', 'SRC_ALPHA', 'ONE_MINUS_SRC_ALPHA', 'SRC_ALPHA', 'DST_ALPHA']/*, - add: ['FUNC_ADD', 'SRC_ALPHA', 'ONE_MINUS_SRC_ALPHA', 'SRC_ALPHA', 'DST_ALPHA']*/ - //todo: multiply, screen + //native blend modes removed for now, because they don't work with linear blending + // normal: ['FUNC_ADD', 'SRC_ALPHA', 'ONE_MINUS_SRC_ALPHA', 'SRC_ALPHA', 'DST_ALPHA'] + //todo: add, multiply, screen }, identity = new Float32Array([ 1, 0, 0, 0, @@ -231,6 +231,7 @@ } shaderSource.vertex = [ + '#define SHADER_NAME seriously.blend.' + mode, 'precision mediump float;', 'attribute vec4 position;', @@ -257,6 +258,7 @@ ].join('\n'); shaderSource.fragment = [ + '#define SHADER_NAME seriously.blend.' + mode, 'precision mediump float;', 'varying vec2 vTexCoord;', 'uniform sampler2D source;', @@ -275,6 +277,7 @@ //todo: need separate texture coords for different size top/bottom images shaderSource.vertex = [ + '#define SHADER_NAME seriously.blend.' + mode, 'precision mediump float;', 'attribute vec4 position;', @@ -301,6 +304,7 @@ ].join('\n'); shaderSource.fragment = [ + '#define SHADER_NAME seriously.blend.' + mode, 'precision mediump float;', 'const vec3 ZERO = vec3(0.0);', @@ -459,6 +463,7 @@ 'uniform sampler2D top;', 'uniform sampler2D bottom;', 'uniform float opacity;', + 'uniform float blendGamma;', 'vec3 BlendOpacity(vec4 base, vec4 blend, float opacity) {', //apply blend, then mix by (opacity * blend.a) @@ -466,14 +471,20 @@ ' return mix(base.rgb, blendedColor, opacity * blend.a);', '}', + 'vec4 linear(vec4 color, vec3 gamma) {', + ' return vec4(pow(color.rgb, gamma), color.a);', + '}', + 'void main(void) {', - ' vec4 topPixel = texture2D(top, texCoordTop);', + ' vec3 exp = vec3(blendGamma);', + ' vec4 topPixel = linear(texture2D(top, texCoordTop), exp);', ' vec4 bottomPixel = texture2D(bottom, texCoordBottom);', ' if (topPixel.a == 0.0) {', ' gl_FragColor = bottomPixel;', ' } else {', - ' gl_FragColor = vec4(BlendOpacity(bottomPixel, topPixel, opacity), bottomPixel.a);', + ' bottomPixel = linear(bottomPixel, exp);', + ' gl_FragColor = vec4(pow(BlendOpacity(bottomPixel, topPixel, opacity), 1.0 / exp), bottomPixel.a);', ' }', '}' ].join('\n'); @@ -541,6 +552,13 @@ } } }, + blendGamma: { + type: 'number', + uniform: 'blendGamma', + defaultValue: 2.2, + min: 0, + max: 4 + }, sizeMode: { type: 'enum', defaultValue: 'bottom', diff --git a/effects/seriously.blur.js b/effects/seriously.blur.js index 10142e6..efe9993 100644 --- a/effects/seriously.blur.js +++ b/effects/seriously.blur.js @@ -23,7 +23,7 @@ http://v002.info/plugins/v002-blurs/ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; var passes = [0.2, 0.3, 0.5, 0.8, 1], @@ -43,6 +43,7 @@ http://v002.info/plugins/v002-blurs/ baseShader, loopUniforms = { amount: 0, + blendGamma: 2, inputScale: 1, resolution: [this.width, this.height], transform: identity, @@ -68,16 +69,9 @@ http://v002.info/plugins/v002-blurs/ }, commonShader: true, shader: function (inputs, shaderSource) { - var gl = this.gl, - /* - Some devices or browsers (e.g. IE11 preview) don't support enough - varying vectors, so we need to fallback to a less efficient method - */ - maxVaryings = gl.getParameter(gl.MAX_VARYING_VECTORS), - defineVaryings = (maxVaryings >= 10 ? '#define USE_VARYINGS' : ''); + var gl = this.gl; shaderSource.vertex = [ - defineVaryings, 'precision mediump float;', 'attribute vec4 position;', @@ -90,25 +84,10 @@ http://v002.info/plugins/v002-blurs/ 'uniform float amount;', 'uniform float inputScale;', - 'const vec2 zero = vec2(0.0, 0.0);', + 'const vec2 zero = vec2(0.0);', 'varying vec2 vTexCoord;', - - '#ifdef USE_VARYINGS', - 'vec2 one;', - 'vec2 amount1;', - 'varying vec2 vTexCoord1;', - 'varying vec2 vTexCoord2;', - 'varying vec2 vTexCoord3;', - 'varying vec2 vTexCoord4;', - 'varying vec2 vTexCoord5;', - 'varying vec2 vTexCoord6;', - 'varying vec2 vTexCoord7;', - 'varying vec2 vTexCoord8;', - '#else', - 'varying vec2 one;', - 'varying vec2 amount1;', - '#endif', + 'varying vec4 vTexCoords[4];', 'void main(void) {', // first convert to screen space @@ -121,78 +100,52 @@ http://v002.info/plugins/v002-blurs/ ' gl_Position.z = screenPosition.z * 2.0 / (resolution.x / resolution.y);', ' vTexCoord = texCoord;', - ' one = vec2(1.0, 1.0) * inputScale;', + ' vec2 one = vec2(1.0) * inputScale;', ' if (inputScale < 1.0) {', ' one -= 1.0 / resolution;', ' }', ' vTexCoord = max(zero, min(one, texCoord.st * inputScale));', - ' amount1 = direction * (inputScale * amount * 5.0 / resolution);', - - '#ifdef USE_VARYINGS', - ' vec2 amount2 = amount1 * 3.0;', - ' vec2 amount3 = amount1 * 6.0;', - ' vec2 amount4 = amount1 * 9.0;', - ' vec2 amount5 = -amount1;', - ' vec2 amount6 = amount5 * 3.0;', - ' vec2 amount7 = amount5 * 6.0;', - ' vec2 amount8 = amount5 * 9.0;', - ' vTexCoord1 = max(zero, min(one, vTexCoord + amount1));', - ' vTexCoord2 = max(zero, min(one, vTexCoord + amount2));', - ' vTexCoord3 = max(zero, min(one, vTexCoord + amount3));', - ' vTexCoord4 = max(zero, min(one, vTexCoord + amount4));', - ' vTexCoord5 = max(zero, min(one, vTexCoord + amount5));', - ' vTexCoord6 = max(zero, min(one, vTexCoord + amount6));', - ' vTexCoord7 = max(zero, min(one, vTexCoord + amount7));', - ' vTexCoord8 = max(zero, min(one, vTexCoord + amount8));', - '#endif', + ' vec2 amount = direction * (inputScale * amount * 5.0 / resolution);', + + ' for (int i = 0; i < 4; i++) {', + ' float s = pow(3.0, float(i));', + ' vTexCoords[i].xy = max(zero, min(one, vTexCoord + amount * s));', + ' vTexCoords[i].zw = max(zero, min(one, vTexCoord - amount * s));', + ' }', '}' ].join('\n'); shaderSource.fragment = [ - defineVaryings, - 'precision mediump float;\n', + 'uniform sampler2D source;', + 'uniform float blendGamma;', + 'varying vec2 vTexCoord;', + 'varying vec4 vTexCoords[4];', - 'uniform sampler2D source;', + 'vec3 exp;', - '#ifdef USE_VARYINGS', - 'varying vec2 vTexCoord1;', - 'varying vec2 vTexCoord2;', - 'varying vec2 vTexCoord3;', - 'varying vec2 vTexCoord4;', - 'varying vec2 vTexCoord5;', - 'varying vec2 vTexCoord6;', - 'varying vec2 vTexCoord7;', - 'varying vec2 vTexCoord8;', - '#else', - 'varying vec2 amount1;', - 'varying vec2 one;', - 'const vec2 zero = vec2(0.0, 0.0);', - '#endif', + 'vec4 sample(sampler2D sampler, vec2 coord) {', + ' vec4 pixel = texture2D(sampler, coord);', + ' pixel.rgb = pow(pixel.rgb, exp);', + ' return pixel;', + '}', 'void main(void) {', - '#ifndef USE_VARYINGS', - ' vec2 vTexCoord1 = max(zero, min(one, vTexCoord + amount1));', - ' vec2 vTexCoord2 = max(zero, min(one, vTexCoord + amount1 * 3.0));', - ' vec2 vTexCoord3 = max(zero, min(one, vTexCoord + amount1 * 6.0));', - ' vec2 vTexCoord4 = max(zero, min(one, vTexCoord + amount1 * 9.0));', - ' vec2 vTexCoord5 = max(zero, min(one, vTexCoord - amount1));', - ' vec2 vTexCoord6 = max(zero, min(one, vTexCoord - amount1 * 3.0));', - ' vec2 vTexCoord7 = max(zero, min(one, vTexCoord - amount1 * 6.0));', - ' vec2 vTexCoord8 = max(zero, min(one, vTexCoord - amount1 * 9.0));', - '#endif', - ' gl_FragColor = texture2D(source, vTexCoord) / 9.0;', - ' gl_FragColor += texture2D(source, vTexCoord1) / 9.0;', - ' gl_FragColor += texture2D(source, vTexCoord2) / 9.0;', - ' gl_FragColor += texture2D(source, vTexCoord3) / 9.0;', - ' gl_FragColor += texture2D(source, vTexCoord4) / 9.0;', - ' gl_FragColor += texture2D(source, vTexCoord5) / 9.0;', - ' gl_FragColor += texture2D(source, vTexCoord6) / 9.0;', - ' gl_FragColor += texture2D(source, vTexCoord7) / 9.0;', - ' gl_FragColor += texture2D(source, vTexCoord8) / 9.0;', - '}' + + ' exp = vec3(blendGamma);', + + ' gl_FragColor = sample(source, vTexCoord) / 9.0;', + + ' for (int i = 0; i < 4; i++) {', + ' gl_FragColor += sample(source, vTexCoords[i].xy) / 9.0;', + ' gl_FragColor += sample(source, vTexCoords[i].zw) / 9.0;', + ' }', + + ' gl_FragColor.rgb = pow(gl_FragColor.rgb, 1.0 / exp);', + + '}', ].join('\n'); return shaderSource; @@ -232,6 +185,7 @@ http://v002.info/plugins/v002-blurs/ } loopUniforms.amount = amount; + loopUniforms.blendGamma = uniforms.blendGamma; loopUniforms.source = this.inputs.source.texture; for (i = 0; i < passes.length; i++) { @@ -292,6 +246,13 @@ http://v002.info/plugins/v002-blurs/ defaultValue: 0.2, min: 0, max: 1 + }, + blendGamma: { + type: 'number', + uniform: 'blendGamma', + defaultValue: 2.2, + min: 0, + max: 4 } }, title: 'Gaussian Blur' diff --git a/effects/seriously.brightness-contrast.js b/effects/seriously.brightness-contrast.js index 7a098c8..400cf36 100644 --- a/effects/seriously.brightness-contrast.js +++ b/effects/seriously.brightness-contrast.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; Seriously.plugin('brightness-contrast', { diff --git a/effects/seriously.channels.js b/effects/seriously.channels.js index 9e4ad99..ca9d52f 100644 --- a/effects/seriously.channels.js +++ b/effects/seriously.channels.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; var channelOptions = [ diff --git a/effects/seriously.checkerboard.js b/effects/seriously.checkerboard.js index ea4ac8b..b94fbaf 100644 --- a/effects/seriously.checkerboard.js +++ b/effects/seriously.checkerboard.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; Seriously.plugin('checkerboard', function () { diff --git a/effects/seriously.chroma.js b/effects/seriously.chroma.js index 3d09481..d944624 100644 --- a/effects/seriously.chroma.js +++ b/effects/seriously.chroma.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; /* @@ -101,7 +101,7 @@ */ ' float alpha = max(0.0, 1.0 - pixelSat / screenSat);', ' alpha = smoothstep(clipBlack, clipWhite, alpha);', - ' vec4 semiTransparentPixel = vec4((sourcePixel.rgb - (1.0 - alpha) * screen.rgb * screenWeight) / alpha, alpha);', + ' vec4 semiTransparentPixel = vec4((sourcePixel.rgb - (1.0 - alpha) * screen.rgb * screenWeight) / max(0.00001, alpha), alpha);', ' vec4 pixel = mix(semiTransparentPixel, sourcePixel, solid);', diff --git a/effects/seriously.color-select.js b/effects/seriously.color-select.js index faebcb8..627513c 100644 --- a/effects/seriously.color-select.js +++ b/effects/seriously.color-select.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; Seriously.plugin('color-select', { diff --git a/effects/seriously.color.js b/effects/seriously.color.js index 940801b..6fb9ab5 100644 --- a/effects/seriously.color.js +++ b/effects/seriously.color.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; Seriously.plugin('color', function () { diff --git a/effects/seriously.colorcomplements.js b/effects/seriously.colorcomplements.js index 73f0502..a9a2ce5 100644 --- a/effects/seriously.colorcomplements.js +++ b/effects/seriously.colorcomplements.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; Seriously.plugin('colorcomplements', { diff --git a/effects/seriously.colorcube.js b/effects/seriously.colorcube.js index a838458..1fe8a0b 100644 --- a/effects/seriously.colorcube.js +++ b/effects/seriously.colorcube.js @@ -14,12 +14,12 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; - //based on tutorial by to Gregg Tavares - //http://www.youtube.com/watch?v=rfQ8rKGTVlg&t=24m30s - //todo: find a way to not invert every single texture + // based on tutorial by to Gregg Tavares + // http://www.youtube.com/watch?v=rfQ8rKGTVlg&t=24m30s + // todo: find a way to not invert every single texture Seriously.plugin('colorcube', { commonShader: true, diff --git a/effects/seriously.crop.js b/effects/seriously.crop.js index 246e2dc..d8cdb68 100755 --- a/effects/seriously.crop.js +++ b/effects/seriously.crop.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; Seriously.plugin('crop', function () { diff --git a/effects/seriously.daltonize.js b/effects/seriously.daltonize.js index ff11175..76f0365 100644 --- a/effects/seriously.daltonize.js +++ b/effects/seriously.daltonize.js @@ -15,7 +15,7 @@ } factory(Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; //todo: add Simulate mode http://mudcu.be/labs/Color/Vision/Javascript/Color.Vision.Simulate.js diff --git a/effects/seriously.directionblur.js b/effects/seriously.directionblur.js index 0d0c48c..e734705 100644 --- a/effects/seriously.directionblur.js +++ b/effects/seriously.directionblur.js @@ -23,7 +23,7 @@ http://v002.info/plugins/v002-blurs/ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; var passes = [0.2, 0.3, 0.5, 0.8], @@ -39,6 +39,7 @@ http://v002.info/plugins/v002-blurs/ baseShader, loopUniforms = { amount: 0, + blendGamma: 2, angle: 0, inputScale: 1, resolution: [this.width, this.height], @@ -70,18 +71,11 @@ http://v002.info/plugins/v002-blurs/ }, commonShader: true, shader: function (inputs, shaderSource) { - var gl = this.gl, - /* - Some devices or browsers (e.g. IE11 preview) don't support enough - varying vectors, so we need to fallback to a less efficient method - */ - maxVaryings = gl.getParameter(gl.MAX_VARYING_VECTORS), - defineVaryings = (maxVaryings >= 10 ? '#define USE_VARYINGS' : ''); + var gl = this.gl; baseShader = this.baseShader; shaderSource.vertex = [ - defineVaryings, 'precision mediump float;', 'attribute vec4 position;', @@ -91,28 +85,14 @@ http://v002.info/plugins/v002-blurs/ 'uniform mat4 projection;', 'uniform mat4 transform;', - 'varying vec2 vTexCoord;', - 'uniform float angle;', 'uniform float amount;', 'uniform float inputScale;', - 'const vec2 zero = vec2(0.0, 0.0);', - '#ifdef USE_VARYINGS', - 'vec2 one;', - 'vec2 amount1;', - 'varying vec2 vTexCoord1;', - 'varying vec2 vTexCoord2;', - 'varying vec2 vTexCoord3;', - 'varying vec2 vTexCoord4;', - 'varying vec2 vTexCoord5;', - 'varying vec2 vTexCoord6;', - 'varying vec2 vTexCoord7;', - 'varying vec2 vTexCoord8;', - '#else', - 'varying vec2 one;', - 'varying vec2 amount1;', - '#endif', + 'const vec2 zero = vec2(0.0);', + + 'varying vec2 vTexCoord;', + 'varying vec4 vTexCoords[4];', 'void main(void) {', // first convert to screen space @@ -125,79 +105,52 @@ http://v002.info/plugins/v002-blurs/ ' gl_Position.z = screenPosition.z * 2.0 / (resolution.x / resolution.y);', ' vTexCoord = texCoord;', - ' one = vec2(1.0, 1.0) * inputScale;', + ' vec2 one = vec2(1.0) * inputScale;', ' if (inputScale < 1.0) {', ' one -= 1.0 / resolution;', ' }', ' vTexCoord = max(zero, min(one, texCoord.st * inputScale));', - ' amount1 = vec2(cos(angle), sin(angle)) * amount * 5.0 / resolution;', - - '#ifdef USE_VARYINGS', - ' vec2 amount2 = amount1 * 3.0;', - ' vec2 amount3 = amount1 * 6.0;', - ' vec2 amount4 = amount1 * 9.0;', - ' vec2 amount5 = -amount1;', - ' vec2 amount6 = amount5 * 3.0;', - ' vec2 amount7 = amount5 * 6.0;', - ' vec2 amount8 = amount5 * 9.0;', - ' vTexCoord1 = max(zero, min(one, vTexCoord + amount1));', - ' vTexCoord2 = max(zero, min(one, vTexCoord + amount2));', - ' vTexCoord3 = max(zero, min(one, vTexCoord + amount3));', - ' vTexCoord4 = max(zero, min(one, vTexCoord + amount4));', - ' vTexCoord5 = max(zero, min(one, vTexCoord + amount5));', - ' vTexCoord6 = max(zero, min(one, vTexCoord + amount6));', - ' vTexCoord7 = max(zero, min(one, vTexCoord + amount7));', - ' vTexCoord8 = max(zero, min(one, vTexCoord + amount8));', - '#endif', + ' vec2 amount = vec2(cos(angle), sin(angle)) * amount * 5.0 / resolution;', + + ' for (int i = 0; i < 4; i++) {', + ' float s = pow(3.0, float(i));', + ' vTexCoords[i].xy = max(zero, min(one, vTexCoord + amount * s));', + ' vTexCoords[i].zw = max(zero, min(one, vTexCoord - amount * s));', + ' }', '}' ].join('\n'); shaderSource.fragment = [ - defineVaryings, - 'precision mediump float;\n', - 'varying vec2 vTexCoord;', - 'uniform sampler2D source;', 'uniform float angle;', 'uniform float amount;', - 'uniform float inputScale;', + 'uniform float blendGamma;', + + 'varying vec2 vTexCoord;', + 'varying vec4 vTexCoords[4];', + + 'vec3 exp;', - '#ifdef USE_VARYINGS', - 'varying vec2 vTexCoord1;', - 'varying vec2 vTexCoord2;', - 'varying vec2 vTexCoord3;', - 'varying vec2 vTexCoord4;', - 'varying vec2 vTexCoord5;', - 'varying vec2 vTexCoord6;', - 'varying vec2 vTexCoord7;', - 'varying vec2 vTexCoord8;', - '#else', - 'varying vec2 amount1;', - 'varying vec2 one;', - 'const vec2 zero = vec2(0.0, 0.0);', - '#endif', + 'vec4 sample(sampler2D sampler, vec2 coord) {', + ' vec4 pixel = texture2D(sampler, coord);', + ' pixel.rgb = pow(pixel.rgb, exp);', + ' return pixel;', + '}', 'void main(void) {', - '#ifndef USE_VARYINGS', - ' vec2 vTexCoord1 = max(zero, min(one, vTexCoord + amount1));', - ' vec2 vTexCoord2 = max(zero, min(one, vTexCoord + amount1 * 3.0));', - ' vec2 vTexCoord3 = max(zero, min(one, vTexCoord + amount1 * 6.0));', - ' vec2 vTexCoord4 = max(zero, min(one, vTexCoord + amount1 * 9.0));', - ' vec2 vTexCoord5 = max(zero, min(one, vTexCoord - amount1));', - ' vec2 vTexCoord6 = max(zero, min(one, vTexCoord - amount1 * 3.0));', - ' vec2 vTexCoord7 = max(zero, min(one, vTexCoord - amount1 * 6.0));', - ' vec2 vTexCoord8 = max(zero, min(one, vTexCoord - amount1 * 9.0));', - '#endif', - ' gl_FragColor = texture2D(source, vTexCoord) / 9.0;', - ' gl_FragColor += texture2D(source, vTexCoord1) / 9.0;', - ' gl_FragColor += texture2D(source, vTexCoord2) / 9.0;', - ' gl_FragColor += texture2D(source, vTexCoord3) / 9.0;', - ' gl_FragColor += texture2D(source, vTexCoord4) / 9.0;', - ' gl_FragColor += texture2D(source, vTexCoord5) / 9.0;', - ' gl_FragColor += texture2D(source, vTexCoord6) / 9.0;', - ' gl_FragColor += texture2D(source, vTexCoord7) / 9.0;', - ' gl_FragColor += texture2D(source, vTexCoord8) / 9.0;', + + ' exp = vec3(blendGamma);', + + ' gl_FragColor = sample(source, vTexCoord) / 9.0;', + + ' for (int i = 0; i < 4; i++) {', + ' gl_FragColor += sample(source, vTexCoords[i].xy) / 9.0;', + ' gl_FragColor += sample(source, vTexCoords[i].zw) / 9.0;', + ' }', + + ' gl_FragColor.rgb = pow(gl_FragColor.rgb, 1.0 / exp);', + '}' ].join('\n'); @@ -293,6 +246,13 @@ http://v002.info/plugins/v002-blurs/ type: 'number', uniform: 'angle', defaultValue: 0 + }, + blendGamma: { + type: 'number', + uniform: 'blendGamma', + defaultValue: 2.2, + min: 0, + max: 4 } }, title: 'Directional Motion Blur' diff --git a/effects/seriously.displacement.js b/effects/seriously.displacement.js index 871a6ca..ff87f0c 100644 --- a/effects/seriously.displacement.js +++ b/effects/seriously.displacement.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; var fillModes = { @@ -22,11 +22,22 @@ clamp: 'pos = min(max(pos, 0.0), 1.0);', ignore: 'pos = texCoordSource;', color: 'gl_FragColor = color;\n\treturn;' + }, + channelVectors = { + none: [0, 0, 0, 0], + red: [1, 0, 0, 0], + green: [0, 1, 0, 0], + blue: [0, 0, 1, 0], + alpha: [0, 0, 0, 1], + luma: [0.2125, 0.7154, 0.0721, 0], + lightness: [1 / 3, 1 / 3, 1 / 3, 0] }; Seriously.plugin('displacement', function () { this.uniforms.resMap = [1, 1]; this.uniforms.resSource = [1, 1]; + this.uniforms.xVector = channelVectors.red; + this.uniforms.yVector = channelVectors.green; return { shader: function (inputs, shaderSource) { @@ -71,10 +82,13 @@ 'uniform float offset;', 'uniform vec2 mapScale;', 'uniform vec4 color;', + 'uniform vec4 xVector;', + 'uniform vec4 yVector;', 'void main(void) {', ' vec4 mapPixel = texture2D(map, texCoordMap);', - ' vec2 pos = texCoordSource + (mapPixel.xy - offset) * mapScale * amount;', + ' vec2 mapVector = vec2(dot(mapPixel, xVector), dot(mapPixel, yVector));', + ' vec2 pos = texCoordSource + (mapVector.xy - offset) * mapScale * amount;', ' if (pos.x < 0.0 || pos.x > 1.0 || pos.y < 0.0 || pos.y > 1.0) {', ' ' + fillMode, @@ -124,6 +138,26 @@ type: 'image', uniform: 'map' }, + xChannel: { + type: 'enum', + defaultValue: 'red', + options: [ + 'red', 'green', 'blue', 'alpha', 'luma', 'lightness', 'none' + ], + update: function (val) { + this.uniforms.xVector = channelVectors[val]; + } + }, + yChannel: { + type: 'enum', + defaultValue: 'green', + options: [ + 'red', 'green', 'blue', 'alpha', 'luma', 'lightness', 'none' + ], + update: function (val) { + this.uniforms.yVector = channelVectors[val]; + } + }, fillMode: { type: 'enum', shaderDirty: true, diff --git a/effects/seriously.dither.js b/effects/seriously.dither.js index 553f8c9..57cb814 100644 --- a/effects/seriously.dither.js +++ b/effects/seriously.dither.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; /* diff --git a/effects/seriously.edge.js b/effects/seriously.edge.js index 320c2f8..2f822da 100644 --- a/effects/seriously.edge.js +++ b/effects/seriously.edge.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; // Adapted from http://rastergrid.com/blog/2011/01/frei-chen-edge-detector/ @@ -67,9 +67,9 @@ this.uniforms.pixelHeight = 1 / this.height; if (this.inputs.mode === 'sobel') { - this.uniforms['G[0]'] = sobelMatrixConstants; + this.uniforms.G = sobelMatrixConstants; } else { - this.uniforms['G[0]'] = freiChenMatrixConstants; + this.uniforms.G = freiChenMatrixConstants; } }, shader: function (inputs, shaderSource) { @@ -157,9 +157,9 @@ ], update: function () { if (this.inputs.mode === 'sobel') { - this.uniforms['G[0]'] = sobelMatrixConstants; + this.uniforms.G = sobelMatrixConstants; } else { - this.uniforms['G[0]'] = freiChenMatrixConstants; + this.uniforms.G = freiChenMatrixConstants; } } } diff --git a/effects/seriously.emboss.js b/effects/seriously.emboss.js index 1df1ec5..e4b07ac 100644 --- a/effects/seriously.emboss.js +++ b/effects/seriously.emboss.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; Seriously.plugin('emboss', { diff --git a/effects/seriously.exposure.js b/effects/seriously.exposure.js index c02592a..be35cfa 100755 --- a/effects/seriously.exposure.js +++ b/effects/seriously.exposure.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; Seriously.plugin('exposure', { diff --git a/effects/seriously.expression.js b/effects/seriously.expression.js index 83c0029..0fd24bf 100644 --- a/effects/seriously.expression.js +++ b/effects/seriously.expression.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; function formatFloat(n) { diff --git a/effects/seriously.fader.js b/effects/seriously.fader.js index a4cf786..ec4d46c 100644 --- a/effects/seriously.fader.js +++ b/effects/seriously.fader.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; Seriously.plugin('fader', { diff --git a/effects/seriously.falsecolor.js b/effects/seriously.falsecolor.js index 320a0d8..d846bf9 100644 --- a/effects/seriously.falsecolor.js +++ b/effects/seriously.falsecolor.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; Seriously.plugin('falsecolor', { diff --git a/effects/seriously.filmgrain.js b/effects/seriously.filmgrain.js index 96401e6..65c2bba 100644 --- a/effects/seriously.filmgrain.js +++ b/effects/seriously.filmgrain.js @@ -25,7 +25,7 @@ Modified to preserve alpha } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; Seriously.plugin('filmgrain', { @@ -135,7 +135,8 @@ Modified to preserve alpha }, time: { type: 'number', - uniform: 'time' + uniform: 'time', + mod: 65536 }, amount: { type: 'number', diff --git a/effects/seriously.freeze.js b/effects/seriously.freeze.js index 8ea4686..1548ca4 100644 --- a/effects/seriously.freeze.js +++ b/effects/seriously.freeze.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; Seriously.plugin('freeze', { diff --git a/effects/seriously.fxaa.js b/effects/seriously.fxaa.js index 859c322..d404b07 100644 --- a/effects/seriously.fxaa.js +++ b/effects/seriously.fxaa.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; /* diff --git a/effects/seriously.gradientwipe.js b/effects/seriously.gradientwipe.js index b45f4cf..9cbf7bf 100644 --- a/effects/seriously.gradientwipe.js +++ b/effects/seriously.gradientwipe.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; Seriously.plugin('gradientwipe', function () { diff --git a/effects/seriously.hex.js b/effects/seriously.hex.js index a43c875..80cbb64 100644 --- a/effects/seriously.hex.js +++ b/effects/seriously.hex.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; /* diff --git a/effects/seriously.highlights-shadows.js b/effects/seriously.highlights-shadows.js index 5b24012..e376156 100644 --- a/effects/seriously.highlights-shadows.js +++ b/effects/seriously.highlights-shadows.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; Seriously.plugin('highlights-shadows', { diff --git a/effects/seriously.hue-saturation.js b/effects/seriously.hue-saturation.js index 5a6a52b..259ab6a 100644 --- a/effects/seriously.hue-saturation.js +++ b/effects/seriously.hue-saturation.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; //inspired by Evan Wallace (https://github.com/evanw/glfx.js) diff --git a/effects/seriously.invert.js b/effects/seriously.invert.js index 47a6b04..2210206 100644 --- a/effects/seriously.invert.js +++ b/effects/seriously.invert.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; Seriously.plugin('invert', { diff --git a/effects/seriously.kaleidoscope.js b/effects/seriously.kaleidoscope.js index a3bdf7f..fe47b37 100644 --- a/effects/seriously.kaleidoscope.js +++ b/effects/seriously.kaleidoscope.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; Seriously.plugin('kaleidoscope', { diff --git a/effects/seriously.layers.js b/effects/seriously.layers.js index 93e4326..50c7381 100644 --- a/effects/seriously.layers.js +++ b/effects/seriously.layers.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; var identity = new Float32Array([ diff --git a/effects/seriously.linear-transfer.js b/effects/seriously.linear-transfer.js index d0b1cf5..080f0b8 100644 --- a/effects/seriously.linear-transfer.js +++ b/effects/seriously.linear-transfer.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; Seriously.plugin('linear-transfer', { diff --git a/effects/seriously.lumakey.js b/effects/seriously.lumakey.js index e8b2332..1a6e224 100644 --- a/effects/seriously.lumakey.js +++ b/effects/seriously.lumakey.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; Seriously.plugin('lumakey', { diff --git a/effects/seriously.lut.js b/effects/seriously.lut.js new file mode 100644 index 0000000..0ebb535 --- /dev/null +++ b/effects/seriously.lut.js @@ -0,0 +1,87 @@ +/* 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); + } +}(window, function (Seriously) { + 'use strict'; + + Seriously.plugin('lut', { + commonShader: true, + shader: function (inputs, shaderSource) { + /* + Shader borrowed from Paul Golds @ BBC R&D, with permission + */ + shaderSource.fragment = [ + 'precision mediump float;', + + 'varying vec2 vTexCoord;', + + 'uniform sampler2D source;', + 'uniform sampler2D lut;', + 'uniform float amount;', + + 'void main(void) {', + + ' vec4 textureColor = texture2D(source, vTexCoord);', + ' textureColor = clamp(textureColor, 0.0, 1.0);', + + ' float blueColor = textureColor.b * 63.0;', + + ' vec2 quad1;', + ' quad1.y = floor(floor(blueColor) / 8.0);', + ' quad1.x = floor(blueColor) - (quad1.y * 8.0);', + + ' vec2 quad2;', + ' quad2.y = floor(ceil(blueColor) / 8.0);', + ' quad2.x = ceil(blueColor) - (quad2.y * 8.0);', + + ' vec2 texPos1;', + ' texPos1 = (quad1 * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.rg);', + + ' vec2 texPos2;', + ' texPos2 = (quad2 * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.rg);', + + ' lowp vec4 newColor1 = texture2D(lut, vec2(texPos1.x, 1.0 - texPos1.y));', + ' lowp vec4 newColor2 = texture2D(lut, vec2(texPos2.x, 1.0 - texPos2.y));', + + ' vec4 newColor = mix(newColor1, newColor2, fract(blueColor));', + + ' gl_FragColor = mix(textureColor, newColor, amount);', + '}' + ].join('\n'); + return shaderSource; + }, + inPlace: true, + inputs: { + source: { + type: 'image', + uniform: 'source' + }, + lut: { + type: 'image', + uniform: 'lut' + }, + amount: { + type: 'number', + uniform: 'amount', + min: 0, + max: 1, + defaultValue: 1 + } + }, + title: 'Color Look-Up Table', + description: '' + }); +})); diff --git a/effects/seriously.mirror.js b/effects/seriously.mirror.js index d78ae80..e29ccc2 100644 --- a/effects/seriously.mirror.js +++ b/effects/seriously.mirror.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; Seriously.plugin('mirror', { diff --git a/effects/seriously.nightvision.js b/effects/seriously.nightvision.js index eeae7fe..f2800fa 100644 --- a/effects/seriously.nightvision.js +++ b/effects/seriously.nightvision.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; //based on tutorial: http://www.geeks3d.com/20091009/shader-library-night-vision-post-processing-filter-glsl/ @@ -29,7 +29,7 @@ 'varying vec2 vTexCoord;', 'uniform sampler2D source;', - 'uniform float timer;', + 'uniform float time;', 'uniform float luminanceThreshold;', 'uniform float amplification;', 'uniform vec3 nightVisionColor;', @@ -38,9 +38,9 @@ 'void main(void) {', ' vec3 noise = vec3(' + - 'makeNoise(vTexCoord.x, vTexCoord.y, timer), ' + - 'makeNoise(vTexCoord.x, vTexCoord.y, timer * 200.0 + 1.0), ' + - 'makeNoise(vTexCoord.x, vTexCoord.y, timer * 100.0 + 3.0)' + + 'makeNoise(vTexCoord.x, vTexCoord.y, time), ' + + 'makeNoise(vTexCoord.x, vTexCoord.y, time * 200.0 + 1.0), ' + + 'makeNoise(vTexCoord.x, vTexCoord.y, time * 100.0 + 3.0)' + ');', ' vec4 pixel = texture2D(source, vTexCoord + noise.xy * 0.0025);', ' float luminance = dot(vec3(0.299, 0.587, 0.114), pixel.rgb);', @@ -56,10 +56,11 @@ uniform: 'source', shaderDirty: false }, - timer: { + time: { type: 'number', - uniform: 'timer', - defaultValue: 0 + uniform: 'time', + defaultValue: 0, + mod: 65536 }, luminanceThreshold: { type: 'number', diff --git a/effects/seriously.noise.js b/effects/seriously.noise.js index 2fdb984..42df1f6 100644 --- a/effects/seriously.noise.js +++ b/effects/seriously.noise.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; Seriously.plugin('noise', { @@ -31,7 +31,7 @@ 'uniform vec2 resolution;', 'uniform float amount;', - 'uniform float timer;', + 'uniform float time;', utilities.shader.noiseHelpers, utilities.shader.snoise3d, @@ -39,8 +39,8 @@ 'void main(void) {', ' vec4 pixel = texture2D(source, vTexCoord);', - ' float r = random(vec2(timer * vTexCoord.xy));', - ' float noise = snoise(vec3(vTexCoord * (1024.4 + r * 512.0), timer)) * 0.5;' + ' float r = random(vec2(time * vTexCoord.xy));', + ' float noise = snoise(vec3(vTexCoord * (1024.4 + r * 512.0), time)) * 0.5;' ]; if (inputs.overlay) { @@ -73,11 +73,11 @@ max: 1, defaultValue: 1 }, - timer: { + time: { type: 'number', - uniform: 'timer', + uniform: 'time', defaultValue: 0, - step: 1 + mod: 65536 } }, title: 'Noise', diff --git a/effects/seriously.opticalflow.js b/effects/seriously.opticalflow.js new file mode 100644 index 0000000..b4ce2eb --- /dev/null +++ b/effects/seriously.opticalflow.js @@ -0,0 +1,145 @@ +/* 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); + } +}(window, function (Seriously) { + 'use strict'; + + /* + Horn-Schunke Optical Flow + Based on shader by Andrew Benson + https://github.com/v002/v002-Optical-Flow/blob/master/v002.GPUHSFlow.frag + + Creative Commons, Attribution – Non Commercial – Share Alike 3.0 + http://v002.info/licenses/ + */ + + Seriously.plugin('opticalflow', function () { + var previousFrameBuffer, + baseShader; + + return { + initialize: function (initialize) { + previousFrameBuffer = new Seriously.util.FrameBuffer(this.gl, this.width, this.height); + initialize(); + baseShader = this.baseShader; + }, + resize: function () { + previousFrameBuffer.resize(this.width, this.height); + }, + commonShader: true, + shader: function (inputs, shaderSource) { + shaderSource.fragment = [ + 'precision mediump float;', + + 'varying vec2 vTexCoord;', + + 'uniform sampler2D source;', + 'uniform sampler2D previous;', + 'uniform vec2 resolution;', + + 'uniform vec2 scale;', + 'uniform float offsetX;', + 'uniform float lambda;', + // 'const vec4 lumcoeff = vec4(0.299, 0.587, 0.114, 0.0);', + + 'void main() {', + ' vec4 a = texture2D(previous, vTexCoord);', + ' vec4 b = texture2D(source, vTexCoord);', + ' vec2 offset = offsetX / resolution;', + ' vec2 x1 = vec2(offset.x, 0.0);', + ' vec2 y1 = vec2(0.0, offset.y);', + + //get the difference + ' vec4 curdif = b - a;', + + //calculate the gradient + ' vec4 gradx = texture2D(source, vTexCoord + x1) - texture2D(source, vTexCoord - x1);', + ' gradx += texture2D(previous, vTexCoord + x1) - texture2D(previous, vTexCoord - x1);', + + ' vec4 grady = texture2D(source, vTexCoord + y1) - texture2D(source, vTexCoord - y1);', + ' grady += texture2D(previous, vTexCoord + y1) - texture2D(previous, vTexCoord - y1);', + + ' vec4 gradmag = sqrt((gradx * gradx) + (grady * grady) + vec4(lambda));', + + ' vec4 vx = curdif * (gradx / gradmag);', + ' float vxd = vx.r;', //assumes greyscale + + //format output for flowrepos, out(-x,+x,-y,+y) + ' vec2 xout = vec2(max(vxd, 0.0), abs(min(vxd, 0.0))) * scale.x;', + + ' vec4 vy = curdif * (grady / gradmag);', + ' float vyd = vy.r;', //assumes greyscale + + //format output for flowrepos, out(-x,+x,-y,+y) + ' vec2 yout = vec2(max(vyd, 0.0), abs(min(vyd, 0.0))) * scale.y;', + + ' gl_FragColor = clamp(vec4(xout.xy, yout.xy), 0.0, 1.0);', + ' gl_FragColor.a = 1.0;', + '}' + ].join('\n'); + + return shaderSource; + }, + draw: function (shader, model, uniforms, frameBuffer, parent) { + uniforms.previous = previousFrameBuffer.texture; + + parent(shader, model, uniforms, frameBuffer); + + //todo: just swap buffers rather than copy? + parent(baseShader, model, uniforms, previousFrameBuffer.frameBuffer); + }, + destroy: function () { + if (previousFrameBuffer) { + previousFrameBuffer.destroy(); + previousFrameBuffer = null; + } + } + }; + }, + { + inPlace: false, + inputs: { + source: { + type: 'image', + uniform: 'source', + shaderDirty: false + }, + lambda: { + type: 'number', + uniform: 'lambda', + min: 0, + defaultValue: 0, + description: 'noise limiting' + }, + scaleResult: { + type: 'vector', + dimensions: 2, + uniform: 'scale', + defaultValue: [1, 1] + }, + offset: { + type: 'number', + uniform: 'offsetX', + defaultValue: 1, + min: 1, + max: 100, + description: 'distance between texel samples for gradient calculation' + } + }, + description: 'Horn-Schunke Optical Flow', + title: 'Optical Flow' + }); +})); diff --git a/effects/seriously.panorama.js b/effects/seriously.panorama.js index b518a20..fa6d1a5 100644 --- a/effects/seriously.panorama.js +++ b/effects/seriously.panorama.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; Seriously.plugin('panorama', function () { diff --git a/effects/seriously.pixelate.js b/effects/seriously.pixelate.js index 3db971c..1c8d70a 100644 --- a/effects/seriously.pixelate.js +++ b/effects/seriously.pixelate.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; Seriously.plugin('pixelate', { diff --git a/effects/seriously.polar.js b/effects/seriously.polar.js index 1af9278..43782dc 100644 --- a/effects/seriously.polar.js +++ b/effects/seriously.polar.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; Seriously.plugin('polar', { diff --git a/effects/seriously.repeat.js b/effects/seriously.repeat.js index b88af9f..701f7b7 100644 --- a/effects/seriously.repeat.js +++ b/effects/seriously.repeat.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; var identity = new Float32Array([ diff --git a/effects/seriously.ripple.js b/effects/seriously.ripple.js index bb26c1f..36d3898 100644 --- a/effects/seriously.ripple.js +++ b/effects/seriously.ripple.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; //http://msdn.microsoft.com/en-us/library/bb313868(v=xnagamestudio.10).aspx diff --git a/effects/seriously.scanlines.js b/effects/seriously.scanlines.js index 43240d5..ca36556 100644 --- a/effects/seriously.scanlines.js +++ b/effects/seriously.scanlines.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; Seriously.plugin('scanlines', { diff --git a/effects/seriously.select.js b/effects/seriously.select.js index bed1a63..c44ec7e 100644 --- a/effects/seriously.select.js +++ b/effects/seriously.select.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; var intRegex = /\d+/; diff --git a/effects/seriously.sepia.js b/effects/seriously.sepia.js index d7c6ce1..05909f3 100644 --- a/effects/seriously.sepia.js +++ b/effects/seriously.sepia.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; // sepia coefficients borrowed from: diff --git a/effects/seriously.simplex.js b/effects/seriously.simplex.js index d9d2285..b40d968 100644 --- a/effects/seriously.simplex.js +++ b/effects/seriously.simplex.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; Seriously.plugin('simplex', function () { diff --git a/effects/seriously.sketch.js b/effects/seriously.sketch.js index 6061c29..8f04999 100644 --- a/effects/seriously.sketch.js +++ b/effects/seriously.sketch.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; /* inspired by http://lab.adjazent.com/2009/01/09/more-pixel-bender/ */ diff --git a/effects/seriously.split.js b/effects/seriously.split.js index b022d6d..9c74197 100644 --- a/effects/seriously.split.js +++ b/effects/seriously.split.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; Seriously.plugin('split', function () { @@ -156,18 +156,22 @@ 'uniform float split;', 'uniform float angle;', 'uniform float fuzzy;', + 'uniform float blendGamma;', - 'vec4 textureLookup(sampler2D tex, vec2 texCoord) {', + 'vec4 textureLookup(sampler2D tex, vec2 texCoord, vec3 exp) {', ' if (any(lessThan(texCoord, vec2(0.0))) || any(greaterThan(texCoord, vec2(1.0)))) {', ' return vec4(0.0);', ' } else {', - ' return texture2D(tex, texCoord);', + ' vec4 pixel = texture2D(tex, texCoord);', + ' pixel.rgb = pow(pixel.rgb, exp);', + ' return pixel;', ' }', '}', 'void main(void) {', - ' vec4 pixel1 = textureLookup(sourceA, vTexCoordA);', - ' vec4 pixel2 = textureLookup(sourceB, vTexCoordB);', + ' vec3 exp = vec3(blendGamma);', + ' vec4 pixel1 = textureLookup(sourceA, vTexCoordA, exp);', + ' vec4 pixel2 = textureLookup(sourceB, vTexCoordB, exp);', ' float mn = (split - fuzzy * (1.0 - split));', ' float mx = (split + fuzzy * split);;', ' vec2 coords = vTexCoord - vec2(0.5);', @@ -175,8 +179,9 @@ ' float scale = max(abs(c - s), abs(s + c));', ' coords /= scale;', ' coords += vec2(0.5);', - ' float x = coords.x;;', + ' float x = coords.x;', ' gl_FragColor = mix(pixel2, pixel1, smoothstep(mn, mx, x));', + ' gl_FragColor.rgb = pow(gl_FragColor.rgb, 1.0 / exp);', '}' ].join('\n'); @@ -261,6 +266,13 @@ defaultValue: 0, min: 0, max: 1 + }, + blendGamma: { + type: 'number', + uniform: 'blendGamma', + defaultValue: 2.2, + min: 0, + max: 4 } }, description: 'Split screen or wipe', diff --git a/effects/seriously.temperature.js b/effects/seriously.temperature.js new file mode 100644 index 0000000..7586bad --- /dev/null +++ b/effects/seriously.temperature.js @@ -0,0 +1,101 @@ +/* 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); + } +}(window, function (Seriously) { + 'use strict'; + + // algorithm from http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/ + + Seriously.plugin('temperature', { + commonShader: true, + shader: function (inputs, shaderSource) { + shaderSource.vertex = [ + 'precision mediump float;', + + 'attribute vec4 position;', + 'attribute vec2 texCoord;', + + 'uniform vec2 resolution;', + 'uniform mat4 transform;', + + 'uniform float temperature;', + + 'varying vec2 vTexCoord;', + 'varying vec3 tempFactor;', + + 'const vec3 luma = vec3(0.2125,0.7154,0.0721);', + + 'vec3 temperatureRGB(float t) {', + ' float temp = t / 100.0;', + ' vec3 color = vec3(1.0);', + ' if (temp < 66.0) {', + ' color.g = 0.3900815787690196 * log(temp) - 0.6318414437886275;', + ' color.b = 0.543206789110196 * log(temp - 10.0) - 1.19625408914;', + ' } else {', + ' color.r = 1.292936186062745 * pow(temp - 60.0, -0.1332047592);', + ' color.g = 1.129890860895294 * pow(temp - 60.0, -0.0755148492);', + ' }', + ' return color;', + '}', + + 'void main(void) {', + // first convert to screen space + ' vec4 screenPosition = vec4(position.xy * resolution / 2.0, position.z, position.w);', + ' screenPosition = transform * screenPosition;', + + // convert back to OpenGL coords + ' gl_Position.xy = screenPosition.xy * 2.0 / resolution;', + ' gl_Position.z = screenPosition.z * 2.0 / (resolution.x / resolution.y);', + ' gl_Position.w = screenPosition.w;', + ' vTexCoord = texCoord;', + ' vec3 tempColor = temperatureRGB(temperature);', + ' tempFactor = dot(tempColor, luma) / tempColor;', + '}\n' + ].join('\n'); + + shaderSource.fragment = [ + 'precision mediump float;', + + 'varying vec2 vTexCoord;', + 'varying vec3 tempFactor;', + + 'uniform sampler2D source;', + + 'void main(void) {', + ' vec4 pixel = texture2D(source, vTexCoord);', + ' gl_FragColor = vec4(pixel.rgb * tempFactor, pixel.a);', + '}' + ].join('\n'); + return shaderSource; + }, + inPlace: true, + inputs: { + source: { + type: 'image', + uniform: 'source' + }, + temperature: { + type: 'number', + uniform: 'temperature', + defaultValue: 6500, + min: 3000, + max: 25000 + } + }, + title: 'Color Temperature', + description: '' + }); +})); diff --git a/effects/seriously.throttle.js b/effects/seriously.throttle.js index 9d8d16e..402965c 100644 --- a/effects/seriously.throttle.js +++ b/effects/seriously.throttle.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; Seriously.plugin('throttle', function () { diff --git a/effects/seriously.tone.js b/effects/seriously.tone.js index b233439..67cf45e 100644 --- a/effects/seriously.tone.js +++ b/effects/seriously.tone.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; Seriously.plugin('tone', { diff --git a/effects/seriously.tvglitch.js b/effects/seriously.tvglitch.js index 333383a..4034abc 100644 --- a/effects/seriously.tvglitch.js +++ b/effects/seriously.tvglitch.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; //particle parameters @@ -63,6 +63,7 @@ particleBuffer.numItems = particleCount; particleVertex = [ + '#define SHADER_NAME seriously.tvglitch.particle', 'precision mediump float;', 'attribute vec4 particle;', @@ -83,6 +84,7 @@ ].join('\n'); particleFragment = [ + '#define SHADER_NAME seriously.tvglitch.particle', 'precision mediump float;', 'varying float intensity;', @@ -129,7 +131,7 @@ ' vec2 texCoord = vTexCoord;', //distortion - ' float drandom = snoise(vec2(time * 50.0, texCoord.y /lineHeight));', + ' float drandom = snoise(vec2(time * 10.0, texCoord.y /lineHeight));', ' float distortAmount = distortion * (drandom - 0.25) * 0.5;', //line sync ' vec4 particleOffset = texture2D(particles, vec2(0.0, texCoord.y));', @@ -208,7 +210,7 @@ gl.vertexAttribPointer(particleShader.location.particle, particleBuffer.itemSize, gl.FLOAT, false, 0, 0); gl.enable(gl.BLEND); gl.blendFunc(gl.SRC_ALPHA, gl.ONE); - particleShader.time.set(uniforms.time); + particleShader.time.set(uniforms.time * this.inputs.barsRate); particleShader.height.set(this.height); gl.drawArrays(gl.POINTS, 0, particleCount); @@ -272,6 +274,10 @@ min: 0, max: 1 }, + barsRate: { + type: 'number', + defaultValue: 1 + }, frameShape: { type: 'number', uniform: 'frameShape', diff --git a/effects/seriously.vibrance.js b/effects/seriously.vibrance.js index 76c6516..85ff7e7 100644 --- a/effects/seriously.vibrance.js +++ b/effects/seriously.vibrance.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; /* diff --git a/effects/seriously.vignette.js b/effects/seriously.vignette.js index 9ffaae0..62e5e19 100644 --- a/effects/seriously.vignette.js +++ b/effects/seriously.vignette.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; Seriously.plugin('vignette', { diff --git a/effects/seriously.whitebalance.js b/effects/seriously.whitebalance.js index 47adc17..c549bb7 100644 --- a/effects/seriously.whitebalance.js +++ b/effects/seriously.whitebalance.js @@ -14,7 +14,7 @@ } factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; /* diff --git a/examples/accumulator/index.html b/examples/accumulator/index.html index e202b10..060e441 100644 --- a/examples/accumulator/index.html +++ b/examples/accumulator/index.html @@ -117,6 +117,7 @@ accumulator.blendMode = '#mode'; accumulator.opacity = '#opacity'; + accumulator.startColor = 'black'; reformat.source = '#image'; move.source = reformat; diff --git a/examples/blur/blur.html b/examples/blur/blur.html index 8f3b155..8fdc752 100644 --- a/examples/blur/blur.html +++ b/examples/blur/blur.html @@ -52,11 +52,7 @@ target, // a wrapper object for our target canvas reformat, - lastRender = 0, oscillating = false, - direction = 1, - amount, - x, control = document.getElementById('amount'), canvas = document.getElementById('canvas'), @@ -96,21 +92,15 @@ seriously.go(function (now) { // callback runs before render + var amount; rS('rAF').tick(); rS('FPS').frame(); if (oscillating) { - if (lastRender) { - if (amount <= 0.01 || amount >= 0.99) { - direction *= -1; - } - x += direction * (now - lastRender) * Math.PI / 1000; - amount = (1 - Math.cos(x)) / 2; - control.value = amount; - blur.amount = amount; - } - lastRender = now; + amount = (1 - Math.cos(now * Math.PI / 1000)) / 2; + control.value = amount; + blur.amount = amount; } }, function () { // callback runs after render @@ -120,7 +110,6 @@ document.getElementById('button').addEventListener('click', function () { if (oscillating) { oscillating = false; - lastRender = 0; // set back to manual control blur.amount = control; @@ -128,13 +117,6 @@ this.innerHTML = 'Oscillate: Start'; } else { oscillating = true; - - // take over manual control - amount = parseFloat(control.value); - - // figure out where in the oscillating cycle we are - x = Math.acos(1 - 2 * amount); - this.innerHTML = 'Oscillate: Stop'; } }); diff --git a/examples/channels/index.html b/examples/channels/index.html index ff769d0..08a16a5 100644 --- a/examples/channels/index.html +++ b/examples/channels/index.html @@ -3,9 +3,22 @@ <head> <title>Seriously.js Channels Example</title> <style type="text/css"> + body { + margin: 0; + padding: 0; + } + img { display: none; } + + #canvas { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + } </style> </head> <body> @@ -36,14 +49,64 @@ mask = document.createElement('canvas'), ctx = mask.getContext('2d'); + function resize() { + target.width = window.innerWidth; + target.height = window.innerHeight; + scalePencils.width = target.width; + scalePencils.height = target.height; + scaleRobot.width = target.width; + scaleRobot.height = target.height; + resizeMask.width = target.width; + resizeMask.height = target.height; + } + + function setPosition(pageX, pageY) { + var canvas = target.original, + x = pageX - canvas.offsetLeft, + y = pageY - canvas.offsetTop; + + moveMask.translateX = x - canvas.width / 2; + moveMask.translateY = canvas.height / 2 - y; + } + + function mouseMove(evt) { + setPosition(evt.pageX, evt.pageY); + } + + function touchStart(evt) { + function update(touch) { + setPosition(touch.pageX, touch.pageY); + } + + function touchMove(evt) { + update(evt.changedTouches[0]); + evt.preventDefault(); + } + + function touchEnd() { + document.body.removeEventListener('touchmove', touchMove, false); + document.body.removeEventListener('touchend', touchEnd, false); + } + + evt.preventDefault(); + if (evt.touches.length !== 1) { + return; + } + + document.body.addEventListener('touchmove', touchMove, false); + document.body.addEventListener('touchend', touchEnd, false); + + update(evt.touches[0]); + } + seriously = new Seriously(); target = seriously.target('#canvas'); channels = seriously.effect('channels'); blend = seriously.effect('blend'); - scaleRobot = seriously.transform('2d'); + scaleRobot = seriously.transform('reformat'); scaleRobot.source = seriously.source('#robot'); - scaleRobot.scale(640/989); + scaleRobot.mode = 'cover'; scalePencils = seriously.transform('reformat'); scalePencils.source = seriously.source('#pencils'); @@ -62,8 +125,6 @@ resizeMask = seriously.transform('reformat'); resizeMask.source = mask; - resizeMask.width = target.width; - resizeMask.height = target.height; moveMask = seriously.transform(); moveMask.source = resizeMask; @@ -81,14 +142,13 @@ target.source = blend; - window.addEventListener('mousemove', function (evt) { - var canvas = target.original, - x = evt.pageX - canvas.offsetLeft, - y = evt.pageY - canvas.offsetTop; + window.addEventListener('mousemove', mouseMove, false); + document.body.addEventListener('touchstart', touchStart, true); - moveMask.translateX = x - canvas.width / 2; - moveMask.translateY = canvas.height / 2 - y; - }, false); + window.addEventListener('resize', resize, false); + window.addEventListener('deviceorientation', resize, false); + + resize(); seriously.go(function (now) { moveMask.rotation = (now % 18000) / 50; diff --git a/examples/color/linear-transfer.html b/examples/color/linear-transfer.html index a669c19..f9f43de 100644 --- a/examples/color/linear-transfer.html +++ b/examples/color/linear-transfer.html @@ -1,7 +1,7 @@ <!DOCTYPE html> <html> <head> - <title>Seriously.js Blur Example</title> + <title>Seriously.js Linear Color Transfer Example</title> <style type="text/css"> img { display: none; diff --git a/examples/color/lut.html b/examples/color/lut.html new file mode 100644 index 0000000..a8657e0 --- /dev/null +++ b/examples/color/lut.html @@ -0,0 +1,83 @@ +<!DOCTYPE html> +<html> +<head> + <title>Seriously.js Color Look-Up Table Example</title> + <style type="text/css"> + img { + display: none; + } + + #controls { + display: inline-block; + vertical-align: top; + } + + #controls input { + width: 400px; + } + + label { + display: block; + } + </style> +</head> +<body> + <img src="../../examples/images/robot.jpg" id="robot"/> + <img src="../../examples/images/lut_cyanspike.png" id="cyanspike"/> + <img src="../../examples/images/lut_lockstock.png" id="lockstock"/> + <img src="../../examples/images/lut_supervivid.png" id="supervivid"/> + <canvas id="canvas" width="640" height="619"></canvas> + <div id="controls"> + <div> + <label>Look-Up Table + <select id="lut"> + <option value="">Original</option> + <option value="cyanspike">Cyan Spike</option> + <option value="lockstock">Lock Stock</option> + <option value="supervivid">Super Vivid</option> + </select> + </label> + </div> + <div> + <label>Amount <input type="range" id="amount" min="0" max="1" step="0.001" value="1"/></label> + </div> + </div> + <script src="../../lib/require.js"></script> + <script> + require.config({ + baseUrl: '../../' + }); + + require([ + 'seriously', + 'effects/seriously.lut' + ], function (Seriously) { + var seriously, // the main object that holds the entire composition + effect, + target, // a wrapper object for our target canvas + selectLut = document.getElementById('lut'); + + function selectTable() { + if (selectLut.value) { + effect.lut = document.getElementById(selectLut.value); + target.source = effect; + } else { + target.source = '#robot'; + } + } + + seriously = new Seriously(); + target = seriously.target('#canvas'); + + effect = seriously.effect('lut'); + effect.source = '#robot'; + effect.amount = '#amount'; + + selectLut.onchange = selectTable; + selectTable(); + + seriously.go(); + }); + </script> +</body> +</html> diff --git a/examples/demo/drunk.html b/examples/demo/drunk.html index 65735ba..4052ec9 100644 --- a/examples/demo/drunk.html +++ b/examples/demo/drunk.html @@ -40,12 +40,7 @@ target, // a wrapper object for our target canvas shake, reformat, - accumulator, - x = 0, - y = 0, - vx = 0, - vy = 0, - lastFrameTime = Date.now(); + accumulator; function resize() { var aspect = window.innerWidth / window.innerHeight; diff --git a/examples/demo/threejs-source.html b/examples/demo/threejs-source.html index e6bd889..4586f48 100644 --- a/examples/demo/threejs-source.html +++ b/examples/demo/threejs-source.html @@ -210,7 +210,8 @@ scene.add(light); map = THREE.ImageUtils.loadTexture('../images/colorbars.png'); - map.wrapS = map.wrapT = THREE.RepeatWrapping; + map.wrapS = map.wrapT = THREE.ClampToEdgeWrapping; + map.minFilter = THREE.LinearFilter; map.anisotropy = 16; material = new THREE.MeshLambertMaterial({ @@ -235,7 +236,7 @@ object.position.set(200, 0, 200); scene.add(object); - object = new THREE.Mesh(new THREE.PlaneGeometry(100, 100, 4, 4), material); + object = new THREE.Mesh(new THREE.PlaneBufferGeometry(100, 100, 4, 4), material); object.position.set(-400, 0, 0); scene.add(object); diff --git a/examples/demo/threejs-target.html b/examples/demo/threejs-target.html index be68f70..3c74974 100644 --- a/examples/demo/threejs-target.html +++ b/examples/demo/threejs-target.html @@ -31,6 +31,7 @@ <script src="../../sources/seriously.three.js"></script> <script src="../../effects/seriously.simplex.js"></script> <script src="../../effects/seriously.tvglitch.js"></script> + <script src="../../effects/seriously.checkerboard.js"></script> <script src="../../targets/seriously.three.js"></script> <script> (function () { @@ -43,6 +44,7 @@ glitch, noiseTarget, glitchTarget, + checkerTarget, // three.js scene scene, @@ -50,6 +52,7 @@ renderer, noiseTexture, glitchTexture, + checkerTexture, pixelRatio = window.devicePixelRatio || 1, outputWidth, @@ -89,7 +92,6 @@ ambient, map, object, - material, points, i; @@ -129,25 +131,33 @@ glitchTexture.wrapS = noiseTexture.wrapT = THREE.RepeatWrapping; glitchTexture.anisotropy = 16; - material = new THREE.MeshLambertMaterial({ - ambient: 0xffffff, - map: noiseTexture, - side: THREE.DoubleSide - }); + checkerTexture = new THREE.WebGLRenderTarget( + 512, + 512, + { + minFilter: THREE.LinearFilter, + magFilter: THREE.NearestFilter, + format: THREE.RGBAFormat + } + ); + checkerTexture.wrapS = checkerTexture.wrapT = THREE.RepeatWrapping; + checkerTexture.anisotropy = 16; + //simplex noise box object = new THREE.Mesh( new THREE.BoxGeometry(200, 200, 200, 4, 4, 4), new THREE.MeshLambertMaterial({ ambient: 0xffffff, map: noiseTexture, - side: THREE.DoubleSide + transparent: true }) ); object.position.set(200, 0, 0); scene.add(object); + //tv glitch plane object = new THREE.Mesh( - new THREE.PlaneGeometry(300, 300), + new THREE.PlaneBufferGeometry(300, 300), new THREE.MeshLambertMaterial({ ambient: 0xffffff, map: glitchTexture, @@ -157,6 +167,19 @@ object.position.set(-200, 0, 0); scene.add(object); + //checkerboard plane + object = new THREE.Mesh( + new THREE.PlaneBufferGeometry(800, 800), + new THREE.MeshLambertMaterial({ + ambient: 0xffffff, + map: checkerTexture, + side: THREE.DoubleSide + }) + ); + object.position.set(0, -150, 0); + object.rotateX(Math.PI / 2); + scene.add(object); + renderer = new THREE.WebGLRenderer({ canvas: canvas }); @@ -166,11 +189,13 @@ */ renderer.setRenderTarget(noiseTexture); renderer.setRenderTarget(glitchTexture); + renderer.setRenderTarget(checkerTexture); } // set up composition function initSeriouslyComps() { - var reformat; + var reformat, + checkerboard; seriously = new Seriously(); @@ -178,6 +203,7 @@ simplex.width = 512; simplex.height = 512; simplex.white = 'blue'; + simplex.black = 'rgba(0, 0, 0, 0.5)'; simplex.noiseScale = 2; timedEffects.push(simplex); @@ -195,12 +221,23 @@ glitch = seriously.effect('tvglitch'); glitch.verticalSync = 0; glitch.source = reformat; - timedEffects.push(glitch) + timedEffects.push(glitch); glitchTarget = seriously.target(glitchTexture, { canvas: canvas }); glitchTarget.source = glitch; + + checkerboard = seriously.effect('checkerboard'); + checkerboard.width = 512; + checkerboard.height = 512; + checkerboard.size = [8, 8]; + checkerboard.color1 = '#330000'; + checkerboard.color2 = '#666'; + checkerTarget = seriously.target(checkerTexture, { + canvas: canvas + }); + checkerTarget.source = checkerboard; } window.onresize = resize; diff --git a/examples/images/README.md b/examples/images/README.md index 7876bf6..9d065d6 100644 --- a/examples/images/README.md +++ b/examples/images/README.md @@ -17,4 +17,11 @@ Attribution-NonCommercial-ShareAlike 2.0 Generic (CC BY-NC-SA 2.0) ## Panorama by Jimmy Ferbuson -http://www.jwjferguson.com \ No newline at end of file +http://www.jwjferguson.com + +## Color Look-Up Talbes +by Ian Forrester +http://www.bbc.co.uk/rd/people/ianforrester +- Cyan Spike +- Lock Stock +- Super Vivid \ No newline at end of file diff --git a/examples/images/lut_cyanspike.png b/examples/images/lut_cyanspike.png new file mode 100644 index 0000000..11a1384 Binary files /dev/null and b/examples/images/lut_cyanspike.png differ diff --git a/examples/images/lut_lockstock.png b/examples/images/lut_lockstock.png new file mode 100644 index 0000000..848767e Binary files /dev/null and b/examples/images/lut_lockstock.png differ diff --git a/examples/images/lut_supervivid.png b/examples/images/lut_supervivid.png new file mode 100644 index 0000000..e666ee5 Binary files /dev/null and b/examples/images/lut_supervivid.png differ diff --git a/examples/index.html b/examples/index.html index 2d942b2..2b5c6f0 100644 --- a/examples/index.html +++ b/examples/index.html @@ -27,11 +27,18 @@ <li><a href="displace">Depth Map/Displacment</a></li> <li><a href="gradientwipe.html">Gradient Wipe</a></li> <li><a href="crop.html">Crop</a></li> - <li><a href="color/linear-transfer.html">Linear Color Transfer</a></li> + <li> + Color Adjustment + <ul> + <li><a href="color/linear-transfer.html">Linear Color Transfer</a></li> + <li><a href="color/lut.html">Look-Up Table</a></li> + </ul> + </li> <li><a href="target/multi-target.html">Multiple Canvas Targets</a></li> <li><a href="demo/select.html">Select</a></li> <li><a href="demo/drunk.html">Drunk</a></li> <li><a href="demo/fog.html">Fog</a></li> + <li><a href="opticalflow.html">Optical Flow</a></li> <li><a href="demo/panorama.html">Panorama</a></li> <li><a href="demo/threejs-source.html">Three.js Source</a></li> <li><a href="demo/threejs-target.html">Three.js Target</a></li> diff --git a/examples/opticalflow.html b/examples/opticalflow.html new file mode 100644 index 0000000..5c6edcf --- /dev/null +++ b/examples/opticalflow.html @@ -0,0 +1,59 @@ +<!DOCTYPE html> +<html> +<head> + <title>Seriously.js Optical Flow Example</title> + <style type="text/css"> + #canvas { + max-width: 100%; + } + </style> +</head> +<body> + <canvas id="canvas" width="1280" height="720"></canvas> + <script src="../seriously.js"></script> + <script src="../sources/seriously.camera.js"></script> + <script src="../effects/seriously.opticalflow.js"></script> + <script> + (function() { + //main code goes here + + // declare our variables + var seriously, // the main object that holds the entire composition + camera, // wrapper object for source video + opticalflow, // mirror detection effect + target, // a wrapper object for our target canvas + reformat; + + if (Seriously.incompatible('camera')) { + document.body.appendChild(document.createTextNode('Sorry, your browser does not support getUserMedia')); + document.querySelector('canvas').style.display = 'none'; + return; + } + + // construct our seriously object + seriously = new Seriously(); + + camera = seriously.source('camera'/*, { + todo: refactor camera plugin for updated getUserMediaConstraints + video: { + width: 1280, + height: 720 + } + }*/); + target = seriously.target('#canvas'); + opticalflow = seriously.effect('opticalflow'); + reformat = seriously.transform('reformat'); + reformat.width = 1280; + reformat.height = 720; + reformat.mode = 'cover'; + + // connect all our nodes in the right order + reformat.source = camera; + opticalflow.source = reformat; + target.source = opticalflow; + + seriously.go(); + }()); + </script> +</body> +</html> diff --git a/index.html b/index.html index 37e5b3f..e6762ab 100644 --- a/index.html +++ b/index.html @@ -16,6 +16,7 @@ <script type="text/javascript" src="effects/seriously.color.js"></script> <script type="text/javascript" src="effects/seriously.colorcomplements.js"></script> <script type="text/javascript" src="effects/seriously.color-select.js"></script> + <script type="text/javascript" src="effects/seriously.temperature.js"></script> <script type="text/javascript" src="effects/seriously.daltonize.js"></script> <script type="text/javascript" src="effects/seriously.dither.js"></script> <script type="text/javascript" src="effects/seriously.edge.js"></script> @@ -35,6 +36,7 @@ <script type="text/javascript" src="effects/seriously.directionblur.js"></script> <script type="text/javascript" src="effects/seriously.nightvision.js"></script> <script type="text/javascript" src="effects/seriously.noise.js"></script> + <script type="text/javascript" src="effects/seriously.opticalflow.js"></script> <script type="text/javascript" src="effects/seriously.pixelate.js"></script> <script type="text/javascript" src="effects/seriously.polar.js"></script> <script type="text/javascript" src="effects/seriously.ripple.js"></script> @@ -193,11 +195,8 @@ target.source = transform3d; s.go(function () { - if (active && active.effect.timer !== undefined) { - active.effect.timer = Date.now(); - } if (active && active.effect.time !== undefined) { - active.effect.time = Date.now(); + active.effect.time = Date.now() / 1000; } }); diff --git a/lib/three.js b/lib/three.js index 636b15d..ae4b1be 100644 --- a/lib/three.js +++ b/lib/three.js @@ -4,7 +4,7 @@ * @author mrdoob / http://mrdoob.com/ */ -var THREE = { REVISION: '69' }; +var THREE = { REVISION: '71' }; // browserify support @@ -18,14 +18,23 @@ if ( typeof module === 'object' ) { if ( Math.sign === undefined ) { + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign + Math.sign = function ( x ) { - return ( x < 0 ) ? - 1 : ( x > 0 ) ? 1 : 0; + return ( x < 0 ) ? - 1 : ( x > 0 ) ? 1 : +x; }; } + +// set the default log handlers +THREE.log = function() { console.log.apply( console, arguments ); } +THREE.warn = function() { console.warn.apply( console, arguments ); } +THREE.error = function() { console.error.apply( console, arguments ); } + + // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent.button THREE.MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2 }; @@ -117,13 +126,15 @@ THREE.AddOperation = 2; // Mapping modes -THREE.UVMapping = function () {}; +THREE.UVMapping = 300; + +THREE.CubeReflectionMapping = 301; +THREE.CubeRefractionMapping = 302; -THREE.CubeReflectionMapping = function () {}; -THREE.CubeRefractionMapping = function () {}; +THREE.EquirectangularReflectionMapping = 303; +THREE.EquirectangularRefractionMapping = 304; -THREE.SphericalReflectionMapping = function () {}; -THREE.SphericalRefractionMapping = function () {}; +THREE.SphericalReflectionMapping = 305; // Wrapping modes @@ -149,6 +160,7 @@ THREE.UnsignedShortType = 1012; THREE.IntType = 1013; THREE.UnsignedIntType = 1014; THREE.FloatType = 1015; +THREE.HalfFloatType = 1025; // Pixel types @@ -164,6 +176,8 @@ THREE.RGBFormat = 1020; THREE.RGBAFormat = 1021; THREE.LuminanceFormat = 1022; THREE.LuminanceAlphaFormat = 1023; +// THREE.RGBEFormat handled as THREE.RGBAFormat in shaders +THREE.RGBEFormat = THREE.RGBAFormat; //1024; // DDS / ST3C Compressed texture formats @@ -181,6 +195,46 @@ THREE.RGBA_PVRTC_4BPPV1_Format = 2102; THREE.RGBA_PVRTC_2BPPV1_Format = 2103; +// DEPRECATED + +THREE.Projector = function () { + + THREE.error( 'THREE.Projector has been moved to /examples/js/renderers/Projector.js.' ); + + this.projectVector = function ( vector, camera ) { + + THREE.warn( 'THREE.Projector: .projectVector() is now vector.project().' ); + vector.project( camera ); + + }; + + this.unprojectVector = function ( vector, camera ) { + + THREE.warn( 'THREE.Projector: .unprojectVector() is now vector.unproject().' ); + vector.unproject( camera ); + + }; + + this.pickingRay = function ( vector, camera ) { + + THREE.error( 'THREE.Projector: .pickingRay() is now raycaster.setFromCamera().' ); + + }; + +}; + +THREE.CanvasRenderer = function () { + + THREE.error( 'THREE.CanvasRenderer has been moved to /examples/js/renderers/CanvasRenderer.js' ); + + this.domElement = document.createElement( 'canvas' ); + this.clear = function () {}; + this.render = function () {}; + this.setClearColor = function () {}; + this.setSize = function () {}; + +}; + // File:src/math/Color.js /** @@ -358,21 +412,27 @@ THREE.Color.prototype = { }, - copyGammaToLinear: function ( color ) { + copyGammaToLinear: function ( color, gammaFactor ) { - this.r = color.r * color.r; - this.g = color.g * color.g; - this.b = color.b * color.b; + if ( gammaFactor === undefined ) gammaFactor = 2.0; + + this.r = Math.pow( color.r, gammaFactor ); + this.g = Math.pow( color.g, gammaFactor ); + this.b = Math.pow( color.b, gammaFactor ); return this; }, - copyLinearToGamma: function ( color ) { + copyLinearToGamma: function ( color, gammaFactor ) { + + if ( gammaFactor === undefined ) gammaFactor = 2.0; - this.r = Math.sqrt( color.r ); - this.g = Math.sqrt( color.g ); - this.b = Math.sqrt( color.b ); + var safeInverse = ( gammaFactor > 0 ) ? ( 1.0 / gammaFactor ) : 1.0; + + this.r = Math.pow( color.r, safeInverse ); + this.g = Math.pow( color.g, safeInverse ); + this.b = Math.pow( color.b, safeInverse ); return this; @@ -551,10 +611,16 @@ THREE.Color.prototype = { }, - toArray: function () { + toArray: function ( array, offset ) { + + if ( array === undefined ) array = []; + if ( offset === undefined ) offset = 0; - return [ this.r, this.g, this.b ]; + array[ offset ] = this.r; + array[ offset + 1 ] = this.g; + array[ offset + 2 ] = this.b; + return array; }, clone: function () { @@ -957,7 +1023,7 @@ THREE.Quaternion.prototype = { if ( p !== undefined ) { - console.warn( 'THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.' ); + THREE.warn( 'THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.' ); return this.multiplyQuaternions( q, p ); } @@ -986,7 +1052,7 @@ THREE.Quaternion.prototype = { multiplyVector3: function ( vector ) { - console.warn( 'THREE.Quaternion: .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead.' ); + THREE.warn( 'THREE.Quaternion: .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead.' ); return vector.applyQuaternion( this ); }, @@ -1197,7 +1263,7 @@ THREE.Vector2.prototype = { if ( w !== undefined ) { - console.warn( 'THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' ); + THREE.warn( 'THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' ); return this.addVectors( v, w ); } @@ -1209,19 +1275,19 @@ THREE.Vector2.prototype = { }, - addVectors: function ( a, b ) { + addScalar: function ( s ) { - this.x = a.x + b.x; - this.y = a.y + b.y; + this.x += s; + this.y += s; return this; }, - addScalar: function ( s ) { + addVectors: function ( a, b ) { - this.x += s; - this.y += s; + this.x = a.x + b.x; + this.y = a.y + b.y; return this; @@ -1231,7 +1297,7 @@ THREE.Vector2.prototype = { if ( w !== undefined ) { - console.warn( 'THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' ); + THREE.warn( 'THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' ); return this.subVectors( v, w ); } @@ -1243,6 +1309,15 @@ THREE.Vector2.prototype = { }, + subScalar: function ( s ) { + + this.x -= s; + this.y -= s; + + return this; + + }, + subVectors: function ( a, b ) { this.x = a.x - b.x; @@ -1488,6 +1563,14 @@ THREE.Vector2.prototype = { }, + lerpVectors: function ( v1, v2, alpha ) { + + this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 ); + + return this; + + }, + equals: function ( v ) { return ( ( v.x === this.x ) && ( v.y === this.y ) ); @@ -1517,6 +1600,19 @@ THREE.Vector2.prototype = { }, + fromAttribute: function ( attribute, index, offset ) { + + if ( offset === undefined ) offset = 0; + + index = index * attribute.itemSize + offset; + + this.x = attribute.array[ index ]; + this.y = attribute.array[ index + 1 ]; + + return this; + + }, + clone: function () { return new THREE.Vector2( this.x, this.y ); @@ -1622,7 +1718,7 @@ THREE.Vector3.prototype = { if ( w !== undefined ) { - console.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' ); + THREE.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' ); return this.addVectors( v, w ); } @@ -1659,7 +1755,7 @@ THREE.Vector3.prototype = { if ( w !== undefined ) { - console.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' ); + THREE.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' ); return this.subVectors( v, w ); } @@ -1671,6 +1767,16 @@ THREE.Vector3.prototype = { return this; }, + + subScalar: function ( s ) { + + this.x -= s; + this.y -= s; + this.z -= s; + + return this; + + }, subVectors: function ( a, b ) { @@ -1686,7 +1792,7 @@ THREE.Vector3.prototype = { if ( w !== undefined ) { - console.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' ); + THREE.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' ); return this.multiplyVectors( v, w ); } @@ -1727,7 +1833,7 @@ THREE.Vector3.prototype = { if ( euler instanceof THREE.Euler === false ) { - console.error( 'THREE.Vector3: .applyEuler() now expects a Euler rotation rather than a Vector3 and order.' ); + THREE.error( 'THREE.Vector3: .applyEuler() now expects a Euler rotation rather than a Vector3 and order.' ); } @@ -2126,11 +2232,19 @@ THREE.Vector3.prototype = { }, + lerpVectors: function ( v1, v2, alpha ) { + + this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 ); + + return this; + + }, + cross: function ( v, w ) { if ( w !== undefined ) { - console.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' ); + THREE.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' ); return this.crossVectors( v, w ); } @@ -2237,19 +2351,19 @@ THREE.Vector3.prototype = { setEulerFromRotationMatrix: function ( m, order ) { - console.error( 'THREE.Vector3: .setEulerFromRotationMatrix() has been removed. Use Euler.setFromRotationMatrix() instead.' ); + THREE.error( 'THREE.Vector3: .setEulerFromRotationMatrix() has been removed. Use Euler.setFromRotationMatrix() instead.' ); }, setEulerFromQuaternion: function ( q, order ) { - console.error( 'THREE.Vector3: .setEulerFromQuaternion() has been removed. Use Euler.setFromQuaternion() instead.' ); + THREE.error( 'THREE.Vector3: .setEulerFromQuaternion() has been removed. Use Euler.setFromQuaternion() instead.' ); }, getPositionFromMatrix: function ( m ) { - console.warn( 'THREE.Vector3: .getPositionFromMatrix() has been renamed to .setFromMatrixPosition().' ); + THREE.warn( 'THREE.Vector3: .getPositionFromMatrix() has been renamed to .setFromMatrixPosition().' ); return this.setFromMatrixPosition( m ); @@ -2257,14 +2371,14 @@ THREE.Vector3.prototype = { getScaleFromMatrix: function ( m ) { - console.warn( 'THREE.Vector3: .getScaleFromMatrix() has been renamed to .setFromMatrixScale().' ); + THREE.warn( 'THREE.Vector3: .getScaleFromMatrix() has been renamed to .setFromMatrixScale().' ); return this.setFromMatrixScale( m ); }, getColumnFromMatrix: function ( index, matrix ) { - console.warn( 'THREE.Vector3: .getColumnFromMatrix() has been renamed to .setFromMatrixColumn().' ); + THREE.warn( 'THREE.Vector3: .getColumnFromMatrix() has been renamed to .setFromMatrixColumn().' ); return this.setFromMatrixColumn( index, matrix ); @@ -2294,7 +2408,7 @@ THREE.Vector3.prototype = { }, setFromMatrixColumn: function ( index, matrix ) { - + var offset = index * 4; var me = matrix.elements; @@ -2338,6 +2452,20 @@ THREE.Vector3.prototype = { }, + fromAttribute: function ( attribute, index, offset ) { + + if ( offset === undefined ) offset = 0; + + index = index * attribute.itemSize + offset; + + this.x = attribute.array[ index ]; + this.y = attribute.array[ index + 1 ]; + this.z = attribute.array[ index + 2 ]; + + return this; + + }, + clone: function () { return new THREE.Vector3( this.x, this.y, this.z ); @@ -2455,7 +2583,7 @@ THREE.Vector4.prototype = { if ( w !== undefined ) { - console.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' ); + THREE.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' ); return this.addVectors( v, w ); } @@ -2495,7 +2623,7 @@ THREE.Vector4.prototype = { if ( w !== undefined ) { - console.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' ); + THREE.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' ); return this.subVectors( v, w ); } @@ -2509,6 +2637,17 @@ THREE.Vector4.prototype = { }, + subScalar: function ( s ) { + + this.x -= s; + this.y -= s; + this.z -= s; + this.w -= s; + + return this; + + }, + subVectors: function ( a, b ) { this.x = a.x - b.x; @@ -2855,49 +2994,49 @@ THREE.Vector4.prototype = { } )(), - floor: function () { + floor: function () { - this.x = Math.floor( this.x ); - this.y = Math.floor( this.y ); - this.z = Math.floor( this.z ); - this.w = Math.floor( this.w ); + this.x = Math.floor( this.x ); + this.y = Math.floor( this.y ); + this.z = Math.floor( this.z ); + this.w = Math.floor( this.w ); - return this; + return this; - }, + }, - ceil: function () { + ceil: function () { - this.x = Math.ceil( this.x ); - this.y = Math.ceil( this.y ); - this.z = Math.ceil( this.z ); - this.w = Math.ceil( this.w ); + this.x = Math.ceil( this.x ); + this.y = Math.ceil( this.y ); + this.z = Math.ceil( this.z ); + this.w = Math.ceil( this.w ); - return this; + return this; - }, + }, - round: function () { + round: function () { - this.x = Math.round( this.x ); - this.y = Math.round( this.y ); - this.z = Math.round( this.z ); - this.w = Math.round( this.w ); + this.x = Math.round( this.x ); + this.y = Math.round( this.y ); + this.z = Math.round( this.z ); + this.w = Math.round( this.w ); - return this; + return this; - }, + }, - roundToZero: function () { + roundToZero: function () { - this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x ); - this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y ); - this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z ); - this.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w ); + this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x ); + this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y ); + this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z ); + this.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w ); - return this; + return this; - }, + }, negate: function () { @@ -2965,6 +3104,14 @@ THREE.Vector4.prototype = { }, + lerpVectors: function ( v1, v2, alpha ) { + + this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 ); + + return this; + + }, + equals: function ( v ) { return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) ); @@ -2998,6 +3145,21 @@ THREE.Vector4.prototype = { }, + fromAttribute: function ( attribute, index, offset ) { + + if ( offset === undefined ) offset = 0; + + index = index * attribute.itemSize + offset; + + this.x = attribute.array[ index ]; + this.y = attribute.array[ index + 1 ]; + this.z = attribute.array[ index + 2 ]; + this.w = attribute.array[ index + 3 ]; + + return this; + + }, + clone: function () { return new THREE.Vector4( this.x, this.y, this.z, this.w ); @@ -3111,7 +3273,7 @@ THREE.Euler.prototype = { }, - setFromRotationMatrix: function ( m, order ) { + setFromRotationMatrix: function ( m, order, update ) { var clamp = THREE.Math.clamp; @@ -3222,80 +3384,37 @@ THREE.Euler.prototype = { } else { - console.warn( 'THREE.Euler: .setFromRotationMatrix() given unsupported order: ' + order ) + THREE.warn( 'THREE.Euler: .setFromRotationMatrix() given unsupported order: ' + order ) } this._order = order; - this.onChangeCallback(); + if ( update !== false ) this.onChangeCallback(); return this; }, - setFromQuaternion: function ( q, order, update ) { - - var clamp = THREE.Math.clamp; - - // q is assumed to be normalized - - // http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m - - var sqx = q.x * q.x; - var sqy = q.y * q.y; - var sqz = q.z * q.z; - var sqw = q.w * q.w; - - order = order || this._order; - - if ( order === 'XYZ' ) { + setFromQuaternion: function () { - this._x = Math.atan2( 2 * ( q.x * q.w - q.y * q.z ), ( sqw - sqx - sqy + sqz ) ); - this._y = Math.asin( clamp( 2 * ( q.x * q.z + q.y * q.w ), - 1, 1 ) ); - this._z = Math.atan2( 2 * ( q.z * q.w - q.x * q.y ), ( sqw + sqx - sqy - sqz ) ); - - } else if ( order === 'YXZ' ) { - - this._x = Math.asin( clamp( 2 * ( q.x * q.w - q.y * q.z ), - 1, 1 ) ); - this._y = Math.atan2( 2 * ( q.x * q.z + q.y * q.w ), ( sqw - sqx - sqy + sqz ) ); - this._z = Math.atan2( 2 * ( q.x * q.y + q.z * q.w ), ( sqw - sqx + sqy - sqz ) ); - - } else if ( order === 'ZXY' ) { - - this._x = Math.asin( clamp( 2 * ( q.x * q.w + q.y * q.z ), - 1, 1 ) ); - this._y = Math.atan2( 2 * ( q.y * q.w - q.z * q.x ), ( sqw - sqx - sqy + sqz ) ); - this._z = Math.atan2( 2 * ( q.z * q.w - q.x * q.y ), ( sqw - sqx + sqy - sqz ) ); - - } else if ( order === 'ZYX' ) { - - this._x = Math.atan2( 2 * ( q.x * q.w + q.z * q.y ), ( sqw - sqx - sqy + sqz ) ); - this._y = Math.asin( clamp( 2 * ( q.y * q.w - q.x * q.z ), - 1, 1 ) ); - this._z = Math.atan2( 2 * ( q.x * q.y + q.z * q.w ), ( sqw + sqx - sqy - sqz ) ); - - } else if ( order === 'YZX' ) { - - this._x = Math.atan2( 2 * ( q.x * q.w - q.z * q.y ), ( sqw - sqx + sqy - sqz ) ); - this._y = Math.atan2( 2 * ( q.y * q.w - q.x * q.z ), ( sqw + sqx - sqy - sqz ) ); - this._z = Math.asin( clamp( 2 * ( q.x * q.y + q.z * q.w ), - 1, 1 ) ); - - } else if ( order === 'XZY' ) { + var matrix; - this._x = Math.atan2( 2 * ( q.x * q.w + q.y * q.z ), ( sqw - sqx + sqy - sqz ) ); - this._y = Math.atan2( 2 * ( q.x * q.z + q.y * q.w ), ( sqw + sqx - sqy - sqz ) ); - this._z = Math.asin( clamp( 2 * ( q.z * q.w - q.x * q.y ), - 1, 1 ) ); + return function ( q, order, update ) { - } else { + if ( matrix === undefined ) matrix = new THREE.Matrix4(); + matrix.makeRotationFromQuaternion( q ); + this.setFromRotationMatrix( matrix, order, update ); - console.warn( 'THREE.Euler: .setFromQuaternion() given unsupported order: ' + order ) + return this; - } + }; - this._order = order; + }(), - if ( update !== false ) this.onChangeCallback(); + setFromVector3: function ( v, order ) { - return this; + return this.set( v.x, v.y, v.z, order || this._order ); }, @@ -3312,7 +3431,6 @@ THREE.Euler.prototype = { }; - }(), equals: function ( euler ) { @@ -3334,9 +3452,30 @@ THREE.Euler.prototype = { }, - toArray: function () { + toArray: function ( array, offset ) { + + if ( array === undefined ) array = []; + if ( offset === undefined ) offset = 0; + + array[ offset ] = this._x; + array[ offset + 1 ] = this._y; + array[ offset + 2 ] = this._z; + array[ offset + 3 ] = this._order; + + return array; + }, + + toVector3: function ( optionalResult ) { + + if ( optionalResult ) { + + return optionalResult.set( this._x, this._y, this._z ); + + } else { + + return new THREE.Vector3( this._x, this._y, this._z ); - return [ this._x, this._y, this._z, this._order ]; + } }, @@ -4100,7 +4239,7 @@ THREE.Matrix3 = function () { if ( arguments.length > 0 ) { - console.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' ); + THREE.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' ); } @@ -4154,14 +4293,14 @@ THREE.Matrix3.prototype = { multiplyVector3: function ( vector ) { - console.warn( 'THREE.Matrix3: .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead.' ); + THREE.warn( 'THREE.Matrix3: .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead.' ); return vector.applyMatrix3( this ); }, multiplyVector3Array: function ( a ) { - console.warn( 'THREE.Matrix3: .multiplyVector3Array() has been renamed. Use matrix.applyToVector3Array( array ) instead.' ); + THREE.warn( 'THREE.Matrix3: .multiplyVector3Array() has been renamed. Use matrix.applyToVector3Array( array ) instead.' ); return this.applyToVector3Array( a ); }, @@ -4175,7 +4314,7 @@ THREE.Matrix3.prototype = { if ( offset === undefined ) offset = 0; if ( length === undefined ) length = array.length; - for ( var i = 0, j = offset, il; i < length; i += 3, j += 3 ) { + for ( var i = 0, j = offset; i < length; i += 3, j += 3 ) { v1.x = array[ j ]; v1.y = array[ j + 1 ]; @@ -4251,7 +4390,7 @@ THREE.Matrix3.prototype = { } else { - console.warn( msg ); + THREE.warn( msg ); } @@ -4383,7 +4522,7 @@ THREE.Matrix4 = function () { if ( arguments.length > 0 ) { - console.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' ); + THREE.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' ); } @@ -4431,7 +4570,7 @@ THREE.Matrix4.prototype = { extractPosition: function ( m ) { - console.warn( 'THREE.Matrix4: .extractPosition() has been renamed to .copyPosition().' ); + THREE.warn( 'THREE.Matrix4: .extractPosition() has been renamed to .copyPosition().' ); return this.copyPosition( m ); }, @@ -4449,6 +4588,31 @@ THREE.Matrix4.prototype = { }, + extractBasis: function ( xAxis, yAxis, zAxis ) { + + var te = this.elements; + + xAxis.set( te[ 0 ], te[ 1 ], te[ 2 ] ); + yAxis.set( te[ 4 ], te[ 5 ], te[ 6 ] ); + zAxis.set( te[ 8 ], te[ 9 ], te[ 10 ] ); + + return this; + + }, + + makeBasis: function ( xAxis, yAxis, zAxis ) { + + this.set( + xAxis.x, yAxis.x, zAxis.x, 0, + xAxis.y, yAxis.y, zAxis.y, 0, + xAxis.z, yAxis.z, zAxis.z, 0, + 0, 0, 0, 1 + ); + + return this; + + }, + extractRotation: function () { var v1 = new THREE.Vector3(); @@ -4484,7 +4648,7 @@ THREE.Matrix4.prototype = { if ( euler instanceof THREE.Euler === false ) { - console.error( 'THREE.Matrix: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' ); + THREE.error( 'THREE.Matrix: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' ); } @@ -4610,7 +4774,7 @@ THREE.Matrix4.prototype = { setRotationFromQuaternion: function ( q ) { - console.warn( 'THREE.Matrix4: .setRotationFromQuaternion() has been renamed to .makeRotationFromQuaternion().' ); + THREE.warn( 'THREE.Matrix4: .setRotationFromQuaternion() has been renamed to .makeRotationFromQuaternion().' ); return this.makeRotationFromQuaternion( q ); @@ -4697,7 +4861,7 @@ THREE.Matrix4.prototype = { if ( n !== undefined ) { - console.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' ); + THREE.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' ); return this.multiplyMatrices( m, n ); } @@ -4776,21 +4940,21 @@ THREE.Matrix4.prototype = { multiplyVector3: function ( vector ) { - console.warn( 'THREE.Matrix4: .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) or vector.applyProjection( matrix ) instead.' ); + THREE.warn( 'THREE.Matrix4: .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) or vector.applyProjection( matrix ) instead.' ); return vector.applyProjection( this ); }, multiplyVector4: function ( vector ) { - console.warn( 'THREE.Matrix4: .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead.' ); + THREE.warn( 'THREE.Matrix4: .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead.' ); return vector.applyMatrix4( this ); }, multiplyVector3Array: function ( a ) { - console.warn( 'THREE.Matrix4: .multiplyVector3Array() has been renamed. Use matrix.applyToVector3Array( array ) instead.' ); + THREE.warn( 'THREE.Matrix4: .multiplyVector3Array() has been renamed. Use matrix.applyToVector3Array( array ) instead.' ); return this.applyToVector3Array( a ); }, @@ -4804,7 +4968,7 @@ THREE.Matrix4.prototype = { if ( offset === undefined ) offset = 0; if ( length === undefined ) length = array.length; - for ( var i = 0, j = offset, il; i < length; i += 3, j += 3 ) { + for ( var i = 0, j = offset; i < length; i += 3, j += 3 ) { v1.x = array[ j ]; v1.y = array[ j + 1 ]; @@ -4826,7 +4990,7 @@ THREE.Matrix4.prototype = { rotateAxis: function ( v ) { - console.warn( 'THREE.Matrix4: .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead.' ); + THREE.warn( 'THREE.Matrix4: .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead.' ); v.transformDirection( this ); @@ -4834,7 +4998,7 @@ THREE.Matrix4.prototype = { crossVector: function ( vector ) { - console.warn( 'THREE.Matrix4: .crossVector() has been removed. Use vector.applyMatrix4( matrix ) instead.' ); + THREE.warn( 'THREE.Matrix4: .crossVector() has been removed. Use vector.applyMatrix4( matrix ) instead.' ); return vector.applyMatrix4( this ); }, @@ -4940,7 +5104,7 @@ THREE.Matrix4.prototype = { return function () { - console.warn( 'THREE.Matrix4: .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead.' ); + THREE.warn( 'THREE.Matrix4: .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead.' ); var te = this.elements; return v1.set( te[ 12 ], te[ 13 ], te[ 14 ] ); @@ -4993,7 +5157,7 @@ THREE.Matrix4.prototype = { if ( det == 0 ) { - var msg = "Matrix4.getInverse(): can't invert matrix, determinant is 0"; + var msg = "THREE.Matrix4.getInverse(): can't invert matrix, determinant is 0"; if ( throwOnInvertible || false ) { @@ -5001,7 +5165,7 @@ THREE.Matrix4.prototype = { } else { - console.warn( msg ); + THREE.warn( msg ); } @@ -5018,31 +5182,31 @@ THREE.Matrix4.prototype = { translate: function ( v ) { - console.warn( 'THREE.Matrix4: .translate() has been removed.' ); + THREE.error( 'THREE.Matrix4: .translate() has been removed.' ); }, rotateX: function ( angle ) { - console.warn( 'THREE.Matrix4: .rotateX() has been removed.' ); + THREE.error( 'THREE.Matrix4: .rotateX() has been removed.' ); }, rotateY: function ( angle ) { - console.warn( 'THREE.Matrix4: .rotateY() has been removed.' ); + THREE.error( 'THREE.Matrix4: .rotateY() has been removed.' ); }, rotateZ: function ( angle ) { - console.warn( 'THREE.Matrix4: .rotateZ() has been removed.' ); + THREE.error( 'THREE.Matrix4: .rotateZ() has been removed.' ); }, rotateByAxis: function ( axis, angle ) { - console.warn( 'THREE.Matrix4: .rotateByAxis() has been removed.' ); + THREE.error( 'THREE.Matrix4: .rotateByAxis() has been removed.' ); }, @@ -5418,53 +5582,70 @@ THREE.Ray.prototype = { }(), - distanceSqToSegment: function ( v0, v1, optionalPointOnRay, optionalPointOnSegment ) { + distanceSqToSegment: function () { + + var segCenter = new THREE.Vector3(); + var segDir = new THREE.Vector3(); + var diff = new THREE.Vector3(); + + return function ( v0, v1, optionalPointOnRay, optionalPointOnSegment ) { + + // from http://www.geometrictools.com/LibMathematics/Distance/Wm5DistRay3Segment3.cpp + // It returns the min distance between the ray and the segment + // defined by v0 and v1 + // It can also set two optional targets : + // - The closest point on the ray + // - The closest point on the segment + + segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 ); + segDir.copy( v1 ).sub( v0 ).normalize(); + diff.copy( this.origin ).sub( segCenter ); + + var segExtent = v0.distanceTo( v1 ) * 0.5; + var a01 = - this.direction.dot( segDir ); + var b0 = diff.dot( this.direction ); + var b1 = - diff.dot( segDir ); + var c = diff.lengthSq(); + var det = Math.abs( 1 - a01 * a01 ); + var s0, s1, sqrDist, extDet; - // from http://www.geometrictools.com/LibMathematics/Distance/Wm5DistRay3Segment3.cpp - // It returns the min distance between the ray and the segment - // defined by v0 and v1 - // It can also set two optional targets : - // - The closest point on the ray - // - The closest point on the segment + if ( det > 0 ) { - var segCenter = v0.clone().add( v1 ).multiplyScalar( 0.5 ); - var segDir = v1.clone().sub( v0 ).normalize(); - var segExtent = v0.distanceTo( v1 ) * 0.5; - var diff = this.origin.clone().sub( segCenter ); - var a01 = - this.direction.dot( segDir ); - var b0 = diff.dot( this.direction ); - var b1 = - diff.dot( segDir ); - var c = diff.lengthSq(); - var det = Math.abs( 1 - a01 * a01 ); - var s0, s1, sqrDist, extDet; + // The ray and segment are not parallel. - if ( det >= 0 ) { + s0 = a01 * b1 - b0; + s1 = a01 * b0 - b1; + extDet = segExtent * det; - // The ray and segment are not parallel. + if ( s0 >= 0 ) { - s0 = a01 * b1 - b0; - s1 = a01 * b0 - b1; - extDet = segExtent * det; + if ( s1 >= - extDet ) { - if ( s0 >= 0 ) { + if ( s1 <= extDet ) { - if ( s1 >= - extDet ) { + // region 0 + // Minimum at interior points of ray and segment. - if ( s1 <= extDet ) { + var invDet = 1 / det; + s0 *= invDet; + s1 *= invDet; + sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c; - // region 0 - // Minimum at interior points of ray and segment. + } else { + + // region 1 - var invDet = 1 / det; - s0 *= invDet; - s1 *= invDet; - sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c; + s1 = segExtent; + s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); + sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; + + } } else { - // region 1 + // region 5 - s1 = segExtent; + s1 = - segExtent; s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; @@ -5472,69 +5653,62 @@ THREE.Ray.prototype = { } else { - // region 5 + if ( s1 <= - extDet ) { - s1 = - segExtent; - s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); - sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; + // region 4 - } + s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) ); + s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent ); + sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; - } else { + } else if ( s1 <= extDet ) { - if ( s1 <= - extDet ) { + // region 3 - // region 4 + s0 = 0; + s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent ); + sqrDist = s1 * ( s1 + 2 * b1 ) + c; - s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) ); - s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent ); - sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; + } else { - } else if ( s1 <= extDet ) { + // region 2 - // region 3 + s0 = Math.max( 0, - ( a01 * segExtent + b0 ) ); + s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent ); + sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; - s0 = 0; - s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent ); - sqrDist = s1 * ( s1 + 2 * b1 ) + c; + } - } else { + } - // region 2 + } else { - s0 = Math.max( 0, - ( a01 * segExtent + b0 ) ); - s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent ); - sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; + // Ray and segment are parallel. - } + s1 = ( a01 > 0 ) ? - segExtent : segExtent; + s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); + sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; } - } else { - - // Ray and segment are parallel. + if ( optionalPointOnRay ) { - s1 = ( a01 > 0 ) ? - segExtent : segExtent; - s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); - sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; + optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin ); - } - - if ( optionalPointOnRay ) { + } - optionalPointOnRay.copy( this.direction.clone().multiplyScalar( s0 ).add( this.origin ) ); + if ( optionalPointOnSegment ) { - } + optionalPointOnSegment.copy( segDir ).multiplyScalar( s1 ).add( segCenter ); - if ( optionalPointOnSegment ) { + } - optionalPointOnSegment.copy( segDir.clone().multiplyScalar( s1 ).add( segCenter ) ); + return sqrDist; - } + }; - return sqrDist; + }(), - }, isIntersectionSphere: function ( sphere ) { @@ -5660,7 +5834,7 @@ THREE.Ray.prototype = { }(), - intersectBox: function ( box , optionalTarget ) { + intersectBox: function ( box, optionalTarget ) { // http://www.scratchapixel.com/lessons/3d-basic-lessons/lesson-7-intersecting-simple-shapes/ray-box-intersection/ @@ -5865,7 +6039,7 @@ THREE.Sphere.prototype = { var box = new THREE.Box3(); - return function ( points, optionalCenter ) { + return function ( points, optionalCenter ) { var center = this.center; @@ -5891,7 +6065,7 @@ THREE.Sphere.prototype = { return this; - }; + }; }(), @@ -6503,7 +6677,7 @@ THREE.Math = { randInt: function ( low, high ) { - return low + Math.floor( Math.random() * ( high - low + 1 ) ); + return Math.floor( this.randFloat( low, high ) ); }, @@ -6551,6 +6725,20 @@ THREE.Math = { return ( value & ( value - 1 ) ) === 0 && value !== 0; + }, + + nextPowerOfTwo: function ( value ) { + + value --; + value |= value >> 1; + value |= value >> 2; + value |= value >> 4; + value |= value >> 8; + value |= value >> 16; + value ++; + + return value; + } }; @@ -6684,7 +6872,7 @@ THREE.Spline = function ( points ) { var i, j, index, indexCurrent, indexNext, - linearDistance, realDistance, + realDistance, sampling, position, newpoints = [], tmpVec = new THREE.Vector3(), @@ -7175,9 +7363,32 @@ THREE.EventDispatcher.prototype = { set: function ( origin, direction ) { - this.ray.set( origin, direction ); // direction is assumed to be normalized (for accurate distance calculations) + this.ray.set( origin, direction ); + + }, + + setFromCamera: function ( coords, camera ) { + + // camera is assumed _not_ to be a child of a transformed object + + if ( camera instanceof THREE.PerspectiveCamera ) { + + this.ray.origin.copy( camera.position ); + this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( camera.position ).normalize(); + + } else if ( camera instanceof THREE.OrthographicCamera ) { + + this.ray.origin.set( coords.x, coords.y, - 1 ).unproject( camera ); + this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld ); + + } else { + + THREE.error( 'THREE.Raycaster: Unsupported camera type.' ); + + } + }, intersectObject: function ( object, recursive ) { @@ -7198,7 +7409,7 @@ THREE.EventDispatcher.prototype = { if ( objects instanceof Array === false ) { - console.log( 'THREE.Raycaster.intersectObjects: objects is not an Array.' ); + THREE.warn( 'THREE.Raycaster.intersectObjects: objects is not an Array.' ); return intersects; } @@ -7242,8 +7453,6 @@ THREE.Object3D = function () { this.up = THREE.Object3D.DefaultUp.clone(); - var scope = this; - var position = new THREE.Vector3(); var rotation = new THREE.Euler(); var quaternion = new THREE.Quaternion(); @@ -7276,11 +7485,9 @@ THREE.Object3D = function () { scale: { enumerable: true, value: scale - }, + } } ); - this.renderDepth = null; - this.rotationAutoUpdate = true; this.matrix = new THREE.Matrix4(); @@ -7295,6 +7502,7 @@ THREE.Object3D = function () { this.receiveShadow = false; this.frustumCulled = true; + this.renderOrder = 0; this.userData = {}; @@ -7308,7 +7516,7 @@ THREE.Object3D.prototype = { get eulerOrder () { - console.warn( 'THREE.Object3D: .eulerOrder has been moved to .rotation.order.' ); + THREE.warn( 'THREE.Object3D: .eulerOrder has been moved to .rotation.order.' ); return this.rotation.order; @@ -7316,7 +7524,7 @@ THREE.Object3D.prototype = { set eulerOrder ( value ) { - console.warn( 'THREE.Object3D: .eulerOrder has been moved to .rotation.order.' ); + THREE.warn( 'THREE.Object3D: .eulerOrder has been moved to .rotation.order.' ); this.rotation.order = value; @@ -7324,13 +7532,13 @@ THREE.Object3D.prototype = { get useQuaternion () { - console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' ); + THREE.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' ); }, set useQuaternion ( value ) { - console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' ); + THREE.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' ); }, @@ -7448,7 +7656,7 @@ THREE.Object3D.prototype = { translate: function ( distance, axis ) { - console.warn( 'THREE.Object3D: .translate() has been removed. Use .translateOnAxis( axis, distance ) instead.' ); + THREE.warn( 'THREE.Object3D: .translate() has been removed. Use .translateOnAxis( axis, distance ) instead.' ); return this.translateOnAxis( axis, distance ); }, @@ -7527,7 +7735,7 @@ THREE.Object3D.prototype = { if ( arguments.length > 1 ) { - for ( var i = 0; i < arguments.length; i++ ) { + for ( var i = 0; i < arguments.length; i ++ ) { this.add( arguments[ i ] ); @@ -7539,7 +7747,7 @@ THREE.Object3D.prototype = { if ( object === this ) { - console.error( "THREE.Object3D.add:", object, "can't be added as a child of itself." ); + THREE.error( "THREE.Object3D.add: object can't be added as a child of itself.", object ); return this; } @@ -7559,7 +7767,7 @@ THREE.Object3D.prototype = { } else { - console.error( "THREE.Object3D.add:", object, "is not an instance of THREE.Object3D." ); + THREE.error( "THREE.Object3D.add: object not an instance of THREE.Object3D.", object ); } @@ -7571,7 +7779,7 @@ THREE.Object3D.prototype = { if ( arguments.length > 1 ) { - for ( var i = 0; i < arguments.length; i++ ) { + for ( var i = 0; i < arguments.length; i ++ ) { this.remove( arguments[ i ] ); @@ -7593,42 +7801,33 @@ THREE.Object3D.prototype = { }, - getChildByName: function ( name, recursive ) { + getChildByName: function ( name ) { - console.warn( 'THREE.Object3D: .getChildByName() has been renamed to .getObjectByName().' ); - return this.getObjectByName( name, recursive ); + THREE.warn( 'THREE.Object3D: .getChildByName() has been renamed to .getObjectByName().' ); + return this.getObjectByName( name ); }, - getObjectById: function ( id, recursive ) { + getObjectById: function ( id ) { - if ( this.id === id ) return this; + return this.getObjectByProperty( 'id', id ); - for ( var i = 0, l = this.children.length; i < l; i ++ ) { - - var child = this.children[ i ]; - var object = child.getObjectById( id, recursive ); - - if ( object !== undefined ) { - - return object; - - } + }, - } + getObjectByName: function ( name ) { - return undefined; + return this.getObjectByProperty( 'name', name ); }, - getObjectByName: function ( name, recursive ) { + getObjectByProperty: function ( name, value ) { - if ( this.name === name ) return this; + if ( this[ name ] === value ) return this; for ( var i = 0, l = this.children.length; i < l; i ++ ) { var child = this.children[ i ]; - var object = child.getObjectByName( name, recursive ); + var object = child.getObjectByProperty( name, value ); if ( object !== undefined ) { @@ -7750,6 +7949,18 @@ THREE.Object3D.prototype = { }, + traverseAncestors: function ( callback ) { + + if ( this.parent ) { + + callback( this.parent ); + + this.parent.traverseAncestors( callback ); + + } + + }, + updateMatrix: function () { this.matrix.compose( this.position, this.quaternion, this.scale ); @@ -7899,6 +8110,7 @@ THREE.Object3D.prototype = { data.color = object.color.getHex(); data.intensity = object.intensity; data.distance = object.distance; + data.decay = object.decay; } else if ( object instanceof THREE.SpotLight ) { @@ -7907,21 +8119,19 @@ THREE.Object3D.prototype = { data.distance = object.distance; data.angle = object.angle; data.exponent = object.exponent; + data.decay = object.decay; } else if ( object instanceof THREE.HemisphereLight ) { data.color = object.color.getHex(); data.groundColor = object.groundColor.getHex(); - } else if ( object instanceof THREE.Mesh ) { + } else if ( object instanceof THREE.Mesh || object instanceof THREE.Line || object instanceof THREE.PointCloud ) { data.geometry = parseGeometry( object.geometry ); data.material = parseMaterial( object.material ); - } else if ( object instanceof THREE.Line ) { - - data.geometry = parseGeometry( object.geometry ); - data.material = parseMaterial( object.material ); + if ( object instanceof THREE.Line ) data.mode = object.mode; } else if ( object instanceof THREE.Sprite ) { @@ -7966,8 +8176,6 @@ THREE.Object3D.prototype = { object.quaternion.copy( this.quaternion ); object.scale.copy( this.scale ); - object.renderDepth = this.renderDepth; - object.rotationAutoUpdate = this.rotationAutoUpdate; object.matrix.copy( this.matrix ); @@ -8006,38 +8214,6 @@ THREE.EventDispatcher.prototype.apply( THREE.Object3D.prototype ); THREE.Object3DIdCount = 0; -// File:src/core/Projector.js - -/** - * @author mrdoob / http://mrdoob.com/ - */ - -THREE.Projector = function () { - - console.warn( 'THREE.Projector has been moved to /examples/renderers/Projector.js.' ); - - this.projectVector = function ( vector, camera ) { - - console.warn( 'THREE.Projector: .projectVector() is now vector.project().' ); - vector.project( camera ); - - }; - - this.unprojectVector = function ( vector, camera ) { - - console.warn( 'THREE.Projector: .unprojectVector() is now vector.unproject().' ); - vector.unproject( camera ); - - }; - - this.pickingRay = function ( vector, camera ) { - - console.error( 'THREE.Projector: .pickingRay() has been removed.' ); - - }; - -}; - // File:src/core/Face3.js /** @@ -8108,7 +8284,7 @@ THREE.Face3.prototype = { THREE.Face4 = function ( a, b, c, d, normal, color, materialIndex ) { - console.warn( 'THREE.Face4 has been removed. A THREE.Face3 will be created instead.' ) + THREE.warn( 'THREE.Face4 has been removed. A THREE.Face3 will be created instead.' ) return new THREE.Face3( a, b, c, normal, color, materialIndex ); }; @@ -8149,11 +8325,15 @@ THREE.BufferAttribute.prototype = { } + return this; + }, - set: function ( value ) { + set: function ( value, offset ) { + + if ( offset === undefined ) offset = 0; - this.array.set( value ); + this.array.set( value, offset ); return this; @@ -8231,21 +8411,21 @@ THREE.BufferAttribute.prototype = { THREE.Int8Attribute = function ( data, itemSize ) { - console.warn( 'THREE.Int8Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' ); + THREE.warn( 'THREE.Int8Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' ); return new THREE.BufferAttribute( data, itemSize ); }; THREE.Uint8Attribute = function ( data, itemSize ) { - console.warn( 'THREE.Uint8Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' ); + THREE.warn( 'THREE.Uint8Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' ); return new THREE.BufferAttribute( data, itemSize ); }; THREE.Uint8ClampedAttribute = function ( data, itemSize ) { - console.warn( 'THREE.Uint8ClampedAttribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' ); + THREE.warn( 'THREE.Uint8ClampedAttribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' ); return new THREE.BufferAttribute( data, itemSize ); @@ -8253,46 +8433,70 @@ THREE.Uint8ClampedAttribute = function ( data, itemSize ) { THREE.Int16Attribute = function ( data, itemSize ) { - console.warn( 'THREE.Int16Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' ); + THREE.warn( 'THREE.Int16Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' ); return new THREE.BufferAttribute( data, itemSize ); }; THREE.Uint16Attribute = function ( data, itemSize ) { - console.warn( 'THREE.Uint16Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' ); + THREE.warn( 'THREE.Uint16Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' ); return new THREE.BufferAttribute( data, itemSize ); }; THREE.Int32Attribute = function ( data, itemSize ) { - console.warn( 'THREE.Int32Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' ); + THREE.warn( 'THREE.Int32Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' ); return new THREE.BufferAttribute( data, itemSize ); }; THREE.Uint32Attribute = function ( data, itemSize ) { - console.warn( 'THREE.Uint32Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' ); + THREE.warn( 'THREE.Uint32Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' ); return new THREE.BufferAttribute( data, itemSize ); }; THREE.Float32Attribute = function ( data, itemSize ) { - console.warn( 'THREE.Float32Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' ); + THREE.warn( 'THREE.Float32Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' ); return new THREE.BufferAttribute( data, itemSize ); }; THREE.Float64Attribute = function ( data, itemSize ) { - console.warn( 'THREE.Float64Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' ); + THREE.warn( 'THREE.Float64Attribute has been removed. Use THREE.BufferAttribute( array, itemSize ) instead.' ); return new THREE.BufferAttribute( data, itemSize ); }; +// File:src/core/DynamicBufferAttribute.js + +/** + * @author benaadams / https://twitter.com/ben_a_adams + * @author mrdoob / http://mrdoob.com/ + */ + +THREE.DynamicBufferAttribute = function ( array, itemSize ) { + + THREE.BufferAttribute.call( this, array, itemSize ); + + this.updateRange = { offset: 0, count: -1 }; + +}; + +THREE.DynamicBufferAttribute.prototype = Object.create( THREE.BufferAttribute.prototype ); +THREE.DynamicBufferAttribute.prototype.constructor = THREE.DynamicBufferAttribute; + +THREE.DynamicBufferAttribute.prototype.clone = function () { + + return new THREE.DynamicBufferAttribute( new this.array.constructor( this.array ), this.itemSize ); + +}; + // File:src/core/BufferGeometry.js /** @@ -8328,7 +8532,7 @@ THREE.BufferGeometry.prototype = { if ( attribute instanceof THREE.BufferAttribute === false ) { - console.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' ); + THREE.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' ); this.attributes[ name ] = { array: arguments[ 1 ], itemSize: arguments[ 2 ] }; @@ -8381,11 +8585,29 @@ THREE.BufferGeometry.prototype = { } + if ( this.boundingBox !== null ) { + + this.computeBoundingBox(); + + } + + if ( this.boundingSphere !== null ) { + + this.computeBoundingSphere(); + + } + }, center: function () { - // TODO + this.computeBoundingBox(); + + var offset = this.boundingBox.center().negate(); + + this.applyMatrix( new THREE.Matrix4().setPosition( offset ) ); + + return offset; }, @@ -8574,7 +8796,7 @@ THREE.BufferGeometry.prototype = { if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) { - console.error( 'THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The "position" attribute is likely to have NaN values.' ); + THREE.error( 'THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The "position" attribute is likely to have NaN values.' ); } @@ -8628,7 +8850,7 @@ THREE.BufferGeometry.prototype = { if ( isNaN( this.boundingSphere.radius ) ) { - console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.' ); + THREE.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.' ); } @@ -8773,7 +8995,7 @@ THREE.BufferGeometry.prototype = { this.attributes.normal === undefined || this.attributes.uv === undefined ) { - console.warn( 'Missing required attributes (index, position, normal or uv) in BufferGeometry.computeTangents()' ); + THREE.warn( 'THREE.BufferGeometry: Missing required attributes (index, position, normal or uv) in BufferGeometry.computeTangents()' ); return; } @@ -8946,24 +9168,18 @@ THREE.BufferGeometry.prototype = { }, /* - computeOffsets - Compute the draw offset for large models by chunking the index buffer into chunks of 65k addressable vertices. - This method will effectively rewrite the index buffer and remap all attributes to match the new indices. - WARNING: This method will also expand the vertex count to prevent sprawled triangles across draw offsets. - indexBufferSize - Defaults to 65535, but allows for larger or smaller chunks. + Compute the draw offset for large models by chunking the index buffer into chunks of 65k addressable vertices. + This method will effectively rewrite the index buffer and remap all attributes to match the new indices. + WARNING: This method will also expand the vertex count to prevent sprawled triangles across draw offsets. + size - Defaults to 65535, but allows for larger or smaller chunks. */ - computeOffsets: function ( indexBufferSize ) { + computeOffsets: function ( size ) { - var size = indexBufferSize; - if ( indexBufferSize === undefined ) - size = 65535; //WebGL limits type of index buffer values to 16-bit. - - var s = Date.now(); + if ( size === undefined ) size = 65535; // WebGL limits type of index buffer values to 16-bit. var indices = this.attributes.index.array; var vertices = this.attributes.position.array; - var verticesCount = ( vertices.length / 3 ); var facesCount = ( indices.length / 3 ); /* @@ -9043,7 +9259,8 @@ THREE.BufferGeometry.prototype = { /* Move all attribute values to map to the new computed indices , also expand the vertice stack to match our new vertexPtr. */ this.reorderBuffers( sortedIndices, revVertexMap, vertexPtr ); - this.offsets = offsets; + this.offsets = offsets; // TODO: Deprecate + this.drawcalls = offsets; /* var orderTime = Date.now(); @@ -9054,11 +9271,43 @@ THREE.BufferGeometry.prototype = { */ return offsets; + }, - merge: function () { + merge: function ( geometry, offset ) { + + if ( geometry instanceof THREE.BufferGeometry === false ) { + + THREE.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry ); + return; + + } + + if ( offset === undefined ) offset = 0; + + var attributes = this.attributes; + + for ( var key in attributes ) { + + if ( geometry.attributes[ key ] === undefined ) continue; + + var attribute1 = attributes[ key ]; + var attributeArray1 = attribute1.array; + + var attribute2 = geometry.attributes[ key ]; + var attributeArray2 = attribute2.array; + + var attributeSize = attribute2.itemSize; - console.log( 'BufferGeometry.merge(): TODO' ); + for ( var i = 0, j = attributeSize * offset; i < attributeArray2.length; i ++, j ++ ) { + + attributeArray1[ j ] = attributeArray2[ i ]; + + } + + } + + return this; }, @@ -9149,13 +9398,7 @@ THREE.BufferGeometry.prototype = { var attribute = attributes[ key ]; - var array = [], typeArray = attribute.array; - - for ( var i = 0, l = typeArray.length; i < l; i ++ ) { - - array[ i ] = typeArray[ i ]; - - } + var array = Array.prototype.slice.call( attribute.array ); output.data.attributes[ key ] = { itemSize: attribute.itemSize, @@ -9308,18 +9551,21 @@ THREE.Geometry.prototype = { } - if ( this.boundingBox instanceof THREE.Box3 ) { + if ( this.boundingBox !== null ) { this.computeBoundingBox(); } - if ( this.boundingSphere instanceof THREE.Sphere ) { + if ( this.boundingSphere !== null ) { this.computeBoundingSphere(); } + this.verticesNeedUpdate = true; + this.normalsNeedUpdate = true; + }, fromBufferGeometry: function ( geometry ) { @@ -9367,15 +9613,44 @@ THREE.Geometry.prototype = { var vertexColors = colors !== undefined ? [ scope.colors[ a ].clone(), scope.colors[ b ].clone(), scope.colors[ c ].clone() ] : []; scope.faces.push( new THREE.Face3( a, b, c, vertexNormals, vertexColors ) ); - scope.faceVertexUvs[ 0 ].push( [ tempUVs[ a ], tempUVs[ b ], tempUVs[ c ] ] ); + + if ( uvs !== undefined ) { + + scope.faceVertexUvs[ 0 ].push( [ tempUVs[ a ].clone(), tempUVs[ b ].clone(), tempUVs[ c ].clone() ] ); + + } }; if ( indices !== undefined ) { - for ( var i = 0; i < indices.length; i += 3 ) { + var drawcalls = geometry.drawcalls; - addFace( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] ); + if ( drawcalls.length > 0 ) { + + for ( var i = 0; i < drawcalls.length; i ++ ) { + + var drawcall = drawcalls[ i ]; + + var start = drawcall.start; + var count = drawcall.count; + var index = drawcall.index; + + for ( var j = start, jl = start + count; j < jl; j += 3 ) { + + addFace( index + indices[ j ], index + indices[ j + 1 ], index + indices[ j + 2 ] ); + + } + + } + + } else { + + for ( var i = 0; i < indices.length; i += 3 ) { + + addFace( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] ); + + } } @@ -9388,7 +9663,7 @@ THREE.Geometry.prototype = { } } - + this.computeFaceNormals(); if ( geometry.boundingBox !== null ) { @@ -9411,13 +9686,9 @@ THREE.Geometry.prototype = { this.computeBoundingBox(); - var offset = new THREE.Vector3(); + var offset = this.boundingBox.center().negate(); - offset.addVectors( this.boundingBox.min, this.boundingBox.max ); - offset.multiplyScalar( - 0.5 ); - - this.applyMatrix( new THREE.Matrix4().makeTranslation( offset.x, offset.y, offset.z ) ); - this.computeBoundingBox(); + this.applyMatrix( new THREE.Matrix4().setPosition( offset ) ); return offset; @@ -9464,9 +9735,8 @@ THREE.Geometry.prototype = { // vertex normals weighted by triangle areas // http://www.iquilezles.org/www/articles/normals/normals.htm - var vA, vB, vC, vD; - var cb = new THREE.Vector3(), ab = new THREE.Vector3(), - db = new THREE.Vector3(), dc = new THREE.Vector3(), bc = new THREE.Vector3(); + var vA, vB, vC; + var cb = new THREE.Vector3(), ab = new THREE.Vector3(); for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { @@ -9640,7 +9910,7 @@ THREE.Geometry.prototype = { // based on http://www.terathon.com/code/tangent.html // tangents go to vertices - var f, fl, v, vl, i, il, vertexIndex, + var f, fl, v, vl, i, vertexIndex, face, uv, vA, vB, vC, uvA, uvB, uvC, x1, x2, y1, y2, z1, z2, s1, s2, t1, t2, r, t, test, @@ -9787,7 +10057,7 @@ THREE.Geometry.prototype = { if ( geometry instanceof THREE.Geometry === false ) { - console.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry ); + THREE.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry ); return; } @@ -9883,7 +10153,7 @@ THREE.Geometry.prototype = { for ( var j = 0, jl = uv.length; j < jl; j ++ ) { - uvCopy.push( new THREE.Vector2( uv[ j ].x, uv[ j ].y ) ); + uvCopy.push( uv[ j ].clone() ); } @@ -9893,6 +10163,21 @@ THREE.Geometry.prototype = { }, + mergeMesh: function ( mesh ) { + + if ( mesh instanceof THREE.Mesh === false ) { + + THREE.error( 'THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh ); + return; + + } + + mesh.matrixAutoUpdate && mesh.updateMatrix(); + + this.merge( mesh.geometry, mesh.matrix ); + + }, + /* * Checks for duplicate vertices with hashmap. * Duplicated vertices are removed @@ -9907,8 +10192,8 @@ THREE.Geometry.prototype = { var v, key; var precisionPoints = 4; // number of decimal points, eg. 4 for epsilon of 0.0001 var precision = Math.pow( 10, precisionPoints ); - var i,il, face; - var indices, k, j, jl, u; + var i, il, face; + var indices, j, jl; for ( i = 0, il = this.vertices.length; i < il; i ++ ) { @@ -10203,19 +10488,31 @@ THREE.Geometry.prototype = { } - var uvs = this.faceVertexUvs[ 0 ]; + for ( var i = 0, il = this.faceVertexUvs.length; i < il; i ++ ) { - for ( var i = 0, il = uvs.length; i < il; i ++ ) { + var faceVertexUvs = this.faceVertexUvs[ i ]; - var uv = uvs[ i ], uvCopy = []; - - for ( var j = 0, jl = uv.length; j < jl; j ++ ) { + if ( geometry.faceVertexUvs[ i ] === undefined ) { - uvCopy.push( new THREE.Vector2( uv[ j ].x, uv[ j ].y ) ); + geometry.faceVertexUvs[ i ] = []; } - geometry.faceVertexUvs[ 0 ].push( uvCopy ); + for ( var j = 0, jl = faceVertexUvs.length; j < jl; j ++ ) { + + var uvs = faceVertexUvs[ j ], uvsCopy = []; + + for ( var k = 0, kl = uvs.length; k < kl; k ++ ) { + + var uv = uvs[ k ]; + + uvsCopy.push( uv.clone() ); + + } + + geometry.faceVertexUvs[ i ].push( uvsCopy ); + + } } @@ -10255,6 +10552,7 @@ THREE.Camera = function () { }; THREE.Camera.prototype = Object.create( THREE.Object3D.prototype ); +THREE.Camera.prototype.constructor = THREE.Camera; THREE.Camera.prototype.getWorldDirection = function () { @@ -10381,6 +10679,7 @@ THREE.CubeCamera = function ( near, far, cubeResolution ) { }; THREE.CubeCamera.prototype = Object.create( THREE.Object3D.prototype ); +THREE.CubeCamera.prototype.constructor = THREE.CubeCamera; // File:src/cameras/OrthographicCamera.js @@ -10409,6 +10708,7 @@ THREE.OrthographicCamera = function ( left, right, top, bottom, near, far ) { }; THREE.OrthographicCamera.prototype = Object.create( THREE.Camera.prototype ); +THREE.OrthographicCamera.prototype.constructor = THREE.OrthographicCamera; THREE.OrthographicCamera.prototype.updateProjectionMatrix = function () { @@ -10468,6 +10768,7 @@ THREE.PerspectiveCamera = function ( fov, aspect, near, far ) { }; THREE.PerspectiveCamera.prototype = Object.create( THREE.Camera.prototype ); +THREE.PerspectiveCamera.prototype.constructor = THREE.PerspectiveCamera; /** @@ -10604,6 +10905,7 @@ THREE.Light = function ( color ) { }; THREE.Light.prototype = Object.create( THREE.Object3D.prototype ); +THREE.Light.prototype.constructor = THREE.Light; THREE.Light.prototype.clone = function ( light ) { @@ -10632,6 +10934,7 @@ THREE.AmbientLight = function ( color ) { }; THREE.AmbientLight.prototype = Object.create( THREE.Light.prototype ); +THREE.AmbientLight.prototype.constructor = THREE.AmbientLight; THREE.AmbientLight.prototype.clone = function () { @@ -10671,6 +10974,7 @@ THREE.AreaLight = function ( color, intensity ) { }; THREE.AreaLight.prototype = Object.create( THREE.Light.prototype ); +THREE.AreaLight.prototype.constructor = THREE.AreaLight; // File:src/lights/DirectionalLight.js @@ -10724,7 +11028,7 @@ THREE.DirectionalLight = function ( color, intensity ) { this.shadowCascadeHeight = [ 512, 512, 512 ]; this.shadowCascadeNearZ = [ - 1.000, 0.990, 0.998 ]; - this.shadowCascadeFarZ = [ 0.990, 0.998, 1.000 ]; + this.shadowCascadeFarZ = [ 0.990, 0.998, 1.000 ]; this.shadowCascadeArray = []; @@ -10738,6 +11042,7 @@ THREE.DirectionalLight = function ( color, intensity ) { }; THREE.DirectionalLight.prototype = Object.create( THREE.Light.prototype ); +THREE.DirectionalLight.prototype.constructor = THREE.DirectionalLight; THREE.DirectionalLight.prototype.clone = function () { @@ -10808,6 +11113,7 @@ THREE.HemisphereLight = function ( skyColor, groundColor, intensity ) { }; THREE.HemisphereLight.prototype = Object.create( THREE.Light.prototype ); +THREE.HemisphereLight.prototype.constructor = THREE.HemisphereLight; THREE.HemisphereLight.prototype.clone = function () { @@ -10828,7 +11134,7 @@ THREE.HemisphereLight.prototype.clone = function () { * @author mrdoob / http://mrdoob.com/ */ -THREE.PointLight = function ( color, intensity, distance ) { +THREE.PointLight = function ( color, intensity, distance, decay ) { THREE.Light.call( this, color ); @@ -10836,10 +11142,12 @@ THREE.PointLight = function ( color, intensity, distance ) { this.intensity = ( intensity !== undefined ) ? intensity : 1; this.distance = ( distance !== undefined ) ? distance : 0; + this.decay = ( decay !== undefined ) ? decay : 1; // for physically correct lights, should be 2. }; THREE.PointLight.prototype = Object.create( THREE.Light.prototype ); +THREE.PointLight.prototype.constructor = THREE.PointLight; THREE.PointLight.prototype.clone = function () { @@ -10849,6 +11157,7 @@ THREE.PointLight.prototype.clone = function () { light.intensity = this.intensity; light.distance = this.distance; + light.decay = this.decay; return light; @@ -10860,7 +11169,7 @@ THREE.PointLight.prototype.clone = function () { * @author alteredq / http://alteredqualia.com/ */ -THREE.SpotLight = function ( color, intensity, distance, angle, exponent ) { +THREE.SpotLight = function ( color, intensity, distance, angle, exponent, decay ) { THREE.Light.call( this, color ); @@ -10873,6 +11182,7 @@ THREE.SpotLight = function ( color, intensity, distance, angle, exponent ) { this.distance = ( distance !== undefined ) ? distance : 0; this.angle = ( angle !== undefined ) ? angle : Math.PI / 3; this.exponent = ( exponent !== undefined ) ? exponent : 10; + this.decay = ( decay !== undefined ) ? decay : 1; // for physically correct lights, should be 2. this.castShadow = false; this.onlyShadow = false; @@ -10901,6 +11211,7 @@ THREE.SpotLight = function ( color, intensity, distance, angle, exponent ) { }; THREE.SpotLight.prototype = Object.create( THREE.Light.prototype ); +THREE.SpotLight.prototype.constructor = THREE.SpotLight; THREE.SpotLight.prototype.clone = function () { @@ -10914,6 +11225,7 @@ THREE.SpotLight.prototype.clone = function () { light.distance = this.distance; light.angle = this.angle; light.exponent = this.exponent; + light.decay = this.decay; light.castShadow = this.castShadow; light.onlyShadow = this.onlyShadow; @@ -10942,15 +11254,9 @@ THREE.SpotLight.prototype.clone = function () { * @author mrdoob / http://mrdoob.com/ */ -THREE.Cache = function () { - - this.files = {}; - -}; +THREE.Cache = { -THREE.Cache.prototype = { - - constructor: THREE.Cache, + files: {}, add: function ( key, file ) { @@ -11212,12 +11518,18 @@ THREE.Loader.prototype = { } - if ( m.transparent !== undefined || m.opacity < 1.0 ) { + if ( m.transparent !== undefined ) { mpars.transparent = m.transparent; } + if ( m.opacity !== undefined && m.opacity < 1.0 ) { + + mpars.transparent = true; + + } + if ( m.depthTest !== undefined ) { mpars.depthTest = m.depthTest; @@ -11286,12 +11598,6 @@ THREE.Loader.prototype = { } - if ( m.colorAmbient ) { - - mpars.ambient = rgb2hex( m.colorAmbient ); - - } - if ( m.colorEmissive ) { mpars.emissive = rgb2hex( m.colorEmissive ); @@ -11300,9 +11606,16 @@ THREE.Loader.prototype = { // modifiers - if ( m.transparency ) { + if ( m.transparency !== undefined ) { + + console.warn( 'THREE.Loader: transparency has been renamed to opacity' ); + m.opacity = m.transparency; + + } + + if ( m.opacity !== undefined ) { - mpars.opacity = m.transparency; + mpars.opacity = m.opacity; } @@ -11358,71 +11671,14 @@ THREE.Loader.prototype = { } - // special case for normal mapped material - - if ( m.mapNormal ) { - - var shader = THREE.ShaderLib[ 'normalmap' ]; - var uniforms = THREE.UniformsUtils.clone( shader.uniforms ); - - uniforms[ 'tNormal' ].value = mpars.normalMap; - - if ( m.mapNormalFactor ) { - - uniforms[ 'uNormalScale' ].value.set( m.mapNormalFactor, m.mapNormalFactor ); - - } - - if ( mpars.map ) { - - uniforms[ 'tDiffuse' ].value = mpars.map; - uniforms[ 'enableDiffuse' ].value = true; - - } - - if ( mpars.specularMap ) { - - uniforms[ 'tSpecular' ].value = mpars.specularMap; - uniforms[ 'enableSpecular' ].value = true; + if ( m.mapNormalFactor ) { - } - - if ( mpars.lightMap ) { - - uniforms[ 'tAO' ].value = mpars.lightMap; - uniforms[ 'enableAO' ].value = true; - - } - - // for the moment don't handle displacement texture - - uniforms[ 'diffuse' ].value.setHex( mpars.color ); - uniforms[ 'specular' ].value.setHex( mpars.specular ); - uniforms[ 'ambient' ].value.setHex( mpars.ambient ); - - uniforms[ 'shininess' ].value = mpars.shininess; - - if ( mpars.opacity !== undefined ) { - - uniforms[ 'opacity' ].value = mpars.opacity; - - } - - var parameters = { fragmentShader: shader.fragmentShader, vertexShader: shader.vertexShader, uniforms: uniforms, lights: true, fog: true }; - var material = new THREE.ShaderMaterial( parameters ); - - if ( mpars.transparent ) { - - material.transparent = true; - - } - - } else { - - var material = new THREE[ mtype ]( mpars ); + mpars.normalScale = new THREE.Vector2( m.mapNormalFactor, m.mapNormalFactor ); } + var material = new THREE[ mtype ]( mpars ); + if ( m.DbgName !== undefined ) material.name = m.DbgName; return material; @@ -11470,7 +11726,6 @@ THREE.Loader.Handlers = { THREE.XHRLoader = function ( manager ) { - this.cache = new THREE.Cache(); this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager; }; @@ -11483,7 +11738,7 @@ THREE.XHRLoader.prototype = { var scope = this; - var cached = scope.cache.get( url ); + var cached = THREE.Cache.get( url ); if ( cached !== undefined ) { @@ -11497,7 +11752,7 @@ THREE.XHRLoader.prototype = { request.addEventListener( 'load', function ( event ) { - scope.cache.add( url, this.response ); + THREE.Cache.add( url, this.response ); if ( onLoad ) onLoad( this.response ); @@ -11556,7 +11811,6 @@ THREE.XHRLoader.prototype = { THREE.ImageLoader = function ( manager ) { - this.cache = new THREE.Cache(); this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager; }; @@ -11569,7 +11823,7 @@ THREE.ImageLoader.prototype = { var scope = this; - var cached = scope.cache.get( url ); + var cached = THREE.Cache.get( url ); if ( cached !== undefined ) { @@ -11580,18 +11834,15 @@ THREE.ImageLoader.prototype = { var image = document.createElement( 'img' ); - if ( onLoad !== undefined ) { - - image.addEventListener( 'load', function ( event ) { + image.addEventListener( 'load', function ( event ) { - scope.cache.add( url, this ); + THREE.Cache.add( url, this ); - onLoad( this ); - scope.manager.itemEnd( url ); - - }, false ); + if ( onLoad ) onLoad( this ); + + scope.manager.itemEnd( url ); - } + }, false ); if ( onProgress !== undefined ) { @@ -11647,11 +11898,10 @@ THREE.JSONLoader = function ( showStatus ) { }; THREE.JSONLoader.prototype = Object.create( THREE.Loader.prototype ); +THREE.JSONLoader.prototype.constructor = THREE.JSONLoader; THREE.JSONLoader.prototype.load = function ( url, callback, texturePath ) { - var scope = this; - // todo: unify load API to for easier SceneLoader use texturePath = texturePath && ( typeof texturePath === 'string' ) ? texturePath : this.extractUrlBase( url ); @@ -11676,11 +11926,23 @@ THREE.JSONLoader.prototype.loadAjaxJSON = function ( context, url, callback, tex if ( xhr.responseText ) { var json = JSON.parse( xhr.responseText ); + var metadata = json.metadata; + + if ( metadata !== undefined ) { + + if ( metadata.type === 'object' ) { + + THREE.error( 'THREE.JSONLoader: ' + url + ' should be loaded with THREE.ObjectLoader instead.' ); + return; + + } - if ( json.metadata !== undefined && json.metadata.type === 'scene' ) { + if ( metadata.type === 'scene' ) { - console.error( 'THREE.JSONLoader: "' + url + '" seems to be a Scene. Use THREE.SceneLoader instead.' ); - return; + THREE.error( 'THREE.JSONLoader: ' + url + ' seems to be a Scene. Use THREE.SceneLoader instead.' ); + return; + + } } @@ -11689,7 +11951,7 @@ THREE.JSONLoader.prototype.loadAjaxJSON = function ( context, url, callback, tex } else { - console.error( 'THREE.JSONLoader: "' + url + '" seems to be unreachable or the file is empty.' ); + THREE.error( 'THREE.JSONLoader: ' + url + ' seems to be unreachable or the file is empty.' ); } @@ -11701,7 +11963,7 @@ THREE.JSONLoader.prototype.loadAjaxJSON = function ( context, url, callback, tex } else { - console.error( 'THREE.JSONLoader: Couldn\'t load "' + url + '" (' + xhr.status + ')' ); + THREE.error( 'THREE.JSONLoader: Couldn\'t load ' + url + ' (' + xhr.status + ')' ); } @@ -11739,8 +12001,7 @@ THREE.JSONLoader.prototype.loadAjaxJSON = function ( context, url, callback, tex THREE.JSONLoader.prototype.parse = function ( json, texturePath ) { - var scope = this, - geometry = new THREE.Geometry(), + var geometry = new THREE.Geometry(), scale = ( json.scale !== undefined ) ? 1.0 / json.scale : 1.0; parseModel( scale ); @@ -11772,7 +12033,7 @@ THREE.JSONLoader.prototype.parse = function ( json, texturePath ) { hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor, - vertex, face, faceA, faceB, color, hex, normal, + vertex, face, faceA, faceB, hex, normal, uvLayer, uv, u, v, @@ -12088,7 +12349,7 @@ THREE.JSONLoader.prototype.parse = function ( json, texturePath ) { if ( geometry.bones && geometry.bones.length > 0 && ( geometry.skinWeights.length !== geometry.skinIndices.length || geometry.skinIndices.length !== geometry.vertices.length ) ) { - console.warn( 'When skinning, number of vertices (' + geometry.vertices.length + '), skinIndices (' + + THREE.warn( 'THREE.JSONLoader: When skinning, number of vertices (' + geometry.vertices.length + '), skinIndices (' + geometry.skinIndices.length + '), and skinWeights (' + geometry.skinWeights.length + ') should match.' ); } @@ -12242,7 +12503,7 @@ THREE.BufferGeometryLoader.prototype = { var scope = this; - var loader = new THREE.XHRLoader(); + var loader = new THREE.XHRLoader( scope.manager ); loader.setCrossOrigin( this.crossOrigin ); loader.load( url, function ( text ) { @@ -12262,7 +12523,7 @@ THREE.BufferGeometryLoader.prototype = { var geometry = new THREE.BufferGeometry(); - var attributes = json.attributes; + var attributes = json.data.attributes; for ( var key in attributes ) { @@ -12273,7 +12534,7 @@ THREE.BufferGeometryLoader.prototype = { } - var offsets = json.offsets; + var offsets = json.data.offsets; if ( offsets !== undefined ) { @@ -12281,7 +12542,7 @@ THREE.BufferGeometryLoader.prototype = { } - var boundingSphere = json.boundingSphere; + var boundingSphere = json.data.boundingSphere; if ( boundingSphere !== undefined ) { @@ -12323,7 +12584,7 @@ THREE.MaterialLoader.prototype = { var scope = this; - var loader = new THREE.XHRLoader(); + var loader = new THREE.XHRLoader( scope.manager ); loader.setCrossOrigin( this.crossOrigin ); loader.load( url, function ( text ) { @@ -12344,13 +12605,12 @@ THREE.MaterialLoader.prototype = { var material = new THREE[ json.type ]; if ( json.color !== undefined ) material.color.setHex( json.color ); - if ( json.ambient !== undefined ) material.ambient.setHex( json.ambient ); if ( json.emissive !== undefined ) material.emissive.setHex( json.emissive ); if ( json.specular !== undefined ) material.specular.setHex( json.specular ); if ( json.shininess !== undefined ) material.shininess = json.shininess; if ( json.uniforms !== undefined ) material.uniforms = json.uniforms; if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader; - if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader; + if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader; if ( json.vertexColors !== undefined ) material.vertexColors = json.vertexColors; if ( json.shading !== undefined ) material.shading = json.shading; if ( json.blending !== undefined ) material.blending = json.blending; @@ -12359,6 +12619,10 @@ THREE.MaterialLoader.prototype = { if ( json.transparent !== undefined ) material.transparent = json.transparent; if ( json.wireframe !== undefined ) material.wireframe = json.wireframe; + // for PointCloudMaterial + if ( json.size !== undefined ) material.size = json.size; + if ( json.sizeAttenuation !== undefined ) material.sizeAttenuation = json.sizeAttenuation; + if ( json.materials !== undefined ) { for ( var i = 0, l = json.materials.length; i < l; i ++ ) { @@ -12384,6 +12648,7 @@ THREE.MaterialLoader.prototype = { THREE.ObjectLoader = function ( manager ) { this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager; + this.texturePath = ''; }; @@ -12393,30 +12658,55 @@ THREE.ObjectLoader.prototype = { load: function ( url, onLoad, onProgress, onError ) { + if ( this.texturePath === '' ) { + + this.texturePath = url.substring( 0, url.lastIndexOf( '/' ) + 1 ); + + } + var scope = this; var loader = new THREE.XHRLoader( scope.manager ); loader.setCrossOrigin( this.crossOrigin ); loader.load( url, function ( text ) { - onLoad( scope.parse( JSON.parse( text ) ) ); + scope.parse( JSON.parse( text ), onLoad ); }, onProgress, onError ); }, + setTexturePath: function ( value ) { + + this.texturePath = value; + + }, + setCrossOrigin: function ( value ) { this.crossOrigin = value; }, - parse: function ( json ) { + parse: function ( json, onLoad ) { var geometries = this.parseGeometries( json.geometries ); - var materials = this.parseMaterials( json.materials ); + + var images = this.parseImages( json.images, function () { + + if ( onLoad !== undefined ) onLoad( object ); + + } ); + var textures = this.parseTextures( json.textures, images ); + var materials = this.parseMaterials( json.materials, textures ); var object = this.parseObject( json.object, geometries, materials ); + if ( json.images === undefined || json.images.length === 0 ) { + + if ( onLoad !== undefined ) onLoad( object ); + + } + return object; }, @@ -12438,8 +12728,9 @@ THREE.ObjectLoader.prototype = { switch ( data.type ) { case 'PlaneGeometry': + case 'PlaneBufferGeometry': - geometry = new THREE.PlaneGeometry( + geometry = new THREE[ data.type ]( data.width, data.height, data.widthSegments, @@ -12535,7 +12826,7 @@ THREE.ObjectLoader.prototype = { case 'BufferGeometry': - geometry = bufferGeometryLoader.parse( data.data ); + geometry = bufferGeometryLoader.parse( data ); break; @@ -12561,12 +12852,24 @@ THREE.ObjectLoader.prototype = { }, - parseMaterials: function ( json ) { + parseMaterials: function ( json, textures ) { var materials = {}; if ( json !== undefined ) { + var getTexture = function ( name ) { + + if ( textures[ name ] === undefined ) { + + THREE.warn( 'THREE.ObjectLoader: Undefined texture', name ); + + } + + return textures[ name ]; + + }; + var loader = new THREE.MaterialLoader(); for ( var i = 0, l = json.length; i < l; i ++ ) { @@ -12578,6 +12881,54 @@ THREE.ObjectLoader.prototype = { if ( data.name !== undefined ) material.name = data.name; + if ( data.map !== undefined ) { + + material.map = getTexture( data.map ); + + } + + if ( data.bumpMap !== undefined ) { + + material.bumpMap = getTexture( data.bumpMap ); + if ( data.bumpScale ) { + material.bumpScale = new THREE.Vector2( data.bumpScale, data.bumpScale ); + } + + } + + if ( data.alphaMap !== undefined ) { + + material.alphaMap = getTexture( data.alphaMap ); + + } + + if ( data.envMap !== undefined ) { + + material.envMap = getTexture( data.envMap ); + + } + + if ( data.normalMap !== undefined ) { + + material.normalMap = getTexture( data.normalMap ); + if ( data.normalScale ) { + material.normalScale = new THREE.Vector2( data.normalScale, data.normalScale ); + } + + } + + if ( data.lightMap !== undefined ) { + + material.lightMap = getTexture( data.lightMap ); + + } + + if ( data.specularMap !== undefined ) { + + material.specularMap = getTexture( data.specularMap ); + + } + materials[ data.uuid ] = material; } @@ -12588,6 +12939,94 @@ THREE.ObjectLoader.prototype = { }, + parseImages: function ( json, onLoad ) { + + var scope = this; + var images = {}; + + if ( json !== undefined && json.length > 0 ) { + + var manager = new THREE.LoadingManager( onLoad ); + + var loader = new THREE.ImageLoader( manager ); + loader.setCrossOrigin( this.crossOrigin ); + + var loadImage = function ( url ) { + + scope.manager.itemStart( url ); + + return loader.load( url, function () { + + scope.manager.itemEnd( url ); + + } ); + + }; + + for ( var i = 0, l = json.length; i < l; i ++ ) { + + var image = json[ i ]; + var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( image.url ) ? image.url : scope.texturePath + image.url; + + images[ image.uuid ] = loadImage( path ); + + } + + } + + return images; + + }, + + parseTextures: function ( json, images ) { + + var textures = {}; + + if ( json !== undefined ) { + + for ( var i = 0, l = json.length; i < l; i ++ ) { + + var data = json[ i ]; + + if ( data.image === undefined ) { + + THREE.warn( 'THREE.ObjectLoader: No "image" speficied for', data.uuid ); + + } + + if ( images[ data.image ] === undefined ) { + + THREE.warn( 'THREE.ObjectLoader: Undefined image', data.image ); + + } + + var texture = new THREE.Texture( images[ data.image ] ); + texture.needsUpdate = true; + + texture.uuid = data.uuid; + + if ( data.name !== undefined ) texture.name = data.name; + if ( data.repeat !== undefined ) texture.repeat = new THREE.Vector2( data.repeat[ 0 ], data.repeat[ 1 ] ); + if ( data.minFilter !== undefined ) texture.minFilter = THREE[ data.minFilter ]; + if ( data.magFilter !== undefined ) texture.magFilter = THREE[ data.magFilter ]; + if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy; + if ( data.wrap instanceof Array ) { + + texture.wrapS = THREE[ data.wrap[ 0 ] ]; + texture.wrapT = THREE[ data.wrap[ 1 ] ]; + + } + + textures[ data.uuid ] = texture; + + } + + } + + return textures; + + }, + parseObject: function () { var matrix = new THREE.Matrix4(); @@ -12596,6 +13035,30 @@ THREE.ObjectLoader.prototype = { var object; + var getGeometry = function ( name ) { + + if ( geometries[ name ] === undefined ) { + + THREE.warn( 'THREE.ObjectLoader: Undefined geometry', name ); + + } + + return geometries[ name ]; + + }; + + var getMaterial = function ( name ) { + + if ( materials[ name ] === undefined ) { + + THREE.warn( 'THREE.ObjectLoader: Undefined material', name ); + + } + + return materials[ name ]; + + }; + switch ( data.type ) { case 'Scene': @@ -12630,13 +13093,13 @@ THREE.ObjectLoader.prototype = { case 'PointLight': - object = new THREE.PointLight( data.color, data.intensity, data.distance ); + object = new THREE.PointLight( data.color, data.intensity, data.distance, data.decay ); break; case 'SpotLight': - object = new THREE.SpotLight( data.color, data.intensity, data.distance, data.angle, data.exponent ); + object = new THREE.SpotLight( data.color, data.intensity, data.distance, data.angle, data.exponent, data.decay ); break; @@ -12648,57 +13111,25 @@ THREE.ObjectLoader.prototype = { case 'Mesh': - var geometry = geometries[ data.geometry ]; - var material = materials[ data.material ]; - - if ( geometry === undefined ) { - - console.warn( 'THREE.ObjectLoader: Undefined geometry', data.geometry ); - - } - - if ( material === undefined ) { - - console.warn( 'THREE.ObjectLoader: Undefined material', data.material ); - - } - - object = new THREE.Mesh( geometry, material ); + object = new THREE.Mesh( getGeometry( data.geometry ), getMaterial( data.material ) ); break; case 'Line': - var geometry = geometries[ data.geometry ]; - var material = materials[ data.material ]; - - if ( geometry === undefined ) { + object = new THREE.Line( getGeometry( data.geometry ), getMaterial( data.material ), data.mode ); - console.warn( 'THREE.ObjectLoader: Undefined geometry', data.geometry ); - - } - - if ( material === undefined ) { - - console.warn( 'THREE.ObjectLoader: Undefined material', data.material ); + break; - } + case 'PointCloud': - object = new THREE.Line( geometry, material ); + object = new THREE.PointCloud( getGeometry( data.geometry ), getMaterial( data.material ) ); break; case 'Sprite': - var material = materials[ data.material ]; - - if ( material === undefined ) { - - console.warn( 'THREE.ObjectLoader: Undefined material', data.material ); - - } - - object = new THREE.Sprite( material ); + object = new THREE.Sprite( getMaterial( data.material ) ); break; @@ -12796,6 +13227,96 @@ THREE.TextureLoader.prototype = { }; +// File:src/loaders/BinaryTextureLoader.js + +/** + * @author Nikos M. / https://github.com/foo123/ + * + * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...) + */ + +THREE.DataTextureLoader = THREE.BinaryTextureLoader = function () { + + // override in sub classes + this._parser = null; + +}; + +THREE.BinaryTextureLoader.prototype = { + + constructor: THREE.BinaryTextureLoader, + + load: function ( url, onLoad, onProgress, onError ) { + + var scope = this; + + var texture = new THREE.DataTexture( ); + + var loader = new THREE.XHRLoader(); + loader.setResponseType( 'arraybuffer' ); + + loader.load( url, function ( buffer ) { + + var texData = scope._parser( buffer ); + + if ( !texData ) return; + + if ( undefined !== texData.image ) { + + texture.image = texData.image; + + } else if ( undefined !== texData.data ) { + + texture.image.width = texData.width; + texture.image.height = texData.height; + texture.image.data = texData.data; + + } + + texture.wrapS = undefined !== texData.wrapS ? texData.wrapS : THREE.ClampToEdgeWrapping; + texture.wrapT = undefined !== texData.wrapT ? texData.wrapT : THREE.ClampToEdgeWrapping; + + texture.magFilter = undefined !== texData.magFilter ? texData.magFilter : THREE.LinearFilter; + texture.minFilter = undefined !== texData.minFilter ? texData.minFilter : THREE.LinearMipMapLinearFilter; + + texture.anisotropy = undefined !== texData.anisotropy ? texData.anisotropy : 1; + + if ( undefined !== texData.format ) { + + texture.format = texData.format; + + } + if ( undefined !== texData.type ) { + + texture.type = texData.type; + + } + + if ( undefined !== texData.mipmaps ) { + + texture.mipmaps = texData.mipmaps; + + } + + if ( 1 === texData.mipmapCount ) { + + texture.minFilter = THREE.LinearFilter; + + } + + texture.needsUpdate = true; + + if ( onLoad ) onLoad( texture, texData ); + + }, onProgress, onError ); + + + return texture; + + } + +}; + // File:src/loaders/CompressedTextureLoader.js /** @@ -12849,7 +13370,7 @@ THREE.CompressedTextureLoader.prototype = { if ( loaded === 6 ) { - if (texDatas.mipmapCount == 1) + if (texDatas.mipmapCount == 1) texture.minFilter = THREE.LinearFilter; texture.format = texDatas.format; @@ -12951,10 +13472,15 @@ THREE.Material = function () { this.blendSrc = THREE.SrcAlphaFactor; this.blendDst = THREE.OneMinusSrcAlphaFactor; this.blendEquation = THREE.AddEquation; + this.blendSrcAlpha = null; + this.blendDstAlpha = null; + this.blendEquationAlpha = null; this.depthTest = true; this.depthWrite = true; + this.colorWrite = true; + this.polygonOffset = false; this.polygonOffsetFactor = 0; this.polygonOffsetUnits = 0; @@ -12965,7 +13491,7 @@ THREE.Material = function () { this.visible = true; - this.needsUpdate = true; + this._needsUpdate = true; }; @@ -12973,6 +13499,20 @@ THREE.Material.prototype = { constructor: THREE.Material, + get needsUpdate () { + + return this._needsUpdate; + + }, + + set needsUpdate ( value ) { + + if ( value === true ) this.update(); + + this._needsUpdate = value; + + }, + setValues: function ( values ) { if ( values === undefined ) return; @@ -12983,7 +13523,7 @@ THREE.Material.prototype = { if ( newValue === undefined ) { - console.warn( "THREE.Material: '" + key + "' parameter is undefined." ); + THREE.warn( "THREE.Material: '" + key + "' parameter is undefined." ); continue; } @@ -13041,26 +13581,25 @@ THREE.Material.prototype = { } else if ( this instanceof THREE.MeshLambertMaterial ) { output.color = this.color.getHex(); - output.ambient = this.ambient.getHex(); output.emissive = this.emissive.getHex(); if ( this.vertexColors !== THREE.NoColors ) output.vertexColors = this.vertexColors; + if ( this.shading !== THREE.SmoothShading ) output.shading = this.shading; if ( this.blending !== THREE.NormalBlending ) output.blending = this.blending; if ( this.side !== THREE.FrontSide ) output.side = this.side; } else if ( this instanceof THREE.MeshPhongMaterial ) { output.color = this.color.getHex(); - output.ambient = this.ambient.getHex(); output.emissive = this.emissive.getHex(); output.specular = this.specular.getHex(); output.shininess = this.shininess; if ( this.vertexColors !== THREE.NoColors ) output.vertexColors = this.vertexColors; + if ( this.shading !== THREE.SmoothShading ) output.shading = this.shading; if ( this.blending !== THREE.NormalBlending ) output.blending = this.blending; if ( this.side !== THREE.FrontSide ) output.side = this.side; } else if ( this instanceof THREE.MeshNormalMaterial ) { - if ( this.shading !== THREE.FlatShading ) output.shading = this.shading; if ( this.blending !== THREE.NormalBlending ) output.blending = this.blending; if ( this.side !== THREE.FrontSide ) output.side = this.side; @@ -13069,6 +13608,15 @@ THREE.Material.prototype = { if ( this.blending !== THREE.NormalBlending ) output.blending = this.blending; if ( this.side !== THREE.FrontSide ) output.side = this.side; + } else if ( this instanceof THREE.PointCloudMaterial ) { + + output.size = this.size; + output.sizeAttenuation = this.sizeAttenuation; + output.color = this.color.getHex(); + + if ( this.vertexColors !== THREE.NoColors ) output.vertexColors = this.vertexColors; + if ( this.blending !== THREE.NormalBlending ) output.blending = this.blending; + } else if ( this instanceof THREE.ShaderMaterial ) { output.uniforms = this.uniforms; @@ -13105,6 +13653,9 @@ THREE.Material.prototype = { material.blendSrc = this.blendSrc; material.blendDst = this.blendDst; material.blendEquation = this.blendEquation; + material.blendSrcAlpha = this.blendSrcAlpha; + material.blendDstAlpha = this.blendDstAlpha; + material.blendEquationAlpha = this.blendEquationAlpha; material.depthTest = this.depthTest; material.depthWrite = this.depthWrite; @@ -13123,6 +13674,12 @@ THREE.Material.prototype = { }, + update: function () { + + this.dispatchEvent( { type: 'update' } ); + + }, + dispose: function () { this.dispatchEvent( { type: 'dispose' } ); @@ -13180,6 +13737,7 @@ THREE.LineBasicMaterial = function ( parameters ) { }; THREE.LineBasicMaterial.prototype = Object.create( THREE.Material.prototype ); +THREE.LineBasicMaterial.prototype.constructor = THREE.LineBasicMaterial; THREE.LineBasicMaterial.prototype.clone = function () { @@ -13249,6 +13807,7 @@ THREE.LineDashedMaterial = function ( parameters ) { }; THREE.LineDashedMaterial.prototype = Object.create( THREE.Material.prototype ); +THREE.LineDashedMaterial.prototype.constructor = THREE.LineDashedMaterial; THREE.LineDashedMaterial.prototype.clone = function () { @@ -13351,6 +13910,7 @@ THREE.MeshBasicMaterial = function ( parameters ) { }; THREE.MeshBasicMaterial.prototype = Object.create( THREE.Material.prototype ); +THREE.MeshBasicMaterial.prototype.constructor = THREE.MeshBasicMaterial; THREE.MeshBasicMaterial.prototype.clone = function () { @@ -13399,7 +13959,6 @@ THREE.MeshBasicMaterial.prototype.clone = function () { * * parameters = { * color: <hex>, - * ambient: <hex>, * emissive: <hex>, * opacity: <float>, * @@ -13441,7 +14000,6 @@ THREE.MeshLambertMaterial = function ( parameters ) { this.type = 'MeshLambertMaterial'; this.color = new THREE.Color( 0xffffff ); // diffuse - this.ambient = new THREE.Color( 0xffffff ); this.emissive = new THREE.Color( 0x000000 ); this.wrapAround = false; @@ -13480,6 +14038,7 @@ THREE.MeshLambertMaterial = function ( parameters ) { }; THREE.MeshLambertMaterial.prototype = Object.create( THREE.Material.prototype ); +THREE.MeshLambertMaterial.prototype.constructor = THREE.MeshLambertMaterial; THREE.MeshLambertMaterial.prototype.clone = function () { @@ -13488,7 +14047,6 @@ THREE.MeshLambertMaterial.prototype.clone = function () { THREE.Material.prototype.clone.call( this, material ); material.color.copy( this.color ); - material.ambient.copy( this.ambient ); material.emissive.copy( this.emissive ); material.wrapAround = this.wrapAround; @@ -13534,7 +14092,6 @@ THREE.MeshLambertMaterial.prototype.clone = function () { * * parameters = { * color: <hex>, - * ambient: <hex>, * emissive: <hex>, * specular: <hex>, * shininess: <float>, @@ -13584,7 +14141,6 @@ THREE.MeshPhongMaterial = function ( parameters ) { this.type = 'MeshPhongMaterial'; this.color = new THREE.Color( 0xffffff ); // diffuse - this.ambient = new THREE.Color( 0xffffff ); this.emissive = new THREE.Color( 0x000000 ); this.specular = new THREE.Color( 0x111111 ); this.shininess = 30; @@ -13633,6 +14189,7 @@ THREE.MeshPhongMaterial = function ( parameters ) { }; THREE.MeshPhongMaterial.prototype = Object.create( THREE.Material.prototype ); +THREE.MeshPhongMaterial.prototype.constructor = THREE.MeshPhongMaterial; THREE.MeshPhongMaterial.prototype.clone = function () { @@ -13641,7 +14198,6 @@ THREE.MeshPhongMaterial.prototype.clone = function () { THREE.Material.prototype.clone.call( this, material ); material.color.copy( this.color ); - material.ambient.copy( this.ambient ); material.emissive.copy( this.emissive ); material.specular.copy( this.specular ); material.shininess = this.shininess; @@ -13722,6 +14278,7 @@ THREE.MeshDepthMaterial = function ( parameters ) { }; THREE.MeshDepthMaterial.prototype = Object.create( THREE.Material.prototype ); +THREE.MeshDepthMaterial.prototype.constructor = THREE.MeshDepthMaterial; THREE.MeshDepthMaterial.prototype.clone = function () { @@ -13760,8 +14317,6 @@ THREE.MeshNormalMaterial = function ( parameters ) { this.type = 'MeshNormalMaterial'; - this.shading = THREE.FlatShading; - this.wireframe = false; this.wireframeLinewidth = 1; @@ -13772,6 +14327,7 @@ THREE.MeshNormalMaterial = function ( parameters ) { }; THREE.MeshNormalMaterial.prototype = Object.create( THREE.Material.prototype ); +THREE.MeshNormalMaterial.prototype.constructor = THREE.MeshNormalMaterial; THREE.MeshNormalMaterial.prototype.clone = function () { @@ -13779,8 +14335,6 @@ THREE.MeshNormalMaterial.prototype.clone = function () { THREE.Material.prototype.clone.call( this, material ); - material.shading = this.shading; - material.wireframe = this.wireframe; material.wireframeLinewidth = this.wireframeLinewidth; @@ -13859,6 +14413,7 @@ THREE.MeshFaceMaterial.prototype = { * map: new THREE.Texture( <Image> ), * * size: <float>, + * sizeAttenuation: <bool>, * * blending: THREE.NormalBlending, * depthTest: <bool>, @@ -13892,6 +14447,7 @@ THREE.PointCloudMaterial = function ( parameters ) { }; THREE.PointCloudMaterial.prototype = Object.create( THREE.Material.prototype ); +THREE.PointCloudMaterial.prototype.constructor = THREE.PointCloudMaterial; THREE.PointCloudMaterial.prototype.clone = function () { @@ -13918,14 +14474,14 @@ THREE.PointCloudMaterial.prototype.clone = function () { THREE.ParticleBasicMaterial = function ( parameters ) { - console.warn( 'THREE.ParticleBasicMaterial has been renamed to THREE.PointCloudMaterial.' ); + THREE.warn( 'THREE.ParticleBasicMaterial has been renamed to THREE.PointCloudMaterial.' ); return new THREE.PointCloudMaterial( parameters ); }; THREE.ParticleSystemMaterial = function ( parameters ) { - console.warn( 'THREE.ParticleSystemMaterial has been renamed to THREE.PointCloudMaterial.' ); + THREE.warn( 'THREE.ParticleSystemMaterial has been renamed to THREE.PointCloudMaterial.' ); return new THREE.PointCloudMaterial( parameters ); }; @@ -14008,6 +14564,7 @@ THREE.ShaderMaterial = function ( parameters ) { }; THREE.ShaderMaterial.prototype = Object.create( THREE.Material.prototype ); +THREE.ShaderMaterial.prototype.constructor = THREE.ShaderMaterial; THREE.ShaderMaterial.prototype.clone = function () { @@ -14058,6 +14615,7 @@ THREE.RawShaderMaterial = function ( parameters ) { }; THREE.RawShaderMaterial.prototype = Object.create( THREE.ShaderMaterial.prototype ); +THREE.RawShaderMaterial.prototype.constructor = THREE.RawShaderMaterial; THREE.RawShaderMaterial.prototype.clone = function () { @@ -14110,6 +14668,7 @@ THREE.SpriteMaterial = function ( parameters ) { }; THREE.SpriteMaterial.prototype = Object.create( THREE.Material.prototype ); +THREE.SpriteMaterial.prototype.constructor = THREE.SpriteMaterial; THREE.SpriteMaterial.prototype.clone = function () { @@ -14143,6 +14702,7 @@ THREE.Texture = function ( image, mapping, wrapS, wrapT, magFilter, minFilter, f this.uuid = THREE.Math.generateUUID(); this.name = ''; + this.sourceFile = ''; this.image = image !== undefined ? image : THREE.Texture.DEFAULT_IMAGE; this.mipmaps = []; @@ -14174,7 +14734,7 @@ THREE.Texture = function ( image, mapping, wrapS, wrapT, magFilter, minFilter, f }; THREE.Texture.DEFAULT_IMAGE = undefined; -THREE.Texture.DEFAULT_MAPPING = new THREE.UVMapping(); +THREE.Texture.DEFAULT_MAPPING = THREE.UVMapping; THREE.Texture.prototype = { @@ -14252,6 +14812,8 @@ THREE.TextureIdCount = 0; THREE.CubeTexture = function ( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) { + mapping = mapping !== undefined ? mapping : THREE.CubeReflectionMapping; + THREE.Texture.call( this, images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); this.images = images; @@ -14259,6 +14821,7 @@ THREE.CubeTexture = function ( images, mapping, wrapS, wrapT, magFilter, minFilt }; THREE.CubeTexture.prototype = Object.create( THREE.Texture.prototype ); +THREE.CubeTexture.prototype.constructor = THREE.CubeTexture; THREE.CubeTexture.clone = function ( texture ) { @@ -14298,6 +14861,7 @@ THREE.CompressedTexture = function ( mipmaps, width, height, format, type, mappi }; THREE.CompressedTexture.prototype = Object.create( THREE.Texture.prototype ); +THREE.CompressedTexture.prototype.constructor = THREE.CompressedTexture; THREE.CompressedTexture.prototype.clone = function () { @@ -14324,6 +14888,7 @@ THREE.DataTexture = function ( data, width, height, format, type, mapping, wrapS }; THREE.DataTexture.prototype = Object.create( THREE.Texture.prototype ); +THREE.DataTexture.prototype.constructor = THREE.DataTexture; THREE.DataTexture.prototype.clone = function () { @@ -14366,6 +14931,7 @@ THREE.VideoTexture = function ( video, mapping, wrapS, wrapT, magFilter, minFilt }; THREE.VideoTexture.prototype = Object.create( THREE.Texture.prototype ); +THREE.VideoTexture.prototype.constructor = THREE.VideoTexture; // File:src/objects/Group.js @@ -14382,6 +14948,7 @@ THREE.Group = function () { }; THREE.Group.prototype = Object.create( THREE.Object3D.prototype ); +THREE.Group.prototype.constructor = THREE.Group; // File:src/objects/PointCloud.js @@ -14398,11 +14965,10 @@ THREE.PointCloud = function ( geometry, material ) { this.geometry = geometry !== undefined ? geometry : new THREE.Geometry(); this.material = material !== undefined ? material : new THREE.PointCloudMaterial( { color: Math.random() * 0xffffff } ); - this.sortParticles = false; - }; THREE.PointCloud.prototype = Object.create( THREE.Object3D.prototype ); +THREE.PointCloud.prototype.constructor = THREE.PointCloud; THREE.PointCloud.prototype.raycast = ( function () { @@ -14479,7 +15045,7 @@ THREE.PointCloud.prototype.raycast = ( function () { } - for ( var oi = 0, ol = offsets.length; oi < ol; ++oi ) { + for ( var oi = 0, ol = offsets.length; oi < ol; ++ oi ) { var start = offsets[ oi ].start; var count = offsets[ oi ].count; @@ -14535,8 +15101,6 @@ THREE.PointCloud.prototype.clone = function ( object ) { if ( object === undefined ) object = new THREE.PointCloud( this.geometry, this.material ); - object.sortParticles = this.sortParticles; - THREE.Object3D.prototype.clone.call( this, object ); return object; @@ -14547,7 +15111,7 @@ THREE.PointCloud.prototype.clone = function ( object ) { THREE.ParticleSystem = function ( geometry, material ) { - console.warn( 'THREE.ParticleSystem has been renamed to THREE.PointCloud.' ); + THREE.warn( 'THREE.ParticleSystem has been renamed to THREE.PointCloud.' ); return new THREE.PointCloud( geometry, material ); }; @@ -14567,7 +15131,7 @@ THREE.Line = function ( geometry, material, mode ) { this.geometry = geometry !== undefined ? geometry : new THREE.Geometry(); this.material = material !== undefined ? material : new THREE.LineBasicMaterial( { color: Math.random() * 0xffffff } ); - this.mode = ( mode !== undefined ) ? mode : THREE.LineStrip; + this.mode = mode !== undefined ? mode : THREE.LineStrip; }; @@ -14575,6 +15139,7 @@ THREE.LineStrip = 0; THREE.LinePieces = 1; THREE.Line.prototype = Object.create( THREE.Object3D.prototype ); +THREE.Line.prototype.constructor = THREE.Line; THREE.Line.prototype.raycast = ( function () { @@ -14605,17 +15170,108 @@ THREE.Line.prototype.raycast = ( function () { inverseMatrix.getInverse( this.matrixWorld ); ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix ); - /* if ( geometry instanceof THREE.BufferGeometry ) { + var vStart = new THREE.Vector3(); + var vEnd = new THREE.Vector3(); + var interSegment = new THREE.Vector3(); + var interRay = new THREE.Vector3(); + var step = this.mode === THREE.LineStrip ? 1 : 2; - } else */ if ( geometry instanceof THREE.Geometry ) { + if ( geometry instanceof THREE.BufferGeometry ) { + + var attributes = geometry.attributes; + + if ( attributes.index !== undefined ) { + + var indices = attributes.index.array; + var positions = attributes.position.array; + var offsets = geometry.offsets; + + if ( offsets.length === 0 ) { + + offsets = [ { start: 0, count: indices.length, index: 0 } ]; + + } + + for ( var oi = 0; oi < offsets.length; oi ++) { + + var start = offsets[ oi ].start; + var count = offsets[ oi ].count; + var index = offsets[ oi ].index; + + for ( var i = start; i < start + count - 1; i += step ) { + + var a = index + indices[ i ]; + var b = index + indices[ i + 1 ]; + + vStart.fromArray( positions, a * 3 ); + vEnd.fromArray( positions, b * 3 ); + + var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment ); + + if ( distSq > precisionSq ) continue; + + var distance = ray.origin.distanceTo( interRay ); + + if ( distance < raycaster.near || distance > raycaster.far ) continue; + + intersects.push( { + + distance: distance, + // What do we want? intersection point on the ray or on the segment?? + // point: raycaster.ray.at( distance ), + point: interSegment.clone().applyMatrix4( this.matrixWorld ), + index: i, + offsetIndex: oi, + face: null, + faceIndex: null, + object: this + + } ); + + } + + } + + } else { + + var positions = attributes.position.array; + + for ( var i = 0; i < positions.length / 3 - 1; i += step ) { + + vStart.fromArray( positions, 3 * i ); + vEnd.fromArray( positions, 3 * i + 3 ); + + var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment ); + + if ( distSq > precisionSq ) continue; + + var distance = ray.origin.distanceTo( interRay ); + + if ( distance < raycaster.near || distance > raycaster.far ) continue; + + intersects.push( { + + distance: distance, + // What do we want? intersection point on the ray or on the segment?? + // point: raycaster.ray.at( distance ), + point: interSegment.clone().applyMatrix4( this.matrixWorld ), + index: i, + face: null, + faceIndex: null, + object: this + + } ); + + } + + } + + } else if ( geometry instanceof THREE.Geometry ) { var vertices = geometry.vertices; var nbVertices = vertices.length; - var interSegment = new THREE.Vector3(); - var interRay = new THREE.Vector3(); - var step = this.mode === THREE.LineStrip ? 1 : 2; - for ( var i = 0; i < nbVertices - 1; i = i + step ) { + for ( var i = 0; i < nbVertices - 1; i += step ) { var distSq = ray.distanceSqToSegment( vertices[ i ], vertices[ i + 1 ], interRay, interSegment ); @@ -14631,6 +15287,7 @@ THREE.Line.prototype.raycast = ( function () { // What do we want? intersection point on the ray or on the segment?? // point: raycaster.ray.at( distance ), point: interSegment.clone().applyMatrix4( this.matrixWorld ), + index: i, face: null, faceIndex: null, object: this @@ -14678,6 +15335,7 @@ THREE.Mesh = function ( geometry, material ) { }; THREE.Mesh.prototype = Object.create( THREE.Object3D.prototype ); +THREE.Mesh.prototype.constructor = THREE.Mesh; THREE.Mesh.prototype.updateMorphTargets = function () { @@ -14707,7 +15365,7 @@ THREE.Mesh.prototype.getMorphTargetIndexByName = function ( name ) { } - console.log( 'THREE.Mesh.getMorphTargetIndexByName: morph target ' + name + ' does not exist. Returning 0.' ); + THREE.warn( 'THREE.Mesh.getMorphTargetIndexByName: morph target ' + name + ' does not exist. Returning 0.' ); return 0; @@ -14748,7 +15406,7 @@ THREE.Mesh.prototype.raycast = ( function () { if ( geometry.boundingBox !== null ) { - if ( ray.isIntersectionBox( geometry.boundingBox ) === false ) { + if ( ray.isIntersectionBox( geometry.boundingBox ) === false ) { return; @@ -14779,7 +15437,7 @@ THREE.Mesh.prototype.raycast = ( function () { } - for ( var oi = 0, ol = offsets.length; oi < ol; ++oi ) { + for ( var oi = 0, ol = offsets.length; oi < ol; ++ oi ) { var start = offsets[ oi ].start; var count = offsets[ oi ].count; @@ -14878,7 +15536,7 @@ THREE.Mesh.prototype.raycast = ( function () { var isFaceMaterial = this.material instanceof THREE.MeshFaceMaterial; var objectMaterials = isFaceMaterial === true ? this.material.materials : null; - var a, b, c, d; + var a, b, c; var precision = raycaster.precision; var vertices = geometry.vertices; @@ -14990,16 +15648,18 @@ THREE.Mesh.prototype.clone = function ( object, recursive ) { * @author ikerr / http://verold.com */ -THREE.Bone = function ( belongsToSkin ) { +THREE.Bone = function ( skin ) { THREE.Object3D.call( this ); - this.skin = belongsToSkin; + this.type = 'Bone'; + + this.skin = skin; }; THREE.Bone.prototype = Object.create( THREE.Object3D.prototype ); - +THREE.Bone.prototype.constructor = THREE.Bone; // File:src/objects/Skeleton.js @@ -15074,7 +15734,7 @@ THREE.Skeleton = function ( bones, boneInverses, useVertexTexture ) { } else { - console.warn( 'THREE.Skeleton bonInverses is the wrong length.' ); + THREE.warn( 'THREE.Skeleton bonInverses is the wrong length.' ); this.boneInverses = []; @@ -15214,7 +15874,7 @@ THREE.SkinnedMesh = function ( geometry, material, useVertexTexture ) { var bone, gbone, p, q, s; - for ( var b = 0, bl = this.geometry.bones.length; b < bl; ++b ) { + for ( var b = 0, bl = this.geometry.bones.length; b < bl; ++ b ) { gbone = this.geometry.bones[ b ]; @@ -15241,7 +15901,7 @@ THREE.SkinnedMesh = function ( geometry, material, useVertexTexture ) { } - for ( var b = 0, bl = this.geometry.bones.length; b < bl; ++b ) { + for ( var b = 0, bl = this.geometry.bones.length; b < bl; ++ b ) { gbone = this.geometry.bones[ b ]; @@ -15268,6 +15928,7 @@ THREE.SkinnedMesh = function ( geometry, material, useVertexTexture ) { THREE.SkinnedMesh.prototype = Object.create( THREE.Mesh.prototype ); +THREE.SkinnedMesh.prototype.constructor = THREE.SkinnedMesh; THREE.SkinnedMesh.prototype.bind = function( skeleton, bindMatrix ) { @@ -15336,7 +15997,7 @@ THREE.SkinnedMesh.prototype.updateMatrixWorld = function( force ) { } else { - console.warn( 'THREE.SkinnedMesh unreckognized bindMode: ' + this.bindMode ); + THREE.warn( 'THREE.SkinnedMesh unreckognized bindMode: ' + this.bindMode ); } @@ -15388,6 +16049,7 @@ THREE.MorphAnimMesh = function ( geometry, material ) { }; THREE.MorphAnimMesh.prototype = Object.create( THREE.Mesh.prototype ); +THREE.MorphAnimMesh.prototype.constructor = THREE.MorphAnimMesh; THREE.MorphAnimMesh.prototype.setFrameRange = function ( start, end ) { @@ -15430,7 +16092,6 @@ THREE.MorphAnimMesh.prototype.parseAnimations = function () { if ( parts && parts.length > 1 ) { var label = parts[ 1 ]; - var num = parts[ 2 ]; if ( ! animations[ label ] ) animations[ label ] = { start: Infinity, end: - Infinity }; @@ -15469,7 +16130,7 @@ THREE.MorphAnimMesh.prototype.playAnimation = function ( label, fps ) { } else { - console.warn( 'animation[' + label + '] undefined' ); + THREE.warn( 'THREE.MorphAnimMesh: animation[' + label + '] undefined in .playAnimation()' ); } @@ -15591,6 +16252,7 @@ THREE.LOD = function () { THREE.LOD.prototype = Object.create( THREE.Object3D.prototype ); +THREE.LOD.prototype.constructor = THREE.LOD; THREE.LOD.prototype.addLevel = function ( object, distance ) { @@ -15736,6 +16398,7 @@ THREE.Sprite = ( function () { } )(); THREE.Sprite.prototype = Object.create( THREE.Object3D.prototype ); +THREE.Sprite.prototype.constructor = THREE.Sprite; THREE.Sprite.prototype.raycast = ( function () { @@ -15796,7 +16459,7 @@ THREE.LensFlare = function ( texture, size, distance, blending, color ) { this.positionScreen = new THREE.Vector3(); this.customUpdateCallback = undefined; - if( texture !== undefined ) { + if ( texture !== undefined ) { this.add( texture, size, distance, blending, color ); @@ -15805,6 +16468,7 @@ THREE.LensFlare = function ( texture, size, distance, blending, color ) { }; THREE.LensFlare.prototype = Object.create( THREE.Object3D.prototype ); +THREE.LensFlare.prototype.constructor = THREE.LensFlare; /* @@ -15847,7 +16511,7 @@ THREE.LensFlare.prototype.updateLensFlares = function () { var vecX = - this.positionScreen.x * 2; var vecY = - this.positionScreen.y * 2; - for( f = 0; f < fl; f ++ ) { + for ( f = 0; f < fl; f ++ ) { flare = this.lensFlares[ f ]; @@ -15882,6 +16546,7 @@ THREE.Scene = function () { }; THREE.Scene.prototype = Object.create( THREE.Object3D.prototype ); +THREE.Scene.prototype.constructor = THREE.Scene; THREE.Scene.prototype.clone = function ( object ) { @@ -15949,21 +16614,25 @@ THREE.FogExp2.prototype.clone = function () { THREE.ShaderChunk = {}; +// File:src/renderers/shaders/ShaderChunk/common.glsl + +THREE.ShaderChunk[ 'common'] = "#define PI 3.14159\n#define PI2 6.28318\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n\nfloat square( in float a ) { return a*a; }\nvec2 square( in vec2 a ) { return vec2( a.x*a.x, a.y*a.y ); }\nvec3 square( in vec3 a ) { return vec3( a.x*a.x, a.y*a.y, a.z*a.z ); }\nvec4 square( in vec4 a ) { return vec4( a.x*a.x, a.y*a.y, a.z*a.z, a.w*a.w ); }\nfloat saturate( in float a ) { return clamp( a, 0.0, 1.0 ); }\nvec2 saturate( in vec2 a ) { return clamp( a, 0.0, 1.0 ); }\nvec3 saturate( in vec3 a ) { return clamp( a, 0.0, 1.0 ); }\nvec4 saturate( in vec4 a ) { return clamp( a, 0.0, 1.0 ); }\nfloat average( in float a ) { return a; }\nfloat average( in vec2 a ) { return ( a.x + a.y) * 0.5; }\nfloat average( in vec3 a ) { return ( a.x + a.y + a.z) / 3.0; }\nfloat average( in vec4 a ) { return ( a.x + a.y + a.z + a.w) * 0.25; }\nfloat whiteCompliment( in float a ) { return saturate( 1.0 - a ); }\nvec2 whiteCompliment( in vec2 a ) { return saturate( vec2(1.0) - a ); }\nvec3 whiteCompliment( in vec3 a ) { return saturate( vec3(1.0) - a ); }\nvec4 whiteCompliment( in vec4 a ) { return saturate( vec4(1.0) - a ); }\nvec3 transformDirection( in vec3 normal, in mat4 matrix ) {\n return normalize( ( matrix * vec4( normal, 0.0 ) ).xyz );\n}\n// http://en.wikibooks.org/wiki/GLSL_Programming/Applying_Matrix_Transformations\nvec3 inverseTransformDirection( in vec3 normal, in mat4 matrix ) {\n return normalize( ( vec4( normal, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal) {\n float distance = dot( planeNormal, point-pointOnPlane );\n return point - distance * planeNormal;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n return sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n return pointOnLine + lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) );\n}\nfloat calcLightAttenuation( float lightDistance, float cutoffDistance, float decayExponent ) {\n if ( decayExponent > 0.0 ) {\n return pow( saturate( 1.0 - lightDistance / cutoffDistance ), decayExponent );\n }\n return 1.0;\n}\n\nvec3 inputToLinear( in vec3 a ) {\n#ifdef GAMMA_INPUT\n return pow( a, vec3( float( GAMMA_FACTOR ) ) );\n#else\n return a;\n#endif\n}\nvec3 linearToOutput( in vec3 a ) {\n#ifdef GAMMA_OUTPUT\n return pow( a, vec3( 1.0 / float( GAMMA_FACTOR ) ) );\n#else\n return a;\n#endif\n}\n"; + // File:src/renderers/shaders/ShaderChunk/alphatest_fragment.glsl -THREE.ShaderChunk[ 'alphatest_fragment'] = "#ifdef ALPHATEST\n\n if ( gl_FragColor.a < ALPHATEST ) discard;\n\n#endif\n"; +THREE.ShaderChunk[ 'alphatest_fragment'] = "#ifdef ALPHATEST\n\n if ( diffuseColor.a < ALPHATEST ) discard;\n\n#endif\n"; // File:src/renderers/shaders/ShaderChunk/lights_lambert_vertex.glsl -THREE.ShaderChunk[ 'lights_lambert_vertex'] = "vLightFront = vec3( 0.0 );\n\n#ifdef DOUBLE_SIDED\n\n vLightBack = vec3( 0.0 );\n\n#endif\n\ntransformedNormal = normalize( transformedNormal );\n\n#if MAX_DIR_LIGHTS > 0\n\nfor( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\n\n vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\n vec3 dirVector = normalize( lDirection.xyz );\n\n float dotProduct = dot( transformedNormal, dirVector );\n vec3 directionalLightWeighting = vec3( max( dotProduct, 0.0 ) );\n\n #ifdef DOUBLE_SIDED\n\n vec3 directionalLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n\n #ifdef WRAP_AROUND\n\n vec3 directionalLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n\n #endif\n\n #endif\n\n #ifdef WRAP_AROUND\n\n vec3 directionalLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\n directionalLightWeighting = mix( directionalLightWeighting, directionalLightWeightingHalf, wrapRGB );\n\n #ifdef DOUBLE_SIDED\n\n directionalLightWeightingBack = mix( directionalLightWeightingBack, directionalLightWeightingHalfBack, wrapRGB );\n\n #endif\n\n #endif\n\n vLightFront += directionalLightColor[ i ] * directionalLightWeighting;\n\n #ifdef DOUBLE_SIDED\n\n vLightBack += directionalLightColor[ i ] * directionalLightWeightingBack;\n\n #endif\n\n}\n\n#endif\n\n#if MAX_POINT_LIGHTS > 0\n\n for( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\n\n vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\n vec3 lVector = lPosition.xyz - mvPosition.xyz;\n\n float lDistance = 1.0;\n if ( pointLightDistance[ i ] > 0.0 )\n lDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\n\n lVector = normalize( lVector );\n float dotProduct = dot( transformedNormal, lVector );\n\n vec3 pointLightWeighting = vec3( max( dotProduct, 0.0 ) );\n\n #ifdef DOUBLE_SIDED\n\n vec3 pointLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n\n #ifdef WRAP_AROUND\n\n vec3 pointLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n\n #endif\n\n #endif\n\n #ifdef WRAP_AROUND\n\n vec3 pointLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\n pointLightWeighting = mix( pointLightWeighting, pointLightWeightingHalf, wrapRGB );\n\n #ifdef DOUBLE_SIDED\n\n pointLightWeightingBack = mix( pointLightWeightingBack, pointLightWeightingHalfBack, wrapRGB );\n\n #endif\n\n #endif\n\n vLightFront += pointLightColor[ i ] * pointLightWeighting * lDistance;\n\n #ifdef DOUBLE_SIDED\n\n vLightBack += pointLightColor[ i ] * pointLightWeightingBack * lDistance;\n\n #endif\n\n }\n\n#endif\n\n#if MAX_SPOT_LIGHTS > 0\n\n for( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\n\n vec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\n vec3 lVector = lPosition.xyz - mvPosition.xyz;\n\n float spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - worldPosition.xyz ) );\n\n if ( spotEffect > spotLightAngleCos[ i ] ) {\n\n spotEffect = max( pow( max( spotEffect, 0.0 ), spotLightExponent[ i ] ), 0.0 );\n\n float lDistance = 1.0;\n if ( spotLightDistance[ i ] > 0.0 )\n lDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\n\n lVector = normalize( lVector );\n\n float dotProduct = dot( transformedNormal, lVector );\n vec3 spotLightWeighting = vec3( max( dotProduct, 0.0 ) );\n\n #ifdef DOUBLE_SIDED\n\n vec3 spotLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n\n #ifdef WRAP_AROUND\n\n vec3 spotLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n\n #endif\n\n #endif\n\n #ifdef WRAP_AROUND\n\n vec3 spotLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\n spotLightWeighting = mix( spotLightWeighting, spotLightWeightingHalf, wrapRGB );\n\n #ifdef DOUBLE_SIDED\n\n spotLightWeightingBack = mix( spotLightWeightingBack, spotLightWeightingHalfBack, wrapRGB );\n\n #endif\n\n #endif\n\n vLightFront += spotLightColor[ i ] * spotLightWeighting * lDistance * spotEffect;\n\n #ifdef DOUBLE_SIDED\n\n vLightBack += spotLightColor[ i ] * spotLightWeightingBack * lDistance * spotEffect;\n\n #endif\n\n }\n\n }\n\n#endif\n\n#if MAX_HEMI_LIGHTS > 0\n\n for( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {\n\n vec4 lDirection = viewMatrix * vec4( hemisphereLightDirection[ i ], 0.0 );\n vec3 lVector = normalize( lDirection.xyz );\n\n float dotProduct = dot( transformedNormal, lVector );\n\n float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;\n float hemiDiffuseWeightBack = -0.5 * dotProduct + 0.5;\n\n vLightFront += mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );\n\n #ifdef DOUBLE_SIDED\n\n vLightBack += mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeightBack );\n\n #endif\n\n }\n\n#endif\n\nvLightFront = vLightFront * diffuse + ambient * ambientLightColor + emissive;\n\n#ifdef DOUBLE_SIDED\n\n vLightBack = vLightBack * diffuse + ambient * ambientLightColor + emissive;\n\n#endif"; +THREE.ShaderChunk[ 'lights_lambert_vertex'] = "vLightFront = vec3( 0.0 );\n\n#ifdef DOUBLE_SIDED\n\n vLightBack = vec3( 0.0 );\n\n#endif\n\ntransformedNormal = normalize( transformedNormal );\n\n#if MAX_DIR_LIGHTS > 0\n\nfor( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\n\n vec3 dirVector = transformDirection( directionalLightDirection[ i ], viewMatrix );\n\n float dotProduct = dot( transformedNormal, dirVector );\n vec3 directionalLightWeighting = vec3( max( dotProduct, 0.0 ) );\n\n #ifdef DOUBLE_SIDED\n\n vec3 directionalLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n\n #ifdef WRAP_AROUND\n\n vec3 directionalLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n\n #endif\n\n #endif\n\n #ifdef WRAP_AROUND\n\n vec3 directionalLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\n directionalLightWeighting = mix( directionalLightWeighting, directionalLightWeightingHalf, wrapRGB );\n\n #ifdef DOUBLE_SIDED\n\n directionalLightWeightingBack = mix( directionalLightWeightingBack, directionalLightWeightingHalfBack, wrapRGB );\n\n #endif\n\n #endif\n\n vLightFront += directionalLightColor[ i ] * directionalLightWeighting;\n\n #ifdef DOUBLE_SIDED\n\n vLightBack += directionalLightColor[ i ] * directionalLightWeightingBack;\n\n #endif\n\n}\n\n#endif\n\n#if MAX_POINT_LIGHTS > 0\n\n for( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\n\n vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\n vec3 lVector = lPosition.xyz - mvPosition.xyz;\n\n float attenuation = calcLightAttenuation( length( lVector ), pointLightDistance[ i ], pointLightDecay[ i ] );\n\n lVector = normalize( lVector );\n float dotProduct = dot( transformedNormal, lVector );\n\n vec3 pointLightWeighting = vec3( max( dotProduct, 0.0 ) );\n\n #ifdef DOUBLE_SIDED\n\n vec3 pointLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n\n #ifdef WRAP_AROUND\n\n vec3 pointLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n\n #endif\n\n #endif\n\n #ifdef WRAP_AROUND\n\n vec3 pointLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\n pointLightWeighting = mix( pointLightWeighting, pointLightWeightingHalf, wrapRGB );\n\n #ifdef DOUBLE_SIDED\n\n pointLightWeightingBack = mix( pointLightWeightingBack, pointLightWeightingHalfBack, wrapRGB );\n\n #endif\n\n #endif\n\n vLightFront += pointLightColor[ i ] * pointLightWeighting * attenuation;\n\n #ifdef DOUBLE_SIDED\n\n vLightBack += pointLightColor[ i ] * pointLightWeightingBack * attenuation;\n\n #endif\n\n }\n\n#endif\n\n#if MAX_SPOT_LIGHTS > 0\n\n for( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\n\n vec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\n vec3 lVector = lPosition.xyz - mvPosition.xyz;\n\n float spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - worldPosition.xyz ) );\n\n if ( spotEffect > spotLightAngleCos[ i ] ) {\n\n spotEffect = max( pow( max( spotEffect, 0.0 ), spotLightExponent[ i ] ), 0.0 );\n\n float attenuation = calcLightAttenuation( length( lVector ), spotLightDistance[ i ], spotLightDecay[ i ] );\n\n lVector = normalize( lVector );\n\n float dotProduct = dot( transformedNormal, lVector );\n vec3 spotLightWeighting = vec3( max( dotProduct, 0.0 ) );\n\n #ifdef DOUBLE_SIDED\n\n vec3 spotLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n\n #ifdef WRAP_AROUND\n\n vec3 spotLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n\n #endif\n\n #endif\n\n #ifdef WRAP_AROUND\n\n vec3 spotLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\n spotLightWeighting = mix( spotLightWeighting, spotLightWeightingHalf, wrapRGB );\n\n #ifdef DOUBLE_SIDED\n\n spotLightWeightingBack = mix( spotLightWeightingBack, spotLightWeightingHalfBack, wrapRGB );\n\n #endif\n\n #endif\n\n vLightFront += spotLightColor[ i ] * spotLightWeighting * attenuation * spotEffect;\n\n #ifdef DOUBLE_SIDED\n\n vLightBack += spotLightColor[ i ] * spotLightWeightingBack * attenuation * spotEffect;\n\n #endif\n\n }\n\n }\n\n#endif\n\n#if MAX_HEMI_LIGHTS > 0\n\n for( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {\n\n vec3 lVector = transformDirection( hemisphereLightDirection[ i ], viewMatrix );\n\n float dotProduct = dot( transformedNormal, lVector );\n\n float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;\n float hemiDiffuseWeightBack = -0.5 * dotProduct + 0.5;\n\n vLightFront += mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );\n\n #ifdef DOUBLE_SIDED\n\n vLightBack += mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeightBack );\n\n #endif\n\n }\n\n#endif\n\nvLightFront += ambientLightColor;\n\n#ifdef DOUBLE_SIDED\n\n vLightBack += ambientLightColor;\n\n#endif\n"; // File:src/renderers/shaders/ShaderChunk/map_particle_pars_fragment.glsl -THREE.ShaderChunk[ 'map_particle_pars_fragment'] = "#ifdef USE_MAP\n\n uniform sampler2D map;\n\n#endif"; +THREE.ShaderChunk[ 'map_particle_pars_fragment'] = "#ifdef USE_MAP\n\n uniform vec4 offsetRepeat;\n uniform sampler2D map;\n\n#endif\n"; // File:src/renderers/shaders/ShaderChunk/default_vertex.glsl -THREE.ShaderChunk[ 'default_vertex'] = "vec4 mvPosition;\n\n#ifdef USE_SKINNING\n\n mvPosition = modelViewMatrix * skinned;\n\n#endif\n\n#if !defined( USE_SKINNING ) && defined( USE_MORPHTARGETS )\n\n mvPosition = modelViewMatrix * vec4( morphed, 1.0 );\n\n#endif\n\n#if !defined( USE_SKINNING ) && ! defined( USE_MORPHTARGETS )\n\n mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\n#endif\n\ngl_Position = projectionMatrix * mvPosition;"; +THREE.ShaderChunk[ 'default_vertex'] = "#ifdef USE_SKINNING\n\n vec4 mvPosition = modelViewMatrix * skinned;\n\n#elif defined( USE_MORPHTARGETS )\n\n vec4 mvPosition = modelViewMatrix * vec4( morphed, 1.0 );\n\n#else\n\n vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\n#endif\n\ngl_Position = projectionMatrix * mvPosition;\n"; // File:src/renderers/shaders/ShaderChunk/map_pars_fragment.glsl @@ -15983,7 +16652,7 @@ THREE.ShaderChunk[ 'lightmap_pars_vertex'] = "#ifdef USE_LIGHTMAP\n\n varying ve // File:src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl -THREE.ShaderChunk[ 'lights_phong_fragment'] = "vec3 normal = normalize( vNormal );\nvec3 viewPosition = normalize( vViewPosition );\n\n#ifdef DOUBLE_SIDED\n\n normal = normal * ( -1.0 + 2.0 * float( gl_FrontFacing ) );\n\n#endif\n\n#ifdef USE_NORMALMAP\n\n normal = perturbNormal2Arb( -vViewPosition, normal );\n\n#elif defined( USE_BUMPMAP )\n\n normal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n\n#endif\n\n#if MAX_POINT_LIGHTS > 0\n\n vec3 pointDiffuse = vec3( 0.0 );\n vec3 pointSpecular = vec3( 0.0 );\n\n for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\n\n vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\n vec3 lVector = lPosition.xyz + vViewPosition.xyz;\n\n float lDistance = 1.0;\n if ( pointLightDistance[ i ] > 0.0 )\n lDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\n\n lVector = normalize( lVector );\n\n // diffuse\n\n float dotProduct = dot( normal, lVector );\n\n #ifdef WRAP_AROUND\n\n float pointDiffuseWeightFull = max( dotProduct, 0.0 );\n float pointDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\n\n vec3 pointDiffuseWeight = mix( vec3( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );\n\n #else\n\n float pointDiffuseWeight = max( dotProduct, 0.0 );\n\n #endif\n\n pointDiffuse += diffuse * pointLightColor[ i ] * pointDiffuseWeight * lDistance;\n\n // specular\n\n vec3 pointHalfVector = normalize( lVector + viewPosition );\n float pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );\n float pointSpecularWeight = specularStrength * max( pow( pointDotNormalHalf, shininess ), 0.0 );\n\n float specularNormalization = ( shininess + 2.0 ) / 8.0;\n\n vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, pointHalfVector ), 0.0 ), 5.0 );\n pointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance * specularNormalization;\n\n }\n\n#endif\n\n#if MAX_SPOT_LIGHTS > 0\n\n vec3 spotDiffuse = vec3( 0.0 );\n vec3 spotSpecular = vec3( 0.0 );\n\n for ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\n\n vec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\n vec3 lVector = lPosition.xyz + vViewPosition.xyz;\n\n float lDistance = 1.0;\n if ( spotLightDistance[ i ] > 0.0 )\n lDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );\n\n lVector = normalize( lVector );\n\n float spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) );\n\n if ( spotEffect > spotLightAngleCos[ i ] ) {\n\n spotEffect = max( pow( max( spotEffect, 0.0 ), spotLightExponent[ i ] ), 0.0 );\n\n // diffuse\n\n float dotProduct = dot( normal, lVector );\n\n #ifdef WRAP_AROUND\n\n float spotDiffuseWeightFull = max( dotProduct, 0.0 );\n float spotDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\n\n vec3 spotDiffuseWeight = mix( vec3( spotDiffuseWeightFull ), vec3( spotDiffuseWeightHalf ), wrapRGB );\n\n #else\n\n float spotDiffuseWeight = max( dotProduct, 0.0 );\n\n #endif\n\n spotDiffuse += diffuse * spotLightColor[ i ] * spotDiffuseWeight * lDistance * spotEffect;\n\n // specular\n\n vec3 spotHalfVector = normalize( lVector + viewPosition );\n float spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );\n float spotSpecularWeight = specularStrength * max( pow( spotDotNormalHalf, shininess ), 0.0 );\n\n float specularNormalization = ( shininess + 2.0 ) / 8.0;\n\n vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, spotHalfVector ), 0.0 ), 5.0 );\n spotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * specularNormalization * spotEffect;\n\n }\n\n }\n\n#endif\n\n#if MAX_DIR_LIGHTS > 0\n\n vec3 dirDiffuse = vec3( 0.0 );\n vec3 dirSpecular = vec3( 0.0 );\n\n for( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\n\n vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\n vec3 dirVector = normalize( lDirection.xyz );\n\n // diffuse\n\n float dotProduct = dot( normal, dirVector );\n\n #ifdef WRAP_AROUND\n\n float dirDiffuseWeightFull = max( dotProduct, 0.0 );\n float dirDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\n\n vec3 dirDiffuseWeight = mix( vec3( dirDiffuseWeightFull ), vec3( dirDiffuseWeightHalf ), wrapRGB );\n\n #else\n\n float dirDiffuseWeight = max( dotProduct, 0.0 );\n\n #endif\n\n dirDiffuse += diffuse * directionalLightColor[ i ] * dirDiffuseWeight;\n\n // specular\n\n vec3 dirHalfVector = normalize( dirVector + viewPosition );\n float dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );\n float dirSpecularWeight = specularStrength * max( pow( dirDotNormalHalf, shininess ), 0.0 );\n\n /*\n // fresnel term from skin shader\n const float F0 = 0.128;\n\n float base = 1.0 - dot( viewPosition, dirHalfVector );\n float exponential = pow( base, 5.0 );\n\n float fresnel = exponential + F0 * ( 1.0 - exponential );\n */\n\n /*\n // fresnel term from fresnel shader\n const float mFresnelBias = 0.08;\n const float mFresnelScale = 0.3;\n const float mFresnelPower = 5.0;\n\n float fresnel = mFresnelBias + mFresnelScale * pow( 1.0 + dot( normalize( -viewPosition ), normal ), mFresnelPower );\n */\n\n float specularNormalization = ( shininess + 2.0 ) / 8.0;\n\n // dirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization * fresnel;\n\n vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( dirVector, dirHalfVector ), 0.0 ), 5.0 );\n dirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;\n\n\n }\n\n#endif\n\n#if MAX_HEMI_LIGHTS > 0\n\n vec3 hemiDiffuse = vec3( 0.0 );\n vec3 hemiSpecular = vec3( 0.0 );\n\n for( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {\n\n vec4 lDirection = viewMatrix * vec4( hemisphereLightDirection[ i ], 0.0 );\n vec3 lVector = normalize( lDirection.xyz );\n\n // diffuse\n\n float dotProduct = dot( normal, lVector );\n float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;\n\n vec3 hemiColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );\n\n hemiDiffuse += diffuse * hemiColor;\n\n // specular (sky light)\n\n vec3 hemiHalfVectorSky = normalize( lVector + viewPosition );\n float hemiDotNormalHalfSky = 0.5 * dot( normal, hemiHalfVectorSky ) + 0.5;\n float hemiSpecularWeightSky = specularStrength * max( pow( max( hemiDotNormalHalfSky, 0.0 ), shininess ), 0.0 );\n\n // specular (ground light)\n\n vec3 lVectorGround = -lVector;\n\n vec3 hemiHalfVectorGround = normalize( lVectorGround + viewPosition );\n float hemiDotNormalHalfGround = 0.5 * dot( normal, hemiHalfVectorGround ) + 0.5;\n float hemiSpecularWeightGround = specularStrength * max( pow( max( hemiDotNormalHalfGround, 0.0 ), shininess ), 0.0 );\n\n float dotProductGround = dot( normal, lVectorGround );\n\n float specularNormalization = ( shininess + 2.0 ) / 8.0;\n\n vec3 schlickSky = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, hemiHalfVectorSky ), 0.0 ), 5.0 );\n vec3 schlickGround = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVectorGround, hemiHalfVectorGround ), 0.0 ), 5.0 );\n hemiSpecular += hemiColor * specularNormalization * ( schlickSky * hemiSpecularWeightSky * max( dotProduct, 0.0 ) + schlickGround * hemiSpecularWeightGround * max( dotProductGround, 0.0 ) );\n\n }\n\n#endif\n\nvec3 totalDiffuse = vec3( 0.0 );\nvec3 totalSpecular = vec3( 0.0 );\n\n#if MAX_DIR_LIGHTS > 0\n\n totalDiffuse += dirDiffuse;\n totalSpecular += dirSpecular;\n\n#endif\n\n#if MAX_HEMI_LIGHTS > 0\n\n totalDiffuse += hemiDiffuse;\n totalSpecular += hemiSpecular;\n\n#endif\n\n#if MAX_POINT_LIGHTS > 0\n\n totalDiffuse += pointDiffuse;\n totalSpecular += pointSpecular;\n\n#endif\n\n#if MAX_SPOT_LIGHTS > 0\n\n totalDiffuse += spotDiffuse;\n totalSpecular += spotSpecular;\n\n#endif\n\n#ifdef METAL\n\n gl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient + totalSpecular );\n\n#else\n\n gl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient ) + totalSpecular;\n\n#endif"; +THREE.ShaderChunk[ 'lights_phong_fragment'] = "#ifndef FLAT_SHADED\n\n vec3 normal = normalize( vNormal );\n\n #ifdef DOUBLE_SIDED\n\n normal = normal * ( -1.0 + 2.0 * float( gl_FrontFacing ) );\n\n #endif\n\n#else\n\n vec3 fdx = dFdx( vViewPosition );\n vec3 fdy = dFdy( vViewPosition );\n vec3 normal = normalize( cross( fdx, fdy ) );\n\n#endif\n\nvec3 viewPosition = normalize( vViewPosition );\n\n#ifdef USE_NORMALMAP\n\n normal = perturbNormal2Arb( -vViewPosition, normal );\n\n#elif defined( USE_BUMPMAP )\n\n normal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n\n#endif\n\nvec3 totalDiffuseLight = vec3( 0.0 );\nvec3 totalSpecularLight = vec3( 0.0 );\n\n#if MAX_POINT_LIGHTS > 0\n\n for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\n\n vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\n vec3 lVector = lPosition.xyz + vViewPosition.xyz;\n\n float attenuation = calcLightAttenuation( length( lVector ), pointLightDistance[ i ], pointLightDecay[ i ] );\n\n lVector = normalize( lVector );\n\n // diffuse\n\n float dotProduct = dot( normal, lVector );\n\n #ifdef WRAP_AROUND\n\n float pointDiffuseWeightFull = max( dotProduct, 0.0 );\n float pointDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\n\n vec3 pointDiffuseWeight = mix( vec3( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );\n\n #else\n\n float pointDiffuseWeight = max( dotProduct, 0.0 );\n\n #endif\n\n totalDiffuseLight += pointLightColor[ i ] * pointDiffuseWeight * attenuation;\n\n // specular\n\n vec3 pointHalfVector = normalize( lVector + viewPosition );\n float pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );\n float pointSpecularWeight = specularStrength * max( pow( pointDotNormalHalf, shininess ), 0.0 );\n\n float specularNormalization = ( shininess + 2.0 ) / 8.0;\n\n vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, pointHalfVector ), 0.0 ), 5.0 );\n totalSpecularLight += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * attenuation * specularNormalization;\n\n }\n\n#endif\n\n#if MAX_SPOT_LIGHTS > 0\n\n for ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\n\n vec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\n vec3 lVector = lPosition.xyz + vViewPosition.xyz;\n\n float attenuation = calcLightAttenuation( length( lVector ), spotLightDistance[ i ], spotLightDecay[ i ] );\n\n lVector = normalize( lVector );\n\n float spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) );\n\n if ( spotEffect > spotLightAngleCos[ i ] ) {\n\n spotEffect = max( pow( max( spotEffect, 0.0 ), spotLightExponent[ i ] ), 0.0 );\n\n // diffuse\n\n float dotProduct = dot( normal, lVector );\n\n #ifdef WRAP_AROUND\n\n float spotDiffuseWeightFull = max( dotProduct, 0.0 );\n float spotDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\n\n vec3 spotDiffuseWeight = mix( vec3( spotDiffuseWeightFull ), vec3( spotDiffuseWeightHalf ), wrapRGB );\n\n #else\n\n float spotDiffuseWeight = max( dotProduct, 0.0 );\n\n #endif\n\n totalDiffuseLight += spotLightColor[ i ] * spotDiffuseWeight * attenuation * spotEffect;\n\n // specular\n\n vec3 spotHalfVector = normalize( lVector + viewPosition );\n float spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );\n float spotSpecularWeight = specularStrength * max( pow( spotDotNormalHalf, shininess ), 0.0 );\n\n float specularNormalization = ( shininess + 2.0 ) / 8.0;\n\n vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, spotHalfVector ), 0.0 ), 5.0 );\n totalSpecularLight += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * attenuation * specularNormalization * spotEffect;\n\n }\n\n }\n\n#endif\n\n#if MAX_DIR_LIGHTS > 0\n\n for( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\n\n vec3 dirVector = transformDirection( directionalLightDirection[ i ], viewMatrix );\n\n // diffuse\n\n float dotProduct = dot( normal, dirVector );\n\n #ifdef WRAP_AROUND\n\n float dirDiffuseWeightFull = max( dotProduct, 0.0 );\n float dirDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\n\n vec3 dirDiffuseWeight = mix( vec3( dirDiffuseWeightFull ), vec3( dirDiffuseWeightHalf ), wrapRGB );\n\n #else\n\n float dirDiffuseWeight = max( dotProduct, 0.0 );\n\n #endif\n\n totalDiffuseLight += directionalLightColor[ i ] * dirDiffuseWeight;\n\n // specular\n\n vec3 dirHalfVector = normalize( dirVector + viewPosition );\n float dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );\n float dirSpecularWeight = specularStrength * max( pow( dirDotNormalHalf, shininess ), 0.0 );\n\n /*\n // fresnel term from skin shader\n const float F0 = 0.128;\n\n float base = 1.0 - dot( viewPosition, dirHalfVector );\n float exponential = pow( base, 5.0 );\n\n float fresnel = exponential + F0 * ( 1.0 - exponential );\n */\n\n /*\n // fresnel term from fresnel shader\n const float mFresnelBias = 0.08;\n const float mFresnelScale = 0.3;\n const float mFresnelPower = 5.0;\n\n float fresnel = mFresnelBias + mFresnelScale * pow( 1.0 + dot( normalize( -viewPosition ), normal ), mFresnelPower );\n */\n\n float specularNormalization = ( shininess + 2.0 ) / 8.0;\n\n // dirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization * fresnel;\n\n vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( dirVector, dirHalfVector ), 0.0 ), 5.0 );\n totalSpecularLight += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;\n\n\n }\n\n#endif\n\n#if MAX_HEMI_LIGHTS > 0\n\n for( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {\n\n vec3 lVector = transformDirection( hemisphereLightDirection[ i ], viewMatrix );\n\n // diffuse\n\n float dotProduct = dot( normal, lVector );\n float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;\n\n vec3 hemiColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );\n\n totalDiffuseLight += hemiColor;\n\n // specular (sky light)\n\n vec3 hemiHalfVectorSky = normalize( lVector + viewPosition );\n float hemiDotNormalHalfSky = 0.5 * dot( normal, hemiHalfVectorSky ) + 0.5;\n float hemiSpecularWeightSky = specularStrength * max( pow( max( hemiDotNormalHalfSky, 0.0 ), shininess ), 0.0 );\n\n // specular (ground light)\n\n vec3 lVectorGround = -lVector;\n\n vec3 hemiHalfVectorGround = normalize( lVectorGround + viewPosition );\n float hemiDotNormalHalfGround = 0.5 * dot( normal, hemiHalfVectorGround ) + 0.5;\n float hemiSpecularWeightGround = specularStrength * max( pow( max( hemiDotNormalHalfGround, 0.0 ), shininess ), 0.0 );\n\n float dotProductGround = dot( normal, lVectorGround );\n\n float specularNormalization = ( shininess + 2.0 ) / 8.0;\n\n vec3 schlickSky = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, hemiHalfVectorSky ), 0.0 ), 5.0 );\n vec3 schlickGround = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVectorGround, hemiHalfVectorGround ), 0.0 ), 5.0 );\n totalSpecularLight += hemiColor * specularNormalization * ( schlickSky * hemiSpecularWeightSky * max( dotProduct, 0.0 ) + schlickGround * hemiSpecularWeightGround * max( dotProductGround, 0.0 ) );\n\n }\n\n#endif\n\n#ifdef METAL\n\n outgoingLight += diffuseColor.rgb * ( totalDiffuseLight + ambientLightColor ) * specular + totalSpecularLight + emissive;\n\n#else\n\n outgoingLight += diffuseColor.rgb * ( totalDiffuseLight + ambientLightColor ) + totalSpecularLight + emissive;\n\n#endif\n"; // File:src/renderers/shaders/ShaderChunk/fog_pars_fragment.glsl @@ -15995,7 +16664,7 @@ THREE.ShaderChunk[ 'morphnormal_vertex'] = "#ifdef USE_MORPHNORMALS\n\n vec3 mor // File:src/renderers/shaders/ShaderChunk/envmap_pars_fragment.glsl -THREE.ShaderChunk[ 'envmap_pars_fragment'] = "#ifdef USE_ENVMAP\n\n uniform float reflectivity;\n uniform samplerCube envMap;\n uniform float flipEnvMap;\n uniform int combine;\n\n #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\n uniform bool useRefract;\n uniform float refractionRatio;\n\n #else\n\n varying vec3 vReflect;\n\n #endif\n\n#endif"; +THREE.ShaderChunk[ 'envmap_pars_fragment'] = "#ifdef USE_ENVMAP\n\n uniform float reflectivity;\n #ifdef ENVMAP_TYPE_CUBE\n uniform samplerCube envMap;\n #else\n uniform sampler2D envMap;\n #endif\n uniform float flipEnvMap;\n\n #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\n uniform float refractionRatio;\n\n #else\n\n varying vec3 vReflect;\n\n #endif\n\n#endif\n"; // File:src/renderers/shaders/ShaderChunk/logdepthbuf_fragment.glsl @@ -16003,7 +16672,7 @@ THREE.ShaderChunk[ 'logdepthbuf_fragment'] = "#if defined(USE_LOGDEPTHBUF) && de // File:src/renderers/shaders/ShaderChunk/normalmap_pars_fragment.glsl -THREE.ShaderChunk[ 'normalmap_pars_fragment'] = "#ifdef USE_NORMALMAP\n\n uniform sampler2D normalMap;\n uniform vec2 normalScale;\n\n // Per-Pixel Tangent Space Normal Mapping\n // http://hacksoflife.blogspot.ch/2009/11/per-pixel-tangent-space-normal-mapping.html\n\n vec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\n vec3 q0 = dFdx( eye_pos.xyz );\n vec3 q1 = dFdy( eye_pos.xyz );\n vec2 st0 = dFdx( vUv.st );\n vec2 st1 = dFdy( vUv.st );\n\n vec3 S = normalize( q0 * st1.t - q1 * st0.t );\n vec3 T = normalize( -q0 * st1.s + q1 * st0.s );\n vec3 N = normalize( surf_norm );\n\n vec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n mapN.xy = normalScale * mapN.xy;\n mat3 tsn = mat3( S, T, N );\n return normalize( tsn * mapN );\n\n }\n\n#endif\n"; +THREE.ShaderChunk[ 'normalmap_pars_fragment'] = "#ifdef USE_NORMALMAP\n\n uniform sampler2D normalMap;\n uniform vec2 normalScale;\n\n // Per-Pixel Tangent Space Normal Mapping\n // http://hacksoflife.blogspot.ch/2009/11/per-pixel-tangent-space-normal-mapping.html\n\n vec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\n vec3 q0 = dFdx( eye_pos.xyz );\n vec3 q1 = dFdy( eye_pos.xyz );\n vec2 st0 = dFdx( vUv.st );\n vec2 st1 = dFdy( vUv.st );\n\n vec3 S = normalize( q0 * st1.t - q1 * st0.t );\n vec3 T = normalize( -q0 * st1.s + q1 * st0.s );\n vec3 N = normalize( surf_norm );\n\n vec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n mapN.xy = normalScale * mapN.xy;\n mat3 tsn = mat3( S, T, N );\n return normalize( tsn * mapN );\n\n }\n\n#endif\n"; // File:src/renderers/shaders/ShaderChunk/lights_phong_pars_vertex.glsl @@ -16023,7 +16692,7 @@ THREE.ShaderChunk[ 'lights_phong_vertex'] = "#if MAX_SPOT_LIGHTS > 0 || defined( // File:src/renderers/shaders/ShaderChunk/map_fragment.glsl -THREE.ShaderChunk[ 'map_fragment'] = "#ifdef USE_MAP\n\n vec4 texelColor = texture2D( map, vUv );\n\n #ifdef GAMMA_INPUT\n\n texelColor.xyz *= texelColor.xyz;\n\n #endif\n\n gl_FragColor = gl_FragColor * texelColor;\n\n#endif"; +THREE.ShaderChunk[ 'map_fragment'] = "#ifdef USE_MAP\n\n vec4 texelColor = texture2D( map, vUv );\n\n texelColor.xyz = inputToLinear( texelColor.xyz );\n\n diffuseColor *= texelColor;\n\n#endif"; // File:src/renderers/shaders/ShaderChunk/lightmap_vertex.glsl @@ -16031,7 +16700,7 @@ THREE.ShaderChunk[ 'lightmap_vertex'] = "#ifdef USE_LIGHTMAP\n\n vUv2 = uv2;\n\n // File:src/renderers/shaders/ShaderChunk/map_particle_fragment.glsl -THREE.ShaderChunk[ 'map_particle_fragment'] = "#ifdef USE_MAP\n\n gl_FragColor = gl_FragColor * texture2D( map, vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y ) );\n\n#endif"; +THREE.ShaderChunk[ 'map_particle_fragment'] = "#ifdef USE_MAP\n\n diffuseColor *= texture2D( map, vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y ) * offsetRepeat.zw + offsetRepeat.xy );\n\n#endif\n"; // File:src/renderers/shaders/ShaderChunk/color_pars_fragment.glsl @@ -16039,7 +16708,7 @@ THREE.ShaderChunk[ 'color_pars_fragment'] = "#ifdef USE_COLOR\n\n varying vec3 v // File:src/renderers/shaders/ShaderChunk/color_vertex.glsl -THREE.ShaderChunk[ 'color_vertex'] = "#ifdef USE_COLOR\n\n #ifdef GAMMA_INPUT\n\n vColor = color * color;\n\n #else\n\n vColor = color;\n\n #endif\n\n#endif"; +THREE.ShaderChunk[ 'color_vertex'] = "#ifdef USE_COLOR\n\n vColor.xyz = inputToLinear( color.xyz );\n\n#endif"; // File:src/renderers/shaders/ShaderChunk/skinning_vertex.glsl @@ -16047,11 +16716,11 @@ THREE.ShaderChunk[ 'skinning_vertex'] = "#ifdef USE_SKINNING\n\n #ifdef USE_MORP // File:src/renderers/shaders/ShaderChunk/envmap_pars_vertex.glsl -THREE.ShaderChunk[ 'envmap_pars_vertex'] = "#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP ) && ! defined( PHONG )\n\n varying vec3 vReflect;\n\n uniform float refractionRatio;\n uniform bool useRefract;\n\n#endif\n"; +THREE.ShaderChunk[ 'envmap_pars_vertex'] = "#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP ) && ! defined( PHONG )\n\n varying vec3 vReflect;\n\n uniform float refractionRatio;\n\n#endif\n"; // File:src/renderers/shaders/ShaderChunk/linear_to_gamma_fragment.glsl -THREE.ShaderChunk[ 'linear_to_gamma_fragment'] = "#ifdef GAMMA_OUTPUT\n\n gl_FragColor.xyz = sqrt( gl_FragColor.xyz );\n\n#endif"; +THREE.ShaderChunk[ 'linear_to_gamma_fragment'] = "\n outgoingLight = linearToOutput( outgoingLight );\n"; // File:src/renderers/shaders/ShaderChunk/color_pars_vertex.glsl @@ -16059,7 +16728,7 @@ THREE.ShaderChunk[ 'color_pars_vertex'] = "#ifdef USE_COLOR\n\n varying vec3 vCo // File:src/renderers/shaders/ShaderChunk/lights_lambert_pars_vertex.glsl -THREE.ShaderChunk[ 'lights_lambert_pars_vertex'] = "uniform vec3 ambient;\nuniform vec3 diffuse;\nuniform vec3 emissive;\n\nuniform vec3 ambientLightColor;\n\n#if MAX_DIR_LIGHTS > 0\n\n uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\n uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n\n#endif\n\n#if MAX_HEMI_LIGHTS > 0\n\n uniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];\n uniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];\n uniform vec3 hemisphereLightDirection[ MAX_HEMI_LIGHTS ];\n\n#endif\n\n#if MAX_POINT_LIGHTS > 0\n\n uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\n uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\n uniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n\n#endif\n\n#if MAX_SPOT_LIGHTS > 0\n\n uniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\n uniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\n uniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\n uniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\n uniform float spotLightAngleCos[ MAX_SPOT_LIGHTS ];\n uniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n\n#endif\n\n#ifdef WRAP_AROUND\n\n uniform vec3 wrapRGB;\n\n#endif\n"; +THREE.ShaderChunk[ 'lights_lambert_pars_vertex'] = "uniform vec3 ambientLightColor;\n\n#if MAX_DIR_LIGHTS > 0\n\n uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\n uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n\n#endif\n\n#if MAX_HEMI_LIGHTS > 0\n\n uniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];\n uniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];\n uniform vec3 hemisphereLightDirection[ MAX_HEMI_LIGHTS ];\n\n#endif\n\n#if MAX_POINT_LIGHTS > 0\n\n uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\n uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\n uniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n uniform float pointLightDecay[ MAX_POINT_LIGHTS ];\n\n#endif\n\n#if MAX_SPOT_LIGHTS > 0\n\n uniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\n uniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\n uniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\n uniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\n uniform float spotLightAngleCos[ MAX_SPOT_LIGHTS ];\n uniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n uniform float spotLightDecay[ MAX_SPOT_LIGHTS ];\n\n#endif\n\n#ifdef WRAP_AROUND\n\n uniform vec3 wrapRGB;\n\n#endif\n"; // File:src/renderers/shaders/ShaderChunk/map_pars_vertex.glsl @@ -16067,7 +16736,7 @@ THREE.ShaderChunk[ 'map_pars_vertex'] = "#if defined( USE_MAP ) || defined( USE_ // File:src/renderers/shaders/ShaderChunk/envmap_fragment.glsl -THREE.ShaderChunk[ 'envmap_fragment'] = "#ifdef USE_ENVMAP\n\n vec3 reflectVec;\n\n #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\n vec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n\n // http://en.wikibooks.org/wiki/GLSL_Programming/Applying_Matrix_Transformations\n // Transforming Normal Vectors with the Inverse Transformation\n\n vec3 worldNormal = normalize( vec3( vec4( normal, 0.0 ) * viewMatrix ) );\n\n if ( useRefract ) {\n\n reflectVec = refract( cameraToVertex, worldNormal, refractionRatio );\n\n } else { \n\n reflectVec = reflect( cameraToVertex, worldNormal );\n\n }\n\n #else\n\n reflectVec = vReflect;\n\n #endif\n\n #ifdef DOUBLE_SIDED\n\n float flipNormal = ( -1.0 + 2.0 * float( gl_FrontFacing ) );\n vec4 cubeColor = textureCube( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\n #else\n\n vec4 cubeColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\n #endif\n\n #ifdef GAMMA_INPUT\n\n cubeColor.xyz *= cubeColor.xyz;\n\n #endif\n\n if ( combine == 1 ) {\n\n gl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularStrength * reflectivity );\n\n } else if ( combine == 2 ) {\n\n gl_FragColor.xyz += cubeColor.xyz * specularStrength * reflectivity;\n\n } else {\n\n gl_FragColor.xyz = mix( gl_FragColor.xyz, gl_FragColor.xyz * cubeColor.xyz, specularStrength * reflectivity );\n\n }\n\n#endif"; +THREE.ShaderChunk[ 'envmap_fragment'] = "#ifdef USE_ENVMAP\n\n #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\n vec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n\n // Transforming Normal Vectors with the Inverse Transformation\n vec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\n #ifdef ENVMAP_MODE_REFLECTION\n\n vec3 reflectVec = reflect( cameraToVertex, worldNormal );\n\n #else\n\n vec3 reflectVec = refract( cameraToVertex, worldNormal, refractionRatio );\n\n #endif\n\n #else\n\n vec3 reflectVec = vReflect;\n\n #endif\n\n #ifdef DOUBLE_SIDED\n float flipNormal = ( -1.0 + 2.0 * float( gl_FrontFacing ) );\n #else\n float flipNormal = 1.0;\n #endif\n\n #ifdef ENVMAP_TYPE_CUBE\n vec4 envColor = textureCube( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\n #elif defined( ENVMAP_TYPE_EQUIREC )\n vec2 sampleUV;\n sampleUV.y = saturate( flipNormal * reflectVec.y * 0.5 + 0.5 );\n sampleUV.x = atan( flipNormal * reflectVec.z, flipNormal * reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n vec4 envColor = texture2D( envMap, sampleUV );\n\n #elif defined( ENVMAP_TYPE_SPHERE )\n vec3 reflectView = flipNormal * normalize((viewMatrix * vec4( reflectVec, 0.0 )).xyz + vec3(0.0,0.0,1.0));\n vec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\n #endif\n\n envColor.xyz = inputToLinear( envColor.xyz );\n\n #ifdef ENVMAP_BLENDING_MULTIPLY\n\n outgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\n #elif defined( ENVMAP_BLENDING_MIX )\n\n outgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\n #elif defined( ENVMAP_BLENDING_ADD )\n\n outgoingLight += envColor.xyz * specularStrength * reflectivity;\n\n #endif\n\n#endif\n"; // File:src/renderers/shaders/ShaderChunk/specularmap_pars_fragment.glsl @@ -16075,7 +16744,7 @@ THREE.ShaderChunk[ 'specularmap_pars_fragment'] = "#ifdef USE_SPECULARMAP\n\n un // File:src/renderers/shaders/ShaderChunk/logdepthbuf_vertex.glsl -THREE.ShaderChunk[ 'logdepthbuf_vertex'] = "#ifdef USE_LOGDEPTHBUF\n\n gl_Position.z = log2(max(1e-6, gl_Position.w + 1.0)) * logDepthBufFC;\n\n #ifdef USE_LOGDEPTHBUF_EXT\n\n vFragDepth = 1.0 + gl_Position.w;\n\n#else\n\n gl_Position.z = (gl_Position.z - 1.0) * gl_Position.w;\n\n #endif\n\n#endif"; +THREE.ShaderChunk[ 'logdepthbuf_vertex'] = "#ifdef USE_LOGDEPTHBUF\n\n gl_Position.z = log2(max( EPSILON, gl_Position.w + 1.0 )) * logDepthBufFC;\n\n #ifdef USE_LOGDEPTHBUF_EXT\n\n vFragDepth = 1.0 + gl_Position.w;\n\n#else\n\n gl_Position.z = (gl_Position.z - 1.0) * gl_Position.w;\n\n #endif\n\n#endif"; // File:src/renderers/shaders/ShaderChunk/morphtarget_pars_vertex.glsl @@ -16087,19 +16756,19 @@ THREE.ShaderChunk[ 'specularmap_fragment'] = "float specularStrength;\n\n#ifdef // File:src/renderers/shaders/ShaderChunk/fog_fragment.glsl -THREE.ShaderChunk[ 'fog_fragment'] = "#ifdef USE_FOG\n\n #ifdef USE_LOGDEPTHBUF_EXT\n\n float depth = gl_FragDepthEXT / gl_FragCoord.w;\n\n #else\n\n float depth = gl_FragCoord.z / gl_FragCoord.w;\n\n #endif\n\n #ifdef FOG_EXP2\n\n const float LOG2 = 1.442695;\n float fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );\n fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );\n\n #else\n\n float fogFactor = smoothstep( fogNear, fogFar, depth );\n\n #endif\n \n gl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );\n\n#endif"; +THREE.ShaderChunk[ 'fog_fragment'] = "#ifdef USE_FOG\n\n #ifdef USE_LOGDEPTHBUF_EXT\n\n float depth = gl_FragDepthEXT / gl_FragCoord.w;\n\n #else\n\n float depth = gl_FragCoord.z / gl_FragCoord.w;\n\n #endif\n\n #ifdef FOG_EXP2\n\n float fogFactor = exp2( - square( fogDensity ) * square( depth ) * LOG2 );\n fogFactor = whiteCompliment( fogFactor );\n\n #else\n\n float fogFactor = smoothstep( fogNear, fogFar, depth );\n\n #endif\n \n outgoingLight = mix( outgoingLight, fogColor, fogFactor );\n\n#endif"; // File:src/renderers/shaders/ShaderChunk/bumpmap_pars_fragment.glsl -THREE.ShaderChunk[ 'bumpmap_pars_fragment'] = "#ifdef USE_BUMPMAP\n\n uniform sampler2D bumpMap;\n uniform float bumpScale;\n\n // Derivative maps - bump mapping unparametrized surfaces by Morten Mikkelsen\n // http://mmikkelsen3d.blogspot.sk/2011/07/derivative-maps.html\n\n // Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2)\n\n vec2 dHdxy_fwd() {\n\n vec2 dSTdx = dFdx( vUv );\n vec2 dSTdy = dFdy( vUv );\n\n float Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n float dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n float dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\n return vec2( dBx, dBy );\n\n }\n\n vec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\n vec3 vSigmaX = dFdx( surf_pos );\n vec3 vSigmaY = dFdy( surf_pos );\n vec3 vN = surf_norm; // normalized\n\n vec3 R1 = cross( vSigmaY, vN );\n vec3 R2 = cross( vN, vSigmaX );\n\n float fDet = dot( vSigmaX, R1 );\n\n vec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n return normalize( abs( fDet ) * surf_norm - vGrad );\n\n }\n\n#endif"; +THREE.ShaderChunk[ 'bumpmap_pars_fragment'] = "#ifdef USE_BUMPMAP\n\n uniform sampler2D bumpMap;\n uniform float bumpScale;\n\n // Derivative maps - bump mapping unparametrized surfaces by Morten Mikkelsen\n // http://mmikkelsen3d.blogspot.sk/2011/07/derivative-maps.html\n\n // Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2)\n\n vec2 dHdxy_fwd() {\n\n vec2 dSTdx = dFdx( vUv );\n vec2 dSTdy = dFdy( vUv );\n\n float Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n float dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n float dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\n return vec2( dBx, dBy );\n\n }\n\n vec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\n vec3 vSigmaX = dFdx( surf_pos );\n vec3 vSigmaY = dFdy( surf_pos );\n vec3 vN = surf_norm; // normalized\n\n vec3 R1 = cross( vSigmaY, vN );\n vec3 R2 = cross( vN, vSigmaX );\n\n float fDet = dot( vSigmaX, R1 );\n\n vec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n return normalize( abs( fDet ) * surf_norm - vGrad );\n\n }\n\n#endif\n"; // File:src/renderers/shaders/ShaderChunk/defaultnormal_vertex.glsl -THREE.ShaderChunk[ 'defaultnormal_vertex'] = "vec3 objectNormal;\n\n#ifdef USE_SKINNING\n\n objectNormal = skinnedNormal.xyz;\n\n#endif\n\n#if !defined( USE_SKINNING ) && defined( USE_MORPHNORMALS )\n\n objectNormal = morphedNormal;\n\n#endif\n\n#if !defined( USE_SKINNING ) && ! defined( USE_MORPHNORMALS )\n\n objectNormal = normal;\n\n#endif\n\n#ifdef FLIP_SIDED\n\n objectNormal = -objectNormal;\n\n#endif\n\nvec3 transformedNormal = normalMatrix * objectNormal;"; +THREE.ShaderChunk[ 'defaultnormal_vertex'] = "#ifdef USE_SKINNING\n\n vec3 objectNormal = skinnedNormal.xyz;\n\n#elif defined( USE_MORPHNORMALS )\n\n vec3 objectNormal = morphedNormal;\n\n#else\n\n vec3 objectNormal = normal;\n\n#endif\n\n#ifdef FLIP_SIDED\n\n objectNormal = -objectNormal;\n\n#endif\n\nvec3 transformedNormal = normalMatrix * objectNormal;\n"; // File:src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl -THREE.ShaderChunk[ 'lights_phong_pars_fragment'] = "uniform vec3 ambientLightColor;\n\n#if MAX_DIR_LIGHTS > 0\n\n uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\n uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n\n#endif\n\n#if MAX_HEMI_LIGHTS > 0\n\n uniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];\n uniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];\n uniform vec3 hemisphereLightDirection[ MAX_HEMI_LIGHTS ];\n\n#endif\n\n#if MAX_POINT_LIGHTS > 0\n\n uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\n\n uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\n uniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n\n#endif\n\n#if MAX_SPOT_LIGHTS > 0\n\n uniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\n uniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\n uniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\n uniform float spotLightAngleCos[ MAX_SPOT_LIGHTS ];\n uniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n\n uniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\n\n#endif\n\n#if MAX_SPOT_LIGHTS > 0 || defined( USE_BUMPMAP ) || defined( USE_ENVMAP )\n\n varying vec3 vWorldPosition;\n\n#endif\n\n#ifdef WRAP_AROUND\n\n uniform vec3 wrapRGB;\n\n#endif\n\nvarying vec3 vViewPosition;\nvarying vec3 vNormal;"; +THREE.ShaderChunk[ 'lights_phong_pars_fragment'] = "uniform vec3 ambientLightColor;\n\n#if MAX_DIR_LIGHTS > 0\n\n uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\n uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n\n#endif\n\n#if MAX_HEMI_LIGHTS > 0\n\n uniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];\n uniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];\n uniform vec3 hemisphereLightDirection[ MAX_HEMI_LIGHTS ];\n\n#endif\n\n#if MAX_POINT_LIGHTS > 0\n\n uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\n\n uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\n uniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n uniform float pointLightDecay[ MAX_POINT_LIGHTS ];\n\n#endif\n\n#if MAX_SPOT_LIGHTS > 0\n\n uniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\n uniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\n uniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\n uniform float spotLightAngleCos[ MAX_SPOT_LIGHTS ];\n uniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n uniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\n uniform float spotLightDecay[ MAX_SPOT_LIGHTS ];\n\n#endif\n\n#if MAX_SPOT_LIGHTS > 0 || defined( USE_BUMPMAP ) || defined( USE_ENVMAP )\n\n varying vec3 vWorldPosition;\n\n#endif\n\n#ifdef WRAP_AROUND\n\n uniform vec3 wrapRGB;\n\n#endif\n\nvarying vec3 vViewPosition;\n\n#ifndef FLAT_SHADED\n\n varying vec3 vNormal;\n\n#endif\n"; // File:src/renderers/shaders/ShaderChunk/skinbase_vertex.glsl @@ -16111,7 +16780,7 @@ THREE.ShaderChunk[ 'map_vertex'] = "#if defined( USE_MAP ) || defined( USE_BUMPM // File:src/renderers/shaders/ShaderChunk/lightmap_fragment.glsl -THREE.ShaderChunk[ 'lightmap_fragment'] = "#ifdef USE_LIGHTMAP\n\n gl_FragColor = gl_FragColor * texture2D( lightMap, vUv2 );\n\n#endif"; +THREE.ShaderChunk[ 'lightmap_fragment'] = "#ifdef USE_LIGHTMAP\n\n outgoingLight *= diffuseColor.xyz * texture2D( lightMap, vUv2 ).xyz;\n\n#endif"; // File:src/renderers/shaders/ShaderChunk/shadowmap_pars_vertex.glsl @@ -16119,7 +16788,7 @@ THREE.ShaderChunk[ 'shadowmap_pars_vertex'] = "#ifdef USE_SHADOWMAP\n\n varying // File:src/renderers/shaders/ShaderChunk/color_fragment.glsl -THREE.ShaderChunk[ 'color_fragment'] = "#ifdef USE_COLOR\n\n gl_FragColor = gl_FragColor * vec4( vColor, 1.0 );\n\n#endif"; +THREE.ShaderChunk[ 'color_fragment'] = "#ifdef USE_COLOR\n\n diffuseColor.rgb *= vColor;\n\n#endif"; // File:src/renderers/shaders/ShaderChunk/morphtarget_vertex.glsl @@ -16127,15 +16796,15 @@ THREE.ShaderChunk[ 'morphtarget_vertex'] = "#ifdef USE_MORPHTARGETS\n\n vec3 mor // File:src/renderers/shaders/ShaderChunk/envmap_vertex.glsl -THREE.ShaderChunk[ 'envmap_vertex'] = "#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP ) && ! defined( PHONG )\n\n vec3 worldNormal = mat3( modelMatrix[ 0 ].xyz, modelMatrix[ 1 ].xyz, modelMatrix[ 2 ].xyz ) * objectNormal;\n worldNormal = normalize( worldNormal );\n\n vec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\n if ( useRefract ) {\n\n vReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\n } else {\n\n vReflect = reflect( cameraToVertex, worldNormal );\n\n }\n\n#endif"; +THREE.ShaderChunk[ 'envmap_vertex'] = "#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP ) && ! defined( PHONG )\n\n vec3 worldNormal = transformDirection( objectNormal, modelMatrix );\n\n vec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\n #ifdef ENVMAP_MODE_REFLECTION\n\n vReflect = reflect( cameraToVertex, worldNormal );\n\n #else\n\n vReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\n #endif\n\n#endif\n"; // File:src/renderers/shaders/ShaderChunk/shadowmap_fragment.glsl -THREE.ShaderChunk[ 'shadowmap_fragment'] = "#ifdef USE_SHADOWMAP\n\n #ifdef SHADOWMAP_DEBUG\n\n vec3 frustumColors[3];\n frustumColors[0] = vec3( 1.0, 0.5, 0.0 );\n frustumColors[1] = vec3( 0.0, 1.0, 0.8 );\n frustumColors[2] = vec3( 0.0, 0.5, 1.0 );\n\n #endif\n\n #ifdef SHADOWMAP_CASCADE\n\n int inFrustumCount = 0;\n\n #endif\n\n float fDepth;\n vec3 shadowColor = vec3( 1.0 );\n\n for( int i = 0; i < MAX_SHADOWS; i ++ ) {\n\n vec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;\n\n // if ( something && something ) breaks ATI OpenGL shader compiler\n // if ( all( something, something ) ) using this instead\n\n bvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n bool inFrustum = all( inFrustumVec );\n\n // don't shadow pixels outside of light frustum\n // use just first frustum (for cascades)\n // don't shadow pixels behind far plane of light frustum\n\n #ifdef SHADOWMAP_CASCADE\n\n inFrustumCount += int( inFrustum );\n bvec3 frustumTestVec = bvec3( inFrustum, inFrustumCount == 1, shadowCoord.z <= 1.0 );\n\n #else\n\n bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\n #endif\n\n bool frustumTest = all( frustumTestVec );\n\n if ( frustumTest ) {\n\n shadowCoord.z += shadowBias[ i ];\n\n #if defined( SHADOWMAP_TYPE_PCF )\n\n // Percentage-close filtering\n // (9 pixel kernel)\n // http://fabiensanglard.net/shadowmappingPCF/\n\n float shadow = 0.0;\n\n /*\n // nested loops breaks shader compiler / validator on some ATI cards when using OpenGL\n // must enroll loop manually\n\n for ( float y = -1.25; y <= 1.25; y += 1.25 )\n for ( float x = -1.25; x <= 1.25; x += 1.25 ) {\n\n vec4 rgbaDepth = texture2D( shadowMap[ i ], vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy );\n\n // doesn't seem to produce any noticeable visual difference compared to simple texture2D lookup\n //vec4 rgbaDepth = texture2DProj( shadowMap[ i ], vec4( vShadowCoord[ i ].w * ( vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy ), 0.05, vShadowCoord[ i ].w ) );\n\n float fDepth = unpackDepth( rgbaDepth );\n\n if ( fDepth < shadowCoord.z )\n shadow += 1.0;\n\n }\n\n shadow /= 9.0;\n\n */\n\n const float shadowDelta = 1.0 / 9.0;\n\n float xPixelOffset = 1.0 / shadowMapSize[ i ].x;\n float yPixelOffset = 1.0 / shadowMapSize[ i ].y;\n\n float dx0 = -1.25 * xPixelOffset;\n float dy0 = -1.25 * yPixelOffset;\n float dx1 = 1.25 * xPixelOffset;\n float dy1 = 1.25 * yPixelOffset;\n\n fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );\n if ( fDepth < shadowCoord.z ) shadow += shadowDelta;\n\n fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );\n if ( fDepth < shadowCoord.z ) shadow += shadowDelta;\n\n fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );\n if ( fDepth < shadowCoord.z ) shadow += shadowDelta;\n\n fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );\n if ( fDepth < shadowCoord.z ) shadow += shadowDelta;\n\n fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );\n if ( fDepth < shadowCoord.z ) shadow += shadowDelta;\n\n fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );\n if ( fDepth < shadowCoord.z ) shadow += shadowDelta;\n\n fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );\n if ( fDepth < shadowCoord.z ) shadow += shadowDelta;\n\n fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );\n if ( fDepth < shadowCoord.z ) shadow += shadowDelta;\n\n fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );\n if ( fDepth < shadowCoord.z ) shadow += shadowDelta;\n\n shadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );\n\n #elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\n // Percentage-close filtering\n // (9 pixel kernel)\n // http://fabiensanglard.net/shadowmappingPCF/\n\n float shadow = 0.0;\n\n float xPixelOffset = 1.0 / shadowMapSize[ i ].x;\n float yPixelOffset = 1.0 / shadowMapSize[ i ].y;\n\n float dx0 = -1.0 * xPixelOffset;\n float dy0 = -1.0 * yPixelOffset;\n float dx1 = 1.0 * xPixelOffset;\n float dy1 = 1.0 * yPixelOffset;\n\n mat3 shadowKernel;\n mat3 depthKernel;\n\n depthKernel[0][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );\n depthKernel[0][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );\n depthKernel[0][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );\n depthKernel[1][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );\n depthKernel[1][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );\n depthKernel[1][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );\n depthKernel[2][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );\n depthKernel[2][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );\n depthKernel[2][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );\n\n vec3 shadowZ = vec3( shadowCoord.z );\n shadowKernel[0] = vec3(lessThan(depthKernel[0], shadowZ ));\n shadowKernel[0] *= vec3(0.25);\n\n shadowKernel[1] = vec3(lessThan(depthKernel[1], shadowZ ));\n shadowKernel[1] *= vec3(0.25);\n\n shadowKernel[2] = vec3(lessThan(depthKernel[2], shadowZ ));\n shadowKernel[2] *= vec3(0.25);\n\n vec2 fractionalCoord = 1.0 - fract( shadowCoord.xy * shadowMapSize[i].xy );\n\n shadowKernel[0] = mix( shadowKernel[1], shadowKernel[0], fractionalCoord.x );\n shadowKernel[1] = mix( shadowKernel[2], shadowKernel[1], fractionalCoord.x );\n\n vec4 shadowValues;\n shadowValues.x = mix( shadowKernel[0][1], shadowKernel[0][0], fractionalCoord.y );\n shadowValues.y = mix( shadowKernel[0][2], shadowKernel[0][1], fractionalCoord.y );\n shadowValues.z = mix( shadowKernel[1][1], shadowKernel[1][0], fractionalCoord.y );\n shadowValues.w = mix( shadowKernel[1][2], shadowKernel[1][1], fractionalCoord.y );\n\n shadow = dot( shadowValues, vec4( 1.0 ) );\n\n shadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );\n\n #else\n\n vec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );\n float fDepth = unpackDepth( rgbaDepth );\n\n if ( fDepth < shadowCoord.z )\n\n // spot with multiple shadows is darker\n\n shadowColor = shadowColor * vec3( 1.0 - shadowDarkness[ i ] );\n\n // spot with multiple shadows has the same color as single shadow spot\n\n // shadowColor = min( shadowColor, vec3( shadowDarkness[ i ] ) );\n\n #endif\n\n }\n\n\n #ifdef SHADOWMAP_DEBUG\n\n #ifdef SHADOWMAP_CASCADE\n\n if ( inFrustum && inFrustumCount == 1 ) gl_FragColor.xyz *= frustumColors[ i ];\n\n #else\n\n if ( inFrustum ) gl_FragColor.xyz *= frustumColors[ i ];\n\n #endif\n\n #endif\n\n }\n\n #ifdef GAMMA_OUTPUT\n\n shadowColor *= shadowColor;\n\n #endif\n\n gl_FragColor.xyz = gl_FragColor.xyz * shadowColor;\n\n#endif\n"; +THREE.ShaderChunk[ 'shadowmap_fragment'] = "#ifdef USE_SHADOWMAP\n\n #ifdef SHADOWMAP_DEBUG\n\n vec3 frustumColors[3];\n frustumColors[0] = vec3( 1.0, 0.5, 0.0 );\n frustumColors[1] = vec3( 0.0, 1.0, 0.8 );\n frustumColors[2] = vec3( 0.0, 0.5, 1.0 );\n\n #endif\n\n #ifdef SHADOWMAP_CASCADE\n\n int inFrustumCount = 0;\n\n #endif\n\n float fDepth;\n vec3 shadowColor = vec3( 1.0 );\n\n for( int i = 0; i < MAX_SHADOWS; i ++ ) {\n\n vec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;\n\n // if ( something && something ) breaks ATI OpenGL shader compiler\n // if ( all( something, something ) ) using this instead\n\n bvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n bool inFrustum = all( inFrustumVec );\n\n // don't shadow pixels outside of light frustum\n // use just first frustum (for cascades)\n // don't shadow pixels behind far plane of light frustum\n\n #ifdef SHADOWMAP_CASCADE\n\n inFrustumCount += int( inFrustum );\n bvec3 frustumTestVec = bvec3( inFrustum, inFrustumCount == 1, shadowCoord.z <= 1.0 );\n\n #else\n\n bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\n #endif\n\n bool frustumTest = all( frustumTestVec );\n\n if ( frustumTest ) {\n\n shadowCoord.z += shadowBias[ i ];\n\n #if defined( SHADOWMAP_TYPE_PCF )\n\n // Percentage-close filtering\n // (9 pixel kernel)\n // http://fabiensanglard.net/shadowmappingPCF/\n\n float shadow = 0.0;\n\n /*\n // nested loops breaks shader compiler / validator on some ATI cards when using OpenGL\n // must enroll loop manually\n\n for ( float y = -1.25; y <= 1.25; y += 1.25 )\n for ( float x = -1.25; x <= 1.25; x += 1.25 ) {\n\n vec4 rgbaDepth = texture2D( shadowMap[ i ], vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy );\n\n // doesn't seem to produce any noticeable visual difference compared to simple texture2D lookup\n //vec4 rgbaDepth = texture2DProj( shadowMap[ i ], vec4( vShadowCoord[ i ].w * ( vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy ), 0.05, vShadowCoord[ i ].w ) );\n\n float fDepth = unpackDepth( rgbaDepth );\n\n if ( fDepth < shadowCoord.z )\n shadow += 1.0;\n\n }\n\n shadow /= 9.0;\n\n */\n\n const float shadowDelta = 1.0 / 9.0;\n\n float xPixelOffset = 1.0 / shadowMapSize[ i ].x;\n float yPixelOffset = 1.0 / shadowMapSize[ i ].y;\n\n float dx0 = -1.25 * xPixelOffset;\n float dy0 = -1.25 * yPixelOffset;\n float dx1 = 1.25 * xPixelOffset;\n float dy1 = 1.25 * yPixelOffset;\n\n fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );\n if ( fDepth < shadowCoord.z ) shadow += shadowDelta;\n\n fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );\n if ( fDepth < shadowCoord.z ) shadow += shadowDelta;\n\n fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );\n if ( fDepth < shadowCoord.z ) shadow += shadowDelta;\n\n fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );\n if ( fDepth < shadowCoord.z ) shadow += shadowDelta;\n\n fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );\n if ( fDepth < shadowCoord.z ) shadow += shadowDelta;\n\n fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );\n if ( fDepth < shadowCoord.z ) shadow += shadowDelta;\n\n fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );\n if ( fDepth < shadowCoord.z ) shadow += shadowDelta;\n\n fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );\n if ( fDepth < shadowCoord.z ) shadow += shadowDelta;\n\n fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );\n if ( fDepth < shadowCoord.z ) shadow += shadowDelta;\n\n shadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );\n\n #elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\n // Percentage-close filtering\n // (9 pixel kernel)\n // http://fabiensanglard.net/shadowmappingPCF/\n\n float shadow = 0.0;\n\n float xPixelOffset = 1.0 / shadowMapSize[ i ].x;\n float yPixelOffset = 1.0 / shadowMapSize[ i ].y;\n\n float dx0 = -1.0 * xPixelOffset;\n float dy0 = -1.0 * yPixelOffset;\n float dx1 = 1.0 * xPixelOffset;\n float dy1 = 1.0 * yPixelOffset;\n\n mat3 shadowKernel;\n mat3 depthKernel;\n\n depthKernel[0][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );\n depthKernel[0][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );\n depthKernel[0][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );\n depthKernel[1][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );\n depthKernel[1][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );\n depthKernel[1][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );\n depthKernel[2][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );\n depthKernel[2][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );\n depthKernel[2][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );\n\n vec3 shadowZ = vec3( shadowCoord.z );\n shadowKernel[0] = vec3(lessThan(depthKernel[0], shadowZ ));\n shadowKernel[0] *= vec3(0.25);\n\n shadowKernel[1] = vec3(lessThan(depthKernel[1], shadowZ ));\n shadowKernel[1] *= vec3(0.25);\n\n shadowKernel[2] = vec3(lessThan(depthKernel[2], shadowZ ));\n shadowKernel[2] *= vec3(0.25);\n\n vec2 fractionalCoord = 1.0 - fract( shadowCoord.xy * shadowMapSize[i].xy );\n\n shadowKernel[0] = mix( shadowKernel[1], shadowKernel[0], fractionalCoord.x );\n shadowKernel[1] = mix( shadowKernel[2], shadowKernel[1], fractionalCoord.x );\n\n vec4 shadowValues;\n shadowValues.x = mix( shadowKernel[0][1], shadowKernel[0][0], fractionalCoord.y );\n shadowValues.y = mix( shadowKernel[0][2], shadowKernel[0][1], fractionalCoord.y );\n shadowValues.z = mix( shadowKernel[1][1], shadowKernel[1][0], fractionalCoord.y );\n shadowValues.w = mix( shadowKernel[1][2], shadowKernel[1][1], fractionalCoord.y );\n\n shadow = dot( shadowValues, vec4( 1.0 ) );\n\n shadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );\n\n #else\n\n vec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );\n float fDepth = unpackDepth( rgbaDepth );\n\n if ( fDepth < shadowCoord.z )\n\n // spot with multiple shadows is darker\n\n shadowColor = shadowColor * vec3( 1.0 - shadowDarkness[ i ] );\n\n // spot with multiple shadows has the same color as single shadow spot\n\n // shadowColor = min( shadowColor, vec3( shadowDarkness[ i ] ) );\n\n #endif\n\n }\n\n\n #ifdef SHADOWMAP_DEBUG\n\n #ifdef SHADOWMAP_CASCADE\n\n if ( inFrustum && inFrustumCount == 1 ) outgoingLight *= frustumColors[ i ];\n\n #else\n\n if ( inFrustum ) outgoingLight *= frustumColors[ i ];\n\n #endif\n\n #endif\n\n }\n\n // NOTE: I am unsure if this is correct in linear space. -bhouston, Dec 29, 2014\n shadowColor = inputToLinear( shadowColor );\n\n outgoingLight = outgoingLight * shadowColor;\n\n#endif\n"; // File:src/renderers/shaders/ShaderChunk/worldpos_vertex.glsl -THREE.ShaderChunk[ 'worldpos_vertex'] = "#if defined( USE_ENVMAP ) || defined( PHONG ) || defined( LAMBERT ) || defined ( USE_SHADOWMAP )\n\n #ifdef USE_SKINNING\n\n vec4 worldPosition = modelMatrix * skinned;\n\n #endif\n\n #if defined( USE_MORPHTARGETS ) && ! defined( USE_SKINNING )\n\n vec4 worldPosition = modelMatrix * vec4( morphed, 1.0 );\n\n #endif\n\n #if ! defined( USE_MORPHTARGETS ) && ! defined( USE_SKINNING )\n\n vec4 worldPosition = modelMatrix * vec4( position, 1.0 );\n\n #endif\n\n#endif"; +THREE.ShaderChunk[ 'worldpos_vertex'] = "#if defined( USE_ENVMAP ) || defined( PHONG ) || defined( LAMBERT ) || defined ( USE_SHADOWMAP )\n\n #ifdef USE_SKINNING\n\n vec4 worldPosition = modelMatrix * skinned;\n\n #elif defined( USE_MORPHTARGETS )\n\n vec4 worldPosition = modelMatrix * vec4( morphed, 1.0 );\n\n #else\n\n vec4 worldPosition = modelMatrix * vec4( position, 1.0 );\n\n #endif\n\n#endif\n"; // File:src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl @@ -16151,7 +16820,7 @@ THREE.ShaderChunk[ 'logdepthbuf_pars_fragment'] = "#ifdef USE_LOGDEPTHBUF\n\n un // File:src/renderers/shaders/ShaderChunk/alphamap_fragment.glsl -THREE.ShaderChunk[ 'alphamap_fragment'] = "#ifdef USE_ALPHAMAP\n\n gl_FragColor.a *= texture2D( alphaMap, vUv ).g;\n\n#endif\n"; +THREE.ShaderChunk[ 'alphamap_fragment'] = "#ifdef USE_ALPHAMAP\n\n diffuseColor.a *= texture2D( alphaMap, vUv ).g;\n\n#endif\n"; // File:src/renderers/shaders/ShaderChunk/alphamap_pars_fragment.glsl @@ -16248,10 +16917,8 @@ THREE.UniformsLib = { "envMap" : { type: "t", value: null }, "flipEnvMap" : { type: "f", value: - 1 }, - "useRefract" : { type: "i", value: 0 }, "reflectivity" : { type: "f", value: 1.0 }, "refractionRatio" : { type: "f", value: 0.98 }, - "combine" : { type: "i", value: 0 }, "morphTargetInfluences" : { type: "f", value: 0 } @@ -16293,13 +16960,15 @@ THREE.UniformsLib = { "pointLightColor" : { type: "fv", value: [] }, "pointLightPosition" : { type: "fv", value: [] }, "pointLightDistance" : { type: "fv1", value: [] }, + "pointLightDecay" : { type: "fv1", value: [] }, "spotLightColor" : { type: "fv", value: [] }, "spotLightPosition" : { type: "fv", value: [] }, "spotLightDirection" : { type: "fv", value: [] }, "spotLightDistance" : { type: "fv1", value: [] }, "spotLightAngleCos" : { type: "fv1", value: [] }, - "spotLightExponent" : { type: "fv1", value: [] } + "spotLightExponent" : { type: "fv1", value: [] }, + "spotLightDecay" : { type: "fv1", value: [] } }, @@ -16310,6 +16979,7 @@ THREE.UniformsLib = { "size" : { type: "f", value: 1.0 }, "scale" : { type: "f", value: 1.0 }, "map" : { type: "t", value: null }, + "offsetRepeat" : { type: "v4", value: new THREE.Vector4( 0, 0, 1, 1 ) }, "fogDensity" : { type: "f", value: 0.00025 }, "fogNear" : { type: "f", value: 1 }, @@ -16357,6 +17027,7 @@ THREE.ShaderLib = { vertexShader: [ + THREE.ShaderChunk[ "common" ], THREE.ShaderChunk[ "map_pars_vertex" ], THREE.ShaderChunk[ "lightmap_pars_vertex" ], THREE.ShaderChunk[ "envmap_pars_vertex" ], @@ -16399,6 +17070,7 @@ THREE.ShaderLib = { "uniform vec3 diffuse;", "uniform float opacity;", + THREE.ShaderChunk[ "common" ], THREE.ShaderChunk[ "color_pars_fragment" ], THREE.ShaderChunk[ "map_pars_fragment" ], THREE.ShaderChunk[ "alphamap_pars_fragment" ], @@ -16411,22 +17083,28 @@ THREE.ShaderLib = { "void main() {", - " gl_FragColor = vec4( diffuse, opacity );", + " vec3 outgoingLight = vec3( 0.0 );", // outgoing light does not have an alpha, the surface does + " vec4 diffuseColor = vec4( diffuse, opacity );", THREE.ShaderChunk[ "logdepthbuf_fragment" ], THREE.ShaderChunk[ "map_fragment" ], + THREE.ShaderChunk[ "color_fragment" ], THREE.ShaderChunk[ "alphamap_fragment" ], THREE.ShaderChunk[ "alphatest_fragment" ], THREE.ShaderChunk[ "specularmap_fragment" ], - THREE.ShaderChunk[ "lightmap_fragment" ], - THREE.ShaderChunk[ "color_fragment" ], + + " outgoingLight = diffuseColor.rgb;", // simple shader + + THREE.ShaderChunk[ "lightmap_fragment" ], // TODO: Light map on an otherwise unlit surface doesn't make sense. THREE.ShaderChunk[ "envmap_fragment" ], - THREE.ShaderChunk[ "shadowmap_fragment" ], + THREE.ShaderChunk[ "shadowmap_fragment" ], // TODO: Shadows on an otherwise unlit surface doesn't make sense. THREE.ShaderChunk[ "linear_to_gamma_fragment" ], THREE.ShaderChunk[ "fog_fragment" ], + " gl_FragColor = vec4( outgoingLight, diffuseColor.a );", // TODO, this should be pre-multiplied to allow for bright highlights on very transparent objects + "}" ].join("\n") @@ -16443,7 +17121,6 @@ THREE.ShaderLib = { THREE.UniformsLib[ "shadowmap" ], { - "ambient" : { type: "c", value: new THREE.Color( 0xffffff ) }, "emissive" : { type: "c", value: new THREE.Color( 0x000000 ) }, "wrapRGB" : { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) } } @@ -16462,6 +17139,7 @@ THREE.ShaderLib = { "#endif", + THREE.ShaderChunk[ "common" ], THREE.ShaderChunk[ "map_pars_vertex" ], THREE.ShaderChunk[ "lightmap_pars_vertex" ], THREE.ShaderChunk[ "envmap_pars_vertex" ], @@ -16499,6 +17177,8 @@ THREE.ShaderLib = { fragmentShader: [ + "uniform vec3 diffuse;", + "uniform vec3 emissive;", "uniform float opacity;", "varying vec3 vLightFront;", @@ -16509,6 +17189,7 @@ THREE.ShaderLib = { "#endif", + THREE.ShaderChunk[ "common" ], THREE.ShaderChunk[ "color_pars_fragment" ], THREE.ShaderChunk[ "map_pars_fragment" ], THREE.ShaderChunk[ "alphamap_pars_fragment" ], @@ -16521,10 +17202,12 @@ THREE.ShaderLib = { "void main() {", - " gl_FragColor = vec4( vec3( 1.0 ), opacity );", + " vec3 outgoingLight = vec3( 0.0 );", // outgoing light does not have an alpha, the surface does + " vec4 diffuseColor = vec4( diffuse, opacity );", THREE.ShaderChunk[ "logdepthbuf_fragment" ], THREE.ShaderChunk[ "map_fragment" ], + THREE.ShaderChunk[ "color_fragment" ], THREE.ShaderChunk[ "alphamap_fragment" ], THREE.ShaderChunk[ "alphatest_fragment" ], THREE.ShaderChunk[ "specularmap_fragment" ], @@ -16535,18 +17218,17 @@ THREE.ShaderLib = { //"gl_FragColor.xyz *= isFront * vLightFront + ( 1.0 - isFront ) * vLightBack;", " if ( gl_FrontFacing )", - " gl_FragColor.xyz *= vLightFront;", + " outgoingLight += diffuseColor.rgb * vLightFront + emissive;", " else", - " gl_FragColor.xyz *= vLightBack;", + " outgoingLight += diffuseColor.rgb * vLightBack + emissive;", " #else", - " gl_FragColor.xyz *= vLightFront;", + " outgoingLight += diffuseColor.rgb * vLightFront + emissive;", " #endif", THREE.ShaderChunk[ "lightmap_fragment" ], - THREE.ShaderChunk[ "color_fragment" ], THREE.ShaderChunk[ "envmap_fragment" ], THREE.ShaderChunk[ "shadowmap_fragment" ], @@ -16554,6 +17236,8 @@ THREE.ShaderLib = { THREE.ShaderChunk[ "fog_fragment" ], + " gl_FragColor = vec4( outgoingLight, diffuseColor.a );", // TODO, this should be pre-multiplied to allow for bright highlights on very transparent objects + "}" ].join("\n") @@ -16572,7 +17256,6 @@ THREE.ShaderLib = { THREE.UniformsLib[ "shadowmap" ], { - "ambient" : { type: "c", value: new THREE.Color( 0xffffff ) }, "emissive" : { type: "c", value: new THREE.Color( 0x000000 ) }, "specular" : { type: "c", value: new THREE.Color( 0x111111 ) }, "shininess": { type: "f", value: 30 }, @@ -16586,8 +17269,14 @@ THREE.ShaderLib = { "#define PHONG", "varying vec3 vViewPosition;", - "varying vec3 vNormal;", + "#ifndef FLAT_SHADED", + + " varying vec3 vNormal;", + + "#endif", + + THREE.ShaderChunk[ "common" ], THREE.ShaderChunk[ "map_pars_vertex" ], THREE.ShaderChunk[ "lightmap_pars_vertex" ], THREE.ShaderChunk[ "envmap_pars_vertex" ], @@ -16609,8 +17298,12 @@ THREE.ShaderLib = { THREE.ShaderChunk[ "skinnormal_vertex" ], THREE.ShaderChunk[ "defaultnormal_vertex" ], + "#ifndef FLAT_SHADED", // Normal computed with derivatives when FLAT_SHADED + " vNormal = normalize( transformedNormal );", + "#endif", + THREE.ShaderChunk[ "morphtarget_vertex" ], THREE.ShaderChunk[ "skinning_vertex" ], THREE.ShaderChunk[ "default_vertex" ], @@ -16632,13 +17325,12 @@ THREE.ShaderLib = { "#define PHONG", "uniform vec3 diffuse;", - "uniform float opacity;", - - "uniform vec3 ambient;", "uniform vec3 emissive;", "uniform vec3 specular;", "uniform float shininess;", + "uniform float opacity;", + THREE.ShaderChunk[ "common" ], THREE.ShaderChunk[ "color_pars_fragment" ], THREE.ShaderChunk[ "map_pars_fragment" ], THREE.ShaderChunk[ "alphamap_pars_fragment" ], @@ -16654,10 +17346,12 @@ THREE.ShaderLib = { "void main() {", - " gl_FragColor = vec4( vec3( 1.0 ), opacity );", + " vec3 outgoingLight = vec3( 0.0 );", // outgoing light does not have an alpha, the surface does + " vec4 diffuseColor = vec4( diffuse, opacity );", THREE.ShaderChunk[ "logdepthbuf_fragment" ], THREE.ShaderChunk[ "map_fragment" ], + THREE.ShaderChunk[ "color_fragment" ], THREE.ShaderChunk[ "alphamap_fragment" ], THREE.ShaderChunk[ "alphatest_fragment" ], THREE.ShaderChunk[ "specularmap_fragment" ], @@ -16665,7 +17359,6 @@ THREE.ShaderLib = { THREE.ShaderChunk[ "lights_phong_fragment" ], THREE.ShaderChunk[ "lightmap_fragment" ], - THREE.ShaderChunk[ "color_fragment" ], THREE.ShaderChunk[ "envmap_fragment" ], THREE.ShaderChunk[ "shadowmap_fragment" ], @@ -16673,6 +17366,8 @@ THREE.ShaderLib = { THREE.ShaderChunk[ "fog_fragment" ], + " gl_FragColor = vec4( outgoingLight, diffuseColor.a );", // TODO, this should be pre-multiplied to allow for bright highlights on very transparent objects + "}" ].join("\n") @@ -16693,6 +17388,7 @@ THREE.ShaderLib = { "uniform float size;", "uniform float scale;", + THREE.ShaderChunk[ "common" ], THREE.ShaderChunk[ "color_pars_vertex" ], THREE.ShaderChunk[ "shadowmap_pars_vertex" ], THREE.ShaderChunk[ "logdepthbuf_pars_vertex" ], @@ -16724,6 +17420,7 @@ THREE.ShaderLib = { "uniform vec3 psColor;", "uniform float opacity;", + THREE.ShaderChunk[ "common" ], THREE.ShaderChunk[ "color_pars_fragment" ], THREE.ShaderChunk[ "map_particle_pars_fragment" ], THREE.ShaderChunk[ "fog_pars_fragment" ], @@ -16732,15 +17429,21 @@ THREE.ShaderLib = { "void main() {", - " gl_FragColor = vec4( psColor, opacity );", + " vec3 outgoingLight = vec3( 0.0 );", // outgoing light does not have an alpha, the surface does + " vec4 diffuseColor = vec4( psColor, opacity );", THREE.ShaderChunk[ "logdepthbuf_fragment" ], THREE.ShaderChunk[ "map_particle_fragment" ], - THREE.ShaderChunk[ "alphatest_fragment" ], THREE.ShaderChunk[ "color_fragment" ], + THREE.ShaderChunk[ "alphatest_fragment" ], + + " outgoingLight = diffuseColor.rgb;", // simple shader + THREE.ShaderChunk[ "shadowmap_fragment" ], THREE.ShaderChunk[ "fog_fragment" ], + " gl_FragColor = vec4( outgoingLight, diffuseColor.a );", // TODO, this should be pre-multiplied to allow for bright highlights on very transparent objects + "}" ].join("\n") @@ -16769,6 +17472,7 @@ THREE.ShaderLib = { "varying float vLineDistance;", + THREE.ShaderChunk[ "common" ], THREE.ShaderChunk[ "color_pars_vertex" ], THREE.ShaderChunk[ "logdepthbuf_pars_vertex" ], @@ -16797,6 +17501,7 @@ THREE.ShaderLib = { "varying float vLineDistance;", + THREE.ShaderChunk[ "common" ], THREE.ShaderChunk[ "color_pars_fragment" ], THREE.ShaderChunk[ "fog_pars_fragment" ], THREE.ShaderChunk[ "logdepthbuf_pars_fragment" ], @@ -16809,12 +17514,18 @@ THREE.ShaderLib = { " }", - " gl_FragColor = vec4( diffuse, opacity );", + " vec3 outgoingLight = vec3( 0.0 );", // outgoing light does not have an alpha, the surface does + " vec4 diffuseColor = vec4( diffuse, opacity );", THREE.ShaderChunk[ "logdepthbuf_fragment" ], THREE.ShaderChunk[ "color_fragment" ], + + " outgoingLight = diffuseColor.rgb;", // simple shader + THREE.ShaderChunk[ "fog_fragment" ], + " gl_FragColor = vec4( outgoingLight, diffuseColor.a );", // TODO, this should be pre-multiplied to allow for bright highlights on very transparent objects + "}" ].join("\n") @@ -16833,6 +17544,7 @@ THREE.ShaderLib = { vertexShader: [ + THREE.ShaderChunk[ "common" ], THREE.ShaderChunk[ "morphtarget_pars_vertex" ], THREE.ShaderChunk[ "logdepthbuf_pars_vertex" ], @@ -16852,6 +17564,7 @@ THREE.ShaderLib = { "uniform float mFar;", "uniform float opacity;", + THREE.ShaderChunk[ "common" ], THREE.ShaderChunk[ "logdepthbuf_pars_fragment" ], "void main() {", @@ -16869,7 +17582,7 @@ THREE.ShaderLib = { " #endif", " float color = 1.0 - smoothstep( mNear, mFar, depth );", - " gl_FragColor = vec4( vec3( color ), opacity );", + " gl_FragColor = vec4( vec3( color ), opacity );", // TODO, this should be pre-multiplied to allow for bright highlights on very transparent objects "}" @@ -16889,6 +17602,7 @@ THREE.ShaderLib = { "varying vec3 vNormal;", + THREE.ShaderChunk[ "common" ], THREE.ShaderChunk[ "morphtarget_pars_vertex" ], THREE.ShaderChunk[ "logdepthbuf_pars_vertex" ], @@ -16909,6 +17623,7 @@ THREE.ShaderLib = { "uniform float opacity;", "varying vec3 vNormal;", + THREE.ShaderChunk[ "common" ], THREE.ShaderChunk[ "logdepthbuf_pars_fragment" ], "void main() {", @@ -16924,616 +17639,48 @@ THREE.ShaderLib = { }, /* ------------------------------------------------------------------------- - // Normal map shader - // - Blinn-Phong - // - normal + diffuse + specular + AO + displacement + reflection + shadow maps - // - point and directional lights (use with "lights: true" material option) + // Cube map shader ------------------------------------------------------------------------- */ - 'normalmap' : { - - uniforms: THREE.UniformsUtils.merge( [ - - THREE.UniformsLib[ "fog" ], - THREE.UniformsLib[ "lights" ], - THREE.UniformsLib[ "shadowmap" ], - - { - - "enableAO" : { type: "i", value: 0 }, - "enableDiffuse" : { type: "i", value: 0 }, - "enableSpecular" : { type: "i", value: 0 }, - "enableReflection" : { type: "i", value: 0 }, - "enableDisplacement": { type: "i", value: 0 }, - - "tDisplacement": { type: "t", value: null }, // must go first as this is vertex texture - "tDiffuse" : { type: "t", value: null }, - "tCube" : { type: "t", value: null }, - "tNormal" : { type: "t", value: null }, - "tSpecular" : { type: "t", value: null }, - "tAO" : { type: "t", value: null }, - - "uNormalScale": { type: "v2", value: new THREE.Vector2( 1, 1 ) }, - - "uDisplacementBias": { type: "f", value: 0.0 }, - "uDisplacementScale": { type: "f", value: 1.0 }, - - "diffuse": { type: "c", value: new THREE.Color( 0xffffff ) }, - "specular": { type: "c", value: new THREE.Color( 0x111111 ) }, - "ambient": { type: "c", value: new THREE.Color( 0xffffff ) }, - "shininess": { type: "f", value: 30 }, - "opacity": { type: "f", value: 1 }, - - "useRefract": { type: "i", value: 0 }, - "refractionRatio": { type: "f", value: 0.98 }, - "reflectivity": { type: "f", value: 0.5 }, - - "uOffset" : { type: "v2", value: new THREE.Vector2( 0, 0 ) }, - "uRepeat" : { type: "v2", value: new THREE.Vector2( 1, 1 ) }, - - "wrapRGB" : { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) } - - } - - ] ), - - fragmentShader: [ - - "uniform vec3 ambient;", - "uniform vec3 diffuse;", - "uniform vec3 specular;", - "uniform float shininess;", - "uniform float opacity;", - - "uniform bool enableDiffuse;", - "uniform bool enableSpecular;", - "uniform bool enableAO;", - "uniform bool enableReflection;", - - "uniform sampler2D tDiffuse;", - "uniform sampler2D tNormal;", - "uniform sampler2D tSpecular;", - "uniform sampler2D tAO;", - - "uniform samplerCube tCube;", - - "uniform vec2 uNormalScale;", - - "uniform bool useRefract;", - "uniform float refractionRatio;", - "uniform float reflectivity;", - - "varying vec3 vTangent;", - "varying vec3 vBinormal;", - "varying vec3 vNormal;", - "varying vec2 vUv;", - - "uniform vec3 ambientLightColor;", - - "#if MAX_DIR_LIGHTS > 0", - - " uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];", - " uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];", - - "#endif", - - "#if MAX_HEMI_LIGHTS > 0", - - " uniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];", - " uniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];", - " uniform vec3 hemisphereLightDirection[ MAX_HEMI_LIGHTS ];", - - "#endif", - - "#if MAX_POINT_LIGHTS > 0", - - " uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];", - " uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];", - " uniform float pointLightDistance[ MAX_POINT_LIGHTS ];", - - "#endif", - - "#if MAX_SPOT_LIGHTS > 0", - - " uniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];", - " uniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];", - " uniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];", - " uniform float spotLightAngleCos[ MAX_SPOT_LIGHTS ];", - " uniform float spotLightExponent[ MAX_SPOT_LIGHTS ];", - " uniform float spotLightDistance[ MAX_SPOT_LIGHTS ];", - - "#endif", - - "#ifdef WRAP_AROUND", + 'cube': { - " uniform vec3 wrapRGB;", + uniforms: { "tCube": { type: "t", value: null }, + "tFlip": { type: "f", value: - 1 } }, - "#endif", + vertexShader: [ "varying vec3 vWorldPosition;", - "varying vec3 vViewPosition;", - THREE.ShaderChunk[ "shadowmap_pars_fragment" ], - THREE.ShaderChunk[ "fog_pars_fragment" ], - THREE.ShaderChunk[ "logdepthbuf_pars_fragment" ], + THREE.ShaderChunk[ "common" ], + THREE.ShaderChunk[ "logdepthbuf_pars_vertex" ], "void main() {", - THREE.ShaderChunk[ "logdepthbuf_fragment" ], - - " gl_FragColor = vec4( vec3( 1.0 ), opacity );", - - " vec3 specularTex = vec3( 1.0 );", - - " vec3 normalTex = texture2D( tNormal, vUv ).xyz * 2.0 - 1.0;", - " normalTex.xy *= uNormalScale;", - " normalTex = normalize( normalTex );", - - " if( enableDiffuse ) {", - - " #ifdef GAMMA_INPUT", - - " vec4 texelColor = texture2D( tDiffuse, vUv );", - " texelColor.xyz *= texelColor.xyz;", - - " gl_FragColor = gl_FragColor * texelColor;", - - " #else", - - " gl_FragColor = gl_FragColor * texture2D( tDiffuse, vUv );", - - " #endif", - - " }", - - " if( enableAO ) {", - - " #ifdef GAMMA_INPUT", - - " vec4 aoColor = texture2D( tAO, vUv );", - " aoColor.xyz *= aoColor.xyz;", - - " gl_FragColor.xyz = gl_FragColor.xyz * aoColor.xyz;", - - " #else", - - " gl_FragColor.xyz = gl_FragColor.xyz * texture2D( tAO, vUv ).xyz;", - - " #endif", - - " }", - - THREE.ShaderChunk[ "alphatest_fragment" ], - - " if( enableSpecular )", - " specularTex = texture2D( tSpecular, vUv ).xyz;", - - " mat3 tsb = mat3( normalize( vTangent ), normalize( vBinormal ), normalize( vNormal ) );", - " vec3 finalNormal = tsb * normalTex;", - - " #ifdef FLIP_SIDED", - - " finalNormal = -finalNormal;", - - " #endif", - - " vec3 normal = normalize( finalNormal );", - " vec3 viewPosition = normalize( vViewPosition );", - - // point lights - - " #if MAX_POINT_LIGHTS > 0", - - " vec3 pointDiffuse = vec3( 0.0 );", - " vec3 pointSpecular = vec3( 0.0 );", - - " for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {", - - " vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );", - " vec3 pointVector = lPosition.xyz + vViewPosition.xyz;", - - " float pointDistance = 1.0;", - " if ( pointLightDistance[ i ] > 0.0 )", - " pointDistance = 1.0 - min( ( length( pointVector ) / pointLightDistance[ i ] ), 1.0 );", - - " pointVector = normalize( pointVector );", - - // diffuse - - " #ifdef WRAP_AROUND", - - " float pointDiffuseWeightFull = max( dot( normal, pointVector ), 0.0 );", - " float pointDiffuseWeightHalf = max( 0.5 * dot( normal, pointVector ) + 0.5, 0.0 );", - - " vec3 pointDiffuseWeight = mix( vec3( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );", - - " #else", - - " float pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );", - - " #endif", - - " pointDiffuse += pointDistance * pointLightColor[ i ] * diffuse * pointDiffuseWeight;", - - // specular - - " vec3 pointHalfVector = normalize( pointVector + viewPosition );", - " float pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );", - " float pointSpecularWeight = specularTex.r * max( pow( pointDotNormalHalf, shininess ), 0.0 );", - - " float specularNormalization = ( shininess + 2.0 ) / 8.0;", - - " vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( pointVector, pointHalfVector ), 0.0 ), 5.0 );", - " pointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * pointDistance * specularNormalization;", - - " }", - - " #endif", - - // spot lights - - " #if MAX_SPOT_LIGHTS > 0", - - " vec3 spotDiffuse = vec3( 0.0 );", - " vec3 spotSpecular = vec3( 0.0 );", - - " for ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {", - - " vec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );", - " vec3 spotVector = lPosition.xyz + vViewPosition.xyz;", - - " float spotDistance = 1.0;", - " if ( spotLightDistance[ i ] > 0.0 )", - " spotDistance = 1.0 - min( ( length( spotVector ) / spotLightDistance[ i ] ), 1.0 );", - - " spotVector = normalize( spotVector );", - - " float spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) );", - - " if ( spotEffect > spotLightAngleCos[ i ] ) {", - - " spotEffect = max( pow( max( spotEffect, 0.0 ), spotLightExponent[ i ] ), 0.0 );", - - // diffuse - - " #ifdef WRAP_AROUND", - - " float spotDiffuseWeightFull = max( dot( normal, spotVector ), 0.0 );", - " float spotDiffuseWeightHalf = max( 0.5 * dot( normal, spotVector ) + 0.5, 0.0 );", - - " vec3 spotDiffuseWeight = mix( vec3( spotDiffuseWeightFull ), vec3( spotDiffuseWeightHalf ), wrapRGB );", - - " #else", - - " float spotDiffuseWeight = max( dot( normal, spotVector ), 0.0 );", - - " #endif", - - " spotDiffuse += spotDistance * spotLightColor[ i ] * diffuse * spotDiffuseWeight * spotEffect;", - - // specular - - " vec3 spotHalfVector = normalize( spotVector + viewPosition );", - " float spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );", - " float spotSpecularWeight = specularTex.r * max( pow( spotDotNormalHalf, shininess ), 0.0 );", - - " float specularNormalization = ( shininess + 2.0 ) / 8.0;", - - " vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( spotVector, spotHalfVector ), 0.0 ), 5.0 );", - " spotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * spotDistance * specularNormalization * spotEffect;", - - " }", - " }", + " vWorldPosition = transformDirection( position, modelMatrix );", - " #endif", - - // directional lights - - " #if MAX_DIR_LIGHTS > 0", - - " vec3 dirDiffuse = vec3( 0.0 );", - " vec3 dirSpecular = vec3( 0.0 );", - - " for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {", - - " vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );", - " vec3 dirVector = normalize( lDirection.xyz );", - - // diffuse - - " #ifdef WRAP_AROUND", - - " float directionalLightWeightingFull = max( dot( normal, dirVector ), 0.0 );", - " float directionalLightWeightingHalf = max( 0.5 * dot( normal, dirVector ) + 0.5, 0.0 );", - - " vec3 dirDiffuseWeight = mix( vec3( directionalLightWeightingFull ), vec3( directionalLightWeightingHalf ), wrapRGB );", - - " #else", - - " float dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );", - - " #endif", - - " dirDiffuse += directionalLightColor[ i ] * diffuse * dirDiffuseWeight;", - - // specular - - " vec3 dirHalfVector = normalize( dirVector + viewPosition );", - " float dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );", - " float dirSpecularWeight = specularTex.r * max( pow( dirDotNormalHalf, shininess ), 0.0 );", - - " float specularNormalization = ( shininess + 2.0 ) / 8.0;", - - " vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( dirVector, dirHalfVector ), 0.0 ), 5.0 );", - " dirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;", - - " }", - - " #endif", - - // hemisphere lights - - " #if MAX_HEMI_LIGHTS > 0", - - " vec3 hemiDiffuse = vec3( 0.0 );", - " vec3 hemiSpecular = vec3( 0.0 );" , - - " for( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {", - - " vec4 lDirection = viewMatrix * vec4( hemisphereLightDirection[ i ], 0.0 );", - " vec3 lVector = normalize( lDirection.xyz );", - - // diffuse - - " float dotProduct = dot( normal, lVector );", - " float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;", - - " vec3 hemiColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );", - - " hemiDiffuse += diffuse * hemiColor;", - - // specular (sky light) - - - " vec3 hemiHalfVectorSky = normalize( lVector + viewPosition );", - " float hemiDotNormalHalfSky = 0.5 * dot( normal, hemiHalfVectorSky ) + 0.5;", - " float hemiSpecularWeightSky = specularTex.r * max( pow( max( hemiDotNormalHalfSky, 0.0 ), shininess ), 0.0 );", - - // specular (ground light) - - " vec3 lVectorGround = -lVector;", - - " vec3 hemiHalfVectorGround = normalize( lVectorGround + viewPosition );", - " float hemiDotNormalHalfGround = 0.5 * dot( normal, hemiHalfVectorGround ) + 0.5;", - " float hemiSpecularWeightGround = specularTex.r * max( pow( max( hemiDotNormalHalfGround, 0.0 ), shininess ), 0.0 );", - - " float dotProductGround = dot( normal, lVectorGround );", - - " float specularNormalization = ( shininess + 2.0 ) / 8.0;", - - " vec3 schlickSky = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, hemiHalfVectorSky ), 0.0 ), 5.0 );", - " vec3 schlickGround = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVectorGround, hemiHalfVectorGround ), 0.0 ), 5.0 );", - " hemiSpecular += hemiColor * specularNormalization * ( schlickSky * hemiSpecularWeightSky * max( dotProduct, 0.0 ) + schlickGround * hemiSpecularWeightGround * max( dotProductGround, 0.0 ) );", - - " }", - - " #endif", - - // all lights contribution summation - - " vec3 totalDiffuse = vec3( 0.0 );", - " vec3 totalSpecular = vec3( 0.0 );", - - " #if MAX_DIR_LIGHTS > 0", - - " totalDiffuse += dirDiffuse;", - " totalSpecular += dirSpecular;", - - " #endif", - - " #if MAX_HEMI_LIGHTS > 0", - - " totalDiffuse += hemiDiffuse;", - " totalSpecular += hemiSpecular;", - - " #endif", - - " #if MAX_POINT_LIGHTS > 0", - - " totalDiffuse += pointDiffuse;", - " totalSpecular += pointSpecular;", - - " #endif", - - " #if MAX_SPOT_LIGHTS > 0", - - " totalDiffuse += spotDiffuse;", - " totalSpecular += spotSpecular;", - - " #endif", - - " #ifdef METAL", - - " gl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * ambient + totalSpecular );", - - " #else", - - " gl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * ambient ) + totalSpecular;", - - " #endif", - - " if ( enableReflection ) {", - - " vec3 vReflect;", - " vec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );", - - " if ( useRefract ) {", - - " vReflect = refract( cameraToVertex, normal, refractionRatio );", - - " } else {", - - " vReflect = reflect( cameraToVertex, normal );", - - " }", - - " vec4 cubeColor = textureCube( tCube, vec3( -vReflect.x, vReflect.yz ) );", - - " #ifdef GAMMA_INPUT", - - " cubeColor.xyz *= cubeColor.xyz;", - - " #endif", - - " gl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularTex.r * reflectivity );", - - " }", + " gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", - THREE.ShaderChunk[ "shadowmap_fragment" ], - THREE.ShaderChunk[ "linear_to_gamma_fragment" ], - THREE.ShaderChunk[ "fog_fragment" ], + THREE.ShaderChunk[ "logdepthbuf_vertex" ], "}" ].join("\n"), - vertexShader: [ - - "attribute vec4 tangent;", - - "uniform vec2 uOffset;", - "uniform vec2 uRepeat;", - - "uniform bool enableDisplacement;", - - "#ifdef VERTEX_TEXTURES", - - " uniform sampler2D tDisplacement;", - " uniform float uDisplacementScale;", - " uniform float uDisplacementBias;", - - "#endif", + fragmentShader: [ - "varying vec3 vTangent;", - "varying vec3 vBinormal;", - "varying vec3 vNormal;", - "varying vec2 vUv;", + "uniform samplerCube tCube;", + "uniform float tFlip;", "varying vec3 vWorldPosition;", - "varying vec3 vViewPosition;", - THREE.ShaderChunk[ "skinning_pars_vertex" ], - THREE.ShaderChunk[ "shadowmap_pars_vertex" ], - THREE.ShaderChunk[ "logdepthbuf_pars_vertex" ], + THREE.ShaderChunk[ "common" ], + THREE.ShaderChunk[ "logdepthbuf_pars_fragment" ], "void main() {", - THREE.ShaderChunk[ "skinbase_vertex" ], - THREE.ShaderChunk[ "skinnormal_vertex" ], - - // normal, tangent and binormal vectors - - " #ifdef USE_SKINNING", - - " vNormal = normalize( normalMatrix * skinnedNormal.xyz );", - - " vec4 skinnedTangent = skinMatrix * vec4( tangent.xyz, 0.0 );", - " vTangent = normalize( normalMatrix * skinnedTangent.xyz );", - - " #else", - - " vNormal = normalize( normalMatrix * normal );", - " vTangent = normalize( normalMatrix * tangent.xyz );", - - " #endif", - - " vBinormal = normalize( cross( vNormal, vTangent ) * tangent.w );", - - " vUv = uv * uRepeat + uOffset;", - - // displacement mapping - - " vec3 displacedPosition;", - - " #ifdef VERTEX_TEXTURES", - - " if ( enableDisplacement ) {", - - " vec3 dv = texture2D( tDisplacement, uv ).xyz;", - " float df = uDisplacementScale * dv.x + uDisplacementBias;", - " displacedPosition = position + normalize( normal ) * df;", - - " } else {", - - " #ifdef USE_SKINNING", - - " vec4 skinVertex = bindMatrix * vec4( position, 1.0 );", - - " vec4 skinned = vec4( 0.0 );", - " skinned += boneMatX * skinVertex * skinWeight.x;", - " skinned += boneMatY * skinVertex * skinWeight.y;", - " skinned += boneMatZ * skinVertex * skinWeight.z;", - " skinned += boneMatW * skinVertex * skinWeight.w;", - " skinned = bindMatrixInverse * skinned;", - - " displacedPosition = skinned.xyz;", - - " #else", - - " displacedPosition = position;", - - " #endif", - - " }", - - " #else", - - " #ifdef USE_SKINNING", - - " vec4 skinVertex = bindMatrix * vec4( position, 1.0 );", - - " vec4 skinned = vec4( 0.0 );", - " skinned += boneMatX * skinVertex * skinWeight.x;", - " skinned += boneMatY * skinVertex * skinWeight.y;", - " skinned += boneMatZ * skinVertex * skinWeight.z;", - " skinned += boneMatW * skinVertex * skinWeight.w;", - " skinned = bindMatrixInverse * skinned;", - - " displacedPosition = skinned.xyz;", - - " #else", - - " displacedPosition = position;", - - " #endif", - - " #endif", - - // - - " vec4 mvPosition = modelViewMatrix * vec4( displacedPosition, 1.0 );", - " vec4 worldPosition = modelMatrix * vec4( displacedPosition, 1.0 );", - - " gl_Position = projectionMatrix * mvPosition;", - - THREE.ShaderChunk[ "logdepthbuf_vertex" ], - - // - - " vWorldPosition = worldPosition.xyz;", - " vViewPosition = -mvPosition.xyz;", - - // shadows - - " #ifdef USE_SHADOWMAP", - - " for( int i = 0; i < MAX_SHADOWS; i ++ ) {", - - " vShadowCoord[ i ] = shadowMatrix[ i ] * worldPosition;", - - " }", + " gl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );", - " #endif", + THREE.ShaderChunk[ "logdepthbuf_fragment" ], "}" @@ -17545,21 +17692,21 @@ THREE.ShaderLib = { // Cube map shader ------------------------------------------------------------------------- */ - 'cube': { + 'equirect': { - uniforms: { "tCube": { type: "t", value: null }, + uniforms: { "tEquirect": { type: "t", value: null }, "tFlip": { type: "f", value: - 1 } }, vertexShader: [ "varying vec3 vWorldPosition;", + THREE.ShaderChunk[ "common" ], THREE.ShaderChunk[ "logdepthbuf_pars_vertex" ], "void main() {", - " vec4 worldPosition = modelMatrix * vec4( position, 1.0 );", - " vWorldPosition = worldPosition.xyz;", + " vWorldPosition = transformDirection( position, modelMatrix );", " gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", @@ -17571,16 +17718,22 @@ THREE.ShaderLib = { fragmentShader: [ - "uniform samplerCube tCube;", + "uniform sampler2D tEquirect;", "uniform float tFlip;", "varying vec3 vWorldPosition;", + THREE.ShaderChunk[ "common" ], THREE.ShaderChunk[ "logdepthbuf_pars_fragment" ], "void main() {", - " gl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );", + // " gl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );", + "vec3 direction = normalize( vWorldPosition );", + "vec2 sampleUV;", + "sampleUV.y = saturate( tFlip * direction.y * -0.5 + 0.5 );", + "sampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;", + "gl_FragColor = texture2D( tEquirect, sampleUV );", THREE.ShaderChunk[ "logdepthbuf_fragment" ], @@ -17608,6 +17761,7 @@ THREE.ShaderLib = { vertexShader: [ + THREE.ShaderChunk[ "common" ], THREE.ShaderChunk[ "morphtarget_pars_vertex" ], THREE.ShaderChunk[ "skinning_pars_vertex" ], THREE.ShaderChunk[ "logdepthbuf_pars_vertex" ], @@ -17626,6 +17780,7 @@ THREE.ShaderLib = { fragmentShader: [ + THREE.ShaderChunk[ "common" ], THREE.ShaderChunk[ "logdepthbuf_pars_fragment" ], "vec4 pack_depth( const in float depth ) {", @@ -17683,6 +17838,8 @@ THREE.WebGLRenderer = function ( parameters ) { var _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElement( 'canvas' ), _context = parameters.context !== undefined ? parameters.context : null, + pixelRatio = 1, + _precision = parameters.precision !== undefined ? parameters.precision : 'highp', _alpha = parameters.alpha !== undefined ? parameters.alpha : false, @@ -17711,11 +17868,6 @@ THREE.WebGLRenderer = function ( parameters ) { this.domElement = _canvas; this.context = null; - this.devicePixelRatio = parameters.devicePixelRatio !== undefined - ? parameters.devicePixelRatio - : self.devicePixelRatio !== undefined - ? self.devicePixelRatio - : 1; // clearing @@ -17730,6 +17882,7 @@ THREE.WebGLRenderer = function ( parameters ) { // physically based shading + this.gammaFactor = 2.0; // for backwards compatibility this.gammaInput = false; this.gammaOutput = false; @@ -17784,31 +17937,11 @@ THREE.WebGLRenderer = function ( parameters ) { _currentProgram = null, _currentFramebuffer = null, _currentMaterialId = - 1, - _currentGeometryGroupHash = - 1, + _currentGeometryProgram = '', _currentCamera = null, _usedTextureUnits = 0, - // GL state cache - - _oldDoubleSided = - 1, - _oldFlipSided = - 1, - - _oldBlending = - 1, - - _oldBlendEquation = - 1, - _oldBlendSrc = - 1, - _oldBlendDst = - 1, - - _oldDepthTest = - 1, - _oldDepthWrite = - 1, - - _oldPolygonOffset = null, - _oldPolygonOffsetFactor = null, - _oldPolygonOffsetUnits = null, - - _oldLineWidth = null, - _viewportX = 0, _viewportY = 0, _viewportWidth = _canvas.width, @@ -17816,9 +17949,6 @@ THREE.WebGLRenderer = function ( parameters ) { _currentWidth = 0, _currentHeight = 0, - _newAttributes = new Uint8Array( 16 ), - _enabledAttributes = new Uint8Array( 16 ), - // frustum _frustum = new THREE.Frustum(), @@ -17826,7 +17956,6 @@ THREE.WebGLRenderer = function ( parameters ) { // camera matrices cache _projScreenMatrix = new THREE.Matrix4(), - _projScreenMatrixPS = new THREE.Matrix4(), _vector3 = new THREE.Vector3(), @@ -17840,8 +17969,8 @@ THREE.WebGLRenderer = function ( parameters ) { ambient: [ 0, 0, 0 ], directional: { length: 0, colors:[], positions: [] }, - point: { length: 0, colors: [], positions: [], distances: [] }, - spot: { length: 0, colors: [], positions: [], distances: [], directions: [], anglesCos: [], exponents: [] }, + point: { length: 0, colors: [], positions: [], distances: [], decays: [] }, + spot: { length: 0, colors: [], positions: [], distances: [], directions: [], anglesCos: [], exponents: [], decays: [] }, hemi: { length: 0, skyColors: [], groundColors: [], positions: [] } }; @@ -17877,12 +18006,25 @@ THREE.WebGLRenderer = function ( parameters ) { } + _canvas.addEventListener( 'webglcontextlost', function ( event ) { + + event.preventDefault(); + + resetGLState(); + setDefaultGLState(); + + _webglObjects = {}; + + }, false); + } catch ( error ) { - console.error( error ); + THREE.error( 'THREE.WebGLRenderer: ' + error ); } + var state = new THREE.WebGLState( _gl, paramThreeToGL ); + if ( _gl.getShaderPrecisionFormat === undefined ) { _gl.getShaderPrecisionFormat = function () { @@ -17901,6 +18043,8 @@ THREE.WebGLRenderer = function ( parameters ) { extensions.get( 'OES_texture_float' ); extensions.get( 'OES_texture_float_linear' ); + extensions.get( 'OES_texture_half_float' ); + extensions.get( 'OES_texture_half_float_linear' ); extensions.get( 'OES_standard_derivatives' ); if ( _logarithmicDepthBuffer ) { @@ -17911,7 +18055,19 @@ THREE.WebGLRenderer = function ( parameters ) { // - function setDefaultGLState() { + var glClearColor = function ( r, g, b, a ) { + + if ( _premultipliedAlpha === true ) { + + r *= a; g *= a; b *= a; + + } + + _gl.clearColor( r, g, b, a ); + + }; + + var setDefaultGLState = function () { _gl.clearColor( 0, 0, 0, 1 ); _gl.clearDepth( 1 ); @@ -17930,13 +18086,28 @@ THREE.WebGLRenderer = function ( parameters ) { _gl.viewport( _viewportX, _viewportY, _viewportWidth, _viewportHeight ); - _gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha ); + glClearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha ); - } + }; + + var resetGLState = function () { + + _currentProgram = null; + _currentCamera = null; + + _currentGeometryProgram = ''; + _currentMaterialId = - 1; + + _lightsNeedUpdate = true; + + state.reset(); + + }; setDefaultGLState(); this.context = _gl; + this.state = state; // GPU capabilities @@ -17952,11 +18123,9 @@ THREE.WebGLRenderer = function ( parameters ) { var _vertexShaderPrecisionHighpFloat = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.HIGH_FLOAT ); var _vertexShaderPrecisionMediumpFloat = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.MEDIUM_FLOAT ); - var _vertexShaderPrecisionLowpFloat = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.LOW_FLOAT ); var _fragmentShaderPrecisionHighpFloat = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.HIGH_FLOAT ); var _fragmentShaderPrecisionMediumpFloat = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.MEDIUM_FLOAT ); - var _fragmentShaderPrecisionLowpFloat = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.LOW_FLOAT ); var getCompressedTextureFormats = ( function () { @@ -17976,14 +18145,14 @@ THREE.WebGLRenderer = function ( parameters ) { var formats = _gl.getParameter( _gl.COMPRESSED_TEXTURE_FORMATS ); - for ( var i = 0; i < formats.length; i ++ ){ + for ( var i = 0; i < formats.length; i ++ ) { array.push( formats[ i ] ); } } - + return array; }; @@ -18000,12 +18169,12 @@ THREE.WebGLRenderer = function ( parameters ) { if ( mediumpAvailable ) { _precision = 'mediump'; - console.warn( 'THREE.WebGLRenderer: highp not supported, using mediump.' ); + THREE.warn( 'THREE.WebGLRenderer: highp not supported, using mediump.' ); } else { _precision = 'lowp'; - console.warn( 'THREE.WebGLRenderer: highp and mediump not supported, using lowp.' ); + THREE.warn( 'THREE.WebGLRenderer: highp and mediump not supported, using lowp.' ); } @@ -18014,7 +18183,7 @@ THREE.WebGLRenderer = function ( parameters ) { if ( _precision === 'mediump' && ! mediumpAvailable ) { _precision = 'lowp'; - console.warn( 'THREE.WebGLRenderer: mediump not supported, using lowp.' ); + THREE.warn( 'THREE.WebGLRenderer: mediump not supported, using lowp.' ); } @@ -18033,6 +18202,12 @@ THREE.WebGLRenderer = function ( parameters ) { }; + this.forceContextLoss = function () { + + extensions.get( 'WEBGL_lose_context' ).loseContext(); + + }; + this.supportsVertexTextures = function () { return _supportsVertexTextures; @@ -18045,6 +18220,12 @@ THREE.WebGLRenderer = function ( parameters ) { }; + this.supportsHalfFloatTextures = function () { + + return extensions.get( 'OES_texture_half_float' ); + + }; + this.supportsStandardDerivatives = function () { return extensions.get( 'OES_standard_derivatives' ); @@ -18097,10 +18278,22 @@ THREE.WebGLRenderer = function ( parameters ) { }; + this.getPixelRatio = function () { + + return pixelRatio; + + }; + + this.setPixelRatio = function ( value ) { + + pixelRatio = value; + + }; + this.setSize = function ( width, height, updateStyle ) { - _canvas.width = width * this.devicePixelRatio; - _canvas.height = height * this.devicePixelRatio; + _canvas.width = width * pixelRatio; + _canvas.height = height * pixelRatio; if ( updateStyle !== false ) { @@ -18115,11 +18308,11 @@ THREE.WebGLRenderer = function ( parameters ) { this.setViewport = function ( x, y, width, height ) { - _viewportX = x * this.devicePixelRatio; - _viewportY = y * this.devicePixelRatio; + _viewportX = x * pixelRatio; + _viewportY = y * pixelRatio; - _viewportWidth = width * this.devicePixelRatio; - _viewportHeight = height * this.devicePixelRatio; + _viewportWidth = width * pixelRatio; + _viewportHeight = height * pixelRatio; _gl.viewport( _viewportX, _viewportY, _viewportWidth, _viewportHeight ); @@ -18128,10 +18321,10 @@ THREE.WebGLRenderer = function ( parameters ) { this.setScissor = function ( x, y, width, height ) { _gl.scissor( - x * this.devicePixelRatio, - y * this.devicePixelRatio, - width * this.devicePixelRatio, - height * this.devicePixelRatio + x * pixelRatio, + y * pixelRatio, + width * pixelRatio, + height * pixelRatio ); }; @@ -18144,31 +18337,33 @@ THREE.WebGLRenderer = function ( parameters ) { // Clearing + this.getClearColor = function () { + + return _clearColor; + + }; + this.setClearColor = function ( color, alpha ) { _clearColor.set( color ); + _clearAlpha = alpha !== undefined ? alpha : 1; - _gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha ); + glClearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha ); }; - this.setClearColorHex = function ( hex, alpha ) { + this.getClearAlpha = function () { - console.warn( 'THREE.WebGLRenderer: .setClearColorHex() is being removed. Use .setClearColor() instead.' ); - this.setClearColor( hex, alpha ); + return _clearAlpha; }; - this.getClearColor = function () { - - return _clearColor; - - }; + this.setClearAlpha = function ( alpha ) { - this.getClearAlpha = function () { + _clearAlpha = alpha; - return _clearAlpha; + glClearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha ); }; @@ -18211,22 +18406,7 @@ THREE.WebGLRenderer = function ( parameters ) { // Reset - this.resetGLState = function () { - - _currentProgram = null; - _currentCamera = null; - - _oldBlending = - 1; - _oldDepthTest = - 1; - _oldDepthWrite = - 1; - _oldDoubleSided = - 1; - _oldFlipSided = - 1; - _currentGeometryGroupHash = - 1; - _currentMaterialId = - 1; - - _lightsNeedUpdate = true; - - }; + this.resetGLState = resetGLState; // Buffer allocation @@ -18264,13 +18444,13 @@ THREE.WebGLRenderer = function ( parameters ) { geometryGroup.__webglFaceBuffer = _gl.createBuffer(); geometryGroup.__webglLineBuffer = _gl.createBuffer(); - var m, ml; + var numMorphTargets = geometryGroup.numMorphTargets; - if ( geometryGroup.numMorphTargets ) { + if ( numMorphTargets ) { geometryGroup.__webglMorphTargetsBuffers = []; - for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) { + for ( var m = 0, ml = numMorphTargets; m < ml; m ++ ) { geometryGroup.__webglMorphTargetsBuffers.push( _gl.createBuffer() ); @@ -18278,11 +18458,13 @@ THREE.WebGLRenderer = function ( parameters ) { } - if ( geometryGroup.numMorphNormals ) { + var numMorphNormals = geometryGroup.numMorphNormals; + + if ( numMorphNormals ) { geometryGroup.__webglMorphNormalsBuffers = []; - for ( m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) { + for ( var m = 0, ml = numMorphNormals; m < ml; m ++ ) { geometryGroup.__webglMorphNormalsBuffers.push( _gl.createBuffer() ); @@ -18358,7 +18540,7 @@ THREE.WebGLRenderer = function ( parameters ) { // Buffer deallocation var deleteBuffers = function ( geometry ) { - + var buffers = [ '__webglVertexBuffer', '__webglNormalBuffer', @@ -18366,13 +18548,13 @@ THREE.WebGLRenderer = function ( parameters ) { '__webglColorBuffer', '__webglUVBuffer', '__webglUV2Buffer', - + '__webglSkinIndicesBuffer', '__webglSkinWeightsBuffer', - + '__webglFaceBuffer', '__webglLineBuffer', - + '__webglLineDistanceBuffer' ]; @@ -18415,7 +18597,7 @@ THREE.WebGLRenderer = function ( parameters ) { if ( geometry instanceof THREE.BufferGeometry ) { for ( var name in geometry.attributes ) { - + var attribute = geometry.attributes[ name ]; if ( attribute.buffer !== undefined ) { @@ -18436,7 +18618,7 @@ THREE.WebGLRenderer = function ( parameters ) { if ( geometryGroupsList !== undefined ) { - for ( var i = 0,l = geometryGroupsList.length; i < l; i ++ ) { + for ( var i = 0, l = geometryGroupsList.length; i < l; i ++ ) { var geometryGroup = geometryGroupsList[ i ]; @@ -18480,7 +18662,7 @@ THREE.WebGLRenderer = function ( parameters ) { // TOFIX: Workaround for deleted geometry being currently bound - _currentGeometryGroupHash = - 1; + _currentGeometryProgram = ''; }; @@ -18659,8 +18841,6 @@ THREE.WebGLRenderer = function ( parameters ) { geometry.__vertexArray = new Float32Array( nvertices * 3 ); geometry.__colorArray = new Float32Array( nvertices * 3 ); - geometry.__sortArray = []; - geometry.__webglParticleCount = nvertices; initCustomAttributes( object ); @@ -18722,13 +18902,13 @@ THREE.WebGLRenderer = function ( parameters ) { geometryGroup.__faceArray = new UintArray( ntris * 3 ); geometryGroup.__lineArray = new UintArray( nlines * 2 ); - var m, ml; + var numMorphTargets = geometryGroup.numMorphTargets; - if ( geometryGroup.numMorphTargets ) { + if ( numMorphTargets ) { geometryGroup.__morphTargetsArrays = []; - for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) { + for ( var m = 0, ml = numMorphTargets; m < ml; m ++ ) { geometryGroup.__morphTargetsArrays.push( new Float32Array( nvertices * 3 ) ); @@ -18736,11 +18916,13 @@ THREE.WebGLRenderer = function ( parameters ) { } - if ( geometryGroup.numMorphNormals ) { + var numMorphNormals = geometryGroup.numMorphNormals; + + if ( numMorphNormals ) { geometryGroup.__morphNormalsArrays = []; - for ( m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) { + for ( var m = 0, ml = numMorphNormals; m < ml; m ++ ) { geometryGroup.__morphNormalsArrays.push( new Float32Array( nvertices * 3 ) ); @@ -18816,19 +18998,19 @@ THREE.WebGLRenderer = function ( parameters ) { ? object.material.materials[ geometryGroup.materialIndex ] : object.material; - }; + } - function materialNeedsSmoothNormals ( material ) { + function materialNeedsFaceNormals ( material ) { - return material && material.shading !== undefined && material.shading === THREE.SmoothShading; + return material instanceof THREE.MeshPhongMaterial === false && material.shading === THREE.FlatShading; - }; + } // Buffer setting function setParticleBuffers ( geometry, hint, object ) { - var v, c, vertex, offset, index, color, + var v, c, vertex, offset, color, vertices = geometry.vertices, vl = vertices.length, @@ -18839,39 +19021,20 @@ THREE.WebGLRenderer = function ( parameters ) { vertexArray = geometry.__vertexArray, colorArray = geometry.__colorArray, - sortArray = geometry.__sortArray, - dirtyVertices = geometry.verticesNeedUpdate, - dirtyElements = geometry.elementsNeedUpdate, dirtyColors = geometry.colorsNeedUpdate, customAttributes = geometry.__webglCustomAttributesList, i, il, - a, ca, cal, value, + ca, cal, value, customAttribute; - if ( object.sortParticles ) { - - _projScreenMatrixPS.copy( _projScreenMatrix ); - _projScreenMatrixPS.multiply( object.matrixWorld ); + if ( dirtyVertices ) { for ( v = 0; v < vl; v ++ ) { vertex = vertices[ v ]; - _vector3.copy( vertex ); - _vector3.applyProjection( _projScreenMatrixPS ); - - sortArray[ v ] = [ _vector3.z, v ]; - - } - - sortArray.sort( numericalSort ); - - for ( v = 0; v < vl; v ++ ) { - - vertex = vertices[ sortArray[ v ][ 1 ] ]; - offset = v * 3; vertexArray[ offset ] = vertex.x; @@ -18880,11 +19043,18 @@ THREE.WebGLRenderer = function ( parameters ) { } + _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglVertexBuffer ); + _gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint ); + + } + + if ( dirtyColors ) { + for ( c = 0; c < cl; c ++ ) { - offset = c * 3; + color = colors[ c ]; - color = colors[ sortArray[ c ][ 1 ] ]; + offset = c * 3; colorArray[ offset ] = color.r; colorArray[ offset + 1 ] = color.g; @@ -18892,25 +19062,28 @@ THREE.WebGLRenderer = function ( parameters ) { } - if ( customAttributes ) { + _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglColorBuffer ); + _gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint ); + + } - for ( i = 0, il = customAttributes.length; i < il; i ++ ) { + if ( customAttributes ) { - customAttribute = customAttributes[ i ]; + for ( i = 0, il = customAttributes.length; i < il; i ++ ) { - if ( ! ( customAttribute.boundTo === undefined || customAttribute.boundTo === 'vertices' ) ) continue; + customAttribute = customAttributes[ i ]; - offset = 0; + if ( customAttribute.needsUpdate && ( customAttribute.boundTo === undefined || customAttribute.boundTo === 'vertices' ) ) { cal = customAttribute.value.length; + offset = 0; + if ( customAttribute.size === 1 ) { for ( ca = 0; ca < cal; ca ++ ) { - index = sortArray[ ca ][ 1 ]; - - customAttribute.array[ ca ] = customAttribute.value[ index ]; + customAttribute.array[ ca ] = customAttribute.value[ ca ]; } @@ -18918,9 +19091,7 @@ THREE.WebGLRenderer = function ( parameters ) { for ( ca = 0; ca < cal; ca ++ ) { - index = sortArray[ ca ][ 1 ]; - - value = customAttribute.value[ index ]; + value = customAttribute.value[ ca ]; customAttribute.array[ offset ] = value.x; customAttribute.array[ offset + 1 ] = value.y; @@ -18935,11 +19106,9 @@ THREE.WebGLRenderer = function ( parameters ) { for ( ca = 0; ca < cal; ca ++ ) { - index = sortArray[ ca ][ 1 ]; - - value = customAttribute.value[ index ]; + value = customAttribute.value[ ca ]; - customAttribute.array[ offset ] = value.r; + customAttribute.array[ offset ] = value.r; customAttribute.array[ offset + 1 ] = value.g; customAttribute.array[ offset + 2 ] = value.b; @@ -18951,9 +19120,7 @@ THREE.WebGLRenderer = function ( parameters ) { for ( ca = 0; ca < cal; ca ++ ) { - index = sortArray[ ca ][ 1 ]; - - value = customAttribute.value[ index ]; + value = customAttribute.value[ ca ]; customAttribute.array[ offset ] = value.x; customAttribute.array[ offset + 1 ] = value.y; @@ -18969,9 +19136,7 @@ THREE.WebGLRenderer = function ( parameters ) { for ( ca = 0; ca < cal; ca ++ ) { - index = sortArray[ ca ][ 1 ]; - - value = customAttribute.value[ index ]; + value = customAttribute.value[ ca ]; customAttribute.array[ offset ] = value.x; customAttribute.array[ offset + 1 ] = value.y; @@ -18986,160 +19151,10 @@ THREE.WebGLRenderer = function ( parameters ) { } - } - - } else { - - if ( dirtyVertices ) { - - for ( v = 0; v < vl; v ++ ) { - - vertex = vertices[ v ]; - - offset = v * 3; - - vertexArray[ offset ] = vertex.x; - vertexArray[ offset + 1 ] = vertex.y; - vertexArray[ offset + 2 ] = vertex.z; - - } - - } - - if ( dirtyColors ) { - - for ( c = 0; c < cl; c ++ ) { - - color = colors[ c ]; - - offset = c * 3; - - colorArray[ offset ] = color.r; - colorArray[ offset + 1 ] = color.g; - colorArray[ offset + 2 ] = color.b; - - } - - } - - if ( customAttributes ) { - - for ( i = 0, il = customAttributes.length; i < il; i ++ ) { - - customAttribute = customAttributes[ i ]; - - if ( customAttribute.needsUpdate && - ( customAttribute.boundTo === undefined || - customAttribute.boundTo === 'vertices' ) ) { - - cal = customAttribute.value.length; - - offset = 0; - - if ( customAttribute.size === 1 ) { - - for ( ca = 0; ca < cal; ca ++ ) { - - customAttribute.array[ ca ] = customAttribute.value[ ca ]; - - } - - } else if ( customAttribute.size === 2 ) { - - for ( ca = 0; ca < cal; ca ++ ) { - - value = customAttribute.value[ ca ]; - - customAttribute.array[ offset ] = value.x; - customAttribute.array[ offset + 1 ] = value.y; - - offset += 2; - - } - - } else if ( customAttribute.size === 3 ) { - - if ( customAttribute.type === 'c' ) { - - for ( ca = 0; ca < cal; ca ++ ) { - - value = customAttribute.value[ ca ]; - - customAttribute.array[ offset ] = value.r; - customAttribute.array[ offset + 1 ] = value.g; - customAttribute.array[ offset + 2 ] = value.b; - - offset += 3; - - } - - } else { - - for ( ca = 0; ca < cal; ca ++ ) { - - value = customAttribute.value[ ca ]; - - customAttribute.array[ offset ] = value.x; - customAttribute.array[ offset + 1 ] = value.y; - customAttribute.array[ offset + 2 ] = value.z; - - offset += 3; - - } - - } - - } else if ( customAttribute.size === 4 ) { - - for ( ca = 0; ca < cal; ca ++ ) { - - value = customAttribute.value[ ca ]; - - customAttribute.array[ offset ] = value.x; - customAttribute.array[ offset + 1 ] = value.y; - customAttribute.array[ offset + 2 ] = value.z; - customAttribute.array[ offset + 3 ] = value.w; - - offset += 4; - - } - - } - - } - - } - - } - - } - - if ( dirtyVertices || object.sortParticles ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglVertexBuffer ); - _gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint ); - - } - - if ( dirtyColors || object.sortParticles ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglColorBuffer ); - _gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint ); - - } - - if ( customAttributes ) { - - for ( i = 0, il = customAttributes.length; i < il; i ++ ) { - - customAttribute = customAttributes[ i ]; - - if ( customAttribute.needsUpdate || object.sortParticles ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, customAttribute.buffer ); - _gl.bufferData( _gl.ARRAY_BUFFER, customAttribute.array, hint ); + _gl.bindBuffer( _gl.ARRAY_BUFFER, customAttribute.buffer ); + _gl.bufferData( _gl.ARRAY_BUFFER, customAttribute.array, hint ); - } + customAttribute.needsUpdate = false; } @@ -19170,7 +19185,7 @@ THREE.WebGLRenderer = function ( parameters ) { customAttributes = geometry.__webglCustomAttributesList, i, il, - a, ca, cal, value, + ca, cal, value, customAttribute; if ( dirtyVertices ) { @@ -19230,9 +19245,7 @@ THREE.WebGLRenderer = function ( parameters ) { customAttribute = customAttributes[ i ]; - if ( customAttribute.needsUpdate && - ( customAttribute.boundTo === undefined || - customAttribute.boundTo === 'vertices' ) ) { + if ( customAttribute.needsUpdate && ( customAttribute.boundTo === undefined || customAttribute.boundTo === 'vertices' ) ) { offset = 0; @@ -19311,6 +19324,8 @@ THREE.WebGLRenderer = function ( parameters ) { _gl.bindBuffer( _gl.ARRAY_BUFFER, customAttribute.buffer ); _gl.bufferData( _gl.ARRAY_BUFFER, customAttribute.array, hint ); + customAttribute.needsUpdate = false; + } } @@ -19327,23 +19342,20 @@ THREE.WebGLRenderer = function ( parameters ) { } - var needsSmoothNormals = materialNeedsSmoothNormals( material ); + var needsFaceNormals = materialNeedsFaceNormals( material ); var f, fl, fi, face, - vertexNormals, faceNormal, normal, + vertexNormals, faceNormal, vertexColors, faceColor, vertexTangents, - uv, uv2, v1, v2, v3, v4, t1, t2, t3, t4, n1, n2, n3, n4, + uv, uv2, v1, v2, v3, t1, t2, t3, n1, n2, n3, c1, c2, c3, - sw1, sw2, sw3, sw4, - si1, si2, si3, si4, - sa1, sa2, sa3, sa4, - sb1, sb2, sb3, sb4, - m, ml, i, il, + sw1, sw2, sw3, + si1, si2, si3, + i, il, vn, uvi, uv2i, vk, vkl, vka, nka, chf, faceVertexNormals, - a, vertexIndex = 0, @@ -19358,7 +19370,6 @@ THREE.WebGLRenderer = function ( parameters ) { offset_skin = 0, offset_morphTarget = 0, offset_custom = 0, - offset_customSrc = 0, value, @@ -19398,8 +19409,6 @@ THREE.WebGLRenderer = function ( parameters ) { obj_uvs = geometry.faceVertexUvs[ 0 ], obj_uvs2 = geometry.faceVertexUvs[ 1 ], - obj_colors = geometry.colors, - obj_skinIndices = geometry.skinIndices, obj_skinWeights = geometry.skinWeights, @@ -19472,7 +19481,13 @@ THREE.WebGLRenderer = function ( parameters ) { if ( material.morphNormals ) { - if ( needsSmoothNormals ) { + if ( needsFaceNormals ) { + + n1 = morphNormals[ vk ].faceNormals[ chf ]; + n2 = n1; + n3 = n1; + + } else { faceVertexNormals = morphNormals[ vk ].vertexNormals[ chf ]; @@ -19480,12 +19495,6 @@ THREE.WebGLRenderer = function ( parameters ) { n2 = faceVertexNormals.b; n3 = faceVertexNormals.c; - } else { - - n1 = morphNormals[ vk ].faceNormals[ chf ]; - n2 = n1; - n3 = n1; - } nka = morphNormalsArrays[ vk ]; @@ -19681,7 +19690,7 @@ THREE.WebGLRenderer = function ( parameters ) { vertexNormals = face.vertexNormals; faceNormal = face.normal; - if ( vertexNormals.length === 3 && needsSmoothNormals ) { + if ( vertexNormals.length === 3 && needsFaceNormals === false ) { for ( i = 0; i < 3; i ++ ) { @@ -19822,7 +19831,6 @@ THREE.WebGLRenderer = function ( parameters ) { if ( ! customAttribute.__original.needsUpdate ) continue; offset_custom = 0; - offset_customSrc = 0; if ( customAttribute.size === 1 ) { @@ -20118,43 +20126,11 @@ THREE.WebGLRenderer = function ( parameters ) { }; - function setDirectBuffers( geometry ) { - - var attributes = geometry.attributes; - var attributesKeys = geometry.attributesKeys; - - for ( var i = 0, l = attributesKeys.length; i < l; i ++ ) { - - var key = attributesKeys[ i ]; - var attribute = attributes[ key ]; - - if ( attribute.buffer === undefined ) { - - attribute.buffer = _gl.createBuffer(); - attribute.needsUpdate = true; - - } - - if ( attribute.needsUpdate === true ) { - - var bufferType = ( key === 'index' ) ? _gl.ELEMENT_ARRAY_BUFFER : _gl.ARRAY_BUFFER; - - _gl.bindBuffer( bufferType, attribute.buffer ); - _gl.bufferData( bufferType, attribute.array, _gl.STATIC_DRAW ); - - attribute.needsUpdate = false; - - } - - } - - } - // Buffer rendering this.renderBufferImmediate = function ( object, program, material ) { - initAttributes(); + state.initAttributes(); if ( object.hasPositions && ! object.__webglVertexBuffer ) object.__webglVertexBuffer = _gl.createBuffer(); if ( object.hasNormals && ! object.__webglNormalBuffer ) object.__webglNormalBuffer = _gl.createBuffer(); @@ -20165,7 +20141,9 @@ THREE.WebGLRenderer = function ( parameters ) { _gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglVertexBuffer ); _gl.bufferData( _gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW ); - enableAttribute( program.attributes.position ); + + state.enableAttribute( program.attributes.position ); + _gl.vertexAttribPointer( program.attributes.position, 3, _gl.FLOAT, false, 0, 0 ); } @@ -20174,7 +20152,8 @@ THREE.WebGLRenderer = function ( parameters ) { _gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglNormalBuffer ); - if ( material.shading === THREE.FlatShading ) { + if ( material instanceof THREE.MeshPhongMaterial === false && + material.shading === THREE.FlatShading ) { var nx, ny, nz, nax, nbx, ncx, nay, nby, ncy, naz, nbz, ncz, @@ -20218,7 +20197,9 @@ THREE.WebGLRenderer = function ( parameters ) { } _gl.bufferData( _gl.ARRAY_BUFFER, object.normalArray, _gl.DYNAMIC_DRAW ); - enableAttribute( program.attributes.normal ); + + state.enableAttribute( program.attributes.normal ); + _gl.vertexAttribPointer( program.attributes.normal, 3, _gl.FLOAT, false, 0, 0 ); } @@ -20227,7 +20208,9 @@ THREE.WebGLRenderer = function ( parameters ) { _gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglUvBuffer ); _gl.bufferData( _gl.ARRAY_BUFFER, object.uvArray, _gl.DYNAMIC_DRAW ); - enableAttribute( program.attributes.uv ); + + state.enableAttribute( program.attributes.uv ); + _gl.vertexAttribPointer( program.attributes.uv, 2, _gl.FLOAT, false, 0, 0 ); } @@ -20236,12 +20219,14 @@ THREE.WebGLRenderer = function ( parameters ) { _gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglColorBuffer ); _gl.bufferData( _gl.ARRAY_BUFFER, object.colorArray, _gl.DYNAMIC_DRAW ); - enableAttribute( program.attributes.color ); + + state.enableAttribute( program.attributes.color ); + _gl.vertexAttribPointer( program.attributes.color, 3, _gl.FLOAT, false, 0, 0 ); } - disableUnusedAttributes(); + state.disableUnusedAttributes(); _gl.drawArrays( _gl.TRIANGLES, 0, object.count ); @@ -20271,7 +20256,7 @@ THREE.WebGLRenderer = function ( parameters ) { _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryAttribute.buffer ); - enableAttribute( programAttribute ); + state.enableAttribute( programAttribute ); _gl.vertexAttribPointer( programAttribute, size, _gl.FLOAT, false, 0, startIndex * size * 4 ); // 4 bytes per Float32 @@ -20293,7 +20278,7 @@ THREE.WebGLRenderer = function ( parameters ) { } - disableUnusedAttributes(); + state.disableUnusedAttributes(); } @@ -20301,22 +20286,24 @@ THREE.WebGLRenderer = function ( parameters ) { if ( material.visible === false ) return; + updateObject( object ); + var program = setProgram( camera, lights, fog, material, object ); var updateBuffers = false, wireframeBit = material.wireframe ? 1 : 0, - geometryHash = ( geometry.id * 0xffffff ) + ( program.id * 2 ) + wireframeBit; + geometryProgram = 'direct_' + geometry.id + '_' + program.id + '_' + wireframeBit; - if ( geometryHash !== _currentGeometryGroupHash ) { + if ( geometryProgram !== _currentGeometryProgram ) { - _currentGeometryGroupHash = geometryHash; + _currentGeometryProgram = geometryProgram; updateBuffers = true; } if ( updateBuffers ) { - initAttributes(); + state.initAttributes(); } @@ -20408,11 +20395,11 @@ THREE.WebGLRenderer = function ( parameters ) { // render non-indexed triangles - _gl.drawArrays( mode, 0, position.array.length / 3 ); + _gl.drawArrays( mode, 0, position.array.length / position.itemSize ); _this.info.render.calls ++; - _this.info.render.vertices += position.array.length / 3; - _this.info.render.faces += position.array.length / 9; + _this.info.render.vertices += position.array.length / position.itemSize; + _this.info.render.faces += position.array.length / ( 3 * position.itemSize ); } @@ -20420,26 +20407,114 @@ THREE.WebGLRenderer = function ( parameters ) { // render particles - if ( updateBuffers ) { + var mode = _gl.POINTS; - setupVertexAttributes( material, program, geometry, 0 ); + var index = geometry.attributes.index; - } + if ( index ) { - var position = geometry.attributes.position; + // indexed points - // render particles + var type, size; - _gl.drawArrays( _gl.POINTS, 0, position.array.length / 3 ); + if ( index.array instanceof Uint32Array && extensions.get( 'OES_element_index_uint' ) ) { - _this.info.render.calls ++; - _this.info.render.points += position.array.length / 3; + type = _gl.UNSIGNED_INT; + size = 4; + + } else { + + type = _gl.UNSIGNED_SHORT; + size = 2; + + } + + var offsets = geometry.offsets; + + if ( offsets.length === 0 ) { + + if ( updateBuffers ) { + + setupVertexAttributes( material, program, geometry, 0 ); + _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, index.buffer ); + + } + + _gl.drawElements( mode, index.array.length, type, 0); + + _this.info.render.calls ++; + _this.info.render.points += index.array.length; + + } else { + + // if there is more than 1 chunk + // must set attribute pointers to use new offsets for each chunk + // even if geometry and materials didn't change + + if ( offsets.length > 1 ) updateBuffers = true; + + for ( var i = 0, il = offsets.length; i < il; i ++ ) { + + var startIndex = offsets[ i ].index; + + if ( updateBuffers ) { + + setupVertexAttributes( material, program, geometry, startIndex ); + _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, index.buffer ); + + } + + // render indexed points + + _gl.drawElements( mode, offsets[ i ].count, type, offsets[ i ].start * size ); + + _this.info.render.calls ++; + _this.info.render.points += offsets[ i ].count; + + } + + } + + } else { + + // non-indexed points + + if ( updateBuffers ) { + + setupVertexAttributes( material, program, geometry, 0 ); + + } + + var position = geometry.attributes.position; + var offsets = geometry.offsets; + + if ( offsets.length === 0 ) { + + _gl.drawArrays( mode, 0, position.array.length / 3 ); + + _this.info.render.calls ++; + _this.info.render.points += position.array.length / 3; + + } else { + + for ( var i = 0, il = offsets.length; i < il; i ++ ) { + + _gl.drawArrays( mode, offsets[ i ].index, offsets[ i ].count ); + + _this.info.render.calls ++; + _this.info.render.points += offsets[ i ].count; + + } + + } + + } } else if ( object instanceof THREE.Line ) { var mode = ( object.mode === THREE.LineStrip ) ? _gl.LINE_STRIP : _gl.LINES; - setLineWidth( material.linewidth ); + state.setLineWidth( material.linewidth * pixelRatio ); var index = geometry.attributes.index; @@ -20518,11 +20593,27 @@ THREE.WebGLRenderer = function ( parameters ) { } var position = geometry.attributes.position; + var offsets = geometry.offsets; + + if ( offsets.length === 0 ) { - _gl.drawArrays( mode, 0, position.array.length / 3 ); + _gl.drawArrays( mode, 0, position.array.length / 3 ); - _this.info.render.calls ++; - _this.info.render.points += position.array.length / 3; + _this.info.render.calls ++; + _this.info.render.vertices += position.array.length / 3; + + } else { + + for ( var i = 0, il = offsets.length; i < il; i ++ ) { + + _gl.drawArrays( mode, offsets[ i ].index, offsets[ i ].count ); + + _this.info.render.calls ++; + _this.info.render.vertices += offsets[ i ].count; + + } + + } } @@ -20534,24 +20625,26 @@ THREE.WebGLRenderer = function ( parameters ) { if ( material.visible === false ) return; + updateObject( object ); + var program = setProgram( camera, lights, fog, material, object ); var attributes = program.attributes; var updateBuffers = false, wireframeBit = material.wireframe ? 1 : 0, - geometryGroupHash = ( geometryGroup.id * 0xffffff ) + ( program.id * 2 ) + wireframeBit; + geometryProgram = geometryGroup.id + '_' + program.id + '_' + wireframeBit; - if ( geometryGroupHash !== _currentGeometryGroupHash ) { + if ( geometryProgram !== _currentGeometryProgram ) { - _currentGeometryGroupHash = geometryGroupHash; + _currentGeometryProgram = geometryProgram; updateBuffers = true; } if ( updateBuffers ) { - initAttributes(); + state.initAttributes(); } @@ -20562,7 +20655,9 @@ THREE.WebGLRenderer = function ( parameters ) { if ( updateBuffers ) { _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglVertexBuffer ); - enableAttribute( attributes.position ); + + state.enableAttribute( attributes.position ); + _gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 ); } @@ -20593,7 +20688,9 @@ THREE.WebGLRenderer = function ( parameters ) { if ( attributes[ attribute.buffer.belongsToAttribute ] >= 0 ) { _gl.bindBuffer( _gl.ARRAY_BUFFER, attribute.buffer ); - enableAttribute( attributes[ attribute.buffer.belongsToAttribute ] ); + + state.enableAttribute( attributes[ attribute.buffer.belongsToAttribute ] ); + _gl.vertexAttribPointer( attributes[ attribute.buffer.belongsToAttribute ], attribute.size, _gl.FLOAT, false, 0, 0 ); } @@ -20610,7 +20707,9 @@ THREE.WebGLRenderer = function ( parameters ) { if ( object.geometry.colors.length > 0 || object.geometry.faces.length > 0 ) { _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglColorBuffer ); - enableAttribute( attributes.color ); + + state.enableAttribute( attributes.color ); + _gl.vertexAttribPointer( attributes.color, 3, _gl.FLOAT, false, 0, 0 ); } else if ( material.defaultAttributeValues !== undefined ) { @@ -20627,7 +20726,9 @@ THREE.WebGLRenderer = function ( parameters ) { if ( attributes.normal >= 0 ) { _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglNormalBuffer ); - enableAttribute( attributes.normal ); + + state.enableAttribute( attributes.normal ); + _gl.vertexAttribPointer( attributes.normal, 3, _gl.FLOAT, false, 0, 0 ); } @@ -20637,7 +20738,9 @@ THREE.WebGLRenderer = function ( parameters ) { if ( attributes.tangent >= 0 ) { _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglTangentBuffer ); - enableAttribute( attributes.tangent ); + + state.enableAttribute( attributes.tangent ); + _gl.vertexAttribPointer( attributes.tangent, 4, _gl.FLOAT, false, 0, 0 ); } @@ -20649,7 +20752,9 @@ THREE.WebGLRenderer = function ( parameters ) { if ( object.geometry.faceVertexUvs[ 0 ] ) { _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUVBuffer ); - enableAttribute( attributes.uv ); + + state.enableAttribute( attributes.uv ); + _gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 0, 0 ); } else if ( material.defaultAttributeValues !== undefined ) { @@ -20666,7 +20771,9 @@ THREE.WebGLRenderer = function ( parameters ) { if ( object.geometry.faceVertexUvs[ 1 ] ) { _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUV2Buffer ); - enableAttribute( attributes.uv2 ); + + state.enableAttribute( attributes.uv2 ); + _gl.vertexAttribPointer( attributes.uv2, 2, _gl.FLOAT, false, 0, 0 ); } else if ( material.defaultAttributeValues !== undefined ) { @@ -20682,11 +20789,15 @@ THREE.WebGLRenderer = function ( parameters ) { attributes.skinIndex >= 0 && attributes.skinWeight >= 0 ) { _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinIndicesBuffer ); - enableAttribute( attributes.skinIndex ); + + state.enableAttribute( attributes.skinIndex ); + _gl.vertexAttribPointer( attributes.skinIndex, 4, _gl.FLOAT, false, 0, 0 ); _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinWeightsBuffer ); - enableAttribute( attributes.skinWeight ); + + state.enableAttribute( attributes.skinWeight ); + _gl.vertexAttribPointer( attributes.skinWeight, 4, _gl.FLOAT, false, 0, 0 ); } @@ -20696,14 +20807,16 @@ THREE.WebGLRenderer = function ( parameters ) { if ( attributes.lineDistance >= 0 ) { _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglLineDistanceBuffer ); - enableAttribute( attributes.lineDistance ); + + state.enableAttribute( attributes.lineDistance ); + _gl.vertexAttribPointer( attributes.lineDistance, 1, _gl.FLOAT, false, 0, 0 ); } } - disableUnusedAttributes(); + state.disableUnusedAttributes(); // render mesh @@ -20715,7 +20828,8 @@ THREE.WebGLRenderer = function ( parameters ) { if ( material.wireframe ) { - setLineWidth( material.wireframeLinewidth ); + state.setLineWidth( material.wireframeLinewidth * pixelRatio ); + if ( updateBuffers ) _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglLineBuffer ); _gl.drawElements( _gl.LINES, geometryGroup.__webglLineCount, type, 0 ); @@ -20738,7 +20852,7 @@ THREE.WebGLRenderer = function ( parameters ) { var mode = ( object.mode === THREE.LineStrip ) ? _gl.LINE_STRIP : _gl.LINES; - setLineWidth( material.linewidth ); + state.setLineWidth( material.linewidth * pixelRatio ); _gl.drawArrays( mode, 0, geometryGroup.__webglLineCount ); @@ -20757,44 +20871,6 @@ THREE.WebGLRenderer = function ( parameters ) { }; - function initAttributes() { - - for ( var i = 0, l = _newAttributes.length; i < l; i ++ ) { - - _newAttributes[ i ] = 0; - - } - - } - - function enableAttribute( attribute ) { - - _newAttributes[ attribute ] = 1; - - if ( _enabledAttributes[ attribute ] === 0 ) { - - _gl.enableVertexAttribArray( attribute ); - _enabledAttributes[ attribute ] = 1; - - } - - } - - function disableUnusedAttributes() { - - for ( var i = 0, l = _enabledAttributes.length; i < l; i ++ ) { - - if ( _enabledAttributes[ i ] !== _newAttributes[ i ] ) { - - _gl.disableVertexAttribArray( i ); - _enabledAttributes[ i ] = 0; - - } - - } - - } - function setupMorphTargets ( material, geometryGroup, object ) { // set base @@ -20804,13 +20880,17 @@ THREE.WebGLRenderer = function ( parameters ) { if ( object.morphTargetBase !== - 1 && attributes.position >= 0 ) { _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ object.morphTargetBase ] ); - enableAttribute( attributes.position ); + + state.enableAttribute( attributes.position ); + _gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 ); } else if ( attributes.position >= 0 ) { _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglVertexBuffer ); - enableAttribute( attributes.position ); + + state.enableAttribute( attributes.position ); + _gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 ); } @@ -20823,46 +20903,60 @@ THREE.WebGLRenderer = function ( parameters ) { var order = object.morphTargetForcedOrder; var influences = object.morphTargetInfluences; + var attribute; + while ( m < material.numSupportedMorphTargets && m < order.length ) { - if ( attributes[ 'morphTarget' + m ] >= 0 ) { + attribute = attributes[ 'morphTarget' + m ]; + + if ( attribute >= 0 ) { _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ order[ m ] ] ); - enableAttribute( attributes[ 'morphTarget' + m ] ); - _gl.vertexAttribPointer( attributes[ 'morphTarget' + m ], 3, _gl.FLOAT, false, 0, 0 ); + + state.enableAttribute( attribute ); + + _gl.vertexAttribPointer( attribute, 3, _gl.FLOAT, false, 0, 0 ); } - if ( attributes[ 'morphNormal' + m ] >= 0 && material.morphNormals ) { + attribute = attributes[ 'morphNormal' + m ]; + + if ( attribute >= 0 && material.morphNormals ) { _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphNormalsBuffers[ order[ m ] ] ); - enableAttribute( attributes[ 'morphNormal' + m ] ); - _gl.vertexAttribPointer( attributes[ 'morphNormal' + m ], 3, _gl.FLOAT, false, 0, 0 ); + + state.enableAttribute( attribute ); + + _gl.vertexAttribPointer( attribute, 3, _gl.FLOAT, false, 0, 0 ); } object.__webglMorphTargetInfluences[ m ] = influences[ order[ m ] ]; m ++; + } } else { // find the most influencing - var influence, activeInfluenceIndices = []; + var activeInfluenceIndices = []; var influences = object.morphTargetInfluences; - var i, il = influences.length; + var morphTargets = object.geometry.morphTargets; + + if ( influences.length > morphTargets.length ) { - for ( i = 0; i < il; i ++ ) { + console.warn( 'THREE.WebGLRenderer: Influences array is bigger than morphTargets array.' ); + influences.length = morphTargets.length; - influence = influences[ i ]; + } - if ( influence > 0 ) { + for ( var i = 0, il = influences.length; i < il; i ++ ) { - activeInfluenceIndices.push( [ influence, i ] ); + var influence = influences[ i ]; - } + activeInfluenceIndices.push( [ influence, i ] ); } @@ -20879,30 +20973,37 @@ THREE.WebGLRenderer = function ( parameters ) { activeInfluenceIndices.push( [ 0, 0 ] ); - }; + } - var influenceIndex, m = 0; + var attribute; - while ( m < material.numSupportedMorphTargets ) { + for ( var m = 0, ml = material.numSupportedMorphTargets; m < ml; m ++ ) { if ( activeInfluenceIndices[ m ] ) { - influenceIndex = activeInfluenceIndices[ m ][ 1 ]; + var influenceIndex = activeInfluenceIndices[ m ][ 1 ]; + + attribute = attributes[ 'morphTarget' + m ]; - if ( attributes[ 'morphTarget' + m ] >= 0 ) { + if ( attribute >= 0 ) { _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ influenceIndex ] ); - enableAttribute( attributes[ 'morphTarget' + m ] ); - _gl.vertexAttribPointer( attributes[ 'morphTarget' + m ], 3, _gl.FLOAT, false, 0, 0 ); + + state.enableAttribute( attribute ); + + _gl.vertexAttribPointer( attribute, 3, _gl.FLOAT, false, 0, 0 ); } - if ( attributes[ 'morphNormal' + m ] >= 0 && material.morphNormals ) { + attribute = attributes[ 'morphNormal' + m ]; + + if ( attribute >= 0 && material.morphNormals ) { _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphNormalsBuffers[ influenceIndex ] ); - enableAttribute( attributes[ 'morphNormal' + m ] ); - _gl.vertexAttribPointer( attributes[ 'morphNormal' + m ], 3, _gl.FLOAT, false, 0, 0 ); + state.enableAttribute( attribute ); + + _gl.vertexAttribPointer( attribute, 3, _gl.FLOAT, false, 0, 0 ); } @@ -20924,8 +21025,6 @@ THREE.WebGLRenderer = function ( parameters ) { } - m ++; - } } @@ -20944,13 +21043,17 @@ THREE.WebGLRenderer = function ( parameters ) { function painterSortStable ( a, b ) { - if ( a.material.id !== b.material.id ) { + if ( a.object.renderOrder !== b.object.renderOrder ) { - return b.material.id - a.material.id; + return a.object.renderOrder - b.object.renderOrder; + + } else if ( a.material.id !== b.material.id ) { + + return a.material.id - b.material.id; } else if ( a.z !== b.z ) { - return b.z - a.z; + return a.z - b.z; } else { @@ -20962,9 +21065,13 @@ THREE.WebGLRenderer = function ( parameters ) { function reversePainterSortStable ( a, b ) { - if ( a.z !== b.z ) { + if ( a.object.renderOrder !== b.object.renderOrder ) { - return a.z - b.z; + return a.object.renderOrder - b.object.renderOrder; + + } if ( a.z !== b.z ) { + + return b.z - a.z; } else { @@ -20986,7 +21093,7 @@ THREE.WebGLRenderer = function ( parameters ) { if ( camera instanceof THREE.Camera === false ) { - console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' ); + THREE.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' ); return; } @@ -20995,7 +21102,7 @@ THREE.WebGLRenderer = function ( parameters ) { // reset caching for this frame - _currentGeometryGroupHash = - 1; + _currentGeometryProgram = ''; _currentMaterialId = - 1; _currentCamera = null; _lightsNeedUpdate = true; @@ -21032,7 +21139,7 @@ THREE.WebGLRenderer = function ( parameters ) { sprites.length = 0; lensFlares.length = 0; - projectObject( scene, scene ); + projectObject( scene ); if ( _this.sortObjects === true ) { @@ -21079,32 +21186,27 @@ THREE.WebGLRenderer = function ( parameters ) { if ( scene.overrideMaterial ) { - var material = scene.overrideMaterial; + var overrideMaterial = scene.overrideMaterial; - this.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst ); - this.setDepthTest( material.depthTest ); - this.setDepthWrite( material.depthWrite ); - setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits ); + setMaterial( overrideMaterial ); - renderObjects( opaqueObjects, camera, lights, fog, true, material ); - renderObjects( transparentObjects, camera, lights, fog, true, material ); - renderObjectsImmediate( _webglObjectsImmediate, '', camera, lights, fog, false, material ); + renderObjects( opaqueObjects, camera, lights, fog, overrideMaterial ); + renderObjects( transparentObjects, camera, lights, fog, overrideMaterial ); + renderObjectsImmediate( _webglObjectsImmediate, '', camera, lights, fog, overrideMaterial ); } else { - var material = null; - // opaque pass (front-to-back order) - this.setBlending( THREE.NoBlending ); + state.setBlending( THREE.NoBlending ); - renderObjects( opaqueObjects, camera, lights, fog, false, material ); - renderObjectsImmediate( _webglObjectsImmediate, 'opaque', camera, lights, fog, false, material ); + renderObjects( opaqueObjects, camera, lights, fog, null ); + renderObjectsImmediate( _webglObjectsImmediate, 'opaque', camera, lights, fog, null ); // transparent pass (back-to-front order) - renderObjects( transparentObjects, camera, lights, fog, true, material ); - renderObjectsImmediate( _webglObjectsImmediate, 'transparent', camera, lights, fog, true, material ); + renderObjects( transparentObjects, camera, lights, fog, null ); + renderObjectsImmediate( _webglObjectsImmediate, 'transparent', camera, lights, fog, null ); } @@ -21123,14 +21225,15 @@ THREE.WebGLRenderer = function ( parameters ) { // Ensure depth buffer writing is enabled so it can be cleared on next render - this.setDepthTest( true ); - this.setDepthWrite( true ); + state.setDepthTest( true ); + state.setDepthWrite( true ); + state.setColorWrite( true ); // _gl.finish(); }; - function projectObject( scene, object ) { + function projectObject( object ) { if ( object.visible === false ) return; @@ -21140,7 +21243,7 @@ THREE.WebGLRenderer = function ( parameters ) { } else { - initObject( object, scene ); + initObject( object ); if ( object instanceof THREE.Light ) { @@ -21160,11 +21263,9 @@ THREE.WebGLRenderer = function ( parameters ) { if ( webglObjects && ( object.frustumCulled === false || _frustum.intersectsObject( object ) === true ) ) { - updateObject( object, scene ); - for ( var i = 0, l = webglObjects.length; i < l; i ++ ) { - var webglObject = webglObjects[i]; + var webglObject = webglObjects[ i ]; unrollBufferMaterial( webglObject ); @@ -21172,18 +21273,10 @@ THREE.WebGLRenderer = function ( parameters ) { if ( _this.sortObjects === true ) { - if ( object.renderDepth !== null ) { - - webglObject.z = object.renderDepth; - - } else { - - _vector3.setFromMatrixPosition( object.matrixWorld ); - _vector3.applyProjection( _projScreenMatrix ); - - webglObject.z = _vector3.z; + _vector3.setFromMatrixPosition( object.matrixWorld ); + _vector3.applyProjection( _projScreenMatrix ); - } + webglObject.z = _vector3.z; } @@ -21197,17 +21290,17 @@ THREE.WebGLRenderer = function ( parameters ) { for ( var i = 0, l = object.children.length; i < l; i ++ ) { - projectObject( scene, object.children[ i ] ); + projectObject( object.children[ i ] ); } } - function renderObjects( renderList, camera, lights, fog, useBlending, overrideMaterial ) { + function renderObjects( renderList, camera, lights, fog, overrideMaterial ) { var material; - for ( var i = renderList.length - 1; i !== - 1; i -- ) { + for ( var i = 0, l = renderList.length; i < l; i ++ ) { var webglObject = renderList[ i ]; @@ -21226,11 +21319,7 @@ THREE.WebGLRenderer = function ( parameters ) { if ( ! material ) continue; - if ( useBlending ) _this.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst ); - - _this.setDepthTest( material.depthTest ); - _this.setDepthWrite( material.depthWrite ); - setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits ); + setMaterial( material ); } @@ -21250,11 +21339,11 @@ THREE.WebGLRenderer = function ( parameters ) { } - function renderObjectsImmediate ( renderList, materialType, camera, lights, fog, useBlending, overrideMaterial ) { + function renderObjectsImmediate ( renderList, materialType, camera, lights, fog, overrideMaterial ) { var material; - for ( var i = 0, il = renderList.length; i < il; i ++ ) { + for ( var i = 0, l = renderList.length; i < l; i ++ ) { var webglObject = renderList[ i ]; var object = webglObject.object; @@ -21271,11 +21360,7 @@ THREE.WebGLRenderer = function ( parameters ) { if ( ! material ) continue; - if ( useBlending ) _this.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst ); - - _this.setDepthTest( material.depthTest ); - _this.setDepthWrite( material.depthWrite ); - setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits ); + setMaterial( material ); } @@ -21291,7 +21376,7 @@ THREE.WebGLRenderer = function ( parameters ) { var program = setProgram( camera, lights, fog, material, object ); - _currentGeometryGroupHash = - 1; + _currentGeometryProgram = ''; _this.setMaterialFaces( material ); @@ -21370,7 +21455,7 @@ THREE.WebGLRenderer = function ( parameters ) { } - function initObject( object, scene ) { + function initObject( object ) { if ( object.__webglInit === undefined ) { @@ -21395,11 +21480,11 @@ THREE.WebGLRenderer = function ( parameters ) { if ( geometry instanceof THREE.BufferGeometry ) { - // + _this.info.memory.geometries ++; } else if ( object instanceof THREE.Mesh ) { - initGeometryGroups( scene, object, geometry ); + initGeometryGroups( object, geometry ); } else if ( object instanceof THREE.Line ) { @@ -21507,7 +21592,7 @@ THREE.WebGLRenderer = function ( parameters ) { numMorphTargets: numMorphTargets, numMorphNormals: numMorphNormals }; - + groups[ groupHash ] = group; groupsList.push( group ); @@ -21528,7 +21613,7 @@ THREE.WebGLRenderer = function ( parameters ) { numMorphTargets: numMorphTargets, numMorphNormals: numMorphNormals }; - + groups[ groupHash ] = group; groupsList.push( group ); @@ -21545,7 +21630,7 @@ THREE.WebGLRenderer = function ( parameters ) { } - function initGeometryGroups( scene, object, geometry ) { + function initGeometryGroups( object, geometry ) { var material = object.material, addBuffers = false; @@ -21634,13 +21719,55 @@ THREE.WebGLRenderer = function ( parameters ) { // Objects updates - function updateObject( object, scene ) { + function updateObject( object ) { - var geometry = object.geometry, customAttributesDirty, material; + var geometry = object.geometry; if ( geometry instanceof THREE.BufferGeometry ) { - setDirectBuffers( geometry ); + var attributes = geometry.attributes; + var attributesKeys = geometry.attributesKeys; + + for ( var i = 0, l = attributesKeys.length; i < l; i ++ ) { + + var key = attributesKeys[ i ]; + var attribute = attributes[ key ]; + var bufferType = ( key === 'index' ) ? _gl.ELEMENT_ARRAY_BUFFER : _gl.ARRAY_BUFFER; + + if ( attribute.buffer === undefined ) { + + attribute.buffer = _gl.createBuffer(); + _gl.bindBuffer( bufferType, attribute.buffer ); + _gl.bufferData( bufferType, attribute.array, ( attribute instanceof THREE.DynamicBufferAttribute ) ? _gl.DYNAMIC_DRAW : _gl.STATIC_DRAW ); + + attribute.needsUpdate = false; + + } else if ( attribute.needsUpdate === true ) { + + _gl.bindBuffer( bufferType, attribute.buffer ); + + if ( attribute.updateRange === undefined || attribute.updateRange.count === -1 ) { // Not using update ranges + + _gl.bufferSubData( bufferType, 0, attribute.array ); + + } else if ( attribute.updateRange.count === 0 ) { + + console.error( 'THREE.WebGLRenderer.updateObject: using updateRange for THREE.DynamicBufferAttribute and marked as needsUpdate but count is 0, ensure you are using set methods or updating manually.' ); + + } else { + + _gl.bufferSubData( bufferType, attribute.updateRange.offset * attribute.array.BYTES_PER_ELEMENT, + attribute.array.subarray( attribute.updateRange.offset, attribute.updateRange.offset + attribute.updateRange.count ) ); + + attribute.updateRange.count = 0; // reset range + + } + + attribute.needsUpdate = false; + + } + + } } else if ( object instanceof THREE.Mesh ) { @@ -21648,7 +21775,7 @@ THREE.WebGLRenderer = function ( parameters ) { if ( geometry.groupsNeedUpdate === true ) { - initGeometryGroups( scene, object, geometry ); + initGeometryGroups( object, geometry ); } @@ -21657,16 +21784,9 @@ THREE.WebGLRenderer = function ( parameters ) { for ( var i = 0, il = geometryGroupsList.length; i < il; i ++ ) { var geometryGroup = geometryGroupsList[ i ]; + var material = getBufferMaterial( object, geometryGroup ); - material = getBufferMaterial( object, geometryGroup ); - - if ( geometry.groupsNeedUpdate === true ) { - - initMeshBuffers( geometryGroup, object ); - - } - - customAttributesDirty = material.attributes && areCustomAttributesDirty( material ); + var customAttributesDirty = material.attributes && areCustomAttributesDirty( material ); if ( geometry.verticesNeedUpdate || geometry.morphTargetsNeedUpdate || geometry.elementsNeedUpdate || geometry.uvsNeedUpdate || geometry.normalsNeedUpdate || @@ -21690,9 +21810,8 @@ THREE.WebGLRenderer = function ( parameters ) { } else if ( object instanceof THREE.Line ) { - material = getBufferMaterial( object, geometry ); - - customAttributesDirty = material.attributes && areCustomAttributesDirty( material ); + var material = getBufferMaterial( object, geometry ); + var customAttributesDirty = material.attributes && areCustomAttributesDirty( material ); if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate || geometry.lineDistancesNeedUpdate || customAttributesDirty ) { @@ -21706,14 +21825,12 @@ THREE.WebGLRenderer = function ( parameters ) { material.attributes && clearCustomAttributes( material ); - } else if ( object instanceof THREE.PointCloud ) { - material = getBufferMaterial( object, geometry ); - - customAttributesDirty = material.attributes && areCustomAttributesDirty( material ); + var material = getBufferMaterial( object, geometry ); + var customAttributesDirty = material.attributes && areCustomAttributesDirty( material ); - if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate || object.sortParticles || customAttributesDirty ) { + if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate || customAttributesDirty ) { setParticleBuffers( geometry, _gl.DYNAMIC_DRAW, object ); @@ -21792,45 +21909,22 @@ THREE.WebGLRenderer = function ( parameters ) { // Materials + var shaderIDs = { + MeshDepthMaterial: 'depth', + MeshNormalMaterial: 'normal', + MeshBasicMaterial: 'basic', + MeshLambertMaterial: 'lambert', + MeshPhongMaterial: 'phong', + LineBasicMaterial: 'basic', + LineDashedMaterial: 'dashed', + PointCloudMaterial: 'particle_basic' + }; + function initMaterial( material, lights, fog, object ) { material.addEventListener( 'dispose', onMaterialDispose ); - var shaderID; - - if ( material instanceof THREE.MeshDepthMaterial ) { - - shaderID = 'depth'; - - } else if ( material instanceof THREE.MeshNormalMaterial ) { - - shaderID = 'normal'; - - } else if ( material instanceof THREE.MeshBasicMaterial ) { - - shaderID = 'basic'; - - } else if ( material instanceof THREE.MeshLambertMaterial ) { - - shaderID = 'lambert'; - - } else if ( material instanceof THREE.MeshPhongMaterial ) { - - shaderID = 'phong'; - - } else if ( material instanceof THREE.LineBasicMaterial ) { - - shaderID = 'basic'; - - } else if ( material instanceof THREE.LineDashedMaterial ) { - - shaderID = 'dashed'; - - } else if ( material instanceof THREE.PointCloudMaterial ) { - - shaderID = 'particle_basic'; - - } + var shaderID = shaderIDs[ material.type ]; if ( shaderID ) { @@ -21866,18 +21960,23 @@ THREE.WebGLRenderer = function ( parameters ) { map: !! material.map, envMap: !! material.envMap, + envMapMode: material.envMap && material.envMap.mapping, lightMap: !! material.lightMap, bumpMap: !! material.bumpMap, normalMap: !! material.normalMap, specularMap: !! material.specularMap, alphaMap: !! material.alphaMap, + combine: material.combine, + vertexColors: material.vertexColors, fog: fog, useFog: material.fog, fogExp: fog instanceof THREE.FogExp2, + flatShading: material.shading === THREE.FlatShading, + sizeAttenuation: material.sizeAttenuation, logarithmicDepthBuffer: _logarithmicDepthBuffer, @@ -22030,6 +22129,25 @@ THREE.WebGLRenderer = function ( parameters ) { } + function setMaterial( material ) { + + if ( material.transparent === true ) { + + state.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha ); + + } else { + + state.setBlending( THREE.NoBlending ); + + } + + state.setDepthTest( material.depthTest ); + state.setDepthWrite( material.depthWrite ); + state.setColorWrite( material.colorWrite ); + state.setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits ); + + } + function setProgram( camera, lights, fog, material, object ) { _usedTextureUnits = 0; @@ -22112,6 +22230,7 @@ THREE.WebGLRenderer = function ( parameters ) { if ( material instanceof THREE.MeshPhongMaterial || material instanceof THREE.MeshLambertMaterial || + material instanceof THREE.MeshBasicMaterial || material instanceof THREE.ShaderMaterial || material.skinning ) { @@ -22281,15 +22400,7 @@ THREE.WebGLRenderer = function ( parameters ) { uniforms.opacity.value = material.opacity; - if ( _this.gammaInput ) { - - uniforms.diffuse.value.copyGammaToLinear( material.color ); - - } else { - - uniforms.diffuse.value = material.color; - - } + uniforms.diffuse.value = material.color; uniforms.map.value = material.map; uniforms.lightMap.value = material.lightMap; @@ -22353,20 +22464,8 @@ THREE.WebGLRenderer = function ( parameters ) { uniforms.envMap.value = material.envMap; uniforms.flipEnvMap.value = ( material.envMap instanceof THREE.WebGLRenderTargetCube ) ? 1 : - 1; - if ( _this.gammaInput ) { - - //uniforms.reflectivity.value = material.reflectivity * material.reflectivity; - uniforms.reflectivity.value = material.reflectivity; - - } else { - - uniforms.reflectivity.value = material.reflectivity; - - } - + uniforms.reflectivity.value = material.reflectivity; uniforms.refractionRatio.value = material.refractionRatio; - uniforms.combine.value = material.combine; - uniforms.useRefract.value = material.envMap && material.envMap.mapping instanceof THREE.CubeRefractionMapping; } @@ -22394,6 +22493,15 @@ THREE.WebGLRenderer = function ( parameters ) { uniforms.map.value = material.map; + if ( material.map !== null ) { + + var offset = material.map.offset; + var repeat = material.map.repeat; + + uniforms.offsetRepeat.value.set( offset.x, offset.y, repeat.x, repeat.y ); + + } + } function refreshUniformsFog ( uniforms, fog ) { @@ -22417,19 +22525,8 @@ THREE.WebGLRenderer = function ( parameters ) { uniforms.shininess.value = material.shininess; - if ( _this.gammaInput ) { - - uniforms.ambient.value.copyGammaToLinear( material.ambient ); - uniforms.emissive.value.copyGammaToLinear( material.emissive ); - uniforms.specular.value.copyGammaToLinear( material.specular ); - - } else { - - uniforms.ambient.value = material.ambient; - uniforms.emissive.value = material.emissive; - uniforms.specular.value = material.specular; - - } + uniforms.emissive.value = material.emissive; + uniforms.specular.value = material.specular; if ( material.wrapAround ) { @@ -22441,17 +22538,7 @@ THREE.WebGLRenderer = function ( parameters ) { function refreshUniformsLambert ( uniforms, material ) { - if ( _this.gammaInput ) { - - uniforms.ambient.value.copyGammaToLinear( material.ambient ); - uniforms.emissive.value.copyGammaToLinear( material.emissive ); - - } else { - - uniforms.ambient.value = material.ambient; - uniforms.emissive.value = material.emissive; - - } + uniforms.emissive.value = material.emissive; if ( material.wrapAround ) { @@ -22471,6 +22558,7 @@ THREE.WebGLRenderer = function ( parameters ) { uniforms.pointLightColor.value = lights.point.colors; uniforms.pointLightPosition.value = lights.point.positions; uniforms.pointLightDistance.value = lights.point.distances; + uniforms.pointLightDecay.value = lights.point.decays; uniforms.spotLightColor.value = lights.spot.colors; uniforms.spotLightPosition.value = lights.spot.positions; @@ -22478,6 +22566,7 @@ THREE.WebGLRenderer = function ( parameters ) { uniforms.spotLightDirection.value = lights.spot.directions; uniforms.spotLightAngleCos.value = lights.spot.anglesCos; uniforms.spotLightExponent.value = lights.spot.exponents; + uniforms.spotLightDecay.value = lights.spot.decays; uniforms.hemisphereLightSkyColor.value = lights.hemi.skyColors; uniforms.hemisphereLightGroundColor.value = lights.hemi.groundColors; @@ -22487,27 +22576,29 @@ THREE.WebGLRenderer = function ( parameters ) { // If uniforms are marked as clean, they don't need to be loaded to the GPU. - function markUniformsLightsNeedsUpdate ( uniforms, boolean ) { + function markUniformsLightsNeedsUpdate ( uniforms, value ) { - uniforms.ambientLightColor.needsUpdate = boolean; + uniforms.ambientLightColor.needsUpdate = value; - uniforms.directionalLightColor.needsUpdate = boolean; - uniforms.directionalLightDirection.needsUpdate = boolean; + uniforms.directionalLightColor.needsUpdate = value; + uniforms.directionalLightDirection.needsUpdate = value; - uniforms.pointLightColor.needsUpdate = boolean; - uniforms.pointLightPosition.needsUpdate = boolean; - uniforms.pointLightDistance.needsUpdate = boolean; + uniforms.pointLightColor.needsUpdate = value; + uniforms.pointLightPosition.needsUpdate = value; + uniforms.pointLightDistance.needsUpdate = value; + uniforms.pointLightDecay.needsUpdate = value; - uniforms.spotLightColor.needsUpdate = boolean; - uniforms.spotLightPosition.needsUpdate = boolean; - uniforms.spotLightDistance.needsUpdate = boolean; - uniforms.spotLightDirection.needsUpdate = boolean; - uniforms.spotLightAngleCos.needsUpdate = boolean; - uniforms.spotLightExponent.needsUpdate = boolean; + uniforms.spotLightColor.needsUpdate = value; + uniforms.spotLightPosition.needsUpdate = value; + uniforms.spotLightDistance.needsUpdate = value; + uniforms.spotLightDirection.needsUpdate = value; + uniforms.spotLightAngleCos.needsUpdate = value; + uniforms.spotLightExponent.needsUpdate = value; + uniforms.spotLightDecay.needsUpdate = value; - uniforms.hemisphereLightSkyColor.needsUpdate = boolean; - uniforms.hemisphereLightGroundColor.needsUpdate = boolean; - uniforms.hemisphereLightDirection.needsUpdate = boolean; + uniforms.hemisphereLightSkyColor.needsUpdate = value; + uniforms.hemisphereLightGroundColor.needsUpdate = value; + uniforms.hemisphereLightDirection.needsUpdate = value; } @@ -22563,7 +22654,7 @@ THREE.WebGLRenderer = function ( parameters ) { if ( textureUnit >= _maxTextures ) { - console.warn( 'WebGLRenderer: trying to use ' + textureUnit + ' texture units while this GPU supports only ' + _maxTextures ); + THREE.warn( 'WebGLRenderer: trying to use ' + textureUnit + ' texture units while this GPU supports only ' + _maxTextures ); } @@ -22901,7 +22992,7 @@ THREE.WebGLRenderer = function ( parameters ) { default: - console.warn( 'THREE.WebGLRenderer: Unknown uniform type: ' + type ); + THREE.warn( 'THREE.WebGLRenderer: Unknown uniform type: ' + type ); } @@ -22916,16 +23007,6 @@ THREE.WebGLRenderer = function ( parameters ) { } - // - - function setColorGamma( array, offset, color, intensitySq ) { - - array[ offset ] = color.r * color.r * intensitySq; - array[ offset + 1 ] = color.g * color.g * intensitySq; - array[ offset + 2 ] = color.b * color.b * intensitySq; - - } - function setColorLinear( array, offset, color, intensity ) { array[ offset ] = color.r * intensity; @@ -22936,11 +23017,10 @@ THREE.WebGLRenderer = function ( parameters ) { function setupLights ( lights ) { - var l, ll, light, n, + var l, ll, light, r = 0, g = 0, b = 0, color, skyColor, groundColor, - intensity, intensitySq, - position, + intensity, distance, zlights = _lights, @@ -22951,6 +23031,7 @@ THREE.WebGLRenderer = function ( parameters ) { pointColors = zlights.point.colors, pointPositions = zlights.point.positions, pointDistances = zlights.point.distances, + pointDecays = zlights.point.decays, spotColors = zlights.spot.colors, spotPositions = zlights.spot.positions, @@ -22958,6 +23039,7 @@ THREE.WebGLRenderer = function ( parameters ) { spotDirections = zlights.spot.directions, spotAnglesCos = zlights.spot.anglesCos, spotExponents = zlights.spot.exponents, + spotDecays = zlights.spot.decays, hemiSkyColors = zlights.hemi.skyColors, hemiGroundColors = zlights.hemi.groundColors, @@ -22992,19 +23074,9 @@ THREE.WebGLRenderer = function ( parameters ) { if ( ! light.visible ) continue; - if ( _this.gammaInput ) { - - r += color.r * color.r; - g += color.g * color.g; - b += color.b * color.b; - - } else { - - r += color.r; - g += color.g; - b += color.b; - - } + r += color.r; + g += color.g; + b += color.b; } else if ( light instanceof THREE.DirectionalLight ) { @@ -23023,15 +23095,7 @@ THREE.WebGLRenderer = function ( parameters ) { dirPositions[ dirOffset + 1 ] = _direction.y; dirPositions[ dirOffset + 2 ] = _direction.z; - if ( _this.gammaInput ) { - - setColorGamma( dirColors, dirOffset, color, intensity * intensity ); - - } else { - - setColorLinear( dirColors, dirOffset, color, intensity ); - - } + setColorLinear( dirColors, dirOffset, color, intensity ); dirLength += 1; @@ -23043,15 +23107,7 @@ THREE.WebGLRenderer = function ( parameters ) { pointOffset = pointLength * 3; - if ( _this.gammaInput ) { - - setColorGamma( pointColors, pointOffset, color, intensity * intensity ); - - } else { - - setColorLinear( pointColors, pointOffset, color, intensity ); - - } + setColorLinear( pointColors, pointOffset, color, intensity ); _vector3.setFromMatrixPosition( light.matrixWorld ); @@ -23059,7 +23115,9 @@ THREE.WebGLRenderer = function ( parameters ) { pointPositions[ pointOffset + 1 ] = _vector3.y; pointPositions[ pointOffset + 2 ] = _vector3.z; + // distance is 0 if decay is 0, because there is no attenuation at all. pointDistances[ pointLength ] = distance; + pointDecays[ pointLength ] = ( light.distance === 0 ) ? 0.0 : light.decay; pointLength += 1; @@ -23071,15 +23129,7 @@ THREE.WebGLRenderer = function ( parameters ) { spotOffset = spotLength * 3; - if ( _this.gammaInput ) { - - setColorGamma( spotColors, spotOffset, color, intensity * intensity ); - - } else { - - setColorLinear( spotColors, spotOffset, color, intensity ); - - } + setColorLinear( spotColors, spotOffset, color, intensity ); _direction.setFromMatrixPosition( light.matrixWorld ); @@ -23099,6 +23149,7 @@ THREE.WebGLRenderer = function ( parameters ) { spotAnglesCos[ spotLength ] = Math.cos( light.angle ); spotExponents[ spotLength ] = light.exponent; + spotDecays[ spotLength ] = ( light.distance === 0 ) ? 0.0 : light.decay; spotLength += 1; @@ -23120,19 +23171,8 @@ THREE.WebGLRenderer = function ( parameters ) { skyColor = light.color; groundColor = light.groundColor; - if ( _this.gammaInput ) { - - intensitySq = intensity * intensity; - - setColorGamma( hemiSkyColors, hemiOffset, skyColor, intensitySq ); - setColorGamma( hemiGroundColors, hemiOffset, groundColor, intensitySq ); - - } else { - - setColorLinear( hemiSkyColors, hemiOffset, skyColor, intensity ); - setColorLinear( hemiGroundColors, hemiOffset, groundColor, intensity ); - - } + setColorLinear( hemiSkyColors, hemiOffset, skyColor, intensity ); + setColorLinear( hemiGroundColors, hemiOffset, groundColor, intensity ); hemiLength += 1; @@ -23202,185 +23242,8 @@ THREE.WebGLRenderer = function ( parameters ) { this.setMaterialFaces = function ( material ) { - var doubleSided = material.side === THREE.DoubleSide; - var flipSided = material.side === THREE.BackSide; - - if ( _oldDoubleSided !== doubleSided ) { - - if ( doubleSided ) { - - _gl.disable( _gl.CULL_FACE ); - - } else { - - _gl.enable( _gl.CULL_FACE ); - - } - - _oldDoubleSided = doubleSided; - - } - - if ( _oldFlipSided !== flipSided ) { - - if ( flipSided ) { - - _gl.frontFace( _gl.CW ); - - } else { - - _gl.frontFace( _gl.CCW ); - - } - - _oldFlipSided = flipSided; - - } - - }; - - this.setDepthTest = function ( depthTest ) { - - if ( _oldDepthTest !== depthTest ) { - - if ( depthTest ) { - - _gl.enable( _gl.DEPTH_TEST ); - - } else { - - _gl.disable( _gl.DEPTH_TEST ); - - } - - _oldDepthTest = depthTest; - - } - - }; - - this.setDepthWrite = function ( depthWrite ) { - - if ( _oldDepthWrite !== depthWrite ) { - - _gl.depthMask( depthWrite ); - _oldDepthWrite = depthWrite; - - } - - }; - - function setLineWidth ( width ) { - - if ( width !== _oldLineWidth ) { - - _gl.lineWidth( width ); - - _oldLineWidth = width; - - } - - } - - function setPolygonOffset ( polygonoffset, factor, units ) { - - if ( _oldPolygonOffset !== polygonoffset ) { - - if ( polygonoffset ) { - - _gl.enable( _gl.POLYGON_OFFSET_FILL ); - - } else { - - _gl.disable( _gl.POLYGON_OFFSET_FILL ); - - } - - _oldPolygonOffset = polygonoffset; - - } - - if ( polygonoffset && ( _oldPolygonOffsetFactor !== factor || _oldPolygonOffsetUnits !== units ) ) { - - _gl.polygonOffset( factor, units ); - - _oldPolygonOffsetFactor = factor; - _oldPolygonOffsetUnits = units; - - } - - } - - this.setBlending = function ( blending, blendEquation, blendSrc, blendDst ) { - - if ( blending !== _oldBlending ) { - - if ( blending === THREE.NoBlending ) { - - _gl.disable( _gl.BLEND ); - - } else if ( blending === THREE.AdditiveBlending ) { - - _gl.enable( _gl.BLEND ); - _gl.blendEquation( _gl.FUNC_ADD ); - _gl.blendFunc( _gl.SRC_ALPHA, _gl.ONE ); - - } else if ( blending === THREE.SubtractiveBlending ) { - - // TODO: Find blendFuncSeparate() combination - _gl.enable( _gl.BLEND ); - _gl.blendEquation( _gl.FUNC_ADD ); - _gl.blendFunc( _gl.ZERO, _gl.ONE_MINUS_SRC_COLOR ); - - } else if ( blending === THREE.MultiplyBlending ) { - - // TODO: Find blendFuncSeparate() combination - _gl.enable( _gl.BLEND ); - _gl.blendEquation( _gl.FUNC_ADD ); - _gl.blendFunc( _gl.ZERO, _gl.SRC_COLOR ); - - } else if ( blending === THREE.CustomBlending ) { - - _gl.enable( _gl.BLEND ); - - } else { - - _gl.enable( _gl.BLEND ); - _gl.blendEquationSeparate( _gl.FUNC_ADD, _gl.FUNC_ADD ); - _gl.blendFuncSeparate( _gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA, _gl.ONE, _gl.ONE_MINUS_SRC_ALPHA ); - - } - - _oldBlending = blending; - - } - - if ( blending === THREE.CustomBlending ) { - - if ( blendEquation !== _oldBlendEquation ) { - - _gl.blendEquation( paramThreeToGL( blendEquation ) ); - - _oldBlendEquation = blendEquation; - - } - - if ( blendSrc !== _oldBlendSrc || blendDst !== _oldBlendDst ) { - - _gl.blendFunc( paramThreeToGL( blendSrc ), paramThreeToGL( blendDst ) ); - - _oldBlendSrc = blendSrc; - _oldBlendDst = blendDst; - - } - - } else { - - _oldBlendEquation = null; - _oldBlendSrc = null; - _oldBlendDst = null; - - } + state.setDoubleSided( material.side === THREE.DoubleSide ); + state.setFlipSided( material.side === THREE.BackSide ); }; @@ -23403,19 +23266,31 @@ THREE.WebGLRenderer = function ( parameters ) { _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE ); _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE ); + if ( texture.wrapS !== THREE.ClampToEdgeWrapping || texture.wrapT !== THREE.ClampToEdgeWrapping ) { + + THREE.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping. ( ' + texture.sourceFile + ' )' ); + + } + _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) ); _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) ); + if ( texture.minFilter !== THREE.NearestFilter && texture.minFilter !== THREE.LinearFilter ) { + + THREE.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter. ( ' + texture.sourceFile + ' )' ); + + } + } extension = extensions.get( 'EXT_texture_filter_anisotropic' ); - if ( extension && texture.type !== THREE.FloatType ) { + if ( extension && texture.type !== THREE.FloatType && texture.type !== THREE.HalfFloatType ) { - if ( texture.anisotropy > 1 || texture.__oldAnisotropy ) { + if ( texture.anisotropy > 1 || texture.__currentAnisotropy ) { _gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, _this.getMaxAnisotropy() ) ); - texture.__oldAnisotropy = texture.anisotropy; + texture.__currentAnisotropy = texture.anisotropy; } @@ -23491,7 +23366,7 @@ THREE.WebGLRenderer = function ( parameters ) { } else { - console.warn( "Attempt to load unsupported compressed texture format" ); + THREE.warn( "THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()" ); } @@ -23568,7 +23443,7 @@ THREE.WebGLRenderer = function ( parameters ) { var context = canvas.getContext( '2d' ); context.drawImage( image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height ); - console.log( 'THREE.WebGLRenderer:', image, 'is too big (' + image.width + 'x' + image.height + '). Resized to ' + canvas.width + 'x' + canvas.height + '.' ); + THREE.warn( 'THREE.WebGLRenderer: image is too big (' + image.width + 'x' + image.height + '). Resized to ' + canvas.width + 'x' + canvas.height, image ); return canvas; @@ -23655,7 +23530,7 @@ THREE.WebGLRenderer = function ( parameters ) { } else { - console.warn( "Attempt to load unsupported compressed texture format" ); + THREE.warn( "THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setCubeTexture()" ); } @@ -23885,6 +23760,54 @@ THREE.WebGLRenderer = function ( parameters ) { }; + this.readRenderTargetPixels = function( renderTarget, x, y, width, height, buffer ) { + + if ( ! ( renderTarget instanceof THREE.WebGLRenderTarget ) ) { + + console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' ); + return; + + } + + if ( renderTarget.__webglFramebuffer ) { + + if ( renderTarget.format !== THREE.RGBAFormat ) { + + console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA format. readPixels can read only RGBA format.' ); + return; + + } + + var restore = false; + + if ( renderTarget.__webglFramebuffer !== _currentFramebuffer ) { + + _gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTarget.__webglFramebuffer ); + + restore = true; + + } + + if ( _gl.checkFramebufferStatus( _gl.FRAMEBUFFER ) === _gl.FRAMEBUFFER_COMPLETE ) { + + _gl.readPixels( x, y, width, height, _gl.RGBA, _gl.UNSIGNED_BYTE, buffer ); + + } else { + + console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.' ); + + } + + if ( restore ) { + + _gl.bindFramebuffer( _gl.FRAMEBUFFER, _currentFramebuffer ); + + } + + } + + }; + function updateRenderTargetMipmap ( renderTarget ) { if ( renderTarget instanceof THREE.WebGLRenderTargetCube ) { @@ -23947,6 +23870,14 @@ THREE.WebGLRenderer = function ( parameters ) { if ( p === THREE.UnsignedIntType ) return _gl.UNSIGNED_INT; if ( p === THREE.FloatType ) return _gl.FLOAT; + extension = extensions.get( 'OES_texture_half_float' ); + + if ( extension !== null ) { + + if ( p === THREE.HalfFloatType ) return extension.HALF_FLOAT_OES; + + } + if ( p === THREE.AlphaFormat ) return _gl.ALPHA; if ( p === THREE.RGBFormat ) return _gl.RGB; if ( p === THREE.RGBAFormat ) return _gl.RGBA; @@ -24034,7 +23965,7 @@ THREE.WebGLRenderer = function ( parameters ) { if ( maxBones < object.skeleton.bones.length ) { - console.warn( 'WebGLRenderer: too many bones - ' + object.skeleton.bones.length + ', this GPU supports just ' + maxBones + ' (try OpenGL instead of ANGLE)' ); + THREE.warn( 'WebGLRenderer: too many bones - ' + object.skeleton.bones.length + ', this GPU supports just ' + maxBones + ' (try OpenGL instead of ANGLE)' ); } @@ -24090,28 +24021,28 @@ THREE.WebGLRenderer = function ( parameters ) { } // DEPRECATED - + this.initMaterial = function () { - console.warn( 'THREE.WebGLRenderer: .initMaterial() has been removed.' ); + THREE.warn( 'THREE.WebGLRenderer: .initMaterial() has been removed.' ); }; this.addPrePlugin = function () { - console.warn( 'THREE.WebGLRenderer: .addPrePlugin() has been removed.' ); + THREE.warn( 'THREE.WebGLRenderer: .addPrePlugin() has been removed.' ); }; this.addPostPlugin = function () { - console.warn( 'THREE.WebGLRenderer: .addPostPlugin() has been removed.' ); + THREE.warn( 'THREE.WebGLRenderer: .addPostPlugin() has been removed.' ); }; this.updateShadowMap = function () { - console.warn( 'THREE.WebGLRenderer: .updateShadowMap() has been removed.' ); + THREE.warn( 'THREE.WebGLRenderer: .updateShadowMap() has been removed.' ); }; @@ -24150,7 +24081,7 @@ THREE.WebGLRenderTarget = function ( width, height, options ) { this.generateMipmaps = true; - this.shareDepthFrom = null; + this.shareDepthFrom = options.shareDepthFrom !== undefined ? options.shareDepthFrom : null; }; @@ -24219,9 +24150,14 @@ THREE.WebGLRenderTargetCube = function ( width, height, options ) { }; THREE.WebGLRenderTargetCube.prototype = Object.create( THREE.WebGLRenderTarget.prototype ); +THREE.WebGLRenderTargetCube.prototype.constructor = THREE.WebGLRenderTargetCube; // File:src/renderers/webgl/WebGLExtensions.js +/** +* @author mrdoob / http://mrdoob.com/ +*/ + THREE.WebGLExtensions = function ( gl ) { var extensions = {}; @@ -24237,18 +24173,6 @@ THREE.WebGLExtensions = function ( gl ) { var extension; switch ( name ) { - - case 'OES_texture_float': - extension = gl.getExtension( 'OES_texture_float' ); - break; - - case 'OES_texture_float_linear': - extension = gl.getExtension( 'OES_texture_float_linear' ); - break; - - case 'OES_standard_derivatives': - extension = gl.getExtension( 'OES_standard_derivatives' ); - break; case 'EXT_texture_filter_anisotropic': extension = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' ); @@ -24262,23 +24186,14 @@ THREE.WebGLExtensions = function ( gl ) { extension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' ); break; - case 'OES_element_index_uint': - extension = gl.getExtension( 'OES_element_index_uint' ); - break; - - case 'EXT_blend_minmax': - extension = gl.getExtension( 'EXT_blend_minmax' ); - break; - - case 'EXT_frag_depth': - extension = gl.getExtension( 'EXT_frag_depth' ); - break; + default: + extension = gl.getExtension( name ); } if ( extension === null ) { - console.log( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' ); + THREE.warn( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' ); } @@ -24305,12 +24220,12 @@ THREE.WebGLProgram = ( function () { value = defines[ d ]; if ( value === false ) continue; - chunk = "#define " + d + " " + value; + chunk = '#define ' + d + ' ' + value; chunks.push( chunk ); } - return chunks.join( "\n" ); + return chunks.join( '\n' ); }; @@ -24366,19 +24281,72 @@ THREE.WebGLProgram = ( function () { } - var shadowMapTypeDefine = "SHADOWMAP_TYPE_BASIC"; + var shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC'; if ( parameters.shadowMapType === THREE.PCFShadowMap ) { - shadowMapTypeDefine = "SHADOWMAP_TYPE_PCF"; + shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF'; } else if ( parameters.shadowMapType === THREE.PCFSoftShadowMap ) { - shadowMapTypeDefine = "SHADOWMAP_TYPE_PCF_SOFT"; + shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT'; } - // console.log( "building new program " ); + var envMapTypeDefine = 'ENVMAP_TYPE_CUBE'; + var envMapModeDefine = 'ENVMAP_MODE_REFLECTION'; + var envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY'; + + if ( parameters.envMap ) { + + switch ( material.envMap.mapping ) { + + case THREE.CubeReflectionMapping: + case THREE.CubeRefractionMapping: + envMapTypeDefine = 'ENVMAP_TYPE_CUBE'; + break; + + case THREE.EquirectangularReflectionMapping: + case THREE.EquirectangularRefractionMapping: + envMapTypeDefine = 'ENVMAP_TYPE_EQUIREC'; + break; + + case THREE.SphericalReflectionMapping: + envMapTypeDefine = 'ENVMAP_TYPE_SPHERE'; + break; + + } + + switch ( material.envMap.mapping ) { + + case THREE.CubeRefractionMapping: + case THREE.EquirectangularRefractionMapping: + envMapModeDefine = 'ENVMAP_MODE_REFRACTION'; + break; + + } + + switch ( material.combine ) { + + case THREE.MultiplyOperation: + envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY'; + break; + + case THREE.MixOperation: + envMapBlendingDefine = 'ENVMAP_BLENDING_MIX'; + break; + + case THREE.AddOperation: + envMapBlendingDefine = 'ENVMAP_BLENDING_ADD'; + break; + + } + + } + + var gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0; + + // console.log( 'building new program ' ); // @@ -24399,157 +24367,167 @@ THREE.WebGLProgram = ( function () { prefix_vertex = [ - "precision " + parameters.precision + " float;", - "precision " + parameters.precision + " int;", + 'precision ' + parameters.precision + ' float;', + 'precision ' + parameters.precision + ' int;', customDefines, - parameters.supportsVertexTextures ? "#define VERTEX_TEXTURES" : "", + parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '', + + _this.gammaInput ? '#define GAMMA_INPUT' : '', + _this.gammaOutput ? '#define GAMMA_OUTPUT' : '', + '#define GAMMA_FACTOR ' + gammaFactorDefine, - _this.gammaInput ? "#define GAMMA_INPUT" : "", - _this.gammaOutput ? "#define GAMMA_OUTPUT" : "", + '#define MAX_DIR_LIGHTS ' + parameters.maxDirLights, + '#define MAX_POINT_LIGHTS ' + parameters.maxPointLights, + '#define MAX_SPOT_LIGHTS ' + parameters.maxSpotLights, + '#define MAX_HEMI_LIGHTS ' + parameters.maxHemiLights, - "#define MAX_DIR_LIGHTS " + parameters.maxDirLights, - "#define MAX_POINT_LIGHTS " + parameters.maxPointLights, - "#define MAX_SPOT_LIGHTS " + parameters.maxSpotLights, - "#define MAX_HEMI_LIGHTS " + parameters.maxHemiLights, + '#define MAX_SHADOWS ' + parameters.maxShadows, - "#define MAX_SHADOWS " + parameters.maxShadows, + '#define MAX_BONES ' + parameters.maxBones, - "#define MAX_BONES " + parameters.maxBones, + parameters.map ? '#define USE_MAP' : '', + parameters.envMap ? '#define USE_ENVMAP' : '', + parameters.envMap ? '#define ' + envMapModeDefine : '', + parameters.lightMap ? '#define USE_LIGHTMAP' : '', + parameters.bumpMap ? '#define USE_BUMPMAP' : '', + parameters.normalMap ? '#define USE_NORMALMAP' : '', + parameters.specularMap ? '#define USE_SPECULARMAP' : '', + parameters.alphaMap ? '#define USE_ALPHAMAP' : '', + parameters.vertexColors ? '#define USE_COLOR' : '', - parameters.map ? "#define USE_MAP" : "", - parameters.envMap ? "#define USE_ENVMAP" : "", - parameters.lightMap ? "#define USE_LIGHTMAP" : "", - parameters.bumpMap ? "#define USE_BUMPMAP" : "", - parameters.normalMap ? "#define USE_NORMALMAP" : "", - parameters.specularMap ? "#define USE_SPECULARMAP" : "", - parameters.alphaMap ? "#define USE_ALPHAMAP" : "", - parameters.vertexColors ? "#define USE_COLOR" : "", + parameters.flatShading ? '#define FLAT_SHADED': '', - parameters.skinning ? "#define USE_SKINNING" : "", - parameters.useVertexTexture ? "#define BONE_TEXTURE" : "", + parameters.skinning ? '#define USE_SKINNING' : '', + parameters.useVertexTexture ? '#define BONE_TEXTURE' : '', - parameters.morphTargets ? "#define USE_MORPHTARGETS" : "", - parameters.morphNormals ? "#define USE_MORPHNORMALS" : "", - parameters.wrapAround ? "#define WRAP_AROUND" : "", - parameters.doubleSided ? "#define DOUBLE_SIDED" : "", - parameters.flipSided ? "#define FLIP_SIDED" : "", + parameters.morphTargets ? '#define USE_MORPHTARGETS' : '', + parameters.morphNormals ? '#define USE_MORPHNORMALS' : '', + parameters.wrapAround ? '#define WRAP_AROUND' : '', + parameters.doubleSided ? '#define DOUBLE_SIDED' : '', + parameters.flipSided ? '#define FLIP_SIDED' : '', - parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "", - parameters.shadowMapEnabled ? "#define " + shadowMapTypeDefine : "", - parameters.shadowMapDebug ? "#define SHADOWMAP_DEBUG" : "", - parameters.shadowMapCascade ? "#define SHADOWMAP_CASCADE" : "", + parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', + parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', + parameters.shadowMapDebug ? '#define SHADOWMAP_DEBUG' : '', + parameters.shadowMapCascade ? '#define SHADOWMAP_CASCADE' : '', - parameters.sizeAttenuation ? "#define USE_SIZEATTENUATION" : "", + parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '', - parameters.logarithmicDepthBuffer ? "#define USE_LOGDEPTHBUF" : "", - //_this._glExtensionFragDepth ? "#define USE_LOGDEPTHBUF_EXT" : "", + parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', + //_this._glExtensionFragDepth ? '#define USE_LOGDEPTHBUF_EXT' : '', - "uniform mat4 modelMatrix;", - "uniform mat4 modelViewMatrix;", - "uniform mat4 projectionMatrix;", - "uniform mat4 viewMatrix;", - "uniform mat3 normalMatrix;", - "uniform vec3 cameraPosition;", + 'uniform mat4 modelMatrix;', + 'uniform mat4 modelViewMatrix;', + 'uniform mat4 projectionMatrix;', + 'uniform mat4 viewMatrix;', + 'uniform mat3 normalMatrix;', + 'uniform vec3 cameraPosition;', - "attribute vec3 position;", - "attribute vec3 normal;", - "attribute vec2 uv;", - "attribute vec2 uv2;", + 'attribute vec3 position;', + 'attribute vec3 normal;', + 'attribute vec2 uv;', + 'attribute vec2 uv2;', - "#ifdef USE_COLOR", + '#ifdef USE_COLOR', - " attribute vec3 color;", + ' attribute vec3 color;', - "#endif", + '#endif', - "#ifdef USE_MORPHTARGETS", + '#ifdef USE_MORPHTARGETS', - " attribute vec3 morphTarget0;", - " attribute vec3 morphTarget1;", - " attribute vec3 morphTarget2;", - " attribute vec3 morphTarget3;", + ' attribute vec3 morphTarget0;', + ' attribute vec3 morphTarget1;', + ' attribute vec3 morphTarget2;', + ' attribute vec3 morphTarget3;', - " #ifdef USE_MORPHNORMALS", + ' #ifdef USE_MORPHNORMALS', - " attribute vec3 morphNormal0;", - " attribute vec3 morphNormal1;", - " attribute vec3 morphNormal2;", - " attribute vec3 morphNormal3;", + ' attribute vec3 morphNormal0;', + ' attribute vec3 morphNormal1;', + ' attribute vec3 morphNormal2;', + ' attribute vec3 morphNormal3;', - " #else", + ' #else', - " attribute vec3 morphTarget4;", - " attribute vec3 morphTarget5;", - " attribute vec3 morphTarget6;", - " attribute vec3 morphTarget7;", + ' attribute vec3 morphTarget4;', + ' attribute vec3 morphTarget5;', + ' attribute vec3 morphTarget6;', + ' attribute vec3 morphTarget7;', - " #endif", + ' #endif', - "#endif", + '#endif', - "#ifdef USE_SKINNING", + '#ifdef USE_SKINNING', - " attribute vec4 skinIndex;", - " attribute vec4 skinWeight;", + ' attribute vec4 skinIndex;', + ' attribute vec4 skinWeight;', - "#endif", + '#endif', - "" + '' ].join( '\n' ); prefix_fragment = [ - "precision " + parameters.precision + " float;", - "precision " + parameters.precision + " int;", + 'precision ' + parameters.precision + ' float;', + 'precision ' + parameters.precision + ' int;', - ( parameters.bumpMap || parameters.normalMap ) ? "#extension GL_OES_standard_derivatives : enable" : "", + ( parameters.bumpMap || parameters.normalMap || parameters.flatShading ) ? '#extension GL_OES_standard_derivatives : enable' : '', customDefines, - "#define MAX_DIR_LIGHTS " + parameters.maxDirLights, - "#define MAX_POINT_LIGHTS " + parameters.maxPointLights, - "#define MAX_SPOT_LIGHTS " + parameters.maxSpotLights, - "#define MAX_HEMI_LIGHTS " + parameters.maxHemiLights, + '#define MAX_DIR_LIGHTS ' + parameters.maxDirLights, + '#define MAX_POINT_LIGHTS ' + parameters.maxPointLights, + '#define MAX_SPOT_LIGHTS ' + parameters.maxSpotLights, + '#define MAX_HEMI_LIGHTS ' + parameters.maxHemiLights, - "#define MAX_SHADOWS " + parameters.maxShadows, + '#define MAX_SHADOWS ' + parameters.maxShadows, - parameters.alphaTest ? "#define ALPHATEST " + parameters.alphaTest: "", + parameters.alphaTest ? '#define ALPHATEST ' + parameters.alphaTest : '', - _this.gammaInput ? "#define GAMMA_INPUT" : "", - _this.gammaOutput ? "#define GAMMA_OUTPUT" : "", + _this.gammaInput ? '#define GAMMA_INPUT' : '', + _this.gammaOutput ? '#define GAMMA_OUTPUT' : '', + '#define GAMMA_FACTOR ' + gammaFactorDefine, - ( parameters.useFog && parameters.fog ) ? "#define USE_FOG" : "", - ( parameters.useFog && parameters.fogExp ) ? "#define FOG_EXP2" : "", + ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '', + ( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '', - parameters.map ? "#define USE_MAP" : "", - parameters.envMap ? "#define USE_ENVMAP" : "", - parameters.lightMap ? "#define USE_LIGHTMAP" : "", - parameters.bumpMap ? "#define USE_BUMPMAP" : "", - parameters.normalMap ? "#define USE_NORMALMAP" : "", - parameters.specularMap ? "#define USE_SPECULARMAP" : "", - parameters.alphaMap ? "#define USE_ALPHAMAP" : "", - parameters.vertexColors ? "#define USE_COLOR" : "", + parameters.map ? '#define USE_MAP' : '', + parameters.envMap ? '#define USE_ENVMAP' : '', + parameters.envMap ? '#define ' + envMapTypeDefine : '', + parameters.envMap ? '#define ' + envMapModeDefine : '', + parameters.envMap ? '#define ' + envMapBlendingDefine : '', + parameters.lightMap ? '#define USE_LIGHTMAP' : '', + parameters.bumpMap ? '#define USE_BUMPMAP' : '', + parameters.normalMap ? '#define USE_NORMALMAP' : '', + parameters.specularMap ? '#define USE_SPECULARMAP' : '', + parameters.alphaMap ? '#define USE_ALPHAMAP' : '', + parameters.vertexColors ? '#define USE_COLOR' : '', - parameters.metal ? "#define METAL" : "", - parameters.wrapAround ? "#define WRAP_AROUND" : "", - parameters.doubleSided ? "#define DOUBLE_SIDED" : "", - parameters.flipSided ? "#define FLIP_SIDED" : "", + parameters.flatShading ? '#define FLAT_SHADED': '', - parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "", - parameters.shadowMapEnabled ? "#define " + shadowMapTypeDefine : "", - parameters.shadowMapDebug ? "#define SHADOWMAP_DEBUG" : "", - parameters.shadowMapCascade ? "#define SHADOWMAP_CASCADE" : "", + parameters.metal ? '#define METAL' : '', + parameters.wrapAround ? '#define WRAP_AROUND' : '', + parameters.doubleSided ? '#define DOUBLE_SIDED' : '', + parameters.flipSided ? '#define FLIP_SIDED' : '', - parameters.logarithmicDepthBuffer ? "#define USE_LOGDEPTHBUF" : "", - //_this._glExtensionFragDepth ? "#define USE_LOGDEPTHBUF_EXT" : "", + parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', + parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', + parameters.shadowMapDebug ? '#define SHADOWMAP_DEBUG' : '', + parameters.shadowMapCascade ? '#define SHADOWMAP_CASCADE' : '', - "uniform mat4 viewMatrix;", - "uniform vec3 cameraPosition;", - "" + parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', + //_this._glExtensionFragDepth ? '#define USE_LOGDEPTHBUF_EXT' : '', + + 'uniform mat4 viewMatrix;', + 'uniform vec3 cameraPosition;', + '' ].join( '\n' ); @@ -24573,17 +24551,19 @@ THREE.WebGLProgram = ( function () { _gl.linkProgram( program ); + var programLogInfo = _gl.getProgramInfoLog( program ); + if ( _gl.getProgramParameter( program, _gl.LINK_STATUS ) === false ) { - console.error( 'THREE.WebGLProgram: Could not initialise shader.' ); - console.error( 'gl.VALIDATE_STATUS', _gl.getProgramParameter( program, _gl.VALIDATE_STATUS ) ); - console.error( 'gl.getError()', _gl.getError() ); + THREE.error( 'THREE.WebGLProgram: shader error: ' + _gl.getError(), 'gl.VALIDATE_STATUS', _gl.getProgramParameter( program, _gl.VALIDATE_STATUS ), 'gl.getPRogramInfoLog', programLogInfo ); } - if ( _gl.getProgramInfoLog( program ) !== '' ) { + if ( programLogInfo !== '' ) { - console.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()', _gl.getProgramInfoLog( program ) ); + THREE.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()' + programLogInfo ); + // THREE.warn( _gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glVertexShader ) ); + // THREE.warn( _gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glFragmentShader ) ); } @@ -24596,7 +24576,15 @@ THREE.WebGLProgram = ( function () { var identifiers = [ - 'viewMatrix', 'modelViewMatrix', 'projectionMatrix', 'normalMatrix', 'modelMatrix', 'cameraPosition', 'morphTargetInfluences', 'bindMatrix', 'bindMatrixInverse' + 'viewMatrix', + 'modelViewMatrix', + 'projectionMatrix', + 'normalMatrix', + 'modelMatrix', + 'cameraPosition', + 'morphTargetInfluences', + 'bindMatrix', + 'bindMatrixInverse' ]; @@ -24631,20 +24619,27 @@ THREE.WebGLProgram = ( function () { identifiers = [ - "position", "normal", "uv", "uv2", "tangent", "color", - "skinIndex", "skinWeight", "lineDistance" + 'position', + 'normal', + 'uv', + 'uv2', + 'tangent', + 'color', + 'skinIndex', + 'skinWeight', + 'lineDistance' ]; for ( var i = 0; i < parameters.maxMorphTargets; i ++ ) { - identifiers.push( "morphTarget" + i ); + identifiers.push( 'morphTarget' + i ); } for ( var i = 0; i < parameters.maxMorphNormals; i ++ ) { - identifiers.push( "morphNormal" + i ); + identifiers.push( 'morphNormal' + i ); } @@ -24699,14 +24694,13 @@ THREE.WebGLShader = ( function () { if ( gl.getShaderParameter( shader, gl.COMPILE_STATUS ) === false ) { - console.error( 'THREE.WebGLShader: Shader couldn\'t compile.' ); + THREE.error( 'THREE.WebGLShader: Shader couldn\'t compile.' ); } if ( gl.getShaderInfoLog( shader ) !== '' ) { - console.warn( 'THREE.WebGLShader: gl.getShaderInfoLog()', gl.getShaderInfoLog( shader ) ); - console.warn( addLineNumbers( string ) ); + THREE.warn( 'THREE.WebGLShader: gl.getShaderInfoLog()', gl.getShaderInfoLog( shader ), addLineNumbers( string ) ); } @@ -24719,6 +24713,302 @@ THREE.WebGLShader = ( function () { } )(); +// File:src/renderers/webgl/WebGLState.js + +/** +* @author mrdoob / http://mrdoob.com/ +*/ + +THREE.WebGLState = function ( gl, paramThreeToGL ) { + + var newAttributes = new Uint8Array( 16 ); + var enabledAttributes = new Uint8Array( 16 ); + + var currentBlending = null; + var currentBlendEquation = null; + var currentBlendSrc = null; + var currentBlendDst = null; + var currentBlendEquationAlpha = null; + var currentBlendSrcAlpha = null; + var currentBlendDstAlpha = null; + + var currentDepthTest = null; + var currentDepthWrite = null; + + var currentColorWrite = null; + + var currentDoubleSided = null; + var currentFlipSided = null; + + var currentLineWidth = null; + + var currentPolygonOffset = null; + var currentPolygonOffsetFactor = null; + var currentPolygonOffsetUnits = null; + + this.initAttributes = function () { + + for ( var i = 0, l = newAttributes.length; i < l; i ++ ) { + + newAttributes[ i ] = 0; + + } + + }; + + this.enableAttribute = function ( attribute ) { + + newAttributes[ attribute ] = 1; + + if ( enabledAttributes[ attribute ] === 0 ) { + + gl.enableVertexAttribArray( attribute ); + enabledAttributes[ attribute ] = 1; + + } + + }; + + this.disableUnusedAttributes = function () { + + for ( var i = 0, l = enabledAttributes.length; i < l; i ++ ) { + + if ( enabledAttributes[ i ] !== newAttributes[ i ] ) { + + gl.disableVertexAttribArray( i ); + enabledAttributes[ i ] = 0; + + } + + } + + }; + + this.setBlending = function ( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha ) { + + if ( blending !== currentBlending ) { + + if ( blending === THREE.NoBlending ) { + + gl.disable( gl.BLEND ); + + } else if ( blending === THREE.AdditiveBlending ) { + + gl.enable( gl.BLEND ); + gl.blendEquation( gl.FUNC_ADD ); + gl.blendFunc( gl.SRC_ALPHA, gl.ONE ); + + } else if ( blending === THREE.SubtractiveBlending ) { + + // TODO: Find blendFuncSeparate() combination + gl.enable( gl.BLEND ); + gl.blendEquation( gl.FUNC_ADD ); + gl.blendFunc( gl.ZERO, gl.ONE_MINUS_SRC_COLOR ); + + } else if ( blending === THREE.MultiplyBlending ) { + + // TODO: Find blendFuncSeparate() combination + gl.enable( gl.BLEND ); + gl.blendEquation( gl.FUNC_ADD ); + gl.blendFunc( gl.ZERO, gl.SRC_COLOR ); + + } else if ( blending === THREE.CustomBlending ) { + + gl.enable( gl.BLEND ); + + } else { + + gl.enable( gl.BLEND ); + gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); + gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); + + } + + currentBlending = blending; + + } + + if ( blending === THREE.CustomBlending ) { + + blendEquationAlpha = blendEquationAlpha || blendEquation; + blendSrcAlpha = blendSrcAlpha || blendSrc; + blendDstAlpha = blendDstAlpha || blendDst; + + if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) { + + gl.blendEquationSeparate( paramThreeToGL( blendEquation ), paramThreeToGL( blendEquationAlpha ) ); + + currentBlendEquation = blendEquation; + currentBlendEquationAlpha = blendEquationAlpha; + + } + + if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) { + + gl.blendFuncSeparate( paramThreeToGL( blendSrc ), paramThreeToGL( blendDst ), paramThreeToGL( blendSrcAlpha ), paramThreeToGL( blendDstAlpha ) ); + + currentBlendSrc = blendSrc; + currentBlendDst = blendDst; + currentBlendSrcAlpha = blendSrcAlpha; + currentBlendDstAlpha = blendDstAlpha; + + } + + } else { + + currentBlendEquation = null; + currentBlendSrc = null; + currentBlendDst = null; + currentBlendEquationAlpha = null; + currentBlendSrcAlpha = null; + currentBlendDstAlpha = null; + + } + + }; + + this.setDepthTest = function ( depthTest ) { + + if ( currentDepthTest !== depthTest ) { + + if ( depthTest ) { + + gl.enable( gl.DEPTH_TEST ); + + } else { + + gl.disable( gl.DEPTH_TEST ); + + } + + currentDepthTest = depthTest; + + } + + }; + + this.setDepthWrite = function ( depthWrite ) { + + if ( currentDepthWrite !== depthWrite ) { + + gl.depthMask( depthWrite ); + currentDepthWrite = depthWrite; + + } + + }; + + this.setColorWrite = function ( colorWrite ) { + + if ( currentColorWrite !== colorWrite ) { + + gl.colorMask( colorWrite, colorWrite, colorWrite, colorWrite ); + currentColorWrite = colorWrite; + + } + + }; + + this.setDoubleSided = function ( doubleSided ) { + + if ( currentDoubleSided !== doubleSided ) { + + if ( doubleSided ) { + + gl.disable( gl.CULL_FACE ); + + } else { + + gl.enable( gl.CULL_FACE ); + + } + + currentDoubleSided = doubleSided; + + } + + }; + + this.setFlipSided = function ( flipSided ) { + + if ( currentFlipSided !== flipSided ) { + + if ( flipSided ) { + + gl.frontFace( gl.CW ); + + } else { + + gl.frontFace( gl.CCW ); + + } + + currentFlipSided = flipSided; + + } + + }; + + this.setLineWidth = function ( width ) { + + if ( width !== currentLineWidth ) { + + gl.lineWidth( width ); + + currentLineWidth = width; + + } + + }; + + this.setPolygonOffset = function ( polygonoffset, factor, units ) { + + if ( currentPolygonOffset !== polygonoffset ) { + + if ( polygonoffset ) { + + gl.enable( gl.POLYGON_OFFSET_FILL ); + + } else { + + gl.disable( gl.POLYGON_OFFSET_FILL ); + + } + + currentPolygonOffset = polygonoffset; + + } + + if ( polygonoffset && ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) ) { + + gl.polygonOffset( factor, units ); + + currentPolygonOffsetFactor = factor; + currentPolygonOffsetUnits = units; + + } + + }; + + this.reset = function () { + + for ( var i = 0; i < enabledAttributes.length; i ++ ) { + + enabledAttributes[ i ] = 0; + + } + + currentBlending = null; + currentDepthTest = null; + currentDepthWrite = null; + currentColorWrite = null; + currentDoubleSided = null; + currentFlipSided = null; + + }; + +}; + // File:src/renderers/webgl/plugins/LensFlarePlugin.js /** @@ -25044,7 +25334,7 @@ THREE.LensFlarePlugin = function ( renderer, flares ) { // calc object screen position var flare = flares[ i ]; - + tempPosition.set( flare.matrixWorld.elements[12], flare.matrixWorld.elements[13], flare.matrixWorld.elements[14] ); tempPosition.applyMatrix4( camera.matrixWorldInverse ); @@ -25142,7 +25432,7 @@ THREE.LensFlarePlugin = function ( renderer, flares ) { gl.uniform1f( uniforms.opacity, sprite.opacity ); gl.uniform3f( uniforms.color, sprite.color.r, sprite.color.g, sprite.color.b ); - renderer.setBlending( sprite.blending, sprite.blendEquation, sprite.blendSrc, sprite.blendDst ); + renderer.state.setBlending( sprite.blending, sprite.blendEquation, sprite.blendSrc, sprite.blendDst ); renderer.setTexture( sprite.texture, 1 ); gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); @@ -25210,7 +25500,7 @@ THREE.ShadowMapPlugin = function ( _renderer, _lights, _webglObjects, _webglObje _max = new THREE.Vector3(), _matrixPosition = new THREE.Vector3(), - + _renderList = []; // init @@ -25258,7 +25548,7 @@ THREE.ShadowMapPlugin = function ( _renderer, _lights, _webglObjects, _webglObje var i, il, j, jl, n, shadowMap, shadowMatrix, shadowCamera, - program, buffer, material, + buffer, material, webglObject, object, light, lights = [], @@ -25284,7 +25574,7 @@ THREE.ShadowMapPlugin = function ( _renderer, _lights, _webglObjects, _webglObje } - _renderer.setDepthTest( true ); + _renderer.state.setDepthTest( true ); // preprocess lights // - skip lights that are not casting shadows @@ -25317,7 +25607,7 @@ THREE.ShadowMapPlugin = function ( _renderer, _lights, _webglObjects, _webglObje light.shadowCascadeArray[ n ] = virtualLight; - console.log( "Created virtualLight", virtualLight ); + //console.log( "Created virtualLight", virtualLight ); } else { @@ -25378,7 +25668,7 @@ THREE.ShadowMapPlugin = function ( _renderer, _lights, _webglObjects, _webglObje } else { - console.error( "Unsupported light type for shadow" ); + THREE.error( "THREE.ShadowMapPlugin: Unsupported light type for shadow", light ); continue; } @@ -25543,7 +25833,7 @@ THREE.ShadowMapPlugin = function ( _renderer, _lights, _webglObjects, _webglObje }; - function projectObject( scene, object, shadowCamera ){ + function projectObject( scene, object, shadowCamera ) { if ( object.visible ) { @@ -25731,7 +26021,13 @@ THREE.SpritePlugin = function ( renderer, sprites ) { var program, attributes, uniforms; var texture; - + + // decompose matrixWorld + + var spritePosition = new THREE.Vector3(); + var spriteRotation = new THREE.Quaternion(); + var spriteScale = new THREE.Vector3(); + var init = function () { var vertices = new Float32Array( [ @@ -25872,16 +26168,7 @@ THREE.SpritePlugin = function ( renderer, sprites ) { var sprite = sprites[ i ]; sprite._modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, sprite.matrixWorld ); - - if ( sprite.renderDepth === null ) { - - sprite.z = - sprite._modelViewMatrix.elements[ 14 ]; - - } else { - - sprite.z = sprite.renderDepth; - - } + sprite.z = - sprite._modelViewMatrix.elements[ 14 ]; } @@ -25899,8 +26186,10 @@ THREE.SpritePlugin = function ( renderer, sprites ) { gl.uniform1f( uniforms.alphaTest, material.alphaTest ); gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, sprite._modelViewMatrix.elements ); - scale[ 0 ] = sprite.scale.x; - scale[ 1 ] = sprite.scale.y; + sprite.matrixWorld.decompose( spritePosition, spriteRotation, spriteScale ); + + scale[ 0 ] = spriteScale.x; + scale[ 1 ] = spriteScale.y; var fogType = 0; @@ -25935,9 +26224,9 @@ THREE.SpritePlugin = function ( renderer, sprites ) { gl.uniform1f( uniforms.rotation, material.rotation ); gl.uniform2fv( uniforms.scale, scale ); - renderer.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst ); - renderer.setDepthTest( material.depthTest ); - renderer.setDepthWrite( material.depthWrite ); + renderer.state.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst ); + renderer.state.setDepthTest( material.depthTest ); + renderer.state.setDepthWrite( material.depthWrite ); if ( material.map && material.map.image && material.map.image.width ) { @@ -25956,7 +26245,7 @@ THREE.SpritePlugin = function ( renderer, sprites ) { // restore gl gl.enable( gl.CULL_FACE ); - + renderer.resetGLState(); }; @@ -26094,7 +26383,7 @@ THREE.GeometryUtils = { merge: function ( geometry1, geometry2, materialIndexOffset ) { - console.warn( 'THREE.GeometryUtils: .merge() has been moved to Geometry. Use geometry.merge( geometry2, matrix, materialIndexOffset ) instead.' ); + THREE.warn( 'THREE.GeometryUtils: .merge() has been moved to Geometry. Use geometry.merge( geometry2, matrix, materialIndexOffset ) instead.' ); var matrix; @@ -26113,7 +26402,7 @@ THREE.GeometryUtils = { center: function ( geometry ) { - console.warn( 'THREE.GeometryUtils: .center() has been moved to Geometry. Use geometry.center() instead.' ); + THREE.warn( 'THREE.GeometryUtils: .center() has been moved to Geometry. Use geometry.center() instead.' ); return geometry.center(); } @@ -26189,7 +26478,7 @@ THREE.ImageUtils = { } - } ); + }, undefined, onError ); } @@ -26205,13 +26494,13 @@ THREE.ImageUtils = { loadCompressedTexture: function () { - console.error( 'THREE.ImageUtils.loadCompressedTexture has been removed. Use THREE.DDSLoader instead.' ) + THREE.error( 'THREE.ImageUtils.loadCompressedTexture has been removed. Use THREE.DDSLoader instead.' ) }, loadCompressedTextureCube: function () { - console.error( 'THREE.ImageUtils.loadCompressedTextureCube has been removed. Use THREE.DDSLoader instead.' ) + THREE.error( 'THREE.ImageUtils.loadCompressedTextureCube has been removed. Use THREE.DDSLoader instead.' ) }, @@ -26268,7 +26557,7 @@ THREE.ImageUtils = { points.push( [ - 1, 0, data[ ( y * width + lx ) * 4 ] / 255 * depth ] ); points.push( [ - 1, - 1, data[ ( ly * width + lx ) * 4 ] / 255 * depth ] ); points.push( [ 0, - 1, data[ ( ly * width + x ) * 4 ] / 255 * depth ] ); - points.push( [ 1, - 1, data[ ( ly * width + ux ) * 4 ] / 255 * depth ] ); + points.push( [ 1, - 1, data[ ( ly * width + ux ) * 4 ] / 255 * depth ] ); points.push( [ 1, 0, data[ ( y * width + ux ) * 4 ] / 255 * depth ] ); points.push( [ 1, 1, data[ ( uy * width + ux ) * 4 ] / 255 * depth ] ); points.push( [ 0, 1, data[ ( uy * width + x ) * 4 ] / 255 * depth ] ); @@ -26447,7 +26736,7 @@ THREE.FontUtils = { ThreeFont.faces[ family ][ data.cssFontWeight ] = ThreeFont.faces[ family ][ data.cssFontWeight ] || {}; ThreeFont.faces[ family ][ data.cssFontWeight ][ data.cssFontStyle ] = data; - var face = ThreeFont.faces[ family ][ data.cssFontWeight ][ data.cssFontStyle ] = data; + ThreeFont.faces[ family ][ data.cssFontWeight ][ data.cssFontStyle ] = data; return data; @@ -26455,11 +26744,9 @@ THREE.FontUtils = { drawText: function ( text ) { - var characterPts = [], allPts = []; - // RenderText - var i, p, + var i, face = this.getFace(), scale = this.size / face.resolution, offset = 0, @@ -26547,7 +26834,7 @@ THREE.FontUtils = { x = outline[ i ++ ] * scaleX + offset; y = outline[ i ++ ] * scaleY; - path.lineTo( x,y ); + path.lineTo( x, y ); break; case 'q': @@ -26571,13 +26858,13 @@ THREE.FontUtils = { for ( i2 = 1, divisions = this.divisions; i2 <= divisions; i2 ++ ) { var t = i2 / divisions; - var tx = THREE.Shape.Utils.b2( t, cpx0, cpx1, cpx ); - var ty = THREE.Shape.Utils.b2( t, cpy0, cpy1, cpy ); - } + THREE.Shape.Utils.b2( t, cpx0, cpx1, cpx ); + THREE.Shape.Utils.b2( t, cpy0, cpy1, cpy ); + } - } + } - break; + break; case 'b': @@ -26602,8 +26889,8 @@ THREE.FontUtils = { for ( i2 = 1, divisions = this.divisions; i2 <= divisions; i2 ++ ) { var t = i2 / divisions; - var tx = THREE.Shape.Utils.b3( t, cpx0, cpx1, cpx2, cpx ); - var ty = THREE.Shape.Utils.b3( t, cpy0, cpy1, cpy2, cpy ); + THREE.Shape.Utils.b3( t, cpx0, cpx1, cpx2, cpx ); + THREE.Shape.Utils.b3( t, cpy0, cpy1, cpy2, cpy ); } @@ -26724,7 +27011,7 @@ THREE.FontUtils.generateShapes = function ( text, parameters ) { //throw ( "Warning, unable to triangulate polygon!" ); //return null; // Sometimes warning is fine, especially polygons are triangulated in reverse. - console.log( 'Warning, unable to triangulate polygon!' ); + THREE.warn( 'THREE.FontUtils: Warning, unable to triangulate polygon! in Triangulate.process()' ); if ( indices ) return vertIndices; return result; @@ -26758,7 +27045,7 @@ THREE.FontUtils.generateShapes = function ( text, parameters ) { /* remove v from the remaining polygon */ - for ( s = v, t = v + 1; t < nv; s++, t++ ) { + for ( s = v, t = v + 1; t < nv; s ++, t ++ ) { verts[ s ] = verts[ t ]; @@ -26874,6 +27161,7 @@ THREE.Audio = function ( listener ) { this.context = listener.context; this.source = this.context.createBufferSource(); + this.source.onended = this.onEnded.bind(this); this.gain = this.context.createGain(); this.gain.connect( this.context.destination ); @@ -26881,9 +27169,15 @@ THREE.Audio = function ( listener ) { this.panner = this.context.createPanner(); this.panner.connect( this.gain ); + this.autoplay = false; + + this.startTime = 0; + this.isPlaying = false; + }; THREE.Audio.prototype = Object.create( THREE.Object3D.prototype ); +THREE.Audio.prototype.constructor = THREE.Audio; THREE.Audio.prototype.load = function ( file ) { @@ -26897,8 +27191,8 @@ THREE.Audio.prototype.load = function ( file ) { scope.context.decodeAudioData( this.response, function ( buffer ) { scope.source.buffer = buffer; - scope.source.connect( scope.panner ); - scope.source.start( 0 ); + + if( scope.autoplay ) scope.play(); } ); @@ -26909,6 +27203,49 @@ THREE.Audio.prototype.load = function ( file ) { }; +THREE.Audio.prototype.play = function () { + + if ( this.isPlaying === true ) { + + THREE.warn( 'THREE.Audio: Audio is already playing.' ); + return; + + } + + var source = this.context.createBufferSource(); + + source.buffer = this.source.buffer; + source.loop = this.source.loop; + source.onended = this.source.onended; + source.connect( this.panner ); + source.start( 0, this.startTime ); + + this.isPlaying = true; + + this.source = source; + +}; + +THREE.Audio.prototype.pause = function () { + + this.source.stop(); + this.startTime = this.context.currentTime; + +}; + +THREE.Audio.prototype.stop = function () { + + this.source.stop(); + this.startTime = 0; + +}; + +THREE.Audio.prototype.onEnded = function() { + + this.isPlaying = false; + +}; + THREE.Audio.prototype.setLoop = function ( value ) { this.source.loop = value; @@ -26927,6 +27264,12 @@ THREE.Audio.prototype.setRolloffFactor = function ( value ) { }; +THREE.Audio.prototype.setVolume = function ( value ) { + + this.gain.gain.value = value; + +}; + THREE.Audio.prototype.updateMatrixWorld = ( function () { var position = new THREE.Vector3(); @@ -26960,6 +27303,7 @@ THREE.AudioListener = function () { }; THREE.AudioListener.prototype = Object.create( THREE.Object3D.prototype ); +THREE.AudioListener.prototype.constructor = THREE.AudioListener; THREE.AudioListener.prototype.updateMatrixWorld = ( function () { @@ -26977,6 +27321,7 @@ THREE.AudioListener.prototype.updateMatrixWorld = ( function () { THREE.Object3D.prototype.updateMatrixWorld.call( this, force ); var listener = this.context.listener; + var up = this.up; this.matrixWorld.decompose( position, quaternion, scale ); @@ -26984,7 +27329,7 @@ THREE.AudioListener.prototype.updateMatrixWorld = ( function () { velocity.subVectors( position, positionPrev ); listener.setPosition( position.x, position.y, position.z ); - listener.setOrientation( orientation.x, orientation.y, orientation.z, this.up.x, this.up.y, this.up.z ); + listener.setOrientation( orientation.x, orientation.y, orientation.z, up.x, up.y, up.z ); listener.setVelocity( velocity.x, velocity.y, velocity.z ); positionPrev.copy( position ); @@ -27040,7 +27385,7 @@ THREE.Curve = function () { THREE.Curve.prototype.getPoint = function ( t ) { - console.log( "Warning, getPoint() not implemented!" ); + THREE.warn( "THREE.Curve: Warning, getPoint() not implemented!" ); return null; }; @@ -27104,7 +27449,7 @@ THREE.Curve.prototype.getLength = function () { THREE.Curve.prototype.getLengths = function ( divisions ) { - if ( ! divisions ) divisions = (this.__arcLengthDivisions) ? (this.__arcLengthDivisions): 200; + if ( ! divisions ) divisions = (this.__arcLengthDivisions) ? (this.__arcLengthDivisions) : 200; if ( this.cacheArcLengths && ( this.cacheArcLengths.length == divisions + 1 ) @@ -27179,12 +27524,10 @@ THREE.Curve.prototype.getUtoTmapping = function ( u, distance ) { if ( comparison < 0 ) { low = i + 1; - continue; } else if ( comparison > 0 ) { high = i - 1; - continue; } else { @@ -27211,17 +27554,17 @@ THREE.Curve.prototype.getUtoTmapping = function ( u, distance ) { // we could get finer grain at lengths, or use simple interpolatation between two points var lengthBefore = arcLengths[ i ]; - var lengthAfter = arcLengths[ i + 1 ]; + var lengthAfter = arcLengths[ i + 1 ]; - var segmentLength = lengthAfter - lengthBefore; + var segmentLength = lengthAfter - lengthBefore; // determine where we are between the 'before' and 'after' points - var segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength; + var segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength; // add that fractional amount to t - var t = ( i + segmentFraction ) / ( il -1 ); + var t = ( i + segmentFraction ) / ( il - 1 ); return t; @@ -27280,8 +27623,8 @@ THREE.Curve.Utils = { tangentCubicBezier: function (t, p0, p1, p2, p3 ) { return - 3 * p0 * (1 - t) * (1 - t) + - 3 * p1 * (1 - t) * (1-t) - 6 *t *p1 * (1-t) + - 6 * t * p2 * (1-t) - 3 * t * t * p2 + + 3 * p1 * (1 - t) * (1 - t) - 6 * t * p1 * (1 - t) + + 6 * t * p2 * (1 - t) - 3 * t * t * p2 + 3 * t * t * p3; }, @@ -27325,6 +27668,7 @@ THREE.Curve.Utils = { THREE.Curve.create = function ( constructor, getPointFunc ) { constructor.prototype = Object.create( THREE.Curve.prototype ); + constructor.prototype.constructor = constructor; constructor.prototype.getPoint = getPointFunc; return constructor; @@ -27352,6 +27696,7 @@ THREE.CurvePath = function () { }; THREE.CurvePath.prototype = Object.create( THREE.Curve.prototype ); +THREE.CurvePath.prototype.constructor = THREE.CurvePath; THREE.CurvePath.prototype.add = function ( curve ) { @@ -27370,7 +27715,7 @@ THREE.CurvePath.prototype.closePath = function() { // and verify for vector3 (needs to implement equals) // Add a line curve if start and end of lines are not connected var startPoint = this.curves[0].getPoint(0); - var endPoint = this.curves[this.curves.length-1].getPoint(1); + var endPoint = this.curves[this.curves.length - 1].getPoint(1); if (! startPoint.equals(endPoint)) { this.curves.push( new THREE.LineCurve(endPoint, startPoint) ); @@ -27406,7 +27751,6 @@ THREE.CurvePath.prototype.getPoint = function( t ) { return curve.getPointAt( u ); - break; } i ++; @@ -27672,6 +28016,7 @@ THREE.Gyroscope = function () { }; THREE.Gyroscope.prototype = Object.create( THREE.Object3D.prototype ); +THREE.Gyroscope.prototype.constructor = THREE.Gyroscope; THREE.Gyroscope.prototype.updateMatrixWorld = ( function () { @@ -27749,6 +28094,7 @@ THREE.Path = function ( points ) { }; THREE.Path.prototype = Object.create( THREE.CurvePath.prototype ); +THREE.Path.prototype.constructor = THREE.Path; THREE.PathActions = { @@ -27957,7 +28303,7 @@ THREE.Path.prototype.getPoints = function( divisions, closedPath ) { action = item.action; args = item.args; - switch( action ) { + switch ( action ) { case THREE.PathActions.MOVE_TO: @@ -28104,7 +28450,7 @@ THREE.Path.prototype.getPoints = function( divisions, closedPath ) { //console.log(points); - break; + break; case THREE.PathActions.ELLIPSE: @@ -28142,7 +28488,7 @@ THREE.Path.prototype.getPoints = function( divisions, closedPath ) { //console.log(points); - break; + break; } // end switch @@ -28249,7 +28595,7 @@ THREE.Path.prototype.toShapes = function( isCCW, noHoles ) { // with the horizontal line through inPt, left of inPt // not counting lowerY endpoints of edges and whole edges on that line var inside = false; - for( var p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) { + for ( var p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) { var edgeLowPt = inPolygon[ p ]; var edgeHighPt = inPolygon[ q ]; @@ -28362,7 +28708,6 @@ THREE.Path.prototype.toShapes = function( isCCW, noHoles ) { betterShapeHoles[sIdx] = []; } for (var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) { - var sh = newShapes[sIdx]; var sho = newShapeHoles[sIdx]; for (var hIdx = 0; hIdx < sho.length; hIdx ++ ) { var ho = sho[hIdx]; @@ -28425,6 +28770,7 @@ THREE.Shape = function () { }; THREE.Shape.prototype = Object.create( THREE.Path.prototype ); +THREE.Shape.prototype.constructor = THREE.Shape; // Convenience method to return ExtrudeGeometry @@ -28580,16 +28926,16 @@ THREE.Shape.Utils = { if ( perpSeg2 == 0 ) { if ( ( inExcludeAdjacentSegs ) && ( ( perpSeg1 == 0 ) || ( perpSeg1 == limit ) ) ) return []; - return [ inSeg1Pt1 ]; + return [ inSeg1Pt1 ]; } if ( perpSeg2 == limit ) { if ( ( inExcludeAdjacentSegs ) && ( ( perpSeg1 == 0 ) || ( perpSeg1 == limit ) ) ) return []; - return [ inSeg1Pt2 ]; + return [ inSeg1Pt2 ]; } // intersection at endpoint of segment#2? - if ( perpSeg1 == 0 ) return [ inSeg2Pt1 ]; - if ( perpSeg1 == limit ) return [ inSeg2Pt2 ]; + if ( perpSeg1 == 0 ) return [ inSeg2Pt1 ]; + if ( perpSeg1 == limit ) return [ inSeg2Pt2 ]; // return real intersection point var factorSeg1 = perpSeg2 / limit; @@ -28607,17 +28953,17 @@ THREE.Shape.Utils = { if ( seg1Pt && seg2Pt ) { if ( (inSeg1Pt1.x != inSeg2Pt1.x) || (inSeg1Pt1.y != inSeg2Pt1.y) ) return []; // they are distinct points - return [ inSeg1Pt1 ]; // they are the same point + return [ inSeg1Pt1 ]; // they are the same point } // segment#1 is a single point if ( seg1Pt ) { if (! point_in_segment_2D_colin( inSeg2Pt1, inSeg2Pt2, inSeg1Pt1 ) ) return []; // but not in segment#2 - return [ inSeg1Pt1 ]; + return [ inSeg1Pt1 ]; } // segment#2 is a single point if ( seg2Pt ) { if (! point_in_segment_2D_colin( inSeg1Pt1, inSeg1Pt2, inSeg2Pt1 ) ) return []; // but not in segment#1 - return [ inSeg2Pt1 ]; + return [ inSeg2Pt1 ]; } // they are collinear segments, which might overlap @@ -28748,7 +29094,7 @@ THREE.Shape.Utils = { // checks for intersections with shape edges var sIdx, nextIdx, intersection; for ( sIdx = 0; sIdx < shape.length; sIdx ++ ) { - nextIdx = sIdx+1; nextIdx %= shape.length; + nextIdx = sIdx + 1; nextIdx %= shape.length; intersection = intersect_segments_2D( inShapePt, inHolePt, shape[sIdx], shape[nextIdx], true ); if ( intersection.length > 0 ) return true; } @@ -28765,7 +29111,7 @@ THREE.Shape.Utils = { for ( ihIdx = 0; ihIdx < indepHoles.length; ihIdx ++ ) { chkHole = holes[indepHoles[ihIdx]]; for ( hIdx = 0; hIdx < chkHole.length; hIdx ++ ) { - nextIdx = hIdx+1; nextIdx %= chkHole.length; + nextIdx = hIdx + 1; nextIdx %= chkHole.length; intersection = intersect_segments_2D( inShapePt, inHolePt, chkHole[hIdx], chkHole[nextIdx], true ); if ( intersection.length > 0 ) return true; } @@ -28817,12 +29163,12 @@ THREE.Shape.Utils = { if ( intersectsHoleEdge( shapePt, holePt ) ) continue; holeIndex = h2; - indepHoles.splice(h,1); + indepHoles.splice(h, 1); - tmpShape1 = shape.slice( 0, shapeIndex+1 ); + tmpShape1 = shape.slice( 0, shapeIndex + 1 ); tmpShape2 = shape.slice( shapeIndex ); tmpHole1 = hole.slice( holeIndex ); - tmpHole2 = hole.slice( 0, holeIndex+1 ); + tmpHole2 = hole.slice( 0, holeIndex + 1 ); shape = tmpShape1.concat( tmpHole1 ).concat( tmpHole2 ).concat( tmpShape2 ); @@ -28869,7 +29215,7 @@ THREE.Shape.Utils = { if ( allPointsMap[ key ] !== undefined ) { - console.log( "Duplicate point", key ); + THREE.warn( "THREE.Shape: Duplicate point", key ); } @@ -28997,6 +29343,7 @@ THREE.LineCurve = function ( v1, v2 ) { }; THREE.LineCurve.prototype = Object.create( THREE.Curve.prototype ); +THREE.LineCurve.prototype.constructor = THREE.LineCurve; THREE.LineCurve.prototype.getPoint = function ( t ) { @@ -29039,6 +29386,7 @@ THREE.QuadraticBezierCurve = function ( v0, v1, v2 ) { }; THREE.QuadraticBezierCurve.prototype = Object.create( THREE.Curve.prototype ); +THREE.QuadraticBezierCurve.prototype.constructor = THREE.QuadraticBezierCurve; THREE.QuadraticBezierCurve.prototype.getPoint = function ( t ) { @@ -29082,6 +29430,7 @@ THREE.CubicBezierCurve = function ( v0, v1, v2, v3 ) { }; THREE.CubicBezierCurve.prototype = Object.create( THREE.Curve.prototype ); +THREE.CubicBezierCurve.prototype.constructor = THREE.CubicBezierCurve; THREE.CubicBezierCurve.prototype.getPoint = function ( t ) { @@ -29121,6 +29470,7 @@ THREE.SplineCurve = function ( points /* array of Vector2 */ ) { }; THREE.SplineCurve.prototype = Object.create( THREE.Curve.prototype ); +THREE.SplineCurve.prototype.constructor = THREE.SplineCurve; THREE.SplineCurve.prototype.getPoint = function ( t ) { @@ -29132,8 +29482,8 @@ THREE.SplineCurve.prototype.getPoint = function ( t ) { var point0 = points[ intPoint == 0 ? intPoint : intPoint - 1 ] var point1 = points[ intPoint ] - var point2 = points[ intPoint > points.length - 2 ? points.length -1 : intPoint + 1 ] - var point3 = points[ intPoint > points.length - 3 ? points.length -1 : intPoint + 2 ] + var point2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ] + var point3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ] var vector = new THREE.Vector2(); @@ -29166,6 +29516,7 @@ THREE.EllipseCurve = function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle }; THREE.EllipseCurve.prototype = Object.create( THREE.Curve.prototype ); +THREE.EllipseCurve.prototype.constructor = THREE.EllipseCurve; THREE.EllipseCurve.prototype.getPoint = function ( t ) { @@ -29207,6 +29558,7 @@ THREE.ArcCurve = function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise }; THREE.ArcCurve.prototype = Object.create( THREE.EllipseCurve.prototype ); +THREE.ArcCurve.prototype.constructor = THREE.ArcCurve; // File:src/extras/curves/LineCurve3.js @@ -29394,9 +29746,9 @@ THREE.AnimationHandler = { // - add: function () { console.warn( 'THREE.AnimationHandler.add() has been deprecated.' ); }, - get: function () { console.warn( 'THREE.AnimationHandler.get() has been deprecated.' ); }, - remove: function () { console.warn( 'THREE.AnimationHandler.remove() has been deprecated.' ); }, + add: function () { THREE.warn( 'THREE.AnimationHandler.add() has been deprecated.' ); }, + get: function () { THREE.warn( 'THREE.AnimationHandler.get() has been deprecated.' ); }, + remove: function () { THREE.warn( 'THREE.AnimationHandler.remove() has been deprecated.' ); }, // @@ -29404,7 +29756,7 @@ THREE.AnimationHandler = { init: function ( data ) { - if ( data.initialized === true ) return; + if ( data.initialized === true ) return data; // loop through all keys @@ -29616,390 +29968,387 @@ THREE.Animation = function ( root, data ) { }; +THREE.Animation.prototype = { -THREE.Animation.prototype.keyTypes = [ "pos", "rot", "scl" ]; + constructor: THREE.Animation, + keyTypes: [ "pos", "rot", "scl" ], -THREE.Animation.prototype.play = function ( startTime, weight ) { + play: function ( startTime, weight ) { - this.currentTime = startTime !== undefined ? startTime : 0; - this.weight = weight !== undefined ? weight: 1; + this.currentTime = startTime !== undefined ? startTime : 0; + this.weight = weight !== undefined ? weight : 1; - this.isPlaying = true; + this.isPlaying = true; - this.reset(); + this.reset(); - THREE.AnimationHandler.play( this ); + THREE.AnimationHandler.play( this ); -}; + }, + stop: function() { -THREE.Animation.prototype.stop = function() { + this.isPlaying = false; - this.isPlaying = false; + THREE.AnimationHandler.stop( this ); - THREE.AnimationHandler.stop( this ); + }, -}; + reset: function () { -THREE.Animation.prototype.reset = function () { + for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) { - for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) { + var object = this.hierarchy[ h ]; + + if ( object.animationCache === undefined ) { - var object = this.hierarchy[ h ]; + object.animationCache = { + animations: {}, + blending: { + positionWeight: 0.0, + quaternionWeight: 0.0, + scaleWeight: 0.0 + } + }; + } - object.matrixAutoUpdate = true; + var name = this.data.name; + var animations = object.animationCache.animations; + var animationCache = animations[ name ]; - if ( object.animationCache === undefined ) { + if ( animationCache === undefined ) { - object.animationCache = { - animations: {}, - blending: { - positionWeight: 0.0, - quaternionWeight: 0.0, - scaleWeight: 0.0 - } - }; - } + animationCache = { + prevKey: { pos: 0, rot: 0, scl: 0 }, + nextKey: { pos: 0, rot: 0, scl: 0 }, + originalMatrix: object.matrix + }; - if ( object.animationCache.animations[this.data.name] === undefined ) { + animations[ name ] = animationCache; - object.animationCache.animations[this.data.name] = {}; - object.animationCache.animations[this.data.name].prevKey = { pos: 0, rot: 0, scl: 0 }; - object.animationCache.animations[this.data.name].nextKey = { pos: 0, rot: 0, scl: 0 }; - object.animationCache.animations[this.data.name].originalMatrix = object.matrix; + } - } + // Get keys to match our current time - var animationCache = object.animationCache.animations[this.data.name]; + for ( var t = 0; t < 3; t ++ ) { - // Get keys to match our current time + var type = this.keyTypes[ t ]; - for ( var t = 0; t < 3; t ++ ) { + var prevKey = this.data.hierarchy[ h ].keys[ 0 ]; + var nextKey = this.getNextKeyWith( type, h, 1 ); - var type = this.keyTypes[ t ]; + while ( nextKey.time < this.currentTime && nextKey.index > prevKey.index ) { - var prevKey = this.data.hierarchy[ h ].keys[ 0 ]; - var nextKey = this.getNextKeyWith( type, h, 1 ); + prevKey = nextKey; + nextKey = this.getNextKeyWith( type, h, nextKey.index + 1 ); - while ( nextKey.time < this.currentTime && nextKey.index > prevKey.index ) { + } - prevKey = nextKey; - nextKey = this.getNextKeyWith( type, h, nextKey.index + 1 ); + animationCache.prevKey[ type ] = prevKey; + animationCache.nextKey[ type ] = nextKey; } - animationCache.prevKey[ type ] = prevKey; - animationCache.nextKey[ type ] = nextKey; - } - } + }, -}; + resetBlendWeights: function () { + + for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) { -THREE.Animation.prototype.resetBlendWeights = function () { + var object = this.hierarchy[ h ]; + var animationCache = object.animationCache; - for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) { + if ( animationCache !== undefined ) { - var object = this.hierarchy[ h ]; + var blending = animationCache.blending; - if ( object.animationCache !== undefined ) { + blending.positionWeight = 0.0; + blending.quaternionWeight = 0.0; + blending.scaleWeight = 0.0; - object.animationCache.blending.positionWeight = 0.0; - object.animationCache.blending.quaternionWeight = 0.0; - object.animationCache.blending.scaleWeight = 0.0; + } } - } + }, -}; + update: ( function() { -THREE.Animation.prototype.update = (function(){ + var points = []; + var target = new THREE.Vector3(); + var newVector = new THREE.Vector3(); + var newQuat = new THREE.Quaternion(); - var points = []; - var target = new THREE.Vector3(); - var newVector = new THREE.Vector3(); - var newQuat = new THREE.Quaternion(); + // Catmull-Rom spline - // Catmull-Rom spline + var interpolateCatmullRom = function ( points, scale ) { - var interpolateCatmullRom = function ( points, scale ) { + var c = [], v3 = [], + point, intPoint, weight, w2, w3, + pa, pb, pc, pd; - var c = [], v3 = [], - point, intPoint, weight, w2, w3, - pa, pb, pc, pd; + point = ( points.length - 1 ) * scale; + intPoint = Math.floor( point ); + weight = point - intPoint; - point = ( points.length - 1 ) * scale; - intPoint = Math.floor( point ); - weight = point - intPoint; + c[ 0 ] = intPoint === 0 ? intPoint : intPoint - 1; + c[ 1 ] = intPoint; + c[ 2 ] = intPoint > points.length - 2 ? intPoint : intPoint + 1; + c[ 3 ] = intPoint > points.length - 3 ? intPoint : intPoint + 2; - c[ 0 ] = intPoint === 0 ? intPoint : intPoint - 1; - c[ 1 ] = intPoint; - c[ 2 ] = intPoint > points.length - 2 ? intPoint : intPoint + 1; - c[ 3 ] = intPoint > points.length - 3 ? intPoint : intPoint + 2; + pa = points[ c[ 0 ] ]; + pb = points[ c[ 1 ] ]; + pc = points[ c[ 2 ] ]; + pd = points[ c[ 3 ] ]; - pa = points[ c[ 0 ] ]; - pb = points[ c[ 1 ] ]; - pc = points[ c[ 2 ] ]; - pd = points[ c[ 3 ] ]; + w2 = weight * weight; + w3 = weight * w2; - w2 = weight * weight; - w3 = weight * w2; + v3[ 0 ] = interpolate( pa[ 0 ], pb[ 0 ], pc[ 0 ], pd[ 0 ], weight, w2, w3 ); + v3[ 1 ] = interpolate( pa[ 1 ], pb[ 1 ], pc[ 1 ], pd[ 1 ], weight, w2, w3 ); + v3[ 2 ] = interpolate( pa[ 2 ], pb[ 2 ], pc[ 2 ], pd[ 2 ], weight, w2, w3 ); - v3[ 0 ] = interpolate( pa[ 0 ], pb[ 0 ], pc[ 0 ], pd[ 0 ], weight, w2, w3 ); - v3[ 1 ] = interpolate( pa[ 1 ], pb[ 1 ], pc[ 1 ], pd[ 1 ], weight, w2, w3 ); - v3[ 2 ] = interpolate( pa[ 2 ], pb[ 2 ], pc[ 2 ], pd[ 2 ], weight, w2, w3 ); + return v3; - return v3; + }; - }; + var interpolate = function ( p0, p1, p2, p3, t, t2, t3 ) { - var interpolate = function ( p0, p1, p2, p3, t, t2, t3 ) { + var v0 = ( p2 - p0 ) * 0.5, + v1 = ( p3 - p1 ) * 0.5; - var v0 = ( p2 - p0 ) * 0.5, - v1 = ( p3 - p1 ) * 0.5; + return ( 2 * ( p1 - p2 ) + v0 + v1 ) * t3 + ( - 3 * ( p1 - p2 ) - 2 * v0 - v1 ) * t2 + v0 * t + p1; - return ( 2 * ( p1 - p2 ) + v0 + v1 ) * t3 + ( - 3 * ( p1 - p2 ) - 2 * v0 - v1 ) * t2 + v0 * t + p1; + }; - }; + return function ( delta ) { - return function ( delta ) { + if ( this.isPlaying === false ) return; - if ( this.isPlaying === false ) return; + this.currentTime += delta * this.timeScale; - this.currentTime += delta * this.timeScale; + if ( this.weight === 0 ) + return; - if ( this.weight === 0 ) - return; + // - // + var duration = this.data.length; - var duration = this.data.length; + if ( this.currentTime > duration || this.currentTime < 0 ) { - if ( this.currentTime > duration || this.currentTime < 0 ) { + if ( this.loop ) { - if ( this.loop ) { + this.currentTime %= duration; - this.currentTime %= duration; + if ( this.currentTime < 0 ) + this.currentTime += duration; - if ( this.currentTime < 0 ) - this.currentTime += duration; + this.reset(); - this.reset(); + } else { - } else { + this.stop(); - this.stop(); - return; + } } - } + for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) { - for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) { + var object = this.hierarchy[ h ]; + var animationCache = object.animationCache.animations[this.data.name]; + var blending = object.animationCache.blending; - var object = this.hierarchy[ h ]; - var animationCache = object.animationCache.animations[this.data.name]; - var blending = object.animationCache.blending; + // loop through pos/rot/scl - // loop through pos/rot/scl + for ( var t = 0; t < 3; t ++ ) { - for ( var t = 0; t < 3; t ++ ) { + // get keys - // get keys + var type = this.keyTypes[ t ]; + var prevKey = animationCache.prevKey[ type ]; + var nextKey = animationCache.nextKey[ type ]; - var type = this.keyTypes[ t ]; - var prevKey = animationCache.prevKey[ type ]; - var nextKey = animationCache.nextKey[ type ]; + if ( ( this.timeScale > 0 && nextKey.time <= this.currentTime ) || + ( this.timeScale < 0 && prevKey.time >= this.currentTime ) ) { - if ( ( this.timeScale > 0 && nextKey.time <= this.currentTime ) || - ( this.timeScale < 0 && prevKey.time >= this.currentTime ) ) { + prevKey = this.data.hierarchy[ h ].keys[ 0 ]; + nextKey = this.getNextKeyWith( type, h, 1 ); - prevKey = this.data.hierarchy[ h ].keys[ 0 ]; - nextKey = this.getNextKeyWith( type, h, 1 ); + while ( nextKey.time < this.currentTime && nextKey.index > prevKey.index ) { - while ( nextKey.time < this.currentTime && nextKey.index > prevKey.index ) { + prevKey = nextKey; + nextKey = this.getNextKeyWith( type, h, nextKey.index + 1 ); - prevKey = nextKey; - nextKey = this.getNextKeyWith( type, h, nextKey.index + 1 ); + } - } + animationCache.prevKey[ type ] = prevKey; + animationCache.nextKey[ type ] = nextKey; - animationCache.prevKey[ type ] = prevKey; - animationCache.nextKey[ type ] = nextKey; + } - } + var scale = ( this.currentTime - prevKey.time ) / ( nextKey.time - prevKey.time ); - object.matrixAutoUpdate = true; - object.matrixWorldNeedsUpdate = true; + var prevXYZ = prevKey[ type ]; + var nextXYZ = nextKey[ type ]; - var scale = ( this.currentTime - prevKey.time ) / ( nextKey.time - prevKey.time ); + if ( scale < 0 ) scale = 0; + if ( scale > 1 ) scale = 1; - var prevXYZ = prevKey[ type ]; - var nextXYZ = nextKey[ type ]; + // interpolate - if ( scale < 0 ) scale = 0; - if ( scale > 1 ) scale = 1; + if ( type === "pos" ) { - // interpolate + if ( this.interpolationType === THREE.AnimationHandler.LINEAR ) { - if ( type === "pos" ) { + newVector.x = prevXYZ[ 0 ] + ( nextXYZ[ 0 ] - prevXYZ[ 0 ] ) * scale; + newVector.y = prevXYZ[ 1 ] + ( nextXYZ[ 1 ] - prevXYZ[ 1 ] ) * scale; + newVector.z = prevXYZ[ 2 ] + ( nextXYZ[ 2 ] - prevXYZ[ 2 ] ) * scale; - if ( this.interpolationType === THREE.AnimationHandler.LINEAR ) { + // blend + var proportionalWeight = this.weight / ( this.weight + blending.positionWeight ); + object.position.lerp( newVector, proportionalWeight ); + blending.positionWeight += this.weight; - newVector.x = prevXYZ[ 0 ] + ( nextXYZ[ 0 ] - prevXYZ[ 0 ] ) * scale; - newVector.y = prevXYZ[ 1 ] + ( nextXYZ[ 1 ] - prevXYZ[ 1 ] ) * scale; - newVector.z = prevXYZ[ 2 ] + ( nextXYZ[ 2 ] - prevXYZ[ 2 ] ) * scale; + } else if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM || + this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) { - // blend - var proportionalWeight = this.weight / ( this.weight + blending.positionWeight ); - object.position.lerp( newVector, proportionalWeight ); - blending.positionWeight += this.weight; + points[ 0 ] = this.getPrevKeyWith( "pos", h, prevKey.index - 1 )[ "pos" ]; + points[ 1 ] = prevXYZ; + points[ 2 ] = nextXYZ; + points[ 3 ] = this.getNextKeyWith( "pos", h, nextKey.index + 1 )[ "pos" ]; - } else if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM || - this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) { + scale = scale * 0.33 + 0.33; - points[ 0 ] = this.getPrevKeyWith( "pos", h, prevKey.index - 1 )[ "pos" ]; - points[ 1 ] = prevXYZ; - points[ 2 ] = nextXYZ; - points[ 3 ] = this.getNextKeyWith( "pos", h, nextKey.index + 1 )[ "pos" ]; + var currentPoint = interpolateCatmullRom( points, scale ); + var proportionalWeight = this.weight / ( this.weight + blending.positionWeight ); + blending.positionWeight += this.weight; - scale = scale * 0.33 + 0.33; + // blend - var currentPoint = interpolateCatmullRom( points, scale ); - var proportionalWeight = this.weight / ( this.weight + blending.positionWeight ); - blending.positionWeight += this.weight; + var vector = object.position; - // blend + vector.x = vector.x + ( currentPoint[ 0 ] - vector.x ) * proportionalWeight; + vector.y = vector.y + ( currentPoint[ 1 ] - vector.y ) * proportionalWeight; + vector.z = vector.z + ( currentPoint[ 2 ] - vector.z ) * proportionalWeight; - var vector = object.position; - - vector.x = vector.x + ( currentPoint[ 0 ] - vector.x ) * proportionalWeight; - vector.y = vector.y + ( currentPoint[ 1 ] - vector.y ) * proportionalWeight; - vector.z = vector.z + ( currentPoint[ 2 ] - vector.z ) * proportionalWeight; + if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) { - if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) { + var forwardPoint = interpolateCatmullRom( points, scale * 1.01 ); - var forwardPoint = interpolateCatmullRom( points, scale * 1.01 ); + target.set( forwardPoint[ 0 ], forwardPoint[ 1 ], forwardPoint[ 2 ] ); + target.sub( vector ); + target.y = 0; + target.normalize(); - target.set( forwardPoint[ 0 ], forwardPoint[ 1 ], forwardPoint[ 2 ] ); - target.sub( vector ); - target.y = 0; - target.normalize(); + var angle = Math.atan2( target.x, target.z ); + object.rotation.set( 0, angle, 0 ); - var angle = Math.atan2( target.x, target.z ); - object.rotation.set( 0, angle, 0 ); + } } - } + } else if ( type === "rot" ) { - } else if ( type === "rot" ) { + THREE.Quaternion.slerp( prevXYZ, nextXYZ, newQuat, scale ); - THREE.Quaternion.slerp( prevXYZ, nextXYZ, newQuat, scale ); + // Avoid paying the cost of an additional slerp if we don't have to + if ( blending.quaternionWeight === 0 ) { - // Avoid paying the cost of an additional slerp if we don't have to - if ( blending.quaternionWeight === 0 ) { + object.quaternion.copy(newQuat); + blending.quaternionWeight = this.weight; - object.quaternion.copy(newQuat); - blending.quaternionWeight = this.weight; + } else { - } else { + var proportionalWeight = this.weight / ( this.weight + blending.quaternionWeight ); + THREE.Quaternion.slerp( object.quaternion, newQuat, object.quaternion, proportionalWeight ); + blending.quaternionWeight += this.weight; - var proportionalWeight = this.weight / ( this.weight + blending.quaternionWeight ); - THREE.Quaternion.slerp( object.quaternion, newQuat, object.quaternion, proportionalWeight ); - blending.quaternionWeight += this.weight; + } - } + } else if ( type === "scl" ) { - } else if ( type === "scl" ) { + newVector.x = prevXYZ[ 0 ] + ( nextXYZ[ 0 ] - prevXYZ[ 0 ] ) * scale; + newVector.y = prevXYZ[ 1 ] + ( nextXYZ[ 1 ] - prevXYZ[ 1 ] ) * scale; + newVector.z = prevXYZ[ 2 ] + ( nextXYZ[ 2 ] - prevXYZ[ 2 ] ) * scale; - newVector.x = prevXYZ[ 0 ] + ( nextXYZ[ 0 ] - prevXYZ[ 0 ] ) * scale; - newVector.y = prevXYZ[ 1 ] + ( nextXYZ[ 1 ] - prevXYZ[ 1 ] ) * scale; - newVector.z = prevXYZ[ 2 ] + ( nextXYZ[ 2 ] - prevXYZ[ 2 ] ) * scale; + var proportionalWeight = this.weight / ( this.weight + blending.scaleWeight ); + object.scale.lerp( newVector, proportionalWeight ); + blending.scaleWeight += this.weight; - var proportionalWeight = this.weight / ( this.weight + blending.scaleWeight ); - object.scale.lerp( newVector, proportionalWeight ); - blending.scaleWeight += this.weight; + } } } - } - - return true; - - }; - -})(); - - + return true; + }; + } )(), -// Get next key with + getNextKeyWith: function ( type, h, key ) { -THREE.Animation.prototype.getNextKeyWith = function ( type, h, key ) { + var keys = this.data.hierarchy[ h ].keys; - var keys = this.data.hierarchy[ h ].keys; + if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM || + this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) { - if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM || - this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) { + key = key < keys.length - 1 ? key : keys.length - 1; - key = key < keys.length - 1 ? key : keys.length - 1; + } else { - } else { + key = key % keys.length; - key = key % keys.length; + } - } + for ( ; key < keys.length; key ++ ) { - for ( ; key < keys.length; key ++ ) { + if ( keys[ key ][ type ] !== undefined ) { - if ( keys[ key ][ type ] !== undefined ) { + return keys[ key ]; - return keys[ key ]; + } } - } - - return this.data.hierarchy[ h ].keys[ 0 ]; + return this.data.hierarchy[ h ].keys[ 0 ]; -}; + }, -// Get previous key with + getPrevKeyWith: function ( type, h, key ) { -THREE.Animation.prototype.getPrevKeyWith = function ( type, h, key ) { + var keys = this.data.hierarchy[ h ].keys; - var keys = this.data.hierarchy[ h ].keys; + if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM || + this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) { - if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM || - this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) { + key = key > 0 ? key : 0; - key = key > 0 ? key : 0; + } else { - } else { + key = key >= 0 ? key : key + keys.length; - key = key >= 0 ? key : key + keys.length; + } - } + for ( ; key >= 0; key -- ) { - for ( ; key >= 0; key -- ) { + if ( keys[ key ][ type ] !== undefined ) { - if ( keys[ key ][ type ] !== undefined ) { + return keys[ key ]; - return keys[ key ]; + } } - } + return this.data.hierarchy[ h ].keys[ keys.length - 1 ]; - return this.data.hierarchy[ h ].keys[ keys.length - 1 ]; + } }; @@ -30057,196 +30406,193 @@ THREE.KeyFrameAnimation = function ( data ) { }; +THREE.KeyFrameAnimation.prototype = { -THREE.KeyFrameAnimation.prototype.play = function ( startTime ) { + constructor: THREE.KeyFrameAnimation, - this.currentTime = startTime !== undefined ? startTime : 0; + play: function ( startTime ) { - if ( this.isPlaying === false ) { + this.currentTime = startTime !== undefined ? startTime : 0; - this.isPlaying = true; + if ( this.isPlaying === false ) { - // reset key cache + this.isPlaying = true; - var h, hl = this.hierarchy.length, - object, - node; + // reset key cache - for ( h = 0; h < hl; h ++ ) { + var h, hl = this.hierarchy.length, + object, + node; - object = this.hierarchy[ h ]; - node = this.data.hierarchy[ h ]; + for ( h = 0; h < hl; h ++ ) { - if ( node.animationCache === undefined ) { + object = this.hierarchy[ h ]; + node = this.data.hierarchy[ h ]; - node.animationCache = {}; - node.animationCache.prevKey = null; - node.animationCache.nextKey = null; - node.animationCache.originalMatrix = object.matrix; + if ( node.animationCache === undefined ) { - } + node.animationCache = {}; + node.animationCache.prevKey = null; + node.animationCache.nextKey = null; + node.animationCache.originalMatrix = object.matrix; + + } + + var keys = this.data.hierarchy[h].keys; - var keys = this.data.hierarchy[h].keys; + if (keys.length) { - if (keys.length) { + node.animationCache.prevKey = keys[ 0 ]; + node.animationCache.nextKey = keys[ 1 ]; - node.animationCache.prevKey = keys[ 0 ]; - node.animationCache.nextKey = keys[ 1 ]; + this.startTime = Math.min( keys[0].time, this.startTime ); + this.endTime = Math.max( keys[keys.length - 1].time, this.endTime ); - this.startTime = Math.min( keys[0].time, this.startTime ); - this.endTime = Math.max( keys[keys.length - 1].time, this.endTime ); + } } - } + this.update( 0 ); - this.update( 0 ); + } - } + this.isPaused = false; - this.isPaused = false; + THREE.AnimationHandler.play( this ); - THREE.AnimationHandler.play( this ); + }, -}; + stop: function () { + this.isPlaying = false; + this.isPaused = false; -THREE.KeyFrameAnimation.prototype.stop = function() { + THREE.AnimationHandler.stop( this ); - this.isPlaying = false; - this.isPaused = false; + // reset JIT matrix and remove cache - THREE.AnimationHandler.stop( this ); + for ( var h = 0; h < this.data.hierarchy.length; h ++ ) { - // reset JIT matrix and remove cache + var obj = this.hierarchy[ h ]; + var node = this.data.hierarchy[ h ]; - for ( var h = 0; h < this.data.hierarchy.length; h ++ ) { - - var obj = this.hierarchy[ h ]; - var node = this.data.hierarchy[ h ]; + if ( node.animationCache !== undefined ) { - if ( node.animationCache !== undefined ) { + var original = node.animationCache.originalMatrix; - var original = node.animationCache.originalMatrix; + original.copy( obj.matrix ); + obj.matrix = original; - original.copy( obj.matrix ); - obj.matrix = original; + delete node.animationCache; - delete node.animationCache; + } } - } - -}; + }, + update: function ( delta ) { -// Update + if ( this.isPlaying === false ) return; -THREE.KeyFrameAnimation.prototype.update = function ( delta ) { + this.currentTime += delta * this.timeScale; - if ( this.isPlaying === false ) return; + // - this.currentTime += delta * this.timeScale; + var duration = this.data.length; - // + if ( this.loop === true && this.currentTime > duration ) { - var duration = this.data.length; + this.currentTime %= duration; - if ( this.loop === true && this.currentTime > duration ) { + } - this.currentTime %= duration; + this.currentTime = Math.min( this.currentTime, duration ); - } + for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) { - this.currentTime = Math.min( this.currentTime, duration ); + var object = this.hierarchy[ h ]; + var node = this.data.hierarchy[ h ]; - for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) { + var keys = node.keys, + animationCache = node.animationCache; - var object = this.hierarchy[ h ]; - var node = this.data.hierarchy[ h ]; - var keys = node.keys, - animationCache = node.animationCache; + if ( keys.length ) { + var prevKey = animationCache.prevKey; + var nextKey = animationCache.nextKey; - if ( keys.length ) { + if ( nextKey.time <= this.currentTime ) { - var prevKey = animationCache.prevKey; - var nextKey = animationCache.nextKey; + while ( nextKey.time < this.currentTime && nextKey.index > prevKey.index ) { - if ( nextKey.time <= this.currentTime ) { + prevKey = nextKey; + nextKey = keys[ prevKey.index + 1 ]; - while ( nextKey.time < this.currentTime && nextKey.index > prevKey.index ) { + } - prevKey = nextKey; - nextKey = keys[ prevKey.index + 1 ]; + animationCache.prevKey = prevKey; + animationCache.nextKey = nextKey; } - animationCache.prevKey = prevKey; - animationCache.nextKey = nextKey; + if ( nextKey.time >= this.currentTime ) { - } + prevKey.interpolate( nextKey, this.currentTime ); - if ( nextKey.time >= this.currentTime ) { + } else { - prevKey.interpolate( nextKey, this.currentTime ); + prevKey.interpolate( nextKey, nextKey.time ); - } else { + } - prevKey.interpolate( nextKey, nextKey.time ); + this.data.hierarchy[ h ].node.updateMatrix(); + object.matrixWorldNeedsUpdate = true; } - this.data.hierarchy[ h ].node.updateMatrix(); - object.matrixWorldNeedsUpdate = true; - } - } - -}; + }, -// Get next key with + getNextKeyWith: function ( sid, h, key ) { -THREE.KeyFrameAnimation.prototype.getNextKeyWith = function( sid, h, key ) { + var keys = this.data.hierarchy[ h ].keys; + key = key % keys.length; - var keys = this.data.hierarchy[ h ].keys; - key = key % keys.length; + for ( ; key < keys.length; key ++ ) { - for ( ; key < keys.length; key ++ ) { + if ( keys[ key ].hasTarget( sid ) ) { - if ( keys[ key ].hasTarget( sid ) ) { + return keys[ key ]; - return keys[ key ]; + } } - } - - return keys[ 0 ]; + return keys[ 0 ]; -}; + }, -// Get previous key with + getPrevKeyWith: function ( sid, h, key ) { -THREE.KeyFrameAnimation.prototype.getPrevKeyWith = function( sid, h, key ) { + var keys = this.data.hierarchy[ h ].keys; + key = key >= 0 ? key : key + keys.length; - var keys = this.data.hierarchy[ h ].keys; - key = key >= 0 ? key : key + keys.length; + for ( ; key >= 0; key -- ) { - for ( ; key >= 0; key -- ) { + if ( keys[ key ].hasTarget( sid ) ) { - if ( keys[ key ].hasTarget( sid ) ) { + return keys[ key ]; - return keys[ key ]; + } } - } + return keys[ keys.length - 1 ]; - return keys[ keys.length - 1 ]; + } }; @@ -30254,6 +30600,7 @@ THREE.KeyFrameAnimation.prototype.getPrevKeyWith = function( sid, h, key ) { /** * @author mrdoob / http://mrdoob.com + * @author willy-vvu / http://willy-vvu.github.io */ THREE.MorphAnimation = function ( mesh ) { @@ -30263,6 +30610,8 @@ THREE.MorphAnimation = function ( mesh ) { this.currentTime = 0; this.duration = 1000; this.loop = true; + this.lastFrame = 0; + this.currentFrame = 0; this.isPlaying = false; @@ -30270,6 +30619,8 @@ THREE.MorphAnimation = function ( mesh ) { THREE.MorphAnimation.prototype = { + constructor: THREE.MorphAnimation, + play: function () { this.isPlaying = true; @@ -30282,45 +30633,40 @@ THREE.MorphAnimation.prototype = { }, - update: ( function () { - - var lastFrame = 0; - var currentFrame = 0; - - return function ( delta ) { - - if ( this.isPlaying === false ) return; + update: function ( delta ) { - this.currentTime += delta; + if ( this.isPlaying === false ) return; - if ( this.loop === true && this.currentTime > this.duration ) { + this.currentTime += delta; - this.currentTime %= this.duration; + if ( this.loop === true && this.currentTime > this.duration ) { - } + this.currentTime %= this.duration; - this.currentTime = Math.min( this.currentTime, this.duration ); + } - var interpolation = this.duration / this.frames; - var frame = Math.floor( this.currentTime / interpolation ); + this.currentTime = Math.min( this.currentTime, this.duration ); - if ( frame != currentFrame ) { + var interpolation = this.duration / this.frames; + var frame = Math.floor( this.currentTime / interpolation ); - this.mesh.morphTargetInfluences[ lastFrame ] = 0; - this.mesh.morphTargetInfluences[ currentFrame ] = 1; - this.mesh.morphTargetInfluences[ frame ] = 0; + var influences = this.mesh.morphTargetInfluences; - lastFrame = currentFrame; - currentFrame = frame; + if ( frame != this.currentFrame ) { - } + influences[ this.lastFrame ] = 0; + influences[ this.currentFrame ] = 1; + influences[ frame ] = 0; - this.mesh.morphTargetInfluences[ frame ] = ( this.currentTime % interpolation ) / interpolation; - this.mesh.morphTargetInfluences[ lastFrame ] = 1 - this.mesh.morphTargetInfluences[ frame ]; + this.lastFrame = this.currentFrame; + this.currentFrame = frame; } - } )() + influences[ frame ] = ( this.currentTime % interpolation ) / interpolation; + influences[ this.lastFrame ] = 1 - influences[ frame ]; + + } }; @@ -30452,6 +30798,7 @@ THREE.BoxGeometry = function ( width, height, depth, widthSegments, heightSegmen }; THREE.BoxGeometry.prototype = Object.create( THREE.Geometry.prototype ); +THREE.BoxGeometry.prototype.constructor = THREE.BoxGeometry; // File:src/extras/geometries/CircleGeometry.js @@ -30513,6 +30860,7 @@ THREE.CircleGeometry = function ( radius, segments, thetaStart, thetaLength ) { }; THREE.CircleGeometry.prototype = Object.create( THREE.Geometry.prototype ); +THREE.CircleGeometry.prototype.constructor = THREE.CircleGeometry; // File:src/extras/geometries/CubeGeometry.js @@ -30523,7 +30871,7 @@ THREE.CircleGeometry.prototype = Object.create( THREE.Geometry.prototype ); THREE.CubeGeometry = function ( width, height, depth, widthSegments, heightSegments, depthSegments ) { - console.warn( 'THREE.CubeGeometry has been renamed to THREE.BoxGeometry.' ); + THREE.warn( 'THREE.CubeGeometry has been renamed to THREE.BoxGeometry.' ); return new THREE.BoxGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ); }; @@ -30534,7 +30882,7 @@ THREE.CubeGeometry = function ( width, height, depth, widthSegments, heightSegme * @author mrdoob / http://mrdoob.com/ */ -THREE.CylinderGeometry = function ( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded ) { +THREE.CylinderGeometry = function ( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) { THREE.Geometry.call( this ); @@ -30546,7 +30894,9 @@ THREE.CylinderGeometry = function ( radiusTop, radiusBottom, height, radialSegme height: height, radialSegments: radialSegments, heightSegments: heightSegments, - openEnded: openEnded + openEnded: openEnded, + thetaStart: thetaStart, + thetaLength: thetaLength }; radiusTop = radiusTop !== undefined ? radiusTop : 20; @@ -30557,6 +30907,8 @@ THREE.CylinderGeometry = function ( radiusTop, radiusBottom, height, radialSegme heightSegments = heightSegments || 1; openEnded = openEnded !== undefined ? openEnded : false; + thetaStart = thetaStart !== undefined ? thetaStart : 0; + thetaLength = thetaLength !== undefined ? thetaLength : 2 * Math.PI; var heightHalf = height / 2; @@ -30575,9 +30927,9 @@ THREE.CylinderGeometry = function ( radiusTop, radiusBottom, height, radialSegme var u = x / radialSegments; var vertex = new THREE.Vector3(); - vertex.x = radius * Math.sin( u * Math.PI * 2 ); + vertex.x = radius * Math.sin( u * thetaLength + thetaStart ); vertex.y = - v * height + heightHalf; - vertex.z = radius * Math.cos( u * Math.PI * 2 ); + vertex.z = radius * Math.cos( u * thetaLength + thetaStart ); this.vertices.push( vertex ); @@ -30673,16 +31025,16 @@ THREE.CylinderGeometry = function ( radiusTop, radiusBottom, height, radialSegme for ( x = 0; x < radialSegments; x ++ ) { - var v1 = vertices[ y ][ x + 1 ]; - var v2 = vertices[ y ][ x ]; + var v1 = vertices[ heightSegments ][ x + 1 ]; + var v2 = vertices[ heightSegments ][ x ]; var v3 = this.vertices.length - 1; var n1 = new THREE.Vector3( 0, - 1, 0 ); var n2 = new THREE.Vector3( 0, - 1, 0 ); var n3 = new THREE.Vector3( 0, - 1, 0 ); - var uv1 = uvs[ y ][ x + 1 ].clone(); - var uv2 = uvs[ y ][ x ].clone(); + var uv1 = uvs[ heightSegments ][ x + 1 ].clone(); + var uv2 = uvs[ heightSegments ][ x ].clone(); var uv3 = new THREE.Vector2( uv2.x, 1 ); this.faces.push( new THREE.Face3( v1, v2, v3, [ n1, n2, n3 ] ) ); @@ -30694,9 +31046,10 @@ THREE.CylinderGeometry = function ( radiusTop, radiusBottom, height, radialSegme this.computeFaceNormals(); -} +}; THREE.CylinderGeometry.prototype = Object.create( THREE.Geometry.prototype ); +THREE.CylinderGeometry.prototype.constructor = THREE.CylinderGeometry; // File:src/extras/geometries/ExtrudeGeometry.js @@ -30754,6 +31107,7 @@ THREE.ExtrudeGeometry = function ( shapes, options ) { }; THREE.ExtrudeGeometry.prototype = Object.create( THREE.Geometry.prototype ); +THREE.ExtrudeGeometry.prototype.constructor = THREE.ExtrudeGeometry; THREE.ExtrudeGeometry.prototype.addShapeList = function ( shapes, options ) { var sl = shapes.length; @@ -30824,7 +31178,6 @@ THREE.ExtrudeGeometry.prototype.addShape = function ( shape, options ) { var ahole, h, hl; // looping of holes var scope = this; - var bevelPoints = []; var shapesOffset = this.vertices.length; @@ -30864,7 +31217,7 @@ THREE.ExtrudeGeometry.prototype.addShape = function ( shape, options ) { var contour = vertices; // vertices has all points but contour has only points of circumference - for ( h = 0, hl = holes.length; h < hl; h ++ ) { + for ( h = 0, hl = holes.length; h < hl; h ++ ) { ahole = holes[ h ]; @@ -30875,7 +31228,7 @@ THREE.ExtrudeGeometry.prototype.addShape = function ( shape, options ) { function scalePt2 ( pt, vec, size ) { - if ( ! vec ) console.log( "die" ); + if ( ! vec ) THREE.error( "THREE.ExtrudeGeometry: vec does not exist" ); return vec.clone().multiplyScalar( size ).add( pt ); @@ -30883,14 +31236,11 @@ THREE.ExtrudeGeometry.prototype.addShape = function ( shape, options ) { var b, bs, t, z, vert, vlen = vertices.length, - face, flen = faces.length, - cont, clen = contour.length; + face, flen = faces.length; // Find directions for point movement - var RAD_TO_DEGREES = 180 / Math.PI; - function getBevelVec( inPt, inPrev, inNext ) { @@ -30993,11 +31343,7 @@ THREE.ExtrudeGeometry.prototype.addShape = function ( shape, options ) { // (j)---(i)---(k) // console.log('i,j,k', i, j , k) - var pt_i = contour[ i ]; - var pt_j = contour[ j ]; - var pt_k = contour[ k ]; - - contourMovements[ i ]= getBevelVec( contour[ i ], contour[ j ], contour[ k ] ); + contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] ); } @@ -31015,7 +31361,7 @@ THREE.ExtrudeGeometry.prototype.addShape = function ( shape, options ) { if ( k === il ) k = 0; // (j)---(i)---(k) - oneHoleMovements[ i ]= getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] ); + oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] ); } @@ -31034,7 +31380,7 @@ THREE.ExtrudeGeometry.prototype.addShape = function ( shape, options ) { z = bevelThickness * ( 1 - t ); //z = bevelThickness * t; - bs = bevelSize * ( Math.sin ( t * Math.PI/2 ) ) ; // curved + bs = bevelSize * ( Math.sin ( t * Math.PI / 2 ) ) ; // curved //bs = bevelSize * t ; // linear // contract shape @@ -31134,7 +31480,7 @@ THREE.ExtrudeGeometry.prototype.addShape = function ( shape, options ) { t = b / bevelSegments; z = bevelThickness * ( 1 - t ); //bs = bevelSize * ( 1-Math.sin ( ( 1 - t ) * Math.PI/2 ) ); - bs = bevelSize * Math.sin ( t * Math.PI/2 ) ; + bs = bevelSize * Math.sin ( t * Math.PI / 2 ) ; // contract shape @@ -31197,7 +31543,7 @@ THREE.ExtrudeGeometry.prototype.addShape = function ( shape, options ) { for ( i = 0; i < flen; i ++ ) { face = faces[ i ]; - f3( face[ 2 ]+ offset, face[ 1 ]+ offset, face[ 0 ] + offset ); + f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset ); } @@ -31244,7 +31590,7 @@ THREE.ExtrudeGeometry.prototype.addShape = function ( shape, options ) { sidewalls( contour, layeroffset ); layeroffset += contour.length; - for ( h = 0, hl = holes.length; h < hl; h ++ ) { + for ( h = 0, hl = holes.length; h < hl; h ++ ) { ahole = holes[ h ]; sidewalls( ahole, layeroffset ); @@ -31261,7 +31607,7 @@ THREE.ExtrudeGeometry.prototype.addShape = function ( shape, options ) { var j, k; i = contour.length; - while ( --i >= 0 ) { + while ( -- i >= 0 ) { j = i; k = i - 1; @@ -31306,7 +31652,7 @@ THREE.ExtrudeGeometry.prototype.addShape = function ( shape, options ) { var uvs = uvgen.generateTopUV( scope, a, b, c ); - scope.faceVertexUvs[ 0 ].push( uvs ); + scope.faceVertexUvs[ 0 ].push( uvs ); } @@ -31317,13 +31663,13 @@ THREE.ExtrudeGeometry.prototype.addShape = function ( shape, options ) { c += shapesOffset; d += shapesOffset; - scope.faces.push( new THREE.Face3( a, b, d, null, null, extrudeMaterial ) ); - scope.faces.push( new THREE.Face3( b, c, d, null, null, extrudeMaterial ) ); + scope.faces.push( new THREE.Face3( a, b, d, null, null, extrudeMaterial ) ); + scope.faces.push( new THREE.Face3( b, c, d, null, null, extrudeMaterial ) ); - var uvs = uvgen.generateSideWallUV( scope, a, b, c, d ); + var uvs = uvgen.generateSideWallUV( scope, a, b, c, d ); - scope.faceVertexUvs[ 0 ].push( [ uvs[ 0 ], uvs[ 1 ], uvs[ 3 ] ] ); - scope.faceVertexUvs[ 0 ].push( [ uvs[ 1 ], uvs[ 2 ], uvs[ 3 ] ] ); + scope.faceVertexUvs[ 0 ].push( [ uvs[ 0 ], uvs[ 1 ], uvs[ 3 ] ] ); + scope.faceVertexUvs[ 0 ].push( [ uvs[ 1 ], uvs[ 2 ], uvs[ 3 ] ] ); } @@ -31407,6 +31753,7 @@ THREE.ShapeGeometry = function ( shapes, options ) { }; THREE.ShapeGeometry.prototype = Object.create( THREE.Geometry.prototype ); +THREE.ShapeGeometry.prototype.constructor = THREE.ShapeGeometry; /** * Add an array of shapes to THREE.ShapeGeometry. @@ -31436,7 +31783,7 @@ THREE.ShapeGeometry.prototype.addShape = function ( shape, options ) { // - var i, l, hole, s; + var i, l, hole; var shapesOffset = this.vertices.length; var shapePoints = shape.extractPoints( curveSegments ); @@ -31485,7 +31832,6 @@ THREE.ShapeGeometry.prototype.addShape = function ( shape, options ) { var vert, vlen = vertices.length; var face, flen = faces.length; - var cont, clen = contour.length; for ( i = 0; i < vlen; i ++ ) { @@ -31617,6 +31963,7 @@ THREE.LatheGeometry = function ( points, segments, phiStart, phiLength ) { }; THREE.LatheGeometry.prototype = Object.create( THREE.Geometry.prototype ); +THREE.LatheGeometry.prototype.constructor = THREE.LatheGeometry; // File:src/extras/geometries/PlaneGeometry.js @@ -31645,6 +31992,7 @@ THREE.PlaneGeometry = function ( width, height, widthSegments, heightSegments ) }; THREE.PlaneGeometry.prototype = Object.create( THREE.Geometry.prototype ); +THREE.PlaneGeometry.prototype.constructor = THREE.PlaneGeometry; // File:src/extras/geometries/PlaneBufferGeometry.js @@ -31743,6 +32091,7 @@ THREE.PlaneBufferGeometry = function ( width, height, widthSegments, heightSegme }; THREE.PlaneBufferGeometry.prototype = Object.create( THREE.BufferGeometry.prototype ); +THREE.PlaneBufferGeometry.prototype.constructor = THREE.PlaneBufferGeometry; // File:src/extras/geometries/RingGeometry.js @@ -31827,6 +32176,7 @@ THREE.RingGeometry = function ( innerRadius, outerRadius, thetaSegments, phiSegm }; THREE.RingGeometry.prototype = Object.create( THREE.Geometry.prototype ); +THREE.RingGeometry.prototype.constructor = THREE.RingGeometry; // File:src/extras/geometries/SphereGeometry.js @@ -31943,6 +32293,7 @@ THREE.SphereGeometry = function ( radius, widthSegments, heightSegments, phiStar }; THREE.SphereGeometry.prototype = Object.create( THREE.Geometry.prototype ); +THREE.SphereGeometry.prototype.constructor = THREE.SphereGeometry; // File:src/extras/geometries/TextGeometry.js @@ -32007,6 +32358,7 @@ THREE.TextGeometry = function ( text, parameters ) { }; THREE.TextGeometry.prototype = Object.create( THREE.ExtrudeGeometry.prototype ); +THREE.TextGeometry.prototype.constructor = THREE.TextGeometry; // File:src/extras/geometries/TorusGeometry.js @@ -32088,6 +32440,7 @@ THREE.TorusGeometry = function ( radius, tube, radialSegments, tubularSegments, }; THREE.TorusGeometry.prototype = Object.create( THREE.Geometry.prototype ); +THREE.TorusGeometry.prototype.constructor = THREE.TorusGeometry; // File:src/extras/geometries/TorusKnotGeometry.js @@ -32203,6 +32556,7 @@ THREE.TorusKnotGeometry = function ( radius, tube, radialSegments, tubularSegmen }; THREE.TorusKnotGeometry.prototype = Object.create( THREE.Geometry.prototype ); +THREE.TorusKnotGeometry.prototype.constructor = THREE.TorusKnotGeometry; // File:src/extras/geometries/TubeGeometry.js @@ -32210,6 +32564,7 @@ THREE.TorusKnotGeometry.prototype = Object.create( THREE.Geometry.prototype ); * @author WestLangley / https://github.com/WestLangley * @author zz85 / https://github.com/zz85 * @author miningold / https://github.com/miningold + * @author jonobr1 / https://github.com/jonobr1 * * Modified from the TorusKnotGeometry by @oosmoxiecode * @@ -32219,7 +32574,7 @@ THREE.TorusKnotGeometry.prototype = Object.create( THREE.Geometry.prototype ); * http://www.cs.indiana.edu/pub/techreports/TR425.pdf */ -THREE.TubeGeometry = function ( path, segments, radius, radialSegments, closed ) { +THREE.TubeGeometry = function ( path, segments, radius, radialSegments, closed, taper ) { THREE.Geometry.call( this ); @@ -32237,6 +32592,7 @@ THREE.TubeGeometry = function ( path, segments, radius, radialSegments, closed ) radius = radius || 1; radialSegments = radialSegments || 8; closed = closed || false; + taper = taper || THREE.TubeGeometry.NoTaper; var grid = []; @@ -32248,9 +32604,7 @@ THREE.TubeGeometry = function ( path, segments, radius, radialSegments, closed ) numpoints = segments + 1, - x, y, z, - tx, ty, tz, - u, v, + u, v, r, cx, cy, pos, pos2 = new THREE.Vector3(), @@ -32289,12 +32643,14 @@ THREE.TubeGeometry = function ( path, segments, radius, radialSegments, closed ) normal = normals[ i ]; binormal = binormals[ i ]; + r = radius * taper( u ); + for ( j = 0; j < radialSegments; j ++ ) { v = j / radialSegments * 2 * Math.PI; - cx = - radius * Math.cos( v ); // TODO: Hack: Negating it so it faces outside. - cy = radius * Math.sin( v ); + cx = - r * Math.cos( v ); // TODO: Hack: Negating it so it faces outside. + cy = r * Math.sin( v ); pos2.copy( pos ); pos2.x += cx * normal.x + cy * binormal.x; @@ -32341,14 +32697,24 @@ THREE.TubeGeometry = function ( path, segments, radius, radialSegments, closed ) }; THREE.TubeGeometry.prototype = Object.create( THREE.Geometry.prototype ); +THREE.TubeGeometry.prototype.constructor = THREE.TubeGeometry; + +THREE.TubeGeometry.NoTaper = function ( u ) { + return 1; + +}; + +THREE.TubeGeometry.SinusoidalTaper = function ( u ) { + + return Math.sin( Math.PI * u ); + +}; // For computing of Frenet frames, exposing the tangents, normals and binormals the spline THREE.TubeGeometry.FrenetFrames = function ( path, segments, closed ) { - var tangent = new THREE.Vector3(), - normal = new THREE.Vector3(), - binormal = new THREE.Vector3(), + var normal = new THREE.Vector3(), tangents = [], normals = [], @@ -32363,7 +32729,7 @@ THREE.TubeGeometry.FrenetFrames = function ( path, segments, closed ) { smallest, tx, ty, tz, - i, u, v; + i, u; // expose internals @@ -32444,17 +32810,17 @@ THREE.TubeGeometry.FrenetFrames = function ( path, segments, closed ) { for ( i = 1; i < numpoints; i ++ ) { - normals[ i ] = normals[ i-1 ].clone(); + normals[ i ] = normals[ i - 1 ].clone(); - binormals[ i ] = binormals[ i-1 ].clone(); + binormals[ i ] = binormals[ i - 1 ].clone(); - vec.crossVectors( tangents[ i-1 ], tangents[ i ] ); + vec.crossVectors( tangents[ i - 1 ], tangents[ i ] ); if ( vec.length() > epsilon ) { vec.normalize(); - theta = Math.acos( THREE.Math.clamp( tangents[ i-1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors + theta = Math.acos( THREE.Math.clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) ); @@ -32469,10 +32835,10 @@ THREE.TubeGeometry.FrenetFrames = function ( path, segments, closed ) { if ( closed ) { - theta = Math.acos( THREE.Math.clamp( normals[ 0 ].dot( normals[ numpoints-1 ] ), - 1, 1 ) ); + theta = Math.acos( THREE.Math.clamp( normals[ 0 ].dot( normals[ numpoints - 1 ] ), - 1, 1 ) ); theta /= ( numpoints - 1 ); - if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ numpoints-1 ] ) ) > 0 ) { + if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ numpoints - 1 ] ) ) > 0 ) { theta = - theta; @@ -32521,7 +32887,7 @@ THREE.PolyhedronGeometry = function ( vertices, indices, radius, detail ) { } - var midpoints = [], p = this.vertices; + var p = this.vertices; var faces = []; @@ -32629,7 +32995,6 @@ THREE.PolyhedronGeometry = function ( vertices, indices, radius, detail ) { function subdivide( face, detail ) { var cols = Math.pow(2, detail); - var cells = Math.pow(4, detail); var a = prepare( that.vertices[ face.a ] ); var b = prepare( that.vertices[ face.b ] ); var c = prepare( that.vertices[ face.c ] ); @@ -32726,6 +33091,7 @@ THREE.PolyhedronGeometry = function ( vertices, indices, radius, detail ) { }; THREE.PolyhedronGeometry.prototype = Object.create( THREE.Geometry.prototype ); +THREE.PolyhedronGeometry.prototype.constructor = THREE.PolyhedronGeometry; // File:src/extras/geometries/DodecahedronGeometry.js @@ -32784,6 +33150,7 @@ THREE.DodecahedronGeometry = function ( radius, detail ) { }; THREE.DodecahedronGeometry.prototype = Object.create( THREE.Geometry.prototype ); +THREE.DodecahedronGeometry.prototype.constructor = THREE.DodecahedronGeometry; // File:src/extras/geometries/IcosahedronGeometry.js @@ -32819,6 +33186,7 @@ THREE.IcosahedronGeometry = function ( radius, detail ) { }; THREE.IcosahedronGeometry.prototype = Object.create( THREE.Geometry.prototype ); +THREE.IcosahedronGeometry.prototype.constructor = THREE.IcosahedronGeometry; // File:src/extras/geometries/OctahedronGeometry.js @@ -32852,6 +33220,7 @@ THREE.OctahedronGeometry = function ( radius, detail ) { }; THREE.OctahedronGeometry.prototype = Object.create( THREE.Geometry.prototype ); +THREE.OctahedronGeometry.prototype.constructor = THREE.OctahedronGeometry; // File:src/extras/geometries/TetrahedronGeometry.js @@ -32881,6 +33250,7 @@ THREE.TetrahedronGeometry = function ( radius, detail ) { }; THREE.TetrahedronGeometry.prototype = Object.create( THREE.Geometry.prototype ); +THREE.TetrahedronGeometry.prototype.constructor = THREE.TetrahedronGeometry; // File:src/extras/geometries/ParametricGeometry.js @@ -32909,10 +33279,9 @@ THREE.ParametricGeometry = function ( func, slices, stacks ) { var faces = this.faces; var uvs = this.faceVertexUvs[ 0 ]; - var i, il, j, p; + var i, j, p; var u, v; - var stackCount = stacks + 1; var sliceCount = slices + 1; for ( i = 0; i <= stacks; i ++ ) { @@ -32968,6 +33337,7 @@ THREE.ParametricGeometry = function ( func, slices, stacks ) { }; THREE.ParametricGeometry.prototype = Object.create( THREE.Geometry.prototype ); +THREE.ParametricGeometry.prototype.constructor = THREE.ParametricGeometry; // File:src/extras/helpers/AxisHelper.js @@ -33003,6 +33373,7 @@ THREE.AxisHelper = function ( size ) { }; THREE.AxisHelper.prototype = Object.create( THREE.Line.prototype ); +THREE.AxisHelper.prototype.constructor = THREE.AxisHelper; // File:src/extras/helpers/ArrowHelper.js @@ -33059,6 +33430,7 @@ THREE.ArrowHelper = ( function () { }() ); THREE.ArrowHelper.prototype = Object.create( THREE.Object3D.prototype ); +THREE.ArrowHelper.prototype.constructor = THREE.ArrowHelper; THREE.ArrowHelper.prototype.setDirection = ( function () { @@ -33096,7 +33468,7 @@ THREE.ArrowHelper.prototype.setLength = function ( length, headLength, headWidth if ( headLength === undefined ) headLength = 0.2 * length; if ( headWidth === undefined ) headWidth = 0.2 * headLength; - this.line.scale.set( 1, length, 1 ); + this.line.scale.set( 1, length - headLength, 1 ); this.line.updateMatrix(); this.cone.scale.set( headWidth, headLength, headWidth ); @@ -33134,6 +33506,7 @@ THREE.BoxHelper = function ( object ) { }; THREE.BoxHelper.prototype = Object.create( THREE.Line.prototype ); +THREE.BoxHelper.prototype.constructor = THREE.BoxHelper; THREE.BoxHelper.prototype.update = function ( object ) { @@ -33236,6 +33609,7 @@ THREE.BoundingBoxHelper = function ( object, hex ) { }; THREE.BoundingBoxHelper.prototype = Object.create( THREE.Mesh.prototype ); +THREE.BoundingBoxHelper.prototype.constructor = THREE.BoundingBoxHelper; THREE.BoundingBoxHelper.prototype.update = function () { @@ -33355,6 +33729,7 @@ THREE.CameraHelper = function ( camera ) { }; THREE.CameraHelper.prototype = Object.create( THREE.Line.prototype ); +THREE.CameraHelper.prototype.constructor = THREE.CameraHelper; THREE.CameraHelper.prototype.update = function () { @@ -33488,6 +33863,7 @@ THREE.DirectionalLightHelper = function ( light, size ) { }; THREE.DirectionalLightHelper.prototype = Object.create( THREE.Object3D.prototype ); +THREE.DirectionalLightHelper.prototype.constructor = THREE.DirectionalLightHelper; THREE.DirectionalLightHelper.prototype.dispose = function () { @@ -33524,11 +33900,20 @@ THREE.DirectionalLightHelper.prototype.update = function () { /** * @author WestLangley / http://github.com/WestLangley + * @param object THREE.Mesh whose geometry will be used + * @param hex line color + * @param thresholdAngle the minimim angle (in degrees), + * between the face normals of adjacent faces, + * that is required to render an edge. A value of 10 means + * an edge is only rendered if the angle is at least 10 degrees. */ -THREE.EdgesHelper = function ( object, hex ) { +THREE.EdgesHelper = function ( object, hex, thresholdAngle ) { var color = ( hex !== undefined ) ? hex : 0xffffff; + thresholdAngle = ( thresholdAngle !== undefined ) ? thresholdAngle : 1; + + var thresholdDot = Math.cos( THREE.Math.degToRad( thresholdAngle ) ); var edge = [ 0, 0 ], hash = {}; var sortFunction = function ( a, b ) { return a - b }; @@ -33536,7 +33921,18 @@ THREE.EdgesHelper = function ( object, hex ) { var keys = [ 'a', 'b', 'c' ]; var geometry = new THREE.BufferGeometry(); - var geometry2 = object.geometry.clone(); + var geometry2; + + if ( object.geometry instanceof THREE.BufferGeometry ) { + + geometry2 = new THREE.Geometry(); + geometry2.fromBufferGeometry( object.geometry ); + + } else { + + geometry2 = object.geometry.clone(); + + } geometry2.mergeVertices(); geometry2.computeFaceNormals(); @@ -33580,7 +33976,7 @@ THREE.EdgesHelper = function ( object, hex ) { var h = hash[ key ]; - if ( h.face2 === undefined || faces[ h.face1 ].normal.dot( faces[ h.face2 ].normal ) < 0.9999 ) { // hardwired const OK + if ( h.face2 === undefined || faces[ h.face1 ].normal.dot( faces[ h.face2 ].normal ) <= thresholdDot ) { var vertex = vertices[ h.vert1 ]; coords[ index ++ ] = vertex.x; @@ -33606,6 +34002,7 @@ THREE.EdgesHelper = function ( object, hex ) { }; THREE.EdgesHelper.prototype = Object.create( THREE.Line.prototype ); +THREE.EdgesHelper.prototype.constructor = THREE.EdgesHelper; // File:src/extras/helpers/FaceNormalsHelper.js @@ -33645,6 +34042,7 @@ THREE.FaceNormalsHelper = function ( object, size, hex, linewidth ) { }; THREE.FaceNormalsHelper.prototype = Object.create( THREE.Line.prototype ); +THREE.FaceNormalsHelper.prototype.constructor = THREE.FaceNormalsHelper; THREE.FaceNormalsHelper.prototype.update = function () { @@ -33716,6 +34114,7 @@ THREE.GridHelper = function ( size, step ) { }; THREE.GridHelper.prototype = Object.create( THREE.Line.prototype ); +THREE.GridHelper.prototype.constructor = THREE.GridHelper; THREE.GridHelper.prototype.setColors = function( colorCenterLine, colorGrid ) { @@ -33733,7 +34132,7 @@ THREE.GridHelper.prototype.setColors = function( colorCenterLine, colorGrid ) { * @author mrdoob / http://mrdoob.com/ */ -THREE.HemisphereLightHelper = function ( light, sphereSize, arrowLength, domeSize ) { +THREE.HemisphereLightHelper = function ( light, sphereSize ) { THREE.Object3D.call( this ); @@ -33764,6 +34163,7 @@ THREE.HemisphereLightHelper = function ( light, sphereSize, arrowLength, domeSiz }; THREE.HemisphereLightHelper.prototype = Object.create( THREE.Object3D.prototype ); +THREE.HemisphereLightHelper.prototype.constructor = THREE.HemisphereLightHelper; THREE.HemisphereLightHelper.prototype.dispose = function () { this.lightSphere.geometry.dispose(); @@ -33832,6 +34232,7 @@ THREE.PointLightHelper = function ( light, sphereSize ) { }; THREE.PointLightHelper.prototype = Object.create( THREE.Mesh.prototype ); +THREE.PointLightHelper.prototype.constructor = THREE.PointLightHelper; THREE.PointLightHelper.prototype.dispose = function () { @@ -33905,6 +34306,7 @@ THREE.SkeletonHelper = function ( object ) { THREE.SkeletonHelper.prototype = Object.create( THREE.Line.prototype ); +THREE.SkeletonHelper.prototype.constructor = THREE.SkeletonHelper; THREE.SkeletonHelper.prototype.getBoneList = function( object ) { @@ -33993,6 +34395,7 @@ THREE.SpotLightHelper = function ( light ) { }; THREE.SpotLightHelper.prototype = Object.create( THREE.Object3D.prototype ); +THREE.SpotLightHelper.prototype.constructor = THREE.SpotLightHelper; THREE.SpotLightHelper.prototype.dispose = function () { this.cone.geometry.dispose(); @@ -34041,8 +34444,6 @@ THREE.VertexNormalsHelper = function ( object, size, hex, linewidth ) { var geometry = new THREE.Geometry(); - var vertices = object.geometry.vertices; - var faces = object.geometry.faces; for ( var i = 0, l = faces.length; i < l; i ++ ) { @@ -34068,6 +34469,7 @@ THREE.VertexNormalsHelper = function ( object, size, hex, linewidth ) { }; THREE.VertexNormalsHelper.prototype = Object.create( THREE.Line.prototype ); +THREE.VertexNormalsHelper.prototype.constructor = THREE.VertexNormalsHelper; THREE.VertexNormalsHelper.prototype.update = ( function ( object ) { @@ -34143,8 +34545,6 @@ THREE.VertexTangentsHelper = function ( object, size, hex, linewidth ) { var geometry = new THREE.Geometry(); - var vertices = object.geometry.vertices; - var faces = object.geometry.faces; for ( var i = 0, l = faces.length; i < l; i ++ ) { @@ -34169,6 +34569,7 @@ THREE.VertexTangentsHelper = function ( object, size, hex, linewidth ) { }; THREE.VertexTangentsHelper.prototype = Object.create( THREE.Line.prototype ); +THREE.VertexTangentsHelper.prototype.constructor = THREE.VertexTangentsHelper; THREE.VertexTangentsHelper.prototype.update = ( function ( object ) { @@ -34401,6 +34802,7 @@ THREE.WireframeHelper = function ( object, hex ) { }; THREE.WireframeHelper.prototype = Object.create( THREE.Line.prototype ); +THREE.WireframeHelper.prototype.constructor = THREE.WireframeHelper; // File:src/extras/objects/ImmediateRenderObject.js @@ -34417,6 +34819,7 @@ THREE.ImmediateRenderObject = function () { }; THREE.ImmediateRenderObject.prototype = Object.create( THREE.Object3D.prototype ); +THREE.ImmediateRenderObject.prototype.constructor = THREE.ImmediateRenderObject; // File:src/extras/objects/MorphBlendMesh.js @@ -34449,6 +34852,7 @@ THREE.MorphBlendMesh = function( geometry, material ) { }; THREE.MorphBlendMesh.prototype = Object.create( THREE.Mesh.prototype ); +THREE.MorphBlendMesh.prototype.constructor = THREE.MorphBlendMesh; THREE.MorphBlendMesh.prototype.createAnimation = function ( name, start, end, fps ) { @@ -34497,7 +34901,6 @@ THREE.MorphBlendMesh.prototype.autoCreateAnimations = function ( fps ) { if ( chunks && chunks.length > 1 ) { var name = chunks[ 1 ]; - var num = chunks[ 2 ]; if ( ! frameRanges[ name ] ) frameRanges[ name ] = { start: Infinity, end: - Infinity }; @@ -34642,7 +35045,7 @@ THREE.MorphBlendMesh.prototype.playAnimation = function ( name ) { } else { - console.warn( "animation[" + name + "] undefined" ); + THREE.warn( "THREE.MorphBlendMesh: animation[" + name + "] undefined in .playAnimation()" ); } diff --git a/seriously.js b/seriously.js index cc699a8..8fa213b 100755 --- a/seriously.js +++ b/seriously.js @@ -20,7 +20,7 @@ // Browser globals root.Seriously = factory(root); } -}(this, function (window) { +}(window, function (window) { 'use strict'; var document = window.document, @@ -31,7 +31,7 @@ */ testContext, - colorElement, + colorCtx, incompatibility, seriousEffects = {}, seriousTransforms = {}, @@ -78,9 +78,34 @@ orange: [1, 165 / 255, 0, 1] }, + colorRegex = /^(rgb|hsl)a?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*(\d+(\.\d*)?)\s*)?\)/i, + hexColorRegex = /^#(([0-9a-fA-F]{3,8}))/, + vectorFields = ['x', 'y', 'z', 'w'], colorFields = ['r', 'g', 'b', 'a'], + outputRenderOptions = { + srcRGB: 0x0302, //SRC_ALPHA + dstRGB: 0x0303, //ONE_MINUS_SRC_ALPHA + srcAlpha: 0x01, //ONE + dstAlpha: 0x0303 //ONE_MINUS_SRC_ALPHA + }, + + shaderDebugConstants = [ + 'MAX_COMBINED_TEXTURE_IMAGE_UNITS', + 'MAX_FRAGMENT_UNIFORM_VECTORS', + 'MAX_TEXTURE_IMAGE_UNITS', + 'MAX_VARYING_VECTORS', + 'MAX_VERTEX_ATTRIBS', + 'MAX_VERTEX_TEXTURE_IMAGE_UNITS', + 'MAX_VERTEX_UNIFORM_VECTORS' + ], + + shaderNameRegex = /^[\t ]*#define[\t ]+SHADER_NAME\s+([^$\n\r]+)/i, + + baseVertexShader, + baseFragmentShader, + /* utility functions */ @@ -290,7 +315,7 @@ 'id', 'incompatible', 'isDestroyed', - 'isEffect',, + 'isEffect', 'isNode', 'isSource', 'isTarget', @@ -306,6 +331,7 @@ function getElement(input, tags) { var element, tag; + if (typeof input === 'string') { //element = document.getElementById(input) || document.getElementsByTagName(input)[0]; element = document.querySelector(input); @@ -381,6 +407,34 @@ }; } + /* + Like instanceof, but it will work on elements that come from different windows (e.g. iframes) + + We do not use this for constructors defined in this script. + */ + function isInstance(obj, proto) { + if (!proto) { + proto = 'HTMLElement'; + } + + if (obj instanceof window[proto]) { + return true; + } + + if (!obj || typeof obj !== 'object') { + return false; + } + + while (obj) { + obj = Object.getPrototypeOf(obj); + if (obj && obj.constructor.name === proto) { + return true; + } + } + + return false; + } + //http://www.w3.org/TR/css3-color/#hsl-color function hslToRgb(h, s, l, a, out) { function hueToRgb(m1, m2, h) { @@ -670,6 +724,10 @@ input.step = 0; } + if (isNaN(input.mod)) { + input.mod = 0; + } + if (input.type === 'enum') { /* Normalize options to make validation easy @@ -854,6 +912,7 @@ programError = '', shaderError, i, l, + shaderNameRegexMatch, obj; function compileShader(source, fragment) { @@ -972,7 +1031,19 @@ gl.deleteProgram(program); gl.deleteShader(vertexShader); gl.deleteShader(fragmentShader); - throw new Error('Could not initialise shader: ' + programError); + + shaderNameRegexMatch = shaderNameRegex.exec(vertexShaderSource) || + shaderNameRegex.exec(fragmentShaderSource); + + if (shaderNameRegexMatch) { + programError = 'Shader = ' + shaderNameRegexMatch[1] + '\n' + programError; + } + + shaderDebugConstants.forEach(function (c) { + programError += '\n' + c + ': ' + gl.getParameter(gl[c]); + }); + + throw new Error('Could not initialize shader:\n' + programError); } gl.useProgram(program); @@ -985,7 +1056,7 @@ info: gl.getActiveUniform(program, i) }; - obj.name = obj.info.name; + obj.name = obj.info.name.replace(/\[0\]$/, ''); obj.loc = gl.getUniformLocation(program, obj.name); obj.set = makeShaderSetter(obj.info, obj.loc); obj.get = makeShaderGetter(obj.loc); @@ -1070,7 +1141,6 @@ rectangleModel, commonShaders = {}, baseShader, - baseVertexShader, baseFragmentShader, Node, SourceNode, EffectNode, TransformNode, TargetNode, Effect, Source, Transform, Target, auto = false, @@ -1152,7 +1222,10 @@ rectangleModel = buildRectangleModel(gl); - baseShader = new ShaderProgram(gl, baseVertexShader, baseFragmentShader); + baseShader = new ShaderProgram( + gl, + '#define SHADER_NAME seriously.base\n' + baseVertexShader, '#define SHADER_NAME seriously.base\n' + baseFragmentShader + ); for (i = 0; i < effects.length; i++) { node = effects[i]; @@ -1190,14 +1263,14 @@ //todo: if too many webglcontextlost events fired in too short a time, abort //todo: consider allowing "manual" control of restoring context - if (target instanceof WebGLFramebuffer) { + if (isInstance(target, 'WebGLFramebuffer')) { Seriously.logger.error('Unable to restore target built on WebGLFramebuffer'); return; } context = getWebGlContext(target, { alpha: true, - premultipliedAlpha: false, + premultipliedAlpha: true, preserveDrawingBuffer: true, stencil: true, debugContext: primaryTarget.debugContext @@ -1275,6 +1348,9 @@ node.texture = null; if (node.shader && node.shader.destroy) { node.shader.destroy(); + if (node.effect.commonShader) { + delete commonShaders[node.hook]; + } } node.shaderDirty = true; node.shader = null; @@ -1352,7 +1428,7 @@ forcing all dependent nodes to render */ function renderDaemon(now) { - var i, node, media, + var i, node, keepRunning = false; rafId = 0; @@ -1369,7 +1445,6 @@ for (i = 0; i < sources.length; i++) { node = sources[i]; - media = node.source; if (node.dirty || node.checkDirty && node.checkDirty()) { node.dirty = false; @@ -1473,7 +1548,7 @@ value = uniforms[name]; shaderUniform = shader.uniforms[name]; if (shaderUniform) { - if (value instanceof WebGLTexture) { + if (isInstance(value, 'WebGLTexture')) { nodeGl.activeTexture(nodeGl.TEXTURE0 + numTextures); nodeGl.bindTexture(nodeGl.TEXTURE_2D, value); shaderUniform.set(numTextures); @@ -1673,7 +1748,7 @@ //todo: figure out formats and types if (dest === undefined) { dest = new Uint8Array(width * height * 4); - } else if (!dest instanceof Uint8Array) { + } else if (!(isInstance(dest, 'Uint8Array'))) { throw new Error('Incompatible array type'); } @@ -1838,7 +1913,7 @@ //todo: color? date/time? } - if (input instanceof HTMLInputElement || input instanceof HTMLSelectElement) { + if (isInstance(input, 'HTMLInputElement') || isInstance(input, 'HTMLSelectElement')) { value = input.value; if (lookup && lookup.element !== input) { @@ -2035,6 +2110,7 @@ result.min = input.min; result.max = input.max; result.step = input.step; + result.mod = input.mod; } else if (input.type === 'enum') { //make a copy result.options = extend({}, input.options); @@ -2190,7 +2266,8 @@ } }; - extend(EffectNode, Node); + EffectNode.prototype = Object.create(Node.prototype); + EffectNode.prototype.constructor = EffectNode; EffectNode.prototype.initialize = function () { if (!this.initialized) { @@ -2310,7 +2387,19 @@ }; EffectNode.prototype.buildShader = function () { - var shader, effect = this.effect; + var shader, + effect = this.effect, + me = this; + + function addShaderName(shaderSrc) { + if (shaderNameRegex.test(shaderSrc)) { + return shaderSrc; + } + + return '#define SHADER_NAME seriously.' + me.hook + '\n' + + shaderSrc; + } + if (this.shaderDirty) { if (effect.commonShader && commonShaders[this.hook]) { if (!this.shader) { @@ -2329,7 +2418,11 @@ if (shader instanceof ShaderProgram) { this.shader = shader; } else if (shader && shader.vertex && shader.fragment) { - this.shader = new ShaderProgram(gl, shader.vertex, shader.fragment); + this.shader = new ShaderProgram( + gl, + addShaderName(shader.vertex), + addShaderName(shader.fragment) + ); } else { this.shader = baseShader; } @@ -3144,7 +3237,7 @@ } //todo: could probably stand to re-work and re-indent this whole block now that we have plugins - if (!plugin && source instanceof HTMLElement) { + if (!plugin && isInstance(source)) { if (source.tagName === 'CANVAS') { this.width = source.width; this.height = source.height; @@ -3179,7 +3272,7 @@ this.hook = 'image'; this.compare = compareSource; } - } else if (!plugin && source instanceof WebGLTexture) { + } else if (!plugin && isInstance(source, 'WebGLTexture')) { if (gl && !gl.isTexture(source)) { throw new Error('Not a valid WebGL texture.'); } @@ -3261,7 +3354,8 @@ } }; - extend(SourceNode, Node); + SourceNode.prototype = Object.create(Node.prototype); + SourceNode.prototype.constructor = SourceNode; SourceNode.prototype.initialize = function () { var texture; @@ -3640,7 +3734,7 @@ } opts = options || {}; - flip = opts.flip === undefined ? true : opts.flip + flip = opts.flip === undefined ? true : opts.flip; width = parseInt(opts.width, 10); height = parseInt(opts.height, 10); debugContext = opts.debugContext; @@ -3652,16 +3746,16 @@ this.renderToTexture = opts.renderToTexture; - if (target instanceof WebGLFramebuffer) { + if (isInstance(target, 'WebGLFramebuffer')) { frameBuffer = target; - if (opts instanceof HTMLCanvasElement) { + if (isInstance(opts, 'HTMLCanvasElement')) { target = opts; - } else if (opts instanceof WebGLRenderingContext) { + } else if (isInstance(opts, 'WebGLRenderingContext')) { target = opts.canvas; - } else if (opts.canvas instanceof HTMLCanvasElement) { + } else if (isInstance(opts.canvas, 'HTMLCanvasElement')) { target = opts.canvas; - } else if (opts.context instanceof WebGLRenderingContext) { + } else if (isInstance(opts.context, 'WebGLRenderingContext')) { target = opts.context.canvas; } else { //todo: search all canvases for matching contexts? @@ -3669,7 +3763,7 @@ } } - if (target instanceof HTMLElement && target.tagName === 'CANVAS') { + if (isInstance(target, 'HTMLCanvasElement')) { width = target.width; height = target.height; @@ -3678,7 +3772,7 @@ triedWebGl = true; context = getWebGlContext(target, { alpha: true, - premultipliedAlpha: false, + premultipliedAlpha: true, preserveDrawingBuffer: true, stencil: true, debugContext: debugContext @@ -3801,7 +3895,8 @@ targets.push(this); }; - extend(TargetNode, Node); + TargetNode.prototype = Object.create(Node.prototype); + TargetNode.prototype.constructor = TargetNode; TargetNode.prototype.setSource = function (source) { var newSource; @@ -3842,7 +3937,7 @@ TargetNode.prototype.resize = function () { //if target is a canvas, reset size to canvas size - if (this.target instanceof HTMLCanvasElement) { + if (isInstance(this.target, 'HTMLCanvasElement')) { if (this.width !== this.target.width || this.height !== this.target.height) { this.target.width = this.width; this.target.height = this.height; @@ -3916,7 +4011,7 @@ this.transformDirty = false; } - draw(baseShader, rectangleModel, this.uniforms, this.frameBuffer.frameBuffer, this); + draw(baseShader, rectangleModel, this.uniforms, this.frameBuffer.frameBuffer, this, outputRenderOptions); this.emit('render'); this.dirty = false; @@ -3965,7 +4060,7 @@ } this.uniforms.source = this.texture; - draw(this.shader, this.model, this.uniforms, null, this); + draw(this.shader, this.model, this.uniforms, null, this, outputRenderOptions); this.dirty = false; } @@ -4044,7 +4139,7 @@ } } - if (input instanceof HTMLInputElement || input instanceof HTMLSelectElement) { + if (isInstance(input, 'HTMLInputElement') || isInstance(input, 'HTMLSelectElement')) { value = input.value; if (lookup && lookup.element !== input) { @@ -4181,7 +4276,7 @@ // attach methods for (key in me.methods) { if (me.methods.hasOwnProperty(key)) { - this[key] = makeMethod(me.methods[key].bind(me)); + this[key] = makeMethod(me.methods[key]); } } @@ -4224,6 +4319,7 @@ result.min = input.min; result.max = input.max; result.step = input.step; + result.mod = input.mod; } else if (input.type === 'enum') { //make a copy result.options = extend({}, input.options); @@ -4380,6 +4476,9 @@ allTransformsByHook[hook].push(this); }; + TransformNode.prototype = Object.create(Node.prototype); + TransformNode.prototype.constructor = TransformNode; + TransformNode.prototype.setDirty = function () { this.renderDirty = true; Node.prototype.setDirty.call(this); @@ -4620,7 +4719,7 @@ if (dest === undefined) { dest = new Uint8Array(width * height * 4); - } else if (!dest instanceof Uint8Array) { + } else if (!(isInstance(dest, 'Uint8Array'))) { throw new Error('Incompatible array type'); } @@ -4707,7 +4806,7 @@ Initialize Seriously object based on options */ - if (options instanceof HTMLCanvasElement) { + if (isInstance(options, 'HTMLCanvasElement')) { options = { canvas: options }; @@ -4761,7 +4860,6 @@ this.target = function (hook, target, options) { var targetNode, element, - hook, i; if (hook && typeof hook === 'string' && !seriousTargets[hook]) { @@ -4877,8 +4975,8 @@ descriptor; while (nodes.length) { - node = nodes.shift(); - node.destroy(); + node = nodes[0]; + node.pub.destroy(); } for (i in this) { @@ -4893,8 +4991,6 @@ } } - baseFragmentShader = null; - baseVertexShader = null; seriously = null; //todo: do we really need to allocate new arrays here? @@ -4994,48 +5090,6 @@ //todo: load, save, find - baseVertexShader = [ - 'precision mediump float;', - - 'attribute vec4 position;', - 'attribute vec2 texCoord;', - - 'uniform vec2 resolution;', - 'uniform mat4 transform;', - - 'varying vec2 vTexCoord;', - - 'void main(void) {', - // first convert to screen space - ' vec4 screenPosition = vec4(position.xy * resolution / 2.0, position.z, position.w);', - ' screenPosition = transform * screenPosition;', - - // convert back to OpenGL coords - ' gl_Position.xy = screenPosition.xy * 2.0 / resolution;', - ' gl_Position.z = screenPosition.z * 2.0 / (resolution.x / resolution.y);', - ' gl_Position.w = screenPosition.w;', - ' vTexCoord = texCoord;', - '}\n' - ].join('\n'); - - baseFragmentShader = [ - 'precision mediump float;', - - 'varying vec2 vTexCoord;', - - 'uniform sampler2D source;', - - 'void main(void) {', - /* - ' if (any(lessThan(vTexCoord, vec2(0.0))) || any(greaterThanEqual(vTexCoord, vec2(1.0)))) {', - ' gl_FragColor = vec4(0.0);', - ' } else {', - */ - ' gl_FragColor = texture2D(source, vTexCoord);', - //' }', - '}' - ].join('\n'); - this.defaults(options.defaults); } @@ -5339,35 +5393,39 @@ //todo: validators should not allocate new objects/arrays if input is valid Seriously.inputValidators = { color: function (value, input, defaultValue, oldValue) { - var s, a, i, computed, bg; + var s, + a, + match, + i; a = oldValue || []; if (typeof value === 'string') { //todo: support percentages, decimals - s = (/^(rgb|hsl)a?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*(\d+(\.\d*)?)\s*)?\)/i).exec(value); - if (s && s.length) { - if (s.length < 3) { + match = colorRegex.exec(value); + if (match && match.length) { + if (match.length < 3) { a[0] = a[1] = a[2] = a[3] = 0; return a; } a[3] = 1; for (i = 0; i < 3; i++) { - a[i] = parseFloat(s[i+2]) / 255; + a[i] = parseFloat(match[i + 2]) / 255; } - if (!isNaN(s[6])) { - a[3] = parseFloat(s[6]); + if (!isNaN(match[6])) { + a[3] = parseFloat(match[6]); } - if (s[1].toLowerCase() === 'hsl') { + if (match[1].toLowerCase() === 'hsl') { return hslToRgb(a[0], a[1], a[2], a[3], a); } + return a; } - s = (/^#(([0-9a-fA-F]{3,8}))/).exec(value); - if (s && s.length) { - s = s[1]; + match = hexColorRegex.exec(value); + if (match && match.length) { + s = match[1]; if (s.length === 3) { a[0] = parseInt(s[0], 16) / 15; a[1] = parseInt(s[1], 16) / 15; @@ -5394,25 +5452,21 @@ return a; } - s = colorNames[value.toLowerCase()]; - if (s) { + match = colorNames[value.toLowerCase()]; + if (match) { for (i = 0; i < 4; i++) { - a[i] = s[i]; + a[i] = match[i]; } return a; } - if (!colorElement) { - colorElement = document.createElement('a'); + if (!colorCtx) { + colorCtx = document.createElement('canvas').getContext('2d'); } - colorElement.style.backgroundColor = ''; - colorElement.style.backgroundColor = value; - computed = window.getComputedStyle(colorElement); - bg = computed.getPropertyValue('background-color') || - computed.getPropertyValue('backgroundColor') || - colorElement.style.backgroundColor; - if (bg && bg !== value) { - return Seriously.inputValidators.color(bg, input, oldValue); + colorCtx.fillStyle = value; + s = colorCtx.fillStyle; + if (s && s !== '#000000') { + return Seriously.inputValidators.color(s, input, defaultValue, oldValue); } a[0] = a[1] = a[2] = a[3] = 0; @@ -5459,11 +5513,15 @@ return a; }, number: function (value, input, defaultValue) { + value = parseFloat(value); + if (isNaN(value)) { return defaultValue || 0; } - value = parseFloat(value); + if (input.mod) { + value = value - input.mod * Math.floor(value / input.mod); + } if (value < input.min) { return input.min; @@ -5582,6 +5640,7 @@ step: input.step, min: input.min, max: input.max, + mod: input.mod, minCount: input.minCount, maxCount: input.maxCount, dimensions: input.dimensions, @@ -5662,7 +5721,6 @@ Seriously.source('video', function (video, options, force) { var me = this, - video, key, opts, @@ -5709,7 +5767,7 @@ me.setDirty(); } - if (video instanceof window.HTMLVideoElement) { + if (isInstance(video, 'HTMLVideoElement')) { if (video.readyState) { initializeVideo(); } else { @@ -6436,9 +6494,50 @@ todo: additional transform node types - perspective - matrix - - crop? - maybe not - probably would just scale. */ + baseVertexShader = [ + 'precision mediump float;', + + 'attribute vec4 position;', + 'attribute vec2 texCoord;', + + 'uniform vec2 resolution;', + 'uniform mat4 transform;', + + 'varying vec2 vTexCoord;', + + 'void main(void) {', + // first convert to screen space + ' vec4 screenPosition = vec4(position.xy * resolution / 2.0, position.z, position.w);', + ' screenPosition = transform * screenPosition;', + + // convert back to OpenGL coords + ' gl_Position.xy = screenPosition.xy * 2.0 / resolution;', + ' gl_Position.z = screenPosition.z * 2.0 / (resolution.x / resolution.y);', + ' gl_Position.w = screenPosition.w;', + ' vTexCoord = texCoord;', + '}\n' + ].join('\n'); + + baseFragmentShader = [ + 'precision mediump float;', + + 'varying vec2 vTexCoord;', + + 'uniform sampler2D source;', + + 'void main(void) {', + /* + ' if (any(lessThan(vTexCoord, vec2(0.0))) || any(greaterThanEqual(vTexCoord, vec2(1.0)))) {', + ' gl_FragColor = vec4(0.0);', + ' } else {', + */ + ' gl_FragColor = texture2D(source, vTexCoord);', + //' }', + '}' + ].join('\n'); + /* * simplex noise shaders * https://github.com/ashima/webgl-noise diff --git a/sources/seriously.array.js b/sources/seriously.array.js index 8fe3e61..c5c2f76 100644 --- a/sources/seriously.array.js +++ b/sources/seriously.array.js @@ -17,7 +17,7 @@ */ factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; Seriously.source('array', function (source, options, force) { diff --git a/sources/seriously.camera.js b/sources/seriously.camera.js index f4ba12a..81494d3 100644 --- a/sources/seriously.camera.js +++ b/sources/seriously.camera.js @@ -17,7 +17,7 @@ */ factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia, diff --git a/sources/seriously.depth.js b/sources/seriously.depth.js index e241325..2facf1e 100644 --- a/sources/seriously.depth.js +++ b/sources/seriously.depth.js @@ -17,7 +17,7 @@ */ factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; /* diff --git a/sources/seriously.imagedata.js b/sources/seriously.imagedata.js index 8d7d04c..d260c14 100644 --- a/sources/seriously.imagedata.js +++ b/sources/seriously.imagedata.js @@ -17,7 +17,7 @@ */ factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; Seriously.source('imagedata', function (source) { diff --git a/sources/seriously.three.js b/sources/seriously.three.js index 8a5b031..04bde14 100644 --- a/sources/seriously.three.js +++ b/sources/seriously.three.js @@ -17,7 +17,7 @@ */ factory(root.Seriously, root.THREE); } -}(this, function (Seriously, THREE) { +}(window, function (Seriously, THREE) { 'use strict'; Seriously.source('three', function (source, options, force) { diff --git a/targets/seriously.three.js b/targets/seriously.three.js index 813eccb..bdce279 100644 --- a/targets/seriously.three.js +++ b/targets/seriously.three.js @@ -33,7 +33,7 @@ ]), mat4 = Seriously.util.mat4; - Seriously.target('three', function (target, options, force) { + Seriously.target('three', function (target, options) { var me = this, gl, frameBuffer; @@ -59,16 +59,16 @@ } else if (options) { if (options.gl) { gl = options.gl; - } else if (options.canvas) { + } else if (options.canvas && options.canvas.getContext) { try { - gl = canvas.getContext('webgl'); - } catch (expError) { + gl = options.canvas.getContext('webgl'); + } catch (ignore) { } if (!gl) { try { - gl = canvas.getContext('experimental-webgl'); - } catch (error) { + gl = options.canvas.getContext('experimental-webgl'); + } catch (ignore) { } } } diff --git a/test/seriously.unit.js b/test/seriously.unit.js index 9e267b9..c06f586 100644 --- a/test/seriously.unit.js +++ b/test/seriously.unit.js @@ -456,7 +456,7 @@ Seriously.removePlugin('removeme'); }); - test('Effect Info', 24, function () { + test('Effect Info', 25, function () { var inputs, seriously, effect; @@ -468,6 +468,7 @@ min: -4, max: 100, step: 2, + mod: 360, defaultValue: 8, description: 'this is a number', title: 'Number' @@ -503,6 +504,7 @@ 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.mod, 360, 'Number mod 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'); @@ -1035,12 +1037,61 @@ target.source = reformat; }); + asyncTest('Source elements in iframe (#102)', 3, function () { + var iframe; + + iframe = document.createElement('iframe'); + iframe.style.display = 'none'; + iframe.addEventListener('load', function () { + var win = this.contentWindow, + doc = this.contentDocument, + seriously, + video, + canvas, + img, + source; + + doc.body.innerHTML = [ + '<video id="source-video"></video>', + '<canvas id="source-canvas"></canvas>', + '<img id="source-image"/>' + ].join(''); + video = doc.getElementById('source-video'); + canvas = doc.getElementById('source-canvas'); + img = doc.getElementById('source-image'); + + seriously = new Seriously(); + + try { + source = seriously.source(video); + } catch (e1) {} + ok(seriously.isSource(source) && source.original === video, + 'Successfully created source node for video in same-origin iframe'); + + try { + source = seriously.source(canvas); + } catch (e2) {} + ok(seriously.isSource(source) && source.original === canvas, + 'Successfully created source node for canvas in same-origin iframe'); + + try { + source = seriously.source(img); + } catch (e3) {} + ok(seriously.isSource(source) && source.original === img, + 'Successfully created source node for image in same-origin iframe'); + + seriously.destroy(); + start(); + }); + document.body.appendChild(iframe); + }); + module('Inputs'); /* * all different types * test html elements as inputs (with overwriting) */ - test('Number', 6, function () { + test('Number', 9, function () { var s, e, val, input; Seriously.plugin('testNumberInput', { @@ -1057,6 +1108,10 @@ step: { type: 'number', step: 7 + }, + mod: { + type: 'number', + mod: 7 } } }); @@ -1080,6 +1135,18 @@ val = e.step; equal(val, 84, 'Step rounds up'); + e.mod = 5; + val = e.mod; + equal(val, 5, 'Mod within range returns original'); + + e.mod = 27; + val = e.mod; + equal(val, 27 % 7, 'Set number above mod'); + + e.mod = -5; + val = e.mod; + equal(val, 2, 'Negative number with mod'); + e.number = 'not a number'; val = e.number; equal(val, 42, 'Bad number reverts to default value'); @@ -2120,6 +2187,7 @@ canvas, source, effect, + commonEffect, target, gl, @@ -2147,6 +2215,7 @@ Seriously.logger.log = nop; seriously.destroy(); Seriously.removePlugin('test'); + Seriously.removePlugin('common-shader'); start(); } @@ -2215,6 +2284,26 @@ } }); + Seriously.plugin('common-shader', { + title: 'Test Effect with common shader', + commonShader: true, + shader: function (inputs, shaderSource) { + return shaderSource; + }, + draw: function (shader, model, uniforms, frameBuffer, draw) { + try { + draw(shader, model, uniforms, frameBuffer); + } catch (e) { + ok(false, 'Failed to draw effect with common shader'); + } + }, + inputs: { + source: { + type: 'image' + } + } + }); + seriously = new Seriously(); source = seriously.source('#colorbars'); @@ -2222,8 +2311,11 @@ effect = seriously.effect('test'); effect.source = source; + commonEffect = seriously.effect('common-shader'); + commonEffect.source = effect; + target = seriously.target(canvas); - target.source = effect; + target.source = commonEffect; source.on('webglcontextlost', function () { lostFired = true; @@ -2250,6 +2342,8 @@ target.on('webglcontextrestored', function () { restoredFired = true; ok(!lost && restored, 'webglcontextrestored event fired on target node'); + + target.render(); }); seriously.go(function () { @@ -2344,6 +2438,36 @@ Seriously.logger.warn = nop; }); + asyncTest('Target canvas element in iframe (#102)', 1, function () { + var iframe; + + iframe = document.createElement('iframe'); + iframe.style.display = 'none'; + iframe.addEventListener('load', function () { + var win = this.contentWindow, + doc = this.contentDocument, + seriously, + canvas, + target; + + doc.body.innerHTML = '<canvas id="source-canvas"></canvas>'; + canvas = doc.getElementById('source-canvas'); + + seriously = new Seriously(); + + try { + target = seriously.target(canvas); + } catch (e) { + } + ok(seriously.isTarget(target) && target.original === canvas, + 'Successfully created target node for canvas in same-origin iframe'); + + seriously.destroy(); + start(); + }); + document.body.appendChild(iframe); + }); + module('Alias'); test('Effect alias', 2, function () { var seriously, @@ -2439,7 +2563,7 @@ module('Destroy'); - test('Destroy things', 20, function() { + test('Destroy things', 21, function() { var seriously, source, target, effect, transform, canvas, seriouslyId, sourceId, targetId, effectId, transformId; @@ -2488,6 +2612,7 @@ seriously.destroy(); ok(seriously.isDestroyed(), 'Destroyed Seriously instance is destroyed'); equal(seriously.id, seriouslyId, 'id property retained on destroyed Seriously instance'); + equal(target.width, undefined, 'Destorying Seriously instance cleans up node objects'); ok(source.isDestroyed(), 'Destroy Seriously instance destroys source'); ok(effect.isDestroyed(), 'Destroy Seriously instance destroys effect'); @@ -2859,12 +2984,14 @@ source, pixels, error, - incompatible; + incompatible, + input = [255, 128, 100, 200], + expected; incompatible = Seriously.incompatible(); seriously = new Seriously(); - source = seriously.source([255, 128, 100, 200], { + source = seriously.source(input, { width: 1, height: 1 }); @@ -2885,8 +3012,17 @@ } catch (e) { error = e; } + + expected = input.map(function (value, channel) { + if (channel < 3) { + return Math.round((255 - value) * input[3] / 255); + } + + return value; + }); + ok(incompatible ? error : !error, 'readPixels throws error iff incompatible'); - ok(incompatible || pixels && compare(pixels, [0, 127, 155, 200]), 'Invert effect rendered accurately.'); + ok(incompatible || pixels && compare(pixels, expected), 'Invert effect rendered accurately.'); seriously.destroy(); Seriously.removePlugin('invert'); diff --git a/transforms/seriously.camerashake.js b/transforms/seriously.camerashake.js index 79fc584..31cd87f 100644 --- a/transforms/seriously.camerashake.js +++ b/transforms/seriously.camerashake.js @@ -17,7 +17,7 @@ */ factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; /* diff --git a/transforms/seriously.transform3d.js b/transforms/seriously.transform3d.js index 6277fe8..501a77a 100644 --- a/transforms/seriously.transform3d.js +++ b/transforms/seriously.transform3d.js @@ -17,7 +17,7 @@ */ factory(root.Seriously); } -}(this, function (Seriously) { +}(window, function (Seriously) { 'use strict'; var mat4 = Seriously.util.mat4;