Sony Megatron Colour Video Monitor

No, this is really about the phosphor stripes. On a CRT, they’re still slighty visible even when not excited by the electron beam.

I’ve tried to include examples but I can add some more or better ones if you wish.

This is something that can be seen on almost any good quality CRT photo once it’s bright and zoomed in enough.

That’s understandable.

It’s just to add to the realism/accuracy of the shader. Currently the edges of the colours from the phosphors fade or transition to a black void, whereas on a CRT this isn’t actually the case. The darkest part of the screen would be the unlit phosphor stripes, which weren’t quite jet black and can be seen under the right circumstances, especially in photos.

If it’s expensive performance wise and cumbersome settings wise, I’m wondering if @GPDP1 can work his/her magic once again and implement it in a modular fashion as was done with the CRT-Guest-Advance-NTSC section, provided that it’s okay with Mr. @guest.r of course.

Here’s another beautiful example of what I’m talking about but tastefully implemented via a shader preset by @RetroGames4K.

You have to zoom in on the dark areas and your screen needs to be bright enough to see the unlit phosphor stripes.

https://www.reddit.com/r/crtgaming/s/YBXBbf7c2h

3 Likes

The easiest way to do something like that would be to just clamp the image before the mask is applied to something like clamp(img, vec3(0.05), vec3(1.0)). However, that’ll only look right on aperture grille masks, since it’s simulating ambient light shining on the phosphor mask rather than light coming from the phosphors themselves.

That is, you wouldn’t see the crossbars of the shadowmask, since that’s behind the phosphor layer, and this light would be coming from in front.

2 Likes

This is how it’s supposed to look on both aperture grille and slot mask screens.

You’re not supposed to see the crossbars while seeing the unlit phosphors.

Yeah, that’s what I meant. If you just clamp to raise the minimum before the mask is applied and are using a slot mask, it’ll show those crossbars, which isn’t what you want.

1 Like

Here’s a photo of a CRT corraborating what @Cyber is saying

Credit to @ruuupu1 from Twitter

Model is Sony Trinitron KV-AF1 14 Inch CRT

5 Likes

Preliminary decoupling of the NTSC passes from guest.r’s most recent crt-guest-advanced-ntsc update for use with Megatron:

shaders = "8"
shader0 = "shaders_slang/crt-guest-advanced-2024-02-17-release1/shaders/guest/advanced/stock.slang"
filter_linear0 = "false"
wrap_mode0 = "clamp_to_border"
mipmap_input0 = "false"
alias0 = "StockPass"
float_framebuffer0 = "false"
srgb_framebuffer0 = "false"
scale_type_x0 = "source"
scale_x0 = "1.000000"
scale_type_y0 = "source"
scale_y0 = "1.000000"
shader1 = "shaders_slang/crt-guest-advanced-2024-02-17-release1/shaders/guest/advanced/afterglow0.slang"
filter_linear1 = "true"
wrap_mode1 = "clamp_to_border"
mipmap_input1 = "false"
alias1 = "AfterglowPass"
float_framebuffer1 = "false"
srgb_framebuffer1 = "false"
scale_type_x1 = "source"
scale_x1 = "1.000000"
scale_type_y1 = "source"
scale_y1 = "1.000000"
shader2 = "shaders_slang/crt-guest-advanced-2024-02-17-release1/shaders/guest/advanced/pre-shaders-afterglow.slang"
filter_linear2 = "true"
wrap_mode2 = "clamp_to_border"
mipmap_input2 = "false"
alias2 = "PrePass0"
float_framebuffer2 = "false"
srgb_framebuffer2 = "false"
scale_type_x2 = "source"
scale_x2 = "1.000000"
scale_type_y2 = "source"
scale_y2 = "1.000000"

textures = "SamplerLUT1;SamplerLUT2;SamplerLUT3;SamplerLUT4"
SamplerLUT1 = "shaders_slang/crt-guest-advanced-2024-02-17-release1/shaders/guest/advanced/lut/trinitron-lut.png"
SamplerLUT1_linear = "true"
SamplerLUT1_wrap_mode = "clamp_to_border"
SamplerLUT1_mipmap = "false"
SamplerLUT2 = "shaders_slang/crt-guest-advanced-2024-02-17-release1/shaders/guest/advanced/lut/inv-trinitron-lut.png"
SamplerLUT2_linear = "true"
SamplerLUT2_wrap_mode = "clamp_to_border"
SamplerLUT2_mipmap = "false"
SamplerLUT3 = "shaders_slang/crt-guest-advanced-2024-02-17-release1/shaders/guest/advanced/lut/nec-lut.png"
SamplerLUT3_linear = "true"
SamplerLUT3_wrap_mode = "clamp_to_border"
SamplerLUT3_mipmap = "false"
SamplerLUT4 = "shaders_slang/crt-guest-advanced-2024-02-17-release1/shaders/guest/advanced/lut/ntsc-lut.png"
SamplerLUT4_linear = "true"
SamplerLUT4_wrap_mode = "clamp_to_border"
SamplerLUT4_mipmap = "false"

