Hello,
I've only just started experimenting with heavy masking in PixiJS and I've hit a performance wall when using certain configurations. Specifically, my scene can’t seem to be rendered faster than 30fps in Safari when using the Intel Iris integrated GPUs. I’m using PixiJS 4.3.5.
Here’s a boiled-down snippet of what I’m doing for the moment:
var app = new PIXI.Application(width, height, config);
var mainStage = new PIXI.Container();
var maskStage = new PIXI.Container();
var baseMaskTexture = new PIXI.BaseRenderTexture(width, height, PIXI.SCALE_MODES.LINEAR, 1);
var maskTexture = new PIXI.RenderTexture(baseMaskTexture);
var maskSprite = new PIXI.Sprite(maskTexture);
mainStage.mask = maskSprite;
app.stage.addChild(mainStage);
/* I then add about a dozen Graphics() elements to the maskStage that are later animated
through their .x, .y and .scale props. The mainStage also contains a few Graphics(). */
var img = new PIXI.Sprite.fromImage(someJPEG);
mainStage.addChild(img);
app.ticker.add(function() {
app.renderer.render(maskStage, maskTexture);
});
As PixiJS only supports Graphics and Sprites as masks at the moment, and I need my main stage to be masked by multiple individual shapes, I placed these shapes into their own container that is rendered into a texture, and that texture is used as the actual mask.
Everything is buttery smooth in Chrome and Firefox (iGPU or dGPU) and Safari (dGPU), but it all becomes super janky in Safari (iGPU). The scene itself is rendered @1.5x on retina displays to avoid as much blurriness as possible but still maintain decent performances. I guess I could go lower than @1.5x in Safari, but I’d rather avoid that.
Now as I said, I'm quite new to masking in PixiJS, so I’m not sure what could be improved (if anything), or if I should or shouldn’t be doing something. Any advice would be greatly appreciated!
Thank you
Well, if your shapes aren't moving, you dont have to call "render" every frame, but I assume that in your case they are moving.
You can try blending instead of masking: just add a sprite with maskTexture to original stage and set blendMode to PIXI.BLEND_MODES.MULTIPLY.
That's how http://pixijs.github.io/examples/#/layers/lighting.js works. But it also uses a plugin to re-arrange order of sprites and move graphics to other. The only problem is that demo is using big graphics as background "gray" color, when its better to use backgroundColor of renderTexture.
Thanks a lot for your reply!
Using blend modes instead of masks has allowed me to gain 5-10fps on average on slower devices. Not earth-shattering, but it’s something I can work with.
Probably the only downside I can think of would be if I needed another layer of content _below_ the masked stage (which I might need later on): then that additional layer would interfere with the “mask”.
-- Layer 2: PIXI.Container() that should be masked with PIXI.BLEND_MODES.MULTIPLY
-- Layer 1: PIXI.Container() containing multiple Graphics() used as the Mask
-- Layer 0: content that shouldn’t be masked
Let’s say the Layer 0 is filled with a plain color — red. How could I prevent it from interfering with Layer 2’s blendMode, and have Layer 2 being only masked with what’s inside Layer 1?
Is there a way to limit blendModes to a certain scope?
Thank you again! 👌🏻
That can be done. Combine Layer1-2 into new container and use VoidFilter on it, specify correct filterArea.
That way combined result of layer1 + layer2 will be blended on layer0
Right! I've yet to learn the wonders of the VoidFilter. “Very handy” indeed. Thank you for that!
I may have one last question to bother you with: after I applied the VoidFilter, I saw a noticeable dip in image quality when the renderer’s resolution is anything other than 1. Basically, everything touched by the VoidFilter becomes slightly blurry, which truly catches the eye when text or straight lines are involved.
I cooked up a small fiddle demonstrating the issue:
https://jsfiddle.net/9wakxrqx/1/
Is it by design, and is there anyway to prevent it?
Thanks again for your support, it really means a lot!
Right, you have to set "PIXI.settings.resolution" (global), or "filter.resolution" (this one filter)
I had assumed that Pixi would automatically use the renderer’s resolution for the filters by default, but then I stumbled upon an old thread and saw that it’s been a topic of debate.
Anyway, thanks again! That really helped.
Hi there! Closing this issue for now due to its inactivity. Feel free to give us a poke if you would like this issue reopened. 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.