| Index: src/core/SkShadowShader.cpp
|
| diff --git a/src/core/SkShadowShader.cpp b/src/core/SkShadowShader.cpp
|
| index b1f49b851d775877d6c711db3089a5456abf44a6..b97f644db7cb8e2667189ddf6e4603150b3cc64e 100644
|
| --- a/src/core/SkShadowShader.cpp
|
| +++ b/src/core/SkShadowShader.cpp
|
| @@ -118,12 +118,11 @@ 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();
|
| + fLightColor[fNumNonAmbLights].scale(lights->light(i).intensity());
|
| + } else {
|
| + fLightDirOrPos[fNumNonAmbLights] = lights->light(i).dir();
|
| }
|
|
|
| fIsPointLight[fNumNonAmbLights] =
|
| @@ -174,11 +173,17 @@ public:
|
|
|
| const char* lightDirOrPosUniName[SkShadowShader::kMaxNonAmbientLights] = {nullptr};
|
| const char* lightColorUniName[SkShadowShader::kMaxNonAmbientLights] = {nullptr};
|
| - const char* lightIntensityUniName[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 +207,6 @@ public:
|
| kDefault_GrSLPrecision,
|
| lightColorUniNameStr.c_str(),
|
| &lightColorUniName[i]);
|
| - fLightIntensityUni[i] =
|
| - uniformHandler->addUniform(kFragment_GrShaderFlag,
|
| - kFloat_GrSLType,
|
| - kDefault_GrSLPrecision,
|
| - lightIntensityUniNameStr.c_str(),
|
| - &lightIntensityUniName[i]);
|
|
|
| fDepthMapWidthUni[i] = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
| kInt_GrSLType,
|
| @@ -221,9 +220,6 @@ public:
|
| &depthMapHeightUniName[i]);
|
| }
|
|
|
| - const char* shBiasUniName = nullptr;
|
| - const char* minVarianceUniName = nullptr;
|
| -
|
| fBiasingConstantUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
|
| kFloat_GrSLType,
|
| kDefault_GrSLPrecision,
|
| @@ -233,9 +229,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 +238,38 @@ 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->codeAppend ("vec3 totalLightColor = vec3(0);");
|
| +
|
| + // probability that a fragment is lit. For each light, we multiply this by the
|
| + // light's color to get its contribution to totalLightColor.
|
| + fragBuilder->codeAppend ("float lightProbability;");
|
| +
|
| + // coordinates of current fragment in world space
|
| + fragBuilder->codeAppend ("vec3 worldCor;");
|
| +
|
| // 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);",
|
| + // Note: vMatrixCoord_0_1_Stage0 is the texture sampler coordinates.
|
| + 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.
|
| @@ -264,7 +277,6 @@ public:
|
| SkString povCoord("povCoord");
|
| povCoord.appendf("%d", i);
|
|
|
| - // vMatrixCoord_0_1_Stage0 is the texture sampler coordinates.
|
| // povDepth.b * 255 scales it to 0 - 255, bringing it to world space,
|
| // and the / vec2(width, height) brings it back to a sampler coordinate
|
| SkString offset("offset");
|
| @@ -273,72 +285,63 @@ public:
|
| SkString scaleVec("scaleVec");
|
| scaleVec.appendf("%d", i);
|
|
|
| - SkString scaleOffsetVec("scaleOffsetVec");
|
| - scaleOffsetVec.appendf("%d", i);
|
| -
|
| fragBuilder->codeAppendf("vec2 %s;", offset.c_str());
|
|
|
| + // note that we flip the y-coord of the offset and then later add
|
| + // a value just to the y-coord of povCoord. This is to account for
|
| + // the shifted origins from switching from raster into GPU.
|
| if (shadowFP.fIsPointLight[i]) {
|
| fragBuilder->codeAppendf("vec3 fragToLight%d = %s - worldCor;",
|
| i, lightDirOrPosUniName[i]);
|
| 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);",
|
| + fragBuilder->codeAppendf("%s = vec2(worldCor.x - %s.x, %s.y - worldCor.y) * "
|
| + "povDepth.b;",
|
| offset.c_str(), lightDirOrPosUniName[i],
|
| - lightDirOrPosUniName[i],
|
| - widthUniName, heightUniName);
|
| + 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 * vec2(255.0, -255.0);",
|
| + 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) {",
|
| 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 mess with depth and depth^2 in their given scales.
|
| + // (i.e. between 0 and 1)
|
| + 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 +350,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 +361,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);",
|
| clamp.c_str(), shBiasUniName, shBiasUniName);
|
|
|
| fragBuilder->codeAppendf("lightProbability = %s;", clamp.c_str());
|
| @@ -371,28 +374,21 @@ 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);",
|
| + i, lightColorUniName[i], 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&,
|
| @@ -424,12 +420,6 @@ public:
|
| fLightColor[i] = lightColor;
|
| }
|
|
|
| - SkScalar lightIntensity = shadowFP.lightIntensity(i);
|
| - if (lightIntensity != fLightIntensity[i]) {
|
| - pdman.set1f(fLightIntensityUni[i], lightIntensity);
|
| - fLightIntensity[i] = lightIntensity;
|
| - }
|
| -
|
| int depthMapWidth = shadowFP.depthMapWidth(i);
|
| if (depthMapWidth != fDepthMapWidth[i]) {
|
| pdman.set1i(fDepthMapWidthUni[i], depthMapWidth);
|
| @@ -450,8 +440,9 @@ public:
|
|
|
| SkScalar minVariance = shadowFP.shadowParams().fMinVariance;
|
| if (minVariance != fMinVariance) {
|
| - pdman.set1f(fMinVarianceUni, minVariance);
|
| - fMinVariance = minVariance;
|
| + // transform variance from pixel-scale to normalized scale
|
| + pdman.set1f(fMinVarianceUni, minVariance / 65536.0f);
|
| + fMinVariance = minVariance / 65536.0f;
|
| }
|
|
|
| int width = shadowFP.width();
|
| @@ -481,10 +472,6 @@ public:
|
| GrGLSLProgramDataManager::UniformHandle
|
| fLightColorUni[SkShadowShader::kMaxNonAmbientLights];
|
|
|
| - SkScalar fLightIntensity[SkShadowShader::kMaxNonAmbientLights];
|
| - GrGLSLProgramDataManager::UniformHandle
|
| - fLightIntensityUni[SkShadowShader::kMaxNonAmbientLights];
|
| -
|
| int fDepthMapWidth[SkShadowShader::kMaxNonAmbientLights];
|
| GrGLSLProgramDataManager::UniformHandle
|
| fDepthMapWidthUni[SkShadowShader::kMaxNonAmbientLights];
|
| @@ -530,11 +517,6 @@ public:
|
| SkASSERT(i < fNumNonAmbLights);
|
| return fLightColor[i];
|
| }
|
| - SkScalar lightIntensity(int i) const {
|
| - SkASSERT(i < fNumNonAmbLights);
|
| - return fLightIntensity[i];
|
| - }
|
| -
|
| int depthMapWidth(int i) const {
|
| SkASSERT(i < fNumNonAmbLights);
|
| return fDepthMapWidth[i];
|
| @@ -565,7 +547,6 @@ private:
|
| for (int i = 0; i < fNumNonAmbLights; i++) {
|
| if (fLightDirOrPos[i] != shadowFP.fLightDirOrPos[i] ||
|
| fLightColor[i] != shadowFP.fLightColor[i] ||
|
| - fLightIntensity[i] != shadowFP.fLightIntensity[i] ||
|
| fIsPointLight[i] != shadowFP.fIsPointLight[i]) {
|
| return false;
|
| }
|
| @@ -584,7 +565,6 @@ private:
|
| bool fIsPointLight[SkShadowShader::kMaxNonAmbientLights];
|
| SkVector3 fLightDirOrPos[SkShadowShader::kMaxNonAmbientLights];
|
| SkColor3f fLightColor[SkShadowShader::kMaxNonAmbientLights];
|
| - SkScalar fLightIntensity[SkShadowShader::kMaxNonAmbientLights];
|
| GrTextureAccess fDepthMapAccess[SkShadowShader::kMaxNonAmbientLights];
|
| sk_sp<GrTexture> fTexture[SkShadowShader::kMaxNonAmbientLights];
|
|
|
|
|