Moved shaders to a separate repo

This commit is contained in:
Marat Tanalin 2020-10-26 17:59:27 +03:00
parent f975752601
commit 0c1fa394b8
124 changed files with 1 additions and 141063 deletions

View file

@ -1,93 +0,0 @@
#version 150
// AntiAliased Nearest Neighbor
// by jimbo1qaz and wareya
// Licensed MIT
precision highp float;
uniform sampler2D source[];
uniform vec4 sourceSize[];
uniform vec4 targetSize[];
in Vertex {
vec2 texCoord;
};
out vec4 fragColor;
#define NOT(fl) (1-fl)
#define YES(fl) fl
vec4 vpow(vec4 n, float e)
{
return vec4(pow(n.x, e), pow(n.y, e), pow(n.z, e), pow(n.w, e));
}
vec4 getLQV(vec3 mine) {
return vec4
( mine.r
, mine.g
, mine.b
, mine.r*0.2989 + mine.g*0.5870 + mine.b*0.1140);
}
vec3 fromLQV(vec4 mine) {
float f = mine.w/(mine.r*0.2989 + mine.g*0.5870 + mine.b*0.1140);
return vec3(mine.rgb)*f;
}
vec3 percent(float ssize, float tsize, float coord) {
float minfull = (coord*tsize - 0.5) /tsize*ssize;
float maxfull = (coord*tsize + 0.5) /tsize*ssize;
float realfull = floor(maxfull);
if (minfull > realfull) {
return vec3(1, (realfull+0.5)/ssize, (realfull+0.5)/ssize);
}
return vec3(
(maxfull - realfull) / (maxfull - minfull),
(realfull-0.5) / ssize,
(realfull+0.5) / ssize
);
}
void main() {
float cheapsrgb = 2.1;
float gamma = 3.0;
vec3 xstuff = percent(sourceSize[0].x, targetSize[0].x, texCoord.x);
vec3 ystuff = percent(sourceSize[0].y, targetSize[0].y, texCoord.y);
float xkeep = xstuff[0];
float ykeep = ystuff[0];
// get points to interpolate across, in linear rgb
vec4 a = getLQV(vpow(texture(source[0],vec2(xstuff[1],ystuff[1])), cheapsrgb).rgb);
vec4 b = getLQV(vpow(texture(source[0],vec2(xstuff[2],ystuff[1])), cheapsrgb).rgb);
vec4 c = getLQV(vpow(texture(source[0],vec2(xstuff[1],ystuff[2])), cheapsrgb).rgb);
vec4 d = getLQV(vpow(texture(source[0],vec2(xstuff[2],ystuff[2])), cheapsrgb).rgb);
// use perceptual gamma for luminance component
a.w = pow(a.w, 1/gamma);
b.w = pow(b.w, 1/gamma);
c.w = pow(c.w, 1/gamma);
d.w = pow(d.w, 1/gamma);
// interpolate
vec4 gammaLQVresult =
NOT(xkeep)*NOT(ykeep)*a +
YES(xkeep)*NOT(ykeep)*b +
NOT(xkeep)*YES(ykeep)*c +
YES(xkeep)*YES(ykeep)*d;
// change luminance gamma back to linear
vec4 LQVresult = gammaLQVresult;
LQVresult.w = pow(gammaLQVresult.w, gamma);
// convert back to srgb; lqv -> lrgb -> srgb
vec4 c1 = vpow(vec4(fromLQV(LQVresult), 1), 1/cheapsrgb);
fragColor = c1;
}

View file

@ -1,8 +0,0 @@
input
filter: nearest
program
fragment: AANN.fs
output
filter: nearest

View file

@ -1,297 +0,0 @@
#version 150
/*
CRT-interlaced
Copyright (C) 2010-2012 cgwg, Themaister and DOLLS
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.
(cgwg gave their consent to have the original version of this shader
distributed under the GPL in this message:
http://board.byuu.org/viewtopic.php?p=26075#p26075
"Feel free to distribute my shaders under the GPL. After all, the
barrel distortion code was taken from the Curvature shader, which is
under the GPL."
)
This shader variant is pre-configured with screen curvature
*/
//#define INTERLACED
uniform sampler2D source[];
uniform vec4 sourceSize[];
uniform vec4 targetSize;
uniform int phase;
in Vertex {
vec2 texCoord;
};
out vec4 fragColor;
// 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
// vertex params //
// 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 vec2(1.0 , 1.0)//(0.93 , 0.915)
// aspect ratio
#define aspect vec2(1.0, 0.75)
// lengths are measured in units of (approximately) the width of the monitor
// simulated distance from viewer to monitor
#define d 2.0
// radius of curvature
#define R 2.0
// tilt angle in radians
// (behavior might be a bit wrong if both components are nonzero)
#define angle vec2(0.0,-0.0)
// size of curved corners
#define cornersize 0.02
// border smoothness parameter
// decrease if borders are too aliased
#define cornersmooth 80.0
#define sinangle sin(angle)
#define cosangle cos(angle)
#define stretch maxscale()
#define ilfac vec2(1.0, floor(sourceSize[0].y / 200.0))
#define one (ilfac / sourceSize[0].xy)
#define mod_factor (texCoord.x * targetSize.x)
// END of vertex params //
// Macros.
#define FIX(c) max(abs(c), 1e-5);
#define PI 3.141592653589
#ifdef LINEAR_PROCESSING
# define TEX2D(c) pow(texture(source[0], (c)), vec4(CRTgamma))
#else
# define TEX2D(c) texture(source[0], (c))
#endif
#define FIX(c) max(abs(c), 1e-5);
float intersect(vec2 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);
}
vec2 bkwtrans(vec2 xy)
{
float c = intersect(xy);
vec2 point = vec2(c)*xy;
point -= vec2(-R)*sinangle;
point /= vec2(R);
vec2 tang = sinangle/cosangle;
vec2 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);
vec2 uv = (point-a*sinangle)/cosangle;
float r = R*acos(a);
return uv*r/sin(r/R);
}
vec2 fwtrans(vec2 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;
}
vec3 maxscale()
{
vec2 c = bkwtrans(-R * sinangle / (1.0 + R/d*cosangle.x*cosangle.y));
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));
}
vec2 transform(vec2 coord)
{
coord = (coord-vec2(0.5))*aspect*stretch.z+stretch.xy;
return (bkwtrans(coord)/overscan/aspect+vec2(0.5));
}
float corner(vec2 coord)
{
coord = (coord - vec2(0.5)) * overscan + vec2(0.5);
coord = min(coord, vec2(1.0)-coord) * aspect;
vec2 cdist = vec2(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.
vec4 scanlineWeights(float distance, vec4 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
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 / 0.3);
return 1.4 * exp(-pow(weights * inversesqrt(0.5 * wid), wid)) / (0.6 + 0.2 * wid);
#endif
}
void main()
{
// 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
vec2 xy = transform(texCoord);
#else
vec2 xy = texCoord;
#endif
float cval = corner(xy);
// Of all the pixels that are mapped onto the texel we are
// currently rendering, which pixel are we currently rendering?
#ifdef INTERLACED
vec2 ilvec = vec2(0.0,ilfac.y > 1.5 ? mod(float(phase),2.0) : 0.0);
#else
vec2 ilvec = vec2(0.0,ilfac.y);
#endif
vec2 ratio_scale = (xy * sourceSize[0].xy - vec2(0.5) + ilvec)/ilfac;
#ifdef OVERSAMPLE
float filter_ = sourceSize[0].y / targetSize.y;
#endif
vec2 uv_ratio = fract(ratio_scale);
// Snap to the center of the underlying texel.
xy = (floor(ratio_scale)*ilfac + vec2(0.5) - ilvec) / sourceSize[0].xy;
// Calculate Lanczos scaling coefficients describing the effect
// of various neighbour texels in a scanline on the current
// pixel.
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.
coeffs = FIX(coeffs);
// Lanczos2 kernel.
coeffs = 2.0 * sin(coeffs) * sin(coeffs / 2.0) / (coeffs * coeffs);
// Normalize.
coeffs /= dot(coeffs, vec4(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.
vec4 col = clamp(mat4(
TEX2D(xy + vec2(-one.x, 0.0)),
TEX2D(xy),
TEX2D(xy + vec2(one.x, 0.0)),
TEX2D(xy + vec2(2.0 * one.x, 0.0))) * coeffs,
0.0, 1.0);
vec4 col2 = clamp(mat4(
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
col = pow(col , vec4(CRTgamma));
col2 = pow(col2, vec4(CRTgamma));
#endif
// Calculate the influence of the current and next scanlines on
// the current pixel.
vec4 weights = scanlineWeights(uv_ratio.y, col);
vec4 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
vec3 mul_res = (col * weights + col2 * weights2).rgb * vec3(cval);
// dot-mask emulation:
// Output pixels are alternately tinted green and magenta.
vec3 dotMaskWeights = mix(
vec3(1.0, 0.7, 1.0),
vec3(0.7, 1.0, 0.7),
floor(mod(mod_factor, 2.0))
);
mul_res *= dotMaskWeights;
// Convert the image gamma for display on our output device.
mul_res = pow(mul_res, vec3(1.0 / monitorgamma));
// Color the texel.
fragColor = vec4(mul_res, 1.0);
}

View file

@ -1,121 +0,0 @@
#version 150
in vec4 position;
in vec2 texCoord;
in vec4 sourceSize[];
in vec4 targetSize;
out Vertex {
vec2 texCoord;
} vertexOut;
float CRTgamma;
float monitorgamma;
vec2 overscan;
vec2 aspect;
float d;
float R;
float cornersize;
float cornersmooth;
vec3 stretch;
vec2 sinangle;
vec2 cosangle;
vec2 one;
float mod_factor;
vec2 ilfac;
#define FIX(c) max(abs(c), 1e-5);
float intersect(vec2 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);
}
vec2 bkwtrans(vec2 xy)
{
float c = intersect(xy);
vec2 point = vec2(c)*xy;
point -= vec2(-R)*sinangle;
point /= vec2(R);
vec2 tang = sinangle/cosangle;
vec2 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);
vec2 uv = (point-a*sinangle)/cosangle;
float r = R*acos(a);
return uv*r/sin(r/R);
}
vec2 fwtrans(vec2 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;
}
vec3 maxscale()
{
vec2 c = bkwtrans(-R * sinangle / (1.0 + R/d*cosangle.x*cosangle.y));
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));
}
void main()
{
// START of parameters
// gamma of simulated CRT
CRTgamma = 2.4;
// gamma of display monitor (typically 2.2 is correct)
monitorgamma = 2.2;
// overscan (e.g. 1.02 for 2% overscan)
overscan = vec2(0.99,0.99);
// aspect ratio
aspect = vec2(1.0, 0.75);
// lengths are measured in units of (approximately) the width of the monitor
// simulated distance from viewer to monitor
d = 2.0;
// radius of curvature
R = 2.0;
// tilt angle in radians
// (behavior might be a bit wrong if both components are nonzero)
const vec2 angle = vec2(0.0,-0.0);
// size of curved corners
cornersize = 0.03;
// border smoothness parameter
// decrease if borders are too aliased
cornersmooth = 80.0;
// END of parameters
vertexOut.texCoord = texCoord.xy;
gl_Position = position;
// 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,floor(sourceSize[0].y/200.0));
// The size of one texel, in texture-coordinates.
one = ilfac / sourceSize[0].xy;
// Resulting X pixel-coordinate of the pixel we're drawing.
mod_factor = texCoord.x * targetSize.x;
}

View file

@ -1,21 +0,0 @@
#version 150
#define distortion 0.08
uniform sampler2D source[];
uniform vec4 sourceSize[];
in Vertex {
vec2 texCoord;
};
out vec4 fragColor;
vec2 radialDistortion(vec2 coord) {
vec2 cc = coord - vec2(0.5);
float dist = dot(cc, cc) * distortion;
return coord + cc * (1.0 - dist) * dist;
}
void main(void) {
fragColor = texture(source[0], radialDistortion(texCoord));
}

View file

@ -1,5 +0,0 @@
program
vertex: crt-geom.vs
fragment: crt-geom.fs
modulo: 2

View file

@ -1,32 +0,0 @@
#version 150
uniform sampler2D source[];
uniform vec4 sourceSize[];
in Vertex {
vec2 vTexCoord;
};
out vec4 FragColor;
// Higher value, more centered glow.
// Lower values might need more taps.
#define GLOW_FALLOFF 0.35
#define TAPS 4
#define kernel(x) exp(-GLOW_FALLOFF * (x) * (x))
void main() {
vec3 col = vec3(0.0);
float dx = 4.0 * sourceSize[0].z; // Mipmapped
float k_total = 0.0;
for (int i = -TAPS; i <= TAPS; i++)
{
float k = kernel(i);
k_total += k;
col += k * texture(source[0], vTexCoord + vec2(float(i) * dx, 0.0)).rgb;
}
FragColor = vec4(col / k_total, 1.0);
}

View file

@ -1,16 +0,0 @@
#version 150
in vec4 position;
in vec2 texCoord;
out Vertex {
vec2 vTexCoord;
};
uniform vec4 targetSize;
uniform vec4 sourceSize[];
void main() {
gl_Position = position;
vTexCoord = texCoord;
}

View file

@ -1,32 +0,0 @@
#version 150
uniform sampler2D source[];
uniform vec4 sourceSize[];
in Vertex {
vec2 vTexCoord;
};
out vec4 FragColor;
// Higher value, more centered glow.
// Lower values might need more taps.
#define GLOW_FALLOFF 0.35
#define TAPS 4
#define kernel(x) exp(-GLOW_FALLOFF * (x) * (x))
void main() {
vec3 col = vec3(0.0);
float dy = sourceSize[0].w;
float k_total = 0.0;
for (int i = -TAPS; i <= TAPS; i++)
{
float k = kernel(i);
k_total += k;
col += k * texture(source[0], vTexCoord + vec2(0.0, float(i) * dy)).rgb;
}
FragColor = vec4(col / k_total, 1.0);
}

View file

@ -1,13 +0,0 @@
#version 150
in vec4 position;
in vec2 texCoord;
out Vertex {
vec2 vTexCoord;
};
void main() {
gl_Position = position;
vTexCoord = texCoord;
}

View file

@ -1,33 +0,0 @@
#version 150
#define INV_SQRT_2_PI 0.38 // Doesn't have to be accurate.
#define HORIZ_GAUSS_WIDTH 0.5
uniform sampler2D source[];
uniform vec4 sourceSize[];
in Vertex {
vec2 vTexCoord;
float data_pix_no;
float data_one;
};
out vec4 FragColor;
void main() {
float texel = floor(data_pix_no);
float phase = data_pix_no - texel;
float base_phase = phase - 0.5;
vec2 tex = vec2((texel + 0.5) * sourceSize[0].z, vTexCoord.y);
vec3 col = vec3(0.0);
for (int i = -2; i <= 2; i++)
{
float phase = base_phase - float(i);
float g = INV_SQRT_2_PI * exp(-0.5 * phase * phase / (HORIZ_GAUSS_WIDTH * HORIZ_GAUSS_WIDTH)) / HORIZ_GAUSS_WIDTH;
col += texture(source[0], tex + vec2(float(i) * data_one, 0.0)).rgb * g;
}
FragColor = vec4(col, 1.0);
}

View file

@ -1,20 +0,0 @@
#version 150
in vec4 position;
in vec2 texCoord;
out Vertex {
vec2 vTexCoord;
float data_pix_no;
float data_one;
};
uniform vec4 sourceSize[];
void main() {
gl_Position = position;
vTexCoord = texCoord;
data_pix_no = vTexCoord.x * sourceSize[0].x;
data_one = sourceSize[0].z;
}

View file

@ -1,49 +0,0 @@
#version 150
#define BOOST 1.0
#define CRT_GEOM_BEAM 1
uniform sampler2D source[];
uniform vec4 sourceSize[];
in Vertex {
vec2 vTexCoord;
vec2 data_pix_no;
float data_one;
};
out vec4 FragColor;
vec3 beam(vec3 color, float dist)
{
#if CRT_GEOM_BEAM
vec3 wid = 2.0 + 2.0 * pow(color, vec3(4.0));
vec3 weights = vec3(abs(dist) * 3.333333333);
return 2.0 * color * exp(-pow(weights * inversesqrt(0.5 * wid), wid)) / (0.6 + 0.2 * wid);
#else
float reciprocal_width = 4.0;
vec3 x = dist * reciprocal_width;
return 2.0 * color * exp(-0.5 * x * x) * reciprocal_width;
#endif
}
void main() {
vec2 texel = floor(data_pix_no);
float phase = data_pix_no.y - texel.y;
vec2 tex = vec2(texel + 0.5) * sourceSize[0].zw;
vec3 top = texture(source[0], tex + vec2(0.0, 0 * data_one)).rgb;
vec3 bottom = texture(source[0], tex + vec2(0.0, 1 * data_one)).rgb;
float dist0 = phase;
float dist1 = 1.0 - phase;
vec3 scanline = vec3(0.0);
scanline += beam(top, dist0);
scanline += beam(bottom, dist1);
FragColor = vec4(BOOST * scanline * 0.869565217391304, 1.0);
}

View file

@ -1,20 +0,0 @@
#version 150
in vec4 position;
in vec2 texCoord;
out Vertex {
vec2 vTexCoord;
vec2 data_pix_no;
float data_one;
};
uniform vec4 sourceSize[];
void main() {
gl_Position = position;
vTexCoord = texCoord;
data_pix_no = vTexCoord.xy * sourceSize[0].xy - vec2(0.0, 0.5);
data_one = sourceSize[0].w;
}

View file

@ -1,13 +0,0 @@
#version 150
uniform sampler2D source[];
in Vertex {
vec2 vTexCoord;
};
out vec4 FragColor;
void main() {
FragColor = texture(source[0], vTexCoord);
}

View file

@ -1,15 +0,0 @@
#version 150
in vec4 position;
in vec2 texCoord;
out Vertex {
vec2 vTexCoord;
};
uniform vec4 sourceSize[];
void main() {
gl_Position = position;
vTexCoord = texCoord;
}

View file

@ -1,15 +0,0 @@
#version 150
#define INPUT_GAMMA 2.2
uniform sampler2D source[];
in Vertex {
vec2 vTexCoord;
};
out vec4 FragColor;
void main() {
FragColor = pow(texture(source[0], vTexCoord), vec4(INPUT_GAMMA));
}

View file

@ -1,15 +0,0 @@
#version 150
in vec4 position;
in vec2 texCoord;
out Vertex {
vec2 vTexCoord;
};
uniform vec4 sourceSize[];
void main() {
gl_Position = position;
vTexCoord = texCoord;
}

View file

@ -1,54 +0,0 @@
input
filter: nearest
program
format: srgb8
filter: nearest
vertex: linearize.vs
fragment: linearize.fs
program
format: srgb8
filter: nearest
height: 25%
width: 100%
vertex: gauss_horiz.vs
fragment: gauss_horiz.fs
program
format: srgb8
filter: nearest
vertex: gauss_vert.vs
fragment: gauss_vert.fs
program
format: srgb8
filter: nearest
height: 100%
width: 100%
vertex: threshold.vs
fragment: threshold.fs
program
format: srgb8
filter: linear
height: 25%
width: 25%
vertex: blur_horiz.vs
fragment: blur_horiz.fs
program
format: srgb8
filter: linear
height: 100%
width: 100%
vertex: blur_vert.vs
fragment: blur_vert.fs
program
filter: linear
vertex: resolve.vs
fragment: resolve.fs
output
filter: linear

View file

@ -1,28 +0,0 @@
#version 150
#define BLOOM_STRENGTH 0.25
#define OUTPUT_GAMMA 2.2
uniform sampler2D source[];
in Vertex {
vec2 vTexCoord;
};
out vec4 FragColor;
// For debugging
#define BLOOM_ONLY 0
#define CRT_PASS source[3]
void main() {
#if BLOOM_ONLY
vec3 source = BLOOM_STRENGTH * texture(source[0], vTexCoord).rgb;
#else
vec3 source_ = 1.15 * texture(CRT_PASS, vTexCoord).rgb;
vec3 bloom = texture(source[0], vTexCoord).rgb;
source_ += BLOOM_STRENGTH * bloom;
#endif
FragColor = vec4(pow(clamp(source_, 0.0, 1.0), vec3(1.0 / OUTPUT_GAMMA)), 1.0);
}

View file

@ -1,13 +0,0 @@
#version 150
in vec4 position;
in vec2 texCoord;
out Vertex {
vec2 vTexCoord;
};
void main() {
gl_Position = position;
vTexCoord = texCoord;
}

View file

@ -1,19 +0,0 @@
#version 150
#define GLOW_WHITEPOINT 1.0
#define GLOW_ROLLOFF 3.0
uniform sampler2D source[];
in Vertex {
vec2 vTexCoord;
};
out vec4 FragColor;
void main() {
vec3 color = 1.15 * texture(source[0], vTexCoord).rgb;
vec3 factor = clamp(color / GLOW_WHITEPOINT, 0.0, 1.0);
FragColor = vec4(pow(factor, vec3(GLOW_ROLLOFF)), 1.0);
}

View file

@ -1,13 +0,0 @@
#version 150
in vec4 position;
in vec2 texCoord;
out Vertex {
vec2 vTexCoord;
};
void main() {
gl_Position = position;
vTexCoord = texCoord;
}

View file

@ -1,306 +0,0 @@
#version 150
// PUBLIC DOMAIN CRT STYLED SCAN-LINE SHADER
//
// by Timothy Lottes
//
// This is more along the style of a really good CGA arcade monitor.
// With RGB inputs instead of NTSC.
// The shadow mask example has the mask rotated 90 degrees for less chromatic aberration.
//
// Left it unoptimized to show the theory behind the algorithm.
//
// It is an example what I personally would want as a display option for pixel art games.
// Please take and use, change, or whatever.
#define hardScan -8.0
#define hardPix -3.0
#define warpX 0.031
#define warpY 0.041
#define maskDark 0.5
#define maskLight 1.5
#define scaleInLinearGamma 1.0
#define shadowMask 3.0
#define brightBoost 1.0
#define hardBloomPix -1.5
#define hardBloomScan -2.0
#define bloomAmount 0.4
#define shape 2.0
uniform sampler2D source[];
uniform vec4 sourceSize[];
in Vertex {
vec2 vTexCoord;
};
out vec4 FragColor;
//Uncomment to reduce instructions with simpler linearization
//(fixes HD3000 Sandy Bridge IGP)
//#define SIMPLE_LINEAR_GAMMA
#define DO_BLOOM 1
// ------------- //
// sRGB to Linear.
// Assuming using sRGB typed textures this should not be needed.
#ifdef SIMPLE_LINEAR_GAMMA
float ToLinear1(float c)
{
return c;
}
vec3 ToLinear(vec3 c)
{
return c;
}
vec3 ToSrgb(vec3 c)
{
return pow(c, vec3(1.0 / 2.2));
}
#else
float ToLinear1(float c)
{
if (scaleInLinearGamma == 0)
return c;
return(c<=0.04045) ? c/12.92 : pow((c + 0.055)/1.055, 2.4);
}
vec3 ToLinear(vec3 c)
{
if (scaleInLinearGamma==0)
return c;
return vec3(ToLinear1(c.r), ToLinear1(c.g), ToLinear1(c.b));
}
// Linear to sRGB.
// Assuming using sRGB typed textures this should not be needed.
float ToSrgb1(float c)
{
if (scaleInLinearGamma == 0)
return c;
return(c<0.0031308 ? c*12.92 : 1.055*pow(c, 0.41666) - 0.055);
}
vec3 ToSrgb(vec3 c)
{
if (scaleInLinearGamma == 0)
return c;
return vec3(ToSrgb1(c.r), ToSrgb1(c.g), ToSrgb1(c.b));
}
#endif
// Nearest emulated sample given floating point position and texel offset.
// Also zero's off screen.
vec3 Fetch(vec2 pos,vec2 off){
pos=(floor(pos*sourceSize[0].xy+off)+vec2(0.5,0.5))/sourceSize[0].xy;
#ifdef SIMPLE_LINEAR_GAMMA
return ToLinear(brightBoost * pow(texture(source[0],pos.xy).rgb, vec3(2.2)));
#else
return ToLinear(brightBoost * texture(source[0],pos.xy).rgb);
#endif
}
// Distance in emulated pixels to nearest texel.
vec2 Dist(vec2 pos)
{
pos = pos*sourceSize[0].xy;
return -((pos - floor(pos)) - vec2(0.5));
}
// 1D Gaussian.
float Gaus(float pos, float scale)
{
return exp2(scale*pow(abs(pos), shape));
}
// 3-tap Gaussian filter along horz line.
vec3 Horz3(vec2 pos, float off)
{
vec3 b = Fetch(pos, vec2(-1.0, off));
vec3 c = Fetch(pos, vec2( 0.0, off));
vec3 d = Fetch(pos, vec2( 1.0, off));
float dst = Dist(pos).x;
// Convert distance to weight.
float scale = hardPix;
float wb = Gaus(dst-1.0,scale);
float wc = Gaus(dst+0.0,scale);
float wd = Gaus(dst+1.0,scale);
// Return filtered sample.
return (b*wb+c*wc+d*wd)/(wb+wc+wd);
}
// 5-tap Gaussian filter along horz line.
vec3 Horz5(vec2 pos,float off){
vec3 a = Fetch(pos,vec2(-2.0, off));
vec3 b = Fetch(pos,vec2(-1.0, off));
vec3 c = Fetch(pos,vec2( 0.0, off));
vec3 d = Fetch(pos,vec2( 1.0, off));
vec3 e = Fetch(pos,vec2( 2.0, off));
float dst = Dist(pos).x;
// Convert distance to weight.
float scale = hardPix;
float wa = Gaus(dst - 2.0, scale);
float wb = Gaus(dst - 1.0, scale);
float wc = Gaus(dst + 0.0, scale);
float wd = Gaus(dst + 1.0, scale);
float we = Gaus(dst + 2.0, scale);
// Return filtered sample.
return (a*wa+b*wb+c*wc+d*wd+e*we)/(wa+wb+wc+wd+we);
}
// 7-tap Gaussian filter along horz line.
vec3 Horz7(vec2 pos,float off)
{
vec3 a = Fetch(pos, vec2(-3.0, off));
vec3 b = Fetch(pos, vec2(-2.0, off));
vec3 c = Fetch(pos, vec2(-1.0, off));
vec3 d = Fetch(pos, vec2( 0.0, off));
vec3 e = Fetch(pos, vec2( 1.0, off));
vec3 f = Fetch(pos, vec2( 2.0, off));
vec3 g = Fetch(pos, vec2( 3.0, off));
float dst = Dist(pos).x;
// Convert distance to weight.
float scale = hardBloomPix;
float wa = Gaus(dst - 3.0, scale);
float wb = Gaus(dst - 2.0, scale);
float wc = Gaus(dst - 1.0, scale);
float wd = Gaus(dst + 0.0, scale);
float we = Gaus(dst + 1.0, scale);
float wf = Gaus(dst + 2.0, scale);
float wg = Gaus(dst + 3.0, scale);
// Return filtered sample.
return (a*wa+b*wb+c*wc+d*wd+e*we+f*wf+g*wg)/(wa+wb+wc+wd+we+wf+wg);
}
// Return scanline weight.
float Scan(vec2 pos, float off)
{
float dst = Dist(pos).y;
return Gaus(dst + off, hardScan);
}
// Return scanline weight for bloom.
float BloomScan(vec2 pos, float off)
{
float dst = Dist(pos).y;
return Gaus(dst + off, hardBloomScan);
}
// Allow nearest three lines to effect pixel.
vec3 Tri(vec2 pos)
{
vec3 a = Horz3(pos,-1.0);
vec3 b = Horz5(pos, 0.0);
vec3 c = Horz3(pos, 1.0);
float wa = Scan(pos,-1.0);
float wb = Scan(pos, 0.0);
float wc = Scan(pos, 1.0);
return a*wa + b*wb + c*wc;
}
// Small bloom.
vec3 Bloom(vec2 pos)
{
vec3 a = Horz5(pos,-2.0);
vec3 b = Horz7(pos,-1.0);
vec3 c = Horz7(pos, 0.0);
vec3 d = Horz7(pos, 1.0);
vec3 e = Horz5(pos, 2.0);
float wa = BloomScan(pos,-2.0);
float wb = BloomScan(pos,-1.0);
float wc = BloomScan(pos, 0.0);
float wd = BloomScan(pos, 1.0);
float we = BloomScan(pos, 2.0);
return a*wa+b*wb+c*wc+d*wd+e*we;
}
// Distortion of scanlines, and end of screen alpha.
vec2 Warp(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;
}
// 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*0.166666666) < 0.5) odd = 1.0;
if (fract((pos.y + odd) * 0.5) < 0.5) line = maskDark;
pos.x = fract(pos.x*0.333333333);
if (pos.x < 0.333) mask.r = maskLight;
else if (pos.x < 0.666) mask.g = maskLight;
else mask.b = maskLight;
mask*=line;
}
// Aperture-grille.
else if (shadowMask == 2.0)
{
pos.x = fract(pos.x*0.333333333);
if (pos.x < 0.333) mask.r = maskLight;
else if (pos.x < 0.666) mask.g = maskLight;
else 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*0.166666666);
if (pos.x < 0.333) mask.r = maskLight;
else if (pos.x < 0.666) mask.g = maskLight;
else 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*0.166666666);
if (pos.x < 0.333) mask.r = maskLight;
else if (pos.x < 0.666) mask.g = maskLight;
else mask.b = maskLight;
}
return mask;
}
void main() {
FragColor = vec4(Bloom(vTexCoord)*bloomAmount, 1.0);
}

