Classify spot shadows for general shapes

Add some simple checks so we can tell whether a shadow's umbra is
completely covered by the occluder, partially covered, or less than
halfway covered.

Change-Id: I092281c4933bd0380946eb0fdd458ce04b0d713c
Reviewed-on: https://skia-review.googlesource.com/16603
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
This commit is contained in:
Jim Van Verth 2017-05-11 17:05:28 -04:00 committed by Skia Commit-Bot
parent cd9af1bfa8
commit a783c3623d

View File

@ -640,6 +640,9 @@ void SkShadowUtils::DrawShadow(SkCanvas* canvas, const SkPath& path, const SkPoi
SpotVerticesFactory factory;
SkScalar occluderHeight = zPlaneParams.fZ;
float zRatio = SkTPin(occluderHeight / (devLightPos.fZ - occluderHeight), 0.0f, 0.95f);
SkScalar radius = lightRadius * zRatio;
// Compute the translation for the spot shadow.
SkPoint center = SkPoint::Make(path.getBounds().centerX(), path.getBounds().centerY());
viewMatrix.mapPoints(&center, 1);
factory.fOffset = SkVector::Make(zRatio * (center.fX - devLightPos.fX),
@ -647,9 +650,34 @@ void SkShadowUtils::DrawShadow(SkCanvas* canvas, const SkPath& path, const SkPoi
factory.fOccluderHeight = occluderHeight;
factory.fDevLightPos = devLightPos;
factory.fLightRadius = lightRadius;
// the only valid choice we have right now
factory.fOccluderType = SpotVerticesFactory::OccluderType::kTransparent;
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()) {
factory.fOccluderType = SpotVerticesFactory::OccluderType::kTransparent;
} else if (factory.fOffset.length() < radius) {
// if we don't translate more than the blur distance, can assume umbra is covered
factory.fOccluderType = SpotVerticesFactory::OccluderType::kOpaqueCoversUmbra;
} else {
factory.fOccluderType = SpotVerticesFactory::OccluderType::kOpaque;
}
#ifdef DEBUG_SHADOW_CHECKS
switch (factory.fOccluderType) {
case SpotVerticesFactory::OccluderType::kTransparent:
color = 0xFFD2B48C; // tan for transparent
break;
case SpotVerticesFactory::OccluderType::kOpaque:
color = 0xFFFFA500; // orange for opaque
break;
case SpotVerticesFactory::OccluderType::kOpaqueCoversUmbra:
color = SK_ColorYELLOW; // corn yellow for covered
break;
}
#endif
SkColor renderColor = compute_render_color(color, spotAlpha);
draw_shadow(factory, canvas, shadowedPath, renderColor);
}