gluPerspective problem, with real numbers to work with

gluPerspective() takes the vertical fov, aspect, and near and far view ranges. I want the viewport to always use the same horizontal fov, and adjust the vertical fov so that it isn’t stretched, regardless of the viewport height.

Viewport width=1024
Viewport height=768
desired horizontal fov=90 degrees

The aspect is the width divided by the height, which is 1024/768=1.33333333. I tried this:

gluPerspective 90.0/1.3333333,1.3333333,near,far

But this gave me a little less than 90 degrees view in the horizontal direction. The only way I could get a perfect 90-degree view in the horizontal direction was like this:

gluPerspective 90.0/1.3333333,1.5,near,far

What’s going on here? I noticed that 90.0/1.3333333/1.5=45.0, which might be significant.

Then I tried using glFrustum:
glfrustum -nearrange/zoom,nearrange/zoom,-nearrange/aspect/zoom,nearrange/aspect/zoom,nearrange,farrange

When zoom=1.0, I get a perfect 90-degree fov in the horizontal direction. However, when I try changing zoom to 2.0, for a 45-degree fov, I get a somewhat larger fov in the horizontal direction (approximately 50-60 degrees).

Well, after drawing it out on paper I saw that this takes a little trig to do. I have never seen a mention of precision zooming with the frustum, so I will post my solution here.

With zoom=1.0, the horizontal fov will be 90.0. With a zoom of 2.0, the horizontal fov will be 45.0 degrees. The vertical fov is dependent on viewport height. The aspect is the viewport width divided by the viewport height:

zoom#=2.0 // for a 45-degree fov. Use 1.0 for 90 degrees.
aspect#=width#/height#
theta#=Tan(45.0/zoom#) // temporary angle value
glfrustum -nearrange#*theta#,nearrange#*theta#,-nearrange#/aspect#*theta#,nearrange#/aspect#*theta#,nearrange#,farrange#