Switch LOD generation to use iterative simplification#110027
Switch LOD generation to use iterative simplification#110027clayjohn merged 1 commit intogodotengine:masterfrom
Conversation
|
For posterity, I'll note future work here as I've done in prior issues (assuming all 4 PRs in the chain land):
And, these two ideally should wait for meshoptimizer 1.0 as both upstream features are experimental and will see some improvements in the next version:
|
There was a problem hiding this comment.
Tested locally, it works as expected. Code looks good to me.
Preview
Before
This is after updating meshoptimizer to 0.25, i.e. the "After" video in #109990. This uses the same MRP as in my review there.
pr.webm
After
pr_iterative.webm
|
The “flashing images” disclaimer will haunt me now 😅 fwiw this is mostly the case on axis aligned tessellated planes that previously got an error that’s exactly zero and now get a small error in 1e-6 neighborhood. Any sufficiently non-zero lod threshold will still select the most coarse lod but small thresholds may select intermediate lods in certain cases. Non axis aligned tessellation has round-off error during internal calculations so that never generated error = 0. |
Instead of simplifying every LOD from the original down to an increasing number of triangles, we simplify each LOD from the previous LOD and stop when the simplification can't proceed further. This has a few benefits: - It's significantly faster; using sparse flag helps ensure that subsequent simplifications after the first one are increasingly cheaper. - It results in higher quality attributes on generated LODs; attribute quadrics reduce the quality of attribute preservation the more they are accumulated, so recomputing them from intermediate geometry helps. - It results in monotonic appearance: if a feature is reduced in a higher LOD, it will stay reduced or get reduced more significantly in lower LODs. This is not a significant problem right now, but can be helpful to ensure if the number of LODs increases or some newer features get enabled.
|
Thank you! |


Instead of simplifying every LOD from the original down to an
increasing number of triangles, we simplify each LOD from the previous
LOD and stop when the simplification can't proceed further.
This has a few benefits:
It's significantly faster; using sparse flag helps ensure that
subsequent simplifications after the first one are increasingly
cheaper.
It results in higher quality attributes on generated LODs; attribute
quadrics reduce the quality of attribute preservation the more they
are accumulated, so recomputing them from intermediate geometry helps.
It results in monotonic appearance: if a feature is reduced in a
higher LOD, it will stay reduced or get reduced more significantly in
lower LODs. This is not a significant problem right now, but can be
helpful to ensure if the number of LODs increases or some newer
features get enabled.
After this change, the set of generated LODs will be a little different, as the number
of triangles the simplifier is given is naturally distinct - however, the behavior
in general should be more or less consistent. Now that generating more LODs is
quite cheap, we can explore making LODs a little more frequent (e.g. doing 1.6x steps
instead of 2x steps) in the future.
Just like previously, on some models we end up reducing the LOD 2x and generating
a significantly steeper error, whereas a 1.6x reduction could result in a more reasonable
error. This is something we can explore fixing in the future (for example, if a given simplification
produced an error that's more than 3x the previous error, we can attempt to rerun it with a
smaller target, which is now easy and fairly cheap). To reduce the complexity of this change,
it doesn't do that.
Testing this on a 100-model variant from #93587,
I get 25 seconds to import before this change, and 17 seconds after. This, however, doesn't
tell the full story: before this change, the simplification time during the import is 11 seconds,
and after this change it's just 3!
0.5 out of 3 seconds after this change is spent outside of
meshopt_simplifyin various hashmapcode. This can be improved in the future / separately; that all will be unnecessary if we switch
to permissive simplification, but that will probably be in 4.7 timeframe.