Skip to content
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

About setting widescreen fov parameter [question] #49

Open
suijingfeng opened this issue Jul 27, 2018 · 11 comments
Open

About setting widescreen fov parameter [question] #49

suijingfeng opened this issue Jul 27, 2018 · 11 comments

Comments

@suijingfeng
Copy link

suijingfeng commented Jul 27, 2018

This thread is more about question than issue. The following code is extracted from RE_RenderScene in tr_scene.c

parms.fovX = tr.refdef.fov_x;
parms.fovY = tr.refdef.fov_y;

if (!( fd->rdflags & RDF_NOWORLDMODEL ) ) // don't affect interface refdefs
{
	float zoomfov = tr.refdef.fov_x / 90;	
	int thisisit;
	float erspact = tr.refdef.width / tr.refdef.height;
	float aspact = glConfig.vidWidth / glConfig.vidHeight;
	if (erspact == aspact) thisisit = 1;
	if (((tr.refdef.fov_x /  tr.refdef.fov_y) > 1.3) && (thisisit))
        {
                // undo vert-
                parms.fovY = parms.fovY * (73.739792 / tr.refdef.fov_y) * zoomfov;
                // recalculate the fov
                parms.fovX = (atan (glConfig.vidWidth / (glConfig.vidHeight / tan ((parms.fovY * M_PI) / 360.0f))) * 360.0f) / M_PI;
                parms.fovY = (atan (glConfig.vidHeight / (glConfig.vidWidth / tan ((parms.fovX * M_PI) / 360.0f))) * 360.0f) / M_PI;
        }
}

It boil down to

parms.fovX = tr.refdef.fov_x;
parms.fovY = tr.refdef.fov_y;
if (!( fd->rdflags & RDF_NOWORLDMODEL ) ) // don't affect interface refdefs
{
    if ((parms.fovX > parms.fovY * 1.3f) && (tr.refdef.width * glConfig.vidHeight == glConfig.vidWidth * tr.refdef.height ))
    {
        // undo vert-
        parms.fovY = parms.fovX * (73.739792 / 90.0);
        // recalculate the fov_x
        parms.fovX = atan( tan(parms.fovY*(M_PI/360.0)) * glConfig.windowAspect ) * (360.0 / M_PI);
    }
}

because:

  1. glConfig.windowAspect = glConfig.vidWidth / glConfig.vidHeight is already computed previously, don't compute it every time in the main loop.

  2. parms.fovX = (atan (glConfig.vidWidth / (glConfig.vidHeight / tan ((parms.fovY * M_PI) / 360.0f))) * 360.0f) / M_PI are equivalent to parms.fovY = (atan (glConfig.vidHeight / (glConfig.vidWidth / tan ((parms.fovX * M_PI) / 360.0f))) * 360.0f) / M_PI; because:

glConfig.vidWidth / glConfig.vidHeight = tan( parms.fovX * M_PI / 360) / tan( parms.fovY * M_PI / 360)
there no need to compute parms.fovY again, right?

  1. what i am doing is trying to avoid float divided, it seems that adding this code code snippet to my rendergl2 module make sarge run faster. it may somewhere which OA different from ioq3.

I don't know how 1.3f and 73.739792 this two parameters comes from. Can someone tell something about that?

@The-Gig
Copy link

The-Gig commented Jul 30, 2018

While waiting for someone capable of answering to you, maybe you may take a look to this: #37 (a different way to compute widescreen fov, which should not have a small problem that current implementation has got in case of cg_fov <>90).

@leilei-
Copy link
Member

leilei- commented Aug 1, 2018

1.3f comes from wanting to check if the refdef has an aspect of 4:3 or wider (comes from 320 / 240, and to exclude widescreen processing a vert+ 5:4 mode like 1280x1024, which would be 1.25)

As for the other, I think 73.739792 was from calculating against the cgame's assumed vertical FOV and that I couldn't get a divide working properly.

A lot of it was trial and error on adapting older engoo code (which is either adapted from mh or quakespasm code) and attempting to apply that renderer-side for compatibility so it shouldn't affect gameplay. Also all the refdefs (viewports, etc) in the game go through that function and I had tried to make sure the widescreen fov only applies to the player view. A lot of my code is this messy as I've rarely had a second opinion whenever I commit stuff, especially back in 2014.

