diff --git a/config/ConfigFormUnit.cpp b/config/ConfigFormUnit.cpp
index 7ae9420..3a1564a 100644
--- a/config/ConfigFormUnit.cpp
+++ b/config/ConfigFormUnit.cpp
@@ -787,6 +787,7 @@ void __fastcall TConfigForm::FormCreate(TObject *Sender)
 		ShaderCbx->AddItem("Nearest neighbor", NULL);
 		ShaderCbx->AddItem("Bilinear", NULL);
 		ShaderCbx->AddItem("Bicubic", NULL);
+        ShaderCbx->AddItem("Lanczos", NULL);
 	}
 
 	auto shader = ini->ReadString("ddraw", "shader", "Bicubic");
diff --git a/inc/openglshader.h b/inc/openglshader.h
index fce2c96..94a9d22 100644
--- a/inc/openglshader.h
+++ b/inc/openglshader.h
@@ -250,6 +250,222 @@ const char CATMULL_ROM_FRAG_SHADER_CORE[] =
     "    FragColor = vec4(result * (1. / (wtm + wml + wmm + wmr + wbm)), 1.0);\n"
     "}\n";
 
+/*
+// The following code is licensed under the MIT license:
+// Hyllian's jinc windowed-jinc 2-lobe sharper with anti-ringing Shader
+// Copyright (C) 2011-2016 Hyllian/Jararaca - sergiogdb@gmail.com
+// https://github.com/libretro/glsl-shaders/blob/09e2942efbab2f51b60ff0b93b7761b0b0570910/windowed/shaders/lanczos2-sharp.glsl
+*/
 
+const char LANCZOS2_FRAG_SHADER[] =
+    "#version 130\n"
+    "#define JINC2_WINDOW_SINC 0.5\n"
+    "#define JINC2_SINC 1.0\n"
+    "#define JINC2_AR_STRENGTH 0.8\n"
+    "\n"
+    "out vec4 FragColor;\n"
+    "uniform int FrameDirection;\n"
+    "uniform int FrameCount;\n"
+    "uniform vec2 OutputSize;\n"
+    "uniform vec2 TextureSize;\n"
+    "uniform vec2 InputSize;\n"
+    "uniform sampler2D Texture;\n"
+    "in vec4 TEX0;\n"
+    "\n"
+    "const   float pi                = 3.1415926535897932384626433832795;\n"
+    "const   float wa                = JINC2_WINDOW_SINC*pi;\n"
+    "const   float wb                = JINC2_SINC*pi;\n"
+    "\n"
+    "// Calculates the distance between two points\n"
+    "float d(vec2 pt1, vec2 pt2)\n"
+    "{\n"
+    "  vec2 v = pt2 - pt1;\n"
+    "  return sqrt(dot(v,v));\n"
+    "}\n"
+    "\n"
+    "vec3 min4(vec3 a, vec3 b, vec3 c, vec3 d)\n"
+    "{\n"
+    "    return min(a, min(b, min(c, d)));\n"
+    "}\n"
+    "\n"
+    "vec3 max4(vec3 a, vec3 b, vec3 c, vec3 d)\n"
+    "{\n"
+    "    return max(a, max(b, max(c, d)));\n"
+    "}\n"
+    "\n"
+    "vec4 resampler(vec4 x)\n"
+    "{\n"
+    "   vec4 res;\n"
+    "\n"
+    "   res.x = (x.x==0.0) ?  wa*wb  :  sin(x.x*wa)*sin(x.x*wb)/(x.x*x.x);\n"
+    "   res.y = (x.y==0.0) ?  wa*wb  :  sin(x.y*wa)*sin(x.y*wb)/(x.y*x.y);\n"
+    "   res.z = (x.z==0.0) ?  wa*wb  :  sin(x.z*wa)*sin(x.z*wb)/(x.z*x.z);\n"
+    "   res.w = (x.w==0.0) ?  wa*wb  :  sin(x.w*wa)*sin(x.w*wb)/(x.w*x.w);\n"
+    "\n"
+    "   return res;\n"
+    "}\n"
+    "\n"
+    "void main()\n"
+    "{\n"
+    "    vec3 color;\n"
+    "    vec4 weights[4];\n"
+    "\n"
+    "    vec2 dx = vec2(1.0, 0.0);\n"
+    "    vec2 dy = vec2(0.0, 1.0);\n"
+    "\n"
+    "    vec2 pc = TEX0.xy*TextureSize;\n"
+    "\n"
+    "    vec2 tc = (floor(pc-vec2(0.5,0.5))+vec2(0.5,0.5));\n"
+    "     \n"
+    "    weights[0] = resampler(vec4(d(pc, tc    -dx    -dy), d(pc, tc           -dy), d(pc, tc    +dx    -dy), d(pc, tc+2.0*dx    -dy)));\n"
+    "    weights[1] = resampler(vec4(d(pc, tc    -dx       ), d(pc, tc              ), d(pc, tc    +dx       ), d(pc, tc+2.0*dx       )));\n"
+    "    weights[2] = resampler(vec4(d(pc, tc    -dx    +dy), d(pc, tc           +dy), d(pc, tc    +dx    +dy), d(pc, tc+2.0*dx    +dy)));\n"
+    "    weights[3] = resampler(vec4(d(pc, tc    -dx+2.0*dy), d(pc, tc       +2.0*dy), d(pc, tc    +dx+2.0*dy), d(pc, tc+2.0*dx+2.0*dy)));\n"
+    "\n"
+    "    dx = dx/TextureSize;\n"
+    "    dy = dy/TextureSize;\n"
+    "    tc = tc/TextureSize;\n"
+    "\n"
+    "    vec3 c00 = texture(Texture, tc    -dx    -dy).xyz;\n"
+    "    vec3 c10 = texture(Texture, tc           -dy).xyz;\n"
+    "    vec3 c20 = texture(Texture, tc    +dx    -dy).xyz;\n"
+    "    vec3 c30 = texture(Texture, tc+2.0*dx    -dy).xyz;\n"
+    "    vec3 c01 = texture(Texture, tc    -dx       ).xyz;\n"
+    "    vec3 c11 = texture(Texture, tc              ).xyz;\n"
+    "    vec3 c21 = texture(Texture, tc    +dx       ).xyz;\n"
+    "    vec3 c31 = texture(Texture, tc+2.0*dx       ).xyz;\n"
+    "    vec3 c02 = texture(Texture, tc    -dx    +dy).xyz;\n"
+    "    vec3 c12 = texture(Texture, tc           +dy).xyz;\n"
+    "    vec3 c22 = texture(Texture, tc    +dx    +dy).xyz;\n"
+    "    vec3 c32 = texture(Texture, tc+2.0*dx    +dy).xyz;\n"
+    "    vec3 c03 = texture(Texture, tc    -dx+2.0*dy).xyz;\n"
+    "    vec3 c13 = texture(Texture, tc       +2.0*dy).xyz;\n"
+    "    vec3 c23 = texture(Texture, tc    +dx+2.0*dy).xyz;\n"
+    "    vec3 c33 = texture(Texture, tc+2.0*dx+2.0*dy).xyz;\n"
+    "	\n"
+    "    //  Get min/max samples\n"
+    "    vec3 min_sample = min4(c11, c21, c12, c22);\n"
+    "    vec3 max_sample = max4(c11, c21, c12, c22);\n"
+    "	\n"
+    "    color = vec3(dot(weights[0], vec4(c00.x, c10.x, c20.x, c30.x)), dot(weights[0], vec4(c00.y, c10.y, c20.y, c30.y)), dot(weights[0], vec4(c00.z, c10.z, c20.z, c30.z)));\n"
+    "    color+= vec3(dot(weights[1], vec4(c01.x, c11.x, c21.x, c31.x)), dot(weights[1], vec4(c01.y, c11.y, c21.y, c31.y)), dot(weights[1], vec4(c01.z, c11.z, c21.z, c31.z)));\n"
+    "    color+= vec3(dot(weights[2], vec4(c02.x, c12.x, c22.x, c32.x)), dot(weights[2], vec4(c02.y, c12.y, c22.y, c32.y)), dot(weights[2], vec4(c02.z, c12.z, c22.z, c32.z)));\n"
+    "    color+= vec3(dot(weights[3], vec4(c03.x, c13.x, c23.x, c33.x)), dot(weights[3], vec4(c03.y, c13.y, c23.y, c33.y)), dot(weights[3], vec4(c03.z, c13.z, c23.z, c33.z)));\n"
+    "    color = color/(dot(weights[0], vec4(1,1,1,1)) + dot(weights[1], vec4(1,1,1,1)) + dot(weights[2], vec4(1,1,1,1)) + dot(weights[3], vec4(1,1,1,1)));\n"
+    "\n"
+    "    // Anti-ringing\n"
+    "    vec3 aux = color;\n"
+    "    color = clamp(color, min_sample, max_sample);\n"
+    "    color = mix(aux, color, JINC2_AR_STRENGTH);\n"
+    "\n"
+    "    // final sum and weight normalization\n"
+    "    FragColor.xyz = color;\n"
+    "}\n";
+
+
+const char LANCZOS2_FRAG_SHADER_CORE[] =
+    "#version 150\n"
+    "#define JINC2_WINDOW_SINC 0.5\n"
+    "#define JINC2_SINC 1.0\n"
+    "#define JINC2_AR_STRENGTH 0.8\n"
+    "\n"
+    "out vec4 FragColor;\n"
+    "uniform int FrameDirection;\n"
+    "uniform int FrameCount;\n"
+    "uniform vec2 OutputSize;\n"
+    "uniform vec2 TextureSize;\n"
+    "uniform vec2 InputSize;\n"
+    "uniform sampler2D Texture;\n"
+    "in vec4 TEX0;\n"
+    "\n"
+    "const   float pi                = 3.1415926535897932384626433832795;\n"
+    "const   float wa                = JINC2_WINDOW_SINC*pi;\n"
+    "const   float wb                = JINC2_SINC*pi;\n"
+    "\n"
+    "// Calculates the distance between two points\n"
+    "float d(vec2 pt1, vec2 pt2)\n"
+    "{\n"
+    "  vec2 v = pt2 - pt1;\n"
+    "  return sqrt(dot(v,v));\n"
+    "}\n"
+    "\n"
+    "vec3 min4(vec3 a, vec3 b, vec3 c, vec3 d)\n"
+    "{\n"
+    "    return min(a, min(b, min(c, d)));\n"
+    "}\n"
+    "\n"
+    "vec3 max4(vec3 a, vec3 b, vec3 c, vec3 d)\n"
+    "{\n"
+    "    return max(a, max(b, max(c, d)));\n"
+    "}\n"
+    "\n"
+    "vec4 resampler(vec4 x)\n"
+    "{\n"
+    "   vec4 res;\n"
+    "\n"
+    "   res.x = (x.x==0.0) ?  wa*wb  :  sin(x.x*wa)*sin(x.x*wb)/(x.x*x.x);\n"
+    "   res.y = (x.y==0.0) ?  wa*wb  :  sin(x.y*wa)*sin(x.y*wb)/(x.y*x.y);\n"
+    "   res.z = (x.z==0.0) ?  wa*wb  :  sin(x.z*wa)*sin(x.z*wb)/(x.z*x.z);\n"
+    "   res.w = (x.w==0.0) ?  wa*wb  :  sin(x.w*wa)*sin(x.w*wb)/(x.w*x.w);\n"
+    "\n"
+    "   return res;\n"
+    "}\n"
+    "\n"
+    "void main()\n"
+    "{\n"
+    "    vec3 color;\n"
+    "    vec4 weights[4];\n"
+    "\n"
+    "    vec2 dx = vec2(1.0, 0.0);\n"
+    "    vec2 dy = vec2(0.0, 1.0);\n"
+    "\n"
+    "    vec2 pc = TEX0.xy*TextureSize;\n"
+    "\n"
+    "    vec2 tc = (floor(pc-vec2(0.5,0.5))+vec2(0.5,0.5));\n"
+    "     \n"
+    "    weights[0] = resampler(vec4(d(pc, tc    -dx    -dy), d(pc, tc           -dy), d(pc, tc    +dx    -dy), d(pc, tc+2.0*dx    -dy)));\n"
+    "    weights[1] = resampler(vec4(d(pc, tc    -dx       ), d(pc, tc              ), d(pc, tc    +dx       ), d(pc, tc+2.0*dx       )));\n"
+    "    weights[2] = resampler(vec4(d(pc, tc    -dx    +dy), d(pc, tc           +dy), d(pc, tc    +dx    +dy), d(pc, tc+2.0*dx    +dy)));\n"
+    "    weights[3] = resampler(vec4(d(pc, tc    -dx+2.0*dy), d(pc, tc       +2.0*dy), d(pc, tc    +dx+2.0*dy), d(pc, tc+2.0*dx+2.0*dy)));\n"
+    "\n"
+    "    dx = dx/TextureSize;\n"
+    "    dy = dy/TextureSize;\n"
+    "    tc = tc/TextureSize;\n"
+    "\n"
+    "    vec3 c00 = texture(Texture, tc    -dx    -dy).xyz;\n"
+    "    vec3 c10 = texture(Texture, tc           -dy).xyz;\n"
+    "    vec3 c20 = texture(Texture, tc    +dx    -dy).xyz;\n"
+    "    vec3 c30 = texture(Texture, tc+2.0*dx    -dy).xyz;\n"
+    "    vec3 c01 = texture(Texture, tc    -dx       ).xyz;\n"
+    "    vec3 c11 = texture(Texture, tc              ).xyz;\n"
+    "    vec3 c21 = texture(Texture, tc    +dx       ).xyz;\n"
+    "    vec3 c31 = texture(Texture, tc+2.0*dx       ).xyz;\n"
+    "    vec3 c02 = texture(Texture, tc    -dx    +dy).xyz;\n"
+    "    vec3 c12 = texture(Texture, tc           +dy).xyz;\n"
+    "    vec3 c22 = texture(Texture, tc    +dx    +dy).xyz;\n"
+    "    vec3 c32 = texture(Texture, tc+2.0*dx    +dy).xyz;\n"
+    "    vec3 c03 = texture(Texture, tc    -dx+2.0*dy).xyz;\n"
+    "    vec3 c13 = texture(Texture, tc       +2.0*dy).xyz;\n"
+    "    vec3 c23 = texture(Texture, tc    +dx+2.0*dy).xyz;\n"
+    "    vec3 c33 = texture(Texture, tc+2.0*dx+2.0*dy).xyz;\n"
+    "	\n"
+    "    //  Get min/max samples\n"
+    "    vec3 min_sample = min4(c11, c21, c12, c22);\n"
+    "    vec3 max_sample = max4(c11, c21, c12, c22);\n"
+    "	\n"
+    "    color = vec3(dot(weights[0], vec4(c00.x, c10.x, c20.x, c30.x)), dot(weights[0], vec4(c00.y, c10.y, c20.y, c30.y)), dot(weights[0], vec4(c00.z, c10.z, c20.z, c30.z)));\n"
+    "    color+= vec3(dot(weights[1], vec4(c01.x, c11.x, c21.x, c31.x)), dot(weights[1], vec4(c01.y, c11.y, c21.y, c31.y)), dot(weights[1], vec4(c01.z, c11.z, c21.z, c31.z)));\n"
+    "    color+= vec3(dot(weights[2], vec4(c02.x, c12.x, c22.x, c32.x)), dot(weights[2], vec4(c02.y, c12.y, c22.y, c32.y)), dot(weights[2], vec4(c02.z, c12.z, c22.z, c32.z)));\n"
+    "    color+= vec3(dot(weights[3], vec4(c03.x, c13.x, c23.x, c33.x)), dot(weights[3], vec4(c03.y, c13.y, c23.y, c33.y)), dot(weights[3], vec4(c03.z, c13.z, c23.z, c33.z)));\n"
+    "    color = color/(dot(weights[0], vec4(1,1,1,1)) + dot(weights[1], vec4(1,1,1,1)) + dot(weights[2], vec4(1,1,1,1)) + dot(weights[3], vec4(1,1,1,1)));\n"
+    "\n"
+    "    // Anti-ringing\n"
+    "    vec3 aux = color;\n"
+    "    color = clamp(color, min_sample, max_sample);\n"
+    "    color = mix(aux, color, JINC2_AR_STRENGTH);\n"
+    "\n"
+    "    // final sum and weight normalization\n"
+    "    FragColor.xyz = color;\n"
+    "}\n";
 
 #endif
