13
\$\begingroup\$

Basically, I want to know how I can remove distortion or stretching of the rendered image when the viewport/window size changes.

The following images exemplify the distortion/stretching I'm talking about:

Original Image (Square Window)

No Distortion

Distorted/Stretched Image (Rectangular Window)

With Distortion

Ideally, the second image should display the sphere without the horizontal stretching, and would expose more of the scene to the user to account for the larger window size.

How can this be done?

I'm working with OpenGL to render the image, and I make use of the perspective projection via the calls:

glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(60, window.width/window.height, 0.01f, 100.0f)

The aspect-ratio width/height is in accordance to all of the documents/tutorials I've come across, so I don't expect it to be incorrect. However, my suspicion is that it is affecting the stretching problem.


After thought

Honestly, as I think about the issue more, I'd led to believe that the solution involves a directly proportional relationship between the fovy (field of view in the y-direction) angle and the aspect-ratio.

Perspective Projection

Using the above image as a reference, if the width grows (causing a horizontal stretch), it seems very plausible that the fovy angle must increase to cause a vertical stretch that 'fixes' the proportionality of the rendered image.

Likewise, a decrease in width requires a decrease in the fovy angle.

Update:

So, after investigating this further, I've decided to change the way I've set up the viewing frustum like this:

gluPerspective(60 * (float)window.width/window.height, (float)window.width/window.height, 0.01f, 100.0f)

And my expectations were correct, that solved the proportionality issue. However, it doesn't achieve my desired results. When the window width increases, the rendered image becomes smaller (but the sphere is indeed circular). Instead, the sphere shouldn't change size at all; only the amount of scene that is displayed should change.

\$\endgroup\$
14
\$\begingroup\$

In fact, the original question is 1 cast away from the solution.

Original Code

glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(60, window.width/window.height, 0.01f, 100.0f)

Fixed Code

glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(60, (float)window.width/window.height, 0.01f, 100.0f)

The problem was that window.width and window.height are integers, which caused the aspect-ratio to be the result of an integer division.

Casting one of the dimensions to a float causes the result to use floating-point division instead.

Because the aspect-ratio is now correct, there is no more stretching as seen in the original post.

EDIT: The code in the original post (and the answer) is simply pseudo-code for the calls to the GPU; the actual program used to output the images above is written in Java. To those not working with Java, I've not researched to see if the integer/floating-point division is implemented in the same way. Regardless, the solution is about making sure that the aspect-ratio is indeed correctly computed.

\$\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.