Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved LOD importing #7339

Open
reduz opened this issue Jul 20, 2023 · 17 comments
Open

Improved LOD importing #7339

reduz opened this issue Jul 20, 2023 · 17 comments

Comments

@reduz
Copy link
Member

reduz commented Jul 20, 2023

Describe the project you are working on

Godot

Describe the problem or limitation you are having in your project

While Godot supports importing LOD automatically with meshes, and the current algorithm should kind of more or less work in most cases, it does not in all of them. Sometimes, when the mesh has a certain complexity (like a character, a tree, etc) the current automatic LOD falls short in either quality or performance (as it can't improve past certain level of decimation).

In other words, automatic LOD works for most cases, but not always and it can't be finetuned.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

The idea here is that finetuning options are used for LODs that artists can tweak more easily to ensure a low amount of vertices when the object is far away at the most optimal quality.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

Important: This proposal is dependent on #7238 and should be implemented as a continuation, as the ability to preview materials in the viewport is needed for this.

Ideally, the Mesh importer screen should look like this:

image

The LOD option is moved to its own section. Most of the properties in the LOD section should be hidden when parent option is disabled, but they are shown here for context. They are explained as follows:

  • Generate: Toggles LOD generation, this can happen by default on import or not.
  • Normal/Split: Explained in the docs
  • HLOD: This is a high level LOD used to finetune the LOD creation. After a certain distance, the HLOD kicks in and replaces the mesh entirely by another one. There are two modes available:
    • Merged: It merges all surfaces, renders all materials to texture, generates a new UV unwrap and transfers everything to that single texture. This allows to LOD to bypass surface seams. This process may be repeated for each halving of vertex count in the decimation. It is the highest quality mode for LOD, generally preferred for things like characters, monsters, hero props, etc.
    • Impostor: This renders the mesh to N views (this could be a customizable option) and swaps them depending on view vector. this is a less quality option, but generally very useful for things like trees or foliage, which can't be LODed efficiently otherwise.
  • Distance: Distance at which the HLOD kicks in.
  • Texture Size: Both Impostor and Merged mode need a texture size to work with.

Viewport Preview

Any changes to LOD settings will trigger regeneration and preview of LOD in the viewport (some progress bar needs to be put somewhere, as this will happen in a thread). There are certain preview options:

  • Preview LOD: Toggles preview of LOD in the viewport. Disable to quickly compare with unlodded object.
  • LOD: Disable LOD (hides object when within LOD range, so you can better see the transition to HLOD).
  • HLOD: Disable HLOD (hides object when within HLOD range, so you can better see the transition back to LOD).
  • Bias: Lets you push a LOD bias, so you can see how the LOD meshes/impostor look like without actually zooming in or out.

Additionally, an option to toggle viewport to wireframe needs to be added.

If this enhancement will not be used often, can it be worked around with a few lines of script?

N/A

Is there a reason why this should be core and not an add-on in the asset library?

N/A

@clayjohn
Copy link
Member

Should the HLOD mode also support a "manual" HLOD where the user can specify an artist-created LOD mesh? For certain assets, it may still be worthwhile to support an artist-controlled workflow.

@reduz
Copy link
Member Author

reduz commented Jul 20, 2023

@clayjohn I think that can be done at the scene level already, since its just a VisualInstance property, but my idea here was to add another editor to the mesh importer that is more complex (not just mesh based) where you can select a single mesh as a replacement of multiple ones (as in, all scene going to an impostor or an artist supplied LOD). So its likely a feature that happens more at scene level in the importer in a separate tab.

My idea was calling it "Group Lod" where you can associate multiple meshes to a single other one, even if it also works for one to one.

@lyuma
Copy link

lyuma commented Jul 20, 2023

Regarding import flow for manually constructed LODs, I would like to propose that we solve that by implementing MSFT_lod, which permits a glTF document to define LOD levels for meshes and materials.
https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Vendor/MSFT_lod/README.md

It's a good fit for the HLOD workflow, since it is done at import time in the same way: instead of autogenerating these LOD levels, it's just getting them from the glTF document. It may be somewhat lacking in tooling, but that problem tends to resolve itself if it's useful functionality.

As an alternative to (or in addition to) the glTF extension, we could also offer support for naming child mesh nodes whose names are -lod1, -lod2 etc

@reduz
Copy link
Member Author

reduz commented Jul 20, 2023

@lyuma that should be easy to add if someone wants to do it in the GLTF importer.

@fire
Copy link
Member

fire commented Jul 20, 2023

Notes for my future reference:

Octahedral-Impostors has an implementation here https://github.com/wojtekpil/Godot-Octahedral-Impostors

I believe @aaronfranke has contact with @wojtekpil

Merged: It merges all surfaces, renders all materials to texture, generates a new UV unwrap

I proof of concept this scheme several years ago with xatlas unwrap. Is this still a valid texture unwrap method? Maybe there's another. I recall a simple method where each texture sheet is statically tiled.

https://github.com/V-Sekai/godot/tree/vsk-merge-scene

This is in a state where mesh merging almost is restored from Godot Engine 3.0, but is currently broken.

  1. It depends on a unwrapping based on xtlas V-Sekai/godot@bae2cfa
  2. The code for https://github.com/V-Sekai/godot/blob/vsk-merge-scene/modules/scene_merge/merge.cpp#L260-L324 for baking materials is fairly complicated. I recall you had an rendering based baking method. Can you remind me?

@Calinou
Copy link
Member

Calinou commented Jul 20, 2023

@cosmoddd Please don't bump issues without contributing significant new information. Use the 👍 reaction button on the first post instead.

@mrjustaguy
Copy link

doesn't HLOD also make sense to kick in based on the same heuristics as ALOD (namely relative size on screen) instead of just a fixed distance from camera which is what I'm guessing the Distance is, or am I getting something wrong here?

@atirut-w
Copy link

Not sure how they meant it to work in Godot, but Unity uses on-screen size IIRC. Sounds like a better approach in my opinion.

@Calinou
Copy link
Member

Calinou commented Jul 23, 2023

doesn't HLOD also make sense to kick in based on the same heuristics as ALOD (namely relative size on screen) instead of just a fixed distance from camera which is what I'm guessing the Distance is, or am I getting something wrong here?

HLOD generally requires manual control to look best, as it also works best with artist-authored LODs. Also, how do you compute the on-screen size for HLOD nodes? Remember that these can be adjuted in real-time with no baking.

If you need automatic distance threshold adjusment based on resolution or FOV, this can be done with a script once #3787 is implemented. (This could also be implemented in core with similar logic, but I'm not sure if it can be done without breaking split screen support if each camera uses a different FOV.)

@atirut-w
Copy link

atirut-w commented Jul 24, 2023

Also, how do you compute the on-screen size for HLOD nodes?

In pixels? That way, the quality also scales with resolution.

@Calinou
Copy link
Member

Calinou commented Jul 24, 2023

In pixels? That way, the quality also scales with resolution.

I don't mean the unit, but how do you compute it considering the content of HLODs is not necessarily a single mesh? It can be any node inheriting from GeometryInstance3D, which includes particles (CPUParticles and GPUParticles), etc. It can also be multiple mesh nodes, a MultiMeshInstance3D, …

I haven't checked the mesh LOD detection for LOD selection – does it only use a AABB size or something more elaborate?

@atirut-w
Copy link

atirut-w commented Jul 24, 2023

I don't mean the unit, but how do you compute it considering the content of HLODs is not necessarily a single mesh?

I see. I'd personally go for the quick and dirty method of using AABB, but there are clearly better methods out there. Maybe combine the screen area taken by just the meshes? Maybe do it on a per-mesh basis?

@fire
Copy link
Member

fire commented Nov 2, 2023

updated port of imposters to Godot 4: wojtekpil/Godot-Octahedral-Impostors#20

@Rytelier
Copy link

I've been researching around LODs lately so I'll add few things to the proposal:

  • Crossfade animation where one mesh is fades then other mesh unfades. Use alpha dithering or hashing. Make it a tween instead of position based, so it doesn't get stuck in the middle of fading at certain camera positions.
  • Global setting for HLOD distance (that can be easily changed in game too), where in the mesh settings user sets the multiplier for it.
  • Allow custom variants for the impostor shader, so user can add things like wind sway animation for tree imposters.
  • Allow mixing auto-lod and HLOD for more levels.

@Calinou
Copy link
Member

Calinou commented Apr 12, 2024

  • Crossfade animation where one mesh is fades then other mesh unfades. Use alpha dithering or hashing. Make it a tween instead of position based, so it doesn't get stuck in the middle of fading at certain camera positions.

This is about LOD rendering, not importing (this proposal is purely focused on importing). It's also tracked in another proposal: #5240

  • Global setting for HLOD distance (that can be easily changed in game too), where in the mesh settings user sets the multiplier for it.

This is also about rendering, and it's being tracked in #3787.

@fire
Copy link
Member

fire commented Apr 12, 2024

I've been improving the lod generation godotengine/godot#90180

@michaelharmonart
Copy link

I'll ask here since It seems it seems to be related to the UV generation of LODs (also please correct me if I'm mistaken)

Currently the way we do mesh LOD generation with meahoptimizer means that the UVs of the mesh stay as close to the original as possible to the original mesh such that original materials and textures can be used without modifications (no problems here)

A nice side effect is that lightmapGI works flawlessly with this system.

Now that we have baked shadowmasks #2354 , one pretty big use case for lightmaps is having far away geometry with baked shadows or lighting and then blending to realtime shadows up close for dynamic shadows. Would this new LOD system work with that use case?

The "ideal" world I see would allow for baking of this style of LOD or even artist authored HLOD with lower texel resolution for each LOD level. (assuming that UV2s will not be compatible the same way they are now)

This would hopefully even work for the farthest level with the imposters so there's no sudden brightness change or pop-in.

If I should make a seperate proposal or issue for discussion on this, let me know. But especially for the standalone VR work I'm doing lightmaps and good LODs are both vital for good visuals and performance and I'm very anxious to see how they can be made to work together as well as possible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants