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

Authentic adaptive CRT shaders #2777

Merged
merged 32 commits into from Aug 31, 2023
Merged

Authentic adaptive CRT shaders #2777

merged 32 commits into from Aug 31, 2023

Conversation

johnnovak
Copy link
Member

@johnnovak johnnovak commented Aug 21, 2023

I've decided to write the release notes for this one now and paste it here. I intend to continue this practice, at least for major features.

A bit long, but an important feature like this must be properly explained, plus most of it will be eventually lifted into the manual. Definitely not wasted effort.


Authentic adaptive CRT shaders

We are happy to announce that we've removed all CRT shaders previously bundled with our releases.

Every single one of them.

What the @^$*%#!!!?? Have these guys gone mad??!

The reason for removing them is that they got replaced with something far better: a set of no less than 21 CRT shaders tweaked to perfection to emulate the glorious PC CRT monitors of the past, including authentic recreations of Hercules, CGA, monochrome CGA, composite CGA, EGA, and VGA monitors.

21 new CRT shaders sound a lot—how will someone not intimately familiar with PC CRT monitor technology know which is the best for a particular game? Well, the good news is you don't need to know—DOSBox Staging automatically picks the best shader variant based on the current video mode and viewport resolution. High-DPI and displays from 720p to 4k resolutions are fully supported and absolutely no manual configuration is required!

The following "magic" glshader options have been introduced:

  • crt-auto — This is the new default—an adaptive CRT shader that prioritises developer intent and how people experienced the game at the time of release. The appropriate shader variant is automatically selected based on the graphics standard of the current video mode and the viewport resolution, irrespective of the machine setting. This means that even on an emulated VGA card you'll get authentic single-scanned EGA monitor emulation with visible "thick scanlines" in EGA games.

  • crt-auto-machine — Similar to crt-auto, but this picks a fixed CRT monitor appropriate for the video adapter configured via the machine setting. So CGA and EGA games on an emulated VGA adapter will appear double-scanned with big chunky pixels, just like on a real VGA monitor.

  • crt-auto-arcade — This fantasy option does not exist in real life, but it can be a lot of fun! It emulates a 15 kHz arcade or home computer monitor less sharp than a typical PC CRT with thick scanlines in low-resolution modes. Playing VGA DOS ports of Amiga games with this setting will give you that authentic single-scanned Commodore monitor look—now you can experience Amiga games with MT-32 or SC-55 sound from a strange parallel universe! 😎

Adaptive CRT shaders work in tandem with the new integer scaling feature to achieve the most optimal results. The default auto setting for integer_scaling auto-enables vertical integer scaling for adaptive CRT shaders only. This is to avoid unwanted interference patterns that can result from non-integer vertical scaling ratios.

If you don't like CRT shaders, no problem—you can simply set glshader to sharp in your config to revert to the previous behaviour. Naturally, you can continue to use regular GLSL shaders like before. And if you'd like to experiment with the deprecated CRT shaders, they're still available as a separate download.

(This will be a sidenote section)

One problem with the previously bundled shaders was that they lacked proper documentation, so it wasn't clear which shader was meant for what monitor resolution (some were tuned for 1080p, some for 4k, etc.) Moreover, most were designed to emulate arcade monitors or TV sets from the 80s and early 90s; these displays had very different characteristics from PC monitors. Because of all this, many people were not getting the results they were hoping for from them and gave up on CRT shaders altogether.


Technical notes

Some further comments (these are not part of the release notes):

  • I've spent a lot of time tweaking and optimising these 21 presets. 19 of them use a custom hacked version of crt-hyllian (I grafted some other stuff on top of it from other shaders), and two are my own creations that I cobbled together from various bits and pieces (vga-1080p and vga-1080p-fake-double-scan). I've tweaked all of them for equal brightness across the board, meaning if you switch between the sharp shader and any of these CRT shaders, in most cases you will get the same perceptual brightness (or very close). I'm gonna do some further testing and tweaking over the coming week or so, but these are 90% already there.

  • The actual shader-switching implementation is as sophisticated and elegant as a sledgehammer. But—just like a sledgehammer—it does its job very effectively. Whenever we're switching to a new shader, 1) the shader gets loaded from disk, 2) it gets compiled, 3) then we reinit the whole renderer—all from the main thread! Yeah, fuck it 😎 It all takes only about 15-20ms though, so this works out fine. This definitely results in a small audio pop about 50% of the time, but very few games do actually switch between resolutions, and even if they do, they don't do it all the time, and even for these handful of games, the mode switching will not necessarily result in shader switching (it depends on the modes in question and the resolution of the viewport). Then for entering/exiting fullscreen or changing the window size, it's a moot point as those operations already introduce a small pause and thus a very audible gap in the audio emulation anyway.

  • If someone wants to optimise this and perhaps cache the shader sources, or maybe even store the compiled shaders in a cache, or perhaps do things in a more clever way without doing a full RENDER_Init on switching, be my guest. I guarantee you it won't be easy, though, and it most certainly won't be me as I consider this fit for purpose—for now. Also be aware that this will be throw-away work... The next evolution of the adaptive shaders will be implemented as a single mega-shader that we only compile once and then dynamically set various shader parameters at runtime. This mega uber-shader approach is what most modern games do and that will result in effectively zero lag. But a few other things will need to be in place before we can do that, so more on that later (proposal coming at some point, etc.)

