Skip to content

Commit

Permalink
Add feathering mask options (#19)
Browse files Browse the repository at this point in the history
* Add feathering option to circle mask
* Add feathering option to crop and rectangular mask
  • Loading branch information
exeldro committed Aug 31, 2023
1 parent 757e83d commit 9e52d5e
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 23 deletions.
3 changes: 3 additions & 0 deletions data/locale/en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ CompositeBlurFilter.EffectMask.Crop.Bottom="Bottom (%)"
CompositeBlurFilter.EffectMask.Crop.Left="Left (%)"
CompositeBlurFilter.EffectMask.Crop.Right="Right (%)"
CompositeBlurFilter.EffectMask.CornerRadius="Corner Radius (%)"
CompositeBlurFilter.EffectMask.Feathering="Feathering (%)"
CompositeBlurFilter.EffectMask.Invert="Invert Mask?"
CompositeBlurFilter.EffectMask.SourceParameters="Source Mask Parameters"
CompositeBlurFilter.EffectMask.ImageParameters="Image Mask Parameters"
Expand All @@ -60,10 +61,12 @@ CompositeBlurFilter.EffectMask.Source.Multiplier="Multiplier"
CompositeBlurFilter.EffectMask.Circle.CenterX="Center X (%)"
CompositeBlurFilter.EffectMask.Circle.CenterY="Center Y (%)"
CompositeBlurFilter.EffectMask.Circle.Radius="Radius (%)"
CompositeBlurFilter.EffectMask.Circle.Feathering="Feathering (%)"
CompositeBlurFilter.EffectMask.CircleParameters="Circle Mask Parameters"
CompositeBlurFilter.EffectMask.Rect.CenterX="Center X (%)"
CompositeBlurFilter.EffectMask.Rect.CenterY="Center Y (%)"
CompositeBlurFilter.EffectMask.Rect.Width="Width (%)"
CompositeBlurFilter.EffectMask.Rect.Height="Height (%)"
CompositeBlurFilter.EffectMask.Rect.CornerRadius="Corner Radius (%)"
CompositeBlurFilter.EffectMask.Rect.Feathering="Feathering (%)"
CompositeBlurFilter.EffectMask.RectParameters="Rectangle Mask Parameters"
11 changes: 11 additions & 0 deletions data/shaders/effect_mask_circle.effect
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ uniform texture2d image;
uniform texture2d filtered_image;

uniform float circle_radius;
uniform float feathering;
uniform float2 center;
uniform float2 uv_scale;
uniform bool inv = false;
Expand Down Expand Up @@ -34,6 +35,16 @@ float4 mainImage(VertData v_in) : TARGET
if (dist > circle_radius) {
return !inv ? image.Sample(textureSampler, v_in.uv) : filtered_image.Sample(textureSampler, v_in.uv);
}
if(feathering > 0.0 && circle_radius > 0.0){
float distance_factor = dist / circle_radius;
if (distance_factor > (1.0 - feathering)) {
float feathering_effect = (distance_factor - (1.0 - feathering)) / feathering;
if(inv){
feathering_effect = 1.0 - feathering_effect;
}
return ((image.Sample(textureSampler, v_in.uv) * feathering_effect) + (filtered_image.Sample(textureSampler, v_in.uv) * (1.0-feathering_effect)));
}
}
return inv ? image.Sample(textureSampler, v_in.uv) : filtered_image.Sample(textureSampler, v_in.uv);
}

Expand Down
61 changes: 38 additions & 23 deletions data/shaders/effect_mask_crop.effect
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ uniform float2 scale;
uniform float2 offset;
uniform float2 box_aspect_ratio;
uniform float corner_radius;
uniform float feathering;
uniform bool inv = false;

sampler_state textureSampler{
Expand Down Expand Up @@ -34,47 +35,61 @@ float4 mainImage(VertData v_in) : TARGET
// Outside
return inv ? filtered_image.Sample(textureSampler, v_in.uv) : image.Sample(textureSampler, v_in.uv);
}
// Inside
// 1. Scale to 1:1 ratio, shorten long side
float2 inner_coord = transform_coord * box_aspect_ratio;
if(
inner_coord.x > corner_radius && inner_coord.y > corner_radius &&
inner_coord.x < (box_aspect_ratio.x - corner_radius) && inner_coord.y < (box_aspect_ratio.y - corner_radius)
) {
return inv ? image.Sample(textureSampler, v_in.uv) : filtered_image.Sample(textureSampler, v_in.uv);
}
float min_dist;
if(inner_coord.x < corner_radius && inner_coord.y < corner_radius) {
// top left
if (distance(inner_coord, float2(corner_radius, corner_radius)) > corner_radius) {
float d = distance(inner_coord, float2(corner_radius, corner_radius));
if (d > corner_radius) {
return inv ? filtered_image.Sample(textureSampler, v_in.uv) : image.Sample(textureSampler, v_in.uv);
}
min_dist = corner_radius - d;
} else if(inner_coord.x < corner_radius && inner_coord.y > (box_aspect_ratio.y - corner_radius)) {
// bot left
if (distance(inner_coord, float2(corner_radius, box_aspect_ratio.y - corner_radius)) > corner_radius) {
return inv ? filtered_image.Sample(textureSampler, v_in.uv) : image.Sample(textureSampler, v_in.uv);
float d = distance(inner_coord, float2(corner_radius, box_aspect_ratio.y - corner_radius));
if (d > corner_radius) {
return inv ? filtered_image.Sample(textureSampler, v_in.uv) : image.Sample(textureSampler, v_in.uv);
}
min_dist = corner_radius - d;
} else if(inner_coord.x > (box_aspect_ratio.x - corner_radius) && inner_coord.y < corner_radius) {
// top right
if (distance(inner_coord, float2(box_aspect_ratio.x - corner_radius, corner_radius)) > corner_radius) {
float d = distance(inner_coord, float2(box_aspect_ratio.x - corner_radius, corner_radius));
if (d > corner_radius) {
return inv ? filtered_image.Sample(textureSampler, v_in.uv) : image.Sample(textureSampler, v_in.uv);
}
min_dist = corner_radius - d;
} else if(inner_coord.x > (box_aspect_ratio.x - corner_radius) && inner_coord.y > (box_aspect_ratio.y - corner_radius)) {
// bot right
if (distance(inner_coord, float2(box_aspect_ratio.x - corner_radius, box_aspect_ratio.y - corner_radius)) > corner_radius) {
float d = distance(inner_coord, float2(box_aspect_ratio.x - corner_radius, box_aspect_ratio.y - corner_radius));
if (d > corner_radius) {
return inv ? filtered_image.Sample(textureSampler, v_in.uv) : image.Sample(textureSampler, v_in.uv);
}
min_dist = corner_radius - d;
}else{
min_dist = inner_coord.x;
if (inner_coord.y < min_dist)
min_dist = inner_coord.y;
if (box_aspect_ratio.y - inner_coord.y < min_dist)
min_dist = box_aspect_ratio.y - inner_coord.y;
if (box_aspect_ratio.x - inner_coord.x < min_dist)
min_dist = box_aspect_ratio.x - inner_coord.x;
}
float feathering_effect = 0.0f;
float distance_factor = min_dist / (((box_aspect_ratio.x > box_aspect_ratio.y) ? box_aspect_ratio.y : box_aspect_ratio.x) / 2.0);
if (distance_factor < feathering) {
feathering_effect = 1.0 - (distance_factor / feathering);
}
if(inv){
feathering_effect = 1.0 - feathering_effect;
}
if (feathering_effect <= 0.0){
return filtered_image.Sample(textureSampler, v_in.uv);
} else if (feathering_effect >= 1.0){
return image.Sample(textureSampler, v_in.uv);
} else {
return ((image.Sample(textureSampler, v_in.uv) * feathering_effect) + (filtered_image.Sample(textureSampler, v_in.uv) * (1.0-feathering_effect)));
}

return inv ? image.Sample(textureSampler, v_in.uv) : filtered_image.Sample(textureSampler, v_in.uv);

// else if(
// transform_coord.x > corner_radius && transform_coord.x < 1.0f-corner_radius &&
// transform_coord.y > corner_radius && transform_coord.y < 1.0f-corner_radius
// ) {
// return inv ? image.Sample(textureSampler, v_in.uv) : filtered_image.Sample(textureSampler, v_in.uv);
// }
// return float4(1.0, 0.0, 1.0, 1.0);

}

technique Draw
Expand Down
47 changes: 47 additions & 0 deletions src/obs-composite-blur-filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,15 @@ static void *composite_blur_create(obs_data_t *settings, obs_source_t *source)
filter->param_mask_crop_offset = NULL;
filter->param_mask_crop_box_aspect_ratio = NULL;
filter->param_mask_crop_corner_radius = NULL;
filter->param_mask_crop_feathering = NULL;
filter->param_mask_crop_invert = NULL;
filter->param_mask_source_alpha_source = NULL;
filter->param_mask_source_rgba_weights = NULL;
filter->param_mask_source_multiplier = NULL;
filter->param_mask_source_invert = NULL;
filter->param_mask_circle_center = NULL;
filter->param_mask_circle_radius = NULL;
filter->param_mask_circle_feathering = NULL;
filter->param_mask_circle_inv = NULL;
filter->param_mask_circle_uv_scale = NULL;

Expand All @@ -118,6 +120,7 @@ static void *composite_blur_create(obs_data_t *settings, obs_source_t *source)
filter->mask_type = 0;
filter->mask_type_last = -1;
filter->mask_crop_corner_radius = 0.0f;
filter->mask_crop_feathering = 0.0;
filter->mask_crop_invert = false;

filter->mask_source_filter_type = EFFECT_MASK_SOURCE_FILTER_ALPHA;
Expand Down Expand Up @@ -231,6 +234,8 @@ static void composite_blur_update(void *data, obs_data_t *settings)
(float)obs_data_get_double(settings, "effect_mask_crop_right");
filter->mask_crop_corner_radius = (float)obs_data_get_double(
settings, "effect_mask_crop_corner_radius");
filter->mask_crop_feathering = (float)obs_data_get_double(
settings, "effect_mask_crop_feathering");
filter->mask_crop_invert =
obs_data_get_bool(settings, "effect_mask_crop_invert");
if (filter->mask_type != filter->mask_type_last) {
Expand Down Expand Up @@ -313,6 +318,8 @@ static void composite_blur_update(void *data, obs_data_t *settings)
settings, "effect_mask_circle_center_y");
filter->mask_circle_radius = (float)obs_data_get_double(
settings, "effect_mask_circle_radius");
filter->mask_circle_feathering = (float)obs_data_get_double(
settings, "effect_mask_circle_feathering");
filter->mask_circle_inv =
obs_data_get_bool(settings, "effect_mask_circle_invert");

Expand All @@ -326,6 +333,8 @@ static void composite_blur_update(void *data, obs_data_t *settings)
(float)obs_data_get_double(settings, "effect_mask_rect_height");
filter->mask_rect_corner_radius = (float)obs_data_get_double(
settings, "effect_mask_rect_corner_radius");
filter->mask_rect_feathering = (float)obs_data_get_double(
settings, "effect_mask_rect_feathering");
filter->mask_rect_inv =
obs_data_get_bool(settings, "effect_mask_rect_invert");

Expand Down Expand Up @@ -661,6 +670,12 @@ static void apply_effect_mask_rect(composite_blur_filter_data_t *filter)
gs_effect_set_float(filter->param_mask_crop_corner_radius,
radius);
}

float feathering = filter->mask_rect_feathering / 100.0f;
if (filter->param_mask_crop_feathering) {
gs_effect_set_float(filter->param_mask_crop_feathering,
feathering);
}
set_blending_parameters();

filter->output_texrender =
Expand Down Expand Up @@ -741,6 +756,12 @@ static void apply_effect_mask_crop(composite_blur_filter_data_t *filter)
gs_effect_set_float(filter->param_mask_crop_corner_radius,
radius);
}

float feathering = filter->mask_crop_feathering / 100.0f;
if (filter->param_mask_crop_feathering) {
gs_effect_set_float(filter->param_mask_crop_feathering,
feathering);
}
set_blending_parameters();

filter->output_texrender =
Expand Down Expand Up @@ -806,6 +827,11 @@ static void apply_effect_mask_circle(composite_blur_filter_data_t *filter)
if (filter->param_mask_circle_radius) {
gs_effect_set_float(filter->param_mask_circle_radius, radius);
}
float feathering = filter->mask_circle_feathering / 100.0f;
if (filter->param_mask_circle_feathering) {
gs_effect_set_float(filter->param_mask_circle_feathering,
feathering);
}
set_blending_parameters();

filter->output_texrender =
Expand Down Expand Up @@ -994,6 +1020,12 @@ static obs_properties_t *composite_blur_properties(void *data)
obs_module_text("CompositeBlurFilter.EffectMask.Circle.Radius"),
0.0, 500.01, 0.01);

