New CRT shader from Guest + CRT Guest Advanced updates

@guest.r, what deconvergence setup could be cool for arcade? And why is the default value for “substrative sharpness” not 1.0 since it is the recommended value?

1 Like

I prefer 1.0 to 2.0 wide red-blue deconvergence, but it might depend a bit on display resolution.

Substractive sharpness introduces a new type of filtering. Value of 1.0 is really recommended to fit it into some standards if someone decides for this approach. That’s why it’s pointed out, because you can get a look similar to cubic or lanczos…

Lower values still allow a wider pixel blend (4-6 pixels) and make lower horizontal sharpness values to work as intended.

Substractive sharpness at 1.0 or higher allows only 2 pixels to blend regardless of horizontal sharpness setting, which might really annoy less experienced users. As a footnote, it works best with horizontal sharpness from like 2.6 to 3.4.

3 Likes

Have you ever thought about writing a crt shader based on lanczos, bicubic or something? I think you kinda need a filter like this for composite video to look right, trying to do it with gaussian blur feels like an uphill battle (subtractive sharpness only gets you so far).

I’ve been playing with crt geom and ntsc adaptive recently, but I really miss the scanlines, mask, color and brightness control in GDV.

1 Like

Have you tried blargg’s sw filter at least for NES/SNES cores? Scaling seems to be fixed with newer RA releases.

Although adding lanczos over GDV filtering wouldn’t bring too much. It takes a very decisive approach for a special look, which might not allow many filtering tweaks.

2 Likes

My memory of composite signal fuzziness is far to gone but I did find if you changed the NTSC pass from linear to nearest it has an effect closer to Blarg’s. Blurring, rainbowing, and deconvergence are fun and pretty to look at. Composite blocky artifacting is tricky because it’s just plain ugly.

2 Likes

@guest.r

If I would want a higher horizontal sharpness setting for interlaced screens when using the hires shader with the PUAE core (it uses a horizontal pixel mode of 720 pixels, doubling the low res 360 pixel to 720 pixels, which needs more smoothing to look good, and uses real 720 pixel wide source for interlace, needing less smoothing), would it be sufficient to do the following in the main shader:

replace:

float h_sharp1 = pow(h_sharp,1.4);

by

float h_sharp1 = (interb) ? pow((h_sharp*2), 1.4):pow(h_sharp,1.4);

Doubling h_sharp in interlace mode. It seems to work, just verifying with you if this is the correct way of raising h_sharp when interlace is active?

But then when trying to add it as a separate parameter, I can’t get it to work.

If I add a separate parameter like “h_sharp_int”, like this:

add it to the float defines at the beginning

layout(push_constant) uniform Push
{
	float h_sharp_int;
}

then add a separate parameter:

#pragma parameter h_sharp_int "          Horizontal sharpness (Interlace) " 5.20 0.20 15.0 0.10
#define h_sharp      params.h_sharp_int     // pixel sharpness

and then replace:

float h_sharp1 = pow(h_sharp,1.4);

by

float h_sharp1 = (interb) ? pow((h_sharp_int), 1.4):pow(h_sharp,1.4);

it does not work, shader fails :frowning: I have actually little clue what I’m doing, so would appreciate if you can tell me how I can get it to work as a separate parameter?

1 Like

Best define h_sharp_int under the global construct, push can cover only a limited number of registers.

Then you can define it like this:

#pragma parameter h_sharp_int "          Horizontal sharpness (Interlace) " 5.20 0.20 15.0 0.10
#define h_sharp_int   global.h_sharp_int     // pixel sharpness

It can be continued:

float h_sharp1 = (interb) ? (h_sharp_int) : pow(h_sharp,1.4);

Pow isn’t necessary here, because a more blurry appearance is welcomed.

If you have any troubles beyond this point, you can let me know.

1 Like

That works fine, thanks!

1 Like

