diff --git a/blurs/dual_filter_2_pass.slangp b/blurs/dual_filter_2_pass.slangp new file mode 100644 index 0000000..3dad1b1 --- /dev/null +++ b/blurs/dual_filter_2_pass.slangp @@ -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 diff --git a/blurs/dual_filter_4_pass.slangp b/blurs/dual_filter_4_pass.slangp new file mode 100644 index 0000000..e655cd7 --- /dev/null +++ b/blurs/dual_filter_4_pass.slangp @@ -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 + diff --git a/blurs/dual_filter_6_pass.slangp b/blurs/dual_filter_6_pass.slangp new file mode 100644 index 0000000..181b8bf --- /dev/null +++ b/blurs/dual_filter_6_pass.slangp @@ -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 diff --git a/blurs/shaders/dual_filter_downsample.slang b/blurs/shaders/dual_filter_downsample.slang new file mode 100644 index 0000000..f775432 --- /dev/null +++ b/blurs/shaders/dual_filter_downsample.slang @@ -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); +} diff --git a/blurs/shaders/dual_filter_parameters.slang b/blurs/shaders/dual_filter_parameters.slang new file mode 100644 index 0000000..5075c30 --- /dev/null +++ b/blurs/shaders/dual_filter_parameters.slang @@ -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 diff --git a/blurs/shaders/dual_filter_upsample.slang b/blurs/shaders/dual_filter_upsample.slang new file mode 100644 index 0000000..5ce2f92 --- /dev/null +++ b/blurs/shaders/dual_filter_upsample.slang @@ -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); +}