Major update to crt-hyllian and variants

- All shaders are multipass now and include curvature code;
- Get rid of most old presets keep only relevant ones;
This commit is contained in:
Hyllian 2024-02-15 11:05:55 -03:00
parent 63edcb38db
commit 0de94ba9ca
31 changed files with 1719 additions and 1820 deletions

View file

@ -1,105 +0,0 @@
shaders = "9"
shader0 = ../stock.slang
alias0 = PrePass0
shader1 = shaders/guest/advanced/ntsc/ntsc-pass1.slang
alias1 = NPass1
scale_type_x1 = source
scale_type_y1 = source
scale_x1 = 4.0
scale_y1 = 1.0
float_framebuffer1 = true
filter_linear1 = false
shader2 = shaders/guest/advanced/ntsc/ntsc-pass2.slang
filter_linear2 = true
float_framebuffer2 = true
scale_type2 = source
scale_x2 = 0.5
scale_y2 = 1.0
shader3 = shaders/guest/advanced/ntsc/ntsc-pass3.slang
filter_linear3 = true
scale_type3 = source
scale_x3 = 1.0
scale_y3 = 1.0
shader4 = "../crt/shaders/hyllian/crt-hyllian-curvature.slang"
filter_linear4 = "false"
wrap_mode4 = "clamp_to_border"
mipmap_input4 = "false"
alias4 = "CRTPass"
float_framebuffer4 = "false"
srgb_framebuffer4 = "true"
scale_type_x4 = "viewport"
scale_x4 = "1.000000"
scale_type_y4 = "viewport"
scale_y4 = "1.000000"
shader5 = "../crt/shaders/glow/threshold.slang"
filter_linear5 = "true"
wrap_mode5 = "clamp_to_border"
mipmap_input5 = "false"
alias5 = ""
float_framebuffer5 = "false"
srgb_framebuffer5 = "true"
shader6 = "../crt/shaders/glow/blur_horiz.slang"
filter_linear6 = "true"
wrap_mode6 = "clamp_to_border"
mipmap_input6 = "true"
alias6 = ""
float_framebuffer6 = "false"
srgb_framebuffer6 = "true"
scale_type_x6 = "viewport"
scale_x6 = "0.200000"
scale_type_y6 = "viewport"
scale_y6 = "0.200000"
shader7 = "../crt/shaders/glow/blur_vert.slang"
filter_linear7 = "true"
wrap_mode7 = "clamp_to_border"
mipmap_input7 = "false"
alias7 = ""
float_framebuffer7 = "false"
srgb_framebuffer7 = "true"
shader8 = "../crt/shaders/glow/resolve.slang"
filter_linear8 = "true"
wrap_mode8 = "clamp_to_border"
mipmap_input8 = "false"
alias8 = ""
float_framebuffer8 = "false"
srgb_framebuffer8 = "false"
scale_type8 = viewport
parameters = "linearize;quality;ntsc_sat;BEAM_PROFILE;HFILTER_PROFILE;BEAM_MIN_WIDTH;BEAM_MAX_WIDTH;SCANLINES_STRENGTH;COLOR_BOOST;PHOSPHOR_LAYOUT;MASK_INTENSITY;CRT_ANTI_RINGING;InputGamma;OutputGamma;VSCANLINES;CRT_CURVATURE;CRT_warpX;CRT_warpY;CRT_cornersize;CRT_cornersmooth;GLOW_WHITEPOINT;GLOW_ROLLOFF;BLOOM_STRENGTH;OUTPUT_GAMMA;CURVATURE;warpX;warpY;cornersize;cornersmooth;noise_amt;shadowMask;maskDark;maskLight"
BEAM_PROFILE = "0.000000"
HFILTER_PROFILE = "1.000000"
BEAM_MIN_WIDTH = "0.920000"
BEAM_MAX_WIDTH = "1.000000"
SCANLINES_STRENGTH = "0.720000"
COLOR_BOOST = "1.600000"
PHOSPHOR_LAYOUT = "4.000000"
MASK_INTENSITY = "0.700000"
CRT_ANTI_RINGING = "1.000000"
InputGamma = "2.000000"
OutputGamma = "2.000000"
VSCANLINES = "0.000000"
CRT_CURVATURE = "1.000000"
CRT_warpX = "0.015000"
CRT_warpY = "0.015000"
CRT_cornersize = "0.010000"
CRT_cornersmooth = "380.000000"
GLOW_WHITEPOINT = "0.900000"
GLOW_ROLLOFF = "3.000000"
BLOOM_STRENGTH = "0.100000"
OUTPUT_GAMMA = "2.200000"
CURVATURE = "0.000000"
warpX = "0.015000"
warpY = "0.015000"
cornersize = "0.010000"
cornersmooth = "380.000000"
noise_amt = "0.000000"
shadowMask = "0.000000"
maskDark = "0.500000"
maskLight = "1.500000"
linearize = "1.0"
quality = "0.0"
ntsc_sat = "1.2"

View file

@ -1,5 +0,0 @@
shaders = 1
shader0 = shaders/hyllian/crt-hyllian-curvature.slang
filter_linear0 = false
scale_type0 = viewport

View file

@ -1,97 +0,0 @@
shaders = "9"
shader0 = "../crt/shaders/glow/linearize.slang"
filter_linear0 = "false"
wrap_mode0 = "clamp_to_border"
mipmap_input0 = "false"
alias0 = "LinearGamma"
float_framebuffer0 = "false"
srgb_framebuffer0 = "true"
shader1 = ../dithering/shaders/checkerboard-dedither/checkerboard-dedither-pass1.slang
filter_linear1 = false
scale_type1 = source
scale1 = 1.0
shader2 = ../dithering/shaders/checkerboard-dedither/checkerboard-dedither-pass2.slang
filter_linear2 = false
scale_type2 = source
scale2 = 1.0
shader3 = ../dithering/shaders/checkerboard-dedither/checkerboard-dedither-pass3.slang
filter_linear3 = false
scale_type3 = source
scale3 = 1.0
shader4 = "shaders/hyllian/crt-hyllian.slang"
filter_linear4 = "false"
wrap_mode4 = "clamp_to_border"
mipmap_input4 = "false"
alias4 = "CRTPass"
float_framebuffer4 = "false"
srgb_framebuffer4 = "true"
scale_type_x4 = "viewport"
scale_x4 = "1.000000"
scale_type_y4 = "viewport"
scale_y4 = "1.000000"
shader5 = "../crt/shaders/glow/threshold.slang"
filter_linear5 = "false"
wrap_mode5 = "clamp_to_border"
mipmap_input5 = "false"
alias5 = ""
float_framebuffer5 = "false"
srgb_framebuffer5 = "true"
shader6 = "../crt/shaders/glow/blur_horiz.slang"
filter_linear6 = "true"
wrap_mode6 = "clamp_to_border"
mipmap_input6 = "true"
alias6 = ""
float_framebuffer6 = "false"
srgb_framebuffer6 = "true"
scale_type_x6 = "viewport"
scale_x6 = "0.200000"
scale_type_y6 = "viewport"
scale_y6 = "0.200000"
shader7 = "../crt/shaders/glow/blur_vert.slang"
filter_linear7 = "true"
wrap_mode7 = "clamp_to_border"
mipmap_input7 = "false"
alias7 = ""
float_framebuffer7 = "false"
srgb_framebuffer7 = "true"
shader8 = "../crt/shaders/glow/resolve.slang"
filter_linear8 = "true"
wrap_mode8 = "clamp_to_border"
mipmap_input8 = "false"
alias8 = ""
float_framebuffer8 = "false"
srgb_framebuffer8 = "false"
scale_type8 = viewport
parameters = "CD_HUD_DETAILS;INPUT_GAMMA;HFILTER_PROFILE;BEAM_MIN_WIDTH;BEAM_MAX_WIDTH;SCANLINES_STRENGTH;COLOR_BOOST;SHARPNESS_HACK;PHOSPHOR_LAYOUT;MASK_INTENSITY;InputGamma;OutputGamma;VSCANLINES;GLOW_WHITEPOINT;GLOW_ROLLOFF;BLOOM_STRENGTH;OUTPUT_GAMMA;CURVATURE;warpX;warpY;cornersize;cornersmooth;noise_amt;shadowMask;maskDark;maskLight"
CD_HUD_DETAILS = "5.0"
INPUT_GAMMA = "2.000000"
HFILTER_PROFILE = "0.000000"
BEAM_MIN_WIDTH = "1.000000"
BEAM_MAX_WIDTH = "1.000000"
SCANLINES_STRENGTH = "0.580000"
COLOR_BOOST = "1.300000"
SHARPNESS_HACK = "1.000000"
PHOSPHOR_LAYOUT = "4.000000"
MASK_INTENSITY = "0.700000"
InputGamma = "2.400000"
OutputGamma = "1.000000"
VSCANLINES = "0.000000"
GLOW_WHITEPOINT = "0.900000"
GLOW_ROLLOFF = "3.000000"
BLOOM_STRENGTH = "0.100000"
OUTPUT_GAMMA = "2.200000"
CURVATURE = "0.000000"
warpX = "0.010000"
warpY = "0.020000"
cornersize = "0.010000"
cornersmooth = "280.000000"
noise_amt = "1.000000"
shadowMask = "0.000000"
maskDark = "0.500000"
maskLight = "1.500000"

View file

@ -1,80 +0,0 @@
shaders = "6"
shader0 = "shaders/glow/linearize.slang"
filter_linear0 = "false"
wrap_mode0 = "clamp_to_border"
mipmap_input0 = "false"
alias0 = ""
float_framebuffer0 = "false"
srgb_framebuffer0 = "true"
shader1 = "shaders/hyllian/crt-hyllian.slang"
filter_linear1 = "false"
wrap_mode1 = "clamp_to_border"
mipmap_input1 = "false"
alias1 = "CRTPass"
float_framebuffer1 = "false"
srgb_framebuffer1 = "true"
scale_type_x1 = "viewport"
scale_x1 = "1.000000"
scale_type_y1 = "viewport"
scale_y1 = "1.000000"
shader2 = "shaders/glow/threshold.slang"
filter_linear2 = "true"
wrap_mode2 = "clamp_to_border"
mipmap_input2 = "false"
alias2 = ""
float_framebuffer2 = "false"
srgb_framebuffer2 = "true"
shader3 = "shaders/glow/blur_horiz.slang"
filter_linear3 = "true"
wrap_mode3 = "clamp_to_border"
mipmap_input3 = "true"
alias3 = ""
float_framebuffer3 = "false"
srgb_framebuffer3 = "true"
scale_type_x3 = "viewport"
scale_x3 = "0.200000"
scale_type_y3 = "viewport"
scale_y3 = "0.200000"
shader4 = "shaders/glow/blur_vert.slang"
filter_linear4 = "true"
wrap_mode4 = "clamp_to_border"
mipmap_input4 = "false"
alias4 = ""
float_framebuffer4 = "false"
srgb_framebuffer4 = "true"
shader5 = "shaders/glow/resolve.slang"
filter_linear5 = "true"
wrap_mode5 = "clamp_to_border"
mipmap_input5 = "false"
alias5 = ""
float_framebuffer5 = "false"
srgb_framebuffer5 = "false"
scale_type5 = viewport
parameters = "INPUT_GAMMA;BEAM_PROFILE;HFILTER_PROFILE;BEAM_MIN_WIDTH;BEAM_MAX_WIDTH;SCANLINES_STRENGTH;COLOR_BOOST;SHARPNESS_HACK;PHOSPHOR_LAYOUT;MASK_INTENSITY;CRT_ANTI_RINGING;InputGamma;OutputGamma;VSCANLINES;GLOW_WHITEPOINT;GLOW_ROLLOFF;BLOOM_STRENGTH;OUTPUT_GAMMA;CURVATURE;warpX;warpY;cornersize;cornersmooth;noise_amt;shadowMask;maskDark;maskLight"
INPUT_GAMMA = "2.400000"
BEAM_PROFILE = "0.000000"
HFILTER_PROFILE = "0.000000"
BEAM_MIN_WIDTH = "1.000000"
BEAM_MAX_WIDTH = "1.000000"
SCANLINES_STRENGTH = "0.580000"
COLOR_BOOST = "1.350000"
SHARPNESS_HACK = "1.000000"
PHOSPHOR_LAYOUT = "4.000000"
MASK_INTENSITY = "0.700000"
CRT_ANTI_RINGING = "1.000000"
InputGamma = "1.000000"
OutputGamma = "1.000000"
VSCANLINES = "0.000000"
GLOW_WHITEPOINT = "0.900000"
GLOW_ROLLOFF = "3.000000"
BLOOM_STRENGTH = "0.100000"
OUTPUT_GAMMA = "2.200000"
CURVATURE = "0.000000"
warpX = "0.015000"
warpY = "0.015000"
cornersize = "0.010000"
cornersmooth = "380.000000"
noise_amt = "0.000000"
shadowMask = "0.000000"
maskDark = "0.500000"
maskLight = "1.500000"

View file

@ -1,19 +0,0 @@
shaders = 2
shader0 = shaders/hyllian/crt-hyllian-multipass/crt-hyllian-pass0.slang
filter_linear0 = false
srgb_framebuffer0 = true
scale_type_x0 = viewport
scale_type_y0 = source
scale_x0 = 1.0
scale_y0 = 1.0
shader1 = shaders/hyllian/crt-hyllian-multipass/crt-hyllian-pass1.slang
filter_linear1 = false
scale_type1 = viewport
# Uncomment these lines for a sharper variation
#parameters = "SHARPNESS;SCANLINES_STRENGTH;BEAM_MIN_WIDTH"
#SHARPNESS = "2.0"
#SCANLINES_STRENGTH = "0.50"
#BEAM_MIN_WIDTH = "0.44"

View file

@ -0,0 +1,72 @@
shaders = "5"
feedback_pass = "0"
shader0 = "shaders/hyllian/support/multiLUT-modified.slang"
wrap_mode0 = "clamp_to_border"
mipmap_input0 = "false"
alias0 = ""
float_framebuffer0 = "false"
srgb_framebuffer0 = "false"
scale_type_x0 = "source"
scale_x0 = "1.000000"
scale_type_y0 = "source"
scale_y0 = "1.000000"
shader1 = "shaders/hyllian/support/ntsc/shaders/ntsc-adaptive-lite/ntsc-lite-pass1.slang"
filter_linear1 = "false"
wrap_mode1 = "clamp_to_edge"
mipmap_input1 = "false"
alias1 = ""
float_framebuffer1 = "true"
srgb_framebuffer1 = "false"
scale_type_x1 = "source"
scale_x1 = "4.000000"
scale_type_y1 = "source"
scale_y1 = "1.000000"
shader2 = "shaders/hyllian/support/ntsc/shaders/ntsc-adaptive-lite/ntsc-lite-pass2.slang"
filter_linear2 = "true"
wrap_mode2 = "clamp_to_edge"
mipmap_input2 = "false"
alias2 = ""
float_framebuffer2 = "false"
srgb_framebuffer2 = "false"
scale_type_x2 = "source"
scale_x2 = "1.000000"
scale_type_y2 = "source"
scale_y2 = "1.000000"
shader3 = "shaders/hyllian/support/linearize.slang"
filter_linear3 = "true"
wrap_mode3 = "clamp_to_edge"
mipmap_input3 = "false"
alias3 = ""
float_framebuffer3 = "false"
srgb_framebuffer3 = "true"
scale_type_x3 = "viewport"
scale_x3 = "1.000000"
scale_type_y3 = "source"
scale_y3 = "1.000000"
shader4 = "shaders/hyllian/crt-hyllian-pass1.slang"
filter_linear4 = "false"
wrap_mode4 = "clamp_to_edge"
mipmap_input4 = "false"
alias4 = ""
float_framebuffer4 = "false"
srgb_framebuffer4 = "false"
scale_type_x4 = "viewport"
scale_x4 = "1.000000"
scale_type_y4 = "viewport"
scale_y4 = "1.000000"
LUT_selector_param = "2.000000"
quality = "-1.000000"
chroma_scale = "3.000000"
cust_artifacting = "0.500000"
ntsc_artifacting_rainbow = "1.000000"
HFILTER_PROFILE = "0.000000"
BEAM_MIN_WIDTH = "0.860000"
BRIGHTBOOST = "1.600000"
PHOSPHOR_LAYOUT = "2.000000"
InputGamma = "2.400000"
textures = "SamplerLUT1;SamplerLUT2"
SamplerLUT1 = "shaders/guest/advanced/lut/ntsc-lut.png"
SamplerLUT1_linear = true
SamplerLUT2 = "shaders/hyllian/support/LUT/some-grade.png"
SamplerLUT2_linear = true