shader3 = "shaders_slang/crt-guest-advanced-2024-02-17-release1/shaders/guest/advanced/ntsc/ntsc-pass1.slang"
filter_linear3 = "false"
wrap_mode3 = "clamp_to_border"
mipmap_input3 = "false"
alias3 = "NPass1"
float_framebuffer3 = "true"
srgb_framebuffer3 = "false"
scale_type_x3 = "source"
scale_x3 = "4.000000"
scale_type_y3 = "source"
scale_y3 = "1.000000"
shader4 = "shaders_slang/crt-guest-advanced-2024-02-17-release1/shaders/guest/advanced/ntsc/ntsc-pass2.slang"
filter_linear4 = "true"
wrap_mode4 = "clamp_to_border"
mipmap_input4 = "false"
alias4 = ""
float_framebuffer4 = "true"
srgb_framebuffer4 = "false"
scale_type_x4 = "source"
scale_x4 = "0.500000"
scale_type_y4 = "source"
scale_y4 = "1.000000"
shader5 = "shaders_slang/crt-guest-advanced-2024-02-17-release1/shaders/guest/advanced/ntsc/ntsc-pass3.slang"
filter_linear5 = "true"
wrap_mode5 = "clamp_to_border"
mipmap_input5 = "false"
alias5 = ""
float_framebuffer5 = "false"
srgb_framebuffer5 = "false"
scale_type_x5 = "source"
scale_x5 = "1.000000"
scale_type_y5 = "source"
scale_y5 = "1.000000"
shader6 = "shaders_slang/crt-guest-advanced-2024-02-17-release1/shaders/guest/advanced/custom-fast-sharpen.slang"
filter_linear6 = "true"
wrap_mode6 = "clamp_to_border"
mipmap_input6 = "false"
// alias6 = "NtscPass"
alias6 = "LinearizePass"
// alias6 named incorrectly for compatibilty with unaltered crt-guest-advanced-ntsc-pass1.slang
float_framebuffer6 = "false"
srgb_framebuffer6 = "false"
scale_type_x6 = "source"
scale_x6 = "1.000000"
scale_type_y6 = "source"
scale_y6 = "1.000000"
shader7 = "shaders_slang/crt-guest-advanced-2024-02-17-release1/shaders/guest/advanced/crt-guest-advanced-ntsc-pass1.slang"
filter_linear7 = "true"
wrap_mode7 = "clamp_to_border"
mipmap_input7 = "false"
alias7 = "Pass1"
float_framebuffer7 = "false"
srgb_framebuffer7 = "false"
scale_type_x7 = "viewport"
scale_x7 = "1.000000"
scale_type_y7 = "source"
scale_y7 = "1.000000"

PR = "0.000000"
PG = "0.000000"
PB = "0.000000"
AS = "0.000000"
sat = "0.000000"
CP = "-1.000000"

(presumes the “crt-guest-advanced-2024-02-17-release1” folder is extracted to shaders_slang)

I’m aiming to ultimately make this decoupling a little more futureproof than our previous attempt, so there are a number of settings that aren’t necessarily of any use to us, and alias6 is intentionally misnamed to allow use of the unmodified version of crt-guest-advanced-ntsc-pass1.slang.

I left in afterglow0.slang and pre-shaders-afterglow.slang because i wanted to be able to use the Sega Brightness Fix/Sega Luma Fix effect. As far as i can see, they are completely inert with the included settings.

4 Likes

Thanks very much @Azurfel! Is there any chance we could also get the new Sega Genesis and Master System palettes from the new Grade as well? I’m not sure if they’re integrated into the new CRT-Guest-Advanced-NTSC shader yet.

Over at the Mega Bezel thread we compared Grade’s and Guest’s implementation of the Sega Luma Fix/Genesis Brightness Fix and we choose one over the other because one seemed slightly more neutral.

Mega Bezel Reflection Shader! - Feedback and Updates

1 Like

Ok so yes I see what you’re talking about but its not accurate to simply raise the mask colour from black. The mask is black specifically what youre pointing out is that the horizontal parts (cross bar pixels) of the mask on a slot mask is non black as the phosphor runs over the top of it and we see the non lit phosphor instead of the underlying mask. We can certain do that but its a bit fiddly and I’m not 100% sure it contributes that much when the screen is turned on - certainly camera’s can deceive so that photo maybe a bit deceptive in its prominence but also I dont have a slot mask CRT to make an informative decision.

Regardless what is way more important in the photo you show is that the blacks of the phosphors aren’t black and have a non-zero base to them. I’ve actually had versions of this shader that had a non-zero black and I got a lot of complaints - you can change this by changing the gamma cutoff point in the shader arguments this should give you 90% of what youre seeing in the photo admittedly without the non zero ‘horizontal pixels’ of the slot mask but aperture grille will look perfect.

