Added parameters to all modified files.

Fixed a bug (introduced when porting to slang) related
to crt-hyllian and the PHOSPHOR feature.
This commit is contained in:
Arzed Five 2016-08-03 06:24:41 +01:00
parent 69ab6da976
commit 6a31c2dec5
9 changed files with 437 additions and 321 deletions

View File

@ -1,8 +1,4 @@
#version 450
/* COMPATIBILITY
- HLSL compilers
- Cg compilers
*/
/*
cgwg's CRT shader
@ -25,6 +21,13 @@
)
*/
layout(push_constant) uniform Push
{
float CRTCGWG_GAMMA;
} param;
#pragma parameter CRTCGWG_GAMMA "CRTcgwg Gamma" 2.7 0.0 10.0 0.01
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
@ -55,11 +58,11 @@ layout(location = 10) out vec2 ratio_scale;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
vTexCoord = TexCoord;
vec2 delta = 1.0 / global.SourceSize.xy;
float dx = delta.x;
float dy = delta.y;
vec2 delta = global.SourceSize.zw;
float dx = delta.x;
float dy = delta.y;
c01 = vTexCoord + vec2(-dx, 0.0);
c11 = vTexCoord + vec2(0.0, 0.0);
@ -88,9 +91,6 @@ layout(location = 10) in vec2 ratio_scale;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
/* Config */
#define CRTCGWG_GAMMA 2.7
#define TEX2D(c) texture(Source ,(c))
#define PI 3.141592653589
@ -115,8 +115,8 @@ void main()
vec3 wid = 2.0 * pow(col, vec3(4.0, 4.0, 4.0)) + 2.0;
vec3 wid2 = 2.0 * pow(col2, vec3(4.0, 4.0, 4.0)) + 2.0;
col = pow(col, vec3(CRTCGWG_GAMMA, CRTCGWG_GAMMA, CRTCGWG_GAMMA));
col2 = pow(col2, vec3(CRTCGWG_GAMMA, CRTCGWG_GAMMA, CRTCGWG_GAMMA));
col = pow(col, vec3(param.CRTCGWG_GAMMA));
col2 = pow(col2, vec3(param.CRTCGWG_GAMMA));
vec3 sqrt1 = inversesqrt(0.5 * wid);
vec3 sqrt2 = inversesqrt(0.5 * wid2);

View File

