[video output=day472 member=cmuratori stream_platform=twitch stream_username=handmade_hero project=code title="Making a Simple Scene with the Separated Renderer" vod_platform=youtube id=D3nI8x_pxpU annotator=Miblo]
[0:00][Recap and set the stage for the day cleaning up the renderer's :API][:speech]
[0:50][Texture handling][:api :"asset loading" :rendering :speech]
[3:38][Texture atlases and mipmapping][:api :"asset loading" :rendering :speech]
[6:30][Our potential to lean on the streaming system for texture handling][:api :"asset loading" :rendering :speech]
[9:03][Keep Reminder.txt open][:admin]
[9:45][:Run the Renderer Test with the determination to render textured cubes and sprites]
[10:41][Consult a screenshot of Hartacon Tactics[ref
    site="https://media.indiedb.com/images/games/1/26/25317/s.jpg"
    url=https://media.indiedb.com/images/games/1/26/25317/s.jpg]][:art :research]
[15:16][Introduce PushSimpleScene()][:rendering]
[20:14][:Run the Renderer Test to see our world of cubes][:rendering]
[20:21][Make PushSimpleScene() push blue cubes][:rendering]
[20:57][:Run it to see our blue world][:rendering]
[21:20][Make our :camera orbit the world]
[22:09][:Run it to see our orbiting perspective of the world][:camera]
[22:32][Apply a texture to our cubes][:"asset loading" :rendering]
[28:43][Enable OpenGLManageTextures() in handmade_renderer_opengl.cpp to fully manage the textures, introducing DequeuePending() and EnqueueFree() in handmade_renderer.h][:rendering :threading]
[35:05][Wait-free vs ticketed mutex][:speech :threading]
[35:57][Finish implementing EnqueueFree() and OpenGLManageTextures()][:rendering :threading]
[41:21][:Run the game to see that we're not running okay][:rendering]
[41:40][Introduce InitTextureQueue() in handmade_renderer.h][:rendering :threading]
[45:36][:Run the game okay, with scepticism on this texture initialisation code][:rendering :threading]
[47:13][Call OpenGLManageTextures() in win32_renderer_test.cpp][:rendering :threading]
[47:42][:Run the Renderer Test to see our textured cubes][:rendering]
[48:36][Select a tree and forest asset][:art :drawing]
[52:41][Change LoadBMP() to take a renderer_texture and load our forest tile into the test][:"asset loading" :rendering]
[55:15][:Run the test to see our textured ground][:"asset loading" :rendering]
[55:56][Load our tree sprite into the test and enable PushSimpleScene() to sprinkle them around the scene][:"asset loading" :rendering]
[57:41][Consider making PushBitmap() part of the renderer proper][:rendering :speech]
[59:10][Introduce PushBitmap() in handmade_renderer.cpp][:"asset loading" :rendering]
[59:41][Consider relieving PushBitmap() of the need to shrink bitmap borders in favour of making the software renderer upload textures into a bordered region][:"asset loading" :rendering :speech]
[1:03:21][Rename PushBitmap() to PushSprite() and clean it up][:"asset loading" :rendering]
[1:10:12][Try making PushSimpleScene() call PushSprite() for our trees][:"asset loading" :rendering]
[1:11:34][:Run the Renderer Test, see no trees and step into PushSprite() to see what it's computing][:"asset loading" :rendering]
[1:12:53][Prevent PushSimpleScene() from pushing cubes][:rendering]
[1:13:06][:Run it to see our trees][:rendering]
[1:13:12][Enable PushSimpleScene() to elevate sprites above the cubes][:rendering]
[1:14:08][:Run it to see our trees above the ground cubes][:rendering]
[1:14:37][Make PushSprite() centre the sprites on the cubes][:rendering]
[1:15:44][:Run it to see our centred trees][:rendering]
[1:15:55][Grow the trees in PushSimpleScene() and scatter them randomly][:rendering]
[1:16:23][:Run it to see our scattered trees][:rendering]
[1:16:50][Make the :camera pan rather than orbit]
[1:21:43][:Run it to see our panning :camera]
[1:22:31][Widen the scene and shrink the trees in PushSimpleScene()][:rendering]
[1:22:51][:Run it to see our scene, feeling like the trees aren't quite pegged to the centre][:rendering]
[1:24:02][Enable PushCube() to map our texture to the faces of the cube][:rendering]
[1:28:51][:Run it to see our textured cubes, and reconsider the sprite centring][:rendering]
[1:30:41][Enable PushSimpleScene() to push Krampus' head and walls][:rendering]
[1:34:15][Check out our scene][:rendering]
[1:34:33][Make PushSimpleScene() position Krampus unit forwards and apply the correct texture to the walls][:rendering]
[1:35:14][:Run it to see Z-fighting][:rendering]
[1:35:30][Make PushSimpleScene() elevate the walls above the ground by their radius][:rendering]
[1:35:59][:Run it to see trees intersecting wall geometry][:rendering]
[1:37:44][Make PushSprite() bias the Z of upright sprites by their entire vertical size][:rendering]
[1:37:56][:Run it to see how that looks][:rendering]
[1:38:15][Reduce the WallRadius in PushSimpleScene()][:rendering]
[1:38:52][:Run it to see the trees more correctly occluding the walls][:rendering]
[1:40:06][Make PushSprite() render the sprites without modifying their axes][:rendering]
[1:41:07][:Run it to see the trees standing perfectly upright, but looking like cardboard cutouts][:rendering]
[1:41:47][Enable PushSprite() to lerp between modified axes][:rendering]
[1:42:11][:Run it to see that it looks quite nice from this perspective][:rendering]
[1:43:40][Increase the :camera pitch and bias the lerp towards the correct axes][:rendering]
[1:45:48][Check out how that looks][:rendering :run]
[1:47:47][Play with the :camera focal length, pitch and position]
[1:52:13][:Run it to see everything stacking nicely][:rendering]
[1:53:20][Create win32_renderer_test.h and introduce test_scene struct, InitTestScene() and PlaceRandom()][:"procedural generation" :rendering]
[2:04:20][:Run it to see our well-spaced scene][:rendering]
[2:05:08][Fix PlaceRandom() to space elements out more][:rendering]
[2:05:23][:Run it to see our even better-spaced scene][:rendering]
[2:06:42][Q&A][:speech]
[2:06:52][@quote_corn_if_brother][Q: Are we going to do anything special on Day 500?]
[2:07:40][@vateferfout][Q: The right side of the walls seems to be flipped vertically, I guess it's because of the UV ordering][:rendering]
[2:07:53][@somebody_took_my_name][Q: Not a question, but I think you changed the meaning of the code in the EnqueueFree() function. The pending list is put back on the queue instead of on the free list (Queue->FirstFree)][:threading]
[2:08:10][Fix EnqueueFree() to set the Queue->FirstFree][:threading]
[2:09:39][Fix PushCube() to map our texture to the correct faces of the cube][:rendering]
[2:12:48][:Run it to see that our wall textures look good][:rendering]
[2:14:05][@vaualbus][Q: So I missed the stream today. What have we done with the texture generation today?]
[2:14:59][@filiadelski][Q: Are we done with the renderer or will we maintain both versions?]
[2:15:43][@jim0_o][Q: [~hero Handmade Hero] will be using this decoupled renderer, right?]
[2:16:11][@cirdanvalen][Q: Would it be helpful in this situation to use the old school billboards that are two or three sprites in a + or X shape?][:rendering]
[2:17:20][@filiadelski][Q: I assumed we weren't going to use the decoupled version, but that makes sense]
[2:18:47][Build the game in -O2]
[2:19:04][:Run the renderer test]
[2:19:24][@jim0_o][Q: Would it be too much to attach the :profiling stuff to just see the FPS etc?]
[2:19:36][Enable win32_renderer_test.cpp to print the milliseconds per frame][:profiling]
[2:24:20][:Run it to see our milliseconds per frame][:performance]
[2:24:55][Reduce the TEST_SCENE_DIM_Y]
[2:25:27][:Run it to see our still-variable frame rate][:performance]
[2:26:02][Increase the TEST_SCENE_DIM_Y]
[2:26:16][:Run it to see our just-as-variable frame rate][:performance]
[2:26:48][@neitchzehrer][Q: Did you update ~4coder yesterday (if necessary)?]
[2:26:52][Check our :rendering :performance][:run]
[2:28:13][@filiadelski][Q: Why do the frames drop so badly when moving the window? Does Windows spam the process with messages or something?][:performance :threading]
[2:30:04][Enable win32_renderer_test.cpp to create a thread for the :rendering separate from Windows' message processing][:threading]
[2:34:25][:Run it and reconsider our :rendering :performance]
[2:36:31][@nickito97][Q: What is volatile?][:language]
[2:39:21][@mmozeiko][Q: Now the main thread should use GetMessage(), not PeekMessage(), to save on CPU]
[2:39:41][Change win32_renderer_test.cpp to use GetMessage()[ref
    site=MSDN
    page="GetMessage function"
    url=https://msdn.microsoft.com/en-us/library/windows/desktop/ms644936(v=vs.85).aspx]]
[2:42:54][@pythno][Q: Could you go over the extra render thread thing briefly again, please? I thought the DC is thread-specific and so the OpenGL RC has to reside within the same thread][:threading]
[2:44:14][@mmozeiko][Q: GetMessage should be GetMessageA]
[2:44:40][Remove all the "A" function-name suffixes]
[2:46:47][@mmozeiko][Q: Without A or W you'll depend on "project settings" whether Unicode is set or not, and people had a lot of issues on forums, when they used [~hero Handmade Hero] code in Visual Studio projects]
[2:47:16][Embark on Windows Unicode string handling]
[2:51:26][@mmozeiko][Q: Try to #define UNICODE at top of file, to see if the compiler is happy]
[2:51:32][Try to #define UNICODE and continue down the Windows Unicode rat-hole[ref
    site="The Old New Thing"
    page="What(‘s) a character!"
    url=https://blogs.msdn.microsoft.com/oldnewthing/20070105-00/?p=28503][ref
    site=MSDN
    page="sprintf_s, _sprintf_s_l, swprintf_s, _swprintf_s_l"
    url=https://msdn.microsoft.com/en-us/library/ce3zzk1k.aspx]]
[3:00:25][][:rant :speech][quote 625]
[3:00:45][:Run it successfully]
[3:01:10][@mmozeiko][Q: I think you need to also #define _UNICODE 1]
[3:01:59][Reflect on the progress of our standalone renderer][:speech]
[3:03:13][Make our :camera orbit the world]
[3:04:39][:Run it to see our 2D sprites rotating erroneously][:camera]
[3:06:34][Wind it down][:speech]
[/video]
