New Feature: Frustum Culling
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.
You are correct. It's not intentional, it just hasn't been implemented yet. We can use this bug to track frustum culling.
Alright, thanks!
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...
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.
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)?
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.
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.
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).
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 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.
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.