-
Notifications
You must be signed in to change notification settings - Fork 79
[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
base: main
Are you sure you want to change the base?
[ZH] Adjust field of view based on aspect ratio #518
Conversation
Can I ask why do you get less horizontal FOV on 9:16 compared to 4:3? |
Is the PR only for Zero Hour? Because I see changes in Generals too. |
7651a21
to
cb3225e
Compare
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.
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. |
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. |
If you are playing on your phone maybe you need this :D |
cb3225e
to
c52e1e8
Compare
c52e1e8
to
74e96ed
Compare
74e96ed
to
07c1097
Compare
There was a problem hiding this 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) |
There was a problem hiding this comment.
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: |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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?
ReviewI tested this change in 32:9 and it causes way too much distortion at the far edges. Check how this Overlord distorts near the edge SuggestionI 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, |
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. |
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. |
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
W3DView::adjustFovToAspectRatio
which is called every time when display resolution changes;adjustFovToAspectRatio
changes camera FOV differently based on aspect ratio: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