BFI/Strobing/Motionblur thread reorganized

No worries about the accounts. Just keep going with whichever one you want to use :slight_smile:

That’s some exciting news about monitor developments. We’ll have to overhaul our BFI to include different patterns and partial frames. Btw, when you say '0%-25%-100%-25%, are the 25%s brightness for the full image or full-black covering 25% of the image to simulate rolling scan?

2 Likes

Global at first, for simplicity.

I have two github Feature Requests.

BFI Version 2 (Easy, Global)

Improvements to BFI to support higher-Hz monitors.

BFI Version 3 (Harder Rolling, but more Holy Grail)

Emulation of CRT electron beam

2 Likes

Hey got a question for you Chief Blurbuster!

I noticed this Mac/Linux-only emulator called Clock Signal.

It does DSP emulation of CRT output, at least to my understanding.

In theory could this be what you are looking for as far as the CRT Rolling Scan stuff? The details are a bit over my head.

I think that @TomHarte’s CLK engijne might theoretically be a codebase that can become an eventual BFIv3, especially if Windows support is also added.

It already has what seems to be a partial implementation of the rolling scan stuff (at least frame overlapped with previous frame, but without rolling-black in between yet).

It already supports beam racing in an internal prototype that Tom did, and likely (with some more debugging), add some temporal-behavior elements (like rolling black frame insertion).

With more modifications, and modularizing it to RetroArch, it probably is something doable with CLK. It would be within the bounds of the bounty if CLK was modified to make the CRT emulator modular enough to also become the CRT emulator for any other emulators (MAME, RetroArch, etc). In that sense, it could also become the beam-raced sync module for RetroArch.

I may be able to also, additionally, loan a 240 Hz gaming monitor (that becomes awarded/keeper upon successful completion) to any developer that wants to do some rolling-scan improvements to an existing CRT-tube emulator such as CLK or MAME HLSL. Blur Busters has LOTS of leftover samples as a display testing laboratory…). While it won’t be as good on a 300nit 240Hz monitor as on a 2000nit future locally-dimmed 360Hz+ display (since you need sheer brightness to compensate for the dimness of BFI – much like how bright a CRT electron gun phosphor dot is) – a 240Hz monitor is the beginnings of the minimum refresh rate for viable software-nased rolling scan emulation (quarter-persistence, four overlapped alpha-blended frameslices).

CLK uses the MIT license, so is likely opensource-compatible with LibRetro as a codebase that could be used for either https://github.com/mamedev/mame/issues/6762 or for LibRetro BFIv3 (#10757), though there might be some code duplicatioin issues.

Also, AFAIK, Tom hasn’t committed the beamraced code and CLK is not yet Windows compatible – but theoretically could easily become Windows compatible without too many modifications (at least when piggybacking off an opensource 2D-OpenGL/Direct3D friendly engine such as MonoGame which can create 2D framebuffer graphics with text/bitmaps in just 100 lines of programming…and was the engine that I used for Tearline Jedi experiments)

2 Likes

Thanks for the reply. It would be cool if that CLK mode could be the beginnings of a Retroarch CRT emulator but it will require someone to jump onboard for development.

I don’t think it will help me personally that much if it requires 240hz though. I have the LG 27gl83a-b 144hz monitor, which I’m extremely happy with except for it’s complete lack of a Lightboost-esque mode. And the problem is software BFI in Retroarch produces terrible IR. Do you think the best hope for monitors like this is having 50% brightness frames? I’m guessing that would have a corresponding effect of higher motion blur than if the monitor was capable of regular BFI?

1 Like

My view is a CRT emulator is a 5-year incubation goal.

What should happen first is BFI Version 2 (burnin-proof version)

If RetroArch implements BFIv2 with the anti-burnin feature, that would be a solved problem.

The optional 50% brightness frame only needs to occur once every 20 seconds or 30 seconds, merely simply only as a flicker-prevention measure during the phase-swap moment. You don’t even need to do this, if you can tolerate a brief flicker once every 20 seconds, but adding a gamma-corrected 50% brightness frame balances this out (e.g. two consecutive 50% brightness frames replacing one 100% brightness frame, only once every 20 seconds or 30 seconds). This interval could be configurable, such as once every 5 minutes or once every 15 minutes, depending on how fast static electricity in the pixels builds up to create image retention. Otherwise, the BFI is unchanged – it looks the same as before, the anti-burn-in frame only lasts for 1/120sec (at 120Hz) once every 20 or 30 seconds. The problem is that without the 50% brightness technique for 2/120sec, there’s a minor flicker once every 20 or 30 seconds during this anti-burnin manoevere.

RetroArch could theoretically run microscopically slower or faster (e.g. 1 refresh cycle every 20 or 30 seconds) to keep things running normally internally. This would be a special divisor/multiplier factor applied to the current monitor refresh rate.

Now, even this is optional if you buy a monitor capable of 180Hz+

Alternatively, combining variable refresh rate + software BFI can be used to introduce phase swaps with less disruptions.

Also, for fixed Hz, if you use an odd divisor (180Hz or 300Hz), there is no burn in, since the BFI is no longer in sync with the LCD voltage inversion, so no static electricity builds up in the pixels to create the temporary image retention effect.

Now if you stay at 144Hz, you don’t have enough refresh rate for the 180Hz technique, so you need the anti-burnin logic described at: http://forum.arcadecontrols.com/index.php/topic,162926.msg1715845.html?PHPSESSID=6c20t410rjdbcu2jh4a5lhisdj#msg1715845

3 Likes

Maybe this could be implemented on the emulation/software side just as they have done with the inclusion of software BFI?

Couldn’t a shader do something like this? We already have rolling scanlines. Maybe we just need two parallel rolling black windows to obscure the display window which would be in between?

That should create the effect of the viewport being a rolling window, shouldn’t it?

What do you think @MajorPainTheCactus, @HyperspaceMadness, @guest.r, @hunterk, @Hyllian?

The issue we have is that the shader system runs on game frames rather than monitor frames. This is a pretty fundamental issue that would need to be resolved before we can do high-refresh effects.

The software BFI setting from the ‘video’ menu is certainly usable, but using a display’s built-in backlight strobing when available is typically better, since any stutter in the framerate causes very noticeable flickering with software BFI.

2 Likes

Doesn’t it just have to obscure part of the viewport in a strobing motion? Why can’t it simply use a similar algorithm to rolling scanlines and the user can just adust the width and speed of the strobing until they dial it in correctly? Would it go out of sync with the display? Perhaps the strobe can be synced with the frame interval or something like that. So maybe one or two oscillations per frame or something like that?

I would love to have a display with a rolling refresh, and I wish all OLEDs had it as an option and not just the ridiculously expensive ones. But to simulate it on a regular sample and hold display I’m pretty sure you would need a very high refresh rate. Otherwise if you’re only using 120Hz for example wouldn’t that just mean you could only get like the top half and then the bottom half of the screen flashing back and forth?

Either way it would be really interesting to see someone here do a mockup with video editing to simulate different variations of it to see what it would look like.

1 Like

That’s an interesting idea. I don’t personally notice the sample-and-hold blur, so I can’t really tell for myself, but you can try the interlacing shader in the ‘misc’ folder on a 480i/p source (the SNES 240p test suite can do 480i) to try a sort of “distributed” BFI effect, and I added scanline roll to the res-independent scanlines here you can try:

#version 450

/*
    Resolution-Independent Scanlines
    based on
    Scanlines Sine Absolute Value
    An ultra light scanline shader
    by RiskyJumps
	license: public domain
*/

layout(push_constant) uniform Push
{
	vec4 SourceSize;
	vec4 OriginalSize;
	vec4 OutputSize;
	uint FrameCount;
	float amp;
	float phase;
	float lines_black;
	float lines_white;
	float mask, mask_weight, imageSize, rollspeed;
} params;

#pragma parameter amp          "Amplitude"      1.2500  0.000 2.000 0.05
#pragma parameter phase        "Phase"          0.5000  0.000 2.000 0.05
#pragma parameter lines_black  "Lines Blacks"   0.0000  0.000 1.000 0.05
#pragma parameter lines_white  "Lines Whites"   1.0000  0.000 2.000 0.05
#pragma parameter rollspeed    "Rolling Speed"  1.0000  0.010 2.000 0.01

#pragma parameter mask "Mask Layout" 0.0 0.0 19.0 1.0
#pragma parameter mask_weight "Mask Weight" 0.5 0.0 1.0 0.01
#pragma parameter imageSize "Simulated Image Height" 224.0 144.0 260.0 1.0

#define freq             0.500000
#define offset           0.000000
#define pi               3.141592654

layout(std140, set = 0, binding = 0) uniform UBO
{
	mat4 MVP;
} global;

#define pi 3.141592654
#include "../../include/subpixel_masks.h"

#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
layout(location = 1) out float omega;

void main()
{
   gl_Position = global.MVP * Position;
   vTexCoord = TexCoord;
   
   omega = 2.0 * pi * freq;              // Angular frequency
}

#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 1) in float omega;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;

