[video output=day394 member=cmuratori stream_platform=twitch stream_username=handmade_hero project=code title="Basic Multigrid Lighting Upward Iteration" vod_platform=youtube id=h6D85wUYMgg annotator=Miblo]
[0:03][Recap and set the stage for the day]
[0:54]["You can't win 'em all but you're certainly not gonna win if you never roll"][quote 584]
[0:59][Run the game to see where we're at with respect to lighting]
[4:13][A few words on multigrid solvers]
[6:54][The two halves of our problem: 1) Getting our lighting information down to the renderer]
[9:22][2) We will need normals]
[9:59][handmade_opengl.h: Rename WriteEmit to WriteEmitFramebuffer in the light_buffer struct, and describe the framebuffers in this struct]
[14:33][Blackboard: On the possible need for an additional texture to write into]
[20:06][handmade_opengl.cpp: Toggle on the framebuffer visualisation code in OpenGLRenderCommands()]
[22:50][Research glReadBuffer[ref
    site=docs.GL
    page="glReadBuffer"
    url=http://docs.gl/gl3/glReadBuffer]]
[24:27][handmade_opengl.cpp: Enable the framebuffer visualisation code to pick from a colour buffer]
[27:30][Run the game a get a black screen]
[27:58][handmade_opengl.cpp: Introduce FakeSeedLighting() and ComputeLightTransport()]
[30:17]["I assume it's "hare-brained", like the rabbit. Or is it "hair-brained", like the follicle?"][quote 585]
[30:29][handmade_opengl.cpp: Implement FakeSeedLighting() and introduce OpenGLBeginScreenFill() and OpenGLEndScreenFill() to perform some of ResolveMultisample()]
[35:06][Run the game to make sure that that still works]
[35:23][handmade_opengl.cpp: Finish implementing FakeSeedLighting()]
[37:12][handmade_opengl.cpp: Introduce CompileFakeSeedLighting() based on CompileResolveMultisample(), with some structured artwork]
[41:12][handmade_opengl.h: Introduce fake_seed_lighting_program struct and add it to open_gl]
[42:14][handmade_opengl.cpp: Introduce a version of UseProgramBegin() that only takes a Prog and Setup, and enable OpenGLRenderCommands() to set up the debug lighting framebuffer]
[44:30][Run the game to see a green screen, and investigate why we do]
[45:45][Consult the Quick Reference Card[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"] and the OpenGL Spec[ref
    site="Khronos"
    page="The OpenGL Shading Language 1.50"
    url="https://khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.1.50.pdf"] to determine how to line up the output fragments with the framebuffer's bound colour attachments]
[50:23][handmade_opengl.cpp: Specify the fragments into which CompileFakeSeedLighting() should write our test colours]
[51:18][Run the game to see that that worked]
[51:21][handmade_platform.h: Add DebugLightBufferIndex and DebugLightBufferTexIndex to game_render_settings]
[54:50][Determine to provide debug keys to control the lighting framebuffers]
[56:22][handmade_opengl.h: Move the DebugLightBuffer settings into open_gl]
[56:50][win32_handmade.cpp: Add debug keys in Win32ProcessPendingMessage() for cycling through the lighting framebuffers]
[58:10][Note the "Sign extension bug" issue[ref
    site="GitHub"
    page="HandmadeHero/cpp Issues"
    url="https://github.com/HandmadeHero/cpp/issues"]]
[58:45][win32_handmade.cpp: Continue adding these debug keys in Win32ProcessPendingMessage()[ref
    site="MSDN"
    page="GetKeyState function"
    url="https://msdn.microsoft.com/en-us/library/windows/desktop/ms646301"]]
[1:00:54][handmade_opengl.cpp: Make OpenGLRenderCommands() keep our framebuffer indices in bounds]
[1:02:58][handmade_math.h: Introduce a version of Clamp() that works on s32s]
[1:03:32][win32_handmade.cpp: Tweak those bindings in Win32ProcessPendingMessage()]
[1:04:20][Run the game to try cycling through the framebuffers, and investigate why nothing happens]
[1:05:39][win32_handmade.cpp: Change Win32ProcessPendingMessage() to use 0 and 9]
[1:06:47][Run the game to see that 0 and 9 do work]
[1:07:12][Investigate which VK_ keys are available to us]
[1:10:06][win32_handmade.cpp: Make Win32ProcessPendingMessage() use VK_OEM_PLUS and VK_OEM_MINUS]
[1:10:46][Run the game to try out our key bindings, and investigate why we can't cycle between the textures]
[1:12:29][handmade_opengl.cpp: Double-check CompileFinalStretch()]
[1:13:05][Consult the documentation on Framebuffer[ref
    site="Khronos"
    page="Framebuffer"
    url="https://khronos.org/opengl/wiki/Framebuffer"]]
[1:15:00][handmade_opengl.cpp: Make OpenGLChangeToSettings() specify the mapping table and call glDrawBuffers() for both framebuffers[ref
    site="Khronos"
    page="glcorearb.h"
    url=https://www.khronos.org/registry/OpenGL/api/GL/glcorearb.h][ref
    site=docs.GL
    page="glDrawBuffers"
    url=http://docs.gl/gl3/glDrawBuffers]]
[1:17:52][Run the game and cycle between our texture]
[1:18:30][win32_handmade.cpp: Enable Win32ProcessPendingMessage() to print out debug text for the keyboard input]
[1:20:26][Run the game and inspect that output]
[1:21:05][win32_handmade.cpp: Fix Win32ProcessPendingMessage() to only handle the lighting keys in the IsDown path]
[1:22:05][Run the game to see that this is more stable]
[1:22:25][handmade_opengl.cpp: Try to make CompileFakeSeedLighting() use vec3 textures]
[1:24:15][Run the game to see that that seems to work]
[1:25:02][handmade_opengl.cpp: Enable CompileFakeSeedLighting() to light the scene with an emitter that is red on the left and green on the right]
[1:36:01][handmade_opengl.cpp: Make CompileFakeSeedLighting() use a v4 for the output gl_FragData]
[1:36:23][Run the game, see nothing and investigate why]
[1:39:09][handmade_opengl.cpp: Force CompileFakeSeedLighting() to draw a red blob]
[1:40:57][Run the game, see a 10 pixel blob in the corner of the screen and investigate why]
[1:43:05][Realise that we're rendering at 960*540]
[1:43:25][handmade_opengl.cpp: Make CompileFakeSeedLighting() centre the light and slow down its movement]
[1:44:43][Run the game and try moving the light]
[1:45:16][handmade_opengl.cpp: Implement the upward phase of ComputeLightTransport(), building successively less detailed light buffers]
[1:50:39][handmade_opengl.cpp: Introduce OpenGLBindTex() for ComputeLightTransport() to call]
[1:53:49][handmade_opengl.cpp: Introduce CompileMultiLightUp() based on CompileFinalStretch()]
[2:03:01][handmade_opengl.cpp: Introduce a blank CompileMultiLightDown() and fix compile errors]
[2:05:41][Run the game to see that one of our lower detail textures is black, and investigate why]
[2:10:03][handmade_opengl.cpp: Try to make ComputeLightTransport() use the FakeSeedLighting() program at every level]
[2:10:46][Run the game to determine that there's something wrong with CompileMultiLightUp()]
[2:11:42][handmade_opengl.cpp: Manually set all the values in CompileMultiLightUp()]
[2:12:16][Run the game to see no pixels being filled]
[2:12:34][handmade_opengl.cpp: Make CompileMultiLightUp() correctly set the input position]
[2:12:50][Run the game and successfully cycle through the colours]
[2:13:01][handmade_opengl.cpp: Remove the debug code from CompileMultiLightUp()]
[2:13:10][Run the game and cycle through the detail levels, but see that texture 1 uses red rather than green, and investigate why]
[2:17:03][@4bitlightning][Additional semicolon in glGetUniformLocal "SourceBackEmitTex;"]
[2:17:21][handmade_opengl.cpp: Remove spurious semicolon from CompileMultiLightUp()]
[2:17:28][Run the game and cycle through all the textures and detail levels]
[2:17:48][Q&A][:speech]
[2:19:14][@fr0styninja][Is this going to be pulled out of the final ship to pull aside as DLC content to charge for?]
[2:19:39][@4bitlightning][Ideas for a good IDE-integrated debugger for Linux, like VS and CDB?]
[2:21:08][@d7samurai][Could you recap / outline the idea for this lighting scheme?]
[2:22:17][@zilarrezko][Will I be able to pay money for an expansion that crashes every so often?]
[2:22:53][@hholst80][Is this a single player game or will there be some network / multiplayer features?]
[2:24:37][Close it down][:speech]
[/video]