View file

@ -1,15 +0,0 @@
#version 150
in vec4 position;
in vec2 texCoord;
out Vertex {
vec2 vTexCoord;
};
uniform vec4 sourceSize[];
void main() {
gl_Position = position;
vTexCoord = texCoord;
}

View file

@ -1,18 +0,0 @@
input
filter: nearest
program
filter: nearest
format: srgb8
height: 100%
width: 100%
vertex: bloompass.vs
fragment: bloompass.fs
program
filter: nearest
vertex: scanpass.vs
fragment: scanpass.fs
output
filter: linear

View file

@ -1,317 +0,0 @@
#version 150
// PUBLIC DOMAIN CRT STYLED SCAN-LINE SHADER
//
// by Timothy Lottes
//
// This is more along the style of a really good CGA arcade monitor.
// With RGB inputs instead of NTSC.
// The shadow mask example has the mask rotated 90 degrees for less chromatic aberration.
//
// Left it unoptimized to show the theory behind the algorithm.
//
// It is an example what I personally would want as a display option for pixel art games.
// Please take and use, change, or whatever.
#define hardScan -8.0
#define hardPix -3.0
#define warpX 0.031
#define warpY 0.041
#define maskDark 0.5
#define maskLight 1.5
#define scaleInLinearGamma 1.0
#define shadowMask 3.0
#define brightBoost 1.0
#define hardBloomPix -1.5
#define hardBloomScan -2.0
#define bloomAmount 0.4
#define shape 2.0
uniform sampler2D source[];
uniform vec4 sourceSize[];
uniform vec4 outputSize;
in Vertex {
vec2 vTexCoord;
};
out vec4 FragColor;
//Uncomment to reduce instructions with simpler linearization
//(fixes HD3000 Sandy Bridge IGP)
//#define SIMPLE_LINEAR_GAMMA
#define DO_BLOOM 1
// ------------- //
// sRGB to Linear.
// Assuming using sRGB typed textures this should not be needed.
#ifdef SIMPLE_LINEAR_GAMMA
float ToLinear1(float c)
{
return c;
}
vec3 ToLinear(vec3 c)
{
return c;
}
vec3 ToSrgb(vec3 c)
{
return pow(c, vec3(1.0 / 2.2));
}
#else
float ToLinear1(float c)
{
if (scaleInLinearGamma == 0)
return c;
return(c<=0.04045) ? c/12.92 : pow((c + 0.055)/1.055, 2.4);
}
vec3 ToLinear(vec3 c)
{
if (scaleInLinearGamma==0)
return c;
return vec3(ToLinear1(c.r), ToLinear1(c.g), ToLinear1(c.b));
}
// Linear to sRGB.
// Assuming using sRGB typed textures this should not be needed.
float ToSrgb1(float c)
{
if (scaleInLinearGamma == 0)
return c;
return(c<0.0031308 ? c*12.92 : 1.055*pow(c, 0.41666) - 0.055);
}
vec3 ToSrgb(vec3 c)
{
if (scaleInLinearGamma == 0)
return c;
return vec3(ToSrgb1(c.r), ToSrgb1(c.g), ToSrgb1(c.b));
}
#endif
// Nearest emulated sample given floating point position and texel offset.
// Also zero's off screen.
vec3 Fetch(vec2 pos,vec2 off){
pos=(floor(pos*sourceSize[0].xy+off)+vec2(0.5,0.5))/sourceSize[0].xy;
#ifdef SIMPLE_LINEAR_GAMMA
return ToLinear(brightBoost * pow(texture(source[1],pos.xy).rgb, vec3(2.2)));
#else
return ToLinear(brightBoost * texture(source[1],pos.xy).rgb);
#endif
}
// Distance in emulated pixels to nearest texel.
vec2 Dist(vec2 pos)
{
pos = pos*sourceSize[0].xy;
return -((pos - floor(pos)) - vec2(0.5));
}
// 1D Gaussian.
float Gaus(float pos, float scale)
{
return exp2(scale*pow(abs(pos), shape));
}
// 3-tap Gaussian filter along horz line.
vec3 Horz3(vec2 pos, float off)
{
vec3 b = Fetch(pos, vec2(-1.0, off));
vec3 c = Fetch(pos, vec2( 0.0, off));
vec3 d = Fetch(pos, vec2( 1.0, off));
float dst = Dist(pos).x;
// Convert distance to weight.
float scale = hardPix;
float wb = Gaus(dst-1.0,scale);
float wc = Gaus(dst+0.0,scale);
float wd = Gaus(dst+1.0,scale);
// Return filtered sample.
return (b*wb+c*wc+d*wd)/(wb+wc+wd);
}
// 5-tap Gaussian filter along horz line.
vec3 Horz5(vec2 pos,float off){
vec3 a = Fetch(pos,vec2(-2.0, off));
vec3 b = Fetch(pos,vec2(-1.0, off));
vec3 c = Fetch(pos,vec2( 0.0, off));
vec3 d = Fetch(pos,vec2( 1.0, off));
vec3 e = Fetch(pos,vec2( 2.0, off));
float dst = Dist(pos).x;
// Convert distance to weight.
float scale = hardPix;
float wa = Gaus(dst - 2.0, scale);
float wb = Gaus(dst - 1.0, scale);
float wc = Gaus(dst + 0.0, scale);
float wd = Gaus(dst + 1.0, scale);
float we = Gaus(dst + 2.0, scale);
// Return filtered sample.
return (a*wa+b*wb+c*wc+d*wd+e*we)/(wa+wb+wc+wd+we);
}
// 7-tap Gaussian filter along horz line.
vec3 Horz7(vec2 pos,float off)
{
vec3 a = Fetch(pos, vec2(-3.0, off));
vec3 b = Fetch(pos, vec2(-2.0, off));
vec3 c = Fetch(pos, vec2(-1.0, off));
vec3 d = Fetch(pos, vec2( 0.0, off));
vec3 e = Fetch(pos, vec2( 1.0, off));
vec3 f = Fetch(pos, vec2( 2.0, off));
vec3 g = Fetch(pos, vec2( 3.0, off));
float dst = Dist(pos).x;
// Convert distance to weight.
float scale = hardBloomPix;
float wa = Gaus(dst - 3.0, scale);
float wb = Gaus(dst - 2.0, scale);
float wc = Gaus(dst - 1.0, scale);
float wd = Gaus(dst + 0.0, scale);
float we = Gaus(dst + 1.0, scale);
float wf = Gaus(dst + 2.0, scale);
float wg = Gaus(dst + 3.0, scale);
// Return filtered sample.
return (a*wa+b*wb+c*wc+d*wd+e*we+f*wf+g*wg)/(wa+wb+wc+wd+we+wf+wg);
}
// Return scanline weight.
float Scan(vec2 pos, float off)
{
float dst = Dist(pos).y;
return Gaus(dst + off, hardScan);
}
// Return scanline weight for bloom.
float BloomScan(vec2 pos, float off)
{
float dst = Dist(pos).y;
return Gaus(dst + off, hardBloomScan);
}
// Allow nearest three lines to effect pixel.
vec3 Tri(vec2 pos)
{
vec3 a = Horz3(pos,-1.0);
vec3 b = Horz5(pos, 0.0);
vec3 c = Horz3(pos, 1.0);
float wa = Scan(pos,-1.0);
float wb = Scan(pos, 0.0);
float wc = Scan(pos, 1.0);
return a*wa + b*wb + c*wc;
}
// Small bloom.
vec3 Bloom(vec2 pos)
{
vec3 a = Horz5(pos,-2.0);
vec3 b = Horz7(pos,-1.0);
vec3 c = Horz7(pos, 0.0);
vec3 d = Horz7(pos, 1.0);
vec3 e = Horz5(pos, 2.0);
float wa = BloomScan(pos,-2.0);
float wb = BloomScan(pos,-1.0);
float wc = BloomScan(pos, 0.0);
float wd = BloomScan(pos, 1.0);
float we = BloomScan(pos, 2.0);
return a*wa+b*wb+c*wc+d*wd+e*we;
}
// Distortion of scanlines, and end of screen alpha.
vec2 Warp(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;
}
// 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*0.166666666) < 0.5) odd = 1.0;
if (fract((pos.y + odd) * 0.5) < 0.5) line = maskDark;
pos.x = fract(pos.x*0.333333333);
if (pos.x < 0.333) mask.r = maskLight;
else if (pos.x < 0.666) mask.g = maskLight;
else mask.b = maskLight;
mask*=line;
}
// Aperture-grille.
else if (shadowMask == 2.0)
{
pos.x = fract(pos.x*0.333333333);
if (pos.x < 0.333) mask.r = maskLight;
else if (pos.x < 0.666) mask.g = maskLight;
else 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*0.166666666);
if (pos.x < 0.333) mask.r = maskLight;
else if (pos.x < 0.666) mask.g = maskLight;
else 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*0.166666666);
if (pos.x < 0.333) mask.r = maskLight;
else if (pos.x < 0.666) mask.g = maskLight;
else mask.b = maskLight;
}
return mask;
}
void main() {
vec2 pos = Warp(vTexCoord);
vec3 outColor = Tri(pos).rgb;
if (shadowMask > 0.0)
outColor.rgb *= Mask(vTexCoord.xy * outputSize.xy * 1.000001);
#ifdef DO_BLOOM
//Add Bloom
outColor.rgb += mix( vec3(0.0), texture(source[0], pos).rgb, bloomAmount);
#endif
FragColor = vec4(ToSrgb(outColor.rgb), 1.0);
}

