first version of font atlas generator complete
This commit is contained in:
parent
2780f811f0
commit
63c942294c
Binary file not shown.
@ -10,6 +10,7 @@ import math;
|
||||
import core.stdc.math : cosf, sinf;
|
||||
import std.algorithm.sorting;
|
||||
import fonts;
|
||||
import main;
|
||||
|
||||
f32 g_DELTA;
|
||||
|
||||
@ -109,13 +110,7 @@ InitGame(PlatformWindow* window)
|
||||
u8[16*16*4] white_tex;
|
||||
white_tex[] = u8.max;
|
||||
|
||||
u8[] atlas = LoadAssetData(&g.frame_arena, "textures/atlas.png");
|
||||
int width, height, has_ch;
|
||||
auto img = stbi_load_from_memory(atlas.ptr, cast(int)atlas.length, &width, &height, &has_ch, 4);
|
||||
assert(width == FONT_ATLAS.width && height == FONT_ATLAS.height && has_ch == 1, "atlas height and width do not match");
|
||||
u8[] img_slice = img[0 .. width * height * 4];
|
||||
|
||||
CreateImageView(&g.rd, &g.font_tex, FONT_ATLAS.width, FONT_ATLAS.height, 4, img_slice);
|
||||
CreateImageView(&g.rd, &g.font_tex, FONT_ATLAS_TEST.atlas.width, FONT_ATLAS_TEST.atlas.height, 4, FONT_ATLAS_TEST.data);
|
||||
// TODO: fix buffer overflow between two textures
|
||||
//CreateImageView(&g.rd, &g.default_tex, 16, 16, 4, white_tex);
|
||||
|
||||
@ -177,7 +172,7 @@ Cycle(Game* g)
|
||||
Reset(&g.frame_arena);
|
||||
|
||||
DrawRect(g, 500.0, 500.0, 800.0, 800.0, Vec4(0.2, 0.3, 0.7, 1.0));
|
||||
DrawText(g, 200.0, 200.0, FONT_ATLAS.size, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
||||
DrawText(g, 200.0, 200.0, 128.0, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
||||
|
||||
BeginFrame(&g.rd);
|
||||
|
||||
@ -323,19 +318,20 @@ void
|
||||
DrawText(Game* g, f32 x, f32 y, f32 px, string str)
|
||||
{
|
||||
f32 x_pos = x;
|
||||
f32 scale = px / FONT_ATLAS_TEST.atlas.size;
|
||||
foreach(ch; str)
|
||||
{
|
||||
foreach(glyph; FONT_ATLAS.glyphs)
|
||||
foreach(glyph; FONT_ATLAS_TEST.atlas.glyphs)
|
||||
{
|
||||
if (ch == glyph.ch)
|
||||
{
|
||||
UIVertex* v = g.ui_vertex_buf.ptr + g.ui_count;
|
||||
|
||||
f32 r = px * glyph.plane_right;
|
||||
f32 l = px * glyph.plane_left;
|
||||
f32 r = glyph.plane_right * scale;
|
||||
f32 l = glyph.plane_left * scale;
|
||||
f32 w = r - l;
|
||||
f32 h = px * (glyph.plane_bottom - glyph.plane_top);
|
||||
f32 y_pos = px * glyph.plane_bottom;
|
||||
f32 h = (glyph.plane_bottom - glyph.plane_top) * scale;
|
||||
f32 y_pos = glyph.plane_top * scale;
|
||||
|
||||
v.dst_start.x = x_pos + l;
|
||||
v.dst_start.y = y + h - y_pos;
|
||||
@ -349,9 +345,11 @@ DrawText(Game* g, f32 x, f32 y, f32 px, string str)
|
||||
|
||||
v.col = Vec4(1.0, 1.0, 1.0, 1.0);
|
||||
|
||||
x_pos += px * glyph.advance;
|
||||
x_pos += glyph.advance * scale;
|
||||
|
||||
AddUIIndices(g);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
public import includes;
|
||||
import includes;
|
||||
import std.stdio;
|
||||
import aliases;
|
||||
import core.memory;
|
||||
@ -13,6 +13,8 @@ import font;
|
||||
import alloc;
|
||||
import assets;
|
||||
|
||||
FontAtlasBuf FONT_ATLAS_TEST;
|
||||
|
||||
// TODO:
|
||||
// 1. Determine how to better handle inputs
|
||||
// 2. Set up multisampling
|
||||
@ -20,14 +22,14 @@ import assets;
|
||||
|
||||
void main(string[] argv)
|
||||
{
|
||||
PlatformWindow window = CreateWindow("Video Game", 1920, 1080);
|
||||
Game g = InitGame(&window);
|
||||
|
||||
Arena arena = CreateArena(MB(8));
|
||||
Arena arena = CreateArena(MB(32));
|
||||
InitFreeType();
|
||||
u8[] font_data = LoadAssetData(&arena, "fonts/NuberNextCondensed-DemiBold.otf");
|
||||
FontFace font = OpenFont(font_data);
|
||||
FontAtlasBuf atlas = CreateAtlas(&arena, font, 32.0, 256);
|
||||
FONT_ATLAS_TEST = CreateAtlas(&arena, font, 128.0, 2048);
|
||||
|
||||
PlatformWindow window = CreateWindow("Video Game", 1920, 1080);
|
||||
Game g = InitGame(&window);
|
||||
|
||||
while (true)
|
||||
{
|
||||
|
||||
@ -1685,7 +1685,7 @@ CreateGraphicsPipeline(Vulkan* vk, GfxPipelineInfo* build_info)
|
||||
cullMode: VK_CULL_MODE_BACK_BIT,
|
||||
polygonMode: VK_POLYGON_MODE_FILL,
|
||||
lineWidth: 1.0,
|
||||
frontFace: VK_FRONT_FACE_CLOCKWISE,
|
||||
frontFace: VK_FRONT_FACE_COUNTER_CLOCKWISE,
|
||||
};
|
||||
|
||||
VkPipelineMultisampleStateCreateInfo multisample_info = {
|
||||
|
||||
@ -41,10 +41,10 @@ void main()
|
||||
vec2 src_pos = (Vertices[gl_VertexIndex] * src_half_size + src_center);
|
||||
|
||||
vec2 uvs[4] = vec2[4](
|
||||
vec2(in_src_start.x, in_src_end.y),
|
||||
vec2(in_src_start.x, in_src_start.y),
|
||||
vec2(in_src_end.x, in_src_end.y),
|
||||
vec2(in_src_end.x, in_src_start.y)
|
||||
vec2(in_src_start.x, in_src_end.y),
|
||||
vec2(in_src_end.x, in_src_start.y),
|
||||
vec2(in_src_end.x, in_src_end.y)
|
||||
);
|
||||
|
||||
FragData.color = in_col;
|
||||
|
||||
@ -18,6 +18,15 @@ InitFreeType()
|
||||
FT_Init_FreeType(&FT_LIB);
|
||||
}
|
||||
|
||||
void
|
||||
CloseFreeType()
|
||||
{
|
||||
if (FT_LIB)
|
||||
{
|
||||
FT_Done_FreeType(FT_LIB);
|
||||
}
|
||||
}
|
||||
|
||||
FontFace
|
||||
OpenFont(u8[] data)
|
||||
{
|
||||
@ -36,12 +45,17 @@ CloseFont(FontFace font)
|
||||
}
|
||||
|
||||
FontAtlasBuf
|
||||
CreateAtlas(Arena* arena, FontFace font, f32 size, u64 dimension)
|
||||
CreateAtlas(Arena* arena, FontFace font, f32 size, u32 dimension)
|
||||
{
|
||||
assert(dimension >= 128, "Dimension must be at least 128");
|
||||
|
||||
FontAtlasBuf atlas = {
|
||||
data: AllocArray!(u8)(arena, dimension * dimension * 4),
|
||||
atlas: {
|
||||
size: size,
|
||||
width: dimension,
|
||||
height: dimension,
|
||||
},
|
||||
};
|
||||
|
||||
// TODO: proper packing algorithm
|
||||
@ -88,11 +102,15 @@ CreateAtlas(Arena* arena, FontFace font, f32 size, u64 dimension)
|
||||
current_h = 0;
|
||||
count = 0;
|
||||
|
||||
u32 font_w = font.size.metrics.x_ppem;
|
||||
u32 font_h = font.size.metrics.y_ppem;
|
||||
|
||||
char_code = FT_Get_First_Char(font, &index);
|
||||
while (index != 0)
|
||||
{
|
||||
FT_Load_Char(font, char_code, cast(FT_Int32)FT_LOAD_RENDER);
|
||||
|
||||
FT_GlyphSlot glyph = font.glyph;
|
||||
FT_Bitmap* bmp = &font.glyph.bitmap;
|
||||
i32 top = font.glyph.bitmap_top;
|
||||
i32 left = font.glyph.bitmap_left;
|
||||
@ -103,29 +121,48 @@ CreateAtlas(Arena* arena, FontFace font, f32 size, u64 dimension)
|
||||
max_w = 0;
|
||||
}
|
||||
|
||||
i32 x, y;
|
||||
foreach(r; 0 .. bmp.rows)
|
||||
{
|
||||
i32 y = cast(i32)(max_h + r);
|
||||
y = cast(i32)(max_h + r);
|
||||
foreach(c; 0 .. bmp.width)
|
||||
{
|
||||
i32 x = max_w + left + c;
|
||||
x = max_w + c;
|
||||
u64 offset = (y*dimension + x) * 4;
|
||||
|
||||
atlas.data[offset+0] = 255;
|
||||
atlas.data[offset+1] = 255;
|
||||
atlas.data[offset+2] = 255;
|
||||
atlas.data[offset+3] = bmp.buffer[r*bmp.pitch + c];
|
||||
atlas.data[offset+0] = bmp.buffer[r*bmp.pitch + c];
|
||||
atlas.data[offset+1] = bmp.buffer[r*bmp.pitch + c];
|
||||
atlas.data[offset+2] = bmp.buffer[r*bmp.pitch + c];
|
||||
atlas.data[offset+3] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
Glyph* g = atlas.atlas.glyphs.ptr + count;
|
||||
|
||||
g.ch = cast(dchar)char_code;
|
||||
g.advance = cast(f32)(glyph.advance.x >> 6);
|
||||
g.plane_left = cast(f32)left;
|
||||
g.plane_right = g.plane_left + bmp.width;
|
||||
g.plane_top = cast(f32)top;
|
||||
g.plane_bottom = g.plane_top + bmp.rows;
|
||||
|
||||
g.atlas_top = max_h;
|
||||
g.atlas_left = max_w;
|
||||
g.atlas_bottom = max_h + bmp.rows;
|
||||
g.atlas_right = max_w + bmp.width;
|
||||
|
||||
max_w += bmp.width;
|
||||
current_h = bmp.rows > current_h ? bmp.rows : current_h;
|
||||
|
||||
char_code = FT_Get_Next_Char(font, char_code, &index);
|
||||
|
||||
count += 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return atlas;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user