Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Functions | Variables
SkDrawShadowMetrics Namespace Reference

Functions

static SkScalar compute_z (SkScalar x, SkScalar y, const SkPoint3 &params)
 
bool GetSpotShadowTransform (const SkPoint3 &lightPos, SkScalar lightRadius, const SkMatrix &ctm, const SkPoint3 &zPlaneParams, const SkRect &pathBounds, bool directional, SkMatrix *shadowTransform, SkScalar *radius)
 
void GetLocalBounds (const SkPath &path, const SkDrawShadowRec &rec, const SkMatrix &ctm, SkRect *bounds)
 
static float divide_and_pin (float numer, float denom, float min, float max)
 
SkScalar AmbientBlurRadius (SkScalar height)
 
SkScalar AmbientRecipAlpha (SkScalar height)
 
SkScalar SpotBlurRadius (SkScalar occluderZ, SkScalar lightZ, SkScalar lightRadius)
 
void GetSpotParams (SkScalar occluderZ, SkScalar lightX, SkScalar lightY, SkScalar lightZ, SkScalar lightRadius, SkScalar *blurRadius, SkScalar *scale, SkVector *translate)
 
void GetDirectionalParams (SkScalar occluderZ, SkScalar lightX, SkScalar lightY, SkScalar lightZ, SkScalar lightRadius, SkScalar *blurRadius, SkScalar *scale, SkVector *translate)
 

Variables

static constexpr auto kAmbientHeightFactor = 1.0f / 128.0f
 
static constexpr auto kAmbientGeomFactor = 64.0f
 
static constexpr auto kMaxAmbientRadius = 300*kAmbientHeightFactor*kAmbientGeomFactor
 

Function Documentation

◆ AmbientBlurRadius()

SkScalar SkDrawShadowMetrics::AmbientBlurRadius ( SkScalar  height)
inline

Definition at line 51 of file SkDrawShadowInfo.h.

51 {
52 return std::min(height*kAmbientHeightFactor*kAmbientGeomFactor, kMaxAmbientRadius);
53}
int32_t height

◆ AmbientRecipAlpha()

SkScalar SkDrawShadowMetrics::AmbientRecipAlpha ( SkScalar  height)
inline

Definition at line 55 of file SkDrawShadowInfo.h.

55 {
56 return 1.0f + std::max(height*kAmbientHeightFactor, 0.0f);
57}

◆ compute_z()

static SkScalar SkDrawShadowMetrics::compute_z ( SkScalar  x,
SkScalar  y,
const SkPoint3 params 
)
static

Definition at line 18 of file SkDrawShadowInfo.cpp.

18 {
19 return x*params.fX + y*params.fY + params.fZ;
20}
const EmbeddedViewParams * params
double y
double x

◆ divide_and_pin()

static float SkDrawShadowMetrics::divide_and_pin ( float  numer,
float  denom,
float  min,
float  max 
)
inlinestatic

Definition at line 44 of file SkDrawShadowInfo.h.

44 {
45 float result = SkTPin(sk_ieee_float_divide(numer, denom), min, max);
46 // ensure that SkTPin handled non-finites correctly
47 SkASSERT(result >= min && result <= max);
48 return result;
49}
#define SkASSERT(cond)
Definition SkAssert.h:116
static constexpr float sk_ieee_float_divide(float numer, float denom)
static constexpr const T & SkTPin(const T &x, const T &lo, const T &hi)
Definition SkTPin.h:19
GAsyncResult * result
static float max(float r, float g, float b)
Definition hsl.cpp:49
static float min(float r, float g, float b)
Definition hsl.cpp:48

◆ GetDirectionalParams()

void SkDrawShadowMetrics::GetDirectionalParams ( SkScalar  occluderZ,
SkScalar  lightX,
SkScalar  lightY,
SkScalar  lightZ,
SkScalar  lightRadius,
SkScalar blurRadius,
SkScalar scale,
SkVector translate 
)
inline

Definition at line 72 of file SkDrawShadowInfo.h.

