透视投影将立方体变成奇怪的电视形长方体

Perspective projection turns cube into weird tv shaped cuboid

这是我的透视投影矩阵代码

inline m4
Projection(float WidthOverHeight, float FOV)
{
    float Near = 1.0f;
    float Far = 100.0f;

    float f = 1.0f/(float)tan(DegToRad(FOV / 2.0f));
    float fn = 1.0f / (Near - Far);


    float a = f / WidthOverHeight;
    float b = f;
    float c = Far * fn;
    float d = Near * Far * fn;

    m4 Result = 
    {
        {{a, 0, 0, 0},
         {0, b, 0, 0},
         {0, 0, c, -1},
         {0, 0, d, 0}}
    };
    return Result;
}

这是主要代码

    m4 Project = Projection(ar, 90);
    m4 Move = {};
    CreateMat4(&Move,
        1, 0, 0, 0,
        0, 1, 0, 0,
        0, 0, 1, -2,
        0, 0, 0, 1);
    m4 Rotate = Rotation(Scale);
    Scale += 0.01f;

    m4 FinalTransformation = Project * Move * Rotate;
    SetShaderUniformMat4("Project", FinalTransformation, ShaderProgram);

Here是一些立方体旋转的图片。 在着色器代码中,我只是将变换乘以位置(变换在左侧)。

我不确定它是否有帮助,但这是旋转代码:

float c = cos(Angle);
float s = sin(Angle);
m4 R =
{
    {{ c, 0, s, 0},
     { 0, 1, 0, 0},
     {-s, 0, c, 0},
     { 0, 0, 0, 1}}
};
return R;

我尝试在着色器代码中而不是在 C++ 端乘以矩阵,但随后一切都消失了。

OpenGL 矩阵按列主要顺序存储。您必须从左到右阅读 。例如,矩阵 R 的第一列是 { c, 0, s, 0},第二列是 { 0, 1, 0, 0},第三列是 {-s, 0, c, 0},第四列是 { 0, 0, 0, 1}。您代码中的行实际上是列(而不是行)。
因此,您需要转置投影矩阵 (Project) 和平移矩阵 (Move)。