Emulator Issues #12725
openPixel Perfect / Integer Scaling mode
0%
Description
Hey there, Dolphin people!
Lately I've been playing around with Dolphin on an old 4:3 CRT computer monitor and I'm having a lot of fun. Playing games in 480p with progressive scan is just fantastic.
With that said, in my quest to get the most accurate, console-like experience out of the emulator and the monitor I came across an issue that probably doesn't bother a lot of people, but I felt it was worth mentioning anyhow.
I don't really know what the proper place to post this finding is, but I'll put it here for now. Also, I'm by no means an expert on any of the things I'm about to show, so I'd appreciate it if someone more knowledgeable could correct me.
What I found is this: there is no way to consistently display games in 480p without some sort of scaling taking place (I'm guessing it's bilinear filtering but I'm not sure).
Here are the tests I did (you might have to zoom on the pictures to see the scanlines):
Booted up Sonic Riders in a 640x480 fullscreen window with the aspect ratio set to "Auto" and I got these scaling artifacts:
(Notice the uneven pixel crawl, the blue halo around Sonic and the dark halo around the light beam)
By taking a screenshot, I figured out that the native resolution of the game is 584x480, so I tried the "Force 4:3" and "Stretch To Window" modes and the poor scaling went away on the stretched image:
(Notice the even pixel crawl, and how the edges have perfect contrast with no halo)
I don't really know why this worked. My only guess is that it might have something to do with a CRT not having a fixed pixel structure.
Sadly, this trick only works with games that have to be stretched horizontally.
I took a screenshot of Mario Sunshine and found out its resolution is 640x476, which means that a couple of lines of pixels are cut from the top and bottom part of the screen. This doesn't sound like a big deal at first. However, with how Dolphin's video modes work, this ends up messing up the entire image.
Whereas Sonic Riders was scaled horizontally in "Auto" mode, Mario Sunshine is always scaled vertically no matter what aspect ratio you choose:
"Auto":
"Force 4:3" and "Stretch To Window":
(Notice the uneven pixel crawl and the red halo above Mario, or the dark one above his shoes and his shadow)
I'm guessing all of this could probably be fixed by implementing a Pixel Perfect / Integer Scaling mode. This way, all the pixels that aren't used would simply be black, and all the active pixels would line up with the scanlines or the pixel grid of the display. This wouldn't just benefit CRT users, but also owners of 480p LCDs and people who use HD TVs / monitors who don't mind having black bars around the image.
I know this feature is probably not as easy to implement as it sounds, but it would be a welcome one nontheless. But maybe there are other ways...?
I'm looking forward to your feedback! :)
P.S. "Crop" doesn't fix this, if anything it introduces more scaling on both axes...
Files
Updated by phire about 3 years ago
in my quest to get the most accurate, console-like experience out of the emulator and the monitor
Ok... There are some issues with your quest here.
First, a real console simply doesn't output perfect pixel like you are expecting from dolphin. In-fact dolphin outputs significantly "cleaner" pixels, as it skips several steps of blur. The clean image quality you are striving for simply never existed. By default, games always do both vertical and horizontal bluring, and most games do horizontal scaling. All PAL games apply a vertical scaling.
Even in the games that go out of their way to offer a mode that minimise this (like Melee's disable AA filter mode), the vertical blurring incurred from the YUVU framebuffer is impossible to disable on real hardware.
If you want an accurate console experience, we should actually be adding more blur.
Second, The video used by the GameCube and Wii (REC.601) has non-square pixels. 0.91:1 in NTSC and 1.09:1 in PAL. It's simply impossible to accurately portray this on a video mode with 1:1 square pixels, like 640x480 @ 60HZ VGA. Either you need to do some form of scaling (like dolphin currently does) or you end up with an incorrect aspect ratio.
However, I admit the experience could be better for this kind of usecase. At the very least, it should be easy to configure dolphin to a mode that actually showed the correct number of vertical lines with overscan/padding. Such a video mode would still need scaling along the horizontal for the majority of games, but at least you would only have scaling along one axis, and it happens to same axis that composite video really struggles with (and that a real console always has some amount of forced blur).
It would also be nice to have higher quality scaling algorithms, that's already on the todo list.
Updated by JosJuice about 3 years ago
- Tracker changed from Issue to Emulator Issues
- Project changed from Infrastructure to Emulator
- Issue type set to Bug
- Regression set to No
- Relates to usability set to No
- Relates to performance set to No
- Easy set to No
- Relates to maintainability set to No
- Operating system N/A added
Updated by tccalvin about 3 years ago
Ok... There are some issues with your quest here.
Yes! Thank you very much for your feedback. After I did some further testing I figured out I got some information wrong.
First of all, I re-took my screenshots in windowed mode with "auto-adjust window" turned on, and Sonic Riders actually runs at 636x524, which makes a lot more sense.
Turns out I was squeezing the picture in a 640x480 window, which isn't how real hardware behaves (with overscan cropping and all that).
I also read one of your posts on Reddit about "antialiasing" on Gamecube, which made me understand things better.
To be clear, my goal isn't to get hard pixel edges like in a 2D game (I apologize if there was a misunderstanding), I just want the scanlines to line up properly with the game resolution and the pixels to be horizontally even like real hardware displayed on a CRT (with whatever blur might be applied by the console). In short, no post-scaling artifacts.
However, I admit the experience could be better for this kind of usecase. At the very least, it should be easy to configure dolphin to a mode that actually showed the correct number of vertical lines with overscan/padding. Such a video mode would still need scaling along the horizontal for the majority of games, but at least you would only have scaling along one axis, and it happens to same axis that composite video really struggles with (and that a real console always has some amount of forced blur).
It would also be nice to have higher quality scaling algorithms, that's already on the todo list.
My proposal here (as much as it's worth) would be to implement something along the lines of what Nintendo did with the SNES mini, which (iirc) offered a 1:1 pixel perfect mode with no shimmering (albeit with an incorrect aspect ratio), and a 4:3 mode with pixel interpolation (which minimized shimmering). I seem to remember the SNES also had non-square pixels.
Easier said than done, obviously.
The reason I'm saying this is that CRT displays could do without any form of horizontal scaling, since they can adjust the image after it has been sent to the screen, due to them not having a fixed pixel structure. So the correct aspect ratio could be achieved without the emulator doing any scaling (when set in 1:1 PAR). To my knowledge, LG OLEDs also have this "resizing" feature, and while they do have a fixed pixel structure, the pixel density is so high that you wouldn't notice any scaling.
As far as 480p LCDs are concerned, a 1:1 pixel mapping would definitely have an incorrect aspect ratio, however it would arguably be more "CRT-like", meaning that the vertical lines in excess would be vertically cropped and there wouldn't be any horizontal scaling since the pixels would be square (as opposed to having a forced aspect ratio where there would be scaling all over the place).
In a dream scenario, this would also apply to higher rendering resolutions, meaning we could have an EFB of 1280x1056 show up without cropping in a 1:1 pixel mapping on a 1080p screen without any horizontal scaling and so on.
Plaese forgive my ignorance in case I got anything wrong. I'm hoping to learn more from you guys! :)
Updated by phire about 3 years ago
The reason I'm saying this is that CRT displays could do without any form of horizontal scaling, since they can adjust the image after it has been sent to the screen, due to them not having a fixed pixel structure
Ok, yes they could.
But as far as I'm aware, there has never been a sane OS API that actually lets you output non-square pixels over VGA, or even composite. If there was (and if the install-base of CRT monitors was a bit higher) then it would be interesting for dolphin to support.
You could probably hack it together with custom screen modes and manually telling dolphin what the current pixel aspect ratio is, but then you run into problems that different games use different pixel aspect ratios, and some games will probably switch on the fly. It really needs to be dolphin directly controlling the display mode to make any sense.
IMO, it's simply not worth investing any development, code-complexity and support effort in this direction.
To my knowledge, LG OLEDs also have this "resizing" feature, and while they do have a fixed pixel structure, the pixel density is so high that you wouldn't notice any scaling.
Which is actually a very good point. In theory dolphin could upscale 1x IR image to 4K using a high-quality upscaling filter and achieve identical results.
In the future, dolphin will support high-quality custom upscaling/downscaling algorithms as post-processing shaders. You could choose between a high quality bicubic (or AMD's FSR) for smooth resampling that looks a lot better than bilinear's blurry mess. Or choose an upsampling algorithm that tries to preserve the a more pixelated feel without resorting to full nearest neighbour.
In a dream scenario, this would also apply to higher rendering resolutions, meaning we could have an EFB of 1280x1056 show up without cropping in a 1:1 pixel mapping on a 1080p screen without any horizontal scaling and so on.
I'm not sure what you want here? Do you mean with massive black bars on all four sides?
Updated by tccalvin about 3 years ago
IMO, it's simply not worth investing any development, code-complexity and support effort in this direction.
I definitely agree. Thankfully that's not necessary at all.
Here's a little experiment I did with integer scaling in RetroArch:
This is the staircase in the first level of Castelvania Symphony Of The Night, running in 480p (I'm using a 2x nearest neighbor scale from 240p):
Here I used the emulator's options and set the aspect ratio to "corrected", and it's a big mess, with some pixels being square and others being rectangular, and in motion it's even worse because they switch sizes basically every frame, creating shimmering. But the aspect ratio is actually correct.
If I understand it correctly, the Dolphin approach is to keep this correct aspect ratio and add blur to make the uneven pixels less noticeable, which is one way of solving the issue.
Another way would be this (using the "uncorrected" aspect ratio):
Here, the pixels are all square, which makes scrolling smooth as butter, but at the cost of having an incorrect aspect ratio. Some people wouldn't want to play like this, and I understand that point of view. However, I would argue that the trade off is worth it because you get the even pixels you would get on a CRT (if narrower ones), which gets you less shimmering.
Thankfully, I'm lucky enough to have a CRT VGA monitor, so I don't have to make that choice. I can pick the square pixels option and then go into the monitor's OSD and stretch the image horizontally to get my correct aspect ratio:
(Here I stretched the image as far as I could to show the rectangular pixels.)
So yeah, no need to output non-square pixels. And like I said, it's not just CRT users that benefit from this, but also owners of screens with "resizing" features (with results varying in quality depending on the resolution of the display).
But then again, even without resizing some users could just prefer having a slightly narrower or wider image if it means having no scaling blur. All I'm saying is that it would be nice to have the option.
Which is actually a very good point. In theory dolphin could upscale 1x IR image to 4K using a high-quality upscaling filter and achieve identical results.
Yes, that would be a user-friendly way of doing it! :) (if maybe a bit more expensive in terms of rendering...?)
In the future, dolphin will support high-quality custom upscaling/downscaling algorithms as post-processing shaders. You could choose between a high quality bicubic (or AMD's FSR) for smooth resampling that looks a lot better than bilinear's blurry mess. Or choose an upsampling algorithm that tries to preserve the a more pixelated feel without resorting to full nearest neighbour.
I'm looking forward to that! :)
Is there anything wrong with nearest neighbour though...?
I'm not sure what you want here? Do you mean with massive black bars on all four sides?
Uhm... well, let's take Sonic Riders as an example (runs at 636x524 which is very close to the full 640x528 resolution of the EFB).
We could run it at 2x IR and get 1272x1048, which on a 1080p screen would leave 648 black pixels horizontally (1920-1272), and 32 black pixels vertically (1080-1048). It would have an incorrect aspect ratio but it would fit pretty nicely and have a 1:1 pixel mapping with no scaling. 1080p is a pretty popular resolution and I can see how some users could prefer to play this way instead of having scaling.
Again, I apologize for any mistakes! :)
Updated by tccalvin about 3 years ago
EDIT: Did some further testing and found out Dolphin's render window is not to be trusted when trying to pixel count... So yeah, ignore the numbers I gave about games running at certain resolutions (next time I'll learn not to take shortcuts when pixel counting). The point still stands though, whatever the native game resolution might be.
Updated by tccalvin about 3 years ago
UPDATE: If anyone wants to know, I did some manual pixel counting and Sonic Riders outputs 640x480 pixels, which explains how I was able to get no scaling when displaying it in a 640x480 window, whereas Mario Sunshine outputs 640x448, which is why, in a 640x480 frame, it only produces vertical scaling.
Obviously a pixel perfect mode would just turn off the 32 extra vertical lines and we would get no scaling in a 640x480 window.
As a bonus, I also pixel-counted Paper Mario TTYD, which is the complete opposite, it outputs 600x480, meaning it only needs horizontal scaling.
Again, pixel perfect means the image gets narrower, but that also means no scaling. Like we said, however, there are ways to get the proper aspect ratio after the image has been sent to the screen.
Updated by JosJuice almost 3 years ago
- Has duplicate Emulator Issues #12861: [Feature Request] Add support for integer scaling and nearest neighbor filtering added
Updated by taolas over 2 years ago
Is integer scaling just like using "auto-adjust window" with a high IR and then downscaling by a whole number so it fits on the screen? And should (IR / Integer Scale) be a whole number?
Updated by tccalvin over 2 years ago
I've read of this technique but I've had no luck with it so far. Set Window to Auto-adjust and tried auto, 4:3, and stretch to window aspect ratios. All these options always give me an incorrect internal resolution no matter what I do.
If you can help me understand your settings I might be able to answer your question though. Also, how do you downscale your window by a whole number exactly?
As for your second question, yes, integer basically means a whole number. Nearest neighbor scaling means multiplying the resolutions by 1x, 2x, 3x etc.
The thing is that as of now Dolphin always stretches the image to either a certain aspect ratio or to a window/fullscreen size. This means you will get scaling to sizes that are not integer (for ex. 1.25x or 1.5x) and that will cause the blur filtering to kick in to hide the fact that the pixels are of different sizes (for ex. two 1.5x pixels become a 1x pixel and a 2x pixel, distorting the image).
Updated by taolas over 2 years ago
So the correct resolution will be the XFB copy size that is output? And you can check it with the dump xfb option?
The "Dump at internal resolution" does not dump at the xfb size, so that must be the upscaled IR size and is affected by window aspect ratio when using stretch.
I used a program called Sizer and dolphin set to Stretch to set the window to the correct size, but the window border was included in the size, so I used an xfb image to help resize the window manually. I was then able to take a dolphin-screenshot and it came out to the correct 640,448 dimensions. The sizer size was 642,480. It sounds close to 640,480 but it is counting the bulky top of the rendering window.
Once I knew the correct window size I played around with it and, yeah, no combination of options resize the game to the xfb size.
So the goal is to get the xfb size and then set the window size to that or a multiple of it? If the window size is 2x, should 1xIR and 2xIR look the same? If not what should the IR be set to?
Updated by taolas over 2 years ago
The XFB size is accessible from the code that sets the render size. So I hacked the render/screen size to be equal to a multiple of the xfb size. Left is 2x IR, 2x XFB screen size megaman. Right is normal 2x IR, normal auto-scale screen size megaman. Is the left one more correct? Sorry the background is a little different.
Updated by taolas over 2 years ago
Ugh sorry, can't edit my old post.
I realized I could compare the two pictures to a 2xIR XFB dump. The result was that the megaman on the left was pretty much identical to the xfb copy. I think integer scaling to the XFB size should definitely be supported.
I am curious how scaling based on xfb aspect ratio would work.
Updated by tccalvin over 2 years ago
So the correct resolution will be the XFB copy size that is output? And you can check it with the dump xfb option?
The "Dump at internal resolution" does not dump at the xfb size, so that must be the upscaled IR size and is affected by window aspect ratio when using stretch.
I think you've figured it out. I did some testing on my own and I think you're right. The XFB is the real internal resolution of the game.
So the goal is to get the xfb size and then set the window size to that or a multiple of it?
Yes, that would be it for windowed mode. In fullscreen mode the image should be centered and take as many pixels as it needs. For example:
If the fullscreen resolution is 640x480 and the XFB is 640x448, the resulting image should be 640 pixels wide and 448 pixels tall, with the unused resolution lines being black on the top and the bottom of the screen.
Let's say the screen resolution is 1080p, XFB is 640x480. We use a 2x scale to get 1280x960. The image is centered so there are black bars on the top, bottom, left and right, but every pixel of the XFB corresponds to a pixel of the screen. And so on, you get the idea.
If the window size is 2x, should 1xIR and 2xIR look the same?
We should make a difference between the rendering resolution and the scaled output resolution. This is the easiest way I can explain it:
2xIR means double the rendered pixels
A 2x integer scale means that the rendered pixels are double the size (they become chunky squares)
You can combine the two things to get whatever result you like.
A picture as an example:
The image on the left is an XFB dump at 1xIR with a 4x integer scale (using zoom in MS paint), the image on the right is another XFB dump at 2xIR using a 2x integer scale (again, paint).
In the end, the resolution sent to the screen is the same (608x480 x 4 = 2432x1920), but the second image has double the internally rendered pixels, so it's smoother and less blocky.
So I hacked the render/screen size to be equal to a multiple of the xfb size.
Any chance of this option coming to us non-coding people? ;)
Is the left one more correct?
I wouldn't say it's more "correct". It's a trade off. Megaman looks a lot skinnier but you get even pixel width. The Dolphin approach is to keep a somewhat "correct" aspect ratio but display uneven pixel width, which leads to shimmering, aliasing, blur and other bad stuff. It's especially bad in 2D games where the pixels consistently shift between being 1 pixel wide and 2 pixels wide basically every frame.
The best way to solve this is a pixel interpolation algorithm that slightly blurs the edge of pixels to make them appear the same size even though they're not. It's not perfect but it's the best solution so far. You can find such algorithms in the SNES mini, in NES games from the NSO service, in the Retrotink 5x etc.
This is generally done to keep a 4:3 aspect ratio (which is not always "correct") even when the internal resolutions are not 4:3 (and many aren't).
Honestly though? I don't mind playing games with slightly incorrect aspect ratios if I can get them to display even pixels.
For example:
This looks pretty nice to me, if a bit wide. I would totally play the game like this.
So what I would like is a couple options to turn on integer scaling and/or pixel interpolation. I'm sure many would appreciate.
Updated by taolas over 2 years ago
https://github.com/dolphin-emu/dolphin/pull/10720
You can download and try it, if you go to the link, expand checks at the bottom, then click details for the build you want. The builder page will open with a link at the bottom.
Graphics -> general has two new options. With Integer, expand the window and it will scale to the maximum it can based on the size, or just use fullscreen. Tell me if it does what you expect. I'm also interested if Internal aspect ratio, with no Integer Scaling is useful at all.
Updated by tccalvin over 2 years ago
Tell me if it does what you expect.
I mean... I have no words. You've done it!
The internal resolution perfectly matches the scanlines on my CRT:
And on fixed pixels displays it would perfectly match every pixel. Looks great.
I'm also interested if Internal aspect ratio, with no Integer Scaling is useful at all.
It could be useful, in the sense that one could choose to sacrifice even pixels to fill the screen, and still keep an aspect ratio that might be considered more "correct" by some people. For example, there might be instances in which 4:3 or the default aspect ratio cannot display perfect circles or squares, but the XFB aspect ratio does.
In any case, having more options is always nice.
I'm not sure how exactly Dolphin development works, but is this a feature that could carry over into later versions of the emulator? If so, it would be a huge win.
Another big feature would be the option to choose the scaled output resolution (1x, 2x, 3x etc.). For example: on a 4k screen, with an XFB resolution of 640x480, you might be torn between using a 4x scale to reach a height of 1920 pixels with black bars around the image, or you could choose a 5x scale to get a 2400 pixel height, which would vertically fill the screen at the cost of having some of the image cut off, which isn't a huge deal since that's how overscan used to work on old CRTs (there's even a "crop" feature in the graphic options that does just that, albeit with the usual stretched aspect ratio). This should be completely independent from the "IR scaling" option, which affects the internally rendered pixels.
In the future, if people are interested in this, we might even find someone willing to implement a pixel interpolation algorithm, so that we can have correct aspect ratios without the need for uneven pixels and scaling blur.
I think having more options would be great for everybody.
Anyway, thank you very much for your kind work and I hope you get as much enjoyment out of this feature as I do! :)
Updated by taolas over 2 years ago
Thanks for the quick testing, I'm glad it worked correctly! If the PR gets accepted it'll appear in official versions. I'll put in a manual option to select scale.
Pixel interpolation should probably come after the Post Processing rework. Does retroarch have a pixel interpolation that works like what you want? Sharp bilinear?
Updated by tccalvin over 2 years ago
If the PR gets accepted it'll appear in official versions.
Let's hope it does then! :)
I'll put in a manual option to select scale.
That would be awesome. Thank you! :)
Does retroarch have a pixel interpolation that works like what you want? Sharp bilinear?
Ok, so... I'm fairly ignorant about this, but I did some testing after looking at these posts:
https://forums.libretro.com/t/horizontal-interpolation-to-correct-par-after-integer-scale/28120
https://forums.libretro.com/t/problem-with-horizontal-scrolling/31779
I used the first level of Castlevania SOTN because it has a staircase made of identical pixels.
I turned integer scaling on with a 2x scale to get from 240p to 480p, and set the aspect ratio to "uncorrected" in the emulator (Beetle PSX) in order to get a 1:1 pixel aspect ratio:
This is a pixel perfect image but the aspect ratio is "skinny" like in Megaman.
I then set the aspect ratio to 4:3 and got this uneven mess (look at the staircase to compare):
Then I turned on the shaders and chose Sharp Bilinear (default settings):
Then I tried Bandlimit-pixel (default settings):
I think both shaders do the job quite well. The second one is maybe a touch blurrier but I haven't messed around with the settings at all. I've read that some prefer it over the sharper pixels. They both look good to me.
What I've shown in the pictures is horizontal interpolation only. That's because when using integer scaling the vertical resolution lines of old consoles line up pretty much perfectly with the vertical resolution of modern pixel grids.
The problem is the horizontal resolution because pixels on old consoles are mostly wide rectangles, whereas in modern displays they're perfect squares. That's why horizontal interpolation is what we want.
I think the reason this works so well in Retroarch is explained by this post by hunterk:
"RetroArch scaling works like this: integer scaling determines how the y axis is scaled and then the x axis is stretched to match the aspect ratio setting."
If you turn off integer scaling in Retroarch though, you can get interpolation on the y axis too. It's useful to fill the screen, but it gets blurrier, of course.
I'm not sure if Dolphin's stretching algorithm works like this, so this might be a challenge...
Updated by taolas over 2 years ago
- File 0integerscaling.glsl 0integerscaling.glsl added
Yo, try this attached shader in a normal dolphin build. Put it in dolphin.exe's folder / sys / shaders then enable it in graphics options.
Updated by taolas over 2 years ago
- File integerYbilinearX.glsl integerYbilinearX.glsl added
Oops, I left it green to debug it. You can open the file and set c0.g to 0.0.
Lots of great info in your last post. I tried to make another shader based on the Y = integer X = bilinear idea. I'll attach it.
Updated by tccalvin over 2 years ago
- File bad_ps_5_0_D3D_0.txt bad_ps_5_0_D3D_0.txt added
The first shader works wonders. I set the aspect ratio to "Auto" and it looks exactly like your custom build. Although in this case the in-game screenshots (F9) are probably taken pre-shader pass. Not a huge deal, just don't trust the resolution reported by the screenshots, the shader works as it should.
The second one gave me errors, unfortunately:
Sorry for the italian text, it means "error not specified"
It also created a file in the Documents/Dolphin Emulator/Dump folder, I'll attach it for you.
Updated by taolas over 2 years ago
Thanks. It looks like it only works on OpenGL. I'm not 100% sure I coded it correctly anyway.
Updated by taolas over 2 years ago
Oh man, I did some crazy stuff I didn't think I could do with shaders!
Hope you're still around to test. This shader has quite a few options, so be sure to hit the Configure button next to the shader choice. Also, as it says, please put aspect ratio to stretch or it gets a bit wonky.
Updated by tccalvin over 2 years ago
Did some limited testing and, from what I can see, it works! And it's great! It even works with DX11.
This is a huge feature for me and other pixel enthusiasts so thank you for your time and I hope it was fun to work on the code! :)
The nice thing about this being a shader is that it can be used as a plug in for later versions of Dolphin, another huge win.
My knowledge is quite limited but if I can help with anything else, let me know! :)
Updated by TheDimensioner over 2 years ago
This... was exactly what I was looking for, and I'm so glad for this to be a recent development! I wanted to play some Resident Evil 4, since the remake was announced and all, but I wanted the most original experience. The Game Cube release has warmer colors that only shine brighter on a CRT. I have a Wii with component cables and a nice 29" CRT, but it's not currently hooked up, and I'm too lazy to do it right now. But since I also have a nice 17" CRT monitor that I happen to be using daily, I just decided to emulate it using Dolphin at 480p. It didn't look nice...
This is already with the "stretch" option:
Disabling the "copy filter" makes things worse, as this game, as well as some others, create some kind of "square grid pattern", maybe because this is a lower than normal resolution:
This effect is so "there", that it even comes out in an internal recording (look at the tree branches in the middle):
Everything seemed a bit off. To confirm, I used the trusty go to app for any CRT lover, the 240p Test Suite for the Wii, in 480p:
It's obvious there's some kind of linear filtering / upscaling when I put the mouse cursor over the image to compare:
In real 240p (actually 320x240@120Hz), there's no issue, since it's the native resolution of the app, and everything fits perfectly on "stretch" mode, though at the wrong aspect ratio:
But this shader here fixed everything:
The 240p Test Suite now looks crispy sharp at 480p:
So, thanks @tccalvin for highlighting this issue, and thank you @taolas for developing a fix! I hope it gets merged in the official builds so anyone can get a taste of nice, crispy pixels!
Every image: https://imgur.com/a/8ZtHJKZ
Updated by taolas over 2 years ago
Great. Happy to see someone else is getting good results with it as well. If there are any other features this shader could use, let me know (more upscale/downscale support, y-axis stretching, a specific forced aspect ratio, etc), I just don't want to bloat it with things no one will use.
Updated by TheDimensioner over 2 years ago
@taolas Thanks again! Feature wise, one thing that would be nice to have is individual axis scaling. I've never been able to use RetroArch and all its fancy options, because it never worked for me, so I use Mednafen instead, which already gives some nice options for CRT users. Using Castlevania: Symphony of the Night as an example, as @tccalvin did, this is how it looks on my monitor:
This matches the look on my 29" CRT with the PS2, and it has no shimmering. I didn't use any shaders, only the scaling options of the emulator, with 5x horizontal, and 1x vertical, along with a custom 1280x240 monitor resolution:
I think they call it "super resolution", which is very useful for MAME machines that use CRTs. Arcade games have hundreds of odd resolutions, though it's mainly on the X-axis, so having a super resolution with a really high width mitigates the need for hundreds of individual small resolutions. I.e., most PSX games will have either a 256, 320 or 512 width along with a 240 or 224 height, so having a 2560x240 resolution filling the 4:3 screen will allow those games to fit nicely into the picture with a 10x, 8x, or 5x horizontal scaling at their correct aspect ratios. There's also the odd 384 width, which will fit inside a 7x scaling, though the black bars are so small you don't even notice, or you could go as far as to make a custom 384x240/224 res, just for those games. The problem are the games that keep changing their internal res, just like Symphony of the Night in the menus and such, though that's another story.
I'm sure the Game Cube and Wii also have a whole set of weird resolutions, so an option to view what those are would be nice. PCSX2 already shows it in the tittle window, and many PSX emulators also have options for viewing IRs.
Having an idea of how many custom widths the GC and Wii have, it's very easy to calculate a high number that fits them all, simply make that resolution using the GPU driver, and have the CRT monitor display that in full screen, while adjusting the X-axis scaling for each game, maybe in their respective .inis. The super resolution approach already worked for 240p games on Dolphin, like Mega Man X Collection, so having a 480p equivalent would be amazing!
Updated by taolas over 2 years ago
Trying to understand this and not sure I did it right, but here's my first try (attached). Set aspect ratio to 'stretch'. In the shader config choose scale width for CRT. On fullscreen, your monitor's Y resolution will control the Y axis and what you set internal resolution to will control the X axis.
My biggest confusion is how we are upscaling. I think it has to be done with Internal Resolution, or else it will be blurry. We can't just upscale the X-axis internal res, so the shader downscales the Y axis internal res to the monitor and outputs the unscaled X res (which is integer scaled by internal resolution).
The other issue is non-4:3 Y resolutions. If the resolution for Y is too tall, do we non-integer downscale it or do we crop?
Updated by TheDimensioner over 2 years ago
So, this last shader sort of works. I've set my monitor to 1280x480 and launched the 240p Test Suite. The image appeared "as it should", taller, and increasing the IR to 2x scaled it correctly:
https://imgur.com/xtp7krD
https://imgur.com/wqskdX7
https://imgur.com/reQR2r0
But RE4 didn't like it that much, as it still didn't fill the screen's width:
https://imgur.com/XTiPDI0
https://imgur.com/pfY2VBk
Using the former shader, it looked more "correct":
This new shader also doesn't work with native 640x480 anymore, as the image gets blurry, like without the shader at 480p.
What I've realized with the first shader is that, unlike with PSX games, GC and Wii games don't seem to have "wild" horizontal resolutions. Most games only have very small black bars, either on the sides, top and bottom, or all around.
So I finally decided to dust off my Wii for further testing, and discovered that those bars just get overscanned with most CRTs. The 240p Test Suite is actually "taller" on the Wii, as the top and bottom gets cut off on my TV:
https://imgur.com/H2caRD0
https://imgur.com/1M22cmc
There's also a 224p test grid, so we get to see the whole picture on SNES and Mega Drive games (256x224 and 320x224, respectively):
In 480i (mine, and most consumer CRTs, don't support 480p, even with component cables), the picture is even more cropped out:
Something that doesn't happen on my PC CRT monitor using Dolphin (stretched, with the former shader):
240p (2x scale): https://imgur.com/ZCu8avn
480p: https://imgur.com/FpiHYex
The Legend of Zelda: The Wind Waker is another "tall" game. Here's with no shader:
https://imgur.com/vBefn38
https://imgur.com/6gnjOcQ
Cropping the image gets rid of the bars:
https://imgur.com/5UU6Hd3
https://imgur.com/5tdazqo
Which is exactly what happens on real hardware:
https://imgur.com/laqHnqg
https://imgur.com/VnOsK2p
The image seems brighter because I had to set my phone's camera shutter speed to 30 for the 29" CRT pics, because that TV set seems to have thicker scanlines for whatever reason, and Wind Waker looked like it was set to 240p with the shutter speed at 60 XD:
Luckily, Wind Waker supports the force Deinterlace / Copy filter "off" option on Nintendont, so it looks somewhat as sharp as on the PC monitor. This is with the former shader, though notice how Link is "chubbier", since it's stretched to fill the screen:
So, my conclusion is that maybe an option to just set the X-axis is unnecessary, as most GC / Wii games seem to have basically the same width and wouldn't benefit from super resolutions (sorry for my unfounded conclusion in the last comment XD).
From what I understand, GC and Wii actually have taller Y resolutions, so maybe a crop option would be better suited. Though, I really don't know if it would be able match a, let's say, 480p framebuffer output without overlapping pixels, so it would need linear filtering, like Dolphin seems to do already.
But the former shader already works wonders, because a 2x integer scale inside a 1280x960 picture looks beautiful:
https://imgur.com/sEJ3BQC (I still prefer the scanlines that 480p gives XD)
https://imgur.com/BOam5XG
Perhaps it looks just like an OSSC, or RetroTINK-5x on real hardware and a flat panel (I don't have any of those, but there's plenty of videos showing just that around the web XD). And for those with 1440p monitors, I'm sure a fullscreen 3x scale (1920x1440) will look amazing, but the next viable scaling for 480p is only 9x at 8K (5760x4320), which I'm sure can be done already on some 8K TV using Dolphin!
Anyways, I really appreciate your effort with this, @taolas! After testing many games, I just started liking emulation that much more, because even with how advanced Dolphin is right now, it could still support the old hardware some people just can't leave behind (I sorta had a big "dilemma" in the past with Dolphin and my prehistoric PC with a 9600 GT that I wanted to support the newer builds, but it just couldn't, but that's another story XD). And as I mentioned, this also works for those with flat panels that want to play at native resolution, but now with a much sharper picture!
Every image: https://imgur.com/a/Sgo2LN3
Updated by taolas over 2 years ago
Woo thanks for being so thorough! I'm glad the old one turns out to be just fine, because I was having trouble with the updated one. I did add a manual integer width slider though: https://github.com/dolphin-emu/dolphin/pull/10722/files you can just copy it into a glsl file.
For 4:3 crop you could try to set "manual scale" in the shader options with its slider set equal to the IR probably, then "force 4:3" in the graphics options. I'm not sure, but it might give you the correct crop when the height it just a bit too much.
Updated by TheDimensioner over 2 years ago
Thanks, @taolas! I'll definitely try out the latest development, whenever I get a chance XD. It's been a blast playing games in 480p on my CRT monitor, now looking sharper than it was before. It's not that I hate 480i on the original hardware, but my 29" LG CRT seems to update fields slower than normal, or something, so there's plenty of combing artifacts. 480p is just better, though I only wish I had a bigger PC CRT monitor right now XD.
Updated by buvk about 2 years ago
Great job with these shaders. I am using the 0_IntegerScalingOPTIONS.glsl shader with Allow Downscale and Scale Width to fit 4:3. Mega Man 9 finally looks right :)
Updated by tccalvin over 1 year ago
taolas wrote in #note-23:
Oh man, I did some crazy stuff I didn't think I could do with shaders!
Hope you're still around to test. This shader has quite a few options, so be sure to hit the Configure button next to the shader choice. Also, as it says, please put aspect ratio to stretch or it gets a bit wonky.
Hey taolas! Don't know if you're still around. I'm still using your shader and I still love it. I was wondering if it would be possible to add scanlines as an option for the "integer scaling options" shader. It would look really nice when upscaling to higher resolutions on flat panels. Makes the image look less pixelated.