A new little shader i did (glsl)

Here is what’s going on zoomed

2 Likes

I tested your original code with p240 test suite. Red, Green, Blue and White seem to have the same width there. Maybe a better test for scanline shaders?

Checkerboard looks really nice but i have not enough vertical resolution.

Yes because scanline = 1.0 and shader will use full strength everywhere.

Ok. That works and looks more like your screenshots.

Hey I really like this! I was wondering if there’s a way to change it to a flat screen rather than the curved screen. Thanks!

1 Like

Hey there and welcome to the forum. For the flat screen look go into parameters change both the Curvature x and y to 0.

By the way I’ve tweaked it again, the old one fails to load up now after updating my glsl shaders folder so things should be good now with this update.

https://www.mediafire.com/file/fvffd5xrxme41fa/crt-consumer-slotmask.glslp/file

Edit: Did a small edit to the preset so if you downloaded it once please grab it again

Thanks for the welcome and answer! Nice that you are updating it! However when I installed it and tried to load it up I ended up getting an error. I made sure that I was on opengl and that I put it in the glsl folder but still getting an error.

1 Like

That was the issue right there. It works by placing it directly in your shaders folder only. Try placing it there and it should load right up.

Works now! Thank you so much for the responses. I’ve also checked out your main thread of crt shaders! Good stuff man, really cool!

1 Like

Working on a shader with lanczos, for fun, yeah can’t help it :stuck_out_tongue:

#version 450

layout(push_constant) uniform Push
{
	vec4 SourceSize;
	vec4 OriginalSize;
	vec4 OutputSize;
	uint FrameCount;
   float SCANLOW,SCANHIGH,SHADOWMASK, MASKLOW,MASKHIGH,WARPX,WARPY,RADIUS,SATURATION,
   GAMMAIN,GAMMAOUT,BOOST,RG,RB,BG,CORNER,FORCE240P;
} params;

#pragma parameter WARPX "  Curvature X" 0.15 0.0 0.5 0.01
#pragma parameter WARPY "  Curvature Y" 0.20 0.0 0.5 0.01 
#pragma parameter CORNER "  Corner Roundness" 0.020 0.005 0.100 0.01
#pragma parameter SCANLOW "Scanline Amount Low" 0.6 0.0 1.0 0.05
#pragma parameter SCANHIGH "Scanline Amount High" 0.3 0.0 1.0 0.05
#pragma parameter FORCE240P "Force 240p" 0.0 0.0 1.0 1.0
#pragma parameter SHADOWMASK "Mask Type" 0.0 -1.0 1.0 1.0
#pragma parameter MASKLOW "Mask Brightness Low" 0.6 0.0 1.0 0.1
#pragma parameter MASKHIGH "Mask Brightness High" 0.8 0.0 1.0 0.1
#pragma parameter RADIUS "  Lanczos Filter Radius" 1.5 1.0 3.0 0.1
#pragma parameter SATURATION "Saturation" 1.1 0.0 2.0 0.05
#pragma parameter GAMMAIN "Gamma In" 2.5 1.0 4.0 0.05
#pragma parameter GAMMAOUT "Gamma Out" 2.25 1.0 4.0 0.05
#pragma parameter BOOST "Bright Boost" 1.06 1.0 2.0 0.02
#pragma parameter RG "  Green<->Red" 0.05 -1.0 1.0 0.01
#pragma parameter RB "  Blue<->Red" 0.0 -1.0 1.0 0.01
#pragma parameter BG "  Green<->Blue" 0.1 -1.0 1.0 0.01

#define FORCE240P params.FORCE240P
#define CORNER params.CORNER
#define WARPX params.WARPX
#define WARPY params.WARPY
#define SCANLOW params.SCANLOW
#define SCANHIGH params.SCANHIGH
#define SHADOWMASK params.SHADOWMASK
#define MASKLOW params.MASKLOW
#define MASKHIGH params.MASKHIGH
#define RADIUS params.RADIUS
#define SATURATION params.SATURATION
#define GAMMAIN params.GAMMAIN
#define GAMMAOUT params.GAMMAOUT
#define BOOST params.BOOST
#define RG params.RG
#define RB params.RB
#define BG params.BG

