Fix directional shadows.
The xy offset calculation for drawShadow was not quite correct. Rather than normalizing the light vector and using the xy values of that as the base offset value, we should scale the light vector by 1/z. See https://github.com/flutter/engine/pull/27124#issuecomment-880182653 for more detail. Bug: skia:10781 Change-Id: Ib69a313cb96a532f8d89644e3d69f666a184e897 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/428880 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Jim Van Verth <jvanverth@google.com>
This commit is contained in:
parent
dfec4f98ef
commit
6789b82401
@ -34,7 +34,7 @@ class MaterialShadowsView : public Sample {
|
||||
fLargeRRPath.addRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(-64, -64, 128, 128), 4, 4));
|
||||
fSmallRRPath.addRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(-40, -40, 80, 80), 4, 4));
|
||||
|
||||
fLightPos = SkPoint3::Make(0, -700, 600);
|
||||
fLightPos = SkPoint3::Make(0, -700, 700);
|
||||
}
|
||||
|
||||
SkString name() override { return SkString("MaterialShadows"); }
|
||||
|
@ -151,10 +151,8 @@ void GetLocalBounds(const SkPath& path, const SkDrawShadowRec& rec, const SkMatr
|
||||
|
||||
// get spot params (in device space)
|
||||
if (SkToBool(rec.fFlags & SkShadowFlags::kDirectionalLight_ShadowFlag)) {
|
||||
SkPoint3 lightDir = rec.fLightPos;
|
||||
lightDir.normalize();
|
||||
SkDrawShadowMetrics::GetDirectionalParams(occluderZ, lightDir.fX, lightDir.fY,
|
||||
lightDir.fZ, rec.fLightRadius,
|
||||
SkDrawShadowMetrics::GetDirectionalParams(occluderZ, rec.fLightPos.fX, rec.fLightPos.fY,
|
||||
rec.fLightPos.fZ, rec.fLightRadius,
|
||||
&spotBlur, &spotScale, &spotOffset);
|
||||
} else {
|
||||
SkPoint devLightPos = SkPoint::Make(rec.fLightPos.fX, rec.fLightPos.fY);
|
||||
@ -172,10 +170,8 @@ void GetLocalBounds(const SkPath& path, const SkDrawShadowRec& rec, const SkMatr
|
||||
|
||||
// get spot params (in local space)
|
||||
if (SkToBool(rec.fFlags & SkShadowFlags::kDirectionalLight_ShadowFlag)) {
|
||||
SkPoint3 lightDir = rec.fLightPos;
|
||||
lightDir.normalize();
|
||||
SkDrawShadowMetrics::GetDirectionalParams(occluderZ, lightDir.fX, lightDir.fY,
|
||||
lightDir.fZ, rec.fLightRadius,
|
||||
SkDrawShadowMetrics::GetDirectionalParams(occluderZ, rec.fLightPos.fX, rec.fLightPos.fY,
|
||||
rec.fLightPos.fZ, rec.fLightRadius,
|
||||
&spotBlur, &spotScale, &spotOffset);
|
||||
// light dir is in device space, so need to map spot offset back into local space
|
||||
SkMatrix inverse;
|
||||
|
@ -68,8 +68,10 @@ inline void GetDirectionalParams(SkScalar occluderZ, SkScalar lightX, SkScalar l
|
||||
SkScalar* blurRadius, SkScalar* scale, SkVector* translate) {
|
||||
*blurRadius = lightRadius*occluderZ;
|
||||
*scale = 1;
|
||||
// assumption here is that light direction is normalized
|
||||
*translate = SkVector::Make(-occluderZ * lightX, -occluderZ * lightY);
|
||||
// Max z-ratio is "max expected elevation"/"min allowable z"
|
||||
constexpr SkScalar kMaxZRatio = 64/SK_ScalarNearlyZero;
|
||||
SkScalar zRatio = divide_and_pin(occluderZ, lightZ, 0.0f, kMaxZRatio);
|
||||
*translate = SkVector::Make(-zRatio * lightX, -zRatio * lightY);
|
||||
}
|
||||
|
||||
// Create the transformation to apply to a path to get its base shadow outline, given the light
|
||||
|
@ -1152,9 +1152,7 @@ bool GrSurfaceDrawContext::drawFastShadow(const GrClip* clip,
|
||||
|
||||
SkPoint3 devLightPos = rec.fLightPos;
|
||||
bool directional = SkToBool(rec.fFlags & kDirectionalLight_ShadowFlag);
|
||||
if (directional) {
|
||||
devLightPos.normalize();
|
||||
} else {
|
||||
if (!directional) {
|
||||
// transform light
|
||||
viewMatrix.mapPoints((SkPoint*)&devLightPos.fX, 1);
|
||||
}
|
||||
|
@ -664,9 +664,7 @@ void SkBaseDevice::drawShadow(const SkPath& path, const SkDrawShadowRec& rec) {
|
||||
|
||||
SkPoint3 zPlaneParams = rec.fZPlaneParams;
|
||||
SkPoint3 devLightPos = rec.fLightPos;
|
||||
if (directional) {
|
||||
devLightPos.normalize();
|
||||
} else {
|
||||
if (!directional) {
|
||||
viewMatrix.mapPoints((SkPoint*)&devLightPos.fX, 1);
|
||||
}
|
||||
float lightRadius = rec.fLightRadius;
|
||||
|
Loading…
Reference in New Issue
Block a user