Applying post processing effect after UI ignores linear color space

Hello girls and boys!

I found a way to apply a post processing effect after the screenspace-overlay ui, which made me pretty proud. Here is the somewhat hackish code:

// --------------------------------------------------------------------------------------------------------------------
// <copyright file="PostProcessCompleteImage.cs" company="Supyrb">
//   Copyright (c) 2017 Supyrb. All rights reserved.
// </copyright>
// <author>
//   Johannes Deml
//   send@johannesdeml.com
// </author>
// --------------------------------------------------------------------------------------------------------------------

using System;
using System.Collections;
using UnityEngine;

namespace Supyrb
{
    [ExecuteInEditMode]
    [RequireComponent(typeof(Camera))]
    public class PostProcessCompleteImage : MonoBehaviour
    {
        [SerializeField]
        private RenderTextureReadWrite renderTextureReadWrite = RenderTextureReadWrite.Linear;

        [SerializeField]
        private RenderTextureFormat renderTextureFormat = RenderTextureFormat.DefaultHDR;

        [SerializeField]
        private Camera cam = null;

        private RenderTexture tempRt;
        private WaitForEndOfFrame waitForEndOfFrame;
        private bool running;

        void Awake()
        {
            waitForEndOfFrame = new WaitForEndOfFrame();
        }

        void OnEnable()
        {
            running = true;
            StartCoroutine(ApplyEffectAtEndOfFrame());
        }

        void OnDisable()
        {
            running = false;
            StopAllCoroutines();
        }

        void OnPreRender()
        {
            tempRt = RenderTexture.GetTemporary(Screen.width, Screen.height, 24, renderTextureFormat, renderTextureReadWrite);
            cam.targetTexture = tempRt;
        }

        private IEnumerator ApplyEffectAtEndOfFrame()
        {
            while (running)
            {
                yield return waitForEndOfFrame;

                cam.targetTexture = null; //null means framebuffer
                Graphics.Blit(tempRt, null as RenderTexture);
                RenderTexture.ReleaseTemporary(tempRt);
            }
        }


#if UNITY_EDITOR

        void Reset()
        {
            if (cam == null)
            {
                cam = GetComponent<Camera>();
            }
        }

#endif
    }
}

Sadly I found a problem: When using linear color space + UI the color will be quite dark:
Without effect:


With effect:

This does not happen when using gamma color space and also when not using any ui. Is there anything I can change to make the effect work? And is it a really bad idea to run an image effect after WaitForEndOfFrame or is that kind of okay? Feels like a bad idea, but somehow works.
If that is not possible that way, should I take a look at the ScriptableRenderLoop? Or are there any other possibilities? :slight_smile:

I dont understand why is there this song and dance with coroutine and separate render texture? You dont need that. As far as other possibilties go, you can try command buffers.

Thanks for the answer! I never used command buffers before and I wanted to see if it is possible to apply an effect similar to OnRenderImage.

Anyways, that’s good to know. I thought I might have to try the ScriptableRenderLoop, which I really don’t want to do. I will take a look at command buffers :slight_smile: