NTSC shaders redux

@guest.r

Try as I might, I cannot get any currently existing NTSC shader to replicate the look of an NTSC signal as displayed on a CRT, probably due to hardware-based filtering that’s occurring on the CRT. I think a brand new NTSC shader written from the ground up is needed, using a different filtering method for the chroma smear.

Check out this photo for reference (from Hunterk). Notice how the rainbow artifacts are very pronounced in the street, but there’s no trace of that around the white text, which is quite sharp. I don’t think it’s possible to replicate with any of the tools we have available to us now. Even adaptive sharpness doesn’t quite do it, and that has the unfortunate side effect of breaking dithering.

https://forums.libretro.com/uploads/default/original/2X/a/acf6b1455f81ac073f83b28137b94a2af9e167a8.jpeg

3 Likes

I don’t like mixing and matching stuff to make it look “right”, but you can take the output of a dedither pass, extract the luma and then pair it with the janky ntsc-filtered chroma and get there pretty well:

4 Likes

I’m no expert but all of the methods I’ve tried so far seem to use blurs, Gaussian or otherwise to disperse the colour. This does the job of spreading the colour but it causes the image to lose focus at the same time. This isn’t what happens on a real CRT TV. Maybe if there were another method of correctly dispersing the stray colour information the “colour noise” could be where it’s supposed to be creating the effects we are looking for while the image remains in focus not requiring additional sharpening filters in order to bring things back after starting off wrong in the first place.

I’ve been on a similar mission as you @Nesguy and it has been a game of cat and mouse. The latest is adding some NTSC artifacts using GTU, only for it to introduce white halos and strange fuzziness to the image, while decreasing the contrast of the edges. This can be seen particularly on text.

Blur is probably not the best and only way to simulate the “improper” mixing and crosstalk of different signals used on the same cable and other effects of analog bandwidth limitations and circuitry which is what is really going on in our CRT TVs and signals.

Have you tried the Mame NTSC Shaders though? They seem to deliver the most accurate “Rainbow” effects so perhaps they use some different methods or algorithms and might have other improvements that we have yet to experiment with?

3 Likes

The thing with every dedithering shader is the false positives. Even with the use of just the luma we can see some strange things happening on the S’s and e’s in that 240p Test Suite screenshot.

It’s just another imperfect, not too accurate workaround with lots of compromises. Which is what seems to be available in our current arsenal of available tools.

1 Like

@guest.r also suggested this. Unfortunately, I don’t have time for the 1,000 knobs/dials in Mame, it’s just a bit too hardcore for me. But by all means, please see what you can do.

1 Like

One thing, I forgot to add was that part of the challenge in fine tuning these things is figuring out if the blur is being caused by the shaders/settings or my fading eyesight.

I might prefer to wait on a @HyperSpaceMadness Mega Bezel Reflection Shader integration but perhaps in my limited spare time I might give it a try.

@sonkun has been making a lot of strides with his integration as well as @ynnad4.

I’ve also seen a couple other users in these forums extolling the virtues of that shader.

I haven’t given up just yet and I’m really satisfied with the way Arcade, NES, PC Engine, Commodore 64, Atari 2600, PSX, Genesis, 32X, N64 and Dreamcast games look using my current presets. It’s only some SNES games using BSNES, which doesn’t have access to Blargg NTSC Video Filters that I currently still have an issue with. Specifically games that use lots of bright, solid colours with black outlines for example games from the “big N” and Megaman, while darker games which use a lot of shading fare much much better with little to no noticeable blur on the high contrast edges.

1 Like

As I think I’ve mentioned before, I don’t think it’s really feasible for there to be a single perfect, one-size-fits-all NTSC shader/filter that looks exactly like every console’s output, since consoles frequently did weird, nonstandard stuff with the signals. For example, IIRC, the various Genesis/MD models vary in the quality of their composite signals, and I believe NES’ colorburst and dot-crawl stuff are unique, as well.

With that said, the nes_raw_palette NTSC shaders from cgwg and aliaspider emulate the console’s full NTSC video pipeline and manage to stay pretty sharp while still nailing the checkerboard rainbow seen on the Ninja Gaiden sidewalk:

