[video output=day648 member=cmuratori stream_platform=twitch stream_username=handmade_hero  project=code title="Rebuilding Light Tables" vod_platform=youtube id=hNAuQyyuUtE annotator=Miblo]
[0:01][Recap and set the stage for the day building light tables][:lighting :speech]
[1:16][Demo our :lighting colour bleed][:run]
[2:07][Our SampleDirectionTable in handmade_sampling_spheres.inl samples direction \[0, 0, 1\] multiple times][:lighting :research]
[3:35][Plan to rebuild our light table in an evenly distributed blue noise pattern][:lighting :research :sampling]
[5:59][Consider :sampling the light at 16 samples per texel][:lighting :research]
[7:25][@bashtardis][You also need it to be blue-noise temporally as well as spatially for best result][:lighting :sampling]
[7:53][Consider using a pseudo-blue noise :sampling pattern, or tuning the distance parameter manually][:lighting :research]
[9:13][Toggle on the sphere drawing in PushLightingRenderValues()][:"debug visualisation" :lighting]
[9:46][Check out our :sampling sphere][:lighting :run]
[10:22][Plan to rebuild the table then view our drawing][:lighting :research :sampling]
[10:46][Reacquaint ourselves with hhsphere.cpp][:lighting :research :sampling]
[14:08][Remove SamplingSpheres from lighting_solution, the LightSamplingSphereFloatTable from handmade_sampling_spheres.inl with its generator in OutputSphereINL(), InterleaveDirections(), cube_store and sphere_store][:"data structure" :lighting :metaprogramming :sampling]
[18:17][Plan to make OutputSphereINL() output the SampleDirectionTable with all the octahedral rays for a given texel, then all those for the next texel, etc.][:lighting :metaprogramming :research :sampling]
[20:20][Make OutputSphereINL() output the SampleDirectionTable with all the octahedral rays for a given texel, then all those for the next texel, etc.][:lighting :metaprogramming :sampling]
[24:40][Reacquaint ourselves with the light sample sieving in GeneratePoissonDistribution()][:lighting :metaprogramming :research :sampling]
[26:41][Propose to draw the sampling sphere coloured by texel, then fix hhsphere.cpp][:"debug visualisation" :lighting :research :sampling]
[27:32][Make PushLightingRenderValues() draw the sampling sphere coloured by texel][:"debug visualisation" :lighting :sampling]
[33:18][Rework GenerateOctahedralLightingPattern() to structure the sampling directions with all the octahedral rays for a given texel, then all those for the next texel, etc.][:lighting :metaprogramming :sampling]
[35:58][The bug: Our call to GeneratePoissonDistribution(), with its randomness, using TotalDirectionCount, may yield fewer samples on a texel than we need][:lighting :research :sampling]
[37:38][Consider asking GeneratePoissonDistribution() for more sampling points][:lighting :research :sampling]
[38:40][Introduce direction_gen for GeneratePoissonDistribution() to return, and remove GeneratePoissonSamples(), TestFunc() and GeneratePoissonLightingPattern()][:"data structure" :lighting :metaprogramming :sampling]
[42:48][Hunt for a v2u + operator overload][:language :research]
[44:08][Introduce a v2u + operator overload][:language]
[44:37][Update GenerateOctahedralLightingPattern() to use our direction_gen, and ask GeneratePoissonDistribution() for 20% more samples than we'll use, introducing AllocDirArray()][:lighting :metaprogramming :sampling]
[51:34][Make GenerateOctahedralLightingPattern() print an error on "Direction count underflow for texel"][:lighting :metaprogramming :sampling]
[52:47][Finish up the usage code of hhsphere.cpp][:lighting :metaprogramming :sampling]
[57:38][Run hhsphere, and hit a number of "Direction count underflow for texel" errors][:admin :lighting :sampling]
[59:21][Inspect handmade_sampling_spheres.inl, try to compile with it and hit a syntax error][:language :lighting :research :sampling]
[1:00:25][Manually append a ")" to TOTAL_LIGHT_SAMPLE_DIRECTION_COUNT in handmade_sampling_spheres.inl][:language]
[1:01:29][Remove stale #if 0 from GridRayCast()][:language]
[1:01:42][Append the missing ")" to TOTAL_LIGHT_SAMPLE_DIRECTION_COUNT OutputSphereINL()][:lighting :metaprogramming :sampling]
[1:01:52][Update GridRayCast() to use our newly structured SampleDirectionTable][:lighting :sampling]
[1:18:09][Hit a read access violation in GridRayCast()][:lighting :run :sampling]
[1:18:43][Investigate our read access violation in GridRayCast()][:lighting :run :sampling]
[1:21:02][Reacquaint ourselves with tTerminate in ComputeWalkTable()][:lighting :research :sampling]
[1:25:24][Make ComputeWalkTable() set tTerminate to 0 if greater than or equal to 1000000]
[1:27:20][Plan to update ~remedybg from 0.3.5.0 to 0.3.6.3][:admin]
[1:28:05][Again hit a read access violation in GridRayCast()][:lighting :run :sampling]
[1:29:39][Let ComputeWalkTable() use tTerminate as is, and instead make GenerateOctahedralLightingPattern() output a valid \[0, 0, 1\] ray direction on underflow][:lighting :metaprogramming :sampling]
[1:30:58][Run hhsphere, and hit a number of "Direction count underflow for texel" errors][:admin :lighting :sampling]
[1:31:49][Inspect handmade_sampling_spheres.inl and compile just fine][:lighting :research :sampling]
[1:32:29][:Run the game without crashing, but with the sampling sphere possibly being drawn wrong][:lighting :sampling]
[1:33:12][Check RenderDiagrams() for participation in :lighting][:"debug visualisation" :research]
[1:34:12][Make PushLightingRenderValues() draw the sampling sphere lower down][:"debug visualisation" :lighting :sampling]
[1:34:31][Our sampling sphere is lit, and contains gaps][:lighting :run :sampling]
[1:35:55][Fix GridRayCast() to set TransferPPS\[Tx\] to the already accumulated TransferPPSAccum][:lighting :sampling]
[1:37:11][Our lighting is no longer overblown, but still bleeds, and dims while moving][:lighting :run :sampling]
[1:39:19][Try making GenerateOctahedralLightingPattern() ask GeneratePoissonDistribution() for 100% more samples than we'll use, and tighten the convergence criteria from 0.025 to 0.0125][:lighting :metaprogramming :sampling]
[1:41:39][Run hhsphere without completing][:admin :lighting :sampling]
[1:42:41][Revert the convergence criteria to 0.025 in GenerateOctahedralLightingPattern()][:lighting :metaprogramming :sampling]
[1:43:13][Run hhsphere, and still hit a number of "Direction count underflow for texel" errors][:admin :lighting :sampling]
[1:43:46][Investigate why GenerateOctahedralLightingPattern() is not receiving enough sample directions][:lighting :research :sampling]
[1:47:03][Our lighting sphere looks the same][:"debug visualisation" :lighting :run :sampling]
[1:47:17][We're missing something][:lighting :research :sampling]
[1:48:11][Break for snacks][:admin]
[1:48:38][:afk]
[1:51:56][Return with snacks][:admin]
[1:52:12][Consider abandoning vs debugging the sampling point picking scheme][:lighting :research :sampling]
[1:56:40][@tomisqi][What snacks?]
[1:57:21][Need more chicharrones][:food :speech]
[1:57:48][Consider evenly distributing sampling points in texel space][:lighting :research :sampling]
[1:59:01][Propose seeding 16 rays per texel, using a white noise distribution, repulsed to increase evenness, and prevented from leaving their containing texel][:lighting :research :sampling]
[2:01:02][@spacenaming][Won't you get clamping on the edges?][:lighting :sampling]
[2:01:37][Consider starting with the 16 rays per texel white noise distribution, without repulsion][:lighting :research :sampling]
[2:02:09][Make GeneratePoissonDistribution() seed the requested rays per texel in a white noise distribution, and remove GenerateOctahedralLightingPattern()][:lighting :metaprogramming :sampling]
[2:09:23][Run hhsphere, and find a more coherent SampleDirectionTable][:admin :lighting :sampling]
[2:09:55][Our lighting sphere is only half filled in][:"debug visualisation" :lighting :run :sampling]
[2:10:32][Fix GeneratePoissonDistribution() to produce a -1 to 1 distribution][:lighting :metaprogramming :sampling]
[2:11:58][Run hhsphere][:admin :lighting :sampling]
[2:12:09][Our lighting sphere is complete, if clumpy][:"debug visualisation" :lighting :run :sampling]
[2:13:05][Make GeneratePoissonDistribution() repulse the rays, keeping them in the same quadrant][:lighting :metaprogramming :sampling]
[2:18:16][Run hhsphere and quickly lock up][:admin :lighting :sampling]
[2:19:08][Loosen the convergence criteria from 0.025 to 0.14 in GeneratePoissonDistribution()][:lighting :metaprogramming :sampling]
[2:19:35][Run hhsphere to completion][:admin :lighting :sampling]
[2:19:52][Our lighting sphere is not horrible, but good enough for now][:"debug visualisation" :lighting :run :sampling]
[2:21:19][Our rays now look more sane][:"debug visualisation" :lighting :run]
[2:22:26][Make FullCast() clamp the RayIndex to the total count minus 1][:lighting]
[2:22:34][Determine to investigate our green light leakage][:"debug visualisation" :lighting :run]
[2:23:19][Investigate our green light leakage][:lighting :research]
[2:24:47][Toggle on the light atlas drawing in OpenGLEndFrame()][:"debug visualisation" :lighting]
[2:24:56][Our light atlases clearly contain energy bleed][:"debug visualisation" :lighting :run]
[2:25:08][Make OpenGLChangeToSettings() draw our light atlases in their entirety][:"debug visualisation" :lighting]
[2:26:35][Check out our full light atlases][:"debug visualisation" :lighting :run]
[2:26:49][Make OpenGLChangeToSettings() draw 0.25 of our light atlases in both X and Y][:"debug visualisation" :lighting]
[2:27:02][Glimpse our light atlases][:"debug visualisation" :lighting :run]
[2:27:11][Make OpenGLChangeToSettings() draw 0.025 of our light atlases in both X and Y][:"debug visualisation" :lighting]
[2:27:34][Glimpse our light atlases][:"debug visualisation" :lighting :run]
[2:27:37][Make OpenGLChangeToSettings() draw 0.025 of our light atlases in X][:"debug visualisation" :lighting]
[2:28:05][Check out our light atlases][:"debug visualisation" :lighting :run]
[2:28:35][Make OpenGLChangeToSettings() draw 0.0125 of our light atlases in X][:"debug visualisation" :lighting]
[2:28:46][Our light atlases have a consistent light bleed][:"debug visualisation" :lighting :run]
[2:28:55][Let OpenGLChangeToSettings() draw the original portion of our light atlases][:"debug visualisation" :lighting]
[2:29:04][Traverse the orphanage and watch the light bleed in certain areas][:"debug visualisation" :lighting :run]
[2:30:54][Start by investigating BlockCopyAtlas()][:lighting :research]
[2:32:05][Assert in UpdateLighting() that dVoxel.z is 0][:lighting]
[2:32:23][Correctly fail to hit the dVoxel.z assertion][:lighting :run]
[2:32:36][Scour UpdateLighting() for errors in other dVoxel values][:lighting :research]
[2:35:21][Assert in UpdateLighting() that dVoxel.x and dVoxel.y are <= 1][:lighting]
[2:36:18][Hit our dVoxel.x assertion][:lighting :run]
[2:36:30][Make UpdateLighting() skip the dVoxel.x and dVoxel.y assertions first time round][:lighting]
[2:37:05][Correctly fail to hit the dVoxel.x and dVoxel.y assertions][:lighting :run]
[2:37:15][Remove the dVoxel.x and dVoxel.y assertions from UpdateLighting()][:lighting :run]
[2:37:36][Scour BlockCopyAtlas() for bugs][:lighting :research]
[2:39:52][Traverse the orphanage and watch the light bleed in certain areas][:"debug visualisation" :lighting :run]
[2:40:03][Toggle off the light atlas drawing in OpenGLEndFrame()][:"debug visualisation" :lighting]
[2:40:15][Traverse the orphanage and carefully watch the lighting at a slow 0.04 timestep][:"debug visualisation" :lighting :run]
[2:41:50][Set tUpdateBlend to 1 in UpdateLighting()][:lighting]
[2:42:07][The lighting clearly blinks when copying the atlases][:"debug visualisation" :lighting :run]
[2:43:29][Scour BlockCopyAtlas() for bugs][:lighting :research]
[2:44:32][Toggle on the LIGHT_ATLAS_ASSERT for VALIDATE_TEXEL_ATLAS() to fire][:lighting]
[2:44:43][Trap on VALIDATE_TEXEL_ATLAS() of the DiffuseAtlas][:lighting :run]
[2:45:11][Make ValidateTexelComponent() consider a component of between -100 and 100 to be valid][:lighting]
[2:45:30][Immediately trap on VALIDATE_TEXEL_ATLAS() of the SpecAtlas][:lighting :run]
[2:45:44][Consider deferring until next time the investigation of our out-of-bounds lighting values][:lighting :research]
[2:49:13][Introduce VoxelIndexIsInDim() for GridRayCast() to assert that the sample fetch is in bounds][:lighting]
[2:55:54][Hit our IsInBounds assertion in GridRayCast()][:lighting :run]
[2:58:36][Get it][:lighting :research]
[3:00:34][Toggle off the ray drawing in PushLightingRenderValues(), and toggle on DebugDrawSpatialGrid() in UpdateLighting()][:"debug visualisation" :lighting]
[3:01:36][Immediately trap on VALIDATE_TEXEL_ATLAS() of the SpecAtlas][:lighting :run]
[3:01:49][Toggle off the LIGHT_ATLAS_ASSERT][:lighting]
[3:01:57][Our bug: We can sample garbage in Z when not hitting an occluder][:"debug visualisation" :lighting :run]
[3:06:26][GridRayCast() is already clamping][:lighting :research]
[3:09:10][Scour GridRayCast() for a subtle bug causing out-of-bounds sampling][:lighting :research]
[3:14:00][Set the first entry of SampleDirectionTable to an invalid \[0, 0, 0\]][:lighting]
[3:14:49][Hit our read access violation in GridRayCast() on an invalid \[0, 0, 0\] sample direction][:lighting :run :sampling]
[3:14:52][Inspect the values in GridRayCast() on an invalid \[0, 0, 0\] sample direction][:lighting :run :sampling]
[3:18:21][GridRayCast() produces a bogus Txy value][:lighting :run :sampling]
[3:19:17][Revert the first entry of SampleDirectionTable to the generated value][:lighting]
[3:19:25][Consider calling it for today][:speech]
[3:20:04][Take one last look at our light bleed, blinking on copy and light source occlusion][:lighting :run]
[3:23:06][@midnightsun55][Brooo what is going on, [@cmuratori Casey] is about to do Unreal Engine 6 by himself at this point]
[3:23:18][Call it for today][:speech]
[/video]
