Add dual filtering blur filter (#360)

* Add dual filtering blur filter

* Slight docs update
This commit is contained in:
fishcu 2023-01-30 22:07:42 +01:00 committed by GitHub
parent 6cc3b3326f
commit ff05f61aa3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 260 additions and 0 deletions

View file

@ -0,0 +1,31 @@
shaders = 4
shader0 = shaders/kawase/linearize.slang
filter_linear0 = false
scale_type0 = source
scale_x0 = 1.0
scale_y0 = 1.0
float_framebuffer0 = true
shader1 = shaders/dual_filter_downsample.slang
filter_linear1 = true
scale_type1 = source
scale_x1 = 0.5
scale_y1 = 0.5
float_framebuffer1 = true
wrap_mode1 = mirrored_repeat
shader2 = shaders/dual_filter_upsample.slang
filter_linear2 = true
scale_type2 = source
scale_x2 = 2.0
scale_y2 = 2.0
float_framebuffer2 = true
wrap_mode2 = mirrored_repeat
shader3 = shaders/kawase/delinearize.slang
filter_linear3 = true
scale_type3 = viewport
scale_x3 = 1.0
scale_y3 = 1.0
float_framebuffer3 = true

View file

@ -0,0 +1,48 @@
shaders = 6
shader0 = shaders/kawase/linearize.slang
filter_linear0 = false
scale_type0 = source
scale_x0 = 1.0
scale_y0 = 1.0
float_framebuffer0 = true
shader1 = shaders/dual_filter_downsample.slang
filter_linear1 = true
scale_type1 = source
scale_x1 = 0.5
scale_y1 = 0.5
float_framebuffer1 = true
wrap_mode1 = mirrored_repeat
shader2 = 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 = shaders/dual_filter_upsample.slang
filter_linear3 = true
scale_type3 = source
scale_x3 = 2.0
scale_y3 = 2.0
float_framebuffer3 = true
wrap_mode3 = mirrored_repeat
shader4 = shaders/dual_filter_upsample.slang
filter_linear4 = true
scale_type4 = source
scale_x4 = 2.0
scale_y4 = 2.0
float_framebuffer4 = true
wrap_mode4 = mirrored_repeat
shader5 = shaders/kawase/delinearize.slang
filter_linear5 = true
scale_type5 = viewport
scale_x5 = 1.0
scale_y5 = 1.0
float_framebuffer5 = true

View file

@ -0,0 +1,63 @@
shaders = 8
shader0 = shaders/kawase/linearize.slang
filter_linear0 = false
scale_type0 = source
scale_x0 = 1.0
scale_y0 = 1.0
float_framebuffer0 = true
shader1 = shaders/dual_filter_downsample.slang
filter_linear1 = true
scale_type1 = source
scale_x1 = 0.5
scale_y1 = 0.5
float_framebuffer1 = true
wrap_mode1 = mirrored_repeat
shader2 = 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 = 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 = shaders/dual_filter_upsample.slang
filter_linear4 = true
scale_type4 = source
scale_x4 = 2.0
scale_y4 = 2.0
float_framebuffer4 = true
wrap_mode4 = mirrored_repeat
shader5 = 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 = 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 = shaders/kawase/delinearize.slang
filter_linear7 = true
scale_type7 = viewport
scale_x7 = 1.0
scale_y7 = 1.0
float_framebuffer7 = true

View file

@ -0,0 +1,44 @@
#version 450
// See dual_filter_parameters.slang for copyright and other information.
#include "dual_filter_parameters.slang"
layout(push_constant) uniform Push {
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
float BLUR_STRENGTH;
}
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;
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 Source;
void main() {
const vec2 halfpixel = 0.5 * param.SourceSize.zw * param.BLUR_STRENGTH;
vec3 sum = texture(Source, vTexCoord).rgb * 4.0;
sum += texture(Source, vTexCoord - halfpixel).rgb;
sum += texture(Source, vTexCoord + halfpixel).rgb;
sum += texture(Source, vTexCoord + vec2(halfpixel.x, -halfpixel.y)).rgb;
sum += texture(Source, vTexCoord - vec2(halfpixel.x, -halfpixel.y)).rgb;
FragColor = vec4(sum * 0.125, 1.0);
}

View file

@ -0,0 +1,27 @@
/*
Dual filter v1.0, ported to Slang by fishku
Copyright (C) 2023
Public domain license (CC0)
Follows the notes of the SIGGRAPH 2015 talk here:
https://community.arm.com/cfs-file/__key/communityserver-blogs-components-weblogfiles/00-00-00-20-66/siggraph2015_2D00_mmg_2D00_marius_2D00_notes.pdf
Dual filtering is a fast large-radius blur that approximates a Gaussian blur. It is closely
related to the popular blur filter by Kawase, but runs faster at equal quality.
How it works: Any number of downsampling passes are chained with the same number of upsampling
passes in an hourglass configuration. Both types of resampling passes exploit bilinear
interpolation with carefully chosen coordinates and weights to produce a smooth output.
There are just 5 + 8 = 13 texture samples per combined down- and upsampling pass.
The effective blur radius increases with the number of passes.
This implementation adds a configurable blur strength which can diminish or accentuate the
effect compared to the reference implementation, equivalent to strength 1.0.
Changelog:
v1.0: Initial release.
*/
// clang-format off
#pragma parameter DUAL_FILTER_SETTINGS "=== Dual filter v1.0 settings ===" 0.0 0.0 1.0 1.0
#pragma parameter BLUR_STRENGTH "Blur strength" 1.0 0.6 5.0 0.1
// clang-format on

View file

@ -0,0 +1,47 @@
#version 450
// See dual_filter_parameters.slang for copyright and other information.
#include "dual_filter_parameters.slang"
layout(push_constant) uniform Push {
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
float BLUR_STRENGTH;
}
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;
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 Source;
void main() {
const vec2 halfpixel = 0.5 * param.SourceSize.zw * param.BLUR_STRENGTH;
vec3 sum = texture(Source, vTexCoord + vec2(-halfpixel.x * 2.0, 0.0)).rgb;
sum += texture(Source, vTexCoord + vec2(-halfpixel.x, halfpixel.y)).rgb * 2.0;
sum += texture(Source, vTexCoord + vec2(0.0, halfpixel.y * 2.0)).rgb;
sum += texture(Source, vTexCoord + vec2(halfpixel.x, halfpixel.y)).rgb * 2.0;
sum += texture(Source, vTexCoord + vec2(halfpixel.x * 2.0, 0.0)).rgb;
sum += texture(Source, vTexCoord + vec2(halfpixel.x, -halfpixel.y)).rgb * 2.0;
sum += texture(Source, vTexCoord + vec2(0.0, -halfpixel.y * 2.0)).rgb;
sum += texture(Source, vTexCoord + vec2(-halfpixel.x, -halfpixel.y)).rgb * 2.0;
FragColor = vec4(sum / 12.0, 1.0);
}