Render Graph issues for apply material to the camera color texture

I have custom effect for camera, that makes blur effect and splitting the screen (by offsetting it). So, I implemented custom render feature using Render Graph, but it doesn’t work. Can you say what’s wrong here?

Shader Code:

Shader "Custom/DamageEffect"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _BlurAmount ("Blur Amount", Range(0, 1)) = 0
        _DoubleVisionAmount ("Double Vision Amount", Range(0, 1)) = 0
        _Offset ("Offset", Vector) = (0, 0, 0, 0)
    }
    SubShader
    {
        Tags
        {
            "RenderType"="Opaque"
        }
        Pass
        {
            ZTest Always Cull Off ZWrite Off

            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

            sampler2D _MainTex;
            float4    _MainTex_TexelSize;
            float     _BlurAmount;
            float     _DoubleVisionAmount;
            float4    _Offset;

            struct Attributes {
                float4 positionOS : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct Varyings {
                float4 positionHCS : SV_POSITION;
                float2 uv : TEXCOORD0;
            };

            Varyings vert(Attributes v)
            {
                Varyings o;
                o.positionHCS = TransformObjectToHClip(v.positionOS);
                o.uv = v.uv;
                return o;
            }

            float4 frag(Varyings i) : SV_Target
            {
                float2 uv = i.uv;

                // Apply double vision effect
                float2 offsetUV = uv + _Offset.xy * _DoubleVisionAmount;
                float4 color = tex2D(_MainTex, uv);
                float4 offsetColor = tex2D(_MainTex, offsetUV);
                color = lerp(color, offsetColor, _DoubleVisionAmount);

                // Apply blur effect
                if(_BlurAmount > 0)
                {
                    float2 texelSize = _MainTex_TexelSize.xy;
                    float4 blurColor = float4(0, 0, 0, 0);

                    blurColor += tex2D(_MainTex, uv + texelSize * float2(-1, -1));
                    blurColor += tex2D(_MainTex, uv + texelSize * float2(0, -1));
                    blurColor += tex2D(_MainTex, uv + texelSize * float2(1, -1));

                    blurColor += tex2D(_MainTex, uv + texelSize * float2(-1, 0));
                    blurColor += tex2D(_MainTex, uv);
                    blurColor += tex2D(_MainTex, uv + texelSize * float2(1, 0));

                    blurColor += tex2D(_MainTex, uv + texelSize * float2(-1, 1));
                    blurColor += tex2D(_MainTex, uv + texelSize * float2(0, 1));
                    blurColor += tex2D(_MainTex, uv + texelSize * float2(1, 1));

                    blurColor /= 9;

                    color = lerp(color, blurColor, _BlurAmount);
                }

                return color;
            }
            ENDHLSL
        }
    }
}

Render Feature Code:

using System;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.RenderGraphModule;
using UnityEngine.Rendering.RenderGraphModule.Util;
using UnityEngine.Rendering.Universal;

public sealed class DamageEffectRendererFeature : ScriptableRendererFeature
{
    private sealed class DamageEffectRenderPass : ScriptableRenderPass
    {
        private const string PassName = "Damage Effect";

        private readonly Material _damageEffectMaterial;

        public DamageEffectRenderPass(Material material)
        {
            _damageEffectMaterial = material;
            requiresIntermediateTexture = true;
        }

        public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
        {
#if UNITY_EDITOR
            if (_damageEffectMaterial == null)
            {
                throw new NullReferenceException($"Missing material: {nameof(_damageEffectMaterial)}");
            }
#endif

            var resourceData = frameData.Get<UniversalResourceData>();

            var sourceTexture = resourceData.activeColorTexture;

            var destinationDescriptor = renderGraph.GetTextureDesc(sourceTexture);
            destinationDescriptor.name = $"CameraColor-{PassName}";
            destinationDescriptor.clearBuffer = false;
            destinationDescriptor.depthBufferBits = DepthBits.None;
            destinationDescriptor.filterMode = FilterMode.Bilinear;

            var destinationTexture = renderGraph.CreateTexture(destinationDescriptor);

            var pass = new RenderGraphUtils.BlitMaterialParameters(sourceTexture, destinationTexture, _damageEffectMaterial, default(int));
            renderGraph.AddBlitPass(pass, passName);

            resourceData.cameraColor = destinationTexture;
        }
    }

    [SerializeField] private RenderPassEvent renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing;
    [SerializeField] private Material damageEffectMaterial;

    private DamageEffectRenderPass _renderPass;

    public override void Create()
    {
        _renderPass = new DamageEffectRenderPass(damageEffectMaterial)
        {
            renderPassEvent = renderPassEvent,
        };
    }

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

Hey, can you check BlitMaterialParameters and AddBlitPass APIs regarding texture sampling? I haven’t had time to dig into it but I think your shader is incorrect, we use _BlitTexture texture property by default. I re-used the basic shader of the URP RG Sample named BlitAndSwapColorRendererFeature.cs and it worked with your custom feature C# code.

Let me know how it goes, thanks

Adrien

1 Like

I will try it and send an update about it.

Thanks for your hard work!

2 Likes