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