Please show off what crt shaders can do!

The same here. I took off the masks when I just played Super Metroid and SMW to the end. The masks are good in monitor but in big screens they turn everything very dull.

3 Likes

Thanks! Agreed about the contrast/vibrancy. I am also configuring these settings on a TN panel so that doesn’t help. I was more focused on trying to get the mask and scanlines just right; I could try experimenting and see if I can get better contrast and colors out of it.

Though I am so used to using crappy LCD panels that it doesn’t bother me too much. When I got my HD CRT I was blown away at how rich and vivid the colors were, as well as how great the contrast was.

1 Like

I’ve been messing around with Venom mask 1 and have results I like for a 1080p lcd monitor. It’s interesting that my previous laptop struggled with clipping in the reds and the new one in the blues. I’m not sure if it’s Venom2 or the laptop.

shaders = "8"
shader0 = "shaders_slang/sharpen/shaders/fast-sharpen.slang"
filter_linear0 = "true"
wrap_mode0 = "clamp_to_border"
mipmap_input0 = "false"
alias0 = "StockPass"
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/guest/crt-gdv-new/afterglow0.slang"
filter_linear1 = "true"
wrap_mode1 = "clamp_to_border"
mipmap_input1 = "false"
alias1 = "AfterglowPass"
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/crt-gdv-new/pre-shaders-afterglow.slang"
filter_linear2 = "true"
wrap_mode2 = "clamp_to_border"
mipmap_input2 = "false"
alias2 = "PrePass"
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/crt-gdv-new/avg-lum.slang"
filter_linear3 = "true"
wrap_mode3 = "clamp_to_border"
mipmap_input3 = "true"
alias3 = "AvgLumPass"
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/crt-gdv-new/linearize.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/crt-gdv-new/gaussian_horizontal.slang"
filter_linear5 = "true"
wrap_mode5 = "clamp_to_border"
mipmap_input5 = "false"
alias5 = ""
float_framebuffer5 = "false"
srgb_framebuffer5 = "false"
shader6 = "shaders_slang/crt/shaders/guest/crt-gdv-new/gaussian_vertical.slang"
filter_linear6 = "true"
wrap_mode6 = "clamp_to_border"
mipmap_input6 = "false"
alias6 = "GlowPass"
float_framebuffer6 = "false"
srgb_framebuffer6 = "false"
scale_type_x6 = "viewport"
scale_x6 = "0.500000"
scale_type_y6 = "viewport"
scale_y6 = "0.500000"
shader7 = "shaders_slang/crt/shaders/guest/crt-gdv-new/crt-guest-dr-venom2.slang"
filter_linear7 = "true"
wrap_mode7 = "clamp_to_border"
mipmap_input7 = "false"
alias7 = ""
float_framebuffer7 = "false"
srgb_framebuffer7 = "false"
scale_type_x7 = "viewport"
scale_x7 = "1.000000"
scale_type_y7 = "viewport"
scale_y7 = "1.000000"
parameters = "SHARPEN;CONTR;DETAILS;bogus_afterglow;PR;PG;PB;AS;sat;bogus_color;TNTC;CP;CS;WP;wp_saturation;lsmooth;GAMMA_INPUT;bogus_interlacing;inter;interm;bogus_glow;SIZEH;SIGMA_H;SIZEV;SIGMA_V;bogus_brightness;glow;bloom;gamma_c;brightboost;brightboost1;bogus_scanline;gsl;scanline1;scanline2;beam_min;beam_max;beam_size;vertmask;scans;spike;bogus_filtering;h_sharp;s_sharp;smart_ei;ei_limit;sth;bogus_screen;TATE;IOS;OS;BLOOM;csize;bsize;warpX;warpY;bogus_masks;shadowMask;maskstr;masksize;maskDark;maskLight;mcut;mask_gamma;slotmask;slotwidth;double_slot;slotms;mclip;gamma_out"
SHARPEN = "0.250000"
CONTR = "0.250000"
DETAILS = "1.000000"
bogus_afterglow = "0.000000"
PR = "0.140000"
PG = "0.140000"
PB = "0.140000"
AS = "0.070000"
sat = "0.100000"
bogus_color = "0.000000"
TNTC = "0.000000"
CP = "5.000000"
CS = "1.000000"
WP = "-25.000000"
wp_saturation = "1.500000"
lsmooth = "0.750000"
GAMMA_INPUT = "2.400000"
bogus_interlacing = "0.000000"
inter = "325.000000"
interm = "0.000000"
bogus_glow = "0.000000"
SIZEH = "25.000000"
SIGMA_H = "3.999997"
SIZEV = "1.000000"
SIGMA_V = "0.500000"
bogus_brightness = "0.000000"
glow = "0.010000"
bloom = "0.000000"
gamma_c = "0.920000"
brightboost = "1.999999"
brightboost1 = "2.099999"
bogus_scanline = "1.000000"
gsl = "0.000000"
scanline1 = "0.000000"
scanline2 = "25.000000"
beam_min = "2.499999"
beam_max = "0.650000"
beam_size = "0.900000"
vertmask = "0.500000"
scans = "1.000000"
spike = "1.000000"
bogus_filtering = "0.000000"
h_sharp = "5.200000"
s_sharp = "0.000000"
smart_ei = "0.000000"
ei_limit = "12.000000"
sth = "0.000000"
bogus_screen = "0.000000"
TATE = "0.000000"
IOS = "0.000000"
OS = "1.000000"
BLOOM = "0.000000"
csize = "0.000000"
bsize = "600.000000"
warpX = "0.000000"
warpY = "0.000000"
bogus_masks = "0.000000"
shadowMask = "1.000000"
maskstr = "0.500000"
masksize = "1.000000"
maskDark = "0.500000"
maskLight = "1.000000"
mcut = "1.500000"
mask_gamma = "2.400000"
slotmask = "0.000000"
slotwidth = "2.000000"
double_slot = "1.000000"
slotms = "1.000000"
mclip = "0.500000"
gamma_out = "2.400000"
textures = "SamplerLUT1;SamplerLUT2;SamplerLUT3"
SamplerLUT1 = "shaders_slang/crt/shaders/guest/lut/sony_trinitron1.png"
SamplerLUT1_linear = "true"
SamplerLUT1_wrap_mode = "clamp_to_border"
SamplerLUT1_mipmap = "false"
SamplerLUT2 = "shaders_slang/crt/shaders/guest/lut/sony_trinitron2.png"
SamplerLUT2_linear = "true"
SamplerLUT2_wrap_mode = "clamp_to_border"
SamplerLUT2_mipmap = "false"
SamplerLUT3 = "shaders_slang/crt/shaders/guest/lut/other1.png"
SamplerLUT3_linear = "true"
SamplerLUT3_wrap_mode = "clamp_to_border"
SamplerLUT3_mipmap = "false"
5 Likes

