Browse Source

obs-filters: Add sharpen filter

jp9000 10 years ago
parent
commit
6e98fb89f4

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

@@ -7,6 +7,7 @@ set(obs-filters_SOURCES
 	crop-filter.c
 	chroma-key-filter.c
 	color-key-filter.c
+	sharpness-filter.c
 	mask-filter.c)
 
 add_library(obs-filters MODULE

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

@@ -4,6 +4,7 @@ AsyncDelayFilter="Video Delay (Async)"
 CropFilter="Crop"
 ChromaKeyFilter="Chroma Key"
 ColorKeyFilter="Color Key"
+SharpnessFilter="Sharpen"
 DelayMs="Delay (milliseconds)"
 Type="Type"
 MaskBlendType.MaskColor="Alpha Mask (Color Channel)"

+ 118 - 0
plugins/obs-filters/data/sharpness.effect

@@ -0,0 +1,118 @@
+// Based on libretro shader https://github.com/libretro/common-shaders/blob/master/test/lab/misc/sharpness.cg
+// Converted to obs effect file by Nibbles
+
+uniform float4x4 ViewProj;
+uniform texture2d image;
+uniform float4x4 color_matrix;
+uniform float3 color_range_min = {0.0, 0.0, 0.0};
+uniform float3 color_range_max = {1.0, 1.0, 1.0};
+
+uniform texture2d target;
+uniform float4 color = {1.0, 1.0, 1.0, 1.0};
+
+uniform float sharpness;
+uniform float texture_width;
+uniform float texture_height;
+
+sampler_state def_sampler {
+	Filter   = Linear;
+	AddressU = Clamp;
+	AddressV = Clamp;
+};
+
+struct VertInOut {
+	float4 pos : POSITION;
+	float2 uv  : TEXCOORD0;
+};
+
+struct VertOut {
+	float4 pos : POSITION;
+	float4 col : COLOR;
+	float2 uv  : TEXCOORD0;
+	float4 t1  : TEXCOORD1;
+	float4 t2  : TEXCOORD2;
+	float4 t3  : TEXCOORD3;
+};
+
+VertOut VSDefault(VertInOut vert_in)
+{
+	VertOut vert_out;
+	vert_out.pos = mul(float4(vert_in.pos.xyz, 1.0), ViewProj);
+	vert_out.uv  = vert_in.uv;
+	vert_out.col = color;
+
+	float2 ps = float2(1.0/texture_width, 1.0/texture_height);
+	float dx = ps.x;
+	float dy = ps.y;
+
+	vert_out.t1 = vert_in.uv.xxxy + float4( -dx, 0, dx,    -dy); //  A  B  C
+	vert_out.t2 = vert_in.uv.xxxy + float4( -dx, 0, dx,      0); //  D  E  F
+	vert_out.t3 = vert_in.uv.xxxy + float4( -dx, 0, dx,     dy); //  G  H  I
+	return vert_out;
+}
+
+float4 PSDrawBare(VertOut vert_in) : TARGET
+{
+	float4 E  = image.Sample(def_sampler, vert_in.uv);
+
+	float4 colorx = 8*E;
+	float4 B = image.Sample(def_sampler, vert_in.t1.yw);
+	float4 D = image.Sample(def_sampler, vert_in.t2.xw);
+	float4 F = image.Sample(def_sampler, vert_in.t2.zw);
+	float4 H = image.Sample(def_sampler, vert_in.t3.yw);
+	colorx -= image.Sample(def_sampler, vert_in.t1.xw);
+	colorx -= B;
+	colorx -= image.Sample(def_sampler, vert_in.t1.zw);
+	colorx -= D;
+	colorx -= F;
+	colorx -= image.Sample(def_sampler, vert_in.t3.xw);
+	colorx -= H;
+	colorx -= image.Sample(def_sampler, vert_in.t3.zw);
+
+	colorx = ((E!=F && E!=D) || (E!=B && E!=H)) ? saturate(E + colorx*sharpness) : E;
+
+	return colorx;
+}
+
+float4 PSDrawMatrix(VertOut vert_in) : TARGET
+{
+	float4 E  = image.Sample(def_sampler, vert_in.uv);
+
+	float4 colorx = 8*E;
+	float4 B = image.Sample(def_sampler, vert_in.t1.yw);
+	float4 D = image.Sample(def_sampler, vert_in.t2.xw);
+	float4 F = image.Sample(def_sampler, vert_in.t2.zw);
+	float4 H = image.Sample(def_sampler, vert_in.t3.yw);
+	colorx -= image.Sample(def_sampler, vert_in.t1.xw);
+	colorx -= B;
+	colorx -= image.Sample(def_sampler, vert_in.t1.zw);
+	colorx -= D;
+	colorx -= F;
+	colorx -= image.Sample(def_sampler, vert_in.t3.xw);
+	colorx -= H;
+	colorx -= image.Sample(def_sampler, vert_in.t3.zw);
+
+	colorx = ((E!=F && E!=D) || (E!=B && E!=H)) ? saturate(E + colorx*sharpness) : E;
+
+	float4 yuv = colorx;
+	yuv.xyz = clamp(yuv.xyz, color_range_min, color_range_max);
+	return saturate(mul(float4(yuv.xyz, 1.0), color_matrix));
+}
+
+technique Draw
+{
+	pass
+	{
+		vertex_shader = VSDefault(vert_in);
+		pixel_shader  = PSDrawBare(vert_in);
+	}
+}
+
+technique DrawMatrix
+{
+	pass
+	{
+		vertex_shader = VSDefault(vert_in);
+		pixel_shader  = PSDrawMatrix(vert_in);
+	}
+}

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

@@ -8,6 +8,7 @@ extern struct obs_source_info mask_filter;
 extern struct obs_source_info crop_filter;
 extern struct obs_source_info color_filter;
 extern struct obs_source_info color_key_filter;
+extern struct obs_source_info sharpness_filter;
 extern struct obs_source_info chroma_key_filter;
 extern struct obs_source_info async_delay_filter;
 
@@ -17,6 +18,7 @@ bool obs_module_load(void)
 	obs_register_source(&crop_filter);
 	obs_register_source(&color_filter);
 	obs_register_source(&color_key_filter);
+	obs_register_source(&sharpness_filter);
 	obs_register_source(&chroma_key_filter);
 	obs_register_source(&async_delay_filter);
 	return true;

+ 126 - 0
plugins/obs-filters/sharpness-filter.c

@@ -0,0 +1,126 @@
+#include <obs-module.h>
+#include <obs-source.h>
+#include <obs.h>
+#include <util/platform.h>
+
+struct sharpness_data {
+	obs_source_t                   *context;
+
+	gs_effect_t                    *effect;
+	gs_eparam_t                    *sharpness_param;
+	gs_eparam_t                    *texture_width, *texture_height;
+
+	float                          sharpness;
+	float                          texwidth, texheight;
+};
+
+static const char *sharpness_getname(void)
+{
+	return obs_module_text("SharpnessFilter");
+}
+
+static void sharpness_update(void *data, obs_data_t *settings)
+{
+	struct sharpness_data *filter = data;
+	double sharpness = obs_data_get_double(settings, "sharpness");
+
+	filter->sharpness = (float)sharpness;
+}
+
+static void sharpness_destroy(void *data)
+{
+	struct sharpness_data *filter = data;
+
+	if (filter->effect) {
+		obs_enter_graphics();
+		gs_effect_destroy(filter->effect);
+		obs_leave_graphics();
+	}
+
+	bfree(data);
+}
+
+static void *sharpness_create(obs_data_t *settings, obs_source_t *context)
+{
+	struct sharpness_data *filter =
+		bzalloc(sizeof(struct sharpness_data));
+	char *effect_path = obs_module_file("sharpness.effect");
+
+	filter->context = context;
+
+	obs_enter_graphics();
+
+	filter->effect = gs_effect_create_from_file(effect_path, NULL);
+	if (filter) {
+		filter->sharpness_param = gs_effect_get_param_by_name(
+			filter->effect, "sharpness");
+		filter->texture_width = gs_effect_get_param_by_name(
+			filter->effect, "texture_width");
+		filter->texture_height = gs_effect_get_param_by_name(
+			filter->effect, "texture_height");
+	}
+
+	obs_leave_graphics();
+
+	bfree(effect_path);
+
+	if (!filter->effect) {
+		sharpness_destroy(filter);
+		return NULL;
+	}
+
+	sharpness_update(filter, settings);
+	return filter;
+}
+
+static void sharpness_render(void *data, gs_effect_t *effect)
+{
+	struct sharpness_data *filter = data;
+	if (!filter) return;
+	if (!obs_filter_get_target(filter->context)) return;
+
+	obs_source_process_filter_begin(filter->context, GS_RGBA,
+		OBS_ALLOW_DIRECT_RENDERING);
+
+	filter->texwidth =(float)obs_source_get_width(
+			obs_filter_get_target(filter->context));
+	filter->texheight = (float)obs_source_get_height(
+			obs_filter_get_target(filter->context));
+
+	gs_effect_set_float(filter->sharpness_param, filter->sharpness);
+	gs_effect_set_float(filter->texture_width, filter->texwidth);
+	gs_effect_set_float(filter->texture_height, filter->texheight);
+
+	obs_source_process_filter_end(filter->context, filter->effect, 0, 0);
+
+	UNUSED_PARAMETER(effect);
+}
+
+static obs_properties_t *sharpness_properties(void *data)
+{
+	obs_properties_t *props = obs_properties_create();
+
+	obs_properties_add_float_slider(props, "sharpness",
+		"Sharpness", 0.0f, 1.0f, 0.01f);
+
+	UNUSED_PARAMETER(data);
+	return props;
+}
+
+static void sharpness_defaults(obs_data_t *settings)
+{
+	obs_data_set_default_double(settings, "sharpness", 0.08);
+}
+
+struct obs_source_info sharpness_filter = {
+	.id = "sharpness_filter",
+	.type = OBS_SOURCE_TYPE_FILTER,
+	.output_flags = OBS_SOURCE_VIDEO,
+	.get_name = sharpness_getname,
+	.create = sharpness_create,
+	.destroy = sharpness_destroy,
+	.update = sharpness_update,
+	.video_render = sharpness_render,
+	.get_properties = sharpness_properties,
+	.get_defaults = sharpness_defaults
+};