Also, i'm not the best at math, and i'd like to learn how to do this better. This issue is better than that one pull request wrongfully implying i didn't have hor+ in the first place. This issue marks the first time i've had proper insightful feedback and critique on my now-4-years-old widescreen implementation code.

@suijingfeng
Copy link
Author

suijingfeng commented Aug 3, 2018

Thanks for replies, it is very helpful.
By print the results the above code, i learned that
73.739792 = (360.0 / M_PI) * atan( tan( (M_PI/360.0) * 90) * 0.75f ) = (360.0 / M_PI) * atan(0.75)

ryvnf's request is actually can be optimized as follow:

        parms.fovX = tr.refdef.fov_x;
	parms.fovY = tr.refdef.fov_y;
	if (!( fd->rdflags & RDF_NOWORLDMODEL ) ){
		parms.fovY = (360.0 / M_PI) * atan( tan( (M_PI/360.0) * parms.fovX ) * 0.75f );
		parms.fovX = (360.0 / M_PI) * atan( tan( (M_PI/360.0) * parms.fovY ) * tr.refdef.width / tr.refdef.height ) ;
	}
  1. ryvnf's method are actually roughly same with leilei's. they both compute parms.fovY use tr.refdef.fov_x(=fd->fov_x), then compute parms.fovX with parms.fovY.
    Both method preserve the window aspect ratio. ryvnf does't check (parms.fovX / parms.fovY > 1.3f) which may has a influence on 1280*1024.

  2. Both method are not perfect, because players of OA can not set the horizon field of view accurately.
    For example, my display resolution is 1920*1080, if i want to set my HFOV to 140 by set cg_fov = 140, but i will get 140.363510 by using leilei's code, or 149.463058 by using ryvnf's code. I means the actual horizontal fov will not correspond to cg_fov value, and the user cannot know what it is exactly.

I hasty write a naive program to verify this.

if set cg_fov = 90, both leilei and ryvnf's method will get the same results.

width: 320, height: 240
leilei ------ fovX: 90.000000, fovY: 73.739792, aspect: 1.333333
ryvnf ------ fovX: 90.000000, fovY: 73.739792, aspect: 1.333333

width: 400, height: 300
leilei ------ fovX: 90.000000, fovY: 73.739792, aspect: 1.333333
ryvnf ------ fovX: 90.000000, fovY: 73.739792, aspect: 1.333333

width: 512, height: 384
leilei ------ fovX: 90.000000, fovY: 73.739792, aspect: 1.333333
ryvnf ------ fovX: 90.000000, fovY: 73.739792, aspect: 1.333333

width: 640, height: 480
leilei ------ fovX: 90.000000, fovY: 73.739792, aspect: 1.333333
ryvnf ------ fovX: 90.000000, fovY: 73.739792, aspect: 1.333333

width: 800, height: 600
leilei ------ fovX: 90.000000, fovY: 73.739792, aspect: 1.333333
ryvnf ------ fovX: 90.000000, fovY: 73.739792, aspect: 1.333333

width: 960, height: 720
leilei ------ fovX: 90.000000, fovY: 73.739792, aspect: 1.333333
ryvnf ------ fovX: 90.000000, fovY: 73.739792, aspect: 1.333333

width: 1024, height: 768
leilei ------ fovX: 90.000000, fovY: 73.739792, aspect: 1.333333
ryvnf ------ fovX: 90.000000, fovY: 73.739792, aspect: 1.333333

width: 1152, height: 864
leilei ------ fovX: 90.000000, fovY: 73.739792, aspect: 1.333333
ryvnf ------ fovX: 90.000000, fovY: 73.739792, aspect: 1.333333

width: 1280, height: 1024
leilei ------ fovX: 90.000000, fovY: 0.000000, aspect: inf
ryvnf ------ fovX: 90.000000, fovY: 0.000000, aspect: inf

width: 1600, height: 1200
leilei ------ fovX: 90.000000, fovY: 73.739792, aspect: 1.333333
ryvnf ------ fovX: 90.000000, fovY: 73.739792, aspect: 1.333333

