Use specialization consts for blur direction, full screen quad generated by vertex shader, code cleanup

This commit is contained in:
saschawillems 2017-01-07 19:25:04 +01:00
parent c4e50f76ee
commit 6e19ea926a
3 changed files with 172 additions and 231 deletions

View file

@ -50,7 +50,6 @@ public:
vkMeshLoader::MeshBuffer ufo; vkMeshLoader::MeshBuffer ufo;
vkMeshLoader::MeshBuffer ufoGlow; vkMeshLoader::MeshBuffer ufoGlow;
vkMeshLoader::MeshBuffer skyBox; vkMeshLoader::MeshBuffer skyBox;
vkMeshLoader::MeshBuffer quad;
} meshes; } meshes;
struct { struct {
@ -60,27 +59,25 @@ public:
} vertices; } vertices;
struct { struct {
vk::Buffer vsScene; vk::Buffer scene;
vk::Buffer vsFullScreen; vk::Buffer skyBox;
vk::Buffer vsSkyBox; vk::Buffer blurParams;
vk::Buffer fsVertBlur;
vk::Buffer fsHorzBlur;
} uniformBuffers; } uniformBuffers;
struct UBO { struct UBO {
glm::mat4 projection; glm::mat4 projection;
glm::mat4 view;
glm::mat4 model; glm::mat4 model;
}; };
struct UBOBlur { struct UBOBlurParams {
float blurScale = 1.0f; float blurScale = 1.0f;
float blurStrength = 1.5f; float blurStrength = 1.5f;
uint32_t horizontal;
}; };
struct { struct {
UBO scene, fullscreen, skyBox; UBO scene, skyBox;
UBOBlur vertBlur, horzBlur; UBOBlurParams blurParams;
} ubos; } ubos;
struct { struct {
@ -91,18 +88,22 @@ public:
VkPipeline skyBox; VkPipeline skyBox;
} pipelines; } pipelines;
// Pipeline layout is shared amongst all descriptor sets struct {
VkPipelineLayout pipelineLayout; VkPipelineLayout blur;
VkPipelineLayout scene;
} pipelineLayouts;
struct { struct {
VkDescriptorSet blurVert;
VkDescriptorSet blurHorz;
VkDescriptorSet scene; VkDescriptorSet scene;
VkDescriptorSet verticalBlur;
VkDescriptorSet horizontalBlur;
VkDescriptorSet skyBox; VkDescriptorSet skyBox;
} descriptorSets; } descriptorSets;
// Descriptor set layout is shared amongst all descriptor sets struct {
VkDescriptorSetLayout descriptorSetLayout; VkDescriptorSetLayout blur;
VkDescriptorSetLayout scene;
} descriptorSetLayouts;
// Framebuffer for offscreen rendering // Framebuffer for offscreen rendering
struct FrameBufferAttachment { struct FrameBufferAttachment {
@ -127,11 +128,13 @@ public:
VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION) VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION)
{ {
zoom = -10.25f; title = "Vulkan Example - Bloom";
rotation = { 7.5f, -343.0f, 0.0f };
timerSpeed *= 0.5f; timerSpeed *= 0.5f;
enableTextOverlay = true; enableTextOverlay = true;
title = "Vulkan Example - Bloom"; camera.type = Camera::CameraType::lookat;
camera.setPosition(glm::vec3(0.0f, 0.0f, -10.25f));
camera.setRotation(glm::vec3(7.5f, -343.0f, 0.0f));
camera.setPerspective(45.0f, (float)width / (float)height, 0.1f, 256.0f);
} }
~VulkanExample() ~VulkanExample()
@ -164,22 +167,21 @@ public:
vkDestroyPipeline(device, pipelines.glowPass, nullptr); vkDestroyPipeline(device, pipelines.glowPass, nullptr);
vkDestroyPipeline(device, pipelines.skyBox, nullptr); vkDestroyPipeline(device, pipelines.skyBox, nullptr);
vkDestroyPipelineLayout(device, pipelineLayout, nullptr); vkDestroyPipelineLayout(device, pipelineLayouts.blur , nullptr);
vkDestroyPipelineLayout(device, pipelineLayouts.scene, nullptr);
vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.blur, nullptr);
vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.scene, nullptr);
// Meshes // Meshes
vkMeshLoader::freeMeshBufferResources(device, &meshes.ufo); vkMeshLoader::freeMeshBufferResources(device, &meshes.ufo);
vkMeshLoader::freeMeshBufferResources(device, &meshes.ufoGlow); vkMeshLoader::freeMeshBufferResources(device, &meshes.ufoGlow);
vkMeshLoader::freeMeshBufferResources(device, &meshes.skyBox); vkMeshLoader::freeMeshBufferResources(device, &meshes.skyBox);
vkMeshLoader::freeMeshBufferResources(device, &meshes.quad);
// Uniform buffers // Uniform buffers
uniformBuffers.vsScene.destroy(); uniformBuffers.scene.destroy();
uniformBuffers.vsFullScreen.destroy(); uniformBuffers.skyBox.destroy();
uniformBuffers.vsSkyBox.destroy(); uniformBuffers.blurParams.destroy();
uniformBuffers.fsVertBlur.destroy();
uniformBuffers.fsHorzBlur.destroy();
textureLoader->destroyTexture(textures.cubemap); textureLoader->destroyTexture(textures.cubemap);
} }
@ -409,7 +411,7 @@ public:
vkCmdBeginRenderPass(offscreenPass.commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); vkCmdBeginRenderPass(offscreenPass.commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindDescriptorSets(offscreenPass.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.scene, 0, NULL); vkCmdBindDescriptorSets(offscreenPass.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.scene, 0, 1, &descriptorSets.scene, 0, NULL);
vkCmdBindPipeline(offscreenPass.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.glowPass); vkCmdBindPipeline(offscreenPass.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.glowPass);
VkDeviceSize offsets[1] = { 0 }; VkDeviceSize offsets[1] = { 0 };
@ -427,12 +429,9 @@ public:
vkCmdBeginRenderPass(offscreenPass.commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); vkCmdBeginRenderPass(offscreenPass.commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
// Draw horizontally blurred texture vkCmdBindDescriptorSets(offscreenPass.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.blur, 0, 1, &descriptorSets.blurVert, 0, NULL);
vkCmdBindDescriptorSets(offscreenPass.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.verticalBlur, 0, NULL);
vkCmdBindPipeline(offscreenPass.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.blurVert); vkCmdBindPipeline(offscreenPass.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.blurVert);
vkCmdBindVertexBuffers(offscreenPass.commandBuffer, VERTEX_BUFFER_BIND_ID, 1, &meshes.quad.vertices.buf, offsets); vkCmdDraw(offscreenPass.commandBuffer, 3, 1, 0, 0);
vkCmdBindIndexBuffer(offscreenPass.commandBuffer, meshes.quad.indices.buf, 0, VK_INDEX_TYPE_UINT32);
vkCmdDrawIndexed(offscreenPass.commandBuffer, meshes.quad.indexCount, 1, 0, 0, 0);
vkCmdEndRenderPass(offscreenPass.commandBuffer); vkCmdEndRenderPass(offscreenPass.commandBuffer);
@ -484,7 +483,7 @@ public:
VkDeviceSize offsets[1] = { 0 }; VkDeviceSize offsets[1] = { 0 };
// Skybox // Skybox
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.skyBox, 0, NULL); vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.scene, 0, 1, &descriptorSets.skyBox, 0, NULL);
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.skyBox); vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.skyBox);
vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, &meshes.skyBox.vertices.buf, offsets); vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, &meshes.skyBox.vertices.buf, offsets);
@ -492,7 +491,7 @@ public:
vkCmdDrawIndexed(drawCmdBuffers[i], meshes.skyBox.indexCount, 1, 0, 0, 0); vkCmdDrawIndexed(drawCmdBuffers[i], meshes.skyBox.indexCount, 1, 0, 0, 0);
// 3D scene // 3D scene
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.scene, 0, NULL); vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.scene, 0, 1, &descriptorSets.scene, 0, NULL);
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.phongPass); vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.phongPass);
vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, &meshes.ufo.vertices.buf, offsets); vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, &meshes.ufo.vertices.buf, offsets);
@ -504,11 +503,9 @@ public:
// ------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------
if (bloom) if (bloom)
{ {
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.horizontalBlur, 0, NULL); vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.blur, 0, 1, &descriptorSets.blurHorz, 0, NULL);
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.blurHorz); vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.blurHorz);
vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, &meshes.quad.vertices.buf, offsets); vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0);
vkCmdBindIndexBuffer(drawCmdBuffers[i], meshes.quad.indices.buf, 0, VK_INDEX_TYPE_UINT32);
vkCmdDrawIndexed(drawCmdBuffers[i], meshes.quad.indexCount, 1, 0, 0, 0);
} }
vkCmdEndRenderPass(drawCmdBuffers[i]); vkCmdEndRenderPass(drawCmdBuffers[i]);
@ -530,45 +527,6 @@ public:
textureLoader->loadCubemap(getAssetPath() + "textures/cubemap_space.ktx", VK_FORMAT_R8G8B8A8_UNORM, &textures.cubemap); textureLoader->loadCubemap(getAssetPath() + "textures/cubemap_space.ktx", VK_FORMAT_R8G8B8A8_UNORM, &textures.cubemap);
} }
// Setup vertices for a single uv-mapped quad
void generateQuad()
{
struct Vertex {
float pos[3];
float uv[2];
float col[3];
float normal[3];
};
#define QUAD_COLOR_NORMAL { 1.0f, 1.0f, 1.0f }, { 0.0f, 0.0f, 1.0f }
std::vector<Vertex> vertexBuffer =
{
{ { 1.0f, 1.0f, 0.0f },{ 1.0f, 1.0f }, QUAD_COLOR_NORMAL },
{ { 0.0f, 1.0f, 0.0f },{ 0.0f, 1.0f }, QUAD_COLOR_NORMAL },
{ { 0.0f, 0.0f, 0.0f },{ 0.0f, 0.0f }, QUAD_COLOR_NORMAL },
{ { 1.0f, 0.0f, 0.0f },{ 1.0f, 0.0f }, QUAD_COLOR_NORMAL }
};
#undef QUAD_COLOR_NORMAL
createBuffer(
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
vertexBuffer.size() * sizeof(Vertex),
vertexBuffer.data(),
&meshes.quad.vertices.buf,
&meshes.quad.vertices.mem);
// Setup indices
std::vector<uint32_t> indexBuffer = { 0,1,2, 2,3,0 };
meshes.quad.indexCount = indexBuffer.size();
createBuffer(
VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
indexBuffer.size() * sizeof(uint32_t),
indexBuffer.data(),
&meshes.quad.indices.buf,
&meshes.quad.indices.mem);
}
void setupVertexDescriptions() void setupVertexDescriptions()
{ {
// Binding description // Binding description
@ -637,97 +595,69 @@ public:
void setupDescriptorSetLayout() void setupDescriptorSetLayout()
{ {
// Textured quad pipeline layout std::vector<VkDescriptorSetLayoutBinding> setLayoutBindings;
VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo;
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo;
std::vector<VkDescriptorSetLayoutBinding> setLayoutBindings = // Fullscreen blur
{ setLayoutBindings = {
// Binding 0 : Vertex shader uniform buffer vkTools::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 0), // Binding 0: Fragment shader uniform buffer
vkTools::initializers::descriptorSetLayoutBinding( vkTools::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1) // Binding 1: Fragment shader image sampler
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, };
VK_SHADER_STAGE_VERTEX_BIT, descriptorSetLayoutCreateInfo = vkTools::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings.data(), static_cast<uint32_t>(setLayoutBindings.size()));
0), VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCreateInfo, nullptr, &descriptorSetLayouts.blur));
// Binding 1 : Fragment shader image sampler pipelineLayoutCreateInfo = vkTools::initializers::pipelineLayoutCreateInfo(&descriptorSetLayouts.blur, 1);
vkTools::initializers::descriptorSetLayoutBinding( VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayouts.blur));
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
VK_SHADER_STAGE_FRAGMENT_BIT, // Scene rendering
1), setLayoutBindings = {
// Binding 2 : Framgnet shader image sampler vkTools::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), // Binding 0 : Vertex shader uniform buffer
vkTools::initializers::descriptorSetLayoutBinding( vkTools::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), // Binding 1 : Fragment shader image sampler
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vkTools::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 2), // Binding 2 : Framgnet shader image sampler
VK_SHADER_STAGE_FRAGMENT_BIT,
2),
}; };
VkDescriptorSetLayoutCreateInfo descriptorLayout = descriptorSetLayoutCreateInfo = vkTools::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings.data(), setLayoutBindings.size());
vkTools::initializers::descriptorSetLayoutCreateInfo( VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCreateInfo, nullptr, &descriptorSetLayouts.scene));
setLayoutBindings.data(), pipelineLayoutCreateInfo = vkTools::initializers::pipelineLayoutCreateInfo(&descriptorSetLayouts.scene, 1);
setLayoutBindings.size()); VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayouts.scene));
VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout));
VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo =
vkTools::initializers::pipelineLayoutCreateInfo(
&descriptorSetLayout,
1);
VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pPipelineLayoutCreateInfo, nullptr, &pipelineLayout));
} }
void setupDescriptorSet() void setupDescriptorSet()
{ {
VkDescriptorSetAllocateInfo allocInfo = VkDescriptorSetAllocateInfo descriptorSetAllocInfo;
vkTools::initializers::descriptorSetAllocateInfo(
descriptorPool,
&descriptorSetLayout,
1);
std::vector<VkWriteDescriptorSet> writeDescriptorSets; std::vector<VkWriteDescriptorSet> writeDescriptorSets;
// Full screen blur descriptor sets // Full screen blur
// Vertical
// Vertical blur descriptorSetAllocInfo = vkTools::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.blur, 1);
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.verticalBlur)); VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorSetAllocInfo, &descriptorSets.blurVert));
writeDescriptorSets = writeDescriptorSets = {
{ vkTools::initializers::writeDescriptorSet(descriptorSets.blurVert, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.blurParams.descriptor), // Binding 0: Fragment shader uniform buffer
// Binding 0: Vertex shader uniform buffer vkTools::initializers::writeDescriptorSet(descriptorSets.blurVert, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &offscreenPass.framebuffers[0].descriptor), // Binding 1: Fragment shader texture sampler
vkTools::initializers::writeDescriptorSet(descriptorSets.verticalBlur, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.vsScene.descriptor), };
// Binding 1: Fragment shader texture sampler vkUpdateDescriptorSets(device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, NULL);
vkTools::initializers::writeDescriptorSet(descriptorSets.verticalBlur, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &offscreenPass.framebuffers[0].descriptor), // Horizontal
// Binding 2: Fragment shader uniform buffer descriptorSetAllocInfo = vkTools::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.blur, 1);
vkTools::initializers::writeDescriptorSet(descriptorSets.verticalBlur, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2, &uniformBuffers.fsVertBlur.descriptor) VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorSetAllocInfo, &descriptorSets.blurHorz));
writeDescriptorSets = {
vkTools::initializers::writeDescriptorSet(descriptorSets.blurHorz, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.blurParams.descriptor), // Binding 0: Fragment shader uniform buffer
vkTools::initializers::writeDescriptorSet(descriptorSets.blurHorz, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &offscreenPass.framebuffers[1].descriptor), // Binding 1: Fragment shader texture sampler
}; };
vkUpdateDescriptorSets(device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, NULL); vkUpdateDescriptorSets(device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, NULL);
// Horizontal blur // Scene rendering
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.horizontalBlur)); descriptorSetAllocInfo = vkTools::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.scene, 1);
writeDescriptorSets = VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorSetAllocInfo, &descriptorSets.scene));
{ writeDescriptorSets = {
// Binding 0: Vertex shader uniform buffer vkTools::initializers::writeDescriptorSet(descriptorSets.scene, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.scene.descriptor) // Binding 0: Vertex shader uniform buffer
vkTools::initializers::writeDescriptorSet(descriptorSets.horizontalBlur, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.vsScene.descriptor),
// Binding 1: Fragment shader texture sampler
vkTools::initializers::writeDescriptorSet(descriptorSets.horizontalBlur, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &offscreenPass.framebuffers[1].descriptor),
// Binding 2: Fragment shader uniform buffer
vkTools::initializers::writeDescriptorSet(descriptorSets.horizontalBlur, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2, &uniformBuffers.fsHorzBlur.descriptor)
};
vkUpdateDescriptorSets(device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, NULL);
// 3D scene
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.scene));
writeDescriptorSets =
{
// Binding 0: Vertex shader uniform buffer
vkTools::initializers::writeDescriptorSet(descriptorSets.scene, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.vsFullScreen.descriptor)
}; };
vkUpdateDescriptorSets(device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, NULL); vkUpdateDescriptorSets(device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, NULL);
// Skybox // Skybox
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.skyBox)); VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorSetAllocInfo, &descriptorSets.skyBox));
writeDescriptorSets = writeDescriptorSets = {
{ vkTools::initializers::writeDescriptorSet(descriptorSets.skyBox, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.skyBox.descriptor), // Binding 0: Vertex shader uniform buffer
// Binding 0: Vertex shader uniform buffer vkTools::initializers::writeDescriptorSet(descriptorSets.skyBox, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textures.cubemap.descriptor), // Binding 1: Fragment shader texture sampler
vkTools::initializers::writeDescriptorSet(descriptorSets.skyBox, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.vsSkyBox.descriptor),
// Binding 1: Fragment shader texture sampler
vkTools::initializers::writeDescriptorSet(descriptorSets.skyBox, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textures.cubemap.descriptor),
}; };
vkUpdateDescriptorSets(device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, NULL); vkUpdateDescriptorSets(device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, NULL);
} }
@ -783,18 +713,12 @@ public:
std::array<VkPipelineShaderStageCreateInfo, 2> shaderStages; std::array<VkPipelineShaderStageCreateInfo, 2> shaderStages;
// Vertical gauss blur
// Load shaders
shaderStages[0] = loadShader(getAssetPath() + "shaders/bloom/gaussblur.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
shaderStages[1] = loadShader(getAssetPath() + "shaders/bloom/gaussblur.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
VkGraphicsPipelineCreateInfo pipelineCreateInfo = VkGraphicsPipelineCreateInfo pipelineCreateInfo =
vkTools::initializers::pipelineCreateInfo( vkTools::initializers::pipelineCreateInfo(
pipelineLayout, pipelineLayouts.blur,
renderPass, renderPass,
0); 0);
pipelineCreateInfo.pVertexInputState = &vertices.inputState;
pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState; pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState;
pipelineCreateInfo.pRasterizationState = &rasterizationState; pipelineCreateInfo.pRasterizationState = &rasterizationState;
pipelineCreateInfo.pColorBlendState = &colorBlendState; pipelineCreateInfo.pColorBlendState = &colorBlendState;
@ -805,6 +729,13 @@ public:
pipelineCreateInfo.stageCount = shaderStages.size(); pipelineCreateInfo.stageCount = shaderStages.size();
pipelineCreateInfo.pStages = shaderStages.data(); pipelineCreateInfo.pStages = shaderStages.data();
// Blur pipelines
shaderStages[0] = loadShader(getAssetPath() + "shaders/bloom/gaussblur.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
shaderStages[1] = loadShader(getAssetPath() + "shaders/bloom/gaussblur.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
// Empty vertex input state
VkPipelineVertexInputStateCreateInfo emptyInputState = vkTools::initializers::pipelineVertexInputStateCreateInfo();
pipelineCreateInfo.pVertexInputState = &emptyInputState;
pipelineCreateInfo.layout = pipelineLayouts.blur;
// Additive blending // Additive blending
blendAttachmentState.colorWriteMask = 0xF; blendAttachmentState.colorWriteMask = 0xF;
blendAttachmentState.blendEnable = VK_TRUE; blendAttachmentState.blendEnable = VK_TRUE;
@ -815,12 +746,22 @@ public:
blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_DST_ALPHA; blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_DST_ALPHA;
// Use specialization constants to select between horizontal and vertical blur
uint32_t blurdirection = 0;
VkSpecializationMapEntry specializationMapEntry = vkTools::initializers::specializationMapEntry(0, 0, sizeof(uint32_t));
VkSpecializationInfo specializationInfo = vkTools::initializers::specializationInfo(1, &specializationMapEntry, sizeof(uint32_t), &blurdirection);
shaderStages[1].pSpecializationInfo = &specializationInfo;
// Vertical blur pipeline
pipelineCreateInfo.renderPass = offscreenPass.renderPass; pipelineCreateInfo.renderPass = offscreenPass.renderPass;
VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.blurVert)); VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.blurVert));
// Horizontal blur pipeline
blurdirection = 1;
pipelineCreateInfo.renderPass = renderPass; pipelineCreateInfo.renderPass = renderPass;
VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.blurHorz)); VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.blurHorz));
// Phong pass (3D model) // Phong pass (3D model)
pipelineCreateInfo.layout = pipelineLayouts.scene;
pipelineCreateInfo.pVertexInputState = &vertices.inputState;
shaderStages[0] = loadShader(getAssetPath() + "shaders/bloom/phongpass.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); shaderStages[0] = loadShader(getAssetPath() + "shaders/bloom/phongpass.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
shaderStages[1] = loadShader(getAssetPath() + "shaders/bloom/phongpass.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); shaderStages[1] = loadShader(getAssetPath() + "shaders/bloom/phongpass.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
blendAttachmentState.blendEnable = VK_FALSE; blendAttachmentState.blendEnable = VK_FALSE;
@ -851,94 +792,58 @@ public:
VK_CHECK_RESULT(vulkanDevice->createBuffer( VK_CHECK_RESULT(vulkanDevice->createBuffer(
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
&uniformBuffers.vsScene, &uniformBuffers.scene,
sizeof(ubos.scene))); sizeof(ubos.scene)));
// Fullscreen quad display vertex shader uniform buffer // Blur parameters uniform buffers
VK_CHECK_RESULT(vulkanDevice->createBuffer( VK_CHECK_RESULT(vulkanDevice->createBuffer(
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
&uniformBuffers.vsFullScreen, &uniformBuffers.blurParams,
sizeof(ubos.fullscreen))); sizeof(ubos.blurParams)));
// Fullscreen quad fragment shader uniform buffers
// Vertical blur
VK_CHECK_RESULT(vulkanDevice->createBuffer(
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
&uniformBuffers.fsVertBlur,
sizeof(ubos.vertBlur)));
// Horizontal blur
VK_CHECK_RESULT(vulkanDevice->createBuffer(
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
&uniformBuffers.fsHorzBlur,
sizeof(ubos.horzBlur)));
// Skybox // Skybox
VK_CHECK_RESULT(vulkanDevice->createBuffer( VK_CHECK_RESULT(vulkanDevice->createBuffer(
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
&uniformBuffers.vsSkyBox, &uniformBuffers.skyBox,
sizeof(ubos.skyBox))); sizeof(ubos.skyBox)));
// Map persistent // Map persistent
VK_CHECK_RESULT(uniformBuffers.vsScene.map()); VK_CHECK_RESULT(uniformBuffers.scene.map());
VK_CHECK_RESULT(uniformBuffers.vsFullScreen.map()); VK_CHECK_RESULT(uniformBuffers.blurParams.map());
VK_CHECK_RESULT(uniformBuffers.fsVertBlur.map()); VK_CHECK_RESULT(uniformBuffers.skyBox.map());
VK_CHECK_RESULT(uniformBuffers.fsHorzBlur.map());
VK_CHECK_RESULT(uniformBuffers.vsSkyBox.map());
// Intialize uniform buffers // Intialize uniform buffers
updateUniformBuffersScene(); updateUniformBuffersScene();
updateUniformBuffersScreen(); updateUniformBuffersBlur();
} }
// Update uniform buffers for rendering the 3D scene // Update uniform buffers for rendering the 3D scene
void updateUniformBuffersScene() void updateUniformBuffersScene()
{ {
// UFO // UFO
ubos.fullscreen.projection = glm::perspective(glm::radians(45.0f), (float)width / (float)height, 0.1f, 256.0f); ubos.scene.projection = camera.matrices.perspective;
glm::mat4 viewMatrix = glm::translate(glm::mat4(), glm::vec3(0.0f, -1.0f, zoom)); ubos.scene.view = camera.matrices.view;
ubos.fullscreen.model = viewMatrix * ubos.scene.model = glm::translate(glm::mat4(), glm::vec3(sin(glm::radians(timer * 360.0f)) * 0.25f, -1.0f, cos(glm::radians(timer * 360.0f)) * 0.25f) + cameraPos);
glm::translate(glm::mat4(), glm::vec3(sin(glm::radians(timer * 360.0f)) * 0.25f, 0.0f, cos(glm::radians(timer * 360.0f)) * 0.25f) + cameraPos); ubos.scene.model = glm::rotate(ubos.scene.model, -sinf(glm::radians(timer * 360.0f)) * 0.15f, glm::vec3(1.0f, 0.0f, 0.0f));
ubos.scene.model = glm::rotate(ubos.scene.model, glm::radians(timer * 360.0f), glm::vec3(0.0f, 1.0f, 0.0f));
ubos.fullscreen.model = glm::rotate(ubos.fullscreen.model, glm::radians(rotation.x), glm::vec3(1.0f, 0.0f, 0.0f)); memcpy(uniformBuffers.scene.mapped, &ubos.scene, sizeof(ubos.scene));
ubos.fullscreen.model = glm::rotate(ubos.fullscreen.model, -sinf(glm::radians(timer * 360.0f)) * 0.15f, glm::vec3(1.0f, 0.0f, 0.0f));
ubos.fullscreen.model = glm::rotate(ubos.fullscreen.model, glm::radians(rotation.y), glm::vec3(0.0f, 1.0f, 0.0f));
ubos.fullscreen.model = glm::rotate(ubos.fullscreen.model, glm::radians(timer * 360.0f), glm::vec3(0.0f, 1.0f, 0.0f));
ubos.fullscreen.model = glm::rotate(ubos.fullscreen.model, glm::radians(rotation.z), glm::vec3(0.0f, 0.0f, 1.0f));
memcpy(uniformBuffers.vsFullScreen.mapped, &ubos.fullscreen, sizeof(ubos.fullscreen));
// Skybox // Skybox
ubos.skyBox.projection = glm::perspective(glm::radians(45.0f), (float)width / (float)height, 0.1f, 256.0f); ubos.skyBox.projection = glm::perspective(glm::radians(45.0f), (float)width / (float)height, 0.1f, 256.0f);
ubos.skyBox.view = glm::mat4(glm::mat3(camera.matrices.view));
ubos.skyBox.model = glm::mat4(); ubos.skyBox.model = glm::mat4();
ubos.skyBox.model = glm::rotate(ubos.skyBox.model, glm::radians(rotation.x), glm::vec3(1.0f, 0.0f, 0.0f));
ubos.skyBox.model = glm::rotate(ubos.skyBox.model, glm::radians(rotation.y), glm::vec3(0.0f, 1.0f, 0.0f));
ubos.skyBox.model = glm::rotate(ubos.skyBox.model, glm::radians(rotation.z), glm::vec3(0.0f, 0.0f, 1.0f));
memcpy(uniformBuffers.vsSkyBox.mapped, &ubos.skyBox, sizeof(ubos.skyBox)); memcpy(uniformBuffers.skyBox.mapped, &ubos.skyBox, sizeof(ubos.skyBox));
} }
// Update uniform buffers for the fullscreen quad // Update blur pass parameter uniform buffer
void updateUniformBuffersScreen() void updateUniformBuffersBlur()
{ {
// Vertex shader memcpy(uniformBuffers.blurParams.mapped, &ubos.blurParams, sizeof(ubos.blurParams));
ubos.scene.projection = glm::ortho(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f);
ubos.scene.model = glm::mat4();
memcpy(uniformBuffers.vsScene.mapped, &ubos.scene, sizeof(ubos.scene));
// Fragment shader
// Vertical
ubos.vertBlur.horizontal = 0;
memcpy(uniformBuffers.fsVertBlur.mapped, &ubos.vertBlur, sizeof(ubos.vertBlur));
// Horizontal
ubos.horzBlur.horizontal = 1;
memcpy(uniformBuffers.fsHorzBlur.mapped, &ubos.horzBlur, sizeof(ubos.horzBlur));
} }
void draw() void draw()
@ -981,7 +886,6 @@ public:
{ {
VulkanExampleBase::prepare(); VulkanExampleBase::prepare();
loadAssets(); loadAssets();
generateQuad();
setupVertexDescriptions(); setupVertexDescriptions();
prepareUniformBuffers(); prepareUniformBuffers();
prepareOffscreen(); prepareOffscreen();
@ -1007,7 +911,18 @@ public:
virtual void viewChanged() virtual void viewChanged()
{ {
updateUniformBuffersScene(); updateUniformBuffersScene();
updateUniformBuffersScreen(); }
void changeBlurScale(float delta)
{
ubos.blurParams.blurScale += delta;
updateUniformBuffersBlur();
}
void toggleBloom()
{
bloom = !bloom;
reBuildCommandBuffers();
} }
virtual void keyPressed(uint32_t keyCode) virtual void keyPressed(uint32_t keyCode)
@ -1039,19 +954,6 @@ public:
textOverlay->addText("Press \"B\" to toggle bloom", 5.0f, 105.0f, VulkanTextOverlay::alignLeft); textOverlay->addText("Press \"B\" to toggle bloom", 5.0f, 105.0f, VulkanTextOverlay::alignLeft);
#endif #endif
} }
void changeBlurScale(float delta)
{
ubos.vertBlur.blurScale += delta;
ubos.horzBlur.blurScale += delta;
updateUniformBuffersScreen();
}
void toggleBloom()
{
bloom = !bloom;
reBuildCommandBuffers();
}
}; };
VULKAN_EXAMPLE_MAIN() VULKAN_EXAMPLE_MAIN()

View file

@ -89,6 +89,16 @@
<ClInclude Include="..\base\vulkanexamplebase.h" /> <ClInclude Include="..\base\vulkanexamplebase.h" />
<ClInclude Include="..\base\vulkantools.h" /> <ClInclude Include="..\base\vulkantools.h" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Include="..\data\shaders\bloom\colorpass.frag" />
<None Include="..\data\shaders\bloom\colorpass.vert" />
<None Include="..\data\shaders\bloom\gaussblur.frag" />
<None Include="..\data\shaders\bloom\gaussblur.vert" />
<None Include="..\data\shaders\bloom\phongpass.frag" />
<None Include="..\data\shaders\bloom\phongpass.vert" />
<None Include="..\data\shaders\bloom\skybox.frag" />
<None Include="..\data\shaders\bloom\skybox.vert" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">
</ImportGroup> </ImportGroup>

View file

@ -13,6 +13,9 @@
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter> </Filter>
<Filter Include="Shaders">
<UniqueIdentifier>{9db52377-7306-4ab6-9a34-f1eed864f8c6}</UniqueIdentifier>
</Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\base\vulkandebug.cpp"> <ClCompile Include="..\base\vulkandebug.cpp">
@ -39,4 +42,30 @@
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Include="..\data\shaders\bloom\colorpass.frag">
<Filter>Shaders</Filter>
</None>
<None Include="..\data\shaders\bloom\colorpass.vert">
<Filter>Shaders</Filter>
</None>
<None Include="..\data\shaders\bloom\gaussblur.frag">
<Filter>Shaders</Filter>
</None>
<None Include="..\data\shaders\bloom\gaussblur.vert">
<Filter>Shaders</Filter>
</None>
<None Include="..\data\shaders\bloom\phongpass.frag">
<Filter>Shaders</Filter>
</None>
<None Include="..\data\shaders\bloom\phongpass.vert">
<Filter>Shaders</Filter>
</None>
<None Include="..\data\shaders\bloom\skybox.frag">
<Filter>Shaders</Filter>
</None>
<None Include="..\data\shaders\bloom\skybox.vert">
<Filter>Shaders</Filter>
</None>
</ItemGroup>
</Project> </Project>