Skip to content

Commit

Permalink
Work around GLSL mirrored_repeat limitations for blur presets
Browse files Browse the repository at this point in the history
  • Loading branch information
fishcu committed Apr 6, 2024
1 parent 7488bc6 commit fb0162e
Show file tree
Hide file tree
Showing 10 changed files with 221 additions and 235 deletions.
2 changes: 0 additions & 2 deletions blurs/dual_filter_2_pass.glslp
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,13 @@ scale_type1 = source
scale_x1 = 0.5
scale_y1 = 0.5
float_framebuffer1 = true
wrap_mode1 = mirrored_repeat

shader2 = shaders/dual_filter/upsample.glsl
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.glsl
filter_linear3 = true
Expand Down
4 changes: 0 additions & 4 deletions blurs/dual_filter_4_pass.glslp
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,27 @@ scale_type1 = source
scale_x1 = 0.5
scale_y1 = 0.5
float_framebuffer1 = true
wrap_mode1 = mirrored_repeat

shader2 = shaders/dual_filter/downsample.glsl
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.glsl
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.glsl
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.glsl
filter_linear5 = true
Expand Down
6 changes: 0 additions & 6 deletions blurs/dual_filter_6_pass.glslp
Original file line number Diff line number Diff line change
Expand Up @@ -13,47 +13,41 @@ scale_type1 = source
scale_x1 = 0.5
scale_y1 = 0.5
float_framebuffer1 = true
wrap_mode1 = mirrored_repeat

shader2 = shaders/dual_filter/downsample.glsl
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.glsl
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.glsl
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.glsl
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.glsl
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.glsl
filter_linear7 = true
Expand Down
2 changes: 0 additions & 2 deletions blurs/gauss_4tap.glslp
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@ shader0 = shaders/gauss_4tap/gauss_2tap_h.glsl
filter_linear0 = true
scale_type0 = source
scale0 = 1.0
wrap_mode0 = mirrored_repeat

shader1 = shaders/gauss_4tap/gauss_2tap_v.glsl
filter_linear1 = true
scale_type1 = source
scale1 = 1.0
wrap_mode1 = mirrored_repeat
140 changes: 68 additions & 72 deletions blurs/shaders/dual_filter/downsample.glsl
Original file line number Diff line number Diff line change
@@ -1,29 +1,36 @@
/*
Dual Filter Blur & Bloom v1.1 by fishku
Copyright (C) 2023
Dual Filter Blur & Bloom v1.2 by fishku
Copyright (C) 2023-2024
Public domain license (CC0)
The dual filter blur implementation follows the notes of the SIGGRAPH 2015 talk here:
The dual filter blur implementation 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.
A blur strength above 3.0 may lead to artifacts, especially on presets with fewer passes.
The bloom filter applies a thresholding operation, then blurs the input to varying degrees.
The scene luminance is estimated using a feedback pass with variable update speed.
The final pass screen blends a tonemapped bloom value with the original input, with the bloom
intensity controlled by the scene luminance (a.k.a. eye adaption).
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. A blur strength above 3.0 may lead to artifacts, especially
on presets with fewer passes.
The bloom filter applies a thresholding operation, then blurs the input to
varying degrees. The scene luminance is estimated using a feedback pass with
variable update speed. The final pass screen blends a tonemapped bloom value
with the original input, with the bloom intensity controlled by the scene
luminance (a.k.a. eye adaption).
Changelog:
v1.2: Implement mirrored_repeat programmatically to work around GLSL
limitations.
v1.1: Added bloom functionality.
v1.0: Initial release.
*/
Expand All @@ -33,11 +40,9 @@
#if __VERSION__ >= 130
#define COMPAT_VARYING out
#define COMPAT_ATTRIBUTE in
#define COMPAT_TEXTURE texture
#else
#define COMPAT_VARYING varying
#define COMPAT_ATTRIBUTE attribute
#define COMPAT_TEXTURE texture2D
#endif

#ifdef GL_ES
Expand All @@ -51,20 +56,29 @@ COMPAT_ATTRIBUTE vec4 TexCoord;
COMPAT_VARYING vec4 TEX0;

uniform mat4 MVPMatrix;
uniform COMPAT_PRECISION int FrameDirection;
uniform COMPAT_PRECISION int FrameCount;
uniform COMPAT_PRECISION vec2 OutputSize;
uniform COMPAT_PRECISION vec2 TextureSize;
uniform COMPAT_PRECISION vec2 InputSize;

// compatibility #defines
#ifdef PARAMETER_UNIFORM
uniform COMPAT_PRECISION float BLUR_RADIUS;
#else
#define BLUR_RADIUS 1.0
#endif

COMPAT_VARYING vec2 in_size_normalized;
COMPAT_VARYING vec2 mirror_min;
COMPAT_VARYING vec2 mirror_max;
COMPAT_VARYING vec2 offset;

#define vTexCoord TEX0.xy
#define SourceSize vec4(TextureSize, 1.0 / TextureSize)
#define OutSize vec4(OutputSize, 1.0 / OutputSize)

void main() {
gl_Position = MVPMatrix * VertexCoord;
TEX0.xy = TexCoord.xy;
gl_Position = MVPMatrix * VertexCoord;
TEX0.xy = TexCoord.xy;
in_size_normalized = InputSize / TextureSize;
mirror_min = 0.5 / TextureSize;
mirror_max = (InputSize - 0.5) / TextureSize;
offset = BLUR_RADIUS / TextureSize;
}

#elif defined(FRAGMENT)
Expand All @@ -90,57 +104,39 @@ out COMPAT_PRECISION vec4 FragColor;
#define COMPAT_TEXTURE texture2D
#endif

uniform COMPAT_PRECISION int FrameDirection;
uniform COMPAT_PRECISION int FrameCount;
uniform COMPAT_PRECISION vec2 OutputSize;
uniform COMPAT_PRECISION vec2 TextureSize;
uniform COMPAT_PRECISION vec2 InputSize;
uniform sampler2D Texture;
COMPAT_VARYING vec4 TEX0;

// compatibility #defines
COMPAT_VARYING vec2 in_size_normalized;
COMPAT_VARYING vec2 mirror_min;
COMPAT_VARYING vec2 mirror_max;
COMPAT_VARYING vec2 offset;

#define Source Texture
#define vTexCoord TEX0.xy

#define SourceSize vec4(TextureSize, 1.0 / TextureSize)
#define OutSize vec4(OutputSize, 1.0 / OutputSize)

#ifdef PARAMETER_UNIFORM
uniform COMPAT_PRECISION float BLUR_RADIUS;
#else
#define BLUR_RADIUS 1.0
#endif

vec3 downsample(sampler2D tex, vec2 coord, vec2 offset) {
// The offset should be 1 source pixel size which equals 0.5 output pixel
// sizes in the default configuration.
return (COMPAT_TEXTURE(tex, coord - offset).rgb + //
COMPAT_TEXTURE(tex, coord + vec2(offset.x, -offset.y)).rgb + //
COMPAT_TEXTURE(tex, coord).rgb * 4.0 + //
COMPAT_TEXTURE(tex, coord + offset).rgb + //
COMPAT_TEXTURE(tex, coord - vec2(offset.x, -offset.y)).rgb) *
0.125;
vec2 mirror_repeat(vec2 coord) {
vec2 doubled = mod(coord, 2.0 * in_size_normalized);
vec2 mirror = step(in_size_normalized, doubled);
return clamp(mix(doubled, 2.0 * in_size_normalized - doubled, mirror),
mirror_min, mirror_max);
}

vec3 upsample(sampler2D tex, vec2 coord, vec2 offset) {
// The offset should be 0.5 source pixel sizes which equals 1 output pixel
// size in the default configuration.
return (COMPAT_TEXTURE(tex, coord + vec2(0.0, -offset.y * 2.0)).rgb +
(COMPAT_TEXTURE(tex, coord + vec2(-offset.x, -offset.y)).rgb +
COMPAT_TEXTURE(tex, coord + vec2(offset.x, -offset.y)).rgb) *
2.0 +
COMPAT_TEXTURE(tex, coord + vec2(-offset.x * 2.0, 0.0)).rgb +
COMPAT_TEXTURE(tex, coord + vec2(offset.x * 2.0, 0.0)).rgb +
(COMPAT_TEXTURE(tex, coord + vec2(-offset.x, offset.y)).rgb +
COMPAT_TEXTURE(tex, coord + vec2(offset.x, offset.y)).rgb) *
2.0 +
COMPAT_TEXTURE(tex, coord + vec2(0.0, offset.y * 2.0)).rgb) /
12.0;
vec3 downsample(sampler2D tex, vec2 coord, vec2 offset) {
// The offset should be 1 source pixel size which equals 0.5 output pixel
// sizes in the default configuration.
return (COMPAT_TEXTURE(tex, mirror_repeat(coord - offset)).rgb +
COMPAT_TEXTURE(tex,
mirror_repeat(coord + vec2(offset.x, -offset.y)))
.rgb +
COMPAT_TEXTURE(tex, mirror_repeat(coord)).rgb * 4.0 +
COMPAT_TEXTURE(tex, mirror_repeat(coord + offset)).rgb +
COMPAT_TEXTURE(tex,
mirror_repeat(coord - vec2(offset.x, -offset.y)))
.rgb) *
0.125;
}

void main() {
vec2 offset = SourceSize.zw * BLUR_RADIUS;
FragColor = vec4(downsample(Source, vTexCoord, offset), 1.0);
}
void main() { FragColor = vec4(downsample(Source, vTexCoord, offset), 1.0); }

#endif
39 changes: 12 additions & 27 deletions blurs/shaders/dual_filter/linearize_and_parameters.glsl
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// This is a copy of ../kawase/linearize.glsl with added parameters for the preset.
// This is a copy of ../kawase/linearize.glsl with added parameters for the
// preset.

// 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 DUAL_FILTER_SETTINGS "=== Dual Filter Blur & Bloom v1.2 settings ===" 0.0 0.0 1.0 1.0
#pragma parameter BLUR_RADIUS "Blur radius" 1.0 0.0 7.5 0.1
// clang-format on

Expand All @@ -12,8 +13,8 @@
#define COMPAT_ATTRIBUTE in
#define COMPAT_TEXTURE texture
#else
#define COMPAT_VARYING varying
#define COMPAT_ATTRIBUTE attribute
#define COMPAT_VARYING varying
#define COMPAT_ATTRIBUTE attribute
#define COMPAT_TEXTURE texture2D
#endif

Expand All @@ -29,23 +30,15 @@ COMPAT_ATTRIBUTE vec4 TexCoord;
COMPAT_VARYING vec4 COL0;
COMPAT_VARYING vec4 TEX0;

vec4 _oPosition1;
vec4 _oPosition1;
uniform mat4 MVPMatrix;
uniform COMPAT_PRECISION int FrameDirection;
uniform COMPAT_PRECISION int FrameCount;
uniform COMPAT_PRECISION vec2 OutputSize;
uniform COMPAT_PRECISION vec2 TextureSize;
uniform COMPAT_PRECISION vec2 InputSize;

// compatibility #defines
#define vTexCoord TEX0.xy
#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
#define OutSize vec4(OutputSize, 1.0 / OutputSize)

void main()
{
void main() {
gl_Position = MVPMatrix * VertexCoord;
TEX0.xy = TexCoord.xy;
vTexCoord = TexCoord.xy;
}

#elif defined(FRAGMENT)
Expand All @@ -71,23 +64,15 @@ out COMPAT_PRECISION vec4 FragColor;
#define COMPAT_TEXTURE texture2D
#endif

uniform COMPAT_PRECISION int FrameDirection;
uniform COMPAT_PRECISION int FrameCount;
uniform COMPAT_PRECISION vec2 OutputSize;
uniform COMPAT_PRECISION vec2 TextureSize;
uniform COMPAT_PRECISION vec2 InputSize;
uniform sampler2D Texture;
COMPAT_VARYING vec4 TEX0;

// compatibility #defines
#define Source Texture
#define vTexCoord TEX0.xy

#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
#define OutSize vec4(OutputSize, 1.0 / OutputSize)
void main() {
FragColor =
pow(vec4(COMPAT_TEXTURE(Source, vTexCoord).rgb, 1.0), vec4(2.2));
}

void main()
{
FragColor = pow(vec4(COMPAT_TEXTURE(Source, vTexCoord).rgb, 1.0), vec4(2.2));
}
#endif
Loading

0 comments on commit fb0162e

Please sign in to comment.