InstancedMesh2 - Easy handling and frustum culling

165 FPS (monitor’s refreshrate) with an RTX 2080ti.

I’ve increased the count to a million. It gave me 40~70fps, depending on how many models are visible on screen.

1 Like

Thank you very much :slight_smile:

I’m curious if 165 fps fixed fps could be achieved with an InstancedLOD.

In any case, it seems like a good result.

I have optimised the code a little, mainly by making the initial loading faster.

Next week I should publish the first version of the package.

Besides instancedLOD I am also trying to optimise raycasting on this class.

1 Like

Small update :slight_smile:

I wrote this small example where you can see how many instances it is rendering (it’s a bit slow to start because of bvh creation):

Would this library be useful to anyone?
I would like to try it out on some already started projects if possible.
If anyone is interested please contact me in private.

const trees = new InstancedMesh2({
  geometry: treeGLTF.geometry,
  material: treeGLTF.material,
  count,
  behaviour: Behaviour.static,
  onInstanceCreation: (obj, index) => {
    obj.position.setX(Math.random() * terrainSize - terrainSize / 2).setZ(Math.random() * terrainSize - terrainSize / 2);
    obj.scale.setScalar(Math.random() * 0.1 + 0.1);
    obj.rotateY(Math.random() * Math.PI * 2).rotateZ(Math.random() * 0.3 - 0.15);
  },
});
1 Like

I have released a first version of the package, I will release the code shortly.

This package uses vanilla three.js, although in the example I use three.ez for convenience.

Could someone create an example using RTF? I would like to add it to the README.

1 Like

Great work! I’ve tried it in my own scene,here is some feedback:
It is handy to manipulate instance.But my scene is meat to render 300k of totes(a simpified gltf model) at the same time,in a warehouse.So, the frustum culling may loose it’s benefites.And in such a super dense scene, the CullingStatic does not works well, the entire scene disappears when zooming in on a corner.And without any culling, I lost 1fps compared to the original InstancedMesh
Plus, the three version lower than 159 will throw an error because “clearUpdateRanges()” does not exists yet.Maybe you should add a peerDependency declaration.And I’m looking forward the lod of the instanceMesh your are working on can solve the performance issue i’m facing. :heart:

2 Likes

Just a shot in the dark, but the “disappears when zooming in a corner” might mean you need to set .frustumCulled = false on your InstancedMesh itself, since the InstancedMesh2 is handling the frustum culling? Just a guess…

1 Like

the frustumCulled is already setted false by InstancedMesh2. And i take a screen shot of the behavior, see https://pixa.anomanm.com/20240306-154335-min.gif

1 Like

Thanks for the feedback :smiley:

If CullingNone is used, more memory is used (because of the sub instances) but the transformations should be slightly faster because there is no temporary object to copy the data to (I don’t know if this is noticeable).

If CullingStatic is used, it is necessary to value all instances within the callback in the constructor, because it creates a bvh which will no longer be modified (could this be the reason for the disappearance?).

The frustum culling is best activated when the geometry is a little more complex.

I will now update the minimum version of three.js, thank you very much :slight_smile:

I set the frustumCulling property to false, but I would have to figure out if when the count is 0 (no visible instance) it makes a useless draw call…

Found the cause why it “disappeared”! It is when init the object outside the onInstanceCreation method.
The culling works fine when i switched the process inside onInstanceCreation.
Does these two way makes difference?
Besides, when init objects outside the onInstanceCreation, inovking updateMatrix() but all instances are at one place,the transformation is not updated.Only after forceUpdateMatrix() works.

I forked your demo, reproduced disappeared and culling problem, And I reduced the quantity of the instances so that it does not crash when their matrix are not updated. three.ez - InstancedMesh2 - CullingStatic 1kk Forest (forked) - StackBlitz

CullingStatic is optimized to work only with objects that are created and modified in the InstancedMesh2 constructor because after all matrices are updated, a BVH is calculated that cannot currently be modified again (creating a BVH has a certain cost).

The frustum culling is then calculated based on that BVH.

Matrix update is not allowed for that. Using forceUpdateMatrix is not safe, but it may work if the change does not go to damage the BVH.

If you need to modify instances after they are created you will have to use CullingDynamic but the performance is not the same unfortunately.

With CullingStatic did you find an improvement in performance? :slight_smile:

I have some optimizations in mind to do, and in the future I hope to also add a dynamic BVH for cases like these.

Thanks for the reminder.And the performance is ok,although there is still a loss of 1fps when in the overall view, but that is reasonable and absolutely worth it. When operating the scene, it becomes much more smoother than native due to bvh culling. :+1:

1 Like

When you render all instances it is actually slower.

Do you only render the scene when there is actually a change/move?

With CullingStatic you could avoid calling updateCulling if there has been no change to the camera since the last frame ( be careful with the resize), it should improve performance slightly.

I should implement it in the library actually…

1 Like

Thanks, in most cases, performance refers to when user interacts with the scene, so the camera will always change. Btw i will give it a try :grinning:

I published a new version where I speeded up frustum culling if CullingStatic and added a control to avoid useless recalculations :slight_smile:

I posted all the source code here:

2 Likes

Is Occlusion Culling possible using bvh? For example: three.js webgl - Occlusion Queries , for super dense heavy scene, the performance maybe improved through occlusion culling

1 Like

That would be great, but I would have to study how to do it, I’ve never tried.
However, it will be necessary to make some changes to the renderer.

I would have to compare with someone experienced in that field.

However, now I need to optimize the raycasating function using BVH as soon as possible :innocent:

1 Like

I made another topic for this library:

1 Like