Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get Projection Matrix from OpenGL in version 3.3

For compatibility reasons I have to mix old and modern OpenGL code. I would like to retrieve the current projection- and modelview-matrix from OpenGL to pass it to the shader by using a uniform-variable.

The following code shows my attempt to do that for the projection-matrix only. It does not work as intended:

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

After these lines Matrix m contains the identity. I checked this using the following code:

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

I created the context using freeglut and explicitly requested an OpenGL 3.3 context using the following code:

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

When I change the version to OpenGL 2.0 the code above works as expected. Every version above produces the described problem.

I'm working on Xubuntu using an Intel Corporation Broadwell-U Integrated Graphics.

Can someone explain this behaviour? Can someone offer a solution?

like image 481
Henkk Avatar asked Oct 28 '25 10:10

Henkk


1 Answers

The >=OpenGL-3.3 compatibility profiles are an optional feature and there's no requirement to actually support it. Most OpenGL implementations actually don't support the compatibility profiles. The notable exceptions are the proprietary drivers of NVidia and AMD. Hence mixing OpenGL-3.3 with legacy stuff will not work reliably for all systems.

But why are you doing that

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

… at all? First and foremost GLU is not part of OpenGL and GLU functions are just little helpers that internally call OpenGL functions. Anyway the gluPerspective function is extremely simple and the roundtrip through OpenGL just to get the matrix well is awkward (and to be honest is triggering my gag reflex).

At its core gluPerspective is determining parameters for 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);
}

That's all it does. glFrustum itself is very simple as well.

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]);
}

It's trivial to rewrite this to take a pointer to a matrix as a parameter which you then can directly pass to a uniform.

like image 95
datenwolf Avatar answered Oct 30 '25 14:10

datenwolf