filter-*, source-*: Fix rendering of filters and duplication of sources

This commit is contained in:
Michael Fabian 'Xaymar' Dirks 2019-12-17 23:52:10 +01:00
parent 1c7fd1495c
commit 16347beb87
7 changed files with 211 additions and 206 deletions

View File

@ -547,6 +547,7 @@ filter::blur::blur_factory::blur_factory()
_info.type = OBS_SOURCE_TYPE_FILTER; _info.type = OBS_SOURCE_TYPE_FILTER;
_info.output_flags = OBS_SOURCE_VIDEO; _info.output_flags = OBS_SOURCE_VIDEO;
set_resolution_enabled(false);
finish_setup(); finish_setup();
} }

View File

@ -79,8 +79,6 @@ filter::color_grade::color_grade_instance::~color_grade_instance() {}
filter::color_grade::color_grade_instance::color_grade_instance(obs_data_t* data, obs_source_t* self) filter::color_grade::color_grade_instance::color_grade_instance(obs_data_t* data, obs_source_t* self)
: obs::source_instance(data, self) : obs::source_instance(data, self)
{ {
update(data);
{ {
char* file = obs_module_file("effects/color-grade.effect"); char* file = obs_module_file("effects/color-grade.effect");
if (file) { if (file) {
@ -110,6 +108,8 @@ filter::color_grade::color_grade_instance::color_grade_instance(obs_data_t* data
} }
_tex_grade = _rt_grade->get_texture(); _tex_grade = _rt_grade->get_texture();
} }
update(data);
} }
float_t fix_gamma_value(double_t v) float_t fix_gamma_value(double_t v)
@ -261,6 +261,7 @@ filter::color_grade::color_grade_factory::color_grade_factory()
_info.type = OBS_SOURCE_TYPE_FILTER; _info.type = OBS_SOURCE_TYPE_FILTER;
_info.output_flags = OBS_SOURCE_VIDEO; _info.output_flags = OBS_SOURCE_VIDEO;
set_resolution_enabled(false);
finish_setup(); finish_setup();
} }

View File

@ -38,6 +38,8 @@ filter::displacement::displacement_instance::displacement_instance(obs_data_t* d
} }
_effect = gs::effect::create(effect); _effect = gs::effect::create(effect);
update(data);
} }
filter::displacement::displacement_instance::~displacement_instance() filter::displacement::displacement_instance::~displacement_instance()
@ -127,6 +129,7 @@ filter::displacement::displacement_factory::displacement_factory()
_info.type = OBS_SOURCE_TYPE_FILTER; _info.type = OBS_SOURCE_TYPE_FILTER;
_info.output_flags = OBS_SOURCE_VIDEO; _info.output_flags = OBS_SOURCE_VIDEO;
set_resolution_enabled(false);
finish_setup(); finish_setup();
} }

View File

