Add filled occluders to shadow_utils GM, take 2
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>
This commit is contained in:
parent
e334c59654
commit
78c8f30d61
@ -22,7 +22,7 @@ void draw_shadow(SkCanvas* canvas, const SkPath& path, int height, SkColor color
|
|||||||
static constexpr int kW = 800;
|
static constexpr int kW = 800;
|
||||||
static constexpr int kH = 800;
|
static constexpr int kH = 800;
|
||||||
|
|
||||||
DEF_SIMPLE_GM(shadow_utils, canvas, kW, kH) {
|
void draw_paths(SkCanvas* canvas, bool hideOccluders) {
|
||||||
SkTArray<SkPath> paths;
|
SkTArray<SkPath> paths;
|
||||||
paths.push_back().addRoundRect(SkRect::MakeWH(50, 50), 10, 10);
|
paths.push_back().addRoundRect(SkRect::MakeWH(50, 50), 10, 10);
|
||||||
SkRRect oddRRect;
|
SkRRect oddRRect;
|
||||||
@ -34,7 +34,7 @@ DEF_SIMPLE_GM(shadow_utils, canvas, kW, kH) {
|
|||||||
paths.push_back().addOval(SkRect::MakeWH(20, 60));
|
paths.push_back().addOval(SkRect::MakeWH(20, 60));
|
||||||
|
|
||||||
static constexpr SkScalar kPad = 15.f;
|
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 kLightR = 100.f;
|
||||||
static constexpr SkScalar kHeight = 50.f;
|
static constexpr SkScalar kHeight = 50.f;
|
||||||
canvas->translate(3 * kPad, 3 * kPad);
|
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->setRotate(33.f, 25.f, 25.f);
|
||||||
m->postScale(1.2f, 0.8f, 25.f, 25.f);
|
m->postScale(1.2f, 0.8f, 25.f, 25.f);
|
||||||
for (auto& m : matrices) {
|
for (auto& m : matrices) {
|
||||||
for (auto flags : {kNone_ShadowFlag, kTransparentOccluder_ShadowFlag}) {
|
for (auto flags : { kNone_ShadowFlag, kTransparentOccluder_ShadowFlag }) {
|
||||||
for (const auto& path : paths) {
|
for (const auto& path : paths) {
|
||||||
SkRect postMBounds = path.getBounds();
|
SkRect postMBounds = path.getBounds();
|
||||||
m.mapRect(&postMBounds);
|
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.
|
// Draw the path outline in green on top of the ambient and spot shadows.
|
||||||
SkPaint paint;
|
SkPaint paint;
|
||||||
paint.setColor(SK_ColorGREEN);
|
|
||||||
paint.setAntiAlias(true);
|
paint.setAntiAlias(true);
|
||||||
paint.setStyle(SkPaint::kStroke_Style);
|
if (hideOccluders) {
|
||||||
paint.setStrokeWidth(0);
|
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->drawPath(path, paint);
|
||||||
canvas->restore();
|
canvas->restore();
|
||||||
|
|
||||||
@ -93,3 +105,11 @@ DEF_SIMPLE_GM(shadow_utils, canvas, kW, kH) {
|
|||||||
canvas->restore();
|
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);
|
||||||
|
}
|
||||||
|
@ -181,10 +181,12 @@ struct SpotVerticesFactory {
|
|||||||
enum class OccluderType {
|
enum class OccluderType {
|
||||||
// The umbra cannot be dropped out because the occluder is not opaque.
|
// The umbra cannot be dropped out because the occluder is not opaque.
|
||||||
kTransparent,
|
kTransparent,
|
||||||
|
// The occluder is opaque and the umbra is fully visible
|
||||||
|
kOpaqueFullUmbra,
|
||||||
// The umbra can be dropped where it is occluded.
|
// The umbra can be dropped where it is occluded.
|
||||||
kOpaque,
|
kOpaquePartialUmbra,
|
||||||
// It is known that the entire umbra is occluded.
|
// It is known that the entire umbra is occluded.
|
||||||
kOpaqueCoversUmbra
|
kOpaqueNoUmbra
|
||||||
};
|
};
|
||||||
|
|
||||||
SkVector fOffset;
|
SkVector fOffset;
|
||||||
@ -200,12 +202,13 @@ struct SpotVerticesFactory {
|
|||||||
}
|
}
|
||||||
switch (fOccluderType) {
|
switch (fOccluderType) {
|
||||||
case OccluderType::kTransparent:
|
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
|
// 'this' and 'that' will either both have no umbra removed or both have all the
|
||||||
// umbra removed.
|
// umbra removed.
|
||||||
*translate = that.fOffset - fOffset;
|
*translate = that.fOffset - fOffset;
|
||||||
return true;
|
return true;
|
||||||
case OccluderType::kOpaque:
|
case OccluderType::kOpaquePartialUmbra:
|
||||||
// In this case we partially remove the umbra differently for 'this' and 'that'
|
// In this case we partially remove the umbra differently for 'this' and 'that'
|
||||||
// if the offsets don't match.
|
// if the offsets don't match.
|
||||||
if (fOffset == that.fOffset) {
|
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);
|
float zRatio = SkTPin(occluderHeight / (devLightPos.fZ - occluderHeight), 0.0f, 0.95f);
|
||||||
SkScalar radius = lightRadius * zRatio;
|
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());
|
SkPoint center = SkPoint::Make(path.getBounds().centerX(), path.getBounds().centerY());
|
||||||
viewMatrix.mapPoints(¢er, 1);
|
viewMatrix.mapPoints(¢er, 1);
|
||||||
factory.fOffset = SkVector::Make(zRatio * (center.fX - devLightPos.fX),
|
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;
|
factory.fLightRadius = lightRadius;
|
||||||
SkRect devBounds;
|
SkRect devBounds;
|
||||||
viewMatrix.mapRect(&devBounds, path.getBounds());
|
viewMatrix.mapRect(&devBounds, path.getBounds());
|
||||||
if (transparent ||
|
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;
|
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
|
// 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 {
|
} else {
|
||||||
factory.fOccluderType = SpotVerticesFactory::OccluderType::kOpaque;
|
factory.fOccluderType = SpotVerticesFactory::OccluderType::kOpaquePartialUmbra;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_SHADOW_CHECKS
|
#ifdef DEBUG_SHADOW_CHECKS
|
||||||
@ -670,11 +675,14 @@ void SkShadowUtils::DrawShadow(SkCanvas* canvas, const SkPath& path, const SkPoi
|
|||||||
case SpotVerticesFactory::OccluderType::kTransparent:
|
case SpotVerticesFactory::OccluderType::kTransparent:
|
||||||
color = 0xFFD2B48C; // tan for transparent
|
color = 0xFFD2B48C; // tan for transparent
|
||||||
break;
|
break;
|
||||||
case SpotVerticesFactory::OccluderType::kOpaque:
|
case SpotVerticesFactory::OccluderType::kOpaqueFullUmbra:
|
||||||
|
color = 0xFF614126; // brown for umBra
|
||||||
|
break;
|
||||||
|
case SpotVerticesFactory::OccluderType::kOpaquePartialUmbra:
|
||||||
color = 0xFFFFA500; // orange for opaque
|
color = 0xFFFFA500; // orange for opaque
|
||||||
break;
|
break;
|
||||||
case SpotVerticesFactory::OccluderType::kOpaqueCoversUmbra:
|
case SpotVerticesFactory::OccluderType::kOpaqueNoUmbra:
|
||||||
color = SK_ColorYELLOW; // corn yellow for covered
|
color = 0xFFE5E500; // corn yellow for covered
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user