From 37db60d8e29a194cfe343d2578a5b1aff5a10641 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Wed, 26 Oct 2022 04:54:43 -0700 Subject: [PATCH] Move gaussian routines into the shader library --- ci/licenses_golden/licenses_flutter | 1 + .../shader_lib/impeller/constants.glsl | 3 ++ .../shader_lib/impeller/gaussian.glsl | 35 +++++++++++++++++++ impeller/entity/shaders/border_mask_blur.frag | 27 +++----------- impeller/entity/shaders/gaussian_blur.frag | 8 ++--- 5 files changed, 46 insertions(+), 28 deletions(-) create mode 100644 impeller/compiler/shader_lib/impeller/gaussian.glsl diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index da4791076b283..c225182016aa6 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1107,6 +1107,7 @@ FILE: ../../../flutter/impeller/compiler/shader_lib/impeller/blending.glsl FILE: ../../../flutter/impeller/compiler/shader_lib/impeller/branching.glsl FILE: ../../../flutter/impeller/compiler/shader_lib/impeller/color.glsl FILE: ../../../flutter/impeller/compiler/shader_lib/impeller/constants.glsl +FILE: ../../../flutter/impeller/compiler/shader_lib/impeller/gaussian.glsl FILE: ../../../flutter/impeller/compiler/shader_lib/impeller/texture.glsl FILE: ../../../flutter/impeller/compiler/shader_lib/impeller/transform.glsl FILE: ../../../flutter/impeller/compiler/shader_lib/impeller/types.glsl diff --git a/impeller/compiler/shader_lib/impeller/constants.glsl b/impeller/compiler/shader_lib/impeller/constants.glsl index 0ead4981f6411..fe9367a926eae 100644 --- a/impeller/compiler/shader_lib/impeller/constants.glsl +++ b/impeller/compiler/shader_lib/impeller/constants.glsl @@ -13,4 +13,7 @@ const float k1Over2Pi = 0.1591549430918; // sqrt(2 * pi) const float kSqrtTwoPi = 2.50662827463; +// sqrt(2) / 2 == 1 / sqrt(2) +const float kHalfSqrtTwo = 0.70710678118; + #endif diff --git a/impeller/compiler/shader_lib/impeller/gaussian.glsl b/impeller/compiler/shader_lib/impeller/gaussian.glsl new file mode 100644 index 0000000000000..19dce44745ced --- /dev/null +++ b/impeller/compiler/shader_lib/impeller/gaussian.glsl @@ -0,0 +1,35 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GAUSSIAN_GLSL_ +#define GAUSSIAN_GLSL_ + +#include + +float IPGaussian(float x, float sigma) { + float variance = sigma * sigma; + return exp(-0.5 * x * x / variance) / (kSqrtTwoPi * sigma); +} + +/// Abramowitz and Stegun erf approximation. +float IPErf(float x) { + float a = abs(x); + // 0.278393*x + 0.230389*x^2 + 0.078108*x^4 + 1 + float b = (0.278393 + (0.230389 + 0.078108 * a * a) * a) * a + 1.0; + return sign(x) * (1 - 1 / (b * b * b * b)); +} + +vec2 IPVec2Erf(vec2 x) { + return vec2(IPErf(x.x), IPErf(x.y)); +} + +/// Indefinite integral of the Gaussian function (with constant range 0->1). +float IPGaussianIntegral(float x, float sigma) { + // ( 1 + erf( x * (sqrt(2) / (2 * sigma) ) ) / 2 + // Because this sigmoid is always > 1, we remap it (n * 1.07 - 0.07) + // so that it always fades to zero before it reaches the blur radius. + return 0.535 * IPErf(x * (kHalfSqrtTwo / sigma)) + 0.465; +} + +#endif diff --git a/impeller/entity/shaders/border_mask_blur.frag b/impeller/entity/shaders/border_mask_blur.frag index d35280f8dfecf..e9b56fa3cfe0a 100644 --- a/impeller/entity/shaders/border_mask_blur.frag +++ b/impeller/entity/shaders/border_mask_blur.frag @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include #include // Constant time mask blur for image borders. @@ -27,30 +28,12 @@ in float v_outer_blur_factor; out vec4 frag_color; -// Abramowitz and Stegun erf approximation. -float erf(float x) { - float a = abs(x); - // 0.278393*x + 0.230389*x^2 + 0.078108*x^4 + 1 - float b = (0.278393 + (0.230389 + 0.078108 * a * a) * a) * a + 1.0; - return sign(x) * (1 - 1 / (b * b * b * b)); -} - -const float kHalfSqrtTwo = 0.70710678118; - -// Indefinite integral of the Gaussian function (with constant range 0->1). -float GaussianIntegral(float x, float sigma) { - // ( 1 + erf( x * (sqrt(2) / (2 * sigma) ) ) / 2 - // Because this sigmoid is always > 1, we remap it (n * 1.07 - 0.07) - // so that it always fades to zero before it reaches the blur radius. - return 0.535 * erf(x * (kHalfSqrtTwo / sigma)) + 0.465; -} - float BoxBlurMask(vec2 uv) { // LTRB - return GaussianIntegral(uv.x, v_sigma_uv.x) * // - GaussianIntegral(uv.y, v_sigma_uv.y) * // - GaussianIntegral(1 - uv.x, v_sigma_uv.x) * // - GaussianIntegral(1 - uv.y, v_sigma_uv.y); + return IPGaussianIntegral(uv.x, v_sigma_uv.x) * // + IPGaussianIntegral(uv.y, v_sigma_uv.y) * // + IPGaussianIntegral(1 - uv.x, v_sigma_uv.x) * // + IPGaussianIntegral(1 - uv.y, v_sigma_uv.y); } void main() { diff --git a/impeller/entity/shaders/gaussian_blur.frag b/impeller/entity/shaders/gaussian_blur.frag index ec099a6965bc4..06bd0f389ff47 100644 --- a/impeller/entity/shaders/gaussian_blur.frag +++ b/impeller/entity/shaders/gaussian_blur.frag @@ -14,6 +14,7 @@ // level of log2(min_radius). #include +#include #include uniform sampler2D texture_sampler; @@ -46,18 +47,13 @@ in vec2 v_src_texture_coords; out vec4 frag_color; -float Gaussian(float x) { - float variance = frag_info.blur_sigma * frag_info.blur_sigma; - return exp(-0.5 * x * x / variance) / (kSqrtTwoPi * frag_info.blur_sigma); -} - void main() { vec4 total_color = vec4(0); float gaussian_integral = 0; vec2 blur_uv_offset = frag_info.blur_direction / frag_info.texture_size; for (float i = -frag_info.blur_radius; i <= frag_info.blur_radius; i++) { - float gaussian = Gaussian(i); + float gaussian = IPGaussian(i, frag_info.blur_sigma); gaussian_integral += gaussian; total_color += gaussian *