@ -1,11 +1,50 @@
#version 450
layout(push_constant) uniform Push
{
float BRIGHT_BOOST;
float DILATION;
float GAMMA_INPUT;
float GAMMA_OUTPUT;
float MASK_SIZE;
float MASK_STAGGER;
float MASK_STRENGTH;
float MASK_DOT_HEIGHT;
float MASK_DOT_WIDTH;
float SCANLINE_CUTOFF;
float SCANLINE_BEAM_WIDTH_MAX;
float SCANLINE_BEAM_WIDTH_MIN;
float SCANLINE_BRIGHT_MAX;
float SCANLINE_BRIGHT_MIN;
float SCANLINE_STRENGTH;
float SHARPNESS_H;
float SHARPNESS_V;
} param;
#pragma parameter SHARPNESS_H "Sharpness Horizontal" 0.5 0.0 1.0 0.05
#pragma parameter SHARPNESS_V "Sharpness Vertical" 1.0 0.0 1.0 0.05
#pragma parameter MASK_STRENGTH "Mask Strength" 0.3 0.0 1.0 0.01
#pragma parameter MASK_DOT_WIDTH "Mask Dot Width" 1.0 1.0 100.0 1.0
#pragma parameter MASK_DOT_HEIGHT "Mask Dot Height" 1.0 1.0 100.0 1.0
#pragma parameter MASK_STAGGER "Mask Stagger" 0.0 0.0 100.0 1.0
#pragma parameter MASK_SIZE "Mask Size" 1.0 1.0 100.0 1.0
#pragma parameter SCANLINE_STRENGTH "Scanline Strength" 1.0 0.0 1.0 0.05
#pragma parameter SCANLINE_BEAM_WIDTH_MIN "Scanline Beam Width Min." 1.5 0.5 5.0 0.5
#pragma parameter SCANLINE_BEAM_WIDTH_MAX "Scanline Beam Width Max." 1.5 0.5 5.0 0.5
#pragma parameter SCANLINE_BRIGHT_MIN "Scanline Brightness Min." 0.35 0.0 1.0 0.05
#pragma parameter SCANLINE_BRIGHT_MAX "Scanline Brightness Max." 0.65 0.0 1.0 0.05
#pragma parameter SCANLINE_CUTOFF "Scanline Cutoff" 400.0 1.0 1000.0 1.0
#pragma parameter GAMMA_INPUT "Gamma Input" 2.0 0.1 5.0 0.1
#pragma parameter GAMMA_OUTPUT "Gamma Output" 1.8 0.1 5.0 0.1
#pragma parameter BRIGHT_BOOST "Brightness Boost" 1.2 1.0 2.0 0.01
#pragma parameter DILATION "Dilation" 1.0 0.0 1.0 1.0
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
vec4 OutputSize;
vec4 OriginalSize;
vec4 SourceSize;
mat4 MVP;
vec4 OutputSize;
vec4 OriginalSize;
vec4 SourceSize;
} global;
#pragma stage vertex
@ -15,8 +54,8 @@ layout(location = 0) out vec2 vTexCoord;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
}
/*
@ -53,24 +92,6 @@ layout(location = 0) in vec2 vTexCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
#define SHARPNESS_H 0.5
#define SHARPNESS_V 1.0
#define MASK_STRENGTH 0.3
#define MASK_DOT_WIDTH 1.0
#define MASK_DOT_HEIGHT 1.0
#define MASK_STAGGER 0.0
#define MASK_SIZE 1.0
#define SCANLINE_STRENGTH 1.0
#define SCANLINE_BEAM_WIDTH_MIN 1.5
#define SCANLINE_BEAM_WIDTH_MAX 1.5
#define SCANLINE_BRIGHT_MIN 0.35
#define SCANLINE_BRIGHT_MAX 0.65
#define SCANLINE_CUTOFF 400.0
#define GAMMA_INPUT 2.0
#define GAMMA_OUTPUT 1.8
#define BRIGHT_BOOST 1.2
#define DILATION 1.0
#define FIX(c) max(abs(c), 1e-5)
#define PI 3.141592653589
@ -81,7 +102,7 @@ layout(set = 0, binding = 2) uniform sampler2D Source;
vec4 dilate(vec4 col)
{
vec4 x = mix(vec4(1.0), col, DILATION);
vec4 x = mix(vec4(1.0), col, param.DILATION);
return col * x;
}
@ -129,7 +150,7 @@ void main()
vec3 col, col2;
#if ENABLE_LANCZOS
curve_x = curve_distance(dist.x, SHARPNESS_H * SHARPNESS_H);
curve_x = curve_distance(dist.x, param.SHARPNESS_H * param.SHARPNESS_H);
vec4 coeffs = PI * vec4(1.0 + curve_x, curve_x, 1.0 - curve_x, 2.0 - curve_x);
@ -140,38 +161,38 @@ void main()
col = filter_lanczos(coeffs, get_color_matrix(tex_co, dx));
col2 = filter_lanczos(coeffs, get_color_matrix(tex_co + dy, dx));
#else
curve_x = curve_distance(dist.x, SHARPNESS_H);
curve_x = curve_distance(dist.x, param.SHARPNESS_H);
col = mix(TEX2D(tex_co).rgb, TEX2D(tex_co + dx).rgb, curve_x);
col2 = mix(TEX2D(tex_co + dy).rgb, TEX2D(tex_co + dx + dy).rgb, curve_x);
#endif
col = mix(col, col2, curve_distance(dist.y, SHARPNESS_V));
col = pow(col, vec3(GAMMA_INPUT / (DILATION + 1.0)));
col = mix(col, col2, curve_distance(dist.y, param.SHARPNESS_V));
col = pow(col, vec3(param.GAMMA_INPUT / (param.DILATION + 1.0)));
float luma = dot(vec3(0.2126, 0.7152, 0.0722), col);
float bright = (max(col.r, max(col.g, col.b)) + luma) * 0.5;
float scan_bright = clamp(bright, SCANLINE_BRIGHT_MIN, SCANLINE_BRIGHT_MAX);
float scan_beam = clamp(bright * SCANLINE_BEAM_WIDTH_MAX, SCANLINE_BEAM_WIDTH_MIN, SCANLINE_BEAM_WIDTH_MAX);
float scan_weight = 1.0 - pow(cos(vTexCoord.y * 2.0 * PI * global.SourceSize.y) * 0.5 + 0.5, scan_beam) * SCANLINE_STRENGTH;
float scan_bright = clamp(bright, param.SCANLINE_BRIGHT_MIN, param.SCANLINE_BRIGHT_MAX);
float scan_beam = clamp(bright * param.SCANLINE_BEAM_WIDTH_MAX, param.SCANLINE_BEAM_WIDTH_MIN, param.SCANLINE_BEAM_WIDTH_MAX);
float scan_weight = 1.0 - pow(cos(vTexCoord.y * 2.0 * PI * global.SourceSize.y) * 0.5 + 0.5, scan_beam) * param.SCANLINE_STRENGTH;
float mask = 1.0 - MASK_STRENGTH;
vec2 mod_fac = floor(vTexCoord * global.OutputSize.xy * global.SourceSize.xy / (global.SourceSize.xy * vec2(MASK_SIZE, MASK_DOT_HEIGHT * MASK_SIZE)));
int dot_no = int(mod((mod_fac.x + mod(mod_fac.y, 2.0) * MASK_STAGGER) / MASK_DOT_WIDTH, 3.0));
float mask = 1.0 - param.MASK_STRENGTH;
vec2 mod_fac = floor(vTexCoord * global.OutputSize.xy * global.SourceSize.xy / (global.SourceSize.xy * vec2(param.MASK_SIZE, param.MASK_DOT_HEIGHT * param.MASK_SIZE)));
int dot_no = int(mod((mod_fac.x + mod(mod_fac.y, 2.0) * param.MASK_STAGGER) / param.MASK_DOT_WIDTH, 3.0));
vec3 mask_weight;
if (dot_no == 0) mask_weight = vec3(1.0, mask, mask);
else if (dot_no == 1) mask_weight = vec3(mask, 1.0, mask);
else mask_weight = vec3(mask, mask, 1.0);
if (global.SourceSize.y >= SCANLINE_CUTOFF)
if (global.SourceSize.y >= param.SCANLINE_CUTOFF)
scan_weight = 1.0;
col2 = col.rgb;
col *= vec3(scan_weight);
col = mix(col, col2, scan_bright);
col *= mask_weight;
col = pow(col, vec3(1.0 / GAMMA_OUTPUT));
col = pow(col, vec3(1.0 / param.GAMMA_OUTPUT));
FragColor = vec4(col * BRIGHT_BOOST, 1.0);
FragColor = vec4(col * param.BRIGHT_BOOST, 1.0);
}

View File

@ -1,5 +1,36 @@
#version 450
layout(push_constant) uniform Push
{
float PHOSPHOR;
float VSCANLINES;
float InputGamma;
float OutputGamma;
float SHARPNESS;
float COLOR_BOOST;
float RED_BOOST;
float GREEN_BOOST;
float BLUE_BOOST;
float SCANLINES_STRENGTH;
float BEAM_MIN_WIDTH;
float BEAM_MAX_WIDTH;
float CRT_ANTI_RINGING;
} param;
#pragma parameter PHOSPHOR "CRT - Phosphor ON/OFF" 1.0 0.0 1.0 1.0
#pragma parameter VSCANLINES "CRT - Scanlines Direction" 0.0 0.0 1.0 1.0
#pragma parameter InputGamma "CRT - Input gamma" 2.5 0.0 5.0 0.1
#pragma parameter OutputGamma "CRT - Output Gamma" 2.2 0.0 5.0 0.1
#pragma parameter SHARPNESS "CRT - Sharpness Hack" 1.0 1.0 5.0 1.0
#pragma parameter COLOR_BOOST "CRT - Color Boost" 1.5 1.0 2.0 0.05
#pragma parameter RED_BOOST "CRT - Red Boost" 1.0 1.0 2.0 0.01
#pragma parameter GREEN_BOOST "CRT - Green Boost" 1.0 1.0 2.0 0.01
#pragma parameter BLUE_BOOST "CRT - Blue Boost" 1.0 1.0 2.0 0.01
#pragma parameter SCANLINES_STRENGTH "CRT - Scanline Strength" 0.50 0.0 1.0 0.02
#pragma parameter BEAM_MIN_WIDTH "CRT - Min Beam Width" 0.86 0.0 1.0 0.02
#pragma parameter BEAM_MAX_WIDTH "CRT - Max Beam Width" 1.0 0.0 1.0 0.02
#pragma parameter CRT_ANTI_RINGING "CRT - Anti-Ringing" 0.8 0.0 1.0 0.1
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
@ -12,65 +43,45 @@ layout(std140, set = 0, binding = 0) uniform UBO
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
layout(location = 2) out float frame_count;
layout(location = 3) out float frame_direction;
layout(location = 4) out float frame_rotation;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 1) in vec2 FragCoord;
layout(location = 0) out vec4 FragColor;
layout(location = 2) in float frame_count;
layout(location = 3) in float frame_direction;
layout(location = 4) in float frame_rotation;
layout(set = 0, binding = 2) uniform sampler2D Source;
#define PHOSPHOR 1.0
#define VSCANLINES 0.0
#define InputGamma 2.5
#define OutputGamma 2.2
#define SHARPNESS 1.0
#define COLOR_BOOST 1.5
#define RED_BOOST 1.0
#define GREEN_BOOST 1.0
#define BLUE_BOOST 1.0
#define SCANLINES_STRENGTH 0.50
#define BEAM_MIN_WIDTH 0.86
#define BEAM_MAX_WIDTH 1.0
#define CRT_ANTI_RINGING 0.8
/*
Hyllian's CRT Shader
Copyright (C) 2011-2016 Hyllian - sergiogdb@gmail.com
Hyllian's CRT Shader
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:
Copyright (C) 2011-2016 Hyllian - sergiogdb@gmail.com
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
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 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.
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 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))
#define GAMMA_IN(color) pow(color, vec3(param.InputGamma, param.InputGamma, param.InputGamma))
#define GAMMA_OUT(color) pow(color, vec3(1.0 / param.OutputGamma, 1.0 / param.OutputGamma, 1.0 / param.OutputGamma))
// Horizontal cubic filter.
@ -103,16 +114,16 @@ void main()
{
vec3 color;
vec2 TextureSize = vec2(SHARPNESS*global.SourceSize.x, global.SourceSize.y);
vec2 TextureSize = vec2(param.SHARPNESS*global.SourceSize.x, global.SourceSize.y);
vec2 dx = mix(vec2(1.0/TextureSize.x, 0.0), vec2(0.0, 1.0/TextureSize.y), VSCANLINES);
vec2 dy = mix(vec2(0.0, 1.0/TextureSize.y), vec2(1.0/TextureSize.x, 0.0), VSCANLINES);
vec2 dx = mix(vec2(1.0/TextureSize.x, 0.0), vec2(0.0, 1.0/TextureSize.y), param.VSCANLINES);
vec2 dy = mix(vec2(0.0, 1.0/TextureSize.y), vec2(1.0/TextureSize.x, 0.0), param.VSCANLINES);
vec2 pix_coord = vTexCoord*TextureSize + vec2(-0.5, 0.5);
vec2 tc = mix((floor(pix_coord) + vec2(0.5, 0.5))/TextureSize, (floor(pix_coord) + vec2(1.0, -0.5))/TextureSize, VSCANLINES);
vec2 tc = mix((floor(pix_coord) + vec2(0.5, 0.5))/TextureSize, (floor(pix_coord) + vec2(1.0, -0.5))/TextureSize, param.VSCANLINES);
vec2 fp = mix(fract(pix_coord), fract(pix_coord.yx), VSCANLINES);
vec2 fp = mix(fract(pix_coord), fract(pix_coord.yx), param.VSCANLINES);
vec3 c00 = GAMMA_IN(texture(Source, tc - dx - dy).xyz);
vec3 c01 = GAMMA_IN(texture(Source, tc - dy).xyz);
@ -137,36 +148,36 @@ void main()
// Anti-ringing
vec3 aux = color0;
color0 = clamp(color0, min_sample, max_sample);
color0 = mix(aux, color0, CRT_ANTI_RINGING);
color0 = mix(aux, color0, param.CRT_ANTI_RINGING);
aux = color1;
color1 = clamp(color1, min_sample, max_sample);
color1 = mix(aux, color1, CRT_ANTI_RINGING);
color1 = mix(aux, color1, param.CRT_ANTI_RINGING);
float pos0 = fp.y;
float pos1 = 1 - fp.y;
vec3 lum0 = mix(vec3(BEAM_MIN_WIDTH), vec3(BEAM_MAX_WIDTH), color0);
vec3 lum1 = mix(vec3(BEAM_MIN_WIDTH), vec3(BEAM_MAX_WIDTH), color1);
vec3 lum0 = mix(vec3(param.BEAM_MIN_WIDTH), vec3(param.BEAM_MAX_WIDTH), color0);
vec3 lum1 = mix(vec3(param.BEAM_MIN_WIDTH), vec3(param.BEAM_MAX_WIDTH), color1);
vec3 d0 = clamp(pos0/(lum0 + 0.0000001), 0.0, 1.0);
vec3 d1 = clamp(pos1/(lum1 + 0.0000001), 0.0, 1.0);
d0 = exp(-10.0*SCANLINES_STRENGTH*d0*d0);
d1 = exp(-10.0*SCANLINES_STRENGTH*d1*d1);
d0 = exp(-10.0*param.SCANLINES_STRENGTH*d0*d0);
d1 = exp(-10.0*param.SCANLINES_STRENGTH*d1*d1);
color = clamp(color0*d0 + color1*d1, 0.0, 1.0);
color *= COLOR_BOOST*vec3(RED_BOOST, GREEN_BOOST, BLUE_BOOST);
color *= param.COLOR_BOOST*vec3(param.RED_BOOST, param.GREEN_BOOST, param.BLUE_BOOST);
float mod_factor = mix(vTexCoord.x * global.OutputSize.x * global.SourceSize.x, vTexCoord.y * global.OutputSize.y * global.SourceSize.y, VSCANLINES);
float mod_factor = mix(vTexCoord.x * global.OutputSize.x, vTexCoord.y * global.OutputSize.y, param.VSCANLINES);
vec3 dotMaskWeights = mix(
vec3(1.0, 0.7, 1.0),
vec3(0.7, 1.0, 0.7),
floor(mod(mod_factor, 2.0)) /* Possible bug - Does mod() behave like fmod() ? */
floor(mod(mod_factor, 2.0))
);
color.rgb *= mix(vec3(1.0, 1.0, 1.0), dotMaskWeights, PHOSPHOR);
color.rgb *= mix(vec3(1.0), dotMaskWeights, param.PHOSPHOR);
color = GAMMA_OUT(color);

