ソースを参照

obs-filters: Handle premultiplied alpha input

Mostly by converting to straight alpha in shader when necessary.
jpark37 4 年 前
コミット
607ee098c5

+ 7 - 2
plugins/obs-filters/crop-filter.c

@@ -193,8 +193,13 @@ static void crop_filter_render(void *data, gs_effect_t *effect)
 	gs_effect_set_vec2(filter->param_mul, &filter->mul_val);
 	gs_effect_set_vec2(filter->param_add, &filter->add_val);
 
-	obs_source_process_filter_end(filter->context, filter->effect,
-				      filter->width, filter->height);
+	gs_blend_state_push();
+	gs_blend_function(GS_BLEND_ONE, GS_BLEND_INVSRCALPHA);
+
+	obs_source_process_filter_end_srgb(filter->context, filter->effect,
+					   filter->width, filter->height);
+
+	gs_blend_state_pop();
 
 	UNUSED_PARAMETER(effect);
 }

+ 5 - 3
plugins/obs-filters/data/blend_add_filter.effect

@@ -34,10 +34,12 @@ VertDataOut VSDefault(VertDataIn v_in)
 
 float4 PSAddImageRGBA(VertDataOut v_in) : TARGET
 {
-	float4 rgba = image.Sample(textureSampler, v_in.uv) * color;
+	float4 rgba = image.Sample(textureSampler, v_in.uv);
+	rgba.rgb = max(float3(0.0, 0.0, 0.0), rgba.rgb / rgba.a);
+	rgba *= color;
 
-	float4 targetRGB = target.Sample(textureSampler, v_in.uv2);
-	rgba.rgb = saturate(rgba.rgb + targetRGB.rgb);
+	float3 targetRGB = target.Sample(textureSampler, v_in.uv2).rgb;
+	rgba.rgb = saturate(rgba.rgb + targetRGB);
 	return rgba;
 }
 

+ 5 - 3
plugins/obs-filters/data/blend_mul_filter.effect

@@ -34,10 +34,12 @@ VertDataOut VSDefault(VertDataIn v_in)
 
 float4 PSMuliplyImageRGBA(VertDataOut v_in) : TARGET
 {
-	float4 rgba = image.Sample(textureSampler, v_in.uv) * color;
+	float4 rgba = image.Sample(textureSampler, v_in.uv);
+	rgba.rgb = max(float3(0.0, 0.0, 0.0), rgba.rgb / rgba.a);
+	rgba *= color;
 
-	float4 targetRGB = target.Sample(textureSampler, v_in.uv2);
-	rgba.rgb = saturate(rgba.rgb * targetRGB.rgb);
+	float3 targetRGB = target.Sample(textureSampler, v_in.uv2).rgb;
+	rgba.rgb = saturate(rgba.rgb * targetRGB);
 	return rgba;
 }
 

+ 5 - 3
plugins/obs-filters/data/blend_sub_filter.effect

@@ -34,10 +34,12 @@ VertDataOut VSDefault(VertDataIn v_in)
 
 float4 PSSubtractImageRGBA(VertDataOut v_in) : TARGET
 {
-	float4 rgba = image.Sample(textureSampler, v_in.uv) * color;
+	float4 rgba = image.Sample(textureSampler, v_in.uv);
+	rgba.rgb = max(float3(0.0, 0.0, 0.0), rgba.rgb / rgba.a);
+	rgba *= color;
 
-	float4 targetRGB = target.Sample(textureSampler, v_in.uv2);
-	rgba.rgb = saturate(rgba.rgb - targetRGB.rgb);
+	float3 targetRGB = target.Sample(textureSampler, v_in.uv2).rgb;
+	rgba.rgb = saturate(rgba.rgb - targetRGB);
 	return rgba;
 }
 

+ 1 - 0
plugins/obs-filters/data/chroma_key_filter.effect

@@ -85,6 +85,7 @@ float4 ProcessChromaKey(float4 rgba, VertData v_in)
 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);
 }
 

+ 1 - 0
plugins/obs-filters/data/chroma_key_filter_v2.effect

@@ -95,6 +95,7 @@ float4 ProcessChromaKey(float4 rgba, VertData v_in)
 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);
 }
 

+ 1 - 0
plugins/obs-filters/data/color_correction_filter.effect

