obs-filters: Increase opacity precision
For v2 filters, switch Opacity settings from integer [0, 100] to floating-point [0.0, 1.0] with four decimal places for granular blacks. Also multiply alpha in shader to maintain precision.
This commit is contained in:
parent
ec25ade9f2
commit
e55bfa8e20
@ -119,8 +119,7 @@ static inline void
|
||||
color_settings_update_v2(struct chroma_key_filter_data_v2 *filter,
|
||||
obs_data_t *settings)
|
||||
{
|
||||
filter->opacity =
|
||||
(float)obs_data_get_int(settings, SETTING_OPACITY) * 0.01f;
|
||||
filter->opacity = (float)obs_data_get_double(settings, SETTING_OPACITY);
|
||||
|
||||
double contrast = obs_data_get_double(settings, SETTING_CONTRAST);
|
||||
contrast = (contrast < 0.0) ? (1.0 / (-contrast + 1.0))
|
||||
@ -388,9 +387,14 @@ static void chroma_key_render_v2(void *data, gs_effect_t *effect)
|
||||
gs_effect_set_float(filter->smoothness_param, filter->smoothness);
|
||||
gs_effect_set_float(filter->spill_param, filter->spill);
|
||||
|
||||
gs_blend_state_push();
|
||||
gs_blend_function(GS_BLEND_ONE, GS_BLEND_INVSRCALPHA);
|
||||
|
||||
obs_source_process_filter_end_srgb(filter->context, filter->effect, 0,
|
||||
0);
|
||||
|
||||
gs_blend_state_pop();
|
||||
|
||||
UNUSED_PARAMETER(effect);
|
||||
}
|
||||
|
||||
@ -466,8 +470,8 @@ static obs_properties_t *chroma_key_properties_v2(void *data)
|
||||
obs_properties_add_int_slider(props, SETTING_SPILL, TEXT_SPILL, 1, 1000,
|
||||
1);
|
||||
|
||||
obs_properties_add_int_slider(props, SETTING_OPACITY, TEXT_OPACITY, 0,
|
||||
100, 1);
|
||||
obs_properties_add_float_slider(props, SETTING_OPACITY, TEXT_OPACITY,
|
||||
0.0, 1.0, 0.0001);
|
||||
obs_properties_add_float_slider(props, SETTING_CONTRAST, TEXT_CONTRAST,
|
||||
-4.0, 4.0, 0.01);
|
||||
obs_properties_add_float_slider(props, SETTING_BRIGHTNESS,
|
||||
@ -479,7 +483,7 @@ static obs_properties_t *chroma_key_properties_v2(void *data)
|
||||
return props;
|
||||
}
|
||||
|
||||
static void chroma_key_defaults(obs_data_t *settings)
|
||||
static void chroma_key_defaults_v1(obs_data_t *settings)
|
||||
{
|
||||
obs_data_set_default_int(settings, SETTING_OPACITY, 100);
|
||||
obs_data_set_default_double(settings, SETTING_CONTRAST, 0.0);
|
||||
@ -492,6 +496,19 @@ static void chroma_key_defaults(obs_data_t *settings)
|
||||
obs_data_set_default_int(settings, SETTING_SPILL, 100);
|
||||
}
|
||||
|
||||
static void chroma_key_defaults_v2(obs_data_t *settings)
|
||||
{
|
||||
obs_data_set_default_double(settings, SETTING_OPACITY, 1.0);
|
||||
obs_data_set_default_double(settings, SETTING_CONTRAST, 0.0);
|
||||
obs_data_set_default_double(settings, SETTING_BRIGHTNESS, 0.0);
|
||||
obs_data_set_default_double(settings, SETTING_GAMMA, 0.0);
|
||||
obs_data_set_default_int(settings, SETTING_KEY_COLOR, 0x00FF00);
|
||||
obs_data_set_default_string(settings, SETTING_COLOR_TYPE, "green");
|
||||
obs_data_set_default_int(settings, SETTING_SIMILARITY, 400);
|
||||
obs_data_set_default_int(settings, SETTING_SMOOTHNESS, 80);
|
||||
obs_data_set_default_int(settings, SETTING_SPILL, 100);
|
||||
}
|
||||
|
||||
struct obs_source_info chroma_key_filter = {
|
||||
.id = "chroma_key_filter",
|
||||
.type = OBS_SOURCE_TYPE_FILTER,
|
||||
@ -502,7 +519,7 @@ struct obs_source_info chroma_key_filter = {
|
||||
.video_render = chroma_key_render_v1,
|
||||
.update = chroma_key_update_v1,
|
||||
.get_properties = chroma_key_properties_v1,
|
||||
.get_defaults = chroma_key_defaults,
|
||||
.get_defaults = chroma_key_defaults_v1,
|
||||
};
|
||||
|
||||
struct obs_source_info chroma_key_filter_v2 = {
|
||||
@ -516,5 +533,5 @@ struct obs_source_info chroma_key_filter_v2 = {
|
||||
.video_render = chroma_key_render_v2,
|
||||
.update = chroma_key_update_v2,
|
||||
.get_properties = chroma_key_properties_v2,
|
||||
.get_defaults = chroma_key_defaults,
|
||||
.get_defaults = chroma_key_defaults_v2,
|
||||
};
|
||||
|
@ -325,8 +325,7 @@ static void color_correction_filter_update_v2(void *data, obs_data_t *settings)
|
||||
(float)obs_data_get_double(settings, SETTING_HUESHIFT);
|
||||
|
||||
/* Build our Transparency number. */
|
||||
float opacity =
|
||||
(float)obs_data_get_int(settings, SETTING_OPACITY) * 0.01f;
|
||||
float opacity = (float)obs_data_get_double(settings, SETTING_OPACITY);
|
||||
|
||||
/* Hue is the radian of 0 to 360 degrees. */
|
||||
float half_angle = 0.5f * (float)(hue_shift / (180.0f / M_PI));
|
||||
@ -588,8 +587,13 @@ static void color_correction_filter_render_v1(void *data, gs_effect_t *effect)
|
||||
gs_effect_set_matrix4(filter->final_matrix_param,
|
||||
&filter->final_matrix);
|
||||
|
||||
gs_blend_state_push();
|
||||
gs_blend_function(GS_BLEND_ONE, GS_BLEND_INVSRCALPHA);
|
||||
|
||||
obs_source_process_filter_end(filter->context, filter->effect, 0, 0);
|
||||
|
||||
gs_blend_state_pop();
|
||||
|
||||
UNUSED_PARAMETER(effect);
|
||||
}
|
||||
|
||||
@ -606,9 +610,14 @@ static void color_correction_filter_render_v2(void *data, gs_effect_t *effect)
|
||||
gs_effect_set_matrix4(filter->final_matrix_param,
|
||||
&filter->final_matrix);
|
||||
|
||||
gs_blend_state_push();
|
||||
gs_blend_function(GS_BLEND_ONE, GS_BLEND_INVSRCALPHA);
|
||||
|
||||
obs_source_process_filter_end_srgb(filter->context, filter->effect, 0,
|
||||
0);
|
||||
|
||||
gs_blend_state_pop();
|
||||
|
||||
UNUSED_PARAMETER(effect);
|
||||
}
|
||||
|
||||
@ -657,8 +666,8 @@ static obs_properties_t *color_correction_filter_properties_v2(void *data)
|
||||
TEXT_SATURATION, -1.0, 5.0, 0.01);
|
||||
obs_properties_add_float_slider(props, SETTING_HUESHIFT, TEXT_HUESHIFT,
|
||||
-180.0, 180.0, 0.01);
|
||||
obs_properties_add_int_slider(props, SETTING_OPACITY, TEXT_OPACITY, 0,
|
||||
100, 1);
|
||||
obs_properties_add_float_slider(props, SETTING_OPACITY, TEXT_OPACITY,
|
||||
0.0, 1.0, 0.0001);
|
||||
|
||||
obs_properties_add_color(props, SETTING_COLOR_MULTIPLY,
|
||||
TEXT_COLOR_MULTIPLY);
|
||||
@ -693,7 +702,7 @@ static void color_correction_filter_defaults_v2(obs_data_t *settings)
|
||||
obs_data_set_default_double(settings, SETTING_BRIGHTNESS, 0.0);
|
||||
obs_data_set_default_double(settings, SETTING_SATURATION, 0.0);
|
||||
obs_data_set_default_double(settings, SETTING_HUESHIFT, 0.0);
|
||||
obs_data_set_default_int(settings, SETTING_OPACITY, 100);
|
||||
obs_data_set_default_double(settings, SETTING_OPACITY, 1.0);
|
||||
obs_data_set_default_int(settings, SETTING_COLOR_MULTIPLY, 0x00FFFFFF);
|
||||
obs_data_set_default_int(settings, SETTING_COLOR_ADD, 0x00000000);
|
||||
}
|
||||
|
@ -108,8 +108,7 @@ static inline void
|
||||
color_settings_update_v2(struct color_key_filter_data_v2 *filter,
|
||||
obs_data_t *settings)
|
||||
{
|
||||
filter->opacity =
|
||||
(float)obs_data_get_int(settings, SETTING_OPACITY) / 100.0f;
|
||||
filter->opacity = (float)obs_data_get_double(settings, SETTING_OPACITY);
|
||||
|
||||
double contrast = obs_data_get_double(settings, SETTING_CONTRAST);
|
||||
contrast = (contrast < 0.0) ? (1.0 / (-contrast + 1.0))
|
||||
@ -336,9 +335,14 @@ static void color_key_render_v2(void *data, gs_effect_t *effect)
|
||||
gs_effect_set_float(filter->similarity_param, filter->similarity);
|
||||
gs_effect_set_float(filter->smoothness_param, filter->smoothness);
|
||||
|
||||
gs_blend_state_push();
|
||||
gs_blend_function(GS_BLEND_ONE, GS_BLEND_INVSRCALPHA);
|
||||
|
||||
obs_source_process_filter_end_srgb(filter->context, filter->effect, 0,
|
||||
0);
|
||||
|
||||
gs_blend_state_pop();
|
||||
|
||||
UNUSED_PARAMETER(effect);
|
||||
}
|
||||
|
||||
@ -414,8 +418,8 @@ static obs_properties_t *color_key_properties_v2(void *data)
|
||||
obs_properties_add_int_slider(props, SETTING_SMOOTHNESS,
|
||||
TEXT_SMOOTHNESS, 1, 1000, 1);
|
||||
|
||||
obs_properties_add_int_slider(props, SETTING_OPACITY, TEXT_OPACITY, 0,
|
||||
100, 1);
|
||||
obs_properties_add_float_slider(props, SETTING_OPACITY, TEXT_OPACITY,
|
||||
0.0, 1.0, 0.0001);
|
||||
obs_properties_add_float_slider(props, SETTING_CONTRAST, TEXT_CONTRAST,
|
||||
-4.0, 4.0, 0.01);
|
||||
obs_properties_add_float_slider(props, SETTING_BRIGHTNESS,
|
||||
@ -427,7 +431,7 @@ static obs_properties_t *color_key_properties_v2(void *data)
|
||||
return props;
|
||||
}
|
||||
|
||||
static void color_key_defaults(obs_data_t *settings)
|
||||
static void color_key_defaults_v1(obs_data_t *settings)
|
||||
{
|
||||
obs_data_set_default_int(settings, SETTING_OPACITY, 100);
|
||||
obs_data_set_default_double(settings, SETTING_CONTRAST, 0.0);
|
||||
@ -439,6 +443,18 @@ static void color_key_defaults(obs_data_t *settings)
|
||||
obs_data_set_default_int(settings, SETTING_SMOOTHNESS, 50);
|
||||
}
|
||||
|
||||
static void color_key_defaults_v2(obs_data_t *settings)
|
||||
{
|
||||
obs_data_set_default_double(settings, SETTING_OPACITY, 1.0);
|
||||
obs_data_set_default_double(settings, SETTING_CONTRAST, 0.0);
|
||||
obs_data_set_default_double(settings, SETTING_BRIGHTNESS, 0.0);
|
||||
obs_data_set_default_double(settings, SETTING_GAMMA, 0.0);
|
||||
obs_data_set_default_int(settings, SETTING_KEY_COLOR, 0x00FF00);
|
||||
obs_data_set_default_string(settings, SETTING_COLOR_TYPE, "green");
|
||||
obs_data_set_default_int(settings, SETTING_SIMILARITY, 80);
|
||||
obs_data_set_default_int(settings, SETTING_SMOOTHNESS, 50);
|
||||
}
|
||||
|
||||
struct obs_source_info color_key_filter = {
|
||||
.id = "color_key_filter",
|
||||
.type = OBS_SOURCE_TYPE_FILTER,
|
||||
@ -449,7 +465,7 @@ struct obs_source_info color_key_filter = {
|
||||
.video_render = color_key_render_v1,
|
||||
.update = color_key_update_v1,
|
||||
.get_properties = color_key_properties_v1,
|
||||
.get_defaults = color_key_defaults,
|
||||
.get_defaults = color_key_defaults_v1,
|
||||
};
|
||||
|
||||
struct obs_source_info color_key_filter_v2 = {
|
||||
@ -463,5 +479,5 @@ struct obs_source_info color_key_filter_v2 = {
|
||||
.video_render = color_key_render_v2,
|
||||
.update = color_key_update_v2,
|
||||
.get_properties = color_key_properties_v2,
|
||||
.get_defaults = color_key_defaults,
|
||||
.get_defaults = color_key_defaults_v2,
|
||||
};
|
||||
|
@ -40,6 +40,7 @@ float4 PSAddImageRGBA(VertDataOut v_in) : TARGET
|
||||
|
||||
float3 targetRGB = target.Sample(textureSampler, v_in.uv2).rgb;
|
||||
rgba.rgb = saturate(rgba.rgb + targetRGB);
|
||||
rgba.rgb *= rgba.a;
|
||||
return rgba;
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,7 @@ float4 PSMuliplyImageRGBA(VertDataOut v_in) : TARGET
|
||||
|
||||
float3 targetRGB = target.Sample(textureSampler, v_in.uv2).rgb;
|
||||
rgba.rgb = saturate(rgba.rgb * targetRGB);
|
||||
rgba.rgb *= rgba.a;
|
||||
return rgba;
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,7 @@ float4 PSSubtractImageRGBA(VertDataOut v_in) : TARGET
|
||||
|
||||
float3 targetRGB = target.Sample(textureSampler, v_in.uv2).rgb;
|
||||
rgba.rgb = saturate(rgba.rgb - targetRGB);
|
||||
rgba.rgb *= rgba.a;
|
||||
return rgba;
|
||||
}
|
||||
|
||||
|
@ -96,7 +96,9 @@ float4 PSChromaKeyRGBA(VertData v_in) : TARGET
|
||||
{
|
||||
float4 rgba = image.Sample(textureSampler, v_in.uv);
|
||||
rgba.rgb = max(float3(0.0, 0.0, 0.0), rgba.rgb / rgba.a);
|
||||
return ProcessChromaKey(rgba, v_in);
|
||||
rgba = ProcessChromaKey(rgba, v_in);
|
||||
rgba.rgb *= rgba.a;
|
||||
return rgba;
|
||||
}
|
||||
|
||||
technique Draw
|
||||
|
@ -59,6 +59,8 @@ float4 PSColorFilterRGBA(VertData vert_in) : TARGET
|
||||
*/
|
||||
currentPixel = mul(color_matrix, currentPixel);
|
||||
|
||||
currentPixel.rgb *= currentPixel.a;
|
||||
|
||||
return currentPixel;
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,9 @@ float4 PSColorKeyRGBA(VertData v_in) : TARGET
|
||||
float4 rgba = image.Sample(textureSampler, v_in.uv);
|
||||
rgba.rgb = max(float3(0.0, 0.0, 0.0), rgba.rgb / rgba.a);
|
||||
rgba.a *= opacity;
|
||||
return ProcessColorKey(rgba, v_in);
|
||||
rgba = ProcessColorKey(rgba, v_in);
|
||||
rgba.rgb *= rgba.a;
|
||||
return rgba;
|
||||
}
|
||||
|
||||
technique Draw
|
||||
|
@ -40,6 +40,7 @@ float4 PSAlphaMaskRGBA(VertDataOut v_in) : TARGET
|
||||
|
||||
float4 targetRGB = target.Sample(textureSampler, v_in.uv2);
|
||||
rgba.a *= targetRGB.a;
|
||||
rgba.rgb *= rgba.a;
|
||||
return rgba;
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,7 @@ float4 PSColorMaskRGBA(VertDataOut v_in) : TARGET
|
||||
|
||||
float4 targetRGB = target.Sample(textureSampler, v_in.uv2);
|
||||
rgba.a *= (targetRGB.r + targetRGB.g + targetRGB.b) / 3.0;
|
||||
rgba.rgb *= rgba.a;
|
||||
return rgba;
|
||||
}
|
||||
|
||||
|
@ -81,27 +81,25 @@ static void mask_filter_image_load(struct mask_filter_data *filter)
|
||||
}
|
||||
|
||||
static void mask_filter_update_internal(void *data, obs_data_t *settings,
|
||||
bool srgb)
|
||||
float opacity, bool srgb)
|
||||
{
|
||||
struct mask_filter_data *filter = data;
|
||||
|
||||
const char *path = obs_data_get_string(settings, SETTING_IMAGE_PATH);
|
||||
const char *effect_file = obs_data_get_string(settings, SETTING_TYPE);
|
||||
uint32_t color = (uint32_t)obs_data_get_int(settings, SETTING_COLOR);
|
||||
int opacity = (int)obs_data_get_int(settings, SETTING_OPACITY);
|
||||
char *effect_path;
|
||||
|
||||
if (filter->image_file)
|
||||
bfree(filter->image_file);
|
||||
filter->image_file = bstrdup(path);
|
||||
|
||||
color &= 0xFFFFFF;
|
||||
color |= (uint32_t)(((double)opacity) * 2.55) << 24;
|
||||
|
||||
if (srgb)
|
||||
vec4_from_rgba_srgb(&filter->color, color);
|
||||
else
|
||||
vec4_from_rgba(&filter->color, color);
|
||||
filter->color.w = opacity;
|
||||
|
||||
mask_filter_image_load(filter);
|
||||
filter->lock_aspect = !obs_data_get_bool(settings, SETTING_STRETCH);
|
||||
|
||||
@ -117,15 +115,19 @@ static void mask_filter_update_internal(void *data, obs_data_t *settings,
|
||||
|
||||
static void mask_filter_update_v1(void *data, obs_data_t *settings)
|
||||
{
|
||||
mask_filter_update_internal(data, settings, false);
|
||||
const float opacity =
|
||||
(float)(obs_data_get_int(settings, SETTING_OPACITY) * 0.01);
|
||||
mask_filter_update_internal(data, settings, opacity, false);
|
||||
}
|
||||
|
||||
static void mask_filter_update_v2(void *data, obs_data_t *settings)
|
||||
{
|
||||
mask_filter_update_internal(data, settings, true);
|
||||
const float opacity =
|
||||
(float)obs_data_get_double(settings, SETTING_OPACITY);
|
||||
mask_filter_update_internal(data, settings, opacity, true);
|
||||
}
|
||||
|
||||
static void mask_filter_defaults(obs_data_t *settings)
|
||||
static void mask_filter_defaults_v1(obs_data_t *settings)
|
||||
{
|
||||
obs_data_set_default_string(settings, SETTING_TYPE,
|
||||
"mask_color_filter.effect");
|
||||
@ -133,9 +135,17 @@ static void mask_filter_defaults(obs_data_t *settings)
|
||||
obs_data_set_default_int(settings, SETTING_OPACITY, 100);
|
||||
}
|
||||
|
||||
static void mask_filter_defaults_v2(obs_data_t *settings)
|
||||
{
|
||||
obs_data_set_default_string(settings, SETTING_TYPE,
|
||||
"mask_color_filter.effect");
|
||||
obs_data_set_default_int(settings, SETTING_COLOR, 0xFFFFFF);
|
||||
obs_data_set_default_double(settings, SETTING_OPACITY, 1.0);
|
||||
}
|
||||
|
||||
#define IMAGE_FILTER_EXTENSIONS " (*.bmp *.jpg *.jpeg *.tga *.gif *.png)"
|
||||
|
||||
static obs_properties_t *mask_filter_properties(void *data)
|
||||
static obs_properties_t *mask_filter_properties_internal(bool use_float_opacity)
|
||||
{
|
||||
obs_properties_t *props = obs_properties_create();
|
||||
struct dstr filter_str = {0};
|
||||
@ -169,16 +179,34 @@ static obs_properties_t *mask_filter_properties(void *data)
|
||||
obs_properties_add_path(props, SETTING_IMAGE_PATH, TEXT_IMAGE_PATH,
|
||||
OBS_PATH_FILE, filter_str.array, NULL);
|
||||
obs_properties_add_color(props, SETTING_COLOR, TEXT_COLOR);
|
||||
obs_properties_add_int_slider(props, SETTING_OPACITY, TEXT_OPACITY, 0,
|
||||
100, 1);
|
||||
if (use_float_opacity) {
|
||||
obs_properties_add_float_slider(props, SETTING_OPACITY,
|
||||
TEXT_OPACITY, 0.0, 1.0, 0.0001);
|
||||
} else {
|
||||
obs_properties_add_int_slider(props, SETTING_OPACITY,
|
||||
TEXT_OPACITY, 0, 100, 1);
|
||||
}
|
||||
obs_properties_add_bool(props, SETTING_STRETCH, TEXT_STRETCH);
|
||||
|
||||
dstr_free(&filter_str);
|
||||
|
||||
UNUSED_PARAMETER(data);
|
||||
return props;
|
||||
}
|
||||
|
||||
static obs_properties_t *mask_filter_properties_v1(void *data)
|
||||
{
|
||||
UNUSED_PARAMETER(data);
|
||||
|
||||
return mask_filter_properties_internal(false);
|
||||
}
|
||||
|
||||
static obs_properties_t *mask_filter_properties_v2(void *data)
|
||||
{
|
||||
UNUSED_PARAMETER(data);
|
||||
|
||||
return mask_filter_properties_internal(true);
|
||||
}
|
||||
|
||||
static void *mask_filter_create(obs_data_t *settings, obs_source_t *context)
|
||||
{
|
||||
struct mask_filter_data *filter =
|
||||
@ -293,6 +321,9 @@ static void mask_filter_render_internal(void *data, bool srgb)
|
||||
param = gs_effect_get_param_by_name(filter->effect, "add_val");
|
||||
gs_effect_set_vec2(param, &add_val);
|
||||
|
||||
gs_blend_state_push();
|
||||
gs_blend_function(GS_BLEND_ONE, GS_BLEND_INVSRCALPHA);
|
||||
|
||||
if (srgb) {
|
||||
obs_source_process_filter_end_srgb(filter->context,
|
||||
filter->effect, 0, 0);
|
||||
@ -300,6 +331,8 @@ static void mask_filter_render_internal(void *data, bool srgb)
|
||||
obs_source_process_filter_end(filter->context, filter->effect,
|
||||
0, 0);
|
||||
}
|
||||
|
||||
gs_blend_state_pop();
|
||||
}
|
||||
|
||||
static void mask_filter_render_v1(void *data, gs_effect_t *effect)
|
||||
@ -324,8 +357,8 @@ struct obs_source_info mask_filter = {
|
||||
.create = mask_filter_create,
|
||||
.destroy = mask_filter_destroy,
|
||||
.update = mask_filter_update_v1,
|
||||
.get_defaults = mask_filter_defaults,
|
||||
.get_properties = mask_filter_properties,
|
||||
.get_defaults = mask_filter_defaults_v1,
|
||||
.get_properties = mask_filter_properties_v1,
|
||||
.video_tick = mask_filter_tick,
|
||||
.video_render = mask_filter_render_v1,
|
||||
};
|
||||
@ -339,8 +372,8 @@ struct obs_source_info mask_filter_v2 = {
|
||||
.create = mask_filter_create,
|
||||
.destroy = mask_filter_destroy,
|
||||
.update = mask_filter_update_v2,
|
||||
.get_defaults = mask_filter_defaults,
|
||||
.get_properties = mask_filter_properties,
|
||||
.get_defaults = mask_filter_defaults_v2,
|
||||
.get_properties = mask_filter_properties_v2,
|
||||
.video_tick = mask_filter_tick,
|
||||
.video_render = mask_filter_render_v2,
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user