Implemented depth buffering

This commit is contained in:
Lorenzo Torres 2025-08-10 14:40:23 +02:00
parent 09799eaa9b
commit 444a4586ea
6 changed files with 154 additions and 20 deletions

View file

@ -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);

View file

@ -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,

View file

@ -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,

View file

@ -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);

View file

@ -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,

View file

@ -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);
}