diff --git a/packages/core/src/filters/FilterSystem.js b/packages/core/src/filters/FilterSystem.js index 514ec32..3e37d7d 100644 --- a/packages/core/src/filters/FilterSystem.js +++ b/packages/core/src/filters/FilterSystem.js @@ -31,6 +31,8 @@ } } +const screenKey = 'screen'; + /** * @class * @memberof PIXI.systems @@ -88,6 +90,10 @@ filterArea: new Float32Array(4), filterClamp: new Float32Array(4), }, true); + + this._pixelsWidth = renderer.view.width; + + this._pixelsHeight = renderer.view.height; } /** @@ -127,20 +133,18 @@ state.legacy = legacy; - // round to whole number based on resolution - // TODO move that to the shader too? state.sourceFrame = target.filterArea || target.getBounds(true); state.sourceFrame.pad(padding); - if (autoFit) { state.sourceFrame.fit(this.renderer.renderTexture.destinationFrame); } - state.sourceFrame.round(resolution); + // round to whole number based on resolution + state.sourceFrame.ceil(resolution); - state.renderTexture = this.getPotFilterTexture(state.sourceFrame.width, state.sourceFrame.height, resolution); + state.renderTexture = this.getOptimalFilterTexture(state.sourceFrame.width, state.sourceFrame.height, resolution); state.filters = filters; state.destinationFrame.width = state.renderTexture.width; @@ -214,7 +218,7 @@ else { let flip = state.renderTexture; - let flop = this.getPotFilterTexture( + let flop = this.getOptimalFilterTexture( flip.width, flip.height, state.resolution @@ -347,25 +351,29 @@ } /** - * Gets a Power-of-Two render texture. + * Gets a Power-of-Two render texture or fullScreen texture * * TODO move to a seperate class could be on renderer? - * also - could cause issue with multiple contexts? * * @private - * @param {WebGLRenderingContext} gl - The webgl rendering context - * @param {number} minWidth - The minimum width of the render target. - * @param {number} minHeight - The minimum height of the render target. - * @param {number} resolution - The resolution of the render target. - * @return {PIXI.RenderTarget} The new render target. + * @param {number} minWidth - The minimum width of the render texture in real pixels. + * @param {number} minHeight - The minimum height of the render texture in real pixels. + * @param {number} [resolution=1] - The resolution of the render texture. + * @return {PIXI.RenderTexture} The new render texture. */ - getPotFilterTexture(minWidth, minHeight, resolution) + getOptimalFilterTexture(minWidth, minHeight, resolution = 1) { - minWidth = bitTwiddle.nextPow2(minWidth); - minHeight = bitTwiddle.nextPow2(minHeight); - resolution = resolution || 1; + let key = screenKey; - const key = ((minWidth & 0xFFFF) << 16) | (minHeight & 0xFFFF); + minWidth *= resolution; + minHeight *= resolution; + + if (minWidth !== this._pixelsWidth || minHeight !== this._pixelsHeight) + { + minWidth = bitTwiddle.nextPow2(minWidth); + minHeight = bitTwiddle.nextPow2(minHeight); + key = ((minWidth & 0xFFFF) << 16) | (minHeight & 0xFFFF); + } if (!this.texturePool[key]) { @@ -379,12 +387,14 @@ // temporary bypass cache.. // internally - this will cause a texture to be bound.. renderTexture = RenderTexture.create({ - width: minWidth, - height: minHeight, + width: minWidth / resolution, + height: minHeight / resolution, resolution, }); } + renderTexture.filterPoolKey = key; + return renderTexture; } @@ -398,7 +408,7 @@ { const rt = this.activeState.renderTexture; - const filterTexture = this.getPotFilterTexture(rt.width, rt.height, resolution || rt.baseTexture.resolution); + const filterTexture = this.getOptimalFilterTexture(rt.width, rt.height, resolution || rt.baseTexture.resolution); filterTexture.filterFrame = rt.filterFrame; @@ -412,15 +422,9 @@ */ returnFilterTexture(renderTexture) { + const key = renderTexture.filterPoolKey; + renderTexture.filterFrame = null; - - const base = renderTexture.baseTexture; - - const minWidth = base.width; - const minHeight = base.height; - - const key = ((minWidth & 0xFFFF) << 16) | (minHeight & 0xFFFF); - this.texturePool[key].push(renderTexture); } @@ -445,4 +449,21 @@ this.texturePool = {}; } + + resize() + { + const textures = this.texturePool[screenKey]; + + if (textures) + { + for (let j = 0; j < textures.length; j++) + { + textures[j].destroy(true); + } + } + this.texturePool[screenKey] = []; + + this._pixelsWidth = this.renderer.view.width; + this._pixelsHeight = this.renderer.view.height; + } } diff --git a/packages/core/src/filters/FilterSystem.js b/packages/core/src/filters/FilterSystem.js index 514ec32..3e37d7d 100644 --- a/packages/core/src/filters/FilterSystem.js +++ b/packages/core/src/filters/FilterSystem.js @@ -31,6 +31,8 @@ } } +const screenKey = 'screen'; + /** * @class * @memberof PIXI.systems @@ -88,6 +90,10 @@ filterArea: new Float32Array(4), filterClamp: new Float32Array(4), }, true); + + this._pixelsWidth = renderer.view.width; + + this._pixelsHeight = renderer.view.height; } /** @@ -127,20 +133,18 @@ state.legacy = legacy; - // round to whole number based on resolution - // TODO move that to the shader too? state.sourceFrame = target.filterArea || target.getBounds(true); state.sourceFrame.pad(padding); - if (autoFit) { state.sourceFrame.fit(this.renderer.renderTexture.destinationFrame); } - state.sourceFrame.round(resolution); + // round to whole number based on resolution + state.sourceFrame.ceil(resolution); - state.renderTexture = this.getPotFilterTexture(state.sourceFrame.width, state.sourceFrame.height, resolution); + state.renderTexture = this.getOptimalFilterTexture(state.sourceFrame.width, state.sourceFrame.height, resolution); state.filters = filters; state.destinationFrame.width = state.renderTexture.width; @@ -214,7 +218,7 @@ else { let flip = state.renderTexture; - let flop = this.getPotFilterTexture( + let flop = this.getOptimalFilterTexture( flip.width, flip.height, state.resolution @@ -347,25 +351,29 @@ } /** - * Gets a Power-of-Two render texture. + * Gets a Power-of-Two render texture or fullScreen texture * * TODO move to a seperate class could be on renderer? - * also - could cause issue with multiple contexts? * * @private - * @param {WebGLRenderingContext} gl - The webgl rendering context - * @param {number} minWidth - The minimum width of the render target. - * @param {number} minHeight - The minimum height of the render target. - * @param {number} resolution - The resolution of the render target. - * @return {PIXI.RenderTarget} The new render target. + * @param {number} minWidth - The minimum width of the render texture in real pixels. + * @param {number} minHeight - The minimum height of the render texture in real pixels. + * @param {number} [resolution=1] - The resolution of the render texture. + * @return {PIXI.RenderTexture} The new render texture. */ - getPotFilterTexture(minWidth, minHeight, resolution) + getOptimalFilterTexture(minWidth, minHeight, resolution = 1) { - minWidth = bitTwiddle.nextPow2(minWidth); - minHeight = bitTwiddle.nextPow2(minHeight); - resolution = resolution || 1; + let key = screenKey; - const key = ((minWidth & 0xFFFF) << 16) | (minHeight & 0xFFFF); + minWidth *= resolution; + minHeight *= resolution; + + if (minWidth !== this._pixelsWidth || minHeight !== this._pixelsHeight) + { + minWidth = bitTwiddle.nextPow2(minWidth); + minHeight = bitTwiddle.nextPow2(minHeight); + key = ((minWidth & 0xFFFF) << 16) | (minHeight & 0xFFFF); + } if (!this.texturePool[key]) { @@ -379,12 +387,14 @@ // temporary bypass cache.. // internally - this will cause a texture to be bound.. renderTexture = RenderTexture.create({ - width: minWidth, - height: minHeight, + width: minWidth / resolution, + height: minHeight / resolution, resolution, }); } + renderTexture.filterPoolKey = key; + return renderTexture; } @@ -398,7 +408,7 @@ { const rt = this.activeState.renderTexture; - const filterTexture = this.getPotFilterTexture(rt.width, rt.height, resolution || rt.baseTexture.resolution); + const filterTexture = this.getOptimalFilterTexture(rt.width, rt.height, resolution || rt.baseTexture.resolution); filterTexture.filterFrame = rt.filterFrame; @@ -412,15 +422,9 @@ */ returnFilterTexture(renderTexture) { + const key = renderTexture.filterPoolKey; + renderTexture.filterFrame = null; - - const base = renderTexture.baseTexture; - - const minWidth = base.width; - const minHeight = base.height; - - const key = ((minWidth & 0xFFFF) << 16) | (minHeight & 0xFFFF); - this.texturePool[key].push(renderTexture); } @@ -445,4 +449,21 @@ this.texturePool = {}; } + + resize() + { + const textures = this.texturePool[screenKey]; + + if (textures) + { + for (let j = 0; j < textures.length; j++) + { + textures[j].destroy(true); + } + } + this.texturePool[screenKey] = []; + + this._pixelsWidth = this.renderer.view.width; + this._pixelsHeight = this.renderer.view.height; + } } diff --git a/packages/core/src/renderTexture/RenderTexture.js b/packages/core/src/renderTexture/RenderTexture.js index a64b7e7..f1ad810 100644 --- a/packages/core/src/renderTexture/RenderTexture.js +++ b/packages/core/src/renderTexture/RenderTexture.js @@ -94,6 +94,13 @@ */ this.filterFrame = null; + /** + * The key for pooled texture of FilterSystem + * @private + * @member {string} + */ + this.filterPoolKey = null; + this.updateUvs(); } diff --git a/packages/core/src/filters/FilterSystem.js b/packages/core/src/filters/FilterSystem.js index 514ec32..3e37d7d 100644 --- a/packages/core/src/filters/FilterSystem.js +++ b/packages/core/src/filters/FilterSystem.js @@ -31,6 +31,8 @@ } } +const screenKey = 'screen'; + /** * @class * @memberof PIXI.systems @@ -88,6 +90,10 @@ filterArea: new Float32Array(4), filterClamp: new Float32Array(4), }, true); + + this._pixelsWidth = renderer.view.width; + + this._pixelsHeight = renderer.view.height; } /** @@ -127,20 +133,18 @@ state.legacy = legacy; - // round to whole number based on resolution - // TODO move that to the shader too? state.sourceFrame = target.filterArea || target.getBounds(true); state.sourceFrame.pad(padding); - if (autoFit) { state.sourceFrame.fit(this.renderer.renderTexture.destinationFrame); } - state.sourceFrame.round(resolution); + // round to whole number based on resolution + state.sourceFrame.ceil(resolution); - state.renderTexture = this.getPotFilterTexture(state.sourceFrame.width, state.sourceFrame.height, resolution); + state.renderTexture = this.getOptimalFilterTexture(state.sourceFrame.width, state.sourceFrame.height, resolution); state.filters = filters; state.destinationFrame.width = state.renderTexture.width; @@ -214,7 +218,7 @@ else { let flip = state.renderTexture; - let flop = this.getPotFilterTexture( + let flop = this.getOptimalFilterTexture( flip.width, flip.height, state.resolution @@ -347,25 +351,29 @@ } /** - * Gets a Power-of-Two render texture. + * Gets a Power-of-Two render texture or fullScreen texture * * TODO move to a seperate class could be on renderer? - * also - could cause issue with multiple contexts? * * @private - * @param {WebGLRenderingContext} gl - The webgl rendering context - * @param {number} minWidth - The minimum width of the render target. - * @param {number} minHeight - The minimum height of the render target. - * @param {number} resolution - The resolution of the render target. - * @return {PIXI.RenderTarget} The new render target. + * @param {number} minWidth - The minimum width of the render texture in real pixels. + * @param {number} minHeight - The minimum height of the render texture in real pixels. + * @param {number} [resolution=1] - The resolution of the render texture. + * @return {PIXI.RenderTexture} The new render texture. */ - getPotFilterTexture(minWidth, minHeight, resolution) + getOptimalFilterTexture(minWidth, minHeight, resolution = 1) { - minWidth = bitTwiddle.nextPow2(minWidth); - minHeight = bitTwiddle.nextPow2(minHeight); - resolution = resolution || 1; + let key = screenKey; - const key = ((minWidth & 0xFFFF) << 16) | (minHeight & 0xFFFF); + minWidth *= resolution; + minHeight *= resolution; + + if (minWidth !== this._pixelsWidth || minHeight !== this._pixelsHeight) + { + minWidth = bitTwiddle.nextPow2(minWidth); + minHeight = bitTwiddle.nextPow2(minHeight); + key = ((minWidth & 0xFFFF) << 16) | (minHeight & 0xFFFF); + } if (!this.texturePool[key]) { @@ -379,12 +387,14 @@ // temporary bypass cache.. // internally - this will cause a texture to be bound.. renderTexture = RenderTexture.create({ - width: minWidth, - height: minHeight, + width: minWidth / resolution, + height: minHeight / resolution, resolution, }); } + renderTexture.filterPoolKey = key; + return renderTexture; } @@ -398,7 +408,7 @@ { const rt = this.activeState.renderTexture; - const filterTexture = this.getPotFilterTexture(rt.width, rt.height, resolution || rt.baseTexture.resolution); + const filterTexture = this.getOptimalFilterTexture(rt.width, rt.height, resolution || rt.baseTexture.resolution); filterTexture.filterFrame = rt.filterFrame; @@ -412,15 +422,9 @@ */ returnFilterTexture(renderTexture) { + const key = renderTexture.filterPoolKey; + renderTexture.filterFrame = null; - - const base = renderTexture.baseTexture; - - const minWidth = base.width; - const minHeight = base.height; - - const key = ((minWidth & 0xFFFF) << 16) | (minHeight & 0xFFFF); - this.texturePool[key].push(renderTexture); } @@ -445,4 +449,21 @@ this.texturePool = {}; } + + resize() + { + const textures = this.texturePool[screenKey]; + + if (textures) + { + for (let j = 0; j < textures.length; j++) + { + textures[j].destroy(true); + } + } + this.texturePool[screenKey] = []; + + this._pixelsWidth = this.renderer.view.width; + this._pixelsHeight = this.renderer.view.height; + } } diff --git a/packages/core/src/renderTexture/RenderTexture.js b/packages/core/src/renderTexture/RenderTexture.js index a64b7e7..f1ad810 100644 --- a/packages/core/src/renderTexture/RenderTexture.js +++ b/packages/core/src/renderTexture/RenderTexture.js @@ -94,6 +94,13 @@ */ this.filterFrame = null; + /** + * The key for pooled texture of FilterSystem + * @private + * @member {string} + */ + this.filterPoolKey = null; + this.updateUvs(); } diff --git a/packages/math/src/shapes/Rectangle.js b/packages/math/src/shapes/Rectangle.js index af401bd..09beee5 100644 --- a/packages/math/src/shapes/Rectangle.js +++ b/packages/math/src/shapes/Rectangle.js @@ -235,14 +235,22 @@ } } - round(value) + /** + * Enlarges rectangle that way its corners lie on grid + * + * @param {number} [resolution=1] resolution + * @param {number} [eps=0.001] precision + */ + ceil(resolution = 1, eps = 0.001) { - value = value || 1; + const x2 = Math.ceil((this.x + this.width - eps) * resolution) / resolution; + const y2 = Math.ceil((this.y + this.height - eps) * resolution) / resolution; - this.x = ((this.x * value) | 0) / value; - this.y = ((this.y * value) | 0) / value; - this.width = ((this.width * value) | 0) / value; - this.height = ((this.height * value) | 0) / value; + this.x = Math.floor((this.x + eps) * resolution) / resolution; + this.y = Math.floor((this.y + eps) * resolution) / resolution; + + this.width = x2 - this.x; + this.height = y2 - this.y; } /**