Search Unity

Bug Is the LOD system broken?

Discussion in 'General Graphics' started by sebas77, Aug 12, 2021.

  1. sebas77

    sebas77

    Joined:
    Nov 4, 2011
    Posts:
    1,642
    I am convinced the LOD system is broken. I have proof of this, but I need to find the time to write a proper bug report with a proper reproduction. I however wonder how come I cannot find users complaining about this. The lod system should work according to what written in the documentation:

    upload_2021-8-12_18-47-39.png

    while the documentation says that the LOD should depend on the projected height, it is obvious to me that instead is dependent on area/volume.

    Did anyone notice it?
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    I have not noticed this, nor can I reproduce any behavior that contradicts the documentation.

    Setting the aspect ratio to a 1:1 ratio and setting up an LOD transition to be just below the current %, and then changing the aspect ratio to something other than 1:1 should cause the LOD Group to drop to the next LOD level if it worked on ratio. But it doesn't, the aspect ratio has no effect.
    upload_2021-8-12_11-46-8.png upload_2021-8-12_11-46-18.png
    upload_2021-8-12_11-46-44.png

    And while the above is the scene view, doing the same in the game view produces the exact same results.
     
  3. sebas77

    sebas77

    Joined:
    Nov 4, 2011
    Posts:
    1,642
    You can notice only if you compare how lod works with two different gameobjects that have the same lod settings, the same height but different width. I am not sure about depth, but once I'll have time I'll make a repro. To be clear, if the GOs have the same height, they should behave the same indipentently by the other axis. Using a sphere for testing is a very specific scenario.
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    The bounds the LOD Group uses to determine the screen coverage are very basic.

    When the LOD 0 renderers are set, or when you click on "Recalculate Bounds", it gets the collective bounds extents of all renderers visible for LOD 0 in local space to the transform the LOD Group component is on. From that it gets a local space mid point and the max dimension of the total bounds. Note that max dimension is just the max local xyz axis size. That max local size is then scaled by the local max transform scale axis. Those two values are used as the center position and radius of a screen space circle that is used to determine the vertical screen coverage.

    The result is the bounds used for the LOD Group can look nothing like the visible object it's supposed to be representing, and can be much smaller, or much larger, than the meshes its representing, especially when using a wide FOV.

    And that's totally fine for most use cases. The main reason to do it this way is it's super cheap to calculate, which is likely the primary consideration being made when they wrote this system over 10 years ago.
     
  5. sebas77

    sebas77

    Joined:
    Nov 4, 2011
    Posts:
    1,642
    I have to understand what you wrote, I'll do tomorrow. However the documentation says screen space height, that means projected boundaries. I'll re check ASAP taking in consideration your explanation. Anyway to us this behavior causes a lot of problems. We can't set the same lods expecting consistent behavior so we have fine tune them case by case
     
  6. DEEnvironment

    DEEnvironment

    Joined:
    Dec 30, 2018
    Posts:
    437
    just some observation
    the LOD fade systems do have different behaviors from 2018 than that found in 2019

    in 2018 unity used positive values 0 - 1 and in 2019 they introduced negative values to give the fade-in and fade-out accordingly


    not certain what unity version this thread is about

    cheers
     
  7. sebas77

    sebas77

    Joined:
    Nov 4, 2011
    Posts:
    1,642
    ok I found the time to do some test, I don't have much time to go in depth, so let me know what I am not understanding or what extra information you may need.

    From my understanding of the documentation there shouldn't be any difference in behaviour between two meshes that have the same projected height. To not make things complicated, we take in consideration just two simple parallelepipeds that projected should become just rectangles.

    these two meshes have the same height and same lod settings:

    upload_2021-8-16_14-57-51.png

    however the longer one changes lod much earlier:

    upload_2021-8-16_14-58-14.png

    than the short one:

    upload_2021-8-16_14-58-50.png

    even with an orthographic camera to take out from the equation perspective, the result doesn't change.

    Does this make my original post clearer? Please let me know what you think about it.

    P.S.: note that I am not arguing about which behavior makes more sense, I am just comparing it to what I think the documentation is stating. In fairness, for our game, it would make more sense to behave like I think it should behave and not like it is actually behaving.
     
    Last edited: Aug 16, 2021
  8. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    Ah, yes. I see how the documentation is confusing here. The documentation simply states it's the "height of the game object", but never states how that height is calculated. It's entirely logical to expect it to be the actual visual height, but it is not. It's calculated as I described above from the max local bounds. It's done this way because it's cheap to calculate once and doesn't need to be recalculated based on the alignment of the object with the camera.

    I believe you can override the built in behavior for how it calculates the "size" by manually setting
    LODGroup.size
    from c#.
    https://docs.unity3d.com/ScriptReference/LODGroup-size.html

    Or you can set it directly in the editor using the debug inspector. Right click on the Inspector tab and select Debug and the LODGroup size will be exposed and can be modified. Just remember not to hit "recalculate bounds" again.
     
    funkyCoty and sebas77 like this.
  9. sebas77

    sebas77

    Joined:
    Nov 4, 2011
    Posts:
    1,642
    if you can rephrase your explanation it would be nice, I understood only half of it. It seems that it works on the function of the longest axis, but I didn't understand the rest of the procedure. I wonder if this algorithm is standard though, because I do see how the projected height only method would make a lot of sense too.

    while it's true that the longest mesh would be more noticeable for longer on the screen, for the number of pixels on the screen, a high number of vertices wouldn't make sense anyway. A projected height-only behavior would make LOD consistent, so we wouldn't need it to fine-tune it for each mesh.

    I do see a point regarding the cull though, a longer line would be more noticeable than a pixel when culled away...still...
     
  10. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    It's not really about trying to handle a cube vs. a long thin mesh. It's about trying to be as cheap as possible to calculate. Don't think of it as a "height", think of it as a "size", or even better a "diameter". The cheapest option is to only have to worry about a single "size", the max lossy scale axis, a position's distance from the camera, and the camera's FOV.

    The "size" is the max dimension of the combined local AABB (axis aligned bounding box) of the LOD 0 renderers in the space of the game object the LODGroup component is on.

    For a single default cube mesh with no scaling, this is a size of 1.

    For a single default cube mesh on the same game object as the LODGroup that has been scaled, this size is still 1. Because in local (unscaled) space, it's still just the default cube.

    For a cube mesh that's a child of the LODGroup's game object and has been locally scaled to 4x on at least one dimension, the size is now 4. Because in the LODGroup's local space, it's 4 units wide. It does not matter which axis it was scaled on, could be just one, two, or all 3. All that matters is which is the biggest.

    If that child cube is rotated, then the size will also be different, because the AABB in the LODGroup's local space will have changed.


    But it's all just a quick approximation of that object's coverage. There's no special handling for long thin objects vs large objects of the same max bounds. They're the same "size" as far as the system is concerned.
     
    Peter77 likes this.
  11. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    To try and simplify it as much as I can:

    The LOD Group's size is based off of the max dimension of LOD0. The percentage is then calculated by approximating how much of the vertical screen area a screen facing shape (like a sprite or particle) of that size if it was at the current distance and the center of the screen.

    It knows doesn't care or know anything about the actual dimensions of the object being rendered, or it's orientation. It doesn't really even care there is anything visible, and shouldn't, because one of the options for the LOD Group is of course to hide it completely. It doesn't know or care if the object is a cube, sphere, or nearly infinitely thin line. It's just blindly using that single dimension "size" for everything.
     
  12. sebas77

    sebas77

    Joined:
    Nov 4, 2011
    Posts:
    1,642
    from the way you explain it, it seems that the LOD is in function of the projected diameter/radius of the bounding sphere enclosing the mesh. Anyway, I guess the size field you linked before would be enough to change the LOD behaviour if I want to. Still, the documentation should be edited.
     
    Last edited: Aug 17, 2021
    bgolus likes this.