From eb6fc926be7f29d6d92f238146180d510d69c79e Mon Sep 17 00:00:00 2001 From: Frederico Linhares Date: Thu, 11 Aug 2022 15:46:36 -0300 Subject: feat Create directional light --- glsl/shader.frag | 34 +++++++-- glsl/shader.vert | 28 ++++--- src/vk/graphics_pipeline.cpp | 170 +++++++++++++++++++++++++++++-------------- src/vk/graphics_pipeline.hpp | 5 +- src/vk/uniform_buffer.hpp | 7 ++ 5 files changed, 174 insertions(+), 70 deletions(-) diff --git a/glsl/shader.frag b/glsl/shader.frag index 39aa83c..8ecf883 100644 --- a/glsl/shader.frag +++ b/glsl/shader.frag @@ -1,14 +1,38 @@ #version 450 #extension GL_ARB_separate_shader_objects : enable -layout(location = 0) in vec3 in_frag_color; -layout(location = 1) in vec2 in_frag_texture_coord; +struct DataTransferObject +{ + vec4 frag_color; + vec2 frag_texture_coord; + vec3 normal; +}; + +layout(location = 0) in DataTransferObject in_dto; layout(location = 0) out vec4 out_color; -layout(set = 0, binding = 1) uniform sampler2D texture_sampler; +layout(set = 0, binding = 1) uniform UBODirectionalLight +{ + vec3 direction; + vec4 color; +} ubo_directional_light; + +layout(set = 1, binding = 1) uniform sampler2D texture_sampler; -void main() +void +main() { - out_color = texture(texture_sampler, in_frag_texture_coord); + float diffuse_factor = + max(dot(in_dto.normal, -ubo_directional_light.direction), 0.0); + + vec4 diff_samp = texture(texture_sampler, in_dto.frag_texture_coord); + vec4 ambient = vec4(vec3(in_dto.frag_color), diff_samp.a); + vec4 diffuse = + vec4(vec3(ubo_directional_light.color * diffuse_factor), diff_samp.a); + + diffuse *= diff_samp; + ambient *= diff_samp; + + out_color = (ambient + diffuse); } diff --git a/glsl/shader.vert b/glsl/shader.vert index 2407255..bc89a8c 100644 --- a/glsl/shader.vert +++ b/glsl/shader.vert @@ -6,25 +6,35 @@ layout(location = 1) in vec3 in_normal; layout(location = 2) in vec3 in_color; layout(location = 3) in vec2 in_texture_coord; -layout(location = 0) out vec3 frag_color; -layout(location = 1) out vec2 frag_texture_coord; -layout(set = 0, binding = 0) uniform UBOModelInstance +layout(location = 0) out DataTransferObject { - mat4 model[128]; -} ubo_model_instance; + vec4 frag_color; + vec2 frag_texture_coord; + vec3 normal; +} out_dto; -layout(set = 1, binding = 0) uniform UBOViewProjection +layout(set = 0, binding = 0) uniform UBOViewProjection { mat4 view; mat4 proj; + vec4 ambient_color; } ubo_view_projection; -void main() +layout(set = 1, binding = 0) uniform UBOModelInstance +{ + mat4 model[128]; +} ubo_model_instance; + +void +main() { gl_Position = ubo_view_projection.proj * ubo_view_projection.view * ubo_model_instance.model[gl_InstanceIndex] * vec4(in_position, 1.0); - frag_color = in_color; - frag_texture_coord = in_texture_coord; + out_dto.frag_color = vec4(in_color.r, in_color.g, in_color.b, 1.0) * + ubo_view_projection.ambient_color; + out_dto.frag_texture_coord = in_texture_coord; + out_dto.normal = mat3(ubo_model_instance.model[gl_InstanceIndex]) * + in_normal; } diff --git a/src/vk/graphics_pipeline.cpp b/src/vk/graphics_pipeline.cpp index 1ba8a12..bd0406c 100644 --- a/src/vk/graphics_pipeline.cpp +++ b/src/vk/graphics_pipeline.cpp @@ -73,39 +73,45 @@ unload_descriptor_set_layout_model_instance(void *obj) } void -load_descriptor_set_layout_view_projection(void *obj) +load_descriptor_set_layout_world_view(void *obj) { auto self = static_cast(obj); - VkDescriptorSetLayoutBinding layout_binding{}; - layout_binding.binding = 0; - layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - layout_binding.descriptorCount = 1; - layout_binding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - layout_binding.pImmutableSamplers = nullptr; + std::array set_layouts{}; + set_layouts[0].binding = 0; + set_layouts[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + set_layouts[0].descriptorCount = 1; + set_layouts[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + set_layouts[0].pImmutableSamplers = nullptr; + + set_layouts[1].binding = 1; + set_layouts[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + set_layouts[1].descriptorCount = 1; + set_layouts[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + set_layouts[1].pImmutableSamplers = nullptr; VkDescriptorSetLayoutCreateInfo layout_info{}; layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; layout_info.pNext = nullptr; layout_info.flags = 0; - layout_info.bindingCount = 1; - layout_info.pBindings = &layout_binding; + layout_info.bindingCount = set_layouts.size(); + layout_info.pBindings = set_layouts.data(); if(vkCreateDescriptorSetLayout( - cg_core.vk_device_with_swapchain->device, &layout_info, nullptr, - &self->descriptor_set_layout_view_projection) != VK_SUCCESS) + cg_core.vk_device_with_swapchain->device, &layout_info, nullptr, + &self->descriptor_set_layout_world_view) != VK_SUCCESS) throw CommandError{ - "Failed to create Vulkan descriptor set layout for view projection."}; + "Failed to create Vulkan descriptor set layout for world view."}; } void -unload_descriptor_set_layout_view_projection(void *obj) +unload_descriptor_set_layout_world_view(void *obj) { auto self = static_cast(obj); vkDestroyDescriptorSetLayout( cg_core.vk_device_with_swapchain->device, - self->descriptor_set_layout_view_projection, nullptr); + self->descriptor_set_layout_world_view, nullptr); } void @@ -114,8 +120,8 @@ load_pipeline_layout(void *obj) auto self = static_cast(obj); std::array set_layouts{ - self->descriptor_set_layout_model_instance, - self->descriptor_set_layout_view_projection}; + self->descriptor_set_layout_world_view, + self->descriptor_set_layout_model_instance}; VkPipelineLayoutCreateInfo pipeline_layout_info{}; pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; @@ -127,8 +133,7 @@ load_pipeline_layout(void *obj) if(vkCreatePipelineLayout( cg_core.vk_device_with_swapchain->device, &pipeline_layout_info, nullptr, &self->pipeline_layout) != VK_SUCCESS) - throw CommandError{ - "Failed to create Vulkan descriptor set layout for view projection."}; + throw CommandError{"Failed to create Vulkan pipeline layout."}; } void @@ -141,7 +146,7 @@ unload_pipeline_layout(void *obj) } void -load_uniform_buffer(void *obj) +load_view_projection_uniform_buffer(void *obj) { auto self = static_cast(obj); @@ -159,13 +164,39 @@ load_uniform_buffer(void *obj) } void -unload_uniform_buffer(void *obj) +unload_view_projection_uniform_buffer(void *obj) { auto self = static_cast(obj); self->ub_view_projection.clear(); } +void +load_directional_light_uniform_buffer(void *obj) +{ + auto self = static_cast(obj); + + try + { + self->ub_view_projection.reserve(cg_core.vk_swapchain->images_count); + for(auto i{0}; i < cg_core.vk_swapchain->images_count; i++) + self->ub_directional_light.emplace_back( + cg_core.vk_device_with_swapchain, sizeof(VK::UBODirectionalLight)); + } + catch(const std::exception& e) + { + throw CommandError{e.what()}; + } +} + +void +unload_directional_light_uniform_buffer(void *obj) +{ + auto self = static_cast(obj); + + self->ub_directional_light.clear(); +} + void load_descriptor_pool(void *obj) { @@ -173,13 +204,15 @@ load_descriptor_pool(void *obj) VkDescriptorPoolSize descriptor_pool_size{}; descriptor_pool_size.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptor_pool_size.descriptorCount = self->ub_view_projection.size(); + descriptor_pool_size.descriptorCount = + self->ub_view_projection.size() + self->ub_directional_light.size(); VkDescriptorPoolCreateInfo pool_info{}; pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; pool_info.pNext = nullptr; pool_info.flags = 0; - pool_info.maxSets = self->ub_view_projection.size(); + pool_info.maxSets = + self->ub_view_projection.size() + self->ub_directional_light.size(); pool_info.poolSizeCount = 1; pool_info.pPoolSizes = &descriptor_pool_size; @@ -199,13 +232,13 @@ unload_descriptor_pool(void *obj) } void -load_descriptor_sets(void *obj) +load_world_view_descriptor_sets(void *obj) { auto self = static_cast(obj); std::vector layouts( cg_core.vk_swapchain->images_count, - self->descriptor_set_layout_view_projection); + self->descriptor_set_layout_world_view); VkDescriptorSetAllocateInfo alloc_info{}; alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; @@ -213,40 +246,55 @@ load_descriptor_sets(void *obj) alloc_info.descriptorSetCount = self->ub_view_projection.size(); alloc_info.pSetLayouts = layouts.data(); - self->view_projection_descriptor_sets.resize( + self->world_view_descriptor_sets.resize( cg_core.vk_swapchain->images_count); if(vkAllocateDescriptorSets( cg_core.vk_device_with_swapchain->device, &alloc_info, - self->view_projection_descriptor_sets.data()) != VK_SUCCESS) - throw CommandError{"Failed to create Vulkan descriptor set."}; + self->world_view_descriptor_sets.data()) != VK_SUCCESS) + throw CommandError{"Failed to create Vulkan world view descriptor set."}; } void -load_descriptor_sets_to_buffers(void *obj) +load_resources_to_descriptor_sets(void *obj) { auto self = static_cast(obj); for(auto i{0}; i < self->ub_view_projection.size(); i++) { - VkDescriptorBufferInfo buffer_info{}; - buffer_info.buffer = self->ub_view_projection[i].buffer; - buffer_info.offset = 0; - buffer_info.range = sizeof(VK::UBOViewProjection); - - VkWriteDescriptorSet write_descriptor{}; - write_descriptor.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - write_descriptor.dstSet = self->view_projection_descriptor_sets[i]; - write_descriptor.dstBinding = 0; - write_descriptor.dstArrayElement = 0; - write_descriptor.descriptorCount = 1; - write_descriptor.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - write_descriptor.pBufferInfo = &buffer_info; - write_descriptor.pImageInfo = nullptr; - write_descriptor.pTexelBufferView = nullptr; + VkDescriptorBufferInfo view_projection_info{}; + view_projection_info.buffer = self->ub_view_projection[i].buffer; + view_projection_info.offset = 0; + view_projection_info.range = sizeof(VK::UBOViewProjection); + + VkDescriptorBufferInfo directional_light_info{}; + directional_light_info.buffer = self->ub_directional_light[i].buffer; + directional_light_info.offset = 0; + directional_light_info.range = sizeof(VK::UBODirectionalLight); + + std::array write_descriptors{}; + write_descriptors[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write_descriptors[0].dstSet = self->world_view_descriptor_sets[i]; + write_descriptors[0].dstBinding = 0; + write_descriptors[0].dstArrayElement = 0; + write_descriptors[0].descriptorCount = 1; + write_descriptors[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + write_descriptors[0].pBufferInfo = &view_projection_info; + write_descriptors[0].pImageInfo = nullptr; + write_descriptors[0].pTexelBufferView = nullptr; + + write_descriptors[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write_descriptors[1].dstSet = self->world_view_descriptor_sets[i]; + write_descriptors[1].dstBinding = 1; + write_descriptors[1].dstArrayElement = 0; + write_descriptors[1].descriptorCount = 1; + write_descriptors[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + write_descriptors[1].pBufferInfo = &directional_light_info; + write_descriptors[1].pImageInfo = nullptr; + write_descriptors[1].pTexelBufferView = nullptr; vkUpdateDescriptorSets( - cg_core.vk_device_with_swapchain->device, 1, &write_descriptor, 0, - nullptr); + cg_core.vk_device_with_swapchain->device, write_descriptors.size(), + write_descriptors.data(), 0, nullptr); } } @@ -773,14 +821,17 @@ load_draw_command_buffer(void *obj) const CommandChain loader{ {&load_descriptor_set_layout_model_instance, &unload_descriptor_set_layout_model_instance}, - {&load_descriptor_set_layout_view_projection, - &unload_descriptor_set_layout_view_projection}, + {&load_descriptor_set_layout_world_view, + &unload_descriptor_set_layout_world_view}, {&load_pipeline_layout, &unload_pipeline_layout}, - {&load_uniform_buffer, &unload_uniform_buffer}, + {&load_view_projection_uniform_buffer, + &unload_view_projection_uniform_buffer}, + {&load_directional_light_uniform_buffer, + &unload_directional_light_uniform_buffer}, {&load_descriptor_pool, &unload_descriptor_pool}, // By destroying the pool the sets are also destroyed. - {&load_descriptor_sets, nullptr}, - {&load_descriptor_sets_to_buffers, nullptr}, + {&load_world_view_descriptor_sets, nullptr}, + {&load_resources_to_descriptor_sets, nullptr}, {&load_depth_image, &unload_depth_image}, {&load_depth_image_view, &unload_depth_image_view}, {&load_render_pass, &unload_render_pass}, @@ -879,8 +930,8 @@ GraphicsPipeline::draw() // Commands { std::array vk_descriptor_sets{ - model->descriptor_sets[image_index], - this->view_projection_descriptor_sets[image_index]}; + this->world_view_descriptor_sets[image_index], + model->descriptor_sets[image_index]}; VkBuffer vertex_buffers[]{model->vertex_buffer->buffer}; VkDeviceSize offsets[]{0}; @@ -918,7 +969,7 @@ GraphicsPipeline::draw() instance_matrix = glm::translate( instance_matrix, instances[i].position); - ubo_model_instance.model[i] = instance_matrix; + ubo_model_instance.model[i] = instance_matrix; } model->ub_model_instance[image_index].copy_data(&ubo_model_instance); @@ -929,7 +980,7 @@ GraphicsPipeline::draw() throw std::runtime_error{"Failed to end draw command buffer."}; } - // Update uniform buffers + // Update view projection uniform buffers { VK::UBOViewProjection ubo_view_projection{}; @@ -955,9 +1006,20 @@ GraphicsPipeline::draw() 0.1f, 100.0f); ubo_view_projection.proj[1][1] *= -1; + ubo_view_projection.ambient_color = glm::vec4{0.25, 0.25, 0.25, 1.0}; + this->ub_view_projection[image_index].copy_data(&ubo_view_projection); } + // Update directional light uniform buffers + { + UBODirectionalLight ubo_directional_light{}; + ubo_directional_light.direction = glm::vec3{-0.57735, -0.57735, -0.57735}; + ubo_directional_light.color = glm::vec4{0.8, 0.8, 0.8, 1.0}; + + this->ub_directional_light[image_index].copy_data(&ubo_directional_light); + } + // Submit drawing command. { auto queue{this->queue_family->get_queue()}; diff --git a/src/vk/graphics_pipeline.hpp b/src/vk/graphics_pipeline.hpp index c7cc0a0..dffd6fb 100644 --- a/src/vk/graphics_pipeline.hpp +++ b/src/vk/graphics_pipeline.hpp @@ -34,7 +34,7 @@ namespace VK struct GraphicsPipeline { VkDescriptorSetLayout descriptor_set_layout_model_instance; - VkDescriptorSetLayout descriptor_set_layout_view_projection; + VkDescriptorSetLayout descriptor_set_layout_world_view; VkPipelineLayout pipeline_layout; // Depth image. @@ -44,9 +44,10 @@ struct GraphicsPipeline // FIXME: if this vector get resized, it will cause a segmentation fault! std::vector ub_view_projection; + std::vector ub_directional_light; VkDescriptorPool descriptor_pool; - std::vector view_projection_descriptor_sets; + std::vector world_view_descriptor_sets; VkRenderPass render_pass; std::vector swapchain_framebuffers; diff --git a/src/vk/uniform_buffer.hpp b/src/vk/uniform_buffer.hpp index c044699..14deead 100644 --- a/src/vk/uniform_buffer.hpp +++ b/src/vk/uniform_buffer.hpp @@ -35,6 +35,13 @@ struct UBOViewProjection { glm::mat4 view; glm::mat4 proj; + glm::vec4 ambient_color; +}; + +struct UBODirectionalLight +{ + glm::vec3 direction; + glm::vec4 color; }; // FIXME: this class need to delete or create custom copy constructors! -- cgit v1.2.3