View file

@ -0,0 +1,70 @@
shaders = "5"
feedback_pass = "0"
shader0 = "shaders/hyllian/support/multiLUT-modified.slang"
wrap_mode0 = "clamp_to_border"
mipmap_input0 = "false"
alias0 = ""
float_framebuffer0 = "false"
srgb_framebuffer0 = "false"
scale_type_x0 = "source"
scale_x0 = "1.000000"
scale_type_y0 = "source"
scale_y0 = "1.000000"
shader1 = "shaders/hyllian/support/ntsc/shaders/ntsc-adaptive-lite/ntsc-lite-pass1.slang"
filter_linear1 = "false"
wrap_mode1 = "clamp_to_edge"
mipmap_input1 = "false"
alias1 = ""
float_framebuffer1 = "true"
srgb_framebuffer1 = "false"
scale_type_x1 = "source"
scale_x1 = "4.000000"
scale_type_y1 = "source"
scale_y1 = "1.000000"
shader2 = "shaders/hyllian/support/ntsc/shaders/ntsc-adaptive-lite/ntsc-lite-pass2.slang"
filter_linear2 = "true"
wrap_mode2 = "clamp_to_edge"
mipmap_input2 = "false"
alias2 = ""
float_framebuffer2 = "false"
srgb_framebuffer2 = "false"
scale_type_x2 = "source"
scale_x2 = "1.000000"
scale_type_y2 = "source"
scale_y2 = "1.000000"
shader3 = "shaders/hyllian/support/linearize.slang"
filter_linear3 = "true"
wrap_mode3 = "clamp_to_edge"
mipmap_input3 = "false"
alias3 = ""
float_framebuffer3 = "false"
srgb_framebuffer3 = "true"
scale_type_x3 = "viewport"
scale_x3 = "1.000000"
scale_type_y3 = "source"
scale_y3 = "1.000000"
shader4 = "shaders/hyllian/crt-hyllian-pass1.slang"
filter_linear4 = "false"
wrap_mode4 = "clamp_to_edge"
mipmap_input4 = "false"
alias4 = ""
float_framebuffer4 = "false"
srgb_framebuffer4 = "false"
scale_type_x4 = "viewport"
scale_x4 = "1.000000"
scale_type_y4 = "viewport"
scale_y4 = "1.000000"
LUT_selector_param = "2.000000"
quality = "-1.000000"
chroma_scale = "4.000000"
HFILTER_PROFILE = "0.000000"
BEAM_MIN_WIDTH = "0.860000"
BRIGHTBOOST = "1.600000"
PHOSPHOR_LAYOUT = "2.000000"
InputGamma = "2.400000"
textures = "SamplerLUT1;SamplerLUT2"
SamplerLUT1 = "shaders/guest/advanced/lut/ntsc-lut.png"
SamplerLUT1_linear = true
SamplerLUT2 = "shaders/hyllian/support/LUT/some-grade.png"
SamplerLUT2_linear = true

View file

@ -0,0 +1,52 @@
shaders = "3"
feedback_pass = "0"
shader0 = "shaders/hyllian/support/multiLUT-modified.slang"
wrap_mode0 = "clamp_to_border"
mipmap_input0 = "false"
alias0 = ""
float_framebuffer0 = "false"
srgb_framebuffer0 = "false"
scale_type_x0 = "source"
scale_x0 = "1.000000"
scale_type_y0 = "source"
scale_y0 = "1.000000"
shader1 = "shaders/hyllian/crt-hyllian-pass0.slang"
filter_linear1 = "false"
wrap_mode1 = "clamp_to_border"
mipmap_input1 = "false"
alias1 = ""
float_framebuffer1 = "false"
srgb_framebuffer1 = "true"
scale_type_x1 = "viewport"
scale_x1 = "1.000000"
scale_type_y1 = "source"
scale_y1 = "1.000000"
shader2 = "shaders/hyllian/crt-hyllian-pass1.slang"
filter_linear2 = "false"
wrap_mode2 = "clamp_to_edge"
mipmap_input2 = "false"
alias2 = ""
float_framebuffer2 = "false"
srgb_framebuffer2 = "true"
scale_type_x2 = "source"
scale_x2 = "1.000000"
scale_type_y2 = "viewport"
scale_y2 = "1.000000"
LUT_selector_param = "2.000000"
HFILTER_PROFILE = "0.000000"
BEAM_MIN_WIDTH = "0.860000"
BEAM_MAX_WIDTH = "1.000000"
PHOSPHOR_LAYOUT = "11.000000"
MASK_INTENSITY = "0.650000"
BRIGHTBOOST = "1.300000"
SCANLINES_STRENGTH = "0.550000"
CURVATURE = "1.000000"
WARP_X = "0.020000"
WARP_Y = "0.025000"
CORNER_SIZE = "0.025000"
CORNER_SMOOTHNESS = "1.080000"
textures = "SamplerLUT1;SamplerLUT2"
SamplerLUT1 = "shaders/guest/advanced/lut/ntsc-lut.png"
SamplerLUT1_linear = true
SamplerLUT2 = "shaders/hyllian/support/LUT/some-grade.png"
SamplerLUT2_linear = true

View file

@ -0,0 +1,51 @@
shaders = "3"
feedback_pass = "0"
shader0 = "shaders/hyllian/support/multiLUT-modified.slang"
wrap_mode0 = "clamp_to_border"
mipmap_input0 = "false"
alias0 = ""
float_framebuffer0 = "false"
srgb_framebuffer0 = "false"
scale_type_x0 = "source"
scale_x0 = "1.000000"
scale_type_y0 = "source"
scale_y0 = "1.000000"
shader1 = "shaders/hyllian/crt-hyllian-pass0.slang"
filter_linear1 = "false"
wrap_mode1 = "clamp_to_border"
mipmap_input1 = "false"
alias1 = ""
float_framebuffer1 = "false"
srgb_framebuffer1 = "true"
scale_type_x1 = "viewport"
scale_x1 = "1.000000"
scale_type_y1 = "source"
scale_y1 = "1.000000"
shader2 = "shaders/hyllian/crt-hyllian-pass1.slang"
filter_linear2 = "false"
wrap_mode2 = "clamp_to_edge"
mipmap_input2 = "false"
alias2 = ""
float_framebuffer2 = "false"
srgb_framebuffer2 = "true"
scale_type_x2 = "source"
scale_x2 = "1.000000"
scale_type_y2 = "viewport"
scale_y2 = "1.000000"
LUT_selector_param = "2.000000"
HFILTER_PROFILE = "0.000000"
BEAM_MIN_WIDTH = "0.860000"
BEAM_MAX_WIDTH = "1.000000"
SCANLINES_STRENGTH = "0.720000"
BRIGHTBOOST = "1.500000"
PHOSPHOR_LAYOUT = "2.000000"
MASK_INTENSITY = "0.650000"
CURVATURE = "1.000000"
WARP_X = "0.000000"
WARP_Y = "0.025000"
CORNER_SIZE = "0.011000"
textures = "SamplerLUT1;SamplerLUT2"
SamplerLUT1 = "shaders/guest/advanced/lut/ntsc-lut.png"
SamplerLUT1_linear = true
SamplerLUT2 = "shaders/hyllian/support/LUT/some-grade.png"
SamplerLUT2_linear = true

View file

@ -0,0 +1,43 @@
shaders = "3"
feedback_pass = "0"
shader0 = "shaders/hyllian/support/multiLUT-modified.slang"
wrap_mode0 = "clamp_to_border"
mipmap_input0 = "false"
alias0 = ""
float_framebuffer0 = "false"
srgb_framebuffer0 = "false"
scale_type_x0 = "source"
scale_x0 = "1.000000"
scale_type_y0 = "source"
scale_y0 = "1.000000"
shader1 = "shaders/hyllian/crt-hyllian-sinc-pass0.slang"
filter_linear1 = "false"
wrap_mode1 = "clamp_to_border"
mipmap_input1 = "false"
alias1 = ""
float_framebuffer1 = "false"
srgb_framebuffer1 = "true"
scale_type_x1 = "viewport"
scale_x1 = "1.000000"
scale_type_y1 = "source"
scale_y1 = "1.000000"
shader2 = "shaders/hyllian/crt-hyllian-pass1.slang"
filter_linear2 = "false"
wrap_mode2 = "clamp_to_edge"
mipmap_input2 = "false"
alias2 = ""
float_framebuffer2 = "false"
srgb_framebuffer2 = "true"
scale_type_x2 = "source"
scale_x2 = "1.000000"
scale_type_y2 = "viewport"
scale_y2 = "1.000000"
LUT_selector_param = "2.000000"
HFILTER_PROFILE = "2.000000"
PHOSPHOR_LAYOUT = "2.000000"
BRIGHTBOOST = "1.500000
textures = "SamplerLUT1;SamplerLUT2"
SamplerLUT1 = "shaders/guest/advanced/lut/ntsc-lut.png"
SamplerLUT1_linear = true
SamplerLUT2 = "shaders/hyllian/support/LUT/some-grade.png"
SamplerLUT2_linear = true

View file

@ -1,6 +0,0 @@
shaders = 1
shader0 = shaders/hyllian/crt-hyllian-sinc-curvature.slang
filter_linear0 = false
float_framebuffer0 = true
scale_type0 = viewport

View file

@ -1,78 +0,0 @@
shaders = "6"
shader0 = "shaders/glow/linearize.slang"
filter_linear0 = "false"
wrap_mode0 = "clamp_to_border"
mipmap_input0 = "false"
alias0 = ""
float_framebuffer0 = "false"
srgb_framebuffer0 = "true"
shader1 = "shaders/hyllian/crt-hyllian-sinc.slang"
filter_linear1 = "false"
wrap_mode1 = "clamp_to_border"
mipmap_input1 = "false"
alias1 = "CRTPass"
float_framebuffer1 = "false"
srgb_framebuffer1 = "true"
scale_type_x1 = "viewport"
scale_x1 = "1.000000"
scale_type_y1 = "viewport"
scale_y1 = "1.000000"
shader2 = "shaders/glow/threshold.slang"
filter_linear2 = "true"
wrap_mode2 = "clamp_to_border"
mipmap_input2 = "false"
alias2 = ""
float_framebuffer2 = "false"
srgb_framebuffer2 = "true"
shader3 = "shaders/glow/blur_horiz.slang"
filter_linear3 = "true"
wrap_mode3 = "clamp_to_border"
mipmap_input3 = "true"
alias3 = ""
float_framebuffer3 = "false"
srgb_framebuffer3 = "true"
scale_type_x3 = "viewport"
scale_x3 = "0.200000"
scale_type_y3 = "viewport"
scale_y3 = "0.200000"
shader4 = "shaders/glow/blur_vert.slang"
filter_linear4 = "true"
wrap_mode4 = "clamp_to_border"
mipmap_input4 = "false"
alias4 = ""
float_framebuffer4 = "false"
srgb_framebuffer4 = "true"
shader5 = "shaders/glow/resolve.slang"
filter_linear5 = "true"
wrap_mode5 = "clamp_to_border"
mipmap_input5 = "false"
alias5 = ""
float_framebuffer5 = "false"
srgb_framebuffer5 = "false"
scale_type5 = viewport
parameters = "INPUT_GAMMA;BEAM_PROFILE;BEAM_MIN_WIDTH;BEAM_MAX_WIDTH;SCANLINES_STRENGTH;COLOR_BOOST;HFILTER_SHARPNESS;PHOSPHOR_LAYOUT;MASK_INTENSITY;CRT_ANTI_RINGING;InputGamma;OutputGamma;VSCANLINES;GLOW_WHITEPOINT;GLOW_ROLLOFF;BLOOM_STRENGTH;OUTPUT_GAMMA;CURVATURE;warpX;warpY;cornersize;cornersmooth;noise_amt;shadowMask;maskDark;maskLight"
INPUT_GAMMA = "2.400000"
BEAM_PROFILE = "0'.000000"
BEAM_MIN_WIDTH = "0.920000"
BEAM_MAX_WIDTH = "1.000000"
SCANLINES_STRENGTH = "0.720000"
COLOR_BOOST = "1.250000"
PHOSPHOR_LAYOUT = "4.000000"
MASK_INTENSITY = "0.700000"
CRT_ANTI_RINGING = "0.000000"
InputGamma = "1.000000"
OutputGamma = "1.000000"
VSCANLINES = "0.000000"
GLOW_WHITEPOINT = "0.900000"
GLOW_ROLLOFF = "3.000000"
BLOOM_STRENGTH = "0.100000"
OUTPUT_GAMMA = "2.200000"
CURVATURE = "0.000000"
warpX = "0.015000"
warpY = "0.015000"
cornersize = "0.010000"
cornersmooth = "380.000000"
noise_amt = "0.250000"
shadowMask = "0.000000"
maskDark = "0.500000"
maskLight = "1.500000"

View file

@ -1,5 +0,0 @@
shaders = 1
shader0 = shaders/hyllian/crt-hyllian-sinc.slang
filter_linear0 = false
scale_type0 = viewport

View file

@ -1,5 +1,40 @@
shaders = 1
shader0 = shaders/hyllian/crt-hyllian.slang
filter_linear0 = false
scale_type0 = viewport
shaders = "3"
feedback_pass = "0"
shader0 = "shaders/hyllian/support/multiLUT-modified.slang"
wrap_mode0 = "clamp_to_border"
mipmap_input0 = "false"
alias0 = ""
float_framebuffer0 = "false"
srgb_framebuffer0 = "false"
scale_type_x0 = "source"
scale_x0 = "1.000000"
scale_type_y0 = "source"
scale_y0 = "1.000000"
shader1 = "shaders/hyllian/crt-hyllian-pass0.slang"
filter_linear1 = "false"
wrap_mode1 = "clamp_to_border"
mipmap_input1 = "false"
alias1 = ""
float_framebuffer1 = "false"
srgb_framebuffer1 = "true"
scale_type_x1 = "viewport"
scale_x1 = "1.000000"
scale_type_y1 = "source"
scale_y1 = "1.000000"
shader2 = "shaders/hyllian/crt-hyllian-pass1.slang"
filter_linear2 = "false"
wrap_mode2 = "clamp_to_edge"
mipmap_input2 = "false"
alias2 = ""
float_framebuffer2 = "false"
srgb_framebuffer2 = "false"
scale_type_x2 = "source"
scale_x2 = "1.000000"
scale_type_y2 = "viewport"
scale_y2 = "1.000000"
LUT_selector_param = "2.000000"
textures = "SamplerLUT1;SamplerLUT2"
SamplerLUT1 = "shaders/guest/advanced/lut/ntsc-lut.png"
SamplerLUT1_linear = true
SamplerLUT2 = "shaders/hyllian/support/LUT/some-grade.png"
SamplerLUT2_linear = true

View file

