forked from crosire/reshade-shaders
-
Notifications
You must be signed in to change notification settings - Fork 0
/
LightDoF.fx
251 lines (198 loc) · 7.62 KB
/
LightDoF.fx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
/*
Light Depth of Field by luluco250
Poisson disk blur by spite ported from: https://github.com/spite/Wagner/blob/master/fragment-shaders/poisson-disc-blur-fs.glsl
Why "light"?
Because I wanted a DoF shader that didn't tank my GPU and didn't take rocket science to configure.
Also with delayed auto focus like in ENB.
License: https://creativecommons.org/licenses/by-sa/4.0/
CC BY-SA 4.0
You are free to:
Share — copy and redistribute the material in any medium or format
Adapt — remix, transform, and build upon the material
for any purpose, even commercially.
The licensor cannot revoke these freedoms as long as you follow the license terms.
Under the following terms:
Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made.
You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
ShareAlike — If you remix, transform, or build upon the material,
you must distribute your contributions under the same license as the original.
No additional restrictions — You may not apply legal terms or technological measures
that legally restrict others from doing anything the license permits.
*/
#include "ReShade.fxh"
//user variables//////////////////////////////////////////////////////////////////////////////////
uniform float fLightDoF_Width <
ui_label = "Bokeh Width [Light DoF]";
ui_type = "drag";
ui_min = 1.0;
ui_max = 25.0;
> = 5.0;
uniform float fLightDoF_Amount <
ui_label = "DoF Amount [Light DoF]";
ui_type = "drag";
ui_min = 0.0;
ui_max = 10.0;
> = 10.0;
uniform bool bLightDoF_UseCA <
ui_label = "Use Chromatic Aberration [Light DoF]";
ui_tooltip = "Use color channel shifting.";
> = false;
uniform float2 f2LightDoF_CA <
ui_label = "Chromatic Aberration [Light DoF]";
ui_tooltip = "Shifts color channels.\nFirst value controls far CA, second controls near CA.";
ui_type = "drag";
ui_min = 0.0;
ui_max = 1.0;
> = float2(0.0, 1.0);
uniform bool bLightDoF_AutoFocus <
ui_label = "Use Auto Focus [Light DoF]";
> = true;
uniform float fLightDoF_AutoFocusSpeed <
ui_label = "Auto Focus Speed [Light DoF]";
ui_type = "drag";
ui_min = 0.001;
ui_max = 1.0;
> = 0.1;
uniform bool bLightDoF_UseMouseFocus <
ui_label = "Use Mouse for Auto Focus Center [Light DoF]";
ui_tooltip = "Use the mouse position as the auto focus center";
> = false;
uniform float2 f2Bokeh_AutoFocusCenter <
ui_label = "Auto Focus Center [Light DoF]";
ui_tooltip = "Target for auto focus.\nFirst value is horizontal: Left<->Right\nSecond value is vertical: Up<->Down";
ui_type = "drag";
ui_min = 0.0;
ui_max = 1.0;
> = float2(0.5, 0.5);
uniform float fLightDoF_ManualFocus <
ui_label = "Manual Focus [Light DoF]";
ui_type = "drag";
ui_min = 0.0;
ui_max = 1.0;
> = 0.0;
//system variables////////////////////////////////////////////////////////////////////////////////
//internal variable that holds the current mouse position
uniform float2 f2LightDoF_MouseCoord <source="mousepoint";>;
//textures////////////////////////////////////////////////////////////////////////////////////////
/*
For those curious...
Two textures are needed in order to delay focus.
I just lerp between them by a speed.
*/
//texture for saving the current frame's focus
texture tFocus { Format=R16F; };
//texture for saving the last frame's focus
texture tLastFocus { Format=R16F; };
//samplers////////////////////////////////////////////////////////////////////////////////////////
//sampler for the current frame's focus
sampler sFocus { Texture=tFocus; };
//sampler for the last frame's focus
sampler sLastFocus { Texture=tLastFocus; };
//functions///////////////////////////////////////////////////////////////////////////////////////
//interpret the focus textures and separate far/near focuses
float getFocus(float2 coord, bool farOrNear) {
float depth = ReShade::GetLinearizedDepth(coord);
depth -= bLightDoF_AutoFocus ? tex2D(sFocus, 0).x : fLightDoF_ManualFocus;
if (farOrNear) {
depth = saturate(-depth * fLightDoF_Amount);
}
else {
depth = saturate(depth * fLightDoF_Amount);
}
return depth;
}
//helper function for poisson-disk blur
float2 rot2D(float2 pos, float angle) {
float2 source = float2(sin(angle), cos(angle));
return float2(dot(pos, float2(source.y, -source.x)), dot(pos, source));
}
//poisson-disk blur
float3 poisson(sampler sp, float2 uv, float farOrNear, float CA) {
float2 poisson[12];
poisson[0] = float2(-.326,-.406);
poisson[1] = float2(-.840,-.074);
poisson[2] = float2(-.696, .457);
poisson[3] = float2(-.203, .621);
poisson[4] = float2( .962,-.195);
poisson[5] = float2( .473,-.480);
poisson[6] = float2( .519, .767);
poisson[7] = float2( .185,-.893);
poisson[8] = float2( .507, .064);
poisson[9] = float2( .896, .412);
poisson[10] = float2(-.322,-.933);
poisson[11] = float2(-.792,-.598);
float3 col = 0;
float random = frac(sin(dot(uv, float2(12.9898, 78.233))) * 43758.5453);
float4 basis = float4(rot2D(float2(1, 0), random), rot2D(float2(0, 1), random));
[unroll]
for (int i = 0; i < 12; ++i) {
float2 offset = poisson[i];
offset = float2(dot(offset, basis.xz), dot(offset, basis.yw));
if (bLightDoF_UseCA) {
float2 rCoord = uv + offset * ReShade::PixelSize * fLightDoF_Width * (1.0 + CA);
float2 gCoord = uv + offset * ReShade::PixelSize * fLightDoF_Width * (1.0 + CA * 0.5);
float2 bCoord = uv + offset * ReShade::PixelSize * fLightDoF_Width;
rCoord = lerp(uv, rCoord, getFocus(rCoord, farOrNear));
gCoord = lerp(uv, gCoord, getFocus(gCoord, farOrNear));
bCoord = lerp(uv, bCoord, getFocus(bCoord, farOrNear));
col += float3(
tex2Dlod(sp, float4(rCoord, 0, 0)).r,
tex2Dlod(sp, float4(gCoord, 0, 0)).g,
tex2Dlod(sp, float4(bCoord, 0, 0)).b
);
}
else {
float2 coord = uv + offset * ReShade::PixelSize * fLightDoF_Width;
coord = lerp(uv, coord, getFocus(coord, farOrNear));
col += tex2Dlod(sp, float4(coord, 0, 0)).rgb;
}
}
return col * 0.083;
}
//shaders/////////////////////////////////////////////////////////////////////////////////////////
//far blur shader
float3 Far(float4 pos : SV_Position, float2 uv : TEXCOORD0) : SV_Target {
return poisson(ReShade::BackBuffer, uv, false, f2LightDoF_CA.x);
}
//near blur shader
float3 Near(float4 pos : SV_Position, float2 uv : TEXCOORD0) : SV_Target {
return poisson(ReShade::BackBuffer, uv, true, f2LightDoF_CA.y);
}
//shader to get the focus, kinda like center of confusion but less complicated
float GetFocus(float4 pos : SV_Position, float2 uv : TEXCOORD0) : SV_Target {
float2 linearMouse = f2LightDoF_MouseCoord * ReShade::PixelSize; //linearize the mouse position
float2 focus = bLightDoF_UseMouseFocus ? linearMouse : f2Bokeh_AutoFocusCenter;
return lerp(tex2D(sLastFocus, 0).x, ReShade::GetLinearizedDepth(focus), fLightDoF_AutoFocusSpeed);
}
//shader for saving this frame's focus to lerp with the next one's
float SaveFocus(float4 pos : SV_Position, float2 uv : TEXCOORD0) : SV_Target {
return tex2D(sFocus, 0).x;
}
//techniques//////////////////////////////////////////////////////////////////////////////////////
//this technique is dedicated for auto focus, so you don't need it if you're not using auto-focus :)
technique LightDoF_AutoFocus {
pass GetFocus {
VertexShader=PostProcessVS;
PixelShader=GetFocus;
RenderTarget=tFocus;
}
pass SaveFocus {
VertexShader=PostProcessVS;
PixelShader=SaveFocus;
RenderTarget=tLastFocus;
}
}
//technique for far blur
technique LightDoF_Far {
pass Far {
VertexShader=PostProcessVS;
PixelShader=Far;
}
}
//technique for near blur
technique LightDoF_Near {
pass Near {
VertexShader=PostProcessVS;
PixelShader=Near;
}
}