[video output=day422 member=cmuratori stream_platform=twitch stream_username=handmade_hero project=code title="Raycasting AABBs Directly" vod_platform=youtube id=c4Q-6aMUh-k annotator=Miblo]
[0:01][Recap and set the stage for the day][:speech]
[0:53][:Run the game with the determination to raycast :lighting boxes directly][:rendering]
[3:07][Move the Surface computations from LightingTest() into RayCast()][:lighting :rendering]
[6:30][Replace HitSurface in AccumulateSample() and RayCast() with a lighting_box][:lighting :rendering]
[16:10][:Run the game to see our slow :lighting solution, and determine to investigate the slowness][:rendering]
[18:01][Add a TIMED_FUNCTION in RayCast()][:"debug system"]
[18:22][:Run the game and consult the profiler to see that RayCast() is our most costly function][:lighting :performance :rendering]
[19:48][Check the day[ref
    site="Handmade Hero"
    page="Annotated Episode Guide"
    url=https://hero.handmade.network/episode/code][ref
        site=YouTube
        page="Handmade Hero"
        url=https://www.youtube.com/user/handmadeheroarchive/videos]][:admin]
[20:30][Raycasting Against AABB][:blackboard :geometry :lighting :optimisation :rendering]
[24:14][Relieve RayCast() of testing RaySourceN for every surface][:lighting :optimisation :rendering]
[29:17][:Run the game to see that we halved the cost of RayCast()][:lighting :optimisation :rendering]
[29:56][Relieve RayCast() of using redundant data][:lighting :optimisation :rendering]
[32:26][:Run the game to see that that didn't speed it up][:lighting :optimisation :rendering]
[32:34][Make RayCast() perform inline the functionality of GetBoxSurface()][:lighting :optimisation :rendering]
[34:25][:Run the game to see that that halved the cost of RayCast()][:lighting :optimisation :rendering]
[35:00][Relieve RayCast() of performing redundant work originally necessitated by GetBoxSurface()][:lighting :optimisation :rendering]
[38:52][:Run the game to see that the :lighting is busted][:optimisation :rendering][quote 609]
[39:22][Reenable RayCast() to actually compute all the :lighting][:optimisation :rendering]
[42:05][:Run the game to see that our :lighting is back][:optimisation :rendering]
[42:38][Optimise the Normal value out of RayCast() and introduce a Sign value][:lighting :optimisation :rendering]
[50:30][:Run the game to see that we're a little faster][:lighting :optimisation :rendering]
[50:34][Optimise the SignX value out of RayCast()][:lighting :optimisation :rendering]
[53:22][Optimise the HalfWidth and HalfHeight values out of RayCast()][:lighting :optimisation :rendering]
[54:21][Optimise the Width and Height inner product computations out of RayCast()][:lighting :optimisation :rendering]
[58:39][:Run the game to see that we are down below 60ms][:lighting :optimisation :rendering]
[58:55][Change RelOrigin to be relative to the MinCorner in RayCast()][:lighting :optimisation :rendering]
[1:03:16][:Run the game to see that the :lighting is different and investigate why][:optimisation :rendering]
[1:04:39][Revert that RelOrigin change][:lighting :optimisation :rendering]
[1:05:11][Determining the ray intersection point more efficiently][:blackboard :geometry :lighting :rendering]
[1:06:53][Try again to make RayCast() use the HalfWidth and HalfHeight instead of Width and Height][:lighting :optimisation :rendering]
[1:07:25][:Run the game to see that the :lighting is wrong again][:optimisation :rendering]
[1:08:09][Make RayCast() correctly compute the Width and Height][:lighting :optimisation :rendering]
[1:08:40][:Run the game to see that the :lighting remains correct][:optimisation :rendering]
[1:08:43][Consider storing the Span and P in the Box][:lighting :optimisation :rendering :speech]
[1:09:17][:Run the game to see that we are at ~52ms][:lighting :optimisation :rendering]
[1:09:37][Toggle off the snake in PlayWorld()][:"entity system"]
[1:09:54][:Run the game to see that we are at ~26ms][:lighting :optimisation :rendering]
[1:10:07][Relieve RayCast() of doing an extra comparison of XCheck and YCheck with Width and Height respectively][:lighting :optimisation :rendering]
[1:10:30][:Run the game to see that we are about the same][:lighting :optimisation :rendering]
[1:10:46][Add P and Radius to lighting_box for RayCast(), GetBoxSurface() and PushCube() to use][:lighting :optimisation :rendering]
[1:21:54][:Run the game to see black :lighting][:optimisation :rendering]
[1:23:16][Step in to GetBoxSurface() and inspect its values][:lighting :optimisation :rendering :run]
[1:25:34][Make PushCube() correctly set the P and Radius][:lighting :optimisation :rendering]
[1:26:24][:Run the game to see that the :lighting is better][:lighting :optimisation :rendering]
[1:27:13][Toggle back on the snake in PlayWorld()][:"entity system"]
[1:27:24][:Run the game to see that we're at ~47ms][:lighting :optimisation :rendering]
[1:28:43][Toggle off the TIMED_FUNCTION in RayCast()][:"debug system"]
[1:28:52][:Run the game to see that we are below 40ms][:lighting :optimisation :rendering]
[1:29:14][Try to unroll the Axis loop in RayCast()][:lighting :optimisation :rendering]
[1:33:08][:Run the game to see that we are below 30ms][:lighting :optimisation :rendering]
[1:33:50][Further compress the Axis "cases" in RayCast()][:lighting :optimisation :rendering]
[1:37:28][:Run the game to see that we remain below 30ms][:lighting :optimisation :rendering]
[1:37:38][Relieve RayCast() of multiplying the Sign in to RaySourceN and d][:lighting :optimisation :rendering]
[1:38:53][:Run the game to see that we remain below 30ms][:lighting :optimisation :rendering]
[1:39:21][Consider removing the Sign computation from RayCast()][:lighting :optimisation :rendering :speech]
[1:41:13][Switch back to the looped version of RayCast() and relive that of multiplying the Sign in to the RaySourceN and d][:lighting :optimisation :rendering]
[1:42:04][:Run the game]
[1:42:16][Q&A][:speech]
[1:43:32][@gprincip][Q: Is the :lighting done after this?][:rendering]
[1:43:48][@Miblo][Q: You may now sort the episode guide entries from "new to old"[ref
    site="Handmade Hero"
    page="Annotated Episode Guide"
    url=https://hero.handmade.network/episode/code]]
[1:44:12][@stuckpanda][Q: Which headers do you include for working with OpenGL?][:hardware]
[1:44:31][@0lpbm][Q: How long until you'll move all of this to the GPU?][:hardware]
[1:46:12][@praet_a51][Q: Why did inlining GetBoxSurface() in RayCast() result in such an improvement?][:optimisation]
[1:47:54][@frostyninja][Q: Will the :lighting boxes remain sort of separate from the rest of the render commands flow?][:rendering]
[1:48:09][@praet_a51][Q: Great stream by the way and the :lighting looks great][:rendering]
[1:48:43][@filiadelski][Q: In my engine I have 3D models that contain a buffer of uint8 which is cast to a struct which contains OpenGL handles for the model. My instinct is to hide the OpenGL stuff from the game engine itself - is this a good idea or should I just give in to the OpenGL overlords and put #include <GL/gl.h> in my game code? Maybe I'm just being dogmatic][:hardware]
[1:50:14][@skyvaultgames][Q: When the Jai programming :language stabilizes, will you be considering using it for future handmade projects?]
[1:50:52][@stuckpanda][Q: Is there an episode that explains some generalities about what OpenGL shaders are?[ref
    site="Handmade Hero"
    page="Compiling and Linking Shaders in OpenGL"
    url=https://hero.handmade.network/episode/code/day368/][ref
        site="Handmade Hero"
        page="Introduction to Vertex and Fragment Shaders"
        url=https://hero.handmade.network/episode/code/day369/]][:hardware]
[1:51:54][Wrap it up][:speech]
[/video]
