1/* 2 * Copyright 2016 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "SkCanvas.h" 9#include "SkReadBuffer.h" 10#include "SkShadowShader.h" 11 12//////////////////////////////////////////////////////////////////////////// 13#ifdef SK_EXPERIMENTAL_SHADOWING 14 15 16/** \class SkShadowShaderImpl 17 This subclass of shader applies shadowing 18*/ 19class SkShadowShaderImpl : public SkShader { 20public: 21 /** Create a new shadowing shader that shadows 22 @param to do to do 23 */ 24 SkShadowShaderImpl(sk_sp<SkShader> povDepthShader, 25 sk_sp<SkShader> diffuseShader, 26 sk_sp<SkLights> lights, 27 int diffuseWidth, int diffuseHeight, 28 const SkShadowParams& params) 29 : fPovDepthShader(std::move(povDepthShader)) 30 , fDiffuseShader(std::move(diffuseShader)) 31 , fLights(std::move(lights)) 32 , fDiffuseWidth(diffuseWidth) 33 , fDiffuseHeight(diffuseHeight) 34 , fShadowParams(params) { } 35 36 bool isOpaque() const override; 37 38#if SK_SUPPORT_GPU 39 sk_sp<GrFragmentProcessor> asFragmentProcessor(const AsFPArgs&) const override; 40#endif 41 42 class ShadowShaderContext : public SkShader::Context { 43 public: 44 // The context takes ownership of the states. It will call their destructors 45 // but will NOT free the memory. 46 ShadowShaderContext(const SkShadowShaderImpl&, const ContextRec&, 47 SkShader::Context* povDepthContext, 48 SkShader::Context* diffuseContext, 49 void* heapAllocated); 50 51 ~ShadowShaderContext() override; 52 53 void shadeSpan(int x, int y, SkPMColor[], int count) override; 54 55 uint32_t getFlags() const override { return fFlags; } 56 57 private: 58 SkShader::Context* fPovDepthContext; 59 SkShader::Context* fDiffuseContext; 60 uint32_t fFlags; 61 62 void* fHeapAllocated; 63 64 int fNonAmbLightCnt; 65 SkPixmap* fShadowMapPixels; 66 67 68 typedef SkShader::Context INHERITED; 69 }; 70 71 SK_TO_STRING_OVERRIDE() 72 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkShadowShaderImpl) 73 74protected: 75 void flatten(SkWriteBuffer&) const override; 76 size_t onContextSize(const ContextRec&) const override; 77 Context* onCreateContext(const ContextRec&, void*) const override; 78 79private: 80 sk_sp<SkShader> fPovDepthShader; 81 sk_sp<SkShader> fDiffuseShader; 82 sk_sp<SkLights> fLights; 83 84 int fDiffuseWidth; 85 int fDiffuseHeight; 86 87 SkShadowParams fShadowParams; 88 89 friend class SkShadowShader; 90 91 typedef SkShader INHERITED; 92}; 93 94//////////////////////////////////////////////////////////////////////////// 95 96#if SK_SUPPORT_GPU 97 98#include "GrCoordTransform.h" 99#include "GrFragmentProcessor.h" 100#include "GrInvariantOutput.h" 101#include "glsl/GrGLSLFragmentProcessor.h" 102#include "glsl/GrGLSLFragmentShaderBuilder.h" 103#include "SkGr.h" 104#include "SkSpecialImage.h" 105#include "SkImage_Base.h" 106#include "GrContext.h" 107 108class ShadowFP : public GrFragmentProcessor { 109public: 110 ShadowFP(sk_sp<GrFragmentProcessor> povDepth, 111 sk_sp<GrFragmentProcessor> diffuse, 112 sk_sp<SkLights> lights, 113 int diffuseWidth, int diffuseHeight, 114 const SkShadowParams& params, 115 GrContext* context) { 116 117 fAmbientColor = lights->ambientLightColor(); 118 119 fNumNonAmbLights = 0; // count of non-ambient lights 120 for (int i = 0; i < lights->numLights(); ++i) { 121 if (fNumNonAmbLights < SkShadowShader::kMaxNonAmbientLights) { 122 fLightColor[fNumNonAmbLights] = lights->light(i).color(); 123 124 if (SkLights::Light::kPoint_LightType == lights->light(i).type()) { 125 fLightDirOrPos[fNumNonAmbLights] = lights->light(i).pos(); 126 fLightColor[fNumNonAmbLights].scale(lights->light(i).intensity()); 127 } else { 128 fLightDirOrPos[fNumNonAmbLights] = lights->light(i).dir(); 129 } 130 131 fIsPointLight[fNumNonAmbLights] = 132 SkLights::Light::kPoint_LightType == lights->light(i).type(); 133 134 fIsRadialLight[fNumNonAmbLights] = lights->light(i).isRadial(); 135 136 SkImage_Base* shadowMap = ((SkImage_Base*)lights->light(i).getShadowMap()); 137 138 // gets deleted when the ShadowFP is destroyed, and frees the GrTexture* 139 fTexture[fNumNonAmbLights] = sk_sp<GrTexture>(shadowMap->asTextureRef(context, 140 GrSamplerParams::ClampNoFilter(), 141 SkDestinationSurfaceColorMode::kLegacy, 142 nullptr)); 143 fDepthMapSampler[fNumNonAmbLights].reset(fTexture[fNumNonAmbLights].get()); 144 this->addTextureSampler(&fDepthMapSampler[fNumNonAmbLights]); 145 146 fDepthMapHeight[fNumNonAmbLights] = shadowMap->height(); 147 fDepthMapWidth[fNumNonAmbLights] = shadowMap->width(); 148 149 fNumNonAmbLights++; 150 } 151 } 152 153 fWidth = diffuseWidth; 154 fHeight = diffuseHeight; 155 156 fShadowParams = params; 157 158 this->registerChildProcessor(std::move(povDepth)); 159 this->registerChildProcessor(std::move(diffuse)); 160 this->initClassID<ShadowFP>(); 161 } 162 163 class GLSLShadowFP : public GrGLSLFragmentProcessor { 164 public: 165 GLSLShadowFP() { } 166 167 void emitCode(EmitArgs& args) override { 168 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; 169 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 170 const ShadowFP& shadowFP = args.fFp.cast<ShadowFP>(); 171 172 SkASSERT(shadowFP.fNumNonAmbLights <= SkShadowShader::kMaxNonAmbientLights); 173 174 // add uniforms 175 int32_t numLights = shadowFP.fNumNonAmbLights; 176 SkASSERT(numLights <= SkShadowShader::kMaxNonAmbientLights); 177 178 int blurAlgorithm = shadowFP.fShadowParams.fType; 179 180 const char* lightDirOrPosUniName[SkShadowShader::kMaxNonAmbientLights] = {nullptr}; 181 const char* lightColorUniName[SkShadowShader::kMaxNonAmbientLights] = {nullptr}; 182 const char* ambientColorUniName = nullptr; 183 184 const char* depthMapWidthUniName[SkShadowShader::kMaxNonAmbientLights] = {nullptr}; 185 const char* depthMapHeightUniName[SkShadowShader::kMaxNonAmbientLights] = {nullptr}; 186 const char* widthUniName = nullptr; // dimensions of povDepth 187 const char* heightUniName = nullptr; 188 189 const char* shBiasUniName = nullptr; 190 const char* minVarianceUniName = nullptr; 191 192 // setting uniforms 193 for (int i = 0; i < shadowFP.fNumNonAmbLights; i++) { 194 SkString lightDirOrPosUniNameStr("lightDir"); 195 lightDirOrPosUniNameStr.appendf("%d", i); 196 SkString lightColorUniNameStr("lightColor"); 197 lightColorUniNameStr.appendf("%d", i); 198 SkString lightIntensityUniNameStr("lightIntensity"); 199 lightIntensityUniNameStr.appendf("%d", i); 200 201 SkString depthMapWidthUniNameStr("dmapWidth"); 202 depthMapWidthUniNameStr.appendf("%d", i); 203 SkString depthMapHeightUniNameStr("dmapHeight"); 204 depthMapHeightUniNameStr.appendf("%d", i); 205 206 fLightDirOrPosUni[i] = uniformHandler->addUniform(kFragment_GrShaderFlag, 207 kVec3f_GrSLType, 208 kDefault_GrSLPrecision, 209 lightDirOrPosUniNameStr.c_str(), 210 &lightDirOrPosUniName[i]); 211 fLightColorUni[i] = uniformHandler->addUniform(kFragment_GrShaderFlag, 212 kVec3f_GrSLType, 213 kDefault_GrSLPrecision, 214 lightColorUniNameStr.c_str(), 215 &lightColorUniName[i]); 216 217 fDepthMapWidthUni[i] = uniformHandler->addUniform(kFragment_GrShaderFlag, 218 kInt_GrSLType, 219 kDefault_GrSLPrecision, 220 depthMapWidthUniNameStr.c_str(), 221 &depthMapWidthUniName[i]); 222 fDepthMapHeightUni[i] = uniformHandler->addUniform(kFragment_GrShaderFlag, 223 kInt_GrSLType, 224 kDefault_GrSLPrecision, 225 depthMapHeightUniNameStr.c_str(), 226 &depthMapHeightUniName[i]); 227 } 228 229 fBiasingConstantUni = uniformHandler->addUniform(kFragment_GrShaderFlag, 230 kFloat_GrSLType, 231 kDefault_GrSLPrecision, 232 "shadowBias", &shBiasUniName); 233 fMinVarianceUni = uniformHandler->addUniform(kFragment_GrShaderFlag, 234 kFloat_GrSLType, 235 kDefault_GrSLPrecision, 236 "minVariance", &minVarianceUniName); 237 238 fWidthUni = uniformHandler->addUniform(kFragment_GrShaderFlag, 239 kInt_GrSLType, 240 kDefault_GrSLPrecision, 241 "width", &widthUniName); 242 fHeightUni = uniformHandler->addUniform(kFragment_GrShaderFlag, 243 kInt_GrSLType, 244 kDefault_GrSLPrecision, 245 "height", &heightUniName); 246 247 fAmbientColorUni = uniformHandler->addUniform(kFragment_GrShaderFlag, 248 kVec3f_GrSLType, kDefault_GrSLPrecision, 249 "AmbientColor", &ambientColorUniName); 250 251 SkString povDepthSampler("_povDepth"); 252 SkString povDepth("povDepth"); 253 this->emitChild(0, nullptr, &povDepthSampler, args); 254 fragBuilder->codeAppendf("vec4 %s = %s;", povDepth.c_str(), povDepthSampler.c_str()); 255 256 SkString diffuseColorSampler("_inDiffuseColor"); 257 SkString diffuseColor("inDiffuseColor"); 258 this->emitChild(1, nullptr, &diffuseColorSampler, args); 259 fragBuilder->codeAppendf("vec4 %s = %s;", diffuseColor.c_str(), 260 diffuseColorSampler.c_str()); 261 262 SkString depthMaps[SkShadowShader::kMaxNonAmbientLights]; 263 264 fragBuilder->codeAppendf("vec4 resultDiffuseColor = %s;", diffuseColor.c_str()); 265 fragBuilder->codeAppend ("vec3 totalLightColor = vec3(0);"); 266 267 // probability that a fragment is lit. For each light, we multiply this by the 268 // light's color to get its contribution to totalLightColor. 269 fragBuilder->codeAppend ("float lightProbability;"); 270 271 // coordinates of current fragment in world space 272 fragBuilder->codeAppend ("vec3 worldCor;"); 273 274 // Multiply by 255 to transform from sampler coordinates to world 275 // coordinates (since 1 channel is 0xFF) 276 // Note: vMatrixCoord_0_1_Stage0 is the texture sampler coordinates. 277 fragBuilder->codeAppendf("worldCor = vec3(vMatrixCoord_0_1_Stage0 * " 278 "vec2(%s, %s), %s.b * 255);", 279 widthUniName, heightUniName, povDepth.c_str()); 280 281 // Applies the offset indexing that goes from our view space into the light's space. 282 for (int i = 0; i < shadowFP.fNumNonAmbLights; i++) { 283 SkString povCoord("povCoord"); 284 povCoord.appendf("%d", i); 285 286 SkString offset("offset"); 287 offset.appendf("%d", i); 288 fragBuilder->codeAppendf("vec2 %s;", offset.c_str()); 289 290 if (shadowFP.fIsPointLight[i]) { 291 fragBuilder->codeAppendf("vec3 fragToLight%d = %s - worldCor;", 292 i, lightDirOrPosUniName[i]); 293 fragBuilder->codeAppendf("float dist%d = length(fragToLight%d);", 294 i, i); 295 fragBuilder->codeAppendf("%s = vec2(-fragToLight%d) * povDepth.b;", 296 offset.c_str(), i); 297 fragBuilder->codeAppendf("fragToLight%d = normalize(fragToLight%d);", 298 i, i); 299 } 300 301 if (shadowFP.fIsRadialLight[i]) { 302 fragBuilder->codeAppendf("vec2 %s = vec2(vMatrixCoord_0_1_Stage0.x, " 303 "1 - vMatrixCoord_0_1_Stage0.y);\n", 304 povCoord.c_str()); 305 306 fragBuilder->codeAppendf("%s = (%s) * 2.0 - 1.0 + (vec2(%s)/vec2(%s,%s) - 0.5)" 307 "* vec2(-2.0, 2.0);\n", 308 povCoord.c_str(), povCoord.c_str(), 309 lightDirOrPosUniName[i], 310 widthUniName, heightUniName); 311 312 fragBuilder->codeAppendf("float theta = atan(%s.y, %s.x);", 313 povCoord.c_str(), povCoord.c_str()); 314 fragBuilder->codeAppendf("float r = length(%s);", povCoord.c_str()); 315 316 // map output of atan to [0, 1] 317 fragBuilder->codeAppendf("%s.x = (theta + 3.1415) / (2.0 * 3.1415);", 318 povCoord.c_str()); 319 fragBuilder->codeAppendf("%s.y = 0.0;", povCoord.c_str()); 320 } else { 321 // note that we flip the y-coord of the offset and then later add 322 // a value just to the y-coord of povCoord. This is to account for 323 // the shifted origins from switching from raster into GPU. 324 if (shadowFP.fIsPointLight[i]) { 325 // the 0.375s are precalculated transform values, given that the depth 326 // maps for pt lights are 4x the size (linearly) as diffuse maps. 327 // The vec2(0.375, -0.375) is used to transform us to 328 // the center of the map. 329 fragBuilder->codeAppendf("vec2 %s = ((vec2(%s, %s) *" 330 "vMatrixCoord_0_1_Stage0 +" 331 "vec2(0,%s - %s)" 332 "+ %s) / (vec2(%s, %s))) +" 333 "vec2(0.375, -0.375);", 334 povCoord.c_str(), 335 widthUniName, heightUniName, 336 depthMapHeightUniName[i], heightUniName, 337 offset.c_str(), 338 depthMapWidthUniName[i], 339 depthMapWidthUniName[i]); 340 } else { 341 fragBuilder->codeAppendf("%s = vec2(%s) * povDepth.b * " 342 "vec2(255.0, -255.0);", 343 offset.c_str(), lightDirOrPosUniName[i]); 344 345 fragBuilder->codeAppendf("vec2 %s = ((vec2(%s, %s) *" 346 "vMatrixCoord_0_1_Stage0 +" 347 "vec2(0,%s - %s)" 348 "+ %s) / vec2(%s, %s));", 349 povCoord.c_str(), 350 widthUniName, heightUniName, 351 depthMapHeightUniName[i], heightUniName, 352 offset.c_str(), 353 depthMapWidthUniName[i], 354 depthMapWidthUniName[i]); 355 } 356 } 357 358 fragBuilder->appendTextureLookup(&depthMaps[i], args.fTexSamplers[i], 359 povCoord.c_str(), 360 kVec2f_GrSLType); 361 } 362 363 // helper variables for calculating shadowing 364 365 // variance of depth at this fragment in the context of surrounding area 366 // (area size and weighting dependent on blur size and type) 367 fragBuilder->codeAppendf("float variance;"); 368 369 // the difference in depth between the user POV and light POV. 370 fragBuilder->codeAppendf("float d;"); 371 372 // add up light contributions from all lights to totalLightColor 373 for (int i = 0; i < numLights; i++) { 374 fragBuilder->codeAppendf("lightProbability = 1;"); 375 376 if (shadowFP.fIsRadialLight[i]) { 377 fragBuilder->codeAppend("totalLightColor = vec3(0);"); 378 379 fragBuilder->codeAppend("vec2 tc = vec2(povCoord0.x, 0.0);"); 380 fragBuilder->codeAppend("float depth = texture(uTextureSampler0_Stage1," 381 "povCoord0).b * 2.0;"); 382 383 fragBuilder->codeAppendf("lightProbability = step(r, depth);"); 384 385 // 2 is the maximum depth. If this is reached, probably we have 386 // not intersected anything. So values after this should be unshadowed. 387 fragBuilder->codeAppendf("if (%s.b != 0 || depth == 2) {" 388 "lightProbability = 1.0; }", 389 povDepth.c_str()); 390 } else { 391 // 1/512 == .00195... is less than half a pixel; imperceptible 392 fragBuilder->codeAppendf("if (%s.b <= %s.b + .001953125) {", 393 povDepth.c_str(), depthMaps[i].c_str()); 394 if (blurAlgorithm == SkShadowParams::kVariance_ShadowType) { 395 // We mess with depth and depth^2 in their given scales. 396 // (i.e. between 0 and 1) 397 fragBuilder->codeAppendf("vec2 moments%d = vec2(%s.b, %s.g);", 398 i, depthMaps[i].c_str(), depthMaps[i].c_str()); 399 400 // variance biasing lessens light bleeding 401 fragBuilder->codeAppendf("variance = max(moments%d.y - " 402 "(moments%d.x * moments%d.x)," 403 "%s);", i, i, i, 404 minVarianceUniName); 405 406 fragBuilder->codeAppendf("d = (%s.b) - moments%d.x;", 407 povDepth.c_str(), i); 408 fragBuilder->codeAppendf("lightProbability = " 409 "(variance / (variance + d * d));"); 410 411 SkString clamp("clamp"); 412 clamp.appendf("%d", i); 413 414 // choosing between light artifacts or correct shape shadows 415 // linstep 416 fragBuilder->codeAppendf("float %s = clamp((lightProbability - %s) /" 417 "(1 - %s), 0, 1);", 418 clamp.c_str(), shBiasUniName, shBiasUniName); 419 420 fragBuilder->codeAppendf("lightProbability = %s;", clamp.c_str()); 421 } else { 422 fragBuilder->codeAppendf("if (%s.b >= %s.b) {", 423 povDepth.c_str(), depthMaps[i].c_str()); 424 fragBuilder->codeAppendf("lightProbability = 1;"); 425 fragBuilder->codeAppendf("} else { lightProbability = 0; }"); 426 } 427 428 // VSM: The curved shadows near plane edges are artifacts from blurring 429 // lightDir.z is equal to the lightDir dot the surface normal. 430 fragBuilder->codeAppendf("}"); 431 } 432 433 if (shadowFP.isPointLight(i)) { 434 fragBuilder->codeAppendf("totalLightColor += max(fragToLight%d.z, 0) * %s /" 435 "(1 + dist%d) * lightProbability;", 436 i, lightColorUniName[i], i); 437 } else { 438 fragBuilder->codeAppendf("totalLightColor += %s.z * %s * lightProbability;", 439 lightDirOrPosUniName[i], 440 lightColorUniName[i]); 441 } 442 443 fragBuilder->codeAppendf("totalLightColor += %s;", ambientColorUniName); 444 fragBuilder->codeAppendf("%s = resultDiffuseColor * vec4(totalLightColor, 1);", 445 args.fOutputColor); 446 } 447 448 } 449 450 static void GenKey(const GrProcessor& proc, const GrShaderCaps&, 451 GrProcessorKeyBuilder* b) { 452 const ShadowFP& shadowFP = proc.cast<ShadowFP>(); 453 b->add32(shadowFP.fNumNonAmbLights); 454 int isPLR = 0; 455 for (int i = 0; i < SkShadowShader::kMaxNonAmbientLights; i++) { 456 isPLR = isPLR | ((shadowFP.fIsPointLight[i] ? 1 : 0) << i); 457 isPLR = isPLR | ((shadowFP.fIsRadialLight[i] ? 1 : 0) << (i+4)); 458 } 459 b->add32(isPLR); 460 b->add32(shadowFP.fShadowParams.fType); 461 } 462 463 protected: 464 void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& proc) override { 465 const ShadowFP &shadowFP = proc.cast<ShadowFP>(); 466 467 for (int i = 0; i < shadowFP.numLights(); i++) { 468 const SkVector3& lightDirOrPos = shadowFP.lightDirOrPos(i); 469 if (lightDirOrPos != fLightDirOrPos[i]) { 470 pdman.set3fv(fLightDirOrPosUni[i], 1, &lightDirOrPos.fX); 471 fLightDirOrPos[i] = lightDirOrPos; 472 } 473 474 const SkColor3f& lightColor = shadowFP.lightColor(i); 475 if (lightColor != fLightColor[i]) { 476 pdman.set3fv(fLightColorUni[i], 1, &lightColor.fX); 477 fLightColor[i] = lightColor; 478 } 479 480 int depthMapWidth = shadowFP.depthMapWidth(i); 481 if (depthMapWidth != fDepthMapWidth[i]) { 482 pdman.set1i(fDepthMapWidthUni[i], depthMapWidth); 483 fDepthMapWidth[i] = depthMapWidth; 484 } 485 int depthMapHeight = shadowFP.depthMapHeight(i); 486 if (depthMapHeight != fDepthMapHeight[i]) { 487 pdman.set1i(fDepthMapHeightUni[i], depthMapHeight); 488 fDepthMapHeight[i] = depthMapHeight; 489 } 490 } 491 492 SkScalar biasingConstant = shadowFP.shadowParams().fBiasingConstant; 493 if (biasingConstant != fBiasingConstant) { 494 pdman.set1f(fBiasingConstantUni, biasingConstant); 495 fBiasingConstant = biasingConstant; 496 } 497 498 SkScalar minVariance = shadowFP.shadowParams().fMinVariance; 499 if (minVariance != fMinVariance) { 500 // transform variance from pixel-scale to normalized scale 501 pdman.set1f(fMinVarianceUni, minVariance / 65536.0f); 502 fMinVariance = minVariance / 65536.0f; 503 } 504 505 int width = shadowFP.width(); 506 if (width != fWidth) { 507 pdman.set1i(fWidthUni, width); 508 fWidth = width; 509 } 510 int height = shadowFP.height(); 511 if (height != fHeight) { 512 pdman.set1i(fHeightUni, height); 513 fHeight = height; 514 } 515 516 const SkColor3f& ambientColor = shadowFP.ambientColor(); 517 if (ambientColor != fAmbientColor) { 518 pdman.set3fv(fAmbientColorUni, 1, &ambientColor.fX); 519 fAmbientColor = ambientColor; 520 } 521 } 522 523 private: 524 SkVector3 fLightDirOrPos[SkShadowShader::kMaxNonAmbientLights]; 525 GrGLSLProgramDataManager::UniformHandle 526 fLightDirOrPosUni[SkShadowShader::kMaxNonAmbientLights]; 527 528 SkColor3f fLightColor[SkShadowShader::kMaxNonAmbientLights]; 529 GrGLSLProgramDataManager::UniformHandle 530 fLightColorUni[SkShadowShader::kMaxNonAmbientLights]; 531 532 int fDepthMapWidth[SkShadowShader::kMaxNonAmbientLights]; 533 GrGLSLProgramDataManager::UniformHandle 534 fDepthMapWidthUni[SkShadowShader::kMaxNonAmbientLights]; 535 536 int fDepthMapHeight[SkShadowShader::kMaxNonAmbientLights]; 537 GrGLSLProgramDataManager::UniformHandle 538 fDepthMapHeightUni[SkShadowShader::kMaxNonAmbientLights]; 539 540 int fWidth; 541 GrGLSLProgramDataManager::UniformHandle fWidthUni; 542 int fHeight; 543 GrGLSLProgramDataManager::UniformHandle fHeightUni; 544 545 SkScalar fBiasingConstant; 546 GrGLSLProgramDataManager::UniformHandle fBiasingConstantUni; 547 SkScalar fMinVariance; 548 GrGLSLProgramDataManager::UniformHandle fMinVarianceUni; 549 550 SkColor3f fAmbientColor; 551 GrGLSLProgramDataManager::UniformHandle fAmbientColorUni; 552 }; 553 554 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override { 555 GLSLShadowFP::GenKey(*this, caps, b); 556 } 557 558 const char* name() const override { return "shadowFP"; } 559 560 int32_t numLights() const { return fNumNonAmbLights; } 561 const SkColor3f& ambientColor() const { return fAmbientColor; } 562 bool isPointLight(int i) const { 563 SkASSERT(i < fNumNonAmbLights); 564 return fIsPointLight[i]; 565 } 566 bool isRadialLight(int i) const { 567 SkASSERT(i < fNumNonAmbLights); 568 return fIsRadialLight[i]; 569 } 570 const SkVector3& lightDirOrPos(int i) const { 571 SkASSERT(i < fNumNonAmbLights); 572 return fLightDirOrPos[i]; 573 } 574 const SkVector3& lightColor(int i) const { 575 SkASSERT(i < fNumNonAmbLights); 576 return fLightColor[i]; 577 } 578 int depthMapWidth(int i) const { 579 SkASSERT(i < fNumNonAmbLights); 580 return fDepthMapWidth[i]; 581 } 582 int depthMapHeight(int i) const { 583 SkASSERT(i < fNumNonAmbLights); 584 return fDepthMapHeight[i]; 585 } 586 int width() const {return fWidth; } 587 int height() const {return fHeight; } 588 589 const SkShadowParams& shadowParams() const {return fShadowParams; } 590 591private: 592 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new GLSLShadowFP; } 593 594 bool onIsEqual(const GrFragmentProcessor& proc) const override { 595 const ShadowFP& shadowFP = proc.cast<ShadowFP>(); 596 if (fAmbientColor != shadowFP.fAmbientColor || 597 fNumNonAmbLights != shadowFP.fNumNonAmbLights) { 598 return false; 599 } 600 601 if (fWidth != shadowFP.fWidth || fHeight != shadowFP.fHeight) { 602 return false; 603 } 604 605 for (int i = 0; i < fNumNonAmbLights; i++) { 606 if (fLightDirOrPos[i] != shadowFP.fLightDirOrPos[i] || 607 fLightColor[i] != shadowFP.fLightColor[i] || 608 fIsPointLight[i] != shadowFP.fIsPointLight[i] || 609 fIsRadialLight[i] != shadowFP.fIsRadialLight[i]) { 610 return false; 611 } 612 613 if (fDepthMapWidth[i] != shadowFP.fDepthMapWidth[i] || 614 fDepthMapHeight[i] != shadowFP.fDepthMapHeight[i]) { 615 return false; 616 } 617 } 618 619 return true; 620 } 621 622 int fNumNonAmbLights; 623 624 bool fIsPointLight[SkShadowShader::kMaxNonAmbientLights]; 625 bool fIsRadialLight[SkShadowShader::kMaxNonAmbientLights]; 626 SkVector3 fLightDirOrPos[SkShadowShader::kMaxNonAmbientLights]; 627 SkColor3f fLightColor[SkShadowShader::kMaxNonAmbientLights]; 628 TextureSampler fDepthMapSampler[SkShadowShader::kMaxNonAmbientLights]; 629 sk_sp<GrTexture> fTexture[SkShadowShader::kMaxNonAmbientLights]; 630 631 int fDepthMapWidth[SkShadowShader::kMaxNonAmbientLights]; 632 int fDepthMapHeight[SkShadowShader::kMaxNonAmbientLights]; 633 634 int fHeight; 635 int fWidth; 636 637 SkShadowParams fShadowParams; 638 639 SkColor3f fAmbientColor; 640}; 641 642//////////////////////////////////////////////////////////////////////////// 643 644sk_sp<GrFragmentProcessor> SkShadowShaderImpl::asFragmentProcessor(const AsFPArgs& fpargs) const { 645 646 sk_sp<GrFragmentProcessor> povDepthFP = fPovDepthShader->asFragmentProcessor(fpargs); 647 648 sk_sp<GrFragmentProcessor> diffuseFP = fDiffuseShader->asFragmentProcessor(fpargs); 649 650 sk_sp<GrFragmentProcessor> shadowfp = sk_make_sp<ShadowFP>(std::move(povDepthFP), 651 std::move(diffuseFP), 652 std::move(fLights), 653 fDiffuseWidth, fDiffuseHeight, 654 fShadowParams, fpargs.fContext); 655 return shadowfp; 656} 657 658 659#endif 660 661//////////////////////////////////////////////////////////////////////////// 662 663bool SkShadowShaderImpl::isOpaque() const { 664 return fDiffuseShader->isOpaque(); 665} 666 667SkShadowShaderImpl::ShadowShaderContext::ShadowShaderContext( 668 const SkShadowShaderImpl& shader, const ContextRec& rec, 669 SkShader::Context* povDepthContext, 670 SkShader::Context* diffuseContext, 671 void* heapAllocated) 672 : INHERITED(shader, rec) 673 , fPovDepthContext(povDepthContext) 674 , fDiffuseContext(diffuseContext) 675 , fHeapAllocated(heapAllocated) { 676 bool isOpaque = shader.isOpaque(); 677 678 // update fFlags 679 uint32_t flags = 0; 680 if (isOpaque && (255 == this->getPaintAlpha())) { 681 flags |= kOpaqueAlpha_Flag; 682 } 683 684 fFlags = flags; 685 686 const SkShadowShaderImpl& lightShader = static_cast<const SkShadowShaderImpl&>(fShader); 687 688 fNonAmbLightCnt = lightShader.fLights->numLights(); 689 fShadowMapPixels = new SkPixmap[fNonAmbLightCnt]; 690 691 for (int i = 0; i < fNonAmbLightCnt; i++) { 692 if (lightShader.fLights->light(i).type() == SkLights::Light::kDirectional_LightType) { 693 lightShader.fLights->light(i).getShadowMap()-> 694 peekPixels(&fShadowMapPixels[i]); 695 } 696 } 697} 698 699SkShadowShaderImpl::ShadowShaderContext::~ShadowShaderContext() { 700 delete[] fShadowMapPixels; 701 702 // The dependencies have been created outside of the context on memory that was allocated by 703 // the onCreateContext() method. Call the destructors and free the memory. 704 fPovDepthContext->~Context(); 705 fDiffuseContext->~Context(); 706 707 sk_free(fHeapAllocated); 708} 709 710static inline SkPMColor convert(SkColor3f color, U8CPU a) { 711 if (color.fX <= 0.0f) { 712 color.fX = 0.0f; 713 } else if (color.fX >= 255.0f) { 714 color.fX = 255.0f; 715 } 716 717 if (color.fY <= 0.0f) { 718 color.fY = 0.0f; 719 } else if (color.fY >= 255.0f) { 720 color.fY = 255.0f; 721 } 722 723 if (color.fZ <= 0.0f) { 724 color.fZ = 0.0f; 725 } else if (color.fZ >= 255.0f) { 726 color.fZ = 255.0f; 727 } 728 729 return SkPreMultiplyARGB(a, (int) color.fX, (int) color.fY, (int) color.fZ); 730} 731 732// larger is better (fewer times we have to loop), but we shouldn't 733// take up too much stack-space (each one here costs 16 bytes) 734#define BUFFER_MAX 16 735void SkShadowShaderImpl::ShadowShaderContext::shadeSpan(int x, int y, 736 SkPMColor result[], int count) { 737 const SkShadowShaderImpl& lightShader = static_cast<const SkShadowShaderImpl&>(fShader); 738 739 SkPMColor diffuse[BUFFER_MAX]; 740 SkPMColor povDepth[BUFFER_MAX]; 741 742 do { 743 int n = SkTMin(count, BUFFER_MAX); 744 745 fDiffuseContext->shadeSpan(x, y, diffuse, n); 746 fPovDepthContext->shadeSpan(x, y, povDepth, n); 747 748 for (int i = 0; i < n; ++i) { 749 SkColor diffColor = SkUnPreMultiply::PMColorToColor(diffuse[i]); 750 SkColor povDepthColor = povDepth[i]; 751 752 SkColor3f totalLight = lightShader.fLights->ambientLightColor(); 753 // This is all done in linear unpremul color space (each component 0..255.0f though) 754 755 for (int l = 0; l < lightShader.fLights->numLights(); ++l) { 756 const SkLights::Light& light = lightShader.fLights->light(l); 757 758 int pvDepth = SkColorGetB(povDepthColor); // depth stored in blue channel 759 760 if (light.type() == SkLights::Light::kDirectional_LightType) { 761 762 int xOffset = SkScalarRoundToInt(light.dir().fX * pvDepth); 763 int yOffset = SkScalarRoundToInt(light.dir().fY * pvDepth); 764 765 int shX = SkClampMax(x + i + xOffset, light.getShadowMap()->width() - 1); 766 int shY = SkClampMax(y + yOffset, light.getShadowMap()->height() - 1); 767 768 int shDepth = 0; 769 int shDepthsq = 0; 770 771 // pixmaps that point to things have nonzero heights 772 if (fShadowMapPixels[l].height() > 0) { 773 uint32_t pix = *fShadowMapPixels[l].addr32(shX, shY); 774 SkColor shColor(pix); 775 776 shDepth = SkColorGetB(shColor); 777 shDepthsq = SkColorGetG(shColor) * 256; 778 } else { 779 // Make lights w/o a shadow map receive the full light contribution 780 shDepth = pvDepth; 781 } 782 783 SkScalar lightProb = 1.0f; 784 if (pvDepth < shDepth) { 785 if (lightShader.fShadowParams.fType == 786 SkShadowParams::ShadowType::kVariance_ShadowType) { 787 int variance = SkMaxScalar(shDepthsq - shDepth * shDepth, 788 lightShader.fShadowParams.fMinVariance); 789 int d = pvDepth - shDepth; 790 791 lightProb = (SkScalar) variance / ((SkScalar) (variance + d * d)); 792 793 SkScalar bias = lightShader.fShadowParams.fBiasingConstant; 794 795 lightProb = SkMaxScalar((lightProb - bias) / (1.0f - bias), 0.0f); 796 } else { 797 lightProb = 0.0f; 798 } 799 } 800 801 // assume object normals are pointing straight up 802 totalLight.fX += light.dir().fZ * light.color().fX * lightProb; 803 totalLight.fY += light.dir().fZ * light.color().fY * lightProb; 804 totalLight.fZ += light.dir().fZ * light.color().fZ * lightProb; 805 806 } else { 807 // right now we only expect directional and point light types. 808 SkASSERT(light.type() == SkLights::Light::kPoint_LightType); 809 810 int height = lightShader.fDiffuseHeight; 811 812 SkVector3 fragToLight = SkVector3::Make(light.pos().fX - x - i, 813 light.pos().fY - (height - y), 814 light.pos().fZ - pvDepth); 815 816 SkScalar dist = fragToLight.length(); 817 SkScalar normalizedZ = fragToLight.fZ / dist; 818 819 SkScalar distAttenuation = light.intensity() / (1.0f + dist); 820 821 // assume object normals are pointing straight up 822 totalLight.fX += normalizedZ * light.color().fX * distAttenuation; 823 totalLight.fY += normalizedZ * light.color().fY * distAttenuation; 824 totalLight.fZ += normalizedZ * light.color().fZ * distAttenuation; 825 } 826 } 827 828 SkColor3f totalColor = SkColor3f::Make(SkColorGetR(diffColor) * totalLight.fX, 829 SkColorGetG(diffColor) * totalLight.fY, 830 SkColorGetB(diffColor) * totalLight.fZ); 831 832 result[i] = convert(totalColor, SkColorGetA(diffColor)); 833 } 834 835 result += n; 836 x += n; 837 count -= n; 838 } while (count > 0); 839} 840 841//////////////////////////////////////////////////////////////////////////// 842 843#ifndef SK_IGNORE_TO_STRING 844void SkShadowShaderImpl::toString(SkString* str) const { 845 str->appendf("ShadowShader: ()"); 846} 847#endif 848 849sk_sp<SkFlattenable> SkShadowShaderImpl::CreateProc(SkReadBuffer& buf) { 850 851 // Discarding SkShader flattenable params 852 bool hasLocalMatrix = buf.readBool(); 853 SkAssertResult(!hasLocalMatrix); 854 855 sk_sp<SkLights> lights = SkLights::MakeFromBuffer(buf); 856 857 SkShadowParams params; 858 params.fMinVariance = buf.readScalar(); 859 params.fBiasingConstant = buf.readScalar(); 860 params.fType = (SkShadowParams::ShadowType) buf.readInt(); 861 params.fShadowRadius = buf.readScalar(); 862 863 int diffuseWidth = buf.readInt(); 864 int diffuseHeight = buf.readInt(); 865 866 sk_sp<SkShader> povDepthShader(buf.readFlattenable<SkShader>()); 867 sk_sp<SkShader> diffuseShader(buf.readFlattenable<SkShader>()); 868 869 return sk_make_sp<SkShadowShaderImpl>(std::move(povDepthShader), 870 std::move(diffuseShader), 871 std::move(lights), 872 diffuseWidth, diffuseHeight, 873 params); 874} 875 876void SkShadowShaderImpl::flatten(SkWriteBuffer& buf) const { 877 this->INHERITED::flatten(buf); 878 879 fLights->flatten(buf); 880 881 buf.writeScalar(fShadowParams.fMinVariance); 882 buf.writeScalar(fShadowParams.fBiasingConstant); 883 buf.writeInt(fShadowParams.fType); 884 buf.writeScalar(fShadowParams.fShadowRadius); 885 886 buf.writeInt(fDiffuseWidth); 887 buf.writeInt(fDiffuseHeight); 888 889 buf.writeFlattenable(fPovDepthShader.get()); 890 buf.writeFlattenable(fDiffuseShader.get()); 891} 892 893size_t SkShadowShaderImpl::onContextSize(const ContextRec& rec) const { 894 return sizeof(ShadowShaderContext); 895} 896 897SkShader::Context* SkShadowShaderImpl::onCreateContext(const ContextRec& rec, 898 void* storage) const { 899 size_t heapRequired = fPovDepthShader->contextSize(rec) + 900 fDiffuseShader->contextSize(rec); 901 902 void* heapAllocated = sk_malloc_throw(heapRequired); 903 904 void* povDepthContextStorage = heapAllocated; 905 906 SkShader::Context* povDepthContext = 907 fPovDepthShader->createContext(rec, povDepthContextStorage); 908 909 if (!povDepthContext) { 910 sk_free(heapAllocated); 911 return nullptr; 912 } 913 914 void* diffuseContextStorage = (char*)heapAllocated + fPovDepthShader->contextSize(rec); 915 916 SkShader::Context* diffuseContext = fDiffuseShader->createContext(rec, diffuseContextStorage); 917 if (!diffuseContext) { 918 sk_free(heapAllocated); 919 return nullptr; 920 } 921 922 return new (storage) ShadowShaderContext(*this, rec, povDepthContext, diffuseContext, 923 heapAllocated); 924} 925 926/////////////////////////////////////////////////////////////////////////////// 927 928sk_sp<SkShader> SkShadowShader::Make(sk_sp<SkShader> povDepthShader, 929 sk_sp<SkShader> diffuseShader, 930 sk_sp<SkLights> lights, 931 int diffuseWidth, int diffuseHeight, 932 const SkShadowParams& params) { 933 if (!povDepthShader || !diffuseShader) { 934 // TODO: Use paint's color in absence of a diffuseShader 935 // TODO: Use a default implementation of normalSource instead 936 return nullptr; 937 } 938 939 return sk_make_sp<SkShadowShaderImpl>(std::move(povDepthShader), 940 std::move(diffuseShader), 941 std::move(lights), 942 diffuseWidth, diffuseHeight, 943 params); 944} 945 946/////////////////////////////////////////////////////////////////////////////// 947 948SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkShadowShader) 949 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkShadowShaderImpl) 950SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 951 952/////////////////////////////////////////////////////////////////////////////// 953 954#endif 955