Browse Source
[vk, opengl] add lanczo and spline-1 filtering (#2534)
[vk, opengl] add lanczo and spline-1 filtering (#2534)
Signed-off-by: lizzie <lizzie@eden-emu.dev> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2534 Reviewed-by: MaranBr <maranbr@eden-emu.dev> Reviewed-by: Shinmegumi <shinmegumi@eden-emu.dev> Reviewed-by: Maufeat <sahyno1996@gmail.com> Co-authored-by: lizzie <lizzie@eden-emu.dev> Co-committed-by: lizzie <lizzie@eden-emu.dev>pull/2541/head
committed by
crueter
No known key found for this signature in database
GPG Key ID: 425ACD2D4830EBC6
13 changed files with 161 additions and 3 deletions
-
2src/common/settings_enums.h
-
2src/qt_common/shared_translation.cpp
-
4src/qt_common/shared_translation.h
-
6src/video_core/host_shaders/CMakeLists.txt
-
40src/video_core/host_shaders/present_lanczos.frag
-
24src/video_core/host_shaders/present_spline1.frag
-
6src/video_core/renderer_opengl/gl_blit_screen.cpp
-
11src/video_core/renderer_opengl/present/filters.cpp
-
2src/video_core/renderer_opengl/present/filters.h
-
11src/video_core/renderer_vulkan/present/filters.cpp
-
2src/video_core/renderer_vulkan/present/filters.h
-
6src/video_core/renderer_vulkan/vk_blit_screen.cpp
-
48tools/lanczos_gen.c
@ -0,0 +1,40 @@ |
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project |
|||
// SPDX-License-Identifier: GPL-3.0-or-later |
|||
|
|||
// https://en.wikipedia.org/wiki/Lanczos_resampling |
|||
|
|||
#version 460 core |
|||
|
|||
layout (location = 0) in vec2 frag_tex_coord; |
|||
layout (location = 0) out vec4 color; |
|||
layout (binding = 0) uniform sampler2D color_texture; |
|||
|
|||
#define PI 3.1415926535897932384626433 |
|||
float sinc(float x) { |
|||
return x == 0.0f ? 1.0f : sin(PI * x) / (PI * x); |
|||
} |
|||
float lanczos(vec2 v, float a) { |
|||
float d = length(v); |
|||
return sinc(d) / sinc(d / a); |
|||
} |
|||
vec4 textureLanczos(sampler2D textureSampler, vec2 p) { |
|||
vec3 c_sum = vec3(0.0f); |
|||
float w_sum = 0.0f; |
|||
vec2 res = vec2(textureSize(textureSampler, 0)); |
|||
vec2 cc = floor(p * res) / res; |
|||
// kernel size = (2r + 1)^2 |
|||
const int r = 3; //radius (1 = 3 steps) |
|||
for (int x = -r; x <= r; x++) |
|||
for (int y = -r; y <= r; y++) { |
|||
vec2 kp = 0.5f * (vec2(x, y) / res); // 0.5 = half-pixel level resampling |
|||
vec2 uv = cc + kp; |
|||
float w = lanczos(kp, float(r)); |
|||
c_sum += w * texture(textureSampler, p + kp).rgb; |
|||
w_sum += w; |
|||
} |
|||
return vec4(c_sum / w_sum, 1.0f); |
|||
} |
|||
|
|||
void main() { |
|||
color = textureLanczos(color_texture, frag_tex_coord); |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project |
|||
// SPDX-License-Identifier: GPL-3.0-or-later |
|||
|
|||
// Spline (smooth linear inerpolation) with 1 texel fetch (needs bilinear to work) |
|||
// Emulates bicubic without actually doing bicubic |
|||
// See https://iquilezles.org/articles/texture, unfortunely there are issues with the original |
|||
// where smoothstep "expansion" actually results in worse codegen (SPIRV-Opt does a direct conv to smoothstep) |
|||
// TODO: Numerical analysis - fract is sawtooth func and floor, reuse params? Perhaps - no need for precision |
|||
|
|||
#version 460 core |
|||
|
|||
layout (location = 0) in vec2 frag_tex_coord; |
|||
layout (location = 0) out vec4 color; |
|||
layout (binding = 0) uniform sampler2D color_texture; |
|||
|
|||
vec4 textureSpline1(sampler2D sam, vec2 uv) { |
|||
float r = float(textureSize(sam, 0).x); |
|||
vec2 x = fract(uv * r + 0.5); |
|||
return texture(sam, (floor(uv * r + 0.5) + smoothstep(0.0, 1.0, x) - 0.5) / r); |
|||
} |
|||
|
|||
void main() { |
|||
color = textureSpline1(color_texture, frag_tex_coord); |
|||
} |
|||
@ -0,0 +1,48 @@ |
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project |
|||
// SPDX-License-Identifier: GPL-3.0-or-later |
|||
|
|||
// clang -lm tools/lanczos_gen.c -o tools/lanczos_gen && ./tools/lanczos_gen |
|||
#include <stdio.h> |
|||
#include <math.h> |
|||
|
|||
double sinc(double x) { |
|||
return x == 0.0f ? 1.0f : sin(M_PI * x) / (M_PI * x); |
|||
} |
|||
|
|||
typedef struct vec2 { |
|||
double x; |
|||
double y; |
|||
} vec2; |
|||
|
|||
double lanczos(vec2 v, float a) { |
|||
double d = sqrt(v.x * v.x + v.y * v.y); |
|||
return sinc(d) / sinc(d / a); |
|||
} |
|||
|
|||
int main(int argc, char* argv[]) { |
|||
const int r = 3; //radius (1 = 3 steps) |
|||
const int k_size = (r * 2 + 1) * (r * 2 + 1); |
|||
double w_sum = 0.0f; |
|||
// kernel size = (r * 2 + 1) ^ 2 |
|||
printf("const float w_kernel[%i] = float[] (\n ", k_size); |
|||
double factor = 1.0f / ((double)r + 1.0f); |
|||
for (int x = -r; x <= r; x++) |
|||
for (int y = -r; y <= r; y++) { |
|||
double w = lanczos((vec2){ .x = x, .y = y }, (double)r); |
|||
printf("%lff, ", w); |
|||
w_sum += w; |
|||
} |
|||
printf("\n);\n"); |
|||
printf("const vec2 w_pos[%i] = vec2[] (\n ", k_size); |
|||
for (int x = -r; x <= r; x++) |
|||
for (int y = -r; y <= r; y++) { |
|||
vec2 kp = (vec2){ |
|||
.x = x * factor, |
|||
.y = y * factor |
|||
}; |
|||
printf("vec2(%lff, %lff), ", kp.x, kp.y); |
|||
} |
|||
printf("\n);\n"); |
|||
printf("const float w_sum = %lff;\n", w_sum); |
|||
return 0; |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue