From 3a93881392d9ecb2bcb078ea788542024fd92379 Mon Sep 17 00:00:00 2001 From: kbz_8 Date: Sat, 1 Apr 2023 15:48:28 +0200 Subject: [PATCH] working textures --- includes/mlx.h | 7 +- src/core/application.cpp | 28 ++++- src/core/application.h | 12 +- src/core/bridge.cpp | 21 +++- src/platform/window.cpp | 16 ++- src/platform/window.h | 5 +- src/renderer/images/texture.cpp | 74 ++++++++++++- src/renderer/images/texture.h | 21 +++- src/renderer/images/vk_image.h | 7 +- src/renderer/pipeline/pipeline.cpp | 172 +++++++++++++++++------------ src/renderer/pixel_put.cpp | 48 ++------ src/renderer/pixel_put.h | 4 +- src/renderer/renderer.h | 6 +- src/renderer/texture_library.cpp | 47 ++++++++ src/renderer/texture_library.h | 46 ++++++++ test/42_logo.png | Bin 22507 -> 6337 bytes test/main.c | 11 +- 17 files changed, 387 insertions(+), 138 deletions(-) create mode 100644 src/renderer/texture_library.cpp create mode 100644 src/renderer/texture_library.h diff --git a/includes/mlx.h b/includes/mlx.h index 8a32edd..871f9a5 100644 --- a/includes/mlx.h +++ b/includes/mlx.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/04 16:56:35 by maldavid #+# #+# */ -/* Updated: 2023/03/31 12:35:21 by maldavid ### ########.fr */ +/* Updated: 2023/04/01 13:50:52 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -20,7 +20,7 @@ extern "C" { void* mlx_init(); void* mlx_new_window(void* mlx, int w, int h, const char* title); -int mlx_loop_hook(void* mlx, int (*f)(void*), void* param); +int mlx_loop_hook(void* mlx, int (*f)(void*), void* param); int mlx_loop(void* mlx); int mlx_loop_end(void* mlx); @@ -31,6 +31,9 @@ int mlx_mouse_get_pos(void* win_ptr, int* x, int* y); int mlx_pixel_put(void* mlx, void* win_ptr, int x, int y, int color); +int mlx_put_image_to_window(void* mlx_ptr, void* win_ptr, void* img_ptr, int x, int y); +int mlx_destroy_image(void* mlx_ptr, void* img_ptr); + void* mlx_png_file_to_image(void* mlx_ptr, char* filename, int* width, int* height); int mlx_destroy_window(void* mlx, void* win_ptr); diff --git a/src/core/application.cpp b/src/core/application.cpp index 2eeb27c..0015b9f 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -6,11 +6,12 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/04 22:10:52 by maldavid #+# #+# */ -/* Updated: 2022/12/19 00:40:17 by maldavid ### ########.fr */ +/* Updated: 2023/04/01 15:34:00 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ #include "application.h" +#include namespace mlx::core { @@ -29,4 +30,29 @@ namespace mlx::core win->endFrame(); } } + + void* Application::new_stb_texture(char* file, int* w, int* h) + { + std::shared_ptr texture = std::make_shared(stb_texture_load(file, w, h)); + TextureID id = _texture_lib.addTextureToLibrary(texture); + _texture_ids.push_back(id); + return &_texture_ids.back(); + } + + void Application::texture_put(void* win, void* img, int x, int y) + { + std::shared_ptr texture = _texture_lib.getTexture(*static_cast(img)); + _wins[*static_cast(win)]->texture_put(texture, x, y); + } + + void Application::destroy_texture(void* ptr) + { + TextureID id = *static_cast(ptr); + _texture_lib.removeTextureFromLibrary(id); + } + + Application::~Application() + { + _texture_lib.clearLibrary(); + } } diff --git a/src/core/application.h b/src/core/application.h index ef3249b..86484d6 100644 --- a/src/core/application.h +++ b/src/core/application.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/04 21:49:46 by maldavid #+# #+# */ -/* Updated: 2022/12/18 23:10:17 by maldavid ### ########.fr */ +/* Updated: 2023/04/01 14:46:14 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -23,6 +23,8 @@ #include #include +#include + namespace mlx::core { class Application @@ -46,15 +48,21 @@ namespace mlx::core inline void loop_end() noexcept { _in.finish(); } inline void pixel_put(void* win_ptr, int x, int y, int color) const noexcept { _wins[*static_cast(win_ptr)]->pixel_put(x, y, color); } + + void* new_stb_texture(char* file, int* w, int* h); // stb textures are format managed by stb image (png, jpg, bpm, ...) + void texture_put(void* win, void* img, int x, int y); + void destroy_texture(void* ptr); inline void destroy_window(void* win_ptr) { _wins[*static_cast(win_ptr)].reset(); } void run() noexcept; - ~Application() = default; + ~Application(); private: Input _in; + TextureLibrary _texture_lib; + std::vector _texture_ids; std::vector> _wins; std::function _loop_hook; void* _param = nullptr; diff --git a/src/core/bridge.cpp b/src/core/bridge.cpp index e8cd918..85ec142 100644 --- a/src/core/bridge.cpp +++ b/src/core/bridge.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/04 17:35:20 by maldavid #+# #+# */ -/* Updated: 2022/12/18 22:24:25 by maldavid ### ########.fr */ +/* Updated: 2023/04/01 15:32:57 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -58,10 +58,29 @@ extern "C" int mlx_mouse_move(void* win_ptr, int x, int y) { + return 0; } int mlx_mouse_get_pos(void* win_ptr, int* x, int* y) { + return 0; + } + + int mlx_put_image_to_window(void* mlx_ptr, void* win_ptr, void* img_ptr, int x, int y) + { + static_cast(mlx_ptr)->texture_put(win_ptr, img_ptr, x, y); + return 0; + } + + int mlx_destroy_image(void* mlx_ptr, void* img_ptr) + { + static_cast(mlx_ptr)->destroy_texture(img_ptr); + return 0; + } + + void* mlx_png_file_to_image(void* mlx_ptr, char* filename, int* width, int* height) + { + return static_cast(mlx_ptr)->new_stb_texture(filename, width, height); } int mlx_pixel_put(void* mlx, void* win_ptr, int x, int y, int color) diff --git a/src/platform/window.cpp b/src/platform/window.cpp index 8052e01..dd29fb8 100644 --- a/src/platform/window.cpp +++ b/src/platform/window.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/04 17:36:44 by maldavid #+# #+# */ -/* Updated: 2023/04/01 11:55:19 by maldavid ### ########.fr */ +/* Updated: 2023/04/01 15:40:30 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -45,6 +45,18 @@ namespace mlx _renderer->getPixelPutPipeline().setPixel(x, y, color); } + void MLX_Window::texture_put(std::shared_ptr texture, int x, int y) + { + if(texture->getSet() == VK_NULL_HANDLE) + texture->setDescriptor(_renderer->getFragDescriptorSet().duplicate()); + texture->updateSet(0); + std::vector sets; + sets.push_back(_renderer->getVertDescriptorSet().get()); + sets.push_back(texture->getSet()); + vkCmdBindDescriptorSets(_renderer->getActiveCmdBuffer().get(), VK_PIPELINE_BIND_POINT_GRAPHICS, _renderer->getPipeline().getPipelineLayout(), 0, sets.size(), sets.data(), 0, nullptr); + texture->render(*_renderer, x, y); + } + void MLX_Window::endFrame() { auto cmd_buff = _renderer->getActiveCmdBuffer().get(); @@ -54,9 +66,7 @@ namespace mlx std::vector sets; sets.push_back(_renderer->getVertDescriptorSet().get()); sets.push_back(_renderer->getPixelPutPipeline().getDescriptorSet()); - vkCmdBindDescriptorSets(cmd_buff, VK_PIPELINE_BIND_POINT_GRAPHICS, _renderer->getPipeline().getPipelineLayout(), 0, sets.size(), sets.data(), 0, nullptr); - _renderer->getPixelPutPipeline().render(*_renderer); _renderer->endFrame(); diff --git a/src/platform/window.h b/src/platform/window.h index aa8fa1b..4a675bb 100644 --- a/src/platform/window.h +++ b/src/platform/window.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/04 21:53:12 by maldavid #+# #+# */ -/* Updated: 2023/04/01 11:54:09 by maldavid ### ########.fr */ +/* Updated: 2023/04/01 15:27:51 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include namespace mlx @@ -34,6 +34,7 @@ namespace mlx void endFrame(); void pixel_put(int x, int y, int color); + void texture_put(std::shared_ptr texture, int x, int y); ~MLX_Window(); diff --git a/src/renderer/images/texture.cpp b/src/renderer/images/texture.cpp index 9f209ef..02d4b49 100644 --- a/src/renderer/images/texture.cpp +++ b/src/renderer/images/texture.cpp @@ -6,12 +6,17 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/03/31 18:03:35 by maldavid #+# #+# */ -/* Updated: 2023/03/31 18:06:26 by maldavid ### ########.fr */ +/* Updated: 2023/04/01 15:39:59 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ +#include #include #include +#include + +#define STB_IMAGE_IMPLEMENTATION +#include namespace mlx { @@ -26,10 +31,67 @@ namespace mlx Image::createImageView(VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT); Image::createSampler(); - Buffer staging_buffer; - std::size_t size = width * height * (format == VK_FORMAT_R32G32B32A32_SFLOAT ? 16 : 4); - staging_buffer.create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, pixels); - Image::copyBuffer(staging_buffer); - staging_buffer.destroy(); + std::vector vertexData = { + {{0, 0}, {1.f, 1.f, 1.f, 1.f}, {0.0f, 0.0f}}, + {{width, 0}, {1.f, 1.f, 1.f, 1.f}, {1.0f, 0.0f}}, + {{width, height}, {1.f, 1.f, 1.f, 1.f}, {1.0f, 1.0f}}, + {{0, height}, {1.f, 1.f, 1.f, 1.f}, {0.0f, 1.0f}} + }; + + std::vector indexData = { 0, 1, 2, 2, 3, 0 }; + + _vbo.create(sizeof(Vertex) * vertexData.size(), vertexData.data()); + _ibo.create(sizeof(uint16_t) * indexData.size(), indexData.data()); + + if(pixels != nullptr) + { + Buffer staging_buffer; + std::size_t size = width * height * (format == VK_FORMAT_R32G32B32A32_SFLOAT ? 16 : 4); + staging_buffer.create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, pixels); + Image::copyBuffer(staging_buffer); + staging_buffer.destroy(); + } + } + + void Texture::render(Renderer& renderer, int x, int y) + { + _vbo.bind(renderer); + _ibo.bind(renderer); + auto cmd = renderer.getActiveCmdBuffer().get(); + glm::vec2 translate(x, y); + vkCmdPushConstants(cmd, renderer.getPipeline().getPipelineLayout(), VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(translate), &translate); + vkCmdDrawIndexed(cmd, static_cast(_ibo.getSize() / sizeof(uint16_t)), 1, 0, 0, 0); + } + + void Texture::destroy() noexcept + { + Image::destroy(); + _vbo.destroy(); + _ibo.destroy(); + } + + Texture stb_texture_load(std::filesystem::path file, int* w, int* h) + { + Texture texture; + int channels; + VkFormat format; + uint8_t* data = nullptr; + std::string filename = file.string(); + + if(!std::filesystem::exists(std::move(file))) + core::error::report(e_kind::fatal_error, "Image : file not found '%s'", filename.c_str()); + if(stbi_is_hdr(filename.c_str())) + { + data = (uint8_t*)stbi_loadf(filename.c_str(), w, h, &channels, 4); + format = VK_FORMAT_R32G32B32A32_SFLOAT; + } + else + { + data = stbi_load(filename.c_str(), w, h, &channels, 4); + format = VK_FORMAT_R8G8B8A8_UNORM; + } + texture.create(data, *w, *h, format); + stbi_image_free(data); + return texture; } } diff --git a/src/renderer/images/texture.h b/src/renderer/images/texture.h index 0509426..d51e886 100644 --- a/src/renderer/images/texture.h +++ b/src/renderer/images/texture.h @@ -6,14 +6,18 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/03/08 02:24:58 by maldavid #+# #+# */ -/* Updated: 2023/03/31 18:06:09 by maldavid ### ########.fr */ +/* Updated: 2023/04/01 15:31:26 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ #ifndef __MLX_TEXTURE__ #define __MLX_TEXTURE__ +#include #include +#include +#include +#include namespace mlx { @@ -21,9 +25,24 @@ namespace mlx { public: Texture() = default; + void create(uint8_t* pixels, uint32_t width, uint32_t height, VkFormat format); + void render(class Renderer& renderer, int x, int y); + void destroy() noexcept override; + + inline void setDescriptor(DescriptorSet set) noexcept { _set = std::move(set); } + inline VkDescriptorSet getSet() noexcept { return _set.isInit() ? _set.get() : VK_NULL_HANDLE; } + inline void updateSet(int binding) noexcept { _set.writeDescriptor(binding, getImageView(), getSampler());} + ~Texture() = default; + + private: + C_VBO _vbo; + C_IBO _ibo; + DescriptorSet _set; }; + + Texture stb_texture_load(std::filesystem::path file, int* w, int* h); } #endif diff --git a/src/renderer/images/vk_image.h b/src/renderer/images/vk_image.h index 7edc8d0..bfda3d0 100644 --- a/src/renderer/images/vk_image.h +++ b/src/renderer/images/vk_image.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/01/25 11:54:21 by maldavid #+# #+# */ -/* Updated: 2023/03/31 18:04:35 by maldavid ### ########.fr */ +/* Updated: 2023/04/01 15:22:43 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -15,7 +15,7 @@ #include #include -#include +#include namespace mlx { @@ -30,7 +30,7 @@ namespace mlx void createImageView(VkImageViewType type, VkImageAspectFlags aspectFlags) noexcept; void createSampler() noexcept; void copyBuffer(class Buffer& buffer); - void destroy() noexcept; + virtual void destroy() noexcept; inline VkImage get() noexcept { return _image; } inline VkImage operator()() noexcept { return _image; } @@ -42,7 +42,6 @@ namespace mlx virtual ~Image() = default; private: - DescriptorSet _desc; VkImage _image = VK_NULL_HANDLE; VkDeviceMemory _memory = VK_NULL_HANDLE; VkImageView _image_view = VK_NULL_HANDLE; diff --git a/src/renderer/pipeline/pipeline.cpp b/src/renderer/pipeline/pipeline.cpp index 69595ba..be0a3df 100644 --- a/src/renderer/pipeline/pipeline.cpp +++ b/src/renderer/pipeline/pipeline.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/12/18 21:27:38 by maldavid #+# #+# */ -/* Updated: 2023/04/01 12:53:28 by maldavid ### ########.fr */ +/* Updated: 2023/04/01 15:21:00 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -21,19 +21,23 @@ namespace mlx #version 450 core layout(location = 0) in vec2 aPos; - layout(location = 1) in vec3 aColor; + layout(location = 1) in vec4 aColor; layout(location = 2) in vec2 aUV; layout(set=0, binding=0) uniform uProjection { mat4 mat; } uProj; + layout(push_constant) uniform uModelPushConstant { + vec2 vec; + } uTranslate; + out gl_PerVertex { vec4 gl_Position; }; layout(location = 0) out struct { - vec3 Color; + vec4 Color; vec2 UV; } Out; @@ -41,54 +45,63 @@ namespace mlx { Out.Color = aColor; Out.UV = aUV; - gl_Position = uProj.mat * vec4(aPos.x, aPos.y, 0.0, 1.0); + vec2 pos = aPos + uTranslate.vec; + gl_Position = uProj.mat * vec4(pos.x, pos.y, 0.0, 1.0); } */ const std::vector vertex_shader = { - 0x07230203,0x00010000,0x0008000b,0x00000033,0x00000000,0x00020011,0x00000001,0x0006000b, + 0x07230203,0x00010000,0x0008000b,0x0000003b,0x00000000,0x00020011,0x00000001,0x0006000b, 0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001, 0x000a000f,0x00000000,0x00000004,0x6e69616d,0x00000000,0x0000000b,0x0000000f,0x00000015, - 0x0000001c,0x00000024,0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69616d, + 0x0000001b,0x00000026,0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69616d, 0x00000000,0x00030005,0x00000009,0x00000000,0x00050006,0x00000009,0x00000000,0x6f6c6f43, 0x00000072,0x00040006,0x00000009,0x00000001,0x00005655,0x00030005,0x0000000b,0x0074754f, - 0x00040005,0x0000000f,0x6c6f4361,0x0000726f,0x00030005,0x00000015,0x00565561,0x00060005, - 0x0000001a,0x505f6c67,0x65567265,0x78657472,0x00000000,0x00060006,0x0000001a,0x00000000, - 0x505f6c67,0x7469736f,0x006e6f69,0x00030005,0x0000001c,0x00000000,0x00050005,0x0000001e, - 0x6f725075,0x7463656a,0x006e6f69,0x00040006,0x0000001e,0x00000000,0x0074616d,0x00040005, - 0x00000020,0x6f725075,0x0000006a,0x00040005,0x00000024,0x736f5061,0x00000000,0x00040047, - 0x0000000b,0x0000001e,0x00000000,0x00040047,0x0000000f,0x0000001e,0x00000001,0x00040047, - 0x00000015,0x0000001e,0x00000002,0x00050048,0x0000001a,0x00000000,0x0000000b,0x00000000, - 0x00030047,0x0000001a,0x00000002,0x00040048,0x0000001e,0x00000000,0x00000005,0x00050048, - 0x0000001e,0x00000000,0x00000023,0x00000000,0x00050048,0x0000001e,0x00000000,0x00000007, - 0x00000010,0x00030047,0x0000001e,0x00000002,0x00040047,0x00000020,0x00000022,0x00000000, - 0x00040047,0x00000020,0x00000021,0x00000000,0x00040047,0x00000024,0x0000001e,0x00000000, - 0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,0x00030016,0x00000006,0x00000020, - 0x00040017,0x00000007,0x00000006,0x00000003,0x00040017,0x00000008,0x00000006,0x00000002, - 0x0004001e,0x00000009,0x00000007,0x00000008,0x00040020,0x0000000a,0x00000003,0x00000009, - 0x0004003b,0x0000000a,0x0000000b,0x00000003,0x00040015,0x0000000c,0x00000020,0x00000001, - 0x0004002b,0x0000000c,0x0000000d,0x00000000,0x00040020,0x0000000e,0x00000001,0x00000007, - 0x0004003b,0x0000000e,0x0000000f,0x00000001,0x00040020,0x00000011,0x00000003,0x00000007, - 0x0004002b,0x0000000c,0x00000013,0x00000001,0x00040020,0x00000014,0x00000001,0x00000008, - 0x0004003b,0x00000014,0x00000015,0x00000001,0x00040020,0x00000017,0x00000003,0x00000008, - 0x00040017,0x00000019,0x00000006,0x00000004,0x0003001e,0x0000001a,0x00000019,0x00040020, - 0x0000001b,0x00000003,0x0000001a,0x0004003b,0x0000001b,0x0000001c,0x00000003,0x00040018, - 0x0000001d,0x00000019,0x00000004,0x0003001e,0x0000001e,0x0000001d,0x00040020,0x0000001f, - 0x00000002,0x0000001e,0x0004003b,0x0000001f,0x00000020,0x00000002,0x00040020,0x00000021, - 0x00000002,0x0000001d,0x0004003b,0x00000014,0x00000024,0x00000001,0x00040015,0x00000025, - 0x00000020,0x00000000,0x0004002b,0x00000025,0x00000026,0x00000000,0x00040020,0x00000027, - 0x00000001,0x00000006,0x0004002b,0x00000025,0x0000002a,0x00000001,0x0004002b,0x00000006, - 0x0000002d,0x00000000,0x0004002b,0x00000006,0x0000002e,0x3f800000,0x00040020,0x00000031, - 0x00000003,0x00000019,0x00050036,0x00000002,0x00000004,0x00000000,0x00000003,0x000200f8, - 0x00000005,0x0004003d,0x00000007,0x00000010,0x0000000f,0x00050041,0x00000011,0x00000012, - 0x0000000b,0x0000000d,0x0003003e,0x00000012,0x00000010,0x0004003d,0x00000008,0x00000016, - 0x00000015,0x00050041,0x00000017,0x00000018,0x0000000b,0x00000013,0x0003003e,0x00000018, - 0x00000016,0x00050041,0x00000021,0x00000022,0x00000020,0x0000000d,0x0004003d,0x0000001d, - 0x00000023,0x00000022,0x00050041,0x00000027,0x00000028,0x00000024,0x00000026,0x0004003d, - 0x00000006,0x00000029,0x00000028,0x00050041,0x00000027,0x0000002b,0x00000024,0x0000002a, - 0x0004003d,0x00000006,0x0000002c,0x0000002b,0x00070050,0x00000019,0x0000002f,0x00000029, - 0x0000002c,0x0000002d,0x0000002e,0x00050091,0x00000019,0x00000030,0x00000023,0x0000002f, - 0x00050041,0x00000031,0x00000032,0x0000001c,0x0000000d,0x0003003e,0x00000032,0x00000030, - 0x000100fd,0x00010038 + 0x00040005,0x0000000f,0x6c6f4361,0x0000726f,0x00030005,0x00000015,0x00565561,0x00030005, + 0x0000001a,0x00736f70,0x00040005,0x0000001b,0x736f5061,0x00000000,0x00070005,0x0000001d, + 0x646f4d75,0x75506c65,0x6f436873,0x6174736e,0x0000746e,0x00040006,0x0000001d,0x00000000, + 0x00636576,0x00050005,0x0000001f,0x61725475,0x616c736e,0x00006574,0x00060005,0x00000024, + 0x505f6c67,0x65567265,0x78657472,0x00000000,0x00060006,0x00000024,0x00000000,0x505f6c67, + 0x7469736f,0x006e6f69,0x00030005,0x00000026,0x00000000,0x00050005,0x00000028,0x6f725075, + 0x7463656a,0x006e6f69,0x00040006,0x00000028,0x00000000,0x0074616d,0x00040005,0x0000002a, + 0x6f725075,0x0000006a,0x00040047,0x0000000b,0x0000001e,0x00000000,0x00040047,0x0000000f, + 0x0000001e,0x00000001,0x00040047,0x00000015,0x0000001e,0x00000002,0x00040047,0x0000001b, + 0x0000001e,0x00000000,0x00050048,0x0000001d,0x00000000,0x00000023,0x00000000,0x00030047, + 0x0000001d,0x00000002,0x00050048,0x00000024,0x00000000,0x0000000b,0x00000000,0x00030047, + 0x00000024,0x00000002,0x00040048,0x00000028,0x00000000,0x00000005,0x00050048,0x00000028, + 0x00000000,0x00000023,0x00000000,0x00050048,0x00000028,0x00000000,0x00000007,0x00000010, + 0x00030047,0x00000028,0x00000002,0x00040047,0x0000002a,0x00000022,0x00000000,0x00040047, + 0x0000002a,0x00000021,0x00000000,0x00020013,0x00000002,0x00030021,0x00000003,0x00000002, + 0x00030016,0x00000006,0x00000020,0x00040017,0x00000007,0x00000006,0x00000004,0x00040017, + 0x00000008,0x00000006,0x00000002,0x0004001e,0x00000009,0x00000007,0x00000008,0x00040020, + 0x0000000a,0x00000003,0x00000009,0x0004003b,0x0000000a,0x0000000b,0x00000003,0x00040015, + 0x0000000c,0x00000020,0x00000001,0x0004002b,0x0000000c,0x0000000d,0x00000000,0x00040020, + 0x0000000e,0x00000001,0x00000007,0x0004003b,0x0000000e,0x0000000f,0x00000001,0x00040020, + 0x00000011,0x00000003,0x00000007,0x0004002b,0x0000000c,0x00000013,0x00000001,0x00040020, + 0x00000014,0x00000001,0x00000008,0x0004003b,0x00000014,0x00000015,0x00000001,0x00040020, + 0x00000017,0x00000003,0x00000008,0x00040020,0x00000019,0x00000007,0x00000008,0x0004003b, + 0x00000014,0x0000001b,0x00000001,0x0003001e,0x0000001d,0x00000008,0x00040020,0x0000001e, + 0x00000009,0x0000001d,0x0004003b,0x0000001e,0x0000001f,0x00000009,0x00040020,0x00000020, + 0x00000009,0x00000008,0x0003001e,0x00000024,0x00000007,0x00040020,0x00000025,0x00000003, + 0x00000024,0x0004003b,0x00000025,0x00000026,0x00000003,0x00040018,0x00000027,0x00000007, + 0x00000004,0x0003001e,0x00000028,0x00000027,0x00040020,0x00000029,0x00000002,0x00000028, + 0x0004003b,0x00000029,0x0000002a,0x00000002,0x00040020,0x0000002b,0x00000002,0x00000027, + 0x00040015,0x0000002e,0x00000020,0x00000000,0x0004002b,0x0000002e,0x0000002f,0x00000000, + 0x00040020,0x00000030,0x00000007,0x00000006,0x0004002b,0x0000002e,0x00000033,0x00000001, + 0x0004002b,0x00000006,0x00000036,0x00000000,0x0004002b,0x00000006,0x00000037,0x3f800000, + 0x00050036,0x00000002,0x00000004,0x00000000,0x00000003,0x000200f8,0x00000005,0x0004003b, + 0x00000019,0x0000001a,0x00000007,0x0004003d,0x00000007,0x00000010,0x0000000f,0x00050041, + 0x00000011,0x00000012,0x0000000b,0x0000000d,0x0003003e,0x00000012,0x00000010,0x0004003d, + 0x00000008,0x00000016,0x00000015,0x00050041,0x00000017,0x00000018,0x0000000b,0x00000013, + 0x0003003e,0x00000018,0x00000016,0x0004003d,0x00000008,0x0000001c,0x0000001b,0x00050041, + 0x00000020,0x00000021,0x0000001f,0x0000000d,0x0004003d,0x00000008,0x00000022,0x00000021, + 0x00050081,0x00000008,0x00000023,0x0000001c,0x00000022,0x0003003e,0x0000001a,0x00000023, + 0x00050041,0x0000002b,0x0000002c,0x0000002a,0x0000000d,0x0004003d,0x00000027,0x0000002d, + 0x0000002c,0x00050041,0x00000030,0x00000031,0x0000001a,0x0000002f,0x0004003d,0x00000006, + 0x00000032,0x00000031,0x00050041,0x00000030,0x00000034,0x0000001a,0x00000033,0x0004003d, + 0x00000006,0x00000035,0x00000034,0x00070050,0x00000007,0x00000038,0x00000032,0x00000035, + 0x00000036,0x00000037,0x00050091,0x00000007,0x00000039,0x0000002d,0x00000038,0x00050041, + 0x00000011,0x0000003a,0x00000026,0x0000000d,0x0003003e,0x0000003a,0x00000039,0x000100fd, + 0x00010038 }; /** @@ -99,44 +112,52 @@ namespace mlx layout(set=1, binding=0) uniform sampler2D sTexture; layout(location = 0) in struct { - vec3 Color; + vec4 Color; vec2 UV; } In; void main() { - fColor = vec4(In.Color, 1.0) * texture(sTexture, In.UV.st); + vec4 process_color = In.Color * texture(sTexture, In.UV.st); + if(process_color.w == 0) + discard; + fColor = process_color; } */ const std::vector fragment_shader = { - 0x07230203,0x00010000,0x0008000b,0x00000024,0x00000000,0x00020011,0x00000001,0x0006000b, + 0x07230203,0x00010000,0x0008000b,0x0000002c,0x00000000,0x00020011,0x00000001,0x0006000b, 0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001, - 0x0007000f,0x00000004,0x00000004,0x6e69616d,0x00000000,0x00000009,0x0000000e,0x00030010, + 0x0007000f,0x00000004,0x00000004,0x6e69616d,0x00000000,0x0000000d,0x0000002a,0x00030010, 0x00000004,0x00000007,0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69616d, - 0x00000000,0x00040005,0x00000009,0x6c6f4366,0x0000726f,0x00030005,0x0000000c,0x00000000, - 0x00050006,0x0000000c,0x00000000,0x6f6c6f43,0x00000072,0x00040006,0x0000000c,0x00000001, - 0x00005655,0x00030005,0x0000000e,0x00006e49,0x00050005,0x0000001c,0x78655473,0x65727574, - 0x00000000,0x00040047,0x00000009,0x0000001e,0x00000000,0x00040047,0x0000000e,0x0000001e, - 0x00000000,0x00040047,0x0000001c,0x00000022,0x00000001,0x00040047,0x0000001c,0x00000021, - 0x00000000,0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,0x00030016,0x00000006, - 0x00000020,0x00040017,0x00000007,0x00000006,0x00000004,0x00040020,0x00000008,0x00000003, - 0x00000007,0x0004003b,0x00000008,0x00000009,0x00000003,0x00040017,0x0000000a,0x00000006, - 0x00000003,0x00040017,0x0000000b,0x00000006,0x00000002,0x0004001e,0x0000000c,0x0000000a, - 0x0000000b,0x00040020,0x0000000d,0x00000001,0x0000000c,0x0004003b,0x0000000d,0x0000000e, - 0x00000001,0x00040015,0x0000000f,0x00000020,0x00000001,0x0004002b,0x0000000f,0x00000010, - 0x00000000,0x00040020,0x00000011,0x00000001,0x0000000a,0x0004002b,0x00000006,0x00000014, - 0x3f800000,0x00090019,0x00000019,0x00000006,0x00000001,0x00000000,0x00000000,0x00000000, - 0x00000001,0x00000000,0x0003001b,0x0000001a,0x00000019,0x00040020,0x0000001b,0x00000000, - 0x0000001a,0x0004003b,0x0000001b,0x0000001c,0x00000000,0x0004002b,0x0000000f,0x0000001e, - 0x00000001,0x00040020,0x0000001f,0x00000001,0x0000000b,0x00050036,0x00000002,0x00000004, - 0x00000000,0x00000003,0x000200f8,0x00000005,0x00050041,0x00000011,0x00000012,0x0000000e, - 0x00000010,0x0004003d,0x0000000a,0x00000013,0x00000012,0x00050051,0x00000006,0x00000015, - 0x00000013,0x00000000,0x00050051,0x00000006,0x00000016,0x00000013,0x00000001,0x00050051, - 0x00000006,0x00000017,0x00000013,0x00000002,0x00070050,0x00000007,0x00000018,0x00000015, - 0x00000016,0x00000017,0x00000014,0x0004003d,0x0000001a,0x0000001d,0x0000001c,0x00050041, - 0x0000001f,0x00000020,0x0000000e,0x0000001e,0x0004003d,0x0000000b,0x00000021,0x00000020, - 0x00050057,0x00000007,0x00000022,0x0000001d,0x00000021,0x00050085,0x00000007,0x00000023, - 0x00000018,0x00000022,0x0003003e,0x00000009,0x00000023,0x000100fd,0x00010038 + 0x00000000,0x00060005,0x00000009,0x636f7270,0x5f737365,0x6f6c6f63,0x00000072,0x00030005, + 0x0000000b,0x00000000,0x00050006,0x0000000b,0x00000000,0x6f6c6f43,0x00000072,0x00040006, + 0x0000000b,0x00000001,0x00005655,0x00030005,0x0000000d,0x00006e49,0x00050005,0x00000016, + 0x78655473,0x65727574,0x00000000,0x00040005,0x0000002a,0x6c6f4366,0x0000726f,0x00040047, + 0x0000000d,0x0000001e,0x00000000,0x00040047,0x00000016,0x00000022,0x00000001,0x00040047, + 0x00000016,0x00000021,0x00000000,0x00040047,0x0000002a,0x0000001e,0x00000000,0x00020013, + 0x00000002,0x00030021,0x00000003,0x00000002,0x00030016,0x00000006,0x00000020,0x00040017, + 0x00000007,0x00000006,0x00000004,0x00040020,0x00000008,0x00000007,0x00000007,0x00040017, + 0x0000000a,0x00000006,0x00000002,0x0004001e,0x0000000b,0x00000007,0x0000000a,0x00040020, + 0x0000000c,0x00000001,0x0000000b,0x0004003b,0x0000000c,0x0000000d,0x00000001,0x00040015, + 0x0000000e,0x00000020,0x00000001,0x0004002b,0x0000000e,0x0000000f,0x00000000,0x00040020, + 0x00000010,0x00000001,0x00000007,0x00090019,0x00000013,0x00000006,0x00000001,0x00000000, + 0x00000000,0x00000000,0x00000001,0x00000000,0x0003001b,0x00000014,0x00000013,0x00040020, + 0x00000015,0x00000000,0x00000014,0x0004003b,0x00000015,0x00000016,0x00000000,0x0004002b, + 0x0000000e,0x00000018,0x00000001,0x00040020,0x00000019,0x00000001,0x0000000a,0x00040015, + 0x0000001e,0x00000020,0x00000000,0x0004002b,0x0000001e,0x0000001f,0x00000003,0x00040020, + 0x00000020,0x00000007,0x00000006,0x0004002b,0x00000006,0x00000023,0x00000000,0x00020014, + 0x00000024,0x00040020,0x00000029,0x00000003,0x00000007,0x0004003b,0x00000029,0x0000002a, + 0x00000003,0x00050036,0x00000002,0x00000004,0x00000000,0x00000003,0x000200f8,0x00000005, + 0x0004003b,0x00000008,0x00000009,0x00000007,0x00050041,0x00000010,0x00000011,0x0000000d, + 0x0000000f,0x0004003d,0x00000007,0x00000012,0x00000011,0x0004003d,0x00000014,0x00000017, + 0x00000016,0x00050041,0x00000019,0x0000001a,0x0000000d,0x00000018,0x0004003d,0x0000000a, + 0x0000001b,0x0000001a,0x00050057,0x00000007,0x0000001c,0x00000017,0x0000001b,0x00050085, + 0x00000007,0x0000001d,0x00000012,0x0000001c,0x0003003e,0x00000009,0x0000001d,0x00050041, + 0x00000020,0x00000021,0x00000009,0x0000001f,0x0004003d,0x00000006,0x00000022,0x00000021, + 0x000500b4,0x00000024,0x00000025,0x00000022,0x00000023,0x000300f7,0x00000027,0x00000000, + 0x000400fa,0x00000025,0x00000026,0x00000027,0x000200f8,0x00000026,0x000100fc,0x000200f8, + 0x00000027,0x0004003d,0x00000007,0x0000002b,0x00000009,0x0003003e,0x0000002a,0x0000002b, + 0x000100fd,0x00010038 }; void GraphicPipeline::init(Renderer& renderer) @@ -149,6 +170,11 @@ namespace mlx if(vkCreateShaderModule(Render_Core::get().getDevice().get(), &createInfo, nullptr, &vshader) != VK_SUCCESS) core::error::report(e_kind::fatal_error, "Vulkan : failed to create a vertex shader module"); + VkPushConstantRange push_constant; + push_constant.offset = 0; + push_constant.size = sizeof(glm::vec2); + push_constant.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; createInfo.codeSize = fragment_shader.size() * sizeof(uint32_t); createInfo.pCode = fragment_shader.data(); @@ -251,6 +277,8 @@ namespace mlx pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; pipelineLayoutInfo.setLayoutCount = 2; pipelineLayoutInfo.pSetLayouts = layouts; + pipelineLayoutInfo.pushConstantRangeCount = 1; + pipelineLayoutInfo.pPushConstantRanges = &push_constant; if(vkCreatePipelineLayout(Render_Core::get().getDevice().get(), &pipelineLayoutInfo, nullptr, &_pipelineLayout) != VK_SUCCESS) core::error::report(e_kind::fatal_error, "Vulkan : failed to create a graphics pipeline layout"); diff --git a/src/renderer/pixel_put.cpp b/src/renderer/pixel_put.cpp index adc999e..155e8e5 100644 --- a/src/renderer/pixel_put.cpp +++ b/src/renderer/pixel_put.cpp @@ -6,13 +6,11 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/03/31 15:14:50 by maldavid #+# #+# */ -/* Updated: 2023/04/01 12:57:32 by maldavid ### ########.fr */ +/* Updated: 2023/04/01 15:32:23 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ -#include -#include -#include +#include #include #include @@ -20,11 +18,8 @@ namespace mlx { struct PixelPutPipeline::_Pimpl { - Image image; - C_VBO vbo; - C_IBO ibo; + Texture texture; Buffer buffer; - DescriptorSet image_set; void* map = nullptr; uint32_t width = 0; uint32_t height = 0; @@ -34,32 +29,17 @@ namespace mlx void PixelPutPipeline::init(uint32_t width, uint32_t height, Renderer& renderer) noexcept { - _impl->image.create(width, height, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - _impl->image.createImageView(VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT); - _impl->image.createSampler(); + _impl->texture.create(nullptr, width, height, VK_FORMAT_R8G8B8A8_UNORM); + _impl->texture.setDescriptor(renderer.getFragDescriptorSet().duplicate()); + _impl->buffer.create(Buffer::kind::dynamic, sizeof(uint32_t) * (width * height), VK_BUFFER_USAGE_TRANSFER_SRC_BIT); - _impl->image_set = renderer.getFragDescriptorSet().duplicate(); _impl->width = width; _impl->height = height; - - std::vector vertexData = { - {{0, 0}, {1.f, 1.f, 1.f}, {0.0f, 0.0f}}, - {{_impl->width, 0}, {1.f, 1.f, 1.f}, {1.0f, 0.0f}}, - {{_impl->width, _impl->height}, {1.f, 1.f, 1.f}, {1.0f, 1.0f}}, - {{0, _impl->height}, {1.f, 1.f, 1.0}, {0.0f, 1.0f}} - }; - - std::vector indexData = { 0, 1, 2, 2, 3, 0 }; - - _impl->vbo.create(sizeof(Vertex) * vertexData.size(), vertexData.data()); - _impl->ibo.create(sizeof(uint16_t) * indexData.size(), indexData.data()); } - VkDescriptorSet& PixelPutPipeline::getDescriptorSet() noexcept + VkDescriptorSet PixelPutPipeline::getDescriptorSet() noexcept { - return _impl->image_set.get(); + return _impl->texture.getSet(); } void PixelPutPipeline::setPixel(uint32_t x, uint32_t y, int color) noexcept @@ -77,23 +57,19 @@ namespace mlx { if(_impl->buffer.isMapped()) _impl->buffer.unmapMem(); - _impl->image.copyBuffer(_impl->buffer); - _impl->image_set.writeDescriptor(0, _impl->image.getImageView(), _impl->image.getSampler()); + _impl->texture.copyBuffer(_impl->buffer); + _impl->texture.updateSet(0); } void PixelPutPipeline::render(Renderer& renderer) noexcept { - _impl->vbo.bind(renderer); - _impl->ibo.bind(renderer); - vkCmdDrawIndexed(renderer.getActiveCmdBuffer().get(), static_cast(_impl->ibo.getSize() / sizeof(uint16_t)), 1, 0, 0, 0); + _impl->texture.render(renderer, 0, 0); } void PixelPutPipeline::destroy() noexcept { - _impl->vbo.destroy(); - _impl->ibo.destroy(); _impl->buffer.destroy(); - _impl->image.destroy(); + _impl->texture.destroy(); } PixelPutPipeline::~PixelPutPipeline() {} diff --git a/src/renderer/pixel_put.h b/src/renderer/pixel_put.h index 13a1626..54116f5 100644 --- a/src/renderer/pixel_put.h +++ b/src/renderer/pixel_put.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/03/31 13:18:50 by maldavid #+# #+# */ -/* Updated: 2023/04/01 12:10:33 by maldavid ### ########.fr */ +/* Updated: 2023/04/01 15:32:06 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -27,7 +27,7 @@ namespace mlx void setPixel(uint32_t x, uint32_t y, int color) noexcept; void present() noexcept; void render(class Renderer& renderer) noexcept; - VkDescriptorSet& getDescriptorSet() noexcept; + VkDescriptorSet getDescriptorSet() noexcept; void destroy() noexcept; diff --git a/src/renderer/renderer.h b/src/renderer/renderer.h index 786fb22..3ec159f 100644 --- a/src/renderer/renderer.h +++ b/src/renderer/renderer.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/12/18 17:14:45 by maldavid #+# #+# */ -/* Updated: 2023/03/31 17:59:09 by maldavid ### ########.fr */ +/* Updated: 2023/04/01 15:37:40 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -40,7 +40,7 @@ namespace mlx struct Vertex { glm::vec2 pos; - glm::vec3 color; + glm::vec4 color; glm::vec2 uv; static VkVertexInputBindingDescription getBindingDescription() @@ -64,7 +64,7 @@ namespace mlx attributeDescriptions[1].binding = 0; attributeDescriptions[1].location = 1; - attributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT; + attributeDescriptions[1].format = VK_FORMAT_R32G32B32A32_SFLOAT; attributeDescriptions[1].offset = offsetof(Vertex, color); attributeDescriptions[2].binding = 0; diff --git a/src/renderer/texture_library.cpp b/src/renderer/texture_library.cpp new file mode 100644 index 0000000..25589a5 --- /dev/null +++ b/src/renderer/texture_library.cpp @@ -0,0 +1,47 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* texture_library.cpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maldavid +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/04/01 14:24:00 by maldavid #+# #+# */ +/* Updated: 2023/04/01 15:32:35 by maldavid ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include +#include + +namespace mlx +{ + std::shared_ptr TextureLibrary::getTexture(TextureID id) + { + if(!_cache.count(id)) + core::error::report(e_kind::fatal_error, "Texture Library : wrong texture ID '%d'", id); + return _cache[id]; + } + + TextureID TextureLibrary::addTextureToLibrary(std::shared_ptr texture) + { + _cache[_current_id] = texture; + _current_id++; + return _current_id - 1; + } + + void TextureLibrary::removeTextureFromLibrary(TextureID id) + { + if(_cache.count(id)) + { + _cache[id]->destroy(); + _cache.erase(id); + } + } + + void TextureLibrary::clearLibrary() + { + for(auto [id, texture] : _cache) + texture->destroy(); + _cache.clear(); + } +} diff --git a/src/renderer/texture_library.h b/src/renderer/texture_library.h new file mode 100644 index 0000000..c486333 --- /dev/null +++ b/src/renderer/texture_library.h @@ -0,0 +1,46 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* texture_library.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maldavid +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/04/01 14:16:13 by maldavid #+# #+# */ +/* Updated: 2023/04/01 14:42:39 by maldavid ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef __MLX_TEXTURE_LIBRARY__ +#define __MLX_TEXTURE_LIBRARY__ + +#include +#include +#include +#include +#include + +namespace mlx +{ + using TextureID = uint32_t; + constexpr TextureID nulltexture = 0; + + class TextureLibrary + { + public: + TextureLibrary() = default; + + std::shared_ptr getTexture(TextureID id); + TextureID addTextureToLibrary(std::shared_ptr texture); + void removeTextureFromLibrary(TextureID id); + + void clearLibrary(); + + ~TextureLibrary() = default; + + private: + std::unordered_map> _cache; + TextureID _current_id = 1; + }; +} + +#endif diff --git a/test/42_logo.png b/test/42_logo.png index 833ae16f171f02adf6cf88a937e4909e6097f39f..5d2b68188f0843740c6f910ed163325031084ab9 100644 GIT binary patch delta 2754 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 XJ>S^bW)tT`<0ybX;9_5IOQ8P;GgJ*x literal 22507 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 HE?xUyDHK4d diff --git a/test/main.c b/test/main.c index 8d46ac0..640f8f7 100644 --- a/test/main.c +++ b/test/main.c @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/04 17:55:21 by maldavid #+# #+# */ -/* Updated: 2023/04/01 13:00:56 by maldavid ### ########.fr */ +/* Updated: 2023/04/01 13:49:21 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -17,6 +17,7 @@ typedef struct { void *mlx; void *win; + void *logo; } t_mlx; int update(t_mlx *mlx) @@ -24,11 +25,12 @@ int update(t_mlx *mlx) static int i = 0; int j; + mlx_put_image_to_window(mlx->mlx, mlx->win, mlx->logo, 100, 100); j = 0; while (j < 400) { - mlx_pixel_put(mlx->mlx, mlx->win, j, j, 0xFFFFFFFF); - mlx_pixel_put(mlx->mlx, mlx->win, 399 - j, j, 0xFFFFFFFF); + mlx_pixel_put(mlx->mlx, mlx->win, j, j, 0xFF0000FF); + mlx_pixel_put(mlx->mlx, mlx->win, 399 - j, j, 0xFF0000FF); j++; } i++; @@ -40,9 +42,12 @@ int update(t_mlx *mlx) int main(void) { t_mlx mlx; + int w; + int h; mlx.mlx = mlx_init(); mlx.win = mlx_new_window(mlx.mlx, 400, 400, "My window"); + mlx.logo = mlx_png_file_to_image(mlx.mlx, "42_logo.png", &w, &h); mlx_loop_hook(mlx.mlx, update, &mlx); mlx_loop(mlx.mlx); mlx_destroy_window(mlx.mlx, mlx.win);