204 lines
7.2 KiB
GLSL
204 lines
7.2 KiB
GLSL
Shader "Hidden/Ilumisoft/PostProcessing/Outline"
|
|
{
|
|
HLSLINCLUDE
|
|
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareNormalsTexture.hlsl"
|
|
|
|
float4 _OutlineColor;
|
|
float4 _BackgroundColor;
|
|
float _BackgroundColorOpacity;
|
|
float _ReferenceHeight;
|
|
int _OutlineThickness;
|
|
int _IsFadeEnabled;
|
|
float _FadeStart;
|
|
float _FadeEnd;
|
|
float2 _DepthEdge;
|
|
float2 _NormalEdge;
|
|
float _LuminancePower;
|
|
float _LuminanceContrast;
|
|
|
|
// Samples the scene normals remapped to [0,1]
|
|
inline float3 SampleNormal(float2 uv)
|
|
{
|
|
return SampleSceneNormals(uv) * 0.5 + 0.5;
|
|
}
|
|
|
|
// Samples the scene color
|
|
inline float3 SampleColor(float2 uv)
|
|
{
|
|
return SAMPLE_TEXTURE2D(_BlitTexture,sampler_LinearClamp, uv).rgb;
|
|
}
|
|
|
|
// Samples the scene depth linear01
|
|
inline float SampleDepthLinear01(float2 uv)
|
|
{
|
|
return Linear01Depth(SampleSceneDepth(uv),_ZBufferParams);
|
|
}
|
|
|
|
float GetNormalOutline(float3 topLeft, float3 bottomRight, float3 topRight, float3 bottomLeft)
|
|
{
|
|
float3 delta = abs(topLeft-bottomRight) + abs(topRight-bottomLeft);
|
|
|
|
float normalOutline = saturate(max(delta.r, max(delta.g, delta.b)));
|
|
|
|
return smoothstep(_NormalEdge.x, _NormalEdge.y, normalOutline);
|
|
}
|
|
|
|
float GetDepthOutline(float topLeft, float bottomRight, float topRight, float bottomLeft)
|
|
{
|
|
float result = abs(topLeft - bottomRight) + abs(topRight - bottomLeft);
|
|
|
|
result /= max(topLeft, max(bottomRight, max(topRight, bottomLeft)));
|
|
|
|
return smoothstep(_DepthEdge.x, _DepthEdge.y, saturate(result));
|
|
}
|
|
|
|
inline float InverseLerp(float a, float b, float t)
|
|
{
|
|
return saturate((t-a)/(b-a));
|
|
}
|
|
|
|
float LuminancePowerContrast(float3 color, float power, float contrast)
|
|
{
|
|
float luminance = pow(saturate(Luminance(color)), power);
|
|
float midpoint = pow(0.5, 2.2);
|
|
return saturate((luminance - midpoint) * contrast + midpoint);
|
|
}
|
|
|
|
float4 OutlineDepthOnly (Varyings input) : SV_Target
|
|
{
|
|
float2 offset = _OutlineThickness * _BlitTexture_TexelSize.xy*_ScreenParams.y/_ReferenceHeight;
|
|
float2 centerUV = input.texcoord;
|
|
|
|
// Sample color and depth of the current pixel
|
|
float3 centerColor = SampleColor(centerUV);
|
|
float centerDepth = SampleSceneDepth(centerUV);
|
|
float distance = LinearEyeDepth(centerDepth,_ZBufferParams);
|
|
centerDepth = Linear01Depth(centerDepth,_ZBufferParams);
|
|
|
|
float cornerDepths[4];
|
|
float2 cornerUVs[4];
|
|
|
|
// Create corner UVs
|
|
cornerUVs[0] = centerUV + float2(-offset.x, offset.y);
|
|
cornerUVs[1] = centerUV - float2(-offset.x, offset.y);
|
|
cornerUVs[2] = centerUV + offset;
|
|
cornerUVs[3] = centerUV - offset;
|
|
|
|
[unroll]
|
|
for(int i=0; i<4; i++)
|
|
{
|
|
// depth
|
|
cornerDepths[i] = SampleDepthLinear01(cornerUVs[i]);
|
|
|
|
// Discard values with a lower depth
|
|
cornerDepths[i] = (cornerDepths[i]>centerDepth) ? cornerDepths[i] : centerDepth;
|
|
}
|
|
|
|
// Compute outline
|
|
float outline = GetDepthOutline(cornerDepths[0], cornerDepths[1], cornerDepths[2], cornerDepths[3]);
|
|
|
|
// Apply distance fade
|
|
outline *= 1.0 - InverseLerp(_FadeStart, _FadeEnd, distance) * _IsFadeEnabled;
|
|
|
|
// Apply background color fill
|
|
float3 color = LuminancePowerContrast(centerColor, _LuminancePower, _LuminanceContrast) * _BackgroundColor.rgb;
|
|
color = lerp(centerColor, color, _BackgroundColorOpacity);
|
|
|
|
// Apply outline
|
|
color = lerp(color, _OutlineColor.rgb, outline*_OutlineColor.a);
|
|
|
|
return float4(color, 1.0);
|
|
}
|
|
|
|
float4 OutlineDepthNormal (Varyings input) : SV_Target
|
|
{
|
|
float2 offset = _OutlineThickness * _BlitTexture_TexelSize.xy*_ScreenParams.y/_ReferenceHeight;
|
|
float2 centerUV = input.texcoord;
|
|
|
|
// Sample color, depth and normal of the current pixel
|
|
float3 centerNormal = SampleNormal(centerUV);
|
|
float3 centerColor = SampleColor(centerUV);
|
|
float centerDepth = SampleSceneDepth(centerUV);
|
|
float distance = LinearEyeDepth(centerDepth,_ZBufferParams);
|
|
centerDepth = Linear01Depth(centerDepth,_ZBufferParams);
|
|
|
|
float3 cornerNormals[4];
|
|
float cornerDepths[4];
|
|
float2 cornerUVs[4];
|
|
|
|
// Create corner UVs
|
|
cornerUVs[0] = centerUV + float2(-offset.x, offset.y);
|
|
cornerUVs[1] = centerUV - float2(-offset.x, offset.y);
|
|
cornerUVs[2] = centerUV + offset;
|
|
cornerUVs[3] = centerUV - offset;
|
|
|
|
[unroll]
|
|
for(int i=0; i<4; i++)
|
|
{
|
|
// sample normal and depth
|
|
cornerNormals[i] = SampleNormal(cornerUVs[i]);
|
|
cornerDepths[i] = SampleDepthLinear01(cornerUVs[i]);
|
|
|
|
// Discard values with a lower depth
|
|
cornerNormals[i] = (cornerDepths[i]>centerDepth) ? cornerNormals[i] : centerNormal;
|
|
cornerDepths[i] = (cornerDepths[i]>centerDepth) ? cornerDepths[i] : centerDepth;
|
|
}
|
|
|
|
// Compute outline
|
|
float normalOutline = GetNormalOutline(cornerNormals[0], cornerNormals[1], cornerNormals[2], cornerNormals[3]);
|
|
|
|
float depthOutline = GetDepthOutline(cornerDepths[0], cornerDepths[1], cornerDepths[2], cornerDepths[3]);
|
|
|
|
float outline = max(normalOutline, depthOutline);
|
|
|
|
// Apply distance fade
|
|
outline *= 1.0 - InverseLerp(_FadeStart, _FadeEnd, distance) * _IsFadeEnabled;
|
|
|
|
// Apply background color fill
|
|
float3 color = LuminancePowerContrast(centerColor, _LuminancePower, _LuminanceContrast) * _BackgroundColor.rgb;
|
|
color = lerp(centerColor, color, _BackgroundColorOpacity);
|
|
|
|
// Apply outline
|
|
color = lerp(color, _OutlineColor.rgb, outline*_OutlineColor.a);
|
|
|
|
return float4(color, 1.0);
|
|
}
|
|
|
|
ENDHLSL
|
|
|
|
SubShader
|
|
{
|
|
Tags { "RenderType"="Opaque" "RenderPipeline" = "UniversalPipeline"}
|
|
LOD 100
|
|
ZWrite Off Cull Off
|
|
|
|
Pass
|
|
{
|
|
Name "OutlineDepthOnlyPass"
|
|
|
|
HLSLPROGRAM
|
|
|
|
#pragma vertex Vert
|
|
#pragma fragment OutlineDepthOnly
|
|
|
|
ENDHLSL
|
|
}
|
|
|
|
Pass
|
|
{
|
|
Name "OutlineDepthNormalPass"
|
|
|
|
HLSLPROGRAM
|
|
|
|
#pragma vertex Vert
|
|
#pragma fragment OutlineDepthNormal
|
|
|
|
ENDHLSL
|
|
}
|
|
}
|
|
}
|