Search Unity

Image effect in scene editor views

Discussion in 'Scripting' started by n00body, Aug 29, 2011.

  1. n00body

    n00body

    Joined:
    Dec 17, 2010
    Posts:
    691
    Background:
    Okay, I am working on integrating a physically based BRDF into Unity's forward renderer. For that reason, I needed to make sure that I had a custom camera script that accumulated all lights in linear space into an ARGBHalf target, and then an image effect that tonemapped the accumulated results and converted them to gamma space. So far, I have this working in play mode only.

    Question:
    Below, you can see the correct look outlined in green, and the incorrect looks outlined in red. My question is, is there any way I can apply the aforementioned scripts to these views so that my artist can get an accurate preview without having to use the in-game view?

    Thank you for any help you can provide. ;)

     
  2. n00body

    n00body

    Joined:
    Dec 17, 2010
    Posts:
    691
    *grumble grumble*
    That's about what I expected, but I thought I'd ask just to be safe. Thanks for the help dreamora.
     
  3. omgitsalexl

    omgitsalexl

    Joined:
    Jun 20, 2011
    Posts:
    70
  4. DanTreble

    DanTreble

    Joined:
    Aug 31, 2010
    Posts:
    590
    This, I want image effects on the scene view
     
  5. duke

    duke

    Joined:
    Jan 10, 2007
    Posts:
    763
    The scene view has a camera. You may be able to use some hacky editor-only gameobject with a script on it to get a reference to this, and attach the relevant components.

    edit: Yep that works. Pop this on a GameObject in your scene, then add image effects as you would on a regular camera. Otherwise, choose a reference camera and tick UseReferenceCamera to use it's components instead. Update by toggling the enabled state of the script:

    Code (csharp):
    1. using System;
    2. using System.Linq;
    3. using UnityEditor;
    4. using UnityEngine;
    5.  
    6. [ExecuteInEditMode]
    7. public class SceneViewCameraProxy : MonoBehaviour
    8. {
    9. #if UNITY_EDITOR
    10.     public SceneView SceneView;
    11.     public Camera Camera;
    12.  
    13.     public Camera ReferenceCamera;
    14.     public bool UseReferenceCamera;
    15.  
    16.     public void OnEnable()
    17.     {
    18.         Camera = GetCamera();
    19.         UpdateComponents();
    20.     }
    21.  
    22.     private Camera GetCamera()
    23.     {
    24.         SceneView = EditorWindow.GetWindow<SceneView>();
    25.         return SceneView.camera;
    26.     }
    27.  
    28.     private Component[] GetComponents()
    29.     {
    30.         var result = UseReferenceCamera
    31.                      ? ReferenceCamera.GetComponents<Component>()
    32.                      : GetComponents<Component>();
    33.  
    34.         if (result != null  result.Length > 1) // Exclude Transform
    35.         {
    36.             result = result.Except(new[] {UseReferenceCamera ? ReferenceCamera.transform : transform}).ToArray();
    37.  
    38.             var hasCamera = UseReferenceCamera ? true : camera != null;
    39.             if (hasCamera)
    40.                 result = UseReferenceCamera ? result.Except(new[] {ReferenceCamera}).ToArray() : result.Except(new[] {camera}).ToArray();
    41.         }
    42.  
    43.         return result;
    44.     }
    45.  
    46.     private void UpdateComponents()
    47.     {
    48.         if(Camera == null)
    49.             Camera = GetCamera();
    50.  
    51.         if (Camera == null) // This shouldn't happen, but it does
    52.             return;
    53.  
    54.         if(UseReferenceCamera  ReferenceCamera == null)
    55.             throw new Exception("UseReferenceCamera enabled, but none chosen.");
    56.  
    57.         var components = GetComponents();
    58.         if (components != null  components.Length > 1)
    59.         {
    60.             var cameraGo = Camera.gameObject;
    61.  
    62.             Debug.Log(cameraGo);
    63.             Debug.Log(cameraGo.GetComponents(typeof(Component)).Length);
    64.  
    65.             for (var i = 0; i < components.Length; i++)
    66.             {
    67.                 var c = components[i];
    68.                 var cType = c.GetType();
    69.                
    70.                 var existing = cameraGo.GetComponent(cType) ?? cameraGo.AddComponent(cType);
    71.  
    72.                 EditorUtility.CopySerialized(c, existing);
    73.             }
    74.         }
    75.     }
    76. #endif
    77. }
     
    Last edited: Apr 24, 2013
    mliukka likes this.
  6. Erind

    Erind

    Joined:
    Jul 23, 2014
    Posts:
    56
    fixed for 5.3
    Code (CSharp):
    1. using System.Collections.Generic;
    2. using System;
    3. using System.Linq;
    4. using UnityEditor;
    5. using UnityEngine;
    6.  
    7. [ExecuteInEditMode]
    8. public class SceneViewCameraProxy : MonoBehaviour
    9. {
    10.     #if UNITY_EDITOR
    11.     public SceneView SceneView;
    12.     public Camera Camera;
    13.  
    14.     public Camera ReferenceCamera;
    15.     public bool UseReferenceCamera;
    16.  
    17.     public void OnEnable()
    18.     {
    19.         Camera = GetCamera();
    20.         UpdateComponents();
    21.     }
    22.  
    23.     private Camera GetCamera()
    24.     {
    25.         SceneView = EditorWindow.GetWindow<SceneView>();
    26.         return SceneView.camera;
    27.     }
    28.  
    29.     private Component[] GetComponents()
    30.     {
    31.         var result = UseReferenceCamera
    32.             ? ReferenceCamera.GetComponents<Component>()
    33.             : GetComponents<Component>();
    34.  
    35.         if (result != null && result.Length > 1) // Exclude Transform
    36.         {
    37.             result = result.Except(new[] {UseReferenceCamera ? ReferenceCamera.transform : transform}).ToArray();
    38.  
    39.             var hasCamera = UseReferenceCamera ? true : GetComponent<Camera>() != null;
    40.             if (hasCamera)
    41.                 result = UseReferenceCamera ? result.Except(new[] {ReferenceCamera}).ToArray() : result.Except(new[] {GetComponent<Camera>()}).ToArray();
    42.         }
    43.  
    44.         return result;
    45.     }
    46.  
    47.     private void UpdateComponents()
    48.     {
    49.         if(Camera == null)
    50.             Camera = GetCamera();
    51.  
    52.         if (Camera == null) // This shouldn't happen, but it does
    53.             return;
    54.  
    55.         if(UseReferenceCamera && ReferenceCamera == null)
    56.             throw new Exception("UseReferenceCamera enabled, but none chosen.");
    57.  
    58.         var components = GetComponents();
    59.         if (components != null && components.Length > 1)
    60.         {
    61.             var cameraGo = Camera.gameObject;
    62.  
    63.             Debug.Log(cameraGo);
    64.             Debug.Log(cameraGo.GetComponents(typeof(Component)).Length);
    65.  
    66.             for (var i = 0; i < components.Length; i++)
    67.             {
    68.                 var c = components[i];
    69.                 var cType = c.GetType();
    70.  
    71.                 var existing = cameraGo.GetComponent(cType) ?? cameraGo.AddComponent(cType);
    72.  
    73.                 EditorUtility.CopySerialized(c, existing);
    74.             }
    75.         }
    76.     }
    77.     #endif
    78. }
     
  7. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,205
    Added fancy settings so normal scripts are not copied (checks for implementation of OnRenderImage), also fixing an error with copying GUILayer, and added support for automatically updating the image effects once a variable on the object has been changed, allowing for editing them in the scene view without having to disable and re-enable the component to update the image effects.
    Nothing crucial, but I found it comes in really handy:
    Code (csharp):
    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Reflection;
    5.  
    6. using UnityEngine;
    7. #if UNITY_EDITOR
    8. using UnityEditor;
    9. #endif
    10.  
    11. [ExecuteInEditMode]
    12. public class SceneViewCameraProxy : MonoBehaviour
    13. {
    14.     #if UNITY_EDITOR
    15.     private SceneView SceneView;
    16.     public Camera SceneCamera;
    17.  
    18.     public Camera ReferenceCamera;
    19.     public bool UseReferenceCamera;
    20.  
    21.     public bool ReflectionCheckForIE = true;
    22.     public bool CheckForStandardIE = true;
    23.  
    24.     public bool UpdateOnChange = true;
    25.     public bool ResetIEOnDisable = true;
    26.     public bool DebugImageEffects = false;
    27.  
    28.     // Used only for Update
    29.     private int lastComponentCount;
    30.     private Component[] cachedComponents;
    31.  
    32.     private GameObject IEsourceGO { get { return UseReferenceCamera? ReferenceCamera.gameObject : gameObject; } }
    33.  
    34.     public void OnEnable()
    35.     {
    36.         UpdateImageEffects();
    37.     }
    38.  
    39.     public void OnValidate()
    40.     { // Update when a variable on this script was changed
    41.         if (!UpdateOnChange)
    42.             OnEnable ();
    43.     }
    44.  
    45.     public void OnDisable ()
    46.     { // Reset image effects on disabling this component if desired
    47.         if (ResetIEOnDisable)
    48.             ResetImageEffects ();
    49.     }
    50.  
    51.     public void Update ()
    52.     {
    53.         if (UpdateOnChange && Selection.activeGameObject == IEsourceGO)
    54.         { // Update scene camera with changed image effects using cached components, as long as none are added or removed
    55.             if (DebugImageEffects)
    56.                 Debug.Log("Updating reference camera due to changed components!");
    57.             int componentCount = IEsourceGO.GetComponents<Component>().Length;
    58.             if (lastComponentCount != componentCount)
    59.             { // Image Effects might have been added or removed, so refetch them
    60.                 lastComponentCount = componentCount;
    61.                 cachedComponents = GetImageEffectComponents(IEsourceGO);
    62.             }
    63.             UpdateSceneCamera ();
    64.             if (SceneCamera != null)
    65.                 InternalCopyComponents (cachedComponents, SceneCamera.gameObject);
    66.         }
    67.     }
    68.  
    69.     private void UpdateSceneCamera()
    70.     {
    71.         if (UnityEditor.SceneView.lastActiveSceneView != null)
    72.             SceneView = UnityEditor.SceneView.lastActiveSceneView;
    73.         SceneCamera = SceneView == null? null : SceneView.camera;
    74.     }
    75.  
    76.     /// <summary>
    77.     /// Returns all components filtered for image effects
    78.     /// </summary>
    79.     private Component[] GetImageEffectComponents(GameObject GO)
    80.     {
    81.         Component[] components = GO.GetComponents<Component>();
    82.         if (components != null && components.Length > 0)
    83.         { // Exclude Transform and Camera components
    84.             if (ReflectionCheckForIE)
    85.             { // Check if component implements OnRenderImage used for image postprocessing -> Perfect check!
    86.                 components = components.Where((Component c) => c.GetType ().GetMethod ("OnRenderImage", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public) != null).ToArray();
    87.             }
    88.             else if (CheckForStandardIE)
    89.             { // Check if it is an standard image effects; unfortunately does not always work on 3rd party components!
    90.                 components = components.Where ((Component c) => c.GetType ().IsSubclassOf (typeof(UnityStandardAssets.ImageEffects.PostEffectsBase))).ToArray ();
    91.             }
    92.             else
    93.             { // Check for all Components possibly being image effects, but may include normal scripts!
    94.                 components = components.Where((Component c) => {
    95.                     Type cT = c.GetType ();
    96.                     return c != this && cT != typeof(Transform) && cT != typeof(GUILayer) && cT != typeof(Camera);
    97.                 }).ToArray();
    98.             }
    99.         }
    100.         return components;
    101.     }
    102.  
    103.     /// <summary>
    104.     /// Updates the image effects found on the proxy object to the scene camera
    105.     /// </summary>
    106.     private void UpdateImageEffects()
    107.     {
    108.         UpdateSceneCamera ();
    109.         if (SceneCamera == null)
    110.             return;
    111.  
    112.         if(UseReferenceCamera && ReferenceCamera == null)
    113.             throw new Exception("UseReferenceCamera enabled, but none chosen.");
    114.  
    115.         if (DebugImageEffects)
    116.             Debug.Log ("Applying image effects to '" + SceneCamera.gameObject + "':");
    117.  
    118.         lastComponentCount = IEsourceGO.GetComponents<Component>().Length;
    119.         cachedComponents = GetImageEffectComponents(IEsourceGO);
    120.         InternalCopyComponents (cachedComponents, SceneCamera.gameObject);
    121.     }
    122.  
    123.     /// <summary>
    124.     /// Resets all image effects found on the scene camera
    125.     /// </summary>
    126.     private void ResetImageEffects()
    127.     {
    128.         UpdateSceneCamera ();
    129.         if (SceneCamera == null)
    130.             return;
    131.  
    132.         if (DebugImageEffects)
    133.             Debug.Log ("Resetting image effects of '" + SceneCamera.gameObject + "':");
    134.  
    135.         Component[] components = GetImageEffectComponents (SceneCamera.gameObject);
    136.         for (int i = 0; i < components.Length; i++)
    137.         {
    138.             Component comp = components[i];
    139.             if (DebugImageEffects)
    140.                 Debug.Log(comp.GetType().Name);
    141.             DestroyImmediate (comp);
    142.         }
    143.     }
    144.  
    145.     private void InternalCopyComponents (Component[] components, GameObject target)
    146.     {
    147.         if (components != null && components.Length > 0)
    148.         {
    149.             for (int i = 0; i < components.Length; i++)
    150.             {
    151.                 Component comp = components[i];
    152.                 Type cType = comp.GetType();
    153.                 if (DebugImageEffects)
    154.                     Debug.Log(cType.Name);
    155.                 // Copy component values
    156.                 Component existingComp = target.GetComponent(cType) ?? target.AddComponent(cType);
    157.                 EditorUtility.CopySerialized(comp, existingComp);
    158.             }
    159.         }
    160.     }
    161.  
    162.     #endif
    163. }
    EDIT: Fixed calling GetSceneCamera when updating ImageEffects automatically interrupting current keyboard input and randomly opening SceneViews (won't automatically open one if user does not want)
     
    Last edited: Feb 4, 2017
    Flurgle likes this.
  8. Flurgle

    Flurgle

    Joined:
    May 16, 2016
    Posts:
    389
    @Seneral Nice work :)

    (and BTW, your Erosion simulation is beautiful)
     
  9. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,205
    Thanks:)
    Will develop it further after the release of my first tool (in like a month).
    Edit: Just announced said tool;)
     
    Last edited: Feb 5, 2017
    Flurgle likes this.
  10. correia55

    correia55

    Joined:
    Feb 22, 2014
    Posts:
    7
    I've tried adding an image effect to the editor camera with @Seneral 's script, which seems to work well since awake runs. The problem is OnRenderImage does not seem to run at all, I've added Debug.Log and nothing gets printed nor the effect is visualized. The same image effect works properly in the main camera. Am I missing something?

    Thanks in advance

    EDIT: Apparently its a problem with the newest versions of unity as discussed in https://forum.unity.com/threads/image-effects-not-showing-in-the-editor-camera.464160/ .
     
unityunity