Files
HelloVulkan/Engine/src/Renderer/Passes/SkyboxPass.cpp
T
atdunbg f73e52926f Reorganize directory layout: editor panels/, grouped shaders, drop stale header
- App/editor: move 7 panels into panels/ (Editor core stays at root)
- shaders/: group into pbr/ post/ debug/ env/ (runtime load paths updated)
- Delete outdated duplicate Engine/src/Renderer/VulkanAssetUploader.h
2026-10-07 09:52:17 +08:00

196 lines
8.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//
// Created by atdunbg on 2026/9/23.
//
#include <Engine/Renderer/Passes/SkyboxPass.h>
#include <Engine/Renderer/Passes/FullscreenGpu.h>
#include <Engine/Renderer/Cubemap.h>
#include <Engine/Vulkan/Device.h>
#include <Engine/Vulkan/DescriptorManager.h>
#include <Engine/Vulkan/ShaderManager.h>
#include <Engine/Core/Log.h>
#include <glm/glm.hpp>
#include <tracy/Tracy.hpp>
#include <array>
namespace Engine::Passes
{
SkyboxPass::SkyboxPass(Device& device, ShaderManager& shaders,
DescriptorManager& descriptors, FrameSceneData& frame,
RG::TextureHandle hdrColor, const Cubemap* env)
: m_Device(device), m_Descriptors(descriptors), m_Frame(frame),
m_HDRColor(hdrColor), m_Env(env)
{
// Set0 = {samplerCube}(fragment 采样)
std::vector<DescriptorBinding> bindings = {
{0, vk::DescriptorType::eCombinedImageSampler,
vk::ShaderStageFlagBits::eFragment},
};
m_SetLayout = descriptors.CreateLayout(bindings);
// push = invVP 64B(skybox.vert/.frag 声明一致,VUID-08878)
m_Layout = descriptors.CreatePipelineLayout(
std::vector<vk::DescriptorSetLayout>{m_SetLayout},
sizeof(glm::mat4));
const std::string shaderDir = "shaders/env/";
auto vert = shaders.CreateFromFile(
shaderDir + "skybox.vert.spv",
vk::ShaderStageFlagBits::eVertex,
std::vector<vk::DescriptorSetLayout>{m_SetLayout},
sizeof(glm::mat4));
auto frag = shaders.CreateFromFile(
shaderDir + "skybox.frag.spv",
vk::ShaderStageFlagBits::eFragment,
std::vector<vk::DescriptorSetLayout>{m_SetLayout},
sizeof(glm::mat4));
m_Vert = std::move(vert);
m_Frag = std::move(frag);
if (!m_Vert || !m_Frag) {
ENGINE_FATAL("SkyboxPass: failed to create shader objects");
}
// per-slot set:cube view 全程稳定,构造期绑定一次即可
for (u32 slot = 0; slot < kMaxFramesInFlight; ++slot) {
m_Sets[slot] = descriptors.AllocateDescriptorSet(m_SetLayout);
if (m_Env) {
descriptors.UpdateTexture(m_Sets[slot], 0,
m_Env->GetSampler(),
m_Env->GetView());
}
}
}
SkyboxPass::~SkyboxPass()
{
const auto& vkDevice = m_Device.GetDevice();
// shader 随 ShaderRef 引用计数自动销毁,此处只清其余原生句柄
vkDevice.destroyPipelineLayout(m_Layout);
vkDevice.destroyDescriptorSetLayout(m_SetLayout);
}
void SkyboxPass::OnEnvironmentChanged(const Cubemap* env)
{
m_Env = env;
if (!m_Env) return;
// cube view 全程稳定语义是"单个环境内";切换环境 = 新 view,
// per-slot set 全部重绑
for (u32 slot = 0; slot < kMaxFramesInFlight; ++slot) {
m_Descriptors.UpdateTexture(m_Sets[slot], 0,
m_Env->GetSampler(),
m_Env->GetView());
}
}
void SkyboxPass::Register(RG::RenderGraph& rg)
{
rg.AddPass("Skybox", [this](RG::RenderGraphContext& ctx) {
ZoneScopedN("Skybox");
const vk::CommandBuffer cmd = ctx.cmd;
const glm::vec4& cc = m_Frame.ClearColor;
vk::ClearValue clear;
// alpha 语义 = 窗口透过率(透明窗口与桌面合成;tonemap 段
// rgb *= a 预乘)。滑条由用户控制:a<1 = 背景透出桌面
clear.color = vk::ClearColorValue(
std::array<float, 4>{cc.r, cc.g, cc.b, cc.a});
vk::RenderingAttachmentInfo color;
color.setImageView(ctx.View(m_HDRColor))
.setImageLayout(vk::ImageLayout::eColorAttachmentOptimal)
.setLoadOp(vk::AttachmentLoadOp::eClear) // 清屏职责在本 pass
.setStoreOp(vk::AttachmentStoreOp::eStore)
.setClearValue(clear);
vk::RenderingInfo renderingInfo;
renderingInfo.setRenderArea({{0, 0}, ctx.extent})
.setLayerCount(1)
.setColorAttachments(color); // 无深度附件
cmd.beginRendering(renderingInfo);
if (m_Env && m_Frame.DrawSkybox &&
m_Frame.debugView != Passes::kDebugTransparent) {
// 无环境贴图:只清屏(Forward loadOp=Load 依赖这里先写)
const std::array<vk::ShaderStageFlagBits, 2> stages = {
vk::ShaderStageFlagBits::eVertex,
vk::ShaderStageFlagBits::eFragment
};
const std::array<vk::ShaderEXT, 2> shaders = {m_Vert.GetHandle(), m_Frag.GetHandle()};
cmd.bindShadersEXT(stages, shaders);
cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics,
m_Layout, 0,
m_Sets[ctx.frame.frameSlot], {});
cmd.pushConstants<glm::mat4>(
m_Layout,
vk::ShaderStageFlagBits::eVertex |
vk::ShaderStageFlagBits::eFragment,
0, m_Frame.skyInvVP);
// ---- 动态状态 ----
cmd.setRasterizerDiscardEnable(VK_FALSE);
cmd.setDepthTestEnable(VK_FALSE);
cmd.setDepthWriteEnable(VK_FALSE);
cmd.setDepthBoundsTestEnable(VK_FALSE);
cmd.setStencilTestEnable(VK_FALSE);
cmd.setDepthBiasEnable(VK_FALSE);
cmd.setPolygonModeEXT(vk::PolygonMode::eFill);
cmd.setCullMode(vk::CullModeFlagBits::eNone);
cmd.setFrontFace(vk::FrontFace::eCounterClockwise);
cmd.setPrimitiveTopology(vk::PrimitiveTopology::eTriangleList);
cmd.setPrimitiveRestartEnable(VK_FALSE);
// 全屏三角:无顶点输入
cmd.setVertexInputEXT({}, {});
cmd.setRasterizationSamplesEXT(vk::SampleCountFlagBits::e1);
constexpr vk::SampleMask sampleMask = 0xFFFFFFFF;
cmd.setSampleMaskEXT(vk::SampleCountFlagBits::e1, sampleMask);
cmd.setAlphaToCoverageEnableEXT(VK_FALSE);
cmd.setAlphaToOneEnableEXT(VK_FALSE);
const vk::Viewport viewport(0.0f, 0.0f,
static_cast<float>(ctx.extent.width),
static_cast<float>(ctx.extent.height),
0.0f, 1.0f);
cmd.setViewportWithCount(viewport);
cmd.setScissorWithCount(vk::Rect2D({0, 0}, ctx.extent));
// 无混合直写(天空不透明)
vk::ColorBlendEquationEXT blendEquation;
blendEquation.setSrcColorBlendFactor(vk::BlendFactor::eOne)
.setDstColorBlendFactor(vk::BlendFactor::eZero)
.setColorBlendOp(vk::BlendOp::eAdd)
.setSrcAlphaBlendFactor(vk::BlendFactor::eOne)
.setDstAlphaBlendFactor(vk::BlendFactor::eZero)
.setAlphaBlendOp(vk::BlendOp::eAdd);
// ArrayProxyNoTemporaries 拒绝临时量:具名局部变量传入
constexpr vk::Bool32 blendEnable = VK_FALSE;
constexpr vk::ColorComponentFlags colorWriteMask =
vk::ColorComponentFlagBits::eR |
vk::ColorComponentFlagBits::eG |
vk::ColorComponentFlagBits::eB |
vk::ColorComponentFlagBits::eA;
cmd.setColorBlendEnableEXT(0, blendEnable);
cmd.setColorBlendEquationEXT(0, blendEquation);
cmd.setColorWriteMaskEXT(0, colorWriteMask);
cmd.draw(3, 1, 0, 0);
}
cmd.endRendering();
})
.Write(m_HDRColor, RG::ResourceUse::ColorAttachment);
}
} // namespace Engine::Passes