@ -1,252 +0,0 @@
#version 450
layout(push_constant) uniform Push
{
float BEAM_PROFILE;
float HFILTER_PROFILE;
float BEAM_MIN_WIDTH;
float BEAM_MAX_WIDTH;
float SCANLINES_STRENGTH;
float COLOR_BOOST;
float SHARPNESS_HACK;
float PHOSPHOR_LAYOUT;
float MASK_INTENSITY;
float CRT_ANTI_RINGING;
float InputGamma;
float OutputGamma;
float VSCANLINES;
float CRT_CURVATURE;
float CRT_warpX;
float CRT_warpY;
float CRT_cornersize;
float CRT_cornersmooth;
} param;
#pragma parameter CRT_HYLLIAN "[CRT-HYLLIAN PARAMS]" 0.0 0.0 0.0 0.0
#pragma parameter BEAM_PROFILE " BEAM PROFILE (BP)" 0.0 0.0 2.0 1.0
#pragma parameter HFILTER_PROFILE " HORIZONTAL FILTER PROFILE [ HERMITE | CATMULL-ROM ]" 1.0 0.0 1.0 1.0
#pragma parameter BEAM_MIN_WIDTH " Custom [If BP=0.00] MIN BEAM WIDTH" 0.92 0.0 1.0 0.01
#pragma parameter BEAM_MAX_WIDTH " Custom [If BP=0.00] MAX BEAM WIDTH" 1.0 0.0 1.0 0.01
#pragma parameter SCANLINES_STRENGTH " Custom [If BP=0.00] SCANLINES STRENGTH" 0.58 0.0 1.0 0.01
#pragma parameter COLOR_BOOST " Custom [If BP=0.00] COLOR BOOST" 1.60 1.0 2.0 0.05
#pragma parameter SHARPNESS_HACK " SHARPNESS_HACK" 1.0 1.0 4.0 1.0
#pragma parameter PHOSPHOR_LAYOUT " PHOSPHOR LAYOUT" 4.0 0.0 24.0 1.0
#pragma parameter MASK_INTENSITY " MASK INTENSITY" 0.7 0.0 1.0 0.1
#pragma parameter CRT_ANTI_RINGING " ANTI RINGING" 1.0 0.0 1.0 0.2
#pragma parameter InputGamma " INPUT GAMMA" 2.4 0.0 5.0 0.1
#pragma parameter OutputGamma " OUTPUT GAMMA" 2.2 0.0 5.0 0.1
#pragma parameter VSCANLINES " VERTICAL SCANLINES [ OFF | ON ]" 0.0 0.0 1.0 1.0
#pragma parameter CRT_CURVATURE "CRT-Curvature" 1.0 0.0 1.0 1.0
#pragma parameter CRT_warpX "CRT-Curvature X-Axis" 0.015 0.0 0.125 0.005
#pragma parameter CRT_warpY "CRT-Curvature Y-Axis" 0.015 0.0 0.125 0.005
vec2 CRT_Distortion = vec2(param.CRT_warpX, param.CRT_warpY) * 15.;
#pragma parameter CRT_cornersize "CRT-Corner Size" 0.01 0.001 1.0 0.005
#define cornersize param.CRT_cornersize
#pragma parameter CRT_cornersmooth "CRT-Corner Smoothness" 380.0 80.0 2080.0 100.0
#define cornersmooth param.CRT_cornersmooth
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
vec4 OutputSize;
vec4 OriginalSize;
vec4 SourceSize;
} global;
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord * 1.0001;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 1) in vec2 FragCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
/*
Hyllian's CRT Shader
Copyright (C) 2011-2022 Hyllian - sergiogdb@gmail.com
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.
*/
#include "../../../include/subpixel_masks.h"
#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))
const vec2 corner_aspect = vec2(1.0, 0.75);
float corner(vec2 coord)
{
coord = (coord - vec2(0.5)) + vec2(0.5, 0.5);
coord = min(coord, vec2(1.0) - coord) * corner_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);
}
vec2 Warp(vec2 texCoord){
vec2 curvedCoords = texCoord * 2.0 - 1.0;
float curvedCoordsDistance = sqrt(curvedCoords.x*curvedCoords.x+curvedCoords.y*curvedCoords.y);
curvedCoords = curvedCoords / curvedCoordsDistance;
curvedCoords = curvedCoords * (1.0-pow(vec2(1.0-(curvedCoordsDistance/1.4142135623730950488016887242097)),(1.0/(1.0+CRT_Distortion*0.2))));
curvedCoords = curvedCoords / (1.0-pow(vec2(0.29289321881345247559915563789515),(1.0/(vec2(1.0)+CRT_Distortion*0.2))));
curvedCoords = curvedCoords * 0.5 + 0.5;
return curvedCoords;
}
// Horizontal cubic filter.
// Some known filters use these values:
// B = 0.0, C = 0.0 => Hermite cubic filter.
// B = 1.0, C = 0.0 => Cubic B-Spline filter.
// B = 0.0, C = 0.5 => Catmull-Rom Spline filter. This is the default used in this shader.
// B = C = 1.0/3.0 => Mitchell-Netravali cubic filter.
// B = 0.3782, C = 0.3109 => Robidoux filter.
// B = 0.2620, C = 0.3690 => Robidoux Sharp filter.
// Using only Hermite and Catmull-Rom, as the others aren't useful for crt shader.
// For more info, see: http://www.imagemagick.org/Usage/img_diagrams/cubic_survey.gif
mat4x4 get_hfilter_profile()
{
float bf = 0.0;
float cf = 0.0;
if (param.HFILTER_PROFILE == 1) {bf = 0.0; cf = 0.5;}
return mat4x4( (-bf - 6.0*cf)/6.0, (3.0*bf + 12.0*cf)/6.0, (-3.0*bf - 6.0*cf)/6.0, bf/6.0,
(12.0 - 9.0*bf - 6.0*cf)/6.0, (-18.0 + 12.0*bf + 6.0*cf)/6.0, 0.0, (6.0 - 2.0*bf)/6.0,
-(12.0 - 9.0*bf - 6.0*cf)/6.0, (18.0 - 15.0*bf - 12.0*cf)/6.0, (3.0*bf + 6.0*cf)/6.0, bf/6.0,
(bf + 6.0*cf)/6.0, -cf, 0.0, 0.0);
}
#define scanlines_strength (4.0*profile.x)
#define beam_min_width profile.y
#define beam_max_width profile.z
#define color_boost profile.w
vec4 get_beam_profile()
{
vec4 bp = vec4(param.SCANLINES_STRENGTH, param.BEAM_MIN_WIDTH, param.BEAM_MAX_WIDTH, param.COLOR_BOOST);
if (param.BEAM_PROFILE == 1) bp = vec4(0.62, 1.00, 1.00, 1.40); // Catmull-rom
if (param.BEAM_PROFILE == 2) bp = vec4(0.72, 1.00, 1.00, 1.20); // Catmull-rom
return bp;
}
void main()
{
vec4 profile = get_beam_profile();
vec2 TextureSize = mix(vec2(global.SourceSize.x * param.SHARPNESS_HACK, global.SourceSize.y), vec2(global.SourceSize.x, global.SourceSize.y * param.SHARPNESS_HACK), param.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 pp = vTexCoord.xy;
pp = (param.CRT_CURVATURE > 0.5) ? Warp(pp) : pp;
vec2 pix_coord = pp.xy*TextureSize + vec2(-0.5, 0.5);
vec2 tc = mix((floor(pix_coord) + vec2(0.5, 0.5))/TextureSize, (floor(pix_coord) + vec2(1.5, -0.5))/TextureSize, param.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);
vec3 c02 = GAMMA_IN(texture(Source, tc + dx - dy).xyz);
vec3 c03 = GAMMA_IN(texture(Source, tc + 2.0*dx - dy).xyz);
vec3 c10 = GAMMA_IN(texture(Source, tc - dx ).xyz);
vec3 c11 = GAMMA_IN(texture(Source, tc ).xyz);
vec3 c12 = GAMMA_IN(texture(Source, tc + dx ).xyz);
vec3 c13 = GAMMA_IN(texture(Source, tc + 2.0*dx ).xyz);
mat4x4 invX = get_hfilter_profile();
mat4x3 color_matrix0 = mat4x3(c00, c01, c02, c03);
mat4x3 color_matrix1 = mat4x3(c10, c11, c12, c13);
vec4 invX_Px = vec4(fp.x*fp.x*fp.x, fp.x*fp.x, fp.x, 1.0) * invX;
vec3 color0 = color_matrix0 * invX_Px;
vec3 color1 = color_matrix1 * invX_Px;
// Get min/max samples
vec3 min_sample0 = min(c01,c02);
vec3 max_sample0 = max(c01,c02);
vec3 min_sample1 = min(c11,c12);
vec3 max_sample1 = max(c11,c12);
// Anti-ringing
vec3 aux = color0;
color0 = clamp(color0, min_sample0, max_sample0);
color0 = mix(aux, color0, param.CRT_ANTI_RINGING * step(0.0, (c00-c01)*(c02-c03)));
aux = color1;
color1 = clamp(color1, min_sample1, max_sample1);
color1 = mix(aux, color1, param.CRT_ANTI_RINGING * step(0.0, (c10-c11)*(c12-c13)));
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 d0 = scanlines_strength*pos0/(lum0*lum0+0.0000001);
vec3 d1 = scanlines_strength*pos1/(lum1*lum1+0.0000001);
d0 = exp(-d0*d0);
d1 = exp(-d1*d1);
vec3 color = color_boost*(color0*d0+color1*d1);
vec2 mask_coords =vTexCoord.xy * global.OutputSize.xy;
mask_coords = mix(mask_coords.xy, mask_coords.yx, param.VSCANLINES);
color.rgb*=mask_weights(mask_coords, param.MASK_INTENSITY, int(param.PHOSPHOR_LAYOUT));
color = GAMMA_OUT(color);
FragColor = vec4(color, 1.0);
FragColor *= (param.CRT_CURVATURE > 0.5) ? corner(pp) : 1.0;
}

View file

@ -1,185 +0,0 @@
#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" 0.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.2 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" 2.0 1.0 5.0 1.0
#pragma parameter COLOR_BOOST "CRT - Color Boost" 1.3 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" 1.0 0.0 1.0 0.02
#pragma parameter BEAM_MIN_WIDTH "CRT - Min Beam Width" 0.60 0.0 1.0 0.02
#pragma parameter BEAM_MAX_WIDTH "CRT - Max Beam Width" 0.80 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;
vec4 OutputSize;
vec4 OriginalSize;
vec4 SourceSize;
} global;
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
void main()
{
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(set = 0, binding = 2) uniform sampler2D Source;
/*
Hyllian's CRT Shader
Copyright (C) 2011-2016 Hyllian - sergiogdb@gmail.com
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 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.
// Some known filters use these values:
// B = 0.0, C = 0.0 => Hermite cubic filter.
// B = 1.0, C = 0.0 => Cubic B-Spline filter.
// B = 0.0, C = 0.5 => Catmull-Rom Spline filter. This is the default used in this shader.
// B = C = 1.0/3.0 => Mitchell-Netravali cubic filter.
// B = 0.3782, C = 0.3109 => Robidoux filter.
// B = 0.2620, C = 0.3690 => Robidoux Sharp filter.
// B = 0.36, C = 0.28 => My best config for ringing elimination in pixel art (Hyllian).
// For more info, see: http://www.imagemagick.org/Usage/img_diagrams/cubic_survey.gif
// Change these params to configure the horizontal filter.
float B = 0.0;
float C = 0.5;
mat4x4 invX = mat4x4(
(-B - 6.0*C)/6.0, (3.0*B + 12.0*C)/6.0, (-3.0*B - 6.0*C)/6.0, B/6.0,
(12.0 - 9.0*B - 6.0*C)/6.0, (-18.0 + 12.0*B + 6.0*C)/6.0, 0.0, (6.0 - 2.0*B)/6.0,
-(12.0 - 9.0*B - 6.0*C)/6.0, (18.0 - 15.0*B - 12.0*C)/6.0, (3.0*B + 6.0*C)/6.0, B/6.0,
(B + 6.0*C)/6.0, -C, 0.0, 0.0
);
void main()
{
vec3 color;
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), 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, param.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);
vec3 c02 = GAMMA_IN(texture(Source, tc + dx - dy).xyz);
vec3 c03 = GAMMA_IN(texture(Source, tc + 2.0*dx - dy).xyz);
vec3 c10 = GAMMA_IN(texture(Source, tc - dx ).xyz);
vec3 c11 = GAMMA_IN(texture(Source, tc ).xyz);
vec3 c12 = GAMMA_IN(texture(Source, tc + dx ).xyz);
vec3 c13 = GAMMA_IN(texture(Source, tc + 2.0*dx ).xyz);
// Get min/max samples
vec3 min_sample = min(min(c01, c11), min(c02, c12));
vec3 max_sample = max(max(c01, c11), max(c02, c12));
mat4x3 color_matrix0 = mat4x3(c00, c01, c02, c03);
mat4x3 color_matrix1 = mat4x3(c10, c11, c12, c13);
vec4 invX_Px = vec4(fp.x*fp.x*fp.x, fp.x*fp.x, fp.x, 1.0) * invX;
vec3 color0 = color_matrix0 * invX_Px;
vec3 color1 = color_matrix1 * invX_Px;
// Anti-ringing
vec3 aux = color0;
color0 = clamp(color0, min_sample, max_sample);
color0 = mix(aux, color0, param.CRT_ANTI_RINGING);
aux = color1;
color1 = clamp(color1, min_sample, max_sample);
color1 = mix(aux, color1, param.CRT_ANTI_RINGING);
float pos0 = fp.y;
float pos1 = 1 - fp.y;
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*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 *= param.COLOR_BOOST*vec3(param.RED_BOOST, param.GREEN_BOOST, param.BLUE_BOOST);
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))
);
color.rgb *= mix(vec3(1.0), dotMaskWeights, param.PHOSPHOR);
color = GAMMA_OUT(color);
FragColor = vec4(color, 1.0);
}

View file

@ -1,50 +0,0 @@
#version 450
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
float BLOOM_STRENGTH;
float SOURCE_BOOST;
} params;
#pragma parameter BLOOM_STRENGTH "Bloom Strength" 0.45 0.0 1.0 0.01
#pragma parameter SOURCE_BOOST "Bloom Color Boost" 1.15 1.0 1.3 0.01
#define BLOOM_STRENGTH params.BLOOM_STRENGTH
#define SOURCE_BOOST params.SOURCE_BOOST
#define INV_OUTPUT_GAMMA (1.0 / 2.2)
#define saturate(c) clamp(c, 0.0, 1.0)
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
} global;
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
layout(set = 0, binding = 3) uniform sampler2D CRT_PASS;
void main()
{
vec3 source = SOURCE_BOOST * texture(CRT_PASS, vTexCoord).rgb;
vec3 bloom = texture(Source, vTexCoord).rgb;
source += BLOOM_STRENGTH * bloom;
FragColor = vec4(pow(saturate(source), vec3(INV_OUTPUT_GAMMA,INV_OUTPUT_GAMMA,INV_OUTPUT_GAMMA)), 1.0);
}

View file

@ -1,125 +0,0 @@
#version 450
/*
Hyllian's CRT Shader - pass0
Copyright (C) 2011-2016 Hyllian - sergiogdb@gmail.com
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.
*/
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
float SHARPNESS;
float CRT_ANTI_RINGING;
float InputGamma;
} params;
#pragma parameter SHARPNESS "CRT - Sharpness Hack" 1.0 1.0 5.0 1.0
#pragma parameter CRT_ANTI_RINGING "CRT - Anti-Ringing" 0.8 0.0 1.0 0.1
#pragma parameter InputGamma "CRT - Input gamma" 2.5 0.0 5.0 0.1
#define SHARPNESS params.SHARPNESS
#define CRT_ANTI_RINGING params.CRT_ANTI_RINGING
#define InputGamma params.InputGamma
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
} global;
#define GAMMA_IN(color) pow(color, vec3(InputGamma, InputGamma, InputGamma))
// Horizontal cubic filter.
// Some known filters use these values:
// B = 0.0, C = 0.0 => Hermite cubic filter.
// B = 1.0, C = 0.0 => Cubic B-Spline filter.
// B = 0.0, C = 0.5 => Catmull-Rom Spline filter. This is the default used in this shader.
// B = C = 1.0/3.0 => Mitchell-Netravali cubic filter.
// B = 0.3782, C = 0.3109 => Robidoux filter.
// B = 0.2620, C = 0.3690 => Robidoux Sharp filter.
// B = 0.36, C = 0.28 => My best config for ringing elimination in pixel art (Hyllian).
// For more info, see: http://www.imagemagick.org/Usage/img_diagrams/cubic_survey.gif
// Change these params to configure the horizontal filter.
const float B = 0.0;
const float C = 0.5;
const mat4 invX = mat4( (-B - 6.0*C)/6.0, (12.0 - 9.0*B - 6.0*C)/6.0, -(12.0 - 9.0*B - 6.0*C)/6.0, (B + 6.0*C)/6.0,
(3.0*B + 12.0*C)/6.0, (-18.0 + 12.0*B + 6.0*C)/6.0, (18.0 - 15.0*B - 12.0*C)/6.0, -C,
(-3.0*B - 6.0*C)/6.0, 0.0, (3.0*B + 6.0*C)/6.0, 0.0,
B/6.0, (6.0 - 2.0*B)/6.0, B/6.0, 0.0);
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
void main()
{
vec2 texture_size = vec2(SHARPNESS*params.SourceSize.x, params.SourceSize.y);
vec3 color;
vec2 dx = vec2(1.0/texture_size.x, 0.0);
vec2 dy = vec2(0.0, 1.0/texture_size.y);
vec2 pix_coord = vTexCoord*texture_size+vec2(-0.5,0.0);
vec2 tc = (floor(pix_coord)+vec2(0.5,0.001))/texture_size;
vec2 fp = fract(pix_coord);
vec3 c10 = GAMMA_IN(texture(Source, tc - dx).xyz);
vec3 c11 = GAMMA_IN(texture(Source, tc ).xyz);
vec3 c12 = GAMMA_IN(texture(Source, tc + dx).xyz);
vec3 c13 = GAMMA_IN(texture(Source, tc + 2.0*dx).xyz);
// Get min/max samples
vec3 min_sample = min(c11,c12);
vec3 max_sample = max(c11,c12);
mat4x3 color_matrix = mat4x3(c10, c11, c12, c13);
vec4 lobes = vec4(fp.x*fp.x*fp.x, fp.x*fp.x, fp.x, 1.0);
vec4 invX_Px = invX * lobes;
color = color_matrix * invX_Px;
// Anti-ringing
vec3 aux = color;
color = clamp(color, min_sample, max_sample);
color = mix(aux, color, CRT_ANTI_RINGING);
FragColor = vec4(color, 1.0);
}

