A new little shader i did (glsl)

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

1 Like

Thanks, got the look, but definitely more complex than what I thought!

1 Like

Yes that blew my mind thinking floats,integers, check again, again, again lol. Thankfully Linux helps a lot.

1 Like
/*
Commodore 1084 controls shader
DariusG @2023

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.

*/

#pragma parameter GREEN "Green" 0.0 0.0 1.0 1.0
#pragma parameter TINT "Tint" 0.0 -0.5 0.5 0.01
#pragma parameter COLOR "Color" 1.0 0.0 2.0 0.01
#pragma parameter CONTRAST "Contrast" 1.0 0.0 2.0 0.01
#pragma parameter BRIGHTNESS "Brightness" 1.0 0.0 2.0 0.01
#pragma parameter HPHASE "H. Phase" 0.0 -1.0 1.0 0.01
#pragma parameter HORIZSIZE "Horiz. Size" 1.0 0.5 2.0 0.01
#pragma parameter VERTSIZE "Vertical Size" 1.0 0.5 2.0 0.01
#pragma parameter VERTSHIFT "Vertical Shift" 0.0 -1.0 1.0 0.01
#pragma parameter CVBSRGB "CVBS/RGB" 1.0 0.0 1.0 1.0
#pragma parameter NTSC "NTSC Aspect" 0.0 0.0 1.0 1.0
#pragma parameter MSK "Mask Strength" 0.7 0.0 1.0 0.05
#pragma parameter SCAN "Scanline Strength" 1.20 0.5 3.0 0.05

#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 vec2 InputSize;
uniform vec2 OutputSize;

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

#elif defined(FRAGMENT)

uniform sampler2D Texture;
uniform vec2 OutputSize;
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


#ifdef PARAMETER_UNIFORM
uniform COMPAT_PRECISION float NTSC;
uniform COMPAT_PRECISION float MSK;
uniform COMPAT_PRECISION float SCAN;
uniform COMPAT_PRECISION float HPHASE;
uniform COMPAT_PRECISION float VERTSHIFT;
uniform COMPAT_PRECISION float HORIZSIZE;
uniform COMPAT_PRECISION float VERTSIZE;
uniform COMPAT_PRECISION float BRIGHTNESS;
uniform COMPAT_PRECISION float COLOR;
uniform COMPAT_PRECISION float CONTRAST;
uniform COMPAT_PRECISION float GREEN;
uniform COMPAT_PRECISION float CVBSRGB;
uniform COMPAT_PRECISION float TINT;


#else

#define NTSC 0.0
#define MSK 0.3
#define SCAN 0.6
#define HPHASE 0.0
#define VERTSHIFT 0.0
#define HORIZSIZE 1.0
#define VERTSIZE 1.0
#define BRIGHTNESS 1.0
#define COLOR 1.0
#define CONTRAST 1.0
#define GREEN 0.0
#define CVBSRGB 0.0
#define TINT 0.0

#endif

#define blur_y -0.15/(TextureSize.y*2.0)
#define blur_x 1.75/(TextureSize.x*2.0)

float sw (float y, float l)
{
    float scan = mix(8.0, 12.0, y);
    float tmp = mix(SCAN, SCAN*0.7, l);
    float ex = y*tmp;
    return exp2(-scan*ex*ex);
}

 vec3 Mask(vec2 pos)
{
    if (OutputSize.y > 1600.0) pos /=2.0;
    vec3 mask = vec3(0.5);
    float line = 1.5;
        float odd  = 0.0;

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

        pos.x = fract(pos.x*0.5);
    
        if  (pos.x < 0.5) {mask.r = 1.; mask.b = 1.;}
        else  mask.g = 1.;   
        mask*=line;  
        return mask;
}

vec2 Warp(vec2 pos)
{
    pos  = pos*2.0-1.0;    
    pos *= vec2(1.0 + (pos.y*pos.y)*0.03, 1.0 + (pos.x*pos.x)*0.05);
    
    return pos*0.5 + 0.5;
}


float corner(vec2 coord)
{
                coord *= TextureSize/InputSize,InputSize/TextureSize;
                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(0.02);
                coord = (cdist - min(coord,cdist));
                float dist = sqrt(dot(coord,coord));
                return clamp((cdist.x-dist)*300.0,0.0, 1.0);
}  

vec3 toGrayscale(vec3 color, float average)
{
  return vec3(average);
}

vec3 colorize(vec3 grayscale, vec3 color)
{
    return (grayscale * color);
}

 mat3 color = mat3(  1.0,  TINT,  TINT,   //red tint
                    -TINT,   1.0,  -TINT,  //green tint
                    -TINT,  -TINT,   1.0  //blue tint
                     ); //black tint

void main()
{
        vec2 pos = vTexCoord;
        
        if (NTSC == 1.0) {pos.y *=0.833;} 
        pos -= vec2(HPHASE,VERTSHIFT)/10.0;
        pos /= vec2(HORIZSIZE,VERTSIZE);
        
        pos = Warp(pos*TextureSize/InputSize)*(InputSize/TextureSize);
     
        vec2 OGL2Pos = pos * TextureSize;
        vec2 pC4 = floor(OGL2Pos) + 0.5;
        vec2 coord = pC4 / TextureSize;

        vec2 tc = vec2(mix(pos.x,coord.x,0.4), mix(pos.y,coord.y,0.8));

        


//CVBSRGB
        vec4 res, res2, sample1, sample2, sample3, sample1b, sample2b, sample3b;
if (CVBSRGB == 0.0){
      sample1 = texture2D(Source,tc+(vec2(blur_x,-blur_y)));
      sample2 = 0.5*texture2D(Source,tc);
      sample3 = texture2D(Source,tc + vec2(-blur_x,blur_y));

      sample1b = texture2D(Source,tc+ vec2(0.0,SourceSize.w)+(vec2(blur_x,-blur_y)));
      sample2b = 0.5*texture2D(Source,tc+ vec2(0.0,SourceSize.w));
      sample3b = texture2D(Source,tc+ vec2(0.0,SourceSize.w) + vec2(-blur_x,blur_y));
      
      res = vec4(sample1.r*0.5  + sample2.r, 
                     sample1.g*0.25 + sample2.g + sample3.g*0.25, 
                                          sample2.b + sample3.b*0.5, 1.0);
      res2 = vec4(sample1b.r*0.5  + sample2b.r, 
                     sample1b.g*0.25 + sample2b.g + sample3b.g*0.25, 
                                          sample2b.b + sample3b.b*0.5, 1.0);
    }

    else {res = texture2D(Source, tc);
          res2 = texture2D(Source, tc + vec2(0.0,SourceSize.w));}
        

        float lum = dot(vec3(0.3,0.6,0.1),res.rgb);
        float lum2 = dot(vec3(0.3,0.6,0.1),res2.rgb);
if (GREEN == 1.0)
    {
    vec3 col1 = toGrayscale (res.rgb, lum);
    vec3 col2 = toGrayscale (res2.rgb, lum2);
    vec3 c = vec3(0.0, 1.0, 0.0);
    res.rgb = colorize (col1, c);
    res2.rgb = colorize (col2, c);
    }

       //SCANLINES 
        float f = fract(OGL2Pos.y);
        res.rgb = res.rgb*sw(f, lum) + res2.rgb*sw(1.0-f,lum2);
        res.rgb *= BRIGHTNESS; 

       // MASK 
        res.rgb = pow(res.rgb,vec3(2.4));
        res.rgb *= mix(vec3(1.0), Mask(gl_FragCoord.xy), MSK);

        res.rgb = pow(res.rgb, vec3(0.45));

       //SATURATION CONTROLS
        lum = dot(vec3(0.3,0.6,0.1), res.rgb);
        res.rgb = mix(vec3(lum),res.rgb,COLOR);
        res.rgb *= mix(1.3,1.0,lum);
        res.rgb *= color;

        res *=corner(pos);
        vec4 avglum = vec4(0.5);
        res = mix(res, avglum, (1.0 - CONTRAST));
        FragColor = res;

}
#endif

2 Likes

Maybe someone with a 1084S could help tell me how TINT/HUE works, mine died a long time ago. If i remember well i also think HORIZ.SIZE enlarges image both directions x axis?

A summary of what has been done these months

crt-1tap port to glsl, fix for old GLES 2.0
crt-beam  glsl
crt-consumer glsl/slang
gdv-mini glsl/slang
Guest-r.Dr.Venom fix for Android glsl (not loading)
Hyllian-fast port to glsl/slang
crt-pocket glsl/slang
crt-potato-bvm
crt-simple port to glsl/slang
crt-sines glsl/slang
fake-crt-geom glsl/slang
fake-crt-geom-potato glsl/slang
zfast-crt-composite glsl/slang
spline-16-fast port to glsl fixed for GLES 2.0
bilinear-adjustable glsl
prescale-2x-axis
chromaticity port and improved glsl/slang
simple-color-controls glsl/slang
gdv-mini-scanlines glsl
ossc glsl/slang
res-independent-scanlines port to glsl
lanczos3-fast port to glsl, fix for GLES 2.0

Various other minor jobs
6 Likes

An old NTSC shader I found, ported to glsl and made a PR. “OSSC” is on top of it (glsl) on my old android xiaomi note 3 pro. Made some tests, works well with games at 256 x resolution, probably needs some tweaks to work well on 320 x games

3 Likes

What’s its name? Maybe you can optionally mix() the artifacts to make them less visible?

2 Likes

It’s named ‘ntsc-cgwg’ on ‘ntsc’ folder (GLSL), but PR is not yet passed. I didn’t dig that deep to the rabbit hole to try to minimize artifacts. I mostly wanted something that resembles NTSC signal and works on my Android phones (no pink). That was the 10th shader i ported, or so, and it worked well :stuck_out_tongue:

1 Like

A few months ago, I added to ntsc-adaptive a GLES-only function that packs the first pass’ output values to eliminate the need for float framebuffers, which should avoid the pink at the cost of adding a couple of pixels worth of green at the very edge of the screen (for some reason).

3 Likes

Ntsc-adaptive won’t load on android, crashing.

Can you tell me the error? It’s probably something I introduced with that change. I only tested it on PC by removing the float framebuffer attribute, not on an actual GLES machine.

Shader log: ERROR: 0:199: 'mod' : no matching overloaded function found 
ERROR: 0:199: 'mod' : no matching overloaded function found 
ERROR: 0:208: 'mod' : no matching overloaded function found 
ERROR: 0:208: 'mod' : no matching overloaded function found 
ERROR: 4 compilation errors.  No code generated.

Ah, thanks. Probably just need to wrap those FrameCounts in float(), since GLES really, really hates implicit casts. Can you see if this one treats you any better?

#version 130

// NTSC-Adaptive
// based on Themaister's NTSC shader

#pragma parameter quality "NTSC Preset (Svideo=0 Composite=1 RF=2 Custom=-1)" 1.0 -1.0 2.0 1.0
#pragma parameter ntsc_fields "NTSC Merge Fields" 0.0 0.0 1.0 1.0
#pragma parameter ntsc_phase "NTSC Phase: Auto | 2 phase | 3 phase" 1.0 1.0 3.0 1.0
#pragma parameter ntsc_scale "NTSC Resolution Scaling" 1.0 0.20 3.0 0.05
#pragma parameter ntsc_sat "NTSC Color Saturation" 1.0 0.0 2.0 0.01
#pragma parameter ntsc_bright "NTSC Brightness" 1.0 0.0 1.5 0.01
#pragma parameter cust_fringing "NTSC Custom Fringing Value" 0.0 0.0 5.0 0.1
#pragma parameter cust_artifacting "NTSC Custom Artifacting Value" 0.0 0.0 5.0 0.1

#define PI 3.14159265

#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;
COMPAT_VARYING vec2 pix_no;
COMPAT_VARYING float phase;
COMPAT_VARYING float BRIGHTNESS;
COMPAT_VARYING float SATURATION;
COMPAT_VARYING float FRINGING;
COMPAT_VARYING float ARTIFACTING;
COMPAT_VARYING float CHROMA_MOD_FREQ;
COMPAT_VARYING float MERGE;

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;
uniform COMPAT_PRECISION vec2 OrigInputSize;

// compatibility #defines
#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 quality, ntsc_sat, cust_fringing, cust_artifacting, ntsc_bright, ntsc_scale, ntsc_fields, ntsc_phase;
#else
#define ntsc_fields 0.0
#define ntsc_phase 1.0
#define ntsc_sat 1.0
#define ntsc_bright 1.0
#define cust_fringing 0.0
#define cust_artifacting 0.0
#define quality 0.0
#endif

