From 03a4984a2d55bd88eef182beee31675f7495a1ae Mon Sep 17 00:00:00 2001 From: Chris Dailey Date: Tue, 26 Nov 2024 09:58:00 -0500 Subject: [PATCH] adds option to point clamp, uses texture's alpha channel --- data/locale/en-US.ini | 2 ++ data/sliced.hlsl | 26 +++++++++++++++++++------- src/filter-9slice.c | 40 ++++++++++++++++++++++++++++++++-------- 3 files changed, 53 insertions(+), 15 deletions(-) diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index 5299cd6..65e1a57 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -7,6 +7,8 @@ NineSlice="9-Slicing" NineSlice.Description="9-sliced Image filter" NineSlice.Name="9-Slice" NineSlice.ShowUVs="[Debug] Show UVs" +NineSlice.UniformScale="Uniform Scale" +NineSlice.LinearFiltering="Use Linear Texture Filtering" NineSlice.ScaleX="Output Scale X" NineSlice.ScaleY="Output Scale Y" NineSlice.Top="Top (Px.)" diff --git a/data/sliced.hlsl b/data/sliced.hlsl index 76b0acc..7350ec7 100644 --- a/data/sliced.hlsl +++ b/data/sliced.hlsl @@ -11,18 +11,28 @@ uniform bool show_uvs; uniform float4 border; uniform float2 output_size; uniform float2 source_size; +uniform bool use_linear_filtering; uniform bool debug; // General constants #define UVLow 0.0 #define UVHigh 1.0 +// Interpolation method and wrap mode for sampling a texture +SamplerState point_clamp +{ + Filter = Point; // Anisotropy / Point / Linear + AddressU = Clamp; // Wrap / Clamp / Mirror / border / MirrorOnce + AddressV = Clamp; // Wrap / Clamp / Mirror / border / MirrorOnce + borderColor = 00000000; // Used only with border edges (optional) +}; + // Interpolation method and wrap mode for sampling a texture SamplerState linear_clamp { - Filter = Linear; // Anisotropy / Point / Linear - AddressU = Clamp; // Wrap / Clamp / Mirror / border / MirrorOnce - AddressV = Clamp; // Wrap / Clamp / Mirror / border / MirrorOnce + Filter = Linear; // Anisotropy / Point / Linear + AddressU = Clamp; // Wrap / Clamp / Mirror / border / MirrorOnce + AddressV = Clamp; // Wrap / Clamp / Mirror / border / MirrorOnce borderColor = 00000000; // Used only with border edges (optional) }; @@ -93,12 +103,14 @@ float4 PS9Slice(pixel_data pixel) : TARGET ); // sample the texture or show UVs - float3 color = show_uvs - ? float3(uv, 0.0) - : image.Sample(linear_clamp, uv); + float4 color = show_uvs + ? float4(uv, 0.0, 1.0) + : use_linear_filtering + ? image.Sample(linear_clamp, uv) + : image.Sample(point_clamp, uv); // and return the color - return float4(color, 1.0); + return color; } technique Draw diff --git a/src/filter-9slice.c b/src/filter-9slice.c index 9dfc747..278241d 100644 --- a/src/filter-9slice.c +++ b/src/filter-9slice.c @@ -45,11 +45,14 @@ struct filter_9slice { struct vec2 output_pixel_scale; struct vec2 last_source_size; bool show_uvs; + bool uniform_scale; + bool use_linear_filtering; struct filter_9slice_params_t { gs_eparam_t *border; gs_eparam_t *output_size; gs_eparam_t *source_size; gs_eparam_t *show_uvs; + gs_eparam_t *use_linear_filtering; } params; }; @@ -97,6 +100,7 @@ static bool filter_reload_effect(void *data) params->border = NULL; params->output_size = NULL; params->source_size = NULL; + params->use_linear_filtering = NULL; params->show_uvs = NULL; if (!context->effect) { @@ -107,12 +111,17 @@ static bool filter_reload_effect(void *data) params->show_uvs = gs_effect_get_param_by_name(effect, "show_uvs"); + params->use_linear_filtering = + gs_effect_get_param_by_name(effect, "use_linear_filtering"); params->border = gs_effect_get_param_by_name(effect, "border"); params->output_size = gs_effect_get_param_by_name(effect, "output_size"); params->source_size = gs_effect_get_param_by_name(effect, "source_size"); + if (params->use_linear_filtering == NULL) { + warn("Failed to get use_linear_filtering param."); + } if (params->show_uvs == NULL) { warn("Failed to get show_uvs param."); } @@ -161,6 +170,8 @@ static void filter_render(void *data, gs_effect_t *effect) gs_effect_set_vec2(params->source_size, &context->last_source_size); gs_effect_set_vec2(params->output_size, &output_size); gs_effect_set_bool(params->show_uvs, context->show_uvs); + gs_effect_set_bool(params->use_linear_filtering, + context->use_linear_filtering); obs_source_process_filter_end(context->source, context->effect, width, height); @@ -171,6 +182,9 @@ static void filter_update(void *data, obs_data_t *settings) struct filter_9slice *context = data; const bool show_uvs = obs_data_get_bool(settings, "show_uvs"); + const bool uniform_scale = obs_data_get_bool(settings, "uniform_scale"); + const bool use_linear_filtering = + obs_data_get_bool(settings, "use_linear_filtering"); const double output_scale_x = obs_data_get_double(settings, "output_scale_x"); @@ -185,9 +199,15 @@ static void filter_update(void *data, obs_data_t *settings) obs_data_get_double(settings, "border_right"); context->show_uvs = show_uvs; + context->uniform_scale = uniform_scale; + context->use_linear_filtering = use_linear_filtering; context->output_pixel_scale.x = (float)output_scale_x; - context->output_pixel_scale.y = (float)output_scale_y; + context->output_pixel_scale.y = uniform_scale ? (float) output_scale_x : (float)output_scale_y; + + if (uniform_scale) { + obs_data_set_double(settings, "output_scale_y", output_scale_x); + } context->border.x = (float)border_top; context->border.y = (float)border_left; @@ -221,6 +241,8 @@ static void filter_get_defaults(obs_data_t *settings) const double BorderDefault = 8.0; obs_data_set_default_bool(settings, "show_uvs", false); + obs_data_set_default_bool(settings, "uniform_scale", true); + obs_data_set_default_bool(settings, "use_linear_filtering", false); obs_data_set_default_double(settings, "output_scale_x", ScaleDefault); obs_data_set_default_double(settings, "output_scale_y", ScaleDefault); @@ -246,25 +268,27 @@ static obs_properties_t *filter_get_properties(void *data) // limit the border sizes to half of the source size const double SliceWidthMax = - context == NULL - ? ScaleMin - : floor((context->last_source_size.x / 2.0) - 0.5); + context == NULL ? ScaleMin : context->last_source_size.x - 1.0; const double SliceHeightMax = - context == NULL - ? ScaleMin - : floor((context->last_source_size.y / 2.0) - 0.5); + context == NULL ? ScaleMin : context->last_source_size.y - 1.0; // debug options obs_properties_add_bool(props, "show_uvs", obs_module_text("NineSlice.ShowUVs")); + obs_properties_add_bool(props, "uniform_scale", + obs_module_text("NineSlice.UniformScale")); + + obs_properties_add_bool(props, "use_linear_filtering", + obs_module_text("NineSlice.LinearFiltering")); + // output scale x/y obs_properties_add_float_slider(props, "output_scale_x", obs_module_text("NineSlice.ScaleX"), ScaleMin, ScaleMax, ScaleStep); obs_properties_add_float_slider(props, "output_scale_y", - obs_module_text("NineSlice.Scaley"), + obs_module_text("NineSlice.ScaleY"), ScaleMin, ScaleMax, ScaleStep); // border sizes