text rendering
This commit is contained in:
parent
6e80c811cf
commit
d7c708e5d4
Binary file not shown.
|
@ -91,9 +91,44 @@ void make_quad(Platform_Geometry_Buffer* geo, Platform_Shader* shd, Platform_Tex
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
ed_load_font_cb(Platform_File_Async_Job_Args result)
|
ed_load_font_cb(Platform_File_Async_Job_Args result, u8* user_data)
|
||||||
{
|
{
|
||||||
s32 x = 5;
|
App_State* state = (App_State*)user_data;
|
||||||
|
UI* ui = &state->editor->ui;
|
||||||
|
|
||||||
|
u8* f = result.data.base;
|
||||||
|
stbtt_fontinfo font;
|
||||||
|
if (!stbtt_InitFont(&font, f, stbtt_GetFontOffsetForIndex(f, 0)))
|
||||||
|
{
|
||||||
|
invalid_code_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
r32 scale = stbtt_ScaleForPixelHeight(&font, 18.0f);
|
||||||
|
s32 ascent, descent, line_gap;
|
||||||
|
stbtt_GetFontVMetrics(&font, &ascent, &descent, &line_gap);
|
||||||
|
ui->font_ascent = (r32)ascent * scale;
|
||||||
|
ui->font_descent = (r32)descent * scale;
|
||||||
|
ui->font_line_gap = (r32)line_gap * scale;
|
||||||
|
if (ui->font_line_gap == 0) ui->font_line_gap = 5;
|
||||||
|
|
||||||
|
String c = lit_str("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-=_+[]{}\\|;:'\",<.>/?`~");
|
||||||
|
for (u64 i = 0; i < c.len; i++)
|
||||||
|
{
|
||||||
|
s32 w, h, xoff, yoff;
|
||||||
|
u32 id = (u32)c.str[i];
|
||||||
|
u8* bp = stbtt_GetCodepointBitmap(&font, 0, scale, (char)c.str[i], &w, &h, &xoff, &yoff);
|
||||||
|
s32 x0, y0, x1, y1;
|
||||||
|
stbtt_GetCodepointBitmapBoxSubpixel(&font, (char)c.str[i], scale, scale, 0, 0, &x0, &y0, &x1, &y1);
|
||||||
|
|
||||||
|
v2 offset = v2{ 0, (r32)y0 };
|
||||||
|
texture_atlas_register(&state->editor->ui.atlas, bp, (u32)w, (u32)h, id, offset, TextureAtlasRegistration_PixelFormat_Alpha);
|
||||||
|
stbtt_FreeBitmap(bp, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture_Atlas_Sprite m_sprite = texture_atlas_sprite_get(&state->editor->ui.atlas, (u32)'m');
|
||||||
|
ui->font_space_width = (r32)(m_sprite.max_x - m_sprite.min_x);
|
||||||
|
|
||||||
|
platform_texture_update(ui->atlas_texture, ui->atlas.pixels, 1024, 1024, 1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
|
|
|
@ -23,7 +23,6 @@ static String ui_shader_frag_win32 = lit_str(
|
||||||
"uniform sampler2D texture;\n"
|
"uniform sampler2D texture;\n"
|
||||||
"void main(void) {\n"
|
"void main(void) {\n"
|
||||||
" FragColor = texture(texture, uv) * color;\n"
|
" FragColor = texture(texture, uv) * color;\n"
|
||||||
" if (FragColor.w <= 0.01f) discard;\n"
|
|
||||||
"}"
|
"}"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -73,8 +72,13 @@ ui_create(u32 widget_pool_cap, u32 verts_cap, Input_State* input, Allocator* a)
|
||||||
result.atlas = texture_atlas_create(1024, 1024, 512, permanent);
|
result.atlas = texture_atlas_create(1024, 1024, 512, permanent);
|
||||||
result.atlas_texture = platform_texture_create(result.atlas.pixels, 1024, 1024, 1024);
|
result.atlas_texture = platform_texture_create(result.atlas.pixels, 1024, 1024, 1024);
|
||||||
|
|
||||||
u32 white_sprite[] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
|
u32 white_sprite[] = {
|
||||||
ui_sprite_register(&result, (u8*)white_sprite, 2, 2, WHITE_SPRITE_ID);
|
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||||
|
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||||
|
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||||
|
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||||
|
};
|
||||||
|
ui_sprite_register(&result, (u8*)white_sprite, 4, 4, WHITE_SPRITE_ID);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -119,14 +123,17 @@ ui_quad_push(UI* ui, v3 pmin, v3 pmax, v2 tmin, v2 tmax, v4 c)
|
||||||
internal void
|
internal void
|
||||||
ui_sprite_register(UI* ui, u8* pixels, u32 w, u32 h, u32 id)
|
ui_sprite_register(UI* ui, u8* pixels, u32 w, u32 h, u32 id)
|
||||||
{
|
{
|
||||||
texture_atlas_register(&ui->atlas, pixels, w, h, id);
|
texture_atlas_register(&ui->atlas, pixels, w, h, id, v2{0,0}, TextureAtlasRegistration_PixelFormat_RGBA);
|
||||||
platform_texture_update(ui->atlas_texture, ui->atlas.pixels, ui->atlas.width, ui->atlas.height, ui->atlas.width);
|
platform_texture_update(ui->atlas_texture, ui->atlas.pixels, ui->atlas.width, ui->atlas.height, ui->atlas.width);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
ui_sprite_push(UI* ui, v3 pmin, v3 pmax, u32 id, v4 color)
|
ui_sprite_push(UI* ui, v3 pmin, v3 pmax, u32 id, v4 color)
|
||||||
{
|
{
|
||||||
v4 uv = texture_atlas_sprite_get_uvs(&ui->atlas, id);
|
Texture_Atlas_Sprite sprite = texture_atlas_sprite_get(&ui->atlas, id);
|
||||||
|
v4 uv = texture_atlas_sprite_get_uvs(&ui->atlas, sprite);
|
||||||
|
pmin.XY += sprite.draw_offset;
|
||||||
|
pmax.XY += sprite.draw_offset;
|
||||||
ui_quad_push(ui, pmin, pmax, uv.xy, uv.zw, color);
|
ui_quad_push(ui, pmin, pmax, uv.xy, uv.zw, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,6 +143,37 @@ ui_sprite_push(UI* ui, v3 pmin, v3 pmax, u32 id)
|
||||||
ui_sprite_push(ui, pmin, pmax, id, v4{1,1,1,1});
|
ui_sprite_push(ui, pmin, pmax, id, v4{1,1,1,1});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct UI_Char_Draw_Cmd
|
||||||
|
{
|
||||||
|
v4 uv;
|
||||||
|
v3 pmin;
|
||||||
|
v3 pmax;
|
||||||
|
v3 baseline_after;
|
||||||
|
};
|
||||||
|
|
||||||
|
internal UI_Char_Draw_Cmd
|
||||||
|
ui_sprite_char_get_draw_cmd(UI* ui, v3 at, u32 codepoint)
|
||||||
|
{
|
||||||
|
UI_Char_Draw_Cmd result = {};
|
||||||
|
|
||||||
|
Texture_Atlas_Sprite sprite = texture_atlas_sprite_get(&ui->atlas, codepoint);
|
||||||
|
result.uv = texture_atlas_sprite_get_uvs(&ui->atlas, sprite);
|
||||||
|
|
||||||
|
v3 dim = v3{
|
||||||
|
(r32)(sprite.max_x - sprite.min_x),
|
||||||
|
(r32)(sprite.max_y - sprite.min_y),
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
result.pmin = at;
|
||||||
|
result.pmin.XY += sprite.draw_offset;
|
||||||
|
result.pmin = v3_floor(result.pmin);
|
||||||
|
result.pmax = result.pmin + dim;
|
||||||
|
|
||||||
|
result.baseline_after = v3{ result.pmax.x, at.y, at.z };
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
ui_frame_prepare(UI* ui, v2 window_dim)
|
ui_frame_prepare(UI* ui, v2 window_dim)
|
||||||
{
|
{
|
||||||
|
@ -184,12 +222,12 @@ ui_draw(UI* ui)
|
||||||
UI_Widget_Result r0 = ui_widget_push(ui, d0);
|
UI_Widget_Result r0 = ui_widget_push(ui, d0);
|
||||||
|
|
||||||
UI_Widget_Desc d1 = d0;
|
UI_Widget_Desc d1 = d0;
|
||||||
d1.style.flags |= UIWidgetStyle_Outline | UIWidgetStyle_MouseClick;
|
d1.style.flags |= UIWidgetStyle_Outline | UIWidgetStyle_MouseClick | UIWidgetStyle_Text;
|
||||||
d1.style.color_bg = PINK_V4;
|
d1.style.color_bg = PINK_V4;//{ 0.1f, 0.1f, 0.1f, 1.0f }; //
|
||||||
d1.style.color_fg = GREEN_V4;
|
d1.style.color_fg = GREEN_V4;
|
||||||
d1.p_min = v2{ 512, 32 };
|
d1.p_min = v2{ 512, 32 };
|
||||||
d1.p_max = v2{ 640, 128 };
|
d1.p_max = v2{ 640, 128 };
|
||||||
d1.string = lit_str("Hello");
|
d1.string = lit_str("Hello there my friend, what's going on?");
|
||||||
UI_Widget_Result r1 = ui_widget_push(ui, d1);
|
UI_Widget_Result r1 = ui_widget_push(ui, d1);
|
||||||
bool clicked_r1 = has_flag(r1.flags, UIWidgetResult_MouseLeft_WentUp);
|
bool clicked_r1 = has_flag(r1.flags, UIWidgetResult_MouseLeft_WentUp);
|
||||||
if (clicked_r1) show = !show;
|
if (clicked_r1) show = !show;
|
||||||
|
@ -214,7 +252,7 @@ ui_draw(UI* ui)
|
||||||
u32 widget_count = ui->widgets.free_len;
|
u32 widget_count = ui->widgets.free_len;
|
||||||
r32 range_min = -10;
|
r32 range_min = -10;
|
||||||
r32 range_max = -1;
|
r32 range_max = -1;
|
||||||
r32 range_step = (range_max - range_min) / (r32)widget_count;
|
r32 range_step = (range_max - range_min) / (r32)(widget_count * 4);
|
||||||
ui_widgets_to_geometry_recursive(ui, ui->widgets.root, -10, range_step);
|
ui_widgets_to_geometry_recursive(ui, ui->widgets.root, -10, range_step);
|
||||||
|
|
||||||
platform_geometry_buffer_update(
|
platform_geometry_buffer_update(
|
||||||
|
@ -402,14 +440,48 @@ ui_widgets_to_geometry_recursive(UI* ui, UI_Widget* widget, r32 z_start, r32 z_s
|
||||||
|
|
||||||
if (has_flag(child->desc.style.flags, UIWidgetStyle_Bg))
|
if (has_flag(child->desc.style.flags, UIWidgetStyle_Bg))
|
||||||
{
|
{
|
||||||
bg_min.z += z_step;
|
z_at += z_step;
|
||||||
bg_max.z += z_step;
|
bg_min.z = z_at;
|
||||||
|
bg_max.z = z_at;
|
||||||
ui_sprite_push(ui, bg_min, bg_max, desc.style.sprite, color_bg);
|
ui_sprite_push(ui, bg_min, bg_max, desc.style.sprite, color_bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_flag(child->desc.style.flags, UIWidgetStyle_Text))
|
if (has_flag(child->desc.style.flags, UIWidgetStyle_Text))
|
||||||
{
|
{
|
||||||
// TODO(PS):
|
z_at += z_step + z_step;
|
||||||
|
r32 space_width = ui->font_space_width;
|
||||||
|
r32 to_baseline = ui->font_line_gap + ui->font_ascent;
|
||||||
|
v3 line_offset = { 5, 3 + to_baseline, 0 };
|
||||||
|
r32 baseline_x_start = desc.p_min.x + line_offset.x;
|
||||||
|
r32 baseline_y_start = desc.p_min.y + line_offset.y;
|
||||||
|
v3 baseline = { baseline_x_start, baseline_y_start, z_at };
|
||||||
|
for (u64 i = 0; i < child->desc.string.len; i++)
|
||||||
|
{
|
||||||
|
u8 at = child->desc.string.str[i];
|
||||||
|
UI_Char_Draw_Cmd cmd = {};
|
||||||
|
if (!char_is_space(at))
|
||||||
|
{
|
||||||
|
cmd = ui_sprite_char_get_draw_cmd(ui, baseline, (u32)at);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cmd.baseline_after = baseline;
|
||||||
|
cmd.baseline_after.x += space_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd.baseline_after.x >= desc.p_max.x - 5)
|
||||||
|
{
|
||||||
|
baseline.x = baseline_x_start;
|
||||||
|
baseline.y += ui->font_ascent + ui->font_descent + ui->font_line_gap;
|
||||||
|
cmd = ui_sprite_char_get_draw_cmd(ui, baseline, (u32)at);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!char_is_space(at))
|
||||||
|
{
|
||||||
|
ui_quad_push(ui, cmd.pmin, cmd.pmax, cmd.uv.xy, cmd.uv.zw, color_fg);
|
||||||
|
}
|
||||||
|
baseline = cmd.baseline_after;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (child->child_first)
|
if (child->child_first)
|
||||||
|
|
|
@ -130,6 +130,7 @@ struct UI
|
||||||
u32 indices_cap;
|
u32 indices_cap;
|
||||||
|
|
||||||
Texture_Atlas atlas;
|
Texture_Atlas atlas;
|
||||||
|
r32 font_ascent, font_descent, font_line_gap, font_space_width;
|
||||||
|
|
||||||
UI_Widget_Pool widgets;
|
UI_Widget_Pool widgets;
|
||||||
UI_Style_Sheet* style_sheet;
|
UI_Style_Sheet* style_sheet;
|
||||||
|
@ -156,6 +157,7 @@ internal void ui_quad_push(UI* ui, v3 pmin, v3 pmax, v2 tmin, v2 tmax, v4 c);
|
||||||
internal void ui_sprite_register(UI* ui, u8* pixels, u32 w, u32 h, u32 id);
|
internal void ui_sprite_register(UI* ui, u8* pixels, u32 w, u32 h, u32 id);
|
||||||
internal void ui_sprite_push(UI* ui, v3 pmin, v3 pmax, u32 id, v4 color);
|
internal void ui_sprite_push(UI* ui, v3 pmin, v3 pmax, u32 id, v4 color);
|
||||||
internal void ui_sprite_push(UI* ui, v3 pmin, v3 pmax, u32 id);
|
internal void ui_sprite_push(UI* ui, v3 pmin, v3 pmax, u32 id);
|
||||||
|
internal v3 ui_sprite_char_push(UI* ui, v2 at, u32 codepoint, v4 color);
|
||||||
internal void ui_draw(UI* ui);
|
internal void ui_draw(UI* ui);
|
||||||
|
|
||||||
// Widgets
|
// Widgets
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -44,7 +44,7 @@ lumenarium_frame_prepare(App_State* state)
|
||||||
}
|
}
|
||||||
incenter_frame_prepare(state);
|
incenter_frame_prepare(state);
|
||||||
|
|
||||||
platform_file_async_jobs_do_work(4);
|
platform_file_async_jobs_do_work(4, (u8*)state);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
|
|
|
@ -9,17 +9,19 @@ struct Texture_Atlas_Sprite
|
||||||
u16 min_y;
|
u16 min_y;
|
||||||
u16 max_x;
|
u16 max_x;
|
||||||
u16 max_y;
|
u16 max_y;
|
||||||
|
|
||||||
|
v2 draw_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Texture_Atlas
|
struct Texture_Atlas
|
||||||
{
|
{
|
||||||
u8* pixels;
|
u8* pixels;
|
||||||
u16 width;
|
u32 width;
|
||||||
u16 height;
|
u32 height;
|
||||||
|
|
||||||
u16 next_x;
|
u32 next_x;
|
||||||
u16 next_y;
|
u32 next_y;
|
||||||
u16 y_used;
|
u32 y_used;
|
||||||
|
|
||||||
u32* ids;
|
u32* ids;
|
||||||
Texture_Atlas_Sprite* sprites;
|
Texture_Atlas_Sprite* sprites;
|
||||||
|
@ -36,7 +38,7 @@ texture_atlas_create(u32 width, u32 height, u32 cap, Allocator* allocator)
|
||||||
result.height = (u16)height;
|
result.height = (u16)height;
|
||||||
for (u32 i = 0; i < width * height; i++) {
|
for (u32 i = 0; i < width * height; i++) {
|
||||||
u8* base = result.pixels + (i * 4);
|
u8* base = result.pixels + (i * 4);
|
||||||
*(u32*)base = 0xFFFFFFFF;
|
*(u32*)base = 0x00FFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
result.ids = allocator_alloc_array(allocator, u32, cap);
|
result.ids = allocator_alloc_array(allocator, u32, cap);
|
||||||
|
@ -46,23 +48,35 @@ texture_atlas_create(u32 width, u32 height, u32 cap, Allocator* allocator)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
enum Texture_Atlas_Registration_Flags
|
||||||
texture_atlas_register(Texture_Atlas* ta, u8* pixels, u32 width, u32 height, u32 id)
|
|
||||||
{
|
{
|
||||||
u16 min_x = ta->next_x;
|
TextureAtlasRegistration_None = 0,
|
||||||
u16 min_y = ta->next_y;
|
TextureAtlasRegistration_PixelFormat_RGBA = 1,
|
||||||
u16 max_x = min_x + (u16)width;
|
TextureAtlasRegistration_PixelFormat_Alpha = 2,
|
||||||
u16 max_y = min_y + (u16)height;
|
};
|
||||||
|
|
||||||
// TODO(PS): if the sprite won't fit in this row, then we need to shift it to
|
internal void
|
||||||
// the next one
|
texture_atlas_register(Texture_Atlas* ta, u8* pixels, u32 width, u32 height, u32 id, v2 draw_offset, u32 flags)
|
||||||
|
{
|
||||||
|
if (ta->next_x > ta->width || (ta->next_x + width + 2) > ta->width)
|
||||||
|
{
|
||||||
|
ta->next_x = 0;
|
||||||
|
ta->next_y = ta->y_used;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 min_x = ta->next_x + 1;
|
||||||
|
u32 min_y = ta->next_y + 1;
|
||||||
|
u32 max_x = min_x + width;
|
||||||
|
u32 max_y = min_y + height;
|
||||||
|
|
||||||
// copy the data
|
// copy the data
|
||||||
for (u16 y = 0; y < height; y++)
|
if (has_flag(flags, TextureAtlasRegistration_PixelFormat_RGBA))
|
||||||
{
|
{
|
||||||
u16 src_row = (y * (u16)width) * 4;
|
for (u32 y = 0; y < height; y++)
|
||||||
u16 dst_row = (((y + min_y) * ta->width) + min_x) * 4;
|
{
|
||||||
for (u16 x = 0; x < width; x++)
|
u32 src_row = (y * width) * 4;
|
||||||
|
u32 dst_row = (((y + min_y) * ta->width) + min_x) * 4;
|
||||||
|
for (u32 x = 0; x < width; x++)
|
||||||
{
|
{
|
||||||
ta->pixels[dst_row++] = pixels[src_row++];
|
ta->pixels[dst_row++] = pixels[src_row++];
|
||||||
ta->pixels[dst_row++] = pixels[src_row++];
|
ta->pixels[dst_row++] = pixels[src_row++];
|
||||||
|
@ -70,28 +84,73 @@ texture_atlas_register(Texture_Atlas* ta, u8* pixels, u32 width, u32 height, u32
|
||||||
ta->pixels[dst_row++] = pixels[src_row++];
|
ta->pixels[dst_row++] = pixels[src_row++];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else if (has_flag(flags, TextureAtlasRegistration_PixelFormat_Alpha))
|
||||||
|
{
|
||||||
|
for (u32 y = 0; y < height; y++)
|
||||||
|
{
|
||||||
|
u32 src_row = y * width;
|
||||||
|
u32 dst_row = (((y + min_y) * ta->width) + min_x) * 4;
|
||||||
|
for (u32 x = 0; x < width; x++)
|
||||||
|
{
|
||||||
|
ta->pixels[dst_row++] = 0xFF;
|
||||||
|
ta->pixels[dst_row++] = 0xFF;
|
||||||
|
ta->pixels[dst_row++] = 0xFF;
|
||||||
|
ta->pixels[dst_row++] = pixels[src_row++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy nearest pixels to the border
|
||||||
|
u32 pi_width = ta->width;
|
||||||
|
u32 pi_stride = 4;
|
||||||
|
#define PIXEL_INDEX(x,y) ((((y) * pi_width) + (x)) * pi_stride)
|
||||||
|
#define COPY_PIXEL(db,sb) \
|
||||||
|
ta->pixels[(db) + 0] = ta->pixels[(sb) + 0]; \
|
||||||
|
ta->pixels[(db) + 1] = ta->pixels[(sb) + 1]; \
|
||||||
|
ta->pixels[(db) + 2] = ta->pixels[(sb) + 2]; \
|
||||||
|
ta->pixels[(db) + 3] = ta->pixels[(sb) + 3];
|
||||||
|
|
||||||
|
for (u32 x = 0; x < width; x++)
|
||||||
|
{
|
||||||
|
u32 top = PIXEL_INDEX(min_x + x, min_y - 1);
|
||||||
|
u32 top_near = PIXEL_INDEX(min_x + x, min_y);
|
||||||
|
u32 bot = PIXEL_INDEX(min_x + x, max_y);
|
||||||
|
u32 bot_near = PIXEL_INDEX(min_x + x, max_y - 1);
|
||||||
|
COPY_PIXEL(top, top_near);
|
||||||
|
COPY_PIXEL(bot, bot_near);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 y = 0; y < height + 2; y++)
|
||||||
|
{
|
||||||
|
u32 left = PIXEL_INDEX(min_x - 1, min_y + y - 1);
|
||||||
|
u32 left_near = PIXEL_INDEX(min_x, min_y + y - 1);
|
||||||
|
u32 right = PIXEL_INDEX(max_x, min_y + y - 1);
|
||||||
|
u32 right_near = PIXEL_INDEX(max_x - 1, min_y + y - 1);
|
||||||
|
COPY_PIXEL(left, left_near);
|
||||||
|
COPY_PIXEL(right, right_near);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef PIXEL_INDEX
|
||||||
|
#undef COPY_PIXEL
|
||||||
|
|
||||||
// register a new slot
|
// register a new slot
|
||||||
u32 index = hash_table_register(ta->ids, ta->cap, id);
|
u32 index = hash_table_register(ta->ids, ta->cap, id);
|
||||||
|
|
||||||
Texture_Atlas_Sprite* sprite = ta->sprites + index;
|
Texture_Atlas_Sprite* sprite = ta->sprites + index;
|
||||||
sprite->min_x = min_x;
|
sprite->min_x = (u16)min_x;
|
||||||
sprite->min_y = min_y;
|
sprite->min_y = (u16)min_y;
|
||||||
sprite->max_x = max_x;
|
sprite->max_x = (u16)max_x;
|
||||||
sprite->max_y = max_y;
|
sprite->max_y = (u16)max_y;
|
||||||
|
sprite->draw_offset = draw_offset;
|
||||||
|
|
||||||
// Prepare for next registration
|
// Prepare for next registration
|
||||||
if (max_y > ta->y_used)
|
if (max_y > ta->y_used)
|
||||||
{
|
{
|
||||||
ta->y_used = max_y;
|
ta->y_used = max_y + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
ta->next_x = max_x + 1;
|
ta->next_x = max_x + 2;
|
||||||
if (ta->next_x > ta->width)
|
|
||||||
{
|
|
||||||
ta->next_x = 0;
|
|
||||||
ta->next_y = ta->y_used;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Texture_Atlas_Sprite
|
internal Texture_Atlas_Sprite
|
||||||
|
@ -105,9 +164,8 @@ texture_atlas_sprite_get(Texture_Atlas* ta, u32 id)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal v4
|
internal v4
|
||||||
texture_atlas_sprite_get_uvs(Texture_Atlas* ta, u32 id)
|
texture_atlas_sprite_get_uvs(Texture_Atlas* ta, Texture_Atlas_Sprite sprite)
|
||||||
{
|
{
|
||||||
Texture_Atlas_Sprite sprite = texture_atlas_sprite_get(ta, id);
|
|
||||||
v4 result = {};
|
v4 result = {};
|
||||||
|
|
||||||
// uv min
|
// uv min
|
||||||
|
@ -118,11 +176,13 @@ texture_atlas_sprite_get_uvs(Texture_Atlas* ta, u32 id)
|
||||||
result.z = (r32)sprite.max_x / (r32)ta->width;
|
result.z = (r32)sprite.max_x / (r32)ta->width;
|
||||||
result.w = (r32)sprite.max_y / (r32)ta->height;
|
result.w = (r32)sprite.max_y / (r32)ta->height;
|
||||||
|
|
||||||
// inset
|
|
||||||
v2 half_texel = v2{1.0f / ta->width, 1.0f / ta->height};
|
|
||||||
result.xy += half_texel;
|
|
||||||
result.zw -= half_texel;
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal v4
|
||||||
|
texture_atlas_sprite_get_uvs(Texture_Atlas* ta, u32 id)
|
||||||
|
{
|
||||||
|
Texture_Atlas_Sprite sprite = texture_atlas_sprite_get(ta, id);
|
||||||
|
return texture_atlas_sprite_get_uvs(ta, sprite);
|
||||||
|
}
|
||||||
#endif //LUMENARIUM_TEXTURE_ATLAS_CPP
|
#endif //LUMENARIUM_TEXTURE_ATLAS_CPP
|
||||||
|
|
|
@ -244,6 +244,7 @@ hash_table_find(u32* ids, u32 cap, u32 value)
|
||||||
// Vector Extensions
|
// Vector Extensions
|
||||||
|
|
||||||
#define v2_to_v3(xy,z) v3{(xy).x, (xy).y, (z)}
|
#define v2_to_v3(xy,z) v3{(xy).x, (xy).y, (z)}
|
||||||
|
#define v3_floor(v) v3{ floorf(v.x), floorf(v.y), floorf(v.z) }
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
//////////////////////////////////////////////
|
||||||
// Color Constants
|
// Color Constants
|
||||||
|
|
|
@ -26,7 +26,7 @@ void close_err_file() {}
|
||||||
|
|
||||||
// this assert works by simply trying to write to an invalid address
|
// this assert works by simply trying to write to an invalid address
|
||||||
// (in this case, 0x0), which will crash in most debuggers
|
// (in this case, 0x0), which will crash in most debuggers
|
||||||
# define assert_always (*((volatile s32*)0) = 0xFFFF)
|
# define assert_always (*((volatile int*)0) = 0xFFFF)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
WASM_EXTERN void wasm_assert_always(char* file, unsigned int file_len, unsigned int line);
|
WASM_EXTERN void wasm_assert_always(char* file, unsigned int file_len, unsigned int line);
|
||||||
|
@ -34,12 +34,13 @@ WASM_EXTERN void wasm_assert_always(char* file, unsigned int file_len, unsigned
|
||||||
#endif // defined(PLATFORM_WASM)
|
#endif // defined(PLATFORM_WASM)
|
||||||
|
|
||||||
#ifdef USE_ASSERTS
|
#ifdef USE_ASSERTS
|
||||||
# define assert(c) \
|
# define assert(c) do { \
|
||||||
if (!(c)) { \
|
if (!(c)) { \
|
||||||
err_write("Assert Hit: %s:%d\n", __FILE__, (u32)__LINE__); \
|
err_write("Assert Hit: %s:%u\n", __FILE__, (u32)__LINE__); \
|
||||||
close_err_file(); \
|
close_err_file(); \
|
||||||
assert_always; \
|
assert_always; \
|
||||||
}
|
} \
|
||||||
|
} while(false)
|
||||||
|
|
||||||
// useful for catching cases that you aren't sure you'll hit, but
|
// useful for catching cases that you aren't sure you'll hit, but
|
||||||
// want to be alerted when they happen
|
// want to be alerted when they happen
|
||||||
|
|
|
@ -101,7 +101,7 @@ struct Platform_File_Async_Job_Args
|
||||||
u32 error;
|
u32 error;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void Platform_File_Async_Cb(Platform_File_Async_Job_Args args);
|
typedef void Platform_File_Async_Cb(Platform_File_Async_Job_Args args, u8* user_data);
|
||||||
|
|
||||||
struct Platform_File_Async_Job
|
struct Platform_File_Async_Job
|
||||||
{
|
{
|
||||||
|
@ -187,9 +187,9 @@ platform_file_async_write(String path, Data data, Platform_File_Async_Cb* cb)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
platform_file_async_job_complete(Platform_File_Async_Job* job)
|
platform_file_async_job_complete(Platform_File_Async_Job* job, u8* user_data)
|
||||||
{
|
{
|
||||||
job->cb(job->args);
|
job->cb(job->args, user_data);
|
||||||
allocator_free(platform_file_jobs_arena, job->job_memory.base, job->job_memory.size);
|
allocator_free(platform_file_jobs_arena, job->job_memory.base, job->job_memory.size);
|
||||||
if (has_flag(job->args.flags, PlatformFileAsyncJob_Write))
|
if (has_flag(job->args.flags, PlatformFileAsyncJob_Write))
|
||||||
{
|
{
|
||||||
|
@ -200,7 +200,7 @@ platform_file_async_job_complete(Platform_File_Async_Job* job)
|
||||||
void platform_file_async_work_on_job(Platform_File_Async_Job* job);
|
void platform_file_async_work_on_job(Platform_File_Async_Job* job);
|
||||||
|
|
||||||
void
|
void
|
||||||
platform_file_async_jobs_do_work(u64 max_jobs)
|
platform_file_async_jobs_do_work(u64 max_jobs, u8* user_data)
|
||||||
{
|
{
|
||||||
u64 to_do = max_jobs;
|
u64 to_do = max_jobs;
|
||||||
if (max_jobs > platform_file_async_jobs_len) to_do = platform_file_async_jobs_len;
|
if (max_jobs > platform_file_async_jobs_len) to_do = platform_file_async_jobs_len;
|
||||||
|
@ -216,7 +216,7 @@ platform_file_async_jobs_do_work(u64 max_jobs)
|
||||||
platform_file_async_work_on_job(job);
|
platform_file_async_work_on_job(job);
|
||||||
if (has_flag(job->args.flags, completed))
|
if (has_flag(job->args.flags, completed))
|
||||||
{
|
{
|
||||||
platform_file_async_job_complete(job);
|
platform_file_async_job_complete(job, user_data);
|
||||||
platform_file_async_job_rem(i);
|
platform_file_async_job_rem(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,10 @@
|
||||||
|
|
||||||
#include "lumenarium_assert.h"
|
#include "lumenarium_assert.h"
|
||||||
|
|
||||||
|
#define STB_TRUETYPE_IMPLEMENTATION
|
||||||
|
#define STBTT_assert(x) assert(x)
|
||||||
|
#include "../libs/stb_truetype.h"
|
||||||
|
|
||||||
// NOTE(PS): only need the opengl extension headers
|
// NOTE(PS): only need the opengl extension headers
|
||||||
// when running on a platform that is using opengl 3.3+
|
// when running on a platform that is using opengl 3.3+
|
||||||
#if !defined(PLATFORM_wasm)
|
#if !defined(PLATFORM_wasm)
|
||||||
|
@ -21,18 +25,6 @@
|
||||||
# include "wglext.h"
|
# include "wglext.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 0
|
|
||||||
#define HMM_SINF sin
|
|
||||||
#define HMM_COSF cos
|
|
||||||
#define HMM_TANF tan
|
|
||||||
#define HMM_SQRTF sqrt
|
|
||||||
#define HMM_EXPF exp
|
|
||||||
#define HMM_LOGF log
|
|
||||||
#define HMM_ACOSF acos
|
|
||||||
#define HMM_ATANF atan
|
|
||||||
#define HMM_ATAN2F atan2
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define HANDMADE_MATH_IMPLEMENTATION
|
#define HANDMADE_MATH_IMPLEMENTATION
|
||||||
#define HANDMADE_MATH_CPP_MODE
|
#define HANDMADE_MATH_CPP_MODE
|
||||||
#define HANDMADE_MATH_STATIC
|
#define HANDMADE_MATH_STATIC
|
||||||
|
|
|
@ -206,8 +206,8 @@ platform_texture_create(u8* pixels, u32 width, u32 height, u32 stride)
|
||||||
glGenTextures(1, &result.id, sizeof(u32));
|
glGenTextures(1, &result.id, sizeof(u32));
|
||||||
glBindTexture(GL_TEXTURE_2D, result.id);
|
glBindTexture(GL_TEXTURE_2D, result.id);
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
|
|
@ -257,7 +257,7 @@ platform_texture_create(u8* pixels, u32 width, u32 height, u32 stride)
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
win32_gl_no_error();
|
win32_gl_no_error();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue