Remove height functor for shadows and replace with plane equation params
Change-Id: I948eceb2c58dc50468993dba54c209f18e440e48 Reviewed-on: https://skia-review.googlesource.com/15873 Commit-Queue: Jim Van Verth <jvanverth@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com>
This commit is contained in:
parent
6f24180a99
commit
e308a122ef
@ -43,29 +43,65 @@ public:
|
||||
uint32_t flags = SkShadowFlags::kNone_ShadowFlag,
|
||||
SkResourceCache* cache = nullptr);
|
||||
|
||||
/**
|
||||
* Draw an offset spot shadow and outlining ambient shadow for the given path using a disc
|
||||
* light. Takes a function to vary the z value based on the transformed x and y position.
|
||||
* This shadow will not be cached, as the assumption is that this will be used for animation.
|
||||
*
|
||||
* @param canvas The canvas on which to draw the shadows.
|
||||
* @param path The occluder used to generate the shadows.
|
||||
* @param heightFunc A function which returns the vertical offset of the occluder from the
|
||||
* canvas based on local x and y values (the current matrix is not applied).
|
||||
* @param lightPos The 3D position of the light relative to the canvas plane. This is
|
||||
* independent of the canvas's current matrix.
|
||||
* @param lightRadius The radius of the disc light.
|
||||
* @param ambientAlpha The maximum alpha of the ambient shadow.
|
||||
* @param spotAlpha The maxium alpha of the spot shadow.
|
||||
* @param color The shadow color.
|
||||
* @param flags Options controlling opaque occluder optimizations and shadow appearance. See
|
||||
* SkShadowFlags.
|
||||
*/
|
||||
/**
|
||||
* Draw an offset spot shadow and outlining ambient shadow for the given path using a disc
|
||||
* light. Takes a function to vary the z value based on the local x and y position.
|
||||
* This shadow will not be cached, as the assumption is that this will be used for animation.
|
||||
*
|
||||
* Deprecated version with height functor (to be removed when Android is updated).
|
||||
*
|
||||
* @param canvas The canvas on which to draw the shadows.
|
||||
* @param path The occluder used to generate the shadows.
|
||||
* @param heightFunc A function which returns the vertical offset of the occluder from the
|
||||
* canvas based on local x and y values (the current matrix is not applied).
|
||||
* @param lightPos The 3D position of the light relative to the canvas plane. This is
|
||||
* independent of the canvas's current matrix.
|
||||
* @param lightRadius The radius of the disc light.
|
||||
* @param ambientAlpha The maximum alpha of the ambient shadow.
|
||||
* @param spotAlpha The maxium alpha of the spot shadow.
|
||||
* @param color The shadow color.
|
||||
* @param flags Options controlling opaque occluder optimizations and shadow appearance. See
|
||||
* SkShadowFlags.
|
||||
*/
|
||||
static void DrawUncachedShadow(SkCanvas* canvas, const SkPath& path,
|
||||
std::function<SkScalar(SkScalar, SkScalar)> heightFunc,
|
||||
const SkPoint3& lightPos, SkScalar lightRadius,
|
||||
SkScalar ambientAlpha, SkScalar spotAlpha, SkColor color,
|
||||
uint32_t flags = SkShadowFlags::kNone_ShadowFlag) {
|
||||
SkPoint3 zPlane;
|
||||
zPlane.fZ = heightFunc(0, 0);
|
||||
zPlane.fX = heightFunc(1, 0) - zPlane.fZ;
|
||||
zPlane.fY = heightFunc(0, 1) - zPlane.fZ;
|
||||
|
||||
DrawUncachedShadow(canvas, path, zPlane, lightPos, lightRadius, ambientAlpha, spotAlpha,
|
||||
color, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw an offset spot shadow and outlining ambient shadow for the given path using a disc
|
||||
* light. Uses a plane function to vary the z value based on the local x and y position.
|
||||
* This shadow will not be cached, as the assumption is that this will be used for animation.
|
||||
*
|
||||
* @param canvas The canvas on which to draw the shadows.
|
||||
* @param path The occluder used to generate the shadows.
|
||||
* @param zPlaneParams Values for the plane function which returns the Z offset of the
|
||||
* occluder from the canvas based on local x and y values (the current matrix is not applied).
|
||||
* @param lightPos The 3D position of the light relative to the canvas plane. This is
|
||||
* independent of the canvas's current matrix.
|
||||
* @param lightRadius The radius of the disc light.
|
||||
* @param ambientAlpha The maximum alpha of the ambient shadow.
|
||||
* @param spotAlpha The maxium alpha of the spot shadow.
|
||||
* @param color The shadow color.
|
||||
* @param flags Options controlling opaque occluder optimizations and shadow appearance. See
|
||||
* SkShadowFlags.
|
||||
*/
|
||||
static void DrawUncachedShadow(SkCanvas* canvas, const SkPath& path,
|
||||
const SkPoint3& zPlaneParams,
|
||||
const SkPoint3& lightPos, SkScalar lightRadius,
|
||||
SkScalar ambientAlpha, SkScalar spotAlpha, SkColor color,
|
||||
uint32_t flags = SkShadowFlags::kNone_ShadowFlag);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -128,7 +128,7 @@ protected:
|
||||
}
|
||||
|
||||
void drawShadowedPath(SkCanvas* canvas, const SkPath& path,
|
||||
std::function<SkScalar(SkScalar, SkScalar)> zFunc,
|
||||
const SkPoint3& zPlaneParams,
|
||||
const SkPaint& paint, SkScalar ambientAlpha,
|
||||
const SkPoint3& lightPos, SkScalar lightWidth, SkScalar spotAlpha) {
|
||||
if (fIgnoreShadowAlpha) {
|
||||
@ -149,7 +149,7 @@ protected:
|
||||
// zValue,
|
||||
// lightPos, lightWidth,
|
||||
// ambientAlpha, spotAlpha, SK_ColorBLACK, flags);
|
||||
SkShadowUtils::DrawUncachedShadow(canvas, path, zFunc,
|
||||
SkShadowUtils::DrawUncachedShadow(canvas, path, zPlaneParams,
|
||||
lightPos, lightWidth,
|
||||
ambientAlpha, spotAlpha, SK_ColorBLACK, flags);
|
||||
|
||||
@ -175,48 +175,42 @@ protected:
|
||||
paint.setAntiAlias(true);
|
||||
|
||||
SkPoint3 lightPos = fLightPos;
|
||||
SkPoint3 zPlaneParams = SkPoint3::Make(0, 0, 0);
|
||||
|
||||
paint.setColor(SK_ColorWHITE);
|
||||
canvas->translate(200, 90);
|
||||
SkScalar zValue = SkTMax(1.0f, 2 + fZDelta);
|
||||
std::function<SkScalar(SkScalar, SkScalar)> zFunc =
|
||||
[zValue](SkScalar, SkScalar) { return zValue; };
|
||||
this->drawShadowedPath(canvas, fRRPath, zFunc, paint, kAmbientAlpha,
|
||||
zPlaneParams.fZ = SkTMax(1.0f, 2 + fZDelta);
|
||||
this->drawShadowedPath(canvas, fRRPath, zPlaneParams, paint, kAmbientAlpha,
|
||||
lightPos, kLightWidth, kSpotAlpha);
|
||||
|
||||
paint.setColor(SK_ColorRED);
|
||||
canvas->translate(250, 0);
|
||||
zValue = SkTMax(1.0f, 8 + fZDelta);
|
||||
zFunc = [zValue](SkScalar, SkScalar) { return zValue; };
|
||||
this->drawShadowedPath(canvas, fRectPath, zFunc, paint, kAmbientAlpha,
|
||||
zPlaneParams.fZ = SkTMax(1.0f, 8 + fZDelta);
|
||||
this->drawShadowedPath(canvas, fRectPath, zPlaneParams, paint, kAmbientAlpha,
|
||||
lightPos, kLightWidth, kSpotAlpha);
|
||||
|
||||
paint.setColor(SK_ColorBLUE);
|
||||
canvas->translate(-250, 110);
|
||||
zValue = SkTMax(1.0f, 12 + fZDelta);
|
||||
zFunc = [zValue](SkScalar, SkScalar) { return zValue; };
|
||||
this->drawShadowedPath(canvas, fCirclePath, zFunc, paint, kAmbientAlpha,
|
||||
zPlaneParams.fZ = SkTMax(1.0f, 12 + fZDelta);
|
||||
this->drawShadowedPath(canvas, fCirclePath, zPlaneParams, paint, kAmbientAlpha,
|
||||
lightPos, kLightWidth, 0.5f);
|
||||
|
||||
paint.setColor(SK_ColorGREEN);
|
||||
canvas->translate(250, 0);
|
||||
zValue = SkTMax(1.0f, 64 + fZDelta);
|
||||
zFunc = [zValue](SkScalar, SkScalar) { return zValue; };
|
||||
this->drawShadowedPath(canvas, fRRPath, zFunc, paint, kAmbientAlpha,
|
||||
zPlaneParams.fZ = SkTMax(1.0f, 64 + fZDelta);
|
||||
this->drawShadowedPath(canvas, fRRPath, zPlaneParams, paint, kAmbientAlpha,
|
||||
lightPos, kLightWidth, kSpotAlpha);
|
||||
|
||||
paint.setColor(SK_ColorYELLOW);
|
||||
canvas->translate(-250, 110);
|
||||
zValue = SkTMax(1.0f, 8 + fZDelta);
|
||||
zFunc = [zValue](SkScalar, SkScalar) { return zValue; };
|
||||
this->drawShadowedPath(canvas, fFunkyRRPath, zFunc, paint, kAmbientAlpha,
|
||||
zPlaneParams.fZ = SkTMax(1.0f, 8 + fZDelta);
|
||||
this->drawShadowedPath(canvas, fFunkyRRPath, zPlaneParams, paint, kAmbientAlpha,
|
||||
lightPos, kLightWidth, kSpotAlpha);
|
||||
|
||||
paint.setColor(SK_ColorCYAN);
|
||||
canvas->translate(250, 0);
|
||||
zValue = SkTMax(1.0f, 16 + fZDelta);
|
||||
zFunc = [zValue](SkScalar, SkScalar) { return zValue; };
|
||||
this->drawShadowedPath(canvas, fCubicPath, zFunc, paint,
|
||||
zPlaneParams.fZ = SkTMax(1.0f, 16 + fZDelta);
|
||||
this->drawShadowedPath(canvas, fCubicPath, zPlaneParams, paint,
|
||||
kAmbientAlpha, lightPos, kLightWidth, kSpotAlpha);
|
||||
|
||||
// circular reveal
|
||||
@ -227,9 +221,8 @@ protected:
|
||||
|
||||
paint.setColor(SK_ColorMAGENTA);
|
||||
canvas->translate(-125, 60);
|
||||
zValue = SkTMax(1.0f, 32 + fZDelta);
|
||||
zFunc = [zValue](SkScalar, SkScalar) { return zValue; };
|
||||
this->drawShadowedPath(canvas, tmpPath, zFunc, paint, .1f,
|
||||
zPlaneParams.fZ = SkTMax(1.0f, 32 + fZDelta);
|
||||
this->drawShadowedPath(canvas, tmpPath, zPlaneParams, paint, .1f,
|
||||
lightPos, kLightWidth, .5f);
|
||||
|
||||
// perspective paths
|
||||
@ -245,13 +238,11 @@ protected:
|
||||
persp.preTranslate(-pivot.fX, -pivot.fY);
|
||||
persp.postTranslate(pivot.fX + translate.fX, pivot.fY + translate.fY);
|
||||
canvas->setMatrix(persp);
|
||||
zValue = SkTMax(1.0f, 16 + fZDelta);
|
||||
SkScalar radians = SkDegreesToRadians(fAnimAngle);
|
||||
zFunc = [zValue, pivot, radians](SkScalar x, SkScalar y) {
|
||||
return SkScalarSin(-radians)*y +
|
||||
zValue - SkScalarSin(-radians)*pivot.fY;
|
||||
};
|
||||
this->drawShadowedPath(canvas, fWideRectPath, zFunc, paint, .1f,
|
||||
zPlaneParams = SkPoint3::Make(0,
|
||||
SkScalarSin(-radians),
|
||||
SkTMax(1.0f, 16 + fZDelta) - SkScalarSin(-radians)*pivot.fY);
|
||||
this->drawShadowedPath(canvas, fWideRectPath, zPlaneParams, paint, .1f,
|
||||
lightPos, kLightWidth, .5f);
|
||||
|
||||
pivot = SkPoint::Make(fWideOvalPath.getBounds().width() / 2,
|
||||
@ -263,12 +254,10 @@ protected:
|
||||
persp.preTranslate(-pivot.fX, -pivot.fY);
|
||||
persp.postTranslate(pivot.fX + translate.fX, pivot.fY + translate.fY);
|
||||
canvas->setMatrix(persp);
|
||||
zValue = SkTMax(1.0f, 32 + fZDelta);
|
||||
zFunc = [zValue, pivot, radians](SkScalar x, SkScalar y) {
|
||||
return -SkScalarSin(radians)*x +
|
||||
zValue + SkScalarSin(radians)*pivot.fX;
|
||||
};
|
||||
this->drawShadowedPath(canvas, fWideOvalPath, zFunc, paint, .1f,
|
||||
zPlaneParams = SkPoint3::Make(-SkScalarSin(radians),
|
||||
0,
|
||||
SkTMax(1.0f, 32 + fZDelta) + SkScalarSin(radians)*pivot.fX);
|
||||
this->drawShadowedPath(canvas, fWideOvalPath, zPlaneParams, paint, .1f,
|
||||
lightPos, kLightWidth, .5f);
|
||||
}
|
||||
|
||||
|
@ -109,7 +109,7 @@ protected:
|
||||
}
|
||||
|
||||
void drawShadowedPath(SkCanvas* canvas, const SkPath& path,
|
||||
std::function<SkScalar(SkScalar, SkScalar)> zFunc,
|
||||
const SkPoint3& zPlaneParams,
|
||||
const SkPaint& paint, SkScalar ambientAlpha,
|
||||
const SkPoint3& lightPos, SkScalar lightWidth, SkScalar spotAlpha,
|
||||
uint32_t flags) {
|
||||
@ -130,10 +130,10 @@ protected:
|
||||
// zValue,
|
||||
// lightPos, lightWidth,
|
||||
// ambientAlpha, spotAlpha, SK_ColorBLACK, flags);
|
||||
SkShadowUtils::DrawUncachedShadow(canvas, path, zFunc,
|
||||
SkShadowUtils::DrawUncachedShadow(canvas, path, zPlaneParams,
|
||||
lightPos, lightWidth,
|
||||
ambientAlpha, 0, SK_ColorRED, flags);
|
||||
SkShadowUtils::DrawUncachedShadow(canvas, path, zFunc,
|
||||
SkShadowUtils::DrawUncachedShadow(canvas, path, zPlaneParams,
|
||||
lightPos, lightWidth,
|
||||
0, spotAlpha, SK_ColorBLUE, flags);
|
||||
|
||||
@ -172,9 +172,7 @@ protected:
|
||||
SkPaint paint;
|
||||
paint.setColor(SK_ColorGREEN);
|
||||
paint.setAntiAlias(true);
|
||||
SkScalar zValue = SkTMax(1.0f, kHeight + fZDelta);
|
||||
std::function<SkScalar(SkScalar, SkScalar)> zFunc =
|
||||
[zValue](SkScalar, SkScalar) { return zValue; };
|
||||
SkPoint3 zPlaneParams = SkPoint3::Make(0, 0, SkTMax(1.0f, kHeight + fZDelta));
|
||||
for (auto& m : matrices) {
|
||||
for (auto flags : { kNone_ShadowFlag, kTransparentOccluder_ShadowFlag }) {
|
||||
for (const auto& path : fPaths) {
|
||||
@ -192,8 +190,8 @@ protected:
|
||||
|
||||
canvas->save();
|
||||
canvas->concat(m);
|
||||
drawShadowedPath(canvas, path, zFunc, paint, kAmbientAlpha, kLightPos, kLightR,
|
||||
kSpotAlpha, flags);
|
||||
drawShadowedPath(canvas, path, zPlaneParams, paint, kAmbientAlpha, kLightPos,
|
||||
kLightR, kSpotAlpha, flags);
|
||||
canvas->restore();
|
||||
|
||||
canvas->translate(dx, 0);
|
||||
|
@ -22,7 +22,7 @@
|
||||
*/
|
||||
class SkBaseShadowTessellator {
|
||||
public:
|
||||
SkBaseShadowTessellator(SkShadowTessellator::HeightFunc, bool transparent);
|
||||
SkBaseShadowTessellator(const SkPoint3& zPlaneParams, bool transparent);
|
||||
virtual ~SkBaseShadowTessellator() {}
|
||||
|
||||
sk_sp<SkVertices> releaseVertices() {
|
||||
@ -56,11 +56,15 @@ protected:
|
||||
|
||||
bool addArc(const SkVector& nextNormal, bool finishArc);
|
||||
|
||||
SkShadowTessellator::HeightFunc fHeightFunc;
|
||||
SkScalar heightFunc(SkScalar x, SkScalar y) {
|
||||
return fZPlaneParams.fX*x + fZPlaneParams.fY*y + fZPlaneParams.fZ;
|
||||
}
|
||||
|
||||
SkPoint3 fZPlaneParams;
|
||||
std::function<SkScalar(const SkPoint&)> fTransformedHeightFunc;
|
||||
SkScalar fZOffset;
|
||||
// members for perspective height function
|
||||
SkScalar fZParams[3];
|
||||
SkPoint3 fPerspZParams;
|
||||
SkScalar fPartialDeterminants[3];
|
||||
|
||||
// first two points
|
||||
@ -118,9 +122,8 @@ static void compute_radial_steps(const SkVector& v1, const SkVector& v2, SkScala
|
||||
*n = steps;
|
||||
}
|
||||
|
||||
SkBaseShadowTessellator::SkBaseShadowTessellator(SkShadowTessellator::HeightFunc heightFunc,
|
||||
bool transparent)
|
||||
: fHeightFunc(heightFunc)
|
||||
SkBaseShadowTessellator::SkBaseShadowTessellator(const SkPoint3& zPlaneParams, bool transparent)
|
||||
: fZPlaneParams(zPlaneParams)
|
||||
, fZOffset(0)
|
||||
, fFirstVertex(-1)
|
||||
, fSucceeded(false)
|
||||
@ -133,17 +136,17 @@ SkBaseShadowTessellator::SkBaseShadowTessellator(SkShadowTessellator::HeightFunc
|
||||
}
|
||||
|
||||
bool SkBaseShadowTessellator::setZOffset(const SkRect& bounds, bool perspective) {
|
||||
SkScalar minZ = fHeightFunc(bounds.fLeft, bounds.fTop);
|
||||
SkScalar minZ = this->heightFunc(bounds.fLeft, bounds.fTop);
|
||||
if (perspective) {
|
||||
SkScalar z = fHeightFunc(bounds.fLeft, bounds.fBottom);
|
||||
SkScalar z = this->heightFunc(bounds.fLeft, bounds.fBottom);
|
||||
if (z < minZ) {
|
||||
minZ = z;
|
||||
}
|
||||
z = fHeightFunc(bounds.fRight, bounds.fTop);
|
||||
z = this->heightFunc(bounds.fRight, bounds.fTop);
|
||||
if (z < minZ) {
|
||||
minZ = z;
|
||||
}
|
||||
z = fHeightFunc(bounds.fRight, bounds.fBottom);
|
||||
z = this->heightFunc(bounds.fRight, bounds.fBottom);
|
||||
if (z < minZ) {
|
||||
minZ = z;
|
||||
}
|
||||
@ -267,27 +270,28 @@ bool SkBaseShadowTessellator::addArc(const SkVector& nextNormal, bool finishArc)
|
||||
bool SkBaseShadowTessellator::setTransformedHeightFunc(const SkMatrix& ctm) {
|
||||
if (!ctm.hasPerspective()) {
|
||||
fTransformedHeightFunc = [this](const SkPoint& p) {
|
||||
return this->fHeightFunc(0, 0);
|
||||
return fZPlaneParams.fZ;
|
||||
};
|
||||
} else {
|
||||
SkMatrix ctmInverse;
|
||||
if (!ctm.invert(&ctmInverse)) {
|
||||
return false;
|
||||
}
|
||||
SkScalar C = fHeightFunc(0, 0);
|
||||
SkScalar A = fHeightFunc(1, 0) - C;
|
||||
SkScalar B = fHeightFunc(0, 1) - C;
|
||||
|
||||
// multiply by transpose
|
||||
fZParams[0] = ctmInverse[SkMatrix::kMScaleX] * A +
|
||||
ctmInverse[SkMatrix::kMSkewY] * B +
|
||||
ctmInverse[SkMatrix::kMPersp0] * C;
|
||||
fZParams[1] = ctmInverse[SkMatrix::kMSkewX] * A +
|
||||
ctmInverse[SkMatrix::kMScaleY] * B +
|
||||
ctmInverse[SkMatrix::kMPersp1] * C;
|
||||
fZParams[2] = ctmInverse[SkMatrix::kMTransX] * A +
|
||||
ctmInverse[SkMatrix::kMTransY] * B +
|
||||
ctmInverse[SkMatrix::kMPersp2] * C;
|
||||
fPerspZParams = SkPoint3::Make(
|
||||
ctmInverse[SkMatrix::kMScaleX] * fZPlaneParams.fX +
|
||||
ctmInverse[SkMatrix::kMSkewY] * fZPlaneParams.fY +
|
||||
ctmInverse[SkMatrix::kMPersp0] * fZPlaneParams.fZ,
|
||||
|
||||
ctmInverse[SkMatrix::kMSkewX] * fZPlaneParams.fX +
|
||||
ctmInverse[SkMatrix::kMScaleY] * fZPlaneParams.fY +
|
||||
ctmInverse[SkMatrix::kMPersp1] * fZPlaneParams.fZ,
|
||||
|
||||
ctmInverse[SkMatrix::kMTransX] * fZPlaneParams.fX +
|
||||
ctmInverse[SkMatrix::kMTransY] * fZPlaneParams.fY +
|
||||
ctmInverse[SkMatrix::kMPersp2] * fZPlaneParams.fZ
|
||||
);
|
||||
|
||||
// We use Cramer's rule to solve for the W value for a given post-divide X and Y,
|
||||
// so pre-compute those values that are independent of X and Y.
|
||||
@ -304,17 +308,17 @@ bool SkBaseShadowTessellator::setTransformedHeightFunc(const SkMatrix& ctm) {
|
||||
|
||||
// Pre-bake the numerator of Cramer's rule into the zParams to avoid another multiply.
|
||||
// TODO: this may introduce numerical instability, but I haven't seen any issues yet.
|
||||
fZParams[0] *= ctmDeterminant;
|
||||
fZParams[1] *= ctmDeterminant;
|
||||
fZParams[2] *= ctmDeterminant;
|
||||
fPerspZParams.fX *= ctmDeterminant;
|
||||
fPerspZParams.fY *= ctmDeterminant;
|
||||
fPerspZParams.fZ *= ctmDeterminant;
|
||||
|
||||
fTransformedHeightFunc = [this](const SkPoint& p) {
|
||||
SkScalar denom = p.fX * this->fPartialDeterminants[0] +
|
||||
p.fY * this->fPartialDeterminants[1] +
|
||||
this->fPartialDeterminants[2];
|
||||
SkScalar denom = p.fX * fPartialDeterminants[0] +
|
||||
p.fY * fPartialDeterminants[1] +
|
||||
fPartialDeterminants[2];
|
||||
SkScalar w = SkScalarFastInvert(denom);
|
||||
return (this->fZParams[0] * p.fX + this->fZParams[1] * p.fY + this->fZParams[2])*w +
|
||||
this->fZOffset;
|
||||
return (fPerspZParams.fX * p.fX + fPerspZParams.fY * p.fY + fPerspZParams.fZ)*w +
|
||||
fZOffset;
|
||||
};
|
||||
}
|
||||
|
||||
@ -327,7 +331,7 @@ bool SkBaseShadowTessellator::setTransformedHeightFunc(const SkMatrix& ctm) {
|
||||
class SkAmbientShadowTessellator : public SkBaseShadowTessellator {
|
||||
public:
|
||||
SkAmbientShadowTessellator(const SkPath& path, const SkMatrix& ctm,
|
||||
SkShadowTessellator::HeightFunc heightFunc, bool transparent);
|
||||
const SkPoint3& zPlaneParams, bool transparent);
|
||||
|
||||
private:
|
||||
void handleLine(const SkPoint& p) override;
|
||||
@ -352,9 +356,9 @@ private:
|
||||
|
||||
SkAmbientShadowTessellator::SkAmbientShadowTessellator(const SkPath& path,
|
||||
const SkMatrix& ctm,
|
||||
SkShadowTessellator::HeightFunc heightFunc,
|
||||
const SkPoint3& zPlaneParams,
|
||||
bool transparent)
|
||||
: INHERITED(heightFunc, transparent) {
|
||||
: INHERITED(zPlaneParams, transparent) {
|
||||
// Set base colors
|
||||
SkScalar occluderHeight = heightFunc(0, 0);
|
||||
SkScalar umbraAlpha = SkScalarInvert((1.0f + SkTMax(occluderHeight*kHeightFactor, 0.0f)));
|
||||
@ -650,7 +654,7 @@ void SkAmbientShadowTessellator::addEdge(const SkPoint& nextPoint, const SkVecto
|
||||
class SkSpotShadowTessellator : public SkBaseShadowTessellator {
|
||||
public:
|
||||
SkSpotShadowTessellator(const SkPath& path, const SkMatrix& ctm,
|
||||
SkShadowTessellator::HeightFunc heightFunc, const SkPoint3& lightPos,
|
||||
const SkPoint3& zPlaneParams, const SkPoint3& lightPos,
|
||||
SkScalar lightRadius, bool transparent);
|
||||
|
||||
private:
|
||||
@ -693,10 +697,10 @@ private:
|
||||
};
|
||||
|
||||
SkSpotShadowTessellator::SkSpotShadowTessellator(const SkPath& path, const SkMatrix& ctm,
|
||||
SkShadowTessellator::HeightFunc heightFunc,
|
||||
const SkPoint3& zPlaneParams,
|
||||
const SkPoint3& lightPos, SkScalar lightRadius,
|
||||
bool transparent)
|
||||
: INHERITED(heightFunc, transparent)
|
||||
: INHERITED(zPlaneParams, transparent)
|
||||
, fLightZ(lightPos.fZ)
|
||||
, fLightRadius(lightRadius)
|
||||
, fOffsetAdjust(0)
|
||||
@ -714,7 +718,7 @@ SkSpotShadowTessellator::SkSpotShadowTessellator(const SkPath& path, const SkMat
|
||||
|
||||
// Set radius and colors
|
||||
SkPoint center = SkPoint::Make(path.getBounds().centerX(), path.getBounds().centerY());
|
||||
SkScalar occluderHeight = heightFunc(center.fX, center.fY) + fZOffset;
|
||||
SkScalar occluderHeight = this->heightFunc(center.fX, center.fY) + fZOffset;
|
||||
float zRatio = SkTPin(occluderHeight / (fLightZ - occluderHeight), 0.0f, 0.95f);
|
||||
SkScalar radius = lightRadius * zRatio;
|
||||
fRadius = radius;
|
||||
@ -1287,14 +1291,14 @@ void SkSpotShadowTessellator::addEdge(const SkPoint& nextPoint, const SkVector&
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
sk_sp<SkVertices> SkShadowTessellator::MakeAmbient(const SkPath& path, const SkMatrix& ctm,
|
||||
HeightFunc heightFunc, bool transparent) {
|
||||
SkAmbientShadowTessellator ambientTess(path, ctm, heightFunc, transparent);
|
||||
const SkPoint3& zPlane, bool transparent) {
|
||||
SkAmbientShadowTessellator ambientTess(path, ctm, zPlane, transparent);
|
||||
return ambientTess.releaseVertices();
|
||||
}
|
||||
|
||||
sk_sp<SkVertices> SkShadowTessellator::MakeSpot(const SkPath& path, const SkMatrix& ctm,
|
||||
HeightFunc heightFunc, const SkPoint3& lightPos,
|
||||
const SkPoint3& zPlane, const SkPoint3& lightPos,
|
||||
SkScalar lightRadius, bool transparent) {
|
||||
SkSpotShadowTessellator spotTess(path, ctm, heightFunc, lightPos, lightRadius, transparent);
|
||||
SkSpotShadowTessellator spotTess(path, ctm, zPlane, lightPos, lightRadius, transparent);
|
||||
return spotTess.releaseVertices();
|
||||
}
|
||||
|
@ -26,14 +26,14 @@ typedef std::function<SkScalar(SkScalar, SkScalar)> HeightFunc;
|
||||
* If transparent is true, then the center of the ambient shadow will be filled in.
|
||||
*/
|
||||
sk_sp<SkVertices> MakeAmbient(const SkPath& path, const SkMatrix& ctm,
|
||||
HeightFunc heightFunc, bool transparent);
|
||||
const SkPoint3& zPlane, bool transparent);
|
||||
|
||||
/**
|
||||
* This function generates a spot shadow mesh for a path by walking the transformed path,
|
||||
* further transforming by the scale and translation, and outsetting and insetting by a radius.
|
||||
* The center will be clipped against the original path unless transparent is true.
|
||||
*/
|
||||
sk_sp<SkVertices> MakeSpot(const SkPath& path, const SkMatrix& ctm, HeightFunc heightFunc,
|
||||
sk_sp<SkVertices> MakeSpot(const SkPath& path, const SkMatrix& ctm, const SkPoint3& zPlane,
|
||||
const SkPoint3& lightPos, SkScalar lightRadius, bool transparent);
|
||||
}
|
||||
|
||||
|
@ -170,10 +170,8 @@ struct AmbientVerticesFactory {
|
||||
}
|
||||
|
||||
sk_sp<SkVertices> makeVertices(const SkPath& path, const SkMatrix& ctm) const {
|
||||
SkScalar z = fOccluderHeight;
|
||||
return SkShadowTessellator::MakeAmbient(path, ctm,
|
||||
[z](SkScalar, SkScalar) { return z; },
|
||||
fTransparent);
|
||||
SkPoint3 zParams = SkPoint3::Make(0, 0, fOccluderHeight);
|
||||
return SkShadowTessellator::MakeAmbient(path, ctm, zParams, fTransparent);
|
||||
}
|
||||
};
|
||||
|
||||
@ -221,9 +219,8 @@ struct SpotVerticesFactory {
|
||||
|
||||
sk_sp<SkVertices> makeVertices(const SkPath& path, const SkMatrix& ctm) const {
|
||||
bool transparent = OccluderType::kTransparent == fOccluderType;
|
||||
SkScalar z = fOccluderHeight;
|
||||
return SkShadowTessellator::MakeSpot(path, ctm,
|
||||
[z](SkScalar, SkScalar) -> SkScalar { return z; },
|
||||
SkPoint3 zParams = SkPoint3::Make(0, 0, fOccluderHeight);
|
||||
return SkShadowTessellator::MakeSpot(path, ctm, zParams,
|
||||
fDevLightPos, fLightRadius, transparent);
|
||||
}
|
||||
};
|
||||
@ -680,13 +677,13 @@ void SkShadowUtils::DrawShadow(SkCanvas* canvas, const SkPath& path, SkScalar oc
|
||||
// Draw an offset spot shadow and outlining ambient shadow for the given path,
|
||||
// without caching and using a function based on local position to compute the height.
|
||||
void SkShadowUtils::DrawUncachedShadow(SkCanvas* canvas, const SkPath& path,
|
||||
std::function<SkScalar(SkScalar, SkScalar)> heightFunc,
|
||||
const SkPoint3& zPlaneParams,
|
||||
const SkPoint3& lightPos, SkScalar lightRadius,
|
||||
SkScalar ambientAlpha, SkScalar spotAlpha, SkColor color,
|
||||
uint32_t flags) {
|
||||
// try fast paths
|
||||
bool skipAnalytic = SkToBool(flags & SkShadowFlags::kGeometricOnly_ShadowFlag);
|
||||
if (!skipAnalytic && draw_analytic_shadows(canvas, path, heightFunc(0, 0), lightPos,
|
||||
if (!skipAnalytic && draw_analytic_shadows(canvas, path, zPlaneParams.fZ, lightPos,
|
||||
lightRadius, ambientAlpha, spotAlpha, color,
|
||||
flags)) {
|
||||
return;
|
||||
@ -701,7 +698,7 @@ void SkShadowUtils::DrawUncachedShadow(SkCanvas* canvas, const SkPath& path,
|
||||
if (ambientAlpha > 0) {
|
||||
ambientAlpha = SkTMin(ambientAlpha, 1.f);
|
||||
sk_sp<SkVertices> vertices = SkShadowTessellator::MakeAmbient(path, viewMatrix,
|
||||
heightFunc, transparent);
|
||||
zPlaneParams, transparent);
|
||||
SkColor renderColor = compute_render_color(color, ambientAlpha);
|
||||
SkPaint paint;
|
||||
// Run the vertex color through a GaussianColorFilter and then modulate the grayscale
|
||||
@ -714,7 +711,7 @@ void SkShadowUtils::DrawUncachedShadow(SkCanvas* canvas, const SkPath& path,
|
||||
|
||||
if (spotAlpha > 0) {
|
||||
spotAlpha = SkTMin(spotAlpha, 1.f);
|
||||
sk_sp<SkVertices> vertices = SkShadowTessellator::MakeSpot(path, viewMatrix, heightFunc,
|
||||
sk_sp<SkVertices> vertices = SkShadowTessellator::MakeSpot(path, viewMatrix, zPlaneParams,
|
||||
lightPos, lightRadius,
|
||||
transparent);
|
||||
SkColor renderColor = compute_render_color(color, spotAlpha);
|
||||
|
@ -15,24 +15,24 @@
|
||||
void tessellate_shadow(skiatest::Reporter* reporter, const SkPath& path, const SkMatrix& ctm,
|
||||
bool expectSuccess) {
|
||||
|
||||
auto heightFunc = [] (SkScalar, SkScalar) { return 4; };
|
||||
auto heightParams = SkPoint3::Make(0, 0, 4);
|
||||
|
||||
auto verts = SkShadowTessellator::MakeAmbient(path, ctm, heightFunc, true);
|
||||
auto verts = SkShadowTessellator::MakeAmbient(path, ctm, heightParams, true);
|
||||
if (expectSuccess != SkToBool(verts)) {
|
||||
ERRORF(reporter, "Expected shadow tessellation to %s but it did not.",
|
||||
expectSuccess ? "succeed" : "fail");
|
||||
}
|
||||
verts = SkShadowTessellator::MakeAmbient(path, ctm, heightFunc, false);
|
||||
verts = SkShadowTessellator::MakeAmbient(path, ctm, heightParams, false);
|
||||
if (expectSuccess != SkToBool(verts)) {
|
||||
ERRORF(reporter, "Expected shadow tessellation to %s but it did not.",
|
||||
expectSuccess ? "succeed" : "fail");
|
||||
}
|
||||
verts = SkShadowTessellator::MakeSpot(path, ctm, heightFunc, {0, 0, 128}, 128.f, false);
|
||||
verts = SkShadowTessellator::MakeSpot(path, ctm, heightParams, {0, 0, 128}, 128.f, false);
|
||||
if (expectSuccess != SkToBool(verts)) {
|
||||
ERRORF(reporter, "Expected shadow tessellation to %s but it did not.",
|
||||
expectSuccess ? "succeed" : "fail");
|
||||
}
|
||||
verts = SkShadowTessellator::MakeSpot(path, ctm, heightFunc, {0, 0, 128}, 128.f, false);
|
||||
verts = SkShadowTessellator::MakeSpot(path, ctm, heightParams, {0, 0, 128}, 128.f, false);
|
||||
if (expectSuccess != SkToBool(verts)) {
|
||||
ERRORF(reporter, "Expected shadow tessellation to %s but it did not.",
|
||||
expectSuccess ? "succeed" : "fail");
|
||||
|
Loading…
Reference in New Issue
Block a user