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