diff --git a/plugins/obs-filters/data/blend_add_filter.effect b/plugins/obs-filters/data/blend_add_filter.effect index dc64c3408..ccb5107d5 100644 --- a/plugins/obs-filters/data/blend_add_filter.effect +++ b/plugins/obs-filters/data/blend_add_filter.effect @@ -6,6 +6,8 @@ uniform float3 color_range_max = {1.0, 1.0, 1.0}; uniform texture2d target; uniform float4 color; +uniform float2 mul_val; +uniform float2 add_val; sampler_state textureSampler { Filter = Linear; @@ -13,29 +15,36 @@ sampler_state textureSampler { AddressV = Clamp; }; -struct VertData { +struct VertDataIn { float4 pos : POSITION; float2 uv : TEXCOORD0; }; -VertData VSDefault(VertData v_in) +struct VertDataOut { + float4 pos : POSITION; + float2 uv : TEXCOORD0; + float2 uv2 : TEXCOORD1; +}; + +VertDataOut VSDefault(VertDataIn v_in) { - VertData vert_out; + VertDataOut vert_out; vert_out.pos = mul(float4(v_in.pos.xyz, 1.0), ViewProj); vert_out.uv = v_in.uv; + vert_out.uv2 = v_in.uv * mul_val + add_val; return vert_out; } -float4 PSAddImageRGBA(VertData v_in) : TARGET +float4 PSAddImageRGBA(VertDataOut v_in) : TARGET { float4 rgba = image.Sample(textureSampler, v_in.uv) * color; - float4 targetRGB = target.Sample(textureSampler, v_in.uv); + float4 targetRGB = target.Sample(textureSampler, v_in.uv2); rgba.rgb = saturate(rgba.rgb + targetRGB.rgb); return rgba; } -float4 PSAddImageMatrix(VertData v_in) : TARGET +float4 PSAddImageMatrix(VertDataOut v_in) : TARGET { float4 yuv = image.Sample(textureSampler, v_in.uv); yuv.xyz = clamp(yuv.xyz, color_range_min, color_range_max); @@ -43,7 +52,7 @@ float4 PSAddImageMatrix(VertData v_in) : TARGET float4 rgba = saturate(mul(float4(yuv.xyz, 1.0), color_matrix)) * color; - float4 targetRGB = target.Sample(textureSampler, v_in.uv); + float4 targetRGB = target.Sample(textureSampler, v_in.uv2); rgba.rgb = saturate(rgba.rgb + targetRGB.rgb); return rgba; } diff --git a/plugins/obs-filters/data/blend_mul_filter.effect b/plugins/obs-filters/data/blend_mul_filter.effect index 6ec1a8152..94bbe5935 100644 --- a/plugins/obs-filters/data/blend_mul_filter.effect +++ b/plugins/obs-filters/data/blend_mul_filter.effect @@ -6,6 +6,8 @@ uniform float3 color_range_max = {1.0, 1.0, 1.0}; uniform texture2d target; uniform float4 color; +uniform float2 mul_val; +uniform float2 add_val; sampler_state textureSampler { Filter = Linear; @@ -13,29 +15,36 @@ sampler_state textureSampler { AddressV = Clamp; }; -struct VertData { +struct VertDataIn { float4 pos : POSITION; float2 uv : TEXCOORD0; }; -VertData VSDefault(VertData v_in) +struct VertDataOut { + float4 pos : POSITION; + float2 uv : TEXCOORD0; + float2 uv2 : TEXCOORD1; +}; + +VertDataOut VSDefault(VertDataIn v_in) { - VertData vert_out; + VertDataOut vert_out; vert_out.pos = mul(float4(v_in.pos.xyz, 1.0), ViewProj); vert_out.uv = v_in.uv; + vert_out.uv2 = v_in.uv * mul_val + add_val; return vert_out; } -float4 PSMuliplyImageRGBA(VertData v_in) : TARGET +float4 PSMuliplyImageRGBA(VertDataOut v_in) : TARGET { float4 rgba = image.Sample(textureSampler, v_in.uv) * color; - float4 targetRGB = target.Sample(textureSampler, v_in.uv); + float4 targetRGB = target.Sample(textureSampler, v_in.uv2); rgba.rgb = saturate(rgba.rgb * targetRGB.rgb); return rgba; } -float4 PSMuliplyImageMatrix(VertData v_in) : TARGET +float4 PSMuliplyImageMatrix(VertDataOut v_in) : TARGET { float4 yuv = image.Sample(textureSampler, v_in.uv); yuv.xyz = clamp(yuv.xyz, color_range_min, color_range_max); @@ -43,7 +52,7 @@ float4 PSMuliplyImageMatrix(VertData v_in) : TARGET float4 rgba = saturate(mul(float4(yuv.xyz, 1.0), color_matrix)) * color; - float4 targetRGB = target.Sample(textureSampler, v_in.uv); + float4 targetRGB = target.Sample(textureSampler, v_in.uv2); rgba.rgb = saturate(rgba.rgb * targetRGB.rgb); return rgba; } diff --git a/plugins/obs-filters/data/blend_sub_filter.effect b/plugins/obs-filters/data/blend_sub_filter.effect index 841473419..5b63329d9 100644 --- a/plugins/obs-filters/data/blend_sub_filter.effect +++ b/plugins/obs-filters/data/blend_sub_filter.effect @@ -6,6 +6,8 @@ uniform float3 color_range_max = {1.0, 1.0, 1.0}; uniform texture2d target; uniform float4 color; +uniform float2 mul_val; +uniform float2 add_val; sampler_state textureSampler { Filter = Linear; @@ -13,29 +15,36 @@ sampler_state textureSampler { AddressV = Clamp; }; -struct VertData { +struct VertDataIn { float4 pos : POSITION; float2 uv : TEXCOORD0; }; -VertData VSDefault(VertData v_in) +struct VertDataOut { + float4 pos : POSITION; + float2 uv : TEXCOORD0; + float2 uv2 : TEXCOORD1; +}; + +VertDataOut VSDefault(VertDataIn v_in) { - VertData vert_out; + VertDataOut vert_out; vert_out.pos = mul(float4(v_in.pos.xyz, 1.0), ViewProj); vert_out.uv = v_in.uv; + vert_out.uv2 = v_in.uv * mul_val + add_val; return vert_out; } -float4 PSSubtractImageRGBA(VertData v_in) : TARGET +float4 PSSubtractImageRGBA(VertDataOut v_in) : TARGET { float4 rgba = image.Sample(textureSampler, v_in.uv) * color; - float4 targetRGB = target.Sample(textureSampler, v_in.uv); + float4 targetRGB = target.Sample(textureSampler, v_in.uv2); rgba.rgb = saturate(rgba.rgb - targetRGB.rgb); return rgba; } -float4 PSSubtractImageMatrix(VertData v_in) : TARGET +float4 PSSubtractImageMatrix(VertDataOut v_in) : TARGET { float4 yuv = image.Sample(textureSampler, v_in.uv); yuv.xyz = clamp(yuv.xyz, color_range_min, color_range_max); @@ -43,7 +52,7 @@ float4 PSSubtractImageMatrix(VertData v_in) : TARGET float4 rgba = saturate(mul(float4(yuv.xyz, 1.0), color_matrix)) * color; - float4 targetRGB = target.Sample(textureSampler, v_in.uv); + float4 targetRGB = target.Sample(textureSampler, v_in.uv2); rgba.rgb = saturate(rgba.rgb - targetRGB.rgb); return rgba; } diff --git a/plugins/obs-filters/data/locale/en-US.ini b/plugins/obs-filters/data/locale/en-US.ini index 927188c30..a3d9ccacb 100644 --- a/plugins/obs-filters/data/locale/en-US.ini +++ b/plugins/obs-filters/data/locale/en-US.ini @@ -50,3 +50,4 @@ NoiseGate.AttackTime="Attack Time (milliseconds)" NoiseGate.HoldTime="Hold Time (milliseconds)" NoiseGate.ReleaseTime="Release Time (milliseconds)" Gain.GainDB="Gain (dB)" +StretchImage="Stretch Image (discard image aspect ratio)" diff --git a/plugins/obs-filters/data/mask_alpha_filter.effect b/plugins/obs-filters/data/mask_alpha_filter.effect index e02f94150..72f3d7a9a 100644 --- a/plugins/obs-filters/data/mask_alpha_filter.effect +++ b/plugins/obs-filters/data/mask_alpha_filter.effect @@ -6,6 +6,8 @@ uniform float3 color_range_max = {1.0, 1.0, 1.0}; uniform texture2d target; uniform float4 color; +uniform float2 mul_val; +uniform float2 add_val; sampler_state textureSampler { Filter = Linear; @@ -13,29 +15,36 @@ sampler_state textureSampler { AddressV = Clamp; }; -struct VertData { +struct VertDataIn { float4 pos : POSITION; float2 uv : TEXCOORD0; }; -VertData VSDefault(VertData v_in) +struct VertDataOut { + float4 pos : POSITION; + float2 uv : TEXCOORD0; + float2 uv2 : TEXCOORD1; +}; + +VertDataOut VSDefault(VertDataIn v_in) { - VertData vert_out; + VertDataOut vert_out; vert_out.pos = mul(float4(v_in.pos.xyz, 1.0), ViewProj); vert_out.uv = v_in.uv; + vert_out.uv2 = v_in.uv * mul_val + add_val; return vert_out; } -float4 PSAlphaMaskRGBA(VertData v_in) : TARGET +float4 PSAlphaMaskRGBA(VertDataOut v_in) : TARGET { float4 rgba = image.Sample(textureSampler, v_in.uv) * color; - float4 targetRGB = target.Sample(textureSampler, v_in.uv); + float4 targetRGB = target.Sample(textureSampler, v_in.uv2); rgba.a *= targetRGB.a; return rgba; } -float4 PSAlphaMaskMatrix(VertData v_in) : TARGET +float4 PSAlphaMaskMatrix(VertDataOut v_in) : TARGET { float4 yuv = image.Sample(textureSampler, v_in.uv); yuv.xyz = clamp(yuv.xyz, color_range_min, color_range_max); @@ -43,7 +52,7 @@ float4 PSAlphaMaskMatrix(VertData v_in) : TARGET float4 rgba = saturate(mul(float4(yuv.xyz, 1.0), color_matrix)) * color; - float4 targetRGB = target.Sample(textureSampler, v_in.uv); + float4 targetRGB = target.Sample(textureSampler, v_in.uv2); rgba.a = targetRGB.a; return rgba; } diff --git a/plugins/obs-filters/data/mask_color_filter.effect b/plugins/obs-filters/data/mask_color_filter.effect index 0e0fd3ba6..6e0ab7e72 100644 --- a/plugins/obs-filters/data/mask_color_filter.effect +++ b/plugins/obs-filters/data/mask_color_filter.effect @@ -6,6 +6,8 @@ uniform float3 color_range_max = {1.0, 1.0, 1.0}; uniform texture2d target; uniform float4 color; +uniform float2 mul_val; +uniform float2 add_val; sampler_state textureSampler { Filter = Linear; @@ -13,29 +15,36 @@ sampler_state textureSampler { AddressV = Clamp; }; -struct VertData { +struct VertDataIn { float4 pos : POSITION; float2 uv : TEXCOORD0; }; -VertData VSDefault(VertData v_in) +struct VertDataOut { + float4 pos : POSITION; + float2 uv : TEXCOORD0; + float2 uv2 : TEXCOORD1; +}; + +VertDataOut VSDefault(VertDataIn v_in) { - VertData vert_out; + VertDataOut vert_out; vert_out.pos = mul(float4(v_in.pos.xyz, 1.0), ViewProj); vert_out.uv = v_in.uv; + vert_out.uv2 = v_in.uv * mul_val + add_val; return vert_out; } -float4 PSColorMaskRGBA(VertData v_in) : TARGET +float4 PSColorMaskRGBA(VertDataOut v_in) : TARGET { float4 rgba = image.Sample(textureSampler, v_in.uv) * color; - float4 targetRGB = target.Sample(textureSampler, v_in.uv); + float4 targetRGB = target.Sample(textureSampler, v_in.uv2); rgba.a *= (targetRGB.r + targetRGB.g + targetRGB.b) / 3.0; return rgba; } -float4 PSColorMaskMatrix(VertData v_in) : TARGET +float4 PSColorMaskMatrix(VertDataOut v_in) : TARGET { float4 yuv = image.Sample(textureSampler, v_in.uv); yuv.xyz = clamp(yuv.xyz, color_range_min, color_range_max); @@ -43,7 +52,7 @@ float4 PSColorMaskMatrix(VertData v_in) : TARGET float4 rgba = saturate(mul(float4(yuv.xyz, 1.0), color_matrix)) * color; - float4 targetRGB = target.Sample(textureSampler, v_in.uv); + float4 targetRGB = target.Sample(textureSampler, v_in.uv2); rgba.a = (targetRGB.r + targetRGB.g + targetRGB.b) / 3.0; return rgba; } diff --git a/plugins/obs-filters/mask-filter.c b/plugins/obs-filters/mask-filter.c index 4d00d2db5..dfe930e02 100644 --- a/plugins/obs-filters/mask-filter.c +++ b/plugins/obs-filters/mask-filter.c @@ -1,4 +1,5 @@ #include +#include #include #include @@ -6,11 +7,13 @@ #define SETTING_IMAGE_PATH "image_path" #define SETTING_COLOR "color" #define SETTING_OPACITY "opacity" +#define SETTING_STRETCH "stretch" #define TEXT_TYPE obs_module_text("Type") #define TEXT_IMAGE_PATH obs_module_text("Path") #define TEXT_COLOR obs_module_text("Color") #define TEXT_OPACITY obs_module_text("Opacity") +#define TEXT_STRETCH obs_module_text("StretchImage") #define TEXT_PATH_IMAGES obs_module_text("BrowsePath.Images") #define TEXT_PATH_ALL_FILES obs_module_text("BrowsePath.AllFiles") @@ -20,6 +23,7 @@ struct mask_filter_data { gs_texture_t *target; struct vec4 color; + bool lock_aspect; }; static const char *mask_filter_get_name(void *unused) @@ -46,6 +50,7 @@ static void mask_filter_update(void *data, obs_data_t *settings) gs_texture_destroy(filter->target); filter->target = (path) ? gs_texture_create_from_file(path) : NULL; + filter->lock_aspect = !obs_data_get_bool(settings, SETTING_STRETCH); effect_path = obs_module_file(effect_file); gs_effect_destroy(filter->effect); @@ -100,6 +105,7 @@ static obs_properties_t *mask_filter_properties(void *data) OBS_PATH_FILE, filter_str.array, NULL); obs_properties_add_color(props, SETTING_COLOR, TEXT_COLOR); obs_properties_add_int(props, SETTING_OPACITY, TEXT_OPACITY, 0, 100, 1); + obs_properties_add_bool(props, SETTING_STRETCH, TEXT_STRETCH); dstr_free(&filter_str); @@ -132,13 +138,47 @@ static void mask_filter_destroy(void *data) static void mask_filter_render(void *data, gs_effect_t *effect) { struct mask_filter_data *filter = data; + obs_source_t *target = obs_filter_get_target(filter->context); gs_eparam_t *param; + struct vec2 add_val = {0}; + struct vec2 mul_val = {1.0f, 1.0f}; - if (!filter->target || !filter->effect) { + if (!target || !filter->target || !filter->effect) { obs_source_skip_video_filter(filter->context); return; } + if (filter->lock_aspect) { + struct vec2 source_size; + struct vec2 mask_size; + struct vec2 mask_temp; + float source_aspect; + float mask_aspect; + bool size_to_x; + float fix; + + source_size.x = (float)obs_source_get_base_width(target); + source_size.y = (float)obs_source_get_base_height(target); + mask_size.x = (float)gs_texture_get_width(filter->target); + mask_size.y = (float)gs_texture_get_height(filter->target); + + source_aspect = source_size.x / source_size.y; + mask_aspect = mask_size.x / mask_size.y; + size_to_x = (source_aspect < mask_aspect); + + fix = size_to_x ? + (source_size.x / mask_size.x) : + (source_size.y / mask_size.y); + + vec2_mulf(&mask_size, &mask_size, fix); + vec2_div(&mul_val, &source_size, &mask_size); + vec2_mulf(&source_size, &source_size, 0.5f); + vec2_mulf(&mask_temp, &mask_size, 0.5f); + vec2_sub(&add_val, &source_size, &mask_temp); + vec2_neg(&add_val, &add_val); + vec2_div(&add_val, &add_val, &mask_size); + } + obs_source_process_filter_begin(filter->context, GS_RGBA, OBS_ALLOW_DIRECT_RENDERING); @@ -148,6 +188,12 @@ static void mask_filter_render(void *data, gs_effect_t *effect) param = gs_effect_get_param_by_name(filter->effect, "color"); gs_effect_set_vec4(param, &filter->color); + param = gs_effect_get_param_by_name(filter->effect, "mul_val"); + gs_effect_set_vec2(param, &mul_val); + + param = gs_effect_get_param_by_name(filter->effect, "add_val"); + gs_effect_set_vec2(param, &add_val); + obs_source_process_filter_end(filter->context, filter->effect, 0, 0); UNUSED_PARAMETER(effect);