[video output=day375 member=cmuratori stream_platform=twitch stream_username=handmade_hero project=code title="Adding Distance-based Fog" vod_platform=youtube id=RvEOtCTDWf0 annotator=Miblo]
[0:09][Recap and set the stage for the day]
[2:51][Run the game and show where we left off]
[3:18][handmade_world_mode.cpp: Make PlayWorld() stack up 10 rooms and run the game to view them]
[4:57][handmade_world_mode.cpp: Make AddStandardRoom() create holes on every floor]
[5:18][Run the game to view the entities each floor comprises, and determine to reintroduce fog]
[11:57][handmade_opengl.cpp: Try to introduce a GlobalFrameBufferDepth for OpenGLRenderCommands() to output a bitmap[ref
    site="docs.GL"
    page="glBlitFramebuffer"
    url="http://docs.gl/gl3/glBlitFramebuffer"]]
[14:51][Run the game to find that glFramebufferTexture2D() failed, and undo our changes]
[17:47][handmade_opengl.cpp: Begin to reintroduce fog]
[20:13][Blackboard: "Fog" darkening based on distance]
[25:30][handmade_opengl.cpp: Enable the VertexCode to linearly interpolate between the FragColor and FogColor, using GLSL's mix()[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"]]
[36:16][Run the game to see the blending between the two colours]
[36:53][handmade_opengl.cpp: Investigate why the bitmaps are not getting fogged]
[41:42][handmade_opengl.cpp: Enable the FragmentCode to perform the fogging lerp]
[44:09][Run the game to see what we'd expect to see]
[44:33][handmade_opengl.cpp: Enable the VertexCode to compute the FogAmount based on the distance from camera]
[49:14][handmade_opengl.cpp: Introduce Clamp01MapToRange() in the shader]
[51:14][handmade_opengl.cpp: Make the VertexCode call that Clamp01MapToRange()]
[52:32][Run the game and assume that nothing is incorrect there]
[52:45][handmade_opengl.cpp: Make OpenGLInit() and OpenGLRenderCommands() setup our fog data]
[56:18][A few words on threading cables through conduits]
[58:18][handmade_render_group.h: Consider removing render_entry_cliprect in favour of render_entry_textured_quads]
[1:01:03][handmade_render_group.h: Remove render_entry_bitmap, render_entry_rectangle, render_entry_clear and render_entry_saturation]
[1:02:38][Note that this simplification provides us with the ability to view the fog from a different direction]
[1:03:34][handmade_render_group.h: Add fog data to render_entry_cliprect]
[1:03:54][handmade_opengl.cpp: Make the render_entry_textured_quads case in OpenGLRenderCommands() set the fog data]
[1:05:08][win32_handmade.cpp: Pull in glUniform1f, glUniform2fv, glUniform3fv and glUniform4fv from corearb.h[ref
    site="Khronos"
    page="glcorearb.h"
    url="https://www.khronos.org/registry/OpenGL/api/GL/glcorearb.h"]]
[1:08:06][Run the game to determine that we are passing everything through correctly]
[1:08:16][handmade_render_group.h: Add a render_entry_cliprect LastSetup to render_group and propagate that change]
[1:13:36][handmade_render_group.cpp: Clean up how the render_entry_cliprect NewSetup gets used]
[1:19:58][handmade_math.h: Introduce versions of RectMinMax() and RectMinDim() that return a rentangle2i]
[1:21:32][handmade_render_group.cpp: Continue cleaning up the use of NewSetup]
[1:22:42][Run the game to see nothing yet]
[1:23:01][handmade_render_group.cpp: Make BeginRenderGroup() initialise the fog distances]
[1:23:45][Run the game to see our game drawing correctly, and note why]
[1:24:47][handmade_render_group.cpp: Enable SetCameraTransform() to compute the fog by its distance]
[1:26:36][Run the game to see the fog taking effect through the hole]
[1:27:21][handmade_opengl.cpp: Enable the FragmentCode to take a FogColor and blend part of it]
[1:30:19][handmade_render_group.h: Add FogColor to render_entry_cliprect]
[1:30:28][handmade_opengl.cpp: Make OpenGLRenderCommands() set that FogColor]
[1:31:40][Run the game to see our programatically set fog colour]
[1:31:45][handmade_render_group.cpp: Tweak the FogColor in BeginRenderGroup()]
[1:33:14][handmade_render_group.cpp: Investigate how Clear() is working]
[1:35:57][handmade_math.h: Introduce LinearTosRGB()]
[1:36:33][handmade_render_group.cpp: Make BeginRenderGroup() Square the FogColor, and run the game to determine that the Clear does not go through sRGB]
[1:37:06][handmade_platform.h: Label the ClearColor in game_render_commands as not in linear space, but in sRGB space]
[1:39:05][handmade_render_group.cpp: Make Clear() set the FogColor]
[1:41:21][Run the game and consider that to be quite good]
[1:42:30][Consider handling alpha fading of levels nearer to the camera than the hero's current level]
[1:43:39][handmade_world_mode.cpp: Enable AddStandardRoom() to generate stairs]
[1:49:23][Run the game and hop down the stairs]
[1:51:25][handmade_render_group.h: Rename render_entry_cliprect to render_setup for render_entry_textured_quads to contain, and propagate this change, simplifying PushSetup() and OpenGLRenderCommands()]
[2:13:17][handmade_render.cpp: Remove LinearizeClipRects() and PrepForRender()]
[2:14:39][Run the game to see that that worked just great, with a few words on how much cleaner the render commands are now]
[2:15:57][Q&A][:speech]
[2:16:50][@nyeecola][Has the framerate tanked after implementing fog? Or was that a wrong impression of mine?]
[2:17:02][Compile and run with various optimisation settings]
[2:19:54][@Miblo][Now that we're full 3D, may it be worth extending the debug visualisation rectangles into the third dimension?]
[2:20:19][@nyeecola][Why would you (in this case) compile without optimizations? I don't get how it changes your framerate that much (sorry if this is a dumb question)]
[2:21:28][handmade_sim_region.cpp: Make a KillSwitch to disable GetClosestTraversable()]
[2:23:42][Run the game and compare the framerate with and without GetClosestTraversable() running]
[2:25:43][Step in to GetClosestTraversable() and calculate how many operations it performs, and the number of cycles in which it must execute]
[2:30:12][Look at the disassembly for GetClosestTraversable() when compiled with -Od]
[2:33:00][Switch to -O2 and look at the disassembly for GetClosestTraversable() again]
[2:36:08][Compiling with optimisations on inhibits our ability to debug the code effectively]
[2:39:55][@macielda][How do you feel about Uniform Buffer Objects? Am I right to assume the Render Setup struct could be passed to the shader as an UBO instead of separate Uniforms?]
[2:40:24][@macielda][How does the hero know it should hop to the lower level instead of the upper level at the end of the stairs? Where is the code for that?]
[2:41:10][@thesizik][What does the software renderer look like at the moment?]
[2:41:33][@chrysos42][I assume the problems you solve in Handmade Hero are fairly representative of problems you face as a game dev. Can you comment about any social aspects of being a game dev, e.g. how collaborative or supportive the community is, or what it's like sharing a codebase with a number of others?]
[2:44:18][@rocketbuny][How many lines of code does Handmade Hero have?]
[2:47:42][Wind it on down with a glimpse into the future][:speech]
[/video]
