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.output_flags = OBS_SOURCE_VIDEO;
set_resolution_enabled(false);
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)
: obs::source_instance(data, self)
{
update(data);
{
char* file = obs_module_file("effects/color-grade.effect");
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();
}
update(data);
}
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.output_flags = OBS_SOURCE_VIDEO;
set_resolution_enabled(false);
finish_setup();
}

View file

@ -38,6 +38,8 @@ filter::displacement::displacement_instance::displacement_instance(obs_data_t* d
}
_effect = gs::effect::create(effect);
update(data);
}
filter::displacement::displacement_instance::~displacement_instance()
@ -127,6 +129,7 @@ filter::displacement::displacement_factory::displacement_factory()
_info.type = OBS_SOURCE_TYPE_FILTER;
_info.output_flags = OBS_SOURCE_VIDEO;
set_resolution_enabled(false);
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),
_have_final_texture(false), _precalc(), _effect()
{
this->_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);
_filter_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");
try {
this->_effect = gs::effect::create(file);
_effect = gs::effect::create(file);
} catch (const std::exception& ex) {
P_LOG_ERROR("Loading channel mask effect failed with error(s):\n%s", ex.what());
}
assert(this->_effect != nullptr);
assert(_effect != nullptr);
bfree(file);
}
this->update(settings);
update(settings);
}
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.
try {
this->_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);
this->_input->events.rename += std::bind(&filter::dynamic_mask::dynamic_mask_instance::input_renamed, this,
_input = std::make_shared<obs::source>(obs_data_get_string(settings, ST_INPUT));
_input_capture = std::make_shared<gfx::source_texture>(_input, _self);
_input->events.rename += std::bind(&filter::dynamic_mask::dynamic_mask_instance::input_renamed, this,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
} catch (...) {
this->_input.reset();
this->_input_capture.reset();
this->_input_texture.reset();
_input.reset();
_input_capture.reset();
_input_texture.reset();
}
// Update data store
for (auto kv1 : channel_translations) {
auto found = this->_channels.find(kv1.first);
if (found == this->_channels.end()) {
this->_channels.insert({kv1.first, channel_data()});
found = this->_channels.find(kv1.first);
if (found == this->_channels.end()) {
assert(found != this->_channels.end());
auto found = _channels.find(kv1.first);
if (found == _channels.end()) {
_channels.insert({kv1.first, channel_data()});
found = _channels.find(kv1.first);
if (found == _channels.end()) {
assert(found != _channels.end());
throw std::runtime_error("Unable to insert element into data _store.");
}
}
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()));
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;
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;
switch (kv1.first) {
case channel::Red:
ch = &this->_precalc.matrix.x;
ch = &_precalc.matrix.x;
break;
case channel::Green:
ch = &this->_precalc.matrix.y;
ch = &_precalc.matrix.y;
break;
case channel::Blue:
ch = &this->_precalc.matrix.z;
ch = &_precalc.matrix.z;
break;
case channel::Alpha:
ch = &this->_precalc.matrix.t;
ch = &_precalc.matrix.t;
break;
default:
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)
{
if (this->_input) {
obs_data_set_string(settings, ST_INPUT, obs_source_get_name(this->_input->get()));
if (_input) {
obs_data_set_string(settings, ST_INPUT, obs_source_get_name(_input->get()));
}
for (auto kv1 : channel_translations) {
auto found = this->_channels.find(kv1.first);
if (found == this->_channels.end()) {
this->_channels.insert({kv1.first, channel_data()});
found = this->_channels.find(kv1.first);
if (found == this->_channels.end()) {
assert(found != this->_channels.end());
auto found = _channels.find(kv1.first);
if (found == _channels.end()) {
_channels.insert({kv1.first, channel_data()});
found = _channels.find(kv1.first);
if (found == _channels.end()) {
assert(found != _channels.end());
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)
{
obs_source_t* parent = obs_filter_get_parent(this->_self);
obs_source_t* target = obs_filter_get_target(this->_self);
obs_source_t* parent = obs_filter_get_parent(_self);
obs_source_t* target = obs_filter_get_target(_self);
uint32_t width = obs_source_get_base_width(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
if (!_have_filter_texture) {
if (obs_source_process_filter_begin(this->_self, GS_RGBA, OBS_ALLOW_DIRECT_RENDERING)) {
auto op = this->_filter_rt->render(width, height);
if (obs_source_process_filter_begin(_self, GS_RGBA, OBS_ALLOW_DIRECT_RENDERING)) {
auto op = _filter_rt->render(width, height);
gs_blend_state_push();
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_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();
} else {
throw std::runtime_error("Failed to render filter.");
}
this->_filter_texture = this->_filter_rt->get_texture();
this->_have_filter_texture = true;
_filter_texture = _filter_rt->get_texture();
_have_filter_texture = true;
}
if (!_have_input_texture) {
this->_input_texture = this->_input_capture->render(_input->width(), _input->height());
this->_have_input_texture = true;
_input_texture = _input_capture->render(_input->width(), _input->height());
_have_input_texture = true;
}
// 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_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_ortho(0, (float)width, 0, (float)height, -1., 1.);
_effect.get_parameter("pMaskInputA").set_texture(this->_filter_texture);
_effect.get_parameter("pMaskInputB").set_texture(this->_input_texture);
_effect.get_parameter("pMaskInputA").set_texture(_filter_texture);
_effect.get_parameter("pMaskInputB").set_texture(_input_texture);
_effect.get_parameter("pMaskBase").set_float4(this->_precalc.base);
_effect.get_parameter("pMaskMatrix").set_matrix(this->_precalc.matrix);
_effect.get_parameter("pMaskMultiplier").set_float4(this->_precalc.scale);
_effect.get_parameter("pMaskBase").set_float4(_precalc.base);
_effect.get_parameter("pMaskMatrix").set_matrix(_precalc.matrix);
_effect.get_parameter("pMaskMultiplier").set_float4(_precalc.scale);
while (gs_effect_loop(_effect.get(), "Mask")) {
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();
}
this->_final_texture = this->_final_rt->get_texture();
this->_have_final_texture = true;
_final_texture = _final_rt->get_texture();
_have_final_texture = true;
}
} catch (...) {
obs_source_skip_video_filter(this->_self);
obs_source_skip_video_filter(_self);
return;
}
if (!_have_filter_texture || !_have_input_texture || !_have_final_texture) {
obs_source_skip_video_filter(this->_self);
obs_source_skip_video_filter(_self);
return;
}
if (!this->_filter_texture->get_object() || !this->_input_texture->get_object()
|| !this->_final_texture->get_object()) {
obs_source_skip_video_filter(this->_self);
if (!_filter_texture->get_object() || !_input_texture->get_object() || !_final_texture->get_object()) {
obs_source_skip_video_filter(_self);
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_eparam_t* param = gs_effect_get_param_by_name(final_effect, "image");
if (!param) {
P_LOG_ERROR("<filter-dynamic-mask:%s> Failed to set image param.", obs_source_get_name(this->_self));
obs_source_skip_video_filter(this->_self);
P_LOG_ERROR("<filter-dynamic-mask:%s> Failed to set image param.", obs_source_get_name(_self));
obs_source_skip_video_filter(_self);
return;
} 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")) {
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.output_flags = OBS_SOURCE_VIDEO;
set_resolution_enabled(false);
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();
vec4 transparent = {0};
this->_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);
this->_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);
_source_rt = std::make_shared<gs::rendertarget>(GS_RGBA, GS_ZS_NONE);
_sdf_write = std::make_shared<gs::rendertarget>(GS_RGBA32F, GS_ZS_NONE);
_sdf_read = std::make_shared<gs::rendertarget>(GS_RGBA32F, 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,
this->_output_rt};
std::shared_ptr<gs::rendertarget> initialize_rts[] = {_source_rt, _sdf_write, _sdf_read, _output_rt};
for (auto rt : initialize_rts) {
auto op = rt->render(1, 1);
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);
}
}
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)
{
{
this->_outer_shadow =
_outer_shadow =
obs_data_get_bool(data, ST_SHADOW_OUTER)
&& (obs_data_get_double(data, ST_SHADOW_OUTER_ALPHA) >= std::numeric_limits<double_t>::epsilon());
{
@ -134,19 +134,19 @@ void filter::sdf_effects::sdf_effects_instance::update(obs_data_t* data)
cs c;
};
color = uint32_t(obs_data_get_int(data, ST_SHADOW_OUTER_COLOR));
this->_outer_shadow_color.x = float_t(c.r / 255.0);
this->_outer_shadow_color.y = float_t(c.g / 255.0);
this->_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.x = float_t(c.r / 255.0);
_outer_shadow_color.y = float_t(c.g / 255.0);
_outer_shadow_color.z = float_t(c.b / 255.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));
this->_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));
this->_outer_shadow_offset_y = float_t(obs_data_get_double(data, ST_SHADOW_OUTER_OFFSET_Y));
_outer_shadow_range_min = float_t(obs_data_get_double(data, ST_SHADOW_OUTER_RANGE_MINIMUM));
_outer_shadow_range_max = float_t(obs_data_get_double(data, ST_SHADOW_OUTER_RANGE_MAXIMUM));
_outer_shadow_offset_x = float_t(obs_data_get_double(data, ST_SHADOW_OUTER_OFFSET_X));
_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_double(data, ST_SHADOW_INNER_ALPHA) >= std::numeric_limits<double_t>::epsilon());
{
@ -159,20 +159,19 @@ void filter::sdf_effects::sdf_effects_instance::update(obs_data_t* data)
cs c;
};
color = uint32_t(obs_data_get_int(data, ST_SHADOW_INNER_COLOR));
this->_inner_shadow_color.x = float_t(c.r / 255.0);
this->_inner_shadow_color.y = float_t(c.g / 255.0);
this->_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.x = float_t(c.r / 255.0);
_inner_shadow_color.y = float_t(c.g / 255.0);
_inner_shadow_color.z = float_t(c.b / 255.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));
this->_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));
this->_inner_shadow_offset_y = float_t(obs_data_get_double(data, ST_SHADOW_INNER_OFFSET_Y));
_inner_shadow_range_min = float_t(obs_data_get_double(data, ST_SHADOW_INNER_RANGE_MINIMUM));
_inner_shadow_range_max = float_t(obs_data_get_double(data, ST_SHADOW_INNER_RANGE_MAXIMUM));
_inner_shadow_offset_x = float_t(obs_data_get_double(data, ST_SHADOW_INNER_OFFSET_X));
_inner_shadow_offset_y = float_t(obs_data_get_double(data, ST_SHADOW_INNER_OFFSET_Y));
}
{
this->_outer_glow =
obs_data_get_bool(data, ST_GLOW_OUTER)
_outer_glow = obs_data_get_bool(data, ST_GLOW_OUTER)
&& (obs_data_get_double(data, ST_GLOW_OUTER_ALPHA) >= std::numeric_limits<double_t>::epsilon());
{
struct cs {
@ -184,22 +183,21 @@ void filter::sdf_effects::sdf_effects_instance::update(obs_data_t* data)
cs c;
};
color = uint32_t(obs_data_get_int(data, ST_GLOW_OUTER_COLOR));
this->_outer_glow_color.x = float_t(c.r / 255.0);
this->_outer_glow_color.y = float_t(c.g / 255.0);
this->_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.x = float_t(c.r / 255.0);
_outer_glow_color.y = float_t(c.g / 255.0);
_outer_glow_color.z = float_t(c.b / 255.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));
this->_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));
if (this->_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_width = float_t(obs_data_get_double(data, ST_GLOW_OUTER_WIDTH));
_outer_glow_sharpness = float_t(obs_data_get_double(data, ST_GLOW_OUTER_SHARPNESS) / 100.0);
_outer_glow_sharpness_inv = float_t(1.0f / (1.0f - _outer_glow_sharpness));
if (_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 =
obs_data_get_bool(data, ST_GLOW_INNER)
_inner_glow = obs_data_get_bool(data, ST_GLOW_INNER)
&& (obs_data_get_double(data, ST_GLOW_INNER_ALPHA) >= std::numeric_limits<double_t>::epsilon());
{
struct cs {
@ -211,21 +209,21 @@ void filter::sdf_effects::sdf_effects_instance::update(obs_data_t* data)
cs c;
};
color = uint32_t(obs_data_get_int(data, ST_GLOW_INNER_COLOR));
this->_inner_glow_color.x = float_t(c.r / 255.0);
this->_inner_glow_color.y = float_t(c.g / 255.0);
this->_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.x = float_t(c.r / 255.0);
_inner_glow_color.y = float_t(c.g / 255.0);
_inner_glow_color.z = float_t(c.b / 255.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));
this->_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));
if (this->_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_width = float_t(obs_data_get_double(data, ST_GLOW_INNER_WIDTH));
_inner_glow_sharpness = float_t(obs_data_get_double(data, ST_GLOW_INNER_SHARPNESS) / 100.0);
_inner_glow_sharpness_inv = float_t(1.0f / (1.0f - _inner_glow_sharpness));
if (_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());
{
struct cs {
@ -237,22 +235,22 @@ void filter::sdf_effects::sdf_effects_instance::update(obs_data_t* data)
cs c;
};
color = uint32_t(obs_data_get_int(data, ST_OUTLINE_COLOR));
this->_outline_color.x = float_t(c.r / 255.0);
this->_outline_color.y = float_t(c.g / 255.0);
this->_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.x = float_t(c.r / 255.0);
_outline_color.y = float_t(c.g / 255.0);
_outline_color.z = float_t(c.b / 255.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));
this->_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);
this->_outline_sharpness_inv = float_t(1.0f / (1.0f - this->_outline_sharpness));
if (this->_outline_sharpness >= (1.0f - std::numeric_limits<float_t>::epsilon())) {
this->_outline_sharpness = 1.0f - std::numeric_limits<float_t>::epsilon();
_outline_width = float_t(obs_data_get_double(data, ST_OUTLINE_WIDTH));
_outline_offset = float_t(obs_data_get_double(data, ST_OUTLINE_OFFSET));
_outline_sharpness = float_t(obs_data_get_double(data, ST_OUTLINE_SHARPNESS) / 100.0);
_outline_sharpness_inv = float_t(1.0f / (1.0f - _outline_sharpness));
if (_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);
this->_sdf_threshold = float_t(obs_data_get_double(data, ST_SDF_THRESHOLD) / 100.0);
_sdf_scale = double_t(obs_data_get_double(data, ST_SDF_SCALE) / 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)
@ -267,7 +265,7 @@ void filter::sdf_effects::sdf_effects_instance::video_tick(float)
// Figure out the actual source size.
do {
obs_source_t* target = obs_filter_get_target(this->_self);
obs_source_t* target = obs_filter_get_target(_self);
if (target == nullptr) {
break;
}
@ -277,21 +275,21 @@ void filter::sdf_effects::sdf_effects_instance::video_tick(float)
height = obs_source_get_height(target);
} while (false);
this->_source_rendered = false;
this->_output_rendered = false;
_source_rendered = false;
_output_rendered = false;
}
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* target = obs_filter_get_target(this->_self);
obs_source_t* parent = obs_filter_get_parent(_self);
obs_source_t* target = obs_filter_get_target(_self);
uint32_t baseW = obs_source_get_base_width(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* default_effect = obs_get_base_effect(obs_base_effect::OBS_EFFECT_DEFAULT);
if (!this->_self || !parent || !target || !baseW || !baseH || !final_effect) {
obs_source_skip_video_filter(this->_self);
if (!_self || !parent || !target || !baseW || !baseH || !final_effect) {
obs_source_skip_video_filter(_self);
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_op(GS_STENCIL_BOTH, GS_ZERO, GS_ZERO, GS_ZERO);
if (!this->_source_rendered) {
if (!_source_rendered) {
// Store input texture.
{
auto op = _source_rt->render(baseW, baseH);
gs_ortho(0, (float)baseW, 0, (float)baseH, -1, 1);
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)) {
obs_source_process_filter_end(this->_self, final_effect, baseW, baseH);
if (obs_source_process_filter_begin(_self, GS_RGBA, OBS_ALLOW_DIRECT_RENDERING)) {
obs_source_process_filter_end(_self, final_effect, baseW, baseH);
} else {
throw std::runtime_error("failed to process source");
}
}
this->_source_rt->get_texture(this->_source_texture);
if (!this->_source_texture) {
_source_rt->get_texture(_source_texture);
if (!_source_texture) {
throw std::runtime_error("failed to draw source");
}
// Generate SDF Buffers
{
this->_sdf_read->get_texture(this->_sdf_texture);
if (!this->_sdf_texture) {
_sdf_read->get_texture(_sdf_texture);
if (!_sdf_texture) {
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_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("_sdf").set_texture(this->_sdf_texture);
_sdf_producer_effect.get_parameter("_threshold").set_float(this->_sdf_threshold);
_sdf_producer_effect.get_parameter("_sdf").set_texture(_sdf_texture);
_sdf_producer_effect.get_parameter("_threshold").set_float(_sdf_threshold);
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);
this->_sdf_read->get_texture(this->_sdf_texture);
if (!this->_sdf_texture) {
std::swap(_sdf_read, _sdf_write);
_sdf_read->get_texture(_sdf_texture);
if (!_sdf_texture) {
throw std::runtime_error("SDF Backbuffer empty");
}
}
this->_source_rendered = true;
_source_rendered = true;
}
gs_blend_state_pop();
} catch (...) {
gs_blend_state_pop();
obs_source_skip_video_filter(this->_self);
obs_source_skip_video_filter(_self);
return;
}
if (!this->_output_rendered) {
this->_output_texture = this->_source_texture;
if (!_output_rendered) {
_output_texture = _source_texture;
if (!_sdf_consumer_effect) {
obs_source_skip_video_filter(this->_self);
obs_source_skip_video_filter(_self);
return;
}
@ -409,14 +407,14 @@ void filter::sdf_effects::sdf_effects_instance::video_render(gs_effect_t* effect
// Optimized Render path.
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_enable_blending(false);
gs_blend_function(GS_BLEND_ONE, GS_BLEND_ZERO);
auto param = gs_effect_get_param_by_name(default_effect, "image");
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")) {
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_blend_function_separate(GS_BLEND_SRCALPHA, GS_BLEND_INVSRCALPHA, GS_BLEND_ONE, GS_BLEND_ONE);
if (this->_outer_shadow) {
_sdf_consumer_effect.get_parameter("pSDFTexture").set_texture(this->_sdf_texture);
_sdf_consumer_effect.get_parameter("pSDFThreshold").set_float(this->_sdf_threshold);
_sdf_consumer_effect.get_parameter("pImageTexture").set_texture(this->_source_texture->get_object());
_sdf_consumer_effect.get_parameter("pShadowColor").set_float4(this->_outer_shadow_color);
_sdf_consumer_effect.get_parameter("pShadowMin").set_float(this->_outer_shadow_range_min);
_sdf_consumer_effect.get_parameter("pShadowMax").set_float(this->_outer_shadow_range_max);
if (_outer_shadow) {
_sdf_consumer_effect.get_parameter("pSDFTexture").set_texture(_sdf_texture);
_sdf_consumer_effect.get_parameter("pSDFThreshold").set_float(_sdf_threshold);
_sdf_consumer_effect.get_parameter("pImageTexture").set_texture(_source_texture->get_object());
_sdf_consumer_effect.get_parameter("pShadowColor").set_float4(_outer_shadow_color);
_sdf_consumer_effect.get_parameter("pShadowMin").set_float(_outer_shadow_range_min);
_sdf_consumer_effect.get_parameter("pShadowMax").set_float(_outer_shadow_range_max);
_sdf_consumer_effect.get_parameter("pShadowOffset")
.set_float2(this->_outer_shadow_offset_x / float_t(baseW),
this->_outer_shadow_offset_y / float_t(baseH));
.set_float2(_outer_shadow_offset_x / float_t(baseW), _outer_shadow_offset_y / float_t(baseH));
while (gs_effect_loop(_sdf_consumer_effect.get_object(), "ShadowOuter")) {
gs_draw_sprite(0, 0, 1, 1);
}
}
if (this->_inner_shadow) {
_sdf_consumer_effect.get_parameter("pSDFTexture").set_texture(this->_sdf_texture);
_sdf_consumer_effect.get_parameter("pSDFThreshold").set_float(this->_sdf_threshold);
_sdf_consumer_effect.get_parameter("pImageTexture").set_texture(this->_source_texture->get_object());
_sdf_consumer_effect.get_parameter("pShadowColor").set_float4(this->_inner_shadow_color);
_sdf_consumer_effect.get_parameter("pShadowMin").set_float(this->_inner_shadow_range_min);
_sdf_consumer_effect.get_parameter("pShadowMax").set_float(this->_inner_shadow_range_max);
if (_inner_shadow) {
_sdf_consumer_effect.get_parameter("pSDFTexture").set_texture(_sdf_texture);
_sdf_consumer_effect.get_parameter("pSDFThreshold").set_float(_sdf_threshold);
_sdf_consumer_effect.get_parameter("pImageTexture").set_texture(_source_texture->get_object());
_sdf_consumer_effect.get_parameter("pShadowColor").set_float4(_inner_shadow_color);
_sdf_consumer_effect.get_parameter("pShadowMin").set_float(_inner_shadow_range_min);
_sdf_consumer_effect.get_parameter("pShadowMax").set_float(_inner_shadow_range_max);
_sdf_consumer_effect.get_parameter("pShadowOffset")
.set_float2(this->_inner_shadow_offset_x / float_t(baseW),
this->_inner_shadow_offset_y / float_t(baseH));
.set_float2(_inner_shadow_offset_x / float_t(baseW), _inner_shadow_offset_y / float_t(baseH));
while (gs_effect_loop(_sdf_consumer_effect.get_object(), "ShadowInner")) {
gs_draw_sprite(0, 0, 1, 1);
}
}
if (this->_outer_glow) {
_sdf_consumer_effect.get_parameter("pSDFTexture").set_texture(this->_sdf_texture);
_sdf_consumer_effect.get_parameter("pSDFThreshold").set_float(this->_sdf_threshold);
_sdf_consumer_effect.get_parameter("pImageTexture").set_texture(this->_source_texture->get_object());
_sdf_consumer_effect.get_parameter("pGlowColor").set_float4(this->_outer_glow_color);
_sdf_consumer_effect.get_parameter("pGlowWidth").set_float(this->_outer_glow_width);
_sdf_consumer_effect.get_parameter("pGlowSharpness").set_float(this->_outer_glow_sharpness);
_sdf_consumer_effect.get_parameter("pGlowSharpnessInverse").set_float(this->_outer_glow_sharpness_inv);
if (_outer_glow) {
_sdf_consumer_effect.get_parameter("pSDFTexture").set_texture(_sdf_texture);
_sdf_consumer_effect.get_parameter("pSDFThreshold").set_float(_sdf_threshold);
_sdf_consumer_effect.get_parameter("pImageTexture").set_texture(_source_texture->get_object());
_sdf_consumer_effect.get_parameter("pGlowColor").set_float4(_outer_glow_color);
_sdf_consumer_effect.get_parameter("pGlowWidth").set_float(_outer_glow_width);
_sdf_consumer_effect.get_parameter("pGlowSharpness").set_float(_outer_glow_sharpness);
_sdf_consumer_effect.get_parameter("pGlowSharpnessInverse").set_float(_outer_glow_sharpness_inv);
while (gs_effect_loop(_sdf_consumer_effect.get_object(), "GlowOuter")) {
gs_draw_sprite(0, 0, 1, 1);
}
}
if (this->_inner_glow) {
_sdf_consumer_effect.get_parameter("pSDFTexture").set_texture(this->_sdf_texture);
_sdf_consumer_effect.get_parameter("pSDFThreshold").set_float(this->_sdf_threshold);
_sdf_consumer_effect.get_parameter("pImageTexture").set_texture(this->_source_texture->get_object());
_sdf_consumer_effect.get_parameter("pGlowColor").set_float4(this->_inner_glow_color);
_sdf_consumer_effect.get_parameter("pGlowWidth").set_float(this->_inner_glow_width);
_sdf_consumer_effect.get_parameter("pGlowSharpness").set_float(this->_inner_glow_sharpness);
_sdf_consumer_effect.get_parameter("pGlowSharpnessInverse").set_float(this->_inner_glow_sharpness_inv);
if (_inner_glow) {
_sdf_consumer_effect.get_parameter("pSDFTexture").set_texture(_sdf_texture);
_sdf_consumer_effect.get_parameter("pSDFThreshold").set_float(_sdf_threshold);
_sdf_consumer_effect.get_parameter("pImageTexture").set_texture(_source_texture->get_object());
_sdf_consumer_effect.get_parameter("pGlowColor").set_float4(_inner_glow_color);
_sdf_consumer_effect.get_parameter("pGlowWidth").set_float(_inner_glow_width);
_sdf_consumer_effect.get_parameter("pGlowSharpness").set_float(_inner_glow_sharpness);
_sdf_consumer_effect.get_parameter("pGlowSharpnessInverse").set_float(_inner_glow_sharpness_inv);
while (gs_effect_loop(_sdf_consumer_effect.get_object(), "GlowInner")) {
gs_draw_sprite(0, 0, 1, 1);
}
}
if (this->_outline) {
_sdf_consumer_effect.get_parameter("pSDFTexture").set_texture(this->_sdf_texture);
_sdf_consumer_effect.get_parameter("pSDFThreshold").set_float(this->_sdf_threshold);
_sdf_consumer_effect.get_parameter("pImageTexture").set_texture(this->_source_texture->get_object());
_sdf_consumer_effect.get_parameter("pOutlineColor").set_float4(this->_outline_color);
_sdf_consumer_effect.get_parameter("pOutlineWidth").set_float(this->_outline_width);
_sdf_consumer_effect.get_parameter("pOutlineOffset").set_float(this->_outline_offset);
_sdf_consumer_effect.get_parameter("pOutlineSharpness").set_float(this->_outline_sharpness);
_sdf_consumer_effect.get_parameter("pOutlineSharpnessInverse").set_float(this->_outline_sharpness_inv);
if (_outline) {
_sdf_consumer_effect.get_parameter("pSDFTexture").set_texture(_sdf_texture);
_sdf_consumer_effect.get_parameter("pSDFThreshold").set_float(_sdf_threshold);
_sdf_consumer_effect.get_parameter("pImageTexture").set_texture(_source_texture->get_object());
_sdf_consumer_effect.get_parameter("pOutlineColor").set_float4(_outline_color);
_sdf_consumer_effect.get_parameter("pOutlineWidth").set_float(_outline_width);
_sdf_consumer_effect.get_parameter("pOutlineOffset").set_float(_outline_offset);
_sdf_consumer_effect.get_parameter("pOutlineSharpness").set_float(_outline_sharpness);
_sdf_consumer_effect.get_parameter("pOutlineSharpnessInverse").set_float(_outline_sharpness_inv);
while (gs_effect_loop(_sdf_consumer_effect.get_object(), "Outline")) {
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 (...) {
}
this->_output_rt->get_texture(this->_output_texture);
_output_rt->get_texture(_output_texture);
gs_blend_state_pop();
this->_output_rendered = true;
_output_rendered = true;
}
if (!this->_output_texture) {
obs_source_skip_video_filter(this->_self);
if (!_output_texture) {
obs_source_skip_video_filter(_self);
return;
}
gs_eparam_t* ep = gs_effect_get_param_by_name(final_effect, "image");
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")) {
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.output_flags = OBS_SOURCE_VIDEO;
set_resolution_enabled(false);
finish_setup();
}

View file

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

View file

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