Chromium Code Reviews| Index: src/core/SkShadowShader.cpp |
| diff --git a/src/core/SkShadowShader.cpp b/src/core/SkShadowShader.cpp |
| index b1f49b851d775877d6c711db3089a5456abf44a6..400be47e936f6f347b3c487e907f44ce87c20430 100644 |
| --- a/src/core/SkShadowShader.cpp |
| +++ b/src/core/SkShadowShader.cpp |
| @@ -118,12 +118,13 @@ public: |
| if (fNumNonAmbLights < SkShadowShader::kMaxNonAmbientLights) { |
| fLightColor[fNumNonAmbLights] = lights->light(i).color(); |
| - if (SkLights::Light::kDirectional_LightType == lights->light(i).type()) { |
| - fLightDirOrPos[fNumNonAmbLights] = lights->light(i).dir(); |
| - fLightIntensity[fNumNonAmbLights] = 0.0f; |
| - } else if (SkLights::Light::kPoint_LightType == lights->light(i).type()) { |
| + if (SkLights::Light::kPoint_LightType == lights->light(i).type()) { |
| fLightDirOrPos[fNumNonAmbLights] = lights->light(i).pos(); |
| - fLightIntensity[fNumNonAmbLights] = lights->light(i).intensity(); |
| + fInvSqLightIntensity[fNumNonAmbLights] = 1.0f / |
|
jvanverth1
2016/08/29 18:30:14
The standard formula for a point light is L = I *
vjiaoblack
2016/08/29 19:45:21
Okay, i'll simplify the model!
Done.
|
| + (lights->light(i).intensity() * lights->light(i).intensity()); |
| + } else { |
| + fLightDirOrPos[fNumNonAmbLights] = lights->light(i).dir(); |
| + fInvSqLightIntensity[fNumNonAmbLights] = 0.0f; |
| } |
| fIsPointLight[fNumNonAmbLights] = |
| @@ -174,11 +175,20 @@ public: |
| const char* lightDirOrPosUniName[SkShadowShader::kMaxNonAmbientLights] = {nullptr}; |
| const char* lightColorUniName[SkShadowShader::kMaxNonAmbientLights] = {nullptr}; |
| - const char* lightIntensityUniName[SkShadowShader::kMaxNonAmbientLights] = {nullptr}; |
| + const char* invLightIntensitySqUniName[SkShadowShader::kMaxNonAmbientLights] = |
| + {nullptr}; |
| + |
| + const char* ambientColorUniName = nullptr; |
| const char* depthMapWidthUniName[SkShadowShader::kMaxNonAmbientLights] = {nullptr}; |
| const char* depthMapHeightUniName[SkShadowShader::kMaxNonAmbientLights] = {nullptr}; |
| + const char* widthUniName = nullptr; // dimensions of povDepth |
| + const char* heightUniName = nullptr; |
| + const char* shBiasUniName = nullptr; |
| + const char* minVarianceUniName = nullptr; |
| + |
| + // setting uniforms |
| for (int i = 0; i < shadowFP.fNumNonAmbLights; i++) { |
| SkString lightDirOrPosUniNameStr("lightDir"); |
| lightDirOrPosUniNameStr.appendf("%d", i); |
| @@ -202,12 +212,12 @@ public: |
| kDefault_GrSLPrecision, |
| lightColorUniNameStr.c_str(), |
| &lightColorUniName[i]); |
| - fLightIntensityUni[i] = |
| + fInvSqLightIntensityUni[i] = |
| uniformHandler->addUniform(kFragment_GrShaderFlag, |
| kFloat_GrSLType, |
| kDefault_GrSLPrecision, |
| lightIntensityUniNameStr.c_str(), |
| - &lightIntensityUniName[i]); |
| + &invLightIntensitySqUniName[i]); |
| fDepthMapWidthUni[i] = uniformHandler->addUniform(kFragment_GrShaderFlag, |
| kInt_GrSLType, |
| @@ -221,9 +231,6 @@ public: |
| &depthMapHeightUniName[i]); |
| } |
| - const char* shBiasUniName = nullptr; |
| - const char* minVarianceUniName = nullptr; |
| - |
| fBiasingConstantUni = uniformHandler->addUniform(kFragment_GrShaderFlag, |
| kFloat_GrSLType, |
| kDefault_GrSLPrecision, |
| @@ -233,9 +240,6 @@ public: |
| kDefault_GrSLPrecision, |
| "minVariance", &minVarianceUniName); |
| - const char* widthUniName = nullptr; |
| - const char* heightUniName = nullptr; |
| - |
| fWidthUni = uniformHandler->addUniform(kFragment_GrShaderFlag, |
| kInt_GrSLType, |
| kDefault_GrSLPrecision, |
| @@ -245,18 +249,37 @@ public: |
| kDefault_GrSLPrecision, |
| "height", &heightUniName); |
| + fAmbientColorUni = uniformHandler->addUniform(kFragment_GrShaderFlag, |
| + kVec3f_GrSLType, kDefault_GrSLPrecision, |
| + "AmbientColor", &ambientColorUniName); |
| + |
| + SkString povDepthSampler("_povDepth"); |
| SkString povDepth("povDepth"); |
| - this->emitChild(0, nullptr, &povDepth, args); |
| + this->emitChild(0, nullptr, &povDepthSampler, args); |
| + fragBuilder->codeAppendf("vec4 %s = %s;", povDepth.c_str(), povDepthSampler.c_str()); |
| + SkString diffuseColorSampler("_inDiffuseColor"); |
| SkString diffuseColor("inDiffuseColor"); |
| - this->emitChild(1, nullptr, &diffuseColor, args); |
| + this->emitChild(1, nullptr, &diffuseColorSampler, args); |
| + fragBuilder->codeAppendf("vec4 %s = %s;", diffuseColor.c_str(), |
| + diffuseColorSampler.c_str()); |
| SkString depthMaps[SkShadowShader::kMaxNonAmbientLights]; |
| + fragBuilder->codeAppendf("vec4 resultDiffuseColor = %s;", diffuseColor.c_str()); |
| + fragBuilder->codeAppendf("vec3 totalLightColor = vec3(0,0,0);"); |
|
jvanverth1
2016/08/29 18:30:14
You can just do vec3(0);
Don't need appendf.
vjiaoblack
2016/08/29 19:45:21
Done.
|
| + |
| + // probability that a fragment is lit. For each light, we multiply this by the |
| + // light's color to get its contribution to totalLightColor. |
| + fragBuilder->codeAppendf("float lightProbability;"); |
| + |
| + // coordinates of current fragment in world space |
| + fragBuilder->codeAppendf("vec3 worldCor;"); |
|
jvanverth1
2016/08/29 18:30:14
Don't need appendf here, can use append. Same for
vjiaoblack
2016/08/29 19:45:22
Done.
|
| + |
| // Multiply by 255 to transform from sampler coordinates to world |
| // coordinates (since 1 channel is 0xFF) |
| - fragBuilder->codeAppendf("vec3 worldCor = vec3(vMatrixCoord_0_1_Stage0 * " |
| - "vec2(%s, %s), %s.b * 255);", |
| + fragBuilder->codeAppendf("worldCor = vec3(vMatrixCoord_0_1_Stage0 * " |
| + "vec2(%s, %s), %s.b * 255);", |
| widthUniName, heightUniName, povDepth.c_str()); |
| // Applies the offset indexing that goes from our view space into the light's space. |
| @@ -273,9 +296,6 @@ public: |
| SkString scaleVec("scaleVec"); |
| scaleVec.appendf("%d", i); |
| - SkString scaleOffsetVec("scaleOffsetVec"); |
| - scaleOffsetVec.appendf("%d", i); |
| - |
| fragBuilder->codeAppendf("vec2 %s;", offset.c_str()); |
| if (shadowFP.fIsPointLight[i]) { |
| @@ -284,61 +304,50 @@ public: |
| fragBuilder->codeAppendf("float distsq%d = dot(fragToLight%d, fragToLight%d);" |
| "fragToLight%d = normalize(fragToLight%d);", |
| i, i, i, i, i); |
| - fragBuilder->codeAppendf("%s = -vec2(%s.x - worldCor.x, worldCor.y - %s.y)*" |
| - "(povDepth.b) / vec2(%s, %s);", |
| - offset.c_str(), lightDirOrPosUniName[i], |
| - lightDirOrPosUniName[i], |
| - widthUniName, heightUniName); |
| + fragBuilder->codeAppendf("%s = vec2(worldCor - %s) * povDepth.b;", |
| + offset.c_str(), lightDirOrPosUniName[i]); |
| } else { |
| - fragBuilder->codeAppendf("%s = vec2(%s) * povDepth.b * 255 / vec2(%s, %s);", |
| - offset.c_str(), lightDirOrPosUniName[i], |
| - widthUniName, heightUniName); |
| + fragBuilder->codeAppendf("%s = vec2(%s) * povDepth.b * 255 * " |
| + "vec2(1.0, -1.0);", |
|
jvanverth1
2016/08/29 18:30:14
Replace 255*vec2(1, -1) with vec2(255, -255)? And
vjiaoblack
2016/08/29 19:45:22
Done.
|
| + offset.c_str(), lightDirOrPosUniName[i]); |
| } |
| - fragBuilder->codeAppendf("vec2 %s = (vec2(%s, %s) / vec2(%s, %s));", |
| - scaleVec.c_str(), |
| + fragBuilder->codeAppendf("vec2 %s = (vec2(%s, %s) *" |
| + "vMatrixCoord_0_1_Stage0 +" |
| + "vec2(0,%s - %s) + " |
| + "%s) / vec2(%s, %s);", |
| + povCoord.c_str(), |
| widthUniName, heightUniName, |
| + depthMapHeightUniName[i], heightUniName, |
| + offset.c_str(), |
| depthMapWidthUniName[i], depthMapHeightUniName[i]); |
| - 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;", |
| - 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; |
| - fAmbientColorUni = uniformHandler->addUniform(kFragment_GrShaderFlag, |
| - kVec3f_GrSLType, kDefault_GrSLPrecision, |
| - "AmbientColor", &ambientColorUniName); |
| - |
| - fragBuilder->codeAppendf("vec4 resultDiffuseColor = %s;", diffuseColor.c_str()); |
| - |
| - SkString totalLightColor("totalLightColor"); |
| - fragBuilder->codeAppendf("vec3 %s = vec3(0,0,0);", totalLightColor.c_str()); |
| + // helper variables for calculating shadowing |
| - fragBuilder->codeAppendf("float lightProbability;"); |
| + // variance of depth at this fragment in the context of surrounding area |
| + // (area size and weighting dependent on blur size and type) |
| fragBuilder->codeAppendf("float variance;"); |
| + |
| + // the difference in depth between the user POV and light POV. |
| fragBuilder->codeAppendf("float d;"); |
| + // add up light contributions from all lights to totalLightColor |
| for (int i = 0; i < numLights; i++) { |
| if (!shadowFP.isPointLight(i)) { |
| fragBuilder->codeAppendf("lightProbability = 1;"); |
| - // 1/512 is less than half a pixel; imperceptible |
| - fragBuilder->codeAppendf("if (%s.b <= %s.b + 1/512) {", |
| + // 1/512 == .00195... is less than half a pixel; imperceptible |
| + fragBuilder->codeAppendf("if (%s.b <= %s.b + .001953125) {", |
|
jvanverth1
2016/08/29 18:30:14
Good catch.
vjiaoblack
2016/08/29 19:45:22
Done.
|
| povDepth.c_str(), depthMaps[i].c_str()); |
| if (blurAlgorithm == SkShadowParams::kVariance_ShadowType) { |
| - fragBuilder->codeAppendf("vec2 moments%d = vec2(%s.b * 255," |
| - "%s.g * 255 * 256 );", |
| + // we stored depth^2 in the SPFCanvas after dividing it by 256, |
| + // so here we multiply it by 256. |
|
jvanverth1
2016/08/29 18:30:14
Where are we multiplying by 256?
vjiaoblack
2016/08/29 19:45:21
Acknowledged.
|
| + fragBuilder->codeAppendf("vec2 moments%d = vec2(%s.b, %s.g);", |
| i, depthMaps[i].c_str(), depthMaps[i].c_str()); |
| // variance biasing lessens light bleeding |
| @@ -347,7 +356,7 @@ public: |
| "%s);", i, i, i, |
| minVarianceUniName); |
| - fragBuilder->codeAppendf("d = (%s.b * 255) - moments%d.x;", |
| + fragBuilder->codeAppendf("d = (%s.b) - moments%d.x;", |
| povDepth.c_str(), i); |
| fragBuilder->codeAppendf("lightProbability = " |
| "(variance / (variance + d * d));"); |
| @@ -358,7 +367,7 @@ public: |
| // choosing between light artifacts or correct shape shadows |
| // linstep |
| fragBuilder->codeAppendf("float %s = clamp((lightProbability - %s) /" |
| - "(1 - %s), 0, 1);", |
| + "(1 - %s), 0, 1);", |
|
jvanverth1
2016/08/29 18:30:14
Nit: Indent to parenthesis.
vjiaoblack
2016/08/29 19:45:22
Done.
|
| clamp.c_str(), shBiasUniName, shBiasUniName); |
| fragBuilder->codeAppendf("lightProbability = %s;", clamp.c_str()); |
| @@ -371,28 +380,22 @@ public: |
| // VSM: The curved shadows near plane edges are artifacts from blurring |
| fragBuilder->codeAppendf("}"); |
| - fragBuilder->codeAppendf("%s += dot(vec3(0,0,1), %s) * %s * " |
| - "lightProbability;", |
| - totalLightColor.c_str(), |
| + fragBuilder->codeAppendf("totalLightColor += %s.z * %s * " |
| + "lightProbability;", |
| lightDirOrPosUniName[i], |
| lightColorUniName[i]); |
| } else { |
| // fragToLight%d.z is equal to the fragToLight dot the surface normal. |
| - fragBuilder->codeAppendf("%s += max(fragToLight%d.z, 0) * %s /" |
| - "(1 + distsq%d / (%s * %s));", |
| - totalLightColor.c_str(), i, |
| - lightColorUniName[i], i, |
| - lightIntensityUniName[i], |
| - lightIntensityUniName[i]); |
| + fragBuilder->codeAppendf("totalLightColor += max(fragToLight%d.z, 0) * %s /" |
| + "(1 + distsq%d * %s);", |
| + i, lightColorUniName[i], i, |
| + invLightIntensitySqUniName[i]); |
| } |
| } |
| - fragBuilder->codeAppendf("%s += %s;", totalLightColor.c_str(), ambientColorUniName); |
| - |
| - fragBuilder->codeAppendf("resultDiffuseColor *= vec4(%s, 1);", |
| - totalLightColor.c_str()); |
| - |
| - fragBuilder->codeAppendf("%s = resultDiffuseColor;", args.fOutputColor); |
| + fragBuilder->codeAppendf("totalLightColor += %s;", ambientColorUniName); |
| + fragBuilder->codeAppendf("%s = resultDiffuseColor * vec4(totalLightColor, 1);", |
| + args.fOutputColor); |
| } |
| static void GenKey(const GrProcessor& proc, const GrGLSLCaps&, |
| @@ -425,9 +428,9 @@ public: |
| } |
| SkScalar lightIntensity = shadowFP.lightIntensity(i); |
| - if (lightIntensity != fLightIntensity[i]) { |
| - pdman.set1f(fLightIntensityUni[i], lightIntensity); |
| - fLightIntensity[i] = lightIntensity; |
| + if (lightIntensity != fInvSqLightIntensity[i]) { |
| + pdman.set1f(fInvSqLightIntensityUni[i], lightIntensity); |
| + fInvSqLightIntensity[i] = lightIntensity; |
| } |
| int depthMapWidth = shadowFP.depthMapWidth(i); |
| @@ -481,9 +484,9 @@ public: |
| GrGLSLProgramDataManager::UniformHandle |
| fLightColorUni[SkShadowShader::kMaxNonAmbientLights]; |
| - SkScalar fLightIntensity[SkShadowShader::kMaxNonAmbientLights]; |
| + SkScalar fInvSqLightIntensity[SkShadowShader::kMaxNonAmbientLights]; |
| GrGLSLProgramDataManager::UniformHandle |
| - fLightIntensityUni[SkShadowShader::kMaxNonAmbientLights]; |
| + fInvSqLightIntensityUni[SkShadowShader::kMaxNonAmbientLights]; |
| int fDepthMapWidth[SkShadowShader::kMaxNonAmbientLights]; |
| GrGLSLProgramDataManager::UniformHandle |
| @@ -532,7 +535,7 @@ public: |
| } |
| SkScalar lightIntensity(int i) const { |
| SkASSERT(i < fNumNonAmbLights); |
| - return fLightIntensity[i]; |
| + return fInvSqLightIntensity[i]; |
| } |
| int depthMapWidth(int i) const { |
| @@ -565,7 +568,7 @@ private: |
| for (int i = 0; i < fNumNonAmbLights; i++) { |
| if (fLightDirOrPos[i] != shadowFP.fLightDirOrPos[i] || |
| fLightColor[i] != shadowFP.fLightColor[i] || |
| - fLightIntensity[i] != shadowFP.fLightIntensity[i] || |
| + fInvSqLightIntensity[i] != shadowFP.fInvSqLightIntensity[i] || |
| fIsPointLight[i] != shadowFP.fIsPointLight[i]) { |
| return false; |
| } |
| @@ -584,7 +587,7 @@ private: |
| bool fIsPointLight[SkShadowShader::kMaxNonAmbientLights]; |
| SkVector3 fLightDirOrPos[SkShadowShader::kMaxNonAmbientLights]; |
| SkColor3f fLightColor[SkShadowShader::kMaxNonAmbientLights]; |
| - SkScalar fLightIntensity[SkShadowShader::kMaxNonAmbientLights]; |
| + SkScalar fInvSqLightIntensity[SkShadowShader::kMaxNonAmbientLights]; |
| GrTextureAccess fDepthMapAccess[SkShadowShader::kMaxNonAmbientLights]; |
| sk_sp<GrTexture> fTexture[SkShadowShader::kMaxNonAmbientLights]; |