Converting cgwg's CRT-Geom to .glsl or .cg

So I’m having a little trouble converting CRT-Geom to one of the new shader formats. Since XML is now deprecated, I thought it would make sense to adapt it so as to be able to use it with shader presets and combine it with other shaders. I’m not very good with CG, so I thought I would try to convert it to modern GLSL, which seemed simple enough. Thing is, my efforts have not been fruitful, as RetroArch just ends up crashing.

http://pastebin.com/GMzDquyW

That is what I have done so far. What am I doing wrong?

Your shader looks okay to me at first glance, though I’m not really on top of the GLSL format. Does it give you anything in your log?

Related: after a number of failed attempts over the past 2 weeks, I finally got CRT-geom-interlaced converted to Cg:

/* COMPATIBILITY 
   - HLSL compilers
   - Cg   compilers
*/

// This is a good place for any #defines you might have
#define FIX(c) max(abs(c), 1e-5);

// Comment the next line to disable interpolation in linear gamma (and gain speed).
//#define LINEAR_PROCESSING

// Enable screen curvature.
#define CURVATURE

// Enable 3x oversampling of the beam profile
#define OVERSAMPLE

// Use the older, purely gaussian beam profile
//#define USEGAUSSIAN

#define distortion 0.1

// Macros.
#define FIX(c) max(abs(c), 1e-5);
#define PI 3.141592653589

#ifdef LINEAR_PROCESSING
#       define TEX2D(c) pow(tex2D(IN.texture, (c)), float4(CRTgamma))
#else
#       define TEX2D(c) tex2D(IN.texture, (c))
#endif

  // gamma of simulated CRT
#define CRTgamma 2.4

  // gamma of display monitor (typically 2.2 is correct)
#define monitorgamma 2.2

  // overscan (e.g. 1.02 for 2% overscan)
#define overscan float2(1.00,1.00)

  // aspect ratio ; needs 'transform' function
#define aspect float2(1.0, 0.75)

  // size of curved corners
#define cornersize 0.02
  
  // border smoothness parameter
  // decrease if borders are too aliased
#define cornersmooth 80.0

  // lengths are measured in units of (approximately) the width of the monitor
  // simulated distance from viewer to monitor ; needs 'transform' function
#define d 2.0

  // radius of curvature ; needs 'transform' function. use 'distortion' instead
#define R 1.5

  // tilt angle in radians
  // (behavior might be a bit wrong if both components are nonzero) ; needs 'transform' function
#define angle float2(0.0,-0.15)

struct input      // These are things that can attach to 'IN' to achieve similar function to ruby* stuff in existing GLSL shaders. NOTE: the ruby* prefix is deprecated but still works in GLSL for legacy compatibility purposes.
{
  float2 video_size;
  float2 texCoord_size;
  float2 output_size;
  float frame_count;
  float frame_direction;
  float frame_rotation;
  float texture_size;
  sampler2D texture : TEXUNIT0;
};

struct tex_coords
{
   float2 texCoord  : TEXCOORD0; 
   float mod_factor : TEXCOORD1;
   float2 one       : TEXCOORD2;
};

// VERTEX SHADER //

void main_vertex
(
   float4 position : POSITION,
   out float4 oPosition : POSITION,
   uniform float4x4 modelViewProj,

   float4 color : COLOR,
   out float4 oColor : COLOR,

   float2 tex : TEXCOORD,

   uniform input IN,
   out tex_coords coords
 )
{
   oPosition = mul(modelViewProj, position);
   oColor = color;

   coords.texCoord = tex + float2(0.0, 0.0);
   coords.mod_factor = tex.x * IN.output_size.x * IN.texture_size.x / IN.video_size.x;
   coords.one = 1.0 / IN.texture_size;
}

  // Precalculate a bunch of useful values we'll need in the fragment
  // shader.
  float2 sinangle = sin(angle);
  float2 cosangle = cos(angle);
  float3 stretch = maxscale();

float intersect(float2 xy)
{
  float A = dot(xy,xy)+d*d;
  float B = 2.0*(R*(dot(xy,sinangle)-d*cosangle.x*cosangle.y)-d*d);
  float C = d*d + 2.0*R*d*cosangle.x*cosangle.y;
  return (-B-sqrt(B*B-4.0*A*C))/(2.0*A);
}

float2 bkwtrans(float2 xy)
{
  float c = intersect(xy);
  float2 point = float2(c)*xy;
  point -= float2(-R)*sinangle;
  point /= float2(R);
  float2 tang = sinangle/cosangle;
  float2 poc = point/cosangle;
  float A = dot(tang,tang)+1.0;
  float B = -2.0*dot(poc,tang);
  float C = dot(poc,poc)-1.0;
  float a = (-B+sqrt(B*B-4.0*A*C))/(2.0*A);
  float2 uv = (point-a*sinangle)/cosangle;
  float r = R*acos(a);
  return uv*r/sin(r/R);
}

float2 fwtrans(float2 uv)
{
  float r = FIX(sqrt(dot(uv,uv)));
  uv *= sin(r/R)/r;
  float x = 1.0-cos(r/R);
  float D = d/R + x*cosangle.x*cosangle.y+dot(uv,sinangle);
  return d*(uv*cosangle-x*sinangle)/D;
}

float3 maxscale()
{
  float2 c = bkwtrans(-R * sinangle / (1.0 + R/d*cosangle.x*cosangle.y));
  float2 a = float2(0.5,0.5)*aspect;
  float2 lo = float2(fwtrans(float2(-a.x,c.y)).x,
         fwtrans(float2(c.x,-a.y)).y)/aspect;
  float2 hi = float2(fwtrans(float2(+a.x,c.y)).x,
         fwtrans(float2(c.x,+a.y)).y)/aspect;
  return float3((hi+lo)*aspect*0.5,max(hi.x-lo.x,hi.y-lo.y));
}

// Nonworking but left here for reference; reverted to 'radialDistortion' function instead
float2 transform(float2 coord, uniform input IN)
{
  coord *= IN.texture_size / IN.video_size;
  coord = (coord-float2(0.5))*aspect*stretch.z+stretch.xy;
  return (bkwtrans(coord)/overscan/aspect+float2(0.5)) * IN.video_size / IN.texture_size;
}

// Apply radial distortion to the given coordinate.
float2 radialDistortion(float2 coord, uniform input IN) {
    coord *= IN.texture_size.x / IN.video_size.x;
    float2 cc = coord - 0.5;
    float dist = dot(cc, cc) * distortion;                
    return (coord + cc * (1.0 + dist) * dist) * IN.video_size.x / IN.texture_size.x;
}

float corner(float2 coord, uniform  input IN)
{
  coord *= IN.texture_size / IN.video_size;
  coord = (coord - float2(0.5)) * overscan + float2(0.5);
  coord = min(coord, float2(1.0)-coord) * aspect;
  float2 cdist = float2(cornersize);
  coord = (cdist - min(coord,cdist));
  float dist = sqrt(dot(coord,coord));
  return clamp((cdist.x-dist)*cornersmooth,0.0, 1.0);
}

// Calculate the influence of a scanline on the current pixel.
//
// 'distance' is the distance in texture coordinates from the current
// pixel to the scanline in question.
// 'color' is the colour of the scanline at the horizontal location of
// the current pixel.
float4 scanlineWeights(float distance, float4 color)
{
  // "wid" controls the width of the scanline beam, for each RGB channel
  // The "weights" lines basically specify the formula that gives
  // you the profile of the beam, i.e. the intensity as
  // a function of distance from the vertical center of the
  // scanline. In this case, it is gaussian if width=2, and
  // becomes nongaussian for larger widths. Ideally this should
  // be normalized so that the integral across the beam is
  // independent of its width. That is, for a narrower beam
  // "weights" should have a higher peak at the center of the
  // scanline than for a wider beam.
#ifdef USEGAUSSIAN
  float4 wid = 0.3 + 0.1 * pow(color, float4(3.0));
  float4 weights = float4(distance / wid);
  return 0.4 * exp(-weights * weights) / wid;
#else
  float4 wid = 2.0 + 2.0 * pow(color, float4(4.0));
  float4 weights = float4(distance / 0.3);
  return 1.4 * exp(-pow(weights * inversesqrt(0.5 * wid), wid)) / (0.6 + 0.2 * wid);
#endif
}

// FRAGMENT SHADER //

float4 main_fragment(in tex_coords co, uniform input IN, uniform sampler2D s_p : TEXUNIT0) : COLOR
{
// Paste your fragment code--the part that is inside the GLSL shader's "void main(){ ... }"--here:
// Here's a helpful diagram to keep in mind while trying to
  // understand the code:
  //
  //  |      |      |      |      |
  // -------------------------------
  //  |      |      |      |      |
  //  |  01  |  11  |  21  |  31  | <-- current scanline
  //  |      | @    |      |      |
  // -------------------------------
  //  |      |      |      |      |
  //  |  02  |  12  |  22  |  32  | <-- next scanline
  //  |      |      |      |      |
  // -------------------------------
  //  |      |      |      |      |
  //
  // Each character-cell represents a pixel on the output
  // surface, "@" represents the current pixel (always somewhere
  // in the bottom half of the current scan-line, or the top-half
  // of the next scanline). The grid of lines represents the
  // edges of the texels of the underlying texture.

  // Texture coordinates of the texel containing the active pixel.
#ifdef CURVATURE
  float2 xy = radialDistortion(co.texCoord, IN); //transform(co.texCoord, IN);
#else
  float2 xy = co.texCoord;
#endif
  float cval = corner(xy, IN);

  float2 ilfac = float2(1.0,floor(IN.video_size.y/200.0));

 // The size of one texel, in texture-coordinates.
float2 one = ilfac / IN.texture_size;
  
  // Of all the pixels that are mapped onto the texel we are
  // currently rendering, which pixel are we currently rendering?
  float2 ilvec = float2(0.0,ilfac.y > 1.5 ? mod(float(IN.frame_count),2.0) : 0.0);
  float2 ratio_scale = (xy * IN.texture_size - float2(0.5) + ilvec)/ilfac;
#ifdef OVERSAMPLE
  float filter = (IN.video_size / (IN.output_size * IN.texture_size)) *(ratio_scale.y);
#endif
  float2 uv_ratio = fract(ratio_scale);

  // Snap to the center of the underlying texel.
  xy = (floor(ratio_scale)*ilfac + float2(0.5) - ilvec) / IN.texture_size;

  // Calculate Lanczos scaling coefficients describing the effect
  // of various neighbour texels in a scanline on the current
  // pixel.
  float4 coeffs = PI * float4(1.0 + uv_ratio.x, uv_ratio.x, 1.0 - uv_ratio.x, 2.0 - uv_ratio.x);

  // Prevent division by zero.
  coeffs = FIX(coeffs);

  // Lanczos2 kernel.
  coeffs = 2.0 * sin(coeffs) * sin(coeffs / 2.0) / (coeffs * coeffs);

  // Normalize.
  coeffs /= dot(coeffs, float4(1.0));

  // Calculate the effective colour of the current and next
  // scanlines at the horizontal location of the current pixel,
  // using the Lanczos coefficients above.
float4 col  = clamp(mul(coeffs, float4x4(
                    TEX2D(xy + float2(-co.one.x, 0.0)),
                    TEX2D(xy),
                    TEX2D(xy + float2(co.one.x, 0.0)),
                    TEX2D(xy + float2(2.0 * co.one.x, 0.0)))),
            0.0, 1.0);
    float4 col2 = clamp(mul(coeffs, float4x4(
                    TEX2D(xy + float2(-co.one.x, co.one.y)),
                    TEX2D(xy + float2(0.0, co.one.y)),
                    TEX2D(xy + co.one),
                    TEX2D(xy + float2(2.0 * co.one.x, co.one.y)))),
            0.0, 1.0);

#ifndef LINEAR_PROCESSING
  col  = pow(col , float4(CRTgamma));
  col2 = pow(col2, float4(CRTgamma));
#endif

  // Calculate the influence of the current and next scanlines on
  // the current pixel.
  float4 weights  = scanlineWeights(uv_ratio.y, col);
  float4 weights2 = scanlineWeights(1.0 - uv_ratio.y, col2);
#ifdef OVERSAMPLE
  uv_ratio.y =uv_ratio.y+1.0/3.0*filter;
  weights = (weights+scanlineWeights(uv_ratio.y, col))/3.0;
  weights2=(weights2+scanlineWeights(abs(1.0-uv_ratio.y), col2))/3.0;
  uv_ratio.y =uv_ratio.y-2.0/3.0*filter;
  weights=weights+scanlineWeights(abs(uv_ratio.y), col)/3.0;
  weights2=weights2+scanlineWeights(abs(1.0-uv_ratio.y), col2)/3.0;
#endif
  float3 mul_res  = (col * weights + col2 * weights2).rgb * float3(cval);

  // dot-mask emulation:
  // Output pixels are alternately tinted green and magenta.
  float3 dotMaskWeights = lerp(
          float3(1.0, 0.7, 1.0),
          float3(0.7, 1.0, 0.7),
          floor(mod(co.mod_factor, 2.0))
      );
                    
  mul_res *= dotMaskWeights;

  // Convert the image gamma for display on our output device.
  mul_res = pow(mul_res, float3(1.0 / monitorgamma));
  
   return float4(mul_res, 1.0);
}

I had to downgrade the curvature effect to use the older ‘radialDistortion’ function instead of the ‘transform’ function, so doing the variable aspect and tilting doesn’t work, but the corner effects still work just fine.

That’s the thing, it doesn’t. It just crashes RetroArch, says I get an error with a bunch of numbers, and the log says jack shit.

But hey, I’ll take that Cg version! Now to see if it plays well with mdapt.

Help me recall again hunter what is the difference between this shader and the old cgwg shader, doesn’t it produce a more accurate scaling or something?

Actually, the Cg shader just posted is waaaaay too dark.

@GPDP Weird. Looks the same as the XML version here via Pepsi Challenge (radeon and intel GPUs). Can you post a screenshot? Can anyone else confirm/disconfirm?

@solid12345 It just gives you some more options for rounded corners and some very slight variations on scanline bloom (linear vs gaussian, IIRC) and a few other things. One of the major improvements is supposed to be the ability to tilt the screen but I couldn’t get that to work for whatever reason. So, nothing super-awesome, but a few nice little tweaks.

Oooook, so admittedly I made a couple of tweaks (which I had made to the XML version without issue) without testing the shader as it was at first, and it resulted in a dark image. I went ahead and reverted to the original code, and it looks fine. I then made the desired tweaks again, and everything is as it should be. I think I must have changed something the first time around I shouldn’t have changed, probably something related to the corner and curvature settings, which was wholly unnecessary as I could just comment out the #CURVATURE define for that. In any case, it’s working now. Sorry about that.

Excellent. No problem. If it was related to corners and curvature, it was likely the cornersmooth setting, which can make everything really dim/dark (as opposed to too-much-gamma-dark) if the setting is too low.

EDIT: It looks like chaining it with pretty much anything messes up the interlacing detection, so here’s a version that makes that a toggle option (off by default):

/* COMPATIBILITY 
   - HLSL compilers
   - Cg   compilers
*/

// This is a good place for any #defines you might have
#define FIX(c) max(abs(c), 1e-5);

// Comment the next line to disable interpolation in linear gamma (and gain speed).
//#define LINEAR_PROCESSING

// Enable screen curvature.
#define CURVATURE

// Enable 3x oversampling of the beam profile
#define OVERSAMPLE

// Use the older, purely gaussian beam profile
//#define USEGAUSSIAN

// Use interlacing detection; may interfere with other shaders if combined
//#define INTERLACED

#define distortion 0.1

// Macros.
#define FIX(c) max(abs(c), 1e-5);
#define PI 3.141592653589

#ifdef LINEAR_PROCESSING
#       define TEX2D(c) pow(tex2D(IN.texture, (c)), float4(CRTgamma))
#else
#       define TEX2D(c) tex2D(IN.texture, (c))
#endif

  // gamma of simulated CRT
#define CRTgamma 2.4

  // gamma of display monitor (typically 2.2 is correct)
#define monitorgamma 2.2

  // overscan (e.g. 1.02 for 2% overscan)
#define overscan float2(1.00,1.00)

  // aspect ratio ; needs 'transform' function
#define aspect float2(1.0, 0.75)

  // size of curved corners
#define cornersize 0.02
  
  // border smoothness parameter
  // decrease if borders are too aliased
#define cornersmooth 80.0

  // lengths are measured in units of (approximately) the width of the monitor
  // simulated distance from viewer to monitor ; needs 'transform' function
#define d 2.0

  // radius of curvature ; needs 'transform' function. use 'distortion' instead
#define R 1.5

  // tilt angle in radians
  // (behavior might be a bit wrong if both components are nonzero) ; needs 'transform' function
#define angle float2(0.0,-0.15)

struct input      // These are things that can attach to 'IN' to achieve similar function to ruby* stuff in existing GLSL shaders. NOTE: the ruby* prefix is deprecated but still works in GLSL for legacy compatibility purposes.
{
  float2 video_size;
  float2 texCoord_size;
  float2 output_size;
  float frame_count;
  float frame_direction;
  float frame_rotation;
  float texture_size;
  sampler2D texture : TEXUNIT0;
};

struct tex_coords
{
   float2 texCoord  : TEXCOORD0; 
   float mod_factor : TEXCOORD1;
   float2 one       : TEXCOORD2;
};

// VERTEX SHADER //

void main_vertex
(
   float4 position : POSITION,
   out float4 oPosition : POSITION,
   uniform float4x4 modelViewProj,

   float4 color : COLOR,
   out float4 oColor : COLOR,

   float2 tex : TEXCOORD,

   uniform input IN,
   out tex_coords coords
 )
{
   oPosition = mul(modelViewProj, position);
   oColor = color;

   coords.texCoord = tex + float2(0.0, 0.0);
   coords.mod_factor = tex.x * IN.output_size.x * IN.texture_size.x / IN.video_size.x;
   coords.one = 1.0 / IN.texture_size;
}

  // Precalculate a bunch of useful values we'll need in the fragment
  // shader.
  float2 sinangle = sin(angle);
  float2 cosangle = cos(angle);
  float3 stretch = maxscale();

float intersect(float2 xy)
{
  float A = dot(xy,xy)+d*d;
  float B = 2.0*(R*(dot(xy,sinangle)-d*cosangle.x*cosangle.y)-d*d);
  float C = d*d + 2.0*R*d*cosangle.x*cosangle.y;
  return (-B-sqrt(B*B-4.0*A*C))/(2.0*A);
}

float2 bkwtrans(float2 xy)
{
  float c = intersect(xy);
  float2 point = float2(c)*xy;
  point -= float2(-R)*sinangle;
  point /= float2(R);
  float2 tang = sinangle/cosangle;
  float2 poc = point/cosangle;
  float A = dot(tang,tang)+1.0;
  float B = -2.0*dot(poc,tang);
  float C = dot(poc,poc)-1.0;
  float a = (-B+sqrt(B*B-4.0*A*C))/(2.0*A);
  float2 uv = (point-a*sinangle)/cosangle;
  float r = R*acos(a);
  return uv*r/sin(r/R);
}

float2 fwtrans(float2 uv)
{
  float r = FIX(sqrt(dot(uv,uv)));
  uv *= sin(r/R)/r;
  float x = 1.0-cos(r/R);
  float D = d/R + x*cosangle.x*cosangle.y+dot(uv,sinangle);
  return d*(uv*cosangle-x*sinangle)/D;
}

float3 maxscale()
{
  float2 c = bkwtrans(-R * sinangle / (1.0 + R/d*cosangle.x*cosangle.y));
  float2 a = float2(0.5,0.5)*aspect;
  float2 lo = float2(fwtrans(float2(-a.x,c.y)).x,
         fwtrans(float2(c.x,-a.y)).y)/aspect;
  float2 hi = float2(fwtrans(float2(+a.x,c.y)).x,
         fwtrans(float2(c.x,+a.y)).y)/aspect;
  return float3((hi+lo)*aspect*0.5,max(hi.x-lo.x,hi.y-lo.y));
}

// Nonworking but left here for reference; reverted to 'radialDistortion' function instead
float2 transform(float2 coord, uniform input IN)
{
  coord *= IN.texture_size / IN.video_size;
  coord = (coord-float2(0.5))*aspect*stretch.z+stretch.xy;
  return (bkwtrans(coord)/overscan/aspect+float2(0.5)) * IN.video_size / IN.texture_size;
}

// Apply radial distortion to the given coordinate.
float2 radialDistortion(float2 coord, uniform input IN) {
    coord *= IN.texture_size.x / IN.video_size.x;
    float2 cc = coord - 0.5;
    float dist = dot(cc, cc) * distortion;                
    return (coord + cc * (1.0 + dist) * dist) * IN.video_size.x / IN.texture_size.x;
}

float corner(float2 coord, uniform  input IN)
{
  coord *= IN.texture_size / IN.video_size;
  coord = (coord - float2(0.5)) * overscan + float2(0.5);
  coord = min(coord, float2(1.0)-coord) * aspect;
  float2 cdist = float2(cornersize);
  coord = (cdist - min(coord,cdist));
  float dist = sqrt(dot(coord,coord));
  return clamp((cdist.x-dist)*cornersmooth,0.0, 1.0);
}

// Calculate the influence of a scanline on the current pixel.
//
// 'distance' is the distance in texture coordinates from the current
// pixel to the scanline in question.
// 'color' is the colour of the scanline at the horizontal location of
// the current pixel.
float4 scanlineWeights(float distance, float4 color)
{
  // "wid" controls the width of the scanline beam, for each RGB channel
  // The "weights" lines basically specify the formula that gives
  // you the profile of the beam, i.e. the intensity as
  // a function of distance from the vertical center of the
  // scanline. In this case, it is gaussian if width=2, and
  // becomes nongaussian for larger widths. Ideally this should
  // be normalized so that the integral across the beam is
  // independent of its width. That is, for a narrower beam
  // "weights" should have a higher peak at the center of the
  // scanline than for a wider beam.
#ifdef USEGAUSSIAN
  float4 wid = 0.3 + 0.1 * pow(color, float4(3.0));
  float4 weights = float4(distance / wid);
  return 0.4 * exp(-weights * weights) / wid;
#else
  float4 wid = 2.0 + 2.0 * pow(color, float4(4.0));
  float4 weights = float4(distance / 0.3);
  return 1.4 * exp(-pow(weights * inversesqrt(0.5 * wid), wid)) / (0.6 + 0.2 * wid);
#endif
}

// FRAGMENT SHADER //

