[video output=day359 member=cmuratori stream_platform=twitch stream_username=handmade_hero project=code title="OpenGL Projection Matrices Revisited" vod_platform=youtube id=ykOBtVPjzq4 annotator=Miblo]
[0:03][Recap and set the stage for the day]
[4:25][A few words on what "stepping through GPU code" entails]
[8:59][Run the game to see our 2D pipeline running, and determine to remove the screen-space transform]
[10:13][handmade_render_group.cpp: Look at how GetRenderEntityBasisP() transforms the world coordinates into screen coordinates]
[12:50][handmade_opengl.cpp: Look at how OpenGLSetScreenSpace() works and fits into the pipeline]
[13:46]["We're going to go over that in very excruciating detail in a moment"[ref
    site=docs.gl
    page="glLoadMatrix"
    url=http://docs.gl/gl2/glLoadMatrix]][quote 542]
[16:12][Blackboard: Projection Matrix]
[19:43][On "column major" vs "row major", and defining an array in C or C++]
[22:49][Blackboard: What our projection matrix is doing]
[24:28][Blackboard: Homogeneous matrix]
[25:56][Blackboard: Matrix multiply]
[30:04][Blackboard: |xyz1| == point; |xyz0| == vector]
[34:12][Blackboard: More on what our "projection" matrix is doing]
[37:55][Blackboard: Why OpenGL operates in a -1 to 1 space]
[39:01][Blackboard: Clipping]
[42:20][Illustrate "texture warping"[ref
    site="YouTube"
    page="texture warping in PSX emulation"
    url="https://www.youtube.com/watch?v=Bz2ZEBRjm4w"]]
[43:03][Blackboard: On the necessity for correct sub-pixel fill and texture coordinate picking]
[46:25][Blackboard: How OpenGL handles its coordinates system: bilateral unit cube]
[48:49]["As is the rule on Handmade Hero: I never get to do any preparation"][quote 543]
[50:15][Blackboard: Transforming from "clip space" to "window space"[ref
    site="docs.gl"
    page="glViewPort"
    url="http://docs.gl/gl2/glViewport"]]
[53:56][Consult the OpenGL 2.0 specification[ref
    site="OpenGL"
    page="The OpenGL Graphics System: A Specification"
    url="https://www.opengl.org/registry/doc/glspec20.20041022.pdf"]]
[55:23][Blackboard: Fix up the terminology in accordance with the OpenGL spec]
[58:01][Blackboard: Perspective projection]
[1:00:32][Blackboard: Projecting to the screen using a relationship of similar triangles]
[1:02:37][Blackboard: Matrix multiplication doesn't allow for dividing]
[1:05:14][Blackboard: How OpenGL provides for one divide operation, normalisation of the vector by its w coordinate, in order to compute correct perspective]
[1:08:00][Blackboard: Implementing our own perspective projection and why we compute z]
[1:10:11][Double-check the OpenGL spec on coordinate transformations[ref
    site="OpenGL"
    page="The OpenGL Graphics System: A Specification"
    url="https://www.opengl.org/registry/doc/glspec20.20041022.pdf"]]
[1:13:03][Blackboard: Performing the near plane clipping before moving into the -1 to 1 space]
[1:16:33][Blackboard: Recap what our perspective transform must accomplish]
[1:19:30][Blackboard: The Z-buffer and near and far clip planes]
[1:21:56][Further reading: W-buffer; infinite far clip plane; disable far clip plane]
[1:23:46][Blackboard: Camera space, and getting the effects we want out of the projection matrix]
[1:26:47][handmade_render_group.cpp: Consider how our perspective transform is currently happening]
[1:30:04][handmade_opengl.cpp: Temporarily make OpenGLSetScreenSpace() calculate the height dimension based on the width and run the game to see what that does]
[1:31:14][handmade_render_group.cpp: Prevent GetRenderEntityBasisP() from adding CameraTransform->ScreenCenter to the Perspective computation, and run the game to see what that has done]
[1:32:23][handmade_opengl.cpp: Shuffle the projection matrix initialised in OpenGLSetScreenspace(), and run the game to see that our transform is correct, but the sorting is not]
[1:33:52][handmade_render_group.cpp: Consider what the MetersToPixels value is contributing to GetRenderEntityBasisP()]
[1:36:47][Blackboard: How MetersToPixels passes through the pipeline]
[1:41:20][handmade_render.h: Consider how to simplify MetersToPixels]
[1:42:14][handmade_opengl.cpp: Make OpenGLSetScreenspace() compute the Width and Height more simply]
[1:43:34][handmade_render.h: Prevent GetStandardCameraParams() from taking WidthInPixels into account in the MetersToPixels computation, and run the game]
[1:44:29][handmade_render.h: Remove WidthOfMonitor from the camera_params struct and rename MetersToPixels to WorldScale]
[1:47:11][handmade_render_group.cpp: Consider simplifying the ProjectedXY computation]
[1:48:45][handmade_render_group.h: Remove the render_entry_coordinate_system struct]
[1:49:50][handmade_render_group.h: Make the entity_basis_p_result struct contain a 3D coordinate, and propagate that change]
[1:56:21][Run the game with everything being passed down as 3D, and consider how we'll proceed]
[1:57:51][Q&A][:speech]
[1:58:27][@rivten][Concerning the "homogeneous" use. The "homogeneous" word indeed comes from mathematics. Homogeneous is used for mathematical objects that have some scalability property. Here, p0 = (x, y, z, 1) and p1 = (2x, 2y, 2z, 2) represent the same point in space (but p1 = 2 * p0 mathematically speaking). Therefore the usage of homogeneous coordinates and homogeneous matrices here]
[2:00:03][@vaualbus][Turn off the sorting so we won't have flashing]
[2:01:58][handmade_render.cpp: Temporarily make SortEntries() set ShouldSort to false and run the game to see how that affects it]
[2:03:20][@kim_jorgensen][Debug UI is broken?]
[2:05:25][@elxenoaizd][I was reading the article from Fabian about his optimizations on the Intel software renderer and I saw him doing the clipping in a very simple manner in screenspace, where he takes the min / max between the pixel and screen dimensions because he was using orient2d and barycentric coordinates to rasterize. The clipping was only four lines of code and easy to understand. Why does OpenGL have to do complicated homogeneous clipping?[ref
    site="The ryg blog"
    page="Triangle rasterization in practice"
    url="https://fgiesen.wordpress.com/2013/02/08/triangle-rasterization-in-practice/"]]
[2:07:58][@rivten][In practice, does the camera near plane and the camera focal length really differ? I would expect them to be the same]
[2:10:37][@elxenoaizd][Are we going to continue supporting the software renderer in 3D as well?]
[2:11:07][@elxenoaizd][If I set the near clip plane to, say, 10, does that mean that entities with a world space Z less than 10 would be clipped? Just trying to make sure that near / far clip planes are defined in terms of world space]
[2:13:35][@elxenoaizd][Can you use the GPU to bypass the OpenGL or DirectX API / pipeline and just use compute shaders to implement your own pipeline that's also running on the GPU?]
[2:16:51][@rivten][So, to avoid Z fighting, should we have dynamical near / far planes? I mean that their values should change according to the nearest and the farthest objects we want to render in order for the near / far plane space to be as small as possible?[ref
    site="MSDN"
    page="Cascaded Shadow Maps"
    url="https://msdn.microsoft.com/en-us/library/windows/desktop/ee416307.aspx"]]
[2:22:50][@elxenoaizd][Does any of that clip and projection math change if we change the rendering technique that we're using? Say, rasterizing vs raytracing or voxels]
[2:26:40][Close out][:speech]
[/video]
