From bae8f9d87477bacd66ea0fe9ec5b815b1a8e52f7 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Tue, 20 Mar 2018 03:51:32 +0900 Subject: [PATCH] graphics: Bug fix: More strict calculation for the nearest filter (#558) --- image_test.go | 4 ++-- internal/graphics/program.go | 17 ++++++++--------- internal/graphics/shader.go | 35 +++++++++++++++++++++-------------- 3 files changed, 31 insertions(+), 25 deletions(-) diff --git a/image_test.go b/image_test.go index 5151fa11b..7aa89cb19 100644 --- a/image_test.go +++ b/image_test.go @@ -504,7 +504,7 @@ func TestImageFill(t *testing.T) { } } -// Issue #317 +// Issue #317, #558 func TestImageEdge(t *testing.T) { const ( img0Width = 16 @@ -537,7 +537,7 @@ func TestImageEdge(t *testing.T) { transparent := color.RGBA{0, 0, 0, 0} for _, f := range []Filter{FilterNearest, FilterLinear} { - for a := 0; a < 360; a += 5 { + for a := 0; a < 360; a++ { img1.Clear() op := &DrawImageOptions{} w, h := img0.Size() diff --git a/internal/graphics/program.go b/internal/graphics/program.go index 73dec8933..833277668 100644 --- a/internal/graphics/program.go +++ b/internal/graphics/program.go @@ -321,17 +321,16 @@ func (s *openGLState) useProgram(proj []float32, texture opengl.Texture, dst, sr s.lastColorMatrixTranslation = esTranslate } - if program == s.programLinear || program == s.programScreen { - sw, sh := src.Size() - sw = emath.NextPowerOf2Int(sw) - sh = emath.NextPowerOf2Int(sh) + sw, sh := src.Size() + sw = emath.NextPowerOf2Int(sw) + sh = emath.NextPowerOf2Int(sh) - if s.lastSourceWidth != sw || s.lastSourceHeight != sh { - c.UniformFloats(program, "source_size", []float32{float32(sw), float32(sh)}) - s.lastSourceWidth = sw - s.lastSourceHeight = sh - } + if s.lastSourceWidth != sw || s.lastSourceHeight != sh { + c.UniformFloats(program, "source_size", []float32{float32(sw), float32(sh)}) + s.lastSourceWidth = sw + s.lastSourceHeight = sh } + if program == s.programScreen { sw, _ := src.Size() dw, _ := dst.Size() diff --git a/internal/graphics/shader.go b/internal/graphics/shader.go index fe7c01f67..47653cc82 100644 --- a/internal/graphics/shader.go +++ b/internal/graphics/shader.go @@ -76,9 +76,7 @@ uniform sampler2D texture; uniform mat4 color_matrix; uniform vec4 color_matrix_translation; -#if defined(FILTER_LINEAR) || defined(FILTER_SCREEN) uniform highp vec2 source_size; -#endif #if defined(FILTER_SCREEN) uniform highp float scale; @@ -104,19 +102,10 @@ void main(void) { // roundTexel adjusts pos by rounding it (#315, #558). pos = roundTexel(pos); -#if defined(FILTER_NEAREST) - vec4 color = texture2D(texture, pos); - if (pos.x < varying_tex_coord_min.x || - pos.y < varying_tex_coord_min.y || - varying_tex_coord_max.x <= pos.x || - varying_tex_coord_max.y <= pos.y) { - color = vec4(0, 0, 0, 0); - } -#endif - -#if defined(FILTER_LINEAR) highp vec2 texel_size = 1.0 / source_size; +#if defined(FILTER_NEAREST) || defined(FILTER_LINEAR) + // Even with the nearest filter, it is better to calculate the color with around 4 texels (#558). highp vec2 p0 = pos - texel_size / 2.0; highp vec2 p1 = pos + texel_size / 2.0; vec4 c0 = texture2D(texture, p0); @@ -141,11 +130,29 @@ void main(void) { } vec2 rate = fract(p0 * source_size); + +#if defined(FILTER_NEAREST) + vec4 color; + if (rate.x < 0.5) { + if (rate.y < 0.5) { + color = c0; + } else { + color = c2; + } + } else { + if (rate.y < 0.5) { + color = c1; + } else { + color = c3; + } + } +#elif defined(FILTER_LINEAR) vec4 color = mix(mix(c0, c1, rate.x), mix(c2, c3, rate.x), rate.y); #endif +#endif + #if defined(FILTER_SCREEN) - highp vec2 texel_size = 1.0 / source_size; pos -= texel_size / 2.0 / scale; highp vec2 p0 = pos;