| Flutter Impeller |

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
5 #include "impeller/entity/contents/solid_rsuperellipse_blur_contents.h"
6 #include <optional>
7
8 #include "impeller/entity/contents/content_context.h"
9 #include "impeller/entity/entity.h"
10 #include "impeller/geometry/color.h"
11 #include "impeller/geometry/constants.h"
12 #include "impeller/geometry/round_superellipse_param.h"
13 #include "impeller/renderer/render_pass.h"
14 #include "impeller/renderer/vertex_buffer_builder.h"
15
16 namespace impeller {
17
18 namespace {
19 Vector3 Concat3(Size a, Scalar b) {
20 return {a.width, a.height, b};
21 }
22 } // namespace
23
24 SolidRSuperellipseBlurContents::SolidRSuperellipseBlurContents() = default;
25
26 SolidRSuperellipseBlurContents::~SolidRSuperellipseBlurContents() = default;
27
28 bool 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 =
46 RoundSuperellipseParam::MakeBoundsRadius(rect, radius);
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
impeller::RenderPipelineHandle::FragmentShader
FragmentShader_ FragmentShader
Definition: pipeline.h:164
impeller::SolidRRectLikeBlurContents::GetColor
Color GetColor() const
Definition: solid_rrect_like_blur_contents.cc:46
impeller::SolidRRectLikeBlurContents::Concat
static Vector4 Concat(Vector2 &a, Vector2 &b)
Definition: solid_rrect_like_blur_contents.cc:193
impeller::SolidRRectLikeBlurContents::GetCornerRadius
Scalar GetCornerRadius() const
Definition: solid_rrect_like_blur_contents.h:66
impeller::SolidRRectLikeBlurContents::GetRect
Rect GetRect() const
Definition: solid_rrect_like_blur_contents.h:65
impeller::SolidRSuperellipseBlurContents::SolidRSuperellipseBlurContents
SolidRSuperellipseBlurContents()
impeller::SolidRSuperellipseBlurContents::~SolidRSuperellipseBlurContents
~SolidRSuperellipseBlurContents() override
color.h
content_context.h
entity.h
constants.h
impeller::saturated::b
SI b
Definition: saturated_math.h:87
impeller
Definition: allocation.cc:12
impeller::Scalar
float Scalar
Definition: scalar.h:19
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:788
impeller::Point
TPoint< Scalar > Point
Definition: point.h:327
impeller::FS
LinePipeline::FragmentShader FS
Definition: line_contents.cc:14
impeller::kPiOver2
constexpr float kPiOver2
Definition: constants.h:32
impeller::Size
TSize< Scalar > Size
Definition: size.h:159
render_pass.h
round_superellipse_param.h
solid_rsuperellipse_blur_contents.h
impeller::RoundSuperellipseParam::MakeBoundsRadius
static RoundSuperellipseParam MakeBoundsRadius(const Rect &bounds, Scalar radius)
Definition: round_superellipse_param.cc:481
vertex_buffer_builder.h