diff --git a/examples/shadowmappingomni/shadowmappingomni.cpp b/examples/shadowmappingomni/shadowmappingomni.cpp index a99b3c1f..d3895e17 100644 --- a/examples/shadowmappingomni/shadowmappingomni.cpp +++ b/examples/shadowmappingomni/shadowmappingomni.cpp @@ -9,68 +9,56 @@ #include "vulkanexamplebase.h" #include "VulkanglTFModel.h" -// Texture properties -#define TEX_DIM 1024 -#define TEX_FILTER VK_FILTER_LINEAR - -// Offscreen frame buffer properties -#define FB_DIM TEX_DIM -#define FB_COLOR_FORMAT VK_FORMAT_R32_SFLOAT - class VulkanExample : public VulkanExampleBase { public: - bool displayCubeMap = false; + bool displayCubeMap{ false }; - float zNear = 0.1f; - float zFar = 1024.0f; + // Defines the depth range used for the shadow maps + // This should be kept as small as possible for precision + float zNear{ 0.1f }; + float zFar{ 1024.0f }; struct { vkglTF::Model scene; vkglTF::Model debugcube; } models; + glm::vec4 lightPos = glm::vec4(0.0f, -2.5f, 0.0f, 1.0); + + struct UniformData { + glm::mat4 projection; + glm::mat4 view; + glm::mat4 model; + glm::vec4 lightPos; + }; + UniformData uniformDataScene, uniformDataOffscreen; + struct { vks::Buffer scene; vks::Buffer offscreen; } uniformBuffers; struct { - glm::mat4 projection; - glm::mat4 model; - } uboVSquad; - - glm::vec4 lightPos = glm::vec4(0.0f, -2.5f, 0.0f, 1.0); - - struct UBO { - glm::mat4 projection; - glm::mat4 view; - glm::mat4 model; - glm::vec4 lightPos; - }; - - UBO uboVSscene, uboOffscreenVS; - - struct { - VkPipeline scene; - VkPipeline offscreen; - VkPipeline cubemapDisplay; + VkPipeline scene{ VK_NULL_HANDLE }; + VkPipeline offscreen{ VK_NULL_HANDLE }; + VkPipeline cubemapDisplay{ VK_NULL_HANDLE }; } pipelines; struct { - VkPipelineLayout scene; - VkPipelineLayout offscreen; + VkPipelineLayout scene{ VK_NULL_HANDLE }; + VkPipelineLayout offscreen{ VK_NULL_HANDLE }; } pipelineLayouts; struct { - VkDescriptorSet scene; - VkDescriptorSet offscreen; + VkDescriptorSet scene{ VK_NULL_HANDLE }; + VkDescriptorSet offscreen{ VK_NULL_HANDLE }; } descriptorSets; - VkDescriptorSetLayout descriptorSetLayout; + VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; vks::Texture shadowCubeMap; - std::array shadowCubeMapFaceImageViews; + std::array shadowCubeMapFaceImageViews{}; // Framebuffer for offscreen rendering struct FrameBufferAttachment { @@ -87,7 +75,12 @@ public: VkDescriptorImageInfo descriptor; } offscreenPass; - VkFormat fbDepthFormat; + // Size of the shadow map texture (per face) + const uint32_t offscreenImageSize{ 1024 }; + // We use a 32 bit float format for max. precision. Depending on the use case, lower precision may be fine and can save bandwidth + const VkFormat offscreenImageFormat{ VK_FORMAT_R32_SFLOAT }; + // The depth format is selected at runtime + VkFormat offscreenDepthFormat{ VK_FORMAT_UNDEFINED }; VulkanExample() : VulkanExampleBase() { @@ -101,59 +94,54 @@ public: ~VulkanExample() { - // Clean up used Vulkan resources - // Note : Inherited destructor cleans up resources stored in base class + if (device) { + // Cube map + for (uint32_t i = 0; i < 6; i++) { + vkDestroyImageView(device, shadowCubeMapFaceImageViews[i], nullptr); + } - // Cube map - for (uint32_t i = 0; i < 6; i++) - { - vkDestroyImageView(device, shadowCubeMapFaceImageViews[i], nullptr); + vkDestroyImageView(device, shadowCubeMap.view, nullptr); + vkDestroyImage(device, shadowCubeMap.image, nullptr); + vkDestroySampler(device, shadowCubeMap.sampler, nullptr); + vkFreeMemory(device, shadowCubeMap.deviceMemory, nullptr); + + // Depth attachment + vkDestroyImageView(device, offscreenPass.depth.view, nullptr); + vkDestroyImage(device, offscreenPass.depth.image, nullptr); + vkFreeMemory(device, offscreenPass.depth.mem, nullptr); + + for (uint32_t i = 0; i < 6; i++) + { + vkDestroyFramebuffer(device, offscreenPass.frameBuffers[i], nullptr); + } + + vkDestroyRenderPass(device, offscreenPass.renderPass, nullptr); + + // Pipelines + vkDestroyPipeline(device, pipelines.scene, nullptr); + vkDestroyPipeline(device, pipelines.offscreen, nullptr); + vkDestroyPipeline(device, pipelines.cubemapDisplay, nullptr); + + vkDestroyPipelineLayout(device, pipelineLayouts.scene, nullptr); + vkDestroyPipelineLayout(device, pipelineLayouts.offscreen, nullptr); + + vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); + + // Uniform buffers + uniformBuffers.offscreen.destroy(); + uniformBuffers.scene.destroy(); } - - vkDestroyImageView(device, shadowCubeMap.view, nullptr); - vkDestroyImage(device, shadowCubeMap.image, nullptr); - vkDestroySampler(device, shadowCubeMap.sampler, nullptr); - vkFreeMemory(device, shadowCubeMap.deviceMemory, nullptr); - - // Depth attachment - vkDestroyImageView(device, offscreenPass.depth.view, nullptr); - vkDestroyImage(device, offscreenPass.depth.image, nullptr); - vkFreeMemory(device, offscreenPass.depth.mem, nullptr); - - for (uint32_t i = 0; i < 6; i++) - { - vkDestroyFramebuffer(device, offscreenPass.frameBuffers[i], nullptr); - } - - vkDestroyRenderPass(device, offscreenPass.renderPass, nullptr); - - // Pipelines - vkDestroyPipeline(device, pipelines.scene, nullptr); - vkDestroyPipeline(device, pipelines.offscreen, nullptr); - vkDestroyPipeline(device, pipelines.cubemapDisplay, nullptr); - - vkDestroyPipelineLayout(device, pipelineLayouts.scene, nullptr); - vkDestroyPipelineLayout(device, pipelineLayouts.offscreen, nullptr); - - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - - // Uniform buffers - uniformBuffers.offscreen.destroy(); - uniformBuffers.scene.destroy(); } void prepareCubeMap() { - shadowCubeMap.width = TEX_DIM; - shadowCubeMap.height = TEX_DIM; - - // 32 bit float format for higher precision - VkFormat format = VK_FORMAT_R32_SFLOAT; + shadowCubeMap.width = offscreenImageSize; + shadowCubeMap.height = offscreenImageSize; // Cube map image description VkImageCreateInfo imageCreateInfo = vks::initializers::imageCreateInfo(); imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; - imageCreateInfo.format = format; + imageCreateInfo.format = offscreenImageFormat; imageCreateInfo.extent = { shadowCubeMap.width, shadowCubeMap.height, 1 }; imageCreateInfo.mipLevels = 1; imageCreateInfo.arrayLayers = 6; @@ -196,8 +184,8 @@ public: // Create sampler VkSamplerCreateInfo sampler = vks::initializers::samplerCreateInfo(); - sampler.magFilter = TEX_FILTER; - sampler.minFilter = TEX_FILTER; + sampler.magFilter = VK_FILTER_LINEAR; + sampler.minFilter = VK_FILTER_LINEAR; sampler.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; sampler.addressModeV = sampler.addressModeU; @@ -214,7 +202,7 @@ public: VkImageViewCreateInfo view = vks::initializers::imageViewCreateInfo(); view.image = VK_NULL_HANDLE; view.viewType = VK_IMAGE_VIEW_TYPE_CUBE; - view.format = format; + view.format = offscreenImageFormat; view.components = { VK_COMPONENT_SWIZZLE_R }; view.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; view.subresourceRange.layerCount = 6; @@ -232,20 +220,72 @@ public: } } + // Set up a separate render pass for the offscreen frame buffer + // This is necessary as the offscreen frame buffer attachments + // use formats different to the ones from the visible frame buffer + // and at least the depth one may not be compatible + void prepareOffscreenRenderpass() + { + VkAttachmentDescription osAttachments[2] = {}; + + // Find a suitable depth format for + VkBool32 validDepthFormat = vks::tools::getSupportedDepthFormat(physicalDevice, &offscreenDepthFormat); + assert(validDepthFormat); + + osAttachments[0].format = offscreenImageFormat; + osAttachments[0].samples = VK_SAMPLE_COUNT_1_BIT; + osAttachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + osAttachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; + osAttachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + osAttachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + osAttachments[0].initialLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + osAttachments[0].finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + // Depth attachment + osAttachments[1].format = offscreenDepthFormat; + osAttachments[1].samples = VK_SAMPLE_COUNT_1_BIT; + osAttachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + osAttachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE; + osAttachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + osAttachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + osAttachments[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + osAttachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + VkAttachmentReference colorReference = {}; + colorReference.attachment = 0; + colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + VkAttachmentReference depthReference = {}; + depthReference.attachment = 1; + depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + VkSubpassDescription subpass = {}; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.colorAttachmentCount = 1; + subpass.pColorAttachments = &colorReference; + subpass.pDepthStencilAttachment = &depthReference; + + VkRenderPassCreateInfo renderPassCreateInfo = vks::initializers::renderPassCreateInfo(); + renderPassCreateInfo.attachmentCount = 2; + renderPassCreateInfo.pAttachments = osAttachments; + renderPassCreateInfo.subpassCount = 1; + renderPassCreateInfo.pSubpasses = &subpass; + + VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassCreateInfo, nullptr, &offscreenPass.renderPass)); + } + // Prepare a new framebuffer for offscreen rendering // The contents of this framebuffer are then // copied to the different cube map faces void prepareOffscreenFramebuffer() { - offscreenPass.width = FB_DIM; - offscreenPass.height = FB_DIM; - - VkFormat fbColorFormat = FB_COLOR_FORMAT; + offscreenPass.width = offscreenImageSize; + offscreenPass.height = offscreenImageSize; // Color attachment VkImageCreateInfo imageCreateInfo = vks::initializers::imageCreateInfo(); imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; - imageCreateInfo.format = fbColorFormat; + imageCreateInfo.format = offscreenImageFormat; imageCreateInfo.extent.width = offscreenPass.width; imageCreateInfo.extent.height = offscreenPass.height; imageCreateInfo.extent.depth = 1; @@ -260,7 +300,7 @@ public: VkImageViewCreateInfo colorImageView = vks::initializers::imageViewCreateInfo(); colorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D; - colorImageView.format = fbColorFormat; + colorImageView.format = offscreenImageFormat; colorImageView.flags = 0; colorImageView.subresourceRange = {}; colorImageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; @@ -272,17 +312,18 @@ public: VkCommandBuffer layoutCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); // Depth stencil attachment - imageCreateInfo.format = fbDepthFormat; + imageCreateInfo.format = offscreenDepthFormat; imageCreateInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; VkImageViewCreateInfo depthStencilView = vks::initializers::imageViewCreateInfo(); depthStencilView.viewType = VK_IMAGE_VIEW_TYPE_2D; - depthStencilView.format = fbDepthFormat; + depthStencilView.format = offscreenDepthFormat; depthStencilView.flags = 0; depthStencilView.subresourceRange = {}; depthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - if (fbDepthFormat >= VK_FORMAT_D16_UNORM_S8_UINT) + if (offscreenDepthFormat >= VK_FORMAT_D16_UNORM_S8_UINT) { depthStencilView.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; + } depthStencilView.subresourceRange.baseMipLevel = 0; depthStencilView.subresourceRange.levelCount = 1; depthStencilView.subresourceRange.baseArrayLayer = 0; @@ -476,47 +517,29 @@ public: models.scene.loadFromFile(getAssetPath() + "models/shadowscene_fire.gltf", vulkanDevice, queue, glTFLoadingFlags); } - void setupDescriptorPool() + void setupDescriptors() { - // Example uses three ubos and two image samplers + // Pool std::vector poolSizes = { vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3), vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2) }; VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 3); VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - } - void setupDescriptorSetLayout() - { - // Shared pipeline layout + // Layout std::vector setLayoutBindings = { // Binding 0 : Vertex shader uniform buffer vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), // Binding 1 : Fragment shader image sampler (cube map) vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1) }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - // 3D scene pipeline layout - VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pPipelineLayoutCreateInfo, nullptr, &pipelineLayouts.scene)); - - // Offscreen pipeline layout - // Push constants for cube map face view matrices - VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(glm::mat4), 0); - // Push constant ranges are part of the pipeline layout - pPipelineLayoutCreateInfo.pushConstantRangeCount = 1; - pPipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange; - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pPipelineLayoutCreateInfo, nullptr, &pipelineLayouts.offscreen)); - } - - void setupDescriptorSets() - { + // Sets VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - + // 3D scene VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.scene)); // Image descriptor for the cube map @@ -543,62 +566,23 @@ public: vkUpdateDescriptorSets(device, static_cast(offScreenWriteDescriptorSets.size()), offScreenWriteDescriptorSets.data(), 0, nullptr); } - // Set up a separate render pass for the offscreen frame buffer - // This is necessary as the offscreen frame buffer attachments - // use formats different to the ones from the visible frame buffer - // and at least the depth one may not be compatible - void prepareOffscreenRenderpass() - { - VkAttachmentDescription osAttachments[2] = {}; - - // Find a suitable depth format - VkBool32 validDepthFormat = vks::tools::getSupportedDepthFormat(physicalDevice, &fbDepthFormat); - assert(validDepthFormat); - - osAttachments[0].format = FB_COLOR_FORMAT; - osAttachments[0].samples = VK_SAMPLE_COUNT_1_BIT; - osAttachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - osAttachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - osAttachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - osAttachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - osAttachments[0].initialLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - osAttachments[0].finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - // Depth attachment - osAttachments[1].format = fbDepthFormat; - osAttachments[1].samples = VK_SAMPLE_COUNT_1_BIT; - osAttachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - osAttachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - osAttachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - osAttachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - osAttachments[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - osAttachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkAttachmentReference colorReference = {}; - colorReference.attachment = 0; - colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - VkAttachmentReference depthReference = {}; - depthReference.attachment = 1; - depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkSubpassDescription subpass = {}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &colorReference; - subpass.pDepthStencilAttachment = &depthReference; - - VkRenderPassCreateInfo renderPassCreateInfo = vks::initializers::renderPassCreateInfo(); - renderPassCreateInfo.attachmentCount = 2; - renderPassCreateInfo.pAttachments = osAttachments; - renderPassCreateInfo.subpassCount = 1; - renderPassCreateInfo.pSubpasses = &subpass; - - VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassCreateInfo, nullptr, &offscreenPass.renderPass)); - } - void preparePipelines() { + // Layouts + // 3D scene pipeline layout + VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); + VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pPipelineLayoutCreateInfo, nullptr, &pipelineLayouts.scene)); + + // Offscreen pipeline layout + // Push constants for cube map face view matrices + VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(glm::mat4), 0); + // Push constant ranges are part of the pipeline layout + pPipelineLayoutCreateInfo.pushConstantRangeCount = 1; + pPipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange; + VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pPipelineLayoutCreateInfo, nullptr, &pipelineLayouts.offscreen)); + + + // Pipelines VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); @@ -651,45 +635,32 @@ public: void prepareUniformBuffers() { // Offscreen vertex shader uniform buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBuffers.offscreen, - sizeof(uboOffscreenVS))); - + VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.offscreen, sizeof(UniformData))); // Scene vertex shader uniform buffer - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBuffers.scene, - sizeof(uboVSscene))); - + VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffers.scene, sizeof(UniformData))); // Map persistent VK_CHECK_RESULT(uniformBuffers.offscreen.map()); VK_CHECK_RESULT(uniformBuffers.scene.map()); - - updateUniformBufferOffscreen(); - updateUniformBuffers(); } void updateUniformBuffers() { - uboVSscene.projection = camera.matrices.perspective; - uboVSscene.view = camera.matrices.view; - uboVSscene.model = glm::mat4(1.0f); - uboVSscene.lightPos = lightPos; - memcpy(uniformBuffers.scene.mapped, &uboVSscene, sizeof(uboVSscene)); + uniformDataScene.projection = camera.matrices.perspective; + uniformDataScene.view = camera.matrices.view; + uniformDataScene.model = glm::mat4(1.0f); + uniformDataScene.lightPos = lightPos; + memcpy(uniformBuffers.scene.mapped, &uniformDataScene, sizeof(UniformData)); } void updateUniformBufferOffscreen() { lightPos.x = sin(glm::radians(timer * 360.0f)) * 0.15f; lightPos.z = cos(glm::radians(timer * 360.0f)) * 0.15f; - uboOffscreenVS.projection = glm::perspective((float)(M_PI / 2.0), 1.0f, zNear, zFar); - uboOffscreenVS.view = glm::mat4(1.0f); - uboOffscreenVS.model = glm::translate(glm::mat4(1.0f), glm::vec3(-lightPos.x, -lightPos.y, -lightPos.z)); - uboOffscreenVS.lightPos = lightPos; - memcpy(uniformBuffers.offscreen.mapped, &uboOffscreenVS, sizeof(uboOffscreenVS)); + uniformDataOffscreen.projection = glm::perspective((float)(M_PI / 2.0), 1.0f, zNear, zFar); + uniformDataOffscreen.view = glm::mat4(1.0f); + uniformDataOffscreen.model = glm::translate(glm::mat4(1.0f), glm::vec3(-lightPos.x, -lightPos.y, -lightPos.z)); + uniformDataOffscreen.lightPos = lightPos; + memcpy(uniformBuffers.offscreen.mapped, &uniformDataOffscreen, sizeof(UniformData)); } void draw() @@ -707,11 +678,9 @@ public: loadAssets(); prepareUniformBuffers(); prepareCubeMap(); - setupDescriptorSetLayout(); + setupDescriptors(); prepareOffscreenRenderpass(); preparePipelines(); - setupDescriptorPool(); - setupDescriptorSets(); prepareOffscreenFramebuffer(); buildCommandBuffers(); prepared = true; @@ -721,12 +690,9 @@ public: { if (!prepared) return; + updateUniformBuffers(); + updateUniformBufferOffscreen(); draw(); - if (!paused || camera.updated) - { - updateUniformBufferOffscreen(); - updateUniformBuffers(); - } } virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay)