filter-blur: Refactoring
This commit is contained in:
parent
4eb3197720
commit
a56cbf89a9
|
|
@ -376,42 +376,73 @@ std::shared_ptr<std::vector<float_t>> filter::blur::blur_factory::get_gaussian_k
|
||||||
return gaussian_kernels.at(size);
|
return gaussian_kernels.at(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
filter::blur::blur_instance::blur_instance(obs_data_t* settings, obs_source_t* parent)
|
||||||
|
: m_self(parent), m_source_rendered(false), m_output_rendered(false)
|
||||||
|
{
|
||||||
|
m_self = parent;
|
||||||
|
|
||||||
|
// Create RenderTargets
|
||||||
|
try {
|
||||||
|
this->m_source_rt = std::make_shared<gs::rendertarget>(GS_RGBA, GS_ZS_NONE);
|
||||||
|
this->m_output_rt1 = std::make_shared<gs::rendertarget>(GS_RGBA, GS_ZS_NONE);
|
||||||
|
this->m_output_rt2 = std::make_shared<gs::rendertarget>(GS_RGBA, GS_ZS_NONE);
|
||||||
|
} catch (std::exception ex) {
|
||||||
|
P_LOG_ERROR("<filter-blur:%s> Failed to create rendertargets, error %s.", obs_source_get_name(m_self),
|
||||||
|
ex.what());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get initial Blur effect.
|
||||||
|
m_blur_effect = filter::blur::blur_factory::get()->get_effect(filter::blur::type::Box);
|
||||||
|
|
||||||
|
update(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
filter::blur::blur_instance::~blur_instance()
|
||||||
|
{
|
||||||
|
this->m_mask.source.source_texture.reset();
|
||||||
|
this->m_output_rt1.reset();
|
||||||
|
this->m_output_rt2.reset();
|
||||||
|
this->m_source_rt.reset();
|
||||||
|
this->m_blur_effect.reset();
|
||||||
|
this->m_output_texture.reset();
|
||||||
|
}
|
||||||
|
|
||||||
bool filter::blur::blur_instance::apply_shared_param(gs_texture_t* input, float texelX, float texelY)
|
bool filter::blur::blur_instance::apply_shared_param(gs_texture_t* input, float texelX, float texelY)
|
||||||
{
|
{
|
||||||
bool result = true;
|
bool result = true;
|
||||||
|
|
||||||
result = result && gs_set_param_texture(blur_effect->get_object(), "u_image", input);
|
result = result && gs_set_param_texture(m_blur_effect->get_object(), "u_image", input);
|
||||||
|
|
||||||
vec2 imageSize;
|
vec2 imageSize;
|
||||||
vec2_set(&imageSize, (float)gs_texture_get_width(input), (float)gs_texture_get_height(input));
|
vec2_set(&imageSize, (float)gs_texture_get_width(input), (float)gs_texture_get_height(input));
|
||||||
result = result && gs_set_param_float2(blur_effect->get_object(), "u_imageSize", &imageSize);
|
result = result && gs_set_param_float2(m_blur_effect->get_object(), "u_imageSize", &imageSize);
|
||||||
|
|
||||||
vec2 imageTexelDelta;
|
vec2 imageTexelDelta;
|
||||||
vec2_set(&imageTexelDelta, 1.0f, 1.0f);
|
vec2_set(&imageTexelDelta, 1.0f, 1.0f);
|
||||||
vec2_div(&imageTexelDelta, &imageTexelDelta, &imageSize);
|
vec2_div(&imageTexelDelta, &imageTexelDelta, &imageSize);
|
||||||
result = result && gs_set_param_float2(blur_effect->get_object(), "u_imageTexel", &imageTexelDelta);
|
result = result && gs_set_param_float2(m_blur_effect->get_object(), "u_imageTexel", &imageTexelDelta);
|
||||||
|
|
||||||
vec2 texel;
|
vec2 texel;
|
||||||
vec2_set(&texel, texelX, texelY);
|
vec2_set(&texel, texelX, texelY);
|
||||||
result = result && gs_set_param_float2(blur_effect->get_object(), "u_texelDelta", &texel);
|
result = result && gs_set_param_float2(m_blur_effect->get_object(), "u_texelDelta", &texel);
|
||||||
|
|
||||||
result = result && gs_set_param_int(blur_effect->get_object(), "u_radius", (int)size);
|
result = result && gs_set_param_int(m_blur_effect->get_object(), "u_radius", (int)m_blur_size);
|
||||||
result = result && gs_set_param_int(blur_effect->get_object(), "u_diameter", (int)(1 + (size * 2)));
|
result = result && gs_set_param_int(m_blur_effect->get_object(), "u_diameter", (int)(1 + (m_blur_size * 2)));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool filter::blur::blur_instance::apply_bilateral_param()
|
bool filter::blur::blur_instance::apply_bilateral_param()
|
||||||
{
|
{
|
||||||
if (type != type::Bilateral)
|
if (m_blur_type != type::Bilateral)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (blur_effect->has_parameter("bilateralSmoothing")) {
|
if (m_blur_effect->has_parameter("bilateralSmoothing")) {
|
||||||
blur_effect->get_parameter("bilateralSmoothing").set_float((float)(bilateral_smoothing * (1 + size * 2)));
|
m_blur_effect->get_parameter("bilateralSmoothing").set_float((float)(m_blur_bilateral_smoothing * (1 + m_blur_size * 2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blur_effect->has_parameter("bilateralSharpness")) {
|
if (m_blur_effect->has_parameter("bilateralSharpness")) {
|
||||||
blur_effect->get_parameter("bilateralSharpness").set_float((float)(1.0 - bilateral_sharpness));
|
m_blur_effect->get_parameter("bilateralSharpness").set_float((float)(1.0 - m_blur_bilateral_sharpness));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -421,8 +452,8 @@ bool filter::blur::blur_instance::apply_gaussian_param(uint8_t width)
|
||||||
{
|
{
|
||||||
auto kernel = filter::blur::blur_factory::get()->get_gaussian_kernel(width);
|
auto kernel = filter::blur::blur_factory::get()->get_gaussian_kernel(width);
|
||||||
|
|
||||||
if (blur_effect->has_parameter("kernel")) {
|
if (m_blur_effect->has_parameter("kernel")) {
|
||||||
blur_effect->get_parameter("kernel").set_float_array(&(kernel->front()), kernel->size());
|
m_blur_effect->get_parameter("kernel").set_float_array(&(kernel->front()), kernel->size());
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -439,32 +470,32 @@ bool filter::blur::blur_instance::apply_mask_parameters(std::shared_ptr<gs::effe
|
||||||
}
|
}
|
||||||
|
|
||||||
// Region
|
// Region
|
||||||
if (mask.type == mask_type::Region) {
|
if (m_mask.type == mask_type::Region) {
|
||||||
if (effect->has_parameter("mask_region_left")) {
|
if (effect->has_parameter("mask_region_left")) {
|
||||||
effect->get_parameter("mask_region_left").set_float(mask.region.left);
|
effect->get_parameter("mask_region_left").set_float(m_mask.region.left);
|
||||||
}
|
}
|
||||||
if (effect->has_parameter("mask_region_right")) {
|
if (effect->has_parameter("mask_region_right")) {
|
||||||
effect->get_parameter("mask_region_right").set_float(mask.region.right);
|
effect->get_parameter("mask_region_right").set_float(m_mask.region.right);
|
||||||
}
|
}
|
||||||
if (effect->has_parameter("mask_region_top")) {
|
if (effect->has_parameter("mask_region_top")) {
|
||||||
effect->get_parameter("mask_region_top").set_float(mask.region.top);
|
effect->get_parameter("mask_region_top").set_float(m_mask.region.top);
|
||||||
}
|
}
|
||||||
if (effect->has_parameter("mask_region_bottom")) {
|
if (effect->has_parameter("mask_region_bottom")) {
|
||||||
effect->get_parameter("mask_region_bottom").set_float(mask.region.bottom);
|
effect->get_parameter("mask_region_bottom").set_float(m_mask.region.bottom);
|
||||||
}
|
}
|
||||||
if (effect->has_parameter("mask_region_feather")) {
|
if (effect->has_parameter("mask_region_feather")) {
|
||||||
effect->get_parameter("mask_region_feather").set_float(mask.region.feather);
|
effect->get_parameter("mask_region_feather").set_float(m_mask.region.feather);
|
||||||
}
|
}
|
||||||
if (effect->has_parameter("mask_region_feather_shift")) {
|
if (effect->has_parameter("mask_region_feather_shift")) {
|
||||||
effect->get_parameter("mask_region_feather_shift").set_float(mask.region.feather_shift);
|
effect->get_parameter("mask_region_feather_shift").set_float(m_mask.region.feather_shift);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Image
|
// Image
|
||||||
if (mask.type == mask_type::Image) {
|
if (m_mask.type == mask_type::Image) {
|
||||||
if (effect->has_parameter("mask_image")) {
|
if (effect->has_parameter("mask_image")) {
|
||||||
if (mask.image.texture) {
|
if (m_mask.image.texture) {
|
||||||
effect->get_parameter("mask_image").set_texture(mask.image.texture);
|
effect->get_parameter("mask_image").set_texture(m_mask.image.texture);
|
||||||
} else {
|
} else {
|
||||||
effect->get_parameter("mask_image").set_texture(nullptr);
|
effect->get_parameter("mask_image").set_texture(nullptr);
|
||||||
}
|
}
|
||||||
|
|
@ -472,10 +503,10 @@ bool filter::blur::blur_instance::apply_mask_parameters(std::shared_ptr<gs::effe
|
||||||
}
|
}
|
||||||
|
|
||||||
// Source
|
// Source
|
||||||
if (mask.type == mask_type::Source) {
|
if (m_mask.type == mask_type::Source) {
|
||||||
if (effect->has_parameter("mask_image")) {
|
if (effect->has_parameter("mask_image")) {
|
||||||
if (mask.source.texture) {
|
if (m_mask.source.texture) {
|
||||||
effect->get_parameter("mask_image").set_texture(mask.source.texture);
|
effect->get_parameter("mask_image").set_texture(m_mask.source.texture);
|
||||||
} else {
|
} else {
|
||||||
effect->get_parameter("mask_image").set_texture(nullptr);
|
effect->get_parameter("mask_image").set_texture(nullptr);
|
||||||
}
|
}
|
||||||
|
|
@ -484,10 +515,10 @@ bool filter::blur::blur_instance::apply_mask_parameters(std::shared_ptr<gs::effe
|
||||||
|
|
||||||
// Shared
|
// Shared
|
||||||
if (effect->has_parameter("mask_color")) {
|
if (effect->has_parameter("mask_color")) {
|
||||||
effect->get_parameter("mask_color").set_float4(mask.color.r, mask.color.g, mask.color.b, mask.color.a);
|
effect->get_parameter("mask_color").set_float4(m_mask.color.r, m_mask.color.g, m_mask.color.b, m_mask.color.a);
|
||||||
}
|
}
|
||||||
if (effect->has_parameter("mask_multiplier")) {
|
if (effect->has_parameter("mask_multiplier")) {
|
||||||
effect->get_parameter("mask_multiplier").set_float(mask.multiplier);
|
effect->get_parameter("mask_multiplier").set_float(m_mask.multiplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -537,44 +568,6 @@ bool filter::blur::blur_instance::modified_properties(void*, obs_properties_t* p
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool filter::blur::blur_instance::can_log()
|
|
||||||
{
|
|
||||||
// Only allow logging errors every 200ms.
|
|
||||||
auto now = std::chrono::high_resolution_clock::now();
|
|
||||||
auto delta = (now - this->last_log);
|
|
||||||
std::swap(this->last_log, now);
|
|
||||||
return std::chrono::duration_cast<std::chrono::milliseconds>(delta) > std::chrono::milliseconds(200);
|
|
||||||
}
|
|
||||||
|
|
||||||
filter::blur::blur_instance::blur_instance(obs_data_t* settings, obs_source_t* parent)
|
|
||||||
: m_self(parent), m_source_rendered(false)
|
|
||||||
{
|
|
||||||
m_self = parent;
|
|
||||||
|
|
||||||
// Create RenderTargets
|
|
||||||
try {
|
|
||||||
this->rt_source = std::make_shared<gs::rendertarget>(GS_RGBA, GS_ZS_NONE);
|
|
||||||
this->rt_primary = std::make_shared<gs::rendertarget>(GS_RGBA, GS_ZS_NONE);
|
|
||||||
this->rt_secondary = std::make_shared<gs::rendertarget>(GS_RGBA, GS_ZS_NONE);
|
|
||||||
} catch (std::exception ex) {
|
|
||||||
P_LOG_ERROR("<filter-blur:%s> Failed to create rendertargets, error %s.", obs_source_get_name(m_self),
|
|
||||||
ex.what());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get initial Blur effect.
|
|
||||||
blur_effect = filter::blur::blur_factory::get()->get_effect(filter::blur::type::Box);
|
|
||||||
}
|
|
||||||
|
|
||||||
filter::blur::blur_instance::~blur_instance()
|
|
||||||
{
|
|
||||||
this->mask.source.source_texture.reset();
|
|
||||||
this->rt_primary.reset();
|
|
||||||
this->rt_secondary.reset();
|
|
||||||
this->rt_source.reset();
|
|
||||||
this->blur_effect.reset();
|
|
||||||
this->m_source_texture.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
obs_properties_t* filter::blur::blur_instance::get_properties()
|
obs_properties_t* filter::blur::blur_instance::get_properties()
|
||||||
{
|
{
|
||||||
obs_properties_t* pr = obs_properties_create();
|
obs_properties_t* pr = obs_properties_create();
|
||||||
|
|
@ -685,60 +678,60 @@ obs_properties_t* filter::blur::blur_instance::get_properties()
|
||||||
|
|
||||||
void filter::blur::blur_instance::update(obs_data_t* settings)
|
void filter::blur::blur_instance::update(obs_data_t* settings)
|
||||||
{
|
{
|
||||||
type = (blur::type)obs_data_get_int(settings, P_TYPE);
|
m_blur_type = (blur::type)obs_data_get_int(settings, P_TYPE);
|
||||||
blur_effect = blur_factory::get()->get_effect(type);
|
m_blur_effect = blur_factory::get()->get_effect(m_blur_type);
|
||||||
blur_technique = blur_factory::get()->get_technique(type);
|
m_blur_technique = blur_factory::get()->get_technique(m_blur_type);
|
||||||
size = (uint64_t)obs_data_get_int(settings, P_SIZE);
|
m_blur_size = (uint64_t)obs_data_get_int(settings, P_SIZE);
|
||||||
|
|
||||||
// bilateral blur
|
// bilateral blur
|
||||||
bilateral_smoothing = obs_data_get_double(settings, P_BILATERAL_SMOOTHING) / 100.0;
|
m_blur_bilateral_smoothing = obs_data_get_double(settings, P_BILATERAL_SMOOTHING) / 100.0;
|
||||||
bilateral_sharpness = obs_data_get_double(settings, P_BILATERAL_SHARPNESS) / 100.0;
|
m_blur_bilateral_sharpness = obs_data_get_double(settings, P_BILATERAL_SHARPNESS) / 100.0;
|
||||||
|
|
||||||
// region
|
// region
|
||||||
mask.enabled = obs_data_get_bool(settings, P_MASK);
|
m_mask.enabled = obs_data_get_bool(settings, P_MASK);
|
||||||
if (mask.enabled) {
|
if (m_mask.enabled) {
|
||||||
mask.type = static_cast<mask_type>(obs_data_get_int(settings, P_MASK_TYPE));
|
m_mask.type = static_cast<mask_type>(obs_data_get_int(settings, P_MASK_TYPE));
|
||||||
switch (mask.type) {
|
switch (m_mask.type) {
|
||||||
case mask_type::Region:
|
case mask_type::Region:
|
||||||
mask.region.left = float_t(obs_data_get_double(settings, P_MASK_REGION_LEFT) / 100.0);
|
m_mask.region.left = float_t(obs_data_get_double(settings, P_MASK_REGION_LEFT) / 100.0);
|
||||||
mask.region.top = float_t(obs_data_get_double(settings, P_MASK_REGION_TOP) / 100.0);
|
m_mask.region.top = float_t(obs_data_get_double(settings, P_MASK_REGION_TOP) / 100.0);
|
||||||
mask.region.right = 1.0f - float_t(obs_data_get_double(settings, P_MASK_REGION_RIGHT) / 100.0);
|
m_mask.region.right = 1.0f - float_t(obs_data_get_double(settings, P_MASK_REGION_RIGHT) / 100.0);
|
||||||
mask.region.bottom = 1.0f - float_t(obs_data_get_double(settings, P_MASK_REGION_BOTTOM) / 100.0);
|
m_mask.region.bottom = 1.0f - float_t(obs_data_get_double(settings, P_MASK_REGION_BOTTOM) / 100.0);
|
||||||
mask.region.feather = float_t(obs_data_get_double(settings, P_MASK_REGION_FEATHER) / 100.0);
|
m_mask.region.feather = float_t(obs_data_get_double(settings, P_MASK_REGION_FEATHER) / 100.0);
|
||||||
mask.region.feather_shift = float_t(obs_data_get_double(settings, P_MASK_REGION_FEATHER_SHIFT) / 100.0);
|
m_mask.region.feather_shift = float_t(obs_data_get_double(settings, P_MASK_REGION_FEATHER_SHIFT) / 100.0);
|
||||||
mask.region.invert = obs_data_get_bool(settings, P_MASK_REGION_INVERT);
|
m_mask.region.invert = obs_data_get_bool(settings, P_MASK_REGION_INVERT);
|
||||||
break;
|
break;
|
||||||
case mask_type::Image:
|
case mask_type::Image:
|
||||||
mask.image.path = obs_data_get_string(settings, P_MASK_IMAGE);
|
m_mask.image.path = obs_data_get_string(settings, P_MASK_IMAGE);
|
||||||
break;
|
break;
|
||||||
case mask_type::Source:
|
case mask_type::Source:
|
||||||
mask.source.name = obs_data_get_string(settings, P_MASK_SOURCE);
|
m_mask.source.name = obs_data_get_string(settings, P_MASK_SOURCE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ((mask.type == mask_type::Image) || (mask.type == mask_type::Source)) {
|
if ((m_mask.type == mask_type::Image) || (m_mask.type == mask_type::Source)) {
|
||||||
uint32_t color = static_cast<uint32_t>(obs_data_get_int(settings, P_MASK_COLOR));
|
uint32_t color = static_cast<uint32_t>(obs_data_get_int(settings, P_MASK_COLOR));
|
||||||
mask.color.r = ((color >> 0) & 0xFF) / 255.0f;
|
m_mask.color.r = ((color >> 0) & 0xFF) / 255.0f;
|
||||||
mask.color.g = ((color >> 8) & 0xFF) / 255.0f;
|
m_mask.color.g = ((color >> 8) & 0xFF) / 255.0f;
|
||||||
mask.color.b = ((color >> 16) & 0xFF) / 255.0f;
|
m_mask.color.b = ((color >> 16) & 0xFF) / 255.0f;
|
||||||
mask.color.a = static_cast<float_t>(obs_data_get_double(settings, P_MASK_ALPHA));
|
m_mask.color.a = static_cast<float_t>(obs_data_get_double(settings, P_MASK_ALPHA));
|
||||||
mask.multiplier = float_t(obs_data_get_double(settings, P_MASK_MULTIPLIER));
|
m_mask.multiplier = float_t(obs_data_get_double(settings, P_MASK_MULTIPLIER));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Directional Blur
|
// Directional Blur
|
||||||
this->directional = obs_data_get_bool(settings, P_DIRECTIONAL);
|
this->m_blur_directional = obs_data_get_bool(settings, P_DIRECTIONAL);
|
||||||
this->angle = obs_data_get_double(settings, P_DIRECTIONAL_ANGLE);
|
this->m_blur_angle = obs_data_get_double(settings, P_DIRECTIONAL_ANGLE);
|
||||||
|
|
||||||
// Scaling
|
// Scaling
|
||||||
this->scaling = obs_data_get_bool(settings, P_STEPSCALE);
|
this->m_blur_step_scaling = obs_data_get_bool(settings, P_STEPSCALE);
|
||||||
this->scale.first = obs_data_get_double(settings, P_STEPSCALE_X) / 100.0;
|
this->m_blur_step_scale.first = obs_data_get_double(settings, P_STEPSCALE_X) / 100.0;
|
||||||
this->scale.second = obs_data_get_double(settings, P_STEPSCALE_Y) / 100.0;
|
this->m_blur_step_scale.second = obs_data_get_double(settings, P_STEPSCALE_Y) / 100.0;
|
||||||
|
|
||||||
// advanced
|
// advanced
|
||||||
if (obs_data_get_bool(settings, S_ADVANCED)) {
|
if (obs_data_get_bool(settings, S_ADVANCED)) {
|
||||||
color_format = obs_data_get_int(settings, P_COLORFORMAT);
|
m_color_format = obs_data_get_int(settings, P_COLORFORMAT);
|
||||||
} else {
|
} else {
|
||||||
color_format = obs_data_get_default_int(settings, P_COLORFORMAT);
|
m_color_format = obs_data_get_default_int(settings, P_COLORFORMAT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -764,30 +757,31 @@ void filter::blur::blur_instance::deactivate() {}
|
||||||
void filter::blur::blur_instance::video_tick(float)
|
void filter::blur::blur_instance::video_tick(float)
|
||||||
{
|
{
|
||||||
// Load Mask
|
// Load Mask
|
||||||
if (mask.type == mask_type::Image) {
|
if (m_mask.type == mask_type::Image) {
|
||||||
if (mask.image.path_old != mask.image.path) {
|
if (m_mask.image.path_old != m_mask.image.path) {
|
||||||
try {
|
try {
|
||||||
mask.image.texture = std::make_shared<gs::texture>(mask.image.path);
|
m_mask.image.texture = std::make_shared<gs::texture>(m_mask.image.path);
|
||||||
mask.image.path_old = mask.image.path;
|
m_mask.image.path_old = m_mask.image.path;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("<filter-blur> Instance '%s' failed to load image '%s'.", obs_source_get_name(m_self),
|
P_LOG_ERROR("<filter-blur> Instance '%s' failed to load image '%s'.", obs_source_get_name(m_self),
|
||||||
mask.image.path.c_str());
|
m_mask.image.path.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (mask.type == mask_type::Source) {
|
} else if (m_mask.type == mask_type::Source) {
|
||||||
if (mask.source.name_old != mask.source.name) {
|
if (m_mask.source.name_old != m_mask.source.name) {
|
||||||
try {
|
try {
|
||||||
mask.source.source_texture = std::make_shared<gfx::source_texture>(mask.source.name, m_self);
|
m_mask.source.source_texture = std::make_shared<gfx::source_texture>(m_mask.source.name, m_self);
|
||||||
mask.source.is_scene = (obs_scene_from_source(mask.source.source_texture->get_object()) != nullptr);
|
m_mask.source.is_scene = (obs_scene_from_source(m_mask.source.source_texture->get_object()) != nullptr);
|
||||||
mask.source.name_old = mask.source.name;
|
m_mask.source.name_old = m_mask.source.name;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
P_LOG_ERROR("<filter-blur> Instance '%s' failed to grab source '%s'.", obs_source_get_name(m_self),
|
P_LOG_ERROR("<filter-blur> Instance '%s' failed to grab source '%s'.", obs_source_get_name(m_self),
|
||||||
mask.source.name.c_str());
|
m_mask.source.name.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_source_rendered = false;
|
m_source_rendered = false;
|
||||||
|
m_output_rendered = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::blur::blur_instance::video_render(gs_effect_t* effect)
|
void filter::blur::blur_instance::video_render(gs_effect_t* effect)
|
||||||
|
|
@ -797,43 +791,28 @@ void filter::blur::blur_instance::video_render(gs_effect_t* effect)
|
||||||
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);
|
||||||
vec4 black;
|
vec4 black;
|
||||||
vec4_set(&black, 0, 0, 0, 0);
|
bool failed = false;
|
||||||
|
|
||||||
bool failed = false;
|
|
||||||
|
|
||||||
std::shared_ptr<gs::effect> colorConversionEffect = blur_factory::get()->get_color_converter_effect();
|
std::shared_ptr<gs::effect> colorConversionEffect = blur_factory::get()->get_color_converter_effect();
|
||||||
|
gs_effect_t* defaultEffect = obs_get_base_effect(obs_base_effect::OBS_EFFECT_DEFAULT);
|
||||||
|
|
||||||
|
vec4_set(&black, 0, 0, 0, 0);
|
||||||
|
|
||||||
// Verify that we can actually run first.
|
// Verify that we can actually run first.
|
||||||
if (!target || !parent || !this->m_self) {
|
if (!target || !parent || !this->m_self) {
|
||||||
if (this->can_log()) {
|
|
||||||
P_LOG_ERROR("<filter-blur:%s> Invalid context, memory corruption may have happened.",
|
|
||||||
obs_source_get_name(this->m_self));
|
|
||||||
}
|
|
||||||
obs_source_skip_video_filter(this->m_self);
|
obs_source_skip_video_filter(this->m_self);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((baseW == 0) || (baseH == 0)) {
|
if ((baseW == 0) || (baseH == 0)) {
|
||||||
if (this->can_log()) {
|
|
||||||
P_LOG_ERROR("<filter-blur:%s> Invalid base size from '%s': %" PRIu32 "x%" PRIu32 ".",
|
|
||||||
obs_source_get_name(this->m_self), obs_source_get_name(target), baseW, baseH);
|
|
||||||
}
|
|
||||||
obs_source_skip_video_filter(this->m_self);
|
obs_source_skip_video_filter(this->m_self);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!this->rt_primary || !this->rt_secondary || !this->blur_effect) {
|
if (!this->m_output_rt1 || !this->m_output_rt2 || !this->m_blur_effect) {
|
||||||
if (this->can_log()) {
|
|
||||||
P_LOG_ERROR("<filter-blur:%s> Missing RenderTarget or Effect.", obs_source_get_name(this->m_self));
|
|
||||||
}
|
|
||||||
obs_source_skip_video_filter(this->m_self);
|
obs_source_skip_video_filter(this->m_self);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gs_effect_t* defaultEffect = obs_get_base_effect(obs_base_effect::OBS_EFFECT_DEFAULT);
|
|
||||||
|
|
||||||
if (!m_source_rendered) {
|
if (!m_source_rendered) {
|
||||||
std::shared_ptr<gs::texture> tex_source;
|
|
||||||
std::shared_ptr<gs::texture> tex_intermediate;
|
|
||||||
|
|
||||||
// Source To Texture
|
// Source To Texture
|
||||||
{
|
{
|
||||||
gs_blend_state_push();
|
gs_blend_state_push();
|
||||||
|
|
@ -850,7 +829,7 @@ void filter::blur::blur_instance::video_render(gs_effect_t* effect)
|
||||||
gs_stencil_op(GS_STENCIL_BOTH, GS_ZERO, GS_ZERO, GS_ZERO);
|
gs_stencil_op(GS_STENCIL_BOTH, GS_ZERO, GS_ZERO, GS_ZERO);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto op = this->rt_source->render(baseW, baseH);
|
auto op = this->m_source_rt->render(baseW, baseH);
|
||||||
|
|
||||||
// Orthographic Camera and clear RenderTarget.
|
// Orthographic Camera and clear RenderTarget.
|
||||||
gs_ortho(0, (float)baseW, 0, (float)baseH, -1., 1.);
|
gs_ortho(0, (float)baseW, 0, (float)baseH, -1., 1.);
|
||||||
|
|
@ -863,27 +842,26 @@ void filter::blur::blur_instance::video_render(gs_effect_t* effect)
|
||||||
throw std::runtime_error("Failed to render source");
|
throw std::runtime_error("Failed to render source");
|
||||||
}
|
}
|
||||||
} catch (std::exception ex) {
|
} catch (std::exception ex) {
|
||||||
if (this->can_log()) {
|
|
||||||
P_LOG_ERROR("<filter-blur:%s> Rendering parent source to texture failed with error: %s.",
|
|
||||||
obs_source_get_name(this->m_self), ex.what());
|
|
||||||
}
|
|
||||||
gs_blend_state_pop();
|
gs_blend_state_pop();
|
||||||
obs_source_skip_video_filter(this->m_self);
|
obs_source_skip_video_filter(this->m_self);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
gs_blend_state_pop();
|
gs_blend_state_pop();
|
||||||
|
|
||||||
if (!(tex_source = this->rt_source->get_texture())) {
|
if (!(m_source_texture = this->m_source_rt->get_texture())) {
|
||||||
if (this->can_log()) {
|
|
||||||
P_LOG_ERROR("<filter-blur> Failed to get source texture.");
|
|
||||||
}
|
|
||||||
obs_source_skip_video_filter(m_self);
|
obs_source_skip_video_filter(m_self);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_source_rendered = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_output_rendered) {
|
||||||
|
m_output_texture = m_source_texture;
|
||||||
|
|
||||||
// Color Conversion RGB-YUV
|
// Color Conversion RGB-YUV
|
||||||
if ((color_format == ColorFormat::YUV) && colorConversionEffect) {
|
if ((m_color_format != ColorFormat::RGB) && colorConversionEffect) {
|
||||||
gs_blend_state_push();
|
gs_blend_state_push();
|
||||||
gs_reset_blend_state();
|
gs_reset_blend_state();
|
||||||
gs_enable_color(true, true, true, true);
|
gs_enable_color(true, true, true, true);
|
||||||
|
|
@ -898,37 +876,29 @@ void filter::blur::blur_instance::video_render(gs_effect_t* effect)
|
||||||
gs_stencil_op(GS_STENCIL_BOTH, GS_ZERO, GS_ZERO, GS_ZERO);
|
gs_stencil_op(GS_STENCIL_BOTH, GS_ZERO, GS_ZERO, GS_ZERO);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto op = this->rt_primary->render(baseW, baseH);
|
auto op = this->m_output_rt1->render(baseW, baseH);
|
||||||
gs_ortho(0, (float)baseW, 0, (float)baseH, -1, 1);
|
gs_ortho(0, (float)baseW, 0, (float)baseH, -1, 1);
|
||||||
|
|
||||||
if (colorConversionEffect->has_parameter("image")) {
|
if (colorConversionEffect->has_parameter("image")) {
|
||||||
colorConversionEffect->get_parameter("image").set_texture(tex_source->get_object());
|
colorConversionEffect->get_parameter("image").set_texture(m_source_texture->get_object());
|
||||||
}
|
}
|
||||||
while (gs_effect_loop(colorConversionEffect->get_object(), "RGBToYUV")) {
|
while (gs_effect_loop(colorConversionEffect->get_object(), "RGBToYUV")) {
|
||||||
gs_draw_sprite(tex_source->get_object(), 0, baseW, baseH);
|
gs_draw_sprite(m_source_texture->get_object(), 0, baseW, baseH);
|
||||||
}
|
}
|
||||||
} catch (std::exception ex) {
|
} catch (std::exception ex) {
|
||||||
if (this->can_log()) {
|
|
||||||
P_LOG_ERROR("<filter-blur:%s> RGB-YUV conversion failed with error: %s.",
|
|
||||||
obs_source_get_name(this->m_self), ex.what());
|
|
||||||
}
|
|
||||||
gs_blend_state_pop();
|
gs_blend_state_pop();
|
||||||
obs_source_skip_video_filter(m_self);
|
obs_source_skip_video_filter(m_self);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
gs_blend_state_pop();
|
gs_blend_state_pop();
|
||||||
|
|
||||||
if (!(tex_source = this->rt_primary->get_texture())) {
|
if (!(m_output_texture = this->m_output_rt1->get_texture())) {
|
||||||
if (this->can_log()) {
|
|
||||||
P_LOG_ERROR("<filter-blur:%s> Failed to get color conversion texture.",
|
|
||||||
obs_source_get_name(this->m_self));
|
|
||||||
}
|
|
||||||
obs_source_skip_video_filter(m_self);
|
obs_source_skip_video_filter(m_self);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Swap RTs for further rendering.
|
// Swap RTs for further rendering.
|
||||||
std::swap(this->rt_primary, this->rt_secondary);
|
std::swap(this->m_output_rt1, this->m_output_rt2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Blur
|
// Blur
|
||||||
|
|
@ -946,11 +916,10 @@ void filter::blur::blur_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);
|
||||||
|
|
||||||
std::pair<float, float> kvs[] = {{1.0f / baseW, 0.0f}, {0.0f, 1.0f / baseH}};
|
std::pair<float, float> kvs[] = {{1.0f / baseW, 0.0f}, {0.0f, 1.0f / baseH}};
|
||||||
tex_intermediate = tex_source; // We need the original to work.
|
|
||||||
|
|
||||||
// Directional Blur
|
// Directional Blur
|
||||||
if (this->directional) {
|
if (this->m_blur_directional) {
|
||||||
// Directional Blur changes how
|
// Directional Blur changes how
|
||||||
|
|
||||||
kvs[0].first = (1.0f / baseW);
|
kvs[0].first = (1.0f / baseW);
|
||||||
|
|
@ -958,14 +927,14 @@ void filter::blur::blur_instance::video_render(gs_effect_t* effect)
|
||||||
kvs[1].first = kvs[0].first;
|
kvs[1].first = kvs[0].first;
|
||||||
kvs[1].second = kvs[0].second;
|
kvs[1].second = kvs[0].second;
|
||||||
|
|
||||||
double_t rad = this->angle * PI / 180.0;
|
double_t rad = this->m_blur_angle * PI / 180.0;
|
||||||
double_t c0 = cos(rad);
|
double_t c0 = cos(rad);
|
||||||
double_t s0 = sin(rad);
|
double_t s0 = sin(rad);
|
||||||
|
|
||||||
kvs[0].first *= c0;
|
kvs[0].first *= c0;
|
||||||
kvs[0].second *= s0;
|
kvs[0].second *= s0;
|
||||||
|
|
||||||
if (!this->scaling) {
|
if (!this->m_blur_step_scaling) {
|
||||||
kvs[1].first *= 0.0;
|
kvs[1].first *= 0.0;
|
||||||
kvs[1].second *= 0.0;
|
kvs[1].second *= 0.0;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -975,18 +944,18 @@ void filter::blur::blur_instance::video_render(gs_effect_t* effect)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply scaling
|
// Apply scaling
|
||||||
if (this->scaling) {
|
if (this->m_blur_step_scaling) {
|
||||||
if (!this->directional) {
|
if (!this->m_blur_directional) {
|
||||||
kvs[0].first *= float_t(this->scale.first);
|
kvs[0].first *= float_t(this->m_blur_step_scale.first);
|
||||||
kvs[0].second *= float_t(this->scale.second);
|
kvs[0].second *= float_t(this->m_blur_step_scale.second);
|
||||||
kvs[1].first *= float_t(this->scale.first);
|
kvs[1].first *= float_t(this->m_blur_step_scale.first);
|
||||||
kvs[1].second *= float_t(this->scale.second);
|
kvs[1].second *= float_t(this->m_blur_step_scale.second);
|
||||||
} else {
|
} else {
|
||||||
// Directional Blur changes how scaling works as it rotates and needs to be relative to the axis of rotation.
|
// Directional Blur changes how scaling works as it rotates and needs to be relative to the axis of rotation.
|
||||||
kvs[0].first *= float_t(this->scale.first);
|
kvs[0].first *= float_t(this->m_blur_step_scale.first);
|
||||||
kvs[0].second *= float_t(this->scale.first);
|
kvs[0].second *= float_t(this->m_blur_step_scale.first);
|
||||||
kvs[1].first *= float_t(this->scale.second);
|
kvs[1].first *= float_t(this->m_blur_step_scale.second);
|
||||||
kvs[1].second *= float_t(this->scale.second);
|
kvs[1].second *= float_t(this->m_blur_step_scale.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1000,31 +969,27 @@ void filter::blur::blur_instance::video_render(gs_effect_t* effect)
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto op = this->rt_primary->render(baseW, baseH);
|
auto op = this->m_output_rt1->render(baseW, baseH);
|
||||||
gs_ortho(0, (float)baseW, 0, (float)baseH, -1, 1);
|
gs_ortho(0, (float)baseW, 0, (float)baseH, -1, 1);
|
||||||
|
|
||||||
apply_shared_param(tex_intermediate->get_object(), xpel, ypel);
|
apply_shared_param(m_output_texture->get_object(), xpel, ypel);
|
||||||
apply_gaussian_param(uint8_t(this->size));
|
apply_gaussian_param(uint8_t(this->m_blur_size));
|
||||||
apply_bilateral_param();
|
apply_bilateral_param();
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
while (gs_effect_loop(this->blur_effect->get_object(), this->blur_technique.c_str())) {
|
while (gs_effect_loop(this->m_blur_effect->get_object(), this->m_blur_technique.c_str())) {
|
||||||
gs_draw_sprite(tex_intermediate->get_object(), 0, baseW, baseH);
|
gs_draw_sprite(m_output_texture->get_object(), 0, baseW, baseH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(tex_intermediate = this->rt_primary->get_texture())) {
|
if (!(m_output_texture = this->m_output_rt1->get_texture())) {
|
||||||
throw("Failed to get blur texture.");
|
throw("Failed to get blur texture.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Swap RTs for further rendering.
|
// Swap RTs for further rendering.
|
||||||
std::swap(this->rt_primary, this->rt_secondary);
|
std::swap(this->m_output_rt1, this->m_output_rt2);
|
||||||
}
|
}
|
||||||
} catch (std::exception ex) {
|
} catch (std::exception ex) {
|
||||||
if (this->can_log()) {
|
|
||||||
P_LOG_ERROR("<filter-blur:%s> Blur failed with error: %s.", obs_source_get_name(this->m_self),
|
|
||||||
ex.what());
|
|
||||||
}
|
|
||||||
gs_blend_state_pop();
|
gs_blend_state_pop();
|
||||||
obs_source_skip_video_filter(this->m_self);
|
obs_source_skip_video_filter(this->m_self);
|
||||||
return;
|
return;
|
||||||
|
|
@ -1033,7 +998,7 @@ void filter::blur::blur_instance::video_render(gs_effect_t* effect)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mask
|
// Mask
|
||||||
if (mask.enabled) {
|
if (m_mask.enabled) {
|
||||||
gs_blend_state_push();
|
gs_blend_state_push();
|
||||||
gs_reset_blend_state();
|
gs_reset_blend_state();
|
||||||
gs_enable_color(true, true, true, true);
|
gs_enable_color(true, true, true, true);
|
||||||
|
|
@ -1048,16 +1013,16 @@ void filter::blur::blur_instance::video_render(gs_effect_t* effect)
|
||||||
gs_stencil_op(GS_STENCIL_BOTH, GS_ZERO, GS_ZERO, GS_ZERO);
|
gs_stencil_op(GS_STENCIL_BOTH, GS_ZERO, GS_ZERO, GS_ZERO);
|
||||||
|
|
||||||
std::string technique = "";
|
std::string technique = "";
|
||||||
switch (this->mask.type) {
|
switch (this->m_mask.type) {
|
||||||
case Region:
|
case Region:
|
||||||
if (this->mask.region.feather > 0.001) {
|
if (this->m_mask.region.feather > 0.001) {
|
||||||
if (this->mask.region.invert) {
|
if (this->m_mask.region.invert) {
|
||||||
technique = "RegionFeatherInverted";
|
technique = "RegionFeatherInverted";
|
||||||
} else {
|
} else {
|
||||||
technique = "RegionFeather";
|
technique = "RegionFeather";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (this->mask.region.invert) {
|
if (this->m_mask.region.invert) {
|
||||||
technique = "RegionInverted";
|
technique = "RegionInverted";
|
||||||
} else {
|
} else {
|
||||||
technique = "Region";
|
technique = "Region";
|
||||||
|
|
@ -1070,9 +1035,9 @@ void filter::blur::blur_instance::video_render(gs_effect_t* effect)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mask.source.source_texture) {
|
if (m_mask.source.source_texture) {
|
||||||
uint32_t source_width = obs_source_get_width(this->mask.source.source_texture->get_object());
|
uint32_t source_width = obs_source_get_width(this->m_mask.source.source_texture->get_object());
|
||||||
uint32_t source_height = obs_source_get_height(this->mask.source.source_texture->get_object());
|
uint32_t source_height = obs_source_get_height(this->m_mask.source.source_texture->get_object());
|
||||||
|
|
||||||
if (source_width == 0) {
|
if (source_width == 0) {
|
||||||
source_width = baseW;
|
source_width = baseW;
|
||||||
|
|
@ -1080,7 +1045,7 @@ void filter::blur::blur_instance::video_render(gs_effect_t* effect)
|
||||||
if (source_height == 0) {
|
if (source_height == 0) {
|
||||||
source_height = baseH;
|
source_height = baseH;
|
||||||
}
|
}
|
||||||
if (this->mask.source.is_scene) {
|
if (this->m_mask.source.is_scene) {
|
||||||
obs_video_info ovi;
|
obs_video_info ovi;
|
||||||
if (obs_get_video_info(&ovi)) {
|
if (obs_get_video_info(&ovi)) {
|
||||||
source_width = ovi.base_width;
|
source_width = ovi.base_width;
|
||||||
|
|
@ -1088,45 +1053,38 @@ void filter::blur::blur_instance::video_render(gs_effect_t* effect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this->mask.source.texture = this->mask.source.source_texture->render(source_width, source_height);
|
this->m_mask.source.texture = this->m_mask.source.source_texture->render(source_width, source_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<gs::effect> mask_effect = blur_factory::get()->get_mask_effect();
|
std::shared_ptr<gs::effect> mask_effect = blur_factory::get()->get_mask_effect();
|
||||||
apply_mask_parameters(mask_effect, tex_source->get_object(), tex_intermediate->get_object());
|
apply_mask_parameters(mask_effect, m_source_texture->get_object(), m_output_texture->get_object());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto op = this->rt_primary->render(baseW, baseH);
|
auto op = this->m_output_rt1->render(baseW, baseH);
|
||||||
gs_ortho(0, (float)baseW, 0, (float)baseH, -1, 1);
|
gs_ortho(0, (float)baseW, 0, (float)baseH, -1, 1);
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
while (gs_effect_loop(mask_effect->get_object(), technique.c_str())) {
|
while (gs_effect_loop(mask_effect->get_object(), technique.c_str())) {
|
||||||
gs_draw_sprite(tex_intermediate->get_object(), 0, baseW, baseH);
|
gs_draw_sprite(m_output_texture->get_object(), 0, baseW, baseH);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (std::exception ex) {
|
} catch (std::exception ex) {
|
||||||
if (this->can_log()) {
|
|
||||||
P_LOG_ERROR("<filter-blur:%s> Masking failed with error: %s.", obs_source_get_name(this->m_self),
|
|
||||||
ex.what());
|
|
||||||
}
|
|
||||||
gs_blend_state_pop();
|
gs_blend_state_pop();
|
||||||
obs_source_skip_video_filter(this->m_self);
|
obs_source_skip_video_filter(this->m_self);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
gs_blend_state_pop();
|
gs_blend_state_pop();
|
||||||
|
|
||||||
if (!(tex_intermediate = this->rt_primary->get_texture())) {
|
if (!(m_output_texture = this->m_output_rt1->get_texture())) {
|
||||||
if (this->can_log()) {
|
|
||||||
P_LOG_ERROR("<filter-blur:%s> Failed to get masked texture.", obs_source_get_name(this->m_self));
|
|
||||||
}
|
|
||||||
obs_source_skip_video_filter(this->m_self);
|
obs_source_skip_video_filter(this->m_self);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Swap RTs for further rendering.
|
// Swap RTs for further rendering.
|
||||||
std::swap(this->rt_primary, this->rt_secondary);
|
std::swap(this->m_output_rt1, this->m_output_rt2);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_source_texture = tex_intermediate;
|
m_output_rendered = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Color Conversion RGB-YUV or Straight Draw
|
// Color Conversion RGB-YUV or Straight Draw
|
||||||
|
|
@ -1144,7 +1102,7 @@ void filter::blur::blur_instance::video_render(gs_effect_t* effect)
|
||||||
gs_effect_t* finalEffect = effect ? effect : defaultEffect;
|
gs_effect_t* finalEffect = effect ? effect : defaultEffect;
|
||||||
const char* technique = "Draw";
|
const char* technique = "Draw";
|
||||||
|
|
||||||
if ((color_format == ColorFormat::YUV) && colorConversionEffect) {
|
if ((m_color_format == ColorFormat::YUV) && colorConversionEffect) {
|
||||||
finalEffect = colorConversionEffect->get_object();
|
finalEffect = colorConversionEffect->get_object();
|
||||||
technique = "YUVToRGB";
|
technique = "YUVToRGB";
|
||||||
}
|
}
|
||||||
|
|
@ -1154,10 +1112,10 @@ void filter::blur::blur_instance::video_render(gs_effect_t* effect)
|
||||||
P_LOG_ERROR("<filter-blur:%s> Failed to set image param.", obs_source_get_name(this->m_self));
|
P_LOG_ERROR("<filter-blur:%s> Failed to set image param.", obs_source_get_name(this->m_self));
|
||||||
failed = true;
|
failed = true;
|
||||||
} else {
|
} else {
|
||||||
gs_effect_set_texture(param, m_source_texture->get_object());
|
gs_effect_set_texture(param, m_output_texture->get_object());
|
||||||
}
|
}
|
||||||
while (gs_effect_loop(finalEffect, technique)) {
|
while (gs_effect_loop(finalEffect, technique)) {
|
||||||
gs_draw_sprite(m_source_texture->get_object(), 0, baseW, baseH);
|
gs_draw_sprite(m_output_texture->get_object(), 0, baseW, baseH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -120,27 +120,31 @@ namespace filter {
|
||||||
class blur_instance {
|
class blur_instance {
|
||||||
obs_source_t* m_self;
|
obs_source_t* m_self;
|
||||||
|
|
||||||
// Rendering
|
// Input
|
||||||
std::shared_ptr<gs::rendertarget> rt_source;
|
std::shared_ptr<gs::rendertarget> m_source_rt;
|
||||||
std::shared_ptr<gs::rendertarget> rt_primary;
|
|
||||||
std::shared_ptr<gs::rendertarget> rt_secondary;
|
|
||||||
std::shared_ptr<gs::texture> m_source_texture;
|
std::shared_ptr<gs::texture> m_source_texture;
|
||||||
bool m_source_rendered;
|
bool m_source_rendered;
|
||||||
|
|
||||||
|
// Rendering
|
||||||
|
std::shared_ptr<gs::rendertarget> m_output_rt1;
|
||||||
|
std::shared_ptr<gs::rendertarget> m_output_rt2;
|
||||||
|
std::shared_ptr<gs::texture> m_output_texture;
|
||||||
|
bool m_output_rendered;
|
||||||
|
|
||||||
// Blur
|
// Blur
|
||||||
std::shared_ptr<gs::effect> blur_effect;
|
std::shared_ptr<gs::effect> m_blur_effect;
|
||||||
std::string blur_technique;
|
std::string m_blur_technique;
|
||||||
filter::blur::type type;
|
filter::blur::type m_blur_type;
|
||||||
uint64_t size;
|
uint64_t m_blur_size;
|
||||||
/// Bilateral Blur
|
/// Bilateral Blur
|
||||||
double_t bilateral_smoothing;
|
double_t m_blur_bilateral_smoothing;
|
||||||
double_t bilateral_sharpness;
|
double_t m_blur_bilateral_sharpness;
|
||||||
/// Directional Blur
|
/// Directional Blur
|
||||||
bool directional;
|
bool m_blur_directional;
|
||||||
double_t angle;
|
double_t m_blur_angle;
|
||||||
/// Step Scaling
|
/// Step Scaling
|
||||||
bool scaling;
|
bool m_blur_step_scaling;
|
||||||
std::pair<double_t, double_t> scale;
|
std::pair<double_t, double_t> m_blur_step_scale;
|
||||||
|
|
||||||
// Masking
|
// Masking
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -174,11 +178,16 @@ namespace filter {
|
||||||
float_t a;
|
float_t a;
|
||||||
} color;
|
} color;
|
||||||
float_t multiplier;
|
float_t multiplier;
|
||||||
} mask;
|
} m_mask;
|
||||||
|
|
||||||
// advanced
|
// advanced
|
||||||
uint64_t color_format;
|
uint64_t m_color_format;
|
||||||
|
|
||||||
|
public:
|
||||||
|
blur_instance(obs_data_t* settings, obs_source_t* self);
|
||||||
|
~blur_instance();
|
||||||
|
|
||||||
|
private:
|
||||||
bool apply_shared_param(gs_texture_t* input, float texelX, float texelY);
|
bool apply_shared_param(gs_texture_t* input, float texelX, float texelY);
|
||||||
bool apply_bilateral_param();
|
bool apply_bilateral_param();
|
||||||
bool apply_gaussian_param(uint8_t width);
|
bool apply_gaussian_param(uint8_t width);
|
||||||
|
|
@ -188,14 +197,7 @@ namespace filter {
|
||||||
static bool modified_properties(void* ptr, obs_properties_t* props, obs_property* prop,
|
static bool modified_properties(void* ptr, obs_properties_t* props, obs_property* prop,
|
||||||
obs_data_t* settings);
|
obs_data_t* settings);
|
||||||
|
|
||||||
// Logging
|
|
||||||
std::chrono::high_resolution_clock::time_point last_log;
|
|
||||||
bool can_log();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
blur_instance(obs_data_t* settings, obs_source_t* self);
|
|
||||||
~blur_instance();
|
|
||||||
|
|
||||||
obs_properties_t* get_properties();
|
obs_properties_t* get_properties();
|
||||||
void update(obs_data_t*);
|
void update(obs_data_t*);
|
||||||
void load(obs_data_t*);
|
void load(obs_data_t*);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue