diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 00c6d53..fa45c9c 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -6,6 +6,7 @@ BlendModeManager = require('./managers/BlendModeManager'), RenderTarget = require('./utils/RenderTarget'), ObjectRenderer = require('./utils/ObjectRenderer'), + FXAAFilter = require('./filters/FXAAFilter'), math = require('../../math'), utils = require('../../utils'), @@ -49,6 +50,10 @@ this.view.addEventListener('webglcontextlost', this.handleContextLost, false); this.view.addEventListener('webglcontextrestored', this.handleContextRestored, false); + //TODO possibility to force FXAA as it may offer better performance? + this._useFXAA = false; + this._FXAAFilter = null; + /** * The options passed in to create a new webgl context. * @@ -159,6 +164,14 @@ // setup the width/height properties and gl viewport this.resize(this.width, this.height); + + this._useFXAA = this._contextOptions.antialias && ! gl.getContextAttributes().antialias; + + if(this._useFXAA) + { + this._FXAAFilter = [new FXAAFilter()]; + console.warn('WebGL native antialising not available switching to FXAA antialiasing'); + } }; /** @@ -176,6 +189,13 @@ this._lastObjectRendered = object; + if(this._useFXAA) + { + this._FXAAFilter[0].uniforms.resolution.value.x = this.width; + this._FXAAFilter[0].uniforms.resolution.value.y = this.height; + + object.filters = this._FXAAFilter + } var cacheParent = object.parent; object.parent = this._tempDisplayObjectParent; @@ -217,7 +237,6 @@ { // TODO is this needed... //this.blendModeManager.setBlendMode(CONST.blendModes.NORMAL); - this.setRenderTarget(renderTarget); // start the filter manager diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 00c6d53..fa45c9c 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -6,6 +6,7 @@ BlendModeManager = require('./managers/BlendModeManager'), RenderTarget = require('./utils/RenderTarget'), ObjectRenderer = require('./utils/ObjectRenderer'), + FXAAFilter = require('./filters/FXAAFilter'), math = require('../../math'), utils = require('../../utils'), @@ -49,6 +50,10 @@ this.view.addEventListener('webglcontextlost', this.handleContextLost, false); this.view.addEventListener('webglcontextrestored', this.handleContextRestored, false); + //TODO possibility to force FXAA as it may offer better performance? + this._useFXAA = false; + this._FXAAFilter = null; + /** * The options passed in to create a new webgl context. * @@ -159,6 +164,14 @@ // setup the width/height properties and gl viewport this.resize(this.width, this.height); + + this._useFXAA = this._contextOptions.antialias && ! gl.getContextAttributes().antialias; + + if(this._useFXAA) + { + this._FXAAFilter = [new FXAAFilter()]; + console.warn('WebGL native antialising not available switching to FXAA antialiasing'); + } }; /** @@ -176,6 +189,13 @@ this._lastObjectRendered = object; + if(this._useFXAA) + { + this._FXAAFilter[0].uniforms.resolution.value.x = this.width; + this._FXAAFilter[0].uniforms.resolution.value.y = this.height; + + object.filters = this._FXAAFilter + } var cacheParent = object.parent; object.parent = this._tempDisplayObjectParent; @@ -217,7 +237,6 @@ { // TODO is this needed... //this.blendModeManager.setBlendMode(CONST.blendModes.NORMAL); - this.setRenderTarget(renderTarget); // start the filter manager diff --git a/src/core/renderers/webgl/filters/FXAA.frag b/src/core/renderers/webgl/filters/FXAA.frag new file mode 100755 index 0000000..deb9a30 --- /dev/null +++ b/src/core/renderers/webgl/filters/FXAA.frag @@ -0,0 +1,44 @@ +precision mediump float; + +attribute vec2 aVertexPosition; +attribute vec2 aTextureCoord; +attribute vec4 aColor; + +uniform mat3 projectionMatrix; +uniform vec2 resolution; + +varying vec2 vTextureCoord; +varying vec4 vColor; + +varying vec2 vResolution; + +//texcoords computed in vertex step +//to avoid dependent texture reads +varying vec2 v_rgbNW; +varying vec2 v_rgbNE; +varying vec2 v_rgbSW; +varying vec2 v_rgbSE; +varying vec2 v_rgbM; + + +void texcoords(vec2 fragCoord, vec2 resolution, + out vec2 v_rgbNW, out vec2 v_rgbNE, + out vec2 v_rgbSW, out vec2 v_rgbSE, + out vec2 v_rgbM) { + vec2 inverseVP = 1.0 / resolution.xy; + v_rgbNW = (fragCoord + vec2(-1.0, -1.0)) * inverseVP; + v_rgbNE = (fragCoord + vec2(1.0, -1.0)) * inverseVP; + v_rgbSW = (fragCoord + vec2(-1.0, 1.0)) * inverseVP; + v_rgbSE = (fragCoord + vec2(1.0, 1.0)) * inverseVP; + v_rgbM = vec2(fragCoord * inverseVP); +} + +void main(void){ + gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0); + vTextureCoord = aTextureCoord; + vColor = vec4(aColor.rgb * aColor.a, aColor.a); + vResolution = resolution; + + //compute the texture coords and send them to varyings + texcoords(aTextureCoord * resolution, resolution, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM); +} diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 00c6d53..fa45c9c 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -6,6 +6,7 @@ BlendModeManager = require('./managers/BlendModeManager'), RenderTarget = require('./utils/RenderTarget'), ObjectRenderer = require('./utils/ObjectRenderer'), + FXAAFilter = require('./filters/FXAAFilter'), math = require('../../math'), utils = require('../../utils'), @@ -49,6 +50,10 @@ this.view.addEventListener('webglcontextlost', this.handleContextLost, false); this.view.addEventListener('webglcontextrestored', this.handleContextRestored, false); + //TODO possibility to force FXAA as it may offer better performance? + this._useFXAA = false; + this._FXAAFilter = null; + /** * The options passed in to create a new webgl context. * @@ -159,6 +164,14 @@ // setup the width/height properties and gl viewport this.resize(this.width, this.height); + + this._useFXAA = this._contextOptions.antialias && ! gl.getContextAttributes().antialias; + + if(this._useFXAA) + { + this._FXAAFilter = [new FXAAFilter()]; + console.warn('WebGL native antialising not available switching to FXAA antialiasing'); + } }; /** @@ -176,6 +189,13 @@ this._lastObjectRendered = object; + if(this._useFXAA) + { + this._FXAAFilter[0].uniforms.resolution.value.x = this.width; + this._FXAAFilter[0].uniforms.resolution.value.y = this.height; + + object.filters = this._FXAAFilter + } var cacheParent = object.parent; object.parent = this._tempDisplayObjectParent; @@ -217,7 +237,6 @@ { // TODO is this needed... //this.blendModeManager.setBlendMode(CONST.blendModes.NORMAL); - this.setRenderTarget(renderTarget); // start the filter manager diff --git a/src/core/renderers/webgl/filters/FXAA.frag b/src/core/renderers/webgl/filters/FXAA.frag new file mode 100755 index 0000000..deb9a30 --- /dev/null +++ b/src/core/renderers/webgl/filters/FXAA.frag @@ -0,0 +1,44 @@ +precision mediump float; + +attribute vec2 aVertexPosition; +attribute vec2 aTextureCoord; +attribute vec4 aColor; + +uniform mat3 projectionMatrix; +uniform vec2 resolution; + +varying vec2 vTextureCoord; +varying vec4 vColor; + +varying vec2 vResolution; + +//texcoords computed in vertex step +//to avoid dependent texture reads +varying vec2 v_rgbNW; +varying vec2 v_rgbNE; +varying vec2 v_rgbSW; +varying vec2 v_rgbSE; +varying vec2 v_rgbM; + + +void texcoords(vec2 fragCoord, vec2 resolution, + out vec2 v_rgbNW, out vec2 v_rgbNE, + out vec2 v_rgbSW, out vec2 v_rgbSE, + out vec2 v_rgbM) { + vec2 inverseVP = 1.0 / resolution.xy; + v_rgbNW = (fragCoord + vec2(-1.0, -1.0)) * inverseVP; + v_rgbNE = (fragCoord + vec2(1.0, -1.0)) * inverseVP; + v_rgbSW = (fragCoord + vec2(-1.0, 1.0)) * inverseVP; + v_rgbSE = (fragCoord + vec2(1.0, 1.0)) * inverseVP; + v_rgbM = vec2(fragCoord * inverseVP); +} + +void main(void){ + gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0); + vTextureCoord = aTextureCoord; + vColor = vec4(aColor.rgb * aColor.a, aColor.a); + vResolution = resolution; + + //compute the texture coords and send them to varyings + texcoords(aTextureCoord * resolution, resolution, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM); +} diff --git a/src/core/renderers/webgl/filters/FXAA.vert b/src/core/renderers/webgl/filters/FXAA.vert new file mode 100755 index 0000000..2f3b3ae --- /dev/null +++ b/src/core/renderers/webgl/filters/FXAA.vert @@ -0,0 +1,127 @@ +precision lowp float; + + +/** +Basic FXAA implementation based on the code on geeks3d.com with the +modification that the texture2DLod stuff was removed since it's +unsupported by WebGL. + +-- + +From: +https://github.com/mitsuhiko/webgl-meincraft + +Copyright (c) 2011 by Armin Ronacher. + +Some rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * The names of the contributors may not be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef FXAA_REDUCE_MIN + #define FXAA_REDUCE_MIN (1.0/ 128.0) +#endif +#ifndef FXAA_REDUCE_MUL + #define FXAA_REDUCE_MUL (1.0 / 8.0) +#endif +#ifndef FXAA_SPAN_MAX + #define FXAA_SPAN_MAX 8.0 +#endif + +//optimized version for mobile, where dependent +//texture reads can be a bottleneck +vec4 fxaa(sampler2D tex, vec2 fragCoord, vec2 resolution, + vec2 v_rgbNW, vec2 v_rgbNE, + vec2 v_rgbSW, vec2 v_rgbSE, + vec2 v_rgbM) { + vec4 color; + mediump vec2 inverseVP = vec2(1.0 / resolution.x, 1.0 / resolution.y); + vec3 rgbNW = texture2D(tex, v_rgbNW).xyz; + vec3 rgbNE = texture2D(tex, v_rgbNE).xyz; + vec3 rgbSW = texture2D(tex, v_rgbSW).xyz; + vec3 rgbSE = texture2D(tex, v_rgbSE).xyz; + vec4 texColor = texture2D(tex, v_rgbM); + vec3 rgbM = texColor.xyz; + vec3 luma = vec3(0.299, 0.587, 0.114); + float lumaNW = dot(rgbNW, luma); + float lumaNE = dot(rgbNE, luma); + float lumaSW = dot(rgbSW, luma); + float lumaSE = dot(rgbSE, luma); + float lumaM = dot(rgbM, luma); + float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); + float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); + + mediump vec2 dir; + dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); + dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE)); + + float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * + (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN); + + float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce); + dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), + max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), + dir * rcpDirMin)) * inverseVP; + + vec3 rgbA = 0.5 * ( + texture2D(tex, fragCoord * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz + + texture2D(tex, fragCoord * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz); + vec3 rgbB = rgbA * 0.5 + 0.25 * ( + texture2D(tex, fragCoord * inverseVP + dir * -0.5).xyz + + texture2D(tex, fragCoord * inverseVP + dir * 0.5).xyz); + + float lumaB = dot(rgbB, luma); + if ((lumaB < lumaMin) || (lumaB > lumaMax)) + color = vec4(rgbA, texColor.a); + else + color = vec4(rgbB, texColor.a); + return color; +} + + +varying vec2 vTextureCoord; +varying vec4 vColor; +varying vec2 vResolution; + +//texcoords computed in vertex step +//to avoid dependent texture reads +varying vec2 v_rgbNW; +varying vec2 v_rgbNE; +varying vec2 v_rgbSW; +varying vec2 v_rgbSE; +varying vec2 v_rgbM; + +uniform sampler2D uSampler; + + +void main(void){ + + gl_FragColor = fxaa(uSampler, vTextureCoord * vResolution, vResolution, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM); + +} diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 00c6d53..fa45c9c 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -6,6 +6,7 @@ BlendModeManager = require('./managers/BlendModeManager'), RenderTarget = require('./utils/RenderTarget'), ObjectRenderer = require('./utils/ObjectRenderer'), + FXAAFilter = require('./filters/FXAAFilter'), math = require('../../math'), utils = require('../../utils'), @@ -49,6 +50,10 @@ this.view.addEventListener('webglcontextlost', this.handleContextLost, false); this.view.addEventListener('webglcontextrestored', this.handleContextRestored, false); + //TODO possibility to force FXAA as it may offer better performance? + this._useFXAA = false; + this._FXAAFilter = null; + /** * The options passed in to create a new webgl context. * @@ -159,6 +164,14 @@ // setup the width/height properties and gl viewport this.resize(this.width, this.height); + + this._useFXAA = this._contextOptions.antialias && ! gl.getContextAttributes().antialias; + + if(this._useFXAA) + { + this._FXAAFilter = [new FXAAFilter()]; + console.warn('WebGL native antialising not available switching to FXAA antialiasing'); + } }; /** @@ -176,6 +189,13 @@ this._lastObjectRendered = object; + if(this._useFXAA) + { + this._FXAAFilter[0].uniforms.resolution.value.x = this.width; + this._FXAAFilter[0].uniforms.resolution.value.y = this.height; + + object.filters = this._FXAAFilter + } var cacheParent = object.parent; object.parent = this._tempDisplayObjectParent; @@ -217,7 +237,6 @@ { // TODO is this needed... //this.blendModeManager.setBlendMode(CONST.blendModes.NORMAL); - this.setRenderTarget(renderTarget); // start the filter manager diff --git a/src/core/renderers/webgl/filters/FXAA.frag b/src/core/renderers/webgl/filters/FXAA.frag new file mode 100755 index 0000000..deb9a30 --- /dev/null +++ b/src/core/renderers/webgl/filters/FXAA.frag @@ -0,0 +1,44 @@ +precision mediump float; + +attribute vec2 aVertexPosition; +attribute vec2 aTextureCoord; +attribute vec4 aColor; + +uniform mat3 projectionMatrix; +uniform vec2 resolution; + +varying vec2 vTextureCoord; +varying vec4 vColor; + +varying vec2 vResolution; + +//texcoords computed in vertex step +//to avoid dependent texture reads +varying vec2 v_rgbNW; +varying vec2 v_rgbNE; +varying vec2 v_rgbSW; +varying vec2 v_rgbSE; +varying vec2 v_rgbM; + + +void texcoords(vec2 fragCoord, vec2 resolution, + out vec2 v_rgbNW, out vec2 v_rgbNE, + out vec2 v_rgbSW, out vec2 v_rgbSE, + out vec2 v_rgbM) { + vec2 inverseVP = 1.0 / resolution.xy; + v_rgbNW = (fragCoord + vec2(-1.0, -1.0)) * inverseVP; + v_rgbNE = (fragCoord + vec2(1.0, -1.0)) * inverseVP; + v_rgbSW = (fragCoord + vec2(-1.0, 1.0)) * inverseVP; + v_rgbSE = (fragCoord + vec2(1.0, 1.0)) * inverseVP; + v_rgbM = vec2(fragCoord * inverseVP); +} + +void main(void){ + gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0); + vTextureCoord = aTextureCoord; + vColor = vec4(aColor.rgb * aColor.a, aColor.a); + vResolution = resolution; + + //compute the texture coords and send them to varyings + texcoords(aTextureCoord * resolution, resolution, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM); +} diff --git a/src/core/renderers/webgl/filters/FXAA.vert b/src/core/renderers/webgl/filters/FXAA.vert new file mode 100755 index 0000000..2f3b3ae --- /dev/null +++ b/src/core/renderers/webgl/filters/FXAA.vert @@ -0,0 +1,127 @@ +precision lowp float; + + +/** +Basic FXAA implementation based on the code on geeks3d.com with the +modification that the texture2DLod stuff was removed since it's +unsupported by WebGL. + +-- + +From: +https://github.com/mitsuhiko/webgl-meincraft + +Copyright (c) 2011 by Armin Ronacher. + +Some rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * The names of the contributors may not be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef FXAA_REDUCE_MIN + #define FXAA_REDUCE_MIN (1.0/ 128.0) +#endif +#ifndef FXAA_REDUCE_MUL + #define FXAA_REDUCE_MUL (1.0 / 8.0) +#endif +#ifndef FXAA_SPAN_MAX + #define FXAA_SPAN_MAX 8.0 +#endif + +//optimized version for mobile, where dependent +//texture reads can be a bottleneck +vec4 fxaa(sampler2D tex, vec2 fragCoord, vec2 resolution, + vec2 v_rgbNW, vec2 v_rgbNE, + vec2 v_rgbSW, vec2 v_rgbSE, + vec2 v_rgbM) { + vec4 color; + mediump vec2 inverseVP = vec2(1.0 / resolution.x, 1.0 / resolution.y); + vec3 rgbNW = texture2D(tex, v_rgbNW).xyz; + vec3 rgbNE = texture2D(tex, v_rgbNE).xyz; + vec3 rgbSW = texture2D(tex, v_rgbSW).xyz; + vec3 rgbSE = texture2D(tex, v_rgbSE).xyz; + vec4 texColor = texture2D(tex, v_rgbM); + vec3 rgbM = texColor.xyz; + vec3 luma = vec3(0.299, 0.587, 0.114); + float lumaNW = dot(rgbNW, luma); + float lumaNE = dot(rgbNE, luma); + float lumaSW = dot(rgbSW, luma); + float lumaSE = dot(rgbSE, luma); + float lumaM = dot(rgbM, luma); + float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); + float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); + + mediump vec2 dir; + dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); + dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE)); + + float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * + (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN); + + float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce); + dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), + max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), + dir * rcpDirMin)) * inverseVP; + + vec3 rgbA = 0.5 * ( + texture2D(tex, fragCoord * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz + + texture2D(tex, fragCoord * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz); + vec3 rgbB = rgbA * 0.5 + 0.25 * ( + texture2D(tex, fragCoord * inverseVP + dir * -0.5).xyz + + texture2D(tex, fragCoord * inverseVP + dir * 0.5).xyz); + + float lumaB = dot(rgbB, luma); + if ((lumaB < lumaMin) || (lumaB > lumaMax)) + color = vec4(rgbA, texColor.a); + else + color = vec4(rgbB, texColor.a); + return color; +} + + +varying vec2 vTextureCoord; +varying vec4 vColor; +varying vec2 vResolution; + +//texcoords computed in vertex step +//to avoid dependent texture reads +varying vec2 v_rgbNW; +varying vec2 v_rgbNE; +varying vec2 v_rgbSW; +varying vec2 v_rgbSE; +varying vec2 v_rgbM; + +uniform sampler2D uSampler; + + +void main(void){ + + gl_FragColor = fxaa(uSampler, vTextureCoord * vResolution, vResolution, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM); + +} diff --git a/src/core/renderers/webgl/filters/FXAAFilter.js b/src/core/renderers/webgl/filters/FXAAFilter.js new file mode 100644 index 0000000..2b2d8cd --- /dev/null +++ b/src/core/renderers/webgl/filters/FXAAFilter.js @@ -0,0 +1,87 @@ +var AbstractFilter = require('./AbstractFilter'), + math = require('../../../math'); + +/** + * The SpriteMaskFilter class uses the pixel values from the specified texture (called the displacement map) to perform a displacement of an object. + * You can use this filter to apply all manor of crazy warping effects + * Currently the r property of the texture is used to offset the x and the g property of the texture is used to offset the y. + * + * @class + * @extends AbstractFilter + * @namespace PIXI + * @param texture {Texture} The texture used for the displacement map * must be power of 2 texture at the moment + */ +function SpriteMaskFilter(sprite) +{ + var fs = require('fs'); + + AbstractFilter.call(this, + // fragment shader + fs.readFileSync(__dirname + '/FXAA.frag', 'utf8'), + // vertex shader + fs.readFileSync(__dirname + '/FXAA.vert', 'utf8'), + // uniforms + { + resolution:{ type: 'v2', value:{ x: 1, y: 1 }}, + }); + + /** +Basic FXAA implementation based on the code on geeks3d.com with the +modification that the texture2DLod stuff was removed since it's +unsupported by WebGL. + +-- + +From: +https://github.com/mitsuhiko/webgl-meincraft + +Copyright (c) 2011 by Armin Ronacher. + +Some rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * The names of the contributors may not be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + + +} + +SpriteMaskFilter.prototype = Object.create(AbstractFilter.prototype); +SpriteMaskFilter.prototype.constructor = SpriteMaskFilter; +module.exports = SpriteMaskFilter; + +SpriteMaskFilter.prototype.applyFilter = function (renderer, input, output) +{ + var filterManager = renderer.filterManager; + + var shader = this.getShader( renderer ); + // draw the filter... + filterManager.applyFilter(shader, input, output); +}; diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 00c6d53..fa45c9c 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -6,6 +6,7 @@ BlendModeManager = require('./managers/BlendModeManager'), RenderTarget = require('./utils/RenderTarget'), ObjectRenderer = require('./utils/ObjectRenderer'), + FXAAFilter = require('./filters/FXAAFilter'), math = require('../../math'), utils = require('../../utils'), @@ -49,6 +50,10 @@ this.view.addEventListener('webglcontextlost', this.handleContextLost, false); this.view.addEventListener('webglcontextrestored', this.handleContextRestored, false); + //TODO possibility to force FXAA as it may offer better performance? + this._useFXAA = false; + this._FXAAFilter = null; + /** * The options passed in to create a new webgl context. * @@ -159,6 +164,14 @@ // setup the width/height properties and gl viewport this.resize(this.width, this.height); + + this._useFXAA = this._contextOptions.antialias && ! gl.getContextAttributes().antialias; + + if(this._useFXAA) + { + this._FXAAFilter = [new FXAAFilter()]; + console.warn('WebGL native antialising not available switching to FXAA antialiasing'); + } }; /** @@ -176,6 +189,13 @@ this._lastObjectRendered = object; + if(this._useFXAA) + { + this._FXAAFilter[0].uniforms.resolution.value.x = this.width; + this._FXAAFilter[0].uniforms.resolution.value.y = this.height; + + object.filters = this._FXAAFilter + } var cacheParent = object.parent; object.parent = this._tempDisplayObjectParent; @@ -217,7 +237,6 @@ { // TODO is this needed... //this.blendModeManager.setBlendMode(CONST.blendModes.NORMAL); - this.setRenderTarget(renderTarget); // start the filter manager diff --git a/src/core/renderers/webgl/filters/FXAA.frag b/src/core/renderers/webgl/filters/FXAA.frag new file mode 100755 index 0000000..deb9a30 --- /dev/null +++ b/src/core/renderers/webgl/filters/FXAA.frag @@ -0,0 +1,44 @@ +precision mediump float; + +attribute vec2 aVertexPosition; +attribute vec2 aTextureCoord; +attribute vec4 aColor; + +uniform mat3 projectionMatrix; +uniform vec2 resolution; + +varying vec2 vTextureCoord; +varying vec4 vColor; + +varying vec2 vResolution; + +//texcoords computed in vertex step +//to avoid dependent texture reads +varying vec2 v_rgbNW; +varying vec2 v_rgbNE; +varying vec2 v_rgbSW; +varying vec2 v_rgbSE; +varying vec2 v_rgbM; + + +void texcoords(vec2 fragCoord, vec2 resolution, + out vec2 v_rgbNW, out vec2 v_rgbNE, + out vec2 v_rgbSW, out vec2 v_rgbSE, + out vec2 v_rgbM) { + vec2 inverseVP = 1.0 / resolution.xy; + v_rgbNW = (fragCoord + vec2(-1.0, -1.0)) * inverseVP; + v_rgbNE = (fragCoord + vec2(1.0, -1.0)) * inverseVP; + v_rgbSW = (fragCoord + vec2(-1.0, 1.0)) * inverseVP; + v_rgbSE = (fragCoord + vec2(1.0, 1.0)) * inverseVP; + v_rgbM = vec2(fragCoord * inverseVP); +} + +void main(void){ + gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0); + vTextureCoord = aTextureCoord; + vColor = vec4(aColor.rgb * aColor.a, aColor.a); + vResolution = resolution; + + //compute the texture coords and send them to varyings + texcoords(aTextureCoord * resolution, resolution, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM); +} diff --git a/src/core/renderers/webgl/filters/FXAA.vert b/src/core/renderers/webgl/filters/FXAA.vert new file mode 100755 index 0000000..2f3b3ae --- /dev/null +++ b/src/core/renderers/webgl/filters/FXAA.vert @@ -0,0 +1,127 @@ +precision lowp float; + + +/** +Basic FXAA implementation based on the code on geeks3d.com with the +modification that the texture2DLod stuff was removed since it's +unsupported by WebGL. + +-- + +From: +https://github.com/mitsuhiko/webgl-meincraft + +Copyright (c) 2011 by Armin Ronacher. + +Some rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * The names of the contributors may not be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef FXAA_REDUCE_MIN + #define FXAA_REDUCE_MIN (1.0/ 128.0) +#endif +#ifndef FXAA_REDUCE_MUL + #define FXAA_REDUCE_MUL (1.0 / 8.0) +#endif +#ifndef FXAA_SPAN_MAX + #define FXAA_SPAN_MAX 8.0 +#endif + +//optimized version for mobile, where dependent +//texture reads can be a bottleneck +vec4 fxaa(sampler2D tex, vec2 fragCoord, vec2 resolution, + vec2 v_rgbNW, vec2 v_rgbNE, + vec2 v_rgbSW, vec2 v_rgbSE, + vec2 v_rgbM) { + vec4 color; + mediump vec2 inverseVP = vec2(1.0 / resolution.x, 1.0 / resolution.y); + vec3 rgbNW = texture2D(tex, v_rgbNW).xyz; + vec3 rgbNE = texture2D(tex, v_rgbNE).xyz; + vec3 rgbSW = texture2D(tex, v_rgbSW).xyz; + vec3 rgbSE = texture2D(tex, v_rgbSE).xyz; + vec4 texColor = texture2D(tex, v_rgbM); + vec3 rgbM = texColor.xyz; + vec3 luma = vec3(0.299, 0.587, 0.114); + float lumaNW = dot(rgbNW, luma); + float lumaNE = dot(rgbNE, luma); + float lumaSW = dot(rgbSW, luma); + float lumaSE = dot(rgbSE, luma); + float lumaM = dot(rgbM, luma); + float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); + float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); + + mediump vec2 dir; + dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); + dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE)); + + float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * + (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN); + + float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce); + dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), + max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), + dir * rcpDirMin)) * inverseVP; + + vec3 rgbA = 0.5 * ( + texture2D(tex, fragCoord * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz + + texture2D(tex, fragCoord * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz); + vec3 rgbB = rgbA * 0.5 + 0.25 * ( + texture2D(tex, fragCoord * inverseVP + dir * -0.5).xyz + + texture2D(tex, fragCoord * inverseVP + dir * 0.5).xyz); + + float lumaB = dot(rgbB, luma); + if ((lumaB < lumaMin) || (lumaB > lumaMax)) + color = vec4(rgbA, texColor.a); + else + color = vec4(rgbB, texColor.a); + return color; +} + + +varying vec2 vTextureCoord; +varying vec4 vColor; +varying vec2 vResolution; + +//texcoords computed in vertex step +//to avoid dependent texture reads +varying vec2 v_rgbNW; +varying vec2 v_rgbNE; +varying vec2 v_rgbSW; +varying vec2 v_rgbSE; +varying vec2 v_rgbM; + +uniform sampler2D uSampler; + + +void main(void){ + + gl_FragColor = fxaa(uSampler, vTextureCoord * vResolution, vResolution, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM); + +} diff --git a/src/core/renderers/webgl/filters/FXAAFilter.js b/src/core/renderers/webgl/filters/FXAAFilter.js new file mode 100644 index 0000000..2b2d8cd --- /dev/null +++ b/src/core/renderers/webgl/filters/FXAAFilter.js @@ -0,0 +1,87 @@ +var AbstractFilter = require('./AbstractFilter'), + math = require('../../../math'); + +/** + * The SpriteMaskFilter class uses the pixel values from the specified texture (called the displacement map) to perform a displacement of an object. + * You can use this filter to apply all manor of crazy warping effects + * Currently the r property of the texture is used to offset the x and the g property of the texture is used to offset the y. + * + * @class + * @extends AbstractFilter + * @namespace PIXI + * @param texture {Texture} The texture used for the displacement map * must be power of 2 texture at the moment + */ +function SpriteMaskFilter(sprite) +{ + var fs = require('fs'); + + AbstractFilter.call(this, + // fragment shader + fs.readFileSync(__dirname + '/FXAA.frag', 'utf8'), + // vertex shader + fs.readFileSync(__dirname + '/FXAA.vert', 'utf8'), + // uniforms + { + resolution:{ type: 'v2', value:{ x: 1, y: 1 }}, + }); + + /** +Basic FXAA implementation based on the code on geeks3d.com with the +modification that the texture2DLod stuff was removed since it's +unsupported by WebGL. + +-- + +From: +https://github.com/mitsuhiko/webgl-meincraft + +Copyright (c) 2011 by Armin Ronacher. + +Some rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * The names of the contributors may not be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + + +} + +SpriteMaskFilter.prototype = Object.create(AbstractFilter.prototype); +SpriteMaskFilter.prototype.constructor = SpriteMaskFilter; +module.exports = SpriteMaskFilter; + +SpriteMaskFilter.prototype.applyFilter = function (renderer, input, output) +{ + var filterManager = renderer.filterManager; + + var shader = this.getShader( renderer ); + // draw the filter... + filterManager.applyFilter(shader, input, output); +}; diff --git a/src/core/renderers/webgl/managers/MaskManager.js b/src/core/renderers/webgl/managers/MaskManager.js index be38225..dc0d630 100644 --- a/src/core/renderers/webgl/managers/MaskManager.js +++ b/src/core/renderers/webgl/managers/MaskManager.js @@ -84,7 +84,6 @@ MaskManager.prototype.pushStencilMask = function (target, maskData) { - this.renderer.currentRenderTarget.attachStenilBuffer(); this.renderer.stencilManager.pushMask(maskData); }; diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 00c6d53..fa45c9c 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -6,6 +6,7 @@ BlendModeManager = require('./managers/BlendModeManager'), RenderTarget = require('./utils/RenderTarget'), ObjectRenderer = require('./utils/ObjectRenderer'), + FXAAFilter = require('./filters/FXAAFilter'), math = require('../../math'), utils = require('../../utils'), @@ -49,6 +50,10 @@ this.view.addEventListener('webglcontextlost', this.handleContextLost, false); this.view.addEventListener('webglcontextrestored', this.handleContextRestored, false); + //TODO possibility to force FXAA as it may offer better performance? + this._useFXAA = false; + this._FXAAFilter = null; + /** * The options passed in to create a new webgl context. * @@ -159,6 +164,14 @@ // setup the width/height properties and gl viewport this.resize(this.width, this.height); + + this._useFXAA = this._contextOptions.antialias && ! gl.getContextAttributes().antialias; + + if(this._useFXAA) + { + this._FXAAFilter = [new FXAAFilter()]; + console.warn('WebGL native antialising not available switching to FXAA antialiasing'); + } }; /** @@ -176,6 +189,13 @@ this._lastObjectRendered = object; + if(this._useFXAA) + { + this._FXAAFilter[0].uniforms.resolution.value.x = this.width; + this._FXAAFilter[0].uniforms.resolution.value.y = this.height; + + object.filters = this._FXAAFilter + } var cacheParent = object.parent; object.parent = this._tempDisplayObjectParent; @@ -217,7 +237,6 @@ { // TODO is this needed... //this.blendModeManager.setBlendMode(CONST.blendModes.NORMAL); - this.setRenderTarget(renderTarget); // start the filter manager diff --git a/src/core/renderers/webgl/filters/FXAA.frag b/src/core/renderers/webgl/filters/FXAA.frag new file mode 100755 index 0000000..deb9a30 --- /dev/null +++ b/src/core/renderers/webgl/filters/FXAA.frag @@ -0,0 +1,44 @@ +precision mediump float; + +attribute vec2 aVertexPosition; +attribute vec2 aTextureCoord; +attribute vec4 aColor; + +uniform mat3 projectionMatrix; +uniform vec2 resolution; + +varying vec2 vTextureCoord; +varying vec4 vColor; + +varying vec2 vResolution; + +//texcoords computed in vertex step +//to avoid dependent texture reads +varying vec2 v_rgbNW; +varying vec2 v_rgbNE; +varying vec2 v_rgbSW; +varying vec2 v_rgbSE; +varying vec2 v_rgbM; + + +void texcoords(vec2 fragCoord, vec2 resolution, + out vec2 v_rgbNW, out vec2 v_rgbNE, + out vec2 v_rgbSW, out vec2 v_rgbSE, + out vec2 v_rgbM) { + vec2 inverseVP = 1.0 / resolution.xy; + v_rgbNW = (fragCoord + vec2(-1.0, -1.0)) * inverseVP; + v_rgbNE = (fragCoord + vec2(1.0, -1.0)) * inverseVP; + v_rgbSW = (fragCoord + vec2(-1.0, 1.0)) * inverseVP; + v_rgbSE = (fragCoord + vec2(1.0, 1.0)) * inverseVP; + v_rgbM = vec2(fragCoord * inverseVP); +} + +void main(void){ + gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0); + vTextureCoord = aTextureCoord; + vColor = vec4(aColor.rgb * aColor.a, aColor.a); + vResolution = resolution; + + //compute the texture coords and send them to varyings + texcoords(aTextureCoord * resolution, resolution, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM); +} diff --git a/src/core/renderers/webgl/filters/FXAA.vert b/src/core/renderers/webgl/filters/FXAA.vert new file mode 100755 index 0000000..2f3b3ae --- /dev/null +++ b/src/core/renderers/webgl/filters/FXAA.vert @@ -0,0 +1,127 @@ +precision lowp float; + + +/** +Basic FXAA implementation based on the code on geeks3d.com with the +modification that the texture2DLod stuff was removed since it's +unsupported by WebGL. + +-- + +From: +https://github.com/mitsuhiko/webgl-meincraft + +Copyright (c) 2011 by Armin Ronacher. + +Some rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * The names of the contributors may not be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef FXAA_REDUCE_MIN + #define FXAA_REDUCE_MIN (1.0/ 128.0) +#endif +#ifndef FXAA_REDUCE_MUL + #define FXAA_REDUCE_MUL (1.0 / 8.0) +#endif +#ifndef FXAA_SPAN_MAX + #define FXAA_SPAN_MAX 8.0 +#endif + +//optimized version for mobile, where dependent +//texture reads can be a bottleneck +vec4 fxaa(sampler2D tex, vec2 fragCoord, vec2 resolution, + vec2 v_rgbNW, vec2 v_rgbNE, + vec2 v_rgbSW, vec2 v_rgbSE, + vec2 v_rgbM) { + vec4 color; + mediump vec2 inverseVP = vec2(1.0 / resolution.x, 1.0 / resolution.y); + vec3 rgbNW = texture2D(tex, v_rgbNW).xyz; + vec3 rgbNE = texture2D(tex, v_rgbNE).xyz; + vec3 rgbSW = texture2D(tex, v_rgbSW).xyz; + vec3 rgbSE = texture2D(tex, v_rgbSE).xyz; + vec4 texColor = texture2D(tex, v_rgbM); + vec3 rgbM = texColor.xyz; + vec3 luma = vec3(0.299, 0.587, 0.114); + float lumaNW = dot(rgbNW, luma); + float lumaNE = dot(rgbNE, luma); + float lumaSW = dot(rgbSW, luma); + float lumaSE = dot(rgbSE, luma); + float lumaM = dot(rgbM, luma); + float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); + float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); + + mediump vec2 dir; + dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); + dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE)); + + float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * + (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN); + + float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce); + dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), + max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), + dir * rcpDirMin)) * inverseVP; + + vec3 rgbA = 0.5 * ( + texture2D(tex, fragCoord * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz + + texture2D(tex, fragCoord * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz); + vec3 rgbB = rgbA * 0.5 + 0.25 * ( + texture2D(tex, fragCoord * inverseVP + dir * -0.5).xyz + + texture2D(tex, fragCoord * inverseVP + dir * 0.5).xyz); + + float lumaB = dot(rgbB, luma); + if ((lumaB < lumaMin) || (lumaB > lumaMax)) + color = vec4(rgbA, texColor.a); + else + color = vec4(rgbB, texColor.a); + return color; +} + + +varying vec2 vTextureCoord; +varying vec4 vColor; +varying vec2 vResolution; + +//texcoords computed in vertex step +//to avoid dependent texture reads +varying vec2 v_rgbNW; +varying vec2 v_rgbNE; +varying vec2 v_rgbSW; +varying vec2 v_rgbSE; +varying vec2 v_rgbM; + +uniform sampler2D uSampler; + + +void main(void){ + + gl_FragColor = fxaa(uSampler, vTextureCoord * vResolution, vResolution, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM); + +} diff --git a/src/core/renderers/webgl/filters/FXAAFilter.js b/src/core/renderers/webgl/filters/FXAAFilter.js new file mode 100644 index 0000000..2b2d8cd --- /dev/null +++ b/src/core/renderers/webgl/filters/FXAAFilter.js @@ -0,0 +1,87 @@ +var AbstractFilter = require('./AbstractFilter'), + math = require('../../../math'); + +/** + * The SpriteMaskFilter class uses the pixel values from the specified texture (called the displacement map) to perform a displacement of an object. + * You can use this filter to apply all manor of crazy warping effects + * Currently the r property of the texture is used to offset the x and the g property of the texture is used to offset the y. + * + * @class + * @extends AbstractFilter + * @namespace PIXI + * @param texture {Texture} The texture used for the displacement map * must be power of 2 texture at the moment + */ +function SpriteMaskFilter(sprite) +{ + var fs = require('fs'); + + AbstractFilter.call(this, + // fragment shader + fs.readFileSync(__dirname + '/FXAA.frag', 'utf8'), + // vertex shader + fs.readFileSync(__dirname + '/FXAA.vert', 'utf8'), + // uniforms + { + resolution:{ type: 'v2', value:{ x: 1, y: 1 }}, + }); + + /** +Basic FXAA implementation based on the code on geeks3d.com with the +modification that the texture2DLod stuff was removed since it's +unsupported by WebGL. + +-- + +From: +https://github.com/mitsuhiko/webgl-meincraft + +Copyright (c) 2011 by Armin Ronacher. + +Some rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * The names of the contributors may not be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + + +} + +SpriteMaskFilter.prototype = Object.create(AbstractFilter.prototype); +SpriteMaskFilter.prototype.constructor = SpriteMaskFilter; +module.exports = SpriteMaskFilter; + +SpriteMaskFilter.prototype.applyFilter = function (renderer, input, output) +{ + var filterManager = renderer.filterManager; + + var shader = this.getShader( renderer ); + // draw the filter... + filterManager.applyFilter(shader, input, output); +}; diff --git a/src/core/renderers/webgl/managers/MaskManager.js b/src/core/renderers/webgl/managers/MaskManager.js index be38225..dc0d630 100644 --- a/src/core/renderers/webgl/managers/MaskManager.js +++ b/src/core/renderers/webgl/managers/MaskManager.js @@ -84,7 +84,6 @@ MaskManager.prototype.pushStencilMask = function (target, maskData) { - this.renderer.currentRenderTarget.attachStenilBuffer(); this.renderer.stencilManager.pushMask(maskData); }; diff --git a/src/core/renderers/webgl/managers/StencilManager.js b/src/core/renderers/webgl/managers/StencilManager.js index 9875c68..db2383a 100644 --- a/src/core/renderers/webgl/managers/StencilManager.js +++ b/src/core/renderers/webgl/managers/StencilManager.js @@ -40,6 +40,8 @@ */ WebGLMaskManager.prototype.pushStencil = function (graphics, webGLData) { + this.renderer.currentRenderTarget.attachStenilBuffer(); + var gl = this.renderer.gl, sms = this.stencilMaskStack; @@ -303,6 +305,8 @@ */ WebGLMaskManager.prototype.pushMask = function (maskData) { + + this.renderer.setObjectRenderer(this.renderer.plugins.graphics); if (maskData.dirty) diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 00c6d53..fa45c9c 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -6,6 +6,7 @@ BlendModeManager = require('./managers/BlendModeManager'), RenderTarget = require('./utils/RenderTarget'), ObjectRenderer = require('./utils/ObjectRenderer'), + FXAAFilter = require('./filters/FXAAFilter'), math = require('../../math'), utils = require('../../utils'), @@ -49,6 +50,10 @@ this.view.addEventListener('webglcontextlost', this.handleContextLost, false); this.view.addEventListener('webglcontextrestored', this.handleContextRestored, false); + //TODO possibility to force FXAA as it may offer better performance? + this._useFXAA = false; + this._FXAAFilter = null; + /** * The options passed in to create a new webgl context. * @@ -159,6 +164,14 @@ // setup the width/height properties and gl viewport this.resize(this.width, this.height); + + this._useFXAA = this._contextOptions.antialias && ! gl.getContextAttributes().antialias; + + if(this._useFXAA) + { + this._FXAAFilter = [new FXAAFilter()]; + console.warn('WebGL native antialising not available switching to FXAA antialiasing'); + } }; /** @@ -176,6 +189,13 @@ this._lastObjectRendered = object; + if(this._useFXAA) + { + this._FXAAFilter[0].uniforms.resolution.value.x = this.width; + this._FXAAFilter[0].uniforms.resolution.value.y = this.height; + + object.filters = this._FXAAFilter + } var cacheParent = object.parent; object.parent = this._tempDisplayObjectParent; @@ -217,7 +237,6 @@ { // TODO is this needed... //this.blendModeManager.setBlendMode(CONST.blendModes.NORMAL); - this.setRenderTarget(renderTarget); // start the filter manager diff --git a/src/core/renderers/webgl/filters/FXAA.frag b/src/core/renderers/webgl/filters/FXAA.frag new file mode 100755 index 0000000..deb9a30 --- /dev/null +++ b/src/core/renderers/webgl/filters/FXAA.frag @@ -0,0 +1,44 @@ +precision mediump float; + +attribute vec2 aVertexPosition; +attribute vec2 aTextureCoord; +attribute vec4 aColor; + +uniform mat3 projectionMatrix; +uniform vec2 resolution; + +varying vec2 vTextureCoord; +varying vec4 vColor; + +varying vec2 vResolution; + +//texcoords computed in vertex step +//to avoid dependent texture reads +varying vec2 v_rgbNW; +varying vec2 v_rgbNE; +varying vec2 v_rgbSW; +varying vec2 v_rgbSE; +varying vec2 v_rgbM; + + +void texcoords(vec2 fragCoord, vec2 resolution, + out vec2 v_rgbNW, out vec2 v_rgbNE, + out vec2 v_rgbSW, out vec2 v_rgbSE, + out vec2 v_rgbM) { + vec2 inverseVP = 1.0 / resolution.xy; + v_rgbNW = (fragCoord + vec2(-1.0, -1.0)) * inverseVP; + v_rgbNE = (fragCoord + vec2(1.0, -1.0)) * inverseVP; + v_rgbSW = (fragCoord + vec2(-1.0, 1.0)) * inverseVP; + v_rgbSE = (fragCoord + vec2(1.0, 1.0)) * inverseVP; + v_rgbM = vec2(fragCoord * inverseVP); +} + +void main(void){ + gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0); + vTextureCoord = aTextureCoord; + vColor = vec4(aColor.rgb * aColor.a, aColor.a); + vResolution = resolution; + + //compute the texture coords and send them to varyings + texcoords(aTextureCoord * resolution, resolution, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM); +} diff --git a/src/core/renderers/webgl/filters/FXAA.vert b/src/core/renderers/webgl/filters/FXAA.vert new file mode 100755 index 0000000..2f3b3ae --- /dev/null +++ b/src/core/renderers/webgl/filters/FXAA.vert @@ -0,0 +1,127 @@ +precision lowp float; + + +/** +Basic FXAA implementation based on the code on geeks3d.com with the +modification that the texture2DLod stuff was removed since it's +unsupported by WebGL. + +-- + +From: +https://github.com/mitsuhiko/webgl-meincraft + +Copyright (c) 2011 by Armin Ronacher. + +Some rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * The names of the contributors may not be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef FXAA_REDUCE_MIN + #define FXAA_REDUCE_MIN (1.0/ 128.0) +#endif +#ifndef FXAA_REDUCE_MUL + #define FXAA_REDUCE_MUL (1.0 / 8.0) +#endif +#ifndef FXAA_SPAN_MAX + #define FXAA_SPAN_MAX 8.0 +#endif + +//optimized version for mobile, where dependent +//texture reads can be a bottleneck +vec4 fxaa(sampler2D tex, vec2 fragCoord, vec2 resolution, + vec2 v_rgbNW, vec2 v_rgbNE, + vec2 v_rgbSW, vec2 v_rgbSE, + vec2 v_rgbM) { + vec4 color; + mediump vec2 inverseVP = vec2(1.0 / resolution.x, 1.0 / resolution.y); + vec3 rgbNW = texture2D(tex, v_rgbNW).xyz; + vec3 rgbNE = texture2D(tex, v_rgbNE).xyz; + vec3 rgbSW = texture2D(tex, v_rgbSW).xyz; + vec3 rgbSE = texture2D(tex, v_rgbSE).xyz; + vec4 texColor = texture2D(tex, v_rgbM); + vec3 rgbM = texColor.xyz; + vec3 luma = vec3(0.299, 0.587, 0.114); + float lumaNW = dot(rgbNW, luma); + float lumaNE = dot(rgbNE, luma); + float lumaSW = dot(rgbSW, luma); + float lumaSE = dot(rgbSE, luma); + float lumaM = dot(rgbM, luma); + float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); + float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); + + mediump vec2 dir; + dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); + dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE)); + + float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * + (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN); + + float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce); + dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), + max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), + dir * rcpDirMin)) * inverseVP; + + vec3 rgbA = 0.5 * ( + texture2D(tex, fragCoord * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz + + texture2D(tex, fragCoord * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz); + vec3 rgbB = rgbA * 0.5 + 0.25 * ( + texture2D(tex, fragCoord * inverseVP + dir * -0.5).xyz + + texture2D(tex, fragCoord * inverseVP + dir * 0.5).xyz); + + float lumaB = dot(rgbB, luma); + if ((lumaB < lumaMin) || (lumaB > lumaMax)) + color = vec4(rgbA, texColor.a); + else + color = vec4(rgbB, texColor.a); + return color; +} + + +varying vec2 vTextureCoord; +varying vec4 vColor; +varying vec2 vResolution; + +//texcoords computed in vertex step +//to avoid dependent texture reads +varying vec2 v_rgbNW; +varying vec2 v_rgbNE; +varying vec2 v_rgbSW; +varying vec2 v_rgbSE; +varying vec2 v_rgbM; + +uniform sampler2D uSampler; + + +void main(void){ + + gl_FragColor = fxaa(uSampler, vTextureCoord * vResolution, vResolution, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM); + +} diff --git a/src/core/renderers/webgl/filters/FXAAFilter.js b/src/core/renderers/webgl/filters/FXAAFilter.js new file mode 100644 index 0000000..2b2d8cd --- /dev/null +++ b/src/core/renderers/webgl/filters/FXAAFilter.js @@ -0,0 +1,87 @@ +var AbstractFilter = require('./AbstractFilter'), + math = require('../../../math'); + +/** + * The SpriteMaskFilter class uses the pixel values from the specified texture (called the displacement map) to perform a displacement of an object. + * You can use this filter to apply all manor of crazy warping effects + * Currently the r property of the texture is used to offset the x and the g property of the texture is used to offset the y. + * + * @class + * @extends AbstractFilter + * @namespace PIXI + * @param texture {Texture} The texture used for the displacement map * must be power of 2 texture at the moment + */ +function SpriteMaskFilter(sprite) +{ + var fs = require('fs'); + + AbstractFilter.call(this, + // fragment shader + fs.readFileSync(__dirname + '/FXAA.frag', 'utf8'), + // vertex shader + fs.readFileSync(__dirname + '/FXAA.vert', 'utf8'), + // uniforms + { + resolution:{ type: 'v2', value:{ x: 1, y: 1 }}, + }); + + /** +Basic FXAA implementation based on the code on geeks3d.com with the +modification that the texture2DLod stuff was removed since it's +unsupported by WebGL. + +-- + +From: +https://github.com/mitsuhiko/webgl-meincraft + +Copyright (c) 2011 by Armin Ronacher. + +Some rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * The names of the contributors may not be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + + +} + +SpriteMaskFilter.prototype = Object.create(AbstractFilter.prototype); +SpriteMaskFilter.prototype.constructor = SpriteMaskFilter; +module.exports = SpriteMaskFilter; + +SpriteMaskFilter.prototype.applyFilter = function (renderer, input, output) +{ + var filterManager = renderer.filterManager; + + var shader = this.getShader( renderer ); + // draw the filter... + filterManager.applyFilter(shader, input, output); +}; diff --git a/src/core/renderers/webgl/managers/MaskManager.js b/src/core/renderers/webgl/managers/MaskManager.js index be38225..dc0d630 100644 --- a/src/core/renderers/webgl/managers/MaskManager.js +++ b/src/core/renderers/webgl/managers/MaskManager.js @@ -84,7 +84,6 @@ MaskManager.prototype.pushStencilMask = function (target, maskData) { - this.renderer.currentRenderTarget.attachStenilBuffer(); this.renderer.stencilManager.pushMask(maskData); }; diff --git a/src/core/renderers/webgl/managers/StencilManager.js b/src/core/renderers/webgl/managers/StencilManager.js index 9875c68..db2383a 100644 --- a/src/core/renderers/webgl/managers/StencilManager.js +++ b/src/core/renderers/webgl/managers/StencilManager.js @@ -40,6 +40,8 @@ */ WebGLMaskManager.prototype.pushStencil = function (graphics, webGLData) { + this.renderer.currentRenderTarget.attachStenilBuffer(); + var gl = this.renderer.gl, sms = this.stencilMaskStack; @@ -303,6 +305,8 @@ */ WebGLMaskManager.prototype.pushMask = function (maskData) { + + this.renderer.setObjectRenderer(this.renderer.plugins.graphics); if (maskData.dirty) diff --git a/src/core/renderers/webgl/utils/RenderTarget.js b/src/core/renderers/webgl/utils/RenderTarget.js index 4403d8c..c7bee72 100644 --- a/src/core/renderers/webgl/utils/RenderTarget.js +++ b/src/core/renderers/webgl/utils/RenderTarget.js @@ -104,6 +104,7 @@ } + }; RenderTarget.prototype.constructor = RenderTarget; @@ -141,7 +142,7 @@ this.stencilBuffer = gl.createRenderbuffer(); gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencilBuffer); gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, this.stencilBuffer); - gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, this.width , this.height ); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, this.size.width , this.size.height ); } };