Search Unity

A little guidance needed (Custom Pass, RTHandle)

Discussion in 'High Definition Render Pipeline' started by DuvE, May 10, 2021.

  1. DuvE

    DuvE

    Joined:
    May 22, 2016
    Posts:
    169
    Hi,

    I want to create kinda moving painterly image effects, and I'm not sure how to implement it. The idea was to create full-screen ImageEffects/CustomPass, get the Camera colors, blur them, apply a simple painterly effect (Floor(Color*10)/10), and on top of all this ass some kind of liquid effects using Custom Render Texture (Simulation shaders, something like this https://www.shadertoy.com/view/MssyDr). I need to get this Color texture/buffer for blurring and simulation liquid in low resolution, of course, but I'm don't know how to do this.

    Currently, I'm trying to adapt the Blur Sample from Custom Pass Samples https://github.com/alelievr/HDRP-Custom-Passes and I have one issue. I need to somehow save the RTHandle as a regular RenderTexture, so I can send it to a material I use in CustomRenderTexture for simulation. I tried to send RTHandle directly to the material, but no luck, when applied to a CustomRenderTexture, it becomes white.

    Is it even possible to save RTHandle as a regular RenderTexture in the folder? Or send it to material without exposure and other stuff.
     
  2. Egad_McDad

    Egad_McDad

    Joined:
    Feb 5, 2020
    Posts:
    39
    I would suggest the use of a custom post process instead of a custom pass.

    Its been a while since I wrote it but I made a fullscreen effect that required a custom buffer. It was with the 9.0.0 version of the package so I can't say if anything has changed, but this advice should still be relevant. With a custom post process you can work just with RTHandle, no need for the render textures. The docs have a sample show how to render using a given material. You could set the destination RTHandle to your desired target in the Render function.

    Edit: Took a look at those files and I found I also used CustomPass for something similar. In that case you also don't use render texture but rather set the render target to the RTHandle
     
    Last edited: May 10, 2021
    DuvE likes this.
  3. DuvE

    DuvE

    Joined:
    May 22, 2016
    Posts:
    169
    Thx, I understand that if you using Custom Pass, it is better to use RTHandle for all, but I can't see how it can act like CustomRenderTexture, I can't apply a material to a texture with double buffer. So I still need CustomRenderTexture for the simulation.

    If using CustomPostProcessing, is it possible to save the SceneTexture each time to a render texture at half resolution? And this output texture should be without this Post Effect applied to it. In Custom Pass this is easy because you have an injection point and the ColorBuffer at this moment will still be the same, even if you modifying it after.

    I just need a method to save or send the whole Scene texture (Camera color buffer) into a material at half resolution. If I use regular SetTexture inside CustomPass script, I'm getting this error:

    Error assigning 2DArray texture to 2D texture property '_Tex': Dimensions must match

    Probably I should somehow convert RTHandle to a regular texture.



    PS: When using CustomPassUtils.Copy(ctx, source, targetBuffer) I can't just put RenderTexture as a targetBuffer, it requires only RTHandle, unfortunately.
     
  4. antoinel_unity

    antoinel_unity

    Unity Technologies

    Joined:
    Jan 7, 2019
    Posts:
    265
    Hello,

    Yes, it's possible but more complicated than doing it in custom passes (there is no utility function for this case).

    That's because we only use Texture2DArrays in HDRP for the frame buffers (to support VR), so when you copy the texture you need to specify the slices in the function calls.

    I have this example pass that does exactly what you want:

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Rendering;
    3. using UnityEngine.Rendering.HighDefinition;
    4. public class BackupFrameBufferPass : CustomPass
    5. {
    6.     [Header("Output")]
    7.     public RenderTexture outputRenderTexture;
    8.     protected override bool executeInSceneView => true;
    9.     protected override void Execute(CustomPassContext ctx)
    10.     {
    11.         if(outputRenderTexture != null)
    12.         {
    13.             var scale = RTHandles.rtHandleProperties.rtHandleScale;
    14.             ctx.cmd.Blit(ctx.cameraColorBuffer, outputRenderTexture, new Vector2(scale.x, scale.y), Vector2.zero, 0, 0);
    15.         }
    16.     }
    17.     protected override void Cleanup()
    18.     {
    19.         base.Cleanup();
    20.     }
    21. }
    Note the two last parameters of Blit() that are used to set the target and source slices, without that it doesn't work.

    FYI, you can create a RTHandle from a RenderTexture with this overload of RTHandleSystem.Alloc(): https://docs.unity3d.com/Packages/c...HandleSystem_Alloc_UnityEngine_RenderTexture_

    But there was a scaling issue when using an RTHandle created from a RenerTexture and the CustomPassUtils.Copy function that we fixed in HDRP 10.5, so if you want to use it, make sure to update HDRP.
     
    _geo__, Egad_McDad and DuvE like this.
  5. DuvE

    DuvE

    Joined:
    May 22, 2016
    Posts:
    169
    Thank you, this is exactly what I wanted. I don't see the downscale or mip parameter of the blit function, is it ok if I just set the CustomRenderTexture to lower resolution manually, right?
     
  6. antoinel_unity

    antoinel_unity

    Unity Technologies

    Joined:
    Jan 7, 2019
    Posts:
    265
    Yes, it should work as the downscale will be done in the blit (with bilinear filter)