mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-12-01 01:55:41 +00:00
2a90a88055
- Add crt-consumer.glsl; - Add crt-cyclon.fx and its bezel.png texture; - Fix crt-newpixie.fx Frame adjust to game's aspect ratio; - Update others shaders to the new functions to get uniform values.
181 lines
4.4 KiB
GLSL
181 lines
4.4 KiB
GLSL
// zfast_crt - A very simple CRT shader.
|
|
|
|
// Copyright (C) 2017 Greg Hogan (SoltanGris42)
|
|
// edited by metallic 77.
|
|
// ported to slang by gregoricavichioli & hunterk.
|
|
// ported to dolphinfx by Hyllian.
|
|
|
|
// 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.
|
|
|
|
|
|
/*
|
|
[configuration]
|
|
|
|
[OptionRangeFloat]
|
|
GUIName = Curvature
|
|
OptionName = Curvature
|
|
MinValue = 0.0
|
|
MaxValue = 1.0
|
|
StepAmount = 1.0
|
|
DefaultValue = 1.0
|
|
|
|
[OptionRangeFloat]
|
|
GUIName = Convergence X-Axis
|
|
OptionName = blurx
|
|
MinValue = -1.0
|
|
MaxValue = 2.0
|
|
StepAmount = 0.05
|
|
DefaultValue = 0.85
|
|
|
|
[OptionRangeFloat]
|
|
GUIName = Convergence Y-Axis
|
|
OptionName = blury
|
|
MinValue = -1.0
|
|
MaxValue = 1.0
|
|
StepAmount = 0.05
|
|
DefaultValue = -0.10
|
|
|
|
[OptionRangeFloat]
|
|
GUIName = Scanline Amount (Low)
|
|
OptionName = HIGHSCANAMOUNT1
|
|
MinValue = 0.0
|
|
MaxValue = 1.0
|
|
StepAmount = 0.05
|
|
DefaultValue = 0.4
|
|
|
|
[OptionRangeFloat]
|
|
GUIName = Scanline Amount (High)
|
|
OptionName = HIGHSCANAMOUNT2
|
|
MinValue = 0.0
|
|
MaxValue = 1.0
|
|
StepAmount = 0.05
|
|
DefaultValue = 0.3
|
|
|
|
[OptionRangeFloat]
|
|
GUIName = Mask Type
|
|
OptionName = TYPE
|
|
MinValue = 0.0
|
|
MaxValue = 1.0
|
|
StepAmount = 1.0
|
|
DefaultValue = 0.0
|
|
|
|
[OptionRangeFloat]
|
|
GUIName = Mask Effect Amount
|
|
OptionName = MASK_DARK
|
|
MinValue = 0.0
|
|
MaxValue = 1.0
|
|
StepAmount = 0.05
|
|
DefaultValue = 0.3
|
|
|
|
[OptionRangeFloat]
|
|
GUIName = Mask/Scanline Fade
|
|
OptionName = MASK_FADE
|
|
MinValue = 0.0
|
|
MaxValue = 1.0
|
|
StepAmount = 0.05
|
|
DefaultValue = 0.7
|
|
|
|
[OptionRangeFloat]
|
|
GUIName = Saturation
|
|
OptionName = sat
|
|
MinValue = 0.0
|
|
MaxValue = 3.0
|
|
StepAmount = 0.05
|
|
DefaultValue = 1.0
|
|
|
|
[OptionRangeFloat]
|
|
GUIName = Flicker
|
|
OptionName = FLICK
|
|
MinValue = 0.0
|
|
MaxValue = 50.0
|
|
StepAmount = 1.0
|
|
DefaultValue = 10.0
|
|
|
|
[/configuration]
|
|
*/
|
|
|
|
#define pi 3.14159
|
|
|
|
#define blur_y GetOption(blury)/(SourceSize.y*2.0)
|
|
#define blur_x GetOption(blurx)/(SourceSize.x*2.0)
|
|
#define iTimer (float(GetTime())*2.0)
|
|
#define flicker GetOption(FLICK)/1000.0
|
|
|
|
// 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)*0.03, 1.0 + (pos.x*pos.x)*0.05);
|
|
|
|
return pos*0.5 + 0.5;
|
|
}
|
|
|
|
|
|
void main()
|
|
{
|
|
vec2 vTexCoord = GetCoordinates();
|
|
vec2 texSize = 1.0 / GetInvNativePixelSize();
|
|
vec4 SourceSize = vec4(texSize, 1.0 / texSize);
|
|
|
|
float maskFade = 0.3333*GetOption(MASK_FADE);
|
|
float omega = 2.0*pi*SourceSize.y;
|
|
|
|
vec2 pos,corn;
|
|
if (GetOption(Curvature) == 1.0)
|
|
{
|
|
pos = Warp(vTexCoord.xy);
|
|
corn = min(pos,vec2(1.0)-pos); // This is used to mask the rounded
|
|
corn.x = 0.00001/corn.x; // corners later on
|
|
|
|
}
|
|
|
|
else pos = vTexCoord;
|
|
float OGL2Pos = pos.y*SourceSize.y;
|
|
float cent = floor(OGL2Pos)+0.5;
|
|
float ycoord = cent*SourceSize.w;
|
|
ycoord = mix(pos.y,ycoord,0.6);
|
|
pos = vec2(pos.x,ycoord);
|
|
|
|
|
|
vec3 sample1 = sin(iTimer)*flicker + SampleLocation(vec2(pos.x + blur_x, pos.y - blur_y)).rgb;
|
|
vec3 sample2 = 0.5*SampleLocation(pos).rgb;
|
|
vec3 sample3 = sin(iTimer)*flicker + SampleLocation(vec2(pos.x - blur_x, pos.y + blur_y)).rgb;
|
|
|
|
vec3 colour = vec3 (sample1.r*0.5 + sample2.r,
|
|
sample1.g*0.25 + sample2.g + sample3.g*0.25,
|
|
sample2.b + sample3.b*0.5);
|
|
|
|
vec3 interl = colour;
|
|
vec3 lumweight=vec3(0.22,0.71,0.07);
|
|
float lumsat = dot(colour,lumweight);
|
|
|
|
vec3 graycolour = vec3(lumsat);
|
|
colour = vec3(mix(graycolour,colour.rgb,sat));
|
|
|
|
float SCANAMOUNT = mix(GetOption(HIGHSCANAMOUNT1),GetOption(HIGHSCANAMOUNT2),max(max(colour.r,colour.g),colour.b));
|
|
|
|
|
|
if (SourceSize.y > 400.0) {
|
|
colour ;
|
|
}
|
|
else {
|
|
colour *= SCANAMOUNT * sin(fract(OGL2Pos)*3.14159)+1.0-SCANAMOUNT;
|
|
colour *= SCANAMOUNT * sin(fract(1.0-OGL2Pos)*3.14159)+1.0-SCANAMOUNT;
|
|
colour *= SCANAMOUNT * sin(fract(1.0+OGL2Pos)*3.14159)+1.0-SCANAMOUNT;
|
|
}
|
|
|
|
float steps; if (GetOption(TYPE) == 0.0) steps = 0.5; else steps = 0.3333;
|
|
float whichmask = fract(vTexCoord.x*GetWindowSize().x*steps);
|
|
float mask = 1.0 + float(whichmask < steps) * (-GetOption(MASK_DARK));
|
|
|
|
colour.rgb = mix(mask*colour, colour, dot(colour.rgb,vec3(maskFade)));
|
|
|
|
if (GetOption(Curvature) == 1.0 && corn.y < corn.x || GetOption(Curvature) == 1.0 && corn.x < 0.00001 )
|
|
colour = vec3(0.0);
|
|
|
|
SetOutput(vec4(colour.rgb, 1.0));
|
|
}
|