[video output=day373 member=cmuratori stream_platform=twitch stream_username=handmade_hero project=code title="Inverting the Full 3D Transform" vod_platform=youtube id=rMMFFDbh2XU annotator=Miblo]
[0:09][Recap and set the stage for the day]
[3:05]["This will be a stream filled with mucus"][quote 562]
[4:14][handmade_debug.cpp: Consider how to enable DEBUGStart() to correctly place the debug text]
[6:53][handmade_math.h: Make OrthographicProjection() set the near clip plane to be behind the camera]
[9:12][Run the game to see that it's drawing okay, but that we cannot perform a debug click]
[10:56][handmade_debug.cpp: Temporarily make DEBUGStart() shrink the debug text]
[11:38][Determine to get Unproject() working again]
[13:22][Run the game to see those pixel coordinates]
[14:00][handmade_render_group.cpp: Look at how Unproject() currently works]
[15:08][Blackboard: The Projection, Clip-space, Screen-space pipeline]
[19:53][handmade_render_group.cpp: Prevent Unproject() from baking in the aspect ratio]
[21:47][Blackboard: Inverting a matrix]
[25:44][Blackboard: Producing the inverse of our projection matrix]
[30:35][Blackboard: Check our working]
[35:32][Blackboard: Producing the bottom row of the identity projection matrix]
[44:46][Blackboard: Plug in those terms and see if that checks out]
[46:51][handmade_render_group.cpp: Note that our projection matrix is slightly different]
[47:33][Blackboard: Computing the inverse projection matrix for our actual matrix]
[49:38][handmade_math.h: Introduce m4x4_inv struct and augment PerspectiveProjection() to produce both the Forward and Inverse matrices]
[53:56][Step in to PerspectiveProjection() and inspect the resulting matrix]
[55:35][Blackboard: Producing the identity orthographic projection matrix]
[1:01:05][handmade_math.h: Augment OrthographicProjection() to produce both the Forward and Inverse matrices]
[1:02:15][Step in to OrthographicProjection() and inspect the resulting matrix]
[1:03:01][handmade_render_group.cpp: Set up SetCameraTransform() to compute both the Forward and Inverse matrices]
[1:04:42][handmade_math.h: Determine to augment CameraTransform() to produce both the Forward and Inverse matrices]
[1:05:34][Blackboard: Beginning to produce the identity camera matrix]
[1:06:24][Blackboard: Isolating pieces of the matrix]
[1:10:13][Blackboard: Producing the identity camera matrix]
[1:12:45][Blackboard: Handling different length, yet still orthogonal axes]
[1:14:44][handmade_math.h: Augment CameraTransform() to produce both the Forward and Inverse matrices]
[1:16:41][Blackboard: Getting the inverse of a vector's own length]
[1:17:22][handmade_math.h: Continue to augment CameraTransform()]
[1:18:08][handmade_math.h: Introduce an operator/() that operates on vectors]
[1:19:41][Blackboard: Producing our rightmost and bottom vectors for the identity camera matrix]
[1:22:31][handmade_math.h: Enable CameraTransform() to compute our inverse components]
[1:25:50][Step in to CameraTransform() and inspect the resulting matrix]
[1:26:55][handmade_math.h: Fix typos in CameraTransform()]
[1:27:12][Step back in to CameraTransform() and inspect the resulting matrix]
[1:28:39][Blackboard: Producing our inverse components]
[1:31:47][Blackboard: Set up the matrixes in the correct orientation]
[1:33:04][handmade_math.h: Make CameraTransform() correctly compute the iP]
[1:34:18][Step in to CameraTransform() to see that we're now rock solid]
[1:35:03][handmade_render_group.cpp: Enable SetCameraTransform() to compute both matrices, and PushSetup() to take a m4x4_inv]
[1:37:03][Run the game and note that we can always access the inverse of our projection]
[1:37:23][handmade_render_group.cpp: Determine to enable Unproject() to perform the reverse transform on the z]
[1:38:41][Blackboard: Unprojecting the z]
[1:39:50][handmade_render_group.cpp: Enable Unproject() to perform the reverse transform on the z]
[1:43:06][Consider restoring the mouse picking of entities]
[1:45:15][handmade_render_group.cpp: Make Unproject() take a WorldDistanceZ]
[1:47:28][handmade_math.h: Extend Transform() to take a v4]
[1:48:20][handmade_render_group.cpp: Make Unproject() compute the ClipZ from ProbeZ]
[1:49:20][handmade_math.h: Introduce an operator*() that takes a v4]
[1:49:40][handmade_render_group.cpp: Make GetCameraRectangleAtDistance() use WorldDistanceFromCameraZ directly]
[1:50:50][Run the game to see how it currently works]
[1:51:39][handmade_render_group.cpp: Enable SetCameraTransform() to check the inverse of the composite]
[1:52:20][Step in to SetCameraTransform() and inspect that identity composite matrix]
[1:54:02][Step in to Unproject() and inspect the Clip coordinates]
[1:55:30][handmade_debug.cpp: Make DEBUGEnd() set the MouseX to 0 and MouseY to 1079]
[1:56:03][Step in to Unproject() to see that the Clip coordinates are now wrong]
[1:56:57][handmade_render_group.cpp: Make Unproject() correctly compute the ClipSpaceX and ClipSpaceY]
[1:58:06][Blackboard: Dividing by half of the width]
[1:59:06][Step through Unproject() and inspect the values]
[2:01:11][Run the game to find that debug clicking works correctly again]
[2:02:14][todo.txt: Update the TODO list]
[2:03:21][Q&A][:speech]
[2:04:10][@Miblo][Am I right in thinking that today's work has had the cool, and not immediately expected, side effect of beginning to level up the debug camera, in terms of mouse picking of entities? Or did the debug camera have that before anyway?]
[2:04:52][Blackboard: 3D Picking of Entities]
[2:05:46][@kim_jorgensen][Do you plan to keep the Assert in OpenGLDebugCallback? My driver is sending a lot of debug information that fires the assert]
[2:05:54][handmade_opengl.cpp: Disable the OpenGLDebugCallback error message]
[2:08:18][@lucid_frost][Why do you think it is not popular to do x-forward coordinate systems? Jon Blow was talking about it yesterday and it seems like a good idea, at least in terms of rotations]
[2:09:05][@macielda][Why use Square(Length(..))? How does it compare to LengthSq(..)?]
[2:09:21][handmade_math.h: Make CameraTransform() use LengthSq() directly]
[2:10:47][@unknown_20][Will you consider a faster matrix multiplication algorithm other than inner product?]
[2:11:33][@jeffgmelton][Is there a roadmap for what you will be working on over the coming months?]
[2:11:50][@macielda][The ProbeZ thing went a bit too quick for me. I didn't fully understand the role of WorldDistanceFromCameraZ and how you are going to generate it. Are you going to talk more about that next time?]
[2:12:04][Blackboard: The 3D Picking Procedure]
[2:13:56][@pragmascrypt][Since you are only doing quads, wouldn't it be possible to upload a constant index buffer once with the max number of vertices and then never touch it again?]
[2:14:59][@unknown_20][Is it possible that Square Length can result in a zero and blow up?]
[2:15:39][@kim_jorgensen][I get OpenGL messages with severity DEBUG_SEVERITY_NOTIFICATION and DEBUG_SEVERITY_MEDIUM]
[2:15:59][@ratchetfreak][Even a simple pass-through geometry shader is a decent perf hit]
[2:16:15][@rooctag][Sorry, didn't see the whole stream, but why no 60fps with the move to core GL?]
[2:16:31][build.bat: Temporarily switch to -O2 and disable the debug system]
[2:18:45][Run the game in the belief that this is 60fps]
[2:20:01][@kim_jorgensen][e.g. MEDIUM: "Recompiling fragment shader for program 3"]
[2:20:24][handmade_opengl.cpp: Pull in the severities from corearb.h and only make the OpenGLDebugCallback occur on GL_DEBUG_SEVERITY_HIGH[ref
    site="Khronos"
    page="glcorearb.h"
    url="https://www.khronos.org/registry/OpenGL/api/GL/glcorearb.h"]]
[2:21:32][Run the game to see that it still works]
[2:21:40][We are about done for today][:speech]
[/video]
