Search Unity

Applying post processing effect after UI ignores linear color space

Discussion in 'Image Effects' started by Johannski, Oct 16, 2017.

  1. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    826
    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:
    Code (CSharp):
    1. // --------------------------------------------------------------------------------------------------------------------
    2. // <copyright file="PostProcessCompleteImage.cs" company="Supyrb">
    3. //   Copyright (c) 2017 Supyrb. All rights reserved.
    4. // </copyright>
    5. // <author>
    6. //   Johannes Deml
    7. //   send@johannesdeml.com
    8. // </author>
    9. // --------------------------------------------------------------------------------------------------------------------
    10.  
    11. using System;
    12. using System.Collections;
    13. using UnityEngine;
    14.  
    15. namespace Supyrb
    16. {
    17.     [ExecuteInEditMode]
    18.     [RequireComponent(typeof(Camera))]
    19.     public class PostProcessCompleteImage : MonoBehaviour
    20.     {
    21.         [SerializeField]
    22.         private RenderTextureReadWrite renderTextureReadWrite = RenderTextureReadWrite.Linear;
    23.  
    24.         [SerializeField]
    25.         private RenderTextureFormat renderTextureFormat = RenderTextureFormat.DefaultHDR;
    26.  
    27.         [SerializeField]
    28.         private Camera cam = null;
    29.  
    30.         private RenderTexture tempRt;
    31.         private WaitForEndOfFrame waitForEndOfFrame;
    32.         private bool running;
    33.  
    34.         void Awake()
    35.         {
    36.             waitForEndOfFrame = new WaitForEndOfFrame();
    37.         }
    38.  
    39.         void OnEnable()
    40.         {
    41.             running = true;
    42.             StartCoroutine(ApplyEffectAtEndOfFrame());
    43.         }
    44.  
    45.         void OnDisable()
    46.         {
    47.             running = false;
    48.             StopAllCoroutines();
    49.         }
    50.  
    51.         void OnPreRender()
    52.         {
    53.             tempRt = RenderTexture.GetTemporary(Screen.width, Screen.height, 24, renderTextureFormat, renderTextureReadWrite);
    54.             cam.targetTexture = tempRt;
    55.         }
    56.  
    57.         private IEnumerator ApplyEffectAtEndOfFrame()
    58.         {
    59.             while (running)
    60.             {
    61.                 yield return waitForEndOfFrame;
    62.  
    63.                 cam.targetTexture = null; //null means framebuffer
    64.                 Graphics.Blit(tempRt, null as RenderTexture);
    65.                 RenderTexture.ReleaseTemporary(tempRt);
    66.             }
    67.         }
    68.  
    69.  
    70. #if UNITY_EDITOR
    71.  
    72.         void Reset()
    73.         {
    74.             if (cam == null)
    75.             {
    76.                 cam = GetComponent<Camera>();
    77.             }
    78.         }
    79.  
    80. #endif
    81.     }
    82. }
    Sadly I found a problem: When using linear color space + UI the color will be quite dark:
    Without effect:
    upload_2017-10-16_22-5-58.png
    With effect:
    upload_2017-10-16_22-5-33.png

    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? :)
     
  2. customphase

    customphase

    Joined:
    Aug 19, 2012
    Posts:
    246
    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.
     
  3. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    826
    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 :)