我尝试使用此示例将阴影添加到项目中。 (https://github.com/SaschaWillems/Vulkan/tree/master/examples/shadowmapping) 不幸的是,它没有用。更准确地说,它可用于清理第一遍的缓冲区深度。但是过程本身不起作用,或者没有将深度缓冲区写入采样器,而我将其传递给第二遍。同时,用于清洁深度缓冲区的参数会影响采样器。我检查了从光源渲染时场景参数的传递,它们是正确的。我不知道该怎么想了。也许是我不理解的简单错误。
首过管道
VkPipeline MainRenderer::initShadowPipeline(const VKStr::Device & device, VkPipelineLayout pipelineLayout, VkRenderPass renderPass, std::string vShaderName)
{
VkPipeline resultPipelineHandle = VK_NULL_HANDLE;
std::vector<VkVertexInputBindingDescription> bindingDescription = GetVertexInputBindingDescriptions(0);
std::vector<VkVertexInputAttributeDescription> attributeDescriptions = GetVertexInputAttributeDescriptions(0);
VkPipelineVertexInputStateCreateInfo vertexInputStage = {};
vertexInputStage.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputStage.vertexBindingDescriptionCount = (uint32_t)bindingDescription.size();
vertexInputStage.pVertexBindingDescriptions = bindingDescription.data();
vertexInputStage.vertexAttributeDescriptionCount = (uint32_t)attributeDescriptions.size();
vertexInputStage.pVertexAttributeDescriptions = attributeDescriptions.data();
VkPipelineInputAssemblyStateCreateInfo inputAssemblyStage = {};
inputAssemblyStage.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
inputAssemblyStage.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
inputAssemblyStage.primitiveRestartEnable = VK_FALSE;
std::vector<VkPipelineShaderStageCreateInfo> shaderStages = {
{
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
nullptr,
0,
VK_SHADER_STAGE_VERTEX_BIT,
LoadSPIRVShader(vShaderName, device.logicalDevice),
"main",
nullptr
}
};
VkViewport viewport = {};
viewport.width = (float)shadowPass_.width;
viewport.height = (float)shadowPass_.height;
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
VkRect2D scissor = {};
scissor.offset = { 0, 0 };
scissor.extent.width = shadowPass_.width;
scissor.extent.height = shadowPass_.height;
VkPipelineViewportStateCreateInfo viewportState = {};
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportState.viewportCount = 1;
viewportState.pViewports = &viewport;
viewportState.scissorCount = 1;
viewportState.pScissors = &scissor;
viewportState.flags = 0;
VkPipelineRasterizationStateCreateInfo rasterizationStage = {};
rasterizationStage.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterizationStage.depthClampEnable = VK_FALSE;
rasterizationStage.polygonMode = VK_POLYGON_MODE_FILL;
rasterizationStage.lineWidth = 1.0f;
rasterizationStage.cullMode = VK_CULL_MODE_BACK_BIT;
rasterizationStage.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
rasterizationStage.depthBiasEnable = VK_TRUE;
rasterizationStage.depthBiasConstantFactor = 1.25f;
rasterizationStage.depthBiasClamp = 0.0f;
rasterizationStage.depthBiasSlopeFactor = 1.75f;
VkPipelineDepthStencilStateCreateInfo depthStencilStage = {};
depthStencilStage.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
depthStencilStage.depthTestEnable = VK_TRUE;
depthStencilStage.depthWriteEnable = VK_TRUE;
depthStencilStage.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
depthStencilStage.back.compareOp = VK_COMPARE_OP_ALWAYS;
depthStencilStage.front = depthStencilStage.back;
VkPipelineMultisampleStateCreateInfo multisamplingStage = {};
multisamplingStage.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisamplingStage.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
multisamplingStage.flags = 0;
VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
colorBlendAttachment.colorWriteMask = 0xf;
colorBlendAttachment.blendEnable = VK_FALSE;
VkPipelineColorBlendStateCreateInfo colorBlendState = {};
colorBlendState.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
colorBlendState.attachmentCount = 0;
colorBlendState.pAttachments = &colorBlendAttachment;
std::vector<VkDynamicState> dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
dynamicStateEnables.push_back(VK_DYNAMIC_STATE_DEPTH_BIAS);
VkPipelineDynamicStateCreateInfo dynamicStateCI = {};
dynamicStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamicStateCI.pDynamicStates = dynamicStateEnables.data();
dynamicStateCI.dynamicStateCount = dynamicStateEnables.size();
dynamicStateCI.flags = 0;
VkGraphicsPipelineCreateInfo pipelineInfo = {};
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipelineInfo.stageCount = (uint32_t)shaderStages.size();
pipelineInfo.pStages = shaderStages.data();
pipelineInfo.pVertexInputState = &vertexInputStage;
pipelineInfo.pInputAssemblyState = &inputAssemblyStage;
pipelineInfo.pViewportState = &viewportState;
pipelineInfo.pRasterizationState = &rasterizationStage;
pipelineInfo.pDepthStencilState = &depthStencilStage;
pipelineInfo.pMultisampleState = &multisamplingStage;
pipelineInfo.pColorBlendState = &colorBlendState;
pipelineInfo.pDynamicState = &dynamicStateCI;
pipelineInfo.layout = pipelineLayout;
pipelineInfo.renderPass = renderPass;
pipelineInfo.subpass = 0;
pipelineInfo.stageCount = 1;
if (vkCreateGraphicsPipelines(device.logicalDevice, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &resultPipelineHandle) != VK_SUCCESS) {
throw std::runtime_error("Vulkan: Error while creating pipeline");
}
tools::LogMessage("Vulkan: Pipeline sucessfully initialized");
for (VkPipelineShaderStageCreateInfo &shaderStageInfo : shaderStages) {
vkDestroyShaderModule(device.logicalDevice, shaderStageInfo.module, nullptr);
}
return resultPipelineHandle;
}
第一遍renderPassage
VkRenderPass MainRenderer::initShadowRenderPassage(const VKStr::Device &device)
{
std::vector<VkAttachmentDescription> attachments;
VkAttachmentDescription depthStencilAttachment = {};
depthStencilAttachment.format = shadowPass_.depthFormat;
depthStencilAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
depthStencilAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
depthStencilAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
depthStencilAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
depthStencilAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depthStencilAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
depthStencilAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
attachments.push_back(depthStencilAttachment);
VkAttachmentReference depthStencilAttachemntReference = {
0,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
};
VkSubpassDescription subpassDescription = {};
subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpassDescription.colorAttachmentCount = 0;
subpassDescription.pDepthStencilAttachment = &depthStencilAttachemntReference;
std::vector<VkSubpassDependency> dependencies = {
{
VK_SUBPASS_EXTERNAL,
0,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
VK_ACCESS_SHADER_READ_BIT,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
VK_DEPENDENCY_BY_REGION_BIT
},
{
0,
VK_SUBPASS_EXTERNAL,
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
VK_ACCESS_SHADER_READ_BIT,
VK_DEPENDENCY_BY_REGION_BIT
}
};
VkRenderPassCreateInfo renderPassInfo = {};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassInfo.attachmentCount = 1;
renderPassInfo.pAttachments = attachments.data();
renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subpassDescription;
renderPassInfo.dependencyCount = (unsigned int)dependencies.size();
renderPassInfo.pDependencies = dependencies.data();
VkRenderPass renderPass;
if (vkCreateRenderPass(device.logicalDevice, &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS) {
throw std::runtime_error("Vulkan: Failed to create render passage");
}
tools::LogMessage("Vulkan: Render passage successfully initialized");
return renderPass;
}
第一遍frameBuff
void MainRenderer::initShadowFrameBuffer(const VKStr::Device &device)
{
this->shadowPass_.width = 4096;
this->shadowPass_.height = 4096;
VkImageCreateInfo image = {};
image.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
image.imageType = VK_IMAGE_TYPE_2D;
image.extent.width = shadowPass_.width;
image.extent.height = shadowPass_.height;
image.extent.depth = 1;
image.mipLevels = 1;
image.arrayLayers = 1;
image.samples = VK_SAMPLE_COUNT_1_BIT;
image.tiling = VK_IMAGE_TILING_OPTIMAL;
image.format = this->shadowPass_.depthFormat;
image.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
image.sharingMode = VK_SHARING_MODE_CONCURRENT;
if (vkCreateImage(device.logicalDevice, &image, nullptr, &shadowPass_.depth.image) != VK_SUCCESS)
{
throw std::runtime_error("Vulkan: Error shadowImage create info");
}
VkMemoryAllocateInfo memAlloc{};
memAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
VkMemoryRequirements memReqs;
vkGetImageMemoryRequirements(device.logicalDevice, shadowPass_.depth.image, &memReqs);
memAlloc.allocationSize = memReqs.size;
memAlloc.memoryTypeIndex = GetMemoryTypeIndex(device.physicalDevice, memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
if (vkAllocateMemory(device.logicalDevice, &memAlloc, nullptr, &shadowPass_.depth.memory) != VK_SUCCESS)
{
throw std::runtime_error("Vulkan: Error Shadow AllocateMemory");
}
if (vkBindImageMemory(device.logicalDevice, shadowPass_.depth.image, shadowPass_.depth.memory, 0) != VK_SUCCESS)
{
throw std::runtime_error("Vulkan: Error shadow bindMemory");
}
VkImageViewCreateInfo depthStencilView = {};
depthStencilView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
depthStencilView.viewType = VK_IMAGE_VIEW_TYPE_2D;
depthStencilView.format = this->shadowPass_.depthFormat;
depthStencilView.subresourceRange = {};
depthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
depthStencilView.subresourceRange.baseMipLevel = 0;
depthStencilView.subresourceRange.levelCount = 1;
depthStencilView.subresourceRange.baseArrayLayer = 0;
depthStencilView.subresourceRange.layerCount = 1;
depthStencilView.image = shadowPass_.depth.image;
if (vkCreateImageView(device.logicalDevice, &depthStencilView, nullptr, &shadowPass_.depth.view) != VK_SUCCESS)
{
throw std::runtime_error("Vulkan: Error shadow createImageView");
}
VkFramebufferCreateInfo fbufCreateInfo = {};
fbufCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
fbufCreateInfo.renderPass = shadowPass_.renderPass;
fbufCreateInfo.attachmentCount = 1;
fbufCreateInfo.pAttachments = &shadowPass_.depth.view;
fbufCreateInfo.width = shadowPass_.width;
fbufCreateInfo.height = shadowPass_.height;
fbufCreateInfo.layers = 1;
if (vkCreateFramebuffer(device.logicalDevice, &fbufCreateInfo, nullptr, &shadowPass_.frameBuffer) != VK_SUCCESS)
{
throw std::runtime_error("Vulkan: Error shadow frameBuffer");
}
VkSamplerCreateInfo sampler = {};
sampler.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
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_EDGE;
sampler.addressModeV = sampler.addressModeU;
sampler.addressModeW = sampler.addressModeU;
sampler.mipLodBias = 0.0f;
sampler.maxAnisotropy = 1.0f;
sampler.minLod = 0.0f;
sampler.maxLod = 1.0f;
sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
if (vkCreateSampler(device.logicalDevice, &sampler, nullptr, &shadowPass_.depthSampler) != VK_SUCCESS)
{
throw std::runtime_error("Vulkan: Error Shadow createSampler");
}
}
commandBuff
void MainRenderer::PrepareDrawCommands(std::vector<VkCommandBuffer> commandBuffers, VkRenderPass renderPass, std::vector<VkPipelineLayout> pipelineLayout, VkDescriptorSet descriptorSetMain, VkDescriptorSet descriptorSetInfo, VkDescriptorSet descriptorSetVLight, const VKStr::Swapchain & swapchain, const std::vector<VKStr::Primitive>& primitives)
{
VkCommandBufferBeginInfo cmdBufInfo = {};
cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
cmdBufInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
cmdBufInfo.pNext = nullptr;
std::vector<VkClearValue> clearValues(2);
clearValues[0].color = { 0.0f, 0.0f, 0.0f, 1.0f };
clearValues[1].depthStencil.depth = 1.0f;
clearValues[1].depthStencil.stencil = 0;
std::vector<VkClearValue> clearValuesShadow(1);
clearValuesShadow[0].depthStencil = { 1.0f, 0 };
for (unsigned int i = 0; i < commandBuffers.size(); ++i)
{
VkRenderPassBeginInfo renderPassBeginInfo = {};
vkBeginCommandBuffer(commandBuffers[i], &cmdBufInfo);
if (ShadowRender)
{
renderPassBeginInfo = {};
renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassBeginInfo.pNext = nullptr;
renderPassBeginInfo.renderPass = this->shadowPass_.renderPass;
renderPassBeginInfo.renderArea.offset.x = 0;
renderPassBeginInfo.renderArea.offset.y = 0;
renderPassBeginInfo.renderArea.extent.width = this->shadowPass_.width;
renderPassBeginInfo.renderArea.extent.height = this->shadowPass_.height;
renderPassBeginInfo.clearValueCount = clearValuesShadow.size();
renderPassBeginInfo.pClearValues = clearValuesShadow.data();
renderPassBeginInfo.framebuffer = this->shadowPass_.frameBuffer;
vkCmdBeginRenderPass(commandBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdSetDepthBias(
commandBuffers[i],
1.25f,
0.0f,
1.75f);
if (!primitives.empty()) {
for (unsigned int primitiveIndex = 0; primitiveIndex < primitives.size(); primitiveIndex++)
{
vkCmdBindPipeline(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, this->pipelines_[3]);
std::vector<uint32_t> dynamicOffsets = {
primitiveIndex * static_cast<uint32_t>(this->device_.GetDynamicAlignment<glm::mat4>())
};
if (primitives_[primitiveIndex].pipelineIndex == AREAN_SHADER_T_BASE)
{
std::vector<VkDescriptorSet> descriptorSets = {
this->descriptorSetShadow_
};
vkCmdBindDescriptorSets(
commandBuffers[i],
VK_PIPELINE_BIND_POINT_GRAPHICS,
pipelineLayout[2],
0,
(uint32_t)descriptorSets.size(),
descriptorSets.data(),
(uint32_t)dynamicOffsets.size(),
dynamicOffsets.data());
if (primitives[primitiveIndex].drawIndexed && primitives[primitiveIndex].indexBuffer.count > 0) {
VkDeviceSize offsets[1] = { 0 };
vkCmdBindVertexBuffers(commandBuffers[i], 0, 1, &(primitives[primitiveIndex].vertexBuffer.vkBuffer), offsets);
vkCmdBindIndexBuffer(commandBuffers[i], primitives[primitiveIndex].indexBuffer.vkBuffer, 0, VK_INDEX_TYPE_UINT32);
vkCmdDrawIndexed(commandBuffers[i], primitives[primitiveIndex].indexBuffer.count, 1, 0, 0, 0);
}
else {
VkDeviceSize offsets[1] = { 0 };
vkCmdBindVertexBuffers(commandBuffers[i], 0, 1, &(primitives[primitiveIndex].vertexBuffer.vkBuffer), offsets);
vkCmdDraw(commandBuffers[i], primitives[primitiveIndex].vertexBuffer.count, 1, 0, 0);
}
}
}
}
vkCmdEndRenderPass(commandBuffers[i]);
}
/*VkImageSubresourceRange imageRes = {}; //i try it, but not affect.
imageRes.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
imageRes.baseMipLevel = 0;
imageRes.levelCount = 1;
imageRes.baseArrayLayer = 0;
imageRes.layerCount = 1;
VkImageMemoryBarrier imageMemoryBarrier = {};
imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
imageMemoryBarrier.pNext = NULL;
imageMemoryBarrier.image = this->shadowPass_.depth.image;
imageMemoryBarrier.subresourceRange = imageRes;
imageMemoryBarrier.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
vkCmdPipelineBarrier(commandBuffers[i],
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, // srcStageMask
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // dstStageMask
0,
0, nullptr,
0, nullptr,
1, // imageMemoryBarrierCount
&imageMemoryBarrier // pImageMemoryBarriers
);*/
renderPassBeginInfo = {};
renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassBeginInfo.pNext = nullptr;
renderPassBeginInfo.renderPass = renderPass;
renderPassBeginInfo.renderArea.offset.x = 0;
renderPassBeginInfo.renderArea.offset.y = 0;
renderPassBeginInfo.renderArea.extent.width = swapchain.imageExtent.width;
renderPassBeginInfo.renderArea.extent.height = swapchain.imageExtent.height;
renderPassBeginInfo.clearValueCount = (uint32_t)clearValues.size();
renderPassBeginInfo.pClearValues = clearValues.data();
renderPassBeginInfo.framebuffer = swapchain.framebuffers[i];
vkCmdBeginRenderPass(commandBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
/*2 pass*/
}
}