diff --git a/plugins/obs-transitions/data/fade_to_color_transition.effect b/plugins/obs-transitions/data/fade_to_color_transition.effect index fdf79aa1d..ec3fdf8b6 100644 --- a/plugins/obs-transitions/data/fade_to_color_transition.effect +++ b/plugins/obs-transitions/data/fade_to_color_transition.effect @@ -35,7 +35,6 @@ float3 srgb_nonlinear_to_linear(float3 v) float4 PSFadeToColor(VertData v_in) : TARGET { float4 rgba = lerp(tex.Sample(textureSampler, v_in.uv), color, swp); - rgba.rgb = srgb_nonlinear_to_linear(rgba.rgb); return rgba; } diff --git a/plugins/obs-transitions/data/fade_transition.effect b/plugins/obs-transitions/data/fade_transition.effect index d8cba90ba..432a23b0f 100644 --- a/plugins/obs-transitions/data/fade_transition.effect +++ b/plugins/obs-transitions/data/fade_transition.effect @@ -65,6 +65,19 @@ float4 PSFadeLinear(FragData f_in) : TARGET return rgba; } +float4 FadeSingle(FragData f_in) +{ + float4 a_val = tex_a.Sample(textureSampler, f_in.uv); + float4 rgba = a_val * fade_val; + return rgba; +} + +float4 PSFadeSingle(FragData f_in) : TARGET +{ + float4 rgba = FadeSingle(f_in); + return rgba; +} + technique Fade { pass @@ -82,3 +95,12 @@ technique FadeLinear pixel_shader = PSFadeLinear(f_in); } } + +technique FadeSingle +{ + pass + { + vertex_shader = VSDefault(v_in); + pixel_shader = PSFadeSingle(f_in); + } +} diff --git a/plugins/obs-transitions/transition-fade-to-color.c b/plugins/obs-transitions/transition-fade-to-color.c index d270c59ec..eba57d839 100644 --- a/plugins/obs-transitions/transition-fade-to-color.c +++ b/plugins/obs-transitions/transition-fade-to-color.c @@ -15,6 +15,7 @@ struct fade_to_color_info { gs_eparam_t *ep_color; struct vec4 color; + struct vec4 color_srgb; float switch_point; }; @@ -53,6 +54,7 @@ static void fade_to_color_update(void *data, obs_data_t *settings) color |= 0xFF000000; vec4_from_rgba(&fade_to_color->color, color); + vec4_from_rgba_srgb(&fade_to_color->color_srgb, color); fade_to_color->switch_point = (float)swp / 100.0f; } @@ -107,11 +109,21 @@ static void fade_to_color_callback(void *data, gs_texture_t *a, gs_texture_t *b, gs_texture_t *const tex = (t < fade_to_color->switch_point) ? a : b; - const bool previous = gs_framebuffer_srgb_enabled(); - gs_enable_framebuffer_srgb(true); + const bool nonlinear_fade = gs_get_color_space() == GS_CS_SRGB; + + const bool previous = gs_framebuffer_srgb_enabled(); + gs_enable_framebuffer_srgb(!nonlinear_fade); + + if (nonlinear_fade) { + gs_effect_set_texture(fade_to_color->ep_tex, tex); + gs_effect_set_vec4(fade_to_color->ep_color, + &fade_to_color->color); + } else { + gs_effect_set_texture_srgb(fade_to_color->ep_tex, tex); + gs_effect_set_vec4(fade_to_color->ep_color, + &fade_to_color->color_srgb); + } - gs_effect_set_texture(fade_to_color->ep_tex, tex); - gs_effect_set_vec4(fade_to_color->ep_color, &fade_to_color->color); gs_effect_set_float(fade_to_color->ep_swp, swp); while (gs_effect_loop(fade_to_color->effect, "FadeToColor")) @@ -122,10 +134,15 @@ static void fade_to_color_callback(void *data, gs_texture_t *a, gs_texture_t *b, static void fade_to_color_video_render(void *data, gs_effect_t *effect) { + UNUSED_PARAMETER(effect); + + const bool previous = gs_set_linear_srgb(true); + struct fade_to_color_info *fade_to_color = data; obs_transition_video_render(fade_to_color->source, fade_to_color_callback); - UNUSED_PARAMETER(effect); + + gs_set_linear_srgb(previous); } static float mix_a(void *data, float t) @@ -174,6 +191,24 @@ static void fade_to_color_defaults(obs_data_t *settings) obs_data_set_default_int(settings, S_SWITCH_POINT, 50); } +static enum gs_color_space +fade_to_color_video_get_color_space(void *data, size_t count, + const enum gs_color_space *preferred_spaces) +{ + struct fade_to_color_info *fade_to_color = data; + const enum gs_color_space transition_space = + obs_transition_video_get_color_space(fade_to_color->source); + + enum gs_color_space space = transition_space; + for (size_t i = 0; i < count; ++i) { + space = preferred_spaces[i]; + if (space == transition_space) + break; + } + + return space; +} + struct obs_source_info fade_to_color_transition = { .id = "fade_to_color_transition", .type = OBS_SOURCE_TYPE_TRANSITION, @@ -185,4 +220,5 @@ struct obs_source_info fade_to_color_transition = { .audio_render = fade_to_color_audio_render, .get_properties = fade_to_color_properties, .get_defaults = fade_to_color_defaults, + .video_get_color_space = fade_to_color_video_get_color_space, }; diff --git a/plugins/obs-transitions/transition-fade.c b/plugins/obs-transitions/transition-fade.c index 075bf7d3f..947c911a9 100644 --- a/plugins/obs-transitions/transition-fade.c +++ b/plugins/obs-transitions/transition-fade.c @@ -51,39 +51,55 @@ static void fade_destroy(void *data) static void fade_callback(void *data, gs_texture_t *a, gs_texture_t *b, float t, uint32_t cx, uint32_t cy) { - struct fade_info *fade = data; + if (a || b) { + struct fade_info *fade = data; - const bool previous = gs_framebuffer_srgb_enabled(); - gs_enable_framebuffer_srgb(true); + const bool previous = gs_framebuffer_srgb_enabled(); + gs_enable_framebuffer_srgb(true); - const char *tech_name = "Fade"; + const char *tech_name = "Fade"; - /* texture setters look reversed, but they aren't */ - if (gs_get_color_space() == GS_CS_SRGB) { - /* users want nonlinear fade */ - gs_effect_set_texture(fade->a_param, a); - gs_effect_set_texture(fade->b_param, b); - } else { - /* nonlinear fade is too wrong, so use linear fade */ - gs_effect_set_texture_srgb(fade->a_param, a); - gs_effect_set_texture_srgb(fade->b_param, b); - tech_name = "FadeLinear"; + if (!a || !b) { + tech_name = "FadeSingle"; + if (a) { + gs_effect_set_texture_srgb(fade->a_param, a); + t = 1.f - t; + } else { + gs_effect_set_texture_srgb(fade->a_param, b); + } + } else { + /* texture setters look reversed, but they aren't */ + if (gs_get_color_space() == GS_CS_SRGB) { + /* users want nonlinear fade */ + gs_effect_set_texture(fade->a_param, a); + gs_effect_set_texture(fade->b_param, b); + } else { + /* nonlinear fade is too wrong, so use linear fade */ + gs_effect_set_texture_srgb(fade->a_param, a); + gs_effect_set_texture_srgb(fade->b_param, b); + tech_name = "FadeLinear"; + } + } + + gs_effect_set_float(fade->fade_param, t); + + while (gs_effect_loop(fade->effect, tech_name)) + gs_draw_sprite(NULL, 0, cx, cy); + + gs_enable_framebuffer_srgb(previous); } - - gs_effect_set_float(fade->fade_param, t); - - while (gs_effect_loop(fade->effect, tech_name)) - gs_draw_sprite(NULL, 0, cx, cy); - - gs_enable_framebuffer_srgb(previous); } static void fade_video_render(void *data, gs_effect_t *effect) { UNUSED_PARAMETER(effect); + const bool previous = gs_set_linear_srgb(true); + struct fade_info *fade = data; - obs_transition_video_render(fade->source, fade_callback); + obs_transition_video_render2(fade->source, fade_callback, NULL); + + gs_set_linear_srgb(previous); } static float mix_a(void *data, float t)