aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar vjiaoblack <vjiaoblack@google.com>2016-08-25 06:30:23 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-08-25 06:30:23 -0700
commite6f5d5623160a69e1585f5121a3695092327dfe0 (patch)
tree44a73f37db340157c73e005841207e52210e78d0 /src
parent199a2ea665a088dafb2fd364f3aa6a642bfa2fef (diff)
Made shadows blurry (thru implementing variance mapping)
Diffstat (limited to 'src')
-rw-r--r--src/core/SkCanvas.cpp49
-rw-r--r--src/core/SkLiteDL.cpp13
-rw-r--r--src/core/SkLiteDL.h3
-rw-r--r--src/core/SkLiteRecorder.cpp5
-rw-r--r--src/core/SkLiteRecorder.h6
-rw-r--r--src/core/SkPictureRecord.cpp4
-rw-r--r--src/core/SkPictureRecord.h10
-rw-r--r--src/core/SkRecordDraw.cpp2
-rw-r--r--src/core/SkRecorder.cpp9
-rw-r--r--src/core/SkRecorder.h6
-rw-r--r--src/core/SkShadowShader.cpp141
-rw-r--r--src/core/SkShadowShader.h3
-rw-r--r--src/utils/SkShadowPaintFilterCanvas.cpp21
-rw-r--r--src/utils/SkShadowPaintFilterCanvas.h2
14 files changed, 203 insertions, 71 deletions
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 8f77afe78e..0b14368b6e 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -38,13 +38,13 @@
#include "SkTextFormatParams.h"
#include "SkTLazy.h"
#include "SkTraceEvent.h"
-
#include <new>
#if SK_SUPPORT_GPU
#include "GrContext.h"
#include "GrRenderTarget.h"
#include "SkGrPriv.h"
+
#endif
#define RETURN_ON_NULL(ptr) do { if (nullptr == (ptr)) return; } while (0)
@@ -3163,17 +3163,19 @@ void SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
#ifdef SK_EXPERIMENTAL_SHADOWING
void SkCanvas::drawShadowedPicture(const SkPicture* picture,
const SkMatrix* matrix,
- const SkPaint* paint) {
+ const SkPaint* paint,
+ const SkShadowParams& params) {
RETURN_ON_NULL(picture);
TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawShadowedPicture()");
- this->onDrawShadowedPicture(picture, matrix, paint);
+ this->onDrawShadowedPicture(picture, matrix, paint, params);
}
void SkCanvas::onDrawShadowedPicture(const SkPicture* picture,
const SkMatrix* matrix,
- const SkPaint* paint) {
+ const SkPaint* paint,
+ const SkShadowParams& params) {
if (!paint || paint->canComputeFastBounds()) {
SkRect bounds = picture->cullRect();
if (paint) {
@@ -3189,6 +3191,11 @@ void SkCanvas::onDrawShadowedPicture(const SkPicture* picture,
SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
+ sk_sp<SkImage> povDepthMap;
+ sk_sp<SkImage> diffuseMap;
+
+ // TODO: pass the depth to the shader in vertices, or uniforms
+ // so we don't have to render depth and color separately
for (int i = 0; i < fLights->numLights(); ++i) {
// skip over ambient lights; they don't cast shadows
// lights that have shadow maps do not need updating (because lights are immutable)
@@ -3217,23 +3224,36 @@ void SkCanvas::onDrawShadowedPicture(const SkPicture* picture,
// Wrap another SPFCanvas around the surface
sk_sp<SkShadowPaintFilterCanvas> depthMapCanvas =
sk_make_sp<SkShadowPaintFilterCanvas>(surf->getCanvas());
+ depthMapCanvas->setShadowParams(params);
// set the depth map canvas to have the light we're drawing.
SkLights::Builder builder;
builder.add(fLights->light(i));
sk_sp<SkLights> curLight = builder.finish();
-
depthMapCanvas->setLights(std::move(curLight));
+
depthMapCanvas->drawPicture(picture);
+ sk_sp<SkImage> depthMap = surf->makeImageSnapshot();
- fLights->light(i).setShadowMap(surf->makeImageSnapshot());
- }
+ if (params.fType == SkShadowParams::kNoBlur_ShadowType) {
+ fLights->light(i).setShadowMap(std::move(depthMap));
+ } else if (params.fType == SkShadowParams::kVariance_ShadowType) {
+ // we blur the variance map
+ SkPaint blurPaint;
+ blurPaint.setImageFilter(SkImageFilter::MakeBlur(params.fShadowRadius,
+ params.fShadowRadius, nullptr));
- sk_sp<SkImage> povDepthMap;
- sk_sp<SkImage> diffuseMap;
+ SkImageInfo blurInfo = SkImageInfo::Make(shMapSize.fWidth, shMapSize.fHeight,
+ kBGRA_8888_SkColorType,
+ kOpaque_SkAlphaType);
- // TODO: pass the depth to the shader in vertices, or uniforms
- // so we don't have to render depth and color separately
+ sk_sp<SkSurface> blurSurf(this->makeSurface(blurInfo));
+
+ blurSurf->getCanvas()->drawImage(std::move(depthMap), 0, 0, &blurPaint);
+
+ fLights->light(i).setShadowMap(blurSurf->makeImageSnapshot());
+ }
+ }
// povDepthMap
{
@@ -3259,7 +3279,6 @@ void SkCanvas::onDrawShadowedPicture(const SkPicture* picture,
depthMapCanvas->setLights(std::move(povLight));
depthMapCanvas->drawPicture(picture);
-
povDepthMap = surf->makeImageSnapshot();
}
@@ -3275,20 +3294,18 @@ void SkCanvas::onDrawShadowedPicture(const SkPicture* picture,
diffuseMap = surf->makeImageSnapshot();
}
-
SkPaint shadowPaint;
sk_sp<SkShader> povDepthShader = povDepthMap->makeShader(SkShader::kClamp_TileMode,
SkShader::kClamp_TileMode);
-
sk_sp<SkShader> diffuseShader = diffuseMap->makeShader(SkShader::kClamp_TileMode,
SkShader::kClamp_TileMode);
-
sk_sp<SkShader> shadowShader = SkShadowShader::Make(std::move(povDepthShader),
std::move(diffuseShader),
std::move(fLights),
diffuseMap->width(),
- diffuseMap->height());
+ diffuseMap->height(),
+ params);
shadowPaint.setShader(shadowShader);
diff --git a/src/core/SkLiteDL.cpp b/src/core/SkLiteDL.cpp
index f7fe578c4e..d94e1399d6 100644
--- a/src/core/SkLiteDL.cpp
+++ b/src/core/SkLiteDL.cpp
@@ -270,17 +270,20 @@ namespace {
};
struct DrawShadowedPicture final : Op {
static const auto kType = Type::DrawShadowedPicture;
- DrawShadowedPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint)
+ DrawShadowedPicture(const SkPicture* picture, const SkMatrix* matrix,
+ const SkPaint* paint, const SkShadowParams& params)
: picture(sk_ref_sp(picture)) {
if (matrix) { this->matrix = *matrix; }
if (paint) { this->paint = *paint; }
+ this->params = params;
}
sk_sp<const SkPicture> picture;
SkMatrix matrix = SkMatrix::I();
SkPaint paint;
+ SkShadowParams params;
void draw(SkCanvas* c, const SkMatrix&) {
#ifdef SK_EXPERIMENTAL_SHADOWING
- c->drawShadowedPicture(picture.get(), &matrix, &paint);
+ c->drawShadowedPicture(picture.get(), &matrix, &paint, params);
#endif
}
void makeThreadsafe() { make_threadsafe(nullptr, &matrix); }
@@ -615,9 +618,9 @@ void SkLiteDL::drawPicture(const SkPicture* picture,
const SkMatrix* matrix, const SkPaint* paint) {
this->push<DrawPicture>(0, picture, matrix, paint);
}
-void SkLiteDL::drawShadowedPicture(const SkPicture* picture,
- const SkMatrix* matrix, const SkPaint* paint) {
- this->push<DrawShadowedPicture>(0, picture, matrix, paint);
+void SkLiteDL::drawShadowedPicture(const SkPicture* picture, const SkMatrix* matrix,
+ const SkPaint* paint, const SkShadowParams& params) {
+ push<DrawShadowedPicture>(0, picture, matrix, paint, params);
}
void SkLiteDL::drawBitmap(const SkBitmap& bm, SkScalar x, SkScalar y, const SkPaint* paint) {
diff --git a/src/core/SkLiteDL.h b/src/core/SkLiteDL.h
index 400b242322..4f28486840 100644
--- a/src/core/SkLiteDL.h
+++ b/src/core/SkLiteDL.h
@@ -48,7 +48,8 @@ public:
void drawAnnotation (const SkRect&, const char*, SkData*);
void drawDrawable (SkDrawable*, const SkMatrix*);
void drawPicture (const SkPicture*, const SkMatrix*, const SkPaint*);
- void drawShadowedPicture(const SkPicture*, const SkMatrix*, const SkPaint*);
+ void drawShadowedPicture(const SkPicture*, const SkMatrix*,
+ const SkPaint*, const SkShadowParams& params);
void drawText (const void*, size_t, SkScalar, SkScalar, const SkPaint&);
void drawPosText (const void*, size_t, const SkPoint[], const SkPaint&);
diff --git a/src/core/SkLiteRecorder.cpp b/src/core/SkLiteRecorder.cpp
index 3b3c24cf5c..42218acd93 100644
--- a/src/core/SkLiteRecorder.cpp
+++ b/src/core/SkLiteRecorder.cpp
@@ -189,6 +189,7 @@ void SkLiteRecorder::didTranslateZ(SkScalar dz) {
}
void SkLiteRecorder::onDrawShadowedPicture(const SkPicture* picture,
const SkMatrix* matrix,
- const SkPaint* paint) {
- fDL->drawShadowedPicture(picture, matrix, paint);
+ const SkPaint* paint,
+ const SkShadowParams& params) {
+ fDL->drawShadowedPicture(picture, matrix, paint, params);
}
diff --git a/src/core/SkLiteRecorder.h b/src/core/SkLiteRecorder.h
index e2d754d30d..c4e80cd246 100644
--- a/src/core/SkLiteRecorder.h
+++ b/src/core/SkLiteRecorder.h
@@ -76,10 +76,12 @@ public:
#ifdef SK_EXPERIMENTAL_SHADOWING
void didTranslateZ(SkScalar) override;
- void onDrawShadowedPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override;
+ void onDrawShadowedPicture(const SkPicture*, const SkMatrix*,
+ const SkPaint*, const SkShadowParams& params) override;
#else
void didTranslateZ(SkScalar);
- void onDrawShadowedPicture(const SkPicture*, const SkMatrix*, const SkPaint*);
+ void onDrawShadowedPicture(const SkPicture*, const SkMatrix*,
+ const SkPaint*, const SkShadowParams& params);
#endif
private:
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
index 2140795b3d..c461bfbbac 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -666,11 +666,13 @@ void SkPictureRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* ma
void SkPictureRecord::onDrawShadowedPicture(const SkPicture* picture,
const SkMatrix* matrix,
- const SkPaint* paint) {
+ const SkPaint* paint,
+ const SkShadowParams& params) {
// op + picture index
size_t size = 2 * kUInt32Size;
size_t initialOffset;
+ // TODO: handle recording params.
if (nullptr == matrix && nullptr == paint) {
initialOffset = this->addDraw(DRAW_PICTURE, &size);
this->addPicture(picture);
diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h
index 610e6d1c4c..5601d2ac08 100644
--- a/src/core/SkPictureRecord.h
+++ b/src/core/SkPictureRecord.h
@@ -212,13 +212,11 @@ protected:
void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override;
#ifdef SK_EXPERIMENTAL_SHADOWING
- void onDrawShadowedPicture(const SkPicture*,
- const SkMatrix*,
- const SkPaint*) override;
+ void onDrawShadowedPicture(const SkPicture*, const SkMatrix*,
+ const SkPaint*, const SkShadowParams& params) override;
#else
- void onDrawShadowedPicture(const SkPicture*,
- const SkMatrix*,
- const SkPaint*);
+ void onDrawShadowedPicture(const SkPicture*, const SkMatrix*,
+ const SkPaint*, const SkShadowParams& params);
#endif
void onDrawDrawable(SkDrawable*, const SkMatrix*) override;
diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp
index 2b7b9726bd..5b4bc6af6c 100644
--- a/src/core/SkRecordDraw.cpp
+++ b/src/core/SkRecordDraw.cpp
@@ -118,7 +118,7 @@ DRAW(DrawPatch, drawPatch(r.cubics, r.colors, r.texCoords, r.xmode, r.paint));
DRAW(DrawPicture, drawPicture(r.picture.get(), &r.matrix, r.paint));
#ifdef SK_EXPERIMENTAL_SHADOWING
-DRAW(DrawShadowedPicture, drawShadowedPicture(r.picture.get(), &r.matrix, r.paint));
+DRAW(DrawShadowedPicture, drawShadowedPicture(r.picture.get(), &r.matrix, r.paint, r.params));
#else
template <> void Draw::draw(const DrawShadowedPicture& r) { }
#endif
diff --git a/src/core/SkRecorder.cpp b/src/core/SkRecorder.cpp
index caa9bb58c3..214b075ce7 100644
--- a/src/core/SkRecorder.cpp
+++ b/src/core/SkRecorder.cpp
@@ -303,15 +303,16 @@ void SkRecorder::onDrawPicture(const SkPicture* pic, const SkMatrix* matrix, con
}
}
-void SkRecorder::onDrawShadowedPicture(const SkPicture* pic,
- const SkMatrix* matrix,
- const SkPaint* paint) {
+void SkRecorder::onDrawShadowedPicture(const SkPicture* pic, const SkMatrix* matrix,
+ const SkPaint* paint, const SkShadowParams& params) {
if (fDrawPictureMode == Record_DrawPictureMode) {
fApproxBytesUsedBySubPictures += SkPictureUtils::ApproximateBytesUsed(pic);
APPEND(DrawShadowedPicture, this->copy(paint),
sk_ref_sp(pic),
- matrix ? *matrix : SkMatrix::I());
+ matrix ? *matrix : SkMatrix::I(),
+ params);
} else {
+ // TODO update pic->playback(this) to draw the shadowed pic
SkASSERT(fDrawPictureMode == Playback_DrawPictureMode);
SkAutoCanvasMatrixPaint acmp(this, matrix, paint, pic->cullRect());
pic->playback(this);
diff --git a/src/core/SkRecorder.h b/src/core/SkRecorder.h
index 9f8824f85a..6892894927 100644
--- a/src/core/SkRecorder.h
+++ b/src/core/SkRecorder.h
@@ -141,11 +141,13 @@ public:
#ifdef SK_EXPERIMENTAL_SHADOWING
void onDrawShadowedPicture(const SkPicture*,
const SkMatrix*,
- const SkPaint*) override;
+ const SkPaint*,
+ const SkShadowParams& params) override;
#else
void onDrawShadowedPicture(const SkPicture*,
const SkMatrix*,
- const SkPaint*);
+ const SkPaint*,
+ const SkShadowParams& params);
#endif
void onDrawAnnotation(const SkRect&, const char[], SkData*) override;
diff --git a/src/core/SkShadowShader.cpp b/src/core/SkShadowShader.cpp
index 804258321a..9ad23b7c17 100644
--- a/src/core/SkShadowShader.cpp
+++ b/src/core/SkShadowShader.cpp
@@ -5,11 +5,9 @@
* found in the LICENSE file.
*/
-
-#include "SkLights.h"
+#include "SkCanvas.h"
#include "SkReadBuffer.h"
#include "SkShadowShader.h"
-#include "SkPoint3.h"
////////////////////////////////////////////////////////////////////////////
#ifdef SK_EXPERIMENTAL_SHADOWING
@@ -26,12 +24,14 @@ public:
SkShadowShaderImpl(sk_sp<SkShader> povDepthShader,
sk_sp<SkShader> diffuseShader,
sk_sp<SkLights> lights,
- int diffuseWidth, int diffuseHeight)
+ int diffuseWidth, int diffuseHeight,
+ const SkShadowParams& params)
: fPovDepthShader(std::move(povDepthShader))
, fDiffuseShader(std::move(diffuseShader))
, fLights(std::move(lights))
, fDiffuseWidth(diffuseWidth)
- , fDiffuseHeight(diffuseHeight) { }
+ , fDiffuseHeight(diffuseHeight)
+ , fShadowParams(params) { }
bool isOpaque() const override;
@@ -80,6 +80,8 @@ private:
int fDiffuseWidth;
int fDiffuseHeight;
+ SkShadowParams fShadowParams;
+
friend class SkShadowShader;
typedef SkShader INHERITED;
@@ -106,6 +108,7 @@ public:
sk_sp<GrFragmentProcessor> diffuse,
sk_sp<SkLights> lights,
int diffuseWidth, int diffuseHeight,
+ const SkShadowParams& params,
GrContext* context) {
// fuse all ambient lights into a single one
@@ -137,7 +140,9 @@ public:
fWidth = diffuseWidth;
fHeight = diffuseHeight;
- this->registerChildProcessor(std::move(povDepth));
+ fShadowParams = params;
+
+ this->registerChildProcessor(std::move(povDepth));
this->registerChildProcessor(std::move(diffuse));
this->initClassID<ShadowFP>();
}
@@ -155,6 +160,8 @@ public:
int32_t numLights = args.fFp.cast<ShadowFP>().fNumDirLights;
SkASSERT(numLights <= SkShadowShader::kMaxNonAmbientLights);
+ int blurAlgorithm = args.fFp.cast<ShadowFP>().fShadowParams.fType;
+
const char* lightDirUniName[SkShadowShader::kMaxNonAmbientLights] = {nullptr};
const char* lightColorUniName[SkShadowShader::kMaxNonAmbientLights] = {nullptr};
@@ -203,6 +210,17 @@ public:
&depthMapHeightUniName[i]);
}
+ const char* shBiasUniName = nullptr;
+ const char* minVarianceUniName = nullptr;
+
+ fBiasingConstantUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
+ kFloat_GrSLType,
+ kDefault_GrSLPrecision,
+ "shadowBias", &shBiasUniName);
+ fMinVarianceUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
+ kFloat_GrSLType,
+ kDefault_GrSLPrecision,
+ "minVariance", &minVarianceUniName);
const char* widthUniName = nullptr;
const char* heightUniName = nullptr;
@@ -254,17 +272,17 @@ public:
fragBuilder->codeAppendf("vec2 %s = 1 - %s;\n",
scaleOffsetVec.c_str(), scaleVec.c_str());
-
fragBuilder->codeAppendf("vec2 %s = (vMatrixCoord_0_1_Stage0 + "
- "vec2(%s.x, 0 - %s.y)) "
- " * %s + vec2(0,1) * %s;\n",
-
+ "vec2(%s.x, 0 - %s.y)) "
+ " * %s + vec2(0,1) * %s;\n",
povCoord.c_str(), offset.c_str(), offset.c_str(),
scaleVec.c_str(), scaleOffsetVec.c_str());
fragBuilder->appendTextureLookup(&depthMaps[i], args.fTexSamplers[i],
povCoord.c_str(),
kVec2f_GrSLType);
+
+
}
const char* ambientColorUniName = nullptr;
@@ -274,25 +292,58 @@ public:
fragBuilder->codeAppendf("vec4 resultDiffuseColor = %s;", diffuseColor.c_str());
- // Essentially,
- // diffColor * (ambientLightTot + foreachDirLight(lightColor * (N . L)))
SkString totalLightColor("totalLightColor");
- fragBuilder->codeAppendf("vec3 %s = vec3(0);", totalLightColor.c_str());
+ fragBuilder->codeAppendf("vec3 %s = vec3(0,0,0);", totalLightColor.c_str());
+
+ fragBuilder->codeAppendf("float lightProbability;");
+ fragBuilder->codeAppendf("float variance;");
+ fragBuilder->codeAppendf("float d;");
for (int i = 0; i < numLights; i++) {
- fragBuilder->codeAppendf("if (%s.b >= %s.b) {",
+ fragBuilder->codeAppendf("lightProbability = 1;");
+
+ // 1/512 is less than half a pixel; imperceptible
+ fragBuilder->codeAppendf("if (%s.b <= %s.b + 1/512) {",
povDepth.c_str(), depthMaps[i].c_str());
- // Note that dot(vec3(0,0,1), %s) == %s.z * %s
- fragBuilder->codeAppendf("%s += %s.z * %s;",
+ if (blurAlgorithm == SkShadowParams::kVariance_ShadowType) {
+ fragBuilder->codeAppendf("vec2 moments = vec2(%s.b * 255, %s.g * 255 * 256 );",
+ depthMaps[i].c_str(), depthMaps[i].c_str());
+
+ // variance biasing lessens light bleeding
+ fragBuilder->codeAppendf("variance = max(moments.y - (moments.x * moments.x),"
+ "%s);", minVarianceUniName);
+
+ fragBuilder->codeAppendf("d = (%s.b * 255) - moments.x;", povDepth.c_str());
+ fragBuilder->codeAppendf("lightProbability = "
+ "(variance / (variance + d * d));");
+
+ SkString clamp("clamp");
+ clamp.appendf("%d", i);
+
+ // choosing between light artifacts or correct shape shadows
+ // linstep
+ fragBuilder->codeAppendf("float %s = clamp((lightProbability - %s) /"
+ "(1 - %s), 0, 1);",
+ clamp.c_str(), shBiasUniName, shBiasUniName);
+
+ fragBuilder->codeAppendf("lightProbability = %s;", clamp.c_str());
+ } else {
+ fragBuilder->codeAppendf("if (%s.b >= %s.b) {",
+ povDepth.c_str(), depthMaps[i].c_str());
+ fragBuilder->codeAppendf("lightProbability = 1;");
+ fragBuilder->codeAppendf("} else { lightProbability = 0; }");
+ }
+
+ // VSM: The curved shadows near plane edges are mostly light bleeding.
+ fragBuilder->codeAppendf("}");
+
+ fragBuilder->codeAppendf("%s += dot(vec3(0,0,1), %s) * %s * lightProbability;",
totalLightColor.c_str(),
lightDirUniName[i],
lightColorUniName[i]);
- fragBuilder->codeAppendf("}");
}
- fragBuilder->codeAppendf("%s += %s;",
- totalLightColor.c_str(),
- ambientColorUniName);
+ fragBuilder->codeAppendf("%s += %s;", totalLightColor.c_str(), ambientColorUniName);
fragBuilder->codeAppendf("resultDiffuseColor *= vec4(%s, 1);",
totalLightColor.c_str());
@@ -304,15 +355,14 @@ public:
GrProcessorKeyBuilder* b) {
const ShadowFP& shadowFP = proc.cast<ShadowFP>();
b->add32(shadowFP.fNumDirLights);
+ b->add32(shadowFP.fShadowParams.fType);
}
protected:
void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& proc) override {
const ShadowFP &shadowFP = proc.cast<ShadowFP>();
- fNumDirLights = shadowFP.numLights();
-
- for (int i = 0; i < fNumDirLights; i++) {
+ for (int i = 0; i < shadowFP.fNumDirLights; i++) {
const SkVector3& lightDir = shadowFP.lightDir(i);
if (lightDir != fLightDir[i]) {
pdman.set3fv(fLightDirUni[i], 1, &lightDir.fX);
@@ -336,6 +386,18 @@ public:
}
}
+ SkScalar biasingConstant = shadowFP.shadowParams().fBiasingConstant;
+ if (biasingConstant != fBiasingConstant) {
+ pdman.set1f(fBiasingConstantUni, biasingConstant);
+ fBiasingConstant = biasingConstant;
+ }
+
+ SkScalar minVariance = shadowFP.shadowParams().fMinVariance;
+ if (minVariance != fMinVariance) {
+ pdman.set1f(fMinVarianceUni, minVariance);
+ fMinVariance = minVariance;
+ }
+
int width = shadowFP.width();
if (width != fWidth) {
pdman.set1i(fWidthUni, width);
@@ -376,10 +438,13 @@ public:
int fHeight;
GrGLSLProgramDataManager::UniformHandle fHeightUni;
+ SkScalar fBiasingConstant;
+ GrGLSLProgramDataManager::UniformHandle fBiasingConstantUni;
+ SkScalar fMinVariance;
+ GrGLSLProgramDataManager::UniformHandle fMinVarianceUni;
+
SkColor3f fAmbientColor;
GrGLSLProgramDataManager::UniformHandle fAmbientColorUni;
-
- int fNumDirLights;
};
void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
@@ -413,6 +478,8 @@ public:
int width() const {return fWidth; }
int height() const {return fHeight; }
+ const SkShadowParams& shadowParams() const {return fShadowParams; }
+
private:
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new GLSLShadowFP; }
@@ -454,6 +521,8 @@ private:
int fHeight;
int fWidth;
+ SkShadowParams fShadowParams;
+
SkColor3f fAmbientColor;
};
@@ -469,7 +538,7 @@ sk_sp<GrFragmentProcessor> SkShadowShaderImpl::asFragmentProcessor(const AsFPArg
std::move(diffuseFP),
std::move(fLights),
fDiffuseWidth, fDiffuseHeight,
- fpargs.fContext);
+ fShadowParams, fpargs.fContext);
return shadowfp;
}
@@ -594,6 +663,12 @@ sk_sp<SkFlattenable> SkShadowShaderImpl::CreateProc(SkReadBuffer& buf) {
sk_sp<SkLights> lights = SkLights::MakeFromBuffer(buf);
+ SkShadowParams params;
+ params.fMinVariance = buf.readScalar();
+ params.fBiasingConstant = buf.readScalar();
+ params.fType = (SkShadowParams::ShadowType) buf.readInt();
+ params.fShadowRadius = buf.readScalar();
+
int diffuseWidth = buf.readInt();
int diffuseHeight = buf.readInt();
@@ -603,7 +678,8 @@ sk_sp<SkFlattenable> SkShadowShaderImpl::CreateProc(SkReadBuffer& buf) {
return sk_make_sp<SkShadowShaderImpl>(std::move(povDepthShader),
std::move(diffuseShader),
std::move(lights),
- diffuseWidth, diffuseHeight);
+ diffuseWidth, diffuseHeight,
+ params);
}
void SkShadowShaderImpl::flatten(SkWriteBuffer& buf) const {
@@ -611,6 +687,11 @@ void SkShadowShaderImpl::flatten(SkWriteBuffer& buf) const {
fLights->flatten(buf);
+ buf.writeScalar(fShadowParams.fMinVariance);
+ buf.writeScalar(fShadowParams.fBiasingConstant);
+ buf.writeInt(fShadowParams.fType);
+ buf.writeScalar(fShadowParams.fShadowRadius);
+
buf.writeInt(fDiffuseWidth);
buf.writeInt(fDiffuseHeight);
@@ -656,7 +737,8 @@ SkShader::Context* SkShadowShaderImpl::onCreateContext(const ContextRec& rec,
sk_sp<SkShader> SkShadowShader::Make(sk_sp<SkShader> povDepthShader,
sk_sp<SkShader> diffuseShader,
sk_sp<SkLights> lights,
- int diffuseWidth, int diffuseHeight) {
+ int diffuseWidth, int diffuseHeight,
+ const SkShadowParams& params) {
if (!povDepthShader || !diffuseShader) {
// TODO: Use paint's color in absence of a diffuseShader
// TODO: Use a default implementation of normalSource instead
@@ -666,7 +748,8 @@ sk_sp<SkShader> SkShadowShader::Make(sk_sp<SkShader> povDepthShader,
return sk_make_sp<SkShadowShaderImpl>(std::move(povDepthShader),
std::move(diffuseShader),
std::move(lights),
- diffuseWidth, diffuseHeight);
+ diffuseWidth, diffuseHeight,
+ params);
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/SkShadowShader.h b/src/core/SkShadowShader.h
index 163d58acd7..3263950a93 100644
--- a/src/core/SkShadowShader.h
+++ b/src/core/SkShadowShader.h
@@ -23,7 +23,8 @@ public:
static sk_sp<SkShader> Make(sk_sp<SkShader> povDepthShader,
sk_sp<SkShader> diffuseShader,
sk_sp<SkLights> lights,
- int diffuseWidth, int diffuseHeight);
+ int diffuseWidth, int diffuseHeight,
+ const SkShadowParams& params);
// The shadow shader supports any number of ambient lights, but only
// 4 non-ambient lights (currently just refers to directional lights).
diff --git a/src/utils/SkShadowPaintFilterCanvas.cpp b/src/utils/SkShadowPaintFilterCanvas.cpp
index f59facb17c..2a090b78e2 100644
--- a/src/utils/SkShadowPaintFilterCanvas.cpp
+++ b/src/utils/SkShadowPaintFilterCanvas.cpp
@@ -11,7 +11,12 @@
#ifdef SK_EXPERIMENTAL_SHADOWING
SkShadowPaintFilterCanvas::SkShadowPaintFilterCanvas(SkCanvas *canvas)
- : SkPaintFilterCanvas(canvas) { }
+ : SkPaintFilterCanvas(canvas) {
+ fShadowParams.fShadowRadius = 0.0f;
+ fShadowParams.fType = SkShadowParams::kNoBlur_ShadowType;
+ fShadowParams.fBiasingConstant = 0.0f;
+ fShadowParams.fMinVariance = 0.0f;
+}
// TODO use a shader instead
bool SkShadowPaintFilterCanvas::onFilter(SkTCopyOnFirstWrite<SkPaint>* paint, Type type) const {
@@ -24,6 +29,17 @@ bool SkShadowPaintFilterCanvas::onFilter(SkTCopyOnFirstWrite<SkPaint>* paint, Ty
SkColor color = 0xFF000000; // init color to opaque black
color |= z; // Put the index into the blue component
+
+ if (fShadowParams.fType == SkShadowParams::kVariance_ShadowType) {
+ int z2 = z * z;
+ if (z2 > 255 * 256) {
+ color |= 0xff00;
+ } else {
+ // Let's only store the more significant bits of z2 to save space.
+ // In practice, this should barely impact shadow blur quality.
+ color |= z2 & 0x0000ff00;
+ }
+ }
newPaint.setColor(color);
*paint->writable() = newPaint;
@@ -42,6 +58,9 @@ SkISize SkShadowPaintFilterCanvas::ComputeDepthMapSize(const SkLights::Light& li
return SkISize::Make(dMapWidth, dMapHeight);
}
+void SkShadowPaintFilterCanvas::setShadowParams(const SkShadowParams &params) {
+ fShadowParams = params;
+}
void SkShadowPaintFilterCanvas::onDrawPicture(const SkPicture *picture, const SkMatrix *matrix,
const SkPaint *paint) {
diff --git a/src/utils/SkShadowPaintFilterCanvas.h b/src/utils/SkShadowPaintFilterCanvas.h
index 892ec556e5..698f6e1173 100644
--- a/src/utils/SkShadowPaintFilterCanvas.h
+++ b/src/utils/SkShadowPaintFilterCanvas.h
@@ -35,6 +35,7 @@ public:
static SkISize ComputeDepthMapSize(const SkLights::Light& light, int maxDepth,
int width, int height);
+ void setShadowParams(const SkShadowParams &params);
protected:
void onDrawPicture(const SkPicture *picture, const SkMatrix *matrix,
const SkPaint *paint) override;
@@ -107,6 +108,7 @@ protected:
void onDrawTextBlob(const SkTextBlob *blob, SkScalar x,
SkScalar y, const SkPaint &paint) override;
private:
+ SkShadowParams fShadowParams;
typedef SkPaintFilterCanvas INHERITED;
};