Text drawing minor refactor

This commit is contained in:
David Gonzalez Martin 2024-11-14 08:24:09 -06:00 committed by David
parent 8400d9f6e3
commit 4268284ede
3 changed files with 97 additions and 122 deletions

View File

@ -5,6 +5,7 @@
TextureAtlas font_create_texture_atlas(Arena* arena, String font_path)
{
auto font_file = file_read(arena, font_path);
stbtt_fontinfo font_info;
if (!stbtt_InitFont(&font_info, font_file.pointer, stbtt_GetFontOffsetForIndex(font_file.pointer, 0)))
@ -12,57 +13,55 @@ TextureAtlas font_create_texture_atlas(Arena* arena, String font_path)
failed_execution();
}
int atlas_width = 1024;
int atlas_height = 1024;
int atlas_size = atlas_width * atlas_height;
TextureAtlas result = {};
result.character_height = 64;
result.character_width = result.character_height;
result.height = 1024;
result.width = result.height;
auto atlas_size = result.width * result.height;
result.pointer = arena_allocate(arena, u8, atlas_size);
auto* atlas = arena_allocate(arena, u8, atlas_size);
int char_width = 64; // Width of each characters cell in the atlas
int char_height = 64; // Height of each characters cell in the atlas
int x = 0;
int y = 0; // Starting position in the atlas
float scale_x = 0.0f;
float scale_y = stbtt_ScaleForPixelHeight(&font_info, char_height);
float scale_y = stbtt_ScaleForPixelHeight(&font_info, result.character_height);
// Starting position in the atlas
u32 x = 0;
u32 y = 0;
u32 char_count = 256;
for (u32 i = 0; i < 256; ++i)
for (u32 i = 0; i < char_count; ++i)
{
int width;
int height;
int x_offset;
int y_offset;
u32 width;
u32 height;
u32 x_offset;
u32 y_offset;
auto ch = (u8)i;
u8* bitmap = stbtt_GetCodepointBitmap(&font_info, scale_x, scale_y, ch, &width, &height, &x_offset, &y_offset);
u8* bitmap = stbtt_GetCodepointBitmap(&font_info, scale_x, scale_y, ch, (int*)&width, (int*)&height, (int*)&x_offset, (int*)&y_offset);
if (bitmap)
{
for (int j = 0; j < height; ++j)
for (u32 j = 0; j < height; ++j)
{
for (int i = 0; i < width; ++i)
for (u32 i = 0; i < width; ++i)
{
auto atlas_index = (y + j) * atlas_width + (x + i);
auto atlas_index = (y + j) * result.width + (x + i);
auto bitmap_index = (height - j - 1) * width + i;
assert(atlas_index < atlas_size);
atlas[atlas_index] = bitmap[bitmap_index];
result.pointer[atlas_index] = bitmap[bitmap_index];
}
}
stbtt_FreeBitmap(bitmap, 0);
}
x += char_width;
x += result.character_width;
if (x + char_width > atlas_width)
if (x + result.character_width > result.width)
{
x = 0;
y += char_height;
y += result.character_height;
}
}
return (TextureAtlas) {
.pointer = atlas,
.width = atlas_width,
.height = atlas_height,
.char_height = char_height,
};
return result;
}

View File