obs_properties_add_float_slider(
effect_mask_circle, "effect_mask_circle_feathering",
obs_module_text(
"CompositeBlurFilter.EffectMask.Circle.Feathering"),
0.0, 100.01, 0.01);

obs_properties_add_bool(
effect_mask_circle, "effect_mask_circle_invert",
obs_module_text("CompositeBlurFilter.EffectMask.Invert"));
Expand Down Expand Up @@ -1032,6 +1064,12 @@ static obs_properties_t *composite_blur_properties(void *data)
"CompositeBlurFilter.EffectMask.Rect.CornerRadius"),
0.0, 100.01, 0.01);

obs_properties_add_float_slider(
effect_mask_rect, "effect_mask_rect_feathering",
obs_module_text(
"CompositeBlurFilter.EffectMask.Rect.Feathering"),
0.0, 100.01, 0.01);

obs_properties_add_bool(
effect_mask_rect, "effect_mask_rect_invert",
obs_module_text("CompositeBlurFilter.EffectMask.Invert"));
Expand Down Expand Up @@ -1147,6 +1185,11 @@ static obs_properties_t *composite_blur_properties(void *data)
obs_module_text("CompositeBlurFilter.EffectMask.CornerRadius"),
0.0, 50.01, 0.01);

obs_properties_add_float_slider(
effect_mask_crop, "effect_mask_crop_feathering",
obs_module_text("CompositeBlurFilter.EffectMask.Feathering"),
0.0, 100.01, 0.01);

