internal/graphicsdriver/metal, internal/graphicsdriver/opengl: more efficient modulo

This commit is contained in:
Hajime Hoshi 2022-03-04 03:47:55 +09:00
parent ed22052e5f
commit d4d4b9c070
3 changed files with 85 additions and 13 deletions

View File

@ -1318,6 +1318,87 @@ func TestImageAddressRepeat(t *testing.T) {
} }
} }
func TestImageAddressRepeatNegativePosition(t *testing.T) {
const w, h = 16, 16
src := ebiten.NewImage(w, h)
dst := ebiten.NewImage(w, h)
pix := make([]byte, 4*w*h)
for j := 0; j < h; j++ {
for i := 0; i < w; i++ {
idx := 4 * (i + j*w)
if 4 <= i && i < 8 && 4 <= j && j < 8 {
pix[idx] = byte(i-4) * 0x10
pix[idx+1] = byte(j-4) * 0x10
pix[idx+2] = 0
pix[idx+3] = 0xff
} else {
pix[idx] = 0
pix[idx+1] = 0
pix[idx+2] = 0xff
pix[idx+3] = 0xff
}
}
}
src.ReplacePixels(pix)
vs := []ebiten.Vertex{
{
DstX: 0,
DstY: 0,
SrcX: -w,
SrcY: -h,
ColorR: 1,
ColorG: 1,
ColorB: 1,
ColorA: 1,
},
{
DstX: w,
DstY: 0,
SrcX: 0,
SrcY: -h,
ColorR: 1,
ColorG: 1,
ColorB: 1,
ColorA: 1,
},
{
DstX: 0,
DstY: h,
SrcX: -w,
SrcY: 0,
ColorR: 1,
ColorG: 1,
ColorB: 1,
ColorA: 1,
},
{
DstX: w,
DstY: h,
SrcX: 0,
SrcY: 0,
ColorR: 1,
ColorG: 1,
ColorB: 1,
ColorA: 1,
},
}
is := []uint16{0, 1, 2, 1, 2, 3}
op := &ebiten.DrawTrianglesOptions{}
op.Address = ebiten.AddressRepeat
dst.DrawTriangles(vs, is, src.SubImage(image.Rect(4, 4, 8, 8)).(*ebiten.Image), op)
for j := 0; j < h; j++ {
for i := 0; i < w; i++ {
got := dst.At(i, j).(color.RGBA)
want := color.RGBA{byte(i%4) * 0x10, byte(j%4) * 0x10, 0, 0xff}
if !sameColors(got, want, 1) {
t.Errorf("dst.At(%d, %d): got %v, want: %v", i, j, got, want)
}
}
}
}
func TestImageReplacePixelsAfterClear(t *testing.T) { func TestImageReplacePixelsAfterClear(t *testing.T) {
const w, h = 256, 256 const w, h = 256, 256
img := ebiten.NewImage(w, h) img := ebiten.NewImage(w, h)

View File

@ -92,10 +92,8 @@ vertex VertexOut VertexShader(
return out; return out;
} }
float FloorMod(float x, float y) { float EuclideanMod(float x, float y) {
if (x < 0.0) { // Assume that y is always positive.
return y - (-x - y * floor(-x/y));
}
return x - y * floor(x/y); return x - y * floor(x/y);
} }
@ -111,7 +109,7 @@ template<>
inline float2 AdjustTexelByAddress<ADDRESS_REPEAT>(float2 p, float4 source_region) { inline float2 AdjustTexelByAddress<ADDRESS_REPEAT>(float2 p, float4 source_region) {
float2 o = float2(source_region[0], source_region[1]); float2 o = float2(source_region[0], source_region[1]);
float2 size = float2(source_region[2] - source_region[0], source_region[3] - source_region[1]); float2 size = float2(source_region[2] - source_region[0], source_region[3] - source_region[1]);
return float2(FloorMod((p.x - o.x), size.x) + o.x, FloorMod((p.y - o.y), size.y) + o.y); return float2(EuclideanMod((p.x - o.x), size.x) + o.x, EuclideanMod((p.y - o.y), size.y) + o.y);
} }
template<uint8_t filter, uint8_t address> template<uint8_t filter, uint8_t address>

View File

@ -158,13 +158,6 @@ uniform highp float scale;
varying highp vec2 varying_tex; varying highp vec2 varying_tex;
varying highp vec4 varying_color_scale; varying highp vec4 varying_color_scale;
highp float floorMod(highp float x, highp float y) {
if (x < 0.0) {
return y - (-x - y * floor(-x/y));
}
return x - y * floor(x/y);
}
highp vec2 adjustTexelByAddress(highp vec2 p, highp vec4 source_region) { highp vec2 adjustTexelByAddress(highp vec2 p, highp vec4 source_region) {
#if defined(ADDRESS_CLAMP_TO_ZERO) #if defined(ADDRESS_CLAMP_TO_ZERO)
return p; return p;
@ -173,7 +166,7 @@ highp vec2 adjustTexelByAddress(highp vec2 p, highp vec4 source_region) {
#if defined(ADDRESS_REPEAT) #if defined(ADDRESS_REPEAT)
highp vec2 o = vec2(source_region[0], source_region[1]); highp vec2 o = vec2(source_region[0], source_region[1]);
highp vec2 size = vec2(source_region[2] - source_region[0], source_region[3] - source_region[1]); highp vec2 size = vec2(source_region[2] - source_region[0], source_region[3] - source_region[1]);
return vec2(floorMod((p.x - o.x), size.x) + o.x, floorMod((p.y - o.y), size.y) + o.y); return vec2(mod((p.x - o.x), size.x) + o.x, mod((p.y - o.y), size.y) + o.y);
#endif #endif
#if defined(ADDRESS_UNSAFE) #if defined(ADDRESS_UNSAFE)