Please show off what crt shaders can do!

Thanks! Yeah lately I’ve been making the bright beams super wide for additional brightness in highlights, I like the way it looks. IMO it’s basically required in order to get the best dynamic range based on how the internal clamping works in guest-advanced, it’s possible I’ve missed something, though.

Not an emulated notch filter, but maybe as close as it gets with guest-ntsc, there’s a bit of wiggle room too for various quality notch filters. I think I’ve identified all of the parameters that would be influenced by notch/comb filtering. A truly emulated notch filter would require a whole new approach than what ntsc-adaptive is doing- the kind of thing PlainOldPants, DariusG and beans are doing.

Visually, one of the key characteristics is that notch filters are quite a bit blurrier than comb filters, you won’t have razor sharp black lines, etc. Another thing worth noting is you don’t get perfectly blended dithering even with notch filters, it’s probably like 80-90% blended (with comb filters even less of a blend).

I have a few reference shots collected on my phone for notch filter, I’ll do a comparison later.

2 Likes

Ok, finding photos of CRTs that are definitely using notch filters is a bit more difficult than I hoped - I collected a few that “look notch,” but couldn’t confirm 100% if that’s the case.

One thing that we’re not emulating is the vertical fringing you get with comb filters - I don’t know why you would ever want that, though. Basically, I’m just trying to eyeball this in some photos I’ve collected - not very scientific.

https://crtdatabase.com/articles/retrotink-composite-decoding

The thing to look for is clean horizontal lines.

I kind of want to say this one from @Jamirus is notch- the horizontal lines are pretty clean and it’s got the stronger chroma bleed.

(How crappy of a TV do you need for composite video artifacts?)

2 Likes

Probably worth distinguishing between a 3d adaptive comb filter (best case composite, e.g., Sony Wega Trinitron) and a 2D comb filter. From my studies, for retro gaming it’s:

3d adaptive comb filter > 3d comb filter > notch filter > 2d comb filter > nothing

3 Likes

Early computer monitors seem to be good candidates, e.g. Commodore 1701 and the Apple II composite displays, although it’s probably troublesome to find something like NES games running on the latter. The Apple II’s output itself seems to be a bit particular. But apparently, it can make differences with filters pretty obvious. (I may have linked that before…but anyway, when scrolling down to “Filtering and Artifact color” there are some pictures, a 3d adaptive filter is supposed to be devastating in this context…and not because it’s turns the picture upside down, that’s addressed in the comments :smile:).

2 Likes

Came up with this after talking to @PlainOldPants for a bit.

NTSC Colors + GTUv50 + guest-advanced-ntsc

-GTUv50 for more accurate YIQ-based Chroma bleed effect

-NTSC color for NTSC color correction (I think that’s what it does?)

-adjusted color temp to -100 (I guess this is 9300k?)

-lowered contrast for aged phosphor “vintage” look

I’m sure there’s some improvement to be made to the settings, particularly fringing/artifacting, but looking at the videos posted here, I think it’s pretty close!

edit: made a few changes so the photos are no longer an exact match, but still close enough. Improved sharpness, artifacting and fringing. A more chroma smeared image will naturally reduce the appearance of dot crawl and fringing, etc - something to keep in mind when adding chroma smear/bleed. Notch filters had the more pronounced chroma smear, while comb filters reduced the chroma smear and made other artifacts like dot crawl and fringing more apparent. This is probably closer to a notch filter.

