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