View File

@ -1,5 +1,36 @@
#version 450
layout(push_constant) uniform Push
{
float hardScan;
float hardPix;
float warpX;
float warpY;
float maskDark;
float maskLight;
float scaleInLinearGamma;
float shadowMask;
float brightBoost;
float hardBloomScan;
float hardBloomPix;
float bloomAmount;
float shape;
} param;
#pragma parameter hardScan "hardScan" -8.0 -20.0 0.0 1.0
#pragma parameter hardPix "hardPix" -3.0 -20.0 0.0 1.0
#pragma parameter warpX "warpX" 0.031 0.0 0.125 0.01
#pragma parameter warpY "warpY" 0.041 0.0 0.125 0.01
#pragma parameter maskDark "maskDark" 0.5 0.0 2.0 0.1
#pragma parameter maskLight "maskLight" 1.5 0.0 2.0 0.1
#pragma parameter scaleInLinearGamma "scaleInLinearGamma" 1.0 0.0 1.0 1.0
#pragma parameter shadowMask "shadowMask" 3.0 0.0 4.0 1.0
#pragma parameter brightBoost "brightness boost" 1.0 0.0 2.0 0.05
#pragma parameter hardBloomPix "bloom-x soft" -1.5 -2.0 -0.5 0.1
#pragma parameter hardBloomScan "bloom-y soft" -2.0 -4.0 -1.0 0.1
#pragma parameter bloomAmount "bloom ammount" 0.15 0.0 1.0 0.05
#pragma parameter shape "filter kernel shape" 2.0 0.0 10.0 0.05
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
@ -15,8 +46,8 @@ layout(location = 0) out vec2 vTexCoord;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
}
// PUBLIC DOMAIN CRT STYLED SCAN-LINE SHADER
@ -38,22 +69,6 @@ layout(location = 1) in vec2 FragCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
// -- config -- //
#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
#define shadowMask 1
#define brightboost 1
#define hardBloomScan -2.0
#define hardBloomPix -1.5
#define bloomAmount 1.0/16.0
#define shape 2.0
//Uncomment to reduce instructions with simpler linearization
//(fixes HD3000 Sandy Bridge IGP)
//#define SIMPLE_LINEAR_GAMMA
@ -66,41 +81,49 @@ layout(set = 0, binding = 2) uniform sampler2D Source;
#ifdef SIMPLE_LINEAR_GAMMA
float ToLinear1(float c)
{
return c;
return c;
}
float3 ToLinear(vec3 c)
vec3 ToLinear(vec3 c)
{
return c;
return c;
}
vec3 ToSrgb(vec3 c)
{
return pow(c, 1.0 / 2.2);
return pow(c, 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);
if (param.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));
if (param.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);
if (param.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));
if (param.scaleInLinearGamma == 0)
return c;
return vec3(ToSrgb1(c.r), ToSrgb1(c.g), ToSrgb1(c.b));
}
#endif
@ -111,177 +134,224 @@ vec3 ToSrgb(vec3 c)
vec3 Fetch(vec2 pos,vec2 off){
pos=(floor(pos*global.SourceSize.xy+off)+vec2(0.5,0.5))/global.SourceSize.xy;
#ifdef SIMPLE_LINEAR_GAMMA
return ToLinear(brightboost * pow(texture(Source,pos.xy).rgb, 2.2));
return ToLinear(param.brightBoost * pow(texture(Source,pos.xy).rgb, 2.2));
#else
return ToLinear(brightboost * texture(Source,pos.xy).rgb);}
return ToLinear(param.brightBoost * texture(Source,pos.xy).rgb);}
#endif
// Distance in emulated pixels to nearest texel.
vec2 Dist(vec2 pos){pos=pos*global.SourceSize.xy;return -((pos-floor(pos))-vec2(0.5));}
vec2 Dist(vec2 pos)
{
pos = pos*global.SourceSize.xy;
return -((pos - floor(pos)) - vec2(0.5));
}
// 1D Gaussian.
float Gaus(float pos,float scale){return exp2(scale*pow(abs(pos),shape));}
float Gaus(float pos, float scale)
{
return exp2(scale*pow(abs(pos), param.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);}
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 = param.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);}
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 = param.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);}
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 = param.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);}
float Scan(vec2 pos, float off)
{
float dst = Dist(pos).y;
return Gaus(dst + off, param.hardScan);
}
// Return scanline weight for bloom.
float BloomScan(vec2 pos,float off){
float dst=Dist(pos).y;
return Gaus(dst+off,hardBloomScan);}
float BloomScan(vec2 pos, float off)
{
float dst = Dist(pos).y;
return Gaus(dst + off, param.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;}
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;}
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;}
vec2 Warp(vec2 pos)
{
pos = pos*2.0-1.0;
pos *= vec2(1.0 + (pos.y*pos.y)*param.warpX, 1.0 + (pos.x*pos.x)*param.warpY);
return pos*0.5 + 0.5;
}
// Shadow mask.
vec3 Mask(vec2 pos){
vec3 mask=vec3(maskDark,maskDark,maskDark);
vec3 Mask(vec2 pos)
{
vec3 mask = vec3(param.maskDark, param.maskDark, param.maskDark);
// Very compressed TV style shadow mask.
if (shadowMask == 1.0) {
float line=maskLight;
float odd=0.0;
if(fract(pos.x/6.0)<0.5)odd=1.0;
if(fract((pos.y+odd)/2.0)<0.5)line=maskDark;
pos.x=fract(pos.x/3.0);
if(pos.x<0.333)mask.r=maskLight;
else if(pos.x<0.666)mask.g=maskLight;
else mask.b=maskLight;
mask*=line;
}
// Very compressed TV style shadow mask.
if (param.shadowMask == 1.0)
{
float line = param.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 = param.maskDark;
pos.x = fract(pos.x*0.333333333);
// Aperture-grille.
else if (shadowMask == 2.0) {
pos.x=fract(pos.x/3.0);
if (pos.x < 0.333) mask.r = param.maskLight;
else if (pos.x < 0.666) mask.g = param.maskLight;
else mask.b = param.maskLight;
mask*=line;
}
if(pos.x<0.333)mask.r=maskLight;
else if(pos.x<0.666)mask.g=maskLight;
else mask.b=maskLight;
}
// Aperture-grille.
else if (param.shadowMask == 2.0)
{
pos.x = fract(pos.x*0.333333333);
// 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/6.0);
if (pos.x < 0.333) mask.r = param.maskLight;
else if (pos.x < 0.666) mask.g = param.maskLight;
else mask.b = param.maskLight;
}
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 (param.shadowMask == 3.0)
{
pos.x += pos.y*3.0;
pos.x = fract(pos.x*0.166666666);
// 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/6.0);
if (pos.x < 0.333) mask.r = param.maskLight;
else if (pos.x < 0.666) mask.g = param.maskLight;
else mask.b = param.maskLight;
}
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 (param.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);
return mask;}
if (pos.x < 0.333) mask.r = param.maskLight;
else if (pos.x < 0.666) mask.g = param.maskLight;
else mask.b = param.maskLight;
}
return mask;
}
void main()
{
vec2 pos=Warp(vTexCoord);
vec3 outColor = Tri(pos);
#ifdef DO_BLOOM
//Add Bloom
outColor.rgb+=Bloom(pos)*bloomAmount;
#endif
if(shadowMask > 0.0)
outColor.rgb*=Mask(vTexCoord.xy / global.OutputSize.zw * 1.000001);
//hacky clamp fix
vec2 bordertest = (pos);
if ( bordertest.x > 0.0001 && bordertest.x < 0.9999 && bordertest.y > 0.0001 && bordertest.y < 0.9999)
outColor.rgb = outColor.rgb;
else
outColor.rgb = vec3(0.0);
vec2 pos = Warp(vTexCoord);
vec3 outColor = Tri(pos);
FragColor = vec4(ToSrgb(outColor.rgb), 1.0);
}
#ifdef DO_BLOOM
//Add Bloom
outColor.rgb += Bloom(pos)*param.bloomAmount;
#endif
if (param.shadowMask > 0.0)
outColor.rgb *= Mask(vTexCoord.xy / global.OutputSize.zw * 1.000001);
/* TODO/FIXME - hacky clamp fix */
vec2 bordertest = (pos);
if ( bordertest.x > 0.0001 && bordertest.x < 0.9999 && bordertest.y > 0.0001 && bordertest.y < 0.9999)
outColor.rgb = outColor.rgb;
else
outColor.rgb = vec3(0.0);
FragColor = vec4(ToSrgb(outColor.rgb), 1.0);
}