@ -6,10 +6,26 @@
#include <GLFW/glfw3native.h>
#include <volk.h>
#include <std/virtual_buffer.h>
#include <bloat-buster/shader_compilation.h>
#include <bloat-buster/image_loader.h>
#include <bloat-buster/font.h>
STRUCT(Vec4)
{
f32 v[4];
};
STRUCT(Vertex)
{
f32 x;
f32 y;
f32 uv_x;
f32 uv_y;
Vec4 color;
};
decl_vb(Vertex);
[[noreturn]] [[gnu::cold]] fn void wrong_vulkan_result(VkResult result, String call_string, String file, int line)
{
unused(result);
@ -521,18 +537,23 @@ void run_app(Arena* arena)
#endif
};
VkValidationFeatureEnableEXT enabled_validation_features[] =
{
VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT,
};
VkDebugUtilsMessengerCreateInfoEXT msg_ci = {
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
.pNext = 0,
.flags = 0,
.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_DEVICE_ADDRESS_BINDING_BIT_EXT,
.pfnUserCallback = debug_callback,
.pUserData = 0,
};
VkValidationFeatureEnableEXT enabled_validation_features[] =
{
// VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT,
};
u8 enable_shader_debug_printf = 0;
VkValidationFeaturesEXT validation_features = {
.sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT,
@ -553,12 +574,12 @@ void run_app(Arena* arena)
.enabledLayerCount = array_length(layers),
.ppEnabledExtensionNames = extensions,
.enabledExtensionCount = array_length(extensions),
.pNext = &validation_features,
.pNext = enable_shader_debug_printf ? (const void*)&validation_features : (const void*)&msg_ci,
};
vkok(vkCreateInstance(&ci, allocation_callbacks, &instance));
volkLoadInstance(instance);
VkDebugUtilsMessengerEXT messenger;
vkok(vkCreateDebugUtilsMessengerEXT(instance, &msg_ci, allocation_callbacks, &messenger));
}
@ -1218,115 +1239,71 @@ strlit("/usr/share/fonts/TTF/FiraSans-Regular.ttf")
vkUpdateDescriptorSets(device, array_length(write_descriptor_sets), write_descriptor_sets, descriptor_copy_count, descriptor_copies);
}
STRUCT(Vec4)
{
f32 v[4];
};
Vec4 color = {1, 1, 1, 1};
static_assert(sizeof(color) == 4 * sizeof(float));
STRUCT(Vertex)
{
f32 x;
f32 y;
f32 uv_x;
f32 uv_y;
Vec4 color;
};
auto width_float = (f32)initial_width;
auto height_float = (f32)initial_height;
Vertex vertices[4*2];
u32 indices[] = {
0, 1, 2,
1, 3, 2,
0 + 4, 1 + 4, 2 + 4,
1 + 4, 3 + 4, 2 + 4
};
auto string = strlit("abc");
VirtualBuffer(Vertex) vertices = {};
VirtualBuffer(u32) indices = {};
u32 index_offset = 0;
u32 x_offset = width_float / 2;
u32 y_offset = height_float / 2;
for (u64 i = 0; i < string.length; i += 1, index_offset += 4, x_offset += texture_atlas.character_width)
{
u8 c = 'a';
auto character_count_per_row = texture_atlas.width / texture_atlas.char_height;
auto row = c / character_count_per_row;
auto column = c % character_count_per_row;
auto pos_x = width_float / 2;
auto pos_y = height_float / 2;
auto uv_x = column * texture_atlas.char_height;
auto uv_y = row * texture_atlas.char_height;
auto ch = string.pointer[i];
auto character_count_per_row = texture_atlas.width / texture_atlas.character_width;
auto row = ch / character_count_per_row;
auto column = ch % character_count_per_row;
auto pos_x = x_offset;
auto pos_y = y_offset;
auto uv_x = column * texture_atlas.character_width;
auto uv_y = row * texture_atlas.character_height;
vertices[0] = (Vertex) {
*vb_add(&vertices, 1) = (Vertex) {
.x = pos_x,
.y = pos_y,
.uv_x = (f32)uv_x / texture_atlas.width,
.uv_y = (f32)uv_y / texture_atlas.width,
.color = color,
};
vertices[1] = (Vertex) {
.x = pos_x + texture_atlas.char_height,
*vb_add(&vertices, 1) = (Vertex) {
.x = pos_x + texture_atlas.character_height,
.y = pos_y,
.uv_x = (f32)(uv_x + texture_atlas.char_height) / texture_atlas.width,
.uv_x = (f32)(uv_x + texture_atlas.character_height) / texture_atlas.width,
.uv_y = (f32)uv_y / texture_atlas.width,
.color = color,
};
vertices[2] = (Vertex) {
*vb_add(&vertices, 1) = (Vertex) {
.x = pos_x,
.y = pos_y + texture_atlas.char_height,
.y = pos_y + texture_atlas.character_height,
.uv_x = (f32)uv_x / texture_atlas.width,
.uv_y = (f32)(uv_y + texture_atlas.char_height) / texture_atlas.width,
.uv_y = (f32)(uv_y + texture_atlas.character_height) / texture_atlas.width,
.color = color,
};
vertices[3] = (Vertex) {
.x = pos_x + texture_atlas.char_height,
.y = pos_y + texture_atlas.char_height,
.uv_x = (f32)(uv_x + texture_atlas.char_height) / texture_atlas.width,
.uv_y = (f32)(uv_y + texture_atlas.char_height) / texture_atlas.width,
*vb_add(&vertices, 1) = (Vertex) {
.x = pos_x + texture_atlas.character_height,
.y = pos_y + texture_atlas.character_height,
.uv_x = (f32)(uv_x + texture_atlas.character_height) / texture_atlas.width,
.uv_y = (f32)(uv_y + texture_atlas.character_height) / texture_atlas.width,
.color = color,
};
*vb_add(&indices, 1) = index_offset + 0;
*vb_add(&indices, 1) = index_offset + 1;
*vb_add(&indices, 1) = index_offset + 2;
*vb_add(&indices, 1) = index_offset + 1;
*vb_add(&indices, 1) = index_offset + 3;
*vb_add(&indices, 1) = index_offset + 2;
}
{
u8 c = 'b';
auto character_count_per_row = texture_atlas.width / texture_atlas.char_height;
auto row = c / character_count_per_row;
auto column = c % character_count_per_row;
auto pos_x = width_float / 2 + texture_atlas.char_height;
auto pos_y = height_float / 2;
auto uv_x = column * texture_atlas.char_height;
auto uv_y = row * texture_atlas.char_height;
auto vertex_buffer_size = sizeof(*vertices.pointer) * vertices.length;
auto index_buffer_size = sizeof(*indices.pointer) * indices.length;
vertices[4] = (Vertex) {
.x = pos_x,
.y = pos_y,
.uv_x = (f32)uv_x / texture_atlas.width,
.uv_y = (f32)uv_y / texture_atlas.width,
.color = color,
};
vertices[5] = (Vertex) {
.x = pos_x + texture_atlas.char_height,
.y = pos_y,
.uv_x = (f32)(uv_x + texture_atlas.char_height) / texture_atlas.width,
.uv_y = (f32)uv_y / texture_atlas.width,
.color = color,
};
vertices[6] = (Vertex) {
.x = pos_x,
.y = pos_y + texture_atlas.char_height,
.uv_x = (f32)uv_x / texture_atlas.width,
.uv_y = (f32)(uv_y + texture_atlas.char_height) / texture_atlas.width,
.color = color,
};
vertices[7] = (Vertex) {
.x = pos_x + texture_atlas.char_height,
.y = pos_y + texture_atlas.char_height,
.uv_x = (f32)(uv_x + texture_atlas.char_height) / texture_atlas.width,
.uv_y = (f32)(uv_y + texture_atlas.char_height) / texture_atlas.width,
.color = color,
};
}
VulkanBuffer vertex_buffer = vk_buffer_create(device, allocation_callbacks, physical_device_memory_properties, sizeof(vertices), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
VulkanBuffer index_buffer = vk_buffer_create(device, allocation_callbacks, physical_device_memory_properties, sizeof(indices), VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
VulkanBuffer vertex_buffer = vk_buffer_create(device, allocation_callbacks, physical_device_memory_properties, vertex_buffer_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
VulkanBuffer index_buffer = vk_buffer_create(device, allocation_callbacks, physical_device_memory_properties, index_buffer_size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
VkBufferDeviceAddressInfo device_address_info = {
.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
.buffer = vertex_buffer.handle,
@ -1336,9 +1313,8 @@ strlit("/usr/share/fonts/TTF/FiraSans-Regular.ttf")
VulkanBuffer staging_buffer = vk_buffer_create(device, allocation_callbacks, physical_device_memory_properties, vertex_buffer.size + index_buffer.size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
{
memcpy(staging_buffer.cpu_data, vertices, sizeof(vertices));
memcpy((u8*)staging_buffer.cpu_data + sizeof(vertices), indices, sizeof(indices));
memcpy(staging_buffer.cpu_data, vertices.pointer, vertex_buffer_size);
memcpy((u8*)staging_buffer.cpu_data + vertex_buffer_size, indices.pointer, index_buffer_size);
immediate_start(immediate);
@ -1492,7 +1468,7 @@ strlit("/usr/share/fonts/TTF/FiraSans-Regular.ttf")
VkIndexType index_type = VK_INDEX_TYPE_UINT32;
vkCmdBindIndexBuffer(command_buffer, index_buffer.handle, index_buffer_offset, index_type);
vkCmdDrawIndexed(command_buffer, array_length(indices), 1, 0, 0, 0);
vkCmdDrawIndexed(command_buffer, indices.length, 1, 0, 0, 0);
vkCmdEndRendering(command_buffer);

View File

@ -13,7 +13,7 @@ STRUCT(TextureAtlas)
u32 width;
u32 height;
u32 character_width;
u32 char_height;
u32 character_height;
};
EXPORT TextureAtlas font_create_texture_atlas(Arena* arena, String font_path);