mirror of
https://github.com/cemu-project/cemu_graphic_packs.git
synced 2024-11-26 11:34:15 +01:00
Add scaling filters (#391)
Add your titleID in rules.txt for them to work. Updated Cemuhook's Bicubic and Lanczos scaling shader. Credit rajkosto.
This commit is contained in:
parent
27bda17d31
commit
c8aca9778c
48
Filters/Bicubic (4 taps)/output.glsl
Normal file
48
Filters/Bicubic (4 taps)/output.glsl
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
|
||||||
|
#version 420
|
||||||
|
|
||||||
|
in vec2 passUV;
|
||||||
|
layout(binding=0) uniform sampler2D textureSrc;
|
||||||
|
uniform vec2 textureSrcResolution;
|
||||||
|
layout(location = 0) out vec4 colorOut0;
|
||||||
|
|
||||||
|
vec4 cubic(float x)
|
||||||
|
{
|
||||||
|
float x2 = x * x;
|
||||||
|
float x3 = x2 * x;
|
||||||
|
vec4 w;
|
||||||
|
w.x = -x3 + 3 * x2 - 3 * x + 1;
|
||||||
|
w.y = 3 * x3 - 6 * x2 + 4;
|
||||||
|
w.z = -3 * x3 + 3 * x2 + 3 * x + 1;
|
||||||
|
w.w = x3;
|
||||||
|
return w / 6.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 bcFilter(vec2 texcoord, vec2 texscale)
|
||||||
|
{
|
||||||
|
vec2 tc = floor( texcoord - 0.5 ) + 0.5;
|
||||||
|
vec2 f = texcoord - tc;
|
||||||
|
|
||||||
|
vec4 xcubic = cubic(f.x);
|
||||||
|
vec4 ycubic = cubic(f.y);
|
||||||
|
|
||||||
|
vec4 c = vec4(tc.x - 1.0, tc.x + 1.0, tc.y - 1.0, tc.y + 1.0);
|
||||||
|
vec4 s = vec4(xcubic.x + xcubic.y, xcubic.z + xcubic.w, ycubic.x + ycubic.y, ycubic.z + ycubic.w);
|
||||||
|
vec4 offset = c + vec4(xcubic.y, xcubic.w, ycubic.y, ycubic.w) / s;
|
||||||
|
|
||||||
|
vec4 sample0 = texture(textureSrc, vec2(offset.x, offset.z) * texscale);
|
||||||
|
vec4 sample1 = texture(textureSrc, vec2(offset.y, offset.z) * texscale);
|
||||||
|
vec4 sample2 = texture(textureSrc, vec2(offset.x, offset.w) * texscale);
|
||||||
|
vec4 sample3 = texture(textureSrc, vec2(offset.y, offset.w) * texscale);
|
||||||
|
|
||||||
|
float sx = s.x / (s.x + s.y);
|
||||||
|
float sy = s.z / (s.z + s.w);
|
||||||
|
|
||||||
|
return mix(
|
||||||
|
mix(sample3, sample2, sx),
|
||||||
|
mix(sample1, sample0, sx), sy);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
colorOut0 = vec4(bcFilter(passUV*textureSrcResolution, vec2(1.0,1.0)/textureSrcResolution).rgb,1.0);
|
||||||
|
}
|
10
Filters/Bicubic (4 taps)/rules.txt
Normal file
10
Filters/Bicubic (4 taps)/rules.txt
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
[Definition]
|
||||||
|
name = Optimized Bicubic B-spline resampler
|
||||||
|
titleIds =
|
||||||
|
path = "Filters/Bicubic (4 taps)"
|
||||||
|
description = Cemu's Bicubic. Because it's B-spline so it was optimized down to 4 taps.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[OutputShader]
|
||||||
|
upscaleMagFilter = Linear
|
||||||
|
downscaleMagFilter = Linear
|
97
Filters/Bicubic/output.glsl
Normal file
97
Filters/Bicubic/output.glsl
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
// https://github.com/obsproject/obs-studio/blob/master/libobs/data/bicubic_scale.effect // added customizable polynomials back
|
||||||
|
|
||||||
|
#version 420
|
||||||
|
|
||||||
|
in vec2 passUV;
|
||||||
|
layout(binding=0) uniform sampler2D textureSrc;
|
||||||
|
uniform vec2 textureSrcResolution;
|
||||||
|
layout(location = 0) out vec4 colorOut0;
|
||||||
|
|
||||||
|
float weight(float x)
|
||||||
|
{
|
||||||
|
float ax = abs(x);
|
||||||
|
|
||||||
|
const float B = $b;
|
||||||
|
const float C = $c;
|
||||||
|
|
||||||
|
if (ax < 2.0) {
|
||||||
|
float x_squared = x * x;
|
||||||
|
if (ax < 1.0) {
|
||||||
|
return (x_squared *
|
||||||
|
((12.0 - 9.0 * B - 6.0 * C) * ax +
|
||||||
|
(-18.0 + 12.0 * B + 6.0 * C)) +
|
||||||
|
(6.0 - 2.0 * B))
|
||||||
|
/ 6.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (x_squared *
|
||||||
|
((-B - 6.0 * C) * ax + (6.0 * B + 30.0 * C)) +
|
||||||
|
(-12.0 * B - 48.0 * C) * ax +
|
||||||
|
(8.0 * B + 24.0 * C))
|
||||||
|
/ 6.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 weight4(float x)
|
||||||
|
{
|
||||||
|
return vec4(
|
||||||
|
weight(x - 2.0),
|
||||||
|
weight(x - 1.0),
|
||||||
|
weight(x),
|
||||||
|
weight(x + 1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 DrawBicubic(vec2 f_in)
|
||||||
|
{
|
||||||
|
vec2 stepxy = 1.0/textureSrcResolution;
|
||||||
|
vec2 pos = f_in.st + stepxy * 0.5;
|
||||||
|
vec2 f = fract(pos * textureSrcResolution);
|
||||||
|
|
||||||
|
vec4 rowtaps = weight4(1.0 - f.x);
|
||||||
|
vec4 coltaps = weight4(1.0 - f.y);
|
||||||
|
|
||||||
|
vec2 uv0 = (-1.5 - f) * stepxy + pos;
|
||||||
|
vec2 uv1 = uv0 + stepxy;
|
||||||
|
vec2 uv2 = uv1 + stepxy;
|
||||||
|
vec2 uv3 = uv2 + stepxy;
|
||||||
|
|
||||||
|
float u_weight_sum = rowtaps.y + rowtaps.z;
|
||||||
|
float u_middle_offset = rowtaps.z * stepxy.x / u_weight_sum;
|
||||||
|
float u_middle = uv1.x + u_middle_offset;
|
||||||
|
|
||||||
|
float v_weight_sum = coltaps.y + coltaps.z;
|
||||||
|
float v_middle_offset = coltaps.z * stepxy.y / v_weight_sum;
|
||||||
|
float v_middle = uv1.y + v_middle_offset;
|
||||||
|
|
||||||
|
// wrap doesn't apply to texelFetch
|
||||||
|
// clamp
|
||||||
|
// ivec2 coord_top_left = ivec2(max(uv0 * textureSrcResolution, 0.5));
|
||||||
|
// ivec2 coord_bottom_right = ivec2(min(uv3 * textureSrcResolution, textureSrcResolution - 0.5));
|
||||||
|
// mirror
|
||||||
|
ivec2 coord_top_left = ivec2(abs(uv0 * textureSrcResolution));
|
||||||
|
ivec2 coord_bottom_right = ivec2(textureSrcResolution - abs(uv3 * textureSrcResolution - textureSrcResolution));
|
||||||
|
|
||||||
|
vec4 top = texelFetch(textureSrc, ivec2(coord_top_left), 0) * rowtaps.x;
|
||||||
|
top += texture(textureSrc, vec2(u_middle, uv0.y)) * u_weight_sum;
|
||||||
|
top += texelFetch(textureSrc, ivec2(coord_bottom_right.x, coord_top_left.y), 0) * rowtaps.w;
|
||||||
|
vec4 total = top * coltaps.x;
|
||||||
|
|
||||||
|
vec4 middle = texture(textureSrc, vec2(uv0.x, v_middle)) * rowtaps.x;
|
||||||
|
middle += texture(textureSrc, vec2(u_middle, v_middle)) * u_weight_sum;
|
||||||
|
middle += texture(textureSrc, vec2(uv3.x, v_middle)) * rowtaps.w;
|
||||||
|
total += middle * v_weight_sum;
|
||||||
|
|
||||||
|
vec4 bottom = texelFetch(textureSrc, ivec2(coord_top_left.x, coord_bottom_right.y), 0) * rowtaps.x;
|
||||||
|
bottom += texture(textureSrc, vec2(u_middle, uv3.y)) * u_weight_sum;
|
||||||
|
bottom += texelFetch(textureSrc, ivec2(coord_bottom_right), 0) * rowtaps.w;
|
||||||
|
total += bottom * coltaps.w;
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
colorOut0 = vec4(DrawBicubic(passUV).rgb,1.0);
|
||||||
|
}
|
39
Filters/Bicubic/rules.txt
Normal file
39
Filters/Bicubic/rules.txt
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
[Definition]
|
||||||
|
name = Optimized Bicubic spline resampler
|
||||||
|
titleIds =
|
||||||
|
path = "Filters/Bicubic"
|
||||||
|
description = The b and c can adjust the properties of the cubic; sometimes referred to as "blurring" and "ringing" respectively.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[OutputShader]
|
||||||
|
upscaleMagFilter = Linear
|
||||||
|
downscaleMagFilter = Linear
|
||||||
|
|
||||||
|
[Preset]
|
||||||
|
name = Catmull-Rom
|
||||||
|
$b = 0.0
|
||||||
|
$c = 0.5
|
||||||
|
|
||||||
|
[Preset]
|
||||||
|
name = Mitchell-Netravali
|
||||||
|
$b = 1/3
|
||||||
|
$c = 1/3
|
||||||
|
|
||||||
|
[Preset]
|
||||||
|
name = B-spline
|
||||||
|
$b = 1.0
|
||||||
|
$c = 0.0
|
||||||
|
|
||||||
|
[Preset]
|
||||||
|
name = Photoshop
|
||||||
|
$b = 0.0
|
||||||
|
$c = 0.75
|
||||||
|
|
||||||
|
[Preset]
|
||||||
|
name = Custom (edit in rule.txt)
|
||||||
|
$b = 0.0
|
||||||
|
$c = 0.0
|
||||||
|
|
||||||
|
# Generally b,c >= 0. the shader can't produce negative weight at 0-1 because of bilinear optimization
|
||||||
|
# But some combinations of negative b,c might have non-negative weight
|
||||||
|
# Optionally [b + 2c = 1] for numerically accurate filter
|
128
Filters/Jinc/output.glsl
Normal file
128
Filters/Jinc/output.glsl
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
// https://github.com/libretro/glsl-shaders/blob/master/nnedi3/shaders/jinc2-cshift-rgb.glsl
|
||||||
|
// https://github.com/libretro/common-shaders/blob/master/nedi/shaders/nedi-jinc.cg
|
||||||
|
// https://cemuhook.sshnuke.net/sampleResizers.zip
|
||||||
|
/*
|
||||||
|
Hyllian's jinc windowed-jinc 2-lobe with anti-ringing Shader
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#version 420
|
||||||
|
|
||||||
|
in vec2 passUV;
|
||||||
|
layout(binding=0) uniform sampler2D textureSrc;
|
||||||
|
uniform vec2 textureSrcResolution;
|
||||||
|
layout(location = 0) out vec4 colorOut0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
This is an approximation of Jinc(x)*Jinc(x*r1/r2) for x < 2.5,
|
||||||
|
where r1 and r2 are the first two zeros of jinc function.
|
||||||
|
For a jinc 2-lobe best approximation, use A=0.5 and B=0.825.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// #define halfpi 1.5707963267948966192313216916398 // not used?
|
||||||
|
#define pi 3.1415926535897932384626433832795
|
||||||
|
#define wa ($Window_Sinc*pi)
|
||||||
|
#define wb ($SINC*pi)
|
||||||
|
|
||||||
|
|
||||||
|
float resampler(vec2 pt1, vec2 pt2)
|
||||||
|
{
|
||||||
|
vec2 v = pt2 - pt1;
|
||||||
|
float d = sqrt(dot(v,v)); // Calculates the distance between two points
|
||||||
|
|
||||||
|
return (d==0.0) ? wa*wb : sin(d*wa)*sin(d*wb)/(d*d);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 min4(vec3 a, vec3 b, vec3 c, vec3 d)
|
||||||
|
{
|
||||||
|
return min(a, min(b, min(c, d)));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 max4(vec3 a, vec3 b, vec3 c, vec3 d)
|
||||||
|
{
|
||||||
|
return max(a, max(b, max(c, d)));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 JINC2_sharp(vec2 texture_size, vec2 texCoord)
|
||||||
|
{
|
||||||
|
vec3 color;
|
||||||
|
mat4x4 weights;
|
||||||
|
|
||||||
|
vec2 dx = vec2(1.0, 0.0);
|
||||||
|
vec2 dy = vec2(0.0, 1.0);
|
||||||
|
|
||||||
|
vec2 pc = texCoord*texture_size;
|
||||||
|
|
||||||
|
vec2 tc = (floor(pc-vec2(0.5,0.5))+vec2(0.5,0.5));
|
||||||
|
|
||||||
|
weights[0] = vec4(resampler(pc, tc -dx -dy), resampler(pc, tc -dy), resampler(pc, tc +dx -dy), resampler(pc, tc+2.0*dx -dy));
|
||||||
|
weights[1] = vec4(resampler(pc, tc -dx ), resampler(pc, tc ), resampler(pc, tc +dx ), resampler(pc, tc+2.0*dx ));
|
||||||
|
weights[2] = vec4(resampler(pc, tc -dx +dy), resampler(pc, tc +dy), resampler(pc, tc +dx +dy), resampler(pc, tc+2.0*dx +dy));
|
||||||
|
weights[3] = vec4(resampler(pc, tc -dx+2.0*dy), resampler(pc, tc +2.0*dy), resampler(pc, tc +dx+2.0*dy), resampler(pc, tc+2.0*dx+2.0*dy));
|
||||||
|
|
||||||
|
dx = dx/texture_size;
|
||||||
|
dy = dy/texture_size;
|
||||||
|
tc = tc/texture_size;
|
||||||
|
|
||||||
|
// reading the texels
|
||||||
|
vec3 c00 = texture(textureSrc, tc -dx -dy).xyz;
|
||||||
|
vec3 c10 = texture(textureSrc, tc -dy).xyz;
|
||||||
|
vec3 c20 = texture(textureSrc, tc +dx -dy).xyz;
|
||||||
|
vec3 c30 = texture(textureSrc, tc+2.0*dx -dy).xyz;
|
||||||
|
vec3 c01 = texture(textureSrc, tc -dx ).xyz;
|
||||||
|
vec3 c11 = texture(textureSrc, tc ).xyz;
|
||||||
|
vec3 c21 = texture(textureSrc, tc +dx ).xyz;
|
||||||
|
vec3 c31 = texture(textureSrc, tc+2.0*dx ).xyz;
|
||||||
|
vec3 c02 = texture(textureSrc, tc -dx +dy).xyz;
|
||||||
|
vec3 c12 = texture(textureSrc, tc +dy).xyz;
|
||||||
|
vec3 c22 = texture(textureSrc, tc +dx +dy).xyz;
|
||||||
|
vec3 c32 = texture(textureSrc, tc+2.0*dx +dy).xyz;
|
||||||
|
vec3 c03 = texture(textureSrc, tc -dx+2.0*dy).xyz;
|
||||||
|
vec3 c13 = texture(textureSrc, tc +2.0*dy).xyz;
|
||||||
|
vec3 c23 = texture(textureSrc, tc +dx+2.0*dy).xyz;
|
||||||
|
vec3 c33 = texture(textureSrc, tc+2.0*dx+2.0*dy).xyz;
|
||||||
|
|
||||||
|
// Get min/max samples
|
||||||
|
vec3 min_sample = min4(c11, c21, c12, c22);
|
||||||
|
vec3 max_sample = max4(c11, c21, c12, c22);
|
||||||
|
|
||||||
|
color = mat4x3(c00, c10, c20, c30) * weights[0];
|
||||||
|
color+= mat4x3(c01, c11, c21, c31) * weights[1];
|
||||||
|
color+= mat4x3(c02, c12, c22, c32) * weights[2];
|
||||||
|
color+= mat4x3(c03, c13, c23, c33) * weights[3];
|
||||||
|
color = color / dot(weights * vec4(1.0), vec4(1.0));
|
||||||
|
|
||||||
|
// Anti-ringing
|
||||||
|
vec3 aux = color;
|
||||||
|
color = clamp(color, min_sample, max_sample);
|
||||||
|
|
||||||
|
color = mix(aux, color, $Anti_Ringing);
|
||||||
|
|
||||||
|
// final sum and weight normalization
|
||||||
|
return vec4(color, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
colorOut0 = JINC2_sharp(textureSrcResolution, passUV);
|
||||||
|
}
|
47
Filters/Jinc/rules.txt
Normal file
47
Filters/Jinc/rules.txt
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
[Definition]
|
||||||
|
name = Jinc windowed-jinc with anti-ringing
|
||||||
|
titleIds =
|
||||||
|
path = "Filters/Jinc"
|
||||||
|
description = This is an approximation of Jinc. If B=1.0, it's a lanczos filter.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[OutputShader] # need texels
|
||||||
|
upscaleMagFilter = NearestNeighbor
|
||||||
|
downscaleMagFilter = NearestNeighbor
|
||||||
|
|
||||||
|
[Preset]
|
||||||
|
name = Jinc
|
||||||
|
$Window_Sinc = 0.5
|
||||||
|
$SINC = 0.825
|
||||||
|
$Anti_Ringing = 0.5
|
||||||
|
|
||||||
|
[Preset]
|
||||||
|
name = Lanczos
|
||||||
|
$Window_Sinc = 0.5
|
||||||
|
$SINC = 1.0
|
||||||
|
$Anti_Ringing = 0.8
|
||||||
|
|
||||||
|
[Preset]
|
||||||
|
name = preset3 in nnedi3
|
||||||
|
$Window_Sinc = 0.44
|
||||||
|
$SINC = 0.82
|
||||||
|
$Anti_Ringing = 0.5
|
||||||
|
|
||||||
|
[Preset]
|
||||||
|
name = preset4 in nedi
|
||||||
|
$Window_Sinc = 0.42
|
||||||
|
$SINC = 0.92
|
||||||
|
$Anti_Ringing = 0.8
|
||||||
|
|
||||||
|
[Preset]
|
||||||
|
name = custom (edit in rules.txt)
|
||||||
|
$Window_Sinc = 0.5
|
||||||
|
$SINC = 0.825
|
||||||
|
$Anti_Ringing = 0.8
|
||||||
|
|
||||||
|
# $Window_Sinc == A; $SINC == B.
|
||||||
|
# Increase A to get more blur. Decrease it to get a sharper picture.
|
||||||
|
# B = 0.825 to get rid of dithering. Increase B to get a fine sharpness, though dithering returns.
|
||||||
|
|
||||||
|
# $Anti_Ringing reduces overshoot.
|
||||||
|
# Setting it to 1 prevents overshoot, which might cause pixels sticking together.
|
Loading…
Reference in New Issue
Block a user