Skip to content

[ZH] Adjust field of view based on aspect ratio #518

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

valeronm
Copy link

The game doesn't support wide screens well because it has static horizontal field of view (FOV) and static maximum camera height. This means that for every resolution, the camera shows the same horizontal amount of terrain, but the vertical field of view becomes narrower for wider resolutions. So on wide screens, we get a center crop of what is visible on 4:3 resolutions (screenshots below).
To support wider screens, we need to have constant vertical FOV and calculate horizontal FOV based on the screen aspect ratio.

Changes

  • Added function W3DView::adjustFovToAspectRatio which is called every time when display resolution changes;
  • Function adjustFovToAspectRatio changes camera FOV differently based on aspect ratio:
    • when screen is wider than 4:3 it sets the fixed vertical FOV based on vFOV used for 4:3 screens (38.55°);
    • when screen narrower than 4:3 but still horizontal, it sets fixed hFOV used for 4:3 screens (50°) - this is what the game always uses now;
    • for portrait screens it uses varying 50° to 60° vFOV

Screenshots

1600 x 1200 - 4:3 (original)
1600 x 900 - 16:9 (original)
1600 x 900 - 16:9 (new logic)
3200 x 900 - 32:9 (new logic)
900 x 1600 - 9:16 (new logic)

Fixes #78
Depends on #460 to make wide resolutions selectable

@valeronm valeronm changed the title Adjust field of view based on aspect ratio [ZH] Adjust field of view based on aspect ratio Mar 26, 2025
@ElTioRata
Copy link

Can I ask why do you get less horizontal FOV on 9:16 compared to 4:3?

@DevGeniusCode
Copy link

Is the PR only for Zero Hour? Because I see changes in Generals too.

@DevGeniusCode DevGeniusCode added Bug Something is not working right, typically is user facing Critical Severity: Minor < Major < Critical < Blocker ZH Relates to Zero Hour labels Mar 26, 2025
@valeronm valeronm force-pushed the adjust_field_of_view_to_aspect_ratio branch from 7651a21 to cb3225e Compare March 27, 2025 01:09
@valeronm
Copy link
Author

valeronm commented Mar 27, 2025

Can I ask why do you get less horizontal FOV on 9:16 compared to 4:3?

This is done on purpose. The same horizontal FOV will allow seeing almost the entire map in portrait mode. I'm sure this is not an ideal fix for portrait modes, but it should be good enough until a better solution is implemented. One possible solution is to change the angle of the camera towards the terrain for portrait screens.

900 x 1600 with fixed hFOV used for 4:3 screens

Is the PR only for Zero Hour? Because I see changes in Generals too.

This PR depends on #460, so the current branch contains one commit from that PR, which includes changes for both Generals and Zero Hour. After merging #460, this PR will have changes for Zero Hour only.

@ElTioRata
Copy link

ElTioRata commented Mar 27, 2025

The same horizontal FOV will allow seeing almost the entire map in portrait mode.

Out of curiosity, how does it look on 1:1?

@valeronm
Copy link
Author

valeronm commented Mar 27, 2025

Out of curiosity, how does it look on 1:1?

I've made the spreadsheet with original and FOV values and also made the folder with screenshots for different aspect ratios.

@OmniBlade
Copy link

Can I ask why do you get less horizontal FOV on 9:16 compared to 4:3?

This is done on purpose. The same horizontal FOV will allow seeing almost the entire map in portrait mode. I'm sure this is not an ideal fix for portrait modes, but it should be good enough until a better solution is implemented. One possible solution is to change the angle of the camera towards the terrain for portrait screens.
900 x 1600 with fixed hFOV used for 4:3 screens

If you are playing on your phone maybe you need this :D

valeronm added a commit to valeronm/GeneralsGameCode that referenced this pull request Mar 30, 2025
@valeronm valeronm force-pushed the adjust_field_of_view_to_aspect_ratio branch from cb3225e to c52e1e8 Compare March 30, 2025 00:03
valeronm added a commit to valeronm/GeneralsGameCode that referenced this pull request Apr 17, 2025
@valeronm valeronm force-pushed the adjust_field_of_view_to_aspect_ratio branch from c52e1e8 to 74e96ed Compare April 17, 2025 08:12
@valeronm valeronm force-pushed the adjust_field_of_view_to_aspect_ratio branch from 74e96ed to 07c1097 Compare June 30, 2025 22:03
@xezon xezon added Design Is a matter of game design Enhancement Is new feature or request Gen Relates to Generals and removed Bug Something is not working right, typically is user facing labels Jul 1, 2025
@xezon xezon added this to the Important features milestone Jul 1, 2025
Copy link

@xezon xezon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have reservations about scaling FOV like this. On the 32:9 sample image we can see the extreme view distortion towards the left and right edges, where the trees no longer stand straight.

I suggest to move some units to these edges and then check how distorted these will look.

My first instinct here is to primarily scale camera height, not just the FOV. Maybe it can be a mix of both. GenTool only scales the camera height. Mods only scale camera height as well (via GameData.ini). There is no precedent to scaling this with FOV.

We need to test this change to see how this looks in action.

