diff options
author | 2017-12-26 22:27:48 -0800 | |
---|---|---|
committer | 2017-12-30 00:29:47 -0800 | |
commit | 222b41d58254acdfa0f8441c37b7ec43289b7b25 (patch) | |
tree | cc76812c25cf744f97341c9766fd997d59f9f012 /src/osd/modules/opengl | |
parent | 6c456a286507d4d0ba1acb4b9015f9933e2351a4 (diff) |
Add Bicubic Shader to OpenGL Backend
This shader uses the equation described by R. Keys in the paper 'Cubic Convolution Interpolation for Digital Image Processing' which is, in this case, the same as a Catmull-Rom spline. This produces a sharper upscaled image than bilinear filtering.
The new shader is selected by setting gl_glsl_filter to 2. Consequently, gl_glsl_filter is now treated as an int rather than a boolean.
Also fixed a variable name problem in the code guarded by GLSL_SOURCE_ON_DISK.
Diffstat (limited to 'src/osd/modules/opengl')
-rw-r--r-- | src/osd/modules/opengl/gl_shader_mgr.cpp | 17 | ||||
-rw-r--r-- | src/osd/modules/opengl/gl_shader_mgr.h | 1 | ||||
-rwxr-xr-x[-rw-r--r--] | src/osd/modules/opengl/shader/genc.sh | 4 | ||||
-rw-r--r-- | src/osd/modules/opengl/shader/glsl_bicubic_rgb32_dir.fsh | 81 | ||||
-rw-r--r-- | src/osd/modules/opengl/shader/glsl_bicubic_rgb32_dir.fsh.c | 82 |
5 files changed, 179 insertions, 6 deletions
diff --git a/src/osd/modules/opengl/gl_shader_mgr.cpp b/src/osd/modules/opengl/gl_shader_mgr.cpp index 9f8dc8acd05..26eb0d35ee0 100644 --- a/src/osd/modules/opengl/gl_shader_mgr.cpp +++ b/src/osd/modules/opengl/gl_shader_mgr.cpp @@ -23,7 +23,8 @@ static const char * glsl_mamebm_vsh_files [GLSL_VERTEX_SHADER_INT_NUMBER] = static const char * glsl_mamebm_fsh_files [GLSL_SHADER_FEAT_INT_NUMBER] = { "/tmp/glsl_plain_rgb32_dir.fsh", // rgb32 dir plain - "/tmp/glsl_bilinear_rgb32_dir.fsh" // rgb32 dir bilinear + "/tmp/glsl_bilinear_rgb32_dir.fsh", // rgb32 dir bilinear + "/tmp/glsl_bicubic_rgb32_dir.fsh", // rgb32 dir bicubic }; #else // GLSL_SOURCE_ON_DISK @@ -32,6 +33,7 @@ static const char * glsl_mamebm_fsh_files [GLSL_SHADER_FEAT_INT_NUMBER] = #include "shader/glsl_plain_rgb32_dir.fsh.c" #include "shader/glsl_bilinear_rgb32_dir.fsh.c" +#include "shader/glsl_bicubic_rgb32_dir.fsh.c" static const char * glsl_mamebm_vsh_sources [GLSL_VERTEX_SHADER_INT_NUMBER] = { @@ -40,8 +42,9 @@ static const char * glsl_mamebm_vsh_sources [GLSL_VERTEX_SHADER_INT_NUMBER] = static const char * glsl_mamebm_fsh_sources [GLSL_SHADER_FEAT_INT_NUMBER] = { - glsl_plain_rgb32_dir_fsh_src, // rgb32 dir plain - glsl_bilinear_rgb32_dir_fsh_src // rgb32 dir bilinear + glsl_plain_rgb32_dir_fsh_src, // rgb32 dir plain + glsl_bilinear_rgb32_dir_fsh_src, // rgb32 dir bilinear + glsl_bicubic_rgb32_dir_fsh_src, // rgb32 dir bicubic }; #endif // GLSL_SOURCE_ON_DISK @@ -50,12 +53,13 @@ static const char * glsl_mamebm_filter_names [GLSL_SHADER_FEAT_MAX_NUMBER] = { "plain", "bilinear", + "bicubic", "custom" }; static GLhandleARB glsl_mamebm_programs [GLSL_SHADER_FEAT_MAX_NUMBER+9] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* rgb32 dir: plain, bilinear, custom0-9, .. */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* rgb32 dir: plain, bilinear, bicubic, custom0-9, .. */ }; /** @@ -65,6 +69,7 @@ static int glsl_mamebm_fsh2vsh[GLSL_SHADER_FEAT_MAX_NUMBER] = { 0, // plain -> general 0, // bilinear -> general + 0, // bicubic -> general 1, // custom -> custom }; @@ -75,7 +80,7 @@ static GLhandleARB glsl_mamebm_vsh_shader[GLSL_VERTEX_SHADER_MAX_NUMBER+9] = static GLhandleARB glsl_mamebm_fsh_shader [GLSL_SHADER_FEAT_MAX_NUMBER+9] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* rgb32 dir: plain, bilinear, custom0-9 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* rgb32 dir: plain, bilinear, bicubic, custom0-9 */ }; static GLhandleARB glsl_scrn_programs [10] = @@ -145,7 +150,7 @@ glsl_shader_info *glsl_shader_init(osd_gl_context *gl_ctx) if(glsl_mamebm_fsh_files[j]) err = gl_compile_shader_files (&glsl_mamebm_programs[j], &glsl_mamebm_vsh_shader[glsl_mamebm_fsh2vsh[j]], - &glsl_mamebmfsh_shader[j], + &glsl_mamebm_fsh_shader[j], nullptr /*precompiled*/, glsl_mamebm_fsh_files[j], 0); #else if(glsl_mamebm_fsh_sources[j]) diff --git a/src/osd/modules/opengl/gl_shader_mgr.h b/src/osd/modules/opengl/gl_shader_mgr.h index b232243f636..f95ec8c2244 100644 --- a/src/osd/modules/opengl/gl_shader_mgr.h +++ b/src/osd/modules/opengl/gl_shader_mgr.h @@ -11,6 +11,7 @@ enum GLSL_SHADER_FEATURE { GLSL_SHADER_FEAT_PLAIN, GLSL_SHADER_FEAT_BILINEAR, + GLSL_SHADER_FEAT_BICUBIC, GLSL_SHADER_FEAT_INT_NUMBER, GLSL_SHADER_FEAT_CUSTOM = GLSL_SHADER_FEAT_INT_NUMBER, GLSL_SHADER_FEAT_MAX_NUMBER diff --git a/src/osd/modules/opengl/shader/genc.sh b/src/osd/modules/opengl/shader/genc.sh index 2c676e62f9b..339babedc0b 100644..100755 --- a/src/osd/modules/opengl/shader/genc.sh +++ b/src/osd/modules/opengl/shader/genc.sh @@ -44,3 +44,7 @@ echo "const char glsl_bilinear_rgb32_dir_fsh_src[] =" > glsl_bilinear_rgb32_dir. sed -e 's/^/"/g' -e 's/$/\\n"/g' glsl_bilinear_rgb32_dir.fsh >> glsl_bilinear_rgb32_dir.fsh.c echo ";" >> glsl_bilinear_rgb32_dir.fsh.c +echo "const char glsl_bicubic_rgb32_dir_fsh_src[] =" > glsl_bicubic_rgb32_dir.fsh.c +sed -e 's/^/"/g' -e 's/$/\\n"/g' glsl_bicubic_rgb32_dir.fsh >> glsl_bicubic_rgb32_dir.fsh.c +echo ";" >> glsl_bicubic_rgb32_dir.fsh.c + diff --git a/src/osd/modules/opengl/shader/glsl_bicubic_rgb32_dir.fsh b/src/osd/modules/opengl/shader/glsl_bicubic_rgb32_dir.fsh new file mode 100644 index 00000000000..1617bd13a1d --- /dev/null +++ b/src/osd/modules/opengl/shader/glsl_bicubic_rgb32_dir.fsh @@ -0,0 +1,81 @@ +// license:BSD-3-Clause +// copyright-holders:Aaron Stover +#pragma optimize (on) +#pragma debug (off) + +uniform sampler2D color_texture; +uniform vec2 color_texture_pow2_sz; // pow2 tex size +uniform vec4 vid_attributes; // gamma, contrast, brightness + +#define TEX2D(v) texture2D(color_texture,(v)) + +void main() +{ + vec2 pixel = gl_TexCoord[0].st * color_texture_pow2_sz - 0.5; + vec2 uv_ratio = fract(pixel); + vec2 one = 1.0 / color_texture_pow2_sz; + vec2 xy = (floor(pixel) + 0.5) * one; + + // + // Robert G. Keys' + // + // 'Cubic Convolution Interpolation for Digital Image Processing' + // IEEE TRANSACTIONS ON ACOUSTICS, SPEECH, AND SIGNAL PROCESSING, + // VOL. ASSP-29, NO. 6, DECEMBER 1981 + // + // gives the following equation: + // + // g(x) = c_k-1(-s^3 + 2s^2 - s)/2 + // + c_k(3s^3 - 5s^2 + 2)/2 + // + c_k+1(-3s^3 + 4s^2 + s)/2 + // + c_k+2(s^3 - s^2)/2 + // + // c_* are the sample values, s is our uv_ratio. + // + // Weight equations are taken from above. + // + vec2 s = uv_ratio; + vec2 s2 = uv_ratio*uv_ratio; + vec2 s3 = uv_ratio*uv_ratio*uv_ratio; + vec2 w0 = 0.5 * (-s3 + 2.0*s2 - s); + vec2 w1 = 0.5 * (3.0*s3 - 5.0*s2 + 2.0); + vec2 w2 = 0.5 * (-3.0*s3 + 4.0*s2 + s); + vec2 w3 = 0.5 * (s3 - s2); + + // Compute the coordinates to sample from + vec2 pos0 = xy - 1.0*one.xy; + vec2 pos1 = xy; + vec2 pos2 = xy + 1.0*one.xy; + vec2 pos3 = xy + 2.0*one.xy; + + // Finally - take the samples, multiply by weight, and sum + vec4 col = 0.0; + col += TEX2D(vec2(pos0.x, pos0.y)) * w0.x * w0.y; + col += TEX2D(vec2(pos1.x, pos0.y)) * w1.x * w0.y; + col += TEX2D(vec2(pos2.x, pos0.y)) * w2.x * w0.y; + col += TEX2D(vec2(pos3.x, pos0.y)) * w3.x * w0.y; + + col += TEX2D(vec2(pos0.x, pos1.y)) * w0.x * w1.y; + col += TEX2D(vec2(pos1.x, pos1.y)) * w1.x * w1.y; + col += TEX2D(vec2(pos2.x, pos1.y)) * w2.x * w1.y; + col += TEX2D(vec2(pos3.x, pos1.y)) * w3.x * w1.y; + + col += TEX2D(vec2(pos0.x, pos2.y)) * w0.x * w2.y; + col += TEX2D(vec2(pos1.x, pos2.y)) * w1.x * w2.y; + col += TEX2D(vec2(pos2.x, pos2.y)) * w2.x * w2.y; + col += TEX2D(vec2(pos3.x, pos2.y)) * w3.x * w2.y; + + col += TEX2D(vec2(pos0.x, pos3.y)) * w0.x * w3.y; + col += TEX2D(vec2(pos1.x, pos3.y)) * w1.x * w3.y; + col += TEX2D(vec2(pos2.x, pos3.y)) * w2.x * w3.y; + col += TEX2D(vec2(pos3.x, pos3.y)) * w3.x * w3.y; + +#ifdef DO_GAMMA + // gamma/contrast/brightness + vec4 gamma = vec4(1.0 / vid_attributes.r, 1.0 / vid_attributes.r, 1.0 / vid_attributes.r, 0.0); + gl_FragColor = ( pow ( col, gamma ) * vid_attributes.g) + vid_attributes.b - 1.0; +#else + // contrast/brightness + gl_FragColor = ( col * vid_attributes.g) + vid_attributes.b - 1.0; +#endif +}
\ No newline at end of file diff --git a/src/osd/modules/opengl/shader/glsl_bicubic_rgb32_dir.fsh.c b/src/osd/modules/opengl/shader/glsl_bicubic_rgb32_dir.fsh.c new file mode 100644 index 00000000000..cd5655438af --- /dev/null +++ b/src/osd/modules/opengl/shader/glsl_bicubic_rgb32_dir.fsh.c @@ -0,0 +1,82 @@ +const char glsl_bicubic_rgb32_dir_fsh_src[] = +"// license:BSD-3-Clause\n" +"// copyright-holders:Aaron Stover\n" +"#pragma optimize (on)\n" +"#pragma debug (off)\n" +"\n" +"uniform sampler2D color_texture;\n" +"uniform vec2 color_texture_pow2_sz; // pow2 tex size\n" +"uniform vec4 vid_attributes; // gamma, contrast, brightness\n" +"\n" +"#define TEX2D(v) texture2D(color_texture,(v))\n" +"\n" +"void main()\n" +"{\n" +" vec2 pixel = gl_TexCoord[0].st * color_texture_pow2_sz - 0.5;\n" +" vec2 uv_ratio = fract(pixel);\n" +" vec2 one = 1.0 / color_texture_pow2_sz;\n" +" vec2 xy = (floor(pixel) + 0.5) * one;\n" +"\n" +" //\n" +" // Robert G. Keys'\n" +" //\n" +" // 'Cubic Convolution Interpolation for Digital Image Processing'\n" +" // IEEE TRANSACTIONS ON ACOUSTICS, SPEECH, AND SIGNAL PROCESSING, \n" +" // VOL. ASSP-29, NO. 6, DECEMBER 1981 \n" +" //\n" +" // gives the following equation:\n" +" //\n" +" // g(x) = c_k-1(-s^3 + 2s^2 - s)/2 \n" +" // + c_k(3s^3 - 5s^2 + 2)/2\n" +" // + c_k+1(-3s^3 + 4s^2 + s)/2 \n" +" // + c_k+2(s^3 - s^2)/2\n" +" //\n" +" // c_* are the sample values, s is our uv_ratio. \n" +" //\n" +" // Weight equations are taken from above.\n" +" //\n" +" vec2 s = uv_ratio;\n" +" vec2 s2 = uv_ratio*uv_ratio;\n" +" vec2 s3 = uv_ratio*uv_ratio*uv_ratio;\n" +" vec2 w0 = 0.5 * (-s3 + 2.0*s2 - s);\n" +" vec2 w1 = 0.5 * (3.0*s3 - 5.0*s2 + 2.0);\n" +" vec2 w2 = 0.5 * (-3.0*s3 + 4.0*s2 + s);\n" +" vec2 w3 = 0.5 * (s3 - s2);\n" +"\n" +" // Compute the coordinates to sample from\n" +" vec2 pos0 = xy - 1.0*one.xy;\n" +" vec2 pos1 = xy;\n" +" vec2 pos2 = xy + 1.0*one.xy;\n" +" vec2 pos3 = xy + 2.0*one.xy;\n" +"\n" +" // Finally - take the samples, multiply by weight, and sum\n" +" vec4 col = 0.0;\n" +" col += TEX2D(vec2(pos0.x, pos0.y)) * w0.x * w0.y;\n" +" col += TEX2D(vec2(pos1.x, pos0.y)) * w1.x * w0.y;\n" +" col += TEX2D(vec2(pos2.x, pos0.y)) * w2.x * w0.y;\n" +" col += TEX2D(vec2(pos3.x, pos0.y)) * w3.x * w0.y;\n" +"\n" +" col += TEX2D(vec2(pos0.x, pos1.y)) * w0.x * w1.y;\n" +" col += TEX2D(vec2(pos1.x, pos1.y)) * w1.x * w1.y;\n" +" col += TEX2D(vec2(pos2.x, pos1.y)) * w2.x * w1.y;\n" +" col += TEX2D(vec2(pos3.x, pos1.y)) * w3.x * w1.y;\n" +" \n" +" col += TEX2D(vec2(pos0.x, pos2.y)) * w0.x * w2.y;\n" +" col += TEX2D(vec2(pos1.x, pos2.y)) * w1.x * w2.y;\n" +" col += TEX2D(vec2(pos2.x, pos2.y)) * w2.x * w2.y;\n" +" col += TEX2D(vec2(pos3.x, pos2.y)) * w3.x * w2.y;\n" +"\n" +" col += TEX2D(vec2(pos0.x, pos3.y)) * w0.x * w3.y;\n" +" col += TEX2D(vec2(pos1.x, pos3.y)) * w1.x * w3.y;\n" +" col += TEX2D(vec2(pos2.x, pos3.y)) * w2.x * w3.y;\n" +" col += TEX2D(vec2(pos3.x, pos3.y)) * w3.x * w3.y;\n" +"\n" +"#ifdef DO_GAMMA\n" +" // gamma/contrast/brightness\n" +" vec4 gamma = vec4(1.0 / vid_attributes.r, 1.0 / vid_attributes.r, 1.0 / vid_attributes.r, 0.0);\n" +" gl_FragColor = ( pow ( col, gamma ) * vid_attributes.g) + vid_attributes.b - 1.0;\n" +"#else\n" +" // contrast/brightness\n" +" gl_FragColor = ( col * vid_attributes.g) + vid_attributes.b - 1.0;\n" +"#endif\n" +"}\n"; |