mirror of
https://github.com/bloeys/nterm.git
synced 2025-12-29 14:38:19 +00:00
Improve glyph API
This commit is contained in:
@ -1,7 +1,6 @@
|
|||||||
package glyphs
|
package glyphs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/rand"
|
|
||||||
"os"
|
"os"
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
@ -24,6 +23,9 @@ type GlyphRend struct {
|
|||||||
|
|
||||||
GlyphCount int32
|
GlyphCount int32
|
||||||
GlyphVBO []float32
|
GlyphVBO []float32
|
||||||
|
|
||||||
|
ScreenWidth int32
|
||||||
|
ScreenHeight int32
|
||||||
}
|
}
|
||||||
|
|
||||||
//getGlyphRanges returns a list of ranges, each range is: [i][0]<=range<[i][1]
|
//getGlyphRanges returns a list of ranges, each range is: [i][0]<=range<[i][1]
|
||||||
@ -74,10 +76,10 @@ func getGlyphsFromRanges(ranges [][2]rune) []rune {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gr *GlyphRend) DrawTextOpenGL(text string, startPos *gglm.Vec3, winWidth, winHeight int32) {
|
func (gr *GlyphRend) DrawTextOpenGL(text string, screenPos *gglm.Vec3, color *gglm.Vec4) {
|
||||||
|
|
||||||
//The projection matrix fits the screen size. This is needed so we can size and position characters correctly.
|
//The projection matrix fits the screen size. This is needed so we can size and position characters correctly.
|
||||||
projMtx := gglm.Ortho(0, float32(winWidth), float32(winHeight), 0, 0.1, 10)
|
projMtx := gglm.Ortho(0, float32(gr.ScreenWidth), float32(gr.ScreenHeight), 0, 0.1, 10)
|
||||||
viewMtx := gglm.LookAt(gglm.NewVec3(0, 0, -1), gglm.NewVec3(0, 0, 0), gglm.NewVec3(0, 1, 0))
|
viewMtx := gglm.LookAt(gglm.NewVec3(0, 0, -1), gglm.NewVec3(0, 0, 0), gglm.NewVec3(0, 1, 0))
|
||||||
projViewMtx := projMtx.Clone().Mul(viewMtx)
|
projViewMtx := projMtx.Clone().Mul(viewMtx)
|
||||||
|
|
||||||
@ -89,19 +91,15 @@ func (gr *GlyphRend) DrawTextOpenGL(text string, startPos *gglm.Vec3, winWidth,
|
|||||||
rs := []rune(text)
|
rs := []rune(text)
|
||||||
const floatsPerGlyph = 18
|
const floatsPerGlyph = 18
|
||||||
|
|
||||||
rCol := rand.Float32()
|
pos := screenPos.Clone()
|
||||||
gCol := rand.Float32()
|
|
||||||
bCol := rand.Float32()
|
|
||||||
|
|
||||||
pos := startPos.Clone()
|
|
||||||
instancedData := make([]float32, 0, len(rs)*floatsPerGlyph) //This a larger approximation than needed because we don't count spaces etc
|
instancedData := make([]float32, 0, len(rs)*floatsPerGlyph) //This a larger approximation than needed because we don't count spaces etc
|
||||||
for i := 0; i < len(rs); i++ {
|
for i := 0; i < len(rs); i++ {
|
||||||
|
|
||||||
r := rs[i]
|
r := rs[i]
|
||||||
g := gr.Atlas.Glyphs[r]
|
g := gr.Atlas.Glyphs[r]
|
||||||
if r == '\n' {
|
if r == '\n' {
|
||||||
startPos.SetY(startPos.Y() - float32(gr.Atlas.LineHeight))
|
screenPos.SetY(screenPos.Y() - float32(gr.Atlas.LineHeight))
|
||||||
pos = startPos.Clone()
|
pos = screenPos.Clone()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
gr.GlyphCount++
|
gr.GlyphCount++
|
||||||
@ -125,7 +123,7 @@ func (gr *GlyphRend) DrawTextOpenGL(text string, startPos *gglm.Vec3, winWidth,
|
|||||||
g.U, g.V + g.SizeV,
|
g.U, g.V + g.SizeV,
|
||||||
g.U + g.SizeU, g.V + g.SizeV,
|
g.U + g.SizeU, g.V + g.SizeV,
|
||||||
|
|
||||||
rCol, gCol, bCol, 1, //Color
|
color.R(), color.G(), color.B(), color.A(), //Color
|
||||||
drawPos.X(), drawPos.Y(), drawPos.Z(), //Model pos
|
drawPos.X(), drawPos.Y(), drawPos.Z(), //Model pos
|
||||||
scale.X(), scale.Y(), scale.Z(), //Model scale
|
scale.X(), scale.Y(), scale.Z(), //Model scale
|
||||||
}...)
|
}...)
|
||||||
@ -165,7 +163,12 @@ func (gr *GlyphRend) SetFontFromFile(fontFile string, fontOptions *truetype.Opti
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGlyphRend(fontFile string, fontOptions *truetype.Options) (*GlyphRend, error) {
|
func (gr *GlyphRend) SetScreenSize(screenWidth, screenHeight int32) {
|
||||||
|
gr.ScreenWidth = screenWidth
|
||||||
|
gr.ScreenHeight = screenHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGlyphRend(fontFile string, fontOptions *truetype.Options, screenWidth, screenHeight int32) (*GlyphRend, error) {
|
||||||
|
|
||||||
atlas, err := NewFontAtlasFromFile(fontFile, fontOptions)
|
atlas, err := NewFontAtlasFromFile(fontFile, fontOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -293,5 +296,8 @@ func NewGlyphRend(fontFile string, fontOptions *truetype.Options) (*GlyphRend, e
|
|||||||
|
|
||||||
GlyphCount: 0,
|
GlyphCount: 0,
|
||||||
GlyphVBO: make([]float32, 0),
|
GlyphVBO: make([]float32, 0),
|
||||||
|
|
||||||
|
ScreenWidth: screenWidth,
|
||||||
|
ScreenHeight: screenHeight,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
61
main.go
61
main.go
@ -2,7 +2,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/bloeys/gglm/gglm"
|
"github.com/bloeys/gglm/gglm"
|
||||||
@ -22,6 +21,9 @@ type program struct {
|
|||||||
win *engine.Window
|
win *engine.Window
|
||||||
rend *rend3dgl.Rend3DGL
|
rend *rend3dgl.Rend3DGL
|
||||||
imguiInfo nmageimgui.ImguiInfo
|
imguiInfo nmageimgui.ImguiInfo
|
||||||
|
|
||||||
|
FontSize uint32
|
||||||
|
GlyphRend *glyphs.GlyphRend
|
||||||
}
|
}
|
||||||
|
|
||||||
//nMage TODO:
|
//nMage TODO:
|
||||||
@ -30,6 +32,7 @@ type program struct {
|
|||||||
// * Move SetAttribute away from material struct
|
// * Move SetAttribute away from material struct
|
||||||
// * Fix FPS counter
|
// * Fix FPS counter
|
||||||
// * Allow texture loading without cache
|
// * Allow texture loading without cache
|
||||||
|
// * Reduce/remove Game interface
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
@ -51,18 +54,28 @@ func main() {
|
|||||||
win: win,
|
win: win,
|
||||||
rend: rend,
|
rend: rend,
|
||||||
imguiInfo: nmageimgui.NewImGUI(),
|
imguiInfo: nmageimgui.NewImGUI(),
|
||||||
|
|
||||||
|
FontSize: 32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p.win.EventCallbacks = append(p.win.EventCallbacks, func(e sdl.Event) {
|
||||||
|
switch e := e.(type) {
|
||||||
|
case *sdl.WindowEvent:
|
||||||
|
if e.Event == sdl.WINDOWEVENT_SIZE_CHANGED {
|
||||||
|
p.handleWindowResize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
engine.Run(p)
|
engine.Run(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
var fontPointSize uint = 32
|
|
||||||
var glyphRend *glyphs.GlyphRend
|
|
||||||
|
|
||||||
func (p *program) Init() {
|
func (p *program) Init() {
|
||||||
|
|
||||||
|
w, h := p.win.SDLWin.GetSize()
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
glyphRend, err = glyphs.NewGlyphRend("./res/fonts/Consolas.ttf", &truetype.Options{Size: float64(fontPointSize), DPI: 72})
|
p.GlyphRend, err = glyphs.NewGlyphRend("./res/fonts/Consolas.ttf", &truetype.Options{Size: float64(p.FontSize), DPI: 72}, w, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("Failed to create atlas from font file. Err: " + err.Error())
|
panic("Failed to create atlas from font file. Err: " + err.Error())
|
||||||
}
|
}
|
||||||
@ -87,52 +100,47 @@ func (p *program) Update() {
|
|||||||
|
|
||||||
fontSizeChanged := false
|
fontSizeChanged := false
|
||||||
if input.KeyClicked(sdl.K_KP_PLUS) {
|
if input.KeyClicked(sdl.K_KP_PLUS) {
|
||||||
fontPointSize += 2
|
p.FontSize += 2
|
||||||
fontSizeChanged = true
|
fontSizeChanged = true
|
||||||
} else if input.KeyClicked(sdl.K_KP_MINUS) {
|
} else if input.KeyClicked(sdl.K_KP_MINUS) {
|
||||||
fontPointSize -= 2
|
p.FontSize -= 2
|
||||||
fontSizeChanged = true
|
fontSizeChanged = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if fontSizeChanged {
|
if fontSizeChanged {
|
||||||
glyphRend.SetFace(&truetype.Options{Size: float64(fontPointSize), DPI: 72})
|
p.GlyphRend.SetFace(&truetype.Options{Size: float64(p.FontSize), DPI: 72})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var gg = sync.Once{}
|
|
||||||
|
|
||||||
func (p *program) Render() {
|
func (p *program) Render() {
|
||||||
|
|
||||||
w, h := p.win.SDLWin.GetSize()
|
w, h := p.win.SDLWin.GetSize()
|
||||||
|
textColor := gglm.NewVec4(1, 1, 1, 1)
|
||||||
|
|
||||||
//Draw FPS
|
//Draw FPS
|
||||||
var fps float32
|
var fps float32
|
||||||
if frameTime.Milliseconds() > 0 {
|
if frameTime.Milliseconds() > 0 {
|
||||||
fps = 1 / float32(frameTime.Milliseconds()) * 1000
|
fps = 1 / float32(frameTime.Milliseconds()) * 1000
|
||||||
}
|
}
|
||||||
startFromTop := float32(h) - float32(glyphRend.Atlas.LineHeight)
|
startFromTop := float32(h) - float32(p.GlyphRend.Atlas.LineHeight)
|
||||||
glyphRend.DrawTextOpenGL(fmt.Sprintf("FPS=%f", fps), gglm.NewVec3(float32(w)*0.7, startFromTop, 0), w, h)
|
p.GlyphRend.DrawTextOpenGL(fmt.Sprintf("FPS=%f", fps), gglm.NewVec3(float32(w)*0.7, startFromTop, 0), textColor)
|
||||||
|
|
||||||
//Draw point and texture sizes
|
//Draw point and texture sizes
|
||||||
startFromTop -= float32(glyphRend.Atlas.LineHeight)
|
startFromTop -= float32(p.GlyphRend.Atlas.LineHeight)
|
||||||
glyphRend.DrawTextOpenGL(fmt.Sprintf("Point size=%d", fontPointSize), gglm.NewVec3(float32(w)*0.7, startFromTop, 0), w, h)
|
p.GlyphRend.DrawTextOpenGL(fmt.Sprintf("Point size=%d", p.FontSize), gglm.NewVec3(float32(w)*0.7, startFromTop, 0), textColor)
|
||||||
|
|
||||||
startFromTop -= float32(glyphRend.Atlas.LineHeight)
|
startFromTop -= float32(p.GlyphRend.Atlas.LineHeight)
|
||||||
glyphRend.DrawTextOpenGL(fmt.Sprintf("Texture size=%d*%d", glyphRend.Atlas.Img.Rect.Max.X, glyphRend.Atlas.Img.Rect.Max.Y), gglm.NewVec3(float32(w)*0.7, startFromTop, 0), w, h)
|
p.GlyphRend.DrawTextOpenGL(fmt.Sprintf("Texture size=%d*%d", p.GlyphRend.Atlas.Img.Rect.Max.X, p.GlyphRend.Atlas.Img.Rect.Max.Y), gglm.NewVec3(float32(w)*0.7, startFromTop, 0), textColor)
|
||||||
|
|
||||||
//Draw all other
|
//Draw all other
|
||||||
count := 1000
|
count := 1000
|
||||||
startFromBot := float32(glyphRend.Atlas.LineHeight)
|
startFromBot := float32(p.GlyphRend.Atlas.LineHeight)
|
||||||
for i := 0; i < count; i++ {
|
for i := 0; i < count; i++ {
|
||||||
glyphRend.DrawTextOpenGL("Hello friend, how are you?\n", gglm.NewVec3(0, startFromBot, 0), w, h)
|
p.GlyphRend.DrawTextOpenGL("Hello friend, how are you?\n", gglm.NewVec3(0, startFromBot, 0), textColor)
|
||||||
startFromBot += float32(glyphRend.Atlas.LineHeight) * 2
|
startFromBot += float32(p.GlyphRend.Atlas.LineHeight) * 2
|
||||||
}
|
}
|
||||||
|
|
||||||
gg.Do(func() {
|
p.GlyphRend.Draw()
|
||||||
fmt.Printf("Drawn chars: %d\n", glyphRend.GlyphCount)
|
|
||||||
})
|
|
||||||
|
|
||||||
glyphRend.Draw()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *program) FrameEnd() {
|
func (p *program) FrameEnd() {
|
||||||
@ -154,3 +162,8 @@ func (p *program) ShouldRun() bool {
|
|||||||
func (p *program) Deinit() {
|
func (p *program) Deinit() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *program) handleWindowResize() {
|
||||||
|
w, h := p.win.SDLWin.GetSize()
|
||||||
|
p.GlyphRend.SetScreenSize(w, h)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user