View file

@ -1,15 +0,0 @@
#version 150
in vec4 position;
in vec2 texCoord;
out Vertex {
vec2 vTexCoord;
};
uniform vec4 sourceSize[];
void main() {
gl_Position = position;
vTexCoord = texCoord;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,214 +0,0 @@
input
filter: nearest
// IMPORTANT:
// Shader passes need to know details about the image in the mask_texture LUT
// files, so set the following constants in user-preset-constants.h accordingly:
// 1.) mask_triads_per_tile = (number of horizontal triads in mask texture LUT's)
// 2.) mask_texture_small_size = (texture size of mask*texture_small LUT's)
// 3.) mask_texture_large_size = (texture size of mask*texture_large LUT's)
// 4.) mask_grille_avg_color = (avg. brightness of mask_grille_texture* LUT's, in [0, 1])
// 5.) mask_slot_avg_color = (avg. brightness of mask_slot_texture* LUT's, in [0, 1])
// 6.) mask_shadow_avg_color = (avg. brightness of mask_shadow_texture* LUT's, in [0, 1])
// Shader passes also need to know certain scales set in this preset, but their
// compilation model doesn't currently allow the preset file to tell them. Make
// sure to set the following constants in user-preset-constants.h accordingly too:
// 1.) bloom_approx_scale_x = scale_x2
// 2.) mask_resize_viewport_scale = vec2(scale_x6, scale_y5)
// Finally, shader passes need to know the value of geom_max_aspect_ratio used to
// calculate scale_y5 (among other values):
// 1.) geom_max_aspect_ratio = (geom_max_aspect_ratio used to calculate scale_y5)
// Pass0: Linearize the input based on CRT gamma and bob interlaced fields.
// (Bobbing ensures we can immediately blur without getting artifacts.)
program
filter: nearest
vertex: first-pass-linearize-crt-gamma-bob-fields.vs
fragment: first-pass-linearize-crt-gamma-bob-fields.fs
format: rgba16f
height: 100%
width: 100%
// Pass1: Resample interlaced (and misconverged) scanlines vertically.
// Separating vertical/horizontal scanline sampling is faster: It lets us
// consider more scanlines while calculating weights for fewer pixels, and
// it reduces our samples from vertical*horizontal to vertical+horizontal.
// This has to come right after ORIG_LINEARIZED, because there's no
// "original_source" scale_type we can use later.
program
filter: linear
vertex: scanlines-vertical-interlacing.vs
fragment: scanlines-vertical-interlacing.fs
height: 400%
width: 100%
format: rgba16f
// Pass2: Do a small resize blur of ORIG_LINEARIZED at an absolute size, and
// account for convergence offsets. We want to blur a predictable portion of the
// screen to match the phosphor bloom, and absolute scale works best for
// reliable results with a fixed-size bloom. Picking a scale is tricky:
// a.) 400x300 is a good compromise for the "fake-bloom" version: It's low enough
// to blur high-res/interlaced sources but high enough that resampling
// doesn't smear low-res sources too much.
// b.) 320x240 works well for the "real bloom" version: It's 1-1.5% faster, and
// the only noticeable visual difference is a larger halation spread (which
// may be a good thing for people who like to crank it up).
// Note the 4:3 aspect ratio assumes the input has cropped geom_overscan (so it's
// *intended* for an ~4:3 aspect ratio).
program
filter: linear
vertex: bloom-approx.vs
fragment: bloom-approx.fs
format: rgba16f
width: 320 px
height: 240 px
// Pass3: Vertically blur the input for halation and refractive diffusion.
// Base this on BLOOM_APPROX: This blur should be small and fast, and blurring
// a constant portion of the screen is probably physically correct if the
// viewport resolution is proportional to the simulated CRT size.
program
filter: linear
vertex: blur9fast-vertical.vs
fragment: blur9fast-vertical.fs
format: rgba16f
height: 100%
width: 100%
// Pass4: Horizontally blur the input for halation and refractive diffusion.
// Note: Using a one-pass 9x9 blur is about 1% slower.
program
filter: linear
vertex: blur9fast-horizontal.vs
fragment: blur9fast-horizontal.fs
format: rgba16f
height: 100%
width: 100%
// Pass5: Lanczos-resize the phosphor mask vertically. Set the absolute
// scale_x5 == mask_texture_small_size.x (see IMPORTANT above). Larger scales
// will blur, and smaller scales could get nasty. The vertical size must be
// based on the viewport size and calculated carefully to avoid artifacts later.
// First calculate the minimum number of mask tiles we need to draw.
// Since curvature is computed after the scanline masking pass:
// num_resized_mask_tiles = 2.0;
// If curvature were computed in the scanline masking pass (it's not):
// max_mask_texel_border = ~3.0 * (1/3.0 + 4.0*sqrt(2.0) + 0.5 + 1.0);
// max_mask_tile_border = max_mask_texel_border/
// (min_resized_phosphor_triad_size * mask_triads_per_tile);
// num_resized_mask_tiles = max(2.0, 1.0 + max_mask_tile_border * 2.0);
// At typical values (triad_size >= 2.0, mask_triads_per_tile == 8):
// num_resized_mask_tiles = ~3.8
// Triad sizes are given in horizontal terms, so we need geom_max_aspect_ratio
// to relate them to vertical resolution. The widest we expect is:
// geom_max_aspect_ratio = 4.0/3.0 // Note: Shader passes need to know this!
// The fewer triads we tile across the screen, the larger each triad will be as a
// fraction of the viewport size, and the larger scale_y5 must be to draw a full
// num_resized_mask_tiles. Therefore, we must decide the smallest number of
// triads we'll guarantee can be displayed on screen. We'll set this according
// to 3-pixel triads at 768p resolution (the lowest anyone's likely to use):
// min_allowed_viewport_triads = 768.0*geom_max_aspect_ratio / 3.0 = 341.333333
// Now calculate the viewport scale that ensures we can draw resized_mask_tiles:
// min_scale_x = resized_mask_tiles * mask_triads_per_tile /
// min_allowed_viewport_triads
// scale_y5 = geom_max_aspect_ratio * min_scale_x
// # Some code might depend on equal scales:
// scale_x6 = scale_y5
// Given our default geom_max_aspect_ratio and min_allowed_viewport_triads:
// scale_y5 = 4.0/3.0 * 2.0/(341.33333 / 8.0) = 0.0625
// IMPORTANT: The scales MUST be calculated in this way. If you wish to change
// geom_max_aspect_ratio, update that constant in user-preset-constants.h!
program
filter: linear
format: rgba16f
width: 64 px
height: 6.25%
vertex: mask-resize-vertical.vs
fragment: mask-resize-vertical.fs
pixmap: textures/TileableLinearApertureGrille15Wide8And5d5SpacingResizeTo64.png
filter: linear
wrap: repeat
pixmap: textures/TileableLinearApertureGrille15Wide8And5d5Spacing.png
filter: linear
wrap: repeat
pixmap: textures/TileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacingResizeTo64.png
filter: linear
wrap: repeat
pixmap: textures/TileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacing.png
filter: linear
wrap: repeat
pixmap: textures/TileableLinearShadowMaskEDPResizeTo64.png
filter: linear
wrap: repeat
pixmap: textures/TileableLinearShadowMaskEDP.png
filter: linear
wrap: repeat
// Pass6: Lanczos-resize the phosphor mask horizontally. scale_x6 = scale_y5.
// TODO: Check again if the shaders actually require equal scales.
program
filter: nearest
vertex: mask-resize-horizontal.vs
fragment: mask-resize-horizontal.fs
format: rgba16f
// Pass7: Resample (misconverged) scanlines horizontally, apply halation, and
// apply the phosphor mask.
program
filter: linear
format: rgba16f
height: 100%
width: 100%
vertex: scanlines-horizontal-apply-mask.vs
fragment: scanlines-horizontal-apply-mask.fs
pixmap: textures/TileableLinearApertureGrille15Wide8And5d5SpacingResizeTo64.png
filter: linear
wrap: repeat
pixmap: textures/TileableLinearApertureGrille15Wide8And5d5Spacing.png
filter: linear
wrap: repeat
pixmap: textures/TileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacingResizeTo64.png
filter: linear
wrap: repeat
pixmap: textures/TileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacing.png
filter: linear
wrap: repeat
pixmap: textures/TileableLinearShadowMaskEDPResizeTo64.png
filter: linear
wrap: repeat
pixmap: textures/TileableLinearShadowMaskEDP.png
filter: linear
wrap: repeat
// Pass 8: Compute a brightpass. This will require reading the final mask.
program
filter: linear
format: rgba16f
vertex: brightpass.vs
fragment: brightpass.fs
// Pass 9: Blur the brightpass vertically
program
filter: linear
format: rgba16f
vertex: bloom-vertical.vs
fragment: bloom-vertical.fs
// Pass 10: Blur the brightpass horizontally and combine it with the dimpass:
program
filter: linear
format: rgba16f
height: 100%
width: 100%
vertex: bloom-horizontal-reconstitute.vs
fragment: bloom-horizontal-reconstitute.fs
// Pass 11: Compute curvature/AA:
program
filter: linear
format: rgba16f
vertex: geometry-aa-last-pass.vs
fragment: geometry-aa-last-pass.fs
output
filter: nearest

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 194 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 214 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 202 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

View file

@ -1,52 +0,0 @@
#version 150
////////////////////////////////////////////////////////
// GTU version 0.40
// Author: aliaspider - aliaspider@gmail.com
// License: GPLv3
////////////////////////////////////////////////////////
////////////////////////////////////////////////////////
// SETTINGS
////////////////////////////////////////////////////////
//#define CROP_OVERSCAN
#define TV_COLOR_LEVELS
//#define COMPOSITE_CONNECTION
//#define NO_SCANLINES
#define TV_HORIZONTAL_RESOLUTION 400.0
#define TV_VERTICAL_RESOLUTION 300.0
#define SIGNAL_RESOLUTION 280.0
#define SIGNAL_RESOLUTION_I 83.0
#define SIGNAL_RESOLUTION_Q 25.0
#define TV_DISPLAY_GAMMA 2.4
#define OUTPUT_DISPLAY_GAMMA 2.2
////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////
#define RGB_to_YIQ mat3x3( 0.299 , 0.595716 , 0.211456 , 0.587 , -0.274453 , -0.522591 , 0.114 , -0.321263 , 0.311135 )
#define YIQ_to_RGB mat3x3( 1.0 , 1.0 , 1.0 , 0.9563 , -0.2721 , -1.1070 , 0.6210 , -0.6474 , 1.7046 )
#define LEVELS(C) clamp((C -16/ 255.0)*255.0/(235.0-16.0),0.0,1.0)
uniform sampler2D source[];
uniform vec4 sourceSize[];
in Vertex {
vec2 texCoord;
};
out vec4 fragColor;
void main() {
vec3 c=texture2D(source[0], texCoord.xy).xyz;
#ifdef TV_COLOR_LEVELS
c=LEVELS(c);
#endif
#ifdef COMPOSITE_CONNECTION
c=RGB_to_YIQ*c;
#endif
fragColor = vec4(c, 1.0);
}

View file

@ -1,77 +0,0 @@
#version 150
////////////////////////////////////////////////////////
// GTU version 0.40
// Author: aliaspider - aliaspider@gmail.com
// License: GPLv3
////////////////////////////////////////////////////////
////////////////////////////////////////////////////////
// SETTINGS
////////////////////////////////////////////////////////
//#define CROP_OVERSCAN
#define TV_COLOR_LEVELS
//#define COMPOSITE_CONNECTION
//#define NO_SCANLINES
#define TV_HORIZONTAL_RESOLUTION 400.0
#define TV_VERTICAL_RESOLUTION 300.0
#define SIGNAL_RESOLUTION 280.0
#define SIGNAL_RESOLUTION_I 83.0
#define SIGNAL_RESOLUTION_Q 25.0
#define TV_DISPLAY_GAMMA 2.4
#define OUTPUT_DISPLAY_GAMMA 2.2
////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////
#define YIQ_to_RGB mat3x3( 1.0 , 1.0 , 1.0 , 0.9563 , -0.2721 , -1.1070 , 0.6210 , -0.6474 , 1.7046 )
#define pi 3.14159265358
#define a(x) abs(x)
#define d(x,b) (pi*b*min(a(x)+0.5,1.0/b))
#define e(x,b) (pi*b*min(max(a(x)-0.5,-1.0/b),1.0/b))
#define STU(x,b) ((d(x,b)+sin(d(x,b))-e(x,b)-sin(e(x,b)))/(2.0*pi))
#define X(i) (offset-(i))
#define GETC (texture(source[0], vec2(texCoord.x - X*sourceSize[0].z,texCoord.y)).xyz)
#ifdef COMPOSITE_CONNECTION
#define VAL vec3((c.x*STU(X,(SIGNAL_RESOLUTION*sourceSize[0].z))),(c.y*STU(X,(SIGNAL_RESOLUTION_I*sourceSize[0].z))),(c.z*STU(X,(SIGNAL_RESOLUTION_Q*sourceSize[0].z))))
#else
#define VAL (c*STU(X,(SIGNAL_RESOLUTION*sourceSize[0].z)))
#endif //COMPOSITE_CONNECTION
#define PROCESS(i) X=X(i);c=GETC;tempColor+=VAL;
uniform sampler2D source[];
uniform vec4 sourceSize[];
in Vertex {
vec2 texCoord;
};
out vec4 fragColor;
void main() {
float offset = fract((texCoord.x * sourceSize[0].x) - 0.5);
vec3 tempColor = vec3(0.0);
float X;
vec3 c;
PROCESS(-6)PROCESS(-5)PROCESS(-4)PROCESS(-3)PROCESS(-2)PROCESS(-1)PROCESS( 0)
PROCESS( 7)PROCESS( 6)PROCESS( 5)PROCESS( 4)PROCESS( 3)PROCESS( 2)PROCESS( 1)
#ifdef COMPOSITE_CONNECTION
tempColor=clamp(YIQ_to_RGB*tempColor,0.0,1.0);
#endif
tempColor=clamp(pow(tempColor,vec3(TV_DISPLAY_GAMMA)),0.0,1.0);
fragColor = vec4(tempColor,1.0);
}

View file

@ -1,46 +0,0 @@
#version 150
////////////////////////////////////////////////////////
// GTU version 0.40
// Author: aliaspider - aliaspider@gmail.com
// License: GPLv3
////////////////////////////////////////////////////////
////////////////////////////////////////////////////////
// SETTINGS
////////////////////////////////////////////////////////
//#define CROP_OVERSCAN
#define TV_COLOR_LEVELS
//#define COMPOSITE_CONNECTION
//#define NO_SCANLINES
#define TV_HORIZONTAL_RESOLUTION 400.0
#define TV_VERTICAL_RESOLUTION 300.0
#define SIGNAL_RESOLUTION 280.0
#define SIGNAL_RESOLUTION_I 83.0
#define SIGNAL_RESOLUTION_Q 25.0
#define TV_DISPLAY_GAMMA 2.4
#define OUTPUT_DISPLAY_GAMMA 2.2
////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////
in vec4 position;
in vec2 texCoord;
out Vertex{
vec2 texCoord;
}vertexOut;
void main(void){
#ifdef CROP_OVERSCAN
gl_Position=position;
gl_Position.x/=(224.0/240.0);
#else
gl_Position=position;
#endif
vertexOut.texCoord=texCoord;
}

View file

@ -1,63 +0,0 @@
#version 150
////////////////////////////////////////////////////////
// GTU version 0.40
// Author: aliaspider - aliaspider@gmail.com
// License: GPLv3
////////////////////////////////////////////////////////
////////////////////////////////////////////////////////
// SETTINGS
////////////////////////////////////////////////////////
//#define CROP_OVERSCAN
#define TV_COLOR_LEVELS
//#define COMPOSITE_CONNECTION
//#define NO_SCANLINES
#define TV_HORIZONTAL_RESOLUTION 400.0
#define TV_VERTICAL_RESOLUTION 300.0
#define SIGNAL_RESOLUTION 280.0
#define SIGNAL_RESOLUTION_I 83.0
#define SIGNAL_RESOLUTION_Q 25.0
#define TV_DISPLAY_GAMMA 2.4
#define OUTPUT_DISPLAY_GAMMA 2.2
////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////
#define pi 3.14159265358
#define a(x) abs(x)
#define d(x,b) (pi*b*min(a(x)+0.5,1.0/b))
#define e(x,b) (pi*b*min(max(a(x)-0.5,-1.0/b),1.0/b))
#define STU(x,b) ((d(x,b)+sin(d(x,b))-e(x,b)-sin(e(x,b)))/(2.0*pi))
#define X(i) (offset-(i))
#define GETC (texture(source[0], vec2(texCoord.x - X*sourceSize[0].z,texCoord.y)).xyz)
#define VAL (c*STU(X,(TV_HORIZONTAL_RESOLUTION*sourceSize[0].z)))
#define PROCESS(i) X=X(i);c=GETC;tempColor+=VAL;
uniform sampler2D source[];
uniform vec4 sourceSize[];
in Vertex {
vec2 texCoord;
};
out vec4 fragColor;
void main() {
float offset = fract((texCoord.x * sourceSize[0].x) - 0.5);
vec3 tempColor = vec3(0.0);
float X;
vec3 c;
PROCESS(-6)PROCESS(-5)PROCESS(-4)PROCESS(-3)PROCESS(-2)PROCESS(-1)PROCESS( 0)
PROCESS( 7)PROCESS( 6)PROCESS( 5)PROCESS( 4)PROCESS( 3)PROCESS( 2)PROCESS( 1)
// tempColor=pow(tempColor,vec3(1.0/2.2));
fragColor = vec4(tempColor,1.0);
}

View file

@ -1,78 +0,0 @@
#version 150
////////////////////////////////////////////////////////
// GTU version 0.40
// Author: aliaspider - aliaspider@gmail.com
// License: GPLv3
////////////////////////////////////////////////////////
////////////////////////////////////////////////////////
// SETTINGS
////////////////////////////////////////////////////////
//#define CROP_OVERSCAN
#define TV_COLOR_LEVELS
//#define COMPOSITE_CONNECTION
//#define NO_SCANLINES
#define TV_HORIZONTAL_RESOLUTION 400.0
#define TV_VERTICAL_RESOLUTION 300.0
#define SIGNAL_RESOLUTION 280.0
#define SIGNAL_RESOLUTION_I 83.0
#define SIGNAL_RESOLUTION_Q 25.0
#define TV_DISPLAY_GAMMA 2.4
#define OUTPUT_DISPLAY_GAMMA 2.2
////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////
#define SCANLINE_WIDTH (1.5*sourceSize[0].y/TV_VERTICAL_RESOLUTION)
uniform sampler2D source[];
uniform sampler2D texture[];
uniform vec4 sourceSize[];
in Vertex {
vec2 texCoord;
};
out vec4 fragColor;
#define GAMMAOUT(c0) (pow(c0, vec3(1.0/OUTPUTG2)))
#define pi 3.14159265358
#define GAUSS(x,w) ((sqrt(2.0) / (w)) * (exp((-2.0 * pi * (x) * (x)) / ((w) * (w)))))
#define Y(j) (offset.y-(j))
#define a(x) abs(x)
#define d(x,b) (pi*b*min(a(x)+0.5,1.0/b))
#define e(x,b) (pi*b*min(max(a(x)-0.5,-1.0/b),1.0/b))
#define STU(x,b) ((d(x,b)+sin(d(x,b))-e(x,b)-sin(e(x,b)))/(2.0*pi))
#define SOURCE(j) vec2(texCoord.x,texCoord.y - Y(j)*sourceSize[0].w)
#define C(j) (texture2D(source[0], SOURCE(j)).xyz)
#ifdef NO_SCANLINES
#define VAL(j) (C(j)*STU(Y(j),(TV_VERTICAL_RESOLUTION*sourceSize[0].w)))
#else
#define VAL(j) (C(j)*GAUSS(Y(j),SCANLINE_WIDTH))
#endif
void main() {
vec2 offset = fract((texCoord.xy * sourceSize[0].xy) - 0.5);
vec3 tempColor = vec3(0.0);
tempColor+=VAL(-3.0);
tempColor+=VAL(-2.0);
tempColor+=VAL(-1.0);
tempColor+=VAL(0.0);
tempColor+=VAL(1.0);
tempColor+=VAL(2.0);
tempColor+=VAL(3.0);
tempColor+=VAL(4.0);
fragColor = vec4(pow(tempColor,vec3(1.0/OUTPUT_DISPLAY_GAMMA)), 1.0);
}

View file

@ -1,46 +0,0 @@
#version 150
////////////////////////////////////////////////////////
// GTU version 0.40
// Author: aliaspider - aliaspider@gmail.com
// License: GPLv3
////////////////////////////////////////////////////////
////////////////////////////////////////////////////////
// SETTINGS
////////////////////////////////////////////////////////
//#define CROP_OVERSCAN
#define TV_COLOR_LEVELS
//#define COMPOSITE_CONNECTION
//#define NO_SCANLINES
#define TV_HORIZONTAL_RESOLUTION 400.0
#define TV_VERTICAL_RESOLUTION 300.0
#define SIGNAL_RESOLUTION 280.0
#define SIGNAL_RESOLUTION_I 83.0
#define SIGNAL_RESOLUTION_Q 25.0
#define TV_DISPLAY_GAMMA 2.4
#define OUTPUT_DISPLAY_GAMMA 2.2
////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////
in vec4 position;
in vec2 texCoord;
out Vertex{
vec2 texCoord;
}vertexOut;
void main(void){
#ifdef CROP_OVERSCAN
gl_Position=position;
gl_Position.y/=(224.0/240.0);
#else
gl_Position=position;
#endif
vertexOut.texCoord=texCoord;
}

View file

@ -1,28 +0,0 @@
program
width: 100%
height: 100%
format: rgba32f
filter: nearest
wrap: edge
fragment: GTU-pass1.fs
program
height: 100%
format: rgba32f
filter: nearest
wrap: edge
vertex: GTU-pass2.vs
fragment: GTU-pass2.fs
program
height: 100%
format: rgba32f
filter: nearest
wrap: edge
fragment: GTU-pass3.fs
program
format: rgba8
filter: nearest
wrap: edge
vertex: GTU-pass4.vs
fragment: GTU-pass4.fs
output
filter: nearest

View file

@ -1,88 +0,0 @@
#version 150
#in red
#in green
#in blue
#in gain
#in gamma
#in blacklevel
#in ambient
#in BGR
#define outgamma 2.2
uniform sampler2D source[];
uniform vec4 sourceSize[];
uniform vec4 targetSize;
in Vertex {
vec2 texCoord;
};
out vec4 fragColor;
#define fetch_offset(coord,offset) (pow(vec3(gain) * texelFetchOffset(source[0], (coord), 0, (offset)).rgb + vec3(blacklevel), vec3(gamma)) + vec3(ambient))
// integral of (1 - x^2 - x^4 + x^6)^2
const float coeffs_x[] = float[](1.0, -2.0/3.0, -1.0/5.0, 4.0/7.0, -1.0/9.0, -2.0/11.0, 1.0/13.0);
// integral of (1 - 2x^4 + x^6)^2
const float coeffs_y[] = float[](1.0, 0.0, -4.0/5.0, 2.0/7.0, 4.0/9.0, -4.0/11.0, 1.0/13.0);
float intsmear_func(float z, float coeffs[7])
{
float z2 = z*z;
float zn = z;
float ret = 0.0;
for (int i = 0; i < 7; i++) {
ret += zn*coeffs[i];
zn *= z2;
}
return ret;
}
float intsmear(float x, float dx, float d, float coeffs[7])
{
float zl = clamp((x-dx*0.5)/d,-1.0,1.0);
float zh = clamp((x+dx*0.5)/d,-1.0,1.0);
return d * ( intsmear_func(zh,coeffs) - intsmear_func(zl,coeffs) )/dx;
}
void main()
{
vec2 texelSize = 1.0 / sourceSize[0].xy;
vec2 range = sourceSize[0].xy / (targetSize.xy * sourceSize[0].xy);
vec3 cred = pow(red, vec3(outgamma));
vec3 cgreen = pow(green, vec3(outgamma));
vec3 cblue = pow(blue, vec3(outgamma));
ivec2 tli = ivec2(floor(texCoord/texelSize-vec2(0.4999)));
vec3 lcol, rcol;
float subpix = (texCoord.x/texelSize.x - 0.4999 - float(tli.x))*3.0;
float rsubpix = range.x/texelSize.x * 3.0;
lcol = vec3(intsmear(subpix+1.0,rsubpix, 1.5, coeffs_x),
intsmear(subpix ,rsubpix, 1.5, coeffs_x),
intsmear(subpix-1.0,rsubpix, 1.5, coeffs_x));
rcol = vec3(intsmear(subpix-2.0,rsubpix, 1.5, coeffs_x),
intsmear(subpix-3.0,rsubpix, 1.5, coeffs_x),
intsmear(subpix-4.0,rsubpix, 1.5, coeffs_x));
#ifdef BGR
lcol.rgb = lcol.bgr;
rcol.rgb = rcol.bgr;
#endif
float tcol, bcol;
subpix = texCoord.y/texelSize.y - 0.4999 - float(tli.y);
rsubpix = range.y/texelSize.y;
tcol = intsmear(subpix ,rsubpix, 0.63, coeffs_y);
bcol = intsmear(subpix-1.0,rsubpix, 0.63, coeffs_y);
vec3 topLeftColor = fetch_offset(tli, ivec2(0,0)) * lcol * vec3(tcol);
vec3 bottomRightColor = fetch_offset(tli, ivec2(1,1)) * rcol * vec3(bcol);
vec3 bottomLeftColor = fetch_offset(tli, ivec2(0,1)) * lcol * vec3(bcol);
vec3 topRightColor = fetch_offset(tli, ivec2(1,0)) * rcol * vec3(tcol);
vec3 averageColor = topLeftColor + bottomRightColor + bottomLeftColor + topRightColor;
averageColor = mat3x3(cred, cgreen, cblue) * averageColor;
fragColor = vec4(pow(averageColor,vec3(1.0/outgamma)),0.0);
}

View file

@ -1,23 +0,0 @@
settings
persistence: 0.5
red: vec3(1,0,0)
green: vec3(0,1,0)
blue: vec3(0,0,1)
gain: 1.0
gamma: 3.0
blacklevel: 0.05
ambient: 0.0
BGR
input
history: 8
filter: nearest
program
fragment: motion-blur.fs
filter: nearest
width: 100%
height: 100%
program
fragment: lcd-grid.fs

View file

@ -1,23 +0,0 @@
#version 150
uniform sampler2D source[];
uniform sampler2D history[];
in Vertex {
vec2 texCoord;
};
out vec4 fragColor;
void main() {
vec4 color = pow(texture(history[7], texCoord).rgba, vec4(2.2));
color = (color + pow(texture(history[6], texCoord).rgba, vec4(2.2))) / 2.0;
color = (color + pow(texture(history[5], texCoord).rgba, vec4(2.2))) / 2.0;
color = (color + pow(texture(history[4], texCoord).rgba, vec4(2.2))) / 2.0;
color = (color + pow(texture(history[3], texCoord).rgba, vec4(2.2))) / 2.0;
color = (color + pow(texture(history[2], texCoord).rgba, vec4(2.2))) / 2.0;
color = (color + pow(texture(history[1], texCoord).rgba, vec4(2.2))) / 2.0;
color = (color + pow(texture(history[0], texCoord).rgba, vec4(2.2))) / 2.0;
color = (color + pow(texture(source[0], texCoord).rgba, vec4(2.2))) / 2.0;
fragColor = pow(color, vec4(1.0 / 2.2));
}

View file

@ -1,24 +0,0 @@
program
width: 100%
height: 100%
filter: nearest
fragment: mdapt-pass1.fs
wrap: edge
program
width: 100%
height: 100%
filter: nearest
fragment: mdapt-pass2.fs
wrap: edge
program
width: 100%
height: 100%
filter: nearest
fragment: mdapt-pass3.fs
wrap: edge
program
width: 100%
height: 100%
filter: nearest
fragment: mdapt-pass4.fs
wrap: edge

View file

@ -1,200 +0,0 @@
// This is a port of the original CG shader to the quark format
// the original shader can be found here :
// https://github.com/libretro/common-shaders/tree/master/dithering/mdapt-4p
/*
Merge Dithering and Pseudo Transparency Shader v1.5 - Pass 1
by Sp00kyFox, 2013
Finds specific patterns and tags their central pixel.
*/
#version 150
//#define HORI
//#define VERT
#define dtt vec3(65536,255,1)
#define eq_threshold 5.0
uniform sampler2D source[];
uniform vec4 sourceSize[];
uniform vec4 targetSize;
in Vertex{
vec2 texCoord;
};
out vec4 fragColor;
float reduce(vec3 color)
{
return dot(color, dtt);
}
float df(float A, float B)
{
return abs(A-B);
}
bool eq(float A, float B)
{
return (A == B);
}
float remapTo01(float v, float low, float high)
{
return clamp((v - low)/(high-low),0.0,1.0);
}
void main(void) {
vec2 pos = texCoord*sourceSize[0].xy; // pos = pixel position
vec2 dir = sign(pos); // dir = pixel direction
vec2 g1 = dir*vec2(sourceSize[0].z,0.0);
vec2 g2 = dir*vec2(0.0,sourceSize[0].w);;
/*
U3
UUL U2 UUR
ULL UL U1 UR URR
L3 L2 L1 C R1 R2 R3
DLL DL D1 DR DRR
DDL D2 DDR
D3
*/
vec3 c = texture(source[0], texCoord).xyz;
vec3 l1 = texture(source[0], texCoord - g1).xyz;
vec3 l2 = texture(source[0], texCoord - 2*g1).xyz;
vec3 r1 = texture(source[0], texCoord + g1).xyz;
vec3 r2 = texture(source[0], texCoord + 2*g1).xyz;
vec3 u1 = texture(source[0], texCoord - g2).xyz;
vec3 u2 = texture(source[0], texCoord - 2*g2).xyz;
vec3 d1 = texture(source[0], texCoord + g2).xyz;
vec3 d2 = texture(source[0], texCoord + 2*g2).xyz;
vec3 ul = texture(source[0], texCoord - g1 - g2).xyz;
vec3 ur = texture(source[0], texCoord + g1 - g2).xyz;
vec3 dl = texture(source[0], texCoord - g1 + g2).xyz;
vec3 dr = texture(source[0], texCoord + g1 + g2).xyz;
vec3 ull = texture(source[0], texCoord - 2*g1 - g2).xyz;
vec3 uul = texture(source[0], texCoord - g1 - 2*g2).xyz;
vec3 uur = texture(source[0], texCoord + g1 - 2*g2).xyz;
vec3 urr = texture(source[0], texCoord + 2*g1 - g2).xyz;
vec3 drr = texture(source[0], texCoord + 2*g1 + g2).xyz;
vec3 ddr = texture(source[0], texCoord + g1 + 2*g2).xyz;
vec3 ddl = texture(source[0], texCoord - g1 + 2*g2).xyz;
vec3 dll = texture(source[0], texCoord - 2*g1 + g2).xyz;
vec3 l3 = texture(source[0], texCoord - 3*g1).xyz;
vec3 r3 = texture(source[0], texCoord + 3*g1).xyz;
vec3 u3 = texture(source[0], texCoord - 3*g2).xyz;
vec3 d3 = texture(source[0], texCoord + 3*g2).xyz;
float C = reduce( c );
float L1 = reduce( l1 ); float U1 = reduce( u1 );
float L2 = reduce( l2 ); float U2 = reduce( u2 );
float R1 = reduce( r1 ); float D1 = reduce( d1 );
float R2 = reduce( r2 ); float D2 = reduce( d2 );
float UL = reduce( ul ); float L3 = reduce( l3 );
float UR = reduce( ur ); float R3 = reduce( r3 );
float DL = reduce( dl ); float U3 = reduce( u3 );
float DR = reduce( dr ); float D3 = reduce( d3 );
float ULL = reduce( ull ); float DRR = reduce( drr );
float UUL = reduce( uul ); float DDR = reduce( ddr );
float UUR = reduce( uur ); float DDL = reduce( ddl );
float URR = reduce( urr ); float DLL = reduce( dll );
/*
tag values:
0 nothing
checkerboard pattern
9 DL
8 DR
7 UR
6 UL
5 full
horizontal two-line checkerboard
4 bottom line
3 upper line
vertical two-line checkerboard
2 left line
1 right line
one line dither
-1 horizontal
-2 vertical
*/
float type=0;
// checkerboard pattern
if(!eq(C,D1) && !eq(C,U1) && !eq(C,L1) && !eq(C,R1))
{
if(eq(C,UL))
{
if(eq(C,UR))
{
if(eq(C,DR))
{
if(eq(C,DL))
type = 5;
else if(!eq(D1,L1) || eq(D1,DL))
type = 9;
}
else
{
if(eq(C,DL) && (!eq(D1,R1) || eq(D1,DR)))
type = 8;
}
}
else
{
if(eq(C,DR) && eq(C,DL) && (!eq(U1,R1) || eq(U1,UR)))
type = 7;
}
}
else if(eq(C,UR) && eq(C,DR) && eq(C,DL) && (!eq(U1,L1) || eq(U1,UL)))
type = 6;
}
// horizontal two-line checkerboard
else if(eq(C,L2) && eq(C,R2) && eq(C,UL) && eq(C,UR) && !eq(C,L1) && !eq(C,R1) && !eq(C,ULL) && !eq(C,U1) && !eq(C,URR))
{
type = 4;
}
else if(eq(C,L2) && eq(C,R2) && eq(C,DL) && eq(C,DR) && !eq(C,L1) && !eq(C,R1) && !eq(C,DLL) && !eq(C,D1) && !eq(C,DRR))
{
type = 3;
}
// vertical two-line checkerboard
else if(eq(C,U2) && eq(C,D2) && eq(C,UR) && eq(C,DR) && !eq(C,U1) && !eq(C,D1) && !eq(C,R1) && !eq(C,UUR) && !eq(C,DDR))
{
type = 2;
}
else if(eq(C,U2) && eq(C,D2) && eq(C,UL) && eq(C,DL) && !eq(C,U1) && !eq(C,D1) && !eq(C,L1) && !eq(C,UUL) && !eq(C,DDL))
{
type = 1;
}
#ifdef HORI
// horizontal one line dither
else if(eq(C,L2) && eq(C,R2) && eq(L1,R1) && !eq(C,L1) && !eq(C,L3) && !eq(C,R3))
type = -1;
#endif
#ifdef VERT
// vertical one line dither
else if(eq(C,U2) && eq(C,D2) && eq(U1,D1) && !eq(C,U1) && !eq(C,U3) && !eq(C,D3))
type = -2;
#endif
fragColor=vec4(c, remapTo01(type+2, 0, 15));
}

View file

@ -1,161 +0,0 @@
// This is a port of the original CG shader to the quark format
// the original shader can be found here :
// https://github.com/libretro/common-shaders/tree/master/dithering/mdapt-4p
/*
Merge Dithering and Pseudo Transparency Shader v1.5 - Pass 1
by Sp00kyFox, 2013
Finds specific patterns and tags their central pixel.
*/
#version 150
// Radius of the area where the algorithm looks for other detected pixels.
#define rad 2
// Minimal count of detection pixels in search area to be rated as valid.
#define minimum 3
uniform sampler2D source[];
uniform vec4 sourceSize[];
uniform vec4 targetSize;
in Vertex{
vec2 texCoord;
};
out vec4 fragColor;
float remapTo01(float v, float low, float high)
{
return clamp((v - low)/(high-low),0.0,1.0);
}
float remapFrom01(float v, float low, float high)
{
return round(mix(low, high, v));
}
void main(void) {
vec2 pos = texCoord*sourceSize[0].xy; // pos = pixel position
vec2 dir = sign(pos); // dir = pixel direction
vec2 g1 = dir*vec2(sourceSize[0].z,0.0);
vec2 g2 = dir*vec2(0.0,sourceSize[0].w);
vec4 CC = texture(source[0], texCoord).xyzw;
float C = remapFrom01(CC.w, 0, 15) - 2;
if(C == 0){
fragColor=CC;
return;
}
/*
tag values:
0 nothing
checkerboard pattern
9 DL
8 DR
7 UR
6 UL
5 full
horizontal two-line checkerboard
4 bottom line
3 upper line
vertical two-line checkerboard
2 left line
1 right line
one line dither
-1 horizontal
-2 vertical
*/
int hits = 0;
if(C > 0)
{
// for(int x=-rad; x<=rad; x++)
// {
// for(int y=-rad; y<=rad; y++)
// {
// hits += ((remapFrom01(texture(source[0], texCoord + (x*g1) + (y*g2)).x, 0, 15) - 2) > 0) ? 1 : 0;
// }
// }
hits += ((remapFrom01(texture(source[0], texCoord + (-2*g1) + (-2*g2)).w, 0, 15) - 2) > 0) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + (-2*g1) + (-1*g2)).w, 0, 15) - 2) > 0) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + (-2*g1) + ( 0*g2)).w, 0, 15) - 2) > 0) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + (-2*g1) + ( 1*g2)).w, 0, 15) - 2) > 0) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + (-2*g1) + ( 2*g2)).w, 0, 15) - 2) > 0) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + (-1*g1) + (-2*g2)).w, 0, 15) - 2) > 0) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + (-1*g1) + (-1*g2)).w, 0, 15) - 2) > 0) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + (-1*g1) + ( 0*g2)).w, 0, 15) - 2) > 0) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + (-1*g1) + ( 1*g2)).w, 0, 15) - 2) > 0) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + (-1*g1) + ( 2*g2)).w, 0, 15) - 2) > 0) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + ( 0*g1) + (-2*g2)).w, 0, 15) - 2) > 0) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + ( 0*g1) + (-1*g2)).w, 0, 15) - 2) > 0) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + ( 0*g1) + ( 0*g2)).w, 0, 15) - 2) > 0) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + ( 0*g1) + ( 1*g2)).w, 0, 15) - 2) > 0) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + ( 0*g1) + ( 2*g2)).w, 0, 15) - 2) > 0) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + ( 1*g1) + (-2*g2)).w, 0, 15) - 2) > 0) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + ( 1*g1) + (-1*g2)).w, 0, 15) - 2) > 0) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + ( 1*g1) + ( 0*g2)).w, 0, 15) - 2) > 0) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + ( 1*g1) + ( 1*g2)).w, 0, 15) - 2) > 0) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + ( 1*g1) + ( 2*g2)).w, 0, 15) - 2) > 0) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + ( 2*g1) + (-2*g2)).w, 0, 15) - 2) > 0) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + ( 2*g1) + (-1*g2)).w, 0, 15) - 2) > 0) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + ( 2*g1) + ( 0*g2)).w, 0, 15) - 2) > 0) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + ( 2*g1) + ( 1*g2)).w, 0, 15) - 2) > 0) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + ( 2*g1) + ( 2*g2)).w, 0, 15) - 2) > 0) ? 1 : 0;
}
else
{
// for(int x=-rad; x<=rad; x++)
// {
// for(int y=-rad; y<=rad; y++)
// {
// hits += ((remapFrom01(texture(source[0], texCoord + (x*g1) + (y*g2)).x, 0, 15) - 2) == C) ? 1 : 0;
// }
// }
hits += ((remapFrom01(texture(source[0], texCoord + (-2*g1) + (-2*g2)).w, 0, 15) - 2) == C) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + (-2*g1) + (-1*g2)).w, 0, 15) - 2) == C) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + (-2*g1) + ( 0*g2)).w, 0, 15) - 2) == C) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + (-2*g1) + ( 1*g2)).w, 0, 15) - 2) == C) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + (-2*g1) + ( 2*g2)).w, 0, 15) - 2) == C) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + (-1*g1) + (-2*g2)).w, 0, 15) - 2) == C) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + (-1*g1) + (-1*g2)).w, 0, 15) - 2) == C) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + (-1*g1) + ( 0*g2)).w, 0, 15) - 2) == C) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + (-1*g1) + ( 1*g2)).w, 0, 15) - 2) == C) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + (-1*g1) + ( 2*g2)).w, 0, 15) - 2) == C) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + ( 0*g1) + (-2*g2)).w, 0, 15) - 2) == C) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + ( 0*g1) + (-1*g2)).w, 0, 15) - 2) == C) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + ( 0*g1) + ( 0*g2)).w, 0, 15) - 2) == C) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + ( 0*g1) + ( 1*g2)).w, 0, 15) - 2) == C) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + ( 0*g1) + ( 2*g2)).w, 0, 15) - 2) == C) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + ( 1*g1) + (-2*g2)).w, 0, 15) - 2) == C) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + ( 1*g1) + (-1*g2)).w, 0, 15) - 2) == C) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + ( 1*g1) + ( 0*g2)).w, 0, 15) - 2) == C) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + ( 1*g1) + ( 1*g2)).w, 0, 15) - 2) == C) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + ( 1*g1) + ( 2*g2)).w, 0, 15) - 2) == C) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + ( 2*g1) + (-2*g2)).w, 0, 15) - 2) == C) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + ( 2*g1) + (-1*g2)).w, 0, 15) - 2) == C) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + ( 2*g1) + ( 0*g2)).w, 0, 15) - 2) == C) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + ( 2*g1) + ( 1*g2)).w, 0, 15) - 2) == C) ? 1 : 0;
hits += ((remapFrom01(texture(source[0], texCoord + ( 2*g1) + ( 2*g2)).w, 0, 15) - 2) == C) ? 1 : 0;
fragColor=CC;
return;
}
if(hits < minimum)
fragColor=vec4(CC.xyz, remapTo01(2, 0, 15));
else
fragColor=CC;
}

