Ability to set cell background colors

This commit is contained in:
bloeys
2022-08-02 05:32:56 +04:00
parent 054eaebe9a
commit 8863a289d7
3 changed files with 151 additions and 19 deletions

View File

@ -11,6 +11,7 @@ import (
"github.com/bloeys/nmage/buffers"
"github.com/bloeys/nmage/materials"
"github.com/bloeys/nmage/meshes"
"github.com/bloeys/nterm/assert"
"github.com/bloeys/nterm/consts"
"github.com/go-gl/gl/v4.1-core/gl"
"github.com/golang/freetype/truetype"
@ -27,6 +28,19 @@ var (
RuneInfos map[rune]RuneInfo
)
type GlyphRendOpt uint64
const (
GlyphRendOpt_None GlyphRendOpt = 0
GlyphRendOpt_BgColor GlyphRendOpt = 1 << (iota - 1)
GlyphRendOpt_Underline
GlyphRendOpt_COUNT GlyphRendOpt = iota
)
type GlyphRendOptValues struct {
BgColor *gglm.Vec4
}
type GlyphRend struct {
Atlas *FontAtlas
AtlasTex *assets.Texture
@ -37,18 +51,35 @@ type GlyphRend struct {
TextRunsBuf []TextRun
GlyphCount uint32
//NOTE: Because of the sad realities (bugs?) of CGO, passing an array in a struct
//to C explodes (Go pointer to Go pointer error) even though passing the same array
//allocated inside the function is fine (Go potentially can't detect what's happening properly).
//
//Luckily slices still work, so for now we will use our slice as an array (no appending)
GlyphVBO []float32
// GlyphVBO [floatsPerGlyph * maxGlyphsPerBatch]float32
ScreenWidth int32
ScreenHeight int32
SpacesPerTab uint
Opts GlyphRendOpt
OptValues GlyphRendOptValues
}
func (gr *GlyphRend) SetOpts(opts ...GlyphRendOpt) {
for _, v := range opts {
assert.T(v <= (1<<(GlyphRendOpt_COUNT-2)), "Invalid opts of value %d", opts)
if v == GlyphRendOpt_None {
gr.Opts = GlyphRendOpt_None
} else {
gr.Opts |= v
}
}
gl.ProgramUniform1ui(gr.GlyphMat.ShaderProg.ID, gr.GlyphMat.GetUnifLoc("opts1"), uint32(gr.Opts))
}
func (gr *GlyphRend) HasOpt(opt GlyphRendOpt) bool {
return gr.Opts&opt != 0
}
//DrawTextOpenGLAbs prepares text that will be drawn on the next GlyphRend.Draw call.
@ -273,6 +304,18 @@ func (gr *GlyphRend) DrawTextOpenGLAbsRectWithStartPos(text []rune, startPos, re
// @Debug
var PrintPositions bool
func (gr *GlyphRend) GridSize() (w, h int64) {
w = int64(gr.ScreenWidth) / int64(gr.Atlas.SpaceAdvance)
h = int64(gr.ScreenHeight) / int64(gr.Atlas.LineHeight)
return w, h
}
func (gr *GlyphRend) ScreenPosToGridPos(x, y float32) (gridX, gridY float32) {
gridX = floorF32(x / gr.Atlas.SpaceAdvance)
gridY = floorF32(y / gr.Atlas.LineHeight)
return gridX, gridY
}
func (gr *GlyphRend) drawRune(run *TextRun, i int, prevRune rune, pos *gglm.Vec3, color *gglm.Vec4, lineHeightF32 float32, bufIndex *uint32) {
r := run.Runes[i]
@ -317,6 +360,42 @@ func (gr *GlyphRend) drawRune(run *TextRun, i int, prevRune rune, pos *gglm.Vec3
}
//Add the glyph information to the vbo
if gr.HasOpt(GlyphRendOpt_BgColor) {
//UV
gr.GlyphVBO[*bufIndex+0] = -1
gr.GlyphVBO[*bufIndex+1] = -1
*bufIndex += 2
//UVSize
gr.GlyphVBO[*bufIndex+0] = 0
gr.GlyphVBO[*bufIndex+1] = 0
*bufIndex += 2
//Color
gr.GlyphVBO[*bufIndex+0] = gr.OptValues.BgColor.R()
gr.GlyphVBO[*bufIndex+1] = gr.OptValues.BgColor.G()
gr.GlyphVBO[*bufIndex+2] = gr.OptValues.BgColor.B()
gr.GlyphVBO[*bufIndex+3] = gr.OptValues.BgColor.A()
*bufIndex += 4
//Model Pos
gr.GlyphVBO[*bufIndex+0] = pos.X()
gr.GlyphVBO[*bufIndex+1] = pos.Y()
gr.GlyphVBO[*bufIndex+2] = pos.Z()
*bufIndex += 3
//Model Scale
gr.GlyphVBO[*bufIndex+0] = gr.Atlas.SpaceAdvance
gr.GlyphVBO[*bufIndex+1] = lineHeightF32
*bufIndex += 2
gr.GlyphCount++
if gr.GlyphCount == DefaultGlyphsPerBatch {
gr.Draw()
*bufIndex = 0
}
}
//UV
gr.GlyphVBO[*bufIndex+0] = g.U
gr.GlyphVBO[*bufIndex+1] = g.V
@ -598,7 +677,8 @@ func (gr *GlyphRend) updateFontAtlasTexture() error {
//Update material
gr.GlyphMat.DiffuseTex = gr.AtlasTex.TexID
// gr.GlyphMat.SetUnifVec2("sizeUV", &gr.Atlas.SizeUV)
// gr.GlyphMat.SetUnifFloat32("spaceAdv", gr.Atlas.SpaceAdvance)
// gr.GlyphMat.SetUnifFloat32("lineHeight", gr.Atlas.LineHeight)
return nil
}
@ -631,6 +711,11 @@ func NewGlyphRend(fontFile string, fontOptions *truetype.Options, screenWidth, s
GlyphVBO: make([]float32, floatsPerGlyph*DefaultGlyphsPerBatch),
TextRunsBuf: make([]TextRun, 0, 20),
SpacesPerTab: 4,
Opts: GlyphRendOpt_None,
OptValues: GlyphRendOptValues{
BgColor: gglm.NewVec4(0, 0, 0, 0),
},
}
//Create glyph mesh

View File

@ -122,6 +122,7 @@ var (
drawManyLines = false
textToShow = ""
// textToShow = "Hello there, friend!"
xOff float32 = 0
yOff float32 = 0
@ -217,6 +218,9 @@ func (p *nterm) Init() {
panic("Failed to create atlas from font file. Err: " + err.Error())
}
p.GlyphRend.OptValues.BgColor = gglm.NewVec4(1, 0, 0, 0.25)
// p.GlyphRend.SetOpts(glyphs.GlyphRendOpt_BgColor)
// if consts.Mode_Debug {
// glyphs.SaveImgToPNG(p.GlyphRend.Atlas.Img, "./debug-atlas.png")
// }
@ -703,7 +707,6 @@ func (p *nterm) DrawCursor() {
//Position cursor by placing it at the end of the drawn characters then walking backwards
pos := p.lastCmdCharPos.Clone()
p.ScreenPosToGridPos(pos)
pos.AddY(p.GlyphRend.Atlas.LineHeight * 0.5)
for i := clamp(p.cmdBufLen, 0, int64(len(p.cmdBuf))); i > p.cursorCharIndex; i-- {
@ -726,8 +729,8 @@ func (p *nterm) GridSize() (w, h int64) {
}
func (p *nterm) ScreenPosToGridPos(screenPos *gglm.Vec3) {
screenPos.SetX(screenPos.X() / p.GlyphRend.Atlas.SpaceAdvance * p.GlyphRend.Atlas.SpaceAdvance)
screenPos.SetY(screenPos.Y() / p.GlyphRend.Atlas.LineHeight * p.GlyphRend.Atlas.LineHeight)
screenPos.SetX(FloorF32(screenPos.X() / p.GlyphRend.Atlas.SpaceAdvance))
screenPos.SetY(FloorF32(screenPos.Y() / p.GlyphRend.Atlas.LineHeight))
}
func (p *nterm) DebugUpdate() {

View File

@ -13,6 +13,7 @@ layout(location=5) in vec2 aModelScale;
out vec2 v2fUV0;
out vec4 v2fColor;
out vec3 v2fModelPos;
out vec3 v2fFragPos;
uniform mat4 projViewMat;
@ -26,8 +27,9 @@ void main()
aModelPos.x, aModelPos.y, aModelPos.z, 1.0
);
v2fUV0 = aUV0 + aVertPos.xy * aUVSize;
v2fColor = aVertColor;
v2fModelPos = aModelPos;
v2fUV0 = aUV0 + aVertPos.xy * aUVSize;
gl_Position = projViewMat * modelMat * vec4(aVertPos, 1.0);
}
@ -37,22 +39,64 @@ void main()
in vec2 v2fUV0;
in vec4 v2fColor;
in vec3 v2fModelPos;
in vec4 gl_FragCoord;
out vec4 fragColor;
uniform sampler2D diffTex;
uniform int drawBounds;
uniform int drawGlyphBounds;
uniform uint opts1;
// uniform float spaceAdv = 1;
// uniform float lineHeight = 1;
const uint opts1_bgColorMask = 1<<0;
const uint opts1_underlineMask = 1<<1;
bool hasOpts(uint mask)
{
return (opts1&mask) != 0;
}
// vec2 ScreenPosToGridPos(vec2 pos)
// {
// return vec2(floor(pos.x / spaceAdv), floor(pos.y / lineHeight));
// }
// vec4 GridPosToCellStartEnd(vec2 gridPos)
// {
// vec4 startEnd;
// startEnd.x = gridPos.x * spaceAdv;
// startEnd.y = gridPos.y * lineHeight;
// startEnd.z = startEnd.x + spaceAdv;
// startEnd.w = startEnd.y + lineHeight;
// return startEnd;
// }
void main()
{
if (hasOpts(opts1_bgColorMask) && v2fUV0 == vec2(-1,-1))
{
// vec2 gridPos = ScreenPosToGridPos(v2fModelPos.xy);
// vec4 startEnd = GridPosToCellStartEnd(gridPos);
//if (gl_FragCoord.x > startEnd.x && gl_FragCoord.x < startEnd.z)
{
fragColor = v2fColor;
}
return;
}
vec4 texColor = texelFetch(diffTex, ivec2(v2fUV0), 0);
// This part highlights the full region of the char
if (texColor.r == 0 && drawBounds != 0)
if (texColor.r == 0)
{
fragColor = vec4(0,1,0,0.25);
if (drawGlyphBounds != 0)
{
fragColor = vec4(0,1,0,0.25);
}
return;
}
else
{
fragColor = vec4(v2fColor.rgb, texColor.r*v2fColor.a);
}
}
fragColor = vec4(v2fColor.rgb, texColor.r*v2fColor.a);
}