[video output=day426 member=cmuratori stream_platform=twitch stream_username=handmade_hero project=code title="Debugging Lighting Persistence" vod_platform=youtube id=5ZcnljyZLWk annotator=Miblo]
[0:01][Recap and set the stage for the day debugging the :lighting from last stream][:rendering :speech]
[0:50][:Run the game to show our current :lighting situation][:rendering]
[2:03][:Lighting Storage][:blackboard :memory :rendering]
[5:11][Storing :lighting data in entities][:blackboard :"entity system" :memory :rendering]
[7:11][Describe the entity and :lighting structures, donning the Pig :Hat in the process][:"entity system" :rendering :research]
[11:01][Describe PushCube() assigning light indices][:hat :lighting :rendering :research]
[17:50][Determine to ensure that the LightStore round-trips successfully, and read through LightingTest()][:hat :lighting :rendering :research]
[22:02][Assert in LightingTest() that we have extracted the final surface of the :lighting box, and that the EmitC starts off cleared][:hat :programming :rendering]
[26:12][Continue to read through LightingTest()][:hat :lighting :rendering :research]
[28:02][Note in LightingTest() to initialise directions to x = 1000, and pull out LocalCount into a variable to aid debugging][:hat :lighting :programming :rendering]
[32:40][Read through OutputLightingTextures()][:hat :lighting :rendering :research]
[35:06][Read through ComputeLightPropagation()][:hat :lighting :rendering :research]
[37:04][Assert in PushCube() that LightIndex != 0][:hat :lighting :programming :rendering]
[37:19][:Run the game and unexpectedly fail to hit that assertion, before realising that we set LightPointIndex to 1 after all][:hat :lighting :rendering]
[38:27][Continue to read through ComputeLightPropagation()][:hat :lighting :rendering :research]
[40:00][:Run the game and determine to get F1 toggling the :lighting points :"debug visualisation" again][:hat :rendering]
[40:25][Read through OutputLightingPoints()][:hat :lighting :rendering :research]
[42:27][Step in to OutputLightingPoints() and inspect its values][:hat :lighting :rendering :run]
[44:31][Unify the :lighting commands in UpdateAndRenderWorld(), and introduce the notion of discarding old commands][:hat :programming :rendering]
[49:15][Begin to introduce DiscardAllPreviousRenderCommands(), before deciding to let UpdateAndRenderWorld() instead render the old stuff before calling Clear()][:hat :lighting :programming :rendering]
[51:49][:Run the game and view our :lighting points :"debug visualisation" to see that the Clear() does not work][:hat :rendering]
[52:17][Make UpdateAndRenderWorld() call EndDepthPeel() before EndSim() and the :lighting functions][:hat :programming :rendering]
[52:42][:Run the game to see that the Clear() still fails][:hat :lighting :rendering]
[53:16][Introduce render_entry_full_clear in OpenGLRenderCommands()][:hardware :hat :programming :rendering]
[58:50][:Run the game to see nothing][:hat :lighting :rendering]
[59:07][Make UpdateAndRenderWorld() call Clear() before BeginDepthPeel()][:hat :programming :rendering]
[1:00:02][:Run the game to see that we are :rendering again but that the :lighting does not correspond across frames][:hat :rendering]
[1:00:25][Make OpenGLRenderCommands() call OpenGLBindFramebuffer() at the end of the render_entry_full_clear case][:hat :programming :rendering]
[1:00:42][:Run the game to see that our state is still not resetting correctly][:hat :lighting :rendering]
[1:00:57][Investigate why our clearing is failing to produce correct :lighting][:hat :programming :rendering]
[1:04:58][Make OpenGLRenderCommands() call glClearColor() and glClear() at the end of the render_entry_full_clear case][:hat :programming :rendering]
[1:05:28][:Run the game to see no difference][:hat :lighting :rendering]
[1:06:19][OpenGLRenderCommands()][:hat :programming :rendering]
[1:08:38][:Run the game to see no difference][:hat :lighting :rendering]
[1:09:03][Reorganise OpenGLRenderCommands() with a view to correctly clearing the render buffers][:hat :programming :rendering]
[1:15:14][Rename Clear() to PushFullClear() and introduce render_entry_begin_peels struct for BeginDepthPeel() to take][:hat :programming :rendering]
[1:18:28][:Run the game to see similar behaviour][:hat :lighting :rendering]
[1:18:47][Scrutinise OpenGLRenderCommands() to see how the render buffers are being bound and the peel indices are being used][:hat :lighting :rendering :research]
[1:22:21][Make OpenGLRenderCommands() test OnPeelIndex against MaxRenderTargetIndex in the render_entry_begin_peels case][:hat :lighting :programming :rendering]
[1:24:15][Read through ResolveMultisample() and how it is used][:hat :lighting :rendering :research]
[1:25:42][Set glClearDepth before all the render_entry cases in OpenGLRenderCommands()][:hat :lighting :programming :rendering]
[1:26:52][:Run the game to see that the :lighting points :"debug visualisation" actually looks about right, noting that the we seem to have a correspondence problem][:hat :rendering]
[1:28:07][Determine that OpenGLRenderCommands() may now be correct][:hat :rendering :research]
[1:28:51][:Run the game in -O2 and switch between the real and :"debug visualisation" :lighting][:hat :rendering]
[1:30:04][Read through OutputLightingTextures() and then PushCube() to see if our :lighting indices are corresponding correctly][:hat :rendering :research]
[1:35:46][Step through OutputLightingTextures() and inspect the Solution, P, C and D][:hat :lighting :rendering :run]
[1:37:49][Step through OutputLightingPoints() to compare its values with OutputLightingTextures()][:hat :lighting :rendering :run]
[1:38:57][Try to hard set Valid = false in LightingTest()][:hat :lighting :programming :rendering]
[1:39:14][:Run the game and determine that our problem is unrelated to storage][:hat :lighting :memory :rendering]
[1:40:50][Step through LightingTest() and watch its PointIndex and Solution values][:hat :lighting :rendering :run]
[1:46:39][PlayWorld() only generate 1 screen][:hat :"procedural generation" :programming]
[1:46:59][:Run the game and watch the behaviour of the :lighting][:hat :rendering]
[1:47:38][Stop hard setting Valid = false in LightingTest()][:hat :lighting :programming :rendering]
[1:47:50][:Run the game to see that the :lighting still doesn't correspond][:hat :rendering]
[1:48:23][Try hard setting the normals and colour in OutputLightingTextures()][:hat :programming :lighting :rendering]
[1:49:54][:Run the game to see that it looks as expected][:hat :lighting :rendering]
[1:50:03][Let OutputLightingTextures() use the computed normals][:hat :programming :lighting :rendering]
[1:50:13][:Run the game to see a tremendous amount of noise in the normals][:hat :lighting :rendering]
[1:51:32][Hard set Valid = false and the colour values and directions in LightingTest()][:hat :lighting :programming :rendering]
[1:52:56][:Run the game and note that the noise must be coming from somewhere up stream][:hat :lighting :rendering]
[1:54:12][Prevent LightingTest() from hard setting the colours][:hat :lighting :programming :rendering]
[1:54:35][:Run the game to see complete garbage][:hat :lighting :rendering]
[1:55:16][Make LightingTest() smooth the :lighting over 100 frames][:hat :programming :rendering]
[1:55:47][:Run the game to still see noise even in the :"debug visualisation"]
[1:56:25][Hard set Valid = true in LightingTest() to force it to blend][:hat :lighting :programming :rendering]
[1:56:35][:Run the game to see that this removes the noise from the :lighting points :"debug visualisation"][:hat :rendering]
[1:57:03][Hard set the directions in the blending case in LightingTest()][:hat :lighting :programming :rendering]
[1:57:54][:Run the game to see that the (computed) colours are garbage][:hat :lighting :rendering]
[1:58:00][Step through PushQuad() watching the vertices' LightIndex and LightCount, and then on through the rest of the :lighting code][:hat :rendering :run]
[2:08:39][Temporarily make OutputLightingTextures() clamp the colours][:hat :lighting :programming :rendering]
[2:09:27][:Run the game to see that this doesn't affect it][:hat :lighting :rendering]
[2:09:43][Temporarily try to make OutputLightingTextures() loop over the boxes in the same manner as OutputLightingPoints()][:hat :lighting :programming :rendering]
[2:11:23][:Run the game to see that the :lighting still doesn't correspond][:hat :rendering]
[2:12:24][Temporarily prevent UpdateAndRenderWorld() from calling PushFullClear() before OutputLightingPoints()][:hat :lighting :programming :rendering]
[2:12:40][:Run the game to see that the :lighting is still wrong][:hat :rendering]
[2:13:09][Temporarily try to make OutputLightingPoints() perform the very code from OutputLightingTextures()][:hat :lighting :programming :rendering]
[2:14:59][:Run the game and toggle between the two views to see that they perform identically][:hat :lighting :rendering]
[2:16:29][Read carefully through the :lighting code, following the textures down the pipeline, and note that there is one frame lag in them][:hat :rendering :research]
[2:19:36][Make UpdateAndRenderWorld() call PushLighting() immediately after EnableLighting()][:hat :lighting :programming :rendering]
[2:21:00][:Run the game to see that that totally fixes the problem][:hat :lighting :rendering]
[2:22:29][Remove the test code][:hat :lighting :programming :rendering]
[2:22:52][:Run the game to see that it doesn't work quite right][:hat :lighting :rendering]
[2:23:11][Hard set Valid = true in LightingTest()][:hat :lighting :programming :rendering]
[2:23:18][:Run the game to see that it's correct][:hat :lighting :rendering]
[2:24:55][:Owl of Shame Moment: The removed frame of lag exposed the fact that our :lighting indices were not lining up across frames][:hat :memory :rendering :speech]
[2:28:04][Q&A][:hat :speech]
[2:29:20][@jacksonbanan][Q: Perhaps the perspective of the game would make this a bit awkward to do but are you planning to have water in the game with reflections, sine waves, and shaders and all that cool stuff?][:hat :rendering]
[2:30:35][@pythno][Q: Blackboard please][:hat]
[2:30:45][:Lighting Index Correspondence, Old vs New Way][:blackboard :hat :memory :rendering]
[2:37:42][@roam00010011][Q: What time will the pre-stream will start tomorrow? Got some off-topic burning questions][:hat]
[2:38:00][@vaualbus][Q: So we have to call the PushLighting() twice for a solution? Or there is another way to solve the bug?][:hat :lighting :rendering]
[2:39:30][@theseltzer][Q: I know you said it's a common class of bug, but do you have any thoughts on how you might avoid a bug like this in the future?][:hat :memory]
[2:41:44][@vaualbus][Q: So this frame latency is bad if we would made this a multithread system?][:hat]
[2:42:03][@davechat][Q: Are you allowed to elaborate more on how Moustache works exactly?][:hat]
[2:42:22][@stormblaz][Q: So you cant use the 4th lines of light and on the 6th line the light stops? There is no other way to make the light stop?][:hat :lighting :rendering]
[2:42:55][Allow UpdateAndRenderWorld() to call PushFullClear()][:hat :programming :rendering]
[2:43:21][:Run the game to see that the :"debug visualisation" is as expected][:hat :lighting :rendering]
[2:44:31][@vaualbus][Q: What is the :performance on the big level now?][:hat :lighting :rendering]
[2:44:55][Make PlayWorld() generate 32 screens][:hat :"procedural generation" :programming]
[2:45:05][:Run the game to see our :lighting :performance][:hat :rendering]
[2:46:42][@steamymcfly][Q: Will you add tone mapping at some point?][:hat :rendering]
[2:46:55][@stormblaz][Q: Can you implement more light sources later? Like holding a torch, or such or other sources of light?][:hat :lighting :rendering]
[2:47:01][:Run the game to show all of the light sources][:hat :lighting :rendering]
[2:48:14][@somebody_took_my_name][Q: Not exactly on topic but you don't use your attempt in the for loop in SplitBox()][:geometry :hat]
[2:49:08][Set DimIndex = NextDimIndex at the end of SplitBox()][:geometry :hat :programming]
[2:49:39][:Run the game to see that everything seems fine, and note that the :lighting bounds should be based on the :camera][:hat :rendering]
[2:50:22][@jacksonbanan][Q: What's the differences between the game without OpenGL and with OpenGL?][:hardware :hat :rendering]
[2:50:45][@somebody_took_my_name][Q: Yep, otherwise it was a useless loop][:hat]
[2:51:04][@jim0_o][Q: Have you tried the Clang compiler (on windows, the versions of the last few months)? I have been loving the error messages, e.g. it rolls out scopes of macros. (I have it on F3 for when VisualStudio messages fail me.) Just wondering about your opinion if you have used it][:hat]
[2:54:08][Close it down with a few words on updating the Molly Rocket website][:hat :speech]
[/video]
