diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 78df77f..401042c 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -32,6 +32,8 @@ { utils.sayHello('webGL'); + WebGLRenderer._TEMP__ = this; + if (options) { for (var i in CONST.defaultRenderOptions) @@ -431,6 +433,7 @@ texture.on('dispose', this._boundDestroyTexture); } + gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultipliedAlpha); diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 78df77f..401042c 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -32,6 +32,8 @@ { utils.sayHello('webGL'); + WebGLRenderer._TEMP__ = this; + if (options) { for (var i in CONST.defaultRenderOptions) @@ -431,6 +433,7 @@ texture.on('dispose', this._boundDestroyTexture); } + gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultipliedAlpha); diff --git a/src/core/renderers/webgl/managers/FilterManager.js b/src/core/renderers/webgl/managers/FilterManager.js index 29e97a3..30c80e1 100644 --- a/src/core/renderers/webgl/managers/FilterManager.js +++ b/src/core/renderers/webgl/managers/FilterManager.js @@ -198,12 +198,12 @@ // TODO playing around here.. this is temporary - (will end up in the shader) -FilterManager.prototype.calculateMappedMatrix = function (filterArea, sprite) +FilterManager.prototype.calculateMappedMatrix = function (filterArea, sprite, outputMatrix) { - var worldTransform = sprite.worldTransform.copy(math.Matrix.TEMP_MATRIX); - var texture = sprite.texture.baseTexture; + worldTransform = sprite.worldTransform.copy(math.Matrix.TEMP_MATRIX); + texture = sprite.texture.baseTexture; - var mappedMatrix = this.tempMatrix.identity(); + var mappedMatrix = outputMatrix.identity(); // scale.. var ratio = this.textureSize.height / this.textureSize.width; diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 78df77f..401042c 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -32,6 +32,8 @@ { utils.sayHello('webGL'); + WebGLRenderer._TEMP__ = this; + if (options) { for (var i in CONST.defaultRenderOptions) @@ -431,6 +433,7 @@ texture.on('dispose', this._boundDestroyTexture); } + gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultipliedAlpha); diff --git a/src/core/renderers/webgl/managers/FilterManager.js b/src/core/renderers/webgl/managers/FilterManager.js index 29e97a3..30c80e1 100644 --- a/src/core/renderers/webgl/managers/FilterManager.js +++ b/src/core/renderers/webgl/managers/FilterManager.js @@ -198,12 +198,12 @@ // TODO playing around here.. this is temporary - (will end up in the shader) -FilterManager.prototype.calculateMappedMatrix = function (filterArea, sprite) +FilterManager.prototype.calculateMappedMatrix = function (filterArea, sprite, outputMatrix) { - var worldTransform = sprite.worldTransform.copy(math.Matrix.TEMP_MATRIX); - var texture = sprite.texture.baseTexture; + worldTransform = sprite.worldTransform.copy(math.Matrix.TEMP_MATRIX); + texture = sprite.texture.baseTexture; - var mappedMatrix = this.tempMatrix.identity(); + var mappedMatrix = outputMatrix.identity(); // scale.. var ratio = this.textureSize.height / this.textureSize.width; diff --git a/src/core/renderers/webgl/managers/MaskManager.js b/src/core/renderers/webgl/managers/MaskManager.js index 3e7f4a7..732438d 100644 --- a/src/core/renderers/webgl/managers/MaskManager.js +++ b/src/core/renderers/webgl/managers/MaskManager.js @@ -55,7 +55,7 @@ MaskManager.prototype.pushSpriteMask = function (target, maskData) { var alphaMaskFilter = this.alphaMaskPool.pop(); - + if (!alphaMaskFilter) { alphaMaskFilter = [new AlphaMaskFilter(maskData)]; diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 78df77f..401042c 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -32,6 +32,8 @@ { utils.sayHello('webGL'); + WebGLRenderer._TEMP__ = this; + if (options) { for (var i in CONST.defaultRenderOptions) @@ -431,6 +433,7 @@ texture.on('dispose', this._boundDestroyTexture); } + gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultipliedAlpha); diff --git a/src/core/renderers/webgl/managers/FilterManager.js b/src/core/renderers/webgl/managers/FilterManager.js index 29e97a3..30c80e1 100644 --- a/src/core/renderers/webgl/managers/FilterManager.js +++ b/src/core/renderers/webgl/managers/FilterManager.js @@ -198,12 +198,12 @@ // TODO playing around here.. this is temporary - (will end up in the shader) -FilterManager.prototype.calculateMappedMatrix = function (filterArea, sprite) +FilterManager.prototype.calculateMappedMatrix = function (filterArea, sprite, outputMatrix) { - var worldTransform = sprite.worldTransform.copy(math.Matrix.TEMP_MATRIX); - var texture = sprite.texture.baseTexture; + worldTransform = sprite.worldTransform.copy(math.Matrix.TEMP_MATRIX); + texture = sprite.texture.baseTexture; - var mappedMatrix = this.tempMatrix.identity(); + var mappedMatrix = outputMatrix.identity(); // scale.. var ratio = this.textureSize.height / this.textureSize.width; diff --git a/src/core/renderers/webgl/managers/MaskManager.js b/src/core/renderers/webgl/managers/MaskManager.js index 3e7f4a7..732438d 100644 --- a/src/core/renderers/webgl/managers/MaskManager.js +++ b/src/core/renderers/webgl/managers/MaskManager.js @@ -55,7 +55,7 @@ MaskManager.prototype.pushSpriteMask = function (target, maskData) { var alphaMaskFilter = this.alphaMaskPool.pop(); - + if (!alphaMaskFilter) { alphaMaskFilter = [new AlphaMaskFilter(maskData)]; diff --git a/src/core/renderers/webgl/shaders/Shader.js b/src/core/renderers/webgl/shaders/Shader.js index f44095b..8eeeae5 100644 --- a/src/core/renderers/webgl/shaders/Shader.js +++ b/src/core/renderers/webgl/shaders/Shader.js @@ -1,4 +1,5 @@ -var utils = require('../../../utils'); +var utils = require('../../../utils'), + CONST = require('../../../const'); /** * @class @@ -7,7 +8,7 @@ * @param [vertexSrc] {string} The source of the vertex shader. * @param [fragmentSrc] {string} The source of the fragment shader. * @param [uniforms] {object} Uniforms for this shader. - * @param [attributes] {object} Attributes for this shader. + * @param [attributes] {obje=ct} Attributes for this shader. */ function Shader(shaderManager, vertexSrc, fragmentSrc, uniforms, attributes) { @@ -34,7 +35,7 @@ this.attributes = attributes || {}; - this.textureCount = 0; + this.textureCount = 1; /** * The vertex shader. @@ -394,7 +395,8 @@ // PIXI.Texture case 't': case 'sampler2D': - if (!uniform.value || !uniform.value.baseTexture || !uniform.value.baseTexture.hasLoaded) + + if (!uniform.value || !uniform.value.baseTexture.hasLoaded) { break; } @@ -402,6 +404,13 @@ // activate this texture gl.activeTexture(gl['TEXTURE' + this.textureCount]); + var texture = uniform.value.baseTexture._glTextures[gl.id]; + + if(!texture) + { + this.initSampler2D(uniform); + } + // bind the texture gl.bindTexture(gl.TEXTURE_2D, uniform.value.baseTexture._glTextures[gl.id]); @@ -411,13 +420,6 @@ // increment next texture id this.textureCount++; - // initialize the texture if we haven't yet - if (!uniform._init) - { - this.initSampler2D(uniform); - - uniform._init = true; - } break; default: @@ -427,7 +429,7 @@ Shader.prototype.syncUniforms = function () { - this.textureCount = 0; + this.textureCount = 1; for (var key in this.uniforms) { @@ -444,7 +446,14 @@ { var gl = this.gl; - // Extended texture data + var texture = uniform.value.baseTexture; + + texture._glTextures[gl.id] = gl.createTexture(); + + gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); + + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultipliedAlpha); + if (uniform.textureData) { var data = uniform.textureData; @@ -459,40 +468,25 @@ // magFilter can be: gl.LINEAR, gl.LINEAR_MIPMAP_LINEAR or gl.NEAREST // wrapS/T can be: gl.CLAMP_TO_EDGE or gl.REPEAT - var magFilter = (data.magFilter) ? data.magFilter : gl.LINEAR; - var minFilter = (data.minFilter) ? data.minFilter : gl.LINEAR; - var wrapS = (data.wrapS) ? data.wrapS : gl.CLAMP_TO_EDGE; - var wrapT = (data.wrapT) ? data.wrapT : gl.CLAMP_TO_EDGE; - var format = (data.luminance) ? gl.LUMINANCE : gl.RGBA; + gl.texImage2D(gl.TEXTURE_2D, 0, data.luminance ? gl.LUMINANCE : gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source); - if (data.repeat) - { - wrapS = gl.REPEAT; - wrapT = gl.REPEAT; - } + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, data.magFilter ? data.magFilter : gl.LINEAR ); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, data.wrapS ? data.wrapS : gl.CLAMP_TO_EDGE ); - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, !!data.flipY); - - if (data.width) - { - var width = (data.width) ? data.width : 512; - var height = (data.height) ? data.height : 2; - var border = (data.border) ? data.border : 0; - - // void texImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, ArrayBufferView? pixels); - gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, border, format, gl.UNSIGNED_BYTE, null); - } - else - { - // void texImage2D(GLenum target, GLint level, GLenum internalformat, GLenum format, GLenum type, ImageData? pixels); - gl.texImage2D(gl.TEXTURE_2D, 0, format, gl.RGBA, gl.UNSIGNED_BYTE, uniform.value.baseTexture.source); - } - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magFilter); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrapS); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrapT); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, data.wrapS ? data.wrapS : gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, data.wrapT ? data.wrapT : gl.CLAMP_TO_EDGE); } + else + { + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, texture.scaleMode === CONST.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texture.scaleMode === CONST.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + } + }; /** diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 78df77f..401042c 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -32,6 +32,8 @@ { utils.sayHello('webGL'); + WebGLRenderer._TEMP__ = this; + if (options) { for (var i in CONST.defaultRenderOptions) @@ -431,6 +433,7 @@ texture.on('dispose', this._boundDestroyTexture); } + gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultipliedAlpha); diff --git a/src/core/renderers/webgl/managers/FilterManager.js b/src/core/renderers/webgl/managers/FilterManager.js index 29e97a3..30c80e1 100644 --- a/src/core/renderers/webgl/managers/FilterManager.js +++ b/src/core/renderers/webgl/managers/FilterManager.js @@ -198,12 +198,12 @@ // TODO playing around here.. this is temporary - (will end up in the shader) -FilterManager.prototype.calculateMappedMatrix = function (filterArea, sprite) +FilterManager.prototype.calculateMappedMatrix = function (filterArea, sprite, outputMatrix) { - var worldTransform = sprite.worldTransform.copy(math.Matrix.TEMP_MATRIX); - var texture = sprite.texture.baseTexture; + worldTransform = sprite.worldTransform.copy(math.Matrix.TEMP_MATRIX); + texture = sprite.texture.baseTexture; - var mappedMatrix = this.tempMatrix.identity(); + var mappedMatrix = outputMatrix.identity(); // scale.. var ratio = this.textureSize.height / this.textureSize.width; diff --git a/src/core/renderers/webgl/managers/MaskManager.js b/src/core/renderers/webgl/managers/MaskManager.js index 3e7f4a7..732438d 100644 --- a/src/core/renderers/webgl/managers/MaskManager.js +++ b/src/core/renderers/webgl/managers/MaskManager.js @@ -55,7 +55,7 @@ MaskManager.prototype.pushSpriteMask = function (target, maskData) { var alphaMaskFilter = this.alphaMaskPool.pop(); - + if (!alphaMaskFilter) { alphaMaskFilter = [new AlphaMaskFilter(maskData)]; diff --git a/src/core/renderers/webgl/shaders/Shader.js b/src/core/renderers/webgl/shaders/Shader.js index f44095b..8eeeae5 100644 --- a/src/core/renderers/webgl/shaders/Shader.js +++ b/src/core/renderers/webgl/shaders/Shader.js @@ -1,4 +1,5 @@ -var utils = require('../../../utils'); +var utils = require('../../../utils'), + CONST = require('../../../const'); /** * @class @@ -7,7 +8,7 @@ * @param [vertexSrc] {string} The source of the vertex shader. * @param [fragmentSrc] {string} The source of the fragment shader. * @param [uniforms] {object} Uniforms for this shader. - * @param [attributes] {object} Attributes for this shader. + * @param [attributes] {obje=ct} Attributes for this shader. */ function Shader(shaderManager, vertexSrc, fragmentSrc, uniforms, attributes) { @@ -34,7 +35,7 @@ this.attributes = attributes || {}; - this.textureCount = 0; + this.textureCount = 1; /** * The vertex shader. @@ -394,7 +395,8 @@ // PIXI.Texture case 't': case 'sampler2D': - if (!uniform.value || !uniform.value.baseTexture || !uniform.value.baseTexture.hasLoaded) + + if (!uniform.value || !uniform.value.baseTexture.hasLoaded) { break; } @@ -402,6 +404,13 @@ // activate this texture gl.activeTexture(gl['TEXTURE' + this.textureCount]); + var texture = uniform.value.baseTexture._glTextures[gl.id]; + + if(!texture) + { + this.initSampler2D(uniform); + } + // bind the texture gl.bindTexture(gl.TEXTURE_2D, uniform.value.baseTexture._glTextures[gl.id]); @@ -411,13 +420,6 @@ // increment next texture id this.textureCount++; - // initialize the texture if we haven't yet - if (!uniform._init) - { - this.initSampler2D(uniform); - - uniform._init = true; - } break; default: @@ -427,7 +429,7 @@ Shader.prototype.syncUniforms = function () { - this.textureCount = 0; + this.textureCount = 1; for (var key in this.uniforms) { @@ -444,7 +446,14 @@ { var gl = this.gl; - // Extended texture data + var texture = uniform.value.baseTexture; + + texture._glTextures[gl.id] = gl.createTexture(); + + gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); + + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultipliedAlpha); + if (uniform.textureData) { var data = uniform.textureData; @@ -459,40 +468,25 @@ // magFilter can be: gl.LINEAR, gl.LINEAR_MIPMAP_LINEAR or gl.NEAREST // wrapS/T can be: gl.CLAMP_TO_EDGE or gl.REPEAT - var magFilter = (data.magFilter) ? data.magFilter : gl.LINEAR; - var minFilter = (data.minFilter) ? data.minFilter : gl.LINEAR; - var wrapS = (data.wrapS) ? data.wrapS : gl.CLAMP_TO_EDGE; - var wrapT = (data.wrapT) ? data.wrapT : gl.CLAMP_TO_EDGE; - var format = (data.luminance) ? gl.LUMINANCE : gl.RGBA; + gl.texImage2D(gl.TEXTURE_2D, 0, data.luminance ? gl.LUMINANCE : gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source); - if (data.repeat) - { - wrapS = gl.REPEAT; - wrapT = gl.REPEAT; - } + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, data.magFilter ? data.magFilter : gl.LINEAR ); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, data.wrapS ? data.wrapS : gl.CLAMP_TO_EDGE ); - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, !!data.flipY); - - if (data.width) - { - var width = (data.width) ? data.width : 512; - var height = (data.height) ? data.height : 2; - var border = (data.border) ? data.border : 0; - - // void texImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, ArrayBufferView? pixels); - gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, border, format, gl.UNSIGNED_BYTE, null); - } - else - { - // void texImage2D(GLenum target, GLint level, GLenum internalformat, GLenum format, GLenum type, ImageData? pixels); - gl.texImage2D(gl.TEXTURE_2D, 0, format, gl.RGBA, gl.UNSIGNED_BYTE, uniform.value.baseTexture.source); - } - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magFilter); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrapS); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrapT); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, data.wrapS ? data.wrapS : gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, data.wrapT ? data.wrapT : gl.CLAMP_TO_EDGE); } + else + { + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, texture.scaleMode === CONST.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texture.scaleMode === CONST.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + } + }; /** diff --git a/src/core/renderers/webgl/utils/AbstractFilter.js b/src/core/renderers/webgl/utils/AbstractFilter.js index a29f5de..8ec3947 100644 --- a/src/core/renderers/webgl/utils/AbstractFilter.js +++ b/src/core/renderers/webgl/utils/AbstractFilter.js @@ -9,7 +9,7 @@ * @param fragmentSrc {string|string[]} The fragment source in an array of strings. * @param uniforms {object} An object containing the uniforms for this filter. */ -function AbstractFilter(fragmentSrc, uniforms) +function AbstractFilter(vertexSrc, fragmentSrc, uniforms) { /** * An array of passes - some filters contain a few steps this array simply stores the steps in a liniear fashion. @@ -38,12 +38,15 @@ this.uniforms = uniforms || {}; + this.vertexSrc = vertexSrc; + /** * @member {string[]} * @private */ this.fragmentSrc = fragmentSrc; + //typeof fragmentSrc === 'string' ? fragmentSrc.split('') : (fragmentSrc || []); } diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 78df77f..401042c 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -32,6 +32,8 @@ { utils.sayHello('webGL'); + WebGLRenderer._TEMP__ = this; + if (options) { for (var i in CONST.defaultRenderOptions) @@ -431,6 +433,7 @@ texture.on('dispose', this._boundDestroyTexture); } + gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultipliedAlpha); diff --git a/src/core/renderers/webgl/managers/FilterManager.js b/src/core/renderers/webgl/managers/FilterManager.js index 29e97a3..30c80e1 100644 --- a/src/core/renderers/webgl/managers/FilterManager.js +++ b/src/core/renderers/webgl/managers/FilterManager.js @@ -198,12 +198,12 @@ // TODO playing around here.. this is temporary - (will end up in the shader) -FilterManager.prototype.calculateMappedMatrix = function (filterArea, sprite) +FilterManager.prototype.calculateMappedMatrix = function (filterArea, sprite, outputMatrix) { - var worldTransform = sprite.worldTransform.copy(math.Matrix.TEMP_MATRIX); - var texture = sprite.texture.baseTexture; + worldTransform = sprite.worldTransform.copy(math.Matrix.TEMP_MATRIX); + texture = sprite.texture.baseTexture; - var mappedMatrix = this.tempMatrix.identity(); + var mappedMatrix = outputMatrix.identity(); // scale.. var ratio = this.textureSize.height / this.textureSize.width; diff --git a/src/core/renderers/webgl/managers/MaskManager.js b/src/core/renderers/webgl/managers/MaskManager.js index 3e7f4a7..732438d 100644 --- a/src/core/renderers/webgl/managers/MaskManager.js +++ b/src/core/renderers/webgl/managers/MaskManager.js @@ -55,7 +55,7 @@ MaskManager.prototype.pushSpriteMask = function (target, maskData) { var alphaMaskFilter = this.alphaMaskPool.pop(); - + if (!alphaMaskFilter) { alphaMaskFilter = [new AlphaMaskFilter(maskData)]; diff --git a/src/core/renderers/webgl/shaders/Shader.js b/src/core/renderers/webgl/shaders/Shader.js index f44095b..8eeeae5 100644 --- a/src/core/renderers/webgl/shaders/Shader.js +++ b/src/core/renderers/webgl/shaders/Shader.js @@ -1,4 +1,5 @@ -var utils = require('../../../utils'); +var utils = require('../../../utils'), + CONST = require('../../../const'); /** * @class @@ -7,7 +8,7 @@ * @param [vertexSrc] {string} The source of the vertex shader. * @param [fragmentSrc] {string} The source of the fragment shader. * @param [uniforms] {object} Uniforms for this shader. - * @param [attributes] {object} Attributes for this shader. + * @param [attributes] {obje=ct} Attributes for this shader. */ function Shader(shaderManager, vertexSrc, fragmentSrc, uniforms, attributes) { @@ -34,7 +35,7 @@ this.attributes = attributes || {}; - this.textureCount = 0; + this.textureCount = 1; /** * The vertex shader. @@ -394,7 +395,8 @@ // PIXI.Texture case 't': case 'sampler2D': - if (!uniform.value || !uniform.value.baseTexture || !uniform.value.baseTexture.hasLoaded) + + if (!uniform.value || !uniform.value.baseTexture.hasLoaded) { break; } @@ -402,6 +404,13 @@ // activate this texture gl.activeTexture(gl['TEXTURE' + this.textureCount]); + var texture = uniform.value.baseTexture._glTextures[gl.id]; + + if(!texture) + { + this.initSampler2D(uniform); + } + // bind the texture gl.bindTexture(gl.TEXTURE_2D, uniform.value.baseTexture._glTextures[gl.id]); @@ -411,13 +420,6 @@ // increment next texture id this.textureCount++; - // initialize the texture if we haven't yet - if (!uniform._init) - { - this.initSampler2D(uniform); - - uniform._init = true; - } break; default: @@ -427,7 +429,7 @@ Shader.prototype.syncUniforms = function () { - this.textureCount = 0; + this.textureCount = 1; for (var key in this.uniforms) { @@ -444,7 +446,14 @@ { var gl = this.gl; - // Extended texture data + var texture = uniform.value.baseTexture; + + texture._glTextures[gl.id] = gl.createTexture(); + + gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); + + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultipliedAlpha); + if (uniform.textureData) { var data = uniform.textureData; @@ -459,40 +468,25 @@ // magFilter can be: gl.LINEAR, gl.LINEAR_MIPMAP_LINEAR or gl.NEAREST // wrapS/T can be: gl.CLAMP_TO_EDGE or gl.REPEAT - var magFilter = (data.magFilter) ? data.magFilter : gl.LINEAR; - var minFilter = (data.minFilter) ? data.minFilter : gl.LINEAR; - var wrapS = (data.wrapS) ? data.wrapS : gl.CLAMP_TO_EDGE; - var wrapT = (data.wrapT) ? data.wrapT : gl.CLAMP_TO_EDGE; - var format = (data.luminance) ? gl.LUMINANCE : gl.RGBA; + gl.texImage2D(gl.TEXTURE_2D, 0, data.luminance ? gl.LUMINANCE : gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source); - if (data.repeat) - { - wrapS = gl.REPEAT; - wrapT = gl.REPEAT; - } + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, data.magFilter ? data.magFilter : gl.LINEAR ); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, data.wrapS ? data.wrapS : gl.CLAMP_TO_EDGE ); - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, !!data.flipY); - - if (data.width) - { - var width = (data.width) ? data.width : 512; - var height = (data.height) ? data.height : 2; - var border = (data.border) ? data.border : 0; - - // void texImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, ArrayBufferView? pixels); - gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, border, format, gl.UNSIGNED_BYTE, null); - } - else - { - // void texImage2D(GLenum target, GLint level, GLenum internalformat, GLenum format, GLenum type, ImageData? pixels); - gl.texImage2D(gl.TEXTURE_2D, 0, format, gl.RGBA, gl.UNSIGNED_BYTE, uniform.value.baseTexture.source); - } - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magFilter); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrapS); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrapT); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, data.wrapS ? data.wrapS : gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, data.wrapT ? data.wrapT : gl.CLAMP_TO_EDGE); } + else + { + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, texture.scaleMode === CONST.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texture.scaleMode === CONST.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + } + }; /** diff --git a/src/core/renderers/webgl/utils/AbstractFilter.js b/src/core/renderers/webgl/utils/AbstractFilter.js index a29f5de..8ec3947 100644 --- a/src/core/renderers/webgl/utils/AbstractFilter.js +++ b/src/core/renderers/webgl/utils/AbstractFilter.js @@ -9,7 +9,7 @@ * @param fragmentSrc {string|string[]} The fragment source in an array of strings. * @param uniforms {object} An object containing the uniforms for this filter. */ -function AbstractFilter(fragmentSrc, uniforms) +function AbstractFilter(vertexSrc, fragmentSrc, uniforms) { /** * An array of passes - some filters contain a few steps this array simply stores the steps in a liniear fashion. @@ -38,12 +38,15 @@ this.uniforms = uniforms || {}; + this.vertexSrc = vertexSrc; + /** * @member {string[]} * @private */ this.fragmentSrc = fragmentSrc; + //typeof fragmentSrc === 'string' ? fragmentSrc.split('') : (fragmentSrc || []); } diff --git a/src/core/renderers/webgl/utils/AlphaMaskFilter.js b/src/core/renderers/webgl/utils/AlphaMaskFilter.js deleted file mode 100644 index 1d00cae..0000000 --- a/src/core/renderers/webgl/utils/AlphaMaskFilter.js +++ /dev/null @@ -1,136 +0,0 @@ -var AbstractFilter = require('./AbstractFilter'); - -/** - * The AlphaMaskFilter class uses the pixel values from the specified texture (called the displacement map) to perform a displacement of an object. - * You can use this filter to apply all manor of crazy warping effects - * Currently the r property of the texture is used to offset the x and the g property of the texture is used to offset the y. - * - * @class - * @extends AbstractFilter - * @namespace PIXI - * @param texture {Texture} The texture used for the displacement map * must be power of 2 texture at the moment - */ -function AlphaMaskFilter(sprite) -{ - AbstractFilter.call(this); - - this.sprite = sprite; - - var texture = sprite.texture; - // texture.baseTexture._powerOf2 = true; - - // set the uniforms - this.uniforms = { - mask: { type: 'sampler2D', value: texture }, - mapDimensions: { type: '2f', value: { x: 1, y: 5112 } }, - dimensions: { type: '4fv', value: [0, 0, 0, 0] }, - offset: { type: '2f', value: { x: 0, y: 0 } }, - otherMatrix: { type: 'mat3', value: new Float32Array(1, 0, 0, - 0, 1, 0, - 0, 0, 1) } - }; - - if (texture.baseTexture.hasLoaded) - { - this.uniforms.mask.value.x = texture.width; - this.uniforms.mask.value.y = texture.height; - } - else - { - this.boundLoadedFunction = this.onTextureLoaded.bind(this); - - texture.baseTexture.on('loaded', this.boundLoadedFunction); - } - - this.vertexSrc = [ - 'attribute vec2 aVertexPosition;', - 'attribute vec2 aTextureCoord;', - 'attribute vec4 aColor;', - - 'uniform mat3 projectionMatrix;', - 'uniform mat3 otherMatrix;', - - 'varying vec2 vMaskCoord;', - 'varying vec2 vTextureCoord;', - 'varying vec4 vColor;', - - 'void main(void)', - '{', - ' gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', - ' vTextureCoord = aTextureCoord;', - ' vMaskCoord = ( otherMatrix * vec3( aTextureCoord, 1.0) ).xy;', - ' vColor = vec4(aColor.rgb * aColor.a, aColor.a);', - '}' - ].join('\n'); - - this.fragmentSrc = [ - 'precision lowp float;', - - 'varying vec2 vMaskCoord;', - 'varying vec2 vTextureCoord;', - 'varying vec4 vColor;', - - 'uniform sampler2D uSampler;', - 'uniform sampler2D mask;', - - 'void main(void)', - '{', - ' vec4 original = texture2D(uSampler, vTextureCoord);', - ' vec4 masky = texture2D(mask, vMaskCoord);', - ' original *= (masky.r * masky.a);', - ' gl_FragColor = original;', - '}' - ].join('\n'); -} - -AlphaMaskFilter.prototype = Object.create(AbstractFilter.prototype); -AlphaMaskFilter.prototype.constructor = AlphaMaskFilter; -module.exports = AlphaMaskFilter; - -/** - * Sets the map dimensions uniforms when the texture becomes available. - * - */ -AlphaMaskFilter.prototype.onTextureLoaded = function () -{ - this.uniforms.mapDimensions.value.x = this.uniforms.mask.value.width; - this.uniforms.mapDimensions.value.y = this.uniforms.mask.value.height; - - this.uniforms.mask.value.baseTexture.off('loaded', this.boundLoadedFunction); -}; - -Object.defineProperties(AlphaMaskFilter.prototype, { - /** - * The texture used for the displacement map. Must be power of 2 sized texture. - * - * @member {Texture} - * @memberof AlphaMaskFilter# - */ - map: { - get: function () - { - return this.uniforms.mask.value; - }, - set: function (value) - { - this.uniforms.mask.value = value; - } - }, - - /** - * The offset used to move the displacement map. - * - * @member {Point} - * @memberof AlphaMaskFilter# - */ - offset: { - get: function() - { - return this.uniforms.offset.value; - }, - set: function(value) - { - this.uniforms.offset.value = value; - } - } -}); diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 78df77f..401042c 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -32,6 +32,8 @@ { utils.sayHello('webGL'); + WebGLRenderer._TEMP__ = this; + if (options) { for (var i in CONST.defaultRenderOptions) @@ -431,6 +433,7 @@ texture.on('dispose', this._boundDestroyTexture); } + gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultipliedAlpha); diff --git a/src/core/renderers/webgl/managers/FilterManager.js b/src/core/renderers/webgl/managers/FilterManager.js index 29e97a3..30c80e1 100644 --- a/src/core/renderers/webgl/managers/FilterManager.js +++ b/src/core/renderers/webgl/managers/FilterManager.js @@ -198,12 +198,12 @@ // TODO playing around here.. this is temporary - (will end up in the shader) -FilterManager.prototype.calculateMappedMatrix = function (filterArea, sprite) +FilterManager.prototype.calculateMappedMatrix = function (filterArea, sprite, outputMatrix) { - var worldTransform = sprite.worldTransform.copy(math.Matrix.TEMP_MATRIX); - var texture = sprite.texture.baseTexture; + worldTransform = sprite.worldTransform.copy(math.Matrix.TEMP_MATRIX); + texture = sprite.texture.baseTexture; - var mappedMatrix = this.tempMatrix.identity(); + var mappedMatrix = outputMatrix.identity(); // scale.. var ratio = this.textureSize.height / this.textureSize.width; diff --git a/src/core/renderers/webgl/managers/MaskManager.js b/src/core/renderers/webgl/managers/MaskManager.js index 3e7f4a7..732438d 100644 --- a/src/core/renderers/webgl/managers/MaskManager.js +++ b/src/core/renderers/webgl/managers/MaskManager.js @@ -55,7 +55,7 @@ MaskManager.prototype.pushSpriteMask = function (target, maskData) { var alphaMaskFilter = this.alphaMaskPool.pop(); - + if (!alphaMaskFilter) { alphaMaskFilter = [new AlphaMaskFilter(maskData)]; diff --git a/src/core/renderers/webgl/shaders/Shader.js b/src/core/renderers/webgl/shaders/Shader.js index f44095b..8eeeae5 100644 --- a/src/core/renderers/webgl/shaders/Shader.js +++ b/src/core/renderers/webgl/shaders/Shader.js @@ -1,4 +1,5 @@ -var utils = require('../../../utils'); +var utils = require('../../../utils'), + CONST = require('../../../const'); /** * @class @@ -7,7 +8,7 @@ * @param [vertexSrc] {string} The source of the vertex shader. * @param [fragmentSrc] {string} The source of the fragment shader. * @param [uniforms] {object} Uniforms for this shader. - * @param [attributes] {object} Attributes for this shader. + * @param [attributes] {obje=ct} Attributes for this shader. */ function Shader(shaderManager, vertexSrc, fragmentSrc, uniforms, attributes) { @@ -34,7 +35,7 @@ this.attributes = attributes || {}; - this.textureCount = 0; + this.textureCount = 1; /** * The vertex shader. @@ -394,7 +395,8 @@ // PIXI.Texture case 't': case 'sampler2D': - if (!uniform.value || !uniform.value.baseTexture || !uniform.value.baseTexture.hasLoaded) + + if (!uniform.value || !uniform.value.baseTexture.hasLoaded) { break; } @@ -402,6 +404,13 @@ // activate this texture gl.activeTexture(gl['TEXTURE' + this.textureCount]); + var texture = uniform.value.baseTexture._glTextures[gl.id]; + + if(!texture) + { + this.initSampler2D(uniform); + } + // bind the texture gl.bindTexture(gl.TEXTURE_2D, uniform.value.baseTexture._glTextures[gl.id]); @@ -411,13 +420,6 @@ // increment next texture id this.textureCount++; - // initialize the texture if we haven't yet - if (!uniform._init) - { - this.initSampler2D(uniform); - - uniform._init = true; - } break; default: @@ -427,7 +429,7 @@ Shader.prototype.syncUniforms = function () { - this.textureCount = 0; + this.textureCount = 1; for (var key in this.uniforms) { @@ -444,7 +446,14 @@ { var gl = this.gl; - // Extended texture data + var texture = uniform.value.baseTexture; + + texture._glTextures[gl.id] = gl.createTexture(); + + gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); + + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultipliedAlpha); + if (uniform.textureData) { var data = uniform.textureData; @@ -459,40 +468,25 @@ // magFilter can be: gl.LINEAR, gl.LINEAR_MIPMAP_LINEAR or gl.NEAREST // wrapS/T can be: gl.CLAMP_TO_EDGE or gl.REPEAT - var magFilter = (data.magFilter) ? data.magFilter : gl.LINEAR; - var minFilter = (data.minFilter) ? data.minFilter : gl.LINEAR; - var wrapS = (data.wrapS) ? data.wrapS : gl.CLAMP_TO_EDGE; - var wrapT = (data.wrapT) ? data.wrapT : gl.CLAMP_TO_EDGE; - var format = (data.luminance) ? gl.LUMINANCE : gl.RGBA; + gl.texImage2D(gl.TEXTURE_2D, 0, data.luminance ? gl.LUMINANCE : gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source); - if (data.repeat) - { - wrapS = gl.REPEAT; - wrapT = gl.REPEAT; - } + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, data.magFilter ? data.magFilter : gl.LINEAR ); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, data.wrapS ? data.wrapS : gl.CLAMP_TO_EDGE ); - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, !!data.flipY); - - if (data.width) - { - var width = (data.width) ? data.width : 512; - var height = (data.height) ? data.height : 2; - var border = (data.border) ? data.border : 0; - - // void texImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, ArrayBufferView? pixels); - gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, border, format, gl.UNSIGNED_BYTE, null); - } - else - { - // void texImage2D(GLenum target, GLint level, GLenum internalformat, GLenum format, GLenum type, ImageData? pixels); - gl.texImage2D(gl.TEXTURE_2D, 0, format, gl.RGBA, gl.UNSIGNED_BYTE, uniform.value.baseTexture.source); - } - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magFilter); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrapS); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrapT); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, data.wrapS ? data.wrapS : gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, data.wrapT ? data.wrapT : gl.CLAMP_TO_EDGE); } + else + { + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, texture.scaleMode === CONST.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texture.scaleMode === CONST.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + } + }; /** diff --git a/src/core/renderers/webgl/utils/AbstractFilter.js b/src/core/renderers/webgl/utils/AbstractFilter.js index a29f5de..8ec3947 100644 --- a/src/core/renderers/webgl/utils/AbstractFilter.js +++ b/src/core/renderers/webgl/utils/AbstractFilter.js @@ -9,7 +9,7 @@ * @param fragmentSrc {string|string[]} The fragment source in an array of strings. * @param uniforms {object} An object containing the uniforms for this filter. */ -function AbstractFilter(fragmentSrc, uniforms) +function AbstractFilter(vertexSrc, fragmentSrc, uniforms) { /** * An array of passes - some filters contain a few steps this array simply stores the steps in a liniear fashion. @@ -38,12 +38,15 @@ this.uniforms = uniforms || {}; + this.vertexSrc = vertexSrc; + /** * @member {string[]} * @private */ this.fragmentSrc = fragmentSrc; + //typeof fragmentSrc === 'string' ? fragmentSrc.split('') : (fragmentSrc || []); } diff --git a/src/core/renderers/webgl/utils/AlphaMaskFilter.js b/src/core/renderers/webgl/utils/AlphaMaskFilter.js deleted file mode 100644 index 1d00cae..0000000 --- a/src/core/renderers/webgl/utils/AlphaMaskFilter.js +++ /dev/null @@ -1,136 +0,0 @@ -var AbstractFilter = require('./AbstractFilter'); - -/** - * The AlphaMaskFilter class uses the pixel values from the specified texture (called the displacement map) to perform a displacement of an object. - * You can use this filter to apply all manor of crazy warping effects - * Currently the r property of the texture is used to offset the x and the g property of the texture is used to offset the y. - * - * @class - * @extends AbstractFilter - * @namespace PIXI - * @param texture {Texture} The texture used for the displacement map * must be power of 2 texture at the moment - */ -function AlphaMaskFilter(sprite) -{ - AbstractFilter.call(this); - - this.sprite = sprite; - - var texture = sprite.texture; - // texture.baseTexture._powerOf2 = true; - - // set the uniforms - this.uniforms = { - mask: { type: 'sampler2D', value: texture }, - mapDimensions: { type: '2f', value: { x: 1, y: 5112 } }, - dimensions: { type: '4fv', value: [0, 0, 0, 0] }, - offset: { type: '2f', value: { x: 0, y: 0 } }, - otherMatrix: { type: 'mat3', value: new Float32Array(1, 0, 0, - 0, 1, 0, - 0, 0, 1) } - }; - - if (texture.baseTexture.hasLoaded) - { - this.uniforms.mask.value.x = texture.width; - this.uniforms.mask.value.y = texture.height; - } - else - { - this.boundLoadedFunction = this.onTextureLoaded.bind(this); - - texture.baseTexture.on('loaded', this.boundLoadedFunction); - } - - this.vertexSrc = [ - 'attribute vec2 aVertexPosition;', - 'attribute vec2 aTextureCoord;', - 'attribute vec4 aColor;', - - 'uniform mat3 projectionMatrix;', - 'uniform mat3 otherMatrix;', - - 'varying vec2 vMaskCoord;', - 'varying vec2 vTextureCoord;', - 'varying vec4 vColor;', - - 'void main(void)', - '{', - ' gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', - ' vTextureCoord = aTextureCoord;', - ' vMaskCoord = ( otherMatrix * vec3( aTextureCoord, 1.0) ).xy;', - ' vColor = vec4(aColor.rgb * aColor.a, aColor.a);', - '}' - ].join('\n'); - - this.fragmentSrc = [ - 'precision lowp float;', - - 'varying vec2 vMaskCoord;', - 'varying vec2 vTextureCoord;', - 'varying vec4 vColor;', - - 'uniform sampler2D uSampler;', - 'uniform sampler2D mask;', - - 'void main(void)', - '{', - ' vec4 original = texture2D(uSampler, vTextureCoord);', - ' vec4 masky = texture2D(mask, vMaskCoord);', - ' original *= (masky.r * masky.a);', - ' gl_FragColor = original;', - '}' - ].join('\n'); -} - -AlphaMaskFilter.prototype = Object.create(AbstractFilter.prototype); -AlphaMaskFilter.prototype.constructor = AlphaMaskFilter; -module.exports = AlphaMaskFilter; - -/** - * Sets the map dimensions uniforms when the texture becomes available. - * - */ -AlphaMaskFilter.prototype.onTextureLoaded = function () -{ - this.uniforms.mapDimensions.value.x = this.uniforms.mask.value.width; - this.uniforms.mapDimensions.value.y = this.uniforms.mask.value.height; - - this.uniforms.mask.value.baseTexture.off('loaded', this.boundLoadedFunction); -}; - -Object.defineProperties(AlphaMaskFilter.prototype, { - /** - * The texture used for the displacement map. Must be power of 2 sized texture. - * - * @member {Texture} - * @memberof AlphaMaskFilter# - */ - map: { - get: function () - { - return this.uniforms.mask.value; - }, - set: function (value) - { - this.uniforms.mask.value = value; - } - }, - - /** - * The offset used to move the displacement map. - * - * @member {Point} - * @memberof AlphaMaskFilter# - */ - offset: { - get: function() - { - return this.uniforms.offset.value; - }, - set: function(value) - { - this.uniforms.offset.value = value; - } - } -}); diff --git a/src/core/renderers/webgl/utils/SpriteMaskFilter.js b/src/core/renderers/webgl/utils/SpriteMaskFilter.js index 1b5cc37..62f7c7e 100644 --- a/src/core/renderers/webgl/utils/SpriteMaskFilter.js +++ b/src/core/renderers/webgl/utils/SpriteMaskFilter.js @@ -1,4 +1,5 @@ -var AbstractFilter = require('./AbstractFilter'); +var AbstractFilter = require('./AbstractFilter'), + math = require('../../../math'); /** * The AlphaMaskFilter class uses the pixel values from the specified texture (called the displacement map) to perform a displacement of an object. @@ -12,39 +13,11 @@ */ function AlphaMaskFilter(sprite) { - AbstractFilter.call(this); + var maskMatrix = new math.Matrix(); - this.sprite = sprite; - - var texture = sprite.texture; - // texture.baseTexture._powerOf2 = true; - - // set the uniforms - this.uniforms = { - mask: { type: 'sampler2D', value: texture }, - mapDimensions: { type: '2f', value: { x: 1, y: 5112 } }, - dimensions: { type: '4fv', value: [0, 0, 0, 0] }, - offset: { type: '2f', value: { x: 0, y: 0 } }, - otherMatrix: { type: 'mat3', value: new Float32Array(1, 0, 0, - 0, 1, 0, - 0, 0, 1) } - }; - - if (texture.baseTexture.hasLoaded) - { - this.uniforms.mask.value.x = texture.width; - this.uniforms.mask.value.y = texture.height; - } - else - { - this.boundLoadedFunction = this.onTextureLoaded.bind(this); - - texture.baseTexture.on('loaded', this.boundLoadedFunction); - } - - this.vertexSrc = [ - - + AbstractFilter.call(this, + // vertex shader + [ 'attribute vec2 aVertexPosition;', 'attribute vec2 aTextureCoord;', 'attribute vec4 aColor;', @@ -56,22 +29,17 @@ 'varying vec2 vTextureCoord;', 'varying vec4 vColor;', - 'const vec2 center = vec2(-1.0, 1.0);', - - 'void main(void){', - - 'gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', + 'void main(void)', + '{', + ' gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', ' vTextureCoord = aTextureCoord;', - ' vMaskCoord = ( otherMatrix * vec3( aTextureCoord, 1.0) ).xy;', - ' vColor = vec4(aColor.rgb * aColor.a, aColor.a);', - '}' - ].join('\n'); - - this.fragmentSrc = [ - 'precision mediump float;', + ].join('\n'), + // fragment shader + [ + 'precision lowp float;', 'varying vec2 vMaskCoord;', 'varying vec2 vTextureCoord;', @@ -79,36 +47,43 @@ 'uniform sampler2D uSampler;', 'uniform sampler2D mask;', - 'uniform vec2 mapDimensions;', - 'uniform vec4 dimensions;', - 'uniform vec2 offset;', - 'void main()', + 'void main(void)', '{', ' vec4 original = texture2D(uSampler, vTextureCoord);', ' vec4 masky = texture2D(mask, vMaskCoord);', ' original *= (masky.r * masky.a);', ' gl_FragColor = original;', '}' - ].join('\n'); + ].join('\n'), + // uniforms + { + mask: { type: 'sampler2D', value: sprite.texture }, + otherMatrix: { type: 'mat3', value: maskMatrix.toArray(true) } + }); + + this.maskSprite = sprite; + this.maskMatrix = maskMatrix; } AlphaMaskFilter.prototype = Object.create(AbstractFilter.prototype); AlphaMaskFilter.prototype.constructor = AlphaMaskFilter; module.exports = AlphaMaskFilter; -/** - * Sets the map dimensions uniforms when the texture becomes available. - * - */ -AlphaMaskFilter.prototype.onTextureLoaded = function () +AlphaMaskFilter.prototype.applyFilter = function (renderer, input, output) { - this.uniforms.mapDimensions.value.x = this.uniforms.mask.value.width; - this.uniforms.mapDimensions.value.y = this.uniforms.mask.value.height; + var filterManager = renderer.filterManager; - this.uniforms.mask.value.baseTexture.off('loaded', this.boundLoadedFunction); + filterManager.calculateMappedMatrix(input.frame, this.maskSprite, this.maskMatrix); + + this.uniforms.otherMatrix.value = this.maskMatrix.toArray(true); + + shader = this.getShader(renderer); + // draw the filter... + filterManager.applyFilter(shader, input, output); }; + Object.defineProperties(AlphaMaskFilter.prototype, { /** * The texture used for the displacement map. Must be power of 2 sized texture. diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 78df77f..401042c 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -32,6 +32,8 @@ { utils.sayHello('webGL'); + WebGLRenderer._TEMP__ = this; + if (options) { for (var i in CONST.defaultRenderOptions) @@ -431,6 +433,7 @@ texture.on('dispose', this._boundDestroyTexture); } + gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultipliedAlpha); diff --git a/src/core/renderers/webgl/managers/FilterManager.js b/src/core/renderers/webgl/managers/FilterManager.js index 29e97a3..30c80e1 100644 --- a/src/core/renderers/webgl/managers/FilterManager.js +++ b/src/core/renderers/webgl/managers/FilterManager.js @@ -198,12 +198,12 @@ // TODO playing around here.. this is temporary - (will end up in the shader) -FilterManager.prototype.calculateMappedMatrix = function (filterArea, sprite) +FilterManager.prototype.calculateMappedMatrix = function (filterArea, sprite, outputMatrix) { - var worldTransform = sprite.worldTransform.copy(math.Matrix.TEMP_MATRIX); - var texture = sprite.texture.baseTexture; + worldTransform = sprite.worldTransform.copy(math.Matrix.TEMP_MATRIX); + texture = sprite.texture.baseTexture; - var mappedMatrix = this.tempMatrix.identity(); + var mappedMatrix = outputMatrix.identity(); // scale.. var ratio = this.textureSize.height / this.textureSize.width; diff --git a/src/core/renderers/webgl/managers/MaskManager.js b/src/core/renderers/webgl/managers/MaskManager.js index 3e7f4a7..732438d 100644 --- a/src/core/renderers/webgl/managers/MaskManager.js +++ b/src/core/renderers/webgl/managers/MaskManager.js @@ -55,7 +55,7 @@ MaskManager.prototype.pushSpriteMask = function (target, maskData) { var alphaMaskFilter = this.alphaMaskPool.pop(); - + if (!alphaMaskFilter) { alphaMaskFilter = [new AlphaMaskFilter(maskData)]; diff --git a/src/core/renderers/webgl/shaders/Shader.js b/src/core/renderers/webgl/shaders/Shader.js index f44095b..8eeeae5 100644 --- a/src/core/renderers/webgl/shaders/Shader.js +++ b/src/core/renderers/webgl/shaders/Shader.js @@ -1,4 +1,5 @@ -var utils = require('../../../utils'); +var utils = require('../../../utils'), + CONST = require('../../../const'); /** * @class @@ -7,7 +8,7 @@ * @param [vertexSrc] {string} The source of the vertex shader. * @param [fragmentSrc] {string} The source of the fragment shader. * @param [uniforms] {object} Uniforms for this shader. - * @param [attributes] {object} Attributes for this shader. + * @param [attributes] {obje=ct} Attributes for this shader. */ function Shader(shaderManager, vertexSrc, fragmentSrc, uniforms, attributes) { @@ -34,7 +35,7 @@ this.attributes = attributes || {}; - this.textureCount = 0; + this.textureCount = 1; /** * The vertex shader. @@ -394,7 +395,8 @@ // PIXI.Texture case 't': case 'sampler2D': - if (!uniform.value || !uniform.value.baseTexture || !uniform.value.baseTexture.hasLoaded) + + if (!uniform.value || !uniform.value.baseTexture.hasLoaded) { break; } @@ -402,6 +404,13 @@ // activate this texture gl.activeTexture(gl['TEXTURE' + this.textureCount]); + var texture = uniform.value.baseTexture._glTextures[gl.id]; + + if(!texture) + { + this.initSampler2D(uniform); + } + // bind the texture gl.bindTexture(gl.TEXTURE_2D, uniform.value.baseTexture._glTextures[gl.id]); @@ -411,13 +420,6 @@ // increment next texture id this.textureCount++; - // initialize the texture if we haven't yet - if (!uniform._init) - { - this.initSampler2D(uniform); - - uniform._init = true; - } break; default: @@ -427,7 +429,7 @@ Shader.prototype.syncUniforms = function () { - this.textureCount = 0; + this.textureCount = 1; for (var key in this.uniforms) { @@ -444,7 +446,14 @@ { var gl = this.gl; - // Extended texture data + var texture = uniform.value.baseTexture; + + texture._glTextures[gl.id] = gl.createTexture(); + + gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); + + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultipliedAlpha); + if (uniform.textureData) { var data = uniform.textureData; @@ -459,40 +468,25 @@ // magFilter can be: gl.LINEAR, gl.LINEAR_MIPMAP_LINEAR or gl.NEAREST // wrapS/T can be: gl.CLAMP_TO_EDGE or gl.REPEAT - var magFilter = (data.magFilter) ? data.magFilter : gl.LINEAR; - var minFilter = (data.minFilter) ? data.minFilter : gl.LINEAR; - var wrapS = (data.wrapS) ? data.wrapS : gl.CLAMP_TO_EDGE; - var wrapT = (data.wrapT) ? data.wrapT : gl.CLAMP_TO_EDGE; - var format = (data.luminance) ? gl.LUMINANCE : gl.RGBA; + gl.texImage2D(gl.TEXTURE_2D, 0, data.luminance ? gl.LUMINANCE : gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source); - if (data.repeat) - { - wrapS = gl.REPEAT; - wrapT = gl.REPEAT; - } + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, data.magFilter ? data.magFilter : gl.LINEAR ); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, data.wrapS ? data.wrapS : gl.CLAMP_TO_EDGE ); - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, !!data.flipY); - - if (data.width) - { - var width = (data.width) ? data.width : 512; - var height = (data.height) ? data.height : 2; - var border = (data.border) ? data.border : 0; - - // void texImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, ArrayBufferView? pixels); - gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, border, format, gl.UNSIGNED_BYTE, null); - } - else - { - // void texImage2D(GLenum target, GLint level, GLenum internalformat, GLenum format, GLenum type, ImageData? pixels); - gl.texImage2D(gl.TEXTURE_2D, 0, format, gl.RGBA, gl.UNSIGNED_BYTE, uniform.value.baseTexture.source); - } - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magFilter); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrapS); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrapT); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, data.wrapS ? data.wrapS : gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, data.wrapT ? data.wrapT : gl.CLAMP_TO_EDGE); } + else + { + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, texture.scaleMode === CONST.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texture.scaleMode === CONST.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + } + }; /** diff --git a/src/core/renderers/webgl/utils/AbstractFilter.js b/src/core/renderers/webgl/utils/AbstractFilter.js index a29f5de..8ec3947 100644 --- a/src/core/renderers/webgl/utils/AbstractFilter.js +++ b/src/core/renderers/webgl/utils/AbstractFilter.js @@ -9,7 +9,7 @@ * @param fragmentSrc {string|string[]} The fragment source in an array of strings. * @param uniforms {object} An object containing the uniforms for this filter. */ -function AbstractFilter(fragmentSrc, uniforms) +function AbstractFilter(vertexSrc, fragmentSrc, uniforms) { /** * An array of passes - some filters contain a few steps this array simply stores the steps in a liniear fashion. @@ -38,12 +38,15 @@ this.uniforms = uniforms || {}; + this.vertexSrc = vertexSrc; + /** * @member {string[]} * @private */ this.fragmentSrc = fragmentSrc; + //typeof fragmentSrc === 'string' ? fragmentSrc.split('') : (fragmentSrc || []); } diff --git a/src/core/renderers/webgl/utils/AlphaMaskFilter.js b/src/core/renderers/webgl/utils/AlphaMaskFilter.js deleted file mode 100644 index 1d00cae..0000000 --- a/src/core/renderers/webgl/utils/AlphaMaskFilter.js +++ /dev/null @@ -1,136 +0,0 @@ -var AbstractFilter = require('./AbstractFilter'); - -/** - * The AlphaMaskFilter class uses the pixel values from the specified texture (called the displacement map) to perform a displacement of an object. - * You can use this filter to apply all manor of crazy warping effects - * Currently the r property of the texture is used to offset the x and the g property of the texture is used to offset the y. - * - * @class - * @extends AbstractFilter - * @namespace PIXI - * @param texture {Texture} The texture used for the displacement map * must be power of 2 texture at the moment - */ -function AlphaMaskFilter(sprite) -{ - AbstractFilter.call(this); - - this.sprite = sprite; - - var texture = sprite.texture; - // texture.baseTexture._powerOf2 = true; - - // set the uniforms - this.uniforms = { - mask: { type: 'sampler2D', value: texture }, - mapDimensions: { type: '2f', value: { x: 1, y: 5112 } }, - dimensions: { type: '4fv', value: [0, 0, 0, 0] }, - offset: { type: '2f', value: { x: 0, y: 0 } }, - otherMatrix: { type: 'mat3', value: new Float32Array(1, 0, 0, - 0, 1, 0, - 0, 0, 1) } - }; - - if (texture.baseTexture.hasLoaded) - { - this.uniforms.mask.value.x = texture.width; - this.uniforms.mask.value.y = texture.height; - } - else - { - this.boundLoadedFunction = this.onTextureLoaded.bind(this); - - texture.baseTexture.on('loaded', this.boundLoadedFunction); - } - - this.vertexSrc = [ - 'attribute vec2 aVertexPosition;', - 'attribute vec2 aTextureCoord;', - 'attribute vec4 aColor;', - - 'uniform mat3 projectionMatrix;', - 'uniform mat3 otherMatrix;', - - 'varying vec2 vMaskCoord;', - 'varying vec2 vTextureCoord;', - 'varying vec4 vColor;', - - 'void main(void)', - '{', - ' gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', - ' vTextureCoord = aTextureCoord;', - ' vMaskCoord = ( otherMatrix * vec3( aTextureCoord, 1.0) ).xy;', - ' vColor = vec4(aColor.rgb * aColor.a, aColor.a);', - '}' - ].join('\n'); - - this.fragmentSrc = [ - 'precision lowp float;', - - 'varying vec2 vMaskCoord;', - 'varying vec2 vTextureCoord;', - 'varying vec4 vColor;', - - 'uniform sampler2D uSampler;', - 'uniform sampler2D mask;', - - 'void main(void)', - '{', - ' vec4 original = texture2D(uSampler, vTextureCoord);', - ' vec4 masky = texture2D(mask, vMaskCoord);', - ' original *= (masky.r * masky.a);', - ' gl_FragColor = original;', - '}' - ].join('\n'); -} - -AlphaMaskFilter.prototype = Object.create(AbstractFilter.prototype); -AlphaMaskFilter.prototype.constructor = AlphaMaskFilter; -module.exports = AlphaMaskFilter; - -/** - * Sets the map dimensions uniforms when the texture becomes available. - * - */ -AlphaMaskFilter.prototype.onTextureLoaded = function () -{ - this.uniforms.mapDimensions.value.x = this.uniforms.mask.value.width; - this.uniforms.mapDimensions.value.y = this.uniforms.mask.value.height; - - this.uniforms.mask.value.baseTexture.off('loaded', this.boundLoadedFunction); -}; - -Object.defineProperties(AlphaMaskFilter.prototype, { - /** - * The texture used for the displacement map. Must be power of 2 sized texture. - * - * @member {Texture} - * @memberof AlphaMaskFilter# - */ - map: { - get: function () - { - return this.uniforms.mask.value; - }, - set: function (value) - { - this.uniforms.mask.value = value; - } - }, - - /** - * The offset used to move the displacement map. - * - * @member {Point} - * @memberof AlphaMaskFilter# - */ - offset: { - get: function() - { - return this.uniforms.offset.value; - }, - set: function(value) - { - this.uniforms.offset.value = value; - } - } -}); diff --git a/src/core/renderers/webgl/utils/SpriteMaskFilter.js b/src/core/renderers/webgl/utils/SpriteMaskFilter.js index 1b5cc37..62f7c7e 100644 --- a/src/core/renderers/webgl/utils/SpriteMaskFilter.js +++ b/src/core/renderers/webgl/utils/SpriteMaskFilter.js @@ -1,4 +1,5 @@ -var AbstractFilter = require('./AbstractFilter'); +var AbstractFilter = require('./AbstractFilter'), + math = require('../../../math'); /** * The AlphaMaskFilter class uses the pixel values from the specified texture (called the displacement map) to perform a displacement of an object. @@ -12,39 +13,11 @@ */ function AlphaMaskFilter(sprite) { - AbstractFilter.call(this); + var maskMatrix = new math.Matrix(); - this.sprite = sprite; - - var texture = sprite.texture; - // texture.baseTexture._powerOf2 = true; - - // set the uniforms - this.uniforms = { - mask: { type: 'sampler2D', value: texture }, - mapDimensions: { type: '2f', value: { x: 1, y: 5112 } }, - dimensions: { type: '4fv', value: [0, 0, 0, 0] }, - offset: { type: '2f', value: { x: 0, y: 0 } }, - otherMatrix: { type: 'mat3', value: new Float32Array(1, 0, 0, - 0, 1, 0, - 0, 0, 1) } - }; - - if (texture.baseTexture.hasLoaded) - { - this.uniforms.mask.value.x = texture.width; - this.uniforms.mask.value.y = texture.height; - } - else - { - this.boundLoadedFunction = this.onTextureLoaded.bind(this); - - texture.baseTexture.on('loaded', this.boundLoadedFunction); - } - - this.vertexSrc = [ - - + AbstractFilter.call(this, + // vertex shader + [ 'attribute vec2 aVertexPosition;', 'attribute vec2 aTextureCoord;', 'attribute vec4 aColor;', @@ -56,22 +29,17 @@ 'varying vec2 vTextureCoord;', 'varying vec4 vColor;', - 'const vec2 center = vec2(-1.0, 1.0);', - - 'void main(void){', - - 'gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', + 'void main(void)', + '{', + ' gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', ' vTextureCoord = aTextureCoord;', - ' vMaskCoord = ( otherMatrix * vec3( aTextureCoord, 1.0) ).xy;', - ' vColor = vec4(aColor.rgb * aColor.a, aColor.a);', - '}' - ].join('\n'); - - this.fragmentSrc = [ - 'precision mediump float;', + ].join('\n'), + // fragment shader + [ + 'precision lowp float;', 'varying vec2 vMaskCoord;', 'varying vec2 vTextureCoord;', @@ -79,36 +47,43 @@ 'uniform sampler2D uSampler;', 'uniform sampler2D mask;', - 'uniform vec2 mapDimensions;', - 'uniform vec4 dimensions;', - 'uniform vec2 offset;', - 'void main()', + 'void main(void)', '{', ' vec4 original = texture2D(uSampler, vTextureCoord);', ' vec4 masky = texture2D(mask, vMaskCoord);', ' original *= (masky.r * masky.a);', ' gl_FragColor = original;', '}' - ].join('\n'); + ].join('\n'), + // uniforms + { + mask: { type: 'sampler2D', value: sprite.texture }, + otherMatrix: { type: 'mat3', value: maskMatrix.toArray(true) } + }); + + this.maskSprite = sprite; + this.maskMatrix = maskMatrix; } AlphaMaskFilter.prototype = Object.create(AbstractFilter.prototype); AlphaMaskFilter.prototype.constructor = AlphaMaskFilter; module.exports = AlphaMaskFilter; -/** - * Sets the map dimensions uniforms when the texture becomes available. - * - */ -AlphaMaskFilter.prototype.onTextureLoaded = function () +AlphaMaskFilter.prototype.applyFilter = function (renderer, input, output) { - this.uniforms.mapDimensions.value.x = this.uniforms.mask.value.width; - this.uniforms.mapDimensions.value.y = this.uniforms.mask.value.height; + var filterManager = renderer.filterManager; - this.uniforms.mask.value.baseTexture.off('loaded', this.boundLoadedFunction); + filterManager.calculateMappedMatrix(input.frame, this.maskSprite, this.maskMatrix); + + this.uniforms.otherMatrix.value = this.maskMatrix.toArray(true); + + shader = this.getShader(renderer); + // draw the filter... + filterManager.applyFilter(shader, input, output); }; + Object.defineProperties(AlphaMaskFilter.prototype, { /** * The texture used for the displacement map. Must be power of 2 sized texture. diff --git a/src/filters/BlurXFilter.js b/src/filters/BlurXFilter.js index cf02f09..7f6663b 100644 --- a/src/filters/BlurXFilter.js +++ b/src/filters/BlurXFilter.js @@ -11,6 +11,8 @@ function BlurXFilter() { AbstractFilter.call(this, + // vertex shader + null, // fragment shader [ 'precision mediump float;', diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 78df77f..401042c 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -32,6 +32,8 @@ { utils.sayHello('webGL'); + WebGLRenderer._TEMP__ = this; + if (options) { for (var i in CONST.defaultRenderOptions) @@ -431,6 +433,7 @@ texture.on('dispose', this._boundDestroyTexture); } + gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultipliedAlpha); diff --git a/src/core/renderers/webgl/managers/FilterManager.js b/src/core/renderers/webgl/managers/FilterManager.js index 29e97a3..30c80e1 100644 --- a/src/core/renderers/webgl/managers/FilterManager.js +++ b/src/core/renderers/webgl/managers/FilterManager.js @@ -198,12 +198,12 @@ // TODO playing around here.. this is temporary - (will end up in the shader) -FilterManager.prototype.calculateMappedMatrix = function (filterArea, sprite) +FilterManager.prototype.calculateMappedMatrix = function (filterArea, sprite, outputMatrix) { - var worldTransform = sprite.worldTransform.copy(math.Matrix.TEMP_MATRIX); - var texture = sprite.texture.baseTexture; + worldTransform = sprite.worldTransform.copy(math.Matrix.TEMP_MATRIX); + texture = sprite.texture.baseTexture; - var mappedMatrix = this.tempMatrix.identity(); + var mappedMatrix = outputMatrix.identity(); // scale.. var ratio = this.textureSize.height / this.textureSize.width; diff --git a/src/core/renderers/webgl/managers/MaskManager.js b/src/core/renderers/webgl/managers/MaskManager.js index 3e7f4a7..732438d 100644 --- a/src/core/renderers/webgl/managers/MaskManager.js +++ b/src/core/renderers/webgl/managers/MaskManager.js @@ -55,7 +55,7 @@ MaskManager.prototype.pushSpriteMask = function (target, maskData) { var alphaMaskFilter = this.alphaMaskPool.pop(); - + if (!alphaMaskFilter) { alphaMaskFilter = [new AlphaMaskFilter(maskData)]; diff --git a/src/core/renderers/webgl/shaders/Shader.js b/src/core/renderers/webgl/shaders/Shader.js index f44095b..8eeeae5 100644 --- a/src/core/renderers/webgl/shaders/Shader.js +++ b/src/core/renderers/webgl/shaders/Shader.js @@ -1,4 +1,5 @@ -var utils = require('../../../utils'); +var utils = require('../../../utils'), + CONST = require('../../../const'); /** * @class @@ -7,7 +8,7 @@ * @param [vertexSrc] {string} The source of the vertex shader. * @param [fragmentSrc] {string} The source of the fragment shader. * @param [uniforms] {object} Uniforms for this shader. - * @param [attributes] {object} Attributes for this shader. + * @param [attributes] {obje=ct} Attributes for this shader. */ function Shader(shaderManager, vertexSrc, fragmentSrc, uniforms, attributes) { @@ -34,7 +35,7 @@ this.attributes = attributes || {}; - this.textureCount = 0; + this.textureCount = 1; /** * The vertex shader. @@ -394,7 +395,8 @@ // PIXI.Texture case 't': case 'sampler2D': - if (!uniform.value || !uniform.value.baseTexture || !uniform.value.baseTexture.hasLoaded) + + if (!uniform.value || !uniform.value.baseTexture.hasLoaded) { break; } @@ -402,6 +404,13 @@ // activate this texture gl.activeTexture(gl['TEXTURE' + this.textureCount]); + var texture = uniform.value.baseTexture._glTextures[gl.id]; + + if(!texture) + { + this.initSampler2D(uniform); + } + // bind the texture gl.bindTexture(gl.TEXTURE_2D, uniform.value.baseTexture._glTextures[gl.id]); @@ -411,13 +420,6 @@ // increment next texture id this.textureCount++; - // initialize the texture if we haven't yet - if (!uniform._init) - { - this.initSampler2D(uniform); - - uniform._init = true; - } break; default: @@ -427,7 +429,7 @@ Shader.prototype.syncUniforms = function () { - this.textureCount = 0; + this.textureCount = 1; for (var key in this.uniforms) { @@ -444,7 +446,14 @@ { var gl = this.gl; - // Extended texture data + var texture = uniform.value.baseTexture; + + texture._glTextures[gl.id] = gl.createTexture(); + + gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]); + + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultipliedAlpha); + if (uniform.textureData) { var data = uniform.textureData; @@ -459,40 +468,25 @@ // magFilter can be: gl.LINEAR, gl.LINEAR_MIPMAP_LINEAR or gl.NEAREST // wrapS/T can be: gl.CLAMP_TO_EDGE or gl.REPEAT - var magFilter = (data.magFilter) ? data.magFilter : gl.LINEAR; - var minFilter = (data.minFilter) ? data.minFilter : gl.LINEAR; - var wrapS = (data.wrapS) ? data.wrapS : gl.CLAMP_TO_EDGE; - var wrapT = (data.wrapT) ? data.wrapT : gl.CLAMP_TO_EDGE; - var format = (data.luminance) ? gl.LUMINANCE : gl.RGBA; + gl.texImage2D(gl.TEXTURE_2D, 0, data.luminance ? gl.LUMINANCE : gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source); - if (data.repeat) - { - wrapS = gl.REPEAT; - wrapT = gl.REPEAT; - } + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, data.magFilter ? data.magFilter : gl.LINEAR ); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, data.wrapS ? data.wrapS : gl.CLAMP_TO_EDGE ); - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, !!data.flipY); - - if (data.width) - { - var width = (data.width) ? data.width : 512; - var height = (data.height) ? data.height : 2; - var border = (data.border) ? data.border : 0; - - // void texImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, ArrayBufferView? pixels); - gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, border, format, gl.UNSIGNED_BYTE, null); - } - else - { - // void texImage2D(GLenum target, GLint level, GLenum internalformat, GLenum format, GLenum type, ImageData? pixels); - gl.texImage2D(gl.TEXTURE_2D, 0, format, gl.RGBA, gl.UNSIGNED_BYTE, uniform.value.baseTexture.source); - } - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magFilter); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrapS); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrapT); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, data.wrapS ? data.wrapS : gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, data.wrapT ? data.wrapT : gl.CLAMP_TO_EDGE); } + else + { + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, texture.scaleMode === CONST.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texture.scaleMode === CONST.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + } + }; /** diff --git a/src/core/renderers/webgl/utils/AbstractFilter.js b/src/core/renderers/webgl/utils/AbstractFilter.js index a29f5de..8ec3947 100644 --- a/src/core/renderers/webgl/utils/AbstractFilter.js +++ b/src/core/renderers/webgl/utils/AbstractFilter.js @@ -9,7 +9,7 @@ * @param fragmentSrc {string|string[]} The fragment source in an array of strings. * @param uniforms {object} An object containing the uniforms for this filter. */ -function AbstractFilter(fragmentSrc, uniforms) +function AbstractFilter(vertexSrc, fragmentSrc, uniforms) { /** * An array of passes - some filters contain a few steps this array simply stores the steps in a liniear fashion. @@ -38,12 +38,15 @@ this.uniforms = uniforms || {}; + this.vertexSrc = vertexSrc; + /** * @member {string[]} * @private */ this.fragmentSrc = fragmentSrc; + //typeof fragmentSrc === 'string' ? fragmentSrc.split('') : (fragmentSrc || []); } diff --git a/src/core/renderers/webgl/utils/AlphaMaskFilter.js b/src/core/renderers/webgl/utils/AlphaMaskFilter.js deleted file mode 100644 index 1d00cae..0000000 --- a/src/core/renderers/webgl/utils/AlphaMaskFilter.js +++ /dev/null @@ -1,136 +0,0 @@ -var AbstractFilter = require('./AbstractFilter'); - -/** - * The AlphaMaskFilter class uses the pixel values from the specified texture (called the displacement map) to perform a displacement of an object. - * You can use this filter to apply all manor of crazy warping effects - * Currently the r property of the texture is used to offset the x and the g property of the texture is used to offset the y. - * - * @class - * @extends AbstractFilter - * @namespace PIXI - * @param texture {Texture} The texture used for the displacement map * must be power of 2 texture at the moment - */ -function AlphaMaskFilter(sprite) -{ - AbstractFilter.call(this); - - this.sprite = sprite; - - var texture = sprite.texture; - // texture.baseTexture._powerOf2 = true; - - // set the uniforms - this.uniforms = { - mask: { type: 'sampler2D', value: texture }, - mapDimensions: { type: '2f', value: { x: 1, y: 5112 } }, - dimensions: { type: '4fv', value: [0, 0, 0, 0] }, - offset: { type: '2f', value: { x: 0, y: 0 } }, - otherMatrix: { type: 'mat3', value: new Float32Array(1, 0, 0, - 0, 1, 0, - 0, 0, 1) } - }; - - if (texture.baseTexture.hasLoaded) - { - this.uniforms.mask.value.x = texture.width; - this.uniforms.mask.value.y = texture.height; - } - else - { - this.boundLoadedFunction = this.onTextureLoaded.bind(this); - - texture.baseTexture.on('loaded', this.boundLoadedFunction); - } - - this.vertexSrc = [ - 'attribute vec2 aVertexPosition;', - 'attribute vec2 aTextureCoord;', - 'attribute vec4 aColor;', - - 'uniform mat3 projectionMatrix;', - 'uniform mat3 otherMatrix;', - - 'varying vec2 vMaskCoord;', - 'varying vec2 vTextureCoord;', - 'varying vec4 vColor;', - - 'void main(void)', - '{', - ' gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', - ' vTextureCoord = aTextureCoord;', - ' vMaskCoord = ( otherMatrix * vec3( aTextureCoord, 1.0) ).xy;', - ' vColor = vec4(aColor.rgb * aColor.a, aColor.a);', - '}' - ].join('\n'); - - this.fragmentSrc = [ - 'precision lowp float;', - - 'varying vec2 vMaskCoord;', - 'varying vec2 vTextureCoord;', - 'varying vec4 vColor;', - - 'uniform sampler2D uSampler;', - 'uniform sampler2D mask;', - - 'void main(void)', - '{', - ' vec4 original = texture2D(uSampler, vTextureCoord);', - ' vec4 masky = texture2D(mask, vMaskCoord);', - ' original *= (masky.r * masky.a);', - ' gl_FragColor = original;', - '}' - ].join('\n'); -} - -AlphaMaskFilter.prototype = Object.create(AbstractFilter.prototype); -AlphaMaskFilter.prototype.constructor = AlphaMaskFilter; -module.exports = AlphaMaskFilter; - -/** - * Sets the map dimensions uniforms when the texture becomes available. - * - */ -AlphaMaskFilter.prototype.onTextureLoaded = function () -{ - this.uniforms.mapDimensions.value.x = this.uniforms.mask.value.width; - this.uniforms.mapDimensions.value.y = this.uniforms.mask.value.height; - - this.uniforms.mask.value.baseTexture.off('loaded', this.boundLoadedFunction); -}; - -Object.defineProperties(AlphaMaskFilter.prototype, { - /** - * The texture used for the displacement map. Must be power of 2 sized texture. - * - * @member {Texture} - * @memberof AlphaMaskFilter# - */ - map: { - get: function () - { - return this.uniforms.mask.value; - }, - set: function (value) - { - this.uniforms.mask.value = value; - } - }, - - /** - * The offset used to move the displacement map. - * - * @member {Point} - * @memberof AlphaMaskFilter# - */ - offset: { - get: function() - { - return this.uniforms.offset.value; - }, - set: function(value) - { - this.uniforms.offset.value = value; - } - } -}); diff --git a/src/core/renderers/webgl/utils/SpriteMaskFilter.js b/src/core/renderers/webgl/utils/SpriteMaskFilter.js index 1b5cc37..62f7c7e 100644 --- a/src/core/renderers/webgl/utils/SpriteMaskFilter.js +++ b/src/core/renderers/webgl/utils/SpriteMaskFilter.js @@ -1,4 +1,5 @@ -var AbstractFilter = require('./AbstractFilter'); +var AbstractFilter = require('./AbstractFilter'), + math = require('../../../math'); /** * The AlphaMaskFilter class uses the pixel values from the specified texture (called the displacement map) to perform a displacement of an object. @@ -12,39 +13,11 @@ */ function AlphaMaskFilter(sprite) { - AbstractFilter.call(this); + var maskMatrix = new math.Matrix(); - this.sprite = sprite; - - var texture = sprite.texture; - // texture.baseTexture._powerOf2 = true; - - // set the uniforms - this.uniforms = { - mask: { type: 'sampler2D', value: texture }, - mapDimensions: { type: '2f', value: { x: 1, y: 5112 } }, - dimensions: { type: '4fv', value: [0, 0, 0, 0] }, - offset: { type: '2f', value: { x: 0, y: 0 } }, - otherMatrix: { type: 'mat3', value: new Float32Array(1, 0, 0, - 0, 1, 0, - 0, 0, 1) } - }; - - if (texture.baseTexture.hasLoaded) - { - this.uniforms.mask.value.x = texture.width; - this.uniforms.mask.value.y = texture.height; - } - else - { - this.boundLoadedFunction = this.onTextureLoaded.bind(this); - - texture.baseTexture.on('loaded', this.boundLoadedFunction); - } - - this.vertexSrc = [ - - + AbstractFilter.call(this, + // vertex shader + [ 'attribute vec2 aVertexPosition;', 'attribute vec2 aTextureCoord;', 'attribute vec4 aColor;', @@ -56,22 +29,17 @@ 'varying vec2 vTextureCoord;', 'varying vec4 vColor;', - 'const vec2 center = vec2(-1.0, 1.0);', - - 'void main(void){', - - 'gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', + 'void main(void)', + '{', + ' gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', ' vTextureCoord = aTextureCoord;', - ' vMaskCoord = ( otherMatrix * vec3( aTextureCoord, 1.0) ).xy;', - ' vColor = vec4(aColor.rgb * aColor.a, aColor.a);', - '}' - ].join('\n'); - - this.fragmentSrc = [ - 'precision mediump float;', + ].join('\n'), + // fragment shader + [ + 'precision lowp float;', 'varying vec2 vMaskCoord;', 'varying vec2 vTextureCoord;', @@ -79,36 +47,43 @@ 'uniform sampler2D uSampler;', 'uniform sampler2D mask;', - 'uniform vec2 mapDimensions;', - 'uniform vec4 dimensions;', - 'uniform vec2 offset;', - 'void main()', + 'void main(void)', '{', ' vec4 original = texture2D(uSampler, vTextureCoord);', ' vec4 masky = texture2D(mask, vMaskCoord);', ' original *= (masky.r * masky.a);', ' gl_FragColor = original;', '}' - ].join('\n'); + ].join('\n'), + // uniforms + { + mask: { type: 'sampler2D', value: sprite.texture }, + otherMatrix: { type: 'mat3', value: maskMatrix.toArray(true) } + }); + + this.maskSprite = sprite; + this.maskMatrix = maskMatrix; } AlphaMaskFilter.prototype = Object.create(AbstractFilter.prototype); AlphaMaskFilter.prototype.constructor = AlphaMaskFilter; module.exports = AlphaMaskFilter; -/** - * Sets the map dimensions uniforms when the texture becomes available. - * - */ -AlphaMaskFilter.prototype.onTextureLoaded = function () +AlphaMaskFilter.prototype.applyFilter = function (renderer, input, output) { - this.uniforms.mapDimensions.value.x = this.uniforms.mask.value.width; - this.uniforms.mapDimensions.value.y = this.uniforms.mask.value.height; + var filterManager = renderer.filterManager; - this.uniforms.mask.value.baseTexture.off('loaded', this.boundLoadedFunction); + filterManager.calculateMappedMatrix(input.frame, this.maskSprite, this.maskMatrix); + + this.uniforms.otherMatrix.value = this.maskMatrix.toArray(true); + + shader = this.getShader(renderer); + // draw the filter... + filterManager.applyFilter(shader, input, output); }; + Object.defineProperties(AlphaMaskFilter.prototype, { /** * The texture used for the displacement map. Must be power of 2 sized texture. diff --git a/src/filters/BlurXFilter.js b/src/filters/BlurXFilter.js index cf02f09..7f6663b 100644 --- a/src/filters/BlurXFilter.js +++ b/src/filters/BlurXFilter.js @@ -11,6 +11,8 @@ function BlurXFilter() { AbstractFilter.call(this, + // vertex shader + null, // fragment shader [ 'precision mediump float;', diff --git a/src/filters/BlurYFilter.js b/src/filters/BlurYFilter.js index c5fa4a5..bd04819 100644 --- a/src/filters/BlurYFilter.js +++ b/src/filters/BlurYFilter.js @@ -11,7 +11,7 @@ function BlurYFilter() { AbstractFilter.call(this, - + null, [ 'precision mediump float;',