[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]