UE4 & OpenGL坐標(biāo)系

UE4 & OpenGL坐標(biāo)系

UE4 使用左手系(DX),OpenGL固定管線使用右手系,可以通過可編程的管線在OpenGL渲染管線中使用和UE4一樣的左手系。

三維空間的坐標(biāo)系

  • 局部空間(Local Space,或者稱為物體空間(Object Space))
  • 世界空間(World Space)
  • 觀察空間(View Space,或者稱為視覺空間(Eye Space)) 或是視圖坐標(biāo)系
  • 裁剪空間(Clip Space) 或是投影坐標(biāo)系
  • 屏幕空間(Screen Space)

左右手坐標(biāo)系變換在裁剪空間和觀察空間進(jìn)行。

投影坐標(biāo)系

正射投影矩陣

正射投影
正射投影

右手系-正射投影矩陣

正射投影矩陣-右手系
  template<typename T>
    GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> orthoRH_NO(T left, T right, T bottom, T top, T zNear, T zFar)
    {
        mat<4, 4, T, defaultp> Result(1);
        Result[0][0] = static_cast<T>(2) / (right - left);
        Result[1][1] = static_cast<T>(2) / (top - bottom);
        Result[2][2] = - static_cast<T>(2) / (zFar - zNear);
        Result[3][0] = - (right + left) / (right - left);
        Result[3][1] = - (top + bottom) / (top - bottom);
        Result[3][2] = - (zFar + zNear) / (zFar - zNear);
        return Result;
    }

左手系-正射投影矩陣

正射投影矩陣-右手系
template<typename T>
    GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> orthoLH_ZO(T left, T right, T bottom, T top, T zNear, T zFar)
    {
        mat<4, 4, T, defaultp> Result(1);
        Result[0][0] = static_cast<T>(2) / (right - left);
        Result[1][1] = static_cast<T>(2) / (top - bottom);
        Result[2][2] = static_cast<T>(1) / (zFar - zNear);
        Result[3][0] = - (right + left) / (right - left);
        Result[3][1] = - (top + bottom) / (top - bottom);
        Result[3][2] = - zNear / (zFar - zNear);
        return Result;
    }

透視投影

透視投影

透視投影推導(dǎo)

透視投影推導(dǎo)

右手系-透視投影

右手系透視投影
視角和寬高比

透視投影矩陣-右手系
emplate<typename T>
    GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveRH_NO(T fovy, T aspect, T zNear, T zFar)
    {
        assert(abs(aspect - std::numeric_limits<T>::epsilon()) > static_cast<T>(0));

        T const tanHalfFovy = tan(fovy / static_cast<T>(2));

        mat<4, 4, T, defaultp> Result(static_cast<T>(0));
        Result[0][0] = static_cast<T>(1) / (aspect * tanHalfFovy);
        Result[1][1] = static_cast<T>(1) / (tanHalfFovy);
        Result[2][2] = - (zFar + zNear) / (zFar - zNear);
        Result[2][3] = - static_cast<T>(1);
        Result[3][2] = - (static_cast<T>(2) * zFar * zNear) / (zFar - zNear);
        return Result;
    }

左手系-透視投影

透視投影左手系

透視投影-左手
template<typename T>
    GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveLH_ZO(T fovy, T aspect, T zNear, T zFar)
    {
        assert(abs(aspect - std::numeric_limits<T>::epsilon()) > static_cast<T>(0));

        T const tanHalfFovy = tan(fovy / static_cast<T>(2));

        mat<4, 4, T, defaultp> Result(static_cast<T>(0));
        Result[0][0] = static_cast<T>(1) / (aspect * tanHalfFovy);
        Result[1][1] = static_cast<T>(1) / (tanHalfFovy);
        Result[2][2] = zFar / (zFar - zNear);
        Result[2][3] = static_cast<T>(1);
        Result[3][2] = -(zFar * zNear) / (zFar - zNear);
        return Result;
    }

視圖坐標(biāo)系

視圖矩陣的推導(dǎo)
//右手系
template<typename T, qualifier Q>
    GLM_FUNC_QUALIFIER mat<4, 4, T, Q> lookAtRH(vec<3, T, Q> const& eye, vec<3, T, Q> const& center, vec<3, T, Q> const& up)
    {
             //forward:W
        vec<3, T, Q> const f(normalize(center - eye));
              //right:V
        vec<3, T, Q> const s(normalize(cross(f, up)));
              //up:U
        vec<3, T, Q> const u(cross(s, f));

        mat<4, 4, T, Q> Result(1);
        Result[0][0] = s.x;
        Result[1][0] = s.y;
        Result[2][0] = s.z;
        Result[0][1] = u.x;
        Result[1][1] = u.y;
        Result[2][1] = u.z;
        Result[0][2] =-f.x;
        Result[1][2] =-f.y;
        Result[2][2] =-f.z;
        Result[3][0] =-dot(s, eye);
        Result[3][1] =-dot(u, eye);
        Result[3][2] = dot(f, eye);
        return Result;
    }
  //左手系
    template<typename T, qualifier Q>
    GLM_FUNC_QUALIFIER mat<4, 4, T, Q> lookAtLH(vec<3, T, Q> const& eye, vec<3, T, Q> const& center, vec<3, T, Q> const& up)
    {
        vec<3, T, Q> const f(normalize(center - eye));
        vec<3, T, Q> const s(normalize(cross(up, f)));
        vec<3, T, Q> const u(cross(f, s));

        mat<4, 4, T, Q> Result(1);
        Result[0][0] = s.x;
        Result[1][0] = s.y;
        Result[2][0] = s.z;
        Result[0][1] = u.x;
        Result[1][1] = u.y;
        Result[2][1] = u.z;
        Result[0][2] = f.x;
        Result[1][2] = f.y;
        Result[2][2] = f.z;
        Result[3][0] = -dot(s, eye);
        Result[3][1] = -dot(u, eye);
        Result[3][2] = -dot(f, eye);
        return Result;
    }

參考文章

  1. 投影矩陣推導(dǎo)過程
  2. UE4 & OpenGL坐標(biāo)系
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容