diff --git a/com.unity.render-pipelines.universal/CHANGELOG.md b/com.unity.render-pipelines.universal/CHANGELOG.md index 1321dfa45da..6f1c941de97 100644 --- a/com.unity.render-pipelines.universal/CHANGELOG.md +++ b/com.unity.render-pipelines.universal/CHANGELOG.md @@ -22,6 +22,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - UNITY_Z_0_FAR_FROM_CLIPSPACE now remaps to [0, far] range on all platforms consistently. Previously OpenGL platforms did not remap, discarding small amount of range [-near, 0]. - ClearFlag.Depth does not implicitely clear stencil anymore. ClearFlag.Stencil added. - The Forward Renderer asset is renamed to the Universal Renderer asset. The Universal Renderer asset contains the property Rendering Path that lets you select the Forward or the Deferred Rendering Path. +- Improved PixelPerfectCamera UI/UX +- Changed Pixel Snapping and Upscale Render Texture in the PixelPerfectCamera to a dropdown. - Move Assets/Create/Rendering/Universal Render Pipeline/Pipeline Asset (2D Renderer) to Assets/Create/Rendering/URP Asset (with 2D Renderer) - Move Assets/Create/Rendering/Universal Render Pipeline/2D Renderer to Assets/Create/Rendering/URP 2D Renderer - Move Assets/Create/Rendering/Universal Render Pipeline/Renderer Feature to Assets/Create/Rendering/URP Renderer Feature diff --git a/com.unity.render-pipelines.universal/Documentation~/2d-pixelperfect.md b/com.unity.render-pipelines.universal/Documentation~/2d-pixelperfect.md index e68fa486eb1..3ba707517ce 100644 --- a/com.unity.render-pipelines.universal/Documentation~/2d-pixelperfect.md +++ b/com.unity.render-pipelines.universal/Documentation~/2d-pixelperfect.md @@ -59,12 +59,9 @@ The component's Inspector window | --- | --- | |__Asset Pixels Per Unit__|This is the amount of pixels that make up one unit of the Scene. Match this value to the __Pixels Per Unit__ values of all Sprites in the Scene.| |__Reference Resolution__|This is the original resolution your Assets are designed for.| -|__Upscale Render Texture__|Enable this property to create a temporary rendered texture of the Scene close-to or at the Reference Resolution, which is then upscaled.| -|__Pixel Snapping (only available when ‘Upscale Render Texture’ is disabled)__|Enable this feature to snap __Sprite Renderers__ to a grid in world space at render-time. The grid size is based on the Assets’ __Pixels Per Unit__ value.| -|__Crop Frame__|Crops the viewport with black bars to match the Reference Resolution along the checked axis. Check X to add horizontal black bars, and Y to add vertical black bars. For more information and a visual example, refer to the Property Details below.| -|__Stretch Fill (available when both X and Y are checked)__|Enable to expand the viewport to fit the screen resolution while maintaining the viewport's aspect ratio.| -|__Run In Edit Mode__| Enable this checkbox to preview Camera setting changes in Edit Mode. This causes constant changes to the Scene while active. | -|__Current Pixel Ratio (available when ‘Run In Edit Mode’ is enabled)__|Shows the size ratio of the rendered Sprites compared to their original size.| +|__Crop Frame__| Describes what to do when there is a difference in aspect ratio. +|__Grid Snapping__| Describes how to handle snapping. +|__Current Pixel Ratio__|Shows the size ratio of the rendered Sprites compared to their original size.| ## Additional Property Details @@ -72,7 +69,9 @@ The component's Inspector window This is the original resolution your Assets are designed for. Scaling up Scenes and Assets from this resolution preserves your pixel art cleanly at higher resolutions. -### Upscale Render Texture + +### Grid Snapping +#### Upscale Render Texture By default, the Scene is rendered at the pixel perfect resolution closest to the full screen resolution. @@ -82,7 +81,7 @@ Enable this option to have the Scene rendered to a temporary texture set as clos The result is unaliased and unrotated pixels, which may be a desirable visual style for certain game projects. -### Pixel Snapping +#### Pixel Snapping Enable this feature to snap Sprite Renderers to a grid in world space at render-time. The grid size is based on the __Assets Pixels Per Unit__ value. @@ -90,7 +89,7 @@ __Pixel Snapping__ prevents subpixel movement and make Sprites appear to move in ### Crop Frame -Crops the viewport along the checked axis with black bars to match the __Reference Resolution__. Black bars are added to make the Game view fit the full screen resolution. +Crops the viewport based on the option selected, adding black bars to match the __Reference Resolution__. Black bars are added to make the Game view fit the full screen resolution. | ![Uncropped cat](Images/2D/2D_Pix_image_8.png) | ![Cropped cat](Images/2D/2D_Pix_image_9.png) | | :--------------------------------------------: | :------------------------------------------: | diff --git a/com.unity.render-pipelines.universal/Documentation~/Images/2D/2D_Pix_image_6.png b/com.unity.render-pipelines.universal/Documentation~/Images/2D/2D_Pix_image_6.png index 4dfe77a6b5a..2e1be1c5c61 100644 --- a/com.unity.render-pipelines.universal/Documentation~/Images/2D/2D_Pix_image_6.png +++ b/com.unity.render-pipelines.universal/Documentation~/Images/2D/2D_Pix_image_6.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9478560d6cf23e487f5d590b13f9af32f73bbc3571b959aa84de7ac365d5bff1 -size 8082 +oid sha256:b0456981bb66b410bd1bb4dd7fe22c7b8f292ada03c36e05290f9da31b9d49f4 +size 25126 diff --git a/com.unity.render-pipelines.universal/Editor/2D/PixelPerfectCameraEditor.cs b/com.unity.render-pipelines.universal/Editor/2D/PixelPerfectCameraEditor.cs index 076c3d3a1e2..51f279eadae 100644 --- a/com.unity.render-pipelines.universal/Editor/2D/PixelPerfectCameraEditor.cs +++ b/com.unity.render-pipelines.universal/Editor/2D/PixelPerfectCameraEditor.cs @@ -14,13 +14,13 @@ private class Style public GUIContent y = new GUIContent("Y"); public GUIContent assetsPPU = new GUIContent("Assets Pixels Per Unit", "The amount of pixels that make up one unit of the Scene. Set this value to match the PPU value of Sprites in the Scene."); public GUIContent refRes = new GUIContent("Reference Resolution", "The original resolution the Assets are designed for."); - public GUIContent upscaleRT = new GUIContent("Upscale Render Texture", "If enabled, the Scene is rendered as close as possible to the Reference Resolution while maintaining the screen aspect ratio, then upscaled to fit the full screen."); - public GUIContent pixelSnapping = new GUIContent("Pixel Snapping", "If enabled, Sprite Renderers are snapped to a grid in world space at render-time. Grid size is based on the Assets Pixels Per Unit value. This does not affect GameObjects' Transform positions."); + public GUIContent gridSnapping = new GUIContent("Grid Snapping", "Sets the snapping behavior for the camera and sprites."); public GUIContent cropFrame = new GUIContent("Crop Frame", "Crops the viewport to match the Reference Resolution, along the checked axis. Black bars will be added to fit the screen aspect ratio."); public GUIContent stretchFill = new GUIContent("Stretch Fill", "If enabled, expands the viewport to fit the screen resolution while maintaining the viewport aspect ratio."); public GUIContent currentPixelRatio = new GUIContent("Current Pixel Ratio", "Ratio of the rendered Sprites compared to their original size."); public GUIContent runInEditMode = new GUIContent("Run In Edit Mode", "Enable this to preview Camera setting changes in Edit Mode. This will cause constant changes to the Scene while active."); public const string cameraStackingWarning = "Pixel Perfect Camera won't function properly if stacked with another camera."; + public const string nonRenderer2DError = "Pixel Perfect Camera requires a camera using a 2D Renderer."; public GUIStyle centeredLabel; @@ -39,11 +39,8 @@ public Style() private SerializedProperty m_AssetsPPU; private SerializedProperty m_RefResX; private SerializedProperty m_RefResY; - private SerializedProperty m_UpscaleRT; - private SerializedProperty m_PixelSnapping; - private SerializedProperty m_CropFrameY; - private SerializedProperty m_CropFrameX; - private SerializedProperty m_StretchFill; + private SerializedProperty m_CropFrame; + private SerializedProperty m_GridSnapping; private Vector2 m_GameViewSize = Vector2.zero; private GUIContent m_CurrentPixelRatioValue; @@ -58,6 +55,22 @@ private void LazyInit() m_CurrentPixelRatioValue = new GUIContent(); } + bool UsingRenderer2D() + { + PixelPerfectCamera obj = target as PixelPerfectCamera; + UniversalAdditionalCameraData cameraData = null; + obj?.TryGetComponent(out cameraData); + + if (cameraData != null) + { + Renderer2D renderer2D = cameraData.scriptableRenderer as Renderer2D; + if (renderer2D != null) + return true; + } + + return false; + } + void CheckForCameraStacking() { m_CameraStacking = false; @@ -83,11 +96,8 @@ public void OnEnable() m_AssetsPPU = serializedObject.FindProperty("m_AssetsPPU"); m_RefResX = serializedObject.FindProperty("m_RefResolutionX"); m_RefResY = serializedObject.FindProperty("m_RefResolutionY"); - m_UpscaleRT = serializedObject.FindProperty("m_UpscaleRT"); - m_PixelSnapping = serializedObject.FindProperty("m_PixelSnapping"); - m_CropFrameY = serializedObject.FindProperty("m_CropFrameY"); - m_CropFrameX = serializedObject.FindProperty("m_CropFrameX"); - m_StretchFill = serializedObject.FindProperty("m_StretchFill"); + m_CropFrame = serializedObject.FindProperty("m_CropFrame"); + m_GridSnapping = serializedObject.FindProperty("m_GridSnapping"); } public override bool RequiresConstantRepaint() @@ -111,6 +121,12 @@ public override void OnInspectorGUI() { LazyInit(); + if (!UsingRenderer2D()) + { + EditorGUILayout.HelpBox(Style.nonRenderer2DError, MessageType.Error); + return; + } + float originalLabelWidth = EditorGUIUtility.labelWidth; serializedObject.Update(); @@ -143,31 +159,9 @@ public override void OnInspectorGUI() } EditorGUILayout.EndHorizontal(); - EditorGUILayout.PropertyField(m_UpscaleRT, m_Style.upscaleRT); - if (!m_UpscaleRT.boolValue) - { - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(m_PixelSnapping, m_Style.pixelSnapping); - EditorGUI.indentLevel--; - } + EditorGUILayout.PropertyField(m_CropFrame, m_Style.cropFrame); + EditorGUILayout.PropertyField(m_GridSnapping, m_Style.gridSnapping); - EditorGUILayout.BeginHorizontal(); - { - EditorGUILayout.PrefixLabel(m_Style.cropFrame); - - EditorGUIUtility.labelWidth = k_SingleLetterLabelWidth * (EditorGUI.indentLevel + 1); - EditorGUILayout.PropertyField(m_CropFrameX, m_Style.x, GUILayout.MaxWidth(40.0f)); - EditorGUILayout.PropertyField(m_CropFrameY, m_Style.y); - EditorGUIUtility.labelWidth = originalLabelWidth; - } - EditorGUILayout.EndHorizontal(); - - if (m_CropFrameY.boolValue && m_CropFrameX.boolValue) - { - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(m_StretchFill, m_Style.stretchFill); - EditorGUI.indentLevel--; - } serializedObject.ApplyModifiedProperties(); @@ -175,24 +169,6 @@ public override void OnInspectorGUI() if (obj != null) { - EditorGUI.BeginDisabledGroup(EditorApplication.isPlaying || !obj.isActiveAndEnabled); - EditorGUI.BeginChangeCheck(); - - bool runInEditMode = EditorGUILayout.Toggle(obj.runInEditMode, GUI.skin.button, GUILayout.Width(110.0f)); - GUI.Label(GUILayoutUtility.GetLastRect(), m_Style.runInEditMode, m_Style.centeredLabel); - - if (EditorGUI.EndChangeCheck()) - { - obj.runInEditMode = runInEditMode; - - if (runInEditMode) - obj.GetComponent().Render(); - else - obj.OnDisable(); - } - - EditorGUI.EndDisabledGroup(); - if (obj.isActiveAndEnabled && (EditorApplication.isPlaying || obj.runInEditMode)) { if (Event.current.type == EventType.Layout) @@ -222,17 +198,17 @@ void OnSceneGUI() float verticalOrthoSize; float horizontalOrthoSize; - if (obj.cropFrameY && obj.cropFrameX) + if (obj.cropFrame == PixelPerfectCamera.CropFrame.StretchFill || obj.cropFrame == PixelPerfectCamera.CropFrame.Windowbox) { verticalOrthoSize = obj.refResolutionY * 0.5f / obj.assetsPPU; horizontalOrthoSize = verticalOrthoSize * ((float)obj.refResolutionX / obj.refResolutionY); } - else if (obj.cropFrameY) + else if (obj.cropFrame == PixelPerfectCamera.CropFrame.Letterbox) { verticalOrthoSize = obj.refResolutionY * 0.5f / obj.assetsPPU; horizontalOrthoSize = verticalOrthoSize * ((float)gameViewWidth / (zoom * obj.refResolutionY)); } - else if (obj.cropFrameX) + else if (obj.cropFrame == PixelPerfectCamera.CropFrame.Pillarbox) { horizontalOrthoSize = obj.refResolutionX * 0.5f / obj.assetsPPU; verticalOrthoSize = horizontalOrthoSize / (zoom * obj.refResolutionX / (float)gameViewHeight); diff --git a/com.unity.render-pipelines.universal/Editor/Camera/UniversalRenderPipelineCameraEditor.cs b/com.unity.render-pipelines.universal/Editor/Camera/UniversalRenderPipelineCameraEditor.cs index 290158a8576..1e624e49f6c 100644 --- a/com.unity.render-pipelines.universal/Editor/Camera/UniversalRenderPipelineCameraEditor.cs +++ b/com.unity.render-pipelines.universal/Editor/Camera/UniversalRenderPipelineCameraEditor.cs @@ -542,7 +542,20 @@ void DrawCommonSettings() m_CommonCameraSettingsFoldout.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_CommonCameraSettingsFoldout.value, Styles.projectionSettingsText); if (m_CommonCameraSettingsFoldout.value) { - settings.DrawProjection(); + UnityEngine.Experimental.Rendering.Universal.PixelPerfectCamera pixelPerfectCamera; + camera.TryGetComponent(out pixelPerfectCamera); + bool pixelPerfectEnabled = pixelPerfectCamera != null && pixelPerfectCamera.enabled; + + if (pixelPerfectEnabled) + { + EditorGUILayout.HelpBox(Styles.pixelPerfectInfo, MessageType.Info); + EditorGUI.BeginDisabledGroup(true); + settings.DrawProjection(); + EditorGUI.EndDisabledGroup(); + } + else + settings.DrawProjection(); + settings.DrawClippingPlanes(); EditorGUILayout.Space(); EditorGUILayout.Space(); diff --git a/com.unity.render-pipelines.universal/Editor/Camera/UniversalRenderPipelineCameraUI.Skin.cs b/com.unity.render-pipelines.universal/Editor/Camera/UniversalRenderPipelineCameraUI.Skin.cs index 5eb9a792408..91b2ef4d801 100644 --- a/com.unity.render-pipelines.universal/Editor/Camera/UniversalRenderPipelineCameraUI.Skin.cs +++ b/com.unity.render-pipelines.universal/Editor/Camera/UniversalRenderPipelineCameraUI.Skin.cs @@ -56,6 +56,8 @@ public class Styles public static readonly string noRendererError = "There are no valid Renderers available on the Universal Render Pipeline asset."; public static readonly string disabledPostprocessing = "Post Processing is currently disabled on the current Universal Render Pipeline renderer."; + public static readonly string pixelPerfectInfo = "Projection settings have been overriden by the Pixel Perfect Camera."; + public static GUIContent[] cameraBackgroundType = { EditorGUIUtility.TrTextContent("Skybox"), diff --git a/com.unity.render-pipelines.universal/Runtime/2D/Passes/PixelPerfectBackgroundPass.cs b/com.unity.render-pipelines.universal/Runtime/2D/Passes/PixelPerfectBackgroundPass.cs index 9f236e3f41a..8289518b570 100644 --- a/com.unity.render-pipelines.universal/Runtime/2D/Passes/PixelPerfectBackgroundPass.cs +++ b/com.unity.render-pipelines.universal/Runtime/2D/Passes/PixelPerfectBackgroundPass.cs @@ -9,12 +9,20 @@ namespace UnityEngine.Experimental.Rendering.Universal internal class PixelPerfectBackgroundPass : ScriptableRenderPass { private static readonly ProfilingSampler m_ProfilingScope = new ProfilingSampler("Pixel Perfect Background Pass"); + private bool m_SavedIsOrthographic; + private float m_SavedOrthographicSize; public PixelPerfectBackgroundPass(RenderPassEvent evt) { renderPassEvent = evt; } + public void Setup(bool savedIsOrthographic, float savedOrthographicSize) + { + m_SavedIsOrthographic = savedIsOrthographic; + m_SavedOrthographicSize = savedOrthographicSize; + } + public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { var cmd = CommandBufferPool.Get(); @@ -30,8 +38,12 @@ public override void Execute(ScriptableRenderContext context, ref RenderingData Color.black); } + context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); + + renderingData.cameraData.camera.orthographic = m_SavedIsOrthographic; + renderingData.cameraData.camera.orthographicSize = m_SavedOrthographicSize; } } } diff --git a/com.unity.render-pipelines.universal/Runtime/2D/PixelPerfectCamera.cs b/com.unity.render-pipelines.universal/Runtime/2D/PixelPerfectCamera.cs index 903fbbccbd4..d2906dc4b71 100644 --- a/com.unity.render-pipelines.universal/Runtime/2D/PixelPerfectCamera.cs +++ b/com.unity.render-pipelines.universal/Runtime/2D/PixelPerfectCamera.cs @@ -7,13 +7,47 @@ namespace UnityEngine.Experimental.Rendering.Universal /// /// The Pixel Perfect Camera component ensures your pixel art remains crisp and clear at different resolutions, and stable in motion. /// + [ExecuteInEditMode] [DisallowMultipleComponent] [AddComponentMenu("Rendering/2D/Pixel Perfect Camera (Experimental)")] [RequireComponent(typeof(Camera))] [MovedFrom("UnityEngine.Experimental.Rendering.LWRP")] [HelpURL("https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@latest/index.html?subfolder=/manual/2d-pixelperfect.html%23properties")] - public class PixelPerfectCamera : MonoBehaviour, IPixelPerfectCamera + public class PixelPerfectCamera : MonoBehaviour, IPixelPerfectCamera, ISerializationCallbackReceiver { + public enum CropFrame + { + None, + Pillarbox, + Letterbox, + Windowbox, + StretchFill + } + + public enum GridSnapping + { + None, + PixelSnapping, + UpscaleRenderTexture + } + + public enum ComponentVersions + { + Version_Unserialized = 0, + Version_1 = 1 + } + + +#if UNITY_EDITOR + const ComponentVersions k_CurrentComponentVersion = ComponentVersions.Version_1; + [SerializeField] ComponentVersions m_ComponentVersion = ComponentVersions.Version_Unserialized; +#endif + + public CropFrame cropFrame { get { return m_CropFrame; } set { m_CropFrame = value; } } + public GridSnapping gridSnapping { get { return m_GridSnapping;} set { m_GridSnapping = value; } } + + public float orthographicSize { get { return m_Internal.orthoSize; } } + /// /// Match this value to to the Pixels Per Unit values of all Sprites within the Scene. /// @@ -33,29 +67,113 @@ public class PixelPerfectCamera : MonoBehaviour, IPixelPerfectCamera /// Set to true to have the Scene rendered to a temporary texture set as close as possible to the Reference Resolution, /// while maintaining the full screen aspect ratio. This temporary texture is then upscaled to fit the full screen. /// - public bool upscaleRT { get { return m_UpscaleRT; } set { m_UpscaleRT = value; } } + [System.Obsolete("Use gridSnapping instead", false)] + public bool upscaleRT + { + get + { + return m_GridSnapping == GridSnapping.UpscaleRenderTexture; + } + set + { + m_GridSnapping = value ? GridSnapping.UpscaleRenderTexture : GridSnapping.None; + } + } /// /// Set to true to prevent subpixel movement and make Sprites appear to move in pixel-by-pixel increments. /// Only applicable when upscaleRT is false. /// - public bool pixelSnapping { get { return m_PixelSnapping; } set { m_PixelSnapping = value; } } + [System.Obsolete("Use gridSnapping instead", false)] + public bool pixelSnapping + { + get + { + return m_GridSnapping == GridSnapping.PixelSnapping; + } + set + { + m_GridSnapping = value ? GridSnapping.PixelSnapping : GridSnapping.None; + } + } /// /// Set to true to crop the viewport with black bars to match refResolutionX in the horizontal direction. /// - public bool cropFrameX { get { return m_CropFrameX; } set { m_CropFrameX = value; } } + [System.Obsolete("Use cropFrame instead", false)] + public bool cropFrameX + { + get + { + return m_CropFrame == CropFrame.StretchFill || m_CropFrame == CropFrame.Windowbox || m_CropFrame == CropFrame.Pillarbox; + } + set + { + if (value) + { + if (m_CropFrame == CropFrame.None) + m_CropFrame = CropFrame.Pillarbox; + else if (m_CropFrame == CropFrame.Letterbox) + m_CropFrame = CropFrame.Windowbox; + } + else + { + if (m_CropFrame == CropFrame.Pillarbox) + m_CropFrame = CropFrame.None; + else if (m_CropFrame == CropFrame.Windowbox || m_CropFrame == CropFrame.StretchFill) + m_CropFrame = CropFrame.Letterbox; + } + } + } /// /// Set to true to crop the viewport with black bars to match refResolutionY in the vertical direction. /// - public bool cropFrameY { get { return m_CropFrameY; } set { m_CropFrameY = value; } } + [System.Obsolete("Use cropFrame instead", false)] + public bool cropFrameY + { + get + { + return m_CropFrame == CropFrame.StretchFill || m_CropFrame == CropFrame.Windowbox || m_CropFrame == CropFrame.Letterbox; + } + set + { + if (value) + { + if (m_CropFrame == CropFrame.None) + m_CropFrame = CropFrame.Letterbox; + else if (m_CropFrame == CropFrame.Pillarbox) + m_CropFrame = CropFrame.Windowbox; + } + else + { + if (m_CropFrame == CropFrame.Letterbox) + m_CropFrame = CropFrame.None; + else if (m_CropFrame == CropFrame.Windowbox || m_CropFrame == CropFrame.StretchFill) + m_CropFrame = CropFrame.Pillarbox; + } + } + } /// /// Set to true to expand the viewport to fit the screen resolution while maintaining the viewport's aspect ratio. /// Only applicable when both cropFrameX and cropFrameY are true. /// - public bool stretchFill { get { return m_StretchFill; } set { m_StretchFill = value; } } + [System.Obsolete("Use cropFrame instead", false)] + public bool stretchFill + { + get + { + return m_CropFrame == CropFrame.StretchFill; + } + set + { + if (value) + m_CropFrame = CropFrame.StretchFill; + else + m_CropFrame = CropFrame.Windowbox; + } + } /// /// Ratio of the rendered Sprites compared to their original size (readonly). @@ -66,7 +184,7 @@ public int pixelRatio { if (m_CinemachineCompatibilityMode) { - if (m_UpscaleRT) + if (m_GridSnapping == GridSnapping.UpscaleRenderTexture) return m_Internal.zoom * m_Internal.cinemachineVCamZoom; else return m_Internal.cinemachineVCamZoom; @@ -118,36 +236,28 @@ public float CorrectCinemachineOrthoSize(float targetOrthoSize) [SerializeField] int m_AssetsPPU = 100; [SerializeField] int m_RefResolutionX = 320; [SerializeField] int m_RefResolutionY = 180; - [SerializeField] bool m_UpscaleRT; - [SerializeField] bool m_PixelSnapping; - [SerializeField] bool m_CropFrameX; - [SerializeField] bool m_CropFrameY; - [SerializeField] bool m_StretchFill; - Camera m_Camera; - PixelPerfectCameraInternal m_Internal; - bool m_CinemachineCompatibilityMode; + [SerializeField] CropFrame m_CropFrame; + [SerializeField] GridSnapping m_GridSnapping; - internal bool isRunning - { - get - { + // These are obsolete. They are here only for migration. #if UNITY_EDITOR - return (Application.isPlaying || runInEditMode) && enabled; -#else - return enabled; + [SerializeField] bool m_UpscaleRT; + [SerializeField] bool m_PixelSnapping; + [SerializeField] bool m_CropFrameX; + [SerializeField] bool m_CropFrameY; + [SerializeField] bool m_StretchFill; #endif - } - } + + Camera m_Camera; + PixelPerfectCameraInternal m_Internal; + bool m_CinemachineCompatibilityMode; internal FilterMode finalBlitFilterMode { get { - if (!isRunning) - return FilterMode.Bilinear; - else - return m_Internal.useStretchFill ? FilterMode.Bilinear : FilterMode.Point; + return m_Internal.useStretchFill ? FilterMode.Bilinear : FilterMode.Point; } } @@ -155,10 +265,7 @@ internal Vector2Int offscreenRTSize { get { - if (!isRunning) - return Vector2Int.zero; - else - return new Vector2Int(m_Internal.offscreenRTWidth, m_Internal.offscreenRTHeight); + return new Vector2Int(m_Internal.offscreenRTWidth, m_Internal.offscreenRTHeight); } } @@ -188,7 +295,6 @@ void Awake() m_Camera = GetComponent(); m_Internal = new PixelPerfectCameraInternal(this); - m_Internal.originalOrthoSize = m_Camera.orthographicSize; // Case 1249076: Initialize internals immediately after the scene is loaded, // as the Cinemachine extension may need them before OnBeginContextRendering is called. @@ -208,10 +314,6 @@ void OnBeginContextRendering(ScriptableRenderContext context, List camer else m_Camera.rect = new Rect(0.0f, 0.0f, 1.0f, 1.0f); - // In Cinemachine compatibility mode the control over orthographic size should - // be given to the virtual cameras, whose orthographic sizes will be corrected to - // be pixel-perfect. This way when there's blending between virtual cameras, we - // can have temporary not-pixel-perfect but smooth transitions. if (!m_CinemachineCompatibilityMode) { m_Camera.orthographicSize = m_Internal.orthoSize; @@ -237,11 +339,6 @@ void OnEnable() RenderPipelineManager.beginContextRendering += OnBeginContextRendering; RenderPipelineManager.beginCameraRendering += OnBeginCameraRendering; RenderPipelineManager.endCameraRendering += OnEndCameraRendering; - -#if UNITY_EDITOR - if (!UnityEditor.EditorApplication.isPlaying) - UnityEditor.EditorApplication.playModeStateChanged += OnPlayModeChanged; -#endif } internal void OnDisable() @@ -251,24 +348,13 @@ internal void OnDisable() RenderPipelineManager.endCameraRendering -= OnEndCameraRendering; m_Camera.rect = new Rect(0.0f, 0.0f, 1.0f, 1.0f); - m_Camera.orthographicSize = m_Internal.originalOrthoSize; m_Camera.ResetWorldToCameraMatrix(); - -#if UNITY_EDITOR - if (!UnityEditor.EditorApplication.isPlaying) - UnityEditor.EditorApplication.playModeStateChanged -= OnPlayModeChanged; -#endif } #if DEVELOPMENT_BUILD || UNITY_EDITOR // Show on-screen warning about invalid render resolutions. void OnGUI() { -#if UNITY_EDITOR - if (!UnityEditor.EditorApplication.isPlaying && !runInEditMode) - return; -#endif - Color oldColor = GUI.color; GUI.color = Color.red; @@ -295,17 +381,48 @@ void OnGUI() #endif + + public void OnBeforeSerialize() + { #if UNITY_EDITOR - void OnPlayModeChanged(UnityEditor.PlayModeStateChange state) + m_ComponentVersion = k_CurrentComponentVersion; +#endif + } + + public void OnAfterDeserialize() { - // Stop running in edit mode when entering play mode. - if (state == UnityEditor.PlayModeStateChange.ExitingEditMode) +#if UNITY_EDITOR + // Upgrade from no serialized version + if (m_ComponentVersion == ComponentVersions.Version_Unserialized) { - runInEditMode = false; - OnDisable(); - } - } + if (m_UpscaleRT) + m_GridSnapping = GridSnapping.UpscaleRenderTexture; + else if (m_PixelSnapping) + m_GridSnapping = GridSnapping.PixelSnapping; + if (m_CropFrameX && m_CropFrameY) + { + if (m_StretchFill) + m_CropFrame = CropFrame.StretchFill; + else + m_CropFrame = CropFrame.Windowbox; + } + else if (m_CropFrameX) + { + m_CropFrame = CropFrame.Pillarbox; + } + else if (m_CropFrameY) + { + m_CropFrame = CropFrame.Letterbox; + } + else + { + m_CropFrame = CropFrame.None; + } + + m_ComponentVersion = ComponentVersions.Version_1; + } #endif + } } } diff --git a/com.unity.render-pipelines.universal/Runtime/2D/Renderer2D.cs b/com.unity.render-pipelines.universal/Runtime/2D/Renderer2D.cs index 394bd094aef..7477f884323 100644 --- a/com.unity.render-pipelines.universal/Runtime/2D/Renderer2D.cs +++ b/com.unity.render-pipelines.universal/Runtime/2D/Renderer2D.cs @@ -45,6 +45,7 @@ public Renderer2D(Renderer2DData data) : base(data) m_PixelPerfectBackgroundPass = new PixelPerfectBackgroundPass(RenderPassEvent.AfterRenderingTransparents); m_FinalBlitPass = new FinalBlitPass(RenderPassEvent.AfterRendering + 1, m_BlitMaterial); + m_PostProcessPasses = new PostProcessPasses(data.postProcessData, m_BlitMaterial); m_UseDepthStencilBuffer = data.useDepthStencilBuffer; @@ -156,6 +157,9 @@ public override void Setup(ScriptableRenderContext context, ref RenderingData re bool ppcUsesOffscreenRT = false; bool ppcUpscaleRT = false; + bool savedIsOrthographic = renderingData.cameraData.camera.orthographic; + float savedOrthographicSize = renderingData.cameraData.camera.orthographicSize; + if (DebugHandler != null) { if (DebugHandler.AreAnySettingsActive) @@ -181,7 +185,7 @@ public override void Setup(ScriptableRenderContext context, ref RenderingData re if (cameraData.renderType == CameraRenderType.Base && lastCameraInStack) { cameraData.camera.TryGetComponent(out ppc); - if (ppc != null) + if (ppc != null && ppc.enabled) { if (ppc.offscreenRTSize != Vector2Int.zero) { @@ -193,8 +197,11 @@ public override void Setup(ScriptableRenderContext context, ref RenderingData re cameraTargetDescriptor.height = ppc.offscreenRTSize.y; } + renderingData.cameraData.camera.orthographic = true; + renderingData.cameraData.camera.orthographicSize = ppc.orthographicSize; + colorTextureFilterMode = ppc.finalBlitFilterMode; - ppcUpscaleRT = ppc.upscaleRT && ppc.isRunning; + ppcUpscaleRT = ppc.gridSnapping == PixelPerfectCamera.GridSnapping.UpscaleRenderTexture; } } @@ -253,8 +260,11 @@ public override void Setup(ScriptableRenderContext context, ref RenderingData re colorTargetHandle = postProcessDestHandle; } - if (ppc != null && ppc.isRunning && (ppc.cropFrameX || ppc.cropFrameY)) + if (ppc != null && ppc.enabled && (ppc.cropFrame == PixelPerfectCamera.CropFrame.Pillarbox || ppc.cropFrame == PixelPerfectCamera.CropFrame.Letterbox || ppc.cropFrame == PixelPerfectCamera.CropFrame.Windowbox || ppc.cropFrame == PixelPerfectCamera.CropFrame.StretchFill)) + { + m_PixelPerfectBackgroundPass.Setup(savedIsOrthographic, savedOrthographicSize); EnqueuePass(m_PixelPerfectBackgroundPass); + } if (requireFinalPostProcessPass && m_PostProcessPasses.isCreated) {