Просмотр исходного кода

obs-filters: Make mask/blend image center w/aspect by default

Fixes what is arguably the most annoying feature of the mask/blend
filter, the fact that the image always stretches to the entire source.
It now centers and preserves aspect ratio by default, with an option to
make it stretch and discard aspect ratio to make it operate as it did
before.
jp9000 9 лет назад
Родитель
Сommit
4f782f2415

+ 16 - 7
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;
 }

+ 16 - 7
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;
 }

+ 16 - 7
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;
 }

+ 1 - 0
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)"

+ 16 - 7
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;
 }

+ 16 - 7
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;
 }

+ 47 - 1
plugins/obs-filters/mask-filter.c

@@ -1,4 +1,5 @@
 #include <obs-module.h>
+#include <graphics/vec2.h>
 #include <graphics/vec4.h>
 #include <util/dstr.h>
 
@@ -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);