[video output=day404 member=cmuratori stream_platform=twitch stream_username=handmade_hero project=code title="Voxel-Indexed Lighting Samples" vod_platform=youtube id=xNS8M-vHUp8 annotator=Miblo]
[0:08][Recap and set the stage for the day]
[0:42][Run the game and consider the problem of reconstructing per-pixel lighting from our coarse computations]
[8:35][Blackboard: Sending down four interpolation points per quad, instead of doing a global gather]
[15:04][Blackboard: Radial-normalised interpolation]
[17:31][Run the game and consider whether or not to interpolate across primitives]
[20:41][Blackboard: Lighting Lookups]
[24:45][Blackboard: Storage format for a spherical query]
[25:34][Blackboard: Quick spatial query]
[31:00][Consider the problem of packaging up this data for parallel access by the GPU]
[39:18][Consult the Texture Lookup Functions in the OpenGL Shading Language 1.50 Quick Reference Card for sampling from a 3D texture[ref
    site="OpenGL Registry"
    page="The OpenGL Shading Language 1.50 Quick Reference Card"
    url="https://www.khronos.org/files/opengl-quick-reference-card.pdf"]]
[41:15][Blackboard: Artifacts across cell boundaries]
[44:28][Determine to create a voxel-based lighting solution]
[45:14][handmade_render_group.cpp: Introduce OutputLightingTextures()]
[46:25][handmade_world_mode.h: Augment lighting_solution to contain voxel and storage information]
[52:05][handmade_world_mode.h: Introduce lighting_texel linked list for fast access lookup]
[55:54][handmade_world_mode.h: Introduce lighting_textures]
[56:46][handmade_render_group.cpp: Begin to enable OutputLightingTextures() to pack our lighting data]
[59:34][handmade_render_group.cpp: Determine to prevent OutputLightingQuads() from considering the reflector's own colour]
[1:00:12][Run the game to see that it's running slower than expected]
[1:02:17][Run the game and note that we want to stop the reflectors from considering their own colour during the lighting pass]
[1:02:51][handmade_render_group.cpp: Change LightingTest() to multiply in the reflector's colour at the start, and ExtractReflectorsFromVerts() and ExtractReflectorsFromQuads() to not use the reflector's own emission colour]
[1:06:22][Run the game to see that the red and blue reflectors do not show their own colour, but that these colours are also not bouncing off other reflectors, and investigate why]
[1:11:53][handmade_render_group.cpp: Continue to enable OutputLightingTextures() to pack our lighting data into a linked list]
[1:16:14][Blackboard: Mapping world space positions into a screen space lookup table]
[1:20:45][handmade_render_group.cpp: Make OutputLightingTextures() index into voxels]
[1:25:23][Blackboard: Picking a cell from a grid]
[1:27:00][handmade_render_group.cpp: Make OutputLightingTextures() map the lighting into our voxel]
[1:32:39][handmade_world_mode.cpp: Make UpdateAndRenderWorld() call OutputLightingTextures() on test textures]
[1:35:31][handmade_render_group.cpp: Introduce OutputTextureDebug() for OutputLighting() to call]
[1:43:13][Run the game, toggle to the lighting view and see nothing]
[1:43:56][Step in to OutputLightingTextures() and...]
[1:45:40][Wish for the ability to optimise just one routine while waiting for our lighting solution to be computed]
[1:46:37][...inspect the values produced by OutputLightingTextures()]
[1:48:32][handmade_render_group.cpp: Fix OutputTextureDebug() to index into the correct locations]
[1:49:10][Run the game in release mode and see weirdly positioned light voxels]
[1:50:45][handmade_render_group.cpp: Try to put #pragma optimise around OutputTextureDebug() to disable optimisations]
[1:51:10][Step through OutputTextureDebug() to see that the colour is not a sane value]
[1:53:06][handmade_render_group.cpp: Try to make OutputTextureDebug() set the colour to white, and run the game to see that we are storing lighting samples, but that only the colour value is incorrectly computed]
[1:54:12][handmade_render_group.cpp: Fix OutputLightingTextures() to multiply the colour into the correct space]
[1:54:31][Run the game and see our voxelised lighting samples]
[1:54:55][Q&A][:speech]
[1:54:57][handmade_render_group.cpp: Remove the #pragma optimize]
[1:55:23][Run the game and express interest in seeing how this works]
[1:57:49][@Brian][Greetings Casey! For after the stream, here is a collaborative work from us in #hero for a help guide to setting up WeeChat]
[2:00:07][@roam00010011][Maybe it's a non-issue, but because the entity is tilted, when it walks in front of a cube it is being cut. Is there an elegant solution for it?]
[2:01:34][handmade_world_mode.cpp: Make AddPlayer() draw the hero bitmap and run the game]
[2:02:10][handmade_render_group.cpp: Increase the ZBias in PushBitmap() and run the game to see that the hero gets clipped differently by the geometry]
[2:05:15][@alexkelbo][When we made the high and low priority thread queues, how did we make the high queue actually have a higher priority? I can't find the difference between them in the implementation, if that makes sense]
[2:11:23][@roam00010011][If I was to guess, I would say the problem is not the 2D entities in 3D space, but rather 2D entities with 3D entities. If those cubes were sprites like the trees, it would work just fine]
[2:13:03][@alexkelbo][In the software renderer we aligned the memory to 16 bytes for SIMD but then we used the unaligned load and store instructions. Why is that?]
[2:16:18][Blackboard: False sharing of one cache line by two threads]
[2:18:12][That's about it for today][:speech]
[/video]