shaders = "22"
feedback_pass = "0"
shader0 = "shaders_slang/misc/shaders/ntsc-colors.slang"
alias0 = ""
wrap_mode0 = "clamp_to_border"
mipmap_input0 = "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/crt/shaders/gtu-v050/pass1.slang"
alias1 = ""
wrap_mode1 = "clamp_to_border"
mipmap_input1 = "false"
float_framebuffer1 = "true"
srgb_framebuffer1 = "false"
scale_type_x1 = "source"
scale_x1 = "1.000000"
scale_type_y1 = "source"
scale_y1 = "1.000000"
shader2 = "shaders_slang/crt/shaders/gtu-v050/pass2.slang"
alias2 = ""
wrap_mode2 = "clamp_to_border"
mipmap_input2 = "false"
filter_linear2 = "false"
float_framebuffer2 = "true"
srgb_framebuffer2 = "false"
scale_type_x2 = "viewport"
scale_x2 = "1.000000"
scale_type_y2 = "source"
scale_y2 = "1.000000"
shader3 = "shaders_slang/crt/shaders/gtu-v050/pass3.slang"
alias3 = ""
wrap_mode3 = "clamp_to_border"
mipmap_input3 = "false"
filter_linear3 = "false"
float_framebuffer3 = "false"
srgb_framebuffer3 = "false"
scale_type_x3 = "viewport"
scale_x3 = "1.000000"
scale_type_y3 = "viewport"
scale_y3 = "1.000000"
shader4 = "shaders_slang/crt/shaders/guest/advanced/stock.slang"
alias4 = ""
wrap_mode4 = "clamp_to_border"
mipmap_input4 = "false"
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/stock.slang"
alias5 = "StockPass"
wrap_mode5 = "clamp_to_border"
mipmap_input5 = "false"
filter_linear5 = "false"
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/afterglow0.slang"
alias6 = "AfterglowPass"
wrap_mode6 = "clamp_to_border"
mipmap_input6 = "false"
filter_linear6 = "true"
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/shaders/guest/advanced/pre-shaders-afterglow.slang"
alias7 = "PrePass0"
wrap_mode7 = "clamp_to_border"
mipmap_input7 = "false"
filter_linear7 = "true"
float_framebuffer7 = "false"
srgb_framebuffer7 = "false"
scale_type_x7 = "source"
scale_x7 = "1.000000"
scale_type_y7 = "source"
scale_y7 = "1.000000"
shader8 = "shaders_slang/crt/shaders/guest/advanced/ntsc/ntsc-pass1.slang"
alias8 = "NPass1"
wrap_mode8 = "clamp_to_border"
mipmap_input8 = "false"
filter_linear8 = "false"
float_framebuffer8 = "true"
srgb_framebuffer8 = "false"
scale_type_x8 = "source"
scale_x8 = "4.000000"
scale_type_y8 = "source"
scale_y8 = "1.000000"
shader9 = "shaders_slang/crt/shaders/guest/advanced/ntsc/ntsc-pass2.slang"
alias9 = ""
wrap_mode9 = "clamp_to_border"
mipmap_input9 = "false"
filter_linear9 = "true"
float_framebuffer9 = "true"
srgb_framebuffer9 = "false"
scale_type_x9 = "source"
scale_x9 = "0.500000"
scale_type_y9 = "source"
scale_y9 = "1.000000"
shader10 = "shaders_slang/crt/shaders/guest/advanced/ntsc/ntsc-pass3.slang"
alias10 = ""
wrap_mode10 = "clamp_to_border"
mipmap_input10 = "false"
filter_linear10 = "true"
float_framebuffer10 = "false"
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/custom-fast-sharpen.slang"
alias11 = "NtscPass"
wrap_mode11 = "clamp_to_border"
mipmap_input11 = "false"
filter_linear11 = "true"
float_framebuffer11 = "false"
srgb_framebuffer11 = "false"
scale_type_x11 = "source"
scale_x11 = "1.000000"
scale_type_y11 = "source"
scale_y11 = "1.000000"
shader12 = "shaders_slang/crt/shaders/guest/advanced/stock.slang"
alias12 = "PrePass"
wrap_mode12 = "clamp_to_border"
mipmap_input12 = "true"
filter_linear12 = "true"
float_framebuffer12 = "false"
srgb_framebuffer12 = "false"
scale_type_x12 = "source"
scale_x12 = "1.000000"
scale_type_y12 = "source"
scale_y12 = "1.000000"
shader13 = "shaders_slang/crt/shaders/guest/advanced/avg-lum-ntsc.slang"
alias13 = "AvgLumPass"
wrap_mode13 = "clamp_to_border"
mipmap_input13 = "true"
filter_linear13 = "true"
float_framebuffer13 = "false"
srgb_framebuffer13 = "false"
scale_type_x13 = "source"
scale_x13 = "1.000000"
scale_type_y13 = "source"
scale_y13 = "1.000000"
shader14 = "shaders_slang/crt/shaders/guest/advanced/linearize-ntsc.slang"
alias14 = "LinearizePass"
wrap_mode14 = "clamp_to_border"
mipmap_input14 = "false"
filter_linear14 = "true"
float_framebuffer14 = "true"
srgb_framebuffer14 = "false"
scale_type_x14 = "source"
scale_x14 = "1.000000"
scale_type_y14 = "source"
scale_y14 = "1.000000"
shader15 = "shaders_slang/crt/shaders/guest/advanced/crt-guest-advanced-ntsc-pass1.slang"
alias15 = "Pass1"
wrap_mode15 = "clamp_to_border"
mipmap_input15 = "false"
filter_linear15 = "true"
float_framebuffer15 = "true"
srgb_framebuffer15 = "false"
scale_type_x15 = "viewport"
scale_x15 = "1.000000"
scale_type_y15 = "source"
scale_y15 = "1.000000"
shader16 = "shaders_slang/crt/shaders/guest/hd/gaussian_horizontal.slang"
alias16 = ""
wrap_mode16 = "clamp_to_border"
mipmap_input16 = "false"
filter_linear16 = "true"
float_framebuffer16 = "true"
srgb_framebuffer16 = "false"
scale_type_x16 = "absolute"
scale_x16 = "800"
scale_type_y16 = "source"
scale_y16 = "1.000000"
shader17 = "shaders_slang/crt/shaders/guest/advanced/gaussian_vertical.slang"
alias17 = "GlowPass"
wrap_mode17 = "clamp_to_border"
mipmap_input17 = "false"
filter_linear17 = "true"
float_framebuffer17 = "true"
srgb_framebuffer17 = "false"
scale_type_x17 = "absolute"
scale_x17 = "800"
scale_type_y17 = "absolute"
scale_y17 = "600"
shader18 = "shaders_slang/crt/shaders/guest/hd/bloom_horizontal.slang"
alias18 = ""
wrap_mode18 = "clamp_to_border"
mipmap_input18 = "false"
filter_linear18 = "true"
float_framebuffer18 = "true"
srgb_framebuffer18 = "false"
scale_type_x18 = "absolute"
scale_x18 = "800"
scale_type_y18 = "absolute"
scale_y18 = "600"
shader19 = "shaders_slang/crt/shaders/guest/advanced/bloom_vertical.slang"
alias19 = "BloomPass"
wrap_mode19 = "clamp_to_border"
mipmap_input19 = "false"
filter_linear19 = "true"
float_framebuffer19 = "true"
srgb_framebuffer19 = "false"
scale_type_x19 = "absolute"
scale_x19 = "800"
scale_type_y19 = "absolute"
scale_y19 = "600"
shader20 = "shaders_slang/crt/shaders/guest/advanced/crt-guest-advanced-ntsc-pass2.slang"
alias20 = ""
wrap_mode20 = "clamp_to_border"
mipmap_input20 = "false"
filter_linear20 = "true"
float_framebuffer20 = "true"
srgb_framebuffer20 = "false"
scale_type_x20 = "viewport"
scale_x20 = "1.000000"
scale_type_y20 = "viewport"
scale_y20 = "1.000000"
shader21 = "shaders_slang/crt/shaders/guest/advanced/deconvergence-ntsc.slang"
alias21 = ""
wrap_mode21 = "clamp_to_border"
mipmap_input21 = "false"
filter_linear21 = "true"
float_framebuffer21 = "false"
srgb_framebuffer21 = "false"
scale_type_x21 = "viewport"
scale_x21 = "1.000000"
scale_type_y21 = "viewport"
scale_y21 = "1.000000"
compositeConnection = "1.000000"
signalResolution = "512.000000"
signalResolutionI = "84.000000"
signalResolutionQ = "26.000000"
tvVerticalResolution = "240.000000"
contrast = "0.900000"
WP = "-100.000000"
sega_fix = "1.000000"
cust_artifacting = "1.000000"
cust_fringing = "1.000000"
ntsc_cscale = "4.000000"
ntsc_cscale1 = "2.250000"
ntsc_shape = "0.500000"
CSHARPEN = "1.000000"
CCONTR = "0.250000"
DEBLUR = "3.500000"
GAMMA_INPUT = "2.400000"
gamma_out = "2.400000"
interm = "3.000000"
HSHARPNESS = "1.199999"
SIGMA_HOR = "0.500000"
S_SHARP = "1.500002"
HSHARP = "1.400000"
MAXS = "0.220000"
HARNG = "0.200000"
m_glow = "2.000000"
glow = "0.000000"
gsl = "2.000000"
scanline1 = "5.000000"
scanline2 = "70.000000"
beam_min = "1.000000"
beam_max = "0.600000"
beam_size = "0.000000"
scans = "1.000000"
shadowMask = "12.000000"
maskstr = "1.000000"
mcut = "1.000000"
deconrry = "1.000000"
deconrby = "-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"
4 Likes