Finally some great news regarding the vulkan driver. I noticed the swanstation core going buggy after RA and core updates, which is quite unusual. I suspected the old config file playing odd and replaced it with a fresh one and re-configured RA, minus the controller, which was auto configured due newer RA version (x-box series). Everything seem to work very nice from this point. :smiley:

I guess it’s not necessarily a good thing to keep the old config file for too long.

Edit: vulkan driver still seems to dislike bilinear filtering. :thinking:

3 Likes

With FBNeo the NTSC preset can be used with good results. I like to use something like this for vertical games:

NTSC passes add to nice coloring, also make the image a bit messy, which can be nice.

2 Likes

Is there a way to add the sega luma fix from grade into your shader? I hate having all the extra settings

1 Like

Is there a way to adjust the scanlines in gdva to make the minimum thickness 1px wide? As far as I can tell, the minimum thickness is 2px no matter what I do…?

here’s an example using crt-aperture:

2 Likes

Crt aperture uses a different approach to generate scanlines and there is also a feature that handles even scaling factors for possible thinner scanlines (i think the original motivation is 4x vertical scaling).

The GDV approach is although fine for beam dynamics and non-integer scaling. Anyway if you tried a situation with even scaling, then 1px scanlines are nearly impossible.

1px scanlines with 5x vertical scaling were easily achievable though:

1x slotmask is added to ‘guess’ the scanline width more easily.

5 Likes

Mind posting those settings? I’m still struggling to get the beam that small without breaking the image (even at 5x) :confused:

2 Likes

The settings are very basic (scanline type 2.0 etc.), but i guess less suitable for gaming. It definitely helps though to increase the “Scanline Beam Shape” parameters.

Here is a quick setup:

shaders = "12"
shader0 = "shaders_slang/crt-guest-advanced/shaders/guest/advanced/stock.slang"
filter_linear0 = "false"
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-guest-advanced/shaders/guest/advanced/stock.slang"
filter_linear1 = "false"
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-guest-advanced/shaders/guest/advanced/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-guest-advanced/shaders/guest/advanced/pre-shaders-afterglow.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-guest-advanced/shaders/guest/advanced/avg-lum.slang"
filter_linear4 = "true"
wrap_mode4 = "clamp_to_border"
mipmap_input4 = "true"
alias4 = "AvgLumPass"
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-guest-advanced/shaders/guest/advanced/linearize.slang"
filter_linear5 = "true"
wrap_mode5 = "clamp_to_border"
mipmap_input5 = "false"
alias5 = "LinearizePass"
float_framebuffer5 = "true"
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/shaders/guest/advanced/gaussian_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-guest-advanced/shaders/guest/advanced/gaussian_vertical.slang"
filter_linear7 = "true"
wrap_mode7 = "clamp_to_border"
mipmap_input7 = "false"
alias7 = "GlowPass"
float_framebuffer7 = "true"
srgb_framebuffer7 = "false"
scale_type_x7 = "absolute"
scale_x7 = "800"
scale_type_y7 = "absolute"
scale_y7 = "600"
shader8 = "shaders_slang/crt-guest-advanced/shaders/guest/advanced/bloom_horizontal.slang"
filter_linear8 = "true"
wrap_mode8 = "clamp_to_border"
mipmap_input8 = "false"
alias8 = ""
float_framebuffer8 = "true"
srgb_framebuffer8 = "false"
scale_type_x8 = "absolute"
scale_x8 = "800"
scale_type_y8 = "absolute"
scale_y8 = "600"
shader9 = "shaders_slang/crt-guest-advanced/shaders/guest/advanced/bloom_vertical.slang"
filter_linear9 = "true"
wrap_mode9 = "clamp_to_border"
mipmap_input9 = "false"
alias9 = "BloomPass"
float_framebuffer9 = "true"
srgb_framebuffer9 = "false"
scale_type_x9 = "source"
scale_x9 = "1.000000"
scale_type_y9 = "source"
scale_y9 = "1.000000"
shader10 = "shaders_slang/crt-guest-advanced/shaders/guest/advanced/crt-guest-advanced.slang"
filter_linear10 = "true"
wrap_mode10 = "clamp_to_border"
mipmap_input10 = "false"
alias10 = ""
float_framebuffer10 = "false"
srgb_framebuffer10 = "false"
scale_type_x10 = "viewport"
scale_x10 = "1.000000"
scale_type_y10 = "viewport"
scale_y10 = "1.000000"
shader11 = "shaders_slang/crt-guest-advanced/shaders/guest/advanced/deconvergence.slang"
filter_linear11 = "true"
wrap_mode11 = "clamp_to_border"
mipmap_input11 = "false"
alias11 = ""
float_framebuffer11 = "false"
srgb_framebuffer11 = "false"
scale_type_x11 = "viewport"
scale_x11 = "1.000000"
scale_type_y11 = "viewport"
scale_y11 = "1.000000"
gamma_c = "1.599999"
gsl = "2.000000"
scanline1 = "12.000000"
scanline2 = "14.000000"
beam_min = "3.249998"
beam_max = "0.700000"
textures = "SamplerLUT1;SamplerLUT2;SamplerLUT3;SamplerLUT4"
SamplerLUT1 = "shaders_slang/crt-guest-advanced/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/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/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/shaders/guest/advanced/lut/ntsc-lut.png"
SamplerLUT4_linear = "true"
SamplerLUT4_wrap_mode = "clamp_to_border"
SamplerLUT4_mipmap = "false"
5 Likes

