205 lines
8.4 KiB
HLSL
205 lines
8.4 KiB
HLSL
#ifndef BEAUTIFY_PPSOUTLINE
|
|
#define BEAUTIFY_PPSOUTLINE
|
|
// Copyright 2016-2021 Ramiro Oliva (Kronnect) - All Rights Reserved.
|
|
|
|
#include "BeautifyCommon.hlsl"
|
|
|
|
TEXTURE2D_X(_MainTex);
|
|
float4 _MainTex_TexelSize;
|
|
float4 _MainTex_ST;
|
|
|
|
TEXTURE2D_X_FLOAT(_OutlineDepth);
|
|
TEXTURE2D_X_FLOAT(_OutlineObjectId);
|
|
|
|
float4 _Outline;
|
|
#define OUTLINE_EDGE_THRESHOLD _Outline.a
|
|
|
|
float4 _OutlineData;
|
|
#define OUTLINE_INTENSITY_MULTIPLIER _OutlineData.x
|
|
#define OUTLINE_DISTANCE_FADE _OutlineData.y
|
|
#define OUTLINE_MIN_DEPTH_THRESHOLD _OutlineData.z
|
|
#define OUTLINE_MIN_SATURATION_THRESHOLD _OutlineData.w
|
|
|
|
half _BlurScale;
|
|
#define OUTLINE_MIN_SEPARATION _OutlineData.z
|
|
|
|
struct VaryingsOutline {
|
|
float4 positionCS : SV_POSITION;
|
|
float2 uv: TEXCOORD0;
|
|
UNITY_VERTEX_OUTPUT_STEREO
|
|
};
|
|
|
|
struct VaryingsCross {
|
|
float4 positionCS : SV_POSITION;
|
|
float2 uv: TEXCOORD0;
|
|
BEAUTIFY_VERTEX_CROSS_UV_DATA
|
|
UNITY_VERTEX_OUTPUT_STEREO
|
|
};
|
|
|
|
|
|
VaryingsOutline VertOutline(AttributesSimple input) {
|
|
VaryingsOutline output;
|
|
UNITY_SETUP_INSTANCE_ID(input);
|
|
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
|
|
output.positionCS = input.positionOS;
|
|
output.positionCS.y *= _ProjectionParams.x * _FlipY;
|
|
output.uv = input.uv;
|
|
return output;
|
|
}
|
|
|
|
float OutlinePass(VaryingsOutline i) {
|
|
|
|
float3 uvInc = float3(_MainTex_TexelSize.x, _MainTex_TexelSize.y, 0);
|
|
|
|
#if BEAUTIFY_DEPTH_FADE || !BEAUTIFY_OUTLINE_SOBEL
|
|
#if BEAUTIFY_OUTLINE_CUSTOM_DEPTH || BEAUTIFY_OUTLINE_OBJECT_ID
|
|
float depth = BEAUTIFY_GET_CUSTOM_DEPTH_01(_OutlineDepth, i.uv);
|
|
float sceneDepth = BEAUTIFY_GET_SCENE_DEPTH_01(i.uv);
|
|
if (sceneDepth < depth * 0.999) return 0;
|
|
#else
|
|
float depth = BEAUTIFY_GET_SCENE_DEPTH_01(i.uv);
|
|
if (depth >= 1.0) return 0;
|
|
#endif
|
|
#endif
|
|
|
|
float outline = 0;
|
|
|
|
#if BEAUTIFY_OUTLINE_OBJECT_ID && !BEAUTIFY_OUTLINE_SOBEL
|
|
float objS = SAMPLE_TEXTURE2D_X(_OutlineObjectId, sampler_PointClamp, i.uv - uvInc.zy).x;
|
|
float objN = SAMPLE_TEXTURE2D_X(_OutlineObjectId, sampler_PointClamp, i.uv + uvInc.zy).x;
|
|
float objW = SAMPLE_TEXTURE2D_X(_OutlineObjectId, sampler_PointClamp, i.uv - uvInc.xz).x;
|
|
float objE = SAMPLE_TEXTURE2D_X(_OutlineObjectId, sampler_PointClamp, i.uv + uvInc.xz).x;
|
|
float maxObj = max( max(objS, objN), max(objW, objE) );
|
|
float minObj = min( min(objS, objN), min(objW, objE) );
|
|
float objDiff = maxObj - minObj;
|
|
outline = objDiff > 0.01;
|
|
|
|
#if BEAUTIFY_OUTLINE_OUTER_ONLY
|
|
float depthN = BEAUTIFY_GET_CUSTOM_DEPTH_01(_OutlineDepth, i.uv + uvInc.zy);
|
|
float depthS = BEAUTIFY_GET_CUSTOM_DEPTH_01(_OutlineDepth, i.uv - uvInc.zy);
|
|
float depthW = BEAUTIFY_GET_CUSTOM_DEPTH_01(_OutlineDepth, i.uv - uvInc.xz);
|
|
float depthE = BEAUTIFY_GET_CUSTOM_DEPTH_01(_OutlineDepth, i.uv + uvInc.xz);
|
|
|
|
float objM = SAMPLE_TEXTURE2D_X(_OutlineObjectId, sampler_PointClamp, i.uv).x;
|
|
if ( (depth < depthN && abs(objN - objM) > 0.01) ||
|
|
(depth < depthS && abs(objS - objM) > 0.01) ||
|
|
(depth < depthW && abs(objW - objM) > 0.01) ||
|
|
(depth < depthE && abs(objE - objM) > 0.01))
|
|
outline = 0;
|
|
#endif
|
|
|
|
// check object is big enough
|
|
#if BEAUTIFY_OUTLINE_MIN_SEPARATION
|
|
uvInc *= OUTLINE_MIN_SEPARATION;
|
|
float objS2 = SAMPLE_TEXTURE2D_X(_OutlineObjectId, sampler_PointClamp, i.uv - uvInc.zy).x;
|
|
float objN2 = SAMPLE_TEXTURE2D_X(_OutlineObjectId, sampler_PointClamp, i.uv + uvInc.zy).x;
|
|
if (abs(objN2 - objN) > 0.01 && abs(objS2 - objS) > 0.01) outline *= 0.25 / OUTLINE_INTENSITY_MULTIPLIER;
|
|
float objW2 = SAMPLE_TEXTURE2D_X(_OutlineObjectId, sampler_PointClamp, i.uv - uvInc.xz).x;
|
|
float objE2 = SAMPLE_TEXTURE2D_X(_OutlineObjectId, sampler_PointClamp, i.uv + uvInc.xz).x;
|
|
if (abs(objE2 - objE) > 0.01 && abs(objW2 - objW) > 0.01) outline *= 0.25 / OUTLINE_INTENSITY_MULTIPLIER;
|
|
#endif
|
|
|
|
#else
|
|
float3 rgbS = SAMPLE_TEXTURE2D_X(_MainTex, sampler_LinearClamp, i.uv - uvInc.zy).rgb;
|
|
float3 rgbN = SAMPLE_TEXTURE2D_X(_MainTex, sampler_LinearClamp, i.uv + uvInc.zy).rgb;
|
|
float3 rgbW = SAMPLE_TEXTURE2D_X(_MainTex, sampler_LinearClamp, i.uv - uvInc.xz).rgb;
|
|
float3 rgbE = SAMPLE_TEXTURE2D_X(_MainTex, sampler_LinearClamp, i.uv + uvInc.xz).rgb;
|
|
|
|
#if BEAUTIFY_OUTLINE_CUSTOM_DEPTH || !BEAUTIFY_OUTLINE_SOBEL
|
|
#if BEAUTIFY_OUTLINE_CUSTOM_DEPTH
|
|
float depthS = BEAUTIFY_GET_CUSTOM_DEPTH_01(_OutlineDepth, i.uv - uvInc.zy);
|
|
float depthW = BEAUTIFY_GET_CUSTOM_DEPTH_01(_OutlineDepth, i.uv - uvInc.xz);
|
|
float depthE = BEAUTIFY_GET_CUSTOM_DEPTH_01(_OutlineDepth, i.uv + uvInc.xz);
|
|
float depthN = BEAUTIFY_GET_CUSTOM_DEPTH_01(_OutlineDepth, i.uv + uvInc.zy);
|
|
#else
|
|
float depthS = BEAUTIFY_GET_SCENE_DEPTH_01(i.uv - uvInc.zy);
|
|
float depthW = BEAUTIFY_GET_SCENE_DEPTH_01(i.uv - uvInc.xz);
|
|
float depthE = BEAUTIFY_GET_SCENE_DEPTH_01(i.uv + uvInc.xz);
|
|
float depthN = BEAUTIFY_GET_SCENE_DEPTH_01(i.uv + uvInc.zy);
|
|
#endif
|
|
float maxDepth = max(depth, max(max(depthS, depthN), max(depthW, depthE)));
|
|
float minDepth = min(depth, min(min(depthS, depthN), min(depthW, depthE)));
|
|
float depthDiff = maxDepth - minDepth;
|
|
float3 normalNW = getNormal(depth, depthN, depthW, uvInc.zy, float2(-uvInc.x, -uvInc.z));
|
|
float3 normalSE = getNormal(depth, depthS, depthE, -uvInc.zy, uvInc.xz);
|
|
float dnorm = dot(normalNW, normalSE);
|
|
float satN = getSaturation(rgbN);
|
|
float satS = getSaturation(rgbS);
|
|
float satW = getSaturation(rgbW);
|
|
float satE = getSaturation(rgbE);
|
|
float maxSat = max( max(satN, satS), max(satW, satE) );
|
|
float minSat = min( min(satN, satS), min(satW, satE) );
|
|
float dSat = maxSat - minSat;
|
|
outline = dSat > OUTLINE_MIN_SATURATION_THRESHOLD && dnorm < OUTLINE_EDGE_THRESHOLD && depthDiff > OUTLINE_MIN_DEPTH_THRESHOLD;
|
|
#else
|
|
float3 rgbSW = SAMPLE_TEXTURE2D_X(_MainTex, sampler_LinearClamp, i.uv - uvInc.xy).rgb;
|
|
float3 rgbNE = SAMPLE_TEXTURE2D_X(_MainTex, sampler_LinearClamp, i.uv + uvInc.xy).rgb;
|
|
float3 rgbSE = SAMPLE_TEXTURE2D_X(_MainTex, sampler_LinearClamp, i.uv + float2( uvInc.x, -uvInc.y)).rgb;
|
|
float3 rgbNW = SAMPLE_TEXTURE2D_X(_MainTex, sampler_LinearClamp, i.uv + float2(-uvInc.x, uvInc.y)).rgb;
|
|
float3 gx = rgbSW * -1.0;
|
|
gx += rgbSE * 1.0;
|
|
gx += rgbW * -2.0;
|
|
gx += rgbE * 2.0;
|
|
gx += rgbNW * -1.0;
|
|
gx += rgbNE * 1.0;
|
|
float3 gy = rgbSW * -1.0;
|
|
gy += rgbS * -2.0;
|
|
gy += rgbSE * -1.0;
|
|
gy += rgbNW * 1.0;
|
|
gy += rgbN * 2.0;
|
|
gy += rgbNE * 1.0;
|
|
outline = (length(gx * gx + gy * gy) - _Outline.a) > 0.0;
|
|
#endif
|
|
#endif
|
|
|
|
#if BEAUTIFY_DEPTH_FADE
|
|
float factor = max(0, (OUTLINE_DISTANCE_FADE - depth) / OUTLINE_DISTANCE_FADE);
|
|
outline *= factor;
|
|
#endif
|
|
|
|
return outline;
|
|
}
|
|
|
|
float4 fragOutline (VaryingsOutline i) : SV_Target {
|
|
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
|
|
i.uv = UnityStereoTransformScreenSpaceTex(i.uv);
|
|
float outline = OutlinePass(i);
|
|
return outline;
|
|
}
|
|
|
|
|
|
VaryingsCross VertBlur(AttributesSimple v) {
|
|
VaryingsCross o;
|
|
UNITY_SETUP_INSTANCE_ID(v);
|
|
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
|
|
|
o.positionCS = v.positionOS;
|
|
o.positionCS.y *= _ProjectionParams.x * _FlipY;
|
|
o.uv = v.uv;
|
|
BEAUTIFY_VERTEX_OUTPUT_GAUSSIAN_UV(o)
|
|
|
|
return o;
|
|
}
|
|
|
|
half4 FragBlur (VaryingsCross i): SV_Target {
|
|
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
|
|
i.uv = UnityStereoTransformScreenSpaceTex(i.uv);
|
|
BEAUTIFY_FRAG_SETUP_GAUSSIAN_UV(i)
|
|
|
|
half4 pixel = SAMPLE_TEXTURE2D_X(_MainTex, sampler_LinearClamp, i.uv) * 0.2270270270
|
|
+ (SAMPLE_TEXTURE2D_X(_MainTex, sampler_LinearClamp, uv1) + SAMPLE_TEXTURE2D_X(_MainTex, sampler_LinearClamp, uv2)) * 0.3162162162
|
|
+ (SAMPLE_TEXTURE2D_X(_MainTex, sampler_LinearClamp, uv3) + SAMPLE_TEXTURE2D_X(_MainTex, sampler_LinearClamp, uv4)) * 0.0702702703;
|
|
return pixel;
|
|
}
|
|
|
|
half4 FragCopy (VaryingsSimple i): SV_Target {
|
|
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
|
|
i.uv = UnityStereoTransformScreenSpaceTex(i.uv);
|
|
half outline = SAMPLE_TEXTURE2D_X(_MainTex, sampler_LinearClamp, i.uv).r;
|
|
half4 color = half4(_Outline.rgb, _Outline.a * outline);
|
|
color *= OUTLINE_INTENSITY_MULTIPLIER;
|
|
color.a = saturate(color.a);
|
|
return color;
|
|
}
|
|
|
|
#endif |