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