Here’s a port of it, but it doesn’t work right for some unknown reason. The scanlines don’t show up until you put the ‘spot height’ to ~0.2
/*
Reverse Antialiasing Shader
Adapted from the C source (see Copyright below) to shader
cg language by Hyllian/Jararaca - [email protected]
This shader works best in 2x scale.
*/
/*
*
* Copyright (c) 2012, Christoph Feck <[email protected]>
* All Rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
// Parameter lines go here:
#pragma parameter InputGamma "Input Gamma" 2.4 0.1 4.0 0.05
#pragma parameter OutputGamma "Output Gamma" 2.2 0.1 4.0 0.05
#define GAMMA_IN(color) pow(color, vec3(InputGamma, InputGamma, InputGamma))
#define GAMMA_OUT(color) pow(color, vec3(1.0 / OutputGamma, 1.0 / OutputGamma, 1.0 / OutputGamma))
// 0.5 = the spot stays inside the original pixel
// 1.0 = the spot bleeds up to the center of next pixel
#pragma parameter SPOT_HEIGHT "Spot Height" 0.6 0.1 1.0 0.05
// Used to counteract the desaturation effect of weighting
#pragma parameter COLOR_BOOST "Color Boost" 1.4 1.0 0.1 3.0 0.05
// Macro for weights computing
#define WEIGHT(w) \
if(w>1.0) w=1.0; \
w = 1.0 - w * w; \
w = w * w;\
#if defined(VERTEX)
#if __VERSION__ >= 130
#define COMPAT_VARYING out
#define COMPAT_ATTRIBUTE in
#define COMPAT_TEXTURE texture
#else
#define COMPAT_VARYING varying
#define COMPAT_ATTRIBUTE attribute
#define COMPAT_TEXTURE texture2D
#endif
#ifdef GL_ES
#define COMPAT_PRECISION mediump
#else
#define COMPAT_PRECISION
#endif
COMPAT_ATTRIBUTE vec4 VertexCoord;
COMPAT_ATTRIBUTE vec4 TexCoord;
COMPAT_VARYING vec4 TEX0;
COMPAT_VARYING vec4 t1;
COMPAT_VARYING vec4 t2;
COMPAT_VARYING vec4 t3;
COMPAT_VARYING vec4 t4;
COMPAT_VARYING vec4 t5;
COMPAT_VARYING vec4 t6;
COMPAT_VARYING vec4 t7;
vec4 _oPosition1;
uniform mat4 MVPMatrix;
uniform COMPAT_PRECISION int FrameDirection;
uniform COMPAT_PRECISION int FrameCount;
uniform COMPAT_PRECISION vec2 OutputSize;
uniform COMPAT_PRECISION vec2 TextureSize;
uniform COMPAT_PRECISION vec2 InputSize;
// compatibility #defines
#define vTexCoord TEX0.xy
#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
#define OutSize vec4(OutputSize, 1.0 / OutputSize)
void main()
{
gl_Position = MVPMatrix * VertexCoord;
TEX0.xy = TexCoord.xy * 1.00001;
vec2 ps = SourceSize.zw;
float dx = ps.x;
float dy = ps.y;
// A1 B1 C1
// A0 A B C C4
// D0 D E F F4
// G0 G H I I4
// G5 H5 I5
t1 = TEX0.xxxy + vec4( -dx, 0, dx,-2.0*dy); // A1 B1 C1
t2 = TEX0.xxxy + vec4( -dx, 0, dx, -dy); // A B C
t3 = TEX0.xxxy + vec4( -dx, 0, dx, 0); // D E F
t4 = TEX0.xxxy + vec4( -dx, 0, dx, dy); // G H I
t5 = TEX0.xxxy + vec4( -dx, 0, dx, 2.0*dy); // G5 H5 I5
t6 = TEX0.xyyy + vec4(-2.0*dx,-dy, 0, dy); // A0 D0 G0
t7 = TEX0.xyyy + vec4( 2.0*dx,-dy, 0, dy); // C4 F4 I4
}
#elif defined(FRAGMENT)
#ifdef GL_ES
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
#define COMPAT_PRECISION mediump
#else
#define COMPAT_PRECISION
#endif
#if __VERSION__ >= 130
#define COMPAT_VARYING in
#define COMPAT_TEXTURE texture
out COMPAT_PRECISION vec4 FragColor;
#else
#define COMPAT_VARYING varying
#define FragColor gl_FragColor
#define COMPAT_TEXTURE texture2D
#endif
uniform COMPAT_PRECISION int FrameDirection;
uniform COMPAT_PRECISION int FrameCount;
uniform COMPAT_PRECISION vec2 OutputSize;
uniform COMPAT_PRECISION vec2 TextureSize;
uniform COMPAT_PRECISION vec2 InputSize;
uniform sampler2D Texture;
COMPAT_VARYING vec4 TEX0;
COMPAT_VARYING vec4 t1;
COMPAT_VARYING vec4 t2;
COMPAT_VARYING vec4 t3;
COMPAT_VARYING vec4 t4;
COMPAT_VARYING vec4 t5;
COMPAT_VARYING vec4 t6;
COMPAT_VARYING vec4 t7;
// compatibility #defines
#define Source Texture
#define vTexCoord TEX0.xy
#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
#define OutSize vec4(OutputSize, 1.0 / OutputSize)
#ifdef PARAMETER_UNIFORM
uniform COMPAT_PRECISION float InputGamma, OutputGamma, SPOT_HEIGHT, COLOR_BOOST;
#else
#define InputGamma 2.4
#define OutputGamma 2.2
#define SPOT_HEIGHT 0.6
#define COLOR_BOOST 1.4
#endif
void main()
{
vec2 fp = fract(vTexCoord*SourceSize.xy);
vec3 B1 = COMPAT_TEXTURE(Source, t1.yw).rgb;
vec3 B = COMPAT_TEXTURE(Source, t2.yw).rgb;
vec3 D = COMPAT_TEXTURE(Source, t3.xw).rgb;
vec3 E = COMPAT_TEXTURE(Source, t3.yw).rgb;
vec3 F = COMPAT_TEXTURE(Source, t3.zw).rgb;
vec3 H = COMPAT_TEXTURE(Source, t4.yw).rgb;
vec3 H5 = COMPAT_TEXTURE(Source, t5.yw).rgb;
vec3 D0 = COMPAT_TEXTURE(Source, t6.xz).rgb;
vec3 F4 = COMPAT_TEXTURE(Source, t7.xz).rgb;
vec3 n1, n2, n3, n4, s, aa, bb, cc, dd, t, m;
/*
n1 = B1; n2 = B; s = E; n3 = H; n4 = H5;
aa = n2-n1; bb = s-n2; cc = n3-s; dd = n4-n3;
vec3 t = (7. * (bb + cc) - 3. * (aa + dd)) / 16.;
vec3 m;
m.x = (s.x < 0.5) ? 2.*s.x : 2.*(1.0-s.x);
m.y = (s.y < 0.5) ? 2.*s.y : 2.*(1.0-s.y);
m.z = (s.z < 0.5) ? 2.*s.z : 2.*(1.0-s.z);
m = min(m, 2.*abs(bb));
m = min(m, 2.*abs(cc));
t = clamp(t, -m, m);
vec3 s1 = (2.*fp.y-1.)*t + s;
*/
n1 = D0; n2 = D; s = E; n3 = F; n4 = F4;
aa = n2-n1; bb = s-n2; cc = n3-s; dd = n4-n3;
t = (7. * (bb + cc) - 3. * (aa + dd)) / 16.;
m.x = (s.x < 0.5) ? 2.*s.x : 2.*(1.0-s.x);
m.y = (s.y < 0.5) ? 2.*s.y : 2.*(1.0-s.y);
m.z = (s.z < 0.5) ? 2.*s.z : 2.*(1.0-s.z);
m = min(m, 2.*abs(bb)+0.01);
m = min(m, 2.*abs(cc)+0.01);
t = clamp(t, -m, m);
vec3 res = (2.*fp.x-1.)*t + s;
// CRT-caligari - only vertical blend
vec3 color = GAMMA_IN(res);
float ddy = fp.y - 0.5;
float v_weight_00 = ddy / SPOT_HEIGHT;
WEIGHT(v_weight_00);
color *= vec3( v_weight_00, v_weight_00, v_weight_00 );
// get closest vertical neighbour to blend
vec3 coords10;
if (ddy>0.0) {
coords10 = H;
ddy = 1.0 - ddy;
} else {
coords10 = B;
ddy = 1.0 + ddy;
}
vec3 colorNB = GAMMA_IN(coords10);
float v_weight_10 = ddy / SPOT_HEIGHT;
WEIGHT( v_weight_10 );
color += colorNB * vec3( v_weight_10, v_weight_10, v_weight_10 );
color *= vec3( COLOR_BOOST, COLOR_BOOST, COLOR_BOOST );
FragColor = vec4(clamp( GAMMA_OUT(color), 0.0, 1.0 ), 1.0);
}
#endif