From 65517ea4cf34cf1fac45912ef4ba53d8c2d74e0b Mon Sep 17 00:00:00 2001 From: jp9000 Date: Mon, 6 Apr 2015 07:09:47 -0700 Subject: [PATCH] libobs: Add low resolution bilinear scale effect This effect preserves detail of images that are scaled below half size by using sampling 9 pixels. --- libobs/data/bilinear_lowres_scale.effect | 84 ++++++++++++++++++++++++ libobs/obs-internal.h | 1 + libobs/obs.c | 12 ++++ libobs/obs.h | 3 + 4 files changed, 100 insertions(+) create mode 100644 libobs/data/bilinear_lowres_scale.effect diff --git a/libobs/data/bilinear_lowres_scale.effect b/libobs/data/bilinear_lowres_scale.effect new file mode 100644 index 000000000..185011a16 --- /dev/null +++ b/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); + } +} + diff --git a/libobs/obs-internal.h b/libobs/obs-internal.h index f4a988675..852d89aec 100644 --- a/libobs/obs-internal.h +++ b/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; diff --git a/libobs/obs.c b/libobs/obs.c index af5afbc2d..cfaf606c9 100644 --- a/libobs/obs.c +++ b/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; diff --git a/libobs/obs.h b/libobs/obs.h index 3a386872b..f8efbb5cf 100644 --- a/libobs/obs.h +++ b/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);