cacheAsBitmap causing issues in Canvas mode
See original GitHub issueHI all,
First of all, thank you for building this wonderful library. Really makes life so much easier!
While PIXI seems to work without any issues in Webgl mode, I see problems when I am trying to load the same code in Canvas mode. Our setup has thousand of sprites but I tried with only few components as well and if cacheAsBitmap is turned on, it’s the same issue. We are doing panning-zooming on the canvas so probably can be an issue but below code which I forked from cacheAsBitmap function in the webglRenderer seems to do the trick…
I have been diagnosing the issue and found the culprit to be cacheAsBitmap functionality.
I thought cacheAsBitmap would be same for Webgl and canvas and pretty much would work in similar fashion. Also looking at the main function, , it says ‘// TODO this can be the same as the webGL verison… will need to do a little tweaking first though…’. Looks like author realizes that and therefore has added it to the todo list.
Since I needed this fix quickly for what I am doing, I decided to copy Webgl code for similar function and use that after making few necessary changes.
Is it possible to merge that for your next release and even better, look at the code changes I did.
Added
/**
* Changes the current renderer to the one given in parameter
*
* @param {PIXI.ObjectRenderer} objectRenderer - The object renderer to use.
*/
CanvasRenderer.prototype.setObjectRenderer = function setObjectRenderer(objectRenderer) {
if (this.currentRenderer === objectRenderer) {
return;
}
this.currentRenderer.stop();
this.currentRenderer = objectRenderer;
this.currentRenderer.start();
};
/**
* This should be called if you wish to do some custom rendering
* It will basically render anything that may be batched up such as sprites
*
*/
CanvasRenderer.prototype.flush = function flush() {
this.setObjectRenderer(this.emptyRenderer);
};
and then modified function _initCachedDisplayObjectCanvas as below
DisplayObject.prototype._initCachedDisplayObjectCanvas = function _initCachedDisplayObjectCanvas(renderer) {
if (this._cacheData && this._cacheData.sprite) {
return;
}
var cacheAlpha = this.alpha;
this.alpha = 1;
// first we flush anything left in the renderer (otherwise it would get rendered to the cached texture)
renderer.plugins.sprite.renderer.flush();
// this.filters= [];
// get bounds actually transforms the object for us already!
var bounds = this.getLocalBounds();
// next we find the dimensions of the untransformed object
// this function also calls updatetransform on all its children as part of the measuring.
// This means we don't need to update the transform again in this function
// TODO pass an object to clone too? saves having to create a new one each time!
var bounds = this.getLocalBounds().clone();
// add some padding!
if (this._filters) {
var padding = this._filters[0].padding;
bounds.pad(padding);
}
// for now we cache the current renderTarget that the webGL renderer is currently using.
// this could be more elegent..
var cachedRenderTarget = renderer.context;
// We also store the filter stack - I will definitely look to change how this works a little later down the line.
// var stack = renderer.filterManager.filterStack;
// this renderTexture will be used to store the cached DisplayObject
var renderTexture = core.RenderTexture.create(bounds.width | 0, bounds.height | 0);
var textureCacheId = 'cacheAsBitmap_' + (0, _utils.uid)();
this._cacheData.textureCacheId = textureCacheId;
_BaseTexture2.default.addToCache(renderTexture.baseTexture, textureCacheId);
_Texture2.default.addToCache(renderTexture, textureCacheId);
// need to set //
var m = _tempMatrix;
m.tx = -bounds.x;
m.ty = -bounds.y;
// m.tx -= bounds.x;
// m.ty -= bounds.y;
// m.append(this.transform.worldTransform.)
// set all properties to there original so we can render to a texture
this.renderCanvas = this._cacheData.originalRenderCanvas;
renderer.render(this, renderTexture, true, m, true);
// now restore the state be setting the new properties
renderer.context = cachedRenderTarget;
this.renderCanvas = this._renderCachedCanvas;
this._calculateBounds = this._calculateCachedBounds;
this._mask = null;
this.filterArea = null;
// create our cached sprite
var cachedSprite = new core.Sprite(renderTexture);
cachedSprite.transform.worldTransform = this.transform.worldTransform;
cachedSprite.anchor.x = -(bounds.x / bounds.width);
cachedSprite.anchor.y = -(bounds.y / bounds.height);
cachedSprite._bounds = this._bounds;
cachedSprite.alpha = cacheAlpha;
// easy bounds..
this._calculateBounds = this._calculateCachedBounds;
this.getLocalBounds = this._getCachedLocalBounds;
this._cacheData.sprite = cachedSprite;
this.transform._parentID = -1;
// restore the transform of the cached sprite to avoid the nasty flicker..
if (!this.parent) {
this.parent = renderer._tempDisplayObjectParent;
this.updateTransform();
this.parent = null;
} else {
this.updateTransform();
}
this.updateTransform = this.displayObjectUpdateTransform;
this.containsPoint = cachedSprite.containsPoint.bind(cachedSprite);
};
Issue Analytics
- State:
- Created 6 years ago
- Reactions:1
- Comments:8 (1 by maintainers)
Top GitHub Comments
Hi @bigtimebuddy, Where it is causing the issues is file with thousands of line of codes. I will soon have something simpler prepared for you.
Thanks
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.