mirror of
https://github.com/italicsjenga/slang-shaders.git
synced 2024-11-22 15:51:30 +11:00
Add blur fill (#446)
* Initial commit, WIP * First working version; stretching the blur will require some refactoring * Add blur extension to borders * Implement 'trippy mode' (disable blur, show tiled) * Implement proper scaling, cropping, and centering independent of viewport res * Clean up; Fix bug with small blur pass resolutions * Add blur strength presets; Polish * Add background gamma adjustment
This commit is contained in:
parent
362420d8db
commit
b9d89d63db
|
@ -2,5 +2,5 @@
|
|||
|
||||
// clang-format off
|
||||
#pragma parameter DUAL_FILTER_SETTINGS "=== Dual Filter Blur & Bloom v1.1 settings ===" 0.0 0.0 1.0 1.0
|
||||
#pragma parameter BLUR_RADIUS "Blur radius" 1.0 0.1 7.5 0.1
|
||||
#pragma parameter BLUR_RADIUS "Blur radius" 1.0 0.0 7.5 0.1
|
||||
// clang-format on
|
||||
|
|
82
border/blur_fill.slangp
Normal file
82
border/blur_fill.slangp
Normal file
|
@ -0,0 +1,82 @@
|
|||
shaders = 10
|
||||
|
||||
parameters = "BLUR_RADIUS"
|
||||
BLUR_RADIUS = 2.0
|
||||
|
||||
shader0 = ../blurs/shaders/kawase/linearize.slang
|
||||
scale_type0 = source
|
||||
scale_x0 = 1.0
|
||||
scale_y0 = 1.0
|
||||
float_framebuffer0 = true
|
||||
alias0 = "Input"
|
||||
|
||||
shader1 = shaders/blur_fill/render_sampling_areas.slang
|
||||
scale_type1 = viewport
|
||||
scale_x1 = 0.2
|
||||
scale_y1 = 0.2
|
||||
float_framebuffer1 = true
|
||||
alias1 = "Tiled"
|
||||
|
||||
shader2 = ../blurs/shaders/dual_filter/downsample.slang
|
||||
filter_linear2 = true
|
||||
scale_type2 = source
|
||||
scale_x2 = 0.5
|
||||
scale_y2 = 0.5
|
||||
float_framebuffer2 = true
|
||||
wrap_mode2 = mirrored_repeat
|
||||
|
||||
shader3 = ../blurs/shaders/dual_filter/downsample.slang
|
||||
filter_linear3 = true
|
||||
scale_type3 = source
|
||||
scale_x3 = 0.5
|
||||
scale_y3 = 0.5
|
||||
float_framebuffer3 = true
|
||||
wrap_mode3 = mirrored_repeat
|
||||
|
||||
shader4 = ../blurs/shaders/dual_filter/downsample.slang
|
||||
filter_linear4 = true
|
||||
scale_type4 = source
|
||||
scale_x4 = 0.5
|
||||
scale_y4 = 0.5
|
||||
float_framebuffer4 = true
|
||||
wrap_mode4 = mirrored_repeat
|
||||
|
||||
shader5 = ../blurs/shaders/dual_filter/upsample.slang
|
||||
filter_linear5 = true
|
||||
scale_type5 = source
|
||||
scale_x5 = 2.0
|
||||
scale_y5 = 2.0
|
||||
float_framebuffer5 = true
|
||||
wrap_mode5 = mirrored_repeat
|
||||
|
||||
shader6 = ../blurs/shaders/dual_filter/upsample.slang
|
||||
filter_linear6 = true
|
||||
scale_type6 = source
|
||||
scale_x6 = 2.0
|
||||
scale_y6 = 2.0
|
||||
float_framebuffer6 = true
|
||||
wrap_mode6 = mirrored_repeat
|
||||
|
||||
shader7 = ../blurs/shaders/dual_filter/upsample.slang
|
||||
filter_linear7 = true
|
||||
scale_type7 = source
|
||||
scale_x7 = 2.0
|
||||
scale_y7 = 2.0
|
||||
float_framebuffer7 = true
|
||||
wrap_mode7 = mirrored_repeat
|
||||
alias7 = "Blurred"
|
||||
|
||||
shader8 = shaders/blur_fill/compose.slang
|
||||
filter_linear8 = true
|
||||
scale_type8 = viewport
|
||||
scale_x8 = 1.0
|
||||
scale_y8 = 1.0
|
||||
float_framebuffer8 = true
|
||||
mipmap_input8 = true
|
||||
|
||||
shader9 = ../blurs/shaders/kawase/delinearize.slang
|
||||
filter_linear9 = true
|
||||
scale_type9 = viewport
|
||||
scale_x9 = 1.0
|
||||
scale_y9 = 1.0
|
||||
float_framebuffer9 = true
|
82
border/blur_fill_stronger_blur.slangp
Normal file
82
border/blur_fill_stronger_blur.slangp
Normal file
|
@ -0,0 +1,82 @@
|
|||
shaders = 10
|
||||
|
||||
parameters = "BLUR_RADIUS"
|
||||
BLUR_RADIUS = 4.0
|
||||
|
||||
shader0 = ../blurs/shaders/kawase/linearize.slang
|
||||
scale_type0 = source
|
||||
scale_x0 = 1.0
|
||||
scale_y0 = 1.0
|
||||
float_framebuffer0 = true
|
||||
alias0 = "Input"
|
||||
|
||||
shader1 = shaders/blur_fill/render_sampling_areas.slang
|
||||
scale_type1 = viewport
|
||||
scale_x1 = 0.1
|
||||
scale_y1 = 0.1
|
||||
float_framebuffer1 = true
|
||||
alias1 = "Tiled"
|
||||
|
||||
shader2 = ../blurs/shaders/dual_filter/downsample.slang
|
||||
filter_linear2 = true
|
||||
scale_type2 = source
|
||||
scale_x2 = 0.5
|
||||
scale_y2 = 0.5
|
||||
float_framebuffer2 = true
|
||||
wrap_mode2 = mirrored_repeat
|
||||
|
||||
shader3 = ../blurs/shaders/dual_filter/downsample.slang
|
||||
filter_linear3 = true
|
||||
scale_type3 = source
|
||||
scale_x3 = 0.5
|
||||
scale_y3 = 0.5
|
||||
float_framebuffer3 = true
|
||||
wrap_mode3 = mirrored_repeat
|
||||
|
||||
shader4 = ../blurs/shaders/dual_filter/downsample.slang
|
||||
filter_linear4 = true
|
||||
scale_type4 = source
|
||||
scale_x4 = 0.5
|
||||
scale_y4 = 0.5
|
||||
float_framebuffer4 = true
|
||||
wrap_mode4 = mirrored_repeat
|
||||
|
||||
shader5 = ../blurs/shaders/dual_filter/upsample.slang
|
||||
filter_linear5 = true
|
||||
scale_type5 = source
|
||||
scale_x5 = 2.0
|
||||
scale_y5 = 2.0
|
||||
float_framebuffer5 = true
|
||||
wrap_mode5 = mirrored_repeat
|
||||
|
||||
shader6 = ../blurs/shaders/dual_filter/upsample.slang
|
||||
filter_linear6 = true
|
||||
scale_type6 = source
|
||||
scale_x6 = 2.0
|
||||
scale_y6 = 2.0
|
||||
float_framebuffer6 = true
|
||||
wrap_mode6 = mirrored_repeat
|
||||
|
||||
shader7 = ../blurs/shaders/dual_filter/upsample.slang
|
||||
filter_linear7 = true
|
||||
scale_type7 = source
|
||||
scale_x7 = 2.0
|
||||
scale_y7 = 2.0
|
||||
float_framebuffer7 = true
|
||||
wrap_mode7 = mirrored_repeat
|
||||
alias7 = "Blurred"
|
||||
|
||||
shader8 = shaders/blur_fill/compose.slang
|
||||
filter_linear8 = true
|
||||
scale_type8 = viewport
|
||||
scale_x8 = 1.0
|
||||
scale_y8 = 1.0
|
||||
float_framebuffer8 = true
|
||||
mipmap_input8 = true
|
||||
|
||||
shader9 = ../blurs/shaders/kawase/delinearize.slang
|
||||
filter_linear9 = true
|
||||
scale_type9 = viewport
|
||||
scale_x9 = 1.0
|
||||
scale_y9 = 1.0
|
||||
float_framebuffer9 = true
|
82
border/blur_fill_weaker_blur.slangp
Normal file
82
border/blur_fill_weaker_blur.slangp
Normal file
|
@ -0,0 +1,82 @@
|
|||
shaders = 10
|
||||
|
||||
parameters = "BLUR_RADIUS"
|
||||
BLUR_RADIUS = 1.0
|
||||
|
||||
shader0 = ../blurs/shaders/kawase/linearize.slang
|
||||
scale_type0 = source
|
||||
scale_x0 = 1.0
|
||||
scale_y0 = 1.0
|
||||
float_framebuffer0 = true
|
||||
alias0 = "Input"
|
||||
|
||||
shader1 = shaders/blur_fill/render_sampling_areas.slang
|
||||
scale_type1 = viewport
|
||||
scale_x1 = 0.4
|
||||
scale_y1 = 0.4
|
||||
float_framebuffer1 = true
|
||||
alias1 = "Tiled"
|
||||
|
||||
shader2 = ../blurs/shaders/dual_filter/downsample.slang
|
||||
filter_linear2 = true
|
||||
scale_type2 = source
|
||||
scale_x2 = 0.5
|
||||
scale_y2 = 0.5
|
||||
float_framebuffer2 = true
|
||||
wrap_mode2 = mirrored_repeat
|
||||
|
||||
shader3 = ../blurs/shaders/dual_filter/downsample.slang
|
||||
filter_linear3 = true
|
||||
scale_type3 = source
|
||||
scale_x3 = 0.5
|
||||
scale_y3 = 0.5
|
||||
float_framebuffer3 = true
|
||||
wrap_mode3 = mirrored_repeat
|
||||
|
||||
shader4 = ../blurs/shaders/dual_filter/downsample.slang
|
||||
filter_linear4 = true
|
||||
scale_type4 = source
|
||||
scale_x4 = 0.5
|
||||
scale_y4 = 0.5
|
||||
float_framebuffer4 = true
|
||||
wrap_mode4 = mirrored_repeat
|
||||
|
||||
shader5 = ../blurs/shaders/dual_filter/upsample.slang
|
||||
filter_linear5 = true
|
||||
scale_type5 = source
|
||||
scale_x5 = 2.0
|
||||
scale_y5 = 2.0
|
||||
float_framebuffer5 = true
|
||||
wrap_mode5 = mirrored_repeat
|
||||
|
||||
shader6 = ../blurs/shaders/dual_filter/upsample.slang
|
||||
filter_linear6 = true
|
||||
scale_type6 = source
|
||||
scale_x6 = 2.0
|
||||
scale_y6 = 2.0
|
||||
float_framebuffer6 = true
|
||||
wrap_mode6 = mirrored_repeat
|
||||
|
||||
shader7 = ../blurs/shaders/dual_filter/upsample.slang
|
||||
filter_linear7 = true
|
||||
scale_type7 = source
|
||||
scale_x7 = 2.0
|
||||
scale_y7 = 2.0
|
||||
float_framebuffer7 = true
|
||||
wrap_mode7 = mirrored_repeat
|
||||
alias7 = "Blurred"
|
||||
|
||||
shader8 = shaders/blur_fill/compose.slang
|
||||
filter_linear8 = true
|
||||
scale_type8 = viewport
|
||||
scale_x8 = 1.0
|
||||
scale_y8 = 1.0
|
||||
float_framebuffer8 = true
|
||||
mipmap_input8 = true
|
||||
|
||||
shader9 = ../blurs/shaders/kawase/delinearize.slang
|
||||
filter_linear9 = true
|
||||
scale_type9 = viewport
|
||||
scale_x9 = 1.0
|
||||
scale_y9 = 1.0
|
||||
float_framebuffer9 = true
|
109
border/shaders/blur_fill/compose.slang
Normal file
109
border/shaders/blur_fill/compose.slang
Normal file
|
@ -0,0 +1,109 @@
|
|||
#version 450
|
||||
|
||||
/*
|
||||
Blur fill v1.0 by fishku
|
||||
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:
|
||||
v1.0: Initial release.
|
||||
*/
|
||||
|
||||
#include "../../../blurs/shaders/dual_filter/parameters.slang"
|
||||
#include "parameters.slang"
|
||||
|
||||
layout(push_constant) uniform Push {
|
||||
vec4 InputSize;
|
||||
vec4 TiledSize;
|
||||
vec4 FinalViewportSize;
|
||||
float OS_CROP_TOP;
|
||||
float OS_CROP_BOTTOM;
|
||||
float OS_CROP_LEFT;
|
||||
float OS_CROP_RIGHT;
|
||||
float CENTER_CROP;
|
||||
float SAMPLE_SIZE;
|
||||
float FORCE_ASPECT_RATIO;
|
||||
float ASPECT_H;
|
||||
float ASPECT_V;
|
||||
float FORCE_INTEGER_SCALING;
|
||||
float FILL_GAMMA;
|
||||
// From dual filter blur
|
||||
float BLUR_RADIUS;
|
||||
}
|
||||
param;
|
||||
|
||||
#include "scaling.slang"
|
||||
|
||||
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;
|
||||
|
||||
void main() {
|
||||
gl_Position = global.MVP * Position;
|
||||
vTexCoord = TexCoord;
|
||||
}
|
||||
|
||||
#pragma stage fragment
|
||||
layout(location = 0) in vec2 vTexCoord;
|
||||
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() {
|
||||
const vec2 pixel_coord = o2i(vTexCoord) * param.InputSize.xy;
|
||||
|
||||
const vec4 input_extrema = vec4(param.OS_CROP_LEFT, param.OS_CROP_TOP,
|
||||
param.InputSize.x - param.OS_CROP_RIGHT,
|
||||
param.InputSize.y - param.OS_CROP_BOTTOM);
|
||||
if (any(lessThan(pixel_coord, input_extrema.xy)) ||
|
||||
any(greaterThanEqual(pixel_coord, input_extrema.zw))) {
|
||||
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.
|
||||
// Do a sharp (nearest neighbor) resampling.
|
||||
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.
|
||||
// Do a sharp (nearest neighbor) resampling.
|
||||
FragColor = vec4(
|
||||
texture(Input, (floor(pixel_coord) + 0.5) * param.InputSize.zw).rgb,
|
||||
1.0);
|
||||
}
|
||||
}
|
24
border/shaders/blur_fill/parameters.slang
Normal file
24
border/shaders/blur_fill/parameters.slang
Normal file
|
@ -0,0 +1,24 @@
|
|||
// See compose.slang for copyright and other information.
|
||||
|
||||
// clang-format off
|
||||
#pragma parameter BLUR_FILL_SETTINGS "=== Blur fill v1.0 settings ===" 0.0 0.0 1.0 1.0
|
||||
#pragma parameter OS_CROP_TOP "Overscan crop top" 0.0 0.0 1024.0 1.0
|
||||
#pragma parameter OS_CROP_BOTTOM "Overscan crop bottom" 0.0 0.0 1024.0 1.0
|
||||
#pragma parameter OS_CROP_LEFT "Overscan crop left" 0.0 0.0 1024.0 1.0
|
||||
#pragma parameter OS_CROP_RIGHT "Overscan crop right" 0.0 0.0 1024.0 1.0
|
||||
|
||||
#pragma parameter CENTER_CROP "Center cropped area" 1.0 0.0 1.0 1.0
|
||||
|
||||
#pragma parameter SAMPLE_SIZE "No. of lines for rendering the blur" 16.0 1.0 1024.0 1.0
|
||||
|
||||
#pragma parameter BLUR_EXTEND_H "Extend the blur horizontally" 0.0 0.0 1.0 1.0
|
||||
#pragma parameter BLUR_EXTEND_V "Extend the blur vertically" 1.0 0.0 1.0 1.0
|
||||
#pragma parameter MIRROR_BLUR "Mirror the blur" 0.0 0.0 1.0 1.0
|
||||
|
||||
#pragma parameter FORCE_ASPECT_RATIO "Force aspect ratio" 0.0 0.0 1.0 1.0
|
||||
#pragma parameter ASPECT_H "Horizontal aspect ratio before crop" 4.0 1.0 100.0 1.0
|
||||
#pragma parameter ASPECT_V "Vertical aspect ratio before crop" 3.0 1.0 100.0 1.0
|
||||
#pragma parameter FORCE_INTEGER_SCALING "Force integer scaling" 1.0 0.0 1.0 1.0
|
||||
|
||||
#pragma parameter FILL_GAMMA "Background fill gamma adjustment" 1.4 0.5 2.0 0.1
|
||||
// clang-format on
|
226
border/shaders/blur_fill/render_sampling_areas.slang
Normal file
226
border/shaders/blur_fill/render_sampling_areas.slang
Normal file
|
@ -0,0 +1,226 @@
|
|||
#version 450
|
||||
|
||||
// See compose.slang for copyright and other information.
|
||||
|
||||
#include "parameters.slang"
|
||||
|
||||
layout(push_constant) uniform Push {
|
||||
vec4 InputSize;
|
||||
vec4 FinalViewportSize;
|
||||
float OS_CROP_TOP;
|
||||
float OS_CROP_BOTTOM;
|
||||
float OS_CROP_LEFT;
|
||||
float OS_CROP_RIGHT;
|
||||
float CENTER_CROP;
|
||||
float SAMPLE_SIZE;
|
||||
float BLUR_EXTEND_H;
|
||||
float BLUR_EXTEND_V;
|
||||
float MIRROR_BLUR;
|
||||
float FORCE_ASPECT_RATIO;
|
||||
float ASPECT_H;
|
||||
float ASPECT_V;
|
||||
float FORCE_INTEGER_SCALING;
|
||||
}
|
||||
param;
|
||||
|
||||
#include "scaling.slang"
|
||||
|
||||
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;
|
||||
|
||||
void main() {
|
||||
gl_Position = global.MVP * Position;
|
||||
vTexCoord = TexCoord;
|
||||
}
|
||||
|
||||
#pragma stage fragment
|
||||
layout(location = 0) in vec2 vTexCoord;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
layout(set = 0, binding = 2) uniform sampler2D Input;
|
||||
|
||||
float min(vec4 i) { return min(min(i.x, i.y), min(i.z, i.w)); }
|
||||
|
||||
int argmin(vec4 i) {
|
||||
const vec4 m = vec4(min(i));
|
||||
const vec4 ma = step(i, m) * vec4(0.0, -1.0, -2.0, -3.0);
|
||||
return -int(min(ma));
|
||||
}
|
||||
|
||||
// Returns a coordinate in [0, w) when repeating that interval (and optionally
|
||||
// mirroring).
|
||||
float mirrored_repeat(float w, float x) {
|
||||
const float phase = mod(x, w);
|
||||
if (param.MIRROR_BLUR < 0.5) {
|
||||
return phase;
|
||||
}
|
||||
const int period = int(x / w);
|
||||
return period % 2 == 1 != x > 0.0 ? phase : w - phase;
|
||||
}
|
||||
|
||||
float extend_left(vec2 coord, vec4 input_extrema) {
|
||||
return input_extrema.x +
|
||||
mirrored_repeat(param.SAMPLE_SIZE, coord.x - input_extrema.x);
|
||||
}
|
||||
|
||||
float extend_right(vec2 coord, vec4 input_extrema) {
|
||||
return input_extrema.z -
|
||||
mirrored_repeat(param.SAMPLE_SIZE, input_extrema.z - coord.x);
|
||||
}
|
||||
|
||||
float extend_top(vec2 coord, vec4 input_extrema) {
|
||||
return input_extrema.y +
|
||||
mirrored_repeat(param.SAMPLE_SIZE, coord.y - input_extrema.y);
|
||||
}
|
||||
|
||||
float extend_bottom(vec2 coord, vec4 input_extrema) {
|
||||
return input_extrema.w -
|
||||
mirrored_repeat(param.SAMPLE_SIZE, input_extrema.w - coord.y);
|
||||
}
|
||||
|
||||
// This function samples in a very specific way which is the foundation for
|
||||
// blurring later.
|
||||
// - If the sample coordinate is outside of the cropped input, Either black is
|
||||
// returned if blur extension is turned off, or a repeated pattern from the
|
||||
// sampling frame band is returned.
|
||||
// - If the coordinate is inside the cropped input and within the frame band
|
||||
// given by SAMPLE_SIZE, the original texture sample is returned.
|
||||
// - If the coordinate is further inside than the frame band, a mirrored
|
||||
// repeating sample is returned. The side of the frame that is sampled is given
|
||||
// by the one that is closest to the sampled point.
|
||||
vec3 sample_mirrored_frame(sampler2D tex, vec2 coord, vec4 input_extrema) {
|
||||
if (coord.x < input_extrema.x) {
|
||||
if (param.BLUR_EXTEND_H < 0.5) {
|
||||
return vec3(0.0);
|
||||
}
|
||||
if (coord.y < input_extrema.y) {
|
||||
// Top left corner extension
|
||||
if (param.BLUR_EXTEND_V < 0.5) {
|
||||
return vec3(0.0);
|
||||
}
|
||||
return texture(tex, vec2(extend_left(coord, input_extrema),
|
||||
extend_top(coord, input_extrema)) *
|
||||
param.InputSize.zw)
|
||||
.rgb;
|
||||
} else if (coord.y < input_extrema.w) {
|
||||
// Left extension
|
||||
return texture(tex,
|
||||
vec2(extend_left(coord, input_extrema), coord.y) *
|
||||
param.InputSize.zw)
|
||||
.rgb;
|
||||
} else {
|
||||
// Bottom left corner extension
|
||||
if (param.BLUR_EXTEND_V < 0.5) {
|
||||
return vec3(0.0);
|
||||
}
|
||||
return texture(tex, vec2(extend_left(coord, input_extrema),
|
||||
extend_bottom(coord, input_extrema)) *
|
||||
param.InputSize.zw)
|
||||
.rgb;
|
||||
}
|
||||
} else if (coord.x < input_extrema.z) {
|
||||
if (coord.y < input_extrema.y) {
|
||||
if (param.BLUR_EXTEND_V < 0.5) {
|
||||
return vec3(0.0);
|
||||
}
|
||||
// Top extension
|
||||
return texture(tex,
|
||||
vec2(coord.x, extend_top(coord, input_extrema)) *
|
||||
param.InputSize.zw)
|
||||
.rgb;
|
||||
} else if (coord.y < input_extrema.w) {
|
||||
const vec4 inner_extrema =
|
||||
input_extrema + vec4(param.SAMPLE_SIZE, param.SAMPLE_SIZE,
|
||||
-param.SAMPLE_SIZE, -param.SAMPLE_SIZE);
|
||||
if (any(lessThan(coord, inner_extrema.xy)) ||
|
||||
any(greaterThanEqual(coord, inner_extrema.zw))) {
|
||||
// In frame band
|
||||
return texture(tex, coord * param.InputSize.zw).rgb;
|
||||
}
|
||||
// Innermost -- mirrored repeat sampling from nearest side
|
||||
const vec4 distances =
|
||||
vec4(coord.x - inner_extrema.x, inner_extrema.z - coord.x,
|
||||
coord.y - inner_extrema.y, inner_extrema.w - coord.y);
|
||||
switch (argmin(distances)) {
|
||||
case 0:
|
||||
// left
|
||||
return texture(tex, vec2(extend_left(coord, input_extrema),
|
||||
coord.y) *
|
||||
param.InputSize.zw)
|
||||
.rgb;
|
||||
case 1:
|
||||
// right
|
||||
return texture(tex, vec2(extend_right(coord, input_extrema),
|
||||
coord.y) *
|
||||
param.InputSize.zw)
|
||||
.rgb;
|
||||
case 2:
|
||||
// top
|
||||
return texture(tex, vec2(coord.x,
|
||||
extend_top(coord, input_extrema)) *
|
||||
param.InputSize.zw)
|
||||
.rgb;
|
||||
case 3:
|
||||
default:
|
||||
// bottom
|
||||
return texture(tex,
|
||||
vec2(coord.x,
|
||||
extend_bottom(coord, input_extrema)) *
|
||||
param.InputSize.zw)
|
||||
.rgb;
|
||||
}
|
||||
} else {
|
||||
if (param.BLUR_EXTEND_V < 0.5) {
|
||||
return vec3(0.0);
|
||||
}
|
||||
// Bottom extension
|
||||
return texture(tex,
|
||||
vec2(coord.x, extend_bottom(coord, input_extrema)) *
|
||||
param.InputSize.zw)
|
||||
.rgb;
|
||||
}
|
||||
} else {
|
||||
if (param.BLUR_EXTEND_H < 0.5) {
|
||||
return vec3(0.0);
|
||||
}
|
||||
if (coord.y < input_extrema.y) {
|
||||
// Top right corner extension
|
||||
if (param.BLUR_EXTEND_V < 0.5) {
|
||||
return vec3(0.0);
|
||||
}
|
||||
return texture(tex, vec2(extend_right(coord, input_extrema),
|
||||
extend_top(coord, input_extrema)) *
|
||||
param.InputSize.zw)
|
||||
.rgb;
|
||||
} else if (coord.y < input_extrema.w) {
|
||||
// Right extension
|
||||
return texture(tex,
|
||||
vec2(extend_right(coord, input_extrema), coord.y) *
|
||||
param.InputSize.zw)
|
||||
.rgb;
|
||||
} else {
|
||||
// Bottom right corner extension
|
||||
if (param.BLUR_EXTEND_V < 0.5) {
|
||||
return vec3(0.0);
|
||||
}
|
||||
return texture(tex, vec2(extend_right(coord, input_extrema),
|
||||
extend_bottom(coord, input_extrema)) *
|
||||
param.InputSize.zw)
|
||||
.rgb;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
const vec2 pixel_coord = o2i(vTexCoord) * param.InputSize.xy;
|
||||
FragColor = vec4(
|
||||
sample_mirrored_frame(Input, pixel_coord,
|
||||
vec4(param.OS_CROP_LEFT, param.OS_CROP_TOP,
|
||||
param.InputSize.x - param.OS_CROP_RIGHT,
|
||||
param.InputSize.y - param.OS_CROP_BOTTOM)),
|
||||
1.0);
|
||||
}
|
64
border/shaders/blur_fill/scaling.slang
Normal file
64
border/shaders/blur_fill/scaling.slang
Normal file
|
@ -0,0 +1,64 @@
|
|||
#include "parameters.slang"
|
||||
|
||||
// See compose.slang for copyright and other information.
|
||||
|
||||
// Pixels in input coord. space
|
||||
vec2 eff_input_res() {
|
||||
if (param.CENTER_CROP > 0.5) {
|
||||
return param.InputSize.xy -
|
||||
vec2(param.OS_CROP_LEFT + param.OS_CROP_RIGHT,
|
||||
param.OS_CROP_TOP + param.OS_CROP_BOTTOM);
|
||||
}
|
||||
return param.InputSize.xy -
|
||||
2.0 * vec2(min(param.OS_CROP_LEFT, param.OS_CROP_RIGHT),
|
||||
min(param.OS_CROP_TOP, param.OS_CROP_BOTTOM));
|
||||
}
|
||||
|
||||
// Output to input scaling, in unit coordinate systems.
|
||||
vec2 scale_o2i() {
|
||||
const vec2 eff_input_res = eff_input_res();
|
||||
const vec2 eff_aspect =
|
||||
vec2(eff_input_res.x, param.FORCE_ASPECT_RATIO > 0.5
|
||||
? eff_input_res.y / param.InputSize.y *
|
||||
param.InputSize.x * param.ASPECT_V /
|
||||
param.ASPECT_H
|
||||
: eff_input_res.y);
|
||||
if (param.FinalViewportSize.x / eff_aspect.x <
|
||||
param.FinalViewportSize.y / eff_aspect.y) {
|
||||
// Scale will be limited by width. Calc x scale, then derive y scale
|
||||
// using aspect ratio.
|
||||
const float scale_x =
|
||||
param.FORCE_INTEGER_SCALING > 0.5
|
||||
? floor(param.FinalViewportSize.x / eff_input_res.x)
|
||||
: param.FinalViewportSize.x / eff_input_res.x;
|
||||
const float scale_y = scale_x * eff_input_res.x * eff_aspect.y /
|
||||
(eff_input_res.y * eff_aspect.x);
|
||||
return param.FinalViewportSize.xy * param.InputSize.zw /
|
||||
vec2(scale_x, scale_y);
|
||||
} else {
|
||||
// Scale will be limited by height.
|
||||
const float scale_y =
|
||||
param.FORCE_INTEGER_SCALING > 0.5
|
||||
? floor(param.FinalViewportSize.y / eff_input_res.y)
|
||||
: param.FinalViewportSize.y / eff_input_res.y;
|
||||
const float scale_x = scale_y * eff_input_res.y * eff_aspect.x /
|
||||
(eff_input_res.x * eff_aspect.y);
|
||||
return param.FinalViewportSize.xy * param.InputSize.zw /
|
||||
vec2(scale_x, scale_y);
|
||||
}
|
||||
}
|
||||
|
||||
// In unit space (output to input)
|
||||
// coord_in_input_space = o2i(coord_in_output_space)
|
||||
// This is used to sample from the input texture in the output pass.
|
||||
vec2 o2i(vec2 x) {
|
||||
const vec2 center_in =
|
||||
param.CENTER_CROP > 0.5
|
||||
? 0.5 * param.InputSize.zw *
|
||||
vec2(param.OS_CROP_LEFT + param.InputSize.x -
|
||||
param.OS_CROP_RIGHT,
|
||||
param.OS_CROP_TOP + param.InputSize.y -
|
||||
param.OS_CROP_BOTTOM)
|
||||
: vec2(0.49999);
|
||||
return (x - 0.49999) * scale_o2i() + center_in;
|
||||
}
|
Loading…
Reference in a new issue