您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

486 行
12 KiB

Shader "Hidden/Dof/DepthOfField34" {
Properties {
_MainTex ("Base", 2D) = "" {}
_TapLowBackground ("TapLowBackground", 2D) = "" {}
_TapLowForeground ("TapLowForeground", 2D) = "" {}
_TapMedium ("TapMedium", 2D) = "" {}
}
CGINCLUDE
#include "UnityCG.cginc"
struct v2f {
half4 pos : SV_POSITION;
half2 uv1 : TEXCOORD0;
};
struct v2fDofApply {
half4 pos : SV_POSITION;
half2 uv : TEXCOORD0;
};
struct v2fRadius {
half4 pos : SV_POSITION;
half2 uv : TEXCOORD0;
half4 uv1[4] : TEXCOORD1;
};
struct v2fDown {
half4 pos : SV_POSITION;
half2 uv0 : TEXCOORD0;
half2 uv[2] : TEXCOORD1;
};
sampler2D _MainTex;
sampler2D_float _CameraDepthTexture;
sampler2D _TapLowBackground;
sampler2D _TapLowForeground;
sampler2D _TapMedium;
half4 _CurveParams;
half _ForegroundBlurExtrude;
uniform half3 _Threshhold;
uniform float4 _MainTex_TexelSize;
uniform float2 _InvRenderTargetSize;
v2f vert( appdata_img v ) {
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
o.uv1.xy = v.texcoord.xy;
return o;
}
v2fRadius vertWithRadius( appdata_img v ) {
v2fRadius o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv.xy = v.texcoord.xy;
const half2 blurOffsets[4] = {
half2(-0.5, +1.5),
half2(+0.5, -1.5),
half2(+1.5, +0.5),
half2(-1.5, -0.5)
};
o.uv1[0].xy = v.texcoord.xy + 5.0 * _MainTex_TexelSize.xy * blurOffsets[0];
o.uv1[1].xy = v.texcoord.xy + 5.0 * _MainTex_TexelSize.xy * blurOffsets[1];
o.uv1[2].xy = v.texcoord.xy + 5.0 * _MainTex_TexelSize.xy * blurOffsets[2];
o.uv1[3].xy = v.texcoord.xy + 5.0 * _MainTex_TexelSize.xy * blurOffsets[3];
o.uv1[0].zw = v.texcoord.xy + 3.0 * _MainTex_TexelSize.xy * blurOffsets[0];
o.uv1[1].zw = v.texcoord.xy + 3.0 * _MainTex_TexelSize.xy * blurOffsets[1];
o.uv1[2].zw = v.texcoord.xy + 3.0 * _MainTex_TexelSize.xy * blurOffsets[2];
o.uv1[3].zw = v.texcoord.xy + 3.0 * _MainTex_TexelSize.xy * blurOffsets[3];
return o;
}
v2fDofApply vertDofApply( appdata_img v ) {
v2fDofApply o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv.xy = v.texcoord.xy;
return o;
}
v2fDown vertDownsampleWithCocConserve(appdata_img v) {
v2fDown o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv0.xy = v.texcoord.xy;
o.uv[0].xy = v.texcoord.xy + half2(-1.0,-1.0) * _InvRenderTargetSize;
o.uv[1].xy = v.texcoord.xy + half2(1.0,-1.0) * _InvRenderTargetSize;
return o;
}
half4 BokehPrereqs (sampler2D tex, half4 uv1[4], half4 center, half considerCoc) {
// @NOTE 1:
// we are checking for 3 things in order to create a bokeh.
// goal is to get the highest bang for the buck.
// 1.) contrast/frequency should be very high (otherwise bokeh mostly unvisible)
// 2.) luminance should be high
// 3.) no occluder nearby (stored in alpha channel)
// @NOTE 2: about the alpha channel in littleBlur:
// the alpha channel stores an heuristic on how likely it is
// that there is no bokeh occluder nearby.
// if we didn't' check for that, we'd get very noise bokeh
// popping because of the sudden contrast changes
half4 sampleA = tex2D(tex, uv1[0].zw);
half4 sampleB = tex2D(tex, uv1[1].zw);
half4 sampleC = tex2D(tex, uv1[2].zw);
half4 sampleD = tex2D(tex, uv1[3].zw);
half4 littleBlur = 0.125 * (sampleA + sampleB + sampleC + sampleD);
sampleA = tex2D(tex, uv1[0].xy);
sampleB = tex2D(tex, uv1[1].xy);
sampleC = tex2D(tex, uv1[2].xy);
sampleD = tex2D(tex, uv1[3].xy);
littleBlur += 0.125 * (sampleA + sampleB + sampleC + sampleD);
littleBlur = lerp (littleBlur, center, saturate(100.0 * considerCoc * abs(littleBlur.a - center.a)));
return littleBlur;
}
half4 fragDownsampleWithCocConserve(v2fDown i) : SV_Target {
half2 rowOfs[4];
rowOfs[0] = half2(0.0, 0.0);
rowOfs[1] = half2(0.0, _InvRenderTargetSize.y);
rowOfs[2] = half2(0.0, _InvRenderTargetSize.y) * 2.0;
rowOfs[3] = half2(0.0, _InvRenderTargetSize.y) * 3.0;
half4 color = tex2D(_MainTex, i.uv0.xy);
half4 sampleA = tex2D(_MainTex, i.uv[0].xy + rowOfs[0]);
half4 sampleB = tex2D(_MainTex, i.uv[1].xy + rowOfs[0]);
half4 sampleC = tex2D(_MainTex, i.uv[0].xy + rowOfs[2]);
half4 sampleD = tex2D(_MainTex, i.uv[1].xy + rowOfs[2]);
color += sampleA + sampleB + sampleC + sampleD;
color *= 0.2;
// @NOTE we are doing max on the alpha channel for 2 reasons:
// 1) foreground blur likes a slightly bigger radius
// 2) otherwise we get an ugly outline between high blur- and medium blur-areas
// drawback: we get a little bit of color bleeding
color.a = max(max(sampleA.a, sampleB.a), max(sampleC.a, sampleD.a));
return color;
}
half4 fragDofApplyBg (v2fDofApply i) : SV_Target {
half4 tapHigh = tex2D (_MainTex, i.uv.xy);
#if UNITY_UV_STARTS_AT_TOP
if (_MainTex_TexelSize.y < 0)
i.uv.xy = i.uv.xy * half2(1,-1)+half2(0,1);
#endif
half4 tapLow = tex2D (_TapLowBackground, i.uv.xy); // already mixed with medium blur
tapHigh = lerp (tapHigh, tapLow, tapHigh.a);
return tapHigh;
}
half4 fragDofApplyBgDebug (v2fDofApply i) : SV_Target {
half4 tapHigh = tex2D (_MainTex, i.uv.xy);
half4 tapLow = tex2D (_TapLowBackground, i.uv.xy);
half4 tapMedium = tex2D (_TapMedium, i.uv.xy);
tapMedium.rgb = (tapMedium.rgb + half3 (1, 1, 0)) * 0.5;
tapLow.rgb = (tapLow.rgb + half3 (0, 1, 0)) * 0.5;
tapLow = lerp (tapMedium, tapLow, saturate (tapLow.a * tapLow.a));
tapLow = tapLow * 0.5 + tex2D (_TapLowBackground, i.uv.xy) * 0.5;
return lerp (tapHigh, tapLow, tapHigh.a);
}
half4 fragDofApplyFg (v2fDofApply i) : SV_Target {
half4 fgBlur = tex2D(_TapLowForeground, i.uv.xy);
#if UNITY_UV_STARTS_AT_TOP
if (_MainTex_TexelSize.y < 0)
i.uv.xy = i.uv.xy * half2(1,-1)+half2(0,1);
#endif
half4 fgColor = tex2D(_MainTex,i.uv.xy);
//fgBlur.a = saturate(fgBlur.a*_ForegroundBlurWeight+saturate(fgColor.a-fgBlur.a));
//fgBlur.a = max (fgColor.a, (2.0 * fgBlur.a - fgColor.a)) * _ForegroundBlurExtrude;
fgBlur.a = max(fgColor.a, fgBlur.a * _ForegroundBlurExtrude); //max (fgColor.a, (2.0*fgBlur.a-fgColor.a)) * _ForegroundBlurExtrude;
return lerp (fgColor, fgBlur, saturate(fgBlur.a));
}
half4 fragDofApplyFgDebug (v2fDofApply i) : SV_Target {
half4 fgBlur = tex2D(_TapLowForeground, i.uv.xy);
half4 fgColor = tex2D(_MainTex,i.uv.xy);
fgBlur.a = max(fgColor.a, fgBlur.a * _ForegroundBlurExtrude); //max (fgColor.a, (2.0*fgBlur.a-fgColor.a)) * _ForegroundBlurExtrude;
half4 tapMedium = half4 (1, 1, 0, fgBlur.a);
tapMedium.rgb = 0.5 * (tapMedium.rgb + fgColor.rgb);
fgBlur.rgb = 0.5 * (fgBlur.rgb + half3(0,1,0));
fgBlur.rgb = lerp (tapMedium.rgb, fgBlur.rgb, saturate (fgBlur.a * fgBlur.a));
return lerp ( fgColor, fgBlur, saturate(fgBlur.a));
}
half4 fragCocBg (v2f i) : SV_Target {
float d = SAMPLE_DEPTH_TEXTURE (_CameraDepthTexture, i.uv1.xy);
d = Linear01Depth (d);
half coc = 0.0;
half focalDistance01 = _CurveParams.w + _CurveParams.z;
if (d > focalDistance01)
coc = (d - focalDistance01);
coc = saturate (coc * _CurveParams.y);
return coc;
}
half4 fragCocFg (v2f i) : SV_Target {
half4 color = tex2D (_MainTex, i.uv1.xy);
color.a = 0.0;
#if UNITY_UV_STARTS_AT_TOP
if (_MainTex_TexelSize.y < 0)
i.uv1.xy = i.uv1.xy * half2(1,-1)+half2(0,1);
#endif
float d = SAMPLE_DEPTH_TEXTURE (_CameraDepthTexture, i.uv1.xy);
d = Linear01Depth (d);
half focalDistance01 = (_CurveParams.w - _CurveParams.z);
if (d < focalDistance01)
color.a = (focalDistance01 - d);
color.a = saturate (color.a * _CurveParams.x);
return color;
}
// not being used atm
half4 fragMask (v2f i) : SV_Target {
return half4(0,0,0,0);
}
// used for simple one one blend
half4 fragAddBokeh (v2f i) : SV_Target {
half4 from = tex2D( _MainTex, i.uv1.xy );
return from;
}
half4 fragAddFgBokeh (v2f i) : SV_Target {
half4 from = tex2D( _MainTex, i.uv1.xy );
return from;
}
half4 fragDarkenForBokeh(v2fRadius i) : SV_Target {
half4 fromOriginal = tex2D(_MainTex, i.uv.xy);
half4 lowRez = BokehPrereqs (_MainTex, i.uv1, fromOriginal, _Threshhold.z);
half4 outColor = half4(0,0,0, fromOriginal.a);
half modulate = fromOriginal.a;
// this code imitates the if-then-else conditions below
half2 conditionCheck = half2( dot(abs(fromOriginal.rgb-lowRez.rgb), half3(0.3,0.5,0.2)), Luminance(fromOriginal.rgb));
conditionCheck *= fromOriginal.a;
conditionCheck = saturate(_Threshhold.xy - conditionCheck);
outColor = lerp (outColor, fromOriginal, saturate (dot(conditionCheck, half2(1000.0,1000.0))));
/*
if ( abs(dot(fromOriginal.rgb - lowRez.rgb, half3 (0.3,0.5,0.2))) * modulate < _Threshhold.x)
outColor = fromOriginal; // no darkening
if (Luminance(fromOriginal.rgb) * modulate < _Threshhold.y)
outColor = fromOriginal; // no darkening
if (lowRez.a < _Threshhold.z) // need to make foreground not cast false bokeh's
outColor = fromOriginal; // no darkenin
*/
return outColor;
}
half4 fragExtractAndAddToBokeh (v2fRadius i) : SV_Target {
half4 from = tex2D(_MainTex, i.uv.xy);
half4 lowRez = BokehPrereqs(_MainTex, i.uv1, from, _Threshhold.z);
half4 outColor = from;
// this code imitates the if-then-else conditions below
half2 conditionCheck = half2( dot(abs(from.rgb-lowRez.rgb), half3(0.3,0.5,0.2)), Luminance(from.rgb));
conditionCheck *= from.a;
conditionCheck = saturate(_Threshhold.xy - conditionCheck);
outColor = lerp (outColor, half4(0,0,0,0), saturate (dot(conditionCheck, half2(1000.0,1000.0))));
/*
if ( abs(dot(from.rgb - lowRez.rgb, half3 (0.3,0.5,0.2))) * modulate < _Threshhold.x)
outColor = half4(0,0,0,0); // don't add
if (Luminance(from.rgb) * modulate < _Threshhold.y)
outColor = half4(0,0,0,0); // don't add
if (lowRez.a < _Threshhold.z) // need to make foreground not cast false bokeh's
outColor = half4(0,0,0,0); // don't add
*/
return outColor;
}
ENDCG
Subshader {
// pass 0
Pass {
ZTest Always Cull Off ZWrite Off
CGPROGRAM
#pragma vertex vertDofApply
#pragma fragment fragDofApplyBg
ENDCG
}
// pass 1
Pass {
ZTest Always Cull Off ZWrite Off
ColorMask RGB
CGPROGRAM
#pragma vertex vertDofApply
#pragma fragment fragDofApplyFgDebug
ENDCG
}
// pass 2
Pass {
ZTest Always Cull Off ZWrite Off
ColorMask RGB
CGPROGRAM
#pragma vertex vertDofApply
#pragma fragment fragDofApplyBgDebug
ENDCG
}
// pass 3
Pass {
ZTest Always Cull Off ZWrite Off
ColorMask A
CGPROGRAM
#pragma vertex vert
#pragma fragment fragCocBg
ENDCG
}
// pass 4
Pass {
ZTest Always Cull Off ZWrite Off
ColorMask RGB
//Blend One One
CGPROGRAM
#pragma vertex vertDofApply
#pragma fragment fragDofApplyFg
ENDCG
}
// pass 5
Pass {
ZTest Always Cull Off ZWrite Off
ColorMask ARGB
CGPROGRAM
#pragma vertex vert
#pragma fragment fragCocFg
ENDCG
}
// pass 6
Pass {
ZTest Always Cull Off ZWrite Off
CGPROGRAM
#pragma vertex vertDownsampleWithCocConserve
#pragma fragment fragDownsampleWithCocConserve
ENDCG
}
// pass 7
// not being used atm
Pass {
ZTest Always Cull Off ZWrite Off
ColorMask RGBA
CGPROGRAM
#pragma vertex vert
#pragma fragment fragMask
ENDCG
}
// pass 8
Pass {
ZTest Always Cull Off ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
ColorMask RGB
CGPROGRAM
#pragma vertex vert
#pragma fragment fragAddBokeh
ENDCG
}
// pass 9
Pass {
ZTest Always Cull Off ZWrite Off
Blend One One
ColorMask RGB
CGPROGRAM
#pragma vertex vertWithRadius
#pragma fragment fragExtractAndAddToBokeh
ENDCG
}
// pass 10
Pass {
ZTest Always Cull Off ZWrite Off
CGPROGRAM
#pragma vertex vertWithRadius
#pragma fragment fragDarkenForBokeh
ENDCG
}
// pass 11
Pass {
ZTest Always Cull Off ZWrite Off
CGPROGRAM
#pragma vertex vertWithRadius
#pragma fragment fragExtractAndAddToBokeh
ENDCG
}
}
Fallback off
}