width: 2048, height: 1536
leilei ------ fovX: 90.000000, fovY: 73.739792, aspect: 1.333333
ryvnf ------ fovX: 90.000000, fovY: 73.739792, aspect: 1.333333

width: 856, height: 480
leilei ------ fovX: 106.431747, fovY: 73.739792, aspect: 1.783333
ryvnf ------ fovX: 106.431747, fovY: 73.739792, aspect: 1.783333

width: 1280, height: 720
leilei ------ fovX: 106.260201, fovY: 73.739792, aspect: 1.777778
ryvnf ------ fovX: 106.260201, fovY: 73.739792, aspect: 1.777778

width: 1280, height: 768
leilei ------ fovX: 102.680382, fovY: 73.739792, aspect: 1.666667
ryvnf ------ fovX: 102.680382, fovY: 73.739792, aspect: 1.666667

width: 1280, height: 800
leilei ------ fovX: 100.388855, fovY: 73.739792, aspect: 1.600000
ryvnf ------ fovX: 100.388855, fovY: 73.739792, aspect: 1.600000

width: 1280, height: 960
leilei ------ fovX: 90.000000, fovY: 73.739792, aspect: 1.333333
ryvnf ------ fovX: 90.000000, fovY: 73.739792, aspect: 1.333333

width: 1360, height: 768
leilei ------ fovX: 106.044807, fovY: 73.739792, aspect: 1.770833
ryvnf ------ fovX: 106.044807, fovY: 73.739792, aspect: 1.770833

width: 1366, height: 768
leilei ------ fovX: 106.287048, fovY: 73.739792, aspect: 1.778646
ryvnf ------ fovX: 106.287048, fovY: 73.739792, aspect: 1.778646

width: 1360, height: 1024
leilei ------ fovX: 89.775749, fovY: 73.739792, aspect: 1.328125
ryvnf ------ fovX: 89.775749, fovY: 73.739792, aspect: 1.328125

width: 1400, height: 1050
leilei ------ fovX: 90.000000, fovY: 73.739792, aspect: 1.333333
ryvnf ------ fovX: 90.000000, fovY: 73.739792, aspect: 1.333333

width: 1400, height: 900
leilei ------ fovX: 98.797409, fovY: 73.739792, aspect: 1.555556
ryvnf ------ fovX: 98.797409, fovY: 73.739792, aspect: 1.555556

width: 1600, height: 900
leilei ------ fovX: 106.260201, fovY: 73.739792, aspect: 1.777778
ryvnf ------ fovX: 106.260201, fovY: 73.739792, aspect: 1.777778

width: 1680, height: 1050
leilei ------ fovX: 100.388855, fovY: 73.739792, aspect: 1.600000
ryvnf ------ fovX: 100.388855, fovY: 73.739792, aspect: 1.600000

width: 1920, height: 1080
leilei ------ fovX: 106.260201, fovY: 73.739792, aspect: 1.777778
ryvnf ------ fovX: 106.260201, fovY: 73.739792, aspect: 1.777778

width: 1920, height: 1200
leilei ------ fovX: 100.388855, fovY: 73.739792, aspect: 1.600000
ryvnf ------ fovX: 100.388855, fovY: 73.739792, aspect: 1.600000

width: 1920, height: 1440
leilei ------ fovX: 90.000000, fovY: 73.739792, aspect: 1.333333
ryvnf ------ fovX: 90.000000, fovY: 73.739792, aspect: 1.333333

width: 2560, height: 1600
leilei ------ fovX: 100.388855, fovY: 73.739792, aspect: 1.600000
ryvnf ------ fovX: 100.388855, fovY: 73.739792, aspect: 1.600000

width: 3840, height: 2160
leilei ------ fovX: 106.260201, fovY: 73.739792, aspect: 1.777778
ryvnf ------ fovX: 106.260201, fovY: 73.739792, aspect: 1.777778

But set cg_fov = 140

width: 320, height: 240
leilei ------ fovX: 128.670578, fovY: 114.706345, aspect: 1.333333
ryvnf ------ fovX: 140.000000, fovY: 128.225998, aspect: 1.333333

