From bf63d2310d18a33471a8f315731768a558ebd416 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Sat, 18 Mar 2023 10:17:13 +0900 Subject: [PATCH] ebitenutil: revert the implementation of Draw* functions Using vector functions caused unexpected increase of draw calls. Revert the Draw* functions to use regular DrawImage/DrawTriangles. Closes #2605 --- ebitenutil/shapes.go | 58 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/ebitenutil/shapes.go b/ebitenutil/shapes.go index e2a86e7b5..5209bfbb6 100644 --- a/ebitenutil/shapes.go +++ b/ebitenutil/shapes.go @@ -15,35 +15,79 @@ package ebitenutil import ( + "image" "image/color" + "math" "github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2/vector" ) +var ( + whiteImage = ebiten.NewImage(3, 3) + whiteSubImage = whiteImage.SubImage(image.Rect(1, 1, 2, 2)).(*ebiten.Image) +) + +func init() { + pix := make([]byte, 4*3*3) + for i := range pix { + pix[i] = 0xff + } + whiteImage.WritePixels(pix) +} + // DrawLine draws a line segment on the given destination dst. // // DrawLine is intended to be used mainly for debugging or prototyping purpose. // -// Deprecated: as of v2.5. Use vector.StrokeLine instead. +// Use vector.StrokeLine instead if you require rendering with higher quality. func DrawLine(dst *ebiten.Image, x1, y1, x2, y2 float64, clr color.Color) { - vector.StrokeLine(dst, float32(x1), float32(y1), float32(x2), float32(y2), 1, clr) + length := math.Hypot(x2-x1, y2-y1) + + op := &ebiten.DrawImageOptions{} + op.GeoM.Scale(length, 1) + op.GeoM.Rotate(math.Atan2(y2-y1, x2-x1)) + op.GeoM.Translate(x1, y1) + op.ColorM.ScaleWithColor(clr) + // Filter must be 'nearest' filter (default). + // Linear filtering would make edges blurred. + dst.DrawImage(whiteSubImage, op) } // DrawRect draws a rectangle on the given destination dst. // // DrawRect is intended to be used mainly for debugging or prototyping purpose. // -// Deprecated: as of v2.5. Use vector.DrawFilledRect instead. +// Use vector.DrawFilledRect instead if you require rendering with higher quality. func DrawRect(dst *ebiten.Image, x, y, width, height float64, clr color.Color) { - vector.DrawFilledRect(dst, float32(x), float32(y), float32(width), float32(height), clr) + op := &ebiten.DrawImageOptions{} + op.GeoM.Scale(width, height) + op.GeoM.Translate(x, y) + op.ColorM.ScaleWithColor(clr) + // Filter must be 'nearest' filter (default). + // Linear filtering would make edges blurred. + dst.DrawImage(whiteImage.SubImage(image.Rect(1, 1, 2, 2)).(*ebiten.Image), op) } // DrawCircle draws a circle on given destination dst. // -// DrawCircle is intended to be used mainly for debugging or prototyping purpose. +// DrawCircle is intended to be used mainly for debugging or prototyping puropose. // -// Deprecated: as of v2.5. Use vector.DrawFilledCircle instead. +// Use vector.DrawFilledCircle instead if you require rendering with higher quality. func DrawCircle(dst *ebiten.Image, cx, cy, r float64, clr color.Color) { - vector.DrawFilledCircle(dst, float32(cx), float32(cy), float32(r), clr) + var path vector.Path + rd, g, b, a := clr.RGBA() + + path.Arc(float32(cx), float32(cy), float32(r), 0, 2*math.Pi, vector.Clockwise) + + vertices, indices := path.AppendVerticesAndIndicesForFilling(nil, nil) + for i := range vertices { + vertices[i].SrcX = 1 + vertices[i].SrcY = 1 + vertices[i].ColorR = float32(rd) / 0xffff + vertices[i].ColorG = float32(g) / 0xffff + vertices[i].ColorB = float32(b) / 0xffff + vertices[i].ColorA = float32(a) / 0xffff + } + dst.DrawTriangles(vertices, indices, whiteSubImage, nil) }