浏览代码

obs-transitions: Add 'slide' transition

Closes jp9000/obs-studio#516
hwdro 9 年之前
父节点
当前提交
e3a9f395a6

+ 1 - 0
plugins/obs-transitions/CMakeLists.txt

@@ -2,6 +2,7 @@ project(obs-transitions)
 
 set(obs-transitions_SOURCES
 	obs-transitions.c
+	transition-slide.c
 	transition-swipe.c
 	transition-fade.c
 	transition-cut.c

+ 1 - 0
plugins/obs-transitions/data/locale/en-US.ini

@@ -1,6 +1,7 @@
 FadeTransition="Fade"
 CutTransition="Cut"
 SwipeTransition="Swipe"
+SlideTransition="Slide"
 Direction="Direction"
 Direction.Left="Left"
 Direction.Right="Right"

+ 45 - 0
plugins/obs-transitions/data/slide_transition.effect

@@ -0,0 +1,45 @@
+uniform float4x4 ViewProj;
+uniform texture2d tex_a;
+uniform texture2d tex_b;
+uniform float2 tex_a_dir;
+uniform float2 tex_b_dir;
+
+
+sampler_state textureSampler {
+	Filter    = Linear;
+	AddressU  = Clamp;
+	AddressV  = Clamp;
+};
+
+struct VertData {
+	float4 pos : POSITION;
+	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;
+	return vert_out;
+}
+
+float4 PSSlide(VertData v_in) : TARGET
+{
+	float2 tex_a_uv = v_in.uv + tex_a_dir;
+	float2 tex_b_uv = v_in.uv - tex_b_dir;
+
+	return (tex_a_uv.x - saturate(tex_a_uv.x) != 0.0) ||
+	       (tex_a_uv.y - saturate(tex_a_uv.y) != 0.0)
+		   ? tex_b.Sample(textureSampler, tex_b_uv)
+		   : tex_a.Sample(textureSampler, tex_a_uv);
+}
+
+technique Slide
+{
+	pass
+	{
+		vertex_shader = VSDefault(v_in);
+		pixel_shader = PSSlide(v_in);
+	}
+}

+ 11 - 0
plugins/obs-transitions/easings.h

@@ -0,0 +1,11 @@
+#pragma once
+
+static inline float cubic_ease_in_out(float t)
+{
+	if (t < 0.5f) {
+		return 4.0f * t * t * t;
+	} else {
+		float temp = (2.0f * t - 2.0f);
+		return (t - 1.0f) * temp * temp + 1.0f;
+	}
+}

+ 2 - 0
plugins/obs-transitions/obs-transitions.c

@@ -7,11 +7,13 @@ OBS_MODULE_USE_DEFAULT_LOCALE("obs-transitions", "en-US")
 extern struct obs_source_info cut_transition;
 extern struct obs_source_info fade_transition;
 extern struct obs_source_info swipe_transition;
+extern struct obs_source_info slide_transition;
 
 bool obs_module_load(void)
 {
 	obs_register_source(&cut_transition);
 	obs_register_source(&fade_transition);
 	obs_register_source(&swipe_transition);
+	obs_register_source(&slide_transition);
 	return true;
 }

+ 165 - 0
plugins/obs-transitions/transition-slide.c

@@ -0,0 +1,165 @@
+#include <obs-module.h>
+#include <graphics/vec2.h>
+#include "easings.h"
+
+#define S_DIRECTION "direction"
+
+struct slide_info {
+	obs_source_t *source;
+
+	gs_effect_t *effect;
+	gs_eparam_t *a_param;
+	gs_eparam_t *b_param;
+	gs_eparam_t *tex_a_dir_param;
+	gs_eparam_t *tex_b_dir_param;
+
+	struct vec2 dir;
+	bool slide_in;
+};
+
+static const char *slide_get_name(void *type_data)
+{
+	UNUSED_PARAMETER(type_data);
+	return obs_module_text("SlideTransition");
+}
+
+static void slide_update(void *data, obs_data_t *settings)
+{
+	struct slide_info *slide = data;
+	const char *dir = obs_data_get_string(settings, S_DIRECTION);
+
+	if (strcmp(dir, "right") == 0)
+		slide->dir = (struct vec2){ -1.0f, 0.0f };
+	else if (strcmp(dir, "up") == 0)
+		slide->dir = (struct vec2){ 0.0f, 1.0f };
+	else if (strcmp(dir, "down") == 0)
+		slide->dir = (struct vec2){ 0.0f, -1.0f };
+	else /* left */
+		slide->dir = (struct vec2){ 1.0f, 0.0f };
+}
+
+void *slide_create(obs_data_t *settings, obs_source_t *source)
+{
+	struct slide_info *slide;
+	gs_effect_t *effect;
+
+	char *file = obs_module_file("slide_transition.effect");
+
+	obs_enter_graphics();
+	effect = gs_effect_create_from_file(file, NULL);
+	obs_leave_graphics();
+
+	bfree(file);
+
+	if (!effect) {
+		blog(LOG_ERROR, "Could not find slide_transition.effect");
+		return NULL;
+	}
+
+	slide = bzalloc(sizeof(*slide));
+
+	slide->source = source;
+	slide->effect = effect;
+
+	slide->a_param = gs_effect_get_param_by_name(effect, "tex_a");
+	slide->b_param = gs_effect_get_param_by_name(effect, "tex_b");
+
+	slide->tex_a_dir_param =
+		gs_effect_get_param_by_name(effect, "tex_a_dir");
+	slide->tex_b_dir_param =
+		gs_effect_get_param_by_name(effect, "tex_b_dir");
+
+	obs_source_update(source, settings);
+
+	return slide;
+}
+
+void slide_destroy(void *data)
+{
+	struct slide_info *slide = data;
+	bfree(slide);
+}
+
+static void slide_callback(void *data, gs_texture_t *a, gs_texture_t *b,
+			   float t, uint32_t cx, uint32_t cy)
+{
+	struct slide_info *slide = data;
+
+	struct vec2 tex_a_dir = slide->dir;
+	struct vec2 tex_b_dir = slide->dir;
+
+	t = cubic_ease_in_out(t);
+
+	vec2_mulf(&tex_a_dir, &tex_a_dir, t);
+	vec2_mulf(&tex_b_dir, &tex_b_dir, 1.0f - t);
+
+	gs_effect_set_texture(slide->a_param, a);
+	gs_effect_set_texture(slide->b_param, b);
+
+	gs_effect_set_vec2(slide->tex_a_dir_param, &tex_a_dir);
+	gs_effect_set_vec2(slide->tex_b_dir_param, &tex_b_dir);
+
+	while (gs_effect_loop(slide->effect, "Slide"))
+		gs_draw_sprite(NULL, 0, cx, cy);
+}
+
+void slide_video_render(void *data, gs_effect_t *effect)
+{
+	struct slide_info *slide = data;
+	obs_transition_video_render(slide->source, slide_callback);
+	UNUSED_PARAMETER(effect);
+}
+
+static float mix_a(void *data, float t)
+{
+	UNUSED_PARAMETER(data);
+	return 1.0f - cubic_ease_in_out(t);
+}
+
+static float mix_b(void *data, float t)
+{
+	UNUSED_PARAMETER(data);
+	return cubic_ease_in_out(t);
+}
+
+bool slide_audio_render(void *data, uint64_t *ts_out,
+		struct obs_source_audio_mix *audio, uint32_t mixers,
+		size_t channels, size_t sample_rate)
+{
+	struct slide_info *slide = data;
+	return obs_transition_audio_render(slide->source, ts_out,
+		audio, mixers, channels, sample_rate, mix_a, mix_b);
+}
+
+static obs_properties_t *slide_properties(void *data)
+{
+	obs_properties_t *ppts = obs_properties_create();
+	obs_property_t *p;
+
+	p = obs_properties_add_list(ppts, S_DIRECTION,
+			obs_module_text("Direction"), OBS_COMBO_TYPE_LIST,
+			OBS_COMBO_FORMAT_STRING);
+	obs_property_list_add_string(p, obs_module_text("Direction.Left"),
+			"left");
+	obs_property_list_add_string(p, obs_module_text("Direction.Right"),
+			"right");
+	obs_property_list_add_string(p, obs_module_text("Direction.Up"),
+			"up");
+	obs_property_list_add_string(p, obs_module_text("Direction.Down"),
+			"down");
+
+	UNUSED_PARAMETER(data);
+	return ppts;
+}
+
+struct obs_source_info slide_transition = {
+	.id = "slide_transition",
+	.type = OBS_SOURCE_TYPE_TRANSITION,
+	.get_name = slide_get_name,
+	.create = slide_create,
+	.destroy = slide_destroy,
+	.update = slide_update,
+	.video_render = slide_video_render,
+	.audio_render = slide_audio_render,
+	.get_properties = slide_properties
+};

+ 4 - 13
plugins/obs-transitions/transition-swipe.c

@@ -1,5 +1,6 @@
 #include <obs-module.h>
 #include <graphics/vec2.h>
+#include "easings.h"
 
 struct swipe_info {
 	obs_source_t *source;
@@ -16,16 +17,6 @@ struct swipe_info {
 #define S_DIRECTION "direction"
 #define S_SWIPE_IN  "swipe_in"
 
-static float get_easing(float t)
-{
-	if (t < 0.5f) {
-		return 4.0f * t * t * t;
-	} else {
-		float temp = (2.0f * t - 2.0f);
-		return (t - 1.0f) * temp * temp + 1.0f;
-	}
-}
-
 static const char *swipe_get_name(void *type_data)
 {
 	UNUSED_PARAMETER(type_data);
@@ -93,7 +84,7 @@ static void swipe_callback(void *data, gs_texture_t *a, gs_texture_t *b,
 	if (swipe->swipe_in)
 		vec2_neg(&swipe_val, &swipe_val);
 
-	t = get_easing(t);
+	t = cubic_ease_in_out(t);
 
 	vec2_mulf(&swipe_val, &swipe_val, swipe->swipe_in ? 1.0f - t : t);
 
@@ -115,13 +106,13 @@ static void swipe_video_render(void *data, gs_effect_t *effect)
 static float mix_a(void *data, float t)
 {
 	UNUSED_PARAMETER(data);
-	return 1.0f - get_easing(t);
+	return 1.0f - cubic_ease_in_out(t);
 }
 
 static float mix_b(void *data, float t)
 {
 	UNUSED_PARAMETER(data);
-	return get_easing(t);
+	return cubic_ease_in_out(t);
 }
 
 static bool swipe_audio_render(void *data, uint64_t *ts_out,