Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

Resolved Shadergraph Materials and Custom Render Features in VR/XR

Discussion in 'Universal Render Pipeline' started by Jonathan_L, Jan 17, 2022.

  1. Jonathan_L

    Jonathan_L

    Joined:
    Jan 26, 2016
    Posts:
    38
    Is there support/documentation for using custom render features with shadergraph materials in VR/XR? Is this supported?

    I've been following this tutorial here:
    https://docs.unity3d.com/Packages/c...eatures/how-to-fullscreen-blit-in-xr-spi.html
    It's slightly out of date, but I've made the modifications to bring it up-to-date.

    Now I tried to drop a shadegraph material instead and I was getting a weird blue square in the middle of the screen. Then I messed around with the unlit shadergraph settings and I got the right color but the square was still there. Then I found a post where somebody used the line:
    cmd.SetViewProjectionMatrices(Matrix4x4.identity, Matrix4x4.identity);
    and that seemed to solve the problem, because now it looks like it wraps around the whole screen. (See first image below).

    However, when I enter VR, the effect seems to be applied on some plane in world space instead of over the whole screen. (see second image). I tried to use the stereo view and projection matrices as well but not much changed. Does anybody have an idea on what might be going on here? I put the source of my render pass on the bottom of the page.

    By the way this is on Unity 2022, URP 14.

    Game view in editor (before play)
    upload_2022-1-17_1-1-23.png

    Game view during play mode. Effect is applied in world space...
    upload_2022-1-17_1-0-17.png

    Code (CSharp):
    1. internal class CameraBlitPass : ScriptableRenderPass
    2. {
    3.  
    4.     private Material material;
    5.     private int shaderPass;
    6.     private Target target;
    7.     private string targetTextureId;
    8.  
    9.     // For profiling code underneath scope
    10.     private ProfilingSampler sampler;
    11.  
    12.     private RTHandle cameraColorRT;
    13.     private RTHandle cameraDepthRT;
    14.  
    15.     private RTHandle temporaryRT;
    16.  
    17.     public CameraBlitPass(Material material, int pass, Target target, string textureId, string tag)
    18.     {
    19.         this.material = material;
    20.         shaderPass = pass;
    21.         this.target = target;
    22.         targetTextureId = textureId;
    23.         sampler = new ProfilingSampler(tag);
    24.     }
    25.  
    26.     public void Setup(RTHandle color = null, RTHandle depth = null)
    27.     {
    28.         cameraColorRT = color;
    29.         cameraDepthRT = depth;
    30.     }
    31.  
    32.     // This method is called before executing the render pass.
    33.     // It can be used to configure render targets and their clear state. Also to create temporary render target textures.
    34.     // When empty this render pass will render to the active camera render target.
    35.     // You should never call CommandBuffer.SetRenderTarget. Instead call <c>ConfigureTarget</c> and <c>ConfigureClear</c>.
    36.     // The render pipeline will ensure target setup and clearing happens in a performant manner.
    37.     public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
    38.     {
    39.         if (target == Target.Color)
    40.         {
    41.             ConfigureTarget(cameraColorRT);
    42.         }
    43.         if (target == Target.Texture)
    44.         {
    45.             temporaryRT = RTHandles.Alloc(Vector2.one, depthBufferBits: DepthBits.Depth32, dimension: TextureDimension.Tex2D, name: targetTextureId);
    46.             ConfigureTarget(temporaryRT);
    47.         }
    48.     }
    49.  
    50.     // Here you can implement the rendering logic.
    51.     // Use <c>ScriptableRenderContext</c> to issue drawing commands or execute command buffers
    52.     // https://docs.unity3d.com/ScriptReference/Rendering.ScriptableRenderContext.html
    53.     // You don't have to call ScriptableRenderContext.submit, the render pipeline will call it at specific points in the pipeline.
    54.     public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
    55.     {
    56.         CommandBuffer cmd = CommandBufferPool.Get();
    57.  
    58.         if (target == Target.Color)
    59.         {
    60.             Camera camera = renderingData.cameraData.camera;
    61.             if (camera.cameraType != CameraType.Game)
    62.             {
    63.                 return;
    64.             }
    65.         }
    66.  
    67.         using (new ProfilingScope(cmd, sampler))
    68.         {
    69.            
    70.             // This is to set the fullscreen rect mesh to render across the whole screen, and not in world space
    71.             Matrix4x4 viewMatrix = Matrix4x4.identity;
    72.             Matrix4x4 projectionMatrix = Matrix4x4.identity;
    73.             // viewMatrix = Camera.main.GetStereoViewMatrix(Camera.StereoscopicEye.Left);
    74.             // projectionMatrix = Camera.main.GetStereoNonJitteredProjectionMatrix(Camera.StereoscopicEye.Left);
    75.             cmd.SetViewProjectionMatrices(viewMatrix, projectionMatrix);
    76.  
    77.             // The RenderingUtils.fullscreenMesh argument specifies that the mesh to draw is a quad.
    78.             cmd.DrawMesh(RenderingUtils.fullscreenMesh, Matrix4x4.identity, material, 0, shaderPass);
    79.         }
    80.  
    81.         context.ExecuteCommandBuffer(cmd);
    82.         cmd.Clear();
    83.  
    84.         CommandBufferPool.Release(cmd);
    85.     }
    86.  
    87.     // Cleanup any allocated resources that were created during the execution of this render pass.
    88.     public override void OnCameraCleanup(CommandBuffer cmd)
    89.     {
    90.         if (temporaryRT != null)
    91.         {
    92.             RTHandles.Release(temporaryRT);
    93.             temporaryRT = null;
    94.         }
    95.     }
    96. }
     
  2. Jonathan_L

    Jonathan_L

    Joined:
    Jan 26, 2016
    Posts:
    38
    For anybody who has a similar issue, I resolved it by trying to render the mesh in front of the camera. Not the best fix, but it works enough for me.

    Code (CSharp):
    1. private Matrix4x4 GetNearClipWorldTransform(Camera camera)
    2. {
    3.     // Attempts to transform fullscreenMesh to world coordinates past camera near plane
    4.     Matrix4x4 localToWorld = camera.transform.localToWorldMatrix;
    5.     Matrix4x4 pushPassNear = Matrix4x4.Translate(new Vector3(0, 0, camera.nearClipPlane * 2));
    6.     return localToWorld * pushPassNear;
    7. }
    And changed the drawing call to:
    Code (CSharp):
    1. Matrix4x4 nearClipWorldTransform = GetNearClipWorldTransform(camera);
    2. cmd.SetViewProjectionMatrices(Matrix4x4.identity, Matrix4x4.identity);
    3. cmd.DrawMesh(RenderingUtils.fullscreenMesh, nearClipWorldTransform, material, 0, shaderPass);
     
  3. nostraverse

    nostraverse

    Joined:
    Mar 3, 2021
    Posts:
    7
    Is there a way to fix this properly? I'm having the same problem with post processing effects in VR
     
    Fenther likes this.