add some debug features using keys in gl avalonia:

- [U] - use default material for rendering
- [I] - toggle text shader (show raw texture)
- [O] - change text thickness ([O] - increase, [Shift] + [O] - decrease)
This commit is contained in:
firedef 2022-03-09 00:20:59 +03:00
Родитель 1a62b273cf
Коммит 2c4715b3a7
13 изменённых файлов: 68 добавлений и 45 удалений

Просмотреть файл

@ -98,7 +98,7 @@ public static class ElementsExamples {
Label l = new("amogus", canvas.canvas);
canvas.AddElement(l);
l.color = new("#FF8855");
l.color = new("#eb4034");
l.GenerateMesh();
// l.beforeRender += () => {

Просмотреть файл

@ -17,5 +17,5 @@ public abstract class ChartFactory {
public abstract Texture CreateTexture(string path);
public abstract Texture CreateTexture(float2 size);
public abstract FontTextures CreateFontTextureAtlas(FreeTypeFaceFacade face);
public abstract FontTextures CreateFontTextureAtlas(FreeTypeFaceFacade face, uint resolution = 32);
}

Просмотреть файл

@ -19,11 +19,11 @@ public class Font {
this.textures = textures;
}
public static Font LoadFromPath(string path, ChartsCanvas canvas) {
public static Font LoadFromPath(string path, ChartsCanvas canvas, uint resolution = 32) {
using FileStream fs = new(path, FileMode.Open);
FT.FT_New_Face(FreeType.ftLib.Native, path, 0, out IntPtr face).CheckError();
FreeTypeFaceFacade faceF = new(FreeType.ftLib, face);
return new("todo", false, false, false, canvas.factory.CreateFontTextureAtlas(faceF));
return new("todo", false, false, false, canvas.factory.CreateFontTextureAtlas(faceF, resolution));
}
}

Просмотреть файл

@ -9,15 +9,14 @@ public abstract class FontTextureAtlas {
public List<FontCharData> characters = new();
protected RectPack packer;
protected FontTextureAtlas(int size = 1024) => packer = new(size, 0);
protected FontTextureAtlas(int size = 1024) => packer = new(size, 1);
public unsafe (int i, int x, int y) Pack(int width, int height, string character) {
float2 size = texture.size;
float2 pos = packer.Pack(new(width, height));
if (pos == new float2(-1, -1)) return (-1, 0, 0);
AddChar((int) pos.x, (int) pos.y, width, height, character);
AddChar((int)pos.x, (int)pos.y, width, height, character);
return (characters.Count - 1, (int) pos.x, (int) pos.y);
}

Просмотреть файл

@ -0,0 +1,6 @@
namespace SomeChartsUi.ui.text;
//TODO: impl
public class TextMesh {
}

Просмотреть файл

@ -17,5 +17,5 @@ public class GlChartFactory : ChartFactory {
public override Shader CreateShader(string name, string vertex, string fragment) => new GlShader(name, vertex, fragment);
public override Texture CreateTexture(string path) => new GlTexture(path);
public override Texture CreateTexture(float2 size) => throw new NotImplementedException();
public override unsafe FontTextures CreateFontTextureAtlas(FreeTypeFaceFacade face) => new GlFontTextures(face);
public override unsafe FontTextures CreateFontTextureAtlas(FreeTypeFaceFacade face, uint resolution) => new GlFontTextures(face, resolution);
}

Просмотреть файл

@ -22,7 +22,8 @@ public class GlChartsBackend : ChartsBackendBase {
//TODO: oof
public override unsafe void DrawText(string text, color col, FontData font, RenderableTransform transform) {
testFont ??= Font.LoadFromPath("data/Comfortaa-VariableFont_wght.ttf", renderer.owner);
uint resolution = 32;
testFont ??= Font.LoadFromPath("data/Comfortaa-VariableFont_wght.ttf", renderer.owner, resolution);
// (FontCharData ch, int atlas) glyph = "AMOGUSamogus".ToCharArray().Select(c => testFont.textures.GetGlyph(c.ToString())).Last();
Random rnd = new();
//char c = (char) rnd.Next(60, 200);
@ -53,30 +54,39 @@ public class GlChartsBackend : ChartsBackendBase {
for (int i = 0; i < 1; i++) {
float xPos = 0;
float zPos = i * 0.1f;
foreach (char c in "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed tincidunt mollis pretium. Phasellus euismod tortor consequat, lobortis erat quis, accumsan ligula. Vestibulum at dolor congue ante ultricies lacinia. Vestibulum nec tellus nec mauris porttitor rhoncus. Nulla pellentesque placerat pulvinar. Nullam ut rutrum ante. Nulla nunc tellus, accumsan et facilisis ut, placerat vel neque. Proin feugiat eleifend justo nec posuere. Vestibulum convallis ipsum ut rutrum faucibus. Fusce faucibus suscipit nibh, ac pellentesque lorem pellentesque et. Donec at arcu a purus ultrices sagittis. Proin at congue diam.") {
string str =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed tincidunt mollis pretium. Phasellus euismod tortor consequat, lobortis erat quis, accumsan ligula. Vestibulum at dolor congue ante ultricies lacinia. Vestibulum nec tellus nec mauris porttitor rhoncus. Nulla pellentesque placerat pulvinar. Nullam ut rutrum ante. Nulla nunc tellus, accumsan et facilisis ut, placerat vel neque. Proin feugiat eleifend justo nec posuere. Vestibulum convallis ipsum ut rutrum faucibus. Fusce faucibus suscipit nibh, ac pellentesque lorem pellentesque et. Donec at arcu a purus ultrices sagittis. Proin at congue diam.";
for (int index = 0; index < str.Length; index++) {
char c = str[index];
float s = 16f / resolution;
(FontCharData ch, int atlas) glyph = testFont.textures.GetGlyph(c.ToString());
float s = 16 / 32f;
float zPos = index * 0.001f;
float yPos = -glyph.ch.baseline*s;
Vertex[] vertices = new Vertex[4] {
new(new(xPos, 0, zPos), new(0, 0), new(glyph.ch.position.x / 1024, glyph.ch.position.y / 1024 + glyph.ch.size.y / 1024), col),
new(new(xPos, s*glyph.ch.size.y, zPos), new(0, 1), new(glyph.ch.position.x / 1024, glyph.ch.position.y / 1024), col),
new(new(xPos+s*glyph.ch.size.x, s*glyph.ch.size.y, zPos), new(1, 1), new(glyph.ch.position.x / 1024 + glyph.ch.size.x / 1024, glyph.ch.position.y / 1024), col),
new(new(xPos+s*glyph.ch.size.x, 0, zPos), new(1, 0), new(glyph.ch.position.x / 1024 + glyph.ch.size.x / 1024, glyph.ch.position.y / 1024 + glyph.ch.size.y / 1024), col),
new(new(xPos, 0 + yPos, zPos), new(0, 0), new(glyph.ch.position.x / 1024, glyph.ch.position.y / 1024 + glyph.ch.size.y / 1024), col),
new(new(xPos, s * glyph.ch.size.y + yPos, zPos), new(0, 1), new(glyph.ch.position.x / 1024, glyph.ch.position.y / 1024), col),
new(new(xPos + s * glyph.ch.size.x, s * glyph.ch.size.y + yPos, zPos), new(1, 1), new(glyph.ch.position.x / 1024 + glyph.ch.size.x / 1024, glyph.ch.position.y / 1024), col),
new(new(xPos + s * glyph.ch.size.x, 0 + yPos, zPos), new(1, 0), new(glyph.ch.position.x / 1024 + glyph.ch.size.x / 1024, glyph.ch.position.y / 1024 + glyph.ch.size.y / 1024), col),
};
using Mesh m = owner.factory.CreateMesh();
m.SetIndexes(indices);
m.SetVertices(vertices);
if (testFont.textures.atlases.Count > 0) {
((GlTexture)testFont.textures.atlases[0].texture).Bind();
Material mat = new(GlShaders.basicText);
Material mat = new(AvaloniaGlChartsCanvas.debugTextMat ? GlShaders.basicTextured : GlShaders.basicText);
mat.SetProperty("texture0", ((GlTexture)testFont.textures.atlases[0].texture));
mat.SetProperty("u_gamma", AvaloniaGlChartsCanvas.textThickness);
DrawMesh(m, mat, transform);
}
xPos += 16;
xPos += glyph.ch.advance*s;
}
}

Просмотреть файл

@ -1,3 +1,4 @@
using System;
using Avalonia.Input;
using SomeChartsUi.ui;
using SomeChartsUi.ui.canvas;
@ -20,6 +21,16 @@ public class AvaloniaGlCanvasUiController : CanvasUiControllerBase {
base.OnKey(key, mods);
if (key == keycode.y) AvaloniaGlChartsCanvas.polygonMode = (PolygonMode)(((int)AvaloniaGlChartsCanvas.polygonMode + 1) % 3);
if (key == keycode.u) AvaloniaGlChartsCanvas.useDefaultMat = !AvaloniaGlChartsCanvas.useDefaultMat;
if (key == keycode.I) AvaloniaGlChartsCanvas.debugTextMat = !AvaloniaGlChartsCanvas.debugTextMat;
if (key == keycode.p) GlChartsBackend.perspectiveMode = !GlChartsBackend.perspectiveMode;
if (key == keycode.o) {
float th = AvaloniaGlChartsCanvas.textThickness;
th += (mods & keymods.shift) != 0 ? -.01f : .01f;
if (th > 1) th -= 1;
if (th < 0) th += 1;
Console.WriteLine(th);
AvaloniaGlChartsCanvas.textThickness = th;
}
}
}

Просмотреть файл

@ -23,7 +23,9 @@ public enum PolygonMode {
}
public class AvaloniaGlChartsCanvas : OpenGlControlBase {
public static bool useDefaultMat = false;
public static bool debugTextMat = false;
public static float textThickness = 0.52f;
public static PolygonMode polygonMode = PolygonMode.fill;
public readonly ChartsCanvas canvas = CreateCanvas();

Просмотреть файл

@ -1,3 +1,4 @@
using System;
using Avalonia.OpenGL;
using FreeTypeSharp.Native;
using MathStuff.vectors;
@ -9,7 +10,6 @@ namespace SomeChartsUiAvalonia.utils;
public class GlFontTextureAtlas : FontTextureAtlas {
private GlFontTextures _owner;
public const uint resolution = 32;
public GlFontTextureAtlas(GlFontTextures owner, int size = 1024) : base(size) {
_owner = owner;
@ -20,22 +20,15 @@ public class GlFontTextureAtlas : FontTextureAtlas {
GlTexture tex = new(width, height, GlConsts.GL_RED, GlConsts.GL_UNSIGNED_BYTE);
tex.Bind();
GlInfo.glExt!.GenerateMipmap(GlConsts.GL_TEXTURE_2D);
//GlInfo.glExt!.GenerateMipmap(GlConsts.GL_TEXTURE_2D);
return tex;
}
protected override unsafe void AddChar(int x, int y, int w, int h, string ch) {
//CodePoint point = new(ch[0]);
//Glyph glyph = _owner.face.GetGlyph(point, 32);
FT.FT_Set_Pixel_Sizes(_owner.face.Face, 0, resolution);
uint res0 = 0;
uint res = resolution;
//FT.FT_Set_Char_Size(_owner.face.Face, (IntPtr)(&res0), (IntPtr)(&res), 0, resolution);
FT.FT_Load_Char(_owner.face.Face, ch[0], FT.FT_LOAD_RENDER).CheckError();
uint height = _owner.face.FaceRec->glyph->bitmap.rows;
float advance = *(float*) &_owner.face.FaceRec->glyph->advance.x;
float baseline = *(float*) &_owner.face.FaceRec->glyph->advance.y;
float advance = *(int*)&_owner.face.FaceRec->glyph->linearHoriAdvance / 65536f;
float baseline = _owner.face.FaceRec->glyph->bitmap.rows - _owner.face.FaceRec->glyph->bitmap_top;
Console.WriteLine(baseline);
float2 size = new(w, h);
FontCharData data = new(advance, baseline, new(x, y), size, ch);
characters.Add(data);
@ -46,6 +39,6 @@ public class GlFontTextureAtlas : FontTextureAtlas {
GlInfo.glExt!.PixelStorei(GlConsts.GL_UNPACK_ALIGNMENT, 1);
GlInfo.glExt!.TexSubImage2D(GlConsts.GL_TEXTURE_2D, level, x, y, width, height, GlConsts.GL_RED, GlConsts.GL_UNSIGNED_BYTE, img);
//GlInfo.glExt!.TexSubImage2D(GlConsts.GL_TEXTURE_2D, 1, x>>1, y>>1, width>>1, height>>1, GlConsts.GL_RED, GlConsts.GL_UNSIGNED_BYTE, img);
GlInfo.glExt.GenerateMipmap(GlConsts.GL_TEXTURE_2D);
//GlInfo.glExt.GenerateMipmap(GlConsts.GL_TEXTURE_2D);
}
}

Просмотреть файл

@ -7,23 +7,25 @@ namespace SomeChartsUiAvalonia.utils;
public class GlFontTextures : FontTextures {
public FreeTypeFaceFacade face;
public uint resolution;
public unsafe GlFontTextures(FreeTypeFaceFacade face) => this.face = face;
public GlFontTextures(FreeTypeFaceFacade face, uint resolution) {
this.face = face;
this.resolution = resolution;
}
protected override unsafe (FontCharData ch, int atlas) Add(string character) {
//CodePoint point = new(character[0]);
FT.FT_Set_Pixel_Sizes(face.Face, 0, GlFontTextureAtlas.resolution);
FT.FT_Set_Pixel_Sizes(face.Face, 0, resolution);
FT.FT_Load_Char(face.Face, character[0], FT.FT_LOAD_RENDER).CheckError();
uint charIndex = face.GetCharIndex(character[0]);
if (charIndex == 0) return (default, -1);
FT.FT_Render_Glyph((IntPtr)face.GlyphSlot, FT_Render_Mode.FT_RENDER_MODE_SDF).CheckError();
uint width = face.FaceRec->glyph->bitmap.width;
uint height = face.FaceRec->glyph->bitmap.rows;
FT.FT_Render_Glyph((IntPtr)face.GlyphSlot, FT_Render_Mode.FT_RENDER_MODE_SDF).CheckError();
for (int i = 0; i < atlases.Count; i++) {
int index = Add_(atlases[i]);

Просмотреть файл

@ -67,7 +67,7 @@ public class GlTexture : Texture, IDisposable {
}
public static void SetFilter(TextureFilter v) {
SetParameter(GlConsts.GL_TEXTURE_MIN_FILTER, (v == TextureFilter.nearest ? GlConsts.GL_NEAREST : GlConsts.GL_LINEAR_MIPMAP_LINEAR));
SetParameter(GlConsts.GL_TEXTURE_MIN_FILTER, (v == TextureFilter.nearest ? GlConsts.GL_NEAREST : GlConsts.GL_LINEAR));
SetParameter(GlConsts.GL_TEXTURE_MAG_FILTER, (int)v);
}

Просмотреть файл

@ -96,7 +96,7 @@ public class GlMesh : Mesh {
BindBuffers();
if (updateRequired | isDynamic) UpdateBuffers();
GlShader shader = material == null ? GlShaders.basic : (GlShader) material.shader;
GlShader shader = material == null || AvaloniaGlChartsCanvas.useDefaultMat ? GlShaders.basic : (GlShader) material.shader;
if (shader.shaderProgram == 0) shader.TryCompile();
if (shader.shaderProgram == 0) return;