Remove height functor for shadows and replace with plane equation params
authorJim Van Verth <jvanverth@google.com>
Mon, 8 May 2017 18:19:30 +0000 (14:19 -0400)
committerSkia Commit-Bot <skia-commit-bot@chromium.org>
Mon, 8 May 2017 18:42:48 +0000 (18:42 +0000)
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>
include/utils/SkShadowUtils.h
samplecode/SampleAndroidShadows.cpp
samplecode/SampleShadowUtils.cpp
src/utils/SkShadowTessellator.cpp
src/utils/SkShadowTessellator.h
src/utils/SkShadowUtils.cpp
tests/ShadowUtilsTest.cpp

index 01514a4..4a497bb 100644 (file)
@@ -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
index c8ce14c..81dc0cc 100644 (file)
@@ -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);
     }
 
index f5b6635..6d047be 100755 (executable)
@@ -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);
index 32a1142..9a82ec3 100755 (executable)
@@ -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();
 }
index d6e784e..351beee 100644 (file)
@@ -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);
 }
 
index 19b2c2d..7295e48 100644 (file)
@@ -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);
index f83e44a..c0e20d5 100644 (file)
 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");