Ok, here’s what I have so far in Cg. I’ll try to convert them to GLSL this evening.
It seems the scanline one is actually correct, it just looks bad on things like Super Mario World…
/* COMPATIBILITY
- HLSL compilers
- Cg compilers
*/
/*
Scanline shader
ported from PPSSPP
*/
struct sine_coord
{
float2 omega;
};
struct input
{
float2 video_size;
float2 texture_size;
float2 output_size;
float frame_count;
float frame_direction;
float frame_rotation;
sampler2D texture;
};
void main_vertex
(
float4 position : POSITION,
out float4 oPosition : POSITION,
uniform float4x4 modelViewProj,
float4 color : COLOR,
out float4 oColor : COLOR,
float2 tex : TEXCOORD,
out float2 oTex : TEXCOORD,
uniform input IN,
out sine_coord coords : TEXCOORD2
)
{
oPosition = mul(modelViewProj, position);
oColor = color;
oTex = tex;
}
const float amount = 1.0; // suitable range = 0.0 - 1.0
const float intensity = 0.5; // suitable range = 0.0 - 1.0
float4 main_fragment (in float2 tex : TEXCOORD, uniform input IN) : COLOR
{
float pos0 = ((tex.y + 1.0) * IN.texture_size.y * amount);
float pos1 = cos((frac(pos0) - 0.5) * 3.1415926 * intensity) * 1.5;
float4 rgb = tex2D(IN.texture, tex);
// slight contrast curve
float4 color = rgb * 0.5 + 0.5 * rgb * rgb * 1.2;
// color tint
color *= float4(0.9, 1.0, 0.7, 0.0);
// vignette
color *= 1.1 - 0.6 * (dot(tex - 0.5, tex - 0.5) * 2.0);
return float4(lerp(float4(0.0), color, pos1));
}
And here’s the CRT one:
/* COMPATIBILITY
- HLSL compilers
- Cg compilers
*/
/*
CRT shader
ported from PPSSPP
*/
struct sine_coord
{
float2 omega;
};
struct input
{
float2 video_size;
float2 texture_size;
float2 output_size;
float frame_count;
float frame_direction;
float frame_rotation;
sampler2D texture;
};
void main_vertex
(
float4 position : POSITION,
out float4 oPosition : POSITION,
uniform float4x4 modelViewProj,
float4 color : COLOR,
out float4 oColor : COLOR,
float2 tex : TEXCOORD,
out float2 oTex : TEXCOORD,
uniform input IN
)
{
oPosition = mul(modelViewProj, position);
oColor = color;
oTex = tex;
}
float4 main_fragment (in float2 tex : TEXCOORD, uniform input IN) : COLOR
{
int vPos = int((tex.y + IN.frame_count * 1.0) * IN.texture_size.y); // IN.texture_size.y is a hardcoded 272.0 in ppsspp, but I assumed that was meant to be the native vertical resolution.
float line_intensity = fmod(float(vPos), 1.0);
//color shift
float off = line_intensity * 0.0005;
float2 shift = float2(off, 0.0);
//shift R and G channels to simulate color bleed
float2 colorShift = float2(0.001, 0.0);
float r = tex2D(IN.texture, tex + colorShift + shift).r;
float g = tex2D(IN.texture, tex - colorShift + shift).g;
float b = tex2D(IN.texture, tex).b;
float4 c = float4(r, g * 0.99, b, 1.0) * clamp(line_intensity, 0.85, 1.0);
float rollbar = sin((tex.y + IN.frame_count) * 4.0);
return float4(c + (rollbar * 0.02));
}
Let me know if the flickering stuff doesn’t look right in the CRT one and I can keep playing with the values. I couldn’t find any videos of how it’s supposed to look.
EDIT: hmm. they don’t seem to want to convert programatically… I may try to convert them by hand.