Game Basics Mathematics for 3D Games Part 3: Perspective Projection Transformation and Depth Values
Hello, everyone?
This is Lee Deuk-woo from Game Mathematics
In this session,
we’ll discuss perspective projection
We’ll explain what perspective projection transformation is
and how to implement it
We’ll also explore the concepts
of clip space,
homogeneous coordinates,
and vanishing points, which are used in the perspective projection process
Next, we’ll look into depth values
I’ll explain what depth values are
and why they are necessary
To handle depth values, we need to create
a specific geometric shape
which is called a frustum
For the frustum
we will examine how it is constructed
We’ll also explore
how to design the newly defined space
using the frustum
This is what we will explore today
Finally, we’ll discuss
the final perspective projection matrix
that incorporates the frustum and calculates depth values
Perspective Projection Transformation
First, let’s discuss the perspective projection transformation
This is referred to in English as
the Perspective Projection Transformation
That is what it is called
It’s related to
the perspective techniques often mentioned in art
You can think of it as a method
to implement perspective drawing techniques
This perspective technique in art
was devised during the Renaissance period
and has evolved into a technique
that is now used in nearly all
three-dimensional drawings
In the past, to achieve this,
a single focal point would be set
and strings were extended
to project the image onto a surface
in a highly precise, detailed process
This was done manually
Even today, when drawing
it’s common to use vanishing points as a reference
and apply perspective techniques using lines
is common
Instead of applying these techniques
step by step manually,
we can use matrices
to efficiently represent objects with perspective
all at once
This is achieved through
the perspective projection transformation
I explained earlier
The principle behind perspective projection transformation is as follows
We start with a real-world space where the three axes
are orthogonal to each other
The space we perceive with our eyes
views this orthogonal space
slightly differently
In the real world
objects are arranged orthogonally
but the world we perceive
begins from a single point, like a camera
and expands outward
in a specified field of view
So you can think of the spaces
as being configured differently
You can understand it like this
In this expanding space
defined by the field of view
we designate a plane
to project the objects in the space
onto this plane
The farther this plane is from the camera
the larger it becomes
and the closer it is, the smaller it appears
We need to specify a single plane
that changes depending on the distance
This specified plane is called the projection plane
The shortest distance from the camera to this plane
is called the focal length
With these two concepts in mind,
we can now project objects onto that plane
to create a final image
with perspective
If we look at this from the side
it can be visualized as follows
First, there’s the field of view
This is predetermined in the camera
The field of view is defined
Next, we specify the projection plane onto which objects will be projected
The shortest distance between the camera and the projection plane
is called the focal length, correct?
Let’s denote this as d
From this basic setup
we need to determine
how to implement this
A commonly used method
is to define the projected area
known as NDC
Typically, the final game screen
is displayed on a monitor
Depending on the monitor specifications
resolutions can range from 1024x768
to 1920x1080 or even 4K
There are various types of resolutions, right?
These different resolutions use varying pixel densities
to form the screen
It’s impractical to handle all these resolutions individually
So, in programming,
the resolution is handled separately
while the projected space is designed
to be as simple as possible
using a unit scale of 1
for the projection plane
This is the fundamental principle of NDC
Similarly, in textures
no matter how large the texture image is
we use UV coordinates from (0, 0)
to (1, 1)
Regardless of the screen resolution
we define the projection plane
as a 1 unit-sized plane
This is the NDC coordinate system
However, when specifying a size of 1,
it doesn’t mean the entire size is 1
As shown here
only half the size is defined as 1
This makes calculations easier
If the half-size of the projection plane
is defined as 1 within the field of view
we’ll be working with only half the field of view
For this half field of view, we can calculate
the focal length and form a right triangle
with one side equal to 1
When viewed from the front, the resulting plane
will take this form
Since half the size is defined as 1
the plane extends 1 unit up and down
and 1 unit left and right from (0, 0)
This creates a plane with a total size of 2 units
The coordinates of the points
projected onto this plane are referred to
as NDC coordinates
The mathematics behind NDC
as explained earlier,
starts with the half field of view, the focal length
and a right triangle
with one side equal to 1
The focal length depends on the field of view
so how do we calculate it
What happens as the field of view decreases?
As the field of view decreases
the size corresponding to 1 moves farther back
This is because the size of 1 remains constant
Only at this distance
can the size of 1 be maintained as the field of view narrows
This demonstrates an inverse proportionality
The focal length is related to tan θ/2
the tangent of half the field of view
Since it’s the height divided by the base
it equals 1/focal length
To calculate d,
take the reciprocal of tan θ/2
where θ is half the field of view
This is how you can do it
Let’s visualize how
a point in view space
is projected onto the projection plane
using this triangle
There are various points in this space
Some points are in the foreground
while others are in the background
All points are projected
toward the camera point onto the projection plane
By drawing lines toward the camera
we find the NDC coordinates
where they intersect the projection plane
This allows us to calculate the points in the NDC coordinate system
Using these points, we construct triangles
to render the scene
This enables us to
create a 3D space with perspective
Our goal is to create
a matrix that performs
this transformation
So, how do we create this matrix?
We use the similarity ratio of two triangles
Here,
although we don’t know the angle
we aim to obtain the projected coordinates
We already know the focal length
We know the focal length
and in the arbitrary view space
if a point exists in the view space
where the three axes are orthogonal
we can determine
the point’s distance and height
relative to the camera
This information is derived from the coordinates in view space
If we know the focal length,
we can establish a proportional relationship
between the focal length
the distance from the camera
the y-value, and the NDC value we want to calculate
Previously, we mentioned that the view space
always faces the back of the camera, right?
Thus, all object coordinates in the view space
in front of the camera
always have negative values
When setting up the proportional relationship
the z-value, which is negative
needs to be multiplied by -1
to convert it into
a positive value
Once converted to positive
the two proportional equations
allow us to calculate the y-value
for the Pndc coordinate
For the x-axis,
since it shares the same field of view
as the y-axis,
the principle is the same
In essence, there’s no difference between the y and x axis
So, applying the same calculations
to the x-axis,
we can obtain
the projected coordinate values in this form
This results in an NDC coordinate system
where the size
is a square extending 2 units
horizontally and vertically
So how do we project this onto
an actual monitor?
We expand it proportionally to the monitor's resolution
and calculate accordingly
For instance, if the monitor has
a resolution of 800x600
you scale the NDC area
by 400 horizontally and 300 vertically
extending it like this will help make it
to fit it perfectly onto the screen
However, there’s an issue
when expanding the NDC space
to fit the screen resolution
As mentioned earlier,
the NDC space is a uniform square
But most monitor resolutions
have different horizontal and vertical aspect ratios
This creates a problem
For example, let’s say we have
a perfect circle in NDC space
as shown here
If we expand it
horizontally and vertically based on the screen resolution
the differing aspect ratio
causes the circle to distort into an ellipse
as shown on the screen
This can be confusing
You might wonder why your perfect sphere
that you made
looks distorted
To prevent this issue
you need to address
the differing aspect ratios
The solution is
to apply the aspect ratio
to the object in NDC space
distorting it first, and then scaling it up
By doing this, the distortion cancels out
during scaling, and you end up
with a perfect sphere
What is the reference point for the aspect ratio?
Does it use the horizontal
or vertical dimension as a reference?
It can vary depending on the choice
In most cases, the vertical dimension is used as the reference
So here, we’re using
the vertical as the reference
and the a value will be greater than 1
This is because
the horizontal length is usually greater than the vertical length
To apply this,
we account for the reciprocal of the aspect ratio in the calculations
We don’t adjust
the y-component specifically
because we’re only distorting the x-component
Thus, we apply the reciprocal of the aspect ratio
only to the x-component
The final NDC coordinates
will have the same focal length (d) and depth values
Everything remains unchanged,
except that the aspect ratio adjustment
is applied inversely to the x-component
Using this calculation method
we can determine the NDC coordinates
The matrix reflecting these adjustments
can be calculated as follows
When we obtain the x, y, z values in the view coordinate system
the matrix for deriving the Pndc values
can be structured like this
However, there is an issue when examining this matrix closely
The problem lies in the fact
that this matrix
uses the vz value
It relies on the z value
of individual points
Why is this a problem?
In general, when using matrices
we don’t create a unique matrix for each point
Instead, we create a fixed matrix
that can be applied to tens, hundreds, or millions of points at once
Matrices are designed to be uniform
and applied simultaneously to many points
If the z-coordinate of a point
is directly integrated into the matrix design
it means we would need
to create a new matrix for each point
being transformed
This undermines the purpose of using a fixed, reusable matrix
For instance, if there are 100,000 points
100,000 matrices would need to be generated
This approach is clearly impractical
Fortunately, there are solutions to this issue
The solution lies in what we call clip space
which I’ll now explain
Clip space is used to create a general-purpose matrix
that works independently of specific points
It serves as an intermediate space
This is what we call a Clip space
Here, we’ve summarized
the concept of clip space as follows
It’s essentially
a 3D space transformed from the view space
It’s an intermediate space
between the view space and the final 3D NDC space
Think of it as a transitional step
This space retains all three dimensions
as part of the intermediate stage
Unlike NDC space,
which only requires 2D since it’s a plane
clip space is structured in 3D
But why is it structured as 3D?
In this equation,
all coordinates are divided by -vz
So, before dividing, the idea is to use this value
to construct the coordinates
After constructing the coordinates, dividing by -vz
yields the basic NDC coordinates
we intended to obtain
beforehand
This means applying the matrix
doesn’t directly yield NDC coordinates
but instead produces the clip space coordinates
denoted as Pclip
which becomes the primary goal of the matrix
So, how can we set this up?
To get -vz
simply place -1 in the last element of the matrix
This allows us to design such a matrix
As you can see, the P-matrix
used for perspective projection
doesn’t contain point-specific information
Instead, it only depends on the camera’s focal length
field of view,
and horizontal-to-vertical aspect ratio
With these parameters
we can construct the perspective projection matrix
Thus, even if there are 100,000 points
a single precomputed matrix
based on the camera settings,
can be applied universally to all points
Once the coordinates are generated
manually dividing by the last element
yields the desired
NDC coordinates
This approach satisfies
both objectives
The concept of clip space
is closely related to what is called
homogeneous coordinates
In 3D computer graphics
you can think of it as involving two types of spaces
First, there’s the world space
which is used for placement and overall structure
where x, y, z are orthogonal
Next, the world space
is transformed into view space
where it is adjusted to match the camera’s perspective
This transformation mimics the rules
by which humans perceive the world
through their eyes
It follows those rules
in the same procedure
This process occurs
in what we previously described as clip space
Mathematically, this is referred to as projective space
It’s called "projective space"
Let me explain the differences
between these two spaces
In Euclidean space
parallel lines never intersect
This is something we are all familiar with
However, let’s consider an assumption
regarding these parallel lines
This pertains to results within a 2D space
Let’s assume that these 2D results
are part of a system
constructed within a 3D space
Let's make such an assumption
The current coordinates
we see are just a partial projection
of a 3D space
Unseen elements from the 3D space
influence this projection
So, how do they affect it?
The value divided by the last dimension
in this case represented
by ax + b
is the result of dividing
by the new dimension, z
Let’s analyze it this way
So, when we divide the 3D space
represented by x', y' z',
by z', it results in x, y, 1
This shows that
the plane is constructed using x and y
In this mechanism
the essence of x is
that it’s derived by dividing x' by z'
Similarly, the essence of y
is that it’s derived by dividing y' by z'
If we substitute this into the linear equation
y = ax + b discussed earlier,
we can express it in terms
of the underlying spatial rules
Multiplying both sides by z'
yields the equation y' = ax' + bz'
This is the equation that is created
Looking at these equations,
since x', y' and z' all share
the same linear degree
this is called a homogeneous equation
A space constructed based on this theory
is referred to as homogeneous space
This is equivalent to the previously mentioned
projective space
Thus, dividing by the last element
is analogous to the process
of converting from clip space
to NDC space
In other words, this process is the same
as the conversion from clip space to NDC space
Therefore, clip space can be thought of as
a space created relative to NDC space,
where the concept is
that it exists in one additional dimension
beyond what NDC space can perceive
You can understand it as a concept like this
Let’s examine how
clip space operates
One key example is the principle of vanishing points, which we discussed earlier
In Euclidean space,
parallel lines never intersect, right?
But let’s consider this in projective space
In projective space,
if we think about it this way,
as x and y increase
z consistently influences
the space
If we change the z value
along a line in projective space
in Euclidean space
where x, y, and z are orthogonal
z does not influence x and y at all
Thus, z simply moves independently,
unaffected by x and y
However, in projective space
z affects x and y
This interaction means that
as z increases
and y values also increase
They have such characteristics
What happens if z decreases
and approaches 0?
The x and y values will also ultimately
appear as 0
For lines with different slopes
when z = 0
no matter what values they have
they will converge
to 0
So, values in projective space
with the same slope
can be thought of as belonging
to the same category
The points along this line
are considered of the same type
However, even if
the points have
different slopes
they all ultimately converge at the origin
Similarly, lines extending in the opposite direction
converge at a point
at infinity
This is the fundamental principle
of projective space
This may seem like a difficult concept
but to summarize
the last element always
influences x and y
There are sets of points
sharing the same ratio,
and these points form a line
The points forming the line
are described as having the same properties
There are infinitely many points
with the same properties
Among them, we use only
one specific point
Specifically, the point
where z = 1
This is because it represents
the actual displayable area on the monitor
Thus, the points in the same category
converge here
By dividing by the last element,
the z-value becomes 1
allowing us to extract just one point
from the many
sharing the same properties
This rule ensures that
when we render points on the screen
what happens if
the vz value is set to infinity?
If vz is infinite,
it is technically -vz
because it is the opposite direction of the camera
I mean it aligns with the camera’s viewing direction
If we set it to infinity
along the camera’s direction
the value approaches 0
as it increases toward infinity
Thus, points far away from the camera converge
near the center of the NDC space at 0
All objects located infinitely
far from the camera
converge near 0 in the NDC space
We can understand it like this
Consequently, these points
converge to the NDC
coordinate (0,0)
This is the same principle
as the vanishing point
often discussed in art
Taking this vanishing point principle into account,
let’s design the system accordingly
The last dimension
doesn’t hold much significance in this context
You only need to replace the z-value with -z
A 4x4 matrix must be used
to integrate it
into the rendering pipeline
This allows us to construct the perspective projection matrix
as follows
This concludes our discussion on the matrices
for perspective projection transformation
Depth Values
First, let’s discuss depth values
Why are depth values necessary?
Depth values represent
the numerical data
that indicate how far an object is
from the camera
If we were to render multiple objects
in 3D space
without depth values
as shown in the image
we wouldn’t be able to determine
which objects are in front
and which are behind
The large character face here
is actually positioned in the foreground
but because it was drawn first
it gets covered by faces drawn afterward
As a result, it appears to be
in the background when viewed
So, how do we solve this issue?
What we have to do is
we need to calculate depth values
and use them
to ensure that objects in the foreground
aren’t overwritten by those in the background
This must be calculated and applied
at the pixel level
This is referred to as a depth buffer
We’ll explore how to implement a depth buffer
in more detail next time
but today, we’ll focus on
how to calculate the depth values
used in it
That is what we will discuss today
To address depth values,
we ultimately need to expand
the existing 2D NDC space
by adding
an additional dimension
We extend the NDC space
into 3D as follows,
so that the depth values are defined
within this range
We must specify the depth range
from one boundary to another
This is wher
the frustum comes into play
A frustum is formed when
we define a field of view from the camera
It extends outward from the camera
to infinity
But there’s no defined start or end point
The starting point is essentially the camera’s position,
but it can also extend backward
In projective space
if the camera is at the center
it projects forward
but can also extend backward
Effectively, it creates a space
that extends infinitely
in both directions
Instead of calculating depth values
across an infinite range
we define a finite range, similar to NDC space
We specify a fixed range
for rendering
Then, we define one end as the minimum value
and the other as the maximum value
This effectively slices a finite section
out of the infinite projective space
Only the objects within this range are rendered
The resulting 3D shape
is called a frustum
When sliced at two points,
it forms a truncated pyramid-like shape
where the point is cut
as you can see
The first slice,
closer to the camera,
is called the near plane
Since we cannot draw the end of infinity
the farthest slice within the drawable range
is called the far plane
The depth value for the near plane
is typically set to -1
and the depth value for the far plane
is set to 1
Objects within the frustum
will have depth values between -1 and 1
This prevents the issue we saw earlier,
where objects in the foreground
appeared in the background
We can prevent this
Let’s look at how this is applied
If we extend this
to NDC space,
the coordinates will look like this
The values closest to the camera
have a z value of -1
and the farthest values
have a z value of 1
This is how you can think about
the 3D NDC coordinate system
One notable aspect here is that
since x ranges from
-1 to 1
and y ranges from -1 ro 1
you might expect z to follow the same range
That would make the three axes align perfectly
However, from a practical perspective,
when calculating depth values
they are often represented as images
Images, after all, represent color
and color typically
does not exist in minus
it ranges from 0 to 1
0 corresponds to black,
and 1 corresponds to white
To make depth values useful when expressed as colors
between 0 and 1
some systems avoid negative values
nd start from 0
In graphics libraries like DirectX
the depth value
for the near plane
is sometimes set to 0
This is something
you should keep in mind
If we summarize
this coordinate system
in NDC space,
the farther an object is from the camera
what happens?
Its size appears to increase
But as we’ve seen before,
in view space,
which uses a right-handed coordinate system
the x-axis typically points left
and the y-axis points up
this is typical
Even if the camera faces a certain direction
the z-axis isn't aligned
with the camera’s view direction
Instead, priority is given to how the screen is structured
Thus, the z-axis in the view space, structured using a right-handed coordinate system
points opposite to the viewing direction
because it uses a right-handed coordinate system
However,
the objects we render
aren’t behind the camera
but rather in front of it
When transformed
into view space
all points of objects in front of the camera
will always have negative z-values
we can make this conclusion
This is due to the use of a right-handed coordinate system
However, in NDC space,
for objects in front of the camera
the z-value or depth value
increases as the object moves farther away
This means that
NDC space
uses a left-handed coordinate system
It’s not a right-handed system
but a left-handed one
Let’s briefly review
what we’ve learned so far
In our example,
we started with world space
World space uses
a right-handed coordinate system
for ease of object placement and viewing
I previously mentioned that
engines like Unity and Unreal
use left-handed coordinate systems
Thus, we constructed the world
using a right-handed coordinate system
and the camera’s view space
also uses
a right-handed system
This is something
important to remember
However, during the conversion
from view space to NDC space
the system transitions to a left-handed coordinate system
This goes back to when we discussed
perspective projection matrices
We always multiplied the z-value by -1
to construct the z-value in clip space
Since we constructed the z-value in clip space,
this step indicates a transition from a right-handed coordinate system
to a left-handed one
When we transitioned clip space
we summarized it as follows
In local space
the coordinate system is
typically determined by the modeling program
Most modeling programs use
a right-handed coordinate system
In world space,
the coordinate system depends on the game engine
Unity and Unreal Engine use left-handed systems,
but in this course
we’re using a right-handed coordinate system
View space also uses a right-handed system,
even in game engines
However, when transitioning to clip space,
the z-value is multiplied by -1
switching to a left-handed system
Simply dividing by the last element
results in NDC space also adopting a left-handed system
It’s useful to understand
these coordinate system characteristics
so I provided this summary
Now, let’s look at
the final perspective projection matrix
that incorporates
depth values
Previously, we wasted a row
in the 4x4 matrix
just to make it conform to the format
But now, we’ll assign
meaningful values
to calculate depth
For the third row,
let’s assume there are four components
i, j, k, l as unknowns
We will assume this
If we determine these four values,
we can calculate
the depth as well
We don’t know the exact depth values
resulting from multiplying i, j, k, l
but depth
is independent of x and y
Depth is unrelated to x and y values
In other words, depth depends
on the z-values in view space
Therefore, the first and second components,
which are related to a
should effectively be 0
This is because they don’t influence depth
So, we’ve already resolved two of the four components
Next, we need to find k
and l
To determine these values,
we use the characteristics of the near plane and the far plane
and derive
two sample data points
The simplest sample
is a point on the near plane
where both x and y
are 0
In view space,
how is the camera’s view direction
defined?
It becomes a negative value, right?
The near plane
has a value of n
based on the specified size
In view space, the point is (0,0,-n)
Similarly, the far plane point
in view space
is 0, 0, -f
However, once transformed
into NDC space,
the depth values range from -1 to 1
Thus, the near plane point becomes 0, 0, -1
and the far plane pint becomes 0,0,1
Using this basic data,
let’s derive the intermediate values
for k and l
The point in view space
is 0,0,-n, 1
When this point is multiplied
by a matrix containing two unresolved unknowns,
what is the result?
Ultimately, we need to examine
what this value turns out to be
At this point, these aren’t NDC values
but clip space value
When the matrix is applied,
the result will be in clip space
Here, if we take -n
the fourth component will definitely be n
Similarly, in this case
the fourth component will definitely be f
The key is determining the third component
The value divided by the last element
must equal -1
so here it will be -n
On the other hand,
since the NDC value here is 0,0,1
dividing by f to get 1
means this must be f
Thus, the respective clip coordinates
0, 0,-n,n here
and 0,0,f,f there
Using this, let’s proceed with the calculations
0,0,-n,1 should transform into 0,0,-n,n
and 0,0,-f,1 should correspont to
0,0,f,f
When multiplied directly
what is -kn + l
the result for the third element is -n
-kf + l
must equal f
However, n and fare
predefined by the user
as the near and far planes of the camera
Since they represent the near and far plane values
of the frustum,
they are treated as constants
The unknowns here are
k and l
Eliminating variables
k is caluclated as n+f/n-f
and l is calculated as 2nf/n-f
Substituting these values
yields the final
perspective projection matrix
This completes the calculation
of the final perspective projection matrix
we’ve been developing
That’s it for today’s lecture
Thank you for attending
Thank you
Summary perspective projection transformation is implemented by drawing lines based on vanishing points Projection Plane: mapped based on distance
Focal Length:shortest distance from camera-projection plane method to normalize screen size while considering resolution NDC regardless of monitor spe
Defines projection plane size as 1 for easy calculation focal length d=1/tan(θ/2) Objects may appear distorted
due to different monitor aspect ratios this is corrected in NDC space Final NDC coordinates Pndc = -vz/d a/vx, vy
Clip Space Intermediary space used to create general-purpose matrices Perspective projection matrices constructed with camera focal length&aspect rate
pv = a/d 0 0, 0 d 0, 0 0 -1 vx vy vz=a/d vx, d vy,-vz Vanishing Point Principle: In projective space, all lines converge to origin as z-values decreas
Clip Space Coordinates represent lines where points within same category are gathered Dimension-Aligned Perspective Projection matrix
p= a/d 0 0 0, 0 d 0 0, 0 0 -1 0, 0 0 0 1
Necessity of Depth Values First object drawn may appear in background Ensure that objects behind dodo not overwrite those in front through pixel value
Frustum A 3D geometric region with a truncated pyramid shape, created by defining a range for z-values within the camera's usable space
Coordinate Systems When transformed to NDC space, right-handed coordinate systems are converted into left Local Space: Most modeling programs use righ
World Space: Uses the coordinate system defined by the game engine. View Space: Uses right-handed Clip Space: Uses left-handed NDC: Uses left-handed
Final Projection Matrix A final projection matrix that calculates depth values while accounting for frustum p= a/d 0 0 0, 0 d 0 0, 0 0 n-f/n+f n-f/nf,