| | |
| | | #ifndef __DEPTH_OF_FIELD__ |
| | | #define __DEPTH_OF_FIELD__ |
| | | |
| | | #if SHADER_TARGET >= 50 |
| | | // Use separate texture/sampler objects on Shader Model 5.0 |
| | | #define SEPARATE_TEXTURE_SAMPLER |
| | | #define DOF_DECL_TEX2D(tex) Texture2D tex; SamplerState sampler##tex |
| | | #define DOF_TEX2D(tex, coord) tex.Sample(sampler##tex, coord) |
| | | #else |
| | | #define DOF_DECL_TEX2D(tex) sampler2D tex |
| | | #define DOF_TEX2D(tex, coord) tex2D(tex, coord) |
| | | #endif |
| | | |
| | | #include "Common.cginc" |
| | | #include "DiskKernels.cginc" |
| | | |
| | | DOF_DECL_TEX2D(_CameraDepthTexture); |
| | | DOF_DECL_TEX2D(_CameraMotionVectorsTexture); |
| | | DOF_DECL_TEX2D(_CoCTex); |
| | | |
| | | // Camera parameters |
| | | float _Distance; |
| | | float _LensCoeff; // f^2 / (N * (S1 - f) * film_width * 2) |
| | | float _MaxCoC; |
| | | float _RcpMaxCoC; |
| | | float _RcpAspect; |
| | | half3 _TaaParams; // Jitter.x, Jitter.y, Blending |
| | | |
| | | struct VaryingsDOF |
| | | { |
| | | float4 pos : SV_POSITION; |
| | | half2 uv : TEXCOORD0; |
| | | half2 uvAlt : TEXCOORD1; |
| | | }; |
| | | |
| | | // Common vertex shader with single pass stereo rendering support |
| | | VaryingsDOF VertDOF(AttributesDefault v) |
| | | { |
| | | half2 uvAlt = v.texcoord; |
| | | #if UNITY_UV_STARTS_AT_TOP |
| | | if (_MainTex_TexelSize.y < 0.0) uvAlt.y = 1.0 - uvAlt.y; |
| | | #endif |
| | | |
| | | VaryingsDOF o; |
| | | o.pos = UnityObjectToClipPos(v.vertex); |
| | | |
| | | #if defined(UNITY_SINGLE_PASS_STEREO) |
| | | o.uv = UnityStereoScreenSpaceUVAdjust(v.texcoord, _MainTex_ST); |
| | | o.uvAlt = UnityStereoScreenSpaceUVAdjust(uvAlt, _MainTex_ST); |
| | | #else |
| | | o.uv = v.texcoord; |
| | | o.uvAlt = uvAlt; |
| | | #endif |
| | | |
| | | return o; |
| | | } |
| | | |
| | | // CoC calculation |
| | | half4 FragCoC(VaryingsDOF i) : SV_Target |
| | | { |
| | | float depth = LinearEyeDepth(DOF_TEX2D(_CameraDepthTexture, i.uv)); |
| | | half coc = (depth - _Distance) * _LensCoeff / max(depth, 1e-5); |
| | | return saturate(coc * 0.5 * _RcpMaxCoC + 0.5); |
| | | } |
| | | |
| | | // Temporal filter |
| | | half4 FragTempFilter(VaryingsDOF i) : SV_Target |
| | | { |
| | | float3 uvOffs = _MainTex_TexelSize.xyy * float3(1, 1, 0); |
| | | |
| | | #if defined(SEPARATE_TEXTURE_SAMPLER) |
| | | |
| | | half4 cocTL = _CoCTex.GatherRed(sampler_CoCTex, i.uv - uvOffs.xy * 0.5); // top-left |
| | | half4 cocBR = _CoCTex.GatherRed(sampler_CoCTex, i.uv + uvOffs.xy * 0.5); // bottom-right |
| | | half coc1 = cocTL.x; // top |
| | | half coc2 = cocTL.z; // left |
| | | half coc3 = cocBR.x; // bottom |
| | | half coc4 = cocBR.z; // right |
| | | |
| | | #else |
| | | |
| | | half coc1 = DOF_TEX2D(_CoCTex, i.uv - uvOffs.xz).r; // top |
| | | half coc2 = DOF_TEX2D(_CoCTex, i.uv - uvOffs.zy).r; // left |
| | | half coc3 = DOF_TEX2D(_CoCTex, i.uv + uvOffs.zy).r; // bottom |
| | | half coc4 = DOF_TEX2D(_CoCTex, i.uv + uvOffs.xz).r; // right |
| | | |
| | | #endif |
| | | |
| | | // Dejittered center sample. |
| | | half coc0 = DOF_TEX2D(_CoCTex, i.uv - _TaaParams.xy).r; |
| | | |
| | | // CoC dilation: determine the closest point in the four neighbors. |
| | | float3 closest = float3(0, 0, coc0); |
| | | closest = coc1 < closest.z ? float3(-uvOffs.xz, coc1) : closest; |
| | | closest = coc2 < closest.z ? float3(-uvOffs.zy, coc2) : closest; |
| | | closest = coc3 < closest.z ? float3(+uvOffs.zy, coc3) : closest; |
| | | closest = coc4 < closest.z ? float3(+uvOffs.xz, coc4) : closest; |
| | | |
| | | // Sample the history buffer with the motion vector at the closest point. |
| | | float2 motion = DOF_TEX2D(_CameraMotionVectorsTexture, i.uv + closest.xy).xy; |
| | | half cocHis = DOF_TEX2D(_MainTex, i.uv - motion).r; |
| | | |
| | | // Neighborhood clamping. |
| | | half cocMin = closest.z; |
| | | half cocMax = max(max(max(max(coc0, coc1), coc2), coc3), coc4); |
| | | cocHis = clamp(cocHis, cocMin, cocMax); |
| | | |
| | | // Blend with the history. |
| | | return lerp(coc0, cocHis, _TaaParams.z); |
| | | } |
| | | |
| | | // Prefilter: downsampling and premultiplying. |
| | | half4 FragPrefilter(VaryingsDOF i) : SV_Target |
| | | { |
| | | #if defined(SEPARATE_TEXTURE_SAMPLER) |
| | | |
| | | // Sample source colors. |
| | | half4 c_r = _MainTex.GatherRed (sampler_MainTex, i.uv); |
| | | half4 c_g = _MainTex.GatherGreen(sampler_MainTex, i.uv); |
| | | half4 c_b = _MainTex.GatherBlue (sampler_MainTex, i.uv); |
| | | |
| | | half3 c0 = half3(c_r.x, c_g.x, c_b.x); |
| | | half3 c1 = half3(c_r.y, c_g.y, c_b.y); |
| | | half3 c2 = half3(c_r.z, c_g.z, c_b.z); |
| | | half3 c3 = half3(c_r.w, c_g.w, c_b.w); |
| | | |
| | | // Sample CoCs. |
| | | half4 cocs = _CoCTex.Gather(sampler_CoCTex, i.uvAlt) * 2.0 - 1.0; |
| | | half coc0 = cocs.x; |
| | | half coc1 = cocs.y; |
| | | half coc2 = cocs.z; |
| | | half coc3 = cocs.w; |
| | | |
| | | #else |
| | | |
| | | float3 duv = _MainTex_TexelSize.xyx * float3(0.5, 0.5, -0.5); |
| | | |
| | | // Sample source colors. |
| | | half3 c0 = DOF_TEX2D(_MainTex, i.uv - duv.xy).rgb; |
| | | half3 c1 = DOF_TEX2D(_MainTex, i.uv - duv.zy).rgb; |
| | | half3 c2 = DOF_TEX2D(_MainTex, i.uv + duv.zy).rgb; |
| | | half3 c3 = DOF_TEX2D(_MainTex, i.uv + duv.xy).rgb; |
| | | |
| | | // Sample CoCs. |
| | | half coc0 = DOF_TEX2D(_CoCTex, i.uvAlt - duv.xy).r * 2.0 - 1.0; |
| | | half coc1 = DOF_TEX2D(_CoCTex, i.uvAlt - duv.zy).r * 2.0 - 1.0; |
| | | half coc2 = DOF_TEX2D(_CoCTex, i.uvAlt + duv.zy).r * 2.0 - 1.0; |
| | | half coc3 = DOF_TEX2D(_CoCTex, i.uvAlt + duv.xy).r * 2.0 - 1.0; |
| | | |
| | | #endif |
| | | |
| | | // Apply CoC and luma weights to reduce bleeding and flickering. |
| | | float w0 = abs(coc0) / (Max3(c0) + 1.0); |
| | | float w1 = abs(coc1) / (Max3(c1) + 1.0); |
| | | float w2 = abs(coc2) / (Max3(c2) + 1.0); |
| | | float w3 = abs(coc3) / (Max3(c3) + 1.0); |
| | | |
| | | // Weighted average of the color samples |
| | | half3 avg = c0 * w0 + c1 * w1 + c2 * w2 + c3 * w3; |
| | | avg /= max(w0 + w1 + w2 + w3, 1e-5); |
| | | |
| | | // Select the largest CoC value. |
| | | half coc_min = Min4(coc0, coc1, coc2, coc3); |
| | | half coc_max = Max4(coc0, coc1, coc2, coc3); |
| | | half coc = (-coc_min > coc_max ? coc_min : coc_max) * _MaxCoC; |
| | | |
| | | // Premultiply CoC again. |
| | | avg *= smoothstep(0, _MainTex_TexelSize.y * 2, abs(coc)); |
| | | |
| | | #if defined(UNITY_COLORSPACE_GAMMA) |
| | | avg = GammaToLinearSpace(avg); |
| | | #endif |
| | | |
| | | return half4(avg, coc); |
| | | } |
| | | |
| | | // Bokeh filter with disk-shaped kernels |
| | | half4 FragBlur(VaryingsDOF i) : SV_Target |
| | | { |
| | | half4 samp0 = DOF_TEX2D(_MainTex, i.uv); |
| | | |
| | | half4 bgAcc = 0.0; // Background: far field bokeh |
| | | half4 fgAcc = 0.0; // Foreground: near field bokeh |
| | | |
| | | UNITY_LOOP for (int si = 0; si < kSampleCount; si++) |
| | | { |
| | | float2 disp = kDiskKernel[si] * _MaxCoC; |
| | | float dist = length(disp); |
| | | |
| | | float2 duv = float2(disp.x * _RcpAspect, disp.y); |
| | | half4 samp = DOF_TEX2D(_MainTex, i.uv + duv); |
| | | |
| | | // BG: Compare CoC of the current sample and the center sample |
| | | // and select smaller one. |
| | | half bgCoC = max(min(samp0.a, samp.a), 0.0); |
| | | |
| | | // Compare the CoC to the sample distance. |
| | | // Add a small margin to smooth out. |
| | | const half margin = _MainTex_TexelSize.y * 2; |
| | | half bgWeight = saturate((bgCoC - dist + margin) / margin); |
| | | half fgWeight = saturate((-samp.a - dist + margin) / margin); |
| | | |
| | | // Cut influence from focused areas because they're darkened by CoC |
| | | // premultiplying. This is only needed for near field. |
| | | fgWeight *= step(_MainTex_TexelSize.y, -samp.a); |
| | | |
| | | // Accumulation |
| | | bgAcc += half4(samp.rgb, 1.0) * bgWeight; |
| | | fgAcc += half4(samp.rgb, 1.0) * fgWeight; |
| | | } |
| | | |
| | | // Get the weighted average. |
| | | bgAcc.rgb /= bgAcc.a + (bgAcc.a == 0.0); // zero-div guard |
| | | fgAcc.rgb /= fgAcc.a + (fgAcc.a == 0.0); |
| | | |
| | | // BG: Calculate the alpha value only based on the center CoC. |
| | | // This is a rather aggressive approximation but provides stable results. |
| | | bgAcc.a = smoothstep(_MainTex_TexelSize.y, _MainTex_TexelSize.y * 2.0, samp0.a); |
| | | |
| | | // FG: Normalize the total of the weights. |
| | | fgAcc.a *= UNITY_PI / kSampleCount; |
| | | |
| | | // Alpha premultiplying |
| | | half alpha = saturate(fgAcc.a); |
| | | half3 rgb = lerp(bgAcc.rgb, fgAcc.rgb, alpha); |
| | | |
| | | return half4(rgb, alpha); |
| | | } |
| | | |
| | | // Postfilter blur |
| | | half4 FragPostBlur(VaryingsDOF i) : SV_Target |
| | | { |
| | | // 9 tap tent filter with 4 bilinear samples |
| | | const float4 duv = _MainTex_TexelSize.xyxy * float4(0.5, 0.5, -0.5, 0); |
| | | half4 acc; |
| | | acc = DOF_TEX2D(_MainTex, i.uv - duv.xy); |
| | | acc += DOF_TEX2D(_MainTex, i.uv - duv.zy); |
| | | acc += DOF_TEX2D(_MainTex, i.uv + duv.zy); |
| | | acc += DOF_TEX2D(_MainTex, i.uv + duv.xy); |
| | | return acc / 4.0; |
| | | } |
| | | |
| | | #endif // __DEPTH_OF_FIELD__ |
| | | #ifndef __DEPTH_OF_FIELD__
|
| | | #define __DEPTH_OF_FIELD__
|
| | |
|
| | | #if SHADER_TARGET >= 50
|
| | | // Use separate texture/sampler objects on Shader Model 5.0
|
| | | #define SEPARATE_TEXTURE_SAMPLER
|
| | | #define DOF_DECL_TEX2D(tex) Texture2D tex; SamplerState sampler##tex
|
| | | #define DOF_TEX2D(tex, coord) tex.Sample(sampler##tex, coord)
|
| | | #else
|
| | | #define DOF_DECL_TEX2D(tex) sampler2D tex
|
| | | #define DOF_TEX2D(tex, coord) tex2D(tex, coord)
|
| | | #endif
|
| | |
|
| | | #include "Common.cginc"
|
| | | #include "DiskKernels.cginc"
|
| | |
|
| | | DOF_DECL_TEX2D(_CameraDepthTexture);
|
| | | DOF_DECL_TEX2D(_CameraMotionVectorsTexture);
|
| | | DOF_DECL_TEX2D(_CoCTex);
|
| | |
|
| | | // Camera parameters
|
| | | float _Distance;
|
| | | float _LensCoeff; // f^2 / (N * (S1 - f) * film_width * 2)
|
| | | float _MaxCoC;
|
| | | float _RcpMaxCoC;
|
| | | float _RcpAspect;
|
| | | half3 _TaaParams; // Jitter.x, Jitter.y, Blending
|
| | |
|
| | | struct VaryingsDOF
|
| | | {
|
| | | float4 pos : SV_POSITION;
|
| | | half2 uv : TEXCOORD0;
|
| | | half2 uvAlt : TEXCOORD1;
|
| | | };
|
| | |
|
| | | // Common vertex shader with single pass stereo rendering support
|
| | | VaryingsDOF VertDOF(AttributesDefault v)
|
| | | {
|
| | | half2 uvAlt = v.texcoord;
|
| | | #if UNITY_UV_STARTS_AT_TOP
|
| | | if (_MainTex_TexelSize.y < 0.0) uvAlt.y = 1.0 - uvAlt.y;
|
| | | #endif
|
| | |
|
| | | VaryingsDOF o;
|
| | | o.pos = UnityObjectToClipPos(v.vertex);
|
| | |
|
| | | #if defined(UNITY_SINGLE_PASS_STEREO)
|
| | | o.uv = UnityStereoScreenSpaceUVAdjust(v.texcoord, _MainTex_ST);
|
| | | o.uvAlt = UnityStereoScreenSpaceUVAdjust(uvAlt, _MainTex_ST);
|
| | | #else
|
| | | o.uv = v.texcoord;
|
| | | o.uvAlt = uvAlt;
|
| | | #endif
|
| | |
|
| | | return o;
|
| | | }
|
| | |
|
| | | // CoC calculation
|
| | | half4 FragCoC(VaryingsDOF i) : SV_Target
|
| | | {
|
| | | float depth = LinearEyeDepth(DOF_TEX2D(_CameraDepthTexture, i.uv));
|
| | | half coc = (depth - _Distance) * _LensCoeff / max(depth, 1e-5);
|
| | | return saturate(coc * 0.5 * _RcpMaxCoC + 0.5);
|
| | | }
|
| | |
|
| | | // Temporal filter
|
| | | half4 FragTempFilter(VaryingsDOF i) : SV_Target
|
| | | {
|
| | | float3 uvOffs = _MainTex_TexelSize.xyy * float3(1, 1, 0);
|
| | |
|
| | | #if defined(SEPARATE_TEXTURE_SAMPLER)
|
| | |
|
| | | half4 cocTL = _CoCTex.GatherRed(sampler_CoCTex, i.uv - uvOffs.xy * 0.5); // top-left
|
| | | half4 cocBR = _CoCTex.GatherRed(sampler_CoCTex, i.uv + uvOffs.xy * 0.5); // bottom-right
|
| | | half coc1 = cocTL.x; // top
|
| | | half coc2 = cocTL.z; // left
|
| | | half coc3 = cocBR.x; // bottom
|
| | | half coc4 = cocBR.z; // right
|
| | |
|
| | | #else
|
| | |
|
| | | half coc1 = DOF_TEX2D(_CoCTex, i.uv - uvOffs.xz).r; // top
|
| | | half coc2 = DOF_TEX2D(_CoCTex, i.uv - uvOffs.zy).r; // left
|
| | | half coc3 = DOF_TEX2D(_CoCTex, i.uv + uvOffs.zy).r; // bottom
|
| | | half coc4 = DOF_TEX2D(_CoCTex, i.uv + uvOffs.xz).r; // right
|
| | |
|
| | | #endif
|
| | |
|
| | | // Dejittered center sample.
|
| | | half coc0 = DOF_TEX2D(_CoCTex, i.uv - _TaaParams.xy).r;
|
| | |
|
| | | // CoC dilation: determine the closest point in the four neighbors.
|
| | | float3 closest = float3(0, 0, coc0);
|
| | | closest = coc1 < closest.z ? float3(-uvOffs.xz, coc1) : closest;
|
| | | closest = coc2 < closest.z ? float3(-uvOffs.zy, coc2) : closest;
|
| | | closest = coc3 < closest.z ? float3(+uvOffs.zy, coc3) : closest;
|
| | | closest = coc4 < closest.z ? float3(+uvOffs.xz, coc4) : closest;
|
| | |
|
| | | // Sample the history buffer with the motion vector at the closest point.
|
| | | float2 motion = DOF_TEX2D(_CameraMotionVectorsTexture, i.uv + closest.xy).xy;
|
| | | half cocHis = DOF_TEX2D(_MainTex, i.uv - motion).r;
|
| | |
|
| | | // Neighborhood clamping.
|
| | | half cocMin = closest.z;
|
| | | half cocMax = max(max(max(max(coc0, coc1), coc2), coc3), coc4);
|
| | | cocHis = clamp(cocHis, cocMin, cocMax);
|
| | |
|
| | | // Blend with the history.
|
| | | return lerp(coc0, cocHis, _TaaParams.z);
|
| | | }
|
| | |
|
| | | // Prefilter: downsampling and premultiplying.
|
| | | half4 FragPrefilter(VaryingsDOF i) : SV_Target
|
| | | {
|
| | | #if defined(SEPARATE_TEXTURE_SAMPLER)
|
| | |
|
| | | // Sample source colors.
|
| | | half4 c_r = _MainTex.GatherRed (sampler_MainTex, i.uv);
|
| | | half4 c_g = _MainTex.GatherGreen(sampler_MainTex, i.uv);
|
| | | half4 c_b = _MainTex.GatherBlue (sampler_MainTex, i.uv);
|
| | |
|
| | | half3 c0 = half3(c_r.x, c_g.x, c_b.x);
|
| | | half3 c1 = half3(c_r.y, c_g.y, c_b.y);
|
| | | half3 c2 = half3(c_r.z, c_g.z, c_b.z);
|
| | | half3 c3 = half3(c_r.w, c_g.w, c_b.w);
|
| | |
|
| | | // Sample CoCs.
|
| | | half4 cocs = _CoCTex.Gather(sampler_CoCTex, i.uvAlt) * 2.0 - 1.0;
|
| | | half coc0 = cocs.x;
|
| | | half coc1 = cocs.y;
|
| | | half coc2 = cocs.z;
|
| | | half coc3 = cocs.w;
|
| | |
|
| | | #else
|
| | |
|
| | | float3 duv = _MainTex_TexelSize.xyx * float3(0.5, 0.5, -0.5);
|
| | |
|
| | | // Sample source colors.
|
| | | half3 c0 = DOF_TEX2D(_MainTex, i.uv - duv.xy).rgb;
|
| | | half3 c1 = DOF_TEX2D(_MainTex, i.uv - duv.zy).rgb;
|
| | | half3 c2 = DOF_TEX2D(_MainTex, i.uv + duv.zy).rgb;
|
| | | half3 c3 = DOF_TEX2D(_MainTex, i.uv + duv.xy).rgb;
|
| | |
|
| | | // Sample CoCs.
|
| | | half coc0 = DOF_TEX2D(_CoCTex, i.uvAlt - duv.xy).r * 2.0 - 1.0;
|
| | | half coc1 = DOF_TEX2D(_CoCTex, i.uvAlt - duv.zy).r * 2.0 - 1.0;
|
| | | half coc2 = DOF_TEX2D(_CoCTex, i.uvAlt + duv.zy).r * 2.0 - 1.0;
|
| | | half coc3 = DOF_TEX2D(_CoCTex, i.uvAlt + duv.xy).r * 2.0 - 1.0;
|
| | |
|
| | | #endif
|
| | |
|
| | | // Apply CoC and luma weights to reduce bleeding and flickering.
|
| | | float w0 = abs(coc0) / (Max3(c0) + 1.0);
|
| | | float w1 = abs(coc1) / (Max3(c1) + 1.0);
|
| | | float w2 = abs(coc2) / (Max3(c2) + 1.0);
|
| | | float w3 = abs(coc3) / (Max3(c3) + 1.0);
|
| | |
|
| | | // Weighted average of the color samples
|
| | | half3 avg = c0 * w0 + c1 * w1 + c2 * w2 + c3 * w3;
|
| | | avg /= max(w0 + w1 + w2 + w3, 1e-5);
|
| | |
|
| | | // Select the largest CoC value.
|
| | | half coc_min = Min4(coc0, coc1, coc2, coc3);
|
| | | half coc_max = Max4(coc0, coc1, coc2, coc3);
|
| | | half coc = (-coc_min > coc_max ? coc_min : coc_max) * _MaxCoC;
|
| | |
|
| | | // Premultiply CoC again.
|
| | | avg *= smoothstep(0, _MainTex_TexelSize.y * 2, abs(coc));
|
| | |
|
| | | #if defined(UNITY_COLORSPACE_GAMMA)
|
| | | avg = GammaToLinearSpace(avg);
|
| | | #endif
|
| | |
|
| | | return half4(avg, coc);
|
| | | }
|
| | |
|
| | | // Bokeh filter with disk-shaped kernels
|
| | | half4 FragBlur(VaryingsDOF i) : SV_Target
|
| | | {
|
| | | half4 samp0 = DOF_TEX2D(_MainTex, i.uv);
|
| | |
|
| | | half4 bgAcc = 0.0; // Background: far field bokeh
|
| | | half4 fgAcc = 0.0; // Foreground: near field bokeh
|
| | |
|
| | | UNITY_LOOP for (int si = 0; si < kSampleCount; si++)
|
| | | {
|
| | | float2 disp = kDiskKernel[si] * _MaxCoC;
|
| | | float dist = length(disp);
|
| | |
|
| | | float2 duv = float2(disp.x * _RcpAspect, disp.y);
|
| | | half4 samp = DOF_TEX2D(_MainTex, i.uv + duv);
|
| | |
|
| | | // BG: Compare CoC of the current sample and the center sample
|
| | | // and select smaller one.
|
| | | half bgCoC = max(min(samp0.a, samp.a), 0.0);
|
| | |
|
| | | // Compare the CoC to the sample distance.
|
| | | // Add a small margin to smooth out.
|
| | | const half margin = _MainTex_TexelSize.y * 2;
|
| | | half bgWeight = saturate((bgCoC - dist + margin) / margin);
|
| | | half fgWeight = saturate((-samp.a - dist + margin) / margin);
|
| | |
|
| | | // Cut influence from focused areas because they're darkened by CoC
|
| | | // premultiplying. This is only needed for near field.
|
| | | fgWeight *= step(_MainTex_TexelSize.y, -samp.a);
|
| | |
|
| | | // Accumulation
|
| | | bgAcc += half4(samp.rgb, 1.0) * bgWeight;
|
| | | fgAcc += half4(samp.rgb, 1.0) * fgWeight;
|
| | | }
|
| | |
|
| | | // Get the weighted average.
|
| | | bgAcc.rgb /= bgAcc.a + (bgAcc.a == 0.0); // zero-div guard
|
| | | fgAcc.rgb /= fgAcc.a + (fgAcc.a == 0.0);
|
| | |
|
| | | // BG: Calculate the alpha value only based on the center CoC.
|
| | | // This is a rather aggressive approximation but provides stable results.
|
| | | bgAcc.a = smoothstep(_MainTex_TexelSize.y, _MainTex_TexelSize.y * 2.0, samp0.a);
|
| | |
|
| | | // FG: Normalize the total of the weights.
|
| | | fgAcc.a *= UNITY_PI / kSampleCount;
|
| | |
|
| | | // Alpha premultiplying
|
| | | half alpha = saturate(fgAcc.a);
|
| | | half3 rgb = lerp(bgAcc.rgb, fgAcc.rgb, alpha);
|
| | |
|
| | | return half4(rgb, alpha);
|
| | | }
|
| | |
|
| | | // Postfilter blur
|
| | | half4 FragPostBlur(VaryingsDOF i) : SV_Target
|
| | | {
|
| | | // 9 tap tent filter with 4 bilinear samples
|
| | | const float4 duv = _MainTex_TexelSize.xyxy * float4(0.5, 0.5, -0.5, 0);
|
| | | half4 acc;
|
| | | acc = DOF_TEX2D(_MainTex, i.uv - duv.xy);
|
| | | acc += DOF_TEX2D(_MainTex, i.uv - duv.zy);
|
| | | acc += DOF_TEX2D(_MainTex, i.uv + duv.zy);
|
| | | acc += DOF_TEX2D(_MainTex, i.uv + duv.xy);
|
| | | return acc / 4.0;
|
| | | }
|
| | |
|
| | | #endif // __DEPTH_OF_FIELD__
|