Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(483)

Unified Diff: src/core/SkShadowShader.cpp

Issue 2224163005: Made shadows blurry (thru implementing variance mapping) (Closed) Base URL: https://skia.googlesource.com/skia@master
Patch Set: Trying different include path Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/core/SkShadowShader.h ('k') | src/utils/SkShadowPaintFilterCanvas.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/core/SkShadowShader.cpp
diff --git a/src/core/SkShadowShader.cpp b/src/core/SkShadowShader.cpp
index 804258321a80f9ab0bd20b7ffa995878ab079b17..9ad23b7c17ab60e5d1b959580bea710a3a168659 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);
}
///////////////////////////////////////////////////////////////////////////////
« no previous file with comments | « src/core/SkShadowShader.h ('k') | src/utils/SkShadowPaintFilterCanvas.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698