@@ -47,6 +47,7 @@ float4 PSColorFilterRGBA(VertData vert_in) : TARGET
 {
 	/* Grab the current pixel to perform operations on. */
 	float4 currentPixel = image.Sample(textureSampler, vert_in.uv);
+	currentPixel.rgb = max(float3(0.0, 0.0, 0.0), currentPixel.rgb / currentPixel.a);
 
 	/* Always address the gamma first. */
 	currentPixel.rgb = pow(currentPixel.rgb, float3(gamma, gamma, gamma));

+ 14 - 8
plugins/obs-filters/data/color_grade_filter.effect

@@ -40,9 +40,9 @@ float srgb_linear_to_nonlinear_channel(float u)
 	return (u <= 0.0031308) ? (12.92 * u) : ((1.055 * pow(u, 1.0 / 2.4)) - 0.055);
 }
 
-float4 srgb_linear_to_nonlinear(float4 v)
+float3 srgb_linear_to_nonlinear(float3 v)
 {
-	return float4(srgb_linear_to_nonlinear_channel(v.r), srgb_linear_to_nonlinear_channel(v.g), srgb_linear_to_nonlinear_channel(v.b), v.a);
+	return float3(srgb_linear_to_nonlinear_channel(v.r), srgb_linear_to_nonlinear_channel(v.g), srgb_linear_to_nonlinear_channel(v.b));
 }
 
 float srgb_nonlinear_to_linear_channel(float u)
@@ -50,14 +50,16 @@ float srgb_nonlinear_to_linear_channel(float u)
 	return (u <= 0.04045) ? (u / 12.92) : pow((u + 0.055) / 1.055, 2.4);
 }
 
-float4 srgb_nonlinear_to_linear(float4 v)
+float3 srgb_nonlinear_to_linear(float3 v)
 {
-	return float4(srgb_nonlinear_to_linear_channel(v.r), srgb_nonlinear_to_linear_channel(v.g), srgb_nonlinear_to_linear_channel(v.b), v.a);
+	return float3(srgb_nonlinear_to_linear_channel(v.r), srgb_nonlinear_to_linear_channel(v.g), srgb_nonlinear_to_linear_channel(v.b));
 }
 
 float4 LUT1D(VertDataOut v_in) : TARGET
 {
-	float4 textureColor = srgb_linear_to_nonlinear(image.Sample(textureSampler, v_in.uv));
+	float4 textureColor = image.Sample(textureSampler, v_in.uv);
+	textureColor.rgb = max(float3(0.0, 0.0, 0.0), textureColor.rgb / textureColor.a);
+	textureColor.rgb = srgb_linear_to_nonlinear(textureColor.rgb);
 
 	if (textureColor.r >= domain_min.r && textureColor.r <= domain_max.r) {
 		float u = textureColor.r * clut_scale.r + clut_offset.r;
@@ -77,12 +79,15 @@ float4 LUT1D(VertDataOut v_in) : TARGET
 		textureColor.b = lerp(textureColor.b, channel, clut_amount);
 	}
 
-	return srgb_nonlinear_to_linear(textureColor);
+	textureColor.rgb = srgb_nonlinear_to_linear(textureColor.rgb);
+	return textureColor;
 }
 
 float4 LUT3D(VertDataOut v_in) : TARGET
 {
-	float4 textureColor = srgb_linear_to_nonlinear(image.Sample(textureSampler, v_in.uv));
+	float4 textureColor = image.Sample(textureSampler, v_in.uv);
+	textureColor.rgb = max(0.0, textureColor.rgb / textureColor.a);
+	textureColor.rgb = srgb_linear_to_nonlinear(textureColor.rgb);
 	float r = textureColor.r;
 	float g = textureColor.g;
 	float b = textureColor.b;
@@ -165,7 +170,8 @@ float4 LUT3D(VertDataOut v_in) : TARGET
 		textureColor.rgb = lerp(textureColor.rgb, luttedColor, clut_amount);
 	}
 
-	return srgb_nonlinear_to_linear(textureColor);
+	textureColor.rgb = srgb_nonlinear_to_linear(textureColor.rgb);
+	return textureColor;
 }
 
 technique Draw1D

+ 1 - 0
plugins/obs-filters/data/color_key_filter.effect

@@ -50,6 +50,7 @@ float4 ProcessColorKey(float4 rgba, VertData v_in)
 float4 PSColorKeyRGBA(VertData v_in) : TARGET
 {
 	float4 rgba = image.Sample(textureSampler, v_in.uv) * color;
+	rgba.rgb = max(float3(0.0, 0.0, 0.0), rgba.rgb / rgba.a);
 	return ProcessColorKey(rgba, v_in);
 }
 

+ 1 - 0
plugins/obs-filters/data/color_key_filter_v2.effect

@@ -50,6 +50,7 @@ float4 ProcessColorKey(float4 rgba, VertData v_in)
 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);
 }

+ 1 - 0
plugins/obs-filters/data/luma_key_filter.effect

