OpenGL Projection Matrices Revisited

?

?# Keyboard Navigation

## Global Keys

[, < / ], > Jump to previous / next episode

W, K, P / S, J, N Jump to previous / next timestamp

t / T Toggle theatre / SUPERtheatre mode

V Revert filter to original state Y Select link (requires manual Ctrl-c)## Menu toggling

q Quotes
r References
f Filter
y Link
c Credits
## In-Menu and Index Controls

## Quotes and References Menus and Index

Enter Jump to timestamp

## Quotes, References and Credits Menus

o Open URL (in new tab)
## Filter Menu

x, Space Toggle category and focus next

X, ShiftSpace Toggle category and focus previous

v Invert topics / media as per focus## Filter and Link Menus

z Toggle filter / linking mode
## Credits Menu

Enter Open URL (in new tab)

W, K, P / S, J, N Jump to previous / next timestamp

t / T Toggle theatre / SUPERtheatre mode

V Revert filter to original state Y Select link (requires manual Ctrl-c)

a

w

s

s

d

h
j
k
l

←

↑

↓

↓

→

Esc Close menu / unfocus timestamp

X, ShiftSpace Toggle category and focus previous

v Invert topics / media as per focus

⏫

Previous: 'Introduction to Depth Buffers'

⏫

0:03Recap and set the stage for the day

0:03Recap and set the stage for the day

0:03Recap and set the stage for the day

4:25A few words on what "stepping through GPU code" entails

4:25A few words on what "stepping through GPU code" entails

4:25A few words on what "stepping through GPU code" entails

8:59Run the game to see our 2D pipeline running, and determine to remove the screen-space transform

8:59Run the game to see our 2D pipeline running, and determine to remove the screen-space transform

8:59Run the game to see our 2D pipeline running, and determine to remove the screen-space transform

10:13handmade_render_group.cpp: Look at how GetRenderEntityBasisP() transforms the world coordinates into screen coordinates

10:13handmade_render_group.cpp: Look at how GetRenderEntityBasisP() transforms the world coordinates into screen coordinates

12:50handmade_opengl.cpp: Look at how OpenGLSetScreenSpace() works and fits into the pipeline

12:50handmade_opengl.cpp: Look at how OpenGLSetScreenSpace() works and fits into the pipeline

12:50handmade_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"^{1}^{α}

13:46"We're going to go over that in very excruciating detail in a moment"^{1}^{α}

13:46"We're going to go over that in very excruciating detail in a moment"^{1}^{α}

16:12Blackboard: Projection Matrix

16:12Blackboard: Projection Matrix

16:12Blackboard: Projection Matrix

19:43On "column major" vs "row major", and defining an array in C or C++

19:43On "column major" vs "row major", and defining an array in C or C++

19:43On "column major" vs "row major", and defining an array in C or C++

22:49Blackboard: What our projection matrix is doing

22:49Blackboard: What our projection matrix is doing

22:49Blackboard: What our projection matrix is doing

24:28Blackboard: Homogeneous matrix

24:28Blackboard: Homogeneous matrix

24:28Blackboard: Homogeneous matrix

25:56Blackboard: Matrix multiply

25:56Blackboard: Matrix multiply

25:56Blackboard: Matrix multiply

30:04Blackboard: |xyz1| == point; |xyz0| == vector

30:04Blackboard: |xyz1| == point; |xyz0| == vector

30:04Blackboard: |xyz1| == point; |xyz0| == vector

34:12Blackboard: More on what our "projection" matrix is doing

34:12Blackboard: More on what our "projection" matrix is doing

34:12Blackboard: More on what our "projection" matrix is doing

37:55Blackboard: Why OpenGL operates in a -1 to 1 space

37:55Blackboard: Why OpenGL operates in a -1 to 1 space

37:55Blackboard: Why OpenGL operates in a -1 to 1 space

39:01Blackboard: Clipping

39:01Blackboard: Clipping

