Please show off what crt shaders can do!

Thanks,based on Crt-Royale and my own chroma_filter taps,chroma_phase,chroma_mod_freq,changed yiq_mat values to yuv444 and other settings. And I need to change other values. :man_mechanic:

@hunterk I’m gonna make a preset with your big mask function and neutral settings so they can make the preset they like. I will edit this message in a few minutes.

Edit: shaders\shaders_slang\include\subpixel_masks.h

/*
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 white   = vec3(on, on, on);
   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);
   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
      vec3 slotmask[3][4] = {
         {magenta, green, black,   black},
         {magenta, green, magenta, green},
         {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)));

      // use the indexes to find which color to apply to the current pixel
      weights = slotmask[w][z];
      return weights;
   }

   else 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 delta1[2][4] = {
         {red,  green, blue, black},
         {blue, black, red,  green}
      };
      
      w = int(floor(mod(coord.y, 2.0)));
      z = int(floor(mod(coord.x, 4.0)));
      
      weights = delta1[w][z];
      return weights;
   }
   
   else if(phosphor_layout == 12){
      // delta_2_4x1_rgb
      vec3 delta[2][4] = {
         {red, yellow, cyan, blue},
         {cyan, blue, red, yellow}
      };
      
      w = int(floor(mod(coord.y, 2.0)));
      z = int(floor(mod(coord.x, 4.0)));
      
      weights = delta[w][z];
      return weights;
   }
   
   else if(phosphor_layout == 13){
      // delta_2_4x2_rgb
      vec3 delta[4][4] = {
         {red,  yellow, cyan, blue},
         {red,  yellow, cyan, blue},
         {cyan, blue,   red,  yellow},
         {cyan, blue,   red,  yellow}
      };
      
      w = int(floor(mod(coord.y, 4.0)));
      z = int(floor(mod(coord.x, 4.0)));
      
      weights = delta[w][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+
      vec3 slotmask[3][6] = {
         {magenta, green, black, black,   black, black},
         {magenta, green, black, magenta, green, black},
         {black,   black, black, magenta, green, black}
      };
      
      w = int(floor(mod(coord.y, 3.0)));

      z = int(floor(mod(coord.x, 6.0)));

      weights = slotmask[w][z];
      return weights;
   }
   
   else if(phosphor_layout == 15){
      // slot_2_4x4_rgb
      vec3 slot2[4][8] = {
         {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 }
      };
   
      w = int(floor(mod(coord.y, 4.0)));
      z = int(floor(mod(coord.x, 8.0)));
      
      weights = slot2[w][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+
      vec3 slotmask[3][4] = {
         {yellow, blue,  black,  black},
         {yellow, blue,  yellow, blue},
         {black,  black, yellow, blue}
      };
      
      w = int(floor(mod(coord.y, 3.0)));

      z = int(floor(mod(coord.x, 4.0)));

      weights = slotmask[w][z];
      return weights;
   }
   
   else if(phosphor_layout == 17){
      // slot_2_5x4_bgr
      vec3 slot2[4][10] = {
         {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}
      };
   
      w = int(floor(mod(coord.y, 4.0)));
      z = int(floor(mod(coord.x, 10.0)));
      
      weights = slot2[w][z];
      return weights;
   }
   
   else if(phosphor_layout == 18){
      // same as above but for RBG panels
      vec3 slot2[4][10] = {
         {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 }
      };
   
      w = int(floor(mod(coord.y, 4.0)));
      z = int(floor(mod(coord.x, 10.0)));
      
      weights = slot2[w][z];
      return weights;
   }
   
   else if(phosphor_layout == 19){
      // slot_3_7x6_rgb
      vec3 slot[6][14] = {
         {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}
      };
      
      w = int(floor(mod(coord.y, 6.0)));
      z = int(floor(mod(coord.x, 14.0)));
      
      weights = slot[w][z];
      return weights;
   }

   else if(phosphor_layout == 20){
      // black and white aperture grille; good for 1080p, too small for 4K+
      weights  = mix(white, black, floor(mod(coord.x, 2.0)));
      return weights;
   }

   else if(phosphor_layout == 21){
      // black and white dot mask; good for 1080p, too small for 4K+
      vec3 wb = mix(black, white, floor(mod(coord.x, 2.0)));
      vec3 bw = mix(white, black, floor(mod(coord.x, 2.0)));
      weights = mix(wb, bw, floor(mod(coord.y, 2.0)));
      return weights;
   }
   
   else if(phosphor_layout == 22){
      // 3px-width black and white aperture
      
      vec3 big_bw[3] = vec3[](white, white, black);
      
      w = int(floor(mod(coord.x, 3.)));
      
      weights = big_bw[w];
      return weights;
   }
   
   else if(phosphor_layout == 23){
      // 4px-width black and white aperture
      
      vec3 big_bw[4] = vec3[](white, white, white, black);
      
      w = int(floor(mod(coord.x, 4.)));
      
      weights = big_bw[w];
      return weights;
   }

   else return weights;
}

shaders\shaders_slang\misc\subpixel_mask.slang

#version 450

#include "../include/subpixel_masks.h"

layout(push_constant) uniform Push
{
    float msk_str;
    float phosphor;
} params;

// For testing the different subpixels masks
// using the updated "include" file from hunterk:
// https://forums.libretro.com/t/please-show-off-what-crt-shaders-can-do/19193/1510

#pragma parameter msk_str "mask_intensity" 1.0 0.0 1.0 0.1
#pragma parameter phosphor "phosphor_layout" 0.0 0.0 23.0 1.0


layout(std140, set = 0, binding = 0) uniform UBO
{
    mat4 MVP;
    vec4 SourceSize;
    vec4 OriginalSize;
    vec4 OutputSize;
} 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 * 1.00001;
}

#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()
{
    vec3 col = texture(Source, vTexCoord.xy).rgb;

    vec2 xy = vTexCoord.xy * global.OutputSize.xy;
    vec3 mask = mask_weights(xy, params.msk_str, int(params.phosphor));

    FragColor = vec4(col*mask, 1.0);
}

Neutral Guest-Venom preset with hunterk masks.

shaders = "11"
shader0 = "shaders_slang/crt/shaders/guest/lut/lut.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/shaders/guest/color-profiles.slang"
filter_linear1 = "true"
wrap_mode1 = "clamp_to_border"
mipmap_input1 = "false"
alias1 = ""
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/d65-d50.slang"
filter_linear2 = "true"
wrap_mode2 = "clamp_to_border"
mipmap_input2 = "false"
alias2 = "WhitePointPass"
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/afterglow.slang"
filter_linear3 = "true"
wrap_mode3 = "clamp_to_border"
mipmap_input3 = "false"
alias3 = "AfterglowPass"
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/avg-lum.slang"
filter_linear4 = "true"
wrap_mode4 = "clamp_to_border"
mipmap_input4 = "true"
alias4 = "AvgLumPass"
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/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/shaders/guest/blur_horiz.slang"
filter_linear6 = "true"
wrap_mode6 = "clamp_to_border"
mipmap_input6 = "false"
alias6 = ""
float_framebuffer6 = "true"
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/blur_vert.slang"
filter_linear7 = "true"
wrap_mode7 = "clamp_to_border"
mipmap_input7 = "false"
alias7 = "GlowPass"
float_framebuffer7 = "true"
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/linearize_scanlines.slang"
filter_linear8 = "true"
wrap_mode8 = "clamp_to_border"
mipmap_input8 = "false"
alias8 = ""
float_framebuffer8 = "true"
srgb_framebuffer8 = "false"
scale_type_x8 = "source"
scale_x8 = "1.000000"
scale_type_y8 = "source"
scale_y8 = "1.000000"
shader9 = "shaders_slang/crt/shaders/guest/crt-guest-dr-venom.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"
shader10 = "shaders_slang/misc/subpixel_mask.slang"
wrap_mode10 = "clamp_to_border"
mipmap_input10 = "false"
alias10 = ""
float_framebuffer10 = "false"
srgb_framebuffer10 = "false"
parameters = "TNTC;CP;CS;WP;wp_saturation;SW;AR;PR;AG;PG;AB;PB;sat;lsmooth;GAMMA_INPUT;TAPSH;GLOW_FALLOFF_H;TAPSV;GLOW_FALLOFF_V;TATE;IOS;OS;BLOOM;brightboost;brightboost1;gsl;scanline1;scanline2;beam_min;beam_max;beam_size;h_sharp;s_sharp;csize;bsize;warpX;warpY;glow;shadowMask;masksize;vertmask;slotmask;slotwidth;double_slot;slotms;mcut;maskDark;maskLight;CGWG;gamma_out;spike;inter;interm;bloom;scans;msk_str;phosphor"
TNTC = "0.000000"
CP = "-1.000000"
CS = "0.000000"
WP = "0.000000"
wp_saturation = "1.000000"
SW = "1.000000"
AR = "0.070000"
PR = "0.050000"
AG = "0.070000"
PG = "0.050000"
AB = "0.070000"
PB = "0.050000"
sat = "0.100000"
lsmooth = "0.900000"
GAMMA_INPUT = "2.400000"
TAPSH = "4.000000"
GLOW_FALLOFF_H = "0.300000"
TAPSV = "4.000000"
GLOW_FALLOFF_V = "0.300000"
TATE = "0.000000"
IOS = "0.000000"
OS = "0.000000"
BLOOM = "0.000000"
brightboost = "1.000000"
brightboost1 = "1.000000"
gsl = "1.000000"
scanline1 = "1.000000"
scanline2 = "1.000000"
beam_min = "2.649999"
beam_max = "2.649999"
beam_size = "0.000000"
h_sharp = "5.250000"
s_sharp = "0.000000"
csize = "0.000000"
bsize = "600.000000"
warpX = "0.000000"
warpY = "0.000000"
glow = "0.000000"
shadowMask = "-1.000000"
masksize = "1.000000"
vertmask = "0.000000"
slotmask = "0.000000"
slotwidth = "1.000000"
double_slot = "1.000000"
slotms = "1.000000"
mcut = "0.000000"
maskDark = "1.000000"
maskLight = "1.000000"
CGWG = "0.000000"
gamma_out = "2.400000"
spike = "0.000000"
inter = "800.000000"
interm = "0.000000"
bloom = "0.000000"
scans = "0.000000"
msk_str = "1.000000"
phosphor = "0.000000"
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"
3 Likes

I love the look of this shader, but it’s only available in cg/cgp. Is there one that looks like this but it’s slang? Or how to make a crt shader look like this? My guess is a crt shader with a blur underneath. I tried and can’t get it quite right.

1 Like

I’m glad some people are out here trying to make shaders better while I’m trying to make it worse. sr02

4 Likes

No luck with Venom Guest? There are both bloom and glow to work with.

@lilbud Might help if you actually say what shader that is, I imagine it’s from the bigbox forums.

It is from the big box forums, the caption just says ‘esper’ and that it’s a cg/cgp shader.

I ended up with this using the guest venom shader. It’s almost there, not quite

Zombeaver’s shaders are based on Birm’s 199X (originally posted here and his YouTube), and 199X is based on Analog Shader Pack v3.

Only when the Analog shader pack got fully moved to .slang, the rest of two are not the problems at all. Since they all are just heavy tweak with .cgp and maybe also slightly +/- originally .cg files.

Good news is solid12345 the author of Analog shaders had the promise and working; Bad one is his last post has been 3 years ago.

Analog shader pack got moved to slang? Where?

Nowhere. It’s suspended. He’s not active anymore since last post.

@BendBombBoom

I’m impressed with your screenshots. Now I’d like to see some actual photos of shaders running on a 4K screen, preferably showing the subpixels. I think it should be possible to get a good result with the BW masks or Lottes stretched shadowmask provided that you can increase the phosphor size. I think even the magenta/green slotmask will work at 4K if you want an “off the shelf crt” slotmask. Brightness might still be a problem though as it really needs 100% strength to function as intended.

image

Actually, I think maybe even 1440p is sufficient for this mask to match a high-pitch/low TVL CRT (like 2 triads per scanline).

@hunterk

did the permissions thing with github ever get sorted out?

Not yet :frowning: Dunno what the holdup is, but I haven’t really pressed it. Been working on other things.

1 Like

Some photos showing my latest “maxDR” settings for guest-dr-venom on a 1080p screen. Colors are much more vibrant in person.

2 Likes

Settings for the above.

shaders = "8"
shader0 = "shaders_slang/misc/grade.slang"
filter_linear0 = "true"
wrap_mode0 = "clamp_to_border"
mipmap_input0 = "false"
alias0 = "WhitePointPass"
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/afterglow.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/avg-lum.slang"
filter_linear2 = "true"
wrap_mode2 = "clamp_to_border"
mipmap_input2 = "true"
alias2 = "AvgLumPass"
float_framebuffer2 = "true"
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/linearize.slang"
filter_linear3 = "true"
wrap_mode3 = "clamp_to_border"
mipmap_input3 = "false"
alias3 = "LinearizePass"
float_framebuffer3 = "true"
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/blur_horiz.slang"
filter_linear4 = "true"
wrap_mode4 = "clamp_to_border"
mipmap_input4 = "false"
alias4 = ""
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/blur_vert.slang"
filter_linear5 = "true"
wrap_mode5 = "clamp_to_border"
mipmap_input5 = "false"
alias5 = "GlowPass"
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/shaders/guest/linearize_scanlines.slang"
filter_linear6 = "true"
wrap_mode6 = "clamp_to_border"
mipmap_input6 = "false"
alias6 = ""
float_framebuffer6 = "true"
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/crt-guest-dr-venom.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 = "g_gamma_in;g_signal_type;g_gamma_type;g_crtgamut;g_space_out;g_hue_degrees;g_I_SHIFT;g_Q_SHIFT;g_I_MUL;g_Q_MUL;g_lum_fix;g_vignette;g_vstr;g_vpower;g_lum;g_cntrst;g_mid;wp_temperature;g_sat;g_vibr;g_satr;g_satg;g_satb;g_lift;blr;blg;blb;wlr;wlg;wlb;rg;rb;gr;gb;br;bg;LUT_Size1;LUT1_toggle;LUT_Size2;LUT2_toggle;SW;AR;PR;AG;PG;AB;PB;sat;lsmooth;GAMMA_INPUT;TAPSH;GLOW_FALLOFF_H;TAPSV;GLOW_FALLOFF_V;TATE;IOS;OS;BLOOM;brightboost;brightboost1;gsl;scanline1;scanline2;beam_min;beam_max;beam_size;h_sharp;s_sharp;csize;bsize;warpX;warpY;glow;shadowMask;masksize;vertmask;slotmask;slotwidth;double_slot;slotms;mcut;maskDark;maskLight;CGWG;gamma_out;spike;inter;interm;bloom;scans"
g_gamma_in = "2.500000"
g_signal_type = "0.000000"
g_gamma_type = "1.000000"
g_crtgamut = "2.000000"
g_space_out = "0.000000"
g_hue_degrees = "0.000000"
g_I_SHIFT = "0.000000"
g_Q_SHIFT = "0.000000"
g_I_MUL = "1.000000"
g_Q_MUL = "1.000000"
g_lum_fix = "0.000000"
g_vignette = "0.000000"
g_vstr = "40.000000"
g_vpower = "0.200000"
g_lum = "0.000000"
g_cntrst = "0.000000"
g_mid = "0.500000"
wp_temperature = "8005.000000"
g_sat = "0.000000"
g_vibr = "0.000000"
g_satr = "0.000000"
g_satg = "0.000000"
g_satb = "0.000000"
g_lift = "0.000000"
blr = "0.000000"
blg = "0.000000"
blb = "0.000000"
wlr = "1.000000"
wlg = "1.000000"
wlb = "1.000000"
rg = "0.000000"
rb = "0.000000"
gr = "0.000000"
gb = "0.000000"
br = "0.000000"
bg = "0.000000"
LUT_Size1 = "16.000000"
LUT1_toggle = "0.000000"
LUT_Size2 = "64.000000"
LUT2_toggle = "0.000000"
SW = "1.000000"
AR = "0.070000"
PR = "0.050000"
AG = "0.070000"
PG = "0.050000"
AB = "0.070000"
PB = "0.050000"
sat = "0.100000"
lsmooth = "0.900000"
GAMMA_INPUT = "3.499996"
TAPSH = "1.000000"
GLOW_FALLOFF_H = "0.300000"
TAPSV = "1.000000"
GLOW_FALLOFF_V = "0.300000"
TATE = "0.000000"
IOS = "0.000000"
OS = "1.000000"
BLOOM = "0.000000"
brightboost = "2.000000"
brightboost1 = "2.000000"
gsl = "2.000000"
scanline1 = "1.000000"
scanline2 = "100.000000"
beam_min = "2.000000"
beam_max = "1.000000"
beam_size = "0.000000"
h_sharp = "3.000000"
s_sharp = "1.000000"
csize = "0.000000"
bsize = "600.000000"
warpX = "0.000000"
warpY = "0.000000"
glow = "0.000000"
shadowMask = "-1.000000"
masksize = "1.000000"
vertmask = "0.000000"
slotmask = "0.000000"
slotwidth = "2.000000"
double_slot = "1.000000"
slotms = "1.000000"
mcut = "0.250000"
maskDark = "0.500000"
maskLight = "1.500000"
CGWG = "0.500000"
gamma_out = "3.500000"
spike = "0.000000"
inter = "400.000000"
interm = "1.000000"
bloom = "0.500000"
scans = "1.000000"
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"

That looks absolutely wonderful, @ProfessorBraun!

1 Like

Here is a photo of my Venom Dotty with my iphone, but I find it less accurate than a screenshot as angle, lighting, and camera lens all distort it a little. I haven’t had luck with lotte’s style masks in black in white thus far.

7 Likes

Trying to clone SEGA Versus City screen,

(slightly decreased brightness and contrast to fit my LCD shot)

originally shot,

Still tweaking around, so post the configs later.

5 Likes

A photo is more accurate than a screenshot in terms of how the mask actually looks with the pixel grid. The photo isn’t in-focus enough to really see the subpixels, though. Looks good but I was curious how the mask looked with the subpixels at 4K. Is the mask BW aperture?

What game is that?

I know it’s probably a slot mask CRT but I think BW aperture grille or mask-less scanlines will actually be a closer approximation of the photos. The granularity of the slot mask on the CRT is already very close to that of the pixel grid on a 1080p display.

The currently main issue is the color space clone. There’re a lot of VC arcade machines in the arcades, each one (the tube) has their own color styles… Say one has warm colors, one has warm with magenta colors… - and one with cyannish looking. Only a few has decent colors (means they are stables with no color shifting as like the normal LCDs do).

But that is not the problem at all. Since those are just *old grandpa* issues (Those tubes are poor and getting old). The real problem is that no matter how they do the color-shifting in many different ways, they still based on their own color space - a CRT TV colors look; Which is totally not like LCD colors (digital RGB raw colors). That being said the same logic to all CRTs compared to the LCDs.

It’s pretty tricky and hard to explain, I know there’re already have shaders can handle the color space switcher, and LUT/ICC color profiles. But still none have matched IRL. Although they may have technology correct (more probably because missing a regular CRT TV ICC). So all needs to be a manually color correction with grade.slang. After over and over trial and error, I figured out that only needs to grab and get to know how their base color space work, the rest are not important anymore (since you can never get > 95% color accurate).

There’re used/now have a lot of retro old TV shaders, Analog Shader Pack, 199X and Zombeaver. But these shaders are totally go another way, they made for fancy, over colored and memoried, retro, vaporwave look, not made for IRL.

For example, in Street Fighter III, choose Ryu with default white color clothes, load these shaders, you only see Ryu with plain over colored white clothes, can’t see any fold and shadow detailed. But IRL, VC arcade CRT TV, Ryu’s white clothes look just as like in LCD’s raw colors.

TL;DR. Anyway, here’re the shots,

raw colors, crt-guest-dr-venom-kurozumi, crt-royale

1 Like