From 3d7b4e6a14690148c9ae965d1acad843b8db3912 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Thu, 12 Nov 2020 16:53:09 +0100 Subject: [PATCH 1/5] Empty image layers in the graphics compositor don't render black anymore --- .../Runtime/Compositor/CompositionLayer.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/Compositor/CompositionLayer.cs b/com.unity.render-pipelines.high-definition/Runtime/Compositor/CompositionLayer.cs index 747da77bff9..29e9014978e 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Compositor/CompositionLayer.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Compositor/CompositionLayer.cs @@ -552,7 +552,7 @@ public void UpdateOutputCamera() { var compositorData = m_LayerCamera.GetComponent(); if (compositorData) - compositorData.clearColorTexture = (m_Show && m_InputTexture != null) ? m_InputTexture : Texture2D.blackTexture; + compositorData.clearColorTexture = (m_Show && m_InputTexture != null) ? m_InputTexture : null; } if (m_LayerCamera.enabled) @@ -653,14 +653,16 @@ public void SetupLayerCamera(CompositorLayer targetLayer, int layerPositionInSta { if (layerPositionInStack != 0) { - // The next layer in the stack should clear with the texture of the previous layer: this will copy the content of the target RT to the RTHandle and preserve post process + // The next layer in the stack should clear with the texture of the previous layer: + // this will copy the content of the target RT to the RTHandle and preserve post process + // Unless we have an image layer with a valid texture: in this case we use the texture as clear color cameraData.clearColorMode = HDAdditionalCameraData.ClearColorMode.None; var compositorData = m_LayerCamera.GetComponent(); if (!compositorData) { compositorData = m_LayerCamera.gameObject.AddComponent(); } - if (m_Type != LayerType.Image) + if (m_Type != LayerType.Image || (m_Type == LayerType.Image && m_InputTexture == null)) { compositorData.clearColorTexture = targetLayer.GetRenderTarget(); compositorData.clearDepthTexture = targetLayer.m_RTHandle; From cc3971dcc2d0fce06823d50befd673ee37ac7bb8 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Thu, 12 Nov 2020 17:43:13 +0100 Subject: [PATCH 2/5] Improve camera management in compositor --- .../CHANGELOG.md | 1 + .../Runtime/Compositor/CompositionLayer.cs | 18 ++++++++++++------ .../Runtime/Compositor/CompositionManager.cs | 13 +++++++++++++ 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/CHANGELOG.md b/com.unity.render-pipelines.high-definition/CHANGELOG.md index c91b6526b68..a32f0cc233d 100644 --- a/com.unity.render-pipelines.high-definition/CHANGELOG.md +++ b/com.unity.render-pipelines.high-definition/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Fixed - Fixed probe volumes debug views. +- Fixed issues with image layers in graphics compositor (empty layers don't render black, improve internal camera management - case 1289936) ## [10.2.0] - 2020-10-19 diff --git a/com.unity.render-pipelines.high-definition/Runtime/Compositor/CompositionLayer.cs b/com.unity.render-pipelines.high-definition/Runtime/Compositor/CompositionLayer.cs index 29e9014978e..a119d51cfb6 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Compositor/CompositionLayer.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Compositor/CompositionLayer.cs @@ -137,6 +137,7 @@ public float aspectRatio // Returns true if this layer is using a camera that was cloned internally for drawing internal bool isUsingACameraClone => !m_LayerCamera.Equals(m_Camera); + internal bool isImageOrVideoLayer => (m_Type == LayerType.Image || m_Type == LayerType.Video); // The input alpha will be mapped between the min and max range when blending between the post-processed and plain image regions. This way the user can controls how steep is the transition. [SerializeField] float m_AlphaMin = 0.0f; @@ -151,12 +152,12 @@ public static CompositorLayer CreateStackLayer(LayerType type = CompositorLayer. var newLayer = new CompositorLayer(); newLayer.m_LayerName = layerName; newLayer.m_Type = type; - newLayer.m_Camera = CompositionManager.GetSceneCamera(); + newLayer.m_Camera = newLayer.isImageOrVideoLayer ? null : CompositionManager.GetSceneCamera(); newLayer.m_CullingMask = newLayer.m_Camera? newLayer.m_Camera.cullingMask : 0; //LayerMask.GetMask("None"); newLayer.m_OutputTarget = CompositorLayer.OutputTarget.CameraStack; newLayer.m_ClearDepth = true; - if (newLayer.m_Type == LayerType.Image || newLayer.m_Type == LayerType.Video) + if (newLayer.isImageOrVideoLayer) { // Image and movie layers do not render any 3D objects newLayer.m_OverrideCullingMask = true; @@ -229,6 +230,11 @@ public void Init(string layerID = "") // Compositor output layers (that allocate the render targets) also need a reference camera, just to get the reference pixel width/height // Note: Movie & image layers are rendered at the output resolution (and not the movie/image resolution). This is required to have post-processing effects like film grain at full res. + if (m_Camera == null && isImageOrVideoLayer) + { + // For image and video layers, we use a brand-new camera (to avoid sharing the same camera with other layers) + m_Camera = CompositionManager.AddNewCamera(m_LayerName); + } if (m_Camera == null) { m_Camera = CompositionManager.GetSceneCamera(); @@ -242,11 +248,11 @@ public void Init(string layerID = "") // We do not clone the camera if : // - it has no layer overrides // - is not shared between layers - // - is not used in an mage/video layer (in this case the camera is not exposed at all, so it makes sense to let the compositor manage it) + // - it is an mage/video layer (in this case we use a brand-new camera that is not exposed at all and is managed by the compositor) // - it does not force-clear the RT (the first layer of a stack, even if disabled by the user), still clears the RT bool shouldClear = !enabled && m_LayerPositionInStack == 0; - bool isImageOrVideo = (m_Type == LayerType.Image || m_Type == LayerType.Video); - if (!isImageOrVideo && !hasLayerOverrides && !shouldClear && !compositor.IsThisCameraShared(m_Camera)) + + if (isImageOrVideoLayer || (!hasLayerOverrides && !shouldClear && !compositor.IsThisCameraShared(m_Camera))) { m_LayerCamera = m_Camera; } @@ -414,7 +420,7 @@ public void DestroyCameras() // We should destroy the layer camera only if it was cloned if (m_LayerCamera != null) { - if (isUsingACameraClone) + if (isUsingACameraClone || isImageOrVideoLayer) { var cameraData = m_LayerCamera.GetComponent(); if (cameraData) diff --git a/com.unity.render-pipelines.high-definition/Runtime/Compositor/CompositionManager.cs b/com.unity.render-pipelines.high-definition/Runtime/Compositor/CompositionManager.cs index d1269b3188d..fed4c3b3dbc 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Compositor/CompositionManager.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Compositor/CompositionManager.cs @@ -843,6 +843,19 @@ static public Camera GetSceneCamera() return null; } + static public Camera AddNewCamera(string cameraName) + { + var newCameraGameObject = new GameObject(cameraName) + { + hideFlags = HideFlags.HideInInspector | HideFlags.HideInHierarchy | HideFlags.HideAndDontSave + }; + + var camera = newCameraGameObject.AddComponent(); + newCameraGameObject.AddComponent(); + + return camera; + } + static public CompositionManager GetInstance() => s_CompositorInstance ?? (s_CompositorInstance = GameObject.FindObjectOfType(typeof(CompositionManager), true) as CompositionManager); From 9cb75886f03f903c926933e8e2192ddea5ae5a36 Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Thu, 12 Nov 2020 18:14:05 +0100 Subject: [PATCH 3/5] Revert "Improve camera management in compositor" This reverts commit cc3971dcc2d0fce06823d50befd673ee37ac7bb8. --- .../CHANGELOG.md | 1 - .../Runtime/Compositor/CompositionLayer.cs | 18 ++++++------------ .../Runtime/Compositor/CompositionManager.cs | 13 ------------- 3 files changed, 6 insertions(+), 26 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/CHANGELOG.md b/com.unity.render-pipelines.high-definition/CHANGELOG.md index a32f0cc233d..c91b6526b68 100644 --- a/com.unity.render-pipelines.high-definition/CHANGELOG.md +++ b/com.unity.render-pipelines.high-definition/CHANGELOG.md @@ -11,7 +11,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Fixed - Fixed probe volumes debug views. -- Fixed issues with image layers in graphics compositor (empty layers don't render black, improve internal camera management - case 1289936) ## [10.2.0] - 2020-10-19 diff --git a/com.unity.render-pipelines.high-definition/Runtime/Compositor/CompositionLayer.cs b/com.unity.render-pipelines.high-definition/Runtime/Compositor/CompositionLayer.cs index a119d51cfb6..29e9014978e 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Compositor/CompositionLayer.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Compositor/CompositionLayer.cs @@ -137,7 +137,6 @@ public float aspectRatio // Returns true if this layer is using a camera that was cloned internally for drawing internal bool isUsingACameraClone => !m_LayerCamera.Equals(m_Camera); - internal bool isImageOrVideoLayer => (m_Type == LayerType.Image || m_Type == LayerType.Video); // The input alpha will be mapped between the min and max range when blending between the post-processed and plain image regions. This way the user can controls how steep is the transition. [SerializeField] float m_AlphaMin = 0.0f; @@ -152,12 +151,12 @@ public static CompositorLayer CreateStackLayer(LayerType type = CompositorLayer. var newLayer = new CompositorLayer(); newLayer.m_LayerName = layerName; newLayer.m_Type = type; - newLayer.m_Camera = newLayer.isImageOrVideoLayer ? null : CompositionManager.GetSceneCamera(); + newLayer.m_Camera = CompositionManager.GetSceneCamera(); newLayer.m_CullingMask = newLayer.m_Camera? newLayer.m_Camera.cullingMask : 0; //LayerMask.GetMask("None"); newLayer.m_OutputTarget = CompositorLayer.OutputTarget.CameraStack; newLayer.m_ClearDepth = true; - if (newLayer.isImageOrVideoLayer) + if (newLayer.m_Type == LayerType.Image || newLayer.m_Type == LayerType.Video) { // Image and movie layers do not render any 3D objects newLayer.m_OverrideCullingMask = true; @@ -230,11 +229,6 @@ public void Init(string layerID = "") // Compositor output layers (that allocate the render targets) also need a reference camera, just to get the reference pixel width/height // Note: Movie & image layers are rendered at the output resolution (and not the movie/image resolution). This is required to have post-processing effects like film grain at full res. - if (m_Camera == null && isImageOrVideoLayer) - { - // For image and video layers, we use a brand-new camera (to avoid sharing the same camera with other layers) - m_Camera = CompositionManager.AddNewCamera(m_LayerName); - } if (m_Camera == null) { m_Camera = CompositionManager.GetSceneCamera(); @@ -248,11 +242,11 @@ public void Init(string layerID = "") // We do not clone the camera if : // - it has no layer overrides // - is not shared between layers - // - it is an mage/video layer (in this case we use a brand-new camera that is not exposed at all and is managed by the compositor) + // - is not used in an mage/video layer (in this case the camera is not exposed at all, so it makes sense to let the compositor manage it) // - it does not force-clear the RT (the first layer of a stack, even if disabled by the user), still clears the RT bool shouldClear = !enabled && m_LayerPositionInStack == 0; - - if (isImageOrVideoLayer || (!hasLayerOverrides && !shouldClear && !compositor.IsThisCameraShared(m_Camera))) + bool isImageOrVideo = (m_Type == LayerType.Image || m_Type == LayerType.Video); + if (!isImageOrVideo && !hasLayerOverrides && !shouldClear && !compositor.IsThisCameraShared(m_Camera)) { m_LayerCamera = m_Camera; } @@ -420,7 +414,7 @@ public void DestroyCameras() // We should destroy the layer camera only if it was cloned if (m_LayerCamera != null) { - if (isUsingACameraClone || isImageOrVideoLayer) + if (isUsingACameraClone) { var cameraData = m_LayerCamera.GetComponent(); if (cameraData) diff --git a/com.unity.render-pipelines.high-definition/Runtime/Compositor/CompositionManager.cs b/com.unity.render-pipelines.high-definition/Runtime/Compositor/CompositionManager.cs index fed4c3b3dbc..d1269b3188d 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Compositor/CompositionManager.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Compositor/CompositionManager.cs @@ -843,19 +843,6 @@ static public Camera GetSceneCamera() return null; } - static public Camera AddNewCamera(string cameraName) - { - var newCameraGameObject = new GameObject(cameraName) - { - hideFlags = HideFlags.HideInInspector | HideFlags.HideInHierarchy | HideFlags.HideAndDontSave - }; - - var camera = newCameraGameObject.AddComponent(); - newCameraGameObject.AddComponent(); - - return camera; - } - static public CompositionManager GetInstance() => s_CompositorInstance ?? (s_CompositorInstance = GameObject.FindObjectOfType(typeof(CompositionManager), true) as CompositionManager); From 65ab6147a534452715eb51fd9bade96761382f6c Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Thu, 12 Nov 2020 18:16:53 +0100 Subject: [PATCH 4/5] Update changelog --- com.unity.render-pipelines.high-definition/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/com.unity.render-pipelines.high-definition/CHANGELOG.md b/com.unity.render-pipelines.high-definition/CHANGELOG.md index c91b6526b68..105a1c43880 100644 --- a/com.unity.render-pipelines.high-definition/CHANGELOG.md +++ b/com.unity.render-pipelines.high-definition/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Fixed - Fixed probe volumes debug views. +- Fixed issue with image layers in the graphics compositor (case 1289936). ## [10.2.0] - 2020-10-19 From 2ae75b033e1c62fbd529e846b00c0a4ce7b91f5a Mon Sep 17 00:00:00 2001 From: Pavlos Mavridis Date: Thu, 12 Nov 2020 19:26:50 +0100 Subject: [PATCH 5/5] For image layers that are first, still clear to black if no texture is attached --- .../Runtime/Compositor/CompositionLayer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/Compositor/CompositionLayer.cs b/com.unity.render-pipelines.high-definition/Runtime/Compositor/CompositionLayer.cs index 29e9014978e..416bb946bdd 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Compositor/CompositionLayer.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Compositor/CompositionLayer.cs @@ -552,7 +552,7 @@ public void UpdateOutputCamera() { var compositorData = m_LayerCamera.GetComponent(); if (compositorData) - compositorData.clearColorTexture = (m_Show && m_InputTexture != null) ? m_InputTexture : null; + compositorData.clearColorTexture = (m_Show && m_InputTexture != null) ? m_InputTexture : (m_LayerPositionInStack == 0) ? Texture2D.blackTexture : null; } if (m_LayerCamera.enabled)