width: 400, height: 300
leilei ------ fovX: 128.670578, fovY: 114.706345, aspect: 1.333333
ryvnf ------ fovX: 140.000000, fovY: 128.225998, aspect: 1.333333

width: 512, height: 384
leilei ------ fovX: 128.670578, fovY: 114.706345, aspect: 1.333333
ryvnf ------ fovX: 140.000000, fovY: 128.225998, aspect: 1.333333

width: 640, height: 480
leilei ------ fovX: 128.670578, fovY: 114.706345, aspect: 1.333333
ryvnf ------ fovX: 140.000000, fovY: 128.225998, aspect: 1.333333

width: 800, height: 600
leilei ------ fovX: 128.670578, fovY: 114.706345, aspect: 1.333333
ryvnf ------ fovX: 140.000000, fovY: 128.225998, aspect: 1.333333

width: 960, height: 720
leilei ------ fovX: 128.670578, fovY: 114.706345, aspect: 1.333333
ryvnf ------ fovX: 140.000000, fovY: 128.225998, aspect: 1.333333

width: 1024, height: 768
leilei ------ fovX: 128.670578, fovY: 114.706345, aspect: 1.333333
ryvnf ------ fovX: 140.000000, fovY: 128.225998, aspect: 1.333333

width: 1152, height: 864
leilei ------ fovX: 128.670578, fovY: 114.706345, aspect: 1.333333
ryvnf ------ fovX: 140.000000, fovY: 128.225998, aspect: 1.333333

width: 1280, height: 1024
leilei ------ fovX: 140.000000, fovY: 0.000000, aspect: inf
ryvnf ------ fovX: 140.000000, fovY: 0.000000, aspect: inf

width: 1600, height: 1200
leilei ------ fovX: 128.670578, fovY: 114.706345, aspect: 1.333333
ryvnf ------ fovX: 140.000000, fovY: 128.225998, aspect: 1.333333

width: 2048, height: 1536
leilei ------ fovX: 128.670578, fovY: 114.706345, aspect: 1.333333
ryvnf ------ fovX: 140.000000, fovY: 128.225998, aspect: 1.333333

width: 856, height: 480
leilei ------ fovX: 140.477417, fovY: 114.706345, aspect: 1.783333
ryvnf ------ fovX: 149.553772, fovY: 128.225998, aspect: 1.783333

width: 1280, height: 720
leilei ------ fovX: 140.363510, fovY: 114.706345, aspect: 1.777778
ryvnf ------ fovX: 149.463058, fovY: 128.225998, aspect: 1.777778

width: 1280, height: 768
leilei ------ fovX: 137.945755, fovY: 114.706345, aspect: 1.666667
ryvnf ------ fovX: 147.531403, fovY: 128.225998, aspect: 1.666667

width: 1280, height: 800
leilei ------ fovX: 136.355270, fovY: 114.706345, aspect: 1.600000
ryvnf ------ fovX: 146.254013, fovY: 128.225998, aspect: 1.600000

width: 1280, height: 960
leilei ------ fovX: 128.670578, fovY: 114.706345, aspect: 1.333333
ryvnf ------ fovX: 140.000000, fovY: 128.225998, aspect: 1.333333

width: 1360, height: 768
leilei ------ fovX: 140.220245, fovY: 114.706345, aspect: 1.770833
ryvnf ------ fovX: 149.348923, fovY: 128.225998, aspect: 1.770833

width: 1366, height: 768
leilei ------ fovX: 140.381348, fovY: 114.706345, aspect: 1.778646
ryvnf ------ fovX: 149.477264, fovY: 128.225998, aspect: 1.778646

width: 1360, height: 1024
leilei ------ fovX: 128.495285, fovY: 114.706345, aspect: 1.328125
ryvnf ------ fovX: 139.855652, fovY: 128.225998, aspect: 1.328125

width: 1400, height: 1050
leilei ------ fovX: 128.670578, fovY: 114.706345, aspect: 1.333333
ryvnf ------ fovX: 140.000000, fovY: 128.225998, aspect: 1.333333

