2 * Copyright 2012 The Android Open Source Project
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "SkLightingImageFilter.h"
10 #include "SkColorPriv.h"
11 #include "SkReadBuffer.h"
12 #include "SkWriteBuffer.h"
13 #include "SkReadBuffer.h"
14 #include "SkWriteBuffer.h"
18 #include "effects/GrSingleTextureEffect.h"
19 #include "gl/GrGLProcessor.h"
20 #include "gl/builders/GrGLProgramBuilder.h"
21 #include "GrProcessor.h"
22 #include "GrTBackendProcessorFactory.h"
24 class GrGLDiffuseLightingEffect;
25 class GrGLSpecularLightingEffect;
28 typedef GrGLProgramDataManager::UniformHandle UniformHandle;
33 const SkScalar gOneThird = SkScalarInvert(SkIntToScalar(3));
34 const SkScalar gTwoThirds = SkScalarDiv(SkIntToScalar(2), SkIntToScalar(3));
35 const SkScalar gOneHalf = 0.5f;
36 const SkScalar gOneQuarter = 0.25f;
39 void setUniformPoint3(const GrGLProgramDataManager& pdman, UniformHandle uni,
40 const SkPoint3& point) {
41 GR_STATIC_ASSERT(sizeof(SkPoint3) == 3 * sizeof(GrGLfloat));
42 pdman.set3fv(uni, 1, &point.fX);
45 void setUniformNormal3(const GrGLProgramDataManager& pdman, UniformHandle uni,
46 const SkPoint3& point) {
47 setUniformPoint3(pdman, uni, SkPoint3(point.fX, point.fY, point.fZ));
51 // Shift matrix components to the left, as we advance pixels to the right.
52 inline void shiftMatrixLeft(int m[9]) {
61 class DiffuseLightingType {
63 DiffuseLightingType(SkScalar kd)
65 SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight,
66 const SkPoint3& lightColor) const {
67 SkScalar colorScale = SkScalarMul(fKD, normal.dot(surfaceTolight));
68 colorScale = SkScalarClampMax(colorScale, SK_Scalar1);
69 SkPoint3 color(lightColor * colorScale);
70 return SkPackARGB32(255,
71 SkClampMax(SkScalarRoundToInt(color.fX), 255),
72 SkClampMax(SkScalarRoundToInt(color.fY), 255),
73 SkClampMax(SkScalarRoundToInt(color.fZ), 255));
79 class SpecularLightingType {
81 SpecularLightingType(SkScalar ks, SkScalar shininess)
82 : fKS(ks), fShininess(shininess) {}
83 SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight,
84 const SkPoint3& lightColor) const {
85 SkPoint3 halfDir(surfaceTolight);
86 halfDir.fZ += SK_Scalar1; // eye position is always (0, 0, 1)
88 SkScalar colorScale = SkScalarMul(fKS,
89 SkScalarPow(normal.dot(halfDir), fShininess));
90 colorScale = SkScalarClampMax(colorScale, SK_Scalar1);
91 SkPoint3 color(lightColor * colorScale);
92 return SkPackARGB32(SkClampMax(SkScalarRoundToInt(color.maxComponent()), 255),
93 SkClampMax(SkScalarRoundToInt(color.fX), 255),
94 SkClampMax(SkScalarRoundToInt(color.fY), 255),
95 SkClampMax(SkScalarRoundToInt(color.fZ), 255));
102 inline SkScalar sobel(int a, int b, int c, int d, int e, int f, SkScalar scale) {
103 return SkScalarMul(SkIntToScalar(-a + b - 2 * c + 2 * d -e + f), scale);
106 inline SkPoint3 pointToNormal(SkScalar x, SkScalar y, SkScalar surfaceScale) {
107 SkPoint3 vector(SkScalarMul(-x, surfaceScale),
108 SkScalarMul(-y, surfaceScale),
114 inline SkPoint3 topLeftNormal(int m[9], SkScalar surfaceScale) {
115 return pointToNormal(sobel(0, 0, m[4], m[5], m[7], m[8], gTwoThirds),
116 sobel(0, 0, m[4], m[7], m[5], m[8], gTwoThirds),
120 inline SkPoint3 topNormal(int m[9], SkScalar surfaceScale) {
121 return pointToNormal(sobel( 0, 0, m[3], m[5], m[6], m[8], gOneThird),
122 sobel(m[3], m[6], m[4], m[7], m[5], m[8], gOneHalf),
126 inline SkPoint3 topRightNormal(int m[9], SkScalar surfaceScale) {
127 return pointToNormal(sobel( 0, 0, m[3], m[4], m[6], m[7], gTwoThirds),
128 sobel(m[3], m[6], m[4], m[7], 0, 0, gTwoThirds),
132 inline SkPoint3 leftNormal(int m[9], SkScalar surfaceScale) {
133 return pointToNormal(sobel(m[1], m[2], m[4], m[5], m[7], m[8], gOneHalf),
134 sobel( 0, 0, m[1], m[7], m[2], m[8], gOneThird),
139 inline SkPoint3 interiorNormal(int m[9], SkScalar surfaceScale) {
140 return pointToNormal(sobel(m[0], m[2], m[3], m[5], m[6], m[8], gOneQuarter),
141 sobel(m[0], m[6], m[1], m[7], m[2], m[8], gOneQuarter),
145 inline SkPoint3 rightNormal(int m[9], SkScalar surfaceScale) {
146 return pointToNormal(sobel(m[0], m[1], m[3], m[4], m[6], m[7], gOneHalf),
147 sobel(m[0], m[6], m[1], m[7], 0, 0, gOneThird),
151 inline SkPoint3 bottomLeftNormal(int m[9], SkScalar surfaceScale) {
152 return pointToNormal(sobel(m[1], m[2], m[4], m[5], 0, 0, gTwoThirds),
153 sobel( 0, 0, m[1], m[4], m[2], m[5], gTwoThirds),
157 inline SkPoint3 bottomNormal(int m[9], SkScalar surfaceScale) {
158 return pointToNormal(sobel(m[0], m[2], m[3], m[5], 0, 0, gOneThird),
159 sobel(m[0], m[3], m[1], m[4], m[2], m[5], gOneHalf),
163 inline SkPoint3 bottomRightNormal(int m[9], SkScalar surfaceScale) {
164 return pointToNormal(sobel(m[0], m[1], m[3], m[4], 0, 0, gTwoThirds),
165 sobel(m[0], m[3], m[1], m[4], 0, 0, gTwoThirds),
169 template <class LightingType, class LightType> void lightBitmap(
170 const LightingType& lightingType, const SkLight* light, const SkBitmap& src, SkBitmap* dst,
171 SkScalar surfaceScale, const SkIRect& bounds) {
172 SkASSERT(dst->width() == bounds.width() && dst->height() == bounds.height());
173 const LightType* l = static_cast<const LightType*>(light);
174 int left = bounds.left(), right = bounds.right();
175 int bottom = bounds.bottom();
176 int y = bounds.top();
177 SkPMColor* dptr = dst->getAddr32(0, 0);
180 const SkPMColor* row1 = src.getAddr32(x, y);
181 const SkPMColor* row2 = src.getAddr32(x, y + 1);
183 m[4] = SkGetPackedA32(*row1++);
184 m[5] = SkGetPackedA32(*row1++);
185 m[7] = SkGetPackedA32(*row2++);
186 m[8] = SkGetPackedA32(*row2++);
187 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
188 *dptr++ = lightingType.light(topLeftNormal(m, surfaceScale), surfaceToLight,
189 l->lightColor(surfaceToLight));
190 for (++x; x < right - 1; ++x)
193 m[5] = SkGetPackedA32(*row1++);
194 m[8] = SkGetPackedA32(*row2++);
195 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
196 *dptr++ = lightingType.light(topNormal(m, surfaceScale), surfaceToLight,
197 l->lightColor(surfaceToLight));
200 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
201 *dptr++ = lightingType.light(topRightNormal(m, surfaceScale), surfaceToLight,
202 l->lightColor(surfaceToLight));
205 for (++y; y < bottom - 1; ++y) {
207 const SkPMColor* row0 = src.getAddr32(x, y - 1);
208 const SkPMColor* row1 = src.getAddr32(x, y);
209 const SkPMColor* row2 = src.getAddr32(x, y + 1);
211 m[1] = SkGetPackedA32(*row0++);
212 m[2] = SkGetPackedA32(*row0++);
213 m[4] = SkGetPackedA32(*row1++);
214 m[5] = SkGetPackedA32(*row1++);
215 m[7] = SkGetPackedA32(*row2++);
216 m[8] = SkGetPackedA32(*row2++);
217 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
218 *dptr++ = lightingType.light(leftNormal(m, surfaceScale), surfaceToLight,
219 l->lightColor(surfaceToLight));
220 for (++x; x < right - 1; ++x) {
222 m[2] = SkGetPackedA32(*row0++);
223 m[5] = SkGetPackedA32(*row1++);
224 m[8] = SkGetPackedA32(*row2++);
225 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
226 *dptr++ = lightingType.light(interiorNormal(m, surfaceScale), surfaceToLight,
227 l->lightColor(surfaceToLight));
230 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
231 *dptr++ = lightingType.light(rightNormal(m, surfaceScale), surfaceToLight,
232 l->lightColor(surfaceToLight));
237 const SkPMColor* row0 = src.getAddr32(x, bottom - 2);
238 const SkPMColor* row1 = src.getAddr32(x, bottom - 1);
240 m[1] = SkGetPackedA32(*row0++);
241 m[2] = SkGetPackedA32(*row0++);
242 m[4] = SkGetPackedA32(*row1++);
243 m[5] = SkGetPackedA32(*row1++);
244 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
245 *dptr++ = lightingType.light(bottomLeftNormal(m, surfaceScale), surfaceToLight,
246 l->lightColor(surfaceToLight));
247 for (++x; x < right - 1; ++x)
250 m[2] = SkGetPackedA32(*row0++);
251 m[5] = SkGetPackedA32(*row1++);
252 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
253 *dptr++ = lightingType.light(bottomNormal(m, surfaceScale), surfaceToLight,
254 l->lightColor(surfaceToLight));
257 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
258 *dptr++ = lightingType.light(bottomRightNormal(m, surfaceScale), surfaceToLight,
259 l->lightColor(surfaceToLight));
263 SkPoint3 readPoint3(SkReadBuffer& buffer) {
265 point.fX = buffer.readScalar();
266 point.fY = buffer.readScalar();
267 point.fZ = buffer.readScalar();
268 buffer.validate(SkScalarIsFinite(point.fX) &&
269 SkScalarIsFinite(point.fY) &&
270 SkScalarIsFinite(point.fZ));
274 void writePoint3(const SkPoint3& point, SkWriteBuffer& buffer) {
275 buffer.writeScalar(point.fX);
276 buffer.writeScalar(point.fY);
277 buffer.writeScalar(point.fZ);
280 class SkDiffuseLightingImageFilter : public SkLightingImageFilter {
282 static SkImageFilter* Create(SkLight* light, SkScalar surfaceScale, SkScalar kd, SkImageFilter*,
283 const CropRect*, uint32_t uniqueID = 0);
285 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDiffuseLightingImageFilter)
286 SkScalar kd() const { return fKD; }
289 SkDiffuseLightingImageFilter(SkLight* light, SkScalar surfaceScale,
290 SkScalar kd, SkImageFilter* input, const CropRect* cropRect,
292 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
293 explicit SkDiffuseLightingImageFilter(SkReadBuffer& buffer);
295 virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE;
296 virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&,
297 SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE;
299 virtual bool asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&,
300 const SkIRect& bounds) const SK_OVERRIDE;
304 friend class SkLightingImageFilter;
305 typedef SkLightingImageFilter INHERITED;
309 class SkSpecularLightingImageFilter : public SkLightingImageFilter {
311 static SkImageFilter* Create(SkLight* light, SkScalar surfaceScale,
312 SkScalar ks, SkScalar shininess, SkImageFilter*, const CropRect*,
313 uint32_t uniqueID = 0);
315 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSpecularLightingImageFilter)
317 SkScalar ks() const { return fKS; }
318 SkScalar shininess() const { return fShininess; }
321 SkSpecularLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar ks,
322 SkScalar shininess, SkImageFilter* input, const CropRect*,
324 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
325 explicit SkSpecularLightingImageFilter(SkReadBuffer& buffer);
327 virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE;
328 virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&,
329 SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE;
331 virtual bool asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&,
332 const SkIRect& bounds) const SK_OVERRIDE;
338 friend class SkLightingImageFilter;
339 typedef SkLightingImageFilter INHERITED;
344 class GrLightingEffect : public GrSingleTextureEffect {
346 GrLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale, const SkMatrix& matrix);
347 virtual ~GrLightingEffect();
349 const SkLight* light() const { return fLight; }
350 SkScalar surfaceScale() const { return fSurfaceScale; }
351 const SkMatrix& filterMatrix() const { return fFilterMatrix; }
353 virtual void getConstantColorComponents(GrColor* color,
354 uint32_t* validFlags) const SK_OVERRIDE {
355 // lighting shaders are complicated. We just throw up our hands.
360 virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE;
363 typedef GrSingleTextureEffect INHERITED;
364 const SkLight* fLight;
365 SkScalar fSurfaceScale;
366 SkMatrix fFilterMatrix;
369 class GrDiffuseLightingEffect : public GrLightingEffect {
371 static GrFragmentProcessor* Create(GrTexture* texture,
372 const SkLight* light,
373 SkScalar surfaceScale,
374 const SkMatrix& matrix,
376 return SkNEW_ARGS(GrDiffuseLightingEffect, (texture,
383 static const char* Name() { return "DiffuseLighting"; }
385 typedef GrGLDiffuseLightingEffect GLProcessor;
387 virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE;
388 SkScalar kd() const { return fKD; }
391 virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE;
393 GrDiffuseLightingEffect(GrTexture* texture,
394 const SkLight* light,
395 SkScalar surfaceScale,
396 const SkMatrix& matrix,
399 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
400 typedef GrLightingEffect INHERITED;
404 class GrSpecularLightingEffect : public GrLightingEffect {
406 static GrFragmentProcessor* Create(GrTexture* texture,
407 const SkLight* light,
408 SkScalar surfaceScale,
409 const SkMatrix& matrix,
411 SkScalar shininess) {
412 return SkNEW_ARGS(GrSpecularLightingEffect, (texture,
419 static const char* Name() { return "SpecularLighting"; }
421 typedef GrGLSpecularLightingEffect GLProcessor;
423 virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE;
424 SkScalar ks() const { return fKS; }
425 SkScalar shininess() const { return fShininess; }
428 virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE;
430 GrSpecularLightingEffect(GrTexture* texture,
431 const SkLight* light,
432 SkScalar surfaceScale,
433 const SkMatrix& matrix,
437 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
438 typedef GrLightingEffect INHERITED;
443 ///////////////////////////////////////////////////////////////////////////////
447 virtual ~GrGLLight() {}
450 * This is called by GrGLLightingEffect::emitCode() before either of the two virtual functions
451 * below. It adds a vec3f uniform visible in the FS that represents the constant light color.
453 void emitLightColorUniform(GrGLProgramBuilder*);
456 * These two functions are called from GrGLLightingEffect's emitCode() function.
457 * emitSurfaceToLight places an expression in param out that is the vector from the surface to
458 * the light. The expression will be used in the FS. emitLightColor writes an expression into
459 * the FS that is the color of the light. Either function may add functions and/or uniforms to
460 * the FS. The default of emitLightColor appends the name of the constant light color uniform
461 * and so this function only needs to be overridden if the light color varies spatially.
463 virtual void emitSurfaceToLight(GrGLProgramBuilder*, const char* z) = 0;
464 virtual void emitLightColor(GrGLProgramBuilder*, const char *surfaceToLight);
466 // This is called from GrGLLightingEffect's setData(). Subclasses of GrGLLight must call
467 // INHERITED::setData().
468 virtual void setData(const GrGLProgramDataManager&,
469 const SkLight* light) const;
473 * Gets the constant light color uniform. Subclasses can use this in their emitLightColor
476 UniformHandle lightColorUni() const { return fColorUni; }
479 UniformHandle fColorUni;
481 typedef SkRefCnt INHERITED;
484 ///////////////////////////////////////////////////////////////////////////////
486 class GrGLDistantLight : public GrGLLight {
488 virtual ~GrGLDistantLight() {}
489 virtual void setData(const GrGLProgramDataManager&,
490 const SkLight* light) const SK_OVERRIDE;
491 virtual void emitSurfaceToLight(GrGLProgramBuilder*, const char* z) SK_OVERRIDE;
494 typedef GrGLLight INHERITED;
495 UniformHandle fDirectionUni;
498 ///////////////////////////////////////////////////////////////////////////////
500 class GrGLPointLight : public GrGLLight {
502 virtual ~GrGLPointLight() {}
503 virtual void setData(const GrGLProgramDataManager&,
504 const SkLight* light) const SK_OVERRIDE;
505 virtual void emitSurfaceToLight(GrGLProgramBuilder*, const char* z) SK_OVERRIDE;
508 typedef GrGLLight INHERITED;
509 UniformHandle fLocationUni;
512 ///////////////////////////////////////////////////////////////////////////////
514 class GrGLSpotLight : public GrGLLight {
516 virtual ~GrGLSpotLight() {}
517 virtual void setData(const GrGLProgramDataManager&,
518 const SkLight* light) const SK_OVERRIDE;
519 virtual void emitSurfaceToLight(GrGLProgramBuilder*, const char* z) SK_OVERRIDE;
520 virtual void emitLightColor(GrGLProgramBuilder*, const char *surfaceToLight) SK_OVERRIDE;
523 typedef GrGLLight INHERITED;
525 SkString fLightColorFunc;
526 UniformHandle fLocationUni;
527 UniformHandle fExponentUni;
528 UniformHandle fCosOuterConeAngleUni;
529 UniformHandle fCosInnerConeAngleUni;
530 UniformHandle fConeScaleUni;
541 ///////////////////////////////////////////////////////////////////////////////
543 class SkLight : public SkRefCnt {
545 SK_DECLARE_INST_COUNT(SkLight)
552 virtual LightType type() const = 0;
553 const SkPoint3& color() const { return fColor; }
554 virtual GrGLLight* createGLLight() const = 0;
555 virtual bool isEqual(const SkLight& other) const {
556 return fColor == other.fColor;
558 // Called to know whether the generated GrGLLight will require access to the fragment position.
559 virtual bool requiresFragmentPosition() const = 0;
560 virtual SkLight* transform(const SkMatrix& matrix) const = 0;
562 // Defined below SkLight's subclasses.
563 void flattenLight(SkWriteBuffer& buffer) const;
564 static SkLight* UnflattenLight(SkReadBuffer& buffer);
567 SkLight(SkColor color)
568 : fColor(SkIntToScalar(SkColorGetR(color)),
569 SkIntToScalar(SkColorGetG(color)),
570 SkIntToScalar(SkColorGetB(color))) {}
571 SkLight(const SkPoint3& color)
573 SkLight(SkReadBuffer& buffer) {
574 fColor = readPoint3(buffer);
577 virtual void onFlattenLight(SkWriteBuffer& buffer) const = 0;
581 typedef SkRefCnt INHERITED;
585 ///////////////////////////////////////////////////////////////////////////////
587 class SkDistantLight : public SkLight {
589 SkDistantLight(const SkPoint3& direction, SkColor color)
590 : INHERITED(color), fDirection(direction) {
593 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
596 SkPoint3 lightColor(const SkPoint3&) const { return color(); }
597 virtual LightType type() const { return kDistant_LightType; }
598 const SkPoint3& direction() const { return fDirection; }
599 virtual GrGLLight* createGLLight() const SK_OVERRIDE {
601 return SkNEW(GrGLDistantLight);
603 SkDEBUGFAIL("Should not call in GPU-less build");
607 virtual bool requiresFragmentPosition() const SK_OVERRIDE { return false; }
609 virtual bool isEqual(const SkLight& other) const SK_OVERRIDE {
610 if (other.type() != kDistant_LightType) {
614 const SkDistantLight& o = static_cast<const SkDistantLight&>(other);
615 return INHERITED::isEqual(other) &&
616 fDirection == o.fDirection;
619 SkDistantLight(SkReadBuffer& buffer) : INHERITED(buffer) {
620 fDirection = readPoint3(buffer);
624 SkDistantLight(const SkPoint3& direction, const SkPoint3& color)
625 : INHERITED(color), fDirection(direction) {
627 virtual SkLight* transform(const SkMatrix& matrix) const {
628 return new SkDistantLight(direction(), color());
630 virtual void onFlattenLight(SkWriteBuffer& buffer) const SK_OVERRIDE {
631 writePoint3(fDirection, buffer);
635 typedef SkLight INHERITED;
639 ///////////////////////////////////////////////////////////////////////////////
641 class SkPointLight : public SkLight {
643 SkPointLight(const SkPoint3& location, SkColor color)
644 : INHERITED(color), fLocation(location) {}
646 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
647 SkPoint3 direction(fLocation.fX - SkIntToScalar(x),
648 fLocation.fY - SkIntToScalar(y),
649 fLocation.fZ - SkScalarMul(SkIntToScalar(z), surfaceScale));
650 direction.normalize();
653 SkPoint3 lightColor(const SkPoint3&) const { return color(); }
654 virtual LightType type() const { return kPoint_LightType; }
655 const SkPoint3& location() const { return fLocation; }
656 virtual GrGLLight* createGLLight() const SK_OVERRIDE {
658 return SkNEW(GrGLPointLight);
660 SkDEBUGFAIL("Should not call in GPU-less build");
664 virtual bool requiresFragmentPosition() const SK_OVERRIDE { return true; }
665 virtual bool isEqual(const SkLight& other) const SK_OVERRIDE {
666 if (other.type() != kPoint_LightType) {
669 const SkPointLight& o = static_cast<const SkPointLight&>(other);
670 return INHERITED::isEqual(other) &&
671 fLocation == o.fLocation;
673 virtual SkLight* transform(const SkMatrix& matrix) const {
674 SkPoint location2 = SkPoint::Make(fLocation.fX, fLocation.fY);
675 matrix.mapPoints(&location2, 1);
676 // Use X scale and Y scale on Z and average the result
677 SkPoint locationZ = SkPoint::Make(fLocation.fZ, fLocation.fZ);
678 matrix.mapVectors(&locationZ, 1);
679 SkPoint3 location(location2.fX, location2.fY, SkScalarAve(locationZ.fX, locationZ.fY));
680 return new SkPointLight(location, color());
683 SkPointLight(SkReadBuffer& buffer) : INHERITED(buffer) {
684 fLocation = readPoint3(buffer);
688 SkPointLight(const SkPoint3& location, const SkPoint3& color)
689 : INHERITED(color), fLocation(location) {}
690 virtual void onFlattenLight(SkWriteBuffer& buffer) const SK_OVERRIDE {
691 writePoint3(fLocation, buffer);
695 typedef SkLight INHERITED;
699 ///////////////////////////////////////////////////////////////////////////////
701 class SkSpotLight : public SkLight {
703 SkSpotLight(const SkPoint3& location, const SkPoint3& target, SkScalar specularExponent, SkScalar cutoffAngle, SkColor color)
707 fSpecularExponent(SkScalarPin(specularExponent, kSpecularExponentMin, kSpecularExponentMax))
709 fS = target - location;
711 fCosOuterConeAngle = SkScalarCos(SkDegreesToRadians(cutoffAngle));
712 const SkScalar antiAliasThreshold = 0.016f;
713 fCosInnerConeAngle = fCosOuterConeAngle + antiAliasThreshold;
714 fConeScale = SkScalarInvert(antiAliasThreshold);
717 virtual SkLight* transform(const SkMatrix& matrix) const {
718 SkPoint location2 = SkPoint::Make(fLocation.fX, fLocation.fY);
719 matrix.mapPoints(&location2, 1);
720 // Use X scale and Y scale on Z and average the result
721 SkPoint locationZ = SkPoint::Make(fLocation.fZ, fLocation.fZ);
722 matrix.mapVectors(&locationZ, 1);
723 SkPoint3 location(location2.fX, location2.fY, SkScalarAve(locationZ.fX, locationZ.fY));
724 SkPoint target2 = SkPoint::Make(fTarget.fX, fTarget.fY);
725 matrix.mapPoints(&target2, 1);
726 SkPoint targetZ = SkPoint::Make(fTarget.fZ, fTarget.fZ);
727 matrix.mapVectors(&targetZ, 1);
728 SkPoint3 target(target2.fX, target2.fY, SkScalarAve(targetZ.fX, targetZ.fY));
729 SkPoint3 s = target - location;
731 return new SkSpotLight(location, target, fSpecularExponent, fCosOuterConeAngle, fCosInnerConeAngle, fConeScale, s, color());
734 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
735 SkPoint3 direction(fLocation.fX - SkIntToScalar(x),
736 fLocation.fY - SkIntToScalar(y),
737 fLocation.fZ - SkScalarMul(SkIntToScalar(z), surfaceScale));
738 direction.normalize();
741 SkPoint3 lightColor(const SkPoint3& surfaceToLight) const {
742 SkScalar cosAngle = -surfaceToLight.dot(fS);
743 if (cosAngle < fCosOuterConeAngle) {
744 return SkPoint3(0, 0, 0);
746 SkScalar scale = SkScalarPow(cosAngle, fSpecularExponent);
747 if (cosAngle < fCosInnerConeAngle) {
748 scale = SkScalarMul(scale, cosAngle - fCosOuterConeAngle);
749 return color() * SkScalarMul(scale, fConeScale);
751 return color() * scale;
753 virtual GrGLLight* createGLLight() const SK_OVERRIDE {
755 return SkNEW(GrGLSpotLight);
757 SkDEBUGFAIL("Should not call in GPU-less build");
761 virtual bool requiresFragmentPosition() const SK_OVERRIDE { return true; }
762 virtual LightType type() const { return kSpot_LightType; }
763 const SkPoint3& location() const { return fLocation; }
764 const SkPoint3& target() const { return fTarget; }
765 SkScalar specularExponent() const { return fSpecularExponent; }
766 SkScalar cosInnerConeAngle() const { return fCosInnerConeAngle; }
767 SkScalar cosOuterConeAngle() const { return fCosOuterConeAngle; }
768 SkScalar coneScale() const { return fConeScale; }
769 const SkPoint3& s() const { return fS; }
771 SkSpotLight(SkReadBuffer& buffer) : INHERITED(buffer) {
772 fLocation = readPoint3(buffer);
773 fTarget = readPoint3(buffer);
774 fSpecularExponent = buffer.readScalar();
775 fCosOuterConeAngle = buffer.readScalar();
776 fCosInnerConeAngle = buffer.readScalar();
777 fConeScale = buffer.readScalar();
778 fS = readPoint3(buffer);
779 buffer.validate(SkScalarIsFinite(fSpecularExponent) &&
780 SkScalarIsFinite(fCosOuterConeAngle) &&
781 SkScalarIsFinite(fCosInnerConeAngle) &&
782 SkScalarIsFinite(fConeScale));
785 SkSpotLight(const SkPoint3& location, const SkPoint3& target, SkScalar specularExponent, SkScalar cosOuterConeAngle, SkScalar cosInnerConeAngle, SkScalar coneScale, const SkPoint3& s, const SkPoint3& color)
789 fSpecularExponent(specularExponent),
790 fCosOuterConeAngle(cosOuterConeAngle),
791 fCosInnerConeAngle(cosInnerConeAngle),
792 fConeScale(coneScale),
796 virtual void onFlattenLight(SkWriteBuffer& buffer) const SK_OVERRIDE {
797 writePoint3(fLocation, buffer);
798 writePoint3(fTarget, buffer);
799 buffer.writeScalar(fSpecularExponent);
800 buffer.writeScalar(fCosOuterConeAngle);
801 buffer.writeScalar(fCosInnerConeAngle);
802 buffer.writeScalar(fConeScale);
803 writePoint3(fS, buffer);
806 virtual bool isEqual(const SkLight& other) const SK_OVERRIDE {
807 if (other.type() != kSpot_LightType) {
811 const SkSpotLight& o = static_cast<const SkSpotLight&>(other);
812 return INHERITED::isEqual(other) &&
813 fLocation == o.fLocation &&
814 fTarget == o.fTarget &&
815 fSpecularExponent == o.fSpecularExponent &&
816 fCosOuterConeAngle == o.fCosOuterConeAngle;
820 static const SkScalar kSpecularExponentMin;
821 static const SkScalar kSpecularExponentMax;
823 typedef SkLight INHERITED;
826 SkScalar fSpecularExponent;
827 SkScalar fCosOuterConeAngle;
828 SkScalar fCosInnerConeAngle;
833 // According to the spec, the specular term should be in the range [1, 128] :
834 // http://www.w3.org/TR/SVG/filters.html#feSpecularLightingSpecularExponentAttribute
835 const SkScalar SkSpotLight::kSpecularExponentMin = 1.0f;
836 const SkScalar SkSpotLight::kSpecularExponentMax = 128.0f;
838 ///////////////////////////////////////////////////////////////////////////////
840 void SkLight::flattenLight(SkWriteBuffer& buffer) const {
841 // Write type first, then baseclass, then subclass.
842 buffer.writeInt(this->type());
843 writePoint3(fColor, buffer);
844 this->onFlattenLight(buffer);
847 /*static*/ SkLight* SkLight::UnflattenLight(SkReadBuffer& buffer) {
849 const SkLight::LightType type = (SkLight::LightType)buffer.readInt();
851 // Each of these constructors must first call SkLight's, so we'll read the baseclass
852 // then subclass, same order as flattenLight.
853 case SkLight::kDistant_LightType: return SkNEW_ARGS(SkDistantLight, (buffer));
854 case SkLight::kPoint_LightType: return SkNEW_ARGS(SkPointLight, (buffer));
855 case SkLight::kSpot_LightType: return SkNEW_ARGS(SkSpotLight, (buffer));
857 SkDEBUGFAIL("Unknown LightType.");
858 buffer.validate(false);
862 ///////////////////////////////////////////////////////////////////////////////
864 SkLightingImageFilter::SkLightingImageFilter(SkLight* light, SkScalar surfaceScale,
865 SkImageFilter* input, const CropRect* cropRect,
867 : INHERITED(1, &input, cropRect, uniqueID)
868 , fLight(SkRef(light))
869 , fSurfaceScale(surfaceScale / 255)
872 SkImageFilter* SkLightingImageFilter::CreateDistantLitDiffuse(const SkPoint3& direction,
874 SkScalar surfaceScale,
876 SkImageFilter* input,
877 const CropRect* cropRect) {
878 SkAutoTUnref<SkLight> light(SkNEW_ARGS(SkDistantLight, (direction, lightColor)));
879 return SkDiffuseLightingImageFilter::Create(light, surfaceScale, kd, input, cropRect);
882 SkImageFilter* SkLightingImageFilter::CreatePointLitDiffuse(const SkPoint3& location,
884 SkScalar surfaceScale,
886 SkImageFilter* input,
887 const CropRect* cropRect) {
888 SkAutoTUnref<SkLight> light(SkNEW_ARGS(SkPointLight, (location, lightColor)));
889 return SkDiffuseLightingImageFilter::Create(light, surfaceScale, kd, input, cropRect);
892 SkImageFilter* SkLightingImageFilter::CreateSpotLitDiffuse(const SkPoint3& location,
893 const SkPoint3& target,
894 SkScalar specularExponent,
895 SkScalar cutoffAngle,
897 SkScalar surfaceScale,
899 SkImageFilter* input,
900 const CropRect* cropRect) {
901 SkAutoTUnref<SkLight> light(SkNEW_ARGS(SkSpotLight, (location, target, specularExponent,
902 cutoffAngle, lightColor)));
903 return SkDiffuseLightingImageFilter::Create(light, surfaceScale, kd, input, cropRect);
906 SkImageFilter* SkLightingImageFilter::CreateDistantLitSpecular(const SkPoint3& direction,
908 SkScalar surfaceScale,
911 SkImageFilter* input,
912 const CropRect* cropRect) {
913 SkAutoTUnref<SkLight> light(SkNEW_ARGS(SkDistantLight, (direction, lightColor)));
914 return SkSpecularLightingImageFilter::Create(light, surfaceScale, ks, shine, input, cropRect);
917 SkImageFilter* SkLightingImageFilter::CreatePointLitSpecular(const SkPoint3& location,
919 SkScalar surfaceScale,
922 SkImageFilter* input,
923 const CropRect* cropRect) {
924 SkAutoTUnref<SkLight> light(SkNEW_ARGS(SkPointLight, (location, lightColor)));
925 return SkSpecularLightingImageFilter::Create(light, surfaceScale, ks, shine, input, cropRect);
928 SkImageFilter* SkLightingImageFilter::CreateSpotLitSpecular(const SkPoint3& location,
929 const SkPoint3& target,
930 SkScalar specularExponent,
931 SkScalar cutoffAngle,
933 SkScalar surfaceScale,
936 SkImageFilter* input,
937 const CropRect* cropRect) {
938 SkAutoTUnref<SkLight> light(SkNEW_ARGS(SkSpotLight, (location, target, specularExponent,
939 cutoffAngle, lightColor)));
940 return SkSpecularLightingImageFilter::Create(light, surfaceScale, ks, shine, input, cropRect);
943 SkLightingImageFilter::~SkLightingImageFilter() {}
945 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
946 SkLightingImageFilter::SkLightingImageFilter(SkReadBuffer& buffer)
947 : INHERITED(1, buffer) {
948 fLight.reset(SkLight::UnflattenLight(buffer));
949 fSurfaceScale = buffer.readScalar();
950 buffer.validate(SkScalarIsFinite(fSurfaceScale));
954 void SkLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
955 this->INHERITED::flatten(buffer);
956 fLight->flattenLight(buffer);
957 buffer.writeScalar(fSurfaceScale * 255);
960 ///////////////////////////////////////////////////////////////////////////////
962 SkImageFilter* SkDiffuseLightingImageFilter::Create(SkLight* light, SkScalar surfaceScale,
963 SkScalar kd, SkImageFilter* input, const CropRect* cropRect, uint32_t uniqueID) {
967 if (!SkScalarIsFinite(surfaceScale) || !SkScalarIsFinite(kd)) {
970 // According to the spec, kd can be any non-negative number :
971 // http://www.w3.org/TR/SVG/filters.html#feDiffuseLightingElement
975 return SkNEW_ARGS(SkDiffuseLightingImageFilter, (light, surfaceScale, kd, input, cropRect, uniqueID));
978 SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar kd, SkImageFilter* input, const CropRect* cropRect, uint32_t uniqueID)
979 : SkLightingImageFilter(light, surfaceScale, input, cropRect, uniqueID),
984 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
985 SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkReadBuffer& buffer)
988 fKD = buffer.readScalar();
989 buffer.validate(SkScalarIsFinite(fKD) && (fKD >= 0));
993 SkFlattenable* SkDiffuseLightingImageFilter::CreateProc(SkReadBuffer& buffer) {
994 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
995 SkAutoTUnref<SkLight> light(SkLight::UnflattenLight(buffer));
996 SkScalar surfaceScale = buffer.readScalar();
997 SkScalar kd = buffer.readScalar();
998 return Create(light, surfaceScale, kd, common.getInput(0), &common.cropRect(), common.uniqueID());
1001 void SkDiffuseLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
1002 this->INHERITED::flatten(buffer);
1003 buffer.writeScalar(fKD);
1006 bool SkDiffuseLightingImageFilter::onFilterImage(Proxy* proxy,
1007 const SkBitmap& source,
1010 SkIPoint* offset) const {
1011 SkImageFilter* input = getInput(0);
1012 SkBitmap src = source;
1013 SkIPoint srcOffset = SkIPoint::Make(0, 0);
1014 if (input && !input->filterImage(proxy, source, ctx, &src, &srcOffset)) {
1018 if (src.colorType() != kN32_SkColorType) {
1022 if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) {
1026 if (bounds.width() < 2 || bounds.height() < 2) {
1030 SkAutoLockPixels alp(src);
1031 if (!src.getPixels()) {
1035 if (!dst->tryAllocPixels(src.info().makeWH(bounds.width(), bounds.height()))) {
1039 SkAutoTUnref<SkLight> transformedLight(light()->transform(ctx.ctm()));
1041 DiffuseLightingType lightingType(fKD);
1042 offset->fX = bounds.left();
1043 offset->fY = bounds.top();
1044 bounds.offset(-srcOffset);
1045 switch (transformedLight->type()) {
1046 case SkLight::kDistant_LightType:
1047 lightBitmap<DiffuseLightingType, SkDistantLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
1049 case SkLight::kPoint_LightType:
1050 lightBitmap<DiffuseLightingType, SkPointLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
1052 case SkLight::kSpot_LightType:
1053 lightBitmap<DiffuseLightingType, SkSpotLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
1061 bool SkDiffuseLightingImageFilter::asFragmentProcessor(GrFragmentProcessor** fp,
1063 const SkMatrix& matrix,
1064 const SkIRect&) const {
1066 SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255));
1067 *fp = GrDiffuseLightingEffect::Create(texture, light(), scale, matrix, kd());
1073 ///////////////////////////////////////////////////////////////////////////////
1075 SkImageFilter* SkSpecularLightingImageFilter::Create(SkLight* light, SkScalar surfaceScale,
1076 SkScalar ks, SkScalar shininess, SkImageFilter* input, const CropRect* cropRect, uint32_t uniqueID) {
1077 if (NULL == light) {
1080 if (!SkScalarIsFinite(surfaceScale) || !SkScalarIsFinite(ks) || !SkScalarIsFinite(shininess)) {
1083 // According to the spec, ks can be any non-negative number :
1084 // http://www.w3.org/TR/SVG/filters.html#feSpecularLightingElement
1088 return SkNEW_ARGS(SkSpecularLightingImageFilter,
1089 (light, surfaceScale, ks, shininess, input, cropRect, uniqueID));
1092 SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess, SkImageFilter* input, const CropRect* cropRect, uint32_t uniqueID)
1093 : SkLightingImageFilter(light, surfaceScale, input, cropRect, uniqueID),
1095 fShininess(shininess)
1099 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
1100 SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkReadBuffer& buffer)
1103 fKS = buffer.readScalar();
1104 fShininess = buffer.readScalar();
1105 buffer.validate(SkScalarIsFinite(fKS) && (fKS >= 0) &&
1106 SkScalarIsFinite(fShininess));
1110 SkFlattenable* SkSpecularLightingImageFilter::CreateProc(SkReadBuffer& buffer) {
1111 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
1112 SkAutoTUnref<SkLight> light(SkLight::UnflattenLight(buffer));
1113 SkScalar surfaceScale = buffer.readScalar();
1114 SkScalar ks = buffer.readScalar();
1115 SkScalar shine = buffer.readScalar();
1116 return Create(light, surfaceScale, ks, shine, common.getInput(0), &common.cropRect(), common.uniqueID());
1119 void SkSpecularLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
1120 this->INHERITED::flatten(buffer);
1121 buffer.writeScalar(fKS);
1122 buffer.writeScalar(fShininess);
1125 bool SkSpecularLightingImageFilter::onFilterImage(Proxy* proxy,
1126 const SkBitmap& source,
1129 SkIPoint* offset) const {
1130 SkImageFilter* input = getInput(0);
1131 SkBitmap src = source;
1132 SkIPoint srcOffset = SkIPoint::Make(0, 0);
1133 if (input && !input->filterImage(proxy, source, ctx, &src, &srcOffset)) {
1137 if (src.colorType() != kN32_SkColorType) {
1142 if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) {
1146 if (bounds.width() < 2 || bounds.height() < 2) {
1150 SkAutoLockPixels alp(src);
1151 if (!src.getPixels()) {
1155 if (!dst->tryAllocPixels(src.info().makeWH(bounds.width(), bounds.height()))) {
1159 SpecularLightingType lightingType(fKS, fShininess);
1160 offset->fX = bounds.left();
1161 offset->fY = bounds.top();
1162 bounds.offset(-srcOffset);
1163 SkAutoTUnref<SkLight> transformedLight(light()->transform(ctx.ctm()));
1164 switch (transformedLight->type()) {
1165 case SkLight::kDistant_LightType:
1166 lightBitmap<SpecularLightingType, SkDistantLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
1168 case SkLight::kPoint_LightType:
1169 lightBitmap<SpecularLightingType, SkPointLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
1171 case SkLight::kSpot_LightType:
1172 lightBitmap<SpecularLightingType, SkSpotLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
1179 bool SkSpecularLightingImageFilter::asFragmentProcessor(GrFragmentProcessor** fp,
1181 const SkMatrix& matrix,
1182 const SkIRect&) const {
1184 SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255));
1185 *fp = GrSpecularLightingEffect::Create(texture, light(), scale, matrix, ks(), shininess());
1191 ///////////////////////////////////////////////////////////////////////////////
1196 SkPoint3 random_point3(SkRandom* random) {
1197 return SkPoint3(SkScalarToFloat(random->nextSScalar1()),
1198 SkScalarToFloat(random->nextSScalar1()),
1199 SkScalarToFloat(random->nextSScalar1()));
1202 SkLight* create_random_light(SkRandom* random) {
1203 int type = random->nextULessThan(3);
1206 return SkNEW_ARGS(SkDistantLight, (random_point3(random), random->nextU()));
1209 return SkNEW_ARGS(SkPointLight, (random_point3(random), random->nextU()));
1212 return SkNEW_ARGS(SkSpotLight, (random_point3(random),
1213 random_point3(random),
1214 random->nextUScalar1(),
1215 random->nextUScalar1(),
1219 SkFAIL("Unexpected value.");
1226 class GrGLLightingEffect : public GrGLFragmentProcessor {
1228 GrGLLightingEffect(const GrBackendProcessorFactory&, const GrProcessor&);
1229 virtual ~GrGLLightingEffect();
1231 virtual void emitCode(GrGLProgramBuilder*,
1232 const GrFragmentProcessor&,
1233 const GrProcessorKey&,
1234 const char* outputColor,
1235 const char* inputColor,
1236 const TransformedCoordsArray&,
1237 const TextureSamplerArray&) SK_OVERRIDE;
1239 static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder* b);
1242 * Subclasses of GrGLLightingEffect must call INHERITED::setData();
1244 virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE;
1247 virtual void emitLightFunc(GrGLProgramBuilder*, SkString* funcName) = 0;
1250 typedef GrGLFragmentProcessor INHERITED;
1252 UniformHandle fImageIncrementUni;
1253 UniformHandle fSurfaceScaleUni;
1257 ///////////////////////////////////////////////////////////////////////////////
1259 class GrGLDiffuseLightingEffect : public GrGLLightingEffect {
1261 GrGLDiffuseLightingEffect(const GrBackendProcessorFactory&, const GrProcessor&);
1262 virtual void emitLightFunc(GrGLProgramBuilder*, SkString* funcName) SK_OVERRIDE;
1263 virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE;
1266 typedef GrGLLightingEffect INHERITED;
1268 UniformHandle fKDUni;
1271 ///////////////////////////////////////////////////////////////////////////////
1273 class GrGLSpecularLightingEffect : public GrGLLightingEffect {
1275 GrGLSpecularLightingEffect(const GrBackendProcessorFactory&, const GrProcessor&);
1276 virtual void emitLightFunc(GrGLProgramBuilder*, SkString* funcName) SK_OVERRIDE;
1277 virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE;
1280 typedef GrGLLightingEffect INHERITED;
1282 UniformHandle fKSUni;
1283 UniformHandle fShininessUni;
1286 ///////////////////////////////////////////////////////////////////////////////
1288 GrLightingEffect::GrLightingEffect(GrTexture* texture,
1289 const SkLight* light,
1290 SkScalar surfaceScale,
1291 const SkMatrix& matrix)
1292 : INHERITED(texture, GrCoordTransform::MakeDivByTextureWHMatrix(texture))
1294 , fSurfaceScale(surfaceScale)
1295 , fFilterMatrix(matrix) {
1297 if (light->requiresFragmentPosition()) {
1298 this->setWillReadFragmentPosition();
1302 GrLightingEffect::~GrLightingEffect() {
1306 bool GrLightingEffect::onIsEqual(const GrProcessor& sBase) const {
1307 const GrLightingEffect& s = sBase.cast<GrLightingEffect>();
1308 return this->texture(0) == s.texture(0) &&
1309 fLight->isEqual(*s.fLight) &&
1310 fSurfaceScale == s.fSurfaceScale;
1313 ///////////////////////////////////////////////////////////////////////////////
1315 GrDiffuseLightingEffect::GrDiffuseLightingEffect(GrTexture* texture,
1316 const SkLight* light,
1317 SkScalar surfaceScale,
1318 const SkMatrix& matrix,
1320 : INHERITED(texture, light, surfaceScale, matrix), fKD(kd) {
1323 const GrBackendFragmentProcessorFactory& GrDiffuseLightingEffect::getFactory() const {
1324 return GrTBackendFragmentProcessorFactory<GrDiffuseLightingEffect>::getInstance();
1327 bool GrDiffuseLightingEffect::onIsEqual(const GrProcessor& sBase) const {
1328 const GrDiffuseLightingEffect& s = sBase.cast<GrDiffuseLightingEffect>();
1329 return INHERITED::onIsEqual(sBase) &&
1330 this->kd() == s.kd();
1333 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDiffuseLightingEffect);
1335 GrFragmentProcessor* GrDiffuseLightingEffect::TestCreate(SkRandom* random,
1337 const GrDrawTargetCaps&,
1338 GrTexture* textures[]) {
1339 SkScalar surfaceScale = random->nextSScalar1();
1340 SkScalar kd = random->nextUScalar1();
1341 SkAutoTUnref<SkLight> light(create_random_light(random));
1343 for (int i = 0; i < 9; i++) {
1344 matrix[i] = random->nextUScalar1();
1346 return GrDiffuseLightingEffect::Create(textures[GrProcessorUnitTest::kAlphaTextureIdx],
1347 light, surfaceScale, matrix, kd);
1351 ///////////////////////////////////////////////////////////////////////////////
1353 GrGLLightingEffect::GrGLLightingEffect(const GrBackendProcessorFactory& factory,
1354 const GrProcessor& fp)
1355 : INHERITED(factory) {
1356 const GrLightingEffect& m = fp.cast<GrLightingEffect>();
1357 fLight = m.light()->createGLLight();
1360 GrGLLightingEffect::~GrGLLightingEffect() {
1364 void GrGLLightingEffect::emitCode(GrGLProgramBuilder* builder,
1365 const GrFragmentProcessor&,
1366 const GrProcessorKey& key,
1367 const char* outputColor,
1368 const char* inputColor,
1369 const TransformedCoordsArray& coords,
1370 const TextureSamplerArray& samplers) {
1371 fImageIncrementUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
1374 fSurfaceScaleUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
1377 fLight->emitLightColorUniform(builder);
1379 this->emitLightFunc(builder, &lightFunc);
1380 static const GrGLShaderVar gSobelArgs[] = {
1381 GrGLShaderVar("a", kFloat_GrSLType),
1382 GrGLShaderVar("b", kFloat_GrSLType),
1383 GrGLShaderVar("c", kFloat_GrSLType),
1384 GrGLShaderVar("d", kFloat_GrSLType),
1385 GrGLShaderVar("e", kFloat_GrSLType),
1386 GrGLShaderVar("f", kFloat_GrSLType),
1387 GrGLShaderVar("scale", kFloat_GrSLType),
1389 SkString sobelFuncName;
1390 GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
1391 SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0);
1393 fsBuilder->emitFunction(kFloat_GrSLType,
1395 SK_ARRAY_COUNT(gSobelArgs),
1397 "\treturn (-a + b - 2.0 * c + 2.0 * d -e + f) * scale;\n",
1399 static const GrGLShaderVar gPointToNormalArgs[] = {
1400 GrGLShaderVar("x", kFloat_GrSLType),
1401 GrGLShaderVar("y", kFloat_GrSLType),
1402 GrGLShaderVar("scale", kFloat_GrSLType),
1404 SkString pointToNormalName;
1405 fsBuilder->emitFunction(kVec3f_GrSLType,
1407 SK_ARRAY_COUNT(gPointToNormalArgs),
1409 "\treturn normalize(vec3(-x * scale, y * scale, 1));\n",
1410 &pointToNormalName);
1412 static const GrGLShaderVar gInteriorNormalArgs[] = {
1413 GrGLShaderVar("m", kFloat_GrSLType, 9),
1414 GrGLShaderVar("surfaceScale", kFloat_GrSLType),
1416 SkString interiorNormalBody;
1417 interiorNormalBody.appendf("\treturn %s(%s(m[0], m[2], m[3], m[5], m[6], m[8], 0.25),\n"
1418 "\t %s(m[0], m[6], m[1], m[7], m[2], m[8], 0.25),\n"
1419 "\t surfaceScale);\n",
1420 pointToNormalName.c_str(),
1421 sobelFuncName.c_str(),
1422 sobelFuncName.c_str());
1423 SkString interiorNormalName;
1424 fsBuilder->emitFunction(kVec3f_GrSLType,
1426 SK_ARRAY_COUNT(gInteriorNormalArgs),
1427 gInteriorNormalArgs,
1428 interiorNormalBody.c_str(),
1429 &interiorNormalName);
1431 fsBuilder->codeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str());
1432 fsBuilder->codeAppend("\t\tfloat m[9];\n");
1434 const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
1435 const char* surfScale = builder->getUniformCStr(fSurfaceScaleUni);
1438 for (int dy = -1; dy <= 1; dy++) {
1439 for (int dx = -1; dx <= 1; dx++) {
1441 texCoords.appendf("coord + vec2(%d, %d) * %s", dx, dy, imgInc);
1442 fsBuilder->codeAppendf("\t\tm[%d] = ", index++);
1443 fsBuilder->appendTextureLookup(samplers[0], texCoords.c_str());
1444 fsBuilder->codeAppend(".a;\n");
1447 fsBuilder->codeAppend("\t\tvec3 surfaceToLight = ");
1449 arg.appendf("%s * m[4]", surfScale);
1450 fLight->emitSurfaceToLight(builder, arg.c_str());
1451 fsBuilder->codeAppend(";\n");
1452 fsBuilder->codeAppendf("\t\t%s = %s(%s(m, %s), surfaceToLight, ",
1453 outputColor, lightFunc.c_str(), interiorNormalName.c_str(), surfScale);
1454 fLight->emitLightColor(builder, "surfaceToLight");
1455 fsBuilder->codeAppend(");\n");
1457 GrGLSLMulVarBy4f(&modulate, 2, outputColor, inputColor);
1458 fsBuilder->codeAppend(modulate.c_str());
1461 void GrGLLightingEffect::GenKey(const GrProcessor& proc,
1462 const GrGLCaps& caps, GrProcessorKeyBuilder* b) {
1463 b->add32(proc.cast<GrLightingEffect>().light()->type());
1466 void GrGLLightingEffect::setData(const GrGLProgramDataManager& pdman,
1467 const GrProcessor& proc) {
1468 const GrLightingEffect& lighting = proc.cast<GrLightingEffect>();
1469 GrTexture* texture = lighting.texture(0);
1470 float ySign = texture->origin() == kTopLeft_GrSurfaceOrigin ? -1.0f : 1.0f;
1471 pdman.set2f(fImageIncrementUni, 1.0f / texture->width(), ySign / texture->height());
1472 pdman.set1f(fSurfaceScaleUni, lighting.surfaceScale());
1473 SkAutoTUnref<SkLight> transformedLight(lighting.light()->transform(lighting.filterMatrix()));
1474 fLight->setData(pdman, transformedLight);
1477 ///////////////////////////////////////////////////////////////////////////////
1479 ///////////////////////////////////////////////////////////////////////////////
1481 GrGLDiffuseLightingEffect::GrGLDiffuseLightingEffect(const GrBackendProcessorFactory& factory,
1482 const GrProcessor& proc)
1483 : INHERITED(factory, proc) {
1486 void GrGLDiffuseLightingEffect::emitLightFunc(GrGLProgramBuilder* builder, SkString* funcName) {
1488 fKDUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
1493 static const GrGLShaderVar gLightArgs[] = {
1494 GrGLShaderVar("normal", kVec3f_GrSLType),
1495 GrGLShaderVar("surfaceToLight", kVec3f_GrSLType),
1496 GrGLShaderVar("lightColor", kVec3f_GrSLType)
1499 lightBody.appendf("\tfloat colorScale = %s * dot(normal, surfaceToLight);\n", kd);
1500 lightBody.appendf("\treturn vec4(lightColor * clamp(colorScale, 0.0, 1.0), 1.0);\n");
1501 builder->getFragmentShaderBuilder()->emitFunction(kVec4f_GrSLType,
1503 SK_ARRAY_COUNT(gLightArgs),
1509 void GrGLDiffuseLightingEffect::setData(const GrGLProgramDataManager& pdman,
1510 const GrProcessor& proc) {
1511 INHERITED::setData(pdman, proc);
1512 const GrDiffuseLightingEffect& diffuse = proc.cast<GrDiffuseLightingEffect>();
1513 pdman.set1f(fKDUni, diffuse.kd());
1516 ///////////////////////////////////////////////////////////////////////////////
1518 GrSpecularLightingEffect::GrSpecularLightingEffect(GrTexture* texture,
1519 const SkLight* light,
1520 SkScalar surfaceScale,
1521 const SkMatrix& matrix,
1524 : INHERITED(texture, light, surfaceScale, matrix),
1526 fShininess(shininess) {
1529 const GrBackendFragmentProcessorFactory& GrSpecularLightingEffect::getFactory() const {
1530 return GrTBackendFragmentProcessorFactory<GrSpecularLightingEffect>::getInstance();
1533 bool GrSpecularLightingEffect::onIsEqual(const GrProcessor& sBase) const {
1534 const GrSpecularLightingEffect& s = sBase.cast<GrSpecularLightingEffect>();
1535 return INHERITED::onIsEqual(sBase) &&
1536 this->ks() == s.ks() &&
1537 this->shininess() == s.shininess();
1540 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrSpecularLightingEffect);
1542 GrFragmentProcessor* GrSpecularLightingEffect::TestCreate(SkRandom* random,
1544 const GrDrawTargetCaps&,
1545 GrTexture* textures[]) {
1546 SkScalar surfaceScale = random->nextSScalar1();
1547 SkScalar ks = random->nextUScalar1();
1548 SkScalar shininess = random->nextUScalar1();
1549 SkAutoTUnref<SkLight> light(create_random_light(random));
1551 for (int i = 0; i < 9; i++) {
1552 matrix[i] = random->nextUScalar1();
1554 return GrSpecularLightingEffect::Create(textures[GrProcessorUnitTest::kAlphaTextureIdx],
1555 light, surfaceScale, matrix, ks, shininess);
1558 ///////////////////////////////////////////////////////////////////////////////
1560 GrGLSpecularLightingEffect::GrGLSpecularLightingEffect(const GrBackendProcessorFactory& factory,
1561 const GrProcessor& proc)
1562 : INHERITED(factory, proc) {
1565 void GrGLSpecularLightingEffect::emitLightFunc(GrGLProgramBuilder* builder, SkString* funcName) {
1567 const char* shininess;
1569 fKSUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
1570 kFloat_GrSLType, "KS", &ks);
1571 fShininessUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
1572 kFloat_GrSLType, "Shininess", &shininess);
1574 static const GrGLShaderVar gLightArgs[] = {
1575 GrGLShaderVar("normal", kVec3f_GrSLType),
1576 GrGLShaderVar("surfaceToLight", kVec3f_GrSLType),
1577 GrGLShaderVar("lightColor", kVec3f_GrSLType)
1580 lightBody.appendf("\tvec3 halfDir = vec3(normalize(surfaceToLight + vec3(0, 0, 1)));\n");
1581 lightBody.appendf("\tfloat colorScale = %s * pow(dot(normal, halfDir), %s);\n", ks, shininess);
1582 lightBody.appendf("\tvec3 color = lightColor * clamp(colorScale, 0.0, 1.0);\n");
1583 lightBody.appendf("\treturn vec4(color, max(max(color.r, color.g), color.b));\n");
1584 builder->getFragmentShaderBuilder()->emitFunction(kVec4f_GrSLType,
1586 SK_ARRAY_COUNT(gLightArgs),
1592 void GrGLSpecularLightingEffect::setData(const GrGLProgramDataManager& pdman,
1593 const GrProcessor& effect) {
1594 INHERITED::setData(pdman, effect);
1595 const GrSpecularLightingEffect& spec = effect.cast<GrSpecularLightingEffect>();
1596 pdman.set1f(fKSUni, spec.ks());
1597 pdman.set1f(fShininessUni, spec.shininess());
1600 ///////////////////////////////////////////////////////////////////////////////
1601 void GrGLLight::emitLightColorUniform(GrGLProgramBuilder* builder) {
1602 fColorUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
1603 kVec3f_GrSLType, "LightColor");
1606 void GrGLLight::emitLightColor(GrGLProgramBuilder* builder,
1607 const char *surfaceToLight) {
1608 builder->getFragmentShaderBuilder()->codeAppend(builder->getUniformCStr(this->lightColorUni()));
1611 void GrGLLight::setData(const GrGLProgramDataManager& pdman,
1612 const SkLight* light) const {
1613 setUniformPoint3(pdman, fColorUni, light->color() * SkScalarInvert(SkIntToScalar(255)));
1616 ///////////////////////////////////////////////////////////////////////////////
1618 void GrGLDistantLight::setData(const GrGLProgramDataManager& pdman,
1619 const SkLight* light) const {
1620 INHERITED::setData(pdman, light);
1621 SkASSERT(light->type() == SkLight::kDistant_LightType);
1622 const SkDistantLight* distantLight = static_cast<const SkDistantLight*>(light);
1623 setUniformNormal3(pdman, fDirectionUni, distantLight->direction());
1626 void GrGLDistantLight::emitSurfaceToLight(GrGLProgramBuilder* builder, const char* z) {
1628 fDirectionUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec3f_GrSLType,
1629 "LightDirection", &dir);
1630 builder->getFragmentShaderBuilder()->codeAppend(dir);
1633 ///////////////////////////////////////////////////////////////////////////////
1635 void GrGLPointLight::setData(const GrGLProgramDataManager& pdman,
1636 const SkLight* light) const {
1637 INHERITED::setData(pdman, light);
1638 SkASSERT(light->type() == SkLight::kPoint_LightType);
1639 const SkPointLight* pointLight = static_cast<const SkPointLight*>(light);
1640 setUniformPoint3(pdman, fLocationUni, pointLight->location());
1643 void GrGLPointLight::emitSurfaceToLight(GrGLProgramBuilder* builder, const char* z) {
1645 fLocationUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec3f_GrSLType,
1646 "LightLocation", &loc);
1647 GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
1648 fsBuilder->codeAppendf("normalize(%s - vec3(%s.xy, %s))",
1649 loc, fsBuilder->fragmentPosition(), z);
1652 ///////////////////////////////////////////////////////////////////////////////
1654 void GrGLSpotLight::setData(const GrGLProgramDataManager& pdman,
1655 const SkLight* light) const {
1656 INHERITED::setData(pdman, light);
1657 SkASSERT(light->type() == SkLight::kSpot_LightType);
1658 const SkSpotLight* spotLight = static_cast<const SkSpotLight *>(light);
1659 setUniformPoint3(pdman, fLocationUni, spotLight->location());
1660 pdman.set1f(fExponentUni, spotLight->specularExponent());
1661 pdman.set1f(fCosInnerConeAngleUni, spotLight->cosInnerConeAngle());
1662 pdman.set1f(fCosOuterConeAngleUni, spotLight->cosOuterConeAngle());
1663 pdman.set1f(fConeScaleUni, spotLight->coneScale());
1664 setUniformNormal3(pdman, fSUni, spotLight->s());
1667 void GrGLSpotLight::emitSurfaceToLight(GrGLProgramBuilder* builder, const char* z) {
1668 const char* location;
1669 fLocationUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
1670 kVec3f_GrSLType, "LightLocation", &location);
1672 GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
1673 fsBuilder->codeAppendf("normalize(%s - vec3(%s.xy, %s))",
1674 location, fsBuilder->fragmentPosition(), z);
1677 void GrGLSpotLight::emitLightColor(GrGLProgramBuilder* builder,
1678 const char *surfaceToLight) {
1680 const char* color = builder->getUniformCStr(this->lightColorUni()); // created by parent class.
1682 const char* exponent;
1683 const char* cosInner;
1684 const char* cosOuter;
1685 const char* coneScale;
1687 fExponentUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
1688 kFloat_GrSLType, "Exponent", &exponent);
1689 fCosInnerConeAngleUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
1690 kFloat_GrSLType, "CosInnerConeAngle", &cosInner);
1691 fCosOuterConeAngleUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
1692 kFloat_GrSLType, "CosOuterConeAngle", &cosOuter);
1693 fConeScaleUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
1694 kFloat_GrSLType, "ConeScale", &coneScale);
1695 fSUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
1696 kVec3f_GrSLType, "S", &s);
1698 static const GrGLShaderVar gLightColorArgs[] = {
1699 GrGLShaderVar("surfaceToLight", kVec3f_GrSLType)
1701 SkString lightColorBody;
1702 lightColorBody.appendf("\tfloat cosAngle = -dot(surfaceToLight, %s);\n", s);
1703 lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosOuter);
1704 lightColorBody.appendf("\t\treturn vec3(0);\n");
1705 lightColorBody.appendf("\t}\n");
1706 lightColorBody.appendf("\tfloat scale = pow(cosAngle, %s);\n", exponent);
1707 lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosInner);
1708 lightColorBody.appendf("\t\treturn %s * scale * (cosAngle - %s) * %s;\n",
1709 color, cosOuter, coneScale);
1710 lightColorBody.appendf("\t}\n");
1711 lightColorBody.appendf("\treturn %s;\n", color);
1712 GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
1713 fsBuilder->emitFunction(kVec3f_GrSLType,
1715 SK_ARRAY_COUNT(gLightColorArgs),
1717 lightColorBody.c_str(),
1720 fsBuilder->codeAppendf("%s(%s)", fLightColorFunc.c_str(), surfaceToLight);
1725 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingImageFilter)
1726 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDiffuseLightingImageFilter)
1727 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSpecularLightingImageFilter)
1728 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END