<p>First of all we need to understand why do we need 4x4 matrices in the first place. With 3x3, we couldn't represent translation as it wasn't a linear transformation (it displaces the origin). So in order to avoid extra work, homogeneous coordinates and affine transformation was introduced. </p>

<p>Now instead of doing</p>

<p>$v' = Lv + t$ </p>

<p>where <code>L</code> is a linear transform and <code>t</code> is the translation, we can do</p>

<p>$v' = Av$</p>

<p>Where <code>A</code> is the affine matrix. This makes it cleaner. So 4x4 matrices are a real necessity, we just can't work without them. In order to distinguish between vectors and points we use <code>w = 1</code> for points and <code>w = 0</code> for vectors. So you are suggesting to make this 4th dimension implicit and don't store it as it'll actually use space/memory.</p>

<blockquote>
  <p>We can pretend that the 3 dimensional vector is 4 dimensional (imaginary w = 1). This is after all Computer Science, not math.</p>
</blockquote>

<p>This works but up-to a certain extent. Using this approach we would have 4x4 matrices and 3 dimensional row/column vectors. But now when doing multiplication we will have to make a check whether it's point or vector and based on that we multiply the elements of the 4th column of the transformation matrix by <code>0</code> or <code>1</code>.</p>

<p>This alone starts creating mess, check every time whether it's a point or a vector so why not just use the space for a single float more and get rid of this stupid check.</p>

<p>That aside most modern CPUs have SIMD registers 128 bits wide perfect to fit 4D vectors. If you are doing your calculations on the GPU, all the more reason to store 4D vectors as branching instructions are much more costly on the GPU.</p>

<p>If you start feeling the need to use 4D, great. If not then we still have the problem of composing matrix transformations. Instead of multiplying individual transformations with our vector we would like to pre-multiply all of the transformations then do a single vector-matrix multiplication. This can't work with projective transformations where we need to divide by "something"</p>

<p>Let's come to reason number 3.</p>

<blockquote>
  <p>You will have to do division by w after projection matrix anyway. Why not divide by z then and get something like [x/z, y/z, z]. Both of them cost 1 computation.</p>
</blockquote>

<p>This is the simple case for just a projective transformation. Consider the vector going through 5 or 6 transformations  and in the last comes the projective transformation. If we pre-multiply all these transformation to create a single matrix, you will notice that now when we multiply the vector with this combined transformation matrix the division factor isn't just a simple <code>-z</code> value. The 4th row of the matrix won't be <code>0 0 -1 0</code> as in the standard projection matrix. It might have changed due to multiplying all the transformations together. Now when you multiply that 4th row with the 4D vector, you will get your <code>w</code> value by which you need to divide now. </p>

CC BY-SA 3.0
2018-02-22T09:43:23.457Z
Good answer. I'd add to the last part, even in the case of a simple projection transform with no other matrix multiplies the Z component doesn't carry over untouched - it ends up in the form A*Z + B, used for near and far clipping and perspective-correct interpolation. So even in the simplest case you still need to store the original Z value somewhere.
russ
CC BY-SA 3.0
2018-02-22T19:32:53.403Z
@russ - true that, but thinking from his perspective, even tho the final Z value is A*Z + B, we still have the original vector IF we aren't overwriting/ storing the modified vector in the original variable. So he could argue we still have the original Z value stored. That's why tried to give an explanation where the division factor isn't just "-z" it's something entirely else.
gallickgunner
CC BY-SA 3.0
2018-02-22T21:30:48.550Z
"why not just use the space for a single float more and get rid of this stupid check" Why not let the type system keep track of which things are points and which vectors at compile time, and get rid of this stupid extra float that needs to be multiplied and added at runtime 
Nathan Reed
CC BY-SA 3.0
2018-02-22T21:37:52.833Z
Also FYI, to the point about SIMD, storing an xyzw vector as a SIMD register actually isn't best practice. Better is to go SOA and have one register of 4 vectors' X values, another of the 4 Y values, etc. This generalizes a lot better to larger SIMD widths. Note that a lot of newer CPUs have 8-wide SIMD, and GPUs have 32- or 64-wide SIMD.
Nathan Reed
CC BY-SA 3.0
2018-02-23T09:10:12.350Z
@Nathan Reed - don't understand what you meant by "type system" in your first comment? If you meant something like separate classes for points and vector each having a `*` operator defined for itself and a matrix and the actual `1` or `0` hardcoded inside that function, then it isn't applicable in for example shaders.
gallickgunner
CC BY-SA 3.0
2018-02-14T11:23:27.570Z
2018-02-14T11:23:27.570Z
gallickgunner
<p>Some very quick answers:</p>

