Hello, I’m now using React three fiber to create several boxes, and in each box there are about 12 models, these models are instanced with gltfjsx.
The problem is that when I put my mouse onto these models in boxes, the fps decreases dramatically (from 50fps to 20 even 10). The problem still exists when I remove the pointerOver and PointerOut event in these gltf components, and I don’t know why.
I use the profiler in dev tools and I can’ find any rerender except from the component for the model when I keep moving my mouse around these models.
By the way, I created about 20 boxes and in each box there are 12 models. So there are about 320 models in the scene, and every group of models in each box is instanced independently. The box has a moving animation when clicked. But the problem of mouse hovering over models make this animation too bad.
Raycasting is expensive and it sounds like you are raycasting against your entire scene of instanced models. Raycasting needs to be carefully controlled in dense scenes.
Also, note that raycasting cost is proportional to vertex count. You’ll see a slowdown especially when raycasting high-poly models. I would measure your vertex count if you haven’t already, and consider reducing it if possible, or using lower-poly meshes for the raycasting operations.
If that’s not possible, then you could also consider using the BVH-accelerated raycaster from GitHub - gkjohnson/three-mesh-bvh: A BVH implementation to speed up raycasting and enable spatial queries against three.js meshes..
there’s a bvh helper, you basically just wrap the scene into <Bvh>
, see https://codesandbox.io/p/sandbox/bvh-txzeq8
and a raycast hook which forces it into a less precise box/sphere lookup meshBounds - Drei
you could also override raycast yourself if there are models in the box you don’t want it to pick up on
<Box>
<mesh geometry={foo} raycast={() => null} ... />
<mesh geometry={bar} raycast={() => null} ... />
ps r3f already tries to optimise raycast for you, only objects that have pointer events ever get tested. it will never just indiscriminally run the whole scene. but, if you have an object with pointers on, and it has children, then these must count towards that parent object, be it a mesh, a group or otherwise.
so, given
<group onPointerOver={e => console.log("over!")}>
<mesh ... />
<mesh ... />
<mesh ... />
<mesh ... />
if the mouse is over any of them it will trigger the event. if it’s over all four the same time, it must trigger four times with each event having a different “object”. if you only want the closest to the camera, that’s e.stopPropagation()
, and only one event will fire.
Thank you for giving me detailed solutions. I had wrapped my scene with Bvh. But for setting raycast property, since I instanced models with gltfjsx node scripts, I don’t know where can I set the raycast property now.