On the right track now, thanks :slight_smile:

on the subject of ntsc emulation… I think you really need a sharpening filter for this to look authentic. Black lines become bolder via composite (see this photo), and I think only Blargg’s filter and the standalone ntsc shaders are capturing that aspect right now. Besides being more accurate, I think it’s also easier to look at. Is there any way to do this in guest-ntsc?

2 Likes

@guest.r, could you incorporate some Grade and Glass settings into your shaders?

Grade:

Phosphor (NTSC-U, NTSC-J, PAL)
Sega Luma Fix

Glass:

Screen Flicker
Screen Shake
Reflection Toggle
Refl. Deband Grain
Refl. Brightness
Refl. Fresnel
Refl. Blur
Zoom

:pleading_face:

Lacking on them grade requests imho

1 Like

Cmon guys :relaxed:, i’m endorsing the usage of grade and glass shaders. I might add some brightness options, but duplicating or reproducing too much stuff already available is a pesky move.

A sharpening filter is already available as substractive sharpness, but i might add ordinary sharpness without a special filtering purpose and see how it goes.

At normal aspect ratios and 1080p-1440p horizontal black insertions would look quite crappy, maybe conditionally acceptable at 1440p. Masks and mask effects in general have it’s limitations rooting in display technology and are also affected by scanline/interlaced modes. I might add a mask which inhabits a black spacing, but it’s worth to think it trough first.

6 Likes

I totally agree with this, Guest’s shader is fantastic and it is focused what it does amazingly well which is the crt scanline dynamics and mask and phosphor behaviour.

IMHO If you want more features which are outside of the focus the specific shader the best way is to add different shaders together to get the result you desire, this way each can do what it is focused on well.

Otherwise you end up with one shader which tries to do everything and is hard to maintain, and there will always some additional feature to add if the shader’s goals aren’t focused.

You may end up with more parameters than you might like, but technically it’s much more maintainable.

So for example for me:

  • Guest-DrVenom is an amazing CRT shader so I use it in my chain.

  • Grade does color correction really well, so I add that to my chains to do color correction.

  • Mdapt does De-Dithering really well so I add that to my chains

And on and on…

Creating these combinations should get easier in the future, I’m hoping to add a retroarch feature to add the passes from a preset to the beginning of the chain you have loaded so this will be easier in the UI.

9 Likes