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

Feedback How to Blit in URP - Documentation Needed

Discussion in 'Universal Render Pipeline' started by daneobyrd, Dec 13, 2021.

  1. BruceKristelijn

    BruceKristelijn

    Joined:
    Apr 28, 2017
    Posts:
    92



    So I think I understand why these issues happen. I am developing for the Quest 2 and enabling opaque texture causes these issues without and renderpass enabled. So maybe if I can find a way to prevent the passes enabling opaque texture it could work but I guess it is a hardware limitation.
     
  2. wwWwwwW1

    wwWwwwW1

    Joined:
    Oct 31, 2021
    Posts:
    631
  3. chentianqin

    chentianqin

    Joined:
    Jan 7, 2021
    Posts:
    3
    If I want to blit from a source renderTexture that is allocated by calling commandBuffer.GetTemporaryRT(), how can I do? It reports error when I call Blitter.BlitCameraTexture()
     
    shotoutgames likes this.
  4. StrangeWays777

    StrangeWays777

    Joined:
    Jul 21, 2018
    Posts:
    29
    I have done as you said but I am getting an error saying ''VolumetricRendering.SetupRenderPasses(ScriptableRenderer, ref RenderingData)': no suitable method found to override'

    There is almost no documentation on this and what I do find is always outdated. Any help would be massively appreciated. Thanks in advance.
     
  5. daneobyrd

    daneobyrd

    Joined:
    Mar 29, 2018
    Posts:
    101
    I ran into this recently, you need to change the RenderingData parameter to `in` instead of `ref`.
     
    StrangeWays777 likes this.
  6. StrangeWays777

    StrangeWays777

    Joined:
    Jul 21, 2018
    Posts:
    29
    Thank you! It worked.

    Still need to figure out why I still keep getting the warning
    'CommandBuffer: temporary render texture not found while executing RenderClouds (SetGlobalTexture)'
    But now I am one step closer!

    SOLVED:
    I had to set the source for the RenderPass which ended up looking like this.

    Code (CSharp):
    1.     public override void SetupRenderPasses(ScriptableRenderer renderer, in RenderingData renderingData)
    2.     {
    3.         if (settings.cloudRenderer == null)
    4.         {
    5.             Debug.LogWarningFormat("Missing Blit Material. {0} blit pass will not execute. Check for missing reference in the assigned renderer.", GetType().Name);
    6.             return;
    7.         }
    8.        
    9.         cloudsPass.source = renderer.cameraColorTargetHandle;
    10.     }
     
    Last edited: Jun 28, 2023
  7. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    848
    I need help with this. All these new methods in URP are utterly confusing.

    I am rendering the scene using a depth only pass, into the color target of the camera, which is a RenderTexture asset of type RFloat. That works. Now, I want the depth to be Linear01, so I thought I would add a Blit to the CommandBuffer in the RendererFeature, but this seems to break the depth rendering. I am not entirely sure what is going on. When I add the Blitter blit, the scene content disappears and it seems like it is also no longer cleared, because whatever I blit into the texture accumulates.

    Any hints are greatly appreciated.


    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Rendering;
    3. using UnityEngine.Rendering.Universal;
    4. using UnityEngine.Rendering.RendererUtils;
    5.  
    6. public class RenderToDepthTextureFeature : ScriptableRendererFeature
    7. {
    8.     public LayerMask layerMask;
    9.     public RenderPassEvent renderPassEvent = RenderPassEvent.BeforeRenderingSkybox;
    10.  
    11.     RenderToDepthTexturePass _scriptablePass;
    12.     Material _fixMaterial;
    13.  
    14.  
    15.     public override void Create()
    16.     {
    17.         _scriptablePass = new RenderToDepthTexturePass( layerMask, _fixMaterial );
    18.         _scriptablePass.renderPassEvent = renderPassEvent;
    19.  
    20.         _fixMaterial = CoreUtils.CreateEngineMaterial( Shader.Find( "Hidden/RenderToDepthTextureFeatureFix" ) );
    21.     }
    22.  
    23.  
    24.     public override void AddRenderPasses( ScriptableRenderer renderer, ref RenderingData renderingData )
    25.     {
    26.         renderer.EnqueuePass( _scriptablePass );
    27.     }
    28.  
    29.  
    30.     public override void SetupRenderPasses( ScriptableRenderer renderer, in RenderingData renderingData )
    31.     {
    32.         if (renderingData.cameraData.cameraType == CameraType.Game)
    33.         {
    34.             // Calling ConfigureInput with the ScriptableRenderPassInput.Color argument
    35.             // ensures that the opaque texture is available to the Render Pass.
    36.             _scriptablePass.ConfigureInput( ScriptableRenderPassInput.Color );
    37.             _scriptablePass.SetTarget( renderer.cameraColorTargetHandle );
    38.         }
    39.     }
    40.  
    41.  
    42.     protected override void Dispose(bool disposing)
    43.     {
    44.         CoreUtils.Destroy( _fixMaterial );
    45.     }
    46.  
    47.  
    48.  
    49.     class RenderToDepthTexturePass : ScriptableRenderPass
    50.     {
    51.         ProfilingSampler _profilingSampler;
    52.         ShaderTagId _depthOnlyId;
    53.  
    54.         LayerMask _layerMask;
    55.         Material _fixMaterial;
    56.  
    57.         RTHandle _colorTargetHandle;
    58.  
    59.  
    60.         public RenderToDepthTexturePass( LayerMask layerMask, Material fixMaterial )
    61.         {
    62.             _layerMask = layerMask;
    63.             _depthOnlyId = new ShaderTagId( "DepthOnly" );
    64.             _profilingSampler = new ProfilingSampler( nameof( RenderToDepthTexturePass ) );
    65.             _fixMaterial = fixMaterial;
    66.         }
    67.  
    68.  
    69.         public void SetTarget( RTHandle colorHandle )
    70.         {
    71.             _colorTargetHandle = colorHandle;
    72.         }
    73.  
    74.  
    75.         public override void OnCameraSetup( CommandBuffer cmd, ref RenderingData renderingData )
    76.         {
    77.             ConfigureTarget( _colorTargetHandle );
    78.         }
    79.  
    80.  
    81.         public override void Execute( ScriptableRenderContext context, ref RenderingData renderingData )
    82.         {
    83.             CommandBuffer cmd = CommandBufferPool.Get();
    84.  
    85.             using( new ProfilingScope( cmd, _profilingSampler ) )
    86.             {
    87.                 RendererListDesc descrp = new RendererListDesc( _depthOnlyId, renderingData.cullResults, renderingData.cameraData.camera );
    88.                 descrp.renderQueueRange = RenderQueueRange.opaque;
    89.                 descrp.layerMask = _layerMask;
    90.                 RendererList rendererList = context.CreateRendererList( descrp );
    91.        
    92.                 // TEST
    93.                 //cmd.SetRenderTarget( _colorTargetHandle );
    94.  
    95.                 cmd.ClearRenderTarget( clearDepth: true, clearColor: true, Color.black );
    96.                 cmd.DrawRendererList( rendererList );
    97.        
    98.                 // TEST
    99.                 //cmd.CopyTexture( renderingData.cameraData.renderer.cameraColorTargetHandle, _colorTargetHandle );
    100.  
    101.                 // By example.https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@16.0/manual/renderer-features/how-to-fullscreen-blit.html
    102.                 // "Do not use the cmd.Blit method in URP XR projects because that method has compatibility issues with the URP XR integration.
    103.                 // Using cmd.Blit might implicitly enable or disable XR shader keywords, which breaks XR SPI rendering."
    104.                 Blitter.BlitCameraTexture( cmd, _colorTargetHandle, _colorTargetHandle, _fixMaterial, pass: 0 );
    105.                 //cmd.Blit( _colorTargetHandle, _colorTargetHandle, _fixMaterial ); // NO NO
    106.             }
    107.  
    108.             context.ExecuteCommandBuffer( cmd );
    109.             cmd.Clear();
    110.  
    111.             CommandBufferPool.Release( cmd );
    112.         }
    113.     }
    114. }

    Code (CSharp):
    1. Shader "Hidden/RenderToDepthTextureFeatureFix"
    2. {
    3.     SubShader
    4.     {
    5.         Tags { "RenderType"="Opaque" "RenderPipeline" = "UniversalPipeline"}
    6.         LOD 100
    7.         ZWrite Off Cull Off
    8.         Pass
    9.         {
    10.             Name "RenderToDepthTextureFeatureFix"
    11.  
    12.             HLSLPROGRAM
    13.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    14.             // The Blit.hlsl file provides the vertex shader (Vert),
    15.             // input structure (Attributes) and output strucutre (Varyings)
    16.             #include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
    17.  
    18.             #pragma vertex Vert
    19.             #pragma fragment frag
    20.  
    21.             TEXTURE2D_X( _CameraOpaqueTexture );
    22.             SAMPLER( sampler_CameraOpaqueTexture );
    23.  
    24.             float frag( Varyings input ) : SV_Target
    25.             {
    26.                 UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX( input );
    27.        
    28.                 float  depth = SAMPLE_TEXTURE2D_X( _CameraOpaqueTexture, sampler_CameraOpaqueTexture, input.texcoord ).r;
    29.        
    30.                 // TODO: Depth to linear.
    31.                 // https://teodutra.com/unity/shaders/urp/graphics/2020/05/18/From-Built-in-to-URP/
    32.                 //depth = Linear01Depth( depth, _ZBufferParams );
    33.  
    34.                 // TEST
    35.                 depth += 0.1;
    36.        
    37.                 return depth;
    38.             }
    39.             ENDHLSL
    40.         }
    41.     }
    42. }
    I can see that both the depth pass and blit pass is operating on the same texture. I really don't get it.

    DepthOnlyPass.png

    BlitFixPass.png

    If I log the name of _colorTarget handle (defined in the RenderToDepthTexturePass class), I see that its called "_CameraColorAttachmentA". But in the FrameDebugger, its called "_CameraColorAttachmentA_640x576_R32_SFloat_Tex2D". Does this have something to do with the issue?

    Also, if I compare renderingData.cameraData.renderer.cameraColorTargetHandle with _colorTargetHandle inside RenderToDepthTexturePass.Execute they are the same! So why should I go through the hassle of parsing in the RTHandle from the RendererFeature to the RenderPass like recommended in the official Blit example?
     
    Last edited: Sep 28, 2023
  8. RebelEggGames

    RebelEggGames

    Joined:
    Dec 12, 2022
    Posts:
    27
    It took me several hours to make it work. Unity docs are outdated and they suck.
    Since docs were useless, forums, google and GPT4 didnt help as well, I had to go over a very complex (but working!) post process someone else made and... what I've found out is that basically in order to avoid render stacking you have to draw the renderers yourself, before blitting.
    I am pretty sure this is not an expected behaviour, post-process should affect only the current frame, not the next one (WTF UNITY?).

    The example I prepared is good enough for my current problem, however bear in mind that you might need to change the input to "DrawRenderers" method, depending on what you want to render and how (e.g: transparent objects).

    I have just finished it, so it is a first solution I've created, so while it solves the main problem (postprocess stacking), I'm pretty sure it can be improved.

    Full code:

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using UnityEngine.Rendering;
    4. using UnityEngine.Rendering.Universal;
    5.  
    6. public class OutlineRendererFeature : ScriptableRendererFeature
    7. {
    8.     [System.Serializable]
    9.     public class OutlineRendererSettings
    10.     {
    11.         public RenderPassEvent Event = RenderPassEvent.AfterRenderingTransparents;
    12.         public RenderQueueRange Range;
    13.         public LayerMask mask;
    14.         public Shader postProcessShader = null;
    15.         public float scale = 1.0f;
    16.     }
    17.  
    18.     public OutlineRendererSettings settings = new OutlineRendererSettings();
    19.  
    20.     private Material material;
    21.     private OutlineRendererPass outlineRendererPass;
    22.  
    23.     public override void Create()
    24.     {
    25.         if (settings.postProcessShader == null)
    26.         {
    27.             Debug.LogError("Missing post-process shader in OutlineRenderer settings.");
    28.             return;
    29.         }
    30.  
    31.         material = CoreUtils.CreateEngineMaterial(settings.postProcessShader);
    32.         outlineRendererPass = new OutlineRendererPass(name, settings.Event, settings.Range, settings.mask, material);
    33.     }
    34.  
    35.     public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    36.     {
    37.         renderer.EnqueuePass(outlineRendererPass);
    38.     }
    39.  
    40.     public override void SetupRenderPasses(ScriptableRenderer renderer, in RenderingData renderingData)
    41.     {
    42.         if (renderingData.cameraData.cameraType == CameraType.Game)
    43.         {
    44.             outlineRendererPass.ConfigureInput(ScriptableRenderPassInput.Color);
    45.             outlineRendererPass.SetTarget(renderer.cameraColorTargetHandle, settings.scale);
    46.         }
    47.     }
    48.  
    49.     protected override void Dispose(bool disposing)
    50.     {
    51.         CoreUtils.Destroy(material);
    52.     }
    53. }
    54.  
    55. class OutlineRendererPass : ScriptableRenderPass
    56. {
    57.     private RTHandle cameraColorTarget;
    58.     private Material postProcessMaterial;
    59.     private float scale;
    60.  
    61.     private FilteringSettings filteringSettings;
    62.     private RenderStateBlock renderStateBlock;
    63.     private ShaderTagId shaderTagId = new ShaderTagId("OutlineRenderer");
    64.     private string profilerTag;
    65.     private ProfilingSampler customProfilingSampler;
    66.  
    67.     public OutlineRendererPass(Material material)
    68.     {
    69.         this.postProcessMaterial = material;
    70.     }
    71.  
    72.     public OutlineRendererPass(string profilerTag, RenderPassEvent renderPassEvent, RenderQueueRange renderQueueRange, LayerMask layerMask, Material material)
    73.     {
    74.         this.profilerTag = profilerTag;
    75.         customProfilingSampler = new ProfilingSampler(profilerTag);
    76.         this.renderPassEvent = renderPassEvent;
    77.         filteringSettings = new FilteringSettings(renderQueueRange, layerMask);
    78.         this.postProcessMaterial = material;
    79.         renderStateBlock = new RenderStateBlock(RenderStateMask.Nothing);
    80.     }
    81.  
    82.     public void SetTarget(RTHandle colorHandle, float scale)
    83.     {
    84.         cameraColorTarget = colorHandle;
    85.         this.scale = scale;
    86.     }
    87.  
    88.     public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
    89.     {
    90.         if (cameraColorTarget == null)
    91.         {
    92.             Debug.LogError("cameraColorTarget is null!");
    93.             return;
    94.         }
    95.         ConfigureTarget(cameraColorTarget);
    96.     }
    97.  
    98.     public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
    99.     {
    100.         if (renderingData.cameraData.camera.cameraType != CameraType.Game)
    101.         {
    102.             return;
    103.         }
    104.  
    105.         if (postProcessMaterial == null)
    106.         {
    107.             Debug.LogError("postProcessMaterial is null! This should never happen.");
    108.             return;
    109.         }
    110.  
    111.         CommandBuffer cmd = CommandBufferPool.Get();
    112.         using (new ProfilingScope(cmd, customProfilingSampler))
    113.         {
    114.             context.ExecuteCommandBuffer(cmd);
    115.             cmd.Clear();
    116.  
    117.             SortingSettings sortingSettings = new SortingSettings(renderingData.cameraData.camera);
    118.             sortingSettings.criteria = SortingCriteria.CommonOpaque;
    119.             DrawingSettings drawSettings = new DrawingSettings(shaderTagId, sortingSettings);
    120.             drawSettings.perObjectData = PerObjectData.None;
    121.  
    122.             context.DrawRenderers(renderingData.cullResults, ref drawSettings, ref filteringSettings, ref renderStateBlock);
    123.  
    124.             postProcessMaterial.SetFloat("_Scale", scale);
    125.             Blitter.BlitCameraTexture(cmd, cameraColorTarget, cameraColorTarget, postProcessMaterial, 0);
    126.         }
    127.         context.ExecuteCommandBuffer(cmd);
    128.         cmd.Clear();
    129.  
    130.         CommandBufferPool.Release(cmd);
    131.     }
    132. }
    133.  
    <shameless-self-promotion>
    If this helps & you want to thank me -> go buy my game on Steam & send me feedback!
    </shameless-self-promotion>

    Good luck! :D
     
    Last edited: Oct 5, 2023
    nasos_333, cecarlsen and thelebaron like this.
  9. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,662
    Working on URP blitting for my assets, and just have to say this is an absolute clusterfuck.

    Lack of/incorrect/outdated documentation, no clear gold standard to follow, and lots of boilerplate code required even for the simplest post process effect.

    Hooray SRPs.
     
    RebelEggGames likes this.
  10. RebelEggGames

    RebelEggGames

    Joined:
    Dec 12, 2022
    Posts:
    27
    I feel you man, working with URP is a nightmare, if you want to create some post process effects...
    Also, lack of grab pass is just... uhh, you need to do 2 seperate post processes to work around this problem...
     
  11. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,662
    It's not just that things are extremely lacking compared to the built-in pipeline, it's the huge amount of time wasted on the simplest of things. I just spent an entire day debugging trough a custom renderer feature, only to realize that Blitter.BlitCameraTexture passes the input texture to the shader as "_BlitTexture" instead of "_MainTex". Furthermore, it is necessary to use a specific vertex shader for this method to work at all.

    Does this follow Unity's own conventions? no. Was it a necessary naming change? probably not. Is it mentioned in the method's documentation? nope. Had to use the frame debugger to figure out where the problem was, then wade trough URP's source code to get an answer.

    At this point I've spent more time reverse-engineering Unity's SRPs than working on my own stuff... it's nerve-wracking. Sorry for the rant.
     
    Last edited: Oct 31, 2023 at 9:00 AM
    nasos_333 likes this.
  12. nasos_333

    nasos_333

    Joined:
    Feb 13, 2013
    Posts:
    12,894
    So pretty much they broke everything that they could in this new changes.

    This is just so unbelievable.

    I tried to replace based on the above and just nothing works, i get multiple errors no matter what i do.

    The whole thing looks broken.
     
    Last edited: Nov 1, 2023 at 5:01 AM