void main()
{
    float angle = (gl_FragCoord.y * params.OutputSize.w) * omega * params.imageSize + (params.phase*float(mod(params.FrameCount,60)*params.rollspeed));
    vec3 color = texture(Source, vTexCoord).xyz;
    float grid;
 
    float lines;
 
    lines = sin(angle);
    lines *= params.amp;
    lines += offset;
    lines = abs(lines);
    lines *= params.lines_white - params.lines_black;
    lines += params.lines_black;
    color *= lines;
 
    FragColor = vec4(color.xyz, 1.0);
   FragColor.rgb *= mask_weights(gl_FragCoord.xy, params.mask_weight, int(params.mask));
}
4 Likes

I only have 60Hz screens (besides an old CRT Monitor that I don’t use) so I guess I won’t be able to do this at anything more than 30Hz per field but yes, distributed BFI is kinda what I’m getting at instead of full frame. Any improvement in motion clarity should be welcomed so it doesn’t need to be all that aggressive all the time.

Maybe the strobe can probably be a really fast sweep and it can even be field sequential, dividing the screen into an equal number of alternating on and off windows.

This might introduce new type of interlacing artifacts though.

You know what might also look good? A chekerboard BFI pattern. With every other block alternating between on/off. Perhaps the perceived brightness might be higher with that than with full frame BFI at the same frequency?

Forgive me for thinking aloud.

I’m assuming that I just have to copy and paste the above code into a new *.slang file and load it up?

I’m only used to loading *.slangp and *.cgp files.

1 Like

Yes. You have to load it manually by ticking the number of passes from 0 to 1 and then where it says “shader 1 N/A”, navigate to the shader, select it and hit ‘apply’.

1 Like

Help needed,

When I try to load the code you just posted, I get [ERROR] [slang]: Failed to open shader file: “…\RetroArch\shaders\include\subpixel_masks.h”.

I tried the interlacing shader and the scrolling looks pretty smooth with it. It’s hard to tell what to look for though. If I had masks and triads which would normally disappear during horizontal scrolling, that might have helped.

One thing I like about the interlacing shader is that I’m not noticing any flicker from the distance I’m viewing the screen from. Near the end of the CRT era, I couldn’t stand looking at a CRT computer monitor at 60Hz after getting used to 85Hz.

oh, whoops. Put it in the scanlines/shaders directory. It has the subpixel masks in it, so it needs to be able to reach that path where it expects it.

1 Like

Right, so I got this to work. I had to also put the include folder in my Downloads folder.

The easiest mask layout for me to see at my normal viewing distance was Mask Layout 8.

The only phase setting that didn’t bob up and down was 0.00. 0.05 didn’t really bob much either but I could see some moire like artifacts on the sky in the 240p test suite scrolling test. 0.00 eliminated that.

No matter what Rolling Speed I set, the Mask blurred into white once scrolling started.

Is it possible to disable interlacing and have a rolling Window instead of just rolling scanlines, which is what it looks like when the Phase is set to 0.05?

1 Like

The mask shouldn’t really be affected, since it’s not actually moving. AFAIK, the mask/scanlines disappearing during scrolling is purely an optical illusion.

You would need to test something like fast side-scrolling.

I’m not sure I understand what you mean by a rolling window.

At least on my monitor, 0.05 is way too slow to actually do what we want here, which is cleaning out the existing pixel to make room for the next one. If it’s just crawling along, there’s no real benefit.

1 Like

Yes, I know that this is what was happening.

Oh, I just wanted to see if it was possible to recreate a rolling-scan BFI by using shaders to obscure part of the screen that we wanted to be black.

So basically create the same effect seen in the Sony and Dell OLED monitors that can do that via hardware.

I didn’t try such a low speed because I wanted to, it was just the only speed that didn’t bob or produce moire artifacts.

Thanks for trying to help!

2 Likes

This really needs to be done at the display level and not the shader level. The reason being is that you need high refresh rates as many of you have said but you don’t want to try sending all that data down the hdmi/DP cable.

It just needs a very simple algorithm in the monitor to repro it but it needs quite an expensive CPU to reach the speeds needed to create the back light strobe.

Basically this has been done partially on a few monitors by the BlurBusters namely @mdrejhon above. He’s certainly created a tool for a few monitors to tweak back light strobing.

What I think we might want to try is simulating what multiple scanning beam heads would look like (using a displays backlight strobing) and reduce high refresh rate required that way i.e two virtual scanning beam heads would halve the refresh rate required, four would drop it by a quarter and so on.

Not sure if that all works as I have imagined it though…

3 Likes

bumping this since there’s been a lot of BFI-related stuff lately.

Is there any way to make BFI retention-proof at 160Hz?

1 Like