I can try to bring some life to the colors in the game by boosting the Saturation in grade by 0.15, that way the colors “pop” a little bit and aren’t so dull looking. There’s not much that I can do about the contrast but perhaps a bit of saturation like this can bring some life to the colors in these games.

1 Like

Some more VHS screens :

With SNES games :

5 Likes

I want to share the shaders I’m running with. I’ve classified the main ones by kinda, sorta, connection types. I have and Xbox wireless elite 2 controller I map the paddles to switch between shaders and I enjoy that almost much as playing the games themselves.

None (For Comparison)

RGB-US This is the Hyllian-Sinc. It’s fast and looks great.

RGB-JP Venom 2 pushed cool. I like the look of Japanese games cooler and American made games warmer.

VGA High contrast, sharp, and a severe pain to get right. This is a tweaked Mame that I like to keep around because it has the best version of scanline scaling for higher res content when desired.

S-Video Venom 2 NTSC, this feels “right” to me. It’s the closest I can get to the TV’s I had as a kid.

Composite New-Pixie with a few tweaks. It has scrolling scanlines, ntsc artifacting, rainbowing…everything to look like an old hand-me-down TV or a dying arcade monitor.

RF-B&W It’s more fun to look at video content than games but at one point I was young at an old relatives house and all they had was a black and white tv.

FX A stupid but fun shader with Venom mixed reshade passes.

LCD For my GBA and PSP game or when I want even more LCD power while playing on an LCD.

7 Likes

This, thisthisthis, thisthis, this-THIS.

I adore -absolutely adore- the concept of having connection-based presets. It’s always been how I try to set my own presets up (brilliant idea using the paddles to swap these BTW). I just can’t lay enough praise on the concept.

