blob: 9b8fb0f7c0e5ebcd7b38f2f3fbf2ee72408c5744 [file] [log] [blame]
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +00001/*
2 * Copyright 2012 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkLightingImageFilter.h"
9#include "SkBitmap.h"
10#include "SkColorPriv.h"
senorblanco@chromium.org894790d2012-07-11 16:01:22 +000011#include "GrProgramStageFactory.h"
12#include "gl/GrGLProgramStage.h"
13#include "gl/GrGLSL.h"
14#include "gl/GrGLTexture.h"
15#include "GrCustomStage.h"
16
17class GrGLDiffuseLightingEffect;
18class GrGLSpecularLightingEffect;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +000019
20// FIXME: Eventually, this should be implemented properly, and put in
21// SkScalar.h.
22#define SkScalarPow(x, y) SkFloatToScalar(powf(SkScalarToFloat(x), SkScalarToFloat(y)))
23namespace {
24
25const SkScalar gOneThird = SkScalarInvert(SkIntToScalar(3));
26const SkScalar gTwoThirds = SkScalarDiv(SkIntToScalar(2), SkIntToScalar(3));
27const SkScalar gOneHalf = SkFloatToScalar(0.5f);
28const SkScalar gOneQuarter = SkFloatToScalar(0.25f);
29
senorblanco@chromium.org894790d2012-07-11 16:01:22 +000030void setUniformPoint3(const GrGLInterface* gl, GrGLint location, const SkPoint3& point) {
31 float x = SkScalarToFloat(point.fX);
32 float y = SkScalarToFloat(point.fY);
33 float z = SkScalarToFloat(point.fZ);
34 GR_GL_CALL(gl, Uniform3f(location, x, y, z));
35}
36
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +000037// Shift matrix components to the left, as we advance pixels to the right.
38inline void shiftMatrixLeft(int m[9]) {
39 m[0] = m[1];
40 m[3] = m[4];
41 m[6] = m[7];
42 m[1] = m[2];
43 m[4] = m[5];
44 m[7] = m[8];
45}
46
47class DiffuseLightingType {
48public:
49 DiffuseLightingType(SkScalar kd)
50 : fKD(kd) {}
51 SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight, const SkPoint3& lightColor) const {
52 SkScalar colorScale = SkScalarMul(fKD, normal.dot(surfaceTolight));
53 colorScale = SkScalarClampMax(colorScale, SK_Scalar1);
54 SkPoint3 color(lightColor * colorScale);
55 return SkPackARGB32(255,
56 SkScalarFloorToInt(color.fX),
57 SkScalarFloorToInt(color.fY),
58 SkScalarFloorToInt(color.fZ));
59 }
60private:
61 SkScalar fKD;
62};
63
64class SpecularLightingType {
65public:
66 SpecularLightingType(SkScalar ks, SkScalar shininess)
67 : fKS(ks), fShininess(shininess) {}
68 SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight, const SkPoint3& lightColor) const {
69 SkPoint3 halfDir(surfaceTolight);
70 halfDir.fZ += SK_Scalar1; // eye position is always (0, 0, 1)
71 halfDir.normalize();
72 SkScalar colorScale = SkScalarMul(fKS,
73 SkScalarPow(normal.dot(halfDir), fShininess));
74 colorScale = SkScalarClampMax(colorScale, SK_Scalar1);
75 SkPoint3 color(lightColor * colorScale);
76 return SkPackARGB32(SkScalarFloorToInt(color.maxComponent()),
77 SkScalarFloorToInt(color.fX),
78 SkScalarFloorToInt(color.fY),
79 SkScalarFloorToInt(color.fZ));
80 }
81private:
82 SkScalar fKS;
83 SkScalar fShininess;
84};
85
86inline SkScalar sobel(int a, int b, int c, int d, int e, int f, SkScalar scale) {
87 return SkScalarMul(SkIntToScalar(-a + b - 2 * c + 2 * d -e + f), scale);
88}
89
90inline SkPoint3 pointToNormal(SkScalar x, SkScalar y, SkScalar surfaceScale) {
91 SkPoint3 vector(SkScalarMul(-x, surfaceScale),
92 SkScalarMul(-y, surfaceScale),
93 SK_Scalar1);
94 vector.normalize();
95 return vector;
96}
97
98inline SkPoint3 topLeftNormal(int m[9], SkScalar surfaceScale) {
99 return pointToNormal(sobel(0, 0, m[4], m[5], m[7], m[8], gTwoThirds),
100 sobel(0, 0, m[4], m[7], m[5], m[8], gTwoThirds),
101 surfaceScale);
102}
103
104inline SkPoint3 topNormal(int m[9], SkScalar surfaceScale) {
105 return pointToNormal(sobel( 0, 0, m[3], m[5], m[6], m[8], gOneThird),
106 sobel(m[3], m[6], m[4], m[7], m[5], m[8], gOneHalf),
107 surfaceScale);
108}
109
110inline SkPoint3 topRightNormal(int m[9], SkScalar surfaceScale) {
111 return pointToNormal(sobel( 0, 0, m[3], m[4], m[6], m[7], gTwoThirds),
112 sobel(m[3], m[6], m[4], m[7], 0, 0, gTwoThirds),
113 surfaceScale);
114}
115
116inline SkPoint3 leftNormal(int m[9], SkScalar surfaceScale) {
117 return pointToNormal(sobel(m[1], m[2], m[4], m[5], m[7], m[8], gOneHalf),
118 sobel( 0, 0, m[1], m[7], m[2], m[8], gOneThird),
119 surfaceScale);
120}
121
122
123inline SkPoint3 interiorNormal(int m[9], SkScalar surfaceScale) {
124 return pointToNormal(sobel(m[0], m[2], m[3], m[5], m[6], m[8], gOneQuarter),
125 sobel(m[0], m[6], m[1], m[7], m[2], m[8], gOneQuarter),
126 surfaceScale);
127}
128
129inline SkPoint3 rightNormal(int m[9], SkScalar surfaceScale) {
130 return pointToNormal(sobel(m[0], m[1], m[3], m[4], m[6], m[7], gOneHalf),
131 sobel(m[0], m[6], m[1], m[7], 0, 0, gOneThird),
132 surfaceScale);
133}
134
135inline SkPoint3 bottomLeftNormal(int m[9], SkScalar surfaceScale) {
136 return pointToNormal(sobel(m[1], m[2], m[4], m[5], 0, 0, gTwoThirds),
137 sobel( 0, 0, m[1], m[4], m[2], m[5], gTwoThirds),
138 surfaceScale);
139}
140
141inline SkPoint3 bottomNormal(int m[9], SkScalar surfaceScale) {
142 return pointToNormal(sobel(m[0], m[2], m[3], m[5], 0, 0, gOneThird),
143 sobel(m[0], m[3], m[1], m[4], m[2], m[5], gOneHalf),
144 surfaceScale);
145}
146
147inline SkPoint3 bottomRightNormal(int m[9], SkScalar surfaceScale) {
148 return pointToNormal(sobel(m[0], m[1], m[3], m[4], 0, 0, gTwoThirds),
149 sobel(m[0], m[3], m[1], m[4], 0, 0, gTwoThirds),
150 surfaceScale);
151}
152
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000153template <class LightingType, class LightType> void lightBitmap(const LightingType& lightingType, const SkLight* light, const SkBitmap& src, SkBitmap* dst, SkScalar surfaceScale) {
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000154 const LightType* l = static_cast<const LightType*>(light);
155 int y = 0;
156 {
157 const SkPMColor* row1 = src.getAddr32(0, 0);
158 const SkPMColor* row2 = src.getAddr32(0, 1);
159 SkPMColor* dptr = dst->getAddr32(0, 0);
160 int m[9];
161 int x = 0;
162 m[4] = SkGetPackedA32(*row1++);
163 m[5] = SkGetPackedA32(*row1++);
164 m[7] = SkGetPackedA32(*row2++);
165 m[8] = SkGetPackedA32(*row2++);
166 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000167 *dptr++ = lightingType.light(topLeftNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000168 for (x = 1; x < src.width() - 1; ++x)
169 {
170 shiftMatrixLeft(m);
171 m[5] = SkGetPackedA32(*row1++);
172 m[8] = SkGetPackedA32(*row2++);
173 surfaceToLight = l->surfaceToLight(x, 0, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000174 *dptr++ = lightingType.light(topNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000175 }
176 shiftMatrixLeft(m);
177 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000178 *dptr++ = lightingType.light(topRightNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000179 }
180
181 for (++y; y < src.height() - 1; ++y) {
182 const SkPMColor* row0 = src.getAddr32(0, y - 1);
183 const SkPMColor* row1 = src.getAddr32(0, y);
184 const SkPMColor* row2 = src.getAddr32(0, y + 1);
185 SkPMColor* dptr = dst->getAddr32(0, y);
186 int m[9];
187 int x = 0;
188 m[1] = SkGetPackedA32(*row0++);
189 m[2] = SkGetPackedA32(*row0++);
190 m[4] = SkGetPackedA32(*row1++);
191 m[5] = SkGetPackedA32(*row1++);
192 m[7] = SkGetPackedA32(*row2++);
193 m[8] = SkGetPackedA32(*row2++);
194 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000195 *dptr++ = lightingType.light(leftNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000196 for (x = 1; x < src.width() - 1; ++x) {
197 shiftMatrixLeft(m);
198 m[2] = SkGetPackedA32(*row0++);
199 m[5] = SkGetPackedA32(*row1++);
200 m[8] = SkGetPackedA32(*row2++);
201 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000202 *dptr++ = lightingType.light(interiorNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000203 }
204 shiftMatrixLeft(m);
205 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000206 *dptr++ = lightingType.light(rightNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000207 }
208
209 {
210 const SkPMColor* row0 = src.getAddr32(0, src.height() - 2);
211 const SkPMColor* row1 = src.getAddr32(0, src.height() - 1);
212 int x = 0;
213 SkPMColor* dptr = dst->getAddr32(0, src.height() - 1);
214 int m[9];
215 m[1] = SkGetPackedA32(*row0++);
216 m[2] = SkGetPackedA32(*row0++);
217 m[4] = SkGetPackedA32(*row1++);
218 m[5] = SkGetPackedA32(*row1++);
219 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000220 *dptr++ = lightingType.light(bottomLeftNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000221 for (x = 1; x < src.width() - 1; ++x)
222 {
223 shiftMatrixLeft(m);
224 m[2] = SkGetPackedA32(*row0++);
225 m[5] = SkGetPackedA32(*row1++);
226 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000227 *dptr++ = lightingType.light(bottomNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000228 }
229 shiftMatrixLeft(m);
230 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000231 *dptr++ = lightingType.light(bottomRightNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000232 }
233}
234
235SkPoint3 readPoint3(SkFlattenableReadBuffer& buffer) {
236 SkPoint3 point;
237 point.fX = buffer.readScalar();
238 point.fY = buffer.readScalar();
239 point.fZ = buffer.readScalar();
240 return point;
241};
242
243void writePoint3(const SkPoint3& point, SkFlattenableWriteBuffer& buffer) {
244 buffer.writeScalar(point.fX);
245 buffer.writeScalar(point.fY);
246 buffer.writeScalar(point.fZ);
247};
248
249class SkDiffuseLightingImageFilter : public SkLightingImageFilter {
250public:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000251 SkDiffuseLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar kd);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000252 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDiffuseLightingImageFilter)
253
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000254 virtual bool asNewCustomStage(GrCustomStage** stage) const SK_OVERRIDE;
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000255 SkScalar kd() const { return fKD; }
256
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000257protected:
258 explicit SkDiffuseLightingImageFilter(SkFlattenableReadBuffer& buffer);
259 virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE;
260 virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
261 SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
262
263
264private:
265 typedef SkLightingImageFilter INHERITED;
266 SkScalar fKD;
267};
268
269class SkSpecularLightingImageFilter : public SkLightingImageFilter {
270public:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000271 SkSpecularLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000272 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSpecularLightingImageFilter)
273
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000274 virtual bool asNewCustomStage(GrCustomStage** stage) const SK_OVERRIDE;
275 SkScalar ks() const { return fKS; }
276 SkScalar shininess() const { return fShininess; }
277
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000278protected:
279 explicit SkSpecularLightingImageFilter(SkFlattenableReadBuffer& buffer);
280 virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE;
281 virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
282 SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
283
284private:
285 typedef SkLightingImageFilter INHERITED;
286 SkScalar fKS;
287 SkScalar fShininess;
288};
289
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000290
291class GrLightingEffect : public GrCustomStage {
292public:
293 GrLightingEffect(const SkLight* light, SkScalar surfaceScale);
294 virtual ~GrLightingEffect();
295
296 virtual bool isEqual(const GrCustomStage&) const SK_OVERRIDE;
297
298 const SkLight* light() const { return fLight; }
299 SkScalar surfaceScale() const { return fSurfaceScale; }
300private:
301 typedef GrCustomStage INHERITED;
302 const SkLight* fLight;
303 SkScalar fSurfaceScale;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000304};
305
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000306class GrDiffuseLightingEffect : public GrLightingEffect {
307public:
308 GrDiffuseLightingEffect(const SkLight* light, SkScalar surfaceScale, SkScalar kd);
309
310 static const char* Name() { return "DiffuseLighting"; }
311
312 typedef GrGLDiffuseLightingEffect GLProgramStage;
313
314 virtual const GrProgramStageFactory& getFactory() const SK_OVERRIDE;
315 virtual bool isEqual(const GrCustomStage&) const SK_OVERRIDE;
316 SkScalar kd() const { return fKD; }
317private:
318 typedef GrLightingEffect INHERITED;
319 SkScalar fKD;
320};
321
322class GrSpecularLightingEffect : public GrLightingEffect {
323public:
324 GrSpecularLightingEffect(const SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess);
325
326 static const char* Name() { return "SpecularLighting"; }
327
328 typedef GrGLSpecularLightingEffect GLProgramStage;
329
330 virtual const GrProgramStageFactory& getFactory() const SK_OVERRIDE;
331 virtual bool isEqual(const GrCustomStage&) const SK_OVERRIDE;
332 SkScalar ks() const { return fKS; }
333 SkScalar shininess() const { return fShininess; }
334
335private:
336 typedef GrLightingEffect INHERITED;
337 SkScalar fKS;
338 SkScalar fShininess;
339};
340
341///////////////////////////////////////////////////////////////////////////////
342
343class GrGLLight {
344public:
senorblanco@chromium.org6730cbb2012-07-11 16:35:00 +0000345 virtual ~GrGLLight() {}
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000346 virtual void setupVariables(GrGLShaderBuilder* state, int stage);
347 virtual void emitVS(SkString* builder) const {}
348 virtual void emitFuncs(SkString* builder) const {}
349 virtual void emitSurfaceToLight(SkString* builder, const char* z) const = 0;
350 virtual void emitLightColor(SkString* builder, const char *surfaceToLight) const;
351 virtual void initUniforms(const GrGLInterface* gl, int programID);
352 virtual void setData(const GrGLInterface*, const SkLight* light) const;
353
354private:
355 typedef SkRefCnt INHERITED;
356
357protected:
358 const GrGLShaderVar* fColorVar;
359 int fColorVarLocation;
360};
361
362///////////////////////////////////////////////////////////////////////////////
363
364class GrGLDistantLight : public GrGLLight {
365public:
senorblanco@chromium.org6730cbb2012-07-11 16:35:00 +0000366 virtual ~GrGLDistantLight() {}
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000367 virtual void setupVariables(GrGLShaderBuilder* state, int stage) SK_OVERRIDE;
368 virtual void initUniforms(const GrGLInterface* gl, int programID) SK_OVERRIDE;
369 virtual void setData(const GrGLInterface* gl, const SkLight* light) const SK_OVERRIDE;
370 virtual void emitSurfaceToLight(SkString* builder, const char* z) const SK_OVERRIDE;
371
372private:
373 typedef GrGLLight INHERITED;
374 const GrGLShaderVar* fDirectionVar;
375 int fDirectionLocation;
376};
377
378///////////////////////////////////////////////////////////////////////////////
379
380class GrGLPointLight : public GrGLLight {
381public:
senorblanco@chromium.org6730cbb2012-07-11 16:35:00 +0000382 virtual ~GrGLPointLight() {}
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000383 virtual void setupVariables(GrGLShaderBuilder* state, int stage);
384 virtual void initUniforms(const GrGLInterface* gl, int programID);
385 virtual void setData(const GrGLInterface* gl, const SkLight* light) const SK_OVERRIDE;
386 virtual void emitVS(SkString* builder) const;
387 virtual void emitSurfaceToLight(SkString* builder, const char* z) const SK_OVERRIDE;
388
389private:
390 typedef GrGLLight INHERITED;
391 SkPoint3 fLocation;
392 const GrGLShaderVar* fLocationVar;
393 int fLocationLocation;
394 const char* fHeightVaryingName;
395};
396
397///////////////////////////////////////////////////////////////////////////////
398
399class GrGLSpotLight : public GrGLLight {
400public:
senorblanco@chromium.org6730cbb2012-07-11 16:35:00 +0000401 virtual ~GrGLSpotLight() {}
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000402 virtual void setupVariables(GrGLShaderBuilder* state, int stage);
403 virtual void initUniforms(const GrGLInterface* gl, int programID);
404 virtual void setData(const GrGLInterface* gl, const SkLight* light) const SK_OVERRIDE;
405 virtual void emitVS(SkString* builder) const;
406 virtual void emitFuncs(SkString* builder) const;
407 virtual void emitSurfaceToLight(SkString* builder, const char* z) const SK_OVERRIDE;
408 virtual void emitLightColor(SkString* builder, const char *surfaceToLight) const;
409
410private:
411 typedef GrGLLight INHERITED;
412
413 const GrGLShaderVar* fLocationVar;
414 int fLocationLocation;
415 const GrGLShaderVar* fExponentVar;
416 int fExponentLocation;
417 const GrGLShaderVar* fCosOuterConeAngleVar;
418 int fCosOuterConeAngleLocation;
419 const GrGLShaderVar* fCosInnerConeAngleVar;
420 int fCosInnerConeAngleLocation;
421 const GrGLShaderVar* fConeScaleVar;
422 int fConeScaleLocation;
423 const GrGLShaderVar* fSVar;
424 int fSLocation;
425 const char* fHeightVaryingName;
426};
427
428};
429
430///////////////////////////////////////////////////////////////////////////////
431
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000432class SkLight : public SkFlattenable {
433public:
robertphillips@google.com0456e0b2012-06-27 14:03:26 +0000434 SK_DECLARE_INST_COUNT(SkLight)
435
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000436 enum LightType {
437 kDistant_LightType,
438 kPoint_LightType,
439 kSpot_LightType,
440 };
441 virtual LightType type() const = 0;
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000442 const SkPoint3& color() const { return fColor; }
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000443 virtual GrGLLight* createGLLight() const = 0;
444 virtual bool isEqual(const SkLight& other) const {
445 return fColor == other.fColor;
446 }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000447
djsollen@google.com08337772012-06-26 14:33:13 +0000448protected:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000449 SkLight(SkColor color)
450 : fColor(SkIntToScalar(SkColorGetR(color)),
451 SkIntToScalar(SkColorGetG(color)),
452 SkIntToScalar(SkColorGetB(color))) {}
453 SkLight(SkFlattenableReadBuffer& buffer)
454 : INHERITED(buffer) {
455 fColor = readPoint3(buffer);
456 }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000457 virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
djsollen@google.com08337772012-06-26 14:33:13 +0000458 INHERITED::flatten(buffer);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000459 writePoint3(fColor, buffer);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000460 }
djsollen@google.com08337772012-06-26 14:33:13 +0000461
462private:
463 typedef SkFlattenable INHERITED;
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000464 SkPoint3 fColor;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000465};
466
robertphillips@google.com0456e0b2012-06-27 14:03:26 +0000467SK_DEFINE_INST_COUNT(SkLight)
468
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000469///////////////////////////////////////////////////////////////////////////////
470
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000471class SkDistantLight : public SkLight {
472public:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000473 SkDistantLight(const SkPoint3& direction, SkColor color)
474 : INHERITED(color), fDirection(direction) {
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000475 }
djsollen@google.com08337772012-06-26 14:33:13 +0000476
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000477 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
478 return fDirection;
479 };
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000480 SkPoint3 lightColor(const SkPoint3&) const { return color(); }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000481 virtual LightType type() const { return kDistant_LightType; }
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000482 const SkPoint3& direction() const { return fDirection; }
483 virtual GrGLLight* createGLLight() const SK_OVERRIDE;
senorblanco@chromium.org6730cbb2012-07-11 16:35:00 +0000484 virtual bool isEqual(const SkLight& other) const SK_OVERRIDE {
485 if (other.type() != kDistant_LightType) {
486 return false;
487 }
488
489 const SkDistantLight& o = static_cast<const SkDistantLight&>(other);
490 return INHERITED::isEqual(other) &&
491 fDirection == o.fDirection;
492 }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000493
494 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDistantLight)
495
djsollen@google.com08337772012-06-26 14:33:13 +0000496protected:
497 SkDistantLight(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
498 fDirection = readPoint3(buffer);
499 }
500 virtual void flatten(SkFlattenableWriteBuffer& buffer) const {
501 INHERITED::flatten(buffer);
502 writePoint3(fDirection, buffer);
503 }
504
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000505private:
djsollen@google.com08337772012-06-26 14:33:13 +0000506 typedef SkLight INHERITED;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000507 SkPoint3 fDirection;
508};
509
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000510///////////////////////////////////////////////////////////////////////////////
511
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000512class SkPointLight : public SkLight {
513public:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000514 SkPointLight(const SkPoint3& location, SkColor color)
515 : INHERITED(color), fLocation(location) {}
djsollen@google.com08337772012-06-26 14:33:13 +0000516
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000517 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
518 SkPoint3 direction(fLocation.fX - SkIntToScalar(x),
519 fLocation.fY - SkIntToScalar(y),
520 fLocation.fZ - SkScalarMul(SkIntToScalar(z), surfaceScale));
521 direction.normalize();
522 return direction;
523 };
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000524 SkPoint3 lightColor(const SkPoint3&) const { return color(); }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000525 virtual LightType type() const { return kPoint_LightType; }
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000526 const SkPoint3& location() const { return fLocation; }
527 virtual GrGLLight* createGLLight() const SK_OVERRIDE {
528 return new GrGLPointLight();
529 }
senorblanco@chromium.org6730cbb2012-07-11 16:35:00 +0000530 virtual bool isEqual(const SkLight& other) const SK_OVERRIDE {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000531 if (other.type() != kPoint_LightType) {
532 return false;
533 }
534 const SkPointLight& o = static_cast<const SkPointLight&>(other);
535 return INHERITED::isEqual(other) &&
536 fLocation == o.fLocation;
537 }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000538
539 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkPointLight)
540
djsollen@google.com08337772012-06-26 14:33:13 +0000541protected:
542 SkPointLight(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
543 fLocation = readPoint3(buffer);
544 }
545 virtual void flatten(SkFlattenableWriteBuffer& buffer) const {
546 INHERITED::flatten(buffer);
547 writePoint3(fLocation, buffer);
548 }
549
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000550private:
djsollen@google.com08337772012-06-26 14:33:13 +0000551 typedef SkLight INHERITED;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000552 SkPoint3 fLocation;
553};
554
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000555///////////////////////////////////////////////////////////////////////////////
556
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000557class SkSpotLight : public SkLight {
558public:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000559 SkSpotLight(const SkPoint3& location, const SkPoint3& target, SkScalar specularExponent, SkScalar cutoffAngle, SkColor color)
560 : INHERITED(color),
561 fLocation(location),
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000562 fTarget(target),
563 fSpecularExponent(specularExponent)
564 {
565 fS = target - location;
566 fS.normalize();
567 fCosOuterConeAngle = SkScalarCos(SkDegreesToRadians(cutoffAngle));
568 const SkScalar antiAliasThreshold = SkFloatToScalar(0.016f);
569 fCosInnerConeAngle = fCosOuterConeAngle + antiAliasThreshold;
570 fConeScale = SkScalarInvert(antiAliasThreshold);
571 }
djsollen@google.com08337772012-06-26 14:33:13 +0000572
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000573 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
574 SkPoint3 direction(fLocation.fX - SkIntToScalar(x),
575 fLocation.fY - SkIntToScalar(y),
576 fLocation.fZ - SkScalarMul(SkIntToScalar(z), surfaceScale));
577 direction.normalize();
578 return direction;
579 };
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000580 SkPoint3 lightColor(const SkPoint3& surfaceToLight) const {
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000581 SkScalar cosAngle = -surfaceToLight.dot(fS);
582 if (cosAngle < fCosOuterConeAngle) {
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000583 return SkPoint3(0, 0, 0);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000584 }
585 SkScalar scale = SkScalarPow(cosAngle, fSpecularExponent);
586 if (cosAngle < fCosInnerConeAngle) {
587 scale = SkScalarMul(scale, cosAngle - fCosOuterConeAngle);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000588 return color() * SkScalarMul(scale, fConeScale);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000589 }
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000590 return color() * scale;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000591 }
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000592 virtual GrGLLight* createGLLight() const SK_OVERRIDE {
593 return new GrGLSpotLight();
594 }
djsollen@google.com08337772012-06-26 14:33:13 +0000595 virtual LightType type() const { return kSpot_LightType; }
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000596 const SkPoint3& location() const { return fLocation; }
597 const SkPoint3& target() const { return fTarget; }
598 SkScalar specularExponent() const { return fSpecularExponent; }
599 SkScalar cosInnerConeAngle() const { return fCosInnerConeAngle; }
600 SkScalar cosOuterConeAngle() const { return fCosOuterConeAngle; }
601 SkScalar coneScale() const { return fConeScale; }
602 SkPoint3 s() const { return fS; }
djsollen@google.com08337772012-06-26 14:33:13 +0000603
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000604 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSpotLight)
605
djsollen@google.com08337772012-06-26 14:33:13 +0000606protected:
607 SkSpotLight(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
608 fLocation = readPoint3(buffer);
609 fTarget = readPoint3(buffer);
610 fSpecularExponent = buffer.readScalar();
611 fCosOuterConeAngle = buffer.readScalar();
612 fCosInnerConeAngle = buffer.readScalar();
613 fConeScale = buffer.readScalar();
614 fS = readPoint3(buffer);
615 }
616 virtual void flatten(SkFlattenableWriteBuffer& buffer) const {
617 INHERITED::flatten(buffer);
618 writePoint3(fLocation, buffer);
619 writePoint3(fTarget, buffer);
620 buffer.writeScalar(fSpecularExponent);
621 buffer.writeScalar(fCosOuterConeAngle);
622 buffer.writeScalar(fCosInnerConeAngle);
623 buffer.writeScalar(fConeScale);
624 writePoint3(fS, buffer);
625 }
626
senorblanco@chromium.orgbd9fad62012-07-11 16:25:37 +0000627 virtual bool isEqual(const SkLight& other) const SK_OVERRIDE {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000628 if (other.type() != kSpot_LightType) {
629 return false;
630 }
631
632 const SkSpotLight& o = static_cast<const SkSpotLight&>(other);
633 return INHERITED::isEqual(other) &&
634 fLocation == o.fLocation &&
635 fTarget == o.fTarget &&
636 fSpecularExponent == o.fSpecularExponent &&
637 fCosOuterConeAngle == o.fCosOuterConeAngle;
638 }
639
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000640private:
djsollen@google.com08337772012-06-26 14:33:13 +0000641 typedef SkLight INHERITED;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000642 SkPoint3 fLocation;
643 SkPoint3 fTarget;
644 SkScalar fSpecularExponent;
645 SkScalar fCosOuterConeAngle;
646 SkScalar fCosInnerConeAngle;
647 SkScalar fConeScale;
648 SkPoint3 fS;
649};
650
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000651///////////////////////////////////////////////////////////////////////////////
652
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000653SkLightingImageFilter::SkLightingImageFilter(SkLight* light, SkScalar surfaceScale)
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000654 : fLight(light),
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000655 fSurfaceScale(SkScalarDiv(surfaceScale, SkIntToScalar(255)))
656{
657 SkASSERT(fLight);
reed@google.com51f38662012-06-27 14:24:29 +0000658 // our caller knows that we take ownership of the light, so we don't
659 // need to call ref() here.
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000660}
661
662SkImageFilter* SkLightingImageFilter::CreateDistantLitDiffuse(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000663 const SkPoint3& direction, SkColor lightColor, SkScalar surfaceScale,
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000664 SkScalar kd) {
665 return new SkDiffuseLightingImageFilter(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000666 new SkDistantLight(direction, lightColor), surfaceScale, kd);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000667}
668
669SkImageFilter* SkLightingImageFilter::CreatePointLitDiffuse(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000670 const SkPoint3& location, SkColor lightColor, SkScalar surfaceScale,
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000671 SkScalar kd) {
672 return new SkDiffuseLightingImageFilter(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000673 new SkPointLight(location, lightColor), surfaceScale, kd);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000674}
675
676SkImageFilter* SkLightingImageFilter::CreateSpotLitDiffuse(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000677 const SkPoint3& location, const SkPoint3& target,
678 SkScalar specularExponent, SkScalar cutoffAngle,
679 SkColor lightColor, SkScalar surfaceScale, SkScalar kd) {
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000680 return new SkDiffuseLightingImageFilter(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000681 new SkSpotLight(location, target, specularExponent, cutoffAngle, lightColor),
682 surfaceScale, kd);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000683}
684
685SkImageFilter* SkLightingImageFilter::CreateDistantLitSpecular(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000686 const SkPoint3& direction, SkColor lightColor, SkScalar surfaceScale,
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000687 SkScalar ks, SkScalar shininess) {
688 return new SkSpecularLightingImageFilter(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000689 new SkDistantLight(direction, lightColor), surfaceScale, ks, shininess);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000690}
691
692SkImageFilter* SkLightingImageFilter::CreatePointLitSpecular(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000693 const SkPoint3& location, SkColor lightColor, SkScalar surfaceScale,
694 SkScalar ks, SkScalar shininess) {
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000695 return new SkSpecularLightingImageFilter(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000696 new SkPointLight(location, lightColor), surfaceScale, ks, shininess);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000697}
698
699SkImageFilter* SkLightingImageFilter::CreateSpotLitSpecular(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000700 const SkPoint3& location, const SkPoint3& target,
701 SkScalar specularExponent, SkScalar cutoffAngle,
702 SkColor lightColor, SkScalar surfaceScale,
703 SkScalar ks, SkScalar shininess) {
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000704 return new SkSpecularLightingImageFilter(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000705 new SkSpotLight(location, target, specularExponent, cutoffAngle, lightColor),
706 surfaceScale, ks, shininess);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000707}
708
709SkLightingImageFilter::~SkLightingImageFilter() {
710 fLight->unref();
711}
712
713SkLightingImageFilter::SkLightingImageFilter(SkFlattenableReadBuffer& buffer)
714 : INHERITED(buffer)
715{
djsollen@google.com08337772012-06-26 14:33:13 +0000716 fLight = (SkLight*)buffer.readFlattenable();
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000717 fSurfaceScale = buffer.readScalar();
718}
719
720void SkLightingImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
721 this->INHERITED::flatten(buffer);
djsollen@google.com08337772012-06-26 14:33:13 +0000722 buffer.writeFlattenable(fLight);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000723 buffer.writeScalar(fSurfaceScale);
724}
725
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000726///////////////////////////////////////////////////////////////////////////////
727
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000728SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar kd)
729 : SkLightingImageFilter(light, surfaceScale),
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000730 fKD(kd)
731{
732}
733
734SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkFlattenableReadBuffer& buffer)
735 : INHERITED(buffer)
736{
737 fKD = buffer.readScalar();
738}
739
740void SkDiffuseLightingImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
741 this->INHERITED::flatten(buffer);
742 buffer.writeScalar(fKD);
743}
744
745bool SkDiffuseLightingImageFilter::onFilterImage(Proxy*,
746 const SkBitmap& src,
747 const SkMatrix&,
748 SkBitmap* dst,
749 SkIPoint*) {
750 if (src.config() != SkBitmap::kARGB_8888_Config) {
751 return false;
752 }
753 SkAutoLockPixels alp(src);
754 if (!src.getPixels()) {
755 return false;
756 }
757 if (src.width() < 2 || src.height() < 2) {
758 return false;
759 }
760 dst->setConfig(src.config(), src.width(), src.height());
761 dst->allocPixels();
762
763 DiffuseLightingType lightingType(fKD);
764 switch (light()->type()) {
765 case SkLight::kDistant_LightType:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000766 lightBitmap<DiffuseLightingType, SkDistantLight>(lightingType, light(), src, dst, surfaceScale());
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000767 break;
768 case SkLight::kPoint_LightType:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000769 lightBitmap<DiffuseLightingType, SkPointLight>(lightingType, light(), src, dst, surfaceScale());
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000770 break;
771 case SkLight::kSpot_LightType:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000772 lightBitmap<DiffuseLightingType, SkSpotLight>(lightingType, light(), src, dst, surfaceScale());
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000773 break;
774 }
775 return true;
776}
777
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000778bool SkDiffuseLightingImageFilter::asNewCustomStage(GrCustomStage** stage) const {
779 if (stage) {
780 SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255));
781 *stage = new GrDiffuseLightingEffect(light(), scale, kd());
782 }
783 return true;
784}
785
786///////////////////////////////////////////////////////////////////////////////
787
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000788SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess)
789 : SkLightingImageFilter(light, surfaceScale),
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000790 fKS(ks),
791 fShininess(shininess)
792{
793}
794
795SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkFlattenableReadBuffer& buffer)
796 : INHERITED(buffer)
797{
798 fKS = buffer.readScalar();
799 fShininess = buffer.readScalar();
800}
801
802void SkSpecularLightingImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
803 this->INHERITED::flatten(buffer);
804 buffer.writeScalar(fKS);
805 buffer.writeScalar(fShininess);
806}
807
808bool SkSpecularLightingImageFilter::onFilterImage(Proxy*,
809 const SkBitmap& src,
810 const SkMatrix&,
811 SkBitmap* dst,
812 SkIPoint*) {
813 if (src.config() != SkBitmap::kARGB_8888_Config) {
814 return false;
815 }
816 SkAutoLockPixels alp(src);
817 if (!src.getPixels()) {
818 return false;
819 }
820 if (src.width() < 2 || src.height() < 2) {
821 return false;
822 }
823 dst->setConfig(src.config(), src.width(), src.height());
824 dst->allocPixels();
825
826 SpecularLightingType lightingType(fKS, fShininess);
827 switch (light()->type()) {
828 case SkLight::kDistant_LightType:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000829 lightBitmap<SpecularLightingType, SkDistantLight>(lightingType, light(), src, dst, surfaceScale());
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000830 break;
831 case SkLight::kPoint_LightType:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000832 lightBitmap<SpecularLightingType, SkPointLight>(lightingType, light(), src, dst, surfaceScale());
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000833 break;
834 case SkLight::kSpot_LightType:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000835 lightBitmap<SpecularLightingType, SkSpotLight>(lightingType, light(), src, dst, surfaceScale());
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000836 break;
837 }
838 return true;
839}
840
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000841bool SkSpecularLightingImageFilter::asNewCustomStage(GrCustomStage** stage) const {
842 if (stage) {
843 SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255));
844 *stage = new GrSpecularLightingEffect(light(), scale, ks(), shininess());
845 }
846 return true;
847}
848
849///////////////////////////////////////////////////////////////////////////////
850
851class GrGLLightingEffect : public GrGLProgramStage {
852public:
853 GrGLLightingEffect(const GrProgramStageFactory& factory,
854 const GrCustomStage& stage);
855 virtual ~GrGLLightingEffect();
856
857 virtual void setupVariables(GrGLShaderBuilder* state,
858 int stage) SK_OVERRIDE;
859 virtual void emitVS(GrGLShaderBuilder* state,
860 const char* vertexCoords) SK_OVERRIDE;
861 virtual void emitFS(GrGLShaderBuilder* state,
862 const char* outputColor,
863 const char* inputColor,
864 const char* samplerName) SK_OVERRIDE;
865
866 virtual void emitLightFunc(SkString* funcs) = 0;
867
868 static inline StageKey GenKey(const GrCustomStage& s);
869
870 virtual void initUniforms(const GrGLInterface*, int programID) SK_OVERRIDE;
871 virtual void setData(const GrGLInterface*,
872 const GrGLTexture&,
873 const GrCustomStage&,
874 int stageNum) SK_OVERRIDE;
875
876private:
877 typedef GrGLProgramStage INHERITED;
878
879 const GrGLShaderVar* fImageIncrementVar;
880 GrGLint fImageIncrementLocation;
881 const GrGLShaderVar* fSurfaceScaleVar;
882 GrGLint fSurfaceScaleLocation;
883 GrGLLight* fLight;
884};
885
886///////////////////////////////////////////////////////////////////////////////
887
888class GrGLDiffuseLightingEffect : public GrGLLightingEffect {
889public:
890 GrGLDiffuseLightingEffect(const GrProgramStageFactory& factory,
891 const GrCustomStage& stage);
892 virtual void setupVariables(GrGLShaderBuilder* state,
893 int stage) SK_OVERRIDE;
894 virtual void emitLightFunc(SkString* funcs) SK_OVERRIDE;
895 virtual void initUniforms(const GrGLInterface*, int programID) SK_OVERRIDE;
896 virtual void setData(const GrGLInterface*,
897 const GrGLTexture&,
898 const GrCustomStage&,
899 int stageNum) SK_OVERRIDE;
900
901private:
902 typedef GrGLLightingEffect INHERITED;
903
904 const GrGLShaderVar* fKDVar;
905 GrGLint fKDLocation;
906};
907
908///////////////////////////////////////////////////////////////////////////////
909
910class GrGLSpecularLightingEffect : public GrGLLightingEffect {
911public:
912 GrGLSpecularLightingEffect(const GrProgramStageFactory& factory,
913 const GrCustomStage& stage);
914 virtual void setupVariables(GrGLShaderBuilder* state,
915 int stage) SK_OVERRIDE;
916 virtual void emitLightFunc(SkString* funcs) SK_OVERRIDE;
917 virtual void initUniforms(const GrGLInterface*, int programID) SK_OVERRIDE;
918 virtual void setData(const GrGLInterface*,
919 const GrGLTexture&,
920 const GrCustomStage&,
921 int stageNum) SK_OVERRIDE;
922
923private:
924 typedef GrGLLightingEffect INHERITED;
925
926 const GrGLShaderVar* fKSVar;
927 GrGLint fKSLocation;
928 const GrGLShaderVar* fShininessVar;
929 GrGLint fShininessLocation;
930};
931
932///////////////////////////////////////////////////////////////////////////////
933
934GrLightingEffect::GrLightingEffect(const SkLight* light, SkScalar surfaceScale)
935 : fLight(light)
936 , fSurfaceScale(surfaceScale) {
937 fLight->ref();
938}
939
940GrLightingEffect::~GrLightingEffect() {
941 fLight->unref();
942}
943
944bool GrLightingEffect::isEqual(const GrCustomStage& sBase) const {
945 const GrLightingEffect& s =
946 static_cast<const GrLightingEffect&>(sBase);
947 return fLight->isEqual(*s.fLight) &&
948 fSurfaceScale == s.fSurfaceScale;
949}
950
951///////////////////////////////////////////////////////////////////////////////
952
953GrDiffuseLightingEffect::GrDiffuseLightingEffect(const SkLight* light, SkScalar surfaceScale, SkScalar kd)
954 : INHERITED(light, surfaceScale), fKD(kd) {
955}
956
957const GrProgramStageFactory& GrDiffuseLightingEffect::getFactory() const {
958 return GrTProgramStageFactory<GrDiffuseLightingEffect>::getInstance();
959}
960
961bool GrDiffuseLightingEffect::isEqual(const GrCustomStage& sBase) const {
962 const GrDiffuseLightingEffect& s =
963 static_cast<const GrDiffuseLightingEffect&>(sBase);
964 return INHERITED::isEqual(sBase) &&
965 this->kd() == s.kd();
966}
967
968///////////////////////////////////////////////////////////////////////////////
969
970GrGLLightingEffect::GrGLLightingEffect(const GrProgramStageFactory& factory,
971 const GrCustomStage& stage)
972 : GrGLProgramStage(factory)
973 , fImageIncrementVar(NULL)
974 , fImageIncrementLocation(0)
975 , fSurfaceScaleVar(NULL)
976 , fSurfaceScaleLocation(0) {
977 const GrLightingEffect& m = static_cast<const GrLightingEffect&>(stage);
978 fLight = m.light()->createGLLight();
979}
980
981GrGLLightingEffect::~GrGLLightingEffect() {
982 delete fLight;
983}
984
985void GrGLLightingEffect::setupVariables(GrGLShaderBuilder* state, int stage) {
986 fImageIncrementVar = &state->addUniform(
987 GrGLShaderBuilder::kFragment_ShaderType,
988 kVec2f_GrSLType, "uImageIncrement", stage);
989 fSurfaceScaleVar = &state->addUniform(
990 GrGLShaderBuilder::kFragment_ShaderType,
991 kFloat_GrSLType, "uSurfaceScale", stage);
992 fLight->setupVariables(state, stage);
993}
994
995void GrGLLightingEffect::emitVS(GrGLShaderBuilder* state,
996 const char* vertexCoords) {
997 fLight->emitVS(&state->fVSCode);
998}
999
1000void GrGLLightingEffect::initUniforms(const GrGLInterface* gl,
1001 int programID) {
1002 GR_GL_CALL_RET(gl, fSurfaceScaleLocation,
1003 GetUniformLocation(programID,
1004 fSurfaceScaleVar->getName().c_str()));
1005 GR_GL_CALL_RET(gl, fImageIncrementLocation,
1006 GetUniformLocation(programID,
1007 fImageIncrementVar->getName().c_str()));
1008 fLight->initUniforms(gl, programID);
1009}
1010
1011void GrGLLightingEffect::emitFS(GrGLShaderBuilder* state,
1012 const char* outputColor,
1013 const char* inputColor,
1014 const char* samplerName) {
1015 SkString* code = &state->fFSCode;
1016 SkString* funcs = &state->fFSFunctions;
1017 fLight->emitFuncs(funcs);
1018 emitLightFunc(funcs);
1019 funcs->appendf("float sobel(float a, float b, float c, float d, float e, float f, float scale) {\n");
1020 funcs->appendf("\treturn (-a + b - 2 * c + 2 * d -e + f) * scale;\n");
1021 funcs->appendf("}\n");
1022 funcs->appendf("vec3 pointToNormal(float x, float y, float scale) {\n");
1023 funcs->appendf("\treturn normalize(vec3(-x * scale, -y * scale, 1));\n");
1024 funcs->appendf("}\n");
1025 funcs->append("\n\
1026vec3 interiorNormal(float m[9], float surfaceScale) {\n\
1027 return pointToNormal(sobel(m[0], m[2], m[3], m[5], m[6], m[8], 0.25),\n\
1028 sobel(m[0], m[6], m[1], m[7], m[2], m[8], 0.25),\n\
1029 surfaceScale);\n}\n");
1030
1031 code->appendf("\t\tvec2 coord = %s;\n", state->fSampleCoords.c_str());
1032 code->appendf("\t\tfloat m[9];\n");
1033 int index = 0;
1034 for (int dy = -1; dy <= 1; dy++) {
1035 for (int dx = -1; dx <= 1; dx++) {
1036 SkString texCoords;
1037 texCoords.appendf("coord + vec2(%d, %d) * %s", dx, dy, fImageIncrementVar->getName().c_str());
1038 code->appendf("\t\tm[%d] = ", index++);
1039 state->emitTextureLookup(samplerName, texCoords.c_str());
1040 code->appendf(".a;\n");
1041 }
1042 }
1043 code->appendf("\t\tvec3 surfaceToLight = ");
1044 SkString arg;
1045 arg.appendf("%s * m[4]", fSurfaceScaleVar->getName().c_str());
1046 fLight->emitSurfaceToLight(code, arg.c_str());
1047 code->appendf(";\n");
1048 code->appendf("\t\t%s = light(interiorNormal(m, %s), surfaceToLight, ", outputColor, fSurfaceScaleVar->getName().c_str());
1049 fLight->emitLightColor(code, "surfaceToLight");
1050 code->appendf(")%s;\n", state->fModulate.c_str());
1051}
1052
1053GrGLProgramStage::StageKey GrGLLightingEffect::GenKey(
1054 const GrCustomStage& s) {
1055 return static_cast<const GrLightingEffect&>(s).light()->type();
1056}
1057
1058void GrGLLightingEffect::setData(const GrGLInterface* gl,
1059 const GrGLTexture& texture,
1060 const GrCustomStage& data,
1061 int stageNum) {
1062 const GrLightingEffect& effect =
1063 static_cast<const GrLightingEffect&>(data);
1064 GR_GL_CALL(gl, Uniform2f(fImageIncrementLocation, 1.0f / texture.width(), 1.0f / texture.height()));
1065 GR_GL_CALL(gl, Uniform1f(fSurfaceScaleLocation, effect.surfaceScale()));
1066 fLight->setData(gl, effect.light());
1067}
1068
1069///////////////////////////////////////////////////////////////////////////////
1070
1071///////////////////////////////////////////////////////////////////////////////
1072
1073GrGLDiffuseLightingEffect::GrGLDiffuseLightingEffect(const GrProgramStageFactory& factory,
1074 const GrCustomStage& stage)
1075 : INHERITED(factory, stage)
1076 , fKDVar(NULL)
1077 , fKDLocation(0) {
1078}
1079
1080void GrGLDiffuseLightingEffect::setupVariables(GrGLShaderBuilder* state, int stage) {
1081 INHERITED::setupVariables(state, stage);
1082 fKDVar = &state->addUniform(
1083 GrGLShaderBuilder::kFragment_ShaderType,
1084 kFloat_GrSLType, "uKD", stage);
1085}
1086
1087void GrGLDiffuseLightingEffect::initUniforms(const GrGLInterface* gl,
1088 int programID) {
1089 INHERITED::initUniforms(gl, programID);
1090 GR_GL_CALL_RET(gl, fKDLocation,
1091 GetUniformLocation(programID,
1092 fKDVar->getName().c_str()));
1093}
1094
1095void GrGLDiffuseLightingEffect::emitLightFunc(SkString* funcs) {
1096 funcs->appendf("vec4 light(vec3 normal, vec3 surfaceToLight, vec3 lightColor) {\n");
1097 funcs->appendf("\tfloat colorScale = %s * dot(normal, surfaceToLight);\n", fKDVar->getName().c_str());
1098 funcs->appendf("\treturn vec4(lightColor * clamp(colorScale, 0, 1), 1);\n");
1099 funcs->appendf("}\n");
1100}
1101
1102void GrGLDiffuseLightingEffect::setData(const GrGLInterface* gl,
1103 const GrGLTexture& texture,
1104 const GrCustomStage& data,
1105 int stageNum) {
1106 INHERITED::setData(gl, texture, data, stageNum);
1107 const GrDiffuseLightingEffect& effect =
1108 static_cast<const GrDiffuseLightingEffect&>(data);
1109 GR_GL_CALL(gl, Uniform1f(fKDLocation, effect.kd()));
1110}
1111
1112///////////////////////////////////////////////////////////////////////////////
1113
1114GrSpecularLightingEffect::GrSpecularLightingEffect(const SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess)
1115 : INHERITED(light, surfaceScale),
1116 fKS(ks),
1117 fShininess(shininess) {
1118}
1119
1120const GrProgramStageFactory& GrSpecularLightingEffect::getFactory() const {
1121 return GrTProgramStageFactory<GrSpecularLightingEffect>::getInstance();
1122}
1123
1124bool GrSpecularLightingEffect::isEqual(const GrCustomStage& sBase) const {
1125 const GrSpecularLightingEffect& s =
1126 static_cast<const GrSpecularLightingEffect&>(sBase);
1127 return INHERITED::isEqual(sBase) &&
1128 this->ks() == s.ks() &&
1129 this->shininess() == s.shininess();
1130}
1131
1132///////////////////////////////////////////////////////////////////////////////
1133
1134GrGLSpecularLightingEffect::GrGLSpecularLightingEffect(const GrProgramStageFactory& factory,
1135 const GrCustomStage& stage)
1136 : GrGLLightingEffect(factory, stage)
1137 , fKSVar(NULL)
1138 , fKSLocation(0)
1139 , fShininessVar(NULL)
1140 , fShininessLocation(0) {
1141}
1142
1143void GrGLSpecularLightingEffect::setupVariables(GrGLShaderBuilder* state, int stage) {
1144 INHERITED::setupVariables(state, stage);
1145 fKSVar = &state->addUniform(
1146 GrGLShaderBuilder::kFragment_ShaderType,
1147 kFloat_GrSLType, "uKS", stage);
1148 fShininessVar = &state->addUniform(
1149 GrGLShaderBuilder::kFragment_ShaderType,
1150 kFloat_GrSLType, "uShininess", stage);
1151}
1152
1153void GrGLSpecularLightingEffect::initUniforms(const GrGLInterface* gl,
1154 int programID) {
1155 INHERITED::initUniforms(gl, programID);
1156 GR_GL_CALL_RET(gl, fKSLocation,
1157 GetUniformLocation(programID, fKSVar->getName().c_str()));
1158 GR_GL_CALL_RET(gl, fShininessLocation,
1159 GetUniformLocation(programID, fShininessVar->getName().c_str()));
1160}
1161
1162void GrGLSpecularLightingEffect::emitLightFunc(SkString* funcs) {
1163 funcs->appendf("vec4 light(vec3 normal, vec3 surfaceToLight, vec3 lightColor) {\n");
1164 funcs->appendf("\tvec3 halfDir = vec3(normalize(surfaceToLight + vec3(0, 0, 1)));\n");
1165
1166 funcs->appendf("\tfloat colorScale = %s * pow(dot(normal, halfDir), %s);\n",
1167 fKSVar->getName().c_str(), fShininessVar->getName().c_str());
1168 funcs->appendf("\treturn vec4(lightColor * clamp(colorScale, 0, 1), 1);\n");
1169 funcs->appendf("}\n");
1170}
1171
1172void GrGLSpecularLightingEffect::setData(const GrGLInterface* gl,
1173 const GrGLTexture& texture,
1174 const GrCustomStage& data,
1175 int stageNum) {
1176 INHERITED::setData(gl, texture, data, stageNum);
1177 const GrSpecularLightingEffect& effect =
1178 static_cast<const GrSpecularLightingEffect&>(data);
1179 GR_GL_CALL(gl, Uniform1f(fKSLocation, effect.ks()));
1180 GR_GL_CALL(gl, Uniform1f(fShininessLocation, effect.shininess()));
1181}
1182
1183///////////////////////////////////////////////////////////////////////////////
1184
1185void GrGLLight::emitLightColor(SkString* builder, const char *surfaceToLight) const {
1186 builder->append(fColorVar->getName().c_str());
1187}
1188
1189void GrGLLight::setupVariables(GrGLShaderBuilder* state, int stage) {
1190 fColorVar = &state->addUniform(
1191 GrGLShaderBuilder::kFragment_ShaderType,
1192 kVec3f_GrSLType, "uLightColor", stage);
1193}
1194
1195void GrGLLight::initUniforms(const GrGLInterface* gl, int programID) {
1196 GR_GL_CALL_RET(gl, fColorVarLocation,
1197 GetUniformLocation(programID, fColorVar->getName().c_str()));
1198}
1199
1200void GrGLLight::setData(const GrGLInterface* gl, const SkLight* light) const {
1201 setUniformPoint3(gl, fColorVarLocation, light->color() * SkScalarInvert(SkIntToScalar(255)));
1202}
1203
1204GrGLLight* SkDistantLight::createGLLight() const {
1205 return new GrGLDistantLight();
1206}
1207
1208///////////////////////////////////////////////////////////////////////////////
1209
1210void GrGLDistantLight::setupVariables(GrGLShaderBuilder* state, int stage) {
1211 INHERITED::setupVariables(state, stage);
1212 fDirectionVar = &state->addUniform(
1213 GrGLShaderBuilder::kFragment_ShaderType, kVec3f_GrSLType,
1214 "uLightDirection", stage);
1215}
1216
1217void GrGLDistantLight::initUniforms(const GrGLInterface* gl, int programID) {
1218 INHERITED::initUniforms(gl, programID);
1219 GR_GL_CALL_RET(gl, fDirectionLocation,
1220 GetUniformLocation(programID, fDirectionVar->getName().c_str()));
1221}
1222
1223void GrGLDistantLight::setData(const GrGLInterface* gl, const SkLight* light) const {
1224 INHERITED::setData(gl, light);
1225 SkASSERT(light->type() == SkLight::kDistant_LightType);
1226 const SkDistantLight* distantLight = static_cast<const SkDistantLight*>(light);
1227 setUniformPoint3(gl, fDirectionLocation, distantLight->direction());
1228}
1229
1230void GrGLDistantLight::emitSurfaceToLight(SkString* builder,
1231 const char* z) const {
1232 builder->append(fDirectionVar->getName().c_str());
1233}
1234
1235///////////////////////////////////////////////////////////////////////////////
1236
1237void GrGLPointLight::setupVariables(GrGLShaderBuilder* state, int stage) {
1238 INHERITED::setupVariables(state, stage);
1239 fLocationVar = &state->addUniform(
1240 GrGLShaderBuilder::kFragment_ShaderType, kVec3f_GrSLType,
1241 "uLightLocation", stage);
1242 state->addVarying(kFloat_GrSLType, "Height", stage, &fHeightVaryingName);
1243}
1244
1245void GrGLPointLight::initUniforms(const GrGLInterface* gl, int programID) {
1246 INHERITED::initUniforms(gl, programID);
1247 GR_GL_CALL_RET(gl, fLocationLocation,
1248 GetUniformLocation(programID, fLocationVar->getName().c_str()));
1249}
1250
1251void GrGLPointLight::setData(const GrGLInterface* gl, const SkLight* light) const {
1252 INHERITED::setData(gl, light);
1253 SkASSERT(light->type() == SkLight::kPoint_LightType);
1254 const SkPointLight* pointLight = static_cast<const SkPointLight*>(light);
1255 setUniformPoint3(gl, fLocationLocation, pointLight->location());
1256}
1257
1258void GrGLPointLight::emitVS(SkString* builder) const {
1259 // Compute viewport height from the Y scale of the matrix.
1260 builder->appendf("\t\t%s = -2.0 / uViewM[1][1];\n", fHeightVaryingName);
1261}
1262
1263void GrGLPointLight::emitSurfaceToLight(SkString* builder,
1264 const char* z) const {
1265 builder->appendf(
1266 "normalize(%s - vec3(gl_FragCoord.x, %s - gl_FragCoord.y, %s))",
1267 fLocationVar->getName().c_str(), fHeightVaryingName, z);
1268}
1269
1270///////////////////////////////////////////////////////////////////////////////
1271
1272void GrGLSpotLight::setupVariables(GrGLShaderBuilder* state, int stage) {
1273 INHERITED::setupVariables(state, stage);
1274 fLocationVar = &state->addUniform(
1275 GrGLShaderBuilder::kFragment_ShaderType,
1276 kVec3f_GrSLType, "uLightLocation", stage);
1277 fExponentVar = &state->addUniform(
1278 GrGLShaderBuilder::kFragment_ShaderType,
1279 kFloat_GrSLType, "uExponent", stage);
1280 fCosInnerConeAngleVar = &state->addUniform(
1281 GrGLShaderBuilder::kFragment_ShaderType,
1282 kFloat_GrSLType, "uCosInnerConeAngle", stage);
1283 fCosOuterConeAngleVar = &state->addUniform(
1284 GrGLShaderBuilder::kFragment_ShaderType,
1285 kFloat_GrSLType, "uCosOuterConeAngle", stage);
1286 fConeScaleVar = &state->addUniform(
1287 GrGLShaderBuilder::kFragment_ShaderType,
1288 kFloat_GrSLType, "uConeScale", stage);
1289 fSVar = &state->addUniform(
1290 GrGLShaderBuilder::kFragment_ShaderType,
1291 kVec3f_GrSLType, "uS", stage);
1292 state->addVarying(kFloat_GrSLType, "Height", stage, &fHeightVaryingName);
1293}
1294
1295void GrGLSpotLight::initUniforms(const GrGLInterface* gl, int programID) {
1296 INHERITED::initUniforms(gl, programID);
1297 GR_GL_CALL_RET(gl, fLocationLocation,
1298 GetUniformLocation(programID, fLocationVar->getName().c_str()));
1299 GR_GL_CALL_RET(gl, fExponentLocation,
1300 GetUniformLocation(programID, fExponentVar->getName().c_str()));
1301 GR_GL_CALL_RET(gl, fCosInnerConeAngleLocation,
1302 GetUniformLocation(programID, fCosInnerConeAngleVar->getName().c_str()));
1303 GR_GL_CALL_RET(gl, fCosOuterConeAngleLocation,
1304 GetUniformLocation(programID, fCosOuterConeAngleVar->getName().c_str()));
1305 GR_GL_CALL_RET(gl, fCosOuterConeAngleLocation,
1306 GetUniformLocation(programID, fCosOuterConeAngleVar->getName().c_str()));
1307 GR_GL_CALL_RET(gl, fConeScaleLocation,
1308 GetUniformLocation(programID, fConeScaleVar->getName().c_str()));
1309 GR_GL_CALL_RET(gl, fSLocation,
1310 GetUniformLocation(programID, fSVar->getName().c_str()));
1311}
1312
1313void GrGLSpotLight::setData(const GrGLInterface* gl, const SkLight* light) const {
1314 INHERITED::setData(gl, light);
1315 SkASSERT(light->type() == SkLight::kSpot_LightType);
1316 const SkSpotLight* spotLight = static_cast<const SkSpotLight *>(light);
1317 setUniformPoint3(gl, fLocationLocation, spotLight->location());
1318 GR_GL_CALL(gl, Uniform1f(fExponentLocation, spotLight->specularExponent()));
1319 GR_GL_CALL(gl, Uniform1f(fCosInnerConeAngleLocation, spotLight->cosInnerConeAngle()));
1320 GR_GL_CALL(gl, Uniform1f(fCosOuterConeAngleLocation, spotLight->cosOuterConeAngle()));
1321 GR_GL_CALL(gl, Uniform1f(fConeScaleLocation, spotLight->coneScale()));
1322 setUniformPoint3(gl, fSLocation, spotLight->s());
1323}
1324
1325void GrGLSpotLight::emitVS(SkString* builder) const {
1326 // Compute viewport height from the Y scale of the matrix.
1327 builder->appendf("\t\t%s = -2.0 / uViewM[1][1];\n", fHeightVaryingName);
1328}
1329
1330void GrGLSpotLight::emitFuncs(SkString* builder) const {
1331 builder->appendf("vec3 lightColor(vec3 surfaceToLight) {\n");
1332 builder->appendf("\tfloat cosAngle = -dot(surfaceToLight, %s);\n", fSVar->getName().c_str());
1333 builder->appendf("\tif (cosAngle < %s) {\n", fCosOuterConeAngleVar->getName().c_str());
1334 builder->appendf("\t\treturn vec3(0);\n");
1335 builder->appendf("\t}\n");
1336 builder->appendf("\tfloat scale = pow(cosAngle, %s);\n", fExponentVar->getName().c_str());
1337 builder->appendf("\tif (cosAngle < %s) {\n", fCosInnerConeAngleVar->getName().c_str());
1338 builder->appendf("\t\treturn %s * scale * (cosAngle - %s) * %s;\n", fColorVar->getName().c_str(), fCosOuterConeAngleVar->getName().c_str(), fConeScaleVar->getName().c_str());
1339 builder->appendf("\t}\n");
1340 builder->appendf("\treturn %s;\n", fColorVar->getName().c_str());
1341 builder->appendf("}\n");
1342}
1343
1344void GrGLSpotLight::emitSurfaceToLight(SkString* builder, const char* z) const {
1345 builder->appendf("normalize(%s - vec3(gl_FragCoord.x, %s - gl_FragCoord.y, %s))", fLocationVar->getName().c_str(), fHeightVaryingName, z);
1346}
1347
1348void GrGLSpotLight::emitLightColor(SkString* builder, const char *surfaceToLight) const {
1349 builder->appendf("lightColor(%s)", surfaceToLight);
1350}
1351
djsollen@google.com08337772012-06-26 14:33:13 +00001352SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingImageFilter)
1353 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDiffuseLightingImageFilter)
1354 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSpecularLightingImageFilter)
1355 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDistantLight)
1356 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPointLight)
1357 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSpotLight)
1358SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END