View file

@ -1,175 +0,0 @@
// This is a port of the original CG shader to the quark format
// the original shader can be found here :
// https://github.com/libretro/common-shaders/tree/master/dithering/mdapt-4p
/*
Merge Dithering and Pseudo Transparency Shader v1.5 - Pass 3
by Sp00kyFox, 2013
Tags the rest of the detected pattern from pass 1.
*/
#version 150
uniform sampler2D source[];
uniform vec4 sourceSize[];
uniform vec4 targetSize;
in Vertex{
vec2 texCoord;
};
out vec4 fragColor;
float remapTo01(float v, float low, float high)
{
return clamp((v - low)/(high-low),0.0,1.0);
}
float remapFrom01(float v, float low, float high)
{
return round(mix(low, high, v));
}
void main(void) {
vec2 pos = texCoord*sourceSize[0].xy; // pos = pixel position
vec2 dir = sign(pos); // dir = pixel direction
vec2 g1 = dir*vec2(sourceSize[0].z,0.0);
vec2 g2 = dir*vec2(0.0,sourceSize[0].w);
/*
U2
UL U1 UR
L2 L1 xC R1 R2
DL D1 DR
D2
*/
vec4 xC = texture(source[0], texCoord).xyzw;
vec4 xL1 = texture(source[0], texCoord - g1).xyzw;
vec4 xL2 = texture(source[0], texCoord - 2*g1).xyzw;
vec4 xR1 = texture(source[0], texCoord + g1).xyzw;
vec4 xR2 = texture(source[0], texCoord + 2*g1).xyzw;
vec4 xU1 = texture(source[0], texCoord - g2).xyzw;
vec4 xU2 = texture(source[0], texCoord - 2*g2).xyzw;
vec4 xD1 = texture(source[0], texCoord + g2).xyzw;
vec4 xD2 = texture(source[0], texCoord + 2*g2).xyzw;
vec4 xUL = texture(source[0], texCoord - g1 - g2).xyzw;
vec4 xUR = texture(source[0], texCoord + g1 - g2).xyzw;
vec4 xDL = texture(source[0], texCoord - g1 + g2).xyzw;
vec4 xDR = texture(source[0], texCoord + g1 + g2).xyzw;
float C = remapFrom01(xC.w, 0, 15) - 2;
float L1 = remapFrom01(xL1.w, 0, 15) - 2;
float L2 = remapFrom01(xL2.w, 0, 15) - 2;
float R1 = remapFrom01(xR1.w, 0, 15) - 2;
float R2 = remapFrom01(xR2.w, 0, 15) - 2;
float U1 = remapFrom01(xU1.w, 0, 15) - 2;
float U2 = remapFrom01(xU2.w, 0, 15) - 2;
float D1 = remapFrom01(xD1.w, 0, 15) - 2;
float D2 = remapFrom01(xD2.w, 0, 15) - 2;
float UL = remapFrom01(xUL.w, 0, 15) - 2;
float UR = remapFrom01(xUR.w, 0, 15) - 2;
float DL = remapFrom01(xDL.w, 0, 15) - 2;
float DR = remapFrom01(xDR.w, 0, 15) - 2;
/*
tag values:
0 nothing
checkerboard pattern
9 DL
8 DR
7 UR
6 UL
5 full
horizontal two-line checkerboard
4 bottom line
3 upper line
vertical two-line checkerboard
2 left line
1 right line
one line dither
-1 horizontal
-2 vertical
*/
// checkerboard pattern
if(U1 == 5 || D1 == 5 || L1 == 5 || R1 == 5 || UL == 5 || UR == 5 || DR == 5 || DL == 5)
{
fragColor=vec4(xC.xyz, remapTo01(5+2, 0, 15));
return ;
}
if(U1 == 6 || L1 == 6 || UL == 6 || UR == 6 || DL == 6) // UL
{
fragColor=vec4(xC.xyz, remapTo01(6+2, 0, 15));
return ;
}
if(U1 == 7 || R1 == 7 || UL == 7 || UR == 7 || DR == 7) // UR
{
fragColor=vec4(xC.xyz, remapTo01(7+2, 0, 15));
return ;
}
if(D1 == 8 || R1 == 8 || UR == 8 || DR == 8 || DL == 8) // DR
{
fragColor=vec4(xC.xyz, remapTo01(8+2, 0, 15));
return ;
}
if(D1 == 9 || L1 == 9 || UL == 9 || DR == 9 || DL == 9) // DL
{
fragColor=vec4(xC.xyz, remapTo01(9+2, 0, 15));
return ;
}
// horizontal two-line checkerboard
if (L2 == 4 || L1 == 4 || R1 == 4 || R2 == 4 || DL == 4 || D1 == 4 || DR == 4)
{
fragColor=vec4(xC.xyz, remapTo01(4+2, 0, 15));
return ;
}
if (L2 == 3 || L1 == 3 || R1 == 3 || R2 == 3 || UL == 3 || U1 == 3 || UR == 3)
{
fragColor=vec4(xC.xyz, remapTo01(3+2, 0, 15));
return ;
}
// vertical two-line checkerboard
if (U2 == 2 || U1 == 2 || D1 == 2 || D2 == 2 || UL == 2 || L1 == 2 || DL == 2)
{
fragColor=vec4(xC.xyz, remapTo01(2+2, 0, 15));
return ;
}
if (U2 == 1 || U1 == 1 || D1 == 1 || D2 == 1 || UR == 1 || R1 == 1 || DR == 1)
{
fragColor=vec4(xC.xyz, remapTo01(1+2, 0, 15));
return ;
}
if(C > 0){
fragColor=xC;
return ;
}
// horizontal one line dither
if (L2 == -1 || L1 == -1 || R1 == -1 || R2 == -1)
{
fragColor=vec4(xC.xyz, remapTo01(-1+2, 0, 15));
return ;
}
// vertical one line dither
if (U2 == -2 || U1 == -2 || D1 == -2 || D2 == -2)
{
fragColor=vec4(xC.xyz, remapTo01(-2+2, 0, 15));
return;
}
fragColor=xC;
}

