diff --git a/src/render/pipeline/command_processor.cpp b/src/render/pipeline/command_processor.cpp index 649973a..e5938cb 100644 --- a/src/render/pipeline/command_processor.cpp +++ b/src/render/pipeline/command_processor.cpp @@ -2,6 +2,7 @@ #include "renderer/vertex_types.h" #include #include +#include namespace mirage { void command_processor::set_viewport_size(const vector2f_t& size) { diff --git a/src/render/pipeline/post_effect_applicator.cpp b/src/render/pipeline/post_effect_applicator.cpp index 38811ee..a2e3e51 100644 --- a/src/render/pipeline/post_effect_applicator.cpp +++ b/src/render/pipeline/post_effect_applicator.cpp @@ -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 pipeline(variant index 1) + auto vignette_pipeline = create_effect_pipeline(render_pass, shaders::vignette_frag_spirv); + pipelines_[1] = vignette_pipeline; + // 创建 chromatic_aberration pipeline(variant 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; + if constexpr (std::is_same_v) { apply_blur(cmd, target, eff, time); } else if constexpr (std::is_same_v) { apply_chromatic_aberration(cmd, target, eff, time); } - // 其他后效类型可以在这里添加 + else if constexpr (std::is_same_v) { + apply_vignette(cmd, target, eff, time); + } + else if constexpr (std::is_same_v) { + // TODO: 实现 color_adjust 效果 + } + else if constexpr (std::is_same_v) { + // TODO: 实现 color_tint 效果 + } + else if constexpr (std::is_same_v) { + // TODO: 实现 noise 效果 + } + else if constexpr (std::is_same_v) { + // 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(¶ms, 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 sets = {tex_set, param_set}; + cmd.bindDescriptorSets( + vk::PipelineBindPoint::eGraphics, + pipeline_layout_, + 0, + static_cast(sets.size()), + sets.data(), + 0, nullptr + ); + + // 设置视口和裁剪 + vk::Viewport viewport{ + 0.0f, 0.0f, + static_cast(width_), static_cast(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(width_); + float h = static_cast(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; } diff --git a/src/render/pipeline/post_effect_applicator.h b/src/render/pipeline/post_effect_applicator.h index ae82d64..33298da 100644 --- a/src/render/pipeline/post_effect_applicator.h +++ b/src/render/pipeline/post_effect_applicator.h @@ -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> blur_params_buffer_; + std::optional> vignette_params_buffer_; std::optional> 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,