The cgwg one at least is easy to pair up with other CRT effects, since you just need to replace the last pass–which is essentially just regular ol’ crt-geom–with your shader(s) of choice. EDIT: seems you can do it with the gtu one, too.

6 Likes

As I mentioned before, I haven’t given up. Sometimes it’s not about the tools but the technician and I’m still trying to learn and understand these things so I guess we just need to keep trying, learning and growing as the available tools themselves continue to evolve.

Old

New

3 Likes

Also if I may suggest you give a shot to crt-geom-ntsc-sharp shader. It’s the sharpest out of the box shader I’ve tried and blends everything real nice.

3 Likes

Another potentially game changing possibility is if advanced users could have had access to the parameters of the Blargg NTSC Video Filters built into several cores instead of the rigid presets that we currently have which don’t look anything like the way my NES looked on my Commodore 1702 Monitor back in the day.

Just a tiny bit of fine tuning can bring those Blargg presets into the current century.

1 Like

Tried it but it doesn’t quite address the problem and has its own weird artifacts. I’m convinced that there is nothing that can be done short of an entirely new shader.

@Cyber

I gave guest+MAME a spin and I’m not seeing any obvious advantage compared to regular guest-ntsc. Do you have any ideas?

@hunterk Could you please move these posts to a new topic?

3 Likes

I was waiting for the split before responding but here goes. I have only read about this shader combination mainly through the works and diligence of @ynnad4 and @sonkun, who I would say have been much more passionate than I am about getting the rainbow effects right when it comes to Genesis transparencies.

I prefer a rainbow-less experience that does transparency well and that’s exactly what I’ve been able to achieve with my filter preset tweaks.

I think I could remember @sonkun expressing that there was an advantage in using that particular shader combination over the others in terms of accurately generating that particular effect, which is why I suggested probably lookin in that as well as their direction as we probably don’t need to reinvent the wheel with the amount of time and experience that they had already put into the matter.

I have gathered some of the useful posts which I think might be relevant in this regard and I’ll share them in a post if the topic is eventually split.

I’m a tinkerer but I don’t have much incentive to delve into that particular shader combination at this very moment since I’m kinda addicted to HSM Mega Bezel Reflection Shader. So much so that you can even call me a fanboy…lol

If I happen to get a chance someday, I might definitely give it a go but it’s not up there on my list of priorities.

Maybe if it can do a better job than the GTU or CRT-Guest-Advance-NTSC that are already integrated in HSM Mega Bezel Reflection Shader then that would make me much more motivated and inclined because I was recently trying to see if I could’ve added a nice composite effect to BSNES/HIGAN emulation and have had some limited success but there is still lots of room for improvement.

Anyway, I would like to get back on topic with much respect to the shader wizard himself @guest.r and one of his most significant partners in talent @HyperspaceMadness and all other Shader creators out there!

I’d say that I haven’t even scratched the surface of what could be done with CRT-Guest-Advance-NTSC if you count how much time I’ve spent trying to tweak it vs trying other solutions.

I can also argue that I probably didn’t need as much time with those solutions to start seeing results closer to what I was looking for as well but that could be just because of my lack of skill and experience and not have any bearing on the shader itself.

With advance tools requires advanced knowledge.

1 Like

You’re right, that mame_ntsc shader is the only one I’ve come across that gets the rainbow effect down correct, Youtuber Retro Crisis made a video showcasing my composite preset showing off that very effect on the Sonic waterfall:

I guess as a start if @Nesguy wants to try, he can start with the shader in the ntsc folder called “md rainbows” or something like that, it’s basically the mame_ntsc shader tweaked to give you that rainbow banding effect. There’s a couple ntsc parameters that can be tweaked there so that can be a start.

I personally like the mame_ntsc shader that’s located in the folder:

crt/shaders/mame_hlsl/shaders/old/shaders/mame_hlsl/shaders/mame_ntsc

There’s a parameter setting there called “Signal Offset” that not only gives off a smoother looking image but also gives off a slight flickering effect that has been turned off by default in all the newer mame_ntsc shaders. Only thing about that setting is that has this weird “twitch” effect where the screen “jumps” every few seconds. Some people may not like it but I don’t mind.

@hunterk I guess I replied right when you moved the topic lol. Please move my reply over there as well.

1 Like

@Nesguy