@@ -28,6 +28,7 @@ VertData VSDefault(VertData v_in)
 float4 PSALumaKeyRGBA(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);
 
 	float4 lumaCoef = float4(0.2989, 0.5870, 0.1140, 0.0);
 

+ 1 - 0
plugins/obs-filters/data/luma_key_filter_v2.effect

@@ -28,6 +28,7 @@ VertData VSDefault(VertData v_in)
 float4 PSALumaKeyRGBA(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);
 
 	float3 lumaCoef = float3(0.2126, 0.7152, 0.0722);
 

+ 3 - 1
plugins/obs-filters/data/mask_alpha_filter.effect

@@ -34,7 +34,9 @@ VertDataOut VSDefault(VertDataIn v_in)
 
 float4 PSAlphaMaskRGBA(VertDataOut v_in) : TARGET
 {
-	float4 rgba = image.Sample(textureSampler, v_in.uv) * color;
+	float4 rgba = image.Sample(textureSampler, v_in.uv);
+	rgba.rgb = max(float3(0.0, 0.0, 0.0), rgba.rgb / rgba.a);
+	rgba *= color;
 
 	float4 targetRGB = target.Sample(textureSampler, v_in.uv2);
 	rgba.a *= targetRGB.a;

+ 3 - 1
plugins/obs-filters/data/mask_color_filter.effect

@@ -34,7 +34,9 @@ VertDataOut VSDefault(VertDataIn v_in)
 
 float4 PSColorMaskRGBA(VertDataOut v_in) : TARGET
 {
-	float4 rgba = image.Sample(textureSampler, v_in.uv) * color;
+	float4 rgba = image.Sample(textureSampler, v_in.uv);
+	rgba.rgb = max(float3(0.0, 0.0, 0.0), rgba.rgb / rgba.a);
+	rgba *= color;
 
 	float4 targetRGB = target.Sample(textureSampler, v_in.uv2);
 	rgba.a *= (targetRGB.r + targetRGB.g + targetRGB.b) / 3.0;

+ 7 - 3
plugins/obs-filters/luma-key-filter.c

@@ -130,9 +130,13 @@ static void luma_key_render_internal(void *data, bool srgb)
 	gs_effect_set_float(filter->luma_min_smooth_param,
 			    filter->luma_min_smooth);
 
-	const bool previous = gs_set_linear_srgb(srgb);
-	obs_source_process_filter_end(filter->context, filter->effect, 0, 0);
-	gs_set_linear_srgb(previous);
+	if (srgb) {
+		obs_source_process_filter_end_srgb(filter->context,
+						   filter->effect, 0, 0);
+	} else {
+		obs_source_process_filter_end(filter->context, filter->effect,
+					      0, 0);
+	}
 }
 
 static void luma_key_render_v1(void *data, gs_effect_t *effect)

+ 7 - 3
plugins/obs-filters/mask-filter.c

@@ -293,9 +293,13 @@ 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);
 
-	const bool previous = gs_set_linear_srgb(srgb);
-	obs_source_process_filter_end(filter->context, filter->effect, 0, 0);
-	gs_set_linear_srgb(previous);
+	if (srgb) {
+		obs_source_process_filter_end_srgb(filter->context,
+						   filter->effect, 0, 0);
+	} else {
+		obs_source_process_filter_end(filter->context, filter->effect,
+					      0, 0);
+	}
 }
 
 static void mask_filter_render_v1(void *data, gs_effect_t *effect)

+ 7 - 1
plugins/obs-filters/scroll-filter.c

@@ -218,7 +218,13 @@ static void scroll_filter_render(void *data, gs_effect_t *effect)
 
 	gs_effect_set_next_sampler(filter->param_image, filter->sampler);
 
-	obs_source_process_filter_end(filter->context, filter->effect, cx, cy);
+	gs_blend_state_push();
+	gs_blend_function(GS_BLEND_ONE, GS_BLEND_INVSRCALPHA);
+
+	obs_source_process_filter_end_srgb(filter->context, filter->effect, cx,
+					   cy);
+
+	gs_blend_state_pop();
 
 	UNUSED_PARAMETER(effect);
 }

+ 7 - 3
plugins/obs-filters/sharpness-filter.c

@@ -90,9 +90,13 @@ static void sharpness_render_internal(void *data, bool srgb)
 	gs_effect_set_float(filter->texture_width, filter->texwidth);
 	gs_effect_set_float(filter->texture_height, filter->texheight);
 
-	const bool previous = gs_set_linear_srgb(srgb);
-	obs_source_process_filter_end(filter->context, filter->effect, 0, 0);
-	gs_set_linear_srgb(previous);
+	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();
 }
 
 static void sharpness_render_v1(void *data, gs_effect_t *effect)