diff --git a/.github/workflows/npmpublish.yml b/.github/workflows/npmpublish.yml index 9d54621..f5ac9f4 100644 --- a/.github/workflows/npmpublish.yml +++ b/.github/workflows/npmpublish.yml @@ -17,5 +17,6 @@ jobs: - run: | npm publish Outline.Core/Packages/UnityFx.Outline npm publish Outline.PostProcessing/Packages/UnityFx.Outline.PostProcessing + npm publish Outline.URP/Packages/UnityFx.Outline.URP env: NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} diff --git a/CHANGELOG.md b/CHANGELOG.md index 1498997..b1728fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,32 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/); this project adheres to [Semantic Versioning](http://semver.org/). +## [0.8.0] - 2020.05.30 + +[URP](https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@8.1/manual/index.html) support, core refactoring and bugfixes. + +### Added +- Added [URP](https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@8.1/manual/index.html) support ([#5](https://github.com/Arvtesh/UnityFx.Outline/issues/5)). +- Use procedural geometry ([DrawProcedural](https://docs.unity3d.com/ScriptReference/Rendering.CommandBuffer.DrawProcedural.html)) on SM3.5+. +- Added support for both forward and deferred renderers (built-in RP). +- Added ignore layer mask settings to `OutlineLayerCollection` (previously the ignore layers were specified when adding game objects to layers). +- Added `OutlineBuilder` helper script for managinf `OutlineLayerCollection` content from editor ([#8](https://github.com/Arvtesh/UnityFx.Outline/issues/8)). + +### Changed +- Changed `OutlineSettings` to display enum mask instead of checkboxes. +- Changed inspector look and feel for `OutlineLayerCollection` assets. +- Merged shaders for the 2 outline passes into one multi-pass shader. +- `OutlineLayerCollection` doe not depend on `OutlineRenderer` now. + +### Fixed +- Fixed outline rendering on mobiles ([#7](https://github.com/Arvtesh/UnityFx.Outline/issues/7)). +- Fixed outline shader error on low-end devices. +- Fixed post-ptocessing implementation to require depth texture. + +### Removed +- Dropped .NET 3.5 support, minimal Unity version is set to 2018.4. +- Removed `IOutlineSettingsEx` interface. + ## [0.7.2] - 2020.04.08 Depth testing support and performance optimizations. diff --git a/Docs/OutlineBehaviourInspector.png b/Docs/OutlineBehaviourInspector.png index 8ec031f..2a2a2b6 100644 Binary files a/Docs/OutlineBehaviourInspector.png and b/Docs/OutlineBehaviourInspector.png differ diff --git a/Docs/OutlineLayerCollectionInspector.png b/Docs/OutlineLayerCollectionInspector.png index 3dead01..ce77d67 100644 Binary files a/Docs/OutlineLayerCollectionInspector.png and b/Docs/OutlineLayerCollectionInspector.png differ diff --git a/Docs/PpOutlineSettings.png b/Docs/PpOutlineSettings.png new file mode 100644 index 0000000..3b3d686 Binary files /dev/null and b/Docs/PpOutlineSettings.png differ diff --git a/Docs/UrpOutlineSettings.png b/Docs/UrpOutlineSettings.png new file mode 100644 index 0000000..88d669d Binary files /dev/null and b/Docs/UrpOutlineSettings.png differ diff --git a/Outline.Core/Packages/UnityFx.Outline/Runtime/Shaders/OutlinePass2.shader.meta b/Outline.Core/Assets/Common.meta similarity index 56% rename from Outline.Core/Packages/UnityFx.Outline/Runtime/Shaders/OutlinePass2.shader.meta rename to Outline.Core/Assets/Common.meta index 5852e4b..5b070c8 100644 --- a/Outline.Core/Packages/UnityFx.Outline/Runtime/Shaders/OutlinePass2.shader.meta +++ b/Outline.Core/Assets/Common.meta @@ -1,8 +1,8 @@ fileFormatVersion: 2 -guid: 1df0cb1700e142f4ca3b28297d3957da -ShaderImporter: +guid: 3f19b0b14f634f941adfaa12f23064d8 +folderAsset: yes +DefaultImporter: externalObjects: {} - defaultTextures: [] userData: assetBundleName: assetBundleVariant: diff --git a/Outline.Core/Assets/Common/FpsCounter.cs b/Outline.Core/Assets/Common/FpsCounter.cs new file mode 100644 index 0000000..3e6e7b3 --- /dev/null +++ b/Outline.Core/Assets/Common/FpsCounter.cs @@ -0,0 +1,70 @@ +// Copyright (C) 2018-2020 Digimation. All rights reserved. +// See the LICENSE.md file in the project root for more information. + +using System; +using UnityEngine; + +/// +/// An FPS counter. +/// +/// +public class FpsCounter : MonoBehaviour +{ + private const float _updateInterval = 0.5F; + + private float _accum; + private int _frames; + private float _timeleft; + private float _fps; + + public float Fps => _fps; + + public static void RenderFps(float fps, string s, Rect rc) + { + var text = string.Format("{0}: {1:F2}", s, fps); + + if (fps < 10) + { + GUI.color = Color.red; + } + else if (fps < 30) + { + GUI.color = Color.yellow; + } + else + { + GUI.color = Color.green; + } + + GUI.Label(rc, text); + } + + private void OnEnable() + { + _accum = 0; + _frames = 0; + _timeleft = 0; + _fps = 0; + } + + private void Update() + { + _timeleft -= Time.deltaTime; + _accum += Time.timeScale / Time.deltaTime; + + ++_frames; + + if (_timeleft <= 0.0) + { + _fps = _accum / _frames; + _timeleft = _updateInterval; + _accum = 0.0F; + _frames = 0; + } + } + + private void OnGUI() + { + RenderFps(_fps, "FPS", new Rect(Screen.width - 80, 0, 80, 20)); + } +} diff --git a/Outline.Core/Assets/Tests/Editor/Scripts/OutlineRendererTests.cs.meta b/Outline.Core/Assets/Common/FpsCounter.cs.meta similarity index 83% rename from Outline.Core/Assets/Tests/Editor/Scripts/OutlineRendererTests.cs.meta rename to Outline.Core/Assets/Common/FpsCounter.cs.meta index dce56a7..5ec5174 100644 --- a/Outline.Core/Assets/Tests/Editor/Scripts/OutlineRendererTests.cs.meta +++ b/Outline.Core/Assets/Common/FpsCounter.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 0c4dcc61e824b6f4f8805dbe543d2997 +guid: c9e1f138162751048bdb3432e85d7a73 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Outline.Core/Assets/Examples/SimplePerCamera/Outline.unity b/Outline.Core/Assets/Examples/SimplePerCamera/Outline.unity index c172ec7..5a17553 100644 --- a/Outline.Core/Assets/Examples/SimplePerCamera/Outline.unity +++ b/Outline.Core/Assets/Examples/SimplePerCamera/Outline.unity @@ -191,8 +191,9 @@ GameObject: m_Component: - component: {fileID: 692811816} - component: {fileID: 692811815} + - component: {fileID: 692811813} - component: {fileID: 692811818} - - component: {fileID: 692811817} + - component: {fileID: 692811814} m_Layer: 0 m_Name: Main Camera m_TagString: MainCamera @@ -200,6 +201,36 @@ GameObject: m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 +--- !u!114 &692811813 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 692811812} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: c9e1f138162751048bdb3432e85d7a73, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!114 &692811814 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 692811812} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e746e776b0ae00d4a9d458b9430b95d7, type: 3} + m_Name: + m_EditorClassIdentifier: + _outlineLayers: {fileID: 11400000, guid: 3a6c3b3c5f6e3ad4ab8e09fc219865bd, type: 2} + _content: + - Go: {fileID: 1579373802} + LayerIndex: 0 + - Go: {fileID: 748173439} + LayerIndex: 1 --- !u!20 &692811815 Camera: m_ObjectHideFlags: 0 @@ -259,21 +290,6 @@ Transform: m_Father: {fileID: 0} m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &692811817 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 692811812} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 5a318c96b1bc1614683eccf7abd717a1, type: 3} - m_Name: - m_EditorClassIdentifier: - _outlineGos: - - {fileID: 1579373802} - - {fileID: 748173439} --- !u!114 &692811818 MonoBehaviour: m_ObjectHideFlags: 0 @@ -524,7 +540,8 @@ MonoBehaviour: _outlineWidth: 15 _outlineIntensity: 2 _outlineMode: 1 - _depthTestEnabled: 0 + _layerMask: 0 + _updateRenderers: 0 --- !u!23 &1789341923 MeshRenderer: m_ObjectHideFlags: 0 diff --git a/Outline.Core/Assets/Examples/SimplePerCamera/OutlineEffectBuilder.cs b/Outline.Core/Assets/Examples/SimplePerCamera/OutlineEffectBuilder.cs deleted file mode 100644 index 444b39c..0000000 --- a/Outline.Core/Assets/Examples/SimplePerCamera/OutlineEffectBuilder.cs +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (C) 2019-2020 Alexander Bogarsukov. All rights reserved. -// See the LICENSE.md file in the project root for more information. - -using System; -using UnityEngine; - -namespace UnityFx.Outline.Examples -{ - /// - /// Helperr class for managing outlines from editor. - /// - [RequireComponent(typeof(OutlineEffect))] - public class OutlineEffectBuilder : MonoBehaviour - { - #region data - -#pragma warning disable 0649 - - [SerializeField] - private GameObject[] _outlineGos; - -#pragma warning restore 0649 - - private OutlineEffect _outlineEffect; - private OutlineLayer _outlineLayer; - - #endregion - - #region MonoBehaviour - - private void Awake() - { - if (_outlineEffect == null) - { - _outlineEffect = GetComponent(); - } - - if (_outlineLayer == null) - { - if (_outlineEffect.OutlineLayers.Count > 0) - { - _outlineLayer = _outlineEffect.OutlineLayers[0]; - } - else - { - _outlineLayer = new OutlineLayer(); - _outlineEffect.OutlineLayers.Add(_outlineLayer); - } - } - - foreach (var go in _outlineGos) - { - if (go) - { - _outlineLayer.Add(go); - } - } - } - - private void OnValidate() - { - if (_outlineEffect == null) - { - _outlineEffect = GetComponent(); - } - - if (_outlineEffect.OutlineLayers.Count > 0) - { - _outlineLayer = _outlineEffect.OutlineLayers[0]; - } - else - { - _outlineLayer = new OutlineLayer(); - _outlineEffect.OutlineLayers.Add(_outlineLayer); - } - - foreach (var go in _outlineGos) - { - if (go) - { - _outlineLayer.Add(go); - } - } - } - - #endregion - } -} diff --git a/Outline.Core/Assets/Examples/SimplePerCamera/TestOutlineLayers.asset b/Outline.Core/Assets/Examples/SimplePerCamera/TestOutlineLayers.asset index 3de703c..0c2023b 100644 --- a/Outline.Core/Assets/Examples/SimplePerCamera/TestOutlineLayers.asset +++ b/Outline.Core/Assets/Examples/SimplePerCamera/TestOutlineLayers.asset @@ -20,8 +20,7 @@ MonoBehaviour: _outlineWidth: 5 _outlineIntensity: 2 _outlineMode: 0 - _name: - _zOrder: 0 + _name: My pretty layer _enabled: 1 - _settings: _outlineSettings: {fileID: 0} @@ -29,8 +28,7 @@ MonoBehaviour: _outlineWidth: 15 _outlineIntensity: 2 _outlineMode: 1 - _name: - _zOrder: 0 + _name: The second layer _enabled: 1 - _settings: _outlineSettings: {fileID: 0} @@ -38,6 +36,6 @@ MonoBehaviour: _outlineWidth: 4 _outlineIntensity: 2 _outlineMode: 0 - _name: - _zOrder: 0 + _name: The best layer _enabled: 1 + _layerMask: 2 diff --git a/Outline.Core/Assets/Tests/Editor/Scripts/Helpers/IOutlineSettingsExTests.cs b/Outline.Core/Assets/Tests/Editor/Scripts/Helpers/IOutlineSettingsExTests.cs deleted file mode 100644 index af05396..0000000 --- a/Outline.Core/Assets/Tests/Editor/Scripts/Helpers/IOutlineSettingsExTests.cs +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (C) 2019-2020 Alexander Bogarsukov. All rights reserved. -// See the LICENSE.md file in the project root for more information. - -using System; -using System.ComponentModel; -using UnityEngine; -using UnityEngine.TestTools; -using NUnit.Framework; - -namespace UnityFx.Outline -{ - public abstract class IOutlineSettingsExTests : IOutlineSettingsTests - { - private IOutlineSettingsEx _settings; - private IChangeTracking _changeTracking; - - protected void Init(IOutlineSettingsEx settings) - { - _settings = settings; - _changeTracking = settings as IChangeTracking; - base.Init(settings); - } - - [Test] - public void OutlineSettings_SetsValue() - { - var settings = ScriptableObject.CreateInstance(); - - try - { - _settings.OutlineSettings = settings; - - Assert.AreEqual(settings, _settings.OutlineSettings); - - _settings.OutlineSettings = null; - - Assert.IsNull(_settings.OutlineSettings); - } - finally - { - UnityEngine.Object.DestroyImmediate(settings); - } - } - - [Test] - public void OutlineSettings_SetsChanged() - { - if (_changeTracking != null) - { - var settings = ScriptableObject.CreateInstance(); - - try - { - _changeTracking.AcceptChanges(); - _settings.OutlineSettings = settings; - - Assert.IsTrue(_changeTracking.IsChanged); - } - finally - { - UnityEngine.Object.DestroyImmediate(settings); - } - } - } - - [Test] - public void OutlineSettings_DoesNotSetsChangedOnSameValue() - { - if (_changeTracking != null) - { - _changeTracking.AcceptChanges(); - _settings.OutlineSettings = _settings.OutlineSettings; - - Assert.IsFalse(_changeTracking.IsChanged); - } - } - - [Test] - public void OutlineSettings_MakesOtherSettersThrow() - { - var settings = ScriptableObject.CreateInstance(); - - try - { - _settings.OutlineSettings = settings; - - Assert.Throws(() => _settings.OutlineColor = Color.blue); - Assert.Throws(() => _settings.OutlineWidth = 12); - Assert.Throws(() => _settings.OutlineRenderMode = OutlineRenderFlags.Blurred); - Assert.Throws(() => _settings.OutlineIntensity = 17); - } - finally - { - UnityEngine.Object.DestroyImmediate(settings); - } - } - } -} diff --git a/Outline.Core/Assets/Tests/Editor/Scripts/Helpers/IOutlineSettingsTests.cs b/Outline.Core/Assets/Tests/Editor/Scripts/Helpers/IOutlineSettingsTests.cs index 55a2687..805662e 100644 --- a/Outline.Core/Assets/Tests/Editor/Scripts/Helpers/IOutlineSettingsTests.cs +++ b/Outline.Core/Assets/Tests/Editor/Scripts/Helpers/IOutlineSettingsTests.cs @@ -56,14 +56,14 @@ public void OutlineColor_DoesNotSetsChangedOnSameValue() [Test] public void OutlineWidth_DefaultValueIsValid() { - Assert.LessOrEqual(OutlineRenderer.MinWidth, _settings.OutlineWidth); - Assert.GreaterOrEqual(OutlineRenderer.MaxWidth, _settings.OutlineWidth); + Assert.LessOrEqual(OutlineResources.MinWidth, _settings.OutlineWidth); + Assert.GreaterOrEqual(OutlineResources.MaxWidth, _settings.OutlineWidth); } [Test] public void OutlineWidth_SetsValue() { - var width = UnityEngine.Random.Range(OutlineRenderer.MinWidth, OutlineRenderer.MaxWidth); + var width = UnityEngine.Random.Range(OutlineResources.MinWidth, OutlineResources.MaxWidth); _settings.OutlineWidth = width; Assert.AreEqual(width, _settings.OutlineWidth); @@ -74,11 +74,11 @@ public void OutlineWidth_ClampsValue() { _settings.OutlineWidth = 1000; - Assert.AreEqual(OutlineRenderer.MaxWidth, _settings.OutlineWidth); + Assert.AreEqual(OutlineResources.MaxWidth, _settings.OutlineWidth); _settings.OutlineWidth = -1000; - Assert.AreEqual(OutlineRenderer.MinWidth, _settings.OutlineWidth); + Assert.AreEqual(OutlineResources.MinWidth, _settings.OutlineWidth); } [Test] @@ -111,8 +111,8 @@ public void OutlineMode_SetsValue() _settings.OutlineRenderMode = OutlineRenderFlags.Blurred; Assert.AreEqual(OutlineRenderFlags.Blurred, _settings.OutlineRenderMode); - _settings.OutlineRenderMode = OutlineRenderFlags.Solid; - Assert.AreEqual(OutlineRenderFlags.Solid, _settings.OutlineRenderMode); + _settings.OutlineRenderMode = OutlineRenderFlags.None; + Assert.AreEqual(OutlineRenderFlags.None, _settings.OutlineRenderMode); } [Test] @@ -142,14 +142,14 @@ public void OutlineMode_DoesNotSetsChangedOnSameValue() [Test] public void OutlineIntensity_DefaultValueIsValid() { - Assert.LessOrEqual(OutlineRenderer.MinIntensity, _settings.OutlineIntensity); - Assert.GreaterOrEqual(OutlineRenderer.MaxIntensity, _settings.OutlineIntensity); + Assert.LessOrEqual(OutlineResources.MinIntensity, _settings.OutlineIntensity); + Assert.GreaterOrEqual(OutlineResources.MaxIntensity, _settings.OutlineIntensity); } [Test] public void OutlineIntensity_SetsValue() { - var intensity = UnityEngine.Random.Range(OutlineRenderer.MinIntensity, OutlineRenderer.MaxIntensity); + var intensity = UnityEngine.Random.Range(OutlineResources.MinIntensity, OutlineResources.MaxIntensity); _settings.OutlineIntensity = intensity; @@ -161,11 +161,11 @@ public void OutlineIntensity_ClampsValue() { _settings.OutlineIntensity = 1000; - Assert.AreEqual(OutlineRenderer.MaxIntensity, _settings.OutlineIntensity); + Assert.AreEqual(OutlineResources.MaxIntensity, _settings.OutlineIntensity); _settings.OutlineIntensity = -1000; - Assert.AreEqual(OutlineRenderer.MinIntensity, _settings.OutlineIntensity); + Assert.AreEqual(OutlineResources.MinIntensity, _settings.OutlineIntensity); } [Test] diff --git a/Outline.Core/Assets/Tests/Editor/Scripts/OutlineBehaviourTests.cs b/Outline.Core/Assets/Tests/Editor/Scripts/OutlineBehaviourTests.cs index 02c4202..1fe501f 100644 --- a/Outline.Core/Assets/Tests/Editor/Scripts/OutlineBehaviourTests.cs +++ b/Outline.Core/Assets/Tests/Editor/Scripts/OutlineBehaviourTests.cs @@ -11,7 +11,7 @@ namespace UnityFx.Outline { [Category("OutlineBehaviour"), TestOf(typeof(OutlineBehaviour))] - public class OutlineBehaviourTests : IOutlineSettingsExTests, IDisposable + public class OutlineBehaviourTests : IOutlineSettingsTests, IDisposable { private GameObject _go; private OutlineBehaviour _outlineEffect; diff --git a/Outline.Core/Assets/Tests/Editor/Scripts/OutlineLayerCollectionTests.cs b/Outline.Core/Assets/Tests/Editor/Scripts/OutlineLayerCollectionTests.cs index fc19adb..1629d5c 100644 --- a/Outline.Core/Assets/Tests/Editor/Scripts/OutlineLayerCollectionTests.cs +++ b/Outline.Core/Assets/Tests/Editor/Scripts/OutlineLayerCollectionTests.cs @@ -140,25 +140,5 @@ public void Contains_SearchesArgument() Assert.IsTrue(_layerCollection.Contains(layer)); } - - [Test] - public void SortedLayers_IsSortedByPriority() - { - var layer1 = new OutlineLayer() - { - Priority = 2 - }; - - var layer2 = new OutlineLayer(); - var layer3 = new OutlineLayer(); - - _layerCollection.Add(layer1); - _layerCollection.Add(layer2); - _layerCollection.Add(layer3); - - Assert.AreEqual(layer2, _layerCollection.SortedLayers[0]); - Assert.AreEqual(layer3, _layerCollection.SortedLayers[1]); - Assert.AreEqual(layer1, _layerCollection.SortedLayers[2]); - } } } diff --git a/Outline.Core/Assets/Tests/Editor/Scripts/OutlineLayerTests.cs b/Outline.Core/Assets/Tests/Editor/Scripts/OutlineLayerTests.cs index df639c6..e6d4eb2 100644 --- a/Outline.Core/Assets/Tests/Editor/Scripts/OutlineLayerTests.cs +++ b/Outline.Core/Assets/Tests/Editor/Scripts/OutlineLayerTests.cs @@ -11,7 +11,7 @@ namespace UnityFx.Outline { [Category("OutlineLayer"), TestOf(typeof(OutlineLayer))] - public class OutlineLayerTests : IOutlineSettingsExTests, IDisposable + public class OutlineLayerTests : IOutlineSettingsTests, IDisposable { private OutlineLayer _layer; @@ -56,14 +56,15 @@ public void Add_FiltersRenderesByLayer() { var go = new GameObject("r1", typeof(MeshRenderer)); var go2 = new GameObject("r2", typeof(MeshRenderer)); + var layers = new OutlineLayerCollection(); + layers.IgnoreLayerMask = 1 << LayerMask.NameToLayer("TransparentFX"); + layers.Add(_layer); go2.layer = LayerMask.NameToLayer("TransparentFX"); go2.transform.SetParent(go.transform, false); - ICollection r; - - _layer.Add(go, "TransparentFX"); - _layer.TryGetRenderers(go, out r); + _layer.Add(go); + _layer.TryGetRenderers(go, out var r); Assert.AreEqual(1, r.Count); Assert.IsTrue(r.Contains(go.GetComponent())); diff --git a/Outline.Core/Assets/Tests/Editor/Scripts/OutlineRendererTests.cs b/Outline.Core/Assets/Tests/Editor/Scripts/OutlineRendererTests.cs deleted file mode 100644 index e4c83b0..0000000 --- a/Outline.Core/Assets/Tests/Editor/Scripts/OutlineRendererTests.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (C) 2019-2020 Alexander Bogarsukov. All rights reserved. -// See the LICENSE.md file in the project root for more information. - -using System; -using System.Collections; -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.Rendering; -using UnityEngine.TestTools; -using NUnit.Framework; - -namespace UnityFx.Outline -{ - [Category("OutlineRenderer"), TestOf(typeof(OutlineRenderer))] - public class OutlineRendererTests : IDisposable - { - private CommandBuffer _commandBuffer; - private OutlineRenderer _renderer; - - [SetUp] - public void Init() - { - _commandBuffer = new CommandBuffer(); - _renderer = new OutlineRenderer(_commandBuffer, BuiltinRenderTextureType.CameraTarget); - } - - [TearDown] - public void Dispose() - { - _commandBuffer.Dispose(); - } - - [Test] - public void Dispose_CanBeCalledMultipleTimes() - { - _renderer.Dispose(); - _renderer.Dispose(); - } - - [Test] - public void RenderSingleObject_ThrowsIfNullArguments() - { - Assert.Throws(() => _renderer.Render(default(IList), null, null)); - Assert.Throws(() => _renderer.Render(default(Renderer), null, null)); - } - } -} diff --git a/Outline.Core/Packages/UnityFx.Outline/CHANGELOG.md b/Outline.Core/Packages/UnityFx.Outline/CHANGELOG.md index d148afd..0460817 100644 --- a/Outline.Core/Packages/UnityFx.Outline/CHANGELOG.md +++ b/Outline.Core/Packages/UnityFx.Outline/CHANGELOG.md @@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/); this project adheres to [Semantic Versioning](http://semver.org/). +## [0.8.0] - 2020.05.30 + +Major refactoring and bugfixes. + +### Added +- Use procedural geometry ([DrawProcedural](https://docs.unity3d.com/ScriptReference/Rendering.CommandBuffer.DrawProcedural.html)) on SM3.5+. +- Added support for both forward and deferred renderers. +- Added ignore layer mask settings to `OutlineLayerCollection` (previously the ignore layers were specified when adding game objects to layers). +- Added `OutlineBuilder` helper script for managinf `OutlineLayerCollection` content from editor ([#8](https://github.com/Arvtesh/UnityFx.Outline/issues/8)). + +### Changed +- Changed `OutlineSettings` to display enum mask instead of checkboxes. +- Changed inspector look and feel for `OutlineLayerCollection` assets. +- Merged shaders for the 2 outline passes into one multi-pass shader. +- `OutlineLayerCollection` doe not depend on `OutlineRenderer` now. + +### Fixed +- Fixed outline rendering on mobiles ([#7](https://github.com/Arvtesh/UnityFx.Outline/issues/7)). +- Fixed outline shader error on low-end devices. + +### Removed +- Dropped .NET 3.5 support, minimal Unity version is set to 2018.4. +- Removed `IOutlineSettingsEx` interface. + ## [0.7.2] - 2020.04.08 Depth testing support and performance optimizations. diff --git a/Outline.Core/Packages/UnityFx.Outline/Editor/Scripts/OutlineBehaviourEditor.cs b/Outline.Core/Packages/UnityFx.Outline/Editor/Scripts/OutlineBehaviourEditor.cs index 492498a..17b32c6 100644 --- a/Outline.Core/Packages/UnityFx.Outline/Editor/Scripts/OutlineBehaviourEditor.cs +++ b/Outline.Core/Packages/UnityFx.Outline/Editor/Scripts/OutlineBehaviourEditor.cs @@ -3,6 +3,7 @@ using System; using UnityEditor; +using UnityEditorInternal; using UnityEditor.SceneManagement; using UnityEngine; @@ -28,7 +29,41 @@ public override void OnInspectorGUI() // 1) Outline settings. EditorGUI.BeginChangeCheck(); - OutlineEditorUtility.Render(_effect, _effect); + var mask = EditorGUILayout.MaskField("Ignore layers", _effect.IgnoreLayerMask, InternalEditorUtility.layers); + + if (_effect.IgnoreLayerMask != mask) + { + Undo.RecordObject(_effect, "Set Ignore Layers"); + _effect.IgnoreLayerMask = mask; + } + + var obj = (OutlineSettings)EditorGUILayout.ObjectField("Outline Settings", _effect.OutlineSettings, typeof(OutlineSettings), true); + + if (_effect.OutlineSettings != obj) + { + Undo.RecordObject(_effect, "Set Settings"); + _effect.OutlineSettings = obj; + } + + if (obj) + { + EditorGUI.BeginDisabledGroup(true); + EditorGUI.indentLevel += 1; + + OutlineEditorUtility.Render(_effect, _effect); + + EditorGUILayout.HelpBox(string.Format("Outline settings are overriden with values from {0}.", obj.name), MessageType.Info, true); + EditorGUI.indentLevel -= 1; + EditorGUI.EndDisabledGroup(); + } + else + { + EditorGUI.indentLevel += 1; + + OutlineEditorUtility.Render(_effect, _effect); + + EditorGUI.indentLevel -= 1; + } if (EditorGUI.EndChangeCheck()) { diff --git a/Outline.Core/Packages/UnityFx.Outline/Editor/Scripts/OutlineBuilderEditor.cs b/Outline.Core/Packages/UnityFx.Outline/Editor/Scripts/OutlineBuilderEditor.cs new file mode 100644 index 0000000..75d54b8 --- /dev/null +++ b/Outline.Core/Packages/UnityFx.Outline/Editor/Scripts/OutlineBuilderEditor.cs @@ -0,0 +1,162 @@ +// Copyright (C) 2019-2020 Alexander Bogarsukov. All rights reserved. +// See the LICENSE.md file in the project root for more information. + +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEditor; +using UnityEditorInternal; +using UnityEditor.SceneManagement; +using UnityEngine; + +namespace UnityFx.Outline +{ + [CustomEditor(typeof(OutlineBuilder))] + public class OutlineBuilderEditor : Editor + { + private OutlineBuilder _builder; + private ReorderableList _content; + private List _lists; + + private void OnEnable() + { + _builder = (OutlineBuilder)target; + + if (EditorApplication.isPlaying) + { + if (_builder.OutlineLayers) + { + _lists = new List(_builder.OutlineLayers.Count); + + foreach (var layer in _builder.OutlineLayers) + { + var list0 = new ArrayList(layer.Count); + + foreach (var go in layer) + { + list0.Add(go); + } + + var editorList = new ReorderableList(list0, typeof(GameObject), false, true, true, true); + + editorList.onAddCallback += (list) => + { + list.list.Add(null); + }; + + editorList.onRemoveCallback += (list) => + { + var go = list.list[list.index]; + list.list.RemoveAt(list.index); + layer.Remove(go as GameObject); + }; + + editorList.drawElementCallback += (rect, index, isActive, isFocused) => + { + var prevGo = list0[index] as GameObject; + var go = (GameObject)EditorGUI.ObjectField(new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), $"#{index}", prevGo, typeof(GameObject), true); + + if (prevGo != go) + { + list0[index] = go; + layer.Remove(prevGo); + layer.Add(go); + } + }; + + editorList.drawHeaderCallback += (rect) => + { + EditorGUI.LabelField(rect, layer.Name); + }; + + editorList.elementHeightCallback += (index) => + { + return EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + }; + + _lists.Add(editorList); + } + } + } + else + { + _content = new ReorderableList(_builder.Content, typeof(OutlineBuilder.ContentItem), true, true, true, true); + + _content.drawElementCallback += (rect, index, isActive, isFocused) => + { + var item = _builder.Content[index]; + item.Go = (GameObject)EditorGUI.ObjectField(new Rect(rect.x + rect.width * 0.3f + 1, rect.y, rect.width * 0.7f, EditorGUIUtility.singleLineHeight), item.Go, typeof(GameObject), true); + item.LayerIndex = EditorGUI.IntField(new Rect(rect.x, rect.y, rect.width * 0.3f - 1, EditorGUIUtility.singleLineHeight), item.LayerIndex); + }; + + _content.drawHeaderCallback += (rect) => + { + EditorGUI.LabelField(rect, "Content"); + }; + + _content.elementHeightCallback += (index) => + { + return EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + }; + } + } + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + + EditorGUI.BeginChangeCheck(); + + if (_content != null) + { + EditorGUILayout.HelpBox("Game objectes listed below will be added to corresponding outline layers when application is started. Only scene references are allowed.", MessageType.Info); + _content.DoLayoutList(); + EditorGUILayout.Space(); + + if (GUILayout.Button("Clear")) + { + _builder.Content.Clear(); + } + + serializedObject.ApplyModifiedProperties(); + } + else if (_lists != null && _lists.Count > 0) + { + EditorGUILayout.HelpBox("Settings below are not serialized, they only exist in runtime.", MessageType.Info); + + for (var i = 0; i < _lists.Count; ++i) + { + _lists[i].DoLayoutList(); + EditorGUILayout.Space(); + } + + if (GUILayout.Button("Clear")) + { + foreach (var list in _lists) + { + list.list.Clear(); + } + + _builder.Clear(); + } + + serializedObject.ApplyModifiedProperties(); + } + else + { + // TODO + } + + if (EditorGUI.EndChangeCheck()) + { + Undo.RecordObject(_builder, "Builder"); + + if (!EditorApplication.isPlayingOrWillChangePlaymode) + { + EditorUtility.SetDirty(_builder.gameObject); + EditorSceneManager.MarkSceneDirty(_builder.gameObject.scene); + } + } + } + } +} diff --git a/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/IOutlineSettingsEx.cs.meta b/Outline.Core/Packages/UnityFx.Outline/Editor/Scripts/OutlineBuilderEditor.cs.meta similarity index 83% rename from Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/IOutlineSettingsEx.cs.meta rename to Outline.Core/Packages/UnityFx.Outline/Editor/Scripts/OutlineBuilderEditor.cs.meta index 73a20da..20872eb 100644 --- a/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/IOutlineSettingsEx.cs.meta +++ b/Outline.Core/Packages/UnityFx.Outline/Editor/Scripts/OutlineBuilderEditor.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 9d3517d0fef6af540b0b046d3b2421dd +guid: c2ba41e0b025a6e46abc7b69d31d1907 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Outline.Core/Packages/UnityFx.Outline/Editor/Scripts/OutlineEditorUtility.cs b/Outline.Core/Packages/UnityFx.Outline/Editor/Scripts/OutlineEditorUtility.cs index 3f82a55..2b8bf4c 100644 --- a/Outline.Core/Packages/UnityFx.Outline/Editor/Scripts/OutlineEditorUtility.cs +++ b/Outline.Core/Packages/UnityFx.Outline/Editor/Scripts/OutlineEditorUtility.cs @@ -22,37 +22,6 @@ public static void RenderDivider(Color color, int thickness = 1, int padding = 5 EditorGUI.DrawRect(r, color); } - public static void Render(IOutlineSettingsEx settings, UnityEngine.Object undoContext) - { - var obj = (OutlineSettings)EditorGUILayout.ObjectField("Outline Settings", settings.OutlineSettings, typeof(OutlineSettings), true); - - if (settings.OutlineSettings != obj) - { - Undo.RecordObject(undoContext, "Settings"); - settings.OutlineSettings = obj; - } - - if (obj) - { - EditorGUI.BeginDisabledGroup(true); - EditorGUI.indentLevel += 1; - - Render((IOutlineSettings)settings, undoContext); - - EditorGUILayout.HelpBox(string.Format("Outline settings are overriden with values from {0}.", obj.name), MessageType.Info, true); - EditorGUI.indentLevel -= 1; - EditorGUI.EndDisabledGroup(); - } - else - { - EditorGUI.indentLevel += 1; - - Render((IOutlineSettings)settings, undoContext); - - EditorGUI.indentLevel -= 1; - } - } - public static void Render(IOutlineSettings settings, UnityEngine.Object undoContext) { var color = EditorGUILayout.ColorField("Color", settings.OutlineColor); @@ -63,7 +32,7 @@ public static void Render(IOutlineSettings settings, UnityEngine.Object undoCont settings.OutlineColor = color; } - var width = EditorGUILayout.IntSlider("Width", settings.OutlineWidth, OutlineRenderer.MinWidth, OutlineRenderer.MaxWidth); + var width = EditorGUILayout.IntSlider("Width", settings.OutlineWidth, OutlineResources.MinWidth, OutlineResources.MaxWidth); if (settings.OutlineWidth != width) { @@ -71,53 +40,24 @@ public static void Render(IOutlineSettings settings, UnityEngine.Object undoCont settings.OutlineWidth = width; } - var prevBlurred = (settings.OutlineRenderMode & OutlineRenderFlags.Blurred) != 0; - var blurred = EditorGUILayout.Toggle("Blurred", prevBlurred); + var prevRenderMode = settings.OutlineRenderMode; + var renderMode = (OutlineRenderFlags)EditorGUILayout.EnumFlagsField("Render Flags", prevRenderMode); - if (blurred) + if (renderMode != prevRenderMode) { - EditorGUI.indentLevel += 1; + Undo.RecordObject(undoContext, "Render Flags"); + settings.OutlineRenderMode = renderMode; + } - var i = EditorGUILayout.Slider("Blur Intensity", settings.OutlineIntensity, OutlineRenderer.MinIntensity, OutlineRenderer.MaxIntensity); + if ((renderMode & OutlineRenderFlags.Blurred) != 0) + { + var i = EditorGUILayout.Slider("Blur Intensity", settings.OutlineIntensity, OutlineResources.MinIntensity, OutlineResources.MaxIntensity); if (!Mathf.Approximately(settings.OutlineIntensity, i)) { Undo.RecordObject(undoContext, "Blur Intensity"); settings.OutlineIntensity = i; } - - EditorGUI.indentLevel -= 1; - } - - if (blurred != prevBlurred) - { - Undo.RecordObject(undoContext, "Blur"); - - if (blurred) - { - settings.OutlineRenderMode |= OutlineRenderFlags.Blurred; - } - else - { - settings.OutlineRenderMode &= ~OutlineRenderFlags.Blurred; - } - } - - var prevDepthTestEnabled = (settings.OutlineRenderMode & OutlineRenderFlags.EnableDepthTesting) != 0; - var depthTestEnabled = EditorGUILayout.Toggle("Depth Test", prevDepthTestEnabled); - - if (depthTestEnabled != prevDepthTestEnabled) - { - Undo.RecordObject(undoContext, "Depth Test"); - - if (depthTestEnabled) - { - settings.OutlineRenderMode |= OutlineRenderFlags.EnableDepthTesting; - } - else - { - settings.OutlineRenderMode &= ~OutlineRenderFlags.EnableDepthTesting; - } } } @@ -134,7 +74,7 @@ public static void RenderPreview(OutlineLayer layer, int layerIndex, bool showOb if (layer.Enabled) { - EditorGUILayout.LabelField(layer.OutlineRenderMode == OutlineRenderFlags.Solid ? layer.OutlineRenderMode.ToString() : string.Format("Blurred ({0})", layer.OutlineIntensity), GUILayout.MaxWidth(70)); + EditorGUILayout.LabelField(layer.OutlineRenderMode == OutlineRenderFlags.None ? layer.OutlineRenderMode.ToString() : string.Format("Blurred ({0})", layer.OutlineIntensity), GUILayout.MaxWidth(70)); EditorGUILayout.IntField(layer.OutlineWidth, GUILayout.MaxWidth(100)); EditorGUILayout.ColorField(layer.OutlineColor, GUILayout.MinWidth(100)); } diff --git a/Outline.Core/Packages/UnityFx.Outline/Editor/Scripts/OutlineLayerCollectionEditor.cs b/Outline.Core/Packages/UnityFx.Outline/Editor/Scripts/OutlineLayerCollectionEditor.cs index f0c57e0..faa90bf 100644 --- a/Outline.Core/Packages/UnityFx.Outline/Editor/Scripts/OutlineLayerCollectionEditor.cs +++ b/Outline.Core/Packages/UnityFx.Outline/Editor/Scripts/OutlineLayerCollectionEditor.cs @@ -5,6 +5,7 @@ using System.Collections; using System.Collections.Generic; using UnityEditor; +using UnityEditorInternal; using UnityEngine; namespace UnityFx.Outline @@ -12,110 +13,184 @@ namespace UnityFx.Outline [CustomEditor(typeof(OutlineLayerCollection))] public class OutlineLayerCollectionEditor : Editor { - private readonly GUILayoutOption _layerButtonStyle = GUILayout.ExpandWidth(false); private OutlineLayerCollection _layers; + private SerializedProperty _layersProp; + private ReorderableList _layersList; + + private void OnEnable() + { + _layers = (OutlineLayerCollection)target; + + _layersProp = serializedObject.FindProperty("_layers"); + _layersList = new ReorderableList(serializedObject, _layersProp, true, true, true, true); + _layersList.drawElementCallback += OnDrawLayer; + _layersList.drawHeaderCallback += OnDrawHeader; + _layersList.elementHeightCallback += OnGetElementHeight; + _layersList.onAddCallback += OnAddLayer; + _layersList.onRemoveCallback += OnRemoveLayer; + } + public override void OnInspectorGUI() { base.OnInspectorGUI(); EditorGUI.BeginChangeCheck(); - var removeLayer = -1; + var mask = EditorGUILayout.MaskField("Ignore layers", _layers.IgnoreLayerMask, InternalEditorUtility.layers); - // 1) Layers list. - if (_layers.Count > 0) + if (EditorGUI.EndChangeCheck()) { - for (var i = 0; i < _layers.Count; i++) - { - EditorGUILayout.Space(); - OutlineEditorUtility.RenderDivider(Color.gray); + Undo.RecordObject(_layers, "Set Layers"); + _layers.IgnoreLayerMask = mask; + } - EditorGUILayout.BeginHorizontal(); - var enabled = EditorGUILayout.ToggleLeft("Layer #" + i.ToString(), _layers[i].Enabled, EditorStyles.boldLabel); + EditorGUILayout.Space(); - if (enabled != _layers[i].Enabled) - { - if (enabled) - { - Undo.RecordObject(_layers, "Enable Layer"); - } - else - { - Undo.RecordObject(_layers, "Disable Layer"); - } + _layersList.DoLayoutList(); - _layers[i].Enabled = enabled; - } - - GUILayout.FlexibleSpace(); + if (_layers.NumberOfObjects > 0) + { + EditorGUILayout.Space(); + EditorGUILayout.HelpBox("Read-only lists below represent game objects assigned to specific outline layers. Only non-empty layers are displayed.", MessageType.Info); - if (GUILayout.Button("Remove", _layerButtonStyle)) + foreach (var layer in _layers) + { + if (layer.Count > 0) { - removeLayer = i; - } + EditorGUILayout.LabelField(layer.Name, EditorStyles.boldLabel); + EditorGUI.BeginDisabledGroup(true); + EditorGUI.indentLevel += 1; - EditorGUILayout.EndHorizontal(); - EditorGUILayout.Space(); + var index = 0; - var name = EditorGUILayout.TextField("Layer Name", _layers[i].NameTag); + foreach (var go in layer) + { + EditorGUILayout.ObjectField($"#{index++}", go, typeof(GameObject), true); + } - if (name != _layers[i].NameTag) - { - Undo.RecordObject(_layers, "Set Layer Name"); - _layers[i].NameTag = name; + EditorGUI.indentLevel -= 1; + EditorGUI.EndDisabledGroup(); } + } + } - var priority = EditorGUILayout.IntField("Layer Priority", _layers[i].Priority); + serializedObject.ApplyModifiedProperties(); + } - if (priority != _layers[i].Priority) - { - Undo.RecordObject(_layers, "Set Layer Priority"); - _layers[i].Priority = priority; - } + private void OnDrawLayer(Rect rect, int index, bool isActive, bool isFocused) + { + var lineHeight = EditorGUIUtility.singleLineHeight; + var lineSpacing = EditorGUIUtility.standardVerticalSpacing; + var lineOffset = lineHeight + lineSpacing; + var y = rect.y + lineSpacing; + var layer = _layers[index]; + + var obj = layer.OutlineSettings; + var enabled = layer.Enabled; + var name = layer.NameTag; + var color = layer.OutlineColor; + var width = layer.OutlineWidth; + var renderMode = layer.OutlineRenderMode; + var blurIntensity = layer.OutlineIntensity; - OutlineEditorUtility.Render(_layers[i], _layers); - } - } - else + EditorGUI.BeginChangeCheck(); + + // Header { - EditorGUILayout.HelpBox("The layer collection is empty.", MessageType.Info, true); + var rc = new Rect(rect.x, y, rect.width, lineHeight); + var bgRect = new Rect(rect.x - 2, y - 2, rect.width + 3, lineHeight + 3); + + // Header background + EditorGUI.DrawRect(rc, Color.gray); + EditorGUI.DrawRect(new Rect(bgRect.x, bgRect.y, bgRect.width, 1), Color.gray); + EditorGUI.DrawRect(new Rect(bgRect.x, bgRect.yMax, bgRect.width, 1), Color.gray); + EditorGUI.DrawRect(new Rect(bgRect.x, bgRect.y, 1, bgRect.height), Color.gray); + EditorGUI.DrawRect(new Rect(bgRect.xMax, bgRect.y, 1, bgRect.height), Color.gray); + + obj = (OutlineSettings)EditorGUI.ObjectField(rc, " ", obj, typeof(OutlineSettings), true); + enabled = EditorGUI.ToggleLeft(rc, "Layer #" + index.ToString(), enabled, EditorStyles.boldLabel); + y += lineOffset; } - // Add/remove processing. - OutlineEditorUtility.RenderDivider(Color.gray); - EditorGUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - - if (GUILayout.Button("Add New", _layerButtonStyle)) + // Layer properties { - Undo.RecordObject(_layers, "Add Layer"); - _layers.Add(new OutlineLayer()); + name = EditorGUI.TextField(new Rect(rect.x, y, rect.width, lineHeight), "Name", name); + y += lineOffset; } - if (GUILayout.Button("Remove All", _layerButtonStyle)) + // Outline settings { - Undo.RecordObject(_layers, "Remove All Layers"); - _layers.Clear(); + EditorGUI.BeginDisabledGroup(obj != null); + + color = EditorGUI.ColorField(new Rect(rect.x, y, rect.width, lineHeight), "Color", color); + y += lineOffset; + + width = EditorGUI.IntSlider(new Rect(rect.x, y, rect.width, lineHeight), "Width", width, OutlineResources.MinWidth, OutlineResources.MaxWidth); + y += lineOffset; + + renderMode = (OutlineRenderFlags)EditorGUI.EnumFlagsField(new Rect(rect.x, y, rect.width, lineHeight), "Render Flags", renderMode); + y += lineOffset; + + if ((renderMode & OutlineRenderFlags.Blurred) != 0) + { + blurIntensity = EditorGUI.Slider(new Rect(rect.x, y, rect.width, lineHeight), "Blur Intensity", blurIntensity, OutlineResources.MinIntensity, OutlineResources.MaxIntensity); + } + + EditorGUI.EndDisabledGroup(); } - if (removeLayer >= 0) + if (EditorGUI.EndChangeCheck()) { - Undo.RecordObject(_layers, "Remove Layer"); - _layers.RemoveAt(removeLayer); + Undo.RecordObject(_layers, "Layers changed"); + EditorUtility.SetDirty(_layers); + + layer.OutlineSettings = obj; + layer.Enabled = enabled; + layer.NameTag = name; + layer.OutlineWidth = width; + layer.OutlineColor = color; + layer.OutlineRenderMode = renderMode; + layer.OutlineIntensity = blurIntensity; } + } + + private void OnDrawHeader(Rect rect) + { + EditorGUI.LabelField(rect, "Layer settings"); + } - EditorGUILayout.EndHorizontal(); + private float OnGetElementHeight(int index) + { + var numberOfLines = 5; - if (EditorGUI.EndChangeCheck()) + if ((_layers[index].OutlineRenderMode & OutlineRenderFlags.Blurred) != 0) { - EditorUtility.SetDirty(_layers); + ++numberOfLines; } + + return (EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing) * numberOfLines + EditorGUIUtility.standardVerticalSpacing; } - private void OnEnable() + private void OnAddLayer(ReorderableList list) { - _layers = (OutlineLayerCollection)target; + var layer = new OutlineLayer(); + + Undo.RecordObject(_layers, "Add Layer"); + EditorUtility.SetDirty(_layers); + + _layers.Add(layer); + } + + private void OnRemoveLayer(ReorderableList list) + { + var index = list.index; + var layer = _layers[index]; + + Undo.RecordObject(_layers, "Remove Layer"); + EditorUtility.SetDirty(_layers); + + _layers.RemoveAt(index); } } } diff --git a/Outline.Core/Packages/UnityFx.Outline/Runtime/Prefabs/OutlineResources.asset b/Outline.Core/Packages/UnityFx.Outline/Runtime/Prefabs/OutlineResources.asset index 5b0a0c7..285880e 100644 --- a/Outline.Core/Packages/UnityFx.Outline/Runtime/Prefabs/OutlineResources.asset +++ b/Outline.Core/Packages/UnityFx.Outline/Runtime/Prefabs/OutlineResources.asset @@ -3,8 +3,9 @@ --- !u!114 &11400000 MonoBehaviour: m_ObjectHideFlags: 0 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 0} m_Enabled: 1 m_EditorHideFlags: 0 @@ -12,5 +13,4 @@ MonoBehaviour: m_Name: OutlineResources m_EditorClassIdentifier: RenderShader: {fileID: 4800000, guid: ac20fbf75bafe454aba5ef3c098349df, type: 3} - HPassShader: {fileID: 4800000, guid: 41c9acbf41c8245498ac9beab378de12, type: 3} - VPassBlendShader: {fileID: 4800000, guid: 1df0cb1700e142f4ca3b28297d3957da, type: 3} + OutlineShader: {fileID: 4800000, guid: 41c9acbf41c8245498ac9beab378de12, type: 3} diff --git a/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/IOutlineSettingsEx.cs b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/IOutlineSettingsEx.cs deleted file mode 100644 index 0939a90..0000000 --- a/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/IOutlineSettingsEx.cs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (C) 2019-2020 Alexander Bogarsukov. All rights reserved. -// See the LICENSE.md file in the project root for more information. - -using System; -using UnityEngine; - -namespace UnityFx.Outline -{ - /// - /// Extended outline settings. - /// - public interface IOutlineSettingsEx : IOutlineSettings - { - /// - /// Gets or sets serializable outline settings. Set this to non- value to share settings with other components. - /// - OutlineSettings OutlineSettings { get; set; } - } -} diff --git a/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineBehaviour.cs b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineBehaviour.cs index 325b329..96daed1 100644 --- a/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineBehaviour.cs +++ b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineBehaviour.cs @@ -15,26 +15,26 @@ namespace UnityFx.Outline /// [ExecuteInEditMode] [DisallowMultipleComponent] - public sealed class OutlineBehaviour : MonoBehaviour, IOutlineSettingsEx + public sealed class OutlineBehaviour : MonoBehaviour, IOutlineSettings { #region data #pragma warning disable 0649 - [SerializeField, Tooltip("Sets outline resources to use. Do not change the defaults unless you know what you're doing.")] + [SerializeField, Tooltip(OutlineResources.OutlineResourcesTooltip)] private OutlineResources _outlineResources; [SerializeField, HideInInspector] private OutlineSettingsInstance _outlineSettings; + [SerializeField, HideInInspector] + private int _layerMask; [SerializeField, Tooltip("If set, list of object renderers is updated on each frame. Enable if the object has child renderers which are enabled/disabled frequently.")] private bool _updateRenderers; #pragma warning restore 0649 - private OutlineRendererCollection _renderers; - private CommandBuffer _commandBuffer; - private Dictionary _cameraMap = new Dictionary(); - private float _cameraMapUpdateTimer; + private List _camerasToRemove = new List(); + private OutlineRendererCollection _renderers; #endregion @@ -44,6 +44,7 @@ public sealed class OutlineBehaviour : MonoBehaviour, IOutlineSettingsEx /// Gets or sets resources used by the effect implementation. /// /// Thrown if setter argument is . + /// public OutlineResources OutlineResources { get @@ -52,17 +53,56 @@ public OutlineResources OutlineResources } set { - if (value == null) + if (value is null) { - throw new ArgumentNullException("OutlineResources"); + throw new ArgumentNullException(nameof(OutlineResources)); } - if (_outlineResources != value) + _outlineResources = value; + } + } + + /// + /// Gets or sets outline settings. Set this to non- value to share settings with other components. + /// + /// + public OutlineSettings OutlineSettings + { + get + { + if (_outlineSettings == null) { - CreateSettingsIfNeeded(); + _outlineSettings = new OutlineSettingsInstance(); + } - _outlineResources = value; - _outlineSettings.OutlineResources = _outlineResources; + return _outlineSettings.OutlineSettings; + } + set + { + if (_outlineSettings == null) + { + _outlineSettings = new OutlineSettingsInstance(); + } + + _outlineSettings.OutlineSettings = value; + } + } + + /// + /// Gets or sets layer mask to use for ignored components in this game object. + /// + public int IgnoreLayerMask + { + get + { + return _layerMask; + } + set + { + if (_layerMask != value) + { + _layerMask = value; + _renderers?.Reset(false, value); } } } @@ -70,6 +110,7 @@ public OutlineResources OutlineResources /// /// Gets outline renderers. By default all child components are used for outlining. /// + /// public ICollection OutlineRenderers { get @@ -82,12 +123,15 @@ public ICollection OutlineRenderers /// /// Gets all cameras outline data is rendered to. /// - public ICollection Cameras + public ICollection Cameras => _cameraMap.Keys; + + /// + /// Updates renderer list. + /// + /// + public void UpdateRenderers() { - get - { - return _cameraMap.Keys; - } + _renderers?.Reset(false, _layerMask); } #endregion @@ -98,21 +142,10 @@ private void Awake() { CreateRenderersIfNeeded(); CreateSettingsIfNeeded(); - - _outlineSettings.OutlineResources = _outlineResources; - } - - private void OnDestroy() - { - if (_outlineSettings != null) - { - _outlineSettings.OutlineResources = null; - } } private void OnEnable() { - CreateCommandBufferIfNeeded(); Camera.onPreRender += OnCameraPreRender; } @@ -126,39 +159,51 @@ private void OnDisable() { kvp.Key.RemoveCommandBuffer(OutlineRenderer.RenderEvent, kvp.Value); } + + kvp.Value.Dispose(); } _cameraMap.Clear(); - - if (_commandBuffer != null) - { - _commandBuffer.Dispose(); - _commandBuffer = null; - } } private void Update() { - _cameraMapUpdateTimer += Time.deltaTime; - - if (_cameraMapUpdateTimer > 16) - { - RemoveDestroyedCameras(); - _cameraMapUpdateTimer = 0; - } - if (_outlineResources != null && _renderers != null) { + _camerasToRemove.Clear(); + if (_updateRenderers) { - _renderers.Reset(false); + _renderers.Reset(false, _layerMask); } - _commandBuffer.Clear(); + foreach (var kvp in _cameraMap) + { + var camera = kvp.Key; + var cmdBuffer = kvp.Value; + + if (camera) + { + cmdBuffer.Clear(); + + if (_renderers.Count > 0) + { + using (var renderer = new OutlineRenderer(cmdBuffer, _outlineResources, camera.actualRenderingPath)) + { + renderer.Render(_renderers.GetList(), _outlineSettings, name); + } + } + } + else + { + cmdBuffer.Dispose(); + _camerasToRemove.Add(camera); + } + } - using (var renderer = new OutlineRenderer(_commandBuffer, BuiltinRenderTextureType.CameraTarget)) + foreach (var camera in _camerasToRemove) { - renderer.Render(_renderers.GetList(), _outlineSettings.OutlineResources, _outlineSettings); + _cameraMap.Remove(camera); } } } @@ -168,22 +213,14 @@ private void Update() private void OnValidate() { CreateRenderersIfNeeded(); - CreateCommandBufferIfNeeded(); CreateSettingsIfNeeded(); - - _outlineSettings.OutlineResources = _outlineResources; } private void Reset() { - if (_outlineSettings != null) - { - _outlineSettings.OutlineResources = _outlineResources; - } - if (_renderers != null) { - _renderers.Reset(true); + _renderers.Reset(false, _layerMask); } } @@ -191,35 +228,6 @@ private void Reset() #endregion - #region IOutlineSettingsEx - - /// - /// Gets or sets outline settings. Set this to non- value to share settings with other components. - /// - public OutlineSettings OutlineSettings - { - get - { - if (_outlineSettings == null) - { - _outlineSettings = new OutlineSettingsInstance(); - } - - return _outlineSettings.OutlineSettings; - } - set - { - if (_outlineSettings == null) - { - _outlineSettings = new OutlineSettingsInstance(); - } - - _outlineSettings.OutlineSettings = value; - } - } - - #endregion - #region IOutlineSettings /// @@ -307,54 +315,20 @@ private void OnCameraPreRender(Camera camera) if (!_cameraMap.ContainsKey(camera)) { - camera.AddCommandBuffer(OutlineRenderer.RenderEvent, _commandBuffer); - _cameraMap.Add(camera, _commandBuffer); - } - } - } - - private void RemoveDestroyedCameras() - { - List camerasToRemove = null; + var cmdBuf = new CommandBuffer(); + cmdBuf.name = string.Format("{0} - {1}", GetType().Name, name); + camera.AddCommandBuffer(OutlineRenderer.RenderEvent, cmdBuf); - foreach (var camera in _cameraMap.Keys) - { - if (camera == null) - { - if (camerasToRemove != null) - { - camerasToRemove.Add(camera); - } - else - { - camerasToRemove = new List() { camera }; - } + _cameraMap.Add(camera, cmdBuf); } } - - if (camerasToRemove != null) - { - foreach (var camera in camerasToRemove) - { - _cameraMap.Remove(camera); - } - } - } - - private void CreateCommandBufferIfNeeded() - { - if (_commandBuffer == null) - { - _commandBuffer = new CommandBuffer(); - _commandBuffer.name = string.Format("{0} - {1}", GetType().Name, name); - } } private void CreateSettingsIfNeeded() { if (_outlineSettings == null) { - _outlineSettings = new OutlineSettingsInstance(_outlineResources); + _outlineSettings = new OutlineSettingsInstance(); } } @@ -363,7 +337,7 @@ private void CreateRenderersIfNeeded() if (_renderers == null) { _renderers = new OutlineRendererCollection(gameObject); - _renderers.Reset(true); + _renderers.Reset(false, _layerMask); } } diff --git a/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineBuilder.cs b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineBuilder.cs new file mode 100644 index 0000000..5192987 --- /dev/null +++ b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineBuilder.cs @@ -0,0 +1,93 @@ +// Copyright (C) 2019-2020 Alexander Bogarsukov. All rights reserved. +// See the LICENSE.md file in the project root for more information. + +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace UnityFx.Outline +{ + /// + /// A helper behaviour for managing content of via Unity Editor. + /// + public sealed class OutlineBuilder : MonoBehaviour + { + #region data + + [Serializable] + internal class ContentItem + { + public GameObject Go; + public int LayerIndex; + } + +#pragma warning disable 0649 + + [SerializeField, Tooltip(OutlineResources.OutlineLayerCollectionTooltip)] + private OutlineLayerCollection _outlineLayers; + [SerializeField, HideInInspector] + private List _content; + +#pragma warning restore 0649 + + #endregion + + #region interface + + internal List Content { get => _content; set => _content = value; } + + /// + /// Gets or sets a collection of layers to manage. + /// + public OutlineLayerCollection OutlineLayers { get => _outlineLayers; set => _outlineLayers = value; } + + /// + /// Clears content of all layers. + /// + /// + public void Clear() + { + _outlineLayers?.ClearLayerContent(); + } + + #endregion + + #region MonoBehaviour + + private void OnEnable() + { + if (_outlineLayers && _content != null) + { + foreach (var item in _content) + { + if (item.LayerIndex >= 0 && item.LayerIndex < _outlineLayers.Count && item.Go) + { + _outlineLayers.GetOrAddLayer(item.LayerIndex).Add(item.Go); + } + } + } + } + +#if UNITY_EDITOR + + private void Reset() + { + var effect = GetComponent(); + + if (effect) + { + _outlineLayers = effect.OutlineLayersInternal; + } + } + + private void OnDestroy() + { + _outlineLayers?.ClearLayerContent(); + } + +#endif + + #endregion + } +} diff --git a/Outline.Core/Assets/Tests/Editor/Scripts/Helpers/IOutlineSettingsExTests.cs.meta b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineBuilder.cs.meta similarity index 83% rename from Outline.Core/Assets/Tests/Editor/Scripts/Helpers/IOutlineSettingsExTests.cs.meta rename to Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineBuilder.cs.meta index eacde42..fc6b25c 100644 --- a/Outline.Core/Assets/Tests/Editor/Scripts/Helpers/IOutlineSettingsExTests.cs.meta +++ b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineBuilder.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: c7d2cd56d59228e40917059e616e5ee9 +guid: e746e776b0ae00d4a9d458b9430b95d7 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineEffect.cs b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineEffect.cs index a4bacb8..0150be3 100644 --- a/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineEffect.cs +++ b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineEffect.cs @@ -21,14 +21,16 @@ public sealed partial class OutlineEffect : MonoBehaviour { #region data - [SerializeField, Tooltip("Sets outline resources to use. Do not change the defaults unless you know what you're doing.")] + [SerializeField, Tooltip(OutlineResources.OutlineResourcesTooltip)] private OutlineResources _outlineResources; - [SerializeField, Tooltip("Collection of outline layers to use. This can be used to share outline settings between multiple cameras.")] + [SerializeField, Tooltip(OutlineResources.OutlineLayerCollectionTooltip)] private OutlineLayerCollection _outlineLayers; [SerializeField, HideInInspector] private CameraEvent _cameraEvent = OutlineRenderer.RenderEvent; + private Camera _camera; private CommandBuffer _commandBuffer; + private List _renderObjects = new List(16); #endregion @@ -46,9 +48,9 @@ public OutlineResources OutlineResources } set { - if (ReferenceEquals(value, null)) + if (value is null) { - throw new ArgumentNullException("OutlineResources"); + throw new ArgumentNullException(nameof(OutlineResources)); } _outlineResources = value; @@ -68,6 +70,11 @@ public IList OutlineLayers } } + /// + /// Gets outline layers (for internal use only). + /// + internal OutlineLayerCollection OutlineLayersInternal => _outlineLayers; + /// /// Gets or sets used to render the outlines. /// @@ -153,27 +160,25 @@ private void Awake() private void OnEnable() { - var camera = GetComponent(); + _camera = GetComponent(); - if (camera) + if (_camera) { _commandBuffer = new CommandBuffer { name = string.Format("{0} - {1}", GetType().Name, name) }; - camera.depthTextureMode |= DepthTextureMode.Depth; - camera.AddCommandBuffer(_cameraEvent, _commandBuffer); + _camera.depthTextureMode |= DepthTextureMode.Depth; + _camera.AddCommandBuffer(_cameraEvent, _commandBuffer); } } private void OnDisable() { - var camera = GetComponent(); - - if (camera) + if (_camera) { - camera.RemoveCommandBuffer(_cameraEvent, _commandBuffer); + _camera.RemoveCommandBuffer(_cameraEvent, _commandBuffer); } if (_commandBuffer != null) @@ -185,7 +190,7 @@ private void OnDisable() private void Update() { - if (_outlineLayers) + if (_camera && _outlineLayers) { FillCommandBuffer(); } @@ -219,16 +224,22 @@ private void FillCommandBuffer() if (_outlineResources && _outlineResources.IsValid) { - using (var renderer = new OutlineRenderer(_commandBuffer, BuiltinRenderTextureType.CameraTarget)) + using (var renderer = new OutlineRenderer(_commandBuffer, _outlineResources, _camera.actualRenderingPath)) { - _outlineLayers.Render(renderer, _outlineResources); + _renderObjects.Clear(); + _outlineLayers.GetRenderObjects(_renderObjects); + + foreach (var renderObject in _renderObjects) + { + renderer.Render(renderObject); + } } } } private void CreateLayersIfNeeded() { - if (ReferenceEquals(_outlineLayers, null)) + if (_outlineLayers is null) { _outlineLayers = ScriptableObject.CreateInstance(); _outlineLayers.name = "OutlineLayers"; diff --git a/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineLayer.cs b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineLayer.cs index eac4774..d3d71da 100644 --- a/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineLayer.cs +++ b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineLayer.cs @@ -16,7 +16,7 @@ namespace UnityFx.Outline /// /// [Serializable] - public sealed partial class OutlineLayer : ICollection, IOutlineSettingsEx + public sealed class OutlineLayer : ICollection, IReadOnlyCollection, IOutlineSettings { #region data @@ -25,8 +25,6 @@ public sealed partial class OutlineLayer : ICollection, IOutlineSett [SerializeField, HideInInspector] private string _name; [SerializeField, HideInInspector] - private int _zOrder; - [SerializeField, HideInInspector] private bool _enabled = true; private OutlineLayerCollection _parentCollection; @@ -69,43 +67,33 @@ public bool Enabled } /// - /// Gets or sets the layer priority. Layers with greater values are rendered on top of layers with lower priority. - /// Layers with equal priorities are rendered according to index in parent collection. + /// Gets index of the layer in parent collection. /// - /// - public int Priority + public int Index { get { - return _zOrder; - } - set - { - if (_zOrder != value) + if (_parentCollection != null) { - if (_parentCollection != null) - { - _parentCollection.SetOrderChanged(); - } - - _zOrder = value; + return _parentCollection.IndexOf(this); } + + return -1; } } /// - /// Gets index of the layer in parent collection. + /// Gets or sets outline settings. Set this to non- value to share settings with other components. /// - public int Index + public OutlineSettings OutlineSettings { get { - if (_parentCollection != null) - { - return _parentCollection.IndexOf(this); - } - - return -1; + return _settings.OutlineSettings; + } + set + { + _settings.OutlineSettings = value; } } @@ -116,6 +104,14 @@ public OutlineLayer() { } + /// + /// Initializes a new instance of the class. + /// + internal OutlineLayer(OutlineLayerCollection parentCollection) + { + _parentCollection = parentCollection; + } + /// /// Initializes a new instance of the class. /// @@ -130,9 +126,9 @@ public OutlineLayer(string name) /// Thrown if is . public OutlineLayer(OutlineSettings settings) { - if (ReferenceEquals(settings, null)) + if (settings is null) { - throw new ArgumentNullException("settings"); + throw new ArgumentNullException(nameof(settings)); } _settings.OutlineSettings = settings; @@ -144,57 +140,27 @@ public OutlineLayer(OutlineSettings settings) /// Thrown if is . public OutlineLayer(string name, OutlineSettings settings) { - if (ReferenceEquals(settings, null)) + if (settings is null) { - throw new ArgumentNullException("settings"); + throw new ArgumentNullException(nameof(settings)); } _name = name; _settings.OutlineSettings = settings; } - /// - /// Adds a new object to the layer. - /// - /// Thrown if is . - public void Add(GameObject go, int ignoreLayerMask) - { - if (ReferenceEquals(go, null)) - { - throw new ArgumentNullException("go"); - } - - if (!_outlineObjects.ContainsKey(go)) - { - var renderers = new OutlineRendererCollection(go); - renderers.Reset(false, ignoreLayerMask); - _outlineObjects.Add(go, renderers); - } - } - - /// - /// Adds a new object to the layer. - /// - /// Thrown if is . - public void Add(GameObject go, string ignoreLayer) - { - Add(go, 1 << LayerMask.NameToLayer(ignoreLayer)); - } - /// /// Attempts to get renderers assosiated with the specified . /// /// Thrown if is . public bool TryGetRenderers(GameObject go, out ICollection renderers) { - if (ReferenceEquals(go, null)) + if (go is null) { - throw new ArgumentNullException("go"); + throw new ArgumentNullException(nameof(go)); } - OutlineRendererCollection result; - - if (_outlineObjects.TryGetValue(go, out result)) + if (_outlineObjects.TryGetValue(go, out var result)) { renderers = result; return true; @@ -205,19 +171,19 @@ public bool TryGetRenderers(GameObject go, out ICollection renderers) } /// - /// Renders the layers. + /// Gets the objects for rendering. /// - public void Render(OutlineRenderer renderer, OutlineResources resources) + public void GetRenderObjects(IList renderObjects) { if (_enabled) { - _settings.OutlineResources = resources; - foreach (var kvp in _outlineObjects) { - if (kvp.Key && kvp.Key.activeInHierarchy) + var go = kvp.Key; + + if (go && go.activeInHierarchy) { - renderer.Render(kvp.Value.GetList(), resources, _settings); + renderObjects.Add(new OutlineRenderObject(go, kvp.Value.GetList(), _settings)); } } } @@ -239,17 +205,18 @@ internal string NameTag } } - internal OutlineLayerCollection ParentCollection + internal OutlineLayerCollection ParentCollection => _parentCollection; + + internal void UpdateRenderers(int ignoreLayers) { - get + foreach (var renderers in _outlineObjects.Values) { - return _parentCollection; + renderers.Reset(false, ignoreLayers); } } internal void Reset() { - _settings.OutlineResources = null; _outlineObjects.Clear(); } @@ -267,25 +234,6 @@ internal void SetCollection(OutlineLayerCollection collection) #endregion - #region IOutlineSettingsEx - - /// - /// Gets or sets outline settings. Set this to non- value to share settings with other components. - /// - public OutlineSettings OutlineSettings - { - get - { - return _settings.OutlineSettings; - } - set - { - _settings.OutlineSettings = value; - } - } - - #endregion - #region IOutlineSettings /// @@ -345,44 +293,42 @@ public OutlineRenderFlags OutlineRenderMode #region ICollection /// - public int Count - { - get - { - return _outlineObjects.Count; - } - } + public int Count => _outlineObjects.Count; /// - public bool IsReadOnly - { - get - { - return false; - } - } + public bool IsReadOnly => false; /// public void Add(GameObject go) { - Add(go, 0); + if (go is null) + { + throw new ArgumentNullException(nameof(go)); + } + + if (!_outlineObjects.ContainsKey(go)) + { + var renderers = new OutlineRendererCollection(go); + renderers.Reset(false, _parentCollection.IgnoreLayerMask); + _outlineObjects.Add(go, renderers); + } } /// public bool Remove(GameObject go) { - if (!ReferenceEquals(go, null)) + if (go is null) { - return _outlineObjects.Remove(go); + return false; } - return false; + return _outlineObjects.Remove(go); } /// public bool Contains(GameObject go) { - if (ReferenceEquals(go, null)) + if (go is null) { return false; } @@ -451,12 +397,6 @@ public override string ToString() text.Append(_parentCollection.IndexOf(this)); } - if (_zOrder > 0) - { - text.Append(" z"); - text.Append(_zOrder); - } - if (_outlineObjects.Count > 0) { text.Append(" ("); diff --git a/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineLayerCollection.cs b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineLayerCollection.cs index d28f982..a701654 100644 --- a/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineLayerCollection.cs +++ b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineLayerCollection.cs @@ -15,63 +15,114 @@ namespace UnityFx.Outline /// /// [CreateAssetMenu(fileName = "OutlineLayerCollection", menuName = "UnityFx/Outline/Outline Layer Collection")] - public sealed class OutlineLayerCollection : ScriptableObject, IList + public sealed class OutlineLayerCollection : ScriptableObject, IList, IReadOnlyList { #region data - private class OutlineLayerComparer : IComparer - { - public int Compare(OutlineLayer x, OutlineLayer y) - { - return x.Priority - y.Priority; - } - } - [SerializeField, HideInInspector] private List _layers = new List(); - - private List _sortedLayers = new List(); - private OutlineLayerComparer _sortComparer = new OutlineLayerComparer(); - private bool _orderChanged = true; + [SerializeField, HideInInspector] + private int _layerMask; #endregion #region interface /// - /// Gets layers ordered by . + /// Gets or sets layer mask to use for ignored components in layer game objects. + /// + public int IgnoreLayerMask + { + get + { + return _layerMask; + } + set + { + if (_layerMask != value) + { + _layerMask = value; + + foreach (var layer in _layers) + { + layer.UpdateRenderers(value); + } + } + } + } + + /// + /// Gets number of game objects in the layers. /// - public OutlineLayer[] SortedLayers + public int NumberOfObjects { get { - UpdateSortedLayersIfNeeded(); - return _sortedLayers.ToArray(); + var result = 0; + + foreach (var layer in _layers) + { + result += layer.Count; + } + + return result; } } /// - /// Renders all layers. + /// Gets a layer with the specified index. If layer at the does not exist, creates one. /// - public void Render(OutlineRenderer renderer, OutlineResources resources) + public OutlineLayer GetOrAddLayer(int index) { - UpdateSortedLayersIfNeeded(); + if (index < 0) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } - foreach (var layer in _sortedLayers) + while (index >= _layers.Count) { - layer.Render(renderer, resources); + _layers.Add(new OutlineLayer(this)); } + + return _layers[index]; } - #endregion + /// + /// Adds a new layer. + /// + public OutlineLayer AddLayer() + { + var layer = new OutlineLayer(this); + _layers.Add(layer); + return layer; + } - #region internals + /// + /// Gets the objects for rendering. + /// + public void GetRenderObjects(IList renderObjects) + { + foreach (var layer in _layers) + { + layer.GetRenderObjects(renderObjects); + } + } - internal void SetOrderChanged() + /// + /// Removes all game objects registered in layers. + /// + public void ClearLayerContent() { - _orderChanged = true; + foreach (var layer in _layers) + { + layer.Clear(); + } } + #endregion + + #region internals + internal void Reset() { foreach (var layer in _layers) @@ -88,10 +139,9 @@ private void OnEnable() { foreach (var layer in _layers) { + layer.Clear(); layer.SetCollection(this); } - - _orderChanged = true; } #endregion @@ -107,14 +157,14 @@ public OutlineLayer this[int layerIndex] } set { - if (value == null) + if (value is null) { throw new ArgumentNullException("layer"); } if (layerIndex < 0 || layerIndex >= _layers.Count) { - throw new ArgumentOutOfRangeException("layerIndex"); + throw new ArgumentOutOfRangeException(nameof(layerIndex)); } if (_layers[layerIndex] != value) @@ -123,8 +173,6 @@ public OutlineLayer this[int layerIndex] _layers[layerIndex].SetCollection(null); _layers[layerIndex] = value; - - _orderChanged = true; } } } @@ -143,18 +191,15 @@ public int IndexOf(OutlineLayer layer) /// public void Insert(int index, OutlineLayer layer) { - if (layer == null) + if (layer is null) { - throw new ArgumentNullException("layer"); + throw new ArgumentNullException(nameof(layer)); } if (layer.ParentCollection != this) { layer.SetCollection(this); - _layers.Insert(index, layer); - - _orderChanged = true; } } @@ -165,8 +210,6 @@ public void RemoveAt(int index) { _layers[index].SetCollection(null); _layers.RemoveAt(index); - - _orderChanged = true; } } @@ -175,37 +218,23 @@ public void RemoveAt(int index) #region ICollection /// - public int Count - { - get - { - return _layers.Count; - } - } + public int Count => _layers.Count; /// - public bool IsReadOnly - { - get - { - return false; - } - } + public bool IsReadOnly => false; /// public void Add(OutlineLayer layer) { - if (layer == null) + if (layer is null) { - throw new ArgumentNullException("layer"); + throw new ArgumentNullException(nameof(layer)); } if (layer.ParentCollection != this) { layer.SetCollection(this); - _layers.Add(layer); - _orderChanged = true; } } @@ -215,9 +244,6 @@ public bool Remove(OutlineLayer layer) if (_layers.Remove(layer)) { layer.SetCollection(null); - - _sortedLayers.Remove(layer); - return true; } @@ -235,14 +261,13 @@ public void Clear() } _layers.Clear(); - _sortedLayers.Clear(); } } /// public bool Contains(OutlineLayer layer) { - if (layer == null) + if (layer is null) { return false; } @@ -274,18 +299,6 @@ IEnumerator IEnumerable.GetEnumerator() #endregion #region implementation - - private void UpdateSortedLayersIfNeeded() - { - if (_orderChanged) - { - _sortedLayers.Clear(); - _sortedLayers.AddRange(_layers); - _sortedLayers.Sort(_sortComparer); - _orderChanged = false; - } - } - #endregion } } diff --git a/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineRenderFlags.cs b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineRenderFlags.cs index c911c0d..d180f46 100644 --- a/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineRenderFlags.cs +++ b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineRenderFlags.cs @@ -14,7 +14,7 @@ public enum OutlineRenderFlags /// /// Outline frame is a solid line. /// - Solid = 0, + None = 0, /// /// Outline frame is blurred. @@ -24,6 +24,6 @@ public enum OutlineRenderFlags /// /// Enabled depth testing when rendering object outlines. Only visible parts of objects are outlined. /// - EnableDepthTesting = 0x100 + EnableDepthTesting = 2 } } diff --git a/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineRenderObject.cs b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineRenderObject.cs new file mode 100644 index 0000000..fe7469a --- /dev/null +++ b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineRenderObject.cs @@ -0,0 +1,72 @@ +// Copyright (C) 2019-2020 Alexander Bogarsukov. All rights reserved. +// See the LICENSE.md file in the project root for more information. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using UnityEngine; + +namespace UnityFx.Outline +{ + /// + /// A single outline object + its outline settings. + /// + public readonly struct OutlineRenderObject : IEquatable + { + #region data + + private readonly GameObject _go; + private readonly IReadOnlyList _renderers; + private readonly IOutlineSettings _outlineSettings; + + #endregion + + #region interface + + /// + /// Gets the . + /// + public GameObject Go => _go; + + /// + /// Gets renderers for the object. + /// + public IReadOnlyList Renderers => _renderers; + + /// + /// Gets outline settings for this object. + /// + public IOutlineSettings OutlineSettings => _outlineSettings; + + /// + /// Initializes a new instance of the struct. + /// + public OutlineRenderObject(GameObject go, IReadOnlyList renderers, IOutlineSettings outlineSettings) + { + _go = go; + _renderers = renderers; + _outlineSettings = outlineSettings; + } + + /// + /// Implicit convertino to . + /// + public static implicit operator GameObject(OutlineRenderObject o) + { + return o._go; + } + + #endregion + + #region IEquatable + + /// + public bool Equals(OutlineRenderObject other) + { + return _go == other._go && _renderers == other._renderers && _outlineSettings == other._outlineSettings; + } + + #endregion + } +} diff --git a/Outline.Core/Assets/Examples/SimplePerCamera/OutlineEffectBuilder.cs.meta b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineRenderObject.cs.meta similarity index 71% rename from Outline.Core/Assets/Examples/SimplePerCamera/OutlineEffectBuilder.cs.meta rename to Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineRenderObject.cs.meta index 7150935..024cad2 100644 --- a/Outline.Core/Assets/Examples/SimplePerCamera/OutlineEffectBuilder.cs.meta +++ b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineRenderObject.cs.meta @@ -1,7 +1,5 @@ fileFormatVersion: 2 -guid: 5a318c96b1bc1614683eccf7abd717a1 -timeCreated: 1566138009 -licenseType: Free +guid: b9fa0d37014ee9049afd5e65be9f288b MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineRenderer.cs b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineRenderer.cs index 3569cf7..6ac7e84 100644 --- a/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineRenderer.cs +++ b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineRenderer.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; using UnityEngine; using UnityEngine.Rendering; @@ -23,53 +24,29 @@ namespace UnityFx.Outline /// /// var commandBuffer = new CommandBuffer(); /// - /// using (var renderer = new OutlineRenderer(commandBuffer, BuiltinRenderTextureType.CameraTarget)) + /// using (var renderer = new OutlineRenderer(commandBuffer, resources)) /// { - /// renderer.Render(renderers, resources, settings); + /// renderer.Render(renderers, settings); /// } /// /// camera.AddCommandBuffer(CameraEvent.BeforeImageEffects, commandBuffer); /// - /// - /// [Preserve] - /// public class OutlineEffectRenderer : PostProcessEffectRenderer - /// { - /// public override void Init() - /// { - /// base.Init(); - /// - /// // Reuse fullscreen triangle mesh from PostProcessing (do not create own). - /// settings.OutlineResources.FullscreenTriangleMesh = RuntimeUtilities.fullscreenTriangle; - /// } - /// - /// public override void Render(PostProcessRenderContext context) - /// { - /// var resources = settings.OutlineResources; - /// var layers = settings.OutlineLayers; - /// - /// if (resources && resources.IsValid && layers) - /// { - /// // No need to setup property sheet parameters, all the rendering staff is handled by the OutlineRenderer. - /// using (var renderer = new OutlineRenderer(context.command, context.source, context.destination)) - /// { - /// layers.Render(renderer, resources); - /// } - /// } - /// } - /// } - /// /// - public struct OutlineRenderer : IDisposable + public readonly struct OutlineRenderer : IDisposable { #region data - private static readonly int _mainRtId = Shader.PropertyToID("_MainTex"); + private const int _hPassId = 0; + private const int _vPassId = 1; + private const RenderTextureFormat _rtFormat = RenderTextureFormat.R8; + private static readonly int _maskRtId = Shader.PropertyToID("_MaskTex"); private static readonly int _hPassRtId = Shader.PropertyToID("_HPassTex"); - private readonly RenderTargetIdentifier _source; - private readonly RenderTargetIdentifier _destination; + private readonly RenderTargetIdentifier _rt; + private readonly RenderTargetIdentifier _depth; private readonly CommandBuffer _commandBuffer; + private readonly OutlineResources _resources; #endregion @@ -81,254 +58,233 @@ public struct OutlineRenderer : IDisposable public const CameraEvent RenderEvent = CameraEvent.BeforeImageEffects; /// - /// Name of the outline effect. - /// - public const string EffectName = "Outline"; - - /// - /// Minimum value of outline width parameter. - /// - /// - public const int MinWidth = 1; - - /// - /// Maximum value of outline width parameter. - /// - /// - public const int MaxWidth = 32; - - /// - /// Minimum value of outline intensity parameter. - /// - /// - /// - public const int MinIntensity = 1; - - /// - /// Maximum value of outline intensity parameter. - /// - /// - /// - public const int MaxIntensity = 64; - - /// - /// Value of outline intensity parameter that is treated as solid fill. + /// Initializes a new instance of the struct. /// - /// - /// - public const int SolidIntensity = 100; + /// A to render the effect to. It should be cleared manually (if needed) before passing to this method. + /// Outline resources. + /// Thrown if is . + public OutlineRenderer(CommandBuffer cmd, OutlineResources resources) + : this(cmd, resources, BuiltinRenderTextureType.CameraTarget, BuiltinRenderTextureType.Depth, Vector2Int.zero) + { + } /// /// Initializes a new instance of the struct. /// - /// A to render the effect to. It should be cleared manually (if needed) before passing to this method. - /// Render target. - /// Thrown if is . - public OutlineRenderer(CommandBuffer commandBuffer, BuiltinRenderTextureType rt) - : this(commandBuffer, rt, rt, Vector2Int.zero) + /// A to render the effect to. It should be cleared manually (if needed) before passing to this method. + /// Outline resources. + /// The rendering path of target camera (). + /// Thrown if is . + public OutlineRenderer(CommandBuffer cmd, OutlineResources resources, RenderingPath renderingPath) + : this(cmd, resources, BuiltinRenderTextureType.CameraTarget, GetBuiltinDepth(renderingPath), Vector2Int.zero) { } /// /// Initializes a new instance of the struct. /// - /// A to render the effect to. It should be cleared manually (if needed) before passing to this method. - /// Render target. - /// Thrown if is . - public OutlineRenderer(CommandBuffer commandBuffer, RenderTargetIdentifier rt) - : this(commandBuffer, rt, rt, Vector2Int.zero) + /// A to render the effect to. It should be cleared manually (if needed) before passing to this method. + /// Outline resources. + /// Render target. + /// Thrown if is . + public OutlineRenderer(CommandBuffer cmd, OutlineResources resources, RenderTargetIdentifier dst) + : this(cmd, resources, dst, BuiltinRenderTextureType.Depth, Vector2Int.zero) { } /// /// Initializes a new instance of the struct. /// - /// A to render the effect to. It should be cleared manually (if needed) before passing to this method. - /// Source image. Can be the same as . + /// A to render the effect to. It should be cleared manually (if needed) before passing to this method. /// Render target. - /// Thrown if is . - public OutlineRenderer(CommandBuffer commandBuffer, RenderTargetIdentifier src, RenderTargetIdentifier dst) - : this(commandBuffer, src, dst, Vector2Int.zero) + /// The rendering path of target camera (). + /// Thrown if is . + public OutlineRenderer(CommandBuffer cmd, OutlineResources resources, RenderTargetIdentifier dst, RenderingPath renderingPath, Vector2Int rtSize) + : this(cmd, resources, dst, GetBuiltinDepth(renderingPath), rtSize) { } /// /// Initializes a new instance of the struct. /// - /// A to render the effect to. It should be cleared manually (if needed) before passing to this method. - /// Source image. Can be the same as . + /// A to render the effect to. It should be cleared manually (if needed) before passing to this method. + /// Outline resources. /// Render target. - /// Size of the temporaty render textures. - /// Thrown if is . - public OutlineRenderer(CommandBuffer commandBuffer, RenderTargetIdentifier src, RenderTargetIdentifier dst, Vector2Int rtSize) + /// Depth dexture to use. + /// Thrown if is . + public OutlineRenderer(CommandBuffer cmd, OutlineResources resources, RenderTargetIdentifier dst, RenderTargetIdentifier depth, Vector2Int rtSize) { - if (commandBuffer == null) + if (cmd is null) { - throw new ArgumentNullException("commandBuffer"); + throw new ArgumentNullException(nameof(cmd)); } - var cx = rtSize.x > 0 ? rtSize.x : -1; - var cy = rtSize.y > 0 ? rtSize.y : -1; - - _source = src; - _destination = dst; + if (resources is null) + { + throw new ArgumentNullException(nameof(resources)); + } - _commandBuffer = commandBuffer; - _commandBuffer.BeginSample(EffectName); - _commandBuffer.GetTemporaryRT(_maskRtId, cx, cy, 0, FilterMode.Bilinear, RenderTextureFormat.R8); - _commandBuffer.GetTemporaryRT(_hPassRtId, cx, cy, 0, FilterMode.Bilinear, RenderTextureFormat.R8); + if (rtSize.x <= 0) + { + rtSize.x = -1; + } - // Need to copy src content into dst if they are not the same. For instance this is the case when rendering - // the outline effect as part of Unity Post Processing stack. - if (!src.Equals(dst)) + if (rtSize.y <= 0) { - if (SystemInfo.copyTextureSupport > CopyTextureSupport.None) - { - _commandBuffer.CopyTexture(src, dst); - } - else - { -#if UNITY_2018_2_OR_NEWER - _commandBuffer.SetRenderTarget(dst, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store); -#else - _commandBuffer.SetRenderTarget(dst); -#endif - _commandBuffer.Blit(src, BuiltinRenderTextureType.CurrentActive); - } + rtSize.y = -1; } + + cmd.GetTemporaryRT(_maskRtId, rtSize.x, rtSize.y, 0, FilterMode.Bilinear, _rtFormat); + cmd.GetTemporaryRT(_hPassRtId, rtSize.x, rtSize.y, 0, FilterMode.Bilinear, _rtFormat); + + _rt = dst; + _depth = depth; + _commandBuffer = cmd; + _resources = resources; } /// - /// Renders outline around a single object. This version allows enumeration of with no GC allocations. + /// Initializes a new instance of the struct. /// - /// One or more renderers representing a single object to be outlined. + /// A to render the effect to. It should be cleared manually (if needed) before passing to this method. /// Outline resources. - /// Outline settings. - /// Thrown if any of the arguments is . - /// - /// - public void Render(IList renderers, OutlineResources resources, IOutlineSettings settings) + /// Render target. + /// Depth dexture to use. + /// Render texture decsriptor. + /// Thrown if is . + public OutlineRenderer(CommandBuffer cmd, OutlineResources resources, RenderTargetIdentifier dst, RenderTargetIdentifier depth, RenderTextureDescriptor rtDesc) { - if (renderers == null) + if (cmd is null) + { + throw new ArgumentNullException(nameof(cmd)); + } + + if (resources is null) { - throw new ArgumentNullException("renderers"); + throw new ArgumentNullException(nameof(resources)); } - if (resources == null) + if (rtDesc.width <= 0) { - throw new ArgumentNullException("resources"); + rtDesc.width = -1; } - if (settings == null) + if (rtDesc.height <= 0) { - throw new ArgumentNullException("settings"); + rtDesc.height = -1; } - Init(resources, settings); - RenderObject(resources, settings, renderers); - RenderHPass(resources, settings); - RenderVPassBlend(resources, settings); + if (rtDesc.dimension == TextureDimension.None || rtDesc.dimension == TextureDimension.Unknown) + { + rtDesc.dimension = TextureDimension.Tex2D; + } + + rtDesc.shadowSamplingMode = ShadowSamplingMode.None; + rtDesc.depthBufferBits = 0; + rtDesc.colorFormat = _rtFormat; + rtDesc.volumeDepth = 1; + + cmd.GetTemporaryRT(_maskRtId, rtDesc, FilterMode.Bilinear); + cmd.GetTemporaryRT(_hPassRtId, rtDesc, FilterMode.Bilinear); + + _rt = dst; + _depth = depth; + _commandBuffer = cmd; + _resources = resources; } /// - /// Renders outline around a single object. + /// Renders outline around a single object. This version allows enumeration of with no GC allocations. + /// + /// An object to be outlined. + /// + /// + public void Render(OutlineRenderObject obj) + { + Render(obj.Renderers, obj.OutlineSettings, obj.Go.name); + } + + /// + /// Renders outline around a single object. This version allows enumeration of with no GC allocations. /// /// One or more renderers representing a single object to be outlined. - /// Outline resources. /// Outline settings. + /// Optional name of the sample (visible in profiler). /// Thrown if any of the arguments is . - /// - /// - public void Render(IEnumerable renderers, OutlineResources resources, IOutlineSettings settings) + /// + /// + public void Render(IReadOnlyList renderers, IOutlineSettings settings, string sampleName = null) { - if (renderers == null) + if (renderers is null) { - throw new ArgumentNullException("renderers"); + throw new ArgumentNullException(nameof(renderers)); } - if (resources == null) + if (settings is null) { - throw new ArgumentNullException("resources"); + throw new ArgumentNullException(nameof(settings)); } - if (settings == null) + if (renderers.Count > 0) { - throw new ArgumentNullException("settings"); - } + if (string.IsNullOrEmpty(sampleName)) + { + sampleName = renderers[0].name; + } - Init(resources, settings); - RenderObject(resources, settings, renderers); - RenderHPass(resources, settings); - RenderVPassBlend(resources, settings); + _commandBuffer.BeginSample(sampleName); + RenderObject(settings, renderers); + RenderOutline(settings); + _commandBuffer.EndSample(sampleName); + } } /// /// Renders outline around a single object. /// /// A representing an object to be outlined. - /// Outline resources. /// Outline settings. + /// Optional name of the sample (visible in profiler). /// Thrown if any of the arguments is . - /// - /// - public void Render(Renderer renderer, OutlineResources resources, IOutlineSettings settings) + /// + /// + public void Render(Renderer renderer, IOutlineSettings settings, string sampleName = null) { - if (renderer == null) + if (renderer is null) { - throw new ArgumentNullException("renderers"); + throw new ArgumentNullException(nameof(renderer)); } - if (resources == null) + if (settings is null) { - throw new ArgumentNullException("resources"); + throw new ArgumentNullException(nameof(settings)); } - if (settings == null) + if (string.IsNullOrEmpty(sampleName)) { - throw new ArgumentNullException("settings"); + sampleName = renderer.name; } - Init(resources, settings); - RenderObject(resources, settings, renderer); - RenderHPass(resources, settings); - RenderVPassBlend(resources, settings); + _commandBuffer.BeginSample(sampleName); + RenderObject(settings, renderer); + RenderOutline(settings); + _commandBuffer.EndSample(sampleName); } /// - /// Calculates value of Gauss function for the specified and values. + /// Gets depth texture identifier for built-in render pipeline. /// - /// - /// - public static float Gauss(float x, float stdDev) + public static RenderTargetIdentifier GetBuiltinDepth(RenderingPath renderingPath) { - var stdDev2 = stdDev * stdDev * 2; - var a = 1 / Mathf.Sqrt((float)Math.PI * stdDev2); - var gauss = a * Mathf.Pow((float)Math.E, -x * x / stdDev2); - - return gauss; + return (renderingPath == RenderingPath.DeferredShading || renderingPath == RenderingPath.DeferredLighting) ? BuiltinRenderTextureType.ResolvedDepth : BuiltinRenderTextureType.Depth; } /// - /// Samples Gauss function for the specified . + /// Creates a default instance or . /// - /// - public static float[] GetGaussSamples(int width, float[] samples) + public static RenderTextureDescriptor GetDefaultRtDesc() { - // NOTE: According to '3 sigma' rule there is no reason to have StdDev less then width / 3. - // In practice blur looks best when StdDev is within range [width / 3, width / 2]. - var stdDev = width * 0.5f; - - if (samples == null) - { - samples = new float[MaxWidth]; - } - - for (var i = 0; i < width; i++) - { - samples[i] = Gauss(i, stdDev); - } - - return samples; + return new RenderTextureDescriptor(-1, -1, RenderTextureFormat.R8, 0); } #endregion @@ -342,150 +298,96 @@ public void Dispose() { _commandBuffer.ReleaseTemporaryRT(_hPassRtId); _commandBuffer.ReleaseTemporaryRT(_maskRtId); - _commandBuffer.EndSample(EffectName); } #endregion #region implementation - private void Init(OutlineResources resources, IOutlineSettings settings) + private void RenderObjectClear(OutlineRenderFlags flags) { - _commandBuffer.SetGlobalFloatArray(resources.GaussSamplesId, resources.GetGaussSamples(settings.OutlineWidth)); - } - - private void RenderObjectClear(bool depthTestEnabled) - { - if (depthTestEnabled) + if ((flags & OutlineRenderFlags.EnableDepthTesting) != 0) { // NOTE: Use the camera depth buffer when rendering the mask. Shader only reads from the depth buffer (ZWrite Off). -#if UNITY_2018_2_OR_NEWER - _commandBuffer.SetRenderTarget(_maskRtId, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, BuiltinRenderTextureType.Depth, RenderBufferLoadAction.Load, RenderBufferStoreAction.DontCare); -#else - _commandBuffer.SetRenderTarget(_maskRtId, BuiltinRenderTextureType.Depth); -#endif + _commandBuffer.SetRenderTarget(_maskRtId, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, _depth, RenderBufferLoadAction.Load, RenderBufferStoreAction.DontCare); } else { -#if UNITY_2018_2_OR_NEWER _commandBuffer.SetRenderTarget(_maskRtId, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store); -#else - _commandBuffer.SetRenderTarget(_maskRtId); -#endif } _commandBuffer.ClearRenderTarget(false, true, Color.clear); } - private void RenderObject(OutlineResources resources, IOutlineSettings settings, IList renderers) + private void RenderObject(IOutlineSettings settings, IReadOnlyList renderers) { - RenderObjectClear((settings.OutlineRenderMode & OutlineRenderFlags.EnableDepthTesting) != 0); + RenderObjectClear(settings.OutlineRenderMode); for (var i = 0; i < renderers.Count; ++i) { var r = renderers[i]; - if (r && r.enabled && r.gameObject.activeInHierarchy) + if (r && r.enabled && r.isVisible && r.gameObject.activeInHierarchy) { // NOTE: Accessing Renderer.sharedMaterials triggers GC.Alloc. That's why we use a temporary // list of materials, cached with the outline resources. - r.GetSharedMaterials(resources.TmpMaterials); + r.GetSharedMaterials(_resources.TmpMaterials); - for (var j = 0; j < resources.TmpMaterials.Count; ++j) + for (var j = 0; j < _resources.TmpMaterials.Count; ++j) { - _commandBuffer.DrawRenderer(r, resources.RenderMaterial, j); + _commandBuffer.DrawRenderer(r, _resources.RenderMaterial, j); } } } } - private void RenderObject(OutlineResources resources, IOutlineSettings settings, IEnumerable renderers) + private void RenderObject(IOutlineSettings settings, Renderer renderer) { - RenderObjectClear((settings.OutlineRenderMode & OutlineRenderFlags.EnableDepthTesting) != 0); + RenderObjectClear(settings.OutlineRenderMode); - // NOTE: Calling IEnumerable.GetEnumerator() triggers GC.Alloc. - foreach (var r in renderers) - { - if (r && r.enabled && r.gameObject.activeInHierarchy) - { - // NOTE: Accessing Renderer.sharedMaterials triggers GC.Alloc. That's why we use a temporary - // list of materials, cached with the outline resources. - r.GetSharedMaterials(resources.TmpMaterials); - - for (var j = 0; j < resources.TmpMaterials.Count; ++j) - { - _commandBuffer.DrawRenderer(r, resources.RenderMaterial, j); - } - } - } - } - - private void RenderObject(OutlineResources resources, IOutlineSettings settings, Renderer renderer) - { - RenderObjectClear((settings.OutlineRenderMode & OutlineRenderFlags.EnableDepthTesting) != 0); - - if (renderer && renderer.gameObject.activeInHierarchy && renderer.enabled) + if (renderer && renderer.enabled && renderer.isVisible && renderer.gameObject.activeInHierarchy) { // NOTE: Accessing Renderer.sharedMaterials triggers GC.Alloc. That's why we use a temporary // list of materials, cached with the outline resources. - renderer.GetSharedMaterials(resources.TmpMaterials); + renderer.GetSharedMaterials(_resources.TmpMaterials); - for (var i = 0; i < resources.TmpMaterials.Count; ++i) + for (var i = 0; i < _resources.TmpMaterials.Count; ++i) { - _commandBuffer.DrawRenderer(renderer, resources.RenderMaterial, i); + _commandBuffer.DrawRenderer(renderer, _resources.RenderMaterial, i); } } } - private void RenderHPass(OutlineResources resources, IOutlineSettings settings) + private void RenderOutline(IOutlineSettings settings) { - // Setup shader parameter overrides. - var props = resources.HPassProperties; - props.SetFloat(resources.WidthId, settings.OutlineWidth); + var mat = _resources.OutlineMaterial; + var props = _resources.GetProperties(settings); - // Set source texture as _MainTex to match Blit behavior. - _commandBuffer.SetGlobalTexture(_mainRtId, _maskRtId); + _commandBuffer.SetGlobalFloatArray(_resources.GaussSamplesId, _resources.GetGaussSamples(settings.OutlineWidth)); - // Set destination texture as render target. -#if UNITY_2018_2_OR_NEWER + // HPass _commandBuffer.SetRenderTarget(_hPassRtId, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store); -#else - _commandBuffer.SetRenderTarget(_hPassRtId); -#endif + Blit(_commandBuffer, _maskRtId, _resources, _hPassId, mat, props); - // Blit fullscreen triangle. - _commandBuffer.DrawMesh(resources.FullscreenTriangleMesh, Matrix4x4.identity, resources.HPassMaterial, 0, 0, props); + // VPassBlend + _commandBuffer.SetRenderTarget(_rt, RenderBufferLoadAction.Load, RenderBufferStoreAction.Store); + Blit(_commandBuffer, _hPassRtId, _resources, _vPassId, mat, props); } - private void RenderVPassBlend(OutlineResources resources, IOutlineSettings settings) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void Blit(CommandBuffer cmdBuffer, RenderTargetIdentifier src, OutlineResources resources, int shaderPass, Material mat, MaterialPropertyBlock props) { - // Setup shader parameter overrides. - var props = resources.VPassBlendProperties; - - props.SetFloat(resources.WidthId, settings.OutlineWidth); - props.SetColor(resources.ColorId, settings.OutlineColor); + // Set source texture as _MainTex to match Blit behavior. + cmdBuffer.SetGlobalTexture(resources.MainTexId, src); - if ((settings.OutlineRenderMode & OutlineRenderFlags.Blurred) != 0) + if (SystemInfo.graphicsShaderLevel < 35 || resources.UseFullscreenTriangleMesh) { - props.SetFloat(resources.IntensityId, settings.OutlineIntensity); + cmdBuffer.DrawMesh(resources.FullscreenTriangleMesh, Matrix4x4.identity, mat, 0, shaderPass, props); } else { - props.SetFloat(resources.IntensityId, SolidIntensity); + cmdBuffer.DrawProcedural(Matrix4x4.identity, mat, shaderPass, MeshTopology.Triangles, 3, 1, props); } - - // Set source texture as _MainTex to match Blit behavior. - _commandBuffer.SetGlobalTexture(_mainRtId, _source); - - // Set destination texture as render target. -#if UNITY_2018_2_OR_NEWER - _commandBuffer.SetRenderTarget(_destination, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store); -#else - _commandBuffer.SetRenderTarget(_destination); -#endif - - // Blit fullscreen triangle. - _commandBuffer.DrawMesh(resources.FullscreenTriangleMesh, Matrix4x4.identity, resources.VPassBlendMaterial, 0, 0, props); } #endregion diff --git a/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineRenderer.cs.meta b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineRenderer.cs.meta index 90c49ef..6bfadc4 100644 --- a/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineRenderer.cs.meta +++ b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineRenderer.cs.meta @@ -1,7 +1,5 @@ fileFormatVersion: 2 guid: 4271470bd9f5d5041a4a8881d8457a55 -timeCreated: 1566150038 -licenseType: Free MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineRendererCollection.cs b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineRendererCollection.cs index 730e6dd..e157672 100644 --- a/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineRendererCollection.cs +++ b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineRendererCollection.cs @@ -25,7 +25,7 @@ internal OutlineRendererCollection(GameObject go) _go = go; } - internal List GetList() + internal IReadOnlyList GetList() { return _renderers; } @@ -39,49 +39,31 @@ internal void Reset(bool includeInactive, int ignoreLayerMask) { _renderers.Clear(); - var renderers = _go.GetComponentsInChildren(includeInactive); - - if (renderers != null) + if (ignoreLayerMask != 0) { - if (ignoreLayerMask != 0) - { - foreach (var renderer in renderers) - { - if (((1 << renderer.gameObject.layer) & ignoreLayerMask) == 0) - { - _renderers.Add(renderer); - } - } - } - else + var renderers = _go.GetComponentsInChildren(includeInactive); + + foreach (var renderer in renderers) { - foreach (var renderer in renderers) + if (((1 << renderer.gameObject.layer) & ignoreLayerMask) == 0) { _renderers.Add(renderer); } } } + else + { + _go.GetComponentsInChildren(includeInactive, _renderers); + } } #endregion #region ICollection - public int Count - { - get - { - return _renderers.Count; - } - } + public int Count => _renderers.Count; - public bool IsReadOnly - { - get - { - return false; - } - } + public bool IsReadOnly => false; public void Add(Renderer renderer) { @@ -130,14 +112,14 @@ IEnumerator IEnumerable.GetEnumerator() private void Validate(Renderer renderer) { - if (renderer == null) + if (renderer is null) { - throw new ArgumentNullException("renderer"); + throw new ArgumentNullException(nameof(renderer)); } if (!renderer.transform.IsChildOf(_go.transform)) { - throw new ArgumentException(string.Format("Only children of the {0} are allowed.", _go.name), "renderer"); + throw new ArgumentException(string.Format("Only children of the {0} are allowed.", _go.name), nameof(renderer)); } } diff --git a/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineResources.cs b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineResources.cs index 8d8f169..3431e1f 100644 --- a/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineResources.cs +++ b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineResources.cs @@ -17,36 +17,118 @@ public sealed class OutlineResources : ScriptableObject #region data private Material _renderMaterial; - private Material _hPassMaterial; - private Material _vPassMaterial; - private MaterialPropertyBlock _hPassProperties; - private MaterialPropertyBlock _vPassProperties; + private Material _outlineMaterial; + private MaterialPropertyBlock _props; private Mesh _fullscreenTriangleMesh; private float[][] _gaussSamples; + private bool _useDrawMesh; #endregion #region interface + /// + /// Minimum value of outline width parameter. + /// + /// + public const int MinWidth = 1; + + /// + /// Maximum value of outline width parameter. + /// + /// + public const int MaxWidth = 32; + + /// + /// Minimum value of outline intensity parameter. + /// + /// + /// + public const int MinIntensity = 1; + + /// + /// Maximum value of outline intensity parameter. + /// + /// + /// + public const int MaxIntensity = 64; + + /// + /// Value of outline intensity parameter that is treated as solid fill. + /// + /// + /// + public const int SolidIntensity = 100; + + /// + /// Name of _MainTex shader parameter. + /// + public const string MainTexName = "_MainTex"; + + /// + /// Name of _Color shader parameter. + /// + public const string ColorName = "_Color"; + + /// + /// Name of _Width shader parameter. + /// + public const string WidthName = "_Width"; + + /// + /// Name of _Intensity shader parameter. + /// + public const string IntensityName = "_Intensity"; + + /// + /// Name of _GaussSamples shader parameter. + /// + public const string GaussSamplesName = "_GaussSamples"; + + /// + /// Name of the _USE_DRAWMESH shader feature. + /// + public const string UseDrawMeshFeatureName = "_USE_DRAWMESH"; + + /// + /// Name of the outline effect. + /// + public const string EffectName = "Outline"; + + /// + /// Tooltip text for field. + /// + public const string OutlineResourcesTooltip = "Outline resources to use (shaders, materials etc). Do not change defaults unless you know what you're doing."; + + /// + /// Tooltip text for field. + /// + public const string OutlineLayerCollectionTooltip = "Collection of outline layers to use. This can be used to share outline settings between multiple cameras."; + + /// + /// Hashed name of _MainTex shader parameter. + /// + public readonly int MainTexId = Shader.PropertyToID(MainTexName); + /// /// Hashed name of _Color shader parameter. /// - public readonly int ColorId = Shader.PropertyToID("_Color"); + public readonly int ColorId = Shader.PropertyToID(ColorName); /// /// Hashed name of _Width shader parameter. /// - public readonly int WidthId = Shader.PropertyToID("_Width"); + public readonly int WidthId = Shader.PropertyToID(WidthName); /// /// Hashed name of _Intensity shader parameter. /// - public readonly int IntensityId = Shader.PropertyToID("_Intensity"); + public readonly int IntensityId = Shader.PropertyToID(IntensityName); /// /// Hashed name of _GaussSamples shader parameter. /// - public readonly int GaussSamplesId = Shader.PropertyToID("_GaussSamples"); + public readonly int GaussSamplesId = Shader.PropertyToID(GaussSamplesName); /// /// Temp materials list. Used by to avoid GC allocations. @@ -59,14 +141,9 @@ public sealed class OutlineResources : ScriptableObject public Shader RenderShader; /// - /// Gets or sets a that renders outline around the mask, that was generated with (pass 1). - /// - public Shader HPassShader; - - /// - /// Gets or sets a that renders outline around the mask, that was generated with and (pass 2). + /// Gets or sets a that renders outline around the mask, that was generated with . /// - public Shader VPassBlendShader; + public Shader OutlineShader; /// /// Gets a -based material. @@ -79,7 +156,7 @@ public Material RenderMaterial { _renderMaterial = new Material(RenderShader) { - name = "Outline - SimpleRender", + name = "Outline - RenderColor", hideFlags = HideFlags.HideAndDontSave }; } @@ -89,80 +166,55 @@ public Material RenderMaterial } /// - /// Gets a -based material. + /// Gets a -based material. /// - public Material HPassMaterial + public Material OutlineMaterial { get { - if (_hPassMaterial == null) + if (_outlineMaterial == null) { - _hPassMaterial = new Material(HPassShader) + _outlineMaterial = new Material(OutlineShader) { - name = "Outline - HPassRender", + name = "Outline - Main", hideFlags = HideFlags.HideAndDontSave }; - } - - return _hPassMaterial; - } - } - /// - /// Gets a -based material. - /// - public Material VPassBlendMaterial - { - get - { - if (_vPassMaterial == null) - { - _vPassMaterial = new Material(VPassBlendShader) + if (_useDrawMesh) { - name = "Outline - VPassBlendRender", - hideFlags = HideFlags.HideAndDontSave - }; + _outlineMaterial.EnableKeyword(UseDrawMeshFeatureName); + } } - return _vPassMaterial; - } - } - - /// - /// Gets a for . - /// - public MaterialPropertyBlock HPassProperties - { - get - { - if (_hPassProperties == null) - { - _hPassProperties = new MaterialPropertyBlock(); - } - - return _hPassProperties; + return _outlineMaterial; } } /// /// Gets a for . /// - public MaterialPropertyBlock VPassBlendProperties + public MaterialPropertyBlock Properties { get { - if (_vPassProperties == null) + if (_props is null) { - _vPassProperties = new MaterialPropertyBlock(); + _props = new MaterialPropertyBlock(); } - return _vPassProperties; + return _props; } } /// - /// Gets or sets a fullscreen triangle mesh. + /// Gets or sets a fullscreen triangle mesh. The mesh is lazy-initialized on the first access. /// + /// + /// This is used by to avoid Blit() calls and use DrawMesh() passing + /// this mesh as the first argument. When running on a device with Shader Model 3.5 support this + /// should not be used at all, as the vertices are generated in vertex shader with DrawProcedural() call. + /// + /// public Mesh FullscreenTriangleMesh { get @@ -173,8 +225,8 @@ public Mesh FullscreenTriangleMesh { name = "Outline - FullscreenTriangle", hideFlags = HideFlags.HideAndDontSave, - vertices = new Vector3[] { new Vector3(-1f, -1f, 0f), new Vector3(-1f, 3f, 0f), new Vector3( 3f, -1f, 0f) }, - triangles = new int[] {0, 1, 2 } + vertices = new Vector3[] { new Vector3(-1, -1, 0), new Vector3(3, -1, 0), new Vector3(-1, 3, 0) }, + triangles = new int[] { 0, 1, 2 } }; _fullscreenTriangleMesh.UploadMeshData(true); @@ -189,31 +241,80 @@ public Mesh FullscreenTriangleMesh } /// - /// Gets a value indicating whether the instance is in valid state. + /// Gets or sets a value indicating whether is used for image effects rendering even when procedural rendering is available. /// - public bool IsValid + public bool UseFullscreenTriangleMesh { get { - return RenderShader && HPassShader && VPassBlendShader; + return _useDrawMesh; + } + set + { + if (_useDrawMesh != value) + { + _useDrawMesh = value; + + if (_outlineMaterial) + { + if (_useDrawMesh) + { + _outlineMaterial.EnableKeyword(UseDrawMeshFeatureName); + } + else + { + _outlineMaterial.DisableKeyword(UseDrawMeshFeatureName); + } + } + } } } + /// + /// Gets a value indicating whether the instance is in valid state. + /// + public bool IsValid => RenderShader && OutlineShader; + + /// + /// Returns a instance initialized with values from . + /// + public MaterialPropertyBlock GetProperties(IOutlineSettings settings) + { + if (_props is null) + { + _props = new MaterialPropertyBlock(); + } + + _props.SetFloat(WidthId, settings.OutlineWidth); + _props.SetColor(ColorId, settings.OutlineColor); + + if ((settings.OutlineRenderMode & OutlineRenderFlags.Blurred) != 0) + { + _props.SetFloat(IntensityId, settings.OutlineIntensity); + } + else + { + _props.SetFloat(IntensityId, SolidIntensity); + } + + return _props; + } + /// /// Gets cached gauss samples for the specified outline . /// public float[] GetGaussSamples(int width) { - var index = Mathf.Clamp(width, 1, OutlineRenderer.MaxWidth) - 1; + var index = Mathf.Clamp(width, 1, MaxWidth) - 1; - if (_gaussSamples == null) + if (_gaussSamples is null) { - _gaussSamples = new float[OutlineRenderer.MaxWidth][]; + _gaussSamples = new float[MaxWidth][]; } - if (_gaussSamples[index] == null) + if (_gaussSamples[index] is null) { - _gaussSamples[index] = OutlineRenderer.GetGaussSamples(width, null); + _gaussSamples[index] = GetGaussSamples(width, null); } return _gaussSamples[index]; @@ -224,9 +325,45 @@ public float[] GetGaussSamples(int width) /// public void ResetToDefaults() { - RenderShader = Shader.Find("UnityFx/Outline/RenderColor"); - HPassShader = Shader.Find("UnityFx/Outline/HPass"); - VPassBlendShader = Shader.Find("UnityFx/Outline/VPassBlend"); + RenderShader = Shader.Find("Hidden/UnityFx/OutlineColor"); + OutlineShader = Shader.Find("Hidden/UnityFx/Outline"); + } + + /// + /// Calculates value of Gauss function for the specified and values. + /// + /// + /// + public static float Gauss(float x, float stdDev) + { + var stdDev2 = stdDev * stdDev * 2; + var a = 1 / Mathf.Sqrt(Mathf.PI * stdDev2); + var gauss = a * Mathf.Pow((float)Math.E, -x * x / stdDev2); + + return gauss; + } + + /// + /// Samples Gauss function for the specified . + /// + /// + public static float[] GetGaussSamples(int width, float[] samples) + { + // NOTE: According to '3 sigma' rule there is no reason to have StdDev less then width / 3. + // In practice blur looks best when StdDev is within range [width / 3, width / 2]. + var stdDev = width * 0.5f; + + if (samples is null) + { + samples = new float[MaxWidth]; + } + + for (var i = 0; i < width; i++) + { + samples[i] = Gauss(i, stdDev); + } + + return samples; } #endregion diff --git a/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineSettings.cs b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineSettings.cs index 2535031..1b6fe4b 100644 --- a/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineSettings.cs +++ b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineSettings.cs @@ -67,7 +67,7 @@ public int OutlineWidth } set { - _outlineWidth = Mathf.Clamp(value, OutlineRenderer.MinWidth, OutlineRenderer.MaxWidth); + _outlineWidth = Mathf.Clamp(value, OutlineResources.MinWidth, OutlineResources.MaxWidth); } } @@ -80,7 +80,7 @@ public float OutlineIntensity } set { - _outlineIntensity = Mathf.Clamp(value, OutlineRenderer.MinIntensity, OutlineRenderer.MaxIntensity); + _outlineIntensity = Mathf.Clamp(value, OutlineResources.MinIntensity, OutlineResources.MaxIntensity); } } diff --git a/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineSettingsInstance.cs b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineSettingsInstance.cs index a39ef7e..b887cdd 100644 --- a/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineSettingsInstance.cs +++ b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/OutlineSettingsInstance.cs @@ -7,7 +7,7 @@ namespace UnityFx.Outline { [Serializable] - internal class OutlineSettingsInstance : IOutlineSettingsEx + internal class OutlineSettingsInstance : IOutlineSettings { #region data @@ -27,52 +27,18 @@ internal class OutlineSettingsInstance : IOutlineSettingsEx #pragma warning restore 0649 - private OutlineResources _resources; - #endregion #region interface - public OutlineResources OutlineResources - { - get - { - return _resources; - } - set - { - _resources = value; - } - } - public bool RequiresCameraDepth { get { - var renderMode = _outlineMode; - - if (!ReferenceEquals(_outlineSettings, null)) - { - renderMode = _outlineSettings.OutlineRenderMode; - } - - return (renderMode & OutlineRenderFlags.EnableDepthTesting) != 0; + return (OutlineRenderMode & OutlineRenderFlags.EnableDepthTesting) != 0; } } - internal OutlineSettingsInstance() - { - } - - internal OutlineSettingsInstance(OutlineResources resources) - { - _resources = resources; - } - - #endregion - - #region IOutlineSettingsEx - public OutlineSettings OutlineSettings { get @@ -94,12 +60,7 @@ public Color OutlineColor { get { - if (!ReferenceEquals(_outlineSettings, null)) - { - return _outlineSettings.OutlineColor; - } - - return _outlineColor; + return _outlineSettings is null ? _outlineColor : _outlineSettings.OutlineColor; } set { @@ -112,16 +73,11 @@ public int OutlineWidth { get { - if (!ReferenceEquals(_outlineSettings, null)) - { - return _outlineSettings.OutlineWidth; - } - - return _outlineWidth; + return _outlineSettings is null ? _outlineWidth : _outlineSettings.OutlineWidth; } set { - _outlineWidth = Mathf.Clamp(value, OutlineRenderer.MinWidth, OutlineRenderer.MaxWidth); + _outlineWidth = Mathf.Clamp(value, OutlineResources.MinWidth, OutlineResources.MaxWidth); } } @@ -130,16 +86,11 @@ public float OutlineIntensity { get { - if (!ReferenceEquals(_outlineSettings, null)) - { - return _outlineSettings.OutlineIntensity; - } - - return _outlineIntensity; + return _outlineSettings is null ? _outlineIntensity : _outlineSettings.OutlineIntensity; } set { - _outlineIntensity = Mathf.Clamp(value, OutlineRenderer.MinIntensity, OutlineRenderer.MaxIntensity); + _outlineIntensity = Mathf.Clamp(value, OutlineResources.MinIntensity, OutlineResources.MaxIntensity); } } @@ -148,12 +99,7 @@ public OutlineRenderFlags OutlineRenderMode { get { - if (!ReferenceEquals(_outlineSettings, null)) - { - return _outlineSettings.OutlineRenderMode; - } - - return _outlineMode; + return _outlineSettings is null ? _outlineMode : _outlineSettings.OutlineRenderMode; } set { diff --git a/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/Properties/Startup.cs b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/Properties/Startup.cs new file mode 100644 index 0000000..7925a95 --- /dev/null +++ b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/Properties/Startup.cs @@ -0,0 +1,10 @@ +// Copyright (C) 2019-2020 Alexander Bogarsukov. All rights reserved. +// See the LICENSE.md file in the project root for more information. + +#if !UNITY_2018_4_OR_NEWER +#error UnityFx.Outline requires Unity 2018.4 or newer. +#endif + +#if NET_LEGACY || NET_2_0 || NET_2_0_SUBSET +#error UnityFx.Outline does not support .NET 3.5. Please set Scripting Runtime Version to .NET 4.x Equivalent in Unity Player Settings. +#endif diff --git a/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/Properties/Startup.cs.meta b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/Properties/Startup.cs.meta new file mode 100644 index 0000000..b4865cd --- /dev/null +++ b/Outline.Core/Packages/UnityFx.Outline/Runtime/Scripts/Properties/Startup.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 955bb53eefa37054cb49969575341469 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Outline.Core/Packages/UnityFx.Outline/Runtime/Shaders/Outline.shader b/Outline.Core/Packages/UnityFx.Outline/Runtime/Shaders/Outline.shader new file mode 100644 index 0000000..ec2be87 --- /dev/null +++ b/Outline.Core/Packages/UnityFx.Outline/Runtime/Shaders/Outline.shader @@ -0,0 +1,186 @@ +// Copyright (C) 2019-2020 Alexander Bogarsukov. All rights reserved. +// See the LICENSE.md file in the project root for more information. + +// Renders outline based on a texture produced with 'UnityF/OutlineColor'. +// Modified version of 'Custom/Post Outline' shader taken from https://willweissman.wordpress.com/tutorials/shaders/unity-shaderlab-object-outlines/. +Shader "Hidden/UnityFx/Outline" +{ + Properties + { + _Width("Outline thickness (in pixels)", Range(1, 32)) = 5 + _Intensity("Outline intensity", Range(0.1, 100)) = 2 + _Color("Outline color", Color) = (1, 0, 0, 1) + } + + HLSLINCLUDE + + #include "UnityCG.cginc" + + CBUFFER_START(UnityPerMaterial) + float _Intensity; + int _Width; + float4 _Color; + CBUFFER_END + + UNITY_DECLARE_SCREENSPACE_TEXTURE(_MaskTex); + UNITY_DECLARE_SCREENSPACE_TEXTURE(_MainTex); + float2 _MainTex_TexelSize; + float _GaussSamples[32]; + +#if SHADER_TARGET < 35 || _USE_DRAWMESH + + v2f_img vert(appdata_img v) + { + v2f_img o; + UNITY_INITIALIZE_OUTPUT(v2f_img, o); + UNITY_SETUP_INSTANCE_ID(v); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); + + o.pos = float4(v.vertex.xy, UNITY_NEAR_CLIP_VALUE, 1); + o.uv = ComputeScreenPos(o.pos); + + return o; + } + +#else + + struct appdata_vid + { + uint vertexID : SV_VertexID; + UNITY_VERTEX_INPUT_INSTANCE_ID + }; + + float4 GetFullScreenTriangleVertexPosition(uint vertexID, float z) + { + // Generates a triangle in homogeneous clip space, s.t. + // v0 = (-1, -1, 1), v1 = (3, -1, 1), v2 = (-1, 3, 1). + float2 uv = float2((vertexID << 1) & 2, vertexID & 2); + return float4(uv * 2 - 1, z, 1); + } + + v2f_img vert(appdata_vid v) + { + v2f_img o; + UNITY_INITIALIZE_OUTPUT(v2f_img, o); + UNITY_SETUP_INSTANCE_ID(v); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); + + o.pos = GetFullScreenTriangleVertexPosition(v.vertexID, UNITY_NEAR_CLIP_VALUE); + o.uv = ComputeScreenPos(o.pos); + + return o; + } + +#endif + + float CalcIntensity(float2 uv, float2 offset) + { + float intensity = 0; + + // Accumulates horizontal or vertical blur intensity for the specified texture position. + // Set offset = (tx, 0) for horizontal sampling and offset = (0, ty) for vertical. + for (int k = -_Width; k <= _Width; ++k) + { + intensity += UNITY_SAMPLE_SCREENSPACE_TEXTURE(_MainTex, uv + k * offset).r * _GaussSamples[abs(k)]; + } + + return intensity; + } + + float4 frag_h(v2f_img i) : SV_Target + { + float intensity = CalcIntensity(i.uv, float2(_MainTex_TexelSize.x, 0)); + return float4(intensity, intensity, intensity, 1); + } + + float4 frag_v(v2f_img i) : SV_Target + { + if (UNITY_SAMPLE_SCREENSPACE_TEXTURE(_MaskTex, i.uv).r > 0) + { + // TODO: Avoid discard/clip to improve performance on mobiles. + discard; + } + + float intensity = CalcIntensity(i.uv, float2(0, _MainTex_TexelSize.y)); + intensity = _Intensity > 99 ? step(0.01, intensity) : intensity * _Intensity; + return float4(_Color.rgb, saturate(_Color.a * intensity)); + } + + ENDHLSL + + // SM3.5+ + SubShader + { + Cull Off + ZWrite Off + ZTest Always + Lighting Off + + // 0) HPass + Pass + { + Name "HPass" + + HLSLPROGRAM + + #pragma target 3.5 + #pragma shader_feature_local _USE_DRAWMESH + #pragma vertex vert + #pragma fragment frag_h + + ENDHLSL + } + + // 1) VPass + Pass + { + Name "VPassBlend" + Blend SrcAlpha OneMinusSrcAlpha + + HLSLPROGRAM + + #pragma target 3.5 + #pragma shader_feature_local _USE_DRAWMESH + #pragma vertex vert + #pragma fragment frag_v + + ENDHLSL + } + } + + // SM2.0 + SubShader + { + Cull Off + ZWrite Off + ZTest Always + Lighting Off + + // 0) HPass + Pass + { + Name "HPass" + + HLSLPROGRAM + + #pragma vertex vert + #pragma fragment frag_h + + ENDHLSL + } + + // 1) VPass + Pass + { + Name "VPassBlend" + Blend SrcAlpha OneMinusSrcAlpha + + HLSLPROGRAM + + #pragma vertex vert + #pragma fragment frag_v + + ENDHLSL + } + } +} diff --git a/Outline.Core/Packages/UnityFx.Outline/Runtime/Shaders/OutlinePass1.shader.meta b/Outline.Core/Packages/UnityFx.Outline/Runtime/Shaders/Outline.shader.meta similarity index 100% rename from Outline.Core/Packages/UnityFx.Outline/Runtime/Shaders/OutlinePass1.shader.meta rename to Outline.Core/Packages/UnityFx.Outline/Runtime/Shaders/Outline.shader.meta diff --git a/Outline.Core/Packages/UnityFx.Outline/Runtime/Shaders/OutlineRenderColor.shader b/Outline.Core/Packages/UnityFx.Outline/Runtime/Shaders/OutlineColor.shader similarity index 58% rename from Outline.Core/Packages/UnityFx.Outline/Runtime/Shaders/OutlineRenderColor.shader rename to Outline.Core/Packages/UnityFx.Outline/Runtime/Shaders/OutlineColor.shader index bf53276..bca1a57 100644 --- a/Outline.Core/Packages/UnityFx.Outline/Runtime/Shaders/OutlineRenderColor.shader +++ b/Outline.Core/Packages/UnityFx.Outline/Runtime/Shaders/OutlineColor.shader @@ -3,8 +3,19 @@ // Renders everything with while color. // Modified version of 'Custom/DrawSimple' shader taken from https://willweissman.wordpress.com/tutorials/shaders/unity-shaderlab-object-outlines/. -Shader "UnityFx/Outline/RenderColor" +Shader "Hidden/UnityFx/OutlineColor" { + HLSLINCLUDE + + #include "UnityCG.cginc" + + half4 frag() : SV_Target + { + return 1; + } + + ENDHLSL + SubShader { Cull Off @@ -16,26 +27,8 @@ Shader "UnityFx/Outline/RenderColor" { HLSLPROGRAM - #pragma vertex Vert - #pragma fragment Frag - #include "UnityCG.cginc" - - struct v2f - { - float4 pos: POSITION; - }; - - v2f Vert(v2f i) - { - v2f o; - o.pos = UnityObjectToClipPos(i.pos); - return o; - } - - half4 Frag(): COLOR0 - { - return half4(1, 1, 1, 1); - } + #pragma vertex vert_img + #pragma fragment frag ENDHLSL } diff --git a/Outline.Core/Packages/UnityFx.Outline/Runtime/Shaders/OutlineRenderColor.shader.meta b/Outline.Core/Packages/UnityFx.Outline/Runtime/Shaders/OutlineColor.shader.meta similarity index 100% rename from Outline.Core/Packages/UnityFx.Outline/Runtime/Shaders/OutlineRenderColor.shader.meta rename to Outline.Core/Packages/UnityFx.Outline/Runtime/Shaders/OutlineColor.shader.meta diff --git a/Outline.Core/Packages/UnityFx.Outline/Runtime/Shaders/OutlinePass1.shader b/Outline.Core/Packages/UnityFx.Outline/Runtime/Shaders/OutlinePass1.shader deleted file mode 100644 index 2febb62..0000000 --- a/Outline.Core/Packages/UnityFx.Outline/Runtime/Shaders/OutlinePass1.shader +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (C) 2019-2020 Alexander Bogarsukov. All rights reserved. -// See the LICENSE.md file in the project root for more information. - -// Renders outline based on a texture produces by 'UnityF/Outline/RenderColor' output. -// Modified version of 'Custom/Post Outline' shader taken from https://willweissman.wordpress.com/tutorials/shaders/unity-shaderlab-object-outlines/. -Shader "UnityFx/Outline/HPass" -{ - Properties - { - _Width("Outline thickness (in pixels)", Range(1, 32)) = 5 - } - - SubShader - { - Cull Off - ZWrite Off - ZTest Always - Lighting Off - - Pass - { - HLSLPROGRAM - - #pragma vertex Vert - #pragma fragment Frag - #include "UnityCG.cginc" - - CBUFFER_START(UnityPerMaterial) - int _Width; - CBUFFER_END - - UNITY_DECLARE_TEX2D(_MaskTex); - float2 _MaskTex_TexelSize; - float _GaussSamples[32]; - - struct v2f - { - float4 pos : POSITION; - float2 uvs : TEXCOORD0; - }; - - v2f Vert(appdata_base v) - { - v2f o; - - o.pos = float4(v.vertex.xy, 0.0, 1.0); - o.uvs = ComputeScreenPos(o.pos); - - return o; - } - - float Frag(v2f i) : COLOR - { - float TX_x = _MaskTex_TexelSize.x; - float intensity; - int n = _Width; - - for (int k = -n; k <= n; k += 1) - { - intensity += UNITY_SAMPLE_TEX2D(_MaskTex, i.uvs.xy + float2(k * TX_x, 0)).r * _GaussSamples[abs(k)]; - } - - return intensity; - } - - ENDHLSL - } - } -} diff --git a/Outline.Core/Packages/UnityFx.Outline/Runtime/Shaders/OutlinePass2.shader b/Outline.Core/Packages/UnityFx.Outline/Runtime/Shaders/OutlinePass2.shader deleted file mode 100644 index dbf1a18..0000000 --- a/Outline.Core/Packages/UnityFx.Outline/Runtime/Shaders/OutlinePass2.shader +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (C) 2019-2020 Alexander Bogarsukov. All rights reserved. -// See the LICENSE.md file in the project root for more information. - -// Renders outline based on a texture produces by 'UnityF/Outline/RenderColor' output. -// Modified version of 'Custom/Post Outline' shader taken from https://willweissman.wordpress.com/tutorials/shaders/unity-shaderlab-object-outlines/. -Shader "UnityFx/Outline/VPassBlend" -{ - Properties - { - _Width("Outline thickness (in pixels)", Range(1, 32)) = 5 - _Intensity("Outline intensity", Range(0.1, 100)) = 2 - _Color("Outline color", Color) = (1, 0, 0, 1) - } - - SubShader - { - Cull Off - ZWrite Off - ZTest Always - Lighting Off - - Blend SrcAlpha OneMinusSrcAlpha - - Pass - { - HLSLPROGRAM - - #pragma vertex Vert - #pragma fragment Frag - #include "UnityCG.cginc" - - CBUFFER_START(UnityPerMaterial) - float _Intensity; - int _Width; - float4 _Color; - CBUFFER_END - - UNITY_DECLARE_TEX2D(_MaskTex); - float2 _MaskTex_TexelSize; - UNITY_DECLARE_TEX2D(_HPassTex); - float2 _HPassTex_TexelSize; - float _GaussSamples[32]; - - struct v2f - { - float4 pos : POSITION; - float2 uvs : TEXCOORD0; - }; - - v2f Vert(appdata_base v) - { - v2f o; - - o.pos = float4(v.vertex.xy, 0.0, 1.0); - o.uvs = ComputeScreenPos(o.pos); - - return o; - } - - float4 Frag(v2f i) : COLOR - { - if (UNITY_SAMPLE_TEX2D(_MaskTex, i.uvs.xy).r > 0) - { - discard; - } - - float TX_y = _MaskTex_TexelSize.y; - float intensity; - int n = _Width; - - for (int k = -n; k <= _Width; k += 1) - { - intensity += UNITY_SAMPLE_TEX2D(_HPassTex, i.uvs.xy + float2(0, k * TX_y)).r * _GaussSamples[abs(k)]; - } - - intensity = _Intensity > 99 ? step(0.01, intensity) : intensity * _Intensity; - return float4(_Color.rgb, saturate(_Color.a * intensity)); - } - - ENDHLSL - } - } -} diff --git a/Outline.Core/Packages/UnityFx.Outline/package.json b/Outline.Core/Packages/UnityFx.Outline/package.json index b41e8a4..6dc340f 100644 --- a/Outline.Core/Packages/UnityFx.Outline/package.json +++ b/Outline.Core/Packages/UnityFx.Outline/package.json @@ -1,9 +1,9 @@ { "name": "com.unityfx.outline", - "version": "0.7.2", - "displayName": "Screen-space outline", - "description": "Configurable per-object and per-camera outline effect implementation for built-in render pipeline. Both solid and blurred outline modes are supported (Gauss blur). Scriptable render pipeline is not supported.", - "unity": "2017.2", + "version": "0.8.0", + "displayName": "Outline toolkit", + "description": "This package contains configurable per-object and per-camera outline effect implementation for built-in render pipeline. Both solid and blurred outline modes are supported (Gauss blur), as well as depth testing. Reusable and extensible API.", + "unity": "2018.4", "keywords": [ "UnityFx", "UnityFx.Outline", diff --git a/Outline.Core/ProjectSettings/EditorBuildSettings.asset b/Outline.Core/ProjectSettings/EditorBuildSettings.asset index 0147887..d5c9d72 100644 --- a/Outline.Core/ProjectSettings/EditorBuildSettings.asset +++ b/Outline.Core/ProjectSettings/EditorBuildSettings.asset @@ -4,5 +4,8 @@ EditorBuildSettings: m_ObjectHideFlags: 0 serializedVersion: 2 - m_Scenes: [] + m_Scenes: + - enabled: 1 + path: Assets/Examples/SimplePerCamera/Outline.unity + guid: e1f1f5e7ceb61b746b9f2016f0e53a93 m_configObjects: {} diff --git a/Outline.HDRP/Assets/Example/Test.unity b/Outline.HDRP/Assets/Example/Test.unity index 4d65fc6..e6e52f5 100644 --- a/Outline.HDRP/Assets/Example/Test.unity +++ b/Outline.HDRP/Assets/Example/Test.unity @@ -444,6 +444,39 @@ MonoBehaviour: - {fileID: 646807773} - {fileID: 750107942} _layers: {fileID: 11400000, guid: 65159dc68f867cd4f90261bae63e29a7, type: 2} +--- !u!114 &1130691894 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1130691892} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 26d6499a6bd256e47b859377446493a1, type: 3} + m_Name: + m_EditorClassIdentifier: + isGlobal: 1 + fadeRadius: 0 + customPasses: + - id: 0 + injectionPoint: 2 + references: + version: 1 + 00000000: + type: {class: OutlinePass, ns: UnityFx.Outline.HDRP, asm: UnityFx.Outline.HDRP} + data: + name: Outline + enabled: 1 + targetColorBuffer: 0 + targetDepthBuffer: 0 + clearFlags: 0 + passFoldout: 0 + m_Version: 0 + _outlineResources: {fileID: 11400000, guid: d28e70f030b1a634db9a6a6d5478ef19, + type: 2} + _outlineLayers: {fileID: 11400000, guid: 65159dc68f867cd4f90261bae63e29a7, + type: 2} --- !u!1 &1202059779 GameObject: m_ObjectHideFlags: 0 diff --git a/Outline.HDRP/Packages/UnityFx.Outline.HDRP/Runtime/Scripts/Outline.cs b/Outline.HDRP/Packages/UnityFx.Outline.HDRP/Runtime/Scripts/Outline.cs deleted file mode 100644 index 0293025..0000000 --- a/Outline.HDRP/Packages/UnityFx.Outline.HDRP/Runtime/Scripts/Outline.cs +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright (C) 2019-2020 Alexander Bogarsukov. All rights reserved. -// See the LICENSE.md file in the project root for more information. - -using System; -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.Rendering; -using UnityEngine.Rendering.HighDefinition; - -namespace UnityFx.Outline.HDRP -{ - [Serializable] - [VolumeComponentMenu("Post-processing/UnityFx/Outline")] - public sealed class Outline : CustomPostProcessVolumeComponent, IPostProcessComponent - { - #region data - -#pragma warning disable 0649 - - [Serializable] - private class OutlineResourcesParameter : VolumeParameter - { - } - - [Serializable] - private class OutlineLayersParameter : VolumeParameter - { - } - - [SerializeField, HideInInspector] - private OutlineResources _defaultResources; - [SerializeField] - private OutlineResourcesParameter _resources = new OutlineResourcesParameter(); - [SerializeField] - private OutlineLayersParameter _layers = new OutlineLayersParameter(); - -#pragma warning restore 0649 - - #endregion - - #region interface - - public IList OutlineLayers - { - get - { - return _layers.value; - } - } - - #endregion - - #region CustomPostProcessVolumeComponent - - public override CustomPostProcessInjectionPoint injectionPoint - { - get - { - return CustomPostProcessInjectionPoint.BeforePostProcess; - } - } - - public override void Setup() - { - base.Setup(); - } - - public override void Render(CommandBuffer cmd, HDCamera camera, RTHandle source, RTHandle destination) - { - using (var renderer = new OutlineRenderer(cmd, source, destination, source.referenceSize)) - { - _layers.value.Render(renderer, _resources.value); - } - } - - public override void Cleanup() - { - base.Cleanup(); - } - - #endregion - - #region ScriptableObject - - protected override void OnEnable() - { - // NOTE: This should go before base.OnEnable(). - if (!_resources.value) - { - _resources.value = _defaultResources; - } - - base.OnEnable(); - } - - #endregion - - #region IPostProcessComponent - - public bool IsActive() - { - if (!Application.isPlaying) - { - return false; - } - - if (_resources == null || _layers == null) - { - return false; - } - - var r = _resources.value; - - if (r == null || !r.IsValid) - { - return false; - } - - var l = _layers.value; - - if (l == null || l.Count == 0) - { - return false; - } - - return true; - } - - #endregion - } -} diff --git a/Outline.HDRP/Packages/UnityFx.Outline.HDRP/Runtime/Scripts/OutlinePass.cs b/Outline.HDRP/Packages/UnityFx.Outline.HDRP/Runtime/Scripts/OutlinePass.cs new file mode 100644 index 0000000..425a186 --- /dev/null +++ b/Outline.HDRP/Packages/UnityFx.Outline.HDRP/Runtime/Scripts/OutlinePass.cs @@ -0,0 +1,63 @@ +// Copyright (C) 2019-2020 Alexander Bogarsukov. All rights reserved. +// See the LICENSE.md file in the project root for more information. + +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.Rendering.HighDefinition; + +namespace UnityFx.Outline.HDRP +{ + /// + /// + /// + public sealed class OutlinePass : CustomPass + { + #region data + +#pragma warning disable 0649 + + [SerializeField, Tooltip(OutlineResources.OutlineResourcesTooltip)] + private OutlineResources _outlineResources; + [SerializeField, Tooltip(OutlineResources.OutlineLayerCollectionTooltip)] + private OutlineLayerCollection _outlineLayers; + +#pragma warning restore 0649 + + private List _renderList; + + #endregion + + #region CustomPass + + protected override void Setup(ScriptableRenderContext renderContext, CommandBuffer cmd) + { + if (_renderList is null) + { + _renderList = new List(); + } + } + + protected override void Execute(ScriptableRenderContext renderContext, CommandBuffer cmd, HDCamera hdCamera, CullingResults cullingResult) + { + if (_outlineResources && _outlineLayers) + { + GetCameraBuffers(out var colorBuffer, out var depthBuffer); + + using (var renderer = new OutlineRenderer(cmd, _outlineResources, colorBuffer.nameID, depthBuffer.nameID, colorBuffer.rt.descriptor)) + { + _renderList.Clear(); + _outlineLayers.GetRenderObjects(_renderList); + + foreach (var obj in _renderList) + { + renderer.Render(obj); + } + } + } + } + + #endregion + } +} diff --git a/Outline.HDRP/Packages/UnityFx.Outline.HDRP/Runtime/Scripts/Outline.cs.meta b/Outline.HDRP/Packages/UnityFx.Outline.HDRP/Runtime/Scripts/OutlinePass.cs.meta similarity index 100% rename from Outline.HDRP/Packages/UnityFx.Outline.HDRP/Runtime/Scripts/Outline.cs.meta rename to Outline.HDRP/Packages/UnityFx.Outline.HDRP/Runtime/Scripts/OutlinePass.cs.meta diff --git a/Outline.PostProcessing/Assets/Examples/PostProcessing/OutlineLayerCollection.asset b/Outline.PostProcessing/Assets/Examples/PostProcessing/OutlineLayerCollection.asset new file mode 100644 index 0000000..42472cb --- /dev/null +++ b/Outline.PostProcessing/Assets/Examples/PostProcessing/OutlineLayerCollection.asset @@ -0,0 +1,40 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 57d0c11168277cf4eb3b4b89706e6aa5, type: 3} + m_Name: OutlineLayerCollection + m_EditorClassIdentifier: + _layers: + - _settings: + _outlineSettings: {fileID: 0} + _outlineColor: {r: 1, g: 0, b: 0.970881, a: 1} + _outlineWidth: 4 + _outlineIntensity: 2 + _outlineMode: 0 + _name: + _enabled: 1 + - _settings: + _outlineSettings: {fileID: 0} + _outlineColor: {r: 1, g: 0, b: 0, a: 1} + _outlineWidth: 6 + _outlineIntensity: 2 + _outlineMode: 2 + _name: + _enabled: 1 + - _settings: + _outlineSettings: {fileID: 0} + _outlineColor: {r: 0, g: 0.23238373, b: 1, a: 1} + _outlineWidth: 10 + _outlineIntensity: 2 + _outlineMode: 1 + _name: + _enabled: 1 + _layerMask: 0 diff --git a/Outline.PostProcessing/Assets/Examples/PostProcessing/OutlineLayerCollection.asset.meta b/Outline.PostProcessing/Assets/Examples/PostProcessing/OutlineLayerCollection.asset.meta new file mode 100644 index 0000000..528902b --- /dev/null +++ b/Outline.PostProcessing/Assets/Examples/PostProcessing/OutlineLayerCollection.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 747aa7f9a78f24945a8d07c0ba1511c6 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Outline.PostProcessing/Assets/Examples/PostProcessing/PostProcessingProfile.asset b/Outline.PostProcessing/Assets/Examples/PostProcessing/PostProcessingProfile.asset index 725ebe2..17e2ac4 100644 --- a/Outline.PostProcessing/Assets/Examples/PostProcessing/PostProcessingProfile.asset +++ b/Outline.PostProcessing/Assets/Examples/PostProcessing/PostProcessingProfile.asset @@ -35,5 +35,5 @@ MonoBehaviour: overrideState: 0 value: {fileID: 11400000, guid: d28e70f030b1a634db9a6a6d5478ef19, type: 2} Layers: - overrideState: 0 - value: {fileID: 0} + overrideState: 1 + value: {fileID: 11400000, guid: 747aa7f9a78f24945a8d07c0ba1511c6, type: 2} diff --git a/Outline.PostProcessing/Assets/Examples/PostProcessing/PostProcessingSample.unity b/Outline.PostProcessing/Assets/Examples/PostProcessing/PostProcessingSample.unity index 289e850..bc614c5 100644 --- a/Outline.PostProcessing/Assets/Examples/PostProcessing/PostProcessingSample.unity +++ b/Outline.PostProcessing/Assets/Examples/PostProcessing/PostProcessingSample.unity @@ -192,6 +192,7 @@ GameObject: - component: {fileID: 692811816} - component: {fileID: 692811815} - component: {fileID: 692811813} + - component: {fileID: 692811814} m_Layer: 0 m_Name: Main Camera m_TagString: MainCamera @@ -261,6 +262,26 @@ MonoBehaviour: - assemblyQualifiedName: UnityFx.Outline.PostProcessing.Outline, UnityFx.Outline.PostProcessing, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null m_AfterStackBundles: [] +--- !u!114 &692811814 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 692811812} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e746e776b0ae00d4a9d458b9430b95d7, type: 3} + m_Name: + m_EditorClassIdentifier: + _outlineLayers: {fileID: 11400000, guid: 747aa7f9a78f24945a8d07c0ba1511c6, type: 2} + _content: + - Go: {fileID: 1579373802} + LayerIndex: 0 + - Go: {fileID: 748173439} + LayerIndex: 1 + - Go: {fileID: 1789341920} + LayerIndex: 2 --- !u!20 &692811815 Camera: m_ObjectHideFlags: 0 diff --git a/Outline.PostProcessing/Packages/UnityFx.Outline.PostProcessing/CHANGELOG.md b/Outline.PostProcessing/Packages/UnityFx.Outline.PostProcessing/CHANGELOG.md index ae04922..d3a13d5 100644 --- a/Outline.PostProcessing/Packages/UnityFx.Outline.PostProcessing/CHANGELOG.md +++ b/Outline.PostProcessing/Packages/UnityFx.Outline.PostProcessing/CHANGELOG.md @@ -3,6 +3,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/); this project adheres to [Semantic Versioning](http://semver.org/). +## [0.2.0] - 2020.05.30 + +Minor improvements and bugfixes. + +### Fixed +- Fixed post-ptocessing implementation to require depth texture. + +### Removed +- Dropped .NET 3.5 support, minimal Unity version is set to 2018.4. + ## [0.1.0] - 2020.04.08 ### Added diff --git a/Outline.PostProcessing/Packages/UnityFx.Outline.PostProcessing/Runtime/Scripts/Outline.cs b/Outline.PostProcessing/Packages/UnityFx.Outline.PostProcessing/Runtime/Scripts/Outline.cs index e7ef71d..b43431e 100644 --- a/Outline.PostProcessing/Packages/UnityFx.Outline.PostProcessing/Runtime/Scripts/Outline.cs +++ b/Outline.PostProcessing/Packages/UnityFx.Outline.PostProcessing/Runtime/Scripts/Outline.cs @@ -38,7 +38,9 @@ public class OutlineLayersParameter : ParameterOverride } // NOTE: PostProcessEffectSettings.OnEnable implementation requires the fields to be public to function properly. + [Tooltip(OutlineResources.OutlineResourcesTooltip)] public OutlineResourcesParameter Resources = new OutlineResourcesParameter(); + [Tooltip(OutlineResources.OutlineLayerCollectionTooltip)] public OutlineLayersParameter Layers = new OutlineLayersParameter(); public Outline() diff --git a/Outline.PostProcessing/Packages/UnityFx.Outline.PostProcessing/Runtime/Scripts/OutlineEffectRenderer.cs b/Outline.PostProcessing/Packages/UnityFx.Outline.PostProcessing/Runtime/Scripts/OutlineEffectRenderer.cs index 3b8cf2f..b60c331 100644 --- a/Outline.PostProcessing/Packages/UnityFx.Outline.PostProcessing/Runtime/Scripts/OutlineEffectRenderer.cs +++ b/Outline.PostProcessing/Packages/UnityFx.Outline.PostProcessing/Runtime/Scripts/OutlineEffectRenderer.cs @@ -2,6 +2,7 @@ // See the LICENSE.md file in the project root for more information. using System; +using System.Collections.Generic; using UnityEngine; using UnityEngine.Rendering.PostProcessing; using UnityEngine.Scripting; @@ -12,12 +13,18 @@ namespace UnityFx.Outline.PostProcessing public sealed class OutlineEffectRenderer : PostProcessEffectRenderer { private OutlineResources _defaultResources; + private List _objects = new List(); + + public override DepthTextureMode GetCameraFlags() + { + return DepthTextureMode.Depth; + } public override void Render(PostProcessRenderContext context) { OutlineResources resources; - if (settings.Resources.value != null) + if (settings.Resources.value) { resources = settings.Resources; } @@ -35,9 +42,17 @@ public override void Render(PostProcessRenderContext context) if (resources && resources.IsValid) { - using (var renderer = new OutlineRenderer(context.command, context.source, context.destination)) + RuntimeUtilities.CopyTexture(context.command, context.source, context.destination); + + using (var renderer = new OutlineRenderer(context.command, resources, context.destination, context.camera.actualRenderingPath, new Vector2Int(context.width, context.height))) { - settings.Layers.value.Render(renderer, resources); + _objects.Clear(); + settings.Layers.value.GetRenderObjects(_objects); + + foreach (var obj in _objects) + { + renderer.Render(obj); + } } } } diff --git a/Outline.PostProcessing/Packages/UnityFx.Outline.PostProcessing/package.json b/Outline.PostProcessing/Packages/UnityFx.Outline.PostProcessing/package.json index 6c5b92f..a6bc730 100644 --- a/Outline.PostProcessing/Packages/UnityFx.Outline.PostProcessing/package.json +++ b/Outline.PostProcessing/Packages/UnityFx.Outline.PostProcessing/package.json @@ -1,12 +1,12 @@ { "name": "com.unityfx.outline.postprocessing", - "version": "0.1.0", - "displayName": "Screen-space outline (Post-processing v2)", - "description": "Configurable outline implementation for Unity post-processing stack (v2). Both solid and blurred modes supported (Gauss blur). Scriptable render pipeline is not supported.", + "version": "0.2.0", + "displayName": "Outline toolkit (Post-processing v2)", + "description": "This package contains configurable outline implementation for Unity post-processing stack (v2).", "unity": "2018.4", "dependencies": { - "com.unityfx.outline": "0.7.2", - "com.unity.postprocessing": "2.2.2" + "com.unityfx.outline": "0.8.0", + "com.unity.postprocessing": "2.3.0" }, "keywords": [ "UnityFx", diff --git a/Outline.PostProcessing/Packages/manifest.json b/Outline.PostProcessing/Packages/manifest.json index 215c50c..1a706d4 100644 --- a/Outline.PostProcessing/Packages/manifest.json +++ b/Outline.PostProcessing/Packages/manifest.json @@ -1,16 +1,7 @@ { - "scopedRegistries": [ - { - "name": "Arvtesh", - "url": "https://registry.npmjs.org/", - "scopes": [ - "com.unityfx" - ] - } - ], "dependencies": { "com.unity.package-manager-ui": "2.0.8", - "com.unityfx.outline": "0.7.1", + "com.unityfx.outline": "file:../../Outline.Core/Packages/UnityFx.Outline", "com.unity.modules.ai": "1.0.0", "com.unity.modules.animation": "1.0.0", "com.unity.modules.assetbundle": "1.0.0", diff --git a/Outline.URP/Assets/Example.meta b/Outline.URP/Assets/Example.meta new file mode 100644 index 0000000..7246202 --- /dev/null +++ b/Outline.URP/Assets/Example.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ea27ed3498ff43e40aab89c627664573 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Outline.URP/Assets/Example/OutlineLayerCollection.asset b/Outline.URP/Assets/Example/OutlineLayerCollection.asset new file mode 100644 index 0000000..b09ddfe --- /dev/null +++ b/Outline.URP/Assets/Example/OutlineLayerCollection.asset @@ -0,0 +1,32 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 57d0c11168277cf4eb3b4b89706e6aa5, type: 3} + m_Name: OutlineLayerCollection + m_EditorClassIdentifier: + _layers: + - _settings: + _outlineSettings: {fileID: 0} + _outlineColor: {r: 1, g: 0, b: 0, a: 1} + _outlineWidth: 25 + _outlineIntensity: 2 + _outlineMode: 1 + _name: + _enabled: 1 + - _settings: + _outlineSettings: {fileID: 0} + _outlineColor: {r: 0, g: 1, b: 0.060156345, a: 1} + _outlineWidth: 7 + _outlineIntensity: 2 + _outlineMode: 1 + _name: + _enabled: 1 + _layerMask: 0 diff --git a/Outline.URP/Assets/Example/OutlineLayerCollection.asset.meta b/Outline.URP/Assets/Example/OutlineLayerCollection.asset.meta new file mode 100644 index 0000000..0548bf7 --- /dev/null +++ b/Outline.URP/Assets/Example/OutlineLayerCollection.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 059d229f23209a74687769672d1084b8 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Outline.URP/Assets/Example/TestScene.unity b/Outline.URP/Assets/Example/TestScene.unity new file mode 100644 index 0000000..20e3d19 --- /dev/null +++ b/Outline.URP/Assets/Example/TestScene.unity @@ -0,0 +1,442 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 256 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 1 + m_PVRDenoiserTypeDirect: 1 + m_PVRDenoiserTypeIndirect: 1 + m_PVRDenoiserTypeAO: 1 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 1 +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &845078339 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 845078341} + - component: {fileID: 845078340} + m_Layer: 0 + m_Name: Directional Light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &845078340 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 845078339} + m_Enabled: 1 + serializedVersion: 10 + m_Type: 1 + m_Shape: 0 + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_Intensity: 1 + m_Range: 10 + m_SpotAngle: 30 + m_InnerSpotAngle: 21.80208 + m_CookieSize: 10 + m_Shadows: + m_Type: 0 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 4 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &845078341 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 845078339} + m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} + m_LocalPosition: {x: 1.56, y: 3.71, z: -2.7} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} +--- !u!1 &925532356 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 925532360} + - component: {fileID: 925532359} + - component: {fileID: 925532358} + - component: {fileID: 925532357} + - component: {fileID: 925532361} + m_Layer: 0 + m_Name: Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &925532357 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 925532356} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e746e776b0ae00d4a9d458b9430b95d7, type: 3} + m_Name: + m_EditorClassIdentifier: + _outlineLayers: {fileID: 11400000, guid: 059d229f23209a74687769672d1084b8, type: 2} + _content: + - Go: {fileID: 958073178} + LayerIndex: 0 +--- !u!81 &925532358 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 925532356} + m_Enabled: 1 +--- !u!20 &925532359 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 925532356} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &925532360 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 925532356} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 958073179} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &925532361 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 925532356} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3} + m_Name: + m_EditorClassIdentifier: + m_RenderShadows: 1 + m_RequiresDepthTextureOption: 2 + m_RequiresOpaqueTextureOption: 2 + m_CameraType: 0 + m_CameraOutput: 0 + m_Cameras: [] + m_RendererIndex: -1 + m_VolumeLayerMask: + serializedVersion: 2 + m_Bits: 1 + m_VolumeTrigger: {fileID: 0} + m_RenderPostProcessing: 0 + m_Antialiasing: 0 + m_AntialiasingQuality: 2 + m_StopNaN: 0 + m_Dithering: 0 + m_RequiresDepthTexture: 0 + m_RequiresColorTexture: 0 + m_Version: 2 +--- !u!1 &958073178 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 958073179} + - component: {fileID: 958073182} + - component: {fileID: 958073181} + - component: {fileID: 958073180} + m_Layer: 0 + m_Name: Cylinder + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &958073179 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 958073178} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 3.06} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 925532360} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!136 &958073180 +CapsuleCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 958073178} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + m_Radius: 0.5000001 + m_Height: 2 + m_Direction: 1 + m_Center: {x: 0.000000059604645, y: 0, z: -0.00000008940697} +--- !u!23 &958073181 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 958073178} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &958073182 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 958073178} + m_Mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0} diff --git a/Outline.URP/Assets/Example/TestScene.unity.meta b/Outline.URP/Assets/Example/TestScene.unity.meta new file mode 100644 index 0000000..d176f60 --- /dev/null +++ b/Outline.URP/Assets/Example/TestScene.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: de30e76e0b738334f8e043d91d10419d +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Outline.URP/Assets/URP.meta b/Outline.URP/Assets/URP.meta new file mode 100644 index 0000000..90625cd --- /dev/null +++ b/Outline.URP/Assets/URP.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 10050ed397807bc4289f21067a025607 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Outline.URP/Assets/URP/UniversalRenderPipelineAsset.asset b/Outline.URP/Assets/URP/UniversalRenderPipelineAsset.asset new file mode 100644 index 0000000..9540d39 --- /dev/null +++ b/Outline.URP/Assets/URP/UniversalRenderPipelineAsset.asset @@ -0,0 +1,54 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: bf2edee5c58d82540a51f03df9d42094, type: 3} + m_Name: UniversalRenderPipelineAsset + m_EditorClassIdentifier: + k_AssetVersion: 5 + k_AssetPreviousVersion: 5 + m_RendererType: 1 + m_RendererData: {fileID: 0} + m_RendererDataList: + - {fileID: 11400000, guid: f1ccc14d55573e14f80806280c11d740, type: 2} + m_DefaultRendererIndex: 0 + m_RequireDepthTexture: 1 + m_RequireOpaqueTexture: 0 + m_OpaqueDownsampling: 1 + m_SupportsTerrainHoles: 0 + m_SupportsHDR: 0 + m_MSAA: 1 + m_RenderScale: 1 + m_MainLightRenderingMode: 1 + m_MainLightShadowsSupported: 1 + m_MainLightShadowmapResolution: 2048 + m_AdditionalLightsRenderingMode: 1 + m_AdditionalLightsPerObjectLimit: 4 + m_AdditionalLightShadowsSupported: 0 + m_AdditionalLightsShadowmapResolution: 512 + m_ShadowDistance: 50 + m_ShadowCascades: 0 + m_Cascade2Split: 0.25 + m_Cascade4Split: {x: 0.067, y: 0.2, z: 0.467} + m_ShadowDepthBias: 1 + m_ShadowNormalBias: 1 + m_SoftShadowsSupported: 0 + m_UseSRPBatcher: 1 + m_SupportsDynamicBatching: 0 + m_MixedLightingSupported: 1 + m_DebugLevel: 0 + m_ColorGradingMode: 0 + m_ColorGradingLutSize: 32 + m_ShadowType: 1 + m_LocalShadowsSupported: 0 + m_LocalShadowsAtlasResolution: 256 + m_MaxPixelLights: 0 + m_ShadowAtlasResolution: 256 + m_ShaderVariantLogLevel: 0 diff --git a/Outline.URP/Assets/URP/UniversalRenderPipelineAsset.asset.meta b/Outline.URP/Assets/URP/UniversalRenderPipelineAsset.asset.meta new file mode 100644 index 0000000..360640c --- /dev/null +++ b/Outline.URP/Assets/URP/UniversalRenderPipelineAsset.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3d47f01a90fe56d43b0cfac27039c94c +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Outline.URP/Assets/URP/UniversalRenderPipelineAsset_Renderer.asset b/Outline.URP/Assets/URP/UniversalRenderPipelineAsset_Renderer.asset new file mode 100644 index 0000000..df60544 --- /dev/null +++ b/Outline.URP/Assets/URP/UniversalRenderPipelineAsset_Renderer.asset @@ -0,0 +1,51 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &-2278397774415627597 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: dd37d03d18ee9584d881763c34816b35, type: 3} + m_Name: Outline + m_EditorClassIdentifier: + _outlineResources: {fileID: 11400000, guid: d28e70f030b1a634db9a6a6d5478ef19, type: 2} + _outlineLayers: {fileID: 11400000, guid: 059d229f23209a74687769672d1084b8, type: 2} +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: de640fe3d0db1804a85f9fc8f5cadab6, type: 3} + m_Name: UniversalRenderPipelineAsset_Renderer + m_EditorClassIdentifier: + m_RendererFeatures: + - {fileID: -2278397774415627597} + postProcessData: {fileID: 11400000, guid: 41439944d30ece34e96484bdb6645b55, type: 2} + shaders: + blitPS: {fileID: 4800000, guid: c17132b1f77d20942aa75f8429c0f8bc, type: 3} + copyDepthPS: {fileID: 4800000, guid: d6dae50ee9e1bfa4db75f19f99355220, type: 3} + screenSpaceShadowPS: {fileID: 4800000, guid: 0f854b35a0cf61a429bd5dcfea30eddd, + type: 3} + samplingPS: {fileID: 4800000, guid: 04c410c9937594faa893a11dceb85f7e, type: 3} + fallbackErrorPS: {fileID: 4800000, guid: e6e9a19c3678ded42a3bc431ebef7dbd, type: 3} + m_OpaqueLayerMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_TransparentLayerMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_DefaultStencilState: + overrideStencilState: 0 + stencilReference: 0 + stencilCompareFunction: 8 + passOperation: 0 + failOperation: 0 + zFailOperation: 0 diff --git a/Outline.URP/Assets/URP/UniversalRenderPipelineAsset_Renderer.asset.meta b/Outline.URP/Assets/URP/UniversalRenderPipelineAsset_Renderer.asset.meta new file mode 100644 index 0000000..477bcf6 --- /dev/null +++ b/Outline.URP/Assets/URP/UniversalRenderPipelineAsset_Renderer.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f1ccc14d55573e14f80806280c11d740 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Outline.URP/Packages/UnityFx.Outline.URP/CHANGELOG.md b/Outline.URP/Packages/UnityFx.Outline.URP/CHANGELOG.md new file mode 100644 index 0000000..1935a50 --- /dev/null +++ b/Outline.URP/Packages/UnityFx.Outline.URP/CHANGELOG.md @@ -0,0 +1,9 @@ +# UnityFx.Outline.URP changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/); this project adheres to [Semantic Versioning](http://semver.org/). + +## [0.1.0] - 2020.05.30 + +### Added +- Initial release. diff --git a/Outline.URP/Packages/UnityFx.Outline.URP/CHANGELOG.md.meta b/Outline.URP/Packages/UnityFx.Outline.URP/CHANGELOG.md.meta new file mode 100644 index 0000000..f3ea157 --- /dev/null +++ b/Outline.URP/Packages/UnityFx.Outline.URP/CHANGELOG.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: d2731cfdae865ee439fd0fef782fa994 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Outline.URP/Packages/UnityFx.Outline.URP/README.md b/Outline.URP/Packages/UnityFx.Outline.URP/README.md new file mode 100644 index 0000000..aec8aa2 --- /dev/null +++ b/Outline.URP/Packages/UnityFx.Outline.URP/README.md @@ -0,0 +1,11 @@ +# UnityFx.Outline.URP + +## SUMMARY +Screen-space outline effects for URP. + +## USEFUL LINKS +* [Github project](https://github.com/Arvtesh/UnityFx.Outline) +* [npm package](https://www.npmjs.com/package/com.unityfx.outline.urp) +* [Documentation](https://github.com/Arvtesh/UnityFx.Outline/blob/master/README.md) +* [License](https://github.com/Arvtesh/UnityFx.Outline/blob/master/LICENSE.md) +* [Support](mailto:arvtesh@gmail.com) diff --git a/Outline.URP/Packages/UnityFx.Outline.URP/README.md.meta b/Outline.URP/Packages/UnityFx.Outline.URP/README.md.meta new file mode 100644 index 0000000..39c522c --- /dev/null +++ b/Outline.URP/Packages/UnityFx.Outline.URP/README.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 3db1fff9dd9ae804888eebc4382e1fb8 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Outline.URP/Packages/UnityFx.Outline.URP/Runtime.meta b/Outline.URP/Packages/UnityFx.Outline.URP/Runtime.meta new file mode 100644 index 0000000..5ef6e3e --- /dev/null +++ b/Outline.URP/Packages/UnityFx.Outline.URP/Runtime.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 58d8c6c8330ffc042ade41ba15f8da23 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Outline.URP/Packages/UnityFx.Outline.URP/Runtime/Scripts.meta b/Outline.URP/Packages/UnityFx.Outline.URP/Runtime/Scripts.meta new file mode 100644 index 0000000..100ae09 --- /dev/null +++ b/Outline.URP/Packages/UnityFx.Outline.URP/Runtime/Scripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 85518f862b075044bbd76d57354f8f3e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Outline.URP/Packages/UnityFx.Outline.URP/Runtime/Scripts/OutlineFeature.cs b/Outline.URP/Packages/UnityFx.Outline.URP/Runtime/Scripts/OutlineFeature.cs new file mode 100644 index 0000000..ad6c82e --- /dev/null +++ b/Outline.URP/Packages/UnityFx.Outline.URP/Runtime/Scripts/OutlineFeature.cs @@ -0,0 +1,73 @@ +// Copyright (C) 2019-2020 Alexander Bogarsukov. All rights reserved. +// See the LICENSE.md file in the project root for more information. + +using System; +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.Rendering.Universal; + +namespace UnityFx.Outline.URP +{ + /// + /// Outline feature (URP). + /// + /// + /// Add instance of this class to . Configure + /// and assign outline resources and layers collection. Make sure + /// is set if you use . + /// + public class OutlineFeature : ScriptableRendererFeature + { + #region data + +#pragma warning disable 0649 + + [SerializeField, Tooltip(OutlineResources.OutlineResourcesTooltip)] + private OutlineResources _outlineResources; + [SerializeField, Tooltip(OutlineResources.OutlineLayerCollectionTooltip)] + private OutlineLayerCollection _outlineLayers; + +#pragma warning restore 0649 + + private OutlinePass _outlinePass; + + #endregion + + #region interface + + /// + /// Gets the outline resources. + /// + public OutlineResources OutlineResources => _outlineResources; + + /// + /// Gets outline layers collection attached. + /// + public OutlineLayerCollection OutlineLayers => _outlineLayers; + + #endregion + + #region ScriptableRendererFeature + + /// + public override void Create() + { + _outlinePass = new OutlinePass(this) + { + renderPassEvent = RenderPassEvent.BeforeRenderingPostProcessing + }; + } + + /// + public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) + { + if (_outlineResources && _outlineResources.IsValid && _outlineLayers) + { + _outlinePass.Setup(renderer.cameraColorTarget, renderer.cameraDepth); + renderer.EnqueuePass(_outlinePass); + } + } + + #endregion + } +} diff --git a/Outline.URP/Packages/UnityFx.Outline.URP/Runtime/Scripts/OutlineFeature.cs.meta b/Outline.URP/Packages/UnityFx.Outline.URP/Runtime/Scripts/OutlineFeature.cs.meta new file mode 100644 index 0000000..cb0f643 --- /dev/null +++ b/Outline.URP/Packages/UnityFx.Outline.URP/Runtime/Scripts/OutlineFeature.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: dd37d03d18ee9584d881763c34816b35 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: + - _outlineResources: {fileID: 11400000, guid: d28e70f030b1a634db9a6a6d5478ef19, + type: 2} + - _outlineLayers: {instanceID: 0} + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Outline.URP/Packages/UnityFx.Outline.URP/Runtime/Scripts/OutlinePass.cs b/Outline.URP/Packages/UnityFx.Outline.URP/Runtime/Scripts/OutlinePass.cs new file mode 100644 index 0000000..154fde4 --- /dev/null +++ b/Outline.URP/Packages/UnityFx.Outline.URP/Runtime/Scripts/OutlinePass.cs @@ -0,0 +1,56 @@ +// Copyright (C) 2019-2020 Alexander Bogarsukov. All rights reserved. +// See the LICENSE.md file in the project root for more information. + +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.Rendering.Universal; + +namespace UnityFx.Outline.URP +{ + internal class OutlinePass : ScriptableRenderPass + { + private readonly OutlineFeature _feature; + private readonly List _renderObjects = new List(); + + private RenderTargetIdentifier _rt; + private RenderTargetIdentifier _depth; + private RenderTextureDescriptor _rtDesc; + + public OutlinePass(OutlineFeature feature) + { + _feature = feature; + } + + public void Setup(RenderTargetIdentifier rt, RenderTargetIdentifier depth) + { + _rt = rt; + _depth = depth; + } + + public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor) + { + _rtDesc = cameraTextureDescriptor; + } + + public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) + { + var cmd = CommandBufferPool.Get(OutlineResources.EffectName); + + using (var renderer = new OutlineRenderer(cmd, _feature.OutlineResources, _rt, _depth, _rtDesc)) + { + _renderObjects.Clear(); + _feature.OutlineLayers.GetRenderObjects(_renderObjects); + + foreach (var obj in _renderObjects) + { + renderer.Render(obj); + } + } + + context.ExecuteCommandBuffer(cmd); + CommandBufferPool.Release(cmd); + } + } +} diff --git a/Outline.URP/Packages/UnityFx.Outline.URP/Runtime/Scripts/OutlinePass.cs.meta b/Outline.URP/Packages/UnityFx.Outline.URP/Runtime/Scripts/OutlinePass.cs.meta new file mode 100644 index 0000000..869a028 --- /dev/null +++ b/Outline.URP/Packages/UnityFx.Outline.URP/Runtime/Scripts/OutlinePass.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b3a7683689e159546992ec0f529efcca +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Outline.URP/Packages/UnityFx.Outline.URP/Runtime/UnityFx.Outline.URP.asmdef b/Outline.URP/Packages/UnityFx.Outline.URP/Runtime/UnityFx.Outline.URP.asmdef new file mode 100644 index 0000000..3f9ff3f --- /dev/null +++ b/Outline.URP/Packages/UnityFx.Outline.URP/Runtime/UnityFx.Outline.URP.asmdef @@ -0,0 +1,17 @@ +{ + "name": "UnityFx.Outline.URP", + "references": [ + "Unity.RenderPipelines.Core.Runtime", + "Unity.RenderPipelines.Universal.Runtime", + "UnityFx.Outline" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Outline.URP/Packages/UnityFx.Outline.URP/Runtime/UnityFx.Outline.URP.asmdef.meta b/Outline.URP/Packages/UnityFx.Outline.URP/Runtime/UnityFx.Outline.URP.asmdef.meta new file mode 100644 index 0000000..418ae3e --- /dev/null +++ b/Outline.URP/Packages/UnityFx.Outline.URP/Runtime/UnityFx.Outline.URP.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 8130e23c3199afb43ae1c34b3e328d00 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Outline.URP/Packages/UnityFx.Outline.URP/package.json b/Outline.URP/Packages/UnityFx.Outline.URP/package.json new file mode 100644 index 0000000..9c6ce85 --- /dev/null +++ b/Outline.URP/Packages/UnityFx.Outline.URP/package.json @@ -0,0 +1,32 @@ +{ + "name": "com.unityfx.outline.urp", + "version": "0.1.0", + "displayName": "Outline toolkit (URP)", + "description": "This package contains configurable outline implementation for Universal Render Pipeline.", + "unity": "2019.3", + "dependencies": { + "com.unityfx.outline": "0.8.0", + "com.unity.render-pipelines.universal": "7.0.0" + }, + "keywords": [ + "UnityFx", + "UnityFx.Outline", + "UnityFx.Outline.URP", + "Outline", + "URP" + ], + "category": "UnityFx", + "author": { + "name": "Arvtesh", + "email": "arvtesh@gmail.com" + }, + "license": "MIT", + "homepage": "https://github.com/Arvtesh/UnityFx.Outline", + "repository": { + "type": "git", + "url": "https://github.com/Arvtesh/UnityFx.Outline.git" + }, + "bugs": { + "url": "https://github.com/Arvtesh/UnityFx.Outline/issues" + } +} diff --git a/Outline.URP/Packages/UnityFx.Outline.URP/package.json.meta b/Outline.URP/Packages/UnityFx.Outline.URP/package.json.meta new file mode 100644 index 0000000..3132f4f --- /dev/null +++ b/Outline.URP/Packages/UnityFx.Outline.URP/package.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 761dcd9f6f741bd4b9a86aa1fc1f11b7 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Outline.URP/Packages/manifest.json b/Outline.URP/Packages/manifest.json new file mode 100644 index 0000000..7c56d24 --- /dev/null +++ b/Outline.URP/Packages/manifest.json @@ -0,0 +1,37 @@ +{ + "dependencies": { + "com.unity.render-pipelines.universal": "7.1.8", + "com.unityfx.outline": "file:../../Outline.Core/Packages/UnityFx.Outline", + "com.unity.modules.ai": "1.0.0", + "com.unity.modules.androidjni": "1.0.0", + "com.unity.modules.animation": "1.0.0", + "com.unity.modules.assetbundle": "1.0.0", + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.cloth": "1.0.0", + "com.unity.modules.director": "1.0.0", + "com.unity.modules.imageconversion": "1.0.0", + "com.unity.modules.imgui": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.particlesystem": "1.0.0", + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.physics2d": "1.0.0", + "com.unity.modules.screencapture": "1.0.0", + "com.unity.modules.terrain": "1.0.0", + "com.unity.modules.terrainphysics": "1.0.0", + "com.unity.modules.tilemap": "1.0.0", + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.uielements": "1.0.0", + "com.unity.modules.umbra": "1.0.0", + "com.unity.modules.unityanalytics": "1.0.0", + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.unitywebrequestassetbundle": "1.0.0", + "com.unity.modules.unitywebrequestaudio": "1.0.0", + "com.unity.modules.unitywebrequesttexture": "1.0.0", + "com.unity.modules.unitywebrequestwww": "1.0.0", + "com.unity.modules.vehicles": "1.0.0", + "com.unity.modules.video": "1.0.0", + "com.unity.modules.vr": "1.0.0", + "com.unity.modules.wind": "1.0.0", + "com.unity.modules.xr": "1.0.0" + } +} diff --git a/Outline.URP/ProjectSettings/AudioManager.asset b/Outline.URP/ProjectSettings/AudioManager.asset new file mode 100644 index 0000000..27287fe --- /dev/null +++ b/Outline.URP/ProjectSettings/AudioManager.asset @@ -0,0 +1,19 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!11 &1 +AudioManager: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Volume: 1 + Rolloff Scale: 1 + Doppler Factor: 1 + Default Speaker Mode: 2 + m_SampleRate: 0 + m_DSPBufferSize: 1024 + m_VirtualVoiceCount: 512 + m_RealVoiceCount: 32 + m_SpatializerPlugin: + m_AmbisonicDecoderPlugin: + m_DisableAudio: 0 + m_VirtualizeEffects: 1 + m_RequestedDSPBufferSize: 0 diff --git a/Outline.URP/ProjectSettings/ClusterInputManager.asset b/Outline.URP/ProjectSettings/ClusterInputManager.asset new file mode 100644 index 0000000..e7886b2 --- /dev/null +++ b/Outline.URP/ProjectSettings/ClusterInputManager.asset @@ -0,0 +1,6 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!236 &1 +ClusterInputManager: + m_ObjectHideFlags: 0 + m_Inputs: [] diff --git a/Outline.URP/ProjectSettings/DynamicsManager.asset b/Outline.URP/ProjectSettings/DynamicsManager.asset new file mode 100644 index 0000000..1596c42 --- /dev/null +++ b/Outline.URP/ProjectSettings/DynamicsManager.asset @@ -0,0 +1,36 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!55 &1 +PhysicsManager: + m_ObjectHideFlags: 0 + serializedVersion: 13 + m_Gravity: {x: 0, y: -9.81, z: 0} + m_DefaultMaterial: {fileID: 0} + m_BounceThreshold: 2 + m_SleepThreshold: 0.005 + m_DefaultContactOffset: 0.01 + m_DefaultSolverIterations: 6 + m_DefaultSolverVelocityIterations: 1 + m_QueriesHitBackfaces: 0 + m_QueriesHitTriggers: 1 + m_EnableAdaptiveForce: 0 + m_ClothInterCollisionDistance: 0.1 + m_ClothInterCollisionStiffness: 0.2 + m_ContactsGeneration: 1 + m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + m_AutoSimulation: 1 + m_AutoSyncTransforms: 0 + m_ReuseCollisionCallbacks: 0 + m_ClothInterCollisionSettingsToggle: 0 + m_ClothGravity: {x: 0, y: -9.81, z: 0} + m_ContactPairsMode: 0 + m_BroadphaseType: 0 + m_WorldBounds: + m_Center: {x: 0, y: 0, z: 0} + m_Extent: {x: 250, y: 250, z: 250} + m_WorldSubdivisions: 8 + m_FrictionType: 0 + m_EnableEnhancedDeterminism: 0 + m_EnableUnifiedHeightmaps: 1 + m_SolverType: 0 + m_DefaultMaxAngularSpeed: 50 diff --git a/Outline.URP/ProjectSettings/EditorBuildSettings.asset b/Outline.URP/ProjectSettings/EditorBuildSettings.asset new file mode 100644 index 0000000..0147887 --- /dev/null +++ b/Outline.URP/ProjectSettings/EditorBuildSettings.asset @@ -0,0 +1,8 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1045 &1 +EditorBuildSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Scenes: [] + m_configObjects: {} diff --git a/Outline.URP/ProjectSettings/EditorSettings.asset b/Outline.URP/ProjectSettings/EditorSettings.asset new file mode 100644 index 0000000..c8da44e --- /dev/null +++ b/Outline.URP/ProjectSettings/EditorSettings.asset @@ -0,0 +1,35 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!159 &1 +EditorSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_ExternalVersionControlSupport: Visible Meta Files + m_SerializationMode: 2 + m_LineEndingsForNewScripts: 2 + m_DefaultBehaviorMode: 0 + m_PrefabRegularEnvironment: {fileID: 0} + m_PrefabUIEnvironment: {fileID: 0} + m_SpritePackerMode: 0 + m_SpritePackerPaddingPower: 1 + m_EtcTextureCompressorBehavior: 1 + m_EtcTextureFastCompressor: 1 + m_EtcTextureNormalCompressor: 2 + m_EtcTextureBestCompressor: 4 + m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmdef;asmref;rsp + m_ProjectGenerationRootNamespace: + m_CollabEditorSettings: + inProgressEnabled: 1 + m_EnableTextureStreamingInEditMode: 1 + m_EnableTextureStreamingInPlayMode: 1 + m_AsyncShaderCompilation: 1 + m_EnterPlayModeOptionsEnabled: 0 + m_EnterPlayModeOptions: 3 + m_ShowLightmapResolutionOverlay: 1 + m_UseLegacyProbeSampleCount: 0 + m_AssetPipelineMode: 1 + m_CacheServerMode: 0 + m_CacheServerEndpoint: + m_CacheServerNamespacePrefix: default + m_CacheServerEnableDownload: 1 + m_CacheServerEnableUpload: 1 diff --git a/Outline.URP/ProjectSettings/GraphicsSettings.asset b/Outline.URP/ProjectSettings/GraphicsSettings.asset new file mode 100644 index 0000000..f032055 --- /dev/null +++ b/Outline.URP/ProjectSettings/GraphicsSettings.asset @@ -0,0 +1,65 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!30 &1 +GraphicsSettings: + m_ObjectHideFlags: 0 + serializedVersion: 13 + m_Deferred: + m_Mode: 1 + m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0} + m_DeferredReflections: + m_Mode: 1 + m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0} + m_ScreenSpaceShadows: + m_Mode: 1 + m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0} + m_LegacyDeferred: + m_Mode: 1 + m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0} + m_DepthNormals: + m_Mode: 1 + m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0} + m_MotionVectors: + m_Mode: 1 + m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0} + m_LightHalo: + m_Mode: 1 + m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0} + m_LensFlare: + m_Mode: 1 + m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0} + m_AlwaysIncludedShaders: + - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 10783, guid: 0000000000000000f000000000000000, type: 0} + m_PreloadedShaders: [] + m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, + type: 0} + m_CustomRenderPipeline: {fileID: 11400000, guid: 3d47f01a90fe56d43b0cfac27039c94c, + type: 2} + m_TransparencySortMode: 0 + m_TransparencySortAxis: {x: 0, y: 0, z: 1} + m_DefaultRenderingPath: 1 + m_DefaultMobileRenderingPath: 1 + m_TierSettings: [] + m_LightmapStripping: 0 + m_FogStripping: 0 + m_InstancingStripping: 0 + m_LightmapKeepPlain: 1 + m_LightmapKeepDirCombined: 1 + m_LightmapKeepDynamicPlain: 1 + m_LightmapKeepDynamicDirCombined: 1 + m_LightmapKeepShadowMask: 1 + m_LightmapKeepSubtractive: 1 + m_FogKeepLinear: 1 + m_FogKeepExp: 1 + m_FogKeepExp2: 1 + m_AlbedoSwatchInfos: [] + m_LightsUseLinearIntensity: 0 + m_LightsUseColorTemperature: 0 + m_LogWhenShaderIsCompiled: 0 + m_AllowEnlightenSupportForUpgradedProject: 0 diff --git a/Outline.URP/ProjectSettings/HDRPProjectSettings.asset b/Outline.URP/ProjectSettings/HDRPProjectSettings.asset new file mode 100644 index 0000000..dddb307 --- /dev/null +++ b/Outline.URP/ProjectSettings/HDRPProjectSettings.asset @@ -0,0 +1,21 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &1 +MonoBehaviour: + m_ObjectHideFlags: 61 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 63a2978a97e4fc04cb9d905947216f3d, type: 3} + m_Name: + m_EditorClassIdentifier: + version: 1 + m_DefaultScenePrefabSaved: {fileID: 0} + m_DefaultDXRScenePrefabSaved: {fileID: 0} + m_ProjectSettingFolderPath: HDRPDefaultResources + m_WizardPopupAtStart: 0 + m_WizardActiveTab: 0 + m_PackageVersionForMaterials: 7.1.8 diff --git a/Outline.URP/ProjectSettings/InputManager.asset b/Outline.URP/ProjectSettings/InputManager.asset new file mode 100644 index 0000000..b16147e --- /dev/null +++ b/Outline.URP/ProjectSettings/InputManager.asset @@ -0,0 +1,487 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!13 &1 +InputManager: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Axes: + - serializedVersion: 3 + m_Name: Horizontal + descriptiveName: + descriptiveNegativeName: + negativeButton: left + positiveButton: right + altNegativeButton: a + altPositiveButton: d + gravity: 3 + dead: 0.001 + sensitivity: 3 + snap: 1 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Vertical + descriptiveName: + descriptiveNegativeName: + negativeButton: down + positiveButton: up + altNegativeButton: s + altPositiveButton: w + gravity: 3 + dead: 0.001 + sensitivity: 3 + snap: 1 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire1 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left ctrl + altNegativeButton: + altPositiveButton: mouse 0 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire2 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left alt + altNegativeButton: + altPositiveButton: mouse 1 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire3 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left shift + altNegativeButton: + altPositiveButton: mouse 2 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Jump + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: space + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Mouse X + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0 + sensitivity: 0.1 + snap: 0 + invert: 0 + type: 1 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Mouse Y + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0 + sensitivity: 0.1 + snap: 0 + invert: 0 + type: 1 + axis: 1 + joyNum: 0 + - serializedVersion: 3 + m_Name: Mouse ScrollWheel + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0 + sensitivity: 0.1 + snap: 0 + invert: 0 + type: 1 + axis: 2 + joyNum: 0 + - serializedVersion: 3 + m_Name: Horizontal + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0.19 + sensitivity: 1 + snap: 0 + invert: 0 + type: 2 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Vertical + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0.19 + sensitivity: 1 + snap: 0 + invert: 1 + type: 2 + axis: 1 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire1 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 0 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire2 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 1 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire3 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 2 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Jump + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 3 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Submit + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: return + altNegativeButton: + altPositiveButton: joystick button 0 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Submit + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: enter + altNegativeButton: + altPositiveButton: space + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Cancel + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: escape + altNegativeButton: + altPositiveButton: joystick button 1 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Enable Debug Button 1 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left ctrl + altNegativeButton: + altPositiveButton: joystick button 8 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Enable Debug Button 2 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: backspace + altNegativeButton: + altPositiveButton: joystick button 9 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Reset + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left alt + altNegativeButton: + altPositiveButton: joystick button 1 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Next + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: page down + altNegativeButton: + altPositiveButton: joystick button 5 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Previous + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: page up + altNegativeButton: + altPositiveButton: joystick button 4 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Validate + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: return + altNegativeButton: + altPositiveButton: joystick button 0 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Persistent + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: right shift + altNegativeButton: + altPositiveButton: joystick button 2 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Multiplier + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left shift + altNegativeButton: + altPositiveButton: joystick button 3 + gravity: 0 + dead: 0 + sensitivity: 0 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Horizontal + descriptiveName: + descriptiveNegativeName: + negativeButton: left + positiveButton: right + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Vertical + descriptiveName: + descriptiveNegativeName: + negativeButton: down + positiveButton: up + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Vertical + descriptiveName: + descriptiveNegativeName: + negativeButton: down + positiveButton: up + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 2 + axis: 6 + joyNum: 0 + - serializedVersion: 3 + m_Name: Debug Horizontal + descriptiveName: + descriptiveNegativeName: + negativeButton: left + positiveButton: right + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 2 + axis: 5 + joyNum: 0 diff --git a/Outline.URP/ProjectSettings/NavMeshAreas.asset b/Outline.URP/ProjectSettings/NavMeshAreas.asset new file mode 100644 index 0000000..3b0b7c3 --- /dev/null +++ b/Outline.URP/ProjectSettings/NavMeshAreas.asset @@ -0,0 +1,91 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!126 &1 +NavMeshProjectSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + areas: + - name: Walkable + cost: 1 + - name: Not Walkable + cost: 1 + - name: Jump + cost: 2 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + m_LastAgentTypeID: -887442657 + m_Settings: + - serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.75 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_SettingNames: + - Humanoid diff --git a/Outline.URP/ProjectSettings/Physics2DSettings.asset b/Outline.URP/ProjectSettings/Physics2DSettings.asset new file mode 100644 index 0000000..6c5cf8a --- /dev/null +++ b/Outline.URP/ProjectSettings/Physics2DSettings.asset @@ -0,0 +1,56 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!19 &1 +Physics2DSettings: + m_ObjectHideFlags: 0 + serializedVersion: 4 + m_Gravity: {x: 0, y: -9.81} + m_DefaultMaterial: {fileID: 0} + m_VelocityIterations: 8 + m_PositionIterations: 3 + m_VelocityThreshold: 1 + m_MaxLinearCorrection: 0.2 + m_MaxAngularCorrection: 8 + m_MaxTranslationSpeed: 100 + m_MaxRotationSpeed: 360 + m_BaumgarteScale: 0.2 + m_BaumgarteTimeOfImpactScale: 0.75 + m_TimeToSleep: 0.5 + m_LinearSleepTolerance: 0.01 + m_AngularSleepTolerance: 2 + m_DefaultContactOffset: 0.01 + m_JobOptions: + serializedVersion: 2 + useMultithreading: 0 + useConsistencySorting: 0 + m_InterpolationPosesPerJob: 100 + m_NewContactsPerJob: 30 + m_CollideContactsPerJob: 100 + m_ClearFlagsPerJob: 200 + m_ClearBodyForcesPerJob: 200 + m_SyncDiscreteFixturesPerJob: 50 + m_SyncContinuousFixturesPerJob: 50 + m_FindNearestContactsPerJob: 100 + m_UpdateTriggerContactsPerJob: 100 + m_IslandSolverCostThreshold: 100 + m_IslandSolverBodyCostScale: 1 + m_IslandSolverContactCostScale: 10 + m_IslandSolverJointCostScale: 10 + m_IslandSolverBodiesPerJob: 50 + m_IslandSolverContactsPerJob: 50 + m_AutoSimulation: 1 + m_QueriesHitTriggers: 1 + m_QueriesStartInColliders: 1 + m_CallbacksOnDisable: 1 + m_ReuseCollisionCallbacks: 0 + m_AutoSyncTransforms: 0 + m_AlwaysShowColliders: 0 + m_ShowColliderSleep: 1 + m_ShowColliderContacts: 0 + m_ShowColliderAABB: 0 + m_ContactArrowScale: 0.2 + m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412} + m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432} + m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745} + m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804} + m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff diff --git a/Outline.URP/ProjectSettings/PresetManager.asset b/Outline.URP/ProjectSettings/PresetManager.asset new file mode 100644 index 0000000..67a94da --- /dev/null +++ b/Outline.URP/ProjectSettings/PresetManager.asset @@ -0,0 +1,7 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1386491679 &1 +PresetManager: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_DefaultPresets: {} diff --git a/Outline.URP/ProjectSettings/ProjectSettings.asset b/Outline.URP/ProjectSettings/ProjectSettings.asset new file mode 100644 index 0000000..dd0b4e2 --- /dev/null +++ b/Outline.URP/ProjectSettings/ProjectSettings.asset @@ -0,0 +1,610 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!129 &1 +PlayerSettings: + m_ObjectHideFlags: 0 + serializedVersion: 20 + productGUID: 0070264e70e54274fa5f11274f89afab + AndroidProfiler: 0 + AndroidFilterTouchesWhenObscured: 0 + AndroidEnableSustainedPerformanceMode: 0 + defaultScreenOrientation: 4 + targetDevice: 2 + useOnDemandResources: 0 + accelerometerFrequency: 60 + companyName: DefaultCompany + productName: Outline.URP + defaultCursor: {fileID: 0} + cursorHotspot: {x: 0, y: 0} + m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1} + m_ShowUnitySplashScreen: 1 + m_ShowUnitySplashLogo: 1 + m_SplashScreenOverlayOpacity: 1 + m_SplashScreenAnimation: 1 + m_SplashScreenLogoStyle: 1 + m_SplashScreenDrawMode: 0 + m_SplashScreenBackgroundAnimationZoom: 1 + m_SplashScreenLogoAnimationZoom: 1 + m_SplashScreenBackgroundLandscapeAspect: 1 + m_SplashScreenBackgroundPortraitAspect: 1 + m_SplashScreenBackgroundLandscapeUvs: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + m_SplashScreenBackgroundPortraitUvs: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + m_SplashScreenLogos: [] + m_VirtualRealitySplashScreen: {fileID: 0} + m_HolographicTrackingLossScreen: {fileID: 0} + defaultScreenWidth: 1024 + defaultScreenHeight: 768 + defaultScreenWidthWeb: 960 + defaultScreenHeightWeb: 600 + m_StereoRenderingPath: 0 + m_ActiveColorSpace: 0 + m_MTRendering: 1 + m_StackTraceTypes: 010000000100000001000000010000000100000001000000 + iosShowActivityIndicatorOnLoading: -1 + androidShowActivityIndicatorOnLoading: -1 + iosUseCustomAppBackgroundBehavior: 0 + iosAllowHTTPDownload: 1 + allowedAutorotateToPortrait: 1 + allowedAutorotateToPortraitUpsideDown: 1 + allowedAutorotateToLandscapeRight: 1 + allowedAutorotateToLandscapeLeft: 1 + useOSAutorotation: 1 + use32BitDisplayBuffer: 1 + preserveFramebufferAlpha: 0 + disableDepthAndStencilBuffers: 0 + androidStartInFullscreen: 1 + androidRenderOutsideSafeArea: 1 + androidUseSwappy: 0 + androidBlitType: 0 + defaultIsNativeResolution: 1 + macRetinaSupport: 1 + runInBackground: 0 + captureSingleScreen: 0 + muteOtherAudioSources: 0 + Prepare IOS For Recording: 0 + Force IOS Speakers When Recording: 0 + deferSystemGesturesMode: 0 + hideHomeButton: 0 + submitAnalytics: 1 + usePlayerLog: 1 + bakeCollisionMeshes: 0 + forceSingleInstance: 0 + useFlipModelSwapchain: 1 + resizableWindow: 0 + useMacAppStoreValidation: 0 + macAppStoreCategory: public.app-category.games + gpuSkinning: 0 + xboxPIXTextureCapture: 0 + xboxEnableAvatar: 0 + xboxEnableKinect: 0 + xboxEnableKinectAutoTracking: 0 + xboxEnableFitness: 0 + visibleInBackground: 1 + allowFullscreenSwitch: 1 + fullscreenMode: 1 + xboxSpeechDB: 0 + xboxEnableHeadOrientation: 0 + xboxEnableGuest: 0 + xboxEnablePIXSampling: 0 + metalFramebufferOnly: 0 + xboxOneResolution: 0 + xboxOneSResolution: 0 + xboxOneXResolution: 3 + xboxOneMonoLoggingLevel: 0 + xboxOneLoggingLevel: 1 + xboxOneDisableEsram: 0 + xboxOnePresentImmediateThreshold: 0 + switchQueueCommandMemory: 1048576 + switchQueueControlMemory: 16384 + switchQueueComputeMemory: 262144 + switchNVNShaderPoolsGranularity: 33554432 + switchNVNDefaultPoolsGranularity: 16777216 + switchNVNOtherPoolsGranularity: 16777216 + vulkanNumSwapchainBuffers: 3 + vulkanEnableSetSRGBWrite: 0 + m_SupportedAspectRatios: + 4:3: 1 + 5:4: 1 + 16:10: 1 + 16:9: 1 + Others: 1 + bundleVersion: 1.0 + preloadedAssets: [] + metroInputSource: 0 + wsaTransparentSwapchain: 0 + m_HolographicPauseOnTrackingLoss: 1 + xboxOneDisableKinectGpuReservation: 1 + xboxOneEnable7thCore: 1 + vrSettings: + cardboard: + depthFormat: 0 + enableTransitionView: 0 + daydream: + depthFormat: 0 + useSustainedPerformanceMode: 0 + enableVideoLayer: 0 + useProtectedVideoMemory: 0 + minimumSupportedHeadTracking: 0 + maximumSupportedHeadTracking: 1 + hololens: + depthFormat: 1 + depthBufferSharingEnabled: 1 + lumin: + depthFormat: 0 + frameTiming: 2 + enableGLCache: 0 + glCacheMaxBlobSize: 524288 + glCacheMaxFileSize: 8388608 + oculus: + sharedDepthBuffer: 1 + dashSupport: 1 + lowOverheadMode: 0 + protectedContext: 0 + v2Signing: 1 + enable360StereoCapture: 0 + isWsaHolographicRemotingEnabled: 0 + enableFrameTimingStats: 0 + useHDRDisplay: 0 + D3DHDRBitDepth: 0 + m_ColorGamuts: 00000000 + targetPixelDensity: 0 + resolutionScalingMode: 0 + androidSupportedAspectRatio: 1 + androidMaxAspectRatio: 2.1 + applicationIdentifier: {} + buildNumber: {} + AndroidBundleVersionCode: 1 + AndroidMinSdkVersion: 19 + AndroidTargetSdkVersion: 0 + AndroidPreferredInstallLocation: 1 + aotOptions: + stripEngineCode: 1 + iPhoneStrippingLevel: 0 + iPhoneScriptCallOptimization: 0 + ForceInternetPermission: 0 + ForceSDCardPermission: 0 + CreateWallpaper: 0 + APKExpansionFiles: 0 + keepLoadedShadersAlive: 0 + StripUnusedMeshComponents: 0 + VertexChannelCompressionMask: 4054 + iPhoneSdkVersion: 988 + iOSTargetOSVersionString: + tvOSSdkVersion: 0 + tvOSRequireExtendedGameController: 0 + tvOSTargetOSVersionString: + uIPrerenderedIcon: 0 + uIRequiresPersistentWiFi: 0 + uIRequiresFullScreen: 1 + uIStatusBarHidden: 1 + uIExitOnSuspend: 0 + uIStatusBarStyle: 0 + iPhoneSplashScreen: {fileID: 0} + iPhoneHighResSplashScreen: {fileID: 0} + iPhoneTallHighResSplashScreen: {fileID: 0} + iPhone47inSplashScreen: {fileID: 0} + iPhone55inPortraitSplashScreen: {fileID: 0} + iPhone55inLandscapeSplashScreen: {fileID: 0} + iPhone58inPortraitSplashScreen: {fileID: 0} + iPhone58inLandscapeSplashScreen: {fileID: 0} + iPadPortraitSplashScreen: {fileID: 0} + iPadHighResPortraitSplashScreen: {fileID: 0} + iPadLandscapeSplashScreen: {fileID: 0} + iPadHighResLandscapeSplashScreen: {fileID: 0} + iPhone65inPortraitSplashScreen: {fileID: 0} + iPhone65inLandscapeSplashScreen: {fileID: 0} + iPhone61inPortraitSplashScreen: {fileID: 0} + iPhone61inLandscapeSplashScreen: {fileID: 0} + appleTVSplashScreen: {fileID: 0} + appleTVSplashScreen2x: {fileID: 0} + tvOSSmallIconLayers: [] + tvOSSmallIconLayers2x: [] + tvOSLargeIconLayers: [] + tvOSLargeIconLayers2x: [] + tvOSTopShelfImageLayers: [] + tvOSTopShelfImageLayers2x: [] + tvOSTopShelfImageWideLayers: [] + tvOSTopShelfImageWideLayers2x: [] + iOSLaunchScreenType: 0 + iOSLaunchScreenPortrait: {fileID: 0} + iOSLaunchScreenLandscape: {fileID: 0} + iOSLaunchScreenBackgroundColor: + serializedVersion: 2 + rgba: 0 + iOSLaunchScreenFillPct: 100 + iOSLaunchScreenSize: 100 + iOSLaunchScreenCustomXibPath: + iOSLaunchScreeniPadType: 0 + iOSLaunchScreeniPadImage: {fileID: 0} + iOSLaunchScreeniPadBackgroundColor: + serializedVersion: 2 + rgba: 0 + iOSLaunchScreeniPadFillPct: 100 + iOSLaunchScreeniPadSize: 100 + iOSLaunchScreeniPadCustomXibPath: + iOSUseLaunchScreenStoryboard: 0 + iOSLaunchScreenCustomStoryboardPath: + iOSDeviceRequirements: [] + iOSURLSchemes: [] + iOSBackgroundModes: 0 + iOSMetalForceHardShadows: 0 + metalEditorSupport: 1 + metalAPIValidation: 1 + iOSRenderExtraFrameOnPause: 0 + appleDeveloperTeamID: + iOSManualSigningProvisioningProfileID: + tvOSManualSigningProvisioningProfileID: + iOSManualSigningProvisioningProfileType: 0 + tvOSManualSigningProvisioningProfileType: 0 + appleEnableAutomaticSigning: 0 + iOSRequireARKit: 0 + iOSAutomaticallyDetectAndAddCapabilities: 1 + appleEnableProMotion: 0 + clonedFromGUID: 00000000000000000000000000000000 + templatePackageId: + templateDefaultScene: + AndroidTargetArchitectures: 1 + AndroidSplashScreenScale: 0 + androidSplashScreen: {fileID: 0} + AndroidKeystoreName: + AndroidKeyaliasName: + AndroidBuildApkPerCpuArchitecture: 0 + AndroidTVCompatibility: 0 + AndroidIsGame: 1 + AndroidEnableTango: 0 + androidEnableBanner: 1 + androidUseLowAccuracyLocation: 0 + androidUseCustomKeystore: 0 + m_AndroidBanners: + - width: 320 + height: 180 + banner: {fileID: 0} + androidGamepadSupportLevel: 0 + AndroidValidateAppBundleSize: 1 + AndroidAppBundleSizeToValidate: 150 + m_BuildTargetIcons: [] + m_BuildTargetPlatformIcons: [] + m_BuildTargetBatching: [] + m_BuildTargetGraphicsJobs: [] + m_BuildTargetGraphicsJobMode: [] + m_BuildTargetGraphicsAPIs: [] + m_BuildTargetVRSettings: [] + openGLRequireES31: 0 + openGLRequireES31AEP: 0 + openGLRequireES32: 0 + m_TemplateCustomTags: {} + mobileMTRendering: + Android: 1 + iPhone: 1 + tvOS: 1 + m_BuildTargetGroupLightmapEncodingQuality: [] + m_BuildTargetGroupLightmapSettings: [] + playModeTestRunnerEnabled: 0 + runPlayModeTestAsEditModeTest: 0 + actionOnDotNetUnhandledException: 1 + enableInternalProfiler: 0 + logObjCUncaughtExceptions: 1 + enableCrashReportAPI: 0 + cameraUsageDescription: + locationUsageDescription: + microphoneUsageDescription: + switchNetLibKey: + switchSocketMemoryPoolSize: 6144 + switchSocketAllocatorPoolSize: 128 + switchSocketConcurrencyLimit: 14 + switchScreenResolutionBehavior: 2 + switchUseCPUProfiler: 0 + switchApplicationID: 0x01004b9000490000 + switchNSODependencies: + switchTitleNames_0: + switchTitleNames_1: + switchTitleNames_2: + switchTitleNames_3: + switchTitleNames_4: + switchTitleNames_5: + switchTitleNames_6: + switchTitleNames_7: + switchTitleNames_8: + switchTitleNames_9: + switchTitleNames_10: + switchTitleNames_11: + switchTitleNames_12: + switchTitleNames_13: + switchTitleNames_14: + switchPublisherNames_0: + switchPublisherNames_1: + switchPublisherNames_2: + switchPublisherNames_3: + switchPublisherNames_4: + switchPublisherNames_5: + switchPublisherNames_6: + switchPublisherNames_7: + switchPublisherNames_8: + switchPublisherNames_9: + switchPublisherNames_10: + switchPublisherNames_11: + switchPublisherNames_12: + switchPublisherNames_13: + switchPublisherNames_14: + switchIcons_0: {fileID: 0} + switchIcons_1: {fileID: 0} + switchIcons_2: {fileID: 0} + switchIcons_3: {fileID: 0} + switchIcons_4: {fileID: 0} + switchIcons_5: {fileID: 0} + switchIcons_6: {fileID: 0} + switchIcons_7: {fileID: 0} + switchIcons_8: {fileID: 0} + switchIcons_9: {fileID: 0} + switchIcons_10: {fileID: 0} + switchIcons_11: {fileID: 0} + switchIcons_12: {fileID: 0} + switchIcons_13: {fileID: 0} + switchIcons_14: {fileID: 0} + switchSmallIcons_0: {fileID: 0} + switchSmallIcons_1: {fileID: 0} + switchSmallIcons_2: {fileID: 0} + switchSmallIcons_3: {fileID: 0} + switchSmallIcons_4: {fileID: 0} + switchSmallIcons_5: {fileID: 0} + switchSmallIcons_6: {fileID: 0} + switchSmallIcons_7: {fileID: 0} + switchSmallIcons_8: {fileID: 0} + switchSmallIcons_9: {fileID: 0} + switchSmallIcons_10: {fileID: 0} + switchSmallIcons_11: {fileID: 0} + switchSmallIcons_12: {fileID: 0} + switchSmallIcons_13: {fileID: 0} + switchSmallIcons_14: {fileID: 0} + switchManualHTML: + switchAccessibleURLs: + switchLegalInformation: + switchMainThreadStackSize: 1048576 + switchPresenceGroupId: + switchLogoHandling: 0 + switchReleaseVersion: 0 + switchDisplayVersion: 1.0.0 + switchStartupUserAccount: 0 + switchTouchScreenUsage: 0 + switchSupportedLanguagesMask: 0 + switchLogoType: 0 + switchApplicationErrorCodeCategory: + switchUserAccountSaveDataSize: 0 + switchUserAccountSaveDataJournalSize: 0 + switchApplicationAttribute: 0 + switchCardSpecSize: -1 + switchCardSpecClock: -1 + switchRatingsMask: 0 + switchRatingsInt_0: 0 + switchRatingsInt_1: 0 + switchRatingsInt_2: 0 + switchRatingsInt_3: 0 + switchRatingsInt_4: 0 + switchRatingsInt_5: 0 + switchRatingsInt_6: 0 + switchRatingsInt_7: 0 + switchRatingsInt_8: 0 + switchRatingsInt_9: 0 + switchRatingsInt_10: 0 + switchRatingsInt_11: 0 + switchRatingsInt_12: 0 + switchLocalCommunicationIds_0: + switchLocalCommunicationIds_1: + switchLocalCommunicationIds_2: + switchLocalCommunicationIds_3: + switchLocalCommunicationIds_4: + switchLocalCommunicationIds_5: + switchLocalCommunicationIds_6: + switchLocalCommunicationIds_7: + switchParentalControl: 0 + switchAllowsScreenshot: 1 + switchAllowsVideoCapturing: 1 + switchAllowsRuntimeAddOnContentInstall: 0 + switchDataLossConfirmation: 0 + switchUserAccountLockEnabled: 0 + switchSystemResourceMemory: 16777216 + switchSupportedNpadStyles: 22 + switchNativeFsCacheSize: 32 + switchIsHoldTypeHorizontal: 0 + switchSupportedNpadCount: 8 + switchSocketConfigEnabled: 0 + switchTcpInitialSendBufferSize: 32 + switchTcpInitialReceiveBufferSize: 64 + switchTcpAutoSendBufferSizeMax: 256 + switchTcpAutoReceiveBufferSizeMax: 256 + switchUdpSendBufferSize: 9 + switchUdpReceiveBufferSize: 42 + switchSocketBufferEfficiency: 4 + switchSocketInitializeEnabled: 1 + switchNetworkInterfaceManagerInitializeEnabled: 1 + switchPlayerConnectionEnabled: 1 + ps4NPAgeRating: 12 + ps4NPTitleSecret: + ps4NPTrophyPackPath: + ps4ParentalLevel: 11 + ps4ContentID: ED1633-NPXX51362_00-0000000000000000 + ps4Category: 0 + ps4MasterVersion: 01.00 + ps4AppVersion: 01.00 + ps4AppType: 0 + ps4ParamSfxPath: + ps4VideoOutPixelFormat: 0 + ps4VideoOutInitialWidth: 1920 + ps4VideoOutBaseModeInitialWidth: 1920 + ps4VideoOutReprojectionRate: 60 + ps4PronunciationXMLPath: + ps4PronunciationSIGPath: + ps4BackgroundImagePath: + ps4StartupImagePath: + ps4StartupImagesFolder: + ps4IconImagesFolder: + ps4SaveDataImagePath: + ps4SdkOverride: + ps4BGMPath: + ps4ShareFilePath: + ps4ShareOverlayImagePath: + ps4PrivacyGuardImagePath: + ps4NPtitleDatPath: + ps4RemotePlayKeyAssignment: -1 + ps4RemotePlayKeyMappingDir: + ps4PlayTogetherPlayerCount: 0 + ps4EnterButtonAssignment: 2 + ps4ApplicationParam1: 0 + ps4ApplicationParam2: 0 + ps4ApplicationParam3: 0 + ps4ApplicationParam4: 0 + ps4DownloadDataSize: 0 + ps4GarlicHeapSize: 2048 + ps4ProGarlicHeapSize: 2560 + playerPrefsMaxSize: 32768 + ps4Passcode: frAQBc8Wsa1xVPfvJcrgRYwTiizs2trQ + ps4pnSessions: 1 + ps4pnPresence: 1 + ps4pnFriends: 1 + ps4pnGameCustomData: 1 + playerPrefsSupport: 0 + enableApplicationExit: 0 + resetTempFolder: 1 + restrictedAudioUsageRights: 0 + ps4UseResolutionFallback: 0 + ps4ReprojectionSupport: 0 + ps4UseAudio3dBackend: 0 + ps4SocialScreenEnabled: 0 + ps4ScriptOptimizationLevel: 2 + ps4Audio3dVirtualSpeakerCount: 14 + ps4attribCpuUsage: 0 + ps4PatchPkgPath: + ps4PatchLatestPkgPath: + ps4PatchChangeinfoPath: + ps4PatchDayOne: 0 + ps4attribUserManagement: 0 + ps4attribMoveSupport: 0 + ps4attrib3DSupport: 0 + ps4attribShareSupport: 0 + ps4attribExclusiveVR: 0 + ps4disableAutoHideSplash: 0 + ps4videoRecordingFeaturesUsed: 0 + ps4contentSearchFeaturesUsed: 0 + ps4attribEyeToEyeDistanceSettingVR: 0 + ps4IncludedModules: [] + ps4attribVROutputEnabled: 0 + monoEnv: + splashScreenBackgroundSourceLandscape: {fileID: 0} + splashScreenBackgroundSourcePortrait: {fileID: 0} + blurSplashScreenBackground: 1 + spritePackerPolicy: + webGLMemorySize: 32 + webGLExceptionSupport: 1 + webGLNameFilesAsHashes: 0 + webGLDataCaching: 1 + webGLDebugSymbols: 0 + webGLEmscriptenArgs: + webGLModulesDirectory: + webGLTemplate: APPLICATION:Default + webGLAnalyzeBuildSize: 0 + webGLUseEmbeddedResources: 0 + webGLCompressionFormat: 0 + webGLLinkerTarget: 1 + webGLThreadsSupport: 0 + webGLWasmStreaming: 0 + scriptingDefineSymbols: {} + platformArchitecture: {} + scriptingBackend: {} + il2cppCompilerConfiguration: {} + managedStrippingLevel: {} + incrementalIl2cppBuild: {} + allowUnsafeCode: 0 + additionalIl2CppArgs: + scriptingRuntimeVersion: 1 + gcIncremental: 0 + gcWBarrierValidation: 0 + apiCompatibilityLevelPerPlatform: {} + m_RenderingPath: 1 + m_MobileRenderingPath: 1 + metroPackageName: Outline.URP + metroPackageVersion: + metroCertificatePath: + metroCertificatePassword: + metroCertificateSubject: + metroCertificateIssuer: + metroCertificateNotAfter: 0000000000000000 + metroApplicationDescription: Outline.URP + wsaImages: {} + metroTileShortName: + metroTileShowName: 0 + metroMediumTileShowName: 0 + metroLargeTileShowName: 0 + metroWideTileShowName: 0 + metroSupportStreamingInstall: 0 + metroLastRequiredScene: 0 + metroDefaultTileSize: 1 + metroTileForegroundText: 2 + metroTileBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21568628, a: 0} + metroSplashScreenBackgroundColor: {r: 0.12941177, g: 0.17254902, b: 0.21568628, + a: 1} + metroSplashScreenUseBackgroundColor: 0 + platformCapabilities: {} + metroTargetDeviceFamilies: {} + metroFTAName: + metroFTAFileTypes: [] + metroProtocolName: + XboxOneProductId: + XboxOneUpdateKey: + XboxOneSandboxId: + XboxOneContentId: + XboxOneTitleId: + XboxOneSCId: + XboxOneGameOsOverridePath: + XboxOnePackagingOverridePath: + XboxOneAppManifestOverridePath: + XboxOneVersion: 1.0.0.0 + XboxOnePackageEncryption: 0 + XboxOnePackageUpdateGranularity: 2 + XboxOneDescription: + XboxOneLanguage: + - enus + XboxOneCapability: [] + XboxOneGameRating: {} + XboxOneIsContentPackage: 0 + XboxOneEnableGPUVariability: 1 + XboxOneSockets: {} + XboxOneSplashScreen: {fileID: 0} + XboxOneAllowedProductIds: [] + XboxOnePersistentLocalStorageSize: 0 + XboxOneXTitleMemory: 8 + XboxOneOverrideIdentityName: + vrEditorSettings: + daydream: + daydreamIconForeground: {fileID: 0} + daydreamIconBackground: {fileID: 0} + cloudServicesEnabled: {} + luminIcon: + m_Name: + m_ModelFolderPath: + m_PortalFolderPath: + luminCert: + m_CertPath: + m_SignPackage: 1 + luminIsChannelApp: 0 + luminVersion: + m_VersionCode: 1 + m_VersionName: + apiCompatibilityLevel: 6 + cloudProjectId: + framebufferDepthMemorylessMode: 0 + projectName: + organizationId: + cloudEnabled: 0 + enableNativePlatformBackendsForNewInputSystem: 0 + disableOldInputManagerSupport: 0 + legacyClampBlendShapeWeights: 0 diff --git a/Outline.URP/ProjectSettings/ProjectVersion.txt b/Outline.URP/ProjectSettings/ProjectVersion.txt new file mode 100644 index 0000000..798259b --- /dev/null +++ b/Outline.URP/ProjectSettings/ProjectVersion.txt @@ -0,0 +1,2 @@ +m_EditorVersion: 2019.3.0f6 +m_EditorVersionWithRevision: 2019.3.0f6 (27ab2135bccf) diff --git a/Outline.URP/ProjectSettings/QualitySettings.asset b/Outline.URP/ProjectSettings/QualitySettings.asset new file mode 100644 index 0000000..38a45f3 --- /dev/null +++ b/Outline.URP/ProjectSettings/QualitySettings.asset @@ -0,0 +1,236 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!47 &1 +QualitySettings: + m_ObjectHideFlags: 0 + serializedVersion: 5 + m_CurrentQuality: 5 + m_QualitySettings: + - serializedVersion: 2 + name: Very Low + pixelLightCount: 0 + shadows: 0 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 15 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 0 + skinWeights: 1 + textureQuality: 1 + anisotropicTextures: 0 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 0 + lodBias: 0.3 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 4 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + customRenderPipeline: {fileID: 0} + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Low + pixelLightCount: 0 + shadows: 0 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 20 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 0 + skinWeights: 2 + textureQuality: 0 + anisotropicTextures: 0 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 0 + lodBias: 0.4 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 16 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + customRenderPipeline: {fileID: 0} + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Medium + pixelLightCount: 1 + shadows: 1 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 20 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 0 + skinWeights: 2 + textureQuality: 0 + anisotropicTextures: 1 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 1 + lodBias: 0.7 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 64 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + customRenderPipeline: {fileID: 0} + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: High + pixelLightCount: 2 + shadows: 2 + shadowResolution: 1 + shadowProjection: 1 + shadowCascades: 2 + shadowDistance: 40 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 1 + skinWeights: 2 + textureQuality: 0 + anisotropicTextures: 1 + antiAliasing: 0 + softParticles: 0 + softVegetation: 1 + realtimeReflectionProbes: 1 + billboardsFaceCameraPosition: 1 + vSyncCount: 1 + lodBias: 1 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 256 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + customRenderPipeline: {fileID: 0} + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Very High + pixelLightCount: 3 + shadows: 2 + shadowResolution: 2 + shadowProjection: 1 + shadowCascades: 2 + shadowDistance: 70 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 1 + skinWeights: 4 + textureQuality: 0 + anisotropicTextures: 2 + antiAliasing: 2 + softParticles: 1 + softVegetation: 1 + realtimeReflectionProbes: 1 + billboardsFaceCameraPosition: 1 + vSyncCount: 1 + lodBias: 1.5 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 1024 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + customRenderPipeline: {fileID: 0} + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Ultra + pixelLightCount: 4 + shadows: 2 + shadowResolution: 2 + shadowProjection: 1 + shadowCascades: 4 + shadowDistance: 150 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 1 + skinWeights: 255 + textureQuality: 0 + anisotropicTextures: 2 + antiAliasing: 0 + softParticles: 1 + softVegetation: 1 + realtimeReflectionProbes: 1 + billboardsFaceCameraPosition: 1 + vSyncCount: 1 + lodBias: 2 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 4096 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + customRenderPipeline: {fileID: 0} + excludedTargetPlatforms: [] + m_PerPlatformDefaultQuality: + Android: 2 + Lumin: 5 + Nintendo Switch: 5 + PS4: 5 + Stadia: 5 + Standalone: 5 + WebGL: 3 + Windows Store Apps: 5 + XboxOne: 5 + iPhone: 2 + tvOS: 2 diff --git a/Outline.URP/ProjectSettings/TagManager.asset b/Outline.URP/ProjectSettings/TagManager.asset new file mode 100644 index 0000000..1c92a78 --- /dev/null +++ b/Outline.URP/ProjectSettings/TagManager.asset @@ -0,0 +1,43 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!78 &1 +TagManager: + serializedVersion: 2 + tags: [] + layers: + - Default + - TransparentFX + - Ignore Raycast + - + - Water + - UI + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + m_SortingLayers: + - name: Default + uniqueID: 0 + locked: 0 diff --git a/Outline.URP/ProjectSettings/TimeManager.asset b/Outline.URP/ProjectSettings/TimeManager.asset new file mode 100644 index 0000000..558a017 --- /dev/null +++ b/Outline.URP/ProjectSettings/TimeManager.asset @@ -0,0 +1,9 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!5 &1 +TimeManager: + m_ObjectHideFlags: 0 + Fixed Timestep: 0.02 + Maximum Allowed Timestep: 0.33333334 + m_TimeScale: 1 + Maximum Particle Timestep: 0.03 diff --git a/Outline.URP/ProjectSettings/URPProjectSettings.asset b/Outline.URP/ProjectSettings/URPProjectSettings.asset new file mode 100644 index 0000000..fa89832 --- /dev/null +++ b/Outline.URP/ProjectSettings/URPProjectSettings.asset @@ -0,0 +1,15 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &1 +MonoBehaviour: + m_ObjectHideFlags: 61 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 247994e1f5a72c2419c26a37e9334c01, type: 3} + m_Name: + m_EditorClassIdentifier: + m_LastMaterialVersion: 1 diff --git a/Outline.URP/ProjectSettings/UnityConnectSettings.asset b/Outline.URP/ProjectSettings/UnityConnectSettings.asset new file mode 100644 index 0000000..fa0b146 --- /dev/null +++ b/Outline.URP/ProjectSettings/UnityConnectSettings.asset @@ -0,0 +1,34 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!310 &1 +UnityConnectSettings: + m_ObjectHideFlags: 0 + serializedVersion: 1 + m_Enabled: 0 + m_TestMode: 0 + m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events + m_EventUrl: https://cdp.cloud.unity3d.com/v1/events + m_ConfigUrl: https://config.uca.cloud.unity3d.com + m_TestInitMode: 0 + CrashReportingSettings: + m_EventUrl: https://perf-events.cloud.unity3d.com + m_Enabled: 0 + m_LogBufferSize: 10 + m_CaptureEditorExceptions: 1 + UnityPurchasingSettings: + m_Enabled: 0 + m_TestMode: 0 + UnityAnalyticsSettings: + m_Enabled: 0 + m_TestMode: 0 + m_InitializeOnStartup: 1 + UnityAdsSettings: + m_Enabled: 0 + m_InitializeOnStartup: 1 + m_TestMode: 0 + m_IosGameId: + m_AndroidGameId: + m_GameIds: {} + m_GameId: + PerformanceReportingSettings: + m_Enabled: 0 diff --git a/Outline.URP/ProjectSettings/VFXManager.asset b/Outline.URP/ProjectSettings/VFXManager.asset new file mode 100644 index 0000000..3a95c98 --- /dev/null +++ b/Outline.URP/ProjectSettings/VFXManager.asset @@ -0,0 +1,12 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!937362698 &1 +VFXManager: + m_ObjectHideFlags: 0 + m_IndirectShader: {fileID: 0} + m_CopyBufferShader: {fileID: 0} + m_SortShader: {fileID: 0} + m_StripUpdateShader: {fileID: 0} + m_RenderPipeSettingsPath: + m_FixedTimeStep: 0.016666668 + m_MaxDeltaTime: 0.05 diff --git a/Outline.URP/ProjectSettings/XRSettings.asset b/Outline.URP/ProjectSettings/XRSettings.asset new file mode 100644 index 0000000..482590c --- /dev/null +++ b/Outline.URP/ProjectSettings/XRSettings.asset @@ -0,0 +1,10 @@ +{ + "m_SettingKeys": [ + "VR Device Disabled", + "VR Device User Alert" + ], + "m_SettingValues": [ + "False", + "False" + ] +} \ No newline at end of file diff --git a/README.md b/README.md index bd34d56..9fff0c8 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,16 @@ # UnityFx.Outline Channel | UnityFx.Outline | ----------|---------------| +--------|-----------------| Github | [![GitHub release](https://img.shields.io/github/release/Arvtesh/UnityFx.Outline.svg?logo=github)](https://github.com/Arvtesh/UnityFx.Outline/releases) Npm (core + built-in RP) | [![Npm release](https://img.shields.io/npm/v/com.unityfx.outline.svg)](https://www.npmjs.com/package/com.unityfx.outline) ![npm](https://img.shields.io/npm/dt/com.unityfx.outline) Npm (Post-processing v2) | [![Npm release](https://img.shields.io/npm/v/com.unityfx.outline.postprocessing.svg)](https://www.npmjs.com/package/com.unityfx.outline.postprocessing) ![npm](https://img.shields.io/npm/dt/com.unityfx.outline.postprocessing) +Npm (URP) | [![Npm release](https://img.shields.io/npm/v/com.unityfx.outline.urp.svg)](https://www.npmjs.com/package/com.unityfx.outline.urp) ![npm](https://img.shields.io/npm/dt/com.unityfx.outline.urp) +Npm (HDRP) | TODO -**Requires Unity 2017 or higher.**
-**Compatible with [Unity Post-processing Stack v2](https://github.com/Unity-Technologies/PostProcessing/tree/v2).** +**Requires Unity 2018.4 or higher.**
+**Compatible with [Unity Post-processing Stack v2](https://github.com/Unity-Technologies/PostProcessing/tree/v2).**
+**Compatible with [Universal Render Pipeline](https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@8.1/manual/index.html).** **Please ask any questions and leave feedback at the [Unity forums](https://forum.unity.com/threads/screen-space-outline-effect-for-unity-free.836908/).** @@ -17,25 +20,27 @@ Npm (Post-processing v2) | [![Npm release](https://img.shields.io/npm/v/com.unit *UnityFx.Outline* implements configurable per-object and per-camera outlines. Both solid and blurred outline modes are supported (Gauss blur). The outlines can be easily customized either through scripts or with Unity editor (both in edit-time or runtime). -Implementation is based on Unity [command buffers](https://docs.unity3d.com/ScriptReference/Rendering.CommandBuffer.html), compatible with [Unity Post-processing Stack v2](https://github.com/Unity-Technologies/PostProcessing/tree/v2), extendable and has no external dependencies. +Implementation is based on Unity [command buffers](https://docs.unity3d.com/ScriptReference/Rendering.CommandBuffer.html), compatible with [Unity Post-processing Stack v2](https://github.com/Unity-Technologies/PostProcessing/tree/v2) and [Universal Render Pipeline](https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@8.1/manual/index.html), extendable and has no external dependencies. Supported outline parameters are: - Color; - Width (in pixels); - Type (solid or blurred); -- Intensity (for blurred outlines). +- Intensity (for blurred outlines); +- Depth testing. Supported platforms: - Windows/Mac standalone; - Android; -- iOS. +- iOS; +- Other platforms (untested). Please see [CHANGELOG](CHANGELOG.md) for information on recent changes. ## Getting Started ### Prerequisites You may need the following software installed in order to build/use the library: -- [Unity3d 2017+](https://store.unity.com/). +- [Unity3d 2018.4+](https://store.unity.com/). ### Getting the code You can get the code by cloning the github repository using your preffered git client UI or you can do it from command line as follows: @@ -46,8 +51,9 @@ git clone https://github.com/Arvtesh/UnityFx.Outline.git ### Npm packages [![NPM](https://nodei.co/npm/com.unityfx.outline.png)](https://www.npmjs.com/package/com.unityfx.outline)
[![NPM](https://nodei.co/npm/com.unityfx.outline.postprocessing.png)](https://www.npmjs.com/package/com.unityfx.outline.postprocessing)
+[![NPM](https://nodei.co/npm/com.unityfx.outline.urp.png)](https://www.npmjs.com/package/com.unityfx.outline.urp)
-Npm core package is available at [npmjs.com](https://www.npmjs.com/package/com.unityfx.outline). There are dedicated packages for [Post-processing Stack v2](https://github.com/Unity-Technologies/PostProcessing/tree/v2), [Universal Render Pipeline](https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@8.0/manual/index.html) and [High Definition Render Pipeline](https://docs.unity3d.com/Packages/com.unity.render-pipelines.high-definition@8.0/manual/index.html). To use the packages, add the following line to dependencies section of your `manifest.json`. Unity should download and link the package automatically: +Npm core package is available at [npmjs.com](https://www.npmjs.com/package/com.unityfx.outline). There are dedicated packages for [Post-processing Stack v2](https://github.com/Unity-Technologies/PostProcessing/tree/v2) and [Universal Render Pipeline](https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@8.0/manual/index.html). To use the packages, add the following line to dependencies section of your `manifest.json`. Unity should download and link the package automatically: ```json { "scopedRegistries": [ @@ -60,8 +66,8 @@ Npm core package is available at [npmjs.com](https://www.npmjs.com/package/com.u } ], "dependencies": { - "com.unityfx.outline": "0.7.2", - "com.unityfx.outline.postprocessing": "0.1.0" + "com.unityfx.outline": "0.8.0", + "com.unityfx.outline.urp": "0.1.0", } } ``` @@ -75,7 +81,7 @@ using UnityFx.Outline; ### Per-camera outlines (built-in RP) ![Outline demo](Docs/OutlineEffectInspector.png "OutlineEffect Inspector") -Add `OutlineEffect` script to a camera that should render outlines. Then add and configure as many layers as you need: +Add `OutlineEffect` script to a camera that should render outlines. Then add and configure as many layers as you need. An outline layer is a group of game objects that share the same outline settings: ```csharp var outlineEffect = Camera.main.GetComponent(); var layer = new OutlineLayer("MyOutlines"); @@ -132,7 +138,7 @@ outlineBehaviour.OutlineIntensity = 10; ``` ### Depth testing -By default depth testing is disabled when rendering outlines. This behaviour can be overriden by setting `OutlineRenderFlags.EnableDepthTesting` flag of `OutlineRenderMode` or settings the corresponding checkbox in editor. +By default depth testing is disabled when rendering outlines. This behaviour can be overriden by setting `EnableDepthTesting` flag of `Rander Flags` (either via scripting API or with editor). ```csharp var outlineSettings = GetComponent(); @@ -141,6 +147,13 @@ outlineSettings.OutlineWidth = 2; outlineSettings.OutlineRenderMode = OutlineRenderFlags.Blurred | OutlineRenderFlags.EnableDepthTesting; ``` +### Ignore layers +When adding a `GameObject` to outline collection it is often desirable to ignore child renderers in specific layers (for instance, `TransparentFX`). This can be achieved by settings the `IgnoreLayers` mask in outline settings (or through corresponding API). +```csharp +var outlineSettings = GetComponent(); +outlineSettings.IgnoreLayerMask = LayerMask.GetMask("TransparentFX", "UI"); +``` + ### Extensibility There are a number of helper classes that can be used for writing highly customized outline implementations (if neither `OutlineBehaviour` nor `OutlineEffect` does not suit your needs). All outline implementations use following helpers: @@ -162,51 +175,33 @@ settings.OutlineWidth = 12; // Get outline assets instance. In real app this usually comes from MonoBehaviour's serialized fields. var resources = GetMyResources(); -using (var renderer = new OutlineRenderer(commandBuffer, BuiltinRenderTextureType.CameraTarget)) +using (var renderer = new OutlineRenderer(commandBuffer, resources)) { - renderer.Render(renderers, resources, settings); + renderer.Render(renderers, settings, myCamera.actualRenderingPath); } myCamera.AddCommandBuffer(OutlineRenderer.RenderEvent, commandBuffer); ``` -### Integration with Unity post-processing. +## Integration with Unity post-processing v2. [![NPM](https://nodei.co/npm/com.unityfx.outline.postprocessing.png)](https://www.npmjs.com/package/com.unityfx.outline.postprocessing) -The outline effect can easily be added to [Post-processing Stack v2](https://github.com/Unity-Technologies/PostProcessing/tree/v2). A minimal integration example is shown below: -```csharp -using System; -using UnityEngine; -using UnityEngine.Rendering.PostProcessing; -using UnityFx.Outline; +Install the package, add `Outline` effect to `PostProcessProfile`'s overrides list. Configure the effect parameters, make sure outline resources and layer collection are set: -[Serializable] -[PostProcess(typeof(OutlineEffectRenderer), PostProcessEvent.BeforeStack, "MyOutline", false)] -public sealed class Outline : PostProcessEffectSettings -{ - public OutlineResources OutlineResources; - public OutlineLayers OutlineLayers; -} +![Post processing outlinesettings](Docs/PpOutlineSettings.png "Post processing outlinesettings") -public sealed class OutlineEffectRenderer : PostProcessEffectRenderer -{ - public override void Render(PostProcessRenderContext context) - { - using (var renderer = new OutlineRenderer(context.command, context.source, context.destination)) - { - settings.OutlineLayers.Render(renderer, settings.OutlineResources); - } - } -} -``` -For the sake of simplicity the sample does not include any kind of error checking and no editor integration provided. In real world app the `Outline` class should expose its data to Unity editor either via custom inspector or using parameter overrides. Also, there are quite a few optimizations missing (for example, resusing `RuntimeUtilities.fullscreenTriangle` value as `OutlineResources.FullscreenTriangleMesh`). +Assign the configured `PostProcessProfile` to `PostProcessVolume` and that's it! -More info on writing custom post processing effects can be found [here](https://docs.unity3d.com/Packages/com.unity.postprocessing@2.2/manual/Writing-Custom-Effects.html). +More info on writing custom post processing effects can be found [here](https://docs.unity3d.com/Packages/com.unity.postprocessing@2.3/manual/Writing-Custom-Effects.html). -### Integration with Universal Render Pipeline (URP). +## Integration with Universal Render Pipeline (URP). [![NPM](https://nodei.co/npm/com.unityfx.outline.urp.png)](https://www.npmjs.com/package/com.unityfx.outline.urp) -TODO +Install the package, add `OutlineFeature` to `ScriptableRendererData`'s list of features. Configure the feature parameters (make sure outline resources and layer collection are set): + +![URP outline settings](Docs/UrpOutlineSettings.png "URP outline settings") + +Enable depth texture rendering in `UniversalRenderPipelineAsset` and that's it! ### Integration with High Definition Render Pipeline (HDRP). [![NPM](https://nodei.co/npm/com.unityfx.outline.hdrp.png)](https://www.npmjs.com/package/com.unityfx.outline.hdrp)