Sign in to follow this  
QuinTRON

How to crop/hide over flow of sprites which clip outside of the world boundaries

Recommended Posts

Perfect thanks :)

Here is the change I have applied:

// MASK (clip things outside the background border)
var px_mask_outter_bounds = new PIXI.Graphics();
px_mask_outter_bounds.drawRect(0, 0, worldWidth, worldHeight); // In this case it is 8000x8000
px_mask_outter_bounds.renderable = true;
px_mask_outter_bounds.cacheAsBitmap = true;
app.stage.addChild(px_mask_outter_bounds);
app.stage.mask = px_mask_outter_bounds;

I was concerned this would make things laggy considering the world size, yet to my surprise I don't notice any impacts! 

Could my above implementation be done better?

Share this post


Link to post
Share on other sites

I think its better to remove "renderable" and "cacheAsBitmap" there. That way mask will be drawn with "gl.scissor" and that's the fastest you can get.

One more way, but coords are in screen, not in world.

app.stage.filters = [new PIXI.filters.VoidFilter()]
app.stage.filterArea = new PIXI.Rectangle(minX, minY, maxX, maxY) //<-- its SCREEN coords,you have to  calculate the part of screen that must be drawn.

 

One more way is to add big rectangles on edges, and I think it'll be good too.

Share this post


Link to post
Share on other sites

I have applied your first change, by removing "renderable" and "cacheAsBitmap"; feels good! 

Your 2nd comment is very interesting:  [new PIXI.filters.VoidFilter()
Is this telling the renderer -to only consider rendering things in the filterArea bounds; in this case the users screen coordinates? 
Isn't this what every gamer wants by default, feels too good to be true!?

Share this post


Link to post
Share on other sites

With a filter, stage is rendered to separate framebuffer. Then framebuffer is rendered into actual canvas.

Mask works the same way, but it has to render mask in second framebuffer and combine it with AlphaMaskShader, that's why its less performant.

Rectangle mask is a special case, its using "gl.scissor" which doesn't eat extra power at all and doesn't disable antialiasing.

 

Filters are very useful, sometimes i use VoidFilter on whole stage just to enable some advanced stuff inside it :) Its like a "layer". For example, you can wrap multiple objects in that filter and then specify blending for whole layer, its useful for lighting: http://pixijs.github.io/examples/#/layers/lighting.js

Share this post


Link to post
Share on other sites

Very cool! I've looked at this example for some time now and i found this part particularly interesting:

The example in Pixi js

function createBunny() {
    var bunny = new PIXI.Sprite(bunnyTexture);
    bunny.update = updateBunny;

    var angle = Math.random() * Math.PI * 2;
    var speed = 200.0; //px per second
    bunny.vx = Math.cos(angle) * speed / 60.0;
    bunny.vy = Math.sin(angle) * speed / 60.0;
    bunny.position.set(Math.random() * WIDTH, Math.random() * HEIGHT);
    bunny.anchor.set(0.5, 0.5);

    var lightbulb = new PIXI.Graphics();
    var rr = Math.random() * 0x80 | 0;
    var rg = Math.random() * 0x80 | 0;
    var rb = Math.random() * 0x80 | 0;
    var rad = 50 + Math.random() * 20;
    lightbulb.beginFill((rr << 16) + (rg << 8) + rb, 1.0);
    lightbulb.drawCircle(0, 0, rad);
    lightbulb.endFill();
    lightbulb.parentLayer = lighting;//<-- try comment it

    bunny.addChild(lightbulb);

    return bunny;
}

for (var i = 0; i < 40; i++) {
    bunnyWorld.addChild(createBunny());
}

What is the benefit from the above example than this (besides the local variables being created all the time in the for-loop):

for (var i=0; i < 40; i++) {
    var bunny = new PIXI.Sprite(bunnyTexture);
    bunny.update = updateBunny;

    var angle = Math.random() * Math.PI * 2;
    var speed = 200.0; //px per second
    bunny.vx = Math.cos(angle) * speed / 60.0;
    bunny.vy = Math.sin(angle) * speed / 60.0;
    bunny.position.set(Math.random() * WIDTH, Math.random() * HEIGHT);
    bunny.anchor.set(0.5, 0.5);

    var lightbulb = new PIXI.Graphics();
    var rr = Math.random() * 0x80 | 0;
    var rg = Math.random() * 0x80 | 0;
    var rb = Math.random() * 0x80 | 0;
    var rad = 50 + Math.random() * 20;
    lightbulb.beginFill((rr << 16) + (rg << 8) + rb, 1.0);
    lightbulb.drawCircle(0, 0, rad);
    lightbulb.endFill();
    lightbulb.parentLayer = lighting;//<-- try comment it

    bunny.addChild(lightbulb);
    bunnyWorld.addChild(bunny);
}

 

 

Share this post


Link to post
Share on other sites
On 2/18/2017 at 2:29 AM, QuinTRON said:

Perfect thanks :)

Here is the change I have applied:


// MASK (clip things outside the background border)
var px_mask_outter_bounds = new PIXI.Graphics();
px_mask_outter_bounds.drawRect(0, 0, worldWidth, worldHeight); // In this case it is 8000x8000
px_mask_outter_bounds.renderable = true;
px_mask_outter_bounds.cacheAsBitmap = true;
app.stage.addChild(px_mask_outter_bounds);
app.stage.mask = px_mask_outter_bounds;

I was concerned this would make things laggy considering the world size, yet to my surprise I don't notice any impacts! 

Could my above implementation be done better?

This worked great. However, in order to preserve interactivity of sprites within the masked container, I had to change your code snippet to the following:

// MASK (clip things outside the background border)
var px_mask_outter_bounds = new PIXI.Graphics();
px_mask_outter_bounds.beginFill(0xFFFFFF);
px_mask_outter_bounds.drawRect(0, 0, worldWidth, worldHeight); // In this case it is 8000x8000
px_mask_outter_bounds.endFill();
app.stage.addChild(px_mask_outter_bounds);
app.stage.mask = px_mask_outter_bounds;

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.