summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrederico Linhares <fred@linhares.blue>2022-08-11 15:46:36 -0300
committerFrederico Linhares <fred@linhares.blue>2022-08-16 16:22:19 -0300
commiteb6fc926be7f29d6d92f238146180d510d69c79e (patch)
treefd619189a699b2a2d6f80b36aa5dbc1f2a0f0f57
parentb8838794e135c1b849ac7a8638ca8e948042ef86 (diff)
feat Create directional light
-rw-r--r--glsl/shader.frag34
-rw-r--r--glsl/shader.vert28
-rw-r--r--src/vk/graphics_pipeline.cpp170
-rw-r--r--src/vk/graphics_pipeline.hpp5
-rw-r--r--src/vk/uniform_buffer.hpp7
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<VK::GraphicsPipeline*>(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<VkDescriptorSetLayoutBinding, 2> 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<VK::GraphicsPipeline*>(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<VK::GraphicsPipeline*>(obj);
std::array<VkDescriptorSetLayout, 2> 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<VK::GraphicsPipeline*>(obj);
@@ -159,7 +164,7 @@ load_uniform_buffer(void *obj)
}
void
-unload_uniform_buffer(void *obj)
+unload_view_projection_uniform_buffer(void *obj)
{
auto self = static_cast<VK::GraphicsPipeline*>(obj);
@@ -167,19 +172,47 @@ unload_uniform_buffer(void *obj)
}
void
+load_directional_light_uniform_buffer(void *obj)
+{
+ auto self = static_cast<VK::GraphicsPipeline*>(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<VK::GraphicsPipeline*>(obj);
+
+ self->ub_directional_light.clear();
+}
+
+void
load_descriptor_pool(void *obj)
{
auto self = static_cast<VK::GraphicsPipeline*>(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<VK::GraphicsPipeline*>(obj);
std::vector<VkDescriptorSetLayout> 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<VK::GraphicsPipeline*>(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<VkWriteDescriptorSet, 2> 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<VkDescriptorSet, 2> 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<UniformBuffer> ub_view_projection;
+ std::vector<UniformBuffer> ub_directional_light;
VkDescriptorPool descriptor_pool;
- std::vector<VkDescriptorSet> view_projection_descriptor_sets;
+ std::vector<VkDescriptorSet> world_view_descriptor_sets;
VkRenderPass render_pass;
std::vector<VkFramebuffer> 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!