How does games manage different resolutions?

Started by
8 comments, last by Volgogradetzzz 8 years, 9 months ago

Hello!

We all saw that every game allows to select a resolution. It looks simple but some questions doesn't give me to sleep.

  1. How can I obtain available resolutions? Just take the most popular and hardcode?
  2. I can iterate over available outputs and find supported resolutions as well as sync intervals. But what if the user selected an adapter that is not have any output bounded (actually how does this works at all - I have 2 GPUs, I can switch between them, and I always have a picture, even if a card doesn't have an output)?
  3. What if the user have several monitors. How should I choose correct one (and should I at all)?
  4. In Starcraft 2 I noticed that in windowed mode there's no resolution selection at all - I can resize a window and picture scales accordingly. How it is done? Do they have fixed resolution for the windowed mode?
Advertisement

For fullscreen modes and used monitors query the OS, preferably using a library like GLFW3:
http://www.glfw.org/docs/latest/monitor.html#monitor_modes

For windowed, well, just let it have any size the user wants it to and have a callback on the

window-changed-size-event of whatever library you use.

http://www.glfw.org/docs/latest/window.html#window_events

It's actually really easy if you use a proper library.

Edit: as for multiple GPUs, don't bother with that until you have your windows working on the default one...

Hi, thank you for the answer.

I know how to setup for basic rendering. My next step in learning is to understand this low level stuff.

Description for GLFW states that it's a library for OpenGL or OpenGL ES. And we're in DirectX section, so this is not very helpful for me. Thought I got an idea, there's still a question - what to do if the user selected an adapter with zero outputs?

If you want to use DirectX, maybe look into SDL as a library. http://libsdl.org/
By using i.e SDL_GetNumVideoDisplays, SDL_GetNumDisplayModes, SDL_GetDisplayMode, SDL_GetDisplayName and so on you can build a nice list of all adapters and their available fullscreen-modes for the user to choose from.

Any adapters without available modes you'd ignore and not show.

If you would want to do that without any library, which i, and probably everybody else, would strongly suggest you do not do, you would use win32 api to do pretty much the same as written here: https://msdn.microsoft.com/en-us/library/windows/desktop/dd162611(v=vs.85).aspx

@ninnghazad, I see you misunderstood a question. I know how to obtain all the information I need (btw, why are you strongly suggest not do so?). All I want to know how to use this info or how other do it.

One more example - I have a laptop with 2 gpus. Obviously that only one - integrated gpu have an output. The more powerful discrete gpu don't have outputs. Following your words I should ignore it. But of course I shouldn't and in fact I'm using only it for games. But how does system knows where to output a picture in that case. Personally for me EnumOutputs() looks useless for the scenario with more that one gpu.

1. Call IDXGIOutput::GetDisplayModeList. It will give you the list of possible resolutions and refresh rates that you can use for creating your fullscreen swapchain on that particular monitor.

2. Many games actually don't handle multi-GPU and multi-monitor very well: they'll just default to the first adapter and use the first output on that adapter. What I would probably do is have either a configuration dialog or command line options that let advanced users pick which GPU to use, and then pick which monitor to use. If they just use default options, then you can just do what other games do and use the first adapter and the first output from that adapter. This will always be the "primary" display for Windows, so it's usually not a bad choice. If the user picks an adapter that has no outputs, then you can either try to gracefully fall back to a different adapter that does have outputs, our you can just output an error message.

3. Like I said above, I would probably just default to the first output and then provide an advanced settings menu for letting users choose a different display. You could try and be smart by looking at all displays and picking the biggest, but I think that defaulting to the primary display is still a sensible choice.

4. For windowed mode you just find out the size of the window's client area, and then use that for your backbuffer size when creating your swap chain. Or alternatively, just specify 0 as the width and height when creating your swap chain and it will automatically use the client area size. To handle resizing, you just need to check for WM_SIZE messages from your window and then call IDXGISwapChain::ResizeBuffers to resize the back buffer. Once again you can either ask the window for its client area size, or just pass 0 to let DXGI do that for you. Also if it's not convenient to handle window messages, you can instead just ask the window for its client area during every tick of your update loop, and then call ResizeBuffers if the size is different from last frame.
I use directX and have the following "strategy":

- pick 6 (or any other number you want to support) resolutions you want to support
- when creating the settings menu for resolutions, I check these resolutions on the used hardware (the way MJP mentioned), only the supported ones are added and visible in the menu
- make your hud and especially the positioning of the individual elements scalable, based on the active resolution
- don't forget to recreate your buffers and projection matrix

You can check out the result in my recent game:
http://www.crealysm.com/games/booh_setup.exe

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me


- pick 6 (or any other number you want to support) resolutions you want to support

What advice is this??? You just ignore user's desktop native resolution, that his screen is designed and calibrated for, and force one of your 6 ratio-fitting luckily resolution's no matter what?


- pick 6 (or any other number you want to support) resolutions you want to support

What advice is this??? You just ignore user's desktop native resolution, that his screen is designed and calibrated for, and force one of your 6 ratio-fitting luckily resolution's no matter what?

It's a very common scheme.

The problem is with 2D graphics. You have two approaches.

1) Scaling : You design at one resolution and then scale the results to the users viewport.

Pros:

Works in all resolutions

Simple to implement

Cons:

Scaling artifacts can make your pretty graphics look shit.

If the screen resolution is a lot smaller than design, interacting with gui items can be impossible.

Gui interactions have to be scaled.

2) Layout: The layout of gui items is created at run time to support the screen resolution

Pros:

Graphics always look as designed.

Cons:

May not work in all screen resolutions.

Gui items can look too big or too small dependent on screen resolution

Can be complex to code due to landscape / portrait screen mode switch.

Because of this it is very common to pick a set of resolutions to support. You can then do things like use different assets for different screen resolutions. Different layouts, use scaling only on certain assets, all sorts of things.

The end result is a set of known to be 100% correct screen layouts.

You can do a half way house system and pick a set of assets and layout based on a near match of screen and design resolution, then use scaling to fudge it to the screen size.

However that usually looks poor when you have a case half way between two design sizes.

Thank you, guys.

I chose this approach:

  1. Allow the user to select from available gpus with outputs (i.e. if gpu doesn't have an output - ignore it).
  2. After swap chain creation I'm requesting for an output with swapChain->GetContainingOutput()
  3. Request for supported resolutions and refresh rates.
  4. For windowed mode I'm ignoring resolution selection, just resizing as MJP said.

This topic is closed to new replies.

Advertisement