SkLightingImageFilter.cpp revision e2022cc36e47b9f0d219eb5cd24be61772c28d3b
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 23class GrGLDiffuseLightingEffect; 24class GrGLSpecularLightingEffect; 25 26// For brevity 27typedef GrGLUniformManager::UniformHandle UniformHandle; 28static const UniformHandle kInvalidUniformHandle = GrGLUniformManager::kInvalidUniformHandle; 29#endif 30 31namespace { 32 33const SkScalar gOneThird = SkScalarInvert(SkIntToScalar(3)); 34const SkScalar gTwoThirds = SkScalarDiv(SkIntToScalar(2), SkIntToScalar(3)); 35const SkScalar gOneHalf = SkFloatToScalar(0.5f); 36const SkScalar gOneQuarter = SkFloatToScalar(0.25f); 37 38#if SK_SUPPORT_GPU 39void 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 44void 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. 50inline 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 59class DiffuseLightingType { 60public: 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 } 72private: 73 SkScalar fKD; 74}; 75 76class SpecularLightingType { 77public: 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 } 93private: 94 SkScalar fKS; 95 SkScalar fShininess; 96}; 97 98inline 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 102inline 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 110inline 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 116inline 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 122inline 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 128inline 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 135inline 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 141inline 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 147inline 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 153inline 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 159inline 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 165template <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 247SkPoint3 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 255void writePoint3(const SkPoint3& point, SkFlattenableWriteBuffer& buffer) { 256 buffer.writeScalar(point.fX); 257 buffer.writeScalar(point.fY); 258 buffer.writeScalar(point.fZ); 259}; 260 261class SkDiffuseLightingImageFilter : public SkLightingImageFilter { 262public: 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 270protected: 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 277private: 278 typedef SkLightingImageFilter INHERITED; 279 SkScalar fKD; 280}; 281 282class SkSpecularLightingImageFilter : public SkLightingImageFilter { 283public: 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 291protected: 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 297private: 298 typedef SkLightingImageFilter INHERITED; 299 SkScalar fKS; 300 SkScalar fShininess; 301}; 302 303#if SK_SUPPORT_GPU 304 305class GrLightingEffect : public GrSingleTextureEffect { 306public: 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 319protected: 320 virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE; 321 322private: 323 typedef GrSingleTextureEffect INHERITED; 324 const SkLight* fLight; 325 SkScalar fSurfaceScale; 326}; 327 328class GrDiffuseLightingEffect : public GrLightingEffect { 329public: 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 348private: 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 361class GrSpecularLightingEffect : public GrLightingEffect { 362public: 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 383private: 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 400class GrGLLight { 401public: 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*, 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 425protected: 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 432private: 433 UniformHandle fColorUni; 434 435 typedef SkRefCnt INHERITED; 436}; 437 438/////////////////////////////////////////////////////////////////////////////// 439 440class GrGLDistantLight : public GrGLLight { 441public: 442 virtual ~GrGLDistantLight() {} 443 virtual void setData(const GrGLUniformManager&, const SkLight* light) const SK_OVERRIDE; 444 virtual void emitSurfaceToLight(GrGLShaderBuilder*, const char* z) SK_OVERRIDE; 445private: 446 typedef GrGLLight INHERITED; 447 UniformHandle fDirectionUni; 448}; 449 450/////////////////////////////////////////////////////////////////////////////// 451 452class GrGLPointLight : public GrGLLight { 453public: 454 virtual ~GrGLPointLight() {} 455 virtual void setData(const GrGLUniformManager&, const SkLight* light) const SK_OVERRIDE; 456 virtual void emitSurfaceToLight(GrGLShaderBuilder*, const char* z) SK_OVERRIDE; 457private: 458 typedef GrGLLight INHERITED; 459 SkPoint3 fLocation; 460 UniformHandle fLocationUni; 461}; 462 463/////////////////////////////////////////////////////////////////////////////// 464 465class GrGLSpotLight : public GrGLLight { 466public: 467 virtual ~GrGLSpotLight() {} 468 virtual void setData(const GrGLUniformManager&, const SkLight* light) const SK_OVERRIDE; 469 virtual void emitSurfaceToLight(GrGLShaderBuilder*, const char* z) SK_OVERRIDE; 470 virtual void emitLightColor(GrGLShaderBuilder*, const char *surfaceToLight) SK_OVERRIDE; 471private: 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 484class GrGLLight; 485 486#endif 487 488}; 489 490/////////////////////////////////////////////////////////////////////////////// 491 492class SkLight : public SkFlattenable { 493public: 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 508protected: 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 522private: 523 typedef SkFlattenable INHERITED; 524 SkPoint3 fColor; 525}; 526 527SK_DEFINE_INST_COUNT(SkLight) 528 529/////////////////////////////////////////////////////////////////////////////// 530 531class SkDistantLight : public SkLight { 532public: 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 563protected: 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 572private: 573 typedef SkLight INHERITED; 574 SkPoint3 fDirection; 575}; 576 577/////////////////////////////////////////////////////////////////////////////// 578 579class SkPointLight : public SkLight { 580public: 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 613protected: 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 622private: 623 typedef SkLight INHERITED; 624 SkPoint3 fLocation; 625}; 626 627/////////////////////////////////////////////////////////////////////////////// 628 629class SkSpotLight : public SkLight { 630public: 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 683protected: 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 717private: 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 730SkLightingImageFilter::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 740SkImageFilter* 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 748SkImageFilter* 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 756SkImageFilter* 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 767SkImageFilter* 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 775SkImageFilter* 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 783SkImageFilter* 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 793SkLightingImageFilter::~SkLightingImageFilter() { 794 fLight->unref(); 795} 796 797SkLightingImageFilter::SkLightingImageFilter(SkFlattenableReadBuffer& buffer) 798 : INHERITED(buffer) 799{ 800 fLight = buffer.readFlattenableT<SkLight>(); 801 fSurfaceScale = buffer.readScalar(); 802} 803 804void SkLightingImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { 805 this->INHERITED::flatten(buffer); 806 buffer.writeFlattenable(fLight); 807 buffer.writeScalar(fSurfaceScale); 808} 809 810/////////////////////////////////////////////////////////////////////////////// 811 812SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar kd, SkImageFilter* input) 813 : SkLightingImageFilter(light, surfaceScale, input), 814 fKD(kd) 815{ 816} 817 818SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkFlattenableReadBuffer& buffer) 819 : INHERITED(buffer) 820{ 821 fKD = buffer.readScalar(); 822} 823 824void SkDiffuseLightingImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { 825 this->INHERITED::flatten(buffer); 826 buffer.writeScalar(fKD); 827} 828 829bool 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 862bool 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 878SkSpecularLightingImageFilter::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 885SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkFlattenableReadBuffer& buffer) 886 : INHERITED(buffer) 887{ 888 fKS = buffer.readScalar(); 889 fShininess = buffer.readScalar(); 890} 891 892void SkSpecularLightingImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { 893 this->INHERITED::flatten(buffer); 894 buffer.writeScalar(fKS); 895 buffer.writeScalar(fShininess); 896} 897 898bool 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 931bool 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 949namespace { 950SkPoint3 random_point3(SkMWCRandom* random) { 951 return SkPoint3(SkScalarToFloat(random->nextSScalar1()), 952 SkScalarToFloat(random->nextSScalar1()), 953 SkScalarToFloat(random->nextSScalar1())); 954} 955 956SkLight* create_random_light(SkMWCRandom* 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 980class GrGLLightingEffect : public GrGLEffect { 981public: 982 GrGLLightingEffect(const GrBackendEffectFactory& factory, 983 const GrDrawEffect& effect); 984 virtual ~GrGLLightingEffect(); 985 986 virtual void emitCode(GrGLShaderBuilder*, 987 const GrDrawEffect&, 988 EffectKey, 989 const char* outputColor, 990 const char* inputColor, 991 const TextureSamplerArray&) SK_OVERRIDE; 992 993 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); 994 995 /** 996 * Subclasses of GrGLLightingEffect must call INHERITED::setData(); 997 */ 998 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE; 999 1000protected: 1001 virtual void emitLightFunc(GrGLShaderBuilder*, SkString* funcName) = 0; 1002 1003private: 1004 typedef GrGLEffect INHERITED; 1005 1006 UniformHandle fImageIncrementUni; 1007 UniformHandle fSurfaceScaleUni; 1008 GrGLLight* fLight; 1009 GrGLEffectMatrix fEffectMatrix; 1010}; 1011 1012/////////////////////////////////////////////////////////////////////////////// 1013 1014class GrGLDiffuseLightingEffect : public GrGLLightingEffect { 1015public: 1016 GrGLDiffuseLightingEffect(const GrBackendEffectFactory& factory, 1017 const GrDrawEffect& drawEffect); 1018 virtual void emitLightFunc(GrGLShaderBuilder*, SkString* funcName) SK_OVERRIDE; 1019 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE; 1020 1021private: 1022 typedef GrGLLightingEffect INHERITED; 1023 1024 UniformHandle fKDUni; 1025}; 1026 1027/////////////////////////////////////////////////////////////////////////////// 1028 1029class GrGLSpecularLightingEffect : public GrGLLightingEffect { 1030public: 1031 GrGLSpecularLightingEffect(const GrBackendEffectFactory& factory, 1032 const GrDrawEffect& effect); 1033 virtual void emitLightFunc(GrGLShaderBuilder*, SkString* funcName) SK_OVERRIDE; 1034 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE; 1035 1036private: 1037 typedef GrGLLightingEffect INHERITED; 1038 1039 UniformHandle fKSUni; 1040 UniformHandle fShininessUni; 1041}; 1042 1043/////////////////////////////////////////////////////////////////////////////// 1044 1045GrLightingEffect::GrLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale) 1046 : INHERITED(texture, MakeDivByTextureWHMatrix(texture)) 1047 , fLight(light) 1048 , fSurfaceScale(surfaceScale) { 1049 fLight->ref(); 1050} 1051 1052GrLightingEffect::~GrLightingEffect() { 1053 fLight->unref(); 1054} 1055 1056bool GrLightingEffect::onIsEqual(const GrEffect& sBase) const { 1057 const GrLightingEffect& s = CastEffect<GrLightingEffect>(sBase); 1058 return this->texture(0) == s.texture(0) && 1059 fLight->isEqual(*s.fLight) && 1060 fSurfaceScale == s.fSurfaceScale; 1061} 1062 1063/////////////////////////////////////////////////////////////////////////////// 1064 1065GrDiffuseLightingEffect::GrDiffuseLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale, SkScalar kd) 1066 : INHERITED(texture, light, surfaceScale), fKD(kd) { 1067} 1068 1069const GrBackendEffectFactory& GrDiffuseLightingEffect::getFactory() const { 1070 return GrTBackendEffectFactory<GrDiffuseLightingEffect>::getInstance(); 1071} 1072 1073bool GrDiffuseLightingEffect::onIsEqual(const GrEffect& sBase) const { 1074 const GrDiffuseLightingEffect& s = CastEffect<GrDiffuseLightingEffect>(sBase); 1075 return INHERITED::onIsEqual(sBase) && 1076 this->kd() == s.kd(); 1077} 1078 1079GR_DEFINE_EFFECT_TEST(GrDiffuseLightingEffect); 1080 1081GrEffectRef* GrDiffuseLightingEffect::TestCreate(SkMWCRandom* random, 1082 GrContext* context, 1083 GrTexture* textures[]) { 1084 SkScalar surfaceScale = random->nextSScalar1(); 1085 SkScalar kd = random->nextUScalar1(); 1086 SkAutoTUnref<SkLight> light(create_random_light(random)); 1087 return GrDiffuseLightingEffect::Create(textures[GrEffectUnitTest::kAlphaTextureIdx], 1088 light, surfaceScale, kd); 1089} 1090 1091 1092/////////////////////////////////////////////////////////////////////////////// 1093 1094GrGLLightingEffect::GrGLLightingEffect(const GrBackendEffectFactory& factory, 1095 const GrDrawEffect& drawEffect) 1096 : INHERITED(factory) 1097 , fImageIncrementUni(kInvalidUniformHandle) 1098 , fSurfaceScaleUni(kInvalidUniformHandle) 1099 , fEffectMatrix(drawEffect.castEffect<GrLightingEffect>().coordsType()) { 1100 const GrLightingEffect& m = drawEffect.castEffect<GrLightingEffect>(); 1101 fLight = m.light()->createGLLight(); 1102} 1103 1104GrGLLightingEffect::~GrGLLightingEffect() { 1105 delete fLight; 1106} 1107 1108void GrGLLightingEffect::emitCode(GrGLShaderBuilder* builder, 1109 const GrDrawEffect&, 1110 EffectKey key, 1111 const char* outputColor, 1112 const char* inputColor, 1113 const TextureSamplerArray& samplers) { 1114 const char* coords; 1115 fEffectMatrix.emitCodeMakeFSCoords2D(builder, key, &coords); 1116 1117 fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, 1118 kVec2f_GrSLType, 1119 "ImageIncrement"); 1120 fSurfaceScaleUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, 1121 kFloat_GrSLType, 1122 "SurfaceScale"); 1123 fLight->emitLightColorUniform(builder); 1124 SkString lightFunc; 1125 this->emitLightFunc(builder, &lightFunc); 1126 static const GrGLShaderVar gSobelArgs[] = { 1127 GrGLShaderVar("a", kFloat_GrSLType), 1128 GrGLShaderVar("b", kFloat_GrSLType), 1129 GrGLShaderVar("c", kFloat_GrSLType), 1130 GrGLShaderVar("d", kFloat_GrSLType), 1131 GrGLShaderVar("e", kFloat_GrSLType), 1132 GrGLShaderVar("f", kFloat_GrSLType), 1133 GrGLShaderVar("scale", kFloat_GrSLType), 1134 }; 1135 SkString sobelFuncName; 1136 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType, 1137 kFloat_GrSLType, 1138 "sobel", 1139 SK_ARRAY_COUNT(gSobelArgs), 1140 gSobelArgs, 1141 "\treturn (-a + b - 2.0 * c + 2.0 * d -e + f) * scale;\n", 1142 &sobelFuncName); 1143 static const GrGLShaderVar gPointToNormalArgs[] = { 1144 GrGLShaderVar("x", kFloat_GrSLType), 1145 GrGLShaderVar("y", kFloat_GrSLType), 1146 GrGLShaderVar("scale", kFloat_GrSLType), 1147 }; 1148 SkString pointToNormalName; 1149 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType, 1150 kVec3f_GrSLType, 1151 "pointToNormal", 1152 SK_ARRAY_COUNT(gPointToNormalArgs), 1153 gPointToNormalArgs, 1154 "\treturn normalize(vec3(-x * scale, y * scale, 1));\n", 1155 &pointToNormalName); 1156 1157 static const GrGLShaderVar gInteriorNormalArgs[] = { 1158 GrGLShaderVar("m", kFloat_GrSLType, 9), 1159 GrGLShaderVar("surfaceScale", kFloat_GrSLType), 1160 }; 1161 SkString interiorNormalBody; 1162 interiorNormalBody.appendf("\treturn %s(%s(m[0], m[2], m[3], m[5], m[6], m[8], 0.25),\n" 1163 "\t %s(m[0], m[6], m[1], m[7], m[2], m[8], 0.25),\n" 1164 "\t surfaceScale);\n", 1165 pointToNormalName.c_str(), 1166 sobelFuncName.c_str(), 1167 sobelFuncName.c_str()); 1168 SkString interiorNormalName; 1169 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType, 1170 kVec3f_GrSLType, 1171 "interiorNormal", 1172 SK_ARRAY_COUNT(gInteriorNormalArgs), 1173 gInteriorNormalArgs, 1174 interiorNormalBody.c_str(), 1175 &interiorNormalName); 1176 1177 builder->fsCodeAppendf("\t\tvec2 coord = %s;\n", coords); 1178 builder->fsCodeAppend("\t\tfloat m[9];\n"); 1179 1180 const char* imgInc = builder->getUniformCStr(fImageIncrementUni); 1181 const char* surfScale = builder->getUniformCStr(fSurfaceScaleUni); 1182 1183 int index = 0; 1184 for (int dy = -1; dy <= 1; dy++) { 1185 for (int dx = -1; dx <= 1; dx++) { 1186 SkString texCoords; 1187 texCoords.appendf("coord + vec2(%d, %d) * %s", dx, dy, imgInc); 1188 builder->fsCodeAppendf("\t\tm[%d] = ", index++); 1189 builder->appendTextureLookup(GrGLShaderBuilder::kFragment_ShaderType, 1190 samplers[0], 1191 texCoords.c_str()); 1192 builder->fsCodeAppend(".a;\n"); 1193 } 1194 } 1195 builder->fsCodeAppend("\t\tvec3 surfaceToLight = "); 1196 SkString arg; 1197 arg.appendf("%s * m[4]", surfScale); 1198 fLight->emitSurfaceToLight(builder, arg.c_str()); 1199 builder->fsCodeAppend(";\n"); 1200 builder->fsCodeAppendf("\t\t%s = %s(%s(m, %s), surfaceToLight, ", 1201 outputColor, lightFunc.c_str(), interiorNormalName.c_str(), surfScale); 1202 fLight->emitLightColor(builder, "surfaceToLight"); 1203 builder->fsCodeAppend(");\n"); 1204 SkString modulate; 1205 GrGLSLMulVarBy4f(&modulate, 2, outputColor, inputColor); 1206 builder->fsCodeAppend(modulate.c_str()); 1207} 1208 1209GrGLEffect::EffectKey GrGLLightingEffect::GenKey(const GrDrawEffect& drawEffect, 1210 const GrGLCaps& caps) { 1211 const GrLightingEffect& lighting = drawEffect.castEffect<GrLightingEffect>(); 1212 EffectKey key = lighting.light()->type(); 1213 key <<= GrGLEffectMatrix::kKeyBits; 1214 EffectKey matrixKey = GrGLEffectMatrix::GenKey(lighting.getMatrix(), 1215 drawEffect, 1216 lighting.coordsType(), 1217 lighting.texture(0)); 1218 return key | matrixKey; 1219} 1220 1221void GrGLLightingEffect::setData(const GrGLUniformManager& uman, 1222 const GrDrawEffect& drawEffect) { 1223 const GrLightingEffect& lighting = drawEffect.castEffect<GrLightingEffect>(); 1224 GrTexture* texture = lighting.texture(0); 1225 float ySign = texture->origin() == kTopLeft_GrSurfaceOrigin ? -1.0f : 1.0f; 1226 uman.set2f(fImageIncrementUni, 1.0f / texture->width(), ySign / texture->height()); 1227 uman.set1f(fSurfaceScaleUni, lighting.surfaceScale()); 1228 fLight->setData(uman, lighting.light()); 1229 fEffectMatrix.setData(uman, 1230 lighting.getMatrix(), 1231 drawEffect, 1232 lighting.texture(0)); 1233} 1234 1235/////////////////////////////////////////////////////////////////////////////// 1236 1237/////////////////////////////////////////////////////////////////////////////// 1238 1239GrGLDiffuseLightingEffect::GrGLDiffuseLightingEffect(const GrBackendEffectFactory& factory, 1240 const GrDrawEffect& drawEffect) 1241 : INHERITED(factory, drawEffect) 1242 , fKDUni(kInvalidUniformHandle) { 1243} 1244 1245void GrGLDiffuseLightingEffect::emitLightFunc(GrGLShaderBuilder* builder, SkString* funcName) { 1246 const char* kd; 1247 fKDUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, 1248 kFloat_GrSLType, 1249 "KD", 1250 &kd); 1251 1252 static const GrGLShaderVar gLightArgs[] = { 1253 GrGLShaderVar("normal", kVec3f_GrSLType), 1254 GrGLShaderVar("surfaceToLight", kVec3f_GrSLType), 1255 GrGLShaderVar("lightColor", kVec3f_GrSLType) 1256 }; 1257 SkString lightBody; 1258 lightBody.appendf("\tfloat colorScale = %s * dot(normal, surfaceToLight);\n", kd); 1259 lightBody.appendf("\treturn vec4(lightColor * clamp(colorScale, 0.0, 1.0), 1.0);\n"); 1260 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType, 1261 kVec4f_GrSLType, 1262 "light", 1263 SK_ARRAY_COUNT(gLightArgs), 1264 gLightArgs, 1265 lightBody.c_str(), 1266 funcName); 1267} 1268 1269void GrGLDiffuseLightingEffect::setData(const GrGLUniformManager& uman, 1270 const GrDrawEffect& drawEffect) { 1271 INHERITED::setData(uman, drawEffect); 1272 const GrDiffuseLightingEffect& diffuse = drawEffect.castEffect<GrDiffuseLightingEffect>(); 1273 uman.set1f(fKDUni, diffuse.kd()); 1274} 1275 1276/////////////////////////////////////////////////////////////////////////////// 1277 1278GrSpecularLightingEffect::GrSpecularLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess) 1279 : INHERITED(texture, light, surfaceScale), 1280 fKS(ks), 1281 fShininess(shininess) { 1282} 1283 1284const GrBackendEffectFactory& GrSpecularLightingEffect::getFactory() const { 1285 return GrTBackendEffectFactory<GrSpecularLightingEffect>::getInstance(); 1286} 1287 1288bool GrSpecularLightingEffect::onIsEqual(const GrEffect& sBase) const { 1289 const GrSpecularLightingEffect& s = CastEffect<GrSpecularLightingEffect>(sBase); 1290 return INHERITED::onIsEqual(sBase) && 1291 this->ks() == s.ks() && 1292 this->shininess() == s.shininess(); 1293} 1294 1295GR_DEFINE_EFFECT_TEST(GrSpecularLightingEffect); 1296 1297GrEffectRef* GrSpecularLightingEffect::TestCreate(SkMWCRandom* random, 1298 GrContext* context, 1299 GrTexture* textures[]) { 1300 SkScalar surfaceScale = random->nextSScalar1(); 1301 SkScalar ks = random->nextUScalar1(); 1302 SkScalar shininess = random->nextUScalar1(); 1303 SkAutoTUnref<SkLight> light(create_random_light(random)); 1304 return GrSpecularLightingEffect::Create(textures[GrEffectUnitTest::kAlphaTextureIdx], 1305 light, surfaceScale, ks, shininess); 1306} 1307 1308/////////////////////////////////////////////////////////////////////////////// 1309 1310GrGLSpecularLightingEffect::GrGLSpecularLightingEffect(const GrBackendEffectFactory& factory, 1311 const GrDrawEffect& drawEffect) 1312 : GrGLLightingEffect(factory, drawEffect) 1313 , fKSUni(kInvalidUniformHandle) 1314 , fShininessUni(kInvalidUniformHandle) { 1315} 1316 1317void GrGLSpecularLightingEffect::emitLightFunc(GrGLShaderBuilder* builder, SkString* funcName) { 1318 const char* ks; 1319 const char* shininess; 1320 1321 fKSUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, 1322 kFloat_GrSLType, "KS", &ks); 1323 fShininessUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, 1324 kFloat_GrSLType, "Shininess", &shininess); 1325 1326 static const GrGLShaderVar gLightArgs[] = { 1327 GrGLShaderVar("normal", kVec3f_GrSLType), 1328 GrGLShaderVar("surfaceToLight", kVec3f_GrSLType), 1329 GrGLShaderVar("lightColor", kVec3f_GrSLType) 1330 }; 1331 SkString lightBody; 1332 lightBody.appendf("\tvec3 halfDir = vec3(normalize(surfaceToLight + vec3(0, 0, 1)));\n"); 1333 lightBody.appendf("\tfloat colorScale = %s * pow(dot(normal, halfDir), %s);\n", ks, shininess); 1334 lightBody.appendf("\tvec3 color = lightColor * clamp(colorScale, 0.0, 1.0);\n"); 1335 lightBody.appendf("\treturn vec4(color, max(max(color.r, color.g), color.b));\n"); 1336 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType, 1337 kVec4f_GrSLType, 1338 "light", 1339 SK_ARRAY_COUNT(gLightArgs), 1340 gLightArgs, 1341 lightBody.c_str(), 1342 funcName); 1343} 1344 1345void GrGLSpecularLightingEffect::setData(const GrGLUniformManager& uman, 1346 const GrDrawEffect& drawEffect) { 1347 INHERITED::setData(uman, drawEffect); 1348 const GrSpecularLightingEffect& spec = drawEffect.castEffect<GrSpecularLightingEffect>(); 1349 uman.set1f(fKSUni, spec.ks()); 1350 uman.set1f(fShininessUni, spec.shininess()); 1351} 1352 1353/////////////////////////////////////////////////////////////////////////////// 1354void GrGLLight::emitLightColorUniform(GrGLShaderBuilder* builder) { 1355 fColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, 1356 kVec3f_GrSLType, "LightColor"); 1357} 1358 1359void GrGLLight::emitLightColor(GrGLShaderBuilder* builder, 1360 const char *surfaceToLight) { 1361 builder->fsCodeAppend(builder->getUniformCStr(this->lightColorUni())); 1362} 1363 1364void GrGLLight::setData(const GrGLUniformManager& uman, const SkLight* light) const { 1365 setUniformPoint3(uman, fColorUni, light->color() * SkScalarInvert(SkIntToScalar(255))); 1366} 1367 1368/////////////////////////////////////////////////////////////////////////////// 1369 1370void GrGLDistantLight::setData(const GrGLUniformManager& uman, const SkLight* light) const { 1371 INHERITED::setData(uman, light); 1372 SkASSERT(light->type() == SkLight::kDistant_LightType); 1373 const SkDistantLight* distantLight = static_cast<const SkDistantLight*>(light); 1374 setUniformNormal3(uman, fDirectionUni, distantLight->direction()); 1375} 1376 1377void GrGLDistantLight::emitSurfaceToLight(GrGLShaderBuilder* builder, const char* z) { 1378 const char* dir; 1379 fDirectionUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, kVec3f_GrSLType, 1380 "LightDirection", &dir); 1381 builder->fsCodeAppend(dir); 1382} 1383 1384/////////////////////////////////////////////////////////////////////////////// 1385 1386void GrGLPointLight::setData(const GrGLUniformManager& uman, 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 1393void GrGLPointLight::emitSurfaceToLight(GrGLShaderBuilder* builder, const char* z) { 1394 const char* loc; 1395 fLocationUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, kVec3f_GrSLType, 1396 "LightLocation", &loc); 1397 builder->fsCodeAppendf("normalize(%s - vec3(%s.xy, %s))", loc, builder->fragmentPosition(), z); 1398} 1399 1400/////////////////////////////////////////////////////////////////////////////// 1401 1402void GrGLSpotLight::setData(const GrGLUniformManager& uman, const SkLight* light) const { 1403 INHERITED::setData(uman, light); 1404 SkASSERT(light->type() == SkLight::kSpot_LightType); 1405 const SkSpotLight* spotLight = static_cast<const SkSpotLight *>(light); 1406 setUniformPoint3(uman, fLocationUni, spotLight->location()); 1407 uman.set1f(fExponentUni, spotLight->specularExponent()); 1408 uman.set1f(fCosInnerConeAngleUni, spotLight->cosInnerConeAngle()); 1409 uman.set1f(fCosOuterConeAngleUni, spotLight->cosOuterConeAngle()); 1410 uman.set1f(fConeScaleUni, spotLight->coneScale()); 1411 setUniformNormal3(uman, fSUni, spotLight->s()); 1412} 1413 1414void GrGLSpotLight::emitSurfaceToLight(GrGLShaderBuilder* builder, const char* z) { 1415 const char* location; 1416 fLocationUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, 1417 kVec3f_GrSLType, "LightLocation", &location); 1418 builder->fsCodeAppendf("normalize(%s - vec3(%s.xy, %s))", 1419 location, builder->fragmentPosition(), z); 1420} 1421 1422void GrGLSpotLight::emitLightColor(GrGLShaderBuilder* builder, 1423 const char *surfaceToLight) { 1424 1425 const char* color = builder->getUniformCStr(this->lightColorUni()); // created by parent class. 1426 1427 const char* exponent; 1428 const char* cosInner; 1429 const char* cosOuter; 1430 const char* coneScale; 1431 const char* s; 1432 fExponentUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, 1433 kFloat_GrSLType, "Exponent", &exponent); 1434 fCosInnerConeAngleUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, 1435 kFloat_GrSLType, "CosInnerConeAngle", &cosInner); 1436 fCosOuterConeAngleUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, 1437 kFloat_GrSLType, "CosOuterConeAngle", &cosOuter); 1438 fConeScaleUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, 1439 kFloat_GrSLType, "ConeScale", &coneScale); 1440 fSUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, 1441 kVec3f_GrSLType, "S", &s); 1442 1443 static const GrGLShaderVar gLightColorArgs[] = { 1444 GrGLShaderVar("surfaceToLight", kVec3f_GrSLType) 1445 }; 1446 SkString lightColorBody; 1447 lightColorBody.appendf("\tfloat cosAngle = -dot(surfaceToLight, %s);\n", s); 1448 lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosOuter); 1449 lightColorBody.appendf("\t\treturn vec3(0);\n"); 1450 lightColorBody.appendf("\t}\n"); 1451 lightColorBody.appendf("\tfloat scale = pow(cosAngle, %s);\n", exponent); 1452 lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosInner); 1453 lightColorBody.appendf("\t\treturn %s * scale * (cosAngle - %s) * %s;\n", 1454 color, cosOuter, coneScale); 1455 lightColorBody.appendf("\t}\n"); 1456 lightColorBody.appendf("\treturn %s;\n", color); 1457 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType, 1458 kVec3f_GrSLType, 1459 "lightColor", 1460 SK_ARRAY_COUNT(gLightColorArgs), 1461 gLightColorArgs, 1462 lightColorBody.c_str(), 1463 &fLightColorFunc); 1464 1465 builder->fsCodeAppendf("%s(%s)", fLightColorFunc.c_str(), surfaceToLight); 1466} 1467 1468#endif 1469 1470SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingImageFilter) 1471 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDiffuseLightingImageFilter) 1472 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSpecularLightingImageFilter) 1473 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDistantLight) 1474 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPointLight) 1475 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSpotLight) 1476SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 1477