#define FIX(c) max(abs(c), 1e-5);
#define PI 3.14159265358
#define iTime float(params.FrameCount) / 2.0
#define SourceSize params.SourceSize
#define OutputSize params.OutputSize

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;
layout(location = 1) out vec2 pix;


void main()
{
   gl_Position = global.MVP * Position;
   vTexCoord = TexCoord*1.0001;
   pix = vec2(1.0, SourceSize.z/SourceSize.zw);

}

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


vec3 weight3(float x)
{

    vec3 texel = FIX(2.0 * PI * vec3(x - 1.5, x - 0.5, x + 0.5));

    // Lanczos3. Note: we normalize outside this function, so no point in multiplying by radius.
    return /*radius **/ sin(texel) * sin(texel / RADIUS) / (texel * texel/RADIUS);
}

vec3 pixel(float xpos, float ypos)
{
    return texture(Source, vec2(xpos, ypos)).rgb;
}

vec3 line(float ypos, vec3 xpos1, vec3 xpos2, vec3 linetaps1, vec3 linetaps2)
{
    return
        pixel(xpos1.r, ypos) * linetaps1.r +
        pixel(xpos1.g, ypos) * linetaps2.r +
        pixel(xpos1.b, ypos) * linetaps1.g +
        pixel(xpos2.r, ypos) * linetaps2.g +
        pixel(xpos2.g, ypos) * linetaps1.b +
        pixel(xpos2.b, ypos) * linetaps2.b;
}

vec2 curve(vec2 uv)
{
   uv = (uv - 0.5) * 2.0;
   uv *= 1.1;  
   uv.x *= 1.0 + pow((abs(uv.y) * WARPX), 2.0);
   uv.y *= 1.0 + pow((abs(uv.x) * WARPY), 2.0);
   uv  = (uv / 2.0) + 0.5;
   uv =  uv *0.92 + 0.04;
   return uv;
}


vec3 mask(float x, float l)
{
   vec3 Mask = vec3(1.0);

   if (SHADOWMASK == 0.0)
   {float pos = fract(x*0.5);
   if (pos<0.5) Mask = mix(vec3(MASKLOW), vec3(MASKHIGH), l); 
   else Mask;}

   else if (SHADOWMASK == 1.0)
    {float pos = fract(x*0.3333);
   if (pos<0.3333) Mask = mix(vec3(MASKLOW), vec3(MASKHIGH), l); 
   else Mask;}

   return Mask;
}

vec4 hue(vec4 c)
{
    c.rg *= vec2(1.0+RG,1.0-RG);
    c.rb *= vec2(1.0+RB,1.0-RB);
    c.bg *= vec2(1.0+BG,1.0-BG);

    return c; 
}

float corner(vec2 coord)
{
                coord = (coord - vec2(0.5)) * 1.0 + vec2(0.5);
                coord = min(coord, vec2(1.0)-coord) * pix;
           vec2 cdist = vec2(CORNER);
                coord = (cdist - min(coord,cdist));
           float dist = sqrt(dot(coord,coord));
            
           return clamp( (cdist.x-dist)*300.0, 0.0, 1.0);
}  

