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. Dismiss Notice

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:
    449
    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:
    631
    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:
    449
    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:
    631
    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:
    631
    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:
    449
    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:
    631
    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:
    449
  14. wwWwwwW1

    wwWwwwW1

    Joined:
    Oct 31, 2021
    Posts:
    631
    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().