A little guidance needed (Custom Pass, RTHandle)

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 Shader - Shadertoy BETA). 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 GitHub - alelievr/HDRP-Custom-Passes: A bunch of custom passes made for HDRP 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.

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

1 Like

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.

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:

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
public class BackupFrameBufferPass : CustomPass
{
    [Header("Output")]
    public RenderTexture outputRenderTexture;
    protected override bool executeInSceneView => true;
    protected override void Execute(CustomPassContext ctx)
    {
        if(outputRenderTexture != null)
        {
            var scale = RTHandles.rtHandleProperties.rtHandleScale;
            ctx.cmd.Blit(ctx.cameraColorBuffer, outputRenderTexture, new Vector2(scale.x, scale.y), Vector2.zero, 0, 0);
        }
    }
    protected override void Cleanup()
    {
        base.Cleanup();
    }
}

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/com.unity.render-pipelines.core@10.5/api/UnityEngine.Rendering.RTHandleSystem.html#UnityEngine_Rendering_RTHandleSystem_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.

3 Likes

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?

Yes, it should work as the downscale will be done in the blit (with bilinear filter)