View File

@ -1,5 +1,12 @@
#version 450
layout(push_constant) uniform Push
{
float BOOST;
} param;
#pragma parameter BOOST "Color Boost" 1.0 0.5 1.5 0.02
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
@ -48,8 +55,6 @@ vec3 beam(vec3 color, float dist)
#endif
}
#define COLOR_BOOST 1.0
void main()
{
vec2 texel = floor(data_pix_no);
@ -67,6 +72,6 @@ void main()
scanline += beam(top, dist0);
scanline += beam(bottom, dist1);
FragColor = vec4(COLOR_BOOST * scanline * 0.869565217391304, 1.0);
FragColor = vec4(param.BOOST * scanline * 0.869565217391304, 1.0);
}

View File

@ -1,5 +1,12 @@
#version 450
layout(push_constant) uniform Push
{
float INPUT_GAMMA;
} param;
#pragma parameter INPUT_GAMMA "Input Gamma" 2.4 2.0 2.6 0.02
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
@ -24,11 +31,9 @@ layout(location = 0) in vec2 vTexCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
#define INPUT_GAMMA 2.4
void main()
{
vec3 color = texture(Source, vTexCoord).rgb;
FragColor = vec4(pow(color, vec3(INPUT_GAMMA)), 1.0);
FragColor = vec4(pow(color, vec3(param.INPUT_GAMMA)), 1.0);
}

