2023-06-15 05:21:36 +10:00
|
|
|
#version 450
|
|
|
|
|
|
|
|
/*
|
2023-09-15 10:55:13 +10:00
|
|
|
Blur fill v1.8 by fishku
|
2023-06-15 05:21:36 +10:00
|
|
|
Copyright (C) 2023
|
|
|
|
Public domain license (CC0)
|
|
|
|
|
|
|
|
This shader preset allows cropping the image on any side, and filling the
|
|
|
|
cropped area with a blurred version of the input image borders.
|
|
|
|
This is useful for certain games that do not render a full image to maintain
|
|
|
|
the overall aspect ratio and to avoid burn-in.
|
|
|
|
|
|
|
|
The preset also allows you to extend the original content to a larger
|
|
|
|
screen. It's recommended to set the video scaling options as follows:
|
|
|
|
- Turn integer scaling OFF
|
|
|
|
- Set aspect ratio to FULL
|
|
|
|
The shader will then take over and handle the proper scaling and aspect
|
|
|
|
ratio of the input.
|
|
|
|
|
|
|
|
The preset comes in three variants which differ only in the strength of the
|
|
|
|
blur.
|
|
|
|
Since the blur strength in the dual filter blur depends on the input
|
|
|
|
resolution, and because there is currently no mechanism to set resolution
|
|
|
|
based on user parameters, the three variants provide different sampling
|
|
|
|
resolutions which affect the strength of the blur.
|
|
|
|
Additionally to the resolution, a blur radius parameter controls the
|
|
|
|
strength of the blur.
|
|
|
|
|
|
|
|
Changelog:
|
2023-09-15 10:55:13 +10:00
|
|
|
v1.8: Add overscale option from crop and scale library.
|
2023-09-11 00:15:41 +10:00
|
|
|
v1.7: Refactor for new scaling library. Add rotation support.
|
2023-07-30 07:32:34 +10:00
|
|
|
v1.6: Optimize. Update to new Pixel AA version. Tune default blur strength.
|
2023-06-28 05:26:04 +10:00
|
|
|
v1.5: Add anti-aliased interpolation for non-integer scaling.
|
2023-06-25 13:40:26 +10:00
|
|
|
v1.4: Fix scaling bugs.
|
2023-06-23 08:09:07 +10:00
|
|
|
v1.3: Reduce shimmering artifacts.
|
2023-06-22 09:08:10 +10:00
|
|
|
v1.2: Fix scaling bugs.
|
2023-06-17 04:04:32 +10:00
|
|
|
v1.1: Fix bug with glcore driver.
|
2023-06-15 05:21:36 +10:00
|
|
|
v1.0: Initial release.
|
|
|
|
*/
|
|
|
|
|
2023-07-30 07:32:34 +10:00
|
|
|
// clang-format off
|
2023-06-15 05:21:36 +10:00
|
|
|
#include "parameters.slang"
|
2023-07-30 07:32:34 +10:00
|
|
|
#include "../../../blurs/shaders/dual_filter/parameters.slang"
|
2023-09-11 00:15:41 +10:00
|
|
|
#include "../../../pixel-art-scaling/shaders/pixel_aa/parameters.slang"
|
2023-07-30 07:32:34 +10:00
|
|
|
// clang-format on
|
2023-06-15 05:21:36 +10:00
|
|
|
|
2023-09-15 10:55:13 +10:00
|
|
|
#include "../../../misc/shaders/crop_and_scale/crop_and_scale.slang"
|
2023-09-11 00:15:41 +10:00
|
|
|
#include "../../../pixel-art-scaling/shaders/pixel_aa/shared.slang"
|
|
|
|
|
2023-06-15 05:21:36 +10:00
|
|
|
layout(push_constant) uniform Push {
|
|
|
|
vec4 InputSize;
|
|
|
|
vec4 TiledSize;
|
2023-09-11 00:15:41 +10:00
|
|
|
vec4 OutputSize;
|
|
|
|
uint Rotation;
|
2023-09-15 10:55:13 +10:00
|
|
|
// Own settings
|
|
|
|
float FILL_GAMMA;
|
2023-06-15 05:21:36 +10:00
|
|
|
float SAMPLE_SIZE;
|
2023-09-15 10:55:13 +10:00
|
|
|
// From crop and scale, scaling section
|
2023-06-15 05:21:36 +10:00
|
|
|
float FORCE_ASPECT_RATIO;
|
|
|
|
float ASPECT_H;
|
|
|
|
float ASPECT_V;
|
2023-09-11 00:15:41 +10:00
|
|
|
float FORCE_INTEGER_SCALING_H;
|
|
|
|
float FORCE_INTEGER_SCALING_V;
|
2023-09-15 10:55:13 +10:00
|
|
|
float OVERSCALE;
|
|
|
|
// From crop and scale, cropping section
|
|
|
|
float OS_CROP_TOP;
|
|
|
|
float OS_CROP_BOTTOM;
|
|
|
|
float OS_CROP_LEFT;
|
|
|
|
float OS_CROP_RIGHT;
|
|
|
|
float CENTER_AFTER_CROPPING;
|
2023-06-15 05:21:36 +10:00
|
|
|
// From dual filter blur
|
|
|
|
float BLUR_RADIUS;
|
2023-06-28 05:26:04 +10:00
|
|
|
// From pixel AA
|
|
|
|
float PIX_AA_SHARP;
|
|
|
|
float PIX_AA_SUBPX;
|
|
|
|
float PIX_AA_SUBPX_BGR;
|
2023-06-15 05:21:36 +10:00
|
|
|
}
|
|
|
|
param;
|
|
|
|
|
|
|
|
layout(std140, set = 0, binding = 0) uniform UBO { mat4 MVP; }
|
|
|
|
global;
|
|
|
|
|
|
|
|
#pragma stage vertex
|
|
|
|
layout(location = 0) in vec4 Position;
|
|
|
|
layout(location = 1) in vec2 TexCoord;
|
|
|
|
layout(location = 0) out vec2 vTexCoord;
|
2023-07-30 07:32:34 +10:00
|
|
|
layout(location = 1) out vec2 tx_coord;
|
|
|
|
layout(location = 2) out vec2 tx_per_px;
|
|
|
|
layout(location = 3) out vec2 tx_to_uv;
|
2023-09-11 00:15:41 +10:00
|
|
|
layout(location = 4) out vec4 input_corners;
|
2023-06-15 05:21:36 +10:00
|
|
|
|
|
|
|
void main() {
|
|
|
|
gl_Position = global.MVP * Position;
|
|
|
|
vTexCoord = TexCoord;
|
2023-09-11 00:15:41 +10:00
|
|
|
const vec4 crop = vec4(param.OS_CROP_TOP, param.OS_CROP_LEFT,
|
|
|
|
param.OS_CROP_BOTTOM, param.OS_CROP_RIGHT);
|
|
|
|
const vec2 scale_o2i = get_scale_o2i(
|
|
|
|
param.InputSize.xy, param.OutputSize.xy, crop, param.Rotation,
|
|
|
|
param.CENTER_AFTER_CROPPING, param.FORCE_ASPECT_RATIO,
|
|
|
|
vec2(param.ASPECT_H, param.ASPECT_V),
|
|
|
|
vec2(param.FORCE_INTEGER_SCALING_H, param.FORCE_INTEGER_SCALING_V),
|
2023-09-15 10:55:13 +10:00
|
|
|
param.OVERSCALE,
|
2023-09-11 00:15:41 +10:00
|
|
|
/* output_size_is_final_viewport_size = */ false);
|
|
|
|
tx_coord = o2i(vTexCoord, param.InputSize.xy, crop, param.Rotation,
|
|
|
|
param.CENTER_AFTER_CROPPING, scale_o2i);
|
|
|
|
tx_per_px = scale_o2i * param.OutputSize.zw;
|
2023-07-30 07:32:34 +10:00
|
|
|
tx_to_uv = param.InputSize.zw;
|
2023-09-11 00:15:41 +10:00
|
|
|
input_corners = get_input_corners(param.InputSize.xy, crop, param.Rotation);
|
2023-06-15 05:21:36 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
#pragma stage fragment
|
|
|
|
layout(location = 0) in vec2 vTexCoord;
|
2023-07-30 07:32:34 +10:00
|
|
|
layout(location = 1) in vec2 tx_coord;
|
|
|
|
layout(location = 2) in vec2 tx_per_px;
|
|
|
|
layout(location = 3) in vec2 tx_to_uv;
|
2023-09-11 00:15:41 +10:00
|
|
|
layout(location = 4) in vec4 input_corners;
|
2023-06-15 05:21:36 +10:00
|
|
|
layout(location = 0) out vec4 FragColor;
|
|
|
|
layout(set = 0, binding = 2) uniform sampler2D Input;
|
|
|
|
layout(set = 0, binding = 3) uniform sampler2D Tiled;
|
|
|
|
layout(set = 0, binding = 4) uniform sampler2D Blurred;
|
|
|
|
|
|
|
|
void main() {
|
2023-09-11 00:15:41 +10:00
|
|
|
if (any(lessThan(tx_coord, input_corners.xy)) ||
|
|
|
|
any(greaterThanEqual(tx_coord, input_corners.zw))) {
|
2023-06-15 05:21:36 +10:00
|
|
|
if (param.BLUR_RADIUS > 0.0) {
|
|
|
|
// Sample blur.
|
|
|
|
FragColor = vec4(
|
|
|
|
pow(texture(Blurred, vTexCoord).rgb, vec3(param.FILL_GAMMA)),
|
|
|
|
1.0);
|
|
|
|
} else {
|
|
|
|
// Sample tiled pattern.
|
2023-09-11 00:15:41 +10:00
|
|
|
// Do a perfectly sharp (nearest neighbor) resampling.
|
2023-06-15 05:21:36 +10:00
|
|
|
FragColor =
|
|
|
|
vec4(pow(texture(Tiled,
|
|
|
|
(floor(vTexCoord * param.TiledSize.xy) + 0.5) *
|
|
|
|
param.TiledSize.zw)
|
|
|
|
.rgb,
|
|
|
|
vec3(param.FILL_GAMMA)),
|
|
|
|
1.0);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Sample original.
|
2023-09-11 00:15:41 +10:00
|
|
|
if (param.FORCE_INTEGER_SCALING_H > 0.5 &&
|
|
|
|
param.FORCE_INTEGER_SCALING_V > 0.5) {
|
2023-06-28 05:26:04 +10:00
|
|
|
// Do a perfectly sharp (nearest neighbor) sampling.
|
|
|
|
FragColor = vec4(
|
2023-07-30 07:32:34 +10:00
|
|
|
texture(Input, (floor(tx_coord) + 0.5) * param.InputSize.zw)
|
2023-06-28 05:26:04 +10:00
|
|
|
.rgb,
|
|
|
|
1.0);
|
|
|
|
} else {
|
|
|
|
// Do a sharp anti-aliased interpolation.
|
|
|
|
// Do not correct for gamma additionally because the input is
|
|
|
|
// already in linear color space.
|
2023-07-30 07:32:34 +10:00
|
|
|
FragColor = pixel_aa(
|
|
|
|
Input, tx_per_px, tx_to_uv, tx_coord, param.PIX_AA_SHARP,
|
|
|
|
/* gamma_correct = */ false, param.PIX_AA_SUBPX > 0.5,
|
2023-09-11 00:15:41 +10:00
|
|
|
param.PIX_AA_SUBPX_BGR > 0.5, param.Rotation);
|
2023-06-28 05:26:04 +10:00
|
|
|
}
|
2023-06-15 05:21:36 +10:00
|
|
|
}
|
|
|
|
}
|