diff --git a/data/resources/shaders/dolphinfx/crt/CRT-CONSUMER.glsl b/data/resources/shaders/dolphinfx/crt/CRT-CONSUMER.glsl deleted file mode 100644 index 0eeb87076..000000000 --- a/data/resources/shaders/dolphinfx/crt/CRT-CONSUMER.glsl +++ /dev/null @@ -1,780 +0,0 @@ -// Crt-Consumer - -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - - -/* -[configuration] - - -[OptionRangeFloat] -GUIName = Pre-Scale Sharpening -OptionName = PRE_SCALE -MinValue = 1.0 -MaxValue = 4.0 -StepAmount = 0.1 -DefaultValue = 1.5 - -[OptionRangeFloat] -GUIName = Convergence X -OptionName = blurx -MinValue = -4.0 -MaxValue = 4.0 -StepAmount = 0.05 -DefaultValue = 0.25 - -[OptionRangeFloat] -GUIName = Convergence Y -OptionName = blury -MinValue = -4.0 -MaxValue = 4.0 -StepAmount = 0.05 -DefaultValue = -0.1 - -[OptionRangeFloat] -GUIName = Curvature X -OptionName = warpx -MinValue = 0.0 -MaxValue = 0.12 -StepAmount = 0.01 -DefaultValue = 0.03 - -[OptionRangeFloat] -GUIName = Curvature Y -OptionName = warpy -MinValue = 0.0 -MaxValue = 0.12 -StepAmount = 0.01 -DefaultValue = 0.04 - -[OptionRangeFloat] -GUIName = Corner size -OptionName = corner -MinValue = 0.0 -MaxValue = 0.10 -StepAmount = 0.01 -DefaultValue = 0.03 - -[OptionRangeFloat] -GUIName = Border Smoothness -OptionName = smoothness -MinValue = 100.0 -MaxValue = 600.0 -StepAmount = 5.0 -DefaultValue = 400.0 - -[OptionRangeFloat] -GUIName = Interlacing Toggle -OptionName = inter -MinValue = 0.0 -MaxValue = 1.0 -StepAmount = 1.0 -DefaultValue = 1.0 - -[OptionRangeFloat] -GUIName = Interlacing Downscale Scanlines -OptionName = Downscale -MinValue = 1.0 -MaxValue = 8.0 -StepAmount = 1. -DefaultValue = 2.0 - -[OptionRangeFloat] -GUIName = Beam low -OptionName = scanlow -MinValue = 1.0 -MaxValue = 15.0 -StepAmount = 1.0 -DefaultValue = 6.0 - -[OptionRangeFloat] -GUIName = Beam high -OptionName = scanhigh -MinValue = 1.0 -MaxValue = 15.0 -StepAmount = 1.0 -DefaultValue = 8.0 - -[OptionRangeFloat] -GUIName = Scanlines dark -OptionName = beamlow -MinValue = 0.5 -MaxValue = 2.5 -StepAmount = 0.0 -DefaultValue = 1.45 - -[OptionRangeFloat] -GUIName = Scanlines bright -OptionName = beamhigh -MinValue = 0.5 -MaxValue = 2.5 -StepAmount = 0.0 -DefaultValue = 1.05 - -[OptionRangeFloat] -GUIName = Protect White On Masks -OptionName = preserve -MinValue = 0.0 -MaxValue = 1.0 -StepAmount = 0.01 -DefaultValue = 0.98 - -[OptionRangeFloat] -GUIName = Bright boost dark pixels -OptionName = brightboost1 -MinValue = 0.0 -MaxValue = 3.0 -StepAmount = 0.05 -DefaultValue = 1.25 - -[OptionRangeFloat] -GUIName = Bright boost bright pixels -OptionName = brightboost2 -MinValue = 0.0 -MaxValue = 3.0 -StepAmount = 0.05 -DefaultValue = 1.0 - -[OptionRangeFloat] -GUIName = Glow pixels per axis -OptionName = glow -MinValue = 1.0 -MaxValue = 6.0 -StepAmount = 1.0 -DefaultValue = 3.0 - -[OptionRangeFloat] -GUIName = Glow quality -OptionName = quality -MinValue = 0.25 -MaxValue = 4.0 -StepAmount = 0.05 -DefaultValue = 1.0 - -[OptionRangeFloat] -GUIName = Glow intensity -OptionName = glow_str -MinValue = 0.0001 -MaxValue = 2.0 -StepAmount = 0.05 -DefaultValue = 0.3 - -[OptionRangeFloat] -GUIName = Add Noise -OptionName = nois -MinValue = 0.0 -MaxValue = 32.0 -StepAmount = 1.0 -DefaultValue = 0.0 - -[OptionRangeFloat] -GUIName = Post Brightness -OptionName = postbr -MinValue = 0.0 -MaxValue = 2.5 -StepAmount = 0.02 -DefaultValue = 1.0 - -[OptionRangeFloat] -GUIName = Palette Fixes. Sega, PUAE Atari ST dark colors -OptionName = palette_fix -MinValue = 0.0 -MaxValue = 2.0 -StepAmount = 1.0 -DefaultValue = 0.0 - -[OptionRangeFloat] -GUIName = Mask Type -OptionName = Shadowmask -MinValue = -1.0 -MaxValue = 8.0 -StepAmount = 1. -DefaultValue = 0.0 - -[OptionRangeFloat] -GUIName = Mask Size -OptionName = masksize -MinValue = 1.0 -MaxValue = 2.0 -StepAmount = 1.0 -DefaultValue = 1.0 - -[OptionRangeFloat] -GUIName = Mask dark -OptionName = MaskDark -MinValue = 0.0 -MaxValue = 2.0 -StepAmount = 0.1 -DefaultValue = 0.2 - -[OptionRangeFloat] -GUIName = Mask light -OptionName = MaskLight -MinValue = 0.0 -MaxValue = 2.0 -StepAmount = 0.1 -DefaultValue = 1.5 - -[OptionRangeFloat] -GUIName = Slot Mask Strength -OptionName = slotmask -MinValue = 0.0 -MaxValue = 1.0 -StepAmount = 0.05 -DefaultValue = 0.0 - -[OptionRangeFloat] -GUIName = Slot Mask Width -OptionName = slotwidth -MinValue = 1.0 -MaxValue = 6.0 -StepAmount = 0.5 -DefaultValue = 2.0 - -[OptionRangeFloat] -GUIName = Slot Mask Height: 2x1 or 4x1 -OptionName = double_slot -MinValue = 1.0 -MaxValue = 2.0 -StepAmount = 1.0 -DefaultValue = 1.0 - -[OptionRangeFloat] -GUIName = Slot Mask Size -OptionName = slotms -MinValue = 1.0 -MaxValue = 2.0 -StepAmount = 1.0 -DefaultValue = 1.0 - -[OptionRangeFloat] -GUIName = Gamma Out -OptionName = GAMMA_OUT -MinValue = 0.0 -MaxValue = 4.0 -StepAmount = 0.05 -DefaultValue = 2.25 - -[OptionRangeFloat] -GUIName = Saturation -OptionName = sat -MinValue = 0.0 -MaxValue = 2.0 -StepAmount = 0.05 -DefaultValue = 1.0 - -[OptionRangeFloat] -GUIName = Contrast, 1.0:Off -OptionName = contrast -MinValue = 0.00 -MaxValue = 2.00 -StepAmount = 0.05 -DefaultValue = 1.0 - -[OptionRangeFloat] -GUIName = Color Temperature % -OptionName = WP -MinValue = -100.0 -MaxValue = 100.0 -StepAmount = 5. -DefaultValue = 0.0 - -[OptionRangeFloat] -GUIName = Red-Green Tint -OptionName = rg -MinValue = -1.0 -MaxValue = 1.0 -StepAmount = 0.005 -DefaultValue = 0.0 - -[OptionRangeFloat] -GUIName = Red-Blue Tint -OptionName = rb -MinValue = -1.0 -MaxValue = 1.0 -StepAmount = 0.005 -DefaultValue = 0.0 - -[OptionRangeFloat] -GUIName = Green-Red Tint -OptionName = gr -MinValue = -1.0 -MaxValue = 1.0 -StepAmount = 0.005 -DefaultValue = 0.0 - -[OptionRangeFloat] -GUIName = Green-Blue Tint -OptionName = gb -MinValue = -1.0 -MaxValue = 1.0 -StepAmount = 0.005 -DefaultValue = 0.0 - -[OptionRangeFloat] -GUIName = Blue-Red Tint -OptionName = br -MinValue = -1.0 -MaxValue = 1.0 -StepAmount = 0.005 -DefaultValue = 0.0 - -[OptionRangeFloat] -GUIName = Blue-Green Tint -OptionName = bg -MinValue = -1.0 -MaxValue = 1.0 -StepAmount = 0.005 -DefaultValue = 0.0 - -[OptionRangeFloat] -GUIName = Vignette On/Off -OptionName = vignette -MinValue = 0.0 -MaxValue = 1.0 -StepAmount = 1.0 -DefaultValue = 0.0 - -[OptionRangeFloat] -GUIName = Vignette Power -OptionName = vpower -MinValue = 0.0 -MaxValue = 1.0 -StepAmount = 0.01 -DefaultValue = 0.15 - -[OptionRangeFloat] -GUIName = Vignette strength -OptionName = vstr -MinValue = 0.0 -MaxValue = 50.0 -StepAmount = 1.0 -DefaultValue = 40.0 - -[OptionRangeFloat] -GUIName = Switch off shader -OptionName = alloff -MinValue = 0.0 -MaxValue = 1.0 -StepAmount = 1.0 -DefaultValue = 0.0 - - -[/configuration] -*/ - -#define iTime (float(GetTime())/2.0) -#define iTimer (float(GetTime())/60.0) - -#define SourceSize (vec4(1.0/GetInvNativePixelSize(),GetInvNativePixelSize())) - -vec2 Warp(vec2 pos) -{ - pos = pos * 2.0 - 1.0; - pos *= vec2(1.0 + (pos.y * pos.y) * warpx, 1.0 + (pos.x * pos.x) * warpy); - return pos * 0.5 + 0.5; -} - -float sw(float y, float l) -{ - float beam = mix(scanlow, scanhigh, y); - float scan = mix(beamlow, beamhigh, l); - float ex = y * scan; - return exp2(-beam * ex * ex); -} - -vec3 mask(vec2 x, vec3 col, float l) -{ - x = floor(x / masksize); - - if (Shadowmask == 0.0) - { - float m = fract(x.x * 0.4999); - if (m < 0.4999) return vec3(1.0, MaskDark, 1.0); - else return vec3(MaskDark, 1.0, MaskDark); - } - - else if (Shadowmask == 1.0) - { - vec3 Mask = vec3(MaskDark, MaskDark, MaskDark); - float line = MaskLight; - float odd = 0.0; - - if (fract(x.x / 6.0) < 0.5) odd = 1.0; - if (fract((x.y + odd) / 2.0) < 0.5) line = MaskDark; - - float m = fract(x.x / 3.0); - if (m < 0.333) Mask.b = MaskLight; - else if (m < 0.666) Mask.g = MaskLight; - else Mask.r = MaskLight; - - Mask *= line; - return Mask; - } - - else if (Shadowmask == 2.0) - { - float m = fract(x.x*0.3333); - if (m < 0.3333) return vec3(MaskDark, MaskDark, MaskLight); - if (m < 0.6666) return vec3(MaskDark, MaskLight, MaskDark); - else return vec3(MaskLight, MaskDark, MaskDark); - } - - if (Shadowmask == 3.0) - { - float m = fract(x.x * 0.5); - if (m < 0.5) return vec3(1.0, 1.0, 1.0); - else return vec3(MaskDark, MaskDark, MaskDark); - } - - else if (Shadowmask == 4.0) - { - vec3 Mask = vec3(col.rgb); - float line = MaskLight; - float odd = 0.0; - - if (fract(x.x / 4.0) < 0.5) odd = 1.0; - if (fract((x.y + odd) / 2.0) < 0.5) line = MaskDark; - - float m = fract(x.x / 2.0); - if (m < 0.5) { Mask.r = 1.0; Mask.b = 1.0; } - else Mask.g = 1.0; - - Mask *= line; - return Mask; - } - - else if (Shadowmask == 5.0) - { - vec3 Mask = vec3(1.0, 1.0, 1.0); - - if (fract(x.x / 4.0) < 0.5) - { - if (fract(x.y / 3.0) < 0.666) - { - if (fract(x.x / 2.0) < 0.5) Mask = vec3(1.0, MaskDark, 1.0); - else Mask = vec3(MaskDark, 1.0, MaskDark); - } - else Mask *= l; - } - else if (fract(x.x / 4.0) >= 0.5) - { - if (fract(x.y / 3.0) > 0.333) - { - if (fract(x.x / 2.0) < 0.5) Mask = vec3(1.0, MaskDark, 1.0); - else Mask = vec3(MaskDark, 1.0, MaskDark); - } - else Mask *= l; - } - - return Mask; - } - - else if (Shadowmask == 6.0) - { - vec3 Mask = vec3(MaskDark, MaskDark, MaskDark); - if (fract(x.x / 6.0) < 0.5) - { - if (fract(x.y / 4.0) < 0.75) - { - if (fract(x.x / 3.0) < 0.3333) Mask.r = MaskLight; - else if (fract(x.x / 3.0) < 0.6666) Mask.g = MaskLight; - else Mask.b = MaskLight; - } - else Mask * l * 0.9; - } - else if (fract(x.x / 6.0) >= 0.5) - { - if (fract(x.y / 4.0) >= 0.5 || fract(x.y / 4.0) < 0.25) - { - if (fract(x.x / 3.0) < 0.3333) Mask.r = MaskLight; - else if (fract(x.x / 3.0) < 0.6666) Mask.g = MaskLight; - else Mask.b = MaskLight; - } - else Mask * l * 0.9; - } - return Mask; - } - - else if (Shadowmask == 7.0) - { - float m = fract(x.x * 0.3333); - - if (m < 0.3333) return vec3(MaskDark, MaskLight, MaskLight * col.b); //Cyan - if (m < 0.6666) return vec3(MaskLight * col.r, MaskDark, MaskLight); //Magenta - else return vec3(MaskLight, MaskLight * col.g, MaskDark); //Yellow - } - - else if (Shadowmask == 8.0) - { - vec3 Mask = vec3(MaskDark, MaskDark, MaskDark); - - float bright = MaskLight; - float left = 0.0; - if (fract(x.x / 6.0) < 0.5) left = 1.0; - - float m = fract(x.x / 3.0); - if (m < 0.333) Mask.b = 0.9; - else if (m < 0.666) Mask.g = 0.9; - else Mask.r = 0.9; - - if (mod(x.y, 2.0) == 1.0 && left == 1.0 || mod(x.y, 2.0) == 0.0 && left == 0.0) - Mask *= bright; - - return Mask; - } - - else return vec3(1.0, 1.0, 1.0); -} - -float SlotMask(vec2 pos, vec3 c) -{ - if (slotmask == 0.0) return 1.0; - - pos = floor(pos / slotms); - float mx = pow(max(max(c.r, c.g), c.b), 1.33); - float mlen = slotwidth * 2.0; - float px = fract(pos.x / mlen); - float py = floor(fract(pos.y / (2.0 * double_slot)) * 2.0 * double_slot); - float slot_dark = mix(1.0 - slotmask, 1.0 - 0.80 * slotmask, mx); - float slot = 1.0 + 0.7 * slotmask * (1.0 - mx); - - if (py == 0.0 && px < 0.5) slot = slot_dark; - else if (py == double_slot && px >= 0.5) slot = slot_dark; - - return slot; -} - -mat4 contrastMatrix(float contrast) -{ - float t = (1.0 - contrast) / 2.0; - - return mat4(contrast, 0, 0, 0, - 0, contrast, 0, 0, - 0, 0, contrast, 0, - t, t, t, 1); -} - -mat3 vign(float l) -{ -// vec2 vpos = vTexCoord; - vec2 vpos = GetCoordinates(); - vpos *= 1.0 - vpos.xy; - - float vig = vpos.x * vpos.y * vstr; - vig = min(pow(vig, vpower), 1.0); - if (vignette == 0.0) vig = 1.0; - - return mat3(vig, 0, 0, - 0, vig, 0, - 0, 0, vig); -} - -vec3 saturation(vec3 textureColor) -{ - float luminance = length(textureColor.rgb) * 0.5775; - - vec3 luminanceWeighting = vec3(0.4, 0.5, 0.1); - if (luminance < 0.5) luminanceWeighting.rgb = (luminanceWeighting.rgb * luminanceWeighting.rgb) - + (luminanceWeighting.rgb * luminanceWeighting.rgb); - - luminance = dot(textureColor.rgb, luminanceWeighting); - vec3 greyScaleColor = vec3(luminance, luminance, luminance); - - vec3 res = vec3(mix(greyScaleColor, textureColor.rgb, sat)); - return res; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////// - -vec3 glow0 (vec2 texcoord, vec3 col) -{ - - // the more quality, the smaller the offset and better quality, less visible glow too - vec2 size = SourceSize.zw/quality; - - vec3 c01; - vec3 sum = vec3(0.0); - - // glow = pixels per axis, the more the slower! - - for (float x = -glow; x <= glow; x = x+1.0) - { - - // multiply texture, the more far away the less pronounced - float factor = 1.0/glow; - for (float y = -glow; y <= glow; y = y+1.0) - { - - vec2 offset = vec2(x, y) * size; - - c01 = SampleLocation(texcoord + offset).rgb*factor; c01 = c01*c01; - - sum += c01; - } - } - - return (glow_str * sum / (glow * glow )) ; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////// - -float noise(vec2 co) -{ - return fract(sin(iTimer * dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); -} - -float corner0(vec2 coord) -{ - coord = (coord - vec2(0.5, 0.5)) * 1.0 + vec2(0.5, 0.5); - coord = min(coord, vec2(1.0, 1.0) - coord) * vec2(1.0, SourceSize.y / SourceSize.x); - - vec2 cdist = vec2(corner, corner); - coord = (cdist - min(coord, cdist)); - float dist = sqrt(dot(coord, coord)); - - return clamp((cdist.x - dist) * smoothness, 0.0, 1.0); -} - -const mat3 D65_to_XYZ = mat3( - 0.4306190, 0.2220379, 0.0201853, - 0.3415419, 0.7066384, 0.1295504, - 0.1783091, 0.0713236, 0.9390944); - -const mat3 XYZ_to_D65 = mat3( - 3.0628971, -0.9692660, 0.0678775, - -1.3931791, 1.8760108, -0.2288548, - -0.4757517, 0.0415560, 1.0693490); - -const mat3 D50_to_XYZ = mat3( - 0.4552773, 0.2323025, 0.0145457, - 0.3675500, 0.7077956, 0.1049154, - 0.1413926, 0.0599019, 0.7057489); - -const mat3 XYZ_to_D50 = mat3( - 2.9603944, -0.9787684, 0.0844874, - -1.4678519, 1.9161415, -0.2545973, - -0.4685105, 0.0334540, 1.4216174); - -void main() -{ - vec2 vTexCoord = GetCoordinates(); - vec2 pos = Warp(vTexCoord.xy); - vec2 tex_size = 1.0 / GetInvNativePixelSize(); - vec2 OutputSize = GetWindowSize(); - - - vec2 pC4 = (pos + 0.5/tex_size); - vec2 fp = fract(pos * tex_size); - if (inter < 0.5 && tex_size.y > 400.0){ fp.y = fract(pos.y * tex_size.y*1.0/Downscale);} - - vec4 res = vec4(1.0); - - if (alloff == 1.0) - res = SampleLocation(pC4); - else - { - - vec2 texel = pos * tex_size; - vec2 texel_floored = floor(texel); - - float scale = PRE_SCALE; - float region_range = 0.5 - 0.5 / scale; - - // Figure out where in the texel to sample to get correct pre-scaled bilinear. - // Uses the hardware bilinear interpolator to avoid having to sample 4 times manually. - - vec2 center_dist = fp - 0.5; - - vec2 fpp = (center_dist - clamp(center_dist, -region_range, region_range)) * scale + 0.5; - - vec2 mod_texel = texel_floored + fpp; - vec2 coords = mod_texel / SourceSize.xy; - - vec3 sample1 = SampleLocation(vec2(coords.x + blurx*SourceSize.z, coords.y - blury*SourceSize.w)).rgb; - vec3 sample2 = SampleLocation(coords).rgb; - vec3 sample3 = SampleLocation(vec2(coords.x - blurx*SourceSize.z, coords.y + blury*SourceSize.w )).rgb; - - vec3 color = vec3(sample1.r * 0.5 + sample2.r * 0.5, - sample1.g * 0.25 + sample2.g * 0.5 + sample3.g * 0.25, - sample2.b * 0.5 + sample3.b * 0.5); - if (palette_fix != 0.0) - { - if (palette_fix == 1.0) color = color* 1.0667; - else if (palette_fix == 2.0) color = color * 2.0; - } - - //COLOR TEMPERATURE FROM GUEST.R-DR.VENOM - if (WP != 0.0) - { - vec3 warmer = D50_to_XYZ * color; - warmer = XYZ_to_D65 * warmer; - - vec3 cooler = D65_to_XYZ * color; - cooler = XYZ_to_D50 * cooler; - - float m = abs(WP) / 100.0; - vec3 comp = (WP < 0.0) ? cooler : warmer; - comp = clamp(comp, 0.0, 1.0); - - color = vec3(mix(color, comp, m)); - } - - mat3 hue = mat3 (1., rg, rb, //red tint - gr, 1., gb, //green tint - br, bg, 1.); //blue tint - - color = hue * color; - - color = (2.0*pow(color,vec3(2.8))) - pow(color,vec3(3.6)); - - float lum = color.r * 0.3 + color.g * 0.6 + color.b * 0.1; - - float f = fract(fp.y -0.5); - - if (inter > 0.5 && tex_size.y > 400.0) color = color; - else - {color = color * sw(f,lum) + color * sw (1.0-f,lum);} - - float lum1 = color.r * 0.3 + color.g * 0.6 + color.b * 0.1; - - - color *= mix(mask((vTexCoord * OutputSize.xy), color,lum1), vec3(1.0), lum1*preserve); - - - if (slotmask != 0.0) color *= SlotMask((vTexCoord * OutputSize.xy) * 1.0001, color); - - color *= mix(brightboost1, brightboost2, max(max(color.r, color.g), color.b)); - - - - color = pow(color,vec3(1.0 / GAMMA_OUT)); - if (glow_str != 0.0) color += glow0(coords,color); - - if (sat != 1.0) color = saturation(color); - if (corner != 0.0) color *= corner0(pC4); - if (nois != 0.0) color *= 1.0 + noise(coords * 2.0) / nois; - - color *= mix(1.0, postbr, lum); - res = vec4(color, 1.0); - if (contrast != 1.0) res = contrastMatrix(contrast) * res; - if (inter > 0.5 && SourceSize.y > 400.0 && fract(iTime) < 0.5) res = res * 0.95; - res.rgb *= vign(lum); - - } - - SetOutput(res); -} diff --git a/data/resources/shaders/reshade/Shaders/crt/crt-consumer.fx b/data/resources/shaders/reshade/Shaders/crt/crt-consumer.fx new file mode 100644 index 000000000..25a61de2d --- /dev/null +++ b/data/resources/shaders/reshade/Shaders/crt/crt-consumer.fx @@ -0,0 +1,797 @@ +#include "ReShade.fxh" + + +/* + CRT-Consumer + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + + + +uniform float PRE_SCALE < + ui_type = "drag"; + ui_min = 1.0; + ui_max = 4.0; + ui_step = 0.1; + ui_label = "Pre-Scale Sharpening"; +> = 1.5; + +uniform float blurx < + ui_type = "drag"; + ui_min = -4.0; + ui_max = 4.0; + ui_step = 0.05; + ui_label = "Convergence X"; +> = 0.25; + +uniform float blury < + ui_type = "drag"; + ui_min = -4.0; + ui_max = 4.0; + ui_step = 0.05; + ui_label = "Convergence Y"; +> = -0.1; + +uniform float warpx < + ui_type = "drag"; + ui_min = 0.0; + ui_max = 0.12; + ui_step = 0.01; + ui_label = " Curvature X"; +> = 0.03; + +uniform float warpy < + ui_type = "drag"; + ui_min = 0.0; + ui_max = 0.12; + ui_step = 0.01; + ui_label = " Curvature Y"; +> = 0.04; + +uniform float corner < + ui_type = "drag"; + ui_min = 0.0; + ui_max = 0.10; + ui_step = 0.01; + ui_label = " Corner size"; +> = 0.03; + +uniform float smoothness < + ui_type = "drag"; + ui_min = 100.0; + ui_max = 600.0; + ui_step = 5.0; + ui_label = " Border Smoothness"; +> = 400.0; + +uniform bool inter < + ui_type = "radio"; + ui_label = "Interlacing Toggle"; +> = true; + +uniform float Downscale < + ui_type = "drag"; + ui_min = 1.0; + ui_max = 8.0; + ui_step = 1.; + ui_label = "Interlacing Downscale Scanlines"; +> = 2.0; + +uniform float scanlow < + ui_type = "drag"; + ui_min = 1.0; + ui_max = 15.0; + ui_step = 1.0; + ui_label = "Beam low"; +> = 6.0; + +uniform float scanhigh < + ui_type = "drag"; + ui_min = 1.0; + ui_max = 15.0; + ui_step = 1.0; + ui_label = "Beam high"; +> = 8.0; + +uniform float beamlow < + ui_type = "drag"; + ui_min = 0.5; + ui_max = 2.5; + ui_step = 0.0; + ui_label = "Scanlines dark"; +> = 1.45; + +uniform float beamhigh < + ui_type = "drag"; + ui_min = 0.5; + ui_max = 2.5; + ui_step = 0.0; + ui_label = "Scanlines bright"; +> = 1.05; + +uniform float preserve < + ui_type = "drag"; + ui_min = 0.0; + ui_max = 1.0; + ui_step = 0.01; + ui_label = "Protect White On Masks"; +> = 0.98; + +uniform float brightboost1 < + ui_type = "drag"; + ui_min = 0.0; + ui_max = 3.0; + ui_step = 0.05; + ui_label = "Bright boost dark pixels"; +> = 1.25; + +uniform float brightboost2 < + ui_type = "drag"; + ui_min = 0.0; + ui_max = 3.0; + ui_step = 0.05; + ui_label = "Bright boost bright pixels"; +> = 1.0; + +uniform float glow < + ui_type = "drag"; + ui_min = 1.0; + ui_max = 6.0; + ui_step = 1.0; + ui_label = "Glow pixels per axis"; +> = 3.0; + +uniform float quality < + ui_type = "drag"; + ui_min = 0.25; + ui_max = 4.0; + ui_step = 0.05; + ui_label = "Glow quality"; +> = 1.0; + +uniform float glow_str < + ui_type = "drag"; + ui_min = 0.0001; + ui_max = 2.0; + ui_step = 0.05; + ui_label = "Glow intensity"; +> = 0.3; + +uniform float nois < + ui_type = "drag"; + ui_min = 0.0; + ui_max = 32.0; + ui_step = 1.0; + ui_label = "Add Noise"; +> = 0.0; + +uniform float postbr < + ui_type = "drag"; + ui_min = 0.0; + ui_max = 2.5; + ui_step = 0.02; + ui_label = "Post Brightness"; +> = 1.0; + +uniform float palette_fix < + ui_type = "drag"; + ui_min = 0.0; + ui_max = 2.0; + ui_step = 1.0; + ui_label = "Palette Fixes. Sega, PUAE Atari ST dark colors"; +> = 0.0; + +uniform float Shadowmask < + ui_type = "drag"; + ui_min = -1.0; + ui_max = 8.0; + ui_step = 1.; + ui_label = "Mask Type"; +> = 0.0; + +uniform float masksize < + ui_type = "drag"; + ui_min = 1.0; + ui_max = 2.0; + ui_step = 1.0; + ui_label = "Mask Size"; +> = 1.0; + +uniform float MaskDark < + ui_type = "drag"; + ui_min = 0.0; + ui_max = 2.0; + ui_step = 0.1; + ui_label = "Mask dark"; +> = 0.2; + +uniform float MaskLight < + ui_type = "drag"; + ui_min = 0.0; + ui_max = 2.0; + ui_step = 0.1; + ui_label = "Mask light"; +> = 1.5; + +uniform float slotmask < + ui_type = "drag"; + ui_min = 0.0; + ui_max = 1.0; + ui_step = 0.05; + ui_label = "Slot Mask Strength"; +> = 0.0; + +uniform float slotwidth < + ui_type = "drag"; + ui_min = 1.0; + ui_max = 6.0; + ui_step = 0.5; + ui_label = "Slot Mask Width"; +> = 2.0; + +uniform float double_slot < + ui_type = "drag"; + ui_min = 1.0; + ui_max = 2.0; + ui_step = 1.0; + ui_label = "Slot Mask Height: 2x1 or 4x1"; +> = 1.0; + +uniform float slotms < + ui_type = "drag"; + ui_min = 1.0; + ui_max = 2.0; + ui_step = 1.0; + ui_label = "Slot Mask Size"; +> = 1.0; + +uniform float GAMMA_OUT < + ui_type = "drag"; + ui_min = 0.0; + ui_max = 4.0; + ui_step = 0.05; + ui_label = "Gamma Out"; +> = 2.25; + +uniform float sat < + ui_type = "drag"; + ui_min = 0.0; + ui_max = 2.0; + ui_step = 0.05; + ui_label = "Saturation"; +> = 1.0; + +uniform float contrast < + ui_type = "drag"; + ui_min = 0.00; + ui_max = 2.00; + ui_step = 0.05; + ui_label = "Contrast, 1.0:Off"; +> = 1.0; + +uniform float WP < + ui_type = "drag"; + ui_min = -100.0; + ui_max = 100.0; + ui_step = 5.; + ui_label = "Color Temperature %"; +> = 0.0; + +uniform float rg < + ui_type = "drag"; + ui_min = -1.0; + ui_max = 1.0; + ui_step = 0.005; + ui_label = "Red-Green Tint"; +> = 0.0; + +uniform float rb < + ui_type = "drag"; + ui_min = -1.0; + ui_max = 1.0; + ui_step = 0.005; + ui_label = "Red-Blue Tint"; +> = 0.0; + +uniform float gr < + ui_type = "drag"; + ui_min = -1.0; + ui_max = 1.0; + ui_step = 0.005; + ui_label = "Green-Red Tint"; +> = 0.0; + +uniform float gb < + ui_type = "drag"; + ui_min = -1.0; + ui_max = 1.0; + ui_step = 0.005; + ui_label = "Green-Blue Tint"; +> = 0.0; + +uniform float br < + ui_type = "drag"; + ui_min = -1.0; + ui_max = 1.0; + ui_step = 0.005; + ui_label = "Blue-Red Tint"; +> = 0.0; + +uniform float bg < + ui_type = "drag"; + ui_min = -1.0; + ui_max = 1.0; + ui_step = 0.005; + ui_label = "Blue-Green Tint"; +> = 0.0; + +uniform bool vignette < + ui_type = "radio"; + ui_label = "Vignette On/Off"; +> = false; + +uniform float vpower < + ui_type = "drag"; + ui_min = 0.0; + ui_max = 1.0; + ui_step = 0.01; + ui_label = "Vignette Power"; +> = 0.15; + +uniform float vstr < + ui_type = "drag"; + ui_min = 0.0; + ui_max = 50.0; + ui_step = 1.0; + ui_label = "Vignette strength"; +> = 40.0; + +uniform bool alloff < + ui_type = "radio"; + ui_label = "Switch off shader"; +> = false; + + +uniform float FrameCount < source = "framecount"; >; +uniform float2 BufferToViewportRatio < source = "buffer_to_viewport_ratio"; >; +uniform float2 NormalizedNativePixelSize < source = "normalized_native_pixel_size"; >; +uniform float2 ViewportSize < source = "viewportsize"; >; +uniform float ViewportX < source = "viewportx"; >; +uniform float ViewportY < source = "viewporty"; >; +uniform float ViewportWidth < source = "viewportwidth"; >; +uniform float ViewportHeight < source = "viewportheight"; >; +uniform float2 ViewportOffset < source = "viewportoffset"; >; +uniform float BufferWidth < source = "bufferwidth"; >; +uniform float BufferHeight < source = "bufferheight"; >; +uniform float NativeWidth < source = "nativewidth"; >; +uniform float NativeHeight < source = "nativeheight"; >; +uniform float InternalWidth < source = "internalwidth"; >; +uniform float InternalHeight < source = "internalheight"; >; + +sampler2D sBackBuffer{Texture=ReShade::BackBufferTex;AddressU=CLAMP;AddressV=CLAMP;AddressW=CLAMP;MagFilter=POINT;MinFilter=POINT;}; + +#define iTime (float(FrameCount)/2.0) +#define iTimer (float(FrameCount)/60.0) + +#define SourceSize (float4(1.0/NormalizedNativePixelSize,NormalizedNativePixelSize)) +#define OutputSize (ViewportSize*BufferToViewportRatio) + +float2 Warp(float2 pos) +{ + pos = pos * 2.0 - 1.0; + pos *= float2(1.0 + (pos.y * pos.y) * warpx, 1.0 + (pos.x * pos.x) * warpy); + return pos * 0.5 + 0.5; +} + +float sw(float y, float l) +{ + float beam = lerp(scanlow, scanhigh, y); + float scan = lerp(beamlow, beamhigh, l); + float ex = y * scan; + return exp2(-beam * ex * ex); +} + +float3 mask(float2 x, float3 col, float l) +{ + x = floor(x / masksize); + + if (Shadowmask == 0.0) + { + float m = frac(x.x * 0.4999); + if (m < 0.4999) return float3(1.0, MaskDark, 1.0); + else return float3(MaskDark, 1.0, MaskDark); + } + + else if (Shadowmask == 1.0) + { + float3 Mask = float3(MaskDark, MaskDark, MaskDark); + float line = MaskLight; + float odd = 0.0; + + if (frac(x.x / 6.0) < 0.5) odd = 1.0; + if (frac((x.y + odd) / 2.0) < 0.5) line = MaskDark; + + float m = frac(x.x / 3.0); + if (m < 0.333) Mask.b = MaskLight; + else if (m < 0.666) Mask.g = MaskLight; + else Mask.r = MaskLight; + + Mask *= line; + return Mask; + } + + else if (Shadowmask == 2.0) + { + float m = frac(x.x*0.3333); + if (m < 0.3333) return float3(MaskDark, MaskDark, MaskLight); + if (m < 0.6666) return float3(MaskDark, MaskLight, MaskDark); + else return float3(MaskLight, MaskDark, MaskDark); + } + + if (Shadowmask == 3.0) + { + float m = frac(x.x * 0.5); + if (m < 0.5) return float3(1.0, 1.0, 1.0); + else return float3(MaskDark, MaskDark, MaskDark); + } + + else if (Shadowmask == 4.0) + { + float3 Mask = float3(col.rgb); + float line = MaskLight; + float odd = 0.0; + + if (frac(x.x / 4.0) < 0.5) odd = 1.0; + if (frac((x.y + odd) / 2.0) < 0.5) line = MaskDark; + + float m = frac(x.x / 2.0); + if (m < 0.5) { Mask.r = 1.0; Mask.b = 1.0; } + else Mask.g = 1.0; + + Mask *= line; + return Mask; + } + + else if (Shadowmask == 5.0) + { + float3 Mask = float3(1.0, 1.0, 1.0); + + if (frac(x.x / 4.0) < 0.5) + { + if (frac(x.y / 3.0) < 0.666) + { + if (frac(x.x / 2.0) < 0.5) Mask = float3(1.0, MaskDark, 1.0); + else Mask = float3(MaskDark, 1.0, MaskDark); + } + else Mask *= l; + } + else if (frac(x.x / 4.0) >= 0.5) + { + if (frac(x.y / 3.0) > 0.333) + { + if (frac(x.x / 2.0) < 0.5) Mask = float3(1.0, MaskDark, 1.0); + else Mask = float3(MaskDark, 1.0, MaskDark); + } + else Mask *= l; + } + + return Mask; + } + + else if (Shadowmask == 6.0) + { + float3 Mask = float3(MaskDark, MaskDark, MaskDark); + if (frac(x.x / 6.0) < 0.5) + { + if (frac(x.y / 4.0) < 0.75) + { + if (frac(x.x / 3.0) < 0.3333) Mask.r = MaskLight; + else if (frac(x.x / 3.0) < 0.6666) Mask.g = MaskLight; + else Mask.b = MaskLight; + } + else Mask * l * 0.9; + } + else if (frac(x.x / 6.0) >= 0.5) + { + if (frac(x.y / 4.0) >= 0.5 || frac(x.y / 4.0) < 0.25) + { + if (frac(x.x / 3.0) < 0.3333) Mask.r = MaskLight; + else if (frac(x.x / 3.0) < 0.6666) Mask.g = MaskLight; + else Mask.b = MaskLight; + } + else Mask * l * 0.9; + } + return Mask; + } + + else if (Shadowmask == 7.0) + { + float m = frac(x.x * 0.3333); + + if (m < 0.3333) return float3(MaskDark, MaskLight, MaskLight * col.b); //Cyan + if (m < 0.6666) return float3(MaskLight * col.r, MaskDark, MaskLight); //Magenta + else return float3(MaskLight, MaskLight * col.g, MaskDark); //Yellow + } + + else if (Shadowmask == 8.0) + { + float3 Mask = float3(MaskDark, MaskDark, MaskDark); + + float bright = MaskLight; + float left = 0.0; + if (frac(x.x / 6.0) < 0.5) left = 1.0; + + float m = frac(x.x / 3.0); + if (m < 0.333) Mask.b = 0.9; + else if (m < 0.666) Mask.g = 0.9; + else Mask.r = 0.9; + + if ((x.y % 2.0) == 1.0 && left == 1.0 || (x.y % 2.0) == 0.0 && left == 0.0) + Mask *= bright; + + return Mask; + } + + else return float3(1.0, 1.0, 1.0); +} + +float SlotMask(float2 pos, float3 c) +{ + if (slotmask == 0.0) return 1.0; + + pos = floor(pos / slotms); + float mx = pow(max(max(c.r, c.g), c.b), 1.33); + float mlen = slotwidth * 2.0; + float px = frac(pos.x / mlen); + float py = floor(frac(pos.y / (2.0 * double_slot)) * 2.0 * double_slot); + float slot_dark = lerp(1.0 - slotmask, 1.0 - 0.80 * slotmask, mx); + float slot = 1.0 + 0.7 * slotmask * (1.0 - mx); + + if (py == 0.0 && px < 0.5) slot = slot_dark; + else if (py == double_slot && px >= 0.5) slot = slot_dark; + + return slot; +} + +float4x4 contrastMatrix(float contrast) +{ + float t = (1.0 - contrast) / 2.0; + + return float4x4(contrast, 0, 0, 0, + 0, contrast, 0, 0, + 0, 0, contrast, 0, + t, t, t, 1); +} + +float3x3 vign(float l, float2 tex) +{ + float2 vpos = tex; + vpos *= 1.0 - vpos.xy; + + float vig = vpos.x * vpos.y * vstr; + vig = min(pow(vig, vpower), 1.0); + if (vignette == false) vig = 1.0; + + return float3x3(vig, 0, 0, + 0, vig, 0, + 0, 0, vig); +} + +float3 saturation(float3 textureColor) +{ + float luminance = length(textureColor.rgb) * 0.5775; + + float3 luminanceWeighting = float3(0.4, 0.5, 0.1); + if (luminance < 0.5) luminanceWeighting.rgb = (luminanceWeighting.rgb * luminanceWeighting.rgb) + + (luminanceWeighting.rgb * luminanceWeighting.rgb); + + luminance = dot(textureColor.rgb, luminanceWeighting); + float3 greyScaleColor = float3(luminance, luminance, luminance); + + float3 res = float3(lerp(greyScaleColor, textureColor.rgb, sat)); + return res; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// + +float3 glow0 (float2 texcoord, float3 col) +{ + + // the more quality, the smaller the offset and better quality, less visible glow too + float2 size = SourceSize.zw/quality; + + float3 c01; + float3 sum = float3(0.0, 0.0, 0.0); + + // glow = pixels per axis, the more the slower! + + for (float x = -glow; x <= glow; x = x+1.0) + { + + // multiply texture, the more far away the less pronounced + float factor = 1.0/glow; + for (float y = -glow; y <= glow; y = y+1.0) + { + + float2 offset = float2(x, y) * size; + + c01 = tex2D(sBackBuffer, texcoord + offset).rgb*factor; c01 = c01*c01; + + sum += c01; + } + } + + return (glow_str * sum / (glow * glow )) ; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// + +float noise(float2 co) +{ + return frac(sin(iTimer * dot(co.xy ,float2(12.9898,78.233))) * 43758.5453); +} + +float corner0(float2 coord) +{ + coord = (coord - float2(0.5, 0.5)) * 1.0 + float2(0.5, 0.5); + coord = min(coord, float2(1.0, 1.0) - coord) * float2(1.0, SourceSize.y / SourceSize.x); + + float2 cdist = float2(corner, corner); + coord = (cdist - min(coord, cdist)); + float dist = sqrt(dot(coord, coord)); + + return clamp((cdist.x - dist) * smoothness, 0.0, 1.0); +} + +static const float3x3 D65_to_XYZ = float3x3( + 0.4306190, 0.2220379, 0.0201853, + 0.3415419, 0.7066384, 0.1295504, + 0.1783091, 0.0713236, 0.9390944); + +static const float3x3 XYZ_to_D65 = float3x3( + 3.0628971, -0.9692660, 0.0678775, + -1.3931791, 1.8760108, -0.2288548, + -0.4757517, 0.0415560, 1.0693490); + +static const float3x3 D50_to_XYZ = float3x3( + 0.4552773, 0.2323025, 0.0145457, + 0.3675500, 0.7077956, 0.1049154, + 0.1413926, 0.0599019, 0.7057489); + +static const float3x3 XYZ_to_D50 = float3x3( + 2.9603944, -0.9787684, 0.0844874, + -1.4678519, 1.9161415, -0.2545973, + -0.4685105, 0.0334540, 1.4216174); + + +float4 PS_CRT_CONSUMER(float4 vpos: SV_Position, float2 vTexCoord : TEXCOORD0) : SV_Target +{ + float2 pos = Warp(vTexCoord.xy); + float2 tex_size = SourceSize.xy; + + float2 pC4 = (pos + 0.5/tex_size); + float2 fp = frac(pos * tex_size); + if (inter == false && tex_size.y > 400.0){ fp.y = frac(pos.y * tex_size.y*1.0/Downscale);} + + float4 res = float4(1.0, 1.0, 1.0, 1.0); + + if (alloff == true) + res = tex2D(sBackBuffer, pC4); + else + { + + float2 texel = pos * tex_size; + float2 texel_floored = floor(texel); + + float scale = PRE_SCALE; + float region_range = 0.5 - 0.5 / scale; + + // Figure out where in the texel to sample to get correct pre-scaled bilinear. + // Uses the hardware bilinear interpolator to avoid having to sample 4 times manually. + + float2 center_dist = fp - 0.5; + + float2 fpp = (center_dist - clamp(center_dist, -region_range, region_range)) * scale + 0.5; + + float2 mod_texel = texel_floored + fpp; + float2 coords = mod_texel / SourceSize.xy; + + float3 sample1 = tex2D(sBackBuffer, float2(coords.x + blurx*SourceSize.z, coords.y - blury*SourceSize.w)).rgb; + float3 sample2 = tex2D(sBackBuffer, coords).rgb; + float3 sample3 = tex2D(sBackBuffer, float2(coords.x - blurx*SourceSize.z, coords.y + blury*SourceSize.w )).rgb; + + float3 color = float3(sample1.r * 0.5 + sample2.r * 0.5, + sample1.g * 0.25 + sample2.g * 0.5 + sample3.g * 0.25, + sample2.b * 0.5 + sample3.b * 0.5); + if (palette_fix != 0.0) + { + if (palette_fix == 1.0) color = color* 1.0667; + else if (palette_fix == 2.0) color = color * 2.0; + } + + //COLOR TEMPERATURE FROM GUEST.R-DR.VENOM + if (WP != 0.0) + { + float3 warmer = mul(color, D50_to_XYZ); + warmer = mul(warmer, XYZ_to_D65); + + float3 cooler = mul(color, D65_to_XYZ); + cooler = mul(cooler, XYZ_to_D50); + + float m = abs(WP) / 100.0; + float3 comp = (WP < 0.0) ? cooler : warmer; + comp = clamp(comp, 0.0, 1.0); + + color = float3(lerp(color, comp, m)); + } + + float3x3 hue = float3x3 (1., rg, rb, //red tint + gr, 1., gb, //green tint + br, bg, 1.); //blue tint + + color = mul(color, hue); + + color = (2.0*pow(color,float3(2.8, 2.8, 2.8))) - pow(color,float3(3.6, 3.6, 3.6)); + + float lum = color.r * 0.3 + color.g * 0.6 + color.b * 0.1; + + float f = frac(fp.y -0.5); + + if (inter == true && tex_size.y > 400.0) color = color; + else + {color = color * sw(f,lum) + color * sw (1.0-f,lum);} + + float lum1 = color.r * 0.3 + color.g * 0.6 + color.b * 0.1; + + + color *= lerp(mask((vTexCoord * OutputSize.xy), color,lum1), float3(1.0, 1.0, 1.0), lum1*preserve); + + + if (slotmask != 0.0) color *= SlotMask((vTexCoord * OutputSize.xy) * 1.0001, color); + + color *= lerp(brightboost1, brightboost2, max(max(color.r, color.g), color.b)); + + + + color = pow(color,float3(1.0 / GAMMA_OUT, 1.0 / GAMMA_OUT, 1.0 / GAMMA_OUT)); + if (glow_str != 0.0) color += glow0(coords,color); + + if (sat != 1.0) color = saturation(color); + if (corner != 0.0) color *= corner0(pC4); + if (nois != 0.0) color *= 1.0 + noise(coords * 2.0) / nois; + + color *= lerp(1.0, postbr, lum); + res = float4(color, 1.0); + if (contrast != 1.0) res = mul(res, contrastMatrix(contrast)); + if (inter == true && SourceSize.y > 400.0 && frac(iTime) < 0.5) res = res * 0.95; + res.rgb = mul(res.rgb, vign(lum, vTexCoord)); + + } + + return res; +} + + + +technique CRT_CONSUMER +{ + pass + { + VertexShader = PostProcessVS; + PixelShader = PS_CRT_CONSUMER; + } +} diff --git a/data/resources/shaders/reshade/Shaders/crt/crt-geom.fx b/data/resources/shaders/reshade/Shaders/crt/crt-geom.fx index ff82558cc..807fffdd2 100644 --- a/data/resources/shaders/reshade/Shaders/crt/crt-geom.fx +++ b/data/resources/shaders/reshade/Shaders/crt/crt-geom.fx @@ -52,16 +52,13 @@ uniform bool CURVATURE < ui_category = "Curvature"; ui_type = "radio"; ui_label = "CRTGeom Curvature Toggle"; -> = 1.0; +> = true; -uniform float invert_aspect < - ui_type = "drag"; +uniform bool invert_aspect < + ui_type = "radio"; ui_category = "Curvature"; - ui_min = 0.0; - ui_max = 1.0; - ui_step = 1.0; ui_label = "CRTGeom Curvature Aspect Inversion"; -> = 0.0; +> = false; uniform float R < ui_type = "drag"; @@ -93,8 +90,8 @@ uniform float cornersmooth < uniform float x_tilt < ui_type = "drag"; ui_category = "Curvature"; - ui_min = -0.5; - ui_max = 0.5; + ui_min = -1.0; + ui_max = 1.0; ui_step = 0.05; ui_label = "CRTGeom Horizontal Tilt"; > = 0.0; @@ -102,8 +99,8 @@ uniform float x_tilt < uniform float y_tilt < ui_type = "drag"; ui_category = "Curvature"; - ui_min = -0.5; - ui_max = 0.5; + ui_min = -1.0; + ui_max = 1.0; ui_step = 0.05; ui_label = "CRTGeom Vertical Tilt"; > = 0.0; @@ -125,19 +122,19 @@ uniform float overscan_y < > = 100.0; uniform float centerx < - ui_type = "drag"; - ui_min = -9.99; - ui_max = 9.99; - ui_step = 0.01; - ui_label = "Image Center X"; + ui_type = "drag"; + ui_min = -100.0; + ui_max = 100.0; + ui_step = 0.1; + ui_label = "Image Center X"; > = 0.00; uniform float centery < - ui_type = "drag"; - ui_min = -9.99; - ui_max = 9.99; - ui_step = 0.01; - ui_label = "Image Center Y"; + ui_type = "drag"; + ui_min = -100.0; + ui_max = 100.0; + ui_step = 0.1; + ui_label = "Image Center Y"; > = 0.00; uniform float DOTMASK < @@ -164,13 +161,10 @@ uniform float scanline_weight < ui_label = "CRTGeom Scanline Weight"; > = 0.3; -uniform float vertical_scanlines < - ui_type = "drag"; - ui_min = 0.0; - ui_max = 1.0; - ui_step = 1.0; +uniform bool vertical_scanlines < + ui_type = "radio"; ui_label = "CRTGeom Vertical Scanlines"; -> = 0.0; +> = false; uniform float lum < ui_type = "drag"; @@ -191,13 +185,15 @@ uniform float interlace_detect < uniform float FrameCount < source = "framecount"; >; -uniform float2 BufferViewportRatio < source = "buffer_to_viewport_ratio"; >; +uniform float2 BufferToViewportRatio < source = "buffer_to_viewport_ratio"; >; uniform float2 InternalPixelSize < source = "internal_pixel_size"; >; uniform float2 NativePixelSize < source = "native_pixel_size"; >; uniform float2 NormalizedInternalPixelSize < source = "normalized_internal_pixel_size"; >; uniform float2 NormalizedNativePixelSize < source = "normalized_native_pixel_size"; >; uniform float UpscaleMultiplier < source = "upscale_multiplier"; >; uniform float2 ViewportSize < source = "viewportsize"; >; +uniform float ViewportWidth < source = "viewportwidth"; >; +uniform float ViewportHeight < source = "viewportheight"; >; sampler2D sBackBuffer{Texture=ReShade::BackBufferTex;AddressU=BORDER;AddressV=BORDER;AddressW=BORDER;MagFilter=POINT;MinFilter=POINT;}; @@ -222,7 +218,7 @@ sampler2D sBackBuffer{Texture=ReShade::BackBufferTex;AddressU=BORDER;AddressV=BO #endif // aspect ratio -#define aspect (invert_aspect>0.5?float2(0.75,1.0):float2(1.0,0.75)) +#define aspect (invert_aspect==true?float2(ViewportHeight/ViewportWidth,1.0):float2(1.0,ViewportHeight/ViewportWidth)) #define overscan (float2(1.01,1.01)); @@ -311,7 +307,7 @@ void VS_CRT_Geom(in uint id : SV_VertexID, out float4 position : SV_Position, ou texcoord = Warp(texcoord - float2(centerx,centery)/100.0); float2 SourceSize = 1.0/NormalizedNativePixelSize; - float2 OutputSize = ViewportSize*BufferViewportRatio; + float2 OutputSize = ViewportSize*BufferToViewportRatio; // Precalculate a bunch of useful values we'll need in the fragment // shader. @@ -319,7 +315,7 @@ void VS_CRT_Geom(in uint id : SV_VertexID, out float4 position : SV_Position, ou vVARS.cosangle = cos(float2(x_tilt, y_tilt)); vVARS.stretch = vs_maxscale(vVARS.sinangle, vVARS.cosangle); - if(vertical_scanlines < 0.5) + if(vertical_scanlines == false) { vVARS.TextureSize = float2(SHARPER * SourceSize.x, SourceSize.y); @@ -350,7 +346,7 @@ float intersect(float2 xy, float2 sinangle, float2 cosangle) float A = dot(xy,xy) + d*d; float B, C; - if(vertical_scanlines < 0.5) + if(vertical_scanlines == false) { B = 2.0*(R*(dot(xy,sinangle) - d*cosangle.x*cosangle.y) - d*d); C = d*d + 2.0*R*d*cosangle.x*cosangle.y; @@ -387,7 +383,7 @@ float2 fwtrans(float2 uv, float2 sinangle, float2 cosangle) float x = 1.0 - cos(r/R); float D; - if(vertical_scanlines < 0.5) + if(vertical_scanlines == false) D = d/R + x*cosangle.x*cosangle.y + dot(uv,sinangle); else D = d/R + x*cosangle.y*cosangle.x + dot(uv,sinangle); @@ -397,7 +393,7 @@ float2 fwtrans(float2 uv, float2 sinangle, float2 cosangle) float3 maxscale(float2 sinangle, float2 cosangle) { - if(vertical_scanlines < 0.5) + if(vertical_scanlines == false) { float2 c = bkwtrans(-R * sinangle / (1.0 + R/d*cosangle.x*cosangle.y), sinangle, cosangle); float2 a = float2(0.5, 0.5)*aspect; @@ -464,13 +460,12 @@ float2 transform(float2 coord, float2 sinangle, float2 cosangle, float3 stretch) float corner(float2 coord) { - coord = (coord - float2(0.5, 0.5)) * float2(overscan_x / 100.0, overscan_y / 100.0) + float2(0.5, 0.5); coord = min(coord, float2(1.0, 1.0) - coord) * aspect; float2 cdist = float2(cornersize, cornersize); coord = (cdist - min(coord, cdist)); float dist = sqrt(dot(coord, coord)); - if(vertical_scanlines < 0.5) + if(vertical_scanlines == false) return clamp((cdist.x - dist)*cornersmooth, 0.0, 1.0); else return clamp((cdist.y - dist)*cornersmooth, 0.0, 1.0); @@ -508,17 +503,17 @@ float4 PS_CRT_Geom(float4 vpos: SV_Position, float2 vTexCoord : TEXCOORD, in ST_ // Texture coordinates of the texel containing the active pixel. float2 xy; - if (CURVATURE > 0.5) + if (CURVATURE == true) xy = transform(vTexCoord, vVARS.sinangle, vVARS.cosangle, vVARS.stretch); else xy = vTexCoord; - float cval = corner(xy); + float cval = corner((xy-float2(0.5,0.5)) * BufferToViewportRatio + float2(0.5,0.5)); // Of all the pixels that are mapped onto the texel we are // currently rendering, which pixel are we currently rendering? float2 ilvec; - if(vertical_scanlines < 0.5) + if(vertical_scanlines == false) ilvec = float2(0.0, vVARS.ilfac.y * interlace_detect > 1.5 ? (float(FrameCount) % 2.0) : 0.0); else ilvec = float2(vVARS.ilfac.x * interlace_detect > 1.5 ? (float(FrameCount) % 2.0) : 0.0, 0.0); @@ -533,7 +528,7 @@ float4 PS_CRT_Geom(float4 vpos: SV_Position, float2 vTexCoord : TEXCOORD, in ST_ // of various neighbour texels in a scanline on the current // pixel. float4 coeffs; - if(vertical_scanlines < 0.5) + if(vertical_scanlines == false) coeffs = PI * float4(1.0 + uv_ratio.x, uv_ratio.x, 1.0 - uv_ratio.x, 2.0 - uv_ratio.x); else coeffs = PI * float4(1.0 + uv_ratio.y, uv_ratio.y, 1.0 - uv_ratio.y, 2.0 - uv_ratio.y); @@ -551,7 +546,7 @@ float4 PS_CRT_Geom(float4 vpos: SV_Position, float2 vTexCoord : TEXCOORD, in ST_ // scanlines at the horizontal location of the current pixel, // using the Lanczos coefficients above. float4 col, col2; - if(vertical_scanlines < 0.5) + if(vertical_scanlines == false) { col = clamp( mul(coeffs, float4x4( @@ -600,7 +595,7 @@ float4 PS_CRT_Geom(float4 vpos: SV_Position, float2 vTexCoord : TEXCOORD, in ST_ // Calculate the influence of the current and next scanlines on // the current pixel. float4 weights, weights2; - if(vertical_scanlines < 0.5) + if(vertical_scanlines == false) { weights = scanlineWeights(uv_ratio.y, col); weights2 = scanlineWeights(1.0 - uv_ratio.y, col2); diff --git a/data/resources/shaders/reshade/Shaders/edge-smoothing/super-xbr.fx b/data/resources/shaders/reshade/Shaders/edge-smoothing/super-xbr.fx index 72402560a..1f6cb5278 100644 --- a/data/resources/shaders/reshade/Shaders/edge-smoothing/super-xbr.fx +++ b/data/resources/shaders/reshade/Shaders/edge-smoothing/super-xbr.fx @@ -184,7 +184,9 @@ float3 super_xbr(float wp[6], float4 P0, float4 B, float4 C, float4 P1, float4 float4 PS_BackBufferY(float4 pos: SV_Position, float2 vTexCoord : TEXCOORD) : SV_Target { - float3 color = tex2D(ReShade::BackBuffer, vTexCoord.xy).rgb; + float2 tc = (floor(vTexCoord / NormalizedNativePixelSize)+float2(0.5,0.5)) * NormalizedNativePixelSize; + + float3 color = tex2D(ReShade::BackBuffer, tc).rgb; return float4(color, luma(color)); } diff --git a/data/resources/shaders/reshade/Shaders/misc/geom.fx b/data/resources/shaders/reshade/Shaders/misc/geom.fx index 61db0dc6d..1fc96565a 100644 --- a/data/resources/shaders/reshade/Shaders/misc/geom.fx +++ b/data/resources/shaders/reshade/Shaders/misc/geom.fx @@ -76,16 +76,16 @@ uniform float geom_cornersmooth < uniform float geom_x_tilt < ui_type = "drag"; - ui_min = -0.5; - ui_max = 0.5; + ui_min = -1.0; + ui_max = 1.0; ui_step = 0.05; ui_label = "Geom Horizontal Tilt"; > = 0.0; uniform float geom_y_tilt < ui_type = "drag"; - ui_min = -0.5; - ui_max = 0.5; + ui_min = -1.0; + ui_max = 1.0; ui_step = 0.05; ui_label = "Geom Vertical Tilt"; > = 0.0; @@ -108,17 +108,17 @@ uniform float geom_overscan_y < uniform float centerx < ui_type = "drag"; - ui_min = -9.99; - ui_max = 9.99; - ui_step = 0.01; + ui_min = -100.0; + ui_max = 100.0; + ui_step = 0.1; ui_label = "Image Center X"; > = 0.00; uniform float centery < ui_type = "drag"; - ui_min = -9.99; - ui_max = 9.99; - ui_step = 0.01; + ui_min = -100.0; + ui_max = 100.0; + ui_step = 0.1; ui_label = "Image Center Y"; > = 0.00; @@ -147,9 +147,11 @@ uniform float geom_monitor_gamma < > = 2.2; -uniform float2 BufferViewportRatio < source = "buffer_to_viewport_ratio"; >; +uniform float2 BufferToViewportRatio < source = "buffer_to_viewport_ratio"; >; uniform float2 NormalizedNativePixelSize < source = "normalized_native_pixel_size"; >; uniform float2 ViewportSize < source = "viewportsize"; >; +uniform float ViewportWidth < source = "viewportwidth"; >; +uniform float ViewportHeight < source = "viewportheight"; >; sampler2D sBackBuffer{Texture=ReShade::BackBufferTex;AddressU=BORDER;AddressV=BORDER;AddressW=BORDER;MagFilter=LINEAR;MinFilter=LINEAR;}; @@ -174,7 +176,7 @@ sampler2D sBackBuffer{Texture=ReShade::BackBufferTex;AddressU=BORDER;AddressV=BO #endif // aspect ratio -#define aspect (geom_invert_aspect==true?float2(0.75,1.0):float2(1.0,0.75)) +#define aspect (geom_invert_aspect==true?float2(ViewportHeight/ViewportWidth,1.0):float2(1.0,ViewportHeight/ViewportWidth)) #define overscan (float2(1.01,1.01)); @@ -259,8 +261,7 @@ void VS_CRT_Geom(in uint id : SV_VertexID, out float4 position : SV_Position, ou // center screen texcoord = Warp(texcoord - float2(centerx,centery)/100.0); -// float2 SourceSize = 1.0/NormalizedNativePixelSize; - float2 SourceSize = ViewportSize*BufferViewportRatio; + float2 SourceSize = 1.0/NormalizedNativePixelSize; // Precalculate a bunch of useful values we'll need in the fragment // shader. @@ -336,7 +337,6 @@ float2 transform(float2 coord, float2 sinangle, float2 cosangle, float3 stretch) float corner(float2 coord) { - coord = (coord - float2(0.5, 0.5)) * float2(geom_overscan_x / 100.0, geom_overscan_y / 100.0) + float2(0.5, 0.5); coord = min(coord, float2(1.0, 1.0) - coord) * aspect; float2 cdist = float2(geom_cornersize, geom_cornersize); coord = (cdist - min(coord, cdist)); @@ -360,7 +360,7 @@ float4 PS_CRT_Geom(float4 vpos: SV_Position, float2 vTexCoord : TEXCOORD, in ST_ else xy = vTexCoord; - float cval = corner(xy); + float cval = corner((xy-float2(0.5,0.5)) * BufferToViewportRatio + float2(0.5,0.5)); float2 uv_ratio = frac((xy * vVARS.TextureSize - float2(0.5, 0.5)) / vVARS.TextureSize); diff --git a/data/resources/shaders/reshade/Shaders/overlay/geom-overlay.fx b/data/resources/shaders/reshade/Shaders/overlay/geom-overlay.fx new file mode 100644 index 000000000..b41888a77 --- /dev/null +++ b/data/resources/shaders/reshade/Shaders/overlay/geom-overlay.fx @@ -0,0 +1,415 @@ +#include "ReShade.fxh" + +/* + Geom Shader - a modified CRT-Geom without CRT features made to be appended/integrated + into any other shaders and provide curvature/warping/oversampling features. + + Adapted by Hyllian (2024). +*/ + + +/* + CRT-interlaced + + Copyright (C) 2010-2012 cgwg, Themaister and DOLLS + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + (cgwg gave their consent to have the original version of this shader + distributed under the GPL in this message: + + http://board.byuu.org/viewtopic.php?p=26075#p26075 + + "Feel free to distribute my shaders under the GPL. After all, the + barrel distortion code was taken from the Curvature shader, which is + under the GPL." + ) + This shader variant is pre-configured with screen curvature +*/ + + + +uniform bool geom_curvature < + ui_type = "radio"; + ui_label = "Geom Curvature Toggle"; + ui_category = "Curvature"; + ui_tooltip = "This shader only works with Aspect Ratio: Stretch to Fill."; +> = true; + +uniform float geom_R < + ui_type = "drag"; + ui_min = 0.1; + ui_max = 10.0; + ui_step = 0.1; + ui_label = "Geom Curvature Radius"; +> = 10.0; + +uniform float geom_d < + ui_type = "drag"; + ui_min = 0.1; + ui_max = 10.0; + ui_step = 0.1; + ui_label = "Geom Distance"; +> = 10.0; + +uniform bool geom_invert_aspect < + ui_type = "radio"; + ui_label = "Geom Curvature Aspect Inversion"; +> = 0.0; + +uniform float geom_cornersize < + ui_type = "drag"; + ui_min = 0.001; + ui_max = 1.0; + ui_step = 0.005; + ui_label = "Geom Corner Size"; +> = 0.006; + +uniform float geom_cornersmooth < + ui_type = "drag"; + ui_min = 80.0; + ui_max = 2000.0; + ui_step = 100.0; + ui_label = "Geom Corner Smoothness"; +> = 200.0; + +uniform float geom_x_tilt < + ui_type = "drag"; + ui_min = -1.0; + ui_max = 1.0; + ui_step = 0.05; + ui_label = "Geom Horizontal Tilt"; +> = 0.0; + +uniform float geom_y_tilt < + ui_type = "drag"; + ui_min = -1.0; + ui_max = 1.0; + ui_step = 0.05; + ui_label = "Geom Vertical Tilt"; +> = 0.0; + +uniform float geom_overscan_x < + ui_type = "drag"; + ui_min = -125.0; + ui_max = 125.0; + ui_step = 0.5; + ui_label = "Geom Horiz. Overscan %"; +> = 48.5; + +uniform float geom_overscan_y < + ui_type = "drag"; + ui_min = -125.0; + ui_max = 125.0; + ui_step = 0.5; + ui_label = "Geom Vert. Overscan %"; +> = 64.5; + +uniform float centerx < + ui_type = "drag"; + ui_min = -100.0; + ui_max = 100.0; + ui_step = 0.1; + ui_label = "Image Center X"; +> = 0.0; + +uniform float centery < + ui_type = "drag"; + ui_min = -100.0; + ui_max = 100.0; + ui_step = 0.1; + ui_label = "Image Center Y"; +> = -8.8; + +uniform float geom_lum < + ui_type = "drag"; + ui_min = 0.5; + ui_max = 2.0; + ui_step = 0.01; + ui_label = "Geom Luminance"; +> = 1.0; + +uniform float geom_target_gamma < + ui_type = "drag"; + ui_min = 0.1; + ui_max = 5.0; + ui_step = 0.1; + ui_label = "Geom Target Gamma"; +> = 2.4; + +uniform float geom_monitor_gamma < + ui_type = "drag"; + ui_min = 0.1; + ui_max = 5.0; + ui_step = 0.1; + ui_label = "Geom Monitor Gamma"; +> = 2.2; + + +uniform float2 BufferToViewportRatio < source = "buffer_to_viewport_ratio"; >; +uniform float2 NormalizedNativePixelSize < source = "normalized_native_pixel_size"; >; +uniform float2 ViewportSize < source = "viewportsize"; >; +uniform float ViewportX < source = "viewportx"; >; +uniform float ViewportY < source = "viewporty"; >; +uniform float ViewportWidth < source = "viewportwidth"; >; +uniform float ViewportHeight < source = "viewportheight"; >; +uniform float2 ViewportOffset < source = "viewportoffset"; >; + +sampler2D sBackBuffer{Texture=ReShade::BackBufferTex;AddressU=BORDER;AddressV=BORDER;AddressW=BORDER;MagFilter=LINEAR;MinFilter=LINEAR;}; + +texture tOverlay < source = "overlay/psx.jpg"; > +{ + Width = BUFFER_WIDTH; + Height = BUFFER_HEIGHT; + MipLevels = 1; +}; + +sampler sOverlay { Texture = tOverlay; AddressU = BORDER; AddressV = BORDER; MinFilter = LINEAR; MagFilter = LINEAR;}; + +// Comment the next line to disable interpolation in linear gamma (and +// gain speed). +#define LINEAR_PROCESSING + +// Enable 3x oversampling of the beam profile; improves moire effect caused by scanlines+curvature +#define OVERSAMPLE + +// Use the older, purely gaussian beam profile; uncomment for speed +//#define USEGAUSSIAN + +// Macros. +#define FIX(c) max(abs(c), 1e-5); +#define PI 3.141592653589 + +#ifdef LINEAR_PROCESSING +# define TEX2D(c) pow(tex2D(sBackBuffer, (c)), float4(geom_target_gamma,geom_target_gamma,geom_target_gamma,geom_target_gamma)) +#else +# define TEX2D(c) tex2D(sBackBuffer, (c)) +#endif + +// aspect ratio +#define aspect (geom_invert_aspect==true?float2(ViewportHeight/ViewportWidth,1.0):float2(1.0,ViewportHeight/ViewportWidth)) +#define overscan (float2(1.01,1.01)); + + +struct ST_VertexOut +{ + float2 sinangle : TEXCOORD1; + float2 cosangle : TEXCOORD2; + float3 stretch : TEXCOORD3; + float2 TextureSize : TEXCOORD4; +}; + + +float vs_intersect(float2 xy, float2 sinangle, float2 cosangle) +{ + float A = dot(xy,xy) + geom_d*geom_d; + float B = 2.0*(geom_R*(dot(xy,sinangle)-geom_d*cosangle.x*cosangle.y)-geom_d*geom_d); + float C = geom_d*geom_d + 2.0*geom_R*geom_d*cosangle.x*cosangle.y; + + return (-B-sqrt(B*B-4.0*A*C))/(2.0*A); +} + +float2 vs_bkwtrans(float2 xy, float2 sinangle, float2 cosangle) +{ + float c = vs_intersect(xy, sinangle, cosangle); + float2 point = (float2(c, c)*xy - float2(-geom_R, -geom_R)*sinangle) / float2(geom_R, geom_R); + float2 poc = point/cosangle; + + float2 tang = sinangle/cosangle; + float A = dot(tang, tang) + 1.0; + float B = -2.0*dot(poc, tang); + float C = dot(poc, poc) - 1.0; + + float a = (-B + sqrt(B*B - 4.0*A*C))/(2.0*A); + float2 uv = (point - a*sinangle)/cosangle; + float r = FIX(geom_R*acos(a)); + + return uv*r/sin(r/geom_R); +} + +float2 vs_fwtrans(float2 uv, float2 sinangle, float2 cosangle) +{ + float r = FIX(sqrt(dot(uv,uv))); + uv *= sin(r/geom_R)/r; + float x = 1.0-cos(r/geom_R); + float D = geom_d/geom_R + x*cosangle.x*cosangle.y+dot(uv,sinangle); + + return geom_d*(uv*cosangle-x*sinangle)/D; +} + +float3 vs_maxscale(float2 sinangle, float2 cosangle) +{ + float2 c = vs_bkwtrans(-geom_R * sinangle / (1.0 + geom_R/geom_d*cosangle.x*cosangle.y), sinangle, cosangle); + float2 a = float2(0.5,0.5)*aspect; + + float2 lo = float2(vs_fwtrans(float2(-a.x, c.y), sinangle, cosangle).x, + vs_fwtrans(float2( c.x, -a.y), sinangle, cosangle).y)/aspect; + + float2 hi = float2(vs_fwtrans(float2(+a.x, c.y), sinangle, cosangle).x, + vs_fwtrans(float2( c.x, +a.y), sinangle, cosangle).y)/aspect; + + return float3((hi+lo)*aspect*0.5,max(hi.x-lo.x,hi.y-lo.y)); +} + + + + +// Vertex shader generating a triangle covering the entire screen +void VS_CRT_Geom(in uint id : SV_VertexID, out float4 position : SV_Position, out float2 texcoord : TEXCOORD, out ST_VertexOut vVARS) +{ + texcoord.x = (id == 2) ? 2.0 : 0.0; + texcoord.y = (id == 1) ? 2.0 : 0.0; + position = float4(texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0); + + float2 SourceSize = 1.0/NormalizedNativePixelSize; + + // Precalculate a bunch of useful values we'll need in the fragment + // shader. + vVARS.sinangle = sin(float2(geom_x_tilt, geom_y_tilt)); + vVARS.cosangle = cos(float2(geom_x_tilt, geom_y_tilt)); + vVARS.stretch = vs_maxscale(vVARS.sinangle, vVARS.cosangle); + vVARS.TextureSize = float2(SourceSize.x, SourceSize.y); +} + + + +float intersect(float2 xy, float2 sinangle, float2 cosangle) +{ + float A = dot(xy,xy) + geom_d*geom_d; + float B, C; + + B = 2.0*(geom_R*(dot(xy,sinangle) - geom_d*cosangle.x*cosangle.y) - geom_d*geom_d); + C = geom_d*geom_d + 2.0*geom_R*geom_d*cosangle.x*cosangle.y; + + return (-B-sqrt(B*B - 4.0*A*C))/(2.0*A); +} + +float2 bkwtrans(float2 xy, float2 sinangle, float2 cosangle) +{ + float c = intersect(xy, sinangle, cosangle); + float2 point = (float2(c, c)*xy - float2(-geom_R, -geom_R)*sinangle) / float2(geom_R, geom_R); + float2 poc = point/cosangle; + float2 tang = sinangle/cosangle; + + float A = dot(tang, tang) + 1.0; + float B = -2.0*dot(poc, tang); + float C = dot(poc, poc) - 1.0; + + float a = (-B + sqrt(B*B - 4.0*A*C)) / (2.0*A); + float2 uv = (point - a*sinangle) / cosangle; + float r = FIX(geom_R*acos(a)); + + return uv*r/sin(r/geom_R); +} + +float2 fwtrans(float2 uv, float2 sinangle, float2 cosangle) +{ + float r = FIX(sqrt(dot(uv, uv))); + uv *= sin(r/geom_R)/r; + float x = 1.0 - cos(r/geom_R); + float D; + + D = geom_d/geom_R + x*cosangle.x*cosangle.y + dot(uv,sinangle); + + return geom_d*(uv*cosangle - x*sinangle)/D; +} + +float3 maxscale(float2 sinangle, float2 cosangle) +{ + float2 c = bkwtrans(-geom_R * sinangle / (1.0 + geom_R/geom_d*cosangle.x*cosangle.y), sinangle, cosangle); + float2 a = float2(0.5, 0.5)*aspect; + + float2 lo = float2(fwtrans(float2(-a.x, c.y), sinangle, cosangle).x, + fwtrans(float2( c.x, -a.y), sinangle, cosangle).y)/aspect; + float2 hi = float2(fwtrans(float2(+a.x, c.y), sinangle, cosangle).x, + fwtrans(float2( c.x, +a.y), sinangle, cosangle).y)/aspect; + + return float3((hi+lo)*aspect*0.5,max(hi.x-lo.x, hi.y-lo.y)); +} + +float2 transform(float2 coord, float2 sinangle, float2 cosangle, float3 stretch) +{ + coord = (coord - float2(0.5, 0.5))*aspect*stretch.z + stretch.xy; + + return (bkwtrans(coord, sinangle, cosangle) / + float2(geom_overscan_x / 100.0, geom_overscan_y / 100.0)/aspect + float2(0.5, 0.5)); +} + +float corner(float2 coord) +{ + coord = min(coord, float2(1.0, 1.0) - coord) * aspect; + float2 cdist = float2(geom_cornersize, geom_cornersize); + coord = (cdist - min(coord, cdist)); + float dist = sqrt(dot(coord, coord)); + + return clamp((cdist.x - dist)*geom_cornersmooth, 0.0, 1.0); +} + +float fwidth(float value){ + return abs(ddx(value)) + abs(ddy(value)); +} + + +// Code snippet borrowed from crt-cyclon. (credits to DariusG) +float2 Warp(float2 pos) +{ + pos = pos*2.0 - 1.0; + pos *= float2(1.0 + pos.y*pos.y*0, 1.0 + pos.x*pos.x*0); + pos = pos*0.5 + 0.5; + + return pos; +} + +float4 PS_CRT_Geom(float4 vpos: SV_Position, float2 vTexCoord : TEXCOORD, in ST_VertexOut vVARS) : SV_Target +{ + // Texture coordinates of the texel containing the active pixel. + float2 xy; + + if (geom_curvature == true) + xy = transform(vTexCoord, vVARS.sinangle, vVARS.cosangle, vVARS.stretch); + else + xy = vTexCoord; + + // center screen + xy = Warp(xy - float2(centerx,centery)/100.0); + + float cval = corner((xy-float2(0.5,0.5)) * BufferToViewportRatio + float2(0.5,0.5)); + + float2 uv_ratio = frac((xy * vVARS.TextureSize - float2(0.5, 0.5)) / vVARS.TextureSize); + + float4 col = TEX2D(xy); + +#ifndef LINEAR_PROCESSING + col = pow(col , float4(geom_target_gamma, geom_target_gamma, geom_target_gamma, geom_target_gamma)); +#endif + + col.rgb *= (geom_lum * step(0.0, uv_ratio.y)); + + float3 mul_res = col.rgb * float3(cval, cval, cval); + + // Convert the image gamma for display on our output device. + mul_res = pow(mul_res, float3(1.0 / geom_monitor_gamma, 1.0 / geom_monitor_gamma, 1.0 / geom_monitor_gamma)); + + float4 overlay = tex2D(sOverlay, vTexCoord); + + float2 top_left = (float2(ViewportX, ViewportY) - ViewportOffset)/ViewportSize; + float2 bottom_right = (float2(ViewportX + ViewportWidth, ViewportY + ViewportHeight) - ViewportOffset)/ViewportSize; + + if (xy.x < top_left.x || xy.x > bottom_right.x || xy.y < top_left.y || xy.y > bottom_right.y) + mul_res = overlay.rgb; + + return float4(mul_res, 1.0); +} + + +technique CRT_Geom +{ + pass + { + VertexShader = VS_CRT_Geom; + PixelShader = PS_CRT_Geom; + } +} diff --git a/data/resources/shaders/reshade/Textures/overlay/OVERLAY_CREDITS_AND_LICENSE.md b/data/resources/shaders/reshade/Textures/overlay/OVERLAY_CREDITS_AND_LICENSE.md new file mode 100644 index 000000000..bd322c094 --- /dev/null +++ b/data/resources/shaders/reshade/Textures/overlay/OVERLAY_CREDITS_AND_LICENSE.md @@ -0,0 +1,15 @@ +# To Use + +Choose Aspect Ratio: Stretch to Fill. + +# Psx.jpg Credits + +To the Author: SOQUEROEU. + +The "psx.jpg" background was edited from the one obtained from "Soqueroeu TV Backgrounds 2.0" repository: https://github.com/soqueroeu/Soqueroeu-TV-Backgrounds_V2.0/tree/main. + +The material is free to use according to the agreement below: + +## AGREEMENT + +This pack is free. You should not pay for anything related to this graphics pack and shader preset. You may distribute and reproduce part from this content, as long as you give credit to the authors involved. You may not profit from the sale of products that contain material in this package without the author's prior permission. diff --git a/data/resources/shaders/reshade/Textures/overlay/psx.jpg b/data/resources/shaders/reshade/Textures/overlay/psx.jpg new file mode 100644 index 000000000..378e2f601 Binary files /dev/null and b/data/resources/shaders/reshade/Textures/overlay/psx.jpg differ