View file

@ -1,127 +0,0 @@
#version 450
/*
Hyllian's CRT Shader - pass1
Copyright (C) 2011-2016 Hyllian - sergiogdb@gmail.com
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.
*/
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
float OutputGamma;
float PHOSPHOR;
float COLOR_BOOST;
float RED_BOOST;
float GREEN_BOOST;
float BLUE_BOOST;
float SCANLINES_STRENGTH;
float BEAM_MIN_WIDTH;
float BEAM_MAX_WIDTH;
} params;
#pragma parameter OutputGamma "CRT - Output Gamma" 2.2 0.0 5.0 0.1
#pragma parameter PHOSPHOR "CRT - Phosphor ON/OFF" 1.0 0.0 1.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.72 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
#define OutputGamma params.OutputGamma
#define PHOSPHOR params.PHOSPHOR
#define COLOR_BOOST params.COLOR_BOOST
#define RED_BOOST params.RED_BOOST
#define GREEN_BOOST params.GREEN_BOOST
#define BLUE_BOOST params.BLUE_BOOST
#define SCANLINES_STRENGTH params.SCANLINES_STRENGTH
#define BEAM_MIN_WIDTH params.BEAM_MIN_WIDTH
#define BEAM_MAX_WIDTH params.BEAM_MAX_WIDTH
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
} global;
#define GAMMA_OUT(color) pow(color, vec3(1.0 / OutputGamma, 1.0 / OutputGamma, 1.0 / OutputGamma))
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
void main()
{
vec2 texture_size = params.SourceSize.xy;
vec3 color;
vec2 dx = vec2(1.0/texture_size.x, 0.0);
vec2 dy = vec2(0.0, 1.0/texture_size.y);
vec2 pix_coord = vTexCoord*texture_size+vec2(0.0,0.5);
vec2 tc = (floor(pix_coord)+vec2(0.0,0.5))/texture_size;
vec2 fp = fract(pix_coord);
vec3 color0 = texture(Source, tc - dy).xyz;
vec3 color1 = texture(Source, tc ).xyz;
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 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);
color = clamp(color0*d0+color1*d1, 0.0, 1.0);
color *= COLOR_BOOST*vec3(RED_BOOST, GREEN_BOOST, BLUE_BOOST);
float mod_factor = vTexCoord.x * params.OutputSize.x;
vec3 dotMaskWeights = mix(
vec3(1.0, 0.7, 1.0),
vec3(0.7, 1.0, 0.7),
floor(mod(mod_factor, 2.0))
);
color.rgb *= mix(vec3(1.0, 1.0, 1.0), dotMaskWeights, PHOSPHOR);
color = GAMMA_OUT(color);
FragColor = vec4(color, 1.0);
}

View file

@ -0,0 +1,180 @@
#version 450
/*
Hyllian's CRT Shader
Copyright (C) 2011-2024 Hyllian - sergiogdb@gmail.com
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.
*/
layout(push_constant) uniform Push
{
float HFILTER_PROFILE;
float SHARPNESS_HACK;
float CRT_ANTI_RINGING;
float CRT_InputGamma;
float CURVATURE;
float WARP_X;
float WARP_Y;
} params;
#pragma parameter CRT_HYLLIAN "[CRT-HYLLIAN PARAMS]" 0.0 0.0 0.0 0.0
#pragma parameter HFILTER_PROFILE " HORIZONTAL FILTER PROFILE [ SHARP1 | SHARP2 ]" 1.0 0.0 1.0 1.0
#pragma parameter CRT_ANTI_RINGING " ANTI RINGING" 1.0 0.0 1.0 1.0
#pragma parameter SHARPNESS_HACK " SHARPNESS_HACK" 1.0 1.0 4.0 1.0
#pragma parameter CRT_InputGamma " INPUT GAMMA" 2.4 1.0 5.0 0.1
#pragma parameter CRT_OutputGamma "OUTPUT GAMMA" 2.2 1.0 5.0 0.05
#pragma parameter PHOSPHOR_LAYOUT "PHOSPHOR LAYOUT [1-6 Aperture, 7-10 Shadow, 11-14 Slot]" 1.0 0.0 15.0 1.0
#pragma parameter MASK_INTENSITY "MASK INTENSITY" 0.65 0.0 1.0 0.01
#pragma parameter MONITOR_SUBPIXELS "MONITOR SUBPIXELS LAYOUT [0=RGB, 1=BGR]" 0.0 0.0 1.0 1.0
#pragma parameter BRIGHTBOOST "BRIGHTNESS BOOST" 1.40 1.0 3.0 0.05
#pragma parameter BEAM_MIN_WIDTH "MIN BEAM WIDTH" 0.86 0.0 1.0 0.02
#pragma parameter BEAM_MAX_WIDTH "MAX BEAM WIDTH" 1.0 0.0 1.0 0.02
#pragma parameter SCANLINES_STRENGTH "SCANLINES STRENGTH" 0.72 0.0 1.0 0.01
#pragma parameter SCANLINES_SHAPE "SCANLINES SHAPE (SINC | GAUSSIAN)" 0.0 0.0 1.0 1.0
#pragma parameter POST_BRIGHTNESS "POST-BRIGHTNESS" 1.00 1.0 3.0 0.05
#pragma parameter CURVATURE "ENABLE CURVATURE" 0.0 0.0 1.0 1.0
#pragma parameter WARP_X " CURVATURE-X" 0.015 0.0 0.125 0.005
#pragma parameter WARP_Y " CURVATURE-Y" 0.015 0.0 0.125 0.005
#pragma parameter CORNER_SIZE " CORNER SIZE" 0.02 0.001 1.0 0.005
#pragma parameter CORNER_SMOOTHNESS " CORNER SMOOTHNESS" 1.10 1.0 2.2 0.02
#define HFILTER_PROFILE params.HFILTER_PROFILE
#define CRT_ANTI_RINGING params.CRT_ANTI_RINGING
#define SHARPNESS_HACK params.SHARPNESS_HACK
#define CRT_InputGamma params.CRT_InputGamma
#define CURVATURE params.CURVATURE
#define WARP_X params.WARP_X
#define WARP_Y params.WARP_Y
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
vec4 OutputSize;
vec4 OriginalSize;
vec4 SourceSize;
} global;
#define GAMMA_IN(color) pow(color, vec3(CRT_InputGamma, CRT_InputGamma, CRT_InputGamma))
/* Curvature code. Credits to torridgristle! */
vec2 CRT_Distortion = vec2(WARP_X, 0.0) * 15.;
#define SQRT_OF_2 1.4142135623730950488016887242097
// Radius of Convergence = 1.0 - SQRT_OF_2 / 2
#define CONVERGENCE_RADIUS 0.29289321881345247559915563789515
vec2 Warp(vec2 texCoord)
{
vec2 cCoords = texCoord * 2.0 - 1.0;
float cCoordsDist = sqrt(cCoords.x * cCoords.x + cCoords.y * cCoords.y);
cCoords = cCoords / cCoordsDist;
cCoords = cCoords * (1.0 - pow(vec2(1.0 - (cCoordsDist/SQRT_OF_2)),(1.0/(1.0+CRT_Distortion*0.2))));
cCoords = cCoords / (1.0-pow(vec2(CONVERGENCE_RADIUS),(1.0/(vec2(1.0)+CRT_Distortion*0.2))));
cCoords = cCoords * 0.5 + 0.5;
return cCoords;
}
// Horizontal cubic filter.
// Some known filters use these values:
// B = 0.5, C = 0.0 => A sharp almost gaussian filter.
// B = 0.0, C = 0.0 => Hermite cubic filter.
// B = 1.0, C = 0.0 => Cubic B-Spline filter.
// B = 0.0, C = 0.5 => Catmull-Rom Spline filter.
// B = C = 1.0/3.0 => Mitchell-Netravali cubic filter.
// B = 0.3782, C = 0.3109 => Robidoux filter.
// B = 0.2620, C = 0.3690 => Robidoux Sharp filter.
// For more info, see: http://www.imagemagick.org/Usage/img_diagrams/cubic_survey.gif
mat4 get_hfilter_profile()
{
float bf = 0.0;
float cf = 0.0;
if (HFILTER_PROFILE > 0.5) {bf = 0.0; cf = 0.5;}
return mat4( ( -bf - 6.0*cf)/6.0, (3.0*bf + 12.0*cf)/6.0, (-3.0*bf - 6.0*cf)/6.0, bf/6.0,
(12.0 - 9.0*bf - 6.0*cf)/6.0, (-18.0 + 12.0*bf + 6.0*cf)/6.0, 0.0, (6.0 - 2.0*bf)/6.0,
-(12.0 - 9.0*bf - 6.0*cf)/6.0, (18.0 - 15.0*bf - 12.0*cf)/6.0, (3.0*bf + 6.0*cf)/6.0, bf/6.0,
( bf + 6.0*cf)/6.0, -cf, 0.0, 0.0);
}
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord*1.0001;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 1) in vec2 FragCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
void main()
{
vec2 texture_size = vec2(SHARPNESS_HACK*global.SourceSize.x, global.SourceSize.y);
vec2 dx = vec2(1.0/texture_size.x, 0.0);
vec2 WarpedTexCoord = vTexCoord.xy;
WarpedTexCoord = (CURVATURE > 0.5) ? Warp(WarpedTexCoord) : WarpedTexCoord;
vec2 pix_coord = WarpedTexCoord.xy*texture_size + vec2(-0.5, 0.0);
vec2 tc = (floor(pix_coord) + vec2(0.5,0.5))/texture_size;
vec2 fp = fract(pix_coord);
vec3 c10 = GAMMA_IN(texture(Source, tc - dx).xyz);
vec3 c11 = GAMMA_IN(texture(Source, tc ).xyz);
vec3 c12 = GAMMA_IN(texture(Source, tc + dx).xyz);
vec3 c13 = GAMMA_IN(texture(Source, tc + 2.0*dx).xyz);
mat4x3 color_matrix = mat4x3(c10, c11, c12, c13);
mat4 invX = get_hfilter_profile();
vec4 lobes = vec4(fp.x*fp.x*fp.x, fp.x*fp.x, fp.x, 1.0);
vec4 invX_Px = lobes * invX;
vec3 color = color_matrix * invX_Px;
// Anti-ringing
// Get min/max samples
vec3 min_sample = min(c11,c12);
vec3 max_sample = max(c11,c12);
vec3 aux = color;
color = clamp(color, min_sample, max_sample);
color = mix(aux, color, CRT_ANTI_RINGING);
FragColor = vec4(color, 1.0);
}

View file