-NTSC color for NTSC color correction (I think that’s what it does?)

That’s a good opportunity then to clarify what it does vs. what other options do like Blargg filters and the shaders by @Guest and others (how does the NTSC LUT compare?)

Also, does it make a difference for content (hardware) that uses non-RGB palettes (NES, Atari 8-bit consoles and computers, C64 etc…) versus RGB generated? I wonder if there are scenarios where you are correcting essentially twice.

2 Likes

Hey there,

Still trying to prepend various stuff like NTSC-adaptative and scaleFX for NewPixie. I use 1080p, seems the rolling scanlines are set to fit that resolution. Is there a way to adapt the shader to QHD or 4K in the parameters? There’s no Y-resolution parameter, so when trying on those resolutions, the scanlines are a bit too thin for my taste.

Having a blast from the past right now with Isolated Warrior, my favourite game on the NES… Look at this guy, old friend of mine…

3 Likes

Good point, yes, I think you’re double correcting with those consoles when you select an NTSC palette- the palette should already be “corrected,” right? Any palette based on the final displayed image on a CRT doesn’t need to be corrected again…

Turbografx 16 is interesting, it did its own internal correction with a LUT to convert RGB to composite video colors before sending the signal to the TV, so the colors stay fairly consistent when switching from RGB and composite.

2 Likes

Nice! What’s that game?

1 Like

Yeah the design is really cool. It’s a boss from NES game “Isolated Warrior”.

2 Likes

Guest-advanced-ntsc + GTUv50 + NTSC colors, adjusted to 9300k, 4k HDR1000, adjusted for Trinitron-like sharpness while fully blending dithering:

3 Likes

Threw together this quick comparison in guest-advanced-ntsc (can only be viewed correctly on an HDR1000 monitor; please forgive the darkness otherwise)

Composite

S-video

RGB

2 Likes

Hey there!

This week’s tweak got me playing some GameBoy Color titles. I’m a sucker for the retroachievement event and this month’s Zelda Oracle of Season is prescribed, so I’ll play that, to praise and please goddess Cheevos.

The shader chain comprise a LCD time response motion blur for transparency sprites based on blinking (I found it looked better to me than the built in motion blur in some cores when using the next shaders on top), JINC2 and ScaleFX for upscaling, GBC color correction and then CRT-Guest-Advanced-NTSC. Thanks you guys so much for all that. Here are some pics in 1080p and a download link if you want to test that, you can set CRT mask size and zoom parameters to your liking and resolution within the shader params ofc.

https://mega.nz/file/GBAwwSyI#xa8aPAjKrpbbiz5PmOjrp5RWYOkgirLVcGmdmIYBdvA

3 Likes

Hello my old friends and all the “new” people that share the love for CRT simulations. I finally got myself a new computer, and can run all the shaders properly at big resolutions. Was really looking forward to this. By courtesy of guest’s insane shader, enter Pulstar :slight_smile:

To my eyes, it just doesn’t get better than this.

8 Likes

Hey there!

Played some NES games this week. Mesen core with composite by FirebrandX palette, and a preset mixing JINC2, ScaleFX, NTSC adaptive and NewPixie on top. You can get the preset for 1080p here if you want a go at it :

https://mega.nz/file/WR5UVALQ#XQPzdqNUuNiTxHXSAHEkGWkvF2OK-InG9ToxL8sP5as

4 Likes

