mirror of
https://github.com/mkxp-z/mkxp-z.git
synced 2025-04-21 21:52:04 +02:00
Add Lanczos3 scaling (#9)
"Lanczos filtering tends to yield much better quality (sharper image) than bilinear filtering."
This commit is contained in:
parent
ae6fd075fa
commit
f26a9a8e1c
8 changed files with 118 additions and 7 deletions
|
@ -73,6 +73,13 @@
|
||||||
// "smoothScaling": false,
|
// "smoothScaling": false,
|
||||||
|
|
||||||
|
|
||||||
|
// Apply Lanczos3 interpolation when game screen
|
||||||
|
// is upscaled (typically higher quality than linear)
|
||||||
|
// (default: disabled)
|
||||||
|
//
|
||||||
|
// "lanczos3Scaling": false,
|
||||||
|
|
||||||
|
|
||||||
// Sync screen redraws to the monitor refresh rate
|
// Sync screen redraws to the monitor refresh rate
|
||||||
// (default: disabled)
|
// (default: disabled)
|
||||||
//
|
//
|
||||||
|
|
48
shader/lanczos3.frag
Normal file
48
shader/lanczos3.frag
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
// From https://raw.githubusercontent.com/Sentmoraap/doing-sdl-right/93a52a0db0ff2da5066cce12f5b9a2ac62e6f401/assets/lanczos3.frag
|
||||||
|
// Copyright 2020 Lilian Gimenez (Sentmoraap).
|
||||||
|
// MIT license.
|
||||||
|
|
||||||
|
uniform sampler2D texture;
|
||||||
|
uniform vec2 sourceSize;
|
||||||
|
uniform vec2 texSizeInv;
|
||||||
|
varying vec2 v_texCoord;
|
||||||
|
|
||||||
|
float lanczos3(float x)
|
||||||
|
{
|
||||||
|
x = max(abs(x), 0.00001);
|
||||||
|
float val = x * 3.141592654;
|
||||||
|
return sin(val) * sin(val / 3) / (val * val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec2 pixel = v_texCoord * sourceSize + 0.5;
|
||||||
|
vec2 frac = fract(pixel);
|
||||||
|
vec2 onePixel = texSizeInv;
|
||||||
|
pixel = floor(pixel) * texSizeInv - onePixel / 2;
|
||||||
|
|
||||||
|
float lanczosX[6];
|
||||||
|
float sum = 0;
|
||||||
|
for(int x = 0; x < 6; x++)
|
||||||
|
{
|
||||||
|
lanczosX[x] = lanczos3(x - 2 - frac.x);
|
||||||
|
sum += lanczosX[x];
|
||||||
|
}
|
||||||
|
for(int x = 0; x < 6; x++) lanczosX[x] /= sum;
|
||||||
|
sum = 0;
|
||||||
|
float lanczosY[6];
|
||||||
|
for(int y = 0; y < 6; y++)
|
||||||
|
{
|
||||||
|
lanczosY[y] = lanczos3(y - 2 - frac.y);
|
||||||
|
sum += lanczosY[y];
|
||||||
|
}
|
||||||
|
for(int y = 0; y < 6; y++) lanczosY[y] /= sum;
|
||||||
|
gl_FragColor = vec4(0);
|
||||||
|
for(int y = -2; y <= 3; y++)
|
||||||
|
{
|
||||||
|
vec4 colour = vec4(0);
|
||||||
|
for(int x = -2; x <= 3; x++)
|
||||||
|
colour += texture2D(texture, pixel + vec2(x * onePixel.x, y * onePixel.y)).rgba * lanczosX[x + 2];
|
||||||
|
gl_FragColor += colour * lanczosY[y + 2];
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,6 +15,7 @@ embedded_shaders = [
|
||||||
'simpleAlphaUni.frag',
|
'simpleAlphaUni.frag',
|
||||||
'tilemap.frag',
|
'tilemap.frag',
|
||||||
'flashMap.frag',
|
'flashMap.frag',
|
||||||
|
'lanczos3.frag',
|
||||||
'minimal.vert',
|
'minimal.vert',
|
||||||
'simple.vert',
|
'simple.vert',
|
||||||
'simpleColor.vert',
|
'simpleColor.vert',
|
||||||
|
|
|
@ -134,6 +134,7 @@ void Config::read(int argc, char *argv[]) {
|
||||||
{"fullscreen", false},
|
{"fullscreen", false},
|
||||||
{"fixedAspectRatio", true},
|
{"fixedAspectRatio", true},
|
||||||
{"smoothScaling", false},
|
{"smoothScaling", false},
|
||||||
|
{"lanczos3Scaling", false},
|
||||||
{"vsync", false},
|
{"vsync", false},
|
||||||
{"defScreenW", 0},
|
{"defScreenW", 0},
|
||||||
{"defScreenH", 0},
|
{"defScreenH", 0},
|
||||||
|
@ -257,6 +258,7 @@ try { exp } catch (...) {}
|
||||||
SET_OPT(fullscreen, boolean);
|
SET_OPT(fullscreen, boolean);
|
||||||
SET_OPT(fixedAspectRatio, boolean);
|
SET_OPT(fixedAspectRatio, boolean);
|
||||||
SET_OPT(smoothScaling, boolean);
|
SET_OPT(smoothScaling, boolean);
|
||||||
|
SET_OPT(lanczos3Scaling, boolean);
|
||||||
SET_OPT(winResizable, boolean);
|
SET_OPT(winResizable, boolean);
|
||||||
SET_OPT(vsync, boolean);
|
SET_OPT(vsync, boolean);
|
||||||
SET_STRINGOPT(windowTitle, windowTitle);
|
SET_STRINGOPT(windowTitle, windowTitle);
|
||||||
|
|
|
@ -43,6 +43,7 @@ struct Config {
|
||||||
bool fullscreen;
|
bool fullscreen;
|
||||||
bool fixedAspectRatio;
|
bool fixedAspectRatio;
|
||||||
bool smoothScaling;
|
bool smoothScaling;
|
||||||
|
bool lanczos3Scaling;
|
||||||
bool vsync;
|
bool vsync;
|
||||||
|
|
||||||
int defScreenW;
|
int defScreenW;
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "sharedstate.h"
|
#include "sharedstate.h"
|
||||||
#include "glstate.h"
|
#include "glstate.h"
|
||||||
#include "quad.h"
|
#include "quad.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
namespace GLMeta
|
namespace GLMeta
|
||||||
{
|
{
|
||||||
|
@ -144,10 +145,22 @@ static void _blitBegin(FBO::ID fbo, const Vec2i &size)
|
||||||
FBO::bind(fbo);
|
FBO::bind(fbo);
|
||||||
glState.viewport.pushSet(IntRect(0, 0, size.x, size.y));
|
glState.viewport.pushSet(IntRect(0, 0, size.x, size.y));
|
||||||
|
|
||||||
SimpleShader &shader = shState->shaders().simple;
|
if (shState->config().lanczos3Scaling)
|
||||||
shader.bind();
|
{
|
||||||
shader.applyViewportProj();
|
Lanczos3Shader &shader = shState->shaders().lanczos3;
|
||||||
shader.setTranslation(Vec2i());
|
shader.bind();
|
||||||
|
shader.applyViewportProj();
|
||||||
|
shader.setTranslation(Vec2i());
|
||||||
|
shader.setTexSize(Vec2i(size.x, size.y));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SimpleShader &shader = shState->shaders().simple;
|
||||||
|
shader.bind();
|
||||||
|
shader.applyViewportProj();
|
||||||
|
shader.setTranslation(Vec2i());
|
||||||
|
shader.setTexSize(Vec2i(size.x, size.y));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,8 +182,18 @@ void blitSource(TEXFBO &source)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SimpleShader &shader = shState->shaders().simple;
|
if (shState->config().lanczos3Scaling)
|
||||||
shader.setTexSize(Vec2i(source.width, source.height));
|
{
|
||||||
|
Lanczos3Shader &shader = shState->shaders().lanczos3;
|
||||||
|
shader.bind();
|
||||||
|
shader.setTexSize(Vec2i(source.width, source.height));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SimpleShader &shader = shState->shaders().simple;
|
||||||
|
shader.bind();
|
||||||
|
shader.setTexSize(Vec2i(source.width, source.height));
|
||||||
|
}
|
||||||
TEX::bind(source.tex);
|
TEX::bind(source.tex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
#include "simpleAlphaUni.frag.xxd"
|
#include "simpleAlphaUni.frag.xxd"
|
||||||
#include "tilemap.frag.xxd"
|
#include "tilemap.frag.xxd"
|
||||||
#include "flashMap.frag.xxd"
|
#include "flashMap.frag.xxd"
|
||||||
|
#include "lanczos3.frag.xxd"
|
||||||
#include "minimal.vert.xxd"
|
#include "minimal.vert.xxd"
|
||||||
#include "simple.vert.xxd"
|
#include "simple.vert.xxd"
|
||||||
#include "simpleColor.vert.xxd"
|
#include "simpleColor.vert.xxd"
|
||||||
|
@ -746,3 +747,19 @@ void BltShader::setOpacity(float value)
|
||||||
{
|
{
|
||||||
gl.Uniform1f(u_opacity, value);
|
gl.Uniform1f(u_opacity, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Lanczos3Shader::Lanczos3Shader()
|
||||||
|
{
|
||||||
|
INIT_SHADER(simple, lanczos3, Lanczos3Shader);
|
||||||
|
|
||||||
|
ShaderBase::init();
|
||||||
|
|
||||||
|
GET_U(texOffsetX);
|
||||||
|
GET_U(sourceSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lanczos3Shader::setTexSize(const Vec2i &value)
|
||||||
|
{
|
||||||
|
ShaderBase::setTexSize(value);
|
||||||
|
gl.Uniform2f(u_sourceSize, (float)value.x, (float)value.y);
|
||||||
|
}
|
||||||
|
|
|
@ -113,7 +113,7 @@ public:
|
||||||
|
|
||||||
void setTexOffsetX(int value);
|
void setTexOffsetX(int value);
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
GLint u_texOffsetX;
|
GLint u_texOffsetX;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -326,6 +326,17 @@ private:
|
||||||
GLint u_source, u_destination, u_subRect, u_opacity;
|
GLint u_source, u_destination, u_subRect, u_opacity;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Lanczos3Shader : public SimpleShader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Lanczos3Shader();
|
||||||
|
|
||||||
|
void setTexSize(const Vec2i &value);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
GLint u_sourceSize;
|
||||||
|
};
|
||||||
|
|
||||||
/* Global object containing all available shaders */
|
/* Global object containing all available shaders */
|
||||||
struct ShaderSet
|
struct ShaderSet
|
||||||
{
|
{
|
||||||
|
@ -347,6 +358,7 @@ struct ShaderSet
|
||||||
SimpleMatrixShader simpleMatrix;
|
SimpleMatrixShader simpleMatrix;
|
||||||
BlurShader blur;
|
BlurShader blur;
|
||||||
TilemapVXShader tilemapVX;
|
TilemapVXShader tilemapVX;
|
||||||
|
Lanczos3Shader lanczos3;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SHADER_H
|
#endif // SHADER_H
|
||||||
|
|
Loading…
Add table
Reference in a new issue