123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470 |
- using System;
- using System.Collections.Generic;
- using UnityEngine.Rendering;
- namespace UnityEngine.PostProcessing
- {
- using DebugMode = BuiltinDebugViewsModel.Mode;
- #if UNITY_5_4_OR_NEWER
- [ImageEffectAllowedInSceneView]
- #endif
- [RequireComponent(typeof(Camera)), DisallowMultipleComponent, ExecuteInEditMode]
- [AddComponentMenu("Effects/Post-Processing Behaviour", -1)]
- public class PostProcessingBehaviour : MonoBehaviour
- {
- // Inspector fields
- public PostProcessingProfile profile;
- public Func<Vector2, Matrix4x4> jitteredMatrixFunc;
- // Internal helpers
- Dictionary<Type, KeyValuePair<CameraEvent, CommandBuffer>> m_CommandBuffers;
- List<PostProcessingComponentBase> m_Components;
- Dictionary<PostProcessingComponentBase, bool> m_ComponentStates;
- MaterialFactory m_MaterialFactory;
- RenderTextureFactory m_RenderTextureFactory;
- PostProcessingContext m_Context;
- Camera m_Camera;
- PostProcessingProfile m_PreviousProfile;
- bool m_RenderingInSceneView = false;
- // Effect components
- BuiltinDebugViewsComponent m_DebugViews;
- AmbientOcclusionComponent m_AmbientOcclusion;
- ScreenSpaceReflectionComponent m_ScreenSpaceReflection;
- FogComponent m_FogComponent;
- MotionBlurComponent m_MotionBlur;
- TaaComponent m_Taa;
- EyeAdaptationComponent m_EyeAdaptation;
- DepthOfFieldComponent m_DepthOfField;
- BloomComponent m_Bloom;
- ChromaticAberrationComponent m_ChromaticAberration;
- ColorGradingComponent m_ColorGrading;
- UserLutComponent m_UserLut;
- GrainComponent m_Grain;
- VignetteComponent m_Vignette;
- DitheringComponent m_Dithering;
- FxaaComponent m_Fxaa;
- void OnEnable()
- {
- m_CommandBuffers = new Dictionary<Type, KeyValuePair<CameraEvent, CommandBuffer>>();
- m_MaterialFactory = new MaterialFactory();
- m_RenderTextureFactory = new RenderTextureFactory();
- m_Context = new PostProcessingContext();
- // Keep a list of all post-fx for automation purposes
- m_Components = new List<PostProcessingComponentBase>();
- // Component list
- m_DebugViews = AddComponent(new BuiltinDebugViewsComponent());
- m_AmbientOcclusion = AddComponent(new AmbientOcclusionComponent());
- m_ScreenSpaceReflection = AddComponent(new ScreenSpaceReflectionComponent());
- m_FogComponent = AddComponent(new FogComponent());
- m_MotionBlur = AddComponent(new MotionBlurComponent());
- m_Taa = AddComponent(new TaaComponent());
- m_EyeAdaptation = AddComponent(new EyeAdaptationComponent());
- m_DepthOfField = AddComponent(new DepthOfFieldComponent());
- m_Bloom = AddComponent(new BloomComponent());
- m_ChromaticAberration = AddComponent(new ChromaticAberrationComponent());
- m_ColorGrading = AddComponent(new ColorGradingComponent());
- m_UserLut = AddComponent(new UserLutComponent());
- m_Grain = AddComponent(new GrainComponent());
- m_Vignette = AddComponent(new VignetteComponent());
- m_Dithering = AddComponent(new DitheringComponent());
- m_Fxaa = AddComponent(new FxaaComponent());
- // Prepare state observers
- m_ComponentStates = new Dictionary<PostProcessingComponentBase, bool>();
- foreach (var component in m_Components)
- m_ComponentStates.Add(component, false);
- useGUILayout = false;
- }
- void OnPreCull()
- {
- // All the per-frame initialization logic has to be done in OnPreCull instead of Update
- // because [ImageEffectAllowedInSceneView] doesn't trigger Update events...
- m_Camera = GetComponent<Camera>();
- if (profile == null || m_Camera == null)
- return;
- #if UNITY_EDITOR
- // Track the scene view camera to disable some effects we don't want to see in the
- // scene view
- // Currently disabled effects :
- // - Temporal Antialiasing
- // - Depth of Field
- // - Motion blur
- m_RenderingInSceneView = UnityEditor.SceneView.currentDrawingSceneView != null
- && UnityEditor.SceneView.currentDrawingSceneView.camera == m_Camera;
- #endif
- // Prepare context
- var context = m_Context.Reset();
- context.profile = profile;
- context.renderTextureFactory = m_RenderTextureFactory;
- context.materialFactory = m_MaterialFactory;
- context.camera = m_Camera;
- // Prepare components
- m_DebugViews.Init(context, profile.debugViews);
- m_AmbientOcclusion.Init(context, profile.ambientOcclusion);
- m_ScreenSpaceReflection.Init(context, profile.screenSpaceReflection);
- m_FogComponent.Init(context, profile.fog);
- m_MotionBlur.Init(context, profile.motionBlur);
- m_Taa.Init(context, profile.antialiasing);
- m_EyeAdaptation.Init(context, profile.eyeAdaptation);
- m_DepthOfField.Init(context, profile.depthOfField);
- m_Bloom.Init(context, profile.bloom);
- m_ChromaticAberration.Init(context, profile.chromaticAberration);
- m_ColorGrading.Init(context, profile.colorGrading);
- m_UserLut.Init(context, profile.userLut);
- m_Grain.Init(context, profile.grain);
- m_Vignette.Init(context, profile.vignette);
- m_Dithering.Init(context, profile.dithering);
- m_Fxaa.Init(context, profile.antialiasing);
- // Handles profile change and 'enable' state observers
- if (m_PreviousProfile != profile)
- {
- DisableComponents();
- m_PreviousProfile = profile;
- }
- CheckObservers();
- // Find out which camera flags are needed before rendering begins
- // Note that motion vectors will only be available one frame after being enabled
- var flags = context.camera.depthTextureMode;
- foreach (var component in m_Components)
- {
- if (component.active)
- flags |= component.GetCameraFlags();
- }
- context.camera.depthTextureMode = flags;
- // Temporal antialiasing jittering, needs to happen before culling
- if (!m_RenderingInSceneView && m_Taa.active && !profile.debugViews.willInterrupt)
- m_Taa.SetProjectionMatrix(jitteredMatrixFunc);
- }
- void OnPreRender()
- {
- if (profile == null)
- return;
- // Command buffer-based effects should be set-up here
- TryExecuteCommandBuffer(m_DebugViews);
- TryExecuteCommandBuffer(m_AmbientOcclusion);
- TryExecuteCommandBuffer(m_ScreenSpaceReflection);
- TryExecuteCommandBuffer(m_FogComponent);
- if (!m_RenderingInSceneView)
- TryExecuteCommandBuffer(m_MotionBlur);
- }
- void OnPostRender()
- {
- if (profile == null || m_Camera == null)
- return;
- if (!m_RenderingInSceneView && m_Taa.active && !profile.debugViews.willInterrupt)
- m_Context.camera.ResetProjectionMatrix();
- }
- // Classic render target pipeline for RT-based effects
- void OnRenderImage(RenderTexture source, RenderTexture destination)
- {
- if (profile == null || m_Camera == null)
- {
- Graphics.Blit(source, destination);
- return;
- }
- // Uber shader setup
- bool uberActive = false;
- bool fxaaActive = m_Fxaa.active;
- bool taaActive = m_Taa.active && !m_RenderingInSceneView;
- bool dofActive = m_DepthOfField.active && !m_RenderingInSceneView;
- var uberMaterial = m_MaterialFactory.Get("Hidden/Post FX/Uber Shader");
- uberMaterial.shaderKeywords = null;
- var src = source;
- var dst = destination;
- if (taaActive)
- {
- var tempRT = m_RenderTextureFactory.Get(src);
- m_Taa.Render(src, tempRT);
- src = tempRT;
- }
- #if UNITY_EDITOR
- // Render to a dedicated target when monitors are enabled so they can show information
- // about the final render.
- // At runtime the output will always be the backbuffer or whatever render target is
- // currently set on the camera.
- if (profile.monitors.onFrameEndEditorOnly != null)
- dst = m_RenderTextureFactory.Get(src);
- #endif
- Texture autoExposure = GraphicsUtils.whiteTexture;
- if (m_EyeAdaptation.active)
- {
- uberActive = true;
- autoExposure = m_EyeAdaptation.Prepare(src, uberMaterial);
- }
- uberMaterial.SetTexture("_AutoExposure", autoExposure);
- if (dofActive)
- {
- uberActive = true;
- m_DepthOfField.Prepare(src, uberMaterial, taaActive, m_Taa.jitterVector, m_Taa.model.settings.taaSettings.motionBlending);
- }
- if (m_Bloom.active)
- {
- uberActive = true;
- m_Bloom.Prepare(src, uberMaterial, autoExposure);
- }
- uberActive |= TryPrepareUberImageEffect(m_ChromaticAberration, uberMaterial);
- uberActive |= TryPrepareUberImageEffect(m_ColorGrading, uberMaterial);
- uberActive |= TryPrepareUberImageEffect(m_Vignette, uberMaterial);
- uberActive |= TryPrepareUberImageEffect(m_UserLut, uberMaterial);
- var fxaaMaterial = fxaaActive
- ? m_MaterialFactory.Get("Hidden/Post FX/FXAA")
- : null;
- if (fxaaActive)
- {
- fxaaMaterial.shaderKeywords = null;
- TryPrepareUberImageEffect(m_Grain, fxaaMaterial);
- TryPrepareUberImageEffect(m_Dithering, fxaaMaterial);
- if (uberActive)
- {
- var output = m_RenderTextureFactory.Get(src);
- Graphics.Blit(src, output, uberMaterial, 0);
- src = output;
- }
- m_Fxaa.Render(src, dst);
- }
- else
- {
- uberActive |= TryPrepareUberImageEffect(m_Grain, uberMaterial);
- uberActive |= TryPrepareUberImageEffect(m_Dithering, uberMaterial);
- if (uberActive)
- {
- if (!GraphicsUtils.isLinearColorSpace)
- uberMaterial.EnableKeyword("UNITY_COLORSPACE_GAMMA");
- Graphics.Blit(src, dst, uberMaterial, 0);
- }
- }
- if (!uberActive && !fxaaActive)
- Graphics.Blit(src, dst);
- #if UNITY_EDITOR
- if (profile.monitors.onFrameEndEditorOnly != null)
- {
- Graphics.Blit(dst, destination);
- var oldRt = RenderTexture.active;
- profile.monitors.onFrameEndEditorOnly(dst);
- RenderTexture.active = oldRt;
- }
- #endif
- m_RenderTextureFactory.ReleaseAll();
- }
- void OnGUI()
- {
- if (Event.current.type != EventType.Repaint)
- return;
- if (profile == null || m_Camera == null)
- return;
- if (m_EyeAdaptation.active && profile.debugViews.IsModeActive(DebugMode.EyeAdaptation))
- m_EyeAdaptation.OnGUI();
- else if (m_ColorGrading.active && profile.debugViews.IsModeActive(DebugMode.LogLut))
- m_ColorGrading.OnGUI();
- else if (m_UserLut.active && profile.debugViews.IsModeActive(DebugMode.UserLut))
- m_UserLut.OnGUI();
- }
- void OnDisable()
- {
- // Clear command buffers
- foreach (var cb in m_CommandBuffers.Values)
- {
- m_Camera.RemoveCommandBuffer(cb.Key, cb.Value);
- cb.Value.Dispose();
- }
- m_CommandBuffers.Clear();
- // Clear components
- if (profile != null)
- DisableComponents();
- m_Components.Clear();
- // Factories
- m_MaterialFactory.Dispose();
- m_RenderTextureFactory.Dispose();
- GraphicsUtils.Dispose();
- }
- public void ResetTemporalEffects()
- {
- m_Taa.ResetHistory();
- m_MotionBlur.ResetHistory();
- m_EyeAdaptation.ResetHistory();
- }
- #region State management
- List<PostProcessingComponentBase> m_ComponentsToEnable = new List<PostProcessingComponentBase>();
- List<PostProcessingComponentBase> m_ComponentsToDisable = new List<PostProcessingComponentBase>();
- void CheckObservers()
- {
- foreach (var cs in m_ComponentStates)
- {
- var component = cs.Key;
- var state = component.GetModel().enabled;
- if (state != cs.Value)
- {
- if (state) m_ComponentsToEnable.Add(component);
- else m_ComponentsToDisable.Add(component);
- }
- }
- for (int i = 0; i < m_ComponentsToDisable.Count; i++)
- {
- var c = m_ComponentsToDisable[i];
- m_ComponentStates[c] = false;
- c.OnDisable();
- }
- for (int i = 0; i < m_ComponentsToEnable.Count; i++)
- {
- var c = m_ComponentsToEnable[i];
- m_ComponentStates[c] = true;
- c.OnEnable();
- }
- m_ComponentsToDisable.Clear();
- m_ComponentsToEnable.Clear();
- }
- void DisableComponents()
- {
- foreach (var component in m_Components)
- {
- var model = component.GetModel();
- if (model != null && model.enabled)
- component.OnDisable();
- }
- }
- #endregion
- #region Command buffer handling & rendering helpers
- // Placeholders before the upcoming Scriptable Render Loop as command buffers will be
- // executed on the go so we won't need of all that stuff
- CommandBuffer AddCommandBuffer<T>(CameraEvent evt, string name)
- where T : PostProcessingModel
- {
- var cb = new CommandBuffer { name = name };
- var kvp = new KeyValuePair<CameraEvent, CommandBuffer>(evt, cb);
- m_CommandBuffers.Add(typeof(T), kvp);
- m_Camera.AddCommandBuffer(evt, kvp.Value);
- return kvp.Value;
- }
- void RemoveCommandBuffer<T>()
- where T : PostProcessingModel
- {
- KeyValuePair<CameraEvent, CommandBuffer> kvp;
- var type = typeof(T);
- if (!m_CommandBuffers.TryGetValue(type, out kvp))
- return;
- m_Camera.RemoveCommandBuffer(kvp.Key, kvp.Value);
- m_CommandBuffers.Remove(type);
- kvp.Value.Dispose();
- }
- CommandBuffer GetCommandBuffer<T>(CameraEvent evt, string name)
- where T : PostProcessingModel
- {
- CommandBuffer cb;
- KeyValuePair<CameraEvent, CommandBuffer> kvp;
- if (!m_CommandBuffers.TryGetValue(typeof(T), out kvp))
- {
- cb = AddCommandBuffer<T>(evt, name);
- }
- else if (kvp.Key != evt)
- {
- RemoveCommandBuffer<T>();
- cb = AddCommandBuffer<T>(evt, name);
- }
- else cb = kvp.Value;
- return cb;
- }
- void TryExecuteCommandBuffer<T>(PostProcessingComponentCommandBuffer<T> component)
- where T : PostProcessingModel
- {
- if (component.active)
- {
- var cb = GetCommandBuffer<T>(component.GetCameraEvent(), component.GetName());
- cb.Clear();
- component.PopulateCommandBuffer(cb);
- }
- else RemoveCommandBuffer<T>();
- }
- bool TryPrepareUberImageEffect<T>(PostProcessingComponentRenderTexture<T> component, Material material)
- where T : PostProcessingModel
- {
- if (!component.active)
- return false;
- component.Prepare(material);
- return true;
- }
- T AddComponent<T>(T component)
- where T : PostProcessingComponentBase
- {
- m_Components.Add(component);
- return component;
- }
- #endregion
- }
- }
|