Index: src/core/SkShadowShader.cpp |
diff --git a/src/core/SkShadowShader.cpp b/src/core/SkShadowShader.cpp |
index 5fc992acc14dd790ab86e43e6a761ecc7b7db8bc..9f7ea5ebae4bb64bbcc74bd56e2467edfb2758fb 100644 |
--- a/src/core/SkShadowShader.cpp |
+++ b/src/core/SkShadowShader.cpp |
@@ -26,12 +26,14 @@ public: |
SkShadowShaderImpl(sk_sp<SkShader> povDepthShader, |
sk_sp<SkShader> diffuseShader, |
sk_sp<SkLights> lights, |
- int diffuseWidth, int diffuseHeight) |
+ int diffuseWidth, int diffuseHeight, |
+ SkShadowType sType) |
: fPovDepthShader(std::move(povDepthShader)) |
, fDiffuseShader(std::move(diffuseShader)) |
, fLights(std::move(lights)) |
, fDiffuseWidth(diffuseWidth) |
- , fDiffuseHeight(diffuseHeight) { } |
+ , fDiffuseHeight(diffuseHeight) |
+ , fShType(sType) { } |
bool isOpaque() const override; |
@@ -80,6 +82,8 @@ private: |
int fDiffuseWidth; |
int fDiffuseHeight; |
+ SkShadowType fShType; |
+ |
friend class SkShadowShader; |
typedef SkShader INHERITED; |
@@ -106,6 +110,7 @@ public: |
sk_sp<GrFragmentProcessor> diffuse, |
sk_sp<SkLights> lights, |
int diffuseWidth, int diffuseHeight, |
+ SkShadowType sType, |
GrContext* context) { |
// fuse all ambient lights into a single one |
@@ -137,6 +142,11 @@ public: |
fWidth = diffuseWidth; |
fHeight = diffuseHeight; |
+ fShType = sType; |
+ |
+ |
+// printf("init: %d\n", sType.fBlurAlgorithm); |
jvanverth1
2016/08/12 17:39:09
Remove this or put in #ifdef block (e.g. #ifdef DU
vjiaoblack
2016/08/12 19:07:42
Thanks! Done.
|
+ |
this->registerChildProcessor(std::move(povDepth)); |
this->registerChildProcessor(std::move(diffuse)); |
this->initClassID<ShadowFP>(); |
@@ -155,6 +165,8 @@ public: |
int32_t numLights = args.fFp.cast<ShadowFP>().fNumDirLights; |
SkASSERT(numLights <= SkShadowShader::kMaxNonAmbientLights); |
+ int blurAlgorithm = args.fFp.cast<ShadowFP>().fShType.fBlurAlgorithm; |
+ |
const char* lightDirUniName[SkShadowShader::kMaxNonAmbientLights] = {nullptr}; |
const char* lightColorUniName[SkShadowShader::kMaxNonAmbientLights] = {nullptr}; |
@@ -203,6 +215,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 +277,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 +297,70 @@ public: |
fragBuilder->codeAppendf("vec4 resultDiffuseColor = %s;", diffuseColor.c_str()); |
- // Essentially, |
- // diffColor * (ambientLightTot + foreachDirLight(lightColor * (N . L))) |
+ // all the normal vectors point straight up |
SkString totalLightColor("totalLightColor"); |
- fragBuilder->codeAppendf("vec3 %s = vec3(0);", totalLightColor.c_str()); |
+ fragBuilder->codeAppendf("vec3 %s = vec3(0,0,0);", totalLightColor.c_str()); |
+ |
+ SkString lightProb("lightProbability"); |
+ fragBuilder->codeAppendf("float %s;", lightProb.c_str()); |
+ fragBuilder->codeAppendf("float variance;"); |
+ fragBuilder->codeAppendf("float d;"); |
for (int i = 0; i < numLights; i++) { |
- fragBuilder->codeAppendf("if (%s.b >= %s.b) {", |
+ fragBuilder->codeAppendf("%s = 1;", lightProb.c_str()); |
+ |
+ // 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 == SkShadowType::kVariance_BlurAlgorithm) { |
+ 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("%s = (variance / (variance + d * d));", |
+ lightProb.c_str()); |
+ |
+ SkString clamp("clamp"); |
+ clamp.appendf("%d", i); |
+ |
+ // choosing between light artifacts or correct shape shadows |
+ // linstep |
+ fragBuilder->codeAppendf("float %s = clamp((%s - %s) / (1 - %s), 0, 1);", |
+ clamp.c_str(), lightProb.c_str(), |
+ shBiasUniName, shBiasUniName); |
+ |
+ // different bias types |
+ // sqrt pulls in and makes an edge |
+ // pow2 pushes out |
+ // fragBuilder->codeAppendf("%s = %s * %s * (3.0 - 2.0 * %s);", |
+ // lightProb.c_str(), clamp.c_str(), clamp.c_str(), clamp.c_str()); |
jvanverth1
2016/08/12 17:39:09
Line length > 100? And are these commented out lin
vjiaoblack
2016/08/12 19:07:42
I would like to keep them as comments to document
jvanverth1
2016/08/12 19:44:10
Then I would block them out with an #ifdef, just l
|
+ // fragBuilder->codeAppendf("%s = 6 * pow(%s, 5) - 15 * pow(%s, 4) + 10 * pow(%s, 3);", |
+ // lightProb.c_str(), clamp.c_str(), clamp.c_str(), clamp.c_str()); |
+ |
+ fragBuilder->codeAppendf("%s = %s;", |
+ lightProb.c_str(), clamp.c_str()); |
+ } else { |
+ fragBuilder->codeAppendf("if (%s.b >= %s.b) {", |
+ povDepth.c_str(), depthMaps[i].c_str()); |
+ fragBuilder->codeAppendf("%s = 1;", lightProb.c_str()); |
+ fragBuilder->codeAppendf("} else { %s = 0; }", lightProb.c_str()); |
+ } |
+ |
+ // VSM: The curved shadows near plane edges are mostly light bleeding. |
+ fragBuilder->codeAppendf("}"); |
+ |
+ fragBuilder->codeAppendf("%s += dot(vec3(0,0,1), %s) * %s * %s;", |
totalLightColor.c_str(), |
lightDirUniName[i], |
- lightColorUniName[i]); |
- fragBuilder->codeAppendf("}"); |
+ lightColorUniName[i], |
+ lightProb.c_str()); |
} |
- 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 +372,14 @@ public: |
GrProcessorKeyBuilder* b) { |
const ShadowFP& shadowFP = proc.cast<ShadowFP>(); |
b->add32(shadowFP.fNumDirLights); |
+ b->add32(shadowFP.fShType.fBlurAlgorithm); |
} |
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 +403,18 @@ public: |
} |
} |
+ SkScalar biasingConstant = shadowFP.shadowType().fBiasingConstant; |
+ if (biasingConstant != fBiasingConstant) { |
+ pdman.set1f(fBiasingConstantUni, biasingConstant); |
+ fBiasingConstant = biasingConstant; |
+ } |
+ |
+ SkScalar minVariance = shadowFP.shadowType().fMinVariance; |
+ if (minVariance != fMinVariance) { |
+ pdman.set1f(fMinVarianceUni, minVariance); |
+ fMinVariance = minVariance; |
+ } |
+ |
int width = shadowFP.width(); |
if (width != fWidth) { |
pdman.set1i(fWidthUni, width); |
@@ -376,10 +455,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 +495,8 @@ public: |
int width() const {return fWidth; } |
int height() const {return fHeight; } |
+ SkShadowType shadowType() const {return fShType; } |
+ |
private: |
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new GLSLShadowFP; } |
@@ -454,6 +538,8 @@ private: |
int fHeight; |
int fWidth; |
+ SkShadowType fShType; |
+ |
SkColor3f fAmbientColor; |
}; |
@@ -469,7 +555,7 @@ sk_sp<GrFragmentProcessor> SkShadowShaderImpl::asFragmentProcessor(const AsFPArg |
std::move(diffuseFP), |
std::move(fLights), |
fDiffuseWidth, fDiffuseHeight, |
- fpargs.fContext); |
+ fShType, fpargs.fContext); |
return shadowfp; |
} |
@@ -626,6 +712,12 @@ sk_sp<SkFlattenable> SkShadowShaderImpl::CreateProc(SkReadBuffer& buf) { |
sk_sp<SkLights> lights(builder.finish()); |
+ SkShadowType sType; |
+ sType.fMinVariance = buf.readScalar(); |
+ sType.fBiasingConstant = buf.readScalar(); |
+ sType.fBlurAlgorithm = (SkShadowType::BlurAlgorithm) buf.readInt(); |
+ sType.fShadowRadius = buf.readScalar(); |
+ |
int diffuseWidth = buf.readInt(); |
int diffuseHeight = buf.readInt(); |
@@ -635,7 +727,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, |
+ sType); |
} |
void SkShadowShaderImpl::flatten(SkWriteBuffer& buf) const { |
@@ -657,6 +750,11 @@ void SkShadowShaderImpl::flatten(SkWriteBuffer& buf) const { |
buf.writeImage(light.getShadowMap()); |
} |
+ buf.writeScalar(fShType.fMinVariance); |
+ buf.writeScalar(fShType.fBiasingConstant); |
+ buf.writeInt(fShType.fBlurAlgorithm); |
+ buf.writeScalar(fShType.fShadowRadius); |
+ |
buf.writeInt(fDiffuseWidth); |
buf.writeInt(fDiffuseHeight); |
@@ -702,7 +800,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, |
+ SkShadowType sType) { |
if (!povDepthShader || !diffuseShader) { |
// TODO: Use paint's color in absence of a diffuseShader |
// TODO: Use a default implementation of normalSource instead |
@@ -712,7 +811,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, |
+ sType); |
} |
/////////////////////////////////////////////////////////////////////////////// |