Here are more screenshots demonstrating the WIP effort on the Scanline Classic shader. https://forums.libretro.com/t/the-scanline-classic-shader/41497/13?u=anikom15

I attempted to mimic the S-Video output from the Famicom Titler. The desaturation of colors is due to the belief that the titler cuts the chroma signal by 50%, as described here: https://www.nesdev.org/wiki/X0858CE

The result appears to be somewhat of an overcorrection. I am comparing it to what a composite NES might look like using the WIP composite mode of my shader and the ‘feedback filter’. Note that the screenshots look more filthy than what it looks like while running because the fields blur together and reduce the strength of the rainbow colors.

4 Likes

When I started this “journey”, I had a goal in mind. I just wasn’t sure what it looked like. It slowly revealed itself throughout the years. Thank you all :_)

:drooling_face:

7 Likes

Ridiculously wide bloom, strong halation and vignette, and screen brightness uniformity on lowest level:

8 Likes

Hi, could you share your setting?

Yes of course. I made this using reshade and standalone MAME because it’s faster for me to run experiments and stack shaders with its gui. I will most definitely port it to retroarch in the near future and post the results here if someone is interested. Color correction and sharpness and managed with other shaders, but here goes the most important stuff, the values for guest-advanced:

addnoised=0.000000
bardir=0.000000
barintensity=0.000000
barspeed=50.000000
beam_max=1.250000
beam_min=1.300000
beam_size=0.600000
blm_1=-2.000000
blm_2=0.000000
bloom_dist=0.500000
bmask=0.000000
brightboost1=4.500000
brightboost2=1.100000
bsize=0.060000
b_mask=1.000000
clp=0.000000
csize=0.005000
c_shape=0.200000
dctypex=0.000000
dctypey=0.000000
deconbx=0.000000
deconby=0.000000
decongx=0.000000
decongy=0.000000
deconrx=0.000000
deconry=0.000000
decons=1.000000
double_slot=1.000000
downsample_levelx=1.500000
downsample_levely=0.000000
ei_limit=0.250000
FINE_BLOOM=1.000000
FINE_GAUSS=1.000000
gamma_c=1.000000
gamma_i=2.400000
gamma_o=2.400000
glow=0.300000
gsl=2.000000
halation=0.150000
hiscan=0.000000
h_mask=0.500000
h_sharp=15.000000
interm=0.000000
interr=375.000000
intres=0.000000
IOS=0.000000
iscanb=0.000000
iscans=0.250000
lsmooth=0.700000
maskboost=1.000000
masksize=1.000000
maskstr=0.600000
mask_bloom=0.000000
mask_drk=0.500000
mask_gamma=3.500000
mask_layout=1.000000
mask_lgt=1.500000
mask_zoom=0.000000
mclip=0.500000
mcut=1.100000
mshift=0.000000
m_glow=1.000000
m_glow_cutoff=0.100000
m_glow_dist=1.000000
m_glow_high=3.000000
m_glow_low=3.000000
m_glow_mask=0.500000
noiseresd=1.000000
noisetype=1.000000
no_scanlines=0.000000
OS=0.000000
overscanx=0.000000
overscany=0.000000
post_br=1.000000
PreprocessorDefinitions=Resolution_X=1920,Resolution_Y=224
ring=0.000000
sborder=0.750000
scangamma=3.500000
scanline1=20.000000
scanline2=8.000000
scans=0.500000
scan_falloff=1.000000
shadow_msk=9.000000
SIGMA_H=2.000000
SIGMA_V=0.400000
SIGMA_X=5.000000
SIGMA_Y=1.000000
SIZEH=6.000000
SIZEV=6.000000
SIZEX=15.000000
SIZEY=2.000000
slotmask1=0.000000
slotmask2=0.000000
slotms=1.000000
slotwidth=0.000000
smart_ei=0.000000
smask_mit=0.000000
smoothmask=1.000000
spike=1.000000
ssharp=0.000000
sth=0.230000
s_sharp=0.500000
TATE=0.000000
tds=0.000000
vga_mode=0.000000
vigdef=1.000000
vigstr=0.000000
warpx=0.040000
warpy=0.040000
zoom_mask=0.000000

:drooling_face:

1 Like