OpenGL:正交投影

OpenGL: Orthographic Projection

我正在尝试将正交投影用于我的 GUI 渲染。当我只使用我的常规变换矩阵绘制网格时,我得到了我期望的结果,但是当我使用我的正交投影时,我什么也得不到。我的透视投影也很好用。我的邻位矩阵:

public Matrix4f initOrthographic(float left, float right, float bottom, float top, float near, float far)
{
    m[0][0] = 2.0f / (right - left);    m[0][1] = 0;                        m[0][2] = 0;                    m[0][3] = (left + right) / (left - right);
    m[1][0] = 0;                        m[1][1] = 2.0f / (top - bottom);    m[1][2] = 0;                    m[1][3] = (bottom + top) / (bottom - top);
    m[2][0] = 0;                        m[2][1] = 0;                        m[2][2] = 2.0f / (near - far);  m[2][3] = (far + near) / (far - near);
    m[3][0] = 0;                        m[3][1] = 0;                        m[3][2] = 0;                    m[3][3] = 1;

    return this;
}

我这辈子都查不出哪里出了问题。我将这个矩阵乘以常规变换,然后将该矩阵乘以着色器中的顶点位置。有任何想法吗?如果需要,我可以 post 更多 code/information。

我想我刚刚发现了问题。我的顶部为 0,底部为 720,当我将这些值翻转为 720 顶部和 0 底部时,它工作得很好。唯一的问题是我希望左上角为 (0, 0)。有什么办法可以做到这一点,还是我一直停留在左下角 (0, 0)?

我的正交矩阵看起来和你的很不一样:

      2.0f / (right - left)                          0                                    0                      0
                0                          2.0f / (top - bottom)                          0                      0
                0                                    0                           2.0f / (zFar - zNear)           0
-(right + left) / (right - left)     -(top + bottom) / (top - bottom)    -(zFar + zNear) / (zFar - zNear)        1

重要的是如何存储这些值。如果您要为矩阵使用单个浮点数组,则可以这样存储它:

float orthoMat[] =
{
    2.0f / (right - left),
    0,
    0,
    0,

    0,
    2.0f / (top - bottom),
    0,
    0,

    0,
    0,
    2.0f / (zFar - zNear),
    0,

    -(right + left) / (right - left),
    -(top + bottom) / (top - bottom),
    -(zFar + zNear) / (zFar - zNear),
    1
};

这是 OpenGL 希望您传递给着色器的布局。这是列主要约定。 DirectX 使用行优先约定。所以基本上我的矩阵可以从左到右、下一行、从左到右阅读,而你的矩阵应该从上到下、下一列、从上到下阅读。如果你转置你的矩阵,你得到的矩阵几乎和我一样。然而,我们的矩阵之间存在一些差异,即使在转置时也是如此:

在你的代码中

- m[2][2] should be 2.0f / (zFar - zNear)
- m[0][3], m[1][3] and m[2][3] should be negative

只要您解决矩阵的这些问题并确保在将矩阵传递给着色器时元素的顺序正确,您仍然可以使用矩阵实现。请记住元素 12、13 和 14 存储翻译。如果您对所有这些 row-major/column-major 内容感到困惑,请阅读 this 关于它的简短文章,其中解释得非常好。我强烈推荐它。