width: 1400, height: 900
leilei ------ fovX: 135.229904, fovY: 114.706345, aspect: 1.555555
ryvnf ------ fovX: 145.346832, fovY: 128.225998, aspect: 1.555556

width: 1600, height: 900
leilei ------ fovX: 140.363510, fovY: 114.706345, aspect: 1.777778
ryvnf ------ fovX: 149.463058, fovY: 128.225998, aspect: 1.777778

width: 1680, height: 1050
leilei ------ fovX: 136.355270, fovY: 114.706345, aspect: 1.600000
ryvnf ------ fovX: 146.254013, fovY: 128.225998, aspect: 1.600000

width: 1920, height: 1080
leilei ------ fovX: 140.363510, fovY: 114.706345, aspect: 1.777778
ryvnf ------ fovX: 149.463058, fovY: 128.225998, aspect: 1.777778

width: 1920, height: 1200
leilei ------ fovX: 136.355270, fovY: 114.706345, aspect: 1.600000
ryvnf ------ fovX: 146.254013, fovY: 128.225998, aspect: 1.600000

width: 1920, height: 1440
leilei ------ fovX: 128.670578, fovY: 114.706345, aspect: 1.333333
ryvnf ------ fovX: 140.000000, fovY: 128.225998, aspect: 1.333333

width: 2560, height: 1600
leilei ------ fovX: 136.355270, fovY: 114.706345, aspect: 1.600000
ryvnf ------ fovX: 146.254013, fovY: 128.225998, aspect: 1.600000

width: 3840, height: 2160
leilei ------ fovX: 140.363510, fovY: 114.706345, aspect: 1.777778
ryvnf ------ fovX: 149.463058, fovY: 128.225998, aspect: 1.777778

@The-Gig
Copy link

The-Gig commented Aug 3, 2018

Excuse me, what do you mean with this sentence?

"Both method are not perfect, because we can not set the horizon field of version accurately."

I suppose you meant "field of view" instead of "field of version", okay... But I still don't get what you mean...

Maybe do you mean that you would prefer to be able to set a cg_fov corresponding to the horizontal fov you actually want to obtain on your screen, instead of the one you would have at 4:3 ratio?
Aw, I really did not explain myself well in the above sentence. Let's try again.
With vert-, your cg_fov was always your actual horizontal fov value, right? With hor+, cg_fov refers to the horizontal fov you would have in case of a 4:3 ratio. In case your ratio is different, your actual horizontal fov will not correspond to cg_fov value, and the user cannot know what it is exacly. If cg_fov 90 gives fovX 106.260201 at FullHD, did you mean you wanted to have this info somewhere, or to directly enter 106 in cg_fov cvar? Or what else? I'm a bit lost...
I have to admit I don't know how modern games deal with that. Like, maybe they assume the horizontal FOV you specify refers to 16:9, and silently adapt fovX for other ratios?

@suijingfeng
Copy link
Author

suijingfeng commented Aug 3, 2018

@The-Gig , thanks for feedback and sorry for my poor English written skills. I revise my comment, wish you could understand it.

I am now doubt the necessary of the leilei's widescreen support code and ryvnf's widescreen support request. Because those patched code do not help the players get the best HFOV and VFOR parameter for
a specific resolution. In other word, I think leilei's widescreen support code should be removed from the engine. The reasons are as follows.

As I puts it earlier, display aspect = winWidth / winHeight = tan( parms.fovX * M_PI / 360) / tan( parms.fovY * M_PI / 360). Either parms.fovX or parms.fovY are independent, If we know the width and height of the rendering windows. In other word, parms.fovY can be calculated from parms.fovX if we want preserve the display aspect. The game code fov_y = (360.0/M_PI) * atan2( tan( fov_x * (M_PI/360.0) ) * cg.refdef.height , cg.refdef.width); in CG_CalcFov is meant to preserve aspect, there no need to recalculate parms.fovX and parms.fovY again.

Both leilei and ryvnf's code are not useful with cg_fov = 90 setting by default, it does not help widescreen players get the best fov parameters for a specific display resolution. You have to turn cg_fov by youselves for best efficiency or for view effect.

@The-Gig
Copy link