void main()
{
    vec2 stepxy = 1.0 / SourceSize.xy;
    vec2 texCoord = curve(vTexCoord.xy);
    
    vec2 pos = texCoord.xy + stepxy * 0.5;
    vec2 f = fract(pos / stepxy);
    
    vec3 linetaps1   = weight3(0.5 - f.x * 0.5);
    vec3 linetaps2   = weight3(1.0 - f.x * 0.5);
    vec3 columntaps1 = weight3(0.5 - f.y * 0.5);
    vec3 columntaps2 = weight3(1.0 - f.y * 0.5);

    // make sure all taps added together is exactly 1.0, otherwise some
    // (very small) distortion can occur
    float suml = dot(linetaps1, vec3(1.0)) + dot(linetaps2, vec3(1.0));
    float sumc = dot(columntaps1, vec3(1.0)) + dot(columntaps2, vec3(1.0));
    linetaps1 /= suml;
    linetaps2 /= suml;
    columntaps1 /= sumc;
    columntaps2 /= sumc;

    vec2 xystart = (-2.5 - f) * stepxy + pos;
    vec3 xpos1 = vec3(xystart.x, xystart.x + stepxy.x, xystart.x + stepxy.x * 2.0);
    vec3 xpos2 = vec3(xystart.x + stepxy.x * 3.0, xystart.x + stepxy.x * 4.0, xystart.x + stepxy.x * 5.0);

    vec4 color = vec4(
        line(xystart.y                 , xpos1, xpos2, linetaps1, linetaps2) * columntaps1.r +
        line(xystart.y + stepxy.y      , xpos1, xpos2, linetaps1, linetaps2) * columntaps2.r +
        line(xystart.y + stepxy.y * 2.0, xpos1, xpos2, linetaps1, linetaps2) * columntaps1.g +
        line(xystart.y + stepxy.y * 3.0, xpos1, xpos2, linetaps1, linetaps2) * columntaps2.g +
        line(xystart.y + stepxy.y * 4.0, xpos1, xpos2, linetaps1, linetaps2) * columntaps1.b +
        line(xystart.y + stepxy.y * 5.0, xpos1, xpos2, linetaps1, linetaps2) * columntaps2.b,
        1.0);

    float lum = dot(color.rgb, vec3(0.3,0.6,0.1));
    color.rgb = mix(vec3(lum),color.rgb,SATURATION);

    float SCANLINE = mix(SCANLOW,SCANHIGH,lum);

    if (params.OriginalSize.y > 400.0 )
        if ( FORCE240P == 1.0) 
          color *= (1.0-SCANLINE) + SCANLINE * sin(fract(texCoord.y*0.5*SourceSize.y)*PI);
          else color;
    else  color *= (1.0-SCANLINE) + SCANLINE * sin(fract(texCoord.y*SourceSize.y)*PI);
    color = pow(color,vec4(GAMMAIN));

    color.rgb *= mask(vTexCoord.x*OutputSize.x, lum);
    color = pow(color,vec4(1.0/GAMMAOUT));
    color *= mix(1.0,BOOST,lum);
    color = hue(color);
    color *=corner(texCoord);
    FragColor = color;
}
3 Likes

Turned this in to something bigger. Lanczos was nice but too slow, destroying performance so switched to something light. The point is if one would need a very beefy adapter to run it why not switch to big boys like guest-advanced or royale?

I use chromaticity glsl as 1st pass and linear filter on 2nd pass (this shader). Still needs some things e.g. how to handle interlacing etc

#pragma parameter SHARPNESSX "   Horizontal Sharpness"  0.25 0.0 1.0 0.05
#pragma parameter SHARPNESSY "   Vertical Sharpness"  0.7 0.0 1.0 0.05
#pragma parameter WARPX "Curvature Horizontal" 0.03 0.0 0.2 0.01
#pragma parameter WARPY "Curvature Vertical" 0.05 0.0 0.2 0.01
#pragma parameter CORNER_ROUND "Corner Roundness" 0.02 0.005 0.2 0.01
#pragma parameter BORDER "Border Smoothness" 400.0 100.0 1000.0 25.0
#pragma parameter SCANLOW "   Scanline Low Brightness" 0.15 0.01 1.0 0.05
#pragma parameter SCANHIGH "   Scanline High Brightness" 0.20 0.01 1.0 0.05
#pragma parameter MINSCAN "   Scanline Min Brightness" 0.04 0.01 1.0 0.01
#pragma parameter SHADOWMASK "Mask Type, CGWG, Lottes 1-4" 1.0 -1.0 4.0 1.0
#pragma parameter BGR "RGB/BGR subpixels" 1.0 0.0 1.0 1.0 
#pragma parameter MASKLOW "Mask Strength Low" 1.0 0.0 1.0 0.05
#pragma parameter MASKHIGH "Mask Strength High" 0.75 0.0 1.0 0.05
#pragma parameter DOTMASK_STRENGTH "CGWG Dot Mask Strength" 0.3 0.0 1.0 0.05
#pragma parameter MASKDARK "Lottes Mask Dark" 0.5 0.0 2.0 0.1
#pragma parameter MASKLIGHT "Lottes Mask Light" 1.5 0.0 2.0 0.1
#pragma parameter GAMMAIN "   Gamma In" 2.4 1.0 4.0 0.05
#pragma parameter GAMMAOUT "   Gamma Out" 2.25 1.0 4.0 0.05
#pragma parameter BLACK "   Black Level" 0.0 -0.20 0.20 0.01 
#pragma parameter TEMP "   Color Temperature in Kelvins"  9311.0 1031.0 12047.0 72.0
#pragma parameter SAT "   Saturation" 1.0 0.0 2.0 0.01
#pragma parameter SEGA "   SEGA Lum Fix" 0.0 0.0 1.0 1.0
#pragma parameter GLOW "   Glow Strength" 0.12 0.0 1.0 0.01
#pragma parameter quality "   Glow Size" 1.0 0.0 1.5 0.05
#pragma parameter VIGNETTE "Vignette On/Off" 1.0 0.0 1.0 1.0
#pragma parameter VPOWER "Vignette Power" 0.1 0.0 1.0 0.01
#pragma parameter VSTR "Vignette Strength" 45.0 0.0 50.0 1.0

#pragma parameter nois "Noise strength" 0.4 0.0 1.0 0.01

#define PI  3.14159265 
#define FIX(c) max(abs(c), 1e-5);
#define mod_factor vTexCoord.x * OutputSize.x/InputSize.x* SourceSize.x 


#define scale vec4(TextureSize/InputSize,InputSize/TextureSize)
#define filterWidth (InputSize.y / OutputSize.y) / 3.0


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


uniform vec2 TextureSize;
varying vec2 TEX0;

#if defined(VERTEX)
uniform mat4 MVPMatrix;
attribute vec4 VertexCoord;
attribute vec2 TexCoord;
uniform int FrameCount;
uniform vec2 InputSize;
uniform vec2 OutputSize;

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

#elif defined(FRAGMENT)

uniform sampler2D Texture;
uniform vec2 OutputSize;
uniform int FrameCount;
uniform vec2 InputSize;

#define vTexCoord TEX0.xy
#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
#define FragColor gl_FragColor
#define Source Texture
#define iTime FrameCount/60


#ifdef PARAMETER_UNIFORM
uniform COMPAT_PRECISION float SHARPNESSX;
uniform COMPAT_PRECISION float SHARPNESSY;
uniform COMPAT_PRECISION float WARPX;
uniform COMPAT_PRECISION float WARPY;
uniform COMPAT_PRECISION float CORNER_ROUND;
uniform COMPAT_PRECISION float BORDER;
uniform COMPAT_PRECISION float SHADOWMASK;
uniform COMPAT_PRECISION float MASKLOW;
uniform COMPAT_PRECISION float MASKHIGH;
uniform COMPAT_PRECISION float DOTMASK_STRENGTH;
uniform COMPAT_PRECISION float MASKDARK;
uniform COMPAT_PRECISION float MASKLIGHT;
uniform COMPAT_PRECISION float GAMMAIN;
uniform COMPAT_PRECISION float GAMMAOUT;
uniform COMPAT_PRECISION float SAT;
uniform COMPAT_PRECISION float SCANLOW;
uniform COMPAT_PRECISION float SCANHIGH;
uniform COMPAT_PRECISION float MINSCAN;
uniform COMPAT_PRECISION float VIGNETTE;
uniform COMPAT_PRECISION float VPOWER;
uniform COMPAT_PRECISION float VSTR;
uniform COMPAT_PRECISION float TEMP;
uniform COMPAT_PRECISION float SEGA;
uniform COMPAT_PRECISION float BLACK;
uniform COMPAT_PRECISION float GLOW;
uniform COMPAT_PRECISION float SIZE;
uniform COMPAT_PRECISION float quality;
uniform COMPAT_PRECISION float nois;
uniform COMPAT_PRECISION float BGR;


#else

