mupen64plus-libretro-nx
mupen64plus-libretro-nx copied to clipboard
Native resolution option
First off, awesome work! This is a big improvement over the previous Mupen64Plus core. If it matters, I'm using the build from https://m4xw.net/nextcloud/index.php/s/ASMiAmQBPnP8D3w
Gauntlet Legends boots up and plays mostly ok. However, the text is very blurry (even unreadable in some cases). I compared it to Angrylion which looks perfect (alas, it's too slow on my machine). Comparison below, same shader for both. Yes they're taken with my phone :) was faster than getting a proper screenshot.
Mupen64Plus Next (all default settings):
Parallel N64 (with Angrylion):
I eventually determined this is because the resolution is set to 320x240. However, setting the resolution to the next level up, 640x480, isn't quite right either. It appears this game runs at 640x240 (at least, that what is with Angylion, and that looks right to me). The vertical resolution does matter since it greatly affects the look of scanlines from the shader. Also according to https://nintendo.fandom.com/wiki/Nintendo_64_Expansion_Pak, it would appear there are a wide variety of resolutions between 320x240 and 640x480 that are used. Ideally there should be a "native resolution" option in addition to the fixed resolution options. However, if it's easier to implement, a reasonable partial solution would be a "320x240 with high-res" (maybe you could come up with a better name) option. That would be 320x240 for most games, but would switch to 640x480 for games that use any higher resolution.
Can you check the GLideN64 branch?
There is also config.frameBufferEmulation.nativeResFactor, I don't expose that tho.
@m4xw Do you mean check https://github.com/libretro/mupen64plus-libretro-nx/tree/GLideN64? Isn't that what https://m4xw.net/nextcloud/index.php/s/ASMiAmQBPnP8D3w is built from?
I briefly searched the code for "nativeResFactor". Base off this snippet, it sounds like setting nativeResFactor to 1 might give me what I want, but I haven't tested that.
Also, some related discussions here:
https://github.com/libretro/parallel-n64/issues/403 https://forums.libretro.com/t/automatically-select-native-resolution-for-n64-games/2073
Just for some additional justification besides the "purist" perspective, another reason such an option would be preferable over simply always using 640x480 is that some games have graphical artifacts when rendered at 640x480 (e.g. Bomberman Hero).
Do you mean check https://github.com/libretro/mupen64plus-libretro-nx/tree/GLideN64? Isn't that what https://m4xw.net/nextcloud/index.php/s/ASMiAmQBPnP8D3w is built from?
Yes
That's the build I'm using.
You can try just hard-coding GLideN64\src\Config.cpp line 64 to 1.
Made that change. Managed to build successfully (attached). Will test out tonight.
Edit: and a build with nativeResFactor hard-coded to 2
@m4xw I believe I've determined what the nativeResFactor setting does. When it's set, Mupen64Plus renders to an internal framebuffer that is the set multiple of the game's native resolution. Bomberman Hero is a good way to verify this, since it has visual artifacts at 2x native resolution that do not show up at 1x native resolution.
Regardless of nativeResFactor, the final output resolution resolution is always the resolution in the settings. So somewhere along the way it gets scaled (looks like biliear) to that resolution before being handed off to Retroarch. If you were just going to use simple bilinear filtering to bring it up to your display resolution this intermediate scaling wouldn't really matter, but with the way Retroarch's shaders work it's best if the input is at native resolution.
I've found a reasonable compromise to be have nativeResFactor at 1, resolution at 640x480, and a 2-stage shader. The first stage scales the image down to 640x240, the second stage is the shader I actually want to apply. This looks pretty decent for most games, although isn't ideal for games that had > 240 vertical resolution. This could be done more simply by 1) exposing the nativeResFactor option (not sure you need to expose an integer, a true/false "Render at native resolution" option seems sufficient) and 2) adding a 640x240 resolution option. Even better though, would be to find the code that scales from the internal framebuffer to the resolution in the settings and disable that when nativeResFactor is set.
Looking through the code a bit, I think libretro is what's responsible for scaling from the framebuffer resolution to the resolution in the settings, and I think that's controlled here. Instead, in native resolution mode you would want to set it based on VI.width/VI.height. There's also a whole lot going on in this codebase and I've only just started looking at it, so I could be off base here.
Thanks I will investigate it.
Based on the threads here and here, assuming what they say is accurate, then regardless of whatever resolution the internal framebuffer is (which is often 320x240, but can be a variety of resolutions, and can even change midgame) the N64 always scales the output to either 640x240p or 640x480i. Angylion follows this approach - every screenshot I took with it was either 640x240 or 640x480, and the 640x480 screenshots were clearly interlaced (I guess angrylion being a low-level plugin actually implements interlaced rendering).
An "output directly at framebuffer resolution" option would be interesting, although not strictly faithful to the N64, and harder to implement. I think the approach I hacked together to simulate 640x240 is probably pretty close to the right approach. I suppose the question is mostly how to present these options to the user. I have a few proposals:
- A true/false "Render at native resolution" option
- Replace the "4:3 Resolution" and "16:9 Resolution" options with independent "Horizontal Resolution" and "Vertical Resolution" options. Default to 640 horizontal and 240 vertical. The aspect ratio is still controlled by the "Aspect Ratio" option.
- Not as important, but as a "nice to have", maybe an option to double the vertical resolution if the game is in interlaced mode. This only really matters if you have a low vertical resolution, so maybe one of the options under "Vertical Resolution" could special case this. Something like "240p/480i" which sets vertical resolution to 240 if the N64 requests progressive output and 480 if it requests interlaced output.
Implementing the third of those is a bit beyond me at this point, but I could implement the first two if you're interested. Might be a couple weeks before I have enough free time to get around to it, though.
libretro supports rendering to a max_width and max_height. there is a "base_width, base_height" which is a floor() option.
libretro can render to any resolution in between. Its just a matter of rendering to the render target at that resolution which is in the video_refresh callback.
Just to add on to this. M64p automatically selects the native resolution for every game and scales it from there. Using an expansion pack will also change the internal emulated resolution to what is should apporiatly be. It would be great for a feature where we don’t have to select a games resolution and it just had an “auto” setting where it picks the correct one based on the game and expansion pack settings.
@m4xw Quick question: I saw that you're claiming the bounty, but the "mupen_next" branch is still old. Is the buildbot now pointing to the "GLideN64" branch? And if so, should that be updated to the default?
I ask because I may take a look at this later, and want to make sure I'm working off the right branch.
@Bezier89 use the GLideN64 branch, it will be merged after I figured how I want to progress with multi-plugin-support. fwiw I changed the default branch or the time being
I recently talked about the poor image quality in some N64 games.
https://forums.libretro.com/t/n64-poor-image-quality/22857
Very good to know that will be implemented a native resolution option in Mupen64Plus Next core.
Thanks all to the work and dedication!
S2
Thanks for the work. This explains why many games look blurry. Even with upscale filters
@Papermanzero you want to close the other issue then?
In general there are Independent issues: This one is native resolution, the other is texture filtering/scaling. Both lead to a blurry image. I compared the image quality with beetle psx and I was surprised that the mupen core display many things like fonts so blurry and unsharp compared to psx games. I think the native resolution is the main issue which leads to this behavior.
therefore i will close the other issue, because @gonetz has to implement the sprite/texture filtering or scaling feature in gliden64.
@bezier89 - Can you share what shader you used for scaling as I'd like to do something similar to you?
@cobhc2019 I use crt-lottes-fast with the following settings:
Mask Type 3.00
Mask Intensity 0.60
Scanline Intensity 0.40
Sharpness 2.50
Curvature 0.00
Triniton-style Curvature 0.00
Corner Round 0.00
CRT Gamma 2.40
Also, if anyone is interested on working on this issue, feel free to take it. Just had a kid so we've been a bit busy :)
@bezier89 Is that for the scaling as well? I was more interested in what you were doing to scale 640x480 down to 640x240.
@cobhc2019 Ah, that. I just apply a stock linear filter first to scale it down. See attached file for examples (glsl and slang). It downscales both axis, but change scale_x0
to 1.0 if you want to only downscale the vertical (y) axis.
Pay close attention to the edge... gonetz/GLideN64#1981
Any update on that one?
@Papermanzero I might look at that before christmas
@Bezier89 wanna give this a try? Keep in mind it uses different filtering so its gonna be a bit more blurry anyway. Make sure you set 640x480 4:3 for testing, this also forces nativeResFactor. mupen64plus_next_libretro.zip
hah, parallel's AL def renders at higher resolutions than it should for real native res...
@m4xw Nice work. Has the filtering logic changed in this core recently? Even at 320x240, Gauntlet Legends is much more readable than it used to be.
Old build (from when issue was created):
320x240
640x480
Latest official build (as of 11/30/2019):
320x240
640x480
Build from your comment:
640x480 (although 320x240 looks identical as far as I can tell):
Even with the improved filtering, this seems like a worthwhile feature. The screenshot from your build appears to have slightly less blurry text compared to 320x240 from the latest official build. Also I can confirm that games that have artifacts at 640x480, such as Bomberman Hero, do not exhibit said artifacts.
@Bezier89 can u give me some close up shots like the first post?
That build still doesnt have the nearest neighbours scaling i want
Heres another example (left is my build, right is current)
There also has been a regression upstream, there is no longer true support for rendering lower than real hw would have, so I have to force nativeResFactor = 1 for lowest configuration (still need to create a issue on Gliden with my findings.. have been procrastinating on that)
The build I gave you sets the Resolution u set as max but it will always display the resolution the N64 would render and pretty much every funky number inbetween for each VI.
I will write some more details tomorrow or monday, got to go now.
(Also yes theres a new hybrid filter for some textures on upstream GLN64)