39:01Blackboard: Clipping

42:20Illustrate "texture warping"^{2}

42:20Illustrate "texture warping"^{2}

42:20Illustrate "texture warping"^{2}

43:03Blackboard: On the necessity for correct sub-pixel fill and texture coordinate picking

43:03Blackboard: On the necessity for correct sub-pixel fill and texture coordinate picking

43:03Blackboard: On the necessity for correct sub-pixel fill and texture coordinate picking

46:25Blackboard: How OpenGL handles its coordinates system: bilateral unit cube

46:25Blackboard: How OpenGL handles its coordinates system: bilateral unit cube

46:25Blackboard: 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"^{β}

48:49"As is the rule on Handmade Hero: I never get to do any preparation"^{β}

48:49"As is the rule on Handmade Hero: I never get to do any preparation"^{β}

50:15Blackboard: Transforming from "clip space" to "window space"^{3}

50:15Blackboard: Transforming from "clip space" to "window space"^{3}

50:15Blackboard: Transforming from "clip space" to "window space"^{3}

53:56Consult the OpenGL 2.0 specification^{4}

53:56Consult the OpenGL 2.0 specification^{4}

53:56Consult the OpenGL 2.0 specification^{4}

55:23Blackboard: Fix up the terminology in accordance with the OpenGL spec

55:23Blackboard: Fix up the terminology in accordance with the OpenGL spec

55:23Blackboard: Fix up the terminology in accordance with the OpenGL spec

58:01Blackboard: Perspective projection

58:01Blackboard: Perspective projection

58:01Blackboard: Perspective projection

1:00:32Blackboard: Projecting to the screen using a relationship of similar triangles

1:00:32Blackboard: Projecting to the screen using a relationship of similar triangles

1:00:32Blackboard: Projecting to the screen using a relationship of similar triangles

1:02:37Blackboard: Matrix multiplication doesn't allow for dividing

1:02:37Blackboard: Matrix multiplication doesn't allow for dividing

1:02:37Blackboard: Matrix multiplication doesn't allow for dividing

1:05:14Blackboard: How OpenGL provides for one divide operation, normalisation of the vector by its w coordinate, in order to compute correct perspective

1:05:14Blackboard: How OpenGL provides for one divide operation, normalisation of the vector by its w coordinate, in order to compute correct perspective

1:08:00Blackboard: Implementing our own perspective projection and why we compute z

1:08:00Blackboard: Implementing our own perspective projection and why we compute z

1:08:00Blackboard: Implementing our own perspective projection and why we compute z

1:10:11Double-check the OpenGL spec on coordinate transformations^{5}

1:10:11Double-check the OpenGL spec on coordinate transformations^{5}

1:10:11Double-check the OpenGL spec on coordinate transformations^{5}

1:13:03Blackboard: Performing the near plane clipping before moving into the -1 to 1 space

1:13:03Blackboard: Performing the near plane clipping before moving into the -1 to 1 space

1:13:03Blackboard: Performing the near plane clipping before moving into the -1 to 1 space

1:16:33Blackboard: Recap what our perspective transform must accomplish

1:16:33Blackboard: Recap what our perspective transform must accomplish

1:16:33Blackboard: Recap what our perspective transform must accomplish

1:19:30Blackboard: The Z-buffer and near and far clip planes

1:19:30Blackboard: The Z-buffer and near and far clip planes

1:19:30Blackboard: The Z-buffer and near and far clip planes

1:21:56Further reading: W-buffer; infinite far clip plane; disable far clip plane

1:21:56Further reading: W-buffer; infinite far clip plane; disable far clip plane

1:21:56Further reading: W-buffer; infinite far clip plane; disable far clip plane

1:23:46Blackboard: Camera space, and getting the effects we want out of the projection matrix

1:23:46Blackboard: Camera space, and getting the effects we want out of the projection matrix

