glViewport 偏移和正射投影

Posted

技术标签:

【中文标题】glViewport 偏移和正射投影【英文标题】:glViewport offset and ortho projection 【发布时间】:2016-06-01 14:53:15 【问题描述】:

在我发现的所有关于根据视口大小创建投影矩阵的教程中,所有教程都假设视口的左下坐标为 (0,0)。

现在我想绘制到屏幕的不同部分,为此我想相应地切换视口:

glViewport(0,0,windowWidth/2, windowHeight/2); //left bottom
glViewport(0,windowHeight/2,windowWidth/2, windowHeight/2);//left top
glViewport(windowWidth/2,0,windowWidth/2, windowHeight/2);//right bottom
glViewport(windowWidth/2, windowHeight/2,windowWidth/2, windowHeight/2);//right top

现在我在定义我的投影矩阵时遇到了问题。在没有任何 (x,y) 干扰的情况下,我使用此代码来计算我的正射投影矩阵:

if (m_WindowWidth > m_WindowHeight)

    auto viewportAspectRatio = (float)m_WindowWidth / (float)m_WindowHeight;

    m_ProjectionMatrix.m_fLeft = (-1.0f) * m_fWindowSize * viewportAspectRatio;
    m_ProjectionMatrix.m_fRight = m_fWindowSize * viewportAspectRatio;
    m_ProjectionMatrix.m_fBottom = (-1.0f)*m_fWindowSize;
    m_ProjectionMatrix.m_fTop = m_fWindowSize;
    m_ProjectionMatrix.m_fNear = -(10.0f)*m_fWindowSize;
    m_ProjectionMatrix.m_fFar = (10.0f)*m_fWindowSize;

    m_fMoveSpeed = static_cast<GLfloat>(m_fWindowSize * 2 / static_cast<float>(m_WindowHeight));

else

    auto viewportAspectRatio = (float)m_WindowHeight / (float)m_WindowWidth;

    m_ProjectionMatrix.m_fLeft = (-1.0f)*m_fWindowSize;
    m_ProjectionMatrix.m_fRight = m_fWindowSize;
    m_ProjectionMatrix.m_fBottom = (-1.0f)*m_fWindowSize * viewportAspectRatio;
    m_ProjectionMatrix.m_fTop = m_fWindowSize * viewportAspectRatio;
    m_ProjectionMatrix.m_fNear = -(10.0f)*m_fWindowSize;
    m_ProjectionMatrix.m_fFar = (10.0f)*m_fWindowSize;

    m_fMoveSpeed = static_cast<GLfloat>(m_fWindowSize * 2 / static_cast<float>(m_WindowWidth));

这很好直到我将添加任何(x,y)偏移到我的视口。使用glViewport(0, m_WindowHeight/2, m_WindowWidth/2, m_WindowHeight/2时效果如下:

还有glViewport(0, 0, m_WindowWidth/2, m_WindowHeight/2)

我怎样才能让它发挥作用?

【问题讨论】:

【参考方案1】:

首先,纵横比始终是宽/高。

那我想你要找的是:

m_ProjectionMatrix.m_fLeft = x;
m_ProjectionMatrix.m_fRight = x + m_WindowWidth;
m_ProjectionMatrix.m_fBottom = y;
m_ProjectionMatrix.m_fTop = y + m_WindowHeight;
m_ProjectionMatrix.m_fNear = -(10.0f)*m_fWindowSize;
m_ProjectionMatrix.m_fFar = (10.0f)*m_fWindowSize;

看看这个wiki page

【讨论】:

好吧,那行不通。您能否编辑您的帖子并描述您是如何提出这个解决方案的?并且可能共享参考?因为关于正射投影的维基页面没有关于它的信息。【参考方案2】:

我找到了解决这个问题的方法并将其发布在 gamedev 论坛上: https://gamedev.stackexchange.com/questions/122284/glviewport-offset-and-ortho-projection/122289#122289

简而言之: 我将整个场景绘制到帧缓冲区,然后将生成的纹理渲染到屏幕上。此操作导致不必要的 glViewport() 转换累积。

解决方案是在渲染到帧缓冲区之前将 glViewport() 设置为原点,然后在将纹理渲染到屏幕时设置偏移量。

【讨论】:

以上是关于glViewport 偏移和正射投影的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL中投影变换函数的实现

Shadowmap 适用于正射投影,但不适用于透视投影

OpenGL正射投影被破坏

正射投影的问题 | OpenGL

Model, View(Camera), Perspective

QOpenGLWidget的resizeGL不是调用glViewport的地方吗?