SameBoy | Accurate GB/GBC emulator |
| download: https://git.y1.nz/archives/sameboy.tar.gz | |
| README | Files | Log | Refs | LICENSE |
commit 84a193a918ab9a9d26b9b6d398f450d7a9459961 parent 859ff79527beb83c01ad3dbdd8865885b48d98ea Author: Lior Halphon <LIJI32@gmail.com> Date: Fri, 29 Jul 2022 17:08:51 +0300 Fix shader artifacts, revise AAScale4x Diffstat:
| M | Shaders/AAScale2x.fsh | 18 | ++++++------------ |
| M | Shaders/AAScale4x.fsh | 41 | +++++++++++++++-------------------------- |
| M | Shaders/CRT.fsh | 18 | +++++++++--------- |
| M | Shaders/HQ2x.fsh | 22 | ++++++++++------------ |
| M | Shaders/LCD.fsh | 18 | +++++++++--------- |
| M | Shaders/MasterShader.fsh | 6 | ++++++ |
| M | Shaders/MasterShader.metal | 7 | +++++++ |
| M | Shaders/OmniScale.fsh | 34 | +++++++++++++++++----------------- |
| M | Shaders/Scale2x.fsh | 18 | ++++++------------ |
| M | Shaders/Scale4x.fsh | 41 | +++++++++++++++++------------------------ |
10 files changed, 102 insertions(+), 121 deletions(-)
diff --git a/Shaders/AAScale2x.fsh b/Shaders/AAScale2x.fsh @@ -1,21 +1,15 @@ STATIC vec4 scale2x(sampler2D image, vec2 position, vec2 input_resolution, vec2 output_resolution) -{ - // o = offset, the width of a pixel - vec2 o = 1.0 / input_resolution; - +{ // texel arrangement // A B C // D E F // G H I // vec4 A = texture(image, position + vec2( -o.x, o.y)); - vec4 B = texture(image, position + vec2( 0, o.y)); - // vec4 C = texture(image, position + vec2( o.x, o.y)); - vec4 D = texture(image, position + vec2( -o.x, 0)); - vec4 E = texture(image, position + vec2( 0, 0)); - vec4 F = texture(image, position + vec2( o.x, 0)); - // vec4 G = texture(image, position + vec2( -o.x, -o.y)); - vec4 H = texture(image, position + vec2( 0, -o.y)); - // vec4 I = texture(image, position + vec2( o.x, -o.y)); + vec4 B = texture_relative(image, position, vec2( 0, 1)); + vec4 D = texture_relative(image, position, vec2( -1, 0)); + vec4 E = texture_relative(image, position, vec2( 0, 0)); + vec4 F = texture_relative(image, position, vec2( 1, 0)); + vec4 H = texture_relative(image, position, vec2( 0, -1)); vec2 p = position * input_resolution; // p = the position within a pixel [0...1] p = fract(p); diff --git a/Shaders/AAScale4x.fsh b/Shaders/AAScale4x.fsh @@ -1,20 +1,15 @@ STATIC vec4 scale2x(sampler2D image, vec2 position, vec2 input_resolution, vec2 output_resolution) { - // o = offset, the width of a pixel - vec2 o = 1.0 / input_resolution; // texel arrangement // A B C // D E F // G H I - // vec4 A = texture(image, position + vec2( -o.x, o.y)); - vec4 B = texture(image, position + vec2( 0, o.y)); - // vec4 C = texture(image, position + vec2( o.x, o.y)); - vec4 D = texture(image, position + vec2( -o.x, 0)); - vec4 E = texture(image, position + vec2( 0, 0)); - vec4 F = texture(image, position + vec2( o.x, 0)); - // vec4 G = texture(image, position + vec2( -o.x, -o.y)); - vec4 H = texture(image, position + vec2( 0, -o.y)); - // vec4 I = texture(image, position + vec2( o.x, -o.y)); + + vec4 B = texture_relative(image, position, vec2( 0, 1)); + vec4 D = texture_relative(image, position, vec2( -1, 0)); + vec4 E = texture_relative(image, position, vec2( 0, 0)); + vec4 F = texture_relative(image, position, vec2( 1, 0)); + vec4 H = texture_relative(image, position, vec2( 0, -1)); vec2 p = position * input_resolution; // p = the position within a pixel [0...1] p = fract(p); @@ -36,30 +31,24 @@ STATIC vec4 scale2x(sampler2D image, vec2 position, vec2 input_resolution, vec2 } } } - -STATIC vec4 aaScale2x(sampler2D image, vec2 position, vec2 input_resolution, vec2 output_resolution) +STATIC vec4 scale2x_wrapper(sampler2D t, vec2 pos, vec2 offset, vec2 input_resolution, vec2 output_resolution) { - return mix(texture(image, position), scale2x(image, position, input_resolution, output_resolution), 0.5); + vec2 origin = (floor(pos * input_resolution * 2)) + vec2(0.5, 0.5); + return scale2x(t, (origin + offset) / input_resolution / 2, input_resolution, output_resolution); } STATIC vec4 scale(sampler2D image, vec2 position, vec2 input_resolution, vec2 output_resolution) { - // o = offset, the width of a pixel - vec2 o = 1.0 / (input_resolution * 2.); - // texel arrangement // A B C // D E F // G H I - // vec4 A = aaScale2x(image, position + vec2( -o.x, o.y), input_resolution, output_resolution); - vec4 B = aaScale2x(image, position + vec2( 0, o.y), input_resolution, output_resolution); - // vec4 C = aaScale2x(image, position + vec2( o.x, o.y), input_resolution, output_resolution); - vec4 D = aaScale2x(image, position + vec2( -o.x, 0), input_resolution, output_resolution); - vec4 E = aaScale2x(image, position + vec2( 0, 0), input_resolution, output_resolution); - vec4 F = aaScale2x(image, position + vec2( o.x, 0), input_resolution, output_resolution); - // vec4 G = aaScale2x(image, position + vec2( -o.x, -o.y), input_resolution, output_resolution); - vec4 H = aaScale2x(image, position + vec2( 0, -o.y), input_resolution, output_resolution); - // vec4 I = aaScale2x(image, position + vec2( o.x, -o.y), input_resolution, output_resolution); + vec4 B = scale2x_wrapper(image, position, vec2( 0, 1), input_resolution, output_resolution); + vec4 D = scale2x_wrapper(image, position, vec2( -1, 0), input_resolution, output_resolution); + vec4 E = scale2x_wrapper(image, position, vec2( 0, 0), input_resolution, output_resolution); + vec4 F = scale2x_wrapper(image, position, vec2( 1, 0), input_resolution, output_resolution); + vec4 H = scale2x_wrapper(image, position, vec2( 0, -1), input_resolution, output_resolution); + vec4 R; vec2 p = position * input_resolution * 2.; // p = the position within a pixel [0...1] diff --git a/Shaders/CRT.fsh b/Shaders/CRT.fsh @@ -25,20 +25,20 @@ STATIC vec4 scale(sampler2D image, vec2 position, vec2 input_resolution, vec2 ou vec2 pos = fract(position * input_resolution); vec2 sub_pos = fract(position * input_resolution * 6); - vec4 center = texture(image, position); - vec4 left = texture(image, position - vec2(1.0 / input_resolution.x, 0)); - vec4 right = texture(image, position + vec2(1.0 / input_resolution.x, 0)); + vec4 center = texture_relative(image, position, vec2(0, 0)); + vec4 left = texture_relative(image, position, vec2(-1, 0)); + vec4 right = texture_relative(image, position, vec2(1, 0)); /* Vertical blurring */ if (pos.y < 1.0 / 6.0) { - center = mix(center, texture(image, position + vec2(0, -1.0 / input_resolution.y)), 0.5 - sub_pos.y / 2.0); - left = mix(left, texture(image, position + vec2(-1.0 / input_resolution.x, -1.0 / input_resolution.y)), 0.5 - sub_pos.y / 2.0); - right = mix(right, texture(image, position + vec2( 1.0 / input_resolution.x, -1.0 / input_resolution.y)), 0.5 - sub_pos.y / 2.0); + center = mix(center, texture_relative(image, position, vec2( 0, -1)), 0.5 - sub_pos.y / 2.0); + left = mix(left, texture_relative(image, position, vec2(-1, -1)), 0.5 - sub_pos.y / 2.0); + right = mix(right, texture_relative(image, position, vec2( 1, -1)), 0.5 - sub_pos.y / 2.0); } else if (pos.y > 5.0 / 6.0) { - center = mix(center, texture(image, position + vec2(0, 1.0 / input_resolution.y)), sub_pos.y / 2.0); - left = mix(left, texture(image, position + vec2(-1.0 / input_resolution.x, 1.0 / input_resolution.y)), sub_pos.y / 2.0); - right = mix(right, texture(image, position + vec2( 1.0 / input_resolution.x, 1.0 / input_resolution.y)), sub_pos.y / 2.0); + center = mix(center, texture_relative(image, position, vec2( 0, 1)), sub_pos.y / 2.0); + left = mix(left, texture_relative(image, position, vec2(-1, 1)), sub_pos.y / 2.0); + right = mix(right, texture_relative(image, position, vec2( 1, 1)), sub_pos.y / 2.0); } /* Scanlines */ diff --git a/Shaders/HQ2x.fsh b/Shaders/HQ2x.fsh @@ -30,7 +30,7 @@ STATIC vec4 interp_3px(vec4 c1, float w1, vec4 c2, float w2, vec4 c3, float w3) STATIC vec4 scale(sampler2D image, vec2 position, vec2 input_resolution, vec2 output_resolution) { // o = offset, the width of a pixel - vec2 o = 1.0 / input_resolution; + vec2 o = vec2(1, 1); /* We always calculate the top left pixel. If we need a different pixel, we flip the image */ @@ -40,17 +40,15 @@ STATIC vec4 scale(sampler2D image, vec2 position, vec2 input_resolution, vec2 ou if (p.x > 0.5) o.x = -o.x; if (p.y > 0.5) o.y = -o.y; - - - vec4 w0 = texture(image, position + vec2( -o.x, -o.y)); - vec4 w1 = texture(image, position + vec2( 0, -o.y)); - vec4 w2 = texture(image, position + vec2( o.x, -o.y)); - vec4 w3 = texture(image, position + vec2( -o.x, 0)); - vec4 w4 = texture(image, position + vec2( 0, 0)); - vec4 w5 = texture(image, position + vec2( o.x, 0)); - vec4 w6 = texture(image, position + vec2( -o.x, o.y)); - vec4 w7 = texture(image, position + vec2( 0, o.y)); - vec4 w8 = texture(image, position + vec2( o.x, o.y)); + vec4 w0 = texture_relative(image, position, vec2( -o.x, -o.y)); + vec4 w1 = texture_relative(image, position, vec2( 0, -o.y)); + vec4 w2 = texture_relative(image, position, vec2( o.x, -o.y)); + vec4 w3 = texture_relative(image, position, vec2( -o.x, 0)); + vec4 w4 = texture_relative(image, position, vec2( 0, 0)); + vec4 w5 = texture_relative(image, position, vec2( o.x, 0)); + vec4 w6 = texture_relative(image, position, vec2( -o.x, o.y)); + vec4 w7 = texture_relative(image, position, vec2( 0, o.y)); + vec4 w8 = texture_relative(image, position, vec2( o.x, o.y)); int pattern = 0; if (is_different(w0, w4)) pattern |= 1; diff --git a/Shaders/LCD.fsh b/Shaders/LCD.fsh @@ -7,22 +7,22 @@ STATIC vec4 scale(sampler2D image, vec2 position, vec2 input_resolution, vec2 ou vec2 pos = fract(position * input_resolution); vec2 sub_pos = fract(position * input_resolution * 6); - vec4 center = texture(image, position); - vec4 left = texture(image, position - vec2(1.0 / input_resolution.x, 0)); - vec4 right = texture(image, position + vec2(1.0 / input_resolution.x, 0)); + vec4 center = texture_relative(image, position, vec2(0, 0)); + vec4 left = texture_relative(image, position, vec2(-1, 0)); + vec4 right = texture_relative(image, position, vec2(1, 0)); if (pos.y < 1.0 / 6.0) { - center = mix(center, texture(image, position + vec2(0, -1.0 / input_resolution.y)), 0.5 - sub_pos.y / 2.0); - left = mix(left, texture(image, position + vec2(-1.0 / input_resolution.x, -1.0 / input_resolution.y)), 0.5 - sub_pos.y / 2.0); - right = mix(right, texture(image, position + vec2( 1.0 / input_resolution.x, -1.0 / input_resolution.y)), 0.5 - sub_pos.y / 2.0); + center = mix(center, texture_relative(image, position, vec2( 0, -1)), 0.5 - sub_pos.y / 2.0); + left = mix(left, texture_relative(image, position, vec2(-1, -1)), 0.5 - sub_pos.y / 2.0); + right = mix(right, texture_relative(image, position, vec2( 1, -1)), 0.5 - sub_pos.y / 2.0); center *= sub_pos.y * SCANLINE_DEPTH + (1 - SCANLINE_DEPTH); left *= sub_pos.y * SCANLINE_DEPTH + (1 - SCANLINE_DEPTH); right *= sub_pos.y * SCANLINE_DEPTH + (1 - SCANLINE_DEPTH); } else if (pos.y > 5.0 / 6.0) { - center = mix(center, texture(image, position + vec2(0, 1.0 / input_resolution.y)), sub_pos.y / 2.0); - left = mix(left, texture(image, position + vec2(-1.0 / input_resolution.x, 1.0 / input_resolution.y)), sub_pos.y / 2.0); - right = mix(right, texture(image, position + vec2( 1.0 / input_resolution.x, 1.0 / input_resolution.y)), sub_pos.y / 2.0); + center = mix(center, texture_relative(image, position, vec2( 0, 1)), sub_pos.y / 2.0); + left = mix(left, texture_relative(image, position, vec2(-1, 1)), sub_pos.y / 2.0); + right = mix(right, texture_relative(image, position, vec2( 1, 1)), sub_pos.y / 2.0); center *= (1.0 - sub_pos.y) * SCANLINE_DEPTH + (1 - SCANLINE_DEPTH); left *= (1.0 - sub_pos.y) * SCANLINE_DEPTH + (1 - SCANLINE_DEPTH); right *= (1.0 - sub_pos.y) * SCANLINE_DEPTH + (1 - SCANLINE_DEPTH); diff --git a/Shaders/MasterShader.fsh b/Shaders/MasterShader.fsh @@ -18,6 +18,12 @@ vec4 _texture(sampler2D t, vec2 pos) return pow(texture(t, pos), vec4(GAMMA)); } +vec4 texture_relative(sampler2D t, vec2 pos, vec2 offset) +{ + vec2 input_resolution = textureSize(t, 0); + return _texture(t, (floor(pos * input_resolution) + offset + vec2(0.5, 0.5)) / input_resolution); +} + #define texture _texture #line 1 diff --git a/Shaders/MasterShader.metal b/Shaders/MasterShader.metal @@ -40,6 +40,13 @@ static inline float4 texture(texture2d<half> texture, float2 pos) return pow(float4(texture.sample(texture_sampler, pos)), GAMMA); } +__attribute__((unused)) static inline float4 texture_relative(texture2d<half> t, float2 pos, float2 offset) +{ + float2 input_resolution = float2(t.get_width(), t.get_height());; + float2 origin = (floor(pos * input_resolution)) + float2(0.5, 0.5); + return texture(t, (origin + offset) / input_resolution); +} + #line 1 {filter} diff --git a/Shaders/OmniScale.fsh b/Shaders/OmniScale.fsh @@ -27,7 +27,7 @@ STATIC bool is_different(vec4 a, vec4 b) STATIC vec4 scale(sampler2D image, vec2 position, vec2 input_resolution, vec2 output_resolution) { // o = offset, the width of a pixel - vec2 o = 1.0 / input_resolution; + vec2 o = vec2(1, 1); /* We always calculate the top left quarter. If we need a different quarter, we flip our co-ordinates */ @@ -43,15 +43,15 @@ STATIC vec4 scale(sampler2D image, vec2 position, vec2 input_resolution, vec2 ou p.y = 1.0 - p.y; } - vec4 w0 = texture(image, position + vec2( -o.x, -o.y)); - vec4 w1 = texture(image, position + vec2( 0, -o.y)); - vec4 w2 = texture(image, position + vec2( o.x, -o.y)); - vec4 w3 = texture(image, position + vec2( -o.x, 0)); - vec4 w4 = texture(image, position + vec2( 0, 0)); - vec4 w5 = texture(image, position + vec2( o.x, 0)); - vec4 w6 = texture(image, position + vec2( -o.x, o.y)); - vec4 w7 = texture(image, position + vec2( 0, o.y)); - vec4 w8 = texture(image, position + vec2( o.x, o.y)); + vec4 w0 = texture_relative(image, position, vec2( -o.x, -o.y)); + vec4 w1 = texture_relative(image, position, vec2( 0, -o.y)); + vec4 w2 = texture_relative(image, position, vec2( o.x, -o.y)); + vec4 w3 = texture_relative(image, position, vec2( -o.x, 0)); + vec4 w4 = texture_relative(image, position, vec2( 0, 0)); + vec4 w5 = texture_relative(image, position, vec2( o.x, 0)); + vec4 w6 = texture_relative(image, position, vec2( -o.x, o.y)); + vec4 w7 = texture_relative(image, position, vec2( 0, o.y)); + vec4 w8 = texture_relative(image, position, vec2( o.x, o.y)); int pattern = 0; if (is_different(w0, w4)) pattern |= 1 << 0; @@ -228,13 +228,13 @@ STATIC vec4 scale(sampler2D image, vec2 position, vec2 input_resolution, vec2 ou } /* We need more samples to "solve" this diagonal */ - vec4 x0 = texture(image, position + vec2( -o.x * 2.0, -o.y * 2.0)); - vec4 x1 = texture(image, position + vec2( -o.x , -o.y * 2.0)); - vec4 x2 = texture(image, position + vec2( 0.0 , -o.y * 2.0)); - vec4 x3 = texture(image, position + vec2( o.x , -o.y * 2.0)); - vec4 x4 = texture(image, position + vec2( -o.x * 2.0, -o.y )); - vec4 x5 = texture(image, position + vec2( -o.x * 2.0, 0.0 )); - vec4 x6 = texture(image, position + vec2( -o.x * 2.0, o.y )); + vec4 x0 = texture_relative(image, position, vec2( -o.x * 2.0, -o.y * 2.0)); + vec4 x1 = texture_relative(image, position, vec2( -o.x , -o.y * 2.0)); + vec4 x2 = texture_relative(image, position, vec2( 0.0 , -o.y * 2.0)); + vec4 x3 = texture_relative(image, position, vec2( o.x , -o.y * 2.0)); + vec4 x4 = texture_relative(image, position, vec2( -o.x * 2.0, -o.y )); + vec4 x5 = texture_relative(image, position, vec2( -o.x * 2.0, 0.0 )); + vec4 x6 = texture_relative(image, position, vec2( -o.x * 2.0, o.y )); if (is_different(x0, w4)) pattern |= 1 << 8; if (is_different(x1, w4)) pattern |= 1 << 9; diff --git a/Shaders/Scale2x.fsh b/Shaders/Scale2x.fsh @@ -2,22 +2,16 @@ STATIC vec4 scale(sampler2D image, vec2 position, vec2 input_resolution, vec2 output_resolution) { - // o = offset, the width of a pixel - vec2 o = 1.0 / input_resolution; - // texel arrangement // A B C // D E F // G H I - // vec4 A = texture(image, position + vec2( -o.x, o.y)); - vec4 B = texture(image, position + vec2( 0, o.y)); - // vec4 C = texture(image, position + vec2( o.x, o.y)); - vec4 D = texture(image, position + vec2( -o.x, 0)); - vec4 E = texture(image, position + vec2( 0, 0)); - vec4 F = texture(image, position + vec2( o.x, 0)); - // vec4 G = texture(image, position + vec2( -o.x, -o.y)); - vec4 H = texture(image, position + vec2( 0, -o.y)); - // vec4 I = texture(image, position + vec2( o.x, -o.y)); + + vec4 B = texture_relative(image, position, vec2( 0, 1)); + vec4 D = texture_relative(image, position, vec2( -1, 0)); + vec4 E = texture_relative(image, position, vec2( 0, 0)); + vec4 F = texture_relative(image, position, vec2( 1, 0)); + vec4 H = texture_relative(image, position, vec2( 0, -1)); vec2 p = position * input_resolution; // p = the position within a pixel [0...1] p = fract(p); diff --git a/Shaders/Scale4x.fsh b/Shaders/Scale4x.fsh @@ -1,23 +1,16 @@ STATIC vec4 scale2x(sampler2D image, vec2 position, vec2 input_resolution, vec2 output_resolution) { - // o = offset, the width of a pixel - vec2 o = 1.0 / input_resolution; // texel arrangement // A B C // D E F // G H I - // vec4 A = texture(image, position + vec2( -o.x, o.y)); - vec4 B = texture(image, position + vec2( 0, o.y)); - // vec4 C = texture(image, position + vec2( o.x, o.y)); - vec4 D = texture(image, position + vec2( -o.x, 0)); - vec4 E = texture(image, position + vec2( 0, 0)); - vec4 F = texture(image, position + vec2( o.x, 0)); - // vec4 G = texture(image, position + vec2( -o.x, -o.y)); - vec4 H = texture(image, position + vec2( 0, -o.y)); - // vec4 I = texture(image, position + vec2( o.x, -o.y)); + vec4 B = texture_relative(image, position, vec2( 0, 1)); + vec4 D = texture_relative(image, position, vec2( -1, 0)); + vec4 E = texture_relative(image, position, vec2( 0, 0)); + vec4 F = texture_relative(image, position, vec2( 1, 0)); + vec4 H = texture_relative(image, position, vec2( 0, -1)); vec2 p = position * input_resolution; // p = the position within a pixel [0...1] - vec4 R; p = fract(p); if (p.x > .5) { if (p.y > .5) { @@ -38,24 +31,24 @@ STATIC vec4 scale2x(sampler2D image, vec2 position, vec2 input_resolution, vec2 } } +STATIC vec4 scale2x_wrapper(sampler2D t, vec2 pos, vec2 offset, vec2 input_resolution, vec2 output_resolution) +{ + vec2 origin = (floor(pos * input_resolution * 2)) + vec2(0.5, 0.5); + return scale2x(t, (origin + offset) / input_resolution / 2, input_resolution, output_resolution); +} + STATIC vec4 scale(sampler2D image, vec2 position, vec2 input_resolution, vec2 output_resolution) { - // o = offset, the width of a pixel - vec2 o = 1.0 / (input_resolution * 2.); - // texel arrangement // A B C // D E F // G H I - // vec4 A = scale2x(image, position + vec2( -o.x, o.y), input_resolution, output_resolution); - vec4 B = scale2x(image, position + vec2( 0, o.y), input_resolution, output_resolution); - // vec4 C = scale2x(image, position + vec2( o.x, o.y), input_resolution, output_resolution); - vec4 D = scale2x(image, position + vec2( -o.x, 0), input_resolution, output_resolution); - vec4 E = scale2x(image, position + vec2( 0, 0), input_resolution, output_resolution); - vec4 F = scale2x(image, position + vec2( o.x, 0), input_resolution, output_resolution); - // vec4 G = scale2x(image, position + vec2( -o.x, -o.y), input_resolution, output_resolution); - vec4 H = scale2x(image, position + vec2( 0, -o.y), input_resolution, output_resolution); - // vec4 I = scale2x(image, position + vec2( o.x, -o.y), input_resolution, output_resolution); + vec4 B = scale2x_wrapper(image, position, vec2( 0, 1), input_resolution, output_resolution); + vec4 D = scale2x_wrapper(image, position, vec2( -1, 0), input_resolution, output_resolution); + vec4 E = scale2x_wrapper(image, position, vec2( 0, 0), input_resolution, output_resolution); + vec4 F = scale2x_wrapper(image, position, vec2( 1, 0), input_resolution, output_resolution); + vec4 H = scale2x_wrapper(image, position, vec2( 0, -1), input_resolution, output_resolution); + vec2 p = position * input_resolution * 2.; // p = the position within a pixel [0...1] p = fract(p);
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.