#include "shadowpass.h" #include #include #include "renderer.h" #include "world.h" #include "mesh.h" #include "light.h" ShadowPass::ShadowPass(Renderer& renderer) : renderer_(renderer) { createRenderPass(); createFramebuffer(); createPipeline(); } ShadowPass::~ShadowPass() { vkDestroyPipeline(renderer_.getDevice(), pipeline_, nullptr); vkDestroyPipelineLayout(renderer_.getDevice(), pipelineLayout_, nullptr); vkDestroySampler(renderer_.getDevice(), shadowSampler_, nullptr); vkDestroyFramebuffer(renderer_.getDevice(), shadowFramebuffer_, nullptr); vkDestroyImageView(renderer_.getDevice(), shadowImageView_, nullptr); vkFreeMemory(renderer_.getDevice(), shadowMemory_, nullptr); vkDestroyImage(renderer_.getDevice(), shadowImage_, nullptr); vkDestroyRenderPass(renderer_.getDevice(), renderPass_, nullptr); } void ShadowPass::render(VkCommandBuffer commandBuffer, World& world) { VkViewport viewport = {}; viewport.width = renderer_.getConfig().shadowResolution; viewport.height = renderer_.getConfig().shadowResolution; viewport.maxDepth = 1.0f; vkCmdSetViewport(commandBuffer, 0, 1, &viewport); VkRect2D scissor = {}; scissor.extent.width = renderer_.getConfig().shadowResolution; scissor.extent.height = renderer_.getConfig().shadowResolution; vkCmdSetScissor(commandBuffer, 0, 1, &scissor); VkClearValue clearColor = {}; clearColor.depthStencil.depth = 1.0f; VkRenderPassBeginInfo renderPassBeginInfo = {}; renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; renderPassBeginInfo.framebuffer = shadowFramebuffer_; renderPassBeginInfo.renderPass = renderPass_; renderPassBeginInfo.renderArea.extent.width = renderer_.getConfig().shadowResolution; renderPassBeginInfo.renderArea.extent.height = renderer_.getConfig().shadowResolution; renderPassBeginInfo.clearValueCount = 1; renderPassBeginInfo.pClearValues = &clearColor; vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_); glm::mat4 lightSpace = glm::mat4(1.0f); //lightSpace = glm::perspective(glm::radians(75.0f), 1.0f, 0.1f, 100.0f); lightSpace = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, 0.1f, 100.0f); lightSpace *= glm::lookAt(world.lights[0]->position, glm::vec3(0), glm::vec3(0, -1, 0)); world.lights[0]->matrix = lightSpace; for(const auto& mesh : world.meshes) { glm::mat4 mvp = world.lights[0]->matrix; mvp = glm::translate(mvp, mesh->position); vkCmdPushConstants(commandBuffer, pipelineLayout_, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &mvp); VkDeviceSize offsets[] = {0}; vkCmdBindVertexBuffers(commandBuffer, 0, 1, &mesh->vertexBuffer, offsets); vkCmdBindIndexBuffer(commandBuffer, mesh->indexBuffer, 0, VK_INDEX_TYPE_UINT32); vkCmdDrawIndexed(commandBuffer, mesh->indices.size(), 1, 0, 0, 0); } vkCmdEndRenderPass(commandBuffer); } void ShadowPass::createRenderPass() { VkAttachmentDescription depthAttachment = {}; depthAttachment.format = VK_FORMAT_D32_SFLOAT; depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT; depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; depthAttachment.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; VkAttachmentReference depthAttachmentRef = {}; depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; VkSubpassDescription subpass = {}; subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; subpass.pDepthStencilAttachment = &depthAttachmentRef; VkRenderPassCreateInfo renderPassInfo = {}; renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; renderPassInfo.attachmentCount = 1; renderPassInfo.pAttachments = &depthAttachment; renderPassInfo.subpassCount = 1; renderPassInfo.pSubpasses = &subpass; vkCreateRenderPass(renderer_.getDevice(), &renderPassInfo, nullptr, &renderPass_); } void ShadowPass::createFramebuffer() { VkImageCreateInfo imageCreateInfo = {}; imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; imageCreateInfo.format = VK_FORMAT_D32_SFLOAT; imageCreateInfo.extent.width = renderer_.getConfig().shadowResolution; imageCreateInfo.extent.height = renderer_.getConfig().shadowResolution; imageCreateInfo.extent.depth = 1; imageCreateInfo.mipLevels = 1; imageCreateInfo.arrayLayers = 1; imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; imageCreateInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; vkCreateImage(renderer_.getDevice(), &imageCreateInfo, nullptr, &shadowImage_); VkMemoryRequirements memoryRequirements = {}; vkGetImageMemoryRequirements(renderer_.getDevice(), shadowImage_, &memoryRequirements); VkMemoryAllocateInfo allocateInfo = {}; allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; allocateInfo.allocationSize = memoryRequirements.size; allocateInfo.memoryTypeIndex = renderer_.findMemoryType(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); vkAllocateMemory(renderer_.getDevice(), &allocateInfo, nullptr, &shadowMemory_); vkBindImageMemory(renderer_.getDevice(), shadowImage_, shadowMemory_, 0); VkImageViewCreateInfo createInfo = {}; createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; createInfo.image = shadowImage_; createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; createInfo.format = VK_FORMAT_D32_SFLOAT; createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; createInfo.subresourceRange.levelCount = 1; createInfo.subresourceRange.layerCount = 1; vkCreateImageView(renderer_.getDevice(), &createInfo, nullptr, &shadowImageView_); VkFramebufferCreateInfo framebufferInfo = {}; framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; framebufferInfo.renderPass = renderPass_; framebufferInfo.attachmentCount = 1; framebufferInfo.pAttachments = &shadowImageView_; framebufferInfo.width = renderer_.getConfig().shadowResolution; framebufferInfo.height = renderer_.getConfig().shadowResolution; framebufferInfo.layers = 1; vkCreateFramebuffer(renderer_.getDevice(), &framebufferInfo, nullptr, &shadowFramebuffer_); VkSamplerCreateInfo samplerInfo = {}; samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; samplerInfo.magFilter = VK_FILTER_LINEAR; samplerInfo.minFilter = VK_FILTER_LINEAR; samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK; samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; vkCreateSampler(renderer_.getDevice(), &samplerInfo, nullptr, &shadowSampler_); } void ShadowPass::createPipeline() { VkShaderModule vertShaderModule = renderer_.createShader("shaders/shadow.vert.spv"); VkPipelineShaderStageCreateInfo vertShaderStageInfo = {}; vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT; vertShaderStageInfo.module = vertShaderModule; vertShaderStageInfo.pName = "main"; VkVertexInputBindingDescription vertexBindingDescription = {}; vertexBindingDescription.stride = sizeof(Vertex); VkVertexInputAttributeDescription positionAttributeDescription = {}; positionAttributeDescription.format = VK_FORMAT_R32G32B32_SFLOAT; VkPipelineVertexInputStateCreateInfo vertexInputInfo = {}; vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; vertexInputInfo.vertexBindingDescriptionCount = 1; vertexInputInfo.pVertexBindingDescriptions = &vertexBindingDescription; vertexInputInfo.vertexAttributeDescriptionCount = 1; vertexInputInfo.pVertexAttributeDescriptions = &positionAttributeDescription; VkPipelineInputAssemblyStateCreateInfo inputAssembly = {}; inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; VkPipelineViewportStateCreateInfo viewportState = {}; viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; viewportState.viewportCount = 1; viewportState.scissorCount = 1; VkPipelineRasterizationStateCreateInfo rasterizer = {}; rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; rasterizer.polygonMode = VK_POLYGON_MODE_FILL; rasterizer.lineWidth = 1.0f; rasterizer.cullMode = VK_CULL_MODE_FRONT_BIT; rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; rasterizer.depthBiasEnable = VK_TRUE; rasterizer.depthBiasConstantFactor = 1.25f; rasterizer.depthBiasSlopeFactor = 1.75f; VkPipelineMultisampleStateCreateInfo multisampling = {}; multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; VkPipelineColorBlendStateCreateInfo colorBlending = {}; colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; VkPipelineDepthStencilStateCreateInfo depthState = {}; depthState.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; depthState.depthTestEnable = VK_TRUE; depthState.depthWriteEnable = VK_TRUE; depthState.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; const std::array dynamicStates = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; VkPipelineDynamicStateCreateInfo dynamicState = {}; dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; dynamicState.dynamicStateCount = dynamicStates.size(); dynamicState.pDynamicStates = dynamicStates.data(); VkPushConstantRange pushConstant = {}; pushConstant.size = sizeof(glm::mat4); pushConstant.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; VkPipelineLayoutCreateInfo pipelineLayoutInfo = {}; pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; pipelineLayoutInfo.pushConstantRangeCount = 1; pipelineLayoutInfo.pPushConstantRanges = &pushConstant; vkCreatePipelineLayout(renderer_.getDevice(), &pipelineLayoutInfo, nullptr, &pipelineLayout_); VkGraphicsPipelineCreateInfo pipelineInfo = {}; pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; pipelineInfo.stageCount = 1; pipelineInfo.pStages = &vertShaderStageInfo; pipelineInfo.pVertexInputState = &vertexInputInfo; pipelineInfo.pInputAssemblyState = &inputAssembly; pipelineInfo.pViewportState = &viewportState; pipelineInfo.pRasterizationState = &rasterizer; pipelineInfo.pMultisampleState = &multisampling; pipelineInfo.pColorBlendState = &colorBlending; pipelineInfo.pDepthStencilState = &depthState; pipelineInfo.pDynamicState = &dynamicState; pipelineInfo.layout = pipelineLayout_; pipelineInfo.renderPass = renderPass_; vkCreateGraphicsPipelines(renderer_.getDevice(), nullptr, 1, &pipelineInfo, nullptr, &pipeline_); vkDestroyShaderModule(renderer_.getDevice(), vertShaderModule, nullptr); }