diff --git a/assets/shaders/shader.frag b/assets/shaders/shader.frag index 8c4d5d8..7b369c5 100644 --- a/assets/shaders/shader.frag +++ b/assets/shaders/shader.frag @@ -73,8 +73,8 @@ void main() { vec3 norm = normalize(Normal); vec3 viewDir = normalize(viewPos.pos - FragPos); - //vec3 result = calc_directional_light(norm, viewDir); - vec3 result = vec3(0.0, 0.0, 0.0); + vec3 result = calc_directional_light(norm, viewDir); + //vec3 result = vec3(0.0, 0.0, 0.0); for(int i = 0; i < pushConstants.light_count; i++) result += calc_point_light(i, norm, FragPos, viewDir); diff --git a/src/rendering/GraphicsPipeline.zig b/src/rendering/GraphicsPipeline.zig index 1c0d701..d477dfa 100644 --- a/src/rendering/GraphicsPipeline.zig +++ b/src/rendering/GraphicsPipeline.zig @@ -392,6 +392,17 @@ pub fn init(allocator: Allocator, device: vk.Device, swapchain: vk.Swapchain, re try vk.mapError(c.vkCreatePipelineLayout(device.handle, &layout_info, null, @ptrCast(&layout))); + const depth_stencil: c.VkPipelineDepthStencilStateCreateInfo = .{ + .sType = c.VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, + .depthTestEnable = c.VK_TRUE, + .depthWriteEnable = c.VK_TRUE, + .depthCompareOp = c.VK_COMPARE_OP_LESS, + .depthBoundsTestEnable = c.VK_FALSE, + .minDepthBounds = 0.0, + .maxDepthBounds = 1.0, + .stencilTestEnable = c.VK_FALSE, + }; + const pipeline_info: c.VkGraphicsPipelineCreateInfo = .{ .sType = c.VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .stageCount = 2, @@ -401,7 +412,7 @@ pub fn init(allocator: Allocator, device: vk.Device, swapchain: vk.Swapchain, re .pViewportState = &viewport_state_info, .pRasterizationState = &rasterizer_info, .pMultisampleState = &multisampling_info, - .pDepthStencilState = null, + .pDepthStencilState = &depth_stencil, .pColorBlendState = &color_blend_info, .pDynamicState = null, .layout = layout, diff --git a/src/rendering/PhysicalDevice.zig b/src/rendering/PhysicalDevice.zig index 57b4734..58bd40c 100644 --- a/src/rendering/PhysicalDevice.zig +++ b/src/rendering/PhysicalDevice.zig @@ -162,6 +162,7 @@ pub fn create_device(self: *PhysicalDevice, surface: vk.Surface, allocator: Allo var device_properties: c.VkPhysicalDeviceProperties = undefined; c.vkGetPhysicalDeviceProperties(self.handle, &device_properties); + return .{ .handle = device, .graphics_queue = graphics_queue, diff --git a/src/rendering/Renderer.zig b/src/rendering/Renderer.zig index c34110f..6893713 100644 --- a/src/rendering/Renderer.zig +++ b/src/rendering/Renderer.zig @@ -67,6 +67,14 @@ pub fn init(allocator: Allocator, instance_handle: vk.c.VkInstance, surface_hand graphics_pipeline.point_lights[0].diffuse = .{0.5, 0.5, 0.5}; graphics_pipeline.point_lights[0].specular = .{1.0, 1.0, 1.0}; + graphics_pipeline.point_lights[1].position = .{-1.0, 1.0, 0.0}; + graphics_pipeline.point_lights[1].data[0] = 1.0; + graphics_pipeline.point_lights[1].data[1] = 0.9; + graphics_pipeline.point_lights[1].data[2] = 0.8; + graphics_pipeline.point_lights[1].ambient = .{0.2, 0.2, 0.2}; + graphics_pipeline.point_lights[1].diffuse = .{0.5, 0.5, 0.5}; + graphics_pipeline.point_lights[1].specular = .{1.0, 1.0, 1.0}; + return Renderer{ .instance = instance, .surface = surface, @@ -76,8 +84,8 @@ pub fn init(allocator: Allocator, instance_handle: vk.c.VkInstance, surface_hand .swapchain = swapchain, .graphics_pipeline = graphics_pipeline, .current_frame = 0, - .transform = math.Transform.init(.{1.0, 0.0, 0.0}, .{0.5, 0.5, 0.5}, .{0.0, 0.0, 0.0}), - .transform2 = math.Transform.init(.{-1.0, 0.0, 0.0}, .{0.5, 0.5, 0.5}, .{0.0, 0.0, 0.0}), + .transform = math.Transform.init(.{0.0, 0.0, -1.0}, .{0.5, 0.5, 0.5}, .{0.0, 0.0, 0.0}), + .transform2 = math.Transform.init(.{0.0, 0.0, 0.0}, .{0.5, 0.5, 0.5}, .{0.0, 0.0, 0.0}), .previous_time = try std.time.Instant.now(), .mesh = mesh, }; @@ -109,11 +117,12 @@ pub fn render(pool: *ecs.Pool) anyerror!void { view_pos[1] = camera.position[1]; view_pos[2] = camera.position[2]; - renderer.transform.rotate(math.rad(15) * delta_time, .{0.0, 1.0, 0.0}); - renderer.transform2.rotate(math.rad(-15) * delta_time, .{0.0, 1.0, 0.0}); + _ = delta_time; + //renderer.transform.rotate(math.rad(15) * delta_time, .{0.0, 1.0, 0.0}); + //renderer.transform2.rotate(math.rad(-15) * delta_time, .{0.0, 1.0, 0.0}); - renderer.transform.rotate(math.rad(15) * delta_time, .{1.0, 0.0, 0.0}); - renderer.transform2.rotate(math.rad(-15) * delta_time, .{1.0, 0.0, 0.0}); + //renderer.transform.rotate(math.rad(15) * delta_time, .{1.0, 0.0, 0.0}); + //renderer.transform2.rotate(math.rad(-15) * delta_time, .{1.0, 0.0, 0.0}); const transform_memory = renderer.graphics_pipeline.transform_buffer.mapped_memory; transform_memory[0] = renderer.transform; @@ -128,7 +137,7 @@ pub fn render(pool: *ecs.Pool) anyerror!void { renderer.device.bindVertexBuffer(renderer.graphics_pipeline.vertex_buffer, renderer.current_frame); renderer.device.bindIndexBuffer(renderer.graphics_pipeline.index_buffer, renderer.current_frame); renderer.device.bindDescriptorSets(renderer.graphics_pipeline, renderer.current_frame, 0); - var lights: u32 = 1; + var lights: u32 = 2; renderer.device.pushConstant(renderer.graphics_pipeline, c.VK_SHADER_STAGE_FRAGMENT_BIT, 0, 4, @ptrCast(&lights), renderer.current_frame); var transform: u32 = 0; renderer.device.pushConstant(renderer.graphics_pipeline, c.VK_SHADER_STAGE_VERTEX_BIT, 4, 4, @ptrCast(&transform), renderer.current_frame); diff --git a/src/rendering/Swapchain.zig b/src/rendering/Swapchain.zig index 34dbcd7..6aaa932 100644 --- a/src/rendering/Swapchain.zig +++ b/src/rendering/Swapchain.zig @@ -135,11 +135,12 @@ pub fn init(allocator: Allocator, surface: vk.Surface, device: vk.Device, physic const framebuffers = try allocator.alloc(c.VkFramebuffer, image_count); for (image_views, 0..) |view, index| { + const attachments = &[_]c.VkImageView { view, render_pass.depth_view }; const framebuffer_info: c.VkFramebufferCreateInfo = .{ .sType = c.VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, .renderPass = render_pass.handle, - .attachmentCount = 1, - .pAttachments = &view, + .attachmentCount = 2, + .pAttachments = attachments[0..].ptr, .width = extent.width, .height = extent.height, .layers = 1, diff --git a/src/rendering/vulkan.zig b/src/rendering/vulkan.zig index aa02978..5e27035 100644 --- a/src/rendering/vulkan.zig +++ b/src/rendering/vulkan.zig @@ -143,10 +143,15 @@ pub const Sampler = struct { pub const RenderPass = struct { handle: c.VkRenderPass, + depth_image: c.VkImage, + depth_memory: c.VkDeviceMemory, + depth_view: c.VkImageView, const Self = @This(); pub fn init(allocator: Allocator, device: Device, surface: Surface, physical_device: PhysicalDevice) !Self { + const depth_image, const depth_view , const depth_memory, const depth_format = try createDepthResources(device, physical_device); + const color_attachment: c.VkAttachmentDescription = .{ .format = (try Swapchain.pickFormat(allocator, surface, physical_device)).format, .samples = c.VK_SAMPLE_COUNT_1_BIT, @@ -163,25 +168,44 @@ pub const RenderPass = struct { .layout = c.VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, }; + const depth_attachment: c.VkAttachmentDescription = .{ + .format = depth_format, + .samples = c.VK_SAMPLE_COUNT_1_BIT, + .loadOp = c.VK_ATTACHMENT_LOAD_OP_CLEAR, + .storeOp = c.VK_ATTACHMENT_STORE_OP_DONT_CARE, + .stencilLoadOp = c.VK_ATTACHMENT_LOAD_OP_DONT_CARE, + .stencilStoreOp = c.VK_ATTACHMENT_STORE_OP_DONT_CARE, + .initialLayout = c.VK_IMAGE_LAYOUT_UNDEFINED, + .finalLayout = c.VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + }; + + const depth_attachment_reference: c.VkAttachmentReference = .{ + .attachment = 1, + .layout = c.VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + }; + const subpass: c.VkSubpassDescription = .{ .pipelineBindPoint = c.VK_PIPELINE_BIND_POINT_GRAPHICS, .colorAttachmentCount = 1, .pColorAttachments = &color_attachment_reference, + .pDepthStencilAttachment = &depth_attachment_reference, }; const dependency: c.VkSubpassDependency = .{ .srcSubpass = c.VK_SUBPASS_EXTERNAL, .dstSubpass = 0, - .srcStageMask = c.VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - .srcAccessMask = 0, - .dstStageMask = c.VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - .dstAccessMask = c.VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + .srcStageMask = c.VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | c.VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + .srcAccessMask = c.VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + .dstStageMask = c.VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | c.VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, + .dstAccessMask = c.VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | c.VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, }; + const attachments = &[_]c.VkAttachmentDescription { color_attachment, depth_attachment }; + const render_pass_info: c.VkRenderPassCreateInfo = .{ .sType = c.VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, - .attachmentCount = 1, - .pAttachments = &color_attachment, + .attachmentCount = 2, + .pAttachments = attachments[0..].ptr, .subpassCount = 1, .pSubpasses = &subpass, .dependencyCount = 1, @@ -194,12 +218,18 @@ pub const RenderPass = struct { return Self{ .handle = render_pass, + .depth_image = depth_image, + .depth_view = depth_view, + .depth_memory = depth_memory, }; } pub fn begin(self: Self, swapchain: Swapchain, device: Device, image: usize, frame: usize) void { std.debug.assert(frame < frames_in_flight); const clear_color: c.VkClearValue = .{ .color = .{ .float32 = .{ 0.0, 0.0, 0.0, 1.0 } } }; + const depth_stencil: c.VkClearValue = .{ .depthStencil = .{ .depth = 1.0, .stencil = 0 } }; + + const clear_values = &[_]c.VkClearValue { clear_color, depth_stencil }; const begin_info: c.VkRenderPassBeginInfo = .{ .sType = c.VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, @@ -209,8 +239,8 @@ pub const RenderPass = struct { .offset = .{ .x = 0, .y = 0 }, .extent = swapchain.extent, }, - .clearValueCount = 1, - .pClearValues = &clear_color, + .clearValueCount = 2, + .pClearValues = clear_values[0..].ptr, }; c.vkCmdBeginRenderPass(device.command_buffers[frame], &begin_info, c.VK_SUBPASS_CONTENTS_INLINE); @@ -222,6 +252,88 @@ pub const RenderPass = struct { c.vkCmdEndRenderPass(device.command_buffers[frame]); } + fn findSupportedFormat(physical_device: PhysicalDevice, candidates: []c.VkFormat, tiling: c.VkImageTiling, features: c.VkFormatFeatureFlags) ?c.VkFormat { + for (candidates) |format| { + var format_properties: c.VkFormatProperties = undefined; + c.vkGetPhysicalDeviceFormatProperties(physical_device.handle, format, &format_properties); + if (tiling == c.VK_IMAGE_TILING_LINEAR and (format_properties.linearTilingFeatures & features) == features) { + return format; + } else if (tiling == c.VK_IMAGE_TILING_OPTIMAL and (format_properties.optimalTilingFeatures & features) == features) { + return format; + } + } + + return null; + } + + fn createDepthResources(device: Device, physical_device: PhysicalDevice) !struct { c.VkImage, c.VkImageView, c.VkDeviceMemory, c.VkFormat } { + const candidates = &[_]u32 { + c.VK_FORMAT_D32_SFLOAT, + c.VK_FORMAT_D32_SFLOAT_S8_UINT, + c.VK_FORMAT_D24_UNORM_S8_UINT, + }; + + if (findSupportedFormat(physical_device, @constCast(candidates), c.VK_IMAGE_TILING_OPTIMAL, c.VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) |format| { + const create_info: c.VkImageCreateInfo = .{ + .sType = c.VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + .imageType = c.VK_IMAGE_TYPE_2D, + .extent = .{ + .width = @intCast(800), + .height = @intCast(600), + .depth = 1, + }, + .mipLevels = 1, + .arrayLayers = 1, + .format = format, + .tiling = c.VK_IMAGE_TILING_OPTIMAL, + .initialLayout = c.VK_IMAGE_LAYOUT_UNDEFINED, + .usage = c.VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, + .sharingMode = c.VK_SHARING_MODE_EXCLUSIVE, + .samples = c.VK_SAMPLE_COUNT_1_BIT, + .flags = 0, + }; + + var image: c.VkImage = undefined; + var image_memory: c.VkDeviceMemory = undefined; + try mapError(c.vkCreateImage(device.handle, &create_info, null, &image)); + + var memory_requirements: c.VkMemoryRequirements = undefined; + c.vkGetImageMemoryRequirements(device.handle, image, &memory_requirements); + + const alloc_info: c.VkMemoryAllocateInfo = .{ + .sType = c.VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + .allocationSize = memory_requirements.size, + .memoryTypeIndex = try device.findMemoryType(memory_requirements.memoryTypeBits, c.VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT), + }; + + try mapError(c.vkAllocateMemory(device.handle, &alloc_info, null, &image_memory)); + try mapError(c.vkBindImageMemory(device.handle, image, image_memory, 0)); + + const view_create_info: c.VkImageViewCreateInfo = .{ + .sType = c.VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, + .image = image, + .viewType = c.VK_IMAGE_VIEW_TYPE_2D, + .format = format, + .subresourceRange = .{ + .aspectMask = c.VK_IMAGE_ASPECT_DEPTH_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }, + }; + + var image_view: c.VkImageView = undefined; + + try mapError(c.vkCreateImageView(device.handle, &view_create_info, null, &image_view)); + + return .{ image, image_view, image_memory, format }; + } else { + return error.UnsupportedDepthFormat; + } + } + + pub fn deinit(self: Self, device: Device) void { c.vkDestroyRenderPass(device.handle, self.handle, null); }