#define SHARPNESSX 0.3
#define SHARPNESSY 0.5
#define WARPX 0.03
#define WARPY 0.05
#define CORNER_ROUND 0.02
#define BORDER 400.0
#define SHADOWMASK 3.0
#define MASKLOW 0.5
#define MASKHIGH 0.3
#define DOTMASK_STRENGTH 0.3
#define MASKDARK 0.5
#define MASKLIGHT 1.5
#define GAMMAIN 2.5
#define GAMMAOUT 2.25
#define SAT 1.0
#define SCANLOW 0.15
#define SCANHIGH 0.35
#define MINSCAN 0.12
#define VIGNETTE 1.0
#define VPOWER 0.15
#define VSTR 45.0
#define TEMP 9300.0
#define SEGA 0.0
#define BLACK 0.0
#define GLOW 0.0 
#define SIZE 2.0
#define quality 1.0
#define BGR 1.0
#define nois 0.0

#endif

#define iTimer (float(FrameCount) / 60.0)


vec2 curve(vec2 pos)
{
    pos  = pos*2.0-1.0;    
    pos *= vec2(1.0 + (pos.y*pos.y)*WARPX, 
        1.0 + (pos.x*pos.x)*WARPY);
    
    return pos*0.5 + 0.5;
}

float corner(vec2 coord)
{
                coord *= scale.xy;
                coord = (coord - vec2(0.5)) * 1.0 + vec2(0.5);
                coord = min(coord, vec2(1.0)-coord) * vec2(1.0, InputSize.y/InputSize.x);
                vec2 cdist = vec2(CORNER_ROUND);
                coord = (cdist - min(coord,cdist));
                float dist = sqrt(dot(coord,coord));
                return clamp((cdist.x-dist)*BORDER,0.0, 1.0);
}  



float CalcScanLineWeight(float dist, float scan)
{
    return max(1.0-dist*dist/scan, MINSCAN);
}

float ScanLine(float dy, float l)
{
    float scan = mix(SCANLOW, SCANHIGH, l);
    float scanLineWeight = CalcScanLineWeight(dy, scan);
    scanLineWeight += CalcScanLineWeight(dy-filterWidth, scan);
    scanLineWeight += CalcScanLineWeight(dy+filterWidth, scan);
    scanLineWeight *= 0.3333333;
    return scanLineWeight;
}


// Shadow mask.
vec3 Mask(vec2 pos)
{
   vec3 mask = vec3(MASKDARK, MASKDARK, MASKDARK);
   
   // Very compressed TV style shadow mask.
   if (SHADOWMASK == 1.0)
   {
      float line = MASKLIGHT;
      float odd  = 0.0;

      if (fract(pos.x/6.0) < 0.5)
         odd = 1.0;
      if (fract((pos.y + odd)/2.0) < 0.5)
         line = MASKDARK;

      pos.x = fract(pos.x/3.0);
    
      if      (pos.x < 0.333) (BGR == 1.0) ? mask.b = MASKLIGHT : mask.r = MASKLIGHT;
      else if (pos.x < 0.666) mask.g = MASKLIGHT;
      else                    (BGR == 1.0) ? mask.r = MASKLIGHT : mask.b = MASKLIGHT;
      mask*=line;  
   } 

   // Aperture-grille.
   else if (SHADOWMASK == 2.0)
   {
      pos.x = fract(pos.x/3.0);

      if      (pos.x < 0.333) (BGR == 1.0) ? mask.b = MASKLIGHT : mask.r = MASKLIGHT;
      else if (pos.x < 0.666) mask.g = MASKLIGHT;
      else                   (BGR == 1.0) ? mask.r = MASKLIGHT : mask.b = MASKLIGHT;
   } 

   // Stretched VGA style shadow mask (same as prior shaders).
   else if (SHADOWMASK == 3.0)
   {
      pos.x += pos.y*3.0;
      pos.x  = fract(pos.x/6.0);

      if      (pos.x < 0.333) (BGR == 1.0) ? mask.b = MASKLIGHT : mask.r = MASKLIGHT;
      else if (pos.x < 0.666) mask.g = MASKLIGHT;
      else                    (BGR == 1.0) ? mask.r = MASKLIGHT : mask.b = MASKLIGHT;
   }

   // VGA style shadow mask.
   else if (SHADOWMASK == 4.0)
   {
      pos.xy = floor(pos.xy*vec2(1.0, 0.5));
      pos.x += pos.y*3.0;
      pos.x  = fract(pos.x/6.0);

      if      (pos.x < 0.333) (BGR == 1.0) ? mask.b = MASKLIGHT : mask.r = MASKLIGHT;
      else if (pos.x < 0.666) mask.g = MASKLIGHT;
      else                    (BGR == 1.0) ? mask.r = MASKLIGHT : mask.b = MASKLIGHT;
   }
   else if (SHADOWMASK == -1.0) mask = vec3(1.0);
   return mask;
}

mat3 vign()
{
    vec2 vpos = vTexCoord * TextureSize/InputSize;
    vpos *= 1.0 - vpos;    

    float vig = vpos.x * vpos.y * VSTR;

    vig = min(pow(vig, VPOWER), 1.0); 
    
    if (VIGNETTE == 0.0) vig=1.0;
   
    return mat3(vig, 0, 0,
                 0,   vig, 0,
                 0,    0, vig);
}

float saturate(float v) 
    { 
        return clamp(v, 0.0, 1.0);       
    }

// https://www.shadertoy.com/view/lsSXW1
vec3 ColorTemperatureToRGB(float temperatureInKelvins)
{
    vec3 retColor;
    temperatureInKelvins = clamp(temperatureInKelvins, 1000.0, 40000.0) / 100.0;
    
    if (temperatureInKelvins <= 66.0)
    {
        retColor.r = 1.0;
        retColor.g = saturate(0.39008157876901960784 * log(temperatureInKelvins) - 0.63184144378862745098);
    }
    else
    {
        float t = temperatureInKelvins - 60.0;
        retColor.r = saturate(1.29293618606274509804 * pow(t, -0.1332047592));
        retColor.g = saturate(1.12989086089529411765 * pow(t, -0.0755148492));
    }
    
    if (temperatureInKelvins >= 66.0)
        retColor.b = 1.0;
    else if(temperatureInKelvins <= 19.0)
        retColor.b = 0.0;
    else
        retColor.b = saturate(0.54320678911019607843 * log(temperatureInKelvins - 10.0) - 1.19625408914);

    return retColor;
}


vec3 glow0 (vec2 uv)
{
   vec3 sum = vec3(0.0);
   float x = uv.x;
   float y = uv.y;
   float xx = SourceSize.z*quality;
   float yy = SourceSize.w*quality;

   sum += texture2D(Source, vec2(x-xx,y)).rgb*0.1;
   sum += texture2D(Source,vec2(x-xx,y-yy)).rgb*0.1;
   sum += texture2D(Source,vec2(x,y-yy)).rgb*0.1;
   sum += texture2D(Source,vec2(x+xx,y-yy)).rgb*0.1;
   sum += texture2D(Source,vec2(x+xx,y)).rgb*0.1;
   sum += texture2D(Source,vec2(x+xx,y+yy)).rgb*0.1;
   sum += texture2D(Source,vec2(x, y-yy)).rgb*0.1;
   sum += texture2D(Source,vec2(x+xx,y+yy)).rgb*0.1;

   sum += texture2D(Source,vec2(x-2.0*xx,y)).rgb*0.05;
   sum += texture2D(Source,vec2(x-2.0*xx,y-yy)).rgb*0.05;
   sum += texture2D(Source,vec2(x-xx,y-2.0*yy)).rgb*0.05;
   sum += texture2D(Source,vec2(x,y-2.0*yy)).rgb*0.05;
   sum += texture2D(Source,vec2(x+xx,y-2.0*yy)).rgb*0.05;
   sum += texture2D(Source,vec2(x+2.0*xx,y-yy)).rgb*0.05;
   sum += texture2D(Source,vec2(x+2.0*xx,y)).rgb*0.05;
   sum += texture2D(Source,vec2(x+2.0*xx,y+yy)).rgb*0.05;
   sum += texture2D(Source,vec2(x+xx,y+2.0*yy)).rgb*0.05;
   sum += texture2D(Source,vec2(x,y+2.0*yy)).rgb*0.05;
   sum += texture2D(Source,vec2(x-xx,y+2.0*yy)).rgb*0.05;
   sum += texture2D(Source,vec2(x-2.0*xx,y-yy)).rgb*0.05;

   return sum * GLOW; 
}

