1
\$\begingroup\$

In all tutorials I found about creating projection matrix based on viewport size all of them assumed that left bottom coordinates of viewport will be (0,0).

Now I want to draw to the different parts of the screen and for that purpose I want to switch viewports accordingly:

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

Now I have a problem with defining my projection matrix. Without having any (x,y) offest I was using this code for calculating my ortho projection matrix:

float m_fWindowSize = 15.0f;

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));
}

And this works fine UNTIL I will add any (x,y) offset to my viewport. The effect is following when using glViewport(0, m_WindowHeight/2, m_WindowWidth/2, m_WindowHeight/2):

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

And with glViewport(0, 0, m_WindowWidth/2, m_WindowHeight/2): glViewport(0, 0,  m_WindowWidth/2, m_WindowHeight/2)

So how I can change projection matrix accordingly to the viewport offset?

\$\endgroup\$
1
\$\begingroup\$

You don't have to change your projection matrix accordingly to the viewport.

Have you considered to render the scene to a fbo and then render the fbo fullscreen (from -1, -1 to 1, 1) with glViewport(width / 2, height / 2, width / 2, height / 2)? This will took a quarter of the screen (top right).

In my current project, i can freely set the offset of glViewport without any problem and without changing my projection matrix. So i suppose the problem lies in your projection matrix or somewhere else.

Edit: On second thought, i just realize you didn't set up the matrix manually. Well that's harder for me.. lol. By the way, the person answering your question on StackOverflow is right, aspect ratio is width / height. Probably not going to fix your problem, but good to know.

\$\endgroup\$
  • \$\begingroup\$ Thanks for mentioning drawng to the framebuffer. I was already doing that and glViewport() accumulation caused the whole issue \$\endgroup\$ – Amadeusz Jun 2 '16 at 9:35
  • \$\begingroup\$ @Amadeusz Glad you solved it :) \$\endgroup\$ – Greffin28 Jun 2 '16 at 9:41
0
\$\begingroup\$

I finally found the solution to my problem: I have to set the viewport to begin at origin when I render to framebuffer.

I didn't mentioned that I was rendering my scene to the framebuffer, because I thought it was irrelevant and apparently that casued the problem.

In my case viewport transfromations accumulated: first when rendering to texture using framebuffer and second time when rendering this texture to screen.

So the result was that when I set offset in glViewport() as windowWidth/2 or windowHeight/2 my whole texture was shifted by windowWidth or windowHeight and rendered outside the screen.

What I had to do in my rendering pipeline was basicly that:

glViewport(0,0,windowWidth, windowHeight);
//*************************
//render stuff to the framebuffer
//*************************
glViewport(windowWidth/2, windowHeight/2,windowWidth/2, windowHeight/2);

And the effect is as expected: Success!!!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.