Browse Source

obs-filters: Improve "Color Correction" filter

Replaces the "Color Correction" filter with a newer version that uses a
matrix, adds hue and saturation, and improves the contrast option.

Closes jp9000/obs-studio#708
Cephas Reis 9 years ago
parent
commit
d4cd14b05c

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

@@ -20,7 +20,7 @@ include_directories(${LIBSPEEXDSP_INCLUDE_DIRS}
 
 set(obs-filters_SOURCES
 	obs-filters.c
-	color-filter.c
+	color-correction-filter.c
 	async-delay-filter.c
 	crop-filter.c
 	scale-filter.c

+ 372 - 0
plugins/obs-filters/color-correction-filter.c

@@ -0,0 +1,372 @@
+/*****************************************************************************
+Copyright (C) 2016 by c3r1c3 <[email protected]>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+#include <obs-module.h>
+#include <graphics/matrix4.h>
+#include <graphics/quat.h>
+
+
+#define SETTING_GAMMA                  "gamma"
+#define SETTING_CONTRAST               "contrast"
+#define SETTING_BRIGHTNESS             "brightness"
+#define SETTING_SATURATION             "saturation"
+#define SETTING_HUESHIFT               "hue_shift"
+#define SETTING_OPACITY                "opacity"
+
+#define TEXT_GAMMA                     obs_module_text("Gamma")
+#define TEXT_CONTRAST                  obs_module_text("Contrast")
+#define TEXT_BRIGHTNESS                obs_module_text("Brightness")
+#define TEXT_SATURATION                obs_module_text("Saturation")
+#define TEXT_HUESHIFT                  obs_module_text("HueShift")
+#define TEXT_OPACITY                   obs_module_text("Opacity")
+
+struct color_correction_filter_data {
+	obs_source_t                   *context;
+
+	gs_effect_t                    *effect;
+
+	gs_eparam_t                    *gamma_param;
+	gs_eparam_t                    *final_matrix_param;
+
+	struct vec3                     gamma;
+	float                           contrast;
+	float                           brightness;
+	float                           saturation;
+	float                           hue_shift;
+	float                           opacity;
+
+	/* Pre-Computes */
+	struct matrix4                  con_matrix;
+	struct matrix4                  bright_matrix;
+	struct matrix4                  sat_matrix;
+	struct matrix4                  hue_op_matrix;
+	struct matrix4                  final_matrix;
+
+	struct vec3                     rot_quaternion;
+	float                           rot_quaternion_w;
+	struct vec3                     cross;
+	struct vec3                     square;
+	struct vec3                     wimag;
+	struct vec3                     diag;
+	struct vec3                     a_line;
+	struct vec3                     b_line;
+	struct vec3                     half_unit;
+};
+
+const static float root3 = 0.57735f;
+
+/*
+* As the functions' namesake, this provides the user facing name
+* of your Filter.
+*/
+static const char *color_correction_filter_name(void *unused)
+{
+	UNUSED_PARAMETER(unused);
+	return obs_module_text("ColorFilter");
+}
+
+/*
+* This function is called (see bottom of this file for more details)
+* whenever the OBS filter interface changes. So when the user is messing
+* with a slider this function is called to update the internal settings
+* in OBS, and hence the settings being passed to the CPU/GPU.
+*/
+static void color_correction_filter_update(void *data, obs_data_t *settings)
+{
+	struct color_correction_filter_data *filter = data;
+
+	/* Build our Gamma numbers. */
+	double gamma = obs_data_get_double(settings, SETTING_GAMMA);
+	gamma = (gamma < 0.0) ? (-gamma + 1.0) : (1.0 / (gamma + 1.0));
+	vec3_set(&filter->gamma, (float)gamma, (float)gamma, (float)gamma);
+
+	/* Build our contrast number. */
+	filter->contrast = (float)obs_data_get_double(settings,
+			SETTING_CONTRAST) + 1.0f;
+	float one_minus_con = (1.0f - filter->contrast) / 2.0f;
+
+	/* Now let's build our Contrast matrix. */
+	filter->con_matrix = (struct matrix4)
+	{
+		filter->contrast, 0.0f, 0.0f, 0.0f,
+		0.0f, filter->contrast, 0.0f, 0.0f,
+		0.0f, 0.0f, filter->contrast, 0.0f,
+		one_minus_con, one_minus_con, one_minus_con, 1.0f
+	};
+
+	/* Build our brightness number. */
+	filter->brightness = (float)obs_data_get_double(settings,
+			SETTING_BRIGHTNESS);
+
+	/*
+	 * Now let's build our Brightness matrix.
+	 * Earlier (in the function color_correction_filter_create) we set
+	 * this matrix to the identity matrix, so now we only need
+	 * to set the 3 variables that have changed.
+	 */
+	filter->bright_matrix.t.x = filter->brightness;
+	filter->bright_matrix.t.y = filter->brightness;
+	filter->bright_matrix.t.z = filter->brightness;
+
+	/* Build our Saturation number. */
+	filter->saturation = (float)obs_data_get_double(settings,
+			SETTING_SATURATION) + 1.0f;
+
+	/* Factor in the selected color weights. */
+	float one_minus_sat = (1.0f - filter->saturation) / 3.0f;
+	float sat_val = one_minus_sat + filter->saturation;
+
+	/* Now we build our Saturation matrix. */
+	filter->sat_matrix = (struct matrix4)
+	{
+		sat_val, one_minus_sat, one_minus_sat, 0.0f,
+		one_minus_sat, sat_val, one_minus_sat, 0.0f,
+		one_minus_sat, one_minus_sat, sat_val, 0.0f,
+		0.0f, 0.0f, 0.0f, 1.0f
+	};
+
+	/* Build our Hue number. */
+	filter->hue_shift = (float)obs_data_get_double(settings,
+			SETTING_HUESHIFT);
+
+	/* Build our Transparency number. */
+	filter->opacity = (float)obs_data_get_int(settings,
+			SETTING_OPACITY) * 0.01f;
+
+	/* Hue is the radian of 0 to 360 degrees. */
+	float half_angle = 0.5f * (float)(filter->hue_shift / (180.0f / M_PI));
+
+	/* Pseudo-Quaternion To Matrix. */
+	float rot_quad1 = root3 * (float)sin(half_angle);
+	vec3_set(&filter->rot_quaternion, rot_quad1, rot_quad1,
+			rot_quad1);
+	filter->rot_quaternion_w = (float)cos(half_angle);
+
+	vec3_mul(&filter->cross, &filter->rot_quaternion,
+			&filter->rot_quaternion);
+	vec3_mul(&filter->square, &filter->rot_quaternion,
+			&filter->rot_quaternion);
+	vec3_mulf(&filter->wimag, &filter->rot_quaternion,
+			filter->rot_quaternion_w);
+
+	vec3_mulf(&filter->square, &filter->square, 2.0f);
+	vec3_sub(&filter->diag, &filter->half_unit, &filter->square);
+	vec3_add(&filter->a_line, &filter->cross, &filter->wimag);
+	vec3_sub(&filter->b_line, &filter->cross, &filter->wimag);
+
+	/* Now we build our Hue and Opacity matrix. */
+	filter->hue_op_matrix = (struct matrix4)
+	{
+		filter->diag.x * 2.0f,
+		filter->b_line.z * 2.0f,
+		filter->a_line.y * 2.0f,
+		0.0f,
+
+		filter->a_line.z * 2.0f,
+		filter->diag.y * 2.0f,
+		filter->b_line.x * 2.0f,
+		0.0f,
+
+		filter->b_line.y * 2.0f,
+		filter->a_line.x * 2.0f,
+		filter->diag.z * 2.0f,
+		0.0f,
+
+		0.0f, 0.0f, 0.0f, filter->opacity
+	};
+
+	/* First we apply the Contrast & Brightness matrix. */
+	matrix4_mul(&filter->final_matrix, &filter->bright_matrix,
+			&filter->con_matrix);
+	/* Now we apply the Saturation matrix. */
+	matrix4_mul(&filter->final_matrix, &filter->final_matrix,
+			&filter->sat_matrix);
+	/* Lastly we apply the Hue+Opacity matrix. */
+	matrix4_mul(&filter->final_matrix, &filter->final_matrix,
+			&filter->hue_op_matrix);
+}
+
+/*
+* Since this is C we have to be careful when destroying/removing items from
+* OBS. Jim has added several useful functions to help keep memory leaks to
+* a minimum, and handle the destruction and construction of these filters.
+*/
+static void color_correction_filter_destroy(void *data)
+{
+	struct color_correction_filter_data *filter = data;
+
+	if (filter->effect) {
+		obs_enter_graphics();
+		gs_effect_destroy(filter->effect);
+		obs_leave_graphics();
+	}
+
+	bfree(data);
+}
+
+/*
+* When you apply a filter OBS creates it, and adds it to the source. OBS also
+* starts rendering it immediately. This function doesn't just 'create' the
+* filter, it also calls the render function (farther below) that contains the
+* actual rendering code.
+*/
+static void *color_correction_filter_create(obs_data_t *settings,
+	obs_source_t *context)
+{
+	/*
+	* Because of limitations of pre-c99 compilers, you can't create an
+	* array that doesn't have a know size at compile time. The below
+	* function calculates the size needed and allocates memory to
+	* handle the source.
+	*/
+	struct color_correction_filter_data *filter =
+		bzalloc(sizeof(struct color_correction_filter_data));
+
+	/*
+	 * By default the effect file is stored in the ./data directory that
+	 * your filter resides in.
+	*/
+	char *effect_path = obs_module_file("color_correction_filter.effect");
+
+	filter->context = context;
+
+	/* Set/clear/assign for all necessary vectors. */
+	vec3_set(&filter->half_unit, 0.5f, 0.5f, 0.5f);
+	matrix4_identity(&filter->bright_matrix);
+
+	/* Here we enter the GPU drawing/shader portion of our code. */
+	obs_enter_graphics();
+
+	/* Load the shader on the GPU. */
+	filter->effect = gs_effect_create_from_file(effect_path, NULL);
+
+	/* If the filter is active pass the parameters to the filter. */
+	if (filter->effect) {
+		filter->gamma_param = gs_effect_get_param_by_name(
+				filter->effect, SETTING_GAMMA);
+		filter->final_matrix_param = gs_effect_get_param_by_name(
+				filter->effect, "color_matrix");
+	}
+
+	obs_leave_graphics();
+
+	bfree(effect_path);
+
+	/*
+	 * If the filter has been removed/deactivated, destroy the filter
+	 * and exit out so we don't crash OBS by telling it to update
+	 * values that don't exist anymore.
+	 */
+	if (!filter->effect) {
+		color_correction_filter_destroy(filter);
+		return NULL;
+	}
+
+	/*
+	* It's important to call the update function here. if we don't
+	* we could end up with the user controlled sliders and values
+	* updating, but the visuals not updating to match.
+	*/
+	color_correction_filter_update(filter, settings);
+	return filter;
+}
+
+/* This is where the actual rendering of the filter takes place. */
+static void color_correction_filter_render(void *data, gs_effect_t *effect)
+{
+	struct color_correction_filter_data *filter = data;
+
+	if (!obs_source_process_filter_begin(filter->context, GS_RGBA,
+			OBS_ALLOW_DIRECT_RENDERING))
+		return;
+
+	/* Now pass the interface variables to the .effect file. */
+	gs_effect_set_vec3(filter->gamma_param, &filter->gamma);
+	gs_effect_set_matrix4(filter->final_matrix_param, &filter->final_matrix);
+
+	obs_source_process_filter_end(filter->context, filter->effect, 0, 0);
+
+	UNUSED_PARAMETER(effect);
+}
+
+/*
+* This function sets the interface. the types (add_*_Slider), the type of
+* data collected (int), the internal name, user-facing name, minimum,
+* maximum and step values. While a custom interface can be built, for a
+* simple filter like this it's better to use the supplied functions.
+*/
+static obs_properties_t *color_correction_filter_properties(void *data)
+{
+	obs_properties_t *props = obs_properties_create();
+
+	obs_properties_add_float_slider(props, SETTING_GAMMA,
+			TEXT_GAMMA, -3.0f, 3.0f, 0.01f);
+
+	obs_properties_add_float_slider(props, SETTING_CONTRAST,
+			TEXT_CONTRAST, -2.0f, 2.0f, 0.01f);
+	obs_properties_add_float_slider(props, SETTING_BRIGHTNESS,
+			TEXT_BRIGHTNESS, -1.0f, 1.0f, 0.01f);
+	obs_properties_add_float_slider(props, SETTING_SATURATION,
+			TEXT_SATURATION, -1.0f, 5.0f, 0.01f);
+	obs_properties_add_float_slider(props, SETTING_HUESHIFT,
+			TEXT_HUESHIFT, -180.0f, 180.0f, 0.01f);
+	obs_properties_add_int_slider(props, SETTING_OPACITY,
+			TEXT_OPACITY, 0, 100, 1);
+
+	UNUSED_PARAMETER(data);
+	return props;
+}
+
+/*
+ * As the functions' namesake, this provides the default settings for any
+* options you wish to provide a default for. Try to select defaults that
+* make sense to the end user, or that don't effect the data.
+* *NOTE* this function is completely optional, as is providing a default
+* for any particular setting.
+*/
+static void color_correction_filter_defaults(obs_data_t *settings)
+{
+	obs_data_set_default_double(settings, SETTING_GAMMA, 0.0);
+	obs_data_set_default_double(settings, SETTING_CONTRAST, 0.0);
+	obs_data_set_default_double(settings, SETTING_BRIGHTNESS, 0.0);
+	obs_data_set_default_double(settings,
+			SETTING_SATURATION, 0.0);
+	obs_data_set_default_double(settings, SETTING_HUESHIFT, 0.0);
+	obs_data_set_default_double(settings, SETTING_OPACITY, 100.0);
+}
+
+/*
+* So how does OBS keep track of all these plug-ins/filters? How does OBS know
+* which function to call when it needs to update a setting? Or a source? Or
+* what type of source this is?
+*
+* OBS does it through the obs_source_info_struct. Notice how variables are
+* assigned the name of a function? Notice how the function name has the
+* variable name in it? While not mandatory, it helps a ton for you (and those
+* reading your code) to follow this convention.
+*/
+struct obs_source_info color_filter = {
+	.id = "color_filter",
+	.type = OBS_SOURCE_TYPE_FILTER,
+	.output_flags = OBS_SOURCE_VIDEO,
+	.get_name = color_correction_filter_name,
+	.create = color_correction_filter_create,
+	.destroy = color_correction_filter_destroy,
+	.video_render = color_correction_filter_render,
+	.update = color_correction_filter_update,
+	.get_properties = color_correction_filter_properties,
+	.get_defaults = color_correction_filter_defaults
+};

+ 0 - 174
plugins/obs-filters/color-filter.c

@@ -1,174 +0,0 @@
-#include <obs-module.h>
-#include <graphics/vec4.h>
-
-#define SETTING_COLOR                  "color"
-#define SETTING_OPACITY                "opacity"
-#define SETTING_CONTRAST               "contrast"
-#define SETTING_BRIGHTNESS             "brightness"
-#define SETTING_GAMMA                  "gamma"
-
-#define TEXT_COLOR                     obs_module_text("Color")
-#define TEXT_OPACITY                   obs_module_text("Opacity")
-#define TEXT_CONTRAST                  obs_module_text("Contrast")
-#define TEXT_BRIGHTNESS                obs_module_text("Brightness")
-#define TEXT_GAMMA                     obs_module_text("Gamma")
-
-#define MIN_CONTRAST 0.5f
-#define MAX_CONTRAST 2.0f
-#define MIN_BRIGHTNESS -1.0
-#define MAX_BRIGHTNESS 1.0
-
-struct color_filter_data {
-	obs_source_t                   *context;
-
-	gs_effect_t                    *effect;
-
-	gs_eparam_t                    *color_param;
-	gs_eparam_t                    *contrast_param;
-	gs_eparam_t                    *brightness_param;
-	gs_eparam_t                    *gamma_param;
-
-	struct vec4                    color;
-	float                          contrast;
-	float                          brightness;
-	float                          gamma;
-};
-
-static const char *color_filter_name(void *unused)
-{
-	UNUSED_PARAMETER(unused);
-	return obs_module_text("ColorFilter");
-}
-
-static void color_filter_update(void *data, obs_data_t *settings)
-{
-	struct color_filter_data *filter = data;
-	uint32_t color = (uint32_t)obs_data_get_int(settings, SETTING_COLOR);
-	uint32_t opacity = (uint32_t)obs_data_get_int(settings,
-			SETTING_OPACITY);
-	double contrast = obs_data_get_double(settings, SETTING_CONTRAST);
-	double brightness = obs_data_get_double(settings, SETTING_BRIGHTNESS);
-	double gamma = obs_data_get_double(settings, SETTING_GAMMA);
-
-	color &= 0xFFFFFF;
-	color |= ((opacity * 255) / 100) << 24;
-
-	vec4_from_rgba(&filter->color, color);
-
-	contrast = (contrast < 0.0) ?
-		(1.0 / (-contrast + 1.0)) : (contrast + 1.0);
-
-	brightness *= 0.5;
-
-	gamma = (gamma < 0.0) ? (-gamma + 1.0) : (1.0 / (gamma + 1.0));
-
-	filter->contrast = (float)contrast;
-	filter->brightness = (float)brightness;
-	filter->gamma = (float)gamma;
-}
-
-static void color_filter_destroy(void *data)
-{
-	struct color_filter_data *filter = data;
-
-	if (filter->effect) {
-		obs_enter_graphics();
-		gs_effect_destroy(filter->effect);
-		obs_leave_graphics();
-	}
-
-	bfree(data);
-}
-
-static void *color_filter_create(obs_data_t *settings, obs_source_t *context)
-{
-	struct color_filter_data *filter =
-		bzalloc(sizeof(struct color_filter_data));
-	char *effect_path = obs_module_file("color_filter.effect");
-
-	filter->context = context;
-
-	obs_enter_graphics();
-
-	filter->effect = gs_effect_create_from_file(effect_path, NULL);
-	if (filter->effect) {
-		filter->color_param = gs_effect_get_param_by_name(
-				filter->effect, "color");
-		filter->contrast_param = gs_effect_get_param_by_name(
-				filter->effect, "contrast");
-		filter->brightness_param = gs_effect_get_param_by_name(
-				filter->effect, "brightness");
-		filter->gamma_param = gs_effect_get_param_by_name(
-				filter->effect, "gamma");
-	}
-
-	obs_leave_graphics();
-
-	bfree(effect_path);
-
-	if (!filter->effect) {
-		color_filter_destroy(filter);
-		return NULL;
-	}
-
-	color_filter_update(filter, settings);
-	return filter;
-}
-
-static void color_filter_render(void *data, gs_effect_t *effect)
-{
-	struct color_filter_data *filter = data;
-
-	if (!obs_source_process_filter_begin(filter->context, GS_RGBA,
-				OBS_ALLOW_DIRECT_RENDERING))
-		return;
-
-	gs_effect_set_vec4(filter->color_param, &filter->color);
-	gs_effect_set_float(filter->contrast_param, filter->contrast);
-	gs_effect_set_float(filter->brightness_param, filter->brightness);
-	gs_effect_set_float(filter->gamma_param, filter->gamma);
-
-	obs_source_process_filter_end(filter->context, filter->effect, 0, 0);
-
-	UNUSED_PARAMETER(effect);
-}
-
-static obs_properties_t *color_filter_properties(void *data)
-{
-	obs_properties_t *props = obs_properties_create();
-
-	obs_properties_add_color(props, SETTING_COLOR, TEXT_COLOR);
-	obs_properties_add_int(props, SETTING_OPACITY, TEXT_OPACITY,
-			0, 100, 1);
-	obs_properties_add_float_slider(props, SETTING_CONTRAST,
-			TEXT_CONTRAST, -1.0, 1.0, 0.01);
-	obs_properties_add_float_slider(props, SETTING_BRIGHTNESS,
-			TEXT_BRIGHTNESS, -1.0, 1.0, 0.01);
-	obs_properties_add_float_slider(props, SETTING_GAMMA,
-			TEXT_GAMMA, -1.0, 1.0, 0.01);
-
-	UNUSED_PARAMETER(data);
-	return props;
-}
-
-static void color_filter_defaults(obs_data_t *settings)
-{
-	obs_data_set_default_int(settings, SETTING_COLOR, 0xFFFFFF);
-	obs_data_set_default_int(settings, SETTING_OPACITY, 100);
-	obs_data_set_default_double(settings, SETTING_CONTRAST, 0.0);
-	obs_data_set_default_double(settings, SETTING_BRIGHTNESS, 0.0);
-	obs_data_set_default_double(settings, SETTING_GAMMA, 0.0);
-}
-
-struct obs_source_info color_filter = {
-	.id                            = "color_filter",
-	.type                          = OBS_SOURCE_TYPE_FILTER,
-	.output_flags                  = OBS_SOURCE_VIDEO,
-	.get_name                      = color_filter_name,
-	.create                        = color_filter_create,
-	.destroy                       = color_filter_destroy,
-	.video_render                  = color_filter_render,
-	.update                        = color_filter_update,
-	.get_properties                = color_filter_properties,
-	.get_defaults                  = color_filter_defaults
-};

+ 78 - 0
plugins/obs-filters/data/color_correction_filter.effect

@@ -0,0 +1,78 @@
+/*****************************************************************************
+Copyright (C) 2016 by c3r1c3 <[email protected]>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+uniform float4x4 ViewProj;
+uniform texture2d image;
+
+uniform float3 gamma;
+
+/* Pre-Compute variables. */
+uniform float4x4 color_matrix;
+
+
+sampler_state textureSampler {
+	Filter   = Linear;
+	AddressU = Clamp;
+	AddressV = Clamp;
+};
+
+struct VertData {
+	float4 pos : POSITION;
+	float2 uv : TEXCOORD0;
+};
+
+struct CurrentPixel {
+	float4 current_pixel;
+};
+
+VertData VSDefault(VertData vert_in)
+{
+	VertData vert_out;
+	vert_out.pos = mul(float4(vert_in.pos.xyz, 1.0), ViewProj);
+	vert_out.uv = vert_in.uv;
+	return vert_out;
+}
+
+float4 PSColorFilterRGBA(VertData vert_in) : TARGET
+{
+	/* Realize the struct. */
+	CurrentPixel pixel = (CurrentPixel) 0;
+
+	/* Grab the current pixel to perform operations on. */
+	pixel.current_pixel = image.Sample(textureSampler, vert_in.uv);
+
+	/* Always address the gamma first. */
+	pixel.current_pixel.rgb = pow(pixel.current_pixel.rgb, gamma);
+
+	/* Much easier to manipulate pixels for these types of operations
+	 * when in a matrix such as the below. See
+	 * http://www.graficaobscura.com/matrix/index.html and
+	 * https://docs.rainmeter.net/tips/colormatrix-guide/for more info.
+	 */
+	pixel.current_pixel = mul(color_matrix, pixel.current_pixel);
+
+	return pixel.current_pixel;
+}
+
+technique Draw
+{
+	pass
+	{
+		vertex_shader = VSDefault(vert_in);
+		pixel_shader = PSColorFilterRGBA(vert_in);
+	}
+}

+ 0 - 46
plugins/obs-filters/data/color_filter.effect

@@ -1,46 +0,0 @@
-uniform float4x4 ViewProj;
-uniform texture2d image;
-
-uniform float4 color;
-uniform float contrast;
-uniform float brightness;
-uniform float gamma;
-
-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 CalcColor(float4 rgba)
-{
-	return float4(pow(rgba.rgb, float3(gamma, gamma, gamma)) * contrast + brightness, rgba.a);
-}
-
-float4 PSColorFilterRGBA(VertData v_in) : TARGET
-{
-	float4 rgba = image.Sample(textureSampler, v_in.uv) * color;
-	return CalcColor(rgba);
-}
-
-technique Draw
-{
-	pass
-	{
-		vertex_shader = VSDefault(v_in);
-		pixel_shader  = PSColorFilterRGBA(v_in);
-	}
-}

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

@@ -61,3 +61,5 @@ ScaleFiltering.Bilinear="Bilinear"
 ScaleFiltering.Bicubic="Bicubic"
 ScaleFiltering.Lanczos="Lanczos"
 NoiseSuppress.SuppressLevel="Suppression Level (dB)"
+Saturation="Saturation"
+HueShift="Hue Shift"