Shader Challenge: composite video on a PVM

Maybe you can try/replace with this “custom-fast-sharpen.slang”. Best results are if used together with ntsc-anti-ringing option or effects will be on both sides still.

#version 450

   Fast Sharpen Shader (Custom)
   Copyright (C) 2005 - 2022 guest(r) - [email protected]

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; either version 2
   of the License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

layout(push_constant) uniform Push
	vec4 SourceSize;
	vec4 OriginalSize;
	vec4 OutputSize;
	uint FrameCount;
} params;

#pragma parameter CSHARPEN  "Sharpen strength"       0.00 0.0 5.00 0.10 
#pragma parameter CCONTR_L  "Ammount of ringing - left"  0.05 0.0 0.25 0.01
#pragma parameter CCONTR_R  "Ammount of ringing - right"  0.05 0.0 0.25 0.01
#pragma parameter CDETAILS  "Details sharpened "     1.00 0.0 1.00 0.05 

#define CSHARPEN params.CSHARPEN
#define CCONTR_L params.CCONTR_L
#define CCONTR_R params.CCONTR_R
#define CDETAILS params.CDETAILS

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

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

void main()
   gl_Position = global.MVP * Position;
   vTexCoord = TexCoord;

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

void main()
	vec2 g01 = vec2(-1.0, 0.0)*;
	vec2 g21 = vec2( 1.0, 0.0)*; 

	vec3 c01 = texture(Source, vTexCoord + g01).rgb;
	vec3 c21 = texture(Source, vTexCoord + g21).rgb;
	vec3 c11 = texture(Source, vTexCoord      ).rgb;
	vec3 b11 = 0.5*(c01+c21); 
	float contrast  = max(max(c11.r,c11.g),c11.b);
	float contrastl = mix(2.0*CCONTR_L, CCONTR_L, contrast);
	float contrastr = mix(2.0*CCONTR_R, CCONTR_R, contrast);
	vec3 mn1 = min(min(c01*(1.0-contrastl),c11), min(c21*(1.0-contrastr),c11));
	vec3 mx1 = max(max(c01*(1.0+contrastl),c11), max(c21*(1.0+contrastr),c11));
	vec3 dif = pow(mx1-mn1+0.0001, vec3(0.75,0.75,0.75));
	vec3 sharpen = mix(vec3(CSHARPEN*CDETAILS), vec3(CSHARPEN), dif);
	c11 = clamp(mix(c11,b11,-sharpen), mn1,mx1);
	FragColor = vec4(c11,1.0); 

@Nesguy perhaps it would be fruitful to make “accurate” composite presets for more consoles? I think there’s one covering Genesis elsewhere in this forum already, but perhaps at the very least we could cover SNES as well, though, and my memory could be hazy here, I don’t recall its composite output having any particular noteworthy peculiarities compared to NES and Genesis, but I’d love to be proven wrong. In any case, some high quality pics of SNES composite output would be nice.


How can one hope to achieve this using a single preset when the blending of the waterfall and the sharpness of the NES output have a lot to do with not only how a CRT handles the signal but in how both consoles produce and output the signal?

Genesis uses 2 phase NTSC while NES uses 3 phase. NES merges fields to deal with colourburst while Genesis does not.

This produces different kinds of and levels of artifacting on either console which is why I think that a preset shouldn’t only attempt to emulate the different input and output characteristics of a TV but also the individual output characteristics of the different systems and media hooked up to that TV.

This is the same reason why if you wanted video footage to look like it came from a VHS VCR, you’d also have to simulate the tracking and other unique artifacts produced by the VHS VCR hardware device.

If you use a preset that only focused on being the perfect PVM or NES preset, VHS Video is going to look far from accurate because you’re missing an important part of the equation.

1 Like

Hey all, been a while. Just checking in. What’s the current state of NTSC shaders? Are they all still too blurry?


Ok new challenge, then: recreate the image while blending the dithering that’s supposed to be blended on the NES

1 Like

This is my most recent work on NES NTSC presets:

And this post has some clean NES Shadow Mask screenshots, not using the NTSC shader though but looks good to me.

1 Like

NTSC adaptive are still as they were. I could mess a bit with the luma coefs to produce a sharper blend, but it’s tricky because of the “integral sum” can easily produce luma artifacts. Meanwhile you could boost up adaptive sharpening a notch. :wink:

Meanwhile @sonkun has mastered the old mame ntsc shader and created very nice and sharp presets for different signal types.


Are you sure that’s even necessary?

This example below uses the NTSC preset and it’s very sharp. It can even be sharper if I adjusted the setting below Horizontal Filter Range but then that would be really harsh.

CyberLab_SNES_S-Video_Slot_Mask_IV_OLED_NTSC_II + CFRS_Mega_TV.slangp

This one below has more NTSC artifacts but isn’t as sharp but I could easily make it sharper by adjusting the Subtractive Sharpness, Horizontal Filter Range and the setting directly below it if necessary.

CyberLab_NES_Composite_Slot_Mask_IV_OLED_NTSC + CFRS_Mega_TV.slangp

Has @Nesguy fully explored all the possibilities when it comes to sharpness using the existing tools available in the shader?


