mirror of
https://github.com/bloeys/nterm.git
synced 2025-12-29 14:38:19 +00:00
Pad font atlas to avoid bleeding+togglable grid
This commit is contained in:
@ -70,13 +70,15 @@ func NewFontAtlasFromFont(f *truetype.Font, face font.Face, pointSize uint) (*Fo
|
|||||||
atlasSizeX := 512
|
atlasSizeX := 512
|
||||||
atlasSizeY := 512
|
atlasSizeY := 512
|
||||||
|
|
||||||
charWidthFixed, _ := face.GlyphAdvance('L')
|
const charPaddingX = 4
|
||||||
charWidth := charWidthFixed.Ceil()
|
const charPaddingY = 4
|
||||||
|
charAdvFixed, _ := face.GlyphAdvance('L')
|
||||||
|
charAdv := charAdvFixed.Ceil() + charPaddingX
|
||||||
|
|
||||||
lineHeight := face.Metrics().Height.Ceil()
|
lineHeight := face.Metrics().Height.Ceil()
|
||||||
|
|
||||||
maxLinesInAtlas := atlasSizeY/lineHeight - 1
|
maxLinesInAtlas := atlasSizeY/lineHeight - 1
|
||||||
charsPerLine := atlasSizeX / charWidth
|
charsPerLine := atlasSizeX / charAdv
|
||||||
linesNeeded := int(math.Ceil(float64(len(glyphs)) / float64(charsPerLine)))
|
linesNeeded := int(math.Ceil(float64(len(glyphs)) / float64(charsPerLine)))
|
||||||
|
|
||||||
for linesNeeded > maxLinesInAtlas {
|
for linesNeeded > maxLinesInAtlas {
|
||||||
@ -86,7 +88,7 @@ func NewFontAtlasFromFont(f *truetype.Font, face font.Face, pointSize uint) (*Fo
|
|||||||
|
|
||||||
maxLinesInAtlas = atlasSizeY/lineHeight - 1
|
maxLinesInAtlas = atlasSizeY/lineHeight - 1
|
||||||
|
|
||||||
charsPerLine = atlasSizeX / charWidth
|
charsPerLine = atlasSizeX / charAdv
|
||||||
linesNeeded = int(math.Ceil(float64(len(glyphs)) / float64(charsPerLine)))
|
linesNeeded = int(math.Ceil(float64(len(glyphs)) / float64(charsPerLine)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,6 +116,8 @@ func NewFontAtlasFromFont(f *truetype.Font, face font.Face, pointSize uint) (*Fo
|
|||||||
//Put glyphs on atlas
|
//Put glyphs on atlas
|
||||||
atlasSizeXF32 := float32(atlasSizeX)
|
atlasSizeXF32 := float32(atlasSizeX)
|
||||||
atlasSizeYF32 := float32(atlasSizeY)
|
atlasSizeYF32 := float32(atlasSizeY)
|
||||||
|
charPaddingXFixed := fixed.I(charPaddingX)
|
||||||
|
charPaddingYFixed := fixed.I(charPaddingY)
|
||||||
|
|
||||||
charsOnLine := 0
|
charsOnLine := 0
|
||||||
lineHeightFixed := fixed.I(lineHeight)
|
lineHeightFixed := fixed.I(lineHeight)
|
||||||
@ -127,7 +131,7 @@ func NewFontAtlasFromFont(f *truetype.Font, face font.Face, pointSize uint) (*Fo
|
|||||||
descent := absFixedI26_6(gBounds.Max.Y)
|
descent := absFixedI26_6(gBounds.Max.Y)
|
||||||
bearingX := absFixedI26_6(gBounds.Min.X)
|
bearingX := absFixedI26_6(gBounds.Min.X)
|
||||||
|
|
||||||
glyphWidth := float32((absFixedI26_6(gBounds.Max.X - gBounds.Min.X)).Ceil())
|
glyphWidth := float32((absFixedI26_6(gBounds.Max.X) - absFixedI26_6(gBounds.Min.X)).Ceil())
|
||||||
heightRounded := (ascent + descent).Ceil()
|
heightRounded := (ascent + descent).Ceil()
|
||||||
|
|
||||||
atlas.Glyphs[g] = FontAtlasGlyph{
|
atlas.Glyphs[g] = FontAtlasGlyph{
|
||||||
@ -144,14 +148,16 @@ func NewFontAtlasFromFont(f *truetype.Font, face font.Face, pointSize uint) (*Fo
|
|||||||
BearingX: float32(bearingX.Ceil()),
|
BearingX: float32(bearingX.Ceil()),
|
||||||
Width: glyphWidth,
|
Width: glyphWidth,
|
||||||
}
|
}
|
||||||
|
|
||||||
drawer.DrawString(string(g))
|
drawer.DrawString(string(g))
|
||||||
|
drawer.Dot.X += charPaddingXFixed
|
||||||
|
|
||||||
charsOnLine++
|
charsOnLine++
|
||||||
if charsOnLine == charsPerLine {
|
if charsOnLine == charsPerLine {
|
||||||
|
|
||||||
charsOnLine = 0
|
charsOnLine = 0
|
||||||
drawer.Dot.X = 0
|
drawer.Dot.X = 0
|
||||||
drawer.Dot.Y += lineHeightFixed
|
drawer.Dot.Y += lineHeightFixed + charPaddingYFixed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
35
main.go
35
main.go
@ -27,6 +27,11 @@ type program struct {
|
|||||||
FontSize uint32
|
FontSize uint32
|
||||||
Dpi float64
|
Dpi float64
|
||||||
GlyphRend *glyphs.GlyphRend
|
GlyphRend *glyphs.GlyphRend
|
||||||
|
|
||||||
|
gridMesh *meshes.Mesh
|
||||||
|
gridMat *materials.Material
|
||||||
|
|
||||||
|
shouldDrawGrid bool
|
||||||
}
|
}
|
||||||
|
|
||||||
//nMage TODO:
|
//nMage TODO:
|
||||||
@ -61,7 +66,7 @@ func main() {
|
|||||||
rend: rend,
|
rend: rend,
|
||||||
imguiInfo: nmageimgui.NewImGUI(),
|
imguiInfo: nmageimgui.NewImGUI(),
|
||||||
|
|
||||||
FontSize: 80,
|
FontSize: 14,
|
||||||
}
|
}
|
||||||
|
|
||||||
p.win.EventCallbacks = append(p.win.EventCallbacks, func(e sdl.Event) {
|
p.win.EventCallbacks = append(p.win.EventCallbacks, func(e sdl.Event) {
|
||||||
@ -97,19 +102,16 @@ func (p *program) Init() {
|
|||||||
glyphs.SaveImgToPNG(p.GlyphRend.Atlas.Img, "./debug-atlas.png")
|
glyphs.SaveImgToPNG(p.GlyphRend.Atlas.Img, "./debug-atlas.png")
|
||||||
}
|
}
|
||||||
|
|
||||||
var gridMesh *meshes.Mesh
|
|
||||||
var gridMat *materials.Material
|
|
||||||
|
|
||||||
func (p *program) Start() {
|
func (p *program) Start() {
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
gridMesh, err = meshes.NewMesh("grid", "./res/models/quad.obj", 0)
|
p.gridMesh, err = meshes.NewMesh("grid", "./res/models/quad.obj", 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err.Error())
|
panic(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
gridMat = materials.NewMaterial("grid", "./res/shaders/grid")
|
p.gridMat = materials.NewMaterial("grid", "./res/shaders/grid")
|
||||||
gridMat.SetAttribute(gridMesh.Buf)
|
p.gridMat.SetAttribute(p.gridMesh.Buf)
|
||||||
p.handleWindowResize()
|
p.handleWindowResize()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,6 +128,7 @@ func (p *program) Update() {
|
|||||||
p.handleWindowResize()
|
p.handleWindowResize()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Font sizing
|
||||||
oldFont := p.FontSize
|
oldFont := p.FontSize
|
||||||
fontSizeChanged := false
|
fontSizeChanged := false
|
||||||
if input.KeyClicked(sdl.K_KP_PLUS) {
|
if input.KeyClicked(sdl.K_KP_PLUS) {
|
||||||
@ -144,10 +147,11 @@ func (p *program) Update() {
|
|||||||
println("Failed to update font face. Err: " + err.Error())
|
println("Failed to update font face. Err: " + err.Error())
|
||||||
} else {
|
} else {
|
||||||
glyphs.SaveImgToPNG(p.GlyphRend.Atlas.Img, "./debug-atlas.png")
|
glyphs.SaveImgToPNG(p.GlyphRend.Atlas.Img, "./debug-atlas.png")
|
||||||
println("New font size:", p.FontSize)
|
println("New font size:", p.FontSize, "; New texture size:", p.GlyphRend.Atlas.Img.Rect.Max.X, "\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Move text
|
||||||
var speed float32 = 1
|
var speed float32 = 1
|
||||||
if input.KeyDown(sdl.K_RIGHT) {
|
if input.KeyDown(sdl.K_RIGHT) {
|
||||||
xOff += speed
|
xOff += speed
|
||||||
@ -160,6 +164,11 @@ func (p *program) Update() {
|
|||||||
} else if input.KeyDown(sdl.K_DOWN) {
|
} else if input.KeyDown(sdl.K_DOWN) {
|
||||||
yOff -= speed
|
yOff -= speed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Grid
|
||||||
|
if input.KeyClicked(sdl.K_SPACE) {
|
||||||
|
p.shouldDrawGrid = !p.shouldDrawGrid
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var xOff float32 = 0
|
var xOff float32 = 0
|
||||||
@ -175,7 +184,9 @@ func (p *program) Render() {
|
|||||||
// p.GlyphRend.DrawTextOpenGLAbs("Hello there, friend.\nABCDEFGHIJKLMNOPQRSTUVWXYZ", gglm.NewVec3(0, 0, 0), textColor)
|
// p.GlyphRend.DrawTextOpenGLAbs("Hello there, friend.\nABCDEFGHIJKLMNOPQRSTUVWXYZ", gglm.NewVec3(0, 0, 0), textColor)
|
||||||
p.GlyphRend.DrawTextOpenGLAbs(" Hello there, friend|.\n ABCDEFGHIJKLMNOPQRSTUVWXYZ", gglm.NewVec3(xOff, float32(p.GlyphRend.Atlas.LineHeight)*2+yOff, 0), textColor)
|
p.GlyphRend.DrawTextOpenGLAbs(" Hello there, friend|.\n ABCDEFGHIJKLMNOPQRSTUVWXYZ", gglm.NewVec3(xOff, float32(p.GlyphRend.Atlas.LineHeight)*2+yOff, 0), textColor)
|
||||||
|
|
||||||
// p.drawGrid()
|
if p.shouldDrawGrid {
|
||||||
|
p.drawGrid()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *program) drawGrid() {
|
func (p *program) drawGrid() {
|
||||||
@ -186,12 +197,12 @@ func (p *program) drawGrid() {
|
|||||||
//columns
|
//columns
|
||||||
adv := p.GlyphRend.Atlas.Glyphs['A'].Advance
|
adv := p.GlyphRend.Atlas.Glyphs['A'].Advance
|
||||||
for i := int32(0); i < p.GlyphRend.ScreenWidth; i += int32(adv) {
|
for i := int32(0); i < p.GlyphRend.ScreenWidth; i += int32(adv) {
|
||||||
p.rend.Draw(gridMesh, gglm.NewTrMatId().Translate(gglm.NewVec3(float32(i)+0.5, sizeY/2, 0)).Scale(gglm.NewVec3(1, sizeY, 1)), gridMat)
|
p.rend.Draw(p.gridMesh, gglm.NewTrMatId().Translate(gglm.NewVec3(float32(i)+0.5, sizeY/2, 0)).Scale(gglm.NewVec3(1, sizeY, 1)), p.gridMat)
|
||||||
}
|
}
|
||||||
|
|
||||||
//rows
|
//rows
|
||||||
for i := int32(0); i < p.GlyphRend.ScreenHeight; i += int32(p.GlyphRend.Atlas.LineHeight) {
|
for i := int32(0); i < p.GlyphRend.ScreenHeight; i += int32(p.GlyphRend.Atlas.LineHeight) {
|
||||||
p.rend.Draw(gridMesh, gglm.NewTrMatId().Translate(gglm.NewVec3(sizeX/2, float32(i), 0)).Scale(gglm.NewVec3(sizeX, 1, 1)), gridMat)
|
p.rend.Draw(p.gridMesh, gglm.NewTrMatId().Translate(gglm.NewVec3(sizeX/2, float32(i), 0)).Scale(gglm.NewVec3(sizeX, 1, 1)), p.gridMat)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,5 +231,5 @@ func (p *program) handleWindowResize() {
|
|||||||
|
|
||||||
projMtx := gglm.Ortho(0, float32(w), float32(h), 0, 0.1, 20)
|
projMtx := gglm.Ortho(0, float32(w), float32(h), 0, 0.1, 20)
|
||||||
viewMtx := gglm.LookAt(gglm.NewVec3(0, 0, -10), gglm.NewVec3(0, 0, 0), gglm.NewVec3(0, 1, 0))
|
viewMtx := gglm.LookAt(gglm.NewVec3(0, 0, -10), gglm.NewVec3(0, 0, 0), gglm.NewVec3(0, 1, 0))
|
||||||
gridMat.SetUnifMat4("projViewMat", &projMtx.Mul(viewMtx).Mat4)
|
p.gridMat.SetUnifMat4("projViewMat", &projMtx.Mul(viewMtx).Mat4)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user