Search Unity

Fast Occlusion Culling Best Practices?

Discussion in 'VR' started by trzy, Aug 16, 2016.

  1. trzy

    trzy

    Joined:
    Jul 2, 2016
    Posts:
    128
    Hi,

    I use the Spatial Mapping Renderer component for culling and attach it to the main camera object (I never need to turn it off). I think by default it updates the mesh every 2.5 seconds. It seems that this component can cause the frame rate to degrade to 30 FPS (although not immediately, but seemingly after game objects are moved around).

    What are most people doing for occlusion culling at near 60FPS? Is pre-scanning the room and using a static mesh (a la games like Young Conker) the recommended method of doing this? I presume this requires rolling ones own spatial mesh manager?

    Thanks,

    Bart
     
  2. BrandonFogerty

    BrandonFogerty

    Joined:
    Jan 29, 2016
    Posts:
    83
    Hi @trzy

    Could you clarify what you mean by using the Spatial Mapping Renderer component to cull? The renderer component will try to add as many surface game objects to your environment as the HoloLens reports. Therefore you should stop requesting updates from the device as soon as you can. You don't need to roll your own renderer component to do this. You can simply set the "FreezeUpdates" property on the component to true when you no longer need spatial mapping updates. The following is an example.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.VR.WSA;
    3.  
    4. public class RoomManager : MonoBehaviour
    5. {
    6.     public SpatialMappingRenderer smRenderer = null;
    7.     public float maxTimeInSeconds = 30.0f;
    8.  
    9.     private float endTime = float.MaxValue;
    10.  
    11.     // Use this for initialization
    12.     void Start ()
    13.     {
    14.         endTime = Time.time + maxTimeInSeconds;
    15.     }
    16.    
    17.     // Update is called once per frame
    18.     void Update ()
    19.     {
    20.         if(smRenderer.freezeUpdates)
    21.         {
    22.             return;
    23.         }
    24.  
    25.         if(Time.time >= endTime)
    26.         {
    27.             smRenderer.freezeUpdates = true;
    28.             Debug.Log("Froze Spatial Mapping Renderer Updates!");
    29.         }
    30.     }
    31. }
     
    behram likes this.
  3. trzy

    trzy

    Joined:
    Jul 2, 2016
    Posts:
    128
    I have the component attached to the main camera as shown in the image. I never freeze updates. But I'll give this a try. If I understand correctly, I can use this component to direct the user to map the room and then upon their request, freeze updates and begin the game, resuming again only when they've left the mapped area (I presume this is somehow detectable). Is that more or less correct?
     

    Attached Files:

    • spat.jpg
      spat.jpg
      File size:
      23.1 KB
      Views:
      816
  4. BrandonFogerty

    BrandonFogerty

    Joined:
    Jan 29, 2016
    Posts:
    83
    That is correct.
     
  5. trzy

    trzy

    Joined:
    Jul 2, 2016
    Posts:
    128
    How do you attach the SpatialMappingRenderer to a custom scripted object? I created an empty game object, attached a script much like the one you posted above, and then added the SpatialMappingRenderer as a component of the game object. However, I cannot obtain the object:

    Code (csharp):
    1.  
    2. m_renderer = GetComponent<SpatialMappingRenderer>();
    3.  
    Also, what is the purpose of the Surface Parent field? The documentation says a game object will automatically be created. Is there any reason for the user to define one?

    Thanks.
     
  6. trzy

    trzy

    Joined:
    Jul 2, 2016
    Posts:
    128
    I guess it has to be instantiated in code. For reference:

    Code (csharp):
    1.  
    2. public class SpatialMap : MonoBehaviour
    3. {
    4. public Material m_occlusion_material;
    5. public Material m_rendering_material;
    6. private SpatialMappingRenderer m_renderer;
    7. public void Disable()
    8. {
    9. m_renderer.FreezeMeshUpdates = true;
    10. m_renderer.enabled = false;
    11. }
    12. public void Scan()
    13. {
    14. m_renderer.FreezeMeshUpdates = false;
    15. m_renderer.CurrentRenderingSetting = SpatialMappingRenderer.RenderingSetting.Material;
    16. m_renderer.enabled = true;
    17. }
    18. public void Occlude()
    19. {
    20. m_renderer.FreezeMeshUpdates = true;
    21. m_renderer.CurrentRenderingSetting = SpatialMappingRenderer.RenderingSetting.Occlusion;
    22. m_renderer.enabled = true;
    23. }
    24. void Awake()
    25. {
    26. m_renderer = gameObject.AddComponent<SpatialMappingRenderer>();
    27. m_renderer.OcclusionMaterial = m_occlusion_material;
    28. m_renderer.RenderingMaterial = m_rendering_material;
    29. m_renderer.CurrentRenderingSetting = SpatialMappingRenderer.RenderingSetting.Material;
    30. m_renderer.FreezeMeshUpdates = false;
    31. m_renderer.LevelOfDetail = SMBaseAbstract.MeshLevelOfDetail.Medium;
    32. m_renderer.TimeBetweenUpdates = 2.5f;
    33. m_renderer.NumUpdatesBeforeRemoval = 10;
    34. m_renderer.UseSphereBounds = false;
    35. m_renderer.Extents = new Vector3(10, 10, 10);
    36. Disable();
    37. }
    38. }