Browse Source

libobs: Add low resolution bilinear scale effect

This effect preserves detail of images that are scaled below half size
by using sampling 9 pixels.
jp9000 10 years ago
parent
commit
65517ea4cf
4 changed files with 100 additions and 0 deletions
  1. 84 0
      libobs/data/bilinear_lowres_scale.effect
  2. 1 0
      libobs/obs-internal.h
  3. 12 0
      libobs/obs.c
  4. 3 0
      libobs/obs.h

+ 84 - 0
libobs/data/bilinear_lowres_scale.effect

@@ -0,0 +1,84 @@
+/*
+ * bilinear low res scaling, samples 9 pixels of a larger image to scale to a
+ * low resolution image below half size
+ */
+
+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 float2 base_dimension_i;
+
+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 pixel(float2 uv)
+{
+	return image.Sample(textureSampler, uv);
+}
+
+float4 DrawLowresBilinear(VertData v_in)
+{
+	float2 stepxy = base_dimension_i;
+	float4 output;
+
+	output  = pixel(v_in.uv);
+	output += pixel(v_in.uv + float2(-stepxy.x, -stepxy.y));
+	output += pixel(v_in.uv + float2(-stepxy.x,       0.0));
+	output += pixel(v_in.uv + float2(-stepxy.x,  stepxy.y));
+	output += pixel(v_in.uv + float2(      0.0, -stepxy.y));
+	output += pixel(v_in.uv + float2(      0.0,  stepxy.y));
+	output += pixel(v_in.uv + float2( stepxy.x, -stepxy.y));
+	output += pixel(v_in.uv + float2( stepxy.x,       0.0));
+	output += pixel(v_in.uv + float2( stepxy.x,  stepxy.y));
+	return output / float4(9.0, 9.0, 9.0, 9.0);
+}
+
+float4 PSDrawLowresBilinearRGBA(VertData v_in) : TARGET
+{
+	return DrawLowresBilinear(v_in);
+}
+
+float4 PSDrawLowresBilinearMatrix(VertData v_in) : TARGET
+{
+	float4 yuv = DrawLowresBilinear(v_in);
+
+	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(v_in);
+		pixel_shader  = PSDrawLowresBilinearRGBA(v_in);
+	}
+}
+
+technique DrawMatrix
+{
+	pass
+	{
+		vertex_shader = VSDefault(v_in);
+		pixel_shader  = PSDrawLowresBilinearMatrix(v_in);
+	}
+}
+

+ 1 - 0
libobs/obs-internal.h

@@ -154,6 +154,7 @@ struct obs_core_video {
 	gs_effect_t                     *conversion_effect;
 	gs_effect_t                     *bicubic_effect;
 	gs_effect_t                     *lanczos_effect;
+	gs_effect_t                     *bilinear_lowres_effect;
 	gs_stagesurf_t                  *mapped_surface;
 	int                             cur_texture;
 

+ 12 - 0
libobs/obs.c

@@ -254,6 +254,11 @@ static int obs_init_graphics(struct obs_video_info *ovi)
 			NULL);
 	bfree(filename);
 
+	filename = find_libobs_data_file("bilinear_lowres_scale.effect");
+	video->bilinear_lowres_effect = gs_effect_create_from_file(filename,
+			NULL);
+	bfree(filename);
+
 	if (!video->default_effect)
 		success = false;
 	if (gs_get_device_type() == GS_DEVICE_OPENGL) {
@@ -423,6 +428,7 @@ static void obs_free_graphics(void)
 		gs_effect_destroy(video->conversion_effect);
 		gs_effect_destroy(video->bicubic_effect);
 		gs_effect_destroy(video->lanczos_effect);
+		gs_effect_destroy(video->bilinear_lowres_effect);
 		video->default_effect = NULL;
 
 		gs_leave_context();
@@ -1197,6 +1203,12 @@ gs_effect_t *obs_get_lanczos_effect(void)
 	return obs->video.lanczos_effect;
 }
 
+gs_effect_t *obs_get_bilinear_lowres_effect(void)
+{
+	if (!obs) return NULL;
+	return obs->video.bilinear_lowres_effect;
+}
+
 signal_handler_t *obs_get_signal_handler(void)
 {
 	if (!obs) return NULL;

+ 3 - 0
libobs/obs.h

@@ -509,6 +509,9 @@ EXPORT gs_effect_t *obs_get_bicubic_effect(void);
 /** Returns the lanczos scaling effect */
 EXPORT gs_effect_t *obs_get_lanczos_effect(void);
 
+/** Returns the bilinear lowres scaling effect */
+EXPORT gs_effect_t *obs_get_bilinear_lowres_effect(void);
+
 /** Returns the primary obs signal handler */
 EXPORT signal_handler_t *obs_get_signal_handler(void);