c++ - 我在获取在 Vulkan 中工作的辐照度图时遇到了一些问题
问题描述
我在获得在 Vulkan 中工作数天的辐照度图时遇到了一些问题。似乎纹理没有拉伸以适合其投影的平原。我已经尝试了多种方法来弄清楚如何让全文显示并且没有任何工作。如果立方体贴图为 512 x 512,则 CubeMap 将仅显示 512x512 像素并截断其余像素。如果它是 2048x2048,它会显示所有纹理,但其余部分只是空白区域。
这里没有应用辐照度部分。它只是获取立方体的 6 个视图并投影它们。
这是我一直在使用的辐照度代码。
#pragma once
#include "BaseRenderPass.h"
#include "RenderedDepthTexture.h"
#include "BlinnPhongPipeline.h"
#include "MeshManager.h"
#include "RenderedColorTexture.h"
#include "SkyBoxRenderPipeline.h"
#include "RenderedCubeMapTexture.h"
#include "IrradiancePipeline.h"
class IrradianceRenderPass : public BaseRenderPass
{
private:
void CreateRenderPass();
void CreateRendererFramebuffers();
void SetUpCommandBuffers();
uint32_t CubeMapSize;
VkFramebuffer IrradianceMapFrameBuffer;
public:
IrradianceRenderPass();
IrradianceRenderPass(std::shared_ptr<VulkanEngine> engine);
~IrradianceRenderPass();
std::shared_ptr<RenderedCubeMapTexture> RenderedCubeMap;
std::shared_ptr<IrradiancePipeline> irradiancePipeline;
void RebuildSwapChain();
void Draw();
void Destroy();
};
#include "IrradianceRenderPass.h"
#include "GraphicsPipeline.h"
#include "Skybox.h"
IrradianceRenderPass::IrradianceRenderPass() : BaseRenderPass()
{
}
IrradianceRenderPass::IrradianceRenderPass(std::shared_ptr<VulkanEngine> engine) : BaseRenderPass()
{
CubeMapSize = 512.0f;
RenderedCubeMap = std::make_shared<RenderedCubeMapTexture>(RenderedCubeMapTexture(glm::ivec2(CubeMapSize)));
CreateRenderPass();
CreateRendererFramebuffers();
irradiancePipeline = std::make_shared<IrradiancePipeline>(IrradiancePipeline(RenderPass));
SetUpCommandBuffers();
Draw();
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &CommandBuffer[EnginePtr::GetEnginePtr()->CMDIndex];
VkFenceCreateInfo fenceCreateInfo{};
fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fenceCreateInfo.flags = 0;
VkFence fence;
vkCreateFence(VulkanPtr::GetDevice(), &fenceCreateInfo, nullptr, &fence);
vkQueueSubmit(VulkanPtr::GetGraphicsQueue(), 1, &submitInfo, fence);
vkWaitForFences(VulkanPtr::GetDevice(), 1, &fence, VK_TRUE, UINT64_MAX);
vkDestroyFence(VulkanPtr::GetDevice(), fence, nullptr);
}
IrradianceRenderPass::~IrradianceRenderPass()
{
}
void IrradianceRenderPass::CreateRenderPass()
{
std::vector<VkAttachmentDescription> AttachmentDescriptionList;
VkAttachmentDescription CubeMapAttachment = {};
CubeMapAttachment.format = VK_FORMAT_R8G8B8A8_UNORM;
CubeMapAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
CubeMapAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
CubeMapAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
CubeMapAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
CubeMapAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
CubeMapAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
CubeMapAttachment.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
AttachmentDescriptionList.emplace_back(CubeMapAttachment);
std::vector<VkAttachmentReference> ColorRefsList;
ColorRefsList.emplace_back(VkAttachmentReference{ 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL });
VkSubpassDescription subpassDescription = {};
subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpassDescription.colorAttachmentCount = static_cast<uint32_t>(ColorRefsList.size());
subpassDescription.pColorAttachments = ColorRefsList.data();
std::vector<VkSubpassDependency> DependencyList;
VkSubpassDependency FirstDependency = {};
FirstDependency.srcSubpass = VK_SUBPASS_EXTERNAL;
FirstDependency.dstSubpass = 0;
FirstDependency.srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
FirstDependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
FirstDependency.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
FirstDependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
FirstDependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
DependencyList.emplace_back(FirstDependency);
VkSubpassDependency SecondDependency = {};
SecondDependency.srcSubpass = 0;
SecondDependency.dstSubpass = VK_SUBPASS_EXTERNAL;
SecondDependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
SecondDependency.dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
SecondDependency.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
SecondDependency.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
SecondDependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
DependencyList.emplace_back(SecondDependency);
const uint32_t viewMask = 0b00111111;
const uint32_t correlationMask = 0b00111111;
VkRenderPassMultiviewCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO;
createInfo.subpassCount = 1;
createInfo.pViewMasks = &viewMask;
createInfo.correlationMaskCount = 1;
createInfo.pCorrelationMasks = &correlationMask;
VkRenderPassCreateInfo renderPassInfo = {};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassInfo.attachmentCount = static_cast<uint32_t>(AttachmentDescriptionList.size());
renderPassInfo.pAttachments = AttachmentDescriptionList.data();
renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subpassDescription;
renderPassInfo.dependencyCount = static_cast<uint32_t>(DependencyList.size());
renderPassInfo.pDependencies = DependencyList.data();
renderPassInfo.pNext = &createInfo;
if (vkCreateRenderPass(EnginePtr::GetEnginePtr()->Device, &renderPassInfo, nullptr, &RenderPass))
{
throw std::runtime_error("failed to create GBuffer RenderPass!");
}
}
void IrradianceRenderPass::CreateRendererFramebuffers()
{
SwapChainFramebuffers.resize(EnginePtr::GetEnginePtr()->SwapChain.GetSwapChainImageCount());
for (size_t i = 0; i < EnginePtr::GetEnginePtr()->SwapChain.GetSwapChainImageCount(); i++)
{
std::vector<VkImageView> AttachmentList;
AttachmentList.emplace_back(RenderedCubeMap->View);
VkFramebufferCreateInfo frameBufferCreateInfo = {};
frameBufferCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
frameBufferCreateInfo.renderPass = RenderPass;
frameBufferCreateInfo.attachmentCount = static_cast<uint32_t>(AttachmentList.size());
frameBufferCreateInfo.pAttachments = AttachmentList.data();
frameBufferCreateInfo.width = CubeMapSize;
frameBufferCreateInfo.height = CubeMapSize;
frameBufferCreateInfo.layers = 1;
if (vkCreateFramebuffer(EnginePtr::GetEnginePtr()->Device, &frameBufferCreateInfo, nullptr, &SwapChainFramebuffers[i]))
{
throw std::runtime_error("Failed to create Gbuffer FrameBuffer.");
}
}
}
void IrradianceRenderPass::SetUpCommandBuffers()
{
CommandBuffer.resize(EnginePtr::GetEnginePtr()->SwapChain.GetSwapChainImageCount());
for (size_t i = 0; i < EnginePtr::GetEnginePtr()->SwapChain.GetSwapChainImageCount(); i++)
{
VkCommandBufferAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.commandPool = EnginePtr::GetEnginePtr()->CommandPool;
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandBufferCount = 1;
if (vkAllocateCommandBuffers(EnginePtr::GetEnginePtr()->Device, &allocInfo, &CommandBuffer[i]) != VK_SUCCESS) {
throw std::runtime_error("failed to allocate command buffers!");
}
}
}
void IrradianceRenderPass::RebuildSwapChain()
{
irradiancePipeline->Destroy();
vkDestroyRenderPass(EnginePtr::GetEnginePtr()->Device, RenderPass, nullptr);
RenderPass = VK_NULL_HANDLE;
for (auto& framebuffer : SwapChainFramebuffers)
{
vkDestroyFramebuffer(EnginePtr::GetEnginePtr()->Device, framebuffer, nullptr);
framebuffer = VK_NULL_HANDLE;
}
CreateRenderPass();
CreateRendererFramebuffers();
irradiancePipeline->UpdateGraphicsPipeLine(RenderPass);
SetUpCommandBuffers();
}
void IrradianceRenderPass::Draw()
{
VkCommandBufferBeginInfo beginInfo{};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
if (vkBeginCommandBuffer(CommandBuffer[EnginePtr::GetEnginePtr()->CMDIndex], &beginInfo) != VK_SUCCESS) {
throw std::runtime_error("failed to begin recording command buffer!");
}
std::array<VkClearValue, 2> clearValues{};
clearValues[0].color = { {0.0f, 1.0f, 0.0f, 1.0f} };
clearValues[1].color = { {0.0f, 1.0f, 0.0f, 1.0f} };
VkRenderPassBeginInfo renderPassInfo{};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassInfo.renderPass = RenderPass;
renderPassInfo.framebuffer = SwapChainFramebuffers[EnginePtr::GetEnginePtr()->ImageIndex];
renderPassInfo.renderArea.offset = { 0, 0 };
renderPassInfo.renderArea.extent.width = CubeMapSize;
renderPassInfo.renderArea.extent.height = CubeMapSize;
renderPassInfo.clearValueCount = static_cast<uint32_t>(clearValues.size());
renderPassInfo.pClearValues = clearValues.data();
vkCmdBindPipeline(CommandBuffer[EnginePtr::GetEnginePtr()->CMDIndex], VK_PIPELINE_BIND_POINT_GRAPHICS, irradiancePipeline->ShaderPipeline);
vkCmdBindDescriptorSets(CommandBuffer[EnginePtr::GetEnginePtr()->CMDIndex], VK_PIPELINE_BIND_POINT_GRAPHICS, irradiancePipeline->ShaderPipelineLayout, 0, 1, &irradiancePipeline->DescriptorSet, 0, nullptr);
vkCmdBeginRenderPass(CommandBuffer[EnginePtr::GetEnginePtr()->CMDIndex], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
static_cast<Skybox*>(MeshManagerPtr::GetMeshManagerPtr()->GetMeshByType(MeshTypeFlag::Mesh_Type_SkyBox)[0].get())->Draw(CommandBuffer[EnginePtr::GetEnginePtr()->CMDIndex]);
vkCmdEndRenderPass(CommandBuffer[EnginePtr::GetEnginePtr()->CMDIndex]);
if (vkEndCommandBuffer(CommandBuffer[EnginePtr::GetEnginePtr()->CMDIndex]) != VK_SUCCESS) {
throw std::runtime_error("failed to record command buffer!");
}
}
void IrradianceRenderPass::Destroy()
{
irradiancePipeline->Destroy();
BaseRenderPass::Destroy();
}
解决方案
推荐阅读
- apache-calcite - 如何利用方解石服务器
- java - 可以用我自己的对象来做到这一点(整数广告 = 8;和整数广告 = 8;)
- android - Windows 10,在 Qt Creator 中开发 Android 项目
- html - 如何仅使用 html 和 css 将两个按钮放在同一行?
- amazon-web-services - 如何通过 Amazon Elastic Beanstalk 发布 MVC Web 应用程序,使其不会删除 App_data 目录的任何内容?
- javascript - 这是否仍然可以关闭未由 javascript 打开的 chrome/firefox 选项卡
- c++ - std::string 是否保证不会自发归还内存?
- javascript - HTML 正则表达式与 JS 正则表达式相同吗?
- r - 考虑到R中的纬度和经度值,如何计算两个不同变量的平均值?
- ios - iOS 中加密 HLS 内容的离线播放