1:23:46Blackboard: Camera space, and getting the effects we want out of the projection matrix

1:26:47handmade_render_group.cpp: Consider how our perspective transform is currently happening

1:26:47handmade_render_group.cpp: Consider how our perspective transform is currently happening

1:26:47handmade_render_group.cpp: Consider how our perspective transform is currently happening

1:30:04handmade_opengl.cpp: Temporarily make OpenGLSetScreenSpace() calculate the height dimension based on the width and run the game to see what that does

1:30:04handmade_opengl.cpp: Temporarily make OpenGLSetScreenSpace() calculate the height dimension based on the width and run the game to see what that does

1:31:14handmade_render_group.cpp: Prevent GetRenderEntityBasisP() from adding CameraTransform->ScreenCenter to the Perspective computation, and run the game to see what that has done

1:31:14handmade_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:23handmade_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:32:23handmade_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:52handmade_render_group.cpp: Consider what the MetersToPixels value is contributing to GetRenderEntityBasisP()

1:33:52handmade_render_group.cpp: Consider what the MetersToPixels value is contributing to GetRenderEntityBasisP()

1:36:47Blackboard: How MetersToPixels passes through the pipeline

1:36:47Blackboard: How MetersToPixels passes through the pipeline

1:36:47Blackboard: How MetersToPixels passes through the pipeline

1:41:20handmade_render.h: Consider how to simplify MetersToPixels

1:41:20handmade_render.h: Consider how to simplify MetersToPixels

1:41:20handmade_render.h: Consider how to simplify MetersToPixels

1:42:14handmade_opengl.cpp: Make OpenGLSetScreenspace() compute the Width and Height more simply

1:42:14handmade_opengl.cpp: Make OpenGLSetScreenspace() compute the Width and Height more simply

1:42:14handmade_opengl.cpp: Make OpenGLSetScreenspace() compute the Width and Height more simply

1:43:34handmade_render.h: Prevent GetStandardCameraParams() from taking WidthInPixels into account in the MetersToPixels computation, and run the game

1:43:34handmade_render.h: Prevent GetStandardCameraParams() from taking WidthInPixels into account in the MetersToPixels computation, and run the game

1:44:29handmade_render.h: Remove WidthOfMonitor from the camera_params struct and rename MetersToPixels to WorldScale

1:44:29handmade_render.h: Remove WidthOfMonitor from the camera_params struct and rename MetersToPixels to WorldScale

1:47:11handmade_render_group.cpp: Consider simplifying the ProjectedXY computation

1:47:11handmade_render_group.cpp: Consider simplifying the ProjectedXY computation

1:47:11handmade_render_group.cpp: Consider simplifying the ProjectedXY computation

1:48:45handmade_render_group.h: Remove the render_entry_coordinate_system struct

1:48:45handmade_render_group.h: Remove the render_entry_coordinate_system struct

1:48:45handmade_render_group.h: Remove the render_entry_coordinate_system struct

1:49:50handmade_render_group.h: Make the entity_basis_p_result struct contain a 3D coordinate, and propagate that change

1:49:50handmade_render_group.h: Make the entity_basis_p_result struct contain a 3D coordinate, and propagate that change

1:56:21Run the game with everything being passed down as 3D, and consider how we'll proceed

1:56:21Run the game with everything being passed down as 3D, and consider how we'll proceed

1:56:21Run the game with everything being passed down as 3D, and consider how we'll proceed

1:57:51Q&A

🗩

1:57:51Q&A

🗩

1:57:51Q&A

🗩

2:01:58handmade_render.cpp: Temporarily make SortEntries() set ShouldSort to false and run the game to see how that affects it

2:01:58handmade_render.cpp: Temporarily make SortEntries() set ShouldSort to false and run the game to see how that affects it

2:26:40Close out

🗩

2:26:40Close out

🗩

2:26:40Close out

🗩

⏬

Next: 'Moving the Perspective Divide to OpenGL'

⏬