I love the idea of pushing JP games into cooler ranges as well, I’d never thought of that but it’s an interesting concept given what I’ve read about the differences in screens between regions.

This is my config for SNES.

It was tested on 1080p Plasma and 4k LCD. After trying many times getting a comfy look, where my eyes didn’t distract too much, I’ve got this config on Retroarch. It is set to use mask1 with intensity=0.5, though I prefer no mask at all on big screens.

I noticed SNES games have some annoying noise caused by high frequency colors on backgrounds (low contrast). This is a bit distracting, mainly when you’re in fact playing a game for some hours. Recently I played to the end some games (Super Metroid, SMW, Super Mario Bros 3, etc) and had to find some way to reduce noise on backgrounds. That’s how I got this config. Believe me, it’s very good in motion. This preset combines sgenpt-mix blend level 2 (just checkerboard) to get rid of common cboard dithering in low contrast backgrounds and a new version of smartblur (included in zip), with a slide to control blur level.

I took some screenshots using only crt-hyllian vanilla (the first shots) and other using my snes preset (the second ones):

SNES crt preset (include new smartblur shader)

6 Likes

Lovely work Hyllian, I’d like to ask, is your hyllian-sinc shader finalized and if so, could you post a glsl version of it? Also are you thinking whenever you have a final version of your shaders maybe combining them, like hyllian-sinc with the other ones like glow or sgenpt? Thanks a lot and keep it up!

1 Like

Yeah. I thought there wasn’t demand for that shader. So, the sinc version is basically finished. I think I’ll make the variants (glow, glsl and others) and then post here when finished.

3 Likes

Here’s the slang final versions with glow and smartblur: crt-hyllian-sinc (slang, vanilla and variants) - v2

I’ve added two beam profiles to this sinc shader. You should try BP=2.0 and see if you like. Default is 1.0.

I’ll convert to glsl later.

EDIT: I’ve toned down color boost. The original sinc color boost was too strong.

Using BP=2.0 (if you like retro look and wanna see the pixels!)

7 Likes

Yeah IMO gaussian is much better for vertical detail, but did you make some changes to the sinc version that I missed (I’ve been away)?

Last time I tested it I got some undesirable results.

You should test again. Maybe it’s fixed.

1 Like

Hey, @hunterk, Do you have that subpixel mask include for glsl shaders?

I’m looking for it to properly port crt-hyllian with latest evolutions. Besides, to use mask with glow I need to put it as a last pass, otherwise some weird scaling artifacts appear.

There’s an old port of it here:

but it’s missing a few of the later masks (and they might be in a different order). Let me know if you need me to work on it.

The main issue with GLSL is that it doesn’t support 2D arrays until relatively late in the game, so for compatibility’s sake, I’ve switched to xBR-style nested boolean comparisons.

