using System.Collections.Generic; namespace UnityEngine.Rendering.PostProcessing { #if (ENABLE_VR_MODULE && ENABLE_VR) using XRSettings = UnityEngine.XR.XRSettings; #endif /// /// A context object passed around all post-processing effects in a frame. /// public sealed class PostProcessRenderContext { // ----------------------------------------------------------------------------------------- // The following should be filled by the render pipeline Camera m_Camera; /// /// The camera currently being rendered. /// public Camera camera { get { return m_Camera; } set { m_Camera = value; #if !UNITY_SWITCH && (ENABLE_VR_MODULE && ENABLE_VR) if (m_Camera.stereoEnabled) { var xrDesc = XRSettings.eyeTextureDesc; stereoRenderingMode = StereoRenderingMode.SinglePass; numberOfEyes = 1; #if UNITY_2018_3_OR_NEWER if (XRSettings.stereoRenderingMode == XRSettings.StereoRenderingMode.MultiPass) stereoRenderingMode = StereoRenderingMode.MultiPass; #endif #if UNITY_STANDALONE || UNITY_EDITOR || UNITY_PS4 || UNITY_PS5 if (xrDesc.dimension == TextureDimension.Tex2DArray) stereoRenderingMode = StereoRenderingMode.SinglePassInstanced; #endif if (stereoRenderingMode == StereoRenderingMode.SinglePassInstanced) numberOfEyes = 2; width = xrDesc.width; height = xrDesc.height; m_sourceDescriptor = xrDesc; if (m_Camera.stereoActiveEye == Camera.MonoOrStereoscopicEye.Right) xrActiveEye = (int)Camera.StereoscopicEye.Right; screenWidth = XRSettings.eyeTextureWidth; screenHeight = XRSettings.eyeTextureHeight; stereoActive = true; } else #endif { width = m_Camera.pixelWidth; height = m_Camera.pixelHeight; m_sourceDescriptor.width = width; m_sourceDescriptor.height = height; screenWidth = width; screenHeight = height; stereoActive = false; numberOfEyes = 1; } } } /// /// The command buffer to fill render commands in. /// public CommandBuffer command { get; set; } /// /// The source target for this pass (can't be the same as ). /// public RenderTargetIdentifier source { get; set; } /// /// The destination target for this pass (can't be the same as ). /// public RenderTargetIdentifier destination { get; set; } /// /// The texture format used for the source target. /// // We need this to be set explictely as we don't have any way of knowing if we're rendering // using HDR or not as scriptable render pipelines may ignore the HDR toggle on camera // completely public RenderTextureFormat sourceFormat { get; set; } /// /// Should we flip the last pass? /// public bool flip { get; set; } // ----------------------------------------------------------------------------------------- // The following is auto-populated by the post-processing stack /// /// The resource asset contains reference to external resources (shaders, textures...). /// public PostProcessResources resources { get; internal set; } /// /// The property sheet factory handled by the currently active . /// public PropertySheetFactory propertySheets { get; internal set; } /// /// A dictionary to store custom user data objects. This is handy to share data between /// custom effects. /// public Dictionary userData { get; private set; } /// /// A reference to the internal debug layer. /// public PostProcessDebugLayer debugLayer { get; internal set; } /// /// The current camera width (in pixels). /// public int width { get; private set; } /// /// The current camera height (in pixels). /// public int height { get; private set; } /// /// Is stereo rendering active? /// public bool stereoActive { get; private set; } /// /// The current active rendering eye (for XR). /// public int xrActiveEye { get; set; } /// /// The number of eyes for XR outputs. /// public int numberOfEyes { get; private set; } /// /// Available XR rendering modes. /// public enum StereoRenderingMode { /// /// Multi-pass. /// MultiPass = 0, /// /// Single-pass. /// SinglePass, /// /// Single-pass instanced. /// SinglePassInstanced, /// /// Single-pass multi-view. /// SinglePassMultiview } /// /// The current rendering mode for XR. /// public StereoRenderingMode stereoRenderingMode { get; private set; } /// /// The width of the logical screen size. /// public int screenWidth { get; private set; } /// /// The height of the logical screen size. /// public int screenHeight { get; private set; } /// /// Are we currently rendering in the scene view? /// public bool isSceneView { get; internal set; } /// /// The current anti-aliasing method used by the camera. /// public PostProcessLayer.Antialiasing antialiasing { get; internal set; } /// /// A reference to the temporal anti-aliasing settings for the rendering layer. This is /// mostly used to grab the jitter vector and other TAA-related values when an effect needs /// to do temporal reprojection. /// public TemporalAntialiasing temporalAntialiasing { get; internal set; } // Internal values used for builtin effects // Beware, these may not have been set before a specific builtin effect has been executed internal PropertySheet uberSheet; internal Texture autoExposureTexture; internal LogHistogram logHistogram; internal Texture logLut; internal AutoExposure autoExposure; internal int bloomBufferNameID; #if UNITY_2018_2_OR_NEWER internal bool physicalCamera; #endif /// /// Resets the state of this context object. This is called by the render pipeline on every /// frame and allows re-using the same context object between frames without having to /// recreate a new one. /// public void Reset() { m_Camera = null; width = 0; height = 0; m_sourceDescriptor = new RenderTextureDescriptor(0, 0); #if UNITY_2018_2_OR_NEWER physicalCamera = false; #endif stereoActive = false; xrActiveEye = (int)Camera.StereoscopicEye.Left; screenWidth = 0; screenHeight = 0; command = null; source = 0; destination = 0; sourceFormat = RenderTextureFormat.ARGB32; flip = false; resources = null; propertySheets = null; debugLayer = null; isSceneView = false; antialiasing = PostProcessLayer.Antialiasing.None; temporalAntialiasing = null; uberSheet = null; autoExposureTexture = null; logLut = null; autoExposure = null; bloomBufferNameID = -1; if (userData == null) userData = new Dictionary(); userData.Clear(); } /// /// Checks if temporal anti-aliasing is supported and enabled. /// /// true if temporal anti-aliasing is supported and enabled, false /// otherwise public bool IsTemporalAntialiasingActive() { return antialiasing == PostProcessLayer.Antialiasing.TemporalAntialiasing && !isSceneView && temporalAntialiasing.IsSupported(); } /// /// Checks if a specific debug overlay is enabled. /// /// The debug overlay to look for /// true if the specified debug overlay is enable, false /// otherwise public bool IsDebugOverlayEnabled(DebugOverlay overlay) { return debugLayer.debugOverlay == overlay; } /// /// Blit a source render target to the debug overlay target. This is a direct shortcut to /// . /// /// The command buffer to send render commands to /// The source target /// The property sheet to use for the blit /// The pass to use for the property sheet /// public void PushDebugOverlay(CommandBuffer cmd, RenderTargetIdentifier source, PropertySheet sheet, int pass) { debugLayer.PushDebugOverlay(cmd, source, sheet, pass); } // TODO: Change w/h name to texture w/h in order to make // size usages explicit RenderTextureDescriptor m_sourceDescriptor; internal RenderTextureDescriptor GetDescriptor(int depthBufferBits = 0, RenderTextureFormat colorFormat = RenderTextureFormat.Default, RenderTextureReadWrite readWrite = RenderTextureReadWrite.Default) { var modifiedDesc = new RenderTextureDescriptor(m_sourceDescriptor.width, m_sourceDescriptor.height, m_sourceDescriptor.colorFormat, depthBufferBits); modifiedDesc.dimension = m_sourceDescriptor.dimension; modifiedDesc.volumeDepth = m_sourceDescriptor.volumeDepth; modifiedDesc.vrUsage = m_sourceDescriptor.vrUsage; modifiedDesc.msaaSamples = m_sourceDescriptor.msaaSamples; modifiedDesc.memoryless = m_sourceDescriptor.memoryless; modifiedDesc.useMipMap = m_sourceDescriptor.useMipMap; modifiedDesc.autoGenerateMips = m_sourceDescriptor.autoGenerateMips; modifiedDesc.enableRandomWrite = m_sourceDescriptor.enableRandomWrite; modifiedDesc.shadowSamplingMode = m_sourceDescriptor.shadowSamplingMode; #if UNITY_2019_1_OR_NEWER if (m_Camera.allowDynamicResolution) modifiedDesc.useDynamicScale = true; #endif if (colorFormat != RenderTextureFormat.Default) modifiedDesc.colorFormat = colorFormat; #if UNITY_2019_1_OR_NEWER if (readWrite == RenderTextureReadWrite.sRGB) modifiedDesc.sRGB = true; else if (readWrite == RenderTextureReadWrite.Linear) modifiedDesc.sRGB = false; else if (readWrite == RenderTextureReadWrite.Default) modifiedDesc.sRGB = QualitySettings.activeColorSpace != ColorSpace.Gamma; #else modifiedDesc.sRGB = readWrite != RenderTextureReadWrite.Linear; #endif return modifiedDesc; } /// /// Grabs a temporary render target with the current display size. /// /// The command buffer to grab a render target from /// The shader property name for this texture /// The number of bits to use for the depth buffer /// The render texture format /// The color space conversion mode /// The texture filtering mode /// Override the display width; use 0 to disable the override /// Override the display height; use 0 to disable the override public void GetScreenSpaceTemporaryRT(CommandBuffer cmd, int nameID, int depthBufferBits = 0, RenderTextureFormat colorFormat = RenderTextureFormat.Default, RenderTextureReadWrite readWrite = RenderTextureReadWrite.Default, FilterMode filter = FilterMode.Bilinear, int widthOverride = 0, int heightOverride = 0) { var desc = GetDescriptor(depthBufferBits, colorFormat, readWrite); if (widthOverride > 0) desc.width = widthOverride; if (heightOverride > 0) desc.height = heightOverride; //intermediates in VR are unchanged if (stereoActive && desc.dimension == Rendering.TextureDimension.Tex2DArray) desc.dimension = Rendering.TextureDimension.Tex2D; #if UNITY_2019_1_OR_NEWER cmd.GetTemporaryRT(nameID, desc, filter); #elif UNITY_2017_3_OR_NEWER cmd.GetTemporaryRT(nameID, desc.width, desc.height, desc.depthBufferBits, filter, desc.colorFormat, readWrite, desc.msaaSamples, desc.enableRandomWrite, desc.memoryless, m_Camera.allowDynamicResolution); #else cmd.GetTemporaryRT(nameID, desc.width, desc.height, desc.depthBufferBits, filter, desc.colorFormat, readWrite, desc.msaaSamples, desc.enableRandomWrite, desc.memoryless); #endif } /// /// Grabs a temporary render target with the current display size. /// /// The number of bits to use for the depth buffer /// The render texture format /// The color space conversion mode /// Override the display width; use 0 to disable the override /// Override the display height; use 0 to disable the override /// A temporary render target public RenderTexture GetScreenSpaceTemporaryRT(int depthBufferBits = 0, RenderTextureFormat colorFormat = RenderTextureFormat.Default, RenderTextureReadWrite readWrite = RenderTextureReadWrite.Default, int widthOverride = 0, int heightOverride = 0) { var desc = GetDescriptor(depthBufferBits, colorFormat, readWrite); if (widthOverride > 0) desc.width = widthOverride; if (heightOverride > 0) desc.height = heightOverride; return RenderTexture.GetTemporary(desc); } /// /// Update current single-pass stereo state for TAA, AO, etc. /// /// The enabled state of Temporal Anti-aliasing /// The enabled state of Ambient Occlusion /// The enabled state of Screen-space Reflections public void UpdateSinglePassStereoState(bool isTAAEnabled, bool isAOEnabled, bool isSSREnabled) { #if UNITY_2019_1_OR_NEWER && ENABLE_VR_MODULE && ENABLE_VR var xrDesc = XRSettings.eyeTextureDesc; screenWidth = XRSettings.eyeTextureWidth; if (stereoRenderingMode == StereoRenderingMode.SinglePass) { //For complex effects, it's more efficient to disable XR single-pass interface if (isTAAEnabled || isAOEnabled || isSSREnabled) { numberOfEyes = 1; } else { //Use XR-interface method: //We take care of providing stereoized camera render texture to postprocessing framework and rendering out the final postprocessed results to the each of the eye textures // https://docs.google.com/document/d/1hANbhKCRIJs6ww7XoAIXbX3ArdAs7OBOTfZL1MqgtPI numberOfEyes = 2; xrDesc.width /= 2; xrDesc.vrUsage = VRTextureUsage.None; screenWidth /= 2; } width = xrDesc.width; height = xrDesc.height; m_sourceDescriptor = xrDesc; } #endif } } }