<blockquote>
  <p>We can pretend that the 3 dimensional vector is 4 dimensional (imaginary w =1). This is after all Computer Science, not math. </p>
</blockquote>

<p>Ahh.. but sometimes in graphics we don't have w=1. Some examples that come to mind are</p>

<ol>
<li>Placing a vertex at "infinity", e.g. for shadow volumes </li>
<li>Representing directions rather than absolute positions</li>
<li>Doing rational curves. e.g. $\frac{Quadratic Bezier()}{Quadratic Bezier()}$ to represent, say, conic sections.</li>
</ol>

<p>I'm sorry, I've no idea what you mean by <em>"to crush z"</em>, but sometimes, if chosen carefully, after the projection transform you may be able to get by with just 3 terms, e.g. (X/W, Y/W, 1/W) assuming you also have the post-projection texture coordinates, (U/W, V/W).</p>

<blockquote>
  <p>I'm not dividing by z because it will be used for z-buffering</p>
</blockquote>

<p>Typically, despite the name, the Z-buffer contains an interpolated 1/W, 1/Z, or some linear function of one of these.</p>

<p>-</p>

CC BY-SA 3.0
2018-02-14T13:45:55.453Z
By crush z, I mean making them 0 to make points become 2d
Manh Nguyen Huu
CC BY-SA 3.0
2018-02-15T01:49:01.053Z
@ManhNguyenHuu: But the points *never* "become 2d". That's the point. They're *always* three-dimensional positions, even in window-space.
Nicol Bolas
CC BY-SA 3.0
2018-02-14T08:51:25.613Z
2018-02-14T08:51:25.613Z
Simon F
<p>We use projective geometry and homogeneous coordinates so that we can make use of <strong>linear algebra</strong> to do our transformations.</p>

<p>And by the way, this <strong>is</strong> math.  I think you should read wikipedia's pages about <a href="https://en.wikipedia.org/wiki/Projective_geometry" rel="nofollow noreferrer">Projective Geometry</a>, and the clever idea to introduce a <a href="https://en.wikipedia.org/wiki/Point_at_infinity" rel="nofollow noreferrer">Point at Infinity</a>, and use <a href="https://en.wikipedia.org/wiki/Homogeneous_coordinates" rel="nofollow noreferrer">Homogeneous Coordiantes</a> to allow you to deal with projective geometry transformations using <strong>linear algebra</strong> as opposed to dealing with the ugly math required to do transformations after the divide (because projections are non-linear).</p>

<p>At some point, you must divide though, so this technique is a way of deferring that divide to the very end.  All the other transformations can be dealt with in a linear fashion with nice simple matrices and such - even though we are dealing with projection.  In terms of OpenGL (and others) we only divide when we go from <em>Clip Space</em> to <em>Normalized Device Space</em> - long after all the 3D transformations have been applied.</p>

CC BY-SA 3.0
2018-02-20T16:17:00.433Z
2018-02-20T16:17:00.433Z
Wyck
<p>This question perhaps has been asked and answered a thousand times, and yet I haven't found any that satisfy me. The reasons are often these:</p>

<p>1/ You need a 4 dimensional vector to work with 4x4 matrices.</p>

<p>2/ You need to have z stored in some way so that you could later use it for z-buffering, etc.</p>

<p>3/ You need a matrix that is independent of z so that you could multiply matrices together and save computations. Instead of having to multiply each vector with each of the matrix, you could multiply 1 result matrix with each of the vector. </p>

<p>Here's the problems I have with each of them.</p>

<ol>
<li><p>We can pretend that the 3 dimensional vector is 4 dimensional (imaginary w = 1). This is after all Computer Science, not math. </p></li>
<li><p>When multiply matrices with vector, we don't need to crush z. Keep it and use it. When drawing, we can pretend that z is already crushed. </p></li>
<li><p>You will have to do division by w after projection matrix anyway. Why not divide by z then and get something like [x/z, y/z, z] (I'm not dividing by z because it will be used for z-buffering). Both of them cost 1 computation. </p></li>
</ol>

<p>So why do we need homogenous divide?</p>

CC BY-SA 3.0
2018-02-15T01:54:52.107Z
"*So why do we need homogenous divide?*" Perhaps the questions you need to ask yourself are 1) what are the alternatives? 2) are they more efficient or more amenable to hardware implementation?
Nicol Bolas
<3d>
What is the use of homogenous divide?
Manh Nguyen Huu
# What is the use of homogenous divide?

(Asked by: username_0 on 2018-02-13)

This question perhaps has been asked and answered a thousand times, and yet I haven't found any that satisfy me. The reasons are often these:

1/ You need a 4 dimensional vector to work with 4x4 matrices.

2/ You need to have z stored in some way so that you could later use it for z-buffering, etc.

3/ You need a matrix that is independent of z so that you could multiply matrices together and save computations. Instead of having to multiply each vector with each of the matrix, you could multiply 1 result matrix with each of the vector.

Here's the problems I have with each of them.

1. We can pretend that the 3 dimensional vector is 4 dimensional (imaginary w = 1). This is after all Computer Science, not math.
2. When multiply matrices with vector, we don't need to crush z. Keep it and use it. When drawing, we can pretend that z is already crushed.
3. You will have to do division by w after projection matrix anyway. Why not divide by z then and get something like [x/z, y/z, z] (I'm not dividing by z because it will be used for z-buffering). Both of them cost 1 computation.

So why do we need homogenous divide?

**Tags:** 3d

> **Comments:**
> **username_1**: "*So why do we need homogenous divide?*" Perhaps the questions you need to ask yourself are 1) what are the alternatives? 2) are they more efficient or more amenable to hardware implementation?  

---

## 3 answers

### Answer by username_2 on 2018-02-14. Score: 7

First of all we need to understand why do we need 4x4 matrices in the first place. With 3x3, we couldn't represent translation as it wasn't a linear transformation (it displaces the origin). So in order to avoid extra work, homogeneous coordinates and affine transformation was introduced.

Now instead of doing

$v' = Lv + t$

where `L` is a linear transform and `t` is the translation, we can do

$v' = Av$

Where `A` is the affine matrix. This makes it cleaner. So 4x4 matrices are a real necessity, we just can't work without them. In order to distinguish between vectors and points we use `w = 1` for points and `w = 0` for vectors. So you are suggesting to make this 4th dimension implicit and don't store it as it'll actually use space/memory.

> We can pretend that the 3 dimensional vector is 4 dimensional (imaginary w = 1). This is after all Computer Science, not math.

This works but up-to a certain extent. Using this approach we would have 4x4 matrices and 3 dimensional row/column vectors. But now when doing multiplication we will have to make a check whether it's point or vector and based on that we multiply the elements of the 4th column of the transformation matrix by `0` or `1`.

This alone starts creating mess, check every time whether it's a point or a vector so why not just use the space for a single float more and get rid of this stupid check.

That aside most modern CPUs have SIMD registers 128 bits wide perfect to fit 4D vectors. If you are doing your calculations on the GPU, all the more reason to store 4D vectors as branching instructions are much more costly on the GPU.

If you start feeling the need to use 4D, great. If not then we still have the problem of composing matrix transformations. Instead of multiplying individual transformations with our vector we would like to pre-multiply all of the transformations then do a single vector-matrix multiplication. This can't work with projective transformations where we need to divide by "something"

Let's come to reason number 3.

> You will have to do division by w after projection matrix anyway. Why not divide by z then and get something like [x/z, y/z, z]. Both of them cost 1 computation.

This is the simple case for just a projective transformation. Consider the vector going through 5 or 6 transformations and in the last comes the projective transformation. If we pre-multiply all these transformation to create a single matrix, you will notice that now when we multiply the vector with this combined transformation matrix the division factor isn't just a simple `-z` value. The 4th row of the matrix won't be `0 0 -1 0` as in the standard projection matrix. It might have changed due to multiplying all the transformations together. Now when you multiply that 4th row with the 4D vector, you will get your `w` value by which you need to divide now.

> **Comments:**
> **username_3**: Good answer. I'd add to the last part, even in the case of a simple projection transform with no other matrix multiplies the Z component doesn't carry over untouched - it ends up in the form A*Z + B, used for near and far clipping and perspective-correct interpolation. So even in the simplest case you still need to store the original Z value somewhere.  
> **username_2**: @username_3 - true that, but thinking from his perspective, even tho the final Z value is A*Z + B, we still have the original vector IF we aren't overwriting/ storing the modified vector in the original variable. So he could argue we still have the original Z value stored. That's why tried to give an explanation where the division factor isn't just "-z" it's something entirely else.  
> **username_4**: "why not just use the space for a single float more and get rid of this stupid check" Why not let the type system keep track of which things are points and which vectors at compile time, and get rid of this stupid extra float that needs to be multiplied and added at runtime   
> **username_4**: Also FYI, to the point about SIMD, storing an xyzw vector as a SIMD register actually isn't best practice. Better is to go SOA and have one register of 4 vectors' X values, another of the 4 Y values, etc. This generalizes a lot better to larger SIMD widths. Note that a lot of newer CPUs have 8-wide SIMD, and GPUs have 32- or 64-wide SIMD.  
> **username_2**: @username_4 - don't understand what you meant by "type system" in your first comment? If you meant something like separate classes for points and vector each having a `*` operator defined for itself and a matrix and the actual `1` or `0` hardcoded inside that function, then it isn't applicable in for example shaders.  

---

### Answer by username_5 on 2018-02-14. Score: 1

Some very quick answers:

> We can pretend that the 3 dimensional vector is 4 dimensional (imaginary w =1). This is after all Computer Science, not math.

Ahh.. but sometimes in graphics we don't have w=1. Some examples that come to mind are

1. Placing a vertex at "infinity", e.g. for shadow volumes
2. Representing directions rather than absolute positions
3. Doing rational curves. e.g. $\frac{Quadratic Bezier()}{Quadratic Bezier()}$ to represent, say, conic sections.

I'm sorry, I've no idea what you mean by *"to crush z"*, but sometimes, if chosen carefully, after the projection transform you may be able to get by with just 3 terms, e.g. (X/W, Y/W, 1/W) assuming you also have the post-projection texture coordinates, (U/W, V/W).

> I'm not dividing by z because it will be used for z-buffering

Typically, despite the name, the Z-buffer contains an interpolated 1/W, 1/Z, or some linear function of one of these.

-

> **Comments:**
> **username_0**: By crush z, I mean making them 0 to make points become 2d  
> **username_1**: @username_0: But the points *never* "become 2d". That's the point. They're *always* three-dimensional positions, even in window-space.  

---

### Answer by username_6 on 2018-02-20. Score: 0

We use projective geometry and homogeneous coordinates so that we can make use of **linear algebra** to do our transformations.

And by the way, this **is** math. I think you should read wikipedia's pages about [Projective Geometry](https://en.wikipedia.org/wiki/Projective_geometry), and the clever idea to introduce a [Point at Infinity](https://en.wikipedia.org/wiki/Point_at_infinity), and use [Homogeneous Coordiantes](https://en.wikipedia.org/wiki/Homogeneous_coordinates) to allow you to deal with projective geometry transformations using **linear algebra** as opposed to dealing with the ugly math required to do transformations after the divide (because projections are non-linear).

At some point, you must divide though, so this technique is a way of deferring that divide to the very end. All the other transformations can be dealt with in a linear fashion with nice simple matrices and such - even though we are dealing with projection. In terms of OpenGL (and others) we only divide when we go from *Clip Space* to *Normalized Device Space* - long after all the 3D transformations have been applied.


---