float noise(vec2 co)
{
return fract(sin(iTimer * dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}

void main()
{

// FILTER
	vec2 stepxy = SourceSize.zw;
    vec2 texCoord = curve(TEX0.xy*(TextureSize.xy/InputSize.xy))*(InputSize.xy/TextureSize.xy);
    
    vec2 pos = texCoord.xy + stepxy * 0.5;
    vec2 OGL2Pos = texCoord * TextureSize;
    vec2 pC4 = floor(OGL2Pos) + 0.5;
    vec2 coord = pC4 / TextureSize;
    vec2 f = fract(pos / stepxy);
    
    float x = mix(texCoord.x,coord.x,SHARPNESSX);
    float y = mix(texCoord.y,coord.y,SHARPNESSY);
    vec4 color = texture2D(Source,vec2(x,y)); 

    float lum2 = dot(color.rgb,vec3(0.29,0.60,0.11));

//gamma in    
    color = pow(color, vec4(GAMMAIN));
    
//Color temp    
    color.rgb *= ColorTemperatureToRGB(TEMP);
    
    float lum = max(max(color.r,color.g),color.b);
// noise    
    color.rgb *= mix(1.0 + noise(texCoord)*nois,1.0,lum);
//scanlines
float ss = ScanLine(f.y, lum)+ScanLine(1.0-f.y, lum);
    color *= ss;
//mask
    float mask = 1.0 - DOTMASK_STRENGTH;
    vec3 dotMaskWeights = mix(vec3(1.0, mask, 1.0),
                             vec3(mask, 1.0, mask),
                             floor(mod(mod_factor, 2.0)));
    float msk = mix(MASKLOW,MASKHIGH,lum2);

 if (SHADOWMASK == 0.0) 
   {
      color.rgb *= mix(vec3(1.0),dotMaskWeights, msk);
   }
   else 
   {
      color.rgb *= mix(vec3(1.0),Mask(floor(1.000001 * gl_FragCoord.xy + vec2(0.5,0.5))), msk);
   }

//gamma out
    color = pow(color, vec4(1.0/GAMMAOUT));  
//glow    
    color.rgb += glow0(pos);
//saturation
    color.rgb = mix(vec3(lum2)*ss,color.rgb, SAT);
//black level    
    color.rgb -= vec3(BLACK);
    color.rgb *= vec3(1.0)/vec3(1.0-BLACK);
//corner    
    color *= corner(texCoord);

    if (SEGA == 1.0) color.rgb *= 1.0625;

// vignette    
    color.rgb *= vign();
    FragColor = color;
}
#endif
2 Likes

More screens. MX Linux helps massively because there is “Watch shader for any changes” so any change you do in code is instantly visible.

7 Likes

Isn’t watch shader for changes available in other systems? Not even a slow polling?

IIRC, linux has a nice, straightforward way to do it, while Windows requires a spammy hack, so the guy who added it chose to leave Windows off.

The only problem with watching shader changes is that if you introduce a syntax error, it will fail to compile and you have to go fix it in the interface, so you need to be careful about when you hit ctrl+s :stuck_out_tongue:

1 Like

It was there in windows, disappeared maybe after version 1.9. I also think that Windows performs better with onboard HD630 or it could be that Linux uses the laptop’s gtx 1060 at very low freq. because battery runs faster. Didn’t check that.

Yeah, my oneliner way is:

while true ; do clear ; retroarch -L /path/to/core.so /path/to/rom --set-shader /path/to/shader.slangp 2>&1 |grep -i error; sleep 0.1 ; done

…that way, when i do a mistake, i just close the retroarch window and it reloads.

Usually I just use a static picture instead of the rom

2 Likes

Ok so i found why performance was low on Linux compared to Windows. HARD GPU SYNC was on, after switch off performance skyrocketed.

2 Likes

An experiment to add a slot mask to ossc shader.

2 Likes

Nice, I recognize the pattern, you’re offsetting whole scanlines, right?

1 Like

That’s a separate pass, “slotmask.slang” in crt/shaders, meant to top “ossc” . But I checked it works just fine with crt-geom at the right scale.

1 Like