├── .gitattributes ├── EdgeDetect-PostProcessingUnity ├── Resources │ ├── EdgeDetectNormalsPostProcess.shader.meta │ └── EdgeDetectNormalsPostProcess.shader ├── Editor.meta ├── Resources.meta ├── Editor │ ├── EdgeDetect_BeforeStack_Editor.cs.meta │ ├── EdgeDetect_AfterStack_Editor.cs.meta │ ├── EdgeDetectPostProcessing_Editor.cs.meta │ ├── EdgeDetect_BeforeTransparent_Editor.cs.meta │ ├── EdgeDetect_AfterStack_Editor.cs │ ├── EdgeDetect_BeforeStack_Editor.cs │ ├── EdgeDetect_BeforeTransparent_Editor.cs │ └── EdgeDetectPostProcessing_Editor.cs ├── EdgeDetect_AfterStack.cs.meta ├── EdgeDetectPostProcessing.cs.meta ├── EdgeDetect_BeforeStack.cs.meta ├── EdgeDetect_BeforeTransparent.cs.meta ├── EdgeDetect_AfterStack.cs ├── EdgeDetect_BeforeStack.cs ├── EdgeDetect_BeforeTransparent.cs └── EdgeDetectPostProcessing.cs └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto -------------------------------------------------------------------------------- /EdgeDetect-PostProcessingUnity/Resources/EdgeDetectNormalsPostProcess.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3e5635ce4055e6c4b93d391e2ca4a7ec 3 | ShaderImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /EdgeDetect-PostProcessingUnity/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ac19f53d83ca8234296964e36309e3fc 3 | folderAsset: yes 4 | timeCreated: 1506513993 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /EdgeDetect-PostProcessingUnity/Resources.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 20e84f09f19d61f41adde35b69099bb7 3 | folderAsset: yes 4 | timeCreated: 1513170971 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /EdgeDetect-PostProcessingUnity/Editor/EdgeDetect_BeforeStack_Editor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3e6076e6bf3aa294084303a709c45e68 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /EdgeDetect-PostProcessingUnity/EdgeDetect_AfterStack.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 79c756fe45ae37747864bbe1e991ae38 3 | timeCreated: 1506497287 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /EdgeDetect-PostProcessingUnity/EdgeDetectPostProcessing.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9d855211644836f4782ecd611ffbc36f 3 | timeCreated: 1506497287 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /EdgeDetect-PostProcessingUnity/EdgeDetect_BeforeStack.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2d5989756ea37ac46b1c199fb99ffc33 3 | timeCreated: 1506497287 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /EdgeDetect-PostProcessingUnity/EdgeDetect_BeforeTransparent.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9e1905ad603bb9a479914accad762e92 3 | timeCreated: 1506497287 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /EdgeDetect-PostProcessingUnity/Editor/EdgeDetect_AfterStack_Editor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1e08f6e8b932fcd49b5e6eb11d433eac 3 | timeCreated: 1506497287 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /EdgeDetect-PostProcessingUnity/Editor/EdgeDetectPostProcessing_Editor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0a990cb83f3b22840995e112ed30b0cd 3 | timeCreated: 1506497287 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /EdgeDetect-PostProcessingUnity/Editor/EdgeDetect_BeforeTransparent_Editor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0248e34e0651ec84c8a0a3c492c9997a 3 | timeCreated: 1506497287 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /EdgeDetect-PostProcessingUnity/Editor/EdgeDetect_AfterStack_Editor.cs: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------------------------------------------------------------------- 2 | // Port of the Legacy Unity "Edge Detect" image effect to Post Processing Stack v2 3 | // Jean Moreno, 2017-2018 4 | // Legacy Image Effect: https://docs.unity3d.com/550/Documentation/Manual/script-EdgeDetectEffectNormals.html 5 | // Post Processing Stack v2: https://github.com/Unity-Technologies/PostProcessing/tree/v2 6 | //-------------------------------------------------------------------------------------------------------------------------------- 7 | 8 | using UnityEditor.Rendering.PostProcessing; 9 | 10 | [PostProcessEditor(typeof(EdgeDetect_AfterStack))] 11 | public sealed class EdgeDetect_AfterStack_Editor : EdgeDetectPostProcessing_Editor { } 12 | -------------------------------------------------------------------------------- /EdgeDetect-PostProcessingUnity/Editor/EdgeDetect_BeforeStack_Editor.cs: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------------------------------------------------------------------- 2 | // Port of the Legacy Unity "Edge Detect" image effect to Post Processing Stack v2 3 | // Jean Moreno, 2017-2018 4 | // Legacy Image Effect: https://docs.unity3d.com/550/Documentation/Manual/script-EdgeDetectEffectNormals.html 5 | // Post Processing Stack v2: https://github.com/Unity-Technologies/PostProcessing/tree/v2 6 | //-------------------------------------------------------------------------------------------------------------------------------- 7 | 8 | using UnityEditor.Rendering.PostProcessing; 9 | 10 | [PostProcessEditor(typeof(EdgeDetect_BeforeStack))] 11 | public sealed class EdgeDetect_BeforeStack_Editor : EdgeDetectPostProcessing_Editor { } 12 | -------------------------------------------------------------------------------- /EdgeDetect-PostProcessingUnity/Editor/EdgeDetect_BeforeTransparent_Editor.cs: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------------------------------------------------------------------- 2 | // Port of the Legacy Unity "Edge Detect" image effect to Post Processing Stack v2 3 | // Jean Moreno, 2017-2018 4 | // Legacy Image Effect: https://docs.unity3d.com/550/Documentation/Manual/script-EdgeDetectEffectNormals.html 5 | // Post Processing Stack v2: https://github.com/Unity-Technologies/PostProcessing/tree/v2 6 | //-------------------------------------------------------------------------------------------------------------------------------- 7 | 8 | using UnityEditor.Rendering.PostProcessing; 9 | 10 | [PostProcessEditor(typeof(EdgeDetect_BeforeTransparent))] 11 | public sealed class EdgeDetect_BeforeTransparent_Editor : EdgeDetectPostProcessing_Editor { } 12 | -------------------------------------------------------------------------------- /EdgeDetect-PostProcessingUnity/EdgeDetect_AfterStack.cs: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------------------------------------------------------------------- 2 | // Port of the Legacy Unity "Edge Detect" image effect to Post Processing Stack v2 3 | // Jean Moreno, 2017-2018 4 | // Legacy Image Effect: https://docs.unity3d.com/550/Documentation/Manual/script-EdgeDetectEffectNormals.html 5 | // Post Processing Stack v2: https://github.com/Unity-Technologies/PostProcessing/tree/v2 6 | //-------------------------------------------------------------------------------------------------------------------------------- 7 | 8 | using UnityEngine.Rendering.PostProcessing; 9 | 10 | //-------------------------------------------------------------------------------------------------------------------------------- 11 | 12 | [System.Serializable] 13 | [PostProcess(typeof(EdgeDetectPostProcessingRenderer_AfterStack), PostProcessEvent.AfterStack, "Unity Legacy/Edge Detection (After Stack)")] 14 | public sealed class EdgeDetect_AfterStack : EdgeDetectPostProcessing { } 15 | 16 | //-------------------------------------------------------------------------------------------------------------------------------- 17 | 18 | public sealed class EdgeDetectPostProcessingRenderer_AfterStack : EdgeDetectPostProcessingRenderer { } 19 | -------------------------------------------------------------------------------- /EdgeDetect-PostProcessingUnity/EdgeDetect_BeforeStack.cs: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------------------------------------------------------------------- 2 | // Port of the Legacy Unity "Edge Detect" image effect to Post Processing Stack v2 3 | // Jean Moreno, 2017-2018 4 | // Legacy Image Effect: https://docs.unity3d.com/550/Documentation/Manual/script-EdgeDetectEffectNormals.html 5 | // Post Processing Stack v2: https://github.com/Unity-Technologies/PostProcessing/tree/v2 6 | //-------------------------------------------------------------------------------------------------------------------------------- 7 | 8 | using UnityEngine.Rendering.PostProcessing; 9 | 10 | //-------------------------------------------------------------------------------------------------------------------------------- 11 | 12 | [System.Serializable] 13 | [PostProcess(typeof(EdgeDetectPostProcessingRenderer_BeforeStack), PostProcessEvent.BeforeStack, "Unity Legacy/Edge Detection (Before Stack)")] 14 | public sealed class EdgeDetect_BeforeStack : EdgeDetectPostProcessing { } 15 | 16 | //-------------------------------------------------------------------------------------------------------------------------------- 17 | 18 | public sealed class EdgeDetectPostProcessingRenderer_BeforeStack : EdgeDetectPostProcessingRenderer { } 19 | -------------------------------------------------------------------------------- /EdgeDetect-PostProcessingUnity/EdgeDetect_BeforeTransparent.cs: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------------------------------------------------------------------- 2 | // Port of the Legacy Unity "Edge Detect" image effect to Post Processing Stack v2 3 | // Jean Moreno, 2017-2018 4 | // Legacy Image Effect: https://docs.unity3d.com/550/Documentation/Manual/script-EdgeDetectEffectNormals.html 5 | // Post Processing Stack v2: https://github.com/Unity-Technologies/PostProcessing/tree/v2 6 | //-------------------------------------------------------------------------------------------------------------------------------- 7 | 8 | using UnityEngine.Rendering.PostProcessing; 9 | 10 | //-------------------------------------------------------------------------------------------------------------------------------- 11 | 12 | [System.Serializable] 13 | [PostProcess(typeof(EdgeDetectPostProcessingRenderer_BeforeTransparent), PostProcessEvent.BeforeTransparent, "Unity Legacy/Edge Detection (Before Transparent)")] 14 | public sealed class EdgeDetect_BeforeTransparent : EdgeDetectPostProcessing { } 15 | 16 | //-------------------------------------------------------------------------------------------------------------------------------- 17 | 18 | public sealed class EdgeDetectPostProcessingRenderer_BeforeTransparent : EdgeDetectPostProcessingRenderer { } 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EdgeDetect-PostProcessingUnity 2 | 3 | Port of the legacy Unity "Edge Detect Normals" image effect to Post Processing Stack **v2** 4 | 5 | - [Edge Detect Effect Normals - Unity Documentation](https://docs.unity3d.com/550/Documentation/Manual/script-EdgeDetectEffectNormals.html) 6 | - [Post Processing Stack v2 - Unity Technologies GitHub](https://github.com/Unity-Technologies/PostProcessing/tree/v2) 7 | 8 | ![Screenshot](https://i.imgur.com/8SH535F.gif) 9 | 10 | ## Installation 11 | 12 | Place the `EdgeDetect-PostProcessingUnity` folder anywhere in your project, and make sure that [Post Processing Stack v2](https://github.com/Unity-Technologies/PostProcessing/tree/v2) is in the project as well. 13 | 14 | ## Usage 15 | 16 | The new effect should be available for a post processing profile with different injection points: 17 | 18 | - `Add effect... > Unity Legacy > Edge Detection (Before Transparent)` 19 | Will render the Edge Detect effect before transparent objects are rendered, recommended for Legacy renderer (doesn't work with Scriptable Render Pipelines at time of writing - september 2018) 20 | - `Add effect... > Unity Legacy > Edge Detection (Before Stack)` 21 | Will render the Edge Detect effect before the built-in Post Processing Stack effects, recommended for Scriptable Render Pipelines 22 | - `Add effect... > Unity Legacy > Edge Detection (After Stack)` 23 | Will render the Edge Detect effect after the built-in Post Processing Stack effects, if you want the edges to appear on top of everything -------------------------------------------------------------------------------- /EdgeDetect-PostProcessingUnity/EdgeDetectPostProcessing.cs: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------------------------------------------------------------------- 2 | // Port of the Legacy Unity "Edge Detect" image effect to Post Processing Stack v2 3 | // Jean Moreno, 2017-2018 4 | // Legacy Image Effect: https://docs.unity3d.com/550/Documentation/Manual/script-EdgeDetectEffectNormals.html 5 | // Post Processing Stack v2: https://github.com/Unity-Technologies/PostProcessing/tree/v2 6 | //-------------------------------------------------------------------------------------------------------------------------------- 7 | 8 | using System; 9 | using UnityEngine; 10 | using UnityEngine.Rendering.PostProcessing; 11 | using EdgeDetectMode = EdgeDetectPostProcessing.EdgeDetectMode; 12 | 13 | //-------------------------------------------------------------------------------------------------------------------------------- 14 | 15 | public class EdgeDetectPostProcessing : PostProcessEffectSettings 16 | { 17 | public enum EdgeDetectMode 18 | { 19 | TriangleDepthNormals = 0, 20 | RobertsCrossDepthNormals = 1, 21 | SobelDepth = 2, 22 | SobelDepthThin = 3, 23 | TriangleLuminance = 4, 24 | } 25 | 26 | [Serializable] 27 | public sealed class EdgeDetectModeParameter : ParameterOverride 28 | { 29 | public override void Interp(EdgeDetectMode from, EdgeDetectMode to, float t) 30 | { 31 | base.Interp(from, to, t); 32 | } 33 | } 34 | 35 | public EdgeDetectModeParameter mode = new EdgeDetectModeParameter() { value = EdgeDetectMode.SobelDepthThin }; 36 | public FloatParameter sensitivityDepth = new FloatParameter() { value = 1.0f }; 37 | public FloatParameter sensitivityNormals = new FloatParameter() { value = 1.0f }; 38 | public FloatParameter lumThreshold = new FloatParameter() { value = 0.2f }; 39 | public FloatParameter edgeExp = new FloatParameter() { value = 1.0f }; 40 | public FloatParameter sampleDist = new FloatParameter() { value = 1.0f }; 41 | [Range(0f,1f)] 42 | public FloatParameter edgesOnly = new FloatParameter() { value = 0.0f }; 43 | public ColorParameter edgesOnlyBgColor = new ColorParameter() { value = Color.white }; 44 | } 45 | 46 | //-------------------------------------------------------------------------------------------------------------------------------- 47 | 48 | public class EdgeDetectPostProcessingRenderer : PostProcessEffectRenderer where T : EdgeDetectPostProcessing 49 | { 50 | 51 | public override void Render(PostProcessRenderContext context) 52 | { 53 | if (settings == null) 54 | return; 55 | 56 | var sheet = context.propertySheets.Get(Shader.Find("Hidden/EdgeDetect-PostProcess")); 57 | 58 | Vector2 sensitivity = new Vector2(settings.sensitivityDepth, settings.sensitivityNormals); 59 | sheet.properties.SetVector("_Sensitivity", new Vector4(sensitivity.x, sensitivity.y, 1.0f, sensitivity.y)); 60 | sheet.properties.SetFloat("_BgFade", settings.edgesOnly); 61 | sheet.properties.SetFloat("_SampleDistance", settings.sampleDist); 62 | sheet.properties.SetVector("_BgColor", settings.edgesOnlyBgColor.value); 63 | sheet.properties.SetFloat("_Exponent", settings.edgeExp); 64 | sheet.properties.SetFloat("_Threshold", settings.lumThreshold); 65 | 66 | context.command.BlitFullscreenTriangle(context.source, context.destination, sheet, (int)settings.mode.value); 67 | } 68 | 69 | public override DepthTextureMode GetCameraFlags() 70 | { 71 | if (settings == null) 72 | return DepthTextureMode.None; 73 | 74 | if (settings.mode == EdgeDetectMode.SobelDepth || settings.mode == EdgeDetectMode.SobelDepthThin) 75 | return DepthTextureMode.Depth; 76 | else if (settings.mode == EdgeDetectMode.TriangleDepthNormals || settings.mode == EdgeDetectMode.RobertsCrossDepthNormals) 77 | return DepthTextureMode.DepthNormals; 78 | 79 | return base.GetCameraFlags(); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /EdgeDetect-PostProcessingUnity/Editor/EdgeDetectPostProcessing_Editor.cs: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------------------------------------------------------------------- 2 | // Port of the Legacy Unity "Edge Detect" image effect to Post Processing Stack v2 3 | // Jean Moreno, 2017-2018 4 | // Legacy Image Effect: https://docs.unity3d.com/550/Documentation/Manual/script-EdgeDetectEffectNormals.html 5 | // Post Processing Stack v2: https://github.com/Unity-Technologies/PostProcessing/tree/v2 6 | //-------------------------------------------------------------------------------------------------------------------------------- 7 | 8 | using UnityEngine; 9 | using UnityEditor; 10 | using UnityEditor.Rendering.PostProcessing; 11 | using UnityEngine.Rendering.PostProcessing; 12 | 13 | public class EdgeDetectPostProcessing_Editor : PostProcessEffectEditor where T : EdgeDetectPostProcessing 14 | { 15 | SerializedParameterOverride mode; 16 | SerializedParameterOverride sensitivityDepth; 17 | SerializedParameterOverride sensitivityNormals; 18 | SerializedParameterOverride lumThreshold; 19 | SerializedParameterOverride edgeExp; 20 | SerializedParameterOverride sampleDist; 21 | SerializedParameterOverride edgesOnly; 22 | SerializedParameterOverride edgesOnlyBgColor; 23 | 24 | GUIContent gc_mode = new GUIContent("Mode"); 25 | GUIContent gc_sensitivityDepth = new GUIContent(" Depth Sensitivity"); 26 | GUIContent gc_sensitivityNormals = new GUIContent(" Normals Sensitivity"); 27 | GUIContent gc_lumThreshold = new GUIContent(" Luminance Threshold"); 28 | GUIContent gc_edgeExp = new GUIContent(" Edge Exponent"); 29 | GUIContent gc_sampleDist = new GUIContent(" Sample Distance"); 30 | GUIContent gc_edgesOnly = new GUIContent(" Edges Only"); 31 | GUIContent gc_edgesOnlyBgColor = new GUIContent(" Color"); 32 | 33 | string gc_description = "Detects spatial differences and converts into black outlines\n\nLegacy image effect from previous Unity versions ported to Post Processing v2"; 34 | GUIContent gc_background = new GUIContent("Background Options"); 35 | 36 | public override void OnEnable() 37 | { 38 | mode = FindParameterOverride(x => x.mode); 39 | sensitivityDepth = FindParameterOverride(x => x.sensitivityDepth); 40 | sensitivityNormals = FindParameterOverride(x => x.sensitivityNormals); 41 | lumThreshold = FindParameterOverride(x => x.lumThreshold); 42 | edgeExp = FindParameterOverride(x => x.edgeExp); 43 | sampleDist = FindParameterOverride(x => x.sampleDist); 44 | edgesOnly = FindParameterOverride(x => x.edgesOnly); 45 | edgesOnlyBgColor = FindParameterOverride(x => x.edgesOnlyBgColor); 46 | } 47 | 48 | public override void OnInspectorGUI() 49 | { 50 | EditorGUILayout.HelpBox(gc_description, MessageType.None); 51 | 52 | PropertyField(mode, gc_mode); 53 | 54 | EdgeDetectPostProcessing.EdgeDetectMode edgeDetectMode = (EdgeDetectPostProcessing.EdgeDetectMode)mode.value.enumValueIndex; 55 | 56 | if (RuntimeUtilities.scriptableRenderPipelineActive && 57 | (edgeDetectMode == EdgeDetectPostProcessing.EdgeDetectMode.RobertsCrossDepthNormals 58 | || edgeDetectMode == EdgeDetectPostProcessing.EdgeDetectMode.TriangleDepthNormals)) 59 | { 60 | EditorGUILayout.HelpBox("Edge Detection effects that rely on Camera Depth + Normals texture don't work with scriptable render pipelines.", MessageType.Warning); 61 | return; 62 | } 63 | 64 | PropertyField(sampleDist, gc_sampleDist); 65 | 66 | if (mode.value.enumValueIndex < 2) 67 | { 68 | PropertyField(sensitivityDepth, gc_sensitivityDepth); 69 | PropertyField(sensitivityNormals, gc_sensitivityNormals); 70 | } 71 | else if (mode.value.enumValueIndex < 4) 72 | { 73 | PropertyField(edgeExp, gc_edgeExp); 74 | } 75 | else 76 | { 77 | // lum based mode 78 | PropertyField(lumThreshold, gc_lumThreshold); 79 | } 80 | 81 | EditorGUILayout.Space(); 82 | 83 | GUILayout.Label(gc_background); 84 | PropertyField(edgesOnly, gc_edgesOnly); 85 | PropertyField(edgesOnlyBgColor, gc_edgesOnlyBgColor); 86 | } 87 | } -------------------------------------------------------------------------------- /EdgeDetect-PostProcessingUnity/Resources/EdgeDetectNormalsPostProcess.shader: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------------------------------------------------------------------- 2 | // Port of the Legacy Unity "Edge Detect" image effect to Post Processing Stack v2 3 | // Jean Moreno, September 2017 4 | // Legacy Image Effect: https://docs.unity3d.com/550/Documentation/Manual/script-EdgeDetectEffectNormals.html 5 | // Post Processing Stack v2: https://github.com/Unity-Technologies/PostProcessing/tree/v2 6 | //-------------------------------------------------------------------------------------------------------------------------------- 7 | Shader "Hidden/EdgeDetect-PostProcess" 8 | { 9 | HLSLINCLUDE 10 | 11 | #include "Packages/com.unity.postprocessing/PostProcessing/Shaders/StdLib.hlsl" 12 | 13 | //Functions and macros from UnityCG, because we can't include it here (causes duplicates from StdLib) 14 | //Copied from UnityCG.cginc v2017.1.0f3 15 | 16 | inline float DecodeFloatRG( float2 enc ) 17 | { 18 | float2 kDecodeDot = float2(1.0, 1/255.0); 19 | return dot( enc, kDecodeDot ); 20 | } 21 | 22 | #if !defined(SHADER_TARGET_GLSL) && !defined(SHADER_API_PSSL) && !defined(SHADER_API_GLES3) && !defined(SHADER_API_VULKAN) && !(defined(SHADER_API_METAL) && defined(UNITY_COMPILER_HLSLCC)) 23 | #define sampler2D_float sampler2D 24 | #endif 25 | 26 | #undef SAMPLE_DEPTH_TEXTURE 27 | #if defined(SHADER_API_PSP2) 28 | half4 SAMPLE_DEPTH_TEXTURE(sampler2D s, float4 uv) { return tex2D(s, (float3)uv); } 29 | half4 SAMPLE_DEPTH_TEXTURE(sampler2D s, float3 uv) { return tex2D(s, uv); } 30 | half4 SAMPLE_DEPTH_TEXTURE(sampler2D s, float2 uv) { return tex2D(s, uv); } 31 | #else 32 | #define SAMPLE_DEPTH_TEXTURE(sampler, uv) (tex2D(sampler, uv).r) 33 | #endif 34 | 35 | //-------------------------------------------------------------------------------------------------------------------------------- 36 | 37 | //Source image 38 | TEXTURE2D_SAMPLER2D(_MainTex, sampler_MainTex); 39 | float4 _MainTex_ST; 40 | float4 _MainTex_TexelSize; 41 | 42 | //Camera depth/normals 43 | sampler2D _CameraDepthNormalsTexture; 44 | half4 _CameraDepthNormalsTexture_ST; 45 | sampler2D_float _CameraDepthTexture; 46 | half4 _CameraDepthTexture_ST; 47 | 48 | //Settings 49 | half4 _Sensitivity; 50 | half4 _BgColor; 51 | half _BgFade; 52 | half _SampleDistance; 53 | float _Exponent; 54 | float _Threshold; 55 | 56 | //-------------------------------------------------------------------------------------------------------------------------------- 57 | 58 | struct Varyings 59 | { 60 | float4 vertex : SV_POSITION; 61 | float2 texcoord[5] : TEXCOORD0; 62 | float2 texcoordStereo : TEXCOORD5; 63 | }; 64 | 65 | struct VaryingsD 66 | { 67 | float4 vertex : SV_POSITION; 68 | float2 texcoord[2] : TEXCOORD0; 69 | float2 texcoordStereo : TEXCOORD2; 70 | }; 71 | 72 | struct VaryingsLum 73 | { 74 | float4 vertex : SV_POSITION; 75 | float2 texcoord[3] : TEXCOORD0; 76 | float2 texcoordStereo : TEXCOORD3; 77 | }; 78 | 79 | //-------------------------------------------------------------------------------------------------------------------------------- 80 | 81 | inline half CheckSame (half2 centerNormal, float centerDepth, half4 theSample) 82 | { 83 | // difference in normals 84 | // do not bother decoding normals - there's no need here 85 | half2 diff = abs(centerNormal - theSample.xy) * _Sensitivity.y; 86 | int isSameNormal = (diff.x + diff.y) * _Sensitivity.y < 0.1; 87 | // difference in depth 88 | float sampleDepth = DecodeFloatRG (theSample.zw); 89 | float zdiff = abs(centerDepth-sampleDepth); 90 | // scale the required threshold by the distance 91 | int isSameDepth = zdiff * _Sensitivity.x < 0.09 * centerDepth; 92 | 93 | // return: 94 | // 1 - if normals and depth are similar enough 95 | // 0 - otherwise 96 | return isSameNormal * isSameDepth ? 1.0 : 0.0; 97 | } 98 | 99 | //-------------------------------------------------------------------------------------------------------------------------------- 100 | 101 | Varyings VertRobert(AttributesDefault v) 102 | { 103 | Varyings o; 104 | 105 | o.vertex = float4(v.vertex.xy, 0.0, 1.0); 106 | float2 texcoord = TransformTriangleVertexToUV(v.vertex.xy); 107 | 108 | #if UNITY_UV_STARTS_AT_TOP 109 | texcoord = texcoord * float2(1.0, -1.0) + float2(0.0, 1.0); 110 | #endif 111 | 112 | o.texcoordStereo = TransformStereoScreenSpaceTex(texcoord, 1.0); 113 | o.texcoord[0] = UnityStereoScreenSpaceUVAdjust(texcoord, _MainTex_ST); 114 | 115 | o.texcoord[1] = UnityStereoScreenSpaceUVAdjust(texcoord + _MainTex_TexelSize.xy * half2(1,1) * _SampleDistance, _MainTex_ST); 116 | o.texcoord[2] = UnityStereoScreenSpaceUVAdjust(texcoord + _MainTex_TexelSize.xy * half2(-1,-1) * _SampleDistance, _MainTex_ST); 117 | o.texcoord[3] = UnityStereoScreenSpaceUVAdjust(texcoord + _MainTex_TexelSize.xy * half2(-1,1) * _SampleDistance, _MainTex_ST); 118 | o.texcoord[4] = UnityStereoScreenSpaceUVAdjust(texcoord + _MainTex_TexelSize.xy * half2(1,-1) * _SampleDistance, _MainTex_ST); 119 | 120 | return o; 121 | } 122 | 123 | float4 FragRobert(Varyings i) : SV_Target 124 | { 125 | half4 color = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord[0]); 126 | 127 | half4 sample1 = tex2D(_CameraDepthNormalsTexture, i.texcoord[1].xy); 128 | half4 sample2 = tex2D(_CameraDepthNormalsTexture, i.texcoord[2].xy); 129 | half4 sample3 = tex2D(_CameraDepthNormalsTexture, i.texcoord[3].xy); 130 | half4 sample4 = tex2D(_CameraDepthNormalsTexture, i.texcoord[4].xy); 131 | 132 | half edge = 1.0; 133 | edge *= CheckSame(sample1.xy, DecodeFloatRG(sample1.zw), sample2); 134 | edge *= CheckSame(sample3.xy, DecodeFloatRG(sample3.zw), sample4); 135 | 136 | return edge * lerp(color, _BgColor, _BgFade); 137 | } 138 | 139 | //-------------------------------------------------------------------------------------------------------------------------------- 140 | 141 | VaryingsLum VertThin(AttributesDefault v) 142 | { 143 | VaryingsLum o; 144 | 145 | o.vertex = float4(v.vertex.xy, 0.0, 1.0); 146 | float2 texcoord = TransformTriangleVertexToUV(v.vertex.xy); 147 | 148 | #if UNITY_UV_STARTS_AT_TOP 149 | texcoord = texcoord * float2(1.0, -1.0) + float2(0.0, 1.0); 150 | #endif 151 | 152 | o.texcoordStereo = TransformStereoScreenSpaceTex(texcoord, 1.0); 153 | o.texcoord[0] = UnityStereoScreenSpaceUVAdjust(texcoord, _MainTex_ST); 154 | 155 | // offsets for two additional samples 156 | o.texcoord[1] = UnityStereoScreenSpaceUVAdjust(texcoord + float2(-_MainTex_TexelSize.x, -_MainTex_TexelSize.y) * _SampleDistance, _MainTex_ST); 157 | o.texcoord[2] = UnityStereoScreenSpaceUVAdjust(texcoord + float2(+_MainTex_TexelSize.x, -_MainTex_TexelSize.y) * _SampleDistance, _MainTex_ST); 158 | 159 | return o; 160 | } 161 | 162 | float4 FragThin(VaryingsLum i) : SV_Target 163 | { 164 | half4 color = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord[0]); 165 | 166 | half4 center = tex2D(_CameraDepthNormalsTexture, i.texcoord[0]); 167 | half4 sample1 = tex2D(_CameraDepthNormalsTexture, i.texcoord[1]); 168 | half4 sample2 = tex2D(_CameraDepthNormalsTexture, i.texcoord[2]); 169 | 170 | // encoded normal 171 | half2 centerNormal = center.xy; 172 | // decoded depth 173 | float centerDepth = DecodeFloatRG(center.zw); 174 | 175 | half edge = 1.0; 176 | edge *= CheckSame(centerNormal, centerDepth, sample1); 177 | edge *= CheckSame(centerNormal, centerDepth, sample2); 178 | 179 | return edge * lerp(color, _BgColor, _BgFade); 180 | } 181 | 182 | //-------------------------------------------------------------------------------------------------------------------------------- 183 | 184 | VaryingsD VertD(AttributesDefault v) 185 | { 186 | VaryingsD o; 187 | 188 | o.vertex = float4(v.vertex.xy, 0.0, 1.0); 189 | float2 texcoord = TransformTriangleVertexToUV(v.vertex.xy); 190 | 191 | #if UNITY_UV_STARTS_AT_TOP 192 | texcoord = texcoord * float2(1.0, -1.0) + float2(0.0, 1.0); 193 | #endif 194 | 195 | o.texcoordStereo = TransformStereoScreenSpaceTex(texcoord, 1.0); 196 | o.texcoord[0] = UnityStereoScreenSpaceUVAdjust(texcoord, _MainTex_ST); 197 | o.texcoord[1] = texcoord; 198 | 199 | return o; 200 | } 201 | 202 | float4 FragD(VaryingsD i) : SV_Target 203 | { 204 | half4 color = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord[0]); 205 | 206 | // inspired by borderlands implementation of popular "sobel filter" 207 | 208 | #if defined(FRAGD_CHEAP) 209 | float centerDepth = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.texcoord[1])); 210 | #else 211 | float centerDepth = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, UnityStereoScreenSpaceUVAdjust(i.texcoord[1], _CameraDepthTexture_ST))); 212 | #endif 213 | 214 | float4 depthsDiag; 215 | float4 depthsAxis; 216 | 217 | float2 uvDist = _SampleDistance * _MainTex_TexelSize.xy; 218 | 219 | depthsDiag.x = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, UnityStereoScreenSpaceUVAdjust(i.texcoord[1]+uvDist, _CameraDepthTexture_ST))); // TR 220 | depthsDiag.y = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, UnityStereoScreenSpaceUVAdjust(i.texcoord[1]+uvDist*float2(-1,1), _CameraDepthTexture_ST))); // TL 221 | depthsDiag.z = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, UnityStereoScreenSpaceUVAdjust(i.texcoord[1]-uvDist*float2(-1,1), _CameraDepthTexture_ST))); // BR 222 | depthsDiag.w = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, UnityStereoScreenSpaceUVAdjust(i.texcoord[1]-uvDist, _CameraDepthTexture_ST))); // BL 223 | 224 | depthsAxis.x = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, UnityStereoScreenSpaceUVAdjust(i.texcoord[1]+uvDist*float2(0,1), _CameraDepthTexture_ST))); // T 225 | depthsAxis.y = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, UnityStereoScreenSpaceUVAdjust(i.texcoord[1]-uvDist*float2(1,0), _CameraDepthTexture_ST))); // L 226 | depthsAxis.z = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, UnityStereoScreenSpaceUVAdjust(i.texcoord[1]+uvDist*float2(1,0), _CameraDepthTexture_ST))); // R 227 | depthsAxis.w = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, UnityStereoScreenSpaceUVAdjust(i.texcoord[1]-uvDist*float2(0,1), _CameraDepthTexture_ST))); // B 228 | 229 | #if !defined(FRAGD_CHEAP) 230 | // make it work nicely with depth based image effects such as depth of field: 231 | depthsDiag = (depthsDiag > centerDepth.xxxx) ? depthsDiag : centerDepth.xxxx; 232 | depthsAxis = (depthsAxis > centerDepth.xxxx) ? depthsAxis : centerDepth.xxxx; 233 | #endif 234 | 235 | depthsDiag -= centerDepth; 236 | depthsAxis /= centerDepth; 237 | 238 | const float4 HorizDiagCoeff = float4(1,1,-1,-1); 239 | const float4 VertDiagCoeff = float4(-1,1,-1,1); 240 | const float4 HorizAxisCoeff = float4(1,0,0,-1); 241 | const float4 VertAxisCoeff = float4(0,1,-1,0); 242 | 243 | float4 SobelH = depthsDiag * HorizDiagCoeff + depthsAxis * HorizAxisCoeff; 244 | float4 SobelV = depthsDiag * VertDiagCoeff + depthsAxis * VertAxisCoeff; 245 | 246 | float SobelX = dot(SobelH, float4(1,1,1,1)); 247 | float SobelY = dot(SobelV, float4(1,1,1,1)); 248 | float Sobel = sqrt(SobelX * SobelX + SobelY * SobelY); 249 | 250 | Sobel = 1.0-pow(saturate(Sobel), _Exponent); 251 | return Sobel * lerp(color, _BgColor, _BgFade); 252 | } 253 | 254 | //-------------------------------------------------------------------------------------------------------------------------------- 255 | 256 | VaryingsLum VertLum(AttributesDefault v) 257 | { 258 | VaryingsLum o; 259 | 260 | o.vertex = float4(v.vertex.xy, 0.0, 1.0); 261 | float2 texcoord = TransformTriangleVertexToUV(v.vertex.xy); 262 | 263 | #if UNITY_UV_STARTS_AT_TOP 264 | texcoord = texcoord * float2(1.0, -1.0) + float2(0.0, 1.0); 265 | #endif 266 | 267 | o.texcoordStereo = TransformStereoScreenSpaceTex(texcoord, 1.0); 268 | 269 | o.texcoord[0] = UnityStereoScreenSpaceUVAdjust(texcoord, _MainTex_ST); 270 | o.texcoord[1] = UnityStereoScreenSpaceUVAdjust(texcoord + float2(-_MainTex_TexelSize.x, -_MainTex_TexelSize.y) * _SampleDistance, _MainTex_ST); 271 | o.texcoord[2] = UnityStereoScreenSpaceUVAdjust(texcoord + float2(+_MainTex_TexelSize.x, -_MainTex_TexelSize.y) * _SampleDistance, _MainTex_ST); 272 | 273 | return o; 274 | } 275 | 276 | float4 FragLum(VaryingsLum i) : SV_Target 277 | { 278 | half4 color = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord[0]); 279 | 280 | // a very simple cross gradient filter 281 | half3 p1 = color.rgb; 282 | half3 p2 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord[1]).rgb; 283 | half3 p3 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord[2]).rgb; 284 | 285 | half3 diff = p1 * 2 - p2 - p3; 286 | half len = dot(diff, diff); 287 | len = step(len, _Threshold); 288 | //if(len >= _Threshold) 289 | // color.rgb = 0; 290 | 291 | return len * lerp(color, _BgColor, _BgFade); 292 | } 293 | 294 | ENDHLSL 295 | 296 | //-------------------------------------------------------------------------------------------------------------------------------- 297 | 298 | Subshader 299 | { 300 | Cull Off 301 | ZWrite Off 302 | ZTest Always 303 | 304 | Pass 305 | { 306 | HLSLPROGRAM 307 | #pragma vertex VertThin 308 | #pragma fragment FragThin 309 | ENDHLSL 310 | } 311 | 312 | Pass 313 | { 314 | HLSLPROGRAM 315 | #pragma vertex VertRobert 316 | #pragma fragment FragRobert 317 | ENDHLSL 318 | } 319 | 320 | Pass 321 | { 322 | HLSLPROGRAM 323 | #pragma multi_compile FRAGD_CHEAP 324 | #pragma vertex VertD 325 | #pragma fragment FragD 326 | ENDHLSL 327 | } 328 | 329 | Pass 330 | { 331 | HLSLPROGRAM 332 | #pragma vertex VertD 333 | #pragma fragment FragD 334 | ENDHLSL 335 | } 336 | 337 | Pass 338 | { 339 | HLSLPROGRAM 340 | #pragma vertex VertLum 341 | #pragma fragment FragLum 342 | ENDHLSL 343 | } 344 | } 345 | 346 | Fallback off 347 | } --------------------------------------------------------------------------------