@ -53,21 +53,21 @@ filter::dynamic_mask::dynamic_mask_instance::dynamic_mask_instance(obs_data_t* s
: obs::source_instance(settings, self), _have_filter_texture(false), _have_input_texture(false), : obs::source_instance(settings, self), _have_filter_texture(false), _have_input_texture(false),
_have_final_texture(false), _precalc(), _effect() _have_final_texture(false), _precalc(), _effect()
{ {
this->_filter_rt = std::make_shared<gs::rendertarget>(GS_RGBA, GS_ZS_NONE); _filter_rt = std::make_shared<gs::rendertarget>(GS_RGBA, GS_ZS_NONE);
this->_final_rt = std::make_shared<gs::rendertarget>(GS_RGBA, GS_ZS_NONE); _final_rt = std::make_shared<gs::rendertarget>(GS_RGBA, GS_ZS_NONE);
{ {
char* file = obs_module_file("effects/channel-mask.effect"); char* file = obs_module_file("effects/channel-mask.effect");
try { try {
this->_effect = gs::effect::create(file); _effect = gs::effect::create(file);
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
P_LOG_ERROR("Loading channel mask effect failed with error(s):\n%s", ex.what()); P_LOG_ERROR("Loading channel mask effect failed with error(s):\n%s", ex.what());
} }
assert(this->_effect != nullptr); assert(_effect != nullptr);
bfree(file); bfree(file);
} }
this->update(settings); update(settings);
} }
filter::dynamic_mask::dynamic_mask_instance::~dynamic_mask_instance() {} filter::dynamic_mask::dynamic_mask_instance::~dynamic_mask_instance() {}
@ -76,49 +76,49 @@ void filter::dynamic_mask::dynamic_mask_instance::update(obs_data_t* settings)
{ {
// Update source. // Update source.
try { try {
this->_input = std::make_shared<obs::source>(obs_data_get_string(settings, ST_INPUT)); _input = std::make_shared<obs::source>(obs_data_get_string(settings, ST_INPUT));
this->_input_capture = std::make_shared<gfx::source_texture>(this->_input, _self); _input_capture = std::make_shared<gfx::source_texture>(_input, _self);
this->_input->events.rename += std::bind(&filter::dynamic_mask::dynamic_mask_instance::input_renamed, this, _input->events.rename += std::bind(&filter::dynamic_mask::dynamic_mask_instance::input_renamed, this,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
} catch (...) { } catch (...) {
this->_input.reset(); _input.reset();
this->_input_capture.reset(); _input_capture.reset();
this->_input_texture.reset(); _input_texture.reset();
} }
// Update data store // Update data store
for (auto kv1 : channel_translations) { for (auto kv1 : channel_translations) {
auto found = this->_channels.find(kv1.first); auto found = _channels.find(kv1.first);
if (found == this->_channels.end()) { if (found == _channels.end()) {
this->_channels.insert({kv1.first, channel_data()}); _channels.insert({kv1.first, channel_data()});
found = this->_channels.find(kv1.first); found = _channels.find(kv1.first);
if (found == this->_channels.end()) { if (found == _channels.end()) {
assert(found != this->_channels.end()); assert(found != _channels.end());
throw std::runtime_error("Unable to insert element into data _store."); throw std::runtime_error("Unable to insert element into data _store.");
} }
} }
std::string chv_key = std::string(ST_CHANNEL_VALUE) + "." + kv1.second; std::string chv_key = std::string(ST_CHANNEL_VALUE) + "." + kv1.second;
found->second.value = static_cast<float_t>(obs_data_get_double(settings, chv_key.c_str())); found->second.value = static_cast<float_t>(obs_data_get_double(settings, chv_key.c_str()));
this->_precalc.base.ptr[static_cast<size_t>(kv1.first)] = found->second.value; _precalc.base.ptr[static_cast<size_t>(kv1.first)] = found->second.value;
std::string chm_key = std::string(ST_CHANNEL_MULTIPLIER) + "." + kv1.second; std::string chm_key = std::string(ST_CHANNEL_MULTIPLIER) + "." + kv1.second;
found->second.scale = static_cast<float_t>(obs_data_get_double(settings, chm_key.c_str())); found->second.scale = static_cast<float_t>(obs_data_get_double(settings, chm_key.c_str()));
this->_precalc.scale.ptr[static_cast<size_t>(kv1.first)] = found->second.scale; _precalc.scale.ptr[static_cast<size_t>(kv1.first)] = found->second.scale;
vec4* ch = &_precalc.matrix.x; vec4* ch = &_precalc.matrix.x;
switch (kv1.first) { switch (kv1.first) {
case channel::Red: case channel::Red:
ch = &this->_precalc.matrix.x; ch = &_precalc.matrix.x;
break; break;
case channel::Green: case channel::Green:
ch = &this->_precalc.matrix.y; ch = &_precalc.matrix.y;
break; break;
case channel::Blue: case channel::Blue:
ch = &this->_precalc.matrix.z; ch = &_precalc.matrix.z;
break; break;
case channel::Alpha: case channel::Alpha:
ch = &this->_precalc.matrix.t; ch = &_precalc.matrix.t;
break; break;
default: default:
break; break;
@ -140,17 +140,17 @@ void filter::dynamic_mask::dynamic_mask_instance::load(obs_data_t* settings)
void filter::dynamic_mask::dynamic_mask_instance::save(obs_data_t* settings) void filter::dynamic_mask::dynamic_mask_instance::save(obs_data_t* settings)
{ {
if (this->_input) { if (_input) {
obs_data_set_string(settings, ST_INPUT, obs_source_get_name(this->_input->get())); obs_data_set_string(settings, ST_INPUT, obs_source_get_name(_input->get()));
} }
for (auto kv1 : channel_translations) { for (auto kv1 : channel_translations) {
auto found = this->_channels.find(kv1.first); auto found = _channels.find(kv1.first);
if (found == this->_channels.end()) { if (found == _channels.end()) {
this->_channels.insert({kv1.first, channel_data()}); _channels.insert({kv1.first, channel_data()});
found = this->_channels.find(kv1.first); found = _channels.find(kv1.first);
if (found == this->_channels.end()) { if (found == _channels.end()) {
assert(found != this->_channels.end()); assert(found != _channels.end());
throw std::runtime_error("Unable to insert element into data _store."); throw std::runtime_error("Unable to insert element into data _store.");
} }
} }
@ -212,8 +212,8 @@ void filter::dynamic_mask::dynamic_mask_instance::video_tick(float)
void filter::dynamic_mask::dynamic_mask_instance::video_render(gs_effect_t* in_effect) void filter::dynamic_mask::dynamic_mask_instance::video_render(gs_effect_t* in_effect)
{ {
obs_source_t* parent = obs_filter_get_parent(this->_self); obs_source_t* parent = obs_filter_get_parent(_self);
obs_source_t* target = obs_filter_get_target(this->_self); obs_source_t* target = obs_filter_get_target(_self);
uint32_t width = obs_source_get_base_width(target); uint32_t width = obs_source_get_base_width(target);
uint32_t height = obs_source_get_base_height(target); uint32_t height = obs_source_get_base_height(target);
@ -229,8 +229,8 @@ void filter::dynamic_mask::dynamic_mask_instance::video_render(gs_effect_t* in_e
try { // Capture filter and input try { // Capture filter and input
if (!_have_filter_texture) { if (!_have_filter_texture) {
if (obs_source_process_filter_begin(this->_self, GS_RGBA, OBS_ALLOW_DIRECT_RENDERING)) { if (obs_source_process_filter_begin(_self, GS_RGBA, OBS_ALLOW_DIRECT_RENDERING)) {
auto op = this->_filter_rt->render(width, height); auto op = _filter_rt->render(width, height);
gs_blend_state_push(); gs_blend_state_push();
gs_reset_blend_state(); gs_reset_blend_state();
@ -249,26 +249,26 @@ void filter::dynamic_mask::dynamic_mask_instance::video_render(gs_effect_t* in_e
gs_stencil_op(GS_STENCIL_BOTH, GS_KEEP, GS_KEEP, GS_KEEP); gs_stencil_op(GS_STENCIL_BOTH, GS_KEEP, GS_KEEP, GS_KEEP);
gs_ortho(0, (float)width, 0, (float)height, -1., 1.); gs_ortho(0, (float)width, 0, (float)height, -1., 1.);
obs_source_process_filter_end(this->_self, default_effect, width, height); obs_source_process_filter_end(_self, default_effect, width, height);
gs_blend_state_pop(); gs_blend_state_pop();
} else { } else {
throw std::runtime_error("Failed to render filter."); throw std::runtime_error("Failed to render filter.");
} }
this->_filter_texture = this->_filter_rt->get_texture(); _filter_texture = _filter_rt->get_texture();
this->_have_filter_texture = true; _have_filter_texture = true;
} }
if (!_have_input_texture) { if (!_have_input_texture) {
this->_input_texture = this->_input_capture->render(_input->width(), _input->height()); _input_texture = _input_capture->render(_input->width(), _input->height());
this->_have_input_texture = true; _have_input_texture = true;
} }
// Draw source // Draw source
if (!this->_have_final_texture) { if (!_have_final_texture) {
{ {
auto op = this->_final_rt->render(width, height); auto op = _final_rt->render(width, height);
gs_blend_state_push(); gs_blend_state_push();
gs_reset_blend_state(); gs_reset_blend_state();
@ -287,12 +287,12 @@ void filter::dynamic_mask::dynamic_mask_instance::video_render(gs_effect_t* in_e
gs_stencil_op(GS_STENCIL_BOTH, GS_KEEP, GS_KEEP, GS_KEEP); gs_stencil_op(GS_STENCIL_BOTH, GS_KEEP, GS_KEEP, GS_KEEP);
gs_ortho(0, (float)width, 0, (float)height, -1., 1.); gs_ortho(0, (float)width, 0, (float)height, -1., 1.);
_effect.get_parameter("pMaskInputA").set_texture(this->_filter_texture); _effect.get_parameter("pMaskInputA").set_texture(_filter_texture);
_effect.get_parameter("pMaskInputB").set_texture(this->_input_texture); _effect.get_parameter("pMaskInputB").set_texture(_input_texture);
_effect.get_parameter("pMaskBase").set_float4(this->_precalc.base); _effect.get_parameter("pMaskBase").set_float4(_precalc.base);
_effect.get_parameter("pMaskMatrix").set_matrix(this->_precalc.matrix); _effect.get_parameter("pMaskMatrix").set_matrix(_precalc.matrix);
_effect.get_parameter("pMaskMultiplier").set_float4(this->_precalc.scale); _effect.get_parameter("pMaskMultiplier").set_float4(_precalc.scale);
while (gs_effect_loop(_effect.get(), "Mask")) { while (gs_effect_loop(_effect.get(), "Mask")) {
gs_draw_sprite(0, 0, width, height); gs_draw_sprite(0, 0, width, height);
@ -301,21 +301,20 @@ void filter::dynamic_mask::dynamic_mask_instance::video_render(gs_effect_t* in_e
gs_blend_state_pop(); gs_blend_state_pop();
} }
this->_final_texture = this->_final_rt->get_texture(); _final_texture = _final_rt->get_texture();
this->_have_final_texture = true; _have_final_texture = true;
} }
} catch (...) { } catch (...) {
obs_source_skip_video_filter(this->_self); obs_source_skip_video_filter(_self);
return; return;
} }
if (!_have_filter_texture || !_have_input_texture || !_have_final_texture) { if (!_have_filter_texture || !_have_input_texture || !_have_final_texture) {
obs_source_skip_video_filter(this->_self); obs_source_skip_video_filter(_self);
return; return;
} }
if (!this->_filter_texture->get_object() || !this->_input_texture->get_object() if (!_filter_texture->get_object() || !_input_texture->get_object() || !_final_texture->get_object()) {
|| !this->_final_texture->get_object()) { obs_source_skip_video_filter(_self);
obs_source_skip_video_filter(this->_self);
return; return;
} }
@ -334,11 +333,11 @@ void filter::dynamic_mask::dynamic_mask_instance::video_render(gs_effect_t* in_e
gs_effect_t* final_effect = in_effect ? in_effect : default_effect; gs_effect_t* final_effect = in_effect ? in_effect : default_effect;
gs_eparam_t* param = gs_effect_get_param_by_name(final_effect, "image"); gs_eparam_t* param = gs_effect_get_param_by_name(final_effect, "image");
if (!param) { if (!param) {
P_LOG_ERROR("<filter-dynamic-mask:%s> Failed to set image param.", obs_source_get_name(this->_self)); P_LOG_ERROR("<filter-dynamic-mask:%s> Failed to set image param.", obs_source_get_name(_self));
obs_source_skip_video_filter(this->_self); obs_source_skip_video_filter(_self);
return; return;
} else { } else {
gs_effect_set_texture(param, this->_final_texture->get_object()); gs_effect_set_texture(param, _final_texture->get_object());
} }
while (gs_effect_loop(final_effect, "Draw")) { while (gs_effect_loop(final_effect, "Draw")) {
gs_draw_sprite(0, 0, width, height); gs_draw_sprite(0, 0, width, height);
@ -352,6 +351,7 @@ filter::dynamic_mask::dynamic_mask_factory::dynamic_mask_factory()
_info.type = OBS_SOURCE_TYPE_FILTER; _info.type = OBS_SOURCE_TYPE_FILTER;
_info.output_flags = OBS_SOURCE_VIDEO; _info.output_flags = OBS_SOURCE_VIDEO;
set_resolution_enabled(false);
finish_setup(); finish_setup();
} }

View File

@ -82,13 +82,12 @@ filter::sdf_effects::sdf_effects_instance::sdf_effects_instance(obs_data_t* sett
auto gctx = gs::context(); auto gctx = gs::context();
vec4 transparent = {0}; vec4 transparent = {0};
this->_source_rt = std::make_shared<gs::rendertarget>(GS_RGBA, GS_ZS_NONE); _source_rt = std::make_shared<gs::rendertarget>(GS_RGBA, GS_ZS_NONE);
this->_sdf_write = std::make_shared<gs::rendertarget>(GS_RGBA32F, GS_ZS_NONE); _sdf_write = std::make_shared<gs::rendertarget>(GS_RGBA32F, GS_ZS_NONE);
this->_sdf_read = std::make_shared<gs::rendertarget>(GS_RGBA32F, GS_ZS_NONE); _sdf_read = std::make_shared<gs::rendertarget>(GS_RGBA32F, GS_ZS_NONE);
this->_output_rt = std::make_shared<gs::rendertarget>(GS_RGBA, GS_ZS_NONE); _output_rt = std::make_shared<gs::rendertarget>(GS_RGBA, GS_ZS_NONE);
std::shared_ptr<gs::rendertarget> initialize_rts[] = {this->_source_rt, this->_sdf_write, this->_sdf_read, std::shared_ptr<gs::rendertarget> initialize_rts[] = {_source_rt, _sdf_write, _sdf_read, _output_rt};
this->_output_rt};
for (auto rt : initialize_rts) { for (auto rt : initialize_rts) {
auto op = rt->render(1, 1); auto op = rt->render(1, 1);
gs_clear(GS_CLEAR_COLOR | GS_CLEAR_DEPTH, &transparent, 0, 0); gs_clear(GS_CLEAR_COLOR | GS_CLEAR_DEPTH, &transparent, 0, 0);
@ -113,6 +112,7 @@ filter::sdf_effects::sdf_effects_instance::sdf_effects_instance(obs_data_t* sett
bfree(path); bfree(path);
} }
} }
update(settings); update(settings);
} }
@ -121,7 +121,7 @@ filter::sdf_effects::sdf_effects_instance::~sdf_effects_instance() {}
void filter::sdf_effects::sdf_effects_instance::update(obs_data_t* data) void filter::sdf_effects::sdf_effects_instance::update(obs_data_t* data)
{ {
{ {
this->_outer_shadow = _outer_shadow =
obs_data_get_bool(data, ST_SHADOW_OUTER) obs_data_get_bool(data, ST_SHADOW_OUTER)
&& (obs_data_get_double(data, ST_SHADOW_OUTER_ALPHA) >= std::numeric_limits<double_t>::epsilon()); && (obs_data_get_double(data, ST_SHADOW_OUTER_ALPHA) >= std::numeric_limits<double_t>::epsilon());
{ {
@ -133,20 +133,20 @@ void filter::sdf_effects::sdf_effects_instance::update(obs_data_t* data)
uint8_t channel[4]; uint8_t channel[4];
cs c; cs c;
}; };
color = uint32_t(obs_data_get_int(data, ST_SHADOW_OUTER_COLOR)); color = uint32_t(obs_data_get_int(data, ST_SHADOW_OUTER_COLOR));
this->_outer_shadow_color.x = float_t(c.r / 255.0); _outer_shadow_color.x = float_t(c.r / 255.0);
this->_outer_shadow_color.y = float_t(c.g / 255.0); _outer_shadow_color.y = float_t(c.g / 255.0);
this->_outer_shadow_color.z = float_t(c.b / 255.0); _outer_shadow_color.z = float_t(c.b / 255.0);
this->_outer_shadow_color.w = float_t(obs_data_get_double(data, ST_SHADOW_OUTER_ALPHA) / 100.0); _outer_shadow_color.w = float_t(obs_data_get_double(data, ST_SHADOW_OUTER_ALPHA) / 100.0);
} }
this->_outer_shadow_range_min = float_t(obs_data_get_double(data, ST_SHADOW_OUTER_RANGE_MINIMUM)); _outer_shadow_range_min = float_t(obs_data_get_double(data, ST_SHADOW_OUTER_RANGE_MINIMUM));
this->_outer_shadow_range_max = float_t(obs_data_get_double(data, ST_SHADOW_OUTER_RANGE_MAXIMUM)); _outer_shadow_range_max = float_t(obs_data_get_double(data, ST_SHADOW_OUTER_RANGE_MAXIMUM));
this->_outer_shadow_offset_x = float_t(obs_data_get_double(data, ST_SHADOW_OUTER_OFFSET_X)); _outer_shadow_offset_x = float_t(obs_data_get_double(data, ST_SHADOW_OUTER_OFFSET_X));
this->_outer_shadow_offset_y = float_t(obs_data_get_double(data, ST_SHADOW_OUTER_OFFSET_Y)); _outer_shadow_offset_y = float_t(obs_data_get_double(data, ST_SHADOW_OUTER_OFFSET_Y));
} }
{ {
this->_inner_shadow = _inner_shadow =
obs_data_get_bool(data, ST_SHADOW_INNER) obs_data_get_bool(data, ST_SHADOW_INNER)
&& (obs_data_get_double(data, ST_SHADOW_INNER_ALPHA) >= std::numeric_limits<double_t>::epsilon()); && (obs_data_get_double(data, ST_SHADOW_INNER_ALPHA) >= std::numeric_limits<double_t>::epsilon());
{ {
@ -158,22 +158,21 @@ void filter::sdf_effects::sdf_effects_instance::update(obs_data_t* data)
uint8_t channel[4]; uint8_t channel[4];
cs c; cs c;
}; };
color = uint32_t(obs_data_get_int(data, ST_SHADOW_INNER_COLOR)); color = uint32_t(obs_data_get_int(data, ST_SHADOW_INNER_COLOR));
this->_inner_shadow_color.x = float_t(c.r / 255.0); _inner_shadow_color.x = float_t(c.r / 255.0);
this->_inner_shadow_color.y = float_t(c.g / 255.0); _inner_shadow_color.y = float_t(c.g / 255.0);
this->_inner_shadow_color.z = float_t(c.b / 255.0); _inner_shadow_color.z = float_t(c.b / 255.0);
this->_inner_shadow_color.w = float_t(obs_data_get_double(data, ST_SHADOW_INNER_ALPHA) / 100.0); _inner_shadow_color.w = float_t(obs_data_get_double(data, ST_SHADOW_INNER_ALPHA) / 100.0);
} }
this->_inner_shadow_range_min = float_t(obs_data_get_double(data, ST_SHADOW_INNER_RANGE_MINIMUM)); _inner_shadow_range_min = float_t(obs_data_get_double(data, ST_SHADOW_INNER_RANGE_MINIMUM));
this->_inner_shadow_range_max = float_t(obs_data_get_double(data, ST_SHADOW_INNER_RANGE_MAXIMUM)); _inner_shadow_range_max = float_t(obs_data_get_double(data, ST_SHADOW_INNER_RANGE_MAXIMUM));
this->_inner_shadow_offset_x = float_t(obs_data_get_double(data, ST_SHADOW_INNER_OFFSET_X)); _inner_shadow_offset_x = float_t(obs_data_get_double(data, ST_SHADOW_INNER_OFFSET_X));
this->_inner_shadow_offset_y = float_t(obs_data_get_double(data, ST_SHADOW_INNER_OFFSET_Y)); _inner_shadow_offset_y = float_t(obs_data_get_double(data, ST_SHADOW_INNER_OFFSET_Y));
} }
{ {
this->_outer_glow = _outer_glow = obs_data_get_bool(data, ST_GLOW_OUTER)
obs_data_get_bool(data, ST_GLOW_OUTER) && (obs_data_get_double(data, ST_GLOW_OUTER_ALPHA) >= std::numeric_limits<double_t>::epsilon());
&& (obs_data_get_double(data, ST_GLOW_OUTER_ALPHA) >= std::numeric_limits<double_t>::epsilon());
{ {
struct cs { struct cs {
uint8_t r, g, b, a; uint8_t r, g, b, a;
@ -183,24 +182,23 @@ void filter::sdf_effects::sdf_effects_instance::update(obs_data_t* data)
uint8_t channel[4]; uint8_t channel[4];
cs c; cs c;
}; };
color = uint32_t(obs_data_get_int(data, ST_GLOW_OUTER_COLOR)); color = uint32_t(obs_data_get_int(data, ST_GLOW_OUTER_COLOR));
this->_outer_glow_color.x = float_t(c.r / 255.0); _outer_glow_color.x = float_t(c.r / 255.0);
this->_outer_glow_color.y = float_t(c.g / 255.0); _outer_glow_color.y = float_t(c.g / 255.0);
this->_outer_glow_color.z = float_t(c.b / 255.0); _outer_glow_color.z = float_t(c.b / 255.0);
this->_outer_glow_color.w = float_t(obs_data_get_double(data, ST_GLOW_OUTER_ALPHA) / 100.0); _outer_glow_color.w = float_t(obs_data_get_double(data, ST_GLOW_OUTER_ALPHA) / 100.0);
} }
this->_outer_glow_width = float_t(obs_data_get_double(data, ST_GLOW_OUTER_WIDTH)); _outer_glow_width = float_t(obs_data_get_double(data, ST_GLOW_OUTER_WIDTH));
this->_outer_glow_sharpness = float_t(obs_data_get_double(data, ST_GLOW_OUTER_SHARPNESS) / 100.0); _outer_glow_sharpness = float_t(obs_data_get_double(data, ST_GLOW_OUTER_SHARPNESS) / 100.0);
this->_outer_glow_sharpness_inv = float_t(1.0f / (1.0f - this->_outer_glow_sharpness)); _outer_glow_sharpness_inv = float_t(1.0f / (1.0f - _outer_glow_sharpness));
if (this->_outer_glow_sharpness >= (1.0f - std::numeric_limits<float_t>::epsilon())) { if (_outer_glow_sharpness >= (1.0f - std::numeric_limits<float_t>::epsilon())) {
this->_outer_glow_sharpness = 1.0f - std::numeric_limits<float_t>::epsilon(); _outer_glow_sharpness = 1.0f - std::numeric_limits<float_t>::epsilon();
} }
} }
{ {
this->_inner_glow = _inner_glow = obs_data_get_bool(data, ST_GLOW_INNER)
obs_data_get_bool(data, ST_GLOW_INNER) && (obs_data_get_double(data, ST_GLOW_INNER_ALPHA) >= std::numeric_limits<double_t>::epsilon());
&& (obs_data_get_double(data, ST_GLOW_INNER_ALPHA) >= std::numeric_limits<double_t>::epsilon());
{ {
struct cs { struct cs {
uint8_t r, g, b, a; uint8_t r, g, b, a;
@ -210,23 +208,23 @@ void filter::sdf_effects::sdf_effects_instance::update(obs_data_t* data)
uint8_t channel[4]; uint8_t channel[4];
cs c; cs c;
}; };
color = uint32_t(obs_data_get_int(data, ST_GLOW_INNER_COLOR)); color = uint32_t(obs_data_get_int(data, ST_GLOW_INNER_COLOR));
this->_inner_glow_color.x = float_t(c.r / 255.0); _inner_glow_color.x = float_t(c.r / 255.0);
this->_inner_glow_color.y = float_t(c.g / 255.0); _inner_glow_color.y = float_t(c.g / 255.0);
this->_inner_glow_color.z = float_t(c.b / 255.0); _inner_glow_color.z = float_t(c.b / 255.0);
this->_inner_glow_color.w = float_t(obs_data_get_double(data, ST_GLOW_INNER_ALPHA) / 100.0); _inner_glow_color.w = float_t(obs_data_get_double(data, ST_GLOW_INNER_ALPHA) / 100.0);
} }
this->_inner_glow_width = float_t(obs_data_get_double(data, ST_GLOW_INNER_WIDTH)); _inner_glow_width = float_t(obs_data_get_double(data, ST_GLOW_INNER_WIDTH));
this->_inner_glow_sharpness = float_t(obs_data_get_double(data, ST_GLOW_INNER_SHARPNESS) / 100.0); _inner_glow_sharpness = float_t(obs_data_get_double(data, ST_GLOW_INNER_SHARPNESS) / 100.0);
this->_inner_glow_sharpness_inv = float_t(1.0f / (1.0f - this->_inner_glow_sharpness)); _inner_glow_sharpness_inv = float_t(1.0f / (1.0f - _inner_glow_sharpness));
if (this->_inner_glow_sharpness >= (1.0f - std::numeric_limits<float_t>::epsilon())) { if (_inner_glow_sharpness >= (1.0f - std::numeric_limits<float_t>::epsilon())) {
this->_inner_glow_sharpness = 1.0f - std::numeric_limits<float_t>::epsilon(); _inner_glow_sharpness = 1.0f - std::numeric_limits<float_t>::epsilon();
} }
} }
{ {
this->_outline = obs_data_get_bool(data, ST_OUTLINE) _outline = obs_data_get_bool(data, ST_OUTLINE)
&& (obs_data_get_double(data, ST_OUTLINE_ALPHA) >= std::numeric_limits<double_t>::epsilon()); && (obs_data_get_double(data, ST_OUTLINE_ALPHA) >= std::numeric_limits<double_t>::epsilon());
{ {
struct cs { struct cs {
uint8_t r, g, b, a; uint8_t r, g, b, a;
@ -236,23 +234,23 @@ void filter::sdf_effects::sdf_effects_instance::update(obs_data_t* data)
uint8_t channel[4]; uint8_t channel[4];
cs c; cs c;
}; };
color = uint32_t(obs_data_get_int(data, ST_OUTLINE_COLOR)); color = uint32_t(obs_data_get_int(data, ST_OUTLINE_COLOR));
this->_outline_color.x = float_t(c.r / 255.0); _outline_color.x = float_t(c.r / 255.0);
this->_outline_color.y = float_t(c.g / 255.0); _outline_color.y = float_t(c.g / 255.0);
this->_outline_color.z = float_t(c.b / 255.0); _outline_color.z = float_t(c.b / 255.0);
this->_outline_color.w = float_t(obs_data_get_double(data, ST_OUTLINE_ALPHA) / 100.0); _outline_color.w = float_t(obs_data_get_double(data, ST_OUTLINE_ALPHA) / 100.0);
} }
this->_outline_width = float_t(obs_data_get_double(data, ST_OUTLINE_WIDTH)); _outline_width = float_t(obs_data_get_double(data, ST_OUTLINE_WIDTH));
this->_outline_offset = float_t(obs_data_get_double(data, ST_OUTLINE_OFFSET)); _outline_offset = float_t(obs_data_get_double(data, ST_OUTLINE_OFFSET));
this->_outline_sharpness = float_t(obs_data_get_double(data, ST_OUTLINE_SHARPNESS) / 100.0); _outline_sharpness = float_t(obs_data_get_double(data, ST_OUTLINE_SHARPNESS) / 100.0);
this->_outline_sharpness_inv = float_t(1.0f / (1.0f - this->_outline_sharpness)); _outline_sharpness_inv = float_t(1.0f / (1.0f - _outline_sharpness));
if (this->_outline_sharpness >= (1.0f - std::numeric_limits<float_t>::epsilon())) { if (_outline_sharpness >= (1.0f - std::numeric_limits<float_t>::epsilon())) {
this->_outline_sharpness = 1.0f - std::numeric_limits<float_t>::epsilon(); _outline_sharpness = 1.0f - std::numeric_limits<float_t>::epsilon();
} }
} }
this->_sdf_scale = double_t(obs_data_get_double(data, ST_SDF_SCALE) / 100.0); _sdf_scale = double_t(obs_data_get_double(data, ST_SDF_SCALE) / 100.0);
this->_sdf_threshold = float_t(obs_data_get_double(data, ST_SDF_THRESHOLD) / 100.0); _sdf_threshold = float_t(obs_data_get_double(data, ST_SDF_THRESHOLD) / 100.0);
} }
void filter::sdf_effects::sdf_effects_instance::load(obs_data_t* settings) void filter::sdf_effects::sdf_effects_instance::load(obs_data_t* settings)
@ -267,7 +265,7 @@ void filter::sdf_effects::sdf_effects_instance::video_tick(float)
// Figure out the actual source size. // Figure out the actual source size.
do { do {
obs_source_t* target = obs_filter_get_target(this->_self); obs_source_t* target = obs_filter_get_target(_self);
if (target == nullptr) { if (target == nullptr) {
break; break;
} }
@ -277,21 +275,21 @@ void filter::sdf_effects::sdf_effects_instance::video_tick(float)
height = obs_source_get_height(target); height = obs_source_get_height(target);
} while (false); } while (false);
this->_source_rendered = false; _source_rendered = false;
this->_output_rendered = false; _output_rendered = false;
} }
void filter::sdf_effects::sdf_effects_instance::video_render(gs_effect_t* effect) void filter::sdf_effects::sdf_effects_instance::video_render(gs_effect_t* effect)
{ {
obs_source_t* parent = obs_filter_get_parent(this->_self); obs_source_t* parent = obs_filter_get_parent(_self);
obs_source_t* target = obs_filter_get_target(this->_self); obs_source_t* target = obs_filter_get_target(_self);
uint32_t baseW = obs_source_get_base_width(target); uint32_t baseW = obs_source_get_base_width(target);
uint32_t baseH = obs_source_get_base_height(target); uint32_t baseH = obs_source_get_base_height(target);
gs_effect_t* final_effect = effect ? effect : obs_get_base_effect(obs_base_effect::OBS_EFFECT_DEFAULT); gs_effect_t* final_effect = effect ? effect : obs_get_base_effect(obs_base_effect::OBS_EFFECT_DEFAULT);
gs_effect_t* default_effect = obs_get_base_effect(obs_base_effect::OBS_EFFECT_DEFAULT); gs_effect_t* default_effect = obs_get_base_effect(obs_base_effect::OBS_EFFECT_DEFAULT);
if (!this->_self || !parent || !target || !baseW || !baseH || !final_effect) { if (!_self || !parent || !target || !baseW || !baseH || !final_effect) {
obs_source_skip_video_filter(this->_self); obs_source_skip_video_filter(_self);
return; return;
} }
@ -314,28 +312,28 @@ void filter::sdf_effects::sdf_effects_instance::video_render(gs_effect_t* effect
gs_stencil_function(GS_STENCIL_BOTH, GS_ALWAYS); gs_stencil_function(GS_STENCIL_BOTH, GS_ALWAYS);
gs_stencil_op(GS_STENCIL_BOTH, GS_ZERO, GS_ZERO, GS_ZERO); gs_stencil_op(GS_STENCIL_BOTH, GS_ZERO, GS_ZERO, GS_ZERO);
if (!this->_source_rendered) { if (!_source_rendered) {
// Store input texture. // Store input texture.
{ {
auto op = _source_rt->render(baseW, baseH); auto op = _source_rt->render(baseW, baseH);
gs_ortho(0, (float)baseW, 0, (float)baseH, -1, 1); gs_ortho(0, (float)baseW, 0, (float)baseH, -1, 1);
gs_clear(GS_CLEAR_COLOR | GS_CLEAR_DEPTH, &color_transparent, 0, 0); gs_clear(GS_CLEAR_COLOR | GS_CLEAR_DEPTH, &color_transparent, 0, 0);
if (obs_source_process_filter_begin(this->_self, GS_RGBA, OBS_ALLOW_DIRECT_RENDERING)) { if (obs_source_process_filter_begin(_self, GS_RGBA, OBS_ALLOW_DIRECT_RENDERING)) {
obs_source_process_filter_end(this->_self, final_effect, baseW, baseH); obs_source_process_filter_end(_self, final_effect, baseW, baseH);
} else { } else {
throw std::runtime_error("failed to process source"); throw std::runtime_error("failed to process source");
} }
} }
this->_source_rt->get_texture(this->_source_texture); _source_rt->get_texture(_source_texture);
if (!this->_source_texture) { if (!_source_texture) {
throw std::runtime_error("failed to draw source"); throw std::runtime_error("failed to draw source");
} }
// Generate SDF Buffers // Generate SDF Buffers
{ {
this->_sdf_read->get_texture(this->_sdf_texture); _sdf_read->get_texture(_sdf_texture);
if (!this->_sdf_texture) { if (!_sdf_texture) {
throw std::runtime_error("SDF Backbuffer empty"); throw std::runtime_error("SDF Backbuffer empty");
} }
@ -355,41 +353,41 @@ void filter::sdf_effects::sdf_effects_instance::video_render(gs_effect_t* effect
} }
{ {
auto op = this->_sdf_write->render(uint32_t(sdfW), uint32_t(sdfH)); auto op = _sdf_write->render(uint32_t(sdfW), uint32_t(sdfH));
gs_ortho(0, (float)sdfW, 0, (float)sdfH, -1, 1); gs_ortho(0, (float)sdfW, 0, (float)sdfH, -1, 1);
gs_clear(GS_CLEAR_COLOR | GS_CLEAR_DEPTH, &color_transparent, 0, 0); gs_clear(GS_CLEAR_COLOR | GS_CLEAR_DEPTH, &color_transparent, 0, 0);
_sdf_producer_effect.get_parameter("_image").set_texture(this->_source_texture); _sdf_producer_effect.get_parameter("_image").set_texture(_source_texture);
_sdf_producer_effect.get_parameter("_size").set_float2(float_t(sdfW), float_t(sdfH)); _sdf_producer_effect.get_parameter("_size").set_float2(float_t(sdfW), float_t(sdfH));
_sdf_producer_effect.get_parameter("_sdf").set_texture(this->_sdf_texture); _sdf_producer_effect.get_parameter("_sdf").set_texture(_sdf_texture);
_sdf_producer_effect.get_parameter("_threshold").set_float(this->_sdf_threshold); _sdf_producer_effect.get_parameter("_threshold").set_float(_sdf_threshold);
while (gs_effect_loop(_sdf_producer_effect.get_object(), "Draw")) { while (gs_effect_loop(_sdf_producer_effect.get_object(), "Draw")) {
gs_draw_sprite(this->_sdf_texture->get_object(), 0, uint32_t(sdfW), uint32_t(sdfH)); gs_draw_sprite(_sdf_texture->get_object(), 0, uint32_t(sdfW), uint32_t(sdfH));
} }
} }
std::swap(this->_sdf_read, this->_sdf_write); std::swap(_sdf_read, _sdf_write);
this->_sdf_read->get_texture(this->_sdf_texture); _sdf_read->get_texture(_sdf_texture);
if (!this->_sdf_texture) { if (!_sdf_texture) {
throw std::runtime_error("SDF Backbuffer empty"); throw std::runtime_error("SDF Backbuffer empty");
} }
} }
this->_source_rendered = true; _source_rendered = true;
} }
gs_blend_state_pop(); gs_blend_state_pop();
} catch (...) { } catch (...) {
gs_blend_state_pop(); gs_blend_state_pop();
obs_source_skip_video_filter(this->_self); obs_source_skip_video_filter(_self);
return; return;
} }
if (!this->_output_rendered) { if (!_output_rendered) {
this->_output_texture = this->_source_texture; _output_texture = _source_texture;
if (!_sdf_consumer_effect) { if (!_sdf_consumer_effect) {
obs_source_skip_video_filter(this->_self); obs_source_skip_video_filter(_self);
return; return;
} }
@ -409,14 +407,14 @@ void filter::sdf_effects::sdf_effects_instance::video_render(gs_effect_t* effect
// Optimized Render path. // Optimized Render path.
try { try {
auto op = this->_output_rt->render(baseW, baseH); auto op = _output_rt->render(baseW, baseH);
gs_ortho(0, 1, 0, 1, 0, 1); gs_ortho(0, 1, 0, 1, 0, 1);
gs_enable_blending(false); gs_enable_blending(false);
gs_blend_function(GS_BLEND_ONE, GS_BLEND_ZERO); gs_blend_function(GS_BLEND_ONE, GS_BLEND_ZERO);
auto param = gs_effect_get_param_by_name(default_effect, "image"); auto param = gs_effect_get_param_by_name(default_effect, "image");
if (param) { if (param) {
gs_effect_set_texture(param, this->_output_texture->get_object()); gs_effect_set_texture(param, _output_texture->get_object());
} }
while (gs_effect_loop(default_effect, "Draw")) { while (gs_effect_loop(default_effect, "Draw")) {
gs_draw_sprite(0, 0, 1, 1); gs_draw_sprite(0, 0, 1, 1);
@ -424,67 +422,65 @@ void filter::sdf_effects::sdf_effects_instance::video_render(gs_effect_t* effect
gs_enable_blending(true); gs_enable_blending(true);
gs_blend_function_separate(GS_BLEND_SRCALPHA, GS_BLEND_INVSRCALPHA, GS_BLEND_ONE, GS_BLEND_ONE); gs_blend_function_separate(GS_BLEND_SRCALPHA, GS_BLEND_INVSRCALPHA, GS_BLEND_ONE, GS_BLEND_ONE);
if (this->_outer_shadow) { if (_outer_shadow) {
_sdf_consumer_effect.get_parameter("pSDFTexture").set_texture(this->_sdf_texture); _sdf_consumer_effect.get_parameter("pSDFTexture").set_texture(_sdf_texture);
_sdf_consumer_effect.get_parameter("pSDFThreshold").set_float(this->_sdf_threshold); _sdf_consumer_effect.get_parameter("pSDFThreshold").set_float(_sdf_threshold);
_sdf_consumer_effect.get_parameter("pImageTexture").set_texture(this->_source_texture->get_object()); _sdf_consumer_effect.get_parameter("pImageTexture").set_texture(_source_texture->get_object());
_sdf_consumer_effect.get_parameter("pShadowColor").set_float4(this->_outer_shadow_color); _sdf_consumer_effect.get_parameter("pShadowColor").set_float4(_outer_shadow_color);
_sdf_consumer_effect.get_parameter("pShadowMin").set_float(this->_outer_shadow_range_min); _sdf_consumer_effect.get_parameter("pShadowMin").set_float(_outer_shadow_range_min);
_sdf_consumer_effect.get_parameter("pShadowMax").set_float(this->_outer_shadow_range_max); _sdf_consumer_effect.get_parameter("pShadowMax").set_float(_outer_shadow_range_max);
_sdf_consumer_effect.get_parameter("pShadowOffset") _sdf_consumer_effect.get_parameter("pShadowOffset")
.set_float2(this->_outer_shadow_offset_x / float_t(baseW), .set_float2(_outer_shadow_offset_x / float_t(baseW), _outer_shadow_offset_y / float_t(baseH));
this->_outer_shadow_offset_y / float_t(baseH));
while (gs_effect_loop(_sdf_consumer_effect.get_object(), "ShadowOuter")) { while (gs_effect_loop(_sdf_consumer_effect.get_object(), "ShadowOuter")) {
gs_draw_sprite(0, 0, 1, 1); gs_draw_sprite(0, 0, 1, 1);
} }
} }
if (this->_inner_shadow) { if (_inner_shadow) {
_sdf_consumer_effect.get_parameter("pSDFTexture").set_texture(this->_sdf_texture); _sdf_consumer_effect.get_parameter("pSDFTexture").set_texture(_sdf_texture);
_sdf_consumer_effect.get_parameter("pSDFThreshold").set_float(this->_sdf_threshold); _sdf_consumer_effect.get_parameter("pSDFThreshold").set_float(_sdf_threshold);
_sdf_consumer_effect.get_parameter("pImageTexture").set_texture(this->_source_texture->get_object()); _sdf_consumer_effect.get_parameter("pImageTexture").set_texture(_source_texture->get_object());
_sdf_consumer_effect.get_parameter("pShadowColor").set_float4(this->_inner_shadow_color); _sdf_consumer_effect.get_parameter("pShadowColor").set_float4(_inner_shadow_color);
_sdf_consumer_effect.get_parameter("pShadowMin").set_float(this->_inner_shadow_range_min); _sdf_consumer_effect.get_parameter("pShadowMin").set_float(_inner_shadow_range_min);
_sdf_consumer_effect.get_parameter("pShadowMax").set_float(this->_inner_shadow_range_max); _sdf_consumer_effect.get_parameter("pShadowMax").set_float(_inner_shadow_range_max);
_sdf_consumer_effect.get_parameter("pShadowOffset") _sdf_consumer_effect.get_parameter("pShadowOffset")
.set_float2(this->_inner_shadow_offset_x / float_t(baseW), .set_float2(_inner_shadow_offset_x / float_t(baseW), _inner_shadow_offset_y / float_t(baseH));
this->_inner_shadow_offset_y / float_t(baseH));
while (gs_effect_loop(_sdf_consumer_effect.get_object(), "ShadowInner")) { while (gs_effect_loop(_sdf_consumer_effect.get_object(), "ShadowInner")) {
gs_draw_sprite(0, 0, 1, 1); gs_draw_sprite(0, 0, 1, 1);
} }
} }
if (this->_outer_glow) { if (_outer_glow) {
_sdf_consumer_effect.get_parameter("pSDFTexture").set_texture(this->_sdf_texture); _sdf_consumer_effect.get_parameter("pSDFTexture").set_texture(_sdf_texture);
_sdf_consumer_effect.get_parameter("pSDFThreshold").set_float(this->_sdf_threshold); _sdf_consumer_effect.get_parameter("pSDFThreshold").set_float(_sdf_threshold);
_sdf_consumer_effect.get_parameter("pImageTexture").set_texture(this->_source_texture->get_object()); _sdf_consumer_effect.get_parameter("pImageTexture").set_texture(_source_texture->get_object());
_sdf_consumer_effect.get_parameter("pGlowColor").set_float4(this->_outer_glow_color); _sdf_consumer_effect.get_parameter("pGlowColor").set_float4(_outer_glow_color);
_sdf_consumer_effect.get_parameter("pGlowWidth").set_float(this->_outer_glow_width); _sdf_consumer_effect.get_parameter("pGlowWidth").set_float(_outer_glow_width);
_sdf_consumer_effect.get_parameter("pGlowSharpness").set_float(this->_outer_glow_sharpness); _sdf_consumer_effect.get_parameter("pGlowSharpness").set_float(_outer_glow_sharpness);
_sdf_consumer_effect.get_parameter("pGlowSharpnessInverse").set_float(this->_outer_glow_sharpness_inv); _sdf_consumer_effect.get_parameter("pGlowSharpnessInverse").set_float(_outer_glow_sharpness_inv);
while (gs_effect_loop(_sdf_consumer_effect.get_object(), "GlowOuter")) { while (gs_effect_loop(_sdf_consumer_effect.get_object(), "GlowOuter")) {
gs_draw_sprite(0, 0, 1, 1); gs_draw_sprite(0, 0, 1, 1);
} }
} }
if (this->_inner_glow) { if (_inner_glow) {
_sdf_consumer_effect.get_parameter("pSDFTexture").set_texture(this->_sdf_texture); _sdf_consumer_effect.get_parameter("pSDFTexture").set_texture(_sdf_texture);
_sdf_consumer_effect.get_parameter("pSDFThreshold").set_float(this->_sdf_threshold); _sdf_consumer_effect.get_parameter("pSDFThreshold").set_float(_sdf_threshold);
_sdf_consumer_effect.get_parameter("pImageTexture").set_texture(this->_source_texture->get_object()); _sdf_consumer_effect.get_parameter("pImageTexture").set_texture(_source_texture->get_object());
_sdf_consumer_effect.get_parameter("pGlowColor").set_float4(this->_inner_glow_color); _sdf_consumer_effect.get_parameter("pGlowColor").set_float4(_inner_glow_color);
_sdf_consumer_effect.get_parameter("pGlowWidth").set_float(this->_inner_glow_width); _sdf_consumer_effect.get_parameter("pGlowWidth").set_float(_inner_glow_width);
_sdf_consumer_effect.get_parameter("pGlowSharpness").set_float(this->_inner_glow_sharpness); _sdf_consumer_effect.get_parameter("pGlowSharpness").set_float(_inner_glow_sharpness);
_sdf_consumer_effect.get_parameter("pGlowSharpnessInverse").set_float(this->_inner_glow_sharpness_inv); _sdf_consumer_effect.get_parameter("pGlowSharpnessInverse").set_float(_inner_glow_sharpness_inv);
while (gs_effect_loop(_sdf_consumer_effect.get_object(), "GlowInner")) { while (gs_effect_loop(_sdf_consumer_effect.get_object(), "GlowInner")) {
gs_draw_sprite(0, 0, 1, 1); gs_draw_sprite(0, 0, 1, 1);
} }
} }
if (this->_outline) { if (_outline) {
_sdf_consumer_effect.get_parameter("pSDFTexture").set_texture(this->_sdf_texture); _sdf_consumer_effect.get_parameter("pSDFTexture").set_texture(_sdf_texture);
_sdf_consumer_effect.get_parameter("pSDFThreshold").set_float(this->_sdf_threshold); _sdf_consumer_effect.get_parameter("pSDFThreshold").set_float(_sdf_threshold);
_sdf_consumer_effect.get_parameter("pImageTexture").set_texture(this->_source_texture->get_object()); _sdf_consumer_effect.get_parameter("pImageTexture").set_texture(_source_texture->get_object());
_sdf_consumer_effect.get_parameter("pOutlineColor").set_float4(this->_outline_color); _sdf_consumer_effect.get_parameter("pOutlineColor").set_float4(_outline_color);
_sdf_consumer_effect.get_parameter("pOutlineWidth").set_float(this->_outline_width); _sdf_consumer_effect.get_parameter("pOutlineWidth").set_float(_outline_width);
_sdf_consumer_effect.get_parameter("pOutlineOffset").set_float(this->_outline_offset); _sdf_consumer_effect.get_parameter("pOutlineOffset").set_float(_outline_offset);
_sdf_consumer_effect.get_parameter("pOutlineSharpness").set_float(this->_outline_sharpness); _sdf_consumer_effect.get_parameter("pOutlineSharpness").set_float(_outline_sharpness);
_sdf_consumer_effect.get_parameter("pOutlineSharpnessInverse").set_float(this->_outline_sharpness_inv); _sdf_consumer_effect.get_parameter("pOutlineSharpnessInverse").set_float(_outline_sharpness_inv);
while (gs_effect_loop(_sdf_consumer_effect.get_object(), "Outline")) { while (gs_effect_loop(_sdf_consumer_effect.get_object(), "Outline")) {
gs_draw_sprite(0, 0, 1, 1); gs_draw_sprite(0, 0, 1, 1);
} }
@ -492,20 +488,20 @@ void filter::sdf_effects::sdf_effects_instance::video_render(gs_effect_t* effect
} catch (...) { } catch (...) {
} }
this->_output_rt->get_texture(this->_output_texture); _output_rt->get_texture(_output_texture);
gs_blend_state_pop(); gs_blend_state_pop();
this->_output_rendered = true; _output_rendered = true;
} }
if (!this->_output_texture) { if (!_output_texture) {
obs_source_skip_video_filter(this->_self); obs_source_skip_video_filter(_self);
return; return;
} }
gs_eparam_t* ep = gs_effect_get_param_by_name(final_effect, "image"); gs_eparam_t* ep = gs_effect_get_param_by_name(final_effect, "image");
if (ep) { if (ep) {
gs_effect_set_texture(ep, this->_output_texture->get_object()); gs_effect_set_texture(ep, _output_texture->get_object());
} }
while (gs_effect_loop(final_effect, "Draw")) { while (gs_effect_loop(final_effect, "Draw")) {
gs_draw_sprite(0, 0, baseW, baseH); gs_draw_sprite(0, 0, baseW, baseH);
@ -518,6 +514,7 @@ filter::sdf_effects::sdf_effects_factory::sdf_effects_factory()
_info.type = OBS_SOURCE_TYPE_FILTER; _info.type = OBS_SOURCE_TYPE_FILTER;
_info.output_flags = OBS_SOURCE_VIDEO; _info.output_flags = OBS_SOURCE_VIDEO;
set_resolution_enabled(false);
finish_setup(); finish_setup();
} }

View File

@ -405,6 +405,7 @@ filter::transform::transform_factory::transform_factory()
_info.type = OBS_SOURCE_TYPE_FILTER; _info.type = OBS_SOURCE_TYPE_FILTER;
_info.output_flags = OBS_SOURCE_VIDEO; _info.output_flags = OBS_SOURCE_VIDEO;
set_resolution_enabled(false);
finish_setup(); finish_setup();
} }

View File

@ -120,6 +120,8 @@ source::mirror::mirror_instance::mirror_instance(obs_data_t* settings, obs_sourc
// Spawn Audio Thread // Spawn Audio Thread
/// ToDo: Use ThreadPool for this? /// ToDo: Use ThreadPool for this?
_audio_thread = std::thread(std::bind(&source::mirror::mirror_instance::audio_output_cb, this)); _audio_thread = std::thread(std::bind(&source::mirror::mirror_instance::audio_output_cb, this));
update(settings);
} }
source::mirror::mirror_instance::~mirror_instance() source::mirror::mirror_instance::~mirror_instance()