gluPerspective 在 OpenGL 3.1 中被删除,有啥替代品吗?

Posted

技术标签:

【中文标题】gluPerspective 在 OpenGL 3.1 中被删除,有啥替代品吗?【英文标题】:gluPerspective was removed in OpenGL 3.1, any replacements?gluPerspective 在 OpenGL 3.1 中被删除,有什么替代品吗? 【发布时间】:2011-01-25 22:31:03 【问题描述】:

我正在尝试阅读网上的一些 OpenGL 教程。问题是我发现了一些旧的使用gluPerspective()。 gluPerspective 在 OpenGL 3.0 中已被弃用,并在 3.1 中被移除。

我可以用什么函数代替?

我正在使用安装了最新 FreeGlut 的 C++。

【问题讨论】:

我知道这是迂腐的,但 gluPerspective 从来都不是 OpenGL 的一部分(因此是 glu 前缀)。 glFrustum 曾经并且已经被弃用。 【参考方案1】:

您必须手动计算矩阵,然后将其传递给 OpenGL。

计算矩阵

这个sn-p的代码基于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;
 

有一个名为 OpenGL Mathematics 的 C++ 库可能很有用。

在 OpenGL 3.1 中加载矩阵

我还是 OpenGL 3.1 API 的新手,但是您需要更新 GPU 上的矩阵,然后在顶点着色器中使用它以获得正确的透视。以下代码只是使用glUniformMatrix4fv 将矩阵加载到视频卡上。


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

来自随机blog 的简单顶点着色器(通过堆栈溢出找到)。

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;

【讨论】:

谢谢 :) opengl 数学库似乎一点也不差。 这个功能不起作用。什么是 xmax 和 ymax?它们在第二行使用,未定义 我完成了 gluPerspective 和 glFrustum 的数学运算。写成 width = xmax-xmin 和 height = ymax-ymin 可能更简洁;之后不需要 w = w/aspect 行。 我想补充一点,正如 koan 所说,w = w/aspect 必须从计算中删除,因为它现在代表矩阵正常工作。我自己使用了这个矩阵,但当我使用 1 以外的任何东西作为方面时,我无法弄清楚为什么方面是错误的。另外width = xymax - xmin 应该是width = xmax - xminheight = xymax - ymin 应该是height = ymax - ymin 还要指出,“fov”是vertical fov。很容易意外指定水平 fov,因为这通常是游戏所说的。【参考方案2】:

使用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));

注意,如果您定义了GLM_FORCE_RADIANS,那么您应该在透视函数中使用弧度,而不是度...

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

【讨论】:

请注意,从 GLM 0.9.6.0 开始,不再需要也不支持 GLM_FORCE_RADIANS,因为 GLM 现在仅适用于弧度。【参考方案3】:

从我的一个旧项目中复制:

// 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 );

【讨论】:

除了 glFrustum() 在 3.1 中也被弃用了。 为什么在 gluPerspective 中将 fieldOfView 除以 2.0f。在规范中指定您应该使用完整的 fov... @genpfault 是的,现代 OpenGL 要求您处理 矩阵 进行转换。【参考方案4】:

这是 Dan 函数的修改版本,简化了 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;

【讨论】:

我认为您错过了您提供的链接中提到的 f (h in your code) = 1/tan(fovy/2) 的位。 另外,tan 需要在弧度上执行,而不是度数。现在结果与 Dan 和我自己的代码相匹配。【参考方案5】:

各种透视矩阵的公式记录在the Direct3D documentation。

这是D3DXMatrixPerspectiveFovRH的公式,右手透视投影矩阵:

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

【讨论】:

以上是关于gluPerspective 在 OpenGL 3.1 中被删除,有啥替代品吗?的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL函数解析之gluPerspective()

OpenGL的gluPerspective函数详解[转]

QT 开发opengl 错误1

openGL学习过程中资料总结

OpenGL中矩阵乘法的顺序

裁剪平面附近的 OpenGL