diff --git a/blurs/gauss_4tap.slangp b/blurs/gauss_4tap.slangp new file mode 100644 index 0000000..3753fbc --- /dev/null +++ b/blurs/gauss_4tap.slangp @@ -0,0 +1,13 @@ +shaders = 2 + +shader0 = shaders/gauss_4tap/gauss_2tap_h.slang +filter_linear0 = true +scale_type0 = source +scale0 = 1.0 +wrap_mode0 = mirrored_repeat + +shader1 = shaders/gauss_4tap/gauss_2tap_v.slang +filter_linear1 = true +scale_type1 = source +scale1 = 1.0 +wrap_mode1 = mirrored_repeat diff --git a/blurs/shaders/gauss_4tap/common.slang b/blurs/shaders/gauss_4tap/common.slang new file mode 100644 index 0000000..c603fa8 --- /dev/null +++ b/blurs/shaders/gauss_4tap/common.slang @@ -0,0 +1,21 @@ +/* + Gauss-4tap v1.0 by fishku + Copyright (C) 2023 + Public domain license (CC0) + + Simple two-pass Gaussian blur filter which does two taps per pass. + Idea based on: + https://www.rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/ + + Changelog: + v1.0: Initial release. +*/ + +// Finds the offset so that two samples drawn with linear filtering at that +// offset from a central pixel, multiplied with 1/2 each, sum up to a 3-sample +// approximation of the Gaussian sampled at pixel centers. +float get_offset(float sigma) { + // Weight at x = 0 evaluates to 1 for all values of sigma. + const float w = exp(-1.0 / (sigma * sigma)); + return 2.0 * w / (2.0 * w + 1.0); +} diff --git a/blurs/shaders/gauss_4tap/gauss_2tap_h.slang b/blurs/shaders/gauss_4tap/gauss_2tap_h.slang new file mode 100644 index 0000000..c05fd2e --- /dev/null +++ b/blurs/shaders/gauss_4tap/gauss_2tap_h.slang @@ -0,0 +1,37 @@ +#version 450 + +// See common.slang for copyright and other information. + +#include "parameters.slang" + +layout(push_constant) uniform Push { + vec4 SourceSize; + float SIGMA; +} +param; + +#include "common.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 Source; + +void main() { + const vec2 offset = vec2(get_offset(param.SIGMA) * param.SourceSize.z, 0.0); + FragColor = 0.5 * (texture(Source, vTexCoord - offset) + + texture(Source, vTexCoord + offset)); +} diff --git a/blurs/shaders/gauss_4tap/gauss_2tap_v.slang b/blurs/shaders/gauss_4tap/gauss_2tap_v.slang new file mode 100644 index 0000000..7a8e257 --- /dev/null +++ b/blurs/shaders/gauss_4tap/gauss_2tap_v.slang @@ -0,0 +1,37 @@ +#version 450 + +// See common.slang for copyright and other information. + +#include "parameters.slang" + +layout(push_constant) uniform Push { + vec4 SourceSize; + float SIGMA; +} +param; + +#include "common.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 Source; + +void main() { + const vec2 offset = vec2(0.0, get_offset(param.SIGMA) * param.SourceSize.w); + FragColor = 0.5 * (texture(Source, vTexCoord - offset) + + texture(Source, vTexCoord + offset)); +} diff --git a/blurs/shaders/gauss_4tap/parameters.slang b/blurs/shaders/gauss_4tap/parameters.slang new file mode 100644 index 0000000..09e9cfd --- /dev/null +++ b/blurs/shaders/gauss_4tap/parameters.slang @@ -0,0 +1,6 @@ +// See common.slang for copyright and other information. + +// clang-format off +#pragma parameter GAUSS_4TAP_SETTINGS "=== Gauss-4tap v1.0 settings ===" 0.0 0.0 1.0 1.0 +#pragma parameter SIGMA "Blur radius" 1.0 0.0 2.0 0.05 +// clang-format on