feat: TAA 时域抗锯齿(velocity + 邻域 clamp + 子像素抖动)
- Velocity buffer:Forward 第二颜色附件,vertex 计算 clip 空间运动向量 (UBO 尾部追加 projNoJitter/prevView/prevProj;上一帧实例矩阵 SSBO Set0 binding2,与当前实例数组平行对齐——转动的物体速度正确不鬼影) - 子像素抖动:SceneRenderer Halton(2,3)×8 序列,抖动只进光栅化投影 - TAA resolve pass:velocity 反推历史位置 + 3×3 邻域 clamp 去鬼影 + mix(cur,hist,0.9) 时域累积;TAAColor 自引用历史 - RG 历史读补 post-barrier:采样后恢复镜像 resting layout(TAA 的历史 是 ColorAttachment layout,不恢复则下帧 entry oldLayout 脱节) - 管线:Forward(HDR+Velocity) → TAA(TAAColor) → Bloom/Tonemap 改源 TAAColor - 编译零错误、validation 零警告、8 秒冒烟通过(10 pass 全活跃)
This commit is contained in:
@@ -177,6 +177,11 @@ namespace Engine::RG {
|
||||
bool history = false;
|
||||
};
|
||||
std::vector<BarrierPair> barriers;
|
||||
|
||||
// 历史读的出口 barrier(exec 之后执行):历史镜像被临时转进读
|
||||
// layout 采样,读完必须恢复 resting layout,否则下一帧该槽位
|
||||
// entry barrier 的 oldLayout 与实际 layout 脱节
|
||||
std::vector<BarrierPair> postBarriers;
|
||||
};
|
||||
|
||||
// ---------- RenderGraph ----------
|
||||
|
||||
@@ -18,10 +18,11 @@ namespace Engine::Passes {
|
||||
class ForwardPass final : public RenderPass {
|
||||
public:
|
||||
ForwardPass(SceneGpu& gpu, FrameSceneData& frame,
|
||||
RG::TextureHandle hdrColor, RG::TextureHandle depth,
|
||||
RG::TextureHandle shadowMap)
|
||||
RG::TextureHandle hdrColor, RG::TextureHandle velocity,
|
||||
RG::TextureHandle depth, RG::TextureHandle shadowMap)
|
||||
: m_Gpu(gpu), m_Frame(frame),
|
||||
m_HDRColor(hdrColor), m_Depth(depth), m_ShadowMap(shadowMap) {}
|
||||
m_HDRColor(hdrColor), m_Velocity(velocity),
|
||||
m_Depth(depth), m_ShadowMap(shadowMap) {}
|
||||
|
||||
void Register(RG::RenderGraph& rg) override;
|
||||
|
||||
@@ -29,6 +30,7 @@ namespace Engine::Passes {
|
||||
SceneGpu& m_Gpu;
|
||||
FrameSceneData& m_Frame;
|
||||
RG::TextureHandle m_HDRColor;
|
||||
RG::TextureHandle m_Velocity; // TAA 运动向量(第二颜色附件)
|
||||
RG::TextureHandle m_Depth;
|
||||
RG::TextureHandle m_ShadowMap;
|
||||
};
|
||||
|
||||
@@ -54,6 +54,7 @@ namespace Engine {
|
||||
vk::Sampler sampler;
|
||||
vk::ShaderEXT vert{}, extractFrag{}, blurFrag{}, tonemapFrag{};
|
||||
vk::ShaderEXT diffFrag{}; // temporal_diff(帧历史调试)
|
||||
vk::ShaderEXT taaFrag{}; // taa(时域抗锯齿 resolve)
|
||||
|
||||
// 各 pass 自己持有 per-slot set;分配统一走这里
|
||||
vk::DescriptorSet AllocateSet();
|
||||
|
||||
@@ -29,14 +29,15 @@ namespace Engine {
|
||||
public:
|
||||
SceneGpu(Device& device, DescriptorManager& descriptors,
|
||||
ShaderManager& shaders,
|
||||
UniformBuffer& ubo, UniformBuffer& objectBuffer);
|
||||
UniformBuffer& ubo, UniformBuffer& objectBuffer,
|
||||
UniformBuffer& prevObjectBuffer);
|
||||
~SceneGpu();
|
||||
|
||||
SceneGpu(const SceneGpu&) = delete;
|
||||
SceneGpu& operator=(const SceneGpu&) = delete;
|
||||
|
||||
// ---- set 布局(shader 契约,改绑定必须同步 shaders/)----
|
||||
vk::DescriptorSetLayout uboSetLayout; // Set0 = {UBO, ObjectBuffer}
|
||||
vk::DescriptorSetLayout uboSetLayout; // Set0 = {UBO, ObjectBuffer, PrevObjectBuffer}
|
||||
vk::DescriptorSetLayout textureSetLayout; // Set1 = {albedo}
|
||||
vk::DescriptorSetLayout shadowSetLayout; // Set2 = {shadow map}
|
||||
vk::PipelineLayout forwardLayout; // 3 sets,无 push(GPUDriven 经 SSBO)
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// Created by atdunbg on 2026/9/23.
|
||||
//
|
||||
// TAAPass:时域抗锯齿 resolve。
|
||||
// 读当前帧 HDR + velocity + 历史累积(ReadHistory 自引用 TAAColor),
|
||||
// 邻域 clamp 去鬼影后时域混合。TAAColor 既是输出也是下一帧的历史——
|
||||
// 这是帧历史资源最典型的"自引用"形态(UE 的 history pool 同构)。
|
||||
//
|
||||
|
||||
#ifndef HELLOVULKAN_TAAPASS_H
|
||||
#define HELLOVULKAN_TAAPASS_H
|
||||
|
||||
#include <Engine/Renderer/Passes/RenderPass.h>
|
||||
#include <Engine/Renderer/Passes/FullscreenGpu.h>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace Engine::Passes {
|
||||
|
||||
class TAAPass final : public RenderPass {
|
||||
public:
|
||||
TAAPass(FullscreenGpu& gpu, f32 historyAlpha,
|
||||
RG::TextureHandle hdrColor, RG::TextureHandle velocity,
|
||||
RG::TextureHandle taaColor);
|
||||
~TAAPass() override = default;
|
||||
|
||||
void Register(RG::RenderGraph& rg) override;
|
||||
void OnTargetsRebuilt(RG::RenderGraph& rg) override;
|
||||
|
||||
private:
|
||||
FullscreenGpu& m_Gpu;
|
||||
f32 m_HistoryAlpha;
|
||||
RG::TextureHandle m_HDR;
|
||||
RG::TextureHandle m_Velocity;
|
||||
RG::TextureHandle m_TAAColor; // 输出 = 下一帧的历史
|
||||
|
||||
std::vector<vk::DescriptorSet> m_Sets; // per-slot
|
||||
};
|
||||
|
||||
} // namespace Engine::Passes
|
||||
|
||||
#endif //HELLOVULKAN_TAAPASS_H
|
||||
@@ -109,6 +109,7 @@ namespace Engine {
|
||||
Scope<ShaderManager> m_ShaderManager;
|
||||
Scope<UniformBuffer> m_UniformBuffer; // per-slot UBO ring
|
||||
Scope<UniformBuffer> m_ObjectBuffer; // GPUDriven 实例矩阵 ring(SSBO)
|
||||
Scope<UniformBuffer> m_PrevObjectBuffer; // 上一帧实例矩阵 ring(TAA velocity)
|
||||
Scope<Passes::SceneGpu> m_SceneGpu; // 场景类 pass 共享装配
|
||||
Scope<Passes::FullscreenGpu> m_FullscreenGpu; // 全屏 pass 共享装配
|
||||
Scope<Swapchain> m_Swapchain;
|
||||
@@ -125,7 +126,9 @@ namespace Engine {
|
||||
RG::TextureHandle m_Backbuffer{};
|
||||
RG::TextureHandle m_Depth{};
|
||||
RG::TextureHandle m_ShadowMap{};
|
||||
RG::TextureHandle m_HDRColor{}; // Forward 输出(线性 HDR),Tonemap 归一
|
||||
RG::TextureHandle m_HDRColor{}; // Forward 输出(线性 HDR),TAA 归一
|
||||
RG::TextureHandle m_Velocity{}; // Forward 输出(clip 空间运动向量)
|
||||
RG::TextureHandle m_TAAColor{}; // TAA 累积输出(自引用历史),后处理源
|
||||
RG::TextureHandle m_BloomA{}; // 半分辨率:提取 + 垂直模糊结果
|
||||
RG::TextureHandle m_BloomB{}; // 半分辨率:水平模糊中间结果
|
||||
RG::TextureHandle m_TemporalDiff{}; // 半分辨率:帧历史差异(调试)
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include <Engine/Core/Types.h>
|
||||
#include <Engine/Renderer/SceneTypes.h>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace Engine {
|
||||
@@ -32,8 +33,9 @@ namespace Engine {
|
||||
class SceneRenderer {
|
||||
public:
|
||||
// 从场景构建当帧渲染数据。无 primary 相机返回 false(渲染跳帧)。
|
||||
// aspect 由调用方传入(跟随 swapchain,本类不感知窗口)。
|
||||
bool BuildFrame(ECS::Scene& scene, Assets::AssetManager& assets, f32 aspect);
|
||||
// targetExtent 用于 TAA 子像素抖动的 NDC 偏移折算。
|
||||
bool BuildFrame(ECS::Scene& scene, Assets::AssetManager& assets,
|
||||
vk::Extent2D targetExtent);
|
||||
|
||||
FrameSceneData& Frame() { return m_Frame; }
|
||||
|
||||
@@ -53,6 +55,15 @@ namespace Engine {
|
||||
std::unordered_map<Mesh*, u32> m_MainLookup;
|
||||
std::unordered_map<Mesh*, u32> m_ShadowLookup;
|
||||
|
||||
// ---- TAA 时域状态 ----
|
||||
u64 m_FrameIndex = 0; // 抖动序列游标(Halton 2,3 ×8 采样)
|
||||
glm::mat4 m_LastView{1.0f}; // 上一帧视图(velocity)
|
||||
glm::mat4 m_LastProjNoJitter{1.0f}; // 上一帧未抖动投影(velocity)
|
||||
// 实体的上一帧世界矩阵(key = entt 实体 integral)。
|
||||
// 每帧重建 m_CurWorlds 后与 m_PrevWorlds swap——自动清理销毁实体
|
||||
std::unordered_map<u32, glm::mat4> m_PrevWorlds;
|
||||
std::unordered_map<u32, glm::mat4> m_CurWorlds;
|
||||
|
||||
bool m_TruncationWarned = false; // 实例缓冲打满只告警一次
|
||||
};
|
||||
|
||||
|
||||
@@ -42,13 +42,19 @@ namespace Engine {
|
||||
glm::vec4 color; // rgb = 颜色,a = 强度
|
||||
};
|
||||
|
||||
// 镜像 simple_shader 的 UBO 布局(std140 语义由 shader 侧对齐)
|
||||
// 镜像 simple_shader 的 UBO 布局(std140 语义由 shader 侧对齐)。
|
||||
// 字段只能追加在尾部(shadow.vert 共用本 set 前缀,前插会错位)。
|
||||
struct UniformBufferObject {
|
||||
glm::mat4 view;
|
||||
glm::mat4 proj;
|
||||
glm::mat4 proj; // 抖动后的投影(光栅化用)
|
||||
glm::mat4 lightSpace; // 阴影光源 VP(写入与采样共用同一矩阵)
|
||||
glm::vec4 ambientColor;
|
||||
LightData lights[kMaxLights];
|
||||
|
||||
// ---- TAA(尾部追加;velocity 在 vertex 里算)----
|
||||
glm::mat4 projNoJitter; // 未抖动投影(velocity 当前帧 clip 用)
|
||||
glm::mat4 prevView; // 上一帧视图(velocity)
|
||||
glm::mat4 prevProj; // 上一帧未抖动投影(velocity)
|
||||
};
|
||||
|
||||
// 每帧从场景收集的渲染数据(SceneRenderer 生产,pass 消费)。
|
||||
@@ -58,6 +64,9 @@ namespace Engine {
|
||||
|
||||
// 实例矩阵数组 = [主视图段 | 阴影视图段](共享同一 per-slot SSBO)
|
||||
std::vector<glm::mat4> instanceModels;
|
||||
// 上一帧世界矩阵,与 instanceModels 平行对齐(同一下标 = 同一
|
||||
// 实例的上一帧姿态,TAA velocity 用);首帧/新实体 = 当前矩阵
|
||||
std::vector<glm::mat4> prevInstanceModels;
|
||||
CullResult mainView; // 相机视锥 → Forward pass
|
||||
CullResult shadowView; // 光源视锥 → Shadow pass(相机外实体仍投影子)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user