Page MenuHomeWildfire Games

Discrete LOD
Changes PlannedPublic

Authored by Angen on Nov 24 2019, 8:14 PM.

Details

Reviewers
None
Summary

Implementing Discrete Level of detail for models based on the distance from camera.

Before submitting model to the renderer, it calculates distance from camera. Based on that computed distance, is switched to another variant of the model.
To not rebuild model everytime, there is member variable LOD, which is true, if lower level of detail have been chosen to not rebuild models when it is staying the same.

In actor, main model (not props) can introduce variant with name "low" and that will be chosen. It will switch back to or frequency = "1" or name = "high" variant in the same group.

What we can do with this is, that we can hide all small props that do not need to be visible from distance and it does not matter. Another thing we can do is to switch to meshes with lower number of vertices.

Current distance to switch models is hardcoded and kind of small for showcase (maybe it is enough, dont know actually).

I am also hiding projectiles at some distance entirely, because units have high rate of fire and they stay at ground quite long so with bigg frustrum range, there is really a lot of them so that might help perf too. (I ll split this to another diff if someone suggests it)

Another usage: Hyrule Conquest would like to have that.


I ll remove actor changes for another diff after feature is complete.
Also I would like to do profiling but i need find out why profiler2 is failing for me.

Btw. That units edited are in combat demo huge
I do not expect too much improvement since I removed just some random props.

Test Plan

Suggest better names
Check logic

Event Timeline

Angen created this revision.Nov 24 2019, 8:14 PM
Owners added subscribers: Restricted Owners Package, Restricted Owners Package.Nov 24 2019, 8:14 PM
Stan awarded a token.Nov 24 2019, 8:16 PM

Successful build - Chance fights ever on the side of the prudent.

Link to build: https://jenkins.wildfiregames.com/job/vs2015-differential/639/display/redirect

Successful build - Chance fights ever on the side of the prudent.

Link to build: https://jenkins.wildfiregames.com/job/docker-differential/1155/display/redirect

elexis added a comment.EditedNov 24 2019, 8:27 PM

The intervals should probably not be buried in the code but specified somewhere, probably ideally in some model related art file or template (and ideally support more than two levels).
Perhaps std::pair<CStr, CStr>("lod", "low")) / selections can be constructed only once per program launch instead of once per call.
{ on a separate line.
Hiding projectiles after a set distance means it will fail for some projectiles of a given size, so it should be moved to data files as well.
It would be a good feature, although I guess in the average case only high level of detail will be shown, since the camera is top down on average?

Angen planned changes to this revision.EditedNov 24 2019, 8:49 PM

move interval to each actor
check distance only if actor defines that it has lod versions
disable/enable lod from graphic options
remove projectile manager changes as not exactly related

Angen added a comment.Nov 24 2019, 8:50 PM

It would be a good feature, although I guess in the average case only high level of detail will be shown, since the camera is top down on average?

With reasonable distance one can have high level models with close camera and low level in normal

vladislavbelov added inline comments.Nov 24 2019, 9:01 PM
binaries/data/mods/public/art/actors/structures/athenians/civil_centre.xml
28

I think it'd be better to use numbers here, because it's easier to pick (no need to store strings in C++) and sometimes we need more levels of LODs and then we'd have a problem with new naming.

source/simulation2/components/CCmpProjectileManager.cpp
378

It's not needed to calculate inverse of a camera matrix for each model. For many models it might be noticeable for performance (see implementation of GetInverse).

source/simulation2/components/CCmpUnitRenderer.cpp
74

What does the LOD name mean? It's not obvious from the name.

nani awarded a token.Nov 24 2019, 9:28 PM
Stan added a comment.Nov 25 2019, 2:27 PM

Lods should be in the template visual actor. Else actors will become a great mess. Also there will be warnings everywhere or missing props.

Good feature, indeed the implementation is relatively straightforward.

You probably want to make hardcoded numbers into class constants or configurable constants (or indeed, an option).

source/simulation2/components/CCmpProjectileManager.cpp
382

This definitely needs to be a different check. Ideally, you would take the AABB, calculate how many pixels across it'd be, and possibly skip if the # of pixel is significantly less than 1.

Very good idea to work on that :) .
This needs some work before it can be committed, but nothing too huge I think.


