99
1010sampler2D_float _CameraDepthTexture;
1111sampler2D_float _HistoryCoC;
12+ float _HistoryWeight;
1213
1314// Camera parameters
1415float _Distance;
@@ -33,21 +34,40 @@ VaryingsDOF VertDOF(AttributesDefault v)
3334#endif
3435
3536 VaryingsDOF o;
36- #if defined (UNITY_SINGLE_PASS_STEREO)
3737 o.pos = UnityObjectToClipPos (v.vertex);
38+
39+ #if defined (UNITY_SINGLE_PASS_STEREO)
3840 o.uv = UnityStereoScreenSpaceUVAdjust (v.texcoord, _MainTex_ST);
3941 o.uvAlt = UnityStereoScreenSpaceUVAdjust (uvAlt, _MainTex_ST);
4042#else
41- o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
4243 o.uv = v.texcoord;
4344 o.uvAlt = uvAlt;
4445#endif
4546
4647 return o;
4748}
4849
49- // Downsampling, prefiltering and CoC calculation
50- half4 FragPrefilter (VaryingsDOF i) : SV_Target
50+ // Prefilter: CoC calculation, downsampling and premultiplying.
51+
52+ #if defined (PREFILTER_TAA)
53+
54+ // TAA enabled: use MRT to update the history buffer in the same pass.
55+ struct PrefilterOutput
56+ {
57+ half4 base : SV_Target0 ;
58+ half4 history : SV_Target1 ;
59+ };
60+ #define PrefilterSemantics
61+
62+ #else
63+
64+ // No TAA
65+ #define PrefilterOutput half4
66+ #define PrefilterSemantics :SV_Target
67+
68+ #endif
69+
70+ PrefilterOutput FragPrefilter (VaryingsDOF i) PrefilterSemantics
5171{
5272 float3 duv = _MainTex_TexelSize.xyx * float3 (0.5 , 0.5 , -0.5 );
5373
@@ -68,6 +88,12 @@ half4 FragPrefilter(VaryingsDOF i) : SV_Target
6888 float4 cocs = (depths - _Distance) * _LensCoeff / depths;
6989 cocs = clamp (cocs, -_MaxCoC, _MaxCoC);
7090
91+ #if defined (PREFILTER_TAA)
92+ // Get the average with the history to avoid temporal aliasing.
93+ half hcoc = tex2D (_HistoryCoC, i.uv).r;
94+ cocs = lerp (cocs, hcoc, _HistoryWeight);
95+ #endif
96+
7197 // Premultiply CoC to reduce background bleeding.
7298 float4 weights = saturate (abs (cocs) * _RcpMaxCoC);
7399
@@ -87,7 +113,9 @@ half4 FragPrefilter(VaryingsDOF i) : SV_Target
87113 avg /= dot (weights, 1.0 );
88114
89115 // Output CoC = average of CoCs
90- half coc = dot (cocs, 0.25 );
116+ half cocmin = Min4 (cocs);
117+ half cocmax = Max4 (cocs);
118+ half coc = -cocmin > cocmax ? cocmin : cocmax;
91119
92120 // Premultiply CoC again.
93121 avg *= smoothstep (0 , _MainTex_TexelSize.y * 2 , abs (coc));
@@ -96,33 +124,14 @@ half4 FragPrefilter(VaryingsDOF i) : SV_Target
96124 avg = GammaToLinearSpace (avg);
97125#endif
98126
99- return half4 (avg, coc);
100- }
101-
102- // Very simple temporal antialiasing on CoC to reduce jitter (mostly visible on the front plane)
103- struct Output
104- {
105- half4 base : SV_Target0 ;
106- half4 history : SV_Target1 ;
107- };
108-
109- Output FragAntialiasCoC (VaryingsDOF i)
110- {
111- half4 base = tex2D (_MainTex, i.uv);
112- half hCoC = tex2D (_HistoryCoC, i.uv).r;
113- half CoC = base.a;
114- half nCoC = hCoC * CoC < 0.0 ? CoC : (hCoC + CoC) / 2.0 ; // TODO: Smarter CoC AA
115-
116- Output output;
117- output.base = half4 (base.rgb, nCoC);
118- output.history = nCoC.xxxx;
127+ #if defined (PREFILTER_TAA)
128+ PrefilterOutput output;
129+ output.base = half4 (avg, coc);
130+ output.history = coc.xxxx;
119131 return output;
120- }
121-
122- // CoC history clearing
123- half4 FragClearCoCHistory (VaryingsDOF i) : SV_Target
124- {
125- return tex2D (_MainTex, i.uv).aaaa;
132+ #else
133+ return half4 (avg, coc);
134+ #endif
126135}
127136
128137// Bokeh filter with disk-shaped kernels
@@ -187,21 +196,35 @@ half4 FragPostBlur(VaryingsDOF i) : SV_Target
187196{
188197 // 9-tap tent filter
189198 float4 duv = _MainTex_TexelSize.xyxy * float4 (1 , 1 , -1 , 0 );
190- half4 acc;
191199
192- acc = tex2D (_MainTex, i.uv - duv.xy);
193- acc += tex2D (_MainTex, i.uv - duv.wy) * 2 ;
194- acc += tex2D (_MainTex, i.uv - duv.zy);
200+ half4 c0 = tex2D (_MainTex, i.uv - duv.xy);
201+ half4 c1 = tex2D (_MainTex, i.uv - duv.wy);
202+ half4 c2 = tex2D (_MainTex, i.uv - duv.zy);
203+
204+ half4 c3 = tex2D (_MainTex, i.uv + duv.zw);
205+ half4 c4 = tex2D (_MainTex, i.uv );
206+ half4 c5 = tex2D (_MainTex, i.uv + duv.xw);
207+
208+ half4 c6 = tex2D (_MainTex, i.uv + duv.zy);
209+ half4 c7 = tex2D (_MainTex, i.uv + duv.wy);
210+ half4 c8 = tex2D (_MainTex, i.uv + duv.xy);
211+
212+ half4 acc = c0 * 1 + c1 * 2 + c2 * 1 +
213+ c3 * 2 + c4 * 4 + c5 * 2 +
214+ c6 * 1 + c7 * 2 + c8 * 1 ;
215+
216+ half aa =
217+ c0.a * c0.a * 1 + c1.a * c1.a * 2 + c2.a * c2.a * 1 +
218+ c3.a * c3.a * 2 + c4.a * c4.a * 4 + c5.a * c5.a * 2 +
219+ c6.a * c6.a * 1 + c7.a * c7.a * 2 + c8.a * c8.a * 1 ;
195220
196- acc += tex2D (_MainTex, i.uv + duv.zw) * 2 ;
197- acc += tex2D (_MainTex, i.uv ) * 4 ;
198- acc += tex2D (_MainTex, i.uv + duv.xw) * 2 ;
221+ half wb = 1.2 ;
222+ half a = (wb * acc.a - aa) / (wb * 16 - acc.a);
199223
200- acc += tex2D (_MainTex, i.uv + duv.zy);
201- acc += tex2D (_MainTex, i.uv + duv.wy) * 2 ;
202- acc += tex2D (_MainTex, i.uv + duv.xy);
224+ acc /= 16 ;
203225
204- return acc / 16 ;
226+ half3 rgb = acc.rgb * (1 + saturate (acc.a - a));
227+ return half4 (rgb, a);
205228}
206229
207230#endif // __DEPTH_OF_FIELD__
0 commit comments