使用 Qt/OpenGL 保持正交投影成比例的问题

Problems keeping orthographic projection proportional using Qt/OpenGL

我很难理解我应该在对 QMatrix4x4::ortho(left, right, bottom, top, near, far) 的调用中使用什么值。

具体来说,我不理解有关左、右、下和上值的文档。我有一个可以使用投影矩阵绘制 OpenGL 猴子的工作演示。我设置了演示,以便当我在键盘上按下 'O' 时,它会将投影矩阵从透视切换到正交。透视投影效果很好,因为它使模型的纵横比保持不变(即它不会在宽度或高度上拉伸)。这是调用 'O' 或 'P' 键并更新 m_proj 时调用的函数。如您所见,这有点乱七八糟,我已经尝试了很多想法,none 其中的想法确实按照我想要的方式工作。

感谢任何有助于我理解这一点的见解。其他有用的细节:我的视线位于 z=2 面向中心 (0,0,0),向上为 (0,1,0)。

void AppGLScene::setProjectionMatrix(void)
{
    m_projectionMatrix.setToIdentity();
    float windowWidth = rect().width();
    float windowHeight = rect().height();
    float left, right, bottom, top;
    float aratio = (float) windowWidth / (float) windowHeight;
    qDebug() << "win wid, win hei" << windowWidth << windowHeight;

    // I modify the vertical FOV in an attempt to keep the size of the
    // model the same as the vertical size of the window changes.
    //
    float vFov = 90 * ((float)windowHeight / m_initialWinHeight);
    qDebug() << "vFov" << vFov;

    switch (m_proj)
    {
    case PROJ_PERSP:
        m_projectionMatrix.perspective(vFov, qreal(windowWidth)/qreal(windowHeight), 0.5, 40);
        break;
    case PROJ_ORTHO:
    default:
//        left = rect().x();
//        right = rect().x() + rect().width();
//        bottom = rect().y();
//        top = rect().y() + rect().height();
        if (windowWidth > windowHeight)
        {
            left = -(3.0 - ((float)windowHeight/(float)windowWidth));
            right = -left;
            bottom = -3.0;
            top = 3.0;
        }
        else
        {
            left = -3.0;
            right = 3.0;
            bottom = -(3.0 - ((float)windowWidth/(float)windowHeight));
            top = -bottom;
        }

        qDebug() << "l r b t = " << left << right << bottom << top;
        m_projectionMatrix.ortho(left, right, bottom, top, 0.5, 40);
//        m_projectionMatrix.ortho(-3.0, 3.0, -3.0, 3.0, 0.5, 40);
//        m_projectionMatrix.ortho(-aratio, aratio, -aratio, aratio, 0.5, 40);
        break;
    }
}

为避免在任一方向拉伸对象,您需要 (右 - 左)/(上 - 下) 与 window 的纵横比相匹配.在您的情况下,您可以通过 righttop 的值乘以纵横比来确保。

您似乎想对较短的 window 维度使用范围 [-3.0, 3.0],并相应地调整较长的维度。上面然后翻译成:

    if (windowWidth > windowHeight)
    {
        top = 3.0f;
        bottom = -top;
        right = top * aratio;
        left = -right;
    }
    else
    {
        right = 3.0f;
        left = -right;
        top = right / aratio;
        bottom = -top;
    }

请注意,对于这两种情况,right / top = aratio