The-Gig commented Aug 4, 2018

Your rewording of the previous post confirmed I understood correctly about that specific sentence, thanks.

However, for me it's okay to just say "Cg_fov is the horizontal FOV with a 4:3 ratio. In case of widescreen, actual FOV will be larger".
However, I don't know how modern games deal with this. I don't know if they automatically change your FOV setting in case you change your resolution to a different ratio or what else...

I'm sorry I get lost with the calculations, I'm not good with them.

Hor+ may give an advantage to widescreen users (compared to 4:3 users) with the same fov (more horizontal view), but vert- gives them a disadvantage (less vertical view). Considering today widescreen is the norm, I'm okay with hor+...

@leilei-
Copy link
Member

leilei- commented Aug 5, 2018

My implementation is intended to be mod compatible and cgame should not be changed for widescreen support.

Here's an old gif of my implementation which had me feel certain about the hor+ FOV being correct

oawidescreen2

I'm not removing widescreen.

It should also be noted that John Carmack did consider widescreen hor+ in Q3 but decided against it because of the fov setting confusion that would possibly upset the "config enthusiast" playerbase

However, I don't know how modern games deal with this.

Letterboxing for non-wide.

@The-Gig
Copy link

The-Gig commented Sep 4, 2018

About suijingfeng's note that players cannot control or know actual fov, here's a small idea (take it for what it is, just an idea): what about adding a new command to output effective fov info to console?

Your cg_fov is 90. Actual fovX: 102.680382, fovY: 73.739792
Your cg_zoomfov is 22.5. Actual zoomFovX: xxxxxxxxx, zoomFovY: yyyyyyyyyy

Or maybe the output may be more verbose, also recapping some other related infos:

Resolution/Field Of View settings:
r_mode -1 (custom)
r_customheight 1920 [to be shown in case of r_mode -1]
r_customwidth 1080 [to be shown in case of r_mode -1]
r_custompixelaspect 0 [somewhat related with r_mode -1, IIRC. Note, I don't know if this may have some relationship with the resulting FOV]
r_fullscreen 0
Resolution: 1920x1080, ratio 1.33333
cg_fov 90. Actual fovX: 102.680382, fovY: 73.739792
cg_zoomfov 22.5. Actual zoomFovX: xxxxxxxxx, zoomFovY: yyyyyyyyyy

Well, at least players would have a way to know which is their actual FOV, while the reference cg_fov value would still refer to 4:3.

About the "1.3f" thing in leilei's implementation, have I understood correctly how it works?
1.33333 means 4:3 ratio, which is set as reference. Assuming "widescreen" meaning > 1.33333 and "narrowsreen" < 1.33333...
In "hor+" using a narrowscreen would ed up in doing a "hor-" (actual fovX smaller than cg_fov). Leilei code in that case reverts to "vert-", ending up doing a "vert+" (actual fovX equal to cg_fov).
Did I understand correctly? Probably leilei's explanation from Aug 1 is clear enough about it... but I ask because suijingfeng's resolution/fov comparison examples above just list as "fovY 00000, ratio inf." the cases where ratio is smaller than 1.33333, so I'm not sure about actual results.
That sounds a quite good solution, much better than letterboxing! ^_^
Wondering what does ryvnf code do in case of narrowscreen (narrower than 4:3)...?
Also, is 1.3f equal to 1.3 or 1.33333? I mean, rounding decimals may be a problem here?

@Kezuz
Copy link

Kezuz commented May 26, 2019

@leilei- ryvnf claimed the implementation is flawed for cg_fov values not equal to 90. It appears you use cg_fov 90 in your GIF.

I tried to replicate your example with cg_fov 130 and it appears ryvnf was correct. See for yourself:

130

The vertical FOV changes between 640x480, 800x480 and 960x480 which it shouldn't in a correct implementation.

@suijingfeng
Copy link
Author

@Kezuz @leilei- how to generate GIT like what your have done? I'm also want to generate one.

@Kezuz
Copy link

Kezuz commented May 28, 2019

@suijingfeng I used the screenshotjpeg command after each change in cg_fov. Then open up the screenshots in GIMP and make a animated gif of them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants