[video output=day416 member=cmuratori stream_platform=twitch stream_username=handmade_hero project=code title="Separating Lighting and Geometry Submission" vod_platform=youtube id=NjKttSC6mG4 annotator=Miblo]
[0:15][Recap and set the stage for the day][:speech]
[1:03][:Run the game to see a :"debug visualisation" of our current :lighting solution][:rendering]
[1:53][Make UseProgramBegin() use glVertexAttribIPointer() rather than glVertexAttribPointer() for LightIndex and LightCount[ref
    site=docs.GL
    page=glVertexAttribPointer
    url=http://docs.gl/gl3/glVertexAttribPointer]][:hardware :rendering]
[5:22][:Run the game to see our correctly coloured scene, and thank @seventh_chord for the suggestion][:lighting :rendering]
[6:52][Try to make VertLightIndex, VertLightCount, FragLightIndex and FragLightCount regular signed ints][:hardware :lighting :rendering]
[7:52][:Run the game to see the exact same results][:"debug visualisation" :lighting :rendering]
[8:11][Let SumLight() loop over the whole LightCount and call SumLight()][:hardware :lighting :rendering]
[8:56][:Run the game to see that we're in striking distance][:"debug visualisation" :lighting :rendering]
[10:41][Cursorily investigate why the light seems to be so blown out][:lighting :rendering]
[12:12][:Run the game and consider what we need to do][:lighting :rendering]
[16:13][Light / :Geometry Specification: 1) Occluders separate from sprites][:blackboard :lighting :rendering]
[20:43][Light / :Geometry Specification: 2) Sampling Control][:blackboard :lighting :rendering]
[24:21][Our tasks: 1) "No :Lighting" Lighting; 2) Occluder Buffer; 3) Samples for Occluders][:blackboard :rendering]
[25:12][Make CompileZBiasProgram() keep FragLightIndex unlit][:hardware :lighting :rendering]
[26:48][:Run the game to see our one unlit primitive][:lighting :rendering]
[27:11][Add LightingEnabled and LightIndex to render_group, and enable PushQuad() to use these values][:lighting :rendering]
[29:53][:Run the game to see nothing lit][:lighting :rendering]
[30:35][Try to increase the main resolution to 1920x1080][:rendering]
[30:42][:Run the game to see that it runs fine]
[31:13][Introduce EnableLighting() for UpdateAndRenderWorld() to call][:rendering]
[33:40][:Run the game to see our :"debug system" correctly unlit]
[34:10][Make UpdateAndRenderWorld() only call EnableLighting() if we are not ShowLighting][:lighting :rendering]
[34:27][:Run the game to see that everything is lit as expected]
[35:57][Demonstrate the necessity of an occluder buffer caused by the tree sprites][:lighting :rendering :run]
[39:02][Try to run the :lighting in real time][:rendering]
[39:52][:Run the game to see that it is surprisingly fast, but exhibiting flickering artifacts][:lighting :rendering]
[44:00][Explain the necessity of having separate occluders and world :geometry][:lighting :rendering :speech]
[45:59][Separate lighting_element out into lighting_surface, lighting_point and lighting_intermediate][:lighting :rendering]
[52:32][Gradually get all necessary functions to use these new structures][:lighting :rendering]
[1:10:43][Duplicate the emanating surface normal in the lighting_point][:lighting :rendering]
[1:16:00][Choosing where in the surface to record the light][:blackboard :lighting :rendering]
[1:17:12][Make ComputeLightPropagation() accumulate the light of all :lighting points][:rendering]
[1:20:03][Continue to propagate the new :lighting structures to all necessary functions, including removing GatherFinalLighting()][:rendering]
[1:27:12][:Run the game to see no :lighting, and step through it to debug why][:rendering]
[1:28:46][Make ExtractReflectorsFromQuads() correctly set the PointCount][:lighting :rendering]
[1:29:03][:Run the game to see our working and sped-up, although still flickering, :lighting solution][:rendering]
[1:31:33][Consider merging lighting_point into lighting_intermediate][:lighting :rendering :speech]
[1:33:44][Merge lighting_intermediate into lighting_solution and propagate that change to the necessary functions][:lighting :rendering]
[1:46:08][Step through ExtractReflectorsFromQuads() and inspect the values][:lighting :rendering :run]
[1:48:18][Remove EmitC from lighting_point and make ComputeLightPropagation() set the correct EmitC][:lighting :rendering]
[1:49:22][:Run the game as we were before][:lighting :rendering]
[1:49:57][Introduce the notion of SamplePower in ComputeLightPropagation()][:lighting :rendering]
[1:50:59][:Run the game to see that this doesn't quite provide what we want][:lighting :rendering]
[1:52:28][Make ComputeLightPropagation() call AccumulateSample() only once, outside the surface point loop if it gets a ClosestPointIndex][:lighting :rendering]
[1:56:19][:Run the game to see the light still not really doing what we want][:lighting :rendering]
[1:56:46][Read through CompileZBiasProgram() and ExtractReflectorsFromQuads() for any blunders][:lighting :rendering]
[1:57:52][:Run the game and wonder why we are still getting uniform :lighting][:rendering]
[1:58:31][Read through the code, wondering why we rarely get gradients][:lighting :rendering]
[2:00:41][:Run the game and take another look at the :lighting][:rendering]
[2:01:17][Q&A][:speech]
[2:01:57][@Kknewkles][Q: Hi Casey! Wanted to pick your brain about :metaprogramming a bit. 0 - Short of a manual comparison, how do you obtain an enum field's name by supplying a corresponding numeric value? E.g. 1 -> Sunday? Or metaprogramming is overkill for this? 1 - If you have a gigantic struct printf which you want to "automate", in the way of not having to manually enlist all its fields, metaprogramming is the way to go here, right? Probably take the definition of the struct from the (Vulkan) spec, store it in a file, for example, and match it with the struct going by the sizes and offsets of the fields?][:language]
[2:03:10][@yoshimoto555][Q: Would doing the ray tracing on the GPU with OpenCL or CUDA be viable?][:lighting :rendering]
[2:03:28][@dragoonx6][Q: Do you have any issues with the (ms) CRT on windows? Do you think :memory management could be improved?]
[2:04:36][@longboolean][Q: Concerning the flickering, when does mixing between frames give appropriate results, when not?][:lighting :rendering]
[2:05:20][@garryjohanson][Q: So, mentioning this is probably a bit premature because I haven't looked into it very thoroughly, but there's a CPU implementation of OpenGL and DirectX called "swiftshader". Could be useful for debugging purposes]
[2:06:52][Close things down][:speech]
[/video]
