Advertisement
Guest User

Shader Outline

a guest
Apr 3rd, 2021
155
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 6.21 KB | None | 0 0
  1. Shader "Hidden/Roystan/Outline Post Process"
  2. {
  3.     SubShader
  4.     {
  5.         Cull Off ZWrite Off ZTest Always
  6.  
  7.         Pass
  8.         {
  9.             // Custom post processing effects are written in HLSL blocks,
  10.             // with lots of macros to aid with platform differences.
  11.             // https://github.com/Unity-Technologies/PostProcessing/wiki/Writing-Custom-Effects#shader
  12.             HLSLPROGRAM
  13.             #pragma vertex Vert
  14.             #pragma fragment Frag
  15.             #include "Packages/com.unity.postprocessing/PostProcessing/Shaders/StdLib.hlsl"
  16.  
  17.             TEXTURE2D_SAMPLER2D(_MainTex, sampler_MainTex);
  18.             // _CameraNormalsTexture contains the view space normals transformed
  19.             // to be in the 0...1 range.
  20.             TEXTURE2D_SAMPLER2D(_CameraNormalsTexture, sampler_CameraNormalsTexture);
  21.             TEXTURE2D_SAMPLER2D(_CameraDepthTexture, sampler_CameraDepthTexture);
  22.        
  23.             // Data pertaining to _MainTex's dimensions.
  24.             // https://docs.unity3d.com/Manual/SL-PropertiesInPrograms.html
  25.             float4 _MainTex_TexelSize;
  26.  
  27.             float _Scale;
  28.             float4 _Color;
  29.  
  30.             float _DepthThreshold;
  31.             float _DepthNormalThreshold;
  32.             float _DepthNormalThresholdScale;
  33.  
  34.             float _NormalThreshold;
  35.  
  36.             // This matrix is populated in PostProcessOutline.cs.
  37.             float4x4 _ClipToView;
  38.  
  39.             // Combines the top and bottom colors using normal blending.
  40.             // https://en.wikipedia.org/wiki/Blend_modes#Normal_blend_mode
  41.             // This performs the same operation as Blend SrcAlpha OneMinusSrcAlpha.
  42.             float4 alphaBlend(float4 top, float4 bottom)
  43.             {
  44.                 float3 color = (top.rgb * top.a) + (bottom.rgb * (1 - top.a));
  45.                 float alpha = top.a + bottom.a * (1 - top.a);
  46.  
  47.                 return float4(color, alpha);
  48.             }
  49.  
  50.             // Both the Varyings struct and the Vert shader are copied
  51.             // from StdLib.hlsl included above, with some modifications.
  52.             struct Varyings
  53.             {
  54.                 float4 vertex : SV_POSITION;
  55.                 float2 texcoord : TEXCOORD0;
  56.                 float2 texcoordStereo : TEXCOORD1;
  57.                 float3 viewSpaceDir : TEXCOORD2;
  58.             #if STEREO_INSTANCING_ENABLED
  59.                 uint stereoTargetEyeIndex : SV_RenderTargetArrayIndex;
  60.             #endif
  61.             };
  62.  
  63.             Varyings Vert(AttributesDefault v)
  64.             {
  65.                 Varyings o;
  66.                 o.vertex = float4(v.vertex.xy, 0.0, 1.0);
  67.                 o.texcoord = TransformTriangleVertexToUV(v.vertex.xy);
  68.                 // Transform our point first from clip to view space,
  69.                 // taking the xyz to interpret it as a direction.
  70.                 o.viewSpaceDir = mul(_ClipToView, o.vertex).xyz;
  71.  
  72.             #if UNITY_UV_STARTS_AT_TOP
  73.                 o.texcoord = o.texcoord * float2(1.0, -1.0) + float2(0.0, 1.0);
  74.             #endif
  75.  
  76.                 o.texcoordStereo = TransformStereoScreenSpaceTex(o.texcoord, 1.0);
  77.  
  78.                 return o;
  79.             }
  80.  
  81.             float4 Frag(Varyings i) : SV_Target
  82.             {
  83.                 float halfScaleFloor = floor(_Scale * 0.5);
  84.                 float halfScaleCeil = ceil(_Scale * 0.5);
  85.  
  86.                 // Sample the pixels in an X shape, roughly centered around i.texcoord.
  87.                 // As the _CameraDepthTexture and _CameraNormalsTexture default samplers
  88.                 // use point filtering, we use the above variables to ensure we offset
  89.                 // exactly one pixel at a time.
  90.                 float2 bottomLeftUV = i.texcoord - float2(_MainTex_TexelSize.x, _MainTex_TexelSize.y) * halfScaleFloor;
  91.                 float2 topRightUV = i.texcoord + float2(_MainTex_TexelSize.x, _MainTex_TexelSize.y) * halfScaleCeil;  
  92.                 float2 bottomRightUV = i.texcoord + float2(_MainTex_TexelSize.x * halfScaleCeil, -_MainTex_TexelSize.y * halfScaleFloor);
  93.                 float2 topLeftUV = i.texcoord + float2(-_MainTex_TexelSize.x * halfScaleFloor, _MainTex_TexelSize.y * halfScaleCeil);
  94.  
  95.                 float3 normal0 = SAMPLE_TEXTURE2D(_CameraNormalsTexture, sampler_CameraNormalsTexture, bottomLeftUV).rgb;
  96.                 float3 normal1 = SAMPLE_TEXTURE2D(_CameraNormalsTexture, sampler_CameraNormalsTexture, topRightUV).rgb;
  97.                 float3 normal2 = SAMPLE_TEXTURE2D(_CameraNormalsTexture, sampler_CameraNormalsTexture, bottomRightUV).rgb;
  98.                 float3 normal3 = SAMPLE_TEXTURE2D(_CameraNormalsTexture, sampler_CameraNormalsTexture, topLeftUV).rgb;
  99.  
  100.                 float depth0 = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, sampler_CameraDepthTexture, bottomLeftUV).r;
  101.                 float depth1 = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, sampler_CameraDepthTexture, topRightUV).r;
  102.                 float depth2 = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, sampler_CameraDepthTexture, bottomRightUV).r;
  103.                 float depth3 = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, sampler_CameraDepthTexture, topLeftUV).r;
  104.  
  105.                 // Transform the view normal from the 0...1 range to the -1...1 range.
  106.                 float3 viewNormal = normal0 * 2 - 1;
  107.                 float NdotV = 1 - dot(viewNormal, -i.viewSpaceDir);
  108.  
  109.                 // Return a value in the 0...1 range depending on where NdotV lies
  110.                 // between _DepthNormalThreshold and 1.
  111.                 float normalThreshold01 = saturate((NdotV - _DepthNormalThreshold) / (1 - _DepthNormalThreshold));
  112.                 // Scale the threshold, and add 1 so that it is in the range of 1..._NormalThresholdScale + 1.
  113.                 float normalThreshold = normalThreshold01 * _DepthNormalThresholdScale + 1;
  114.  
  115.                 // Modulate the threshold by the existing depth value;
  116.                 // pixels further from the screen will require smaller differences
  117.                 // to draw an edge.
  118.                 float depthThreshold = _DepthThreshold * depth0 * normalThreshold;
  119.  
  120.                 float depthFiniteDifference0 = depth1 - depth0;
  121.                 float depthFiniteDifference1 = depth3 - depth2;
  122.                 // edgeDepth is calculated using the Roberts cross operator.
  123.                 // The same operation is applied to the normal below.
  124.                 // https://en.wikipedia.org/wiki/Roberts_cross
  125.                 float edgeDepth = sqrt(pow(depthFiniteDifference0, 2) + pow(depthFiniteDifference1, 2)) * 100;
  126.                 edgeDepth = edgeDepth > depthThreshold ? 1 : 0;
  127.  
  128.                 float3 normalFiniteDifference0 = normal1 - normal0;
  129.                 float3 normalFiniteDifference1 = normal3 - normal2;
  130.                 // Dot the finite differences with themselves to transform the
  131.                 // three-dimensional values to scalars.
  132.                 float edgeNormal = sqrt(dot(normalFiniteDifference0, normalFiniteDifference0) + dot(normalFiniteDifference1, normalFiniteDifference1));
  133.                 edgeNormal = edgeNormal > _NormalThreshold ? 1 : 0;
  134.  
  135.                 float edge = max(edgeDepth, edgeNormal);
  136.  
  137.                 float4 edgeColor = float4(_Color.rgb, _Color.a * edge);
  138.  
  139.                 float4 color = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord);
  140.  
  141.                 return alphaBlend(edgeColor, color);
  142.             }
  143.             ENDHLSL
  144.         }
  145.     }
  146. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement