Flutter Engine
 
Loading...
Searching...
No Matches
solid_rsuperellipse_blur_contents.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6#include <optional>
7
15
16namespace impeller {
17
18namespace {
19Vector3 Concat3(Size a, Scalar b) {
20 return {a.width, a.height, b};
21}
22} // namespace
23
25
27
28bool SolidRSuperellipseBlurContents::SetPassInfo(
29 RenderPass& pass,
30 const ContentContext& renderer,
31 PassContext& pass_context) const {
32 using FS = RSuperellipseBlurPipeline::FragmentShader;
33
34 FS::FragInfo frag_info;
35 frag_info.color = GetColor();
36 frag_info.center_adjust = Concat(pass_context.center, pass_context.adjust);
37 frag_info.r1_exponent_exponentInv =
38 Vector3(pass_context.r1, pass_context.exponent, pass_context.exponentInv);
39 frag_info.sInv_minEdge_scale =
40 Vector3(pass_context.sInv, pass_context.minEdge, pass_context.scale);
41
42 // Additional math for RSuperellipse. See the frag file for explanation.
43 Scalar radius = GetCornerRadius();
44 Rect rect = GetRect();
45 RoundSuperellipseParam param =
47
48 // Avoid 0-division error when radius is 0.
49 Scalar retractionDepth = fmax(radius, 0.001);
50
51 frag_info.halfAxes_retractionDepth =
52 Concat3(rect.GetSize() / 2, retractionDepth);
53
54 auto compute_info = [radius](RoundSuperellipseParam::Octant& octant) {
55 if (octant.se_n < 1) { // A rectangular corner
56 // Use a large split_radian, which is equivalent to kPiOver4 but avoids
57 // floating errors.
58 const Scalar kLargeSplitRadian = kPiOver2;
59 const Scalar kReallyLargeN = 1e10;
60 return Vector4(kLargeSplitRadian, 0, kReallyLargeN, -1.0 / kReallyLargeN);
61 }
62 Scalar n = octant.se_n;
63 Point split_point = Point(octant.se_a - radius, octant.se_a);
64 Scalar split_radian = std::atan2(split_point.x, split_point.y);
65 Scalar split_retraction =
66 (1 - pow(1 + pow(tan(split_radian), n), -1.0 / n)) * octant.se_a;
67 return Vector4(split_radian, split_retraction, n, -1.0 / n);
68 };
69 frag_info.infoTop = compute_info(param.top_right.top);
70 frag_info.infoRight = compute_info(param.top_right.right);
71
72 auto compute_poly = [radius](RoundSuperellipseParam::Octant& octant) {
73 // Imperical formula that decreases the initial slope as the a/r ratio
74 // increases.
75 Scalar v0 = radius / octant.se_a * 3;
76 // A polynomial that satisfies f(0) = 1, f'(0) = v0, f(1) = 0, f'(1) = 0
77 return Vector4(v0 + 2.0, -2.0 * v0 - 3.0, v0, 1.0);
78 };
79 frag_info.polyTop = compute_poly(param.top_right.top);
80 frag_info.polyRight = compute_poly(param.top_right.right);
81
82 // Back to pass setup.
83 auto& data_host_buffer = renderer.GetTransientsDataBuffer();
84 pass.SetCommandLabel("RSuperellipse Shadow");
85 pass.SetPipeline(renderer.GetRSuperellipseBlurPipeline(pass_context.opts));
86
87 FS::BindFragInfo(pass, data_host_buffer.EmplaceUniform(frag_info));
88 return true;
89}
90
91} // namespace impeller
static Vector4 Concat(Vector2 &a, Vector2 &b)
float Scalar
Definition scalar.h:19
TRect< Scalar > Rect
Definition rect.h:788
TPoint< Scalar > Point
Definition point.h:327
LinePipeline::FragmentShader FS
constexpr float kPiOver2
Definition constants.h:32
TSize< Scalar > Size
Definition size.h:159
static RoundSuperellipseParam MakeBoundsRadius(const Rect &bounds, Scalar radius)