Search Unity

SRP Full Screen Blit Help

Discussion in 'Universal Render Pipeline' started by maxps, Jun 30, 2022.

  1. maxps

    maxps

    Joined:
    May 10, 2018
    Posts:
    2
    Dear Unity community,

    When trying to use CommandBuffer.Blit in Single Pass Instanced VR mode I get this incorrect result


    (Code at bottom of post)
    I have tried all the suggestions in the doc about adding support to the shader for GPU instancing and add the defs to support texture arrays which did not help. I found that calling ScriptableRenderPass.Blit or CommandBuffer.Blit in any way causes the issue, even if it doesn't blit into the CameraTargetColorTarget (back buffer?), for example,

    this.Blit(cmd, m_textureResult.Identifier(), m_texture2Result.Identifier())

    I have since move on to try this tutorial

    How to perform a full screen blit in Single Pass Instanced rendering in XR | Universal RP | 12.1.7 (unity3d.com)

    This leads to more success, however, then doesn't render any objects with Transparent materials.

    Without feature:
    With Feature:


    Using SRP is a new area for me so I apologies for my lack of in-depth knowledge/explanations. Please help me with a solution for simple full screen SRP blitting that works for both VR and NoneVR Single Instanced (Multi View works with first solution already)?

    Thanks!

    Code for first attempt:

    Code (CSharp):
    1. public class FadeSRP : ScriptableRendererFeature
    2. {
    3.     public bool Enabled = false;
    4.  
    5.     [Serializable]
    6.     public class FadeSettings
    7.     {
    8.         public RenderPassEvent renderPassEvent = RenderPassEvent.AfterRenderingTransparents;
    9.         public Material EffectMaterial;
    10.     }
    11.  
    12.     private FadePass m_fadePass;  
    13.     public FadeSettings Settings;
    14.  
    15.     public override void Create()
    16.     {
    17.         if(Settings.EffectMaterial == null)
    18.         {
    19.             Debug.LogWarning("Fade Shader null");
    20.             return;
    21.         }
    22.  
    23.         m_fadePass = new FadePass(Settings.EffectMaterial, Settings.renderPassEvent);
    24.     }
    25.  
    26.     public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    27.     {
    28.         if (renderingData.cameraData.cameraType == CameraType.Game)
    29.         {  
    30.             if (Settings.EffectMaterial != null && Enabled)
    31.             {
    32.                 // Calling ConfigureInput with the ScriptableRenderPassInput.Color argument ensures that the opaque texture is available to the Render Pass
    33.                 m_fadePass.ConfigureInput(ScriptableRenderPassInput.Color);
    34.                 m_fadePass.Setup(renderer.cameraColorTarget);
    35.                 renderer.EnqueuePass(m_fadePass);
    36.             }
    37.         }
    38.     }
    39.  
    40.     public void SetFadeDelta(float delta)
    41.     {
    42.         m_fadePass.SetDelta(delta);
    43.     }
    44. }
    45.  
    Code (CSharp):
    1. public class FadePass : ScriptableRenderPass
    2. {
    3.     private readonly Material m_effectMaterial;
    4.     private RenderTargetIdentifier m_cameraTarget;  
    5.     private const string TagName = "FadePass";
    6.  
    7.     public FadePass(Material effectMaterial, RenderPassEvent renderPassEvent)
    8.     {
    9.         this.renderPassEvent = renderPassEvent;
    10.         m_effectMaterial = effectMaterial;
    11.     }
    12.  
    13.     public void Setup(RenderTargetIdentifier cameraTarget)
    14.     {
    15.         m_cameraTarget = cameraTarget;
    16.     }
    17.  
    18.     public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
    19.     {
    20.         CommandBuffer cmd = CommandBufferPool.Get(TagName);
    21.         cmd.Clear();
    22.  
    23.         this.Blit(cmd, ref renderingData, m_effectMaterial, 0);
    24.  
    25.         context.ExecuteCommandBuffer(cmd);
    26.         CommandBufferPool.Release(cmd);
    27.     }
    28.  
    29.     public void SetDelta(float delta)
    30.     {
    31.         m_effectMaterial.SetFloat("_Delta", delta);
    32.     }
    33. }
    34.  
    35.  
    Code (CSharp):
    1. Shader "SRP/SRPFade"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex("Texture", any) = "" {}
    6.         _Color("Multiplicative color", Color) = (1.0, 1.0, 1.0, 1.0)
    7.         _Delta("Delta", Float) = 0
    8.     }
    9.     SubShader{
    10.         Pass {
    11.             ZTest Always Cull Off ZWrite Off
    12.  
    13.             CGPROGRAM
    14.             #pragma vertex vert
    15.             #pragma fragment frag
    16.             #pragma multi_compile_instancing
    17.             #include "UnityCG.cginc"
    18.  
    19.             UNITY_DECLARE_SCREENSPACE_TEXTURE(_MainTex);
    20.             uniform float4 _MainTex_ST;
    21.             uniform float _Delta;
    22.  
    23.             struct appdata_t {
    24.                 float4 vertex : POSITION;
    25.                 float2 texcoord : TEXCOORD0;
    26.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    27.             };
    28.  
    29.             struct v2f {
    30.                 float4 vertex : SV_POSITION;
    31.                 float2 texcoord : TEXCOORD0;
    32.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    33.                 UNITY_VERTEX_OUTPUT_STEREO
    34.             };
    35.  
    36.             UNITY_INSTANCING_BUFFER_START(Props)
    37.                 UNITY_DEFINE_INSTANCED_PROP(float4, _Color)
    38.             UNITY_INSTANCING_BUFFER_END(Props)
    39.  
    40.             v2f vert(appdata_t v)
    41.             {
    42.                 v2f o;
    43.                 UNITY_SETUP_INSTANCE_ID(v);
    44.                 UNITY_TRANSFER_INSTANCE_ID(v, o);
    45.                 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    46.                 o.vertex = UnityObjectToClipPos(v.vertex);
    47.                 o.texcoord = TRANSFORM_TEX(v.texcoord.xy, _MainTex);
    48.                 return o;
    49.             }
    50.  
    51.             fixed4 frag(v2f i) : SV_Target
    52.             {
    53.                 UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
    54.                 UNITY_SETUP_INSTANCE_ID(i);
    55.                 float4 rawColor = UNITY_SAMPLE_SCREENSPACE_TEXTURE(_MainTex, i.texcoord);
    56.                 return lerp(rawColor, _Color, _Delta);
    57.             }
    58.             ENDCG
    59.  
    60.         }
    61.     }
    62.     Fallback Off
    63. }
    64.  
     
    Last edited: Jun 30, 2022
  2. daneobyrd

    daneobyrd

    Joined:
    Mar 29, 2018
    Posts:
    101
    Look through the ongoing blit forum post for all quests regarding CommandBuffer.Blit
     
  3. maxps

    maxps

    Joined:
    May 10, 2018
    Posts:
    2
    Thanks for the reply @daneobyrd. I had previously done that. However, lacked the knowledge to fully understand everything. However, after much learning and help I know have a working solution!

    A big shout out to Cian Noonan in the Unity Support team for all his help educating me :)

    To summaries what I learned: Blitting in XR is a mixed bag of results in Unity3D 2021. Especially, when using Single Instance Rendering. A warning I recently found on the URP XR blit page:

    "Using cmd.Blit might implicitly enable or disable XR shader keywords, which breaks XR SPI rendering."
    To my best deduction this is because URP is mid way through a transition to the new Blitter.Blit which uses RTHandles rather than RenderTargetIdentifiers in 2021.

    The first part of the solution is to use DrawMesh instead of Blit:

    Code (CSharp):
    1. cmd.SetRenderTarget(new RenderTargetIdentifier(m_cameraColorCopy, 0, CubemapFace.Unknown, -1));
    2. cmd.DrawMesh(RenderingUtils.fullscreenMesh, Matrix4x4.identity, m_copyMaterail);
    The second part was to update my shaders to support texture arrays using TEXTURE2D_X and SAMPLE_TEXTURE2D_X.

    Code (CSharp):
    1. TEXTURE2D_X(_CameraColorCopy);
    2. SAMPLER(sampler_CameraColorCopy);
    3. ...
    4. float4 color = SAMPLE_TEXTURE2D_X(_CameraColorCopy, sampler_CameraColorCopy, input.uv);
    I have attached the 3 complete files for clarity
     

    Attached Files:

    daneobyrd likes this.
  4. daneobyrd

    daneobyrd

    Joined:
    Mar 29, 2018
    Posts:
    101
    That's great news! Yeah, that SAMPLE_TEXTURE2D_X macro eluded me for a while when I first started looking into URP blitting. My situation back then was that I was adapting an HDRP compute shader to work in URP and hadn't noticed the #pragma multi-compile UNITY_TEXTURE2D_X_ARRAY_SUPPORTED which kept giving me errors.

    I hoped they have improved the documentation about those XR macros.
     
  5. 8bitgoose

    8bitgoose

    Joined:
    Dec 28, 2014
    Posts:
    448
    Was anyone able to get this to work with transparent materials as well? I copied the code from the Unity URP 12.1 code but it does not display any transparencies.
     
  6. Sponge2k

    Sponge2k

    Joined:
    Sep 22, 2021
    Posts:
    12
    Thanks for your message, I was also running into trouble.. spent many hours figuring out why it just didn't work. Changing it to opaque immediately makes it appear. I tried a lot with rendering orders and when to call the blit pass, but nothing works so far with transparent.
     
  7. wwWwwwW1

    wwWwwwW1

    Joined:
    Oct 31, 2021
    Posts:
    766
    The "_CameraOpaqueTexture" is copied after opaque objects rendering, so when you use them in a post-processing shader, all transparent objects will not be considered.

    I believe that this texture is designed to be used in transparent shaders or post-processing that happens right after opaque rendering.

    If you want to access scene color in post-processing effects, a better way is to copy the current scene color and then pass it to your shader.
     
  8. 8bitgoose

    8bitgoose

    Joined:
    Dec 28, 2014
    Posts:
    448
    How would I do this? Asking for a friend and not totally for me ;). Any articles would be super helpful. I am good at C# but not at shaders at all.
     
  9. wwWwwwW1

    wwWwwwW1

    Joined:
    Oct 31, 2021
    Posts:
    766
    This can be done in the same custom renderer feature.
    • Create a temporary render texture. (usually use HDR format like B10G11R11)
    • Use blit function to copy the scene color. (blit source is camera."color target", destination is the temporary RT)
    • Now the temporary RT will contain current scene color.
    • Pass this RT to the post-processing material or shader. (can be set material's property / global texture)
    • Execute the post-processing code.
    • Release the temporary RT if needed.

    However, there're some changes to the Blit and Temporary RT parts in different URP versions. (cmd.Blit, Blitter, RTHandle, RenderTargetIdentifier, RT.GetTemporary)

    I am looking forward to any articles or examples too.
     
  10. wwWwwwW1

    wwWwwwW1

    Joined:
    Oct 31, 2021
    Posts:
    766
    I just found that things can be very easy if you use the full screen pass feature in 2022.2.

    The requirements option:
    • Depth: Depth Texture
    • Normal: Normals Texture (like SSAO's)
    • Color: Not Opaque Texture, but a "CopyColor" right before your effect.
    • ...
    FullScreenPass_CopyColorjpg.jpg

    You can also check it in Frame Debugger.
    FrameDebugger_CopyColor.jpg
     
    daneobyrd likes this.
  11. 8bitgoose

    8bitgoose

    Joined:
    Dec 28, 2014
    Posts:
    448
    Thanks so much for the detailed update @wwWwwwW1. I am using XR which had a warning somewhere so I'll have to figure out if this works with XR by Unity. Thanks!
     
    wwWwwwW1 likes this.
  12. wwWwwwW1

    wwWwwwW1

    Joined:
    Oct 31, 2021
    Posts:
    766
    I suggest reporting it as a bug if not, and they should fix this as it's an URP feature.

    What I currently found was that it doesn't support adding multiple features, but I only tested this on 2023.1.a20.
     
  13. 8bitgoose

    8bitgoose

    Joined:
    Dec 28, 2014
    Posts:
    448
  14. wwWwwwW1

    wwWwwwW1

    Joined:
    Oct 31, 2021
    Posts:
    766
    I think the full screen pass (0-code) feature I mentioned in #10 should support XR, because the Blit method is controlled by URP internally.

    By the way, it seems that the Pass Index in the picture doesn't do anything currently, it's always a "Draw Procedure" in Frame Debugger.

    If you would like to write custom renderer features, you can try using Blitter() rather than cmd.Blit().