db48x / emularity

easily embed emulators
GNU General Public License v3.0
619 stars 108 forks source link

Add Software-Based Black Frame Insertion to reduce Motion Blur on 120Hz Monitors #73

Open mdrejhon opened 3 years ago

mdrejhon commented 3 years ago

Software-based black frame insertion can reduce the display motion blur of Emularity emulation. When a display is detected to be equal to exactly twice or triple or quadruple the emulator refresh, it should offer a hotkey for software based black frame insertion.

View BFI demo at 120Hz: testufo.com/blackframes

View BFI demo at 180Hz: testufo.com/blackframes#count=3

View BFI demo at 240Hz: testufo.com/blackframes#count=4

Related RetroArch item: https://github.com/libretro/RetroArch/issues/10754

This feature should be optional (hotkey activated).

db48x commented 3 years ago

This is the kind of feature that would need to be added to each emulator supported by Emularity individually. If you haven't already done so, I suggest speaking with the folks running MAME, DosBox, Scripted Amiga Emulator, etc. Best of luck!

mdrejhon commented 3 years ago

This is the kind of feature that would need to be added to each emulator supported by Emularity individually. If you haven't already done so, I suggest speaking with the folks running MAME, DosBox, Scripted Amiga Emulator, etc. Best of luck!

Architecturally, this isn't necessary.

RetroArch actually implemented the majority of it already; they manages to pull this off without requiring emulators to support BFI.

I am able to use BFI with MAME, DosBox, etc, through the RetroArch interface, they recently extended support to 180Hz and 240Hz BFI as well.

MAME and DosBox doesn't need BFI support -- just the emulator wrapper responsibility to emulate a CRT temporally (BFI) much like emulating a CRT spatially (like a MAME HLSL). That can often be outsourced to the resonsibility of the emulator wrapper to also temporally emulate a CRT, not just spatially, rather than the emulator itself;

Thusly BFI responsibility is at the emulator wrapper level, not the individual emulator level. Being the founder of Blur Busters / TestUFO and the inventor of a lagless VSYNC method now used in certain emulators (beamraced sync between emu raster and real raster) -- I would be happy to educate people on temporal concepts. (This is the first time a meta-emulator wrapper closed a BFI-suggestion submission, so I'm curious)

I was able to add software BFI to a 60fps YouTube Video by oscillating the alpha value between 1 and 0 on a 120hz display in a jsfiddle test; so one can do it externally without involvement of the original site too. But it's more reliable if it's done natively within the emulator wrapper;

The workflow is:

  1. Detect refresh rate (via rAF() counting)
  2. If multiple of emulator rate; provide optional synchronized BFI option

For usability, it can be disabled by default, unless specifically enabled by both the developer (compile time) and by the user (hotkey).

With 120Hz+ rapidly becoming mainstream towards the end of the decade becaues of ergonomic purposes (doubling Hz on a non-strobed/non-BFI display halves display motion blur and halves stroboscopic effect spacing), as it eventually becomes a freebie feature ever since we stopped flickering (like a CRT). This produces expanded future opportunities to use it as a temporal means of CRT simulation over the longer term.

Over the long term, as higher Hz makes it easier to also temporally emulate a CRT, not just spatirally (CRT filters), architecturally, it is often typically recommended further downstream than the emulator module, e.g. the final layer right before displaying on the screen. Sometime after the spatial filtering step. So this gives it huge flexibility to be in the emulator wrapper; which is actually architecturally the more ideal place because of framerate-to-refreshrate synchronization requirements. I also have an issue open at MAME team too, https://github.com/mamedev/mame/issues/6762 ... but this is way more complicated/advanced than simple software BFI. More ideally, it's actually implemented at the emulator wrapper level, rather than the individual emulator modules themselves.

P.S. Although I don't have time at the moment; If I (or someone else) makes a commit myself to the source code in the next few months, will you reopen this issue?

db48x commented 3 years ago

It's much easier for RetroArch to modify or enhance the capabilities of the wrapped emulators than it is for Emularity. Emularity launches the emulator and then has essentially no further communication with it. Just getting MAME to mute correctly was incredibly annoying. Also I'm sceptical that this technique actually improves the image quality. On the other hand, I don't have a high refresh rate monitor, so it's hard for me to say.

I'd be happy to accept a patch, of course.

mdrejhon commented 3 years ago

It's much easier for RetroArch to modify or enhance the capabilities of the wrapped emulators than it is for Emularity. Emularity launches the emulator and then has essentially no further communication with it. Just getting MAME to mute correctly was incredibly annoying.

Ah, that makes sense. A very thin layer between the emulator modules and the screen, does make it quite difficult to add enhancements to the workflow. However, in the long term (5 years), there's benefits to adding a filter/processing layer to Emularity:

I am the inventor of a JavaScript based "VRR emulation" algorithm that can stutterlessly convert 50fps to 60fps: www.testufo.com/vrr and also fixed-Hz emulator [50fps stuttery versus 50fps HTML5-based "standards conversion"] .... This could allow stutter-free emulator operation, like 50fps PAL emulators on 60Hz and 75Hz browser visitors.

Imagine stutter-free 50fps PAL emulators on 60Hz NTSC visitors; a much improved emulator experience!

But to do this, requires architecturing a processing layer between emulator framebuffers (the buffers that emulators provide) and the actual display. Fortunately, you only need the emulator framebuffers (up to 2-3 trailing buffer history), in a Canvas2D compatible image format, being pipelined to the processor that can do the appropriate operations. Currently, JavaScript is fast enough to do this in realtime even on a 5-year-old computer, if you use the right algorithms (some of it actually can be pulled off using some really fun tricks that bypasses the need to do it pixel-by-pixel at a time)

Anyway, I am an expert in these temporal matters; and would be happy to answer questions about temporal architecturing considerations;

Also I'm sceptical that this technique actually improves the image quality. On the other hand, I don't have a high refresh rate monitor, so it's hard for me to say.

I can answer this for you:

So it is a case-by-case basis. For example, on the new IPS 240Hz monitors, software BFI is a major improvement to the expereince of a fast-scrolling platformer such as Sonic Hedgehog that motionblurs very badly on LCDs (LCD motionblur only because of sample-and-hold, not because of pixel response -- due to persistence of vision -- www.testufo.com/persistence and www.blurbusters.com/gtg-vs-mprt can explain these effects better)

mdrejhon commented 3 years ago

It's much easier for RetroArch to modify or enhance the capabilities of the wrapped emulators than it is for Emularity.

Pre-Requsite Forked to Issue #74

Maybe this needs to be a separate issue tracker, "add a filter processing layer to Emularity" -- not BFI specific, but to architecturally make this possible, with no need for modifying emulator modules.

Nontheless, the potential of adding a filter-processing layer to Emularity has lots of pros:

I have moved this to a new gitbub issue, because that is fundamentally a pre-requisite before thinking of the BFI layer.