gluPerspective was removed in OpenGL 3.1, any replacements?
Asked Answered
A

5

31

I'm trying to read some OpenGL tutorials on the net. the problem is that I found some old ones that use gluPerspective(). gluPerspective was deprecated in OpenGL 3.0 and removed in 3.1.

What function can I use instead?

I'm using C++ with latest FreeGlut installed.

Ante answered 10/3, 2010 at 14:39 Comment(1)
I know it's pedantic, but gluPerspective has never been part of OpenGL (hence the glu prefix). glFrustum was, and has been deprecated.Infralapsarian
P
30

You have to compute the matrix manually and then pass it to OpenGL.

Computing the matrix

This snippet of code is based on the gluPerspective documentation.

 void BuildPerspProjMat(float *m, float fov, float aspect,
 float znear, float zfar)
 {
  float f = 1/tan(fov * PI_OVER_360);

  m[0]  = f/aspect;
  m[1]  = 0;
  m[2]  = 0;
  m[3]  = 0;

  m[4]  = 0;
  m[5]  = f;
  m[6]  = 0;
  m[7]  = 0;

  m[8]  = 0;
  m[9]  = 0;
  m[10] = (zfar + znear) / (znear - zfar);
  m[11] = -1;

  m[12] = 0;
  m[13] = 0;
  m[14] = 2*zfar*znear / (znear - zfar);
  m[15] = 0;
 }

There is a C++ library called OpenGL Mathematics that may be useful.

Loading the Matrix in OpenGL 3.1

I am still new to the OpenGL 3.1 API, but you need to update a matrix on the GPU and then make use of it in your vertex shader to get the proper perspective. The following code just loads the matrix using glUniformMatrix4fv onto the video card.

{
  glUseProgram(shaderId);
  glUniformMatrix4fv(glGetUniformLocation(shaderId, "u_proj_matrix"),
                     1, GL_FALSE, theProjectionMatrix);
  RenderObject();
  glUseProgram(0);
}

A simple vertex shader from a random blog (found through stack overflow).

attribute vec4      a_position;
attribute vec4      a_color;

varying vec4        v_color;

uniform mat4 u_proj_matrix;
uniform mat4 u_model_matrix;

void main() {
  mat4 mvp_matrix = u_proj_matrix * u_model_matrix;
  v_color = a_color;
  gl_Position = mvp_matrix * a_position;
}
Phylis answered 10/3, 2010 at 17:50 Comment(7)
thank you :) that opengl mathematics library seems not bad at all.Ante
This function doesn't work. What is xmax and ymax? They're used on the second line and not definedRamulose
I followed the article sources back to the original, which is in French: xgouchet.fr/blog/index.php/post/2009/07/27/…. It sets ymax = znear * tan(fov * PI_OVER_360); and gets via xmax = ymax * aspect. ymin = -ymax; xmin = ymin * aspect;Phylis
I worked through the maths for gluPerspective and glFrustum. It may be neater to write width = xmax-xmin and height = ymax-ymin; following which the line w = w/aspect will not be required.Moulmein
I want to add, that as koan states, w = w/aspect MUST be removed from the computation as it stands now for the matrix to work correctly. I used this matrix myself and couldn't figure out why the aspect was wrong whenever I used anything other than 1 as aspect. Also width = xymax - xmin should be width = xmax - xmin, and height = xymax - ymin should be height = ymax - ymin.Aracelis
It should also be pointed out that "fov" is the vertical fov. It's easy to accidentally specify the horizontal fov, as that's typically what games speak in terms of.Oujda
Could someone who has tested this please edit the appropriate changes instead of making a large change log in the comments.Yevetteyew
A
11

Use GLM.

glm::mat4 projection = glm::perspective(
  // FOV & aspect
  60.0f, 16.0f / 10.0f, 
  // Near and far planes
  0.001f, 1000f);

// If you're using the now deprecated matrix stacks
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(glm::value_ptr(projection));

// if you're using the new shader based pipelines
GLint projectionUniformLocation = ...;
glUniformMatrix4fv(projectionUniformLocation, 1, GL_FALSE, 
  glm::value_ptr(projection));

Note, if you have GLM_FORCE_RADIANS defined then you should use radians in the perspective function, not degrees...

glm::mat4 projection = glm::perspective(
  // FOV & aspect
  PI / 3.0f, 16.0f / 10.0f, 
  // Near and far planes
  0.001f, 1000f);
Anastasio answered 28/10, 2013 at 23:46 Comment(1)
Note that starting from GLM 0.9.6.0, GLM_FORCE_RADIANS is no longer need nor supported, since GLM now works only with radians.Gamecock
P
9

Copied from one of my older projects:

// The following code is a fancy bit of math that is eqivilant to calling:
// gluPerspective( fieldOfView/2.0f, width/height , 0.1f, 255.0f )
// We do it this way simply to avoid requiring glu.h
GLfloat zNear = 0.1f;
GLfloat zFar = 255.0f;
GLfloat aspect = float(width)/float(height);
GLfloat fH = tan( float(fieldOfView / 360.0f * 3.14159f) ) * zNear;
GLfloat fW = fH * aspect;
glFrustum( -fW, fW, -fH, fH, zNear, zFar );
Pierides answered 10/3, 2010 at 14:46 Comment(3)
Except glFrustum() was deprecated in 3.1 also.Kafiristan
why do you divide the fieldOfView by 2.0f in gluPerspective. It is specified in the specs that you should use the full fov...Isotope
@Kafiristan Yes, modern OpenGL requires you to deal in matrices for transformation.Untie
S
0

This is a modified version of Dan's function, with simplified calculations from Unspecified Behavior.

void buildPerspProjMat(GLfloat *m, GLfloat fov, GLfloat aspect,
GLfloat znear, GLfloat zfar){

  GLfloat h = tan(fov);
  GLfloat w = h / aspect;
  GLfloat depth = znear - zfar;
  GLfloat q = (zfar + znear) / depth;
  GLfloat qn = 2 * zfar * znear / depth;

  m[0]  = w;  m[1]  = 0;  m[2]  = 0;  m[3]  = 0;

  m[4]  = 0;  m[5]  = h;  m[6]  = 0;  m[7]  = 0;

  m[8]  = 0;  m[9]  = 0;  m[10] = q;  m[11] = -1;

  m[12] = 0;  m[13] = 0;  m[14] = qn;  m[15] = 0;
}
Sri answered 27/10, 2013 at 0:22 Comment(2)
I think you missed the bit where f (h in your code) = 1/tan(fovy/2) which is mentioned on the link you provide.Yevetteyew
Also, tan needs to be performed on radians, not degrees. Now the results match that of Dan's and my own code.Yevetteyew
U
-1

The formula for various perspective matrices is documented in the Direct3D documentation.

Here is the formulation for D3DXMatrixPerspectiveFovRH, the right-handed perspective projection matrix:

yScale = cot(fovY/2)
xScale = yScale / aspect ratio

xScale     0          0              0
0        yScale       0              0
0        0        zf/(zn-zf)        -1
0        0        zn*zf/(zn-zf)      0
Untie answered 1/12, 2012 at 17:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.