ooflorent

Performance improvement suggestions

Recommended Posts

When rendering is done through a CanvasRenderer, the framerate is cut by half when Pixi.js tries to draw really large textures (such as tilemap drawn using a RenderTexture).

Such textures should be cropped by the CanvasRenderer in order to prevent drawImage() burning all CPU cycles.

 

My last game has more than 10,000 display objects drawn each frame. Pixi.js is not able to render such amount of sprites without serious performance issues. I think an object culling pass should be added to skip off-screen sprites rendering.

 

I don't have the time to fix those issues and send a PR so if the main developer read my post, I'll be happy provide more details.

Share this post


Link to post
Share on other sites

Off screen culling is userland responsibility. You should be culling items in your engine, that is not something we will be adding into Pixi any time soon. The tools to make an item not be rendered are there (visible = false) you just need to use them. Creating a tilemap where you spawn every tile and show them all (even the ones off screen) is in effective.

Try looking at some of the tilemap engines built on pixi to see how you can easily do a smooth scrolling engine that only ever creates the number of tiles shown on the screen.

Share this post


Link to post
Share on other sites

Canvas rendering of massive images is a canvas limitation. You shouldn't be making them so large. Keep them to GPU friendly scales (1024x1024 maximum really). If that's not big enough to hold your tilemap, buffer them or create a few of them and hope you don't run out of memory.

 

Culling should be done by you, not Pixi imho. It's actually really quite complex as I found when I added it to Phaser and there's no "one size fits all" method either. You'd think "not on screen" should be reason enough to cull an object - but what if it has children? You suddenly need to test the position of the object AND all children, every frame, and any children of those children, just to see if you can safely cull it or not. This is trivial in a linear display list where you don't use any parenting, but it's massive overhead for Pixi to be calculating every frame, not knowing if it's even needed or not.

Share this post


Link to post
Share on other sites

I agree about culling.

 

Off screen culling is userland responsibility. You should be culling items in your engine, that is not something we will be adding into Pixi any time soon. The tools to make an item not be rendered are there (visible = false) you just need to use them.

OK, I understand.

 

Try looking at some of the tilemap engines built on pixi to see how you can easily do a smooth scrolling engine that only ever creates the number of tiles shown on the screen.

Can you name some of them?

 

Canvas rendering of massive images is a canvas limitation. You shouldn't be making them so large. Keep them to GPU friendly scales (1024x1024 maximum really). If that's not big enough to hold your tilemap, buffer them or create a few of them and hope you don't run out of memory.

Cropping Pixi frame would be a better solution IMHO. Why would the engine try to render a 8000x6000 image (calling drawImage) while it could simply crop the texture frame?

Considering the following statements:

  • Renderer size: 800x600
  • Texture size: 8000x6000
  • Object position: -2000, 1000

Isn't a good idea to adjust the frame to: (x: 2000, y: -1000, width: 800, height: 600) ?? (or something like this)

Share this post


Link to post
Share on other sites

I'll take another example.

 

suppose you have a tileset of 128x128 frames with 10 frames with and 10 frames height this give you a 1280x1280 image with a total of 100 frames.

 

what you are asking for is creating 100 off screen canvas to be able to render those frames?

 

also textures with : 8000x6000 are really huge for HTML5 games, the maximum I use is 2048x2048  (1024x1024 when possible)
 

Share this post


Link to post
Share on other sites

A RenderTexture is just a hidden canvas object. Create it too large and it'll be too big to be GPU accelerated, regardless of what frame size you set on it for display. On desktop this is less of an issue (depending on video card). On mobile you have to be a lot more careful. The fact you've even got 10k objects in your game tells me you're not worrying about running on mobile at all though :)

Share this post


Link to post
Share on other sites

Exactly what @rich just said. Simply cliping the viewport is *not* the best option for many reasons.

Here is a super helpful discussion that Matt and I had a while back, about how my tile engine should work: https://github.com/GoodBoyDigital/pixi.js/issues/48

The summary amounts to:

 

So the way the tilemap culling works is by generating the entire viewport (plus a 2 tile buffer around it) and storing those sprites. Then, as you move around it moves the sprites around and changes their texture (i.e. if you move 1 tile to the right, it takes the far left sprites and moves them to the far right and changes their texture to the proper one using .setTexture()).

You can view my tilemap implementation in Grapefruit, here: https://github.com/grapefruitjs/grapefruit/tree/master/src/map/tiled

I'm sure if you looked at Phaser there would be a (better) implementation there as well.

Share this post


Link to post
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.

Guest
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.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.