#pragma once /* * Copyright (C) 2024 Brett Terpstra * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef BLT_GRAPHICS_POST_PROCESS_H #define BLT_GRAPHICS_POST_PROCESS_H #include #include #include #include #include #include #include #include #include #include namespace blt::gfx { class pp_engine_t; class pp_step_t; enum class pp_request_t : u64 { BIND_BUFFER = 0x1, CLEAR_BUFFER = 0x2 }; class pp_step_t { public: virtual void create() {} // only called on render() virtual void draw(frame_buffer_t&) {} // only called on bind() virtual void draw() {} // called after rendering, provides previous framebuffer virtual void post_draw(frame_buffer_t&) {} auto& getBuffer() { return draw_buffer; } auto& getShader() { return *shader; } bool hasShader() { return shader != nullptr; } virtual bool requests(pp_request_t) { return true; } virtual ~pp_step_t() { draw_buffer.destroy(); } protected: frame_buffer_t draw_buffer; std::unique_ptr shader; }; class pp_in_place_t : public pp_step_t { public: pp_in_place_t(frame_buffer_t::attachment_t from): from(from), to(from) {} pp_in_place_t(frame_buffer_t::attachment_t from, frame_buffer_t::attachment_t to): from(from), to(to) {} void draw(frame_buffer_t& previous) override; void post_draw(frame_buffer_t& previous) override; void create() override; bool requests(blt::gfx::pp_request_t request) override { return static_cast(request) & ~(static_cast(pp_request_t::BIND_BUFFER) | static_cast(pp_request_t::CLEAR_BUFFER)); } protected: std::unique_ptr shader_pass; frame_buffer_t::attachment_t from; frame_buffer_t::attachment_t to; }; class pp_render_target_t : public pp_step_t { public: void create() override; void draw() override; }; class pp_to_screen_step_t : public pp_step_t { public: void create() override; void draw(frame_buffer_t& previous) override; }; class pp_outline_target_t : public pp_step_t { public: void create() override; void draw() override; }; class pp_outline_step_t : public pp_step_t { public: pp_outline_step_t(matrix_state_manager& manager): manager(manager) {} void create() override; void draw(frame_buffer_t& previous) override; private: matrix_state_manager& manager; }; class pp_blur_step_inplace_t : public pp_in_place_t { public: pp_blur_step_inplace_t(matrix_state_manager& manager, frame_buffer_t::attachment_t from, i32 x_blur = 2, i32 y_blur = 2): pp_in_place_t(from), manager(manager), x_blur(x_blur), y_blur(y_blur) {} pp_blur_step_inplace_t(matrix_state_manager& manager, frame_buffer_t::attachment_t from, frame_buffer_t::attachment_t to, i32 x_blur = 2, i32 y_blur = 2): pp_in_place_t(from, to), manager(manager), x_blur(x_blur), y_blur(y_blur) {} void create() override; void draw(frame_buffer_t& previous) override; private: matrix_state_manager& manager; i32 x_blur; i32 y_blur; }; class pp_overlay_blur_step_t : public pp_in_place_t { public: pp_overlay_blur_step_t(frame_buffer_t::attachment_t from, i32 x_blur = 2, i32 y_blur = 2): pp_in_place_t(from), x_blur(x_blur), y_blur(y_blur) {} pp_overlay_blur_step_t(frame_buffer_t::attachment_t from, frame_buffer_t::attachment_t to, i32 x_blur = 2, i32 y_blur = 2): pp_in_place_t(from, to), x_blur(x_blur), y_blur(y_blur) {} void create() override; void draw(frame_buffer_t& previous) override; private: i32 x_blur; i32 y_blur; }; class pp_multiplier_step_inplace_t : public pp_in_place_t { public: pp_multiplier_step_inplace_t(frame_buffer_t::attachment_t from, const vec4& multiplier = vec4{2, 2, 2, 2}): pp_in_place_t(from), multiplier(multiplier) {} pp_multiplier_step_inplace_t(frame_buffer_t::attachment_t from, frame_buffer_t::attachment_t to, const vec4& multiplier = vec4{2, 2, 2, 2}): pp_in_place_t(from, to), multiplier(multiplier) {} void create() override; void draw(frame_buffer_t& previous) override; private: vec4 multiplier; }; class pp_mouse_highlight_step_t : public pp_in_place_t { public: using pp_in_place_t::pp_in_place_t; void create() override; void draw(frame_buffer_t& previous) override; }; class pp_engine_t { public: void create(); void bind(); void render(); void cleanup(); void addStep(std::unique_ptr step) { steps.emplace_back(std::move(step)); } static std::unique_ptr createShader(std::string_view fragment, std::optional> engine = {}); static std::unique_ptr make_basic_pp() { return make_single_pp(std::make_unique()); } static std::unique_ptr make_single_pp(std::unique_ptr step) { auto engine = new pp_engine_t(); engine->addStep(std::move(step)); return std::unique_ptr(engine); } template static std::unique_ptr make_multi_pp(Args... steps) { auto engine = new pp_engine_t(); (engine->addStep(std::move(steps)), ...); return std::unique_ptr(engine); } static void render_quad(); private: pp_engine_t() = default; pp_step_t& find_last_frame_buffer(size_t index); std::vector> steps; std::unique_ptr screen_vao; }; } #endif //BLT_GRAPHICS_POST_PROCESS_H