Browse Source

obs-transitions: Add HDR support to cut/fade

Both transitions are capable of passing through HDR sources now.
jpark37 3 years ago
parent
commit
6e4ed48188

+ 38 - 5
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);
 	}
 }

+ 9 - 0
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,
 };

+ 36 - 4
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,
 };