├── .gitignore
├── Lens.sln
├── Lens
├── Lens.aps
├── Lens.rc
├── Lens.vcxproj
├── Lens.vcxproj.filters
├── aperture.hlsl
├── common.hlsl
├── copy.hlsl
├── directx.ico
├── dust.bmp
├── fft.h
├── fft.hlsl
├── lens.cpp
├── lens.hlsl
├── post.hlsl
├── ray_trace.h
├── resource.h
├── starburst.hlsl
└── visualization.hlsl
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | Lens.VC.VC.opendb
2 | Lens.VC.db
3 | Lens/Release/Lens.log
4 | Lens/Release/Lens.res
5 | Lens/Release/Lens.tlog/CL.command.1.tlog
6 | Lens/Release/Lens.tlog/CL.read.1.tlog
7 | Lens/Release/Lens.tlog/CL.write.1.tlog
8 | Lens/Release/Lens.tlog/FXC.command.1.tlog
9 | Lens/Release/Lens.tlog/Lens.lastbuildstate
10 | Lens/Release/Lens.tlog/Lens.write.1u.tlog
11 | Lens/Release/Lens.tlog/fxc.read.1.tlog
12 | Lens/Release/Lens.tlog/fxc.write.1.tlog
13 | Lens/Release/Lens.tlog/link.command.1.tlog
14 | Lens/Release/Lens.tlog/link.read.1.tlog
15 | Lens/Release/Lens.tlog/link.write.1.tlog
16 | Lens/Release/Lens.tlog/rc.command.1.tlog
17 | Lens/Release/Lens.tlog/rc.read.1.tlog
18 | Lens/Release/Lens.tlog/rc.write.1.tlog
19 | Lens/Release/lens.obj
20 | Lens/Release/vc140.pdb
21 | Release/Lens.exe
22 | Release/Lens.iobj
23 | Release/Lens.ipdb
24 | Release/Lens.pdb
25 | Release/lens_PS.cso
26 | Release/lens_VS.cso
27 | Debug/Lens.exe
28 | Debug/Lens.ilk
29 | Debug/Lens.pdb
30 | Debug/lens_PS.cso
31 | Debug/lens_VS.cso
32 | Lens/Debug/Lens.log
33 | Lens/Debug/Lens.res
34 | Lens/Debug/Lens.tlog/CL.command.1.tlog
35 | Lens/Debug/Lens.tlog/CL.read.1.tlog
36 | Lens/Debug/Lens.tlog/CL.write.1.tlog
37 | Lens/Debug/Lens.tlog/FXC.command.1.tlog
38 | Lens/Debug/Lens.tlog/Lens.lastbuildstate
39 | Lens/Debug/Lens.tlog/Lens.write.1u.tlog
40 | Lens/Debug/Lens.tlog/fxc.read.1.tlog
41 | Lens/Debug/Lens.tlog/fxc.write.1.tlog
42 | Lens/Debug/Lens.tlog/link.command.1.tlog
43 | Lens/Debug/Lens.tlog/link.read.1.tlog
44 | Lens/Debug/Lens.tlog/link.write.1.tlog
45 | Lens/Debug/Lens.tlog/rc.command.1.tlog
46 | Lens/Debug/Lens.tlog/rc.read.1.tlog
47 | Lens/Debug/Lens.tlog/rc.write.1.tlog
48 | Lens/Debug/lens.obj
49 | Lens/Debug/vc140.idb
50 | Lens/Debug/vc140.pdb
51 | .vs/Lens/v14/.suo
52 | Lens/x64/Release/Lens.log
53 | Lens/x64/Release/Lens.res
54 | Lens/x64/Release/Lens.tlog/CL.command.1.tlog
55 | Lens/x64/Release/Lens.tlog/CL.read.1.tlog
56 | Lens/x64/Release/Lens.tlog/CL.write.1.tlog
57 | Lens/x64/Release/Lens.tlog/FXC.command.1.tlog
58 | Lens/x64/Release/Lens.tlog/Lens.lastbuildstate
59 | Lens/x64/Release/Lens.tlog/Lens.write.1u.tlog
60 | Lens/x64/Release/Lens.tlog/fxc.read.1.tlog
61 | Lens/x64/Release/Lens.tlog/fxc.write.1.tlog
62 | Lens/x64/Release/Lens.tlog/link.command.1.tlog
63 | Lens/x64/Release/Lens.tlog/link.read.1.tlog
64 | Lens/x64/Release/Lens.tlog/link.write.1.tlog
65 | Lens/x64/Release/Lens.tlog/rc.command.1.tlog
66 | Lens/x64/Release/Lens.tlog/rc.read.1.tlog
67 | Lens/x64/Release/Lens.tlog/rc.write.1.tlog
68 | Lens/x64/Release/lens.obj
69 | Lens/x64/Release/vc140.pdb
70 | x64/Release/Lens.exe
71 | x64/Release/Lens.iobj
72 | x64/Release/Lens.ipdb
73 | x64/Release/Lens.pdb
74 | x64/Release/lens_PS.cso
75 | x64/Release/lens_VS.cso
76 | Lens/x64/Debug/Lens.log
77 | Lens/x64/Debug/Lens.res
78 | Lens/x64/Debug/Lens.tlog/CL.command.1.tlog
79 | Lens/x64/Debug/Lens.tlog/CL.read.1.tlog
80 | Lens/x64/Debug/Lens.tlog/CL.write.1.tlog
81 | Lens/x64/Debug/Lens.tlog/FXC.command.1.tlog
82 | Lens/x64/Debug/Lens.tlog/Lens.lastbuildstate
83 | Lens/x64/Debug/Lens.tlog/Lens.write.1u.tlog
84 | Lens/x64/Debug/Lens.tlog/fxc.read.1.tlog
85 | Lens/x64/Debug/Lens.tlog/fxc.write.1.tlog
86 | Lens/x64/Debug/Lens.tlog/link.command.1.tlog
87 | Lens/x64/Debug/Lens.tlog/link.read.1.tlog
88 | Lens/x64/Debug/Lens.tlog/link.write.1.tlog
89 | Lens/x64/Debug/Lens.tlog/rc.command.1.tlog
90 | Lens/x64/Debug/Lens.tlog/rc.read.1.tlog
91 | Lens/x64/Debug/Lens.tlog/rc.write.1.tlog
92 | Lens/x64/Debug/lens.obj
93 | Lens/x64/Debug/vc140.pdb
94 | x64/Debug/Lens.exe
95 | x64/Debug/Lens.ilk
96 | x64/Debug/Lens.pdb
97 | x64/Debug/lens_PS.cso
98 | x64/Debug/lens_VS.cso
99 |
--------------------------------------------------------------------------------
/Lens.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25420.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Lens", "Lens\Lens.vcxproj", "{28877253-3120-4098-86B8-BAAC1C0AF240}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Win32 = Debug|Win32
11 | Debug|x64 = Debug|x64
12 | Profile|Win32 = Profile|Win32
13 | Profile|x64 = Profile|x64
14 | Release|Win32 = Release|Win32
15 | Release|x64 = Release|x64
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {28877253-3120-4098-86B8-BAAC1C0AF240}.Debug|Win32.ActiveCfg = Debug|Win32
19 | {28877253-3120-4098-86B8-BAAC1C0AF240}.Debug|Win32.Build.0 = Debug|Win32
20 | {28877253-3120-4098-86B8-BAAC1C0AF240}.Debug|Win32.Deploy.0 = Debug|Win32
21 | {28877253-3120-4098-86B8-BAAC1C0AF240}.Debug|x64.ActiveCfg = Debug|x64
22 | {28877253-3120-4098-86B8-BAAC1C0AF240}.Debug|x64.Build.0 = Debug|x64
23 | {28877253-3120-4098-86B8-BAAC1C0AF240}.Debug|x64.Deploy.0 = Debug|x64
24 | {28877253-3120-4098-86B8-BAAC1C0AF240}.Profile|Win32.ActiveCfg = Profile|Win32
25 | {28877253-3120-4098-86B8-BAAC1C0AF240}.Profile|Win32.Build.0 = Profile|Win32
26 | {28877253-3120-4098-86B8-BAAC1C0AF240}.Profile|Win32.Deploy.0 = Profile|Win32
27 | {28877253-3120-4098-86B8-BAAC1C0AF240}.Profile|x64.ActiveCfg = Profile|x64
28 | {28877253-3120-4098-86B8-BAAC1C0AF240}.Profile|x64.Build.0 = Profile|x64
29 | {28877253-3120-4098-86B8-BAAC1C0AF240}.Profile|x64.Deploy.0 = Profile|x64
30 | {28877253-3120-4098-86B8-BAAC1C0AF240}.Release|Win32.ActiveCfg = Release|Win32
31 | {28877253-3120-4098-86B8-BAAC1C0AF240}.Release|Win32.Build.0 = Release|Win32
32 | {28877253-3120-4098-86B8-BAAC1C0AF240}.Release|Win32.Deploy.0 = Release|Win32
33 | {28877253-3120-4098-86B8-BAAC1C0AF240}.Release|x64.ActiveCfg = Release|x64
34 | {28877253-3120-4098-86B8-BAAC1C0AF240}.Release|x64.Build.0 = Release|x64
35 | {28877253-3120-4098-86B8-BAAC1C0AF240}.Release|x64.Deploy.0 = Release|x64
36 | EndGlobalSection
37 | GlobalSection(SolutionProperties) = preSolution
38 | HideSolutionNode = FALSE
39 | EndGlobalSection
40 | EndGlobal
41 |
--------------------------------------------------------------------------------
/Lens/Lens.aps:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/greje656/PhysicallyBasedLensFlare/488a8cfb4b18af3f3f43b8122bf9a79605dd782b/Lens/Lens.aps
--------------------------------------------------------------------------------
/Lens/Lens.rc:
--------------------------------------------------------------------------------
1 | // Microsoft Visual C++ generated resource script.
2 | //
3 | #include "resource.h"
4 |
5 | #define APSTUDIO_READONLY_SYMBOLS
6 | /////////////////////////////////////////////////////////////////////////////
7 | //
8 | // Generated from the TEXTINCLUDE 2 resource.
9 | //
10 | #define APSTUDIO_HIDDEN_SYMBOLS
11 | #include "windows.h"
12 | #undef APSTUDIO_HIDDEN_SYMBOLS
13 |
14 | /////////////////////////////////////////////////////////////////////////////
15 | #undef APSTUDIO_READONLY_SYMBOLS
16 |
17 | /////////////////////////////////////////////////////////////////////////////
18 | // English (United States) resources
19 |
20 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
21 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
22 | #pragma code_page(1252)
23 |
24 | /////////////////////////////////////////////////////////////////////////////
25 | //
26 | // Icon
27 | //
28 |
29 | // Icon with lowest ID value placed first to ensure application icon
30 | // remains consistent on all systems.
31 | IDI_TUTORIAL1 ICON "directx.ico"
32 |
33 |
34 | /////////////////////////////////////////////////////////////////////////////
35 | //
36 | // Menu
37 | //
38 |
39 | IDC_TUTORIAL1 MENU
40 | BEGIN
41 | POPUP "&File"
42 | BEGIN
43 | MENUITEM "E&xit", IDM_EXIT
44 | END
45 | POPUP "&Help"
46 | BEGIN
47 | MENUITEM "&About ...", IDM_ABOUT
48 | END
49 | END
50 |
51 |
52 | /////////////////////////////////////////////////////////////////////////////
53 | //
54 | // Accelerator
55 | //
56 |
57 | IDC_TUTORIAL1 ACCELERATORS
58 | BEGIN
59 | "?", IDM_ABOUT, ASCII, ALT
60 | "/", IDM_ABOUT, ASCII, ALT
61 | END
62 |
63 |
64 | /////////////////////////////////////////////////////////////////////////////
65 | //
66 | // Dialog
67 | //
68 |
69 | IDD_ABOUTBOX DIALOG 22, 17, 230, 75
70 | STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
71 | CAPTION "About"
72 | FONT 8, "System"
73 | BEGIN
74 | ICON IDI_TUTORIAL1,IDC_MYICON,14,9,16,16
75 | LTEXT "Tutorial02 Version 1.0",IDC_STATIC,49,10,119,8,SS_NOPREFIX
76 | LTEXT "Copyright (c) Microsoft Corporation. All rights reserved.",IDC_STATIC,49,20,119,8
77 | DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP
78 | END
79 |
80 |
81 | #ifdef APSTUDIO_INVOKED
82 | /////////////////////////////////////////////////////////////////////////////
83 | //
84 | // TEXTINCLUDE
85 | //
86 |
87 | 1 TEXTINCLUDE
88 | BEGIN
89 | "resource.h\0"
90 | END
91 |
92 | 2 TEXTINCLUDE
93 | BEGIN
94 | "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
95 | "#include ""windows.h""\r\n"
96 | "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
97 | "\0"
98 | END
99 |
100 | 3 TEXTINCLUDE
101 | BEGIN
102 | "\r\n"
103 | "\0"
104 | END
105 |
106 | #endif // APSTUDIO_INVOKED
107 |
108 |
109 | /////////////////////////////////////////////////////////////////////////////
110 | //
111 | // Bitmap
112 | //
113 |
114 | IDB_BITMAP1 BITMAP "dust.bmp"
115 |
116 |
117 | /////////////////////////////////////////////////////////////////////////////
118 | //
119 | // String Table
120 | //
121 |
122 | STRINGTABLE
123 | BEGIN
124 | IDS_APP_TITLE "Tutorial02"
125 | IDC_TUTORIAL1 "Tutorial02"
126 | END
127 |
128 | #endif // English (United States) resources
129 | /////////////////////////////////////////////////////////////////////////////
130 |
131 |
132 |
133 | #ifndef APSTUDIO_INVOKED
134 | /////////////////////////////////////////////////////////////////////////////
135 | //
136 | // Generated from the TEXTINCLUDE 3 resource.
137 | //
138 |
139 |
140 | /////////////////////////////////////////////////////////////////////////////
141 | #endif // not APSTUDIO_INVOKED
142 |
143 |
--------------------------------------------------------------------------------
/Lens/Lens.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Debug
10 | x64
11 |
12 |
13 | Profile
14 | Win32
15 |
16 |
17 | Profile
18 | x64
19 |
20 |
21 | Release
22 | Win32
23 |
24 |
25 | Release
26 | x64
27 |
28 |
29 |
30 | Lens
31 | {28877253-3120-4098-86B8-BAAC1C0AF240}
32 | Lens
33 | Win32Proj
34 |
35 |
36 |
37 | Application
38 | Unicode
39 | v140
40 |
41 |
42 | Application
43 | Unicode
44 | v140
45 |
46 |
47 | Application
48 | true
49 | Unicode
50 | v140
51 |
52 |
53 | Application
54 | true
55 | Unicode
56 | v140
57 |
58 |
59 | Application
60 | true
61 | Unicode
62 | v140
63 |
64 |
65 | Application
66 | true
67 | Unicode
68 | v140
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 | true
93 | true
94 |
95 |
96 | true
97 | true
98 |
99 |
100 | false
101 | true
102 |
103 |
104 | false
105 | true
106 |
107 |
108 | false
109 | true
110 |
111 |
112 | false
113 | true
114 |
115 |
116 |
117 | Level4
118 | Disabled
119 | MultiThreadedDebugDLL
120 | false
121 | true
122 | Fast
123 | StreamingSIMDExtensions2
124 | Sync
125 | %(AdditionalOptions)
126 | WIN32;_DEBUG;DEBUG;PROFILE;_WINDOWS;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions)
127 | EditAndContinue
128 | EnableFastChecks
129 |
130 |
131 | %(AdditionalOptions)
132 | d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;%(AdditionalDependencies)
133 | Windows
134 | true
135 | true
136 | true
137 | true
138 | MachineX86
139 | AsInvoker
140 | %(DelayLoadDLLs)
141 |
142 |
143 | true
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 | Level4
157 | Disabled
158 | MultiThreadedDebugDLL
159 | false
160 | true
161 | Fast
162 | Sync
163 | %(AdditionalOptions)
164 | WIN32;_DEBUG;DEBUG;PROFILE;_WINDOWS;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions)
165 | EnableFastChecks
166 |
167 |
168 | %(AdditionalOptions)
169 | d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;%(AdditionalDependencies)
170 | Windows
171 | true
172 | true
173 | true
174 | true
175 | MachineX64
176 | AsInvoker
177 | %(DelayLoadDLLs)
178 |
179 |
180 | true
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 | Level4
194 | MaxSpeed
195 | MultiThreadedDLL
196 | false
197 | true
198 | true
199 | Fast
200 | StreamingSIMDExtensions2
201 | Sync
202 | %(AdditionalOptions)
203 | WIN32;NDEBUG;_WINDOWS;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions)
204 |
205 |
206 | %(AdditionalOptions)
207 | d3d11.lib;d3dcompiler.lib;;dxguid.lib;winmm.lib;comctl32.lib;%(AdditionalDependencies)
208 | true
209 | Windows
210 | true
211 | true
212 | true
213 | true
214 | true
215 | MachineX86
216 | AsInvoker
217 | %(DelayLoadDLLs)
218 |
219 |
220 | true
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 | Level4
234 | MaxSpeed
235 | MultiThreadedDLL
236 | false
237 | true
238 | true
239 | Fast
240 | Sync
241 | %(AdditionalOptions)
242 | WIN32;NDEBUG;_WINDOWS;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions)
243 |
244 |
245 | %(AdditionalOptions)
246 | d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;%(AdditionalDependencies)
247 | true
248 | Windows
249 | true
250 | true
251 | true
252 | true
253 | true
254 | MachineX64
255 | AsInvoker
256 | %(DelayLoadDLLs)
257 |
258 |
259 | true
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 | Level4
273 | MaxSpeed
274 | MultiThreadedDLL
275 | false
276 | true
277 | true
278 | Fast
279 | StreamingSIMDExtensions2
280 | Sync
281 | %(AdditionalOptions)
282 | WIN32;NDEBUG;PROFILE;_WINDOWS;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions)
283 |
284 |
285 | %(AdditionalOptions)
286 | d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;%(AdditionalDependencies)
287 | true
288 | Windows
289 | true
290 | true
291 | true
292 | true
293 | true
294 | MachineX86
295 | AsInvoker
296 | %(DelayLoadDLLs)
297 |
298 |
299 | true
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 | Level4
313 | MaxSpeed
314 | MultiThreadedDLL
315 | false
316 | true
317 | true
318 | Fast
319 | Sync
320 | %(AdditionalOptions)
321 | WIN32;NDEBUG;PROFILE;_WINDOWS;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions)
322 |
323 |
324 | %(AdditionalOptions)
325 | d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;%(AdditionalDependencies)
326 | true
327 | Windows
328 | true
329 | true
330 | true
331 | true
332 | true
333 | MachineX64
334 | AsInvoker
335 | %(DelayLoadDLLs)
336 |
337 |
338 | true
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
--------------------------------------------------------------------------------
/Lens/Lens.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {8e114980-c1a3-4ada-ad7c-83caadf5daeb}
6 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe
7 |
8 |
9 |
10 |
11 | Resource Files
12 |
13 |
14 | Resource Files
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | Resource Files
25 |
26 |
27 | Resource Files
28 |
29 |
30 |
--------------------------------------------------------------------------------
/Lens/aperture.hlsl:
--------------------------------------------------------------------------------
1 | #include "common.hlsl"
2 |
3 | float fade_aperture_edge(float radius, float fade, float signed_distance) {
4 | float l = radius;
5 | float u = radius + fade;
6 | float s = u - l;
7 | float c = 1.f - saturate(saturate(signed_distance - l)/s);
8 | return smoothstep(0, 1, c);
9 | }
10 |
11 | float smax(float a, float b, float k) {
12 | float diff = a - b;
13 | float h = saturate(0.5 + 0.5 * diff / k);
14 | return b + h * (diff + k * (1.0f - h));
15 | }
16 |
17 | float4 PSAperture(float4 pos : SV_POSITION) : SV_Target {
18 |
19 | float2 uv = pos.xy / aperture_resolution;
20 | float2 ndc = ((uv - 0.5f) * 2.f);
21 |
22 | int num_of_blades = int(number_of_blades);
23 |
24 | float a = (atan2(ndc.x, ndc.y) + aperture_opening)/TWOPI + 3.f/4.f;
25 | float o = frac(a * num_of_blades + 0.5);
26 | float w1 = lerp(0.010, 0.001f, saturate((num_of_blades - 4)/10.f));
27 | float w2 = lerp(0.025, 0.001f, saturate((num_of_blades - 4)/10.f));
28 | float s0 = sin(o * 2 * PI);
29 | float s1 = s0 * w1;
30 | float s2 = s0 * w2;
31 |
32 | // fft aperture shape
33 | float signed_distance = 0.f;
34 | for(int i = 0; i < num_of_blades; ++i) {
35 | float angle = aperture_opening + (i/float(num_of_blades)) * TWOPI;
36 | float2 axis = float2(cos(angle), sin(angle));
37 | signed_distance = max(signed_distance, dot(axis, ndc));
38 | }
39 |
40 | //signed_distance += s1;
41 | float aperture_fft = fade_aperture_edge(0.7, 0.00001, signed_distance);
42 |
43 | // camera aperture shape
44 | signed_distance = 0.f;
45 | for(int i = 0; i < num_of_blades; ++i) {
46 | float angle = aperture_opening + (i/float(num_of_blades)) * TWOPI;
47 | float2 axis = float2(cos(angle), sin(angle));
48 | signed_distance = smax(signed_distance, dot(axis, ndc), 0.1);
49 | }
50 |
51 | signed_distance += s2;
52 | float aperture_mask = fade_aperture_edge(0.7, 0.1, signed_distance);
53 |
54 | { // Diffraction rings
55 | float w = 0.2;
56 | float s = signed_distance + 0.05;
57 | float n = saturate(saturate(s + w) - (1.f - w));
58 |
59 | float x = n/w;
60 | float a = x;
61 | float b = -x + 1.f;
62 | float c = min(a,b) * 2.f;
63 | float t = (sin(x * 6.f * PI - 1.5f) + 1.f) * 0.5f;
64 | float rings = pow(t*c, 1.f);
65 | aperture_mask = aperture_mask + rings * 0.125;
66 | }
67 |
68 | float dust_fft = 0.f;
69 | { // Dust
70 | dust_fft = input_texture1.Sample(LinearSampler, uv).r;
71 | aperture_mask *= saturate(dust_fft + 0.9);
72 | }
73 |
74 | float3 rgb = float3(aperture_fft, dust_fft, aperture_mask);
75 |
76 | return float4(rgb, 1);
77 | }
78 |
--------------------------------------------------------------------------------
/Lens/common.hlsl:
--------------------------------------------------------------------------------
1 | #define PI 3.14159265359f
2 | #define TWOPI 6.28318530718f
3 | #define NANO_METER 0.0000001
4 | #define INCOMING_LIGHT_TEMP 6000.f
5 |
6 | SamplerState LinearSampler {
7 | Filter = MIN_MAG_MIP_LINEAR;
8 | AddressU = Wrap;
9 | AddressV = Wrap;
10 | };
11 |
12 | Texture2D input_texture1 : register(t1);
13 | Texture2D input_texture2 : register(t2);
14 |
15 | // Constant buffers
16 | cbuffer GlobalData : register(b1) {
17 | float time;
18 | float spread;
19 | float plate_size;
20 | float aperture_id;
21 |
22 | float num_interfaces;
23 | float coating_quality;
24 | float2 backbuffer_size;
25 |
26 | float3 light_dir;
27 | float aperture_resolution;
28 |
29 | float aperture_opening;
30 | float number_of_blades;
31 | float starburst_resolution;
32 | float padding;
33 | };
34 |
35 | cbuffer PerformanceData : register(b2) {
36 | float4 performance_data;
37 | }
38 |
39 | static float4 temperature_color_map[25] = {
40 | float4( 0.0, 0.000, 0.000, 0.000),
41 | float4( 1000.0, 1.000, 0.007, 0.000),
42 | float4( 1500.0, 1.000, 0.126, 0.000),
43 | float4( 2000.0, 1.000, 0.234, 0.010),
44 | float4( 2500.0, 1.000, 0.349, 0.067),
45 | float4( 3000.0, 1.000, 0.454, 0.151),
46 | float4( 3500.0, 1.000, 0.549, 0.254),
47 | float4( 4000.0, 1.000, 0.635, 0.370),
48 | float4( 4500.0, 1.000, 0.710, 0.493),
49 | float4( 5000.0, 1.000, 0.778, 0.620),
50 | float4( 5500.0, 1.000, 0.837, 0.746),
51 | float4( 6000.0, 1.000, 0.890, 0.869),
52 | float4( 6500.0, 1.000, 0.937, 0.988),
53 | float4( 7000.0, 0.907, 0.888, 1.000),
54 | float4( 7500.0, 0.827, 0.839, 1.000),
55 | float4( 8000.0, 0.762, 0.800, 1.000),
56 | float4( 8500.0, 0.711, 0.766, 1.000),
57 | float4( 9000.0, 0.668, 0.738, 1.000),
58 | float4( 9500.0, 0.632, 0.714, 1.000),
59 | float4(10000.0, 0.602, 0.693, 1.000),
60 | float4(12000.0, 0.518, 0.632, 1.000),
61 | float4(14000.0, 0.468, 0.593, 1.000),
62 | float4(16000.0, 0.435, 0.567, 1.000),
63 | float4(18000.0, 0.411, 0.547, 1.000),
64 | float4(20000.0, 0.394, 0.533, 1.000)
65 | };
66 |
67 | float3 TemperatureToColor(float t) {
68 | int index;
69 | for(int i=0; i < 25; ++i){
70 | if(t < temperature_color_map[i].x) {
71 | index = i;
72 | break;
73 | }
74 | }
75 |
76 | if(index > 0) {
77 | float4 lower = temperature_color_map[index - 1];
78 | float4 upper = temperature_color_map[index];
79 | float l = (t - lower.x)/(upper.x - lower.x);
80 | return lerp(lower.yzw, upper.yzw, l);
81 | } else {
82 | return 0;
83 | }
84 | }
85 |
86 | float2 Rotate(float2 p, float a) {
87 | float x = p.x;
88 | float y = p.y;
89 |
90 | float cosa = cos(a);
91 | float sina = sin(a);
92 |
93 | float x1 = x * cosa - y * sina;
94 | float y1 = y * cosa + x * sina;
95 |
96 | return float2(x1, y1);
97 | }
98 |
--------------------------------------------------------------------------------
/Lens/copy.hlsl:
--------------------------------------------------------------------------------
1 | Texture2D SourceTexture : register(t0);
2 | RWTexture2D TargetTexture : register(u0);
3 |
4 | [numthreads(16, 16, 1)]
5 | void CopyTextureCS(uint3 position : SV_DispatchThreadID) {
6 | TargetTexture[position.xy] = SourceTexture[position.xy];
7 | }
--------------------------------------------------------------------------------
/Lens/directx.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/greje656/PhysicallyBasedLensFlare/488a8cfb4b18af3f3f43b8122bf9a79605dd782b/Lens/directx.ico
--------------------------------------------------------------------------------
/Lens/dust.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/greje656/PhysicallyBasedLensFlare/488a8cfb4b18af3f3f43b8122bf9a79605dd782b/Lens/dust.bmp
--------------------------------------------------------------------------------
/Lens/fft.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | using namespace DirectX;
7 |
8 | struct FFT {
9 | enum FFTTextures {
10 | FFTTexture_Real0,
11 | FFTTexture_Imaginary0,
12 | FFTTexture_Real1,
13 | FFTTexture_Imaginary1,
14 | FFTTexture_Count
15 | };
16 |
17 | ID3D11Texture2D *mTextures[FFTTexture_Count];
18 | ID3D11UnorderedAccessView *mTextureUAV[FFTTexture_Count];
19 | ID3D11ShaderResourceView *mTextureSRV[FFTTexture_Count];
20 | ID3D11RenderTargetView *mRenderTargetViews[FFTTexture_Count];
21 |
22 | void InitFFTTetxtures(ID3D11Device *device, int aperture_resolution) {
23 | D3D11_TEXTURE2D_DESC textureDesc;
24 | memset(&textureDesc, 0, sizeof(textureDesc));
25 | textureDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
26 | textureDesc.Width = (UINT)aperture_resolution;
27 | textureDesc.Height = (UINT)aperture_resolution;
28 | textureDesc.BindFlags = D3D11_BIND_UNORDERED_ACCESS;
29 | textureDesc.MipLevels = 1;
30 | textureDesc.ArraySize = 1;
31 | textureDesc.SampleDesc.Count = 1;
32 | textureDesc.SampleDesc.Quality = 0;
33 | textureDesc.CPUAccessFlags = 0;
34 | textureDesc.Usage = D3D11_USAGE_DEFAULT;
35 |
36 | for (int i = 0; i < FFTTexture_Count; i++) {
37 | textureDesc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
38 | if (i == FFTTexture_Real0 || i == FFTTexture_Imaginary0) {
39 | textureDesc.BindFlags = textureDesc.BindFlags | D3D11_BIND_RENDER_TARGET;
40 | }
41 |
42 | device->CreateTexture2D(&textureDesc, NULL, &mTextures[i]);
43 | device->CreateUnorderedAccessView(mTextures[i], NULL, &mTextureUAV[i]);
44 | device->CreateShaderResourceView(mTextures[i], NULL, &mTextureSRV[i]);
45 |
46 | }
47 |
48 | device->CreateRenderTargetView(mTextures[FFTTexture_Real0], NULL, &mRenderTargetViews[FFTTexture_Real0]);
49 | device->CreateRenderTargetView(mTextures[FFTTexture_Imaginary0], NULL, &mRenderTargetViews[FFTTexture_Imaginary0]);
50 | }
51 |
52 | #define roundup(x,y) ( (int)y * (int)((x + y - 1)/y))
53 | void CopyTextureNoStretch(ID3D11DeviceContext *context, ID3D11ShaderResourceView *srcSRV, ID3D11UnorderedAccessView *dstUAV, int size, ID3D11ComputeShader* copyShader) {
54 | ID3D11UnorderedAccessView* pClearUAVs[] = { NULL, NULL };
55 | ID3D11ShaderResourceView* pClearSRVs[] = { NULL, NULL, NULL };
56 |
57 | context->PSSetShaderResources(0, 3, pClearSRVs);
58 | context->CSSetShaderResources(0, 1, pClearSRVs);
59 | context->CSSetUnorderedAccessViews(0, 2, pClearUAVs, NULL);
60 | context->CSSetShader(copyShader, NULL, 0);
61 |
62 | float values[] = { 0.0f, 0.0f, 0.0f, 0.0f };
63 | context->ClearUnorderedAccessViewFloat(dstUAV, values);
64 | context->CSSetShaderResources(0, 1, &srcSRV);
65 | context->CSSetUnorderedAccessViews(0, 1, &dstUAV, NULL);
66 | int dispatchX = roundup(min(size, size) / 16, 16);
67 | int dispatchY = roundup(min(size, size) / 16, 16);
68 | context->Dispatch(dispatchX, dispatchY, 1);
69 |
70 | context->CSSetShaderResources(0, 1, pClearSRVs);
71 | context->CSSetUnorderedAccessViews(0, 2, pClearUAVs, NULL);
72 | }
73 |
74 | void RunDispatchSLM(ID3D11DeviceContext *context, int pass, ID3D11ComputeShader* shader, int aperture_resolution) {
75 | ID3D11UnorderedAccessView* pUAVs[] = { NULL, NULL };
76 | ID3D11ShaderResourceView* pSRVs[] = { NULL, NULL, NULL };
77 |
78 | context->CSSetShaderResources(0, 3, pSRVs);
79 | context->CSSetUnorderedAccessViews(0, 2, pUAVs, NULL);
80 | context->CSSetShader(shader, NULL, 0);
81 |
82 | pSRVs[0] = mTextureSRV[FFTTexture_Real0 + 2 * pass];
83 | pSRVs[1] = mTextureSRV[FFTTexture_Imaginary0 + 2 * pass];
84 | pUAVs[0] = mTextureUAV[FFTTexture_Real0 + 2 * !pass];
85 | pUAVs[1] = mTextureUAV[FFTTexture_Imaginary0 + 2 * !pass];
86 |
87 | context->CSSetUnorderedAccessViews(0, 2, pUAVs, NULL);
88 | context->CSSetShaderResources(0, 3, pSRVs);
89 |
90 | context->Dispatch(1, (UINT)aperture_resolution, 1);
91 |
92 | pSRVs[0] = NULL; pSRVs[1] = NULL; pSRVs[2] = NULL;
93 | context->CSSetShaderResources(0, 3, pSRVs);
94 | pUAVs[0] = NULL; pUAVs[1] = NULL;
95 | context->CSSetUnorderedAccessViews(0, 2, pUAVs, NULL);
96 | }
97 | } FFT;
--------------------------------------------------------------------------------
/Lens/fft.hlsl:
--------------------------------------------------------------------------------
1 | //--------------------------------------------------------------------------------------
2 | // Copyright 2014 Intel Corporation
3 | // All Rights Reserved
4 | //
5 | // Permission is granted to use, copy, distribute and prepare derivative works of this
6 | // software for any purpose and without fee, provided, that the above copyright notice
7 | // and this statement appear in all copies. Intel makes no representations about the
8 | // suitability of this software for any purpose. THIS SOFTWARE IS PROVIDED "AS IS."
9 | // INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, AND ALL LIABILITY,
10 | // INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, FOR THE USE OF THIS SOFTWARE,
11 | // INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY RIGHTS, AND INCLUDING THE
12 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Intel does not
13 | // assume any responsibility for any errors which may appear in this software nor any
14 | // responsibility to update it.
15 | //--------------------------------------------------------------------------------------
16 |
17 | // Input Preprocess Defines:
18 | // TRANSFORM_INVERSE: Defined for inverse fft only
19 | // BUTTERFLY_COUNT: number of passes to perform
20 | // ROWPASS: defined for tranformation along the x axis
21 | // LENGTH: pixel length of row or column
22 |
23 | Texture2D TextureSourceR : register(t0);
24 | Texture2D TextureSourceI : register(t1);
25 | RWTexture2D TextureTargetR : register(u0);
26 | RWTexture2D TextureTargetI : register(u1);
27 |
28 | static const float PI = 3.14159265f;
29 |
30 | void GetButterflyValues(uint passIndex, uint x, out uint2 indices, out float2 weights) {
31 | int sectionWidth = 2 << passIndex;
32 | int halfSectionWidth = sectionWidth / 2;
33 |
34 | int sectionStartOffset = x & ~(sectionWidth - 1);
35 | int halfSectionOffset = x & (halfSectionWidth - 1);
36 | int sectionOffset = x & (sectionWidth - 1);
37 |
38 | sincos( 2.0*PI*sectionOffset / (float)sectionWidth, weights.y, weights.x );
39 | weights.y = -weights.y;
40 |
41 | indices.x = sectionStartOffset + halfSectionOffset;
42 | indices.y = sectionStartOffset + halfSectionOffset + halfSectionWidth;
43 |
44 | if (passIndex == 0) {
45 | indices = reversebits(indices) >> (32 - BUTTERFLY_COUNT) & (LENGTH - 1);
46 | }
47 | }
48 |
49 | groupshared float3 pingPongArray[4][LENGTH];
50 | void ButterflyPass(int passIndex, uint x, uint t0, uint t1, out float3 resultR, out float3 resultI) {
51 | uint2 Indices;
52 | float2 Weights;
53 | GetButterflyValues(passIndex, x, Indices, Weights);
54 |
55 | float3 inputR1 = pingPongArray[t0][Indices.x];
56 | float3 inputI1 = pingPongArray[t1][Indices.x];
57 |
58 | float3 inputR2 = pingPongArray[t0][Indices.y];
59 | float3 inputI2 = pingPongArray[t1][Indices.y];
60 |
61 | resultR = inputR1 + Weights.x * inputR2 - Weights.y * inputI2;
62 | resultI = inputI1 + Weights.y * inputR2 + Weights.x * inputI2;
63 | }
64 |
65 | [numthreads( LENGTH, 1, 1 )]
66 | void ButterflySLM(uint3 position : SV_DispatchThreadID) {
67 | #ifdef ROWPASS
68 | uint2 texturePos = uint2( position.xy );
69 | #else
70 | uint2 texturePos = uint2( position.yx );
71 | #endif
72 |
73 | // Load entire row or column into scratch array
74 | pingPongArray[0][position.x].xyz = TextureSourceR[texturePos];
75 | #if defined(ROWPASS)
76 | // don't load values from the imaginary texture when loading the original texture
77 | pingPongArray[1][position.x].xyz = 0;
78 | #else
79 | pingPongArray[1][position.x].xyz = TextureSourceI[texturePos];
80 | #endif
81 |
82 | uint4 textureIndices = uint4(0, 1, 2, 3);
83 | for (int i = 0; i < BUTTERFLY_COUNT-1; i++) {
84 | GroupMemoryBarrierWithGroupSync();
85 | ButterflyPass( i, position.x, textureIndices.x, textureIndices.y, pingPongArray[textureIndices.z][position.x].xyz, pingPongArray[textureIndices.w][position.x].xyz );
86 | textureIndices.xyzw = textureIndices.zwxy;
87 | }
88 |
89 | // Final butterfly will write directly to the target texture
90 | GroupMemoryBarrierWithGroupSync();
91 |
92 | // The final pass writes to the output UAV texture
93 | ButterflyPass(BUTTERFLY_COUNT - 1, position.x, textureIndices.x, textureIndices.y, TextureTargetR[texturePos], TextureTargetI[texturePos]);
94 |
95 | }
96 |
--------------------------------------------------------------------------------
/Lens/lens.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | #include
8 | #include
9 |
10 | #include "fft.h"
11 | #include "resource.h"
12 | #include "ray_trace.h"
13 |
14 | //#define DRAW2D
15 | #define DRAWLENSFLARE
16 |
17 | using namespace DirectX;
18 | using namespace std;
19 |
20 | // ---------------------------------------------------------------------------------------------------------
21 | // Structs
22 | // ---------------------------------------------------------------------------------------------------------
23 | struct PatentFormat {
24 | float r;
25 | float d;
26 | float n;
27 | bool f;
28 | float w;
29 | float h;
30 | float c;
31 | };
32 |
33 | struct GlobalData {
34 | float time;
35 | float spread;
36 | float plate_size;
37 | float aperture_id;
38 | float num_interfaces;
39 | float aperture_resolution;
40 |
41 | XMFLOAT2 backbuffer_size;
42 | XMFLOAT4 direction;
43 | XMFLOAT4 aperture_opening;
44 | };
45 |
46 | struct PSInput {
47 | XMFLOAT4 pos;
48 | XMFLOAT4 color;
49 | XMFLOAT4 coordinates;
50 | XMFLOAT4 reflectance;
51 | };
52 |
53 | struct InstanceUniforms {
54 | XMFLOAT4 color;
55 | XMFLOAT4 placement;
56 | };
57 |
58 | struct CSIndirectData {
59 | unsigned int x, y, z;
60 | };
61 |
62 | typedef XMFLOAT3 SimpleVertex;
63 | typedef XMFLOAT4 GhostData;
64 | typedef XMFLOAT4 PerformanceData;
65 |
66 | // ---------------------------------------------------------------------------------------------------------
67 | // Inlined Functions
68 | // ---------------------------------------------------------------------------------------------------------
69 | inline float Sign(float v) {
70 | return v < 0.f ? -1.f : 1.f;
71 | }
72 |
73 | inline float Lerp(float a, float b, float l) {
74 | return a * (1.f - l) + b * l;
75 | }
76 |
77 | inline XMFLOAT4 Lerp(XMFLOAT4& a, XMFLOAT4& b, float l) {
78 | float x = Lerp(a.x, b.x, l);
79 | float y = Lerp(a.y, b.y, l);
80 | float z = Lerp(a.z, b.z, l);
81 | float w = Lerp(a.w, b.w, l);
82 | return{ x, y, z, w };
83 | }
84 |
85 | // ---------------------------------------------------------------------------------------------------------
86 | // Global Data
87 | // ---------------------------------------------------------------------------------------------------------
88 | struct ColorTheme {
89 | XMFLOAT4 NormalizeRGB(XMFLOAT4 c) {
90 | XMFLOAT4 rgb = c;
91 | rgb.x /= 255.f;
92 | rgb.y /= 255.f;
93 | rgb.z /= 255.f;
94 | return rgb;
95 | };
96 |
97 | float alpha = 0.65f;
98 | XMFLOAT4 fill1 = NormalizeRGB({ 64.f, 215.f, 242.f, 0.2f });
99 | XMFLOAT4 fill2 = NormalizeRGB({ 179.f, 178.f, 210.f, 0.2f });
100 | XMFLOAT4 flat_fill = NormalizeRGB({ 190.f, 190.f, 190.f, 1.0f });
101 | XMFLOAT4 stroke = NormalizeRGB({ 115.f, 115.f, 115.f, 1.0f });
102 | XMFLOAT4 stroke1 = NormalizeRGB({ 115.f, 115.f, 115.f, 1.0f });
103 | XMFLOAT4 stroke2 = NormalizeRGB({ 165.f, 165.f, 165.f, 1.0f });
104 | XMFLOAT4 background1 = NormalizeRGB({ 240.f, 240.f, 240.f, 1.0f });
105 | XMFLOAT4 background2 = NormalizeRGB({ 0.f, 0.f, 0.f, 1.0f });
106 | XMFLOAT4 intersection1 = NormalizeRGB({ 0.f, 0.f, 0.f, 0.1f });
107 | XMFLOAT4 intersection2 = NormalizeRGB({ 64.f, 215.f, 242.f, 0.5f });
108 | XMFLOAT4 intersection3 = NormalizeRGB({ 179.f, 178.f, 210.f, 0.5f });
109 | } ColorTheme;
110 |
111 | struct UI {
112 | float x_dir = 0.f;
113 | float y_dir = 0.f;
114 | float aperture_opening = 7.f;
115 | float number_of_blades = 5.f;
116 | float rays_spread = 0.75f;
117 | float coating_quality = 1.25;
118 | int ghost_bounce_1 = 3;
119 | int ghost_bounce_2 = 1;
120 | XMFLOAT3 direction = { 0.f, 0.f, -1.f };
121 |
122 | bool left_mouse_down = false;
123 | bool spacebar_down = false;
124 | bool key_down = false;
125 | bool editing_aperture = false;
126 | bool editing_no_blades = false;
127 | bool editing_spread = false;
128 | bool editing_coating_quality = false;
129 | bool overlay_wireframe = false;
130 | bool aperture_needs_updating = true;
131 | bool draw2d = true;
132 | } UI;
133 |
134 | struct LensDescription {
135 | // Nikon Lens
136 | const float d6 = 53.142f;
137 | const float d10 = 7.063f;
138 | const float d14 = 1.532f;
139 | const float dAp = 2.800f;
140 | const float d20 = 16.889f;
141 | const float Bf = 39.683f;
142 | const int nikon_aperture_id = 14;
143 |
144 | vector nikon_28_75mm = {
145 | { 72.747f, 2.300f, 1.60300f, false, 0.2f, 29.0f, 530 },
146 | { 37.000f, 13.000f, 1.00000f, false, 0.2f, 29.0f, 600 },
147 |
148 | { -172.809f, 2.100f, 1.58913f, false, 2.7f, 26.2f, 570 },
149 | { 39.894f, 1.000f, 1.00000f, false, 2.7f, 26.2f, 660 },
150 |
151 | { 49.820f, 4.400f, 1.86074f, false, 0.5f, 20.0f, 330 },
152 | { 74.750f, d6, 1.00000f, false, 0.5f, 20.0f, 544 },
153 |
154 | { 63.402f, 1.600f, 1.86074f, false, 0.5f, 16.1f, 740 },
155 | { 37.530f, 8.600f, 1.51680f, false, 0.5f, 16.1f, 411 },
156 |
157 | { -75.887f, 1.600f, 1.80458f, false, 0.5f, 16.0f, 580 },
158 | { -97.792f, d10, 1.00000f, false, 0.5f, 16.5f, 730 },
159 |
160 | { 96.034f, 3.600f, 1.62041f, false, 0.5f, 18.0f, 700 },
161 | { 261.743f, 0.100f, 1.00000f, false, 0.5f, 18.0f, 440 },
162 |
163 | { 54.262f, 6.000f, 1.69680f, false, 0.5f, 18.0f, 800 },
164 | { -5995.277f, d14, 1.00000f, false, 0.5f, 18.0f, 300 },
165 |
166 | { 0.0f, dAp, 1.00000f, true, 18.f, UI.aperture_opening, 440 },
167 |
168 | { -74.414f, 2.200f, 1.90265f, false, 0.5f, 13.0f, 500 },
169 |
170 | { -62.929f, 1.450f, 1.51680f, false, 0.1f, 13.0f, 770 },
171 | { 121.380f, 2.500f, 1.00000f, false, 4.0f, 13.1f, 820 },
172 |
173 | { -85.723f, 1.400f, 1.49782f, false, 4.0f, 13.0f, 200 },
174 |
175 | { 31.093f, 2.600f, 1.80458f, false, 4.0f, 13.1f, 540 },
176 | { 84.758f, d20, 1.00000f, false, 0.5f, 13.0f, 580 },
177 |
178 | { 459.690f, 1.400f, 1.86074f, false, 1.0f, 15.0f, 533 },
179 |
180 | { 40.240f, 7.300f, 1.49782f, false, 1.0f, 15.0f, 666 },
181 | { -49.771f, 0.100f, 1.00000f, false, 1.0f, 15.2f, 500 },
182 |
183 | { 62.369f, 7.000f, 1.67025f, false, 1.0f, 16.0f, 487 },
184 | { -76.454f, 5.200f, 1.00000f, false, 1.0f, 16.0f, 671 },
185 |
186 | { -32.524f, 2.000f, 1.80454f, false, 0.5f, 17.0f, 487 },
187 | { -50.194f, Bf, 1.00000f, false, 0.5f, 17.0f, 732 },
188 |
189 | { 0.f, 5.f, 1.00000f, true, 10.f, 10.f, 500 }
190 | };
191 |
192 | // Angenieux Lens
193 | const int angenieux_aperture_id = 7;
194 |
195 | vector angenieux = {
196 | { 164.13f, 10.99f, 1.67510f, false, 0.5f, 52.0f, 432 },
197 | { 559.20f, 0.23f, 1.00000f, false, 0.5f, 52.0f, 532 },
198 |
199 | { 100.12f, 11.45f, 1.66890f, false, 0.5f, 48.0f, 382 },
200 | { 213.54f, 0.23f, 1.00000f, false, 0.5f, 48.0f, 422 },
201 |
202 | { 58.04f, 22.95f, 1.69131f, false, 0.5f, 36.0f, 572 },
203 |
204 | { 2551.10f, 2.58f, 1.67510f, false, 0.5f, 42.0f, 612 },
205 | { 32.39f, 30.66f, 1.00000f, false, 0.3f, 36.0f, 732 },
206 |
207 | { 0.0f, 10.00f, 1.00000f, true, 25.f, UI.aperture_opening, 440 },
208 |
209 | { -40.42f, 2.74f, 1.69920f, false, 1.5f, 13.0f, 602 },
210 |
211 | { 192.98f, 27.92f, 1.62040f, false, 4.0f, 36.0f, 482 },
212 | { -55.53f, 0.23f, 1.00000f, false, 0.5f, 36.0f, 662 },
213 |
214 | { 192.98f, 7.98f, 1.69131f, false, 0.5f, 35.0f, 332 },
215 | { -225.30f, 0.23f, 1.00000f, false, 0.5f, 35.0f, 412 },
216 |
217 | { 175.09f, 8.48f, 1.69130f, false, 0.5f, 35.0f, 532 },
218 | { -203.55f, 40.f, 1.00000f, false, 0.5f, 35.0f, 632 },
219 |
220 | { 0.f, 5.f, 1.00000f, true, 10.f, 5.f, 500 }
221 | };
222 |
223 | vector lens_interface;
224 | vector ghosts;
225 |
226 | vector lens_components = nikon_28_75mm;
227 | int aperture_id = nikon_aperture_id;
228 | int num_of_ghosts = 352; // 27!/2*(27-2)!
229 |
230 | //vector lens_components = angenieux;
231 | //int aperture_id = angenieux_aperture_id;
232 | //int num_of_ghosts = 92; // 14!/2*(14-2)!
233 |
234 | int num_of_lens_components = (int)lens_components.size();
235 | int num_of_intersections_1 = num_of_lens_components + 1;
236 | int num_of_intersections_2 = num_of_lens_components + 1;
237 | int num_of_intersections_3 = num_of_lens_components + 1;
238 | float total_lens_distance = 0.f;
239 | float max_ior = -1000.f;
240 | float min_ior = 1000.f;
241 | } Lens;
242 |
243 | struct Application {
244 | int patch_tesselation = 32;
245 | int num_threads = 32;
246 | int num_groups = patch_tesselation / num_threads;
247 | int num_of_rays = patch_tesselation;
248 |
249 | int num_points_per_cirlces = 200;
250 | int num_vertices_per_cirlces = num_points_per_cirlces * 3;
251 | int num_vertices_per_bundle = (patch_tesselation - 1) * (patch_tesselation - 1);
252 |
253 | float backbuffer_width = 1800;
254 | float backbuffer_height = 900;
255 | float dust_resolution = 512;
256 | float aperture_resolution = 512;
257 | float starburst_resolution = 2056;
258 | float ratio = backbuffer_height / backbuffer_width;
259 | float time = 0.f;
260 | float time_delta = 0.1f;
261 | float global_scale = 0.009;
262 | } App;
263 |
264 | struct Win {
265 | HINSTANCE g_hInst = nullptr;
266 | HWND g_hWnd = nullptr;
267 |
268 | IDXGISwapChain* d3d_swapchain = nullptr;
269 | IDXGISwapChain1* d3d_swapchain1 = nullptr;
270 |
271 | ID3D11InputLayout* d3d_vertex_layout_2d = nullptr;
272 | ID3D11InputLayout* d3d_vertex_layout_3d = nullptr;
273 |
274 | ID3D11Device* d3d_device = nullptr;
275 | ID3D11Device1* d3d_device1 = nullptr;
276 | ID3D11DeviceContext* d3d_context = nullptr;
277 | ID3D11DeviceContext1* d3d_context1 = nullptr;
278 |
279 | D3D_DRIVER_TYPE d3d_driver_type = D3D_DRIVER_TYPE_NULL;
280 | D3D_FEATURE_LEVEL d3d_feature_level = D3D_FEATURE_LEVEL_11_0;
281 |
282 | // Convenient D3d Defaults Valuesf
283 | INT sample_mask = 0x0F;
284 | UINT offset = 0;
285 | UINT stride = sizeof(SimpleVertex);
286 | float blend_factor[4] = { 1.f, 1.f, 1.f, 1.f };
287 | } Win;
288 |
289 | // ---------------------------------------------------------------------------------------------------------
290 | // Ressources
291 | // ---------------------------------------------------------------------------------------------------------
292 | struct Textures {
293 | ID3D11UnorderedAccessView* null_ua_view[1] = { NULL };
294 | ID3D11ShaderResourceView* null_sr_view[1] = { NULL };
295 |
296 | ID3D11DepthStencilView* depthstencil_view = nullptr;
297 | ID3D11DepthStencilView* aperture_depthbuffer_view = nullptr;
298 | ID3D11DepthStencilView* starburst_depth_buffer_view = nullptr;
299 |
300 | ID3D11Texture2D* hdr = nullptr;
301 | ID3D11Texture2D* dust = nullptr;
302 | ID3D11Texture2D* aperture = nullptr;
303 | ID3D11Texture2D* starburst = nullptr;
304 | ID3D11Texture2D* starburst_filtered = nullptr;
305 | ID3D11Texture2D* aperture_depthbuffer = nullptr;
306 | ID3D11Texture2D* depthbuffer = nullptr;
307 |
308 | ID3D11RenderTargetView* backbuffer_rt_view = nullptr;
309 | ID3D11RenderTargetView* hdr_rt_view = nullptr;
310 | ID3D11RenderTargetView* dust_rt_view = nullptr;
311 | ID3D11RenderTargetView* aperture_rt_view = nullptr;
312 | ID3D11RenderTargetView* starburst_rt_view = nullptr;
313 | ID3D11RenderTargetView* starburst_filtered_rt_view = nullptr;
314 |
315 | ID3D11ShaderResourceView* hdr_sr_view = nullptr;
316 | ID3D11ShaderResourceView* dust_sr_view = nullptr;
317 | ID3D11ShaderResourceView* aperture_sr_view = nullptr;
318 |
319 | ID3D11ShaderResourceView* starburst_sr_view = nullptr;
320 | ID3D11ShaderResourceView* starburst_filtered_sr_view = nullptr;
321 |
322 | ID3D11SamplerState* linear_clamp_sampler = nullptr;
323 | ID3D11SamplerState* linear_wrap_sampler = nullptr;
324 |
325 | void InitSamplers() {
326 | D3D11_SAMPLER_DESC desc;
327 | ZeroMemory(&desc, sizeof(desc));
328 | desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
329 | desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
330 | desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
331 | desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
332 | Win.d3d_device->CreateSamplerState(&desc, &linear_clamp_sampler);
333 |
334 | desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
335 | desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
336 | desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
337 | Win.d3d_device->CreateSamplerState(&desc, &linear_wrap_sampler);
338 | }
339 |
340 | void CreateTexture(int width, int height, DXGI_FORMAT format, ID3D11Texture2D*& texture,
341 | ID3D11ShaderResourceView*& sr_view, ID3D11RenderTargetView*& rt_view, D3D11_SUBRESOURCE_DATA* data = nullptr) {
342 |
343 | D3D11_TEXTURE2D_DESC desc;
344 | ZeroMemory(&desc, sizeof(desc));
345 | desc.Width = width;
346 | desc.Height = height;
347 | desc.MipLevels = 1;
348 | desc.ArraySize = 1;
349 | desc.Format = format;
350 | desc.SampleDesc.Count = 1;
351 | desc.SampleDesc.Quality = 0;
352 | desc.Usage = D3D11_USAGE_DEFAULT;
353 | desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
354 | desc.CPUAccessFlags = 0;
355 | desc.MiscFlags = 0;
356 | Win.d3d_device->CreateTexture2D(&desc, data, &texture);
357 |
358 | D3D11_RENDER_TARGET_VIEW_DESC rt_view_desc;
359 | ZeroMemory(&rt_view_desc, sizeof(rt_view_desc));
360 | rt_view_desc.Format = rt_view_desc.Format;
361 | rt_view_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
362 | rt_view_desc.Texture2D.MipSlice = 0;
363 | Win.d3d_device->CreateRenderTargetView(texture, &rt_view_desc, &rt_view);
364 |
365 | D3D11_SHADER_RESOURCE_VIEW_DESC sr_view_desc;
366 | ZeroMemory(&sr_view_desc, sizeof(sr_view_desc));
367 | sr_view_desc.Format = desc.Format;
368 | sr_view_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
369 | sr_view_desc.Texture2D.MostDetailedMip = 0;
370 | sr_view_desc.Texture2D.MipLevels = 1;
371 | Win.d3d_device->CreateShaderResourceView(texture, &sr_view_desc, &sr_view);
372 | }
373 |
374 | void CreateDepthBuffer(int width, int height, ID3D11Texture2D*& buffer, ID3D11DepthStencilView*& buffer_view) {
375 | // Create depth stencil texture
376 | D3D11_TEXTURE2D_DESC desc;
377 | ZeroMemory(&desc, sizeof(desc));
378 | desc.Width = width;
379 | desc.Height = height;
380 | desc.MipLevels = 1;
381 | desc.ArraySize = 1;
382 | desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
383 | desc.SampleDesc.Count = 1;
384 | desc.SampleDesc.Quality = 0;
385 | desc.Usage = D3D11_USAGE_DEFAULT;
386 | desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
387 | desc.CPUAccessFlags = 0;
388 | desc.MiscFlags = 0;
389 | Win.d3d_device->CreateTexture2D(&desc, nullptr, &buffer);
390 |
391 | // Create the depth stencil view
392 | D3D11_DEPTH_STENCIL_VIEW_DESC view_desc;
393 | ZeroMemory(&view_desc, sizeof(view_desc));
394 | view_desc.Format = desc.Format;
395 | view_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
396 | view_desc.Texture2D.MipSlice = 0;
397 | Win.d3d_device->CreateDepthStencilView(buffer, &view_desc, &buffer_view);
398 | }
399 |
400 | void InitTextures() {
401 | ID3D11Texture2D* backbuffer = nullptr;
402 | Win.d3d_swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast(&backbuffer));
403 | Win.d3d_device->CreateRenderTargetView(backbuffer, nullptr, &backbuffer_rt_view);
404 |
405 | CreateDepthBuffer((int)App.backbuffer_width, (int)App.backbuffer_height, depthbuffer, depthstencil_view);
406 | CreateDepthBuffer((int)App.aperture_resolution, (int)App.aperture_resolution, aperture_depthbuffer, aperture_depthbuffer_view);
407 | CreateDepthBuffer((int)App.starburst_resolution, (int)App.starburst_resolution, aperture_depthbuffer, starburst_depth_buffer_view);
408 |
409 | CreateTexture((int)App.backbuffer_width, (int)App.backbuffer_height, DXGI_FORMAT_R16G16B16A16_FLOAT, hdr, hdr_sr_view, hdr_rt_view);
410 | CreateTexture((int)App.aperture_resolution, (int)App.aperture_resolution, DXGI_FORMAT_R16G16B16A16_FLOAT, aperture, aperture_sr_view, aperture_rt_view);
411 | CreateTexture((int)App.starburst_resolution, (int)App.starburst_resolution, DXGI_FORMAT_R16G16B16A16_FLOAT, starburst, starburst_sr_view, starburst_rt_view);
412 | CreateTexture((int)App.starburst_resolution, (int)App.starburst_resolution, DXGI_FORMAT_R16G16B16A16_FLOAT, starburst_filtered, starburst_filtered_sr_view, starburst_filtered_rt_view);
413 |
414 | // Load the dust texture from the application
415 | HBITMAP bitmap = LoadBitmap(Win.g_hInst, MAKEINTRESOURCE(IDB_BITMAP1));
416 | int size = int(App.dust_resolution * App.dust_resolution * 4);
417 | void* bitmap_data = malloc(size);
418 | GetBitmapBits(bitmap, size, bitmap_data);
419 |
420 | D3D11_SUBRESOURCE_DATA resource_data;
421 | resource_data.pSysMem = bitmap_data;
422 | resource_data.SysMemPitch = int(App.dust_resolution * 4);
423 | resource_data.SysMemSlicePitch = size;
424 |
425 | CreateTexture((int)App.dust_resolution, (int)App.dust_resolution, DXGI_FORMAT_R8G8B8A8_UNORM, dust, dust_sr_view, dust_rt_view, &resource_data);
426 | }
427 | } Textures;
428 |
429 | struct Shaders {
430 | ID3D11VertexShader* vs_basic = nullptr;
431 | ID3D11PixelShader* ps_basic = nullptr;
432 | ID3D11PixelShader* ps_tonemapper = nullptr;
433 | ID3D11PixelShader* ps_tonemapper_debug = nullptr;
434 |
435 | ID3D11VertexShader* vs_starburst = nullptr;
436 | ID3D11PixelShader* ps_starburst = nullptr;
437 | ID3D11PixelShader* ps_starburst_from_fft = nullptr;
438 | ID3D11PixelShader* ps_starburst_filter = nullptr;
439 |
440 | ID3D11VertexShader* vs_lens_flare = nullptr;
441 | ID3D11PixelShader* ps_lens_flare = nullptr;
442 | ID3D11PixelShader* ps_lens_flare_debug = nullptr;
443 | ID3D11PixelShader* ps_lens_flare_wireframe = nullptr;
444 | ID3D11ComputeShader* cs_lens_flare = nullptr;
445 |
446 | ID3D11ComputeShader* cs_fft_row = nullptr;
447 | ID3D11ComputeShader* cs_fft_col = nullptr;
448 | ID3D11ComputeShader* cs_fft_copy = nullptr;
449 |
450 | ID3D11PixelShader* ps_aperture;
451 |
452 | HRESULT CompileShaderFromSource(string shaderSource, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut) {
453 | ID3DBlob* temp = nullptr;
454 | HRESULT hr = D3DCompile(shaderSource.c_str(), shaderSource.length(), nullptr, nullptr, nullptr, szEntryPoint, szShaderModel, D3DCOMPILE_ENABLE_STRICTNESS, 0, ppBlobOut, &temp);
455 | char* msg = temp ? (char*)temp : nullptr; msg;
456 | return hr;
457 | }
458 |
459 | HRESULT CompileShaderFromFile(LPCWSTR shaderFile, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut, D3D_SHADER_MACRO* defines = nullptr) {
460 | ID3DBlob* temp = nullptr;
461 | HRESULT hr = D3DCompileFromFile(shaderFile, defines, D3D_COMPILE_STANDARD_FILE_INCLUDE, szEntryPoint, szShaderModel, D3DCOMPILE_ENABLE_STRICTNESS, 0, ppBlobOut, &temp);
462 | char* msg = temp ? (char*)temp->GetBufferPointer() : nullptr; msg;
463 | return hr;
464 | }
465 |
466 | void InitShaders() {
467 | ID3DBlob* blob = nullptr;
468 | D3D11_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, };
469 | UINT numElements = ARRAYSIZE(layout);
470 |
471 | CompileShaderFromFile(L"visualization.hlsl", "VS", "vs_5_0", &blob);
472 | Win.d3d_device->CreateVertexShader(blob->GetBufferPointer(), blob->GetBufferSize(), nullptr, &vs_basic);
473 | Win.d3d_device->CreateInputLayout(layout, numElements, blob->GetBufferPointer(), blob->GetBufferSize(), &Win.d3d_vertex_layout_2d);
474 | blob->Release();
475 |
476 | CompileShaderFromFile(L"visualization.hlsl", "PS", "ps_5_0", &blob);
477 | Win.d3d_device->CreatePixelShader(blob->GetBufferPointer(), blob->GetBufferSize(), nullptr, &ps_basic);
478 | blob->Release();
479 |
480 | string aperture_id_string = to_string(Lens.aperture_id);
481 | string num_groups_string = to_string(App.num_groups);
482 | string num_threads_string = to_string(App.num_threads);
483 | string patch_tesselation_string = to_string(App.patch_tesselation);
484 |
485 | D3D_SHADER_MACRO lens_defines[] = {
486 | "AP_IDX", aperture_id_string.c_str(),
487 | "NUM_GROUPS", num_groups_string.c_str(),
488 | "NUM_THREADS", num_threads_string.c_str(),
489 | "PATCH_TESSELATION", patch_tesselation_string.c_str(), 0, 0 };
490 | CompileShaderFromFile(L"lens.hlsl", "VS", "vs_5_0", &blob, lens_defines);
491 | Win.d3d_device->CreateVertexShader(blob->GetBufferPointer(), blob->GetBufferSize(), nullptr, &vs_lens_flare);
492 | Win.d3d_device->CreateInputLayout(layout, numElements, blob->GetBufferPointer(), blob->GetBufferSize(), &Win.d3d_vertex_layout_3d);
493 | blob->Release();
494 |
495 | CompileShaderFromFile(L"lens.hlsl", "PS", "ps_5_0", &blob, lens_defines);
496 | Win.d3d_device->CreatePixelShader(blob->GetBufferPointer(), blob->GetBufferSize(), nullptr, &ps_lens_flare);
497 | blob->Release();
498 |
499 | D3D_SHADER_MACRO debug_flags[] = { lens_defines[0], lens_defines[1], lens_defines[2], lens_defines[3], "DEBUG_VALUES", "", 0, 0 };
500 | CompileShaderFromFile(L"lens.hlsl", "PS", "ps_5_0", &blob, debug_flags);
501 | Win.d3d_device->CreatePixelShader(blob->GetBufferPointer(), blob->GetBufferSize(), nullptr, &ps_lens_flare_debug);
502 | blob->Release();
503 |
504 | D3D_SHADER_MACRO wireframe_debug_flags[] = { lens_defines[0], lens_defines[1], lens_defines[2], lens_defines[3], "DEBUG_WIREFRAME", "", 0, 0 };
505 | CompileShaderFromFile(L"lens.hlsl", "PS", "ps_5_0", &blob, wireframe_debug_flags);
506 | Win.d3d_device->CreatePixelShader(blob->GetBufferPointer(), blob->GetBufferSize(), nullptr, &ps_lens_flare_wireframe);
507 | blob->Release();
508 |
509 | CompileShaderFromFile(L"lens.hlsl", "CS", "cs_5_0", &blob, lens_defines);
510 | Win.d3d_device->CreateComputeShader(blob->GetBufferPointer(), blob->GetBufferSize(), nullptr, &cs_lens_flare);
511 | blob->Release();
512 |
513 | CompileShaderFromFile(L"post.hlsl", "PSToneMapping", "ps_5_0", &blob);
514 | Win.d3d_device->CreatePixelShader(blob->GetBufferPointer(), blob->GetBufferSize(), nullptr, &ps_tonemapper);
515 | blob->Release();
516 |
517 | D3D_SHADER_MACRO tonemapping_debug_flags[] = { "DISPLAY_PERF_DATA", "", 0, 0 };
518 | CompileShaderFromFile(L"post.hlsl", "PSToneMapping", "ps_5_0", &blob, tonemapping_debug_flags);
519 | Win.d3d_device->CreatePixelShader(blob->GetBufferPointer(), blob->GetBufferSize(), nullptr, &ps_tonemapper_debug);
520 | blob->Release();
521 |
522 | CompileShaderFromFile(L"starburst.hlsl", "VSStarburst", "vs_5_0", &blob);
523 | Win.d3d_device->CreateVertexShader(blob->GetBufferPointer(), blob->GetBufferSize(), nullptr, &vs_starburst);
524 | blob->Release();
525 |
526 | CompileShaderFromFile(L"starburst.hlsl", "PSStarburst", "ps_5_0", &blob);
527 | Win.d3d_device->CreatePixelShader(blob->GetBufferPointer(), blob->GetBufferSize(), nullptr, &ps_starburst);
528 | blob->Release();
529 |
530 | CompileShaderFromFile(L"starburst.hlsl", "PSStarburstFromFFT", "ps_5_0", &blob);
531 | Win.d3d_device->CreatePixelShader(blob->GetBufferPointer(), blob->GetBufferSize(), nullptr, &ps_starburst_from_fft);
532 | blob->Release();
533 |
534 | CompileShaderFromFile(L"starburst.hlsl", "PSStarburstFilter", "ps_5_0", &blob);
535 | Win.d3d_device->CreatePixelShader(blob->GetBufferPointer(), blob->GetBufferSize(), nullptr, &ps_starburst_filter);
536 | blob->Release();
537 |
538 | CompileShaderFromFile(L"aperture.hlsl", "PSAperture", "ps_5_0", &blob);
539 | Win.d3d_device->CreatePixelShader(blob->GetBufferPointer(), blob->GetBufferSize(), nullptr, &ps_aperture);
540 | blob->Release();
541 |
542 | int butterfly_count = (int)(logf(App.aperture_resolution) / logf(2.0));
543 | string resolution_string = to_string((int)App.aperture_resolution);
544 | string butterfly_string = to_string(butterfly_count);
545 | D3D_SHADER_MACRO fft_defines_row[] = {
546 | "LENGTH", resolution_string.c_str(),
547 | "BUTTERFLY_COUNT", butterfly_string.c_str(),
548 | "ROWPASS", "", 0, 0 };
549 | CompileShaderFromFile(L"fft.hlsl", "ButterflySLM", "cs_5_0", &blob, fft_defines_row);
550 | Win.d3d_device->CreateComputeShader(blob->GetBufferPointer(), blob->GetBufferSize(), nullptr, &cs_fft_row);
551 | blob->Release();
552 |
553 | D3D_SHADER_MACRO fft_defines_col[] = {
554 | "LENGTH", resolution_string.c_str(),
555 | "BUTTERFLY_COUNT", butterfly_string.c_str(),
556 | "ROWCOL", "", 0, 0 };
557 | CompileShaderFromFile(L"fft.hlsl", "ButterflySLM", "cs_5_0", &blob, fft_defines_col);
558 | Win.d3d_device->CreateComputeShader(blob->GetBufferPointer(), blob->GetBufferSize(), nullptr, &cs_fft_col);
559 | blob->Release();
560 |
561 | CompileShaderFromFile(L"copy.hlsl", "CopyTextureCS", "cs_5_0", &blob);
562 | Win.d3d_device->CreateComputeShader(blob->GetBufferPointer(), blob->GetBufferSize(), nullptr, &cs_fft_copy);
563 | blob->Release();
564 | }
565 | } Shaders;
566 |
567 | struct Buffers {
568 | D3D11_RESOURCE_MISC_FLAG DEFAULT_MISC_FLAG = D3D11_RESOURCE_MISC_FLAG(0);
569 | D3D11_BIND_FLAG D3D11_BIND_SR_OR_UA_FLAG = D3D11_BIND_FLAG(D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS);
570 |
571 | ID3D11Buffer* ghostdata = nullptr;
572 | ID3D11Buffer* globaldata = nullptr;
573 | ID3D11Buffer* performance_data = nullptr;
574 | ID3D11Buffer* instance_uniforms = nullptr;
575 | ID3D11Buffer* intersection_points1 = nullptr;
576 | ID3D11Buffer* intersection_points2 = nullptr;
577 | ID3D11Buffer* intersection_points3 = nullptr;
578 | ID3D11Buffer* lens_interface = nullptr;
579 |
580 | ID3D11UnorderedAccessView* ghostdata_view;
581 | ID3D11UnorderedAccessView* lensInterface_view;
582 |
583 | void CreateBuffer(ID3D11Buffer** buffer, UINT size, UINT struct_size, D3D11_BIND_FLAG bind_flag,
584 | D3D11_RESOURCE_MISC_FLAG misc_flag, void* init_data_ptr) {
585 |
586 | D3D11_BUFFER_DESC desc;
587 | ZeroMemory(&desc, sizeof(desc));
588 | desc.Usage = D3D11_USAGE_DEFAULT;
589 | desc.BindFlags = bind_flag;
590 | desc.MiscFlags = misc_flag;
591 | desc.CPUAccessFlags = 0;
592 | desc.StructureByteStride = struct_size;
593 | desc.ByteWidth = size * struct_size;
594 |
595 | D3D11_SUBRESOURCE_DATA init_data = { init_data_ptr, sizeof(init_data), 0 };
596 |
597 | Win.d3d_device->CreateBuffer(&desc, init_data_ptr ? &init_data : nullptr, buffer);
598 | }
599 |
600 | void CreateSRView(ID3D11Buffer* buffer, ID3D11ShaderResourceView** view, UINT num_elements) {
601 | D3D11_SHADER_RESOURCE_VIEW_DESC desc;
602 | ZeroMemory(&desc, sizeof(desc));
603 | desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX;
604 | desc.BufferEx.FirstElement = 0;
605 | desc.Format = DXGI_FORMAT_UNKNOWN;
606 | desc.BufferEx.NumElements = num_elements;
607 |
608 | Win.d3d_device->CreateShaderResourceView(buffer, &desc, view);
609 | }
610 |
611 | void CreateUAView(ID3D11Buffer* buffer, ID3D11UnorderedAccessView** view, UINT num_elements) {
612 | D3D11_UNORDERED_ACCESS_VIEW_DESC desc;
613 | ZeroMemory(&desc, sizeof(desc));
614 | desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
615 | desc.Buffer.FirstElement = 0;
616 | desc.Format = DXGI_FORMAT_UNKNOWN;
617 | desc.Buffer.NumElements = num_elements;
618 |
619 | Win.d3d_device->CreateUnorderedAccessView(buffer, &desc, view);
620 | }
621 |
622 | void InitBuffers() {
623 | CreateBuffer(&globaldata, 1, sizeof(GlobalData), D3D11_BIND_CONSTANT_BUFFER, DEFAULT_MISC_FLAG, 0);
624 | CreateBuffer(&performance_data, 1, sizeof(PerformanceData), D3D11_BIND_CONSTANT_BUFFER, DEFAULT_MISC_FLAG, 0);
625 | CreateBuffer(&instance_uniforms, 1, sizeof(InstanceUniforms), D3D11_BIND_CONSTANT_BUFFER, DEFAULT_MISC_FLAG, 0);
626 | CreateBuffer(&intersection_points1, Lens.num_of_intersections_1, sizeof(SimpleVertex), D3D11_BIND_VERTEX_BUFFER, DEFAULT_MISC_FLAG, 0);
627 | CreateBuffer(&intersection_points2, Lens.num_of_intersections_2, sizeof(SimpleVertex), D3D11_BIND_VERTEX_BUFFER, DEFAULT_MISC_FLAG, 0);
628 | CreateBuffer(&intersection_points3, Lens.num_of_intersections_3, sizeof(SimpleVertex), D3D11_BIND_VERTEX_BUFFER, DEFAULT_MISC_FLAG, 0);
629 | CreateBuffer(&ghostdata, Lens.num_of_ghosts, sizeof(GhostData), D3D11_BIND_UNORDERED_ACCESS, D3D11_RESOURCE_MISC_BUFFER_STRUCTURED, &Lens.ghosts[0]);
630 | CreateBuffer(&lens_interface, (UINT)Lens.lens_interface.size(), sizeof(LensInterface), D3D11_BIND_SR_OR_UA_FLAG, D3D11_RESOURCE_MISC_BUFFER_STRUCTURED, &Lens.lens_interface[0]);
631 |
632 | CreateUAView(ghostdata, &ghostdata_view, Lens.num_of_ghosts);
633 | CreateUAView(lens_interface, &lensInterface_view, (UINT)Lens.lens_interface.size());
634 | }
635 | } Buffers;
636 |
637 | struct States {
638 | ID3D11BlendState* bs_blend = nullptr;
639 | ID3D11BlendState* bs_no_blend = nullptr;
640 | ID3D11BlendState* bs_mask = nullptr;
641 | ID3D11BlendState* bs_add = nullptr;
642 | ID3D11RasterizerState* rs_cull = nullptr;
643 | ID3D11RasterizerState* rs_no_cull = nullptr;
644 | ID3D11RasterizerState* rs_wireframe = nullptr;
645 | ID3D11DepthStencilState* dss_default = nullptr;
646 | ID3D11DepthStencilState* dss_fill = nullptr;
647 | ID3D11DepthStencilState* dss_greater_or_equal_incr = nullptr;
648 | ID3D11DepthStencilState* dss_greater_or_equal_decr = nullptr;
649 | ID3D11DepthStencilState* dss_greater_or_equal_read = nullptr;
650 |
651 | void InitStates() {
652 | D3D11_RASTERIZER_DESC raster_state_desc;
653 |
654 | D3D11_BLEND_DESC bs_blend_desc;
655 | D3D11_BLEND_DESC bs_mask_desc;
656 | D3D11_BLEND_DESC bs_add_desc;
657 | D3D11_BLEND_DESC bs_no_blend_desc;
658 |
659 | D3D11_DEPTH_STENCIL_DESC dss_default_desc;
660 | D3D11_DEPTH_STENCIL_DESC dss_fill_desc;
661 | D3D11_DEPTH_STENCIL_DESC dss_greater_or_equal_incr_desc;
662 | D3D11_DEPTH_STENCIL_DESC dss_greater_or_equal_decr_desc;
663 | D3D11_DEPTH_STENCIL_DESC dss_greater_or_equal_incr_read;
664 |
665 | ZeroMemory(&raster_state_desc, sizeof(D3D11_RASTERIZER_DESC));
666 |
667 | ZeroMemory(&bs_blend_desc, sizeof(D3D11_BLEND_DESC));
668 | ZeroMemory(&bs_no_blend_desc, sizeof(D3D11_BLEND_DESC));
669 | ZeroMemory(&bs_mask_desc, sizeof(D3D11_BLEND_DESC));
670 | ZeroMemory(&bs_add_desc, sizeof(D3D11_BLEND_DESC));
671 |
672 | ZeroMemory(&dss_default_desc, sizeof(D3D11_DEPTH_STENCIL_DESC));
673 | ZeroMemory(&dss_fill_desc, sizeof(D3D11_DEPTH_STENCIL_DESC));
674 | ZeroMemory(&dss_greater_or_equal_incr_desc, sizeof(D3D11_DEPTH_STENCIL_DESC));
675 | ZeroMemory(&dss_greater_or_equal_decr_desc, sizeof(D3D11_DEPTH_STENCIL_DESC));
676 | ZeroMemory(&dss_greater_or_equal_incr_read, sizeof(D3D11_DEPTH_STENCIL_DESC));
677 |
678 | // D3D11_RASTERIZER_DESC
679 | raster_state_desc.FillMode = D3D11_FILL_SOLID;
680 | raster_state_desc.CullMode = D3D11_CULL_BACK;
681 | Win.d3d_device->CreateRasterizerState(&raster_state_desc, &rs_cull);
682 |
683 | raster_state_desc.CullMode = D3D11_CULL_NONE;
684 | Win.d3d_device->CreateRasterizerState(&raster_state_desc, &rs_no_cull);
685 |
686 | raster_state_desc.FillMode = D3D11_FILL_WIREFRAME;
687 | Win.d3d_device->CreateRasterizerState(&raster_state_desc, &rs_wireframe);
688 |
689 | // D3D11_BLEND_DESC
690 | bs_no_blend_desc.RenderTarget[0].BlendEnable = FALSE;
691 |
692 | bs_blend_desc.RenderTarget[0].BlendEnable = TRUE;
693 | bs_blend_desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
694 | bs_blend_desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
695 | bs_blend_desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
696 | bs_blend_desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
697 | bs_blend_desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO;
698 | bs_blend_desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
699 | bs_blend_desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
700 |
701 | bs_mask_desc.RenderTarget[0] = bs_blend_desc.RenderTarget[0];
702 | bs_mask_desc.RenderTarget[0].RenderTargetWriteMask = 0x0;
703 |
704 | bs_add_desc.RenderTarget[0].BlendEnable = TRUE;
705 | bs_add_desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
706 | bs_add_desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
707 | bs_add_desc.RenderTarget[0].DestBlend = D3D11_BLEND_SRC_ALPHA;
708 | bs_add_desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
709 | bs_add_desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
710 | bs_add_desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE;
711 | bs_add_desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
712 |
713 | Win.d3d_device->CreateBlendState(&bs_blend_desc, &bs_blend);
714 | Win.d3d_device->CreateBlendState(&bs_blend_desc, &bs_no_blend);
715 | Win.d3d_device->CreateBlendState(&bs_mask_desc, &bs_mask);
716 | Win.d3d_device->CreateBlendState(&bs_add_desc, &bs_add);
717 |
718 | // D3D11_DEPTH_STENCIL_DESC
719 | dss_default_desc.DepthEnable = FALSE;
720 | dss_default_desc.StencilEnable = FALSE;
721 | dss_default_desc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
722 | dss_default_desc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
723 | dss_default_desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
724 | dss_default_desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
725 | dss_default_desc.BackFace = dss_default_desc.FrontFace;
726 |
727 | dss_fill_desc.DepthEnable = FALSE;
728 | dss_fill_desc.StencilEnable = TRUE;
729 | dss_fill_desc.StencilWriteMask = 0xFF;
730 | dss_fill_desc.StencilReadMask = 0xFF;
731 | dss_fill_desc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_REPLACE;
732 | dss_fill_desc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_REPLACE;
733 | dss_fill_desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE;
734 | dss_fill_desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
735 | dss_fill_desc.BackFace = dss_fill_desc.FrontFace;
736 |
737 | dss_greater_or_equal_incr_desc.DepthEnable = FALSE;
738 | dss_greater_or_equal_incr_desc.StencilEnable = TRUE;
739 | dss_greater_or_equal_incr_desc.StencilWriteMask = 0xFF;
740 | dss_greater_or_equal_incr_desc.StencilReadMask = 0xFF;
741 | dss_greater_or_equal_incr_desc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
742 | dss_greater_or_equal_incr_desc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
743 | dss_greater_or_equal_incr_desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_INCR;
744 | dss_greater_or_equal_incr_desc.FrontFace.StencilFunc = D3D11_COMPARISON_LESS_EQUAL;
745 | dss_greater_or_equal_incr_desc.BackFace = dss_greater_or_equal_incr_desc.FrontFace;
746 |
747 | dss_greater_or_equal_decr_desc = dss_greater_or_equal_incr_desc;
748 | dss_greater_or_equal_decr_desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_DECR;
749 | dss_greater_or_equal_decr_desc.BackFace = dss_greater_or_equal_decr_desc.FrontFace;
750 |
751 | dss_greater_or_equal_incr_read = dss_greater_or_equal_incr_desc;
752 | dss_greater_or_equal_incr_read.StencilWriteMask = 0X00;
753 | dss_greater_or_equal_incr_read.FrontFace.StencilFunc = D3D11_COMPARISON_LESS_EQUAL;
754 | dss_greater_or_equal_incr_read.BackFace = dss_greater_or_equal_incr_read.FrontFace;
755 |
756 | Win.d3d_device->CreateDepthStencilState(&dss_default_desc, &dss_default);
757 | Win.d3d_device->CreateDepthStencilState(&dss_fill_desc, &dss_fill);
758 | Win.d3d_device->CreateDepthStencilState(&dss_greater_or_equal_incr_desc, &dss_greater_or_equal_incr);
759 | Win.d3d_device->CreateDepthStencilState(&dss_greater_or_equal_decr_desc, &dss_greater_or_equal_decr);
760 | Win.d3d_device->CreateDepthStencilState(&dss_greater_or_equal_incr_read, &dss_greater_or_equal_read);
761 | }
762 | } States;
763 |
764 | struct GPUQueries {
765 |
766 | ID3D11Query* disjoint;
767 | ID3D11Query* frame_start;
768 | ID3D11Query* frame_end;
769 | ID3D11Query* aperture_start;
770 | ID3D11Query* aperture_end;
771 | ID3D11Query* starburst_start;
772 | ID3D11Query* starburst_end;
773 | ID3D11Query* lensflare_compute_start;
774 | ID3D11Query* lensflare_compute_end;
775 | ID3D11Query* lensflare_draw_start;
776 | ID3D11Query* lensflare_draw_end;
777 |
778 | void InitQueries() {
779 | D3D11_QUERY_DESC time_stamp = { D3D11_QUERY_TIMESTAMP, 0 };
780 | D3D11_QUERY_DESC time_stamp_disjoint = { D3D11_QUERY_TIMESTAMP_DISJOINT, 0 };
781 |
782 | Win.d3d_device->CreateQuery(&time_stamp_disjoint, &disjoint);
783 | Win.d3d_device->CreateQuery(&time_stamp, &frame_start);
784 | Win.d3d_device->CreateQuery(&time_stamp, &frame_end);
785 | Win.d3d_device->CreateQuery(&time_stamp, &aperture_start);
786 | Win.d3d_device->CreateQuery(&time_stamp, &aperture_end);
787 | Win.d3d_device->CreateQuery(&time_stamp, &starburst_start);
788 | Win.d3d_device->CreateQuery(&time_stamp, &starburst_end);
789 | Win.d3d_device->CreateQuery(&time_stamp, &lensflare_compute_start);
790 | Win.d3d_device->CreateQuery(&time_stamp, &lensflare_compute_end);
791 | Win.d3d_device->CreateQuery(&time_stamp, &lensflare_draw_start);
792 | Win.d3d_device->CreateQuery(&time_stamp, &lensflare_draw_end);
793 | }
794 |
795 | static void PrintGPUTimes(GPUQueries& queries) {
796 | while (Win.d3d_context->GetData(queries.disjoint, NULL, 0, 0) == S_FALSE) {
797 | Sleep(1);
798 | }
799 |
800 | D3D10_QUERY_DATA_TIMESTAMP_DISJOINT disjoint_data;
801 | Win.d3d_context->GetData(queries.disjoint, &disjoint_data, sizeof(disjoint_data), 0);
802 |
803 | UINT64 frame_start, frame_end, aperture_start, aperture_end, starburst_start, starburst_end, compute_start, compute_end, draw_start, draw_end = 0;
804 | Win.d3d_context->GetData(queries.frame_start, &frame_start, sizeof(UINT64), 0);
805 | Win.d3d_context->GetData(queries.frame_end, &frame_end, sizeof(UINT64), 0);
806 | Win.d3d_context->GetData(queries.aperture_start, &aperture_start, sizeof(UINT64), 0);
807 | Win.d3d_context->GetData(queries.aperture_end, &aperture_end, sizeof(UINT64), 0);
808 | Win.d3d_context->GetData(queries.starburst_start, &starburst_start, sizeof(UINT64), 0);
809 | Win.d3d_context->GetData(queries.starburst_end, &starburst_end, sizeof(UINT64), 0);
810 | Win.d3d_context->GetData(queries.lensflare_compute_start, &compute_start, sizeof(UINT64), 0);
811 | Win.d3d_context->GetData(queries.lensflare_compute_end, &compute_end, sizeof(UINT64), 0);
812 | Win.d3d_context->GetData(queries.lensflare_draw_start, &draw_start, sizeof(UINT64), 0);
813 | Win.d3d_context->GetData(queries.lensflare_draw_end, &draw_end, sizeof(UINT64), 0);
814 |
815 | float denum = float(disjoint_data.Frequency) / 1000.f;
816 | float ms_frame = float(frame_end - frame_start) / denum;
817 | float ms_compute = float(compute_end - compute_start) / denum;
818 | float ms_draw = float(draw_end - draw_start) / denum;
819 | float ms_aperture = float(aperture_end - aperture_start) / denum;
820 | float ms_startburst = float(starburst_end - starburst_start) / denum;
821 |
822 | PerformanceData updated_performance_data = { ms_frame, ms_compute, ms_draw, ms_aperture + ms_startburst };
823 | Win.d3d_context->UpdateSubresource(Buffers.performance_data, 0, nullptr, &updated_performance_data, 0, 0);
824 |
825 | }
826 |
827 | } GPUQueries;
828 |
829 | struct Shapes {
830 | struct Square {
831 | ID3D11Buffer* indices;
832 | ID3D11Buffer* vertices;
833 | ID3D11Buffer* lines;
834 | };
835 |
836 | struct Circle {
837 | float x, y, r;
838 | ID3D11Buffer* triangles;
839 | ID3D11Buffer* lines;
840 | };
841 |
842 | struct RayBundle {
843 | int subdiv;
844 | ID3D11Buffer* indices;
845 | ID3D11Buffer* cs_vertices;
846 | ID3D11Buffer* cs_group_count_info;
847 | ID3D11ShaderResourceView* vertices_resource_view;
848 | ID3D11UnorderedAccessView* ua_vertices_resource_view;
849 | };
850 |
851 | Square CreateUnitSquare() {
852 | float l = -1.f;
853 | float r = 1.f;
854 | float b = -1.f / App.ratio;
855 | float t = 1.f / App.ratio;
856 |
857 | SimpleVertex vertices[] = {
858 | XMFLOAT3(l, b, 0.f),
859 | XMFLOAT3(l, t, 0.f),
860 | XMFLOAT3(r, t, 0.f),
861 | XMFLOAT3(l, b, 0.f),
862 | XMFLOAT3(r, b, 0.f),
863 | XMFLOAT3(r, t, 0.f),
864 | };
865 |
866 | SimpleVertex lines[] = {
867 | XMFLOAT3(l, b, 0.f),
868 | XMFLOAT3(l, t, 0.f),
869 | XMFLOAT3(r, t, 0.f),
870 | XMFLOAT3(r, b, 0.f),
871 | XMFLOAT3(l, b, 0.f),
872 | };
873 |
874 | unsigned int indices[] = { 2, 0, 1, 1, 3, 2 };
875 |
876 | Square square;
877 |
878 | Buffers.CreateBuffer(&square.indices, 6, sizeof(unsigned int), D3D11_BIND_INDEX_BUFFER, Buffers.DEFAULT_MISC_FLAG, &indices[0]);
879 | Buffers.CreateBuffer(&square.vertices, 6, sizeof(SimpleVertex), D3D11_BIND_VERTEX_BUFFER, Buffers.DEFAULT_MISC_FLAG, &vertices[0]);
880 | Buffers.CreateBuffer(&square.lines, 5, sizeof(SimpleVertex), D3D11_BIND_VERTEX_BUFFER, Buffers.DEFAULT_MISC_FLAG, &lines[0]);
881 |
882 | return square;
883 | }
884 |
885 | Circle CreateUnitCircle() {
886 | vector triangle_vertices;
887 | vector line_vertices;
888 |
889 | triangle_vertices.resize(App.num_points_per_cirlces * 3);
890 | for (int i = 0; i < App.num_points_per_cirlces - 1; i++) {
891 |
892 | float t1 = (float)i / (float)(App.num_points_per_cirlces - 1);
893 | float a1 = t1 * 2.f * PI;
894 | float x1 = sin(a1);
895 | float y1 = cos(a1) / App.ratio;
896 |
897 | float t2 = (float)(i + 1) / (float)(App.num_points_per_cirlces - 1);
898 | float a2 = t2 * 2.f * PI;
899 | float x2 = sin(a2);
900 | float y2 = cos(a2) / App.ratio;
901 |
902 | SimpleVertex to_add1 = XMFLOAT3(x1, y1, 0.f);
903 | SimpleVertex to_add2 = XMFLOAT3(x2, y2, 0.f);
904 | SimpleVertex to_add3 = XMFLOAT3(0.f, 0.f, 0.f);
905 |
906 | triangle_vertices[i * 3 + 0] = to_add1;
907 | triangle_vertices[i * 3 + 1] = to_add2;
908 | triangle_vertices[i * 3 + 2] = to_add3;
909 |
910 | line_vertices.push_back(to_add1);
911 | }
912 |
913 | SimpleVertex to_add = XMFLOAT3(0.f, 1.f / App.ratio, 0.f);
914 | line_vertices.push_back(to_add);
915 |
916 | Circle circle = { 0.f, 0.f, 1.f };
917 |
918 | Buffers.CreateBuffer(&circle.triangles, App.num_vertices_per_cirlces, sizeof(SimpleVertex), D3D11_BIND_VERTEX_BUFFER, Buffers.DEFAULT_MISC_FLAG, &triangle_vertices[0]);
919 | Buffers.CreateBuffer(&circle.lines, App.num_points_per_cirlces, sizeof(SimpleVertex), D3D11_BIND_VERTEX_BUFFER, Buffers.DEFAULT_MISC_FLAG, &line_vertices[0]);
920 |
921 | return circle;
922 | }
923 |
924 | RayBundle CreateRayBundle(int subdiv, int num_patches) {
925 |
926 | float l = -1.0f;
927 | float r = 1.0f;
928 | float b = -1.0f;
929 | float t = 1.0f;
930 |
931 | vector vertices;
932 | vector indices;
933 |
934 | vertices.resize(subdiv * subdiv * num_patches);
935 | for (int n = 0; n < num_patches; ++n) {
936 | for (int y = 0; y < subdiv; ++y) {
937 | float ny = (float)y / (float)(subdiv - 1);
938 | for (int x = 0; x < subdiv; ++x) {
939 | float nx = (float)x / (float)(subdiv - 1);
940 | float x_pos = Lerp(l, r, nx);
941 | float y_pos = Lerp(t, b, ny);
942 | vertices[n * subdiv * subdiv + y * subdiv + x] = { XMFLOAT3(x_pos, y_pos, 0.f) };
943 | }
944 | }
945 | }
946 |
947 | int current_corner = 0;
948 | int num_indices_per_patch = (subdiv - 1) * (subdiv - 1) * 6;
949 | indices.resize(num_indices_per_patch * num_patches);
950 | for (int n = 0; n < num_patches; ++n) {
951 | for (int y = 0; y < (subdiv - 1); ++y) {
952 | for (int x = 0; x < (subdiv - 1); ++x) {
953 | int i = (y * (subdiv - 1) + x) * 6 + num_indices_per_patch * n;
954 |
955 | int i1 = current_corner;
956 | int i2 = i1 + 1;
957 | int i3 = i1 + subdiv;
958 | int i4 = i2 + subdiv;
959 |
960 | indices[i + 0] = i3;
961 | indices[i + 1] = i1;
962 | indices[i + 2] = i2;
963 |
964 | indices[i + 3] = i2;
965 | indices[i + 4] = i4;
966 | indices[i + 5] = i3;
967 |
968 | current_corner++;
969 | }
970 | current_corner++;
971 | }
972 | }
973 |
974 | RayBundle bundle_data;
975 | bundle_data.subdiv = subdiv;
976 |
977 | int num_of_indices = (subdiv - 1) * (subdiv - 1) * num_patches * 6;
978 | int num_of_vertices = (subdiv * subdiv) * num_patches;
979 | void* vertex_data = malloc(sizeof(PSInput) * num_of_vertices);
980 | CSIndirectData group_count_info = { (unsigned)Lens.num_of_ghosts * App.num_groups, (unsigned)App.num_groups, 3 };
981 |
982 | Buffers.CreateBuffer(&bundle_data.indices, num_of_indices, sizeof(unsigned int), D3D11_BIND_INDEX_BUFFER, Buffers.DEFAULT_MISC_FLAG, &indices[0]);
983 | Buffers.CreateBuffer(&bundle_data.cs_vertices, num_of_vertices, sizeof(PSInput), Buffers.D3D11_BIND_SR_OR_UA_FLAG, D3D11_RESOURCE_MISC_BUFFER_STRUCTURED, vertex_data);
984 | Buffers.CreateBuffer(&bundle_data.cs_group_count_info, 1, sizeof(CSIndirectData), D3D11_BIND_UNORDERED_ACCESS, D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS, &group_count_info);
985 |
986 | Buffers.CreateSRView(bundle_data.cs_vertices, &bundle_data.vertices_resource_view, num_of_vertices);
987 | Buffers.CreateUAView(bundle_data.cs_vertices, &bundle_data.ua_vertices_resource_view, num_of_vertices);
988 |
989 | return bundle_data;
990 | }
991 |
992 | Square unit_square;
993 | Circle unit_circle;
994 | RayBundle ray_bundle;
995 |
996 | void InitShapes() {
997 | unit_square = CreateUnitSquare();
998 | unit_circle = CreateUnitCircle();
999 | ray_bundle = CreateRayBundle(App.patch_tesselation, Lens.num_of_ghosts);
1000 | }
1001 | } Shapes;
1002 |
1003 | // ---------------------------------------------------------------------------------------------------------
1004 | // Helper Functions
1005 | // ---------------------------------------------------------------------------------------------------------
1006 | void UpdateLensComponents() {
1007 | Lens.lens_interface[Lens.aperture_id].sa = UI.aperture_opening;
1008 | LensInterface aperture_component = Lens.lens_interface[Lens.aperture_id];
1009 | D3D11_BOX box = { Lens.aperture_id * sizeof(LensInterface), 0, 0, (Lens.aperture_id + 1) * sizeof(LensInterface), 1, 1 };
1010 | Win.d3d_context->UpdateSubresource(Buffers.lens_interface, 0, &box, &aperture_component, 0, 0);
1011 | }
1012 |
1013 | void ParseLensComponents() {
1014 | // Parse the lens components into the LensInterface the ray_trace routine expects
1015 | Lens.lens_interface.resize(Lens.num_of_lens_components);
1016 | for (int i = Lens.num_of_lens_components - 1; i >= 0; --i) {
1017 | PatentFormat& entry = Lens.lens_components[i];
1018 | Lens.total_lens_distance += entry.d;
1019 |
1020 | float left_ior = i == 0 ? 1.f : Lens.lens_components[i - 1].n;
1021 | float right_ior = entry.n;
1022 |
1023 | if (right_ior != 1.f) {
1024 | Lens.min_ior = min(Lens.min_ior, right_ior);
1025 | Lens.max_ior = max(Lens.max_ior, right_ior);
1026 | }
1027 |
1028 | vec3 center = { 0.f, 0.f, Lens.total_lens_distance - entry.r };
1029 | vec3 n = { left_ior, 1.f, right_ior };
1030 |
1031 | LensInterface component = { center, entry.r, n, entry.h, entry.c, (float)entry.f, Lens.total_lens_distance, entry.w };
1032 | Lens.lens_interface[i] = component;
1033 | }
1034 |
1035 | // Enumerate all possible ghosts of the lens system
1036 | int bounce1 = 2;
1037 | int bounce2 = 1;
1038 | int ghost_index = 0;
1039 | Lens.ghosts.resize(Lens.num_of_ghosts);
1040 | while (true) {
1041 | if (bounce1 >= (int)(Lens.lens_interface.size() - 1)) {
1042 | bounce2++;
1043 | bounce1 = bounce2 + 1;
1044 | }
1045 |
1046 | if (bounce2 >= (int)(Lens.lens_interface.size() - 1)) {
1047 | break;
1048 | }
1049 |
1050 | Lens.ghosts[ghost_index] = XMFLOAT4((float)bounce1, (float)bounce2, 0, 0);
1051 | bounce1++;
1052 | ghost_index++;
1053 | }
1054 | }
1055 |
1056 | void DrawRectangle(ID3D11DeviceContext* context, Shapes::Square& rectangle, XMFLOAT4& color, XMFLOAT4& placement, bool filled) {
1057 | InstanceUniforms cb = { color, placement };
1058 | context->UpdateSubresource(Buffers.instance_uniforms, 0, nullptr, &cb, 0, 0);
1059 | if (filled) {
1060 | context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
1061 | context->IASetVertexBuffers(0, 1, &rectangle.vertices, &Win.stride, &Win.offset);
1062 | context->Draw(6, 0);
1063 | } else {
1064 | context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP);
1065 | context->IASetVertexBuffers(0, 1, &rectangle.lines, &Win.stride, &Win.offset);
1066 | context->Draw(5, 0);
1067 | }
1068 | }
1069 |
1070 | void DrawFullscreenQuad(ID3D11DeviceContext* context, Shapes::Square& rectangle, XMFLOAT4& color,
1071 | ID3D11RenderTargetView*& rt_view, ID3D11DepthStencilView*& depth_buffer_view) {
1072 |
1073 | InstanceUniforms cb = { color, XMFLOAT4(0.f, 0.f, 0.f, 0.f) };
1074 | context->UpdateSubresource(Buffers.instance_uniforms, 0, nullptr, &cb, 0, 0);
1075 |
1076 | context->RSSetState(States.rs_cull);
1077 |
1078 | context->OMSetBlendState(States.bs_no_blend, Win.blend_factor, Win.sample_mask);
1079 | context->OMSetDepthStencilState(States.dss_default, 0);
1080 | context->OMSetRenderTargets(1, &rt_view, depth_buffer_view);
1081 | context->ClearRenderTargetView(rt_view, XMVECTORF32{ 0, 0, 0, 0 });
1082 | context->ClearDepthStencilView(depth_buffer_view, D3D11_CLEAR_DEPTH, 1.0f, 0);
1083 |
1084 | context->IASetInputLayout(Win.d3d_vertex_layout_2d);
1085 | context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
1086 | context->IASetVertexBuffers(0, 1, &rectangle.vertices, &Win.stride, &Win.offset);
1087 | context->IASetIndexBuffer(rectangle.indices, DXGI_FORMAT_R32_UINT, 0);
1088 |
1089 | context->Draw(6, 0);
1090 |
1091 | Win.d3d_context->OMSetRenderTargets(1, &Textures.backbuffer_rt_view, Textures.depthstencil_view);
1092 |
1093 | }
1094 |
1095 | void DrawCircle(ID3D11DeviceContext* context, Shapes::Circle& circle, XMFLOAT4& color, XMFLOAT4& placement, bool filled) {
1096 | InstanceUniforms cb = { color, placement };
1097 | context->UpdateSubresource(Buffers.instance_uniforms, 0, nullptr, &cb, 0, 0);
1098 | if (filled) {
1099 | context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
1100 | context->IASetVertexBuffers(0, 1, &circle.triangles, &Win.stride, &Win.offset);
1101 | context->Draw(App.num_vertices_per_cirlces, 0);
1102 | } else {
1103 | context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP);
1104 | context->IASetVertexBuffers(0, 1, &circle.lines, &Win.stride, &Win.offset);
1105 | context->Draw(App.num_points_per_cirlces, 0);
1106 | }
1107 | }
1108 |
1109 | void DrawFlat(LensInterface& right) {
1110 | float mx = -(right.pos * App.global_scale - 1.f);
1111 | float mw = App.global_scale * 0.4f;
1112 |
1113 | XMFLOAT4 mask_placement1 = { mx, 1.f, mw * 1.00f, App.global_scale * right.w };
1114 | XMFLOAT4 mask_placement2 = { mx, 1.f, mw * 1.01f, App.global_scale * right.sa };
1115 | XMFLOAT4 mask_placement3 = { mx + 0.0001f, 1.f, mw * 0.9f, App.global_scale * right.w };
1116 |
1117 | Win.d3d_context->OMSetBlendState(States.bs_mask, Win.blend_factor, Win.sample_mask);
1118 | Win.d3d_context->OMSetDepthStencilState(States.dss_fill, 1);
1119 | DrawRectangle(Win.d3d_context, Shapes.unit_square, ColorTheme.flat_fill, mask_placement1, true);
1120 |
1121 | Win.d3d_context->OMSetDepthStencilState(States.dss_fill, 0);
1122 | DrawRectangle(Win.d3d_context, Shapes.unit_square, ColorTheme.flat_fill, mask_placement2, true);
1123 |
1124 | Win.d3d_context->OMSetDepthStencilState(States.dss_greater_or_equal_read, 1);
1125 | Win.d3d_context->OMSetBlendState(States.bs_blend, Win.blend_factor, Win.sample_mask);
1126 | DrawRectangle(Win.d3d_context, Shapes.unit_square, ColorTheme.flat_fill, mask_placement3, true);
1127 | DrawRectangle(Win.d3d_context, Shapes.unit_square, ColorTheme.stroke, mask_placement3, false);
1128 | }
1129 |
1130 | XMFLOAT4 LensColor(float ior, XMFLOAT4& c1, XMFLOAT4&c2) {
1131 | float normalized_ior = (ior - Lens.min_ior) / (Lens.max_ior - Lens.min_ior);
1132 | return Lerp(c1, c2, normalized_ior);
1133 | //return normalized_ior < 0.5f ? c1 : c2;
1134 | }
1135 |
1136 | XMFLOAT4 IntersectionColor(int i) {
1137 | float ior1 = Lens.lens_interface[i].n.x == 1.f ? Lens.lens_interface[i].n.z : Lens.lens_interface[i].n.x;
1138 | return LensColor(ior1, ColorTheme.intersection2, ColorTheme.intersection3);
1139 | }
1140 |
1141 | void DrawLens(LensInterface& left, LensInterface& right, bool opaque) {
1142 | XMFLOAT4 fill_color = LensColor(right.n.x, ColorTheme.fill1, ColorTheme.fill2);
1143 | fill_color.w = opaque ? ColorTheme.alpha : fill_color.w;
1144 |
1145 | if (opaque)
1146 | ColorTheme.stroke = ColorTheme.stroke1;
1147 | else
1148 | ColorTheme.stroke = ColorTheme.stroke2;
1149 |
1150 | // |\ /|
1151 | // | | | |
1152 | // | | or | |
1153 | // | | | |
1154 | // |/ \|
1155 | if (Sign(left.radius) == Sign(right.radius)) {
1156 | LensInterface _left = left;
1157 | LensInterface _right = right;
1158 | float eps = 0.001f;
1159 |
1160 | float min_radius = max(left.radius, right.radius);
1161 | if ((right.radius) > 0 && (left.radius > 0.f)) {
1162 | min_radius = min(left.radius, right.radius);
1163 | eps *= -1.f;
1164 | _left = right;
1165 | _right = left;
1166 | }
1167 |
1168 | float delta = abs(_right.pos - _left.pos) * 0.5f;
1169 | float mx = -(_right.pos * App.global_scale - 1.f) + eps;
1170 | float mw = (min_radius - delta) * App.global_scale * right.w;
1171 | float mh = App.global_scale * right.sa;
1172 | XMFLOAT4 mask_placement = { mx, 1.f, mw, mh * 1.001f };
1173 | XMFLOAT4 mask_placement2 = { mx, 1.f, mw * 0.995f, mh * 0.997f };
1174 |
1175 | float rx = -(_right.pos * App.global_scale - 1.f);
1176 | float rr = _right.radius * App.global_scale;
1177 | XMFLOAT4 right_placement = { rx, 1.f, rr, rr };
1178 |
1179 | float lx = -(_left.pos * App.global_scale - 1.f);
1180 | float lr = _left.radius * App.global_scale;
1181 | XMFLOAT4 left_placement = { lx, 1.f, lr, lr };
1182 |
1183 | Win.d3d_context->ClearDepthStencilView(Textures.depthstencil_view, D3D11_CLEAR_STENCIL, 1.0f, 0);
1184 | Win.d3d_context->OMSetBlendState(States.bs_mask, Win.blend_factor, Win.sample_mask);
1185 | Win.d3d_context->OMSetDepthStencilState(States.dss_fill, 1);
1186 | DrawRectangle(Win.d3d_context, Shapes.unit_square, ColorTheme.stroke, mask_placement, true);
1187 |
1188 | Win.d3d_context->OMSetDepthStencilState(States.dss_greater_or_equal_incr, 1);
1189 | DrawCircle(Win.d3d_context, Shapes.unit_circle, fill_color, right_placement, true);
1190 |
1191 | Win.d3d_context->OMSetDepthStencilState(States.dss_greater_or_equal_decr, 2);
1192 | DrawCircle(Win.d3d_context, Shapes.unit_circle, fill_color, left_placement, true);
1193 |
1194 | Win.d3d_context->OMSetBlendState(States.bs_blend, Win.blend_factor, Win.sample_mask);
1195 | Win.d3d_context->OMSetDepthStencilState(States.dss_greater_or_equal_read, 2);
1196 | DrawRectangle(Win.d3d_context, Shapes.unit_square, fill_color, mask_placement, true);
1197 | DrawRectangle(Win.d3d_context, Shapes.unit_square, ColorTheme.stroke, mask_placement2, false);
1198 |
1199 | Win.d3d_context->OMSetBlendState(States.bs_mask, Win.blend_factor, Win.sample_mask);
1200 | Win.d3d_context->OMSetDepthStencilState(States.dss_fill, 1);
1201 | DrawRectangle(Win.d3d_context, Shapes.unit_square, ColorTheme.stroke, mask_placement, true);
1202 |
1203 | Win.d3d_context->OMSetDepthStencilState(States.dss_greater_or_equal_read, 1);
1204 | Win.d3d_context->OMSetBlendState(States.bs_blend, Win.blend_factor, Win.sample_mask);
1205 | DrawCircle(Win.d3d_context, Shapes.unit_circle, ColorTheme.stroke, left_placement, false);
1206 | DrawCircle(Win.d3d_context, Shapes.unit_circle, ColorTheme.stroke, right_placement, false);
1207 | }
1208 | // / \
1209 | // | |
1210 | // | |
1211 | // | |
1212 | // \ /
1213 | else if (left.radius > 0.f && right.radius < 0.f) {
1214 | float eps = 0.001f;
1215 | float delta = abs(right.pos - left.pos);
1216 | float mx = -(right.pos * App.global_scale - 1.f) + eps;
1217 | float mw = -delta * App.global_scale * right.w - eps;
1218 | float mh = App.global_scale * right.sa;
1219 | XMFLOAT4 mask_placement = { mx, 1.f, mw, mh };
1220 | XMFLOAT4 mask_placement2 = { mx, 1.f, mw * 0.995f, mh * 0.997f };
1221 |
1222 | float lx = -(left.pos * App.global_scale - 1.f);
1223 | float lr = left.radius * App.global_scale;
1224 | XMFLOAT4 left_placement = { lx, 1.f, lr, lr };
1225 |
1226 | float rx = -(right.pos * App.global_scale - 1.f);
1227 | float rr = right.radius * App.global_scale;
1228 | XMFLOAT4 right_placement = { rx, 1.f, rr, rr };
1229 |
1230 | Win.d3d_context->ClearDepthStencilView(Textures.depthstencil_view, D3D11_CLEAR_STENCIL, 1.0f, 0);
1231 | Win.d3d_context->OMSetBlendState(States.bs_mask, Win.blend_factor, Win.sample_mask);
1232 | Win.d3d_context->OMSetDepthStencilState(States.dss_fill, 1);
1233 | DrawRectangle(Win.d3d_context, Shapes.unit_square, ColorTheme.stroke, mask_placement, true);
1234 | Win.d3d_context->OMSetDepthStencilState(States.dss_greater_or_equal_incr, 1);
1235 | DrawCircle(Win.d3d_context, Shapes.unit_circle, ColorTheme.stroke, left_placement, true);
1236 |
1237 | Win.d3d_context->OMSetDepthStencilState(States.dss_greater_or_equal_incr, 2);
1238 | Win.d3d_context->OMSetBlendState(States.bs_blend, Win.blend_factor, Win.sample_mask);
1239 | DrawCircle(Win.d3d_context, Shapes.unit_circle, fill_color, right_placement, true);
1240 |
1241 | Win.d3d_context->OMSetDepthStencilState(States.dss_greater_or_equal_read, 3);
1242 | DrawRectangle(Win.d3d_context, Shapes.unit_square, ColorTheme.stroke, mask_placement2, false);
1243 |
1244 | Win.d3d_context->ClearDepthStencilView(Textures.depthstencil_view, D3D11_CLEAR_STENCIL, 1.0f, 0);
1245 | Win.d3d_context->OMSetDepthStencilState(States.dss_fill, 1);
1246 | Win.d3d_context->OMSetBlendState(States.bs_mask, Win.blend_factor, Win.sample_mask);
1247 | DrawRectangle(Win.d3d_context, Shapes.unit_square, ColorTheme.stroke, mask_placement, true);
1248 |
1249 | Win.d3d_context->OMSetDepthStencilState(States.dss_greater_or_equal_read, 1);
1250 | Win.d3d_context->OMSetBlendState(States.bs_blend, Win.blend_factor, Win.sample_mask);
1251 | DrawCircle(Win.d3d_context, Shapes.unit_circle, ColorTheme.stroke, left_placement, false);
1252 | DrawCircle(Win.d3d_context, Shapes.unit_circle, ColorTheme.stroke, right_placement, false);
1253 | }
1254 | // \ /
1255 | // | |
1256 | // | |
1257 | // | |
1258 | // / \
1259 | else if (left.radius < 0.f && right.radius > 0.f) {
1260 | float delta = abs(right.pos - left.pos);
1261 | float w = delta * right.w;
1262 | float mx = -((right.pos + delta * 0.5f + w) * App.global_scale - 1.f);
1263 | float mw = App.global_scale * w;
1264 | float mh = App.global_scale * right.sa;
1265 | XMFLOAT4 mask_placement = { mx, 1.f, mw, mh };
1266 | XMFLOAT4 mask_placement2 = { mx, 1.f, mw * 0.995f, mh * 0.995f };
1267 |
1268 | float lx = -(left.pos * App.global_scale - 1.f);
1269 | float lr = left.radius * App.global_scale;
1270 | XMFLOAT4 left_placement = { lx, 1.f, lr, lr };
1271 |
1272 | float rx = -(right.pos * App.global_scale - 1.f);
1273 | float rr = right.radius * App.global_scale;
1274 | XMFLOAT4 right_placement = { rx, 1.f, rr, rr };
1275 |
1276 | Win.d3d_context->ClearDepthStencilView(Textures.depthstencil_view, D3D11_CLEAR_STENCIL, 1.0f, 0);
1277 | Win.d3d_context->OMSetBlendState(States.bs_mask, Win.blend_factor, Win.sample_mask);
1278 | Win.d3d_context->OMSetDepthStencilState(States.dss_fill, 1);
1279 | DrawRectangle(Win.d3d_context, Shapes.unit_square, fill_color, mask_placement, true);
1280 |
1281 | Win.d3d_context->OMSetDepthStencilState(States.dss_fill, 0);
1282 | DrawCircle(Win.d3d_context, Shapes.unit_circle, fill_color, left_placement, true);
1283 | DrawCircle(Win.d3d_context, Shapes.unit_circle, fill_color, right_placement, true);
1284 |
1285 | Win.d3d_context->OMSetBlendState(States.bs_blend, Win.blend_factor, Win.sample_mask);
1286 | Win.d3d_context->OMSetDepthStencilState(States.dss_greater_or_equal_read, 1);
1287 | DrawRectangle(Win.d3d_context, Shapes.unit_square, fill_color, mask_placement, true);
1288 | DrawRectangle(Win.d3d_context, Shapes.unit_square, ColorTheme.stroke, mask_placement2, false);
1289 |
1290 | Win.d3d_context->OMSetDepthStencilState(States.dss_fill, 1);
1291 | Win.d3d_context->OMSetBlendState(States.bs_mask, Win.blend_factor, Win.sample_mask);
1292 | DrawRectangle(Win.d3d_context, Shapes.unit_square, fill_color, mask_placement, true);
1293 |
1294 | Win.d3d_context->OMSetBlendState(States.bs_blend, Win.blend_factor, Win.sample_mask);
1295 | Win.d3d_context->OMSetDepthStencilState(States.dss_greater_or_equal_read, 1);
1296 | DrawCircle(Win.d3d_context, Shapes.unit_circle, ColorTheme.stroke, left_placement, false);
1297 | DrawCircle(Win.d3d_context, Shapes.unit_circle, ColorTheme.stroke, right_placement, false);
1298 | }
1299 | }
1300 |
1301 | void DrawLensInterface() {
1302 | Win.d3d_context->ClearDepthStencilView(Textures.depthstencil_view, D3D11_CLEAR_STENCIL, 1.0f, 0);
1303 | Win.d3d_context->OMSetDepthStencilState(States.dss_default, 0);
1304 | Win.d3d_context->OMSetBlendState(States.bs_blend, Win.blend_factor, Win.sample_mask);
1305 |
1306 | int i = 0;
1307 | while (i < (int)Lens.lens_interface.size()) {
1308 | bool opaque1 = (i == UI.ghost_bounce_1 - 1);
1309 | bool opaque2 = (i == UI.ghost_bounce_2 - 1);
1310 | if (Lens.lens_interface[i].flat) {
1311 | DrawFlat(Lens.lens_interface[i]);
1312 | i += 1;
1313 | } else if (Lens.lens_interface[i].n.x == 1.f) {
1314 | opaque1 = opaque1 || (i == UI.ghost_bounce_1 - 2);
1315 | opaque2 = opaque2 || (i == UI.ghost_bounce_2 - 2);
1316 | DrawLens(Lens.lens_interface[i], Lens.lens_interface[i + 1], opaque1 || opaque2);
1317 | i += 2;
1318 | } else {
1319 | DrawLens(Lens.lens_interface[i - 1], Lens.lens_interface[i], opaque1 || opaque2);
1320 | i += 1;
1321 | }
1322 | }
1323 | }
1324 |
1325 | inline XMFLOAT3 PointToD3d(vec3& point) {
1326 | float x = point.x;
1327 | float y = point.y / App.ratio * App.global_scale;
1328 | float z = point.z * App.global_scale;
1329 | return XMFLOAT3(-(z - 1.f), y, x);
1330 | }
1331 |
1332 | void DrawIntersections(ID3D11DeviceContext* context, ID3D11Buffer* buffer, vector& intersections, int max_points, XMFLOAT4& color) {
1333 | InstanceUniforms cb;
1334 | cb.color = color;
1335 | cb.placement = XMFLOAT4(0.f, 0.f, 0.f, 0.f);
1336 |
1337 | vector points(max_points);
1338 | for (int i = 0; i < (int)intersections.size(); ++i) {
1339 | points[i] = (PointToD3d(intersections[i]));
1340 | }
1341 |
1342 | void* ptr = &points.front();
1343 | context->UpdateSubresource(buffer, 0, nullptr, ptr, 0, 0);
1344 | context->UpdateSubresource(Buffers.instance_uniforms, 0, nullptr, &cb, 0, 0);
1345 |
1346 | Win.d3d_context->OMSetDepthStencilState(States.dss_default, 0);
1347 | Win.d3d_context->OMSetBlendState(States.bs_blend, Win.blend_factor, Win.sample_mask);
1348 |
1349 | context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP);
1350 | context->IASetVertexBuffers(0, 1, &buffer, &Win.stride, &Win.offset);
1351 | context->Draw((int)intersections.size(), 0);
1352 | }
1353 |
1354 | void UpdateGlobals() {
1355 | App.time += App.time_delta;
1356 |
1357 | #if defined(DRAWLENSFLARE)
1358 | vec3 dir = normalize(vec3(-UI.x_dir, UI.y_dir, -1.f));
1359 | #else
1360 | vec3 dir = normalize(vec3(UI.draw2d ? 0 : -UI.x_dir, UI.y_dir, -1.f));
1361 |
1362 | D3D11_BOX box = { 0, 0, 0, sizeof(GhostData), 1, 1 };
1363 | GhostData updated_ghostdata = { (float)UI.ghost_bounce_1, (float)UI.ghost_bounce_2, 0, 0 };
1364 | Win.d3d_context->UpdateSubresource(Buffers.ghostdata, 0, &box, &updated_ghostdata, 0, 0);
1365 | #endif
1366 |
1367 | UI.direction = XMFLOAT3(dir.x, dir.y, dir.z);
1368 |
1369 | GlobalData updated_globaldata = {
1370 | App.time,
1371 | UI.rays_spread,
1372 | Lens.lens_interface[Lens.lens_interface.size() - 1].sa,
1373 |
1374 | (float)Lens.aperture_id,
1375 | (float)Lens.lens_interface.size(),
1376 | UI.coating_quality,
1377 |
1378 | XMFLOAT2(App.backbuffer_width, App.backbuffer_height),
1379 | XMFLOAT4(UI.direction.x, UI.direction.y, UI.direction.z, App.aperture_resolution),
1380 | XMFLOAT4(UI.aperture_opening, UI.number_of_blades, App.starburst_resolution, 0.f)
1381 | };
1382 |
1383 | Win.d3d_context->UpdateSubresource(Buffers.globaldata, 0, nullptr, &updated_globaldata, 0, 0);
1384 | }
1385 |
1386 | void DrawAperture() {
1387 | Win.d3d_context->End(GPUQueries.aperture_start);
1388 |
1389 | Win.d3d_context->VSSetShader(Shaders.vs_basic, nullptr, 0);
1390 | Win.d3d_context->PSSetShader(Shaders.ps_aperture, nullptr, 0);
1391 | Win.d3d_context->PSSetSamplers(0, 1, &Textures.linear_clamp_sampler);
1392 | Win.d3d_context->PSSetShaderResources(1, 1, &Textures.dust_sr_view);
1393 |
1394 | Win.d3d_context->VSSetConstantBuffers(0, 1, &Buffers.instance_uniforms);
1395 | Win.d3d_context->PSSetConstantBuffers(0, 1, &Buffers.instance_uniforms);
1396 | Win.d3d_context->PSSetConstantBuffers(1, 1, &Buffers.globaldata);
1397 |
1398 | DrawFullscreenQuad(Win.d3d_context, Shapes.unit_square, ColorTheme.fill1, Textures.aperture_rt_view, Textures.aperture_depthbuffer_view);
1399 |
1400 | Win.d3d_context->PSSetShaderResources(1, 1, Textures.null_sr_view);
1401 |
1402 | Win.d3d_context->End(GPUQueries.aperture_end);
1403 | }
1404 |
1405 | void DrawStarBurst() {
1406 | Win.d3d_context->End(GPUQueries.starburst_start);
1407 |
1408 | float clear_color[] = { 0,0,0,0 };
1409 |
1410 | // Setup input
1411 | FFT.CopyTextureNoStretch(Win.d3d_context, Textures.aperture_sr_view, FFT.mTextureUAV[FFT.FFTTexture_Real0], (int)App.aperture_resolution, Shaders.cs_fft_copy);
1412 | Win.d3d_context->ClearRenderTargetView(FFT.mRenderTargetViews[FFT.FFTTexture_Imaginary0], clear_color);
1413 |
1414 | FFT.RunDispatchSLM(Win.d3d_context, 0, Shaders.cs_fft_row, (int)App.aperture_resolution);
1415 | FFT.RunDispatchSLM(Win.d3d_context, 1, Shaders.cs_fft_col, (int)App.aperture_resolution);
1416 |
1417 | D3D11_VIEWPORT vp;
1418 | vp.Width = (FLOAT)App.starburst_resolution;
1419 | vp.Height = (FLOAT)App.starburst_resolution;
1420 | vp.MinDepth = 0.f;
1421 | vp.MaxDepth = 1.f;
1422 | vp.TopLeftX = 0.f;
1423 | vp.TopLeftY = 0.f;
1424 | Win.d3d_context->RSSetViewports(1, &vp);
1425 |
1426 | Win.d3d_context->PSSetShader(Shaders.ps_starburst_from_fft, nullptr, 0);
1427 | Win.d3d_context->PSSetShaderResources(1, 2, FFT.mTextureSRV);
1428 | Win.d3d_context->PSSetSamplers(0, 1, &Textures.linear_wrap_sampler);
1429 | Win.d3d_context->PSSetConstantBuffers(1, 1, &Buffers.globaldata);
1430 | DrawFullscreenQuad(Win.d3d_context, Shapes.unit_square, ColorTheme.fill1, Textures.starburst_rt_view, Textures.starburst_depth_buffer_view);
1431 | Win.d3d_context->PSSetShaderResources(1, 1, Textures.null_sr_view);
1432 |
1433 | Win.d3d_context->PSSetShader(Shaders.ps_starburst_filter, nullptr, 0);
1434 | Win.d3d_context->PSSetShaderResources(1, 1, &Textures.starburst_sr_view);
1435 | Win.d3d_context->PSSetSamplers(0, 1, &Textures.linear_wrap_sampler);
1436 | Win.d3d_context->PSSetConstantBuffers(1, 1, &Buffers.globaldata);
1437 | DrawFullscreenQuad(Win.d3d_context, Shapes.unit_square, ColorTheme.fill1, Textures.starburst_filtered_rt_view, Textures.starburst_depth_buffer_view);
1438 | Win.d3d_context->PSSetShaderResources(1, 1, Textures.null_sr_view);
1439 |
1440 | vp.Width = (FLOAT)App.backbuffer_width;
1441 | vp.Height = (FLOAT)App.backbuffer_height;
1442 | Win.d3d_context->RSSetViewports(1, &vp);
1443 |
1444 | Win.d3d_context->End(GPUQueries.starburst_end);
1445 |
1446 | }
1447 |
1448 | // ---------------------------------------------------------------------------------------------------------
1449 | // Render
1450 | // ---------------------------------------------------------------------------------------------------------
1451 | void Render() {
1452 |
1453 | Win.d3d_context->Begin(GPUQueries.disjoint);
1454 | Win.d3d_context->End(GPUQueries.frame_start);
1455 |
1456 | UpdateGlobals();
1457 |
1458 | if (UI.aperture_needs_updating) {
1459 | DrawAperture();
1460 | DrawStarBurst();
1461 | UI.aperture_needs_updating = false;
1462 | }
1463 |
1464 | #if defined(DRAWLENSFLARE)
1465 | // Setup pipeline
1466 | Win.d3d_context->IASetInputLayout(Win.d3d_vertex_layout_3d);
1467 |
1468 | Win.d3d_context->RSSetState(States.rs_no_cull);
1469 | Win.d3d_context->OMSetRenderTargets(1, &Textures.hdr_rt_view, Textures.depthstencil_view);
1470 | Win.d3d_context->ClearRenderTargetView(Textures.hdr_rt_view, XMVECTORF32{ 0, 0, 0, 0 });
1471 | Win.d3d_context->ClearDepthStencilView(Textures.depthstencil_view, D3D11_CLEAR_DEPTH, 1.0f, 0);
1472 |
1473 | Win.d3d_context->OMSetDepthStencilState(States.dss_default, 0);
1474 | Win.d3d_context->OMSetBlendState(States.bs_add, Win.blend_factor, Win.sample_mask);
1475 |
1476 | Win.d3d_context->IASetIndexBuffer(Shapes.ray_bundle.indices, DXGI_FORMAT_R32_UINT, 0);
1477 | Win.d3d_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
1478 |
1479 | Win.d3d_context->VSSetShader(Shaders.vs_lens_flare, nullptr, 0);
1480 | Win.d3d_context->VSSetConstantBuffers(1, 1, &Buffers.globaldata);
1481 |
1482 | Win.d3d_context->PSSetShader(Shaders.ps_lens_flare, nullptr, 0);
1483 | Win.d3d_context->PSSetConstantBuffers(1, 1, &Buffers.globaldata);
1484 | Win.d3d_context->PSSetShaderResources(1, 1, &Textures.aperture_sr_view);
1485 | Win.d3d_context->PSSetSamplers(0, 1, &Textures.linear_clamp_sampler);
1486 |
1487 | Win.d3d_context->CSSetShader(Shaders.cs_lens_flare, nullptr, 0);
1488 | Win.d3d_context->CSSetConstantBuffers(1, 1, &Buffers.globaldata);
1489 |
1490 | // Ray march
1491 | Win.d3d_context->End(GPUQueries.lensflare_compute_start);
1492 | Win.d3d_context->CSSetUnorderedAccessViews(0, 1, &Shapes.ray_bundle.ua_vertices_resource_view, nullptr);
1493 | Win.d3d_context->CSSetUnorderedAccessViews(1, 1, &Buffers.lensInterface_view, nullptr);
1494 | Win.d3d_context->CSSetUnorderedAccessViews(2, 1, &Buffers.ghostdata_view, nullptr);
1495 | Win.d3d_context->DispatchIndirect(Shapes.ray_bundle.cs_group_count_info, 0);
1496 | Win.d3d_context->CSSetUnorderedAccessViews(0, 1, Textures.null_ua_view, nullptr);
1497 | Win.d3d_context->CSSetUnorderedAccessViews(2, 1, Textures.null_ua_view, nullptr);
1498 | Win.d3d_context->End(GPUQueries.lensflare_compute_end);
1499 |
1500 | // Draw Ghosts
1501 | Win.d3d_context->End(GPUQueries.lensflare_draw_start);
1502 | Win.d3d_context->VSSetShaderResources(0, 1, &Shapes.ray_bundle.vertices_resource_view);
1503 | Win.d3d_context->DrawIndexedInstanced(App.num_vertices_per_bundle * 3 * 2, Lens.num_of_ghosts, 0, 0, 0);
1504 | Win.d3d_context->VSSetShaderResources(0, 1, Textures.null_sr_view);
1505 | Win.d3d_context->End(GPUQueries.lensflare_draw_end);
1506 |
1507 | // Draw Starburst
1508 | Win.d3d_context->VSSetShader(Shaders.vs_starburst, nullptr, 0);
1509 | Win.d3d_context->PSSetShaderResources(1, 1, &Textures.starburst_filtered_sr_view);
1510 | Win.d3d_context->PSSetSamplers(0, 1, &Textures.linear_wrap_sampler);
1511 | Win.d3d_context->PSSetShader(Shaders.ps_starburst, nullptr, 0);
1512 | Win.d3d_context->RSSetState(States.rs_cull);
1513 |
1514 | Win.d3d_context->OMSetBlendState(States.bs_add, Win.blend_factor, Win.sample_mask);
1515 |
1516 | Win.d3d_context->IASetInputLayout(Win.d3d_vertex_layout_2d);
1517 | Win.d3d_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
1518 | Win.d3d_context->IASetVertexBuffers(0, 1, &Shapes.unit_square.vertices, &Win.stride, &Win.offset);
1519 | Win.d3d_context->IASetIndexBuffer(Shapes.unit_square.indices, DXGI_FORMAT_R32_UINT, 0);
1520 |
1521 | Win.d3d_context->Draw(6, 0);
1522 |
1523 | // Tonemap
1524 | Win.d3d_context->RSSetState(States.rs_cull);
1525 | Win.d3d_context->IASetInputLayout(Win.d3d_vertex_layout_2d);
1526 | Win.d3d_context->OMSetRenderTargets(1, &Textures.backbuffer_rt_view, Textures.depthstencil_view);
1527 | Win.d3d_context->ClearRenderTargetView(Textures.backbuffer_rt_view, XMVECTORF32{ 0,0,0,0});
1528 |
1529 | Win.d3d_context->VSSetShader(Shaders.vs_basic, nullptr, 0);
1530 | UI.overlay_wireframe ? Win.d3d_context->PSSetShader(Shaders.ps_tonemapper_debug, nullptr, 0) : Win.d3d_context->PSSetShader(Shaders.ps_tonemapper, nullptr, 0);
1531 | Win.d3d_context->PSSetConstantBuffers(0, 1, &Buffers.instance_uniforms);
1532 | Win.d3d_context->PSSetConstantBuffers(2, 1, &Buffers.performance_data);
1533 | Win.d3d_context->VSSetConstantBuffers(0, 1, &Buffers.instance_uniforms);
1534 | Win.d3d_context->PSSetShaderResources(1, 1, &Textures.hdr_sr_view);
1535 |
1536 | DrawFullscreenQuad(Win.d3d_context, Shapes.unit_square, ColorTheme.fill1, Textures.backbuffer_rt_view, Textures.depthstencil_view);
1537 |
1538 | Win.d3d_context->PSSetShaderResources(1, 1, Textures.null_sr_view);
1539 |
1540 | #else
1541 | if(!UI.draw2d) {
1542 | Win.d3d_context->IASetInputLayout(Win.d3d_vertex_layout_3d);
1543 | Win.d3d_context->IASetIndexBuffer(Shapes.ray_bundle.indices, DXGI_FORMAT_R32_UINT, 0);
1544 | Win.d3d_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
1545 |
1546 | Win.d3d_context->OMSetRenderTargets(1, &Textures.backbuffer_rt_view, Textures.depthstencil_view);
1547 | Win.d3d_context->OMSetDepthStencilState(States.dss_default, 0);
1548 | Win.d3d_context->OMSetBlendState(States.bs_add, Win.blend_factor, Win.sample_mask);
1549 | Win.d3d_context->ClearRenderTargetView(Textures.backbuffer_rt_view, XMVECTORF32{ ColorTheme.background2.x, ColorTheme.background2.y, ColorTheme.background2.z, ColorTheme.background2.w });
1550 | Win.d3d_context->ClearDepthStencilView(Textures.depthstencil_view, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
1551 |
1552 | Win.d3d_context->CSSetShader(Shaders.cs_lens_flare, nullptr, 0);
1553 | Win.d3d_context->CSSetConstantBuffers(1, 1, &Buffers.globaldata);
1554 |
1555 | Win.d3d_context->CSSetUnorderedAccessViews(0, 1, &Shapes.ray_bundle.ua_vertices_resource_view, nullptr);
1556 | Win.d3d_context->CSSetUnorderedAccessViews(1, 1, &Buffers.lensInterface_view, nullptr);
1557 | Win.d3d_context->CSSetUnorderedAccessViews(2, 1, &Buffers.ghostdata_view, nullptr);
1558 |
1559 | Win.d3d_context->VSSetShader(Shaders.vs_lens_flare, nullptr, 0);
1560 | Win.d3d_context->VSSetConstantBuffers(1, 1, &Buffers.globaldata);
1561 |
1562 | Win.d3d_context->PSSetShader(Shaders.ps_lens_flare_debug, nullptr, 0);
1563 | Win.d3d_context->PSSetSamplers(0, 1, &Textures.linear_clamp_sampler);
1564 | Win.d3d_context->PSSetConstantBuffers(1, 1, &Buffers.globaldata);
1565 | Win.d3d_context->PSSetShaderResources(1, 1, &Textures.aperture_sr_view);
1566 |
1567 | // Dispatch
1568 | Win.d3d_context->Dispatch(App.num_groups, App.num_groups, 3);
1569 | Win.d3d_context->CSSetUnorderedAccessViews(0, 1, Textures.null_ua_view, nullptr);
1570 | Win.d3d_context->CSSetUnorderedAccessViews(2, 1, Textures.null_ua_view, nullptr);
1571 |
1572 | // Draw
1573 | Win.d3d_context->VSSetShaderResources(0, 1, &Shapes.ray_bundle.vertices_resource_view);
1574 | Win.d3d_context->RSSetState(States.rs_no_cull);
1575 | Win.d3d_context->DrawIndexed(App.num_vertices_per_bundle * 3 * 2, 0, 0);
1576 |
1577 | if (UI.overlay_wireframe) {
1578 | Win.d3d_context->RSSetState(States.rs_wireframe);
1579 | Win.d3d_context->PSSetShader(Shaders.ps_lens_flare_wireframe, nullptr, 0);
1580 | Win.d3d_context->DrawIndexed(App.num_vertices_per_bundle * 3 * 2, 0, 0);
1581 | }
1582 |
1583 | Win.d3d_context->VSSetShaderResources(0, 1, Textures.null_sr_view);
1584 | Win.d3d_context->PSSetShaderResources(1, 1, Textures.null_sr_view);
1585 | } else {
1586 | Win.d3d_context->RSSetState(States.rs_cull);
1587 | Win.d3d_context->IASetInputLayout(Win.d3d_vertex_layout_2d);
1588 |
1589 | Win.d3d_context->OMSetRenderTargets(1, &Textures.backbuffer_rt_view, Textures.depthstencil_view);
1590 | Win.d3d_context->ClearRenderTargetView(Textures.backbuffer_rt_view, XMVECTORF32{ ColorTheme.background1.x, ColorTheme.background1.y, ColorTheme.background1.z, ColorTheme.background1.w });
1591 | Win.d3d_context->ClearDepthStencilView(Textures.depthstencil_view, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
1592 |
1593 | Win.d3d_context->VSSetShader(Shaders.vs_basic, nullptr, 0);
1594 | Win.d3d_context->VSSetConstantBuffers(0, 1, &Buffers.instance_uniforms);
1595 |
1596 | Win.d3d_context->PSSetShader(Shaders.ps_basic, nullptr, 0);
1597 | Win.d3d_context->PSSetConstantBuffers(0, 1, &Buffers.instance_uniforms);
1598 |
1599 | // Trace all rays
1600 | vector> intersections1(App.num_of_rays);
1601 | vector> intersections2(App.num_of_rays);
1602 | vector> intersections3(App.num_of_rays);
1603 |
1604 | vec3 dir(UI.direction.x, UI.direction.y, UI.direction.z);
1605 | for (int i = 0; i < App.num_of_rays; ++i) {
1606 | float pos = Lerp(-1.f, 1.f, (float)i / (float)(App.num_of_rays - 1)) * UI.rays_spread;
1607 |
1608 | vec3 a1 = vec3(0.0f, pos, 400.f);
1609 | vec3 d1 = vec3(0.0f, 0.0f, -1.f);
1610 | Ray r1 = { a1, d1 };
1611 | Intersection i1 = testSPHERE(r1, Lens.lens_interface[0]);
1612 | vec3 a2 = i1.pos - dir;
1613 | Ray r = { a2, dir };
1614 |
1615 | Trace(r, 1.f, Lens.lens_interface, intersections1[i], intersections2[i], intersections3[i], int2{ UI.ghost_bounce_1, UI.ghost_bounce_2 });
1616 | }
1617 |
1618 | // Draw all rays
1619 | XMFLOAT4 ghost_color1 = IntersectionColor(UI.ghost_bounce_1 - 1);
1620 | XMFLOAT4 ghost_color2 = IntersectionColor(UI.ghost_bounce_2 - 1);
1621 | for (int i = 0; i < App.num_of_rays; ++i)
1622 | DrawIntersections(Win.d3d_context, Buffers.intersection_points1, intersections1[i], Lens.num_of_intersections_1, ColorTheme.intersection1);
1623 |
1624 | for (int i = 0; i < App.num_of_rays; ++i)
1625 | DrawIntersections(Win.d3d_context, Buffers.intersection_points2, intersections2[i], Lens.num_of_intersections_2, ghost_color1);
1626 |
1627 | for (int i = 0; i < App.num_of_rays; ++i)
1628 | DrawIntersections(Win.d3d_context, Buffers.intersection_points3, intersections3[i], Lens.num_of_intersections_3, ghost_color2);
1629 |
1630 | // Draw lenses
1631 | DrawLensInterface();
1632 | }
1633 | #endif
1634 |
1635 | // Visualize the aperture texture:
1636 | //Win.d3d_context->PSSetShader(Shaders.ps_tonemapper, nullptr, 0);
1637 | //Win.d3d_context->PSSetShaderResources(1, 1, &Textures.aperture_sr_view);
1638 | //DrawFullscreenQuad(Win.d3d_context, Shapes.unit_square, ColorTheme.fill1, Textures.backbuffer_rt_view, Textures.depthstencil_view);
1639 |
1640 | // Visualize the starburst texture:
1641 | // Win.d3d_context->PSSetShader(Shaders.ps_tonemapper, nullptr, 0);
1642 | // Win.d3d_context->PSSetShaderResources(1, 1, &Textures.starburst_filtered_sr_view);
1643 | // DrawFullscreenQuad(Win.d3d_context, unit_square, ColorTheme.fill1, Textures.backbuffer_rt_view, Textures.depthstencil_view);
1644 |
1645 | // Visualize the dust texture:
1646 | // Win.d3d_context->PSSetShader(Shaders.ps_tonemapper, nullptr, 0);
1647 | // Win.d3d_context->PSSetShaderResources(1, 1, &Textures.dust_sr_view);
1648 |
1649 | Win.d3d_swapchain->Present(0, 0);
1650 |
1651 | Win.d3d_context->End(GPUQueries.frame_end);
1652 | Win.d3d_context->End(GPUQueries.disjoint);
1653 | GPUQueries::PrintGPUTimes(GPUQueries);
1654 | }
1655 |
1656 |
1657 |
1658 |
1659 |
1660 | // ---------------------------------------------------------------------------------------------------------
1661 | // Windows Management
1662 | // ---------------------------------------------------------------------------------------------------------
1663 | LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
1664 | HRESULT InitWindow(HINSTANCE hInstance, int nCmdShow);
1665 | HRESULT InitDevice();
1666 | HRESULT InitResources();
1667 | void Render();
1668 |
1669 | HRESULT InitResources() {
1670 | ParseLensComponents();
1671 |
1672 | Textures.InitTextures();
1673 | Textures.InitSamplers();
1674 | Shaders.InitShaders();
1675 | Buffers.InitBuffers();
1676 | States.InitStates();
1677 | Shapes.InitShapes();
1678 | GPUQueries.InitQueries();
1679 | FFT.InitFFTTetxtures(Win.d3d_device, (int)App.aperture_resolution);
1680 |
1681 | return S_OK;
1682 | }
1683 |
1684 | int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) {
1685 | UNREFERENCED_PARAMETER(hPrevInstance);
1686 | UNREFERENCED_PARAMETER(lpCmdLine);
1687 |
1688 | InitWindow(hInstance, nCmdShow);
1689 | InitDevice();
1690 | InitResources();
1691 |
1692 | // Main message loop
1693 | MSG msg = { 0 };
1694 | while (WM_QUIT != msg.message) {
1695 |
1696 | if (msg.message == WM_KEYDOWN) {
1697 | if (!UI.key_down && msg.wParam == 65)
1698 | UI.overlay_wireframe = !UI.overlay_wireframe;
1699 |
1700 | if (!UI.key_down && msg.wParam == 69)
1701 | UI.editing_coating_quality = !UI.editing_coating_quality;
1702 |
1703 | if (!UI.key_down && msg.wParam == 81)
1704 | UI.editing_aperture = true;
1705 |
1706 | if (!UI.key_down && msg.wParam == 82)
1707 | UI.editing_no_blades = true;
1708 |
1709 | if (!UI.key_down && msg.wParam == 87)
1710 | UI.editing_spread = true;
1711 |
1712 | if (!UI.key_down && msg.wParam == 32)
1713 | UI.draw2d = !UI.draw2d;
1714 |
1715 | if (!UI.key_down && msg.wParam == 37)
1716 | UI.ghost_bounce_1 = max(2, UI.ghost_bounce_1 - 1);
1717 |
1718 | if (!UI.key_down && msg.wParam == 39)
1719 | UI.ghost_bounce_1 = min((int)Lens.lens_interface.size() - 2, UI.ghost_bounce_1 + 1);
1720 |
1721 | if (!UI.key_down && msg.wParam == 40)
1722 | UI.ghost_bounce_2 = max(1, UI.ghost_bounce_2 - 1);
1723 |
1724 | if (!UI.key_down && msg.wParam == 38) {
1725 | UI.ghost_bounce_2 = min((int)Lens.lens_interface.size() - 2, UI.ghost_bounce_2 + 1);
1726 | UI.ghost_bounce_2 = min(UI.ghost_bounce_1 - 2, UI.ghost_bounce_2);
1727 | }
1728 |
1729 | UI.ghost_bounce_1 = max(UI.ghost_bounce_2 + 2, UI.ghost_bounce_1);
1730 | UI.key_down = true;
1731 | }
1732 |
1733 | if (msg.message == WM_KEYUP) {
1734 | UI.key_down = false;
1735 | UI.editing_aperture = false;
1736 | UI.editing_no_blades = false;
1737 | UI.editing_spread = false;
1738 | UI.editing_coating_quality = false;
1739 | }
1740 |
1741 | if (msg.message == WM_LBUTTONDOWN) {
1742 | UI.left_mouse_down = true;
1743 | }
1744 |
1745 | if (msg.message == WM_LBUTTONUP) {
1746 | UI.left_mouse_down = false;
1747 | }
1748 |
1749 | if (msg.message == WM_MOUSEMOVE) {
1750 | POINT p;
1751 | GetCursorPos(&p);
1752 | ScreenToClient(Win.g_hWnd, &p);
1753 |
1754 | float nx = ((p.x / App.backbuffer_width) * 2.f - 1.f);
1755 | float ny = ((p.y / App.backbuffer_height) * 2.f - 1.f);
1756 |
1757 | if (!UI.key_down && UI.left_mouse_down) {
1758 | UI.x_dir = nx * 0.2f;
1759 | UI.y_dir = ny * 0.2f;
1760 | }
1761 |
1762 | if (UI.editing_aperture) {
1763 | UI.aperture_opening = 5.f + ny * 5.f;
1764 | UpdateLensComponents();
1765 | }
1766 |
1767 | if (UI.editing_no_blades) {
1768 | UI.number_of_blades = 10.f + ny * 5.f;
1769 | }
1770 |
1771 | if (UI.editing_spread) {
1772 | UI.rays_spread = 5.f + ny * 5.f;
1773 | }
1774 |
1775 | if (UI.editing_coating_quality) {
1776 | UI.coating_quality = 0.5f + ny;
1777 | }
1778 |
1779 | if (UI.editing_aperture || UI.editing_no_blades)
1780 | UI.aperture_needs_updating = true;
1781 | }
1782 |
1783 | if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
1784 | TranslateMessage(&msg);
1785 | DispatchMessage(&msg);
1786 | }
1787 | else {
1788 | Render();
1789 | }
1790 | }
1791 |
1792 | return (int)msg.wParam;
1793 | }
1794 |
1795 | HRESULT InitWindow(HINSTANCE hInstance, int nCmdShow) {
1796 | // Register class
1797 | WNDCLASSEX wcex;
1798 | wcex.cbSize = sizeof(WNDCLASSEX);
1799 | wcex.style = CS_HREDRAW | CS_VREDRAW;
1800 | wcex.lpfnWndProc = WndProc;
1801 | wcex.cbClsExtra = 0;
1802 | wcex.cbWndExtra = 0;
1803 | wcex.hInstance = hInstance;
1804 | wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_TUTORIAL1);
1805 | wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
1806 | wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
1807 | wcex.lpszMenuName = nullptr;
1808 | wcex.lpszClassName = L"LensClass";
1809 | wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_TUTORIAL1);
1810 |
1811 | if (!RegisterClassEx(&wcex))
1812 | return E_FAIL;
1813 |
1814 | // Create window
1815 | Win.g_hInst = hInstance;
1816 | RECT rc = { 0, 0, (LONG)App.backbuffer_width, (LONG)App.backbuffer_height };
1817 | AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
1818 | Win.g_hWnd = CreateWindow(L"LensClass", L"Lens Interface", WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
1819 | CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, nullptr, nullptr, hInstance, nullptr);
1820 |
1821 | ShowWindow(Win.g_hWnd, nCmdShow);
1822 |
1823 | return S_OK;
1824 | }
1825 |
1826 | HRESULT InitDevice() {
1827 | HRESULT hr = S_OK;
1828 |
1829 | RECT rc;
1830 | GetClientRect(Win.g_hWnd, &rc);
1831 | UINT width = rc.right - rc.left;
1832 | UINT height = rc.bottom - rc.top;
1833 |
1834 | UINT createDeviceFlags = 0;
1835 | #ifdef _DEBUG
1836 | createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
1837 | #endif
1838 |
1839 | D3D_DRIVER_TYPE driverTypes[] = {
1840 | D3D_DRIVER_TYPE_HARDWARE,
1841 | D3D_DRIVER_TYPE_WARP,
1842 | D3D_DRIVER_TYPE_REFERENCE,
1843 | };
1844 |
1845 | UINT numDriverTypes = ARRAYSIZE(driverTypes);
1846 |
1847 | D3D_FEATURE_LEVEL featureLevels[] = {
1848 | D3D_FEATURE_LEVEL_11_1,
1849 | D3D_FEATURE_LEVEL_11_0,
1850 | D3D_FEATURE_LEVEL_10_1,
1851 | D3D_FEATURE_LEVEL_10_0,
1852 | };
1853 |
1854 | UINT numFeatureLevels = ARRAYSIZE(featureLevels);
1855 |
1856 | for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++) {
1857 | Win.d3d_driver_type = driverTypes[driverTypeIndex];
1858 | hr = D3D11CreateDevice(nullptr, Win.d3d_driver_type, nullptr, createDeviceFlags, featureLevels, numFeatureLevels,
1859 | D3D11_SDK_VERSION, &Win.d3d_device, &Win.d3d_feature_level, &Win.d3d_context);
1860 |
1861 | if (hr == E_INVALIDARG) {
1862 | // DirectX 11.0 platforms will not recognize D3D_FEATURE_LEVEL_11_1 so we need to retry without it
1863 | hr = D3D11CreateDevice(nullptr, Win.d3d_driver_type, nullptr, createDeviceFlags, &featureLevels[1], numFeatureLevels - 1,
1864 | D3D11_SDK_VERSION, &Win.d3d_device, &Win.d3d_feature_level, &Win.d3d_context);
1865 | }
1866 |
1867 | if (SUCCEEDED(hr))
1868 | break;
1869 | }
1870 |
1871 | // Obtain DXGI factory from device (since we used nullptr for pAdapter above)
1872 | IDXGIFactory1* dxgiFactory = nullptr;
1873 | IDXGIDevice* dxgiDevice = nullptr;
1874 | IDXGIAdapter* adapter = nullptr;
1875 | hr = Win.d3d_device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast(&dxgiDevice));
1876 | hr = dxgiDevice->GetAdapter(&adapter);
1877 | hr = adapter->GetParent(__uuidof(IDXGIFactory1), reinterpret_cast(&dxgiFactory));
1878 | adapter->Release();
1879 |
1880 | // Create swap chain
1881 | IDXGIFactory2* dxgiFactory2 = nullptr;
1882 | hr = dxgiFactory->QueryInterface(__uuidof(IDXGIFactory2), reinterpret_cast(&dxgiFactory2));
1883 | if (dxgiFactory2) {
1884 | // DirectX 11.1 or later
1885 | hr = Win.d3d_device->QueryInterface(__uuidof(ID3D11Device1), reinterpret_cast(&Win.d3d_device1));
1886 | if (SUCCEEDED(hr)) {
1887 | (void)Win.d3d_context->QueryInterface(__uuidof(ID3D11DeviceContext1), reinterpret_cast(&Win.d3d_context1));
1888 | }
1889 |
1890 | DXGI_SWAP_CHAIN_DESC1 sd;
1891 | ZeroMemory(&sd, sizeof(sd));
1892 | sd.Width = width;
1893 | sd.Height = height;
1894 | sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
1895 | sd.SampleDesc.Count = 1;
1896 | sd.SampleDesc.Quality = 0;
1897 | sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
1898 | sd.BufferCount = 1;
1899 |
1900 | hr = dxgiFactory2->CreateSwapChainForHwnd(Win.d3d_device, Win.g_hWnd, &sd, nullptr, nullptr, &Win.d3d_swapchain1);
1901 | if (SUCCEEDED(hr)) {
1902 | hr = Win.d3d_swapchain1->QueryInterface(__uuidof(IDXGISwapChain), reinterpret_cast(&Win.d3d_swapchain));
1903 | }
1904 |
1905 | dxgiFactory2->Release();
1906 | }
1907 | else {
1908 | // DirectX 11.0 systems
1909 | DXGI_SWAP_CHAIN_DESC sd;
1910 | ZeroMemory(&sd, sizeof(sd));
1911 | sd.BufferCount = 1;
1912 | sd.BufferDesc.Width = width;
1913 | sd.BufferDesc.Height = height;
1914 | sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
1915 | sd.BufferDesc.RefreshRate.Numerator = 60;
1916 | sd.BufferDesc.RefreshRate.Denominator = 1;
1917 | sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
1918 | sd.OutputWindow = Win.g_hWnd;
1919 | sd.SampleDesc.Count = 1;
1920 | sd.SampleDesc.Quality = 0;
1921 | sd.Windowed = TRUE;
1922 |
1923 | hr = dxgiFactory->CreateSwapChain(Win.d3d_device, &sd, &Win.d3d_swapchain);
1924 | }
1925 |
1926 | // Setup the viewport
1927 | D3D11_VIEWPORT vp;
1928 | vp.Width = (FLOAT)width;
1929 | vp.Height = (FLOAT)height;
1930 | vp.MinDepth = 0.f;
1931 | vp.MaxDepth = 1.f;
1932 | vp.TopLeftX = 0.f;
1933 | vp.TopLeftY = 0.f;
1934 | Win.d3d_context->RSSetViewports(1, &vp);
1935 |
1936 | // Note this tutorial doesn't handle full-screen swapchains so we block the ALT+ENTER shortcut
1937 | dxgiFactory->MakeWindowAssociation(Win.g_hWnd, DXGI_MWA_NO_ALT_ENTER);
1938 | dxgiFactory->Release();
1939 |
1940 | return S_OK;
1941 | }
1942 |
1943 | LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
1944 | PAINTSTRUCT ps;
1945 | HDC hdc;
1946 |
1947 | switch (message) {
1948 | case WM_PAINT:
1949 | hdc = BeginPaint(hWnd, &ps);
1950 | EndPaint(hWnd, &ps);
1951 | break;
1952 |
1953 | case WM_DESTROY:
1954 | PostQuitMessage(0);
1955 | break;
1956 |
1957 | default:
1958 | return DefWindowProc(hWnd, message, wParam, lParam);
1959 | }
1960 |
1961 | return 0;
1962 | }
--------------------------------------------------------------------------------
/Lens/lens.hlsl:
--------------------------------------------------------------------------------
1 | #include "common.hlsl"
2 |
3 | struct PSInput {
4 | float4 pos : SV_POSITION;
5 | float4 color : TEXCOORD0;
6 | float4 coordinates : TEXCOORD1;
7 | float4 reflectance : TEXCOORD2;
8 | };
9 |
10 | struct Intersection {
11 | float3 pos;
12 | float3 norm;
13 | float theta;
14 | bool hit;
15 | bool inverted;
16 | };
17 |
18 | struct LensInterface {
19 | float3 center;
20 | float radius;
21 | float3 n;
22 | float sa;
23 | float d1;
24 | float flat;
25 | float pos;
26 | float w;
27 | };
28 |
29 | struct Ray {
30 | float3 pos;
31 | float3 dir;
32 | float4 tex;
33 | };
34 |
35 | struct GhostData{
36 | float bounce1;
37 | float bounce2;
38 | float2 padding;
39 | };
40 |
41 | StructuredBuffer vertices_buffer : register(t0);
42 | RWStructuredBuffer uav_buffer : register(u0);
43 | RWStructuredBuffer lens_interface : register(u1);
44 | RWStructuredBuffer ghostdata_buffer : register(u2);
45 |
46 | Intersection TestFlat(Ray r, LensInterface F) {
47 | Intersection i;
48 | i.pos = r.pos + r.dir * ((F.center.z - r.pos.z) / r.dir.z);
49 | i.norm = r.dir.z > 0 ? float3(0, 0, -1) : float3(0, 0, 1);
50 | i.theta = 0;
51 | i.hit = true;
52 | i.inverted = false;
53 | return i;
54 | }
55 |
56 | Intersection TestSphere(Ray r, LensInterface F) {
57 | Intersection i;
58 |
59 | float3 D = r.pos - F.center;
60 | float B = dot(D, r.dir);
61 | float C = dot(D, D) - F.radius * F.radius;
62 | float B2_C = B*B-C;
63 |
64 | if (B2_C < 0) {
65 | i.hit = false;
66 | return i;
67 | }
68 |
69 | float sgn = (F.radius * r.dir.z) > 0 ? 1.f : -1.f;
70 | float t = sqrt(B2_C) * sgn - B;
71 | i.pos = r.dir * t + r.pos;
72 | i.norm = normalize(i.pos - F.center);
73 |
74 | if (dot(i.norm, r.dir) > 0)
75 | i.norm = -i.norm;
76 |
77 | float d = clamp(-1, 1, dot(-r.dir, i.norm));
78 | i.theta = acos(d);
79 | i.hit = true;
80 | i.inverted = t < 0;
81 |
82 | return i;
83 | }
84 |
85 | float FresnelAR(float theta0, float lambda, float d1, float n0, float n1, float n2) {
86 | float theta1 = asin(sin(theta0) *n0 / n1);
87 | float theta2 = asin(sin(theta0) *n0 / n2);
88 |
89 | float rs01 = -sin(theta0-theta1) / sin(theta0+theta1);
90 | float rp01 = tan(theta0-theta1) / tan(theta0+theta1);
91 | float ts01 = 2*sin(theta1) *cos(theta0) / sin(theta0+theta1);
92 | float tp01 = ts01*cos(theta0-theta1);
93 |
94 | float rs12 = -sin(theta1-theta2) / sin(theta1+theta2);
95 | float rp12 = +tan(theta1-theta2) / tan(theta1+theta2);
96 |
97 | float ris = ts01*ts01*rs12;
98 | float rip = tp01*tp01*rp12;
99 |
100 | float dy = d1*n1 ;
101 | float dx = tan(theta1) *dy;
102 | float delay = sqrt(dx*dx+dy*dy);
103 | float relPhase = 4*PI / lambda*(delay-dx*sin(theta0) );
104 |
105 | float out_s2 = rs01*rs01 + ris*ris + 2*rs01*ris*cos(relPhase);
106 | float out_p2 = rp01*rp01 + rip*rip + 2*rp01*rip*cos(relPhase);
107 |
108 | return (out_s2+out_p2) / 2 ;
109 | }
110 |
111 | Ray Trace(Ray r, float lambda, int2 bounce_pair) {
112 | int LEN = bounce_pair.x + (bounce_pair.x - bounce_pair.y) + (num_interfaces - bounce_pair.y) - 1;
113 | int PHASE = 0;
114 | int DELTA = 1;
115 | int T = 1;
116 |
117 | int k;
118 | for(k=0; k < LEN; k++, T += DELTA) {
119 |
120 | LensInterface F = lens_interface[T];
121 |
122 | bool bReflect = (T == bounce_pair[PHASE]) ? true : false;
123 | if (bReflect) { DELTA = -DELTA; PHASE++; } // intersection test
124 |
125 | Intersection i;
126 | if(F.flat)
127 | i = TestFlat(r, lens_interface[T]);
128 | else
129 | i = TestSphere(r, lens_interface[T]);
130 |
131 | [branch]
132 | if (!i.hit) {
133 | r.pos = 0;
134 | r.tex.a = 0;
135 | break; // exit upon miss
136 | }
137 |
138 | // record texture coord . or max. rel . radius
139 | if (!F.flat)
140 | r.tex.z = max(r.tex.z, length(i.pos.xy) / F.sa);
141 | else if(T==AP_IDX) // iris aperture plane
142 | r.tex.xy = i.pos.xy / lens_interface[AP_IDX].sa; // update ray light_dir and position
143 |
144 | r.dir = normalize(i.pos- r.pos);
145 |
146 | if (i.inverted) r.dir *= -1.f; // correct an ← inverted ray
147 |
148 | r.pos = i.pos;
149 |
150 | // skip reflection / refraction for flat surfaces
151 | if (F.flat)
152 | continue;
153 |
154 | // do reflection / refraction for spher . surfaces
155 | float n0 = r.dir.z < 0.f ? F.n.x : F.n.z;
156 | float n2 = r.dir.z < 0.f ? F.n.z : F.n.x;
157 |
158 | if (!bReflect) { // refraction
159 | r.dir = refract(r.dir,i.norm,n0/n2);
160 |
161 | [branch]
162 | if(length(r.dir) == 0){
163 | r.pos = 0;
164 | r.tex.a = 0;
165 | break; // total reflection
166 | }
167 | } else { // reflection with AR Coating
168 | r.dir = reflect(r.dir,i.norm);
169 |
170 | float n1 = max(sqrt(n0*n2) , 1.38 + coating_quality);
171 | float d1 = (F.d1 * NANO_METER);
172 | float R = FresnelAR(i.theta + 0.001, lambda, d1, n0, n1, n2);
173 | R = saturate(R);
174 |
175 | r.tex.a *= R; // update ray intensity
176 | }
177 | }
178 |
179 | [branch]
180 | if (k= 0 && inv_pos.x < (ms_compute + ms_draw + 2))
23 | return float4(1,1,1,1);
24 |
25 | if(inv_pos.y > -8 && inv_pos.y < 0) {
26 | if(inv_pos.x >= 0 && inv_pos.x < (ms_compute + ms_draw + 2)) {
27 | if(inv_pos.y > -4 && (inv_pos.x % s) == 0)
28 | return float4(1,1,1,1);
29 |
30 | if((inv_pos.x % (5 * s)) == 0)
31 | return float4(1,1,1,1);
32 | }
33 | }
34 |
35 | if(inv_pos.y > 0 && inv_pos.y < padding.y) {
36 | if(inv_pos.x >= 0 && inv_pos.x < ms_compute)
37 | return float4(200.f/255.f, 1, 0, 1);
38 |
39 | if(inv_pos.x > (ms_compute + 1) && inv_pos.x < (ms_compute + ms_draw + 1))
40 | return float4(0, 1, 200.f/255.f, 1);
41 | }
42 | #endif
43 |
44 | float3 c = input_texture1.Load(int3(pos.xy,0)).rgb;
45 | c = ACESFilm(c);
46 | return float4(c, 1);
47 | }
48 |
--------------------------------------------------------------------------------
/Lens/ray_trace.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | //--------------------------------------------------------------------------------------
4 | // This is a port of:
5 | // http://resources.mpi-inf.mpg.de/lensflareRendering/pdf/flare-supplement.pdf
6 | //--------------------------------------------------------------------------------------
7 |
8 |
9 | #include
10 | #include
11 | #include
12 |
13 | using namespace std;
14 |
15 | #define NUM_BOUNCE 2
16 | #define AP_IDX 14
17 | #define PI 3.14159265359f
18 |
19 | struct vec3 {
20 | vec3() { x = y = z = 0.f; }
21 | vec3(float a, float b, float c) : x(a), y(b), z(c) {};
22 | float x, y, z;
23 | vec3 operator-() { return vec3(-this->x, -this->y, -this->z); }
24 | vec3 operator-(const vec3& b) { return vec3(this->x - b.x, this->y - b.y, this->z - b.z); }
25 | vec3 operator+(const vec3& b) { return vec3(this->x + b.x, this->y + b.y, this->z + b.z); }
26 | vec3 operator*(const float b) { return vec3(this->x * b, this->y * b, this->z * b); }
27 | vec3& operator*=(const float b) { this->x *= b, this->y *= b, this->z *= b; return *this; }
28 | bool operator==(const float b) { return (this->x == b && this->y == b && this->z == b); }
29 | };
30 |
31 | struct vec4 {
32 | vec4() { x = y = z = a = 0.f; }
33 | vec4(float a, float b, float c, float d) : x(a), y(b), z(c), a(d) {};
34 | float x, y, z, a;
35 | };
36 |
37 | struct int2 {
38 | int x, y;
39 | int operator[](int i) { return i == 0 ? x : y; }
40 | };
41 |
42 | struct LensInterface {
43 | vec3 center;
44 | float radius;
45 |
46 | vec3 n;
47 | float sa;
48 |
49 | float d1;
50 | float flat;
51 | float pos;
52 | float w;
53 |
54 | };
55 |
56 | struct Ray {
57 | vec3 pos, dir;
58 | vec4 tex;
59 | };
60 |
61 | struct Intersection {
62 | Intersection() {};
63 | vec3 pos;
64 | vec3 norm;
65 | float theta;
66 | bool hit;
67 | bool inverted;
68 | };
69 |
70 | float dot(const vec3& a, const vec3& b) {
71 | return a.x * b.x + a.y * b.y + a.z * b.z;
72 | }
73 |
74 | vec3 normalize(vec3 a) {
75 | float l = sqrt(a.x * a.x + a.y*a.y + a.z*a.z);
76 | return vec3(a.x / l, a.y / l, a.z / l);
77 | }
78 |
79 | vec3 reflect(vec3 i, vec3 n) {
80 | return i - n * 2.f * dot(i, n);
81 | }
82 |
83 | vec3 refract(vec3 i, vec3 n, float eta) {
84 | float N_dot_I = dot(n, i);
85 | float k = 1.f - eta * eta * (1.f - N_dot_I * N_dot_I);
86 | if (k < 0.f)
87 | return vec3(0.f, 0.f, 0.f);
88 | else
89 | return i * eta - n * (eta * N_dot_I + sqrtf(k));
90 | }
91 |
92 | float length_xy(vec3& v) {
93 | return sqrt(v.x * v.x + v.y * v.y);
94 | }
95 |
96 | Intersection testFLAT(Ray r, LensInterface F) {
97 | Intersection i;
98 | i.pos = r.pos + r.dir * ((F.center.z - r.pos.z) / r.dir.z);
99 | i.norm = r.dir.z > 0 ? vec3(0, 0, -1) : vec3(0, 0, 1);
100 | i.theta = 0;
101 | i.hit = true;
102 | i.inverted = false;
103 | return i;
104 | }
105 |
106 | Intersection testSPHERE(Ray r, LensInterface F) {
107 | Intersection i;
108 | vec3 D = r.pos - F.center;
109 | float B = dot(D, r.dir);
110 | float C = dot(D, D) - F.radius * F.radius;
111 | float B2_C = B*B-C;
112 |
113 | if (B2_C < 0)
114 | { i.hit = false; return i; }
115 |
116 | float sgn = (F.radius * r.dir.z) > 0 ? 1.f : -1.f;
117 | float t = sqrtf(B2_C) * sgn - B;
118 | i.pos = r.dir * t + r.pos;
119 | i.norm = normalize(i.pos - F.center);
120 | if (dot(i.norm, r.dir) > 0) i.norm = -i.norm;
121 | i.theta = acos(dot(-r.dir, i.norm));
122 | i.hit = true;
123 | i.inverted = t < 0;
124 |
125 | return i;
126 | }
127 |
128 | float FresnelAR(
129 | float theta0,
130 | float lambda,
131 | float d1,
132 | float n0,
133 | float n1,
134 | float n2
135 | ) {
136 | float theta1 = asin(sin(theta0) *n0 / n1);
137 | float theta2 = asin(sin(theta0) *n0 / n2);
138 |
139 | float rs01 = -sin(theta0-theta1) / sin(theta0 + theta1);
140 | float rp01 = tan(theta0-theta1) / tan(theta0 + theta1);
141 | float ts01 = 2 * sin(theta1) *cos(theta0) / sin(theta0 + theta1);
142 | float tp01 = ts01*cos(theta0-theta1);
143 |
144 | float rs12 = -sin(theta1-theta2) / sin(theta1 + theta2);
145 | float rp12 = +tan(theta1-theta2) / tan(theta1 + theta2);
146 |
147 | float ris = ts01*ts01*rs12;
148 | float rip = tp01*tp01*rp12;
149 | float dy = d1*n1;
150 | float dx = tanf(theta1) *dy;
151 | float delay = sqrt(dx*dx + dy*dy);
152 | float relPhase = 4.f * PI / lambda*(delay-dx*sin(theta0));
153 |
154 | float out_s2 = rs01*rs01 + ris*ris + 2 * rs01*ris*cos(relPhase);
155 | float out_p2 = rp01*rp01 + rip*rip + 2 * rp01*rip*cos(relPhase);
156 | return (out_s2 + out_p2) / 2.f;
157 | }
158 |
159 | Ray Trace(
160 | Ray r,
161 | float lambda,
162 | std::vector& INTERFACE,
163 | std::vector& intersections1,
164 | std::vector& intersections2,
165 | std::vector& intersections3,
166 | int2 STR
167 | ) {
168 |
169 | intersections1.clear();
170 | intersections2.clear();
171 | intersections3.clear();
172 |
173 | intersections1.push_back(r.pos);
174 |
175 | int LEN = STR.x + (STR.x - STR.y) + ((int)INTERFACE.size() - STR.y) - 1;
176 |
177 | int PHASE = 0;
178 | int DELTA = 1;
179 | int T = 1;
180 | int k;
181 | for (k = 0; k < LEN; k++, T += DELTA) {
182 | LensInterface F = INTERFACE[T];
183 |
184 | bool bReflect = (T == STR[PHASE]) ? true : false;
185 | if (bReflect) {
186 | DELTA = -DELTA;
187 | PHASE++;
188 | }
189 |
190 | Intersection i = F.flat ? testFLAT(r, F) : testSPHERE(r, F);
191 |
192 | if (!i.hit) break;
193 |
194 | if (PHASE == 0) {
195 | intersections1.push_back(i.pos);
196 | } else if (PHASE == 1) {
197 | if(bReflect) intersections1.push_back(i.pos);
198 | intersections2.push_back(i.pos);
199 | }
200 | else {
201 | if (bReflect) intersections2.push_back(i.pos);
202 | intersections3.push_back(i.pos);
203 | }
204 |
205 | if (abs(i.pos.y) > F.sa) break;
206 |
207 | if (!F.flat)
208 | r.tex.z = max(r.tex.z, length_xy(i.pos) / F.sa);
209 | else if (T == AP_IDX) {
210 | r.tex.x = i.pos.x / INTERFACE[AP_IDX].sa;
211 | r.tex.y = i.pos.y / INTERFACE[AP_IDX].sa;
212 | };
213 |
214 | r.dir = normalize(i.pos-r.pos);
215 |
216 | if (i.inverted) r.dir *= -1;
217 | r.pos = i.pos;
218 |
219 | if (F.flat) continue;
220 |
221 | float n0 = r.dir.z < 0 ? F.n.x : F.n.z;
222 | float n1 = F.n.y;
223 | float n2 = r.dir.z < 0 ? F.n.z : F.n.x;
224 |
225 | if (!bReflect) {
226 | r.dir = refract(r.dir , i.norm , n0 / n2);
227 | if (r.dir == 0) break;
228 | }
229 | else {
230 | r.dir = reflect(r.dir , i.norm);
231 | float R = FresnelAR(i.theta , lambda , F.d1 , n0 , n1 , n2);
232 | r.tex.a *= R;
233 | }
234 | }
235 |
236 | if (k= 350.0) && (w < 440.0))
14 | r = float3((440.0 - w) / 90.0, 0.0, 1.0);
15 | else if((w >= 440.0) && (w <= 490.0))
16 | r = float3(0.0, (w - 440.0) / 50.0, 1.0);
17 | else if((w >= 490.0) && (w < 510.0))
18 | r = float3(0.0, 1.0, (-(w - 510.0)) / 20.0);
19 | else if ((w >= 510.0) && (w < 580.0))
20 | r = float3((w - 510.0) / 70.0, 1.0, 0.0);
21 | else if((w >= 580.0) && (w < 645.0))
22 | r = float3(1.0, (-(w - 645.0)) / 65.0, 0.0);
23 | else
24 | r = float3(1.0, 0.0, 0.0);
25 |
26 | if(w < 350.0)
27 | r *= 0.3;
28 | else if((w >= 350.0) && (w < 420.0))
29 | r *= 0.3 + (0.7 * ((w - 350.0) / 70.0));
30 | else if((w >= 420.0) && (w <= 700.0))
31 | r *= 1.0;
32 | else if((w > 700.0) && (w <= 780.0))
33 | r *= 0.3 + (0.7 * ((780.0 - w) / 80.0));
34 | else
35 | r *= 0.3;
36 |
37 | return r;
38 | }
39 |
40 | float3 IntersectPlane(float3 n, float3 p0, float3 l0, float3 l) {
41 | float denom = dot(n, l);
42 |
43 | if (denom > 1e-6) {
44 | float3 p0l0 = p0 - l0;
45 | float t = dot(p0l0, n) / denom;
46 | return p0 + l * t;
47 | }
48 |
49 | return 0;
50 | }
51 |
52 | bool Clamped(float2 ndc) {
53 | return ndc.x < -0.5 || ndc.x > 0.5 || ndc.y < -0.5 || ndc.y > 0.5;
54 | }
55 |
56 | StarbustInput VSStarburst(float4 pos : POSITION, uint id : SV_VertexID) {
57 | StarbustInput result;
58 |
59 | float ratio = backbuffer_size.x / backbuffer_size.y;
60 |
61 | float3 n = float3(0, 0, -1);
62 | float3 p0 = float3(0, 0, 20);
63 | float3 l0 = float3(0, 0, 0);
64 | float3 c = IntersectPlane(n, p0, l0, light_dir);
65 |
66 | float intensity = 1.f - saturate(abs(light_dir.x * 9.f));
67 |
68 | float oo1 = 1.f - (sin(time * 5.f) + 1.f) * 0.025f;
69 | float oo2 = 1.f - (sin(time * 1.f) + 1.f) * 0.0125f;
70 | intensity *= oo1 * oo2;
71 |
72 | float opening = 0.2f + saturate(aperture_opening/10.f);
73 | result.pos = float4(pos.xy * opening, 0.f, 1.f);
74 | result.pos.xy += c.xy * float2(0.5f, 1.f);
75 |
76 | result.uv.xy = (pos.xy * float2(1.f, 0.5f) + 1.f) * 0.5f;
77 | result.uv.z = intensity;
78 | return result;
79 | }
80 |
81 | float4 PSStarburst(StarbustInput input) : SV_Target {
82 |
83 | float2 uv = input.uv.xy;
84 | float intensity = input.uv.z;
85 | float3 starburst = input_texture1.Sample(LinearSampler, input.uv.xy).rgb * intensity;
86 |
87 | starburst *= TemperatureToColor(INCOMING_LIGHT_TEMP);
88 |
89 | return float4(starburst, 1.f);
90 | }
91 |
92 | float4 PSStarburstFromFFT(float4 pos : SV_POSITION ) : SV_Target {
93 |
94 | float2 uv = pos.xy / starburst_resolution - 0.5;
95 | float d = length(uv) * 2;
96 |
97 | // -ve violet, +v reds
98 | float scale1 = 0.50f;
99 | float scale2 = -0.75f;
100 | float fft_scale = 0.00001f;
101 |
102 | float3 result = 0.f;
103 | int num_steps = 256;
104 | for(int i = 0; i <= num_steps; ++i) {
105 | float n = (float)i/(float)num_steps;
106 |
107 | float2 scaled_uv1 = uv * lerp(1.f + scale1, 1.f, n);
108 | float2 scaled_uv2 = uv * lerp(1.f + scale2, 1.f, n);
109 |
110 | bool clamped1 = Clamped(scaled_uv1);
111 | bool clamped2 = Clamped(scaled_uv2);
112 |
113 | float r1 = input_texture1.Sample(LinearSampler, scaled_uv1).r * !clamped1;
114 | float i1 = input_texture2.Sample(LinearSampler, scaled_uv1).r * !clamped1;
115 |
116 | float r2 = input_texture1.Sample(LinearSampler, scaled_uv2).g * !clamped2;
117 | float i2 = input_texture2.Sample(LinearSampler, scaled_uv2).g * !clamped2;
118 |
119 | float2 p1 = float2(r1, i1);
120 | float2 p2 = float2(r2, i2);
121 |
122 | float starburst = pow(length(p1), 2.f) * fft_scale * lerp(0.0f, 25.f, d);
123 | float dust = pow(length(p2), 2.f) * fft_scale * lerp(0.5f, 0.f, d);
124 |
125 | float lambda = lerp(380.f, 700.f, n);
126 | float3 rgb = wl2rgbTannenbaum(lambda);
127 | rgb = lerp(1.f, rgb, 0.75f);
128 |
129 | result += (starburst + dust * rgb * 0.25f);
130 | }
131 |
132 | result /= (float)num_steps;
133 | return float4(result, 1);
134 | }
135 |
136 | float4 PSStarburstFilter(float4 pos : SV_POSITION ) : SV_Target {
137 | float2 uv = pos.xy / starburst_resolution - 0.5f;
138 |
139 | float3 result = 0.f;
140 | int num_steps = 256;
141 | for(int i = 0; i <= num_steps; ++i){
142 | float n = (float)i/(float)num_steps;
143 | float a = n * TWOPI * 2.f;
144 |
145 | float2 spiral = float2(cos(a), sin(a)) * n * 0.002f;
146 | float2 rotated_uv = Rotate(uv + spiral, n * 0.05f);
147 |
148 | float3 starburst = input_texture1.Sample(LinearSampler, rotated_uv + 0.5f).rgb * !Clamped(rotated_uv);
149 |
150 | float lambda = lerp(380.f, 700.f, (i % 80)/80.f);
151 | float3 rgb = wl2rgbTannenbaum(lambda);
152 | rgb = lerp(rgb, 1.f, 0.5f);
153 |
154 | result += starburst * rgb;
155 | }
156 |
157 | result /= (float)num_steps;
158 |
159 | return float4(result, 1);
160 | }
161 |
--------------------------------------------------------------------------------
/Lens/visualization.hlsl:
--------------------------------------------------------------------------------
1 | cbuffer Uniforms : register(b0) {
2 | float4 color;
3 | float4 placement;
4 | };
5 |
6 | float4 VS(float4 Pos : POSITION) : SV_POSITION {
7 | float4 p = Pos;
8 |
9 | if (placement.y == 1.f) {
10 | p.xy *= placement.zw;
11 | p.x += placement.z;
12 | p.x += placement.x;
13 | }
14 |
15 | return p;
16 | }
17 |
18 | float4 PS(float4 Pos : SV_POSITION) : SV_Target {
19 | return color;
20 | }
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PhysicallyBasedLensFlare
2 | Lens flare
3 | - [x] Basic implementation
4 | - [ ] Chromatic aberation
5 | - [x] Starbusrt
6 | - [ ] Optimizations
7 |
8 | Controls
9 | - 'q' Change aperture size
10 | - 'w' Change sun disk size
11 | - 'e' Change coating quality
12 | - 'r' Change number of aperture blades
13 | - 'a' Toggle wireframe
14 |
--------------------------------------------------------------------------------