mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 04:57:26 +01:00
graphics: Refactoring: Unify PutVertex and PutQuadVertices implementation
This commit is contained in:
parent
8dc2301e54
commit
69ebc481e8
@ -15,7 +15,6 @@
|
||||
package graphics
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
)
|
||||
|
||||
@ -62,105 +61,19 @@ func VertexSlice(n int) []float32 {
|
||||
return theVerticesBackend.slice(n)
|
||||
}
|
||||
|
||||
func PutQuadVertices(vs []float32, width, height int, sx0, sy0, sx1, sy1 int, a, b, c, d, tx, ty float32, cr, cg, cb, ca float32) {
|
||||
// width and height are the source image's size.
|
||||
|
||||
// For performance reason, graphics.InternalImageSize is not applied to width/height here.
|
||||
|
||||
if !isInternalImageSize(width) {
|
||||
panic(fmt.Sprintf("graphics: width must be an internal image size at QuadVertices: %d", width))
|
||||
}
|
||||
if !isInternalImageSize(height) {
|
||||
panic(fmt.Sprintf("graphics: height must be an internal image size at QuadVertices: %d", height))
|
||||
}
|
||||
|
||||
if sx0 >= sx1 || sy0 >= sy1 {
|
||||
// Do not modify vs. Here, it is assumed that vs is initialized with zero values.
|
||||
return
|
||||
}
|
||||
if sx1 <= 0 || sy1 <= 0 {
|
||||
// Do not modify vs. Here, it is assumed that vs is initialized with zero values.
|
||||
return
|
||||
}
|
||||
|
||||
wf := float32(width)
|
||||
hf := float32(height)
|
||||
u0, v0, u1, v1 := float32(sx0)/wf, float32(sy0)/hf, float32(sx1)/wf, float32(sy1)/hf
|
||||
putQuadVerticesImpl(vs, wf, hf, float32(sx1-sx0), float32(sy1-sy0), u0, v0, u1, v1, a, b, c, d, tx, ty, cr, cg, cb, ca)
|
||||
type VertexPutter interface {
|
||||
PutVertex(dst []float32, dx, dy, sx, sy float32, bx0, by0, bx1, by1 float32, cr, cg, cb, ca float32)
|
||||
}
|
||||
|
||||
const TexelAdjustmentFactor = 512.0
|
||||
|
||||
func putQuadVerticesImpl(vs []float32, sw, sh, x, y, u0, v0, u1, v1, a, b, c, d, tx, ty, cr, cg, cb, ca float32) {
|
||||
// Specifying a range explicitly here is redundant but this helps optimization
|
||||
// to eliminate boundary checks.
|
||||
//
|
||||
// 4*VertexFloatNum is better than 48 in terms of code maintenanceability, but in GopherJS, optimization
|
||||
// might not work.
|
||||
vs = vs[0:48]
|
||||
|
||||
func PutQuadVertices(dst []float32, putter VertexPutter, sx0, sy0, sx1, sy1 int, a, b, c, d, tx, ty float32, cr, cg, cb, ca float32) {
|
||||
x := float32(sx1 - sx0)
|
||||
y := float32(sy1 - sy0)
|
||||
ax, by, cx, dy := a*x, b*y, c*x, d*y
|
||||
|
||||
du := 1.0 / sw / TexelAdjustmentFactor
|
||||
dv := 1.0 / sh / TexelAdjustmentFactor
|
||||
|
||||
// Vertex coordinates
|
||||
vs[0] = tx
|
||||
vs[1] = ty
|
||||
|
||||
// Texture coordinates: first 2 values indicates the actual coodinate, and
|
||||
// the second indicates diagonally opposite coodinates.
|
||||
// The second is needed to calculate source rectangle size in shader programs.
|
||||
vs[2] = u0
|
||||
vs[3] = v0
|
||||
vs[4] = u0
|
||||
vs[5] = v0
|
||||
vs[6] = u1 - du
|
||||
vs[7] = v1 - dv
|
||||
vs[8] = cr
|
||||
vs[9] = cg
|
||||
vs[10] = cb
|
||||
vs[11] = ca
|
||||
|
||||
// and the same for the other three coordinates
|
||||
vs[12] = ax + tx
|
||||
vs[13] = cx + ty
|
||||
vs[14] = u1
|
||||
vs[15] = v0
|
||||
vs[16] = u0
|
||||
vs[17] = v0
|
||||
vs[18] = u1 - du
|
||||
vs[19] = v1 - dv
|
||||
vs[20] = cr
|
||||
vs[21] = cg
|
||||
vs[22] = cb
|
||||
vs[23] = ca
|
||||
|
||||
vs[24] = by + tx
|
||||
vs[25] = dy + ty
|
||||
vs[26] = u0
|
||||
vs[27] = v1
|
||||
vs[28] = u0
|
||||
vs[29] = v0
|
||||
vs[30] = u1 - du
|
||||
vs[31] = v1 - dv
|
||||
vs[32] = cr
|
||||
vs[33] = cg
|
||||
vs[34] = cb
|
||||
vs[35] = ca
|
||||
|
||||
vs[36] = ax + by + tx
|
||||
vs[37] = cx + dy + ty
|
||||
vs[38] = u1
|
||||
vs[39] = v1
|
||||
vs[40] = u0
|
||||
vs[41] = v0
|
||||
vs[42] = u1 - du
|
||||
vs[43] = v1 - dv
|
||||
vs[44] = cr
|
||||
vs[45] = cg
|
||||
vs[46] = cb
|
||||
vs[47] = ca
|
||||
u0, v0, u1, v1 := float32(sx0), float32(sy0), float32(sx1), float32(sy1)
|
||||
putter.PutVertex(dst[:VertexFloatNum], tx, ty, u0, v0, u0, v0, u1, v1, cr, cg, cb, ca)
|
||||
putter.PutVertex(dst[VertexFloatNum:2*VertexFloatNum], ax+tx, cx+ty, u1, v0, u0, v0, u1, v1, cr, cg, cb, ca)
|
||||
putter.PutVertex(dst[2*VertexFloatNum:3*VertexFloatNum], by+tx, dy+ty, u0, v1, u0, v0, u1, v1, cr, cg, cb, ca)
|
||||
putter.PutVertex(dst[3*VertexFloatNum:4*VertexFloatNum], ax+by+tx, cx+dy+ty, u1, v1, u0, v0, u1, v1, cr, cg, cb, ca)
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -42,13 +42,35 @@ func TestMain(m *testing.M) {
|
||||
os.Exit(code)
|
||||
}
|
||||
|
||||
type testVertexPutter struct {
|
||||
w float32
|
||||
h float32
|
||||
}
|
||||
|
||||
func (t *testVertexPutter) PutVertex(vs []float32, dx, dy, sx, sy float32, bx0, by0, bx1, by1 float32, cr, cg, cb, ca float32) {
|
||||
// The implementation is basically same as restorable.(*Image).PutVertex.
|
||||
// This doesn't adjust texels, but this is fine as long as the rectangle is not rotated or scaled.
|
||||
vs[0] = dx
|
||||
vs[1] = dy
|
||||
vs[2] = sx / t.w
|
||||
vs[3] = sy / t.h
|
||||
vs[4] = bx0 / t.w
|
||||
vs[5] = by0 / t.h
|
||||
vs[6] = bx1 / t.w
|
||||
vs[7] = by1 / t.h
|
||||
vs[8] = cr
|
||||
vs[9] = cg
|
||||
vs[10] = cb
|
||||
vs[11] = ca
|
||||
}
|
||||
|
||||
func TestClear(t *testing.T) {
|
||||
const w, h = 1024, 1024
|
||||
src := NewImage(w/2, h/2)
|
||||
dst := NewImage(w, h)
|
||||
|
||||
vs := graphics.VertexSlice(4)
|
||||
graphics.PutQuadVertices(vs, w/2, h/2, 0, 0, w/2, h/2, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1)
|
||||
graphics.PutQuadVertices(vs, &testVertexPutter{w / 2, h / 2}, 0, 0, w/2, h/2, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1)
|
||||
is := graphics.QuadIndices()
|
||||
dst.DrawTriangles(src, vs, is, nil, graphics.CompositeModeClear, graphics.FilterNearest, graphics.AddressClampToZero)
|
||||
|
||||
@ -76,7 +98,7 @@ func TestReplacePixelsPartAfterDrawTriangles(t *testing.T) {
|
||||
src := NewImage(16, 16)
|
||||
dst := NewImage(w, h)
|
||||
vs := graphics.VertexSlice(4)
|
||||
graphics.PutQuadVertices(vs, 16, 16, 0, 0, w, h, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1)
|
||||
graphics.PutQuadVertices(vs, &testVertexPutter{w / 2, h / 2}, 0, 0, w, h, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1)
|
||||
is := graphics.QuadIndices()
|
||||
dst.DrawTriangles(clr, vs, is, nil, graphics.CompositeModeClear, graphics.FilterNearest, graphics.AddressClampToZero)
|
||||
dst.DrawTriangles(src, vs, is, nil, graphics.CompositeModeSourceOver, graphics.FilterNearest, graphics.AddressClampToZero)
|
||||
|
@ -196,7 +196,7 @@ func (i *Image) fill(r, g, b, a uint8) {
|
||||
dw, dh := i.internalSize()
|
||||
sw, sh := emptyImage.Size()
|
||||
vs := graphics.VertexSlice(4)
|
||||
graphics.PutQuadVertices(vs, dw, dh, 0, 0, sw, sh,
|
||||
graphics.PutQuadVertices(vs, i, 0, 0, sw, sh,
|
||||
float32(dw)/float32(sw), 0, 0, float32(dh)/float32(sh), 0, 0,
|
||||
rf, gf, bf, af)
|
||||
is := graphics.QuadIndices()
|
||||
@ -239,12 +239,16 @@ func (i *Image) internalSize() (int, int) {
|
||||
return i.w2, i.h2
|
||||
}
|
||||
|
||||
func (i *Image) PutQuadVertices(vs []float32, sx0, sy0, sx1, sy1 int, a, b, c, d, tx, ty float32, cr, cg, cb, ca float32) {
|
||||
w, h := i.internalSize()
|
||||
graphics.PutQuadVertices(vs, w, h, sx0, sy0, sx1, sy1, a, b, c, d, tx, ty, cr, cg, cb, ca)
|
||||
}
|
||||
|
||||
func (i *Image) PutVertex(vs []float32, dx, dy, sx, sy float32, bx0, by0, bx1, by1 float32, cr, cg, cb, ca float32) {
|
||||
const texelAdjustmentFactor = 512.0
|
||||
|
||||
// Specifying a range explicitly here is redundant but this helps optimization
|
||||
// to eliminate boundary checks.
|
||||
//
|
||||
// VertexFloatNum is better than 12 in terms of code maintenanceability, but in GopherJS, optimization
|
||||
// might not work.
|
||||
vs = vs[0:12]
|
||||
|
||||
w, h := i.internalSize()
|
||||
vs[0] = dx
|
||||
vs[1] = dy
|
||||
@ -252,8 +256,8 @@ func (i *Image) PutVertex(vs []float32, dx, dy, sx, sy float32, bx0, by0, bx1, b
|
||||
vs[3] = sy / float32(h)
|
||||
vs[4] = bx0 / float32(w)
|
||||
vs[5] = by0 / float32(h)
|
||||
vs[6] = bx1/float32(w) - 1.0/float32(w)/graphics.TexelAdjustmentFactor
|
||||
vs[7] = by1/float32(h) - 1.0/float32(h)/graphics.TexelAdjustmentFactor
|
||||
vs[6] = bx1/float32(w) - 1.0/float32(w)/texelAdjustmentFactor
|
||||
vs[7] = by1/float32(h) - 1.0/float32(h)/texelAdjustmentFactor
|
||||
vs[8] = cr
|
||||
vs[9] = cg
|
||||
vs[10] = cb
|
||||
|
@ -107,7 +107,7 @@ func TestRestoreWithoutDraw(t *testing.T) {
|
||||
|
||||
func quadVertices(src *Image, sw, sh, x, y int) []float32 {
|
||||
vs := graphics.VertexSlice(4)
|
||||
src.PutQuadVertices(vs, 0, 0, sw, sh,
|
||||
graphics.PutQuadVertices(vs, src, 0, 0, sw, sh,
|
||||
1, 0, 0, 1, float32(x), float32(y),
|
||||
1, 1, 1, 1)
|
||||
return vs
|
||||
|
@ -169,10 +169,10 @@ func (i *Image) ensureNotShared() {
|
||||
return
|
||||
}
|
||||
|
||||
x, y, w, h := i.region()
|
||||
_, _, w, h := i.region()
|
||||
newImg := restorable.NewImage(w, h)
|
||||
vs := graphics.VertexSlice(4)
|
||||
i.backend.restorable.PutQuadVertices(vs, x, y, x+w, y+h, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1)
|
||||
i.PutQuadVertices(vs, 0, 0, w, h, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1)
|
||||
is := graphics.QuadIndices()
|
||||
newImg.DrawTriangles(i.backend.restorable, vs, is, nil, graphics.CompositeModeCopy, graphics.FilterNearest, graphics.AddressClampToZero)
|
||||
|
||||
@ -227,26 +227,22 @@ func (i *Image) Size() (width, height int) {
|
||||
return i.width, i.height
|
||||
}
|
||||
|
||||
// PutQuadVertices puts the given dest with vertices for rendering a quad.
|
||||
//
|
||||
// PutQuadVertices is highly optimized for rendering quads, and that's the most significant difference from
|
||||
// PutVertices.
|
||||
func (i *Image) PutQuadVertices(vs []float32, sx0, sy0, sx1, sy1 int, a, b, c, d, tx, ty float32, cr, cg, cb, ca float32) {
|
||||
// PutQuadVertices puts the given dst with vertices for rendering a quad.
|
||||
func (i *Image) PutQuadVertices(dst []float32, sx0, sy0, sx1, sy1 int, a, b, c, d, tx, ty float32, cr, cg, cb, ca float32) {
|
||||
if i.backend == nil {
|
||||
i.allocate(true)
|
||||
}
|
||||
ox, oy, _, _ := i.region()
|
||||
i.backend.restorable.PutQuadVertices(vs, sx0+ox, sy0+oy, sx1+ox, sy1+oy, a, b, c, d, tx, ty, cr, cg, cb, ca)
|
||||
graphics.PutQuadVertices(dst, i, sx0, sy0, sx1, sy1, a, b, c, d, tx, ty, cr, cg, cb, ca)
|
||||
}
|
||||
|
||||
// PutVertices puts the given dest with vertices that can be passed to DrawTriangles.
|
||||
func (i *Image) PutVertex(dest []float32, dx, dy, sx, sy float32, bx0, by0, bx1, by1 float32, cr, cg, cb, ca float32) {
|
||||
// PutVertices puts the given dst with vertices that can be passed to DrawTriangles.
|
||||
func (i *Image) PutVertex(dst []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)
|
||||
i.backend.restorable.PutVertex(dest, dx, dy, sx+oxf, sy+oyf, bx0+oxf, by0+oyf, bx1+oxf, by1+oyf, cr, cg, cb, ca)
|
||||
i.backend.restorable.PutVertex(dst, dx, dy, sx+oxf, sy+oyf, bx0+oxf, by0+oyf, bx1+oxf, by1+oyf, cr, cg, cb, ca)
|
||||
}
|
||||
|
||||
func (i *Image) DrawTriangles(img *Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode graphics.CompositeMode, filter graphics.Filter, address graphics.Address) {
|
||||
|
Loading…
Reference in New Issue
Block a user