Created
May 1, 2024 17:46
-
-
Save Zyko0/413c536b625b7a7dc27ef2030ddfa027 to your computer and use it in GitHub Desktop.
text/v2: DrawTriangles implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bytes" | |
"fmt" | |
"image/color" | |
"log" | |
"os" | |
"runtime/pprof" | |
"github.com/hajimehoshi/ebiten/v2" | |
"github.com/hajimehoshi/ebiten/v2/ebitenutil" | |
"github.com/hajimehoshi/ebiten/v2/text/v2" | |
"golang.org/x/image/font/gofont/goregular" | |
) | |
const ( | |
ScreenWidth, ScreenHeight = 1920, 1080 | |
) | |
var ( | |
glyphAtlas = ebiten.NewImage(256, 256) | |
source *text.GoTextFaceSource | |
face text.Face | |
) | |
func init() { | |
var err error | |
glyphAtlas.Fill(color.White) | |
source, err = text.NewGoTextFaceSource(bytes.NewReader(goregular.TTF)) | |
if err != nil { | |
log.Fatalf("source goregular font: %v", err) | |
} | |
face = &text.GoTextFace{ | |
Source: source, | |
Size: 14, | |
} | |
} | |
var ( | |
boxIndices = [6]uint16{0, 1, 2, 1, 2, 3} | |
vertices []ebiten.Vertex | |
indices []uint16 | |
glyphs []text.Glyph | |
) | |
func TextDraw(dst *ebiten.Image, str string, face text.Face, options *text.DrawOptions) { | |
var layoutOp text.LayoutOptions | |
var drawOp ebiten.DrawImageOptions | |
if options != nil { | |
layoutOp = options.LayoutOptions | |
drawOp = options.DrawImageOptions | |
} | |
geoM := drawOp.GeoM | |
vertices = vertices[:0] | |
indices = indices[:0] | |
var index int | |
x, y := geoM.Apply(0, 0) | |
for _, g := range text.AppendGlyphs(glyphs[:0], str, face, &layoutOp) { | |
if g.Image == nil { | |
continue | |
} | |
gx := x + g.X | |
gy := y + g.Y | |
rect := g.Image.Bounds() | |
vertices = append(vertices, | |
ebiten.Vertex{ | |
DstX: float32(gx), | |
DstY: float32(gy), | |
SrcX: float32(rect.Min.X), | |
SrcY: float32(rect.Min.Y), | |
ColorR: 1, | |
ColorG: 1, | |
ColorB: 1, | |
ColorA: 1, | |
}, | |
ebiten.Vertex{ | |
DstX: float32(gx + float64(rect.Dx())), | |
DstY: float32(gy), | |
SrcX: float32(rect.Max.X), | |
SrcY: float32(rect.Min.Y), | |
ColorR: 1, | |
ColorG: 1, | |
ColorB: 1, | |
ColorA: 1, | |
}, | |
ebiten.Vertex{ | |
DstX: float32(gx), | |
DstY: float32(gy + float64(rect.Dy())), | |
SrcX: float32(rect.Min.X), | |
SrcY: float32(rect.Max.Y), | |
ColorR: 1, | |
ColorG: 1, | |
ColorB: 1, | |
ColorA: 1, | |
}, | |
ebiten.Vertex{ | |
DstX: float32(gx + float64(rect.Dx())), | |
DstY: float32(gy + float64(rect.Dy())), | |
SrcX: float32(rect.Max.X), | |
SrcY: float32(rect.Max.Y), | |
ColorR: 1, | |
ColorG: 1, | |
ColorB: 1, | |
ColorA: 1, | |
}, | |
) | |
indiceCursor := uint16(index * 4) | |
indices = append(indices, | |
boxIndices[0]+indiceCursor, | |
boxIndices[1]+indiceCursor, | |
boxIndices[2]+indiceCursor, | |
boxIndices[3]+indiceCursor, | |
boxIndices[4]+indiceCursor, | |
boxIndices[5]+indiceCursor, | |
) | |
index++ | |
} | |
dst.DrawTriangles(vertices, indices, glyphAtlas, nil) | |
} | |
type Game struct{} | |
func (g *Game) Update() error { | |
if ebiten.IsKeyPressed(ebiten.KeyEscape) { | |
return ebiten.Termination | |
} | |
return nil | |
} | |
const str = "My big sentence containing many glyphs resolving into probably too many DrawImage, but let's see, who am I to assess something without taking measurements first" | |
func (g *Game) Draw(screen *ebiten.Image) { | |
opts := &text.DrawOptions{} | |
opts.GeoM.Translate(64, 64) | |
text.Draw(screen, str, face, opts) | |
opts.GeoM.Translate(0, 64) | |
TextDraw(screen, str, face, opts) | |
ebitenutil.DebugPrint(screen, | |
fmt.Sprintf("TPS %.2f - FPS %.2f", | |
ebiten.ActualTPS(), ebiten.ActualFPS(), | |
), | |
) | |
} | |
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) { | |
return ScreenWidth, ScreenHeight | |
} | |
func main() { | |
ebiten.SetFullscreen(true) | |
ebiten.SetVsyncEnabled(false) | |
f, err := os.Create("profile.prof") | |
if err != nil { | |
log.Fatal(err) | |
} | |
if err := pprof.StartCPUProfile(f); err != nil { | |
log.Fatal(err) | |
} | |
defer pprof.StopCPUProfile() | |
if err := ebiten.RunGame(&Game{}); err != nil && err != ebiten.Termination { | |
log.Fatal(err) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment