Handmade Hero»Episode Guide
Adding an Ambient Occlusion Pass
?
?

Keyboard Navigation

Global Keys

[, < / ], > Jump to previous / next episode
W, K, P / S, J, N Jump to previous / next marker
t / T Toggle theatre / SUPERtheatre mode
V Revert filter to original state Y Select link (requires manual Ctrl-c)

Menu toggling

q Quotes r References f Filter y Link c Credits

In-Menu Movement

a
w
s
d
h j k l


Quotes and References Menus

Enter Jump to timecode

Quotes, References and Credits Menus

o Open URL (in new tab)

Filter Menu

x, Space Toggle category and focus next
X, ShiftSpace Toggle category and focus previous
v Invert topics / media as per focus

Filter and Link Menus

z Toggle filter / linking mode

Credits Menu

Enter Open URL (in new tab)
0:01Recap and set the stage for the day
0:01Recap and set the stage for the day
0:01Recap and set the stage for the day
1:29Run the game to see the lighting diamonds
1:29Run the game to see the lighting diamonds
1:29Run the game to see the lighting diamonds
5:31handmade_render_group.cpp: Make LightingTest() correctly sum the Dest->FrontEmitC
5:31handmade_render_group.cpp: Make LightingTest() correctly sum the Dest->FrontEmitC
5:31handmade_render_group.cpp: Make LightingTest() correctly sum the Dest->FrontEmitC
5:55Run the game to see the correctly summed colours
5:55Run the game to see the correctly summed colours
5:55Run the game to see the correctly summed colours
6:08handmade_render_group.cpp: Make LightingTest() account for the DistanceFalloff
6:08handmade_render_group.cpp: Make LightingTest() account for the DistanceFalloff
6:08handmade_render_group.cpp: Make LightingTest() account for the DistanceFalloff
7:16Run the game with DistanceFalloff and summation, and consider our way forward
7:16Run the game with DistanceFalloff and summation, and consider our way forward
7:16Run the game with DistanceFalloff and summation, and consider our way forward
8:17handmade_render_group.cpp: Make LightingTest() set DiffuseInner to 1.0f
8:17handmade_render_group.cpp: Make LightingTest() set DiffuseInner to 1.0f
8:17handmade_render_group.cpp: Make LightingTest() set DiffuseInner to 1.0f
8:35Run the game to see the flickering
8:35Run the game to see the flickering
8:35Run the game to see the flickering
9:02Determine to introduce the ability to add light sources
9:02Determine to introduce the ability to add light sources
9:02Determine to introduce the ability to add light sources
12:27handmade_platform.h: Add Emission to the textured_vertex struct
12:27handmade_platform.h: Add Emission to the textured_vertex struct
12:27handmade_platform.h: Add Emission to the textured_vertex struct
14:11Run the game to see that nothing bad happens
14:11Run the game to see that nothing bad happens
14:11Run the game to see that nothing bad happens
14:30handmade_render_group.cpp: Make PushQuad() and LightingTest() set the emission
14:30handmade_render_group.cpp: Make PushQuad() and LightingTest() set the emission
14:30handmade_render_group.cpp: Make PushQuad() and LightingTest() set the emission
16:40Run the game to see everything unlit
16:40Run the game to see everything unlit
16:40Run the game to see everything unlit
16:47handmade_render_group.cpp: Introduce PushLight()
16:47handmade_render_group.cpp: Introduce PushLight()
16:47handmade_render_group.cpp: Introduce PushLight()
19:23handmade_world_mode.cpp: Make UpdateAndRenderWorld() call PushLight()
19:23handmade_world_mode.cpp: Make UpdateAndRenderWorld() call PushLight()
19:23handmade_world_mode.cpp: Make UpdateAndRenderWorld() call PushLight()
20:59Run the game and see a cube light that is not emitting any light
20:59Run the game and see a cube light that is not emitting any light
20:59Run the game and see a cube light that is not emitting any light
21:28handmade_render_group.cpp: Make PushQuad() take Emission
21:28handmade_render_group.cpp: Make PushQuad() take Emission
21:28handmade_render_group.cpp: Make PushQuad() take Emission
22:27Run the game to see our emitting light, with less flickering, but that the light itself is not lit up
22:27Run the game to see our emitting light, with less flickering, but that the light itself is not lit up
22:27Run the game to see our emitting light, with less flickering, but that the light itself is not lit up
24:55handmade_render_group.cpp: Add a BreakHere in LightingTest() for the light
24:55handmade_render_group.cpp: Add a BreakHere in LightingTest() for the light
24:55handmade_render_group.cpp: Add a BreakHere in LightingTest() for the light
25:58Step in to LightingTest() and inspect the values for the light
25:58Step in to LightingTest() and inspect the values for the light
25:58Step in to LightingTest() and inspect the values for the light
27:59handmade_render_group.cpp: Make LightingTest() correctly set the FrontEmit
27:59handmade_render_group.cpp: Make LightingTest() correctly set the FrontEmit
27:59handmade_render_group.cpp: Make LightingTest() correctly set the FrontEmit
28:35Run the game to see our lit light
28:35Run the game to see our lit light
28:35Run the game to see our lit light
29:18handmade_render_group.cpp: Make LightingTest() iterate three times
29:18handmade_render_group.cpp: Make LightingTest() iterate three times
29:18handmade_render_group.cpp: Make LightingTest() iterate three times
29:29Run the game to see our much brighter scene, now with flutter
29:29Run the game to see our much brighter scene, now with flutter
29:29Run the game to see our much brighter scene, now with flutter
30:03handmade_render_group.cpp: Revert LightingTest() to perform one iteration
30:03handmade_render_group.cpp: Revert LightingTest() to perform one iteration
30:03handmade_render_group.cpp: Revert LightingTest() to perform one iteration
30:10Run the game and consider building a wall
30:10Run the game and consider building a wall
30:10Run the game and consider building a wall
30:45handmade_world_mode.cpp: Make AddStandardRoom() add a wall
30:45handmade_world_mode.cpp: Make AddStandardRoom() add a wall
30:45handmade_world_mode.cpp: Make AddStandardRoom() add a wall
33:35Run the game to see our wall
33:35Run the game to see our wall
33:35Run the game to see our wall
35:56handmade_render_group.cpp: Enable LightingTest() to compute the colours differently in the debug and game view
35:56handmade_render_group.cpp: Enable LightingTest() to compute the colours differently in the debug and game view
35:56handmade_render_group.cpp: Enable LightingTest() to compute the colours differently in the debug and game view
39:24Run the game to see the beautiful game view
39:24Run the game to see the beautiful game view
39:24Run the game to see the beautiful game view
41:19handmade_render_group.cpp: Consider gathering the light from the cubes' corners rather than their faces
41:19handmade_render_group.cpp: Consider gathering the light from the cubes' corners rather than their faces
41:19handmade_render_group.cpp: Consider gathering the light from the cubes' corners rather than their faces
42:53handmade_config.h: Add Global_Renderer_Lighting_ShowReflectors and Global_Renderer_Lighting_IterationCount
42:53handmade_config.h: Add Global_Renderer_Lighting_ShowReflectors and Global_Renderer_Lighting_IterationCount
42:53handmade_config.h: Add Global_Renderer_Lighting_ShowReflectors and Global_Renderer_Lighting_IterationCount
45:08win32_handmade.cpp: Try to add keys in Win32ProcessPendingMessages() to control the reflectors and lighting iteration count
45:08win32_handmade.cpp: Try to add keys in Win32ProcessPendingMessages() to control the reflectors and lighting iteration count
45:08win32_handmade.cpp: Try to add keys in Win32ProcessPendingMessages() to control the reflectors and lighting iteration count
46:47handmade_opengl.cpp: Prevent OpenGLRenderCommands() from calling ComputeLightTransport()
46:47handmade_opengl.cpp: Prevent OpenGLRenderCommands() from calling ComputeLightTransport()
46:47handmade_opengl.cpp: Prevent OpenGLRenderCommands() from calling ComputeLightTransport()
47:12win32_handmade.cpp: Increase the resolution in WinMain()
47:12win32_handmade.cpp: Increase the resolution in WinMain()
47:12win32_handmade.cpp: Increase the resolution in WinMain()
47:34Run the game to see that it's totally usable for lighting
47:34Run the game to see that it's totally usable for lighting
47:34Run the game to see that it's totally usable for lighting
47:45handmade.cpp: Add lighting controls to the debug system
47:45handmade.cpp: Add lighting controls to the debug system
47:45handmade.cpp: Add lighting controls to the debug system
48:43Run the game and try out those lighting controls
48:43Run the game and try out those lighting controls
48:43Run the game and try out those lighting controls
49:53Determine to compute the lighting hierarchically
49:53Determine to compute the lighting hierarchically
49:53Determine to compute the lighting hierarchically
52:12Consult the multipass shadowing algorithm1
52:12Consult the multipass shadowing algorithm1
52:12Consult the multipass shadowing algorithm1
55:07Run the game and consider the problem of shadowing
55:07Run the game and consider the problem of shadowing
55:07Run the game and consider the problem of shadowing
57:10Blackboard: Comparing reflectors, being an O(n³) problem
57:10Blackboard: Comparing reflectors, being an O(n³) problem
57:10Blackboard: Comparing reflectors, being an O(n³) problem
58:51Read 14.3 Indirect Lighting and Area Lights2
58:51Read 14.3 Indirect Lighting and Area Lights2
58:51Read 14.3 Indirect Lighting and Area Lights2
1:00:26Run the game and consider an iterative solution across multiple frames
1:00:26Run the game and consider an iterative solution across multiple frames
1:00:26Run the game and consider an iterative solution across multiple frames
1:01:56handmade_render_group.cpp: Start to enable LightingTest() to compute some shadowing
1:01:56handmade_render_group.cpp: Start to enable LightingTest() to compute some shadowing
1:01:56handmade_render_group.cpp: Start to enable LightingTest() to compute some shadowing
1:03:57Consult the disk-to-disk occlusion algorithm3
1:03:57Consult the disk-to-disk occlusion algorithm3
1:03:57Consult the disk-to-disk occlusion algorithm3
1:05:32handmade_render_group.cpp: Enable LightingTest() to compute the disk-to-disk occlusion4
1:05:32handmade_render_group.cpp: Enable LightingTest() to compute the disk-to-disk occlusion4
1:05:32handmade_render_group.cpp: Enable LightingTest() to compute the disk-to-disk occlusion4
1:08:24Blackboard: Shadow Approx.5
1:08:24Blackboard: Shadow Approx.5
1:08:24Blackboard: Shadow Approx.5
1:19:58A mini rant on papers giving partial solutions
1:19:58A mini rant on papers giving partial solutions
1:19:58A mini rant on papers giving partial solutions
1:22:06Consider what their saturate function is meant to be doing6
1:22:06Consider what their saturate function is meant to be doing6
1:22:06Consider what their saturate function is meant to be doing6
1:26:31Blackboard: Understanding their shadow approximation equation7
1:26:31Blackboard: Understanding their shadow approximation equation7
1:26:31Blackboard: Understanding their shadow approximation equation7
1:29:25handmade_render_group.cpp: Enable LightingTest() to compute this shadow approximation equation8
1:29:25handmade_render_group.cpp: Enable LightingTest() to compute this shadow approximation equation8
1:29:25handmade_render_group.cpp: Enable LightingTest() to compute this shadow approximation equation8
1:32:08handmade_intrinsics.h: Introduce ReciprocalSquareRoot()
1:32:08handmade_intrinsics.h: Introduce ReciprocalSquareRoot()
1:32:08handmade_intrinsics.h: Introduce ReciprocalSquareRoot()
1:32:47handmade_render_group.cpp: Continue to implement the shadow equation in LightingTest()9
1:32:47handmade_render_group.cpp: Continue to implement the shadow equation in LightingTest()9
1:32:47handmade_render_group.cpp: Continue to implement the shadow equation in LightingTest()9
1:41:28Blackboard: Occlusion from in front and behind
1:41:28Blackboard: Occlusion from in front and behind
1:41:28Blackboard: Occlusion from in front and behind
1:41:46handmade_render_group.cpp: Break out the shadow equation values in LightingTest()
1:41:46handmade_render_group.cpp: Break out the shadow equation values in LightingTest()
1:41:46handmade_render_group.cpp: Break out the shadow equation values in LightingTest()
1:45:22Correcting for occlusion by overlapping objects10
1:45:22Correcting for occlusion by overlapping objects10
1:45:22Correcting for occlusion by overlapping objects10
1:46:43handmade_render_group.cpp: Enable LightingTest() to iteratively occlude
1:46:43handmade_render_group.cpp: Enable LightingTest() to iteratively occlude
1:46:43handmade_render_group.cpp: Enable LightingTest() to iteratively occlude
1:50:07Run the game to see the shadowing looking kind of reasonable
1:50:07Run the game to see the shadowing looking kind of reasonable
1:50:07Run the game to see the shadowing looking kind of reasonable
1:51:21handmade_render_group.cpp: Make LightingTest() perform one shadowing iteration, and run the game to see that the wall's front face is not all black
1:51:21handmade_render_group.cpp: Make LightingTest() perform one shadowing iteration, and run the game to see that the wall's front face is not all black
1:51:21handmade_render_group.cpp: Make LightingTest() perform one shadowing iteration, and run the game to see that the wall's front face is not all black
1:52:20handmade_render_group.cpp: Move the Dest->Visibility setting one scope out in LightingTest()
1:52:20handmade_render_group.cpp: Move the Dest->Visibility setting one scope out in LightingTest()
1:52:20handmade_render_group.cpp: Move the Dest->Visibility setting one scope out in LightingTest()
1:52:39Run the game to see that the wall's front face is still black here
1:52:39Run the game to see that the wall's front face is still black here
1:52:39Run the game to see that the wall's front face is still black here
1:53:51handmade_render_group.cpp: Read carefully though the shadowing code in LightingTest()
1:53:51handmade_render_group.cpp: Read carefully though the shadowing code in LightingTest()
1:53:51handmade_render_group.cpp: Read carefully though the shadowing code in LightingTest()
1:56:01handmade_render_group.cpp: Add assertions in LightingTest() and compile in debug mode
1:56:01handmade_render_group.cpp: Add assertions in LightingTest() and compile in debug mode
1:56:01handmade_render_group.cpp: Add assertions in LightingTest() and compile in debug mode
1:56:43Run the game and fail to hit those assertions
1:56:43Run the game and fail to hit those assertions
1:56:43Run the game and fail to hit those assertions
1:58:44handmade_render_group.cpp: Assert in LightingTest() that the Visibility >= Dest->Visibility on the first iteration
1:58:44handmade_render_group.cpp: Assert in LightingTest() that the Visibility >= Dest->Visibility on the first iteration
1:58:44handmade_render_group.cpp: Assert in LightingTest() that the Visibility >= Dest->Visibility on the first iteration
1:59:33Run the game, hit that assertion and consider why
1:59:33Run the game, hit that assertion and consider why
1:59:33Run the game, hit that assertion and consider why
2:00:37handmade_render_group.cpp: Add a Shadow in LightingTest() to accumulate based on the Visibility
2:00:37handmade_render_group.cpp: Add a Shadow in LightingTest() to accumulate based on the Visibility
2:00:37handmade_render_group.cpp: Add a Shadow in LightingTest() to accumulate based on the Visibility
2:04:42Run the game to see our ambient occlusion solution
2:04:42Run the game to see our ambient occlusion solution
2:04:42Run the game to see our ambient occlusion solution
2:05:20Q&A
🗩
2:05:20Q&A
🗩
2:05:20Q&A
🗩
2:06:43vkar2 square root (A/pi + r²) = square root (r² * ( A/(pi * r²) + 1) = r * square root (A/(pi * r²) + 1)
🗪
2:06:43vkar2 square root (A/pi + r²) = square root (r² * ( A/(pi * r²) + 1) = r * square root (A/(pi * r²) + 1)
🗪
2:06:43vkar2 square root (A/pi + r²) = square root (r² * ( A/(pi * r²) + 1) = r * square root (A/(pi * r²) + 1)
🗪
2:07:31Blackboard: Pulling the r out of square root (A/π + r²)
2:07:31Blackboard: Pulling the r out of square root (A/π + r²)
2:07:31Blackboard: Pulling the r out of square root (A/π + r²)
2:10:36alexkelbo Thank you very much for 400 days of programming. Had I remembered I would've sent you a golden crown to wear today. You're awesome!
🗪
2:10:36alexkelbo Thank you very much for 400 days of programming. Had I remembered I would've sent you a golden crown to wear today. You're awesome!
🗪
2:10:36alexkelbo Thank you very much for 400 days of programming. Had I remembered I would've sent you a golden crown to wear today. You're awesome!
🗪
2:10:43mtsmox What do extra iterations do for ambient occlusion? I understand it for bouncing light, but shadows?
🗪
2:10:43mtsmox What do extra iterations do for ambient occlusion? I understand it for bouncing light, but shadows?
🗪
2:10:43mtsmox What do extra iterations do for ambient occlusion? I understand it for bouncing light, but shadows?
🗪
2:10:59Blackboard: Calculating ambient occlusion over multiple iterations
2:10:59Blackboard: Calculating ambient occlusion over multiple iterations
2:10:59Blackboard: Calculating ambient occlusion over multiple iterations
2:16:12mtsmox Should the accumulator for the light passes be reset to zero at the start of the next pass?
🗪
2:16:12mtsmox Should the accumulator for the light passes be reset to zero at the start of the next pass?
🗪
2:16:12mtsmox Should the accumulator for the light passes be reset to zero at the start of the next pass?
🗪
2:16:40handmade_render_group.cpp: Make LightingTest() reset the accumulator
2:16:40handmade_render_group.cpp: Make LightingTest() reset the accumulator
2:16:40handmade_render_group.cpp: Make LightingTest() reset the accumulator
2:17:50Run the game to see the current lighting
2:17:50Run the game to see the current lighting
2:17:50Run the game to see the current lighting
2:18:14handmade_render_group.cpp: Make LightingTest() perform ambient occlusion
2:18:14handmade_render_group.cpp: Make LightingTest() perform ambient occlusion
2:18:14handmade_render_group.cpp: Make LightingTest() perform ambient occlusion
2:18:55Run the game to see how that looks with ambient occlusion
2:18:55Run the game to see how that looks with ambient occlusion
2:18:55Run the game to see how that looks with ambient occlusion
2:20:50handmade_config.h: Increase the Global_Renderer_Lighting_IterationCount and run the game to see how that looks
2:20:50handmade_config.h: Increase the Global_Renderer_Lighting_IterationCount and run the game to see how that looks
2:20:50handmade_config.h: Increase the Global_Renderer_Lighting_IterationCount and run the game to see how that looks
2:22:22thesizik It seems like the ground colors are off. Looks like it goes light green > gray > dark green
🗪
2:22:22thesizik It seems like the ground colors are off. Looks like it goes light green > gray > dark green
🗪
2:22:22thesizik It seems like the ground colors are off. Looks like it goes light green > gray > dark green
🗪
2:24:24handmade_render_group.cpp: Make LightingTest() cast the Element->Visibility calculation to a V4 in the setting of FrontEmit
2:24:24handmade_render_group.cpp: Make LightingTest() cast the Element->Visibility calculation to a V4 in the setting of FrontEmit
2:24:24handmade_render_group.cpp: Make LightingTest() cast the Element->Visibility calculation to a V4 in the setting of FrontEmit
2:25:25Run the game to see how that looks
2:25:25Run the game to see how that looks
2:25:25Run the game to see how that looks
2:26:40Wind it down
🗩
2:26:40Wind it down
🗩
2:26:40Wind it down
🗩