float4 main_fragment(in tex_coords co, uniform input IN, uniform sampler2D s_p : TEXUNIT0) : COLOR
{
// Paste your fragment code--the part that is inside the GLSL shader's "void main(){ ... }"--here:
// Here's a helpful diagram to keep in mind while trying to
  // understand the code:
  //
  //  |      |      |      |      |
  // -------------------------------
  //  |      |      |      |      |
  //  |  01  |  11  |  21  |  31  | <-- current scanline
  //  |      | @    |      |      |
  // -------------------------------
  //  |      |      |      |      |
  //  |  02  |  12  |  22  |  32  | <-- next scanline
  //  |      |      |      |      |
  // -------------------------------
  //  |      |      |      |      |
  //
  // Each character-cell represents a pixel on the output
  // surface, "@" represents the current pixel (always somewhere
  // in the bottom half of the current scan-line, or the top-half
  // of the next scanline). The grid of lines represents the
  // edges of the texels of the underlying texture.

  // Texture coordinates of the texel containing the active pixel.
#ifdef CURVATURE
  float2 xy = radialDistortion(co.texCoord, IN); //transform(co.texCoord, IN);
#else
  float2 xy = co.texCoord;
#endif
  float cval = corner(xy, IN);

  float2 ilfac = float2(1.0,floor(IN.video_size.y/200.0));

 // The size of one texel, in texture-coordinates.
  float2 one = ilfac / IN.texture_size;

  float2 ilvec = float2(0.0,ilfac.y > 1.5 ? mod(float(IN.frame_count),2.0) : 0.0);
  
  // Of all the pixels that are mapped onto the texel we are
  // currently rendering, which pixel are we currently rendering?
#ifdef INTERLACED
  float2 ratio_scale = (xy * IN.texture_size - float2(0.5) + ilvec)/ilfac;
#else
  float2 ratio_scale = xy * IN.texture_size - float2(0.5);
#endif

#ifdef OVERSAMPLE
  float filter = (IN.video_size / (IN.output_size * IN.texture_size)) *(ratio_scale.y);
#endif
  float2 uv_ratio = fract(ratio_scale);

  // Snap to the center of the underlying texel.
#ifdef INTERLACED
  xy = (floor(ratio_scale)*ilfac + float2(0.5) - ilvec) / IN.texture_size;
#else
  xy = (floor(ratio_scale) + float2(0.5)) / IN.texture_size;
#endif

  // Calculate Lanczos scaling coefficients describing the effect
  // of various neighbour texels in a scanline on the current
  // pixel.
  float4 coeffs = PI * float4(1.0 + uv_ratio.x, uv_ratio.x, 1.0 - uv_ratio.x, 2.0 - uv_ratio.x);

  // Prevent division by zero.
  coeffs = FIX(coeffs);

  // Lanczos2 kernel.
  coeffs = 2.0 * sin(coeffs) * sin(coeffs / 2.0) / (coeffs * coeffs);

  // Normalize.
  coeffs /= dot(coeffs, float4(1.0));

  // Calculate the effective colour of the current and next
  // scanlines at the horizontal location of the current pixel,
  // using the Lanczos coefficients above.
float4 col  = clamp(mul(coeffs, float4x4(
                    TEX2D(xy + float2(-co.one.x, 0.0)),
                    TEX2D(xy),
                    TEX2D(xy + float2(co.one.x, 0.0)),
                    TEX2D(xy + float2(2.0 * co.one.x, 0.0)))),
            0.0, 1.0);
    float4 col2 = clamp(mul(coeffs, float4x4(
                    TEX2D(xy + float2(-co.one.x, co.one.y)),
                    TEX2D(xy + float2(0.0, co.one.y)),
                    TEX2D(xy + co.one),
                    TEX2D(xy + float2(2.0 * co.one.x, co.one.y)))),
            0.0, 1.0);

#ifndef LINEAR_PROCESSING
  col  = pow(col , float4(CRTgamma));
  col2 = pow(col2, float4(CRTgamma));
#endif

  // Calculate the influence of the current and next scanlines on
  // the current pixel.
  float4 weights  = scanlineWeights(uv_ratio.y, col);
  float4 weights2 = scanlineWeights(1.0 - uv_ratio.y, col2);
#ifdef OVERSAMPLE
  uv_ratio.y =uv_ratio.y+1.0/3.0*filter;
  weights = (weights+scanlineWeights(uv_ratio.y, col))/3.0;
  weights2=(weights2+scanlineWeights(abs(1.0-uv_ratio.y), col2))/3.0;
  uv_ratio.y =uv_ratio.y-2.0/3.0*filter;
  weights=weights+scanlineWeights(abs(uv_ratio.y), col)/3.0;
  weights2=weights2+scanlineWeights(abs(1.0-uv_ratio.y), col2)/3.0;
#endif
  float3 mul_res  = (col * weights + col2 * weights2).rgb * float3(cval);

  // dot-mask emulation:
  // Output pixels are alternately tinted green and magenta.
  float3 dotMaskWeights = lerp(
          float3(1.0, 0.7, 1.0),
          float3(0.7, 1.0, 0.7),
          floor(mod(co.mod_factor, 2.0))
      );
                    
  mul_res *= dotMaskWeights;

  // Convert the image gamma for display on our output device.
  mul_res = pow(mul_res, float3(1.0 / monitorgamma));
  
   return float4(mul_res, 1.0);
}