obs_properties_add_bool(
effect_mask_crop, "effect_mask_crop_invert",
obs_module_text("CompositeBlurFilter.EffectMask.Invert"));
Expand Down Expand Up @@ -1552,6 +1595,8 @@ static void load_crop_mask_effect(composite_blur_filter_data_t *filter)
param;
} else if (strcmp(info.name, "corner_radius") == 0) {
filter->param_mask_crop_corner_radius = param;
} else if (strcmp(info.name, "feathering") == 0) {
filter->param_mask_crop_feathering = param;
} else if (strcmp(info.name, "inv") == 0) {
filter->param_mask_crop_invert = param;
}
Expand Down Expand Up @@ -1657,6 +1702,8 @@ static void load_circle_mask_effect(composite_blur_filter_data_t *filter)
filter->param_mask_circle_center = param;
} else if (strcmp(info.name, "circle_radius") == 0) {
filter->param_mask_circle_radius = param;
} else if (strcmp(info.name, "feathering") == 0) {
filter->param_mask_circle_feathering = param;
} else if (strcmp(info.name, "uv_scale") == 0) {
filter->param_mask_circle_uv_scale = param;
}
Expand Down
5 changes: 5 additions & 0 deletions src/obs-composite-blur-filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@ struct composite_blur_filter_data {
gs_eparam_t *param_mask_crop_box_aspect_ratio;
gs_eparam_t *param_mask_crop_corner_radius;
float mask_crop_corner_radius;
gs_eparam_t *param_mask_crop_feathering;
float mask_crop_feathering;
gs_eparam_t *param_mask_crop_invert;
bool mask_crop_invert;
int mask_source_filter_type;
Expand All @@ -194,6 +196,8 @@ struct composite_blur_filter_data {
float mask_circle_center_y;
gs_eparam_t *param_mask_circle_radius;
float mask_circle_radius;
gs_eparam_t *param_mask_circle_feathering;
float mask_circle_feathering;
gs_eparam_t *param_mask_circle_inv;
bool mask_circle_inv;
gs_eparam_t *param_mask_circle_uv_scale;
Expand All @@ -202,6 +206,7 @@ struct composite_blur_filter_data {
float mask_rect_width;
float mask_rect_height;
float mask_rect_corner_radius;
float mask_rect_feathering;
float mask_rect_inv;
gs_image_file_t *mask_image;

Expand Down

0 comments on commit 9e52d5e

Please sign in to comment.