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) TextureAtlas font_create_texture_atlas(Arena* arena, String font_path)
{ {
auto font_file = file_read(arena, font_path); auto font_file = file_read(arena, font_path);
stbtt_fontinfo font_info; stbtt_fontinfo font_info;
if (!stbtt_InitFont(&font_info, font_file.pointer, stbtt_GetFontOffsetForIndex(font_file.pointer, 0))) 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(); failed_execution();
} }
int atlas_width = 1024; TextureAtlas result = {};
int atlas_height = 1024; result.character_height = 64;
int atlas_size = atlas_width * atlas_height; 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_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; u32 width;
int height; u32 height;
int x_offset; u32 x_offset;
int y_offset; u32 y_offset;
auto ch = (u8)i; 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) 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; auto bitmap_index = (height - j - 1) * width + i;
assert(atlas_index < atlas_size); assert(atlas_index < atlas_size);
atlas[atlas_index] = bitmap[bitmap_index]; result.pointer[atlas_index] = bitmap[bitmap_index];
} }
} }
stbtt_FreeBitmap(bitmap, 0); 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; x = 0;
y += char_height; y += result.character_height;
} }
} }
return (TextureAtlas) { return result;
.pointer = atlas,
.width = atlas_width,
.height = atlas_height,
.char_height = char_height,
};
} }

View File

@ -6,10 +6,26 @@
#include <GLFW/glfw3native.h> #include <GLFW/glfw3native.h>
#include <volk.h> #include <volk.h>
#include <std/virtual_buffer.h>
#include <bloat-buster/shader_compilation.h> #include <bloat-buster/shader_compilation.h>
#include <bloat-buster/image_loader.h> #include <bloat-buster/image_loader.h>
#include <bloat-buster/font.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) [[noreturn]] [[gnu::cold]] fn void wrong_vulkan_result(VkResult result, String call_string, String file, int line)
{ {
unused(result); unused(result);
@ -521,18 +537,23 @@ void run_app(Arena* arena)
#endif #endif
}; };
VkValidationFeatureEnableEXT enabled_validation_features[] =
{
VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT,
};
VkDebugUtilsMessengerCreateInfoEXT msg_ci = { VkDebugUtilsMessengerCreateInfoEXT msg_ci = {
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, .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, .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, .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, .pfnUserCallback = debug_callback,
.pUserData = 0, .pUserData = 0,
}; };
VkValidationFeatureEnableEXT enabled_validation_features[] = u8 enable_shader_debug_printf = 0;
{
// VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT,
};
VkValidationFeaturesEXT validation_features = { VkValidationFeaturesEXT validation_features = {
.sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT, .sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT,
@ -553,12 +574,12 @@ void run_app(Arena* arena)
.enabledLayerCount = array_length(layers), .enabledLayerCount = array_length(layers),
.ppEnabledExtensionNames = extensions, .ppEnabledExtensionNames = extensions,
.enabledExtensionCount = array_length(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)); vkok(vkCreateInstance(&ci, allocation_callbacks, &instance));
volkLoadInstance(instance); volkLoadInstance(instance);
VkDebugUtilsMessengerEXT messenger; VkDebugUtilsMessengerEXT messenger;
vkok(vkCreateDebugUtilsMessengerEXT(instance, &msg_ci, allocation_callbacks, &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); 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}; Vec4 color = {1, 1, 1, 1};
static_assert(sizeof(color) == 4 * sizeof(float)); 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 width_float = (f32)initial_width;
auto height_float = (f32)initial_height; auto height_float = (f32)initial_height;
Vertex vertices[4*2];
u32 indices[] = { auto string = strlit("abc");
0, 1, 2, VirtualBuffer(Vertex) vertices = {};
1, 3, 2, VirtualBuffer(u32) indices = {};
0 + 4, 1 + 4, 2 + 4, u32 index_offset = 0;
1 + 4, 3 + 4, 2 + 4 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 ch = string.pointer[i];
auto character_count_per_row = texture_atlas.width / texture_atlas.char_height; auto character_count_per_row = texture_atlas.width / texture_atlas.character_width;
auto row = c / character_count_per_row; auto row = ch / character_count_per_row;
auto column = c % character_count_per_row; auto column = ch % character_count_per_row;
auto pos_x = width_float / 2; auto pos_x = x_offset;
auto pos_y = height_float / 2; auto pos_y = y_offset;
auto uv_x = column * texture_atlas.char_height; auto uv_x = column * texture_atlas.character_width;
auto uv_y = row * texture_atlas.char_height; auto uv_y = row * texture_atlas.character_height;
vertices[0] = (Vertex) { *vb_add(&vertices, 1) = (Vertex) {
.x = pos_x, .x = pos_x,
.y = pos_y, .y = pos_y,
.uv_x = (f32)uv_x / texture_atlas.width, .uv_x = (f32)uv_x / texture_atlas.width,
.uv_y = (f32)uv_y / texture_atlas.width, .uv_y = (f32)uv_y / texture_atlas.width,
.color = color, .color = color,
}; };
vertices[1] = (Vertex) { *vb_add(&vertices, 1) = (Vertex) {
.x = pos_x + texture_atlas.char_height, .x = pos_x + texture_atlas.character_height,
.y = pos_y, .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, .uv_y = (f32)uv_y / texture_atlas.width,
.color = color, .color = color,
}; };
vertices[2] = (Vertex) { *vb_add(&vertices, 1) = (Vertex) {
.x = pos_x, .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_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, .color = color,
}; };
vertices[3] = (Vertex) { *vb_add(&vertices, 1) = (Vertex) {
.x = pos_x + texture_atlas.char_height, .x = pos_x + texture_atlas.character_height,
.y = pos_y + texture_atlas.char_height, .y = pos_y + texture_atlas.character_height,
.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.char_height) / texture_atlas.width, .uv_y = (f32)(uv_y + texture_atlas.character_height) / texture_atlas.width,
.color = color, .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;
} }
{ auto vertex_buffer_size = sizeof(*vertices.pointer) * vertices.length;
u8 c = 'b'; auto index_buffer_size = sizeof(*indices.pointer) * indices.length;
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;
vertices[4] = (Vertex) { 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);
.x = pos_x, 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);
.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);
VkBufferDeviceAddressInfo device_address_info = { VkBufferDeviceAddressInfo device_address_info = {
.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
.buffer = vertex_buffer.handle, .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); 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.pointer, vertex_buffer_size);
memcpy(staging_buffer.cpu_data, vertices, sizeof(vertices)); memcpy((u8*)staging_buffer.cpu_data + vertex_buffer_size, indices.pointer, index_buffer_size);
memcpy((u8*)staging_buffer.cpu_data + sizeof(vertices), indices, sizeof(indices));
immediate_start(immediate); immediate_start(immediate);
@ -1492,7 +1468,7 @@ strlit("/usr/share/fonts/TTF/FiraSans-Regular.ttf")
VkIndexType index_type = VK_INDEX_TYPE_UINT32; VkIndexType index_type = VK_INDEX_TYPE_UINT32;
vkCmdBindIndexBuffer(command_buffer, index_buffer.handle, index_buffer_offset, index_type); 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); vkCmdEndRendering(command_buffer);

View File

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