Yeah, I was gonna say lowering the cornersmooth was actually what was causing the image darkening. I really would prefer not to have any.

If you want it to be completely flat with no corner rounding, set the cornersmooth to something high, like 1000.0 and the cornersize to something very small, like 0.001.

It seems to work pretty well combined with mdapt. Just take the mdapt+sabr that Sp00ky Fox posted and replace sabr.cg with the CRT shader and set scale_type4 to viewport instead of source.

Where is that one in particular? I can’t seem to find it in the thread. You’re not referring to 1.5, right? Because that one appears to have issues with vertical bar dithering like that used heavily in The Lion King.

@GPDP I’m not even sure which version it is, actually. It’s just what I happened to have on my local machine. Anyway, here it is (mdapt+CRT-geom): http://www.mediafire.com/download/14r5ehe75h9dcqb/mdapt%2BCRT-geom.zip

If I load the mdapt.cgp into the RetroArch PC v0.9.9 it crashes.

@xadox You mean the one from the post above yours? If so, it works fine here. Anything informative in your log?

Is anyone else having this problem?

Yes the one from above. Log? Where can I find it?

Normally, you can check the log through RetroArch-Phoenix, but if the whole program is crashing, you probably won’t get anything useful there. Probably the most informative thing would be to launch RetroArch from the command line with the -v switch and then see what it says if/when it crashes.

Here the log.

