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
Conversation
f9dbde1
to
c22b430
Compare
c181233
to
8072fec
Compare
'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()
f810bc3
to
014024e
Compare
Merging; @GranMinigun can complain later if he doesn't like something about the NPOT support 😄 |
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). |
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 themachine
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 tocrt-auto
, but this picks a fixed CRT monitor appropriate for the video adapter configured via themachine
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 forinteger_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
tosharp
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)
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
andvga-1080p-fake-double-scan
). I've tweaked all of them for equal brightness across the board, meaning if you switch between thesharp
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
EGA
CGA
Composite CGA
Arcade (15 kHz monitor)
Some oldsk00l Amiga pixel gfx 😎
Last one...
(I just love how it looks 😎 🤘🏻 )