Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

glm::perspective explanation

I am trying to understand what the following code does:

glm::mat4 Projection = glm::perspective(35.0f, 1.0f, 0.1f, 100.0f); 

Does it create a projection matrix? Clips off anything that is not in the user's view? I wasn't able to find anything on the API page, and the only thing I could find in the pdf on their website was this:

gluPerspective:

glm::mat4 perspective(float fovy, float aspect, float zNear, float zFar); glm::dmat4 perspective( double fovy, double aspect, double zNear, double zFar); From GLM_GTC_matrix_transform extension: <glm/gtc/matrix_transform.hpp> 

But it doesn't explain the parameters. Maybe I missed something.

like image 502
Trt Trt Avatar asked Nov 13 '11 22:11

Trt Trt


People also ask

What is perspective in OpenGL?

Perspective Projection in OpenGL In the end, only the ratio between the size of the image plane and the focal length is important, which is uniquely defined by the opening angle \Theta. All configurations with the same opening angle result in the same image (only with scaled x- and y-coordinates).

What is perspective matrix?

The camera's field of view and image aspect ratio are used to calculate the left, right, bottom and top coordinates which are themselves used in the construction of the perspective projection matrix. This how, they indirectly contribute to modifying how much of the scene we see through the camera.

Which of the OpenGL function is used for the perspective viewing?

OpenGL used a function called glFrustum to create perspective projection matrices. This call takes as arguments, the left, right, bottom and top coordinates in addition to the near and far clipping planes.


2 Answers

It creates a projection matrix, i.e. the matrix that describes the set of linear equations that transforms vectors from eye space into clip space. Matrices really are not black magic. In the case of OpenGL they happen to be a 4-by-4 arrangement of numbers:

X_x Y_x Z_x T_x X_y Y_y Z_y T_y X_z Y_z Z_z T_z X_w Y_w Z_w W_w 

You can multply a 4-vector by a 4×4 matrix:

v' = M * v  v'_x = M_xx * v_x + M_yx * v_y + M_zx * v_z + M_tx * v_w v'_y = M_xy * v_x + M_yy * v_y + M_zy * v_z + M_ty * v_w v'_z = M_xz * v_x + M_yz * v_y + M_zz * v_z + M_tz * v_w v'_w = M_xw * v_x + M_yw * v_y + M_zw * v_z + M_tw * v_w 

After reaching clip space (i.e. after the projection step), the primitives are clipped. The vertices resulting from the clipping are then undergoing the perspective divide, i.e.

v'_x = v_x / v_w v'_y = v_y / v_w v'_z = v_z / v_w ( v_w = 1 = v_w / v_w ) 

And that's it. There's really nothing more going on in all those transformation steps than ordinary matrix-vector multiplication.

Now the cool thing about this is, that matrices can be used to describe the relative alignment of a coordinate system within another coordinate system. What the perspective transform does is, that it let's the vertices z-values "slip" into their projected w-values as well. And by the perspective divide a non-unity w will cause "distortion" of the vertex coordinates. Vertices with small z will be divided by a small w, thus their coordinates "blow" up, whereas vertices with large z will be "squeezed", which is what's causing the perspective effect.

like image 116
datenwolf Avatar answered Oct 11 '22 04:10

datenwolf


This is a c standalone version of the same function. This is roughly a copy paste version of the original.

# include <math.h> # include <stdlib.h> # include <string.h>  typedef struct s_mat {     float *array;     int width;     int height; } t_mat;  t_mat *mat_new(int width, int height) {     t_mat *to_return;      to_return = (t_mat*)malloc(sizeof(t_mat));     to_return->array = malloc(width * height * sizeof(float));     to_return->width = width;     to_return->height = height;     return (to_return); }  void mat_zero(t_mat *dest) {     bzero(dest->array, dest->width * dest->height * sizeof(float)); }  void mat_set(t_mat *m, int x, int y, float val) {     if (m == NULL || x > m->width || y > m->height)         return ;     m->array[m->width * (y - 1) + (x - 1)] = val; }  t_mat *mat_perspective(float angle, float ratio,         float near, float far) {     t_mat *to_return;     float tan_half_angle;      to_return = mat_new(4, 4);     mat_zero(to_return);     tan_half_angle = tan(angle / 2);     mat_set(to_return, 1, 1, 1 / (ratio * tan_half_angle));     mat_set(to_return, 2, 2, 1 / (tan_half_angle));     mat_set(to_return, 3, 3, -(far + near) / (far - near));     mat_set(to_return, 4, 3, -1);     mat_set(to_return, 3, 4, -(2 * far * near) / (far - near));     return (to_return); } 
like image 27
Moebius Avatar answered Oct 11 '22 05:10

Moebius