Some screenies

At 4k only (open in new tab, zoom in, etc.)

VGA

image0008-rendered

image0009-rendered

image0003-rendered

image0006-rendered

EGA

image0005-rendered

image0007-rendered

CGA

image0039-rendered

image0038-rendered

Composite CGA

image0040-rendered

image0043-rendered

image0044-rendered

Arcade (15 kHz monitor)

Some oldsk00l Amiga pixel gfx 😎

image

image image image image

Last one...

image

(I just love how it looks 😎 🤘🏻 )

@johnnovak johnnovak force-pushed the jn/dynamic-shader-simpler branch 18 times, most recently from f9dbde1 to c22b430 Compare August 23, 2023 02:40
@johnnovak johnnovak self-assigned this Aug 23, 2023
@johnnovak johnnovak added enhancement New feature or enhancement of existing features video Graphics and video related issues labels Aug 23, 2023
@johnnovak johnnovak changed the title DO NOT REVIEW Authentic auto-adapting CRT shaders Aug 23, 2023
@johnnovak johnnovak changed the title Authentic auto-adapting CRT shaders Authentic adaptive CRT shaders Aug 23, 2023
@johnnovak johnnovak force-pushed the jn/dynamic-shader-simpler branch 2 times, most recently from c181233 to 8072fec Compare August 23, 2023 08:00
@johnnovak johnnovak marked this pull request as ready for review August 23, 2023 08:46
@johnnovak johnnovak requested review from kcgen, GranMinigun and FeralChild64 and removed request for GranMinigun August 23, 2023 08:46
johnnovak and others added 22 commits August 31, 2023 10:36
'Resources' also ignores 'contrib/resources' on case-preserving file
systems (Windows and macOS).
These shaders have been a constant source of confusion because:

- They're not documented -- a new user wouldn't know which one to pick
  based on the cryptic shader names alone.
- Many of them assume a specific output resolution (e.g., 4k) and look
  quite bad on 1080p, but you don't know that only looking at the
  shader's name.
- Most of them require further tweaking to get optimal results on
  specific output resolutions.
- Most of them don't even aim to emulate the characteristics of PC
  monitors that are quite distinct from arcade monitors, home computer
  monitors, or TV sets from the 80s/early 90s.

Because of the above, we are not bundling them with future DOSBox
Staging releases anymore; they are replaced by the new dynamic shader
system that picks the best CRT shader variant based on the graphics
standard in use (CGA, EGA, VGA, etc.) and the available viewport
resolution (1080p, 1440p, 4k, etc.)

These SVN shader will still be available as a separate download for
people who want to experiment with them.
- All shader management code has been moved from 'render.cpp' to
  the ShaderManager.

- The 'default' shader alias to 'interpolation/sharp' has been replaced
  with the 'sharp' alias.

- Three new adaptive (auto-switching) CRT emulation shader modes have
  been added: 'crt-auto', 'crt-auto-machine', and 'crt-auto-arcade'.
  These modes switch dynamically between CRT shader variants depending
  on the current video mode, the graphics adapter in use, and the
  viewport resolution (see the description of the 'glshader' setting for
  further details).
With the 'integer_scaling = auto' setting, vertical integer scaling is
auto-enabled for adaptive CRT shaders only, and only if a CRT shader is
actually in use, but not for the fallback 'sharp' shader.
After the double-scanning & pixel-doubling changes, a few video mode
pairs became indistinguishable when only looking at the render
parameters. E.g., the render dimensions of the 320x200 (standard BIOS
mode 13h) and 320x400 (non-VESA Mode X variant only) modes are both
320x400, so they were considered the same by the mode-change detection
logic prior to this adjustment.

The solution is to include the contents of the VideoMode struct in the
mode-changed criteria (in this example, that would contain the "nominal"
dimensions of 320x200 and 320x400, respectively).
These have been superseded by VideoMode.to_string()
@johnnovak
Copy link
Member Author

Merging; @GranMinigun can complain later if he doesn't like something about the NPOT support 😄

@johnnovak johnnovak merged commit ae86c03 into main Aug 31, 2023
56 checks passed
@GranMinigun
Copy link
Contributor

I don't like having over 9000 pragmas, but whatever. Here, I complained, and later.

@johnnovak
Copy link
Member Author

I don't like having over 9000 pragmas, but whatever. Here, I complained, and later.

The good news is we have 5, so long way until we hit 9000 😄 We can use either pragmas or an extra metadata file per shader. Hardcoding info about shaders is the worst possible solution, bye bye extendability by the user.

Custom pragmas are supported, even encouraged by the standard to store metadata, look it up. They are used by RA shaders too to add metadata to tweakable shader param uniforms, such as labels and parameter ranges. Which is nice.

So, I guess liking or disliking them is immaterial as they're the only practical solution 😄 (unless you add an extra metadata file for each shader, which has pros and cons).

@kcgen kcgen deleted the jn/dynamic-shader-simpler branch September 26, 2023 21:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or enhancement of existing features shaders Issues related to shaders video Graphics and video related issues
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

None yet

5 participants