Page 1 of 1

### Yet another glOrtho, glFrustum & gluPerspective (OpenGL)

Posted: Sun Dec 02, 2012 9:29 pm
I've done a little bit of clean-up in my OpenGL projection routines and put the resulting source code here (see below). You might find it handy if you are looking for a replacement for glOrtho, glFrustum or gluPerspective, especially if you've just switched from the fixed to programmable graphics pipeline and found out that these routines are not available any more.

ma_matrix4_projection.h
ma_matrix4_projection.inl

glOrtho() equivalent:
Code: Select all
``template <typename T>inline Matrix4<T> make_ortho(T left, T right, T bottom, T top, T znear, T zfar){    // from OpenGL spec PDF:                                 can be rewritten as:    // / 2/(r-l)     0        0       -(r+l)/(r-l)  \        / 2/(r-l)     0        0      (r+l)/(l-r)  \    // |   0      2/(t-b)     0       -(t+b)/(t-b)  |   =>   |   0      2/(t-b)     0      (t+b)/(b-t)  |    // |   0         0     -2/(f-n)   -(f+n)/(f-n)  |        |   0         0     2/(n-f)   (f+n)/(n-f)  |    // \   0         0        0             1       /        \   0         0        0           1       /    // invalid for: l=r, b=t, or n=f    FS_ASSERT(left != right);    FS_ASSERT(bottom != top);    FS_ASSERT(znear != zfar);    const T p_fn = zfar + znear;    const T m_nf = znear - zfar; // ~ -m_fn    const T p_rl = right + left;    const T m_rl = right - left;    const T p_tb = top + bottom;    const T m_tb = top - bottom;    const T m_lr = -m_rl;    const T m_bt = -m_tb;    return Matrix4<T>(     T(2)/m_rl,    T(0),       T(0),     p_rl/m_lr,       T(0),     T(2)/m_tb,    T(0),     p_tb/m_bt,       T(0),       T(0),     T(2)/m_nf,  p_fn/m_nf,       T(0),       T(0),       T(0),       T(1)    );}``

glFrustum() equivalent:
Code: Select all
``template <typename T> inline Matrix4<T> make_frustum(T left, T right, T bottom, T top, T znear, T zfar){    // from OpenGL spec PDF:                                     can be rewritten as:    // /  2n/(r-l)    0        (r+l)/(r-l)       0      \        /  2n/(r-l)    0        (r+l)/(r-l)       0      \    // |     0     2n/(t-b)    (t+b)/(t-b)       0      |   =>   |     0     2n/(t-b)    (t+b)/(t-b)       0      |    // |     0        0       -(f+n)/(f-n)  -2fn/(f-n)  |        |     0        0        (f+n)/(n-f)   2fn/(n-f)  |    // \     0        0            -1            0      /        \     0        0            -1            0      /    // invalid for: n<=0, f<=0, l=r, b=t, or n=f    FS_ASSERT(znear > T(0));    FS_ASSERT(zfar > T(0));    FS_ASSERT(left != right);    FS_ASSERT(bottom != top);    FS_ASSERT(znear != zfar);    const T x_2n = znear + znear;    const T x_2nf = T(2) * znear * zfar;    const T p_fn = zfar + znear;    const T m_nf = znear - zfar; // ~ -m_fn    const T p_rl = right + left;    const T m_rl = right - left;    const T p_tb = top + bottom;    const T m_tb = top - bottom;    return Matrix4<T>(     x_2n/m_rl,    T(0),     p_rl/m_rl,    T(0),       T(0),     x_2n/m_tb,  p_tb/m_tb,    T(0),       T(0),       T(0),     p_fn/m_nf,  x_2nf/m_nf,       T(0),       T(0),       T(-1),      T(0)    );}``

gluPerspective() equivalent:
Code: Select all
``template <typename T> inline Matrix4<T> make_perspective(T fovy_deg, T aspect, T znear, T zfar){    // from OpenGL spec PDF:                             can be rewritten as:    // /    c/a    0        0            0       \       /    c/a    0         0           0      \    // |     0     c        0            0       |  ==>  |     0     c         0           0      |    // |     0     0   -(f+n)/(f-n)  -2nf/(f+n)  |       |     0     0    (f+n)/(n-f)  2nf/(n-f)  |    // \     0     0       -1            0       /       \     0     0        -1           0      /    FS_ASSERT(znear > T(0));    FS_ASSERT(zfar > T(0));    FS_ASSERT(aspect != T(0));    FS_ASSERT(znear != zfar);    const T half_fovy_rad = T(M_PI) * fovy_deg / T(360);    const auto si_co = sin_cos(half_fovy_rad);    const T si = si_co.first;    const T co = si_co.second;    FS_ASSERT(si != T(0));    const T c = co / si; // cotangent    const T a = aspect;    const T x_2nf = T(2) * znear * zfar;    const T p_fn = zfar + znear;    const T m_nf = znear - zfar;    return Matrix4<T>(     c/a,    T(0),     T(0),       T(0),     T(0),    c,       T(0),       T(0),     T(0),   T(0),  p_fn/m_nf,  x_2nf/m_nf,     T(0),   T(0),     T(-1),      T(0)    );}``