New CRT shader from Guest + CRT Guest Advanced updates

I indeed like to use some repeatable scenarios, sometimes with some purposes like dithering resolve etc. Also the 240p Suite for SNES and MD is a must, for various reasons.

Shader performance is best tested on some static images with a faithful resolution.

Recently i updated my Amiga WHDLoad collection, checking what’s new, so that’s what i’m mostly testing the shaders atm…

3 Likes

One of my go-to torture tests for NTSC sharpness is Final Fantasy Tactics- lots of small details that can be easily lost.

Anything with a lot of sharp black lines (vertical) is useful as well - a lot of 8 bit stuff. Super Mario Bros, the outline around the green pipe…

But yeah, 240p Test Suite pretty much has you covered as well. Ringing around the white text if you oversharpen, blurry text if you undersharpen… Color bars will show if you have clipping, etc

3 Likes

I can give you a few games and scenarios off the top of my head:

Donkey Kong Country - SNES

The gradients in the green Nintendo Logo. I like them to gradually fade to black without crushing the darker tones.

Similarly the speakers in the boom box, I like to be able to see the speakers without raising the black levels.

Super Metroid - SNES

Blend dithering on the letters on the Title Screen.

Super Mario World - SNES

Blend checkerboard dithering on blue background and water.

Super Double Dragon, Final Fantasy Mystic Quest, Samurai Showdown

Make sure power bars are rendered evenly.

This also applies to the level meters in Ninja Spirit - Turbo Duo’s sound test.

Some of these can be resolved, helped by choosing the correct aspect ratio and scaling settings.

Gate of Thunder 4 in 1 - Turbo Duo

When Bonk appears, make sure you can see darker shade of yellow is visible in the center of the spotlight without there being a harsh/obvious transition between the 2 shades.

Gate of Thunder Intro, Ys IV cut scenes, Psychosis level 1

Blend all dithering to produce additional colours without introducing any NTSC artifacts to ruin the illusion of seamless additional colours.

Lords Of Thunder, Bank’s Revenge

White text in HUD can be used to test highlight clipping.

Genesis:

Well everyone know about Sonic The Hedgehog level 1 and Streets of Rage 2 bar level for checking transparency and the rainbow effect but Sonic 2 Chemical Plant Zone is a good one too.

Sega Saturn:

Daytona USA for transparencies

PlayStation:

Marvel Super Heroes, Shuma Gorath in the title screen for testing saturation/clipping.

3 Likes

from here seems they are very close in Blending (all of them are indeed has some level of blend compare to RAW razor sharp pixels in emus)

2 Likes

Very detailed. Thank you for taking your time to write this answer! I appreciate it.

2 Likes

That TV has a very good comb filter and signal processing - to get a full blend requires a notch filter, so like a pre-1985 TV or something

2 Likes

@guest.r

Is there a way to simulate saturation loss associated with chroma bleed? Basically, reds should bleed out and look a bit duller, etc?

Currently, it looks like stuff bleeds but kinda remains the same color?

EDIT: gtu-v50 is doing the thing- gives us direct control over YIQ and can achieve that subtle color loss/desaturation with the bleed, adjusted correctly.

guest-ntsc / ntsc-adaptive kinda does it but you have to use a very low setting for chroma scaling and it’s not quite as accurate looking.

1 Like

Hi @guest.r

any reason why EVEN/ODD scanlines is missing? maybe they can be added as interlaced mode=-1 so every 240 settings should work in 480 mode (the 480 mode will be 240 but shifting vertically based on if odd/even frame)

1 Like

That would be Reshade port specific, in Retroarch we fortunatelly get perfect info on vertical resolutions and such hacks aren’t needed.

About interlacing, i really don’t know why i should double the vertical input buffer size by 2x. Some other shader might be designed around this for specific reasons, but not guest-advanced.

With the current state you can play 224p, 240p…content without issues, you can interlace 480p input, or leave it 480p. Other situations are “perfectly” covered too.

I guess the only issue which remains is that guest-advanced-ntsc 2-phase and interlacing pass can be synced. In this case merge fields or disable fringing. Rainbowing wasn’t a thing with 480i, no need to break your teeth on this.