@ -0,0 +1,435 @@
#version 450
/*
Hyllian's CRT Shader
Copyright (C) 2011-2024 Hyllian - sergiogdb@gmail.com
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.
*/
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
float CRT_OutputGamma;
float PHOSPHOR_LAYOUT;
float MASK_INTENSITY;
float MONITOR_SUBPIXELS;
float BRIGHTBOOST;
float SCANLINES_SHAPE;
float SCANLINES_STRENGTH;
float BEAM_MIN_WIDTH;
float BEAM_MAX_WIDTH;
float POST_BRIGHTNESS;
float CURVATURE;
float WARP_X;
float WARP_Y;
float CORNER_SIZE;
float CORNER_SMOOTHNESS;
} params;
#pragma parameter CRT_OutputGamma "OUTPUT GAMMA" 2.2 1.0 5.0 0.05
#pragma parameter PHOSPHOR_LAYOUT "PHOSPHOR LAYOUT [1-6 Aperture, 7-10 Shadow, 11-14 Slot]" 1.0 0.0 15.0 1.0
#pragma parameter MASK_INTENSITY "MASK INTENSITY" 0.65 0.0 1.0 0.01
#pragma parameter MONITOR_SUBPIXELS "MONITOR SUBPIXELS LAYOUT [0=RGB, 1=BGR]" 0.0 0.0 1.0 1.0
#pragma parameter BRIGHTBOOST "BRIGHTNESS BOOST" 1.40 1.0 3.0 0.05
#pragma parameter BEAM_MIN_WIDTH "MIN BEAM WIDTH" 0.86 0.0 1.0 0.02
#pragma parameter BEAM_MAX_WIDTH "MAX BEAM WIDTH" 1.0 0.0 1.0 0.02
#pragma parameter SCANLINES_STRENGTH "SCANLINES STRENGTH" 0.72 0.0 1.0 0.01
#pragma parameter SCANLINES_SHAPE "SCANLINES SHAPE (SINC | GAUSSIAN)" 0.0 0.0 1.0 1.0
#pragma parameter POST_BRIGHTNESS "POST-BRIGHTNESS" 1.00 1.0 3.0 0.05
#pragma parameter CURVATURE "ENABLE CURVATURE" 0.0 0.0 1.0 1.0
#pragma parameter WARP_X " CURVATURE-X" 0.015 0.0 0.125 0.005
#pragma parameter WARP_Y " CURVATURE-Y" 0.015 0.0 0.125 0.005
#pragma parameter CORNER_SIZE " CORNER SIZE" 0.02 0.001 1.0 0.005
#pragma parameter CORNER_SMOOTHNESS " CORNER SMOOTHNESS" 1.10 1.0 2.2 0.02
#define CRT_OutputGamma params.CRT_OutputGamma
#define BRIGHTBOOST (params.BRIGHTBOOST+1.1)
#define SCANLINES_SHAPE params.SCANLINES_SHAPE
#define SCANLINES_STRENGTH (-0.16*SCANLINES_SHAPE+params.SCANLINES_STRENGTH)
#define BEAM_MIN_WIDTH params.BEAM_MIN_WIDTH
#define BEAM_MAX_WIDTH params.BEAM_MAX_WIDTH
#define POST_BRIGHTNESS params.POST_BRIGHTNESS
#define CURVATURE params.CURVATURE
#define WARP_X params.WARP_X
#define WARP_Y params.WARP_Y
#define CORNER_SIZE params.CORNER_SIZE
#define CORNER_SMOOTHNESS (80.0*pow(params.CORNER_SMOOTHNESS,10.0))
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
} global;
#define GAMMA_OUT(color) pow(color, vec3(1.0 / CRT_OutputGamma, 1.0 / CRT_OutputGamma, 1.0 / CRT_OutputGamma))
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord*1.0001;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 1) in vec2 FragCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
const vec2 corner_aspect = vec2(1.0, 0.75);
float corner(vec2 coord)
{
coord = (coord - vec2(0.5)) + vec2(0.5, 0.5);
coord = min(coord, vec2(1.0) - coord) * corner_aspect;
vec2 cdist = vec2(CORNER_SIZE);
coord = (cdist - min(coord, cdist));
float dist = sqrt(dot(coord, coord));
return clamp((cdist.x - dist)*CORNER_SMOOTHNESS, 0.0, 1.0);
}
/* Curvature code. Credits to torridgristle! */
vec2 CRT_Distortion = vec2(0.0, WARP_Y) * 15.;
#define SQRT_OF_2 1.4142135623730950488016887242097
// Radius of Convergence = 1.0 - SQRT_OF_2 / 2
#define CONVERGENCE_RADIUS 0.29289321881345247559915563789515
vec2 Warp(vec2 texCoord)
{
vec2 cCoords = texCoord * 2.0 - 1.0;
float cCoordsDist = sqrt(cCoords.x * cCoords.x + cCoords.y * cCoords.y);
cCoords = cCoords / cCoordsDist;
cCoords = cCoords * (1.0 - pow(vec2(1.0 - (cCoordsDist/SQRT_OF_2)),(1.0/(1.0+CRT_Distortion*0.2))));
cCoords = cCoords / (1.0-pow(vec2(CONVERGENCE_RADIUS),(1.0/(vec2(1.0)+CRT_Distortion*0.2))));
cCoords = cCoords * 0.5 + 0.5;
return cCoords;
}
/* Mask code pasted from subpixel_masks.h. Masks 3 and 4 added. */
vec3 mask_weights(vec2 coord, float mask_intensity, int phosphor_layout, float monitor_subpixels){
vec3 weights = vec3(1.,1.,1.);
float on = 1.;
float off = 1.-mask_intensity;
vec3 red = monitor_subpixels==1.0 ? vec3(on, off, off) : vec3(off, off, on );
vec3 green = vec3(off, on, off);
vec3 blue = monitor_subpixels==1.0 ? vec3(off, off, on ) : vec3(on, off, off);
vec3 magenta = vec3(on, off, on );
vec3 yellow = monitor_subpixels==1.0 ? vec3(on, on, off) : vec3(off, on, on );
vec3 cyan = monitor_subpixels==1.0 ? vec3(off, on, on ) : vec3(on, on, off);
vec3 black = vec3(off, off, off);
vec3 white = vec3(on, on, on );
int w, z = 0;
// This pattern is used by a few layouts, so we'll define it here
vec3 aperture_weights = mix(magenta, green, floor(mod(coord.x, 2.0)));
if(phosphor_layout == 0) return weights;
else if(phosphor_layout == 1){
// classic aperture for RGB panels; good for 1080p, too small for 4K+
// aka aperture_1_2_bgr
weights = aperture_weights;
return weights;
}
else if(phosphor_layout == 2){
// Classic RGB layout; good for 1080p and lower
vec3 bw3[3] = vec3[](red, green, blue);
// vec3 bw3[3] = vec3[](black, yellow, blue);
z = int(floor(mod(coord.x, 3.0)));
weights = bw3[z];
return weights;
}
else if(phosphor_layout == 3){
// black and white aperture; good for weird subpixel layouts and low brightness; good for 1080p and lower
vec3 bw3[3] = vec3[](black, white, black);
z = int(floor(mod(coord.x, 3.0)));
weights = bw3[z];
return weights;
}
else if(phosphor_layout == 4){
// reduced TVL aperture for RGB panels. Good for 4k.
// aperture_2_4_rgb
vec3 big_ap_rgb[4] = vec3[](red, yellow, cyan, blue);
w = int(floor(mod(coord.x, 4.0)));
weights = big_ap_rgb[w];
return weights;
}
else if(phosphor_layout == 5){
// black and white aperture; good for weird subpixel layouts and low brightness; good for 4k
vec3 bw4[4] = vec3[](black, black, white, white);
z = int(floor(mod(coord.x, 4.0)));
weights = bw4[z];
return weights;
}
else if(phosphor_layout == 6){
// aperture_1_4_rgb; good for simulating lower
vec3 ap4[4] = vec3[](red, green, blue, black);
z = int(floor(mod(coord.x, 4.0)));
weights = ap4[z];
return weights;
}
else if(phosphor_layout == 7){
// 2x2 shadow mask for RGB panels; good for 1080p, too small for 4K+
// aka delta_1_2x1_bgr
vec3 inverse_aperture = mix(green, magenta, floor(mod(coord.x, 2.0)));
weights = mix(aperture_weights, inverse_aperture, floor(mod(coord.y, 2.0)));
return weights;
}
else if(phosphor_layout == 8){
// delta_2_4x1_rgb
vec3 delta[2][4] = {
{red, yellow, cyan, blue},
{cyan, blue, red, yellow}
};
w = int(floor(mod(coord.y, 2.0)));
z = int(floor(mod(coord.x, 4.0)));
weights = delta[w][z];
return weights;
}
else if(phosphor_layout == 9){
// delta_1_4x1_rgb; dunno why this is called 4x1 when it's obviously 4x2 /shrug
vec3 delta1[2][4] = {
{red, green, blue, black},
{blue, black, red, green}
};
w = int(floor(mod(coord.y, 2.0)));
z = int(floor(mod(coord.x, 4.0)));
weights = delta1[w][z];
return weights;
}
else if(phosphor_layout == 10){
// delta_2_4x2_rgb
vec3 delta[4][4] = {
{red, yellow, cyan, blue},
{red, yellow, cyan, blue},
{cyan, blue, red, yellow},
{cyan, blue, red, yellow}
};
w = int(floor(mod(coord.y, 4.0)));
z = int(floor(mod(coord.x, 4.0)));
weights = delta[w][z];
return weights;
}
else if(phosphor_layout == 11){
// slot mask for RGB panels; looks okay at 1080p, looks better at 4K
vec3 slotmask[4][6] = {
{red, green, blue, red, green, blue,},
{red, green, blue, black, black, black},
{red, green, blue, red, green, blue,},
{black, black, black, red, green, blue,}
};
w = int(floor(mod(coord.y, 4.0)));
z = int(floor(mod(coord.x, 6.0)));
// use the indexes to find which color to apply to the current pixel
weights = slotmask[w][z];
return weights;
}
else if(phosphor_layout == 12){
// slot mask for RGB panels; looks okay at 1080p, looks better at 4K
vec3 slotmask[4][6] = {
{black, white, black, black, white, black,},
{black, white, black, black, black, black},
{black, white, black, black, white, black,},
{black, black, black, black, white, black,}
};
w = int(floor(mod(coord.y, 4.0)));
z = int(floor(mod(coord.x, 6.0)));
// use the indexes to find which color to apply to the current pixel
weights = slotmask[w][z];
return weights;
}
else if(phosphor_layout == 13){
// based on MajorPainInTheCactus' HDR slot mask
vec3 slot[4][8] = {
{red, green, blue, black, red, green, blue, black},
{red, green, blue, black, black, black, black, black},
{red, green, blue, black, red, green, blue, black},
{black, black, black, black, red, green, blue, black}
};
w = int(floor(mod(coord.y, 4.0)));
z = int(floor(mod(coord.x, 8.0)));
weights = slot[w][z];
return weights;
}
else if(phosphor_layout == 14){
// same as above but for RGB panels
vec3 slot2[4][10] = {
{red, yellow, green, blue, blue, red, yellow, green, blue, blue },
{black, green, green, blue, blue, red, red, black, black, black},
{red, yellow, green, blue, blue, red, yellow, green, blue, blue },
{red, red, black, black, black, black, green, green, blue, blue }
};
w = int(floor(mod(coord.y, 4.0)));
z = int(floor(mod(coord.x, 10.0)));
weights = slot2[w][z];
return weights;
}
else if(phosphor_layout == 15){
// slot_3_7x6_rgb
vec3 slot[6][14] = {
{red, red, yellow, green, cyan, blue, blue, red, red, yellow, green, cyan, blue, blue},
{red, red, yellow, green, cyan, blue, blue, red, red, yellow, green, cyan, blue, blue},
{red, red, yellow, green, cyan, blue, blue, black, black, black, black, black, black, black},
{red, red, yellow, green, cyan, blue, blue, red, red, yellow, green, cyan, blue, blue},
{red, red, yellow, green, cyan, blue, blue, red, red, yellow, green, cyan, blue, blue},
{black, black, black, black, black, black, black, black, red, red, yellow, green, cyan, blue}
};
w = int(floor(mod(coord.y, 6.0)));
z = int(floor(mod(coord.x, 14.0)));
weights = slot[w][z];
return weights;
}
else return weights;
}
#define pi 3.1415926535897932384626433832795
#define wa (0.5*pi)
#define wb (pi)
vec3 resampler3(vec3 x)
{
vec3 res;
res.x = (x.x<=0.001) ? 1.0 : sin(x.x*wa)*sin(x.x*wb)/(wa*wb*x.x*x.x);
res.y = (x.y<=0.001) ? 1.0 : sin(x.y*wa)*sin(x.y*wb)/(wa*wb*x.y*x.y);
res.z = (x.z<=0.001) ? 1.0 : sin(x.z*wa)*sin(x.z*wb)/(wa*wb*x.z*x.z);
return res;
}
vec3 get_scanlines(vec3 d0, vec3 d1, vec3 color0, vec3 color1)
{
if (SCANLINES_SHAPE > 0.5) {
d0 = exp(-16.0*d0*d0);
d1 = exp(-16.0*d1*d1);
}
else {
d0 = clamp(2.0*d0, 0.0, 1.0);
d1 = clamp(2.0*d1, 0.0, 1.0);
d0 = resampler3(d0);
d1 = resampler3(d1);
}
return (color0*d0+color1*d1);
}
void main()
{
vec2 texture_size = params.SourceSize.xy;
vec3 color;
vec2 dy = vec2(0.0, 1.0/texture_size.y);
vec2 WarpedTexCoord = vTexCoord.xy;
WarpedTexCoord = (CURVATURE > 0.5) ? Warp(WarpedTexCoord) : WarpedTexCoord;
vec2 pix_coord = WarpedTexCoord.xy*texture_size + vec2(0.0, -0.5);
vec2 tc = (floor(pix_coord)+vec2(0.5,0.5))/texture_size;
vec2 fp = fract(pix_coord);
vec3 color0 = texture(Source, tc ).xyz;
vec3 color1 = texture(Source, tc + dy).xyz;
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 d0 = SCANLINES_STRENGTH*pos0/(lum0*lum0+0.0000001);
vec3 d1 = SCANLINES_STRENGTH*pos1/(lum1*lum1+0.0000001);
color = BRIGHTBOOST*get_scanlines(d0, d1, color0, color1);
color = GAMMA_OUT(color);
vec2 mask_coords =vTexCoord.xy * params.OutputSize.xy;
color.rgb*=GAMMA_OUT(mask_weights(mask_coords, params.MASK_INTENSITY, int(params.PHOSPHOR_LAYOUT), params.MONITOR_SUBPIXELS));
FragColor = vec4(POST_BRIGHTNESS*color, 1.0);
FragColor *= (CURVATURE > 0.5) ? corner(WarpedTexCoord) : 1.0;
}

View file

