Update crt-geom.slang

Changed the formatting, tab size is 4 spaces.
Based on the discussion in IRC, I carefully deleted every instance of global.SourceSize.zw, because z = 1/x and w = 1/y and zw is NOT the same as IN.video_size.
This commit is contained in:
rz5 2016-07-16 00:01:38 +01:00 committed by GitHub
parent f14ba96715
commit c864dbb2d4

View file

@ -2,11 +2,11 @@
layout(std140, set = 0, binding = 0) uniform UBO layout(std140, set = 0, binding = 0) uniform UBO
{ {
mat4 MVP; mat4 MVP;
vec4 OutputSize; vec4 OutputSize;
vec4 OriginalSize; vec4 OriginalSize;
vec4 SourceSize; vec4 SourceSize;
uint FrameCount; uint FrameCount;
} global; } global;
#define CRTgamma 2.4 #define CRTgamma 2.4
@ -37,42 +37,42 @@ layout(std140, set = 0, binding = 0) uniform UBO
(cgwg gave their consent to have the original version of this shader (cgwg gave their consent to have the original version of this shader
distributed under the GPL in this message: distributed under the GPL in this message:
http://board.byuu.org/viewtopic.php?p=26075#p26075 http://board.byuu.org/viewtopic.php?p=26075#p26075
"Feel free to distribute my shaders under the GPL. After all, the "Feel free to distribute my shaders under the GPL. After all, the
barrel distortion code was taken from the Curvature shader, which is barrel distortion code was taken from the Curvature shader, which is
under the GPL." under the GPL."
) )
This shader variant is pre-configured with screen curvature This shader variant is pre-configured with screen curvature
*/ */
// Comment the next line to disable interpolation in linear gamma (and // Comment the next line to disable interpolation in linear gamma (and
// gain speed). // gain speed).
#define LINEAR_PROCESSING #define LINEAR_PROCESSING
// Enable 3x oversampling of the beam profile; improves moire effect caused by scanlines+curvature // Enable 3x oversampling of the beam profile; improves moire effect caused by scanlines+curvature
#define OVERSAMPLE #define OVERSAMPLE
// Use the older, purely gaussian beam profile; uncomment for speed // Use the older, purely gaussian beam profile; uncomment for speed
#define USEGAUSSIAN #define USEGAUSSIAN
// Use interlacing detection; may interfere with other shaders if combined // Use interlacing detection; may interfere with other shaders if combined
#define INTERLACED #define INTERLACED
// Macros. // Macros.
#define FIX(c) max(abs(c), 1e-5); #define FIX(c) max(abs(c), 1e-5);
#define PI 3.141592653589 #define PI 3.141592653589
#ifdef LINEAR_PROCESSING #ifdef LINEAR_PROCESSING
# define TEX2D(c) pow(texture(Source, (c)), vec4(CRTgamma)) # define TEX2D(c) pow(texture(Source, (c)), vec4(CRTgamma))
#else #else
# define TEX2D(c) texture(Source, (c)) # define TEX2D(c) texture(Source, (c))
#endif #endif
// aspect ratio // aspect ratio
vec2 aspect = vec2(1.0, 0.75); vec2 aspect = vec2(1.0, 0.75);
vec2 angle = vec2(0.0, 0.0); vec2 angle = vec2(0.0, 0.0);
vec2 overscan = vec2(1.01, 1.01); vec2 overscan = vec2(1.01, 1.01);
#pragma stage vertex #pragma stage vertex
layout(location = 0) in vec4 Position; layout(location = 0) in vec4 Position;
@ -86,97 +86,105 @@ layout(location = 5) out vec2 one;
layout(location = 6) out float mod_factor; layout(location = 6) out float mod_factor;
float intersect(vec2 xy) float intersect(vec2 xy)
{ {
float A = dot(xy,xy)+d*d; float A = dot(xy,xy) + d*d;
float B = 2.0*(R*(dot(xy,sinangle)-d*cosangle.x*cosangle.y)-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; float C = d*d + 2.0*R*d*cosangle.x*cosangle.y;
return (-B-sqrt(B*B-4.0*A*C))/(2.0*A);
} return (-B-sqrt(B*B-4.0*A*C))/(2.0*A);
}
vec2 bkwtrans(vec2 xy) vec2 bkwtrans(vec2 xy)
{ {
float c = intersect(xy); float c = intersect(xy);
vec2 point = vec2(c)*xy; vec2 point = vec2(c)*xy;
point -= vec2(-R)*sinangle; point -= vec2(-R)*sinangle;
point /= vec2(R); point /= vec2(R);
vec2 tang = sinangle/cosangle; vec2 tang = sinangle/cosangle;
vec2 poc = point/cosangle; vec2 poc = point/cosangle;
float A = dot(tang,tang)+1.0;
float B = -2.0*dot(poc,tang); float A = dot(tang,tang)+1.0;
float C = dot(poc,poc)-1.0; float B = -2.0*dot(poc,tang);
float a = (-B+sqrt(B*B-4.0*A*C))/(2.0*A); float C = dot(poc,poc)-1.0;
vec2 uv = (point-a*sinangle)/cosangle;
float r = R*acos(a); float a = (-B+sqrt(B*B-4.0*A*C))/(2.0*A);
return uv*r/sin(r/R); vec2 uv = (point-a*sinangle)/cosangle;
} float r = R*acos(a);
return uv*r/sin(r/R);
}
vec2 fwtrans(vec2 uv) vec2 fwtrans(vec2 uv)
{ {
float r = FIX(sqrt(dot(uv,uv))); float r = FIX(sqrt(dot(uv,uv)));
uv *= sin(r/R)/r; uv *= sin(r/R)/r;
float x = 1.0-cos(r/R); float x = 1.0-cos(r/R);
float D = d/R + x*cosangle.x*cosangle.y+dot(uv,sinangle); float D = d/R + x*cosangle.x*cosangle.y+dot(uv,sinangle);
return d*(uv*cosangle-x*sinangle)/D;
} return d*(uv*cosangle-x*sinangle)/D;
}
vec3 maxscale() vec3 maxscale()
{ {
vec2 c = bkwtrans(-R * sinangle / (1.0 + R/d*cosangle.x*cosangle.y)); vec2 c = bkwtrans(-R * sinangle / (1.0 + R/d*cosangle.x*cosangle.y));
vec2 a = vec2(0.5,0.5)*aspect; vec2 a = vec2(0.5,0.5)*aspect;
vec2 lo = vec2(fwtrans(vec2(-a.x,c.y)).x, vec2 lo = vec2(fwtrans(vec2(-a.x,c.y)).x,
fwtrans(vec2(c.x,-a.y)).y)/aspect; fwtrans(vec2(c.x,-a.y)).y)/aspect;
vec2 hi = vec2(fwtrans(vec2(+a.x,c.y)).x, vec2 hi = vec2(fwtrans(vec2(+a.x,c.y)).x,
fwtrans(vec2(c.x,+a.y)).y)/aspect; fwtrans(vec2(c.x,+a.y)).y)/aspect;
return vec3((hi+lo)*aspect*0.5,max(hi.x-lo.x,hi.y-lo.y));
} return vec3((hi+lo)*aspect*0.5,max(hi.x-lo.x,hi.y-lo.y));
}
// Calculate the influence of a scanline on the current pixel. // Calculate the influence of a scanline on the current pixel.
// //
// 'distance' is the distance in texture coordinates from the current // 'distance' is the distance in texture coordinates from the current
// pixel to the scanline in question. // pixel to the scanline in question.
// 'color' is the colour of the scanline at the horizontal location of // 'color' is the colour of the scanline at the horizontal location of
// the current pixel. // the current pixel.
vec4 scanlineWeights(float distance, vec4 color) vec4 scanlineWeights(float distance, vec4 color)
{ {
// "wid" controls the width of the scanline beam, for each RGB // "wid" controls the width of the scanline beam, for each RGB
// channel The "weights" lines basically specify the formula // channel The "weights" lines basically specify the formula
// that gives you the profile of the beam, i.e. the intensity as // that gives you the profile of the beam, i.e. the intensity as
// a function of distance from the vertical center of the // a function of distance from the vertical center of the
// scanline. In this case, it is gaussian if width=2, and // scanline. In this case, it is gaussian if width=2, and
// becomes nongaussian for larger widths. Ideally this should // becomes nongaussian for larger widths. Ideally this should
// be normalized so that the integral across the beam is // be normalized so that the integral across the beam is
// independent of its width. That is, for a narrower beam // independent of its width. That is, for a narrower beam
// "weights" should have a higher peak at the center of the // "weights" should have a higher peak at the center of the
// scanline than for a wider beam. // scanline than for a wider beam.
#ifdef USEGAUSSIAN #ifdef USEGAUSSIAN
vec4 wid = 0.3 + 0.1 * pow(color, vec4(3.0)); vec4 wid = 0.3 + 0.1 * pow(color, vec4(3.0));
vec4 weights = vec4(distance / wid); vec4 weights = vec4(distance / wid);
return 0.4 * exp(-weights * weights) / wid;
#else return 0.4 * exp(-weights * weights) / wid;
vec4 wid = 2.0 + 2.0 * pow(color, vec4(4.0)); #else
vec4 weights = vec4(distance / scanline_weight); vec4 wid = 2.0 + 2.0 * pow(color, vec4(4.0));
return 1.4 * exp(-pow(weights * inversesqrt(0.5 * wid), wid)) / (0.6 + 0.2 * wid); vec4 weights = vec4(distance / scanline_weight);
#endif
} return 1.4 * exp(-pow(weights * inversesqrt(0.5 * wid), wid)) / (0.6 + 0.2 * wid);
#endif
}
void main() void main()
{ {
gl_Position = global.MVP * Position; gl_Position = global.MVP * Position;
vTexCoord = TexCoord; vTexCoord = TexCoord;
// Precalculate a bunch of useful values we'll need in the fragment
// shader.
sinangle = sin(angle);
cosangle = cos(angle);
stretch = maxscale();
ilfac = vec2(1.0,(global.SourceSize.y/200.0)); // Precalculate a bunch of useful values we'll need in the fragment
// shader.
sinangle = sin(angle);
cosangle = cos(angle);
stretch = maxscale();
// The size of one texel, in texture-coordinates. ilfac = vec2(1.0,(global.SourceSize.y/200.0));
one = ilfac / global.SourceSize.xy;
// Resulting X pixel-coordinate of the pixel we're drawing. // The size of one texel, in texture-coordinates.
mod_factor = TexCoord.x * (global.SourceSize.x / global.SourceSize.z) * (global.SourceSize.z / global.SourceSize.x); one = ilfac / global.SourceSize.xy;
// Resulting X pixel-coordinate of the pixel we're drawing.
mod_factor = TexCoord.x * global.SourceSize.x * global.OutputSize.x / global.SourceSize.x;
} }
#pragma stage fragment #pragma stage fragment
@ -191,205 +199,222 @@ layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source; layout(set = 0, binding = 2) uniform sampler2D Source;
float intersect(vec2 xy) float intersect(vec2 xy)
{ {
float A = dot(xy,xy)+d*d; float A = dot(xy,xy) + d*d;
float B = 2.0*(R*(dot(xy,sinangle)-d*cosangle.x*cosangle.y)-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; float C = d*d + 2.0*R*d*cosangle.x*cosangle.y;
return (-B-sqrt(B*B-4.0*A*C))/(2.0*A);
} return (-B-sqrt(B*B - 4.0*A*C))/(2.0*A);
}
vec2 bkwtrans(vec2 xy) vec2 bkwtrans(vec2 xy)
{ {
float c = intersect(xy); float c = intersect(xy);
vec2 point = vec2(c)*xy; vec2 point = vec2(c)*xy;
point -= vec2(-R)*sinangle;
point /= vec2(R); point -= vec2(-R)*sinangle;
vec2 tang = sinangle/cosangle; point /= vec2(R);
vec2 poc = point/cosangle;
float A = dot(tang,tang)+1.0; vec2 tang = sinangle/cosangle;
float B = -2.0*dot(poc,tang); vec2 poc = point/cosangle;
float C = dot(poc,poc)-1.0;
float a = (-B+sqrt(B*B-4.0*A*C))/(2.0*A); float A = dot(tang,tang)+1.0;
vec2 uv = (point-a*sinangle)/cosangle; float B = -2.0*dot(poc,tang);
float r = R*acos(a); float C = dot(poc,poc)-1.0;
return uv*r/sin(r/R);
} float a = (-B+sqrt(B*B-4.0*A*C))/(2.0*A);
vec2 uv = (point-a*sinangle)/cosangle;
float r = R*acos(a);
return uv*r/sin(r/R);
}
vec2 fwtrans(vec2 uv) vec2 fwtrans(vec2 uv)
{ {
float r = FIX(sqrt(dot(uv,uv))); float r = FIX(sqrt(dot(uv,uv)));
uv *= sin(r/R)/r; uv *= sin(r/R)/r;
float x = 1.0-cos(r/R); float x = 1.0-cos(r/R);
float D = d/R + x*cosangle.x*cosangle.y+dot(uv,sinangle); float D = d/R + x*cosangle.x*cosangle.y + dot(uv,sinangle);
return d*(uv*cosangle-x*sinangle)/D;
} return d*(uv*cosangle-x*sinangle)/D;
}
vec3 maxscale() vec3 maxscale()
{ {
vec2 c = bkwtrans(-R * sinangle / (1.0 + R/d*cosangle.x*cosangle.y)); vec2 c = bkwtrans(-R * sinangle / (1.0 + R/d*cosangle.x*cosangle.y));
vec2 a = vec2(0.5,0.5)*aspect; vec2 a = vec2(0.5,0.5)*aspect;
vec2 lo = vec2(fwtrans(vec2(-a.x,c.y)).x,
fwtrans(vec2(c.x,-a.y)).y)/aspect;
vec2 hi = vec2(fwtrans(vec2(+a.x,c.y)).x,
fwtrans(vec2(c.x,+a.y)).y)/aspect;
return vec3((hi+lo)*aspect*0.5,max(hi.x-lo.x,hi.y-lo.y));
}
// Calculate the influence of a scanline on the current pixel. vec2 lo = vec2(fwtrans(vec2(-a.x,c.y)).x,
// fwtrans(vec2(c.x, -a.y)).y)/aspect;
// 'distance' is the distance in texture coordinates from the current vec2 hi = vec2(fwtrans(vec2(+a.x,c.y)).x,
// pixel to the scanline in question. fwtrans(vec2(c.x, +a.y)).y)/aspect;
// 'color' is the colour of the scanline at the horizontal location of
// the current pixel. return vec3((hi+lo)*aspect*0.5,max(hi.x-lo.x, hi.y-lo.y));
vec4 scanlineWeights(float distance, vec4 color) }
{
// "wid" controls the width of the scanline beam, for each RGB // Calculate the influence of a scanline on the current pixel.
// channel The "weights" lines basically specify the formula //
// that gives you the profile of the beam, i.e. the intensity as // 'distance' is the distance in texture coordinates from the current
// a function of distance from the vertical center of the // pixel to the scanline in question.
// scanline. In this case, it is gaussian if width=2, and // 'color' is the colour of the scanline at the horizontal location of
// becomes nongaussian for larger widths. Ideally this should // the current pixel.
// be normalized so that the integral across the beam is vec4 scanlineWeights(float distance, vec4 color)
// independent of its width. That is, for a narrower beam {
// "weights" should have a higher peak at the center of the // "wid" controls the width of the scanline beam, for each RGB
// scanline than for a wider beam. // channel The "weights" lines basically specify the formula
#ifdef USEGAUSSIAN // that gives you the profile of the beam, i.e. the intensity as
vec4 wid = 0.3 + 0.1 * pow(color, vec4(3.0)); // a function of distance from the vertical center of the
vec4 weights = vec4(distance / wid); // scanline. In this case, it is gaussian if width=2, and
return 0.4 * exp(-weights * weights) / wid; // becomes nongaussian for larger widths. Ideally this should
#else // be normalized so that the integral across the beam is
vec4 wid = 2.0 + 2.0 * pow(color, vec4(4.0)); // independent of its width. That is, for a narrower beam
vec4 weights = vec4(distance / scanline_weight); // "weights" should have a higher peak at the center of the
return 1.4 * exp(-pow(weights * inversesqrt(0.5 * wid), wid)) / (0.6 + 0.2 * wid); // scanline than for a wider beam.
#endif #ifdef USEGAUSSIAN
} vec4 wid = 0.3 + 0.1 * pow(color, vec4(3.0));
vec4 weights = vec4(distance / wid);
return 0.4 * exp(-weights * weights) / wid;
#else
vec4 wid = 2.0 + 2.0 * pow(color, vec4(4.0));
vec4 weights = vec4(distance / scanline_weight);
return 1.4 * exp(-pow(weights * inversesqrt(0.5 * wid), wid)) / (0.6 + 0.2 * wid);
#endif
}
vec2 transform(vec2 coord) vec2 transform(vec2 coord)
{ {
coord *= global.SourceSize.xy / global.SourceSize.zw; coord *= global.SourceSize.xy;
coord = (coord-vec2(0.5))*aspect*stretch.z+stretch.xy; coord = (coord-vec2(0.5))*aspect*stretch.z+stretch.xy;
return (bkwtrans(coord)/vec2(overscan_x / 100.0, overscan_y / 100.0)/aspect+vec2(0.5)) * global.SourceSize.zw / global.SourceSize.xy;
} return (bkwtrans(coord)/vec2(overscan_x / 100.0, overscan_y / 100.0)/aspect+vec2(0.5)) * global.SourceSize.xy;
}
float corner(vec2 coord) float corner(vec2 coord)
{ {
// coord *= global.SourceSize.xy / global.SourceSize.zw; // coord *= global.SourceSize.xy / global.SourceSize.zw;
coord = (coord - vec2(0.5)) * vec2(overscan_x / 100.0, overscan_y / 100.0) + vec2(0.5); coord = (coord - vec2(0.5)) * vec2(overscan_x / 100.0, overscan_y / 100.0) + vec2(0.5);
coord = min(coord, vec2(1.0)-coord) * aspect; coord = min(coord, vec2(1.0) - coord) * aspect;
vec2 cdist = vec2(cornersize); vec2 cdist = vec2(cornersize);
coord = (cdist - min(coord,cdist)); coord = (cdist - min(coord, cdist));
float dist = sqrt(dot(coord,coord)); float dist = sqrt(dot(coord, coord));
return clamp((cdist.x-dist)*cornersmooth,0.0, 1.0);
} return clamp((cdist.x-dist)*cornersmooth, 0.0, 1.0);
}
void main() void main()
{ {
// Here's a helpful diagram to keep in mind while trying to // Here's a helpful diagram to keep in mind while trying to
// understand the code: // understand the code:
// //
// | | | | | // | | | | |
// ------------------------------- // -------------------------------
// | | | | | // | | | | |
// | 01 | 11 | 21 | 31 | <-- current scanline // | 01 | 11 | 21 | 31 | <-- current scanline
// | | @ | | | // | | @ | | |
// ------------------------------- // -------------------------------
// | | | | | // | | | | |
// | 02 | 12 | 22 | 32 | <-- next scanline // | 02 | 12 | 22 | 32 | <-- next scanline
// | | | | | // | | | | |
// ------------------------------- // -------------------------------
// | | | | | // | | | | |
// //
// Each character-cell represents a pixel on the output // Each character-cell represents a pixel on the output
// surface, "@" represents the current pixel (always somewhere // surface, "@" represents the current pixel (always somewhere
// in the bottom half of the current scan-line, or the top-half // in the bottom half of the current scan-line, or the top-half
// of the next scanline). The grid of lines represents the // of the next scanline). The grid of lines represents the
// edges of the texels of the underlying texture. // edges of the texels of the underlying texture.
// Texture coordinates of the texel containing the active pixel. // Texture coordinates of the texel containing the active pixel.
#ifdef CURVATURE #ifdef CURVATURE
vec2 xy = transform(vTexCoord); vec2 xy = transform(vTexCoord);
#else #else
vec2 xy = vTexCoord; vec2 xy = vTexCoord;
#endif #endif
float cval = corner(xy); float cval = corner(xy);
// Of all the pixels that are mapped onto the texel we are // Of all the pixels that are mapped onto the texel we are
// currently rendering, which pixel are we currently rendering? // currently rendering, which pixel are we currently rendering?
#ifdef INTERLACED #ifdef INTERLACED
vec2 ilvec = vec2(0.0,ilfac.y > 1.5 ? mod(float(global.FrameCount),2.0) : 0.0); vec2 ilvec = vec2(0.0, ilfac.y > 1.5 ? mod(float(global.FrameCount), 2.0) : 0.0);
#else #else
vec2 ilvec = vec2(0.0,ilfac.y); vec2 ilvec = vec2(0.0, ilfac.y);
#endif #endif
vec2 ratio_scale = (xy * global.SourceSize.xy - vec2(0.5, 0.5) + ilvec)/ilfac; vec2 ratio_scale = (xy * global.SourceSize.xy - vec2(0.5, 0.5) + ilvec)/ilfac;
#ifdef OVERSAMPLE #ifdef OVERSAMPLE
float filter_ = fwidth(ratio_scale.y);//global.SourceSize.y / global.OutputSize.y; float filter_ = fwidth(ratio_scale.y);//global.SourceSize.y / global.OutputSize.y;
#endif #endif
vec2 uv_ratio = fract(ratio_scale); vec2 uv_ratio = fract(ratio_scale);
// Snap to the center of the underlying texel. // Snap to the center of the underlying texel.
xy = (floor(ratio_scale)*ilfac + vec2(0.5, 0.5) - ilvec) / global.SourceSize.xy; xy = (floor(ratio_scale)*ilfac + vec2(0.5, 0.5) - ilvec) / global.SourceSize.xy;
// Calculate Lanczos scaling coefficients describing the effect // Calculate Lanczos scaling coefficients describing the effect
// of various neighbour texels in a scanline on the current // of various neighbour texels in a scanline on the current
// pixel. // pixel.
vec4 coeffs = PI * vec4(1.0 + uv_ratio.x, uv_ratio.x, 1.0 - uv_ratio.x, 2.0 - uv_ratio.x); vec4 coeffs = PI * vec4(1.0 + uv_ratio.x, uv_ratio.x, 1.0 - uv_ratio.x, 2.0 - uv_ratio.x);
// Prevent division by zero. // Prevent division by zero.
coeffs = FIX(coeffs); coeffs = FIX(coeffs);
// Lanczos2 kernel. // Lanczos2 kernel.
coeffs = 2.0 * sin(coeffs) * sin(coeffs / 2.0) / (coeffs * coeffs); coeffs = 2.0 * sin(coeffs) * sin(coeffs / 2.0) / (coeffs * coeffs);
// Normalize. // Normalize.
coeffs /= dot(coeffs, vec4(1.0)); coeffs /= dot(coeffs, vec4(1.0));
// Calculate the effective colour of the current and next // Calculate the effective colour of the current and next
// scanlines at the horizontal location of the current pixel, // scanlines at the horizontal location of the current pixel,
// using the Lanczos coefficients above. // using the Lanczos coefficients above.
vec4 col = clamp(mat4( vec4 col = clamp(
TEX2D(xy + vec2(-one.x, 0.0)), mat4(
TEX2D(xy), TEX2D(xy + vec2(-one.x, 0.0)),
TEX2D(xy + vec2(one.x, 0.0)), TEX2D(xy),
TEX2D(xy + vec2(2.0 * one.x, 0.0))) * coeffs, TEX2D(xy + vec2(one.x, 0.0)),
0.0, 1.0); TEX2D(xy + vec2(2.0 * one.x, 0.0))
vec4 col2 = clamp(mat4( ) * coeffs,
TEX2D(xy + vec2(-one.x, one.y)), 0.0, 1.0
TEX2D(xy + vec2(0.0, one.y)), );
TEX2D(xy + one), vec4 col2 = clamp(
TEX2D(xy + vec2(2.0 * one.x, one.y))) * coeffs, mat4(
0.0, 1.0); TEX2D(xy + vec2(-one.x, one.y)),
TEX2D(xy + vec2(0.0, one.y)),
TEX2D(xy + one),
TEX2D(xy + vec2(2.0 * one.x, one.y))
) * coeffs,
0.0, 1.0
);
#ifndef LINEAR_PROCESSING #ifndef LINEAR_PROCESSING
col = pow(col , vec4(CRTgamma)); col = pow(col , vec4(CRTgamma));
col2 = pow(col2, vec4(CRTgamma)); col2 = pow(col2, vec4(CRTgamma));
#endif #endif
// Calculate the influence of the current and next scanlines on // Calculate the influence of the current and next scanlines on
// the current pixel. // the current pixel.
vec4 weights = scanlineWeights(uv_ratio.y, col); vec4 weights = scanlineWeights(uv_ratio.y, col);
vec4 weights2 = scanlineWeights(1.0 - uv_ratio.y, col2); vec4 weights2 = scanlineWeights(1.0 - uv_ratio.y, col2);
#ifdef OVERSAMPLE #ifdef OVERSAMPLE
uv_ratio.y =uv_ratio.y+1.0/3.0*filter_; uv_ratio.y = uv_ratio.y + 1.0/3.0*filter_;
weights = (weights+scanlineWeights(uv_ratio.y, col))/3.0; weights = (weights + scanlineWeights(uv_ratio.y, col))/3.0;
weights2=(weights2+scanlineWeights(abs(1.0-uv_ratio.y), col2))/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_; uv_ratio.y = uv_ratio.y - 2.0/3.0*filter_;
weights=weights+scanlineWeights(abs(uv_ratio.y), col)/3.0; weights = weights + scanlineWeights(abs(uv_ratio.y), col)/3.0;
weights2=weights2+scanlineWeights(abs(1.0-uv_ratio.y), col2)/3.0; weights2 = weights2 + scanlineWeights(abs(1.0-uv_ratio.y), col2)/3.0;
#endif #endif
vec3 mul_res = (col * weights + col2 * weights2).rgb * vec3(cval); vec3 mul_res = (col * weights + col2 * weights2).rgb * vec3(cval);
// dot-mask emulation: // dot-mask emulation:
// Output pixels are alternately tinted green and magenta. // Output pixels are alternately tinted green and magenta.
vec3 dotMaskWeights = mix( vec3 dotMaskWeights = mix(
vec3(1.0, 1.0 - DOTMASK, 1.0), vec3(1.0, 1.0 - DOTMASK, 1.0),
vec3(1.0 - DOTMASK, 1.0, 1.0 - DOTMASK), vec3(1.0 - DOTMASK, 1.0, 1.0 - DOTMASK),
floor(mod(mod_factor, 2.01)) floor(mod(mod_factor, 2.01))
); );
mul_res *= dotMaskWeights; mul_res *= dotMaskWeights;
// Convert the image gamma for display on our output device. // Convert the image gamma for display on our output device.
mul_res = pow(mul_res, vec3(1.0 / monitorgamma)); mul_res = pow(mul_res, vec3(1.0 / monitorgamma));
FragColor = vec4(mul_res, 1.0); FragColor = vec4(mul_res, 1.0);
} }