Merge pull request #4587 from jpark37/alpha-hack
Apply alpha in nonlinear space for images and async videomaster
commit
81e9ad818f
|
@ -33,6 +33,35 @@ float4 PSDrawAlphaDivide(VertInOut vert_in) : TARGET
|
|||
return float4(rgba.rgb * multiplier, alpha);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
float3 srgb_linear_to_nonlinear(float3 v)
|
||||
{
|
||||
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)
|
||||
{
|
||||
return (u <= 0.04045) ? (u / 12.92) : pow((u + 0.055) / 1.055, 2.4);
|
||||
}
|
||||
|
||||
float3 srgb_nonlinear_to_linear(float3 v)
|
||||
{
|
||||
return float3(srgb_nonlinear_to_linear_channel(v.r), srgb_nonlinear_to_linear_channel(v.g), srgb_nonlinear_to_linear_channel(v.b));
|
||||
}
|
||||
|
||||
float4 PSDrawNonlinearAlpha(VertInOut vert_in) : TARGET
|
||||
{
|
||||
float4 rgba = image.Sample(def_sampler, vert_in.uv);
|
||||
rgba.rgb = srgb_linear_to_nonlinear(rgba.rgb);
|
||||
rgba.rgb *= rgba.a;
|
||||
rgba.rgb = srgb_nonlinear_to_linear(rgba.rgb);
|
||||
return rgba;
|
||||
}
|
||||
|
||||
technique Draw
|
||||
{
|
||||
pass
|
||||
|
@ -50,3 +79,12 @@ technique DrawAlphaDivide
|
|||
pixel_shader = PSDrawAlphaDivide(vert_in);
|
||||
}
|
||||
}
|
||||
|
||||
technique DrawNonlinearAlpha
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_shader = VSDefault(vert_in);
|
||||
pixel_shader = PSDrawNonlinearAlpha(vert_in);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2056,17 +2056,30 @@ static void obs_source_draw_async_texture(struct obs_source *source)
|
|||
{
|
||||
gs_effect_t *effect = gs_get_effect();
|
||||
bool def_draw = (!effect);
|
||||
bool premultiplied = false;
|
||||
gs_technique_t *tech = NULL;
|
||||
|
||||
if (def_draw) {
|
||||
effect = obs_get_base_effect(OBS_EFFECT_DEFAULT);
|
||||
tech = gs_effect_get_technique(effect, "Draw");
|
||||
const bool linear = gs_get_linear_srgb();
|
||||
const char *tech_name = linear ? "DrawNonlinearAlpha" : "Draw";
|
||||
premultiplied = linear;
|
||||
tech = gs_effect_get_technique(effect, tech_name);
|
||||
gs_technique_begin(tech);
|
||||
gs_technique_begin_pass(tech, 0);
|
||||
}
|
||||
|
||||
if (premultiplied) {
|
||||
gs_blend_state_push();
|
||||
gs_blend_function(GS_BLEND_ONE, GS_BLEND_INVSRCALPHA);
|
||||
}
|
||||
|
||||
obs_source_draw_texture(source, effect);
|
||||
|
||||
if (premultiplied) {
|
||||
gs_blend_state_pop();
|
||||
}
|
||||
|
||||
if (def_draw) {
|
||||
gs_technique_end_pass(tech);
|
||||
gs_technique_end(tech);
|
||||
|
@ -3701,10 +3714,11 @@ bool obs_source_process_filter_begin(obs_source_t *filter,
|
|||
filter->filter_texrender =
|
||||
gs_texrender_create(format, GS_ZS_NONE);
|
||||
|
||||
gs_blend_state_push();
|
||||
gs_blend_function(GS_BLEND_ONE, GS_BLEND_ZERO);
|
||||
|
||||
if (gs_texrender_begin(filter->filter_texrender, cx, cy)) {
|
||||
gs_blend_state_push();
|
||||
gs_blend_function_separate(GS_BLEND_SRCALPHA, GS_BLEND_ZERO,
|
||||
GS_BLEND_ONE, GS_BLEND_ZERO);
|
||||
|
||||
bool custom_draw = (parent_flags & OBS_SOURCE_CUSTOM_DRAW) != 0;
|
||||
bool async = (parent_flags & OBS_SOURCE_ASYNC) != 0;
|
||||
struct vec4 clear_color;
|
||||
|
@ -3718,10 +3732,10 @@ bool obs_source_process_filter_begin(obs_source_t *filter,
|
|||
else
|
||||
obs_source_video_render(target);
|
||||
|
||||
gs_blend_state_pop();
|
||||
|
||||
gs_texrender_end(filter->filter_texrender);
|
||||
}
|
||||
|
||||
gs_blend_state_pop();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -3748,6 +3762,9 @@ static void obs_source_process_filter_tech_end_internal(
|
|||
|
||||
const char *tech = tech_name ? tech_name : "Draw";
|
||||
|
||||
gs_blend_state_push();
|
||||
gs_blend_function(GS_BLEND_ONE, GS_BLEND_INVSRCALPHA);
|
||||
|
||||
if (can_bypass(target, parent, parent_flags, filter->allow_direct)) {
|
||||
render_filter_bypass(target, effect, tech);
|
||||
} else {
|
||||
|
@ -3757,6 +3774,8 @@ static void obs_source_process_filter_tech_end_internal(
|
|||
}
|
||||
}
|
||||
|
||||
gs_blend_state_pop();
|
||||
|
||||
gs_set_linear_srgb(previous);
|
||||
}
|
||||
|
||||
|
|
|
@ -147,19 +147,31 @@ static void image_source_render(void *data, gs_effect_t *effect)
|
|||
if (!context->if2.image.texture)
|
||||
return;
|
||||
|
||||
const bool linear_srgb = gs_get_linear_srgb();
|
||||
effect = obs_get_base_effect(OBS_EFFECT_DEFAULT);
|
||||
gs_technique_t *tech =
|
||||
gs_effect_get_technique(effect, "DrawNonlinearAlpha");
|
||||
|
||||
const bool previous = gs_framebuffer_srgb_enabled();
|
||||
gs_enable_framebuffer_srgb(linear_srgb);
|
||||
gs_enable_framebuffer_srgb(true);
|
||||
|
||||
gs_blend_state_push();
|
||||
gs_blend_function(GS_BLEND_ONE, GS_BLEND_INVSRCALPHA);
|
||||
|
||||
gs_eparam_t *const param = gs_effect_get_param_by_name(effect, "image");
|
||||
if (linear_srgb)
|
||||
gs_effect_set_texture_srgb(param, context->if2.image.texture);
|
||||
else
|
||||
gs_effect_set_texture(param, context->if2.image.texture);
|
||||
gs_effect_set_texture_srgb(param, context->if2.image.texture);
|
||||
|
||||
gs_draw_sprite(context->if2.image.texture, 0, context->if2.image.cx,
|
||||
context->if2.image.cy);
|
||||
size_t passes = gs_technique_begin(tech);
|
||||
for (size_t i = 0; i < passes; i++) {
|
||||
gs_technique_begin_pass(tech, i);
|
||||
|
||||
gs_draw_sprite(context->if2.image.texture, 0,
|
||||
context->if2.image.cx, context->if2.image.cy);
|
||||
|
||||
gs_technique_end_pass(tech);
|
||||
}
|
||||
gs_technique_end(tech);
|
||||
|
||||
gs_blend_state_pop();
|
||||
|
||||
gs_enable_framebuffer_srgb(previous);
|
||||
}
|
||||
|
@ -298,7 +310,7 @@ static obs_missing_files_t *image_source_missingfiles(void *data)
|
|||
static struct obs_source_info image_source_info = {
|
||||
.id = "image_source",
|
||||
.type = OBS_SOURCE_TYPE_INPUT,
|
||||
.output_flags = OBS_SOURCE_VIDEO,
|
||||
.output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_CUSTOM_DRAW,
|
||||
.get_name = image_source_get_name,
|
||||
.create = image_source_create,
|
||||
.destroy = image_source_destroy,
|
||||
|
|
Loading…
Reference in New Issue