@ -1,260 +0,0 @@
#version 450
layout(push_constant) uniform Push
{
float BEAM_MIN_WIDTH;
float BEAM_MAX_WIDTH;
float SCANLINES_STRENGTH;
float COLOR_BOOST;
float SHARPNESS_HACK;
float PHOSPHOR_LAYOUT;
float MASK_INTENSITY;
float InputGamma;
float OutputGamma;
float VSCANLINES;
float CRT_ANTI_RINGING;
float CRT_CURVATURE;
float CRT_warpX;
float CRT_warpY;
float CRT_cornersize;
float CRT_cornersmooth;
} param;
#pragma parameter CRT_HYLLIAN_SINC "[CRT-HYLLIAN-SINC PARAMS]" 0.0 0.0 0.0 0.0
#pragma parameter BEAM_MIN_WIDTH " MIN BEAM WIDTH" 0.92 0.0 1.0 0.01
#pragma parameter BEAM_MAX_WIDTH " MAX BEAM WIDTH" 1.0 0.0 1.0 0.01
#pragma parameter SCANLINES_STRENGTH " SCANLINES STRENGTH" 0.72 0.0 1.0 0.01
#pragma parameter COLOR_BOOST " COLOR BOOST" 1.60 1.0 2.0 0.05
#pragma parameter SHARPNESS_HACK " SHARPNESS_HACK" 1.0 1.0 4.0 1.0
#pragma parameter PHOSPHOR_LAYOUT " PHOSPHOR LAYOUT" 4.0 0.0 24.0 1.0
#pragma parameter MASK_INTENSITY " MASK INTENSITY" 0.7 0.0 1.0 0.1
#pragma parameter InputGamma " INPUT GAMMA" 2.4 0.0 5.0 0.1
#pragma parameter OutputGamma " OUTPUT GAMMA" 2.2 0.0 5.0 0.1
#pragma parameter VSCANLINES " SCANLINES DIRECTION" 0.0 0.0 1.0 1.0
#pragma parameter CRT_CURVATURE "CRT-Curvature" 1.0 0.0 1.0 1.0
#pragma parameter CRT_warpX "CRT-Curvature X-Axis" 0.015 0.0 0.125 0.005
#pragma parameter CRT_warpY "CRT-Curvature Y-Axis" 0.015 0.0 0.125 0.005
vec2 CRT_Distortion = vec2(param.CRT_warpX, param.CRT_warpY) * 15.;
#pragma parameter CRT_cornersize "CRT-Corner Size" 0.01 0.001 1.0 0.005
#define cornersize param.CRT_cornersize
#pragma parameter CRT_cornersmooth "CRT-Corner Smoothness" 380.0 80.0 2080.0 100.0
#define cornersmooth param.CRT_cornersmooth
#pragma parameter CRT_ANTI_RINGING "CRT Anti-Ringing [ OFF | ON ]" 1.0 0.0 1.0 1.0
#define CRT_ANTI_RINGING param.CRT_ANTI_RINGING
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
vec4 OutputSize;
vec4 OriginalSize;
vec4 SourceSize;
} global;
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
void main()
{
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(set = 0, binding = 2) uniform sampler2D Source;
/*
Hyllian's CRT Shader - Sinc/Spline16 version
Copyright (C) 2011-2022 Hyllian - sergiogdb@gmail.com
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.
*/
#include "../../../include/subpixel_masks.h"
#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))
#define scanlines_strength (2.0*param.SCANLINES_STRENGTH)
#define beam_min_width param.BEAM_MIN_WIDTH
#define beam_max_width param.BEAM_MAX_WIDTH
#define color_boost param.COLOR_BOOST
#define pi 3.1415926535897932384626433832795
#define wa (0.5*pi)
#define wb (pi)
const vec2 corner_aspect = vec2(1.0, 0.75);
float corner(vec2 coord)
{
coord = (coord - vec2(0.5)) + vec2(0.5, 0.5);
coord = min(coord, vec2(1.0) - coord) * corner_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);
}
vec2 Warp(vec2 texCoord){
vec2 curvedCoords = texCoord * 2.0 - 1.0;
float curvedCoordsDistance = sqrt(curvedCoords.x*curvedCoords.x+curvedCoords.y*curvedCoords.y);
curvedCoords = curvedCoords / curvedCoordsDistance;
curvedCoords = curvedCoords * (1.0-pow(vec2(1.0-(curvedCoordsDistance/1.4142135623730950488016887242097)),(1.0/(1.0+CRT_Distortion*0.2))));
curvedCoords = curvedCoords / (1.0-pow(vec2(0.29289321881345247559915563789515),(1.0/(vec2(1.0)+CRT_Distortion*0.2))));
curvedCoords = curvedCoords * 0.5 + 0.5;
return curvedCoords;
}
float weight(float x)
{
x = abs(x);
if (x < 1.0)
{
return
(
((x - 9.0 / 5.0) * x - 1.0 / 5.0 ) * x + 1.0
);
}
else if ((x >= 1.0) && (x < 2.0))
{
return
(
(( -1.0 / 3.0 * (x - 1) + 4.0 / 5.0 ) * (x - 1) - 7.0 / 15.0 ) * (x - 1)
);
}
else
{
return 0.0;
}
}
vec4 weight4(float x)
{
return vec4(
weight(x - 2.0),
weight(x - 1.0),
weight(x),
weight(x + 1.0)
);
}
vec3 resampler3(vec3 x)
{
vec3 res;
res.x = (x.x<=0.001) ? wa*wb : sin(x.x*wa)*sin(x.x*wb)/(x.x*x.x);
res.y = (x.y<=0.001) ? wa*wb : sin(x.y*wa)*sin(x.y*wb)/(x.y*x.y);
res.z = (x.z<=0.001) ? wa*wb : sin(x.z*wa)*sin(x.z*wb)/(x.z*x.z);
return res;
}
void main()
{
vec2 TextureSize = mix(vec2(global.SourceSize.x * param.SHARPNESS_HACK, global.SourceSize.y), vec2(global.SourceSize.x, global.SourceSize.y * param.SHARPNESS_HACK), param.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 pp = vTexCoord.xy;
pp = (param.CRT_CURVATURE > 0.5) ? Warp(pp) : pp;
vec2 pix_coord = pp.xy*TextureSize + vec2(-0.5, 0.5);
vec2 tc = mix((floor(pix_coord) + vec2(0.5, 0.5))/TextureSize, (floor(pix_coord) + vec2(1.5, -0.5))/TextureSize, param.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);
vec3 c02 = GAMMA_IN(texture(Source, tc + dx - dy).xyz);
vec3 c03 = GAMMA_IN(texture(Source, tc + 2.0*dx - dy).xyz);
vec3 c10 = GAMMA_IN(texture(Source, tc - dx ).xyz);
vec3 c11 = GAMMA_IN(texture(Source, tc ).xyz);
vec3 c12 = GAMMA_IN(texture(Source, tc + dx ).xyz);
vec3 c13 = GAMMA_IN(texture(Source, tc + 2.0*dx ).xyz);
mat4x3 color_matrix0 = mat4x3(c00, c01, c02, c03);
mat4x3 color_matrix1 = mat4x3(c10, c11, c12, c13);
// Get weights for spline16 horizontal filter
vec4 weights = weight4(1.0 - fp.x);
// Spline16 horizontal filter
vec3 color0 = (color_matrix0 * weights)/dot(weights, vec4(1.0));
vec3 color1 = (color_matrix1 * weights)/dot(weights, vec4(1.0));
// Get min/max samples
vec3 min_sample0 = min(c01,c02);
vec3 max_sample0 = max(c01,c02);
vec3 min_sample1 = min(c11,c12);
vec3 max_sample1 = max(c11,c12);
// Anti-ringing
vec3 aux = color0;
color0 = clamp(color0, min_sample0, max_sample0);
color0 = mix(aux, color0, CRT_ANTI_RINGING * step(0.0, (c00-c01)*(c02-c03)));
aux = color1;
color1 = clamp(color1, min_sample1, max_sample1);
color1 = mix(aux, color1, CRT_ANTI_RINGING * step(0.0, (c10-c11)*(c12-c13)));
// Apply scanlines. Sinc filter vertically.
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 d0 = clamp(scanlines_strength*pos0/(lum0*lum0+0.0000001), 0.0, 1.0);
vec3 d1 = clamp(scanlines_strength*pos1/(lum1*lum1+0.0000001), 0.0, 1.0);
d0 = resampler3(d0);
d1 = resampler3(d1);
// Apply color enhancement, scanlines orientation, mask and gamma.
vec3 color = color_boost*(color0*d0+color1*d1)/(wa*wb);
vec2 mask_coords = vTexCoord.xy * global.OutputSize.xy;
mask_coords = mix(mask_coords.xy, mask_coords.yx, param.VSCANLINES);
color.rgb*=mask_weights(mask_coords, param.MASK_INTENSITY, int(param.PHOSPHOR_LAYOUT));
color = GAMMA_OUT(color);
FragColor = vec4(color, 1.0);
FragColor *= (param.CRT_CURVATURE > 0.5) ? corner(pp) : 1.0;
}

View file

@ -0,0 +1,208 @@
#version 450
/*
Hyllian's CRT-sinc Shader
Copyright (C) 2011-2024 Hyllian - sergiogdb@gmail.com
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.
*/
layout(push_constant) uniform Push
{
float HFILTER_PROFILE;
float SHARPNESS_HACK;
float SHP;
float RADIUS;
float CRT_ANTI_RINGING;
float CRT_InputGamma;
float CURVATURE;
float WARP_X;
float WARP_Y;
} params;
#pragma parameter HFILTER_PROFILE "H-FILTER [ Custom | Composite1 | Composite2 ]" 0.0 0.0 2.0 1.0
#pragma parameter SHP " CUSTOM H-FILTER SHARPNESS" 1.0 0.50 1.0 0.01
#pragma parameter RADIUS " CUSTOM H-FILTER RADIUS" 4.0 2.0 4.0 0.1
#pragma parameter CRT_ANTI_RINGING "ANTI RINGING" 1.0 0.0 1.0 0.1
#pragma parameter SHARPNESS_HACK "SHARPNESS HACK" 1.0 1.0 4.0 1.0
#pragma parameter CRT_InputGamma "INPUT GAMMA" 2.4 1.0 5.0 0.1
#pragma parameter CRT_OutputGamma "OUTPUT GAMMA" 2.2 1.0 5.0 0.05
#pragma parameter PHOSPHOR_LAYOUT "PHOSPHOR LAYOUT [1-6 Aperture, 7-10 Shadow, 11-14 Slot]" 1.0 0.0 15.0 1.0
#pragma parameter MASK_INTENSITY "MASK INTENSITY" 0.65 0.0 1.0 0.01
#pragma parameter MONITOR_SUBPIXELS "MONITOR SUBPIXELS LAYOUT [0=RGB, 1=BGR]" 0.0 0.0 1.0 1.0
#pragma parameter BRIGHTBOOST "BRIGHTNESS BOOST" 1.40 1.0 3.0 0.05
#pragma parameter BEAM_MIN_WIDTH "MIN BEAM WIDTH" 0.86 0.0 1.0 0.02
#pragma parameter BEAM_MAX_WIDTH "MAX BEAM WIDTH" 1.0 0.0 1.0 0.02
#pragma parameter SCANLINES_STRENGTH "SCANLINES STRENGTH" 0.72 0.0 1.0 0.01
#pragma parameter SCANLINES_SHAPE "SCANLINES SHAPE (SINC | GAUSSIAN)" 0.0 0.0 1.0 1.0
#pragma parameter POST_BRIGHTNESS "POST-BRIGHTNESS" 1.00 1.0 3.0 0.05
#pragma parameter CURVATURE "ENABLE CURVATURE" 0.0 0.0 1.0 1.0
#pragma parameter WARP_X " CURVATURE-X" 0.015 0.0 0.125 0.005
#pragma parameter WARP_Y " CURVATURE-Y" 0.015 0.0 0.125 0.005
#pragma parameter CORNER_SIZE " CORNER SIZE" 0.02 0.001 1.0 0.005
#pragma parameter CORNER_SMOOTHNESS " CORNER SMOOTHNESS" 1.10 1.0 2.2 0.02
#define HFILTER_PROFILE params.HFILTER_PROFILE
#define SHP params.SHP
#define RADIUS params.RADIUS
#define CRT_ANTI_RINGING params.CRT_ANTI_RINGING
#define SHARPNESS_HACK params.SHARPNESS_HACK
#define CRT_InputGamma params.CRT_InputGamma
#define CURVATURE params.CURVATURE
#define WARP_X params.WARP_X
#define WARP_Y params.WARP_Y
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
vec4 OutputSize;
vec4 OriginalSize;
vec4 SourceSize;
} global;
#define GAMMA_IN(color) pow(color, vec3(CRT_InputGamma, CRT_InputGamma, CRT_InputGamma))
#define pi 3.1415926535897932384626433832795
#define AR_MOD 3.0
/* Curvature code. Credits to torridgristle! */
vec2 CRT_Distortion = vec2(WARP_X, 0.0) * 15.;
#define SQRT_OF_2 1.4142135623730950488016887242097
// Radius of Convergence = 1.0 - SQRT_OF_2 / 2
#define CONVERGENCE_RADIUS 0.29289321881345247559915563789515
vec2 Warp(vec2 texCoord)
{
vec2 cCoords = texCoord * 2.0 - 1.0;
float cCoordsDist = sqrt(cCoords.x * cCoords.x + cCoords.y * cCoords.y);
cCoords = cCoords / cCoordsDist;
cCoords = cCoords * (1.0 - pow(vec2(1.0 - (cCoordsDist/SQRT_OF_2)),(1.0/(1.0+CRT_Distortion*0.2))));
cCoords = cCoords / (1.0-pow(vec2(CONVERGENCE_RADIUS),(1.0/(vec2(1.0)+CRT_Distortion*0.2))));
cCoords = cCoords * 0.5 + 0.5;
return cCoords;
}
vec2 get_hfilter_profile()
{
vec2 hf_profile = vec2(SHP, RADIUS);
if (HFILTER_PROFILE == 1.0) hf_profile = vec2(0.86, 4.0);
else if (HFILTER_PROFILE == 2.0) hf_profile = vec2(0.75, 4.0);
return hf_profile;
}
/* Some window functions for tests. */
vec4 sinc(vec4 x) { return sin(pi*x)/(pi*x+0.00001); }
vec4 hann_window(vec4 x) { return 0.5 * ( 1.0 - cos( 0.5 * pi * ( x + 2.0 ) ) ); }
vec4 blackman_window(vec4 x) { return 0.42 - 0.5*cos(0.5*pi*(x+2.0)) + 0.08*cos(pi*(x+2.0)); }
vec4 lanczos(vec4 x, float a) { return sinc(x) * sinc(x / a); }
vec4 blackman(vec4 x, float a) { return sinc(x) * blackman_window(x); }
vec4 hann(vec4 x, float a) { return sinc(x) * hann_window(x); }
vec4 resampler4(vec4 x, vec2 hfp)
{
return lanczos(x * hfp.x, hfp.y);
}
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord * 1.0001;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 1) in vec2 FragCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
void main()
{
vec3 color;
vec2 texture_size = vec2(SHARPNESS_HACK*global.SourceSize.x, global.SourceSize.y);
vec2 dx = vec2(1.0/texture_size.x, 0.0);
vec2 WarpedTexCoord = vTexCoord.xy;
WarpedTexCoord = (CURVATURE > 0.5) ? Warp(WarpedTexCoord) : WarpedTexCoord;
vec2 pix_coord = WarpedTexCoord.xy*texture_size + vec2(-0.5, 0.0);
vec2 tc = (floor(pix_coord) + vec2(0.5,0.5))/texture_size;
vec2 fp = fract(pix_coord);
vec3 c0 = GAMMA_IN(texture(Source, tc - 3.0*dx).xyz);
vec3 c1 = GAMMA_IN(texture(Source, tc - 2.0*dx).xyz);
vec3 c2 = GAMMA_IN(texture(Source, tc - dx).xyz);
vec3 c3 = GAMMA_IN(texture(Source, tc ).xyz);
vec3 c4 = GAMMA_IN(texture(Source, tc + dx).xyz);
vec3 c5 = GAMMA_IN(texture(Source, tc + 2.0*dx).xyz);
vec3 c6 = GAMMA_IN(texture(Source, tc + 3.0*dx).xyz);
vec3 c7 = GAMMA_IN(texture(Source, tc + 4.0*dx).xyz);
// Anti-ringing pre filtering
vec3 min_sample = min(min(c2,c3),min(c4,c5));
vec3 max_sample = max(max(c2,c3),max(c4,c5));
vec3 mins = (1.0/AR_MOD) * min_sample;
vec3 maxs = AR_MOD * max_sample;
c0 = clamp(c0, mins, maxs);
c1 = clamp(c1, mins, maxs);
c6 = clamp(c6, mins, maxs);
c7 = clamp(c7, mins, maxs);
mat4x3 color_matrix0 = mat4x3(c0, c1, c2, c3);
mat4x3 color_matrix1 = mat4x3(c4, c5, c6, c7);
vec2 hfp = get_hfilter_profile();
vec4 wgt0 = resampler4(vec4(3.0+fp.x, 2.0+fp.x, 1.0+fp.x, fp.x), hfp);
vec4 wgt1 = resampler4(vec4(1.0-fp.x, 2.0-fp.x, 3.0-fp.x, 4.0-fp.x), hfp);
float wgt_sum = (dot(wgt0, vec4(1.0))+dot(wgt1, vec4(1.0)));
wgt0 /= wgt_sum;
wgt1 /= wgt_sum;
color = color_matrix0 * wgt0 + color_matrix1 * wgt1;
// Anti-ringing post filtering
color = mix(color, clamp(color, min_sample, max_sample), CRT_ANTI_RINGING);
FragColor = vec4(color, 1.0);
}

View file

@ -1,214 +0,0 @@
#version 450
layout(push_constant) uniform Push
{
float BEAM_MIN_WIDTH;
float BEAM_MAX_WIDTH;
float SCANLINES_STRENGTH;
float COLOR_BOOST;
float SHARPNESS_HACK;
float PHOSPHOR_LAYOUT;
float MASK_INTENSITY;
float InputGamma;
float OutputGamma;
float VSCANLINES;
float CRT_ANTI_RINGING;
} param;
#pragma parameter CRT_HYLLIAN_SINC "[CRT-HYLLIAN-SINC PARAMS]" 0.0 0.0 0.0 0.0
#pragma parameter BEAM_MIN_WIDTH " MIN BEAM WIDTH" 0.92 0.0 1.0 0.01
#pragma parameter BEAM_MAX_WIDTH " MAX BEAM WIDTH" 1.0 0.0 1.0 0.01
#pragma parameter SCANLINES_STRENGTH " SCANLINES STRENGTH" 0.72 0.0 1.0 0.01
#pragma parameter COLOR_BOOST " COLOR BOOST" 1.60 1.0 2.0 0.05
#pragma parameter SHARPNESS_HACK " SHARPNESS_HACK" 1.0 1.0 4.0 1.0
#pragma parameter PHOSPHOR_LAYOUT " PHOSPHOR LAYOUT" 4.0 0.0 24.0 1.0
#pragma parameter MASK_INTENSITY " MASK INTENSITY" 0.7 0.0 1.0 0.1
#pragma parameter InputGamma " INPUT GAMMA" 2.4 0.0 5.0 0.1
#pragma parameter OutputGamma " OUTPUT GAMMA" 2.2 0.0 5.0 0.1
#pragma parameter VSCANLINES " SCANLINES DIRECTION" 0.0 0.0 1.0 1.0
#pragma parameter CRT_ANTI_RINGING "Spline16 Anti-Ringing [ OFF | ON ]" 0.0 0.0 1.0 1.0
#define CRT_ANTI_RINGING param.CRT_ANTI_RINGING
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
vec4 OutputSize;
vec4 OriginalSize;
vec4 SourceSize;
} global;
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
void main()
{
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(set = 0, binding = 2) uniform sampler2D Source;
/*
Hyllian's CRT Shader - Sinc/Spline16 version
Copyright (C) 2011-2022 Hyllian - sergiogdb@gmail.com
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.
*/
#include "../../../include/subpixel_masks.h"
#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))
#define scanlines_strength (2.0*param.SCANLINES_STRENGTH)
#define beam_min_width param.BEAM_MIN_WIDTH
#define beam_max_width param.BEAM_MAX_WIDTH
#define color_boost param.COLOR_BOOST
#define pi 3.1415926535897932384626433832795
#define wa (0.5*pi)
#define wb (pi)
//#define CRT_ANTI_RINGING 1.0
float weight(float x)
{
x = abs(x);
if (x < 1.0)
{
return
(
((x - 9.0 / 5.0) * x - 1.0 / 5.0 ) * x + 1.0
);
}
else if ((x >= 1.0) && (x < 2.0))
{
return
(
(( -1.0 / 3.0 * (x - 1) + 4.0 / 5.0 ) * (x - 1) - 7.0 / 15.0 ) * (x - 1)
);
}
else
{
return 0.0;
}
}
vec4 weight4(float x)
{
return vec4(
weight(x - 2.0),
weight(x - 1.0),
weight(x),
weight(x + 1.0)
);
}
vec3 resampler3(vec3 x)
{
vec3 res;
res.x = (x.x<=0.001) ? wa*wb : sin(x.x*wa)*sin(x.x*wb)/(x.x*x.x);
res.y = (x.y<=0.001) ? wa*wb : sin(x.y*wa)*sin(x.y*wb)/(x.y*x.y);
res.z = (x.z<=0.001) ? wa*wb : sin(x.z*wa)*sin(x.z*wb)/(x.z*x.z);
return res;
}
void main()
{
vec2 TextureSize = mix(vec2(global.SourceSize.x * param.SHARPNESS_HACK, global.SourceSize.y), vec2(global.SourceSize.x, global.SourceSize.y * param.SHARPNESS_HACK), param.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.5, -0.5))/TextureSize, param.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);
vec3 c02 = GAMMA_IN(texture(Source, tc + dx - dy).xyz);
vec3 c03 = GAMMA_IN(texture(Source, tc + 2.0*dx - dy).xyz);
vec3 c10 = GAMMA_IN(texture(Source, tc - dx ).xyz);
vec3 c11 = GAMMA_IN(texture(Source, tc ).xyz);
vec3 c12 = GAMMA_IN(texture(Source, tc + dx ).xyz);
vec3 c13 = GAMMA_IN(texture(Source, tc + 2.0*dx ).xyz);
mat4x3 color_matrix0 = mat4x3(c00, c01, c02, c03);
mat4x3 color_matrix1 = mat4x3(c10, c11, c12, c13);
// Get weights for spline16 horizontal filter
vec4 weights = weight4(1.0 - fp.x);
// Spline16 horizontal filter
vec3 color0 = (color_matrix0 * weights)/dot(weights, vec4(1.0));
vec3 color1 = (color_matrix1 * weights)/dot(weights, vec4(1.0));
// Get min/max samples
vec3 min_sample0 = min(c01,c02);
vec3 max_sample0 = max(c01,c02);
vec3 min_sample1 = min(c11,c12);
vec3 max_sample1 = max(c11,c12);
// Anti-ringing
vec3 aux = color0;
color0 = clamp(color0, min_sample0, max_sample0);
color0 = mix(aux, color0, CRT_ANTI_RINGING * step(0.0, (c00-c01)*(c02-c03)));
aux = color1;
color1 = clamp(color1, min_sample1, max_sample1);
color1 = mix(aux, color1, CRT_ANTI_RINGING * step(0.0, (c10-c11)*(c12-c13)));
// Apply scanlines. Sinc filter vertically.
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 d0 = clamp(scanlines_strength*pos0/(lum0*lum0+0.0000001), 0.0, 1.0);
vec3 d1 = clamp(scanlines_strength*pos1/(lum1*lum1+0.0000001), 0.0, 1.0);
d0 = resampler3(d0);
d1 = resampler3(d1);
// Apply color enhancement, scanlines orientation, mask and gamma.
vec3 color = color_boost*(color0*d0+color1*d1)/(wa*wb);
vec2 mask_coords = vTexCoord.xy * global.OutputSize.xy;
mask_coords = mix(mask_coords.xy, mask_coords.yx, param.VSCANLINES);
color.rgb*=mask_weights(mask_coords, param.MASK_INTENSITY, int(param.PHOSPHOR_LAYOUT));
color = GAMMA_OUT(color);
FragColor = vec4(color, 1.0);
}

View file

@ -1,207 +0,0 @@
#version 450
layout(push_constant) uniform Push
{
float BEAM_PROFILE;
float HFILTER_PROFILE;
float BEAM_MIN_WIDTH;
float BEAM_MAX_WIDTH;
float SCANLINES_STRENGTH;
float COLOR_BOOST;
float SHARPNESS_HACK;
float PHOSPHOR_LAYOUT;
float MASK_INTENSITY;
float CRT_ANTI_RINGING;
float InputGamma;
float OutputGamma;
float VSCANLINES;
} param;
#pragma parameter CRT_HYLLIAN "[CRT-HYLLIAN PARAMS]" 0.0 0.0 0.0 0.0
#pragma parameter BEAM_PROFILE " BEAM PROFILE (BP)" 0.0 0.0 2.0 1.0
#pragma parameter HFILTER_PROFILE " HORIZONTAL FILTER PROFILE [ HERMITE | CATMULL-ROM ]" 0.0 0.0 1.0 1.0
#pragma parameter BEAM_MIN_WIDTH " Custom [If BP=0.00] MIN BEAM WIDTH" 1.0 0.0 1.0 0.01
#pragma parameter BEAM_MAX_WIDTH " Custom [If BP=0.00] MAX BEAM WIDTH" 1.0 0.0 1.0 0.01
#pragma parameter SCANLINES_STRENGTH " Custom [If BP=0.00] SCANLINES STRENGTH" 0.58 0.0 1.0 0.01
#pragma parameter COLOR_BOOST " Custom [If BP=0.00] COLOR BOOST" 1.30 1.0 2.0 0.05
#pragma parameter SHARPNESS_HACK " SHARPNESS_HACK" 1.0 1.0 4.0 1.0
#pragma parameter PHOSPHOR_LAYOUT " PHOSPHOR LAYOUT" 4.0 0.0 24.0 1.0
#pragma parameter MASK_INTENSITY " MASK INTENSITY" 0.7 0.0 1.0 0.1
#pragma parameter CRT_ANTI_RINGING " ANTI RINGING" 1.0 0.0 1.0 0.2
#pragma parameter InputGamma " INPUT GAMMA" 2.4 0.0 5.0 0.1
#pragma parameter OutputGamma " OUTPUT GAMMA" 2.2 0.0 5.0 0.1
#pragma parameter VSCANLINES " VERTICAL SCANLINES [ OFF | ON ]" 0.0 0.0 1.0 1.0
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
vec4 OutputSize;
vec4 OriginalSize;
vec4 SourceSize;
} global;
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord * 1.0001;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 1) in vec2 FragCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
/*
Hyllian's CRT Shader
Copyright (C) 2011-2022 Hyllian - sergiogdb@gmail.com
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.
*/
#include "../../../include/subpixel_masks.h"
#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.
// Some known filters use these values:
// B = 0.0, C = 0.0 => Hermite cubic filter.
// B = 1.0, C = 0.0 => Cubic B-Spline filter.
// B = 0.0, C = 0.5 => Catmull-Rom Spline filter. This is the default used in this shader.
// B = C = 1.0/3.0 => Mitchell-Netravali cubic filter.
// B = 0.3782, C = 0.3109 => Robidoux filter.
// B = 0.2620, C = 0.3690 => Robidoux Sharp filter.
// Using only Hermite and Catmull-Rom, as the others aren't useful for crt shader.
// For more info, see: http://www.imagemagick.org/Usage/img_diagrams/cubic_survey.gif
mat4x4 get_hfilter_profile()
{
float bf = 0.0;
float cf = 0.0;
if (param.HFILTER_PROFILE == 1) {bf = 0.0; cf = 0.5;}
return mat4x4( (-bf - 6.0*cf)/6.0, (3.0*bf + 12.0*cf)/6.0, (-3.0*bf - 6.0*cf)/6.0, bf/6.0,
(12.0 - 9.0*bf - 6.0*cf)/6.0, (-18.0 + 12.0*bf + 6.0*cf)/6.0, 0.0, (6.0 - 2.0*bf)/6.0,
-(12.0 - 9.0*bf - 6.0*cf)/6.0, (18.0 - 15.0*bf - 12.0*cf)/6.0, (3.0*bf + 6.0*cf)/6.0, bf/6.0,
(bf + 6.0*cf)/6.0, -cf, 0.0, 0.0);
}
#define scanlines_strength (4.0*profile.x)
#define beam_min_width profile.y
#define beam_max_width profile.z
#define color_boost profile.w
vec4 get_beam_profile()
{
vec4 bp = vec4(param.SCANLINES_STRENGTH, param.BEAM_MIN_WIDTH, param.BEAM_MAX_WIDTH, param.COLOR_BOOST);
if (param.BEAM_PROFILE == 1) bp = vec4(0.62, 1.00, 1.00, 1.40); // Catmull-rom
if (param.BEAM_PROFILE == 2) bp = vec4(0.72, 1.00, 1.00, 1.20); // Catmull-rom
return bp;
}
void main()
{
vec4 profile = get_beam_profile();
vec2 TextureSize = mix(vec2(global.SourceSize.x * param.SHARPNESS_HACK, global.SourceSize.y), vec2(global.SourceSize.x, global.SourceSize.y * param.SHARPNESS_HACK), param.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.xy*TextureSize + vec2(-0.5, 0.5);
vec2 tc = mix((floor(pix_coord) + vec2(0.5, 0.5))/TextureSize, (floor(pix_coord) + vec2(1.5, -0.5))/TextureSize, param.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);
vec3 c02 = GAMMA_IN(texture(Source, tc + dx - dy).xyz);
vec3 c03 = GAMMA_IN(texture(Source, tc + 2.0*dx - dy).xyz);
vec3 c10 = GAMMA_IN(texture(Source, tc - dx ).xyz);
vec3 c11 = GAMMA_IN(texture(Source, tc ).xyz);
vec3 c12 = GAMMA_IN(texture(Source, tc + dx ).xyz);
vec3 c13 = GAMMA_IN(texture(Source, tc + 2.0*dx ).xyz);
mat4x4 invX = get_hfilter_profile();
mat4x3 color_matrix0 = mat4x3(c00, c01, c02, c03);
mat4x3 color_matrix1 = mat4x3(c10, c11, c12, c13);
vec4 invX_Px = vec4(fp.x*fp.x*fp.x, fp.x*fp.x, fp.x, 1.0) * invX;
vec3 color0 = color_matrix0 * invX_Px;
vec3 color1 = color_matrix1 * invX_Px;
// Get min/max samples
vec3 min_sample0 = min(c01,c02);
vec3 max_sample0 = max(c01,c02);
vec3 min_sample1 = min(c11,c12);
vec3 max_sample1 = max(c11,c12);
// Anti-ringing
vec3 aux = color0;
color0 = clamp(color0, min_sample0, max_sample0);
color0 = mix(aux, color0, param.CRT_ANTI_RINGING * step(0.0, (c00-c01)*(c02-c03)));
aux = color1;
color1 = clamp(color1, min_sample1, max_sample1);
color1 = mix(aux, color1, param.CRT_ANTI_RINGING * step(0.0, (c10-c11)*(c12-c13)));
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 d0 = scanlines_strength*pos0/(lum0*lum0+0.0000001);
vec3 d1 = scanlines_strength*pos1/(lum1*lum1+0.0000001);
d0 = exp(-d0*d0);
d1 = exp(-d1*d1);
vec3 color = color_boost*(color0*d0+color1*d1);
vec2 mask_coords =vTexCoord.xy * global.OutputSize.xy;
mask_coords = mix(mask_coords.xy, mask_coords.yx, param.VSCANLINES);
color.rgb*=mask_weights(mask_coords, param.MASK_INTENSITY, int(param.PHOSPHOR_LAYOUT));
color = GAMMA_OUT(color);
FragColor = vec4(color, 1.0);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View file

@ -0,0 +1,42 @@
#version 450
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
float OutputGamma;
} params;
#pragma parameter OutputGamma "OUTPUT GAMMA" 2.0 1.0 3.0 0.05
#define OutputGamma params.OutputGamma
#define GAMMA_OUT(color) pow(color, vec3(1.0 / OutputGamma, 1.0 / OutputGamma, 1.0 / OutputGamma))
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
} global;
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
void main()
{
// FragColor = pow(vec4(texture(Source, vTexCoord).rgb, 1.0), vec4(1.0 / 2.2));
FragColor = vec4(GAMMA_OUT(texture(Source, vTexCoord).rgb), 1.0);
}

View file

@ -0,0 +1,43 @@
#version 450
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
float InputGamma;
} params;
#pragma parameter InputGamma "INPUT GAMMA" 2.0 1.0 3.0 0.05
#define InputGamma params.InputGamma
#define GAMMA_IN(color) pow(color, vec3(InputGamma, InputGamma, InputGamma))
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
} global;
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
void main()
{
// FragColor = pow(vec4(texture(Source, vTexCoord).rgb, 1.0), vec4(2.2));
FragColor = vec4(GAMMA_IN(texture(Source, vTexCoord).rgb), 1.0);
}

View file

@ -0,0 +1,81 @@
#version 450
// A version of the LUT shader that loads 2 LUTs.
// Can turn LUT off too.
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
float LUT_selector_param;
} params;
#pragma parameter LUT_selector_param "LUT [ Off | NTSC | Grade ]" 1.0 0.0 2.0 1.0
int LUT_selector = int(params.LUT_selector_param);
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
} global;
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord * 1.0001;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
layout(set = 0, binding = 3) uniform sampler2D SamplerLUT1;
layout(set = 0, binding = 4) uniform sampler2D SamplerLUT2;
// This shouldn't be necessary but it seems some undefined values can
// creep in and each GPU vendor handles that differently. This keeps
// all values within a safe range
vec4 mixfix(vec4 a, vec4 b, float c)
{
return (a.z < 1.0) ? mix(a, b, c) : a;
}
void main()
{
vec4 imgColor = texture(Source, vTexCoord.xy);
if (LUT_selector == 0.0) {
FragColor = imgColor;
}
else {
float LUT_Size = mix(textureSize(SamplerLUT1, 0).y, textureSize(SamplerLUT2, 0).y, params.LUT_selector_param - 1.0);
vec4 color1, color2 = vec4(0.,0.,0.,0.);
float red, green, blue1, blue2, mixer = 0.0;
red = ( imgColor.r * (LUT_Size - 1.0) + 0.4999 ) / (LUT_Size * LUT_Size);
green = ( imgColor.g * (LUT_Size - 1.0) + 0.4999 ) / LUT_Size;
blue1 = (floor( imgColor.b * (LUT_Size - 1.0) ) / LUT_Size) + red;
blue2 = (ceil( imgColor.b * (LUT_Size - 1.0) ) / LUT_Size) + red;
mixer = clamp(max((imgColor.b - blue1) / (blue2 - blue1), 0.0), 0.0, 32.0);
if(LUT_selector == 1)
{
color1 = texture( SamplerLUT1, vec2( blue1, green ));
color2 = texture( SamplerLUT1, vec2( blue2, green ));
}
else
{
color1 = texture( SamplerLUT2, vec2( blue1, green ));
color2 = texture( SamplerLUT2, vec2( blue2, green ));
}
FragColor = mixfix(color1, color2, mixer);
}
}

View file

