From e2bd24784d28ecad64383c6326ea7a7a3af956da Mon Sep 17 00:00:00 2001 From: rsn8887 Date: Wed, 23 Aug 2017 14:45:05 -0500 Subject: [PATCH] Scanline shaders added, renamed 2x-prescale shader --- .../sharp-bilinear-scanlines-thick.glsl | 145 ++++++++++++++++++ .../sharp-bilinear-scanlines-thin.glsl | 145 ++++++++++++++++++ ...glslp => sharp-bilinear-2x-prescale.glslp} | 0 .../sharp-bilinear-scanlines-thick.glslp | 4 + .../sharp-bilinear-scanlines-thin.glslp | 4 + README.md | 17 +- 6 files changed, 311 insertions(+), 4 deletions(-) create mode 100644 Copy_To_RetroPie/shaders/sharp-bilinear-scanlines-thick.glsl create mode 100644 Copy_To_RetroPie/shaders/sharp-bilinear-scanlines-thin.glsl rename Copy_To_RetroPie/{2x-prescale-sharp-bilinear.glslp => sharp-bilinear-2x-prescale.glslp} (100%) create mode 100644 Copy_To_RetroPie/sharp-bilinear-scanlines-thick.glslp create mode 100644 Copy_To_RetroPie/sharp-bilinear-scanlines-thin.glslp diff --git a/Copy_To_RetroPie/shaders/sharp-bilinear-scanlines-thick.glsl b/Copy_To_RetroPie/shaders/sharp-bilinear-scanlines-thick.glsl new file mode 100644 index 0000000..d4bd4a0 --- /dev/null +++ b/Copy_To_RetroPie/shaders/sharp-bilinear-scanlines-thick.glsl @@ -0,0 +1,145 @@ +/* + Author: rsn8887 (based on TheMaister) + License: Public domain + + This is an integer prescale filter that should be combined + with a bilinear hardware filtering (GL_BILINEAR filter or some such) to achieve + a smooth scaling result with minimum blur. This is good for pixelgraphics + that are scaled by non-integer factors. + + The prescale factor and texel coordinates are precalculated + in the vertex shader for speed. The precalculation only works on Windows + but doesn't work on Raspberry Pi and is therefore disabled for now. +*/ + +#if defined(VERTEX) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING out +#define COMPAT_ATTRIBUTE in +#define COMPAT_TEXTURE texture +#else +#define COMPAT_VARYING varying +#define COMPAT_ATTRIBUTE attribute +#define COMPAT_TEXTURE texture2D +#endif + +#ifdef GL_ES +#define COMPAT_PRECISION mediump +#else +#define COMPAT_PRECISION +#endif + +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; + +// vertex compatibility #defines +#define vTexCoord TEX0.xy +#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize +#define outsize vec4(OutputSize, 1.0 / OutputSize) + +/* uncomment for precalculation (not compatible with Raspberry Pi) +out VertexData +{ + vec2 texel; + vec2 prescale; +} precalcOut; +*/ + +void main() +{ + gl_Position = MVPMatrix * VertexCoord; + COL0 = COLOR; + TEX0.xy = TexCoord.xy; + +/* uncomment for precalculation (not compatible with Raspberry Pi) + precalcOut.texel = vTexCoord * SourceSize.xy; + precalcOut.prescale = max(floor(outsize.xy / InputSize.xy), vec2(1.0, 1.0)); +*/ +} + +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#else +#define COMPAT_VARYING varying +#define FragColor gl_FragColor +#define COMPAT_TEXTURE texture2D +#endif + +#ifdef GL_ES +#ifdef GL_FRAGMENT_PRECISION_HIGH +precision highp float; +#else +precision mediump float; +#endif +#define COMPAT_PRECISION mediump +#else +#define COMPAT_PRECISION +#endif + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +uniform sampler2D Texture; +COMPAT_VARYING vec4 TEX0; + +// fragment compatibility #defines +#define Source Texture +#define vTexCoord TEX0.xy +#define texture(c, d) COMPAT_TEXTURE(c, d) +#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize +#define outsize vec4(OutputSize, 1.0 / OutputSize) + +/* uncomment for precalculation (not compatible with Raspberry Pi) +in VertexData +{ + vec2 texel; + vec2 prescale; +} precalcIn; +*/ + +void main() +{ +/* uncomment for precalculation (not compatible with Raspberry Pi) + vec2 texel = precalcIn.texel; + vec2 scale = precalcIn.prescale; +*/ + // comment out next to lines for precalculation (not compatible with RPi) + vec2 texel = vTexCoord * SourceSize.xy; + vec2 scale = max(floor(outsize.xy / InputSize.xy), vec2(1.0, 1.0)); + + vec2 texel_floored = floor(texel); + vec2 s = fract(texel); + vec2 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 = s - 0.5; + vec2 f = (center_dist - clamp(center_dist, -region_range, region_range)) * scale + 0.5; + + vec2 mod_texel = texel_floored + f; + + // thick scanlines based on source resolution + if (mod(floor(vTexCoord.y * 2.0 * InputSize.y), 2.0) == 0.0) + FragColor = vec4(0.0, 0.0, 0.0, 1.0); + else + FragColor = vec4(texture(Source, mod_texel / SourceSize.xy).rgb, 1.0); +} +#endif diff --git a/Copy_To_RetroPie/shaders/sharp-bilinear-scanlines-thin.glsl b/Copy_To_RetroPie/shaders/sharp-bilinear-scanlines-thin.glsl new file mode 100644 index 0000000..0492227 --- /dev/null +++ b/Copy_To_RetroPie/shaders/sharp-bilinear-scanlines-thin.glsl @@ -0,0 +1,145 @@ +/* + Author: rsn8887 (based on TheMaister) + License: Public domain + + This is an integer prescale filter that should be combined + with a bilinear hardware filtering (GL_BILINEAR filter or some such) to achieve + a smooth scaling result with minimum blur. This is good for pixelgraphics + that are scaled by non-integer factors. + + The prescale factor and texel coordinates are precalculated + in the vertex shader for speed. The precalculation only works on Windows + but doesn't work on Raspberry Pi and is therefore disabled for now. +*/ + +#if defined(VERTEX) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING out +#define COMPAT_ATTRIBUTE in +#define COMPAT_TEXTURE texture +#else +#define COMPAT_VARYING varying +#define COMPAT_ATTRIBUTE attribute +#define COMPAT_TEXTURE texture2D +#endif + +#ifdef GL_ES +#define COMPAT_PRECISION mediump +#else +#define COMPAT_PRECISION +#endif + +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; + +uniform mat4 MVPMatrix; +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; + +// vertex compatibility #defines +#define vTexCoord TEX0.xy +#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize +#define outsize vec4(OutputSize, 1.0 / OutputSize) + +/* uncomment for precalculation (not compatible with Raspberry Pi) +out VertexData +{ + vec2 texel; + vec2 prescale; +} precalcOut; +*/ + +void main() +{ + gl_Position = MVPMatrix * VertexCoord; + COL0 = COLOR; + TEX0.xy = TexCoord.xy; + +/* uncomment for precalculation (not compatible with Raspberry Pi) + precalcOut.texel = vTexCoord * SourceSize.xy; + precalcOut.prescale = max(floor(outsize.xy / InputSize.xy), vec2(1.0, 1.0)); +*/ +} + +#elif defined(FRAGMENT) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out vec4 FragColor; +#else +#define COMPAT_VARYING varying +#define FragColor gl_FragColor +#define COMPAT_TEXTURE texture2D +#endif + +#ifdef GL_ES +#ifdef GL_FRAGMENT_PRECISION_HIGH +precision highp float; +#else +precision mediump float; +#endif +#define COMPAT_PRECISION mediump +#else +#define COMPAT_PRECISION +#endif + +uniform int FrameDirection; +uniform int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +uniform sampler2D Texture; +COMPAT_VARYING vec4 TEX0; + +// fragment compatibility #defines +#define Source Texture +#define vTexCoord TEX0.xy +#define texture(c, d) COMPAT_TEXTURE(c, d) +#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize +#define outsize vec4(OutputSize, 1.0 / OutputSize) + +/* uncomment for precalculation (not compatible with Raspberry Pi) +in VertexData +{ + vec2 texel; + vec2 prescale; +} precalcIn; +*/ + +void main() +{ +/* uncomment for precalculation (not compatible with Raspberry Pi) + vec2 texel = precalcIn.texel; + vec2 scale = precalcIn.prescale; +*/ + // comment out next to lines for precalculation (not compatible with RPi) + vec2 texel = vTexCoord * SourceSize.xy; + vec2 scale = max(floor(outsize.xy / InputSize.xy), vec2(1.0, 1.0)); + + vec2 texel_floored = floor(texel); + vec2 s = fract(texel); + vec2 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 = s - 0.5; + vec2 f = (center_dist - clamp(center_dist, -region_range, region_range)) * scale + 0.5; + + vec2 mod_texel = texel_floored + f; + + // thin scanlines based on output display resolution + if (mod(floor(vTexCoord.y * outsize.y), 2.0) == 0.0) + FragColor = vec4(0.0, 0.0, 0.0, 1.0); + else + FragColor = vec4(texture(Source, mod_texel / SourceSize.xy).rgb, 1.0); +} +#endif diff --git a/Copy_To_RetroPie/2x-prescale-sharp-bilinear.glslp b/Copy_To_RetroPie/sharp-bilinear-2x-prescale.glslp similarity index 100% rename from Copy_To_RetroPie/2x-prescale-sharp-bilinear.glslp rename to Copy_To_RetroPie/sharp-bilinear-2x-prescale.glslp diff --git a/Copy_To_RetroPie/sharp-bilinear-scanlines-thick.glslp b/Copy_To_RetroPie/sharp-bilinear-scanlines-thick.glslp new file mode 100644 index 0000000..3675dd4 --- /dev/null +++ b/Copy_To_RetroPie/sharp-bilinear-scanlines-thick.glslp @@ -0,0 +1,4 @@ +shaders = 1 + +shader0 = shaders/sharp-bilinear-scanlines-thick.glsl +filter_linear0 = true \ No newline at end of file diff --git a/Copy_To_RetroPie/sharp-bilinear-scanlines-thin.glslp b/Copy_To_RetroPie/sharp-bilinear-scanlines-thin.glslp new file mode 100644 index 0000000..e66cb38 --- /dev/null +++ b/Copy_To_RetroPie/sharp-bilinear-scanlines-thin.glslp @@ -0,0 +1,4 @@ +shaders = 1 + +shader0 = shaders/sharp-bilinear-scanlines-thin.glsl +filter_linear0 = true \ No newline at end of file diff --git a/README.md b/README.md index 35346b8..9972820 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,9 @@ Sharp-Bilinear Shaders for Retroarch This is a collection of shaders for sharp pixels without pixel wobble and minimal blurring in RetroArch/Libretro. -There are two shaders included. +There are four shaders included. -- "2x-prescale-sharp-bilinear" +- "sharp-bilinear-2x-prescale" This shader does a fixed 2x integer prescale resulting in a small amount of image blurring but no pixelwobble. This is a simple two-pass shader configuration. First, an integer 2x prescale is applied, followed by a bilinear scaling to fullscreen. @@ -13,7 +13,16 @@ This shader does a fixed 2x integer prescale resulting in a small amount of imag This shader does an automatic optimum integer prescale (2x, 3x, 4x etc.), depending on game and screen resolution. I recommend this shader since the autoscaling results in sharper images for some games than the fixed 2x prescale. -Both shader configurations give sharp pixels with zero pixel wobble in all games. +- "sharp-bilinear-scanlines-thin" + +same as above, but with an overlay of thin black scanlines (scanline on every even display line) + +- "sharp-bilinear-scanlines-thick" + +same as above, but with an overlay of thick black scanlines (half of each game pixel, vertically is a scanline) + + +All these shader configurations give sharp pixels with zero pixel wobble in all games. Compared to the "video smoothing=ON" setting with no shaders, pixels are less blurry. Compared to the "video smoothing=OFF" setting with no shaders, the pixels do not change shape/wobble as they move across the screen. @@ -26,7 +35,7 @@ To install this shader in RetroPie: - Copy the contents of the included "Copy_To_RetroPie" folder to /opt/retropie/emulators/retroarch/shader/ - open the RetroPie-Setup menu and choose "Edit RetroPie/RetroArch Configurations"-> "configure basic libretro emulator options"-> "configure default options for all libretro emulators" - set "Video Shader Enable" to "True" -- set "Video Shader File" to "sharp-bilinear-simple.glslp," or "2x-prescale-sharp-bilinear.glslp" depending on your preference. +- set "Video Shader File" to "sharp-bilinear-xxxxx.glslp," choosing xxxxx depending on your preference. Example Images --------------