From a5a82709028c475d0ff6cd54f6d07f16375e156e Mon Sep 17 00:00:00 2001 From: gramanas Date: Fri, 31 May 2024 21:00:57 +0300 Subject: Allaboard --- src/render.c | 518 +++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 435 insertions(+), 83 deletions(-) (limited to 'src/render.c') diff --git a/src/render.c b/src/render.c index b6383c4..db3c168 100644 --- a/src/render.c +++ b/src/render.c @@ -1,4 +1,7 @@ + +#include #include +#include #include #include @@ -22,48 +25,25 @@ #define VKSETUP_IMPLEMENTATION #include "vksetup.h" +#define FAST_OBJ_IMPLEMENTATION +#include "../lib/fast_obj.h" + +#define CGLTF_IMPLEMENTATION +#include "../lib/cgltf.h" + //#include "cplusplus.h" -#include "vkutil.h" +//#include "vkutil.h" #include "state.h" +#define MODEL_PATH "assets/human.obj" +#define TEXTURE_PATH "assets/viking_room.png" + +void load_model_obj(); + // embedded clgm library uint32_t currentFrame = 0; state_t s; -const char *const validation_layers[] = { - "VK_LAYER_KHRONOS_validation" -}; -const uint32_t validation_layer_count = VK_ARRAY_LEN(validation_layers); - -const char *const device_extensions[] = { - VK_KHR_SWAPCHAIN_EXTENSION_NAME, -}; -const uint32_t deviceExtensionCount = VK_ARRAY_LEN(device_extensions); - - -#ifdef VKDEBUG - const bool enableValidationLayers = true; -#else - const bool enableValidationLayers = false; -#endif - -typedef struct { - float x; - float y; -} V2; - -typedef struct { - float x; - float y; - float z; -} V3; - -typedef struct { - V3 pos; - V3 color; - V2 texCoord; -} Vertex; - /* Vertex vertices[] = { */ /* (Vertex) { (V2) {-0.2f, -0.5f}, (V3) {0.0f, 1.0f, 0.0f}}, */ /* (Vertex) { (V2) {0.5f, 0.3f}, (V3) {0.0f, 0.0f, 1.0f}}, */ @@ -97,7 +77,7 @@ Vertex vertices[] = { }; const int VERTICES_SIZE = VK_ARRAY_LEN(vertices); -const uint16_t indices[] = { +const uint32_t indices[] = { 0, 1, 2, 2, 3, 0, 4, 5, 6, 6, 7, 4, 8, 5, 4 }; const int INDICES_SIZE = VK_ARRAY_LEN(indices); @@ -117,7 +97,8 @@ const int INDICES_SIZE = VK_ARRAY_LEN(indices); /* }; */ /* const int INDICES_SIZE = VK_ARRAY_LEN(indices); */ -static int resizing_event_watcher(void* data, SDL_Event* event) { +static int resizing_event_watcher(void *data, SDL_Event *event) { + (void) data; if (event->type == SDL_WINDOWEVENT && event->window.event == SDL_WINDOWEVENT_RESIZED) { s.sdl_window_resized = 1; @@ -180,6 +161,9 @@ debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData) { + (void) messageSeverity; + (void) messageType; + (void) pUserData; vk_log(VK_ERROR, "validation layer: %s\n", pCallbackData->pMessage); return VK_FALSE; } @@ -527,7 +511,6 @@ void mouseCallback(SDL_Event *event) { if (event->type != SDL_MOUSEMOTION) return; - if (!s.mouse_pressed) return; float xoffset = event->motion.xrel; float yoffset = -event->motion.yrel; // Reversed since y-coordinates range from bottom to top @@ -535,7 +518,20 @@ mouseCallback(SDL_Event *event) xoffset *= sensitivity; yoffset *= sensitivity; - update_camera(xoffset, yoffset); + if (s.mouse_pressed) { + update_camera(xoffset, yoffset); + } else if (s.middle_click) { + vec4 _up = {0, 1, 0, 0}; + vec4 _right = {1, 0, 0, 0}; + + vec4 up, right; + glm_mat4_mulv(s.ubo.model, _up, up); + glm_mat4_mulv(s.ubo.model, _right, right); + + glm_rotate(s.ubo.model, glm_rad(xoffset * glm_rad(90.0f)), GLM_ZUP); + glm_rotate(s.ubo.model, glm_rad(yoffset * glm_rad(90.0f)), GLM_XUP); + } + return; } void @@ -612,7 +608,7 @@ vulkan_create_swap_chain() VkImageView -create_image_view(VkImage image, VkFormat format, VkImageAspectFlags aspectFlags) +create_image_view(VkImage image, VkFormat format, VkImageAspectFlags aspectFlags, uint32_t mipLevels) { VkImageViewCreateInfo viewInfo = {0}; viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; @@ -621,7 +617,7 @@ create_image_view(VkImage image, VkFormat format, VkImageAspectFlags aspectFlags viewInfo.format = format; viewInfo.subresourceRange.aspectMask = aspectFlags; viewInfo.subresourceRange.baseMipLevel = 0; - viewInfo.subresourceRange.levelCount = 1; + viewInfo.subresourceRange.levelCount = mipLevels; viewInfo.subresourceRange.baseArrayLayer = 0; viewInfo.subresourceRange.layerCount = 1; @@ -635,7 +631,7 @@ void vulkan_create_image_views() { for (size_t i = 0; i < s.vk_swap_chain_image_count; i++) { - s.vk_swap_chain_image_views[i] = create_image_view(s.vk_swap_chain_images[i], s.vk_swap_chain_image_format, VK_IMAGE_ASPECT_COLOR_BIT); + s.vk_swap_chain_image_views[i] = create_image_view(s.vk_swap_chain_images[i], s.vk_swap_chain_image_format, VK_IMAGE_ASPECT_COLOR_BIT, 1); } vk_log(VK_INFO, "Vulkan image views created!\n"); } @@ -725,7 +721,7 @@ findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) } void -createImage(uint32_t width, uint32_t height, VkFormat format, +createImage(uint32_t width, uint32_t height, uint32_t mipLevels, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage *image, VkDeviceMemory *imageMemory) @@ -736,7 +732,7 @@ createImage(uint32_t width, uint32_t height, VkFormat format, imageInfo.extent.width = width; imageInfo.extent.height = height; imageInfo.extent.depth = 1; - imageInfo.mipLevels = 1; + imageInfo.mipLevels = mipLevels; imageInfo.arrayLayers = 1; imageInfo.format = format; imageInfo.tiling = tiling; @@ -807,7 +803,7 @@ void transitionImageLayout(VkImage image, VkFormat format, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, - VkImageLayout oldLayout, VkImageLayout newLayout) + VkImageLayout oldLayout, VkImageLayout newLayout, uint32_t mipLevels) { VkCommandBuffer commandBuffer = beginSingleTimeCommands(); @@ -833,7 +829,7 @@ transitionImageLayout(VkImage image, VkFormat format, } barrier.subresourceRange.baseMipLevel = 0; - barrier.subresourceRange.levelCount = 1; + barrier.subresourceRange.levelCount = mipLevels; barrier.subresourceRange.baseArrayLayer = 0; barrier.subresourceRange.layerCount = 1; @@ -880,18 +876,18 @@ void vulkan_create_depth_resources() { VkFormat depthFormat = findDepthFormat(); - createImage(s.vk_swap_chain_extent.width, s.vk_swap_chain_extent.height, + createImage(s.vk_swap_chain_extent.width, s.vk_swap_chain_extent.height, 1, depthFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &s.vk_depth_image, &s.vk_depth_image_memory); s.vk_depth_image_view = create_image_view(s.vk_depth_image, depthFormat, - VK_IMAGE_ASPECT_DEPTH_BIT); + VK_IMAGE_ASPECT_DEPTH_BIT, 1); transitionImageLayout(s.vk_depth_image, depthFormat, VK_ACCESS_NONE, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 1); } void @@ -1013,7 +1009,7 @@ vulkan_create_graphics_pipeline(VkPolygonMode polygon_mode) rasterizer.lineWidth = 1.0f; rasterizer.cullMode = VK_CULL_MODE_NONE; //rasterizer.cullMode = VK_CULL_MODE_BACK_BIT; - //rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; rasterizer.depthBiasEnable = VK_FALSE; rasterizer.depthBiasConstantFactor = 0.0f; // Optional rasterizer.depthBiasClamp = 0.0f; // Optional @@ -1159,7 +1155,7 @@ recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) s.vk_swap_chain_images[imageIndex], VK_FORMAT_R8G8B8A8_SRGB, 0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1); VkRenderingAttachmentInfo colorAttachment = {0}; colorAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO; @@ -1168,7 +1164,7 @@ recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; colorAttachment.clearValue.color = - (VkClearColorValue){0.0f, 0.0f, 0.0f, 1.0f}; + (VkClearColorValue){{0.0f, 0.0f, 0.0f, 1.0f}}; VkRenderingAttachmentInfo depthAttachment = {0}; depthAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO; @@ -1210,13 +1206,13 @@ recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) VkDeviceSize offsets[] = {0}; vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets); vkCmdBindIndexBuffer(commandBuffer, s.vk_index_buffer, 0, - VK_INDEX_TYPE_UINT16); + VK_INDEX_TYPE_UINT32); vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, s.vk_pipeline_layout, 0, 1, &s.frames[currentFrame].vk_descriptor_set, 0, NULL); - vkCmdDrawIndexed(commandBuffer, INDICES_SIZE, 1, 0, 0, 0); + vkCmdDrawIndexed(commandBuffer, s.indices_count, 1, 0, 0, 0); vkCmdEndRendering(commandBuffer); transitionImageLayout(s.vk_swap_chain_images[imageIndex], @@ -1225,7 +1221,7 @@ recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, 1); VK_CHECK(vkEndCommandBuffer(commandBuffer)); } @@ -1288,7 +1284,8 @@ void copy_buffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) { void vulkan_create_vertex_buffer() { - VkDeviceSize bufferSize = sizeof(vertices[0]) * VERTICES_SIZE; + VkDeviceSize bufferSize = sizeof(s.vertices[0]) * s.vertices_count; + /* VkDeviceSize bufferSize = sizeof(vertices[0]) * VERTICES_SIZE; */ VkBuffer stagingBuffer; VkDeviceMemory stagingBufferMemory; @@ -1300,7 +1297,8 @@ vulkan_create_vertex_buffer() void* data; VK_CHECK(vkMapMemory(s.vk_device, stagingBufferMemory, 0, bufferSize, 0, &data)); - memcpy(data, vertices, (size_t) bufferSize); + // memcpy(data, vertices, (size_t) bufferSize); + memcpy(data, s.vertices, (size_t) bufferSize); vkUnmapMemory(s.vk_device, stagingBufferMemory); createBuffer(bufferSize, @@ -1317,7 +1315,8 @@ vulkan_create_vertex_buffer() void vulkan_create_index_buffer() { - VkDeviceSize bufferSize = sizeof(indices[0]) * INDICES_SIZE; + VkDeviceSize bufferSize = sizeof(s.indices[0]) * s.indices_count; + /* VkDeviceSize bufferSize = sizeof(indices[0]) * INDICES_SIZE; */ VkBuffer stagingBuffer; VkDeviceMemory stagingBufferMemory; @@ -1329,7 +1328,8 @@ vulkan_create_index_buffer() void* data; VK_CHECK(vkMapMemory(s.vk_device, stagingBufferMemory, 0, bufferSize, 0, &data)); - memcpy(data, indices, (size_t) bufferSize); + memcpy(data, s.indices, (size_t) bufferSize); + /* memcpy(data, indices, (size_t) bufferSize); */ vkUnmapMemory(s.vk_device, stagingBufferMemory); createBuffer(bufferSize, @@ -1544,6 +1544,25 @@ handle_input(bool * quit) case SDLK_l: s.rotate = s.rotate ? 0 : 1; break; + case SDLK_m: + vkDeviceWaitIdle(s.vk_device); + free(s.vertices); + free(s.indices); + if (!strcmp(s.model_path, "assets/human.obj")) + strcpy(s.model_path, "assets/viking_room.obj"); + else if (!strcmp(s.model_path, "assets/viking_room.obj")) + strcpy(s.model_path, "assets/test.obj"); + else + strcpy(s.model_path, "assets/human.obj"); + load_model_obj(); + vkDestroyBuffer(s.vk_device, s.vk_vertex_buffer, NULL); + vkFreeMemory(s.vk_device, s.vk_vertex_buffer_memory, NULL); + + vkDestroyBuffer(s.vk_device, s.vk_index_buffer, NULL); + vkFreeMemory(s.vk_device, s.vk_index_buffer_memory, NULL); + vulkan_create_vertex_buffer(); + vulkan_create_index_buffer(); + break; case SDLK_r: s.camera.pos[0] = 1.0f; s.camera.pos[1] = 1.0f; @@ -1562,6 +1581,10 @@ handle_input(bool * quit) s.camera.lastX = 400.0f; s.camera.lastY = 300.0f; s.camera.fov = 45.0f; + + glm_mat4_identity(s.ubo.model); + + s.zoom = 10; update_camera(0,0); break; } @@ -1569,19 +1592,28 @@ handle_input(bool * quit) else if (e.type == SDL_MOUSEWHEEL) { if(e.wheel.y > 0) // scroll up { - s.zoom += 1; + s.zoom -= 1; } else if(e.wheel.y < 0) // scroll down { - s.zoom -= 1; + s.zoom += 1; if (s.zoom == -100) s.zoom = 1; } } else if (e.type == SDL_MOUSEBUTTONDOWN) { - s.mouse_pressed = 1; + if (e.button.button != 2) { + s.mouse_pressed = 1; + } else { + s.middle_click = 1; + } + } else if (e.type == SDL_MOUSEBUTTONUP) { - s.mouse_pressed = 0; + if (e.button.button != 2) { + s.mouse_pressed = 0; + } else { + s.middle_click = 0; + } } mouseCallback(&e); } @@ -1617,13 +1649,88 @@ copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, endSingleTimeCommands(commandBuffer); } +void generateMipmaps(VkImage image, VkFormat imageFormat, int32_t texWidth, int32_t texHeight, uint32_t mipLevels) { + VkCommandBuffer commandBuffer = beginSingleTimeCommands(); + + VkImageMemoryBarrier barrier = {0}; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.image = image; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = 1; + barrier.subresourceRange.levelCount = 1; + + int32_t mipWidth = texWidth; + int32_t mipHeight = texHeight; + + for (uint32_t i = 1; i < mipLevels; i++) { + barrier.subresourceRange.baseMipLevel = i - 1; + barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, + &barrier); + + VkImageBlit blit = {0}; + blit.srcOffsets[0] = (VkOffset3D){ 0, 0, 0 }; + blit.srcOffsets[1] = (VkOffset3D){ mipWidth, mipHeight, 1 }; + blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + blit.srcSubresource.mipLevel = i - 1; + blit.srcSubresource.baseArrayLayer = 0; + blit.srcSubresource.layerCount = 1; + blit.dstOffsets[0] = (VkOffset3D){ 0, 0, 0 }; + blit.dstOffsets[1] = (VkOffset3D){ mipWidth > 1 ? mipWidth / 2 : 1, mipHeight > 1 ? mipHeight / 2 : 1, 1 }; + blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + blit.dstSubresource.mipLevel = i; + blit.dstSubresource.baseArrayLayer = 0; + blit.dstSubresource.layerCount = 1; + + vkCmdBlitImage(commandBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, + VK_FILTER_LINEAR); + + barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, + NULL, 1, &barrier); + + if (mipWidth > 1) mipWidth /= 2; + if (mipHeight > 1) mipHeight /= 2; + } + + /* barrier.subresourceRange.baseMipLevel = mipLevels - 1; */ + /* barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; */ + /* barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; */ + /* barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; */ + /* barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; */ + + /* vkCmdPipelineBarrier(commandBuffer, */ + /* VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, */ + /* 0, NULL, */ + /* 0, NULL, */ + /* 1, &barrier); */ + + endSingleTimeCommands(commandBuffer); +} + void vulkan_create_texture_image() { int texWidth, texHeight, texChannels; - stbi_uc* pixels = stbi_load("assets/texture.jpg", &texWidth, &texHeight, &texChannels, STBI_rgb_alpha); + stbi_uc* pixels = stbi_load(TEXTURE_PATH, &texWidth, &texHeight, &texChannels, STBI_rgb_alpha); VkDeviceSize imageSize = texWidth * texHeight * 4; + s.vk_mip_levels = (uint32_t)floor(log2(fmax(texWidth, texHeight))) + 1; + if (!pixels) { vk_log(VK_ERROR, "failed to load texture image!\n"); } @@ -1639,9 +1746,9 @@ vulkan_create_texture_image() stbi_image_free(pixels); - createImage(texWidth, texHeight, VK_FORMAT_R8G8B8A8_SRGB, + createImage(texWidth, texHeight, s.vk_mip_levels, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &s.vk_texture_image, &s.vk_texture_image_memory); @@ -1649,15 +1756,16 @@ vulkan_create_texture_image() s.vk_texture_image, VK_FORMAT_R8G8B8A8_SRGB, 0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, s.vk_mip_levels); copyBufferToImage(stagingBuffer, s.vk_texture_image, (uint32_t)texWidth, (uint32_t)texHeight); + generateMipmaps(s.vk_texture_image, VK_FORMAT_R8G8B8A8_SRGB, texWidth, texHeight, s.vk_mip_levels); transitionImageLayout( s.vk_texture_image, VK_FORMAT_R8G8B8A8_SRGB, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, s.vk_mip_levels); vkDestroyBuffer(s.vk_device, stagingBuffer, NULL); vkFreeMemory(s.vk_device, stagingBufferMemory, NULL); @@ -1666,7 +1774,7 @@ vulkan_create_texture_image() void vulkan_create_texture_image_view() { - s.vk_texture_image_view = create_image_view(s.vk_texture_image, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT); + s.vk_texture_image_view = create_image_view(s.vk_texture_image, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT, s.vk_mip_levels); } void vulkan_create_texture_sampler() { @@ -1690,11 +1798,234 @@ void vulkan_create_texture_sampler() { samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; samplerInfo.mipLodBias = 0.0f; samplerInfo.minLod = 0.0f; - samplerInfo.maxLod = 0.0f; + samplerInfo.maxLod = VK_LOD_CLAMP_NONE; VK_CHECK(vkCreateSampler(s.vk_device, &samplerInfo, NULL, &s.vk_texture_sampler)); } +void +load_model_obj() +{ + fastObjMesh *m = fast_obj_read(s.model_path); + + if (!m) { + vk_log(VK_ERROR, "Can't load object\n"); + } + + s.indices_count = m->index_count; + s.indices = (uint32_t *)malloc(s.indices_count * sizeof(uint32_t)); + s.vertices_count = 0; + + if (m->group_count > 1) { + vk_log(VK_WARN, "fast_obj Mesh with groups > 1 not supported."); + } + + /* + Since blender exports objs indexed we use those same indices for our + indexed draw call. + */ + + /* Count indexs and vertices */ + size_t c = 0; + for (size_t ii = 0; ii < m->group_count; ii++) { + const fastObjGroup *grp = &m->groups[ii]; + for (unsigned int jj = 0; jj < grp->face_count; jj++) { + unsigned int fv = m->face_vertices[grp->face_offset + jj]; + for (unsigned int kk = 0; kk < fv; kk++) { + /* position index */ + uint32_t mip = m->indices[grp->index_offset + c].p - 1; /* make index start from zero */ + + /* flag if we've seen the index*/ + int index_seen = 0; + for (size_t i = 0; i < c; i++) { + if (mip == s.indices[i]) { + index_seen = 1; + break; + } + } + s.indices[c] = mip; + if (!index_seen) { + /* If not seen, incremet vertices */ + s.vertices_count++; + } + c++; + } + } + } + + printf("vertex count %ld!!!!!!!!!!!!!!!!!!\n", s.vertices_count); + s.vertices = (Vertex *)malloc(s.vertices_count * sizeof(Vertex)); + + /* for (size_t i = 0; i < s.indices_count; i++) { */ + /* uint32_t mip = s.indices[i]; */ + /* int index_seen = 0; */ + /* for (size_t j = 0; j < i; j++) { */ + /* if (mip == s.indices[j]) { */ + /* index_seen = 1; */ + /* break; */ + /* } */ + /* } */ + /* if (!index_seen) { */ + /* s.vertices[mip].pos.x = m->positions[3 * (mip + 1) + 0]; */ + /* s.vertices[mip].pos.y = m->positions[3 * (mip + 1) + 1]; */ + /* s.vertices[mip].pos.z = m->positions[3 * (mip + 1) + 2]; */ + /* } */ + /* } */ + + for (size_t ii = 0; ii < m->group_count; ii++) { + const fastObjGroup *grp = &m->groups[ii]; + size_t idx = 0; + for (unsigned int jj = 0; jj < grp->face_count; jj++) { + unsigned int fv = m->face_vertices[grp->face_offset + jj]; + for (unsigned int kk = 0; kk < fv; kk++) { + fastObjIndex mi = m->indices[grp->index_offset + idx]; + + int flag = 0; + for (size_t i = 0; i < idx; i++) { + /* if it exists */ + if (mi.p - 1 == s.indices[i]) { + flag = 1; + break; + } + } + if (!flag) { + int index = mi.p - 1; /* zero indexed */ + if (mi.p) { + s.vertices[index].pos.x = m->positions[3 * mi.p + 0]; + s.vertices[index].pos.y = m->positions[3 * mi.p + 1]; + s.vertices[index].pos.z = m->positions[3 * mi.p + 2]; + } + if (mi.t) { + s.vertices[index].texCoord.x = m->texcoords[2 * mi.t + 0]; + s.vertices[index].texCoord.y = 1.0f - m->texcoords[2 * mi.t + 1]; + } + if (mi.n) { + s.vertices[index].color.x = m->normals[3 * mi.n + 0]; + s.vertices[index].color.y = m->normals[3 * mi.n + 1]; + s.vertices[index].color.z = m->normals[3 * mi.n + 2]; + } + } + idx++; + } + } + } + + fast_obj_destroy(m); +} + +void load_model_gltf() { + // TODO maybe copy the raylib implemenetation + /* + RESTRICTIONS: + - Only triangle meshes supported + - Vertex attribute types and formats supported: + > Vertices (position): vec3: float + > Normals: vec3: float + > Texcoords: vec2: float + > Colors: vec4: u8, u16, f32 (normalized) + > Indices: u16, u32 (truncated to u16) + - Node hierarchies or transforms not supported + */ + + /* cgltf_options options; */ + /* memset(&options, 0, sizeof(cgltf_options)); */ + /* cgltf_data* data = NULL; */ + /* cgltf_result result = cgltf_parse_file(&options, MODEL_PATH, &data); */ + + /* if (result == cgltf_result_success) */ + /* result = cgltf_load_buffers(&options, data, MODEL_PATH); */ + + /* if (result == cgltf_result_success) */ + /* result = cgltf_validate(data); */ + + /* if (data->meshes_count < 1) { */ + /* cgltf_free(data); */ + /* return; */ + /* } */ + + /* int idx = 0; */ + /* int meshIndex = 0; */ + /* for (unsigned int i = 0, meshIndex = 0; i < data->meshes_count; i++) { */ + /* for (unsigned int p = 0; p < data->meshes[i].primitives_count; p++) { */ + /* // NOTE: We only support primitives defined by triangles */ + /* // Other alternatives: points, lines, line_strip, triangle_strip */ + /* if (data->meshes[i].primitives[p].type != cgltf_primitive_type_triangles) continue; */ + + /* // NOTE: Attributes data could be provided in several data formats (8, 8u, 16u, 32...), */ + /* // Only some formats for each attribute type are supported, read info at the top of this function! */ + + /* for (unsigned int j = 0; j < data->meshes[i].primitives[p].attributes_count; j++) { */ + /* // Check the different attributes for every primitive */ + /* if (data->meshes[i].primitives[p].attributes[j].type == cgltf_attribute_type_position) { // POSITION, vec3, float */ + /* cgltf_accessor *attribute = data->meshes[i].primitives[p].attributes[j].data; */ + + /* // WARNING: SPECS: POSITION accessor MUST have its min and max properties defined */ + + /* if ((attribute->type == cgltf_type_vec3) && (attribute->component_type == cgltf_component_type_r_32f)) { */ + /* // Init raylib mesh vertices to copy glTF attribute data */ + /* s.vertices_count = attribute->count / 3; */ + /* s.vertices = calloc(attribute->count, attribute->count*sizeof(Vertex)); */ + + /* size_t float_count = cgltf_accessor_unpack_floats(attribute, NULL, 0); */ + /* printf("This many floats: %ld\n", float_count); */ + /* float floats[float_count] = {}; */ + /* cgltf_accessor_unpack_floats(attribute, floats, float_count); */ + + /* for (unsigned int k = 0; k < attribute->count + 3; k+=3) { */ + /* s.vertices[idx].pos.x = floats[k + 0]; */ + /* s.vertices[idx].pos.y = floats[k + 1]; */ + /* s.vertices[idx].pos.z = floats[k + 2]; */ + /* //s.indices[idx] = idx; */ + /* idx++; */ + /* } */ + /* // Load 3 components of float data type into mesh.vertices */ + /* } */ + /* } */ + /* } */ + /* if (data->meshes[i].primitives[p].indices != NULL) { */ + /* printf("THERE ARE INDIXCES!!!\n"); */ + /* cgltf_accessor *attribute = data->meshes[i].primitives[p].indices; */ + + /* s.indices_count = attribute->count / 3; */ + /* s.indices = calloc(attribute->count, attribute->count*sizeof(uint32_t)); */ + + /* if (attribute->component_type == cgltf_component_type_r_16u) { */ + /* size_t float_count = cgltf_accessor_unpack_indices(attribute, NULL, 0, 0); */ + /* printf("This many floats: %ld\n", float_count); */ + /* uint16_t floats[float_count] = {}; */ + /* cgltf_accessor_unpack_indices(attribute, floats, float_count, */ + /* float_count); */ + + /* for (int x = 0; x < float_count; x++) { */ + /* printf("%d \n", floats[x]); */ + /* } */ + + /* } */ + /* else if (attribute->component_type == cgltf_component_type_r_32u) { */ + /* printf("ASDASDASDAS2222222!\n"); */ + /* // Init raylib mesh indices to copy glTF attribute data */ + /* /\* model.meshes[meshIndex].indices = RL_MALLOC(attribute->count*sizeof(unsigned short)); *\/ */ + + /* /\* // Load data into a temp buffer to be converted to raylib data type *\/ */ + /* /\* unsigned int *temp = malloc(attribute->count*sizeof(unsigned int)); *\/ */ + /* /\* LOAD_ATTRIBUTE(attribute, 1, unsigned int, temp); *\/ */ + + /* /\* // Convert data to raylib indices data type (unsigned short) *\/ */ + /* /\* for (unsigned int d = 0; d < attribute->count; d++) model.meshes[meshIndex].indices[d] = (unsigned short)temp[d]; *\/ */ + + /* //free(temp); */ + /* } */ + /* } */ + /* } */ + /* } */ + + /* for (int i = 0; i < s.vertices_count; i++) { */ + /* printf("%d: %f %f %f\n",i, s.vertices[i].pos.x, s.vertices[i].pos.y, s.vertices[i].pos.z); */ + /* } */ + + /* cgltf_free(data); */ +} + void init_vulkan() { @@ -1704,8 +2035,8 @@ init_vulkan() //vulkan_create_instance(); s.vk_instance = - vksetup_create_instance(enableValidationLayers, validation_layers, - validation_layer_count, s.sdl_window); + vks_create_instance(enableValidationLayers, validation_layers, + validation_layer_count, s.sdl_window); // vulkan_setup_debug_messenger(); vulkan_create_surface(); vulkan_pick_physical_device(); @@ -1719,6 +2050,8 @@ init_vulkan() vulkan_create_texture_image(); vulkan_create_texture_image_view(); vulkan_create_texture_sampler(); + load_model_obj(); + //load_model_gltf(); vulkan_create_vertex_buffer(); vulkan_create_index_buffer(); vulkan_create_uniform_buffers(); @@ -1777,6 +2110,9 @@ close_vulkan() if (s.prev_frag_result) { shaderc_result_release(s.prev_frag_result); } + + free(s.vertices); + free(s.indices); } float @@ -1798,24 +2134,28 @@ current_time() } void -updateUniformBuffer(uint32_t currentImage) +updateUniformBuffer(uint32_t currentImage, float dt) { - float time = current_time(); - UniformBufferObject ubo = {0}; + ubo.time = current_time(); + ubo.dt = dt; + ubo.resolution[0] = s.vk_swap_chain_extent.width; ubo.resolution[1] = s.vk_swap_chain_extent.height; - glm_mat4_identity(ubo.model); + //glm_mat4_identity(ubo.model); + glm_mat4_dup(s.ubo.model, ubo.model); + + if (s.rotate) + glm_rotate(ubo.model, glm_rad(30 * dt * glm_rad(90.0f)), GLM_ZUP); - if (!s.rotate) - glm_rotate(ubo.model, glm_rad(50 * time * glm_rad(90.0f)), GLM_ZUP); + glm_mat4_dup(ubo.model, s.ubo.model); - vec3 eye = GLM_VEC3_ONE_INIT; - vec3 center = GLM_VEC3_ZERO_INIT; + /* vec3 eye = GLM_VEC3_ONE_INIT; */ + /* vec3 center = GLM_VEC3_ZERO_INIT; */ -// vk_log(VK_INFO, "{%.2f, %.2f, %.2f}\n", s.camera.front[0], s.camera.front[1], s.camera.front[2]); + // vk_log(VK_INFO, "{%.2f, %.2f, %.2f}\n", s.camera.front[0], s.camera.front[1], s.camera.front[2]); /* glm_vec3_add(s.camera.pos, s.camera.front, center); */ glm_lookat(s.camera.pos, s.camera.front, s.camera.up, ubo.view); @@ -1830,8 +2170,15 @@ updateUniformBuffer(uint32_t currentImage) memcpy(s.frames[currentImage].vk_uniform_buffer_mapped, &ubo, sizeof(ubo)); } +float prev_time = 0; + void draw_frame() { + float time = current_time(); + + float dt = time - prev_time; + + vkWaitForFences(s.vk_device, 1, &s.frames[currentFrame].in_flight_fence, VK_TRUE, UINT64_MAX); uint32_t imageIndex; @@ -1844,7 +2191,7 @@ draw_frame() { vk_log(VK_ERROR, "failed to acquire swap chain image!\n"); } - updateUniformBuffer(currentFrame); + updateUniformBuffer(currentFrame, dt); vkResetFences(s.vk_device, 1, &s.frames[currentFrame].in_flight_fence); @@ -1892,11 +2239,16 @@ draw_frame() { } currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT; + + prev_time = time; } int -main(int argc, char* args[]) +main(int argc, char* argv[]) { + (void) argc; + (void)argv; + init_state(&s); if (!init()) { vk_log(VK_INFO, "Failed to initialize!\n"); -- cgit v1.2.3