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"
13 #include "SkReadBuffer.h"
15 #include "SkWriteBuffer.h"
18 #include "GrContext.h"
19 #include "GrDrawContext.h"
20 #include "GrFragmentProcessor.h"
21 #include "GrInvariantOutput.h"
23 #include "effects/GrSingleTextureEffect.h"
24 #include "glsl/GrGLSLFragmentProcessor.h"
25 #include "glsl/GrGLSLFragmentShaderBuilder.h"
26 #include "glsl/GrGLSLProgramBuilder.h"
27 #include "glsl/GrGLSLProgramDataManager.h"
29 class GrGLDiffuseLightingEffect;
30 class GrGLSpecularLightingEffect;
33 typedef GrGLSLProgramDataManager::UniformHandle UniformHandle;
38 const SkScalar gOneThird = SkIntToScalar(1) / 3;
39 const SkScalar gTwoThirds = SkIntToScalar(2) / 3;
40 const SkScalar gOneHalf = 0.5f;
41 const SkScalar gOneQuarter = 0.25f;
44 void setUniformPoint3(const GrGLSLProgramDataManager& pdman, UniformHandle uni,
45 const SkPoint3& point) {
46 GR_STATIC_ASSERT(sizeof(SkPoint3) == 3 * sizeof(float));
47 pdman.set3fv(uni, 1, &point.fX);
50 void setUniformNormal3(const GrGLSLProgramDataManager& pdman, UniformHandle uni,
51 const SkPoint3& point) {
52 setUniformPoint3(pdman, uni, point);
56 // Shift matrix components to the left, as we advance pixels to the right.
57 inline void shiftMatrixLeft(int m[9]) {
66 static inline void fast_normalize(SkPoint3* vector) {
67 // add a tiny bit so we don't have to worry about divide-by-zero
68 SkScalar magSq = vector->dot(*vector) + SK_ScalarNearlyZero;
69 SkScalar scale = sk_float_rsqrt(magSq);
75 class DiffuseLightingType {
77 DiffuseLightingType(SkScalar kd)
79 SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight,
80 const SkPoint3& lightColor) const {
81 SkScalar colorScale = SkScalarMul(fKD, normal.dot(surfaceTolight));
82 colorScale = SkScalarClampMax(colorScale, SK_Scalar1);
83 SkPoint3 color = lightColor.makeScale(colorScale);
84 return SkPackARGB32(255,
85 SkClampMax(SkScalarRoundToInt(color.fX), 255),
86 SkClampMax(SkScalarRoundToInt(color.fY), 255),
87 SkClampMax(SkScalarRoundToInt(color.fZ), 255));
93 static SkScalar max_component(const SkPoint3& p) {
94 return p.x() > p.y() ? (p.x() > p.z() ? p.x() : p.z()) : (p.y() > p.z() ? p.y() : p.z());
97 class SpecularLightingType {
99 SpecularLightingType(SkScalar ks, SkScalar shininess)
100 : fKS(ks), fShininess(shininess) {}
101 SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight,
102 const SkPoint3& lightColor) const {
103 SkPoint3 halfDir(surfaceTolight);
104 halfDir.fZ += SK_Scalar1; // eye position is always (0, 0, 1)
105 fast_normalize(&halfDir);
106 SkScalar colorScale = SkScalarMul(fKS,
107 SkScalarPow(normal.dot(halfDir), fShininess));
108 colorScale = SkScalarClampMax(colorScale, SK_Scalar1);
109 SkPoint3 color = lightColor.makeScale(colorScale);
110 return SkPackARGB32(SkClampMax(SkScalarRoundToInt(max_component(color)), 255),
111 SkClampMax(SkScalarRoundToInt(color.fX), 255),
112 SkClampMax(SkScalarRoundToInt(color.fY), 255),
113 SkClampMax(SkScalarRoundToInt(color.fZ), 255));
120 inline SkScalar sobel(int a, int b, int c, int d, int e, int f, SkScalar scale) {
121 return SkScalarMul(SkIntToScalar(-a + b - 2 * c + 2 * d -e + f), scale);
124 inline SkPoint3 pointToNormal(SkScalar x, SkScalar y, SkScalar surfaceScale) {
125 SkPoint3 vector = SkPoint3::Make(SkScalarMul(-x, surfaceScale),
126 SkScalarMul(-y, surfaceScale),
128 fast_normalize(&vector);
132 inline SkPoint3 topLeftNormal(int m[9], SkScalar surfaceScale) {
133 return pointToNormal(sobel(0, 0, m[4], m[5], m[7], m[8], gTwoThirds),
134 sobel(0, 0, m[4], m[7], m[5], m[8], gTwoThirds),
138 inline SkPoint3 topNormal(int m[9], SkScalar surfaceScale) {
139 return pointToNormal(sobel( 0, 0, m[3], m[5], m[6], m[8], gOneThird),
140 sobel(m[3], m[6], m[4], m[7], m[5], m[8], gOneHalf),
144 inline SkPoint3 topRightNormal(int m[9], SkScalar surfaceScale) {
145 return pointToNormal(sobel( 0, 0, m[3], m[4], m[6], m[7], gTwoThirds),
146 sobel(m[3], m[6], m[4], m[7], 0, 0, gTwoThirds),
150 inline SkPoint3 leftNormal(int m[9], SkScalar surfaceScale) {
151 return pointToNormal(sobel(m[1], m[2], m[4], m[5], m[7], m[8], gOneHalf),
152 sobel( 0, 0, m[1], m[7], m[2], m[8], gOneThird),
157 inline SkPoint3 interiorNormal(int m[9], SkScalar surfaceScale) {
158 return pointToNormal(sobel(m[0], m[2], m[3], m[5], m[6], m[8], gOneQuarter),
159 sobel(m[0], m[6], m[1], m[7], m[2], m[8], gOneQuarter),
163 inline SkPoint3 rightNormal(int m[9], SkScalar surfaceScale) {
164 return pointToNormal(sobel(m[0], m[1], m[3], m[4], m[6], m[7], gOneHalf),
165 sobel(m[0], m[6], m[1], m[7], 0, 0, gOneThird),
169 inline SkPoint3 bottomLeftNormal(int m[9], SkScalar surfaceScale) {
170 return pointToNormal(sobel(m[1], m[2], m[4], m[5], 0, 0, gTwoThirds),
171 sobel( 0, 0, m[1], m[4], m[2], m[5], gTwoThirds),
175 inline SkPoint3 bottomNormal(int m[9], SkScalar surfaceScale) {
176 return pointToNormal(sobel(m[0], m[2], m[3], m[5], 0, 0, gOneThird),
177 sobel(m[0], m[3], m[1], m[4], m[2], m[5], gOneHalf),
181 inline SkPoint3 bottomRightNormal(int m[9], SkScalar surfaceScale) {
182 return pointToNormal(sobel(m[0], m[1], m[3], m[4], 0, 0, gTwoThirds),
183 sobel(m[0], m[3], m[1], m[4], 0, 0, gTwoThirds),
187 template <class LightingType, class LightType> void lightBitmap(const LightingType& lightingType,
188 const SkImageFilterLight* light,
191 SkScalar surfaceScale,
192 const SkIRect& bounds) {
193 SkASSERT(dst->width() == bounds.width() && dst->height() == bounds.height());
194 const LightType* l = static_cast<const LightType*>(light);
195 int left = bounds.left(), right = bounds.right();
196 int bottom = bounds.bottom();
197 int y = bounds.top();
198 SkPMColor* dptr = dst->getAddr32(0, 0);
201 const SkPMColor* row1 = src.getAddr32(x, y);
202 const SkPMColor* row2 = src.getAddr32(x, y + 1);
204 m[4] = SkGetPackedA32(*row1++);
205 m[5] = SkGetPackedA32(*row1++);
206 m[7] = SkGetPackedA32(*row2++);
207 m[8] = SkGetPackedA32(*row2++);
208 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
209 *dptr++ = lightingType.light(topLeftNormal(m, surfaceScale), surfaceToLight,
210 l->lightColor(surfaceToLight));
211 for (++x; x < right - 1; ++x)
214 m[5] = SkGetPackedA32(*row1++);
215 m[8] = SkGetPackedA32(*row2++);
216 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
217 *dptr++ = lightingType.light(topNormal(m, surfaceScale), surfaceToLight,
218 l->lightColor(surfaceToLight));
221 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
222 *dptr++ = lightingType.light(topRightNormal(m, surfaceScale), surfaceToLight,
223 l->lightColor(surfaceToLight));
226 for (++y; y < bottom - 1; ++y) {
228 const SkPMColor* row0 = src.getAddr32(x, y - 1);
229 const SkPMColor* row1 = src.getAddr32(x, y);
230 const SkPMColor* row2 = src.getAddr32(x, y + 1);
232 m[1] = SkGetPackedA32(*row0++);
233 m[2] = SkGetPackedA32(*row0++);
234 m[4] = SkGetPackedA32(*row1++);
235 m[5] = SkGetPackedA32(*row1++);
236 m[7] = SkGetPackedA32(*row2++);
237 m[8] = SkGetPackedA32(*row2++);
238 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
239 *dptr++ = lightingType.light(leftNormal(m, surfaceScale), surfaceToLight,
240 l->lightColor(surfaceToLight));
241 for (++x; x < right - 1; ++x) {
243 m[2] = SkGetPackedA32(*row0++);
244 m[5] = SkGetPackedA32(*row1++);
245 m[8] = SkGetPackedA32(*row2++);
246 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
247 *dptr++ = lightingType.light(interiorNormal(m, surfaceScale), surfaceToLight,
248 l->lightColor(surfaceToLight));
251 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
252 *dptr++ = lightingType.light(rightNormal(m, surfaceScale), surfaceToLight,
253 l->lightColor(surfaceToLight));
258 const SkPMColor* row0 = src.getAddr32(x, bottom - 2);
259 const SkPMColor* row1 = src.getAddr32(x, bottom - 1);
261 m[1] = SkGetPackedA32(*row0++);
262 m[2] = SkGetPackedA32(*row0++);
263 m[4] = SkGetPackedA32(*row1++);
264 m[5] = SkGetPackedA32(*row1++);
265 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
266 *dptr++ = lightingType.light(bottomLeftNormal(m, surfaceScale), surfaceToLight,
267 l->lightColor(surfaceToLight));
268 for (++x; x < right - 1; ++x)
271 m[2] = SkGetPackedA32(*row0++);
272 m[5] = SkGetPackedA32(*row1++);
273 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
274 *dptr++ = lightingType.light(bottomNormal(m, surfaceScale), surfaceToLight,
275 l->lightColor(surfaceToLight));
278 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
279 *dptr++ = lightingType.light(bottomRightNormal(m, surfaceScale), surfaceToLight,
280 l->lightColor(surfaceToLight));
284 SkPoint3 readPoint3(SkReadBuffer& buffer) {
286 point.fX = buffer.readScalar();
287 point.fY = buffer.readScalar();
288 point.fZ = buffer.readScalar();
289 buffer.validate(SkScalarIsFinite(point.fX) &&
290 SkScalarIsFinite(point.fY) &&
291 SkScalarIsFinite(point.fZ));
295 void writePoint3(const SkPoint3& point, SkWriteBuffer& buffer) {
296 buffer.writeScalar(point.fX);
297 buffer.writeScalar(point.fY);
298 buffer.writeScalar(point.fZ);
302 kTopLeft_BoundaryMode,
304 kTopRight_BoundaryMode,
306 kInterior_BoundaryMode,
308 kBottomLeft_BoundaryMode,
309 kBottom_BoundaryMode,
310 kBottomRight_BoundaryMode,
315 class SkLightingImageFilterInternal : public SkLightingImageFilter {
317 SkLightingImageFilterInternal(SkImageFilterLight* light,
318 SkScalar surfaceScale,
319 SkImageFilter* input,
320 const CropRect* cropRect)
321 : INHERITED(light, surfaceScale, input, cropRect) {}
324 bool canFilterImageGPU() const override { return true; }
325 bool filterImageGPU(Proxy*, const SkBitmap& src, const Context&,
326 SkBitmap* result, SkIPoint* offset) const override;
327 virtual GrFragmentProcessor* getFragmentProcessor(GrTexture*,
329 const SkIRect& bounds,
330 BoundaryMode boundaryMode) const = 0;
334 void drawRect(GrDrawContext* drawContext,
336 const SkMatrix& matrix,
338 const SkRect& dstRect,
339 BoundaryMode boundaryMode,
340 const SkIRect& bounds) const;
342 typedef SkLightingImageFilter INHERITED;
346 void SkLightingImageFilterInternal::drawRect(GrDrawContext* drawContext,
348 const SkMatrix& matrix,
350 const SkRect& dstRect,
351 BoundaryMode boundaryMode,
352 const SkIRect& bounds) const {
353 SkRect srcRect = dstRect.makeOffset(SkIntToScalar(bounds.x()), SkIntToScalar(bounds.y()));
355 GrFragmentProcessor* fp = this->getFragmentProcessor(src, matrix, bounds, boundaryMode);
356 paint.addColorFragmentProcessor(fp)->unref();
357 drawContext->fillRectToRect(clip, paint, SkMatrix::I(), dstRect, srcRect);
360 bool SkLightingImageFilterInternal::filterImageGPU(Proxy* proxy,
364 SkIPoint* offset) const {
365 SkBitmap input = src;
366 SkIPoint srcOffset = SkIPoint::Make(0, 0);
367 if (!this->filterInputGPU(0, proxy, src, ctx, &input, &srcOffset)) {
371 if (!this->applyCropRect(ctx, proxy, input, &srcOffset, &bounds, &input)) {
374 SkRect dstRect = SkRect::MakeWH(SkIntToScalar(bounds.width()),
375 SkIntToScalar(bounds.height()));
376 GrTexture* srcTexture = input.getTexture();
377 GrContext* context = srcTexture->getContext();
380 desc.fFlags = kRenderTarget_GrSurfaceFlag,
381 desc.fWidth = bounds.width();
382 desc.fHeight = bounds.height();
383 desc.fConfig = kRGBA_8888_GrPixelConfig;
385 auto constraint = GrTextureProvider::FromImageFilter(ctx.sizeConstraint());
386 SkAutoTUnref<GrTexture> dst(context->textureProvider()->createTexture(desc, constraint));
392 GrClip clip(dstRect);
394 offset->fX = bounds.left();
395 offset->fY = bounds.top();
396 SkMatrix matrix(ctx.ctm());
397 matrix.postTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
398 bounds.offset(-srcOffset);
399 SkRect topLeft = SkRect::MakeXYWH(0, 0, 1, 1);
400 SkRect top = SkRect::MakeXYWH(1, 0, dstRect.width() - 2, 1);
401 SkRect topRight = SkRect::MakeXYWH(dstRect.width() - 1, 0, 1, 1);
402 SkRect left = SkRect::MakeXYWH(0, 1, 1, dstRect.height() - 2);
403 SkRect interior = dstRect.makeInset(1, 1);
404 SkRect right = SkRect::MakeXYWH(dstRect.width() - 1, 1, 1, dstRect.height() - 2);
405 SkRect bottomLeft = SkRect::MakeXYWH(0, dstRect.height() - 1, 1, 1);
406 SkRect bottom = SkRect::MakeXYWH(1, dstRect.height() - 1, dstRect.width() - 2, 1);
407 SkRect bottomRight = SkRect::MakeXYWH(dstRect.width() - 1, dstRect.height() - 1, 1, 1);
409 SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(dst->asRenderTarget()));
414 this->drawRect(drawContext, srcTexture, matrix, clip, topLeft, kTopLeft_BoundaryMode, bounds);
415 this->drawRect(drawContext, srcTexture, matrix, clip, top, kTop_BoundaryMode, bounds);
416 this->drawRect(drawContext, srcTexture, matrix, clip, topRight, kTopRight_BoundaryMode,
418 this->drawRect(drawContext, srcTexture, matrix, clip, left, kLeft_BoundaryMode, bounds);
419 this->drawRect(drawContext, srcTexture, matrix, clip, interior, kInterior_BoundaryMode,
421 this->drawRect(drawContext, srcTexture, matrix, clip, right, kRight_BoundaryMode, bounds);
422 this->drawRect(drawContext, srcTexture, matrix, clip, bottomLeft, kBottomLeft_BoundaryMode,
424 this->drawRect(drawContext, srcTexture, matrix, clip, bottom, kBottom_BoundaryMode, bounds);
425 this->drawRect(drawContext, srcTexture, matrix, clip, bottomRight,
426 kBottomRight_BoundaryMode, bounds);
427 WrapTexture(dst, bounds.width(), bounds.height(), result);
432 class SkDiffuseLightingImageFilter : public SkLightingImageFilterInternal {
434 static SkImageFilter* Create(SkImageFilterLight* light, SkScalar surfaceScale,
435 SkScalar kd, SkImageFilter*,
438 SK_TO_STRING_OVERRIDE()
439 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDiffuseLightingImageFilter)
440 SkScalar kd() const { return fKD; }
443 SkDiffuseLightingImageFilter(SkImageFilterLight* light, SkScalar surfaceScale,
444 SkScalar kd, SkImageFilter* input, const CropRect* cropRect);
445 void flatten(SkWriteBuffer& buffer) const override;
446 bool onFilterImage(Proxy*, const SkBitmap& src, const Context&,
447 SkBitmap* result, SkIPoint* offset) const override;
449 GrFragmentProcessor* getFragmentProcessor(GrTexture*, const SkMatrix&, const SkIRect& bounds,
450 BoundaryMode) const override;
454 friend class SkLightingImageFilter;
455 typedef SkLightingImageFilterInternal INHERITED;
459 class SkSpecularLightingImageFilter : public SkLightingImageFilterInternal {
461 static SkImageFilter* Create(SkImageFilterLight* light, SkScalar surfaceScale,
462 SkScalar ks, SkScalar shininess, SkImageFilter*, const CropRect*);
464 SK_TO_STRING_OVERRIDE()
465 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSpecularLightingImageFilter)
467 SkScalar ks() const { return fKS; }
468 SkScalar shininess() const { return fShininess; }
471 SkSpecularLightingImageFilter(SkImageFilterLight* light, SkScalar surfaceScale, SkScalar ks,
472 SkScalar shininess, SkImageFilter* input, const CropRect*);
473 void flatten(SkWriteBuffer& buffer) const override;
474 bool onFilterImage(Proxy*, const SkBitmap& src, const Context&,
475 SkBitmap* result, SkIPoint* offset) const override;
477 GrFragmentProcessor* getFragmentProcessor(GrTexture*, const SkMatrix&, const SkIRect& bounds,
478 BoundaryMode) const override;
484 friend class SkLightingImageFilter;
485 typedef SkLightingImageFilterInternal INHERITED;
490 class GrLightingEffect : public GrSingleTextureEffect {
492 GrLightingEffect(GrTexture* texture, const SkImageFilterLight* light, SkScalar surfaceScale,
493 const SkMatrix& matrix, BoundaryMode boundaryMode);
494 virtual ~GrLightingEffect();
496 const SkImageFilterLight* light() const { return fLight; }
497 SkScalar surfaceScale() const { return fSurfaceScale; }
498 const SkMatrix& filterMatrix() const { return fFilterMatrix; }
499 BoundaryMode boundaryMode() const { return fBoundaryMode; }
502 bool onIsEqual(const GrFragmentProcessor&) const override;
504 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
505 // lighting shaders are complicated. We just throw up our hands.
506 inout->mulByUnknownFourComponents();
510 const SkImageFilterLight* fLight;
511 SkScalar fSurfaceScale;
512 SkMatrix fFilterMatrix;
513 BoundaryMode fBoundaryMode;
515 typedef GrSingleTextureEffect INHERITED;
518 class GrDiffuseLightingEffect : public GrLightingEffect {
520 static GrFragmentProcessor* Create(GrTexture* texture,
521 const SkImageFilterLight* light,
522 SkScalar surfaceScale,
523 const SkMatrix& matrix,
525 BoundaryMode boundaryMode) {
526 return new GrDiffuseLightingEffect(texture, light, surfaceScale, matrix, kd, boundaryMode);
529 const char* name() const override { return "DiffuseLighting"; }
531 SkScalar kd() const { return fKD; }
534 GrGLSLFragmentProcessor* onCreateGLInstance() const override;
536 void onGetGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
538 bool onIsEqual(const GrFragmentProcessor&) const override;
540 GrDiffuseLightingEffect(GrTexture* texture,
541 const SkImageFilterLight* light,
542 SkScalar surfaceScale,
543 const SkMatrix& matrix,
545 BoundaryMode boundaryMode);
547 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
548 typedef GrLightingEffect INHERITED;
552 class GrSpecularLightingEffect : public GrLightingEffect {
554 static GrFragmentProcessor* Create(GrTexture* texture,
555 const SkImageFilterLight* light,
556 SkScalar surfaceScale,
557 const SkMatrix& matrix,
560 BoundaryMode boundaryMode) {
561 return new GrSpecularLightingEffect(texture, light, surfaceScale, matrix, ks, shininess,
565 const char* name() const override { return "SpecularLighting"; }
567 GrGLSLFragmentProcessor* onCreateGLInstance() const override;
569 SkScalar ks() const { return fKS; }
570 SkScalar shininess() const { return fShininess; }
573 void onGetGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
575 bool onIsEqual(const GrFragmentProcessor&) const override;
577 GrSpecularLightingEffect(GrTexture* texture,
578 const SkImageFilterLight* light,
579 SkScalar surfaceScale,
580 const SkMatrix& matrix,
583 BoundaryMode boundaryMode);
585 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
586 typedef GrLightingEffect INHERITED;
591 ///////////////////////////////////////////////////////////////////////////////
595 virtual ~GrGLLight() {}
598 * This is called by GrGLLightingEffect::emitCode() before either of the two virtual functions
599 * below. It adds a vec3f uniform visible in the FS that represents the constant light color.
601 void emitLightColorUniform(GrGLSLFPBuilder*);
604 * These two functions are called from GrGLLightingEffect's emitCode() function.
605 * emitSurfaceToLight places an expression in param out that is the vector from the surface to
606 * the light. The expression will be used in the FS. emitLightColor writes an expression into
607 * the FS that is the color of the light. Either function may add functions and/or uniforms to
608 * the FS. The default of emitLightColor appends the name of the constant light color uniform
609 * and so this function only needs to be overridden if the light color varies spatially.
611 virtual void emitSurfaceToLight(GrGLSLFPBuilder*, const char* z) = 0;
612 virtual void emitLightColor(GrGLSLFPBuilder*, const char *surfaceToLight);
614 // This is called from GrGLLightingEffect's setData(). Subclasses of GrGLLight must call
615 // INHERITED::setData().
616 virtual void setData(const GrGLSLProgramDataManager&, const SkImageFilterLight* light) const;
620 * Gets the constant light color uniform. Subclasses can use this in their emitLightColor
623 UniformHandle lightColorUni() const { return fColorUni; }
626 UniformHandle fColorUni;
628 typedef SkRefCnt INHERITED;
631 ///////////////////////////////////////////////////////////////////////////////
633 class GrGLDistantLight : public GrGLLight {
635 virtual ~GrGLDistantLight() {}
636 void setData(const GrGLSLProgramDataManager&, const SkImageFilterLight* light) const override;
637 void emitSurfaceToLight(GrGLSLFPBuilder*, const char* z) override;
640 typedef GrGLLight INHERITED;
641 UniformHandle fDirectionUni;
644 ///////////////////////////////////////////////////////////////////////////////
646 class GrGLPointLight : public GrGLLight {
648 virtual ~GrGLPointLight() {}
649 void setData(const GrGLSLProgramDataManager&, const SkImageFilterLight* light) const override;
650 void emitSurfaceToLight(GrGLSLFPBuilder*, const char* z) override;
653 typedef GrGLLight INHERITED;
654 UniformHandle fLocationUni;
657 ///////////////////////////////////////////////////////////////////////////////
659 class GrGLSpotLight : public GrGLLight {
661 virtual ~GrGLSpotLight() {}
662 void setData(const GrGLSLProgramDataManager&, const SkImageFilterLight* light) const override;
663 void emitSurfaceToLight(GrGLSLFPBuilder*, const char* z) override;
664 void emitLightColor(GrGLSLFPBuilder*, const char *surfaceToLight) override;
667 typedef GrGLLight INHERITED;
669 SkString fLightColorFunc;
670 UniformHandle fLocationUni;
671 UniformHandle fExponentUni;
672 UniformHandle fCosOuterConeAngleUni;
673 UniformHandle fCosInnerConeAngleUni;
674 UniformHandle fConeScaleUni;
685 ///////////////////////////////////////////////////////////////////////////////
687 class SkImageFilterLight : public SkRefCnt {
696 virtual LightType type() const = 0;
697 const SkPoint3& color() const { return fColor; }
698 virtual GrGLLight* createGLLight() const = 0;
699 virtual bool isEqual(const SkImageFilterLight& other) const {
700 return fColor == other.fColor;
702 // Called to know whether the generated GrGLLight will require access to the fragment position.
703 virtual bool requiresFragmentPosition() const = 0;
704 virtual SkImageFilterLight* transform(const SkMatrix& matrix) const = 0;
706 // Defined below SkLight's subclasses.
707 void flattenLight(SkWriteBuffer& buffer) const;
708 static SkImageFilterLight* UnflattenLight(SkReadBuffer& buffer);
711 SkImageFilterLight(SkColor color) {
712 fColor = SkPoint3::Make(SkIntToScalar(SkColorGetR(color)),
713 SkIntToScalar(SkColorGetG(color)),
714 SkIntToScalar(SkColorGetB(color)));
716 SkImageFilterLight(const SkPoint3& color)
718 SkImageFilterLight(SkReadBuffer& buffer) {
719 fColor = readPoint3(buffer);
722 virtual void onFlattenLight(SkWriteBuffer& buffer) const = 0;
726 typedef SkRefCnt INHERITED;
730 ///////////////////////////////////////////////////////////////////////////////
732 class SkDistantLight : public SkImageFilterLight {
734 SkDistantLight(const SkPoint3& direction, SkColor color)
735 : INHERITED(color), fDirection(direction) {
738 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
741 const SkPoint3& lightColor(const SkPoint3&) const { return this->color(); }
742 LightType type() const override { return kDistant_LightType; }
743 const SkPoint3& direction() const { return fDirection; }
744 GrGLLight* createGLLight() const override {
746 return new GrGLDistantLight;
748 SkDEBUGFAIL("Should not call in GPU-less build");
752 bool requiresFragmentPosition() const override { return false; }
754 bool isEqual(const SkImageFilterLight& other) const override {
755 if (other.type() != kDistant_LightType) {
759 const SkDistantLight& o = static_cast<const SkDistantLight&>(other);
760 return INHERITED::isEqual(other) &&
761 fDirection == o.fDirection;
764 SkDistantLight(SkReadBuffer& buffer) : INHERITED(buffer) {
765 fDirection = readPoint3(buffer);
769 SkDistantLight(const SkPoint3& direction, const SkPoint3& color)
770 : INHERITED(color), fDirection(direction) {
772 SkImageFilterLight* transform(const SkMatrix& matrix) const override {
773 return new SkDistantLight(direction(), color());
775 void onFlattenLight(SkWriteBuffer& buffer) const override {
776 writePoint3(fDirection, buffer);
782 typedef SkImageFilterLight INHERITED;
785 ///////////////////////////////////////////////////////////////////////////////
787 class SkPointLight : public SkImageFilterLight {
789 SkPointLight(const SkPoint3& location, SkColor color)
790 : INHERITED(color), fLocation(location) {}
792 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
793 SkPoint3 direction = SkPoint3::Make(fLocation.fX - SkIntToScalar(x),
794 fLocation.fY - SkIntToScalar(y),
795 fLocation.fZ - SkScalarMul(SkIntToScalar(z),
797 fast_normalize(&direction);
800 const SkPoint3& lightColor(const SkPoint3&) const { return this->color(); }
801 LightType type() const override { return kPoint_LightType; }
802 const SkPoint3& location() const { return fLocation; }
803 GrGLLight* createGLLight() const override {
805 return new GrGLPointLight;
807 SkDEBUGFAIL("Should not call in GPU-less build");
811 bool requiresFragmentPosition() const override { return true; }
812 bool isEqual(const SkImageFilterLight& other) const override {
813 if (other.type() != kPoint_LightType) {
816 const SkPointLight& o = static_cast<const SkPointLight&>(other);
817 return INHERITED::isEqual(other) &&
818 fLocation == o.fLocation;
820 SkImageFilterLight* transform(const SkMatrix& matrix) const override {
821 SkPoint location2 = SkPoint::Make(fLocation.fX, fLocation.fY);
822 matrix.mapPoints(&location2, 1);
823 // Use X scale and Y scale on Z and average the result
824 SkPoint locationZ = SkPoint::Make(fLocation.fZ, fLocation.fZ);
825 matrix.mapVectors(&locationZ, 1);
826 SkPoint3 location = SkPoint3::Make(location2.fX,
828 SkScalarAve(locationZ.fX, locationZ.fY));
829 return new SkPointLight(location, color());
832 SkPointLight(SkReadBuffer& buffer) : INHERITED(buffer) {
833 fLocation = readPoint3(buffer);
837 SkPointLight(const SkPoint3& location, const SkPoint3& color)
838 : INHERITED(color), fLocation(location) {}
839 void onFlattenLight(SkWriteBuffer& buffer) const override {
840 writePoint3(fLocation, buffer);
846 typedef SkImageFilterLight INHERITED;
849 ///////////////////////////////////////////////////////////////////////////////
851 class SkSpotLight : public SkImageFilterLight {
853 SkSpotLight(const SkPoint3& location,
854 const SkPoint3& target,
855 SkScalar specularExponent,
856 SkScalar cutoffAngle,
861 fSpecularExponent(SkScalarPin(specularExponent, kSpecularExponentMin, kSpecularExponentMax))
863 fS = target - location;
865 fCosOuterConeAngle = SkScalarCos(SkDegreesToRadians(cutoffAngle));
866 const SkScalar antiAliasThreshold = 0.016f;
867 fCosInnerConeAngle = fCosOuterConeAngle + antiAliasThreshold;
868 fConeScale = SkScalarInvert(antiAliasThreshold);
871 SkImageFilterLight* transform(const SkMatrix& matrix) const override {
872 SkPoint location2 = SkPoint::Make(fLocation.fX, fLocation.fY);
873 matrix.mapPoints(&location2, 1);
874 // Use X scale and Y scale on Z and average the result
875 SkPoint locationZ = SkPoint::Make(fLocation.fZ, fLocation.fZ);
876 matrix.mapVectors(&locationZ, 1);
877 SkPoint3 location = SkPoint3::Make(location2.fX, location2.fY,
878 SkScalarAve(locationZ.fX, locationZ.fY));
879 SkPoint target2 = SkPoint::Make(fTarget.fX, fTarget.fY);
880 matrix.mapPoints(&target2, 1);
881 SkPoint targetZ = SkPoint::Make(fTarget.fZ, fTarget.fZ);
882 matrix.mapVectors(&targetZ, 1);
883 SkPoint3 target = SkPoint3::Make(target2.fX, target2.fY,
884 SkScalarAve(targetZ.fX, targetZ.fY));
885 SkPoint3 s = target - location;
887 return new SkSpotLight(location,
897 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
898 SkPoint3 direction = SkPoint3::Make(fLocation.fX - SkIntToScalar(x),
899 fLocation.fY - SkIntToScalar(y),
900 fLocation.fZ - SkScalarMul(SkIntToScalar(z),
902 fast_normalize(&direction);
905 SkPoint3 lightColor(const SkPoint3& surfaceToLight) const {
906 SkScalar cosAngle = -surfaceToLight.dot(fS);
908 if (cosAngle >= fCosOuterConeAngle) {
909 scale = SkScalarPow(cosAngle, fSpecularExponent);
910 if (cosAngle < fCosInnerConeAngle) {
911 scale = SkScalarMul(scale, cosAngle - fCosOuterConeAngle);
915 return this->color().makeScale(scale);
917 GrGLLight* createGLLight() const override {
919 return new GrGLSpotLight;
921 SkDEBUGFAIL("Should not call in GPU-less build");
925 bool requiresFragmentPosition() const override { return true; }
926 LightType type() const override { return kSpot_LightType; }
927 const SkPoint3& location() const { return fLocation; }
928 const SkPoint3& target() const { return fTarget; }
929 SkScalar specularExponent() const { return fSpecularExponent; }
930 SkScalar cosInnerConeAngle() const { return fCosInnerConeAngle; }
931 SkScalar cosOuterConeAngle() const { return fCosOuterConeAngle; }
932 SkScalar coneScale() const { return fConeScale; }
933 const SkPoint3& s() const { return fS; }
935 SkSpotLight(SkReadBuffer& buffer) : INHERITED(buffer) {
936 fLocation = readPoint3(buffer);
937 fTarget = readPoint3(buffer);
938 fSpecularExponent = buffer.readScalar();
939 fCosOuterConeAngle = buffer.readScalar();
940 fCosInnerConeAngle = buffer.readScalar();
941 fConeScale = buffer.readScalar();
942 fS = readPoint3(buffer);
943 buffer.validate(SkScalarIsFinite(fSpecularExponent) &&
944 SkScalarIsFinite(fCosOuterConeAngle) &&
945 SkScalarIsFinite(fCosInnerConeAngle) &&
946 SkScalarIsFinite(fConeScale));
949 SkSpotLight(const SkPoint3& location,
950 const SkPoint3& target,
951 SkScalar specularExponent,
952 SkScalar cosOuterConeAngle,
953 SkScalar cosInnerConeAngle,
956 const SkPoint3& color)
960 fSpecularExponent(specularExponent),
961 fCosOuterConeAngle(cosOuterConeAngle),
962 fCosInnerConeAngle(cosInnerConeAngle),
963 fConeScale(coneScale),
967 void onFlattenLight(SkWriteBuffer& buffer) const override {
968 writePoint3(fLocation, buffer);
969 writePoint3(fTarget, buffer);
970 buffer.writeScalar(fSpecularExponent);
971 buffer.writeScalar(fCosOuterConeAngle);
972 buffer.writeScalar(fCosInnerConeAngle);
973 buffer.writeScalar(fConeScale);
974 writePoint3(fS, buffer);
977 bool isEqual(const SkImageFilterLight& other) const override {
978 if (other.type() != kSpot_LightType) {
982 const SkSpotLight& o = static_cast<const SkSpotLight&>(other);
983 return INHERITED::isEqual(other) &&
984 fLocation == o.fLocation &&
985 fTarget == o.fTarget &&
986 fSpecularExponent == o.fSpecularExponent &&
987 fCosOuterConeAngle == o.fCosOuterConeAngle;
991 static const SkScalar kSpecularExponentMin;
992 static const SkScalar kSpecularExponentMax;
996 SkScalar fSpecularExponent;
997 SkScalar fCosOuterConeAngle;
998 SkScalar fCosInnerConeAngle;
1002 typedef SkImageFilterLight INHERITED;
1005 // According to the spec, the specular term should be in the range [1, 128] :
1006 // http://www.w3.org/TR/SVG/filters.html#feSpecularLightingSpecularExponentAttribute
1007 const SkScalar SkSpotLight::kSpecularExponentMin = 1.0f;
1008 const SkScalar SkSpotLight::kSpecularExponentMax = 128.0f;
1010 ///////////////////////////////////////////////////////////////////////////////
1012 void SkImageFilterLight::flattenLight(SkWriteBuffer& buffer) const {
1013 // Write type first, then baseclass, then subclass.
1014 buffer.writeInt(this->type());
1015 writePoint3(fColor, buffer);
1016 this->onFlattenLight(buffer);
1019 /*static*/ SkImageFilterLight* SkImageFilterLight::UnflattenLight(SkReadBuffer& buffer) {
1021 const SkImageFilterLight::LightType type = (SkImageFilterLight::LightType)buffer.readInt();
1023 // Each of these constructors must first call SkLight's, so we'll read the baseclass
1024 // then subclass, same order as flattenLight.
1025 case SkImageFilterLight::kDistant_LightType:
1026 return new SkDistantLight(buffer);
1027 case SkImageFilterLight::kPoint_LightType:
1028 return new SkPointLight(buffer);
1029 case SkImageFilterLight::kSpot_LightType:
1030 return new SkSpotLight(buffer);
1032 SkDEBUGFAIL("Unknown LightType.");
1033 buffer.validate(false);
1037 ///////////////////////////////////////////////////////////////////////////////
1039 SkLightingImageFilter::SkLightingImageFilter(SkImageFilterLight* light, SkScalar surfaceScale,
1040 SkImageFilter* input, const CropRect* cropRect)
1041 : INHERITED(1, &input, cropRect)
1042 , fLight(SkRef(light))
1043 , fSurfaceScale(surfaceScale / 255)
1046 SkImageFilter* SkLightingImageFilter::CreateDistantLitDiffuse(const SkPoint3& direction,
1048 SkScalar surfaceScale,
1050 SkImageFilter* input,
1051 const CropRect* cropRect) {
1052 SkAutoTUnref<SkImageFilterLight> light(new SkDistantLight(direction, lightColor));
1053 return SkDiffuseLightingImageFilter::Create(light, surfaceScale, kd, input, cropRect);
1056 SkImageFilter* SkLightingImageFilter::CreatePointLitDiffuse(const SkPoint3& location,
1058 SkScalar surfaceScale,
1060 SkImageFilter* input,
1061 const CropRect* cropRect) {
1062 SkAutoTUnref<SkImageFilterLight> light(new SkPointLight(location, lightColor));
1063 return SkDiffuseLightingImageFilter::Create(light, surfaceScale, kd, input, cropRect);
1066 SkImageFilter* SkLightingImageFilter::CreateSpotLitDiffuse(const SkPoint3& location,
1067 const SkPoint3& target,
1068 SkScalar specularExponent,
1069 SkScalar cutoffAngle,
1071 SkScalar surfaceScale,
1073 SkImageFilter* input,
1074 const CropRect* cropRect) {
1075 SkAutoTUnref<SkImageFilterLight> light(
1076 new SkSpotLight(location, target, specularExponent, cutoffAngle, lightColor));
1077 return SkDiffuseLightingImageFilter::Create(light, surfaceScale, kd, input, cropRect);
1080 SkImageFilter* SkLightingImageFilter::CreateDistantLitSpecular(const SkPoint3& direction,
1082 SkScalar surfaceScale,
1085 SkImageFilter* input,
1086 const CropRect* cropRect) {
1087 SkAutoTUnref<SkImageFilterLight> light(new SkDistantLight(direction, lightColor));
1088 return SkSpecularLightingImageFilter::Create(light, surfaceScale, ks, shine, input, cropRect);
1091 SkImageFilter* SkLightingImageFilter::CreatePointLitSpecular(const SkPoint3& location,
1093 SkScalar surfaceScale,
1096 SkImageFilter* input,
1097 const CropRect* cropRect) {
1098 SkAutoTUnref<SkImageFilterLight> light(new SkPointLight(location, lightColor));
1099 return SkSpecularLightingImageFilter::Create(light, surfaceScale, ks, shine, input, cropRect);
1102 SkImageFilter* SkLightingImageFilter::CreateSpotLitSpecular(const SkPoint3& location,
1103 const SkPoint3& target,
1104 SkScalar specularExponent,
1105 SkScalar cutoffAngle,
1107 SkScalar surfaceScale,
1110 SkImageFilter* input,
1111 const CropRect* cropRect) {
1112 SkAutoTUnref<SkImageFilterLight> light(
1113 new SkSpotLight(location, target, specularExponent, cutoffAngle, lightColor));
1114 return SkSpecularLightingImageFilter::Create(light, surfaceScale, ks, shine, input, cropRect);
1117 SkLightingImageFilter::~SkLightingImageFilter() {}
1119 void SkLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
1120 this->INHERITED::flatten(buffer);
1121 fLight->flattenLight(buffer);
1122 buffer.writeScalar(fSurfaceScale * 255);
1125 ///////////////////////////////////////////////////////////////////////////////
1127 SkImageFilter* SkDiffuseLightingImageFilter::Create(SkImageFilterLight* light,
1128 SkScalar surfaceScale,
1130 SkImageFilter* input,
1131 const CropRect* cropRect) {
1132 if (nullptr == light) {
1135 if (!SkScalarIsFinite(surfaceScale) || !SkScalarIsFinite(kd)) {
1138 // According to the spec, kd can be any non-negative number :
1139 // http://www.w3.org/TR/SVG/filters.html#feDiffuseLightingElement
1143 return new SkDiffuseLightingImageFilter(light, surfaceScale, kd, input, cropRect);
1146 SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkImageFilterLight* light,
1147 SkScalar surfaceScale,
1149 SkImageFilter* input,
1150 const CropRect* cropRect)
1151 : INHERITED(light, surfaceScale, input, cropRect),
1156 SkFlattenable* SkDiffuseLightingImageFilter::CreateProc(SkReadBuffer& buffer) {
1157 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
1158 SkAutoTUnref<SkImageFilterLight> light(SkImageFilterLight::UnflattenLight(buffer));
1159 SkScalar surfaceScale = buffer.readScalar();
1160 SkScalar kd = buffer.readScalar();
1161 return Create(light, surfaceScale, kd, common.getInput(0), &common.cropRect());
1164 void SkDiffuseLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
1165 this->INHERITED::flatten(buffer);
1166 buffer.writeScalar(fKD);
1169 bool SkDiffuseLightingImageFilter::onFilterImage(Proxy* proxy,
1170 const SkBitmap& source,
1173 SkIPoint* offset) const {
1174 SkBitmap src = source;
1175 SkIPoint srcOffset = SkIPoint::Make(0, 0);
1176 if (!this->filterInput(0, proxy, source, ctx, &src, &srcOffset)) {
1180 if (src.colorType() != kN32_SkColorType) {
1184 if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) {
1188 if (bounds.width() < 2 || bounds.height() < 2) {
1192 SkAutoLockPixels alp(src);
1193 if (!src.getPixels()) {
1197 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
1201 *dst = device->accessBitmap(false);
1202 SkAutoLockPixels alp_dst(*dst);
1204 SkMatrix matrix(ctx.ctm());
1205 matrix.postTranslate(SkIntToScalar(-srcOffset.x()), SkIntToScalar(-srcOffset.y()));
1206 SkAutoTUnref<SkImageFilterLight> transformedLight(light()->transform(matrix));
1208 DiffuseLightingType lightingType(fKD);
1209 offset->fX = bounds.left();
1210 offset->fY = bounds.top();
1211 bounds.offset(-srcOffset);
1212 switch (transformedLight->type()) {
1213 case SkImageFilterLight::kDistant_LightType:
1214 lightBitmap<DiffuseLightingType, SkDistantLight>(lightingType,
1221 case SkImageFilterLight::kPoint_LightType:
1222 lightBitmap<DiffuseLightingType, SkPointLight>(lightingType,
1229 case SkImageFilterLight::kSpot_LightType:
1230 lightBitmap<DiffuseLightingType, SkSpotLight>(lightingType,
1242 #ifndef SK_IGNORE_TO_STRING
1243 void SkDiffuseLightingImageFilter::toString(SkString* str) const {
1244 str->appendf("SkDiffuseLightingImageFilter: (");
1245 str->appendf("kD: %f\n", fKD);
1251 GrFragmentProcessor* SkDiffuseLightingImageFilter::getFragmentProcessor(
1253 const SkMatrix& matrix,
1255 BoundaryMode boundaryMode
1257 SkScalar scale = SkScalarMul(this->surfaceScale(), SkIntToScalar(255));
1258 return GrDiffuseLightingEffect::Create(texture, this->light(), scale, matrix, this->kd(),
1263 ///////////////////////////////////////////////////////////////////////////////
1265 SkImageFilter* SkSpecularLightingImageFilter::Create(SkImageFilterLight* light,
1266 SkScalar surfaceScale,
1269 SkImageFilter* input,
1270 const CropRect* cropRect) {
1271 if (nullptr == light) {
1274 if (!SkScalarIsFinite(surfaceScale) || !SkScalarIsFinite(ks) || !SkScalarIsFinite(shininess)) {
1277 // According to the spec, ks can be any non-negative number :
1278 // http://www.w3.org/TR/SVG/filters.html#feSpecularLightingElement
1282 return new SkSpecularLightingImageFilter(light, surfaceScale, ks, shininess, input, cropRect);
1285 SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkImageFilterLight* light,
1286 SkScalar surfaceScale,
1289 SkImageFilter* input,
1290 const CropRect* cropRect)
1291 : INHERITED(light, surfaceScale, input, cropRect),
1293 fShininess(shininess)
1297 SkFlattenable* SkSpecularLightingImageFilter::CreateProc(SkReadBuffer& buffer) {
1298 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
1299 SkAutoTUnref<SkImageFilterLight> light(SkImageFilterLight::UnflattenLight(buffer));
1300 SkScalar surfaceScale = buffer.readScalar();
1301 SkScalar ks = buffer.readScalar();
1302 SkScalar shine = buffer.readScalar();
1303 return Create(light, surfaceScale, ks, shine, common.getInput(0), &common.cropRect());
1306 void SkSpecularLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
1307 this->INHERITED::flatten(buffer);
1308 buffer.writeScalar(fKS);
1309 buffer.writeScalar(fShininess);
1312 bool SkSpecularLightingImageFilter::onFilterImage(Proxy* proxy,
1313 const SkBitmap& source,
1316 SkIPoint* offset) const {
1317 SkBitmap src = source;
1318 SkIPoint srcOffset = SkIPoint::Make(0, 0);
1319 if (!this->filterInput(0, proxy, source, ctx, &src, &srcOffset)) {
1323 if (src.colorType() != kN32_SkColorType) {
1328 if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) {
1332 if (bounds.width() < 2 || bounds.height() < 2) {
1336 SkAutoLockPixels alp(src);
1337 if (!src.getPixels()) {
1341 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
1345 *dst = device->accessBitmap(false);
1346 SkAutoLockPixels alp_dst(*dst);
1348 SpecularLightingType lightingType(fKS, fShininess);
1349 offset->fX = bounds.left();
1350 offset->fY = bounds.top();
1351 SkMatrix matrix(ctx.ctm());
1352 matrix.postTranslate(SkIntToScalar(-srcOffset.x()), SkIntToScalar(-srcOffset.y()));
1353 SkAutoTUnref<SkImageFilterLight> transformedLight(light()->transform(matrix));
1354 bounds.offset(-srcOffset);
1355 switch (transformedLight->type()) {
1356 case SkImageFilterLight::kDistant_LightType:
1357 lightBitmap<SpecularLightingType, SkDistantLight>(lightingType,
1364 case SkImageFilterLight::kPoint_LightType:
1365 lightBitmap<SpecularLightingType, SkPointLight>(lightingType,
1372 case SkImageFilterLight::kSpot_LightType:
1373 lightBitmap<SpecularLightingType, SkSpotLight>(lightingType,
1384 #ifndef SK_IGNORE_TO_STRING
1385 void SkSpecularLightingImageFilter::toString(SkString* str) const {
1386 str->appendf("SkSpecularLightingImageFilter: (");
1387 str->appendf("kS: %f shininess: %f", fKS, fShininess);
1393 GrFragmentProcessor* SkSpecularLightingImageFilter::getFragmentProcessor(
1395 const SkMatrix& matrix,
1397 BoundaryMode boundaryMode) const {
1398 SkScalar scale = SkScalarMul(this->surfaceScale(), SkIntToScalar(255));
1399 return GrSpecularLightingEffect::Create(texture, this->light(), scale, matrix, this->ks(),
1400 this->shininess(), boundaryMode);
1404 ///////////////////////////////////////////////////////////////////////////////
1409 SkPoint3 random_point3(SkRandom* random) {
1410 return SkPoint3::Make(SkScalarToFloat(random->nextSScalar1()),
1411 SkScalarToFloat(random->nextSScalar1()),
1412 SkScalarToFloat(random->nextSScalar1()));
1415 SkImageFilterLight* create_random_light(SkRandom* random) {
1416 int type = random->nextULessThan(3);
1419 return new SkDistantLight(random_point3(random), random->nextU());
1422 return new SkPointLight(random_point3(random), random->nextU());
1425 return new SkSpotLight(random_point3(random), random_point3(random),
1426 random->nextUScalar1(), random->nextUScalar1(), random->nextU());
1429 SkFAIL("Unexpected value.");
1434 SkString emitNormalFunc(BoundaryMode mode,
1435 const char* pointToNormalName,
1436 const char* sobelFuncName) {
1439 case kTopLeft_BoundaryMode:
1440 result.printf("\treturn %s(%s(0.0, 0.0, m[4], m[5], m[7], m[8], %g),\n"
1441 "\t %s(0.0, 0.0, m[4], m[7], m[5], m[8], %g),\n"
1442 "\t surfaceScale);\n",
1443 pointToNormalName, sobelFuncName, gTwoThirds,
1444 sobelFuncName, gTwoThirds);
1446 case kTop_BoundaryMode:
1447 result.printf("\treturn %s(%s(0.0, 0.0, m[3], m[5], m[6], m[8], %g),\n"
1448 "\t %s(0.0, 0.0, m[4], m[7], m[5], m[8], %g),\n"
1449 "\t surfaceScale);\n",
1450 pointToNormalName, sobelFuncName, gOneThird,
1451 sobelFuncName, gOneHalf);
1453 case kTopRight_BoundaryMode:
1454 result.printf("\treturn %s(%s( 0.0, 0.0, m[3], m[4], m[6], m[7], %g),\n"
1455 "\t %s(m[3], m[6], m[4], m[7], 0.0, 0.0, %g),\n"
1456 "\t surfaceScale);\n",
1457 pointToNormalName, sobelFuncName, gTwoThirds,
1458 sobelFuncName, gTwoThirds);
1460 case kLeft_BoundaryMode:
1461 result.printf("\treturn %s(%s(m[1], m[2], m[4], m[5], m[7], m[8], %g),\n"
1462 "\t %s( 0.0, 0.0, m[1], m[7], m[2], m[8], %g),\n"
1463 "\t surfaceScale);\n",
1464 pointToNormalName, sobelFuncName, gOneHalf,
1465 sobelFuncName, gOneThird);
1467 case kInterior_BoundaryMode:
1468 result.printf("\treturn %s(%s(m[0], m[2], m[3], m[5], m[6], m[8], %g),\n"
1469 "\t %s(m[0], m[6], m[1], m[7], m[2], m[8], %g),\n"
1470 "\t surfaceScale);\n",
1471 pointToNormalName, sobelFuncName, gOneQuarter,
1472 sobelFuncName, gOneQuarter);
1474 case kRight_BoundaryMode:
1475 result.printf("\treturn %s(%s(m[0], m[1], m[3], m[4], m[6], m[7], %g),\n"
1476 "\t %s(m[0], m[6], m[1], m[7], 0.0, 0.0, %g),\n"
1477 "\t surfaceScale);\n",
1478 pointToNormalName, sobelFuncName, gOneHalf,
1479 sobelFuncName, gOneThird);
1481 case kBottomLeft_BoundaryMode:
1482 result.printf("\treturn %s(%s(m[1], m[2], m[4], m[5], 0.0, 0.0, %g),\n"
1483 "\t %s( 0.0, 0.0, m[1], m[4], m[2], m[5], %g),\n"
1484 "\t surfaceScale);\n",
1485 pointToNormalName, sobelFuncName, gTwoThirds,
1486 sobelFuncName, gTwoThirds);
1488 case kBottom_BoundaryMode:
1489 result.printf("\treturn %s(%s(m[0], m[2], m[3], m[5], 0.0, 0.0, %g),\n"
1490 "\t %s(m[0], m[3], m[1], m[4], m[2], m[5], %g),\n"
1491 "\t surfaceScale);\n",
1492 pointToNormalName, sobelFuncName, gOneThird,
1493 sobelFuncName, gOneHalf);
1495 case kBottomRight_BoundaryMode:
1496 result.printf("\treturn %s(%s(m[0], m[1], m[3], m[4], 0.0, 0.0, %g),\n"
1497 "\t %s(m[0], m[3], m[1], m[4], 0.0, 0.0, %g),\n"
1498 "\t surfaceScale);\n",
1499 pointToNormalName, sobelFuncName, gTwoThirds,
1500 sobelFuncName, gTwoThirds);
1511 class GrGLLightingEffect : public GrGLSLFragmentProcessor {
1513 GrGLLightingEffect(const GrProcessor&);
1514 virtual ~GrGLLightingEffect();
1516 void emitCode(EmitArgs&) override;
1518 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder* b);
1522 * Subclasses of GrGLLightingEffect must call INHERITED::onSetData();
1524 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
1526 virtual void emitLightFunc(GrGLSLFPBuilder*, SkString* funcName) = 0;
1529 typedef GrGLSLFragmentProcessor INHERITED;
1531 UniformHandle fImageIncrementUni;
1532 UniformHandle fSurfaceScaleUni;
1534 BoundaryMode fBoundaryMode;
1537 ///////////////////////////////////////////////////////////////////////////////
1539 class GrGLDiffuseLightingEffect : public GrGLLightingEffect {
1541 GrGLDiffuseLightingEffect(const GrProcessor&);
1542 void emitLightFunc(GrGLSLFPBuilder*, SkString* funcName) override;
1545 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
1548 typedef GrGLLightingEffect INHERITED;
1550 UniformHandle fKDUni;
1553 ///////////////////////////////////////////////////////////////////////////////
1555 class GrGLSpecularLightingEffect : public GrGLLightingEffect {
1557 GrGLSpecularLightingEffect(const GrProcessor&);
1558 void emitLightFunc(GrGLSLFPBuilder*, SkString* funcName) override;
1561 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
1564 typedef GrGLLightingEffect INHERITED;
1566 UniformHandle fKSUni;
1567 UniformHandle fShininessUni;
1570 ///////////////////////////////////////////////////////////////////////////////
1572 GrLightingEffect::GrLightingEffect(GrTexture* texture,
1573 const SkImageFilterLight* light,
1574 SkScalar surfaceScale,
1575 const SkMatrix& matrix,
1576 BoundaryMode boundaryMode)
1577 : INHERITED(texture, GrCoordTransform::MakeDivByTextureWHMatrix(texture))
1579 , fSurfaceScale(surfaceScale)
1580 , fFilterMatrix(matrix)
1581 , fBoundaryMode(boundaryMode) {
1583 if (light->requiresFragmentPosition()) {
1584 this->setWillReadFragmentPosition();
1588 GrLightingEffect::~GrLightingEffect() {
1592 bool GrLightingEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
1593 const GrLightingEffect& s = sBase.cast<GrLightingEffect>();
1594 return fLight->isEqual(*s.fLight) &&
1595 fSurfaceScale == s.fSurfaceScale &&
1596 fBoundaryMode == s.fBoundaryMode;
1599 ///////////////////////////////////////////////////////////////////////////////
1601 GrDiffuseLightingEffect::GrDiffuseLightingEffect(GrTexture* texture,
1602 const SkImageFilterLight* light,
1603 SkScalar surfaceScale,
1604 const SkMatrix& matrix,
1606 BoundaryMode boundaryMode)
1607 : INHERITED(texture, light, surfaceScale, matrix, boundaryMode), fKD(kd) {
1608 this->initClassID<GrDiffuseLightingEffect>();
1611 bool GrDiffuseLightingEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
1612 const GrDiffuseLightingEffect& s = sBase.cast<GrDiffuseLightingEffect>();
1613 return INHERITED::onIsEqual(sBase) &&
1614 this->kd() == s.kd();
1617 void GrDiffuseLightingEffect::onGetGLProcessorKey(const GrGLSLCaps& caps,
1618 GrProcessorKeyBuilder* b) const {
1619 GrGLDiffuseLightingEffect::GenKey(*this, caps, b);
1622 GrGLSLFragmentProcessor* GrDiffuseLightingEffect::onCreateGLInstance() const {
1623 return new GrGLDiffuseLightingEffect(*this);
1626 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDiffuseLightingEffect);
1628 const GrFragmentProcessor* GrDiffuseLightingEffect::TestCreate(GrProcessorTestData* d) {
1629 SkScalar surfaceScale = d->fRandom->nextSScalar1();
1630 SkScalar kd = d->fRandom->nextUScalar1();
1631 SkAutoTUnref<SkImageFilterLight> light(create_random_light(d->fRandom));
1633 for (int i = 0; i < 9; i++) {
1634 matrix[i] = d->fRandom->nextUScalar1();
1636 BoundaryMode mode = static_cast<BoundaryMode>(d->fRandom->nextU() % kBoundaryModeCount);
1637 return GrDiffuseLightingEffect::Create(d->fTextures[GrProcessorUnitTest::kAlphaTextureIdx],
1638 light, surfaceScale, matrix, kd, mode);
1642 ///////////////////////////////////////////////////////////////////////////////
1644 GrGLLightingEffect::GrGLLightingEffect(const GrProcessor& fp) {
1645 const GrLightingEffect& m = fp.cast<GrLightingEffect>();
1646 fLight = m.light()->createGLLight();
1647 fBoundaryMode = m.boundaryMode();
1650 GrGLLightingEffect::~GrGLLightingEffect() {
1654 void GrGLLightingEffect::emitCode(EmitArgs& args) {
1655 fImageIncrementUni = args.fBuilder->addUniform(GrGLSLProgramBuilder::kFragment_Visibility,
1656 kVec2f_GrSLType, kDefault_GrSLPrecision,
1658 fSurfaceScaleUni = args.fBuilder->addUniform(GrGLSLProgramBuilder::kFragment_Visibility,
1659 kFloat_GrSLType, kDefault_GrSLPrecision,
1661 fLight->emitLightColorUniform(args.fBuilder);
1663 this->emitLightFunc(args.fBuilder, &lightFunc);
1664 static const GrGLSLShaderVar gSobelArgs[] = {
1665 GrGLSLShaderVar("a", kFloat_GrSLType),
1666 GrGLSLShaderVar("b", kFloat_GrSLType),
1667 GrGLSLShaderVar("c", kFloat_GrSLType),
1668 GrGLSLShaderVar("d", kFloat_GrSLType),
1669 GrGLSLShaderVar("e", kFloat_GrSLType),
1670 GrGLSLShaderVar("f", kFloat_GrSLType),
1671 GrGLSLShaderVar("scale", kFloat_GrSLType),
1673 SkString sobelFuncName;
1674 GrGLSLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
1675 SkString coords2D = fsBuilder->ensureFSCoords2D(args.fCoords, 0);
1677 fsBuilder->emitFunction(kFloat_GrSLType,
1679 SK_ARRAY_COUNT(gSobelArgs),
1681 "\treturn (-a + b - 2.0 * c + 2.0 * d -e + f) * scale;\n",
1683 static const GrGLSLShaderVar gPointToNormalArgs[] = {
1684 GrGLSLShaderVar("x", kFloat_GrSLType),
1685 GrGLSLShaderVar("y", kFloat_GrSLType),
1686 GrGLSLShaderVar("scale", kFloat_GrSLType),
1688 SkString pointToNormalName;
1689 fsBuilder->emitFunction(kVec3f_GrSLType,
1691 SK_ARRAY_COUNT(gPointToNormalArgs),
1693 "\treturn normalize(vec3(-x * scale, -y * scale, 1));\n",
1694 &pointToNormalName);
1696 static const GrGLSLShaderVar gInteriorNormalArgs[] = {
1697 GrGLSLShaderVar("m", kFloat_GrSLType, 9),
1698 GrGLSLShaderVar("surfaceScale", kFloat_GrSLType),
1700 SkString normalBody = emitNormalFunc(fBoundaryMode,
1701 pointToNormalName.c_str(),
1702 sobelFuncName.c_str());
1703 SkString normalName;
1704 fsBuilder->emitFunction(kVec3f_GrSLType,
1706 SK_ARRAY_COUNT(gInteriorNormalArgs),
1707 gInteriorNormalArgs,
1711 fsBuilder->codeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str());
1712 fsBuilder->codeAppend("\t\tfloat m[9];\n");
1714 const char* imgInc = args.fBuilder->getUniformCStr(fImageIncrementUni);
1715 const char* surfScale = args.fBuilder->getUniformCStr(fSurfaceScaleUni);
1718 for (int dy = 1; dy >= -1; dy--) {
1719 for (int dx = -1; dx <= 1; dx++) {
1721 texCoords.appendf("coord + vec2(%d, %d) * %s", dx, dy, imgInc);
1722 fsBuilder->codeAppendf("\t\tm[%d] = ", index++);
1723 fsBuilder->appendTextureLookup(args.fSamplers[0], texCoords.c_str());
1724 fsBuilder->codeAppend(".a;\n");
1727 fsBuilder->codeAppend("\t\tvec3 surfaceToLight = ");
1729 arg.appendf("%s * m[4]", surfScale);
1730 fLight->emitSurfaceToLight(args.fBuilder, arg.c_str());
1731 fsBuilder->codeAppend(";\n");
1732 fsBuilder->codeAppendf("\t\t%s = %s(%s(m, %s), surfaceToLight, ",
1733 args.fOutputColor, lightFunc.c_str(), normalName.c_str(), surfScale);
1734 fLight->emitLightColor(args.fBuilder, "surfaceToLight");
1735 fsBuilder->codeAppend(");\n");
1737 GrGLSLMulVarBy4f(&modulate, args.fOutputColor, args.fInputColor);
1738 fsBuilder->codeAppend(modulate.c_str());
1741 void GrGLLightingEffect::GenKey(const GrProcessor& proc,
1742 const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) {
1743 const GrLightingEffect& lighting = proc.cast<GrLightingEffect>();
1744 b->add32(lighting.boundaryMode() << 2 | lighting.light()->type());
1747 void GrGLLightingEffect::onSetData(const GrGLSLProgramDataManager& pdman,
1748 const GrProcessor& proc) {
1749 const GrLightingEffect& lighting = proc.cast<GrLightingEffect>();
1750 GrTexture* texture = lighting.texture(0);
1751 float ySign = texture->origin() == kTopLeft_GrSurfaceOrigin ? -1.0f : 1.0f;
1752 pdman.set2f(fImageIncrementUni, 1.0f / texture->width(), ySign / texture->height());
1753 pdman.set1f(fSurfaceScaleUni, lighting.surfaceScale());
1754 SkAutoTUnref<SkImageFilterLight> transformedLight(
1755 lighting.light()->transform(lighting.filterMatrix()));
1756 fLight->setData(pdman, transformedLight);
1759 ///////////////////////////////////////////////////////////////////////////////
1761 ///////////////////////////////////////////////////////////////////////////////
1763 GrGLDiffuseLightingEffect::GrGLDiffuseLightingEffect(const GrProcessor& proc)
1767 void GrGLDiffuseLightingEffect::emitLightFunc(GrGLSLFPBuilder* builder, SkString* funcName) {
1769 fKDUni = builder->addUniform(GrGLSLProgramBuilder::kFragment_Visibility,
1770 kFloat_GrSLType, kDefault_GrSLPrecision,
1773 static const GrGLSLShaderVar gLightArgs[] = {
1774 GrGLSLShaderVar("normal", kVec3f_GrSLType),
1775 GrGLSLShaderVar("surfaceToLight", kVec3f_GrSLType),
1776 GrGLSLShaderVar("lightColor", kVec3f_GrSLType)
1779 lightBody.appendf("\tfloat colorScale = %s * dot(normal, surfaceToLight);\n", kd);
1780 lightBody.appendf("\treturn vec4(lightColor * clamp(colorScale, 0.0, 1.0), 1.0);\n");
1781 builder->getFragmentShaderBuilder()->emitFunction(kVec4f_GrSLType,
1783 SK_ARRAY_COUNT(gLightArgs),
1789 void GrGLDiffuseLightingEffect::onSetData(const GrGLSLProgramDataManager& pdman,
1790 const GrProcessor& proc) {
1791 INHERITED::onSetData(pdman, proc);
1792 const GrDiffuseLightingEffect& diffuse = proc.cast<GrDiffuseLightingEffect>();
1793 pdman.set1f(fKDUni, diffuse.kd());
1796 ///////////////////////////////////////////////////////////////////////////////
1798 GrSpecularLightingEffect::GrSpecularLightingEffect(GrTexture* texture,
1799 const SkImageFilterLight* light,
1800 SkScalar surfaceScale,
1801 const SkMatrix& matrix,
1804 BoundaryMode boundaryMode)
1805 : INHERITED(texture, light, surfaceScale, matrix, boundaryMode)
1807 , fShininess(shininess) {
1808 this->initClassID<GrSpecularLightingEffect>();
1811 bool GrSpecularLightingEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
1812 const GrSpecularLightingEffect& s = sBase.cast<GrSpecularLightingEffect>();
1813 return INHERITED::onIsEqual(sBase) &&
1814 this->ks() == s.ks() &&
1815 this->shininess() == s.shininess();
1818 void GrSpecularLightingEffect::onGetGLProcessorKey(const GrGLSLCaps& caps,
1819 GrProcessorKeyBuilder* b) const {
1820 GrGLSpecularLightingEffect::GenKey(*this, caps, b);
1823 GrGLSLFragmentProcessor* GrSpecularLightingEffect::onCreateGLInstance() const {
1824 return new GrGLSpecularLightingEffect(*this);
1827 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrSpecularLightingEffect);
1829 const GrFragmentProcessor* GrSpecularLightingEffect::TestCreate(GrProcessorTestData* d) {
1830 SkScalar surfaceScale = d->fRandom->nextSScalar1();
1831 SkScalar ks = d->fRandom->nextUScalar1();
1832 SkScalar shininess = d->fRandom->nextUScalar1();
1833 SkAutoTUnref<SkImageFilterLight> light(create_random_light(d->fRandom));
1835 for (int i = 0; i < 9; i++) {
1836 matrix[i] = d->fRandom->nextUScalar1();
1838 BoundaryMode mode = static_cast<BoundaryMode>(d->fRandom->nextU() % kBoundaryModeCount);
1839 return GrSpecularLightingEffect::Create(d->fTextures[GrProcessorUnitTest::kAlphaTextureIdx],
1840 light, surfaceScale, matrix, ks, shininess, mode);
1843 ///////////////////////////////////////////////////////////////////////////////
1845 GrGLSpecularLightingEffect::GrGLSpecularLightingEffect(const GrProcessor& proc)
1849 void GrGLSpecularLightingEffect::emitLightFunc(GrGLSLFPBuilder* builder, SkString* funcName) {
1851 const char* shininess;
1853 fKSUni = builder->addUniform(GrGLSLProgramBuilder::kFragment_Visibility,
1854 kFloat_GrSLType, kDefault_GrSLPrecision, "KS", &ks);
1855 fShininessUni = builder->addUniform(GrGLSLProgramBuilder::kFragment_Visibility,
1857 kDefault_GrSLPrecision,
1861 static const GrGLSLShaderVar gLightArgs[] = {
1862 GrGLSLShaderVar("normal", kVec3f_GrSLType),
1863 GrGLSLShaderVar("surfaceToLight", kVec3f_GrSLType),
1864 GrGLSLShaderVar("lightColor", kVec3f_GrSLType)
1867 lightBody.appendf("\tvec3 halfDir = vec3(normalize(surfaceToLight + vec3(0, 0, 1)));\n");
1868 lightBody.appendf("\tfloat colorScale = %s * pow(dot(normal, halfDir), %s);\n", ks, shininess);
1869 lightBody.appendf("\tvec3 color = lightColor * clamp(colorScale, 0.0, 1.0);\n");
1870 lightBody.appendf("\treturn vec4(color, max(max(color.r, color.g), color.b));\n");
1871 builder->getFragmentShaderBuilder()->emitFunction(kVec4f_GrSLType,
1873 SK_ARRAY_COUNT(gLightArgs),
1879 void GrGLSpecularLightingEffect::onSetData(const GrGLSLProgramDataManager& pdman,
1880 const GrProcessor& effect) {
1881 INHERITED::onSetData(pdman, effect);
1882 const GrSpecularLightingEffect& spec = effect.cast<GrSpecularLightingEffect>();
1883 pdman.set1f(fKSUni, spec.ks());
1884 pdman.set1f(fShininessUni, spec.shininess());
1887 ///////////////////////////////////////////////////////////////////////////////
1888 void GrGLLight::emitLightColorUniform(GrGLSLFPBuilder* builder) {
1889 fColorUni = builder->addUniform(GrGLSLProgramBuilder::kFragment_Visibility,
1890 kVec3f_GrSLType, kDefault_GrSLPrecision,
1894 void GrGLLight::emitLightColor(GrGLSLFPBuilder* builder, const char *surfaceToLight) {
1895 builder->getFragmentShaderBuilder()->codeAppend(builder->getUniformCStr(this->lightColorUni()));
1898 void GrGLLight::setData(const GrGLSLProgramDataManager& pdman,
1899 const SkImageFilterLight* light) const {
1900 setUniformPoint3(pdman, fColorUni,
1901 light->color().makeScale(SkScalarInvert(SkIntToScalar(255))));
1904 ///////////////////////////////////////////////////////////////////////////////
1906 void GrGLDistantLight::setData(const GrGLSLProgramDataManager& pdman,
1907 const SkImageFilterLight* light) const {
1908 INHERITED::setData(pdman, light);
1909 SkASSERT(light->type() == SkImageFilterLight::kDistant_LightType);
1910 const SkDistantLight* distantLight = static_cast<const SkDistantLight*>(light);
1911 setUniformNormal3(pdman, fDirectionUni, distantLight->direction());
1914 void GrGLDistantLight::emitSurfaceToLight(GrGLSLFPBuilder* builder, const char* z) {
1916 fDirectionUni = builder->addUniform(GrGLSLProgramBuilder::kFragment_Visibility,
1917 kVec3f_GrSLType, kDefault_GrSLPrecision,
1918 "LightDirection", &dir);
1919 builder->getFragmentShaderBuilder()->codeAppend(dir);
1922 ///////////////////////////////////////////////////////////////////////////////
1924 void GrGLPointLight::setData(const GrGLSLProgramDataManager& pdman,
1925 const SkImageFilterLight* light) const {
1926 INHERITED::setData(pdman, light);
1927 SkASSERT(light->type() == SkImageFilterLight::kPoint_LightType);
1928 const SkPointLight* pointLight = static_cast<const SkPointLight*>(light);
1929 setUniformPoint3(pdman, fLocationUni, pointLight->location());
1932 void GrGLPointLight::emitSurfaceToLight(GrGLSLFPBuilder* builder, const char* z) {
1934 fLocationUni = builder->addUniform(GrGLSLProgramBuilder::kFragment_Visibility,
1935 kVec3f_GrSLType, kDefault_GrSLPrecision,
1936 "LightLocation", &loc);
1937 GrGLSLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
1938 fsBuilder->codeAppendf("normalize(%s - vec3(%s.xy, %s))",
1939 loc, fsBuilder->fragmentPosition(), z);
1942 ///////////////////////////////////////////////////////////////////////////////
1944 void GrGLSpotLight::setData(const GrGLSLProgramDataManager& pdman,
1945 const SkImageFilterLight* light) const {
1946 INHERITED::setData(pdman, light);
1947 SkASSERT(light->type() == SkImageFilterLight::kSpot_LightType);
1948 const SkSpotLight* spotLight = static_cast<const SkSpotLight *>(light);
1949 setUniformPoint3(pdman, fLocationUni, spotLight->location());
1950 pdman.set1f(fExponentUni, spotLight->specularExponent());
1951 pdman.set1f(fCosInnerConeAngleUni, spotLight->cosInnerConeAngle());
1952 pdman.set1f(fCosOuterConeAngleUni, spotLight->cosOuterConeAngle());
1953 pdman.set1f(fConeScaleUni, spotLight->coneScale());
1954 setUniformNormal3(pdman, fSUni, spotLight->s());
1957 void GrGLSpotLight::emitSurfaceToLight(GrGLSLFPBuilder* builder, const char* z) {
1958 const char* location;
1959 fLocationUni = builder->addUniform(GrGLSLProgramBuilder::kFragment_Visibility,
1960 kVec3f_GrSLType, kDefault_GrSLPrecision,
1961 "LightLocation", &location);
1963 GrGLSLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
1964 fsBuilder->codeAppendf("normalize(%s - vec3(%s.xy, %s))",
1965 location, fsBuilder->fragmentPosition(), z);
1968 void GrGLSpotLight::emitLightColor(GrGLSLFPBuilder* builder,
1969 const char *surfaceToLight) {
1971 const char* color = builder->getUniformCStr(this->lightColorUni()); // created by parent class.
1973 const char* exponent;
1974 const char* cosInner;
1975 const char* cosOuter;
1976 const char* coneScale;
1978 fExponentUni = builder->addUniform(GrGLSLProgramBuilder::kFragment_Visibility,
1979 kFloat_GrSLType, kDefault_GrSLPrecision,
1980 "Exponent", &exponent);
1981 fCosInnerConeAngleUni = builder->addUniform(GrGLSLProgramBuilder::kFragment_Visibility,
1982 kFloat_GrSLType, kDefault_GrSLPrecision,
1983 "CosInnerConeAngle", &cosInner);
1984 fCosOuterConeAngleUni = builder->addUniform(GrGLSLProgramBuilder::kFragment_Visibility,
1985 kFloat_GrSLType, kDefault_GrSLPrecision,
1986 "CosOuterConeAngle", &cosOuter);
1987 fConeScaleUni = builder->addUniform(GrGLSLProgramBuilder::kFragment_Visibility,
1988 kFloat_GrSLType, kDefault_GrSLPrecision,
1989 "ConeScale", &coneScale);
1990 fSUni = builder->addUniform(GrGLSLProgramBuilder::kFragment_Visibility,
1991 kVec3f_GrSLType, kDefault_GrSLPrecision, "S", &s);
1993 static const GrGLSLShaderVar gLightColorArgs[] = {
1994 GrGLSLShaderVar("surfaceToLight", kVec3f_GrSLType)
1996 SkString lightColorBody;
1997 lightColorBody.appendf("\tfloat cosAngle = -dot(surfaceToLight, %s);\n", s);
1998 lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosOuter);
1999 lightColorBody.appendf("\t\treturn vec3(0);\n");
2000 lightColorBody.appendf("\t}\n");
2001 lightColorBody.appendf("\tfloat scale = pow(cosAngle, %s);\n", exponent);
2002 lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosInner);
2003 lightColorBody.appendf("\t\treturn %s * scale * (cosAngle - %s) * %s;\n",
2004 color, cosOuter, coneScale);
2005 lightColorBody.appendf("\t}\n");
2006 lightColorBody.appendf("\treturn %s;\n", color);
2007 GrGLSLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
2008 fsBuilder->emitFunction(kVec3f_GrSLType,
2010 SK_ARRAY_COUNT(gLightColorArgs),
2012 lightColorBody.c_str(),
2015 fsBuilder->codeAppendf("%s(%s)", fLightColorFunc.c_str(), surfaceToLight);
2020 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingImageFilter)
2021 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDiffuseLightingImageFilter)
2022 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSpecularLightingImageFilter)
2023 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END