When looking at my PVM’s, the base black (because the black mask is interleaved with the slightly reflecting phosphors) is not of the level of the base black on my OLEDs so it is more accurate to have a non zero black.

There is definitely more to this off phosphor colour though when the CRT’s are turned on, as on my PVM it does look like the phosphor strips are transmitting light up them from the lit pixels kind of a little like optic fibre. I do see faint light that fades off as it gets away from the lit pixels but it only seemingly effects one of the phosphor strips - possibly green? I need to investigate a bit further.

Does anybody know what happens on a shadow mask? presumably the dots are not strips of phosphor?

1 Like

Ah fantastic - yes the shader parameters become a bit of a mess when we apply the NTSC passes currently. Thanks for this greatly appreciated!

1 Like

I’d actually say that photo shows there’s a mid way house as the crossbars are slightly visible underneath the phosphor strips. Again the most important feature isn’t the crossbars its instead that the phosphors have a non zero ‘black’. This can be achieved in the shader already by putting up the gamma cutoff to the standards as described at the top of the shader parameter blurb on the megatron.

1 Like

Yeah, off-black is technically caused by the CRT screen not being tinted black and CRT blacks not being perfect like OLED.

1 Like

Just added a pull request that contains a basic rolling scanline implementation based on the recently added shader subframe feature. All Ive done is divide the screen up vertically by the number of subframes and scroll a scissor rect down the screen over that number of sub frames.

So with two frames i.e 120hz refresh rate, the scissor rect covers half the screen and renders the top half of the screen in the first subframe and then the bottom half in the second subframe.

If I had a 360hz screen this would be much more interesting as the scissor rect would be 1/6th of the screen and scroll down over 6 sub frames.

Obviously the higher the refresh rate the more accurate to an actual crt we get.

This is a terrible brute force approach that should be done on the display itself as currently we have to send a whole frame over the cable for every subframe: an absolute waste of resources but hey its there to burn (possibly a metaphor for the world) but limits us to limited refresh rates.

6 Likes

Worth noting that this is exactly how LG’s OLED Motion Pro implementation works, with an update/scroll rate of 240hz on the models with 120hz BFI (C/GX, C/G1, and some hackable C9s), or 120hz on the models limited to 60hz BFI (C7, C8, C/G2, C/G3, and most C9s).

Probable dealbreaker downsides: LG OLEDs get substantially laggier at lower refresh rates, and the brightness hit in HDR is absolutely massive.

Which is why i personally currently use Retroarch BFI with Megatron instead. I will definitely give your rolling implementation a try at some point soon and see how it compares.

2 Likes

Thats good to know! Thanks! Yeah its interesting why display manufacturers dont take advantage of the fact the screen is off for say half the frame at 120hz with bfi and off for 3/4 of the frame at 240hz and dont whack the brightness right up for that brief moment. It must be that burn in isnt down to heat as such just how intense the light gets or theres some exponential in there somewhere between power input and light emitted that I dont understand. They all dont taken advantage of it so it seems something pretty fundamental. All we need to do is convince them to take advantage of the particular attributes of crt shaders they’d sell bazillions of tvs if they did.

1 Like

One benefit the author of bfi and the shader subframe feature pointed out is that when using this the hdr could go a lot higher in nits as only a small part of the screen is lit at any one point so depending on the tvs algorithm maybe its a brightness boost. It has to be noted there is interference at the interface between the two sub frames so use scanlines to hide them i.e the megatron shader or any other shader with black between the scanlines.

1 Like

Not sure if it’s been mentioned/implemented yet, but the last time I was messing with HDR and BFI I was desperately needing a separate UI brightness setting. Cranking brightness for BFI means the menu is eye-searing, which also has the effect of making the game look even darker by comparison because of the eyes adjusting to the bright UI.
Hopefully this is easy enough to do.

3 Likes

What’s the benefit of using software bfi over the TV’s bfi? I found the latter to be much more reliable/stable than the former when I compared a while back. I understand with software bfi you can enable vrr too, but your comment implied a brightness benefit?

1 Like

I don’t think you can enable software BFI and VRR at the same time.

1 Like

I thought you could have software bfi via retroarch and hardware vrr via the tv? Never tried it though

1 Like

I suppose it would be more accurate to say that LG’s hardware BFI is fundamentally incompatible with their HDR tonemapping in a way that results in radically reduced brightness.

Software BFI also gives you 60hz BFI with 120hz input lag.

I use the hardware BFI in SDR for video, higher framerate games, and low fps games that are incompatible with software BFI due to onerous anti-cheat.

You can (and ideally should). It’s hardware BFI that doesn’t work with VRR, at least on LG displays.

3 Likes