filter/upscaling: Restore alpha after processing

As none of the known Upscaling algorithms handle Alpha, we need to manually restore and interpolate it properly. While this technically reduces visual quality slightly, the chances of this being noticed are slim to none considering that Upscaling is already a questionable solution to quality. Linear was picked here as it produces the best overall result for scaling, keeping gradients mostly in one piece. Mostly.

Fixes #646
This commit is contained in:
Michael Fabian 'Xaymar' Dirks 2021-10-06 02:15:28 +02:00
parent fc479bcdaf
commit 5952dfe73f
2 changed files with 28 additions and 5 deletions

View file

@ -102,6 +102,20 @@ upscaling_instance::upscaling_instance(obs_data_t* data, obs_source_t* self)
_input = std::make_shared<::streamfx::obs::gs::rendertarget>(GS_RGBA_UNORM, GS_ZS_NONE); _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. _input->render(1, 1); // Preallocate the RT on the driver and GPU.
_output = _input->get_texture(); _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) { if (data) {
@ -231,8 +245,7 @@ void upscaling_instance::video_render(gs_effect_t* effect)
} }
#ifdef ENABLE_PROFILING #ifdef ENABLE_PROFILING
::streamfx::obs::gs::debug_marker profiler0{::streamfx::obs::gs::debug_color_source, ::streamfx::obs::gs::debug_marker profiler0{::streamfx::obs::gs::debug_color_source, "StreamFX Upscaling"};
"StreamFX Video Super-Resolution"};
::streamfx::obs::gs::debug_marker profiler0_0{::streamfx::obs::gs::debug_color_gray, "'%s' on '%s'", ::streamfx::obs::gs::debug_marker profiler0_0{::streamfx::obs::gs::debug_color_gray, "'%s' on '%s'",
obs_source_get_name(_self), obs_source_get_name(parent)}; obs_source_get_name(_self), obs_source_get_name(parent)};
#endif #endif
@ -310,8 +323,13 @@ void upscaling_instance::video_render(gs_effect_t* effect)
#ifdef ENABLE_PROFILING #ifdef ENABLE_PROFILING
::streamfx::obs::gs::debug_marker profiler1{::streamfx::obs::gs::debug_color_render, "Render"}; ::streamfx::obs::gs::debug_marker profiler1{::streamfx::obs::gs::debug_color_render, "Render"};
#endif #endif
gs_effect_set_texture(gs_effect_get_param_by_name(effect, "image"), _output->get_object()); if (_standard_effect->has_parameter("Channel0", ::streamfx::obs::gs::effect_parameter::type::Texture)) {
while (gs_effect_loop(effect, "Draw")) { _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, _out_size.first, _out_size.second); gs_draw_sprite(nullptr, 0, _out_size.first, _out_size.second);
} }
} }
@ -509,7 +527,7 @@ upscaling_factory::upscaling_factory()
// 3. In any other case, register the filter! // 3. In any other case, register the filter!
_info.id = S_PREFIX "filter-upscaling"; _info.id = S_PREFIX "filter-upscaling";
_info.type = OBS_SOURCE_TYPE_FILTER; _info.type = OBS_SOURCE_TYPE_FILTER;
_info.output_flags = OBS_SOURCE_VIDEO /*| OBS_SOURCE_SRGB*/; _info.output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_CUSTOM_DRAW /*| OBS_SOURCE_SRGB*/;
set_resolution_enabled(true); set_resolution_enabled(true);
finish_setup(); finish_setup();

View file

@ -22,6 +22,7 @@
#include <atomic> #include <atomic>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
#include "obs/gs/gs-effect.hpp"
#include "obs/gs/gs-rendertarget.hpp" #include "obs/gs/gs-rendertarget.hpp"
#include "obs/gs/gs-texture.hpp" #include "obs/gs/gs-texture.hpp"
#include "obs/obs-source-factory.hpp" #include "obs/obs-source-factory.hpp"
@ -53,6 +54,10 @@ namespace streamfx::filter::upscaling {
std::mutex _provider_lock; std::mutex _provider_lock;
std::shared_ptr<util::threadpool::task> _provider_task; 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::rendertarget> _input;
std::shared_ptr<::streamfx::obs::gs::texture> _output; std::shared_ptr<::streamfx::obs::gs::texture> _output;
bool _dirty; bool _dirty;