melonDS icon indicating copy to clipboard operation
melonDS copied to clipboard

[Feature Request] Downsampling (filtering the higher resolutions to prevent aliasing)

Open Zerowalker opened this issue 5 years ago • 9 comments

As you can have higher resolutions with opengl, but the aliasing is still quite obvious i am thinking it has to do with how it's displayed. I know on Ishiiruka (Dolphin) you could use a shader to simply filter it when downsampling to the window resolution, instead of the basic nearest neighbour, and that helps a ton.

I might be mistaken though but i think it should help a lot and probably be fairly "simple" i hope.

Love the emulator, great job!

Zerowalker avatar Dec 12 '20 09:12 Zerowalker

you can already do that, enable screen filtering while running the GL renderer at a higher resolution, it will downscale with a bilinear filter

Arisotura avatar Dec 17 '20 00:12 Arisotura

Oh, thought it tried it and it seemed like it just made everything soft, like when you use it for upscale. But i might have just used it wrong, gotta recheck that!

Zerowalker avatar Dec 19 '20 03:12 Zerowalker

It would be good to have an option to filter only the 3D when scaling it, because 2D elements look pretty bad with bilinear filtering.

nadiaholmquist avatar Dec 19 '20 18:12 nadiaholmquist

hmm, it's kinda odd that it looks bad, cause if it was scaled up as well, then downscaling with bilinear shouldn't do that much i think. Unless the billinear filtering is down afterwards, or perhaps before or something. Cause i think if you upscale with billienear and then downscale with billinear (to a higher resolution than it's original) it shouldn't look that much different from what it would look if it was just upscaled once to that resolution.

I might be wrong though, but it feels like something's off.

Zerowalker avatar Dec 19 '20 23:12 Zerowalker

Ah yeah that's kinda another feature request of mine - supporting doing an integer scale to the nearest scale and then bilinear the rest of the way to avoid the shimmering caused by non-integer scales, this would probably also give us what we want for the 3D scaling.

nadiaholmquist avatar Dec 19 '20 23:12 nadiaholmquist

I'm rather late to this thread, but the issue with upscaling with bilinear and then downscaling with bilinear is that, if your viewport is something like 2x native but you're rendering at something like 4x native, then your 2D elements are still going to have 2x scale of bilinear filtering applied...unless I'm misunderstanding the chain of scaling or something.

Also, depending on what sort of bilinear downscaling is used, sometimes you can end up creating new aliasing artifacts when scaling to sizes smaller than 0.5x more typically referred to as "texture shimmering" or the like - it's my impression this issue happens more often with faster and/or hardware-based scaling and is one reason mipmapping often needs to be a thing (or at least needed to be a thing in the 2000s and modern PC games probably do fancier and/or different stuff now). But since bilinear is rather cheap on most anything made in the last 15 years, even a more software implementation whether CPU or GPU probably would work to avoid such issues.

NintendoManiac64 avatar Dec 02 '25 13:12 NintendoManiac64

I'm rather late to this thread, but the issue with upscaling with bilinear and then downscaling with bilinear is that, if your viewport is something like 2x native but you're rendering at something like 4x native, then your 2D elements are still going to have 2x scale of bilinear filtering applied...unless I'm misunderstanding the chain of scaling or something.

And that's why we need proper upscaling, like MMPX (preserves most details but not fully smooth) from duckstation, nestopia and ppsspp. Or OmniScale|Scale3x (both are overly smooth but mostly pleasant-looking).

There is also the issue of scaling per sprite or per screen. First one is way nicer looking when it works (especially for mix of 2D sprites and textures on 3D models) but breaks down when tile elements get misaligned (such as in Castlevania: Symphony of the Night which hates all per sprite scaling).

v-fox avatar Dec 03 '25 14:12 v-fox

And that's why we need proper upscaling, like MMPX (preserves most details but not fully smooth) from duckstation, nestopia and ppsspp.

...and of course you chose the exact emulators I have basically no experience with. XD (I know of them and have poked around with duckstation, but that's it - Dolphin is by far the major one I use with Mupen and mGBA as secondary and I guess Snex9x as third; also I heavily used Project64 in my pre-Linux years a decade+ ago).

Or OmniScale|Scale3x (both are overly smooth but mostly pleasant-looking).

Isn't Scale3x a post-process upscale over the entire image? How does that help with the aforementioned situation of rendering at 4x internal resolution but outputting at 2x? Isn't the proper solution the one pioneered by N64 emulators of yore e.g. Project64 and/or Rice's Video Plugin of handling texture scaling separately from the 3D polygon models? (heck even Dolphin doesn't support this!...yet?)

NintendoManiac64 avatar Dec 03 '25 16:12 NintendoManiac64

...and of course you chose the exact emulators I have basically no experience with. XD

Well, it's they who chose to use best scaling options. Too bad those aren't universally everywhere. For PS1, NES and PSP those are primary options.

(though nowadays I prefer using Dolphin for any and all retro things for various reasons - yes, running an emulator in an emulator)

Wow. And I thought I do weird things. The only time I did something like that is running Castlevania: SOTN remaster on ppsspp that uses internal PS1 emulator launched via natively running Rondo of Blood remake because that remaster is the definitive version.

Isn't Scale3x a post-process upscale over the entire image? How does that help with the aforementioned situation of rendering at 4x internal resolution but outputting at 2x?

Because it's not. In duckstation it's used per texture/sprite. I use it now instead of xBR or JINC because those are too smooth for low-res textures even though I generally like "impure" smoothness, so MMPX is not smooth enough for textures (but it's great for "almost pure" look in 4K) while bilinear is just sinfully ugly for everything.

For optional whole-screen post-scaling duckstation is basically limited to xBR, not counting 4 flavours of bilinear or nearest-neighbour or lanczos in a separate, mandatory post-scaling step between rendering and viewing resolutions.

I think home-grown N64 emulation core in RetroArch (libretro mupen64plus fork) now also has option for per-texture xBR scaling (at high-res rendering it's better per-texture than whole-screen) but Castlevania 64 looks too weird in 4K|HDR10+ (yes, it does, in fact, natively renders in HDR10+ using vulkan, with dynamic display metadata and everything, expanding colour-space and contrast beyond original) with it even for me.

This is "highly impure" and does not "look as intended" at all but most of the time it's great and the major visual improvement, just like with using mpv to watch SDR videos (like all anime) in HDR screen using "inverse-tone-mapping" to forcefully "stretch" white- and black-point levels from SDR to HDR (maybe colours too, from BT.709 to BT.2020) instead of only using SDR-subset of HDR-space which "proper" standards mandate.

Isn't the proper solution the one pioneered by N64 emulators of yore e.g. Project64 and/or Rice's Video Plugin of handling texture scaling separately from the 3D polygon models? (heck even Dolphin doesn't support this!...yet?)

If by "separately" you mean pre-scaling every texture and sprite with their selected algorithm, then rendering geometry natively with selected resolution using new pre-upscaled textures & sprites and then whole-screen post-scaling & post-processing (with option for more whole-screen post-scaling steps) to avoid discrepancy between rendering and viewing resolutions - then yes.

Yes, we, emulators users, love scaling so much that there is option for more tertiary scaling while secondary scaling after primary scaling.

Basically, my choice of scaling now is either:

  1. general case: 1. sprite+texture pre-rendering for high-res rendering: MMPX+Scale3x (or "AI"/ML texture pack, if available); 2. whole-screen at static internal resolution: [none]; 3. whole-screen at dynamic final (window-geometry|fs) resolution: FSR (if unavailable: lanczos);
  2. "broken tiling" case: [integer NN] -> [OmniScale|xBR] -> [FSR|lanczos];

v-fox avatar Dec 04 '25 13:12 v-fox