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 9f415662..156ed350 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 0b14eab8..b1e46ce3 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;