graphicsutil: Add MipmapLevel

This commit is contained in:
Hajime Hoshi 2018-07-31 01:45:42 +09:00
parent b8ab1363d2
commit 0956ca0ea6
3 changed files with 120 additions and 9 deletions

View File

@ -251,12 +251,18 @@ func (i *Image) DrawImage(img *Image, options *DrawImageOptions) error {
a, b, c, d, tx, ty := geom.elements()
level := uint(0)
level := 0
if filter == graphics.FilterLinear {
det := math.Abs(float64(geom.det()))
for det < 0.25 {
level++
det *= 4
det := geom.det()
if det == 0 {
return
}
if math.IsNan(det) {
return
}
level = graphicsutil.MipmapLevel(det)
if level < 0 {
panic("not reached")
}
}
if level > 6 {
@ -264,7 +270,7 @@ func (i *Image) DrawImage(img *Image, options *DrawImageOptions) error {
}
if level > 0 {
s := 1 << level
s := 1 << uint(level)
a *= float32(s)
b *= float32(s)
c *= float32(s)
@ -276,8 +282,8 @@ func (i *Image) DrawImage(img *Image, options *DrawImageOptions) error {
}
w, h = img.shareableImages[len(img.shareableImages)-1].Size()
for uint(len(img.shareableImages)) < level+1 {
lastl := uint(len(img.shareableImages)) - 1
for len(img.shareableImages) < level+1 {
lastl := len(img.shareableImages) - 1
src := img.shareableImages[lastl]
w2 := int(math.Ceil(float64(w) / 2.0))
h2 := int(math.Ceil(float64(h) / 2.0))
@ -298,7 +304,7 @@ func (i *Image) DrawImage(img *Image, options *DrawImageOptions) error {
h = h2
}
if level < uint(len(img.shareableImages)) {
if level < len(img.shareableImages) {
src := img.shareableImages[level]
vs := src.QuadVertices(sx0, sy0, sx1, sy1, a, b, c, d, tx, ty, options.ColorM.impl)
is := graphicsutil.QuadIndices()

View File

@ -0,0 +1,41 @@
// Copyright 2018 The Ebiten Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package graphicsutil
import (
"math"
)
// MipmapLevel returns an appropriate mipmap level for the given determinant of a geometry matrix.
//
// MipmapLevel returns -1 if det is 0.
//
// MipmapLevel panics if det is NaN.
func MipmapLevel(det float32) int {
if math.IsNaN(float64(det)) {
panic("graphicsutil: det must be finite")
}
if det == 0 {
return -1
}
d := math.Abs(float64(det))
level := 0
for d < 0.25 {
level++
d *= 4
}
return level
}

View File

@ -0,0 +1,64 @@
// Copyright 2018 The Ebiten Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package graphicsutil_test
import (
"math"
"testing"
. "github.com/hajimehoshi/ebiten/internal/graphicsutil"
)
func TestMipmapLevel(t *testing.T) {
inf := float32(math.Inf(1))
cases := []struct {
In float32
Out int
}{
{0, -1},
{1, 0},
{-1, 0},
{2, 0},
{-2, 0},
{100, 0},
{-100, 0},
{1.0 / 2.0, 0},
{-1.0 / 2.0, 0},
{1.0 / 4.0, 0},
{-1.0 / 4.0, 0},
{math.Nextafter32(1.0/4.0, 0), 1},
{math.Nextafter32(-1.0/4.0, 0), 1},
{1.0 / 8.0, 1},
{-1.0 / 8.0, 1},
{1.0 / 16.0, 1},
{-1.0 / 16.0, 1},
{math.Nextafter32(1.0/16.0, 0), 2},
{math.Nextafter32(-1.0/16.0, 0), 2},
{math.Nextafter32(1.0/256.0, 0), 4},
{math.Nextafter32(-1.0/256.0, 0), 4},
{math.SmallestNonzeroFloat32, 74},
{-math.SmallestNonzeroFloat32, 74},
{inf, 0},
{-inf, 0},
}
for _, c := range cases {
got := MipmapLevel(c.In)
want := c.Out
if got != want {
t.Errorf("MipmapLevel(%v): got %v, want %v", c.In, got, want)
}
}
}