two.js icon indicating copy to clipboard operation
two.js copied to clipboard

New Feature: Frustum Culling

Open PassTheMayo opened this issue 6 years ago • 11 comments

I've looked through some of the code, and noticed that it doesn't prevent rendering of objects that are off the renderable area. If you create a simple scene where there was 50 circles, and half of them were in a position that is off the screen, then the draw calls are unnecessary, and result in a loss of performance. Is this a planned implementation? I plan to create a large scale game soon, and if it performs like this, then I won't be able to use it due to the performance drop on low end computers.

PassTheMayo avatar Apr 12 '19 00:04 PassTheMayo

You are correct. It's not intentional, it just hasn't been implemented yet. We can use this bug to track frustum culling.

jonobr1 avatar Apr 12 '19 05:04 jonobr1

Alright, thanks!

PassTheMayo avatar Apr 12 '19 05:04 PassTheMayo

If you have recommendations on an efficient frustum culling technique I'm all ears. An implementation shouldn't take long, because all the logic exists to know if a shape is off screen or not. I've been unsure where to place it in the code because I've been debating adding a camera or not...

jonobr1 avatar Apr 12 '19 05:04 jonobr1

I think a camera is an amazing idea, and would love to see it implemented. You can also use a 3-dimensional vertex for the camera, and defining a depth would just make the scale of everything in the viewing frustrum smaller. I was actually considering making my own lib just to implement this, but I would absolutely use this if we had it.

PassTheMayo avatar Apr 12 '19 05:04 PassTheMayo

Cool, that's a great point. I did make a camera for https://tether.plaid.co.uk/

I'll probably add a setCamera method to an instance of Two.

Just curious, is there a reason you're not interested in using Phaser.js ( with Pixi.js as the rendering engine)?

jonobr1 avatar Apr 12 '19 06:04 jonobr1

The other libraries like Phaser and Pixi aren't lightweight enough, and in my eyes, looks like they were made for the early 2000s. Two.js is really lightweight and high level syntax for supporting WebGL.

PassTheMayo avatar Apr 12 '19 06:04 PassTheMayo

Just a quick follow up on this topic for now. I'm pretty sure that SVGs in the DOM are culled, so there is brief support in that manner. As far as Two.js frustum culling goes an efficient hack toward this end that can be used immediately is to do something like this:

two.bind('update', function(frameCount, timeDelta) {
  for (var i = 0; i < two.scene.children.length; i++) {
    var child = two.scene.children[i];
    // Manipulate the child how you would and
    // keep track of if a transformation change
    // or a vertices change has occurred as
    // a boolean, we'll say `changed`
    if (changed) {
        var rect = child.getBoundingClientRect();
        var horizontallyVisible = rect.left <= two.width && rect.right >= 0;
        var verticallyVisible = rect.top <= two.height && rect.bottom >= 0;
        child.visible = visible;
    }
  }
});

This works mainly for Canvas2d and WebGL contexts and if you're already going through the scenegraph to manipulate the shapes for draw calls. Also, the getBoundingClientRect is an expensive function so if you do go this route it would be good to cache the values depending on what changed on the child.

jonobr1 avatar Apr 14 '19 18:04 jonobr1

Sounds good, should you start a new branch called culling? This would be a good idea to experiment with, and do some performance testing to see if it increases performance compared to drawing off-screen (how it was before).

PassTheMayo avatar Apr 14 '19 19:04 PassTheMayo

Feel free to crack open a new branch. I have final classes coming up and won't be able to tackle this until the summer.

jonobr1 avatar Apr 16 '19 05:04 jonobr1

@jonobr1 you're gonna have to create the branch, I can't do that. I also probably won't be able to work on it either, as I have a lot of active projects I need to catch up on.

PassTheMayo avatar Apr 17 '19 20:04 PassTheMayo

This is currently in development on this feature branch: https://github.com/jonobr1/two.js/tree/culling

I haven't tested thoroughly, but the CanvasRenderer has frustum culling implemented by default.

jonobr1 avatar Apr 06 '21 21:04 jonobr1