mirror of
https://github.com/bloeys/nterm.git
synced 2025-12-29 14:38:19 +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/buffers"
|
||||||
"github.com/bloeys/nmage/materials"
|
"github.com/bloeys/nmage/materials"
|
||||||
"github.com/bloeys/nmage/meshes"
|
"github.com/bloeys/nmage/meshes"
|
||||||
|
"github.com/bloeys/nterm/assert"
|
||||||
"github.com/bloeys/nterm/consts"
|
"github.com/bloeys/nterm/consts"
|
||||||
"github.com/go-gl/gl/v4.1-core/gl"
|
"github.com/go-gl/gl/v4.1-core/gl"
|
||||||
"github.com/golang/freetype/truetype"
|
"github.com/golang/freetype/truetype"
|
||||||
@ -27,6 +28,19 @@ var (
|
|||||||
RuneInfos map[rune]RuneInfo
|
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 {
|
type GlyphRend struct {
|
||||||
Atlas *FontAtlas
|
Atlas *FontAtlas
|
||||||
AtlasTex *assets.Texture
|
AtlasTex *assets.Texture
|
||||||
@ -37,18 +51,35 @@ type GlyphRend struct {
|
|||||||
TextRunsBuf []TextRun
|
TextRunsBuf []TextRun
|
||||||
|
|
||||||
GlyphCount uint32
|
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)
|
//Luckily slices still work, so for now we will use our slice as an array (no appending)
|
||||||
GlyphVBO []float32
|
GlyphVBO []float32
|
||||||
// GlyphVBO [floatsPerGlyph * maxGlyphsPerBatch]float32
|
|
||||||
|
|
||||||
ScreenWidth int32
|
ScreenWidth int32
|
||||||
ScreenHeight int32
|
ScreenHeight int32
|
||||||
|
|
||||||
SpacesPerTab uint
|
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.
|
//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
|
// @Debug
|
||||||
var PrintPositions bool
|
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) {
|
func (gr *GlyphRend) drawRune(run *TextRun, i int, prevRune rune, pos *gglm.Vec3, color *gglm.Vec4, lineHeightF32 float32, bufIndex *uint32) {
|
||||||
|
|
||||||
r := run.Runes[i]
|
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
|
//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
|
//UV
|
||||||
gr.GlyphVBO[*bufIndex+0] = g.U
|
gr.GlyphVBO[*bufIndex+0] = g.U
|
||||||
gr.GlyphVBO[*bufIndex+1] = g.V
|
gr.GlyphVBO[*bufIndex+1] = g.V
|
||||||
@ -598,7 +677,8 @@ func (gr *GlyphRend) updateFontAtlasTexture() error {
|
|||||||
|
|
||||||
//Update material
|
//Update material
|
||||||
gr.GlyphMat.DiffuseTex = gr.AtlasTex.TexID
|
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
|
return nil
|
||||||
}
|
}
|
||||||
@ -631,6 +711,11 @@ func NewGlyphRend(fontFile string, fontOptions *truetype.Options, screenWidth, s
|
|||||||
GlyphVBO: make([]float32, floatsPerGlyph*DefaultGlyphsPerBatch),
|
GlyphVBO: make([]float32, floatsPerGlyph*DefaultGlyphsPerBatch),
|
||||||
TextRunsBuf: make([]TextRun, 0, 20),
|
TextRunsBuf: make([]TextRun, 0, 20),
|
||||||
SpacesPerTab: 4,
|
SpacesPerTab: 4,
|
||||||
|
|
||||||
|
Opts: GlyphRendOpt_None,
|
||||||
|
OptValues: GlyphRendOptValues{
|
||||||
|
BgColor: gglm.NewVec4(0, 0, 0, 0),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
//Create glyph mesh
|
//Create glyph mesh
|
||||||
|
|||||||
9
main.go
9
main.go
@ -122,6 +122,7 @@ var (
|
|||||||
drawManyLines = false
|
drawManyLines = false
|
||||||
|
|
||||||
textToShow = ""
|
textToShow = ""
|
||||||
|
// textToShow = "Hello there, friend!"
|
||||||
|
|
||||||
xOff float32 = 0
|
xOff float32 = 0
|
||||||
yOff float32 = 0
|
yOff float32 = 0
|
||||||
@ -217,6 +218,9 @@ func (p *nterm) Init() {
|
|||||||
panic("Failed to create atlas from font file. Err: " + err.Error())
|
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 {
|
// if consts.Mode_Debug {
|
||||||
// glyphs.SaveImgToPNG(p.GlyphRend.Atlas.Img, "./debug-atlas.png")
|
// 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
|
//Position cursor by placing it at the end of the drawn characters then walking backwards
|
||||||
pos := p.lastCmdCharPos.Clone()
|
pos := p.lastCmdCharPos.Clone()
|
||||||
p.ScreenPosToGridPos(pos)
|
|
||||||
|
|
||||||
pos.AddY(p.GlyphRend.Atlas.LineHeight * 0.5)
|
pos.AddY(p.GlyphRend.Atlas.LineHeight * 0.5)
|
||||||
for i := clamp(p.cmdBufLen, 0, int64(len(p.cmdBuf))); i > p.cursorCharIndex; i-- {
|
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) {
|
func (p *nterm) ScreenPosToGridPos(screenPos *gglm.Vec3) {
|
||||||
screenPos.SetX(screenPos.X() / p.GlyphRend.Atlas.SpaceAdvance * p.GlyphRend.Atlas.SpaceAdvance)
|
screenPos.SetX(FloorF32(screenPos.X() / p.GlyphRend.Atlas.SpaceAdvance))
|
||||||
screenPos.SetY(screenPos.Y() / p.GlyphRend.Atlas.LineHeight * p.GlyphRend.Atlas.LineHeight)
|
screenPos.SetY(FloorF32(screenPos.Y() / p.GlyphRend.Atlas.LineHeight))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *nterm) DebugUpdate() {
|
func (p *nterm) DebugUpdate() {
|
||||||
|
|||||||
@ -13,6 +13,7 @@ layout(location=5) in vec2 aModelScale;
|
|||||||
|
|
||||||
out vec2 v2fUV0;
|
out vec2 v2fUV0;
|
||||||
out vec4 v2fColor;
|
out vec4 v2fColor;
|
||||||
|
out vec3 v2fModelPos;
|
||||||
out vec3 v2fFragPos;
|
out vec3 v2fFragPos;
|
||||||
|
|
||||||
uniform mat4 projViewMat;
|
uniform mat4 projViewMat;
|
||||||
@ -26,8 +27,9 @@ void main()
|
|||||||
aModelPos.x, aModelPos.y, aModelPos.z, 1.0
|
aModelPos.x, aModelPos.y, aModelPos.z, 1.0
|
||||||
);
|
);
|
||||||
|
|
||||||
v2fUV0 = aUV0 + aVertPos.xy * aUVSize;
|
|
||||||
v2fColor = aVertColor;
|
v2fColor = aVertColor;
|
||||||
|
v2fModelPos = aModelPos;
|
||||||
|
v2fUV0 = aUV0 + aVertPos.xy * aUVSize;
|
||||||
|
|
||||||
gl_Position = projViewMat * modelMat * vec4(aVertPos, 1.0);
|
gl_Position = projViewMat * modelMat * vec4(aVertPos, 1.0);
|
||||||
}
|
}
|
||||||
@ -37,22 +39,64 @@ void main()
|
|||||||
|
|
||||||
in vec2 v2fUV0;
|
in vec2 v2fUV0;
|
||||||
in vec4 v2fColor;
|
in vec4 v2fColor;
|
||||||
|
in vec3 v2fModelPos;
|
||||||
|
in vec4 gl_FragCoord;
|
||||||
|
|
||||||
out vec4 fragColor;
|
out vec4 fragColor;
|
||||||
|
|
||||||
uniform sampler2D diffTex;
|
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()
|
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);
|
vec4 texColor = texelFetch(diffTex, ivec2(v2fUV0), 0);
|
||||||
// This part highlights the full region of the char
|
if (texColor.r == 0)
|
||||||
if (texColor.r == 0 && drawBounds != 0)
|
{
|
||||||
|
if (drawGlyphBounds != 0)
|
||||||
{
|
{
|
||||||
fragColor = vec4(0,1,0,0.25);
|
fragColor = vec4(0,1,0,0.25);
|
||||||
}
|
}
|
||||||
else
|
return;
|
||||||
{
|
}
|
||||||
|
|
||||||
fragColor = vec4(v2fColor.rgb, texColor.r*v2fColor.a);
|
fragColor = vec4(v2fColor.rgb, texColor.r*v2fColor.a);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user