This is a list of some of the posts that I’ve read concerning the same MAME NTSC shader Mod as well as some other NTSC Shader talk using the Blargg Filter, which is another one you can try tinkering with. You can even use my custom filter presets as a starting point then add more or less of the things that might help you in your quest, for example more artifacts, higher or lower resolution, more or less sharpness.

I find its pretty decent in the way that it does things and a little goes a long way. I know we’ve already talked about trying to tweak those before.

One thing I would add is that there’s an inherent difference in the way the drawn phosphors and mask wires/metal looks in software form on a flat panel display vs the real CRT. Something like the black lines between each individual phosphor, this can have an effect on sharpness and contrast. That’s not present in the shaders. They display the RGB colours side by side with no black lines between individual phosphor colours as far as I can tell, at least for the slot masks.

Rainbow with composite - MOD preset for Sega Genesis Games

Custom preset para Blargg NTSC Mega Drive video compuesto

NTSC Shaders for SEGA Mega Drive / Genesis

New CRT shader from Guest + CRT Guest Advanced updates

Rainbow with composite - MOD preset for Sega Genesis Games

Custom preset para Blargg NTSC Mega Drive video compuesto

At least the rainbow effect seems possible. You can reproduce some funky color effects with the Mame shader. I’ve mostly used it for reproducing computer artifacting, there are some values known out there, e.g. for more accurate Apple II output I was asking at some point here. Would help if I would actually have a clue what all those parameters actually are though :smiley:

Most important seem to be scanline duration and the NTSC values A and B.

2 Likes

I see, I was able to produce that effect fairly easy on Ninja Gaiden on my composite preset simply by tweaking both “A Value” and “B Value” to 1.00 and making sure Signal Offset is on 0. So is it safe to say that that’s the official nes composite look as far as color artitifacting goes?

1 Like

The sidewalk/checkerboard rainbow should be ~45 degrees going down from left to right. See the pic in OP

4 Likes

So something more like this:

It’s not exactly 1 for 1 as the pic in OP but it’s a start I guess.

For anyone that wants to use my preset as starting point here you go:

