Search Unity

Question IsCameraProjectionMatrixFlipped is being called outside camera rendering scope.

Discussion in 'Universal Render Pipeline' started by collinpatrick15, Sep 14, 2021.

  1. collinpatrick15

    collinpatrick15

    Joined:
    Nov 7, 2018
    Posts:
    38
    Hello!

    I am trying to edit a paint plugin that uses render textures to render paint splats on objects but I keep running to this assertion: "IsCameraProjectionMatrixFlipped is being called outside camera rendering scope." I have no clue what this error actually means or how to fix it. I am not too knowledgeable of the rendering side of Unity so this may be an obvious error, but I cannot seem to find any information about it online. If anyone can help me understand this error, it would be greatly appreciated.

    This assertion occurs when I try to create and apply the paint textures on objects when they become visible using Unity's Culling Group API. My painting system still works as expected other than this error, except if I manage to get the error too many times in quick succession Unity crashes.

    This is the code that is creating the assertion in UniversalRenderPipelineCore.cs
    Code (CSharp):
    1.         /// <summary>
    2.         /// True if the camera device projection matrix is flipped. This happens when the pipeline is rendering
    3.         /// to a render texture in non OpenGL platforms. If you are doing a custom Blit pass to copy camera textures
    4.         /// (_CameraColorTexture, _CameraDepthAttachment) you need to check this flag to know if you should flip the
    5.         /// matrix when rendering with for cmd.Draw* and reading from camera textures.
    6.         /// </summary>
    7.         public bool IsCameraProjectionMatrixFlipped()
    8.         {
    9.             // Users only have access to CameraData on URP rendering scope. The current renderer should never be null.
    10.             var renderer = ScriptableRenderer.current;
    11.             Debug.Assert(renderer != null, "IsCameraProjectionMatrixFlipped is being called outside camera rendering scope.");
    12.  
    13.             if (renderer != null)
    14.             {
    15.                 bool renderingToBackBufferTarget = renderer.cameraColorTarget == BuiltinRenderTextureType.CameraTarget;
    16. #if ENABLE_VR && ENABLE_XR_MODULE
    17.                 if (xr.enabled)
    18.                     renderingToBackBufferTarget |= renderer.cameraColorTarget == xr.renderTarget && !xr.renderTargetIsRenderTexture;
    19. #endif
    20.                 bool renderingToTexture = !renderingToBackBufferTarget || targetTexture != null;
    21.                 return SystemInfo.graphicsUVStartsAtTop && renderingToTexture;
    22.             }
    23.  
    24.             return true;
    25.         }
    This is the snippet of code that initializes and creates the textures for my objects:
    Code (CSharp):
    1.     private void OnVisible() {
    2.         enabled = true;
    3.         _visible = true;
    4.         if( initialized == true ) {
    5.             return;
    6.         }
    7.  
    8.         Initialize();
    9.         ...
    10.     }
    Code (CSharp):
    1. public virtual void Initialize() {
    2.         if ( initialized ) {
    3.             return;
    4.         }
    5.  
    6.         CreateCamera();
    7.         CreateMaterials();
    8.         CreateTextures();
    9.         RenderTextures();
    10.         _initialized = true;
    11.     }
    Code (CSharp):
    1.     private void CreateCamera() {
    2.         GameObject cam = GameObject.Find( "PaintCamera" );
    3.         if ( cam != null ) {
    4.             renderCamera = cam.GetComponent<Camera>();
    5.             return;
    6.         }
    7.  
    8.         GameObject rtCameraObject = new GameObject();
    9.         rtCameraObject.name = "PaintCamera";
    10.         rtCameraObject.transform.position = Vector3.zero;
    11.         rtCameraObject.transform.rotation = Quaternion.identity;
    12.         rtCameraObject.transform.localScale = Vector3.one;
    13.         rtCameraObject.hideFlags = HideFlags.HideInHierarchy;
    14.         renderCamera = rtCameraObject.AddComponent<Camera>();
    15.         renderCamera.clearFlags = CameraClearFlags.SolidColor;
    16.         renderCamera.backgroundColor = new Color( 0, 0, 0, 0 );
    17.         renderCamera.orthographic = true;
    18.         renderCamera.nearClipPlane = 0.0f;
    19.         renderCamera.farClipPlane = 1.0f;
    20.         renderCamera.orthographicSize = 1.0f;
    21.         renderCamera.aspect = 1.0f;
    22.         renderCamera.useOcclusionCulling = false;
    23.         renderCamera.enabled = false;
    24.         renderCamera.cullingMask = LayerMask.NameToLayer( "Nothing" );
    25.     }
    26.  
    27.     private void CreateMaterials() {
    28.         if( paintBlitMaterial == null ) {
    29.             paintBlitMaterial = new Material( Shader.Find( "Hidden/PaintBlit" ) );
    30.         }
    31.  
    32.         if( worldPosMaterial == null ) {
    33.             worldPosMaterial = new Material( Shader.Find( "Hidden/PaintPos" ) );
    34.         }
    35.     }
    36.  
    37.     private void CreateTextures() {
    38.         splatTex = PaintManager.Instance.GetSplatTexture( paintTextureSize );
    39.         splatTexAlt = PaintManager.Instance.GetSplatTexture( paintTextureSize );
    40.         worldPosTex = PaintManager.Instance.GetWorldTexture( paintTextureSize );
    41.         worldPosTexTemp = PaintManager.Instance.GetWorldTexture( paintTextureSize );
    42.  
    43.         foreach ( Material mat in paintRenderer.materials ) {
    44.             mat.SetTexture( "_SplatTex", splatTex.GetObject().obj );
    45.             mat.SetTexture( "_WorldPosTex", worldPosTex.GetObject().obj );
    46.             mat.SetVector( "_SplatTexSize", new Vector4( ( int )paintTextureSize, ( int )paintTextureSize, 0, 0 ) );
    47.         }
    48.  
    49.         if ( _fillPaint ) FillPaintStartup();
    50.     }
    51.  
    52.     private void RenderTextures() {
    53.         this.transform.hasChanged = false;
    54.  
    55.         CommandBuffer cb = new CommandBuffer();
    56.  
    57.         cb.SetRenderTarget( worldPosTex.GetObject().obj );
    58.         cb.ClearRenderTarget( true, true, new Color( 0, 0, 0, 0 ) );
    59.         for ( int i = 0; i < paintRenderer.materials.Length; i++ ) {
    60.             cb.DrawRenderer( paintRenderer, worldPosMaterial, i );
    61.         }
    62.  
    63.         // Only have to render the camera once!
    64.         renderCamera.AddCommandBuffer( CameraEvent.AfterEverything, cb );
    65.         renderCamera.Render();
    66.         renderCamera.RemoveAllCommandBuffers();
    67.  
    68.         // Bleed the world position out 2 pixels
    69.         paintBlitMaterial.SetVector( "_SplatTexSize", new Vector2( ( int )paintTextureSize, ( int )paintTextureSize ) );
    70.         Graphics.Blit( worldPosTex.GetObject().obj, worldPosTexTemp.GetObject().obj, paintBlitMaterial, 2 );
    71.         Graphics.Blit( worldPosTexTemp.GetObject().obj, worldPosTex.GetObject().obj, paintBlitMaterial, 2 );
    72.  
    73.     }
    Based on the description of the IsCameraProjectionMatricFlipped method, I can only assume these two lines are the source of the error, but I don't know anything past that.

    Graphics.Blit( worldPosTex.GetObject().obj, worldPosTexTemp.GetObject().obj, paintBlitMaterial, 2 );

    Graphics.Blit( worldPosTexTemp.GetObject().obj, worldPosTex.GetObject().obj, paintBlitMaterial, 2 );


    I also attached a snippet of the editor logs leading up to the crash.

    If anyone needs any extra information, I will be happy to provide it.
     

    Attached Files:

    • Log.txt
      File size:
      22.3 KB
      Views:
      227
    Last edited: Sep 14, 2021
    Magic-Thor likes this.
  2. collinpatrick15

    collinpatrick15

    Joined:
    Nov 7, 2018
    Posts:
    38
    Update

    Given the assertion means the current ScriptableRenderer is null, I decided to check the documentation of the ScriptableRenderer object.

    "Class ScriptableRenderer
    Class ScriptableRenderer implements a rendering strategy. It describes how culling and lighting works and the effects supported.

    A renderer can be used for all cameras or be overridden on a per-camera basis. It will implement light culling and setup and describe a list of ScriptableRenderPass to execute in a frame. The renderer can be extended to support more effect with additional ScriptableRendererFeature. Resources for the renderer are serialized in ScriptableRendererData."

    Based on this, I assume the supposedly null renderer is the one on my cameras, but that value is never null. I'm really scratching my head here.



    I also found another warning that pops up: "XRSystem.ReleaseFrame() was not called!". I find this odd because I am not using VR/XR. I took a look at the code throwing this warning in URP's XRSystem.cs and it seems to be surrounded by these define symbols "#if ENABLE_VR && ENABLE_XR_MODULE". The code is currently greyed out in Visual Studio which means the warning should not even be possible given those symbols are not active.

    I also seem to get this error too:

    Code (CSharp):
    1. InvalidOperationException: Collection was modified; enumeration operation may not execute.
    2. ...
    3. (UnityEngine.Rendering.ScriptableRenderContext context, UnityEngine.Camera baseCamera) (at Library/PackageCache/com.unity.render-pipelines.universal@11.0.0/Runtime/UniversalRenderPipeline.cs:495)
    4. ...
    *Shortened to prevent being flagged for spam moderation.

    And again, as far as I know, I am not using VR/XR in my project. The collection loop throwing this error is surrounded by the same "#if ENABLE_VR && ENABLE_XR_MODULE" define symbols. My only thought is this is these symbols are somehow getting added to the player during run-time. I don't know if there is a relation between this and the other error, but I find it odd nonetheless.
     
    Last edited: Sep 14, 2021
    Magic-Thor likes this.
  3. collinpatrick15

    collinpatrick15

    Joined:
    Nov 7, 2018
    Posts:
    38
    Update:

    After trying a bunch of random things, I stumbled across something that seems to fix the issue. I moved my OnVisible and OnInvisible calls to only run during the Fixed or Late Update cycles. I have no clue why this works since none of this is tied to the physics system, but at least I am no longer getting errors or crashing. If I were to guess, it might be because both of those update loops probably run before or after the rendering loop. If anyone knows why this works, I would love to hear an explanation.
     
    Last edited: Sep 15, 2021
    NewMagic-Studio and Magic-Thor like this.
  4. AhmadKarim

    AhmadKarim

    Joined:
    Aug 17, 2022
    Posts:
    12
    Thanks for this information. For anyone who has the same problem, I created a tutorial video. I took an example of water prefab in Unity Standard Asset (it has same error) and created the process to fix it.