void main()
{
   float res = ntsc_scale;
   float OriginalSize = OrigInputSize.x;
   gl_Position = MVPMatrix * VertexCoord;
   TEX0.xy = TexCoord.xy;
	if (res < 1.0) pix_no = vTexCoord * SourceSize.xy * (res * OutSize.xy / InputSize.xy);
	else
                  pix_no = vTexCoord * SourceSize.xy * (      OutSize.xy / InputSize.xy);
   pix_no = vTexCoord * SourceSize.xy * (OutSize.xy / InputSize.xy);
	phase = (ntsc_phase < 1.5) ? ((OriginalSize > 300.0) ? 2.0 : 3.0) : ((ntsc_phase > 2.5) ? 3.0 : 2.0);
	
	res = max(res, 1.0);	
	CHROMA_MOD_FREQ = (phase < 2.5) ? (4.0 * PI / 15.0) : (PI / 3.0);
	ARTIFACTING = (quality > -0.5) ? quality * 0.5*(res+1.0) : cust_artifacting;
	FRINGING = (quality > -0.5) ? quality : cust_fringing;
	SATURATION = ntsc_sat;
	BRIGHTNESS = ntsc_bright;	
	pix_no.x = pix_no.x * res;

	MERGE = (int(quality) == 2 || phase < 2.5) ? 0.0 : 1.0;
	MERGE = (int(quality) == -1) ? ntsc_fields : MERGE;
}

#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 COMPAT_PRECISION vec2 OrigInputSize;
uniform sampler2D Texture;
COMPAT_VARYING vec4 TEX0;
COMPAT_VARYING vec2 pix_no;
COMPAT_VARYING float phase;
COMPAT_VARYING float BRIGHTNESS;
COMPAT_VARYING float SATURATION;
COMPAT_VARYING float FRINGING;
COMPAT_VARYING float ARTIFACTING;
COMPAT_VARYING float CHROMA_MOD_FREQ;
COMPAT_VARYING float MERGE;

// 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 quality, ntsc_sat, cust_fringing, cust_artifacting, ntsc_bright, ntsc_scale, ntsc_fields, ntsc_phase;
#else
#define ntsc_fields 0.0
#define ntsc_phase 1.0
#define ntsc_sat 1.0
#define ntsc_bright 1.0
#define cust_fringing 0.0
#define cust_artifacting 0.0
#define quality 0.0
#endif

#define PI 3.14159265

#define mix_mat mat3(BRIGHTNESS, FRINGING, FRINGING, ARTIFACTING, 2.0 * SATURATION, 0.0, ARTIFACTING, 0.0, 2.0 * SATURATION)

const mat3 yiq2rgb_mat = mat3(
   1.0, 0.956, 0.6210,
   1.0, -0.2720, -0.6474,
   1.0, -1.1060, 1.7046);

vec3 yiq2rgb(vec3 yiq)
{
   return yiq * yiq2rgb_mat;
}

const mat3 yiq_mat = mat3(
      0.2989, 0.5870, 0.1140,
      0.5959, -0.2744, -0.3216,
      0.2115, -0.5229, 0.3114
);

vec3 rgb2yiq(vec3 col)
{
   return col * yiq_mat;
}

vec4 pack_float(vec4 color)
{
	return ((color * 10.0) - 1.0);
}

void main()
{
   vec3 col = COMPAT_TEXTURE(Source, vTexCoord).rgb;
   vec3 yiq = rgb2yiq(col);
   vec3 yiq2 = yiq;	

   float mod1 = 2.0;
   float mod2 = 3.0; 

if (MERGE > 0.5)
{
   float chroma_phase2 = (phase < 2.5) ? PI * (mod(pix_no.y, mod1) + mod(float(FrameCount+1), 2.)) : 0.6667 * PI * (mod(pix_no.y, mod2) + mod(float(FrameCount+1), 2.));
   float mod_phase2 = chroma_phase2 + pix_no.x * CHROMA_MOD_FREQ;
   float i_mod2 = cos(mod_phase2);
   float q_mod2 = sin(mod_phase2);
   yiq2.yz *= vec2(i_mod2, q_mod2); // Modulate.
   yiq2 *= mix_mat; // Cross-talk.
   yiq2.yz *= vec2(i_mod2, q_mod2); // Demodulate.   
}
   
   float chroma_phase = (phase < 2.5) ? PI * (mod(pix_no.y, mod1) + mod(float(FrameCount), 2.)) : 0.6667 * PI * (mod(pix_no.y, mod2) + mod(float(FrameCount), 2.));
   float mod_phase = chroma_phase + pix_no.x * CHROMA_MOD_FREQ;

   float i_mod = cos(mod_phase);
   float q_mod = sin(mod_phase);

   yiq.yz *= vec2(i_mod, q_mod); // Modulate.
   yiq *= mix_mat; // Cross-talk.
   yiq.yz *= vec2(i_mod, q_mod); // Demodulate.
      
   yiq = (MERGE < 0.5) ? yiq : 0.5*(yiq+yiq2);
   
   FragColor = vec4(yiq, 1.0);
#ifdef GL_ES
   FragColor = pack_float(FragColor);
#endif
} 
#endif