To keep performance high, mesh authors need to avoid micro-geometry (which slows down fragment shading) and need to reduce the number of triangles (which slows down primitive assembly). We currently have workable whole-mesh LOD to combat this for objects which don’t take up a lot of screen space, but this often falls apart for larger geometry which is viewed from more varied perspectives.
Triangle density
The core problem of LOD is that, as a triangle mesh gets further away, the triangle density on-screen increases.
Ideally, we would want the triangle density on-screen to be constant, which would ensure that nearby geometry, or geometry that takes up a large proportion of the screen, gets allocated an appropriately larger amount of triangles to showcase the details of those objects.
Roblox has LOD systems in place today which approximate this at the whole-mesh level. They don’t take into account angular size as far as I can tell, but at minimum, they make far-away MeshParts render with fewer triangles.
Whole-mesh LOD doesn’t work
However, this is not really enough.
Imagine you have a large cliff face, which is authored as one mesh. You’re standing next to the cliff face, and looking down its length.
On the nearby rocks, we want to be able to see the nuances of the surface. However, including those nuances on the far-away rocks would be a waste of computing resources.
We would need to split the cliff mesh up into multiple, more granular LODs.
We can’t have that granular level of detail on Roblox today, because the cliff face is one mesh, which gets one universal level of detail per instance.
Separating the mesh into multiple modular parts doesn’t work well either, because there’s no guarantee that the boundaries will line up between meshes showcasing different LODs (which will manifest as see-through ‘cracks’ in the cliff face).
Inspiration: triangle clustering
With other rendering engines such as Unreal Engine 5 (source), meshes are processed into triangle clusters. These clusters can then be rendered much more flexibly, for example allowing more granular culling.
The real benefit is that you can consider a cluster in the context of nearby clusters, and group them together to make a more granular LOD system.
Based on this, you can pick different LODs for clusters based on their size in screen space, letting you achieve a more uniform triangle density across the screen.
This is so-called “virtualised geometry” - the artist does not need to worry about triangle density, they only need to provide a sufficiently detailed input mesh. The rendering engine can then take care of ensuring an appropriate number of triangles are shown on screen based on the device’s capability to store and process geometry for rendering.
It also has benefits beyond convenience. LODs can be streamed over the network in granular parts, potentially reducing network load and allowing for faster progressive enhancement of in-game content. It can also help to future-proof content by decoupling what the artist produces from what the engine renders, and also decoupling from today’s devices’ hardware.
But it doesn’t have to be clustering
I don’t necessarily think Roblox would need to implement cluster-based LOD in exactly that form. There are questions there around hardware compatibility.
Even a basic system splitting large meshes into macro “chunks” would be better than exclusively whole mesh LOD. I could imagine large-scale meshes being split into four, eight or sixteen “sub-meshes” which implement similar LOD ideas at a larger scale. These could then be rendered through more conventional rendering pipelines without specialised support.
Whole mesh LOD would remain a suitable fallback for older or incompatible devices here. Those are probably the devices where a more complex LOD wouldn’t necessarily be desirable anyway.
This is not a request for ultra-high detail
A key place where this suggestion diverges from “Nanite in Roblox” suggestions is that I do not advocate for “pixel-level detail”.
Pixel-level detail introduces a bevy of hard problems to do with managing inefficiencies caused by micro-geometry. Rendering such a level of detail is not cheap, and would run contrary to Roblox’s goals of being highly portable across devices of varying capability.
If a way of doing this was found that worked everywhere, then it’s a great upgrade. If it was only implemented for high-end devices, it’s a nice progressive enhancement. But without it, I would still enjoy the flexibility of being able to author meshes without worrying about degraded quality based on viewing angle.
That is all to say, I do not think that pixel-level detail is necessary for this idea to have value.
Is this an area of interest for Roblox? Has any research been conducted adjacent to this area, and how would something like this tie into Roblox’s LOD goals?