View file

@ -1,192 +0,0 @@
// This is a port of the original CG shader to the quark format
// the original shader can be found here :
// https://github.com/libretro/common-shaders/tree/master/dithering/mdapt-4p
/*
Merge Dithering and Pseudo Transparency Shader v1.5 - Pass 4
by Sp00kyFox, 2013
Blends tagged pixels with tagged neighbors.
*/
#version 150
uniform sampler2D source[];
uniform vec4 sourceSize[];
uniform vec4 targetSize;
in Vertex{
vec2 texCoord;
};
out vec4 fragColor;
bool eq(vec4 A, vec4 B)
{
return (A.x == B.x && A.y == B.y && A.z == B.z);
}
float remapFrom01(float v, float low, float high)
{
return round(mix(low, high, v));
}
vec3 merge3(vec4 C, vec4 A, vec4 B, float tag)
{
if(A.w == tag)
{
if(B.w == tag)
return 0.5*C.xyz + 0.25*(A.xyz + B.xyz);
else
return 0.5*(C.xyz + A.xyz);
}
else if(B.w == tag)
return 0.5*(C.xyz + B.xyz);
else
return C.xyz;
}
vec3 merge9(vec4 C, vec4 UL, vec4 UR, vec4 DL, vec4 DR, vec4 U1, vec4 D1, vec4 L1, vec4 R1)
{
//return 0.25*C.xyz + 0.0625*(UL.xyz + UR.xyz + DR.xyz + DL.xyz) + 0.125*(L1.xyz + R1.xyz + D1.xyz + U1.xyz);
vec3 B = vec3(0.0);
vec3 W = vec3(0.0);
float cntB = 0;
float cntW = 0;
if(UL.w > 0 || eq(UL,C) || (D1.w > 0 && eq(UL,D1)) || (R1.w > 0 && eq(UL,R1)) )
{
B = B+UL.xyz;
cntB++;
}
if(UR.w > 0 || eq(UR,C) || (D1.w > 0 && eq(UR,D1)) || (L1.w > 0 && eq(UR,L1)) )
{
B = B+UR.xyz;
cntB++;
}
if(DL.w > 0 || eq(DL,C) || (U1.w > 0 && eq(DL,U1)) || (R1.w > 0 && eq(DL,R1)) )
{
B = B+DL.xyz;
cntB++;
}
if(DR.w > 0 || eq(DR,C) || (U1.w > 0 && eq(DR,U1)) || (L1.w > 0 && eq(DR,L1)) )
{
B = B+DR.xyz;
cntB++;
}
if(U1.w > 0 || eq(U1,C) || (D1.w > 0 && eq(U1,D1)) )
{
W = W+U1.xyz;
cntW++;
}
if(D1.w > 0 || eq(D1,C) || (U1.w > 0 && eq(D1,U1)) )
{
W = W+D1.xyz;
cntW++;
}
if(L1.w > 0 || eq(L1,C) || (R1.w > 0 && eq(L1,R1)) )
{
W = W+L1.xyz;
cntW++;
}
if(R1.w > 0 || eq(R1,C) || (L1.w > 0 && eq(R1,L1)) )
{
W = W+R1.xyz;
cntW++;
}
if(cntB == 0)
{
if(cntW == 0)
return C.xyz;
else
return 0.5*C.xyz + (1/(cntW*2))*W;
}
if(cntW == 0)
return 0.5*C.xyz + (1/(cntB*2))*B;
else
return 0.25*C.xyz + (1/(cntB*4))*B + (1/(cntW*2))*W;
}
void main(void) {
vec2 pos = texCoord*sourceSize[0].xy; // pos = pixel position
vec2 dir = sign(pos); // dir = pixel direction
vec2 g1 = dir*vec2(sourceSize[0].z,0.0);
vec2 g2 = dir*vec2(0.0,sourceSize[0].w);
/*
UL U1 UR
L1 C R1
DL D1 DR
*/
vec4 C = texture(source[0], texCoord).xyzw;
vec4 L1 = texture(source[0], texCoord - g1).xyzw;
vec4 R1 = texture(source[0], texCoord + g1).xyzw;
vec4 U1 = texture(source[0], texCoord - g2).xyzw;
vec4 D1 = texture(source[0], texCoord + g2).xyzw;
vec4 UL = texture(source[0], texCoord - g1 - g2).xyzw;
vec4 UR = texture(source[0], texCoord + g1 - g2).xyzw;
vec4 DL = texture(source[0], texCoord - g1 + g2).xyzw;
vec4 DR = texture(source[0], texCoord + g1 + g2).xyzw;
C.w = remapFrom01(C.w, 0, 15) - 2;
L1.w = remapFrom01(L1.w, 0, 15) - 2;
R1.w = remapFrom01(R1.w, 0, 15) - 2;
U1.w = remapFrom01(U1.w, 0, 15) - 2;
D1.w = remapFrom01(D1.w, 0, 15) - 2;
UL.w = remapFrom01(UL.w, 0, 15) - 2;
UR.w = remapFrom01(UR.w, 0, 15) - 2;
DL.w = remapFrom01(DL.w, 0, 15) - 2;
DR.w = remapFrom01(DR.w, 0, 15) - 2;
/*
tag values:
0 nothing
checkerboard pattern
9 DL
8 DR
7 UR
6 UL
5 full
horizontal two-line checkerboard
4 bottom line
3 upper line
vertical two-line checkerboard
2 left line
1 right line
one line dither
-1 horizontal
-2 vertical
*/
// checkerboard pattern
if(C.w > 0){
fragColor=vec4(merge9(C,UL,UR,DL,DR,U1,D1,L1,R1),0);
return;
}
// horizontal one line dither
if(C.w == -1){
fragColor=vec4(merge3(C,L1,R1,-1),0);
return;
}
// vertical one line dither
if(C.w == -2){
fragColor=vec4(merge3(C,U1,D1,-2),0);
return;
}
fragColor=vec4(C.xyz, 1.0);
}

View file

