NullTale / PixelationFx

⬜ Pixelation post effect for Unity Urp
MIT License
73 stars 2 forks source link

RenderGraph support Request #1

Open AcidicVoid opened 1 month ago

AcidicVoid commented 1 month ago

How to replicate:

  1. Add PixelationFx to Universal Renderer Data
  2. Create Volume, shouldn't matter if global or local
  3. Add a Volume Profile
  4. Add PixelationFx to the Volume Profile and
  5. Have a corresponding camera inside the volume, so the effect should be rendered

Problem:

The effect won't render, Unity shows the following warning:

The render pass VolFx.Pixelation+PassExecution does not have an implementation of the RecordRenderGraph method. Please implement this method, or consider turning on Compatibility Mode (RenderGraph disabled) in the menu Edit > Project Settings > Graphics > URP. Otherwise the render pass will have no effect. For more information, refer to https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@latest/index.html?subfolder=/manual/customizing-urp.html. UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&) I don't want to turn on compatibility mode for various project-specific reasons.

NullTale commented 1 month ago

Emm, i'm do not support render graph

AcidicVoid commented 1 month ago

Oops.

Well, I've updated Pixelation.cs with the RenderGraph method to see if this fixes the issue. Notice that this not well done, just a quickly made "dummy" implementation to prevent the, no precompiler commands added.

The effect still doesn't work. Any ideas what I could have missed?

Maybe it will help someone in the future.

Pixelation.cs:

#if !VOL_FX

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.RenderGraphModule;
using UnityEngine.Rendering.Universal;

//  Pixelation © NullTale - https://twitter.com/NullTale/
namespace VolFx
{
    public class Pixelation : ScriptableRendererFeature
    {
        protected static List<ShaderTagId> k_ShaderTags;

        public static int s_BlitTexId       = Shader.PropertyToID("_BlitTexture");
        public static int s_BlitScaleBiasId = Shader.PropertyToID("_BlitScaleBias");

        [Tooltip("When to execute")]
        public RenderPassEvent _event  = RenderPassEvent.BeforeRenderingPostProcessing;

        public PixelationPass _pass;

        [HideInInspector]
        public Shader _blitShader;

        [NonSerialized]
        public Material _blit;

        [NonSerialized]
        public PassExecution _execution;

        // =======================================================================
        public class PassExecution : ScriptableRenderPass
        {
            public  Pixelation   _owner;
            private RenderTarget _output;

            // =======================================================================
            public void Init()
            {
                renderPassEvent = _owner._event;

                _output = new RenderTarget().Allocate(_owner.name);
            }

            public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
            {
                string passName = "Copy To Debug Texture";
                using (var builder = renderGraph.AddRasterRenderPass<ContextContainer>(passName,
                    out var passData))
                {
                    UniversalResourceData resourceData = frameData.Get<UniversalResourceData>();

                    UniversalCameraData cameraData = frameData.Get<UniversalCameraData>();
                    RenderTextureDescriptor desc = cameraData.cameraTargetDescriptor;
                    desc.msaaSamples = 1;
                    desc.depthBufferBits = 0;

                    TextureHandle destination =
                        UniversalRenderer.CreateRenderGraphTexture(renderGraph, desc,
                            "CopyTexture", false);
                }
            }

            [Obsolete("Deprecated")]
            public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
            {
                _owner._pass.Validate();
                if (_owner._pass.IsActive == false)
                    return;

                // allocate stuff
                var cmd = CommandBufferPool.Get(_owner.name);
                ref var cameraData = ref renderingData.cameraData;
                ref var desc = ref cameraData.cameraTargetDescriptor;
                _output.Get(cmd, in desc);

                var source = _getCameraTex(ref renderingData);

                // draw post process chain
                _owner._pass.Invoke(cmd, source, _output.Handle, context, ref renderingData);
                _owner.Blit(cmd, _output.Handle, source);

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

                // -----------------------------------------------------------------------
                RTHandle _getCameraTex(ref RenderingData renderingData)
                {
                    ref var cameraData = ref renderingData.cameraData;
#if UNITY_2022_1_OR_NEWER
                    return cameraData.renderer.cameraColorTargetHandle;
#else
                    return RTHandles.Alloc(cameraData.renderer.cameraColorTarget);
#endif
                }
            }

            public override void FrameCleanup(CommandBuffer cmd)
            {
                _output.Release(cmd);
                _output.Release(cmd);
                _owner._pass.Cleanup(cmd);
            }
        }

        // =======================================================================
        public void Blit(CommandBuffer cmd, RTHandle source, RTHandle destination)
        {
            cmd.SetGlobalVector(s_BlitScaleBiasId, new Vector4(1, 1, 0));
            cmd.SetGlobalTexture(s_BlitTexId, source);
            cmd.SetRenderTarget(destination, 0);
            cmd.DrawMesh(Utils.FullscreenMesh, Matrix4x4.identity, _blit, 0, 0);
        }

        public override void Create()
        {
#if UNITY_EDITOR
            _blitShader = Shader.Find("Hidden/Universal Render Pipeline/Blit");

            UnityEditor.EditorUtility.SetDirty(this);
#endif
            _blit      = new Material(_blitShader);
            _execution = new PassExecution() { _owner = this };
            _execution.Init();

            if (_pass != null)
                _pass._init();

            if (k_ShaderTags == null)
            {
                k_ShaderTags = new List<ShaderTagId>(new[]
                {
                    new ShaderTagId("SRPDefaultUnlit"),
                    new ShaderTagId("UniversalForward"),
                    new ShaderTagId("UniversalForwardOnly")
                });
            }
        }

        private void Reset()
        {
#if UNITY_EDITOR
            if (_pass != null)
            {
                UnityEditor.AssetDatabase.RemoveObjectFromAsset(_pass);
                UnityEditor.AssetDatabase.SaveAssets();
                _pass = null;
            }
#endif
        }

        public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
        {
            if (renderingData.cameraData.cameraType != CameraType.Game)
                return;
#if UNITY_EDITOR
            if (_blit == null)
                _blit = new Material(_blitShader);

            if (_pass == null)
                return;
#endif
            renderer.EnqueuePass(_execution);
        }

        private void OnDestroy()
        {
#if UNITY_EDITOR
            if (_pass != null)
            {
                UnityEditor.AssetDatabase.RemoveObjectFromAsset(_pass);
                UnityEditor.AssetDatabase.SaveAssets();
                _pass = null;
            }
#endif
        }
    }
}
#endif