Compare commits

..

No commits in common. "b6ab7a10c1f57218499ced930a881ef1738af946" and "89933bf0ab1ca02db49ab74305129cbbe441a091" have entirely different histories.

13 changed files with 127 additions and 217 deletions

View File

@ -247,7 +247,7 @@ func (i *Image) DrawImage(img *Image, options *DrawImageOptions) {
colorm, cr, cg, cb, ca := colorMToScale(options.ColorM.affineColorM()) colorm, cr, cg, cb, ca := colorMToScale(options.ColorM.affineColorM())
cr, cg, cb, ca = options.ColorScale.apply(cr, cg, cb, ca) cr, cg, cb, ca = options.ColorScale.apply(cr, cg, cb, ca)
vs := i.ensureTmpVertices(4 * graphics.VertexFloatCount) vs := i.ensureTmpVertices(4 * graphics.VertexFloatCount)
graphics.QuadVerticesFromSrcAndMatrix(vs, float32(sx0), float32(sy0), float32(sx1), float32(sy1), a, b, c, d, tx, ty, cr, cg, cb, ca) graphics.QuadVertices(vs, float32(sx0), float32(sy0), float32(sx1), float32(sy1), a, b, c, d, tx, ty, cr, cg, cb, ca)
is := graphics.QuadIndices() is := graphics.QuadIndices()
srcs := [graphics.ShaderSrcImageCount]*ui.Image{img.image} srcs := [graphics.ShaderSrcImageCount]*ui.Image{img.image}
@ -829,7 +829,7 @@ func (i *Image) DrawRectShader(width, height int, shader *Shader, options *DrawR
vs := i.ensureTmpVertices(4 * graphics.VertexFloatCount) vs := i.ensureTmpVertices(4 * graphics.VertexFloatCount)
// Do not use srcRegions[0].Dx() and srcRegions[0].Dy() as these might be empty. // Do not use srcRegions[0].Dx() and srcRegions[0].Dy() as these might be empty.
graphics.QuadVerticesFromSrcAndMatrix(vs, graphics.QuadVertices(vs,
float32(srcRegions[0].Min.X), float32(srcRegions[0].Min.Y), float32(srcRegions[0].Min.X), float32(srcRegions[0].Min.Y),
float32(srcRegions[0].Min.X+width), float32(srcRegions[0].Min.Y+height), float32(srcRegions[0].Min.X+width), float32(srcRegions[0].Min.Y+height),
a, b, c, d, tx, ty, cr, cg, cb, ca) a, b, c, d, tx, ty, cr, cg, cb, ca)

View File

@ -662,59 +662,6 @@ func BenchmarkDrawImage(b *testing.B) {
} }
} }
func BenchmarkDrawTriangles(b *testing.B) {
const w, h = 16, 16
img0 := ebiten.NewImage(w, h)
img1 := ebiten.NewImage(w, h)
op := &ebiten.DrawTrianglesOptions{}
vs := []ebiten.Vertex{
{
DstX: 0,
DstY: 0,
SrcX: 0,
SrcY: 0,
ColorR: 1,
ColorG: 1,
ColorB: 1,
ColorA: 1,
},
{
DstX: w,
DstY: 0,
SrcX: w,
SrcY: 0,
ColorR: 1,
ColorG: 1,
ColorB: 1,
ColorA: 1,
},
{
DstX: 0,
DstY: h,
SrcX: 0,
SrcY: h,
ColorR: 1,
ColorG: 1,
ColorB: 1,
ColorA: 1,
},
{
DstX: w,
DstY: h,
SrcX: w,
SrcY: h,
ColorR: 1,
ColorG: 1,
ColorB: 1,
ColorA: 1,
},
}
is := []uint16{0, 1, 2, 1, 2, 3}
for i := 0; i < b.N; i++ {
img0.DrawTriangles(vs, is, img1, op)
}
}
func TestImageLinearGraduation(t *testing.T) { func TestImageLinearGraduation(t *testing.T) {
img0 := ebiten.NewImage(2, 2) img0 := ebiten.NewImage(2, 2)
img0.WritePixels([]byte{ img0.WritePixels([]byte{

View File

@ -43,6 +43,16 @@ func min(a, b int) int {
return b return b
} }
// quadVertices returns vertices to render a quad. These values are passed to graphicscommand.Image.
func quadVertices(dx0, dy0, dx1, dy1, sx0, sy0, sx1, sy1, cr, cg, cb, ca float32) []float32 {
return []float32{
dx0, dy0, sx0, sy0, cr, cg, cb, ca,
dx1, dy0, sx1, sy0, cr, cg, cb, ca,
dx0, dy1, sx0, sy1, cr, cg, cb, ca,
dx1, dy1, sx1, sy1, cr, cg, cb, ca,
}
}
func appendDeferred(f func()) { func appendDeferred(f func()) {
deferredM.Lock() deferredM.Lock()
defer deferredM.Unlock() defer deferredM.Unlock()
@ -139,8 +149,7 @@ func (b *backend) extendIfNeeded(width, height int) {
srcs := [graphics.ShaderSrcImageCount]*graphicscommand.Image{b.image} srcs := [graphics.ShaderSrcImageCount]*graphicscommand.Image{b.image}
sw, sh := b.image.InternalSize() sw, sh := b.image.InternalSize()
vs := make([]float32, 4*graphics.VertexFloatCount) vs := quadVertices(0, 0, float32(sw), float32(sh), 0, 0, float32(sw), float32(sh), 1, 1, 1, 1)
graphics.QuadVerticesFromDstAndSrc(vs, 0, 0, float32(sw), float32(sh), 0, 0, float32(sw), float32(sh), 1, 1, 1, 1)
is := graphics.QuadIndices() is := graphics.QuadIndices()
dr := image.Rect(0, 0, sw, sh) dr := image.Rect(0, 0, sw, sh)
newImg.DrawTriangles(srcs, vs, is, graphicsdriver.BlendCopy, dr, [graphics.ShaderSrcImageCount]image.Rectangle{}, NearestFilterShader.ensureShader(), nil, graphicsdriver.FillRuleFillAll) newImg.DrawTriangles(srcs, vs, is, graphicsdriver.BlendCopy, dr, [graphics.ShaderSrcImageCount]image.Rectangle{}, NearestFilterShader.ensureShader(), nil, graphicsdriver.FillRuleFillAll)
@ -165,8 +174,7 @@ func newClearedImage(width, height int, screen bool) *graphicscommand.Image {
} }
func clearImage(i *graphicscommand.Image, region image.Rectangle) { func clearImage(i *graphicscommand.Image, region image.Rectangle) {
vs := make([]float32, 4*graphics.VertexFloatCount) vs := quadVertices(float32(region.Min.X), float32(region.Min.Y), float32(region.Max.X), float32(region.Max.Y), 0, 0, 0, 0, 0, 0, 0, 0)
graphics.QuadVerticesFromDstAndSrc(vs, float32(region.Min.X), float32(region.Min.Y), float32(region.Max.X), float32(region.Max.Y), 0, 0, 0, 0, 0, 0, 0, 0)
is := graphics.QuadIndices() is := graphics.QuadIndices()
i.DrawTriangles([graphics.ShaderSrcImageCount]*graphicscommand.Image{}, vs, is, graphicsdriver.BlendClear, region, [graphics.ShaderSrcImageCount]image.Rectangle{}, clearShader.ensureShader(), nil, graphicsdriver.FillRuleFillAll) i.DrawTriangles([graphics.ShaderSrcImageCount]*graphicscommand.Image{}, vs, is, graphicsdriver.BlendClear, region, [graphics.ShaderSrcImageCount]image.Rectangle{}, clearShader.ensureShader(), nil, graphicsdriver.FillRuleFillAll)
} }
@ -345,7 +353,7 @@ func (i *Image) ensureIsolatedFromSource(backends []*backend) {
w, h := float32(i.width), float32(i.height) w, h := float32(i.width), float32(i.height)
vs := make([]float32, 4*graphics.VertexFloatCount) vs := make([]float32, 4*graphics.VertexFloatCount)
graphics.QuadVerticesFromSrcAndMatrix(vs, 0, 0, w, h, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1) graphics.QuadVertices(vs, 0, 0, w, h, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1)
is := graphics.QuadIndices() is := graphics.QuadIndices()
dr := image.Rect(0, 0, i.width, i.height) dr := image.Rect(0, 0, i.width, i.height)
@ -376,7 +384,7 @@ func (i *Image) putOnSourceBackend() {
w, h := float32(i.width), float32(i.height) w, h := float32(i.width), float32(i.height)
vs := make([]float32, 4*graphics.VertexFloatCount) vs := make([]float32, 4*graphics.VertexFloatCount)
graphics.QuadVerticesFromSrcAndMatrix(vs, 0, 0, w, h, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1) graphics.QuadVertices(vs, 0, 0, w, h, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1)
is := graphics.QuadIndices() is := graphics.QuadIndices()
dr := image.Rect(0, 0, i.width, i.height) dr := image.Rect(0, 0, i.width, i.height)
newI.drawTriangles([graphics.ShaderSrcImageCount]*Image{i}, vs, is, graphicsdriver.BlendCopy, dr, [graphics.ShaderSrcImageCount]image.Rectangle{}, NearestFilterShader, nil, graphicsdriver.FillRuleFillAll) newI.drawTriangles([graphics.ShaderSrcImageCount]*Image{i}, vs, is, graphicsdriver.BlendCopy, dr, [graphics.ShaderSrcImageCount]image.Rectangle{}, NearestFilterShader, nil, graphicsdriver.FillRuleFillAll)

View File

@ -50,9 +50,12 @@ func quadVertices(sw, sh, x, y int, scalex float32) []float32 {
sy0 := float32(0) sy0 := float32(0)
sx1 := float32(sw) sx1 := float32(sw)
sy1 := float32(sh) sy1 := float32(sh)
vs := make([]float32, 4*graphics.VertexFloatCount) return []float32{
graphics.QuadVerticesFromDstAndSrc(vs, dx0, dy0, dx1, dy1, sx0, sy0, sx1, sy1, 1, 1, 1, 1) dx0, dy0, sx0, sy0, 1, 1, 1, 1,
return vs dx1, dy0, sx1, sy0, 1, 1, 1, 1,
dx0, dy1, sx0, sy1, 1, 1, 1, 1,
dx1, dy1, sx1, sy1, 1, 1, 1, 1,
}
} }
const bigSize = 2049 const bigSize = 2049

View File

@ -246,51 +246,45 @@ func (i *Image) syncPixelsIfNeeded() {
cbf := float32(c[2]) / 0xff cbf := float32(c[2]) / 0xff
caf := float32(c[3]) / 0xff caf := float32(c[3]) / 0xff
vidx := 4 * idx vs[graphics.VertexFloatCount*4*idx] = dx
iidx := 6 * idx vs[graphics.VertexFloatCount*4*idx+1] = dy
vs[graphics.VertexFloatCount*4*idx+2] = sx
vs[graphics.VertexFloatCount*4*idx+3] = sy
vs[graphics.VertexFloatCount*4*idx+4] = crf
vs[graphics.VertexFloatCount*4*idx+5] = cgf
vs[graphics.VertexFloatCount*4*idx+6] = cbf
vs[graphics.VertexFloatCount*4*idx+7] = caf
vs[graphics.VertexFloatCount*4*idx+8] = dx + 1
vs[graphics.VertexFloatCount*4*idx+9] = dy
vs[graphics.VertexFloatCount*4*idx+10] = sx + 1
vs[graphics.VertexFloatCount*4*idx+11] = sy
vs[graphics.VertexFloatCount*4*idx+12] = crf
vs[graphics.VertexFloatCount*4*idx+13] = cgf
vs[graphics.VertexFloatCount*4*idx+14] = cbf
vs[graphics.VertexFloatCount*4*idx+15] = caf
vs[graphics.VertexFloatCount*4*idx+16] = dx
vs[graphics.VertexFloatCount*4*idx+17] = dy + 1
vs[graphics.VertexFloatCount*4*idx+18] = sx
vs[graphics.VertexFloatCount*4*idx+19] = sy + 1
vs[graphics.VertexFloatCount*4*idx+20] = crf
vs[graphics.VertexFloatCount*4*idx+21] = cgf
vs[graphics.VertexFloatCount*4*idx+22] = cbf
vs[graphics.VertexFloatCount*4*idx+23] = caf
vs[graphics.VertexFloatCount*4*idx+24] = dx + 1
vs[graphics.VertexFloatCount*4*idx+25] = dy + 1
vs[graphics.VertexFloatCount*4*idx+26] = sx + 1
vs[graphics.VertexFloatCount*4*idx+27] = sy + 1
vs[graphics.VertexFloatCount*4*idx+28] = crf
vs[graphics.VertexFloatCount*4*idx+29] = cgf
vs[graphics.VertexFloatCount*4*idx+30] = cbf
vs[graphics.VertexFloatCount*4*idx+31] = caf
vs[graphics.VertexFloatCount*vidx] = dx is[6*idx] = uint32(4 * idx)
vs[graphics.VertexFloatCount*vidx+1] = dy is[6*idx+1] = uint32(4*idx + 1)
vs[graphics.VertexFloatCount*vidx+2] = sx is[6*idx+2] = uint32(4*idx + 2)
vs[graphics.VertexFloatCount*vidx+3] = sy is[6*idx+3] = uint32(4*idx + 1)
vs[graphics.VertexFloatCount*vidx+4] = crf is[6*idx+4] = uint32(4*idx + 2)
vs[graphics.VertexFloatCount*vidx+5] = cgf is[6*idx+5] = uint32(4*idx + 3)
vs[graphics.VertexFloatCount*vidx+6] = cbf
vs[graphics.VertexFloatCount*vidx+7] = caf
vs[graphics.VertexFloatCount*(vidx+1)] = dx + 1
vs[graphics.VertexFloatCount*(vidx+1)+1] = dy
vs[graphics.VertexFloatCount*(vidx+1)+2] = sx + 1
vs[graphics.VertexFloatCount*(vidx+1)+3] = sy
vs[graphics.VertexFloatCount*(vidx+1)+4] = crf
vs[graphics.VertexFloatCount*(vidx+1)+5] = cgf
vs[graphics.VertexFloatCount*(vidx+1)+6] = cbf
vs[graphics.VertexFloatCount*(vidx+1)+7] = caf
vs[graphics.VertexFloatCount*(vidx+2)] = dx
vs[graphics.VertexFloatCount*(vidx+2)+1] = dy + 1
vs[graphics.VertexFloatCount*(vidx+2)+2] = sx
vs[graphics.VertexFloatCount*(vidx+2)+3] = sy + 1
vs[graphics.VertexFloatCount*(vidx+2)+4] = crf
vs[graphics.VertexFloatCount*(vidx+2)+5] = cgf
vs[graphics.VertexFloatCount*(vidx+2)+6] = cbf
vs[graphics.VertexFloatCount*(vidx+2)+7] = caf
vs[graphics.VertexFloatCount*(vidx+3)] = dx + 1
vs[graphics.VertexFloatCount*(vidx+3)+1] = dy + 1
vs[graphics.VertexFloatCount*(vidx+3)+2] = sx + 1
vs[graphics.VertexFloatCount*(vidx+3)+3] = sy + 1
vs[graphics.VertexFloatCount*(vidx+3)+4] = crf
vs[graphics.VertexFloatCount*(vidx+3)+5] = cgf
vs[graphics.VertexFloatCount*(vidx+3)+6] = cbf
vs[graphics.VertexFloatCount*(vidx+3)+7] = caf
is[iidx] = uint32(vidx)
is[iidx+1] = uint32(vidx + 1)
is[iidx+2] = uint32(vidx + 2)
is[iidx+3] = uint32(vidx + 1)
is[iidx+4] = uint32(vidx + 2)
is[iidx+5] = uint32(vidx + 3)
idx++ idx++
} }

View File

@ -52,7 +52,7 @@ func TestUnsyncedPixels(t *testing.T) {
// Flush unsynced pixel cache. // Flush unsynced pixel cache.
src := buffered.NewImage(16, 16, atlas.ImageTypeRegular) src := buffered.NewImage(16, 16, atlas.ImageTypeRegular)
vs := make([]float32, 4*graphics.VertexFloatCount) vs := make([]float32, 4*graphics.VertexFloatCount)
graphics.QuadVerticesFromSrcAndMatrix(vs, 0, 0, 16, 16, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1) graphics.QuadVertices(vs, 0, 0, 16, 16, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1)
is := graphics.QuadIndices() is := graphics.QuadIndices()
dr := image.Rect(0, 0, 16, 16) dr := image.Rect(0, 0, 16, 16)
sr := [graphics.ShaderSrcImageCount]image.Rectangle{image.Rect(0, 0, 16, 16)} sr := [graphics.ShaderSrcImageCount]image.Rectangle{image.Rect(0, 0, 16, 16)}

View File

@ -50,16 +50,16 @@ func QuadIndices() []uint32 {
return quadIndices return quadIndices
} }
// QuadVerticesFromSrcAndMatrix sets a float32 slice for a quadrangle. // QuadVertices sets a float32 slice for a quadrangle.
func QuadVerticesFromSrcAndMatrix(dst []float32, sx0, sy0, sx1, sy1 float32, a, b, c, d, tx, ty float32, cr, cg, cb, ca float32) { // QuadVertices sets a slice that never overlaps with other slices returned this function,
// and users can do optimization based on this fact.
func QuadVertices(dst []float32, sx0, sy0, sx1, sy1 float32, a, b, c, d, tx, ty float32, cr, cg, cb, ca float32) {
x := sx1 - sx0 x := sx1 - sx0
y := sy1 - sy0 y := sy1 - sy0
ax, by, cx, dy := a*x, b*y, c*x, d*y ax, by, cx, dy := a*x, b*y, c*x, d*y
u0, v0, u1, v1 := sx0, sy0, sx1, sy1 u0, v0, u1, v1 := sx0, sy0, sx1, sy1
// This function is very performance-sensitive and implement in a very dumb way. // This function is very performance-sensitive and implement in a very dumb way.
// Remove the boundary check.
dst = dst[:4*VertexFloatCount] dst = dst[:4*VertexFloatCount]
dst[0] = adjustDestinationPixel(tx) dst[0] = adjustDestinationPixel(tx)
@ -71,79 +71,32 @@ func QuadVerticesFromSrcAndMatrix(dst []float32, sx0, sy0, sx1, sy1 float32, a,
dst[6] = cb dst[6] = cb
dst[7] = ca dst[7] = ca
dst[VertexFloatCount] = adjustDestinationPixel(ax + tx) dst[8] = adjustDestinationPixel(ax + tx)
dst[VertexFloatCount+1] = adjustDestinationPixel(cx + ty) dst[9] = adjustDestinationPixel(cx + ty)
dst[VertexFloatCount+2] = u1 dst[10] = u1
dst[VertexFloatCount+3] = v0 dst[11] = v0
dst[VertexFloatCount+4] = cr dst[12] = cr
dst[VertexFloatCount+5] = cg dst[13] = cg
dst[VertexFloatCount+6] = cb dst[14] = cb
dst[VertexFloatCount+7] = ca dst[15] = ca
dst[2*VertexFloatCount] = adjustDestinationPixel(by + tx) dst[16] = adjustDestinationPixel(by + tx)
dst[2*VertexFloatCount+1] = adjustDestinationPixel(dy + ty) dst[17] = adjustDestinationPixel(dy + ty)
dst[2*VertexFloatCount+2] = u0 dst[18] = u0
dst[2*VertexFloatCount+3] = v1 dst[19] = v1
dst[2*VertexFloatCount+4] = cr dst[20] = cr
dst[2*VertexFloatCount+5] = cg dst[21] = cg
dst[2*VertexFloatCount+6] = cb dst[22] = cb
dst[2*VertexFloatCount+7] = ca dst[23] = ca
dst[3*VertexFloatCount] = adjustDestinationPixel(ax + by + tx) dst[24] = adjustDestinationPixel(ax + by + tx)
dst[3*VertexFloatCount+1] = adjustDestinationPixel(cx + dy + ty) dst[25] = adjustDestinationPixel(cx + dy + ty)
dst[3*VertexFloatCount+2] = u1 dst[26] = u1
dst[3*VertexFloatCount+3] = v1 dst[27] = v1
dst[3*VertexFloatCount+4] = cr dst[28] = cr
dst[3*VertexFloatCount+5] = cg dst[29] = cg
dst[3*VertexFloatCount+6] = cb dst[30] = cb
dst[3*VertexFloatCount+7] = ca dst[31] = ca
}
// QuadVerticesFromDstAndSrc sets a float32 slice for a quadrangle.
func QuadVerticesFromDstAndSrc(dst []float32, dx0, dy0, dx1, dy1, sx0, sy0, sx1, sy1, cr, cg, cb, ca float32) {
dx0 = adjustDestinationPixel(dx0)
dy0 = adjustDestinationPixel(dy0)
dx1 = adjustDestinationPixel(dx1)
dy1 = adjustDestinationPixel(dy1)
// Remove the boundary check.
dst = dst[:4*VertexFloatCount]
dst[0] = dx0
dst[1] = dy0
dst[2] = sx0
dst[3] = sy0
dst[4] = cr
dst[5] = cg
dst[6] = cb
dst[7] = ca
dst[VertexFloatCount] = dx1
dst[VertexFloatCount+1] = dy0
dst[VertexFloatCount+2] = sx1
dst[VertexFloatCount+3] = sy0
dst[VertexFloatCount+4] = cr
dst[VertexFloatCount+5] = cg
dst[VertexFloatCount+6] = cb
dst[VertexFloatCount+7] = ca
dst[2*VertexFloatCount] = dx0
dst[2*VertexFloatCount+1] = dy1
dst[2*VertexFloatCount+2] = sx0
dst[2*VertexFloatCount+3] = sy1
dst[2*VertexFloatCount+4] = cr
dst[2*VertexFloatCount+5] = cg
dst[2*VertexFloatCount+6] = cb
dst[2*VertexFloatCount+7] = ca
dst[3*VertexFloatCount] = dx1
dst[3*VertexFloatCount+1] = dy1
dst[3*VertexFloatCount+2] = sx1
dst[3*VertexFloatCount+3] = sy1
dst[3*VertexFloatCount+4] = cr
dst[3*VertexFloatCount+5] = cg
dst[3*VertexFloatCount+6] = cb
dst[3*VertexFloatCount+7] = ca
} }
func adjustDestinationPixel(x float32) float32 { func adjustDestinationPixel(x float32) float32 {

View File

@ -183,9 +183,9 @@ func dstRegionFromVertices(vertices []float32) (minX, minY, maxX, maxY float32)
maxX = negInf32 maxX = negInf32
maxY = negInf32 maxY = negInf32
for i := 0; i < len(vertices); i += graphics.VertexFloatCount { for i := 0; i < len(vertices)/graphics.VertexFloatCount; i++ {
x := vertices[i] x := vertices[graphics.VertexFloatCount*i]
y := vertices[i+1] y := vertices[graphics.VertexFloatCount*i+1]
if x < minX { if x < minX {
minX = x minX = x
} }

View File

@ -43,9 +43,12 @@ func TestMain(m *testing.M) {
} }
func quadVertices(w, h float32) []float32 { func quadVertices(w, h float32) []float32 {
vs := make([]float32, 8*graphics.VertexFloatCount) return []float32{
graphics.QuadVerticesFromDstAndSrc(vs, 0, 0, w, h, 0, 0, w, h, 1, 1, 1, 1) 0, 0, 0, 0, 1, 1, 1, 1,
return vs w, 0, w, 0, 1, 1, 1, 1,
0, w, 0, h, 1, 1, 1, 1,
w, h, w, h, 1, 1, 1, 1,
}
} }
func TestClear(t *testing.T) { func TestClear(t *testing.T) {

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
//go:build !playstation5 && ebitenginegldebug //go:build ebitenginegldebug
package opengl package opengl

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
//go:build !playstation5 && !ebitenginegldebug //go:build !ebitenginegldebug
package opengl package opengl

View File

@ -73,22 +73,20 @@ func (m *Mipmap) DrawTriangles(srcs [graphics.ShaderSrcImageCount]*Mipmap, verti
level := 0 level := 0
if !canSkipMipmap && srcs[0] != nil && canUseMipmap(srcs[0].imageType) { if !canSkipMipmap && srcs[0] != nil && canUseMipmap(srcs[0].imageType) {
level = math.MaxInt32 level = math.MaxInt32
for i := 0; i < len(indices); i += 3 { for i := 0; i < len(indices)/3; i++ {
idx0 := indices[i] const n = graphics.VertexFloatCount
idx1 := indices[i+1] dx0 := vertices[n*indices[3*i]+0]
idx2 := indices[i+2] dy0 := vertices[n*indices[3*i]+1]
dx0 := vertices[graphics.VertexFloatCount*idx0] sx0 := vertices[n*indices[3*i]+2]
dy0 := vertices[graphics.VertexFloatCount*idx0+1] sy0 := vertices[n*indices[3*i]+3]
sx0 := vertices[graphics.VertexFloatCount*idx0+2] dx1 := vertices[n*indices[3*i+1]+0]
sy0 := vertices[graphics.VertexFloatCount*idx0+3] dy1 := vertices[n*indices[3*i+1]+1]
dx1 := vertices[graphics.VertexFloatCount*idx1] sx1 := vertices[n*indices[3*i+1]+2]
dy1 := vertices[graphics.VertexFloatCount*idx1+1] sy1 := vertices[n*indices[3*i+1]+3]
sx1 := vertices[graphics.VertexFloatCount*idx1+2] dx2 := vertices[n*indices[3*i+2]+0]
sy1 := vertices[graphics.VertexFloatCount*idx1+3] dy2 := vertices[n*indices[3*i+2]+1]
dx2 := vertices[graphics.VertexFloatCount*idx2] sx2 := vertices[n*indices[3*i+2]+2]
dy2 := vertices[graphics.VertexFloatCount*idx2+1] sy2 := vertices[n*indices[3*i+2]+3]
sx2 := vertices[graphics.VertexFloatCount*idx2+2]
sy2 := vertices[graphics.VertexFloatCount*idx2+3]
if l := mipmapLevelFromDistance(dx0, dy0, dx1, dy1, sx0, sy0, sx1, sy1); level > l { if l := mipmapLevelFromDistance(dx0, dy0, dx1, dy1, sx0, sy0, sx1, sy1); level > l {
level = l level = l
} }
@ -111,10 +109,11 @@ func (m *Mipmap) DrawTriangles(srcs [graphics.ShaderSrcImageCount]*Mipmap, verti
} }
if level != 0 { if level != 0 {
if img := src.level(level); img != nil { if img := src.level(level); img != nil {
const n = graphics.VertexFloatCount
s := float32(pow2(level)) s := float32(pow2(level))
for i := 0; i < len(vertices); i += graphics.VertexFloatCount { for i := 0; i < len(vertices)/n; i++ {
vertices[i+2] /= s vertices[i*n+2] /= s
vertices[i+3] /= s vertices[i*n+3] /= s
} }
imgs[i] = img imgs[i] = img
continue continue
@ -149,10 +148,12 @@ func (m *Mipmap) level(level int) *buffered.Image {
var src *buffered.Image var src *buffered.Image
vs := make([]float32, 4*graphics.VertexFloatCount) vs := make([]float32, 4*graphics.VertexFloatCount)
shader := atlas.NearestFilterShader
switch { switch {
case level == 1: case level == 1:
src = m.orig src = m.orig
graphics.QuadVerticesFromSrcAndMatrix(vs, 0, 0, float32(m.width), float32(m.height), 0.5, 0, 0, 0.5, 0, 0, 1, 1, 1, 1) graphics.QuadVertices(vs, 0, 0, float32(m.width), float32(m.height), 0.5, 0, 0, 0.5, 0, 0, 1, 1, 1, 1)
shader = atlas.LinearFilterShader
case level > 1: case level > 1:
src = m.level(level - 1) src = m.level(level - 1)
if src == nil { if src == nil {
@ -161,7 +162,8 @@ func (m *Mipmap) level(level int) *buffered.Image {
} }
w := sizeForLevel(m.width, level-1) w := sizeForLevel(m.width, level-1)
h := sizeForLevel(m.height, level-1) h := sizeForLevel(m.height, level-1)
graphics.QuadVerticesFromSrcAndMatrix(vs, 0, 0, float32(w), float32(h), 0.5, 0, 0, 0.5, 0, 0, 1, 1, 1, 1) graphics.QuadVertices(vs, 0, 0, float32(w), float32(h), 0.5, 0, 0, 0.5, 0, 0, 1, 1, 1, 1)
shader = atlas.LinearFilterShader
default: default:
panic(fmt.Sprintf("mipmap: invalid level: %d", level)) panic(fmt.Sprintf("mipmap: invalid level: %d", level))
} }
@ -184,7 +186,7 @@ func (m *Mipmap) level(level int) *buffered.Image {
s := buffered.NewImage(w2, h2, m.imageType) s := buffered.NewImage(w2, h2, m.imageType)
dstRegion := image.Rect(0, 0, w2, h2) dstRegion := image.Rect(0, 0, w2, h2)
s.DrawTriangles([graphics.ShaderSrcImageCount]*buffered.Image{src}, vs, is, graphicsdriver.BlendCopy, dstRegion, [graphics.ShaderSrcImageCount]image.Rectangle{}, atlas.LinearFilterShader, nil, graphicsdriver.FillRuleFillAll) s.DrawTriangles([graphics.ShaderSrcImageCount]*buffered.Image{src}, vs, is, graphicsdriver.BlendCopy, dstRegion, [graphics.ShaderSrcImageCount]image.Rectangle{}, shader, nil, graphicsdriver.FillRuleFillAll)
m.setImg(level, s) m.setImg(level, s)
return m.imgs[level] return m.imgs[level]

View File

@ -158,7 +158,7 @@ func (i *Image) Fill(r, g, b, a float32, region image.Rectangle) {
i.tmpVerticesForFill = make([]float32, 4*graphics.VertexFloatCount) i.tmpVerticesForFill = make([]float32, 4*graphics.VertexFloatCount)
} }
// i.tmpVerticesForFill can be reused as this is sent to DrawTriangles immediately. // i.tmpVerticesForFill can be reused as this is sent to DrawTriangles immediately.
graphics.QuadVerticesFromSrcAndMatrix( graphics.QuadVertices(
i.tmpVerticesForFill, i.tmpVerticesForFill,
1, 1, float32(i.ui.whiteImage.width-1), float32(i.ui.whiteImage.height-1), 1, 1, float32(i.ui.whiteImage.width-1), float32(i.ui.whiteImage.height-1),
float32(i.width), 0, 0, float32(i.height), 0, 0, float32(i.width), 0, 0, float32(i.height), 0, 0,
@ -235,7 +235,7 @@ func (i *bigOffscreenImage) drawTriangles(srcs [graphics.ShaderSrcImageCount]*Im
i.tmpVerticesForCopying = make([]float32, 4*graphics.VertexFloatCount) i.tmpVerticesForCopying = make([]float32, 4*graphics.VertexFloatCount)
} }
// i.tmpVerticesForCopying can be reused as this is sent to DrawTriangles immediately. // i.tmpVerticesForCopying can be reused as this is sent to DrawTriangles immediately.
graphics.QuadVerticesFromSrcAndMatrix( graphics.QuadVertices(
i.tmpVerticesForCopying, i.tmpVerticesForCopying,
float32(i.region.Min.X), float32(i.region.Min.Y), float32(i.region.Max.X), float32(i.region.Max.Y), float32(i.region.Min.X), float32(i.region.Min.Y), float32(i.region.Max.X), float32(i.region.Max.Y),
bigOffscreenScale, 0, 0, bigOffscreenScale, 0, 0, bigOffscreenScale, 0, 0, bigOffscreenScale, 0, 0,
@ -279,7 +279,7 @@ func (i *bigOffscreenImage) flush() {
i.tmpVerticesForFlushing = make([]float32, 4*graphics.VertexFloatCount) i.tmpVerticesForFlushing = make([]float32, 4*graphics.VertexFloatCount)
} }
// i.tmpVerticesForFlushing can be reused as this is sent to DrawTriangles in this function. // i.tmpVerticesForFlushing can be reused as this is sent to DrawTriangles in this function.
graphics.QuadVerticesFromSrcAndMatrix( graphics.QuadVertices(
i.tmpVerticesForFlushing, i.tmpVerticesForFlushing,
0, 0, float32(i.region.Dx()*bigOffscreenScale), float32(i.region.Dy()*bigOffscreenScale), 0, 0, float32(i.region.Dx()*bigOffscreenScale), float32(i.region.Dy()*bigOffscreenScale),
1.0/bigOffscreenScale, 0, 0, 1.0/bigOffscreenScale, float32(i.region.Min.X), float32(i.region.Min.Y), 1.0/bigOffscreenScale, 0, 0, 1.0/bigOffscreenScale, float32(i.region.Min.X), float32(i.region.Min.Y),