Jump to content

Troubles with masks and performance


Recommended Posts

Hi, I'm trying to start sort of a drawing app where you can draw lines and show an image through those lines. Problem is, it is incredibly slow...


So I have an "imageToReveal" sprite and mask it with the drawn lines. Now this does work in my project, but I cannot get it to work in JSFiddle. check it out here

This should render the drawn shapes to a texture and set to texture to Sprite that's masking the image to reveal

I don't know if this is the best way, but the simple way with a masked sprite and shapes as children didn't go well either: see this one


So my question is, how do I make the first JSFiddle work? (and is it the best way)

And if it is, how can I make it faster? since it drops from 60 to 40 after a single shape is put on stage.

Link to comment
Share on other sites


So I have this nice image appearing when the dots are drawn, but now I want a background layer behind it that is always showing. So you would sorta draw a new layer on top of it.

I can't get my around it how to do that. With the multiply blendmode everything hidden needs to have black over it, but that means I can not put anything behind it.

Is masking a better option again? or is there a filter where I can only let full alpha through, so I can have a transparent blended image.


Hope I'm making sense


Link to comment
Share on other sites

You canput old stuff in separate container and assign VoidFilter to it - it will render that container into separate frameBuffer. If you put stuff before that container, whole container will be on top of it. That's how masking works - separate layer + MULTIPLY blendmode inside.

var globalVoidFilter = new PIXI.filters.VoidFilter();
container.filters = [globalVoidFilter];


Link to comment
Share on other sites

Thanks again Ivan,

I applied the VoidFilter and put a red rectangle in the background which would need to appear behind the drawn layer.

But I'm not sure how to get it to imitate a mask now. I still have this black color which needs to be transparent, see here

How do I achieve that?


Also, would this still be faster than regular masking? 

Link to comment
Share on other sites

Oh, shit. Yeah, now I realize that for that case MULTIPLY !== mask. We have to think. OK, that will work: https://jsfiddle.net/me2rqnd4/6/

That's my change:

//renderTextureSprite.blendMode = PIXI.BLEND_MODES.MULTIPLY;
container.mask = renderTextureSprite;

Also i removed VoidFilter, we dont need it. I will try to improvise with BlendModes later, find something that'll work instead of multiply ;)

UPD. Yeah, we have to put that drawing demo into pixi examples!!

Link to comment
Share on other sites

Haha great! I'm happy it got made into an example, and this also gives me way better code to work off.

Thank you!


PS: I should say the performance is not optimal for mobile, it's about 35 fps when drawing on my iPhone 5 (but it's manageable for a drawing app)

Link to comment
Share on other sites

Well, if you are going for speed, this one has less operations, and mask is applied only when something is being drawn.

But there can be artifacts on the edge of circle if its anti-aliased.

// for this example you have to use mouse or touchscreen

var app = new PIXI.Application(800, 600);
var stage = app.stage;

//prepare circle texture, that will be our brush
var brush = new PIXI.Graphics();
brush.drawCircle(0, 0, 50);

PIXI.loader.add("t1", "required/assets/bkg-grass.jpg")
PIXI.loader.add("t2", "required/assets/BGrotate.jpg")

function setup(loader, resources) {
    var background = new PIXI.Sprite(resources["t1"].texture);
    background.width = app.screen.width;
    background.height = app.screen.height;

    var imageToReveal = new PIXI.Sprite(resources["t2"].texture);
	imageToReveal.width = app.screen.width;
    imageToReveal.height = app.screen.height;
    imageToReveal.mask = brush;
    var imageMasked = new PIXI.Container();

    var renderTexture = PIXI.RenderTexture.create(app.screen.width, app.screen.height);
    app.renderer.render(background, renderTexture, false);

    stage.addChild(new PIXI.Sprite(renderTexture));

    app.stage.interactive = true;
    app.stage.on('pointerdown', pointerDown);
    app.stage.on('pointerup', pointerUp);
    app.stage.on('pointermove', pointerMove);

    var dragging = false;

    function pointerMove(event) {
        if (dragging) {
            app.renderer.render(imageMasked, renderTexture, false);

    function pointerDown(event) {
        dragging = true;

    function pointerUp(event) {
        dragging = false;


Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...