diff --git a/graphics/src/rse_graphics.c b/graphics/src/rse_graphics.c index a40ed057..2f0ce573 100644 --- a/graphics/src/rse_graphics.c +++ b/graphics/src/rse_graphics.c @@ -47,14 +47,15 @@ uint8_t rse_graphics_run(void) tex_id_2 = rse_load_texture("../../test_image.png"); // FIXME: Temporary array of vertices, for testing purposes - struct rse_vertex_t vertices[] = {{{-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 1.0f}, {1.0f, 0.0f}}, - {{0.5f, -0.5f, 0.0f}, {0.0f, 1.0f, 1.0f}, {0.0f, 0.0f}}, - {{0.5f, 0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 1.0f}}, - {{-0.5f, 0.5f, 0.0f}, {1.0f, 0.0f, 1.0f}, {1.0f, 1.0f}}}; - struct rse_vertex_t vertices2[] = {{{-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 1.0f}, {1.0f, 0.0f}}, - {{0.5f, -0.5f, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f}}, - {{0.5f, 0.5f, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 1.0f}}, - {{-0.5f, 0.5f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, 1.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}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.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}}}; + + struct rse_vertex_t vertices2[] = {{{-0.5f, -0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f}}, + {{0.5f, -0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f}}, + {{0.5f, 0.5f, -0.5f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}}, + {{-0.5f, 0.5f, -0.5f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}}}; // FIXME: Temporary array of vertices, for testing purposes uint16_t indices[] = {0, 1, 2, 2, 3, 0}; @@ -68,7 +69,7 @@ uint8_t rse_graphics_run(void) }); create_mesh_instance(mesh_id, (struct rse_instance_data_t){ - {-1.0f, 0.0f, 0.0f}, + {-1.0f, 0.0f, 0.3f}, {0.0f, 0.0f, 0.0f}, 1.0f, tex_id_2 diff --git a/graphics/src/rse_math.c b/graphics/src/rse_math.c index a70735c1..fb37abff 100644 --- a/graphics/src/rse_math.c +++ b/graphics/src/rse_math.c @@ -29,6 +29,27 @@ static float scalar_cross_vec3(const struct vec3_t* vec1, const struct vec3_t* v +(vec1->z * vec2->z); } +// static struct mat4_t mat4_times_vector3_t(const struct mat4_t* mat, const struct vec3_t* vec) +// { +// /* We can't do that, mathematically speaking, but we can just assume that the 4th +// * element of vector is just 1. */ +// struct mat4_t result = rse_math_uniform_mat4(); + +// result.x_1 = mat->x_1 * vec->x; +// result.x_2 = mat->x_2 * vec->y; +// result.x_3 = mat->x_3 * vec->z; + +// result.y_1 = mat->y_1 * vec->x; +// result.y_2 = mat->y_2 * vec->y; +// result.y_3 = mat->y_3 * vec->z; + +// result.z_1 = mat->z_1 * vec->x; +// result.z_2 = mat->z_2 * vec->y; +// result.z_3 = mat->z_3 * vec->z; + +// return result; +// } + float rse_math_deg_to_radians(float degrees) { return degrees * (PI/180.0f); @@ -122,5 +143,27 @@ struct mat4_t rse_math_look_at(const struct vec3_t* eye, const struct vec3_t* ce result.w_3 = 0; result.w_4 = 1; + return result; +} + +struct mat4_t rse_math_rotate(struct mat4_t matrix, float radians, struct vec3_t rotation_vector) +{ + struct mat4_t result = rse_math_uniform_mat4(); + float cos = cosf(radians); + float sin = sinf(radians); + + //TODO: Switch to quaternion + result.x_1 = cos + powf(rotation_vector.x, 2.0f) * (1 - cos); + result.x_2 = (rotation_vector.x * rotation_vector.y * (1 - cos)) - (rotation_vector.z * sin); + result.x_3 = (rotation_vector.x * rotation_vector.z * (1 - cos)) + (rotation_vector.y * sin); + + result.y_1 = (rotation_vector.y * rotation_vector.x * (1 - cos)) + rotation_vector.z * sin; + result.y_2 = cos + (powf(rotation_vector.y, 2) * (1 - cos)); + result.y_3 = (rotation_vector.y * rotation_vector.z * (1 - cos)) - (rotation_vector.x * sin); + + result.z_1 = (rotation_vector.z * rotation_vector.x * (1 - cos)) - (rotation_vector.y * sin); + result.z_2 = (rotation_vector.z * rotation_vector.y * (1 - cos)) + (rotation_vector.x * sin); + result.z_3 = cos + (powf(rotation_vector.z, 2.0f) * (1 - cos)); + return result; } \ No newline at end of file diff --git a/graphics/src/rse_math.h b/graphics/src/rse_math.h index 89f3f15a..fe6163ec 100644 --- a/graphics/src/rse_math.h +++ b/graphics/src/rse_math.h @@ -113,6 +113,15 @@ struct mat4_t rse_math_look_at(const struct vec3_t* eye, const struct vec3_t* ce */ struct mat4_t rse_math_perspective(float fovy_rad, float aspect_ratio, float z_near, float z_far); +/** + * @brief Rotate matrix around vector for radians degrees + * + * @param matrix Matrix to rotate + * @param radians Degrees + * @param rotation_vector Rotation vector + * @return struct mat4_t resulting matrix + */ +struct mat4_t rse_math_rotate(struct mat4_t matrix, float radians, struct vec3_t rotation_vector); #ifdef __cplusplus } #endif diff --git a/graphics/src/rse_vulkan_image.c b/graphics/src/rse_vulkan_image.c index de7d1df2..735720c9 100644 --- a/graphics/src/rse_vulkan_image.c +++ b/graphics/src/rse_vulkan_image.c @@ -37,8 +37,11 @@ struct rse_vulkan_image_t extern struct rse_vulkan_state_t g_vulkan_state; struct rse_vulkan_image_t g_texture_images[RSE_MAX_IMAGE_COUNT]; + +struct rse_vulkan_image_t g_depth_image; VkSampler g_sampler; + static uint8_t create_sampler() { VkSamplerCreateInfo create_info = {0}; @@ -73,6 +76,117 @@ static uint8_t create_sampler() return VULKAN_ERROR_NO_ERROR; } +// static uint8_t has_stencil_component(VkFormat format) { +// return format == VK_FORMAT_D32_SFLOAT_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT; +// } + +static VkFormat find_supported_format(const VkFormat* candidates, + size_t candidates_count, + VkImageTiling tiling, + VkFormatFeatureFlags features) +{ + size_t i = 0U; + + for (i = 0U; i < candidates_count; ++i) { + VkFormatProperties props; + vkGetPhysicalDeviceFormatProperties(g_vulkan_state.physical_device, candidates[i], &props); + + if (tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures & features) == features) { + return candidates[i]; + } else if (tiling == VK_IMAGE_TILING_OPTIMAL && (props.optimalTilingFeatures & features) == features) { + return candidates[i]; + } + } + + LOGE("Failed to find correct format"); + //FIXME: Add error handling + return 0; +} + +static uint8_t create_depth_resources() +{ + uint8_t status = VULKAN_ERROR_NO_ERROR; + VkFormat depth_format = {0}; + VkExtent3D image_extent = {0}; + VkImageCreateInfo image_info = {0}; + VmaAllocationCreateInfo alloc_create_info = {0}; + VkImageViewCreateInfo image_view_create_info = {0}; + VkSurfaceCapabilitiesKHR physical_device_surface_capabilities; + + + depth_format = find_depth_format(); + vkGetPhysicalDeviceSurfaceCapabilitiesKHR(g_vulkan_state.physical_device, + g_vulkan_state.surface, + &physical_device_surface_capabilities); + + /*TODO: Remove boilerplate code */ + + image_extent.width = physical_device_surface_capabilities.currentExtent.width; + image_extent.height = physical_device_surface_capabilities.currentExtent.height; + image_extent.depth = 1U; + + image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + image_info.pNext = NULL; + image_info.flags = 0U; + image_info.imageType = VK_IMAGE_TYPE_2D; + image_info.format = depth_format; + image_info.extent = image_extent; + image_info.mipLevels = 1U; + image_info.arrayLayers = 1U; + image_info.samples = VK_SAMPLE_COUNT_1_BIT; //TODO: Enable multisampling + image_info.tiling = VK_IMAGE_TILING_OPTIMAL; + image_info.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; //TODO: Change if used by more than one queue family + image_info.queueFamilyIndexCount = 0U; + image_info.pQueueFamilyIndices = NULL; + image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + alloc_create_info.flags = 0U; + alloc_create_info.usage = VMA_MEMORY_USAGE_AUTO; + alloc_create_info.requiredFlags = 0U; + alloc_create_info.preferredFlags = 0U; + alloc_create_info.memoryTypeBits = 0U; + alloc_create_info.pool = NULL; + alloc_create_info.pUserData = NULL; + alloc_create_info.priority = 1.0f; + + if (VK_SUCCESS != vmaCreateImage(g_vulkan_state.allocator, + &image_info, + &alloc_create_info, + &g_depth_image.image, + &g_depth_image.allocation, + &g_depth_image.allocation_info)) { + LOGF("Failed to create image"); + return -1; + } + + image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + image_view_create_info.pNext = NULL; + image_view_create_info.flags = 0U; + image_view_create_info.image = g_depth_image.image; + image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; /* 2D Texture */ + image_view_create_info.format = depth_format; + image_view_create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_create_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + image_view_create_info.subresourceRange.baseMipLevel = 0U; + image_view_create_info.subresourceRange.levelCount = 1U; + image_view_create_info.subresourceRange.baseArrayLayer = 0U; + image_view_create_info.subresourceRange.layerCount = 1U; + + if (VK_SUCCESS != vkCreateImageView(g_vulkan_state.device, + &image_view_create_info, + NULL, + &g_depth_image.image_view)) { + LOGF(vulkan_error_messages[VULKAN_SWAPCHAIN_IMVIEW_CREATION_FAILED]); + return VULKAN_ERROR_SWAPCHAIN_IMVIEW_CREATION_FAILED; + } + + return status; +} + static VkDeviceSize format_to_pixel_size(VkFormat format) { switch (format) @@ -278,6 +392,7 @@ uint8_t init_vulkan_images() // memset(g_texture_images, 0, sizeof(struct rse_vulkan_image_t) * RSE_MAX_IMAGE_COUNT); STATUS_CHECK(create_sampler()); + STATUS_CHECK(create_depth_resources()); return status; } @@ -323,6 +438,9 @@ void rse_destroy_textures() vmaDestroyImage(g_vulkan_state.allocator, g_texture_images[i].image, g_texture_images[i].allocation); } } + + vkDestroyImageView(g_vulkan_state.device, g_depth_image.image_view, NULL); + vmaDestroyImage(g_vulkan_state.allocator, g_depth_image.image, g_depth_image.allocation); } int8_t image_exists(uint8_t image_id) { @@ -334,6 +452,12 @@ VkImageView rse_get_image_view(size_t image_id) return g_texture_images[image_id].image_view; } +VkImageView rse_get_depth_image_view() +{ + return g_depth_image.image_view; +} + + VkSampler rse_get_texture_sampler() { return g_sampler; @@ -351,4 +475,18 @@ size_t get_textures_count() } return count; +} + +VkFormat find_depth_format() +{ + #define formats_count 3 + VkFormat formats[formats_count] = {VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT}; + + return find_supported_format( + formats, + formats_count, + VK_IMAGE_TILING_OPTIMAL, + VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT + ); + #undef formats_count } \ No newline at end of file diff --git a/graphics/src/rse_vulkan_image.h b/graphics/src/rse_vulkan_image.h index 29181de8..e705061a 100644 --- a/graphics/src/rse_vulkan_image.h +++ b/graphics/src/rse_vulkan_image.h @@ -75,4 +75,8 @@ int8_t image_exists(uint8_t image_id); */ size_t get_textures_count(); +VkFormat find_depth_format(); + +VkImageView rse_get_depth_image_view(); + #endif /* RSE_TEXTURE_H */ \ No newline at end of file diff --git a/graphics/src/vulkan_buffers.c b/graphics/src/vulkan_buffers.c index c8b5a2a4..3b99bc6e 100644 --- a/graphics/src/vulkan_buffers.c +++ b/graphics/src/vulkan_buffers.c @@ -202,6 +202,7 @@ void update_uniform_buffers() struct vec3_t eye = {0}; struct vec3_t center = {0}; struct vec3_t up = {0}; + struct vec3_t rotation_vec = {1.0f, 0.0f, 0.0f}; float fovy; float z_near; float z_far; @@ -214,7 +215,7 @@ void update_uniform_buffers() z_near = 0.1f; z_far = 20.0f; - ubo.model = rse_math_uniform_mat4(); + ubo.model = rse_math_rotate(rse_math_uniform_mat4(), rse_math_deg_to_radians(0.0f), rotation_vec); ubo.view = rse_math_look_at(&eye, ¢er, &up); ubo.proj = rse_math_perspective(fovy, g_vulkan_state.swapchain_extent.width / (float)g_vulkan_state.swapchain_extent.height, @@ -330,13 +331,20 @@ uint8_t record_command_buffer(uint32_t image_index) { VkCommandBuffer command_buffer = g_vulkan_state.command_buffers[g_vulkan_state.current_frame]; VkCommandBufferBeginInfo begin_info = {}; - VkClearValue clear_color = {{{0.0f, 0.0f, 0.0f, 1.0f}}}; VkRenderPassBeginInfo render_pass_info = {}; VkViewport viewport = {}; VkRect2D scissor = {}; VkDeviceSize offsets[] = {0}; + VkClearValue clear_values[2] = {}; //For color and depth stencil size_t i = 0U; + clear_values[0].color.float32[0] = 0.0f; + clear_values[0].color.float32[1] = 0.0f; + clear_values[0].color.float32[2] = 0.0f; + + clear_values[1].depthStencil.depth = 1.0f; + clear_values[1].depthStencil.stencil = 0.0f; + begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; begin_info.flags = 0; begin_info.pInheritanceInfo = NULL; @@ -352,8 +360,8 @@ uint8_t record_command_buffer(uint32_t image_index) render_pass_info.renderArea.offset.x = 0; render_pass_info.renderArea.offset.y = 0; render_pass_info.renderArea.extent = g_vulkan_state.swapchain_extent; - render_pass_info.clearValueCount = 1; - render_pass_info.pClearValues = &clear_color; + render_pass_info.clearValueCount = 2; + render_pass_info.pClearValues = clear_values; vkCmdBeginRenderPass(command_buffer, &render_pass_info, VK_SUBPASS_CONTENTS_INLINE); vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_vulkan_state.graphics_pipeline); diff --git a/graphics/src/vulkan_pipeline.c b/graphics/src/vulkan_pipeline.c index 2b794008..3471eed6 100644 --- a/graphics/src/vulkan_pipeline.c +++ b/graphics/src/vulkan_pipeline.c @@ -220,10 +220,26 @@ uint8_t create_swapchain_image_views() */ uint8_t create_render_pass() { + VkAttachmentDescription attachments[2] = {}; VkAttachmentDescription color_attachment = {}; VkAttachmentReference color_attachment_ref = {}; VkSubpassDescription subpass = {}; VkRenderPassCreateInfo renderpass_info = {}; + VkAttachmentDescription depth_attachment = {}; + VkAttachmentReference depth_attachment_ref = {}; + VkSubpassDependency dependency = {}; + + depth_attachment.format = find_depth_format(); + depth_attachment.samples = VK_SAMPLE_COUNT_1_BIT; + depth_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + depth_attachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + depth_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + depth_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + depth_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + depth_attachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + depth_attachment_ref.attachment = 1; + depth_attachment_ref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; color_attachment.flags = 0U; color_attachment.format = IMAGE_FORMAT; @@ -241,12 +257,26 @@ uint8_t create_render_pass() subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; subpass.colorAttachmentCount = 1; subpass.pColorAttachments = &color_attachment_ref; + subpass.pDepthStencilAttachment = &depth_attachment_ref; + + attachments[0] = color_attachment; + attachments[1] = depth_attachment; + + dependency.srcSubpass = VK_SUBPASS_EXTERNAL; + dependency.dstSubpass = 0; + dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; + dependency.srcAccessMask = 0; + dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; + dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + renderpass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderpass_info.attachmentCount = 1; - renderpass_info.pAttachments = &color_attachment; + renderpass_info.attachmentCount = 2; + renderpass_info.pAttachments = attachments; renderpass_info.subpassCount = 1; renderpass_info.pSubpasses = &subpass; + renderpass_info.dependencyCount = 1; + renderpass_info.pDependencies = &dependency; if (VK_SUCCESS != vkCreateRenderPass(g_vulkan_state.device, &renderpass_info, NULL, &g_vulkan_state.render_pass)) { LOGF(vulkan_error_messages[VULKAN_RENDERPASS_CREATION_FAILED]); @@ -340,6 +370,7 @@ uint8_t create_graphics_pipeline() VkPipelineMultisampleStateCreateInfo multisampling = {}; VkPipelineColorBlendStateCreateInfo color_blending = {}; VkPipelineDynamicStateCreateInfo dynamic_state = {}; + VkPipelineDepthStencilStateCreateInfo depth_stencil = {}; STATUS_CHECK(fill_shader_stages(shader_stages)); fill_vertex_input_info(&vertex_input_info); @@ -350,29 +381,41 @@ uint8_t create_graphics_pipeline() fill_color_blend_state_info(&color_blending); fill_dynamic_pipeline_state_info(&dynamic_state); - VkGraphicsPipelineCreateInfo pipelineInfo = {}; - pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - pipelineInfo.pNext = NULL; - pipelineInfo.flags = 0U; - pipelineInfo.stageCount = SHADER_MODULES_COUNT; - pipelineInfo.pStages = shader_stages; - pipelineInfo.pVertexInputState = &vertex_input_info; - pipelineInfo.pInputAssemblyState = &input_assembly; - pipelineInfo.pTessellationState = NULL; - pipelineInfo.pViewportState = &viewport_state; - pipelineInfo.pRasterizationState = &rasterizer; - pipelineInfo.pMultisampleState = &multisampling; - pipelineInfo.pDepthStencilState = NULL; - pipelineInfo.pColorBlendState = &color_blending; - pipelineInfo.pDynamicState = &dynamic_state; - pipelineInfo.layout = g_vulkan_state.pipeline_layout; - pipelineInfo.renderPass = g_vulkan_state.render_pass; - pipelineInfo.subpass = 0; - pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; - pipelineInfo.basePipelineIndex = -1; + //TODO: Move to another function + depth_stencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + depth_stencil.depthTestEnable = VK_TRUE; + depth_stencil.depthWriteEnable = VK_TRUE; + depth_stencil.depthCompareOp = VK_COMPARE_OP_LESS; + depth_stencil.depthBoundsTestEnable = VK_FALSE; + depth_stencil.minDepthBounds = 0.0f; // Optional + depth_stencil.maxDepthBounds = 1.0f; // Optional + depth_stencil.stencilTestEnable = VK_FALSE; + // depth_stencil.front = {0}; // Optional + // depth_stencil.back = {0}; // Optional + + VkGraphicsPipelineCreateInfo pipeline_info = {}; + pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + pipeline_info.pNext = NULL; + pipeline_info.flags = 0U; + pipeline_info.stageCount = SHADER_MODULES_COUNT; + pipeline_info.pStages = shader_stages; + pipeline_info.pVertexInputState = &vertex_input_info; + pipeline_info.pInputAssemblyState = &input_assembly; + pipeline_info.pTessellationState = NULL; + pipeline_info.pViewportState = &viewport_state; + pipeline_info.pRasterizationState = &rasterizer; + pipeline_info.pMultisampleState = &multisampling; + pipeline_info.pDepthStencilState = &depth_stencil; + pipeline_info.pColorBlendState = &color_blending; + pipeline_info.pDynamicState = &dynamic_state; + pipeline_info.layout = g_vulkan_state.pipeline_layout; + pipeline_info.renderPass = g_vulkan_state.render_pass; + pipeline_info.subpass = 0; + pipeline_info.basePipelineHandle = VK_NULL_HANDLE; + pipeline_info.basePipelineIndex = -1; if (VK_SUCCESS != - vkCreateGraphicsPipelines(g_vulkan_state.device, VK_NULL_HANDLE, 1, &pipelineInfo, NULL, &g_vulkan_state.graphics_pipeline)) { + vkCreateGraphicsPipelines(g_vulkan_state.device, VK_NULL_HANDLE, 1, &pipeline_info, NULL, &g_vulkan_state.graphics_pipeline)) { LOGF(vulkan_error_messages[VULKAN_GRAPHICSPIPELINE_CREATION_FAILED]); status = VULKAN_ERROR_GRAPHICSPIPELINE_CREATION_FAILED; } @@ -395,12 +438,12 @@ uint8_t create_framebuffers() g_vulkan_state.swapchain_framebuffers = malloc(sizeof(VkFramebuffer) * g_swapchain_images_count); for (size_t i = 0; i < g_swapchain_images_count; i++) { - VkImageView attachments[] = {g_vulkan_state.swapchain_image_views[i]}; + VkImageView attachments[] = {g_vulkan_state.swapchain_image_views[i], rse_get_depth_image_view()}; VkFramebufferCreateInfo framebufferInfo = {}; framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; framebufferInfo.renderPass = g_vulkan_state.render_pass; - framebufferInfo.attachmentCount = 1; + framebufferInfo.attachmentCount = 2; framebufferInfo.pAttachments = attachments; framebufferInfo.width = g_vulkan_state.swapchain_extent.width; framebufferInfo.height = g_vulkan_state.swapchain_extent.height; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index aabfea54..3e9d8c9c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,7 +1,7 @@ find_package(Criterion) add_executable(tests -src/rse_graphics_tests.c) +src/rse_math_tests.c) target_include_directories(tests PRIVATE ${criterion_INCLUDE_DIR} diff --git a/tests/src/rse_math_tests.c b/tests/src/rse_math_tests.c index c287fd51..9a022955 100644 --- a/tests/src/rse_math_tests.c +++ b/tests/src/rse_math_tests.c @@ -176,4 +176,42 @@ Test(rse_math, perspective) cr_expect_float_eq(result.z_4, expected.z_4, 0.0001, "Expected z_4 %f, got %f", expected.z_4, result.z_4); cr_expect_float_eq(result.w_4, expected.w_4, 0.0001, "Expected w_4 %f, got %f", expected.w_4, result.w_4); +} + +Test(rse_math, rotation) +{ + struct mat4_t matrix_to_rotate = rse_math_uniform_mat4(); + struct vec3_t rotation_vector = {1.0f, 0.0f, 0.0f}; + float rotation = 45.f; + + struct mat4_t result = {0.0f}; + struct mat4_t expected = rse_math_uniform_mat4(); + + expected.y_2 = 0.5253220; + expected.y_3 = -0.8509035; + + expected.z_2 = 0.8509035; + expected.z_3 = 0.5253220; + + result = rse_math_rotate(matrix_to_rotate, rotation, rotation_vector); + + cr_expect_float_eq(result.x_1, expected.x_1, 0.0001, "Expected x_1 %f, got %f", expected.x_1, result.x_1); + cr_expect_float_eq(result.y_1, expected.y_1, 0.0001, "Expected y_1 %f, got %f", expected.y_1, result.y_1); + cr_expect_float_eq(result.z_1, expected.z_1, 0.0001, "Expected z_1 %f, got %f", expected.z_1, result.z_1); + cr_expect_float_eq(result.w_1, expected.w_1, 0.0001, "Expected w_1 %f, got %f", expected.w_1, result.w_1); + + cr_expect_float_eq(result.x_2, expected.x_2, 0.0001, "Expected x_2 %f, got %f", expected.x_2, result.x_2); + cr_expect_float_eq(result.y_2, expected.y_2, 0.0001, "Expected y_2 %f, got %f", expected.y_2, result.y_2); + cr_expect_float_eq(result.z_2, expected.z_2, 0.0001, "Expected z_2 %f, got %f", expected.z_2, result.z_2); + cr_expect_float_eq(result.w_2, expected.w_2, 0.0001, "Expected w_2 %f, got %f", expected.w_2, result.w_2); + + cr_expect_float_eq(result.x_3, expected.x_3, 0.0001, "Expected x_3 %f, got %f", expected.x_3, result.x_3); + cr_expect_float_eq(result.y_3, expected.y_3, 0.0001, "Expected y_3 %f, got %f", expected.y_3, result.y_3); + cr_expect_float_eq(result.z_3, expected.z_3, 0.0001, "Expected z_3 %f, got %f", expected.z_3, result.z_3); + cr_expect_float_eq(result.w_3, expected.w_3, 0.0001, "Expected w_3 %f, got %f", expected.w_3, result.w_3); + + cr_expect_float_eq(result.x_4, expected.x_4, 0.0001, "Expected x_4 %f, got %f", expected.x_4, result.x_4); + cr_expect_float_eq(result.y_4, expected.y_4, 0.0001, "Expected y_4 %f, got %f", expected.y_4, result.y_4); + cr_expect_float_eq(result.z_4, expected.z_4, 0.0001, "Expected z_4 %f, got %f", expected.z_4, result.z_4); + cr_expect_float_eq(result.w_4, expected.w_4, 0.0001, "Expected w_4 %f, got %f", expected.w_4, result.w_4); } \ No newline at end of file