diff --git a/Avocado_baseColor.png b/Avocado_baseColor.png deleted file mode 100644 index 38630edf..00000000 Binary files a/Avocado_baseColor.png and /dev/null differ diff --git a/graphics/src/mesh_controller.c b/graphics/src/mesh_controller.c index 17225274..2dfa9883 100644 --- a/graphics/src/mesh_controller.c +++ b/graphics/src/mesh_controller.c @@ -21,6 +21,7 @@ #include "utilities/errors_common.h" #include "utilities/file_utils.h" #include "vulkan_buffers.h" +#include "vulkan_image.h" rse_err_t mesh_create(struct graphics_context_t* context, struct vertex_t* vertices, @@ -49,7 +50,7 @@ rse_err_t mesh_create(struct graphics_context_t* context, return status; } -rse_err_t mesh_create_from_file(struct graphics_context_t* context, const char* file_name, rse_id_t* mesh_id) +rse_err_t mesh_create_from_file(struct graphics_context_t* context, const char* file_name, rse_id_t* mesh_id, rse_id_t* texture_id) { struct vertex_t* vertices = NULL; uint16_t* indices = NULL; @@ -63,7 +64,10 @@ rse_err_t mesh_create_from_file(struct graphics_context_t* context, const char* size_t* position_data_offset = NULL; size_t* color_data_offset = NULL; size_t* texture_coord_data_offset = NULL; - size_t* indices_data_offset = 0U; + size_t* indices_data_offset = NULL; + size_t* texture_data_offset = NULL; + int* texture_data_size = NULL; + unsigned char *texture_pixel_buffer = NULL; size_t data_count = 0U; size_t data_index = 0U; size_t tmp_offset = 0U; @@ -94,6 +98,15 @@ rse_err_t mesh_create_from_file(struct graphics_context_t* context, const char* rse_malloc(indices, (sizeof(uint16_t) * indices_count)); } + if (primitive->material != NULL) { + if (primitive->material->has_pbr_metallic_roughness) { + rse_malloc(texture_data_offset, sizeof(size_t)); + rse_malloc(texture_data_size, sizeof(int)); + *texture_data_offset = primitive->material->pbr_metallic_roughness.base_color_texture.texture->image->buffer_view->offset; + *texture_data_size = primitive->material->pbr_metallic_roughness.base_color_texture.texture->image->buffer_view->size; + } + } + for (attribute_index = 0; attribute_index < primitive->attributes_count; ++attribute_index) { attribute = &primitive->attributes[attribute_index]; @@ -157,6 +170,12 @@ rse_err_t mesh_create_from_file(struct graphics_context_t* context, const char* } } + if (texture_data_offset != NULL) { + rse_malloc(texture_pixel_buffer, *texture_data_size); + rse_memcpy(texture_pixel_buffer, (bin + *texture_data_offset), *texture_data_size); + STATUS_CHECK(texture_load_from_buffer(context, texture_pixel_buffer, *texture_data_size, texture_id)); + } + rse_memcpy(indices, (bin + *indices_data_offset), (sizeof(uint16_t) * indices_count)); STATUS_CHECK(mesh_create(context, vertices, indices, data_count, indices_count, mesh_id)); @@ -167,6 +186,9 @@ exit: rse_free(color_data_offset); rse_free(texture_coord_data_offset); rse_free(indices_data_offset); + rse_free(texture_data_size); + rse_free(texture_data_offset); + rse_free(texture_pixel_buffer); rse_free(vertices); rse_free(indices); cgltf_free(data); diff --git a/graphics/src/mesh_controller.h b/graphics/src/mesh_controller.h index 9f139873..5c384872 100644 --- a/graphics/src/mesh_controller.h +++ b/graphics/src/mesh_controller.h @@ -41,7 +41,7 @@ rse_err_t mesh_create(struct graphics_context_t* context, struct vertex_t* verti rse_err_t mesh_create_instance(struct graphics_context_t* context, entity_t entity, struct instance_data_t instance_data); -rse_err_t mesh_create_from_file(struct graphics_context_t* context, const char* file_name, rse_id_t* mesh_id); +rse_err_t mesh_create_from_file(struct graphics_context_t* context, const char* file_name, rse_id_t* mesh_id, rse_id_t* texture_id); /** * @brief Get the vertex count for mesh with mesh_id ID * diff --git a/graphics/src/pipeline_builder.c b/graphics/src/pipeline_builder.c index 247d14aa..9bd9d011 100644 --- a/graphics/src/pipeline_builder.c +++ b/graphics/src/pipeline_builder.c @@ -29,7 +29,7 @@ rse_err_t shader_create_module(struct graphics_context_t* context, const char* shader_path, const VkShaderStageFlagBits shader_stage) { - char* buffer; + unsigned char* buffer; size_t buffer_size; VkShaderModuleCreateInfo create_info = {0}; diff --git a/graphics/src/rse_graphics.c b/graphics/src/rse_graphics.c index 91a2f7be..856c5833 100644 --- a/graphics/src/rse_graphics.c +++ b/graphics/src/rse_graphics.c @@ -134,7 +134,6 @@ rse_err_t rse_graphics_test_function(struct graphics_context_t* context) STATUS_CHECK(texture_load_from_file(context, "../../test_image.jpg", &textures[0])); STATUS_CHECK(texture_load_from_file(context, "../../test_image_2.jpg", &textures[1])); - STATUS_CHECK(texture_load_from_file(context, "../../Avocado_baseColor.png", &textures[2])); // STATUS_CHECK(fonts_init()); // STATUS_CHECK(fonts_load_from_file(context, "../../NotoSansMono-Regular.ttf", &font_id)); @@ -183,7 +182,7 @@ rse_err_t rse_graphics_test_function(struct graphics_context_t* context) exit(1); } - mesh_create_from_file(context, "../../Avocado.glb", &avocado_id); + mesh_create_from_file(context, "../../Avocado.glb", &avocado_id, &textures[2]); if (RSE_ERROR_NO_ERROR != mesh_create_instance( context, diff --git a/graphics/src/vulkan_image.c b/graphics/src/vulkan_image.c index acbf49dd..65a487fa 100644 --- a/graphics/src/vulkan_image.c +++ b/graphics/src/vulkan_image.c @@ -16,6 +16,9 @@ #include #include +#define STB_IMAGE_IMPLEMENTATION +#include "stb/stb_image.h" + #define IMAGE_TAKEN 1U #define IMAGE_FREE 0U @@ -515,20 +518,19 @@ rse_err_t load_texture_from_bitmat(struct graphics_context_t* context, return status; } -rse_err_t texture_load_from_file(struct graphics_context_t* context, const char* file_path, rse_id_t* texture_id) +rse_err_t texture_load_from_buffer(struct graphics_context_t* context, const unsigned char* data_buffer, size_t buffer_size, rse_id_t* texture_id) { - rse_err_t status = RSE_ERROR_NO_ERROR; int width = 0; int height = 0; - size_t buffer_size = 0U; + int channels = 0; unsigned char* pixel_buffer = NULL; + rse_err_t status = RSE_ERROR_NO_ERROR; - STATUS_CHECK(file_load_pixels(file_path, NULL, &buffer_size, &width, &height)); - rse_malloc(pixel_buffer, buffer_size); - if (file_load_pixels(file_path, pixel_buffer, &buffer_size, &width, &height) != RSE_ERROR_NO_ERROR) { - status = RSE_ERROR_INTERNAL_ERROR; + pixel_buffer = stbi_load_from_memory(data_buffer, (int)buffer_size, &width, &height, &channels, STBI_rgb_alpha); + if (pixel_buffer == NULL) { + SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Failed to load image"); - goto mem_free; + return RSE_ERROR_INTERNAL_ERROR; } if (load_texture_from_bitmat(context, pixel_buffer, width, height, texture_id, VK_FORMAT_R8G8B8A8_SRGB) != RSE_ERROR_NO_ERROR) { @@ -538,8 +540,26 @@ rse_err_t texture_load_from_file(struct graphics_context_t* context, const char* } mem_free: + stbi_image_free(pixel_buffer); - rse_free(pixel_buffer); + return status; +} + +rse_err_t texture_load_from_file(struct graphics_context_t* context, const char* file_path, rse_id_t* texture_id) +{ + size_t buffer_size = 0U; + unsigned char* data_buffer = NULL; + rse_err_t status = RSE_ERROR_NO_ERROR; + + STATUS_CHECK(file_read_bytes(file_path, &buffer_size, NULL)); + rse_malloc(data_buffer, buffer_size); + STATUS_CHECK(file_read_bytes(file_path, &buffer_size, data_buffer)); + + if (texture_load_from_buffer(context, data_buffer, buffer_size, texture_id) != RSE_ERROR_NO_ERROR) { + status = RSE_ERROR_INTERNAL_ERROR; + } + + rse_free(data_buffer); return status; } diff --git a/graphics/src/vulkan_image.h b/graphics/src/vulkan_image.h index 68e2265c..052ee1c5 100644 --- a/graphics/src/vulkan_image.h +++ b/graphics/src/vulkan_image.h @@ -42,6 +42,7 @@ rse_err_t image_get_extent(struct graphics_context_t* context, VkExtent2D* exten rse_err_t load_texture_from_bitmat(struct graphics_context_t* context, const unsigned char* pixel_buffer, int width, int height, rse_id_t* texture_id, VkFormat color_format); +rse_err_t texture_load_from_buffer(struct graphics_context_t* context, const unsigned char* data_buffer, size_t buffer_size, rse_id_t* texture_id); /** * @brief Loads image from file, for later to be used as a texture * diff --git a/utilities/file_utils.h b/utilities/file_utils.h index c233f2de..210a2da3 100644 --- a/utilities/file_utils.h +++ b/utilities/file_utils.h @@ -15,12 +15,10 @@ * @param bytes_count Returned bytes count * @param buffer Returned filled buffer */ -rse_err_t file_read_bytes(const char* file_path, size_t* bytes_count, char* buffer); +rse_err_t file_read_bytes(const char* file_path, size_t* bytes_count, unsigned char* buffer); rse_err_t file_write(const char* file_name, size_t bytes_count, char* buffer); -rse_err_t file_load_pixels(const char* file_name, unsigned char* buffer, size_t* buffer_size, int* width, int* height); - rse_err_t file_append_full_path(char* file_path, size_t max_buffer_size); rse_err_t file_load_gltf(const char* file_name, cgltf_data** data); diff --git a/utilities/src/file_utils.c b/utilities/src/file_utils.c index a24a90e8..0eeff271 100644 --- a/utilities/src/file_utils.c +++ b/utilities/src/file_utils.c @@ -14,9 +14,6 @@ #include "commons.h" #include "errors_common.h" -#define STB_IMAGE_IMPLEMENTATION -#include "stb/stb_image.h" - #ifdef __linux__ #include #include @@ -119,70 +116,7 @@ rse_err_t file_append_full_path(char* file_path, size_t max_buffer_size) return ret; } -rse_err_t file_load_pixels(const char* file_name, unsigned char* buffer, size_t* buffer_size, int* width, int* height) -{ - int channels = 0; - stbi_uc* pixel_buffer = NULL; - size_t image_buffer_size = 0U; - rse_err_t ret = RSE_ERROR_NO_ERROR; - char real_path[MAX_PATH_LENGTH] = {0}; - - if (buffer_size == NULL) { - SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Provided NULL buffer_size"); - - return RSE_ERROR_INVALID_PARAM; - } - - if (width == NULL) { - SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Provided NULL width"); - - return RSE_ERROR_INVALID_PARAM; - } - - if (height == NULL) { - SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Provided NULL height"); - - return RSE_ERROR_INVALID_PARAM; - } - - strncpy(real_path, file_name, MAX_PATH_LENGTH); - if ((ret = file_append_full_path(real_path, MAX_PATH_LENGTH)) != RSE_ERROR_NO_ERROR) { - return ret; - } - - pixel_buffer = stbi_load(real_path, width, height, &channels, STBI_rgb_alpha); - - if (pixel_buffer == NULL) { - SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Failed to load texture from file: %s", file_name); - return RSE_ERROR_INTERNAL_ERROR; - } - - image_buffer_size = *width * *height * 4; // TODO: "4" is very hardcoded value. Change this - - if ((buffer != NULL) && (image_buffer_size > *buffer_size)) { - SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, - "Provided buffer is to small to hold pixel data. %ld vs %ld", - *buffer_size, - image_buffer_size); - ret = RSE_ERROR_INTERNAL_ERROR; - - goto image_free; - } - - *buffer_size = image_buffer_size; - - if (buffer != NULL) { - memset(buffer, 0, *buffer_size); - memcpy(buffer, pixel_buffer, *buffer_size); - } - -image_free: - stbi_image_free(pixel_buffer); - - return ret; -} - -rse_err_t file_read_bytes(const char* file_name, size_t* bytes_count, char* buffer) +rse_err_t file_read_bytes(const char* file_name, size_t* bytes_count, unsigned char* buffer) { rse_err_t ret = RSE_ERROR_NO_ERROR; FILE* file = NULL;