@@ -226,10 +226,48 @@ void W3DView::setWidth(Int width)
m_3DCamera->Get_Viewport(vMin,vMax);
vMax.X=(Real)(m_originX+width)/(Real)TheDisplay->getWidth();
m_3DCamera->Set_Viewport(vMin,vMax);
}

// TheSuperHackers @tweak valeronm 25/03/2025 Adjusting FOV to look similar to what we have in in 4:3 (hFOV: 50, vFOV 38.55)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in in

@@ -232,7 +232,7 @@ class W3DView : public View, public SubsystemInterface

virtual void setGuardBandBias( const Coord2D *gb ) { m_guardBandBias.x = gb->x; m_guardBandBias.y = gb->y; }


virtual void adjustFovToAspectRatio(const Int width, const Int height);
private:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add blank line before this

void W3DView::adjustFovToAspectRatio(const Int width, const Int height)
{
static const Real fixedHFOV = 50.00f;
static const Real fixedVFOV = 38.55f;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use CONSTEXPR instead of static

// Wider than 4:3 resolutions get fixed vFOV 38.55
vFOVRad = DEG_TO_RADF(fixedVFOV);
hFOVRad = 2.0f * atan(tan(vFOVRad / 2.0f) * aspectRatio);
drawEntireTerrain = true;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks suspicious. The GenTool implementation did not need this for up to 16:9. The original game also did not need this for 4:3. It will affect performance.

void W3DView::adjustFovToAspectRatio(const Int width, const Int height)
{
static const Real fixedHFOV = 50.00f;
static const Real fixedVFOV = 38.55f;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How did the magical 38.55 come to be?

else
{
// Portrait resolutions get fixed vFOV adjusted to aspect ratio
// vFOV increases from 50.0 for 1:1 to 60.0 for 9:21 and then fixed 60.0
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reason for this fine tuning?

Bool drawEntireTerrain = false;
if (aspectRatio >= 4.0f / 3.0f)
{
// Wider than 4:3 resolutions get fixed vFOV 38.55
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment repeats the code value that is assigned to fixedVFOV. This means the commented value can go out of sync when someone changes the code value. Prefer not baking values into comments, unless they definitely never change.

const Real aspectRatio = static_cast<Real>(width)/ static_cast<Real>(height);
Real vFOVRad, hFOVRad;
Bool drawEntireTerrain = false;
if (aspectRatio >= 4.0f / 3.0f)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For Multiplayer, I very much prefer we cap this at max 16/9, min 9/16, to not give these ultra screens a massive advantage, preferably configurable in GameData.ini, so that Mods can do their own setups.

For Singleplayer and Replay it is fine to go wide with no limits.

{
// Wider than 4:3 resolutions get fixed vFOV 38.55
vFOVRad = DEG_TO_RADF(fixedVFOV);
hFOVRad = 2.0f * atan(tan(vFOVRad / 2.0f) * aspectRatio);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not mind a brief explanation in a comment for the math how the fov is scaled.

{
// Narrower than 4:3 but not yet portrait resolutions get fixed hFOV 50.0
hFOVRad = DEG_TO_RADF(fixedHFOV);
vFOVRad = 2.0f * atan(tan(hFOVRad / 2.0f) / aspectRatio);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there no cut in fov'ness between the different conditions? How does this work?

@xezon
Copy link

xezon commented Jul 1, 2025

Review

I tested this change in 32:9 and it causes way too much distortion at the far edges.

shot_20250701_191317_1

Check how this Overlord distorts near the edge

distortion

Suggestion

I suggest to refine this implementation, to not just offer Camera Fov adjustment for Resolution, but also Camera Height adjustment for Resolution.

Then, provide a scalar to scale the Camera Fov & Height adjustments.

So for example, CameraFovWeightForAspectRatioAdjustment = 0.4 would mean 40% adjustment comes from Fov, and 60% adjustment comes from Height. This way we can tweak the desired view distortion level and keep it small.

@ElTioRata
Copy link

ElTioRata commented Jul 1, 2025

I don't see any screen distortion at 16:9 though. My suggestion would be to get the game to start increasing the camera height value when using wider screen proportions than 16:9.

@xezon
Copy link

xezon commented Jul 2, 2025

I don't see any screen distortion at 16:9 though. My suggestion would be to get the game to start increasing the camera height value when using wider screen proportions than 16:9.

Distortion in 16:9 will be much smaller, but it is still there. It is not great to make the logic ever more complicated with more aspect ratio conditions.

The 4:3 is our reference condition. The only fixed requirement is that the camera height and fov at 4:3 is unchanged. From there, make it as simple as possible.

@Mauller
Copy link

Mauller commented Jul 2, 2025

From what i remember seeing, the camera height is currently calculated off the horizontal screen resolution.

This likely wants scaling related to 800x600 and changing to be based off the min of the horizontal or vertical resolution, this should then correct the zoomed in look on wider resolutions while keeping the same FoV. This can then act as a starting basis for any other kind of increases in camera height in future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Critical Severity: Minor < Major < Critical < Blocker Design Is a matter of game design Enhancement Is new feature or request Gen Relates to Generals ZH Relates to Zero Hour
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Camera height does not scale properly along with aspect ratio of game resolution
6 participants