Search Unity

Changing layer in camera's culling mask in runtime, does not work as intended for certain clear flag

Discussion in 'Editor & General Support' started by Karsnen_2, Oct 20, 2019.

  1. Karsnen_2

    Karsnen_2

    Joined:
    Nov 28, 2011
    Posts:
    89
    Unity Version : 2018.4.10f1
    Target Platform : iOS
    Dev Machine: Mac OS 10.14.6 (Macbook Pro 2018)


    Scenario

    At the start, the camera's culling mask is set to only "default" layer. Apart from the built-in layers, I have four user-layers.
    • "HPlane"
    • "VPlane"
    • "Content"


    Now during the application's runtime, I would like to add all/some of the above layers to Camera's culling mask. At the same time, I would also like to remove that particular combination at any point in time. When I remove that particular combination, the Camera's culling mask would end up rendering only the "default" layer.

    Code
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. namespace CameraQA
    6. {
    7.     internal sealed class LayerCulling : MonoBehaviour
    8.     {
    9.         [SerializeField] internal Camera MainCamera;
    10.         private const string defaultLayer = "default", verticalLayer = "VPlane", horizontalLayer = "HPlane", contentLayer = "Content";
    11.         private int hideMask;
    12.  
    13.         private void Start()
    14.         {
    15.             SetMaskFor(true, false);
    16.         }
    17.  
    18. #if UNITY_EDITOR
    19.         private void Update()
    20.         {
    21.             if(Input.GetKeyDown(KeyCode.A) == true)
    22.             {
    23.                 ToggleForDisplay(true);
    24.             }
    25.  
    26.             if(Input.GetKeyDown(KeyCode.B) == true)
    27.             {
    28.                 ToggleForDisplay(false);
    29.             }
    30.         }
    31. #endif
    32.  
    33.         internal void SetMaskFor(bool _isHPLANE, bool _isVPLANE)
    34.         {
    35.             if(_isHPLANE && _isVPLANE)
    36.             {
    37.                 hideMask = LayerMask.GetMask(verticalLayer, horizontalLayer, contentLayer);
    38.             }
    39.             else if (_isHPLANE == true)
    40.             {
    41.                 hideMask = LayerMask.GetMask(horizontalLayer, contentLayer);
    42.             }
    43.             else if (_isVPLANE == true)
    44.             {
    45.                 hideMask = LayerMask.GetMask(verticalLayer, contentLayer);
    46.             }
    47.             else
    48.             {
    49.                 hideMask = LayerMask.GetMask(contentLayer);
    50.             }
    51.         }
    52.  
    53.         private void layerCullingShow(int _layerMask)
    54.         {//http://www.jarrahtechnology.com/2014/04/01/Culling-Mask-Tip/
    55.             MainCamera.cullingMask |= _layerMask;
    56.         }
    57.  
    58.        
    59.         private void layerCullingHide(int _layerMask)
    60.         {
    61.             MainCamera.cullingMask &= ~_layerMask;
    62.         }
    63.  
    64.  
    65.         internal void ToggleForDisplay(bool _toVISIBLE)
    66.         {
    67.             switch(_toVISIBLE)
    68.             {
    69.                 case true:
    70.                     layerCullingShow(hideMask);
    71.                     break;
    72.  
    73.                 case false:
    74.                     layerCullingHide(hideMask);
    75.                     break;
    76.             }
    77.             Debug.Log("Visibility -> " + _toVISIBLE);
    78.         }
    79.     }
    80. }

    Problem

    Now in the inspector for the Camera, the layers get switched properly. Camera renders properly only if the Camera's clear flags are set as either
    • Skybox
    • Solid Color
    The camera does not render properly for the following
    • Depth Only
    • Don't Clear

    Request
    I want this to work for "Depth Only" clear flag on the Camera.

    Project Download Link (Unity 2018.4.10F1)
    https://1drv.ms/u/s!AtsHBEZmJKTwga5cYgAvK_jODAjVHg?e=nGhOvt

    Thank you for your time.
     
  2. Madgvox

    Madgvox

    Joined:
    Apr 13, 2014
    Posts:
    1,317
    I haven't downloaded your project, so without a screenshot, I am only speculating on what you mean when you say that the camera "doesn't render properly". However, I am assuming that you mean that the objects that are in the now-hidden culling layers still appear in the render when using Depth Only or Don't Clear modes. If I'm wrong, ignore this post.

    This is not a bug, and is in fact a perfect illustration of what the Depth Only mode does. Textures that are used for rendering have both color and depth information. Depth Only is true to its namesake and only clears the depth information and not the color information. This means that if you still have something that was rendered in a previous frame in your color buffer, it will still be there in subsequent frames unless it is explicitly drawn over by something else (like the skybox, for example). When Solid Color is selected, it clears the entire color buffer with your chosen color first, and then draws the image. This is why Solid Color works when Depth Only doesn't.

    I'm guessing that you want to use Depth Only mode in order to create a render with a transparent background. You can do this by clearing the buffer with a color that has an alpha of 0 (when the camera is being rendered to the Game View, it ignores any transparency information, but that doesn't mean that the underlying texture can't have any transparency information).
     
  3. Karsnen_2

    Karsnen_2

    Joined:
    Nov 28, 2011
    Posts:
    89
    Thank you for your reply.

    So to be clear, my camera clear flag is "Depth-Only" & I do not have any other camera in the scene.

    When @Madgvox mentioned

    I modified a particular method to

    Code (CSharp):
    1. internal void ToggleForDisplay(bool _toVISIBLE)
    2.         {
    3.             switch(_toVISIBLE)
    4.             {
    5.                 case true:
    6.                     layerCullingShow(hideMask);
    7.                     break;
    8.  
    9.                 case false:
    10.                     layerCullingHide(hideMask);
    11.                     break;
    12.             }
    13.             GL.Clear(true, true, Color.clear);
    14.             Debug.Log("Visibility -> " + _toVISIBLE);
    15.         }
    As you might see in the above code, after I change the layermask in the camera - I call https://docs.unity3d.com/2018.4/Documentation/ScriptReference/GL.Clear.html

    Now there is no effect in the game view panel. But however running on my mobile the camera starts to flicker. That GL call is only made once.

    I am not familiar with culling mask & low-level rendering techniques. Could someone help me here.
     
  4. Madgvox

    Madgvox

    Joined:
    Apr 13, 2014
    Posts:
    1,317
    That is not what I meant by my response! Apologies for not being clearer. If you set the camera to Solid Color and clear it with say, a fully transparent black, then this should give you the transparency you need.

    If this is the only camera in the scene, what do you need the transparency for?
     
  5. Karsnen_2

    Karsnen_2

    Joined:
    Nov 28, 2011
    Posts:
    89
    @Madgvox - I am working in Augmented Reality & it was documented to use such clear flags. I will try with Solid Color.

    I highly appreciate your help.

    Thank you.