mirror of
https://github.com/mkxp-z/mkxp-z.git
synced 2025-03-28 14:56:22 +01:00
Add xBRZ shader
This commit is contained in:
parent
edb3f83777
commit
936d768e4f
10 changed files with 492 additions and 0 deletions
|
@ -8,6 +8,7 @@
|
|||
|
||||
/* Begin PBXBuildFile section */
|
||||
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 */; };
|
||||
3389416F9825F408A40824F3 /* libbrotlicommon-static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A8AA4AE49BB66C97EFAE3055 /* libbrotlicommon-static.a */; };
|
||||
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 */; };
|
||||
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 */; };
|
||||
3D094509A210271690AF48F7 /* xbrz.frag in CopyFiles */ = {isa = PBXBuildFile; fileRef = 88734C4B8039751FD0A59FA7 /* xbrz.frag */; };
|
||||
3E2542219A9FD2B16781B1F5 /* libbrotlidec-static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C4B4BA780D4407F24279700 /* libbrotlidec-static.a */; };
|
||||
3F7F41D98CEDE6F418AAB0D2 /* bicubic.frag in CopyFiles */ = {isa = PBXBuildFile; fileRef = CBEA4C45BE737EE0FF5A8A4C /* bicubic.frag */; };
|
||||
74E9471FB1A876B0D9F2ABFF /* libbrotlidec-static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C254B088D8B18C7E957DE30 /* libbrotlidec-static.a */; };
|
||||
|
@ -766,6 +768,7 @@
|
|||
3B10ECE92568E83D00372D13 /* trans.frag in CopyFiles */,
|
||||
3B10ECEA2568E83D00372D13 /* transSimple.frag in CopyFiles */,
|
||||
3F7F41D98CEDE6F418AAB0D2 /* bicubic.frag in CopyFiles */,
|
||||
3D094509A210271690AF48F7 /* xbrz.frag in CopyFiles */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -777,6 +780,7 @@
|
|||
files = (
|
||||
3B10ECF52568E86B00372D13 /* liberation.ttf in CopyFiles */,
|
||||
319D403193F13F7989325EEA /* bicubic.frag in CopyFiles */,
|
||||
21B74169A8853D63648093D5 /* xbrz.frag in CopyFiles */,
|
||||
);
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
|
@ -1392,6 +1397,7 @@
|
|||
3B10ECA02568E7B600372D13 /* tilemap.vert */,
|
||||
3B10EC962568E7B500372D13 /* tilemapvx.vert */,
|
||||
CBEA4C45BE737EE0FF5A8A4C /* bicubic.frag */,
|
||||
88734C4B8039751FD0A59FA7 /* xbrz.frag */,
|
||||
);
|
||||
name = Shaders;
|
||||
sourceTree = "<group>";
|
||||
|
|
|
@ -83,6 +83,7 @@
|
|||
// 1: Bilinear
|
||||
// 2: Bicubic
|
||||
// 3: Lanczos3
|
||||
// 4: xBRZ
|
||||
// (default: 0)
|
||||
//
|
||||
// "smoothScaling": 0,
|
||||
|
@ -96,6 +97,14 @@
|
|||
// "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
|
||||
// provided in the "Hires" directory.
|
||||
// (You'll also need to set the below Scaling Factors.)
|
||||
|
|
|
@ -29,6 +29,11 @@ embedded_shaders = [
|
|||
'simpleMatrix.vert'
|
||||
]
|
||||
|
||||
# xBRZ shader is GPLv3.
|
||||
if get_option('enable-https') == true
|
||||
embedded_shaders += 'xbrz.frag'
|
||||
endif
|
||||
|
||||
embedded_shaders_f = files(embedded_shaders)
|
||||
|
||||
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},
|
||||
{"smoothScaling", 0},
|
||||
{"bicubicSharpness", 100},
|
||||
#ifdef MKXPZ_SSL
|
||||
{"xbrzScalingFactor", 1.},
|
||||
#endif
|
||||
{"enableHires", false},
|
||||
{"textureScalingFactor", 1.},
|
||||
{"framebufferScalingFactor", 1.},
|
||||
|
@ -267,6 +270,9 @@ try { exp } catch (...) {}
|
|||
SET_OPT(fixedAspectRatio, boolean);
|
||||
SET_OPT(smoothScaling, integer);
|
||||
SET_OPT(bicubicSharpness, integer);
|
||||
#ifdef MKXPZ_SSL
|
||||
SET_OPT(xbrzScalingFactor, integer);
|
||||
#endif
|
||||
SET_OPT(enableHires, boolean);
|
||||
SET_OPT(textureScalingFactor, number);
|
||||
SET_OPT(framebufferScalingFactor, number);
|
||||
|
|
|
@ -45,6 +45,9 @@ struct Config {
|
|||
bool fixedAspectRatio;
|
||||
int smoothScaling;
|
||||
int bicubicSharpness;
|
||||
#ifdef MKXPZ_SSL
|
||||
double xbrzScalingFactor;
|
||||
#endif
|
||||
bool enableHires;
|
||||
double textureScalingFactor;
|
||||
double framebufferScalingFactor;
|
||||
|
|
|
@ -175,6 +175,19 @@ static void _blitBegin(FBO::ID fbo, const Vec2i &size)
|
|||
}
|
||||
|
||||
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:
|
||||
{
|
||||
SimpleShader &shader = shState->shaders().simple;
|
||||
|
@ -261,6 +274,16 @@ void blitSource(TEXFBO &source)
|
|||
}
|
||||
|
||||
break;
|
||||
#ifdef MKXPZ_SSL
|
||||
case xBRZ:
|
||||
{
|
||||
XbrzShader &shader = shState->shaders().xbrz;
|
||||
shader.bind();
|
||||
shader.setTexSize(Vec2i(blitSrcWidthHires, blitSrcHeightHires));
|
||||
}
|
||||
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
{
|
||||
SimpleShader &shader = shState->shaders().simple;
|
||||
|
@ -306,6 +329,13 @@ void blitRectangle(const IntRect &src, const IntRect &dst, bool smooth)
|
|||
}
|
||||
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)
|
||||
TEX::setSmooth(true);
|
||||
|
||||
|
|
|
@ -48,6 +48,9 @@
|
|||
#include "flashMap.frag.xxd"
|
||||
#include "bicubic.frag.xxd"
|
||||
#include "lanczos3.frag.xxd"
|
||||
#ifdef MKXPZ_SSL
|
||||
#include "xbrz.frag.xxd"
|
||||
#endif
|
||||
#include "minimal.vert.xxd"
|
||||
#include "simple.vert.xxd"
|
||||
#include "simpleColor.vert.xxd"
|
||||
|
@ -799,3 +802,21 @@ void Lanczos3Shader::setTexSize(const Vec2i &value)
|
|||
ShaderBase::setTexSize(value);
|
||||
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;
|
||||
};
|
||||
|
||||
#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 */
|
||||
struct ShaderSet
|
||||
{
|
||||
|
@ -375,6 +388,9 @@ struct ShaderSet
|
|||
TilemapVXShader tilemapVX;
|
||||
BicubicShader bicubic;
|
||||
Lanczos3Shader lanczos3;
|
||||
#ifdef MKXPZ_SSL
|
||||
XbrzShader xbrz;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // SHADER_H
|
||||
|
|
|
@ -206,6 +206,9 @@ enum InterpolationMethod
|
|||
Bilinear = 1,
|
||||
Bicubic = 2,
|
||||
Lanczos3 = 3,
|
||||
#ifdef MKXPZ_SSL
|
||||
xBRZ = 4,
|
||||
#endif
|
||||
};
|
||||
|
||||
/* For internal use.
|
||||
|
|
Loading…
Add table
Reference in a new issue