mirror of
https://github.com/italicsjenga/slang-shaders.git
synced 2024-11-22 15:51:30 +11:00
Add dual filtering blur filter (#360)
* Add dual filtering blur filter * Slight docs update
This commit is contained in:
parent
6cc3b3326f
commit
ff05f61aa3
31
blurs/dual_filter_2_pass.slangp
Normal file
31
blurs/dual_filter_2_pass.slangp
Normal 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
|
48
blurs/dual_filter_4_pass.slangp
Normal file
48
blurs/dual_filter_4_pass.slangp
Normal 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
|
||||||
|
|
63
blurs/dual_filter_6_pass.slangp
Normal file
63
blurs/dual_filter_6_pass.slangp
Normal 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
|
44
blurs/shaders/dual_filter_downsample.slang
Normal file
44
blurs/shaders/dual_filter_downsample.slang
Normal 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);
|
||||||
|
}
|
27
blurs/shaders/dual_filter_parameters.slang
Normal file
27
blurs/shaders/dual_filter_parameters.slang
Normal 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
|
47
blurs/shaders/dual_filter_upsample.slang
Normal file
47
blurs/shaders/dual_filter_upsample.slang
Normal 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);
|
||||||
|
}
|
Loading…
Reference in a new issue