74 {
75 *blurRadius = lightRadius*occluderZ;
76 *scale = 1;
77 // Max z-ratio is "max expected elevation"/"min allowable z"
78 constexpr SkScalar kMaxZRatio = 64/SK_ScalarNearlyZero;
79 SkScalar zRatio = divide_and_pin(occluderZ, lightZ, 0.0f, kMaxZRatio);
80 *translate = SkVector::Make(-zRatio * lightX, -zRatio * lightY);
81}
#define SK_ScalarNearlyZero
Definition SkScalar.h:99
float SkScalar
Definition extension.cpp:12
static float divide_and_pin(float numer, float denom, float min, float max)
const Scalar scale
static constexpr SkPoint Make(float x, float y)

◆ GetLocalBounds()

void SkDrawShadowMetrics::GetLocalBounds ( const SkPath path,
const SkDrawShadowRec rec,
const SkMatrix ctm,
SkRect bounds 
)

Definition at line 124 of file SkDrawShadowInfo.cpp.

125 {
126 SkRect ambientBounds = path.getBounds();
127 SkScalar occluderZ;
129 occluderZ = rec.fZPlaneParams.fZ;
130 } else {
131 occluderZ = compute_z(ambientBounds.fLeft, ambientBounds.fTop, rec.fZPlaneParams);
132 occluderZ = std::max(occluderZ, compute_z(ambientBounds.fRight, ambientBounds.fTop,
133 rec.fZPlaneParams));
134 occluderZ = std::max(occluderZ, compute_z(ambientBounds.fLeft, ambientBounds.fBottom,
135 rec.fZPlaneParams));
136 occluderZ = std::max(occluderZ, compute_z(ambientBounds.fRight, ambientBounds.fBottom,
137 rec.fZPlaneParams));
138 }
139 SkScalar ambientBlur;
140 SkScalar spotBlur;
141 SkScalar spotScale;
142 SkPoint spotOffset;
143 if (ctm.hasPerspective()) {
144 // transform ambient and spot bounds into device space
145 ctm.mapRect(&ambientBounds);
146
147 // get ambient blur (in device space)
148 ambientBlur = SkDrawShadowMetrics::AmbientBlurRadius(occluderZ);
149
150 // get spot params (in device space)
153 rec.fLightPos.fZ, rec.fLightRadius,
154 &spotBlur, &spotScale, &spotOffset);
155 } else {
156 SkPoint devLightPos = SkPoint::Make(rec.fLightPos.fX, rec.fLightPos.fY);
157 ctm.mapPoints(&devLightPos, 1);
158 SkDrawShadowMetrics::GetSpotParams(occluderZ, devLightPos.fX, devLightPos.fY,
159 rec.fLightPos.fZ, rec.fLightRadius,
160 &spotBlur, &spotScale, &spotOffset);
161 }
162 } else {
163 SkScalar devToSrcScale = SkScalarInvert(ctm.getMinScale());
164
165 // get ambient blur (in local space)
166 SkScalar devSpaceAmbientBlur = SkDrawShadowMetrics::AmbientBlurRadius(occluderZ);
167 ambientBlur = devSpaceAmbientBlur*devToSrcScale;
168
169 // get spot params (in local space)
172 rec.fLightPos.fZ, rec.fLightRadius,
173 &spotBlur, &spotScale, &spotOffset);
174 // light dir is in device space, so need to map spot offset back into local space
175 SkMatrix inverse;
176 if (ctm.invert(&inverse)) {
177 inverse.mapVectors(&spotOffset, 1);
178 }
179 } else {
181 rec.fLightPos.fZ, rec.fLightRadius,
182 &spotBlur, &spotScale, &spotOffset);
183 }
184
185 // convert spot blur to local space
186 spotBlur *= devToSrcScale;
187 }
188
189 // in both cases, adjust ambient and spot bounds
190 SkRect spotBounds = ambientBounds;
191 ambientBounds.outset(ambientBlur, ambientBlur);
192 spotBounds.fLeft *= spotScale;
193 spotBounds.fTop *= spotScale;
194 spotBounds.fRight *= spotScale;
195 spotBounds.fBottom *= spotScale;
196 spotBounds.offset(spotOffset.fX, spotOffset.fY);
197 spotBounds.outset(spotBlur, spotBlur);
198
199 // merge bounds
200 *bounds = ambientBounds;
201 bounds->join(spotBounds);
202 // outset a bit to account for floating point error
203 bounds->outset(1, 1);
204
205 // if perspective, transform back to src space
206 if (ctm.hasPerspective()) {
207 // TODO: create tighter mapping from dev rect back to src rect
208 SkMatrix inverse;
209 if (ctm.invert(&inverse)) {
210 inverse.mapRect(bounds);
211 }
212 }
213}
#define SkScalarInvert(x)
Definition SkScalar.h:73
static bool SkScalarNearlyZero(SkScalar x, SkScalar tolerance=SK_ScalarNearlyZero)
Definition SkScalar.h:101
@ kDirectionalLight_ShadowFlag
static constexpr bool SkToBool(const T &x)
Definition SkTo.h:35
void mapVectors(SkVector dst[], const SkVector src[], int count) const
void mapPoints(SkPoint dst[], const SkPoint src[], int count) const
Definition SkMatrix.cpp:770
bool invert(SkMatrix *inverse) const
Definition SkMatrix.h:1206
SkScalar getMinScale() const
bool hasPerspective() const
Definition SkMatrix.h:312
bool mapRect(SkRect *dst, const SkRect &src, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
void GetDirectionalParams(SkScalar occluderZ, SkScalar lightX, SkScalar lightY, SkScalar lightZ, SkScalar lightRadius, SkScalar *blurRadius, SkScalar *scale, SkVector *translate)
SkScalar AmbientBlurRadius(SkScalar height)
void GetSpotParams(SkScalar occluderZ, SkScalar lightX, SkScalar lightY, SkScalar lightZ, SkScalar lightRadius, SkScalar *blurRadius, SkScalar *scale, SkVector *translate)
Optional< SkRect > bounds
Definition SkRecords.h:189
SkScalar fX
Definition SkPoint3.h:16
SkScalar fZ
Definition SkPoint3.h:16
SkScalar fY
Definition SkPoint3.h:16
float fX
x-axis value
float fY
y-axis value
SkScalar fBottom
larger y-axis bounds
Definition extension.cpp:17
SkScalar fLeft
smaller x-axis bounds
Definition extension.cpp:14
void outset(float dx, float dy)
Definition SkRect.h:1077
SkScalar fRight
larger x-axis bounds
Definition extension.cpp:16
void offset(float dx, float dy)
Definition SkRect.h:1016
SkScalar fTop
smaller y-axis bounds
Definition extension.cpp:15

◆ GetSpotParams()

void SkDrawShadowMetrics::GetSpotParams ( SkScalar  occluderZ,
SkScalar  lightX,
SkScalar  lightY,
SkScalar  lightZ,
SkScalar  lightRadius,
SkScalar blurRadius,
SkScalar scale,
SkVector translate 
)
inline

Definition at line 63 of file SkDrawShadowInfo.h.

65 {
66 SkScalar zRatio = divide_and_pin(occluderZ, lightZ - occluderZ, 0.0f, 0.95f);
67 *blurRadius = lightRadius*zRatio;
68 *scale = divide_and_pin(lightZ, lightZ - occluderZ, 1.0f, 1.95f);
69 *translate = SkVector::Make(-zRatio * lightX, -zRatio * lightY);
70}

◆ GetSpotShadowTransform()

bool SkDrawShadowMetrics::GetSpotShadowTransform ( const SkPoint3 lightPos,
SkScalar  lightRadius,
const SkMatrix ctm,
const SkPoint3 zPlaneParams,
const SkRect pathBounds,
bool  directional,
SkMatrix shadowTransform,
SkScalar radius 
)

Definition at line 22 of file SkDrawShadowInfo.cpp.

25 {
26 auto heightFunc = [zPlaneParams] (SkScalar x, SkScalar y) {
27 return zPlaneParams.fX*x + zPlaneParams.fY*y + zPlaneParams.fZ;
28 };
29 SkScalar occluderHeight = heightFunc(pathBounds.centerX(), pathBounds.centerY());
30
31 // TODO: have directional lights support tilt via the zPlaneParams
32 if (!ctm.hasPerspective() || directional) {
34 SkVector translate;
35 if (directional) {
36 SkDrawShadowMetrics::GetDirectionalParams(occluderHeight, lightPos.fX, lightPos.fY,
37 lightPos.fZ, lightRadius, radius,
38 &scale, &translate);
39 } else {
40 SkDrawShadowMetrics::GetSpotParams(occluderHeight, lightPos.fX, lightPos.fY,
41 lightPos.fZ, lightRadius, radius,
42 &scale, &translate);
43 }
44 shadowTransform->setScaleTranslate(scale, scale, translate.fX, translate.fY);
45 shadowTransform->preConcat(ctm);
46 } else {
47 if (SkScalarNearlyZero(pathBounds.width()) || SkScalarNearlyZero(pathBounds.height())) {
48 return false;
49 }
50
51 // get rotated quad in 3D
52 SkPoint pts[4];
53 ctm.mapRectToQuad(pts, pathBounds);
54
55 SkPoint3 pts3D[4];
56 SkScalar z = heightFunc(pathBounds.fLeft, pathBounds.fTop);
57 pts3D[0].set(pts[0].fX, pts[0].fY, z);
58 z = heightFunc(pathBounds.fRight, pathBounds.fTop);
59 pts3D[1].set(pts[1].fX, pts[1].fY, z);
60 z = heightFunc(pathBounds.fRight, pathBounds.fBottom);
61 pts3D[2].set(pts[2].fX, pts[2].fY, z);
62 z = heightFunc(pathBounds.fLeft, pathBounds.fBottom);
63 pts3D[3].set(pts[3].fX, pts[3].fY, z);
64
65 // project from light through corners to z=0 plane
66 for (int i = 0; i < 4; ++i) {
67 SkScalar dz = lightPos.fZ - pts3D[i].fZ;
68 // light shouldn't be below or at a corner's z-location
69 if (dz <= SK_ScalarNearlyZero) {
70 return false;
71 }
72 SkScalar zRatio = pts3D[i].fZ / dz;
73 pts3D[i].fX -= (lightPos.fX - pts3D[i].fX)*zRatio;
74 pts3D[i].fY -= (lightPos.fY - pts3D[i].fY)*zRatio;
75 pts3D[i].fZ = SK_Scalar1;
76 }
77
78 // Generate matrix that projects from [-1,1]x[-1,1] square to projected quad
79 SkPoint3 h0, h1, h2;
80 // Compute homogenous crossing point between top and bottom edges (gives new x-axis).
81 h0 = (pts3D[1].cross(pts3D[0])).cross(pts3D[2].cross(pts3D[3]));
82 // Compute homogenous crossing point between left and right edges (gives new y-axis).
83 h1 = (pts3D[0].cross(pts3D[3])).cross(pts3D[1].cross(pts3D[2]));
84 // Compute homogenous crossing point between diagonals (gives new origin).
85 h2 = (pts3D[0].cross(pts3D[2])).cross(pts3D[1].cross(pts3D[3]));
86 // If h2 is a vector (z=0 in 2D homogeneous space), that means that at least
87 // two of the quad corners are coincident and we don't have a realistic projection
88 if (SkScalarNearlyZero(h2.fZ)) {
89 return false;
90 }
91 // In some cases the crossing points are in the wrong direction
92 // to map (-1,-1) to pts3D[0], so we need to correct for that.
93 // Want h0 to be to the right of the left edge.
94 SkVector3 v = pts3D[3] - pts3D[0];
95 SkVector3 w = h0 - pts3D[0];
96 SkScalar perpDot = v.fX*w.fY - v.fY*w.fX;
97 if (perpDot > 0) {
98 h0 = -h0;
99 }
100 // Want h1 to be above the bottom edge.
101 v = pts3D[1] - pts3D[0];
102 perpDot = v.fX*w.fY - v.fY*w.fX;
103 if (perpDot < 0) {
104 h1 = -h1;
105 }
106 shadowTransform->setAll(h0.fX / h2.fZ, h1.fX / h2.fZ, h2.fX / h2.fZ,
107 h0.fY / h2.fZ, h1.fY / h2.fZ, h2.fY / h2.fZ,
108 h0.fZ / h2.fZ, h1.fZ / h2.fZ, 1);
109 // generate matrix that transforms from bounds to [-1,1]x[-1,1] square
110 SkMatrix toHomogeneous;
111 SkScalar xScale = 2/(pathBounds.fRight - pathBounds.fLeft);
112 SkScalar yScale = 2/(pathBounds.fBottom - pathBounds.fTop);
113 toHomogeneous.setAll(xScale, 0, -xScale*pathBounds.fLeft - 1,
114 0, yScale, -yScale*pathBounds.fTop - 1,
115 0, 0, 1);
116 shadowTransform->preConcat(toHomogeneous);
117
118 *radius = SkDrawShadowMetrics::SpotBlurRadius(occluderHeight, lightPos.fZ, lightRadius);
119 }
120
121 return true;
122}
#define SK_Scalar1
Definition SkScalar.h:18
SkMatrix & setAll(SkScalar scaleX, SkScalar skewX, SkScalar transX, SkScalar skewY, SkScalar scaleY, SkScalar transY, SkScalar persp0, SkScalar persp1, SkScalar persp2)
Definition SkMatrix.h:562
void setScaleTranslate(SkScalar sx, SkScalar sy, SkScalar tx, SkScalar ty)
Definition SkMatrix.h:1803
SkMatrix & preConcat(const SkMatrix &other)
Definition SkMatrix.cpp:674
void mapRectToQuad(SkPoint dst[4], const SkRect &rect) const
Definition SkMatrix.h:1620
SkScalar SpotBlurRadius(SkScalar occluderZ, SkScalar lightZ, SkScalar lightRadius)
int64_t cross(Point d0, Point d1)
Definition Myers.cpp:55
SkScalar w
SkPoint3 cross(const SkPoint3 &vec) const
Definition SkPoint3.h:141
void set(SkScalar x, SkScalar y, SkScalar z)
Definition SkPoint3.h:28
constexpr float centerX() const
Definition SkRect.h:776
constexpr float height() const
Definition SkRect.h:769
constexpr float centerY() const
Definition SkRect.h:785
constexpr float width() const
Definition SkRect.h:762

◆ SpotBlurRadius()

SkScalar SkDrawShadowMetrics::SpotBlurRadius ( SkScalar  occluderZ,
SkScalar  lightZ,
SkScalar  lightRadius 
)
inline

Definition at line 59 of file SkDrawShadowInfo.h.

59 {
60 return lightRadius*divide_and_pin(occluderZ, lightZ - occluderZ, 0.0f, 0.95f);
61}

Variable Documentation

◆ kAmbientGeomFactor

constexpr auto SkDrawShadowMetrics::kAmbientGeomFactor = 64.0f
staticconstexpr

Definition at line 38 of file SkDrawShadowInfo.h.

◆ kAmbientHeightFactor

constexpr auto SkDrawShadowMetrics::kAmbientHeightFactor = 1.0f / 128.0f
staticconstexpr

Definition at line 37 of file SkDrawShadowInfo.h.

◆ kMaxAmbientRadius

constexpr auto SkDrawShadowMetrics::kMaxAmbientRadius = 300*kAmbientHeightFactor*kAmbientGeomFactor
staticconstexpr

Definition at line 42 of file SkDrawShadowInfo.h.