On the LOD side, you have some code repetition and Vladislav said, you should not recalculate the camera matrix every time. Maybe add it to "Frustrum" (dunno if that makes sense), or pass it as an argument.

This is skippable, but given that you're doing the same LOD logic (to an extent) in different components, it sounds like a good idea for a header-only helper (basically just a function that takes all proper arguments and outputs the correct LOD). Since this is strictly graphics, it should go in graphics.

I think you should implement a "too far" culling. Ideally, take the bounding box into account and compute a sort of "size on screen", and discard if too low.
This would be particularly useful for props and actors (such as grass). It might thus make sense to implement your LOD directly in SubmitRecursive as well, for props.


With the above said, my main concern is that you're going to be running "ReloadActor" basically every frame. This is wasteful and kind of negates the performance gain of LOD. Further, we're manipulating strings and std::map, and that's slow.
Using variants is clever, but it won't work well for groups that already have named variants. I admit most mesh-only groups don't, but it's a problem.
I don't really have a good way around this... The simplest solution I can think of is to hardcode different actors in the VisualActor based on LOD levels, and then switch at runtime. It's kinda meh to do it in templates though, I think, and it forces creating entirely new actors (that might be OK though, because as elexis said in the general case our cameras don't really experience that much perspective).
The alternative would be creating a cleverer system to create objects, but that sounds entirely non-trivial :P

I'm not sure you actually should implement "low-high" switch for now. If you can already implement a working, efficient LOD that hides units and props when they're too far to see, we'll have something useful.

source/simulation2/components/CCmpUnitRenderer.cpp
448

Don't implement "behind the camera" culling.

Since you don't actually account for the entity BB, you'll fail occasionally and units will "pop-in". Further, culling is already handled, so this is just double-work.

Stan added a comment.May 23 2020, 6:18 PM

Very good idea to work on that :) .
...
It's kinda meh to do it in templates though, I think, and it forces creating entirely new actors (that might be OK though, because as elexis said in the general case our cameras don't really experience that much perspective).

I think it's better to do it in templates for the current actor system is messy enough, and it doesn't give much flexibility if you do it in actors.
Different Lods might have different animations, props and variants (eg less particles, lower poly sword, no fallback animation, simpler rigs) For instance, helmets wil never fit on low poly meshes.

Defining it in templates allows to separate concerns, and reduce the complexity of such files. It does require to introduce new templates though.
One could define a {lod} prefix by default none, with verylow, low, no prefix, high, veryhigh, ultra actors being picked depending on what's available.

<actor>{lod}{civ}_infantry_spearman</actor>

The only downsides is that it doesn't allow for a separation of concerns between the renderer and the simulation, but we don't currently have the resources to generate automatic lods

I made some profiling on the new map oceanside using athenians archers. I noticed realy big performance improvements when zooming out.
Test conditions: oceanside map, athenians archer, no moving of the units, saved at 4:30min, completely zoomed out, no moving of the camera from it's start position (only zooming out)


profiler2 frame: red old, green patched.


profiler2 old


profiler2 patched

Are there any plans to finish and commit this patch?

Stan added a comment.Wed, Nov 11, 12:07 AM

@OptimusShepard is it the same if you disable the props?

I suspect <prop actor="props/units/quiver_greek_back.xml" attachpoint="back"/> to be particularly slow.

In D2440#135335, @Stan wrote:

@OptimusShepard is it the same if you disable the props?

I made a new profiling with deactivating instead of the patch, absolutely the same.

I suspect <prop actor="props/units/quiver_greek_back.xml" attachpoint="back"/> to be particularly slow.

You're right, this is the main point.


profiler2 frame: red patched, green only quiver greek back deactivated, blue old
I guess, trees could be interesting too.

Stan added a comment.Wed, Nov 11, 12:59 AM

I'm gonna push some change, can you try again afterwards ?

In D2440#135338, @Stan wrote:

I'm gonna push some change, can you try again afterwards ?

Sure.