feat(post_effect): 添加暗角效果参数和应用函数

This commit is contained in:
daiqingshuang
2025-11-28 01:53:47 +08:00
parent 99cbe100e6
commit cb6d48e614
3 changed files with 153 additions and 2 deletions

View File

@@ -2,6 +2,7 @@
#include "renderer/vertex_types.h"
#include <algorithm>
#include <variant>
#include <iostream>
namespace mirage {
void command_processor::set_viewport_size(const vector2f_t& size) {

View File

@@ -9,6 +9,7 @@
// 引入后效着色器 SPIR-V 数据
#include "fullscreen_quad_vert_frag.h"
#include "blur_vert_frag.h"
#include "vignette_vert_frag.h"
#include "chromatic_aberration_vert_frag.h"
namespace mirage {
@@ -251,6 +252,25 @@ namespace mirage {
);
}
// 创建暗角参数缓冲
{
auto buffer_result = res_mgr_.create_buffer(
sizeof(vignette_params) * 10,
vk::BufferUsageFlagBits::eUniformBuffer,
vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent
);
if (!buffer_result) {
throw std::runtime_error("Failed to create vignette params buffer");
}
vignette_params_buffer_.emplace(
device_.get_handle(),
std::move(buffer_result.value()),
10
);
}
// 创建色差参数缓冲
{
auto buffer_result = res_mgr_.create_buffer(
@@ -282,6 +302,10 @@ namespace mirage {
auto blur_pipeline = create_effect_pipeline(render_pass, shaders::blur_frag_spirv);
pipelines_[0] = blur_pipeline;
// 创建 vignette pipelinevariant index 1
auto vignette_pipeline = create_effect_pipeline(render_pass, shaders::vignette_frag_spirv);
pipelines_[1] = vignette_pipeline;
// 创建 chromatic_aberration pipelinevariant index 2
auto ca_pipeline = create_effect_pipeline(render_pass, shaders::chromatic_aberration_frag_spirv);
pipelines_[2] = ca_pipeline;
@@ -458,13 +482,28 @@ namespace mirage {
// 根据 effect 类型分发
std::visit([&](const auto& eff) {
using T = std::decay_t<decltype(eff)>;
if constexpr (std::is_same_v<T, blur_effect>) {
apply_blur(cmd, target, eff, time);
}
else if constexpr (std::is_same_v<T, chromatic_aberration_effect>) {
apply_chromatic_aberration(cmd, target, eff, time);
}
// 其他后效类型可以在这里添加
else if constexpr (std::is_same_v<T, vignette_effect>) {
apply_vignette(cmd, target, eff, time);
}
else if constexpr (std::is_same_v<T, color_adjust_effect>) {
// TODO: 实现 color_adjust 效果
}
else if constexpr (std::is_same_v<T, color_tint_effect>) {
// TODO: 实现 color_tint 效果
}
else if constexpr (std::is_same_v<T, noise_effect>) {
// TODO: 实现 noise 效果
}
else if constexpr (std::is_same_v<T, custom_shader_effect>) {
// TODO: 实现 custom_shader 效果
}
}, effect);
}
@@ -657,6 +696,103 @@ namespace mirage {
blit_to_target(cmd, *temp_target_, target, effect.position, effect.size);
}
void post_effect_applicator::apply_vignette(
vk::CommandBuffer cmd,
offscreen_target& target,
const vignette_effect& effect,
float time
) {
// 准备参数
vignette_params params{};
params.radius = effect.radius;
params.softness = effect.softness;
params.tint_color[0] = effect.tint.r;
params.tint_color[1] = effect.tint.g;
params.tint_color[2] = effect.tint.b;
params.tint_color[3] = effect.tint.a;
// 上传参数
vignette_params_buffer_->upload(std::span<const vignette_params>(&params, 1), 0);
// 准备 target 为着色器读取
target.transition_to(cmd, offscreen_target::state::shader_read);
// 分配并更新 descriptor sets
auto [tex_set, param_set] = allocate_and_update_descriptors(
target.view(),
vignette_params_buffer_->get_buffer().buffer,
0,
sizeof(vignette_params)
);
// 开始渲染到临时目标
temp_target_->begin_render(cmd, true); // clear
// 绑定 pipeline
auto pipeline = pipelines_[1]; // vignette variant index
cmd.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
// 绑定 descriptor sets
std::array<vk::DescriptorSet, 2> sets = {tex_set, param_set};
cmd.bindDescriptorSets(
vk::PipelineBindPoint::eGraphics,
pipeline_layout_,
0,
static_cast<uint32_t>(sets.size()),
sets.data(),
0, nullptr
);
// 设置视口和裁剪
vk::Viewport viewport{
0.0f, 0.0f,
static_cast<float>(width_), static_cast<float>(height_),
0.0f, 1.0f
};
cmd.setViewport(0, 1, &viewport);
vk::Rect2D scissor{{0, 0}, {width_, height_}};
cmd.setScissor(0, 1, &scissor);
// 设置 push constants
post_effect_push_constants pc{};
float w = static_cast<float>(width_);
float h = static_cast<float>(height_);
pc.projection[0] = 2.0f / w;
pc.projection[5] = -2.0f / h;
pc.projection[10] = 1.0f;
pc.projection[12] = -1.0f;
pc.projection[13] = 1.0f;
pc.projection[15] = 1.0f;
pc.viewport_size[0] = w;
pc.viewport_size[1] = h;
pc.time = time;
pc.effect_rect[0] = effect.position.x();
pc.effect_rect[1] = effect.position.y();
pc.effect_rect[2] = effect.size.x();
pc.effect_rect[3] = effect.size.y();
pc.intensity = effect.intensity;
cmd.pushConstants(
pipeline_layout_,
vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment,
0,
sizeof(post_effect_push_constants),
&pc
);
// 绘制全屏四边形
cmd.draw(4, 1, 0, 0);
// 结束渲染
temp_target_->end_render(cmd, true); // 转换为 shader_read
// Blit 回目标
blit_to_target(cmd, *temp_target_, target, effect.position, effect.size);
}
// ============================================================================
// 辅助方法
// ============================================================================
@@ -764,7 +900,6 @@ namespace mirage {
// 如果裁剪后区域无效(完全在目标图像外),则跳过 blit
if (dst_x0 >= dst_x1 || dst_y0 >= dst_y1) {
std::cout << "[DEBUG] Blit 区域无效,跳过\n";
return;
}

View File

@@ -30,6 +30,13 @@ namespace mirage {
float _pad; ///< 填充对齐
};
/// 暗角效果参数
struct vignette_params {
float radius; ///< 暗角半径
float softness; ///< 边缘柔和度
float tint_color[4]; ///< vec4 暗角颜色
};
/// 色差效果参数
struct chromatic_aberration_params {
float offset[2]; ///< RGB 通道偏移
@@ -113,6 +120,7 @@ namespace mirage {
// 参数缓冲区(用于各种后效)
std::optional<typed_buffer<blur_params>> blur_params_buffer_;
std::optional<typed_buffer<vignette_params>> vignette_params_buffer_;
std::optional<typed_buffer<chromatic_aberration_params>> ca_params_buffer_;
// 当前尺寸
@@ -152,6 +160,13 @@ namespace mirage {
float time
);
void apply_vignette(
vk::CommandBuffer cmd,
offscreen_target& target,
const vignette_effect& effect,
float time
);
/// 辅助方法:分配并更新 descriptor set
auto allocate_and_update_descriptors(
vk::ImageView source_view,