Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Depth sorting and rendering optimizations #6215

Closed
JernejHabjan opened this issue Sep 8, 2022 · 3 comments
Closed

Depth sorting and rendering optimizations #6215

JernejHabjan opened this issue Sep 8, 2022 · 3 comments

Comments

@JernejHabjan
Copy link

JernejHabjan commented Sep 8, 2022

Version

  • Phaser Version: 3.55.2
  • Operating system: Windows 11 (OS build 22000.856)
  • Browser: Chrome Version 105.0.5195.102 (Official Build) (64-bit)

Description

Hello,
I've discovered that depth sorting is running slow when rendering large number of sprites. Situation doesn't improve if sprite is not on the screen.

Depth sorting:

I've first seen this issue when running this game.
image

I've confirmed this also with following example:
http://labs.phaser.io/view.html?src=src/depth%20sorting/Depth%20Sorting.js&v=3.55.2

  • Steps:
    • Increased for loop from 2000 to 20_000

The performance drops because of depth sorting:
image

Performance of stable sort may be the problem here.
I've "updated" the depthSort function like this:

if (this.sortChildrenFlag)
{
    StableSort = (list, fn) => list.sort(fn); // note this override with native JS fn
    StableSort(this.list, this.sortByDepth);

    this.sortChildrenFlag = false;
}

And results:
image
Results look much better, but sorting may not be correct - right?

Is there a way we could improve this StableSort?
It seems that JS sort is stable since ECMA 2019, and twitter post with example

Rendering:

I've also updated same example with for loop like this

for (let i = 0; i < 20000; i++)
{
    const image = this.add.image(100 + Math.random() * 6000, 100 + Math.random() * 4000, 'atlas', 'veg0' + Math.floor(1 + Math.random() * 9));
    image.depth = image.y;
}

Note that many of sprites won't be visible in camera, so they wouldn't need to be rendered - right?

But by checking renderer function, I see that visibleChildren count doesn't change, whether all sprites are visible on screen or not:

var visibleChildren = this.getVisibleChildren(displayList.getChildren(), camera);
// visibleChildren.length -> this returns 20003

Is there a way these sprites can be occluded?

I am just trying to create new isometric RTS game, where medium-sized grid can be used, and is only partially visible in the camera. So in this case, I have issues with depth sorting slowing down the game, plus renderer taking all sprites into account, and not only ones visible on camera.
Is there a way I can bypass these issues somehow?

@samme
Copy link
Contributor

samme commented Sep 8, 2022

You should probably cull objects outside the camera viewport (toggling visible). Phaser doesn't do this itself.

@photonstorm
Copy link
Collaborator

Ok, please test the new StableSort I've put into the master branch (you'll need to do a Beta 11 build to get it, npm run dist will create that) - as for camera occlusion, that is out of scope for the v3 renderer, so you'll need to figure out a way to do this for your use-case I'm afraid.

@JernejHabjan
Copy link
Author

@photonstorm fyi

For repo Izowave this greatly improves performance:

v3.55
avg depth sort:
95ms (on 200 tile width* 200 tile height map)

v3.6 beta 11 (self-built)
avg depth sort:
20.8ms (on 200 tile width* 200 tile height map)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants