12
\$\begingroup\$

When I set gl_Position I usually assign it such as gl_Position = vec4(in_position, 1.0) where in_position as a vector of three components representing a vertex of my model.

But looking up tutorials and such I cannot find anything explaining what the 4th component of the gl_Position vec4 is doing aside from making the vector big enough so matrix transformations can be applied to it.

Q: What can I do with the 4th component of gl_Position / what does it influence in the rendering process?

\$\endgroup\$
5
  • 1
    \$\begingroup\$ Just a comment since I'm not entirely sure. But if I remember correctly a vector can either be a position or a direction. When the 4th parameter is 1 it is treated as position and when it's 0 as direction. But of course it depends on context how it's used. This is more a convention. \$\endgroup\$
    – Skalli
    Jan 11 '18 at 13:52
  • 1
    \$\begingroup\$ gl_Position = vec4(in_position, 1.0) Do you actually do it in the shader? No matrix transformations? Do you really mean gl_Position = u_matrix * vec4(in_position, 1.0);? \$\endgroup\$ Jan 11 '18 at 14:23
  • \$\begingroup\$ @HolyBlackCat naturally there are some matrix multiplications for view and projection transformations, but I did not see any point in bloating the example with them. \$\endgroup\$
    – dot_Sp0T
    Jan 11 '18 at 14:24
  • 1
    \$\begingroup\$ @dot_Sp0T If you have used a perspective projection matrix, after that multiplication gl_Position.w will no longer be equal to 1, and the perspective division will happen. Not sure if it helps or you ask about a completely different thing. \$\endgroup\$ Jan 11 '18 at 14:30
  • \$\begingroup\$ @HolyBlackCat that is a good point. The idea behind the question is probably best described as 'finding out what that value does in the end' - I will amend the question \$\endgroup\$
    – dot_Sp0T
    Jan 11 '18 at 14:34
10
\$\begingroup\$

gl_Position is a Homogeneous coordinates. Homogeneous coordinates are needed for perspective projection.

Note, if a vector vec4(x, y, z, 1.0) is multiplied by a perspective projection matrix, this results in a Homogeneous coordinates.

The projection matrix describes the mapping from 3D points of a scene, to 2D points of the viewport. The projection matrix transforms from view space to the clip space. The coordinates in the clip space are transformed to the normalized device coordinates (NDC) in the range (-1, -1, -1) to (1, 1, 1) by dividing with the w component of the clip coordinates.
At Perspective Projection the projection matrix describes the mapping from 3D points in the world as they are seen from of a pinhole camera, to 2D points of the viewport.
The eye space coordinates in the camera frustum (a truncated pyramid) are mapped to a cube (the normalized device coordinates).

enter image description here

This means the position in normalized device space is calculated like this:

vec3 ndc = gl_Position.xyz / gl_Position.w;

If you manually set the w component of gl_Position, this causes a reciprocal scaling of the position in normalized device space.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ so, what would modifying the w component do if anything at all? \$\endgroup\$
    – dot_Sp0T
    Jan 13 '18 at 10:42
  • \$\begingroup\$ @dot_Sp0T A reciprocal scaling of the normalized device coordinates. See the answer. \$\endgroup\$
    – Rabbid76
    Jan 13 '18 at 10:51
  • 3
    \$\begingroup\$ sweet, now I only need to find out what 'reciprocal' means. +1 \$\endgroup\$
    – dot_Sp0T
    Jan 13 '18 at 10:53
  • 2
    \$\begingroup\$ @dot_Sp0T In math reciprocal means * 1.0/x in compare to * x. The reciprocal of x is 1.0/x. \$\endgroup\$
    – Rabbid76
    Jan 13 '18 at 10:55
11
\$\begingroup\$

It's not particularly useful for you but you should definitely leave it at 1. It's used when applying transformations to the model.

Matrix multiplication can only multiply numbers, it can't add. That makes moving objects impossible unless the 4th component exists. Let's look at an example: If we want to move the vector

$$\vec v = \begin{bmatrix}a \\ b\\c\end{bmatrix}$$

by

$$\vec d = \begin{bmatrix}x\\y\\z\end{bmatrix}$$

Then we use the

$$T = \begin{bmatrix} 1 & 0 & 0 & x\\ 0 & 1 & 0 & y\\ 0 & 0 & 1 & z\\ 0 & 0 & 0 & 1 \end{bmatrix}$$

matrix and give \$\vec v\$ a fourth component. When we multiply them together, then the result is going to be

$$ \vec r = T\space \cdot\space\vec v = \begin{bmatrix} 1 \cdot a + 0 \cdot b + 0 \cdot c + x \cdot 1\\ 0 \cdot a + 1 \cdot b + 0 \cdot c + y \cdot 1\\ 0 \cdot a + 0 \cdot b + 1 \cdot c + z \cdot 1\\ 0 \cdot a + 0 \cdot b + 0 \cdot c + 1 \cdot 1\\ \end{bmatrix} = \begin{bmatrix} a + x\\ b + y\\ c + z\\ 1 \end{bmatrix} $$

The second use for the 4th component is perspective division. A projection matrix basically normalizes and copies the z component to the w. OpenGL then automatically divides the x, y and z components by it.

\$\endgroup\$
1
  • \$\begingroup\$ A (simplified) real-world example of use of this knowledge can be seen in my answer here, where I convert clip coordinates down to screen coordinates, round them and convert back. \$\endgroup\$
    – Ruslan
    Jan 1 '20 at 14:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.