Search Unity

Bug Fustrum Culling not working - Drawing renderers out of it - No shadows

Discussion in 'General Graphics' started by WBonX, Nov 1, 2023.

  1. WBonX

    WBonX

    Joined:
    Aug 7, 2018
    Posts:
    59
    I'm drawing procedural geometries, recalculating the bounds, made a script to show the new generated bounds.

    Moving an object with a camera around the scene I noticed that renderers with bounds way outside (30/40 dist) from the camera fustrum are still rendered. (This are not even close to the fustrum).

    I disabled all the shadows and tried also disabling receive shadows on the new objects.

    Looks like fustrum culling is just failing and trying to draw outside of the camera fustrum.

    (No object is casting or receiving shadows).

    The new renderer/mesh bounds are correctly drawn in the test gizmos I made.

    Camera is perspective, relatively short clipping plane(5-50).

    I tested by FrameDebugger.. by Checking calls/Trings and by a custom script that calls Renderer.isVisible();

    In the picture you can see the camera fustrum, In red the obj outside of it, in blu the bound box of the renderer/mesh. Consider also the fustrum looks way down, it is at least 30m away from the object at ehe closest point, the object has no childs.

    Position is around(200,0,200) from world origin.

    P.S. Tests done in play mode.

    upload_2023-11-1_15-20-5.png
     
    Last edited: Nov 1, 2023
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,674
    The scene camera is a Camera too. :)
     
  3. WBonX

    WBonX

    Joined:
    Aug 7, 2018
    Posts:
    59
    I will take it as a joke, but good try ;)

    Obviously all checks are done during play mode, with a single camera ;)
     
  4. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,195
    If even a single vertex of a mesh is visible, the whole mesh will be rendered. Kind of hard to tell, but that red mesh looks pretty big, and I wonder if the camera can see one of its verts off in the distance perhaps? It kind of looks like the frustrum will intersect it if that red mesh keeps going a bit further off screen.

    Maybe try testing with a much smaller mesh that you place behind the camera, to convince yourself that the debugging you're doing is giving valid results?
     
  5. WBonX

    WBonX

    Joined:
    Aug 7, 2018
    Posts:
    59
    Hei good try ;)

    But missing a few basic concepts.

    First a recalculated bound box is going to include the whole mesh and later used for fustrum culling (single verts can't be out of it, see pic).

    Second, the clip plane of a camera is the last rendered distance from it, so what you suggest of the camera going to render to infinite isn't the way. As I mentioned my clipping plane is quite short (50, also in the pic).
     
  6. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,195
    Looking at the docs for Renderer.isVisible:

    So I'm not sure whether you can ever visually confirm whether Frustrum culling is happening if you're looking at things in the scene view. But I just tested out whether Renderer.isVisible seemed to work properly, and it seems about right to me.

    Code (CSharp):
    1.     [ExecuteInEditMode]
    2.     public class DeleteMe : MonoBehaviour
    3.     {
    4.         public Renderer Test;
    5.  
    6.         // Update is called once per frame
    7.         void Update()
    8.         {
    9.             if (Test != null)
    10.             {
    11.                 Debug.Log(Test.isVisible);
    12.             }
    13.         }
    14.     }
    I added that to me scene, and assigned a renderer to it. The isVisible result changes correctly as the object goes in/out of view of the scene view camera, as well as in/out of view of my 1st person camera in play mode. There's a bit of a margin where the object claims to be visible even when it isn't, but this margin goes way down if I disable shadows on the renderer.

    So, it all seems pretty much correct behavior as far as I can tell. I'd make sure the issue isn't just that you have the renderer shown in the scene view.
     
  7. WBonX

    WBonX

    Joined:
    Aug 7, 2018
    Posts:
    59
    Thanks for your time, but...

    As I mentioned in the original post and then again in the first answer, the tests are done in Play Mode
    The Renderer.isvisible() is just one of the tests I have done, others are mentioned in the OP.

    It must be more complicated then that, I guess a bug/major approximation in the way the fustrum is computed against the bounding boxes.

    Let's see if others can help. Thank you.
     
  8. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,195
    Can you share the mesh you're testing with? Or better, share a small project that you feel properly demonstrates the bug you're seeing? It's difficult to try to guess at what could be going wrong from just a brief description of the environment and your methodology.

    Like I said, I just tested out frustrum culling, in edit mode and in play mode, and it seems to work as you'd expect. Placing that script on an object, I rotate the camera (in play mode) and find that the debug output becomes True only when the camera is generally looking in the direction of the object, otherwise it's false. I tried setting view distance very low, and that successfully prevents the object from being considered visible, as expected. I also tried making the object Batching Static, thinking that perhaps frustrum culling doesn't work if the object has been merged with other visible objects. It's possible that's the case in a build, but it didn't cause any issues in the editor.

    Anyway, I can at least say that frustrum culling seems to work fine in my simple test. I imagine you can't easily share the actual scene where this is happening, but I'd recommend building a simple test scene that demonstrates the issue occurring, and share that.
     
  9. WBonX

    WBonX

    Joined:
    Aug 7, 2018
    Posts:
    59
    Thank you for your time.

    Unity doesn't batch large meshes, so no that is not the case. ( See documentation).

    The mesh is procedural, in the range of 6-9K vertices, if you want to play around reproducing the issue it is easy to make one procedurally (offset from object origin (200,200) / (600,600).

    I would be more interested if someone expert on the topic would reply with some pseudocode on how Fustrum culling is implemented in Unity.

    My guess, as I mention in the OT, is that there is a bug somewhere in the calculation of the hit of the bound against the fustrum, maybe due to the origin of the Object with the mesh, if that is taken into account. Unlikely I can't see the code.

    I dedicated the bug 2 days, would be nice if a moderator could give some infos.

    Thank you.
     
  10. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,195
    You should just submit a bug report, in that case. You might get lucky with a dev response on the forums, but if you submit a bug report (with a proper demo project that demonstrates the bug), you should get some confirmation on whether the behavior is considered a bug or not. But the burden is kind of on you to submit the bug report with a simple enough test case that shows the behavior.

    Best of luck tracking down the answer.
     
  11. WBonX

    WBonX

    Joined:
    Aug 7, 2018
    Posts:
    59
    I know I can submit bug reports.

    Was hoping to get some infos here first that go beyond my knowledge, I may be missing something.

    Please to avoid crowding the thread reply if you have some advice that go beyond the unity basic knowledge.

    Thank you.
     
  12. WBonX

    WBonX

    Joined:
    Aug 7, 2018
    Posts:
    59
    Still looking for some inside on the OT problem .. .

    I'm also trying to sort out a way to debug Culling in general, I'm noticing it's taking a good part of the computational time in general.

    Someone knows if there is a way to know the contribute of a single object to fustrum culling?
    (terrain mesh of the objects in the picture is on the average 6K verts, not much).

    (Things are optimized enough between splitting in smaller objects when necessary and keeping larger meshes when is optimal, maybe with submeshes if needed)