diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 04ffda5..20ccfee 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -168,7 +168,8 @@ * @member {PIXI.RenderTarget} */ this._activeRenderTarget = null; - this._activeTexture = null; + + this._nextTextureLocation = 0; this.setBlendMode(0); } @@ -250,6 +251,8 @@ return; } + this._nextTextureLocation = 0; + if (!renderTexture) { this._lastObjectRendered = displayObject; @@ -452,33 +455,48 @@ } /** - * Binds the texture ... @mat + * Binds the texture. This will return the location of the bound texture. + * It may not be the same as the one you pass in. This is due to optimisation that prevents + * needless binding of textures. For example if the texture isalready bound it will return the + * current location of the texture instead of the one provided. To bypass this use force location * * @param {PIXI.Texture} texture - the new texture - * @param {number} location - the texture location + * @param {number} location - the suggested texture location + * @param {boolean} forceLocation - force the location * @return {PIXI.WebGLRenderer} Returns itself. */ - bindTexture(texture, location) + bindTexture(texture, location, forceLocation) { - location = location || 0; - texture = texture || this.emptyTextures[location]; - texture = texture.baseTexture || texture; + texture.touched = this.textureGC.count; + + if (!forceLocation) + { + // TODO - maybe look into adding boundIds.. save us the loop? + for (let i = 0; i < this.boundTextures.length; i++) + { + if (this.boundTextures[i] === texture) + { + return i; + } + } + + if (location === undefined) + { + this._nextTextureLocation++; + this._nextTextureLocation %= this.boundTextures.length; + location = this.boundTextures.length - this._nextTextureLocation - 1; + } + } + else + { + location = location || 0; + } const gl = this.gl; const glTexture = texture._glTextures[this.CONTEXT_UID]; - texture.touched = this.textureGC.count; - - if (this.boundTextures[location] === texture) - { - return this; - } - - // TODO - what if we bind a texture that is already bound? - // Should be ok for now.. - if (!glTexture) { // this will also bind the texture.. @@ -488,12 +506,11 @@ { // bind the current texture this.boundTextures[location] = texture; - gl.activeTexture(gl.TEXTURE0 + location); gl.bindTexture(gl.TEXTURE_2D, glTexture.texture); } - return this; + return location; } /** @@ -543,7 +560,6 @@ this._activeShader = null; this._activeRenderTarget = this.rootRenderTarget; - this._activeTexture = null; // bind the main frame buffer (the screen); this.rootRenderTarget.activate(); diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 04ffda5..20ccfee 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -168,7 +168,8 @@ * @member {PIXI.RenderTarget} */ this._activeRenderTarget = null; - this._activeTexture = null; + + this._nextTextureLocation = 0; this.setBlendMode(0); } @@ -250,6 +251,8 @@ return; } + this._nextTextureLocation = 0; + if (!renderTexture) { this._lastObjectRendered = displayObject; @@ -452,33 +455,48 @@ } /** - * Binds the texture ... @mat + * Binds the texture. This will return the location of the bound texture. + * It may not be the same as the one you pass in. This is due to optimisation that prevents + * needless binding of textures. For example if the texture isalready bound it will return the + * current location of the texture instead of the one provided. To bypass this use force location * * @param {PIXI.Texture} texture - the new texture - * @param {number} location - the texture location + * @param {number} location - the suggested texture location + * @param {boolean} forceLocation - force the location * @return {PIXI.WebGLRenderer} Returns itself. */ - bindTexture(texture, location) + bindTexture(texture, location, forceLocation) { - location = location || 0; - texture = texture || this.emptyTextures[location]; - texture = texture.baseTexture || texture; + texture.touched = this.textureGC.count; + + if (!forceLocation) + { + // TODO - maybe look into adding boundIds.. save us the loop? + for (let i = 0; i < this.boundTextures.length; i++) + { + if (this.boundTextures[i] === texture) + { + return i; + } + } + + if (location === undefined) + { + this._nextTextureLocation++; + this._nextTextureLocation %= this.boundTextures.length; + location = this.boundTextures.length - this._nextTextureLocation - 1; + } + } + else + { + location = location || 0; + } const gl = this.gl; const glTexture = texture._glTextures[this.CONTEXT_UID]; - texture.touched = this.textureGC.count; - - if (this.boundTextures[location] === texture) - { - return this; - } - - // TODO - what if we bind a texture that is already bound? - // Should be ok for now.. - if (!glTexture) { // this will also bind the texture.. @@ -488,12 +506,11 @@ { // bind the current texture this.boundTextures[location] = texture; - gl.activeTexture(gl.TEXTURE0 + location); gl.bindTexture(gl.TEXTURE_2D, glTexture.texture); } - return this; + return location; } /** @@ -543,7 +560,6 @@ this._activeShader = null; this._activeRenderTarget = this.rootRenderTarget; - this._activeTexture = null; // bind the main frame buffer (the screen); this.rootRenderTarget.activate(); diff --git a/src/core/sprites/webgl/SpriteRenderer.js b/src/core/sprites/webgl/SpriteRenderer.js index d7fe485..d052a80 100644 --- a/src/core/sprites/webgl/SpriteRenderer.js +++ b/src/core/sprites/webgl/SpriteRenderer.js @@ -198,6 +198,7 @@ const uint32View = buffer.uint32View; const boundTextures = this.boundTextures; + const rendererBoundTextures = this.renderer.boundTextures; const touch = this.renderer.textureGC.count; @@ -222,7 +223,7 @@ // copy textures.. for (i = 0; i < MAX_TEXTURES; ++i) { - boundTextures[i] = this.renderer.boundTextures[i]; + boundTextures[i] = rendererBoundTextures[i]; boundTextures[i]._virtalBoundId = i; } @@ -378,7 +379,7 @@ for (i = 0; i < MAX_TEXTURES; ++i) { - this.renderer.boundTextures[i]._virtalBoundId = -1; + rendererBoundTextures[i]._virtalBoundId = -1; } // render the groups.. @@ -389,11 +390,17 @@ for (let j = 0; j < groupTextureCount; j++) { + currentTexture = group.textures[j]; + // reset virtual ids.. - this.renderer.bindTexture(group.textures[j], group.ids[j]); + // lets do a quick check.. + if (rendererBoundTextures[group.ids[j]] !== currentTexture) + { + this.renderer.bindTexture(currentTexture, group.ids[j], true); + } // reset the virtualId.. - group.textures[j]._virtalBoundId = -1; + currentTexture._virtalBoundId = -1; } // set the blend mode.. diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 04ffda5..20ccfee 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -168,7 +168,8 @@ * @member {PIXI.RenderTarget} */ this._activeRenderTarget = null; - this._activeTexture = null; + + this._nextTextureLocation = 0; this.setBlendMode(0); } @@ -250,6 +251,8 @@ return; } + this._nextTextureLocation = 0; + if (!renderTexture) { this._lastObjectRendered = displayObject; @@ -452,33 +455,48 @@ } /** - * Binds the texture ... @mat + * Binds the texture. This will return the location of the bound texture. + * It may not be the same as the one you pass in. This is due to optimisation that prevents + * needless binding of textures. For example if the texture isalready bound it will return the + * current location of the texture instead of the one provided. To bypass this use force location * * @param {PIXI.Texture} texture - the new texture - * @param {number} location - the texture location + * @param {number} location - the suggested texture location + * @param {boolean} forceLocation - force the location * @return {PIXI.WebGLRenderer} Returns itself. */ - bindTexture(texture, location) + bindTexture(texture, location, forceLocation) { - location = location || 0; - texture = texture || this.emptyTextures[location]; - texture = texture.baseTexture || texture; + texture.touched = this.textureGC.count; + + if (!forceLocation) + { + // TODO - maybe look into adding boundIds.. save us the loop? + for (let i = 0; i < this.boundTextures.length; i++) + { + if (this.boundTextures[i] === texture) + { + return i; + } + } + + if (location === undefined) + { + this._nextTextureLocation++; + this._nextTextureLocation %= this.boundTextures.length; + location = this.boundTextures.length - this._nextTextureLocation - 1; + } + } + else + { + location = location || 0; + } const gl = this.gl; const glTexture = texture._glTextures[this.CONTEXT_UID]; - texture.touched = this.textureGC.count; - - if (this.boundTextures[location] === texture) - { - return this; - } - - // TODO - what if we bind a texture that is already bound? - // Should be ok for now.. - if (!glTexture) { // this will also bind the texture.. @@ -488,12 +506,11 @@ { // bind the current texture this.boundTextures[location] = texture; - gl.activeTexture(gl.TEXTURE0 + location); gl.bindTexture(gl.TEXTURE_2D, glTexture.texture); } - return this; + return location; } /** @@ -543,7 +560,6 @@ this._activeShader = null; this._activeRenderTarget = this.rootRenderTarget; - this._activeTexture = null; // bind the main frame buffer (the screen); this.rootRenderTarget.activate(); diff --git a/src/core/sprites/webgl/SpriteRenderer.js b/src/core/sprites/webgl/SpriteRenderer.js index d7fe485..d052a80 100644 --- a/src/core/sprites/webgl/SpriteRenderer.js +++ b/src/core/sprites/webgl/SpriteRenderer.js @@ -198,6 +198,7 @@ const uint32View = buffer.uint32View; const boundTextures = this.boundTextures; + const rendererBoundTextures = this.renderer.boundTextures; const touch = this.renderer.textureGC.count; @@ -222,7 +223,7 @@ // copy textures.. for (i = 0; i < MAX_TEXTURES; ++i) { - boundTextures[i] = this.renderer.boundTextures[i]; + boundTextures[i] = rendererBoundTextures[i]; boundTextures[i]._virtalBoundId = i; } @@ -378,7 +379,7 @@ for (i = 0; i < MAX_TEXTURES; ++i) { - this.renderer.boundTextures[i]._virtalBoundId = -1; + rendererBoundTextures[i]._virtalBoundId = -1; } // render the groups.. @@ -389,11 +390,17 @@ for (let j = 0; j < groupTextureCount; j++) { + currentTexture = group.textures[j]; + // reset virtual ids.. - this.renderer.bindTexture(group.textures[j], group.ids[j]); + // lets do a quick check.. + if (rendererBoundTextures[group.ids[j]] !== currentTexture) + { + this.renderer.bindTexture(currentTexture, group.ids[j], true); + } // reset the virtualId.. - group.textures[j]._virtalBoundId = -1; + currentTexture._virtalBoundId = -1; } // set the blend mode.. diff --git a/src/extras/webgl/TilingSpriteRenderer.js b/src/extras/webgl/TilingSpriteRenderer.js index bdf815c..cc97c2d 100644 --- a/src/extras/webgl/TilingSpriteRenderer.js +++ b/src/extras/webgl/TilingSpriteRenderer.js @@ -127,6 +127,7 @@ shader.uniforms.uClampFrame = uv.uClampFrame; shader.uniforms.uClampOffset = uv.uClampOffset; } + shader.uniforms.uTransform = tempMat.toArray(true); const color = tempArray; @@ -136,7 +137,8 @@ shader.uniforms.uColor = color; shader.uniforms.translationMatrix = ts.transform.worldTransform.toArray(true); - renderer.bindTexture(tex); + shader.uniforms.uSampler = renderer.bindTexture(tex); + renderer.setBlendMode(ts.blendMode); quad.draw(); diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 04ffda5..20ccfee 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -168,7 +168,8 @@ * @member {PIXI.RenderTarget} */ this._activeRenderTarget = null; - this._activeTexture = null; + + this._nextTextureLocation = 0; this.setBlendMode(0); } @@ -250,6 +251,8 @@ return; } + this._nextTextureLocation = 0; + if (!renderTexture) { this._lastObjectRendered = displayObject; @@ -452,33 +455,48 @@ } /** - * Binds the texture ... @mat + * Binds the texture. This will return the location of the bound texture. + * It may not be the same as the one you pass in. This is due to optimisation that prevents + * needless binding of textures. For example if the texture isalready bound it will return the + * current location of the texture instead of the one provided. To bypass this use force location * * @param {PIXI.Texture} texture - the new texture - * @param {number} location - the texture location + * @param {number} location - the suggested texture location + * @param {boolean} forceLocation - force the location * @return {PIXI.WebGLRenderer} Returns itself. */ - bindTexture(texture, location) + bindTexture(texture, location, forceLocation) { - location = location || 0; - texture = texture || this.emptyTextures[location]; - texture = texture.baseTexture || texture; + texture.touched = this.textureGC.count; + + if (!forceLocation) + { + // TODO - maybe look into adding boundIds.. save us the loop? + for (let i = 0; i < this.boundTextures.length; i++) + { + if (this.boundTextures[i] === texture) + { + return i; + } + } + + if (location === undefined) + { + this._nextTextureLocation++; + this._nextTextureLocation %= this.boundTextures.length; + location = this.boundTextures.length - this._nextTextureLocation - 1; + } + } + else + { + location = location || 0; + } const gl = this.gl; const glTexture = texture._glTextures[this.CONTEXT_UID]; - texture.touched = this.textureGC.count; - - if (this.boundTextures[location] === texture) - { - return this; - } - - // TODO - what if we bind a texture that is already bound? - // Should be ok for now.. - if (!glTexture) { // this will also bind the texture.. @@ -488,12 +506,11 @@ { // bind the current texture this.boundTextures[location] = texture; - gl.activeTexture(gl.TEXTURE0 + location); gl.bindTexture(gl.TEXTURE_2D, glTexture.texture); } - return this; + return location; } /** @@ -543,7 +560,6 @@ this._activeShader = null; this._activeRenderTarget = this.rootRenderTarget; - this._activeTexture = null; // bind the main frame buffer (the screen); this.rootRenderTarget.activate(); diff --git a/src/core/sprites/webgl/SpriteRenderer.js b/src/core/sprites/webgl/SpriteRenderer.js index d7fe485..d052a80 100644 --- a/src/core/sprites/webgl/SpriteRenderer.js +++ b/src/core/sprites/webgl/SpriteRenderer.js @@ -198,6 +198,7 @@ const uint32View = buffer.uint32View; const boundTextures = this.boundTextures; + const rendererBoundTextures = this.renderer.boundTextures; const touch = this.renderer.textureGC.count; @@ -222,7 +223,7 @@ // copy textures.. for (i = 0; i < MAX_TEXTURES; ++i) { - boundTextures[i] = this.renderer.boundTextures[i]; + boundTextures[i] = rendererBoundTextures[i]; boundTextures[i]._virtalBoundId = i; } @@ -378,7 +379,7 @@ for (i = 0; i < MAX_TEXTURES; ++i) { - this.renderer.boundTextures[i]._virtalBoundId = -1; + rendererBoundTextures[i]._virtalBoundId = -1; } // render the groups.. @@ -389,11 +390,17 @@ for (let j = 0; j < groupTextureCount; j++) { + currentTexture = group.textures[j]; + // reset virtual ids.. - this.renderer.bindTexture(group.textures[j], group.ids[j]); + // lets do a quick check.. + if (rendererBoundTextures[group.ids[j]] !== currentTexture) + { + this.renderer.bindTexture(currentTexture, group.ids[j], true); + } // reset the virtualId.. - group.textures[j]._virtalBoundId = -1; + currentTexture._virtalBoundId = -1; } // set the blend mode.. diff --git a/src/extras/webgl/TilingSpriteRenderer.js b/src/extras/webgl/TilingSpriteRenderer.js index bdf815c..cc97c2d 100644 --- a/src/extras/webgl/TilingSpriteRenderer.js +++ b/src/extras/webgl/TilingSpriteRenderer.js @@ -127,6 +127,7 @@ shader.uniforms.uClampFrame = uv.uClampFrame; shader.uniforms.uClampOffset = uv.uClampOffset; } + shader.uniforms.uTransform = tempMat.toArray(true); const color = tempArray; @@ -136,7 +137,8 @@ shader.uniforms.uColor = color; shader.uniforms.translationMatrix = ts.transform.worldTransform.toArray(true); - renderer.bindTexture(tex); + shader.uniforms.uSampler = renderer.bindTexture(tex); + renderer.setBlendMode(ts.blendMode); quad.draw(); diff --git a/src/mesh/webgl/MeshRenderer.js b/src/mesh/webgl/MeshRenderer.js index 968e7a5..148737e 100644 --- a/src/mesh/webgl/MeshRenderer.js +++ b/src/mesh/webgl/MeshRenderer.js @@ -90,7 +90,8 @@ glData.vertexBuffer.upload(); renderer.bindShader(glData.shader); - renderer.bindTexture(texture, 0); + + glData.shader.uniforms.uSampler = renderer.bindTexture(texture); renderer.state.setBlendMode(mesh.blendMode); glData.shader.uniforms.translationMatrix = mesh.worldTransform.toArray(true); diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 04ffda5..20ccfee 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -168,7 +168,8 @@ * @member {PIXI.RenderTarget} */ this._activeRenderTarget = null; - this._activeTexture = null; + + this._nextTextureLocation = 0; this.setBlendMode(0); } @@ -250,6 +251,8 @@ return; } + this._nextTextureLocation = 0; + if (!renderTexture) { this._lastObjectRendered = displayObject; @@ -452,33 +455,48 @@ } /** - * Binds the texture ... @mat + * Binds the texture. This will return the location of the bound texture. + * It may not be the same as the one you pass in. This is due to optimisation that prevents + * needless binding of textures. For example if the texture isalready bound it will return the + * current location of the texture instead of the one provided. To bypass this use force location * * @param {PIXI.Texture} texture - the new texture - * @param {number} location - the texture location + * @param {number} location - the suggested texture location + * @param {boolean} forceLocation - force the location * @return {PIXI.WebGLRenderer} Returns itself. */ - bindTexture(texture, location) + bindTexture(texture, location, forceLocation) { - location = location || 0; - texture = texture || this.emptyTextures[location]; - texture = texture.baseTexture || texture; + texture.touched = this.textureGC.count; + + if (!forceLocation) + { + // TODO - maybe look into adding boundIds.. save us the loop? + for (let i = 0; i < this.boundTextures.length; i++) + { + if (this.boundTextures[i] === texture) + { + return i; + } + } + + if (location === undefined) + { + this._nextTextureLocation++; + this._nextTextureLocation %= this.boundTextures.length; + location = this.boundTextures.length - this._nextTextureLocation - 1; + } + } + else + { + location = location || 0; + } const gl = this.gl; const glTexture = texture._glTextures[this.CONTEXT_UID]; - texture.touched = this.textureGC.count; - - if (this.boundTextures[location] === texture) - { - return this; - } - - // TODO - what if we bind a texture that is already bound? - // Should be ok for now.. - if (!glTexture) { // this will also bind the texture.. @@ -488,12 +506,11 @@ { // bind the current texture this.boundTextures[location] = texture; - gl.activeTexture(gl.TEXTURE0 + location); gl.bindTexture(gl.TEXTURE_2D, glTexture.texture); } - return this; + return location; } /** @@ -543,7 +560,6 @@ this._activeShader = null; this._activeRenderTarget = this.rootRenderTarget; - this._activeTexture = null; // bind the main frame buffer (the screen); this.rootRenderTarget.activate(); diff --git a/src/core/sprites/webgl/SpriteRenderer.js b/src/core/sprites/webgl/SpriteRenderer.js index d7fe485..d052a80 100644 --- a/src/core/sprites/webgl/SpriteRenderer.js +++ b/src/core/sprites/webgl/SpriteRenderer.js @@ -198,6 +198,7 @@ const uint32View = buffer.uint32View; const boundTextures = this.boundTextures; + const rendererBoundTextures = this.renderer.boundTextures; const touch = this.renderer.textureGC.count; @@ -222,7 +223,7 @@ // copy textures.. for (i = 0; i < MAX_TEXTURES; ++i) { - boundTextures[i] = this.renderer.boundTextures[i]; + boundTextures[i] = rendererBoundTextures[i]; boundTextures[i]._virtalBoundId = i; } @@ -378,7 +379,7 @@ for (i = 0; i < MAX_TEXTURES; ++i) { - this.renderer.boundTextures[i]._virtalBoundId = -1; + rendererBoundTextures[i]._virtalBoundId = -1; } // render the groups.. @@ -389,11 +390,17 @@ for (let j = 0; j < groupTextureCount; j++) { + currentTexture = group.textures[j]; + // reset virtual ids.. - this.renderer.bindTexture(group.textures[j], group.ids[j]); + // lets do a quick check.. + if (rendererBoundTextures[group.ids[j]] !== currentTexture) + { + this.renderer.bindTexture(currentTexture, group.ids[j], true); + } // reset the virtualId.. - group.textures[j]._virtalBoundId = -1; + currentTexture._virtalBoundId = -1; } // set the blend mode.. diff --git a/src/extras/webgl/TilingSpriteRenderer.js b/src/extras/webgl/TilingSpriteRenderer.js index bdf815c..cc97c2d 100644 --- a/src/extras/webgl/TilingSpriteRenderer.js +++ b/src/extras/webgl/TilingSpriteRenderer.js @@ -127,6 +127,7 @@ shader.uniforms.uClampFrame = uv.uClampFrame; shader.uniforms.uClampOffset = uv.uClampOffset; } + shader.uniforms.uTransform = tempMat.toArray(true); const color = tempArray; @@ -136,7 +137,8 @@ shader.uniforms.uColor = color; shader.uniforms.translationMatrix = ts.transform.worldTransform.toArray(true); - renderer.bindTexture(tex); + shader.uniforms.uSampler = renderer.bindTexture(tex); + renderer.setBlendMode(ts.blendMode); quad.draw(); diff --git a/src/mesh/webgl/MeshRenderer.js b/src/mesh/webgl/MeshRenderer.js index 968e7a5..148737e 100644 --- a/src/mesh/webgl/MeshRenderer.js +++ b/src/mesh/webgl/MeshRenderer.js @@ -90,7 +90,8 @@ glData.vertexBuffer.upload(); renderer.bindShader(glData.shader); - renderer.bindTexture(texture, 0); + + glData.shader.uniforms.uSampler = renderer.bindTexture(texture); renderer.state.setBlendMode(mesh.blendMode); glData.shader.uniforms.translationMatrix = mesh.worldTransform.toArray(true); diff --git a/src/particles/webgl/ParticleRenderer.js b/src/particles/webgl/ParticleRenderer.js index 11edd93..768672a 100644 --- a/src/particles/webgl/ParticleRenderer.js +++ b/src/particles/webgl/ParticleRenderer.js @@ -156,7 +156,7 @@ // make sure the texture is bound.. const baseTexture = children[0]._texture.baseTexture; - this.renderer.bindTexture(baseTexture); + this.shader.uniforms.uSampler = this.renderer.bindTexture(baseTexture); // now lets upload and render the buffers.. for (let i = 0, j = 0; i < totalChildren; i += batchSize, j += 1)