Improve font rendering performance, eliminate excessive memory usage (#271)

This commit is contained in:
nikitar020 2019-03-23 00:52:18 +02:00 committed by Max Risuhin
parent 745f7a111c
commit f100fac09e
4 changed files with 38 additions and 34 deletions

View File

@ -17,17 +17,19 @@ const DPI = 72
// A Font allows rendering of text to an OpenGL context.
type Font struct {
characters map[rune]*character
vao uint32
vbo uint32
program uint32
texture uint32 // Holds the glyph texture id.
color color
ttf *truetype.Font
ttfFace font.Face
scale float32
linePadding float32
lineHeight float32
characters map[rune]*character
vao uint32
vbo uint32
program uint32
uniformLocationResolution int32
uniformLocationTextColor int32
texture uint32 // Holds the glyph texture id.
color color
ttf *truetype.Font
ttfFace font.Face
scale float32
linePadding float32
lineHeight float32
}
type color struct {
@ -46,15 +48,14 @@ func LoadFont(reader io.Reader, scale float32, windowWidth int, windowHeight int
panic(err)
}
// Activate corresponding render state
gl.UseProgram(program)
font, err := LoadTrueTypeFont(program, reader, scale)
if err != nil {
return nil, err
}
//set screen resolution
resUniform := gl.GetUniformLocation(program, gl.Str("resolution\x00"))
gl.Uniform2f(resUniform, float32(windowWidth), float32(windowHeight))
gl.UseProgram(0)
font.UpdateResolution(windowWidth, windowHeight)
return LoadTrueTypeFont(program, reader, scale)
return font, nil
}
func (f *Font) Free() {
@ -82,10 +83,8 @@ func (f *Font) SetColor(red float32, green float32, blue float32, alpha float32)
func (f *Font) UpdateResolution(windowWidth int, windowHeight int) {
gl.UseProgram(f.program)
resUniform := gl.GetUniformLocation(f.program, gl.Str("resolution\x00"))
gl.Uniform2f(resUniform, float32(windowWidth), float32(windowHeight))
gl.Uniform2f(f.uniformLocationResolution, float32(windowWidth), float32(windowHeight))
gl.UseProgram(0)
//f.characters = map[rune]*character{}
}
func (f *Font) LineHeight() float32 {
@ -112,13 +111,11 @@ func (f *Font) Print(x, y float32, text string) error {
// Activate corresponding render state
gl.UseProgram(f.program)
//set text color
gl.Uniform4f(gl.GetUniformLocation(f.program, gl.Str("textColor\x00")), f.color.r, f.color.g, f.color.b, f.color.a)
//set screen resolution
//resUniform := gl.GetUniformLocation(f.program, gl.Str("resolution\x00"))
//gl.Uniform2f(resUniform, float32(2560), float32(1440))
gl.Uniform4f(f.uniformLocationTextColor, f.color.r, f.color.g, f.color.b, f.color.a)
gl.ActiveTexture(gl.TEXTURE0)
gl.BindVertexArray(f.vao)
gl.BindBuffer(gl.ARRAY_BUFFER, f.vbo)
// Iterate through all characters in string
for i := range indices {
@ -145,7 +142,7 @@ func (f *Font) Print(x, y float32, text string) error {
var y2 = ypos + h
//setup quad array
var vertices = []float32{
var vertices = [...]float32{
// X, Y, Z, U, V
// Front
x1, y1, 0.0, 0.0,
@ -153,25 +150,24 @@ func (f *Font) Print(x, y float32, text string) error {
x1, y2, 0.0, 1.0,
x1, y2, 0.0, 1.0,
x2, y1, 1.0, 0.0,
x2, y2, 1.0, 1.0}
x2, y2, 1.0, 1.0,
}
// Render glyph texture over quad
gl.BindTexture(gl.TEXTURE_2D, ch.textureID)
// Update content of VBO memory
gl.BindBuffer(gl.ARRAY_BUFFER, f.vbo)
//BufferSubData(target Enum, offset int, data []byte)
gl.BufferSubData(gl.ARRAY_BUFFER, 0, len(vertices)*4, gl.Ptr(vertices)) // Be sure to use glBufferSubData and not glBufferData
// Update content of VBO memory
gl.NamedBufferSubData(f.vbo, 0, len(vertices)*4, gl.Ptr(&vertices[0])) // Be sure to use glBufferSubData and not glBufferData
// Render quad
gl.DrawArrays(gl.TRIANGLES, 0, 24)
gl.BindBuffer(gl.ARRAY_BUFFER, 0)
// Now advance cursors for next glyph (note that advance is number of 1/64 pixels)
x += float32((ch.advance >> 6)) // Bitshift by 6 to get value in pixels (2^6 = 64 (divide amount of 1/64th pixels by 64 to get amount of pixels))
}
//clear opengl textures and programs
gl.BindBuffer(gl.ARRAY_BUFFER, 0)
gl.BindVertexArray(0)
gl.BindTexture(gl.TEXTURE_2D, 0)
gl.UseProgram(0)
@ -308,6 +304,7 @@ func (f *Font) GetRune(r rune) (*character, error) {
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, int32(rgba.Rect.Dx()), int32(rgba.Rect.Dy()), 0,
gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(rgba.Pix))
gl.BindTexture(gl.TEXTURE_2D, 0)
char.textureID = texture

View File

@ -30,6 +30,9 @@ func LoadTrueTypeFont(program uint32, r io.Reader, scale float32) (*Font, error)
f.scale = scale
f.characters = map[rune]*character{}
f.program = program //set shader program
f.uniformLocationResolution = gl.GetUniformLocation(program, gl.Str("resolution\x00"))
f.uniformLocationTextColor = gl.GetUniformLocation(program, gl.Str("textColor\x00"))
// Read the truetype font.
f.ttf, err = truetype.Parse(data)
if err != nil {

View File

@ -47,3 +47,7 @@ func (gui *GUI) loadFonts(actualWidth int, actualHeight int) error {
return nil
}
func (gui *GUI) updateFontsResolution(actualWidth int, actualHeight int) {
gui.fontMap.UpdateResolution(actualWidth, actualHeight)
}

View File

@ -321,7 +321,7 @@ func (gui *GUI) resize(w *glfw.Window, width int, height int) {
}
gui.logger.Debugf("Updating font resolutions...")
gui.loadFonts(gui.width, gui.height)
gui.updateFontsResolution(gui.width, gui.height)
gui.logger.Debugf("Setting renderer area...")
gui.renderer.SetArea(0, 0, gui.width-vScrollbarWidth, gui.height)