Hor + vert + FOV, or adaptive field of view



Hello everybody!

Today, when I tested my Quake port on a tablet, I noticed that it is not very pleasant to watch demos in portrait orientation due to the narrow field of view.

Therefore, I decided to come up with a very simple, but looking good (in my opinion) both in portrait and landscape orientation, a way to fix this.

And I called it Hor + vert + FOV.


What was the problem


Since my desktop has a widescreen monitor, I initially decided to use Hor + FOV instead of Vert- , although Quake uses Vert- because it seemed like I was looking at the world through a magnifying glass.

Quake with Vert-FOV on a widescreen monitor.


Hor + worked fine until I got a tablet. Everything looked great in landscape orientation, but in portraiture it was no longer an approximation, but simply crowded.

Quake with Hor + FOV in portrait orientation.


Decision


And the solution was the simplest.

Instead of using either of the two FOV types, I decided to combine the two types.

Since Quake was designed for monitors with an aspect ratio of 4: 3, I began to use this ratio as the base for switching between the two modes.

If the aspect ratio is greater than 4: 3 (wide screen) - use Hor +.
If the aspect ratio is less than or equal to 4: 3 (the screen is narrow or close to square) - Vert- is used.


But since the task was to adjust the FOV to narrow screens, this means that the narrower the screen, the more it should be visible. Therefore, for us, Vert- actually turned into Vert +.

The implementation of this method takes a single check on the condition.

I will give all the code for implementing this method from WebQuake.
if ((vrect.width * 0.75) <= vrect.height)
{
	R.refdef.fov_x = SCR.fov.value;
	R.refdef.fov_y = Math.atan(vrect.height / (vrect.width / Math.tan(SCR.fov.value * Math.PI / 360.0))) * 360.0 / Math.PI;
}
else
{
	R.refdef.fov_x = Math.atan(vrect.width / (vrect.height / Math.tan(SCR.fov.value * 0.82 * Math.PI / 360.0))) * 360.0 / Math.PI;
	R.refdef.fov_y = SCR.fov.value * 0.82;
}


Explanation:
  • SCR.fov is a console variable indicating horizontal FOV with a 4: 3 aspect ratio (ideal aspect ratio for Quake).
  • If the aspect ratio is less than or equal to 4: 3, use Vert +. If not, use Vert-.
  • In the case of Vert +, we take the horizontal FOV from the console variable, and the vertical one - we calculate according to the well-known algorithm.
  • In the case of Hor +, we take the vertical FOV from the console variable, and the horizontal one is calculated.
  • 0.82 - the ratio of vertical to horizontal FOV at a ratio of 4: 3. To get the vertical FOV from a console variable, multiply the value of the variable by this constant.


What came out of it:
Landscape orientation - Hor + is used.

Portrait Orientation - Use Vert +.


As you can see, there is no approximation here, and the review is good.

But there is one small problem.

Error and its solution


As you can see from the previous screenshot, the weapon model is too far from the player.

This problem is present only when Vert + is used - in Hor + this effect is not observed.

Since the weapon model in Quake is drawn separately from the rest of the models, nothing prevents us from switching from Vert + to Hor + before drawing weapons, and then back.

The world is drawn in Vert +, and weapons in Hor +.


The bug is fixed.

Summary and Conclusion


As a result, it turned out as in the first screenshot in this post.



Maybe this technique is not new (although I have not yet seen a single game using something like this), but it is of great importance. Using adaptive FOV is very important in the era of web applications and mobile devices, since the browser window can have any rectangular shape, and smartphones and tablets work both in horizontal and vertical orientation.

Thanks for reading.

Also popular now: