1 /* 2 * Copyright 2012 The Android Open Source Project 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 "SkLightingImageFilter.h" 9 #include "SkBitmap.h" 10 #include "SkColorPriv.h" 11 #include "SkReadBuffer.h" 12 #include "SkWriteBuffer.h" 13 #include "SkReadBuffer.h" 14 #include "SkWriteBuffer.h" 15 #include "SkTypes.h" 16 17 #if SK_SUPPORT_GPU 18 #include "effects/GrSingleTextureEffect.h" 19 #include "gl/GrGLProcessor.h" 20 #include "gl/builders/GrGLProgramBuilder.h" 21 #include "GrProcessor.h" 22 #include "GrTBackendProcessorFactory.h" 23 24 class GrGLDiffuseLightingEffect; 25 class GrGLSpecularLightingEffect; 26 27 // For brevity 28 typedef GrGLProgramDataManager::UniformHandle UniformHandle; 29 #endif 30 31 namespace { 32 33 const SkScalar gOneThird = SkScalarInvert(SkIntToScalar(3)); 34 const SkScalar gTwoThirds = SkScalarDiv(SkIntToScalar(2), SkIntToScalar(3)); 35 const SkScalar gOneHalf = 0.5f; 36 const SkScalar gOneQuarter = 0.25f; 37 38 #if SK_SUPPORT_GPU 39 void setUniformPoint3(const GrGLProgramDataManager& pdman, UniformHandle uni, 40 const SkPoint3& point) { 41 GR_STATIC_ASSERT(sizeof(SkPoint3) == 3 * sizeof(GrGLfloat)); 42 pdman.set3fv(uni, 1, &point.fX); 43 } 44 45 void setUniformNormal3(const GrGLProgramDataManager& pdman, UniformHandle uni, 46 const SkPoint3& point) { 47 setUniformPoint3(pdman, uni, SkPoint3(point.fX, point.fY, point.fZ)); 48 } 49 #endif 50 51 // Shift matrix components to the left, as we advance pixels to the right. 52 inline void shiftMatrixLeft(int m[9]) { 53 m[0] = m[1]; 54 m[3] = m[4]; 55 m[6] = m[7]; 56 m[1] = m[2]; 57 m[4] = m[5]; 58 m[7] = m[8]; 59 } 60 61 class DiffuseLightingType { 62 public: 63 DiffuseLightingType(SkScalar kd) 64 : fKD(kd) {} 65 SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight, 66 const SkPoint3& lightColor) const { 67 SkScalar colorScale = SkScalarMul(fKD, normal.dot(surfaceTolight)); 68 colorScale = SkScalarClampMax(colorScale, SK_Scalar1); 69 SkPoint3 color(lightColor * colorScale); 70 return SkPackARGB32(255, 71 SkClampMax(SkScalarRoundToInt(color.fX), 255), 72 SkClampMax(SkScalarRoundToInt(color.fY), 255), 73 SkClampMax(SkScalarRoundToInt(color.fZ), 255)); 74 } 75 private: 76 SkScalar fKD; 77 }; 78 79 class SpecularLightingType { 80 public: 81 SpecularLightingType(SkScalar ks, SkScalar shininess) 82 : fKS(ks), fShininess(shininess) {} 83 SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight, 84 const SkPoint3& lightColor) const { 85 SkPoint3 halfDir(surfaceTolight); 86 halfDir.fZ += SK_Scalar1; // eye position is always (0, 0, 1) 87 halfDir.normalize(); 88 SkScalar colorScale = SkScalarMul(fKS, 89 SkScalarPow(normal.dot(halfDir), fShininess)); 90 colorScale = SkScalarClampMax(colorScale, SK_Scalar1); 91 SkPoint3 color(lightColor * colorScale); 92 return SkPackARGB32(SkClampMax(SkScalarRoundToInt(color.maxComponent()), 255), 93 SkClampMax(SkScalarRoundToInt(color.fX), 255), 94 SkClampMax(SkScalarRoundToInt(color.fY), 255), 95 SkClampMax(SkScalarRoundToInt(color.fZ), 255)); 96 } 97 private: 98 SkScalar fKS; 99 SkScalar fShininess; 100 }; 101 102 inline SkScalar sobel(int a, int b, int c, int d, int e, int f, SkScalar scale) { 103 return SkScalarMul(SkIntToScalar(-a + b - 2 * c + 2 * d -e + f), scale); 104 } 105 106 inline SkPoint3 pointToNormal(SkScalar x, SkScalar y, SkScalar surfaceScale) { 107 SkPoint3 vector(SkScalarMul(-x, surfaceScale), 108 SkScalarMul(-y, surfaceScale), 109 SK_Scalar1); 110 vector.normalize(); 111 return vector; 112 } 113 114 inline SkPoint3 topLeftNormal(int m[9], SkScalar surfaceScale) { 115 return pointToNormal(sobel(0, 0, m[4], m[5], m[7], m[8], gTwoThirds), 116 sobel(0, 0, m[4], m[7], m[5], m[8], gTwoThirds), 117 surfaceScale); 118 } 119 120 inline SkPoint3 topNormal(int m[9], SkScalar surfaceScale) { 121 return pointToNormal(sobel( 0, 0, m[3], m[5], m[6], m[8], gOneThird), 122 sobel(m[3], m[6], m[4], m[7], m[5], m[8], gOneHalf), 123 surfaceScale); 124 } 125 126 inline SkPoint3 topRightNormal(int m[9], SkScalar surfaceScale) { 127 return pointToNormal(sobel( 0, 0, m[3], m[4], m[6], m[7], gTwoThirds), 128 sobel(m[3], m[6], m[4], m[7], 0, 0, gTwoThirds), 129 surfaceScale); 130 } 131 132 inline SkPoint3 leftNormal(int m[9], SkScalar surfaceScale) { 133 return pointToNormal(sobel(m[1], m[2], m[4], m[5], m[7], m[8], gOneHalf), 134 sobel( 0, 0, m[1], m[7], m[2], m[8], gOneThird), 135 surfaceScale); 136 } 137 138 139 inline SkPoint3 interiorNormal(int m[9], SkScalar surfaceScale) { 140 return pointToNormal(sobel(m[0], m[2], m[3], m[5], m[6], m[8], gOneQuarter), 141 sobel(m[0], m[6], m[1], m[7], m[2], m[8], gOneQuarter), 142 surfaceScale); 143 } 144 145 inline SkPoint3 rightNormal(int m[9], SkScalar surfaceScale) { 146 return pointToNormal(sobel(m[0], m[1], m[3], m[4], m[6], m[7], gOneHalf), 147 sobel(m[0], m[6], m[1], m[7], 0, 0, gOneThird), 148 surfaceScale); 149 } 150 151 inline SkPoint3 bottomLeftNormal(int m[9], SkScalar surfaceScale) { 152 return pointToNormal(sobel(m[1], m[2], m[4], m[5], 0, 0, gTwoThirds), 153 sobel( 0, 0, m[1], m[4], m[2], m[5], gTwoThirds), 154 surfaceScale); 155 } 156 157 inline SkPoint3 bottomNormal(int m[9], SkScalar surfaceScale) { 158 return pointToNormal(sobel(m[0], m[2], m[3], m[5], 0, 0, gOneThird), 159 sobel(m[0], m[3], m[1], m[4], m[2], m[5], gOneHalf), 160 surfaceScale); 161 } 162 163 inline SkPoint3 bottomRightNormal(int m[9], SkScalar surfaceScale) { 164 return pointToNormal(sobel(m[0], m[1], m[3], m[4], 0, 0, gTwoThirds), 165 sobel(m[0], m[3], m[1], m[4], 0, 0, gTwoThirds), 166 surfaceScale); 167 } 168 169 template <class LightingType, class LightType> void lightBitmap( 170 const LightingType& lightingType, const SkLight* light, const SkBitmap& src, SkBitmap* dst, 171 SkScalar surfaceScale, const SkIRect& bounds) { 172 SkASSERT(dst->width() == bounds.width() && dst->height() == bounds.height()); 173 const LightType* l = static_cast<const LightType*>(light); 174 int left = bounds.left(), right = bounds.right(); 175 int bottom = bounds.bottom(); 176 int y = bounds.top(); 177 SkPMColor* dptr = dst->getAddr32(0, 0); 178 { 179 int x = left; 180 const SkPMColor* row1 = src.getAddr32(x, y); 181 const SkPMColor* row2 = src.getAddr32(x, y + 1); 182 int m[9]; 183 m[4] = SkGetPackedA32(*row1++); 184 m[5] = SkGetPackedA32(*row1++); 185 m[7] = SkGetPackedA32(*row2++); 186 m[8] = SkGetPackedA32(*row2++); 187 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); 188 *dptr++ = lightingType.light(topLeftNormal(m, surfaceScale), surfaceToLight, 189 l->lightColor(surfaceToLight)); 190 for (++x; x < right - 1; ++x) 191 { 192 shiftMatrixLeft(m); 193 m[5] = SkGetPackedA32(*row1++); 194 m[8] = SkGetPackedA32(*row2++); 195 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); 196 *dptr++ = lightingType.light(topNormal(m, surfaceScale), surfaceToLight, 197 l->lightColor(surfaceToLight)); 198 } 199 shiftMatrixLeft(m); 200 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); 201 *dptr++ = lightingType.light(topRightNormal(m, surfaceScale), surfaceToLight, 202 l->lightColor(surfaceToLight)); 203 } 204 205 for (++y; y < bottom - 1; ++y) { 206 int x = left; 207 const SkPMColor* row0 = src.getAddr32(x, y - 1); 208 const SkPMColor* row1 = src.getAddr32(x, y); 209 const SkPMColor* row2 = src.getAddr32(x, y + 1); 210 int m[9]; 211 m[1] = SkGetPackedA32(*row0++); 212 m[2] = SkGetPackedA32(*row0++); 213 m[4] = SkGetPackedA32(*row1++); 214 m[5] = SkGetPackedA32(*row1++); 215 m[7] = SkGetPackedA32(*row2++); 216 m[8] = SkGetPackedA32(*row2++); 217 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); 218 *dptr++ = lightingType.light(leftNormal(m, surfaceScale), surfaceToLight, 219 l->lightColor(surfaceToLight)); 220 for (++x; x < right - 1; ++x) { 221 shiftMatrixLeft(m); 222 m[2] = SkGetPackedA32(*row0++); 223 m[5] = SkGetPackedA32(*row1++); 224 m[8] = SkGetPackedA32(*row2++); 225 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); 226 *dptr++ = lightingType.light(interiorNormal(m, surfaceScale), surfaceToLight, 227 l->lightColor(surfaceToLight)); 228 } 229 shiftMatrixLeft(m); 230 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); 231 *dptr++ = lightingType.light(rightNormal(m, surfaceScale), surfaceToLight, 232 l->lightColor(surfaceToLight)); 233 } 234 235 { 236 int x = left; 237 const SkPMColor* row0 = src.getAddr32(x, bottom - 2); 238 const SkPMColor* row1 = src.getAddr32(x, bottom - 1); 239 int m[9]; 240 m[1] = SkGetPackedA32(*row0++); 241 m[2] = SkGetPackedA32(*row0++); 242 m[4] = SkGetPackedA32(*row1++); 243 m[5] = SkGetPackedA32(*row1++); 244 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); 245 *dptr++ = lightingType.light(bottomLeftNormal(m, surfaceScale), surfaceToLight, 246 l->lightColor(surfaceToLight)); 247 for (++x; x < right - 1; ++x) 248 { 249 shiftMatrixLeft(m); 250 m[2] = SkGetPackedA32(*row0++); 251 m[5] = SkGetPackedA32(*row1++); 252 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); 253 *dptr++ = lightingType.light(bottomNormal(m, surfaceScale), surfaceToLight, 254 l->lightColor(surfaceToLight)); 255 } 256 shiftMatrixLeft(m); 257 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); 258 *dptr++ = lightingType.light(bottomRightNormal(m, surfaceScale), surfaceToLight, 259 l->lightColor(surfaceToLight)); 260 } 261 } 262 263 SkPoint3 readPoint3(SkReadBuffer& buffer) { 264 SkPoint3 point; 265 point.fX = buffer.readScalar(); 266 point.fY = buffer.readScalar(); 267 point.fZ = buffer.readScalar(); 268 buffer.validate(SkScalarIsFinite(point.fX) && 269 SkScalarIsFinite(point.fY) && 270 SkScalarIsFinite(point.fZ)); 271 return point; 272 }; 273 274 void writePoint3(const SkPoint3& point, SkWriteBuffer& buffer) { 275 buffer.writeScalar(point.fX); 276 buffer.writeScalar(point.fY); 277 buffer.writeScalar(point.fZ); 278 }; 279 280 class SkDiffuseLightingImageFilter : public SkLightingImageFilter { 281 public: 282 static SkImageFilter* Create(SkLight* light, SkScalar surfaceScale, SkScalar kd, SkImageFilter*, 283 const CropRect*, uint32_t uniqueID = 0); 284 285 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDiffuseLightingImageFilter) 286 SkScalar kd() const { return fKD; } 287 288 protected: 289 SkDiffuseLightingImageFilter(SkLight* light, SkScalar surfaceScale, 290 SkScalar kd, SkImageFilter* input, const CropRect* cropRect, 291 uint32_t uniqueID); 292 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING 293 explicit SkDiffuseLightingImageFilter(SkReadBuffer& buffer); 294 #endif 295 virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE; 296 virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&, 297 SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE; 298 #if SK_SUPPORT_GPU 299 virtual bool asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&, 300 const SkIRect& bounds) const SK_OVERRIDE; 301 #endif 302 303 private: 304 friend class SkLightingImageFilter; 305 typedef SkLightingImageFilter INHERITED; 306 SkScalar fKD; 307 }; 308 309 class SkSpecularLightingImageFilter : public SkLightingImageFilter { 310 public: 311 static SkImageFilter* Create(SkLight* light, SkScalar surfaceScale, 312 SkScalar ks, SkScalar shininess, SkImageFilter*, const CropRect*, 313 uint32_t uniqueID = 0); 314 315 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSpecularLightingImageFilter) 316 317 SkScalar ks() const { return fKS; } 318 SkScalar shininess() const { return fShininess; } 319 320 protected: 321 SkSpecularLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar ks, 322 SkScalar shininess, SkImageFilter* input, const CropRect*, 323 uint32_t uniqueID); 324 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING 325 explicit SkSpecularLightingImageFilter(SkReadBuffer& buffer); 326 #endif 327 virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE; 328 virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&, 329 SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE; 330 #if SK_SUPPORT_GPU 331 virtual bool asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&, 332 const SkIRect& bounds) const SK_OVERRIDE; 333 #endif 334 335 private: 336 SkScalar fKS; 337 SkScalar fShininess; 338 friend class SkLightingImageFilter; 339 typedef SkLightingImageFilter INHERITED; 340 }; 341 342 #if SK_SUPPORT_GPU 343 344 class GrLightingEffect : public GrSingleTextureEffect { 345 public: 346 GrLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale, const SkMatrix& matrix); 347 virtual ~GrLightingEffect(); 348 349 const SkLight* light() const { return fLight; } 350 SkScalar surfaceScale() const { return fSurfaceScale; } 351 const SkMatrix& filterMatrix() const { return fFilterMatrix; } 352 353 virtual void getConstantColorComponents(GrColor* color, 354 uint32_t* validFlags) const SK_OVERRIDE { 355 // lighting shaders are complicated. We just throw up our hands. 356 *validFlags = 0; 357 } 358 359 protected: 360 virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE; 361 362 private: 363 typedef GrSingleTextureEffect INHERITED; 364 const SkLight* fLight; 365 SkScalar fSurfaceScale; 366 SkMatrix fFilterMatrix; 367 }; 368 369 class GrDiffuseLightingEffect : public GrLightingEffect { 370 public: 371 static GrFragmentProcessor* Create(GrTexture* texture, 372 const SkLight* light, 373 SkScalar surfaceScale, 374 const SkMatrix& matrix, 375 SkScalar kd) { 376 return SkNEW_ARGS(GrDiffuseLightingEffect, (texture, 377 light, 378 surfaceScale, 379 matrix, 380 kd)); 381 } 382 383 static const char* Name() { return "DiffuseLighting"; } 384 385 typedef GrGLDiffuseLightingEffect GLProcessor; 386 387 virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE; 388 SkScalar kd() const { return fKD; } 389 390 private: 391 virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE; 392 393 GrDiffuseLightingEffect(GrTexture* texture, 394 const SkLight* light, 395 SkScalar surfaceScale, 396 const SkMatrix& matrix, 397 SkScalar kd); 398 399 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; 400 typedef GrLightingEffect INHERITED; 401 SkScalar fKD; 402 }; 403 404 class GrSpecularLightingEffect : public GrLightingEffect { 405 public: 406 static GrFragmentProcessor* Create(GrTexture* texture, 407 const SkLight* light, 408 SkScalar surfaceScale, 409 const SkMatrix& matrix, 410 SkScalar ks, 411 SkScalar shininess) { 412 return SkNEW_ARGS(GrSpecularLightingEffect, (texture, 413 light, 414 surfaceScale, 415 matrix, 416 ks, 417 shininess)); 418 } 419 static const char* Name() { return "SpecularLighting"; } 420 421 typedef GrGLSpecularLightingEffect GLProcessor; 422 423 virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE; 424 SkScalar ks() const { return fKS; } 425 SkScalar shininess() const { return fShininess; } 426 427 private: 428 virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE; 429 430 GrSpecularLightingEffect(GrTexture* texture, 431 const SkLight* light, 432 SkScalar surfaceScale, 433 const SkMatrix& matrix, 434 SkScalar ks, 435 SkScalar shininess); 436 437 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; 438 typedef GrLightingEffect INHERITED; 439 SkScalar fKS; 440 SkScalar fShininess; 441 }; 442 443 /////////////////////////////////////////////////////////////////////////////// 444 445 class GrGLLight { 446 public: 447 virtual ~GrGLLight() {} 448 449 /** 450 * This is called by GrGLLightingEffect::emitCode() before either of the two virtual functions 451 * below. It adds a vec3f uniform visible in the FS that represents the constant light color. 452 */ 453 void emitLightColorUniform(GrGLProgramBuilder*); 454 455 /** 456 * These two functions are called from GrGLLightingEffect's emitCode() function. 457 * emitSurfaceToLight places an expression in param out that is the vector from the surface to 458 * the light. The expression will be used in the FS. emitLightColor writes an expression into 459 * the FS that is the color of the light. Either function may add functions and/or uniforms to 460 * the FS. The default of emitLightColor appends the name of the constant light color uniform 461 * and so this function only needs to be overridden if the light color varies spatially. 462 */ 463 virtual void emitSurfaceToLight(GrGLProgramBuilder*, const char* z) = 0; 464 virtual void emitLightColor(GrGLProgramBuilder*, const char *surfaceToLight); 465 466 // This is called from GrGLLightingEffect's setData(). Subclasses of GrGLLight must call 467 // INHERITED::setData(). 468 virtual void setData(const GrGLProgramDataManager&, 469 const SkLight* light) const; 470 471 protected: 472 /** 473 * Gets the constant light color uniform. Subclasses can use this in their emitLightColor 474 * function. 475 */ 476 UniformHandle lightColorUni() const { return fColorUni; } 477 478 private: 479 UniformHandle fColorUni; 480 481 typedef SkRefCnt INHERITED; 482 }; 483 484 /////////////////////////////////////////////////////////////////////////////// 485 486 class GrGLDistantLight : public GrGLLight { 487 public: 488 virtual ~GrGLDistantLight() {} 489 virtual void setData(const GrGLProgramDataManager&, 490 const SkLight* light) const SK_OVERRIDE; 491 virtual void emitSurfaceToLight(GrGLProgramBuilder*, const char* z) SK_OVERRIDE; 492 493 private: 494 typedef GrGLLight INHERITED; 495 UniformHandle fDirectionUni; 496 }; 497 498 /////////////////////////////////////////////////////////////////////////////// 499 500 class GrGLPointLight : public GrGLLight { 501 public: 502 virtual ~GrGLPointLight() {} 503 virtual void setData(const GrGLProgramDataManager&, 504 const SkLight* light) const SK_OVERRIDE; 505 virtual void emitSurfaceToLight(GrGLProgramBuilder*, const char* z) SK_OVERRIDE; 506 507 private: 508 typedef GrGLLight INHERITED; 509 UniformHandle fLocationUni; 510 }; 511 512 /////////////////////////////////////////////////////////////////////////////// 513 514 class GrGLSpotLight : public GrGLLight { 515 public: 516 virtual ~GrGLSpotLight() {} 517 virtual void setData(const GrGLProgramDataManager&, 518 const SkLight* light) const SK_OVERRIDE; 519 virtual void emitSurfaceToLight(GrGLProgramBuilder*, const char* z) SK_OVERRIDE; 520 virtual void emitLightColor(GrGLProgramBuilder*, const char *surfaceToLight) SK_OVERRIDE; 521 522 private: 523 typedef GrGLLight INHERITED; 524 525 SkString fLightColorFunc; 526 UniformHandle fLocationUni; 527 UniformHandle fExponentUni; 528 UniformHandle fCosOuterConeAngleUni; 529 UniformHandle fCosInnerConeAngleUni; 530 UniformHandle fConeScaleUni; 531 UniformHandle fSUni; 532 }; 533 #else 534 535 class GrGLLight; 536 537 #endif 538 539 }; 540 541 /////////////////////////////////////////////////////////////////////////////// 542 543 class SkLight : public SkRefCnt { 544 public: 545 SK_DECLARE_INST_COUNT(SkLight) 546 547 enum LightType { 548 kDistant_LightType, 549 kPoint_LightType, 550 kSpot_LightType, 551 }; 552 virtual LightType type() const = 0; 553 const SkPoint3& color() const { return fColor; } 554 virtual GrGLLight* createGLLight() const = 0; 555 virtual bool isEqual(const SkLight& other) const { 556 return fColor == other.fColor; 557 } 558 // Called to know whether the generated GrGLLight will require access to the fragment position. 559 virtual bool requiresFragmentPosition() const = 0; 560 virtual SkLight* transform(const SkMatrix& matrix) const = 0; 561 562 // Defined below SkLight's subclasses. 563 void flattenLight(SkWriteBuffer& buffer) const; 564 static SkLight* UnflattenLight(SkReadBuffer& buffer); 565 566 protected: 567 SkLight(SkColor color) 568 : fColor(SkIntToScalar(SkColorGetR(color)), 569 SkIntToScalar(SkColorGetG(color)), 570 SkIntToScalar(SkColorGetB(color))) {} 571 SkLight(const SkPoint3& color) 572 : fColor(color) {} 573 SkLight(SkReadBuffer& buffer) { 574 fColor = readPoint3(buffer); 575 } 576 577 virtual void onFlattenLight(SkWriteBuffer& buffer) const = 0; 578 579 580 private: 581 typedef SkRefCnt INHERITED; 582 SkPoint3 fColor; 583 }; 584 585 /////////////////////////////////////////////////////////////////////////////// 586 587 class SkDistantLight : public SkLight { 588 public: 589 SkDistantLight(const SkPoint3& direction, SkColor color) 590 : INHERITED(color), fDirection(direction) { 591 } 592 593 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const { 594 return fDirection; 595 }; 596 SkPoint3 lightColor(const SkPoint3&) const { return color(); } 597 virtual LightType type() const { return kDistant_LightType; } 598 const SkPoint3& direction() const { return fDirection; } 599 virtual GrGLLight* createGLLight() const SK_OVERRIDE { 600 #if SK_SUPPORT_GPU 601 return SkNEW(GrGLDistantLight); 602 #else 603 SkDEBUGFAIL("Should not call in GPU-less build"); 604 return NULL; 605 #endif 606 } 607 virtual bool requiresFragmentPosition() const SK_OVERRIDE { return false; } 608 609 virtual bool isEqual(const SkLight& other) const SK_OVERRIDE { 610 if (other.type() != kDistant_LightType) { 611 return false; 612 } 613 614 const SkDistantLight& o = static_cast<const SkDistantLight&>(other); 615 return INHERITED::isEqual(other) && 616 fDirection == o.fDirection; 617 } 618 619 SkDistantLight(SkReadBuffer& buffer) : INHERITED(buffer) { 620 fDirection = readPoint3(buffer); 621 } 622 623 protected: 624 SkDistantLight(const SkPoint3& direction, const SkPoint3& color) 625 : INHERITED(color), fDirection(direction) { 626 } 627 virtual SkLight* transform(const SkMatrix& matrix) const { 628 return new SkDistantLight(direction(), color()); 629 } 630 virtual void onFlattenLight(SkWriteBuffer& buffer) const SK_OVERRIDE { 631 writePoint3(fDirection, buffer); 632 } 633 634 private: 635 typedef SkLight INHERITED; 636 SkPoint3 fDirection; 637 }; 638 639 /////////////////////////////////////////////////////////////////////////////// 640 641 class SkPointLight : public SkLight { 642 public: 643 SkPointLight(const SkPoint3& location, SkColor color) 644 : INHERITED(color), fLocation(location) {} 645 646 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const { 647 SkPoint3 direction(fLocation.fX - SkIntToScalar(x), 648 fLocation.fY - SkIntToScalar(y), 649 fLocation.fZ - SkScalarMul(SkIntToScalar(z), surfaceScale)); 650 direction.normalize(); 651 return direction; 652 }; 653 SkPoint3 lightColor(const SkPoint3&) const { return color(); } 654 virtual LightType type() const { return kPoint_LightType; } 655 const SkPoint3& location() const { return fLocation; } 656 virtual GrGLLight* createGLLight() const SK_OVERRIDE { 657 #if SK_SUPPORT_GPU 658 return SkNEW(GrGLPointLight); 659 #else 660 SkDEBUGFAIL("Should not call in GPU-less build"); 661 return NULL; 662 #endif 663 } 664 virtual bool requiresFragmentPosition() const SK_OVERRIDE { return true; } 665 virtual bool isEqual(const SkLight& other) const SK_OVERRIDE { 666 if (other.type() != kPoint_LightType) { 667 return false; 668 } 669 const SkPointLight& o = static_cast<const SkPointLight&>(other); 670 return INHERITED::isEqual(other) && 671 fLocation == o.fLocation; 672 } 673 virtual SkLight* transform(const SkMatrix& matrix) const { 674 SkPoint location2 = SkPoint::Make(fLocation.fX, fLocation.fY); 675 matrix.mapPoints(&location2, 1); 676 // Use X scale and Y scale on Z and average the result 677 SkPoint locationZ = SkPoint::Make(fLocation.fZ, fLocation.fZ); 678 matrix.mapVectors(&locationZ, 1); 679 SkPoint3 location(location2.fX, location2.fY, SkScalarAve(locationZ.fX, locationZ.fY)); 680 return new SkPointLight(location, color()); 681 } 682 683 SkPointLight(SkReadBuffer& buffer) : INHERITED(buffer) { 684 fLocation = readPoint3(buffer); 685 } 686 687 protected: 688 SkPointLight(const SkPoint3& location, const SkPoint3& color) 689 : INHERITED(color), fLocation(location) {} 690 virtual void onFlattenLight(SkWriteBuffer& buffer) const SK_OVERRIDE { 691 writePoint3(fLocation, buffer); 692 } 693 694 private: 695 typedef SkLight INHERITED; 696 SkPoint3 fLocation; 697 }; 698 699 /////////////////////////////////////////////////////////////////////////////// 700 701 class SkSpotLight : public SkLight { 702 public: 703 SkSpotLight(const SkPoint3& location, const SkPoint3& target, SkScalar specularExponent, SkScalar cutoffAngle, SkColor color) 704 : INHERITED(color), 705 fLocation(location), 706 fTarget(target), 707 fSpecularExponent(SkScalarPin(specularExponent, kSpecularExponentMin, kSpecularExponentMax)) 708 { 709 fS = target - location; 710 fS.normalize(); 711 fCosOuterConeAngle = SkScalarCos(SkDegreesToRadians(cutoffAngle)); 712 const SkScalar antiAliasThreshold = 0.016f; 713 fCosInnerConeAngle = fCosOuterConeAngle + antiAliasThreshold; 714 fConeScale = SkScalarInvert(antiAliasThreshold); 715 } 716 717 virtual SkLight* transform(const SkMatrix& matrix) const { 718 SkPoint location2 = SkPoint::Make(fLocation.fX, fLocation.fY); 719 matrix.mapPoints(&location2, 1); 720 // Use X scale and Y scale on Z and average the result 721 SkPoint locationZ = SkPoint::Make(fLocation.fZ, fLocation.fZ); 722 matrix.mapVectors(&locationZ, 1); 723 SkPoint3 location(location2.fX, location2.fY, SkScalarAve(locationZ.fX, locationZ.fY)); 724 SkPoint target2 = SkPoint::Make(fTarget.fX, fTarget.fY); 725 matrix.mapPoints(&target2, 1); 726 SkPoint targetZ = SkPoint::Make(fTarget.fZ, fTarget.fZ); 727 matrix.mapVectors(&targetZ, 1); 728 SkPoint3 target(target2.fX, target2.fY, SkScalarAve(targetZ.fX, targetZ.fY)); 729 SkPoint3 s = target - location; 730 s.normalize(); 731 return new SkSpotLight(location, target, fSpecularExponent, fCosOuterConeAngle, fCosInnerConeAngle, fConeScale, s, color()); 732 } 733 734 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const { 735 SkPoint3 direction(fLocation.fX - SkIntToScalar(x), 736 fLocation.fY - SkIntToScalar(y), 737 fLocation.fZ - SkScalarMul(SkIntToScalar(z), surfaceScale)); 738 direction.normalize(); 739 return direction; 740 }; 741 SkPoint3 lightColor(const SkPoint3& surfaceToLight) const { 742 SkScalar cosAngle = -surfaceToLight.dot(fS); 743 if (cosAngle < fCosOuterConeAngle) { 744 return SkPoint3(0, 0, 0); 745 } 746 SkScalar scale = SkScalarPow(cosAngle, fSpecularExponent); 747 if (cosAngle < fCosInnerConeAngle) { 748 scale = SkScalarMul(scale, cosAngle - fCosOuterConeAngle); 749 return color() * SkScalarMul(scale, fConeScale); 750 } 751 return color() * scale; 752 } 753 virtual GrGLLight* createGLLight() const SK_OVERRIDE { 754 #if SK_SUPPORT_GPU 755 return SkNEW(GrGLSpotLight); 756 #else 757 SkDEBUGFAIL("Should not call in GPU-less build"); 758 return NULL; 759 #endif 760 } 761 virtual bool requiresFragmentPosition() const SK_OVERRIDE { return true; } 762 virtual LightType type() const { return kSpot_LightType; } 763 const SkPoint3& location() const { return fLocation; } 764 const SkPoint3& target() const { return fTarget; } 765 SkScalar specularExponent() const { return fSpecularExponent; } 766 SkScalar cosInnerConeAngle() const { return fCosInnerConeAngle; } 767 SkScalar cosOuterConeAngle() const { return fCosOuterConeAngle; } 768 SkScalar coneScale() const { return fConeScale; } 769 const SkPoint3& s() const { return fS; } 770 771 SkSpotLight(SkReadBuffer& buffer) : INHERITED(buffer) { 772 fLocation = readPoint3(buffer); 773 fTarget = readPoint3(buffer); 774 fSpecularExponent = buffer.readScalar(); 775 fCosOuterConeAngle = buffer.readScalar(); 776 fCosInnerConeAngle = buffer.readScalar(); 777 fConeScale = buffer.readScalar(); 778 fS = readPoint3(buffer); 779 buffer.validate(SkScalarIsFinite(fSpecularExponent) && 780 SkScalarIsFinite(fCosOuterConeAngle) && 781 SkScalarIsFinite(fCosInnerConeAngle) && 782 SkScalarIsFinite(fConeScale)); 783 } 784 protected: 785 SkSpotLight(const SkPoint3& location, const SkPoint3& target, SkScalar specularExponent, SkScalar cosOuterConeAngle, SkScalar cosInnerConeAngle, SkScalar coneScale, const SkPoint3& s, const SkPoint3& color) 786 : INHERITED(color), 787 fLocation(location), 788 fTarget(target), 789 fSpecularExponent(specularExponent), 790 fCosOuterConeAngle(cosOuterConeAngle), 791 fCosInnerConeAngle(cosInnerConeAngle), 792 fConeScale(coneScale), 793 fS(s) 794 { 795 } 796 virtual void onFlattenLight(SkWriteBuffer& buffer) const SK_OVERRIDE { 797 writePoint3(fLocation, buffer); 798 writePoint3(fTarget, buffer); 799 buffer.writeScalar(fSpecularExponent); 800 buffer.writeScalar(fCosOuterConeAngle); 801 buffer.writeScalar(fCosInnerConeAngle); 802 buffer.writeScalar(fConeScale); 803 writePoint3(fS, buffer); 804 } 805 806 virtual bool isEqual(const SkLight& other) const SK_OVERRIDE { 807 if (other.type() != kSpot_LightType) { 808 return false; 809 } 810 811 const SkSpotLight& o = static_cast<const SkSpotLight&>(other); 812 return INHERITED::isEqual(other) && 813 fLocation == o.fLocation && 814 fTarget == o.fTarget && 815 fSpecularExponent == o.fSpecularExponent && 816 fCosOuterConeAngle == o.fCosOuterConeAngle; 817 } 818 819 private: 820 static const SkScalar kSpecularExponentMin; 821 static const SkScalar kSpecularExponentMax; 822 823 typedef SkLight INHERITED; 824 SkPoint3 fLocation; 825 SkPoint3 fTarget; 826 SkScalar fSpecularExponent; 827 SkScalar fCosOuterConeAngle; 828 SkScalar fCosInnerConeAngle; 829 SkScalar fConeScale; 830 SkPoint3 fS; 831 }; 832 833 // According to the spec, the specular term should be in the range [1, 128] : 834 // http://www.w3.org/TR/SVG/filters.html#feSpecularLightingSpecularExponentAttribute 835 const SkScalar SkSpotLight::kSpecularExponentMin = 1.0f; 836 const SkScalar SkSpotLight::kSpecularExponentMax = 128.0f; 837 838 /////////////////////////////////////////////////////////////////////////////// 839 840 void SkLight::flattenLight(SkWriteBuffer& buffer) const { 841 // Write type first, then baseclass, then subclass. 842 buffer.writeInt(this->type()); 843 writePoint3(fColor, buffer); 844 this->onFlattenLight(buffer); 845 } 846 847 /*static*/ SkLight* SkLight::UnflattenLight(SkReadBuffer& buffer) { 848 // Read type first. 849 const SkLight::LightType type = (SkLight::LightType)buffer.readInt(); 850 switch (type) { 851 // Each of these constructors must first call SkLight's, so we'll read the baseclass 852 // then subclass, same order as flattenLight. 853 case SkLight::kDistant_LightType: return SkNEW_ARGS(SkDistantLight, (buffer)); 854 case SkLight::kPoint_LightType: return SkNEW_ARGS(SkPointLight, (buffer)); 855 case SkLight::kSpot_LightType: return SkNEW_ARGS(SkSpotLight, (buffer)); 856 default: 857 SkDEBUGFAIL("Unknown LightType."); 858 buffer.validate(false); 859 return NULL; 860 } 861 } 862 /////////////////////////////////////////////////////////////////////////////// 863 864 SkLightingImageFilter::SkLightingImageFilter(SkLight* light, SkScalar surfaceScale, 865 SkImageFilter* input, const CropRect* cropRect, 866 uint32_t uniqueID) 867 : INHERITED(1, &input, cropRect, uniqueID) 868 , fLight(SkRef(light)) 869 , fSurfaceScale(surfaceScale / 255) 870 {} 871 872 SkImageFilter* SkLightingImageFilter::CreateDistantLitDiffuse(const SkPoint3& direction, 873 SkColor lightColor, 874 SkScalar surfaceScale, 875 SkScalar kd, 876 SkImageFilter* input, 877 const CropRect* cropRect) { 878 SkAutoTUnref<SkLight> light(SkNEW_ARGS(SkDistantLight, (direction, lightColor))); 879 return SkDiffuseLightingImageFilter::Create(light, surfaceScale, kd, input, cropRect); 880 } 881 882 SkImageFilter* SkLightingImageFilter::CreatePointLitDiffuse(const SkPoint3& location, 883 SkColor lightColor, 884 SkScalar surfaceScale, 885 SkScalar kd, 886 SkImageFilter* input, 887 const CropRect* cropRect) { 888 SkAutoTUnref<SkLight> light(SkNEW_ARGS(SkPointLight, (location, lightColor))); 889 return SkDiffuseLightingImageFilter::Create(light, surfaceScale, kd, input, cropRect); 890 } 891 892 SkImageFilter* SkLightingImageFilter::CreateSpotLitDiffuse(const SkPoint3& location, 893 const SkPoint3& target, 894 SkScalar specularExponent, 895 SkScalar cutoffAngle, 896 SkColor lightColor, 897 SkScalar surfaceScale, 898 SkScalar kd, 899 SkImageFilter* input, 900 const CropRect* cropRect) { 901 SkAutoTUnref<SkLight> light(SkNEW_ARGS(SkSpotLight, (location, target, specularExponent, 902 cutoffAngle, lightColor))); 903 return SkDiffuseLightingImageFilter::Create(light, surfaceScale, kd, input, cropRect); 904 } 905 906 SkImageFilter* SkLightingImageFilter::CreateDistantLitSpecular(const SkPoint3& direction, 907 SkColor lightColor, 908 SkScalar surfaceScale, 909 SkScalar ks, 910 SkScalar shine, 911 SkImageFilter* input, 912 const CropRect* cropRect) { 913 SkAutoTUnref<SkLight> light(SkNEW_ARGS(SkDistantLight, (direction, lightColor))); 914 return SkSpecularLightingImageFilter::Create(light, surfaceScale, ks, shine, input, cropRect); 915 } 916 917 SkImageFilter* SkLightingImageFilter::CreatePointLitSpecular(const SkPoint3& location, 918 SkColor lightColor, 919 SkScalar surfaceScale, 920 SkScalar ks, 921 SkScalar shine, 922 SkImageFilter* input, 923 const CropRect* cropRect) { 924 SkAutoTUnref<SkLight> light(SkNEW_ARGS(SkPointLight, (location, lightColor))); 925 return SkSpecularLightingImageFilter::Create(light, surfaceScale, ks, shine, input, cropRect); 926 } 927 928 SkImageFilter* SkLightingImageFilter::CreateSpotLitSpecular(const SkPoint3& location, 929 const SkPoint3& target, 930 SkScalar specularExponent, 931 SkScalar cutoffAngle, 932 SkColor lightColor, 933 SkScalar surfaceScale, 934 SkScalar ks, 935 SkScalar shine, 936 SkImageFilter* input, 937 const CropRect* cropRect) { 938 SkAutoTUnref<SkLight> light(SkNEW_ARGS(SkSpotLight, (location, target, specularExponent, 939 cutoffAngle, lightColor))); 940 return SkSpecularLightingImageFilter::Create(light, surfaceScale, ks, shine, input, cropRect); 941 } 942 943 SkLightingImageFilter::~SkLightingImageFilter() {} 944 945 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING 946 SkLightingImageFilter::SkLightingImageFilter(SkReadBuffer& buffer) 947 : INHERITED(1, buffer) { 948 fLight.reset(SkLight::UnflattenLight(buffer)); 949 fSurfaceScale = buffer.readScalar(); 950 buffer.validate(SkScalarIsFinite(fSurfaceScale)); 951 } 952 #endif 953 954 void SkLightingImageFilter::flatten(SkWriteBuffer& buffer) const { 955 this->INHERITED::flatten(buffer); 956 fLight->flattenLight(buffer); 957 buffer.writeScalar(fSurfaceScale * 255); 958 } 959 960 /////////////////////////////////////////////////////////////////////////////// 961 962 SkImageFilter* SkDiffuseLightingImageFilter::Create(SkLight* light, SkScalar surfaceScale, 963 SkScalar kd, SkImageFilter* input, const CropRect* cropRect, uint32_t uniqueID) { 964 if (NULL == light) { 965 return NULL; 966 } 967 if (!SkScalarIsFinite(surfaceScale) || !SkScalarIsFinite(kd)) { 968 return NULL; 969 } 970 // According to the spec, kd can be any non-negative number : 971 // http://www.w3.org/TR/SVG/filters.html#feDiffuseLightingElement 972 if (kd < 0) { 973 return NULL; 974 } 975 return SkNEW_ARGS(SkDiffuseLightingImageFilter, (light, surfaceScale, kd, input, cropRect, uniqueID)); 976 } 977 978 SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar kd, SkImageFilter* input, const CropRect* cropRect, uint32_t uniqueID) 979 : SkLightingImageFilter(light, surfaceScale, input, cropRect, uniqueID), 980 fKD(kd) 981 { 982 } 983 984 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING 985 SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkReadBuffer& buffer) 986 : INHERITED(buffer) 987 { 988 fKD = buffer.readScalar(); 989 buffer.validate(SkScalarIsFinite(fKD) && (fKD >= 0)); 990 } 991 #endif 992 993 SkFlattenable* SkDiffuseLightingImageFilter::CreateProc(SkReadBuffer& buffer) { 994 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1); 995 SkAutoTUnref<SkLight> light(SkLight::UnflattenLight(buffer)); 996 SkScalar surfaceScale = buffer.readScalar(); 997 SkScalar kd = buffer.readScalar(); 998 return Create(light, surfaceScale, kd, common.getInput(0), &common.cropRect(), common.uniqueID()); 999 } 1000 1001 void SkDiffuseLightingImageFilter::flatten(SkWriteBuffer& buffer) const { 1002 this->INHERITED::flatten(buffer); 1003 buffer.writeScalar(fKD); 1004 } 1005 1006 bool SkDiffuseLightingImageFilter::onFilterImage(Proxy* proxy, 1007 const SkBitmap& source, 1008 const Context& ctx, 1009 SkBitmap* dst, 1010 SkIPoint* offset) const { 1011 SkImageFilter* input = getInput(0); 1012 SkBitmap src = source; 1013 SkIPoint srcOffset = SkIPoint::Make(0, 0); 1014 if (input && !input->filterImage(proxy, source, ctx, &src, &srcOffset)) { 1015 return false; 1016 } 1017 1018 if (src.colorType() != kN32_SkColorType) { 1019 return false; 1020 } 1021 SkIRect bounds; 1022 if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) { 1023 return false; 1024 } 1025 1026 if (bounds.width() < 2 || bounds.height() < 2) { 1027 return false; 1028 } 1029 1030 SkAutoLockPixels alp(src); 1031 if (!src.getPixels()) { 1032 return false; 1033 } 1034 1035 if (!dst->tryAllocPixels(src.info().makeWH(bounds.width(), bounds.height()))) { 1036 return false; 1037 } 1038 1039 SkAutoTUnref<SkLight> transformedLight(light()->transform(ctx.ctm())); 1040 1041 DiffuseLightingType lightingType(fKD); 1042 offset->fX = bounds.left(); 1043 offset->fY = bounds.top(); 1044 bounds.offset(-srcOffset); 1045 switch (transformedLight->type()) { 1046 case SkLight::kDistant_LightType: 1047 lightBitmap<DiffuseLightingType, SkDistantLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds); 1048 break; 1049 case SkLight::kPoint_LightType: 1050 lightBitmap<DiffuseLightingType, SkPointLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds); 1051 break; 1052 case SkLight::kSpot_LightType: 1053 lightBitmap<DiffuseLightingType, SkSpotLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds); 1054 break; 1055 } 1056 1057 return true; 1058 } 1059 1060 #if SK_SUPPORT_GPU 1061 bool SkDiffuseLightingImageFilter::asFragmentProcessor(GrFragmentProcessor** fp, 1062 GrTexture* texture, 1063 const SkMatrix& matrix, 1064 const SkIRect&) const { 1065 if (fp) { 1066 SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255)); 1067 *fp = GrDiffuseLightingEffect::Create(texture, light(), scale, matrix, kd()); 1068 } 1069 return true; 1070 } 1071 #endif 1072 1073 /////////////////////////////////////////////////////////////////////////////// 1074 1075 SkImageFilter* SkSpecularLightingImageFilter::Create(SkLight* light, SkScalar surfaceScale, 1076 SkScalar ks, SkScalar shininess, SkImageFilter* input, const CropRect* cropRect, uint32_t uniqueID) { 1077 if (NULL == light) { 1078 return NULL; 1079 } 1080 if (!SkScalarIsFinite(surfaceScale) || !SkScalarIsFinite(ks) || !SkScalarIsFinite(shininess)) { 1081 return NULL; 1082 } 1083 // According to the spec, ks can be any non-negative number : 1084 // http://www.w3.org/TR/SVG/filters.html#feSpecularLightingElement 1085 if (ks < 0) { 1086 return NULL; 1087 } 1088 return SkNEW_ARGS(SkSpecularLightingImageFilter, 1089 (light, surfaceScale, ks, shininess, input, cropRect, uniqueID)); 1090 } 1091 1092 SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess, SkImageFilter* input, const CropRect* cropRect, uint32_t uniqueID) 1093 : SkLightingImageFilter(light, surfaceScale, input, cropRect, uniqueID), 1094 fKS(ks), 1095 fShininess(shininess) 1096 { 1097 } 1098 1099 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING 1100 SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkReadBuffer& buffer) 1101 : INHERITED(buffer) 1102 { 1103 fKS = buffer.readScalar(); 1104 fShininess = buffer.readScalar(); 1105 buffer.validate(SkScalarIsFinite(fKS) && (fKS >= 0) && 1106 SkScalarIsFinite(fShininess)); 1107 } 1108 #endif 1109 1110 SkFlattenable* SkSpecularLightingImageFilter::CreateProc(SkReadBuffer& buffer) { 1111 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1); 1112 SkAutoTUnref<SkLight> light(SkLight::UnflattenLight(buffer)); 1113 SkScalar surfaceScale = buffer.readScalar(); 1114 SkScalar ks = buffer.readScalar(); 1115 SkScalar shine = buffer.readScalar(); 1116 return Create(light, surfaceScale, ks, shine, common.getInput(0), &common.cropRect(), common.uniqueID()); 1117 } 1118 1119 void SkSpecularLightingImageFilter::flatten(SkWriteBuffer& buffer) const { 1120 this->INHERITED::flatten(buffer); 1121 buffer.writeScalar(fKS); 1122 buffer.writeScalar(fShininess); 1123 } 1124 1125 bool SkSpecularLightingImageFilter::onFilterImage(Proxy* proxy, 1126 const SkBitmap& source, 1127 const Context& ctx, 1128 SkBitmap* dst, 1129 SkIPoint* offset) const { 1130 SkImageFilter* input = getInput(0); 1131 SkBitmap src = source; 1132 SkIPoint srcOffset = SkIPoint::Make(0, 0); 1133 if (input && !input->filterImage(proxy, source, ctx, &src, &srcOffset)) { 1134 return false; 1135 } 1136 1137 if (src.colorType() != kN32_SkColorType) { 1138 return false; 1139 } 1140 1141 SkIRect bounds; 1142 if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) { 1143 return false; 1144 } 1145 1146 if (bounds.width() < 2 || bounds.height() < 2) { 1147 return false; 1148 } 1149 1150 SkAutoLockPixels alp(src); 1151 if (!src.getPixels()) { 1152 return false; 1153 } 1154 1155 if (!dst->tryAllocPixels(src.info().makeWH(bounds.width(), bounds.height()))) { 1156 return false; 1157 } 1158 1159 SpecularLightingType lightingType(fKS, fShininess); 1160 offset->fX = bounds.left(); 1161 offset->fY = bounds.top(); 1162 bounds.offset(-srcOffset); 1163 SkAutoTUnref<SkLight> transformedLight(light()->transform(ctx.ctm())); 1164 switch (transformedLight->type()) { 1165 case SkLight::kDistant_LightType: 1166 lightBitmap<SpecularLightingType, SkDistantLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds); 1167 break; 1168 case SkLight::kPoint_LightType: 1169 lightBitmap<SpecularLightingType, SkPointLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds); 1170 break; 1171 case SkLight::kSpot_LightType: 1172 lightBitmap<SpecularLightingType, SkSpotLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds); 1173 break; 1174 } 1175 return true; 1176 } 1177 1178 #if SK_SUPPORT_GPU 1179 bool SkSpecularLightingImageFilter::asFragmentProcessor(GrFragmentProcessor** fp, 1180 GrTexture* texture, 1181 const SkMatrix& matrix, 1182 const SkIRect&) const { 1183 if (fp) { 1184 SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255)); 1185 *fp = GrSpecularLightingEffect::Create(texture, light(), scale, matrix, ks(), shininess()); 1186 } 1187 return true; 1188 } 1189 #endif 1190 1191 /////////////////////////////////////////////////////////////////////////////// 1192 1193 #if SK_SUPPORT_GPU 1194 1195 namespace { 1196 SkPoint3 random_point3(SkRandom* random) { 1197 return SkPoint3(SkScalarToFloat(random->nextSScalar1()), 1198 SkScalarToFloat(random->nextSScalar1()), 1199 SkScalarToFloat(random->nextSScalar1())); 1200 } 1201 1202 SkLight* create_random_light(SkRandom* random) { 1203 int type = random->nextULessThan(3); 1204 switch (type) { 1205 case 0: { 1206 return SkNEW_ARGS(SkDistantLight, (random_point3(random), random->nextU())); 1207 } 1208 case 1: { 1209 return SkNEW_ARGS(SkPointLight, (random_point3(random), random->nextU())); 1210 } 1211 case 2: { 1212 return SkNEW_ARGS(SkSpotLight, (random_point3(random), 1213 random_point3(random), 1214 random->nextUScalar1(), 1215 random->nextUScalar1(), 1216 random->nextU())); 1217 } 1218 default: 1219 SkFAIL("Unexpected value."); 1220 return NULL; 1221 } 1222 } 1223 1224 } 1225 1226 class GrGLLightingEffect : public GrGLFragmentProcessor { 1227 public: 1228 GrGLLightingEffect(const GrBackendProcessorFactory&, const GrProcessor&); 1229 virtual ~GrGLLightingEffect(); 1230 1231 virtual void emitCode(GrGLProgramBuilder*, 1232 const GrFragmentProcessor&, 1233 const GrProcessorKey&, 1234 const char* outputColor, 1235 const char* inputColor, 1236 const TransformedCoordsArray&, 1237 const TextureSamplerArray&) SK_OVERRIDE; 1238 1239 static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder* b); 1240 1241 /** 1242 * Subclasses of GrGLLightingEffect must call INHERITED::setData(); 1243 */ 1244 virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE; 1245 1246 protected: 1247 virtual void emitLightFunc(GrGLProgramBuilder*, SkString* funcName) = 0; 1248 1249 private: 1250 typedef GrGLFragmentProcessor INHERITED; 1251 1252 UniformHandle fImageIncrementUni; 1253 UniformHandle fSurfaceScaleUni; 1254 GrGLLight* fLight; 1255 }; 1256 1257 /////////////////////////////////////////////////////////////////////////////// 1258 1259 class GrGLDiffuseLightingEffect : public GrGLLightingEffect { 1260 public: 1261 GrGLDiffuseLightingEffect(const GrBackendProcessorFactory&, const GrProcessor&); 1262 virtual void emitLightFunc(GrGLProgramBuilder*, SkString* funcName) SK_OVERRIDE; 1263 virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE; 1264 1265 private: 1266 typedef GrGLLightingEffect INHERITED; 1267 1268 UniformHandle fKDUni; 1269 }; 1270 1271 /////////////////////////////////////////////////////////////////////////////// 1272 1273 class GrGLSpecularLightingEffect : public GrGLLightingEffect { 1274 public: 1275 GrGLSpecularLightingEffect(const GrBackendProcessorFactory&, const GrProcessor&); 1276 virtual void emitLightFunc(GrGLProgramBuilder*, SkString* funcName) SK_OVERRIDE; 1277 virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE; 1278 1279 private: 1280 typedef GrGLLightingEffect INHERITED; 1281 1282 UniformHandle fKSUni; 1283 UniformHandle fShininessUni; 1284 }; 1285 1286 /////////////////////////////////////////////////////////////////////////////// 1287 1288 GrLightingEffect::GrLightingEffect(GrTexture* texture, 1289 const SkLight* light, 1290 SkScalar surfaceScale, 1291 const SkMatrix& matrix) 1292 : INHERITED(texture, GrCoordTransform::MakeDivByTextureWHMatrix(texture)) 1293 , fLight(light) 1294 , fSurfaceScale(surfaceScale) 1295 , fFilterMatrix(matrix) { 1296 fLight->ref(); 1297 if (light->requiresFragmentPosition()) { 1298 this->setWillReadFragmentPosition(); 1299 } 1300 } 1301 1302 GrLightingEffect::~GrLightingEffect() { 1303 fLight->unref(); 1304 } 1305 1306 bool GrLightingEffect::onIsEqual(const GrProcessor& sBase) const { 1307 const GrLightingEffect& s = sBase.cast<GrLightingEffect>(); 1308 return this->texture(0) == s.texture(0) && 1309 fLight->isEqual(*s.fLight) && 1310 fSurfaceScale == s.fSurfaceScale; 1311 } 1312 1313 /////////////////////////////////////////////////////////////////////////////// 1314 1315 GrDiffuseLightingEffect::GrDiffuseLightingEffect(GrTexture* texture, 1316 const SkLight* light, 1317 SkScalar surfaceScale, 1318 const SkMatrix& matrix, 1319 SkScalar kd) 1320 : INHERITED(texture, light, surfaceScale, matrix), fKD(kd) { 1321 } 1322 1323 const GrBackendFragmentProcessorFactory& GrDiffuseLightingEffect::getFactory() const { 1324 return GrTBackendFragmentProcessorFactory<GrDiffuseLightingEffect>::getInstance(); 1325 } 1326 1327 bool GrDiffuseLightingEffect::onIsEqual(const GrProcessor& sBase) const { 1328 const GrDiffuseLightingEffect& s = sBase.cast<GrDiffuseLightingEffect>(); 1329 return INHERITED::onIsEqual(sBase) && 1330 this->kd() == s.kd(); 1331 } 1332 1333 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDiffuseLightingEffect); 1334 1335 GrFragmentProcessor* GrDiffuseLightingEffect::TestCreate(SkRandom* random, 1336 GrContext* context, 1337 const GrDrawTargetCaps&, 1338 GrTexture* textures[]) { 1339 SkScalar surfaceScale = random->nextSScalar1(); 1340 SkScalar kd = random->nextUScalar1(); 1341 SkAutoTUnref<SkLight> light(create_random_light(random)); 1342 SkMatrix matrix; 1343 for (int i = 0; i < 9; i++) { 1344 matrix[i] = random->nextUScalar1(); 1345 } 1346 return GrDiffuseLightingEffect::Create(textures[GrProcessorUnitTest::kAlphaTextureIdx], 1347 light, surfaceScale, matrix, kd); 1348 } 1349 1350 1351 /////////////////////////////////////////////////////////////////////////////// 1352 1353 GrGLLightingEffect::GrGLLightingEffect(const GrBackendProcessorFactory& factory, 1354 const GrProcessor& fp) 1355 : INHERITED(factory) { 1356 const GrLightingEffect& m = fp.cast<GrLightingEffect>(); 1357 fLight = m.light()->createGLLight(); 1358 } 1359 1360 GrGLLightingEffect::~GrGLLightingEffect() { 1361 delete fLight; 1362 } 1363 1364 void GrGLLightingEffect::emitCode(GrGLProgramBuilder* builder, 1365 const GrFragmentProcessor&, 1366 const GrProcessorKey& key, 1367 const char* outputColor, 1368 const char* inputColor, 1369 const TransformedCoordsArray& coords, 1370 const TextureSamplerArray& samplers) { 1371 fImageIncrementUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, 1372 kVec2f_GrSLType, 1373 "ImageIncrement"); 1374 fSurfaceScaleUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, 1375 kFloat_GrSLType, 1376 "SurfaceScale"); 1377 fLight->emitLightColorUniform(builder); 1378 SkString lightFunc; 1379 this->emitLightFunc(builder, &lightFunc); 1380 static const GrGLShaderVar gSobelArgs[] = { 1381 GrGLShaderVar("a", kFloat_GrSLType), 1382 GrGLShaderVar("b", kFloat_GrSLType), 1383 GrGLShaderVar("c", kFloat_GrSLType), 1384 GrGLShaderVar("d", kFloat_GrSLType), 1385 GrGLShaderVar("e", kFloat_GrSLType), 1386 GrGLShaderVar("f", kFloat_GrSLType), 1387 GrGLShaderVar("scale", kFloat_GrSLType), 1388 }; 1389 SkString sobelFuncName; 1390 GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); 1391 SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0); 1392 1393 fsBuilder->emitFunction(kFloat_GrSLType, 1394 "sobel", 1395 SK_ARRAY_COUNT(gSobelArgs), 1396 gSobelArgs, 1397 "\treturn (-a + b - 2.0 * c + 2.0 * d -e + f) * scale;\n", 1398 &sobelFuncName); 1399 static const GrGLShaderVar gPointToNormalArgs[] = { 1400 GrGLShaderVar("x", kFloat_GrSLType), 1401 GrGLShaderVar("y", kFloat_GrSLType), 1402 GrGLShaderVar("scale", kFloat_GrSLType), 1403 }; 1404 SkString pointToNormalName; 1405 fsBuilder->emitFunction(kVec3f_GrSLType, 1406 "pointToNormal", 1407 SK_ARRAY_COUNT(gPointToNormalArgs), 1408 gPointToNormalArgs, 1409 "\treturn normalize(vec3(-x * scale, y * scale, 1));\n", 1410 &pointToNormalName); 1411 1412 static const GrGLShaderVar gInteriorNormalArgs[] = { 1413 GrGLShaderVar("m", kFloat_GrSLType, 9), 1414 GrGLShaderVar("surfaceScale", kFloat_GrSLType), 1415 }; 1416 SkString interiorNormalBody; 1417 interiorNormalBody.appendf("\treturn %s(%s(m[0], m[2], m[3], m[5], m[6], m[8], 0.25),\n" 1418 "\t %s(m[0], m[6], m[1], m[7], m[2], m[8], 0.25),\n" 1419 "\t surfaceScale);\n", 1420 pointToNormalName.c_str(), 1421 sobelFuncName.c_str(), 1422 sobelFuncName.c_str()); 1423 SkString interiorNormalName; 1424 fsBuilder->emitFunction(kVec3f_GrSLType, 1425 "interiorNormal", 1426 SK_ARRAY_COUNT(gInteriorNormalArgs), 1427 gInteriorNormalArgs, 1428 interiorNormalBody.c_str(), 1429 &interiorNormalName); 1430 1431 fsBuilder->codeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str()); 1432 fsBuilder->codeAppend("\t\tfloat m[9];\n"); 1433 1434 const char* imgInc = builder->getUniformCStr(fImageIncrementUni); 1435 const char* surfScale = builder->getUniformCStr(fSurfaceScaleUni); 1436 1437 int index = 0; 1438 for (int dy = -1; dy <= 1; dy++) { 1439 for (int dx = -1; dx <= 1; dx++) { 1440 SkString texCoords; 1441 texCoords.appendf("coord + vec2(%d, %d) * %s", dx, dy, imgInc); 1442 fsBuilder->codeAppendf("\t\tm[%d] = ", index++); 1443 fsBuilder->appendTextureLookup(samplers[0], texCoords.c_str()); 1444 fsBuilder->codeAppend(".a;\n"); 1445 } 1446 } 1447 fsBuilder->codeAppend("\t\tvec3 surfaceToLight = "); 1448 SkString arg; 1449 arg.appendf("%s * m[4]", surfScale); 1450 fLight->emitSurfaceToLight(builder, arg.c_str()); 1451 fsBuilder->codeAppend(";\n"); 1452 fsBuilder->codeAppendf("\t\t%s = %s(%s(m, %s), surfaceToLight, ", 1453 outputColor, lightFunc.c_str(), interiorNormalName.c_str(), surfScale); 1454 fLight->emitLightColor(builder, "surfaceToLight"); 1455 fsBuilder->codeAppend(");\n"); 1456 SkString modulate; 1457 GrGLSLMulVarBy4f(&modulate, 2, outputColor, inputColor); 1458 fsBuilder->codeAppend(modulate.c_str()); 1459 } 1460 1461 void GrGLLightingEffect::GenKey(const GrProcessor& proc, 1462 const GrGLCaps& caps, GrProcessorKeyBuilder* b) { 1463 b->add32(proc.cast<GrLightingEffect>().light()->type()); 1464 } 1465 1466 void GrGLLightingEffect::setData(const GrGLProgramDataManager& pdman, 1467 const GrProcessor& proc) { 1468 const GrLightingEffect& lighting = proc.cast<GrLightingEffect>(); 1469 GrTexture* texture = lighting.texture(0); 1470 float ySign = texture->origin() == kTopLeft_GrSurfaceOrigin ? -1.0f : 1.0f; 1471 pdman.set2f(fImageIncrementUni, 1.0f / texture->width(), ySign / texture->height()); 1472 pdman.set1f(fSurfaceScaleUni, lighting.surfaceScale()); 1473 SkAutoTUnref<SkLight> transformedLight(lighting.light()->transform(lighting.filterMatrix())); 1474 fLight->setData(pdman, transformedLight); 1475 } 1476 1477 /////////////////////////////////////////////////////////////////////////////// 1478 1479 /////////////////////////////////////////////////////////////////////////////// 1480 1481 GrGLDiffuseLightingEffect::GrGLDiffuseLightingEffect(const GrBackendProcessorFactory& factory, 1482 const GrProcessor& proc) 1483 : INHERITED(factory, proc) { 1484 } 1485 1486 void GrGLDiffuseLightingEffect::emitLightFunc(GrGLProgramBuilder* builder, SkString* funcName) { 1487 const char* kd; 1488 fKDUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, 1489 kFloat_GrSLType, 1490 "KD", 1491 &kd); 1492 1493 static const GrGLShaderVar gLightArgs[] = { 1494 GrGLShaderVar("normal", kVec3f_GrSLType), 1495 GrGLShaderVar("surfaceToLight", kVec3f_GrSLType), 1496 GrGLShaderVar("lightColor", kVec3f_GrSLType) 1497 }; 1498 SkString lightBody; 1499 lightBody.appendf("\tfloat colorScale = %s * dot(normal, surfaceToLight);\n", kd); 1500 lightBody.appendf("\treturn vec4(lightColor * clamp(colorScale, 0.0, 1.0), 1.0);\n"); 1501 builder->getFragmentShaderBuilder()->emitFunction(kVec4f_GrSLType, 1502 "light", 1503 SK_ARRAY_COUNT(gLightArgs), 1504 gLightArgs, 1505 lightBody.c_str(), 1506 funcName); 1507 } 1508 1509 void GrGLDiffuseLightingEffect::setData(const GrGLProgramDataManager& pdman, 1510 const GrProcessor& proc) { 1511 INHERITED::setData(pdman, proc); 1512 const GrDiffuseLightingEffect& diffuse = proc.cast<GrDiffuseLightingEffect>(); 1513 pdman.set1f(fKDUni, diffuse.kd()); 1514 } 1515 1516 /////////////////////////////////////////////////////////////////////////////// 1517 1518 GrSpecularLightingEffect::GrSpecularLightingEffect(GrTexture* texture, 1519 const SkLight* light, 1520 SkScalar surfaceScale, 1521 const SkMatrix& matrix, 1522 SkScalar ks, 1523 SkScalar shininess) 1524 : INHERITED(texture, light, surfaceScale, matrix), 1525 fKS(ks), 1526 fShininess(shininess) { 1527 } 1528 1529 const GrBackendFragmentProcessorFactory& GrSpecularLightingEffect::getFactory() const { 1530 return GrTBackendFragmentProcessorFactory<GrSpecularLightingEffect>::getInstance(); 1531 } 1532 1533 bool GrSpecularLightingEffect::onIsEqual(const GrProcessor& sBase) const { 1534 const GrSpecularLightingEffect& s = sBase.cast<GrSpecularLightingEffect>(); 1535 return INHERITED::onIsEqual(sBase) && 1536 this->ks() == s.ks() && 1537 this->shininess() == s.shininess(); 1538 } 1539 1540 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrSpecularLightingEffect); 1541 1542 GrFragmentProcessor* GrSpecularLightingEffect::TestCreate(SkRandom* random, 1543 GrContext* context, 1544 const GrDrawTargetCaps&, 1545 GrTexture* textures[]) { 1546 SkScalar surfaceScale = random->nextSScalar1(); 1547 SkScalar ks = random->nextUScalar1(); 1548 SkScalar shininess = random->nextUScalar1(); 1549 SkAutoTUnref<SkLight> light(create_random_light(random)); 1550 SkMatrix matrix; 1551 for (int i = 0; i < 9; i++) { 1552 matrix[i] = random->nextUScalar1(); 1553 } 1554 return GrSpecularLightingEffect::Create(textures[GrProcessorUnitTest::kAlphaTextureIdx], 1555 light, surfaceScale, matrix, ks, shininess); 1556 } 1557 1558 /////////////////////////////////////////////////////////////////////////////// 1559 1560 GrGLSpecularLightingEffect::GrGLSpecularLightingEffect(const GrBackendProcessorFactory& factory, 1561 const GrProcessor& proc) 1562 : INHERITED(factory, proc) { 1563 } 1564 1565 void GrGLSpecularLightingEffect::emitLightFunc(GrGLProgramBuilder* builder, SkString* funcName) { 1566 const char* ks; 1567 const char* shininess; 1568 1569 fKSUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, 1570 kFloat_GrSLType, "KS", &ks); 1571 fShininessUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, 1572 kFloat_GrSLType, "Shininess", &shininess); 1573 1574 static const GrGLShaderVar gLightArgs[] = { 1575 GrGLShaderVar("normal", kVec3f_GrSLType), 1576 GrGLShaderVar("surfaceToLight", kVec3f_GrSLType), 1577 GrGLShaderVar("lightColor", kVec3f_GrSLType) 1578 }; 1579 SkString lightBody; 1580 lightBody.appendf("\tvec3 halfDir = vec3(normalize(surfaceToLight + vec3(0, 0, 1)));\n"); 1581 lightBody.appendf("\tfloat colorScale = %s * pow(dot(normal, halfDir), %s);\n", ks, shininess); 1582 lightBody.appendf("\tvec3 color = lightColor * clamp(colorScale, 0.0, 1.0);\n"); 1583 lightBody.appendf("\treturn vec4(color, max(max(color.r, color.g), color.b));\n"); 1584 builder->getFragmentShaderBuilder()->emitFunction(kVec4f_GrSLType, 1585 "light", 1586 SK_ARRAY_COUNT(gLightArgs), 1587 gLightArgs, 1588 lightBody.c_str(), 1589 funcName); 1590 } 1591 1592 void GrGLSpecularLightingEffect::setData(const GrGLProgramDataManager& pdman, 1593 const GrProcessor& effect) { 1594 INHERITED::setData(pdman, effect); 1595 const GrSpecularLightingEffect& spec = effect.cast<GrSpecularLightingEffect>(); 1596 pdman.set1f(fKSUni, spec.ks()); 1597 pdman.set1f(fShininessUni, spec.shininess()); 1598 } 1599 1600 /////////////////////////////////////////////////////////////////////////////// 1601 void GrGLLight::emitLightColorUniform(GrGLProgramBuilder* builder) { 1602 fColorUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, 1603 kVec3f_GrSLType, "LightColor"); 1604 } 1605 1606 void GrGLLight::emitLightColor(GrGLProgramBuilder* builder, 1607 const char *surfaceToLight) { 1608 builder->getFragmentShaderBuilder()->codeAppend(builder->getUniformCStr(this->lightColorUni())); 1609 } 1610 1611 void GrGLLight::setData(const GrGLProgramDataManager& pdman, 1612 const SkLight* light) const { 1613 setUniformPoint3(pdman, fColorUni, light->color() * SkScalarInvert(SkIntToScalar(255))); 1614 } 1615 1616 /////////////////////////////////////////////////////////////////////////////// 1617 1618 void GrGLDistantLight::setData(const GrGLProgramDataManager& pdman, 1619 const SkLight* light) const { 1620 INHERITED::setData(pdman, light); 1621 SkASSERT(light->type() == SkLight::kDistant_LightType); 1622 const SkDistantLight* distantLight = static_cast<const SkDistantLight*>(light); 1623 setUniformNormal3(pdman, fDirectionUni, distantLight->direction()); 1624 } 1625 1626 void GrGLDistantLight::emitSurfaceToLight(GrGLProgramBuilder* builder, const char* z) { 1627 const char* dir; 1628 fDirectionUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec3f_GrSLType, 1629 "LightDirection", &dir); 1630 builder->getFragmentShaderBuilder()->codeAppend(dir); 1631 } 1632 1633 /////////////////////////////////////////////////////////////////////////////// 1634 1635 void GrGLPointLight::setData(const GrGLProgramDataManager& pdman, 1636 const SkLight* light) const { 1637 INHERITED::setData(pdman, light); 1638 SkASSERT(light->type() == SkLight::kPoint_LightType); 1639 const SkPointLight* pointLight = static_cast<const SkPointLight*>(light); 1640 setUniformPoint3(pdman, fLocationUni, pointLight->location()); 1641 } 1642 1643 void GrGLPointLight::emitSurfaceToLight(GrGLProgramBuilder* builder, const char* z) { 1644 const char* loc; 1645 fLocationUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec3f_GrSLType, 1646 "LightLocation", &loc); 1647 GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); 1648 fsBuilder->codeAppendf("normalize(%s - vec3(%s.xy, %s))", 1649 loc, fsBuilder->fragmentPosition(), z); 1650 } 1651 1652 /////////////////////////////////////////////////////////////////////////////// 1653 1654 void GrGLSpotLight::setData(const GrGLProgramDataManager& pdman, 1655 const SkLight* light) const { 1656 INHERITED::setData(pdman, light); 1657 SkASSERT(light->type() == SkLight::kSpot_LightType); 1658 const SkSpotLight* spotLight = static_cast<const SkSpotLight *>(light); 1659 setUniformPoint3(pdman, fLocationUni, spotLight->location()); 1660 pdman.set1f(fExponentUni, spotLight->specularExponent()); 1661 pdman.set1f(fCosInnerConeAngleUni, spotLight->cosInnerConeAngle()); 1662 pdman.set1f(fCosOuterConeAngleUni, spotLight->cosOuterConeAngle()); 1663 pdman.set1f(fConeScaleUni, spotLight->coneScale()); 1664 setUniformNormal3(pdman, fSUni, spotLight->s()); 1665 } 1666 1667 void GrGLSpotLight::emitSurfaceToLight(GrGLProgramBuilder* builder, const char* z) { 1668 const char* location; 1669 fLocationUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, 1670 kVec3f_GrSLType, "LightLocation", &location); 1671 1672 GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); 1673 fsBuilder->codeAppendf("normalize(%s - vec3(%s.xy, %s))", 1674 location, fsBuilder->fragmentPosition(), z); 1675 } 1676 1677 void GrGLSpotLight::emitLightColor(GrGLProgramBuilder* builder, 1678 const char *surfaceToLight) { 1679 1680 const char* color = builder->getUniformCStr(this->lightColorUni()); // created by parent class. 1681 1682 const char* exponent; 1683 const char* cosInner; 1684 const char* cosOuter; 1685 const char* coneScale; 1686 const char* s; 1687 fExponentUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, 1688 kFloat_GrSLType, "Exponent", &exponent); 1689 fCosInnerConeAngleUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, 1690 kFloat_GrSLType, "CosInnerConeAngle", &cosInner); 1691 fCosOuterConeAngleUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, 1692 kFloat_GrSLType, "CosOuterConeAngle", &cosOuter); 1693 fConeScaleUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, 1694 kFloat_GrSLType, "ConeScale", &coneScale); 1695 fSUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, 1696 kVec3f_GrSLType, "S", &s); 1697 1698 static const GrGLShaderVar gLightColorArgs[] = { 1699 GrGLShaderVar("surfaceToLight", kVec3f_GrSLType) 1700 }; 1701 SkString lightColorBody; 1702 lightColorBody.appendf("\tfloat cosAngle = -dot(surfaceToLight, %s);\n", s); 1703 lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosOuter); 1704 lightColorBody.appendf("\t\treturn vec3(0);\n"); 1705 lightColorBody.appendf("\t}\n"); 1706 lightColorBody.appendf("\tfloat scale = pow(cosAngle, %s);\n", exponent); 1707 lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosInner); 1708 lightColorBody.appendf("\t\treturn %s * scale * (cosAngle - %s) * %s;\n", 1709 color, cosOuter, coneScale); 1710 lightColorBody.appendf("\t}\n"); 1711 lightColorBody.appendf("\treturn %s;\n", color); 1712 GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); 1713 fsBuilder->emitFunction(kVec3f_GrSLType, 1714 "lightColor", 1715 SK_ARRAY_COUNT(gLightColorArgs), 1716 gLightColorArgs, 1717 lightColorBody.c_str(), 1718 &fLightColorFunc); 1719 1720 fsBuilder->codeAppendf("%s(%s)", fLightColorFunc.c_str(), surfaceToLight); 1721 } 1722 1723 #endif 1724 1725 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingImageFilter) 1726 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDiffuseLightingImageFilter) 1727 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSpecularLightingImageFilter) 1728 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 1729