mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 02:38:53 +01:00
graphics: Use source-border check even at DrawTriangles
DrawTriangles can now take a sub-image.
This commit is contained in:
parent
4149a56524
commit
189b8a17e9
16
image.go
16
image.go
@ -411,6 +411,7 @@ type Vertex struct {
|
||||
DstY float32
|
||||
|
||||
// SrcX and SrcY represents a point on a source image.
|
||||
// Note that SrcX/SrcY on a sub-image should be in its bounds.
|
||||
SrcX float32
|
||||
SrcY float32
|
||||
|
||||
@ -452,11 +453,6 @@ const MaxIndicesNum = graphics.IndicesNum
|
||||
//
|
||||
// The rule in which DrawTriangles works effectively is same as DrawImage's.
|
||||
//
|
||||
// In contrast to DrawImage, DrawTriangles doesn't care source image edges.
|
||||
// This means that you might need to add 1px gap on a source region when you render an image by DrawTriangles.
|
||||
// Note that Ebiten creates texture atlases internally, so you still have to care this even when
|
||||
// you render a single image.
|
||||
//
|
||||
// When the image i is disposed, DrawTriangles does nothing.
|
||||
//
|
||||
// Internal mipmap is not used on DrawTriangles.
|
||||
@ -468,10 +464,6 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: Implement this.
|
||||
if img.isSubimage() {
|
||||
panic("using a subimage at DrawTriangles is not implemented")
|
||||
}
|
||||
if i.isSubimage() {
|
||||
panic("render to a subimage is not implemented")
|
||||
}
|
||||
@ -499,8 +491,12 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o
|
||||
|
||||
vs := make([]float32, len(vertices)*graphics.VertexFloatNum)
|
||||
src := img.mipmap.original()
|
||||
r := img.Bounds()
|
||||
for idx, v := range vertices {
|
||||
src.PutVertex(vs[idx*graphics.VertexFloatNum:(idx+1)*graphics.VertexFloatNum], float32(v.DstX), float32(v.DstY), v.SrcX, v.SrcY, v.ColorR, v.ColorG, v.ColorB, v.ColorA)
|
||||
src.PutVertex(vs[idx*graphics.VertexFloatNum:(idx+1)*graphics.VertexFloatNum],
|
||||
float32(v.DstX), float32(v.DstY), v.SrcX, v.SrcY,
|
||||
float32(r.Min.X), float32(r.Min.Y), float32(r.Max.X), float32(r.Max.Y),
|
||||
v.ColorR, v.ColorG, v.ColorB, v.ColorA)
|
||||
}
|
||||
i.mipmap.original().DrawImage(img.mipmap.original(), vs, indices, options.ColorM.impl, mode, filter)
|
||||
i.disposeMipmaps()
|
||||
|
118
image_test.go
118
image_test.go
@ -606,38 +606,96 @@ func TestImageEdge(t *testing.T) {
|
||||
for _, s := range []float64{1, 0.5, 0.25} {
|
||||
for _, f := range []Filter{FilterNearest, FilterLinear} {
|
||||
for _, a := range angles {
|
||||
img1.Clear()
|
||||
op := &DrawImageOptions{}
|
||||
w, h := img0Sub.Size()
|
||||
op.GeoM.Translate(-float64(w)/2, -float64(h)/2)
|
||||
op.GeoM.Scale(s, s)
|
||||
op.GeoM.Rotate(a)
|
||||
op.GeoM.Translate(img1Width/2, img1Height/2)
|
||||
op.Filter = f
|
||||
img1.DrawImage(img0Sub, op)
|
||||
allTransparent := true
|
||||
for j := 0; j < img1Height; j++ {
|
||||
for i := 0; i < img1Width; i++ {
|
||||
c := img1.At(i, j)
|
||||
if c == transparent {
|
||||
continue
|
||||
for _, testDrawTriangles := range []bool{false, true} {
|
||||
img1.Clear()
|
||||
w, h := img0Sub.Size()
|
||||
b := img0Sub.Bounds()
|
||||
var geo GeoM
|
||||
geo.Translate(-float64(w)/2, -float64(h)/2)
|
||||
geo.Scale(s, s)
|
||||
geo.Rotate(a)
|
||||
geo.Translate(img1Width/2, img1Height/2)
|
||||
if !testDrawTriangles {
|
||||
op := &DrawImageOptions{}
|
||||
op.GeoM = geo
|
||||
op.Filter = f
|
||||
img1.DrawImage(img0Sub, op)
|
||||
} else {
|
||||
op := &DrawTrianglesOptions{}
|
||||
dx0, dy0 := geo.Apply(0, 0)
|
||||
dx1, dy1 := geo.Apply(float64(w), 0)
|
||||
dx2, dy2 := geo.Apply(0, float64(h))
|
||||
dx3, dy3 := geo.Apply(float64(w), float64(h))
|
||||
vs := []Vertex{
|
||||
{
|
||||
DstX: float32(dx0),
|
||||
DstY: float32(dy0),
|
||||
SrcX: float32(b.Min.X),
|
||||
SrcY: float32(b.Min.Y),
|
||||
ColorR: 1,
|
||||
ColorG: 1,
|
||||
ColorB: 1,
|
||||
ColorA: 1,
|
||||
},
|
||||
{
|
||||
DstX: float32(dx1),
|
||||
DstY: float32(dy1),
|
||||
SrcX: float32(b.Max.X),
|
||||
SrcY: float32(b.Min.Y),
|
||||
ColorR: 1,
|
||||
ColorG: 1,
|
||||
ColorB: 1,
|
||||
ColorA: 1,
|
||||
},
|
||||
{
|
||||
DstX: float32(dx2),
|
||||
DstY: float32(dy2),
|
||||
SrcX: float32(b.Min.X),
|
||||
SrcY: float32(b.Max.Y),
|
||||
ColorR: 1,
|
||||
ColorG: 1,
|
||||
ColorB: 1,
|
||||
ColorA: 1,
|
||||
},
|
||||
{
|
||||
DstX: float32(dx3),
|
||||
DstY: float32(dy3),
|
||||
SrcX: float32(b.Max.X),
|
||||
SrcY: float32(b.Max.Y),
|
||||
ColorR: 1,
|
||||
ColorG: 1,
|
||||
ColorB: 1,
|
||||
ColorA: 1,
|
||||
},
|
||||
}
|
||||
allTransparent = false
|
||||
switch f {
|
||||
case FilterNearest:
|
||||
if c == red {
|
||||
continue
|
||||
}
|
||||
case FilterLinear:
|
||||
if _, g, b, _ := c.RGBA(); g == 0 && b == 0 {
|
||||
continue
|
||||
}
|
||||
}
|
||||
t.Fatalf("img1.At(%d, %d) (filter: %d, scale: %f, angle: %f) want: red or transparent, got: %v", i, j, f, s, a, c)
|
||||
is := graphics.QuadIndices()
|
||||
op.Filter = f
|
||||
img1.DrawTriangles(vs, is, img0Sub, op)
|
||||
}
|
||||
allTransparent := true
|
||||
for j := 0; j < img1Height; j++ {
|
||||
for i := 0; i < img1Width; i++ {
|
||||
c := img1.At(i, j)
|
||||
if c == transparent {
|
||||
continue
|
||||
}
|
||||
allTransparent = false
|
||||
switch f {
|
||||
case FilterNearest:
|
||||
if c == red {
|
||||
continue
|
||||
}
|
||||
case FilterLinear:
|
||||
if _, g, b, _ := c.RGBA(); g == 0 && b == 0 {
|
||||
continue
|
||||
}
|
||||
}
|
||||
t.Fatalf("img1.At(%d, %d) (filter: %d, scale: %f, angle: %f, draw-triangles?: %t) want: red or transparent, got: %v", i, j, f, s, a, testDrawTriangles, c)
|
||||
}
|
||||
}
|
||||
if allTransparent {
|
||||
t.Fatalf("img1 (filter: %d, scale: %f, angle: %f, draw-triangles?: %t) is transparent but should not", f, s, a, testDrawTriangles)
|
||||
}
|
||||
}
|
||||
if allTransparent {
|
||||
t.Fatalf("img1 (filter: %d, scale: %f, angle: %f) is transparent but should not", f, s, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -155,7 +155,7 @@ func QuadIndices() []uint16 {
|
||||
return quadIndices
|
||||
}
|
||||
|
||||
func PutVertex(vs []float32, width, height int, dx, dy, sx, sy float32, cr, cg, cb, ca float32) {
|
||||
func PutVertex(vs []float32, width, height int, dx, dy, su, sv float32, u0, v0, u1, v1 float32, cr, cg, cb, ca float32) {
|
||||
if !isPowerOf2(width) {
|
||||
panic("not reached")
|
||||
}
|
||||
@ -163,21 +163,14 @@ func PutVertex(vs []float32, width, height int, dx, dy, sx, sy float32, cr, cg,
|
||||
panic("not reached")
|
||||
}
|
||||
|
||||
wf := float32(width)
|
||||
hf := float32(height)
|
||||
|
||||
// Specify -1 for the source region, which means the source region is ignored.
|
||||
//
|
||||
// NaN would make more sense to represent an invalid state, but vertices including NaN values doesn't work on
|
||||
// some machines (#696). Let's use negative numbers to represent such state.
|
||||
vs[0] = dx
|
||||
vs[1] = dy
|
||||
vs[2] = sx / wf
|
||||
vs[3] = sy / hf
|
||||
vs[4] = 0
|
||||
vs[5] = 0
|
||||
vs[6] = 1
|
||||
vs[7] = 1
|
||||
vs[2] = su
|
||||
vs[3] = sv
|
||||
vs[4] = u0
|
||||
vs[5] = v0
|
||||
vs[6] = u1
|
||||
vs[7] = v1
|
||||
vs[8] = cr
|
||||
vs[9] = cg
|
||||
vs[10] = cb
|
||||
|
@ -197,13 +197,23 @@ func (i *Image) QuadVertices(sx0, sy0, sx1, sy1 int, a, b, c, d, tx, ty float32,
|
||||
return graphics.QuadVertices(w, h, sx0+ox, sy0+oy, sx1+ox, sy1+oy, a, b, c, d, tx, ty, cr, cg, cb, ca)
|
||||
}
|
||||
|
||||
func (i *Image) PutVertex(dest []float32, dx, dy, sx, sy float32, cr, cg, cb, ca float32) {
|
||||
func (i *Image) PutVertex(dest []float32, dx, dy, sx, sy float32, bx0, by0, bx1, by1 float32,
|
||||
cr, cg, cb, ca float32) {
|
||||
if i.backend == nil {
|
||||
i.allocate(true)
|
||||
}
|
||||
ox, oy, _, _ := i.region()
|
||||
oxf, oyf := float32(ox), float32(oy)
|
||||
w, h := i.backend.restorable.SizePowerOf2()
|
||||
graphics.PutVertex(dest, w, h, dx, dy, sx+float32(ox), sy+float32(oy), cr, cg, cb, ca)
|
||||
|
||||
su := (sx + oxf) / float32(w)
|
||||
sv := (sy + oyf) / float32(h)
|
||||
u0 := (bx0 + oxf) / float32(w)
|
||||
v0 := (by0 + oyf) / float32(h)
|
||||
u1 := (bx1 + oxf) / float32(w)
|
||||
v1 := (by1 + oyf) / float32(h)
|
||||
|
||||
graphics.PutVertex(dest, w, h, dx, dy, su, sv, u0, v0, u1, v1, cr, cg, cb, ca)
|
||||
}
|
||||
|
||||
const MaxCountForShare = 10
|
||||
|
Loading…
Reference in New Issue
Block a user