diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index 20e778c..1413a28 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -249,6 +249,8 @@ }, set: function (value) { + this._filters = value; + /* if (value) { // now put all the passes in one place.. @@ -268,7 +270,7 @@ this._filterBlock = { target: this, filterPasses: passes }; } - this._filters = value; + this._filters = value;*/ } } }); diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index 20e778c..1413a28 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -249,6 +249,8 @@ }, set: function (value) { + this._filters = value; + /* if (value) { // now put all the passes in one place.. @@ -268,7 +270,7 @@ this._filterBlock = { target: this, filterPasses: passes }; } - this._filters = value; + this._filters = value;*/ } } }); diff --git a/src/core/display/DisplayObjectContainer.js b/src/core/display/DisplayObjectContainer.js index 120c9ff..4af3f82 100644 --- a/src/core/display/DisplayObjectContainer.js +++ b/src/core/display/DisplayObjectContainer.js @@ -500,8 +500,9 @@ // push filter first as we need to ensure the stencil buffer is correct for any masking if (this._filters) { - renderer.plugins.sprite.flush(); - renderer.filterManager.pushFilter(this._filterBlock); + renderer.currentRenderer.flush(); + renderer.filterManager.pushFilter(this, this._filters); + renderer.currentRenderer.start(); } if (this._mask) @@ -526,7 +527,9 @@ if (this._filters) { + renderer.currentRenderer.flush(); renderer.filterManager.popFilter(); + renderer.currentRenderer.start(); } } diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index 20e778c..1413a28 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -249,6 +249,8 @@ }, set: function (value) { + this._filters = value; + /* if (value) { // now put all the passes in one place.. @@ -268,7 +270,7 @@ this._filterBlock = { target: this, filterPasses: passes }; } - this._filters = value; + this._filters = value;*/ } } }); diff --git a/src/core/display/DisplayObjectContainer.js b/src/core/display/DisplayObjectContainer.js index 120c9ff..4af3f82 100644 --- a/src/core/display/DisplayObjectContainer.js +++ b/src/core/display/DisplayObjectContainer.js @@ -500,8 +500,9 @@ // push filter first as we need to ensure the stencil buffer is correct for any masking if (this._filters) { - renderer.plugins.sprite.flush(); - renderer.filterManager.pushFilter(this._filterBlock); + renderer.currentRenderer.flush(); + renderer.filterManager.pushFilter(this, this._filters); + renderer.currentRenderer.start(); } if (this._mask) @@ -526,7 +527,9 @@ if (this._filters) { + renderer.currentRenderer.flush(); renderer.filterManager.popFilter(); + renderer.currentRenderer.start(); } } diff --git a/src/core/graphics/webgl/GraphicsRenderer.js b/src/core/graphics/webgl/GraphicsRenderer.js index c81350b..a63640e 100644 --- a/src/core/graphics/webgl/GraphicsRenderer.js +++ b/src/core/graphics/webgl/GraphicsRenderer.js @@ -3,7 +3,9 @@ CONST = require('../../const'), ObjectRenderer = require('../../renderers/webgl/utils/ObjectRenderer'), WebGLRenderer = require('../../renderers/webgl/WebGLRenderer'), - WebGLGraphicsData = require('./WebGLGraphicsData'); + WebGLGraphicsData = require('./WebGLGraphicsData'), + ComplexPrimitiveShader = require('./ComplexPrimitiveShader'), + PrimitiveShader = require('./PrimitiveShader'); /** * Renders the graphics object. diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index 20e778c..1413a28 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -249,6 +249,8 @@ }, set: function (value) { + this._filters = value; + /* if (value) { // now put all the passes in one place.. @@ -268,7 +270,7 @@ this._filterBlock = { target: this, filterPasses: passes }; } - this._filters = value; + this._filters = value;*/ } } }); diff --git a/src/core/display/DisplayObjectContainer.js b/src/core/display/DisplayObjectContainer.js index 120c9ff..4af3f82 100644 --- a/src/core/display/DisplayObjectContainer.js +++ b/src/core/display/DisplayObjectContainer.js @@ -500,8 +500,9 @@ // push filter first as we need to ensure the stencil buffer is correct for any masking if (this._filters) { - renderer.plugins.sprite.flush(); - renderer.filterManager.pushFilter(this._filterBlock); + renderer.currentRenderer.flush(); + renderer.filterManager.pushFilter(this, this._filters); + renderer.currentRenderer.start(); } if (this._mask) @@ -526,7 +527,9 @@ if (this._filters) { + renderer.currentRenderer.flush(); renderer.filterManager.popFilter(); + renderer.currentRenderer.start(); } } diff --git a/src/core/graphics/webgl/GraphicsRenderer.js b/src/core/graphics/webgl/GraphicsRenderer.js index c81350b..a63640e 100644 --- a/src/core/graphics/webgl/GraphicsRenderer.js +++ b/src/core/graphics/webgl/GraphicsRenderer.js @@ -3,7 +3,9 @@ CONST = require('../../const'), ObjectRenderer = require('../../renderers/webgl/utils/ObjectRenderer'), WebGLRenderer = require('../../renderers/webgl/WebGLRenderer'), - WebGLGraphicsData = require('./WebGLGraphicsData'); + WebGLGraphicsData = require('./WebGLGraphicsData'), + ComplexPrimitiveShader = require('./ComplexPrimitiveShader'), + PrimitiveShader = require('./PrimitiveShader'); /** * Renders the graphics object. diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 13892a6..8ff6208 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -194,6 +194,9 @@ */ this.filterManager = new WebGLFilterManager(this); + //TODO FIX THIS EVENT>> + this.filterManager.initShaderBuffers(); + /** * Manages the blendModes * @member {WebGLBlendModeManager} @@ -308,9 +311,6 @@ var gl = this.gl; - // -- Does this need to be set every frame? -- // - gl.viewport(0, 0, this.width, this.height); - // make sure we are bound to the main frame buffer gl.bindFramebuffer(gl.FRAMEBUFFER, null); @@ -344,11 +344,13 @@ this.currentRenderTarget = renderTarget; + this.currentRenderTarget.activate(); + // reset the render session data.. this.drawCount = 0; // start the filter manager - // this.filterManager.begin(renderTarget.frameBuffer); + this.filterManager.begin()//renderTarget.frameBuffer); // render the scene! displayObject.renderWebGL(this); diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index 20e778c..1413a28 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -249,6 +249,8 @@ }, set: function (value) { + this._filters = value; + /* if (value) { // now put all the passes in one place.. @@ -268,7 +270,7 @@ this._filterBlock = { target: this, filterPasses: passes }; } - this._filters = value; + this._filters = value;*/ } } }); diff --git a/src/core/display/DisplayObjectContainer.js b/src/core/display/DisplayObjectContainer.js index 120c9ff..4af3f82 100644 --- a/src/core/display/DisplayObjectContainer.js +++ b/src/core/display/DisplayObjectContainer.js @@ -500,8 +500,9 @@ // push filter first as we need to ensure the stencil buffer is correct for any masking if (this._filters) { - renderer.plugins.sprite.flush(); - renderer.filterManager.pushFilter(this._filterBlock); + renderer.currentRenderer.flush(); + renderer.filterManager.pushFilter(this, this._filters); + renderer.currentRenderer.start(); } if (this._mask) @@ -526,7 +527,9 @@ if (this._filters) { + renderer.currentRenderer.flush(); renderer.filterManager.popFilter(); + renderer.currentRenderer.start(); } } diff --git a/src/core/graphics/webgl/GraphicsRenderer.js b/src/core/graphics/webgl/GraphicsRenderer.js index c81350b..a63640e 100644 --- a/src/core/graphics/webgl/GraphicsRenderer.js +++ b/src/core/graphics/webgl/GraphicsRenderer.js @@ -3,7 +3,9 @@ CONST = require('../../const'), ObjectRenderer = require('../../renderers/webgl/utils/ObjectRenderer'), WebGLRenderer = require('../../renderers/webgl/WebGLRenderer'), - WebGLGraphicsData = require('./WebGLGraphicsData'); + WebGLGraphicsData = require('./WebGLGraphicsData'), + ComplexPrimitiveShader = require('./ComplexPrimitiveShader'), + PrimitiveShader = require('./PrimitiveShader'); /** * Renders the graphics object. diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 13892a6..8ff6208 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -194,6 +194,9 @@ */ this.filterManager = new WebGLFilterManager(this); + //TODO FIX THIS EVENT>> + this.filterManager.initShaderBuffers(); + /** * Manages the blendModes * @member {WebGLBlendModeManager} @@ -308,9 +311,6 @@ var gl = this.gl; - // -- Does this need to be set every frame? -- // - gl.viewport(0, 0, this.width, this.height); - // make sure we are bound to the main frame buffer gl.bindFramebuffer(gl.FRAMEBUFFER, null); @@ -344,11 +344,13 @@ this.currentRenderTarget = renderTarget; + this.currentRenderTarget.activate(); + // reset the render session data.. this.drawCount = 0; // start the filter manager - // this.filterManager.begin(renderTarget.frameBuffer); + this.filterManager.begin()//renderTarget.frameBuffer); // render the scene! displayObject.renderWebGL(this); diff --git a/src/core/renderers/webgl/managers/Quad.js b/src/core/renderers/webgl/managers/Quad.js new file mode 100644 index 0000000..b2fae63 --- /dev/null +++ b/src/core/renderers/webgl/managers/Quad.js @@ -0,0 +1,107 @@ +var WebGLManager = require('./WebGLManager'), + utils = require('../../../utils'); + +/** + * @class + * @namespace PIXI + * @param renderer {WebGLRenderer} The renderer this manager works for. + */ +function Quad(gl) +{ + this.gl = gl; + +// this.textures = new TextureUvs(); + + this.vertices = new Float32Array([ + 0,0, + 200,0, + 200,200, + 0,200 + ]); + + this.uvs = new Float32Array([ + 0,0, + 1,0, + 1,1, + 0,1 + ]); + + var white = (0xFFFFFF >> 16) + (0xFFFFFF & 0xff00) + ((0xFFFFFF & 0xff) << 16) + (1 * 255 << 24); + + this.colors = new Float32Array([ + white, + white, + white, + white + ]) + + this.indices = new Uint16Array([ + 0, 1, 2, 0, 3, 2 + ]); + + this.vertexBuffer = gl.createBuffer(); + this.indexBuffer = gl.createBuffer(); + + gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER, (8 + 8 + 4) * 4, gl.DYNAMIC_DRAW); + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW); + + this.upload(); +} + +Quad.prototype.constructor = Quad; + +Quad.prototype.map = function(rect, rect2) +{ + var x = 0//rect2.x / rect.width; + var y = 0//rect2.y / rect.height; + + this.uvs[0] = x; + this.uvs[1] = y; + + this.uvs[2] = x + rect2.width / rect.width; + this.uvs[3] = y; + + this.uvs[4] = x + rect2.width / rect.width; + this.uvs[5] = y + rect2.height / rect.height; + + this.uvs[6] = x; + this.uvs[7] = y + rect2.height / rect.height; + + /// ----- + x = rect2.x; + y = rect2.y; + + this.vertices[0] = x; + this.vertices[1] = y; + + this.vertices[2] = x + rect2.width; + this.vertices[3] = y; + + this.vertices[4] = x + rect2.width; + this.vertices[5] = y + rect2.height; + + this.vertices[6] = x; + this.vertices[7] = y + rect2.height; + + this.upload(); +} + +Quad.prototype.upload = function() +{ + var gl = this.gl; + + gl.bindBuffer( gl.ARRAY_BUFFER, this.vertexBuffer ); + + gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertices); + + gl.bufferSubData(gl.ARRAY_BUFFER, 8 * 4, this.uvs); + + gl.bufferSubData(gl.ARRAY_BUFFER, (8 + 8) * 4, this.colors); +} + +module.exports = Quad; + + diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index 20e778c..1413a28 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -249,6 +249,8 @@ }, set: function (value) { + this._filters = value; + /* if (value) { // now put all the passes in one place.. @@ -268,7 +270,7 @@ this._filterBlock = { target: this, filterPasses: passes }; } - this._filters = value; + this._filters = value;*/ } } }); diff --git a/src/core/display/DisplayObjectContainer.js b/src/core/display/DisplayObjectContainer.js index 120c9ff..4af3f82 100644 --- a/src/core/display/DisplayObjectContainer.js +++ b/src/core/display/DisplayObjectContainer.js @@ -500,8 +500,9 @@ // push filter first as we need to ensure the stencil buffer is correct for any masking if (this._filters) { - renderer.plugins.sprite.flush(); - renderer.filterManager.pushFilter(this._filterBlock); + renderer.currentRenderer.flush(); + renderer.filterManager.pushFilter(this, this._filters); + renderer.currentRenderer.start(); } if (this._mask) @@ -526,7 +527,9 @@ if (this._filters) { + renderer.currentRenderer.flush(); renderer.filterManager.popFilter(); + renderer.currentRenderer.start(); } } diff --git a/src/core/graphics/webgl/GraphicsRenderer.js b/src/core/graphics/webgl/GraphicsRenderer.js index c81350b..a63640e 100644 --- a/src/core/graphics/webgl/GraphicsRenderer.js +++ b/src/core/graphics/webgl/GraphicsRenderer.js @@ -3,7 +3,9 @@ CONST = require('../../const'), ObjectRenderer = require('../../renderers/webgl/utils/ObjectRenderer'), WebGLRenderer = require('../../renderers/webgl/WebGLRenderer'), - WebGLGraphicsData = require('./WebGLGraphicsData'); + WebGLGraphicsData = require('./WebGLGraphicsData'), + ComplexPrimitiveShader = require('./ComplexPrimitiveShader'), + PrimitiveShader = require('./PrimitiveShader'); /** * Renders the graphics object. diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 13892a6..8ff6208 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -194,6 +194,9 @@ */ this.filterManager = new WebGLFilterManager(this); + //TODO FIX THIS EVENT>> + this.filterManager.initShaderBuffers(); + /** * Manages the blendModes * @member {WebGLBlendModeManager} @@ -308,9 +311,6 @@ var gl = this.gl; - // -- Does this need to be set every frame? -- // - gl.viewport(0, 0, this.width, this.height); - // make sure we are bound to the main frame buffer gl.bindFramebuffer(gl.FRAMEBUFFER, null); @@ -344,11 +344,13 @@ this.currentRenderTarget = renderTarget; + this.currentRenderTarget.activate(); + // reset the render session data.. this.drawCount = 0; // start the filter manager - // this.filterManager.begin(renderTarget.frameBuffer); + this.filterManager.begin()//renderTarget.frameBuffer); // render the scene! displayObject.renderWebGL(this); diff --git a/src/core/renderers/webgl/managers/Quad.js b/src/core/renderers/webgl/managers/Quad.js new file mode 100644 index 0000000..b2fae63 --- /dev/null +++ b/src/core/renderers/webgl/managers/Quad.js @@ -0,0 +1,107 @@ +var WebGLManager = require('./WebGLManager'), + utils = require('../../../utils'); + +/** + * @class + * @namespace PIXI + * @param renderer {WebGLRenderer} The renderer this manager works for. + */ +function Quad(gl) +{ + this.gl = gl; + +// this.textures = new TextureUvs(); + + this.vertices = new Float32Array([ + 0,0, + 200,0, + 200,200, + 0,200 + ]); + + this.uvs = new Float32Array([ + 0,0, + 1,0, + 1,1, + 0,1 + ]); + + var white = (0xFFFFFF >> 16) + (0xFFFFFF & 0xff00) + ((0xFFFFFF & 0xff) << 16) + (1 * 255 << 24); + + this.colors = new Float32Array([ + white, + white, + white, + white + ]) + + this.indices = new Uint16Array([ + 0, 1, 2, 0, 3, 2 + ]); + + this.vertexBuffer = gl.createBuffer(); + this.indexBuffer = gl.createBuffer(); + + gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER, (8 + 8 + 4) * 4, gl.DYNAMIC_DRAW); + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW); + + this.upload(); +} + +Quad.prototype.constructor = Quad; + +Quad.prototype.map = function(rect, rect2) +{ + var x = 0//rect2.x / rect.width; + var y = 0//rect2.y / rect.height; + + this.uvs[0] = x; + this.uvs[1] = y; + + this.uvs[2] = x + rect2.width / rect.width; + this.uvs[3] = y; + + this.uvs[4] = x + rect2.width / rect.width; + this.uvs[5] = y + rect2.height / rect.height; + + this.uvs[6] = x; + this.uvs[7] = y + rect2.height / rect.height; + + /// ----- + x = rect2.x; + y = rect2.y; + + this.vertices[0] = x; + this.vertices[1] = y; + + this.vertices[2] = x + rect2.width; + this.vertices[3] = y; + + this.vertices[4] = x + rect2.width; + this.vertices[5] = y + rect2.height; + + this.vertices[6] = x; + this.vertices[7] = y + rect2.height; + + this.upload(); +} + +Quad.prototype.upload = function() +{ + var gl = this.gl; + + gl.bindBuffer( gl.ARRAY_BUFFER, this.vertexBuffer ); + + gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertices); + + gl.bufferSubData(gl.ARRAY_BUFFER, 8 * 4, this.uvs); + + gl.bufferSubData(gl.ARRAY_BUFFER, (8 + 8) * 4, this.colors); +} + +module.exports = Quad; + + diff --git a/src/core/renderers/webgl/managers/WebGLFilterManager.js b/src/core/renderers/webgl/managers/WebGLFilterManager.js index d6ed3c6..b91b80a 100644 --- a/src/core/renderers/webgl/managers/WebGLFilterManager.js +++ b/src/core/renderers/webgl/managers/WebGLFilterManager.js @@ -1,7 +1,9 @@ var WebGLManager = require('./WebGLManager'), FilterTexture = require('../utils/FilterTexture'), RenderTarget = require('../utils/RenderTarget'); - Shader = require('../shaders/Shader'); + Shader = require('../shaders/Shader'), + Quad = require('./Quad'), + math = require('../../../math'); /** * @class @@ -17,21 +19,17 @@ */ this.filterStack = []; + this.filterStack.push({ + renderTarget:renderer.currentRenderTarget, + filter:[], + bounds:null + }); + /** * @member {any[]]} */ this.texturePool = []; - /** - * @member {number} - */ - this.offsetX = 0; - - /** - * @member {number} - */ - this.offsetY = 0; - // listen for context and update necessary buffers var self = this; this.renderer.on('context', function () @@ -39,6 +37,10 @@ self.texturePool.length = 0; self.initShaderBuffers(); }); + + this.textureSize = new math.Rectangle(0,0,800, 600); + + } WebGLFilterManager.prototype = Object.create(WebGLManager.prototype); @@ -51,12 +53,10 @@ */ WebGLFilterManager.prototype.begin = function (buffer) { - this.defaultShader = this.renderer.shaderManager.plugins.defaultShader; - - this.width = this.renderer.projection.x * 2; - this.height = -this.renderer.projection.y * 2; - - this.buffer = buffer; +// this.defaultShader = this.renderer.shaderManager.plugins.defaultShader; + //console.log("<-------->") + this.filterStack[0].renderTarget = this.renderer.currentRenderTarget; + this.filterStack[0].bounds = new math.Rectangle(0, 0, this.renderer.currentRenderTarget.width, this.renderer.currentRenderTarget.height); }; /** @@ -67,25 +67,114 @@ WebGLFilterManager.prototype.pushFilter = function (target, filters) { var gl = this.renderer.gl; - - var texture = this.texturePool.pop(); - + //console.log("push") // get the bounds of the object.. var bounds = target.filterArea || target.getBounds(); - if (!texture) + this.realSize = bounds;//.clone(); + + var texture = this.texturePool.pop() || new RenderTarget(this.renderer.gl, this.textureSize.width, this.textureSize.height); + + // texture. + // TODO setting frame is lame.. + texture.frame = bounds;//new math.Rectangle(, 0, this.realSize.width, this.realSize.height); + texture.activate(); + texture.clear(); + texture.frame = null; + + this.renderer.currentRenderTarget = texture; + + + + // TODO get rid of object creation! + this.filterStack.push({ + renderTarget:texture, + filter:filters, + bounds:bounds + }); + +}; + + +/** + * Removes the last filter from the filter stack and doesn't return it. + * + */ +WebGLFilterManager.prototype.popFilter = function () +{ + var filterData = this.filterStack.pop(); + + + var input = filterData.renderTarget; + + // use program + var gl = this.renderer.gl; + var filter = filterData.filter[0]; + var shader = filter.shaders[gl.id]; + + // shader.syncUniforms(); + + + this.quad.map(this.textureSize, filterData.bounds); + + // + // + if (!shader) { - texture = new RenderTarget(this.renderer.gl, bounds.width, bounds.height); - } - else - { - texture.resize(bounds.width, bounds.height); + shader = new Shader(this, + filter.vertexSrc, + filter.fragmentSrc, + filter.uniforms, + filter.attributes + ); + + filter.shaders[gl.id] = shader; } - this.texture = texture; + // set the shader + this.renderer.shaderManager.setShader(shader); - this.texture.activate(); - // this.texture. + // RENDER + + gl.bindBuffer(gl.ARRAY_BUFFER, this.quad.vertexBuffer); + + gl.vertexAttribPointer(shader.attributes.aVertexPosition, 2, gl.FLOAT, false, 0, 0); + gl.vertexAttribPointer(shader.attributes.aTextureCoord, 2, gl.FLOAT, false, 0, 2 * 4 * 4); + gl.vertexAttribPointer(shader.attributes.aColor, 1, gl.FLOAT, false, 0, 0); + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.quad.indexBuffer); + + // draw the filter... + + var previousFilter = this.filterStack[this.filterStack.length-1]; + + this.renderer.currentRenderTarget = previousFilter.renderTarget; + + this.renderer.currentRenderTarget.frame = previousFilter.bounds; + this.renderer.currentRenderTarget.activate(); + this.renderer.currentRenderTarget.frame = null; + + gl.uniformMatrix3fv(shader.uniforms.projectionMatrix._location, false, this.renderer.currentRenderTarget.projectionMatrix.toArray(true)); + + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, input.texture); + + gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); + + this.texturePool.push(filterData.renderTarget); +}; + + +// this.projectionMatrix.d = 1/height*2; + // offset.. + + + + + // ----- // + + + // this.texture. /* var projection = this.renderer.projection; var offset = this.renderer.offset; @@ -180,18 +269,9 @@ filterBlock._glFilterTexture = texture; ` */ -}; -/** - * Removes the last filter from the filter stack and doesn't return it. - * - */ -WebGLFilterManager.prototype.popFilter = function () -{ - this.texturePool.push(this.texture); + // this.texturePool.push(output); - this.renderer.currentRenderTarget.activate(); - /* var gl = this.renderer.gl; @@ -362,11 +442,8 @@ // gl.uniform2f(this.defaultShader.offsetVector, -offsetX, -offsetY); // return the texture to the pool - this.texturePool.push(texture); filterBlock._glFilterTexture = null; */ -}; - /** * Applies the filter to the specified area. @@ -437,7 +514,9 @@ { var gl = this.renderer.gl; - // create some buffers + this.quad = new Quad(gl); + + // create some buffers this.vertexBuffer = gl.createBuffer(); this.uvBuffer = gl.createBuffer(); this.colorBuffer = gl.createBuffer(); diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index 20e778c..1413a28 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -249,6 +249,8 @@ }, set: function (value) { + this._filters = value; + /* if (value) { // now put all the passes in one place.. @@ -268,7 +270,7 @@ this._filterBlock = { target: this, filterPasses: passes }; } - this._filters = value; + this._filters = value;*/ } } }); diff --git a/src/core/display/DisplayObjectContainer.js b/src/core/display/DisplayObjectContainer.js index 120c9ff..4af3f82 100644 --- a/src/core/display/DisplayObjectContainer.js +++ b/src/core/display/DisplayObjectContainer.js @@ -500,8 +500,9 @@ // push filter first as we need to ensure the stencil buffer is correct for any masking if (this._filters) { - renderer.plugins.sprite.flush(); - renderer.filterManager.pushFilter(this._filterBlock); + renderer.currentRenderer.flush(); + renderer.filterManager.pushFilter(this, this._filters); + renderer.currentRenderer.start(); } if (this._mask) @@ -526,7 +527,9 @@ if (this._filters) { + renderer.currentRenderer.flush(); renderer.filterManager.popFilter(); + renderer.currentRenderer.start(); } } diff --git a/src/core/graphics/webgl/GraphicsRenderer.js b/src/core/graphics/webgl/GraphicsRenderer.js index c81350b..a63640e 100644 --- a/src/core/graphics/webgl/GraphicsRenderer.js +++ b/src/core/graphics/webgl/GraphicsRenderer.js @@ -3,7 +3,9 @@ CONST = require('../../const'), ObjectRenderer = require('../../renderers/webgl/utils/ObjectRenderer'), WebGLRenderer = require('../../renderers/webgl/WebGLRenderer'), - WebGLGraphicsData = require('./WebGLGraphicsData'); + WebGLGraphicsData = require('./WebGLGraphicsData'), + ComplexPrimitiveShader = require('./ComplexPrimitiveShader'), + PrimitiveShader = require('./PrimitiveShader'); /** * Renders the graphics object. diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 13892a6..8ff6208 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -194,6 +194,9 @@ */ this.filterManager = new WebGLFilterManager(this); + //TODO FIX THIS EVENT>> + this.filterManager.initShaderBuffers(); + /** * Manages the blendModes * @member {WebGLBlendModeManager} @@ -308,9 +311,6 @@ var gl = this.gl; - // -- Does this need to be set every frame? -- // - gl.viewport(0, 0, this.width, this.height); - // make sure we are bound to the main frame buffer gl.bindFramebuffer(gl.FRAMEBUFFER, null); @@ -344,11 +344,13 @@ this.currentRenderTarget = renderTarget; + this.currentRenderTarget.activate(); + // reset the render session data.. this.drawCount = 0; // start the filter manager - // this.filterManager.begin(renderTarget.frameBuffer); + this.filterManager.begin()//renderTarget.frameBuffer); // render the scene! displayObject.renderWebGL(this); diff --git a/src/core/renderers/webgl/managers/Quad.js b/src/core/renderers/webgl/managers/Quad.js new file mode 100644 index 0000000..b2fae63 --- /dev/null +++ b/src/core/renderers/webgl/managers/Quad.js @@ -0,0 +1,107 @@ +var WebGLManager = require('./WebGLManager'), + utils = require('../../../utils'); + +/** + * @class + * @namespace PIXI + * @param renderer {WebGLRenderer} The renderer this manager works for. + */ +function Quad(gl) +{ + this.gl = gl; + +// this.textures = new TextureUvs(); + + this.vertices = new Float32Array([ + 0,0, + 200,0, + 200,200, + 0,200 + ]); + + this.uvs = new Float32Array([ + 0,0, + 1,0, + 1,1, + 0,1 + ]); + + var white = (0xFFFFFF >> 16) + (0xFFFFFF & 0xff00) + ((0xFFFFFF & 0xff) << 16) + (1 * 255 << 24); + + this.colors = new Float32Array([ + white, + white, + white, + white + ]) + + this.indices = new Uint16Array([ + 0, 1, 2, 0, 3, 2 + ]); + + this.vertexBuffer = gl.createBuffer(); + this.indexBuffer = gl.createBuffer(); + + gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER, (8 + 8 + 4) * 4, gl.DYNAMIC_DRAW); + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW); + + this.upload(); +} + +Quad.prototype.constructor = Quad; + +Quad.prototype.map = function(rect, rect2) +{ + var x = 0//rect2.x / rect.width; + var y = 0//rect2.y / rect.height; + + this.uvs[0] = x; + this.uvs[1] = y; + + this.uvs[2] = x + rect2.width / rect.width; + this.uvs[3] = y; + + this.uvs[4] = x + rect2.width / rect.width; + this.uvs[5] = y + rect2.height / rect.height; + + this.uvs[6] = x; + this.uvs[7] = y + rect2.height / rect.height; + + /// ----- + x = rect2.x; + y = rect2.y; + + this.vertices[0] = x; + this.vertices[1] = y; + + this.vertices[2] = x + rect2.width; + this.vertices[3] = y; + + this.vertices[4] = x + rect2.width; + this.vertices[5] = y + rect2.height; + + this.vertices[6] = x; + this.vertices[7] = y + rect2.height; + + this.upload(); +} + +Quad.prototype.upload = function() +{ + var gl = this.gl; + + gl.bindBuffer( gl.ARRAY_BUFFER, this.vertexBuffer ); + + gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertices); + + gl.bufferSubData(gl.ARRAY_BUFFER, 8 * 4, this.uvs); + + gl.bufferSubData(gl.ARRAY_BUFFER, (8 + 8) * 4, this.colors); +} + +module.exports = Quad; + + diff --git a/src/core/renderers/webgl/managers/WebGLFilterManager.js b/src/core/renderers/webgl/managers/WebGLFilterManager.js index d6ed3c6..b91b80a 100644 --- a/src/core/renderers/webgl/managers/WebGLFilterManager.js +++ b/src/core/renderers/webgl/managers/WebGLFilterManager.js @@ -1,7 +1,9 @@ var WebGLManager = require('./WebGLManager'), FilterTexture = require('../utils/FilterTexture'), RenderTarget = require('../utils/RenderTarget'); - Shader = require('../shaders/Shader'); + Shader = require('../shaders/Shader'), + Quad = require('./Quad'), + math = require('../../../math'); /** * @class @@ -17,21 +19,17 @@ */ this.filterStack = []; + this.filterStack.push({ + renderTarget:renderer.currentRenderTarget, + filter:[], + bounds:null + }); + /** * @member {any[]]} */ this.texturePool = []; - /** - * @member {number} - */ - this.offsetX = 0; - - /** - * @member {number} - */ - this.offsetY = 0; - // listen for context and update necessary buffers var self = this; this.renderer.on('context', function () @@ -39,6 +37,10 @@ self.texturePool.length = 0; self.initShaderBuffers(); }); + + this.textureSize = new math.Rectangle(0,0,800, 600); + + } WebGLFilterManager.prototype = Object.create(WebGLManager.prototype); @@ -51,12 +53,10 @@ */ WebGLFilterManager.prototype.begin = function (buffer) { - this.defaultShader = this.renderer.shaderManager.plugins.defaultShader; - - this.width = this.renderer.projection.x * 2; - this.height = -this.renderer.projection.y * 2; - - this.buffer = buffer; +// this.defaultShader = this.renderer.shaderManager.plugins.defaultShader; + //console.log("<-------->") + this.filterStack[0].renderTarget = this.renderer.currentRenderTarget; + this.filterStack[0].bounds = new math.Rectangle(0, 0, this.renderer.currentRenderTarget.width, this.renderer.currentRenderTarget.height); }; /** @@ -67,25 +67,114 @@ WebGLFilterManager.prototype.pushFilter = function (target, filters) { var gl = this.renderer.gl; - - var texture = this.texturePool.pop(); - + //console.log("push") // get the bounds of the object.. var bounds = target.filterArea || target.getBounds(); - if (!texture) + this.realSize = bounds;//.clone(); + + var texture = this.texturePool.pop() || new RenderTarget(this.renderer.gl, this.textureSize.width, this.textureSize.height); + + // texture. + // TODO setting frame is lame.. + texture.frame = bounds;//new math.Rectangle(, 0, this.realSize.width, this.realSize.height); + texture.activate(); + texture.clear(); + texture.frame = null; + + this.renderer.currentRenderTarget = texture; + + + + // TODO get rid of object creation! + this.filterStack.push({ + renderTarget:texture, + filter:filters, + bounds:bounds + }); + +}; + + +/** + * Removes the last filter from the filter stack and doesn't return it. + * + */ +WebGLFilterManager.prototype.popFilter = function () +{ + var filterData = this.filterStack.pop(); + + + var input = filterData.renderTarget; + + // use program + var gl = this.renderer.gl; + var filter = filterData.filter[0]; + var shader = filter.shaders[gl.id]; + + // shader.syncUniforms(); + + + this.quad.map(this.textureSize, filterData.bounds); + + // + // + if (!shader) { - texture = new RenderTarget(this.renderer.gl, bounds.width, bounds.height); - } - else - { - texture.resize(bounds.width, bounds.height); + shader = new Shader(this, + filter.vertexSrc, + filter.fragmentSrc, + filter.uniforms, + filter.attributes + ); + + filter.shaders[gl.id] = shader; } - this.texture = texture; + // set the shader + this.renderer.shaderManager.setShader(shader); - this.texture.activate(); - // this.texture. + // RENDER + + gl.bindBuffer(gl.ARRAY_BUFFER, this.quad.vertexBuffer); + + gl.vertexAttribPointer(shader.attributes.aVertexPosition, 2, gl.FLOAT, false, 0, 0); + gl.vertexAttribPointer(shader.attributes.aTextureCoord, 2, gl.FLOAT, false, 0, 2 * 4 * 4); + gl.vertexAttribPointer(shader.attributes.aColor, 1, gl.FLOAT, false, 0, 0); + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.quad.indexBuffer); + + // draw the filter... + + var previousFilter = this.filterStack[this.filterStack.length-1]; + + this.renderer.currentRenderTarget = previousFilter.renderTarget; + + this.renderer.currentRenderTarget.frame = previousFilter.bounds; + this.renderer.currentRenderTarget.activate(); + this.renderer.currentRenderTarget.frame = null; + + gl.uniformMatrix3fv(shader.uniforms.projectionMatrix._location, false, this.renderer.currentRenderTarget.projectionMatrix.toArray(true)); + + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, input.texture); + + gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); + + this.texturePool.push(filterData.renderTarget); +}; + + +// this.projectionMatrix.d = 1/height*2; + // offset.. + + + + + // ----- // + + + // this.texture. /* var projection = this.renderer.projection; var offset = this.renderer.offset; @@ -180,18 +269,9 @@ filterBlock._glFilterTexture = texture; ` */ -}; -/** - * Removes the last filter from the filter stack and doesn't return it. - * - */ -WebGLFilterManager.prototype.popFilter = function () -{ - this.texturePool.push(this.texture); + // this.texturePool.push(output); - this.renderer.currentRenderTarget.activate(); - /* var gl = this.renderer.gl; @@ -362,11 +442,8 @@ // gl.uniform2f(this.defaultShader.offsetVector, -offsetX, -offsetY); // return the texture to the pool - this.texturePool.push(texture); filterBlock._glFilterTexture = null; */ -}; - /** * Applies the filter to the specified area. @@ -437,7 +514,9 @@ { var gl = this.renderer.gl; - // create some buffers + this.quad = new Quad(gl); + + // create some buffers this.vertexBuffer = gl.createBuffer(); this.uvBuffer = gl.createBuffer(); this.colorBuffer = gl.createBuffer(); diff --git a/src/core/renderers/webgl/shaders/Shader.js b/src/core/renderers/webgl/shaders/Shader.js index 84f321f..4452369 100644 --- a/src/core/renderers/webgl/shaders/Shader.js +++ b/src/core/renderers/webgl/shaders/Shader.js @@ -10,6 +10,7 @@ * @param customUniforms {object} Custom uniforms to use to augment the built-in ones. * @param [fragmentSrc] {string} The source of the fragment shader. */ +//TODO change shaderManager to gl function Shader(shaderManager, vertexSrc, fragmentSrc, customUniforms, customAttributes) { /** @@ -119,6 +120,11 @@ this.cacheUniformLocations(Object.keys(this.uniforms)); this.cacheAttributeLocations(Object.keys(this.attributes)); + + + //this.buildSync(); + + // console.log(this.syncUniforms) }; Shader.prototype.cacheUniformLocations = function (keys) @@ -188,6 +194,29 @@ return (this.program = program); }; +Shader.prototype.buildSync = function () +{ + var str = "" + + str = "Shader.prototype.syncUniforms = function()"; + str += "{\n"; + + for (var key in this.uniforms) + { + var uniform = this.uniforms[key]; + // location = uniform._location, + // value = uniform.value, + //i, il; + + str += "gl.uniform1i(this.uniforms."+ key +"._location, this.uniforms." + key + ".value );\n" + + } + + str += "}"; + // console.log(str) + eval(str); +} + Shader.prototype.syncUniforms = function () { var gl = this.gl; diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index 20e778c..1413a28 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -249,6 +249,8 @@ }, set: function (value) { + this._filters = value; + /* if (value) { // now put all the passes in one place.. @@ -268,7 +270,7 @@ this._filterBlock = { target: this, filterPasses: passes }; } - this._filters = value; + this._filters = value;*/ } } }); diff --git a/src/core/display/DisplayObjectContainer.js b/src/core/display/DisplayObjectContainer.js index 120c9ff..4af3f82 100644 --- a/src/core/display/DisplayObjectContainer.js +++ b/src/core/display/DisplayObjectContainer.js @@ -500,8 +500,9 @@ // push filter first as we need to ensure the stencil buffer is correct for any masking if (this._filters) { - renderer.plugins.sprite.flush(); - renderer.filterManager.pushFilter(this._filterBlock); + renderer.currentRenderer.flush(); + renderer.filterManager.pushFilter(this, this._filters); + renderer.currentRenderer.start(); } if (this._mask) @@ -526,7 +527,9 @@ if (this._filters) { + renderer.currentRenderer.flush(); renderer.filterManager.popFilter(); + renderer.currentRenderer.start(); } } diff --git a/src/core/graphics/webgl/GraphicsRenderer.js b/src/core/graphics/webgl/GraphicsRenderer.js index c81350b..a63640e 100644 --- a/src/core/graphics/webgl/GraphicsRenderer.js +++ b/src/core/graphics/webgl/GraphicsRenderer.js @@ -3,7 +3,9 @@ CONST = require('../../const'), ObjectRenderer = require('../../renderers/webgl/utils/ObjectRenderer'), WebGLRenderer = require('../../renderers/webgl/WebGLRenderer'), - WebGLGraphicsData = require('./WebGLGraphicsData'); + WebGLGraphicsData = require('./WebGLGraphicsData'), + ComplexPrimitiveShader = require('./ComplexPrimitiveShader'), + PrimitiveShader = require('./PrimitiveShader'); /** * Renders the graphics object. diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 13892a6..8ff6208 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -194,6 +194,9 @@ */ this.filterManager = new WebGLFilterManager(this); + //TODO FIX THIS EVENT>> + this.filterManager.initShaderBuffers(); + /** * Manages the blendModes * @member {WebGLBlendModeManager} @@ -308,9 +311,6 @@ var gl = this.gl; - // -- Does this need to be set every frame? -- // - gl.viewport(0, 0, this.width, this.height); - // make sure we are bound to the main frame buffer gl.bindFramebuffer(gl.FRAMEBUFFER, null); @@ -344,11 +344,13 @@ this.currentRenderTarget = renderTarget; + this.currentRenderTarget.activate(); + // reset the render session data.. this.drawCount = 0; // start the filter manager - // this.filterManager.begin(renderTarget.frameBuffer); + this.filterManager.begin()//renderTarget.frameBuffer); // render the scene! displayObject.renderWebGL(this); diff --git a/src/core/renderers/webgl/managers/Quad.js b/src/core/renderers/webgl/managers/Quad.js new file mode 100644 index 0000000..b2fae63 --- /dev/null +++ b/src/core/renderers/webgl/managers/Quad.js @@ -0,0 +1,107 @@ +var WebGLManager = require('./WebGLManager'), + utils = require('../../../utils'); + +/** + * @class + * @namespace PIXI + * @param renderer {WebGLRenderer} The renderer this manager works for. + */ +function Quad(gl) +{ + this.gl = gl; + +// this.textures = new TextureUvs(); + + this.vertices = new Float32Array([ + 0,0, + 200,0, + 200,200, + 0,200 + ]); + + this.uvs = new Float32Array([ + 0,0, + 1,0, + 1,1, + 0,1 + ]); + + var white = (0xFFFFFF >> 16) + (0xFFFFFF & 0xff00) + ((0xFFFFFF & 0xff) << 16) + (1 * 255 << 24); + + this.colors = new Float32Array([ + white, + white, + white, + white + ]) + + this.indices = new Uint16Array([ + 0, 1, 2, 0, 3, 2 + ]); + + this.vertexBuffer = gl.createBuffer(); + this.indexBuffer = gl.createBuffer(); + + gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER, (8 + 8 + 4) * 4, gl.DYNAMIC_DRAW); + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW); + + this.upload(); +} + +Quad.prototype.constructor = Quad; + +Quad.prototype.map = function(rect, rect2) +{ + var x = 0//rect2.x / rect.width; + var y = 0//rect2.y / rect.height; + + this.uvs[0] = x; + this.uvs[1] = y; + + this.uvs[2] = x + rect2.width / rect.width; + this.uvs[3] = y; + + this.uvs[4] = x + rect2.width / rect.width; + this.uvs[5] = y + rect2.height / rect.height; + + this.uvs[6] = x; + this.uvs[7] = y + rect2.height / rect.height; + + /// ----- + x = rect2.x; + y = rect2.y; + + this.vertices[0] = x; + this.vertices[1] = y; + + this.vertices[2] = x + rect2.width; + this.vertices[3] = y; + + this.vertices[4] = x + rect2.width; + this.vertices[5] = y + rect2.height; + + this.vertices[6] = x; + this.vertices[7] = y + rect2.height; + + this.upload(); +} + +Quad.prototype.upload = function() +{ + var gl = this.gl; + + gl.bindBuffer( gl.ARRAY_BUFFER, this.vertexBuffer ); + + gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertices); + + gl.bufferSubData(gl.ARRAY_BUFFER, 8 * 4, this.uvs); + + gl.bufferSubData(gl.ARRAY_BUFFER, (8 + 8) * 4, this.colors); +} + +module.exports = Quad; + + diff --git a/src/core/renderers/webgl/managers/WebGLFilterManager.js b/src/core/renderers/webgl/managers/WebGLFilterManager.js index d6ed3c6..b91b80a 100644 --- a/src/core/renderers/webgl/managers/WebGLFilterManager.js +++ b/src/core/renderers/webgl/managers/WebGLFilterManager.js @@ -1,7 +1,9 @@ var WebGLManager = require('./WebGLManager'), FilterTexture = require('../utils/FilterTexture'), RenderTarget = require('../utils/RenderTarget'); - Shader = require('../shaders/Shader'); + Shader = require('../shaders/Shader'), + Quad = require('./Quad'), + math = require('../../../math'); /** * @class @@ -17,21 +19,17 @@ */ this.filterStack = []; + this.filterStack.push({ + renderTarget:renderer.currentRenderTarget, + filter:[], + bounds:null + }); + /** * @member {any[]]} */ this.texturePool = []; - /** - * @member {number} - */ - this.offsetX = 0; - - /** - * @member {number} - */ - this.offsetY = 0; - // listen for context and update necessary buffers var self = this; this.renderer.on('context', function () @@ -39,6 +37,10 @@ self.texturePool.length = 0; self.initShaderBuffers(); }); + + this.textureSize = new math.Rectangle(0,0,800, 600); + + } WebGLFilterManager.prototype = Object.create(WebGLManager.prototype); @@ -51,12 +53,10 @@ */ WebGLFilterManager.prototype.begin = function (buffer) { - this.defaultShader = this.renderer.shaderManager.plugins.defaultShader; - - this.width = this.renderer.projection.x * 2; - this.height = -this.renderer.projection.y * 2; - - this.buffer = buffer; +// this.defaultShader = this.renderer.shaderManager.plugins.defaultShader; + //console.log("<-------->") + this.filterStack[0].renderTarget = this.renderer.currentRenderTarget; + this.filterStack[0].bounds = new math.Rectangle(0, 0, this.renderer.currentRenderTarget.width, this.renderer.currentRenderTarget.height); }; /** @@ -67,25 +67,114 @@ WebGLFilterManager.prototype.pushFilter = function (target, filters) { var gl = this.renderer.gl; - - var texture = this.texturePool.pop(); - + //console.log("push") // get the bounds of the object.. var bounds = target.filterArea || target.getBounds(); - if (!texture) + this.realSize = bounds;//.clone(); + + var texture = this.texturePool.pop() || new RenderTarget(this.renderer.gl, this.textureSize.width, this.textureSize.height); + + // texture. + // TODO setting frame is lame.. + texture.frame = bounds;//new math.Rectangle(, 0, this.realSize.width, this.realSize.height); + texture.activate(); + texture.clear(); + texture.frame = null; + + this.renderer.currentRenderTarget = texture; + + + + // TODO get rid of object creation! + this.filterStack.push({ + renderTarget:texture, + filter:filters, + bounds:bounds + }); + +}; + + +/** + * Removes the last filter from the filter stack and doesn't return it. + * + */ +WebGLFilterManager.prototype.popFilter = function () +{ + var filterData = this.filterStack.pop(); + + + var input = filterData.renderTarget; + + // use program + var gl = this.renderer.gl; + var filter = filterData.filter[0]; + var shader = filter.shaders[gl.id]; + + // shader.syncUniforms(); + + + this.quad.map(this.textureSize, filterData.bounds); + + // + // + if (!shader) { - texture = new RenderTarget(this.renderer.gl, bounds.width, bounds.height); - } - else - { - texture.resize(bounds.width, bounds.height); + shader = new Shader(this, + filter.vertexSrc, + filter.fragmentSrc, + filter.uniforms, + filter.attributes + ); + + filter.shaders[gl.id] = shader; } - this.texture = texture; + // set the shader + this.renderer.shaderManager.setShader(shader); - this.texture.activate(); - // this.texture. + // RENDER + + gl.bindBuffer(gl.ARRAY_BUFFER, this.quad.vertexBuffer); + + gl.vertexAttribPointer(shader.attributes.aVertexPosition, 2, gl.FLOAT, false, 0, 0); + gl.vertexAttribPointer(shader.attributes.aTextureCoord, 2, gl.FLOAT, false, 0, 2 * 4 * 4); + gl.vertexAttribPointer(shader.attributes.aColor, 1, gl.FLOAT, false, 0, 0); + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.quad.indexBuffer); + + // draw the filter... + + var previousFilter = this.filterStack[this.filterStack.length-1]; + + this.renderer.currentRenderTarget = previousFilter.renderTarget; + + this.renderer.currentRenderTarget.frame = previousFilter.bounds; + this.renderer.currentRenderTarget.activate(); + this.renderer.currentRenderTarget.frame = null; + + gl.uniformMatrix3fv(shader.uniforms.projectionMatrix._location, false, this.renderer.currentRenderTarget.projectionMatrix.toArray(true)); + + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, input.texture); + + gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); + + this.texturePool.push(filterData.renderTarget); +}; + + +// this.projectionMatrix.d = 1/height*2; + // offset.. + + + + + // ----- // + + + // this.texture. /* var projection = this.renderer.projection; var offset = this.renderer.offset; @@ -180,18 +269,9 @@ filterBlock._glFilterTexture = texture; ` */ -}; -/** - * Removes the last filter from the filter stack and doesn't return it. - * - */ -WebGLFilterManager.prototype.popFilter = function () -{ - this.texturePool.push(this.texture); + // this.texturePool.push(output); - this.renderer.currentRenderTarget.activate(); - /* var gl = this.renderer.gl; @@ -362,11 +442,8 @@ // gl.uniform2f(this.defaultShader.offsetVector, -offsetX, -offsetY); // return the texture to the pool - this.texturePool.push(texture); filterBlock._glFilterTexture = null; */ -}; - /** * Applies the filter to the specified area. @@ -437,7 +514,9 @@ { var gl = this.renderer.gl; - // create some buffers + this.quad = new Quad(gl); + + // create some buffers this.vertexBuffer = gl.createBuffer(); this.uvBuffer = gl.createBuffer(); this.colorBuffer = gl.createBuffer(); diff --git a/src/core/renderers/webgl/shaders/Shader.js b/src/core/renderers/webgl/shaders/Shader.js index 84f321f..4452369 100644 --- a/src/core/renderers/webgl/shaders/Shader.js +++ b/src/core/renderers/webgl/shaders/Shader.js @@ -10,6 +10,7 @@ * @param customUniforms {object} Custom uniforms to use to augment the built-in ones. * @param [fragmentSrc] {string} The source of the fragment shader. */ +//TODO change shaderManager to gl function Shader(shaderManager, vertexSrc, fragmentSrc, customUniforms, customAttributes) { /** @@ -119,6 +120,11 @@ this.cacheUniformLocations(Object.keys(this.uniforms)); this.cacheAttributeLocations(Object.keys(this.attributes)); + + + //this.buildSync(); + + // console.log(this.syncUniforms) }; Shader.prototype.cacheUniformLocations = function (keys) @@ -188,6 +194,29 @@ return (this.program = program); }; +Shader.prototype.buildSync = function () +{ + var str = "" + + str = "Shader.prototype.syncUniforms = function()"; + str += "{\n"; + + for (var key in this.uniforms) + { + var uniform = this.uniforms[key]; + // location = uniform._location, + // value = uniform.value, + //i, il; + + str += "gl.uniform1i(this.uniforms."+ key +"._location, this.uniforms." + key + ".value );\n" + + } + + str += "}"; + // console.log(str) + eval(str); +} + Shader.prototype.syncUniforms = function () { var gl = this.gl; diff --git a/src/core/renderers/webgl/utils/RenderTarget.js b/src/core/renderers/webgl/utils/RenderTarget.js index fa7ddf4..5b3929f 100644 --- a/src/core/renderers/webgl/utils/RenderTarget.js +++ b/src/core/renderers/webgl/utils/RenderTarget.js @@ -42,6 +42,8 @@ this.projectionMatrix = new math.Matrix(); + this.frame = null; + /** * @property scaleMode * @type Number @@ -101,13 +103,68 @@ { var gl = this.gl; - gl.clearColor(0,0,0, 0); + gl.clearColor(0,0,0,0); gl.clear(gl.COLOR_BUFFER_BIT); }; RenderTarget.prototype.activate = function() { - this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.frameBuffer); + //TOOD refactor usage of frame.. + var gl = this.gl; + gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer); + + + if(this.frame) + { + // gl.viewport(this.frame.x, this.frame.y, this.frame.width, this.frame.height); + + gl.viewport(0,0, this.frame.width, this.frame.height); + + if (!this.root) + { + + this.projectionMatrix.a = 1/(this.frame.width)*2; + this.projectionMatrix.d = 1/(this.frame.height)*2; + + this.projectionMatrix.tx = -1 - this.frame.x * this.projectionMatrix.a; + this.projectionMatrix.ty = -1 - this.frame.y * this.projectionMatrix.d; + } + else + { + this.projectionMatrix.a = 1/(this.frame.width)*2; + this.projectionMatrix.d = -1/(this.frame.height)*2; + + this.projectionMatrix.tx = -1 - this.frame.x * this.projectionMatrix.a; + this.projectionMatrix.ty = 1 - this.frame.y * this.projectionMatrix.d; + } + + + } + else + { + if (!this.root) + { + this.projectionMatrix.a = 1/(this.width)*2; + this.projectionMatrix.d = 1/(this.height)*2; + + this.projectionMatrix.tx = -1; + this.projectionMatrix.ty = -1; + } + else + { + this.projectionMatrix.a = 1/(this.width)*2; + this.projectionMatrix.d = -1/(this.height)*2; + + this.projectionMatrix.tx = -1; + this.projectionMatrix.ty = 1; + } + + + // this.projectionMatrix.tx = -1; + // this.projectionMatrix.ty = 1; + + gl.viewport(0, 0, this.width, this.height); + } }; /** @@ -119,6 +176,9 @@ */ RenderTarget.prototype.resize = function(width, height) { + width = width | 0; + height = height | 0; + if (this.width === width && this.height === height) { return; } @@ -128,7 +188,6 @@ this.projectionMatrix = new math.Matrix(); - if (!this.root) { var gl = this.gl; @@ -140,10 +199,11 @@ this.projectionMatrix.ty = -1; gl.bindTexture(gl.TEXTURE_2D, this.texture); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width , height , 0, gl.RGBA, gl.UNSIGNED_BYTE, null); // update the stencil buffer width and height gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencilBuffer); - gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width , height ); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width , height ); } else { diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index 20e778c..1413a28 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -249,6 +249,8 @@ }, set: function (value) { + this._filters = value; + /* if (value) { // now put all the passes in one place.. @@ -268,7 +270,7 @@ this._filterBlock = { target: this, filterPasses: passes }; } - this._filters = value; + this._filters = value;*/ } } }); diff --git a/src/core/display/DisplayObjectContainer.js b/src/core/display/DisplayObjectContainer.js index 120c9ff..4af3f82 100644 --- a/src/core/display/DisplayObjectContainer.js +++ b/src/core/display/DisplayObjectContainer.js @@ -500,8 +500,9 @@ // push filter first as we need to ensure the stencil buffer is correct for any masking if (this._filters) { - renderer.plugins.sprite.flush(); - renderer.filterManager.pushFilter(this._filterBlock); + renderer.currentRenderer.flush(); + renderer.filterManager.pushFilter(this, this._filters); + renderer.currentRenderer.start(); } if (this._mask) @@ -526,7 +527,9 @@ if (this._filters) { + renderer.currentRenderer.flush(); renderer.filterManager.popFilter(); + renderer.currentRenderer.start(); } } diff --git a/src/core/graphics/webgl/GraphicsRenderer.js b/src/core/graphics/webgl/GraphicsRenderer.js index c81350b..a63640e 100644 --- a/src/core/graphics/webgl/GraphicsRenderer.js +++ b/src/core/graphics/webgl/GraphicsRenderer.js @@ -3,7 +3,9 @@ CONST = require('../../const'), ObjectRenderer = require('../../renderers/webgl/utils/ObjectRenderer'), WebGLRenderer = require('../../renderers/webgl/WebGLRenderer'), - WebGLGraphicsData = require('./WebGLGraphicsData'); + WebGLGraphicsData = require('./WebGLGraphicsData'), + ComplexPrimitiveShader = require('./ComplexPrimitiveShader'), + PrimitiveShader = require('./PrimitiveShader'); /** * Renders the graphics object. diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 13892a6..8ff6208 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -194,6 +194,9 @@ */ this.filterManager = new WebGLFilterManager(this); + //TODO FIX THIS EVENT>> + this.filterManager.initShaderBuffers(); + /** * Manages the blendModes * @member {WebGLBlendModeManager} @@ -308,9 +311,6 @@ var gl = this.gl; - // -- Does this need to be set every frame? -- // - gl.viewport(0, 0, this.width, this.height); - // make sure we are bound to the main frame buffer gl.bindFramebuffer(gl.FRAMEBUFFER, null); @@ -344,11 +344,13 @@ this.currentRenderTarget = renderTarget; + this.currentRenderTarget.activate(); + // reset the render session data.. this.drawCount = 0; // start the filter manager - // this.filterManager.begin(renderTarget.frameBuffer); + this.filterManager.begin()//renderTarget.frameBuffer); // render the scene! displayObject.renderWebGL(this); diff --git a/src/core/renderers/webgl/managers/Quad.js b/src/core/renderers/webgl/managers/Quad.js new file mode 100644 index 0000000..b2fae63 --- /dev/null +++ b/src/core/renderers/webgl/managers/Quad.js @@ -0,0 +1,107 @@ +var WebGLManager = require('./WebGLManager'), + utils = require('../../../utils'); + +/** + * @class + * @namespace PIXI + * @param renderer {WebGLRenderer} The renderer this manager works for. + */ +function Quad(gl) +{ + this.gl = gl; + +// this.textures = new TextureUvs(); + + this.vertices = new Float32Array([ + 0,0, + 200,0, + 200,200, + 0,200 + ]); + + this.uvs = new Float32Array([ + 0,0, + 1,0, + 1,1, + 0,1 + ]); + + var white = (0xFFFFFF >> 16) + (0xFFFFFF & 0xff00) + ((0xFFFFFF & 0xff) << 16) + (1 * 255 << 24); + + this.colors = new Float32Array([ + white, + white, + white, + white + ]) + + this.indices = new Uint16Array([ + 0, 1, 2, 0, 3, 2 + ]); + + this.vertexBuffer = gl.createBuffer(); + this.indexBuffer = gl.createBuffer(); + + gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER, (8 + 8 + 4) * 4, gl.DYNAMIC_DRAW); + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW); + + this.upload(); +} + +Quad.prototype.constructor = Quad; + +Quad.prototype.map = function(rect, rect2) +{ + var x = 0//rect2.x / rect.width; + var y = 0//rect2.y / rect.height; + + this.uvs[0] = x; + this.uvs[1] = y; + + this.uvs[2] = x + rect2.width / rect.width; + this.uvs[3] = y; + + this.uvs[4] = x + rect2.width / rect.width; + this.uvs[5] = y + rect2.height / rect.height; + + this.uvs[6] = x; + this.uvs[7] = y + rect2.height / rect.height; + + /// ----- + x = rect2.x; + y = rect2.y; + + this.vertices[0] = x; + this.vertices[1] = y; + + this.vertices[2] = x + rect2.width; + this.vertices[3] = y; + + this.vertices[4] = x + rect2.width; + this.vertices[5] = y + rect2.height; + + this.vertices[6] = x; + this.vertices[7] = y + rect2.height; + + this.upload(); +} + +Quad.prototype.upload = function() +{ + var gl = this.gl; + + gl.bindBuffer( gl.ARRAY_BUFFER, this.vertexBuffer ); + + gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertices); + + gl.bufferSubData(gl.ARRAY_BUFFER, 8 * 4, this.uvs); + + gl.bufferSubData(gl.ARRAY_BUFFER, (8 + 8) * 4, this.colors); +} + +module.exports = Quad; + + diff --git a/src/core/renderers/webgl/managers/WebGLFilterManager.js b/src/core/renderers/webgl/managers/WebGLFilterManager.js index d6ed3c6..b91b80a 100644 --- a/src/core/renderers/webgl/managers/WebGLFilterManager.js +++ b/src/core/renderers/webgl/managers/WebGLFilterManager.js @@ -1,7 +1,9 @@ var WebGLManager = require('./WebGLManager'), FilterTexture = require('../utils/FilterTexture'), RenderTarget = require('../utils/RenderTarget'); - Shader = require('../shaders/Shader'); + Shader = require('../shaders/Shader'), + Quad = require('./Quad'), + math = require('../../../math'); /** * @class @@ -17,21 +19,17 @@ */ this.filterStack = []; + this.filterStack.push({ + renderTarget:renderer.currentRenderTarget, + filter:[], + bounds:null + }); + /** * @member {any[]]} */ this.texturePool = []; - /** - * @member {number} - */ - this.offsetX = 0; - - /** - * @member {number} - */ - this.offsetY = 0; - // listen for context and update necessary buffers var self = this; this.renderer.on('context', function () @@ -39,6 +37,10 @@ self.texturePool.length = 0; self.initShaderBuffers(); }); + + this.textureSize = new math.Rectangle(0,0,800, 600); + + } WebGLFilterManager.prototype = Object.create(WebGLManager.prototype); @@ -51,12 +53,10 @@ */ WebGLFilterManager.prototype.begin = function (buffer) { - this.defaultShader = this.renderer.shaderManager.plugins.defaultShader; - - this.width = this.renderer.projection.x * 2; - this.height = -this.renderer.projection.y * 2; - - this.buffer = buffer; +// this.defaultShader = this.renderer.shaderManager.plugins.defaultShader; + //console.log("<-------->") + this.filterStack[0].renderTarget = this.renderer.currentRenderTarget; + this.filterStack[0].bounds = new math.Rectangle(0, 0, this.renderer.currentRenderTarget.width, this.renderer.currentRenderTarget.height); }; /** @@ -67,25 +67,114 @@ WebGLFilterManager.prototype.pushFilter = function (target, filters) { var gl = this.renderer.gl; - - var texture = this.texturePool.pop(); - + //console.log("push") // get the bounds of the object.. var bounds = target.filterArea || target.getBounds(); - if (!texture) + this.realSize = bounds;//.clone(); + + var texture = this.texturePool.pop() || new RenderTarget(this.renderer.gl, this.textureSize.width, this.textureSize.height); + + // texture. + // TODO setting frame is lame.. + texture.frame = bounds;//new math.Rectangle(, 0, this.realSize.width, this.realSize.height); + texture.activate(); + texture.clear(); + texture.frame = null; + + this.renderer.currentRenderTarget = texture; + + + + // TODO get rid of object creation! + this.filterStack.push({ + renderTarget:texture, + filter:filters, + bounds:bounds + }); + +}; + + +/** + * Removes the last filter from the filter stack and doesn't return it. + * + */ +WebGLFilterManager.prototype.popFilter = function () +{ + var filterData = this.filterStack.pop(); + + + var input = filterData.renderTarget; + + // use program + var gl = this.renderer.gl; + var filter = filterData.filter[0]; + var shader = filter.shaders[gl.id]; + + // shader.syncUniforms(); + + + this.quad.map(this.textureSize, filterData.bounds); + + // + // + if (!shader) { - texture = new RenderTarget(this.renderer.gl, bounds.width, bounds.height); - } - else - { - texture.resize(bounds.width, bounds.height); + shader = new Shader(this, + filter.vertexSrc, + filter.fragmentSrc, + filter.uniforms, + filter.attributes + ); + + filter.shaders[gl.id] = shader; } - this.texture = texture; + // set the shader + this.renderer.shaderManager.setShader(shader); - this.texture.activate(); - // this.texture. + // RENDER + + gl.bindBuffer(gl.ARRAY_BUFFER, this.quad.vertexBuffer); + + gl.vertexAttribPointer(shader.attributes.aVertexPosition, 2, gl.FLOAT, false, 0, 0); + gl.vertexAttribPointer(shader.attributes.aTextureCoord, 2, gl.FLOAT, false, 0, 2 * 4 * 4); + gl.vertexAttribPointer(shader.attributes.aColor, 1, gl.FLOAT, false, 0, 0); + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.quad.indexBuffer); + + // draw the filter... + + var previousFilter = this.filterStack[this.filterStack.length-1]; + + this.renderer.currentRenderTarget = previousFilter.renderTarget; + + this.renderer.currentRenderTarget.frame = previousFilter.bounds; + this.renderer.currentRenderTarget.activate(); + this.renderer.currentRenderTarget.frame = null; + + gl.uniformMatrix3fv(shader.uniforms.projectionMatrix._location, false, this.renderer.currentRenderTarget.projectionMatrix.toArray(true)); + + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, input.texture); + + gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); + + this.texturePool.push(filterData.renderTarget); +}; + + +// this.projectionMatrix.d = 1/height*2; + // offset.. + + + + + // ----- // + + + // this.texture. /* var projection = this.renderer.projection; var offset = this.renderer.offset; @@ -180,18 +269,9 @@ filterBlock._glFilterTexture = texture; ` */ -}; -/** - * Removes the last filter from the filter stack and doesn't return it. - * - */ -WebGLFilterManager.prototype.popFilter = function () -{ - this.texturePool.push(this.texture); + // this.texturePool.push(output); - this.renderer.currentRenderTarget.activate(); - /* var gl = this.renderer.gl; @@ -362,11 +442,8 @@ // gl.uniform2f(this.defaultShader.offsetVector, -offsetX, -offsetY); // return the texture to the pool - this.texturePool.push(texture); filterBlock._glFilterTexture = null; */ -}; - /** * Applies the filter to the specified area. @@ -437,7 +514,9 @@ { var gl = this.renderer.gl; - // create some buffers + this.quad = new Quad(gl); + + // create some buffers this.vertexBuffer = gl.createBuffer(); this.uvBuffer = gl.createBuffer(); this.colorBuffer = gl.createBuffer(); diff --git a/src/core/renderers/webgl/shaders/Shader.js b/src/core/renderers/webgl/shaders/Shader.js index 84f321f..4452369 100644 --- a/src/core/renderers/webgl/shaders/Shader.js +++ b/src/core/renderers/webgl/shaders/Shader.js @@ -10,6 +10,7 @@ * @param customUniforms {object} Custom uniforms to use to augment the built-in ones. * @param [fragmentSrc] {string} The source of the fragment shader. */ +//TODO change shaderManager to gl function Shader(shaderManager, vertexSrc, fragmentSrc, customUniforms, customAttributes) { /** @@ -119,6 +120,11 @@ this.cacheUniformLocations(Object.keys(this.uniforms)); this.cacheAttributeLocations(Object.keys(this.attributes)); + + + //this.buildSync(); + + // console.log(this.syncUniforms) }; Shader.prototype.cacheUniformLocations = function (keys) @@ -188,6 +194,29 @@ return (this.program = program); }; +Shader.prototype.buildSync = function () +{ + var str = "" + + str = "Shader.prototype.syncUniforms = function()"; + str += "{\n"; + + for (var key in this.uniforms) + { + var uniform = this.uniforms[key]; + // location = uniform._location, + // value = uniform.value, + //i, il; + + str += "gl.uniform1i(this.uniforms."+ key +"._location, this.uniforms." + key + ".value );\n" + + } + + str += "}"; + // console.log(str) + eval(str); +} + Shader.prototype.syncUniforms = function () { var gl = this.gl; diff --git a/src/core/renderers/webgl/utils/RenderTarget.js b/src/core/renderers/webgl/utils/RenderTarget.js index fa7ddf4..5b3929f 100644 --- a/src/core/renderers/webgl/utils/RenderTarget.js +++ b/src/core/renderers/webgl/utils/RenderTarget.js @@ -42,6 +42,8 @@ this.projectionMatrix = new math.Matrix(); + this.frame = null; + /** * @property scaleMode * @type Number @@ -101,13 +103,68 @@ { var gl = this.gl; - gl.clearColor(0,0,0, 0); + gl.clearColor(0,0,0,0); gl.clear(gl.COLOR_BUFFER_BIT); }; RenderTarget.prototype.activate = function() { - this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.frameBuffer); + //TOOD refactor usage of frame.. + var gl = this.gl; + gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer); + + + if(this.frame) + { + // gl.viewport(this.frame.x, this.frame.y, this.frame.width, this.frame.height); + + gl.viewport(0,0, this.frame.width, this.frame.height); + + if (!this.root) + { + + this.projectionMatrix.a = 1/(this.frame.width)*2; + this.projectionMatrix.d = 1/(this.frame.height)*2; + + this.projectionMatrix.tx = -1 - this.frame.x * this.projectionMatrix.a; + this.projectionMatrix.ty = -1 - this.frame.y * this.projectionMatrix.d; + } + else + { + this.projectionMatrix.a = 1/(this.frame.width)*2; + this.projectionMatrix.d = -1/(this.frame.height)*2; + + this.projectionMatrix.tx = -1 - this.frame.x * this.projectionMatrix.a; + this.projectionMatrix.ty = 1 - this.frame.y * this.projectionMatrix.d; + } + + + } + else + { + if (!this.root) + { + this.projectionMatrix.a = 1/(this.width)*2; + this.projectionMatrix.d = 1/(this.height)*2; + + this.projectionMatrix.tx = -1; + this.projectionMatrix.ty = -1; + } + else + { + this.projectionMatrix.a = 1/(this.width)*2; + this.projectionMatrix.d = -1/(this.height)*2; + + this.projectionMatrix.tx = -1; + this.projectionMatrix.ty = 1; + } + + + // this.projectionMatrix.tx = -1; + // this.projectionMatrix.ty = 1; + + gl.viewport(0, 0, this.width, this.height); + } }; /** @@ -119,6 +176,9 @@ */ RenderTarget.prototype.resize = function(width, height) { + width = width | 0; + height = height | 0; + if (this.width === width && this.height === height) { return; } @@ -128,7 +188,6 @@ this.projectionMatrix = new math.Matrix(); - if (!this.root) { var gl = this.gl; @@ -140,10 +199,11 @@ this.projectionMatrix.ty = -1; gl.bindTexture(gl.TEXTURE_2D, this.texture); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width , height , 0, gl.RGBA, gl.UNSIGNED_BYTE, null); // update the stencil buffer width and height gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencilBuffer); - gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width , height ); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width , height ); } else { diff --git a/src/core/textures/RenderTexture.js b/src/core/textures/RenderTexture.js index dcaacfe..9c262ad 100644 --- a/src/core/textures/RenderTexture.js +++ b/src/core/textures/RenderTexture.js @@ -157,16 +157,6 @@ this.render = this.renderCanvas; this.textureBuffer = new CanvasBuffer(this.width* this.resolution, this.height* this.resolution); this.baseTexture.source = this.textureBuffer.canvas; - /* document.body.appendChild( this.textureBuffer.canvas); - - this.textureBuffer.canvas.style.position = "absolute"; - this.textureBuffer.canvas.style.top = 0; - this.textureBuffer.canvas.style.left= 0; - this.textureBuffer.canvas.style.zIndex = 1000; - this.textureBuffer.canvas.width = width; - this.textureBuffer.canvas.height = height; - - console.log(this.textureBuffer.canvas);*/ } /** @@ -175,8 +165,6 @@ this.valid = true; this._updateUvs(); - - console.log(baseTexture); } RenderTexture.prototype = Object.create(Texture.prototype); diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index 20e778c..1413a28 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -249,6 +249,8 @@ }, set: function (value) { + this._filters = value; + /* if (value) { // now put all the passes in one place.. @@ -268,7 +270,7 @@ this._filterBlock = { target: this, filterPasses: passes }; } - this._filters = value; + this._filters = value;*/ } } }); diff --git a/src/core/display/DisplayObjectContainer.js b/src/core/display/DisplayObjectContainer.js index 120c9ff..4af3f82 100644 --- a/src/core/display/DisplayObjectContainer.js +++ b/src/core/display/DisplayObjectContainer.js @@ -500,8 +500,9 @@ // push filter first as we need to ensure the stencil buffer is correct for any masking if (this._filters) { - renderer.plugins.sprite.flush(); - renderer.filterManager.pushFilter(this._filterBlock); + renderer.currentRenderer.flush(); + renderer.filterManager.pushFilter(this, this._filters); + renderer.currentRenderer.start(); } if (this._mask) @@ -526,7 +527,9 @@ if (this._filters) { + renderer.currentRenderer.flush(); renderer.filterManager.popFilter(); + renderer.currentRenderer.start(); } } diff --git a/src/core/graphics/webgl/GraphicsRenderer.js b/src/core/graphics/webgl/GraphicsRenderer.js index c81350b..a63640e 100644 --- a/src/core/graphics/webgl/GraphicsRenderer.js +++ b/src/core/graphics/webgl/GraphicsRenderer.js @@ -3,7 +3,9 @@ CONST = require('../../const'), ObjectRenderer = require('../../renderers/webgl/utils/ObjectRenderer'), WebGLRenderer = require('../../renderers/webgl/WebGLRenderer'), - WebGLGraphicsData = require('./WebGLGraphicsData'); + WebGLGraphicsData = require('./WebGLGraphicsData'), + ComplexPrimitiveShader = require('./ComplexPrimitiveShader'), + PrimitiveShader = require('./PrimitiveShader'); /** * Renders the graphics object. diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 13892a6..8ff6208 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -194,6 +194,9 @@ */ this.filterManager = new WebGLFilterManager(this); + //TODO FIX THIS EVENT>> + this.filterManager.initShaderBuffers(); + /** * Manages the blendModes * @member {WebGLBlendModeManager} @@ -308,9 +311,6 @@ var gl = this.gl; - // -- Does this need to be set every frame? -- // - gl.viewport(0, 0, this.width, this.height); - // make sure we are bound to the main frame buffer gl.bindFramebuffer(gl.FRAMEBUFFER, null); @@ -344,11 +344,13 @@ this.currentRenderTarget = renderTarget; + this.currentRenderTarget.activate(); + // reset the render session data.. this.drawCount = 0; // start the filter manager - // this.filterManager.begin(renderTarget.frameBuffer); + this.filterManager.begin()//renderTarget.frameBuffer); // render the scene! displayObject.renderWebGL(this); diff --git a/src/core/renderers/webgl/managers/Quad.js b/src/core/renderers/webgl/managers/Quad.js new file mode 100644 index 0000000..b2fae63 --- /dev/null +++ b/src/core/renderers/webgl/managers/Quad.js @@ -0,0 +1,107 @@ +var WebGLManager = require('./WebGLManager'), + utils = require('../../../utils'); + +/** + * @class + * @namespace PIXI + * @param renderer {WebGLRenderer} The renderer this manager works for. + */ +function Quad(gl) +{ + this.gl = gl; + +// this.textures = new TextureUvs(); + + this.vertices = new Float32Array([ + 0,0, + 200,0, + 200,200, + 0,200 + ]); + + this.uvs = new Float32Array([ + 0,0, + 1,0, + 1,1, + 0,1 + ]); + + var white = (0xFFFFFF >> 16) + (0xFFFFFF & 0xff00) + ((0xFFFFFF & 0xff) << 16) + (1 * 255 << 24); + + this.colors = new Float32Array([ + white, + white, + white, + white + ]) + + this.indices = new Uint16Array([ + 0, 1, 2, 0, 3, 2 + ]); + + this.vertexBuffer = gl.createBuffer(); + this.indexBuffer = gl.createBuffer(); + + gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER, (8 + 8 + 4) * 4, gl.DYNAMIC_DRAW); + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW); + + this.upload(); +} + +Quad.prototype.constructor = Quad; + +Quad.prototype.map = function(rect, rect2) +{ + var x = 0//rect2.x / rect.width; + var y = 0//rect2.y / rect.height; + + this.uvs[0] = x; + this.uvs[1] = y; + + this.uvs[2] = x + rect2.width / rect.width; + this.uvs[3] = y; + + this.uvs[4] = x + rect2.width / rect.width; + this.uvs[5] = y + rect2.height / rect.height; + + this.uvs[6] = x; + this.uvs[7] = y + rect2.height / rect.height; + + /// ----- + x = rect2.x; + y = rect2.y; + + this.vertices[0] = x; + this.vertices[1] = y; + + this.vertices[2] = x + rect2.width; + this.vertices[3] = y; + + this.vertices[4] = x + rect2.width; + this.vertices[5] = y + rect2.height; + + this.vertices[6] = x; + this.vertices[7] = y + rect2.height; + + this.upload(); +} + +Quad.prototype.upload = function() +{ + var gl = this.gl; + + gl.bindBuffer( gl.ARRAY_BUFFER, this.vertexBuffer ); + + gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertices); + + gl.bufferSubData(gl.ARRAY_BUFFER, 8 * 4, this.uvs); + + gl.bufferSubData(gl.ARRAY_BUFFER, (8 + 8) * 4, this.colors); +} + +module.exports = Quad; + + diff --git a/src/core/renderers/webgl/managers/WebGLFilterManager.js b/src/core/renderers/webgl/managers/WebGLFilterManager.js index d6ed3c6..b91b80a 100644 --- a/src/core/renderers/webgl/managers/WebGLFilterManager.js +++ b/src/core/renderers/webgl/managers/WebGLFilterManager.js @@ -1,7 +1,9 @@ var WebGLManager = require('./WebGLManager'), FilterTexture = require('../utils/FilterTexture'), RenderTarget = require('../utils/RenderTarget'); - Shader = require('../shaders/Shader'); + Shader = require('../shaders/Shader'), + Quad = require('./Quad'), + math = require('../../../math'); /** * @class @@ -17,21 +19,17 @@ */ this.filterStack = []; + this.filterStack.push({ + renderTarget:renderer.currentRenderTarget, + filter:[], + bounds:null + }); + /** * @member {any[]]} */ this.texturePool = []; - /** - * @member {number} - */ - this.offsetX = 0; - - /** - * @member {number} - */ - this.offsetY = 0; - // listen for context and update necessary buffers var self = this; this.renderer.on('context', function () @@ -39,6 +37,10 @@ self.texturePool.length = 0; self.initShaderBuffers(); }); + + this.textureSize = new math.Rectangle(0,0,800, 600); + + } WebGLFilterManager.prototype = Object.create(WebGLManager.prototype); @@ -51,12 +53,10 @@ */ WebGLFilterManager.prototype.begin = function (buffer) { - this.defaultShader = this.renderer.shaderManager.plugins.defaultShader; - - this.width = this.renderer.projection.x * 2; - this.height = -this.renderer.projection.y * 2; - - this.buffer = buffer; +// this.defaultShader = this.renderer.shaderManager.plugins.defaultShader; + //console.log("<-------->") + this.filterStack[0].renderTarget = this.renderer.currentRenderTarget; + this.filterStack[0].bounds = new math.Rectangle(0, 0, this.renderer.currentRenderTarget.width, this.renderer.currentRenderTarget.height); }; /** @@ -67,25 +67,114 @@ WebGLFilterManager.prototype.pushFilter = function (target, filters) { var gl = this.renderer.gl; - - var texture = this.texturePool.pop(); - + //console.log("push") // get the bounds of the object.. var bounds = target.filterArea || target.getBounds(); - if (!texture) + this.realSize = bounds;//.clone(); + + var texture = this.texturePool.pop() || new RenderTarget(this.renderer.gl, this.textureSize.width, this.textureSize.height); + + // texture. + // TODO setting frame is lame.. + texture.frame = bounds;//new math.Rectangle(, 0, this.realSize.width, this.realSize.height); + texture.activate(); + texture.clear(); + texture.frame = null; + + this.renderer.currentRenderTarget = texture; + + + + // TODO get rid of object creation! + this.filterStack.push({ + renderTarget:texture, + filter:filters, + bounds:bounds + }); + +}; + + +/** + * Removes the last filter from the filter stack and doesn't return it. + * + */ +WebGLFilterManager.prototype.popFilter = function () +{ + var filterData = this.filterStack.pop(); + + + var input = filterData.renderTarget; + + // use program + var gl = this.renderer.gl; + var filter = filterData.filter[0]; + var shader = filter.shaders[gl.id]; + + // shader.syncUniforms(); + + + this.quad.map(this.textureSize, filterData.bounds); + + // + // + if (!shader) { - texture = new RenderTarget(this.renderer.gl, bounds.width, bounds.height); - } - else - { - texture.resize(bounds.width, bounds.height); + shader = new Shader(this, + filter.vertexSrc, + filter.fragmentSrc, + filter.uniforms, + filter.attributes + ); + + filter.shaders[gl.id] = shader; } - this.texture = texture; + // set the shader + this.renderer.shaderManager.setShader(shader); - this.texture.activate(); - // this.texture. + // RENDER + + gl.bindBuffer(gl.ARRAY_BUFFER, this.quad.vertexBuffer); + + gl.vertexAttribPointer(shader.attributes.aVertexPosition, 2, gl.FLOAT, false, 0, 0); + gl.vertexAttribPointer(shader.attributes.aTextureCoord, 2, gl.FLOAT, false, 0, 2 * 4 * 4); + gl.vertexAttribPointer(shader.attributes.aColor, 1, gl.FLOAT, false, 0, 0); + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.quad.indexBuffer); + + // draw the filter... + + var previousFilter = this.filterStack[this.filterStack.length-1]; + + this.renderer.currentRenderTarget = previousFilter.renderTarget; + + this.renderer.currentRenderTarget.frame = previousFilter.bounds; + this.renderer.currentRenderTarget.activate(); + this.renderer.currentRenderTarget.frame = null; + + gl.uniformMatrix3fv(shader.uniforms.projectionMatrix._location, false, this.renderer.currentRenderTarget.projectionMatrix.toArray(true)); + + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, input.texture); + + gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); + + this.texturePool.push(filterData.renderTarget); +}; + + +// this.projectionMatrix.d = 1/height*2; + // offset.. + + + + + // ----- // + + + // this.texture. /* var projection = this.renderer.projection; var offset = this.renderer.offset; @@ -180,18 +269,9 @@ filterBlock._glFilterTexture = texture; ` */ -}; -/** - * Removes the last filter from the filter stack and doesn't return it. - * - */ -WebGLFilterManager.prototype.popFilter = function () -{ - this.texturePool.push(this.texture); + // this.texturePool.push(output); - this.renderer.currentRenderTarget.activate(); - /* var gl = this.renderer.gl; @@ -362,11 +442,8 @@ // gl.uniform2f(this.defaultShader.offsetVector, -offsetX, -offsetY); // return the texture to the pool - this.texturePool.push(texture); filterBlock._glFilterTexture = null; */ -}; - /** * Applies the filter to the specified area. @@ -437,7 +514,9 @@ { var gl = this.renderer.gl; - // create some buffers + this.quad = new Quad(gl); + + // create some buffers this.vertexBuffer = gl.createBuffer(); this.uvBuffer = gl.createBuffer(); this.colorBuffer = gl.createBuffer(); diff --git a/src/core/renderers/webgl/shaders/Shader.js b/src/core/renderers/webgl/shaders/Shader.js index 84f321f..4452369 100644 --- a/src/core/renderers/webgl/shaders/Shader.js +++ b/src/core/renderers/webgl/shaders/Shader.js @@ -10,6 +10,7 @@ * @param customUniforms {object} Custom uniforms to use to augment the built-in ones. * @param [fragmentSrc] {string} The source of the fragment shader. */ +//TODO change shaderManager to gl function Shader(shaderManager, vertexSrc, fragmentSrc, customUniforms, customAttributes) { /** @@ -119,6 +120,11 @@ this.cacheUniformLocations(Object.keys(this.uniforms)); this.cacheAttributeLocations(Object.keys(this.attributes)); + + + //this.buildSync(); + + // console.log(this.syncUniforms) }; Shader.prototype.cacheUniformLocations = function (keys) @@ -188,6 +194,29 @@ return (this.program = program); }; +Shader.prototype.buildSync = function () +{ + var str = "" + + str = "Shader.prototype.syncUniforms = function()"; + str += "{\n"; + + for (var key in this.uniforms) + { + var uniform = this.uniforms[key]; + // location = uniform._location, + // value = uniform.value, + //i, il; + + str += "gl.uniform1i(this.uniforms."+ key +"._location, this.uniforms." + key + ".value );\n" + + } + + str += "}"; + // console.log(str) + eval(str); +} + Shader.prototype.syncUniforms = function () { var gl = this.gl; diff --git a/src/core/renderers/webgl/utils/RenderTarget.js b/src/core/renderers/webgl/utils/RenderTarget.js index fa7ddf4..5b3929f 100644 --- a/src/core/renderers/webgl/utils/RenderTarget.js +++ b/src/core/renderers/webgl/utils/RenderTarget.js @@ -42,6 +42,8 @@ this.projectionMatrix = new math.Matrix(); + this.frame = null; + /** * @property scaleMode * @type Number @@ -101,13 +103,68 @@ { var gl = this.gl; - gl.clearColor(0,0,0, 0); + gl.clearColor(0,0,0,0); gl.clear(gl.COLOR_BUFFER_BIT); }; RenderTarget.prototype.activate = function() { - this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.frameBuffer); + //TOOD refactor usage of frame.. + var gl = this.gl; + gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer); + + + if(this.frame) + { + // gl.viewport(this.frame.x, this.frame.y, this.frame.width, this.frame.height); + + gl.viewport(0,0, this.frame.width, this.frame.height); + + if (!this.root) + { + + this.projectionMatrix.a = 1/(this.frame.width)*2; + this.projectionMatrix.d = 1/(this.frame.height)*2; + + this.projectionMatrix.tx = -1 - this.frame.x * this.projectionMatrix.a; + this.projectionMatrix.ty = -1 - this.frame.y * this.projectionMatrix.d; + } + else + { + this.projectionMatrix.a = 1/(this.frame.width)*2; + this.projectionMatrix.d = -1/(this.frame.height)*2; + + this.projectionMatrix.tx = -1 - this.frame.x * this.projectionMatrix.a; + this.projectionMatrix.ty = 1 - this.frame.y * this.projectionMatrix.d; + } + + + } + else + { + if (!this.root) + { + this.projectionMatrix.a = 1/(this.width)*2; + this.projectionMatrix.d = 1/(this.height)*2; + + this.projectionMatrix.tx = -1; + this.projectionMatrix.ty = -1; + } + else + { + this.projectionMatrix.a = 1/(this.width)*2; + this.projectionMatrix.d = -1/(this.height)*2; + + this.projectionMatrix.tx = -1; + this.projectionMatrix.ty = 1; + } + + + // this.projectionMatrix.tx = -1; + // this.projectionMatrix.ty = 1; + + gl.viewport(0, 0, this.width, this.height); + } }; /** @@ -119,6 +176,9 @@ */ RenderTarget.prototype.resize = function(width, height) { + width = width | 0; + height = height | 0; + if (this.width === width && this.height === height) { return; } @@ -128,7 +188,6 @@ this.projectionMatrix = new math.Matrix(); - if (!this.root) { var gl = this.gl; @@ -140,10 +199,11 @@ this.projectionMatrix.ty = -1; gl.bindTexture(gl.TEXTURE_2D, this.texture); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width , height , 0, gl.RGBA, gl.UNSIGNED_BYTE, null); // update the stencil buffer width and height gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencilBuffer); - gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width , height ); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width , height ); } else { diff --git a/src/core/textures/RenderTexture.js b/src/core/textures/RenderTexture.js index dcaacfe..9c262ad 100644 --- a/src/core/textures/RenderTexture.js +++ b/src/core/textures/RenderTexture.js @@ -157,16 +157,6 @@ this.render = this.renderCanvas; this.textureBuffer = new CanvasBuffer(this.width* this.resolution, this.height* this.resolution); this.baseTexture.source = this.textureBuffer.canvas; - /* document.body.appendChild( this.textureBuffer.canvas); - - this.textureBuffer.canvas.style.position = "absolute"; - this.textureBuffer.canvas.style.top = 0; - this.textureBuffer.canvas.style.left= 0; - this.textureBuffer.canvas.style.zIndex = 1000; - this.textureBuffer.canvas.width = width; - this.textureBuffer.canvas.height = height; - - console.log(this.textureBuffer.canvas);*/ } /** @@ -175,8 +165,6 @@ this.valid = true; this._updateUvs(); - - console.log(baseTexture); } RenderTexture.prototype = Object.create(Texture.prototype); diff --git a/src/filters/ColorMatrixFilter.js b/src/filters/ColorMatrixFilter.js index 73b025a..6750c3b 100644 --- a/src/filters/ColorMatrixFilter.js +++ b/src/filters/ColorMatrixFilter.js @@ -33,9 +33,10 @@ 'void main(void)', '{', - ' gl_FragColor = texture2D(uSampler, vTextureCoord) * matrix;', + ' gl_FragColor = texture2D(uSampler, vTextureCoord) * 2.0;', +// ' gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);',//texture2D(uSampler, vTextureCoord) * matrix;', '}' - ]; + ].join('\n'); } ColorMatrixFilter.prototype = Object.create(AbstractFilter.prototype);