diff --git a/impeller/compiler/shader_lib/impeller/gaussian.glsl b/impeller/compiler/shader_lib/impeller/gaussian.glsl index e98cdc6298c69..f5ab4b9c7bdb7 100644 --- a/impeller/compiler/shader_lib/impeller/gaussian.glsl +++ b/impeller/compiler/shader_lib/impeller/gaussian.glsl @@ -52,7 +52,12 @@ f16vec2 IPVec2GaussianIntegral(f16vec2 x, float16_t sigma) { } /// Simpler (but less accurate) approximation of the Gaussian integral. -f16vec2 IPVec2FastGaussianIntegral(f16vec2 x, float16_t sigma) { +vec2 IPVec2FastGaussianIntegral(vec2 x, float sigma) { + return 1.0 / (1.0 + exp(-kSqrtThree / sigma * x)); +} + +/// Simpler (but less accurate) approximation of the Gaussian integral. +f16vec2 IPHalfVec2FastGaussianIntegral(f16vec2 x, float16_t sigma) { return 1.0hf / (1.0hf + exp(float16_t(-kSqrtThree) / sigma * x)); } diff --git a/impeller/entity/shaders/rrect_blur.frag b/impeller/entity/shaders/rrect_blur.frag index 3f72925573050..8a12da3e42fad 100644 --- a/impeller/entity/shaders/rrect_blur.frag +++ b/impeller/entity/shaders/rrect_blur.frag @@ -7,9 +7,9 @@ uniform FragInfo { f16vec4 color; - f16vec2 rect_size; - float16_t blur_sigma; - float16_t corner_radius; + vec2 rect_size; + float blur_sigma; + float corner_radius; } frag_info; @@ -19,50 +19,47 @@ out f16vec4 frag_color; const int kSampleCount = 4; -float16_t RRectDistance(f16vec2 sample_position, f16vec2 half_size) { - f16vec2 space = abs(sample_position) - half_size + frag_info.corner_radius; - return length(max(space, float16_t(0.0hf))) + - min(max(space.x, space.y), float16_t(0.0hf)) - frag_info.corner_radius; +float16_t RRectDistance(vec2 sample_position, vec2 half_size) { + vec2 space = abs(sample_position) - half_size + frag_info.corner_radius; + return float16_t(length(max(space, 0.0)) + min(max(space.x, space.y), 0.0) - + frag_info.corner_radius); } /// Closed form unidirectional rounded rect blur mask solution using the /// analytical Gaussian integral (with approximated erf). -float16_t RRectBlurX(f16vec2 sample_position, f16vec2 half_size) { +float RRectBlurX(vec2 sample_position, vec2 half_size) { // Compute the X direction distance field (not incorporating the Y distance) // for the rounded rect. - float16_t space = - min(float16_t(0.0hf), - half_size.y - frag_info.corner_radius - abs(sample_position.y)); - float16_t rrect_distance = + float space = + min(0.0, half_size.y - frag_info.corner_radius - abs(sample_position.y)); + float rrect_distance = half_size.x - frag_info.corner_radius + - sqrt(max( - float16_t(0.0hf), - frag_info.corner_radius * frag_info.corner_radius - space * space)); + sqrt(max(0.0, frag_info.corner_radius * frag_info.corner_radius - + space * space)); // Map the linear distance field to the approximate Gaussian integral. - f16vec2 integral = IPVec2FastGaussianIntegral( - sample_position.x + f16vec2(-rrect_distance, rrect_distance), - frag_info.blur_sigma); + vec2 integral = IPVec2FastGaussianIntegral( + float(sample_position.x) + vec2(-rrect_distance, rrect_distance), + float(frag_info.blur_sigma)); return integral.y - integral.x; } -float16_t RRectBlur(f16vec2 sample_position, f16vec2 half_size) { +float RRectBlur(vec2 sample_position, vec2 half_size) { // Limit the sampling range to 3 standard deviations in the Y direction from // the kernel center to incorporate 99.7% of the color contribution. - float16_t half_sampling_range = frag_info.blur_sigma * 3.0hf; + float half_sampling_range = frag_info.blur_sigma * 3.0; - float16_t begin_y = - max(-half_sampling_range, sample_position.y - half_size.y); - float16_t end_y = min(half_sampling_range, sample_position.y + half_size.y); - float16_t interval = (end_y - begin_y) / float16_t(kSampleCount); + float begin_y = max(-half_sampling_range, sample_position.y - half_size.y); + float end_y = min(half_sampling_range, sample_position.y + half_size.y); + float interval = (end_y - begin_y) / kSampleCount; // Sample the X blur kSampleCount times, weighted by the Gaussian function. - float16_t result = 0.0hf; + float result = 0.0; for (int sample_i = 0; sample_i < kSampleCount; sample_i++) { - float16_t y = begin_y + interval * (float16_t(sample_i) + 0.5hf); - result += RRectBlurX(f16vec2(sample_position.x, sample_position.y - y), - half_size) * - IPHalfGaussian(y, frag_info.blur_sigma) * interval; + float y = begin_y + interval * (float(sample_i) + 0.5); + result += + RRectBlurX(vec2(sample_position.x, sample_position.y - y), half_size) * + IPGaussian(float(y), float(frag_info.blur_sigma)) * interval; } return result; @@ -71,12 +68,12 @@ float16_t RRectBlur(f16vec2 sample_position, f16vec2 half_size) { void main() { frag_color = frag_info.color; - f16vec2 half_size = frag_info.rect_size * 0.5hf; - f16vec2 sample_position = f16vec2(v_position) - half_size; + vec2 half_size = frag_info.rect_size * 0.5; + vec2 sample_position = v_position - half_size; - if (frag_info.blur_sigma > 0.0hf) { - frag_color *= RRectBlur(sample_position, half_size); + if (frag_info.blur_sigma > 0.0) { + frag_color *= float16_t(RRectBlur(sample_position, half_size)); } else { - frag_color *= -RRectDistance(sample_position, half_size); + frag_color *= float16_t(-RRectDistance(sample_position, half_size)); } }