Add filled occluders to shadow_utils GM, take 2
authorJim Van Verth <jvanverth@google.com>
Mon, 15 May 2017 14:44:22 +0000 (10:44 -0400)
committerSkia Commit-Bot <skia-commit-bot@chromium.org>
Mon, 15 May 2017 16:01:43 +0000 (16:01 +0000)
Classifies fully visible opaque shadows differently
than transparent to avoid cache collisions.

Change-Id: Iba5aab2b2cbe08f70205c343e86fe92b0cab7497
Reviewed-on: https://skia-review.googlesource.com/16858
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>

gm/shadowutils.cpp
src/utils/SkShadowUtils.cpp

index 9d9eaae..17e2620 100644 (file)
@@ -22,7 +22,7 @@ void draw_shadow(SkCanvas* canvas, const SkPath& path, int height, SkColor color
 static constexpr int kW = 800;
 static constexpr int kH = 800;
 
-DEF_SIMPLE_GM(shadow_utils, canvas, kW, kH) {
+void draw_paths(SkCanvas* canvas, bool hideOccluders) {
     SkTArray<SkPath> paths;
     paths.push_back().addRoundRect(SkRect::MakeWH(50, 50), 10, 10);
     SkRRect oddRRect;
@@ -34,7 +34,7 @@ DEF_SIMPLE_GM(shadow_utils, canvas, kW, kH) {
     paths.push_back().addOval(SkRect::MakeWH(20, 60));
 
     static constexpr SkScalar kPad = 15.f;
-    static constexpr SkPoint3 kLightPos = {250, 400, 500};
+    static constexpr SkPoint3 kLightPos = { 250, 400, 500 };
     static constexpr SkScalar kLightR = 100.f;
     static constexpr SkScalar kHeight = 50.f;
     canvas->translate(3 * kPad, 3 * kPad);
@@ -47,7 +47,7 @@ DEF_SIMPLE_GM(shadow_utils, canvas, kW, kH) {
     m->setRotate(33.f, 25.f, 25.f);
     m->postScale(1.2f, 0.8f, 25.f, 25.f);
     for (auto& m : matrices) {
-        for (auto flags : {kNone_ShadowFlag, kTransparentOccluder_ShadowFlag}) {
+        for (auto flags : { kNone_ShadowFlag, kTransparentOccluder_ShadowFlag }) {
             for (const auto& path : paths) {
                 SkRect postMBounds = path.getBounds();
                 m.mapRect(&postMBounds);
@@ -68,10 +68,22 @@ DEF_SIMPLE_GM(shadow_utils, canvas, kW, kH) {
 
                 // Draw the path outline in green on top of the ambient and spot shadows.
                 SkPaint paint;
-                paint.setColor(SK_ColorGREEN);
                 paint.setAntiAlias(true);
-                paint.setStyle(SkPaint::kStroke_Style);
-                paint.setStrokeWidth(0);
+                if (hideOccluders) {
+                    if (SkToBool(flags & kTransparentOccluder_ShadowFlag)) {
+                        paint.setColor(SK_ColorCYAN);
+                    } else {
+                        paint.setColor(SK_ColorGREEN);
+                    }
+                    paint.setStyle(SkPaint::kStroke_Style);
+                    paint.setStrokeWidth(0);
+                } else {
+                    paint.setColor(SK_ColorLTGRAY);
+                    if (SkToBool(flags & kTransparentOccluder_ShadowFlag)) {
+                        paint.setAlpha(128);
+                    }
+                    paint.setStyle(SkPaint::kFill_Style);
+                }
                 canvas->drawPath(path, paint);
                 canvas->restore();
 
@@ -93,3 +105,11 @@ DEF_SIMPLE_GM(shadow_utils, canvas, kW, kH) {
         canvas->restore();
     }
 }
+
+DEF_SIMPLE_GM(shadow_utils, canvas, kW, kH) {
+    draw_paths(canvas, true);
+}
+
+DEF_SIMPLE_GM(shadow_utils_occl, canvas, kW, kH) {
+    draw_paths(canvas, false);
+}
index 355fb2d..d84c330 100644 (file)
@@ -181,10 +181,12 @@ struct SpotVerticesFactory {
     enum class OccluderType {
         // The umbra cannot be dropped out because the occluder is not opaque.
         kTransparent,
+        // The occluder is opaque and the umbra is fully visible
+        kOpaqueFullUmbra,
         // The umbra can be dropped where it is occluded.
-        kOpaque,
+        kOpaquePartialUmbra,
         // It is known that the entire umbra is occluded.
-        kOpaqueCoversUmbra
+        kOpaqueNoUmbra
     };
 
     SkVector fOffset;
@@ -200,12 +202,13 @@ struct SpotVerticesFactory {
         }
         switch (fOccluderType) {
             case OccluderType::kTransparent:
-            case OccluderType::kOpaqueCoversUmbra:
+            case OccluderType::kOpaqueFullUmbra:
+            case OccluderType::kOpaqueNoUmbra:
                 // 'this' and 'that' will either both have no umbra removed or both have all the
                 // umbra removed.
                 *translate = that.fOffset - fOffset;
                 return true;
-            case OccluderType::kOpaque:
+            case OccluderType::kOpaquePartialUmbra:
                 // In this case we partially remove the umbra differently for 'this' and 'that'
                 // if the offsets don't match.
                 if (fOffset == that.fOffset) {
@@ -642,7 +645,8 @@ void SkShadowUtils::DrawShadow(SkCanvas* canvas, const SkPath& path, const SkPoi
             float zRatio = SkTPin(occluderHeight / (devLightPos.fZ - occluderHeight), 0.0f, 0.95f);
             SkScalar radius = lightRadius * zRatio;
 
-            // Compute the translation for the spot shadow.
+            // Compute the scale and translation for the spot shadow.
+            SkScalar scale = devLightPos.fZ / (devLightPos.fZ - occluderHeight);
             SkPoint center = SkPoint::Make(path.getBounds().centerX(), path.getBounds().centerY());
             viewMatrix.mapPoints(&center, 1);
             factory.fOffset = SkVector::Make(zRatio * (center.fX - devLightPos.fX),
@@ -652,17 +656,18 @@ void SkShadowUtils::DrawShadow(SkCanvas* canvas, const SkPath& path, const SkPoi
             factory.fLightRadius = lightRadius;
             SkRect devBounds;
             viewMatrix.mapRect(&devBounds, path.getBounds());
-            if (transparent ||
-                // if the translation of the shadow is big enough we're going to end up
-                // filling the entire umbra, so we can treat this as transparent
-                SkTAbs(factory.fOffset.fX) > 0.5f*devBounds.width() ||
-                SkTAbs(factory.fOffset.fY) > 0.5f*devBounds.height()) {
+            if (transparent) {
                 factory.fOccluderType = SpotVerticesFactory::OccluderType::kTransparent;
-            } else if (factory.fOffset.length() < radius) {
+            } else if (SkTAbs(factory.fOffset.fX) > 0.5f*devBounds.width() ||
+                       SkTAbs(factory.fOffset.fY) > 0.5f*devBounds.height()) {
+                // if the translation of the shadow is big enough we're going to end up
+                // filling the entire umbra, so we can treat these as all the same
+                factory.fOccluderType = SpotVerticesFactory::OccluderType::kOpaqueFullUmbra;
+            } else if (factory.fOffset.length()*scale + scale < radius) {
                 // if we don't translate more than the blur distance, can assume umbra is covered
-                factory.fOccluderType = SpotVerticesFactory::OccluderType::kOpaqueCoversUmbra;
+                factory.fOccluderType = SpotVerticesFactory::OccluderType::kOpaqueNoUmbra;
             } else {
-                factory.fOccluderType = SpotVerticesFactory::OccluderType::kOpaque;
+                factory.fOccluderType = SpotVerticesFactory::OccluderType::kOpaquePartialUmbra;
             }
 
 #ifdef DEBUG_SHADOW_CHECKS
@@ -670,11 +675,14 @@ void SkShadowUtils::DrawShadow(SkCanvas* canvas, const SkPath& path, const SkPoi
                 case SpotVerticesFactory::OccluderType::kTransparent:
                     color = 0xFFD2B48C;  // tan for transparent
                     break;
-                case SpotVerticesFactory::OccluderType::kOpaque:
+                case SpotVerticesFactory::OccluderType::kOpaqueFullUmbra:
+                    color = 0xFF614126;   // brown for umBra
+                    break;
+                case SpotVerticesFactory::OccluderType::kOpaquePartialUmbra:
                     color = 0xFFFFA500;   // orange for opaque
                     break;
-                case SpotVerticesFactory::OccluderType::kOpaqueCoversUmbra:
-                    color = SK_ColorYELLOW;  // corn yellow for covered
+                case SpotVerticesFactory::OccluderType::kOpaqueNoUmbra:
+                    color = 0xFFE5E500;  // corn yellow for covered
                     break;
             }
 #endif