@ -1,229 +0,0 @@
#version 150
// This is a port of the NTSC encode/decode shader pair in MAME and MESS, modified to use only
// one pass rather than an encode pass and a decode pass. It accurately emulates the sort of
// signal decimation one would see when viewing a composite signal, though it could benefit from a
// pre-pass to re-size the input content to more accurately reflect the actual size that would
// be incoming from a composite signal source.
//
// To encode the composite signal, I convert the RGB value to YIQ, then subsequently evaluate
// the standard NTSC composite equation. Four composite samples per RGB pixel are generated from
// the incoming linearly-interpolated texels.
//
// The decode pass implements a Fixed Impulse Response (FIR) filter designed by MAME/MESS contributor
// "austere" in matlab (if memory serves correctly) to mimic the behavior of a standard television set
// as closely as possible. The filter window is 83 composite samples wide, and there is an additional
// notch filter pass on the luminance (Y) values in order to strip the color signal from the luminance
// signal prior to processing.
//
// Yes, this code could greatly use some cleaning up.
// ported from UltraMoogleMan's "Full MAME/MESS Shader Pipe" shadertoy: https://www.shadertoy.com/view/ldf3Rf
// license: presumably MAME's license at the time, which was noncommercial
uniform sampler2D source[];
uniform vec4 sourceSize[];
in Vertex {
vec2 vTexCoord;
};
out vec4 FragColor;
// Useful Constants
const vec4 Zero = vec4(0.0);
const vec4 Half = vec4(0.5);
const vec4 One = vec4(1.0);
const vec4 Two = vec4(2.0);
const vec3 Gray = vec3(0.3, 0.59, 0.11);
const float Pi = 3.1415926535;
const float Pi2 = 6.283185307;
// NTSC Constants
const vec4 A = vec4(0.5);
const vec4 A2 = vec4(1.0);
const vec4 B = vec4(0.5);
const float P = 1.0;
const float CCFrequency = 3.59754545;
const float NotchUpperFrequency = 5.59754545; //3.59754545 + 2.0;
const float NotchLowerFrequency = 1.59754545; //3.59754545 - 2.0;
const float YFrequency = 6.0;
const float IFrequency = 1.2;
const float QFrequency = 0.6;
const float NotchHalfWidth = 2.0;
const float ScanTime = 52.6;
const float Pi2ScanTime = 330.4955471482;// 6.283185307 * 52.6;
const float MaxC = 2.1183;
const vec4 YTransform = vec4(0.299, 0.587, 0.114, 0.0);
const vec4 ITransform = vec4(0.595716, -0.274453, -0.321263, 0.0);
const vec4 QTransform = vec4(0.211456, -0.522591, 0.311135, 0.0);
const vec3 YIQ2R = vec3(1.0, 0.956, 0.621);
const vec3 YIQ2G = vec3(1.0, -0.272, -0.647);
const vec3 YIQ2B = vec3(1.0, -1.106, 1.703);
const vec4 MinC = vec4(-1.1183);
const vec4 CRange = vec4(3.2366);
const vec4 InvCRange = vec4(1.0/3.2366);
const float Pi2Length = Pi2 / 63.0;
const vec4 NotchOffset = vec4(0.0, 1.0, 2.0, 3.0);
vec4 W = vec4(Pi2 * CCFrequency * ScanTime);
// Color Convolution Constants
const vec3 RedMatrix = vec3(1.0, 0.0, 0.0);
const vec3 GrnMatrix = vec3(0.0, 1.0, 0.0);
const vec3 BluMatrix = vec3(0.0, 0.0, 1.0);
const vec3 DCOffset = vec3(0.0, 0.0, 0.0);
const vec3 ColorScale = vec3(0.95, 0.95, 0.95);
const float Saturation = 1.4;
// Deconverge Constants
const vec3 ConvergeX = vec3(-0.4, 0.0, 0.2);
const vec3 ConvergeY = vec3( 0.0, -0.4, 0.2);
const vec3 RadialConvergeX = vec3(1.0, 1.0, 1.0);
const vec3 RadialConvergeY = vec3(1.0, 1.0, 1.0);
// Scanline/Pincushion Constants
const float PincushionAmount = 0.015;
const float CurvatureAmount = 0.015;
//const float ScanlineAmount = 0.175; <- move to parameter
const float ScanlineScale = 1.0;
const float ScanlineHeight = 1.0;
const float ScanlineBrightScale = 1.0;
const float ScanlineBrightOffset = 0.0;
const float ScanlineOffset = 0.0;
const vec3 Floor = vec3(0.05, 0.05, 0.05);
// 60Hz Bar Constants
const float SixtyHertzRate = (60.0 / 59.97 - 1.0); // Difference between NTSC and line frequency
const float SixtyHertzScale = 0.1;
vec4 CompositeSample(vec2 UV, vec2 InverseRes) {
vec2 InverseP = vec2(P, 0.0) * InverseRes;
// UVs for four linearly-interpolated samples spaced 0.25 texels apart
vec2 C0 = UV;
vec2 C1 = UV + InverseP * 0.25;
vec2 C2 = UV + InverseP * 0.50;
vec2 C3 = UV + InverseP * 0.75;
vec4 Cx = vec4(C0.x, C1.x, C2.x, C3.x);
vec4 Cy = vec4(C0.y, C1.y, C2.y, C3.y);
vec4 Texel0 = texture(source[0], C0);
vec4 Texel1 = texture(source[0], C1);
vec4 Texel2 = texture(source[0], C2);
vec4 Texel3 = texture(source[0], C3);
float Frequency = CCFrequency;
//Frequency = Frequency;// Uncomment for bad color sync + (sin(UV.y * 2.0 - 1.0) / CCFrequency) * 0.001;
// Calculated the expected time of the sample.
vec4 T = A2 * Cy * vec4(sourceSize[0].y) + B + Cx;
vec4 W = vec4(Pi2ScanTime * Frequency);
vec4 TW = T * W;
vec4 Y = vec4(dot(Texel0, YTransform), dot(Texel1, YTransform), dot(Texel2, YTransform), dot(Texel3, YTransform));
vec4 I = vec4(dot(Texel0, ITransform), dot(Texel1, ITransform), dot(Texel2, ITransform), dot(Texel3, ITransform));
vec4 Q = vec4(dot(Texel0, QTransform), dot(Texel1, QTransform), dot(Texel2, QTransform), dot(Texel3, QTransform));
vec4 Encoded = Y + I * cos(TW) + Q * sin(TW);
return (Encoded - MinC) * InvCRange;
}
vec4 NTSCCodec(vec2 UV, vec2 InverseRes)
{
vec4 YAccum = Zero;
vec4 IAccum = Zero;
vec4 QAccum = Zero;
float QuadXSize = sourceSize[0].x * 4.0;
float TimePerSample = ScanTime / QuadXSize;
// Frequency cutoffs for the individual portions of the signal that we extract.
// Y1 and Y2 are the positive and negative frequency limits of the notch filter on Y.
// Y3 is the center of the frequency response of the Y filter.
// I is the center of the frequency response of the I filter.
// Q is the center of the frequency response of the Q filter.
float Fc_y1 = NotchLowerFrequency * TimePerSample;
float Fc_y2 = NotchUpperFrequency * TimePerSample;
float Fc_y3 = YFrequency * TimePerSample;
float Fc_i = IFrequency * TimePerSample;
float Fc_q = QFrequency * TimePerSample;
float Pi2Fc_y1 = Fc_y1 * Pi2;
float Pi2Fc_y2 = Fc_y2 * Pi2;
float Pi2Fc_y3 = Fc_y3 * Pi2;
float Pi2Fc_i = Fc_i * Pi2;
float Pi2Fc_q = Fc_q * Pi2;
float Fc_y1_2 = Fc_y1 * 2.0;
float Fc_y2_2 = Fc_y2 * 2.0;
float Fc_y3_2 = Fc_y3 * 2.0;
float Fc_i_2 = Fc_i * 2.0;
float Fc_q_2 = Fc_q * 2.0;
vec4 CoordY = vec4(UV.y);
// 83 composite samples wide, 4 composite pixels per texel
for(float n = -31.0; n < 32.0; n += 4.0)
{
vec4 n4 = n + NotchOffset;
vec4 CoordX = UV.x + InverseRes.x * n4 * 0.25;
vec2 TexCoord = vec2(CoordX.x, CoordY.x);
vec4 C = CompositeSample(TexCoord, InverseRes) * CRange + MinC;
vec4 WT = W * (CoordX + A2 * CoordY * sourceSize[0].y + B);
vec4 Cosine = 0.54 + 0.46 * cos(Pi2Length * n4);
vec4 SincYIn1 = Pi2Fc_y1 * n4;
vec4 SincYIn2 = Pi2Fc_y2 * n4;
vec4 SincYIn3 = Pi2Fc_y3 * n4;
vec4 SincY1 = sin(SincYIn1) / SincYIn1;
vec4 SincY2 = sin(SincYIn2) / SincYIn2;
vec4 SincY3 = sin(SincYIn3) / SincYIn3;
// These zero-checks could be made more efficient if WebGL supported mix(vec4, vec4, bvec4)
// Unfortunately, the universe hates us
if(SincYIn1.x == 0.0) SincY1.x = 1.0;
if(SincYIn1.y == 0.0) SincY1.y = 1.0;
if(SincYIn1.z == 0.0) SincY1.z = 1.0;
if(SincYIn1.w == 0.0) SincY1.w = 1.0;
if(SincYIn2.x == 0.0) SincY2.x = 1.0;
if(SincYIn2.y == 0.0) SincY2.y = 1.0;
if(SincYIn2.z == 0.0) SincY2.z = 1.0;
if(SincYIn2.w == 0.0) SincY2.w = 1.0;
if(SincYIn3.x == 0.0) SincY3.x = 1.0;
if(SincYIn3.y == 0.0) SincY3.y = 1.0;
if(SincYIn3.z == 0.0) SincY3.z = 1.0;
if(SincYIn3.w == 0.0) SincY3.w = 1.0;
vec4 IdealY = (Fc_y1_2 * SincY1 - Fc_y2_2 * SincY2) + Fc_y3_2 * SincY3;
vec4 FilterY = Cosine * IdealY;
vec4 SincIIn = Pi2Fc_i * n4;
vec4 SincI = sin(SincIIn) / SincIIn;
if (SincIIn.x == 0.0) SincI.x = 1.0;
if (SincIIn.y == 0.0) SincI.y = 1.0;
if (SincIIn.z == 0.0) SincI.z = 1.0;
if (SincIIn.w == 0.0) SincI.w = 1.0;
vec4 IdealI = Fc_i_2 * SincI;
vec4 FilterI = Cosine * IdealI;
vec4 SincQIn = Pi2Fc_q * n4;
vec4 SincQ = sin(SincQIn) / SincQIn;
if (SincQIn.x == 0.0) SincQ.x = 1.0;
if (SincQIn.y == 0.0) SincQ.y = 1.0;
if (SincQIn.z == 0.0) SincQ.z = 1.0;
if (SincQIn.w == 0.0) SincQ.w = 1.0;
vec4 IdealQ = Fc_q_2 * SincQ;
vec4 FilterQ = Cosine * IdealQ;
YAccum += C * FilterY;
IAccum += C * cos(WT) * FilterI;
QAccum += C * sin(WT) * FilterQ;
}
float Y = dot(YAccum, One);
float I = dot(IAccum, One) * 2.0;
float Q = dot(QAccum, One) * 2.0;
vec3 YIQ = vec3(Y, I, Q);
vec3 OutRGB = vec3(dot(YIQ, YIQ2R), dot(YIQ, YIQ2G), dot(YIQ, YIQ2B));
return vec4(OutRGB, 1.0);
}
void main() {
FragColor = vec4(NTSCCodec(vTexCoord, sourceSize[0].zw));
}

View file

@ -1,13 +0,0 @@
#version 150
in vec4 position;
in vec2 texCoord;
out Vertex {
vec2 vTexCoord;
};
void main() {
gl_Position = position;
vTexCoord = texCoord;
}

View file

@ -1,208 +0,0 @@
#version 150
// This is a port of the NTSC encode/decode shader pair in MAME and MESS, modified to use only
// one pass rather than an encode pass and a decode pass. It accurately emulates the sort of
// signal decimation one would see when viewing a composite signal, though it could benefit from a
// pre-pass to re-size the input content to more accurately reflect the actual size that would
// be incoming from a composite signal source.
//
// To encode the composite signal, I convert the RGB value to YIQ, then subsequently evaluate
// the standard NTSC composite equation. Four composite samples per RGB pixel are generated from
// the incoming linearly-interpolated texels.
//
// The decode pass implements a Fixed Impulse Response (FIR) filter designed by MAME/MESS contributor
// "austere" in matlab (if memory serves correctly) to mimic the behavior of a standard television set
// as closely as possible. The filter window is 83 composite samples wide, and there is an additional
// notch filter pass on the luminance (Y) values in order to strip the color signal from the luminance
// signal prior to processing.
//
// Yes, this code could greatly use some cleaning up.
// ported from UltraMoogleMan's "Full MAME/MESS Shader Pipe" shadertoy: https://www.shadertoy.com/view/ldf3Rf
// license: presumably MAME's license at the time, which was noncommercial
#define scanlines 0.0
#define scandark 0.175
#define deconverge 0.0
#define pincushion 0.0
#define hertzroll 0.0
// Useful Constants
const vec4 Zero = vec4(0.0);
const vec4 Half = vec4(0.5);
const vec4 One = vec4(1.0);
const vec4 Two = vec4(2.0);
const vec3 Gray = vec3(0.3, 0.59, 0.11);
const float Pi = 3.1415926535;
const float Pi2 = 6.283185307;
// NTSC Constants
const vec4 A = vec4(0.5);
const vec4 A2 = vec4(1.0);
const vec4 B = vec4(0.5);
const float P = 1.0;
const float CCFrequency = 3.59754545;
const float NotchUpperFrequency = 5.59754545; //3.59754545 + 2.0;
const float NotchLowerFrequency = 1.59754545; //3.59754545 - 2.0;
const float YFrequency = 6.0;
const float IFrequency = 1.2;
const float QFrequency = 0.6;
const float NotchHalfWidth = 2.0;
const float ScanTime = 52.6;
const float Pi2ScanTime = 330.4955471482;// 6.283185307 * 52.6;
const float MaxC = 2.1183;
const vec4 YTransform = vec4(0.299, 0.587, 0.114, 0.0);
const vec4 ITransform = vec4(0.595716, -0.274453, -0.321263, 0.0);
const vec4 QTransform = vec4(0.211456, -0.522591, 0.311135, 0.0);
const vec3 YIQ2R = vec3(1.0, 0.956, 0.621);
const vec3 YIQ2G = vec3(1.0, -0.272, -0.647);
const vec3 YIQ2B = vec3(1.0, -1.106, 1.703);
const vec4 MinC = vec4(-1.1183);
const vec4 CRange = vec4(3.2366);
const vec4 InvCRange = vec4(1.0/3.2366);
const float Pi2Length = Pi2 / 63.0;
const vec4 NotchOffset = vec4(0.0, 1.0, 2.0, 3.0);
vec4 W = vec4(Pi2 * CCFrequency * ScanTime);
// Color Convolution Constants
const vec3 RedMatrix = vec3(1.0, 0.0, 0.0);
const vec3 GrnMatrix = vec3(0.0, 1.0, 0.0);
const vec3 BluMatrix = vec3(0.0, 0.0, 1.0);
const vec3 DCOffset = vec3(0.0, 0.0, 0.0);
const vec3 ColorScale = vec3(0.95, 0.95, 0.95);
const float Saturation = 1.4;
// Deconverge Constants
const vec3 ConvergeX = vec3(-0.4, 0.0, 0.2);
const vec3 ConvergeY = vec3( 0.0, -0.4, 0.2);
const vec3 RadialConvergeX = vec3(1.0, 1.0, 1.0);
const vec3 RadialConvergeY = vec3(1.0, 1.0, 1.0);
// Scanline/Pincushion Constants
const float PincushionAmount = 0.015;
const float CurvatureAmount = 0.015;
//const float ScanlineAmount = 0.175; <- move to parameter
const float ScanlineScale = 1.0;
const float ScanlineHeight = 1.0;
const float ScanlineBrightScale = 1.0;
const float ScanlineBrightOffset = 0.0;
const float ScanlineOffset = 0.0;
const vec3 Floor = vec3(0.05, 0.05, 0.05);
// 60Hz Bar Constants
const float SixtyHertzRate = (60.0 / 59.97 - 1.0); // Difference between NTSC and line frequency
const float SixtyHertzScale = 0.1;
uniform sampler2D source[];
uniform vec4 sourceSize[];
uniform vec4 targetSize;
uniform int phase;
in Vertex {
vec2 vTexCoord;
};
out vec4 FragColor;
vec4 ColorConvolution(vec2 UV, vec2 InverseRes)
{
vec3 InPixel = texture(source[0], UV).rgb;
// Color Matrix
float RedValue = dot(InPixel, RedMatrix);
float GrnValue = dot(InPixel, GrnMatrix);
float BluValue = dot(InPixel, BluMatrix);
vec3 OutColor = vec3(RedValue, GrnValue, BluValue);
// DC Offset & Scale
OutColor = (OutColor * ColorScale) + DCOffset;
// Saturation
float Luma = dot(OutColor, Gray);
vec3 Chroma = OutColor - Luma;
OutColor = (Chroma * Saturation) + Luma;
return vec4(OutColor, 1.0);
}
vec4 Deconverge(vec2 UV)
{
vec2 InverseRes = 1.0 / sourceSize[0].xy;
vec2 InverseSrcRes = 1.0 / sourceSize[0].xy;
vec3 CoordX = UV.x * RadialConvergeX;
vec3 CoordY = UV.y * RadialConvergeY;
CoordX += ConvergeX * InverseRes.x - (RadialConvergeX - 1.0) * 0.5;
CoordY += ConvergeY * InverseRes.y - (RadialConvergeY - 1.0) * 0.5;
float RedValue = ColorConvolution(vec2(CoordX.x, CoordY.x), InverseSrcRes).r;
float GrnValue = ColorConvolution(vec2(CoordX.y, CoordY.y), InverseSrcRes).g;
float BluValue = ColorConvolution(vec2(CoordX.z, CoordY.z), InverseSrcRes).b;
if (deconverge > 0.5) return vec4(RedValue, GrnValue, BluValue, 1.0);
else return vec4(texture(source[0], UV));
}
vec4 ScanlinePincushion(vec2 UV)
{
vec4 InTexel = Deconverge(UV);
vec2 PinUnitCoord = UV * Two.xy - One.xy;
float PincushionR2 = pow(length(PinUnitCoord), 2.0);
vec2 PincushionCurve = PinUnitCoord * PincushionAmount * PincushionR2;
vec2 BaseCoord = UV;
vec2 ScanCoord = UV;
BaseCoord *= One.xy - PincushionAmount * 0.2; // Warning: Magic constant
BaseCoord += PincushionAmount * 0.1;
BaseCoord += PincushionCurve;
ScanCoord *= One.xy - PincushionAmount * 0.2; // Warning: Magic constant
ScanCoord += PincushionAmount * 0.1;
ScanCoord += PincushionCurve;
vec2 CurveClipUnitCoord = UV * Two.xy - One.xy;
float CurvatureClipR2 = pow(length(CurveClipUnitCoord), 2.0);
vec2 CurvatureClipCurve = CurveClipUnitCoord * CurvatureAmount * CurvatureClipR2;
vec2 ScreenClipCoord = UV;
ScreenClipCoord -= Half.xy;
ScreenClipCoord *= One.xy - CurvatureAmount * 0.2; // Warning: Magic constant
ScreenClipCoord += Half.xy;
ScreenClipCoord += CurvatureClipCurve;
if (pincushion > 0.5){
// -- Alpha Clipping --
if (BaseCoord.x < 0.0) return vec4(0.0, 0.0, 0.0, 1.0);
if (BaseCoord.y < 0.0) return vec4(0.0, 0.0, 0.0, 1.0);
if (BaseCoord.x > 1.0) return vec4(0.0, 0.0, 0.0, 1.0);
if (BaseCoord.y > 1.0) return vec4(0.0, 0.0, 0.0, 1.0);
}
// -- Scanline Simulation --
float InnerSine = ScanCoord.y * sourceSize[0].y * ScanlineScale;
float ScanBrightMod = sin(InnerSine * Pi + ScanlineOffset * sourceSize[0].y);
float ScanBrightness = mix(1.0, (pow(ScanBrightMod * ScanBrightMod, ScanlineHeight) * ScanlineBrightScale + 1.0) * 0.5, scandark);
vec3 ScanlineTexel = InTexel.rgb * ScanBrightness;
// -- Color Compression (increasing the floor of the signal without affecting the ceiling) --
ScanlineTexel = Floor + (One.xyz - Floor) * ScanlineTexel;
if (scanlines > 0.5) return vec4(ScanlineTexel, 1.0);
else return vec4(InTexel);
}
vec4 SixtyHertz(vec2 UV)
{
vec4 InPixel = ScanlinePincushion(UV);
float Milliseconds = float(phase) * 15.0;
float TimeStep = fract(Milliseconds * SixtyHertzRate);
float BarPosition = 1.0 - fract(-UV.y + TimeStep) * SixtyHertzScale;
vec4 OutPixel = InPixel * BarPosition;
if (hertzroll > 0.5) return OutPixel;
else return InPixel;
}
void main() {
vec4 OutPixel = SixtyHertz(vTexCoord.xy);
FragColor = OutPixel;
}

