Fix shadow directional light bounds.
The shadowRec bounds code didn't handle directional lights, that's now fixed. Also fixes normalization of the light direction -- it was only using two components, it should use all three. Bug: skia:10781 Change-Id: Ia7d39c5187f976627d017ac4abecbe1d1dc62712 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/345126 Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Jim Van Verth <jvanverth@google.com>
This commit is contained in:
parent
dc3332a079
commit
a8682204dc
@ -266,7 +266,7 @@ DEF_SIMPLE_GM(shadow_utils_directional, canvas, 256, 384) {
|
||||
static constexpr SkScalar kHeight = 12.f;
|
||||
|
||||
SkPath rrect(SkPath::RRect(SkRect::MakeLTRB(-25, -25, 25, 25), 10, 10));
|
||||
SkPoint3 lightPos = { -45, -45, 500 };
|
||||
SkPoint3 lightPos = { -45, -45, 45 };
|
||||
|
||||
SkColor ambientColor = SkColorSetARGB(0.02f * 255, 0, 0, 0);
|
||||
SkColor spotColor = SkColorSetARGB(0.35f * 255, 0, 0, 0);
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "include/core/SkMatrix.h"
|
||||
#include "include/core/SkPath.h"
|
||||
#include "include/core/SkRect.h"
|
||||
#include "include/private/SkShadowFlags.h"
|
||||
#include "src/core/SkDrawShadowInfo.h"
|
||||
#include "src/utils/SkPolyUtils.h"
|
||||
|
||||
@ -149,11 +150,19 @@ void GetLocalBounds(const SkPath& path, const SkDrawShadowRec& rec, const SkMatr
|
||||
ambientBlur = SkDrawShadowMetrics::AmbientBlurRadius(occluderZ);
|
||||
|
||||
// get spot params (in device space)
|
||||
SkPoint devLightPos = SkPoint::Make(rec.fLightPos.fX, rec.fLightPos.fY);
|
||||
ctm.mapPoints(&devLightPos, 1);
|
||||
SkDrawShadowMetrics::GetSpotParams(occluderZ, devLightPos.fX, devLightPos.fY,
|
||||
rec.fLightPos.fZ, rec.fLightRadius,
|
||||
&spotBlur, &spotScale, &spotOffset);
|
||||
if (SkToBool(rec.fFlags & SkShadowFlags::kDirectionalLight_ShadowFlag)) {
|
||||
SkPoint3 lightDir = rec.fLightPos;
|
||||
lightDir.normalize();
|
||||
SkDrawShadowMetrics::GetDirectionalParams(occluderZ, lightDir.fX, lightDir.fY,
|
||||
lightDir.fZ, rec.fLightRadius,
|
||||
&spotBlur, &spotScale, &spotOffset);
|
||||
} else {
|
||||
SkPoint devLightPos = SkPoint::Make(rec.fLightPos.fX, rec.fLightPos.fY);
|
||||
ctm.mapPoints(&devLightPos, 1);
|
||||
SkDrawShadowMetrics::GetSpotParams(occluderZ, devLightPos.fX, devLightPos.fY,
|
||||
rec.fLightPos.fZ, rec.fLightRadius,
|
||||
&spotBlur, &spotScale, &spotOffset);
|
||||
}
|
||||
} else {
|
||||
SkScalar devToSrcScale = SkScalarInvert(ctm.getMinScale());
|
||||
|
||||
@ -162,9 +171,22 @@ void GetLocalBounds(const SkPath& path, const SkDrawShadowRec& rec, const SkMatr
|
||||
ambientBlur = devSpaceAmbientBlur*devToSrcScale;
|
||||
|
||||
// get spot params (in local space)
|
||||
SkDrawShadowMetrics::GetSpotParams(occluderZ, rec.fLightPos.fX, rec.fLightPos.fY,
|
||||
rec.fLightPos.fZ, rec.fLightRadius,
|
||||
&spotBlur, &spotScale, &spotOffset);
|
||||
if (SkToBool(rec.fFlags & SkShadowFlags::kDirectionalLight_ShadowFlag)) {
|
||||
SkPoint3 lightDir = rec.fLightPos;
|
||||
lightDir.normalize();
|
||||
SkDrawShadowMetrics::GetDirectionalParams(occluderZ, lightDir.fX, lightDir.fY,
|
||||
lightDir.fZ, rec.fLightRadius,
|
||||
&spotBlur, &spotScale, &spotOffset);
|
||||
// light dir is in device space, so need to map spot offset back into local space
|
||||
SkMatrix inverse;
|
||||
if (ctm.invert(&inverse)) {
|
||||
inverse.mapVectors(&spotOffset, 1);
|
||||
}
|
||||
} else {
|
||||
SkDrawShadowMetrics::GetSpotParams(occluderZ, rec.fLightPos.fX, rec.fLightPos.fY,
|
||||
rec.fLightPos.fZ, rec.fLightRadius,
|
||||
&spotBlur, &spotScale, &spotOffset);
|
||||
}
|
||||
|
||||
// convert spot blur to local space
|
||||
spotBlur *= devToSrcScale;
|
||||
|
@ -1067,7 +1067,7 @@ bool GrSurfaceDrawContext::drawFastShadow(const GrClip* clip,
|
||||
SkPoint3 devLightPos = rec.fLightPos;
|
||||
bool directional = SkToBool(rec.fFlags & kDirectionalLight_ShadowFlag);
|
||||
if (directional) {
|
||||
((SkPoint*)&devLightPos.fX)->normalize();
|
||||
devLightPos.normalize();
|
||||
} else {
|
||||
// transform light
|
||||
viewMatrix.mapPoints((SkPoint*)&devLightPos.fX, 1);
|
||||
|
@ -629,7 +629,7 @@ void SkBaseDevice::drawShadow(const SkPath& path, const SkDrawShadowRec& rec) {
|
||||
SkPoint3 zPlaneParams = rec.fZPlaneParams;
|
||||
SkPoint3 devLightPos = rec.fLightPos;
|
||||
if (directional) {
|
||||
((SkPoint*)&devLightPos.fX)->normalize();
|
||||
devLightPos.normalize();
|
||||
} else {
|
||||
viewMatrix.mapPoints((SkPoint*)&devLightPos.fX, 1);
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ DEF_TEST(ShadowUtils, reporter) {
|
||||
}
|
||||
|
||||
void check_xformed_bounds(skiatest::Reporter* reporter, const SkPath& path, const SkMatrix& ctm) {
|
||||
const SkDrawShadowRec rec = {
|
||||
SkDrawShadowRec rec = {
|
||||
SkPoint3::Make(0, 0, 4),
|
||||
SkPoint3::Make(100, 0, 600),
|
||||
800.f,
|
||||
@ -131,7 +131,7 @@ void check_xformed_bounds(skiatest::Reporter* reporter, const SkPath& path, cons
|
||||
0x40000000,
|
||||
0
|
||||
};
|
||||
// TODO: implement bounds calculation for directional lights
|
||||
// point light
|
||||
SkRect bounds;
|
||||
SkDrawShadowMetrics::GetLocalBounds(path, rec, ctm, &bounds);
|
||||
ctm.mapRect(&bounds);
|
||||
@ -148,6 +148,25 @@ void check_xformed_bounds(skiatest::Reporter* reporter, const SkPath& path, cons
|
||||
if (verts) {
|
||||
REPORTER_ASSERT(reporter, bounds.contains(verts->bounds()));
|
||||
}
|
||||
|
||||
// directional light
|
||||
rec.fFlags |= SkShadowFlags::kDirectionalLight_ShadowFlag;
|
||||
rec.fLightRadius = 2.0f;
|
||||
SkDrawShadowMetrics::GetLocalBounds(path, rec, ctm, &bounds);
|
||||
ctm.mapRect(&bounds);
|
||||
|
||||
verts = SkShadowTessellator::MakeAmbient(path, ctm, rec.fZPlaneParams, true);
|
||||
if (verts) {
|
||||
REPORTER_ASSERT(reporter, bounds.contains(verts->bounds()));
|
||||
}
|
||||
|
||||
devLightPos = rec.fLightPos;
|
||||
devLightPos.normalize();
|
||||
verts = SkShadowTessellator::MakeSpot(path, ctm, rec.fZPlaneParams, devLightPos,
|
||||
rec.fLightRadius, false, true);
|
||||
if (verts) {
|
||||
REPORTER_ASSERT(reporter, bounds.contains(verts->bounds()));
|
||||
}
|
||||
}
|
||||
|
||||
void check_bounds(skiatest::Reporter* reporter, const SkPath& path) {
|
||||
|
Loading…
Reference in New Issue
Block a user