mirror of
https://github.com/bloeys/nterm.git
synced 2025-12-29 14:38:19 +00:00
Make SizeU/SizeV uniforms instead of per-vertex+reduce glyph info
This commit is contained in:
@ -47,49 +47,40 @@ func (gr *GlyphRend) DrawTextOpenGLAbs(text string, screenPos *gglm.Vec3, color
|
||||
|
||||
// startPos := screenPos.Clone()
|
||||
pos := screenPos.Clone()
|
||||
advanceF32 := float32(gr.Atlas.Advance)
|
||||
lineHeightF32 := float32(gr.Atlas.LineHeight)
|
||||
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++ {
|
||||
|
||||
r := rs[i]
|
||||
g := gr.Atlas.Glyphs[r]
|
||||
if r == '\n' {
|
||||
screenPos.SetY(screenPos.Y() - float32(gr.Atlas.LineHeight))
|
||||
screenPos.SetY(screenPos.Y() - lineHeightF32)
|
||||
pos = screenPos.Clone()
|
||||
continue
|
||||
} else if r == ' ' {
|
||||
pos.SetX(pos.X() + g.Advance)
|
||||
pos.SetX(pos.X() + advanceF32)
|
||||
continue
|
||||
}
|
||||
gr.GlyphCount++
|
||||
|
||||
// glyphHeight := float32(g.Ascent + g.Descent)
|
||||
scale := gglm.NewVec3(g.Advance, float32(gr.Atlas.LineHeight), 1)
|
||||
// scale := gglm.NewVec3(g.Width, glyphHeight, 1)
|
||||
scale := gglm.NewVec3(advanceF32, lineHeightF32, 1)
|
||||
|
||||
//See: https://developer.apple.com/library/archive/documentation/TextFonts/Conceptual/CocoaTextArchitecture/Art/glyph_metrics_2x.png
|
||||
//Quads are drawn from the center and so that's our baseline. But chars shouldn't be centered, they should follow ascent/decent/advance.
|
||||
//To make them do that vertically, we raise them above the baseline (y+height/2), then since they are sitting on top of the baseline we can simply
|
||||
//move them down by the decent amount to put them in the correct vertical position.
|
||||
//
|
||||
//Horizontally the character should be drawn from the left edge not the center, so we just move it forward by advance/2
|
||||
//The uvs coming in make it so that glyphs are sitting on top of the baseline (no descent) and with horizontal bearing applied.
|
||||
//So to position correctly we move them down by the descent amount.
|
||||
drawPos := *pos
|
||||
drawPos.SetX(drawPos.X())
|
||||
drawPos.SetY(drawPos.Y() - g.Descent)
|
||||
// drawPos.SetX(drawPos.X() + g.BearingX)
|
||||
// drawPos.SetY(drawPos.Y() - g.Descent)
|
||||
|
||||
instancedData = append(instancedData, []float32{
|
||||
g.U, g.V,
|
||||
g.U + g.SizeU, g.V,
|
||||
g.U, g.V + g.SizeV,
|
||||
g.U + g.SizeU, g.V + g.SizeV,
|
||||
|
||||
color.R(), color.G(), color.B(), color.A(), //Color
|
||||
roundF32(drawPos.X()), roundF32(drawPos.Y()), drawPos.Z(), //Model pos
|
||||
scale.X(), scale.Y(), scale.Z(), //Model scale
|
||||
}...)
|
||||
|
||||
pos.SetX(pos.X() + g.Advance)
|
||||
pos.SetX(pos.X() + advanceF32)
|
||||
}
|
||||
|
||||
//Draw baselines
|
||||
@ -163,8 +154,10 @@ func (gr *GlyphRend) SetFontFromFile(fontFile string, fontOptions *truetype.Opti
|
||||
//Any old textures are deleted
|
||||
func (gr *GlyphRend) updateFontAtlasTexture() error {
|
||||
|
||||
//Clean old texture and load new texture
|
||||
if gr.AtlasTex != nil {
|
||||
gl.DeleteTextures(1, &gr.AtlasTex.TexID)
|
||||
gr.AtlasTex = nil
|
||||
}
|
||||
|
||||
atlasTex, err := assets.LoadTextureInMemImg(gr.Atlas.Img, nil)
|
||||
@ -180,6 +173,10 @@ func (gr *GlyphRend) updateFontAtlasTexture() error {
|
||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
|
||||
gl.BindTexture(gl.TEXTURE_2D, 0)
|
||||
|
||||
//Update material
|
||||
gr.GlyphMat.DiffuseTex = gr.AtlasTex.TexID
|
||||
gr.GlyphMat.SetUnifVec2("sizeUV", &gr.Atlas.SizeUV)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -193,7 +190,6 @@ func (gr *GlyphRend) SetScreenSize(screenWidth, screenHeight int32) {
|
||||
viewMtx := gglm.LookAt(gglm.NewVec3(0, 0, -10), gglm.NewVec3(0, 0, 0), gglm.NewVec3(0, 1, 0))
|
||||
projViewMtx := projMtx.Mul(viewMtx)
|
||||
|
||||
gr.GlyphMat.DiffuseTex = gr.AtlasTex.TexID
|
||||
gr.GlyphMat.SetUnifMat4("projViewMat", &projViewMtx.Mat4)
|
||||
}
|
||||
|
||||
@ -204,17 +200,6 @@ func NewGlyphRend(fontFile string, fontOptions *truetype.Options, screenWidth, s
|
||||
GlyphVBO: make([]float32, 0),
|
||||
}
|
||||
|
||||
atlas, err := NewFontAtlasFromFile(fontFile, fontOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gr.Atlas = atlas
|
||||
|
||||
err = gr.updateFontAtlasTexture()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//Create glyph mesh
|
||||
gr.GlyphMesh = &meshes.Mesh{
|
||||
Name: "glypQuad",
|
||||
@ -240,7 +225,18 @@ func NewGlyphRend(fontFile string, fontOptions *truetype.Options, screenWidth, s
|
||||
|
||||
//Setup material
|
||||
gr.GlyphMat = materials.NewMaterial("glyphMat", "./res/shaders/glyph.glsl")
|
||||
gr.GlyphMat.DiffuseTex = gr.AtlasTex.TexID
|
||||
|
||||
//With the material ready we can generate the atlas
|
||||
var err error
|
||||
gr.Atlas, err = NewFontAtlasFromFile(fontFile, fontOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = gr.updateFontAtlasTexture()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//Create instanced buf and set its instanced attributes.
|
||||
//Multiple VBOs under one VAO, one VBO for vertex data, and one VBO for instanced data.
|
||||
@ -254,11 +250,7 @@ func NewGlyphRend(fontFile string, fontOptions *truetype.Options, screenWidth, s
|
||||
}
|
||||
|
||||
gr.InstancedBuf.SetLayout(
|
||||
buffers.Element{ElementType: buffers.DataTypeVec2}, //UVST0
|
||||
buffers.Element{ElementType: buffers.DataTypeVec2}, //UVST1
|
||||
buffers.Element{ElementType: buffers.DataTypeVec2}, //UVST2
|
||||
buffers.Element{ElementType: buffers.DataTypeVec2}, //UVST3
|
||||
|
||||
buffers.Element{ElementType: buffers.DataTypeVec2}, //UV0
|
||||
buffers.Element{ElementType: buffers.DataTypeVec4}, //Color
|
||||
buffers.Element{ElementType: buffers.DataTypeVec3}, //ModelPos
|
||||
buffers.Element{ElementType: buffers.DataTypeVec3}, //ModelScale
|
||||
@ -268,43 +260,27 @@ func NewGlyphRend(fontFile string, fontOptions *truetype.Options, screenWidth, s
|
||||
gl.BindBuffer(gl.ARRAY_BUFFER, gr.InstancedBuf.BufID)
|
||||
layout := gr.InstancedBuf.GetLayout()
|
||||
|
||||
//4 UV values
|
||||
//Instanced attributes
|
||||
uvEle := layout[0]
|
||||
gl.EnableVertexAttribArray(1)
|
||||
gl.VertexAttribPointer(1, uvEle.ElementType.CompCount(), uvEle.ElementType.GLType(), false, gr.InstancedBuf.Stride, gl.PtrOffset(uvEle.Offset))
|
||||
gl.VertexAttribDivisor(1, 1)
|
||||
|
||||
uvEle = layout[1]
|
||||
colorEle := layout[1]
|
||||
gl.EnableVertexAttribArray(2)
|
||||
gl.VertexAttribPointer(2, uvEle.ElementType.CompCount(), uvEle.ElementType.GLType(), false, gr.InstancedBuf.Stride, gl.PtrOffset(uvEle.Offset))
|
||||
gl.VertexAttribPointer(2, colorEle.ElementType.CompCount(), colorEle.ElementType.GLType(), false, gr.InstancedBuf.Stride, gl.PtrOffset(colorEle.Offset))
|
||||
gl.VertexAttribDivisor(2, 1)
|
||||
|
||||
uvEle = layout[2]
|
||||
posEle := layout[2]
|
||||
gl.EnableVertexAttribArray(3)
|
||||
gl.VertexAttribPointer(3, uvEle.ElementType.CompCount(), uvEle.ElementType.GLType(), false, gr.InstancedBuf.Stride, gl.PtrOffset(uvEle.Offset))
|
||||
gl.VertexAttribPointer(3, posEle.ElementType.CompCount(), posEle.ElementType.GLType(), false, gr.InstancedBuf.Stride, gl.PtrOffset(posEle.Offset))
|
||||
gl.VertexAttribDivisor(3, 1)
|
||||
|
||||
uvEle = layout[3]
|
||||
scaleEle := layout[3]
|
||||
gl.EnableVertexAttribArray(4)
|
||||
gl.VertexAttribPointer(4, uvEle.ElementType.CompCount(), uvEle.ElementType.GLType(), false, gr.InstancedBuf.Stride, gl.PtrOffset(uvEle.Offset))
|
||||
gl.VertexAttribPointer(4, scaleEle.ElementType.CompCount(), scaleEle.ElementType.GLType(), false, gr.InstancedBuf.Stride, gl.PtrOffset(scaleEle.Offset))
|
||||
gl.VertexAttribDivisor(4, 1)
|
||||
|
||||
//Rest of instanced attributes
|
||||
colorEle := layout[4]
|
||||
gl.EnableVertexAttribArray(5)
|
||||
gl.VertexAttribPointer(5, colorEle.ElementType.CompCount(), colorEle.ElementType.GLType(), false, gr.InstancedBuf.Stride, gl.PtrOffset(colorEle.Offset))
|
||||
gl.VertexAttribDivisor(5, 1)
|
||||
|
||||
posEle := layout[5]
|
||||
gl.EnableVertexAttribArray(6)
|
||||
gl.VertexAttribPointer(6, posEle.ElementType.CompCount(), posEle.ElementType.GLType(), false, gr.InstancedBuf.Stride, gl.PtrOffset(posEle.Offset))
|
||||
gl.VertexAttribDivisor(6, 1)
|
||||
|
||||
scaleEle := layout[6]
|
||||
gl.EnableVertexAttribArray(7)
|
||||
gl.VertexAttribPointer(7, scaleEle.ElementType.CompCount(), scaleEle.ElementType.GLType(), false, gr.InstancedBuf.Stride, gl.PtrOffset(scaleEle.Offset))
|
||||
gl.VertexAttribDivisor(7, 1)
|
||||
|
||||
gl.BindBuffer(gl.ARRAY_BUFFER, 0)
|
||||
gr.InstancedBuf.UnBind()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user