godot-extended-libraries/godot-lod

Take the camera FOV into account for LOD calculations

Calinou opened this issue ยท 15 comments

When the camera FOV decreases, the distances should be multiplied accordingly so distant objects still look detailed. The user-supplied camera distances will be specified for the default camera FOV (which is 70 in Godot 3.2.x).

There should be a project setting to disable this LOD adjustment in case it's not desired (e.g. for a game where the FOV is only changed for aesthetic reasons).

I've also considered using screen density-based LOD calculations, but they have an additional performance cost and some downsides (such as making high-resolution gaming even slower than it would be otherwise).

How about an option is added to take screen coverage into account instead. That way, the LOD swapping is fov independent. I believe that this is the approach that Unity uses as well.

@SIsilicon See OP:

I've also considered using screen density-based LOD calculations, but they have an additional performance cost and some downsides (such as making high-resolution gaming even slower than it would be otherwise).

I know this might be an unpopular opinion in today's LOD scene, but I stand by it ๐Ÿ™‚

Don't know how I missed that in the post. ๐Ÿ˜…
That's understandable though.

Question though. How would that method be slow on high resolution games?

@SIsilicon The method isn't necessarily slower depending on the viewport resolution, but the end result will be slower since higher quality LODs will be selected on higher resolutions (for a given distance).

Lots of 4K displays have higher DPI compared to 1080p/1440p displays, making this high-quality LOD selection not as important as it theoretically should be.

How would that be so? The screen coverage wouldn't be dependent on screen resolution, but rather by the percentage of the screen it covers. The result should theoretically be the same no matter what resolution is used.

@SIsilicon I seeโ€ฆ I always thought it was based on the number of pixels covered by the object (which would make it resolution-dependent).

Either way, I'm not sure if Godot exposes everything required for that โ€“ a mesh's AABB may not be representative of its actual volume. This would also make LODSpatial only work for MeshInstance-derived nodes, rather than all Spatial-derived nodes.
Not to mention performance is critical for this add-on, so I'd prefer keeping computations as simple as possible.

True. I decided to do a stress test with this method, and these were the results.
Without LOD: 40 FPS
Distance LOD: 36-37 FPS
Coverage LOD: 32-33 FPS

These were from spawning 5000 static spheres in a 100x100x100 volume.
It's strange that the FPS dipped with LOD either way though, even when I had a refresh rate of 3 seconds.

Then again, that could be because of the draw calls themselves. If the LOD were to be implemented directly into a MultimeshInstance, things would've been different.
It's too bad that you can't just make an addon for that.

Either way though, I like to see screen coverage as just another option. People don't need to use it if they don't want to. But there are people out there that do, and are used to Unity's way of doing things. Simply having both options would probably be a good idea.
image
Obviously some of the options would appear and disappear depending on the mode used.

This would also make LODSpatial only work for MeshInstance-derived nodes, rather than all Spatial-derived nodes.

Well I mean, it is screen coverage. You wouldn't really expect a node like Position3D to take up screen space.

Then again, that could be because of the draw calls themselves. If the LOD were to be implemented directly into a MultimeshInstance, things would've been different.
It's too bad that you can't just make an addon for that.

The performance drop is likely due to nodes being included in the octree if they're still hidden. To prevent this, you need to remove nodes from the scene tree entirely using remove_child() rather than hiding them. I could investigate this, but adding/removing lots of nodes in rapid succession might impact performance negatively too.

Obviously some of the options would appear and disappear depending on the mode used.

That means I can't use exported properties anymore and have to override the much more complex _get_property_list() method ๐Ÿ™

To prevent this, you need to remove nodes from the scene tree entirely using remove_child() rather than hiding them. I could investigate this, but adding/removing lots of nodes in rapid succession might impact performance negatively too.

I could benchmark that (later).

That means I can't use exported properties anymore and have to override the much more complex _get_property_list() method ๐Ÿ™

Trust me, it's not that complex once you get used to it. It was hard for me too at first, but now I use it all the time in my plugins, and it makes the plugin look more like part of the engine. ๐Ÿ˜
If you'd like I can implement that for you.

One more thing.
I believe both distance based and screen based lod calculations have their advantages and disadvantages.

Distance Based LOD:

  • Simple to understand controls
  • Faster than the latter method
  • Doesn't work accurately with orthogonal projection, or perspective projection with varying Fov

Screen coverage Based LOD:

  • Works with both orthogonal and perspective projection out of the box
  • Calculates LOD levels more accurately then the former method
  • Slower than the former method

Doesn't work accurately with orthogonal projection, or perspective projection with varying Fov

It works with varying FOV if you take it into account during the distance checks ๐Ÿ™‚ This is relatively easy to do, and is already done in many other engines (even id Tech 3 did it IIRC).

As for orthogonal projection, do you need LOD in the first place when using it?

Either way, I'd prefer supporting only distance-based LOD in this add-on to keep it simple. I appreciate the effort, but I'd rather avoid bloat if possible. This is especially the case since finding maintainers to fix bugs can be difficult.

As for orthogonal projection, do you need LOD in the first place when using it?

Zooming in and out in an isometric game for example.

This is especially the case since finding maintainers to fix bugs can be difficult.

I can be the maintainer. :)

Here's what the UI looks like using _get_property_list. I'll open pull request with these feature, including a different way to update the LODs.

image