diff --git a/package.json b/package.json index 4436b84..48a074c 100644 --- a/package.json +++ b/package.json @@ -32,10 +32,8 @@ "dependencies": { "async": "^1.5.0", "bit-twiddle": "^1.0.2", - "brfs": "^1.4.1", "earcut": "^2.0.7", "eventemitter3": "^1.1.1", - "gl-matrix": "git+https://github.com/toji/gl-matrix.git", "object-assign": "^4.0.1", "pixi-gl-core": "git+https://github.com/GoodBoyDigital/pixi-gl-core.git", "resource-loader": "^1.6.4" @@ -73,6 +71,5 @@ "transform": [ "glslify" ] - } } diff --git a/package.json b/package.json index 4436b84..48a074c 100644 --- a/package.json +++ b/package.json @@ -32,10 +32,8 @@ "dependencies": { "async": "^1.5.0", "bit-twiddle": "^1.0.2", - "brfs": "^1.4.1", "earcut": "^2.0.7", "eventemitter3": "^1.1.1", - "gl-matrix": "git+https://github.com/toji/gl-matrix.git", "object-assign": "^4.0.1", "pixi-gl-core": "git+https://github.com/GoodBoyDigital/pixi-gl-core.git", "resource-loader": "^1.6.4" @@ -73,6 +71,5 @@ "transform": [ "glslify" ] - } } diff --git a/src/core/graphics/webgl/PrimitiveShader.js b/src/core/graphics/webgl/PrimitiveShader.js deleted file mode 100644 index 44166b3..0000000 --- a/src/core/graphics/webgl/PrimitiveShader.js +++ /dev/null @@ -1,50 +0,0 @@ -var Shader = require('pixi-gl-core').GLShader; - -/** - * This shader is used to draw simple primitive shapes for {@link PIXI.Graphics}. - * - * @class - * @memberof PIXI - * @extends PIXI.Shader - * @param shaderManager {ShaderManager} The webgl shader manager this shader works for. - */ -function PrimitiveShader(gl) -{ - Shader.call(this, - gl, - // vertex shader - [ - 'attribute vec2 aVertexPosition;', - 'attribute vec4 aColor;', - - 'uniform mat3 translationMatrix;', - 'uniform mat3 projectionMatrix;', - - 'uniform float alpha;', - 'uniform float flipY;', - 'uniform vec3 tint;', - - 'varying vec4 vColor;', - - 'void main(void){', - ' gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', - ' vColor = aColor * vec4(tint * alpha, alpha);', - '}' - ].join('\n'), - // fragment shader - [ - 'precision mediump float;', - - 'varying vec4 vColor;', - - 'void main(void){', - ' gl_FragColor = vColor;', - '}' - ].join('\n') - ); -} - -PrimitiveShader.prototype = Object.create(Shader.prototype); -PrimitiveShader.prototype.constructor = PrimitiveShader; - -module.exports = PrimitiveShader; diff --git a/package.json b/package.json index 4436b84..48a074c 100644 --- a/package.json +++ b/package.json @@ -32,10 +32,8 @@ "dependencies": { "async": "^1.5.0", "bit-twiddle": "^1.0.2", - "brfs": "^1.4.1", "earcut": "^2.0.7", "eventemitter3": "^1.1.1", - "gl-matrix": "git+https://github.com/toji/gl-matrix.git", "object-assign": "^4.0.1", "pixi-gl-core": "git+https://github.com/GoodBoyDigital/pixi-gl-core.git", "resource-loader": "^1.6.4" @@ -73,6 +71,5 @@ "transform": [ "glslify" ] - } } diff --git a/src/core/graphics/webgl/PrimitiveShader.js b/src/core/graphics/webgl/PrimitiveShader.js deleted file mode 100644 index 44166b3..0000000 --- a/src/core/graphics/webgl/PrimitiveShader.js +++ /dev/null @@ -1,50 +0,0 @@ -var Shader = require('pixi-gl-core').GLShader; - -/** - * This shader is used to draw simple primitive shapes for {@link PIXI.Graphics}. - * - * @class - * @memberof PIXI - * @extends PIXI.Shader - * @param shaderManager {ShaderManager} The webgl shader manager this shader works for. - */ -function PrimitiveShader(gl) -{ - Shader.call(this, - gl, - // vertex shader - [ - 'attribute vec2 aVertexPosition;', - 'attribute vec4 aColor;', - - 'uniform mat3 translationMatrix;', - 'uniform mat3 projectionMatrix;', - - 'uniform float alpha;', - 'uniform float flipY;', - 'uniform vec3 tint;', - - 'varying vec4 vColor;', - - 'void main(void){', - ' gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', - ' vColor = aColor * vec4(tint * alpha, alpha);', - '}' - ].join('\n'), - // fragment shader - [ - 'precision mediump float;', - - 'varying vec4 vColor;', - - 'void main(void){', - ' gl_FragColor = vColor;', - '}' - ].join('\n') - ); -} - -PrimitiveShader.prototype = Object.create(Shader.prototype); -PrimitiveShader.prototype.constructor = PrimitiveShader; - -module.exports = PrimitiveShader; diff --git a/src/core/math/Matrix.js b/src/core/math/Matrix.js index 4e7fe99..2313ae3 100644 --- a/src/core/math/Matrix.js +++ b/src/core/math/Matrix.js @@ -51,6 +51,7 @@ * @default 0 */ this.ty = 0; + } Matrix.prototype.constructor = Matrix; diff --git a/package.json b/package.json index 4436b84..48a074c 100644 --- a/package.json +++ b/package.json @@ -32,10 +32,8 @@ "dependencies": { "async": "^1.5.0", "bit-twiddle": "^1.0.2", - "brfs": "^1.4.1", "earcut": "^2.0.7", "eventemitter3": "^1.1.1", - "gl-matrix": "git+https://github.com/toji/gl-matrix.git", "object-assign": "^4.0.1", "pixi-gl-core": "git+https://github.com/GoodBoyDigital/pixi-gl-core.git", "resource-loader": "^1.6.4" @@ -73,6 +71,5 @@ "transform": [ "glslify" ] - } } diff --git a/src/core/graphics/webgl/PrimitiveShader.js b/src/core/graphics/webgl/PrimitiveShader.js deleted file mode 100644 index 44166b3..0000000 --- a/src/core/graphics/webgl/PrimitiveShader.js +++ /dev/null @@ -1,50 +0,0 @@ -var Shader = require('pixi-gl-core').GLShader; - -/** - * This shader is used to draw simple primitive shapes for {@link PIXI.Graphics}. - * - * @class - * @memberof PIXI - * @extends PIXI.Shader - * @param shaderManager {ShaderManager} The webgl shader manager this shader works for. - */ -function PrimitiveShader(gl) -{ - Shader.call(this, - gl, - // vertex shader - [ - 'attribute vec2 aVertexPosition;', - 'attribute vec4 aColor;', - - 'uniform mat3 translationMatrix;', - 'uniform mat3 projectionMatrix;', - - 'uniform float alpha;', - 'uniform float flipY;', - 'uniform vec3 tint;', - - 'varying vec4 vColor;', - - 'void main(void){', - ' gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', - ' vColor = aColor * vec4(tint * alpha, alpha);', - '}' - ].join('\n'), - // fragment shader - [ - 'precision mediump float;', - - 'varying vec4 vColor;', - - 'void main(void){', - ' gl_FragColor = vColor;', - '}' - ].join('\n') - ); -} - -PrimitiveShader.prototype = Object.create(Shader.prototype); -PrimitiveShader.prototype.constructor = PrimitiveShader; - -module.exports = PrimitiveShader; diff --git a/src/core/math/Matrix.js b/src/core/math/Matrix.js index 4e7fe99..2313ae3 100644 --- a/src/core/math/Matrix.js +++ b/src/core/math/Matrix.js @@ -51,6 +51,7 @@ * @default 0 */ this.ty = 0; + } Matrix.prototype.constructor = Matrix; diff --git a/src/core/renderers/webgl/managers/FilterManager.js b/src/core/renderers/webgl/managers/FilterManager.js index b3f7463..5fc6562 100644 --- a/src/core/renderers/webgl/managers/FilterManager.js +++ b/src/core/renderers/webgl/managers/FilterManager.js @@ -64,11 +64,12 @@ - //TODO - should this be rounded to reoultion? not 1? - sourceFrame.x = targetBounds.x | 0; - sourceFrame.y = targetBounds.y | 0; - sourceFrame.width = targetBounds.width | 0; - sourceFrame.height = targetBounds.height | 0; + + sourceFrame.x = ((targetBounds.x * resolution) | 0) / resolution; + sourceFrame.y = ((targetBounds.y * resolution) | 0) / resolution; + sourceFrame.width = ((targetBounds.width * resolution) | 0) / resolution; + sourceFrame.height = ((targetBounds.height * resolution) | 0) / resolution; + sourceFrame.pad(padding * resolution); sourceFrame.fit(this.stack[0].destinationFrame); @@ -79,6 +80,7 @@ currentState.target = target; currentState.filters = filters; + currentState.resolution = resolution; currentState.renderTarget = renderTarget; // bind the render taget to draw the shape in the top corner.. @@ -236,6 +238,13 @@ shader.uniforms[i] = uniforms[i]; } } + else if(uniformData[i].type === 'float') + { + if(shader.uniforms.data[i].value !== uniformData[i]) + { + shader.uniforms[i] = uniforms[i]; + } + } else { shader.uniforms[i] = uniforms[i]; @@ -244,10 +253,18 @@ } -FilterManager.prototype.getPotRenderTarget = function() +FilterManager.prototype.getRenderTarget = function() { var currentState = this.stack[this.stackIndex]; - return FilterManager.getPotRenderTarget(renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, 1); + var renderTarget = FilterManager.getPotRenderTarget(renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, currentState.resolution); + renderTarget.setFrame(currentState.destinationFrame, currentState.sourceFrame); + + return renderTarget; +} + +FilterManager.prototype.returnRenderTarget = function(renderTarget) +{ + return FilterManager.freePotRenderTarget(renderTarget); } /* @@ -325,6 +342,7 @@ this.destinationFrame = new math.Rectangle(); this.filters = []; this.target = null; + this.resolution = 1; } FilterManager.pool = {} diff --git a/package.json b/package.json index 4436b84..48a074c 100644 --- a/package.json +++ b/package.json @@ -32,10 +32,8 @@ "dependencies": { "async": "^1.5.0", "bit-twiddle": "^1.0.2", - "brfs": "^1.4.1", "earcut": "^2.0.7", "eventemitter3": "^1.1.1", - "gl-matrix": "git+https://github.com/toji/gl-matrix.git", "object-assign": "^4.0.1", "pixi-gl-core": "git+https://github.com/GoodBoyDigital/pixi-gl-core.git", "resource-loader": "^1.6.4" @@ -73,6 +71,5 @@ "transform": [ "glslify" ] - } } diff --git a/src/core/graphics/webgl/PrimitiveShader.js b/src/core/graphics/webgl/PrimitiveShader.js deleted file mode 100644 index 44166b3..0000000 --- a/src/core/graphics/webgl/PrimitiveShader.js +++ /dev/null @@ -1,50 +0,0 @@ -var Shader = require('pixi-gl-core').GLShader; - -/** - * This shader is used to draw simple primitive shapes for {@link PIXI.Graphics}. - * - * @class - * @memberof PIXI - * @extends PIXI.Shader - * @param shaderManager {ShaderManager} The webgl shader manager this shader works for. - */ -function PrimitiveShader(gl) -{ - Shader.call(this, - gl, - // vertex shader - [ - 'attribute vec2 aVertexPosition;', - 'attribute vec4 aColor;', - - 'uniform mat3 translationMatrix;', - 'uniform mat3 projectionMatrix;', - - 'uniform float alpha;', - 'uniform float flipY;', - 'uniform vec3 tint;', - - 'varying vec4 vColor;', - - 'void main(void){', - ' gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', - ' vColor = aColor * vec4(tint * alpha, alpha);', - '}' - ].join('\n'), - // fragment shader - [ - 'precision mediump float;', - - 'varying vec4 vColor;', - - 'void main(void){', - ' gl_FragColor = vColor;', - '}' - ].join('\n') - ); -} - -PrimitiveShader.prototype = Object.create(Shader.prototype); -PrimitiveShader.prototype.constructor = PrimitiveShader; - -module.exports = PrimitiveShader; diff --git a/src/core/math/Matrix.js b/src/core/math/Matrix.js index 4e7fe99..2313ae3 100644 --- a/src/core/math/Matrix.js +++ b/src/core/math/Matrix.js @@ -51,6 +51,7 @@ * @default 0 */ this.ty = 0; + } Matrix.prototype.constructor = Matrix; diff --git a/src/core/renderers/webgl/managers/FilterManager.js b/src/core/renderers/webgl/managers/FilterManager.js index b3f7463..5fc6562 100644 --- a/src/core/renderers/webgl/managers/FilterManager.js +++ b/src/core/renderers/webgl/managers/FilterManager.js @@ -64,11 +64,12 @@ - //TODO - should this be rounded to reoultion? not 1? - sourceFrame.x = targetBounds.x | 0; - sourceFrame.y = targetBounds.y | 0; - sourceFrame.width = targetBounds.width | 0; - sourceFrame.height = targetBounds.height | 0; + + sourceFrame.x = ((targetBounds.x * resolution) | 0) / resolution; + sourceFrame.y = ((targetBounds.y * resolution) | 0) / resolution; + sourceFrame.width = ((targetBounds.width * resolution) | 0) / resolution; + sourceFrame.height = ((targetBounds.height * resolution) | 0) / resolution; + sourceFrame.pad(padding * resolution); sourceFrame.fit(this.stack[0].destinationFrame); @@ -79,6 +80,7 @@ currentState.target = target; currentState.filters = filters; + currentState.resolution = resolution; currentState.renderTarget = renderTarget; // bind the render taget to draw the shape in the top corner.. @@ -236,6 +238,13 @@ shader.uniforms[i] = uniforms[i]; } } + else if(uniformData[i].type === 'float') + { + if(shader.uniforms.data[i].value !== uniformData[i]) + { + shader.uniforms[i] = uniforms[i]; + } + } else { shader.uniforms[i] = uniforms[i]; @@ -244,10 +253,18 @@ } -FilterManager.prototype.getPotRenderTarget = function() +FilterManager.prototype.getRenderTarget = function() { var currentState = this.stack[this.stackIndex]; - return FilterManager.getPotRenderTarget(renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, 1); + var renderTarget = FilterManager.getPotRenderTarget(renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, currentState.resolution); + renderTarget.setFrame(currentState.destinationFrame, currentState.sourceFrame); + + return renderTarget; +} + +FilterManager.prototype.returnRenderTarget = function(renderTarget) +{ + return FilterManager.freePotRenderTarget(renderTarget); } /* @@ -325,6 +342,7 @@ this.destinationFrame = new math.Rectangle(); this.filters = []; this.target = null; + this.resolution = 1; } FilterManager.pool = {} diff --git a/src/core/renderers/webgl/utils/RenderTarget.js b/src/core/renderers/webgl/utils/RenderTarget.js index ced94f6..d3daf50 100644 --- a/src/core/renderers/webgl/utils/RenderTarget.js +++ b/src/core/renderers/webgl/utils/RenderTarget.js @@ -136,6 +136,15 @@ { this.frameBuffer = GLFramebuffer.createRGBA(gl, 100, 100); + if( this.scaleMode === CONST.SCALE_MODES.NEAREST) + { + this.frameBuffer.texture.enableNearestScaling() + } + else + { + this.frameBuffer.texture.enableLinearScaling() + + } /* A frame buffer needs a target to render to.. create a texture and bind it attach it to the framebuffer.. @@ -213,8 +222,10 @@ this.projectionMatrix.append(this.transform); } + //TODO add a check as them may be the same! if(this.destinationFrame !== this.sourceFrame) { + gl.enable(gl.SCISSOR_TEST); gl.scissor(this.destinationFrame.x | 0,this.destinationFrame.y | 0, (this.destinationFrame.width * this.resolution) | 0, (this.destinationFrame.height* this.resolution) | 0); } @@ -279,8 +290,6 @@ return; } - console.log(width + " : " + height) - this.size.width = width; this.size.height = height; diff --git a/package.json b/package.json index 4436b84..48a074c 100644 --- a/package.json +++ b/package.json @@ -32,10 +32,8 @@ "dependencies": { "async": "^1.5.0", "bit-twiddle": "^1.0.2", - "brfs": "^1.4.1", "earcut": "^2.0.7", "eventemitter3": "^1.1.1", - "gl-matrix": "git+https://github.com/toji/gl-matrix.git", "object-assign": "^4.0.1", "pixi-gl-core": "git+https://github.com/GoodBoyDigital/pixi-gl-core.git", "resource-loader": "^1.6.4" @@ -73,6 +71,5 @@ "transform": [ "glslify" ] - } } diff --git a/src/core/graphics/webgl/PrimitiveShader.js b/src/core/graphics/webgl/PrimitiveShader.js deleted file mode 100644 index 44166b3..0000000 --- a/src/core/graphics/webgl/PrimitiveShader.js +++ /dev/null @@ -1,50 +0,0 @@ -var Shader = require('pixi-gl-core').GLShader; - -/** - * This shader is used to draw simple primitive shapes for {@link PIXI.Graphics}. - * - * @class - * @memberof PIXI - * @extends PIXI.Shader - * @param shaderManager {ShaderManager} The webgl shader manager this shader works for. - */ -function PrimitiveShader(gl) -{ - Shader.call(this, - gl, - // vertex shader - [ - 'attribute vec2 aVertexPosition;', - 'attribute vec4 aColor;', - - 'uniform mat3 translationMatrix;', - 'uniform mat3 projectionMatrix;', - - 'uniform float alpha;', - 'uniform float flipY;', - 'uniform vec3 tint;', - - 'varying vec4 vColor;', - - 'void main(void){', - ' gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', - ' vColor = aColor * vec4(tint * alpha, alpha);', - '}' - ].join('\n'), - // fragment shader - [ - 'precision mediump float;', - - 'varying vec4 vColor;', - - 'void main(void){', - ' gl_FragColor = vColor;', - '}' - ].join('\n') - ); -} - -PrimitiveShader.prototype = Object.create(Shader.prototype); -PrimitiveShader.prototype.constructor = PrimitiveShader; - -module.exports = PrimitiveShader; diff --git a/src/core/math/Matrix.js b/src/core/math/Matrix.js index 4e7fe99..2313ae3 100644 --- a/src/core/math/Matrix.js +++ b/src/core/math/Matrix.js @@ -51,6 +51,7 @@ * @default 0 */ this.ty = 0; + } Matrix.prototype.constructor = Matrix; diff --git a/src/core/renderers/webgl/managers/FilterManager.js b/src/core/renderers/webgl/managers/FilterManager.js index b3f7463..5fc6562 100644 --- a/src/core/renderers/webgl/managers/FilterManager.js +++ b/src/core/renderers/webgl/managers/FilterManager.js @@ -64,11 +64,12 @@ - //TODO - should this be rounded to reoultion? not 1? - sourceFrame.x = targetBounds.x | 0; - sourceFrame.y = targetBounds.y | 0; - sourceFrame.width = targetBounds.width | 0; - sourceFrame.height = targetBounds.height | 0; + + sourceFrame.x = ((targetBounds.x * resolution) | 0) / resolution; + sourceFrame.y = ((targetBounds.y * resolution) | 0) / resolution; + sourceFrame.width = ((targetBounds.width * resolution) | 0) / resolution; + sourceFrame.height = ((targetBounds.height * resolution) | 0) / resolution; + sourceFrame.pad(padding * resolution); sourceFrame.fit(this.stack[0].destinationFrame); @@ -79,6 +80,7 @@ currentState.target = target; currentState.filters = filters; + currentState.resolution = resolution; currentState.renderTarget = renderTarget; // bind the render taget to draw the shape in the top corner.. @@ -236,6 +238,13 @@ shader.uniforms[i] = uniforms[i]; } } + else if(uniformData[i].type === 'float') + { + if(shader.uniforms.data[i].value !== uniformData[i]) + { + shader.uniforms[i] = uniforms[i]; + } + } else { shader.uniforms[i] = uniforms[i]; @@ -244,10 +253,18 @@ } -FilterManager.prototype.getPotRenderTarget = function() +FilterManager.prototype.getRenderTarget = function() { var currentState = this.stack[this.stackIndex]; - return FilterManager.getPotRenderTarget(renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, 1); + var renderTarget = FilterManager.getPotRenderTarget(renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, currentState.resolution); + renderTarget.setFrame(currentState.destinationFrame, currentState.sourceFrame); + + return renderTarget; +} + +FilterManager.prototype.returnRenderTarget = function(renderTarget) +{ + return FilterManager.freePotRenderTarget(renderTarget); } /* @@ -325,6 +342,7 @@ this.destinationFrame = new math.Rectangle(); this.filters = []; this.target = null; + this.resolution = 1; } FilterManager.pool = {} diff --git a/src/core/renderers/webgl/utils/RenderTarget.js b/src/core/renderers/webgl/utils/RenderTarget.js index ced94f6..d3daf50 100644 --- a/src/core/renderers/webgl/utils/RenderTarget.js +++ b/src/core/renderers/webgl/utils/RenderTarget.js @@ -136,6 +136,15 @@ { this.frameBuffer = GLFramebuffer.createRGBA(gl, 100, 100); + if( this.scaleMode === CONST.SCALE_MODES.NEAREST) + { + this.frameBuffer.texture.enableNearestScaling() + } + else + { + this.frameBuffer.texture.enableLinearScaling() + + } /* A frame buffer needs a target to render to.. create a texture and bind it attach it to the framebuffer.. @@ -213,8 +222,10 @@ this.projectionMatrix.append(this.transform); } + //TODO add a check as them may be the same! if(this.destinationFrame !== this.sourceFrame) { + gl.enable(gl.SCISSOR_TEST); gl.scissor(this.destinationFrame.x | 0,this.destinationFrame.y | 0, (this.destinationFrame.width * this.resolution) | 0, (this.destinationFrame.height* this.resolution) | 0); } @@ -279,8 +290,6 @@ return; } - console.log(width + " : " + height) - this.size.width = width; this.size.height = height; diff --git a/src/core/textures/BaseRenderTexture copy.js b/src/core/textures/BaseRenderTexture copy.js deleted file mode 100644 index acf6ac9..0000000 --- a/src/core/textures/BaseRenderTexture copy.js +++ /dev/null @@ -1,482 +0,0 @@ -var BaseTexture = require('./BaseTexture'), - Texture = require('./Texture'), - RenderTarget = require('../renderers/webgl/utils/RenderTarget'), - FilterManager = require('../renderers/webgl/managers/FilterManager'), - CanvasBuffer = require('../renderers/canvas/utils/CanvasBuffer'), - math = require('../math'), - CONST = require('../const'), - tempMatrix = new math.Matrix(), - tempRect = new math.Rectangle(); - -/** - * A BaseRenderTexture is a special texture that allows any Pixi display object to be rendered to it. - * - * __Hint__: All DisplayObjects (i.e. Sprites) that render to a BaseRenderTexture should be preloaded - * otherwise black rectangles will be drawn instead. - * - * A BaseRenderTexture takes a snapshot of any Display Object given to its render method. The position - * and rotation of the given Display Objects is ignored. For example: - * - * ```js - * var renderer = PIXI.autoDetectRenderer(1024, 1024, { view: canvas, ratio: 1 }); - * var BaserenderTexture = new PIXI.BaseRenderTexture(renderer, 800, 600); - * var sprite = PIXI.Sprite.fromImage("spinObj_01.png"); - * - * sprite.position.x = 800/2; - * sprite.position.y = 600/2; - * sprite.anchor.x = 0.5; - * sprite.anchor.y = 0.5; - * - * BaserenderTexture.render(sprite); - * ``` - * - * The Sprite in this case will be rendered to a position of 0,0. To render this sprite at its actual - * position a Container should be used: - * - * ```js - * var doc = new PIXI.Container(); - * - * doc.addChild(sprite); - * - * BaserenderTexture.render(doc); // Renders to center of BaserenderTexture - * ``` - * - * @class - * @extends PIXI.Texture - * @memberof PIXI - * @param renderer {PIXI.CanvasRenderer|PIXI.WebGLRenderer} The renderer used for this BaseRenderTexture - * @param [width=100] {number} The width of the render texture - * @param [height=100] {number} The height of the render texture - * @param [scaleMode] {number} See {@link PIXI.SCALE_MODES} for possible values - * @param [resolution=1] {number} The resolution of the texture being generated - */ -function BaseRenderTexture(renderer, width, height, scaleMode, resolution) -{ - if (!renderer) - { - throw new Error('Unable to create BaseRenderTexture, you must pass a renderer into the constructor.'); - } - - BaseTexture.call(this, null, scaleMode); - - this.width = width || 100; - this.height = height || 100; - - this.resolution = resolution || CONST.RESOLUTION;; - this.scaleMode = scaleMode || CONST.SCALE_MODES.DEFAULT; - this.hasLoaded = true; - - /** - * Draw/render the given DisplayObject onto the texture. - * - * The displayObject and descendents are transformed during this operation. - * If `updateTransform` is true then the transformations will be restored before the - * method returns. Otherwise it is up to the calling code to correctly use or reset - * the transformed display objects. - * - * The display object is always rendered with a worldAlpha value of 1. - * - * @method - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear=false] {boolean} If true the texture will be cleared before the displayObject is drawn - * @param [updateTransform=true] {boolean} If true the displayObject's worldTransform/worldAlpha and all children - * transformations will be restored. Not restoring this information will be a little faster. - */ - this.render = null; - - /** - * The renderer this BaseRenderTexture uses. A BaseRenderTexture can only belong to one renderer at the moment if its webGL. - * - * @member {PIXI.CanvasRenderer|PIXI.WebGLRenderer} - */ - this.renderer = renderer; - - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - var gl = this.renderer.gl; - - this.textureBuffer = new RenderTarget(gl, this.width, this.height, this.scaleMode, this.resolution);//, this.this.scaleMode); - this._glTextures[gl.id] = this.textureBuffer.texture; - - //TODO refactor filter manager.. as really its no longer a manager if we use it here.. - this.filterManager = new FilterManager(this.renderer); - this.filterManager.onContextChange(); - this.filterManager.resize(width, height); - this.render = this.renderWebGL; - - // the creation of a filter manager unbinds the buffers.. - this.renderer.currentRenderer.start(); - if(this.renderer._activeRenderTarget)this.renderer._activeRenderTarget.activate(); - } - else - { - - this.render = this.renderCanvas; - this.textureBuffer = new CanvasBuffer(this.width* this.resolution, this.height* this.resolution); - this.source = this.textureBuffer.canvas; - } - - /** - * @member {boolean} - */ - this.valid = true; - -} - -BaseRenderTexture.prototype = Object.create(BaseTexture.prototype); -BaseRenderTexture.prototype.constructor = BaseRenderTexture; -module.exports = BaseRenderTexture; - -/** - * Resizes the BaseRenderTexture. - * - * @param width {number} The width to resize to. - * @param height {number} The height to resize to. - * @param updateBase {boolean} Should the baseTexture.width and height values be resized as well? - */ -BaseRenderTexture.prototype.resize = function (width, height) -{ - if (width === this.width && height === this.height) - { - return; - } - - this.valid = (width > 0 && height > 0); - - this.width = width; - this.height = height; - - if (!this.valid) - { - return; - } - - this.textureBuffer.resize(this.width, this.height); - - if(this.filterManager) - { - this.filterManager.resize(this.width, this.height); - } -}; - -/** - * Clears the BaseRenderTexture. - * - */ -BaseRenderTexture.prototype.clear = function (destinationFrame) -{ - if (!this.valid) - { - return; - } - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - this.renderer.gl.bindFramebuffer(this.renderer.gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - } - - this.textureBuffer.clear(false, destinationFrame); -}; - -/** - * Internal method assigned to the `render` property if using a CanvasRenderer. - * - * @private - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear=false] {boolean} If true the texture will be cleared before the displayObject is drawn - * @param [updateTransform=true] {boolean} If true the displayObject's worldTransform/worldAlpha and all children - * transformations will be restored. Not restoring this information will be a little faster. - */ -BaseRenderTexture.prototype.renderWebGL = function (frame, displayObject, matrix, clear, updateTransform) -{ - if (!this.valid) - { - return; - } - - - updateTransform = (updateTransform !== undefined) ? updateTransform : true;//!updateTransform; - - this.textureBuffer.transform = matrix; - - //TODO not a fan that this is here... it will move! - this.textureBuffer.activate(); - - // setWorld Alpha to ensure that the object is renderer at full opacity - displayObject.worldAlpha = 1; - - if (updateTransform) - { - - // reset the matrix of the displatyObject.. - displayObject.worldTransform.identity(); - - displayObject.currentBounds = null; - - // Time to update all the children of the displayObject with the new matrix.. - var children = displayObject.children; - var i, j; - - for (i = 0, j = children.length; i < j; ++i) - { - children[i].updateTransform(); - } - } - - tempRect.width = frame.height; - tempRect.height = frame.width; - - //TODO rename textureBuffer to renderTarget.. - var temp = this.renderer.filterManager; - - this.renderer.filterManager = this.filterManager; - - - this.textureBuffer.activate(frame, tempRect); - console.log(displayObject) - this.renderer.renderDisplayObject(displayObject, this.textureBuffer, clear); - - // console.log("RENDERING "); - this.renderer.filterManager = temp; -}; - - -/** - * Internal method assigned to the `render` property if using a CanvasRenderer. - * - * @private - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear] {boolean} If true the texture will be cleared before the displayObject is drawn - */ -BaseRenderTexture.prototype.renderCanvas = function (frame, displayObject, matrix, clear, updateTransform) -{ - if (!this.valid) - { - return; - } - - updateTransform = !!updateTransform; - - var wt = tempMatrix; - - wt.identity(); - - if (matrix) - { - wt.append(matrix); - } - - - wt.tx += frame.x; - wt.ty += frame.y; - - var cachedWt = displayObject.worldTransform; - - displayObject.worldTransform = wt; - - // setWorld Alpha to ensure that the object is renderer at full opacity - displayObject.worldAlpha = 1; - - // Time to update all the children of the displayObject with the new matrix.. - var children = displayObject.children; - var i, j; - - for (i = 0, j = children.length; i < j; ++i) - { - children[i].updateTransform(); - } - - if (clear) - { - this.textureBuffer.clear(); - } - - -// this.textureBuffer. - var context = this.textureBuffer.context; - - var realResolution = this.renderer.resolution; - - this.renderer.resolution = this.resolution; - - this.renderer.renderDisplayObject(displayObject, context); - - this.renderer.resolution = realResolution; - - if(displayObject.worldTransform === wt) - { - // fixes cacheAsBitmap Happening during the above.. - displayObject.worldTransform = cachedWt; - } - -}; - -/** - * Destroys this texture - * - * @param destroyBase {boolean} Whether to destroy the base texture as well - */ -BaseRenderTexture.prototype.destroy = function () -{ - Texture.prototype.destroy.call(this, true); - - this.textureBuffer.destroy(); - - // destroy the filtermanager.. - if(this.filterManager) - { - this.filterManager.destroy(); - } - - this.renderer = null; -}; - -/** - * Will return a HTML Image of the texture - * - * @return {Image} - */ -BaseRenderTexture.prototype.getImage = function (frame) -{ - var image = new Image(); - image.src = this.getBase64(frame); - return image; -}; - -/** - * Will return a a base64 encoded string of this texture. It works by calling BaseRenderTexture.getCanvas and then running toDataURL on that. - * - * @return {string} A base64 encoded string of the texture. - */ -BaseRenderTexture.prototype.getBase64 = function ( frame ) -{ - return this.getCanvas(frame).toDataURL(); -}; - -/** - * Creates a Canvas element, renders this BaseRenderTexture to it and then returns it. - * - * @return {HTMLCanvasElement} A Canvas element with the texture rendered on. - */ -BaseRenderTexture.prototype.getCanvas = function ( frame ) -{ - - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.size.width; - frame.height = this.textureBuffer.size.height; - } - - var width = frame.width * this.resolution; - var height = frame.height * this.resolution; - - var gl = this.renderer.gl; - - var webGLPixels = new Uint8Array(4 * width * height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - gl.readPixels(frame.x * this.resolution, frame.y * this.resolution, width, height, gl.RGBA, gl.UNSIGNED_BYTE, webGLPixels); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - var tempCanvas = new CanvasBuffer(width, height); - var canvasData = tempCanvas.context.getImageData(0, 0, width, height); - canvasData.data.set(webGLPixels); - - tempCanvas.context.putImageData(canvasData, 0, 0); - - return tempCanvas.canvas; - } - else - { - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.canvas.width; - frame.height = this.textureBuffer.canvas.height; - } - - if(frame.width === this.textureBuffer.canvas.width && - frame.height === this.textureBuffer.canvas.height ) - { - return this.textureBuffer.canvas; - } - else - { - - var resolution = this.resolution; - - var tempCanvas = new CanvasBuffer(frame.width * resolution, frame.height * resolution); - var canvasData = this.textureBuffer.context.getImageData(frame.x * resolution, frame.y * resolution, frame.width * resolution, frame.height * resolution); - - tempCanvas.context.putImageData(canvasData, 0, 0); - - return tempCanvas.canvas; - } - } -}; - -/** - * Will return a one-dimensional array containing the pixel data of the entire texture in RGBA order, with integer values between 0 and 255 (included). - * - * @return {Uint8ClampedArray} - */ -BaseRenderTexture.prototype.getPixels = function ( frame ) -{ - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.size.width; - frame.height = this.textureBuffer.size.height; - } - - var width = frame.width * this.resolution; - var height = frame.height * this.resolution; - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - var gl = this.renderer.gl; - - var webGLPixels = new Uint8Array(4 * width * height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - gl.readPixels(frame.x * this.resolution, frame.y * this.resolution, width, height, gl.RGBA, gl.UNSIGNED_BYTE, webGLPixels); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - return webGLPixels; - } - else - { - return this.textureBuffer.canvas.getContext('2d').getImageData(frame.x * this.resolution, frame.y * this.resolution, width, height).data; - } -}; - -/** - * Will return a one-dimensional array containing the pixel data of a pixel within the texture in RGBA order, with integer values between 0 and 255 (included). - * - * @param x {number} The x coordinate of the pixel to retrieve. - * @param y {number} The y coordinate of the pixel to retrieve. - * @return {Uint8ClampedArray} - */ -BaseRenderTexture.prototype.getPixel = function (frame, x, y) -{ - tempRect.x = x; - tempRect.y = y; - tempRect.width = 1 / this.resolution; - tempRect.height = 1 / this.resolution; - - if(frame) - { - tempRect.x += frame.x; - tempRect.y += frame.y; - } - - return this.getPixels(tempRect); -}; diff --git a/package.json b/package.json index 4436b84..48a074c 100644 --- a/package.json +++ b/package.json @@ -32,10 +32,8 @@ "dependencies": { "async": "^1.5.0", "bit-twiddle": "^1.0.2", - "brfs": "^1.4.1", "earcut": "^2.0.7", "eventemitter3": "^1.1.1", - "gl-matrix": "git+https://github.com/toji/gl-matrix.git", "object-assign": "^4.0.1", "pixi-gl-core": "git+https://github.com/GoodBoyDigital/pixi-gl-core.git", "resource-loader": "^1.6.4" @@ -73,6 +71,5 @@ "transform": [ "glslify" ] - } } diff --git a/src/core/graphics/webgl/PrimitiveShader.js b/src/core/graphics/webgl/PrimitiveShader.js deleted file mode 100644 index 44166b3..0000000 --- a/src/core/graphics/webgl/PrimitiveShader.js +++ /dev/null @@ -1,50 +0,0 @@ -var Shader = require('pixi-gl-core').GLShader; - -/** - * This shader is used to draw simple primitive shapes for {@link PIXI.Graphics}. - * - * @class - * @memberof PIXI - * @extends PIXI.Shader - * @param shaderManager {ShaderManager} The webgl shader manager this shader works for. - */ -function PrimitiveShader(gl) -{ - Shader.call(this, - gl, - // vertex shader - [ - 'attribute vec2 aVertexPosition;', - 'attribute vec4 aColor;', - - 'uniform mat3 translationMatrix;', - 'uniform mat3 projectionMatrix;', - - 'uniform float alpha;', - 'uniform float flipY;', - 'uniform vec3 tint;', - - 'varying vec4 vColor;', - - 'void main(void){', - ' gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', - ' vColor = aColor * vec4(tint * alpha, alpha);', - '}' - ].join('\n'), - // fragment shader - [ - 'precision mediump float;', - - 'varying vec4 vColor;', - - 'void main(void){', - ' gl_FragColor = vColor;', - '}' - ].join('\n') - ); -} - -PrimitiveShader.prototype = Object.create(Shader.prototype); -PrimitiveShader.prototype.constructor = PrimitiveShader; - -module.exports = PrimitiveShader; diff --git a/src/core/math/Matrix.js b/src/core/math/Matrix.js index 4e7fe99..2313ae3 100644 --- a/src/core/math/Matrix.js +++ b/src/core/math/Matrix.js @@ -51,6 +51,7 @@ * @default 0 */ this.ty = 0; + } Matrix.prototype.constructor = Matrix; diff --git a/src/core/renderers/webgl/managers/FilterManager.js b/src/core/renderers/webgl/managers/FilterManager.js index b3f7463..5fc6562 100644 --- a/src/core/renderers/webgl/managers/FilterManager.js +++ b/src/core/renderers/webgl/managers/FilterManager.js @@ -64,11 +64,12 @@ - //TODO - should this be rounded to reoultion? not 1? - sourceFrame.x = targetBounds.x | 0; - sourceFrame.y = targetBounds.y | 0; - sourceFrame.width = targetBounds.width | 0; - sourceFrame.height = targetBounds.height | 0; + + sourceFrame.x = ((targetBounds.x * resolution) | 0) / resolution; + sourceFrame.y = ((targetBounds.y * resolution) | 0) / resolution; + sourceFrame.width = ((targetBounds.width * resolution) | 0) / resolution; + sourceFrame.height = ((targetBounds.height * resolution) | 0) / resolution; + sourceFrame.pad(padding * resolution); sourceFrame.fit(this.stack[0].destinationFrame); @@ -79,6 +80,7 @@ currentState.target = target; currentState.filters = filters; + currentState.resolution = resolution; currentState.renderTarget = renderTarget; // bind the render taget to draw the shape in the top corner.. @@ -236,6 +238,13 @@ shader.uniforms[i] = uniforms[i]; } } + else if(uniformData[i].type === 'float') + { + if(shader.uniforms.data[i].value !== uniformData[i]) + { + shader.uniforms[i] = uniforms[i]; + } + } else { shader.uniforms[i] = uniforms[i]; @@ -244,10 +253,18 @@ } -FilterManager.prototype.getPotRenderTarget = function() +FilterManager.prototype.getRenderTarget = function() { var currentState = this.stack[this.stackIndex]; - return FilterManager.getPotRenderTarget(renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, 1); + var renderTarget = FilterManager.getPotRenderTarget(renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, currentState.resolution); + renderTarget.setFrame(currentState.destinationFrame, currentState.sourceFrame); + + return renderTarget; +} + +FilterManager.prototype.returnRenderTarget = function(renderTarget) +{ + return FilterManager.freePotRenderTarget(renderTarget); } /* @@ -325,6 +342,7 @@ this.destinationFrame = new math.Rectangle(); this.filters = []; this.target = null; + this.resolution = 1; } FilterManager.pool = {} diff --git a/src/core/renderers/webgl/utils/RenderTarget.js b/src/core/renderers/webgl/utils/RenderTarget.js index ced94f6..d3daf50 100644 --- a/src/core/renderers/webgl/utils/RenderTarget.js +++ b/src/core/renderers/webgl/utils/RenderTarget.js @@ -136,6 +136,15 @@ { this.frameBuffer = GLFramebuffer.createRGBA(gl, 100, 100); + if( this.scaleMode === CONST.SCALE_MODES.NEAREST) + { + this.frameBuffer.texture.enableNearestScaling() + } + else + { + this.frameBuffer.texture.enableLinearScaling() + + } /* A frame buffer needs a target to render to.. create a texture and bind it attach it to the framebuffer.. @@ -213,8 +222,10 @@ this.projectionMatrix.append(this.transform); } + //TODO add a check as them may be the same! if(this.destinationFrame !== this.sourceFrame) { + gl.enable(gl.SCISSOR_TEST); gl.scissor(this.destinationFrame.x | 0,this.destinationFrame.y | 0, (this.destinationFrame.width * this.resolution) | 0, (this.destinationFrame.height* this.resolution) | 0); } @@ -279,8 +290,6 @@ return; } - console.log(width + " : " + height) - this.size.width = width; this.size.height = height; diff --git a/src/core/textures/BaseRenderTexture copy.js b/src/core/textures/BaseRenderTexture copy.js deleted file mode 100644 index acf6ac9..0000000 --- a/src/core/textures/BaseRenderTexture copy.js +++ /dev/null @@ -1,482 +0,0 @@ -var BaseTexture = require('./BaseTexture'), - Texture = require('./Texture'), - RenderTarget = require('../renderers/webgl/utils/RenderTarget'), - FilterManager = require('../renderers/webgl/managers/FilterManager'), - CanvasBuffer = require('../renderers/canvas/utils/CanvasBuffer'), - math = require('../math'), - CONST = require('../const'), - tempMatrix = new math.Matrix(), - tempRect = new math.Rectangle(); - -/** - * A BaseRenderTexture is a special texture that allows any Pixi display object to be rendered to it. - * - * __Hint__: All DisplayObjects (i.e. Sprites) that render to a BaseRenderTexture should be preloaded - * otherwise black rectangles will be drawn instead. - * - * A BaseRenderTexture takes a snapshot of any Display Object given to its render method. The position - * and rotation of the given Display Objects is ignored. For example: - * - * ```js - * var renderer = PIXI.autoDetectRenderer(1024, 1024, { view: canvas, ratio: 1 }); - * var BaserenderTexture = new PIXI.BaseRenderTexture(renderer, 800, 600); - * var sprite = PIXI.Sprite.fromImage("spinObj_01.png"); - * - * sprite.position.x = 800/2; - * sprite.position.y = 600/2; - * sprite.anchor.x = 0.5; - * sprite.anchor.y = 0.5; - * - * BaserenderTexture.render(sprite); - * ``` - * - * The Sprite in this case will be rendered to a position of 0,0. To render this sprite at its actual - * position a Container should be used: - * - * ```js - * var doc = new PIXI.Container(); - * - * doc.addChild(sprite); - * - * BaserenderTexture.render(doc); // Renders to center of BaserenderTexture - * ``` - * - * @class - * @extends PIXI.Texture - * @memberof PIXI - * @param renderer {PIXI.CanvasRenderer|PIXI.WebGLRenderer} The renderer used for this BaseRenderTexture - * @param [width=100] {number} The width of the render texture - * @param [height=100] {number} The height of the render texture - * @param [scaleMode] {number} See {@link PIXI.SCALE_MODES} for possible values - * @param [resolution=1] {number} The resolution of the texture being generated - */ -function BaseRenderTexture(renderer, width, height, scaleMode, resolution) -{ - if (!renderer) - { - throw new Error('Unable to create BaseRenderTexture, you must pass a renderer into the constructor.'); - } - - BaseTexture.call(this, null, scaleMode); - - this.width = width || 100; - this.height = height || 100; - - this.resolution = resolution || CONST.RESOLUTION;; - this.scaleMode = scaleMode || CONST.SCALE_MODES.DEFAULT; - this.hasLoaded = true; - - /** - * Draw/render the given DisplayObject onto the texture. - * - * The displayObject and descendents are transformed during this operation. - * If `updateTransform` is true then the transformations will be restored before the - * method returns. Otherwise it is up to the calling code to correctly use or reset - * the transformed display objects. - * - * The display object is always rendered with a worldAlpha value of 1. - * - * @method - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear=false] {boolean} If true the texture will be cleared before the displayObject is drawn - * @param [updateTransform=true] {boolean} If true the displayObject's worldTransform/worldAlpha and all children - * transformations will be restored. Not restoring this information will be a little faster. - */ - this.render = null; - - /** - * The renderer this BaseRenderTexture uses. A BaseRenderTexture can only belong to one renderer at the moment if its webGL. - * - * @member {PIXI.CanvasRenderer|PIXI.WebGLRenderer} - */ - this.renderer = renderer; - - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - var gl = this.renderer.gl; - - this.textureBuffer = new RenderTarget(gl, this.width, this.height, this.scaleMode, this.resolution);//, this.this.scaleMode); - this._glTextures[gl.id] = this.textureBuffer.texture; - - //TODO refactor filter manager.. as really its no longer a manager if we use it here.. - this.filterManager = new FilterManager(this.renderer); - this.filterManager.onContextChange(); - this.filterManager.resize(width, height); - this.render = this.renderWebGL; - - // the creation of a filter manager unbinds the buffers.. - this.renderer.currentRenderer.start(); - if(this.renderer._activeRenderTarget)this.renderer._activeRenderTarget.activate(); - } - else - { - - this.render = this.renderCanvas; - this.textureBuffer = new CanvasBuffer(this.width* this.resolution, this.height* this.resolution); - this.source = this.textureBuffer.canvas; - } - - /** - * @member {boolean} - */ - this.valid = true; - -} - -BaseRenderTexture.prototype = Object.create(BaseTexture.prototype); -BaseRenderTexture.prototype.constructor = BaseRenderTexture; -module.exports = BaseRenderTexture; - -/** - * Resizes the BaseRenderTexture. - * - * @param width {number} The width to resize to. - * @param height {number} The height to resize to. - * @param updateBase {boolean} Should the baseTexture.width and height values be resized as well? - */ -BaseRenderTexture.prototype.resize = function (width, height) -{ - if (width === this.width && height === this.height) - { - return; - } - - this.valid = (width > 0 && height > 0); - - this.width = width; - this.height = height; - - if (!this.valid) - { - return; - } - - this.textureBuffer.resize(this.width, this.height); - - if(this.filterManager) - { - this.filterManager.resize(this.width, this.height); - } -}; - -/** - * Clears the BaseRenderTexture. - * - */ -BaseRenderTexture.prototype.clear = function (destinationFrame) -{ - if (!this.valid) - { - return; - } - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - this.renderer.gl.bindFramebuffer(this.renderer.gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - } - - this.textureBuffer.clear(false, destinationFrame); -}; - -/** - * Internal method assigned to the `render` property if using a CanvasRenderer. - * - * @private - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear=false] {boolean} If true the texture will be cleared before the displayObject is drawn - * @param [updateTransform=true] {boolean} If true the displayObject's worldTransform/worldAlpha and all children - * transformations will be restored. Not restoring this information will be a little faster. - */ -BaseRenderTexture.prototype.renderWebGL = function (frame, displayObject, matrix, clear, updateTransform) -{ - if (!this.valid) - { - return; - } - - - updateTransform = (updateTransform !== undefined) ? updateTransform : true;//!updateTransform; - - this.textureBuffer.transform = matrix; - - //TODO not a fan that this is here... it will move! - this.textureBuffer.activate(); - - // setWorld Alpha to ensure that the object is renderer at full opacity - displayObject.worldAlpha = 1; - - if (updateTransform) - { - - // reset the matrix of the displatyObject.. - displayObject.worldTransform.identity(); - - displayObject.currentBounds = null; - - // Time to update all the children of the displayObject with the new matrix.. - var children = displayObject.children; - var i, j; - - for (i = 0, j = children.length; i < j; ++i) - { - children[i].updateTransform(); - } - } - - tempRect.width = frame.height; - tempRect.height = frame.width; - - //TODO rename textureBuffer to renderTarget.. - var temp = this.renderer.filterManager; - - this.renderer.filterManager = this.filterManager; - - - this.textureBuffer.activate(frame, tempRect); - console.log(displayObject) - this.renderer.renderDisplayObject(displayObject, this.textureBuffer, clear); - - // console.log("RENDERING "); - this.renderer.filterManager = temp; -}; - - -/** - * Internal method assigned to the `render` property if using a CanvasRenderer. - * - * @private - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear] {boolean} If true the texture will be cleared before the displayObject is drawn - */ -BaseRenderTexture.prototype.renderCanvas = function (frame, displayObject, matrix, clear, updateTransform) -{ - if (!this.valid) - { - return; - } - - updateTransform = !!updateTransform; - - var wt = tempMatrix; - - wt.identity(); - - if (matrix) - { - wt.append(matrix); - } - - - wt.tx += frame.x; - wt.ty += frame.y; - - var cachedWt = displayObject.worldTransform; - - displayObject.worldTransform = wt; - - // setWorld Alpha to ensure that the object is renderer at full opacity - displayObject.worldAlpha = 1; - - // Time to update all the children of the displayObject with the new matrix.. - var children = displayObject.children; - var i, j; - - for (i = 0, j = children.length; i < j; ++i) - { - children[i].updateTransform(); - } - - if (clear) - { - this.textureBuffer.clear(); - } - - -// this.textureBuffer. - var context = this.textureBuffer.context; - - var realResolution = this.renderer.resolution; - - this.renderer.resolution = this.resolution; - - this.renderer.renderDisplayObject(displayObject, context); - - this.renderer.resolution = realResolution; - - if(displayObject.worldTransform === wt) - { - // fixes cacheAsBitmap Happening during the above.. - displayObject.worldTransform = cachedWt; - } - -}; - -/** - * Destroys this texture - * - * @param destroyBase {boolean} Whether to destroy the base texture as well - */ -BaseRenderTexture.prototype.destroy = function () -{ - Texture.prototype.destroy.call(this, true); - - this.textureBuffer.destroy(); - - // destroy the filtermanager.. - if(this.filterManager) - { - this.filterManager.destroy(); - } - - this.renderer = null; -}; - -/** - * Will return a HTML Image of the texture - * - * @return {Image} - */ -BaseRenderTexture.prototype.getImage = function (frame) -{ - var image = new Image(); - image.src = this.getBase64(frame); - return image; -}; - -/** - * Will return a a base64 encoded string of this texture. It works by calling BaseRenderTexture.getCanvas and then running toDataURL on that. - * - * @return {string} A base64 encoded string of the texture. - */ -BaseRenderTexture.prototype.getBase64 = function ( frame ) -{ - return this.getCanvas(frame).toDataURL(); -}; - -/** - * Creates a Canvas element, renders this BaseRenderTexture to it and then returns it. - * - * @return {HTMLCanvasElement} A Canvas element with the texture rendered on. - */ -BaseRenderTexture.prototype.getCanvas = function ( frame ) -{ - - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.size.width; - frame.height = this.textureBuffer.size.height; - } - - var width = frame.width * this.resolution; - var height = frame.height * this.resolution; - - var gl = this.renderer.gl; - - var webGLPixels = new Uint8Array(4 * width * height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - gl.readPixels(frame.x * this.resolution, frame.y * this.resolution, width, height, gl.RGBA, gl.UNSIGNED_BYTE, webGLPixels); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - var tempCanvas = new CanvasBuffer(width, height); - var canvasData = tempCanvas.context.getImageData(0, 0, width, height); - canvasData.data.set(webGLPixels); - - tempCanvas.context.putImageData(canvasData, 0, 0); - - return tempCanvas.canvas; - } - else - { - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.canvas.width; - frame.height = this.textureBuffer.canvas.height; - } - - if(frame.width === this.textureBuffer.canvas.width && - frame.height === this.textureBuffer.canvas.height ) - { - return this.textureBuffer.canvas; - } - else - { - - var resolution = this.resolution; - - var tempCanvas = new CanvasBuffer(frame.width * resolution, frame.height * resolution); - var canvasData = this.textureBuffer.context.getImageData(frame.x * resolution, frame.y * resolution, frame.width * resolution, frame.height * resolution); - - tempCanvas.context.putImageData(canvasData, 0, 0); - - return tempCanvas.canvas; - } - } -}; - -/** - * Will return a one-dimensional array containing the pixel data of the entire texture in RGBA order, with integer values between 0 and 255 (included). - * - * @return {Uint8ClampedArray} - */ -BaseRenderTexture.prototype.getPixels = function ( frame ) -{ - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.size.width; - frame.height = this.textureBuffer.size.height; - } - - var width = frame.width * this.resolution; - var height = frame.height * this.resolution; - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - var gl = this.renderer.gl; - - var webGLPixels = new Uint8Array(4 * width * height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - gl.readPixels(frame.x * this.resolution, frame.y * this.resolution, width, height, gl.RGBA, gl.UNSIGNED_BYTE, webGLPixels); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - return webGLPixels; - } - else - { - return this.textureBuffer.canvas.getContext('2d').getImageData(frame.x * this.resolution, frame.y * this.resolution, width, height).data; - } -}; - -/** - * Will return a one-dimensional array containing the pixel data of a pixel within the texture in RGBA order, with integer values between 0 and 255 (included). - * - * @param x {number} The x coordinate of the pixel to retrieve. - * @param y {number} The y coordinate of the pixel to retrieve. - * @return {Uint8ClampedArray} - */ -BaseRenderTexture.prototype.getPixel = function (frame, x, y) -{ - tempRect.x = x; - tempRect.y = y; - tempRect.width = 1 / this.resolution; - tempRect.height = 1 / this.resolution; - - if(frame) - { - tempRect.x += frame.x; - tempRect.y += frame.y; - } - - return this.getPixels(tempRect); -}; diff --git a/src/filters/blur/BlurFilter.js b/src/filters/blur/BlurFilter.js new file mode 100644 index 0000000..fb708a1 --- /dev/null +++ b/src/filters/blur/BlurFilter.js @@ -0,0 +1,114 @@ +var core = require('../../core'), + BlurXFilter = require('./BlurXFilter'), + BlurYFilter = require('./BlurYFilter'); + +/** + * The BlurFilter applies a Gaussian blur to an object. + * The strength of the blur can be set for x- and y-axis separately. + * + * @class + * @extends PIXI.Filter + * @memberof PIXI.filters + */ +function BlurFilter() +{ + core.Filter.call(this); + + this.blurXFilter = new BlurXFilter(); + this.blurYFilter = new BlurYFilter(); + this.resolution = 0.25;//0.25;//0.25//1//01.26; + this.blurYFilter.passes = this.blurXFilter.passes = 2; + this.blurYFilter.strength = this.blurXFilter.strength = 4;//4// 4 + + this.padding = 100 + +} + +BlurFilter.prototype = Object.create(core.Filter.prototype); +BlurFilter.prototype.constructor = BlurFilter; +module.exports = BlurFilter; + +BlurFilter.prototype.apply = function (filterManager, input, output) +{ + var renderTarget = filterManager.getRenderTarget(true); + + this.blurXFilter.apply(filterManager, input, renderTarget, true); + this.blurYFilter.apply(filterManager, renderTarget, output); + + filterManager.returnRenderTarget(renderTarget); +}; + +Object.defineProperties(BlurFilter.prototype, { + /** + * Sets the strength of both the blurX and blurY properties simultaneously + * + * @member {number} + * @memberOf PIXI.filters.BlurFilter# + * @default 2 + */ + blur: { + get: function () + { + return this.blurXFilter.blur; + }, + set: function (value) + { + this.padding = Math.abs(value) * 0.5; + this.blurXFilter.blur = this.blurYFilter.blur = value; + } + }, + + /** + * Sets the number of passes for blur. More passes means higher quaility bluring. + * + * @member {number} + * @memberof PIXI.filters.BlurYFilter# + * @default 1 + */ + passes: { + get: function () + { + return this.blurXFilter.passes; + }, + set: function (value) + { + this.blurXFilter.passes = this.blurYFilter.passes = value; + } + }, + + /** + * Sets the strength of the blurX property + * + * @member {number} + * @memberOf PIXI.filters.BlurFilter# + * @default 2 + */ + blurX: { + get: function () + { + return this.blurXFilter.blur; + }, + set: function (value) + { + this.blurXFilter.blur = value; + } + }, + + /** + * Sets the strength of the blurY property + * + * @member {number} + * @memberOf PIXI.filters.BlurFilter# + * @default 2 + */ + blurY: { + get: function () + { + return this.blurYFilter.blur; + }, + set: function (value) + { + this.blurYFilter.blur = value; + } + } +}); diff --git a/package.json b/package.json index 4436b84..48a074c 100644 --- a/package.json +++ b/package.json @@ -32,10 +32,8 @@ "dependencies": { "async": "^1.5.0", "bit-twiddle": "^1.0.2", - "brfs": "^1.4.1", "earcut": "^2.0.7", "eventemitter3": "^1.1.1", - "gl-matrix": "git+https://github.com/toji/gl-matrix.git", "object-assign": "^4.0.1", "pixi-gl-core": "git+https://github.com/GoodBoyDigital/pixi-gl-core.git", "resource-loader": "^1.6.4" @@ -73,6 +71,5 @@ "transform": [ "glslify" ] - } } diff --git a/src/core/graphics/webgl/PrimitiveShader.js b/src/core/graphics/webgl/PrimitiveShader.js deleted file mode 100644 index 44166b3..0000000 --- a/src/core/graphics/webgl/PrimitiveShader.js +++ /dev/null @@ -1,50 +0,0 @@ -var Shader = require('pixi-gl-core').GLShader; - -/** - * This shader is used to draw simple primitive shapes for {@link PIXI.Graphics}. - * - * @class - * @memberof PIXI - * @extends PIXI.Shader - * @param shaderManager {ShaderManager} The webgl shader manager this shader works for. - */ -function PrimitiveShader(gl) -{ - Shader.call(this, - gl, - // vertex shader - [ - 'attribute vec2 aVertexPosition;', - 'attribute vec4 aColor;', - - 'uniform mat3 translationMatrix;', - 'uniform mat3 projectionMatrix;', - - 'uniform float alpha;', - 'uniform float flipY;', - 'uniform vec3 tint;', - - 'varying vec4 vColor;', - - 'void main(void){', - ' gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', - ' vColor = aColor * vec4(tint * alpha, alpha);', - '}' - ].join('\n'), - // fragment shader - [ - 'precision mediump float;', - - 'varying vec4 vColor;', - - 'void main(void){', - ' gl_FragColor = vColor;', - '}' - ].join('\n') - ); -} - -PrimitiveShader.prototype = Object.create(Shader.prototype); -PrimitiveShader.prototype.constructor = PrimitiveShader; - -module.exports = PrimitiveShader; diff --git a/src/core/math/Matrix.js b/src/core/math/Matrix.js index 4e7fe99..2313ae3 100644 --- a/src/core/math/Matrix.js +++ b/src/core/math/Matrix.js @@ -51,6 +51,7 @@ * @default 0 */ this.ty = 0; + } Matrix.prototype.constructor = Matrix; diff --git a/src/core/renderers/webgl/managers/FilterManager.js b/src/core/renderers/webgl/managers/FilterManager.js index b3f7463..5fc6562 100644 --- a/src/core/renderers/webgl/managers/FilterManager.js +++ b/src/core/renderers/webgl/managers/FilterManager.js @@ -64,11 +64,12 @@ - //TODO - should this be rounded to reoultion? not 1? - sourceFrame.x = targetBounds.x | 0; - sourceFrame.y = targetBounds.y | 0; - sourceFrame.width = targetBounds.width | 0; - sourceFrame.height = targetBounds.height | 0; + + sourceFrame.x = ((targetBounds.x * resolution) | 0) / resolution; + sourceFrame.y = ((targetBounds.y * resolution) | 0) / resolution; + sourceFrame.width = ((targetBounds.width * resolution) | 0) / resolution; + sourceFrame.height = ((targetBounds.height * resolution) | 0) / resolution; + sourceFrame.pad(padding * resolution); sourceFrame.fit(this.stack[0].destinationFrame); @@ -79,6 +80,7 @@ currentState.target = target; currentState.filters = filters; + currentState.resolution = resolution; currentState.renderTarget = renderTarget; // bind the render taget to draw the shape in the top corner.. @@ -236,6 +238,13 @@ shader.uniforms[i] = uniforms[i]; } } + else if(uniformData[i].type === 'float') + { + if(shader.uniforms.data[i].value !== uniformData[i]) + { + shader.uniforms[i] = uniforms[i]; + } + } else { shader.uniforms[i] = uniforms[i]; @@ -244,10 +253,18 @@ } -FilterManager.prototype.getPotRenderTarget = function() +FilterManager.prototype.getRenderTarget = function() { var currentState = this.stack[this.stackIndex]; - return FilterManager.getPotRenderTarget(renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, 1); + var renderTarget = FilterManager.getPotRenderTarget(renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, currentState.resolution); + renderTarget.setFrame(currentState.destinationFrame, currentState.sourceFrame); + + return renderTarget; +} + +FilterManager.prototype.returnRenderTarget = function(renderTarget) +{ + return FilterManager.freePotRenderTarget(renderTarget); } /* @@ -325,6 +342,7 @@ this.destinationFrame = new math.Rectangle(); this.filters = []; this.target = null; + this.resolution = 1; } FilterManager.pool = {} diff --git a/src/core/renderers/webgl/utils/RenderTarget.js b/src/core/renderers/webgl/utils/RenderTarget.js index ced94f6..d3daf50 100644 --- a/src/core/renderers/webgl/utils/RenderTarget.js +++ b/src/core/renderers/webgl/utils/RenderTarget.js @@ -136,6 +136,15 @@ { this.frameBuffer = GLFramebuffer.createRGBA(gl, 100, 100); + if( this.scaleMode === CONST.SCALE_MODES.NEAREST) + { + this.frameBuffer.texture.enableNearestScaling() + } + else + { + this.frameBuffer.texture.enableLinearScaling() + + } /* A frame buffer needs a target to render to.. create a texture and bind it attach it to the framebuffer.. @@ -213,8 +222,10 @@ this.projectionMatrix.append(this.transform); } + //TODO add a check as them may be the same! if(this.destinationFrame !== this.sourceFrame) { + gl.enable(gl.SCISSOR_TEST); gl.scissor(this.destinationFrame.x | 0,this.destinationFrame.y | 0, (this.destinationFrame.width * this.resolution) | 0, (this.destinationFrame.height* this.resolution) | 0); } @@ -279,8 +290,6 @@ return; } - console.log(width + " : " + height) - this.size.width = width; this.size.height = height; diff --git a/src/core/textures/BaseRenderTexture copy.js b/src/core/textures/BaseRenderTexture copy.js deleted file mode 100644 index acf6ac9..0000000 --- a/src/core/textures/BaseRenderTexture copy.js +++ /dev/null @@ -1,482 +0,0 @@ -var BaseTexture = require('./BaseTexture'), - Texture = require('./Texture'), - RenderTarget = require('../renderers/webgl/utils/RenderTarget'), - FilterManager = require('../renderers/webgl/managers/FilterManager'), - CanvasBuffer = require('../renderers/canvas/utils/CanvasBuffer'), - math = require('../math'), - CONST = require('../const'), - tempMatrix = new math.Matrix(), - tempRect = new math.Rectangle(); - -/** - * A BaseRenderTexture is a special texture that allows any Pixi display object to be rendered to it. - * - * __Hint__: All DisplayObjects (i.e. Sprites) that render to a BaseRenderTexture should be preloaded - * otherwise black rectangles will be drawn instead. - * - * A BaseRenderTexture takes a snapshot of any Display Object given to its render method. The position - * and rotation of the given Display Objects is ignored. For example: - * - * ```js - * var renderer = PIXI.autoDetectRenderer(1024, 1024, { view: canvas, ratio: 1 }); - * var BaserenderTexture = new PIXI.BaseRenderTexture(renderer, 800, 600); - * var sprite = PIXI.Sprite.fromImage("spinObj_01.png"); - * - * sprite.position.x = 800/2; - * sprite.position.y = 600/2; - * sprite.anchor.x = 0.5; - * sprite.anchor.y = 0.5; - * - * BaserenderTexture.render(sprite); - * ``` - * - * The Sprite in this case will be rendered to a position of 0,0. To render this sprite at its actual - * position a Container should be used: - * - * ```js - * var doc = new PIXI.Container(); - * - * doc.addChild(sprite); - * - * BaserenderTexture.render(doc); // Renders to center of BaserenderTexture - * ``` - * - * @class - * @extends PIXI.Texture - * @memberof PIXI - * @param renderer {PIXI.CanvasRenderer|PIXI.WebGLRenderer} The renderer used for this BaseRenderTexture - * @param [width=100] {number} The width of the render texture - * @param [height=100] {number} The height of the render texture - * @param [scaleMode] {number} See {@link PIXI.SCALE_MODES} for possible values - * @param [resolution=1] {number} The resolution of the texture being generated - */ -function BaseRenderTexture(renderer, width, height, scaleMode, resolution) -{ - if (!renderer) - { - throw new Error('Unable to create BaseRenderTexture, you must pass a renderer into the constructor.'); - } - - BaseTexture.call(this, null, scaleMode); - - this.width = width || 100; - this.height = height || 100; - - this.resolution = resolution || CONST.RESOLUTION;; - this.scaleMode = scaleMode || CONST.SCALE_MODES.DEFAULT; - this.hasLoaded = true; - - /** - * Draw/render the given DisplayObject onto the texture. - * - * The displayObject and descendents are transformed during this operation. - * If `updateTransform` is true then the transformations will be restored before the - * method returns. Otherwise it is up to the calling code to correctly use or reset - * the transformed display objects. - * - * The display object is always rendered with a worldAlpha value of 1. - * - * @method - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear=false] {boolean} If true the texture will be cleared before the displayObject is drawn - * @param [updateTransform=true] {boolean} If true the displayObject's worldTransform/worldAlpha and all children - * transformations will be restored. Not restoring this information will be a little faster. - */ - this.render = null; - - /** - * The renderer this BaseRenderTexture uses. A BaseRenderTexture can only belong to one renderer at the moment if its webGL. - * - * @member {PIXI.CanvasRenderer|PIXI.WebGLRenderer} - */ - this.renderer = renderer; - - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - var gl = this.renderer.gl; - - this.textureBuffer = new RenderTarget(gl, this.width, this.height, this.scaleMode, this.resolution);//, this.this.scaleMode); - this._glTextures[gl.id] = this.textureBuffer.texture; - - //TODO refactor filter manager.. as really its no longer a manager if we use it here.. - this.filterManager = new FilterManager(this.renderer); - this.filterManager.onContextChange(); - this.filterManager.resize(width, height); - this.render = this.renderWebGL; - - // the creation of a filter manager unbinds the buffers.. - this.renderer.currentRenderer.start(); - if(this.renderer._activeRenderTarget)this.renderer._activeRenderTarget.activate(); - } - else - { - - this.render = this.renderCanvas; - this.textureBuffer = new CanvasBuffer(this.width* this.resolution, this.height* this.resolution); - this.source = this.textureBuffer.canvas; - } - - /** - * @member {boolean} - */ - this.valid = true; - -} - -BaseRenderTexture.prototype = Object.create(BaseTexture.prototype); -BaseRenderTexture.prototype.constructor = BaseRenderTexture; -module.exports = BaseRenderTexture; - -/** - * Resizes the BaseRenderTexture. - * - * @param width {number} The width to resize to. - * @param height {number} The height to resize to. - * @param updateBase {boolean} Should the baseTexture.width and height values be resized as well? - */ -BaseRenderTexture.prototype.resize = function (width, height) -{ - if (width === this.width && height === this.height) - { - return; - } - - this.valid = (width > 0 && height > 0); - - this.width = width; - this.height = height; - - if (!this.valid) - { - return; - } - - this.textureBuffer.resize(this.width, this.height); - - if(this.filterManager) - { - this.filterManager.resize(this.width, this.height); - } -}; - -/** - * Clears the BaseRenderTexture. - * - */ -BaseRenderTexture.prototype.clear = function (destinationFrame) -{ - if (!this.valid) - { - return; - } - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - this.renderer.gl.bindFramebuffer(this.renderer.gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - } - - this.textureBuffer.clear(false, destinationFrame); -}; - -/** - * Internal method assigned to the `render` property if using a CanvasRenderer. - * - * @private - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear=false] {boolean} If true the texture will be cleared before the displayObject is drawn - * @param [updateTransform=true] {boolean} If true the displayObject's worldTransform/worldAlpha and all children - * transformations will be restored. Not restoring this information will be a little faster. - */ -BaseRenderTexture.prototype.renderWebGL = function (frame, displayObject, matrix, clear, updateTransform) -{ - if (!this.valid) - { - return; - } - - - updateTransform = (updateTransform !== undefined) ? updateTransform : true;//!updateTransform; - - this.textureBuffer.transform = matrix; - - //TODO not a fan that this is here... it will move! - this.textureBuffer.activate(); - - // setWorld Alpha to ensure that the object is renderer at full opacity - displayObject.worldAlpha = 1; - - if (updateTransform) - { - - // reset the matrix of the displatyObject.. - displayObject.worldTransform.identity(); - - displayObject.currentBounds = null; - - // Time to update all the children of the displayObject with the new matrix.. - var children = displayObject.children; - var i, j; - - for (i = 0, j = children.length; i < j; ++i) - { - children[i].updateTransform(); - } - } - - tempRect.width = frame.height; - tempRect.height = frame.width; - - //TODO rename textureBuffer to renderTarget.. - var temp = this.renderer.filterManager; - - this.renderer.filterManager = this.filterManager; - - - this.textureBuffer.activate(frame, tempRect); - console.log(displayObject) - this.renderer.renderDisplayObject(displayObject, this.textureBuffer, clear); - - // console.log("RENDERING "); - this.renderer.filterManager = temp; -}; - - -/** - * Internal method assigned to the `render` property if using a CanvasRenderer. - * - * @private - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear] {boolean} If true the texture will be cleared before the displayObject is drawn - */ -BaseRenderTexture.prototype.renderCanvas = function (frame, displayObject, matrix, clear, updateTransform) -{ - if (!this.valid) - { - return; - } - - updateTransform = !!updateTransform; - - var wt = tempMatrix; - - wt.identity(); - - if (matrix) - { - wt.append(matrix); - } - - - wt.tx += frame.x; - wt.ty += frame.y; - - var cachedWt = displayObject.worldTransform; - - displayObject.worldTransform = wt; - - // setWorld Alpha to ensure that the object is renderer at full opacity - displayObject.worldAlpha = 1; - - // Time to update all the children of the displayObject with the new matrix.. - var children = displayObject.children; - var i, j; - - for (i = 0, j = children.length; i < j; ++i) - { - children[i].updateTransform(); - } - - if (clear) - { - this.textureBuffer.clear(); - } - - -// this.textureBuffer. - var context = this.textureBuffer.context; - - var realResolution = this.renderer.resolution; - - this.renderer.resolution = this.resolution; - - this.renderer.renderDisplayObject(displayObject, context); - - this.renderer.resolution = realResolution; - - if(displayObject.worldTransform === wt) - { - // fixes cacheAsBitmap Happening during the above.. - displayObject.worldTransform = cachedWt; - } - -}; - -/** - * Destroys this texture - * - * @param destroyBase {boolean} Whether to destroy the base texture as well - */ -BaseRenderTexture.prototype.destroy = function () -{ - Texture.prototype.destroy.call(this, true); - - this.textureBuffer.destroy(); - - // destroy the filtermanager.. - if(this.filterManager) - { - this.filterManager.destroy(); - } - - this.renderer = null; -}; - -/** - * Will return a HTML Image of the texture - * - * @return {Image} - */ -BaseRenderTexture.prototype.getImage = function (frame) -{ - var image = new Image(); - image.src = this.getBase64(frame); - return image; -}; - -/** - * Will return a a base64 encoded string of this texture. It works by calling BaseRenderTexture.getCanvas and then running toDataURL on that. - * - * @return {string} A base64 encoded string of the texture. - */ -BaseRenderTexture.prototype.getBase64 = function ( frame ) -{ - return this.getCanvas(frame).toDataURL(); -}; - -/** - * Creates a Canvas element, renders this BaseRenderTexture to it and then returns it. - * - * @return {HTMLCanvasElement} A Canvas element with the texture rendered on. - */ -BaseRenderTexture.prototype.getCanvas = function ( frame ) -{ - - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.size.width; - frame.height = this.textureBuffer.size.height; - } - - var width = frame.width * this.resolution; - var height = frame.height * this.resolution; - - var gl = this.renderer.gl; - - var webGLPixels = new Uint8Array(4 * width * height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - gl.readPixels(frame.x * this.resolution, frame.y * this.resolution, width, height, gl.RGBA, gl.UNSIGNED_BYTE, webGLPixels); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - var tempCanvas = new CanvasBuffer(width, height); - var canvasData = tempCanvas.context.getImageData(0, 0, width, height); - canvasData.data.set(webGLPixels); - - tempCanvas.context.putImageData(canvasData, 0, 0); - - return tempCanvas.canvas; - } - else - { - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.canvas.width; - frame.height = this.textureBuffer.canvas.height; - } - - if(frame.width === this.textureBuffer.canvas.width && - frame.height === this.textureBuffer.canvas.height ) - { - return this.textureBuffer.canvas; - } - else - { - - var resolution = this.resolution; - - var tempCanvas = new CanvasBuffer(frame.width * resolution, frame.height * resolution); - var canvasData = this.textureBuffer.context.getImageData(frame.x * resolution, frame.y * resolution, frame.width * resolution, frame.height * resolution); - - tempCanvas.context.putImageData(canvasData, 0, 0); - - return tempCanvas.canvas; - } - } -}; - -/** - * Will return a one-dimensional array containing the pixel data of the entire texture in RGBA order, with integer values between 0 and 255 (included). - * - * @return {Uint8ClampedArray} - */ -BaseRenderTexture.prototype.getPixels = function ( frame ) -{ - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.size.width; - frame.height = this.textureBuffer.size.height; - } - - var width = frame.width * this.resolution; - var height = frame.height * this.resolution; - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - var gl = this.renderer.gl; - - var webGLPixels = new Uint8Array(4 * width * height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - gl.readPixels(frame.x * this.resolution, frame.y * this.resolution, width, height, gl.RGBA, gl.UNSIGNED_BYTE, webGLPixels); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - return webGLPixels; - } - else - { - return this.textureBuffer.canvas.getContext('2d').getImageData(frame.x * this.resolution, frame.y * this.resolution, width, height).data; - } -}; - -/** - * Will return a one-dimensional array containing the pixel data of a pixel within the texture in RGBA order, with integer values between 0 and 255 (included). - * - * @param x {number} The x coordinate of the pixel to retrieve. - * @param y {number} The y coordinate of the pixel to retrieve. - * @return {Uint8ClampedArray} - */ -BaseRenderTexture.prototype.getPixel = function (frame, x, y) -{ - tempRect.x = x; - tempRect.y = y; - tempRect.width = 1 / this.resolution; - tempRect.height = 1 / this.resolution; - - if(frame) - { - tempRect.x += frame.x; - tempRect.y += frame.y; - } - - return this.getPixels(tempRect); -}; diff --git a/src/filters/blur/BlurFilter.js b/src/filters/blur/BlurFilter.js new file mode 100644 index 0000000..fb708a1 --- /dev/null +++ b/src/filters/blur/BlurFilter.js @@ -0,0 +1,114 @@ +var core = require('../../core'), + BlurXFilter = require('./BlurXFilter'), + BlurYFilter = require('./BlurYFilter'); + +/** + * The BlurFilter applies a Gaussian blur to an object. + * The strength of the blur can be set for x- and y-axis separately. + * + * @class + * @extends PIXI.Filter + * @memberof PIXI.filters + */ +function BlurFilter() +{ + core.Filter.call(this); + + this.blurXFilter = new BlurXFilter(); + this.blurYFilter = new BlurYFilter(); + this.resolution = 0.25;//0.25;//0.25//1//01.26; + this.blurYFilter.passes = this.blurXFilter.passes = 2; + this.blurYFilter.strength = this.blurXFilter.strength = 4;//4// 4 + + this.padding = 100 + +} + +BlurFilter.prototype = Object.create(core.Filter.prototype); +BlurFilter.prototype.constructor = BlurFilter; +module.exports = BlurFilter; + +BlurFilter.prototype.apply = function (filterManager, input, output) +{ + var renderTarget = filterManager.getRenderTarget(true); + + this.blurXFilter.apply(filterManager, input, renderTarget, true); + this.blurYFilter.apply(filterManager, renderTarget, output); + + filterManager.returnRenderTarget(renderTarget); +}; + +Object.defineProperties(BlurFilter.prototype, { + /** + * Sets the strength of both the blurX and blurY properties simultaneously + * + * @member {number} + * @memberOf PIXI.filters.BlurFilter# + * @default 2 + */ + blur: { + get: function () + { + return this.blurXFilter.blur; + }, + set: function (value) + { + this.padding = Math.abs(value) * 0.5; + this.blurXFilter.blur = this.blurYFilter.blur = value; + } + }, + + /** + * Sets the number of passes for blur. More passes means higher quaility bluring. + * + * @member {number} + * @memberof PIXI.filters.BlurYFilter# + * @default 1 + */ + passes: { + get: function () + { + return this.blurXFilter.passes; + }, + set: function (value) + { + this.blurXFilter.passes = this.blurYFilter.passes = value; + } + }, + + /** + * Sets the strength of the blurX property + * + * @member {number} + * @memberOf PIXI.filters.BlurFilter# + * @default 2 + */ + blurX: { + get: function () + { + return this.blurXFilter.blur; + }, + set: function (value) + { + this.blurXFilter.blur = value; + } + }, + + /** + * Sets the strength of the blurY property + * + * @member {number} + * @memberOf PIXI.filters.BlurFilter# + * @default 2 + */ + blurY: { + get: function () + { + return this.blurYFilter.blur; + }, + set: function (value) + { + this.blurYFilter.blur = value; + } + } +}); diff --git a/src/filters/blur/BlurXFilter.js b/src/filters/blur/BlurXFilter.js new file mode 100644 index 0000000..61eed96 --- /dev/null +++ b/src/filters/blur/BlurXFilter.js @@ -0,0 +1,94 @@ +var core = require('../../core'); +var glslify = require('glslify'); +var generateBlurVertSource = require('./generateBlurVertSource'); +var generateBlurFragSource = require('./generateBlurFragSource'); + +/** + * The BlurXFilter applies a horizontal Gaussian blur to an object. + * + * @class + * @extends PIXI.Filter + * @memberof PIXI.filters + */ +function BlurXFilter() +{ + var vertSrc = generateBlurVertSource(11, true); + var fragSrc = generateBlurFragSource(11); + + console.log(vertSrc); + console.log(fragSrc); + + core.Filter.call(this, + // vertex shader + vertSrc, + // fragment shader + fragSrc + ); + + /** + * Sets the number of passes for blur. More passes means higher quaility bluring. + * + * @member {number} + * @default 1 + */ + this.passes = 1; + this.resolution = 1;//0.25;//0.5;//0.1//5; + this.strength = 4; +} + +BlurXFilter.prototype = Object.create(core.Filter.prototype); +BlurXFilter.prototype.constructor = BlurXFilter; +module.exports = BlurXFilter; + +BlurXFilter.prototype.apply = function (filterManager, input, output, clear) +{ + this.uniforms.strength = (1/output.destinationFrame.width) * (output.size.width/input.size.width); /// // * 2 //4//this.strength / 4 / this.passes * (input.frame.width / input.size.width); + + // screen space! + this.uniforms.strength *= this.strength; + if(this.passes === 1) + { + filterManager.applyFilter(this, input, output, clear); + } + else + { + var renderTarget = filterManager.getRenderTarget(true); + var flip = input; + var flop = renderTarget; + + for(var i = 0; i < this.passes-1; i++) + { + filterManager.applyFilter(this, flip, flop, true); + + var temp = flop; + flop = flip; + flip = temp; + } + + filterManager.applyFilter(this, flip, output, clear); + + filterManager.returnRenderTarget(renderTarget); + } +}; + + +Object.defineProperties(BlurXFilter.prototype, { + /** + * Sets the strength of both the blur. + * + * @member {number} + * @memberof PIXI.filters.BlurXFilter# + * @default 2 + */ + blur: { + get: function () + { + return this.strength; + }, + set: function (value) + { + this.padding = Math.abs(value) * 0.5; + this.strength = value; + } + } +}); diff --git a/package.json b/package.json index 4436b84..48a074c 100644 --- a/package.json +++ b/package.json @@ -32,10 +32,8 @@ "dependencies": { "async": "^1.5.0", "bit-twiddle": "^1.0.2", - "brfs": "^1.4.1", "earcut": "^2.0.7", "eventemitter3": "^1.1.1", - "gl-matrix": "git+https://github.com/toji/gl-matrix.git", "object-assign": "^4.0.1", "pixi-gl-core": "git+https://github.com/GoodBoyDigital/pixi-gl-core.git", "resource-loader": "^1.6.4" @@ -73,6 +71,5 @@ "transform": [ "glslify" ] - } } diff --git a/src/core/graphics/webgl/PrimitiveShader.js b/src/core/graphics/webgl/PrimitiveShader.js deleted file mode 100644 index 44166b3..0000000 --- a/src/core/graphics/webgl/PrimitiveShader.js +++ /dev/null @@ -1,50 +0,0 @@ -var Shader = require('pixi-gl-core').GLShader; - -/** - * This shader is used to draw simple primitive shapes for {@link PIXI.Graphics}. - * - * @class - * @memberof PIXI - * @extends PIXI.Shader - * @param shaderManager {ShaderManager} The webgl shader manager this shader works for. - */ -function PrimitiveShader(gl) -{ - Shader.call(this, - gl, - // vertex shader - [ - 'attribute vec2 aVertexPosition;', - 'attribute vec4 aColor;', - - 'uniform mat3 translationMatrix;', - 'uniform mat3 projectionMatrix;', - - 'uniform float alpha;', - 'uniform float flipY;', - 'uniform vec3 tint;', - - 'varying vec4 vColor;', - - 'void main(void){', - ' gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', - ' vColor = aColor * vec4(tint * alpha, alpha);', - '}' - ].join('\n'), - // fragment shader - [ - 'precision mediump float;', - - 'varying vec4 vColor;', - - 'void main(void){', - ' gl_FragColor = vColor;', - '}' - ].join('\n') - ); -} - -PrimitiveShader.prototype = Object.create(Shader.prototype); -PrimitiveShader.prototype.constructor = PrimitiveShader; - -module.exports = PrimitiveShader; diff --git a/src/core/math/Matrix.js b/src/core/math/Matrix.js index 4e7fe99..2313ae3 100644 --- a/src/core/math/Matrix.js +++ b/src/core/math/Matrix.js @@ -51,6 +51,7 @@ * @default 0 */ this.ty = 0; + } Matrix.prototype.constructor = Matrix; diff --git a/src/core/renderers/webgl/managers/FilterManager.js b/src/core/renderers/webgl/managers/FilterManager.js index b3f7463..5fc6562 100644 --- a/src/core/renderers/webgl/managers/FilterManager.js +++ b/src/core/renderers/webgl/managers/FilterManager.js @@ -64,11 +64,12 @@ - //TODO - should this be rounded to reoultion? not 1? - sourceFrame.x = targetBounds.x | 0; - sourceFrame.y = targetBounds.y | 0; - sourceFrame.width = targetBounds.width | 0; - sourceFrame.height = targetBounds.height | 0; + + sourceFrame.x = ((targetBounds.x * resolution) | 0) / resolution; + sourceFrame.y = ((targetBounds.y * resolution) | 0) / resolution; + sourceFrame.width = ((targetBounds.width * resolution) | 0) / resolution; + sourceFrame.height = ((targetBounds.height * resolution) | 0) / resolution; + sourceFrame.pad(padding * resolution); sourceFrame.fit(this.stack[0].destinationFrame); @@ -79,6 +80,7 @@ currentState.target = target; currentState.filters = filters; + currentState.resolution = resolution; currentState.renderTarget = renderTarget; // bind the render taget to draw the shape in the top corner.. @@ -236,6 +238,13 @@ shader.uniforms[i] = uniforms[i]; } } + else if(uniformData[i].type === 'float') + { + if(shader.uniforms.data[i].value !== uniformData[i]) + { + shader.uniforms[i] = uniforms[i]; + } + } else { shader.uniforms[i] = uniforms[i]; @@ -244,10 +253,18 @@ } -FilterManager.prototype.getPotRenderTarget = function() +FilterManager.prototype.getRenderTarget = function() { var currentState = this.stack[this.stackIndex]; - return FilterManager.getPotRenderTarget(renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, 1); + var renderTarget = FilterManager.getPotRenderTarget(renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, currentState.resolution); + renderTarget.setFrame(currentState.destinationFrame, currentState.sourceFrame); + + return renderTarget; +} + +FilterManager.prototype.returnRenderTarget = function(renderTarget) +{ + return FilterManager.freePotRenderTarget(renderTarget); } /* @@ -325,6 +342,7 @@ this.destinationFrame = new math.Rectangle(); this.filters = []; this.target = null; + this.resolution = 1; } FilterManager.pool = {} diff --git a/src/core/renderers/webgl/utils/RenderTarget.js b/src/core/renderers/webgl/utils/RenderTarget.js index ced94f6..d3daf50 100644 --- a/src/core/renderers/webgl/utils/RenderTarget.js +++ b/src/core/renderers/webgl/utils/RenderTarget.js @@ -136,6 +136,15 @@ { this.frameBuffer = GLFramebuffer.createRGBA(gl, 100, 100); + if( this.scaleMode === CONST.SCALE_MODES.NEAREST) + { + this.frameBuffer.texture.enableNearestScaling() + } + else + { + this.frameBuffer.texture.enableLinearScaling() + + } /* A frame buffer needs a target to render to.. create a texture and bind it attach it to the framebuffer.. @@ -213,8 +222,10 @@ this.projectionMatrix.append(this.transform); } + //TODO add a check as them may be the same! if(this.destinationFrame !== this.sourceFrame) { + gl.enable(gl.SCISSOR_TEST); gl.scissor(this.destinationFrame.x | 0,this.destinationFrame.y | 0, (this.destinationFrame.width * this.resolution) | 0, (this.destinationFrame.height* this.resolution) | 0); } @@ -279,8 +290,6 @@ return; } - console.log(width + " : " + height) - this.size.width = width; this.size.height = height; diff --git a/src/core/textures/BaseRenderTexture copy.js b/src/core/textures/BaseRenderTexture copy.js deleted file mode 100644 index acf6ac9..0000000 --- a/src/core/textures/BaseRenderTexture copy.js +++ /dev/null @@ -1,482 +0,0 @@ -var BaseTexture = require('./BaseTexture'), - Texture = require('./Texture'), - RenderTarget = require('../renderers/webgl/utils/RenderTarget'), - FilterManager = require('../renderers/webgl/managers/FilterManager'), - CanvasBuffer = require('../renderers/canvas/utils/CanvasBuffer'), - math = require('../math'), - CONST = require('../const'), - tempMatrix = new math.Matrix(), - tempRect = new math.Rectangle(); - -/** - * A BaseRenderTexture is a special texture that allows any Pixi display object to be rendered to it. - * - * __Hint__: All DisplayObjects (i.e. Sprites) that render to a BaseRenderTexture should be preloaded - * otherwise black rectangles will be drawn instead. - * - * A BaseRenderTexture takes a snapshot of any Display Object given to its render method. The position - * and rotation of the given Display Objects is ignored. For example: - * - * ```js - * var renderer = PIXI.autoDetectRenderer(1024, 1024, { view: canvas, ratio: 1 }); - * var BaserenderTexture = new PIXI.BaseRenderTexture(renderer, 800, 600); - * var sprite = PIXI.Sprite.fromImage("spinObj_01.png"); - * - * sprite.position.x = 800/2; - * sprite.position.y = 600/2; - * sprite.anchor.x = 0.5; - * sprite.anchor.y = 0.5; - * - * BaserenderTexture.render(sprite); - * ``` - * - * The Sprite in this case will be rendered to a position of 0,0. To render this sprite at its actual - * position a Container should be used: - * - * ```js - * var doc = new PIXI.Container(); - * - * doc.addChild(sprite); - * - * BaserenderTexture.render(doc); // Renders to center of BaserenderTexture - * ``` - * - * @class - * @extends PIXI.Texture - * @memberof PIXI - * @param renderer {PIXI.CanvasRenderer|PIXI.WebGLRenderer} The renderer used for this BaseRenderTexture - * @param [width=100] {number} The width of the render texture - * @param [height=100] {number} The height of the render texture - * @param [scaleMode] {number} See {@link PIXI.SCALE_MODES} for possible values - * @param [resolution=1] {number} The resolution of the texture being generated - */ -function BaseRenderTexture(renderer, width, height, scaleMode, resolution) -{ - if (!renderer) - { - throw new Error('Unable to create BaseRenderTexture, you must pass a renderer into the constructor.'); - } - - BaseTexture.call(this, null, scaleMode); - - this.width = width || 100; - this.height = height || 100; - - this.resolution = resolution || CONST.RESOLUTION;; - this.scaleMode = scaleMode || CONST.SCALE_MODES.DEFAULT; - this.hasLoaded = true; - - /** - * Draw/render the given DisplayObject onto the texture. - * - * The displayObject and descendents are transformed during this operation. - * If `updateTransform` is true then the transformations will be restored before the - * method returns. Otherwise it is up to the calling code to correctly use or reset - * the transformed display objects. - * - * The display object is always rendered with a worldAlpha value of 1. - * - * @method - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear=false] {boolean} If true the texture will be cleared before the displayObject is drawn - * @param [updateTransform=true] {boolean} If true the displayObject's worldTransform/worldAlpha and all children - * transformations will be restored. Not restoring this information will be a little faster. - */ - this.render = null; - - /** - * The renderer this BaseRenderTexture uses. A BaseRenderTexture can only belong to one renderer at the moment if its webGL. - * - * @member {PIXI.CanvasRenderer|PIXI.WebGLRenderer} - */ - this.renderer = renderer; - - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - var gl = this.renderer.gl; - - this.textureBuffer = new RenderTarget(gl, this.width, this.height, this.scaleMode, this.resolution);//, this.this.scaleMode); - this._glTextures[gl.id] = this.textureBuffer.texture; - - //TODO refactor filter manager.. as really its no longer a manager if we use it here.. - this.filterManager = new FilterManager(this.renderer); - this.filterManager.onContextChange(); - this.filterManager.resize(width, height); - this.render = this.renderWebGL; - - // the creation of a filter manager unbinds the buffers.. - this.renderer.currentRenderer.start(); - if(this.renderer._activeRenderTarget)this.renderer._activeRenderTarget.activate(); - } - else - { - - this.render = this.renderCanvas; - this.textureBuffer = new CanvasBuffer(this.width* this.resolution, this.height* this.resolution); - this.source = this.textureBuffer.canvas; - } - - /** - * @member {boolean} - */ - this.valid = true; - -} - -BaseRenderTexture.prototype = Object.create(BaseTexture.prototype); -BaseRenderTexture.prototype.constructor = BaseRenderTexture; -module.exports = BaseRenderTexture; - -/** - * Resizes the BaseRenderTexture. - * - * @param width {number} The width to resize to. - * @param height {number} The height to resize to. - * @param updateBase {boolean} Should the baseTexture.width and height values be resized as well? - */ -BaseRenderTexture.prototype.resize = function (width, height) -{ - if (width === this.width && height === this.height) - { - return; - } - - this.valid = (width > 0 && height > 0); - - this.width = width; - this.height = height; - - if (!this.valid) - { - return; - } - - this.textureBuffer.resize(this.width, this.height); - - if(this.filterManager) - { - this.filterManager.resize(this.width, this.height); - } -}; - -/** - * Clears the BaseRenderTexture. - * - */ -BaseRenderTexture.prototype.clear = function (destinationFrame) -{ - if (!this.valid) - { - return; - } - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - this.renderer.gl.bindFramebuffer(this.renderer.gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - } - - this.textureBuffer.clear(false, destinationFrame); -}; - -/** - * Internal method assigned to the `render` property if using a CanvasRenderer. - * - * @private - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear=false] {boolean} If true the texture will be cleared before the displayObject is drawn - * @param [updateTransform=true] {boolean} If true the displayObject's worldTransform/worldAlpha and all children - * transformations will be restored. Not restoring this information will be a little faster. - */ -BaseRenderTexture.prototype.renderWebGL = function (frame, displayObject, matrix, clear, updateTransform) -{ - if (!this.valid) - { - return; - } - - - updateTransform = (updateTransform !== undefined) ? updateTransform : true;//!updateTransform; - - this.textureBuffer.transform = matrix; - - //TODO not a fan that this is here... it will move! - this.textureBuffer.activate(); - - // setWorld Alpha to ensure that the object is renderer at full opacity - displayObject.worldAlpha = 1; - - if (updateTransform) - { - - // reset the matrix of the displatyObject.. - displayObject.worldTransform.identity(); - - displayObject.currentBounds = null; - - // Time to update all the children of the displayObject with the new matrix.. - var children = displayObject.children; - var i, j; - - for (i = 0, j = children.length; i < j; ++i) - { - children[i].updateTransform(); - } - } - - tempRect.width = frame.height; - tempRect.height = frame.width; - - //TODO rename textureBuffer to renderTarget.. - var temp = this.renderer.filterManager; - - this.renderer.filterManager = this.filterManager; - - - this.textureBuffer.activate(frame, tempRect); - console.log(displayObject) - this.renderer.renderDisplayObject(displayObject, this.textureBuffer, clear); - - // console.log("RENDERING "); - this.renderer.filterManager = temp; -}; - - -/** - * Internal method assigned to the `render` property if using a CanvasRenderer. - * - * @private - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear] {boolean} If true the texture will be cleared before the displayObject is drawn - */ -BaseRenderTexture.prototype.renderCanvas = function (frame, displayObject, matrix, clear, updateTransform) -{ - if (!this.valid) - { - return; - } - - updateTransform = !!updateTransform; - - var wt = tempMatrix; - - wt.identity(); - - if (matrix) - { - wt.append(matrix); - } - - - wt.tx += frame.x; - wt.ty += frame.y; - - var cachedWt = displayObject.worldTransform; - - displayObject.worldTransform = wt; - - // setWorld Alpha to ensure that the object is renderer at full opacity - displayObject.worldAlpha = 1; - - // Time to update all the children of the displayObject with the new matrix.. - var children = displayObject.children; - var i, j; - - for (i = 0, j = children.length; i < j; ++i) - { - children[i].updateTransform(); - } - - if (clear) - { - this.textureBuffer.clear(); - } - - -// this.textureBuffer. - var context = this.textureBuffer.context; - - var realResolution = this.renderer.resolution; - - this.renderer.resolution = this.resolution; - - this.renderer.renderDisplayObject(displayObject, context); - - this.renderer.resolution = realResolution; - - if(displayObject.worldTransform === wt) - { - // fixes cacheAsBitmap Happening during the above.. - displayObject.worldTransform = cachedWt; - } - -}; - -/** - * Destroys this texture - * - * @param destroyBase {boolean} Whether to destroy the base texture as well - */ -BaseRenderTexture.prototype.destroy = function () -{ - Texture.prototype.destroy.call(this, true); - - this.textureBuffer.destroy(); - - // destroy the filtermanager.. - if(this.filterManager) - { - this.filterManager.destroy(); - } - - this.renderer = null; -}; - -/** - * Will return a HTML Image of the texture - * - * @return {Image} - */ -BaseRenderTexture.prototype.getImage = function (frame) -{ - var image = new Image(); - image.src = this.getBase64(frame); - return image; -}; - -/** - * Will return a a base64 encoded string of this texture. It works by calling BaseRenderTexture.getCanvas and then running toDataURL on that. - * - * @return {string} A base64 encoded string of the texture. - */ -BaseRenderTexture.prototype.getBase64 = function ( frame ) -{ - return this.getCanvas(frame).toDataURL(); -}; - -/** - * Creates a Canvas element, renders this BaseRenderTexture to it and then returns it. - * - * @return {HTMLCanvasElement} A Canvas element with the texture rendered on. - */ -BaseRenderTexture.prototype.getCanvas = function ( frame ) -{ - - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.size.width; - frame.height = this.textureBuffer.size.height; - } - - var width = frame.width * this.resolution; - var height = frame.height * this.resolution; - - var gl = this.renderer.gl; - - var webGLPixels = new Uint8Array(4 * width * height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - gl.readPixels(frame.x * this.resolution, frame.y * this.resolution, width, height, gl.RGBA, gl.UNSIGNED_BYTE, webGLPixels); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - var tempCanvas = new CanvasBuffer(width, height); - var canvasData = tempCanvas.context.getImageData(0, 0, width, height); - canvasData.data.set(webGLPixels); - - tempCanvas.context.putImageData(canvasData, 0, 0); - - return tempCanvas.canvas; - } - else - { - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.canvas.width; - frame.height = this.textureBuffer.canvas.height; - } - - if(frame.width === this.textureBuffer.canvas.width && - frame.height === this.textureBuffer.canvas.height ) - { - return this.textureBuffer.canvas; - } - else - { - - var resolution = this.resolution; - - var tempCanvas = new CanvasBuffer(frame.width * resolution, frame.height * resolution); - var canvasData = this.textureBuffer.context.getImageData(frame.x * resolution, frame.y * resolution, frame.width * resolution, frame.height * resolution); - - tempCanvas.context.putImageData(canvasData, 0, 0); - - return tempCanvas.canvas; - } - } -}; - -/** - * Will return a one-dimensional array containing the pixel data of the entire texture in RGBA order, with integer values between 0 and 255 (included). - * - * @return {Uint8ClampedArray} - */ -BaseRenderTexture.prototype.getPixels = function ( frame ) -{ - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.size.width; - frame.height = this.textureBuffer.size.height; - } - - var width = frame.width * this.resolution; - var height = frame.height * this.resolution; - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - var gl = this.renderer.gl; - - var webGLPixels = new Uint8Array(4 * width * height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - gl.readPixels(frame.x * this.resolution, frame.y * this.resolution, width, height, gl.RGBA, gl.UNSIGNED_BYTE, webGLPixels); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - return webGLPixels; - } - else - { - return this.textureBuffer.canvas.getContext('2d').getImageData(frame.x * this.resolution, frame.y * this.resolution, width, height).data; - } -}; - -/** - * Will return a one-dimensional array containing the pixel data of a pixel within the texture in RGBA order, with integer values between 0 and 255 (included). - * - * @param x {number} The x coordinate of the pixel to retrieve. - * @param y {number} The y coordinate of the pixel to retrieve. - * @return {Uint8ClampedArray} - */ -BaseRenderTexture.prototype.getPixel = function (frame, x, y) -{ - tempRect.x = x; - tempRect.y = y; - tempRect.width = 1 / this.resolution; - tempRect.height = 1 / this.resolution; - - if(frame) - { - tempRect.x += frame.x; - tempRect.y += frame.y; - } - - return this.getPixels(tempRect); -}; diff --git a/src/filters/blur/BlurFilter.js b/src/filters/blur/BlurFilter.js new file mode 100644 index 0000000..fb708a1 --- /dev/null +++ b/src/filters/blur/BlurFilter.js @@ -0,0 +1,114 @@ +var core = require('../../core'), + BlurXFilter = require('./BlurXFilter'), + BlurYFilter = require('./BlurYFilter'); + +/** + * The BlurFilter applies a Gaussian blur to an object. + * The strength of the blur can be set for x- and y-axis separately. + * + * @class + * @extends PIXI.Filter + * @memberof PIXI.filters + */ +function BlurFilter() +{ + core.Filter.call(this); + + this.blurXFilter = new BlurXFilter(); + this.blurYFilter = new BlurYFilter(); + this.resolution = 0.25;//0.25;//0.25//1//01.26; + this.blurYFilter.passes = this.blurXFilter.passes = 2; + this.blurYFilter.strength = this.blurXFilter.strength = 4;//4// 4 + + this.padding = 100 + +} + +BlurFilter.prototype = Object.create(core.Filter.prototype); +BlurFilter.prototype.constructor = BlurFilter; +module.exports = BlurFilter; + +BlurFilter.prototype.apply = function (filterManager, input, output) +{ + var renderTarget = filterManager.getRenderTarget(true); + + this.blurXFilter.apply(filterManager, input, renderTarget, true); + this.blurYFilter.apply(filterManager, renderTarget, output); + + filterManager.returnRenderTarget(renderTarget); +}; + +Object.defineProperties(BlurFilter.prototype, { + /** + * Sets the strength of both the blurX and blurY properties simultaneously + * + * @member {number} + * @memberOf PIXI.filters.BlurFilter# + * @default 2 + */ + blur: { + get: function () + { + return this.blurXFilter.blur; + }, + set: function (value) + { + this.padding = Math.abs(value) * 0.5; + this.blurXFilter.blur = this.blurYFilter.blur = value; + } + }, + + /** + * Sets the number of passes for blur. More passes means higher quaility bluring. + * + * @member {number} + * @memberof PIXI.filters.BlurYFilter# + * @default 1 + */ + passes: { + get: function () + { + return this.blurXFilter.passes; + }, + set: function (value) + { + this.blurXFilter.passes = this.blurYFilter.passes = value; + } + }, + + /** + * Sets the strength of the blurX property + * + * @member {number} + * @memberOf PIXI.filters.BlurFilter# + * @default 2 + */ + blurX: { + get: function () + { + return this.blurXFilter.blur; + }, + set: function (value) + { + this.blurXFilter.blur = value; + } + }, + + /** + * Sets the strength of the blurY property + * + * @member {number} + * @memberOf PIXI.filters.BlurFilter# + * @default 2 + */ + blurY: { + get: function () + { + return this.blurYFilter.blur; + }, + set: function (value) + { + this.blurYFilter.blur = value; + } + } +}); diff --git a/src/filters/blur/BlurXFilter.js b/src/filters/blur/BlurXFilter.js new file mode 100644 index 0000000..61eed96 --- /dev/null +++ b/src/filters/blur/BlurXFilter.js @@ -0,0 +1,94 @@ +var core = require('../../core'); +var glslify = require('glslify'); +var generateBlurVertSource = require('./generateBlurVertSource'); +var generateBlurFragSource = require('./generateBlurFragSource'); + +/** + * The BlurXFilter applies a horizontal Gaussian blur to an object. + * + * @class + * @extends PIXI.Filter + * @memberof PIXI.filters + */ +function BlurXFilter() +{ + var vertSrc = generateBlurVertSource(11, true); + var fragSrc = generateBlurFragSource(11); + + console.log(vertSrc); + console.log(fragSrc); + + core.Filter.call(this, + // vertex shader + vertSrc, + // fragment shader + fragSrc + ); + + /** + * Sets the number of passes for blur. More passes means higher quaility bluring. + * + * @member {number} + * @default 1 + */ + this.passes = 1; + this.resolution = 1;//0.25;//0.5;//0.1//5; + this.strength = 4; +} + +BlurXFilter.prototype = Object.create(core.Filter.prototype); +BlurXFilter.prototype.constructor = BlurXFilter; +module.exports = BlurXFilter; + +BlurXFilter.prototype.apply = function (filterManager, input, output, clear) +{ + this.uniforms.strength = (1/output.destinationFrame.width) * (output.size.width/input.size.width); /// // * 2 //4//this.strength / 4 / this.passes * (input.frame.width / input.size.width); + + // screen space! + this.uniforms.strength *= this.strength; + if(this.passes === 1) + { + filterManager.applyFilter(this, input, output, clear); + } + else + { + var renderTarget = filterManager.getRenderTarget(true); + var flip = input; + var flop = renderTarget; + + for(var i = 0; i < this.passes-1; i++) + { + filterManager.applyFilter(this, flip, flop, true); + + var temp = flop; + flop = flip; + flip = temp; + } + + filterManager.applyFilter(this, flip, output, clear); + + filterManager.returnRenderTarget(renderTarget); + } +}; + + +Object.defineProperties(BlurXFilter.prototype, { + /** + * Sets the strength of both the blur. + * + * @member {number} + * @memberof PIXI.filters.BlurXFilter# + * @default 2 + */ + blur: { + get: function () + { + return this.strength; + }, + set: function (value) + { + this.padding = Math.abs(value) * 0.5; + this.strength = value; + } + } +}); diff --git a/src/filters/blur/BlurYFilter.js b/src/filters/blur/BlurYFilter.js new file mode 100644 index 0000000..86a3171 --- /dev/null +++ b/src/filters/blur/BlurYFilter.js @@ -0,0 +1,85 @@ +var core = require('../../core'); +var generateBlurVertSource = require('./generateBlurVertSource'); +var generateBlurFragSource = require('./generateBlurFragSource'); + + +/** + * The BlurYFilter applies a horizontal Gaussian blur to an object. + * + * @class + * @extends PIXI.Filter + * @memberof PIXI.filters + */ +function BlurYFilter() +{ + var vertSrc = generateBlurVertSource(11, false); + var fragSrc = generateBlurFragSource(11); + + core.Filter.call(this, + // vertex shader + vertSrc, + // fragment shader + fragSrc + ); + + this.passes = 1; + this.resolution = 1;//0.25;//0.5;//0.1//5; + this.strength = 4; +} + +BlurYFilter.prototype = Object.create(core.Filter.prototype); +BlurYFilter.prototype.constructor = BlurYFilter; +module.exports = BlurYFilter; + +BlurYFilter.prototype.apply = function (filterManager, input, output, clear) +{ + this.uniforms.strength = (1/output.destinationFrame.height) * (output.size.height/input.size.height); /// // * 2 //4//this.strength / 4 / this.passes * (input.frame.width / input.size.width); + + this.uniforms.strength *= this.strength; + + if(this.passes === 1) + { + filterManager.applyFilter(this, input, output, clear); + } + else + { + var renderTarget = filterManager.getRenderTarget(true); + var flip = input; + var flop = renderTarget; + + for(var i = 0; i < this.passes-1; i++) + { + filterManager.applyFilter(this, flip, flop, true); + + var temp = flop; + flop = flip; + flip = temp; + } + + filterManager.applyFilter(this, flip, output, clear); + + filterManager.returnRenderTarget(renderTarget); + } +}; + + +Object.defineProperties(BlurYFilter.prototype, { + /** + * Sets the strength of both the blur. + * + * @member {number} + * @memberof PIXI.filters.BlurYFilter# + * @default 2 + */ + blur: { + get: function () + { + return this.strength; + }, + set: function (value) + { + this.padding = Math.abs(value) * 0.5; + this.strength = value; + } + } +}); diff --git a/package.json b/package.json index 4436b84..48a074c 100644 --- a/package.json +++ b/package.json @@ -32,10 +32,8 @@ "dependencies": { "async": "^1.5.0", "bit-twiddle": "^1.0.2", - "brfs": "^1.4.1", "earcut": "^2.0.7", "eventemitter3": "^1.1.1", - "gl-matrix": "git+https://github.com/toji/gl-matrix.git", "object-assign": "^4.0.1", "pixi-gl-core": "git+https://github.com/GoodBoyDigital/pixi-gl-core.git", "resource-loader": "^1.6.4" @@ -73,6 +71,5 @@ "transform": [ "glslify" ] - } } diff --git a/src/core/graphics/webgl/PrimitiveShader.js b/src/core/graphics/webgl/PrimitiveShader.js deleted file mode 100644 index 44166b3..0000000 --- a/src/core/graphics/webgl/PrimitiveShader.js +++ /dev/null @@ -1,50 +0,0 @@ -var Shader = require('pixi-gl-core').GLShader; - -/** - * This shader is used to draw simple primitive shapes for {@link PIXI.Graphics}. - * - * @class - * @memberof PIXI - * @extends PIXI.Shader - * @param shaderManager {ShaderManager} The webgl shader manager this shader works for. - */ -function PrimitiveShader(gl) -{ - Shader.call(this, - gl, - // vertex shader - [ - 'attribute vec2 aVertexPosition;', - 'attribute vec4 aColor;', - - 'uniform mat3 translationMatrix;', - 'uniform mat3 projectionMatrix;', - - 'uniform float alpha;', - 'uniform float flipY;', - 'uniform vec3 tint;', - - 'varying vec4 vColor;', - - 'void main(void){', - ' gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', - ' vColor = aColor * vec4(tint * alpha, alpha);', - '}' - ].join('\n'), - // fragment shader - [ - 'precision mediump float;', - - 'varying vec4 vColor;', - - 'void main(void){', - ' gl_FragColor = vColor;', - '}' - ].join('\n') - ); -} - -PrimitiveShader.prototype = Object.create(Shader.prototype); -PrimitiveShader.prototype.constructor = PrimitiveShader; - -module.exports = PrimitiveShader; diff --git a/src/core/math/Matrix.js b/src/core/math/Matrix.js index 4e7fe99..2313ae3 100644 --- a/src/core/math/Matrix.js +++ b/src/core/math/Matrix.js @@ -51,6 +51,7 @@ * @default 0 */ this.ty = 0; + } Matrix.prototype.constructor = Matrix; diff --git a/src/core/renderers/webgl/managers/FilterManager.js b/src/core/renderers/webgl/managers/FilterManager.js index b3f7463..5fc6562 100644 --- a/src/core/renderers/webgl/managers/FilterManager.js +++ b/src/core/renderers/webgl/managers/FilterManager.js @@ -64,11 +64,12 @@ - //TODO - should this be rounded to reoultion? not 1? - sourceFrame.x = targetBounds.x | 0; - sourceFrame.y = targetBounds.y | 0; - sourceFrame.width = targetBounds.width | 0; - sourceFrame.height = targetBounds.height | 0; + + sourceFrame.x = ((targetBounds.x * resolution) | 0) / resolution; + sourceFrame.y = ((targetBounds.y * resolution) | 0) / resolution; + sourceFrame.width = ((targetBounds.width * resolution) | 0) / resolution; + sourceFrame.height = ((targetBounds.height * resolution) | 0) / resolution; + sourceFrame.pad(padding * resolution); sourceFrame.fit(this.stack[0].destinationFrame); @@ -79,6 +80,7 @@ currentState.target = target; currentState.filters = filters; + currentState.resolution = resolution; currentState.renderTarget = renderTarget; // bind the render taget to draw the shape in the top corner.. @@ -236,6 +238,13 @@ shader.uniforms[i] = uniforms[i]; } } + else if(uniformData[i].type === 'float') + { + if(shader.uniforms.data[i].value !== uniformData[i]) + { + shader.uniforms[i] = uniforms[i]; + } + } else { shader.uniforms[i] = uniforms[i]; @@ -244,10 +253,18 @@ } -FilterManager.prototype.getPotRenderTarget = function() +FilterManager.prototype.getRenderTarget = function() { var currentState = this.stack[this.stackIndex]; - return FilterManager.getPotRenderTarget(renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, 1); + var renderTarget = FilterManager.getPotRenderTarget(renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, currentState.resolution); + renderTarget.setFrame(currentState.destinationFrame, currentState.sourceFrame); + + return renderTarget; +} + +FilterManager.prototype.returnRenderTarget = function(renderTarget) +{ + return FilterManager.freePotRenderTarget(renderTarget); } /* @@ -325,6 +342,7 @@ this.destinationFrame = new math.Rectangle(); this.filters = []; this.target = null; + this.resolution = 1; } FilterManager.pool = {} diff --git a/src/core/renderers/webgl/utils/RenderTarget.js b/src/core/renderers/webgl/utils/RenderTarget.js index ced94f6..d3daf50 100644 --- a/src/core/renderers/webgl/utils/RenderTarget.js +++ b/src/core/renderers/webgl/utils/RenderTarget.js @@ -136,6 +136,15 @@ { this.frameBuffer = GLFramebuffer.createRGBA(gl, 100, 100); + if( this.scaleMode === CONST.SCALE_MODES.NEAREST) + { + this.frameBuffer.texture.enableNearestScaling() + } + else + { + this.frameBuffer.texture.enableLinearScaling() + + } /* A frame buffer needs a target to render to.. create a texture and bind it attach it to the framebuffer.. @@ -213,8 +222,10 @@ this.projectionMatrix.append(this.transform); } + //TODO add a check as them may be the same! if(this.destinationFrame !== this.sourceFrame) { + gl.enable(gl.SCISSOR_TEST); gl.scissor(this.destinationFrame.x | 0,this.destinationFrame.y | 0, (this.destinationFrame.width * this.resolution) | 0, (this.destinationFrame.height* this.resolution) | 0); } @@ -279,8 +290,6 @@ return; } - console.log(width + " : " + height) - this.size.width = width; this.size.height = height; diff --git a/src/core/textures/BaseRenderTexture copy.js b/src/core/textures/BaseRenderTexture copy.js deleted file mode 100644 index acf6ac9..0000000 --- a/src/core/textures/BaseRenderTexture copy.js +++ /dev/null @@ -1,482 +0,0 @@ -var BaseTexture = require('./BaseTexture'), - Texture = require('./Texture'), - RenderTarget = require('../renderers/webgl/utils/RenderTarget'), - FilterManager = require('../renderers/webgl/managers/FilterManager'), - CanvasBuffer = require('../renderers/canvas/utils/CanvasBuffer'), - math = require('../math'), - CONST = require('../const'), - tempMatrix = new math.Matrix(), - tempRect = new math.Rectangle(); - -/** - * A BaseRenderTexture is a special texture that allows any Pixi display object to be rendered to it. - * - * __Hint__: All DisplayObjects (i.e. Sprites) that render to a BaseRenderTexture should be preloaded - * otherwise black rectangles will be drawn instead. - * - * A BaseRenderTexture takes a snapshot of any Display Object given to its render method. The position - * and rotation of the given Display Objects is ignored. For example: - * - * ```js - * var renderer = PIXI.autoDetectRenderer(1024, 1024, { view: canvas, ratio: 1 }); - * var BaserenderTexture = new PIXI.BaseRenderTexture(renderer, 800, 600); - * var sprite = PIXI.Sprite.fromImage("spinObj_01.png"); - * - * sprite.position.x = 800/2; - * sprite.position.y = 600/2; - * sprite.anchor.x = 0.5; - * sprite.anchor.y = 0.5; - * - * BaserenderTexture.render(sprite); - * ``` - * - * The Sprite in this case will be rendered to a position of 0,0. To render this sprite at its actual - * position a Container should be used: - * - * ```js - * var doc = new PIXI.Container(); - * - * doc.addChild(sprite); - * - * BaserenderTexture.render(doc); // Renders to center of BaserenderTexture - * ``` - * - * @class - * @extends PIXI.Texture - * @memberof PIXI - * @param renderer {PIXI.CanvasRenderer|PIXI.WebGLRenderer} The renderer used for this BaseRenderTexture - * @param [width=100] {number} The width of the render texture - * @param [height=100] {number} The height of the render texture - * @param [scaleMode] {number} See {@link PIXI.SCALE_MODES} for possible values - * @param [resolution=1] {number} The resolution of the texture being generated - */ -function BaseRenderTexture(renderer, width, height, scaleMode, resolution) -{ - if (!renderer) - { - throw new Error('Unable to create BaseRenderTexture, you must pass a renderer into the constructor.'); - } - - BaseTexture.call(this, null, scaleMode); - - this.width = width || 100; - this.height = height || 100; - - this.resolution = resolution || CONST.RESOLUTION;; - this.scaleMode = scaleMode || CONST.SCALE_MODES.DEFAULT; - this.hasLoaded = true; - - /** - * Draw/render the given DisplayObject onto the texture. - * - * The displayObject and descendents are transformed during this operation. - * If `updateTransform` is true then the transformations will be restored before the - * method returns. Otherwise it is up to the calling code to correctly use or reset - * the transformed display objects. - * - * The display object is always rendered with a worldAlpha value of 1. - * - * @method - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear=false] {boolean} If true the texture will be cleared before the displayObject is drawn - * @param [updateTransform=true] {boolean} If true the displayObject's worldTransform/worldAlpha and all children - * transformations will be restored. Not restoring this information will be a little faster. - */ - this.render = null; - - /** - * The renderer this BaseRenderTexture uses. A BaseRenderTexture can only belong to one renderer at the moment if its webGL. - * - * @member {PIXI.CanvasRenderer|PIXI.WebGLRenderer} - */ - this.renderer = renderer; - - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - var gl = this.renderer.gl; - - this.textureBuffer = new RenderTarget(gl, this.width, this.height, this.scaleMode, this.resolution);//, this.this.scaleMode); - this._glTextures[gl.id] = this.textureBuffer.texture; - - //TODO refactor filter manager.. as really its no longer a manager if we use it here.. - this.filterManager = new FilterManager(this.renderer); - this.filterManager.onContextChange(); - this.filterManager.resize(width, height); - this.render = this.renderWebGL; - - // the creation of a filter manager unbinds the buffers.. - this.renderer.currentRenderer.start(); - if(this.renderer._activeRenderTarget)this.renderer._activeRenderTarget.activate(); - } - else - { - - this.render = this.renderCanvas; - this.textureBuffer = new CanvasBuffer(this.width* this.resolution, this.height* this.resolution); - this.source = this.textureBuffer.canvas; - } - - /** - * @member {boolean} - */ - this.valid = true; - -} - -BaseRenderTexture.prototype = Object.create(BaseTexture.prototype); -BaseRenderTexture.prototype.constructor = BaseRenderTexture; -module.exports = BaseRenderTexture; - -/** - * Resizes the BaseRenderTexture. - * - * @param width {number} The width to resize to. - * @param height {number} The height to resize to. - * @param updateBase {boolean} Should the baseTexture.width and height values be resized as well? - */ -BaseRenderTexture.prototype.resize = function (width, height) -{ - if (width === this.width && height === this.height) - { - return; - } - - this.valid = (width > 0 && height > 0); - - this.width = width; - this.height = height; - - if (!this.valid) - { - return; - } - - this.textureBuffer.resize(this.width, this.height); - - if(this.filterManager) - { - this.filterManager.resize(this.width, this.height); - } -}; - -/** - * Clears the BaseRenderTexture. - * - */ -BaseRenderTexture.prototype.clear = function (destinationFrame) -{ - if (!this.valid) - { - return; - } - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - this.renderer.gl.bindFramebuffer(this.renderer.gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - } - - this.textureBuffer.clear(false, destinationFrame); -}; - -/** - * Internal method assigned to the `render` property if using a CanvasRenderer. - * - * @private - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear=false] {boolean} If true the texture will be cleared before the displayObject is drawn - * @param [updateTransform=true] {boolean} If true the displayObject's worldTransform/worldAlpha and all children - * transformations will be restored. Not restoring this information will be a little faster. - */ -BaseRenderTexture.prototype.renderWebGL = function (frame, displayObject, matrix, clear, updateTransform) -{ - if (!this.valid) - { - return; - } - - - updateTransform = (updateTransform !== undefined) ? updateTransform : true;//!updateTransform; - - this.textureBuffer.transform = matrix; - - //TODO not a fan that this is here... it will move! - this.textureBuffer.activate(); - - // setWorld Alpha to ensure that the object is renderer at full opacity - displayObject.worldAlpha = 1; - - if (updateTransform) - { - - // reset the matrix of the displatyObject.. - displayObject.worldTransform.identity(); - - displayObject.currentBounds = null; - - // Time to update all the children of the displayObject with the new matrix.. - var children = displayObject.children; - var i, j; - - for (i = 0, j = children.length; i < j; ++i) - { - children[i].updateTransform(); - } - } - - tempRect.width = frame.height; - tempRect.height = frame.width; - - //TODO rename textureBuffer to renderTarget.. - var temp = this.renderer.filterManager; - - this.renderer.filterManager = this.filterManager; - - - this.textureBuffer.activate(frame, tempRect); - console.log(displayObject) - this.renderer.renderDisplayObject(displayObject, this.textureBuffer, clear); - - // console.log("RENDERING "); - this.renderer.filterManager = temp; -}; - - -/** - * Internal method assigned to the `render` property if using a CanvasRenderer. - * - * @private - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear] {boolean} If true the texture will be cleared before the displayObject is drawn - */ -BaseRenderTexture.prototype.renderCanvas = function (frame, displayObject, matrix, clear, updateTransform) -{ - if (!this.valid) - { - return; - } - - updateTransform = !!updateTransform; - - var wt = tempMatrix; - - wt.identity(); - - if (matrix) - { - wt.append(matrix); - } - - - wt.tx += frame.x; - wt.ty += frame.y; - - var cachedWt = displayObject.worldTransform; - - displayObject.worldTransform = wt; - - // setWorld Alpha to ensure that the object is renderer at full opacity - displayObject.worldAlpha = 1; - - // Time to update all the children of the displayObject with the new matrix.. - var children = displayObject.children; - var i, j; - - for (i = 0, j = children.length; i < j; ++i) - { - children[i].updateTransform(); - } - - if (clear) - { - this.textureBuffer.clear(); - } - - -// this.textureBuffer. - var context = this.textureBuffer.context; - - var realResolution = this.renderer.resolution; - - this.renderer.resolution = this.resolution; - - this.renderer.renderDisplayObject(displayObject, context); - - this.renderer.resolution = realResolution; - - if(displayObject.worldTransform === wt) - { - // fixes cacheAsBitmap Happening during the above.. - displayObject.worldTransform = cachedWt; - } - -}; - -/** - * Destroys this texture - * - * @param destroyBase {boolean} Whether to destroy the base texture as well - */ -BaseRenderTexture.prototype.destroy = function () -{ - Texture.prototype.destroy.call(this, true); - - this.textureBuffer.destroy(); - - // destroy the filtermanager.. - if(this.filterManager) - { - this.filterManager.destroy(); - } - - this.renderer = null; -}; - -/** - * Will return a HTML Image of the texture - * - * @return {Image} - */ -BaseRenderTexture.prototype.getImage = function (frame) -{ - var image = new Image(); - image.src = this.getBase64(frame); - return image; -}; - -/** - * Will return a a base64 encoded string of this texture. It works by calling BaseRenderTexture.getCanvas and then running toDataURL on that. - * - * @return {string} A base64 encoded string of the texture. - */ -BaseRenderTexture.prototype.getBase64 = function ( frame ) -{ - return this.getCanvas(frame).toDataURL(); -}; - -/** - * Creates a Canvas element, renders this BaseRenderTexture to it and then returns it. - * - * @return {HTMLCanvasElement} A Canvas element with the texture rendered on. - */ -BaseRenderTexture.prototype.getCanvas = function ( frame ) -{ - - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.size.width; - frame.height = this.textureBuffer.size.height; - } - - var width = frame.width * this.resolution; - var height = frame.height * this.resolution; - - var gl = this.renderer.gl; - - var webGLPixels = new Uint8Array(4 * width * height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - gl.readPixels(frame.x * this.resolution, frame.y * this.resolution, width, height, gl.RGBA, gl.UNSIGNED_BYTE, webGLPixels); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - var tempCanvas = new CanvasBuffer(width, height); - var canvasData = tempCanvas.context.getImageData(0, 0, width, height); - canvasData.data.set(webGLPixels); - - tempCanvas.context.putImageData(canvasData, 0, 0); - - return tempCanvas.canvas; - } - else - { - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.canvas.width; - frame.height = this.textureBuffer.canvas.height; - } - - if(frame.width === this.textureBuffer.canvas.width && - frame.height === this.textureBuffer.canvas.height ) - { - return this.textureBuffer.canvas; - } - else - { - - var resolution = this.resolution; - - var tempCanvas = new CanvasBuffer(frame.width * resolution, frame.height * resolution); - var canvasData = this.textureBuffer.context.getImageData(frame.x * resolution, frame.y * resolution, frame.width * resolution, frame.height * resolution); - - tempCanvas.context.putImageData(canvasData, 0, 0); - - return tempCanvas.canvas; - } - } -}; - -/** - * Will return a one-dimensional array containing the pixel data of the entire texture in RGBA order, with integer values between 0 and 255 (included). - * - * @return {Uint8ClampedArray} - */ -BaseRenderTexture.prototype.getPixels = function ( frame ) -{ - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.size.width; - frame.height = this.textureBuffer.size.height; - } - - var width = frame.width * this.resolution; - var height = frame.height * this.resolution; - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - var gl = this.renderer.gl; - - var webGLPixels = new Uint8Array(4 * width * height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - gl.readPixels(frame.x * this.resolution, frame.y * this.resolution, width, height, gl.RGBA, gl.UNSIGNED_BYTE, webGLPixels); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - return webGLPixels; - } - else - { - return this.textureBuffer.canvas.getContext('2d').getImageData(frame.x * this.resolution, frame.y * this.resolution, width, height).data; - } -}; - -/** - * Will return a one-dimensional array containing the pixel data of a pixel within the texture in RGBA order, with integer values between 0 and 255 (included). - * - * @param x {number} The x coordinate of the pixel to retrieve. - * @param y {number} The y coordinate of the pixel to retrieve. - * @return {Uint8ClampedArray} - */ -BaseRenderTexture.prototype.getPixel = function (frame, x, y) -{ - tempRect.x = x; - tempRect.y = y; - tempRect.width = 1 / this.resolution; - tempRect.height = 1 / this.resolution; - - if(frame) - { - tempRect.x += frame.x; - tempRect.y += frame.y; - } - - return this.getPixels(tempRect); -}; diff --git a/src/filters/blur/BlurFilter.js b/src/filters/blur/BlurFilter.js new file mode 100644 index 0000000..fb708a1 --- /dev/null +++ b/src/filters/blur/BlurFilter.js @@ -0,0 +1,114 @@ +var core = require('../../core'), + BlurXFilter = require('./BlurXFilter'), + BlurYFilter = require('./BlurYFilter'); + +/** + * The BlurFilter applies a Gaussian blur to an object. + * The strength of the blur can be set for x- and y-axis separately. + * + * @class + * @extends PIXI.Filter + * @memberof PIXI.filters + */ +function BlurFilter() +{ + core.Filter.call(this); + + this.blurXFilter = new BlurXFilter(); + this.blurYFilter = new BlurYFilter(); + this.resolution = 0.25;//0.25;//0.25//1//01.26; + this.blurYFilter.passes = this.blurXFilter.passes = 2; + this.blurYFilter.strength = this.blurXFilter.strength = 4;//4// 4 + + this.padding = 100 + +} + +BlurFilter.prototype = Object.create(core.Filter.prototype); +BlurFilter.prototype.constructor = BlurFilter; +module.exports = BlurFilter; + +BlurFilter.prototype.apply = function (filterManager, input, output) +{ + var renderTarget = filterManager.getRenderTarget(true); + + this.blurXFilter.apply(filterManager, input, renderTarget, true); + this.blurYFilter.apply(filterManager, renderTarget, output); + + filterManager.returnRenderTarget(renderTarget); +}; + +Object.defineProperties(BlurFilter.prototype, { + /** + * Sets the strength of both the blurX and blurY properties simultaneously + * + * @member {number} + * @memberOf PIXI.filters.BlurFilter# + * @default 2 + */ + blur: { + get: function () + { + return this.blurXFilter.blur; + }, + set: function (value) + { + this.padding = Math.abs(value) * 0.5; + this.blurXFilter.blur = this.blurYFilter.blur = value; + } + }, + + /** + * Sets the number of passes for blur. More passes means higher quaility bluring. + * + * @member {number} + * @memberof PIXI.filters.BlurYFilter# + * @default 1 + */ + passes: { + get: function () + { + return this.blurXFilter.passes; + }, + set: function (value) + { + this.blurXFilter.passes = this.blurYFilter.passes = value; + } + }, + + /** + * Sets the strength of the blurX property + * + * @member {number} + * @memberOf PIXI.filters.BlurFilter# + * @default 2 + */ + blurX: { + get: function () + { + return this.blurXFilter.blur; + }, + set: function (value) + { + this.blurXFilter.blur = value; + } + }, + + /** + * Sets the strength of the blurY property + * + * @member {number} + * @memberOf PIXI.filters.BlurFilter# + * @default 2 + */ + blurY: { + get: function () + { + return this.blurYFilter.blur; + }, + set: function (value) + { + this.blurYFilter.blur = value; + } + } +}); diff --git a/src/filters/blur/BlurXFilter.js b/src/filters/blur/BlurXFilter.js new file mode 100644 index 0000000..61eed96 --- /dev/null +++ b/src/filters/blur/BlurXFilter.js @@ -0,0 +1,94 @@ +var core = require('../../core'); +var glslify = require('glslify'); +var generateBlurVertSource = require('./generateBlurVertSource'); +var generateBlurFragSource = require('./generateBlurFragSource'); + +/** + * The BlurXFilter applies a horizontal Gaussian blur to an object. + * + * @class + * @extends PIXI.Filter + * @memberof PIXI.filters + */ +function BlurXFilter() +{ + var vertSrc = generateBlurVertSource(11, true); + var fragSrc = generateBlurFragSource(11); + + console.log(vertSrc); + console.log(fragSrc); + + core.Filter.call(this, + // vertex shader + vertSrc, + // fragment shader + fragSrc + ); + + /** + * Sets the number of passes for blur. More passes means higher quaility bluring. + * + * @member {number} + * @default 1 + */ + this.passes = 1; + this.resolution = 1;//0.25;//0.5;//0.1//5; + this.strength = 4; +} + +BlurXFilter.prototype = Object.create(core.Filter.prototype); +BlurXFilter.prototype.constructor = BlurXFilter; +module.exports = BlurXFilter; + +BlurXFilter.prototype.apply = function (filterManager, input, output, clear) +{ + this.uniforms.strength = (1/output.destinationFrame.width) * (output.size.width/input.size.width); /// // * 2 //4//this.strength / 4 / this.passes * (input.frame.width / input.size.width); + + // screen space! + this.uniforms.strength *= this.strength; + if(this.passes === 1) + { + filterManager.applyFilter(this, input, output, clear); + } + else + { + var renderTarget = filterManager.getRenderTarget(true); + var flip = input; + var flop = renderTarget; + + for(var i = 0; i < this.passes-1; i++) + { + filterManager.applyFilter(this, flip, flop, true); + + var temp = flop; + flop = flip; + flip = temp; + } + + filterManager.applyFilter(this, flip, output, clear); + + filterManager.returnRenderTarget(renderTarget); + } +}; + + +Object.defineProperties(BlurXFilter.prototype, { + /** + * Sets the strength of both the blur. + * + * @member {number} + * @memberof PIXI.filters.BlurXFilter# + * @default 2 + */ + blur: { + get: function () + { + return this.strength; + }, + set: function (value) + { + this.padding = Math.abs(value) * 0.5; + this.strength = value; + } + } +}); diff --git a/src/filters/blur/BlurYFilter.js b/src/filters/blur/BlurYFilter.js new file mode 100644 index 0000000..86a3171 --- /dev/null +++ b/src/filters/blur/BlurYFilter.js @@ -0,0 +1,85 @@ +var core = require('../../core'); +var generateBlurVertSource = require('./generateBlurVertSource'); +var generateBlurFragSource = require('./generateBlurFragSource'); + + +/** + * The BlurYFilter applies a horizontal Gaussian blur to an object. + * + * @class + * @extends PIXI.Filter + * @memberof PIXI.filters + */ +function BlurYFilter() +{ + var vertSrc = generateBlurVertSource(11, false); + var fragSrc = generateBlurFragSource(11); + + core.Filter.call(this, + // vertex shader + vertSrc, + // fragment shader + fragSrc + ); + + this.passes = 1; + this.resolution = 1;//0.25;//0.5;//0.1//5; + this.strength = 4; +} + +BlurYFilter.prototype = Object.create(core.Filter.prototype); +BlurYFilter.prototype.constructor = BlurYFilter; +module.exports = BlurYFilter; + +BlurYFilter.prototype.apply = function (filterManager, input, output, clear) +{ + this.uniforms.strength = (1/output.destinationFrame.height) * (output.size.height/input.size.height); /// // * 2 //4//this.strength / 4 / this.passes * (input.frame.width / input.size.width); + + this.uniforms.strength *= this.strength; + + if(this.passes === 1) + { + filterManager.applyFilter(this, input, output, clear); + } + else + { + var renderTarget = filterManager.getRenderTarget(true); + var flip = input; + var flop = renderTarget; + + for(var i = 0; i < this.passes-1; i++) + { + filterManager.applyFilter(this, flip, flop, true); + + var temp = flop; + flop = flip; + flip = temp; + } + + filterManager.applyFilter(this, flip, output, clear); + + filterManager.returnRenderTarget(renderTarget); + } +}; + + +Object.defineProperties(BlurYFilter.prototype, { + /** + * Sets the strength of both the blur. + * + * @member {number} + * @memberof PIXI.filters.BlurYFilter# + * @default 2 + */ + blur: { + get: function () + { + return this.strength; + }, + set: function (value) + { + this.padding = Math.abs(value) * 0.5; + this.strength = value; + } + } +}); diff --git a/src/filters/blur/blur.frag b/src/filters/blur/blur.frag new file mode 100644 index 0000000..0c4f23c --- /dev/null +++ b/src/filters/blur/blur.frag @@ -0,0 +1,31 @@ +precision mediump float; + +varying vec2 vTextureCoord; +varying vec2 vBlurTexCoords[15]; + +uniform sampler2D uSampler; + +void main(void) +{ + gl_FragColor = vec4(0.0); + + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 0]) * 0.000489; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 1]) * 0.002403; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 2]) * 0.009246; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 3]) * 0.02784; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 4]) * 0.065602; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 5]) * 0.120999; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 6]) * 0.174697; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 7]) * 0.197448; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 8]) * 0.174697; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 9]) * 0.120999; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 10]) * 0.065602; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 11]) * 0.02784; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 12]) * 0.009246; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 13]) * 0.002403; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 14]) * 0.000489; + + + + +} diff --git a/package.json b/package.json index 4436b84..48a074c 100644 --- a/package.json +++ b/package.json @@ -32,10 +32,8 @@ "dependencies": { "async": "^1.5.0", "bit-twiddle": "^1.0.2", - "brfs": "^1.4.1", "earcut": "^2.0.7", "eventemitter3": "^1.1.1", - "gl-matrix": "git+https://github.com/toji/gl-matrix.git", "object-assign": "^4.0.1", "pixi-gl-core": "git+https://github.com/GoodBoyDigital/pixi-gl-core.git", "resource-loader": "^1.6.4" @@ -73,6 +71,5 @@ "transform": [ "glslify" ] - } } diff --git a/src/core/graphics/webgl/PrimitiveShader.js b/src/core/graphics/webgl/PrimitiveShader.js deleted file mode 100644 index 44166b3..0000000 --- a/src/core/graphics/webgl/PrimitiveShader.js +++ /dev/null @@ -1,50 +0,0 @@ -var Shader = require('pixi-gl-core').GLShader; - -/** - * This shader is used to draw simple primitive shapes for {@link PIXI.Graphics}. - * - * @class - * @memberof PIXI - * @extends PIXI.Shader - * @param shaderManager {ShaderManager} The webgl shader manager this shader works for. - */ -function PrimitiveShader(gl) -{ - Shader.call(this, - gl, - // vertex shader - [ - 'attribute vec2 aVertexPosition;', - 'attribute vec4 aColor;', - - 'uniform mat3 translationMatrix;', - 'uniform mat3 projectionMatrix;', - - 'uniform float alpha;', - 'uniform float flipY;', - 'uniform vec3 tint;', - - 'varying vec4 vColor;', - - 'void main(void){', - ' gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', - ' vColor = aColor * vec4(tint * alpha, alpha);', - '}' - ].join('\n'), - // fragment shader - [ - 'precision mediump float;', - - 'varying vec4 vColor;', - - 'void main(void){', - ' gl_FragColor = vColor;', - '}' - ].join('\n') - ); -} - -PrimitiveShader.prototype = Object.create(Shader.prototype); -PrimitiveShader.prototype.constructor = PrimitiveShader; - -module.exports = PrimitiveShader; diff --git a/src/core/math/Matrix.js b/src/core/math/Matrix.js index 4e7fe99..2313ae3 100644 --- a/src/core/math/Matrix.js +++ b/src/core/math/Matrix.js @@ -51,6 +51,7 @@ * @default 0 */ this.ty = 0; + } Matrix.prototype.constructor = Matrix; diff --git a/src/core/renderers/webgl/managers/FilterManager.js b/src/core/renderers/webgl/managers/FilterManager.js index b3f7463..5fc6562 100644 --- a/src/core/renderers/webgl/managers/FilterManager.js +++ b/src/core/renderers/webgl/managers/FilterManager.js @@ -64,11 +64,12 @@ - //TODO - should this be rounded to reoultion? not 1? - sourceFrame.x = targetBounds.x | 0; - sourceFrame.y = targetBounds.y | 0; - sourceFrame.width = targetBounds.width | 0; - sourceFrame.height = targetBounds.height | 0; + + sourceFrame.x = ((targetBounds.x * resolution) | 0) / resolution; + sourceFrame.y = ((targetBounds.y * resolution) | 0) / resolution; + sourceFrame.width = ((targetBounds.width * resolution) | 0) / resolution; + sourceFrame.height = ((targetBounds.height * resolution) | 0) / resolution; + sourceFrame.pad(padding * resolution); sourceFrame.fit(this.stack[0].destinationFrame); @@ -79,6 +80,7 @@ currentState.target = target; currentState.filters = filters; + currentState.resolution = resolution; currentState.renderTarget = renderTarget; // bind the render taget to draw the shape in the top corner.. @@ -236,6 +238,13 @@ shader.uniforms[i] = uniforms[i]; } } + else if(uniformData[i].type === 'float') + { + if(shader.uniforms.data[i].value !== uniformData[i]) + { + shader.uniforms[i] = uniforms[i]; + } + } else { shader.uniforms[i] = uniforms[i]; @@ -244,10 +253,18 @@ } -FilterManager.prototype.getPotRenderTarget = function() +FilterManager.prototype.getRenderTarget = function() { var currentState = this.stack[this.stackIndex]; - return FilterManager.getPotRenderTarget(renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, 1); + var renderTarget = FilterManager.getPotRenderTarget(renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, currentState.resolution); + renderTarget.setFrame(currentState.destinationFrame, currentState.sourceFrame); + + return renderTarget; +} + +FilterManager.prototype.returnRenderTarget = function(renderTarget) +{ + return FilterManager.freePotRenderTarget(renderTarget); } /* @@ -325,6 +342,7 @@ this.destinationFrame = new math.Rectangle(); this.filters = []; this.target = null; + this.resolution = 1; } FilterManager.pool = {} diff --git a/src/core/renderers/webgl/utils/RenderTarget.js b/src/core/renderers/webgl/utils/RenderTarget.js index ced94f6..d3daf50 100644 --- a/src/core/renderers/webgl/utils/RenderTarget.js +++ b/src/core/renderers/webgl/utils/RenderTarget.js @@ -136,6 +136,15 @@ { this.frameBuffer = GLFramebuffer.createRGBA(gl, 100, 100); + if( this.scaleMode === CONST.SCALE_MODES.NEAREST) + { + this.frameBuffer.texture.enableNearestScaling() + } + else + { + this.frameBuffer.texture.enableLinearScaling() + + } /* A frame buffer needs a target to render to.. create a texture and bind it attach it to the framebuffer.. @@ -213,8 +222,10 @@ this.projectionMatrix.append(this.transform); } + //TODO add a check as them may be the same! if(this.destinationFrame !== this.sourceFrame) { + gl.enable(gl.SCISSOR_TEST); gl.scissor(this.destinationFrame.x | 0,this.destinationFrame.y | 0, (this.destinationFrame.width * this.resolution) | 0, (this.destinationFrame.height* this.resolution) | 0); } @@ -279,8 +290,6 @@ return; } - console.log(width + " : " + height) - this.size.width = width; this.size.height = height; diff --git a/src/core/textures/BaseRenderTexture copy.js b/src/core/textures/BaseRenderTexture copy.js deleted file mode 100644 index acf6ac9..0000000 --- a/src/core/textures/BaseRenderTexture copy.js +++ /dev/null @@ -1,482 +0,0 @@ -var BaseTexture = require('./BaseTexture'), - Texture = require('./Texture'), - RenderTarget = require('../renderers/webgl/utils/RenderTarget'), - FilterManager = require('../renderers/webgl/managers/FilterManager'), - CanvasBuffer = require('../renderers/canvas/utils/CanvasBuffer'), - math = require('../math'), - CONST = require('../const'), - tempMatrix = new math.Matrix(), - tempRect = new math.Rectangle(); - -/** - * A BaseRenderTexture is a special texture that allows any Pixi display object to be rendered to it. - * - * __Hint__: All DisplayObjects (i.e. Sprites) that render to a BaseRenderTexture should be preloaded - * otherwise black rectangles will be drawn instead. - * - * A BaseRenderTexture takes a snapshot of any Display Object given to its render method. The position - * and rotation of the given Display Objects is ignored. For example: - * - * ```js - * var renderer = PIXI.autoDetectRenderer(1024, 1024, { view: canvas, ratio: 1 }); - * var BaserenderTexture = new PIXI.BaseRenderTexture(renderer, 800, 600); - * var sprite = PIXI.Sprite.fromImage("spinObj_01.png"); - * - * sprite.position.x = 800/2; - * sprite.position.y = 600/2; - * sprite.anchor.x = 0.5; - * sprite.anchor.y = 0.5; - * - * BaserenderTexture.render(sprite); - * ``` - * - * The Sprite in this case will be rendered to a position of 0,0. To render this sprite at its actual - * position a Container should be used: - * - * ```js - * var doc = new PIXI.Container(); - * - * doc.addChild(sprite); - * - * BaserenderTexture.render(doc); // Renders to center of BaserenderTexture - * ``` - * - * @class - * @extends PIXI.Texture - * @memberof PIXI - * @param renderer {PIXI.CanvasRenderer|PIXI.WebGLRenderer} The renderer used for this BaseRenderTexture - * @param [width=100] {number} The width of the render texture - * @param [height=100] {number} The height of the render texture - * @param [scaleMode] {number} See {@link PIXI.SCALE_MODES} for possible values - * @param [resolution=1] {number} The resolution of the texture being generated - */ -function BaseRenderTexture(renderer, width, height, scaleMode, resolution) -{ - if (!renderer) - { - throw new Error('Unable to create BaseRenderTexture, you must pass a renderer into the constructor.'); - } - - BaseTexture.call(this, null, scaleMode); - - this.width = width || 100; - this.height = height || 100; - - this.resolution = resolution || CONST.RESOLUTION;; - this.scaleMode = scaleMode || CONST.SCALE_MODES.DEFAULT; - this.hasLoaded = true; - - /** - * Draw/render the given DisplayObject onto the texture. - * - * The displayObject and descendents are transformed during this operation. - * If `updateTransform` is true then the transformations will be restored before the - * method returns. Otherwise it is up to the calling code to correctly use or reset - * the transformed display objects. - * - * The display object is always rendered with a worldAlpha value of 1. - * - * @method - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear=false] {boolean} If true the texture will be cleared before the displayObject is drawn - * @param [updateTransform=true] {boolean} If true the displayObject's worldTransform/worldAlpha and all children - * transformations will be restored. Not restoring this information will be a little faster. - */ - this.render = null; - - /** - * The renderer this BaseRenderTexture uses. A BaseRenderTexture can only belong to one renderer at the moment if its webGL. - * - * @member {PIXI.CanvasRenderer|PIXI.WebGLRenderer} - */ - this.renderer = renderer; - - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - var gl = this.renderer.gl; - - this.textureBuffer = new RenderTarget(gl, this.width, this.height, this.scaleMode, this.resolution);//, this.this.scaleMode); - this._glTextures[gl.id] = this.textureBuffer.texture; - - //TODO refactor filter manager.. as really its no longer a manager if we use it here.. - this.filterManager = new FilterManager(this.renderer); - this.filterManager.onContextChange(); - this.filterManager.resize(width, height); - this.render = this.renderWebGL; - - // the creation of a filter manager unbinds the buffers.. - this.renderer.currentRenderer.start(); - if(this.renderer._activeRenderTarget)this.renderer._activeRenderTarget.activate(); - } - else - { - - this.render = this.renderCanvas; - this.textureBuffer = new CanvasBuffer(this.width* this.resolution, this.height* this.resolution); - this.source = this.textureBuffer.canvas; - } - - /** - * @member {boolean} - */ - this.valid = true; - -} - -BaseRenderTexture.prototype = Object.create(BaseTexture.prototype); -BaseRenderTexture.prototype.constructor = BaseRenderTexture; -module.exports = BaseRenderTexture; - -/** - * Resizes the BaseRenderTexture. - * - * @param width {number} The width to resize to. - * @param height {number} The height to resize to. - * @param updateBase {boolean} Should the baseTexture.width and height values be resized as well? - */ -BaseRenderTexture.prototype.resize = function (width, height) -{ - if (width === this.width && height === this.height) - { - return; - } - - this.valid = (width > 0 && height > 0); - - this.width = width; - this.height = height; - - if (!this.valid) - { - return; - } - - this.textureBuffer.resize(this.width, this.height); - - if(this.filterManager) - { - this.filterManager.resize(this.width, this.height); - } -}; - -/** - * Clears the BaseRenderTexture. - * - */ -BaseRenderTexture.prototype.clear = function (destinationFrame) -{ - if (!this.valid) - { - return; - } - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - this.renderer.gl.bindFramebuffer(this.renderer.gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - } - - this.textureBuffer.clear(false, destinationFrame); -}; - -/** - * Internal method assigned to the `render` property if using a CanvasRenderer. - * - * @private - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear=false] {boolean} If true the texture will be cleared before the displayObject is drawn - * @param [updateTransform=true] {boolean} If true the displayObject's worldTransform/worldAlpha and all children - * transformations will be restored. Not restoring this information will be a little faster. - */ -BaseRenderTexture.prototype.renderWebGL = function (frame, displayObject, matrix, clear, updateTransform) -{ - if (!this.valid) - { - return; - } - - - updateTransform = (updateTransform !== undefined) ? updateTransform : true;//!updateTransform; - - this.textureBuffer.transform = matrix; - - //TODO not a fan that this is here... it will move! - this.textureBuffer.activate(); - - // setWorld Alpha to ensure that the object is renderer at full opacity - displayObject.worldAlpha = 1; - - if (updateTransform) - { - - // reset the matrix of the displatyObject.. - displayObject.worldTransform.identity(); - - displayObject.currentBounds = null; - - // Time to update all the children of the displayObject with the new matrix.. - var children = displayObject.children; - var i, j; - - for (i = 0, j = children.length; i < j; ++i) - { - children[i].updateTransform(); - } - } - - tempRect.width = frame.height; - tempRect.height = frame.width; - - //TODO rename textureBuffer to renderTarget.. - var temp = this.renderer.filterManager; - - this.renderer.filterManager = this.filterManager; - - - this.textureBuffer.activate(frame, tempRect); - console.log(displayObject) - this.renderer.renderDisplayObject(displayObject, this.textureBuffer, clear); - - // console.log("RENDERING "); - this.renderer.filterManager = temp; -}; - - -/** - * Internal method assigned to the `render` property if using a CanvasRenderer. - * - * @private - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear] {boolean} If true the texture will be cleared before the displayObject is drawn - */ -BaseRenderTexture.prototype.renderCanvas = function (frame, displayObject, matrix, clear, updateTransform) -{ - if (!this.valid) - { - return; - } - - updateTransform = !!updateTransform; - - var wt = tempMatrix; - - wt.identity(); - - if (matrix) - { - wt.append(matrix); - } - - - wt.tx += frame.x; - wt.ty += frame.y; - - var cachedWt = displayObject.worldTransform; - - displayObject.worldTransform = wt; - - // setWorld Alpha to ensure that the object is renderer at full opacity - displayObject.worldAlpha = 1; - - // Time to update all the children of the displayObject with the new matrix.. - var children = displayObject.children; - var i, j; - - for (i = 0, j = children.length; i < j; ++i) - { - children[i].updateTransform(); - } - - if (clear) - { - this.textureBuffer.clear(); - } - - -// this.textureBuffer. - var context = this.textureBuffer.context; - - var realResolution = this.renderer.resolution; - - this.renderer.resolution = this.resolution; - - this.renderer.renderDisplayObject(displayObject, context); - - this.renderer.resolution = realResolution; - - if(displayObject.worldTransform === wt) - { - // fixes cacheAsBitmap Happening during the above.. - displayObject.worldTransform = cachedWt; - } - -}; - -/** - * Destroys this texture - * - * @param destroyBase {boolean} Whether to destroy the base texture as well - */ -BaseRenderTexture.prototype.destroy = function () -{ - Texture.prototype.destroy.call(this, true); - - this.textureBuffer.destroy(); - - // destroy the filtermanager.. - if(this.filterManager) - { - this.filterManager.destroy(); - } - - this.renderer = null; -}; - -/** - * Will return a HTML Image of the texture - * - * @return {Image} - */ -BaseRenderTexture.prototype.getImage = function (frame) -{ - var image = new Image(); - image.src = this.getBase64(frame); - return image; -}; - -/** - * Will return a a base64 encoded string of this texture. It works by calling BaseRenderTexture.getCanvas and then running toDataURL on that. - * - * @return {string} A base64 encoded string of the texture. - */ -BaseRenderTexture.prototype.getBase64 = function ( frame ) -{ - return this.getCanvas(frame).toDataURL(); -}; - -/** - * Creates a Canvas element, renders this BaseRenderTexture to it and then returns it. - * - * @return {HTMLCanvasElement} A Canvas element with the texture rendered on. - */ -BaseRenderTexture.prototype.getCanvas = function ( frame ) -{ - - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.size.width; - frame.height = this.textureBuffer.size.height; - } - - var width = frame.width * this.resolution; - var height = frame.height * this.resolution; - - var gl = this.renderer.gl; - - var webGLPixels = new Uint8Array(4 * width * height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - gl.readPixels(frame.x * this.resolution, frame.y * this.resolution, width, height, gl.RGBA, gl.UNSIGNED_BYTE, webGLPixels); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - var tempCanvas = new CanvasBuffer(width, height); - var canvasData = tempCanvas.context.getImageData(0, 0, width, height); - canvasData.data.set(webGLPixels); - - tempCanvas.context.putImageData(canvasData, 0, 0); - - return tempCanvas.canvas; - } - else - { - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.canvas.width; - frame.height = this.textureBuffer.canvas.height; - } - - if(frame.width === this.textureBuffer.canvas.width && - frame.height === this.textureBuffer.canvas.height ) - { - return this.textureBuffer.canvas; - } - else - { - - var resolution = this.resolution; - - var tempCanvas = new CanvasBuffer(frame.width * resolution, frame.height * resolution); - var canvasData = this.textureBuffer.context.getImageData(frame.x * resolution, frame.y * resolution, frame.width * resolution, frame.height * resolution); - - tempCanvas.context.putImageData(canvasData, 0, 0); - - return tempCanvas.canvas; - } - } -}; - -/** - * Will return a one-dimensional array containing the pixel data of the entire texture in RGBA order, with integer values between 0 and 255 (included). - * - * @return {Uint8ClampedArray} - */ -BaseRenderTexture.prototype.getPixels = function ( frame ) -{ - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.size.width; - frame.height = this.textureBuffer.size.height; - } - - var width = frame.width * this.resolution; - var height = frame.height * this.resolution; - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - var gl = this.renderer.gl; - - var webGLPixels = new Uint8Array(4 * width * height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - gl.readPixels(frame.x * this.resolution, frame.y * this.resolution, width, height, gl.RGBA, gl.UNSIGNED_BYTE, webGLPixels); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - return webGLPixels; - } - else - { - return this.textureBuffer.canvas.getContext('2d').getImageData(frame.x * this.resolution, frame.y * this.resolution, width, height).data; - } -}; - -/** - * Will return a one-dimensional array containing the pixel data of a pixel within the texture in RGBA order, with integer values between 0 and 255 (included). - * - * @param x {number} The x coordinate of the pixel to retrieve. - * @param y {number} The y coordinate of the pixel to retrieve. - * @return {Uint8ClampedArray} - */ -BaseRenderTexture.prototype.getPixel = function (frame, x, y) -{ - tempRect.x = x; - tempRect.y = y; - tempRect.width = 1 / this.resolution; - tempRect.height = 1 / this.resolution; - - if(frame) - { - tempRect.x += frame.x; - tempRect.y += frame.y; - } - - return this.getPixels(tempRect); -}; diff --git a/src/filters/blur/BlurFilter.js b/src/filters/blur/BlurFilter.js new file mode 100644 index 0000000..fb708a1 --- /dev/null +++ b/src/filters/blur/BlurFilter.js @@ -0,0 +1,114 @@ +var core = require('../../core'), + BlurXFilter = require('./BlurXFilter'), + BlurYFilter = require('./BlurYFilter'); + +/** + * The BlurFilter applies a Gaussian blur to an object. + * The strength of the blur can be set for x- and y-axis separately. + * + * @class + * @extends PIXI.Filter + * @memberof PIXI.filters + */ +function BlurFilter() +{ + core.Filter.call(this); + + this.blurXFilter = new BlurXFilter(); + this.blurYFilter = new BlurYFilter(); + this.resolution = 0.25;//0.25;//0.25//1//01.26; + this.blurYFilter.passes = this.blurXFilter.passes = 2; + this.blurYFilter.strength = this.blurXFilter.strength = 4;//4// 4 + + this.padding = 100 + +} + +BlurFilter.prototype = Object.create(core.Filter.prototype); +BlurFilter.prototype.constructor = BlurFilter; +module.exports = BlurFilter; + +BlurFilter.prototype.apply = function (filterManager, input, output) +{ + var renderTarget = filterManager.getRenderTarget(true); + + this.blurXFilter.apply(filterManager, input, renderTarget, true); + this.blurYFilter.apply(filterManager, renderTarget, output); + + filterManager.returnRenderTarget(renderTarget); +}; + +Object.defineProperties(BlurFilter.prototype, { + /** + * Sets the strength of both the blurX and blurY properties simultaneously + * + * @member {number} + * @memberOf PIXI.filters.BlurFilter# + * @default 2 + */ + blur: { + get: function () + { + return this.blurXFilter.blur; + }, + set: function (value) + { + this.padding = Math.abs(value) * 0.5; + this.blurXFilter.blur = this.blurYFilter.blur = value; + } + }, + + /** + * Sets the number of passes for blur. More passes means higher quaility bluring. + * + * @member {number} + * @memberof PIXI.filters.BlurYFilter# + * @default 1 + */ + passes: { + get: function () + { + return this.blurXFilter.passes; + }, + set: function (value) + { + this.blurXFilter.passes = this.blurYFilter.passes = value; + } + }, + + /** + * Sets the strength of the blurX property + * + * @member {number} + * @memberOf PIXI.filters.BlurFilter# + * @default 2 + */ + blurX: { + get: function () + { + return this.blurXFilter.blur; + }, + set: function (value) + { + this.blurXFilter.blur = value; + } + }, + + /** + * Sets the strength of the blurY property + * + * @member {number} + * @memberOf PIXI.filters.BlurFilter# + * @default 2 + */ + blurY: { + get: function () + { + return this.blurYFilter.blur; + }, + set: function (value) + { + this.blurYFilter.blur = value; + } + } +}); diff --git a/src/filters/blur/BlurXFilter.js b/src/filters/blur/BlurXFilter.js new file mode 100644 index 0000000..61eed96 --- /dev/null +++ b/src/filters/blur/BlurXFilter.js @@ -0,0 +1,94 @@ +var core = require('../../core'); +var glslify = require('glslify'); +var generateBlurVertSource = require('./generateBlurVertSource'); +var generateBlurFragSource = require('./generateBlurFragSource'); + +/** + * The BlurXFilter applies a horizontal Gaussian blur to an object. + * + * @class + * @extends PIXI.Filter + * @memberof PIXI.filters + */ +function BlurXFilter() +{ + var vertSrc = generateBlurVertSource(11, true); + var fragSrc = generateBlurFragSource(11); + + console.log(vertSrc); + console.log(fragSrc); + + core.Filter.call(this, + // vertex shader + vertSrc, + // fragment shader + fragSrc + ); + + /** + * Sets the number of passes for blur. More passes means higher quaility bluring. + * + * @member {number} + * @default 1 + */ + this.passes = 1; + this.resolution = 1;//0.25;//0.5;//0.1//5; + this.strength = 4; +} + +BlurXFilter.prototype = Object.create(core.Filter.prototype); +BlurXFilter.prototype.constructor = BlurXFilter; +module.exports = BlurXFilter; + +BlurXFilter.prototype.apply = function (filterManager, input, output, clear) +{ + this.uniforms.strength = (1/output.destinationFrame.width) * (output.size.width/input.size.width); /// // * 2 //4//this.strength / 4 / this.passes * (input.frame.width / input.size.width); + + // screen space! + this.uniforms.strength *= this.strength; + if(this.passes === 1) + { + filterManager.applyFilter(this, input, output, clear); + } + else + { + var renderTarget = filterManager.getRenderTarget(true); + var flip = input; + var flop = renderTarget; + + for(var i = 0; i < this.passes-1; i++) + { + filterManager.applyFilter(this, flip, flop, true); + + var temp = flop; + flop = flip; + flip = temp; + } + + filterManager.applyFilter(this, flip, output, clear); + + filterManager.returnRenderTarget(renderTarget); + } +}; + + +Object.defineProperties(BlurXFilter.prototype, { + /** + * Sets the strength of both the blur. + * + * @member {number} + * @memberof PIXI.filters.BlurXFilter# + * @default 2 + */ + blur: { + get: function () + { + return this.strength; + }, + set: function (value) + { + this.padding = Math.abs(value) * 0.5; + this.strength = value; + } + } +}); diff --git a/src/filters/blur/BlurYFilter.js b/src/filters/blur/BlurYFilter.js new file mode 100644 index 0000000..86a3171 --- /dev/null +++ b/src/filters/blur/BlurYFilter.js @@ -0,0 +1,85 @@ +var core = require('../../core'); +var generateBlurVertSource = require('./generateBlurVertSource'); +var generateBlurFragSource = require('./generateBlurFragSource'); + + +/** + * The BlurYFilter applies a horizontal Gaussian blur to an object. + * + * @class + * @extends PIXI.Filter + * @memberof PIXI.filters + */ +function BlurYFilter() +{ + var vertSrc = generateBlurVertSource(11, false); + var fragSrc = generateBlurFragSource(11); + + core.Filter.call(this, + // vertex shader + vertSrc, + // fragment shader + fragSrc + ); + + this.passes = 1; + this.resolution = 1;//0.25;//0.5;//0.1//5; + this.strength = 4; +} + +BlurYFilter.prototype = Object.create(core.Filter.prototype); +BlurYFilter.prototype.constructor = BlurYFilter; +module.exports = BlurYFilter; + +BlurYFilter.prototype.apply = function (filterManager, input, output, clear) +{ + this.uniforms.strength = (1/output.destinationFrame.height) * (output.size.height/input.size.height); /// // * 2 //4//this.strength / 4 / this.passes * (input.frame.width / input.size.width); + + this.uniforms.strength *= this.strength; + + if(this.passes === 1) + { + filterManager.applyFilter(this, input, output, clear); + } + else + { + var renderTarget = filterManager.getRenderTarget(true); + var flip = input; + var flop = renderTarget; + + for(var i = 0; i < this.passes-1; i++) + { + filterManager.applyFilter(this, flip, flop, true); + + var temp = flop; + flop = flip; + flip = temp; + } + + filterManager.applyFilter(this, flip, output, clear); + + filterManager.returnRenderTarget(renderTarget); + } +}; + + +Object.defineProperties(BlurYFilter.prototype, { + /** + * Sets the strength of both the blur. + * + * @member {number} + * @memberof PIXI.filters.BlurYFilter# + * @default 2 + */ + blur: { + get: function () + { + return this.strength; + }, + set: function (value) + { + this.padding = Math.abs(value) * 0.5; + this.strength = value; + } + } +}); diff --git a/src/filters/blur/blur.frag b/src/filters/blur/blur.frag new file mode 100644 index 0000000..0c4f23c --- /dev/null +++ b/src/filters/blur/blur.frag @@ -0,0 +1,31 @@ +precision mediump float; + +varying vec2 vTextureCoord; +varying vec2 vBlurTexCoords[15]; + +uniform sampler2D uSampler; + +void main(void) +{ + gl_FragColor = vec4(0.0); + + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 0]) * 0.000489; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 1]) * 0.002403; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 2]) * 0.009246; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 3]) * 0.02784; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 4]) * 0.065602; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 5]) * 0.120999; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 6]) * 0.174697; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 7]) * 0.197448; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 8]) * 0.174697; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 9]) * 0.120999; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 10]) * 0.065602; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 11]) * 0.02784; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 12]) * 0.009246; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 13]) * 0.002403; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 14]) * 0.000489; + + + + +} diff --git a/src/filters/blur/blurX.vert b/src/filters/blur/blurX.vert new file mode 100644 index 0000000..cc0e22b --- /dev/null +++ b/src/filters/blur/blurX.vert @@ -0,0 +1,31 @@ +attribute vec2 aVertexPosition; +attribute vec2 aTextureCoord; + +uniform float strength; +uniform mat3 projectionMatrix; + +varying vec2 vTextureCoord; +varying vec2 vBlurTexCoords[15]; + +void main(void) +{ + gl_Position = vec4((projectionMatrix * vec3((aVertexPosition), 1.0)).xy, 0.0, 1.0); + vTextureCoord = aTextureCoord; + + vBlurTexCoords[ 0] = aTextureCoord + vec2(-7.0 * strength, 0.0); + vBlurTexCoords[ 1] = aTextureCoord + vec2(-6.0 * strength, 0.0); + vBlurTexCoords[ 2] = aTextureCoord + vec2(-5.0 * strength, 0.0); + vBlurTexCoords[ 3] = aTextureCoord + vec2(-4.0 * strength, 0.0); + vBlurTexCoords[ 4] = aTextureCoord + vec2(-3.0 * strength, 0.0); + vBlurTexCoords[ 5] = aTextureCoord + vec2(-2.0 * strength, 0.0); + vBlurTexCoords[ 6] = aTextureCoord + vec2(-1.0 * strength, 0.0); + vBlurTexCoords[ 7] = aTextureCoord; + vBlurTexCoords[ 8] = aTextureCoord + vec2(1.0 * strength, 0.0); + vBlurTexCoords[ 9] = aTextureCoord + vec2(2.0 * strength, 0.0); + vBlurTexCoords[ 10] = aTextureCoord + vec2(3.0 * strength, 0.0); + vBlurTexCoords[ 11] = aTextureCoord + vec2(4.0 * strength, 0.0); + vBlurTexCoords[ 12] = aTextureCoord + vec2(5.0 * strength, 0.0); + vBlurTexCoords[ 13] = aTextureCoord + vec2(6.0 * strength, 0.0); + vBlurTexCoords[ 14] = aTextureCoord + vec2(7.0 * strength, 0.0); + +} diff --git a/package.json b/package.json index 4436b84..48a074c 100644 --- a/package.json +++ b/package.json @@ -32,10 +32,8 @@ "dependencies": { "async": "^1.5.0", "bit-twiddle": "^1.0.2", - "brfs": "^1.4.1", "earcut": "^2.0.7", "eventemitter3": "^1.1.1", - "gl-matrix": "git+https://github.com/toji/gl-matrix.git", "object-assign": "^4.0.1", "pixi-gl-core": "git+https://github.com/GoodBoyDigital/pixi-gl-core.git", "resource-loader": "^1.6.4" @@ -73,6 +71,5 @@ "transform": [ "glslify" ] - } } diff --git a/src/core/graphics/webgl/PrimitiveShader.js b/src/core/graphics/webgl/PrimitiveShader.js deleted file mode 100644 index 44166b3..0000000 --- a/src/core/graphics/webgl/PrimitiveShader.js +++ /dev/null @@ -1,50 +0,0 @@ -var Shader = require('pixi-gl-core').GLShader; - -/** - * This shader is used to draw simple primitive shapes for {@link PIXI.Graphics}. - * - * @class - * @memberof PIXI - * @extends PIXI.Shader - * @param shaderManager {ShaderManager} The webgl shader manager this shader works for. - */ -function PrimitiveShader(gl) -{ - Shader.call(this, - gl, - // vertex shader - [ - 'attribute vec2 aVertexPosition;', - 'attribute vec4 aColor;', - - 'uniform mat3 translationMatrix;', - 'uniform mat3 projectionMatrix;', - - 'uniform float alpha;', - 'uniform float flipY;', - 'uniform vec3 tint;', - - 'varying vec4 vColor;', - - 'void main(void){', - ' gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', - ' vColor = aColor * vec4(tint * alpha, alpha);', - '}' - ].join('\n'), - // fragment shader - [ - 'precision mediump float;', - - 'varying vec4 vColor;', - - 'void main(void){', - ' gl_FragColor = vColor;', - '}' - ].join('\n') - ); -} - -PrimitiveShader.prototype = Object.create(Shader.prototype); -PrimitiveShader.prototype.constructor = PrimitiveShader; - -module.exports = PrimitiveShader; diff --git a/src/core/math/Matrix.js b/src/core/math/Matrix.js index 4e7fe99..2313ae3 100644 --- a/src/core/math/Matrix.js +++ b/src/core/math/Matrix.js @@ -51,6 +51,7 @@ * @default 0 */ this.ty = 0; + } Matrix.prototype.constructor = Matrix; diff --git a/src/core/renderers/webgl/managers/FilterManager.js b/src/core/renderers/webgl/managers/FilterManager.js index b3f7463..5fc6562 100644 --- a/src/core/renderers/webgl/managers/FilterManager.js +++ b/src/core/renderers/webgl/managers/FilterManager.js @@ -64,11 +64,12 @@ - //TODO - should this be rounded to reoultion? not 1? - sourceFrame.x = targetBounds.x | 0; - sourceFrame.y = targetBounds.y | 0; - sourceFrame.width = targetBounds.width | 0; - sourceFrame.height = targetBounds.height | 0; + + sourceFrame.x = ((targetBounds.x * resolution) | 0) / resolution; + sourceFrame.y = ((targetBounds.y * resolution) | 0) / resolution; + sourceFrame.width = ((targetBounds.width * resolution) | 0) / resolution; + sourceFrame.height = ((targetBounds.height * resolution) | 0) / resolution; + sourceFrame.pad(padding * resolution); sourceFrame.fit(this.stack[0].destinationFrame); @@ -79,6 +80,7 @@ currentState.target = target; currentState.filters = filters; + currentState.resolution = resolution; currentState.renderTarget = renderTarget; // bind the render taget to draw the shape in the top corner.. @@ -236,6 +238,13 @@ shader.uniforms[i] = uniforms[i]; } } + else if(uniformData[i].type === 'float') + { + if(shader.uniforms.data[i].value !== uniformData[i]) + { + shader.uniforms[i] = uniforms[i]; + } + } else { shader.uniforms[i] = uniforms[i]; @@ -244,10 +253,18 @@ } -FilterManager.prototype.getPotRenderTarget = function() +FilterManager.prototype.getRenderTarget = function() { var currentState = this.stack[this.stackIndex]; - return FilterManager.getPotRenderTarget(renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, 1); + var renderTarget = FilterManager.getPotRenderTarget(renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, currentState.resolution); + renderTarget.setFrame(currentState.destinationFrame, currentState.sourceFrame); + + return renderTarget; +} + +FilterManager.prototype.returnRenderTarget = function(renderTarget) +{ + return FilterManager.freePotRenderTarget(renderTarget); } /* @@ -325,6 +342,7 @@ this.destinationFrame = new math.Rectangle(); this.filters = []; this.target = null; + this.resolution = 1; } FilterManager.pool = {} diff --git a/src/core/renderers/webgl/utils/RenderTarget.js b/src/core/renderers/webgl/utils/RenderTarget.js index ced94f6..d3daf50 100644 --- a/src/core/renderers/webgl/utils/RenderTarget.js +++ b/src/core/renderers/webgl/utils/RenderTarget.js @@ -136,6 +136,15 @@ { this.frameBuffer = GLFramebuffer.createRGBA(gl, 100, 100); + if( this.scaleMode === CONST.SCALE_MODES.NEAREST) + { + this.frameBuffer.texture.enableNearestScaling() + } + else + { + this.frameBuffer.texture.enableLinearScaling() + + } /* A frame buffer needs a target to render to.. create a texture and bind it attach it to the framebuffer.. @@ -213,8 +222,10 @@ this.projectionMatrix.append(this.transform); } + //TODO add a check as them may be the same! if(this.destinationFrame !== this.sourceFrame) { + gl.enable(gl.SCISSOR_TEST); gl.scissor(this.destinationFrame.x | 0,this.destinationFrame.y | 0, (this.destinationFrame.width * this.resolution) | 0, (this.destinationFrame.height* this.resolution) | 0); } @@ -279,8 +290,6 @@ return; } - console.log(width + " : " + height) - this.size.width = width; this.size.height = height; diff --git a/src/core/textures/BaseRenderTexture copy.js b/src/core/textures/BaseRenderTexture copy.js deleted file mode 100644 index acf6ac9..0000000 --- a/src/core/textures/BaseRenderTexture copy.js +++ /dev/null @@ -1,482 +0,0 @@ -var BaseTexture = require('./BaseTexture'), - Texture = require('./Texture'), - RenderTarget = require('../renderers/webgl/utils/RenderTarget'), - FilterManager = require('../renderers/webgl/managers/FilterManager'), - CanvasBuffer = require('../renderers/canvas/utils/CanvasBuffer'), - math = require('../math'), - CONST = require('../const'), - tempMatrix = new math.Matrix(), - tempRect = new math.Rectangle(); - -/** - * A BaseRenderTexture is a special texture that allows any Pixi display object to be rendered to it. - * - * __Hint__: All DisplayObjects (i.e. Sprites) that render to a BaseRenderTexture should be preloaded - * otherwise black rectangles will be drawn instead. - * - * A BaseRenderTexture takes a snapshot of any Display Object given to its render method. The position - * and rotation of the given Display Objects is ignored. For example: - * - * ```js - * var renderer = PIXI.autoDetectRenderer(1024, 1024, { view: canvas, ratio: 1 }); - * var BaserenderTexture = new PIXI.BaseRenderTexture(renderer, 800, 600); - * var sprite = PIXI.Sprite.fromImage("spinObj_01.png"); - * - * sprite.position.x = 800/2; - * sprite.position.y = 600/2; - * sprite.anchor.x = 0.5; - * sprite.anchor.y = 0.5; - * - * BaserenderTexture.render(sprite); - * ``` - * - * The Sprite in this case will be rendered to a position of 0,0. To render this sprite at its actual - * position a Container should be used: - * - * ```js - * var doc = new PIXI.Container(); - * - * doc.addChild(sprite); - * - * BaserenderTexture.render(doc); // Renders to center of BaserenderTexture - * ``` - * - * @class - * @extends PIXI.Texture - * @memberof PIXI - * @param renderer {PIXI.CanvasRenderer|PIXI.WebGLRenderer} The renderer used for this BaseRenderTexture - * @param [width=100] {number} The width of the render texture - * @param [height=100] {number} The height of the render texture - * @param [scaleMode] {number} See {@link PIXI.SCALE_MODES} for possible values - * @param [resolution=1] {number} The resolution of the texture being generated - */ -function BaseRenderTexture(renderer, width, height, scaleMode, resolution) -{ - if (!renderer) - { - throw new Error('Unable to create BaseRenderTexture, you must pass a renderer into the constructor.'); - } - - BaseTexture.call(this, null, scaleMode); - - this.width = width || 100; - this.height = height || 100; - - this.resolution = resolution || CONST.RESOLUTION;; - this.scaleMode = scaleMode || CONST.SCALE_MODES.DEFAULT; - this.hasLoaded = true; - - /** - * Draw/render the given DisplayObject onto the texture. - * - * The displayObject and descendents are transformed during this operation. - * If `updateTransform` is true then the transformations will be restored before the - * method returns. Otherwise it is up to the calling code to correctly use or reset - * the transformed display objects. - * - * The display object is always rendered with a worldAlpha value of 1. - * - * @method - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear=false] {boolean} If true the texture will be cleared before the displayObject is drawn - * @param [updateTransform=true] {boolean} If true the displayObject's worldTransform/worldAlpha and all children - * transformations will be restored. Not restoring this information will be a little faster. - */ - this.render = null; - - /** - * The renderer this BaseRenderTexture uses. A BaseRenderTexture can only belong to one renderer at the moment if its webGL. - * - * @member {PIXI.CanvasRenderer|PIXI.WebGLRenderer} - */ - this.renderer = renderer; - - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - var gl = this.renderer.gl; - - this.textureBuffer = new RenderTarget(gl, this.width, this.height, this.scaleMode, this.resolution);//, this.this.scaleMode); - this._glTextures[gl.id] = this.textureBuffer.texture; - - //TODO refactor filter manager.. as really its no longer a manager if we use it here.. - this.filterManager = new FilterManager(this.renderer); - this.filterManager.onContextChange(); - this.filterManager.resize(width, height); - this.render = this.renderWebGL; - - // the creation of a filter manager unbinds the buffers.. - this.renderer.currentRenderer.start(); - if(this.renderer._activeRenderTarget)this.renderer._activeRenderTarget.activate(); - } - else - { - - this.render = this.renderCanvas; - this.textureBuffer = new CanvasBuffer(this.width* this.resolution, this.height* this.resolution); - this.source = this.textureBuffer.canvas; - } - - /** - * @member {boolean} - */ - this.valid = true; - -} - -BaseRenderTexture.prototype = Object.create(BaseTexture.prototype); -BaseRenderTexture.prototype.constructor = BaseRenderTexture; -module.exports = BaseRenderTexture; - -/** - * Resizes the BaseRenderTexture. - * - * @param width {number} The width to resize to. - * @param height {number} The height to resize to. - * @param updateBase {boolean} Should the baseTexture.width and height values be resized as well? - */ -BaseRenderTexture.prototype.resize = function (width, height) -{ - if (width === this.width && height === this.height) - { - return; - } - - this.valid = (width > 0 && height > 0); - - this.width = width; - this.height = height; - - if (!this.valid) - { - return; - } - - this.textureBuffer.resize(this.width, this.height); - - if(this.filterManager) - { - this.filterManager.resize(this.width, this.height); - } -}; - -/** - * Clears the BaseRenderTexture. - * - */ -BaseRenderTexture.prototype.clear = function (destinationFrame) -{ - if (!this.valid) - { - return; - } - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - this.renderer.gl.bindFramebuffer(this.renderer.gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - } - - this.textureBuffer.clear(false, destinationFrame); -}; - -/** - * Internal method assigned to the `render` property if using a CanvasRenderer. - * - * @private - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear=false] {boolean} If true the texture will be cleared before the displayObject is drawn - * @param [updateTransform=true] {boolean} If true the displayObject's worldTransform/worldAlpha and all children - * transformations will be restored. Not restoring this information will be a little faster. - */ -BaseRenderTexture.prototype.renderWebGL = function (frame, displayObject, matrix, clear, updateTransform) -{ - if (!this.valid) - { - return; - } - - - updateTransform = (updateTransform !== undefined) ? updateTransform : true;//!updateTransform; - - this.textureBuffer.transform = matrix; - - //TODO not a fan that this is here... it will move! - this.textureBuffer.activate(); - - // setWorld Alpha to ensure that the object is renderer at full opacity - displayObject.worldAlpha = 1; - - if (updateTransform) - { - - // reset the matrix of the displatyObject.. - displayObject.worldTransform.identity(); - - displayObject.currentBounds = null; - - // Time to update all the children of the displayObject with the new matrix.. - var children = displayObject.children; - var i, j; - - for (i = 0, j = children.length; i < j; ++i) - { - children[i].updateTransform(); - } - } - - tempRect.width = frame.height; - tempRect.height = frame.width; - - //TODO rename textureBuffer to renderTarget.. - var temp = this.renderer.filterManager; - - this.renderer.filterManager = this.filterManager; - - - this.textureBuffer.activate(frame, tempRect); - console.log(displayObject) - this.renderer.renderDisplayObject(displayObject, this.textureBuffer, clear); - - // console.log("RENDERING "); - this.renderer.filterManager = temp; -}; - - -/** - * Internal method assigned to the `render` property if using a CanvasRenderer. - * - * @private - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear] {boolean} If true the texture will be cleared before the displayObject is drawn - */ -BaseRenderTexture.prototype.renderCanvas = function (frame, displayObject, matrix, clear, updateTransform) -{ - if (!this.valid) - { - return; - } - - updateTransform = !!updateTransform; - - var wt = tempMatrix; - - wt.identity(); - - if (matrix) - { - wt.append(matrix); - } - - - wt.tx += frame.x; - wt.ty += frame.y; - - var cachedWt = displayObject.worldTransform; - - displayObject.worldTransform = wt; - - // setWorld Alpha to ensure that the object is renderer at full opacity - displayObject.worldAlpha = 1; - - // Time to update all the children of the displayObject with the new matrix.. - var children = displayObject.children; - var i, j; - - for (i = 0, j = children.length; i < j; ++i) - { - children[i].updateTransform(); - } - - if (clear) - { - this.textureBuffer.clear(); - } - - -// this.textureBuffer. - var context = this.textureBuffer.context; - - var realResolution = this.renderer.resolution; - - this.renderer.resolution = this.resolution; - - this.renderer.renderDisplayObject(displayObject, context); - - this.renderer.resolution = realResolution; - - if(displayObject.worldTransform === wt) - { - // fixes cacheAsBitmap Happening during the above.. - displayObject.worldTransform = cachedWt; - } - -}; - -/** - * Destroys this texture - * - * @param destroyBase {boolean} Whether to destroy the base texture as well - */ -BaseRenderTexture.prototype.destroy = function () -{ - Texture.prototype.destroy.call(this, true); - - this.textureBuffer.destroy(); - - // destroy the filtermanager.. - if(this.filterManager) - { - this.filterManager.destroy(); - } - - this.renderer = null; -}; - -/** - * Will return a HTML Image of the texture - * - * @return {Image} - */ -BaseRenderTexture.prototype.getImage = function (frame) -{ - var image = new Image(); - image.src = this.getBase64(frame); - return image; -}; - -/** - * Will return a a base64 encoded string of this texture. It works by calling BaseRenderTexture.getCanvas and then running toDataURL on that. - * - * @return {string} A base64 encoded string of the texture. - */ -BaseRenderTexture.prototype.getBase64 = function ( frame ) -{ - return this.getCanvas(frame).toDataURL(); -}; - -/** - * Creates a Canvas element, renders this BaseRenderTexture to it and then returns it. - * - * @return {HTMLCanvasElement} A Canvas element with the texture rendered on. - */ -BaseRenderTexture.prototype.getCanvas = function ( frame ) -{ - - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.size.width; - frame.height = this.textureBuffer.size.height; - } - - var width = frame.width * this.resolution; - var height = frame.height * this.resolution; - - var gl = this.renderer.gl; - - var webGLPixels = new Uint8Array(4 * width * height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - gl.readPixels(frame.x * this.resolution, frame.y * this.resolution, width, height, gl.RGBA, gl.UNSIGNED_BYTE, webGLPixels); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - var tempCanvas = new CanvasBuffer(width, height); - var canvasData = tempCanvas.context.getImageData(0, 0, width, height); - canvasData.data.set(webGLPixels); - - tempCanvas.context.putImageData(canvasData, 0, 0); - - return tempCanvas.canvas; - } - else - { - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.canvas.width; - frame.height = this.textureBuffer.canvas.height; - } - - if(frame.width === this.textureBuffer.canvas.width && - frame.height === this.textureBuffer.canvas.height ) - { - return this.textureBuffer.canvas; - } - else - { - - var resolution = this.resolution; - - var tempCanvas = new CanvasBuffer(frame.width * resolution, frame.height * resolution); - var canvasData = this.textureBuffer.context.getImageData(frame.x * resolution, frame.y * resolution, frame.width * resolution, frame.height * resolution); - - tempCanvas.context.putImageData(canvasData, 0, 0); - - return tempCanvas.canvas; - } - } -}; - -/** - * Will return a one-dimensional array containing the pixel data of the entire texture in RGBA order, with integer values between 0 and 255 (included). - * - * @return {Uint8ClampedArray} - */ -BaseRenderTexture.prototype.getPixels = function ( frame ) -{ - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.size.width; - frame.height = this.textureBuffer.size.height; - } - - var width = frame.width * this.resolution; - var height = frame.height * this.resolution; - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - var gl = this.renderer.gl; - - var webGLPixels = new Uint8Array(4 * width * height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - gl.readPixels(frame.x * this.resolution, frame.y * this.resolution, width, height, gl.RGBA, gl.UNSIGNED_BYTE, webGLPixels); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - return webGLPixels; - } - else - { - return this.textureBuffer.canvas.getContext('2d').getImageData(frame.x * this.resolution, frame.y * this.resolution, width, height).data; - } -}; - -/** - * Will return a one-dimensional array containing the pixel data of a pixel within the texture in RGBA order, with integer values between 0 and 255 (included). - * - * @param x {number} The x coordinate of the pixel to retrieve. - * @param y {number} The y coordinate of the pixel to retrieve. - * @return {Uint8ClampedArray} - */ -BaseRenderTexture.prototype.getPixel = function (frame, x, y) -{ - tempRect.x = x; - tempRect.y = y; - tempRect.width = 1 / this.resolution; - tempRect.height = 1 / this.resolution; - - if(frame) - { - tempRect.x += frame.x; - tempRect.y += frame.y; - } - - return this.getPixels(tempRect); -}; diff --git a/src/filters/blur/BlurFilter.js b/src/filters/blur/BlurFilter.js new file mode 100644 index 0000000..fb708a1 --- /dev/null +++ b/src/filters/blur/BlurFilter.js @@ -0,0 +1,114 @@ +var core = require('../../core'), + BlurXFilter = require('./BlurXFilter'), + BlurYFilter = require('./BlurYFilter'); + +/** + * The BlurFilter applies a Gaussian blur to an object. + * The strength of the blur can be set for x- and y-axis separately. + * + * @class + * @extends PIXI.Filter + * @memberof PIXI.filters + */ +function BlurFilter() +{ + core.Filter.call(this); + + this.blurXFilter = new BlurXFilter(); + this.blurYFilter = new BlurYFilter(); + this.resolution = 0.25;//0.25;//0.25//1//01.26; + this.blurYFilter.passes = this.blurXFilter.passes = 2; + this.blurYFilter.strength = this.blurXFilter.strength = 4;//4// 4 + + this.padding = 100 + +} + +BlurFilter.prototype = Object.create(core.Filter.prototype); +BlurFilter.prototype.constructor = BlurFilter; +module.exports = BlurFilter; + +BlurFilter.prototype.apply = function (filterManager, input, output) +{ + var renderTarget = filterManager.getRenderTarget(true); + + this.blurXFilter.apply(filterManager, input, renderTarget, true); + this.blurYFilter.apply(filterManager, renderTarget, output); + + filterManager.returnRenderTarget(renderTarget); +}; + +Object.defineProperties(BlurFilter.prototype, { + /** + * Sets the strength of both the blurX and blurY properties simultaneously + * + * @member {number} + * @memberOf PIXI.filters.BlurFilter# + * @default 2 + */ + blur: { + get: function () + { + return this.blurXFilter.blur; + }, + set: function (value) + { + this.padding = Math.abs(value) * 0.5; + this.blurXFilter.blur = this.blurYFilter.blur = value; + } + }, + + /** + * Sets the number of passes for blur. More passes means higher quaility bluring. + * + * @member {number} + * @memberof PIXI.filters.BlurYFilter# + * @default 1 + */ + passes: { + get: function () + { + return this.blurXFilter.passes; + }, + set: function (value) + { + this.blurXFilter.passes = this.blurYFilter.passes = value; + } + }, + + /** + * Sets the strength of the blurX property + * + * @member {number} + * @memberOf PIXI.filters.BlurFilter# + * @default 2 + */ + blurX: { + get: function () + { + return this.blurXFilter.blur; + }, + set: function (value) + { + this.blurXFilter.blur = value; + } + }, + + /** + * Sets the strength of the blurY property + * + * @member {number} + * @memberOf PIXI.filters.BlurFilter# + * @default 2 + */ + blurY: { + get: function () + { + return this.blurYFilter.blur; + }, + set: function (value) + { + this.blurYFilter.blur = value; + } + } +}); diff --git a/src/filters/blur/BlurXFilter.js b/src/filters/blur/BlurXFilter.js new file mode 100644 index 0000000..61eed96 --- /dev/null +++ b/src/filters/blur/BlurXFilter.js @@ -0,0 +1,94 @@ +var core = require('../../core'); +var glslify = require('glslify'); +var generateBlurVertSource = require('./generateBlurVertSource'); +var generateBlurFragSource = require('./generateBlurFragSource'); + +/** + * The BlurXFilter applies a horizontal Gaussian blur to an object. + * + * @class + * @extends PIXI.Filter + * @memberof PIXI.filters + */ +function BlurXFilter() +{ + var vertSrc = generateBlurVertSource(11, true); + var fragSrc = generateBlurFragSource(11); + + console.log(vertSrc); + console.log(fragSrc); + + core.Filter.call(this, + // vertex shader + vertSrc, + // fragment shader + fragSrc + ); + + /** + * Sets the number of passes for blur. More passes means higher quaility bluring. + * + * @member {number} + * @default 1 + */ + this.passes = 1; + this.resolution = 1;//0.25;//0.5;//0.1//5; + this.strength = 4; +} + +BlurXFilter.prototype = Object.create(core.Filter.prototype); +BlurXFilter.prototype.constructor = BlurXFilter; +module.exports = BlurXFilter; + +BlurXFilter.prototype.apply = function (filterManager, input, output, clear) +{ + this.uniforms.strength = (1/output.destinationFrame.width) * (output.size.width/input.size.width); /// // * 2 //4//this.strength / 4 / this.passes * (input.frame.width / input.size.width); + + // screen space! + this.uniforms.strength *= this.strength; + if(this.passes === 1) + { + filterManager.applyFilter(this, input, output, clear); + } + else + { + var renderTarget = filterManager.getRenderTarget(true); + var flip = input; + var flop = renderTarget; + + for(var i = 0; i < this.passes-1; i++) + { + filterManager.applyFilter(this, flip, flop, true); + + var temp = flop; + flop = flip; + flip = temp; + } + + filterManager.applyFilter(this, flip, output, clear); + + filterManager.returnRenderTarget(renderTarget); + } +}; + + +Object.defineProperties(BlurXFilter.prototype, { + /** + * Sets the strength of both the blur. + * + * @member {number} + * @memberof PIXI.filters.BlurXFilter# + * @default 2 + */ + blur: { + get: function () + { + return this.strength; + }, + set: function (value) + { + this.padding = Math.abs(value) * 0.5; + this.strength = value; + } + } +}); diff --git a/src/filters/blur/BlurYFilter.js b/src/filters/blur/BlurYFilter.js new file mode 100644 index 0000000..86a3171 --- /dev/null +++ b/src/filters/blur/BlurYFilter.js @@ -0,0 +1,85 @@ +var core = require('../../core'); +var generateBlurVertSource = require('./generateBlurVertSource'); +var generateBlurFragSource = require('./generateBlurFragSource'); + + +/** + * The BlurYFilter applies a horizontal Gaussian blur to an object. + * + * @class + * @extends PIXI.Filter + * @memberof PIXI.filters + */ +function BlurYFilter() +{ + var vertSrc = generateBlurVertSource(11, false); + var fragSrc = generateBlurFragSource(11); + + core.Filter.call(this, + // vertex shader + vertSrc, + // fragment shader + fragSrc + ); + + this.passes = 1; + this.resolution = 1;//0.25;//0.5;//0.1//5; + this.strength = 4; +} + +BlurYFilter.prototype = Object.create(core.Filter.prototype); +BlurYFilter.prototype.constructor = BlurYFilter; +module.exports = BlurYFilter; + +BlurYFilter.prototype.apply = function (filterManager, input, output, clear) +{ + this.uniforms.strength = (1/output.destinationFrame.height) * (output.size.height/input.size.height); /// // * 2 //4//this.strength / 4 / this.passes * (input.frame.width / input.size.width); + + this.uniforms.strength *= this.strength; + + if(this.passes === 1) + { + filterManager.applyFilter(this, input, output, clear); + } + else + { + var renderTarget = filterManager.getRenderTarget(true); + var flip = input; + var flop = renderTarget; + + for(var i = 0; i < this.passes-1; i++) + { + filterManager.applyFilter(this, flip, flop, true); + + var temp = flop; + flop = flip; + flip = temp; + } + + filterManager.applyFilter(this, flip, output, clear); + + filterManager.returnRenderTarget(renderTarget); + } +}; + + +Object.defineProperties(BlurYFilter.prototype, { + /** + * Sets the strength of both the blur. + * + * @member {number} + * @memberof PIXI.filters.BlurYFilter# + * @default 2 + */ + blur: { + get: function () + { + return this.strength; + }, + set: function (value) + { + this.padding = Math.abs(value) * 0.5; + this.strength = value; + } + } +}); diff --git a/src/filters/blur/blur.frag b/src/filters/blur/blur.frag new file mode 100644 index 0000000..0c4f23c --- /dev/null +++ b/src/filters/blur/blur.frag @@ -0,0 +1,31 @@ +precision mediump float; + +varying vec2 vTextureCoord; +varying vec2 vBlurTexCoords[15]; + +uniform sampler2D uSampler; + +void main(void) +{ + gl_FragColor = vec4(0.0); + + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 0]) * 0.000489; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 1]) * 0.002403; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 2]) * 0.009246; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 3]) * 0.02784; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 4]) * 0.065602; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 5]) * 0.120999; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 6]) * 0.174697; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 7]) * 0.197448; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 8]) * 0.174697; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 9]) * 0.120999; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 10]) * 0.065602; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 11]) * 0.02784; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 12]) * 0.009246; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 13]) * 0.002403; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 14]) * 0.000489; + + + + +} diff --git a/src/filters/blur/blurX.vert b/src/filters/blur/blurX.vert new file mode 100644 index 0000000..cc0e22b --- /dev/null +++ b/src/filters/blur/blurX.vert @@ -0,0 +1,31 @@ +attribute vec2 aVertexPosition; +attribute vec2 aTextureCoord; + +uniform float strength; +uniform mat3 projectionMatrix; + +varying vec2 vTextureCoord; +varying vec2 vBlurTexCoords[15]; + +void main(void) +{ + gl_Position = vec4((projectionMatrix * vec3((aVertexPosition), 1.0)).xy, 0.0, 1.0); + vTextureCoord = aTextureCoord; + + vBlurTexCoords[ 0] = aTextureCoord + vec2(-7.0 * strength, 0.0); + vBlurTexCoords[ 1] = aTextureCoord + vec2(-6.0 * strength, 0.0); + vBlurTexCoords[ 2] = aTextureCoord + vec2(-5.0 * strength, 0.0); + vBlurTexCoords[ 3] = aTextureCoord + vec2(-4.0 * strength, 0.0); + vBlurTexCoords[ 4] = aTextureCoord + vec2(-3.0 * strength, 0.0); + vBlurTexCoords[ 5] = aTextureCoord + vec2(-2.0 * strength, 0.0); + vBlurTexCoords[ 6] = aTextureCoord + vec2(-1.0 * strength, 0.0); + vBlurTexCoords[ 7] = aTextureCoord; + vBlurTexCoords[ 8] = aTextureCoord + vec2(1.0 * strength, 0.0); + vBlurTexCoords[ 9] = aTextureCoord + vec2(2.0 * strength, 0.0); + vBlurTexCoords[ 10] = aTextureCoord + vec2(3.0 * strength, 0.0); + vBlurTexCoords[ 11] = aTextureCoord + vec2(4.0 * strength, 0.0); + vBlurTexCoords[ 12] = aTextureCoord + vec2(5.0 * strength, 0.0); + vBlurTexCoords[ 13] = aTextureCoord + vec2(6.0 * strength, 0.0); + vBlurTexCoords[ 14] = aTextureCoord + vec2(7.0 * strength, 0.0); + +} diff --git a/src/filters/blur/blurY.vert b/src/filters/blur/blurY.vert new file mode 100644 index 0000000..f1616f7 --- /dev/null +++ b/src/filters/blur/blurY.vert @@ -0,0 +1,32 @@ +attribute vec2 aVertexPosition; +attribute vec2 aTextureCoord; + +uniform float strength; +uniform mat3 projectionMatrix; + +varying vec2 vTextureCoord; +varying vec2 vBlurTexCoords[15]; + +void main(void) +{ + gl_Position = vec4((projectionMatrix * vec3((aVertexPosition), 1.0)).xy, 0.0, 1.0); + vTextureCoord = aTextureCoord; + + vBlurTexCoords[ 0] = aTextureCoord + vec2(0.0, -7.0 * strength); + vBlurTexCoords[ 1] = aTextureCoord + vec2(0.0, -6.0 * strength); + vBlurTexCoords[ 2] = aTextureCoord + vec2(0.0, -5.0 * strength); + vBlurTexCoords[ 3] = aTextureCoord + vec2(0.0, -4.0 * strength); + vBlurTexCoords[ 4] = aTextureCoord + vec2(0.0, -3.0 * strength); + vBlurTexCoords[ 5] = aTextureCoord + vec2(0.0, -2.0 * strength); + vBlurTexCoords[ 6] = aTextureCoord + vec2(0.0, -1.0 * strength); + vBlurTexCoords[ 7] = aTextureCoord; + vBlurTexCoords[ 8] = aTextureCoord + vec2(0.0, 1.0 * strength); + vBlurTexCoords[ 9] = aTextureCoord + vec2(0.0, 2.0 * strength); + vBlurTexCoords[ 10] = aTextureCoord + vec2(0.0, 3.0 * strength); + vBlurTexCoords[ 11] = aTextureCoord + vec2(0.0, 4.0 * strength); + vBlurTexCoords[ 12] = aTextureCoord + vec2(0.0, 5.0 * strength); + vBlurTexCoords[ 13] = aTextureCoord + vec2(0.0, 6.0 * strength); + vBlurTexCoords[ 14] = aTextureCoord + vec2(0.0, 7.0 * strength); + + +} diff --git a/package.json b/package.json index 4436b84..48a074c 100644 --- a/package.json +++ b/package.json @@ -32,10 +32,8 @@ "dependencies": { "async": "^1.5.0", "bit-twiddle": "^1.0.2", - "brfs": "^1.4.1", "earcut": "^2.0.7", "eventemitter3": "^1.1.1", - "gl-matrix": "git+https://github.com/toji/gl-matrix.git", "object-assign": "^4.0.1", "pixi-gl-core": "git+https://github.com/GoodBoyDigital/pixi-gl-core.git", "resource-loader": "^1.6.4" @@ -73,6 +71,5 @@ "transform": [ "glslify" ] - } } diff --git a/src/core/graphics/webgl/PrimitiveShader.js b/src/core/graphics/webgl/PrimitiveShader.js deleted file mode 100644 index 44166b3..0000000 --- a/src/core/graphics/webgl/PrimitiveShader.js +++ /dev/null @@ -1,50 +0,0 @@ -var Shader = require('pixi-gl-core').GLShader; - -/** - * This shader is used to draw simple primitive shapes for {@link PIXI.Graphics}. - * - * @class - * @memberof PIXI - * @extends PIXI.Shader - * @param shaderManager {ShaderManager} The webgl shader manager this shader works for. - */ -function PrimitiveShader(gl) -{ - Shader.call(this, - gl, - // vertex shader - [ - 'attribute vec2 aVertexPosition;', - 'attribute vec4 aColor;', - - 'uniform mat3 translationMatrix;', - 'uniform mat3 projectionMatrix;', - - 'uniform float alpha;', - 'uniform float flipY;', - 'uniform vec3 tint;', - - 'varying vec4 vColor;', - - 'void main(void){', - ' gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', - ' vColor = aColor * vec4(tint * alpha, alpha);', - '}' - ].join('\n'), - // fragment shader - [ - 'precision mediump float;', - - 'varying vec4 vColor;', - - 'void main(void){', - ' gl_FragColor = vColor;', - '}' - ].join('\n') - ); -} - -PrimitiveShader.prototype = Object.create(Shader.prototype); -PrimitiveShader.prototype.constructor = PrimitiveShader; - -module.exports = PrimitiveShader; diff --git a/src/core/math/Matrix.js b/src/core/math/Matrix.js index 4e7fe99..2313ae3 100644 --- a/src/core/math/Matrix.js +++ b/src/core/math/Matrix.js @@ -51,6 +51,7 @@ * @default 0 */ this.ty = 0; + } Matrix.prototype.constructor = Matrix; diff --git a/src/core/renderers/webgl/managers/FilterManager.js b/src/core/renderers/webgl/managers/FilterManager.js index b3f7463..5fc6562 100644 --- a/src/core/renderers/webgl/managers/FilterManager.js +++ b/src/core/renderers/webgl/managers/FilterManager.js @@ -64,11 +64,12 @@ - //TODO - should this be rounded to reoultion? not 1? - sourceFrame.x = targetBounds.x | 0; - sourceFrame.y = targetBounds.y | 0; - sourceFrame.width = targetBounds.width | 0; - sourceFrame.height = targetBounds.height | 0; + + sourceFrame.x = ((targetBounds.x * resolution) | 0) / resolution; + sourceFrame.y = ((targetBounds.y * resolution) | 0) / resolution; + sourceFrame.width = ((targetBounds.width * resolution) | 0) / resolution; + sourceFrame.height = ((targetBounds.height * resolution) | 0) / resolution; + sourceFrame.pad(padding * resolution); sourceFrame.fit(this.stack[0].destinationFrame); @@ -79,6 +80,7 @@ currentState.target = target; currentState.filters = filters; + currentState.resolution = resolution; currentState.renderTarget = renderTarget; // bind the render taget to draw the shape in the top corner.. @@ -236,6 +238,13 @@ shader.uniforms[i] = uniforms[i]; } } + else if(uniformData[i].type === 'float') + { + if(shader.uniforms.data[i].value !== uniformData[i]) + { + shader.uniforms[i] = uniforms[i]; + } + } else { shader.uniforms[i] = uniforms[i]; @@ -244,10 +253,18 @@ } -FilterManager.prototype.getPotRenderTarget = function() +FilterManager.prototype.getRenderTarget = function() { var currentState = this.stack[this.stackIndex]; - return FilterManager.getPotRenderTarget(renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, 1); + var renderTarget = FilterManager.getPotRenderTarget(renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, currentState.resolution); + renderTarget.setFrame(currentState.destinationFrame, currentState.sourceFrame); + + return renderTarget; +} + +FilterManager.prototype.returnRenderTarget = function(renderTarget) +{ + return FilterManager.freePotRenderTarget(renderTarget); } /* @@ -325,6 +342,7 @@ this.destinationFrame = new math.Rectangle(); this.filters = []; this.target = null; + this.resolution = 1; } FilterManager.pool = {} diff --git a/src/core/renderers/webgl/utils/RenderTarget.js b/src/core/renderers/webgl/utils/RenderTarget.js index ced94f6..d3daf50 100644 --- a/src/core/renderers/webgl/utils/RenderTarget.js +++ b/src/core/renderers/webgl/utils/RenderTarget.js @@ -136,6 +136,15 @@ { this.frameBuffer = GLFramebuffer.createRGBA(gl, 100, 100); + if( this.scaleMode === CONST.SCALE_MODES.NEAREST) + { + this.frameBuffer.texture.enableNearestScaling() + } + else + { + this.frameBuffer.texture.enableLinearScaling() + + } /* A frame buffer needs a target to render to.. create a texture and bind it attach it to the framebuffer.. @@ -213,8 +222,10 @@ this.projectionMatrix.append(this.transform); } + //TODO add a check as them may be the same! if(this.destinationFrame !== this.sourceFrame) { + gl.enable(gl.SCISSOR_TEST); gl.scissor(this.destinationFrame.x | 0,this.destinationFrame.y | 0, (this.destinationFrame.width * this.resolution) | 0, (this.destinationFrame.height* this.resolution) | 0); } @@ -279,8 +290,6 @@ return; } - console.log(width + " : " + height) - this.size.width = width; this.size.height = height; diff --git a/src/core/textures/BaseRenderTexture copy.js b/src/core/textures/BaseRenderTexture copy.js deleted file mode 100644 index acf6ac9..0000000 --- a/src/core/textures/BaseRenderTexture copy.js +++ /dev/null @@ -1,482 +0,0 @@ -var BaseTexture = require('./BaseTexture'), - Texture = require('./Texture'), - RenderTarget = require('../renderers/webgl/utils/RenderTarget'), - FilterManager = require('../renderers/webgl/managers/FilterManager'), - CanvasBuffer = require('../renderers/canvas/utils/CanvasBuffer'), - math = require('../math'), - CONST = require('../const'), - tempMatrix = new math.Matrix(), - tempRect = new math.Rectangle(); - -/** - * A BaseRenderTexture is a special texture that allows any Pixi display object to be rendered to it. - * - * __Hint__: All DisplayObjects (i.e. Sprites) that render to a BaseRenderTexture should be preloaded - * otherwise black rectangles will be drawn instead. - * - * A BaseRenderTexture takes a snapshot of any Display Object given to its render method. The position - * and rotation of the given Display Objects is ignored. For example: - * - * ```js - * var renderer = PIXI.autoDetectRenderer(1024, 1024, { view: canvas, ratio: 1 }); - * var BaserenderTexture = new PIXI.BaseRenderTexture(renderer, 800, 600); - * var sprite = PIXI.Sprite.fromImage("spinObj_01.png"); - * - * sprite.position.x = 800/2; - * sprite.position.y = 600/2; - * sprite.anchor.x = 0.5; - * sprite.anchor.y = 0.5; - * - * BaserenderTexture.render(sprite); - * ``` - * - * The Sprite in this case will be rendered to a position of 0,0. To render this sprite at its actual - * position a Container should be used: - * - * ```js - * var doc = new PIXI.Container(); - * - * doc.addChild(sprite); - * - * BaserenderTexture.render(doc); // Renders to center of BaserenderTexture - * ``` - * - * @class - * @extends PIXI.Texture - * @memberof PIXI - * @param renderer {PIXI.CanvasRenderer|PIXI.WebGLRenderer} The renderer used for this BaseRenderTexture - * @param [width=100] {number} The width of the render texture - * @param [height=100] {number} The height of the render texture - * @param [scaleMode] {number} See {@link PIXI.SCALE_MODES} for possible values - * @param [resolution=1] {number} The resolution of the texture being generated - */ -function BaseRenderTexture(renderer, width, height, scaleMode, resolution) -{ - if (!renderer) - { - throw new Error('Unable to create BaseRenderTexture, you must pass a renderer into the constructor.'); - } - - BaseTexture.call(this, null, scaleMode); - - this.width = width || 100; - this.height = height || 100; - - this.resolution = resolution || CONST.RESOLUTION;; - this.scaleMode = scaleMode || CONST.SCALE_MODES.DEFAULT; - this.hasLoaded = true; - - /** - * Draw/render the given DisplayObject onto the texture. - * - * The displayObject and descendents are transformed during this operation. - * If `updateTransform` is true then the transformations will be restored before the - * method returns. Otherwise it is up to the calling code to correctly use or reset - * the transformed display objects. - * - * The display object is always rendered with a worldAlpha value of 1. - * - * @method - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear=false] {boolean} If true the texture will be cleared before the displayObject is drawn - * @param [updateTransform=true] {boolean} If true the displayObject's worldTransform/worldAlpha and all children - * transformations will be restored. Not restoring this information will be a little faster. - */ - this.render = null; - - /** - * The renderer this BaseRenderTexture uses. A BaseRenderTexture can only belong to one renderer at the moment if its webGL. - * - * @member {PIXI.CanvasRenderer|PIXI.WebGLRenderer} - */ - this.renderer = renderer; - - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - var gl = this.renderer.gl; - - this.textureBuffer = new RenderTarget(gl, this.width, this.height, this.scaleMode, this.resolution);//, this.this.scaleMode); - this._glTextures[gl.id] = this.textureBuffer.texture; - - //TODO refactor filter manager.. as really its no longer a manager if we use it here.. - this.filterManager = new FilterManager(this.renderer); - this.filterManager.onContextChange(); - this.filterManager.resize(width, height); - this.render = this.renderWebGL; - - // the creation of a filter manager unbinds the buffers.. - this.renderer.currentRenderer.start(); - if(this.renderer._activeRenderTarget)this.renderer._activeRenderTarget.activate(); - } - else - { - - this.render = this.renderCanvas; - this.textureBuffer = new CanvasBuffer(this.width* this.resolution, this.height* this.resolution); - this.source = this.textureBuffer.canvas; - } - - /** - * @member {boolean} - */ - this.valid = true; - -} - -BaseRenderTexture.prototype = Object.create(BaseTexture.prototype); -BaseRenderTexture.prototype.constructor = BaseRenderTexture; -module.exports = BaseRenderTexture; - -/** - * Resizes the BaseRenderTexture. - * - * @param width {number} The width to resize to. - * @param height {number} The height to resize to. - * @param updateBase {boolean} Should the baseTexture.width and height values be resized as well? - */ -BaseRenderTexture.prototype.resize = function (width, height) -{ - if (width === this.width && height === this.height) - { - return; - } - - this.valid = (width > 0 && height > 0); - - this.width = width; - this.height = height; - - if (!this.valid) - { - return; - } - - this.textureBuffer.resize(this.width, this.height); - - if(this.filterManager) - { - this.filterManager.resize(this.width, this.height); - } -}; - -/** - * Clears the BaseRenderTexture. - * - */ -BaseRenderTexture.prototype.clear = function (destinationFrame) -{ - if (!this.valid) - { - return; - } - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - this.renderer.gl.bindFramebuffer(this.renderer.gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - } - - this.textureBuffer.clear(false, destinationFrame); -}; - -/** - * Internal method assigned to the `render` property if using a CanvasRenderer. - * - * @private - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear=false] {boolean} If true the texture will be cleared before the displayObject is drawn - * @param [updateTransform=true] {boolean} If true the displayObject's worldTransform/worldAlpha and all children - * transformations will be restored. Not restoring this information will be a little faster. - */ -BaseRenderTexture.prototype.renderWebGL = function (frame, displayObject, matrix, clear, updateTransform) -{ - if (!this.valid) - { - return; - } - - - updateTransform = (updateTransform !== undefined) ? updateTransform : true;//!updateTransform; - - this.textureBuffer.transform = matrix; - - //TODO not a fan that this is here... it will move! - this.textureBuffer.activate(); - - // setWorld Alpha to ensure that the object is renderer at full opacity - displayObject.worldAlpha = 1; - - if (updateTransform) - { - - // reset the matrix of the displatyObject.. - displayObject.worldTransform.identity(); - - displayObject.currentBounds = null; - - // Time to update all the children of the displayObject with the new matrix.. - var children = displayObject.children; - var i, j; - - for (i = 0, j = children.length; i < j; ++i) - { - children[i].updateTransform(); - } - } - - tempRect.width = frame.height; - tempRect.height = frame.width; - - //TODO rename textureBuffer to renderTarget.. - var temp = this.renderer.filterManager; - - this.renderer.filterManager = this.filterManager; - - - this.textureBuffer.activate(frame, tempRect); - console.log(displayObject) - this.renderer.renderDisplayObject(displayObject, this.textureBuffer, clear); - - // console.log("RENDERING "); - this.renderer.filterManager = temp; -}; - - -/** - * Internal method assigned to the `render` property if using a CanvasRenderer. - * - * @private - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear] {boolean} If true the texture will be cleared before the displayObject is drawn - */ -BaseRenderTexture.prototype.renderCanvas = function (frame, displayObject, matrix, clear, updateTransform) -{ - if (!this.valid) - { - return; - } - - updateTransform = !!updateTransform; - - var wt = tempMatrix; - - wt.identity(); - - if (matrix) - { - wt.append(matrix); - } - - - wt.tx += frame.x; - wt.ty += frame.y; - - var cachedWt = displayObject.worldTransform; - - displayObject.worldTransform = wt; - - // setWorld Alpha to ensure that the object is renderer at full opacity - displayObject.worldAlpha = 1; - - // Time to update all the children of the displayObject with the new matrix.. - var children = displayObject.children; - var i, j; - - for (i = 0, j = children.length; i < j; ++i) - { - children[i].updateTransform(); - } - - if (clear) - { - this.textureBuffer.clear(); - } - - -// this.textureBuffer. - var context = this.textureBuffer.context; - - var realResolution = this.renderer.resolution; - - this.renderer.resolution = this.resolution; - - this.renderer.renderDisplayObject(displayObject, context); - - this.renderer.resolution = realResolution; - - if(displayObject.worldTransform === wt) - { - // fixes cacheAsBitmap Happening during the above.. - displayObject.worldTransform = cachedWt; - } - -}; - -/** - * Destroys this texture - * - * @param destroyBase {boolean} Whether to destroy the base texture as well - */ -BaseRenderTexture.prototype.destroy = function () -{ - Texture.prototype.destroy.call(this, true); - - this.textureBuffer.destroy(); - - // destroy the filtermanager.. - if(this.filterManager) - { - this.filterManager.destroy(); - } - - this.renderer = null; -}; - -/** - * Will return a HTML Image of the texture - * - * @return {Image} - */ -BaseRenderTexture.prototype.getImage = function (frame) -{ - var image = new Image(); - image.src = this.getBase64(frame); - return image; -}; - -/** - * Will return a a base64 encoded string of this texture. It works by calling BaseRenderTexture.getCanvas and then running toDataURL on that. - * - * @return {string} A base64 encoded string of the texture. - */ -BaseRenderTexture.prototype.getBase64 = function ( frame ) -{ - return this.getCanvas(frame).toDataURL(); -}; - -/** - * Creates a Canvas element, renders this BaseRenderTexture to it and then returns it. - * - * @return {HTMLCanvasElement} A Canvas element with the texture rendered on. - */ -BaseRenderTexture.prototype.getCanvas = function ( frame ) -{ - - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.size.width; - frame.height = this.textureBuffer.size.height; - } - - var width = frame.width * this.resolution; - var height = frame.height * this.resolution; - - var gl = this.renderer.gl; - - var webGLPixels = new Uint8Array(4 * width * height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - gl.readPixels(frame.x * this.resolution, frame.y * this.resolution, width, height, gl.RGBA, gl.UNSIGNED_BYTE, webGLPixels); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - var tempCanvas = new CanvasBuffer(width, height); - var canvasData = tempCanvas.context.getImageData(0, 0, width, height); - canvasData.data.set(webGLPixels); - - tempCanvas.context.putImageData(canvasData, 0, 0); - - return tempCanvas.canvas; - } - else - { - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.canvas.width; - frame.height = this.textureBuffer.canvas.height; - } - - if(frame.width === this.textureBuffer.canvas.width && - frame.height === this.textureBuffer.canvas.height ) - { - return this.textureBuffer.canvas; - } - else - { - - var resolution = this.resolution; - - var tempCanvas = new CanvasBuffer(frame.width * resolution, frame.height * resolution); - var canvasData = this.textureBuffer.context.getImageData(frame.x * resolution, frame.y * resolution, frame.width * resolution, frame.height * resolution); - - tempCanvas.context.putImageData(canvasData, 0, 0); - - return tempCanvas.canvas; - } - } -}; - -/** - * Will return a one-dimensional array containing the pixel data of the entire texture in RGBA order, with integer values between 0 and 255 (included). - * - * @return {Uint8ClampedArray} - */ -BaseRenderTexture.prototype.getPixels = function ( frame ) -{ - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.size.width; - frame.height = this.textureBuffer.size.height; - } - - var width = frame.width * this.resolution; - var height = frame.height * this.resolution; - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - var gl = this.renderer.gl; - - var webGLPixels = new Uint8Array(4 * width * height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - gl.readPixels(frame.x * this.resolution, frame.y * this.resolution, width, height, gl.RGBA, gl.UNSIGNED_BYTE, webGLPixels); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - return webGLPixels; - } - else - { - return this.textureBuffer.canvas.getContext('2d').getImageData(frame.x * this.resolution, frame.y * this.resolution, width, height).data; - } -}; - -/** - * Will return a one-dimensional array containing the pixel data of a pixel within the texture in RGBA order, with integer values between 0 and 255 (included). - * - * @param x {number} The x coordinate of the pixel to retrieve. - * @param y {number} The y coordinate of the pixel to retrieve. - * @return {Uint8ClampedArray} - */ -BaseRenderTexture.prototype.getPixel = function (frame, x, y) -{ - tempRect.x = x; - tempRect.y = y; - tempRect.width = 1 / this.resolution; - tempRect.height = 1 / this.resolution; - - if(frame) - { - tempRect.x += frame.x; - tempRect.y += frame.y; - } - - return this.getPixels(tempRect); -}; diff --git a/src/filters/blur/BlurFilter.js b/src/filters/blur/BlurFilter.js new file mode 100644 index 0000000..fb708a1 --- /dev/null +++ b/src/filters/blur/BlurFilter.js @@ -0,0 +1,114 @@ +var core = require('../../core'), + BlurXFilter = require('./BlurXFilter'), + BlurYFilter = require('./BlurYFilter'); + +/** + * The BlurFilter applies a Gaussian blur to an object. + * The strength of the blur can be set for x- and y-axis separately. + * + * @class + * @extends PIXI.Filter + * @memberof PIXI.filters + */ +function BlurFilter() +{ + core.Filter.call(this); + + this.blurXFilter = new BlurXFilter(); + this.blurYFilter = new BlurYFilter(); + this.resolution = 0.25;//0.25;//0.25//1//01.26; + this.blurYFilter.passes = this.blurXFilter.passes = 2; + this.blurYFilter.strength = this.blurXFilter.strength = 4;//4// 4 + + this.padding = 100 + +} + +BlurFilter.prototype = Object.create(core.Filter.prototype); +BlurFilter.prototype.constructor = BlurFilter; +module.exports = BlurFilter; + +BlurFilter.prototype.apply = function (filterManager, input, output) +{ + var renderTarget = filterManager.getRenderTarget(true); + + this.blurXFilter.apply(filterManager, input, renderTarget, true); + this.blurYFilter.apply(filterManager, renderTarget, output); + + filterManager.returnRenderTarget(renderTarget); +}; + +Object.defineProperties(BlurFilter.prototype, { + /** + * Sets the strength of both the blurX and blurY properties simultaneously + * + * @member {number} + * @memberOf PIXI.filters.BlurFilter# + * @default 2 + */ + blur: { + get: function () + { + return this.blurXFilter.blur; + }, + set: function (value) + { + this.padding = Math.abs(value) * 0.5; + this.blurXFilter.blur = this.blurYFilter.blur = value; + } + }, + + /** + * Sets the number of passes for blur. More passes means higher quaility bluring. + * + * @member {number} + * @memberof PIXI.filters.BlurYFilter# + * @default 1 + */ + passes: { + get: function () + { + return this.blurXFilter.passes; + }, + set: function (value) + { + this.blurXFilter.passes = this.blurYFilter.passes = value; + } + }, + + /** + * Sets the strength of the blurX property + * + * @member {number} + * @memberOf PIXI.filters.BlurFilter# + * @default 2 + */ + blurX: { + get: function () + { + return this.blurXFilter.blur; + }, + set: function (value) + { + this.blurXFilter.blur = value; + } + }, + + /** + * Sets the strength of the blurY property + * + * @member {number} + * @memberOf PIXI.filters.BlurFilter# + * @default 2 + */ + blurY: { + get: function () + { + return this.blurYFilter.blur; + }, + set: function (value) + { + this.blurYFilter.blur = value; + } + } +}); diff --git a/src/filters/blur/BlurXFilter.js b/src/filters/blur/BlurXFilter.js new file mode 100644 index 0000000..61eed96 --- /dev/null +++ b/src/filters/blur/BlurXFilter.js @@ -0,0 +1,94 @@ +var core = require('../../core'); +var glslify = require('glslify'); +var generateBlurVertSource = require('./generateBlurVertSource'); +var generateBlurFragSource = require('./generateBlurFragSource'); + +/** + * The BlurXFilter applies a horizontal Gaussian blur to an object. + * + * @class + * @extends PIXI.Filter + * @memberof PIXI.filters + */ +function BlurXFilter() +{ + var vertSrc = generateBlurVertSource(11, true); + var fragSrc = generateBlurFragSource(11); + + console.log(vertSrc); + console.log(fragSrc); + + core.Filter.call(this, + // vertex shader + vertSrc, + // fragment shader + fragSrc + ); + + /** + * Sets the number of passes for blur. More passes means higher quaility bluring. + * + * @member {number} + * @default 1 + */ + this.passes = 1; + this.resolution = 1;//0.25;//0.5;//0.1//5; + this.strength = 4; +} + +BlurXFilter.prototype = Object.create(core.Filter.prototype); +BlurXFilter.prototype.constructor = BlurXFilter; +module.exports = BlurXFilter; + +BlurXFilter.prototype.apply = function (filterManager, input, output, clear) +{ + this.uniforms.strength = (1/output.destinationFrame.width) * (output.size.width/input.size.width); /// // * 2 //4//this.strength / 4 / this.passes * (input.frame.width / input.size.width); + + // screen space! + this.uniforms.strength *= this.strength; + if(this.passes === 1) + { + filterManager.applyFilter(this, input, output, clear); + } + else + { + var renderTarget = filterManager.getRenderTarget(true); + var flip = input; + var flop = renderTarget; + + for(var i = 0; i < this.passes-1; i++) + { + filterManager.applyFilter(this, flip, flop, true); + + var temp = flop; + flop = flip; + flip = temp; + } + + filterManager.applyFilter(this, flip, output, clear); + + filterManager.returnRenderTarget(renderTarget); + } +}; + + +Object.defineProperties(BlurXFilter.prototype, { + /** + * Sets the strength of both the blur. + * + * @member {number} + * @memberof PIXI.filters.BlurXFilter# + * @default 2 + */ + blur: { + get: function () + { + return this.strength; + }, + set: function (value) + { + this.padding = Math.abs(value) * 0.5; + this.strength = value; + } + } +}); diff --git a/src/filters/blur/BlurYFilter.js b/src/filters/blur/BlurYFilter.js new file mode 100644 index 0000000..86a3171 --- /dev/null +++ b/src/filters/blur/BlurYFilter.js @@ -0,0 +1,85 @@ +var core = require('../../core'); +var generateBlurVertSource = require('./generateBlurVertSource'); +var generateBlurFragSource = require('./generateBlurFragSource'); + + +/** + * The BlurYFilter applies a horizontal Gaussian blur to an object. + * + * @class + * @extends PIXI.Filter + * @memberof PIXI.filters + */ +function BlurYFilter() +{ + var vertSrc = generateBlurVertSource(11, false); + var fragSrc = generateBlurFragSource(11); + + core.Filter.call(this, + // vertex shader + vertSrc, + // fragment shader + fragSrc + ); + + this.passes = 1; + this.resolution = 1;//0.25;//0.5;//0.1//5; + this.strength = 4; +} + +BlurYFilter.prototype = Object.create(core.Filter.prototype); +BlurYFilter.prototype.constructor = BlurYFilter; +module.exports = BlurYFilter; + +BlurYFilter.prototype.apply = function (filterManager, input, output, clear) +{ + this.uniforms.strength = (1/output.destinationFrame.height) * (output.size.height/input.size.height); /// // * 2 //4//this.strength / 4 / this.passes * (input.frame.width / input.size.width); + + this.uniforms.strength *= this.strength; + + if(this.passes === 1) + { + filterManager.applyFilter(this, input, output, clear); + } + else + { + var renderTarget = filterManager.getRenderTarget(true); + var flip = input; + var flop = renderTarget; + + for(var i = 0; i < this.passes-1; i++) + { + filterManager.applyFilter(this, flip, flop, true); + + var temp = flop; + flop = flip; + flip = temp; + } + + filterManager.applyFilter(this, flip, output, clear); + + filterManager.returnRenderTarget(renderTarget); + } +}; + + +Object.defineProperties(BlurYFilter.prototype, { + /** + * Sets the strength of both the blur. + * + * @member {number} + * @memberof PIXI.filters.BlurYFilter# + * @default 2 + */ + blur: { + get: function () + { + return this.strength; + }, + set: function (value) + { + this.padding = Math.abs(value) * 0.5; + this.strength = value; + } + } +}); diff --git a/src/filters/blur/blur.frag b/src/filters/blur/blur.frag new file mode 100644 index 0000000..0c4f23c --- /dev/null +++ b/src/filters/blur/blur.frag @@ -0,0 +1,31 @@ +precision mediump float; + +varying vec2 vTextureCoord; +varying vec2 vBlurTexCoords[15]; + +uniform sampler2D uSampler; + +void main(void) +{ + gl_FragColor = vec4(0.0); + + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 0]) * 0.000489; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 1]) * 0.002403; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 2]) * 0.009246; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 3]) * 0.02784; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 4]) * 0.065602; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 5]) * 0.120999; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 6]) * 0.174697; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 7]) * 0.197448; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 8]) * 0.174697; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 9]) * 0.120999; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 10]) * 0.065602; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 11]) * 0.02784; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 12]) * 0.009246; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 13]) * 0.002403; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 14]) * 0.000489; + + + + +} diff --git a/src/filters/blur/blurX.vert b/src/filters/blur/blurX.vert new file mode 100644 index 0000000..cc0e22b --- /dev/null +++ b/src/filters/blur/blurX.vert @@ -0,0 +1,31 @@ +attribute vec2 aVertexPosition; +attribute vec2 aTextureCoord; + +uniform float strength; +uniform mat3 projectionMatrix; + +varying vec2 vTextureCoord; +varying vec2 vBlurTexCoords[15]; + +void main(void) +{ + gl_Position = vec4((projectionMatrix * vec3((aVertexPosition), 1.0)).xy, 0.0, 1.0); + vTextureCoord = aTextureCoord; + + vBlurTexCoords[ 0] = aTextureCoord + vec2(-7.0 * strength, 0.0); + vBlurTexCoords[ 1] = aTextureCoord + vec2(-6.0 * strength, 0.0); + vBlurTexCoords[ 2] = aTextureCoord + vec2(-5.0 * strength, 0.0); + vBlurTexCoords[ 3] = aTextureCoord + vec2(-4.0 * strength, 0.0); + vBlurTexCoords[ 4] = aTextureCoord + vec2(-3.0 * strength, 0.0); + vBlurTexCoords[ 5] = aTextureCoord + vec2(-2.0 * strength, 0.0); + vBlurTexCoords[ 6] = aTextureCoord + vec2(-1.0 * strength, 0.0); + vBlurTexCoords[ 7] = aTextureCoord; + vBlurTexCoords[ 8] = aTextureCoord + vec2(1.0 * strength, 0.0); + vBlurTexCoords[ 9] = aTextureCoord + vec2(2.0 * strength, 0.0); + vBlurTexCoords[ 10] = aTextureCoord + vec2(3.0 * strength, 0.0); + vBlurTexCoords[ 11] = aTextureCoord + vec2(4.0 * strength, 0.0); + vBlurTexCoords[ 12] = aTextureCoord + vec2(5.0 * strength, 0.0); + vBlurTexCoords[ 13] = aTextureCoord + vec2(6.0 * strength, 0.0); + vBlurTexCoords[ 14] = aTextureCoord + vec2(7.0 * strength, 0.0); + +} diff --git a/src/filters/blur/blurY.vert b/src/filters/blur/blurY.vert new file mode 100644 index 0000000..f1616f7 --- /dev/null +++ b/src/filters/blur/blurY.vert @@ -0,0 +1,32 @@ +attribute vec2 aVertexPosition; +attribute vec2 aTextureCoord; + +uniform float strength; +uniform mat3 projectionMatrix; + +varying vec2 vTextureCoord; +varying vec2 vBlurTexCoords[15]; + +void main(void) +{ + gl_Position = vec4((projectionMatrix * vec3((aVertexPosition), 1.0)).xy, 0.0, 1.0); + vTextureCoord = aTextureCoord; + + vBlurTexCoords[ 0] = aTextureCoord + vec2(0.0, -7.0 * strength); + vBlurTexCoords[ 1] = aTextureCoord + vec2(0.0, -6.0 * strength); + vBlurTexCoords[ 2] = aTextureCoord + vec2(0.0, -5.0 * strength); + vBlurTexCoords[ 3] = aTextureCoord + vec2(0.0, -4.0 * strength); + vBlurTexCoords[ 4] = aTextureCoord + vec2(0.0, -3.0 * strength); + vBlurTexCoords[ 5] = aTextureCoord + vec2(0.0, -2.0 * strength); + vBlurTexCoords[ 6] = aTextureCoord + vec2(0.0, -1.0 * strength); + vBlurTexCoords[ 7] = aTextureCoord; + vBlurTexCoords[ 8] = aTextureCoord + vec2(0.0, 1.0 * strength); + vBlurTexCoords[ 9] = aTextureCoord + vec2(0.0, 2.0 * strength); + vBlurTexCoords[ 10] = aTextureCoord + vec2(0.0, 3.0 * strength); + vBlurTexCoords[ 11] = aTextureCoord + vec2(0.0, 4.0 * strength); + vBlurTexCoords[ 12] = aTextureCoord + vec2(0.0, 5.0 * strength); + vBlurTexCoords[ 13] = aTextureCoord + vec2(0.0, 6.0 * strength); + vBlurTexCoords[ 14] = aTextureCoord + vec2(0.0, 7.0 * strength); + + +} diff --git a/src/filters/blur/generateBlurFragSource.js b/src/filters/blur/generateBlurFragSource.js new file mode 100644 index 0000000..59cf930 --- /dev/null +++ b/src/filters/blur/generateBlurFragSource.js @@ -0,0 +1,63 @@ +var core = require('../../core') + +var GAUSSIAN_VALUES = { + 5:[0.06136, 0.24477, 0.38774], + 7:[0.00598, 0.060626, 0.241843, 0.383103], + 9:[0.000229, 0.005977, 0.060598, 0.241732, 0.382928], + 11:[0.000003, 0.000229, 0.005977, 0.060598, 0.24173, 0.382925], + 13:[0.0, 0.000003, 0.000229, 0.005977, 0.060598, 0.24173, 0.382925], + 15:[0.0, 0.0, 0.000003, 0.000229, 0.005977, 0.060598, 0.24173, 0.382925] +} + +var generateFragBlurSource = function(kernelSize) +{ + var kernel = GAUSSIAN_VALUES[kernelSize]; + var halfLength = kernel.length; + + var fragSource = fragTemplate; + + var blurLoop = ''; + var template = 'gl_FragColor += texture2D(uSampler, vBlurTexCoords[%index%]) * %value%;' + + for (var i = 0; i < kernelSize; i++) + { + var blur = template.replace('%index%', i); + + value = i; + + if(i >= halfLength) + { + value = kernelSize - i - 1; + } + + + blur = blur.replace('%value%', kernel[value]); + + blurLoop += blur; + blurLoop += '\n'; + }; + + fragSource = fragSource.replace('%blur%', blurLoop) + fragSource = fragSource.replace('%size%', kernelSize) + + + return fragSource; +} + +var fragTemplate = [ + + 'precision mediump float;', + + 'varying vec2 vTextureCoord;', + 'varying vec2 vBlurTexCoords[%size%];', + 'uniform sampler2D uSampler;', + + 'void main(void)', + '{', + ' gl_FragColor = vec4(0.0);', + ' %blur%', + '}' + +].join('\n'); + +module.exports = generateFragBlurSource; \ No newline at end of file diff --git a/package.json b/package.json index 4436b84..48a074c 100644 --- a/package.json +++ b/package.json @@ -32,10 +32,8 @@ "dependencies": { "async": "^1.5.0", "bit-twiddle": "^1.0.2", - "brfs": "^1.4.1", "earcut": "^2.0.7", "eventemitter3": "^1.1.1", - "gl-matrix": "git+https://github.com/toji/gl-matrix.git", "object-assign": "^4.0.1", "pixi-gl-core": "git+https://github.com/GoodBoyDigital/pixi-gl-core.git", "resource-loader": "^1.6.4" @@ -73,6 +71,5 @@ "transform": [ "glslify" ] - } } diff --git a/src/core/graphics/webgl/PrimitiveShader.js b/src/core/graphics/webgl/PrimitiveShader.js deleted file mode 100644 index 44166b3..0000000 --- a/src/core/graphics/webgl/PrimitiveShader.js +++ /dev/null @@ -1,50 +0,0 @@ -var Shader = require('pixi-gl-core').GLShader; - -/** - * This shader is used to draw simple primitive shapes for {@link PIXI.Graphics}. - * - * @class - * @memberof PIXI - * @extends PIXI.Shader - * @param shaderManager {ShaderManager} The webgl shader manager this shader works for. - */ -function PrimitiveShader(gl) -{ - Shader.call(this, - gl, - // vertex shader - [ - 'attribute vec2 aVertexPosition;', - 'attribute vec4 aColor;', - - 'uniform mat3 translationMatrix;', - 'uniform mat3 projectionMatrix;', - - 'uniform float alpha;', - 'uniform float flipY;', - 'uniform vec3 tint;', - - 'varying vec4 vColor;', - - 'void main(void){', - ' gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', - ' vColor = aColor * vec4(tint * alpha, alpha);', - '}' - ].join('\n'), - // fragment shader - [ - 'precision mediump float;', - - 'varying vec4 vColor;', - - 'void main(void){', - ' gl_FragColor = vColor;', - '}' - ].join('\n') - ); -} - -PrimitiveShader.prototype = Object.create(Shader.prototype); -PrimitiveShader.prototype.constructor = PrimitiveShader; - -module.exports = PrimitiveShader; diff --git a/src/core/math/Matrix.js b/src/core/math/Matrix.js index 4e7fe99..2313ae3 100644 --- a/src/core/math/Matrix.js +++ b/src/core/math/Matrix.js @@ -51,6 +51,7 @@ * @default 0 */ this.ty = 0; + } Matrix.prototype.constructor = Matrix; diff --git a/src/core/renderers/webgl/managers/FilterManager.js b/src/core/renderers/webgl/managers/FilterManager.js index b3f7463..5fc6562 100644 --- a/src/core/renderers/webgl/managers/FilterManager.js +++ b/src/core/renderers/webgl/managers/FilterManager.js @@ -64,11 +64,12 @@ - //TODO - should this be rounded to reoultion? not 1? - sourceFrame.x = targetBounds.x | 0; - sourceFrame.y = targetBounds.y | 0; - sourceFrame.width = targetBounds.width | 0; - sourceFrame.height = targetBounds.height | 0; + + sourceFrame.x = ((targetBounds.x * resolution) | 0) / resolution; + sourceFrame.y = ((targetBounds.y * resolution) | 0) / resolution; + sourceFrame.width = ((targetBounds.width * resolution) | 0) / resolution; + sourceFrame.height = ((targetBounds.height * resolution) | 0) / resolution; + sourceFrame.pad(padding * resolution); sourceFrame.fit(this.stack[0].destinationFrame); @@ -79,6 +80,7 @@ currentState.target = target; currentState.filters = filters; + currentState.resolution = resolution; currentState.renderTarget = renderTarget; // bind the render taget to draw the shape in the top corner.. @@ -236,6 +238,13 @@ shader.uniforms[i] = uniforms[i]; } } + else if(uniformData[i].type === 'float') + { + if(shader.uniforms.data[i].value !== uniformData[i]) + { + shader.uniforms[i] = uniforms[i]; + } + } else { shader.uniforms[i] = uniforms[i]; @@ -244,10 +253,18 @@ } -FilterManager.prototype.getPotRenderTarget = function() +FilterManager.prototype.getRenderTarget = function() { var currentState = this.stack[this.stackIndex]; - return FilterManager.getPotRenderTarget(renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, 1); + var renderTarget = FilterManager.getPotRenderTarget(renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, currentState.resolution); + renderTarget.setFrame(currentState.destinationFrame, currentState.sourceFrame); + + return renderTarget; +} + +FilterManager.prototype.returnRenderTarget = function(renderTarget) +{ + return FilterManager.freePotRenderTarget(renderTarget); } /* @@ -325,6 +342,7 @@ this.destinationFrame = new math.Rectangle(); this.filters = []; this.target = null; + this.resolution = 1; } FilterManager.pool = {} diff --git a/src/core/renderers/webgl/utils/RenderTarget.js b/src/core/renderers/webgl/utils/RenderTarget.js index ced94f6..d3daf50 100644 --- a/src/core/renderers/webgl/utils/RenderTarget.js +++ b/src/core/renderers/webgl/utils/RenderTarget.js @@ -136,6 +136,15 @@ { this.frameBuffer = GLFramebuffer.createRGBA(gl, 100, 100); + if( this.scaleMode === CONST.SCALE_MODES.NEAREST) + { + this.frameBuffer.texture.enableNearestScaling() + } + else + { + this.frameBuffer.texture.enableLinearScaling() + + } /* A frame buffer needs a target to render to.. create a texture and bind it attach it to the framebuffer.. @@ -213,8 +222,10 @@ this.projectionMatrix.append(this.transform); } + //TODO add a check as them may be the same! if(this.destinationFrame !== this.sourceFrame) { + gl.enable(gl.SCISSOR_TEST); gl.scissor(this.destinationFrame.x | 0,this.destinationFrame.y | 0, (this.destinationFrame.width * this.resolution) | 0, (this.destinationFrame.height* this.resolution) | 0); } @@ -279,8 +290,6 @@ return; } - console.log(width + " : " + height) - this.size.width = width; this.size.height = height; diff --git a/src/core/textures/BaseRenderTexture copy.js b/src/core/textures/BaseRenderTexture copy.js deleted file mode 100644 index acf6ac9..0000000 --- a/src/core/textures/BaseRenderTexture copy.js +++ /dev/null @@ -1,482 +0,0 @@ -var BaseTexture = require('./BaseTexture'), - Texture = require('./Texture'), - RenderTarget = require('../renderers/webgl/utils/RenderTarget'), - FilterManager = require('../renderers/webgl/managers/FilterManager'), - CanvasBuffer = require('../renderers/canvas/utils/CanvasBuffer'), - math = require('../math'), - CONST = require('../const'), - tempMatrix = new math.Matrix(), - tempRect = new math.Rectangle(); - -/** - * A BaseRenderTexture is a special texture that allows any Pixi display object to be rendered to it. - * - * __Hint__: All DisplayObjects (i.e. Sprites) that render to a BaseRenderTexture should be preloaded - * otherwise black rectangles will be drawn instead. - * - * A BaseRenderTexture takes a snapshot of any Display Object given to its render method. The position - * and rotation of the given Display Objects is ignored. For example: - * - * ```js - * var renderer = PIXI.autoDetectRenderer(1024, 1024, { view: canvas, ratio: 1 }); - * var BaserenderTexture = new PIXI.BaseRenderTexture(renderer, 800, 600); - * var sprite = PIXI.Sprite.fromImage("spinObj_01.png"); - * - * sprite.position.x = 800/2; - * sprite.position.y = 600/2; - * sprite.anchor.x = 0.5; - * sprite.anchor.y = 0.5; - * - * BaserenderTexture.render(sprite); - * ``` - * - * The Sprite in this case will be rendered to a position of 0,0. To render this sprite at its actual - * position a Container should be used: - * - * ```js - * var doc = new PIXI.Container(); - * - * doc.addChild(sprite); - * - * BaserenderTexture.render(doc); // Renders to center of BaserenderTexture - * ``` - * - * @class - * @extends PIXI.Texture - * @memberof PIXI - * @param renderer {PIXI.CanvasRenderer|PIXI.WebGLRenderer} The renderer used for this BaseRenderTexture - * @param [width=100] {number} The width of the render texture - * @param [height=100] {number} The height of the render texture - * @param [scaleMode] {number} See {@link PIXI.SCALE_MODES} for possible values - * @param [resolution=1] {number} The resolution of the texture being generated - */ -function BaseRenderTexture(renderer, width, height, scaleMode, resolution) -{ - if (!renderer) - { - throw new Error('Unable to create BaseRenderTexture, you must pass a renderer into the constructor.'); - } - - BaseTexture.call(this, null, scaleMode); - - this.width = width || 100; - this.height = height || 100; - - this.resolution = resolution || CONST.RESOLUTION;; - this.scaleMode = scaleMode || CONST.SCALE_MODES.DEFAULT; - this.hasLoaded = true; - - /** - * Draw/render the given DisplayObject onto the texture. - * - * The displayObject and descendents are transformed during this operation. - * If `updateTransform` is true then the transformations will be restored before the - * method returns. Otherwise it is up to the calling code to correctly use or reset - * the transformed display objects. - * - * The display object is always rendered with a worldAlpha value of 1. - * - * @method - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear=false] {boolean} If true the texture will be cleared before the displayObject is drawn - * @param [updateTransform=true] {boolean} If true the displayObject's worldTransform/worldAlpha and all children - * transformations will be restored. Not restoring this information will be a little faster. - */ - this.render = null; - - /** - * The renderer this BaseRenderTexture uses. A BaseRenderTexture can only belong to one renderer at the moment if its webGL. - * - * @member {PIXI.CanvasRenderer|PIXI.WebGLRenderer} - */ - this.renderer = renderer; - - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - var gl = this.renderer.gl; - - this.textureBuffer = new RenderTarget(gl, this.width, this.height, this.scaleMode, this.resolution);//, this.this.scaleMode); - this._glTextures[gl.id] = this.textureBuffer.texture; - - //TODO refactor filter manager.. as really its no longer a manager if we use it here.. - this.filterManager = new FilterManager(this.renderer); - this.filterManager.onContextChange(); - this.filterManager.resize(width, height); - this.render = this.renderWebGL; - - // the creation of a filter manager unbinds the buffers.. - this.renderer.currentRenderer.start(); - if(this.renderer._activeRenderTarget)this.renderer._activeRenderTarget.activate(); - } - else - { - - this.render = this.renderCanvas; - this.textureBuffer = new CanvasBuffer(this.width* this.resolution, this.height* this.resolution); - this.source = this.textureBuffer.canvas; - } - - /** - * @member {boolean} - */ - this.valid = true; - -} - -BaseRenderTexture.prototype = Object.create(BaseTexture.prototype); -BaseRenderTexture.prototype.constructor = BaseRenderTexture; -module.exports = BaseRenderTexture; - -/** - * Resizes the BaseRenderTexture. - * - * @param width {number} The width to resize to. - * @param height {number} The height to resize to. - * @param updateBase {boolean} Should the baseTexture.width and height values be resized as well? - */ -BaseRenderTexture.prototype.resize = function (width, height) -{ - if (width === this.width && height === this.height) - { - return; - } - - this.valid = (width > 0 && height > 0); - - this.width = width; - this.height = height; - - if (!this.valid) - { - return; - } - - this.textureBuffer.resize(this.width, this.height); - - if(this.filterManager) - { - this.filterManager.resize(this.width, this.height); - } -}; - -/** - * Clears the BaseRenderTexture. - * - */ -BaseRenderTexture.prototype.clear = function (destinationFrame) -{ - if (!this.valid) - { - return; - } - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - this.renderer.gl.bindFramebuffer(this.renderer.gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - } - - this.textureBuffer.clear(false, destinationFrame); -}; - -/** - * Internal method assigned to the `render` property if using a CanvasRenderer. - * - * @private - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear=false] {boolean} If true the texture will be cleared before the displayObject is drawn - * @param [updateTransform=true] {boolean} If true the displayObject's worldTransform/worldAlpha and all children - * transformations will be restored. Not restoring this information will be a little faster. - */ -BaseRenderTexture.prototype.renderWebGL = function (frame, displayObject, matrix, clear, updateTransform) -{ - if (!this.valid) - { - return; - } - - - updateTransform = (updateTransform !== undefined) ? updateTransform : true;//!updateTransform; - - this.textureBuffer.transform = matrix; - - //TODO not a fan that this is here... it will move! - this.textureBuffer.activate(); - - // setWorld Alpha to ensure that the object is renderer at full opacity - displayObject.worldAlpha = 1; - - if (updateTransform) - { - - // reset the matrix of the displatyObject.. - displayObject.worldTransform.identity(); - - displayObject.currentBounds = null; - - // Time to update all the children of the displayObject with the new matrix.. - var children = displayObject.children; - var i, j; - - for (i = 0, j = children.length; i < j; ++i) - { - children[i].updateTransform(); - } - } - - tempRect.width = frame.height; - tempRect.height = frame.width; - - //TODO rename textureBuffer to renderTarget.. - var temp = this.renderer.filterManager; - - this.renderer.filterManager = this.filterManager; - - - this.textureBuffer.activate(frame, tempRect); - console.log(displayObject) - this.renderer.renderDisplayObject(displayObject, this.textureBuffer, clear); - - // console.log("RENDERING "); - this.renderer.filterManager = temp; -}; - - -/** - * Internal method assigned to the `render` property if using a CanvasRenderer. - * - * @private - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear] {boolean} If true the texture will be cleared before the displayObject is drawn - */ -BaseRenderTexture.prototype.renderCanvas = function (frame, displayObject, matrix, clear, updateTransform) -{ - if (!this.valid) - { - return; - } - - updateTransform = !!updateTransform; - - var wt = tempMatrix; - - wt.identity(); - - if (matrix) - { - wt.append(matrix); - } - - - wt.tx += frame.x; - wt.ty += frame.y; - - var cachedWt = displayObject.worldTransform; - - displayObject.worldTransform = wt; - - // setWorld Alpha to ensure that the object is renderer at full opacity - displayObject.worldAlpha = 1; - - // Time to update all the children of the displayObject with the new matrix.. - var children = displayObject.children; - var i, j; - - for (i = 0, j = children.length; i < j; ++i) - { - children[i].updateTransform(); - } - - if (clear) - { - this.textureBuffer.clear(); - } - - -// this.textureBuffer. - var context = this.textureBuffer.context; - - var realResolution = this.renderer.resolution; - - this.renderer.resolution = this.resolution; - - this.renderer.renderDisplayObject(displayObject, context); - - this.renderer.resolution = realResolution; - - if(displayObject.worldTransform === wt) - { - // fixes cacheAsBitmap Happening during the above.. - displayObject.worldTransform = cachedWt; - } - -}; - -/** - * Destroys this texture - * - * @param destroyBase {boolean} Whether to destroy the base texture as well - */ -BaseRenderTexture.prototype.destroy = function () -{ - Texture.prototype.destroy.call(this, true); - - this.textureBuffer.destroy(); - - // destroy the filtermanager.. - if(this.filterManager) - { - this.filterManager.destroy(); - } - - this.renderer = null; -}; - -/** - * Will return a HTML Image of the texture - * - * @return {Image} - */ -BaseRenderTexture.prototype.getImage = function (frame) -{ - var image = new Image(); - image.src = this.getBase64(frame); - return image; -}; - -/** - * Will return a a base64 encoded string of this texture. It works by calling BaseRenderTexture.getCanvas and then running toDataURL on that. - * - * @return {string} A base64 encoded string of the texture. - */ -BaseRenderTexture.prototype.getBase64 = function ( frame ) -{ - return this.getCanvas(frame).toDataURL(); -}; - -/** - * Creates a Canvas element, renders this BaseRenderTexture to it and then returns it. - * - * @return {HTMLCanvasElement} A Canvas element with the texture rendered on. - */ -BaseRenderTexture.prototype.getCanvas = function ( frame ) -{ - - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.size.width; - frame.height = this.textureBuffer.size.height; - } - - var width = frame.width * this.resolution; - var height = frame.height * this.resolution; - - var gl = this.renderer.gl; - - var webGLPixels = new Uint8Array(4 * width * height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - gl.readPixels(frame.x * this.resolution, frame.y * this.resolution, width, height, gl.RGBA, gl.UNSIGNED_BYTE, webGLPixels); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - var tempCanvas = new CanvasBuffer(width, height); - var canvasData = tempCanvas.context.getImageData(0, 0, width, height); - canvasData.data.set(webGLPixels); - - tempCanvas.context.putImageData(canvasData, 0, 0); - - return tempCanvas.canvas; - } - else - { - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.canvas.width; - frame.height = this.textureBuffer.canvas.height; - } - - if(frame.width === this.textureBuffer.canvas.width && - frame.height === this.textureBuffer.canvas.height ) - { - return this.textureBuffer.canvas; - } - else - { - - var resolution = this.resolution; - - var tempCanvas = new CanvasBuffer(frame.width * resolution, frame.height * resolution); - var canvasData = this.textureBuffer.context.getImageData(frame.x * resolution, frame.y * resolution, frame.width * resolution, frame.height * resolution); - - tempCanvas.context.putImageData(canvasData, 0, 0); - - return tempCanvas.canvas; - } - } -}; - -/** - * Will return a one-dimensional array containing the pixel data of the entire texture in RGBA order, with integer values between 0 and 255 (included). - * - * @return {Uint8ClampedArray} - */ -BaseRenderTexture.prototype.getPixels = function ( frame ) -{ - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.size.width; - frame.height = this.textureBuffer.size.height; - } - - var width = frame.width * this.resolution; - var height = frame.height * this.resolution; - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - var gl = this.renderer.gl; - - var webGLPixels = new Uint8Array(4 * width * height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - gl.readPixels(frame.x * this.resolution, frame.y * this.resolution, width, height, gl.RGBA, gl.UNSIGNED_BYTE, webGLPixels); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - return webGLPixels; - } - else - { - return this.textureBuffer.canvas.getContext('2d').getImageData(frame.x * this.resolution, frame.y * this.resolution, width, height).data; - } -}; - -/** - * Will return a one-dimensional array containing the pixel data of a pixel within the texture in RGBA order, with integer values between 0 and 255 (included). - * - * @param x {number} The x coordinate of the pixel to retrieve. - * @param y {number} The y coordinate of the pixel to retrieve. - * @return {Uint8ClampedArray} - */ -BaseRenderTexture.prototype.getPixel = function (frame, x, y) -{ - tempRect.x = x; - tempRect.y = y; - tempRect.width = 1 / this.resolution; - tempRect.height = 1 / this.resolution; - - if(frame) - { - tempRect.x += frame.x; - tempRect.y += frame.y; - } - - return this.getPixels(tempRect); -}; diff --git a/src/filters/blur/BlurFilter.js b/src/filters/blur/BlurFilter.js new file mode 100644 index 0000000..fb708a1 --- /dev/null +++ b/src/filters/blur/BlurFilter.js @@ -0,0 +1,114 @@ +var core = require('../../core'), + BlurXFilter = require('./BlurXFilter'), + BlurYFilter = require('./BlurYFilter'); + +/** + * The BlurFilter applies a Gaussian blur to an object. + * The strength of the blur can be set for x- and y-axis separately. + * + * @class + * @extends PIXI.Filter + * @memberof PIXI.filters + */ +function BlurFilter() +{ + core.Filter.call(this); + + this.blurXFilter = new BlurXFilter(); + this.blurYFilter = new BlurYFilter(); + this.resolution = 0.25;//0.25;//0.25//1//01.26; + this.blurYFilter.passes = this.blurXFilter.passes = 2; + this.blurYFilter.strength = this.blurXFilter.strength = 4;//4// 4 + + this.padding = 100 + +} + +BlurFilter.prototype = Object.create(core.Filter.prototype); +BlurFilter.prototype.constructor = BlurFilter; +module.exports = BlurFilter; + +BlurFilter.prototype.apply = function (filterManager, input, output) +{ + var renderTarget = filterManager.getRenderTarget(true); + + this.blurXFilter.apply(filterManager, input, renderTarget, true); + this.blurYFilter.apply(filterManager, renderTarget, output); + + filterManager.returnRenderTarget(renderTarget); +}; + +Object.defineProperties(BlurFilter.prototype, { + /** + * Sets the strength of both the blurX and blurY properties simultaneously + * + * @member {number} + * @memberOf PIXI.filters.BlurFilter# + * @default 2 + */ + blur: { + get: function () + { + return this.blurXFilter.blur; + }, + set: function (value) + { + this.padding = Math.abs(value) * 0.5; + this.blurXFilter.blur = this.blurYFilter.blur = value; + } + }, + + /** + * Sets the number of passes for blur. More passes means higher quaility bluring. + * + * @member {number} + * @memberof PIXI.filters.BlurYFilter# + * @default 1 + */ + passes: { + get: function () + { + return this.blurXFilter.passes; + }, + set: function (value) + { + this.blurXFilter.passes = this.blurYFilter.passes = value; + } + }, + + /** + * Sets the strength of the blurX property + * + * @member {number} + * @memberOf PIXI.filters.BlurFilter# + * @default 2 + */ + blurX: { + get: function () + { + return this.blurXFilter.blur; + }, + set: function (value) + { + this.blurXFilter.blur = value; + } + }, + + /** + * Sets the strength of the blurY property + * + * @member {number} + * @memberOf PIXI.filters.BlurFilter# + * @default 2 + */ + blurY: { + get: function () + { + return this.blurYFilter.blur; + }, + set: function (value) + { + this.blurYFilter.blur = value; + } + } +}); diff --git a/src/filters/blur/BlurXFilter.js b/src/filters/blur/BlurXFilter.js new file mode 100644 index 0000000..61eed96 --- /dev/null +++ b/src/filters/blur/BlurXFilter.js @@ -0,0 +1,94 @@ +var core = require('../../core'); +var glslify = require('glslify'); +var generateBlurVertSource = require('./generateBlurVertSource'); +var generateBlurFragSource = require('./generateBlurFragSource'); + +/** + * The BlurXFilter applies a horizontal Gaussian blur to an object. + * + * @class + * @extends PIXI.Filter + * @memberof PIXI.filters + */ +function BlurXFilter() +{ + var vertSrc = generateBlurVertSource(11, true); + var fragSrc = generateBlurFragSource(11); + + console.log(vertSrc); + console.log(fragSrc); + + core.Filter.call(this, + // vertex shader + vertSrc, + // fragment shader + fragSrc + ); + + /** + * Sets the number of passes for blur. More passes means higher quaility bluring. + * + * @member {number} + * @default 1 + */ + this.passes = 1; + this.resolution = 1;//0.25;//0.5;//0.1//5; + this.strength = 4; +} + +BlurXFilter.prototype = Object.create(core.Filter.prototype); +BlurXFilter.prototype.constructor = BlurXFilter; +module.exports = BlurXFilter; + +BlurXFilter.prototype.apply = function (filterManager, input, output, clear) +{ + this.uniforms.strength = (1/output.destinationFrame.width) * (output.size.width/input.size.width); /// // * 2 //4//this.strength / 4 / this.passes * (input.frame.width / input.size.width); + + // screen space! + this.uniforms.strength *= this.strength; + if(this.passes === 1) + { + filterManager.applyFilter(this, input, output, clear); + } + else + { + var renderTarget = filterManager.getRenderTarget(true); + var flip = input; + var flop = renderTarget; + + for(var i = 0; i < this.passes-1; i++) + { + filterManager.applyFilter(this, flip, flop, true); + + var temp = flop; + flop = flip; + flip = temp; + } + + filterManager.applyFilter(this, flip, output, clear); + + filterManager.returnRenderTarget(renderTarget); + } +}; + + +Object.defineProperties(BlurXFilter.prototype, { + /** + * Sets the strength of both the blur. + * + * @member {number} + * @memberof PIXI.filters.BlurXFilter# + * @default 2 + */ + blur: { + get: function () + { + return this.strength; + }, + set: function (value) + { + this.padding = Math.abs(value) * 0.5; + this.strength = value; + } + } +}); diff --git a/src/filters/blur/BlurYFilter.js b/src/filters/blur/BlurYFilter.js new file mode 100644 index 0000000..86a3171 --- /dev/null +++ b/src/filters/blur/BlurYFilter.js @@ -0,0 +1,85 @@ +var core = require('../../core'); +var generateBlurVertSource = require('./generateBlurVertSource'); +var generateBlurFragSource = require('./generateBlurFragSource'); + + +/** + * The BlurYFilter applies a horizontal Gaussian blur to an object. + * + * @class + * @extends PIXI.Filter + * @memberof PIXI.filters + */ +function BlurYFilter() +{ + var vertSrc = generateBlurVertSource(11, false); + var fragSrc = generateBlurFragSource(11); + + core.Filter.call(this, + // vertex shader + vertSrc, + // fragment shader + fragSrc + ); + + this.passes = 1; + this.resolution = 1;//0.25;//0.5;//0.1//5; + this.strength = 4; +} + +BlurYFilter.prototype = Object.create(core.Filter.prototype); +BlurYFilter.prototype.constructor = BlurYFilter; +module.exports = BlurYFilter; + +BlurYFilter.prototype.apply = function (filterManager, input, output, clear) +{ + this.uniforms.strength = (1/output.destinationFrame.height) * (output.size.height/input.size.height); /// // * 2 //4//this.strength / 4 / this.passes * (input.frame.width / input.size.width); + + this.uniforms.strength *= this.strength; + + if(this.passes === 1) + { + filterManager.applyFilter(this, input, output, clear); + } + else + { + var renderTarget = filterManager.getRenderTarget(true); + var flip = input; + var flop = renderTarget; + + for(var i = 0; i < this.passes-1; i++) + { + filterManager.applyFilter(this, flip, flop, true); + + var temp = flop; + flop = flip; + flip = temp; + } + + filterManager.applyFilter(this, flip, output, clear); + + filterManager.returnRenderTarget(renderTarget); + } +}; + + +Object.defineProperties(BlurYFilter.prototype, { + /** + * Sets the strength of both the blur. + * + * @member {number} + * @memberof PIXI.filters.BlurYFilter# + * @default 2 + */ + blur: { + get: function () + { + return this.strength; + }, + set: function (value) + { + this.padding = Math.abs(value) * 0.5; + this.strength = value; + } + } +}); diff --git a/src/filters/blur/blur.frag b/src/filters/blur/blur.frag new file mode 100644 index 0000000..0c4f23c --- /dev/null +++ b/src/filters/blur/blur.frag @@ -0,0 +1,31 @@ +precision mediump float; + +varying vec2 vTextureCoord; +varying vec2 vBlurTexCoords[15]; + +uniform sampler2D uSampler; + +void main(void) +{ + gl_FragColor = vec4(0.0); + + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 0]) * 0.000489; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 1]) * 0.002403; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 2]) * 0.009246; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 3]) * 0.02784; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 4]) * 0.065602; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 5]) * 0.120999; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 6]) * 0.174697; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 7]) * 0.197448; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 8]) * 0.174697; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 9]) * 0.120999; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 10]) * 0.065602; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 11]) * 0.02784; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 12]) * 0.009246; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 13]) * 0.002403; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 14]) * 0.000489; + + + + +} diff --git a/src/filters/blur/blurX.vert b/src/filters/blur/blurX.vert new file mode 100644 index 0000000..cc0e22b --- /dev/null +++ b/src/filters/blur/blurX.vert @@ -0,0 +1,31 @@ +attribute vec2 aVertexPosition; +attribute vec2 aTextureCoord; + +uniform float strength; +uniform mat3 projectionMatrix; + +varying vec2 vTextureCoord; +varying vec2 vBlurTexCoords[15]; + +void main(void) +{ + gl_Position = vec4((projectionMatrix * vec3((aVertexPosition), 1.0)).xy, 0.0, 1.0); + vTextureCoord = aTextureCoord; + + vBlurTexCoords[ 0] = aTextureCoord + vec2(-7.0 * strength, 0.0); + vBlurTexCoords[ 1] = aTextureCoord + vec2(-6.0 * strength, 0.0); + vBlurTexCoords[ 2] = aTextureCoord + vec2(-5.0 * strength, 0.0); + vBlurTexCoords[ 3] = aTextureCoord + vec2(-4.0 * strength, 0.0); + vBlurTexCoords[ 4] = aTextureCoord + vec2(-3.0 * strength, 0.0); + vBlurTexCoords[ 5] = aTextureCoord + vec2(-2.0 * strength, 0.0); + vBlurTexCoords[ 6] = aTextureCoord + vec2(-1.0 * strength, 0.0); + vBlurTexCoords[ 7] = aTextureCoord; + vBlurTexCoords[ 8] = aTextureCoord + vec2(1.0 * strength, 0.0); + vBlurTexCoords[ 9] = aTextureCoord + vec2(2.0 * strength, 0.0); + vBlurTexCoords[ 10] = aTextureCoord + vec2(3.0 * strength, 0.0); + vBlurTexCoords[ 11] = aTextureCoord + vec2(4.0 * strength, 0.0); + vBlurTexCoords[ 12] = aTextureCoord + vec2(5.0 * strength, 0.0); + vBlurTexCoords[ 13] = aTextureCoord + vec2(6.0 * strength, 0.0); + vBlurTexCoords[ 14] = aTextureCoord + vec2(7.0 * strength, 0.0); + +} diff --git a/src/filters/blur/blurY.vert b/src/filters/blur/blurY.vert new file mode 100644 index 0000000..f1616f7 --- /dev/null +++ b/src/filters/blur/blurY.vert @@ -0,0 +1,32 @@ +attribute vec2 aVertexPosition; +attribute vec2 aTextureCoord; + +uniform float strength; +uniform mat3 projectionMatrix; + +varying vec2 vTextureCoord; +varying vec2 vBlurTexCoords[15]; + +void main(void) +{ + gl_Position = vec4((projectionMatrix * vec3((aVertexPosition), 1.0)).xy, 0.0, 1.0); + vTextureCoord = aTextureCoord; + + vBlurTexCoords[ 0] = aTextureCoord + vec2(0.0, -7.0 * strength); + vBlurTexCoords[ 1] = aTextureCoord + vec2(0.0, -6.0 * strength); + vBlurTexCoords[ 2] = aTextureCoord + vec2(0.0, -5.0 * strength); + vBlurTexCoords[ 3] = aTextureCoord + vec2(0.0, -4.0 * strength); + vBlurTexCoords[ 4] = aTextureCoord + vec2(0.0, -3.0 * strength); + vBlurTexCoords[ 5] = aTextureCoord + vec2(0.0, -2.0 * strength); + vBlurTexCoords[ 6] = aTextureCoord + vec2(0.0, -1.0 * strength); + vBlurTexCoords[ 7] = aTextureCoord; + vBlurTexCoords[ 8] = aTextureCoord + vec2(0.0, 1.0 * strength); + vBlurTexCoords[ 9] = aTextureCoord + vec2(0.0, 2.0 * strength); + vBlurTexCoords[ 10] = aTextureCoord + vec2(0.0, 3.0 * strength); + vBlurTexCoords[ 11] = aTextureCoord + vec2(0.0, 4.0 * strength); + vBlurTexCoords[ 12] = aTextureCoord + vec2(0.0, 5.0 * strength); + vBlurTexCoords[ 13] = aTextureCoord + vec2(0.0, 6.0 * strength); + vBlurTexCoords[ 14] = aTextureCoord + vec2(0.0, 7.0 * strength); + + +} diff --git a/src/filters/blur/generateBlurFragSource.js b/src/filters/blur/generateBlurFragSource.js new file mode 100644 index 0000000..59cf930 --- /dev/null +++ b/src/filters/blur/generateBlurFragSource.js @@ -0,0 +1,63 @@ +var core = require('../../core') + +var GAUSSIAN_VALUES = { + 5:[0.06136, 0.24477, 0.38774], + 7:[0.00598, 0.060626, 0.241843, 0.383103], + 9:[0.000229, 0.005977, 0.060598, 0.241732, 0.382928], + 11:[0.000003, 0.000229, 0.005977, 0.060598, 0.24173, 0.382925], + 13:[0.0, 0.000003, 0.000229, 0.005977, 0.060598, 0.24173, 0.382925], + 15:[0.0, 0.0, 0.000003, 0.000229, 0.005977, 0.060598, 0.24173, 0.382925] +} + +var generateFragBlurSource = function(kernelSize) +{ + var kernel = GAUSSIAN_VALUES[kernelSize]; + var halfLength = kernel.length; + + var fragSource = fragTemplate; + + var blurLoop = ''; + var template = 'gl_FragColor += texture2D(uSampler, vBlurTexCoords[%index%]) * %value%;' + + for (var i = 0; i < kernelSize; i++) + { + var blur = template.replace('%index%', i); + + value = i; + + if(i >= halfLength) + { + value = kernelSize - i - 1; + } + + + blur = blur.replace('%value%', kernel[value]); + + blurLoop += blur; + blurLoop += '\n'; + }; + + fragSource = fragSource.replace('%blur%', blurLoop) + fragSource = fragSource.replace('%size%', kernelSize) + + + return fragSource; +} + +var fragTemplate = [ + + 'precision mediump float;', + + 'varying vec2 vTextureCoord;', + 'varying vec2 vBlurTexCoords[%size%];', + 'uniform sampler2D uSampler;', + + 'void main(void)', + '{', + ' gl_FragColor = vec4(0.0);', + ' %blur%', + '}' + +].join('\n'); + +module.exports = generateFragBlurSource; \ No newline at end of file diff --git a/src/filters/blur/generateBlurVertSource.js b/src/filters/blur/generateBlurVertSource.js new file mode 100644 index 0000000..7096810 --- /dev/null +++ b/src/filters/blur/generateBlurVertSource.js @@ -0,0 +1,64 @@ + +var generateVertBlurSource = function(kernelSize, x) +{ + var halfLength = Math.ceil(kernelSize/2); + + var vertSource = vertTemplate; + + var blurLoop = ''; + var template + + if(x) + { + template = 'vBlurTexCoords[%index%] = aTextureCoord + vec2(%samlpeIndex% * strength, 0.0);' + } + else + { + template = 'vBlurTexCoords[%index%] = aTextureCoord + vec2(0.0, %samlpeIndex% * strength);' + + } + + + for (var i = 0; i < kernelSize; i++) + { + var blur = template.replace('%index%', i); + + value = i; + + if(i >= halfLength) + { + value = kernelSize - i - 1; + } + + blur = blur.replace('%samlpeIndex%', (i - (halfLength-1)) + ".0"); + + blurLoop += blur; + blurLoop += '\n'; + }; + + vertSource = vertSource.replace('%blur%', blurLoop) + vertSource = vertSource.replace('%size%', kernelSize) + + return vertSource; +} + +var vertTemplate = [ + + 'attribute vec2 aVertexPosition;', + 'attribute vec2 aTextureCoord;', + + 'uniform float strength;', + 'uniform mat3 projectionMatrix;', + + 'varying vec2 vTextureCoord;', + 'varying vec2 vBlurTexCoords[%size%];', + + 'void main(void)', + '{', + 'gl_Position = vec4((projectionMatrix * vec3((aVertexPosition), 1.0)).xy, 0.0, 1.0);', + 'vTextureCoord = aTextureCoord;',//TODO remove.. + '%blur%', + '}' +].join('\n'); + +module.exports = generateVertBlurSource; \ No newline at end of file diff --git a/package.json b/package.json index 4436b84..48a074c 100644 --- a/package.json +++ b/package.json @@ -32,10 +32,8 @@ "dependencies": { "async": "^1.5.0", "bit-twiddle": "^1.0.2", - "brfs": "^1.4.1", "earcut": "^2.0.7", "eventemitter3": "^1.1.1", - "gl-matrix": "git+https://github.com/toji/gl-matrix.git", "object-assign": "^4.0.1", "pixi-gl-core": "git+https://github.com/GoodBoyDigital/pixi-gl-core.git", "resource-loader": "^1.6.4" @@ -73,6 +71,5 @@ "transform": [ "glslify" ] - } } diff --git a/src/core/graphics/webgl/PrimitiveShader.js b/src/core/graphics/webgl/PrimitiveShader.js deleted file mode 100644 index 44166b3..0000000 --- a/src/core/graphics/webgl/PrimitiveShader.js +++ /dev/null @@ -1,50 +0,0 @@ -var Shader = require('pixi-gl-core').GLShader; - -/** - * This shader is used to draw simple primitive shapes for {@link PIXI.Graphics}. - * - * @class - * @memberof PIXI - * @extends PIXI.Shader - * @param shaderManager {ShaderManager} The webgl shader manager this shader works for. - */ -function PrimitiveShader(gl) -{ - Shader.call(this, - gl, - // vertex shader - [ - 'attribute vec2 aVertexPosition;', - 'attribute vec4 aColor;', - - 'uniform mat3 translationMatrix;', - 'uniform mat3 projectionMatrix;', - - 'uniform float alpha;', - 'uniform float flipY;', - 'uniform vec3 tint;', - - 'varying vec4 vColor;', - - 'void main(void){', - ' gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', - ' vColor = aColor * vec4(tint * alpha, alpha);', - '}' - ].join('\n'), - // fragment shader - [ - 'precision mediump float;', - - 'varying vec4 vColor;', - - 'void main(void){', - ' gl_FragColor = vColor;', - '}' - ].join('\n') - ); -} - -PrimitiveShader.prototype = Object.create(Shader.prototype); -PrimitiveShader.prototype.constructor = PrimitiveShader; - -module.exports = PrimitiveShader; diff --git a/src/core/math/Matrix.js b/src/core/math/Matrix.js index 4e7fe99..2313ae3 100644 --- a/src/core/math/Matrix.js +++ b/src/core/math/Matrix.js @@ -51,6 +51,7 @@ * @default 0 */ this.ty = 0; + } Matrix.prototype.constructor = Matrix; diff --git a/src/core/renderers/webgl/managers/FilterManager.js b/src/core/renderers/webgl/managers/FilterManager.js index b3f7463..5fc6562 100644 --- a/src/core/renderers/webgl/managers/FilterManager.js +++ b/src/core/renderers/webgl/managers/FilterManager.js @@ -64,11 +64,12 @@ - //TODO - should this be rounded to reoultion? not 1? - sourceFrame.x = targetBounds.x | 0; - sourceFrame.y = targetBounds.y | 0; - sourceFrame.width = targetBounds.width | 0; - sourceFrame.height = targetBounds.height | 0; + + sourceFrame.x = ((targetBounds.x * resolution) | 0) / resolution; + sourceFrame.y = ((targetBounds.y * resolution) | 0) / resolution; + sourceFrame.width = ((targetBounds.width * resolution) | 0) / resolution; + sourceFrame.height = ((targetBounds.height * resolution) | 0) / resolution; + sourceFrame.pad(padding * resolution); sourceFrame.fit(this.stack[0].destinationFrame); @@ -79,6 +80,7 @@ currentState.target = target; currentState.filters = filters; + currentState.resolution = resolution; currentState.renderTarget = renderTarget; // bind the render taget to draw the shape in the top corner.. @@ -236,6 +238,13 @@ shader.uniforms[i] = uniforms[i]; } } + else if(uniformData[i].type === 'float') + { + if(shader.uniforms.data[i].value !== uniformData[i]) + { + shader.uniforms[i] = uniforms[i]; + } + } else { shader.uniforms[i] = uniforms[i]; @@ -244,10 +253,18 @@ } -FilterManager.prototype.getPotRenderTarget = function() +FilterManager.prototype.getRenderTarget = function() { var currentState = this.stack[this.stackIndex]; - return FilterManager.getPotRenderTarget(renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, 1); + var renderTarget = FilterManager.getPotRenderTarget(renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, currentState.resolution); + renderTarget.setFrame(currentState.destinationFrame, currentState.sourceFrame); + + return renderTarget; +} + +FilterManager.prototype.returnRenderTarget = function(renderTarget) +{ + return FilterManager.freePotRenderTarget(renderTarget); } /* @@ -325,6 +342,7 @@ this.destinationFrame = new math.Rectangle(); this.filters = []; this.target = null; + this.resolution = 1; } FilterManager.pool = {} diff --git a/src/core/renderers/webgl/utils/RenderTarget.js b/src/core/renderers/webgl/utils/RenderTarget.js index ced94f6..d3daf50 100644 --- a/src/core/renderers/webgl/utils/RenderTarget.js +++ b/src/core/renderers/webgl/utils/RenderTarget.js @@ -136,6 +136,15 @@ { this.frameBuffer = GLFramebuffer.createRGBA(gl, 100, 100); + if( this.scaleMode === CONST.SCALE_MODES.NEAREST) + { + this.frameBuffer.texture.enableNearestScaling() + } + else + { + this.frameBuffer.texture.enableLinearScaling() + + } /* A frame buffer needs a target to render to.. create a texture and bind it attach it to the framebuffer.. @@ -213,8 +222,10 @@ this.projectionMatrix.append(this.transform); } + //TODO add a check as them may be the same! if(this.destinationFrame !== this.sourceFrame) { + gl.enable(gl.SCISSOR_TEST); gl.scissor(this.destinationFrame.x | 0,this.destinationFrame.y | 0, (this.destinationFrame.width * this.resolution) | 0, (this.destinationFrame.height* this.resolution) | 0); } @@ -279,8 +290,6 @@ return; } - console.log(width + " : " + height) - this.size.width = width; this.size.height = height; diff --git a/src/core/textures/BaseRenderTexture copy.js b/src/core/textures/BaseRenderTexture copy.js deleted file mode 100644 index acf6ac9..0000000 --- a/src/core/textures/BaseRenderTexture copy.js +++ /dev/null @@ -1,482 +0,0 @@ -var BaseTexture = require('./BaseTexture'), - Texture = require('./Texture'), - RenderTarget = require('../renderers/webgl/utils/RenderTarget'), - FilterManager = require('../renderers/webgl/managers/FilterManager'), - CanvasBuffer = require('../renderers/canvas/utils/CanvasBuffer'), - math = require('../math'), - CONST = require('../const'), - tempMatrix = new math.Matrix(), - tempRect = new math.Rectangle(); - -/** - * A BaseRenderTexture is a special texture that allows any Pixi display object to be rendered to it. - * - * __Hint__: All DisplayObjects (i.e. Sprites) that render to a BaseRenderTexture should be preloaded - * otherwise black rectangles will be drawn instead. - * - * A BaseRenderTexture takes a snapshot of any Display Object given to its render method. The position - * and rotation of the given Display Objects is ignored. For example: - * - * ```js - * var renderer = PIXI.autoDetectRenderer(1024, 1024, { view: canvas, ratio: 1 }); - * var BaserenderTexture = new PIXI.BaseRenderTexture(renderer, 800, 600); - * var sprite = PIXI.Sprite.fromImage("spinObj_01.png"); - * - * sprite.position.x = 800/2; - * sprite.position.y = 600/2; - * sprite.anchor.x = 0.5; - * sprite.anchor.y = 0.5; - * - * BaserenderTexture.render(sprite); - * ``` - * - * The Sprite in this case will be rendered to a position of 0,0. To render this sprite at its actual - * position a Container should be used: - * - * ```js - * var doc = new PIXI.Container(); - * - * doc.addChild(sprite); - * - * BaserenderTexture.render(doc); // Renders to center of BaserenderTexture - * ``` - * - * @class - * @extends PIXI.Texture - * @memberof PIXI - * @param renderer {PIXI.CanvasRenderer|PIXI.WebGLRenderer} The renderer used for this BaseRenderTexture - * @param [width=100] {number} The width of the render texture - * @param [height=100] {number} The height of the render texture - * @param [scaleMode] {number} See {@link PIXI.SCALE_MODES} for possible values - * @param [resolution=1] {number} The resolution of the texture being generated - */ -function BaseRenderTexture(renderer, width, height, scaleMode, resolution) -{ - if (!renderer) - { - throw new Error('Unable to create BaseRenderTexture, you must pass a renderer into the constructor.'); - } - - BaseTexture.call(this, null, scaleMode); - - this.width = width || 100; - this.height = height || 100; - - this.resolution = resolution || CONST.RESOLUTION;; - this.scaleMode = scaleMode || CONST.SCALE_MODES.DEFAULT; - this.hasLoaded = true; - - /** - * Draw/render the given DisplayObject onto the texture. - * - * The displayObject and descendents are transformed during this operation. - * If `updateTransform` is true then the transformations will be restored before the - * method returns. Otherwise it is up to the calling code to correctly use or reset - * the transformed display objects. - * - * The display object is always rendered with a worldAlpha value of 1. - * - * @method - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear=false] {boolean} If true the texture will be cleared before the displayObject is drawn - * @param [updateTransform=true] {boolean} If true the displayObject's worldTransform/worldAlpha and all children - * transformations will be restored. Not restoring this information will be a little faster. - */ - this.render = null; - - /** - * The renderer this BaseRenderTexture uses. A BaseRenderTexture can only belong to one renderer at the moment if its webGL. - * - * @member {PIXI.CanvasRenderer|PIXI.WebGLRenderer} - */ - this.renderer = renderer; - - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - var gl = this.renderer.gl; - - this.textureBuffer = new RenderTarget(gl, this.width, this.height, this.scaleMode, this.resolution);//, this.this.scaleMode); - this._glTextures[gl.id] = this.textureBuffer.texture; - - //TODO refactor filter manager.. as really its no longer a manager if we use it here.. - this.filterManager = new FilterManager(this.renderer); - this.filterManager.onContextChange(); - this.filterManager.resize(width, height); - this.render = this.renderWebGL; - - // the creation of a filter manager unbinds the buffers.. - this.renderer.currentRenderer.start(); - if(this.renderer._activeRenderTarget)this.renderer._activeRenderTarget.activate(); - } - else - { - - this.render = this.renderCanvas; - this.textureBuffer = new CanvasBuffer(this.width* this.resolution, this.height* this.resolution); - this.source = this.textureBuffer.canvas; - } - - /** - * @member {boolean} - */ - this.valid = true; - -} - -BaseRenderTexture.prototype = Object.create(BaseTexture.prototype); -BaseRenderTexture.prototype.constructor = BaseRenderTexture; -module.exports = BaseRenderTexture; - -/** - * Resizes the BaseRenderTexture. - * - * @param width {number} The width to resize to. - * @param height {number} The height to resize to. - * @param updateBase {boolean} Should the baseTexture.width and height values be resized as well? - */ -BaseRenderTexture.prototype.resize = function (width, height) -{ - if (width === this.width && height === this.height) - { - return; - } - - this.valid = (width > 0 && height > 0); - - this.width = width; - this.height = height; - - if (!this.valid) - { - return; - } - - this.textureBuffer.resize(this.width, this.height); - - if(this.filterManager) - { - this.filterManager.resize(this.width, this.height); - } -}; - -/** - * Clears the BaseRenderTexture. - * - */ -BaseRenderTexture.prototype.clear = function (destinationFrame) -{ - if (!this.valid) - { - return; - } - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - this.renderer.gl.bindFramebuffer(this.renderer.gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - } - - this.textureBuffer.clear(false, destinationFrame); -}; - -/** - * Internal method assigned to the `render` property if using a CanvasRenderer. - * - * @private - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear=false] {boolean} If true the texture will be cleared before the displayObject is drawn - * @param [updateTransform=true] {boolean} If true the displayObject's worldTransform/worldAlpha and all children - * transformations will be restored. Not restoring this information will be a little faster. - */ -BaseRenderTexture.prototype.renderWebGL = function (frame, displayObject, matrix, clear, updateTransform) -{ - if (!this.valid) - { - return; - } - - - updateTransform = (updateTransform !== undefined) ? updateTransform : true;//!updateTransform; - - this.textureBuffer.transform = matrix; - - //TODO not a fan that this is here... it will move! - this.textureBuffer.activate(); - - // setWorld Alpha to ensure that the object is renderer at full opacity - displayObject.worldAlpha = 1; - - if (updateTransform) - { - - // reset the matrix of the displatyObject.. - displayObject.worldTransform.identity(); - - displayObject.currentBounds = null; - - // Time to update all the children of the displayObject with the new matrix.. - var children = displayObject.children; - var i, j; - - for (i = 0, j = children.length; i < j; ++i) - { - children[i].updateTransform(); - } - } - - tempRect.width = frame.height; - tempRect.height = frame.width; - - //TODO rename textureBuffer to renderTarget.. - var temp = this.renderer.filterManager; - - this.renderer.filterManager = this.filterManager; - - - this.textureBuffer.activate(frame, tempRect); - console.log(displayObject) - this.renderer.renderDisplayObject(displayObject, this.textureBuffer, clear); - - // console.log("RENDERING "); - this.renderer.filterManager = temp; -}; - - -/** - * Internal method assigned to the `render` property if using a CanvasRenderer. - * - * @private - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear] {boolean} If true the texture will be cleared before the displayObject is drawn - */ -BaseRenderTexture.prototype.renderCanvas = function (frame, displayObject, matrix, clear, updateTransform) -{ - if (!this.valid) - { - return; - } - - updateTransform = !!updateTransform; - - var wt = tempMatrix; - - wt.identity(); - - if (matrix) - { - wt.append(matrix); - } - - - wt.tx += frame.x; - wt.ty += frame.y; - - var cachedWt = displayObject.worldTransform; - - displayObject.worldTransform = wt; - - // setWorld Alpha to ensure that the object is renderer at full opacity - displayObject.worldAlpha = 1; - - // Time to update all the children of the displayObject with the new matrix.. - var children = displayObject.children; - var i, j; - - for (i = 0, j = children.length; i < j; ++i) - { - children[i].updateTransform(); - } - - if (clear) - { - this.textureBuffer.clear(); - } - - -// this.textureBuffer. - var context = this.textureBuffer.context; - - var realResolution = this.renderer.resolution; - - this.renderer.resolution = this.resolution; - - this.renderer.renderDisplayObject(displayObject, context); - - this.renderer.resolution = realResolution; - - if(displayObject.worldTransform === wt) - { - // fixes cacheAsBitmap Happening during the above.. - displayObject.worldTransform = cachedWt; - } - -}; - -/** - * Destroys this texture - * - * @param destroyBase {boolean} Whether to destroy the base texture as well - */ -BaseRenderTexture.prototype.destroy = function () -{ - Texture.prototype.destroy.call(this, true); - - this.textureBuffer.destroy(); - - // destroy the filtermanager.. - if(this.filterManager) - { - this.filterManager.destroy(); - } - - this.renderer = null; -}; - -/** - * Will return a HTML Image of the texture - * - * @return {Image} - */ -BaseRenderTexture.prototype.getImage = function (frame) -{ - var image = new Image(); - image.src = this.getBase64(frame); - return image; -}; - -/** - * Will return a a base64 encoded string of this texture. It works by calling BaseRenderTexture.getCanvas and then running toDataURL on that. - * - * @return {string} A base64 encoded string of the texture. - */ -BaseRenderTexture.prototype.getBase64 = function ( frame ) -{ - return this.getCanvas(frame).toDataURL(); -}; - -/** - * Creates a Canvas element, renders this BaseRenderTexture to it and then returns it. - * - * @return {HTMLCanvasElement} A Canvas element with the texture rendered on. - */ -BaseRenderTexture.prototype.getCanvas = function ( frame ) -{ - - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.size.width; - frame.height = this.textureBuffer.size.height; - } - - var width = frame.width * this.resolution; - var height = frame.height * this.resolution; - - var gl = this.renderer.gl; - - var webGLPixels = new Uint8Array(4 * width * height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - gl.readPixels(frame.x * this.resolution, frame.y * this.resolution, width, height, gl.RGBA, gl.UNSIGNED_BYTE, webGLPixels); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - var tempCanvas = new CanvasBuffer(width, height); - var canvasData = tempCanvas.context.getImageData(0, 0, width, height); - canvasData.data.set(webGLPixels); - - tempCanvas.context.putImageData(canvasData, 0, 0); - - return tempCanvas.canvas; - } - else - { - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.canvas.width; - frame.height = this.textureBuffer.canvas.height; - } - - if(frame.width === this.textureBuffer.canvas.width && - frame.height === this.textureBuffer.canvas.height ) - { - return this.textureBuffer.canvas; - } - else - { - - var resolution = this.resolution; - - var tempCanvas = new CanvasBuffer(frame.width * resolution, frame.height * resolution); - var canvasData = this.textureBuffer.context.getImageData(frame.x * resolution, frame.y * resolution, frame.width * resolution, frame.height * resolution); - - tempCanvas.context.putImageData(canvasData, 0, 0); - - return tempCanvas.canvas; - } - } -}; - -/** - * Will return a one-dimensional array containing the pixel data of the entire texture in RGBA order, with integer values between 0 and 255 (included). - * - * @return {Uint8ClampedArray} - */ -BaseRenderTexture.prototype.getPixels = function ( frame ) -{ - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.size.width; - frame.height = this.textureBuffer.size.height; - } - - var width = frame.width * this.resolution; - var height = frame.height * this.resolution; - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - var gl = this.renderer.gl; - - var webGLPixels = new Uint8Array(4 * width * height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - gl.readPixels(frame.x * this.resolution, frame.y * this.resolution, width, height, gl.RGBA, gl.UNSIGNED_BYTE, webGLPixels); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - return webGLPixels; - } - else - { - return this.textureBuffer.canvas.getContext('2d').getImageData(frame.x * this.resolution, frame.y * this.resolution, width, height).data; - } -}; - -/** - * Will return a one-dimensional array containing the pixel data of a pixel within the texture in RGBA order, with integer values between 0 and 255 (included). - * - * @param x {number} The x coordinate of the pixel to retrieve. - * @param y {number} The y coordinate of the pixel to retrieve. - * @return {Uint8ClampedArray} - */ -BaseRenderTexture.prototype.getPixel = function (frame, x, y) -{ - tempRect.x = x; - tempRect.y = y; - tempRect.width = 1 / this.resolution; - tempRect.height = 1 / this.resolution; - - if(frame) - { - tempRect.x += frame.x; - tempRect.y += frame.y; - } - - return this.getPixels(tempRect); -}; diff --git a/src/filters/blur/BlurFilter.js b/src/filters/blur/BlurFilter.js new file mode 100644 index 0000000..fb708a1 --- /dev/null +++ b/src/filters/blur/BlurFilter.js @@ -0,0 +1,114 @@ +var core = require('../../core'), + BlurXFilter = require('./BlurXFilter'), + BlurYFilter = require('./BlurYFilter'); + +/** + * The BlurFilter applies a Gaussian blur to an object. + * The strength of the blur can be set for x- and y-axis separately. + * + * @class + * @extends PIXI.Filter + * @memberof PIXI.filters + */ +function BlurFilter() +{ + core.Filter.call(this); + + this.blurXFilter = new BlurXFilter(); + this.blurYFilter = new BlurYFilter(); + this.resolution = 0.25;//0.25;//0.25//1//01.26; + this.blurYFilter.passes = this.blurXFilter.passes = 2; + this.blurYFilter.strength = this.blurXFilter.strength = 4;//4// 4 + + this.padding = 100 + +} + +BlurFilter.prototype = Object.create(core.Filter.prototype); +BlurFilter.prototype.constructor = BlurFilter; +module.exports = BlurFilter; + +BlurFilter.prototype.apply = function (filterManager, input, output) +{ + var renderTarget = filterManager.getRenderTarget(true); + + this.blurXFilter.apply(filterManager, input, renderTarget, true); + this.blurYFilter.apply(filterManager, renderTarget, output); + + filterManager.returnRenderTarget(renderTarget); +}; + +Object.defineProperties(BlurFilter.prototype, { + /** + * Sets the strength of both the blurX and blurY properties simultaneously + * + * @member {number} + * @memberOf PIXI.filters.BlurFilter# + * @default 2 + */ + blur: { + get: function () + { + return this.blurXFilter.blur; + }, + set: function (value) + { + this.padding = Math.abs(value) * 0.5; + this.blurXFilter.blur = this.blurYFilter.blur = value; + } + }, + + /** + * Sets the number of passes for blur. More passes means higher quaility bluring. + * + * @member {number} + * @memberof PIXI.filters.BlurYFilter# + * @default 1 + */ + passes: { + get: function () + { + return this.blurXFilter.passes; + }, + set: function (value) + { + this.blurXFilter.passes = this.blurYFilter.passes = value; + } + }, + + /** + * Sets the strength of the blurX property + * + * @member {number} + * @memberOf PIXI.filters.BlurFilter# + * @default 2 + */ + blurX: { + get: function () + { + return this.blurXFilter.blur; + }, + set: function (value) + { + this.blurXFilter.blur = value; + } + }, + + /** + * Sets the strength of the blurY property + * + * @member {number} + * @memberOf PIXI.filters.BlurFilter# + * @default 2 + */ + blurY: { + get: function () + { + return this.blurYFilter.blur; + }, + set: function (value) + { + this.blurYFilter.blur = value; + } + } +}); diff --git a/src/filters/blur/BlurXFilter.js b/src/filters/blur/BlurXFilter.js new file mode 100644 index 0000000..61eed96 --- /dev/null +++ b/src/filters/blur/BlurXFilter.js @@ -0,0 +1,94 @@ +var core = require('../../core'); +var glslify = require('glslify'); +var generateBlurVertSource = require('./generateBlurVertSource'); +var generateBlurFragSource = require('./generateBlurFragSource'); + +/** + * The BlurXFilter applies a horizontal Gaussian blur to an object. + * + * @class + * @extends PIXI.Filter + * @memberof PIXI.filters + */ +function BlurXFilter() +{ + var vertSrc = generateBlurVertSource(11, true); + var fragSrc = generateBlurFragSource(11); + + console.log(vertSrc); + console.log(fragSrc); + + core.Filter.call(this, + // vertex shader + vertSrc, + // fragment shader + fragSrc + ); + + /** + * Sets the number of passes for blur. More passes means higher quaility bluring. + * + * @member {number} + * @default 1 + */ + this.passes = 1; + this.resolution = 1;//0.25;//0.5;//0.1//5; + this.strength = 4; +} + +BlurXFilter.prototype = Object.create(core.Filter.prototype); +BlurXFilter.prototype.constructor = BlurXFilter; +module.exports = BlurXFilter; + +BlurXFilter.prototype.apply = function (filterManager, input, output, clear) +{ + this.uniforms.strength = (1/output.destinationFrame.width) * (output.size.width/input.size.width); /// // * 2 //4//this.strength / 4 / this.passes * (input.frame.width / input.size.width); + + // screen space! + this.uniforms.strength *= this.strength; + if(this.passes === 1) + { + filterManager.applyFilter(this, input, output, clear); + } + else + { + var renderTarget = filterManager.getRenderTarget(true); + var flip = input; + var flop = renderTarget; + + for(var i = 0; i < this.passes-1; i++) + { + filterManager.applyFilter(this, flip, flop, true); + + var temp = flop; + flop = flip; + flip = temp; + } + + filterManager.applyFilter(this, flip, output, clear); + + filterManager.returnRenderTarget(renderTarget); + } +}; + + +Object.defineProperties(BlurXFilter.prototype, { + /** + * Sets the strength of both the blur. + * + * @member {number} + * @memberof PIXI.filters.BlurXFilter# + * @default 2 + */ + blur: { + get: function () + { + return this.strength; + }, + set: function (value) + { + this.padding = Math.abs(value) * 0.5; + this.strength = value; + } + } +}); diff --git a/src/filters/blur/BlurYFilter.js b/src/filters/blur/BlurYFilter.js new file mode 100644 index 0000000..86a3171 --- /dev/null +++ b/src/filters/blur/BlurYFilter.js @@ -0,0 +1,85 @@ +var core = require('../../core'); +var generateBlurVertSource = require('./generateBlurVertSource'); +var generateBlurFragSource = require('./generateBlurFragSource'); + + +/** + * The BlurYFilter applies a horizontal Gaussian blur to an object. + * + * @class + * @extends PIXI.Filter + * @memberof PIXI.filters + */ +function BlurYFilter() +{ + var vertSrc = generateBlurVertSource(11, false); + var fragSrc = generateBlurFragSource(11); + + core.Filter.call(this, + // vertex shader + vertSrc, + // fragment shader + fragSrc + ); + + this.passes = 1; + this.resolution = 1;//0.25;//0.5;//0.1//5; + this.strength = 4; +} + +BlurYFilter.prototype = Object.create(core.Filter.prototype); +BlurYFilter.prototype.constructor = BlurYFilter; +module.exports = BlurYFilter; + +BlurYFilter.prototype.apply = function (filterManager, input, output, clear) +{ + this.uniforms.strength = (1/output.destinationFrame.height) * (output.size.height/input.size.height); /// // * 2 //4//this.strength / 4 / this.passes * (input.frame.width / input.size.width); + + this.uniforms.strength *= this.strength; + + if(this.passes === 1) + { + filterManager.applyFilter(this, input, output, clear); + } + else + { + var renderTarget = filterManager.getRenderTarget(true); + var flip = input; + var flop = renderTarget; + + for(var i = 0; i < this.passes-1; i++) + { + filterManager.applyFilter(this, flip, flop, true); + + var temp = flop; + flop = flip; + flip = temp; + } + + filterManager.applyFilter(this, flip, output, clear); + + filterManager.returnRenderTarget(renderTarget); + } +}; + + +Object.defineProperties(BlurYFilter.prototype, { + /** + * Sets the strength of both the blur. + * + * @member {number} + * @memberof PIXI.filters.BlurYFilter# + * @default 2 + */ + blur: { + get: function () + { + return this.strength; + }, + set: function (value) + { + this.padding = Math.abs(value) * 0.5; + this.strength = value; + } + } +}); diff --git a/src/filters/blur/blur.frag b/src/filters/blur/blur.frag new file mode 100644 index 0000000..0c4f23c --- /dev/null +++ b/src/filters/blur/blur.frag @@ -0,0 +1,31 @@ +precision mediump float; + +varying vec2 vTextureCoord; +varying vec2 vBlurTexCoords[15]; + +uniform sampler2D uSampler; + +void main(void) +{ + gl_FragColor = vec4(0.0); + + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 0]) * 0.000489; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 1]) * 0.002403; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 2]) * 0.009246; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 3]) * 0.02784; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 4]) * 0.065602; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 5]) * 0.120999; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 6]) * 0.174697; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 7]) * 0.197448; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 8]) * 0.174697; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 9]) * 0.120999; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 10]) * 0.065602; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 11]) * 0.02784; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 12]) * 0.009246; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 13]) * 0.002403; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 14]) * 0.000489; + + + + +} diff --git a/src/filters/blur/blurX.vert b/src/filters/blur/blurX.vert new file mode 100644 index 0000000..cc0e22b --- /dev/null +++ b/src/filters/blur/blurX.vert @@ -0,0 +1,31 @@ +attribute vec2 aVertexPosition; +attribute vec2 aTextureCoord; + +uniform float strength; +uniform mat3 projectionMatrix; + +varying vec2 vTextureCoord; +varying vec2 vBlurTexCoords[15]; + +void main(void) +{ + gl_Position = vec4((projectionMatrix * vec3((aVertexPosition), 1.0)).xy, 0.0, 1.0); + vTextureCoord = aTextureCoord; + + vBlurTexCoords[ 0] = aTextureCoord + vec2(-7.0 * strength, 0.0); + vBlurTexCoords[ 1] = aTextureCoord + vec2(-6.0 * strength, 0.0); + vBlurTexCoords[ 2] = aTextureCoord + vec2(-5.0 * strength, 0.0); + vBlurTexCoords[ 3] = aTextureCoord + vec2(-4.0 * strength, 0.0); + vBlurTexCoords[ 4] = aTextureCoord + vec2(-3.0 * strength, 0.0); + vBlurTexCoords[ 5] = aTextureCoord + vec2(-2.0 * strength, 0.0); + vBlurTexCoords[ 6] = aTextureCoord + vec2(-1.0 * strength, 0.0); + vBlurTexCoords[ 7] = aTextureCoord; + vBlurTexCoords[ 8] = aTextureCoord + vec2(1.0 * strength, 0.0); + vBlurTexCoords[ 9] = aTextureCoord + vec2(2.0 * strength, 0.0); + vBlurTexCoords[ 10] = aTextureCoord + vec2(3.0 * strength, 0.0); + vBlurTexCoords[ 11] = aTextureCoord + vec2(4.0 * strength, 0.0); + vBlurTexCoords[ 12] = aTextureCoord + vec2(5.0 * strength, 0.0); + vBlurTexCoords[ 13] = aTextureCoord + vec2(6.0 * strength, 0.0); + vBlurTexCoords[ 14] = aTextureCoord + vec2(7.0 * strength, 0.0); + +} diff --git a/src/filters/blur/blurY.vert b/src/filters/blur/blurY.vert new file mode 100644 index 0000000..f1616f7 --- /dev/null +++ b/src/filters/blur/blurY.vert @@ -0,0 +1,32 @@ +attribute vec2 aVertexPosition; +attribute vec2 aTextureCoord; + +uniform float strength; +uniform mat3 projectionMatrix; + +varying vec2 vTextureCoord; +varying vec2 vBlurTexCoords[15]; + +void main(void) +{ + gl_Position = vec4((projectionMatrix * vec3((aVertexPosition), 1.0)).xy, 0.0, 1.0); + vTextureCoord = aTextureCoord; + + vBlurTexCoords[ 0] = aTextureCoord + vec2(0.0, -7.0 * strength); + vBlurTexCoords[ 1] = aTextureCoord + vec2(0.0, -6.0 * strength); + vBlurTexCoords[ 2] = aTextureCoord + vec2(0.0, -5.0 * strength); + vBlurTexCoords[ 3] = aTextureCoord + vec2(0.0, -4.0 * strength); + vBlurTexCoords[ 4] = aTextureCoord + vec2(0.0, -3.0 * strength); + vBlurTexCoords[ 5] = aTextureCoord + vec2(0.0, -2.0 * strength); + vBlurTexCoords[ 6] = aTextureCoord + vec2(0.0, -1.0 * strength); + vBlurTexCoords[ 7] = aTextureCoord; + vBlurTexCoords[ 8] = aTextureCoord + vec2(0.0, 1.0 * strength); + vBlurTexCoords[ 9] = aTextureCoord + vec2(0.0, 2.0 * strength); + vBlurTexCoords[ 10] = aTextureCoord + vec2(0.0, 3.0 * strength); + vBlurTexCoords[ 11] = aTextureCoord + vec2(0.0, 4.0 * strength); + vBlurTexCoords[ 12] = aTextureCoord + vec2(0.0, 5.0 * strength); + vBlurTexCoords[ 13] = aTextureCoord + vec2(0.0, 6.0 * strength); + vBlurTexCoords[ 14] = aTextureCoord + vec2(0.0, 7.0 * strength); + + +} diff --git a/src/filters/blur/generateBlurFragSource.js b/src/filters/blur/generateBlurFragSource.js new file mode 100644 index 0000000..59cf930 --- /dev/null +++ b/src/filters/blur/generateBlurFragSource.js @@ -0,0 +1,63 @@ +var core = require('../../core') + +var GAUSSIAN_VALUES = { + 5:[0.06136, 0.24477, 0.38774], + 7:[0.00598, 0.060626, 0.241843, 0.383103], + 9:[0.000229, 0.005977, 0.060598, 0.241732, 0.382928], + 11:[0.000003, 0.000229, 0.005977, 0.060598, 0.24173, 0.382925], + 13:[0.0, 0.000003, 0.000229, 0.005977, 0.060598, 0.24173, 0.382925], + 15:[0.0, 0.0, 0.000003, 0.000229, 0.005977, 0.060598, 0.24173, 0.382925] +} + +var generateFragBlurSource = function(kernelSize) +{ + var kernel = GAUSSIAN_VALUES[kernelSize]; + var halfLength = kernel.length; + + var fragSource = fragTemplate; + + var blurLoop = ''; + var template = 'gl_FragColor += texture2D(uSampler, vBlurTexCoords[%index%]) * %value%;' + + for (var i = 0; i < kernelSize; i++) + { + var blur = template.replace('%index%', i); + + value = i; + + if(i >= halfLength) + { + value = kernelSize - i - 1; + } + + + blur = blur.replace('%value%', kernel[value]); + + blurLoop += blur; + blurLoop += '\n'; + }; + + fragSource = fragSource.replace('%blur%', blurLoop) + fragSource = fragSource.replace('%size%', kernelSize) + + + return fragSource; +} + +var fragTemplate = [ + + 'precision mediump float;', + + 'varying vec2 vTextureCoord;', + 'varying vec2 vBlurTexCoords[%size%];', + 'uniform sampler2D uSampler;', + + 'void main(void)', + '{', + ' gl_FragColor = vec4(0.0);', + ' %blur%', + '}' + +].join('\n'); + +module.exports = generateFragBlurSource; \ No newline at end of file diff --git a/src/filters/blur/generateBlurVertSource.js b/src/filters/blur/generateBlurVertSource.js new file mode 100644 index 0000000..7096810 --- /dev/null +++ b/src/filters/blur/generateBlurVertSource.js @@ -0,0 +1,64 @@ + +var generateVertBlurSource = function(kernelSize, x) +{ + var halfLength = Math.ceil(kernelSize/2); + + var vertSource = vertTemplate; + + var blurLoop = ''; + var template + + if(x) + { + template = 'vBlurTexCoords[%index%] = aTextureCoord + vec2(%samlpeIndex% * strength, 0.0);' + } + else + { + template = 'vBlurTexCoords[%index%] = aTextureCoord + vec2(0.0, %samlpeIndex% * strength);' + + } + + + for (var i = 0; i < kernelSize; i++) + { + var blur = template.replace('%index%', i); + + value = i; + + if(i >= halfLength) + { + value = kernelSize - i - 1; + } + + blur = blur.replace('%samlpeIndex%', (i - (halfLength-1)) + ".0"); + + blurLoop += blur; + blurLoop += '\n'; + }; + + vertSource = vertSource.replace('%blur%', blurLoop) + vertSource = vertSource.replace('%size%', kernelSize) + + return vertSource; +} + +var vertTemplate = [ + + 'attribute vec2 aVertexPosition;', + 'attribute vec2 aTextureCoord;', + + 'uniform float strength;', + 'uniform mat3 projectionMatrix;', + + 'varying vec2 vTextureCoord;', + 'varying vec2 vBlurTexCoords[%size%];', + + 'void main(void)', + '{', + 'gl_Position = vec4((projectionMatrix * vec3((aVertexPosition), 1.0)).xy, 0.0, 1.0);', + 'vTextureCoord = aTextureCoord;',//TODO remove.. + '%blur%', + '}' +].join('\n'); + +module.exports = generateVertBlurSource; \ No newline at end of file diff --git a/src/filters/index.js b/src/filters/index.js index bbf6ddf..d5bfee7 100644 --- a/src/filters/index.js +++ b/src/filters/index.js @@ -11,9 +11,6 @@ module.exports = { // AsciiFilter: require('./ascii/AsciiFilter'), // BloomFilter: require('./bloom/BloomFilter'), - // BlurFilter: require('./blur/BlurFilter'), - // BlurXFilter: require('./blur/BlurXFilter'), - // BlurYFilter: require('./blur/BlurYFilter'), // BlurDirFilter: require('./blur/BlurDirFilter'), // ColorStepFilter: require('./color/ColorStepFilter'), // ConvolutionFilter: require('./convolution/ConvolutionFilter'), @@ -31,7 +28,11 @@ // TiltShiftFilter: require('./tiltshift/TiltShiftFilter'), // TiltShiftXFilter: require('./tiltshift/TiltShiftXFilter'), //TiltShiftYFilter: require('./tiltshift/TiltShiftYFilter'), - ColorMatrixFilter: require('./colormatrix/ColorMatrixFilter'), - TwistFilter: require('./twist/TwistFilter'), - GrayFilter: require('./gray/GrayFilter') + BlurFilter: require('./blur/BlurFilter'), + BlurXFilter: require('./blur/BlurXFilter'), + BlurYFilter: require('./blur/BlurYFilter'), + + ColorMatrixFilter: require('./colormatrix/ColorMatrixFilter'), + TwistFilter: require('./twist/TwistFilter'), + GrayFilter: require('./gray/GrayFilter') }; diff --git a/package.json b/package.json index 4436b84..48a074c 100644 --- a/package.json +++ b/package.json @@ -32,10 +32,8 @@ "dependencies": { "async": "^1.5.0", "bit-twiddle": "^1.0.2", - "brfs": "^1.4.1", "earcut": "^2.0.7", "eventemitter3": "^1.1.1", - "gl-matrix": "git+https://github.com/toji/gl-matrix.git", "object-assign": "^4.0.1", "pixi-gl-core": "git+https://github.com/GoodBoyDigital/pixi-gl-core.git", "resource-loader": "^1.6.4" @@ -73,6 +71,5 @@ "transform": [ "glslify" ] - } } diff --git a/src/core/graphics/webgl/PrimitiveShader.js b/src/core/graphics/webgl/PrimitiveShader.js deleted file mode 100644 index 44166b3..0000000 --- a/src/core/graphics/webgl/PrimitiveShader.js +++ /dev/null @@ -1,50 +0,0 @@ -var Shader = require('pixi-gl-core').GLShader; - -/** - * This shader is used to draw simple primitive shapes for {@link PIXI.Graphics}. - * - * @class - * @memberof PIXI - * @extends PIXI.Shader - * @param shaderManager {ShaderManager} The webgl shader manager this shader works for. - */ -function PrimitiveShader(gl) -{ - Shader.call(this, - gl, - // vertex shader - [ - 'attribute vec2 aVertexPosition;', - 'attribute vec4 aColor;', - - 'uniform mat3 translationMatrix;', - 'uniform mat3 projectionMatrix;', - - 'uniform float alpha;', - 'uniform float flipY;', - 'uniform vec3 tint;', - - 'varying vec4 vColor;', - - 'void main(void){', - ' gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', - ' vColor = aColor * vec4(tint * alpha, alpha);', - '}' - ].join('\n'), - // fragment shader - [ - 'precision mediump float;', - - 'varying vec4 vColor;', - - 'void main(void){', - ' gl_FragColor = vColor;', - '}' - ].join('\n') - ); -} - -PrimitiveShader.prototype = Object.create(Shader.prototype); -PrimitiveShader.prototype.constructor = PrimitiveShader; - -module.exports = PrimitiveShader; diff --git a/src/core/math/Matrix.js b/src/core/math/Matrix.js index 4e7fe99..2313ae3 100644 --- a/src/core/math/Matrix.js +++ b/src/core/math/Matrix.js @@ -51,6 +51,7 @@ * @default 0 */ this.ty = 0; + } Matrix.prototype.constructor = Matrix; diff --git a/src/core/renderers/webgl/managers/FilterManager.js b/src/core/renderers/webgl/managers/FilterManager.js index b3f7463..5fc6562 100644 --- a/src/core/renderers/webgl/managers/FilterManager.js +++ b/src/core/renderers/webgl/managers/FilterManager.js @@ -64,11 +64,12 @@ - //TODO - should this be rounded to reoultion? not 1? - sourceFrame.x = targetBounds.x | 0; - sourceFrame.y = targetBounds.y | 0; - sourceFrame.width = targetBounds.width | 0; - sourceFrame.height = targetBounds.height | 0; + + sourceFrame.x = ((targetBounds.x * resolution) | 0) / resolution; + sourceFrame.y = ((targetBounds.y * resolution) | 0) / resolution; + sourceFrame.width = ((targetBounds.width * resolution) | 0) / resolution; + sourceFrame.height = ((targetBounds.height * resolution) | 0) / resolution; + sourceFrame.pad(padding * resolution); sourceFrame.fit(this.stack[0].destinationFrame); @@ -79,6 +80,7 @@ currentState.target = target; currentState.filters = filters; + currentState.resolution = resolution; currentState.renderTarget = renderTarget; // bind the render taget to draw the shape in the top corner.. @@ -236,6 +238,13 @@ shader.uniforms[i] = uniforms[i]; } } + else if(uniformData[i].type === 'float') + { + if(shader.uniforms.data[i].value !== uniformData[i]) + { + shader.uniforms[i] = uniforms[i]; + } + } else { shader.uniforms[i] = uniforms[i]; @@ -244,10 +253,18 @@ } -FilterManager.prototype.getPotRenderTarget = function() +FilterManager.prototype.getRenderTarget = function() { var currentState = this.stack[this.stackIndex]; - return FilterManager.getPotRenderTarget(renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, 1); + var renderTarget = FilterManager.getPotRenderTarget(renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, currentState.resolution); + renderTarget.setFrame(currentState.destinationFrame, currentState.sourceFrame); + + return renderTarget; +} + +FilterManager.prototype.returnRenderTarget = function(renderTarget) +{ + return FilterManager.freePotRenderTarget(renderTarget); } /* @@ -325,6 +342,7 @@ this.destinationFrame = new math.Rectangle(); this.filters = []; this.target = null; + this.resolution = 1; } FilterManager.pool = {} diff --git a/src/core/renderers/webgl/utils/RenderTarget.js b/src/core/renderers/webgl/utils/RenderTarget.js index ced94f6..d3daf50 100644 --- a/src/core/renderers/webgl/utils/RenderTarget.js +++ b/src/core/renderers/webgl/utils/RenderTarget.js @@ -136,6 +136,15 @@ { this.frameBuffer = GLFramebuffer.createRGBA(gl, 100, 100); + if( this.scaleMode === CONST.SCALE_MODES.NEAREST) + { + this.frameBuffer.texture.enableNearestScaling() + } + else + { + this.frameBuffer.texture.enableLinearScaling() + + } /* A frame buffer needs a target to render to.. create a texture and bind it attach it to the framebuffer.. @@ -213,8 +222,10 @@ this.projectionMatrix.append(this.transform); } + //TODO add a check as them may be the same! if(this.destinationFrame !== this.sourceFrame) { + gl.enable(gl.SCISSOR_TEST); gl.scissor(this.destinationFrame.x | 0,this.destinationFrame.y | 0, (this.destinationFrame.width * this.resolution) | 0, (this.destinationFrame.height* this.resolution) | 0); } @@ -279,8 +290,6 @@ return; } - console.log(width + " : " + height) - this.size.width = width; this.size.height = height; diff --git a/src/core/textures/BaseRenderTexture copy.js b/src/core/textures/BaseRenderTexture copy.js deleted file mode 100644 index acf6ac9..0000000 --- a/src/core/textures/BaseRenderTexture copy.js +++ /dev/null @@ -1,482 +0,0 @@ -var BaseTexture = require('./BaseTexture'), - Texture = require('./Texture'), - RenderTarget = require('../renderers/webgl/utils/RenderTarget'), - FilterManager = require('../renderers/webgl/managers/FilterManager'), - CanvasBuffer = require('../renderers/canvas/utils/CanvasBuffer'), - math = require('../math'), - CONST = require('../const'), - tempMatrix = new math.Matrix(), - tempRect = new math.Rectangle(); - -/** - * A BaseRenderTexture is a special texture that allows any Pixi display object to be rendered to it. - * - * __Hint__: All DisplayObjects (i.e. Sprites) that render to a BaseRenderTexture should be preloaded - * otherwise black rectangles will be drawn instead. - * - * A BaseRenderTexture takes a snapshot of any Display Object given to its render method. The position - * and rotation of the given Display Objects is ignored. For example: - * - * ```js - * var renderer = PIXI.autoDetectRenderer(1024, 1024, { view: canvas, ratio: 1 }); - * var BaserenderTexture = new PIXI.BaseRenderTexture(renderer, 800, 600); - * var sprite = PIXI.Sprite.fromImage("spinObj_01.png"); - * - * sprite.position.x = 800/2; - * sprite.position.y = 600/2; - * sprite.anchor.x = 0.5; - * sprite.anchor.y = 0.5; - * - * BaserenderTexture.render(sprite); - * ``` - * - * The Sprite in this case will be rendered to a position of 0,0. To render this sprite at its actual - * position a Container should be used: - * - * ```js - * var doc = new PIXI.Container(); - * - * doc.addChild(sprite); - * - * BaserenderTexture.render(doc); // Renders to center of BaserenderTexture - * ``` - * - * @class - * @extends PIXI.Texture - * @memberof PIXI - * @param renderer {PIXI.CanvasRenderer|PIXI.WebGLRenderer} The renderer used for this BaseRenderTexture - * @param [width=100] {number} The width of the render texture - * @param [height=100] {number} The height of the render texture - * @param [scaleMode] {number} See {@link PIXI.SCALE_MODES} for possible values - * @param [resolution=1] {number} The resolution of the texture being generated - */ -function BaseRenderTexture(renderer, width, height, scaleMode, resolution) -{ - if (!renderer) - { - throw new Error('Unable to create BaseRenderTexture, you must pass a renderer into the constructor.'); - } - - BaseTexture.call(this, null, scaleMode); - - this.width = width || 100; - this.height = height || 100; - - this.resolution = resolution || CONST.RESOLUTION;; - this.scaleMode = scaleMode || CONST.SCALE_MODES.DEFAULT; - this.hasLoaded = true; - - /** - * Draw/render the given DisplayObject onto the texture. - * - * The displayObject and descendents are transformed during this operation. - * If `updateTransform` is true then the transformations will be restored before the - * method returns. Otherwise it is up to the calling code to correctly use or reset - * the transformed display objects. - * - * The display object is always rendered with a worldAlpha value of 1. - * - * @method - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear=false] {boolean} If true the texture will be cleared before the displayObject is drawn - * @param [updateTransform=true] {boolean} If true the displayObject's worldTransform/worldAlpha and all children - * transformations will be restored. Not restoring this information will be a little faster. - */ - this.render = null; - - /** - * The renderer this BaseRenderTexture uses. A BaseRenderTexture can only belong to one renderer at the moment if its webGL. - * - * @member {PIXI.CanvasRenderer|PIXI.WebGLRenderer} - */ - this.renderer = renderer; - - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - var gl = this.renderer.gl; - - this.textureBuffer = new RenderTarget(gl, this.width, this.height, this.scaleMode, this.resolution);//, this.this.scaleMode); - this._glTextures[gl.id] = this.textureBuffer.texture; - - //TODO refactor filter manager.. as really its no longer a manager if we use it here.. - this.filterManager = new FilterManager(this.renderer); - this.filterManager.onContextChange(); - this.filterManager.resize(width, height); - this.render = this.renderWebGL; - - // the creation of a filter manager unbinds the buffers.. - this.renderer.currentRenderer.start(); - if(this.renderer._activeRenderTarget)this.renderer._activeRenderTarget.activate(); - } - else - { - - this.render = this.renderCanvas; - this.textureBuffer = new CanvasBuffer(this.width* this.resolution, this.height* this.resolution); - this.source = this.textureBuffer.canvas; - } - - /** - * @member {boolean} - */ - this.valid = true; - -} - -BaseRenderTexture.prototype = Object.create(BaseTexture.prototype); -BaseRenderTexture.prototype.constructor = BaseRenderTexture; -module.exports = BaseRenderTexture; - -/** - * Resizes the BaseRenderTexture. - * - * @param width {number} The width to resize to. - * @param height {number} The height to resize to. - * @param updateBase {boolean} Should the baseTexture.width and height values be resized as well? - */ -BaseRenderTexture.prototype.resize = function (width, height) -{ - if (width === this.width && height === this.height) - { - return; - } - - this.valid = (width > 0 && height > 0); - - this.width = width; - this.height = height; - - if (!this.valid) - { - return; - } - - this.textureBuffer.resize(this.width, this.height); - - if(this.filterManager) - { - this.filterManager.resize(this.width, this.height); - } -}; - -/** - * Clears the BaseRenderTexture. - * - */ -BaseRenderTexture.prototype.clear = function (destinationFrame) -{ - if (!this.valid) - { - return; - } - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - this.renderer.gl.bindFramebuffer(this.renderer.gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - } - - this.textureBuffer.clear(false, destinationFrame); -}; - -/** - * Internal method assigned to the `render` property if using a CanvasRenderer. - * - * @private - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear=false] {boolean} If true the texture will be cleared before the displayObject is drawn - * @param [updateTransform=true] {boolean} If true the displayObject's worldTransform/worldAlpha and all children - * transformations will be restored. Not restoring this information will be a little faster. - */ -BaseRenderTexture.prototype.renderWebGL = function (frame, displayObject, matrix, clear, updateTransform) -{ - if (!this.valid) - { - return; - } - - - updateTransform = (updateTransform !== undefined) ? updateTransform : true;//!updateTransform; - - this.textureBuffer.transform = matrix; - - //TODO not a fan that this is here... it will move! - this.textureBuffer.activate(); - - // setWorld Alpha to ensure that the object is renderer at full opacity - displayObject.worldAlpha = 1; - - if (updateTransform) - { - - // reset the matrix of the displatyObject.. - displayObject.worldTransform.identity(); - - displayObject.currentBounds = null; - - // Time to update all the children of the displayObject with the new matrix.. - var children = displayObject.children; - var i, j; - - for (i = 0, j = children.length; i < j; ++i) - { - children[i].updateTransform(); - } - } - - tempRect.width = frame.height; - tempRect.height = frame.width; - - //TODO rename textureBuffer to renderTarget.. - var temp = this.renderer.filterManager; - - this.renderer.filterManager = this.filterManager; - - - this.textureBuffer.activate(frame, tempRect); - console.log(displayObject) - this.renderer.renderDisplayObject(displayObject, this.textureBuffer, clear); - - // console.log("RENDERING "); - this.renderer.filterManager = temp; -}; - - -/** - * Internal method assigned to the `render` property if using a CanvasRenderer. - * - * @private - * @param displayObject {PIXI.DisplayObject} The display object to render this texture on - * @param [matrix] {PIXI.Matrix} Optional matrix to apply to the display object before rendering. - * @param [clear] {boolean} If true the texture will be cleared before the displayObject is drawn - */ -BaseRenderTexture.prototype.renderCanvas = function (frame, displayObject, matrix, clear, updateTransform) -{ - if (!this.valid) - { - return; - } - - updateTransform = !!updateTransform; - - var wt = tempMatrix; - - wt.identity(); - - if (matrix) - { - wt.append(matrix); - } - - - wt.tx += frame.x; - wt.ty += frame.y; - - var cachedWt = displayObject.worldTransform; - - displayObject.worldTransform = wt; - - // setWorld Alpha to ensure that the object is renderer at full opacity - displayObject.worldAlpha = 1; - - // Time to update all the children of the displayObject with the new matrix.. - var children = displayObject.children; - var i, j; - - for (i = 0, j = children.length; i < j; ++i) - { - children[i].updateTransform(); - } - - if (clear) - { - this.textureBuffer.clear(); - } - - -// this.textureBuffer. - var context = this.textureBuffer.context; - - var realResolution = this.renderer.resolution; - - this.renderer.resolution = this.resolution; - - this.renderer.renderDisplayObject(displayObject, context); - - this.renderer.resolution = realResolution; - - if(displayObject.worldTransform === wt) - { - // fixes cacheAsBitmap Happening during the above.. - displayObject.worldTransform = cachedWt; - } - -}; - -/** - * Destroys this texture - * - * @param destroyBase {boolean} Whether to destroy the base texture as well - */ -BaseRenderTexture.prototype.destroy = function () -{ - Texture.prototype.destroy.call(this, true); - - this.textureBuffer.destroy(); - - // destroy the filtermanager.. - if(this.filterManager) - { - this.filterManager.destroy(); - } - - this.renderer = null; -}; - -/** - * Will return a HTML Image of the texture - * - * @return {Image} - */ -BaseRenderTexture.prototype.getImage = function (frame) -{ - var image = new Image(); - image.src = this.getBase64(frame); - return image; -}; - -/** - * Will return a a base64 encoded string of this texture. It works by calling BaseRenderTexture.getCanvas and then running toDataURL on that. - * - * @return {string} A base64 encoded string of the texture. - */ -BaseRenderTexture.prototype.getBase64 = function ( frame ) -{ - return this.getCanvas(frame).toDataURL(); -}; - -/** - * Creates a Canvas element, renders this BaseRenderTexture to it and then returns it. - * - * @return {HTMLCanvasElement} A Canvas element with the texture rendered on. - */ -BaseRenderTexture.prototype.getCanvas = function ( frame ) -{ - - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.size.width; - frame.height = this.textureBuffer.size.height; - } - - var width = frame.width * this.resolution; - var height = frame.height * this.resolution; - - var gl = this.renderer.gl; - - var webGLPixels = new Uint8Array(4 * width * height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - gl.readPixels(frame.x * this.resolution, frame.y * this.resolution, width, height, gl.RGBA, gl.UNSIGNED_BYTE, webGLPixels); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - var tempCanvas = new CanvasBuffer(width, height); - var canvasData = tempCanvas.context.getImageData(0, 0, width, height); - canvasData.data.set(webGLPixels); - - tempCanvas.context.putImageData(canvasData, 0, 0); - - return tempCanvas.canvas; - } - else - { - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.canvas.width; - frame.height = this.textureBuffer.canvas.height; - } - - if(frame.width === this.textureBuffer.canvas.width && - frame.height === this.textureBuffer.canvas.height ) - { - return this.textureBuffer.canvas; - } - else - { - - var resolution = this.resolution; - - var tempCanvas = new CanvasBuffer(frame.width * resolution, frame.height * resolution); - var canvasData = this.textureBuffer.context.getImageData(frame.x * resolution, frame.y * resolution, frame.width * resolution, frame.height * resolution); - - tempCanvas.context.putImageData(canvasData, 0, 0); - - return tempCanvas.canvas; - } - } -}; - -/** - * Will return a one-dimensional array containing the pixel data of the entire texture in RGBA order, with integer values between 0 and 255 (included). - * - * @return {Uint8ClampedArray} - */ -BaseRenderTexture.prototype.getPixels = function ( frame ) -{ - if(!frame) - { - frame = tempRect; - frame.width = this.textureBuffer.size.width; - frame.height = this.textureBuffer.size.height; - } - - var width = frame.width * this.resolution; - var height = frame.height * this.resolution; - - if (this.renderer.type === CONST.RENDERER_TYPE.WEBGL) - { - var gl = this.renderer.gl; - - var webGLPixels = new Uint8Array(4 * width * height); - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); - gl.readPixels(frame.x * this.resolution, frame.y * this.resolution, width, height, gl.RGBA, gl.UNSIGNED_BYTE, webGLPixels); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - return webGLPixels; - } - else - { - return this.textureBuffer.canvas.getContext('2d').getImageData(frame.x * this.resolution, frame.y * this.resolution, width, height).data; - } -}; - -/** - * Will return a one-dimensional array containing the pixel data of a pixel within the texture in RGBA order, with integer values between 0 and 255 (included). - * - * @param x {number} The x coordinate of the pixel to retrieve. - * @param y {number} The y coordinate of the pixel to retrieve. - * @return {Uint8ClampedArray} - */ -BaseRenderTexture.prototype.getPixel = function (frame, x, y) -{ - tempRect.x = x; - tempRect.y = y; - tempRect.width = 1 / this.resolution; - tempRect.height = 1 / this.resolution; - - if(frame) - { - tempRect.x += frame.x; - tempRect.y += frame.y; - } - - return this.getPixels(tempRect); -}; diff --git a/src/filters/blur/BlurFilter.js b/src/filters/blur/BlurFilter.js new file mode 100644 index 0000000..fb708a1 --- /dev/null +++ b/src/filters/blur/BlurFilter.js @@ -0,0 +1,114 @@ +var core = require('../../core'), + BlurXFilter = require('./BlurXFilter'), + BlurYFilter = require('./BlurYFilter'); + +/** + * The BlurFilter applies a Gaussian blur to an object. + * The strength of the blur can be set for x- and y-axis separately. + * + * @class + * @extends PIXI.Filter + * @memberof PIXI.filters + */ +function BlurFilter() +{ + core.Filter.call(this); + + this.blurXFilter = new BlurXFilter(); + this.blurYFilter = new BlurYFilter(); + this.resolution = 0.25;//0.25;//0.25//1//01.26; + this.blurYFilter.passes = this.blurXFilter.passes = 2; + this.blurYFilter.strength = this.blurXFilter.strength = 4;//4// 4 + + this.padding = 100 + +} + +BlurFilter.prototype = Object.create(core.Filter.prototype); +BlurFilter.prototype.constructor = BlurFilter; +module.exports = BlurFilter; + +BlurFilter.prototype.apply = function (filterManager, input, output) +{ + var renderTarget = filterManager.getRenderTarget(true); + + this.blurXFilter.apply(filterManager, input, renderTarget, true); + this.blurYFilter.apply(filterManager, renderTarget, output); + + filterManager.returnRenderTarget(renderTarget); +}; + +Object.defineProperties(BlurFilter.prototype, { + /** + * Sets the strength of both the blurX and blurY properties simultaneously + * + * @member {number} + * @memberOf PIXI.filters.BlurFilter# + * @default 2 + */ + blur: { + get: function () + { + return this.blurXFilter.blur; + }, + set: function (value) + { + this.padding = Math.abs(value) * 0.5; + this.blurXFilter.blur = this.blurYFilter.blur = value; + } + }, + + /** + * Sets the number of passes for blur. More passes means higher quaility bluring. + * + * @member {number} + * @memberof PIXI.filters.BlurYFilter# + * @default 1 + */ + passes: { + get: function () + { + return this.blurXFilter.passes; + }, + set: function (value) + { + this.blurXFilter.passes = this.blurYFilter.passes = value; + } + }, + + /** + * Sets the strength of the blurX property + * + * @member {number} + * @memberOf PIXI.filters.BlurFilter# + * @default 2 + */ + blurX: { + get: function () + { + return this.blurXFilter.blur; + }, + set: function (value) + { + this.blurXFilter.blur = value; + } + }, + + /** + * Sets the strength of the blurY property + * + * @member {number} + * @memberOf PIXI.filters.BlurFilter# + * @default 2 + */ + blurY: { + get: function () + { + return this.blurYFilter.blur; + }, + set: function (value) + { + this.blurYFilter.blur = value; + } + } +}); diff --git a/src/filters/blur/BlurXFilter.js b/src/filters/blur/BlurXFilter.js new file mode 100644 index 0000000..61eed96 --- /dev/null +++ b/src/filters/blur/BlurXFilter.js @@ -0,0 +1,94 @@ +var core = require('../../core'); +var glslify = require('glslify'); +var generateBlurVertSource = require('./generateBlurVertSource'); +var generateBlurFragSource = require('./generateBlurFragSource'); + +/** + * The BlurXFilter applies a horizontal Gaussian blur to an object. + * + * @class + * @extends PIXI.Filter + * @memberof PIXI.filters + */ +function BlurXFilter() +{ + var vertSrc = generateBlurVertSource(11, true); + var fragSrc = generateBlurFragSource(11); + + console.log(vertSrc); + console.log(fragSrc); + + core.Filter.call(this, + // vertex shader + vertSrc, + // fragment shader + fragSrc + ); + + /** + * Sets the number of passes for blur. More passes means higher quaility bluring. + * + * @member {number} + * @default 1 + */ + this.passes = 1; + this.resolution = 1;//0.25;//0.5;//0.1//5; + this.strength = 4; +} + +BlurXFilter.prototype = Object.create(core.Filter.prototype); +BlurXFilter.prototype.constructor = BlurXFilter; +module.exports = BlurXFilter; + +BlurXFilter.prototype.apply = function (filterManager, input, output, clear) +{ + this.uniforms.strength = (1/output.destinationFrame.width) * (output.size.width/input.size.width); /// // * 2 //4//this.strength / 4 / this.passes * (input.frame.width / input.size.width); + + // screen space! + this.uniforms.strength *= this.strength; + if(this.passes === 1) + { + filterManager.applyFilter(this, input, output, clear); + } + else + { + var renderTarget = filterManager.getRenderTarget(true); + var flip = input; + var flop = renderTarget; + + for(var i = 0; i < this.passes-1; i++) + { + filterManager.applyFilter(this, flip, flop, true); + + var temp = flop; + flop = flip; + flip = temp; + } + + filterManager.applyFilter(this, flip, output, clear); + + filterManager.returnRenderTarget(renderTarget); + } +}; + + +Object.defineProperties(BlurXFilter.prototype, { + /** + * Sets the strength of both the blur. + * + * @member {number} + * @memberof PIXI.filters.BlurXFilter# + * @default 2 + */ + blur: { + get: function () + { + return this.strength; + }, + set: function (value) + { + this.padding = Math.abs(value) * 0.5; + this.strength = value; + } + } +}); diff --git a/src/filters/blur/BlurYFilter.js b/src/filters/blur/BlurYFilter.js new file mode 100644 index 0000000..86a3171 --- /dev/null +++ b/src/filters/blur/BlurYFilter.js @@ -0,0 +1,85 @@ +var core = require('../../core'); +var generateBlurVertSource = require('./generateBlurVertSource'); +var generateBlurFragSource = require('./generateBlurFragSource'); + + +/** + * The BlurYFilter applies a horizontal Gaussian blur to an object. + * + * @class + * @extends PIXI.Filter + * @memberof PIXI.filters + */ +function BlurYFilter() +{ + var vertSrc = generateBlurVertSource(11, false); + var fragSrc = generateBlurFragSource(11); + + core.Filter.call(this, + // vertex shader + vertSrc, + // fragment shader + fragSrc + ); + + this.passes = 1; + this.resolution = 1;//0.25;//0.5;//0.1//5; + this.strength = 4; +} + +BlurYFilter.prototype = Object.create(core.Filter.prototype); +BlurYFilter.prototype.constructor = BlurYFilter; +module.exports = BlurYFilter; + +BlurYFilter.prototype.apply = function (filterManager, input, output, clear) +{ + this.uniforms.strength = (1/output.destinationFrame.height) * (output.size.height/input.size.height); /// // * 2 //4//this.strength / 4 / this.passes * (input.frame.width / input.size.width); + + this.uniforms.strength *= this.strength; + + if(this.passes === 1) + { + filterManager.applyFilter(this, input, output, clear); + } + else + { + var renderTarget = filterManager.getRenderTarget(true); + var flip = input; + var flop = renderTarget; + + for(var i = 0; i < this.passes-1; i++) + { + filterManager.applyFilter(this, flip, flop, true); + + var temp = flop; + flop = flip; + flip = temp; + } + + filterManager.applyFilter(this, flip, output, clear); + + filterManager.returnRenderTarget(renderTarget); + } +}; + + +Object.defineProperties(BlurYFilter.prototype, { + /** + * Sets the strength of both the blur. + * + * @member {number} + * @memberof PIXI.filters.BlurYFilter# + * @default 2 + */ + blur: { + get: function () + { + return this.strength; + }, + set: function (value) + { + this.padding = Math.abs(value) * 0.5; + this.strength = value; + } + } +}); diff --git a/src/filters/blur/blur.frag b/src/filters/blur/blur.frag new file mode 100644 index 0000000..0c4f23c --- /dev/null +++ b/src/filters/blur/blur.frag @@ -0,0 +1,31 @@ +precision mediump float; + +varying vec2 vTextureCoord; +varying vec2 vBlurTexCoords[15]; + +uniform sampler2D uSampler; + +void main(void) +{ + gl_FragColor = vec4(0.0); + + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 0]) * 0.000489; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 1]) * 0.002403; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 2]) * 0.009246; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 3]) * 0.02784; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 4]) * 0.065602; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 5]) * 0.120999; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 6]) * 0.174697; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 7]) * 0.197448; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 8]) * 0.174697; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 9]) * 0.120999; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 10]) * 0.065602; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 11]) * 0.02784; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 12]) * 0.009246; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 13]) * 0.002403; + gl_FragColor += texture2D(uSampler, vBlurTexCoords[ 14]) * 0.000489; + + + + +} diff --git a/src/filters/blur/blurX.vert b/src/filters/blur/blurX.vert new file mode 100644 index 0000000..cc0e22b --- /dev/null +++ b/src/filters/blur/blurX.vert @@ -0,0 +1,31 @@ +attribute vec2 aVertexPosition; +attribute vec2 aTextureCoord; + +uniform float strength; +uniform mat3 projectionMatrix; + +varying vec2 vTextureCoord; +varying vec2 vBlurTexCoords[15]; + +void main(void) +{ + gl_Position = vec4((projectionMatrix * vec3((aVertexPosition), 1.0)).xy, 0.0, 1.0); + vTextureCoord = aTextureCoord; + + vBlurTexCoords[ 0] = aTextureCoord + vec2(-7.0 * strength, 0.0); + vBlurTexCoords[ 1] = aTextureCoord + vec2(-6.0 * strength, 0.0); + vBlurTexCoords[ 2] = aTextureCoord + vec2(-5.0 * strength, 0.0); + vBlurTexCoords[ 3] = aTextureCoord + vec2(-4.0 * strength, 0.0); + vBlurTexCoords[ 4] = aTextureCoord + vec2(-3.0 * strength, 0.0); + vBlurTexCoords[ 5] = aTextureCoord + vec2(-2.0 * strength, 0.0); + vBlurTexCoords[ 6] = aTextureCoord + vec2(-1.0 * strength, 0.0); + vBlurTexCoords[ 7] = aTextureCoord; + vBlurTexCoords[ 8] = aTextureCoord + vec2(1.0 * strength, 0.0); + vBlurTexCoords[ 9] = aTextureCoord + vec2(2.0 * strength, 0.0); + vBlurTexCoords[ 10] = aTextureCoord + vec2(3.0 * strength, 0.0); + vBlurTexCoords[ 11] = aTextureCoord + vec2(4.0 * strength, 0.0); + vBlurTexCoords[ 12] = aTextureCoord + vec2(5.0 * strength, 0.0); + vBlurTexCoords[ 13] = aTextureCoord + vec2(6.0 * strength, 0.0); + vBlurTexCoords[ 14] = aTextureCoord + vec2(7.0 * strength, 0.0); + +} diff --git a/src/filters/blur/blurY.vert b/src/filters/blur/blurY.vert new file mode 100644 index 0000000..f1616f7 --- /dev/null +++ b/src/filters/blur/blurY.vert @@ -0,0 +1,32 @@ +attribute vec2 aVertexPosition; +attribute vec2 aTextureCoord; + +uniform float strength; +uniform mat3 projectionMatrix; + +varying vec2 vTextureCoord; +varying vec2 vBlurTexCoords[15]; + +void main(void) +{ + gl_Position = vec4((projectionMatrix * vec3((aVertexPosition), 1.0)).xy, 0.0, 1.0); + vTextureCoord = aTextureCoord; + + vBlurTexCoords[ 0] = aTextureCoord + vec2(0.0, -7.0 * strength); + vBlurTexCoords[ 1] = aTextureCoord + vec2(0.0, -6.0 * strength); + vBlurTexCoords[ 2] = aTextureCoord + vec2(0.0, -5.0 * strength); + vBlurTexCoords[ 3] = aTextureCoord + vec2(0.0, -4.0 * strength); + vBlurTexCoords[ 4] = aTextureCoord + vec2(0.0, -3.0 * strength); + vBlurTexCoords[ 5] = aTextureCoord + vec2(0.0, -2.0 * strength); + vBlurTexCoords[ 6] = aTextureCoord + vec2(0.0, -1.0 * strength); + vBlurTexCoords[ 7] = aTextureCoord; + vBlurTexCoords[ 8] = aTextureCoord + vec2(0.0, 1.0 * strength); + vBlurTexCoords[ 9] = aTextureCoord + vec2(0.0, 2.0 * strength); + vBlurTexCoords[ 10] = aTextureCoord + vec2(0.0, 3.0 * strength); + vBlurTexCoords[ 11] = aTextureCoord + vec2(0.0, 4.0 * strength); + vBlurTexCoords[ 12] = aTextureCoord + vec2(0.0, 5.0 * strength); + vBlurTexCoords[ 13] = aTextureCoord + vec2(0.0, 6.0 * strength); + vBlurTexCoords[ 14] = aTextureCoord + vec2(0.0, 7.0 * strength); + + +} diff --git a/src/filters/blur/generateBlurFragSource.js b/src/filters/blur/generateBlurFragSource.js new file mode 100644 index 0000000..59cf930 --- /dev/null +++ b/src/filters/blur/generateBlurFragSource.js @@ -0,0 +1,63 @@ +var core = require('../../core') + +var GAUSSIAN_VALUES = { + 5:[0.06136, 0.24477, 0.38774], + 7:[0.00598, 0.060626, 0.241843, 0.383103], + 9:[0.000229, 0.005977, 0.060598, 0.241732, 0.382928], + 11:[0.000003, 0.000229, 0.005977, 0.060598, 0.24173, 0.382925], + 13:[0.0, 0.000003, 0.000229, 0.005977, 0.060598, 0.24173, 0.382925], + 15:[0.0, 0.0, 0.000003, 0.000229, 0.005977, 0.060598, 0.24173, 0.382925] +} + +var generateFragBlurSource = function(kernelSize) +{ + var kernel = GAUSSIAN_VALUES[kernelSize]; + var halfLength = kernel.length; + + var fragSource = fragTemplate; + + var blurLoop = ''; + var template = 'gl_FragColor += texture2D(uSampler, vBlurTexCoords[%index%]) * %value%;' + + for (var i = 0; i < kernelSize; i++) + { + var blur = template.replace('%index%', i); + + value = i; + + if(i >= halfLength) + { + value = kernelSize - i - 1; + } + + + blur = blur.replace('%value%', kernel[value]); + + blurLoop += blur; + blurLoop += '\n'; + }; + + fragSource = fragSource.replace('%blur%', blurLoop) + fragSource = fragSource.replace('%size%', kernelSize) + + + return fragSource; +} + +var fragTemplate = [ + + 'precision mediump float;', + + 'varying vec2 vTextureCoord;', + 'varying vec2 vBlurTexCoords[%size%];', + 'uniform sampler2D uSampler;', + + 'void main(void)', + '{', + ' gl_FragColor = vec4(0.0);', + ' %blur%', + '}' + +].join('\n'); + +module.exports = generateFragBlurSource; \ No newline at end of file diff --git a/src/filters/blur/generateBlurVertSource.js b/src/filters/blur/generateBlurVertSource.js new file mode 100644 index 0000000..7096810 --- /dev/null +++ b/src/filters/blur/generateBlurVertSource.js @@ -0,0 +1,64 @@ + +var generateVertBlurSource = function(kernelSize, x) +{ + var halfLength = Math.ceil(kernelSize/2); + + var vertSource = vertTemplate; + + var blurLoop = ''; + var template + + if(x) + { + template = 'vBlurTexCoords[%index%] = aTextureCoord + vec2(%samlpeIndex% * strength, 0.0);' + } + else + { + template = 'vBlurTexCoords[%index%] = aTextureCoord + vec2(0.0, %samlpeIndex% * strength);' + + } + + + for (var i = 0; i < kernelSize; i++) + { + var blur = template.replace('%index%', i); + + value = i; + + if(i >= halfLength) + { + value = kernelSize - i - 1; + } + + blur = blur.replace('%samlpeIndex%', (i - (halfLength-1)) + ".0"); + + blurLoop += blur; + blurLoop += '\n'; + }; + + vertSource = vertSource.replace('%blur%', blurLoop) + vertSource = vertSource.replace('%size%', kernelSize) + + return vertSource; +} + +var vertTemplate = [ + + 'attribute vec2 aVertexPosition;', + 'attribute vec2 aTextureCoord;', + + 'uniform float strength;', + 'uniform mat3 projectionMatrix;', + + 'varying vec2 vTextureCoord;', + 'varying vec2 vBlurTexCoords[%size%];', + + 'void main(void)', + '{', + 'gl_Position = vec4((projectionMatrix * vec3((aVertexPosition), 1.0)).xy, 0.0, 1.0);', + 'vTextureCoord = aTextureCoord;',//TODO remove.. + '%blur%', + '}' +].join('\n'); + +module.exports = generateVertBlurSource; \ No newline at end of file diff --git a/src/filters/index.js b/src/filters/index.js index bbf6ddf..d5bfee7 100644 --- a/src/filters/index.js +++ b/src/filters/index.js @@ -11,9 +11,6 @@ module.exports = { // AsciiFilter: require('./ascii/AsciiFilter'), // BloomFilter: require('./bloom/BloomFilter'), - // BlurFilter: require('./blur/BlurFilter'), - // BlurXFilter: require('./blur/BlurXFilter'), - // BlurYFilter: require('./blur/BlurYFilter'), // BlurDirFilter: require('./blur/BlurDirFilter'), // ColorStepFilter: require('./color/ColorStepFilter'), // ConvolutionFilter: require('./convolution/ConvolutionFilter'), @@ -31,7 +28,11 @@ // TiltShiftFilter: require('./tiltshift/TiltShiftFilter'), // TiltShiftXFilter: require('./tiltshift/TiltShiftXFilter'), //TiltShiftYFilter: require('./tiltshift/TiltShiftYFilter'), - ColorMatrixFilter: require('./colormatrix/ColorMatrixFilter'), - TwistFilter: require('./twist/TwistFilter'), - GrayFilter: require('./gray/GrayFilter') + BlurFilter: require('./blur/BlurFilter'), + BlurXFilter: require('./blur/BlurXFilter'), + BlurYFilter: require('./blur/BlurYFilter'), + + ColorMatrixFilter: require('./colormatrix/ColorMatrixFilter'), + TwistFilter: require('./twist/TwistFilter'), + GrayFilter: require('./gray/GrayFilter') }; diff --git a/src/filters/twist/TwistFilter.js b/src/filters/twist/TwistFilter.js index 6cddb4b..4c482ec 100644 --- a/src/filters/twist/TwistFilter.js +++ b/src/filters/twist/TwistFilter.js @@ -16,7 +16,6 @@ glslify('./twist.vert', 'utf8'), // fragment shader glslify('./twist.frag', 'utf8') - // custom uniforms ); this.uniforms.radius = 400;