Almost getting there lol. I think he’s looking for something a little different from what I’ve been tweaking though.


Probably not, something broke me and I no longer have any patience for tweaking shaders. Hence this thread


I took a brief look at what you guys have been working on and it’s pretty good! At least in a screenshot. Things tend to fall apart in fullscreen, as we all know. I’ll be able to take a closer look some time today.


Well this has to be an honour! Everyone has to go through their own process of experimenting, learning and evolution over time.

I posted a couple screenshots over at r/crtgaming just to see people’s reactions and I would say that this preset either passed or almost passed the Pepsi challenge.

Most users were so fixated on the aspect ratio being incorrect or my speakers being too close to the monitor that they didn’t even notice that it was a CRT Shader they were looking at (at least at first glance)!

I did a second one of my work in progress shadow mask and a new NTSC preset but that one didn’t have the speakers in the Shadow Mask preset screenshots so it was much easier for people to tell it was a shader. Those were also deliberately dark becsuse I was initially trying to match a reference picture which was dark and while some couldn’t appreciate the beauty of the way the shader made the graphics look due to the darkness as well as whatever biases they might have had, the responses were generally favourable with a few people actually being fooled into not realizing it was a shader they were looking at at first glance!


How did you manage to deal with the ringing? Can you post the sharpness settings you used?


I had been avoiding the “sharpness definition” setting because it was producing really horrible artifacts in an earlier iteration. Looks like that’s no longer the case, I can see now that this is a pretty useful setting.


I really don’t know. I didn’t have any issues with ringing before. I actually deliberately cranked up Fast Sharpen in earlier presets because I felt the added ringing and other artifacts made things look more analog. I got these nice, thick clean lines by first disabling Fast Sharpen because it decreased the contrast of the edges, also adjusting my gamma, leaning more to the lower side. As for the sharpness, I just lowered the Horizontal Filter Range slightly and increased the Subtractive Sharpness slightly.

All of my settings are available in my latest preset pack.

These are actually my first presets using crt-guest-advance-NTSC (via HSM Mega Bezel Reflection Shader of course).

These require HSM Mega Bezel Reflection Shader version 1.7.0 currently, since v1.8.0, the NTSC Filtering settings have been broken. Your reaction to these presets is exactly the reason why I’ve been lamenting that they’ve been altered. My lamentations have not gone unnoticed though and fixes should arrive at some point. In the interim, I’ve been using a self patched version of the shader in order to have those working and still be able to work on the new Shadow Mask stuff at the same time while keeping up to date.

I haven’t touched Sharpness Definition yet but I did interfere with Adaptive Sharpness as well.

I also encountered some very wild artifacts depending on the combination of NTSC Horizontal Filter Range and NTSC Subtractive Sharpness used so I just adjusted things a little at a time to try to keep things “within range”.

Lots of trial and error involved. That’s how I get my results. I also do a lot of fine tuning from a distance in order to get rid of that last sometimes hidden bit of blur which makes everything unusable for me.

1 Like

I can’t actually extract the shader pack because I’m getting a “path too long” error.

Adaptive Sharpness has a tendency to break dithering, last time I checked. It’s been several months since I played with it, though.

Does adaptive sharpening still break dithering?

Personally, I’d like to see some different approaches to NTSC shading. It couldn’t hurt. It seems like with the current tools available to us, we can only make the image sharper at the expense of adding ringing, or by breaking dithering.

For example, if I increase sharpening using the custom fast sharpen, you get ringing to the left of the letters in the SMB logo. This isn’t present in the composite video photo of the PVM. Something similar happens with subtractive sharpness. In the real CRT photo, I see darker spots to the right of the white pixels, and bright spots to the right of some dark pixels.

Then again, Cyber seems to have found some kind of magic combination of settings that doesn’t show ringing while looking sharp. I’m wondering if the mask is doing a lot of work to disguise the ringing, or if the higher resolution is helping.

The other thing I’m concerned with is the scanline taper where a bright pixel transitions to a darker pixel. There’s actually very little of this in the real CRT photo. It’s not a smooth taper, it’s a square edged taper with a sharp transition from one pixel to the next. That’s been very difficult to replicate.

1 Like

Instead of trying to Extract, you can open the archive using Windows Explorer or 7zip and copy then paste. You could also try copying the archive to a root drive or folder then copying and pasting the contents there.

1 Like

I took a quick look and I’m fairly sure that it’s a combination of the mask and resolution that’s making the artifacts less noticeable. How does it look when you remove the mask?

I haven’t noticed anything unusual here comparing with the standard settings, but with genesis etc. games negative values are to be used. Sometimes it looks like the blend isn’t 100% smooth, but this is mostly not an adaptive sharpening issue.

Standard ntsc:

Adaptive sharpening at -5.0:

I’ll also make a remark that NES/SNES games are triggering 3-phase filtering with ntsc shaders, which don’t fully blend dithering. You must force 2-phase mode for the full effect.


@Cyber I can’t actually get the presets to load although I’ve followed the installation instructions. Would you mind posting a shot of the NTSC preset from the screenshot above without the mask so we can really see what’s going on?

1 Like