From fc479bcdaf8f46ee9571afe04608886787875bf3 Mon Sep 17 00:00:00 2001 From: Michael Fabian 'Xaymar' Dirks Date: Wed, 6 Oct 2021 02:13:26 +0200 Subject: [PATCH] filter/denoising: Restore alpha after processing As the Alpha channel is completely ignored and possibly destroyed by denoising algorithms, we should restore the Alpha channel manually. Linear interpolation was chosen here as it will behave like Point if the size matches, and properly interpolate if the size doesn't match. Fixes: #646 --- source/filters/filter-denoising.cpp | 25 ++++++++++++++++++++++--- source/filters/filter-denoising.hpp | 5 +++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/source/filters/filter-denoising.cpp b/source/filters/filter-denoising.cpp index 9f41566..156ed35 100644 --- a/source/filters/filter-denoising.cpp +++ b/source/filters/filter-denoising.cpp @@ -97,6 +97,20 @@ denoising_instance::denoising_instance(obs_data_t* data, obs_source_t* self) _input = std::make_shared<::streamfx::obs::gs::rendertarget>(GS_RGBA_UNORM, GS_ZS_NONE); _input->render(1, 1); // Preallocate the RT on the driver and GPU. _output = _input->get_texture(); + + // Load the required effect. + _standard_effect = + std::make_shared<::streamfx::obs::gs::effect>(::streamfx::data_file_path("effects/standard.effect")); + + // Create Samplers + _channel0_sampler = std::make_shared<::streamfx::obs::gs::sampler>(); + _channel0_sampler->set_filter(gs_sample_filter::GS_FILTER_LINEAR); + _channel0_sampler->set_address_mode_u(GS_ADDRESS_CLAMP); + _channel0_sampler->set_address_mode_v(GS_ADDRESS_CLAMP); + _channel1_sampler = std::make_shared<::streamfx::obs::gs::sampler>(); + _channel1_sampler->set_filter(gs_sample_filter::GS_FILTER_LINEAR); + _channel1_sampler->set_address_mode_u(GS_ADDRESS_CLAMP); + _channel1_sampler->set_address_mode_v(GS_ADDRESS_CLAMP); } if (data) { @@ -323,8 +337,13 @@ void denoising_instance::video_render(gs_effect_t* effect) #ifdef ENABLE_PROFILING ::streamfx::obs::gs::debug_marker profiler1{::streamfx::obs::gs::debug_color_render, "Render"}; #endif - gs_effect_set_texture(gs_effect_get_param_by_name(effect, "image"), _output->get_object()); - while (gs_effect_loop(effect, "Draw")) { + if (_standard_effect->has_parameter("Channel0", ::streamfx::obs::gs::effect_parameter::type::Texture)) { + _standard_effect->get_parameter("Channel0").set_texture(_output); + } + if (_standard_effect->has_parameter("Channel1", ::streamfx::obs::gs::effect_parameter::type::Texture)) { + _standard_effect->get_parameter("Channel1").set_texture(_input->get_texture()); + } + while (gs_effect_loop(_standard_effect->get_object(), "RestoreAlpha")) { gs_draw_sprite(nullptr, 0, _size.first, _size.second); } } @@ -508,7 +527,7 @@ denoising_factory::denoising_factory() // 3. In any other case, register the filter! _info.id = S_PREFIX "filter-denoising"; _info.type = OBS_SOURCE_TYPE_FILTER; - _info.output_flags = OBS_SOURCE_VIDEO; + _info.output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_CUSTOM_DRAW; set_resolution_enabled(true); finish_setup(); diff --git a/source/filters/filter-denoising.hpp b/source/filters/filter-denoising.hpp index 0b14eab..b1e46ce 100644 --- a/source/filters/filter-denoising.hpp +++ b/source/filters/filter-denoising.hpp @@ -22,6 +22,7 @@ #include #include #include +#include "obs/gs/gs-effect.hpp" #include "obs/gs/gs-rendertarget.hpp" #include "obs/gs/gs-texture.hpp" #include "obs/obs-source-factory.hpp" @@ -52,6 +53,10 @@ namespace streamfx::filter::denoising { std::mutex _provider_lock; std::shared_ptr _provider_task; + std::shared_ptr<::streamfx::obs::gs::effect> _standard_effect; + std::shared_ptr<::streamfx::obs::gs::sampler> _channel0_sampler; + std::shared_ptr<::streamfx::obs::gs::sampler> _channel1_sampler; + std::shared_ptr<::streamfx::obs::gs::rendertarget> _input; std::shared_ptr<::streamfx::obs::gs::texture> _output; bool _dirty;