Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit f642511

Browse files
committed
[Impeller] Increase 2-pass blur quality and distribution limit
1 parent 1c775e3 commit f642511

File tree

4 files changed

+25
-11
lines changed

4 files changed

+25
-11
lines changed

impeller/compiler/shader_lib/impeller/gaussian.glsl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,13 @@
99
#include <impeller/types.glsl>
1010

1111
/// Gaussian distribution function.
12-
float16_t IPGaussian(float16_t x, float16_t sigma) {
12+
float IPGaussian(float x, float sigma) {
13+
float variance = sigma * sigma;
14+
return exp(-0.5f * x * x / variance) / (kSqrtTwoPi * sigma);
15+
}
16+
17+
/// Gaussian distribution function.
18+
float16_t IPHalfGaussian(float16_t x, float16_t sigma) {
1319
float16_t variance = sigma * sigma;
1420
return exp(-0.5hf * x * x / variance) / (float16_t(kSqrtTwoPi) * sigma);
1521
}

impeller/entity/entity_unittests.cc

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,7 +1004,8 @@ TEST_P(EntityTest, GaussianBlurFilter) {
10041004
static Color input_color = Color::Black();
10051005
static int selected_blur_type = 0;
10061006
static int selected_pass_variation = 0;
1007-
static float blur_amount[2] = {10, 10};
1007+
static float blur_amount_coarse[2] = {0, 0};
1008+
static float blur_amount_fine[2] = {10, 10};
10081009
static int selected_blur_style = 0;
10091010
static int selected_tile_mode = 3;
10101011
static Color cover_color(1, 0, 0, 0.2);
@@ -1034,7 +1035,8 @@ TEST_P(EntityTest, GaussianBlurFilter) {
10341035
pass_variation_names,
10351036
sizeof(pass_variation_names) / sizeof(char*));
10361037
}
1037-
ImGui::SliderFloat2("Sigma", blur_amount, 0, 10);
1038+
ImGui::SliderFloat2("Sigma (coarse)", blur_amount_coarse, 0, 1000);
1039+
ImGui::SliderFloat2("Sigma (fine)", blur_amount_fine, 0, 10);
10381040
ImGui::Combo("Blur style", &selected_blur_style, blur_style_names,
10391041
sizeof(blur_style_names) / sizeof(char*));
10401042
ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
@@ -1051,6 +1053,9 @@ TEST_P(EntityTest, GaussianBlurFilter) {
10511053
}
10521054
ImGui::End();
10531055

1056+
auto blur_sigma_x = Sigma{blur_amount_coarse[0] + blur_amount_fine[0]};
1057+
auto blur_sigma_y = Sigma{blur_amount_coarse[1] + blur_amount_fine[1]};
1058+
10541059
std::shared_ptr<Contents> input;
10551060
Size input_size;
10561061

@@ -1078,18 +1083,17 @@ TEST_P(EntityTest, GaussianBlurFilter) {
10781083
std::shared_ptr<FilterContents> blur;
10791084
if (selected_pass_variation == 0) {
10801085
blur = FilterContents::MakeGaussianBlur(
1081-
FilterInput::Make(input), Sigma{blur_amount[0]},
1082-
Sigma{blur_amount[1]}, blur_styles[selected_blur_style],
1083-
tile_modes[selected_tile_mode]);
1086+
FilterInput::Make(input), blur_sigma_x, blur_sigma_y,
1087+
blur_styles[selected_blur_style], tile_modes[selected_tile_mode]);
10841088
} else {
1085-
Vector2 blur_vector(blur_amount[0], blur_amount[1]);
1089+
Vector2 blur_vector(blur_sigma_x.sigma, blur_sigma_y.sigma);
10861090
blur = FilterContents::MakeDirectionalGaussianBlur(
10871091
FilterInput::Make(input), Sigma{blur_vector.GetLength()},
10881092
blur_vector.Normalize());
10891093
}
10901094

10911095
auto mask_blur = FilterContents::MakeBorderMaskBlur(
1092-
FilterInput::Make(input), Sigma{blur_amount[0]}, Sigma{blur_amount[1]},
1096+
FilterInput::Make(input), blur_sigma_x, blur_sigma_y,
10931097
blur_styles[selected_blur_style]);
10941098

10951099
auto ctm = Matrix::MakeScale(GetContentScale()) *

impeller/entity/shaders/gaussian_blur/gaussian_blur.glsl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ uniform BlurInfo {
2727
// host-side, but both are useful controls here. Sigma (pixels per standard
2828
// deviation) is used to define the gaussian function itself, whereas the
2929
// radius is used to limit how much of the function is integrated.
30-
float16_t blur_sigma;
30+
float blur_sigma;
3131
float16_t blur_radius;
3232
}
3333
blur_info;
@@ -62,7 +62,11 @@ void main() {
6262

6363
for (float16_t i = -blur_info.blur_radius; i <= blur_info.blur_radius;
6464
i += 2.0hf) {
65-
float16_t gaussian = IPGaussian(i, blur_info.blur_sigma);
65+
// Use the 32 bit Gaussian function because the 16 bit variation results in
66+
// quality loss/visible banding. Also, 16 bit variation internally breaks
67+
// down at a moderately high (but still reasonable) blur sigma of >255 when
68+
// computing sigma^2 due to the exponent only having 5 bits.
69+
float16_t gaussian = float16_t(IPGaussian(float(i), blur_info.blur_sigma));
6670
gaussian_integral += gaussian;
6771
total_color +=
6872
gaussian * Sample(texture_sampler, // sampler

impeller/entity/shaders/rrect_blur.frag

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ float16_t RRectShadow(f16vec2 sample_position, f16vec2 half_size) {
6262
float16_t y = begin_y + interval * (float16_t(sample_i) + 0.5hf);
6363
result += RRectShadowX(f16vec2(sample_position.x, sample_position.y - y),
6464
half_size) *
65-
IPGaussian(y, frag_info.blur_sigma) * interval;
65+
IPHalfGaussian(y, frag_info.blur_sigma) * interval;
6666
}
6767

6868
return result;

0 commit comments

Comments
 (0)