diff --git a/src/opengl_utils.c b/src/opengl_utils.c
index f1bc32b..94dda4e 100644
--- a/src/opengl_utils.c
+++ b/src/opengl_utils.c
@@ -283,14 +283,14 @@ GLuint oglu_build_program(const GLchar* vert_source, const GLchar* frag_source)
         glGetShaderiv(frag_shader, GL_COMPILE_STATUS, &is_compiled);
         if (is_compiled == GL_FALSE)
         {
-            /*
+            /**/
             GLint len = 0;
             glGetShaderiv(frag_shader, GL_INFO_LOG_LENGTH, &len);
             char* log = calloc(len + 50, 1);
             glGetShaderInfoLog(frag_shader, len, &len, &log[0]);
             TRACE("| GL_LOG: %s\n", log);
             free(log);
-            */
+            
             if (glDeleteShader)
             {
                 glDeleteShader(frag_shader);
diff --git a/src/render_ogl.c b/src/render_ogl.c
index 1d5c963..9a45936 100644
--- a/src/render_ogl.c
+++ b/src/render_ogl.c
@@ -190,6 +190,7 @@ static void ogl_build_programs()
                             PASSTHROUGH_VERT_SHADER, 
                             _stricmp(g_ddraw->shader, "Nearest neighbor") == 0 ? PASSTHROUGH_FRAG_SHADER :
                             _stricmp(g_ddraw->shader, "Bilinear") == 0 ? PASSTHROUGH_FRAG_SHADER :
+                            _stricmp(g_ddraw->shader, "Lanczos") == 0 ? LANCZOS2_FRAG_SHADER :
                             CATMULL_ROM_FRAG_SHADER);
 
                     if (!g_ogl.scale_program)
@@ -199,10 +200,13 @@ static void ogl_build_programs()
                                 PASSTHROUGH_VERT_SHADER_CORE, 
                                 _stricmp(g_ddraw->shader, "Nearest neighbor") == 0 ? PASSTHROUGH_FRAG_SHADER_CORE :
                                 _stricmp(g_ddraw->shader, "Bilinear") == 0 ? PASSTHROUGH_FRAG_SHADER_CORE :
+                                _stricmp(g_ddraw->shader, "Lanczos") == 0 ? LANCZOS2_FRAG_SHADER_CORE :
                                 CATMULL_ROM_FRAG_SHADER_CORE);
                     }
 
-                    bilinear = _stricmp(g_ddraw->shader, "Nearest neighbor") != 0;
+                    bilinear = TRUE;
+                        _stricmp(g_ddraw->shader, "Nearest neighbor") != 0 && 
+                        _stricmp(g_ddraw->shader, "Lanczos") != 0;
                 }
             }
         }