View file

@ -1,16 +0,0 @@
#version 150
in vec4 position;
in vec2 texCoord;
out Vertex {
vec2 vTexCoord;
};
uniform vec4 targetSize;
uniform vec4 sourceSize[];
void main() {
gl_Position = position;
vTexCoord = texCoord;
}

View file

@ -1,20 +0,0 @@
input
filter: linear
program
filter: linear
height: 100%
width: 100%
vertex: mame-ntsc.vs
fragment: mame-ntsc.fs
program
filter: linear
modulo: 270.0
vertex: mame-postproc.vs
fragment: mame-postproc.fs
output
height: 0
width: 0
filter: linear

View file

@ -1,48 +0,0 @@
// Gaussian Scanlines
//
// adapted from NTSC Shader - written by Hans-Kristian Arntzen
// License: GPLv3
// pulled from git://github.com/libretro/common-shaders.git on 08/05/2013
#version 150
uniform sampler2D source[];
uniform vec4 sourceSize[];
uniform vec4 targetSize;
uniform int phase;
#define DISPLAY_GAMMA 2.1
#define CRT_GAMMA 2.5
#define one (sourceSize[0]) //this is set to 1.0 / sourceSize[0] in the original version, but I think this looks better
#define pix_no texCoord.y * sourceSize[0]
#define TEX(off) pow(texture(source[0], texCoord - vec2(0.0, (off) * one.y)).rgb, vec3(CRT_GAMMA))
in Vertex {
vec2 texCoord;
};
out vec4 fragColor;
void main() {
vec3 frame0 = TEX(-2.0);
vec3 frame1 = TEX(-1.0);
vec3 frame2 = TEX(0.0);
vec3 frame3 = TEX(1.0);
vec3 frame4 = TEX(2.0);
float offset_dist = fract(pix_no.y) - 0.5;
float dist0 = 2.0 + offset_dist;
float dist1 = 1.0 + offset_dist;
float dist2 = 0.0 + offset_dist;
float dist3 = -1.0 + offset_dist;
float dist4 = -2.0 + offset_dist;
vec3 scanline = frame0 * exp(-5.0 * dist0 * dist0);
scanline += frame1 * exp(-5.0 * dist1 * dist1);
scanline += frame2 * exp(-5.0 * dist2 * dist2);
scanline += frame3 * exp(-5.0 * dist3 * dist3);
scanline += frame4 * exp(-5.0 * dist4 * dist4);
fragColor = vec4(pow(1.15 * scanline, vec3(1.0 / DISPLAY_GAMMA)), 1.0);
}

View file

@ -1,26 +0,0 @@
input
filter: nearest
format: rgba16f
program
filter: nearest
format: rgba16f
width: 400%
height: 100%
modulo: 2
fragment: ntsc-pass1.fs
program
filter: nearest
format: rgba16f
width: 50%
height: 100%
fragment: ntsc-pass2.fs
program
filter: linear
width: 100%
height: 100%
output
filter: nearest

View file

@ -1,103 +0,0 @@
// NTSC Shader - written by Hans-Kristian Arntzen
// License: GPLv3
// pulled from git://github.com/libretro/common-shaders.git on 01/30/2014
#version 150
uniform sampler2D source[];
uniform vec4 sourceSize[];
uniform vec4 targetSize;
uniform int phase;
// uniforms added for compatibility
out vec3 col;
out float mod_phase;
out float chroma_phase;
#define THREE_PHASE
#define COMPOSITE
// #include "ntsc-param.inc" //
#define PI 3.14159265
#if defined(TWO_PHASE)
#define CHROMA_MOD_FREQ (4.0 * PI / 15.0)
#elif defined(THREE_PHASE)
#define CHROMA_MOD_FREQ (PI / 3.0)
#endif
#if defined(COMPOSITE)
#define SATURATION 1.0
#define BRIGHTNESS 1.0
#define ARTIFACTING 1.0
#define FRINGING 1.0
#elif defined(SVIDEO)
#define SATURATION 1.0
#define BRIGHTNESS 1.0
#define ARTIFACTING 0.0
#define FRINGING 0.0
#endif
#if defined(COMPOSITE) || defined(SVIDEO)
mat3 mix_mat = mat3(
BRIGHTNESS, FRINGING, FRINGING,
ARTIFACTING, 2.0 * SATURATION, 0.0,
ARTIFACTING, 0.0, 2.0 * SATURATION
);
#endif
// END "ntsc-param.inc" //
// moved from vertex
#define pix_no (texCoord.xy * sourceSize[0].xy * (targetSize.xy / sourceSize[0].xy))
in Vertex {
vec2 texCoord;
};
out vec4 fragColor;
mat3 yiq2rgb_mat = mat3(
1.0, 1.0, 1.0,
0.956, -0.2720, -1.1060,
0.6210, -0.6474, 1.7046
);
vec3 yiq2rgb(vec3 yiq)
{
return (yiq * yiq2rgb_mat);
}
mat3 yiq_mat = mat3(
0.2989, 0.5959, 0.2115,
0.5870, -0.2744, -0.5229,
0.1140, -0.3216, 0.3114
);
vec3 rgb2yiq(vec3 col)
{
return (col * yiq_mat);
}
void main() {
// #include "ntsc-pass1-encode-demodulate.inc" //
vec3 col = texture(source[0], texCoord).rgb;
vec3 yiq = rgb2yiq(col);
#if defined(TWO_PHASE)
float chroma_phase = PI * (mod(pix_no.y, 2.0) + phase);
#elif defined(THREE_PHASE)
float chroma_phase = 0.6667 * PI * (mod(pix_no.y, 3.0) + phase);
#endif
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
fragColor = vec4(yiq, 1.0);
// END "ntsc-pass1-encode-demodulate.inc" //
}

View file

@ -1,252 +0,0 @@
// NTSC Shader - written by Hans-Kristian Arntzen
// License: GPLv3
// pulled from git://github.com/libretro/common-shaders.git on 01/30/2014
#version 150
uniform sampler2D source[];
uniform vec4 sourceSize[];
uniform vec4 targetSize;
#define THREE_PHASE //options here include THREE_PHASE, TWO_PHASE or OLD_THREE_PHASE
#define GAMMA_CORRECTION //comment to disable gamma correction, usually because higan's gamma correction is enabled or you have another shader already doing it
#define CRT_GAMMA 2.5
#define DISPLAY_GAMMA 2.1
#if defined OLD_THREE_PHASE
#define TAPS 24
const float luma_filter[TAPS + 1] = float[TAPS + 1](
-0.000071070,
-0.000032816,
0.000128784,
0.000134711,
-0.000226705,
-0.000777988,
-0.000997809,
-0.000522802,
0.000344691,
0.000768930,
0.000275591,
-0.000373434,
0.000522796,
0.003813817,
0.007502825,
0.006786001,
-0.002636726,
-0.019461182,
-0.033792479,
-0.029921972,
0.005032552,
0.071226466,
0.151755921,
0.218166470,
0.243902439);
const float chroma_filter[TAPS + 1] = float[TAPS + 1](
0.001845562,
0.002381606,
0.003040177,
0.003838976,
0.004795341,
0.005925312,
0.007242534,
0.008757043,
0.010473987,
0.012392365,
0.014503872,
0.016791957,
0.019231195,
0.021787070,
0.024416251,
0.027067414,
0.029682613,
0.032199202,
0.034552198,
0.036677005,
0.038512317,
0.040003044,
0.041103048,
0.041777517,
0.042004791);
#endif
#if defined(THREE_PHASE)
// #include "ntsc-decode-filter-3phase.inc" //
#define TAPS 24
const float luma_filter[TAPS + 1] = float[TAPS + 1](
-0.000012020,
-0.000022146,
-0.000013155,
-0.000012020,
-0.000049979,
-0.000113940,
-0.000122150,
-0.000005612,
0.000170516,
0.000237199,
0.000169640,
0.000285688,
0.000984574,
0.002018683,
0.002002275,
-0.000909882,
-0.007049081,
-0.013222860,
-0.012606931,
0.002460860,
0.035868225,
0.084016453,
0.135563500,
0.175261268,
0.190176552);
const float chroma_filter[TAPS + 1] = float[TAPS + 1](
-0.000118847,
-0.000271306,
-0.000502642,
-0.000930833,
-0.001451013,
-0.002064744,
-0.002700432,
-0.003241276,
-0.003524948,
-0.003350284,
-0.002491729,
-0.000721149,
0.002164659,
0.006313635,
0.011789103,
0.018545660,
0.026414396,
0.035100710,
0.044196567,
0.053207202,
0.061590275,
0.068803602,
0.074356193,
0.077856564,
0.079052396);
// END "ntsc-decode-filter-3phase.inc" //
#elif defined(TWO_PHASE)
// #include "ntsc-decode-filter-3phase.inc" //
#define TAPS 24
const float luma_filter[TAPS + 1] = float[TAPS + 1](
-0.000012020,
-0.000022146,
-0.000013155,
-0.000012020,
-0.000049979,
-0.000113940,
-0.000122150,
-0.000005612,
0.000170516,
0.000237199,
0.000169640,
0.000285688,
0.000984574,
0.002018683,
0.002002275,
-0.000909882,
-0.007049081,
-0.013222860,
-0.012606931,
0.002460860,
0.035868225,
0.084016453,
0.135563500,
0.175261268,
0.190176552);
const float chroma_filter[TAPS + 1] = float[TAPS + 1](
-0.000118847,
-0.000271306,
-0.000502642,
-0.000930833,
-0.001451013,
-0.002064744,
-0.002700432,
-0.003241276,
-0.003524948,
-0.003350284,
-0.002491729,
-0.000721149,
0.002164659,
0.006313635,
0.011789103,
0.018545660,
0.026414396,
0.035100710,
0.044196567,
0.053207202,
0.061590275,
0.068803602,
0.074356193,
0.077856564,
0.079052396);
// END "ntsc-decode-filter-3phase.inc" //
#endif
// #include ntsc-rgbyuv.inc //
mat3 yiq2rgb_mat = mat3(
1.0, 1.0, 1.0,
0.956, -0.2720, -1.1060,
0.6210, -0.6474, 1.7046
);
vec3 yiq2rgb(vec3 yiq)
{
return (yiq * yiq2rgb_mat);
}
mat3 yiq_mat = mat3(
0.2989, 0.5959, 0.2115,
0.5870, -0.2744, -0.5229,
0.1140, -0.3216, 0.3114
);
vec3 rgb2yiq(vec3 col)
{
return (col * yiq_mat);
}
// END ntsc-rgbyuv.inc //
// fixCoord moved from vertex
#define fixCoord (texCoord - vec2(0.5 / sourceSize[0].x, 0.0)) // Compensate for decimate-by-2.
#define fetch_offset(offset, one_x) \
texture(source[0], fixCoord + vec2((offset) * (one_x), 0.0)).xyz
in Vertex {
vec2 texCoord;
};
out vec4 fragColor;
void main() {
// #include "ntsc-pass2-decode.inc" //
float one_x = 1.0 / sourceSize[0].x;
vec3 signal = vec3(0.0);
for (int i = 0; i < TAPS; i++)
{
float offset = float(i);
vec3 sums = fetch_offset(offset - float(TAPS), one_x) +
fetch_offset(float(TAPS) - offset, one_x);
signal += sums * vec3(luma_filter[i], chroma_filter[i], chroma_filter[i]);
}
signal += texture(source[0], fixCoord).xyz * vec3(luma_filter[TAPS], chroma_filter[TAPS], chroma_filter[TAPS]);
// END "ntsc-pass2-decode.inc" //
vec3 rgb = yiq2rgb(signal);
#ifdef GAMMA_CORRECTION
vec3 gamma = vec3(CRT_GAMMA / DISPLAY_GAMMA);
rgb = pow(rgb, gamma.rgb);
#endif
fragColor = vec4(rgb, 1.0);
}

View file

@ -1,11 +0,0 @@
input
filter: nearest
program
filter: nearest
height: 100%
fragment: pal-r57shell.fs
output
height: 0
filter: linear

View file

@ -1,368 +0,0 @@
#version 150
// NES PAL composite signal simulation for RetroArch
// shader by r57shell
// thanks to feos & HardWareMan & NewRisingSun
// also TV subpixels and scanlines
// LICENSE: PUBLIC DOMAIN
// NOTE: for nice TV subpixels and scanlines I recommend to
// disable this features here and apply CRT-specialized shader.
// Quality considerations
// there are three main options:
// USE_RAW (R), USE_DELAY_LINE (D), USE_COLORIMETRY (C)
// here is table of quality in decreasing order:
// RDC, RD, RC, DC, D, C
// compatibility macros
#define float2 vec2
#define float3 vec3
#define float4 vec4
#define frac(c) fract(c)
#define saturate(c) clamp(c, 0.0, 1.0)
#define fmod(x,y) mod(x,y)
#define mul(x,y) (y*x)
#define float2x2 mat2
#define float3x3 mat3
#define float4x4 mat4
#define bool2 bvec2
#define bool3 bvec3
#define bool4 bvec4
#define static
uniform sampler2D source[];
uniform vec4 sourceSize[];
uniform vec4 outputSize;
uniform int phase;
in Vertex {
vec2 texCoord;
};
out vec4 fragColor;
// TWEAKS start
// use delay line technique
// without delay line technique, color would interleave
// to avoid this, set HueRotation to zero.
#define USE_DELAY_LINE
// use this if you need to swap even/odd V sign.
// sign of V changes each scanline
// so if some scanline is positive, then next is negative
// and if you want to match picture
// to actual running PAL NES on TV
// you may want to have this option, to change signs
// if they don't match
//#define SWAP_VSIGN
// rough simulation of scanlines
// better if you use additional shader instead
// if you still use it, make sure that SizeY
// is at least twice lower than output height
#define USE_SCANLINES // FIXME: scanlines are broken and I'm too lazy to fix it right now
// to change gamma of virtual TV from 2.2 to something else
#define USE_GAMMA
// use sampled version. it's much more slower version of shader.
// because it is computing x4 more values. NOT RECOMMENDED.
//#define USE_SAMPLED
#ifndef PARAMETER_UNIFORM
// NTSC standard gamma = 2.2
// PAL standard gamma = 2.8
// according to many sources, very unlikely gamma of TV is 2.8
// most likely gamma of PAL TV is in range 2.4-2.5
const float Gamma_static = 2.8; // gamma of virtual TV
const float Brightness_static = 0.25;
const float Contrast_static = 1.1;
const float Saturation_static = 1.1;
const int
Ywidth_static = 12,
Uwidth_static = 23,
Vwidth_static = 23;
#define Brightness Brightness_static
#define Gamma Gamma_static
#define Ywidth Ywidth_static
#define Uwidth Uwidth_static
#define Vwidth Vwidth_static
#define SCANLINE_MUL (sw.x*dark_scanline+sw.y)
int Mwidth = int(max(float(Ywidth), max(float(Uwidth), float(Vwidth))));
// correct one is -2.5
// works only with USE_RAW
const float HueShift = -2.5;
// rotation of hue due to luma level.
const float HueRotation = 2.;
// touch this only if you know what you doing
const float Phase_Y = 2.; // fmod(341*10,12)
const float Phase_One = 0.; // alternating phases.
const float Phase_Two = 8.;
// screen size, scanlines = y*2; y one field, and y other field.
const int SizeX = 256;
const int SizeY = 240;
// count of pixels of virtual TV.
// value close to 1000 produce small artifacts
const int TV_Pixels = 400;
const float dark_scanline = 0.5; // half
#endif
// this is using following matrixes.
// it provides more scientific approach
// by conversion into linear XYZ space
// and back to sRGB.
// it's using Gamma setting too.
// define USE_GAMMA is not required.
#define USE_COLORIMETRY
const float3x3 RGB_to_XYZ =
mat3(
0.4306190, 0.3415419, 0.1783091,
0.2220379, 0.7066384, 0.0713236,
0.0201853, 0.1295504, 0.9390944
);
const float3x3 XYZ_to_sRGB =
mat3(
3.2406, -1.5372, -0.4986,
-0.9689, 1.8758, 0.0415,
0.0557, -0.2040, 1.0570
);
// TWEAKS end
const float YUV_u = 0.492;
const float YUV_v = 0.877;
const mat3 RGB_to_YUV =
mat3(
float3( 0.299, 0.587, 0.114), //Y
float3(-0.299,-0.587, 0.886)*YUV_u, //B-Y
float3( 0.701,-0.587,-0.114)*YUV_v //R-Y
);
#ifdef USE_DELAY_LINE
const float comb_line = 1.;
#else
const float comb_line = 2.;
#endif
static const float Voltage_0 = 0.518;
static const float Voltage_1 = 1.962;
static const float DeltaV = (Voltage_1-Voltage_0);
float RGB_y = Contrast_static/Ywidth_static/DeltaV;
float RGB_u = comb_line*Contrast_static*Saturation_static/YUV_u/Uwidth_static/DeltaV;
float RGB_v = comb_line*Contrast_static*Saturation_static/YUV_v/Vwidth_static/DeltaV;
mat3 YUV_to_RGB =
mat3(
float3(1., 1., 1.)*RGB_y,
float3(0., -0.114/0.587, 1.)*RGB_u,
float3(1., -0.299/0.587, 0.)*RGB_v
);
const float pi = 3.1415926535897932384626433832795;
float sinn(float x)
{
return sin(/*fmod(x,24)*/x*(pi*2./24.));
}
float coss(float x)
{
return cos(/*fmod(x,24)*/x*(pi*2./24.));
}
float3 monitor(sampler2D tex, float2 p)
{
float2 size = sourceSize[0].xy;//float2(SizeX,SizeY);
// align vertical coord to center of texel
float2 uv = float2(
p.x,
(floor(p.y*sourceSize[0].y)+0.5)/sourceSize[0].y);
#ifdef USE_DELAY_LINE
float2 sh = (sourceSize[0].xy/sourceSize[0].xy/size)*float2(14./10.,-1.0);
#endif
float2 pc = uv*sourceSize[0].xy/sourceSize[0].xy*size*float2(10.,1.);
float alpha = dot(floor(float2(pc.x,pc.y)),float2(2.,Phase_Y*2.));
alpha += Phase_One*2.;
// 1/size.x of screen in uv coords = sourceSize[0].x/sourceSize[0].x/size.x;
// then 1/10*size.x of screen:
float ustep = sourceSize[0].x/sourceSize[0].x/size.x/10.;
float border = sourceSize[0].x/sourceSize[0].x;
float ss = 2.0;
#ifdef SWAP_VSIGN
#define PAL_SWITCH(A) A < 1.
#else
#define PAL_SWITCH(A) A > 1.
#endif
if (PAL_SWITCH(fmod(uv.y*sourceSize[0].y/sourceSize[0].y*size.y,2.0)))
{
// cos(pi-alpha) = -cos(alpha)
// sin(pi-alpha) = sin(alpha)
// pi - alpha
alpha = -alpha+12012.0;
ss = -2.0;
}
float ysum = 0., usum = 0., vsum = 0.;
for (int i=0; i<Mwidth; ++i)
{
float4 res = texture(tex, uv);
float3 yuv = mul(RGB_to_YUV, res.xyz);
float a1 = alpha+(HueShift+2.5)*2.-yuv.x*ss*HueRotation;
float sig = yuv.x+dot(yuv.yz,sign(float2(sinn(a1),coss(a1))));
#ifdef USE_DELAY_LINE
float4 res1 = texture(tex, uv+sh);
float3 yuv1 = mul(RGB_to_YUV, res1.xyz);
float a2 = (HueShift+2.5)*2.+12012.0-alpha+yuv.x*ss*HueRotation;
float sig1 = yuv1.x+dot(yuv1.yz,sign(float2(sinn(a2),coss(a2))));
#endif
if (i < Ywidth)
ysum += sig;
#ifdef USE_DELAY_LINE
if (i < Uwidth)
usum += (sig+sig1)*sinn(alpha);
if (i < Vwidth)
vsum += (sig-sig1)*coss(alpha);
#else
if (i < Uwidth)
usum += sig*sinn(alpha);
if (i < Vwidth)
vsum += sig*coss(alpha);
#endif
alpha -= ss;
uv.x -= ustep;
}
float3 rgb = mul(float3(ysum+Brightness*Ywidth_static,usum,vsum), YUV_to_RGB);
#if defined(USE_GAMMA) && !defined(USE_COLORIMETRY)
float3 rgb1 = saturate(rgb);
rgb = pow(rgb1, Gamma/2.2);
#endif
#ifdef USE_COLORIMETRY
float3 rgb1 = saturate(rgb);
rgb = pow(rgb1, float3(Gamma, Gamma, Gamma));
#endif
#if (defined(USE_SCANLINES))
float2 q = (p*sourceSize[0].xy/sourceSize[0].xy)*float2(TV_Pixels*3.,size.y*2.);
#endif
#ifdef USE_SCANLINES
float scanlines = size.y * outputSize.z;
float top = fmod(q.y-0.5*scanlines*2.,2.);
float bottom = top+frac(scanlines)*2.;
float2 sw = saturate(min(float2(1.,2.),float2(bottom, bottom))
-max(float2(0.,1.),float2(top)))
+saturate(min(float2(3.,4.),float2(bottom, bottom))
-max(float2(2.,3.),float2(top)))
+floor(scanlines);
rgb = rgb*SCANLINE_MUL/(sw.x+sw.y);
/*
//old stupid method
float z =
#ifdef ANIMATE_SCANLINE
fmod(phase,2.0)+
#endif
0.5;
if (abs(fmod(q.y+0.5,2)-z)<0.5)
rgb *= dark_scanline;
*/
#endif
// size of pixel screen in texture coords:
//float output_pixel_size = sourceSize[0].x/(outputSize.x*sourceSize[0].x);
// correctness check
//if (fmod(p.x*output_pixel_size,2.0) < 1.0)
// rgb = float3(0.,0.,0.);
#ifdef USE_COLORIMETRY
float3 xyz1 = mul(RGB_to_XYZ,rgb);
float3 srgb = saturate(mul(XYZ_to_sRGB,xyz1));
float3 a1 = 12.92*srgb;
float3 a2 = 1.055*pow(srgb,float3(1./2.4))-0.055;
float3 ssrgb;
ssrgb.x = (srgb.x<0.0031308?a1.x:a2.x);
ssrgb.y = (srgb.y<0.0031308?a1.y:a2.y);
ssrgb.z = (srgb.z<0.0031308?a1.z:a2.z);
return ssrgb;
#else
return rgb;
#endif
}
// pos (left corner, sample size)
float4 monitor_sample(sampler2D tex, float2 p, float2 sample_)
{
// linear interpolation was...
// now other thing.
// http://imgur.com/m8Z8trV
// AT LAST IT WORKS!!!!
// going to check in retroarch...
float2 size = sourceSize[0].xy;
float2 next = float2(.25,1.)/size;
float2 f = frac(float2(4.,1.)*size*p);
sample_ *= float2(4.,1.)*size;
float2 l;
float2 r;
if (f.x+sample_.x < 1.)
{
l.x = f.x+sample_.x;
r.x = 0.;
}
else
{
l.x = 1.-f.x;
r.x = min(1.,f.x+sample_.x-1.);
}
if (f.y+sample_.y < 1.)
{
l.y = f.y+sample_.y;
r.y = 0.;
}
else
{
l.y = 1.-f.y;
r.y = min(1.,f.y+sample_.y-1.);
}
float3 top = mix(monitor(tex, p), monitor(tex, p+float2(next.x,0.)), r.x/(l.x+r.x));
float3 bottom = mix(monitor(tex, p+float2(0.,next.y)), monitor(tex, p+next), r.x/(l.x+r.x));
return float4(mix(top,bottom, r.y/(l.y+r.y)),1.0);
}
void main() {
#ifdef USE_SAMPLED
fragColor = vec4(monitor_sample(source[0], texCoord, outputSize.zw).rgb, 1.0);
#else
fragColor = float4(monitor(source[0], texCoord), 1.);
#endif
}

View file

@ -1,7 +0,0 @@
program
filter: nearest
wrap: edge
fragment: pixellate.fs
output
filter: nearest

View file

@ -1,40 +0,0 @@
#version 150
uniform sampler2D source[];
uniform vec4 sourceSize[];
uniform vec4 targetSize;
in Vertex {
vec2 texCoord;
};
out vec4 fragColor;
void main() {
vec2 texelSize = 1.0 * sourceSize[0].zw;
vec2 range = vec2(abs(dFdx(texCoord.x)), abs(dFdy(texCoord.y)));
range = range / 2.0 * 0.999;
float left = texCoord.x - range.x;
float top = texCoord.y + range.y;
float right = texCoord.x + range.x;
float bottom = texCoord.y - range.y;
vec4 topLeftColor = pow(texture(source[0], vec2(left, top)), vec4(2.2));
vec4 bottomRightColor = pow(texture(source[0], vec2(right, bottom)), vec4(2.2));
vec4 bottomLeftColor = pow(texture(source[0], vec2(left, bottom)), vec4(2.2));
vec4 topRightColor = pow(texture(source[0], vec2(right, top)), vec4(2.2));
vec2 border = clamp(round(texCoord / texelSize) * texelSize, vec2(left, bottom), vec2(right, top));
float totalArea = 4.0 * range.x * range.y;
vec4 averageColor;
averageColor = ((border.x - left) * (top - border.y) / totalArea) * topLeftColor;
averageColor += ((right - border.x) * (border.y - bottom) / totalArea) * bottomRightColor;
averageColor += ((border.x - left) * (border.y - bottom) / totalArea) * bottomLeftColor;
averageColor += ((right - border.x) * (top - border.y) / totalArea) * topRightColor;
fragColor = pow(averageColor, vec4(1.0/2.2));
}

1
shaders/README.md Normal file
View file

@ -0,0 +1 @@
See the [bsnes-shaders](https://github.com/Marat-Tanalin/bsnes-shaders) repo.

View file

@ -1,31 +0,0 @@
// Gamma Adjustment Shader
// Written by Themaister - based on byuu's bsnes gamma ramp code
#version 150
uniform sampler2D source[];
in Vertex {
vec2 texCoord;
};
out vec4 fragColor;
const float saturation = 1.0;
const float gamma = 1.0;
const float luminance = 1.2;
vec3 grayscale(vec3 col)
{
// Non-conventional way to do grayscale,
// but bSNES uses this as grayscale value.
return vec3(dot(col, vec3(0.3333)));
}
void main() {
vec3 res = texture(source[0], texCoord).xyz;
res = mix(grayscale(res), res, saturation); // Apply saturation
res = pow(res, vec3(gamma)); // Apply gamma
fragColor = vec4(clamp(res * luminance, 0.0, 1.0), 1.0);
}

View file

@ -1,12 +0,0 @@
program
filter: nearest
fragment: retro.fs
program
filter: nearest
fragment: gamma.fs
output
filter: nearest
width: 0
height: 0

View file

@ -1,38 +0,0 @@
// Retro v2 Shader
// Written by Hyllian / Jararaca
#version 150
uniform sampler2D source[];
uniform vec4 sourceSize[];
uniform vec4 targetSize;
// This value must be between 0.0 (totally black) and 1.0 (nearest neighbor)
#define PIXEL_SIZE 0.64
in Vertex {
vec2 texCoord;
};
out vec4 fragColor;
out vec3 E;
out vec2 fp;
out vec2 ps;
out vec2 f;
out vec3 res;
void main() {
// Reading the texel
vec3 E = pow(texture(source[0], texCoord).xyz, vec3(2.4));
vec2 fp = fract(texCoord.xy * sourceSize[0].xy);
vec2 ps = sourceSize[0].xy / targetSize.xy;
vec2 f = clamp(clamp(fp + 0.5*ps, 0.0, 1.0) - PIXEL_SIZE, vec2(0.0, 0.0), ps)/ps;
float max_coord = max(f.x, f.y);
vec3 res = mix(E*(1.04+fp.x*fp.y), E*0.36, max_coord);
fragColor = vec4(clamp( pow(res, vec3(1.0 / 2.2)), 0.0, 1.0 ), 1.0);
}

View file

@ -1,61 +0,0 @@
#version 150
#define dt vec3(1.0, 1.0, 1.0)
uniform sampler2D source[];
in vec3 c00;
in vec3 c10;
in vec3 c20;
in vec3 c01;
in vec3 c11;
in vec3 c21;
in vec3 c02;
in vec3 c12;
in vec3 c22;
in float d1;
in float d2;
in float hl;
in float vl;
in float k1;
in float k2;
in Vertex {
vec2 texCoord;
vec4 t1;
vec4 t2;
vec4 t3;
vec4 t4;
};
out vec4 fragColor;
void main(void) {
vec3 c00 = texture(source[0], t1.zw).xyz;
vec3 c10 = texture(source[0], t3.xy).xyz;
vec3 c20 = texture(source[0], t3.zw).xyz;
vec3 c01 = texture(source[0], t1.xy).xyz;
vec3 c11 = texture(source[0], texCoord).xyz;
vec3 c21 = texture(source[0], t2.xy).xyz;
vec3 c02 = texture(source[0], t2.zw).xyz;
vec3 c12 = texture(source[0], t4.xy).xyz;
vec3 c22 = texture(source[0], t4.zw).xyz;
float d1=dot(abs(c00 - c22), dt) + 0.0001;
float d2=dot(abs(c20 - c02), dt) + 0.0001;
float hl=dot(abs(c01 - c21), dt) + 0.0001;
float vl=dot(abs(c10 - c12), dt) + 0.0001;
float k1 = 0.5 * (hl + vl);
float k2 = 0.5 * (d1 + d2);
vec3 t1 = (hl * (c10 + c12) + vl * (c01 + c21) + k1 * c11) / (2.5 * (hl + vl));
vec3 t2 = (d1 * (c20 + c02) + d2 * (c00 + c22) + k2 * c11) / (2.5 * (d1 + d2));
k1 = dot(abs(t1 - c11), dt) + 0.0001;
k2 = dot(abs(t2 - c11), dt) + 0.0001;
fragColor = vec4((k1 * t2 + k2 * t1) / (k1 + k2), 1.0);
}

View file

@ -1,36 +0,0 @@
#version 150
in vec4 position;
in vec2 texCoord;
uniform vec4 sourceSize[];
in vec2 ps;
in float dx;
in float dy;
out Vertex {
vec2 texCoord;
vec4 t1;
vec4 t2;
vec4 t3;
vec4 t4;
} vertexOut;
void main() {
vec2 ps = vec2(1.0/sourceSize[0].x, 1.0/sourceSize[0].y);
float dx = ps.x * 0.5;
float dy = ps.y * 0.5;
gl_Position = position;
vertexOut.texCoord = texCoord;
vertexOut.t1.xy = texCoord + vec2(-dx, 0);
vertexOut.t2.xy = texCoord + vec2( dx, 0);
vertexOut.t3.xy = texCoord + vec2( 0, -dy);
vertexOut.t4.xy = texCoord + vec2( 0, dy);
vertexOut.t1.zw = texCoord + vec2(-dx, -dy);
vertexOut.t2.zw = texCoord + vec2(-dx, dy);
vertexOut.t3.zw = texCoord + vec2( dx, -dy);
vertexOut.t4.zw = texCoord + vec2( dx, dy);
}

View file

@ -1,51 +0,0 @@
input
filter: nearest
program
filter: nearest
format: rgba16f
width: 100%
height: 100%
vertex: scalefx-pass0.vs
fragment: scalefx-pass0.fs
program
filter: nearest
format: rgba16f
width: 100%
height: 100%
vertex: scalefx-pass1.vs
fragment: scalefx-pass1.fs
program
filter: nearest
width: 100%
height: 100%
vertex: scalefx-pass2.vs
fragment: scalefx-pass2.fs
program
filter: nearest
width: 100%
height: 100%
vertex: scalefx-pass3.vs
fragment: scalefx-pass3.fs
program
filter: nearest
width: 300%
height: 300%
vertex: scalefx-pass4.vs
fragment: scalefx-pass4.fs
program
filter: nearest
height: 200%
width: 200%
vertex: advanced-aa.vs
fragment: advanced-aa.fs
output
height: 0
width: 0
filter: linear

View file

@ -1,83 +0,0 @@
#version 150
/*
ScaleFX - Pass 0
by Sp00kyFox, 2017-03-01
Filter: Nearest
Scale: 1x
ScaleFX is an edge interpolation algorithm specialized in pixel art. It was
originally intended as an improvement upon Scale3x but became a new filter in
its own right.
ScaleFX interpolates edges up to level 6 and makes smooth transitions between
different slopes. The filtered picture will only consist of colours present
in the original.
Pass 0 prepares metric data for the next pass.
Copyright (c) 2016 Sp00kyFox - ScaleFX@web.de
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
uniform sampler2D source[];
uniform vec4 sourceSize[];
uniform vec4 targetSize;
in Vertex {
vec2 vTexCoord;
};
out vec4 FragColor;
// Reference: http://www.compuphase.com/cmetric.htm
float dist(vec3 A, vec3 B)
{
float r = 0.5 * (A.r + B.r);
vec3 d = A - B;
vec3 c = vec3(2 + r, 4, 3 - r);
return sqrt(dot(c*d, d)) / 3;
}
void main() {
/* grid metric
A B C x y z
E F o w
*/
#define TEX(x, y) textureOffset(source[0], vTexCoord, ivec2(x, y)).rgb
// read texels
vec3 A = TEX(-1,-1);
vec3 B = TEX( 0,-1);
vec3 C = TEX( 1,-1);
vec3 E = TEX( 0, 0);
vec3 F = TEX( 1, 0);
// output
FragColor = vec4(dist(E,A), dist(E,B), dist(E,C), dist(E,F));
}

View file

@ -1,13 +0,0 @@
#version 150
in vec4 position;
in vec2 texCoord;
out Vertex {
vec2 vTexCoord;
};
void main() {
gl_Position = position;
vTexCoord = texCoord;
}

View file

@ -1,88 +0,0 @@
#version 150
/*
ScaleFX - Pass 1
by Sp00kyFox, 2017-03-01
Filter: Nearest
Scale: 1x
ScaleFX is an edge interpolation algorithm specialized in pixel art. It was
originally intended as an improvement upon Scale3x but became a new filter in
its own right.
ScaleFX interpolates edges up to level 6 and makes smooth transitions between
different slopes. The filtered picture will only consist of colours present
in the original.
Pass 1 calculates the strength of interpolation candidates.
Copyright (c) 2016 Sp00kyFox - ScaleFX@web.de
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#define SFX_CLR 0.5
#define SFX_SAA 1.0
uniform sampler2D source[];
uniform vec4 sourceSize[];
uniform vec4 targetSize;
in Vertex {
vec2 vTexCoord;
};
out vec4 FragColor;
// corner strength
float str(float d, vec2 a, vec2 b){
float diff = a.x - a.y;
float wght1 = max(SFX_CLR - d, 0) / SFX_CLR;
float wght2 = clamp((1-d) + (min(a.x, b.x) + a.x > min(a.y, b.y) + a.y ? diff : -diff), 0, 1);
return (SFX_SAA == 1 || 2*d < a.x + a.y) ? (wght1 * wght2) * (a.x * a.y) : 0;
}
void main() {
/* grid metric pattern
A B x y z x y
D E F o w w z
G H I
*/
#define TEX(x, y) textureOffset(source[0], vTexCoord, ivec2(x, y))
// metric data
vec4 A = TEX(-1,-1), B = TEX( 0,-1);
vec4 D = TEX(-1, 0), E = TEX( 0, 0), F = TEX( 1, 0);
vec4 G = TEX(-1, 1), H = TEX( 0, 1), I = TEX( 1, 1);
// corner strength
vec4 res;
res.x = str(D.z, vec2(D.w, E.y), vec2(A.w, D.y));
res.y = str(F.x, vec2(E.w, E.y), vec2(B.w, F.y));
res.z = str(H.z, vec2(E.w, H.y), vec2(H.w, I.y));
res.w = str(H.x, vec2(D.w, H.y), vec2(G.w, G.y));
FragColor = res;
}

View file

@ -1,16 +0,0 @@
#version 150
in vec4 position;
in vec2 texCoord;
out Vertex {
vec2 vTexCoord;
};
uniform vec4 targetSize;
uniform vec4 sourceSize[];
void main() {
gl_Position = position;
vTexCoord = texCoord;
}

Some files were not shown because too many files have changed in this diff Show more