From 6e98fb89f46e8f260b6095e18eb3f20726c82c03 Mon Sep 17 00:00:00 2001 From: jp9000 Date: Fri, 1 May 2015 00:08:10 -0700 Subject: [PATCH] obs-filters: Add sharpen filter --- plugins/obs-filters/CMakeLists.txt | 1 + plugins/obs-filters/data/locale/en-US.ini | 1 + plugins/obs-filters/data/sharpness.effect | 118 ++++++++++++++++++++ plugins/obs-filters/obs-filters.c | 2 + plugins/obs-filters/sharpness-filter.c | 126 ++++++++++++++++++++++ 5 files changed, 248 insertions(+) create mode 100644 plugins/obs-filters/data/sharpness.effect create mode 100644 plugins/obs-filters/sharpness-filter.c diff --git a/plugins/obs-filters/CMakeLists.txt b/plugins/obs-filters/CMakeLists.txt index 113770290..28491460e 100644 --- a/plugins/obs-filters/CMakeLists.txt +++ b/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 diff --git a/plugins/obs-filters/data/locale/en-US.ini b/plugins/obs-filters/data/locale/en-US.ini index 986b8c0c4..3ef40cecb 100644 --- a/plugins/obs-filters/data/locale/en-US.ini +++ b/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)" diff --git a/plugins/obs-filters/data/sharpness.effect b/plugins/obs-filters/data/sharpness.effect new file mode 100644 index 000000000..b27e90a72 --- /dev/null +++ b/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); + } +} diff --git a/plugins/obs-filters/obs-filters.c b/plugins/obs-filters/obs-filters.c index c9602f182..f20741050 100644 --- a/plugins/obs-filters/obs-filters.c +++ b/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; diff --git a/plugins/obs-filters/sharpness-filter.c b/plugins/obs-filters/sharpness-filter.c new file mode 100644 index 000000000..0b8b38a3b --- /dev/null +++ b/plugins/obs-filters/sharpness-filter.c @@ -0,0 +1,126 @@ +#include +#include +#include +#include + +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 +}; -- GitLab