【问题标题】:Get Projection Matrix from OpenGL in version 3.3在 3.3 版本中从 OpenGL 获取投影矩阵
【发布时间】:2016-06-15 17:10:39
【问题描述】:

出于兼容性原因,我必须混合使用旧的和现代的 OpenGL 代码。我想从 OpenGL 中检索当前的投影和模型视图矩阵,以使用统一变量将其传递给着色器。

以下代码显示了我仅对投影矩阵执行此操作的尝试。它确实没有按预期工作:

float m[16];
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, aspect, 0.01f, 2.0f);
glGetFloatv(GL_PROJECTION_MATRIX, m);

在这些行之后,矩阵m 包含身份。我使用以下代码检查了这一点:

printf("%f %f %f %f\n", m[0], m[4], m[8],  m[12]);
printf("%f %f %f %f\n", m[1], m[5], m[9],  m[13]);
printf("%f %f %f %f\n", m[2], m[6], m[10], m[14]);
printf("%f %f %f %f\n", m[3], m[7], m[11], m[15]);

我使用freeglut 创建了上下文,并使用以下代码明确请求了 OpenGL 3.3 上下文:

...
glutInitContextVersion(3, 3);
glutCreateWindow(title);

当我将版本更改为 OpenGL 2.0 时,上面的代码按预期工作。上述每个版本都会产生上述问题。

我正在使用 Intel Corporation Broadwell-U Integrated Graphics 开发 Xubuntu。

有人可以解释这种行为吗?有人可以提供解决方案吗?

【问题讨论】:

  • Mesa actually giving you 是在您要求 3.3 时未指定 glutInitContextProfile(GLUT_COMPATIBILITY_PROFILE) 的兼容性上下文吗?还是默默地升级到Core? glGetError()glGetFloatv() 调用之前/之后返回什么?
  • 为什么 StackOverflow 上的每个 OpenGL 问题都被否决了..?这是一个完全合理的问题。
  • 我在创建上下文后检查了版本(感谢链接)。 glGetString(GL_VERSION) 返回 Version: 4.3 (Core Profile) Mesa 12.1.0-devel (git-8c3ecde 2016-06-08 xenial-oibaf-ppa)glGetIntegerv(GL_MAJOR_VERSION/GL_MINOR_VERSION, ...) 告诉我同样的情况。当我明确请求 3.3 上下文时,为什么会得到不同的版本?核心上下文解释了行为。我使用ARB_debug_output 添加了一个错误回调,glMatrixMode 当然是第一个被报告为已弃用的函数。
  • 当我请求 compatibility 上下文时,我在调用 glutCreateWindow 时收到以下错误:X Error of failed request: GLXBadFBConfig Major opcode of failed request: 154 (GLX) Minor失败请求的操作码:34 () 失败请求的序列号:36 输出流中的当前序列号:35

标签: opengl freeglut


【解决方案1】:

>=OpenGL-3.3 兼容性配置文件是一项可选功能,不需要实际支持它。大多数 OpenGL 实现实际上不支持兼容性配置文件。值得注意的例外是 NVidia 和 AMD 的专有驱动程序。因此,将 OpenGL-3.3 与遗留的东西混合起来并不适用于所有系统。

但是你为什么要这样做

float m[16];
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, aspect, 0.01f, 2.0f);
glGetFloatv(GL_PROJECTION_MATRIX, m);

……完全没有?首先,GLU 不是 OpenGL 的一部分,GLU 函数只是内部调用 OpenGL 函数的小帮手。无论如何,gluPerspective 函数非常简单,而且通过 OpenGL 的往返只是为了很好地获取矩阵是很尴尬的(老实说是触发了我的呕吐反射)。

gluPerspective 的核心是确定 glFrustum 的参数:

void gluPerspective(
    double fov,
    double aspect,
    double znear, float zfar)
{
    double const height = znear * tanf(fovyInDegrees * M_PI / 360.0);
    double const width = height * aspect;
    glFrustum(-width, width, -height, height, znear, zfar);
}

就是这样。 glFrustum 本身也很简单。

void glFrustum(double l, double r, double b, double t, double n, double f)
{
    double M[4][4];
    M[0][0] = 2.f*n/(r-l);
    M[0][1] = M[0][2] = M[0][3] = 0.f;

    M[1][1] = 2.*n/(t-b);
    M[1][0] = M[1][2] = M[1][3] = 0.f;

    M[2][0] = (r+l)/(r-l);
    M[2][1] = (t+b)/(t-b);
    M[2][2] = -(f+n)/(f-n);
    M[2][3] = -1.f;

    M[3][2] = -2.f*(f*n)/(f-n);
    M[3][0] = M[3][1] = M[3][3] = 0.f;
    glMultMatrixd(&M[0][0]);
}

重写它以将指向矩阵的指针作为参数很简单,然后您可以直接将其传递给制服。

【讨论】:

  • 感谢您的诚实回答。呕吐反射也存在于此。没错,重写 gluPerspective 或其他投影矩阵显然很容易。我的问题有点误导,因为我的主要目标是为模型视图矩阵执行此操作。这将阻止我重写使用矩阵堆栈和 glRotate、glScale 和 glTranslate 函数的大部分代码。最好的解决方案是使用适当的数学库,如 glm
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-11
  • 1970-01-01
相关资源
最近更新 更多