From fee40bc74d0f8959c546c1df078b87ec1caabc92 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 24 Jun 2021 17:35:16 -0700 Subject: [PATCH] Res: Port scale2x an scale4x shaders --- CHANGES | 1 + res/shaders/scale2x.shader/manifest.ini | 11 +++++ res/shaders/scale2x.shader/scale2x.fs | 39 ++++++++++++++++++ res/shaders/scale4x.shader/manifest.ini | 11 +++++ res/shaders/scale4x.shader/scale4x.fs | 54 +++++++++++++++++++++++++ 5 files changed, 116 insertions(+) create mode 100644 res/shaders/scale2x.shader/manifest.ini create mode 100644 res/shaders/scale2x.shader/scale2x.fs create mode 100644 res/shaders/scale4x.shader/manifest.ini create mode 100644 res/shaders/scale4x.shader/scale4x.fs diff --git a/CHANGES b/CHANGES index 5ef27626f..d42fb656d 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,7 @@ Features: - Cheat code support in homebrew ports - Support for combo "Super Game Boy Color" SGB + GBC ROM hacks - Support for 64 kiB SRAM saves used in some bootlegs + - Additional scaling shaders Emulation fixes: - GB Memory: Add cursory cartridge open bus emulation (fixes mgba.io/i/2032) - GB Video: Clear VRAM on reset (fixes mgba.io/i/2152) diff --git a/res/shaders/scale2x.shader/manifest.ini b/res/shaders/scale2x.shader/manifest.ini new file mode 100644 index 000000000..93b9f91c3 --- /dev/null +++ b/res/shaders/scale2x.shader/manifest.ini @@ -0,0 +1,11 @@ +[shader] +name=Scale2x +author=singron +description=AdvanceMAME's Scale2x algorithm +passes=1 + +[pass.0] +fragmentShader=scale2x.fs +blend=1 +width=-2 +height=-2 diff --git a/res/shaders/scale2x.shader/scale2x.fs b/res/shaders/scale2x.shader/scale2x.fs new file mode 100644 index 000000000..457f61987 --- /dev/null +++ b/res/shaders/scale2x.shader/scale2x.fs @@ -0,0 +1,39 @@ +/* Shader implementation of Scale2x is adapted from https://gist.github.com/singron/3161079 */ +varying vec2 texCoord; +uniform sampler2D tex; +uniform vec2 texSize; + +void main() { + // o = offset, the width of a pixel + vec2 o = 1.0 / texSize; + + // texel arrangement + // A B C + // D E F + // G H I + vec4 B = texture2D(tex, texCoord + vec2( 0.0, o.y)); + vec4 D = texture2D(tex, texCoord + vec2( -o.x, 0.0)); + vec4 E = texture2D(tex, texCoord + vec2( 0.0, 0.0)); + vec4 F = texture2D(tex, texCoord + vec2( o.x, 0.0)); + vec4 H = texture2D(tex, texCoord + vec2( 0.0, -o.y)); + vec2 p = texCoord * texSize; + // p = the texCoord within a pixel [0...1] + p = fract(p); + if (p.x > .5) { + if (p.y > .5) { + // Top Right + gl_FragColor = B == F && B != D && F != H ? F : E; + } else { + // Bottom Right + gl_FragColor = H == F && D != H && B != F ? F : E; + } + } else { + if (p.y > .5) { + // Top Left + gl_FragColor = D == B && B != F && D != H ? D : E; + } else { + // Bottom Left + gl_FragColor = D == H && D != B && H != F ? D : E; + } + } +} diff --git a/res/shaders/scale4x.shader/manifest.ini b/res/shaders/scale4x.shader/manifest.ini new file mode 100644 index 000000000..b3c6c93de --- /dev/null +++ b/res/shaders/scale4x.shader/manifest.ini @@ -0,0 +1,11 @@ +[shader] +name=Scale4x +author=singron, endrift +description=AdvanceMAME's Scale4x algorithm +passes=1 + +[pass.0] +fragmentShader=scale4x.fs +blend=1 +width=-4 +height=-4 diff --git a/res/shaders/scale4x.shader/scale4x.fs b/res/shaders/scale4x.shader/scale4x.fs new file mode 100644 index 000000000..b928ac5ea --- /dev/null +++ b/res/shaders/scale4x.shader/scale4x.fs @@ -0,0 +1,54 @@ +/* Shader implementation of Scale2x is adapted from https://gist.github.com/singron/3161079 */ +varying vec2 texCoord; +uniform sampler2D tex; +uniform vec2 texSize; + +vec4 scale2x(vec4 pixels[5], vec2 p) { + // texel arrangement + // x 0 x + // 1 2 3 + // x 4 x + // p = the texCoord within a pixel [0...1] + p = fract(p); + if (p.x > .5) { + if (p.y > .5) { + // Top Right + return pixels[0] == pixels[3] && pixels[0] != pixels[1] && pixels[3] != pixels[4] ? pixels[3] : pixels[2]; + } else { + // Bottom Right + return pixels[4] == pixels[3] && pixels[1] != pixels[4] && pixels[0] != pixels[3] ? pixels[3] : pixels[2]; + } + } else { + if (p.y > .5) { + // Top Left + return pixels[1] == pixels[0] && pixels[0] != pixels[3] && pixels[1] != pixels[4] ? pixels[1] : pixels[2]; + } else { + // Bottom Left + return pixels[1] == pixels[4] && pixels[1] != pixels[0] && pixels[4] != pixels[3] ? pixels[1] : pixels[2]; + } + } +} + +vec4 scaleNeighborhood(vec2 p, vec2 x, vec2 o) { + vec4 neighborhood[5]; + neighborhood[0] = texture2D(tex, texCoord + x + vec2( 0.0, o.y)); + neighborhood[1] = texture2D(tex, texCoord + x + vec2(-o.x, 0.0)); + neighborhood[2] = texture2D(tex, texCoord + x + vec2( 0.0, 0.0)); + neighborhood[3] = texture2D(tex, texCoord + x + vec2( o.x, 0.0)); + neighborhood[4] = texture2D(tex, texCoord + x + vec2( 0.0, -o.y)); + return scale2x(neighborhood, p + x * texSize); +} + +void main() { + // o = offset, the width of a pixel + vec2 o = 1.0 / texSize; + + vec2 p = texCoord * texSize; + vec4 pixels[5]; + pixels[0] = scaleNeighborhood(p, vec2( 0.0, o.y / 2.0), o); + pixels[1] = scaleNeighborhood(p, vec2(-o.x / 2.0, 0.0), o); + pixels[2] = scaleNeighborhood(p, vec2( 0.0, 0.0), o); + pixels[3] = scaleNeighborhood(p, vec2( o.x / 2.0, 0.0), o); + pixels[4] = scaleNeighborhood(p, vec2( 0.0, -o.y / 2.0), o); + gl_FragColor = scale2x(pixels, p * 2.0); +}