View File

@ -1,5 +1,14 @@
#version 450
layout(push_constant) uniform Push
{
float BLOOM_STRENGTH;
float OUTPUT_GAMMA;
} param;
#pragma parameter BLOOM_STRENGTH "Glow Strength" 0.45 0.0 0.8 0.05
#pragma parameter OUTPUT_GAMMA "Monitor Gamma" 2.2 1.8 2.6 0.02
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
@ -29,9 +38,6 @@ layout(set = 0, binding = 2) uniform sampler2D CRTPass;
// For debugging
#define BLOOM_ONLY 0
#define BLOOM_STRENGTH 0.45
#define OUTPUT_GAMMA 2.2
#define CRT_PASS CRTPass
void main()
@ -42,7 +48,7 @@ void main()
vec3 source = 1.15 * texture(CRT_PASS, vTexCoord).rgb;
vec3 bloom = texture(Source, vTexCoord).rgb;
source += BLOOM_STRENGTH * bloom;
source += param.BLOOM_STRENGTH * bloom;
#endif
FragColor = vec4(pow(clamp(source, 0.0, 1.0), vec3(1.0 / OUTPUT_GAMMA)), 1.0);
FragColor = vec4(pow(clamp(source, 0.0, 1.0), vec3(1.0 / param.OUTPUT_GAMMA)), 1.0);
}

