mirror of
https://github.com/bloeys/nterm.git
synced 2025-12-29 06:28:20 +00:00
Ability to set cell background colors
This commit is contained in:
@ -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
|
||||
|
||||
9
main.go
9
main.go
@ -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() {
|
||||
|
||||
@ -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)
|
||||
{
|
||||
if (drawGlyphBounds != 0)
|
||||
{
|
||||
fragColor = vec4(0,1,0,0.25);
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
fragColor = vec4(v2fColor.rgb, texColor.r*v2fColor.a);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user