Skip to content

Commit

Permalink
filter/denoising: Restore alpha after processing
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Xaymar committed Oct 6, 2021
1 parent c704b99 commit ef012db
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 3 deletions.
25 changes: 22 additions & 3 deletions source/filters/filter-denoising.cpp
Expand Up @@ -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) {
Expand Down Expand Up @@ -375,8 +389,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);
}
}
Expand Down Expand Up @@ -560,7 +579,7 @@ denoising_factory::denoising_factory()
// 3. In any other case, register the filter!
_info.id = S_PREFIX "filter-video-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();
Expand Down
5 changes: 5 additions & 0 deletions source/filters/filter-denoising.hpp
Expand Up @@ -22,6 +22,7 @@
#include <atomic>
#include <memory>
#include <mutex>
#include "obs/gs/gs-effect.hpp"
#include "obs/gs/gs-rendertarget.hpp"
#include "obs/gs/gs-texture.hpp"
#include "obs/obs-source-factory.hpp"
Expand Down Expand Up @@ -52,6 +53,10 @@ namespace streamfx::filter::denoising {
std::mutex _provider_lock;
std::shared_ptr<util::threadpool::task> _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;
Expand Down

0 comments on commit ef012db

Please sign in to comment.