[WIP] Add render text functionality

This commit is contained in:
Piotr Krygier committed 2025-06-20 13:44:33 +02:00
1 parent c1a8b14a90
commit d59d8c640e
6 files changed
+61 -27

No files matched your search

-1
View File
@@ -54,7 +54,6 @@ uint16_t create_mesh(struct rse_vertex_t* vertices,
if(iter >= MAX_MESH_NUMBER) { if(iter >= MAX_MESH_NUMBER) {
LOGE(vulkan_messages[VULKAN_MESH_NO_FREE]); LOGE(vulkan_messages[VULKAN_MESH_NO_FREE]);
/* TODO: Add error handling */
return MAX_MESH_NUMBER; return MAX_MESH_NUMBER;
} }
+13 -11
View File
@@ -43,13 +43,13 @@ void rse_graphics_test_function(void)
LOGE("Failed to do something. Check error messages. Error: %d", status); LOGE("Failed to do something. Check error messages. Error: %d", status);
return; return;
} }
(rse_fonts_initialize()); rse_fonts_initialize();
(rse_fonts_load_from_file("/usr/share/fonts/JetBrainsMonoNerdFont/JetBrainsMonoNerdFont-Medium.ttf")); rse_fonts_load_from_file("/usr/share/fonts/JetBrainsMonoNerdFont/JetBrainsMonoNerdFont-Medium.ttf");
// FIXME: Temporary array of vertices, for testing purposes // FIXME: Temporary array of vertices, for testing purposes
struct rse_vertex_t vertices[] = {{{-0.5f, -0.5f, 0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f}}, struct rse_vertex_t vertices[] = {{{-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f}},
{{0.5f, -0.5f, 0.0f}, {1.0f, 1.0f, 1.0f}, {1.0f, 0.0f}}, {{0.5f, -0.5f, 0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
{{0.5f, 0.5f, 0.0f}, {1.0f, 1.0f, 1.0f}, {1.0f, 1.0f}}, {{0.5f, 0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
{{-0.5f, 0.5f, 0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}}}; {{-0.5f, 0.5f, 0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}}};
struct rse_vertex_t vertices2[] = {{{-0.5f, -0.5f, -0.5f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f}}, struct rse_vertex_t vertices2[] = {{{-0.5f, -0.5f, -0.5f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f}},
@@ -60,28 +60,30 @@ void rse_graphics_test_function(void)
// FIXME: Temporary array of vertices, for testing purposes // FIXME: Temporary array of vertices, for testing purposes
uint16_t indices[] = {0, 1, 2, 2, 3, 0}; uint16_t indices[] = {0, 1, 2, 2, 3, 0};
uint16_t mesh_id = create_mesh(vertices, indices, 8, 6); uint16_t mesh_id = create_mesh(vertices, indices, 6, 6);
create_mesh_instance(mesh_id, (struct rse_instance_data_t){ create_mesh_instance(mesh_id, (struct rse_instance_data_t){
{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f},
{0.0f, 0.0f, rse_math_deg_to_radians(45.0f)}, {0.0f, 0.0f, rse_math_deg_to_radians(45.0f)},
1.0f, 1.0f,
4 tex_id_2
}); });
create_mesh_instance(mesh_id, (struct rse_instance_data_t){ create_mesh_instance(mesh_id, (struct rse_instance_data_t){
{-1.0f, 0.0f, 0.3f}, {-1.0f, 0.0f, 0.3f},
{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f},
1.0f, 1.0f,
49 tex_id_2
}); });
mesh_id = create_mesh(vertices2, indices, 8, 6); mesh_id = create_mesh(vertices2, indices, 6, 6);
create_mesh_instance(mesh_id, (struct rse_instance_data_t){ create_mesh_instance(mesh_id, (struct rse_instance_data_t){
{0.0f, 1.0f, 0.0f}, {2.0f, 1.0f, 0.0f},
{0.0f, 0.0f, rse_math_deg_to_radians(0.0f)}, {0.0f, 0.0f, rse_math_deg_to_radians(0.0f)},
1.0f, 1.0f,
33 tex_id_2
}); });
rse_print_text("Ai");
} }
rse_err_t rse_graphics_run(void) rse_err_t rse_graphics_run(void)
+43 -11
View File
@@ -17,15 +17,20 @@
/* Load only ASCII characters that are needed. TODO: Add unicode characters */ /* Load only ASCII characters that are needed. TODO: Add unicode characters */
#define FONT_CHARACTERS_COUNT 94 #define FONT_CHARACTERS_COUNT 94
#define FONT_START_CHARACTER 33U
#define FONT_SIZE 200
/* Use this to scale font to 0.0 <-> 1.0 range */
#define FONT_SCALING 1.0f/FONT_SIZE
struct font_data_t { struct font_data_t {
uint16_t mesh_id; uint16_t mesh_id;
uint16_t texture_id; uint16_t texture_id;
uint16_t width; float width;
uint16_t height; float height;
uint16_t bearing_x; float bearing_x;
uint16_t bearing_y; float bearing_y;
uint16_t advance; int advance;
}; };
struct font_data_t g_fonts_data[FONT_CHARACTERS_COUNT]; struct font_data_t g_fonts_data[FONT_CHARACTERS_COUNT];
@@ -53,7 +58,7 @@ rse_err_t rse_fonts_load_from_file(const char* file_path)
FT_Face face; FT_Face face;
size_t iter = 0U; size_t iter = 0U;
struct rse_vertex_t font_vertices[4]; struct rse_vertex_t font_vertices[4];
const uint16_t font_indices[] = {0, 1, 2, 2, 3, 0}; uint16_t font_indices[] = {0, 1, 2, 2, 3, 0};
error = FT_New_Face(g_library, file_path, 0, &face); error = FT_New_Face(g_library, file_path, 0, &face);
@@ -62,8 +67,8 @@ rse_err_t rse_fonts_load_from_file(const char* file_path)
return FONT_ERROR_LOAD_FAILED; return FONT_ERROR_LOAD_FAILED;
} }
/* By default we set font size to 200px. TODO: change later? It looks OK though.. It looks OK though.... */ /* By default we set font size to FONT_SIZE.*/
error = FT_Set_Pixel_Sizes(face, 0, 200); error = FT_Set_Pixel_Sizes(face, 0, FONT_SIZE);
if (error) { if (error) {
LOGF(font_messages[FONT_CHANGE_SIZE_FAILED]); LOGF(font_messages[FONT_CHANGE_SIZE_FAILED]);
@@ -73,7 +78,7 @@ rse_err_t rse_fonts_load_from_file(const char* file_path)
/* Convert font face to textured image */ /* Convert font face to textured image */
/* Loading only needed ascii characters, from 40 (space) to 126 (~) */ /* Loading only needed ascii characters, from 40 (space) to 126 (~) */
for (iter = 0U; iter < face->num_glyphs && iter < FONT_CHARACTERS_COUNT; ++iter) { for (iter = 0U; iter < face->num_glyphs && iter < FONT_CHARACTERS_COUNT; ++iter) {
error = FT_Load_Char(face, iter + 33U, FT_LOAD_RENDER); error = FT_Load_Char(face, iter + FONT_START_CHARACTER, FT_LOAD_RENDER);
if (error) { if (error) {
LOGF(font_messages[FONT_LOAD_GLYPH_FAILED]); LOGF(font_messages[FONT_LOAD_GLYPH_FAILED]);
@@ -86,16 +91,27 @@ rse_err_t rse_fonts_load_from_file(const char* file_path)
g_fonts_data[iter].bearing_y = face->glyph->bitmap_top; g_fonts_data[iter].bearing_y = face->glyph->bitmap_top;
g_fonts_data[iter].advance = face->glyph->advance.x; g_fonts_data[iter].advance = face->glyph->advance.x;
LOGI("Width: %f, advance: %f", g_fonts_data[iter].width, g_fonts_data[iter].advance);
font_vertices[0] = (struct rse_vertex_t) { font_vertices[0] = (struct rse_vertex_t) {
{0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f} {g_fonts_data[iter].bearing_x, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f}
}; };
font_vertices[1] = (struct rse_vertex_t) { font_vertices[1] = (struct rse_vertex_t) {
{0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f} {g_fonts_data[iter].bearing_x + g_fonts_data[iter].width, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f}, {1.0f, 0.0f}
}; };
font_vertices[2] = (struct rse_vertex_t) {
{g_fonts_data[iter].bearing_x + g_fonts_data[iter].width, g_fonts_data[iter].height, 0.0f}, {1.0f, 1.0f, 1.0f}, {1.0f, 1.0f}
};
font_vertices[3] = (struct rse_vertex_t) {
{g_fonts_data[iter].bearing_x, g_fonts_data[iter].height, 0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}
};
g_fonts_data[iter].mesh_id = create_mesh(font_vertices, font_indices, 8, 6);
STATUS_CHECK(rse_load_texture_from_bitmat(face->glyph->bitmap.buffer, STATUS_CHECK(rse_load_texture_from_bitmat(face->glyph->bitmap.buffer,
face->glyph->bitmap.width, face->glyph->bitmap.width,
face->glyph->bitmap.rows, face->glyph->bitmap.rows,
&g_fonts_data[iter].texture_id, VK_FORMAT_R8_UNORM)); &g_fonts_data[iter].texture_id, VK_FORMAT_R8_UNORM));
} }
return status; return status;
} }
@@ -103,7 +119,23 @@ rse_err_t rse_fonts_load_from_file(const char* file_path)
rse_err_t rse_print_text(const char* text) rse_err_t rse_print_text(const char* text)
{ {
rse_err_t status = RSE_ERROR_NO_ERROR; rse_err_t status = RSE_ERROR_NO_ERROR;
size_t iter = 0U;
size_t charactet_code = 0U;
float advance = 0.0f;
for (iter = 0U; iter < strlen(text); ++iter) {
charactet_code = (size_t)text[iter] - FONT_START_CHARACTER;
create_mesh_instance(g_fonts_data[charactet_code].mesh_id, (struct rse_instance_data_t){
{advance, 0.0f, 0.0f},
{0.0f, 0.0f, rse_math_deg_to_radians(0.0f)},
FONT_SCALING,
g_fonts_data[charactet_code].texture_id
});
advance += (g_fonts_data[charactet_code].advance >> 6) * FONT_SCALING;
LOGI("Advance: %f", advance);
}
return status; return status;
} }
+1
View File
@@ -18,5 +18,6 @@
rse_err_t rse_fonts_initialize(void); rse_err_t rse_fonts_initialize(void);
rse_err_t rse_fonts_load_from_file(const char* file_path); rse_err_t rse_fonts_load_from_file(const char* file_path);
rse_err_t rse_print_text(const char* text);
#endif // !RSE_TEXT_RENDERER_H_ #endif // !RSE_TEXT_RENDERER_H_
+3 -3
View File
@@ -198,7 +198,7 @@ void update_uniform_buffers()
float z_near; float z_near;
float z_far; float z_far;
eye.z = 5.0f; eye.z = -5.0f;
up.y = 1.0f; up.y = 1.0f;
@@ -261,7 +261,7 @@ rse_err_t rse_add_vertices(uint16_t mesh_id,
vmaDestroyBuffer(g_vulkan_state.allocator, staging_buffer.buffer, staging_buffer.allocation); vmaDestroyBuffer(g_vulkan_state.allocator, staging_buffer.buffer, staging_buffer.allocation);
draw_indirect_command.indexCount = 6; draw_indirect_command.indexCount = vertex_data->count;
draw_indirect_command.instanceCount = 0; draw_indirect_command.instanceCount = 0;
draw_indirect_command.firstIndex = 0; draw_indirect_command.firstIndex = 0;
draw_indirect_command.vertexOffset = vertex_data->buffer_offset; draw_indirect_command.vertexOffset = vertex_data->buffer_offset;
@@ -373,7 +373,7 @@ rse_err_t record_command_buffer(uint32_t image_index)
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_vulkan_state.pipeline_layout, 0, 2, vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_vulkan_state.pipeline_layout, 0, 2,
descriptor_sets, 0, NULL); descriptor_sets, 0, NULL);
for (i = 0; i < 2; ++i) { for (i = 0; i < MAX_MESH_NUMBER; ++i) {
VkBuffer instance_buffer = {g_instance_buffers[i].buffer}; VkBuffer instance_buffer = {g_instance_buffers[i].buffer};
vkCmdBindVertexBuffers(command_buffer, 1, 1, &instance_buffer, offsets); vkCmdBindVertexBuffers(command_buffer, 1, 1, &instance_buffer, offsets);
+1 -1
View File
@@ -592,7 +592,7 @@ static void fill_rasterization_info(VkPipelineRasterizationStateCreateInfo* rast
rasterizer->rasterizerDiscardEnable = VK_FALSE; /* Disable/Enable output to framebuffer*/ rasterizer->rasterizerDiscardEnable = VK_FALSE; /* Disable/Enable output to framebuffer*/
rasterizer->polygonMode = VK_POLYGON_MODE_FILL; rasterizer->polygonMode = VK_POLYGON_MODE_FILL;
rasterizer->cullMode = VK_CULL_MODE_BACK_BIT; rasterizer->cullMode = VK_CULL_MODE_BACK_BIT;
rasterizer->frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; rasterizer->frontFace = VK_FRONT_FACE_CLOCKWISE;
rasterizer->depthBiasEnable = VK_FALSE; rasterizer->depthBiasEnable = VK_FALSE;
rasterizer->depthBiasConstantFactor = 0.0f; rasterizer->depthBiasConstantFactor = 0.0f;
rasterizer->depthBiasClamp = 0.0f; rasterizer->depthBiasClamp = 0.0f;