Efficiently animating many thousands of Nanite meshes (cosmetic only) - culling issues

Hi there, I’m working on a game where I have many thousands of Nanite meshes hovering in the air, that I would like to add interesting motion to.

The meshes are huge, seen both close and far away, and instanced with ISM components. The performance and frame rate is excellent while they are static and with no motion.

The first thing I tried was animating them rotating with WPO offsets in the vertex shader, I figured this would by far be the best option because it all happens on the GPU and I don’t care about collisions or anything like that, this is purely a cosmetic effect.

  • The problem with this method is that the Nanite HZB and Frustum culling logic doesn’t seem to be aware that the vertices are moving, so as an object rotates about it’s axis, many clusters are being culled that are visible to camera (but Nanite thinks it’s occluded), creating constant flickering artifacts, and whole sections of the mesh disappearing and reappearing. Same thing happens around the camera frustum as objects “animate” into frame, they are still being culled I believe since the original geometry is still “outside” the frutum before WPO is applied. I think this is all to be expected, as I’m just moving the vertices on the GPU in the vertex shader.
  • With regular meshes I think the workaround for this is to expand the bounds on the mesh, however that doesn’t seem to have any effect for Nanite geometry? There is an option in the material called “Max World Position Offset Displacement”, which does actually fix the artifacts, but since my objects are huge and are rotating up to 360 degrees, I have to set this value very high and it completely tanks performance as I believe it is adding a huge amount to the bounds in all directions (even though I don’t actually need bigger spatial bounds for rotation).
  • By turning off HZB, Frustum, and TwoPass culling with console variables, it also more or less fixes the problem, but those options are global and so apply to all Nanite meshes in the scene. Is there are way to apply these settings to particular meshes, and not to everything? Or is this impossible due to the way Nanite works, as one big singular mesh?

The second thing I tried was creating a custom C++ component that updates the transforms of the individual instances every frame. This allows a lot more control since any kind of motion can be programmed in but it’s obviously a LOT slower than doing it all on the GPU in the vertex shader… there are also some ugly AA-looking artifacts as the meshes move, that I wasn’t getting with the vertex shader option.

Phew that turned into a long post… if anyone has any tips on what I cold try to get the WPO shader option working without the Nanite culling issues, that would be much appreciated. Even if it was something along the lines of being able to set just these instanced meshes to not use HZB culling that would be a huge help and get me most of the way there!

Cheers

Make the objects rotate on their center (pivot) point, so that they don’t get culled or linger outside their bounds too far.

Drop nanite.
Its a visual only effect.
Why bother with the epic nonsense when having a properly made shader and an HISMC inside of a blueprint can get you billions of moving instances with marginal costs?
Unless you like tilting at windmils - in which case, by all mens do go on :wink: