Downsampling In Render Feature with Cmd.Blit()

Hi guys, I’m currently trying to render a shaderpass as an additive layer through a render feature, and I was looking to find a way to implement downsampling into the code. By downsampling, I can make the shader run much faster, and I think in URP, this is the only way to make that work. Unfortunately, everything I’ve tried so far doesn’t work. Whenever I try to downsample my texture, it just increases its size in the scene and warps it around my screen.

For reference, I want to take the camera color target and create a temporary render texture based off this. This texture is going to be downsized by a certain amount. Then, I will blit the source texture to this new texture with the material pass index of my shader, and then from there, blit the result back to the screen. Unfortunately, it doens’t look like unity does this downsampling/upsampling thing automatically, so whenever I do it, like I said earlier, I get weird zooming in/projection effects. Here are some images for reference:


Also, here is my code:

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

public class DownscaleRenderFeature : ScriptableRendererFeature
{
    class DownscaleRenderPass : ScriptableRenderPass
    {
        private Material drawPathsMaterial;
        private int downscaleAmount;
        private RenderTargetHandle tempTexture;

        public DownscaleRenderPass(Material material, int downscaleAmount)
        {
            this.drawPathsMaterial = material;
            this.downscaleAmount = downscaleAmount;
            tempTexture.Init("_DownscaledTexture");
        }

        public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
        {
            RenderTextureDescriptor descriptor = cameraTextureDescriptor;
            descriptor.width /= downscaleAmount;
            descriptor.height /= downscaleAmount;
            descriptor.colorFormat = RenderTextureFormat.Default;

            // Create a temporary render texture with the downsized dimensions
            cmd.GetTemporaryRT(tempTexture.id, descriptor, FilterMode.Bilinear);
            ConfigureTarget(tempTexture.Identifier());
            ConfigureClear(ClearFlag.All, Color.clear);
        }

        public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
        {
            CommandBuffer cmd = CommandBufferPool.Get("DownscalePass");

            // Run the path drawing shader pass on the downsized texture
            Blit(cmd, renderingData.cameraData.renderer.cameraColorTarget, tempTexture.Identifier(), drawPathsMaterial, 1);

            // Blend the result back into the main camera color buffer
            Blit(cmd, tempTexture.Identifier(), renderingData.cameraData.renderer.cameraColorTarget);

            context.ExecuteCommandBuffer(cmd);
            CommandBufferPool.Release(cmd);
        }

        public override void FrameCleanup(CommandBuffer cmd)
        {
            if (tempTexture != RenderTargetHandle.CameraTarget)
            {
                cmd.ReleaseTemporaryRT(tempTexture.id);
            }
        }
    }

    [System.Serializable]
    public class DownscaleSettings
    {
        public Material drawPathsMaterial = null;
        public int downscaleAmount = 2; // Downscale by a factor of 2 by default
    }

    public DownscaleSettings settings = new DownscaleSettings();
    DownscaleRenderPass downscalePass;

    public override void Create()
    {
        downscalePass = new DownscaleRenderPass(settings.drawPathsMaterial, settings.downscaleAmount)
        {
            renderPassEvent = RenderPassEvent.AfterRenderingTransparents 
        };
    }

    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
        renderer.EnqueuePass(downscalePass);
    }
}

If anyone has had experience with this, or could offer some input, any help would be greatly appreciated :slight_smile: