1+ //===================================================================================================================
2+ #include "Pirate_Lumachroma.fxh"
3+ //===================================================================================================================
4+ uniform float DOF_RADIUS <
5+ ui_label = "DOF - Radius" ;
6+ ui_tooltip = "1.0 = Pixel perfect radius. Values above 1.0 might create artifacts." ;
7+ ui_type = "drag" ;
8+ ui_min = 0.0 ; ui_max = 10.0 ;
9+ > = 1.0 ;
10+ uniform float DOF_NEAR_STRENGTH <
11+ ui_label = "DOF - Near Blur Strength" ;
12+ ui_tooltip = "Strength of the blur between the camera and focal point." ;
13+ ui_type = "drag" ;
14+ ui_min = 0.0 ; ui_max = 2.0 ;
15+ > = 0.5 ;
16+ uniform float DOF_FAR_STRENGTH <
17+ ui_label = "DOF - Far Blur Strength" ;
18+ ui_tooltip = "Strength of the blur past the focal point." ;
19+ ui_type = "drag" ;
20+ ui_min = 0.0 ; ui_max = 2.0 ;
21+ > = 1.0 ;
22+ uniform float DOF_FOCAL_RANGE <
23+ ui_label = "DOF - Focal Range" ;
24+ ui_tooltip = "Along with Focal Curve, this controls how much will be in focus" ;
25+ ui_type = "drag" ;
26+ ui_min = 0.0 ; ui_max = 1.0 ;
27+ > = 0.0 ;
28+ uniform float DOF_FOCAL_CURVE <
29+ ui_label = "DOF - Focal Curve" ;
30+ ui_tooltip = "1.0 = No curve. Values above this put more things in focus, lower values create a macro effect." ;
31+ ui_type = "drag" ;
32+ ui_min = 0.0 ; ui_max = 2.0 ;
33+ > = 1.0 ;
34+ uniform float DOF_HYPERFOCAL <
35+ ui_label = "DOF - Hyperfocal Range" ;
36+ ui_tooltip = "When the focus goes past this point, everything in the distance is focused." ;
37+ ui_type = "drag" ;
38+ ui_min = 0.0 ; ui_max = 1.0 ;
39+ > = 0.9 ;
40+ uniform float DOF_BLEND <
41+ ui_label = "DOF - Blending Curve" ;
42+ ui_tooltip = "Controls the blending curve between the DOF texture and original image. Use this to avoid artifacts where the DOF begins" ;
43+ ui_type = "drag" ;
44+ ui_min = 0.0 ; ui_max = 1.0 ;
45+ > = 0.3 ;
46+ uniform float DOF_BOKEH_CONTRAST <
47+ ui_label = "DOF - Bokeh - Contrast" ;
48+ ui_tooltip = "Contrast of bokeh and blurred areas. Use very small values." ;
49+ ui_type = "drag" ;
50+ ui_min = -1.0 ; ui_max = 1.0 ;
51+ > = 0.04 ;
52+ uniform float DOF_BOKEH_BIAS <
53+ ui_label = "DOF - Bokeh - Bias" ;
54+ ui_tooltip = "0.0 = No Bokeh, 1.0 = Natural bokeh, 2.0 = Forced bokeh." ;
55+ ui_type = "drag" ;
56+ ui_min = 0.0 ; ui_max = 2.0 ;
57+ > = 1.0 ;
58+ uniform float DOF_MANUAL_FOCUS <
59+ ui_label = "DOF - Manual Focus" ;
60+ ui_tooltip = "Only works then manual focus is on." ;
61+ ui_type = "drag" ;
62+ ui_min = 0.0 ; ui_max = 1.0 ;
63+ > = 0.5 ;
64+ uniform float DOF_FOCUS_X <
65+ ui_label = "DOF - Auto Focus X" ;
66+ ui_tooltip = "Horizontal point in the screen to focus. 0.5 = middle" ;
67+ ui_type = "drag" ;
68+ ui_min = 0.0 ; ui_max = 1.0 ;
69+ > = 0.5 ;
70+ uniform float DOF_FOCUS_Y <
71+ ui_label = "DOF - Auto Focus Y" ;
72+ ui_tooltip = "Vertical point in the screen to focus. 0.5 = middle" ;
73+ ui_type = "drag" ;
74+ ui_min = 0.0 ; ui_max = 1.0 ;
75+ > = 0.5 ;
76+ uniform float DOF_FOCUS_SPREAD <
77+ ui_label = "DOF - Auto Focus Spread" ;
78+ ui_tooltip = "Focus takes the average of 5 points, this is how far away they are. Use low values for a precise focus." ;
79+ ui_type = "drag" ;
80+ ui_min = 0.0 ; ui_max = 0.5 ;
81+ > = 0.05 ;
82+ uniform float DOF_FOCUS_SPEED <
83+ ui_label = "DOF - Auto Focus Speed" ;
84+ ui_tooltip = "How fast focus changes happen. 1.0 = One second. Values above 1.0 are faster, bellow are slower." ;
85+ ui_type = "drag" ;
86+ ui_min = 0.0 ; ui_max = 10.0 ;
87+ > = 0.5 ;
88+ uniform float DOF_SCRATCHES_STRENGTH <
89+ ui_label = "DOF - Lens Scratches Strength" ;
90+ ui_tooltip = "How strong is the scratch effect. Low values are better as this shows up a lot in bright scenes." ;
91+ ui_type = "drag" ;
92+ ui_min = 0.0 ; ui_max = 1.0 ;
93+ > = 0.15 ;
94+ uniform int DOF_DEBUG <
95+ ui_label = "DOG - Debug - Show Focus" ;
96+ ui_tooltip = "Black is in focus, red is blurred." ;
97+ ui_type = "combo" ;
98+ ui_items = "No\0 Yes\0 " ;
99+ > = 0 ;
100+ //===================================================================================================================
101+ #if (DOF_USE_MANUAL_FOCUS == 0 )
102+ texture2D TexF1 {Width = 1 ; Height = 1 ; Format = R16F;};
103+ sampler2D SamplerFocalPoint {Texture = TexF1; MinFilter = LINEAR; MagFilter = LINEAR; MipFilter = LINEAR; AddressU = Clamp ; AddressV = Clamp ;};
104+ texture2D TexF2 {Width = 1 ; Height = 1 ; Format = R16F;};
105+ sampler2D SamplerFCopy {Texture = TexF2; MinFilter = LINEAR; MagFilter = LINEAR; MipFilter = LINEAR; AddressU = Clamp ; AddressV = Clamp ;};
106+ #endif
107+
108+ texture2D TexFocus {Width = BUFFER_WIDTH * DOF_TEXTURE_QUALITY; Height = BUFFER_HEIGHT * DOF_TEXTURE_QUALITY; Format = R8;};
109+ sampler2D SamplerFocus {Texture = TexFocus; MinFilter = LINEAR; MagFilter = LINEAR; MipFilter = LINEAR; AddressU = Clamp ; AddressV = Clamp ;};
110+
111+ texture2D TexDOF1 {Width = BUFFER_WIDTH * DOF_TEXTURE_QUALITY; Height = BUFFER_HEIGHT * DOF_TEXTURE_QUALITY; Format = RGBA8;};
112+ sampler2D SamplerDOF1 {Texture = TexDOF1; MinFilter = LINEAR; MagFilter = LINEAR; MipFilter = LINEAR; AddressU = Clamp ; AddressV = Clamp ;};
113+ texture2D TexDOF2 {Width = BUFFER_WIDTH * DOF_TEXTURE_QUALITY; Height = BUFFER_HEIGHT * DOF_TEXTURE_QUALITY; Format = RGBA8;};
114+ sampler2D SamplerDOF2 {Texture = TexDOF2; MinFilter = LINEAR; MagFilter = LINEAR; MipFilter = LINEAR; AddressU = Clamp ; AddressV = Clamp ;};
115+
116+ #if DOF_USE_LENS_SCRATCH
117+ texture2D TexLensScratches <source = DOF_SCRATCH_FILENAME;> { Width = DOF_SCRATCH_WIDTH; Height = DOF_SCRATCH_HEIGHT; Format = RGBA8;};
118+ sampler2D SamplerLensScratches {Texture = TexLensScratches; MinFilter = LINEAR; MagFilter = LINEAR; MipFilter = LINEAR; AddressU = Clamp ; AddressV = Clamp ;};
119+ #endif
120+ //===================================================================================================================
121+ float2 Rotate60 (float2 v) {
122+ #define sin60 0.86602540378f
123+ float x = v.x * 0.5 - v.y * sin60;
124+ float y = v.x * sin60 + v.y * 0.5 ;
125+ return float2 (x, y);
126+ }
127+
128+ float2 Rotate120 (float2 v) {
129+ #define sin120 0.58061118421f
130+ float x = v.x * -0.5 - v.y * sin120;
131+ float y = v.x * sin120 + v.y * -0.5 ;
132+ return float2 (x, y);
133+ }
134+
135+ float2 Rotate (float2 v, float angle) {
136+ float x = v.x * cos (angle) - v.y * sin (angle);
137+ float y = v.x * sin (angle) + v.y * cos (angle);
138+ return float2 (x, y);
139+ }
140+
141+ float GetFocus (float d) {
142+ #if DOF_USE_MANUAL_FOCUS
143+ float focus = min (DOF_HYPERFOCAL, DOF_MANUAL_FOCUS);
144+ #else
145+ float focus = min (DOF_HYPERFOCAL, tex2D (SamplerFocalPoint, 0.5 ).x);
146+ #endif
147+ float res;
148+ if (d > focus) {
149+ res = smoothstep (focus, 1.0 , d) * DOF_FAR_STRENGTH;
150+ res = lerp (res, 0.0 , focus / DOF_HYPERFOCAL);
151+ } else if (d < focus) {
152+ res = smoothstep (focus, 0.0 , d) * DOF_NEAR_STRENGTH;
153+ } else {
154+ res = 0.0 ;
155+ }
156+
157+ res = pow (smoothstep (DOF_FOCAL_RANGE, 1.0 , res), DOF_FOCAL_CURVE);
158+
159+ return res;
160+ }
161+ float4 GenDOF (float2 texcoord, float2 v, sampler2D samp)
162+ {
163+ float4 origcolor = tex2D (samp, texcoord);
164+ float4 res = origcolor;
165+ res.w = LumaChroma (origcolor).w;
166+
167+ float bluramount = tex2D (SamplerFocus, texcoord).r;
168+ if (bluramount == 0 ) return origcolor;
169+ v = Rotate (v, tex2D (SamplerFocalPoint, 0.5 ).x * 2.0 );
170+ res.w *= bluramount;
171+ float4 bokeh = res;
172+ res.rgb *= res.w;
173+
174+ float discradius = bluramount * DOF_RADIUS;
175+ if (discradius < PixelSize.x / DOF_TEXTURE_QUALITY) return origcolor;
176+
177+ float2 calcv = v * discradius * PixelSize / DOF_TEXTURE_QUALITY;
178+
179+ for (int i=1 ; i <= DOF_TAPS; i++)
180+ {
181+
182+ // ++++
183+ float2 tapcoord = texcoord + calcv * i;
184+
185+ float4 tap = tex2D (samp, tapcoord);
186+
187+ float luma = LumaChroma (tap).w;
188+
189+ tap.w = tex2D (SamplerFocus, tapcoord).r * luma;
190+
191+ if (tap.w > bokeh.w) {
192+ bokeh.w = tap.w;
193+ bokeh.rgb = tap.rgb;
194+ }
195+
196+ res.rgb += tap.rgb * tap.w;
197+ res.w += tap.w;
198+
199+ // ----
200+ tapcoord = texcoord - calcv * i;
201+
202+ tap = tex2D (samp, tapcoord);
203+
204+ luma = LumaChroma (tap).w;
205+
206+ tap.w = tex2D (SamplerFocus, tapcoord).r * luma;
207+
208+ if (tap.w > bokeh.w) {
209+ bokeh.w = tap.w;
210+ bokeh.rgb = tap.rgb;
211+ }
212+
213+ res.rgb += tap.rgb * tap.w;
214+ res.w += tap.w;
215+
216+ }
217+
218+ res.rgb /= res.w;
219+ res.rgb = lerp (res.rgb, bokeh.rgb, saturate (bokeh.w * DOF_BOKEH_BIAS));
220+ res.w = 1.0 ;
221+ float4 lc = LumaChroma (res);
222+ lc.w = pow (lc.w, 1.0 + DOF_BOKEH_CONTRAST / 10.0 );
223+ res.rgb = lc.rgb * lc.w;
224+
225+ return res;
226+ }
227+ //===================================================================================================================
228+ float PS_GetFocus (float4 vpos : SV_Position , float2 texcoord : TEXCOORD ) : COLOR
229+ {
230+ float lastfocus = tex2D (SamplerFCopy, 0.5 ).x;
231+ float res;
232+
233+ const float2 offset[5 ]=
234+ {
235+ float2 (0.0 , 0.0 ),
236+ float2 (0.0 , -1.0 ),
237+ float2 (0.0 , 1.0 ),
238+ float2 (1.0 , 0.0 ),
239+ float2 (-1.0 , 0.0 )
240+ };
241+ for (int i=0 ; i < 5 ; i++)
242+ {
243+ res += tex2D (SamplerND, float2 (DOF_FOCUS_X, DOF_FOCUS_Y) + offset[i] * DOF_FOCUS_SPREAD).w;
244+ }
245+ res /= 5 ;
246+ res = lerp (lastfocus, res, DOF_FOCUS_SPEED * Frametime / 1000.0 );
247+ return res;
248+ }
249+ float PS_CopyFocus (float4 vpos : SV_Position , float2 texcoord : TEXCOORD ) : COLOR
250+ {
251+ return tex2D (SamplerFocalPoint, 0.5 ).x;
252+ }
253+
254+ float PS_GenFocus (float4 vpos : SV_Position , float2 texcoord : TEXCOORD ) : COLOR
255+ {
256+ return GetFocus (tex2D (SamplerND, texcoord).w);
257+ }
258+ float4 PS_DOF1 (float4 vpos : SV_Position , float2 texcoord : TEXCOORD ) : COLOR
259+ {
260+ return GenDOF (texcoord, float2 (1.0 , 0.0 ), SamplerColor);
261+ }
262+ float4 PS_DOF2 (float4 vpos : SV_Position , float2 texcoord : TEXCOORD ) : COLOR
263+ {
264+ return GenDOF (texcoord, Rotate60 (float2 (1.0 , 0.0 )), SamplerDOF1);
265+ }
266+ float4 PS_DOF3 (float4 vpos : SV_Position , float2 texcoord : TEXCOORD ) : COLOR
267+ {
268+ return GenDOF (texcoord, Rotate120 (float2 (1.0 , 0.0 )), SamplerDOF2);
269+ }
270+ float4 PS_DOFCombine (float4 vpos : SV_Position , float2 texcoord : TEXCOORD ) : COLOR
271+ {
272+ float bluramount = tex2D (SamplerFocus, texcoord).r;
273+ float4 orig = tex2D (SamplerColor, texcoord);
274+
275+ float4 res;
276+ if (bluramount == 0.0 ) {
277+ res = orig;
278+ } else {
279+ res = lerp (orig, tex2D (SamplerDOF1, texcoord), smoothstep (0.0 , DOF_BLEND, bluramount));
280+ #if DOF_USE_LENS_SCRATCH
281+ res.rgb = lerp (res.rgb, BlendColorDodge (res.rgb, tex2D (SamplerLensScratches, texcoord).rgb), bluramount * LumaChroma (res).w * DOF_SCRATCHES_STRENGTH);
282+ #endif
283+ }
284+ if (DOF_DEBUG) res = tex2D (SamplerFocus, texcoord);
285+ return res;
286+ }
287+ //===================================================================================================================
288+ technique Pirate_DOF
289+ {
290+ pass GetFocus
291+ {
292+ VertexShader = VS_PostProcess;
293+ PixelShader = PS_GetFocus;
294+ RenderTarget = TexF1;
295+ }
296+ pass CopyFocus
297+ {
298+ VertexShader = VS_PostProcess;
299+ PixelShader = PS_CopyFocus;
300+ RenderTarget = TexF2;
301+ }
302+ pass FocalRange
303+ {
304+ VertexShader = VS_PostProcess;
305+ PixelShader = PS_GenFocus;
306+ RenderTarget = TexFocus;
307+ }
308+ pass DOF1
309+ {
310+ VertexShader = VS_PostProcess;
311+ PixelShader = PS_DOF1;
312+ RenderTarget = TexDOF1;
313+ }
314+ pass DOF2
315+ {
316+ VertexShader = VS_PostProcess;
317+ PixelShader = PS_DOF2;
318+ RenderTarget = TexDOF2;
319+ }
320+ pass DOF3
321+ {
322+ VertexShader = VS_PostProcess;
323+ PixelShader = PS_DOF3;
324+ RenderTarget = TexDOF1;
325+ }
326+ pass Combine
327+ {
328+ VertexShader = VS_PostProcess;
329+ PixelShader = PS_DOFCombine;
330+ }
331+ }
0 commit comments