美文网首页
UE4 & OpenGL坐标系

UE4 & OpenGL坐标系

作者: wblong | 来源:发表于2021-04-17 15:55 被阅读0次

    UE4 & OpenGL坐标系

    UE4 使用左手系(DX),OpenGL固定管线使用右手系,可以通过可编程的管线在OpenGL渲染管线中使用和UE4一样的左手系。

    三维空间的坐标系

    • 局部空间(Local Space,或者称为物体空间(Object Space))
    • 世界空间(World Space)
    • 观察空间(View Space,或者称为视觉空间(Eye Space)) 或是视图坐标系
    • 裁剪空间(Clip Space) 或是投影坐标系
    • 屏幕空间(Screen Space)

    左右手坐标系变换在裁剪空间和观察空间进行。

    投影坐标系

    正射投影矩阵

    正射投影 正射投影

    右手系-正射投影矩阵

    正射投影矩阵-右手系
      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;
        }
    

    透视投影

    透视投影
    透视投影推导
    透视投影推导

    右手系-透视投影

    右手系透视投影 视角和宽高比
    透视投影矩阵-右手系
    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;
        }
    

    视图坐标系

    视图矩阵的推导
    //右手系
    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. 投影矩阵推导过程
    2. UE4 & OpenGL坐标系

    相关文章

      网友评论

          本文标题:UE4 & OpenGL坐标系

          本文链接:https://www.haomeiwen.com/subject/wzaulltx.html