Advertisement

SDL2 fulscreen - best resolution for retro 2D games on PC?

Started by September 01, 2018 09:01 AM
5 comments, last by The Geek on Skates 6 years, 5 months ago

Hey guys, what's up?

I've been building a 2D game with SDL, and I'd really like it to have that retro console/arcade look and feel.  This mostly because those are the kinds of games I play, and have since I was a kid, but also partly because 8-bit sprites or (S)NES sprite sheets are about as good as I get in terms of graphic design (lol).  But those old games had really small sprites, 8x8 at the least or 64x64 at the most.  And of course, those old consoles had a surprisingly small resolution of 256x240.  Another important note here: I'm really only targeting PCs for now; I know SDL can be ported to pretty much anything, but I only have my PC to test it on.  I'm also using Windows 10 x64 and Visual Studio 2017, if that helps.

So I started out by using "fake" fullscreen (passing SDL_WINDOW_FULLSCREEN_DESKTOP into the window creation functions).  But this turned out to be a problem because SDL's drawing functions are pixel based.  This is good IMOt, because it makes the math simpler and keeps the images crisper.  But you can't get half-a-pixel, so scaling to fit the player's desktop is literally impossible in some cases.  The end result is I had to draw black bars across the top and bottom, not just on the left and right.  If possible I would like to avoid that, so I switched to "real" fullscreen (SDL_WINDOW_FULLSCREE).  The lowest I could get it to go is 640x480, which is perfect (all image widths and heights can be multiplied by two to fill in the space).

But is 640x480 still supported on modern monitors?  The fact that it worked on my laptop is all well and good, but I'm afraid it would be a problem for others.  I remember using Game Maker (before it was a "studio") back in the early 2000s and that resolution was not an issue back then.  But is it still supported in 2018?  My laptop is relatively new (about 2 years old), a Dell running at 1366x768 normally.  If the answer is "no", what resolution(s) should I be using for this type of game?

Thanks & happy Labor Day weekend! :)

The Geek on Skates

http://www.geekonskates.com

Unless you're targeting CRT monitors, always use SDL_WINDOW_FULLSCREEN_DESKTOP.  SDL_WINDOW_FULLSCREEN relies on scaling at the monitor end, which looks terrible on LCD/LED monitors.

As for the half-a-pixel problem, you have several options:

  • You can render to a smaller texture and then render that texture across the whole screen (being careful to disable texture filtering, or it will look horrible).
  • You can use black bars.
  • You can use OpenGL instead of SDL's 2D rendering API.
  • You can use SDL_RenderSetLogicalSize and let SDL take care of the scaling for you.
Advertisement
36 minutes ago, The Geek on Skates said:

But you can't get half-a-pixel, so scaling to fit the player's desktop is literally impossible in some cases.  The end result is I had to draw black bars across the top and bottom, not just on the left and right.  If possible I would like to avoid that, so I switched to "real" fullscreen (SDL_WINDOW_FULLSCREE). 

You have to remember that an LCD screen is literally a grid of pixels, it only has one resolution. So the scaling needs to happen somewhere, better where you can control it.

Chances are it upscales until one dimension matches the monitors, then fills the other sides with some sort of background. But you have no control over this (there are settings somewhere in the AMD/NVIDIA/Intel control panels, plus I believe the monitor itself if it gets a wrong sized signal).

The algorithms used for upscaling blur the image, since the scaling is often fractional (e.g. 2.25 for 480->1080), and will be visible at any normal display DPI.

16 minutes ago, a light breeze said:
  • You can render to a smaller texture and then render that texture across the whole screen (being careful to disable texture filtering, or it will look horrible).
  • You can use black bars.
  • You can use OpenGL instead of SDL's 2D rendering API.
  • You can use SDL_RenderSetLogicalSize and let SDL take care of the scaling for you.

As such most of these will also do some form of scaling as well, so you need to decide what you want. To keep the games "viewport" the same size, you either get some blurring, or scale only integer amounts with a border around it. Visually the best result would be to change the viewport size to match, if you are say following a player character moving around a larger level that is easy, for some others it is not really practical.

 

Also as a player, most of the time I prefer borderless fullscreen, because alt-tab is instant that way, while switching exclusive mode is fairly slow.  Switching resolution also tends to mess up my other displays with chat, browsers, etc. for some reason.

Thanks for the quick replies! :)

To the first post:

  • I couldn't find "SDL _ RenderSetLogicalSize" in the SDL documentation or even on Google.  Visual Studio's IntelliSense ("auto-complete") didn't recognize it either.  
  • I'd rather not get into OpenGL for simple 2D stuff; I think I'd sooner switch to SFML or Allegro or something that is built primarily for 2D before I resort to that.  But good to know it can do that if I had to.
  • I'd like to avoid black bars if possible.  I knew they would be on the left and right at least, but I'd rather not have bars across the top and bottom (which was what would be necessary on weird resolutions like 1366x768.
  • This leaves me with your first idea. "You can render to a smaller texture and then render that texture across the whole screen (being careful to disable texture filtering, or it will look horrible)."  Would you mind explaining that a bit?  I've never heard of anyone doing this, and I've only just got started with the Texture API; last time I used SDL graphics were rendered using Surfaces (so noobie question... texture "filtering?").  But this idea of using a smaller texture and then somehow scaling that to fit the player's screen is exactly what I've been trying to do.

And to the second post, I appreciate the info on the hardware side.  You're right, technically monitors themselves only have one resolution.  And as a player I agree with you about borderless fullscreen.  All the emulators I play (NES/SNES/Genesis/Game Boy/etc.) are basically in windowed mode, and I use Windows Magnifier to get that borderless fullscreen.  But with those older games, that usually means the top or bottom of the screen is not visible.  And with aspect ratios ranging from 4:3 to 16:9 it's not like there's a straightforward way to have borderless fullscreen on all of them.  But what is this "viewport" you were talking about?  I know HTML/CSS has this concept of a viewport, but that's the only time I've ever read that word. :)

The Geek on Skates

http://www.geekonskates.com

38 minutes ago, The Geek on Skates said:
  • I couldn't find "SDL _ RenderSetLogicalSize" in the SDL documentation or even on Google.  Visual Studio's IntelliSense ("auto-complete") didn't recognize it either.  

http://wiki.libsdl.org/SDL_RenderSetLogicalSize

40 minutes ago, The Geek on Skates said:

This leaves me with your first idea. "You can render to a smaller texture and then render that texture across the whole screen (being careful to disable texture filtering, or it will look horrible)."  Would you mind explaining that a bit?  I've never heard of anyone doing this, and I've only just got started with the Texture API; last time I used SDL graphics were rendered using Surfaces (so noobie question... texture "filtering?").  But this idea of using a smaller texture and then somehow scaling that to fit the player's screen is exactly what I've been trying to do.

 

http://wiki.libsdl.org/SDL_SetRenderTarget

Awesome!  SDL_RenderSetLogicalSize was exactly what I was looking for.  Thanks. :)

The Geek on Skates

http://www.geekonskates.com

This topic is closed to new replies.

Advertisement