├── .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 | --------------------------------------------------------------------------------