1 Like

I mean a mode that act like retroarch CRT-Geom and crt-beans in 480, which use 240p scanlines in 480i but as interlaced scan, interlaced mode=1 is close to it but still there are some settings in “scanline options” that wont affect anything in 480 mode! and that reasonable for many of interlaced modes of CRT Guest Advanced like mode 4

1 Like

It’s the shader design, you can still produce odd-even scanlines in the interlacing/linearize pass by increasing the Interlacing Scanline Effect ('Laced brightness) parameter.

Otherwise i’m quite happy with the current implementation. I’m quite sure interlacing on a regular crt tv didn’t produce same scanline effects as with non-interlaced resolutions.

Interlacing on a regular crt relied on overlaping and phosphor persistance, so there wasn’t a significant brightness loss as detailed “digital, emulated” scanlines would produce. The brightness loss more or less resulted in phosphor fade, which could be also a bit eye straining.

1 Like

well, yes but not 100% different https://youtu.be/YLmv-QL_hG4?t=64

true but in modern screens we got something similar (or worst) which is motion blur :slight_smile: also the after glow pass will help

dont get me wrong, your design for implementing interlaced is nice, and does not blindly imitate interlaced in TV, but still it’s nice to have an option to blindly imitate interlaced in TV, Especially in some presets that has very bright 240p settings (Especially with settings that almost kill the scanlines in bright areas), and as I said interlaced mode=1 is so close to what I want but many settings wont affect in it (Especially settings in “scanline options”)

2 Likes

Hmm…well…i guess this would bring some extra work and tweaking.

Edit: i guess i have it running, too bad there are more guest-advanced versions = more work… :grin:

2 Likes

New Release Version (2025-10-01-r1):

Notable changes:

  • New interlace modes added to standard, ntsc and HD versions.
  • They use odd/even field shifted regular scanlines instead of odd/even linear scanlines.

Download link:

https://mega.nz/file/8oATlIwT#O-JIikltxqHpwcpRvp5No3okMJuv9lDmgqNnkPrgw6E

4 Likes

thanks! I did a test and seems work fine!

what about fast and fastest? I plan to use them, I did test fastest in 2016 mid/low end mobile and seems work even with ntsc adaptive!

also, is it possible to has an option to make “Rolling Scanlines” work only with interlace mode 6 and only with 480?

I guess many feature tweaks are possible, but not this plausible.

I did a test with reinterlacing.slangp then append crt-guest-advanced.slangp

shaders = "13"
feedback_pass = "0"
shader0 = "shaders_slang/crt/shaders/guest/advanced/stock.slang"
alias0 = ""
wrap_mode0 = "clamp_to_border"
mipmap_input0 = "false"
filter_linear0 = "false"
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/deinterlacing/shaders/reinterlacing.slang"
alias1 = ""
wrap_mode1 = "clamp_to_border"
mipmap_input1 = "false"
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/shaders/guest/advanced/stock.slang"
alias2 = "StockPass"
wrap_mode2 = "clamp_to_border"
mipmap_input2 = "false"
filter_linear2 = "false"
float_framebuffer2 = "false"
srgb_framebuffer2 = "false"
scale_type_x2 = "source"
scale_x2 = "1.000000"
scale_type_y2 = "source"
scale_y2 = "1.000000"
shader3 = "shaders_slang/crt/shaders/guest/advanced/afterglow0.slang"
alias3 = "AfterglowPass"
wrap_mode3 = "clamp_to_border"
mipmap_input3 = "false"
filter_linear3 = "false"
float_framebuffer3 = "false"
srgb_framebuffer3 = "false"
scale_type_x3 = "source"
scale_x3 = "1.000000"
scale_type_y3 = "source"
scale_y3 = "1.000000"
shader4 = "shaders_slang/crt/shaders/guest/advanced/pre-shaders-afterglow.slang"
alias4 = "PrePass"
wrap_mode4 = "clamp_to_border"
mipmap_input4 = "true"
filter_linear4 = "false"
float_framebuffer4 = "false"
srgb_framebuffer4 = "false"
scale_type_x4 = "source"
scale_x4 = "1.000000"
scale_type_y4 = "source"
scale_y4 = "1.000000"
shader5 = "shaders_slang/crt/shaders/guest/advanced/avg-lum.slang"
alias5 = "AvgLumPass"
wrap_mode5 = "clamp_to_border"
mipmap_input5 = "true"
filter_linear5 = "true"
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/shaders/guest/advanced/linearize.slang"
alias6 = "LinearizePass"
wrap_mode6 = "clamp_to_border"
mipmap_input6 = "false"
filter_linear6 = "true"
float_framebuffer6 = "true"
srgb_framebuffer6 = "false"
scale_type_x6 = "source"
scale_x6 = "1.000000"
scale_type_y6 = "source"
scale_y6 = "1.000000"
shader7 = "shaders_slang/crt/shaders/guest/advanced/gaussian_horizontal.slang"
alias7 = ""
wrap_mode7 = "clamp_to_border"
mipmap_input7 = "false"
filter_linear7 = "true"
float_framebuffer7 = "true"
srgb_framebuffer7 = "false"
scale_type_x7 = "absolute"
scale_x7 = "800"
scale_type_y7 = "source"
scale_y7 = "1.000000"
shader8 = "shaders_slang/crt/shaders/guest/advanced/gaussian_vertical.slang"
alias8 = "GlowPass"
wrap_mode8 = "clamp_to_border"
mipmap_input8 = "false"
filter_linear8 = "true"
float_framebuffer8 = "true"
srgb_framebuffer8 = "false"
scale_type_x8 = "absolute"
scale_x8 = "800"
scale_type_y8 = "absolute"
scale_y8 = "600"
shader9 = "shaders_slang/crt/shaders/guest/advanced/bloom_horizontal.slang"
alias9 = ""
wrap_mode9 = "clamp_to_border"
mipmap_input9 = "false"
filter_linear9 = "true"
float_framebuffer9 = "true"
srgb_framebuffer9 = "false"
scale_type_x9 = "absolute"
scale_x9 = "800"
scale_type_y9 = "absolute"
scale_y9 = "600"
shader10 = "shaders_slang/crt/shaders/guest/advanced/bloom_vertical.slang"
alias10 = "BloomPass"
wrap_mode10 = "clamp_to_border"
mipmap_input10 = "false"
filter_linear10 = "true"
float_framebuffer10 = "true"
srgb_framebuffer10 = "false"
scale_type_x10 = "source"
scale_x10 = "1.000000"
scale_type_y10 = "source"
scale_y10 = "1.000000"
shader11 = "shaders_slang/crt/shaders/guest/advanced/crt-guest-advanced.slang"
alias11 = ""
wrap_mode11 = "clamp_to_border"
mipmap_input11 = "false"
filter_linear11 = "true"
float_framebuffer11 = "true"
srgb_framebuffer11 = "false"
scale_type_x11 = "viewport"
scale_x11 = "1.000000"
scale_type_y11 = "viewport"
scale_y11 = "1.000000"
shader12 = "shaders_slang/crt/shaders/guest/advanced/deconvergence.slang"
alias12 = ""
wrap_mode12 = "clamp_to_border"
mipmap_input12 = "false"
filter_linear12 = "true"
float_framebuffer12 = "false"
srgb_framebuffer12 = "false"
scale_type_x12 = "viewport"
scale_x12 = "1.000000"
scale_type_y12 = "viewport"
scale_y12 = "1.000000"
interm = "6.000000"
textures = "SamplerLUT1;SamplerLUT2;SamplerLUT3;SamplerLUT4"
SamplerLUT1 = "shaders_slang/crt/shaders/guest/advanced/lut/trinitron-lut.png"
SamplerLUT1_mipmap = "false"
SamplerLUT1_wrap_mode = "clamp_to_border"
SamplerLUT2 = "shaders_slang/crt/shaders/guest/advanced/lut/inv-trinitron-lut.png"
SamplerLUT2_mipmap = "false"
SamplerLUT2_wrap_mode = "clamp_to_border"
SamplerLUT3 = "shaders_slang/crt/shaders/guest/advanced/lut/nec-lut.png"
SamplerLUT3_mipmap = "false"
SamplerLUT3_wrap_mode = "clamp_to_border"
SamplerLUT4 = "shaders_slang/crt/shaders/guest/advanced/lut/ntsc-lut.png"
SamplerLUT4_mipmap = "false"
SamplerLUT4_wrap_mode = "clamp_to_border"

there is indeed a phosphor persistance magic! I cant show you since it’s interlaced, you can try it and see

but not always work, here a test with just reinterlacing and afterglow

shaders = "5"
feedback_pass = "0"
shader0 = "shaders_slang/crt/shaders/guest/advanced/stock.slang"
alias0 = ""
wrap_mode0 = "clamp_to_border"
mipmap_input0 = "false"
filter_linear0 = "false"
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/deinterlacing/shaders/reinterlacing.slang"
alias1 = ""
wrap_mode1 = "clamp_to_border"
mipmap_input1 = "false"
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/shaders/guest/advanced/stock.slang"
alias2 = "StockPass"
wrap_mode2 = "clamp_to_border"
mipmap_input2 = "false"
filter_linear2 = "false"
float_framebuffer2 = "false"
srgb_framebuffer2 = "false"
scale_type_x2 = "source"
scale_x2 = "1.000000"
scale_type_y2 = "source"
scale_y2 = "1.000000"
shader3 = "shaders_slang/crt/shaders/guest/advanced/afterglow0.slang"
alias3 = "AfterglowPass"
wrap_mode3 = "clamp_to_border"
mipmap_input3 = "false"
filter_linear3 = "false"
float_framebuffer3 = "false"
srgb_framebuffer3 = "false"
scale_type_x3 = "source"
scale_x3 = "1.000000"
scale_type_y3 = "source"
scale_y3 = "1.000000"
shader4 = "shaders_slang/crt/shaders/guest/advanced/pre-shaders-afterglow.slang"
alias4 = "PrePass"
wrap_mode4 = "clamp_to_border"
mipmap_input4 = "true"
filter_linear4 = "false"
float_framebuffer4 = "false"
srgb_framebuffer4 = "false"
scale_type_x4 = "source"
scale_x4 = "1.000000"
scale_type_y4 = "source"
scale_y4 = "1.000000"
textures = "SamplerLUT1;SamplerLUT2;SamplerLUT3;SamplerLUT4"
SamplerLUT1 = "shaders_slang/crt/shaders/guest/advanced/lut/trinitron-lut.png"
SamplerLUT1_mipmap = "false"
SamplerLUT1_wrap_mode = "clamp_to_border"
SamplerLUT2 = "shaders_slang/crt/shaders/guest/advanced/lut/inv-trinitron-lut.png"
SamplerLUT2_mipmap = "false"
SamplerLUT2_wrap_mode = "clamp_to_border"
SamplerLUT3 = "shaders_slang/crt/shaders/guest/advanced/lut/nec-lut.png"
SamplerLUT3_mipmap = "false"
SamplerLUT3_wrap_mode = "clamp_to_border"
SamplerLUT4 = "shaders_slang/crt/shaders/guest/advanced/lut/ntsc-lut.png"
SamplerLUT4_mipmap = "false"
SamplerLUT4_wrap_mode = "clamp_to_border"

with “Afterglow Strength” = 0.00

with “Afterglow Strength” = 0.60

it should fill the gaps but it seems it only fill the edge

and with reinterlacing this problem will be worst!

1 Like

I’ve been getting some GREAT results by stacking NTSC colors + GTUv50 + guest-advanced-NTSC.

Unfortunately, it makes my GPU explode - and it’s no slouch (3090 Ti). Games run fine, but it gets the fans spinning full speed. When I try to edit parameters it drops to like 5 fps or something while in the RA menu.

Would there be any significant performance benefit gained by stripping out all the glow and bloom effects and screen options? This is something I’d attempt on my own, just wondering if it would be worth it.

EDIT: nevermind, figured it out, carry on…

that because GTUv50 use viewport (your screen size), maybe NTSC colors is doing this too

1 Like

I solved the problem:

Pause Content When Menu is Active OFF
Pause Content When Not Active OFF