View File

@ -1,5 +1,14 @@
#version 450
layout(push_constant) uniform Push
{
float GLOW_WHITEPOINT;
float GLOW_ROLLOFF;
} param;
#pragma parameter GLOW_WHITEPOINT "Glow Whitepoint" 1.0 0.5 1.1 0.02
#pragma parameter GLOW_ROLLOFF "Glow Rolloff" 3.0 1.2 6.0 0.1
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
@ -24,13 +33,10 @@ layout(location = 0) in vec2 vTexCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
#define GLOW_WHITEPOINT 1.0
#define GLOW_ROLLOFF 3.0
void main()
{
vec3 color = 1.15 * texture(Source, vTexCoord).rgb;
vec3 factor = clamp(color / GLOW_WHITEPOINT, 0.0, 1.0);
vec3 factor = clamp(color / param.GLOW_WHITEPOINT, 0.0, 1.0);
FragColor = vec4(pow(factor, vec3(GLOW_ROLLOFF)), 1.0);
FragColor = vec4(pow(factor, vec3(param.GLOW_ROLLOFF)), 1.0);
}

View File

@ -43,6 +43,17 @@
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
layout(push_constant) uniform Push
{
float FIR_GAIN;
float FIR_INVGAIN;
float PHASE_NOISE;
} param;
#pragma parameter FIR_GAIN "FIR lowpass gain" 1.5 0.0 5.0 0.1
#pragma parameter FIR_INVGAIN "Inverse gain for luma recovery" 1.1 0.0 5.0 0.1
#pragma parameter PHASE_NOISE "Phase noise" 1.0 0.0 5.0 0.1
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
@ -68,30 +79,12 @@ layout(location = 0) in vec2 vTexCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
/* Config options */
/* FIR lowpass gain */
#define FIR_GAIN 1.5
/* Inverse gain for luma recovery (correct for stripes) */
#define FIR_INVGAIN 1.1
/* phase noise (2.5 for crappy cable) */
#define PHASE_NOISE 1.0
/* Subcarrier frequency */
#define FSC 4433618.75
/* Line frequency */
#define FLINE 15625
#define VISIBLELINES 312
#define PI 3.14159265358
@ -140,14 +133,13 @@ float FIR[FIRTAPS] = float[FIRTAPS] (
/* subcarrier counts per scan line = FSC/FLINE = 283.7516 */
/* We save the reciprocal of this only to optimize it */
float counts_per_scanline_reciprocal = 0.00352420920269701;
float counts_per_scanline_reciprocal = 1.0 / (FSC/FLINE);
float width_ratio;
float height_ratio;
float altv;
float invx;
/* http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/ */
float rand(vec2 co)
{
@ -160,7 +152,8 @@ float rand(vec2 co)
return fract(sin(sn) * c);
}
float modulated(vec2 xy, float sinwt, float coswt) {
float modulated(vec2 xy, float sinwt, float coswt)
{
vec3 rgb = fetch(0, xy, invx).xyz;
vec3 yuv = RGB_to_YUV * rgb;
@ -178,14 +171,13 @@ vec2 modem_uv(vec2 xy, float ofs) {
vec3 yuv = RGB_to_YUV * rgb;
float signal = clamp(yuv.x + yuv.y * sinwt + yuv.z * coswt, 0.0, 1.0);
if (PHASE_NOISE != 0)
if (param.PHASE_NOISE != 0)
{
/* .yy is horizontal noise, .xx looks bad, .xy is classic noise */
vec2 seed = vTexCoord.yy + global.FrameCount;
wt = wt + PHASE_NOISE * (rand(seed) - 0.5);
sinwt = sin(wt);
coswt = cos(wt + altv);
vec2 seed = xy.yy * global.FrameCount;
wt = wt + param.PHASE_NOISE * (rand(seed) - 0.5);
sinwt = sin(wt);
coswt = cos(wt + altv);
}
return vec2(signal * sinwt, signal * coswt);
@ -203,7 +195,7 @@ void main()
vec2 filtered = vec2(0.0, 0.0);
for (int i = 0; i < FIRTAPS; i++) {
vec2 uv = modem_uv(xy, i - FIRTAPS*0.5);
filtered += FIR_GAIN * uv * FIR[i];
filtered += param.FIR_GAIN * uv * FIR[i];
}
float t = xy.x * global.SourceSize.x;
@ -212,7 +204,7 @@ void main()
float sinwt = sin(wt);
float coswt = cos(wt + altv);
float luma = modulated(xy, sinwt, coswt) - FIR_INVGAIN * (filtered.x * sinwt + filtered.y * coswt);
float luma = modulated(xy, sinwt, coswt) - param.FIR_INVGAIN * (filtered.x * sinwt + filtered.y * coswt);
vec3 yuv_result = vec3(luma, filtered.x, filtered.y);
FragColor = vec4(YUV_to_RGB * yuv_result, 1.0);