obs-filters: Handle premultiplied alpha input

Mostly by converting to straight alpha in shader when necessary.
This commit is contained in:
jpark37 2021-04-27 23:23:05 -07:00 committed by Jim
parent a44e09f2e4
commit 607ee098c5
18 changed files with 77 additions and 31 deletions

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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));

View File

@ -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

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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)

View File

@ -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);
}

View File

@ -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)