@ -0,0 +1,133 @@
#version 450
// NTSC-Adaptive-Lite - Faster for 2-Phase games (only 15 taps!)
// based on Themaister's NTSC shader
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
vec4 OutputSize;
vec4 OriginalSize;
vec4 SourceSize;
uint FrameCount;
float quality, ntsc_sat, cust_fringing, cust_artifacting, ntsc_bright, ntsc_scale, ntsc_fields, ntsc_phase, ntsc_artifacting_rainbow;
} global;
#pragma parameter quality "NTSC Preset (Svideo=0 Composite=1 RF=2 Custom=-1)" 1.0 -1.0 2.0 1.0
#pragma parameter ntsc_fields "NTSC Merge Fields" 0.0 0.0 1.0 1.0
#pragma parameter ntsc_phase "NTSC Phase: Auto | 2 phase | 3 phase" 1.0 1.0 3.0 1.0
#pragma parameter ntsc_scale "NTSC Resolution Scaling" 1.0 0.20 3.0 0.05
#pragma parameter ntsc_sat "NTSC Color Saturation" 1.0 0.0 2.0 0.01
#pragma parameter ntsc_bright "NTSC Brightness" 1.0 0.0 1.5 0.01
#pragma parameter cust_fringing "NTSC Custom Fringing Value" 0.0 0.0 5.0 0.1
#pragma parameter cust_artifacting "NTSC Custom Artifacting Value" 0.0 0.0 5.0 0.1
#pragma parameter ntsc_artifacting_rainbow "NTSC Artifacting Rainbow Effect" 0.0 -1.0 1.0 0.1
#define PI 3.14159265
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
layout(location = 1) out vec2 pix_no;
layout(location = 2) out float phase;
layout(location = 3) out float BRIGHTNESS;
layout(location = 4) out float SATURATION;
layout(location = 5) out float FRINGING;
layout(location = 6) out float ARTIFACTING;
layout(location = 7) out float CHROMA_MOD_FREQ;
layout(location = 8) out float MERGE;
void main()
{
float res = global.ntsc_scale;
float OriginalSize = global.OriginalSize.x;
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
if (res < 1.0) pix_no = TexCoord * global.SourceSize.xy * (res * global.OutputSize.xy / global.SourceSize.xy); else
pix_no = TexCoord * global.SourceSize.xy * ( global.OutputSize.xy / global.SourceSize.xy);
phase = (global.ntsc_phase < 1.5) ? ((OriginalSize > 300.0) ? 2.0 : 3.0) : ((global.ntsc_phase > 2.5) ? 3.0 : 2.0);
res = max(res, 1.0);
CHROMA_MOD_FREQ = (phase < 2.5) ? (4.0 * PI / 15.0) : (PI / 3.0);
ARTIFACTING = (global.quality > -0.5) ? global.quality * 0.5*(res+1.0) : global.cust_artifacting;
FRINGING = (global.quality > -0.5) ? global.quality : global.cust_fringing;
SATURATION = global.ntsc_sat;
BRIGHTNESS = global.ntsc_bright;
pix_no.x = pix_no.x * res;
MERGE = (int(global.quality) == 2 || phase < 2.5) ? 0.0 : 1.0;
MERGE = (int(global.quality) == -1) ? global.ntsc_fields : MERGE;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 1) in vec2 pix_no;
layout(location = 2) in float phase;
layout(location = 3) in float BRIGHTNESS;
layout(location = 4) in float SATURATION;
layout(location = 5) in float FRINGING;
layout(location = 6) in float ARTIFACTING;
layout(location = 7) in float CHROMA_MOD_FREQ;
layout(location = 8) in float MERGE;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
#define mix_mat mat3(BRIGHTNESS, FRINGING, FRINGING, ARTIFACTING, 2.0 * SATURATION, 0.0, ARTIFACTING, 0.0, 2.0 * SATURATION)
const mat3 yiq2rgb_mat = mat3(
1.0, 0.956, 0.6210,
1.0, -0.2720, -0.6474,
1.0, -1.1060, 1.7046);
vec3 yiq2rgb(vec3 yiq)
{
return yiq * yiq2rgb_mat;
}
const mat3 yiq_mat = mat3(
0.2989, 0.5870, 0.1140,
0.5959, -0.2744, -0.3216,
0.2115, -0.5229, 0.3114
);
vec3 rgb2yiq(vec3 col)
{
return col * yiq_mat;
}
void main()
{
vec3 col = texture(Source, vTexCoord).rgb;
vec3 yiq = rgb2yiq(col);
vec3 yiq2 = yiq;
float mod1 = 2.0;
float mod2 = 3.0;
if (MERGE > 0.5)
{
float chroma_phase2 = (phase < 2.5) ? PI * (mod(pix_no.y, mod1) + mod(global.FrameCount+1, 2.)) : 0.6667 * PI * (mod(pix_no.y, mod2) + mod(global.FrameCount+1, 2.));
float mod_phase2 = (global.ntsc_artifacting_rainbow + 1.0) * chroma_phase2 + pix_no.x * CHROMA_MOD_FREQ;
float i_mod2 = cos(mod_phase2);
float q_mod2 = sin(mod_phase2);
yiq2.yz *= vec2(i_mod2, q_mod2); // Modulate.
yiq2 *= mix_mat; // Cross-talk.
yiq2.yz *= vec2(i_mod2, q_mod2); // Demodulate.
}
float chroma_phase = (phase < 2.5) ? PI * (mod(pix_no.y, mod1) + mod(global.FrameCount, 2.)) : 0.6667 * PI * (mod(pix_no.y, mod2) + mod(global.FrameCount, 2.));
float mod_phase = (global.ntsc_artifacting_rainbow + 1.0) * 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.
yiq = (MERGE < 0.5) ? yiq : 0.5*(yiq+yiq2);
FragColor = vec4(yiq, 1.0);
}

View file

@ -0,0 +1,269 @@
#version 450
// NTSC-Adaptive-Lite
// based on Themaister's NTSC shader
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
vec4 OutputSize;
vec4 OriginalSize;
vec4 SourceSize;
float linearize;
float ntsc_scale;
float ntsc_phase;
float auto_res;
float chroma_scale;
} global;
#pragma parameter chroma_scale "NTSC Chroma Scaling" 1.0 0.2 4.0 0.1
#pragma parameter ntsc_scale "NTSC Resolution Scaling" 1.0 0.20 3.0 0.05
#pragma parameter ntsc_phase "NTSC Phase: Auto | 2 phase | 3 phase" 1.0 1.0 3.0 1.0
#pragma parameter linearize "NTSC Linearize Output Gamma" 0.0 0.0 1.0 1.0
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord - vec2(0.5 / global.SourceSize.x, 0.0); // Compensate for decimate-by-2.
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
//layout(set = 0, binding = 3) uniform sampler2D orig;
vec3 fetch_offset(float offset, vec2 one_x)
{
/* Insert chroma scaling. Thanks to guest.r ideas. */
vec3 yiq;
yiq.x = texture(Source, vTexCoord + vec2((offset) * (one_x.x), 0.0)).x;
yiq.yz = texture(Source, vTexCoord + vec2((offset) * (one_x.y), 0.0)).yz;
return yiq;
/* Old code
return texture(Source, vTexCoord + vec2((offset) * (one_x), 0.0)).xyz;
*/
}
const mat3 yiq2rgb_mat = mat3(
1.0, 0.956, 0.6210,
1.0, -0.2720, -0.6474,
1.0, -1.1060, 1.7046);
vec3 yiq2rgb(vec3 yiq)
{
return yiq * yiq2rgb_mat;
}
const mat3 yiq_mat = mat3(
0.2989, 0.5870, 0.1140,
0.5959, -0.2744, -0.3216,
0.2115, -0.5229, 0.3114
);
vec3 rgb2yiq(vec3 col)
{
return col * yiq_mat;
}
/* These are accurate and normalized coeffs. */
const int TAPS_3_phase = 24;
const float luma_filter_3_phase[25] = float[25](
-0.0000120203033684164,
-0.0000221465589348544,
-0.0000131553320142694,
-0.0000120203033684164,
-0.0000499802614018372,
-0.000113942875690297,
-0.000122153082899506,
-5.61214E-06,
0.000170520303591422,
0.000237204986579451,
0.000169644281482376,
0.000285695210375719,
0.000984598849305758,
0.0020187339488074,
0.00200232553469184,
-0.000909904964181485,
-0.00704925890919635,
-0.0132231937269633,
-0.0126072491817548,
0.00246092210875218,
0.0358691302651096,
0.0840185734607569,
0.135566921437963,
0.175265691355518,
0.190181351796957);
/* These are accurate and normalized coeffs. */
const float chroma_filter_3_phase[25] = float[25](
-0.000135741056915795,
-0.000568115749081878,
-0.00130605691082327,
-0.00231369942971182,
-0.00350569685928248,
-0.00474731062446688,
-0.00585980203774502,
-0.00663114046295865,
-0.00683148404964774,
-0.00623234997205773,
-0.00462792764511295,
-0.00185665431957684,
0.00217899013894782,
0.00749647783836479,
0.0140227874371299,
0.021590863169257,
0.0299437436530477,
0.0387464461271303,
0.0476049759842373,
0.0560911497485196,
0.0637713405314321,
0.0702368383153846,
0.0751333078160781,
0.0781868487834974,
0.0792244191487085);
/* These are accurate and normalized coeffs. Though they don't produce ideal smooth vertical lines transparency. */
const int TAPS_2_phase = 15;
const float luma_filter_2_phase[16] = float[16](
0.00134372867555492,
0.00294231678339247,
0.00399617683765551,
0.00303632635732925,
-0.00110556727614119,
-0.00839970341605087,
-0.0169515379999301,
-0.0229874881474188,
-0.0217113019865528,
-0.00889151239892142,
0.0173269874254282,
0.0550969075027442,
0.098655909675851,
0.139487291941771,
0.168591277052964,
0.17914037794465);
/*
Use these coeffs if you want smoother transparencies (vertical lines genesis dithering).
const int TAPS_2_phase = 15;
const float luma_filter_2_phase[16] = float[16](
0.00358674124928555,
0.00516185579845568,
0.00480461826123886,
0.00132260688600227,
-0.00546931642681805,
-0.014242227285043,
-0.0221097992725951,
-0.025171977770877,
-0.0195669333236999,
-0.00275082885707516,
0.0253995033240388,
0.0620582992351114,
0.101744778642171,
0.137437283264631,
0.162237083549672,
0.171116625451004);
*/
/* These are accurate and normalized coeffs. */
const float chroma_filter_2_phase[16] = float[16](
0.00406084767413046,
0.00578573638571078,
0.00804447474387669,
0.0109152541019797,
0.0144533032717188,
0.0186765858322351,
0.0235518468184291,
0.0289834149989225,
0.034807373222651,
0.0407934139180355,
0.0466558344725586,
0.0520737649339226,
0.0567190701585739,
0.0602887575746322,
0.0625375226221969,
0.0633055985408521);
void main()
{
float res = global.ntsc_scale;
float OriginalSize = global.OriginalSize.x;
vec3 signal = vec3(0.0);
float phase = (global.ntsc_phase < 1.5) ? ((OriginalSize > 300.0) ? 2.0 : 3.0) : ((global.ntsc_phase > 2.5) ? 3.0 : 2.0);
float chroma_scale = phase > 2.5 ? min(global.chroma_scale, 2.2) : global.chroma_scale/2.0;
vec2 one_x = (global.SourceSize.z / res) * vec2(1.0, 1.0 / chroma_scale);
if(phase < 2.5)
{
vec3 sums = fetch_offset(0.0 - 15.0, one_x) + fetch_offset(15.0 - 0.0, one_x);
signal += sums * vec3(luma_filter_2_phase[0], chroma_filter_2_phase[0], chroma_filter_2_phase[0]);
sums = fetch_offset(1.0 - 15.0, one_x) + fetch_offset(15.0 - 1.0, one_x);
signal += sums * vec3(luma_filter_2_phase[1], chroma_filter_2_phase[1], chroma_filter_2_phase[1]);
sums = fetch_offset(2.0 - 15.0, one_x) + fetch_offset(15.0 - 2.0, one_x);
signal += sums * vec3(luma_filter_2_phase[2], chroma_filter_2_phase[2], chroma_filter_2_phase[2]);
sums = fetch_offset(3.0 - 15.0, one_x) + fetch_offset(15.0 - 3.0, one_x);
signal += sums * vec3(luma_filter_2_phase[3], chroma_filter_2_phase[3], chroma_filter_2_phase[3]);
sums = fetch_offset(4.0 - 15.0, one_x) + fetch_offset(15.0 - 4.0, one_x);
signal += sums * vec3(luma_filter_2_phase[4], chroma_filter_2_phase[4], chroma_filter_2_phase[4]);
sums = fetch_offset(5.0 - 15.0, one_x) + fetch_offset(15.0 - 5.0, one_x);
signal += sums * vec3(luma_filter_2_phase[5], chroma_filter_2_phase[5], chroma_filter_2_phase[5]);
sums = fetch_offset(6.0 - 15.0, one_x) + fetch_offset(15.0 - 6.0, one_x);
signal += sums * vec3(luma_filter_2_phase[6], chroma_filter_2_phase[6], chroma_filter_2_phase[6]);
sums = fetch_offset(7.0 - 15.0, one_x) + fetch_offset(15.0 - 7.0, one_x);
signal += sums * vec3(luma_filter_2_phase[7], chroma_filter_2_phase[7], chroma_filter_2_phase[7]);
sums = fetch_offset(8.0 - 15.0, one_x) + fetch_offset(15.0 - 8.0, one_x);
signal += sums * vec3(luma_filter_2_phase[8], chroma_filter_2_phase[8], chroma_filter_2_phase[8]);
sums = fetch_offset(9.0 - 15.0, one_x) + fetch_offset(15.0 - 9.0, one_x);
signal += sums * vec3(luma_filter_2_phase[9], chroma_filter_2_phase[9], chroma_filter_2_phase[9]);
sums = fetch_offset(10.0 - 15.0, one_x) + fetch_offset(15.0 - 10.0, one_x);
signal += sums * vec3(luma_filter_2_phase[10], chroma_filter_2_phase[10], chroma_filter_2_phase[10]);
sums = fetch_offset(11.0 - 15.0, one_x) + fetch_offset(15.0 - 11.0, one_x);
signal += sums * vec3(luma_filter_2_phase[11], chroma_filter_2_phase[11], chroma_filter_2_phase[11]);
sums = fetch_offset(12.0 - 15.0, one_x) + fetch_offset(15.0 - 12.0, one_x);
signal += sums * vec3(luma_filter_2_phase[12], chroma_filter_2_phase[12], chroma_filter_2_phase[12]);
sums = fetch_offset(13.0 - 15.0, one_x) + fetch_offset(15.0 - 13.0, one_x);
signal += sums * vec3(luma_filter_2_phase[13], chroma_filter_2_phase[13], chroma_filter_2_phase[13]);
sums = fetch_offset(14.0 - 15.0, one_x) + fetch_offset(15.0 - 14.0, one_x);
signal += sums * vec3(luma_filter_2_phase[14], chroma_filter_2_phase[14], chroma_filter_2_phase[14]);
signal += texture(Source, vTexCoord).xyz *
vec3(luma_filter_2_phase[TAPS_2_phase], chroma_filter_2_phase[TAPS_2_phase], chroma_filter_2_phase[TAPS_2_phase]);
}
else if(phase > 2.5)
{
for (int i = 0; i < TAPS_3_phase; i++)
{
float offset = float(i);
vec3 sums = fetch_offset(offset - float(TAPS_3_phase), one_x) +
fetch_offset(float(TAPS_3_phase) - offset, one_x);
signal += sums * vec3(luma_filter_3_phase[i], chroma_filter_3_phase[i], chroma_filter_3_phase[i]);
}
signal += texture(Source, vTexCoord).xyz *
vec3(luma_filter_3_phase[TAPS_3_phase], chroma_filter_3_phase[TAPS_3_phase], chroma_filter_3_phase[TAPS_3_phase]);
}
vec3 rgb = yiq2rgb(signal);
FragColor = vec4(rgb, 1.0);
if(global.linearize < 0.5) return;
else FragColor = pow(FragColor, vec4(2.2));
}