diff --git a/plugins/obs-transitions/data/fade_transition.effect b/plugins/obs-transitions/data/fade_transition.effect index f1a1563f1..d8cba90ba 100644 --- a/plugins/obs-transitions/data/fade_transition.effect +++ b/plugins/obs-transitions/data/fade_transition.effect @@ -10,15 +10,19 @@ sampler_state textureSampler { }; struct VertData { + float2 uv : TEXCOORD0; float4 pos : POSITION; +}; + +struct FragData { float2 uv : TEXCOORD0; }; VertData VSDefault(VertData v_in) { VertData vert_out; - vert_out.pos = mul(float4(v_in.pos.xyz, 1.0), ViewProj); vert_out.uv = v_in.uv; + vert_out.pos = mul(float4(v_in.pos.xyz, 1.0), ViewProj); return vert_out; } @@ -32,20 +36,49 @@ 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 PSFade(VertData v_in) : TARGET +float4 Fade(FragData f_in) { - float4 a_val = tex_a.Sample(textureSampler, v_in.uv); - float4 b_val = tex_b.Sample(textureSampler, v_in.uv); + float4 a_val = tex_a.Sample(textureSampler, f_in.uv); + float4 b_val = tex_b.Sample(textureSampler, f_in.uv); float4 rgba = lerp(a_val, b_val, fade_val); rgba.rgb = srgb_nonlinear_to_linear(rgba.rgb); return rgba; } +float4 PSFade(FragData f_in) : TARGET +{ + float4 rgba = Fade(f_in); + return rgba; +} + +float4 FadeLinear(FragData f_in) +{ + float4 a_val = tex_a.Sample(textureSampler, f_in.uv); + float4 b_val = tex_b.Sample(textureSampler, f_in.uv); + float4 rgba = lerp(a_val, b_val, fade_val); + return rgba; +} + +float4 PSFadeLinear(FragData f_in) : TARGET +{ + float4 rgba = FadeLinear(f_in); + return rgba; +} + technique Fade { pass { vertex_shader = VSDefault(v_in); - pixel_shader = PSFade(v_in); + pixel_shader = PSFade(f_in); + } +} + +technique FadeLinear +{ + pass + { + vertex_shader = VSDefault(v_in); + pixel_shader = PSFadeLinear(f_in); } } diff --git a/plugins/obs-transitions/transition-cut.c b/plugins/obs-transitions/transition-cut.c index 9b203834e..5b9641c13 100644 --- a/plugins/obs-transitions/transition-cut.c +++ b/plugins/obs-transitions/transition-cut.c @@ -57,6 +57,14 @@ static bool cut_audio_render(void *data, uint64_t *ts_out, channels, sample_rate, mix_a, mix_b); } +static enum gs_color_space +cut_video_get_color_space(void *data, size_t count, + const enum gs_color_space *preferred_spaces) +{ + struct cut_info *const cut = data; + return obs_transition_video_get_color_space(cut->source); +} + struct obs_source_info cut_transition = { .id = "cut_transition", .type = OBS_SOURCE_TYPE_TRANSITION, @@ -65,4 +73,5 @@ struct obs_source_info cut_transition = { .destroy = cut_destroy, .video_render = cut_video_render, .audio_render = cut_audio_render, + .video_get_color_space = cut_video_get_color_space, }; diff --git a/plugins/obs-transitions/transition-fade.c b/plugins/obs-transitions/transition-fade.c index 26f66b49b..075bf7d3f 100644 --- a/plugins/obs-transitions/transition-fade.c +++ b/plugins/obs-transitions/transition-fade.c @@ -56,11 +56,23 @@ static void fade_callback(void *data, gs_texture_t *a, gs_texture_t *b, float t, const bool previous = gs_framebuffer_srgb_enabled(); gs_enable_framebuffer_srgb(true); - gs_effect_set_texture(fade->a_param, a); - gs_effect_set_texture(fade->b_param, b); + 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"; + } + gs_effect_set_float(fade->fade_param, t); - while (gs_effect_loop(fade->effect, "Fade")) + while (gs_effect_loop(fade->effect, tech_name)) gs_draw_sprite(NULL, 0, cx, cy); gs_enable_framebuffer_srgb(previous); @@ -68,9 +80,10 @@ static void fade_callback(void *data, gs_texture_t *a, gs_texture_t *b, float t, static void fade_video_render(void *data, gs_effect_t *effect) { + UNUSED_PARAMETER(effect); + struct fade_info *fade = data; obs_transition_video_render(fade->source, fade_callback); - UNUSED_PARAMETER(effect); } static float mix_a(void *data, float t) @@ -95,6 +108,24 @@ static bool fade_audio_render(void *data, uint64_t *ts_out, channels, sample_rate, mix_a, mix_b); } +static enum gs_color_space +fade_video_get_color_space(void *data, size_t count, + const enum gs_color_space *preferred_spaces) +{ + struct fade_info *const fade = data; + const enum gs_color_space transition_space = + obs_transition_video_get_color_space(fade->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_transition = { .id = "fade_transition", .type = OBS_SOURCE_TYPE_TRANSITION, @@ -103,4 +134,5 @@ struct obs_source_info fade_transition = { .destroy = fade_destroy, .video_render = fade_video_render, .audio_render = fade_audio_render, + .video_get_color_space = fade_video_get_color_space, };