EDIT: I went ahead and updated it to match the version in the slang repo (full shader included for context; notice that it requires #version 120 or higher):

#version 120

#pragma parameter mask_type "mask_type" 1.0 0.0 20.0 1.0

#if defined(VERTEX)

#if __VERSION__ >= 130
#define COMPAT_VARYING out
#define COMPAT_ATTRIBUTE in
#define COMPAT_TEXTURE texture
#else
#define COMPAT_VARYING varying 
#define COMPAT_ATTRIBUTE attribute 
#define COMPAT_TEXTURE texture2D
#endif

#ifdef GL_ES
#define COMPAT_PRECISION mediump
#else
#define COMPAT_PRECISION
#endif

COMPAT_ATTRIBUTE vec4 VertexCoord;
COMPAT_ATTRIBUTE vec4 TexCoord;
COMPAT_VARYING vec4 TEX0;
// out variables go here as COMPAT_VARYING whatever

uniform mat4 MVPMatrix;
uniform COMPAT_PRECISION int FrameDirection;
uniform COMPAT_PRECISION int FrameCount;
uniform COMPAT_PRECISION vec2 OutputSize;
uniform COMPAT_PRECISION vec2 TextureSize;
uniform COMPAT_PRECISION vec2 InputSize;

#define vTexCoord TEX0.xy
#define SourceSize vec4(TextureSize, 1.0 / TextureSize)
#define OutSize vec4(OutputSize, 1.0 / OutputSize)

void main()
{
   gl_Position = MVPMatrix * VertexCoord;
   TEX0.xy = TexCoord.xy;
}

#elif defined(FRAGMENT)

#ifdef GL_ES
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
#define COMPAT_PRECISION mediump
#else
#define COMPAT_PRECISION
#endif

#if __VERSION__ >= 130
#define COMPAT_VARYING in
#define COMPAT_TEXTURE texture
out COMPAT_PRECISION vec4 FragColor;
#else
#define COMPAT_VARYING varying
#define FragColor gl_FragColor
#define COMPAT_TEXTURE texture2D
#endif

uniform COMPAT_PRECISION int FrameDirection;
uniform COMPAT_PRECISION int FrameCount;
uniform COMPAT_PRECISION vec2 OutputSize;
uniform COMPAT_PRECISION vec2 TextureSize;
uniform COMPAT_PRECISION vec2 InputSize;
uniform sampler2D Texture;
COMPAT_VARYING vec4 TEX0;

// compatibility #defines
#define Source Texture
#define vTexCoord TEX0.xy

#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
#define OutSize vec4(OutputSize, 1.0 / OutputSize)

#ifdef PARAMETER_UNIFORM
uniform COMPAT_PRECISION float mask_type;
#else
#define mask_type 0.0
#endif

/*
A collection of CRT mask effects that work with LCD subpixel structures for
small details

author: hunterk
license: public domain

How to use it:

Multiply your image by the vec3 output:
FragColor.rgb *= mask_weights(gl_FragCoord.xy, 1.0, 1);

The function needs to be tiled across the screen using the physical pixels, e.g.
gl_FragCoord (the "vec2 coord" input). In the case of slang shaders, we use
(vTexCoord.st * OutputSize.xy).

The "mask_intensity" (float value between 0.0 and 1.0) is how strong the mask
effect should be. Full-strength red, green and blue subpixels on a white pixel
are the ideal, and are achieved with an intensity of 1.0, though this darkens
the image significantly and may not always be desirable.

The "phosphor_layout" (int value between 0 and 19) determines which phophor
layout to apply. 0 is no mask/passthru.

Many of these mask arrays are adapted from cgwg's crt-geom-deluxe LUTs, and
those have their filenames included for easy identification
*/

vec3 mask_weights(vec2 coord, float mask_intensity, int phosphor_layout){
   vec3 weights = vec3(1.,1.,1.);
   float on = 1.;
   float off = 1.-mask_intensity;
   vec3 red     = vec3(on,  off, off);
   vec3 green   = vec3(off, on,  off);
   vec3 blue    = vec3(off, off, on );
   vec3 magenta = vec3(on,  off, on );
   vec3 yellow  = vec3(on,  on,  off);
   vec3 cyan    = vec3(off, on,  on );
   vec3 black   = vec3(off, off, off);
   vec3 white   = vec3(on,  on,  on );
   int w, z = 0;
   
   // This pattern is used by a few layouts, so we'll define it here
   vec3 aperture_weights = mix(magenta, green, floor(mod(coord.x, 2.0)));
   
   if(phosphor_layout == 0) return weights;

   else if(phosphor_layout == 1){
      // classic aperture for RGB panels; good for 1080p, too small for 4K+
      // aka aperture_1_2_bgr
      weights  = aperture_weights;
      return weights;
   }

   else if(phosphor_layout == 2){
      // 2x2 shadow mask for RGB panels; good for 1080p, too small for 4K+
      // aka delta_1_2x1_bgr
      vec3 inverse_aperture = mix(green, magenta, floor(mod(coord.x, 2.0)));
      weights               = mix(aperture_weights, inverse_aperture, floor(mod(coord.y, 2.0)));
      return weights;
   }

   else if(phosphor_layout == 3){
      // slot mask for RGB panels; looks okay at 1080p, looks better at 4K
      // {magenta, green, black,   black},
      // {magenta, green, magenta, green},
      // {black,   black, magenta, green}

      // GLSL can't do 2D arrays until version 430, so do this stupid thing instead for compatibility's sake:
      // First lay out the horizontal pixels in arrays
      vec3 slotmask_x1[4] = vec3[](magenta, green, black,   black);
      vec3 slotmask_x2[4] = vec3[](magenta, green, magenta, green);
      vec3 slotmask_x3[4] = vec3[](black,   black, magenta, green);
      
      // find the vertical index
      w = int(floor(mod(coord.y, 3.0)));
      
      // find the horizontal index
      z = int(floor(mod(coord.x, 4.0)));

      // do a big, dumb comparison in place of a 2D array
      weights = (w == 1) ? slotmask_x1[z] : (w == 2) ? slotmask_x2[z] :  slotmask_x3[z];
    }

   if(phosphor_layout == 4){
      // classic aperture for RBG panels; good for 1080p, too small for 4K+
      weights  = mix(yellow, blue, floor(mod(coord.x, 2.0)));
      return weights;
   }

   else if(phosphor_layout == 5){
      // 2x2 shadow mask for RBG panels; good for 1080p, too small for 4K+
      vec3 inverse_aperture = mix(blue, yellow, floor(mod(coord.x, 2.0)));
      weights               = mix(mix(yellow, blue, floor(mod(coord.x, 2.0))), inverse_aperture, floor(mod(coord.y, 2.0)));
      return weights;
   }
   
   else if(phosphor_layout == 6){
      // aperture_1_4_rgb; good for simulating lower 
      vec3 ap4[4] = vec3[](red, green, blue, black);
      
      z = int(floor(mod(coord.x, 4.0)));
      
      weights = ap4[z];
      return weights;
   }
   
   else if(phosphor_layout == 7){
      // aperture_2_5_bgr
      vec3 ap3[5] = vec3[](red, magenta, blue, green, green);
      
      z = int(floor(mod(coord.x, 5.0)));
      
      weights = ap3[z];
      return weights;
   }
   
   else if(phosphor_layout == 8){
      // aperture_3_6_rgb
      
      vec3 big_ap[7] = vec3[](red, red, yellow, green, cyan, blue, blue);
      
      w = int(floor(mod(coord.x, 7.)));
      
      weights = big_ap[w];
      return weights;
   }
   
   else if(phosphor_layout == 9){
      // reduced TVL aperture for RGB panels
      // aperture_2_4_rgb
      
      vec3 big_ap_rgb[4] = vec3[](red, yellow, cyan, blue);
      
      w = int(floor(mod(coord.x, 4.)));
      
      weights = big_ap_rgb[w];
      return weights;
   }
   
   else if(phosphor_layout == 10){
      // reduced TVL aperture for RBG panels
      
      vec3 big_ap_rbg[4] = vec3[](red, magenta, cyan, green);
      
      w = int(floor(mod(coord.x, 4.)));
      
      weights = big_ap_rbg[w];
      return weights;
   }
   
   else if(phosphor_layout == 11){
      // delta_1_4x1_rgb; dunno why this is called 4x1 when it's obviously 4x2 /shrug
      vec3 delta_1_1[4] = vec3[](red, green, blue, black);
      vec3 delta_1_2[4] = vec3[](blue, black, red, green);
      
      w = int(floor(mod(coord.y, 2.0)));
      z = int(floor(mod(coord.x, 4.0)));
      
      weights = (w == 1) ? delta_1_1[z] : delta_1_2[z];
      return weights;
   }
   
   else if(phosphor_layout == 12){
      // delta_2_4x1_rgb
      vec3 delta_2_1[4] = vec3[](red, yellow, cyan, blue);
      vec3 delta_2_2[4] = vec3[](cyan, blue, red, yellow);
      
      z = int(floor(mod(coord.x, 4.0)));
      
      weights = (w == 1) ? delta_2_1[z] : delta_2_2[z];
      return weights;
   }
   
   else if(phosphor_layout == 13){
      // delta_2_4x2_rgb
      vec3 delta_1[4] = vec3[](red, yellow, cyan, blue);
      vec3 delta_2[4] = vec3[](red, yellow, cyan, blue);
      vec3 delta_3[4] = vec3[](cyan, blue, red, yellow);
      vec3 delta_4[4] = vec3[](cyan, blue, red, yellow);
     
      w = int(floor(mod(coord.y, 4.0)));
      z = int(floor(mod(coord.x, 4.0)));
      
      weights = (w == 1) ? delta_1[z] : (w == 2) ? delta_2[z] : (w == 3) ? delta_3[z] : delta_4[z];
      return weights;
   }
   
   else if(phosphor_layout == 14){
      // slot mask for RGB panels; too low-pitch for 1080p, looks okay at 4K, but wants 8K+
      // {magenta, green, black, black,   black, black},
      // {magenta, green, black, magenta, green, black},
      // {black,   black, black, magenta, green, black}
      vec3 slot2_1[6] = vec3[](magenta, green, black, black,   black, black);
      vec3 slot2_2[6] = vec3[](magenta, green, black, magenta, green, black);
      vec3 slot2_3[6] = vec3[](black,   black, black, magenta, green, black);
   
      w = int(floor(mod(coord.y, 3.0)));
      z = int(floor(mod(coord.x, 6.0)));
      
      weights = (w == 1) ? slot2_1[z] : (w == 2) ? slot2_2[z] : slot2_3[z];
      return weights;
   }

   else if(phosphor_layout == 15){
      // slot_2_4x4_rgb
      // {red,   yellow, cyan,  blue,  red,   yellow, cyan,  blue },
      // {red,   yellow, cyan,  blue,  black, black,  black, black},
      // {red,   yellow, cyan,  blue,  red,   yellow, cyan,  blue },
      // {black, black,  black, black, red,   yellow, cyan,  blue }
      vec3 slotmask_RBG_x1[8] = vec3[](red,   yellow, cyan,  blue,  red,   yellow, cyan,  blue );
      vec3 slotmask_RBG_x2[8] = vec3[](red,   yellow, cyan,  blue,  black, black,  black, black);
      vec3 slotmask_RBG_x3[8] = vec3[](red,   yellow, cyan,  blue,  red,   yellow, cyan,  blue );
      vec3 slotmask_RBG_x4[8] = vec3[](black, black,  black, black, red,   yellow, cyan,  blue );
      
      // find the vertical index
      w = int(floor(mod(coord.y, 4.0)));
      
      // find the horizontal index
      z = int(floor(mod(coord.x, 8.0)));

      weights = (w == 1) ? slotmask_RBG_x1[z] : (w == 2) ? slotmask_RBG_x2[z] : (w == 3) ? slotmask_RBG_x3[z] : slotmask_RBG_x4[z];
      return weights;
    }
   
   else if(phosphor_layout == 16){
      // slot mask for RBG panels; too low-pitch for 1080p, looks okay at 4K, but wants 8K+
      // {yellow, blue,  black,  black},
      // {yellow, blue,  yellow, blue},
      // {black,  black, yellow, blue}
      vec3 slot2_1[4] = vec3[](yellow, blue,  black,  black);
      vec3 slot2_2[4] = vec3[](yellow, blue,  yellow, blue);
      vec3 slot2_3[4] = vec3[](black,  black, yellow, blue);
   
      w = int(floor(mod(coord.y, 3.0)));
      z = int(floor(mod(coord.x, 4.0)));
      
      weights = (w == 1) ? slot2_1[z] : (w == 2) ? slot2_2[z] : slot2_3[z];
      return weights;
   }
   
   else if(phosphor_layout == 17){
      // slot_2_5x4_bgr
      // {red,   magenta, blue,  green, green, red,   magenta, blue,  green, green},
      // {black, blue,    blue,  green, green, red,   red,     black, black, black},
      // {red,   magenta, blue,  green, green, red,   magenta, blue,  green, green},
      // {red,   red,     black, black, black, black, blue,    blue,  green, green}
      vec3 slot_1[10] = vec3[](red,   magenta, blue,  green, green, red,   magenta, blue,  green, green);
      vec3 slot_2[10] = vec3[](black, blue,    blue,  green, green, red,   red,     black, black, black);
      vec3 slot_3[10] = vec3[](red,   magenta, blue,  green, green, red,   magenta, blue,  green, green);
      vec3 slot_4[10] = vec3[](red,   red,     black, black, black, black, blue,    blue,  green, green);
      
      w = int(floor(mod(coord.y, 4.0)));
      z = int(floor(mod(coord.x, 10.0)));
      
      weights = (w == 1) ? slot_1[z] : (w == 2) ? slot_2[z] : (w == 3) ? slot_3[z] : slot_4[z];
      return weights;
   }
   
   else if(phosphor_layout == 18){
      // same as above but for RBG panels
      // {red,   yellow, green, blue,  blue,  red,   yellow, green, blue,  blue },
      // {black, green,  green, blue,  blue,  red,   red,    black, black, black},
      // {red,   yellow, green, blue,  blue,  red,   yellow, green, blue,  blue },
      // {red,   red,    black, black, black, black, green,  green, blue,  blue }
      vec3 slot_1[10] = vec3[](red,   yellow, green, blue,  blue,  red,   yellow, green, blue,  blue );
      vec3 slot_2[10] = vec3[](black, green,  green, blue,  blue,  red,   red,    black, black, black);
      vec3 slot_3[10] = vec3[](red,   yellow, green, blue,  blue,  red,   yellow, green, blue,  blue );
      vec3 slot_4[10] = vec3[](red,   red,    black, black, black, black, green,  green, blue,  blue );
      
      w = int(floor(mod(coord.y, 4.0)));
      z = int(floor(mod(coord.x, 10.0)));
      
      weights = (w == 1) ? slot_1[z] : (w == 2) ? slot_2[z] : (w == 3) ? slot_3[z] : slot_4[z];
      return weights;
   }
   
   else if(phosphor_layout == 19){
      // slot_3_7x6_rgb
      // {red,   red,   yellow, green, cyan,  blue,  blue,  red,   red,   yellow, green,  cyan,  blue,  blue},
      // {red,   red,   yellow, green, cyan,  blue,  blue,  red,   red,   yellow, green,  cyan,  blue,  blue},
      // {red,   red,   yellow, green, cyan,  blue,  blue,  black, black, black,  black,  black, black, black},
      // {red,   red,   yellow, green, cyan,  blue,  blue,  red,   red,   yellow, green,  cyan,  blue,  blue},
      // {red,   red,   yellow, green, cyan,  blue,  blue,  red,   red,   yellow, green,  cyan,  blue,  blue},
      // {black, black, black,  black, black, black, black, black, red,   red,    yellow, green, cyan,  blue}
      
      vec3 slot_1[14] = vec3[](red,   red,   yellow, green, cyan,  blue,  blue,  red,   red,   yellow, green,  cyan,  blue,  blue);
      vec3 slot_2[14] = vec3[](red,   red,   yellow, green, cyan,  blue,  blue,  red,   red,   yellow, green,  cyan,  blue,  blue);
      vec3 slot_3[14] = vec3[](red,   red,   yellow, green, cyan,  blue,  blue,  black, black, black,  black,  black, black, black);
      vec3 slot_4[14] = vec3[](red,   red,   yellow, green, cyan,  blue,  blue,  red,   red,   yellow, green,  cyan,  blue,  blue);
      vec3 slot_5[14] = vec3[](red,   red,   yellow, green, cyan,  blue,  blue,  red,   red,   yellow, green,  cyan,  blue,  blue);
      vec3 slot_6[14] = vec3[](black, black, black,  black, black, black, black, black, red,   red,    yellow, green, cyan,  blue);
      
      w = int(floor(mod(coord.y, 6.0)));
      z = int(floor(mod(coord.x, 14.0)));
      
      weights = (w == 1) ? slot_1[z] : (w == 2) ? slot_2[z] : (w == 3) ? slot_3[z] : (w == 4) ? slot_4[z] : (w == 5) ? slot_5[z] : slot_6[z];
      return weights;
   }
   
   else return weights;
}

void main()
{
    FragColor = COMPAT_TEXTURE(Source, vTexCoord);
    FragColor.rgb *= mask_weights(gl_FragCoord.xy, 1.0, int(mask_type));
} 
#endif
2 Likes

Thanks! I’ll use it asap!

BTW, I’ve updated crt-hyllian and variants in slang:

crt-hyllian and variants (slang) - 2021-01-02

crt-hyllian:

crt-hyllian-sinc-glow:

crt-hyllian-curvature-ntsc:

crt-hyllian-smartblur-sgenpt:

9 Likes

Unfortunately, using masks with glow in glsl generates some weird artifacts, instead the slang ones. So glow won’t use masks in glsl.

Here the glsl port of most shaders: crt-hyllian updated (glsl)

Unfortunately, the masks can’t work with glow without artifacts. In slang they can coexist.

2 Likes

Can you post a screenshot of the artifacts? AFAIK, there shouldn’t be anything wildly different between the two.

1 Like

crt-hyllian-glow (no mask):

crt-hyllian-glow (mask 4):

Look at vertical stripes. These artifacts happen with any mask.