mirror of
https://github.com/mkxp-z/mkxp-z.git
synced 2025-03-28 14:56:22 +01:00
Merge pull request #141 from Splendide-Imaginarius/mkxp-z-xbrz
Add xBRZ shader
This commit is contained in:
commit
8d139e2a08
10 changed files with 492 additions and 0 deletions
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
02054AB6B60F49E3DF366CBD /* libjxl_dec.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 672947DA8FC50921A7ED814A /* libjxl_dec.a */; };
|
02054AB6B60F49E3DF366CBD /* libjxl_dec.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 672947DA8FC50921A7ED814A /* libjxl_dec.a */; };
|
||||||
|
21B74169A8853D63648093D5 /* xbrz.frag in CopyFiles */ = {isa = PBXBuildFile; fileRef = 88734C4B8039751FD0A59FA7 /* xbrz.frag */; };
|
||||||
319D403193F13F7989325EEA /* bicubic.frag in CopyFiles */ = {isa = PBXBuildFile; fileRef = CBEA4C45BE737EE0FF5A8A4C /* bicubic.frag */; };
|
319D403193F13F7989325EEA /* bicubic.frag in CopyFiles */ = {isa = PBXBuildFile; fileRef = CBEA4C45BE737EE0FF5A8A4C /* bicubic.frag */; };
|
||||||
3389416F9825F408A40824F3 /* libbrotlicommon-static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A8AA4AE49BB66C97EFAE3055 /* libbrotlicommon-static.a */; };
|
3389416F9825F408A40824F3 /* libbrotlicommon-static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A8AA4AE49BB66C97EFAE3055 /* libbrotlicommon-static.a */; };
|
||||||
3B10EC5C2568D40500372D13 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3BE081562568D3A60006849F /* CoreGraphics.framework */; };
|
3B10EC5C2568D40500372D13 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3BE081562568D3A60006849F /* CoreGraphics.framework */; };
|
||||||
|
@ -505,6 +506,7 @@
|
||||||
3BF5B4BD2685881D00A3B240 /* libSDL2_sound.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3BF5B4BC2685881C00A3B240 /* libSDL2_sound.a */; };
|
3BF5B4BD2685881D00A3B240 /* libSDL2_sound.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3BF5B4BC2685881C00A3B240 /* libSDL2_sound.a */; };
|
||||||
3BF5B4BF2685883B00A3B240 /* libSDL2_sound.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3BF5B4BE2685883B00A3B240 /* libSDL2_sound.a */; };
|
3BF5B4BF2685883B00A3B240 /* libSDL2_sound.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3BF5B4BE2685883B00A3B240 /* libSDL2_sound.a */; };
|
||||||
3BF5B4C02685883B00A3B240 /* libSDL2_sound.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3BF5B4BE2685883B00A3B240 /* libSDL2_sound.a */; };
|
3BF5B4C02685883B00A3B240 /* libSDL2_sound.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3BF5B4BE2685883B00A3B240 /* libSDL2_sound.a */; };
|
||||||
|
3D094509A210271690AF48F7 /* xbrz.frag in CopyFiles */ = {isa = PBXBuildFile; fileRef = 88734C4B8039751FD0A59FA7 /* xbrz.frag */; };
|
||||||
3E2542219A9FD2B16781B1F5 /* libbrotlidec-static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C4B4BA780D4407F24279700 /* libbrotlidec-static.a */; };
|
3E2542219A9FD2B16781B1F5 /* libbrotlidec-static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C4B4BA780D4407F24279700 /* libbrotlidec-static.a */; };
|
||||||
3F7F41D98CEDE6F418AAB0D2 /* bicubic.frag in CopyFiles */ = {isa = PBXBuildFile; fileRef = CBEA4C45BE737EE0FF5A8A4C /* bicubic.frag */; };
|
3F7F41D98CEDE6F418AAB0D2 /* bicubic.frag in CopyFiles */ = {isa = PBXBuildFile; fileRef = CBEA4C45BE737EE0FF5A8A4C /* bicubic.frag */; };
|
||||||
74E9471FB1A876B0D9F2ABFF /* libbrotlidec-static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C254B088D8B18C7E957DE30 /* libbrotlidec-static.a */; };
|
74E9471FB1A876B0D9F2ABFF /* libbrotlidec-static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C254B088D8B18C7E957DE30 /* libbrotlidec-static.a */; };
|
||||||
|
@ -766,6 +768,7 @@
|
||||||
3B10ECE92568E83D00372D13 /* trans.frag in CopyFiles */,
|
3B10ECE92568E83D00372D13 /* trans.frag in CopyFiles */,
|
||||||
3B10ECEA2568E83D00372D13 /* transSimple.frag in CopyFiles */,
|
3B10ECEA2568E83D00372D13 /* transSimple.frag in CopyFiles */,
|
||||||
3F7F41D98CEDE6F418AAB0D2 /* bicubic.frag in CopyFiles */,
|
3F7F41D98CEDE6F418AAB0D2 /* bicubic.frag in CopyFiles */,
|
||||||
|
3D094509A210271690AF48F7 /* xbrz.frag in CopyFiles */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
@ -777,6 +780,7 @@
|
||||||
files = (
|
files = (
|
||||||
3B10ECF52568E86B00372D13 /* liberation.ttf in CopyFiles */,
|
3B10ECF52568E86B00372D13 /* liberation.ttf in CopyFiles */,
|
||||||
319D403193F13F7989325EEA /* bicubic.frag in CopyFiles */,
|
319D403193F13F7989325EEA /* bicubic.frag in CopyFiles */,
|
||||||
|
21B74169A8853D63648093D5 /* xbrz.frag in CopyFiles */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
@ -1128,6 +1132,7 @@
|
||||||
5C254B088D8B18C7E957DE30 /* libbrotlidec-static.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libbrotlidec-static.a"; path = "Dependencies/build-macosx-x86_64/lib/libbrotlidec-static.a"; sourceTree = "<group>"; };
|
5C254B088D8B18C7E957DE30 /* libbrotlidec-static.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libbrotlidec-static.a"; path = "Dependencies/build-macosx-x86_64/lib/libbrotlidec-static.a"; sourceTree = "<group>"; };
|
||||||
667B4E3FBC5B03611D5C334E /* libhwy.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libhwy.a; path = "Dependencies/build-macosx-universal/lib/libhwy.a"; sourceTree = "<group>"; };
|
667B4E3FBC5B03611D5C334E /* libhwy.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libhwy.a; path = "Dependencies/build-macosx-universal/lib/libhwy.a"; sourceTree = "<group>"; };
|
||||||
672947DA8FC50921A7ED814A /* libjxl_dec.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libjxl_dec.a; path = "Dependencies/build-macosx-universal/lib/libjxl_dec.a"; sourceTree = "<group>"; };
|
672947DA8FC50921A7ED814A /* libjxl_dec.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libjxl_dec.a; path = "Dependencies/build-macosx-universal/lib/libjxl_dec.a"; sourceTree = "<group>"; };
|
||||||
|
88734C4B8039751FD0A59FA7 /* xbrz.frag */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = xbrz.frag; path = ../shader/xbrz.frag; sourceTree = "<group>"; };
|
||||||
96563581279A5ABD003D6A75 /* libtheora.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libtheora.a; path = "Dependencies/build-macosx-x86_64/lib/libtheora.a"; sourceTree = "<group>"; };
|
96563581279A5ABD003D6A75 /* libtheora.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libtheora.a; path = "Dependencies/build-macosx-x86_64/lib/libtheora.a"; sourceTree = "<group>"; };
|
||||||
96563584279A5ADA003D6A75 /* libtheora.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libtheora.a; path = "Dependencies/build-macosx-universal/lib/libtheora.a"; sourceTree = "<group>"; };
|
96563584279A5ADA003D6A75 /* libtheora.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libtheora.a; path = "Dependencies/build-macosx-universal/lib/libtheora.a"; sourceTree = "<group>"; };
|
||||||
9656358E279A5B74003D6A75 /* theoraplay_cvtrgb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = theoraplay_cvtrgb.h; sourceTree = "<group>"; };
|
9656358E279A5B74003D6A75 /* theoraplay_cvtrgb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = theoraplay_cvtrgb.h; sourceTree = "<group>"; };
|
||||||
|
@ -1392,6 +1397,7 @@
|
||||||
3B10ECA02568E7B600372D13 /* tilemap.vert */,
|
3B10ECA02568E7B600372D13 /* tilemap.vert */,
|
||||||
3B10EC962568E7B500372D13 /* tilemapvx.vert */,
|
3B10EC962568E7B500372D13 /* tilemapvx.vert */,
|
||||||
CBEA4C45BE737EE0FF5A8A4C /* bicubic.frag */,
|
CBEA4C45BE737EE0FF5A8A4C /* bicubic.frag */,
|
||||||
|
88734C4B8039751FD0A59FA7 /* xbrz.frag */,
|
||||||
);
|
);
|
||||||
name = Shaders;
|
name = Shaders;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
|
@ -83,6 +83,7 @@
|
||||||
// 1: Bilinear
|
// 1: Bilinear
|
||||||
// 2: Bicubic
|
// 2: Bicubic
|
||||||
// 3: Lanczos3
|
// 3: Lanczos3
|
||||||
|
// 4: xBRZ
|
||||||
// (default: 0)
|
// (default: 0)
|
||||||
//
|
//
|
||||||
// "smoothScaling": 0,
|
// "smoothScaling": 0,
|
||||||
|
@ -96,6 +97,14 @@
|
||||||
// "bicubicSharpness": 100,
|
// "bicubicSharpness": 100,
|
||||||
|
|
||||||
|
|
||||||
|
// Scaling factor for xBRZ interpolation
|
||||||
|
// (set to at least the ratio of your window size
|
||||||
|
// to the game's native resolution)
|
||||||
|
// (default: 1.0)
|
||||||
|
//
|
||||||
|
// "xbrzScalingFactor": 4.0,
|
||||||
|
|
||||||
|
|
||||||
// Replace the game's Bitmap files with external high-res files
|
// Replace the game's Bitmap files with external high-res files
|
||||||
// provided in the "Hires" directory.
|
// provided in the "Hires" directory.
|
||||||
// (You'll also need to set the below Scaling Factors.)
|
// (You'll also need to set the below Scaling Factors.)
|
||||||
|
|
|
@ -29,6 +29,11 @@ embedded_shaders = [
|
||||||
'simpleMatrix.vert'
|
'simpleMatrix.vert'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# xBRZ shader is GPLv3.
|
||||||
|
if get_option('enable-https') == true
|
||||||
|
embedded_shaders += 'xbrz.frag'
|
||||||
|
endif
|
||||||
|
|
||||||
embedded_shaders_f = files(embedded_shaders)
|
embedded_shaders_f = files(embedded_shaders)
|
||||||
|
|
||||||
count = 0
|
count = 0
|
||||||
|
|
393
shader/xbrz.frag
Normal file
393
shader/xbrz.frag
Normal file
|
@ -0,0 +1,393 @@
|
||||||
|
// From https://github.com/bsnes-emu/bsnes/tree/c0c60c83a84a49d4a2b822a0491cb258a3c5b98a/shaders/xBRZ.shader
|
||||||
|
// Copyright bsnes contributors.
|
||||||
|
// mkxp-z modifications Copyright 2022-2023 Splendide Imaginarius.
|
||||||
|
// GPLv3+ license.
|
||||||
|
|
||||||
|
// xBRZ freescale
|
||||||
|
// based on :
|
||||||
|
|
||||||
|
// 4xBRZ shader - Copyright (C) 2014-2016 DeSmuME team
|
||||||
|
//
|
||||||
|
// This file is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 2 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This file is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Hyllian's xBR-vertex code and texel mapping
|
||||||
|
|
||||||
|
Copyright (C) 2011/2016 Hyllian - sergiogdb@gmail.com
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef GLSLES
|
||||||
|
precision highp float;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uniform sampler2D texture;
|
||||||
|
uniform vec2 sourceSize;
|
||||||
|
uniform vec2 texSizeInv;
|
||||||
|
uniform vec2 targetScale;
|
||||||
|
|
||||||
|
varying vec2 v_texCoord;
|
||||||
|
|
||||||
|
#define BLEND_NONE 0
|
||||||
|
#define BLEND_NORMAL 1
|
||||||
|
#define BLEND_DOMINANT 2
|
||||||
|
#define LUMINANCE_WEIGHT 1.0
|
||||||
|
#define EQUAL_COLOR_TOLERANCE 30.0/255.0
|
||||||
|
#define STEEP_DIRECTION_THRESHOLD 2.2
|
||||||
|
#define DOMINANT_DIRECTION_THRESHOLD 3.6
|
||||||
|
|
||||||
|
float DistYCbCr(vec3 pixA, vec3 pixB)
|
||||||
|
{
|
||||||
|
const vec3 w = vec3(0.2627, 0.6780, 0.0593);
|
||||||
|
const float scaleB = 0.5 / (1.0 - w.b);
|
||||||
|
const float scaleR = 0.5 / (1.0 - w.r);
|
||||||
|
vec3 diff = pixA - pixB;
|
||||||
|
float Y = dot(diff.rgb, w);
|
||||||
|
float Cb = scaleB * (diff.b - Y);
|
||||||
|
float Cr = scaleR * (diff.r - Y);
|
||||||
|
|
||||||
|
return sqrt(((LUMINANCE_WEIGHT * Y) * (LUMINANCE_WEIGHT * Y)) + (Cb * Cb) + (Cr * Cr));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsPixEqual(const vec3 pixA, const vec3 pixB)
|
||||||
|
{
|
||||||
|
return (DistYCbCr(pixA, pixB) < EQUAL_COLOR_TOLERANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
float get_left_ratio(vec2 center, vec2 origin, vec2 direction, vec2 scale)
|
||||||
|
{
|
||||||
|
vec2 P0 = center - origin;
|
||||||
|
vec2 proj = direction * (dot(P0, direction) / dot(direction, direction));
|
||||||
|
vec2 distv = P0 - proj;
|
||||||
|
vec2 orth = vec2(-direction.y, direction.x);
|
||||||
|
float side = sign(dot(P0, orth));
|
||||||
|
float v = side * length(distv * scale);
|
||||||
|
|
||||||
|
// return step(0, v);
|
||||||
|
return smoothstep(-sqrt(2.0)/2.0, sqrt(2.0)/2.0, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define eq(a,b) (a == b)
|
||||||
|
#define neq(a,b) (a != b)
|
||||||
|
|
||||||
|
// TODO: replace P with P4
|
||||||
|
#define P(x,y) texture2D(texture, coord + texSizeInv * vec2(x, y)).rgb
|
||||||
|
#define P4(x,y) texture2D(texture, coord + texSizeInv * vec2(x, y))
|
||||||
|
|
||||||
|
vec4 pass0(vec2 p0_texCoord) {
|
||||||
|
vec4 fragColor;
|
||||||
|
|
||||||
|
//---------------------------------------
|
||||||
|
// Input Pixel Mapping: -|x|x|x|-
|
||||||
|
// x|A|B|C|x
|
||||||
|
// x|D|E|F|x
|
||||||
|
// x|G|H|I|x
|
||||||
|
// -|x|x|x|-
|
||||||
|
|
||||||
|
vec2 pos = fract(p0_texCoord * sourceSize) - vec2(0.5, 0.5);
|
||||||
|
vec2 coord = p0_texCoord - pos * texSizeInv;
|
||||||
|
|
||||||
|
vec3 A = P(-1,-1);
|
||||||
|
vec3 B = P( 0,-1);
|
||||||
|
vec3 C = P( 1,-1);
|
||||||
|
vec3 D = P(-1, 0);
|
||||||
|
vec3 E = P( 0, 0);
|
||||||
|
vec3 F = P( 1, 0);
|
||||||
|
vec3 G = P(-1, 1);
|
||||||
|
vec3 H = P( 0, 1);
|
||||||
|
vec3 I = P( 1, 1);
|
||||||
|
|
||||||
|
// blendResult Mapping: x|y|
|
||||||
|
// w|z|
|
||||||
|
ivec4 blendResult = ivec4(BLEND_NONE,BLEND_NONE,BLEND_NONE,BLEND_NONE);
|
||||||
|
|
||||||
|
// Preprocess corners
|
||||||
|
// Pixel Tap Mapping: -|-|-|-|-
|
||||||
|
// -|-|B|C|-
|
||||||
|
// -|D|E|F|x
|
||||||
|
// -|G|H|I|x
|
||||||
|
// -|-|x|x|-
|
||||||
|
if (!((eq(E,F) && eq(H,I)) || (eq(E,H) && eq(F,I))))
|
||||||
|
{
|
||||||
|
float dist_H_F = DistYCbCr(G, E) + DistYCbCr(E, C) + DistYCbCr(P(0,2), I) + DistYCbCr(I, P(2,0)) + (4.0 * DistYCbCr(H, F));
|
||||||
|
float dist_E_I = DistYCbCr(D, H) + DistYCbCr(H, P(1,2)) + DistYCbCr(B, F) + DistYCbCr(F, P(2,1)) + (4.0 * DistYCbCr(E, I));
|
||||||
|
bool dominantGradient = (DOMINANT_DIRECTION_THRESHOLD * dist_H_F) < dist_E_I;
|
||||||
|
blendResult.z = ((dist_H_F < dist_E_I) && neq(E,F) && neq(E,H)) ? ((dominantGradient) ? BLEND_DOMINANT : BLEND_NORMAL) : BLEND_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Pixel Tap Mapping: -|-|-|-|-
|
||||||
|
// -|A|B|-|-
|
||||||
|
// x|D|E|F|-
|
||||||
|
// x|G|H|I|-
|
||||||
|
// -|x|x|-|-
|
||||||
|
if (!((eq(D,E) && eq(G,H)) || (eq(D,G) && eq(E,H))))
|
||||||
|
{
|
||||||
|
float dist_G_E = DistYCbCr(P(-2,1) , D) + DistYCbCr(D, B) + DistYCbCr(P(-1,2), H) + DistYCbCr(H, F) + (4.0 * DistYCbCr(G, E));
|
||||||
|
float dist_D_H = DistYCbCr(P(-2,0) , G) + DistYCbCr(G, P(0,2)) + DistYCbCr(A, E) + DistYCbCr(E, I) + (4.0 * DistYCbCr(D, H));
|
||||||
|
bool dominantGradient = (DOMINANT_DIRECTION_THRESHOLD * dist_D_H) < dist_G_E;
|
||||||
|
blendResult.w = ((dist_G_E > dist_D_H) && neq(E,D) && neq(E,H)) ? ((dominantGradient) ? BLEND_DOMINANT : BLEND_NORMAL) : BLEND_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pixel Tap Mapping: -|-|x|x|-
|
||||||
|
// -|A|B|C|x
|
||||||
|
// -|D|E|F|x
|
||||||
|
// -|-|H|I|-
|
||||||
|
// -|-|-|-|-
|
||||||
|
if (!((eq(B,C) && eq(E,F)) || (eq(B,E) && eq(C,F))))
|
||||||
|
{
|
||||||
|
float dist_E_C = DistYCbCr(D, B) + DistYCbCr(B, P(1,-2)) + DistYCbCr(H, F) + DistYCbCr(F, P(2,-1)) + (4.0 * DistYCbCr(E, C));
|
||||||
|
float dist_B_F = DistYCbCr(A, E) + DistYCbCr(E, I) + DistYCbCr(P(0,-2), C) + DistYCbCr(C, P(2,0)) + (4.0 * DistYCbCr(B, F));
|
||||||
|
bool dominantGradient = (DOMINANT_DIRECTION_THRESHOLD * dist_B_F) < dist_E_C;
|
||||||
|
blendResult.y = ((dist_E_C > dist_B_F) && neq(E,B) && neq(E,F)) ? ((dominantGradient) ? BLEND_DOMINANT : BLEND_NORMAL) : BLEND_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pixel Tap Mapping: -|x|x|-|-
|
||||||
|
// x|A|B|C|-
|
||||||
|
// x|D|E|F|-
|
||||||
|
// -|G|H|-|-
|
||||||
|
// -|-|-|-|-
|
||||||
|
if (!((eq(A,B) && eq(D,E)) || (eq(A,D) && eq(B,E))))
|
||||||
|
{
|
||||||
|
float dist_D_B = DistYCbCr(P(-2,0), A) + DistYCbCr(A, P(0,-2)) + DistYCbCr(G, E) + DistYCbCr(E, C) + (4.0 * DistYCbCr(D, B));
|
||||||
|
float dist_A_E = DistYCbCr(P(-2,-1), D) + DistYCbCr(D, H) + DistYCbCr(P(-1,-2), B) + DistYCbCr(B, F) + (4.0 * DistYCbCr(A, E));
|
||||||
|
bool dominantGradient = (DOMINANT_DIRECTION_THRESHOLD * dist_D_B) < dist_A_E;
|
||||||
|
blendResult.x = ((dist_D_B < dist_A_E) && neq(E,D) && neq(E,B)) ? ((dominantGradient) ? BLEND_DOMINANT : BLEND_NORMAL) : BLEND_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
fragColor = vec4(blendResult);
|
||||||
|
|
||||||
|
// Pixel Tap Mapping: -|-|-|-|-
|
||||||
|
// -|-|B|C|-
|
||||||
|
// -|D|E|F|x
|
||||||
|
// -|G|H|I|x
|
||||||
|
// -|-|x|x|-
|
||||||
|
if(blendResult.z == BLEND_DOMINANT || (blendResult.z == BLEND_NORMAL &&
|
||||||
|
!((blendResult.y != BLEND_NONE && !IsPixEqual(E, G)) || (blendResult.w != BLEND_NONE && !IsPixEqual(E, C)) ||
|
||||||
|
(IsPixEqual(G, H) && IsPixEqual(H, I) && IsPixEqual(I, F) && IsPixEqual(F, C) && !IsPixEqual(E, I)))))
|
||||||
|
{
|
||||||
|
fragColor.z += 4.0;
|
||||||
|
|
||||||
|
float dist_F_G = DistYCbCr(F, G);
|
||||||
|
float dist_H_C = DistYCbCr(H, C);
|
||||||
|
|
||||||
|
if((STEEP_DIRECTION_THRESHOLD * dist_F_G <= dist_H_C) && neq(E,G) && neq(D,G))
|
||||||
|
fragColor.z += 16.0;
|
||||||
|
|
||||||
|
if((STEEP_DIRECTION_THRESHOLD * dist_H_C <= dist_F_G) && neq(E,C) && neq(B,C))
|
||||||
|
fragColor.z += 64.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pixel Tap Mapping: -|-|-|-|-
|
||||||
|
// -|A|B|-|-
|
||||||
|
// x|D|E|F|-
|
||||||
|
// x|G|H|I|-
|
||||||
|
// -|x|x|-|-
|
||||||
|
if(blendResult.w == BLEND_DOMINANT || (blendResult.w == BLEND_NORMAL &&
|
||||||
|
!((blendResult.z != BLEND_NONE && !IsPixEqual(E, A)) || (blendResult.x != BLEND_NONE && !IsPixEqual(E, I)) ||
|
||||||
|
(IsPixEqual(A, D) && IsPixEqual(D, G) && IsPixEqual(G, H) && IsPixEqual(H, I) && !IsPixEqual(E, G)))))
|
||||||
|
{
|
||||||
|
fragColor.w += 4.0;
|
||||||
|
|
||||||
|
float dist_H_A = DistYCbCr(H, A);
|
||||||
|
float dist_D_I = DistYCbCr(D, I);
|
||||||
|
|
||||||
|
if((STEEP_DIRECTION_THRESHOLD * dist_H_A <= dist_D_I) && neq(E,A) && neq(B,A))
|
||||||
|
fragColor.w += 16.0;
|
||||||
|
|
||||||
|
if((STEEP_DIRECTION_THRESHOLD * dist_D_I <= dist_H_A) && neq(E,I) && neq(F,I))
|
||||||
|
fragColor.w += 64.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pixel Tap Mapping: -|-|x|x|-
|
||||||
|
// -|A|B|C|x
|
||||||
|
// -|D|E|F|x
|
||||||
|
// -|-|H|I|-
|
||||||
|
// -|-|-|-|-
|
||||||
|
if(blendResult.y == BLEND_DOMINANT || (blendResult.y == BLEND_NORMAL &&
|
||||||
|
!((blendResult.x != BLEND_NONE && !IsPixEqual(E, I)) || (blendResult.z != BLEND_NONE && !IsPixEqual(E, A)) ||
|
||||||
|
(IsPixEqual(I, F) && IsPixEqual(F, C) && IsPixEqual(C, B) && IsPixEqual(B, A) && !IsPixEqual(E, C)))))
|
||||||
|
{
|
||||||
|
fragColor.y += 4.0;
|
||||||
|
|
||||||
|
float dist_B_I = DistYCbCr(B, I);
|
||||||
|
float dist_F_A = DistYCbCr(F, A);
|
||||||
|
|
||||||
|
if((STEEP_DIRECTION_THRESHOLD * dist_B_I <= dist_F_A) && neq(E,I) && neq(H,I))
|
||||||
|
fragColor.y += 16.0;
|
||||||
|
|
||||||
|
if((STEEP_DIRECTION_THRESHOLD * dist_F_A <= dist_B_I) && neq(E,A) && neq(D,A))
|
||||||
|
fragColor.y += 64.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pixel Tap Mapping: -|x|x|-|-
|
||||||
|
// x|A|B|C|-
|
||||||
|
// x|D|E|F|-
|
||||||
|
// -|G|H|-|-
|
||||||
|
// -|-|-|-|-
|
||||||
|
if(blendResult.x == BLEND_DOMINANT || (blendResult.x == BLEND_NORMAL &&
|
||||||
|
!((blendResult.w != BLEND_NONE && !IsPixEqual(E, C)) || (blendResult.y != BLEND_NONE && !IsPixEqual(E, G)) ||
|
||||||
|
(IsPixEqual(C, B) && IsPixEqual(B, A) && IsPixEqual(A, D) && IsPixEqual(D, G) && !IsPixEqual(E, A)))))
|
||||||
|
{
|
||||||
|
fragColor.x += 4.0;
|
||||||
|
|
||||||
|
float dist_D_C = DistYCbCr(D, C);
|
||||||
|
float dist_B_G = DistYCbCr(B, G);
|
||||||
|
|
||||||
|
if((STEEP_DIRECTION_THRESHOLD * dist_D_C <= dist_B_G) && neq(E,C) && neq(F,C))
|
||||||
|
fragColor.x += 16.0;
|
||||||
|
|
||||||
|
if((STEEP_DIRECTION_THRESHOLD * dist_B_G <= dist_D_C) && neq(E,G) && neq(H,G))
|
||||||
|
fragColor.x += 64.0;
|
||||||
|
}
|
||||||
|
fragColor /= 255.0;
|
||||||
|
|
||||||
|
return fragColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 pass1(vec2 p1_texCoord) {
|
||||||
|
vec4 fragColor;
|
||||||
|
|
||||||
|
//---------------------------------------
|
||||||
|
// Input Pixel Mapping: -|B|-
|
||||||
|
// D|E|F
|
||||||
|
// -|H|-
|
||||||
|
|
||||||
|
vec2 scale = targetScale;
|
||||||
|
vec2 pos = fract(p1_texCoord * sourceSize) - vec2(0.5, 0.5);
|
||||||
|
vec2 coord = p1_texCoord - pos * texSizeInv;
|
||||||
|
|
||||||
|
vec4 B = P4( 0,-1);
|
||||||
|
vec4 D = P4(-1, 0);
|
||||||
|
vec4 E = P4( 0, 0);
|
||||||
|
vec4 F = P4( 1, 0);
|
||||||
|
vec4 H = P4( 0, 1);
|
||||||
|
|
||||||
|
vec4 info = floor(pass0(coord) * 255.0 + 0.5);
|
||||||
|
|
||||||
|
// info Mapping: x|y|
|
||||||
|
// w|z|
|
||||||
|
|
||||||
|
vec4 blendResult = floor(mod(info, 4.0));
|
||||||
|
vec4 doLineBlend = floor(mod(info / 4.0, 4.0));
|
||||||
|
vec4 haveShallowLine = floor(mod(info / 16.0, 4.0));
|
||||||
|
vec4 haveSteepLine = floor(mod(info / 64.0, 4.0));
|
||||||
|
|
||||||
|
vec4 res = E;
|
||||||
|
|
||||||
|
// Pixel Tap Mapping: -|-|-
|
||||||
|
// -|E|F
|
||||||
|
// -|H|-
|
||||||
|
|
||||||
|
if(blendResult.z > float(BLEND_NONE))
|
||||||
|
{
|
||||||
|
vec2 origin = vec2(0.0, 1.0 / sqrt(2.0));
|
||||||
|
vec2 direction = vec2(1.0, -1.0);
|
||||||
|
if(doLineBlend.z > 0.0)
|
||||||
|
{
|
||||||
|
origin = haveShallowLine.z > 0.0? vec2(0.0, 0.25) : vec2(0.0, 0.5);
|
||||||
|
direction.x += haveShallowLine.z;
|
||||||
|
direction.y -= haveSteepLine.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: replace the rest of these with vec4
|
||||||
|
vec4 blendPix = mix(H,F, step(DistYCbCr(E.rgb, F.rgb), DistYCbCr(E.rgb, H.rgb)));
|
||||||
|
res = mix(res, blendPix, get_left_ratio(pos, origin, direction, scale));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pixel Tap Mapping: -|-|-
|
||||||
|
// D|E|-
|
||||||
|
// -|H|-
|
||||||
|
if(blendResult.w > float(BLEND_NONE))
|
||||||
|
{
|
||||||
|
vec2 origin = vec2(-1.0 / sqrt(2.0), 0.0);
|
||||||
|
vec2 direction = vec2(1.0, 1.0);
|
||||||
|
if(doLineBlend.w > 0.0)
|
||||||
|
{
|
||||||
|
origin = haveShallowLine.w > 0.0? vec2(-0.25, 0.0) : vec2(-0.5, 0.0);
|
||||||
|
direction.y += haveShallowLine.w;
|
||||||
|
direction.x += haveSteepLine.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: replace the rest of these with vec4
|
||||||
|
vec4 blendPix = mix(H,D, step(DistYCbCr(E.rgb, D.rgb), DistYCbCr(E.rgb, H.rgb)));
|
||||||
|
res = mix(res, blendPix, get_left_ratio(pos, origin, direction, scale));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pixel Tap Mapping: -|B|-
|
||||||
|
// -|E|F
|
||||||
|
// -|-|-
|
||||||
|
if(blendResult.y > float(BLEND_NONE))
|
||||||
|
{
|
||||||
|
vec2 origin = vec2(1.0 / sqrt(2.0), 0.0);
|
||||||
|
vec2 direction = vec2(-1.0, -1.0);
|
||||||
|
|
||||||
|
if(doLineBlend.y > 0.0)
|
||||||
|
{
|
||||||
|
origin = haveShallowLine.y > 0.0? vec2(0.25, 0.0) : vec2(0.5, 0.0);
|
||||||
|
direction.y -= haveShallowLine.y;
|
||||||
|
direction.x -= haveSteepLine.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: replace the rest of these with vec4
|
||||||
|
vec4 blendPix = mix(F,B, step(DistYCbCr(E.rgb, B.rgb), DistYCbCr(E.rgb, F.rgb)));
|
||||||
|
res = mix(res, blendPix, get_left_ratio(pos, origin, direction, scale));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pixel Tap Mapping: -|B|-
|
||||||
|
// D|E|-
|
||||||
|
// -|-|-
|
||||||
|
if(blendResult.x > float(BLEND_NONE))
|
||||||
|
{
|
||||||
|
vec2 origin = vec2(0.0, -1.0 / sqrt(2.0));
|
||||||
|
vec2 direction = vec2(-1.0, 1.0);
|
||||||
|
if(doLineBlend.x > 0.0)
|
||||||
|
{
|
||||||
|
origin = haveShallowLine.x > 0.0? vec2(0.0, -0.25) : vec2(0.0, -0.5);
|
||||||
|
direction.x -= haveShallowLine.x;
|
||||||
|
direction.y += haveSteepLine.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: replace the rest of these with vec4
|
||||||
|
vec4 blendPix = mix(D,B, step(DistYCbCr(E.rgb, B.rgb), DistYCbCr(E.rgb, D.rgb)));
|
||||||
|
res = mix(res, blendPix, get_left_ratio(pos, origin, direction, scale));
|
||||||
|
}
|
||||||
|
|
||||||
|
fragColor = res;
|
||||||
|
|
||||||
|
return fragColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_FragColor = pass1(v_texCoord);
|
||||||
|
}
|
|
@ -136,6 +136,9 @@ void Config::read(int argc, char *argv[]) {
|
||||||
{"fixedAspectRatio", true},
|
{"fixedAspectRatio", true},
|
||||||
{"smoothScaling", 0},
|
{"smoothScaling", 0},
|
||||||
{"bicubicSharpness", 100},
|
{"bicubicSharpness", 100},
|
||||||
|
#ifdef MKXPZ_SSL
|
||||||
|
{"xbrzScalingFactor", 1.},
|
||||||
|
#endif
|
||||||
{"enableHires", false},
|
{"enableHires", false},
|
||||||
{"textureScalingFactor", 1.},
|
{"textureScalingFactor", 1.},
|
||||||
{"framebufferScalingFactor", 1.},
|
{"framebufferScalingFactor", 1.},
|
||||||
|
@ -267,6 +270,9 @@ try { exp } catch (...) {}
|
||||||
SET_OPT(fixedAspectRatio, boolean);
|
SET_OPT(fixedAspectRatio, boolean);
|
||||||
SET_OPT(smoothScaling, integer);
|
SET_OPT(smoothScaling, integer);
|
||||||
SET_OPT(bicubicSharpness, integer);
|
SET_OPT(bicubicSharpness, integer);
|
||||||
|
#ifdef MKXPZ_SSL
|
||||||
|
SET_OPT(xbrzScalingFactor, integer);
|
||||||
|
#endif
|
||||||
SET_OPT(enableHires, boolean);
|
SET_OPT(enableHires, boolean);
|
||||||
SET_OPT(textureScalingFactor, number);
|
SET_OPT(textureScalingFactor, number);
|
||||||
SET_OPT(framebufferScalingFactor, number);
|
SET_OPT(framebufferScalingFactor, number);
|
||||||
|
|
|
@ -45,6 +45,9 @@ struct Config {
|
||||||
bool fixedAspectRatio;
|
bool fixedAspectRatio;
|
||||||
int smoothScaling;
|
int smoothScaling;
|
||||||
int bicubicSharpness;
|
int bicubicSharpness;
|
||||||
|
#ifdef MKXPZ_SSL
|
||||||
|
double xbrzScalingFactor;
|
||||||
|
#endif
|
||||||
bool enableHires;
|
bool enableHires;
|
||||||
double textureScalingFactor;
|
double textureScalingFactor;
|
||||||
double framebufferScalingFactor;
|
double framebufferScalingFactor;
|
||||||
|
|
|
@ -175,6 +175,19 @@ static void _blitBegin(FBO::ID fbo, const Vec2i &size)
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
#ifdef MKXPZ_SSL
|
||||||
|
case xBRZ:
|
||||||
|
{
|
||||||
|
XbrzShader &shader = shState->shaders().xbrz;
|
||||||
|
shader.bind();
|
||||||
|
shader.applyViewportProj();
|
||||||
|
shader.setTranslation(Vec2i());
|
||||||
|
shader.setTexSize(Vec2i(size.x, size.y));
|
||||||
|
shader.setTargetScale(Vec2(1., 1.));
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
SimpleShader &shader = shState->shaders().simple;
|
SimpleShader &shader = shState->shaders().simple;
|
||||||
|
@ -261,6 +274,16 @@ void blitSource(TEXFBO &source)
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
#ifdef MKXPZ_SSL
|
||||||
|
case xBRZ:
|
||||||
|
{
|
||||||
|
XbrzShader &shader = shState->shaders().xbrz;
|
||||||
|
shader.bind();
|
||||||
|
shader.setTexSize(Vec2i(blitSrcWidthHires, blitSrcHeightHires));
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
SimpleShader &shader = shState->shaders().simple;
|
SimpleShader &shader = shState->shaders().simple;
|
||||||
|
@ -306,6 +329,13 @@ void blitRectangle(const IntRect &src, const IntRect &dst, bool smooth)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
#ifdef MKXPZ_SSL
|
||||||
|
if (shState->config().smoothScaling == xBRZ)
|
||||||
|
{
|
||||||
|
XbrzShader &shader = shState->shaders().xbrz;
|
||||||
|
shader.setTargetScale(Vec2((float)(shState->config().xbrzScalingFactor), (float)(shState->config().xbrzScalingFactor)));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (smooth)
|
if (smooth)
|
||||||
TEX::setSmooth(true);
|
TEX::setSmooth(true);
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,9 @@
|
||||||
#include "flashMap.frag.xxd"
|
#include "flashMap.frag.xxd"
|
||||||
#include "bicubic.frag.xxd"
|
#include "bicubic.frag.xxd"
|
||||||
#include "lanczos3.frag.xxd"
|
#include "lanczos3.frag.xxd"
|
||||||
|
#ifdef MKXPZ_SSL
|
||||||
|
#include "xbrz.frag.xxd"
|
||||||
|
#endif
|
||||||
#include "minimal.vert.xxd"
|
#include "minimal.vert.xxd"
|
||||||
#include "simple.vert.xxd"
|
#include "simple.vert.xxd"
|
||||||
#include "simpleColor.vert.xxd"
|
#include "simpleColor.vert.xxd"
|
||||||
|
@ -799,3 +802,21 @@ void Lanczos3Shader::setTexSize(const Vec2i &value)
|
||||||
ShaderBase::setTexSize(value);
|
ShaderBase::setTexSize(value);
|
||||||
gl.Uniform2f(u_sourceSize, (float)value.x, (float)value.y);
|
gl.Uniform2f(u_sourceSize, (float)value.x, (float)value.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MKXPZ_SSL
|
||||||
|
XbrzShader::XbrzShader()
|
||||||
|
{
|
||||||
|
INIT_SHADER(simple, xbrz, XbrzShader);
|
||||||
|
|
||||||
|
ShaderBase::init();
|
||||||
|
|
||||||
|
GET_U(texOffsetX);
|
||||||
|
GET_U(sourceSize);
|
||||||
|
GET_U(targetScale);
|
||||||
|
}
|
||||||
|
|
||||||
|
void XbrzShader::setTargetScale(const Vec2 &value)
|
||||||
|
{
|
||||||
|
gl.Uniform2f(u_targetScale, value.x, value.y);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -352,6 +352,19 @@ protected:
|
||||||
GLint u_bc;
|
GLint u_bc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef MKXPZ_SSL
|
||||||
|
class XbrzShader : public Lanczos3Shader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
XbrzShader();
|
||||||
|
|
||||||
|
void setTargetScale(const Vec2 &value);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
GLint u_targetScale;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Global object containing all available shaders */
|
/* Global object containing all available shaders */
|
||||||
struct ShaderSet
|
struct ShaderSet
|
||||||
{
|
{
|
||||||
|
@ -375,6 +388,9 @@ struct ShaderSet
|
||||||
TilemapVXShader tilemapVX;
|
TilemapVXShader tilemapVX;
|
||||||
BicubicShader bicubic;
|
BicubicShader bicubic;
|
||||||
Lanczos3Shader lanczos3;
|
Lanczos3Shader lanczos3;
|
||||||
|
#ifdef MKXPZ_SSL
|
||||||
|
XbrzShader xbrz;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SHADER_H
|
#endif // SHADER_H
|
||||||
|
|
|
@ -206,6 +206,9 @@ enum InterpolationMethod
|
||||||
Bilinear = 1,
|
Bilinear = 1,
|
||||||
Bicubic = 2,
|
Bicubic = 2,
|
||||||
Lanczos3 = 3,
|
Lanczos3 = 3,
|
||||||
|
#ifdef MKXPZ_SSL
|
||||||
|
xBRZ = 4,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* For internal use.
|
/* For internal use.
|
||||||
|
|
Loading…
Add table
Reference in a new issue