D:\RetroArch>retroarch.exe -v "games\Super Mario World (USA).sfc"
=== Build =======================================
Compiler: MinGW (4.8.0) 64-bit
Built: May 29 2013
=================================================
RetroArch: [CPUID]: Vendor: GenuineIntel
RetroArch: [CPUID]: SSE:  1
RetroArch: [CPUID]: SSE2: 1
RetroArch: [CPUID]: AVX:  0
RetroArch: Loading default config.
=== Config ===
video_driver = "gl"
audio_driver = "dsound"
rewind_enable = "false"
rewind_granularity = "1"
video_shader_enable = "true"
video_aspect_ratio = "-1.000000"
video_scale_integer = "false"
video_smooth = "false"
video_vsync = "true"
video_hard_sync = "false"
video_hard_sync_frames = "0"
aspect_ratio_index = "4"
audio_rate_control = "true"
audio_rate_control_delta = "0.005000"
system_directory = "D:\RetroArch"
savefile_directory = "D:\RetroArch\games"
savestate_directory = "D:\RetroArch\games"
rgui_browser_directory = "D:\RetroArch"
overlay_directory = "D:\RetroArch\games"
overlay_opacity = "1.000000"
overlay_scale = "1.000000"
gamma_correction = "false"
throttle_enable = "false"
triple_buffering_enable = "false"
info_msg_enable = "false"
soft_filter_enable = "false"
flicker_filter_enable = "false"
flicker_filter_index = "0"
soft_filter_index = "0"
current_resolution_id = "0"
custom_viewport_width = "768"
custom_viewport_height = "672"
custom_viewport_x = "0"
custom_viewport_y = "0"
video_font_size = "48.000000"
config_save_on_exit = "true"
sound_mode = "0"
state_slot = "0"
audio_mute = "0"
screen_orientation = "0"
custom_bgm_enable = "false"
input_dpad_emulation_p1 = "0"
input_device_p1 = "0"
input_dpad_emulation_p2 = "0"
input_device_p2 = "0"
input_dpad_emulation_p3 = "0"
input_device_p3 = "0"
input_dpad_emulation_p4 = "0"
input_device_p4 = "0"
input_dpad_emulation_p5 = "0"
input_device_p5 = "0"
input_dpad_emulation_p6 = "0"
input_device_p6 = "0"
input_dpad_emulation_p7 = "0"
input_device_p7 = "0"
input_dpad_emulation_p8 = "0"
input_device_p8 = "0"
libretro_path = "D:\RetroArch\snes9x_libretro_x86_64_20130629.dll"
=== Config end ===
RetroArch: Found default config: D:\RetroArch\retroarch.cfg.
RetroArch: Loading dynamic libretro from: "D:\RetroArch\snes9x_libretro_x86_64_20130629.dll"
RetroArch: Version of libretro API: 1
RetroArch: Compiled against API: 1
RetroArch: Environ GET_OVERSCAN: 0
Sound buffer size: 2048 (512 samples)
RetroArch: Loading ROM file: games\Super Mario World (USA).sfc.
RetroArch: Did not find a valid ROM patch.
RetroArch: CRC32: 0xb19ed489, SHA256: 0838e531fe22c077528febe14cb3ff7c492f1f5fa8de354192bdff7137c27f5b
RetroArch: ROM size: 524288 bytes.
Map_LoROMMap
RetroArch: Environ SET_PIXEL_FORMAT: RGB565.
RetroArch: Set audio input rate to: 31961.16 Hz.
RetroArch: Adjusting aspect ratio to 1.14
RetroArch: Video @ 768x672
RetroArch: Setting multimedia scheduling for DWM.
RetroArch: Found GL context: wgl
RetroArch: Detecting screen resolution 1600x900.
RetroArch: [WGL]: wglSwapInterval(1)
RetroArch: Querying GL extension: ARB_sync => exists
RetroArch: GL: Using resolution 768x672
RetroArch: [GL]: Not loading any shader.
RetroArch: GL: Loaded 0 program(s).
RetroArch: Enumerating DInput joypads ...
RetroArch: Done enumerating DInput joypads ...
RetroArch: Found joypad driver: "dinput".
RetroArch: Using font rendering backend: freetype.
RetroArch: DirectSound devices:
RetroArch:      0: Primõrer Soundtreiber
RetroArch:      1: Lautsprecher (High Definition Audio-Gerõt)
RetroArch: [DirectSound]: Setting buffer size of 12288 bytes
RetroArch: [DirectSound]: Latency = 64 ms
RetroArch: Sinc resampler [SSE]
RetroArch: SINC params (8 phase bits, 16 taps).
RetroArch: [RGUI]: Opening history: D:\RetroArch\.retroarch-history.txt.
RetroArch: GL VSync => on
RetroArch: [WGL]: wglSwapInterval(1)
RetroArch: Setting RGUI shader: D:\RetroArch\shaders\crt-geom\mdapt.cgp.
RetroArch: [Cg]: Vertex profile: gp4vp
RetroArch: [Cg]: Fragment profile: gp4fp
RetroArch: CG: Found semantic "POSITION" in prog #0.
RetroArch: CG: Found semantic "TEXCOORD0" in prog #0.
RetroArch: CG: Found semantic "COLOR" in prog #0.
RetroArch: Loading Cg meta-shader: D:\RetroArch\shaders\crt-geom\mdapt.cgp
RetroArch: Loading Cg shader: "D:\RetroArch\shaders\crt-geom\mdapt_pass1.cg".
RetroArch: Loading Cg shader: "D:\RetroArch\shaders\crt-geom\mdapt_pass2.cg".
RetroArch: Loading Cg shader: "D:\RetroArch\shaders\crt-geom\mdapt_pass3.cg".
RetroArch: Loading Cg shader: "D:\RetroArch\shaders\crt-geom\mdapt_pass4.cg".
RetroArch: Loading Cg shader: "D:\RetroArch\shaders\crt-geom\CRT-geom-interlaced.cg".
RetroArch: CG: Found semantic "POSITION" in prog #1.
RetroArch: CG: Found semantic "TEXCOORD0" in prog #1.
RetroArch: CG: Found semantic "POSITION" in prog #2.
RetroArch: CG: Found semantic "TEXCOORD0" in prog #2.
RetroArch: CG: Found semantic "POSITION" in prog #3.
RetroArch: CG: Found semantic "TEXCOORD0" in prog #3.
RetroArch: CG: Found semantic "POSITION" in prog #4.
RetroArch: CG: Found semantic "TEXCOORD0" in prog #4.
RetroArch: CG: Found semantic "POSITION" in prog #5.
RetroArch: CG: Found semantic "COLOR" in prog #5.
RetroArch: CG: Found semantic "TEXCOORD" in prog #5.
RetroArch: Creating FBO 0 @ 512x512
RetroArch: Creating FBO 1 @ 512x512
RetroArch: Creating FBO 2 @ 512x512
RetroArch: Creating FBO 3 @ 512x512
RetroArch: Creating FBO 4 @ 1024x1024
RetroArch: Querying GL extension: ARB_texture_float => exists
RetroArch: FBO pass #0 is floating-point.
RetroArch: Querying GL extension: ARB_texture_float => exists
RetroArch: FBO pass #1 is floating-point.
RetroArch: Querying GL extension: ARB_texture_float => exists
RetroArch: FBO pass #2 is floating-point.

That all looks fine. I’m not seeing any errors or anything. This log comes from a crash?

I am starting RetroArch from cmd, then I am loading the shader preset from rgui and than it crashes. Same with bsnes. Same with nestopia and nes rom. Same on differend hardware.

I can’t seem to reproduce the issue. Which operating system are you using? Windows? 32-bit or 64? What graphics hardware have you tested it on?