shader0 = "shaders_slang/crt/shaders/tvout-tweaks.slang"
filter_linear0 = "true"
wrap_mode0 = "clamp_to_border"
mipmap_input0 = "false"
alias0 = ""
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/mame_hlsl/shaders/old/shaders/mame_hlsl/shaders/mame_ntsc.slang"
filter_linear1 = "true"
wrap_mode1 = "clamp_to_border"
mipmap_input1 = "false"
alias1 = "StockPass"
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/hd/afterglow0.slang"
filter_linear2 = "false"
wrap_mode2 = "clamp_to_border"
mipmap_input2 = "false"
alias2 = "AfterglowPass"
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/grade/pre-shaders-afterglow-grade.slang"
filter_linear3 = "false"
wrap_mode3 = "clamp_to_border"
mipmap_input3 = "true"
alias3 = "PrePass"
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/hd/linearize-hd.slang"
filter_linear4 = "true"
wrap_mode4 = "clamp_to_border"
mipmap_input4 = "false"
alias4 = "LinearizePass"
float_framebuffer4 = "true"
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/hd/crt-guest-advanced-hd-pass1.slang"
filter_linear5 = "true"
wrap_mode5 = "clamp_to_border"
mipmap_input5 = "false"
alias5 = "Pass1"
float_framebuffer5 = "true"
srgb_framebuffer5 = "false"
scale_type_x5 = "viewport"
scale_x5 = "1.000000"
scale_type_y5 = "source"
scale_y5 = "1.000000"
shader6 = "shaders_slang/crt/shaders/guest/hd/bloom_horizontal.slang"
filter_linear6 = "true"
wrap_mode6 = "clamp_to_border"
mipmap_input6 = "false"
alias6 = ""
float_framebuffer6 = "true"
srgb_framebuffer6 = "false"
scale_type_x6 = "absolute"
scale_x6 = "800"
scale_type_y6 = "source"
scale_y6 = "1.000000"
shader7 = "shaders_slang/crt/shaders/guest/hd/bloom_vertical.slang"
filter_linear7 = "true"
wrap_mode7 = "clamp_to_border"
mipmap_input7 = "false"
alias7 = "BloomPass"
float_framebuffer7 = "true"
srgb_framebuffer7 = "false"
scale_type_x7 = "source"
scale_x7 = "1.000000"
scale_type_y7 = "absolute"
scale_y7 = "600"
shader8 = "shaders_slang/crt/shaders/guest/hd/crt-guest-advanced-hd-pass2.slang"
filter_linear8 = "true"
wrap_mode8 = "clamp_to_border"
mipmap_input8 = "false"
alias8 = ""
float_framebuffer8 = "true"
srgb_framebuffer8 = "false"
scale_type_x8 = "viewport"
scale_x8 = "1.000000"
scale_type_y8 = "viewport"
scale_y8 = "1.000000"
shader9 = "shaders_slang/crt/shaders/guest/hd/deconvergence-hd.slang"
filter_linear9 = "true"
wrap_mode9 = "clamp_to_border"
mipmap_input9 = "false"
alias9 = ""
float_framebuffer9 = "false"
srgb_framebuffer9 = "false"
scale_type_x9 = "viewport"
scale_x9 = "1.000000"
scale_type_y9 = "viewport"
scale_y9 = "1.000000"
TVOUT_COMPOSITE_CONNECTION = "1.000000"
TVOUT_RESOLUTION_Y = "1024.000000"
TVOUT_RESOLUTION_I = "256.000000"
TVOUT_RESOLUTION_Q = "121.599998"
ntscsignal = "1.000000"
avalue = "0.750000"
bvalue = "0.000001"
scantime = "46.900085"
ifreqresponse = "1.750000"
qfreqresponse = "1.450000"
signaloffset = "0.000000"
g_crtgamut = "0.000000"
g_vignette = "0.000000"
g_cntrst = "-0.250000"
g_sat = "-0.030000"
g_lift = "-0.030000"
HSHARP = "0.000000"
spike = "1.500000"
warpX = "0.050000"
warpY = "0.070000"
csize = "0.035000"
glow = "0.200000"
bloom = "-0.800000"
bloom_dist = "0.400000"
halation = "-0.075000"
gamma_c = "1.250000"
brightboost = "1.000000"
brightboost1 = "1.200000"
beam_min = "2.199999"
beam_max = "0.950000"
beam_size = "0.000000"
scans = "0.050000"
scan_falloff = "0.200000"
shadowMask = "6.000000"
maskstr = "1.000000"
maskboost = "1.200000"
slotmask = "1.000000"
slotmask1 = "1.000000"
slotwidth = "3.000000"
double_slot = "2.000000"
smoothmask = "1.000000"
dctypex = "0.050000"
dctypey = "0.050000"
deconrr = "1.000000"
deconrb = "-1.000000"
deconrry = "1.000000"
deconrby = "-1.000000"
post_br = "1.150000"
textures = "SamplerLUT1;SamplerLUT2;SamplerLUT3;SamplerLUT4"
SamplerLUT1 = "shaders_slang/crt/shaders/guest/advanced/lut/trinitron-lut.png"
SamplerLUT1_linear = "true"
SamplerLUT1_wrap_mode = "clamp_to_border"
SamplerLUT1_mipmap = "false"
SamplerLUT2 = "shaders_slang/crt/shaders/guest/advanced/lut/inv-trinitron-lut.png"
SamplerLUT2_linear = "true"
SamplerLUT2_wrap_mode = "clamp_to_border"
SamplerLUT2_mipmap = "false"
SamplerLUT3 = "shaders_slang/crt/shaders/guest/advanced/lut/nec-lut.png"
SamplerLUT3_linear = "true"
SamplerLUT3_wrap_mode = "clamp_to_border"
SamplerLUT3_mipmap = "false"
SamplerLUT4 = "shaders_slang/crt/shaders/guest/advanced/lut/ntsc-lut.png"
SamplerLUT4_linear = "true"
SamplerLUT4_wrap_mode = "clamp_to_border"
SamplerLUT4_mipmap = "false"

Maybe one of you can take it a step further from there.

4 Likes

I don’t remember TVs looking like that at the time… but I think we probably tuned that stuff out after a while. :smile:

1 Like

I agree and I doubt it was due to any tuning out. Remember there was not just one type of image that all TVs displayed. There were a wide variety.

1 Like