[video output=day558 member=cmuratori stream_platform=twitch stream_username=handmade_hero project=code title="Assigning Lighting Probe Slots" vod_platform=youtube id=TrUzbXwIdbk annotator=Miblo]
[0:00][Plug Molly Rocket's Discord channel[ref
    site=Discord
    page=MollyRocket
    url=https://discord.gg/mollyrocket]][:speech]
[1:50][Demo our more performant ground cover][:"entity system" :run]
[3:05][Determine to send down :lighting probe information, initially gauging the :performance of the :sampling][:run]
[6:52][Plan to sample pre-fabricated :lighting][:sampling :speech]
[10:03][Make UpdateAndRenderEntities() draw the light probes as white cubes][:"debug visualisation" :lighting]
[10:14][See our pure white probes][:"debug visualisation" :lighting :run]
[10:28][Wonder if :lighting is enabled][:research]
[11:08][Set up to send :lighting information to our perfect reflectors][:run]
[12:36][Modify lighting_textures for our light probe-based solution, including a voxel lookup][:"data structure" :lighting]
[19:00][Estimate the number of visible light probes][:lighting :run]
[19:25][Augment lighting_textures with a 128³ LightVoxelIndex][:"data structure" :lighting]
[23:04][Determine to switch the :lighting solution away from a push-forward scheme, to a static buffer][:research]
[25:45][Augment game_render_commands with LightProbe data, subsuming lighting_textures][:"data structure" :lighting]
[28:29][Remove PushLighting() and OutputLightingPoints()][:lighting]
[31:48][Crash on the GetCenter() call in BuildSpatialPartitionForLighting()][:lighting :run]
[32:10][Recall what LightingTest() does with the Solution][:lighting :research]
[33:30][Crash again on the GetCenter() call in BuildSpatialPartitionForLighting()][:lighting :run]
[33:40][Recall that PushLighting() used to help set up the RootBox][:lighting :research]
[34:47][Step in to LightingTest() to see that the LightBoxes are not allocated][:lighting :memory :run]
[35:41][Introduce BeginLightingComputation() and rename LightingTest() to EndLightingComputation() for UpdateAndRenderWorld() to call][:lighting]
[41:26][Keep open the possibility of making a hardware-based ray tracing solution][:lighting :speech]
[42:37][Augment game_render_commands with a buffer of lighting_box LightOccluders, and remove LightBox and LightPoint data from render_group][:"data structure" :lighting]
[46:28][Switch PushCube() and EndLightingComputation() over to use our modified data structures][:lighting]
[51:43][Crash again on the GetCenter() call in BuildSpatialPartitionForLighting()][:lighting :run]
[52:27][Begin to make OpenGLInit() allocate our Light buffers][:lighting :memory]
[54:47][Hunt in vain for a main :memory allocator in the renderer][:research]
[57:00][Augment open_gl with static Light arrays][:"data structure" :lighting :memory]
[58:59][Make OpenGLBeginFrame() initialise the Light arrays][:lighting]
[1:02:13][Our GetCenter() crash is resolved][:lighting :run]
[1:02:39][Make BeginLightingComputation() call EnableLighting()][:lighting]
[1:06:03][EndLightingComputation takes 14% of our 41ms frame time][:lighting :performance :run]
[1:06:32][Set up to fill out our light probes][:lighting :research]
[1:07:57][Change UpdateAndRenderEntities() to push our real LightProbeCount onto the :"debug system", and perform DrawGroundCover() in the main entity loop][:"entity system"]
[1:09:47][Consider making the light probes persist stably across frames][:caching :lighting :research]
[1:12:12][Light probe persistence 1: Locating light probe information according to its index in the entity active set][:caching :lighting :research]
[1:16:26][Light probe persistence 2: Keeping a separate list for light probe indices][:caching :lighting :research]
[1:18:32][Reacquaint ourselves with the entity registration code][:"entity system" :research]
[1:20:04][Augment the world with a LightProbeSlots free list][:caching :"data structure" :lighting]
[1:23:44][Augment entity with a LightProbeIndex and make CreateWorld() initialise our light probe free list][:caching :"data structure" :lighting :memory]
[1:27:36][Consider where the light probe free list should live][:caching :"data structure" :lighting :memory :research]
[1:29:55][Introduce AssignIndices() and RemoveIndices() for EnsureRegionIsUnpacked() to call][:caching :"data structure" :lighting]
[1:34:26][@seabass][@cmuratori You might want to ban the person spamming Twitch chat with stupid crap]
[1:35:16][Encourage people not to use Twitch chat][:speech]
[1:36:48][@graemephi][Subscriber only chat]
[1:37:19][Finish implementing RemoveIndices() and augment entity with a LightProbeClear for FillUnpackedEntity() and UpdateAndRenderEntities() to use][:caching :"data structure" :lighting]
[1:41:22][The purpose of clearing light probe slots][:caching :"data structure" :lighting :speech]
[1:42:49][Address Discord spam][:admin]
[1:47:32][Fix up compile errors, passing the MaxLightProbeCount down to CreateWorld()][:caching :"data structure" :lighting :speech]
[1:51:57][Hit our IsLightProbe() assertion in UpdateAndRenderEntities()][:"entity system" :lighting :run]
[1:52:34][Prevent EnsureRegionIsUnpacked() from calling RemoveIndices(), deleting that function and instead making PackEntity() perform its code][:caching :"data structure" :lighting]
[1:54:31][Again hit our IsLightProbe() assertion in UpdateAndRenderEntities()][:"entity system" :lighting :run]
[1:55:19][Ensure that the UnpackedEntities buffer begins cleared][:"entity system" :lighting :research]
[1:56:16][Assert in PackEntity() that LightProbeIndex is 0 for non-light probe entities][:"entity system" :lighting]
[1:56:39][Assert in AssignIndices() that LightProbeIndex is 0][:"entity system" :lighting]
[1:57:14][Hit our new assertion in AssignIndices()][:"entity system" :lighting :run]
[1:58:09][Assert in ClearUnpackedEntityCache() that LightProbeIndex is 0, after calling PackEntity()][:"entity system" :lighting]
[1:58:35][Hit our new assertion in AssignIndices(), to see also that LightProbeClear is 1][:"entity system" :lighting :run]
[1:58:58][Investigate why we are trying to assign an index to an entity that already has one][:"entity system" :lighting :research]
[2:00:40][Reintroduce RemoveIndices() for PackEntity() and EnsureRegionIsUnpacked() to call][:"entity system" :lighting]
[2:01:55][Again hit our assertion in AssignIndices()][:"entity system" :lighting :run]
[2:04:46][Q&A][:speech]
[2:07:05][@somebody_took_my_name][Q: Off-topic: How do you parallelize hash functions?[ref
    site=Wikipedia
    page="Merkle tree"
    url=https://en.wikipedia.org/wiki/Merkle_tree]][:hashing :threading]
[2:10:07][@xxthebigfoxx][Q: How is a hash function like the meowhash useful for game development?][:hashing]
[2:10:49][@pistonminer][Q: This is sorta off-topic so if you don't think it's relevant, feel free to disregard. With member functions they're namespaced based on the type, whereas with free functions they're all in the same namespace unless you specifically namespace. (Of course what the compiler generates is identical.) Since you don't use explicit C++ namespaces, as far as I know, do you think this is a problem and, if so, how do you work around it?][:language]
[2:11:26][@thepr1ms][Q: Hi [@cmuratori Casey], I've missed most of the last few streams. Could you run the game quickly so I can see where we're at?]
[2:11:52][@EladCiuraru][Why not follower only chat?]
[2:14:01][@sapper123][Q: You could do a 1-day follower limit, or something large]
[2:14:42][@culdevu][Q: Since we're going off-topic: I was looking at DPI-aware :UI and :rendering and it seems annoying in win32. I'm usually many years behind trends, so is high-DPI rendering a thing to worry about these days?]
[2:15:53][Close things down][:speech]
[/video]
