Heuristic42
Blog
Opengl
Meta
Rendering
1
comment
Nov 24 at 1:24
Matrices
the macbook i bought from your amazon store is not working.. th…
–
anonymous
edited
Sep 17 at 23:20
Writing custom C++ containers, iterators and value references
Generic containers are awesome. 1. The effort required to wr…
–
pknowles
created
Sep 17 at 23:16
Writing custom C++ containers, iterators and value references
Generic containers are awesome. 1. The effort required to wr…
–
pknowles
comment
Sep 15 at 19:08
DerBard: Custom Split Mechanical Keyboard Prototype
Hey. Thanks for your interest! I've uploaded the files here, bu…
–
pknowles
comment
Sep 13 at 15:06
DerBard: Custom Split Mechanical Keyboard Prototype
Hi! Is it possible to get some models so I can also make it?
–
anonymous
edited
Aug 14 at 17:55
On docker stealing routes and breaking the internet
Boy this is frustrating. The internet just doesn't work with do…
–
pknowles
edited
Aug 14 at 16:55
On docker stealing routes and breaking the internet
Boy this is frustrating. The internet just doesn't work with do…
–
pknowles
created
Aug 14 at 16:52
On docker stealing routes and breaking the internet
Boy this is frustrating. The internet just doesn't work with do…
–
pknowles
comment
Jul 13 at 6:48
Matrices
[deleted]
–
anonymous
comment
Jul 6 at 0:39
Matrices
[deleted]
–
anonymous
edited
Jun 19 at 20:22
DerBard: Custom Split Mechanical Keyboard Prototype
![DerBard Cover Image][1] In my last post I presented my que…
–
pknowles
comment
Jun 2 at 11:49
Matrices
[deleted]
–
anonymous
comment
Jun 2 at 10:31
Matrices
[deleted]
–
anonymous
created
May 30 at 5:22
Calling Babel from Django for React+JSX
Sharing my frustrations so you can enjoy them too... :) As o…
–
pknowles
edited
May 22 at 18:57
Microsoft Natural Ergonomic 4000 Replacement
![my old natural 4k][1] **They stopped making it!** I'm actu…
–
pknowles
comment
May 22 at 16:00
Prime Mover - Processor (final problem) [Spoilers!]
this should be fixed now
–
pknowles
edited
May 18 at 22:15
Clip Space
Clip space is a linearly dependent vector space between eye spa…
–
pknowles
created
May 18 at 21:56
Clip Space
Clip space is a linearly dependent vector space between eye spa…
–
pknowles
edited
May 18 at 19:50
Vector Spaces
A number of vector spaces are discussed below and widely used i…
–
pknowles
edited
May 18 at 19:43
Projection Matrix
A projection is fundamental to [cameras](/8/rendering/cameras/)…
–
pknowles
edited
May 18 at 18:32
Matrices
Matrices are 2D arrays of numbers, grouped as such to enable hi…
–
pknowles
edited
May 14 at 21:47
DerBard: Custom Split Mechanical Keyboard Prototype
In my last post I talked about a [MS Natural 4K replacement](/b…
–
pknowles
created
May 14 at 21:46
Matching complex shapes for a custom keyboard in Fusion360
For my [custom mechanical keyboard](/blog/55/derbard-custom-spl…
–
pknowles
comment
May 8 at 0:32
Matrices
[deleted]
–
anonymous
…
View All
Log in
Projection Matrix
leave this field blank to prove your humanity
Slug
*
A URL path component
Parent page
<root>
3D Rendering (Computer Graphics)
--- Cameras
--- Matrices
------ Projection Matrix
--- Vectors
--- 3D Geometry
------ triangle_meshes
--- Shading
------ Transparency and Alpha Blending
--- Lights
--- rasterization
------ Deep Image
--- Shadows
--- Vector Spaces
------ Tangent Space
------ Clip Space
--- rotations
--- images
------ mipmapping
--- materials
OpenGL Tutorials
--- Order Independent Transparency (OIT)
--- The Framebuffer
Pages About This Site
--- Contributing
--- Bugs
--- Why does this website exist?
The parent page this belongs to.
Article title
*
Article revisions must have a non-empty title
Article body
*
A projection is fundamental to [cameras](/8/rendering/cameras/), mapping a 3D space onto a 2D image to render geometry. The projection [matrix](/9/rendering/matrices/) is widely used in computer graphics to encodes such a transform between spaces. It is a linear transform preserving straight lines, which both looks natural and is important for fast rasterizaiton, unlike a fisheye projection for example which is non-linear. A projection matrix is a 4×4 homogeneous matrix and can be pre-multiplied with other transformation matrices. Multiplying a point in world space, of the form $(x, y, z, 1)$, by a projection matrix produces *clip space* coordinates. For some projection matrices, a "*perspective normalise*" divide is required to convert from clip space to normalised device coordinates (NDC). The $(x, y)$ coordinates can be scaled by the image resolution for coordinates in pixels. This process is included in the discussion of [spaces](/18/rendering/spaces/). The projection matrix implicitly defines a viewing volume and image bounaries at the -1 to 1 planes in NDC. That is, the image is formed by $(x, y)$ points inside the -1 to 1 range after being transformed by the projection matrix. Geometry outside the range is "clipped", discussed later. $z$ may also be constrained to the -1 to 1 range for precision reasons with depth testing. When projected back into world space, these boundaries create a typical cube or frustum shaped viewing volume shown in many projection visualizations. There are two common projection matrices used in 3D graphics: orthographic and perspective. An orthographic projection is commonly seen in mathematical diagrams as it preserves relative lengths in addition to straight lines. It is also useful in modelling packages to align geometry. The projection matrix is more natural and objects in the distance become smaller, just like typical rectilinear lenses and the human eye. # Orthographic The orthographic matrix gives a cuboid viewing volume and is really just a scale matrix to frame the scene. The image is eventually formed by geometry in the -1 to 1 range after the projection matrix is applied. To define an orthographic projection, left, right, top and bottom distances ($L$, $R$, $T$, $B$) are chosen to map to the image borders. An orthographic matrix scales these down to the -1 to 1 range. It also performs a translation if the borders are not symmetric. Near and far distances ($N$, $F$) for the depth range are also chosen, particularly so that objects behind a camera are not drawn, but also to help hidden surface removal methods such as the depth buffer. $$ \begin{bmatrix} \frac{2}{R-L} & 0 & 0 & \frac{L+R}{L-R} \\ 0 & \frac{2}{T-B} & 0 & \frac{B+T}{B-T} \\ 0 & 0 & \frac{2}{N-F} & \frac{N+F}{N-F} \\ 0 & 0 & 0 & 1 \end{bmatrix} $$ The component $\frac{2}{N-F}$ is negative which inverts $z$ components so that the camera looks towards $-Z$. Because the bottom row is $(0, 0, 0, 1)$ the depth range is scaled linearly, unlike in the projection matrix later. This affects the depth buffer's precision. In some cases it is desirable to create a projection which matches world space units with width and height in pixels of the final image, as in the following matrix. Note $B=\mathsf{height}$ rather than $T$ so that $+Y$ is down. While this doesn't make much sense for computer graphics it is essential for text alignment as we read from top to bottom. $$ \begin{array}{2} L=0 & R=\mathsf{width} \\ B=\mathsf{height} & T=0 \\ N=-1 & F=1 \end{array} $$ # Perspective A [perspective projection](/8/rendering/cameras/#projection) computes intersections between a plane and lines from the origin to points in the 3D world, or, "projects" those points onto a plane. Imagine drawing what you see through a sheet of glass, held exactly one unit away from you. The maths is easy: divide points by their $z$ coordinate. An alternative interpretation is to shrink distant objects by scaling down their x and y coordinates by their distance, although that's more the effect than the intention of a projection. With the perspective divide convention, a perspective projection can be represented in a 4×4 matrix. A perspective viewing volume is typically symmetric, defined by a field of view, $\mathsf{fov}$, an aspect ratio $a$, which is discussed later, and near and far ($N$, $F$) boundaries. Rarely is a perspective projection asymmetric and more general frustum viewing volume is not provided here. $$ f = \operatorname{cot}(\frac{\mathsf{fov}_y}{2}) = \frac{1}{\tan(\frac{\mathsf{fov}_y}{2})} $$ $$ a = \frac{\mathsf{width}}{\mathsf{height}} $$ $$ \begin{bmatrix} \frac{f}{a} & 0 & 0 & 0 \\ 0 & f & 0 & 0 \\ 0 & 0 & \frac{N+F}{N-F} & \frac{2NF}{N-F} \\ 0 & 0 & -1 & 0 \end{bmatrix} $$ Note the $(0, 0, -1, 0)$ bottom row which makes the $w$ component of a transformed vector dependent on $z$. This is what causes objects to become smaller in the distance as $x$ and $y$ are divide by $w$ during the perspective divide, discussed later. # Clip Space and the Perspective Divide After a vector is transformed by a projection matrix it is in [clip space](/27/rendering/spaces/clip_space/). It is a 4D space and called clip space because this is where geometry is "clipped" at the borders of the image. Some form of clipping is necessary as it would be inefficient to perform computation on geometry outside the image. Clipping is more important to rasterizers as triangles are transformed into image space for pixel--polygon intersection tests (although the intersections are generated) rather than testing in world space as a raytracer does. Exactly why clipping is performed in clip space becomes more apparent after the perspective divide is introduced. The perspective divide "normalizes" a clip space vector by dividing by its $w$ component so that the new $w$ is 1: $$ v_\mathsf{NDC} = \frac{v_\mathsf{clip}}{v_{\mathsf{clip}_w}} $$ As said earlier, this scales down objects in the distance in the case of a perspective projection. ## Precision In addition to scaling $x$ and $y$ the perspective divide also affects $z$, creating a hyperbolic mapping which has some beneficial properties for precision when comparing $z$ values. When truncated to integers, the number 3.1 is not less than 3.2 as only the 3 is compared. The resolution of possible values is one, i.e. numbers have to be at least one apart before they are distinct. Using linear $z$ the resolution is the same for objects close to the camera as those way off in the distance. However high precision in the distance is often not necessary as geometry there is sparse, while detailed geometry is drawn up close. By scaling $z$ so that possible values are closer together near the camera, the precision is better optimized for typical scenes. ## Clipping One method is to clip polygons at the image boundaries, as in the image below. However the resulting shapes may be quads and additional vertices and triangles are needed. Clipping geometry is expensive. Alternatively the rasterizer may simply not produce fragments for pixel positions outside the image. I.e. triangles completely outside the image are culled and those that intersect it are still sent to the rasterizer which can efficiently ignore their area outside the image. This works fine for triangles bordering the $X$ and $Y$ boundaries, but there are a few problems in the $Z$ direction. ![Clipping triangles to the image borders][1] The perspective projection preserves straight lines, with the exception of lines that cross the $z=0$ plane, for example a triangle with some vertices in front of the camera and some behind. The point behind will have its $(x, y)$ position inverted and edge interpolation will be incorrect. This makes it impossible to perform triangle clipping in image space or NDC and elevates the importance of clipping in clip space, as it's named. Triangles that bridge the $z=0$ and $z=N$ region and are within the $X$ and $Y$ image boundaries must be clipped to the near plane before the perspective divide. Triangles which intersect the near and far clipping planes may be rasterized without geometry clipping and clipped by discarding fragments outside the depth range. Clipping implementation is discussed in more detail by [Fabian Giesen at his blog](https://fgiesen.wordpress.com/2011/07/05/a-trip-through-the-graphics-pipeline-2011-part-5/). # Aspect Ratio The aspect ratio is a ratio between the width and height of the image, specifically width:height or $\mathsf{width}/\mathsf{height}$. For example, some common resolutions are 640×480, 1680×1050 and 1920×1080 with aspect ratios of 4:3, 16:10 and 16:9 respectively. The projection normally encodes the image aspect ratio so that after NDC, scaling to the image resolution produces an undistorted image. A seeming alternative may be to apply the aspect ratio when scaling NDC, but clipping must be performed in clip space so the aspect ratio must be applied beforehand. [1]: /u/img/bcf7ab83539f.svg
Toggle Preview
Edit message
*
A description of the changes made
Discard Draft
Save Draft
leave this field blank to prove your humanity
Flag
the thing you clicked
for moderator attention.
Reason choice:
Spam, promoting, advertising without disclosure
Rude, inappropriate, generally offensive
Too arrogant or demeaning to others
Other
Reason:
The reason for raising the flag
Error