blob: ddb31936ca1029dcfc58c8bae7e968850ab9a5e4 [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"
djsollen@google.comc73dd5c2012-08-07 15:54:32 +000011#include "SkFlattenableBuffers.h"
12#include "SkOrderedReadBuffer.h"
13#include "SkOrderedWriteBuffer.h"
tomhudson@google.com300f5622012-07-20 14:15:22 +000014#include "SkTypes.h"
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +000015
16#if SK_SUPPORT_GPU
senorblanco@chromium.org894790d2012-07-11 16:01:22 +000017#include "GrProgramStageFactory.h"
tomhudson@google.comd0c1a062012-07-12 17:23:52 +000018#include "effects/GrSingleTextureEffect.h"
senorblanco@chromium.org894790d2012-07-11 16:01:22 +000019#include "gl/GrGLProgramStage.h"
senorblanco@chromium.org894790d2012-07-11 16:01:22 +000020#include "gl/GrGLTexture.h"
21#include "GrCustomStage.h"
22
23class GrGLDiffuseLightingEffect;
24class GrGLSpecularLightingEffect;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +000025
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000026// For brevity
27typedef GrGLUniformManager::UniformHandle UniformHandle;
28static const UniformHandle kInvalidUniformHandle = GrGLUniformManager::kInvalidUniformHandle;
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +000029#endif
bsalomon@google.com032b2212012-07-16 13:36:18 +000030
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +000031namespace {
32
33const SkScalar gOneThird = SkScalarInvert(SkIntToScalar(3));
34const SkScalar gTwoThirds = SkScalarDiv(SkIntToScalar(2), SkIntToScalar(3));
35const SkScalar gOneHalf = SkFloatToScalar(0.5f);
36const SkScalar gOneQuarter = SkFloatToScalar(0.25f);
37
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +000038#if SK_SUPPORT_GPU
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000039void setUniformPoint3(const GrGLUniformManager& uman, UniformHandle uni, const SkPoint3& point) {
bsalomon@google.comb9119a62012-07-25 17:55:26 +000040 GR_STATIC_ASSERT(sizeof(SkPoint3) == 3 * sizeof(GrGLfloat));
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000041 uman.set3fv(uni, 0, 1, &point.fX);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +000042}
43
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000044void setUniformNormal3(const GrGLUniformManager& uman, UniformHandle uni, const SkPoint3& point) {
45 setUniformPoint3(uman, uni, SkPoint3(point.fX, -point.fY, point.fZ));
senorblanco@chromium.orgf4770d72012-07-13 18:25:06 +000046}
47
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000048void setUniformPoint3FlipY(const GrGLUniformManager& uman,
49 UniformHandle uni,
50 const SkPoint3& point,
51 int height) {
52 setUniformPoint3(uman, uni, SkPoint3(point.fX, height-point.fY, point.fZ));
senorblanco@chromium.orgf4770d72012-07-13 18:25:06 +000053}
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +000054#endif
senorblanco@chromium.orgf4770d72012-07-13 18:25:06 +000055
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +000056// Shift matrix components to the left, as we advance pixels to the right.
57inline void shiftMatrixLeft(int m[9]) {
58 m[0] = m[1];
59 m[3] = m[4];
60 m[6] = m[7];
61 m[1] = m[2];
62 m[4] = m[5];
63 m[7] = m[8];
64}
65
66class DiffuseLightingType {
67public:
68 DiffuseLightingType(SkScalar kd)
69 : fKD(kd) {}
70 SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight, const SkPoint3& lightColor) const {
71 SkScalar colorScale = SkScalarMul(fKD, normal.dot(surfaceTolight));
72 colorScale = SkScalarClampMax(colorScale, SK_Scalar1);
73 SkPoint3 color(lightColor * colorScale);
74 return SkPackARGB32(255,
75 SkScalarFloorToInt(color.fX),
76 SkScalarFloorToInt(color.fY),
77 SkScalarFloorToInt(color.fZ));
78 }
79private:
80 SkScalar fKD;
81};
82
83class SpecularLightingType {
84public:
85 SpecularLightingType(SkScalar ks, SkScalar shininess)
86 : fKS(ks), fShininess(shininess) {}
87 SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight, const SkPoint3& lightColor) const {
88 SkPoint3 halfDir(surfaceTolight);
89 halfDir.fZ += SK_Scalar1; // eye position is always (0, 0, 1)
90 halfDir.normalize();
91 SkScalar colorScale = SkScalarMul(fKS,
92 SkScalarPow(normal.dot(halfDir), fShininess));
93 colorScale = SkScalarClampMax(colorScale, SK_Scalar1);
94 SkPoint3 color(lightColor * colorScale);
95 return SkPackARGB32(SkScalarFloorToInt(color.maxComponent()),
96 SkScalarFloorToInt(color.fX),
97 SkScalarFloorToInt(color.fY),
98 SkScalarFloorToInt(color.fZ));
99 }
100private:
101 SkScalar fKS;
102 SkScalar fShininess;
103};
104
105inline SkScalar sobel(int a, int b, int c, int d, int e, int f, SkScalar scale) {
106 return SkScalarMul(SkIntToScalar(-a + b - 2 * c + 2 * d -e + f), scale);
107}
108
109inline SkPoint3 pointToNormal(SkScalar x, SkScalar y, SkScalar surfaceScale) {
110 SkPoint3 vector(SkScalarMul(-x, surfaceScale),
111 SkScalarMul(-y, surfaceScale),
112 SK_Scalar1);
113 vector.normalize();
114 return vector;
115}
116
117inline SkPoint3 topLeftNormal(int m[9], SkScalar surfaceScale) {
118 return pointToNormal(sobel(0, 0, m[4], m[5], m[7], m[8], gTwoThirds),
119 sobel(0, 0, m[4], m[7], m[5], m[8], gTwoThirds),
120 surfaceScale);
121}
122
123inline SkPoint3 topNormal(int m[9], SkScalar surfaceScale) {
124 return pointToNormal(sobel( 0, 0, m[3], m[5], m[6], m[8], gOneThird),
125 sobel(m[3], m[6], m[4], m[7], m[5], m[8], gOneHalf),
126 surfaceScale);
127}
128
129inline SkPoint3 topRightNormal(int m[9], SkScalar surfaceScale) {
130 return pointToNormal(sobel( 0, 0, m[3], m[4], m[6], m[7], gTwoThirds),
131 sobel(m[3], m[6], m[4], m[7], 0, 0, gTwoThirds),
132 surfaceScale);
133}
134
135inline SkPoint3 leftNormal(int m[9], SkScalar surfaceScale) {
136 return pointToNormal(sobel(m[1], m[2], m[4], m[5], m[7], m[8], gOneHalf),
137 sobel( 0, 0, m[1], m[7], m[2], m[8], gOneThird),
138 surfaceScale);
139}
140
141
142inline SkPoint3 interiorNormal(int m[9], SkScalar surfaceScale) {
143 return pointToNormal(sobel(m[0], m[2], m[3], m[5], m[6], m[8], gOneQuarter),
144 sobel(m[0], m[6], m[1], m[7], m[2], m[8], gOneQuarter),
145 surfaceScale);
146}
147
148inline SkPoint3 rightNormal(int m[9], SkScalar surfaceScale) {
149 return pointToNormal(sobel(m[0], m[1], m[3], m[4], m[6], m[7], gOneHalf),
150 sobel(m[0], m[6], m[1], m[7], 0, 0, gOneThird),
151 surfaceScale);
152}
153
154inline SkPoint3 bottomLeftNormal(int m[9], SkScalar surfaceScale) {
155 return pointToNormal(sobel(m[1], m[2], m[4], m[5], 0, 0, gTwoThirds),
156 sobel( 0, 0, m[1], m[4], m[2], m[5], gTwoThirds),
157 surfaceScale);
158}
159
160inline SkPoint3 bottomNormal(int m[9], SkScalar surfaceScale) {
161 return pointToNormal(sobel(m[0], m[2], m[3], m[5], 0, 0, gOneThird),
162 sobel(m[0], m[3], m[1], m[4], m[2], m[5], gOneHalf),
163 surfaceScale);
164}
165
166inline SkPoint3 bottomRightNormal(int m[9], SkScalar surfaceScale) {
167 return pointToNormal(sobel(m[0], m[1], m[3], m[4], 0, 0, gTwoThirds),
168 sobel(m[0], m[3], m[1], m[4], 0, 0, gTwoThirds),
169 surfaceScale);
170}
171
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000172template <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 +0000173 const LightType* l = static_cast<const LightType*>(light);
174 int y = 0;
175 {
176 const SkPMColor* row1 = src.getAddr32(0, 0);
177 const SkPMColor* row2 = src.getAddr32(0, 1);
178 SkPMColor* dptr = dst->getAddr32(0, 0);
179 int m[9];
180 int x = 0;
181 m[4] = SkGetPackedA32(*row1++);
182 m[5] = SkGetPackedA32(*row1++);
183 m[7] = SkGetPackedA32(*row2++);
184 m[8] = SkGetPackedA32(*row2++);
185 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000186 *dptr++ = lightingType.light(topLeftNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000187 for (x = 1; x < src.width() - 1; ++x)
188 {
189 shiftMatrixLeft(m);
190 m[5] = SkGetPackedA32(*row1++);
191 m[8] = SkGetPackedA32(*row2++);
192 surfaceToLight = l->surfaceToLight(x, 0, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000193 *dptr++ = lightingType.light(topNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000194 }
195 shiftMatrixLeft(m);
196 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000197 *dptr++ = lightingType.light(topRightNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000198 }
199
200 for (++y; y < src.height() - 1; ++y) {
201 const SkPMColor* row0 = src.getAddr32(0, y - 1);
202 const SkPMColor* row1 = src.getAddr32(0, y);
203 const SkPMColor* row2 = src.getAddr32(0, y + 1);
204 SkPMColor* dptr = dst->getAddr32(0, y);
205 int m[9];
206 int x = 0;
207 m[1] = SkGetPackedA32(*row0++);
208 m[2] = SkGetPackedA32(*row0++);
209 m[4] = SkGetPackedA32(*row1++);
210 m[5] = SkGetPackedA32(*row1++);
211 m[7] = SkGetPackedA32(*row2++);
212 m[8] = SkGetPackedA32(*row2++);
213 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000214 *dptr++ = lightingType.light(leftNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000215 for (x = 1; x < src.width() - 1; ++x) {
216 shiftMatrixLeft(m);
217 m[2] = SkGetPackedA32(*row0++);
218 m[5] = SkGetPackedA32(*row1++);
219 m[8] = SkGetPackedA32(*row2++);
220 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000221 *dptr++ = lightingType.light(interiorNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000222 }
223 shiftMatrixLeft(m);
224 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000225 *dptr++ = lightingType.light(rightNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000226 }
227
228 {
229 const SkPMColor* row0 = src.getAddr32(0, src.height() - 2);
230 const SkPMColor* row1 = src.getAddr32(0, src.height() - 1);
231 int x = 0;
232 SkPMColor* dptr = dst->getAddr32(0, src.height() - 1);
233 int m[9];
234 m[1] = SkGetPackedA32(*row0++);
235 m[2] = SkGetPackedA32(*row0++);
236 m[4] = SkGetPackedA32(*row1++);
237 m[5] = SkGetPackedA32(*row1++);
238 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000239 *dptr++ = lightingType.light(bottomLeftNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000240 for (x = 1; x < src.width() - 1; ++x)
241 {
242 shiftMatrixLeft(m);
243 m[2] = SkGetPackedA32(*row0++);
244 m[5] = SkGetPackedA32(*row1++);
245 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000246 *dptr++ = lightingType.light(bottomNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000247 }
248 shiftMatrixLeft(m);
249 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000250 *dptr++ = lightingType.light(bottomRightNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000251 }
252}
253
254SkPoint3 readPoint3(SkFlattenableReadBuffer& buffer) {
255 SkPoint3 point;
256 point.fX = buffer.readScalar();
257 point.fY = buffer.readScalar();
258 point.fZ = buffer.readScalar();
259 return point;
260};
261
262void writePoint3(const SkPoint3& point, SkFlattenableWriteBuffer& buffer) {
263 buffer.writeScalar(point.fX);
264 buffer.writeScalar(point.fY);
265 buffer.writeScalar(point.fZ);
266};
267
268class SkDiffuseLightingImageFilter : public SkLightingImageFilter {
269public:
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000270 SkDiffuseLightingImageFilter(SkLight* light, SkScalar surfaceScale,
271 SkScalar kd, SkImageFilter* input);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000272 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDiffuseLightingImageFilter)
273
tomhudson@google.comd0c1a062012-07-12 17:23:52 +0000274 virtual bool asNewCustomStage(GrCustomStage** stage, GrTexture*) const SK_OVERRIDE;
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000275 SkScalar kd() const { return fKD; }
276
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000277protected:
278 explicit SkDiffuseLightingImageFilter(SkFlattenableReadBuffer& buffer);
279 virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE;
280 virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
281 SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
282
283
284private:
285 typedef SkLightingImageFilter INHERITED;
286 SkScalar fKD;
287};
288
289class SkSpecularLightingImageFilter : public SkLightingImageFilter {
290public:
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000291 SkSpecularLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess, SkImageFilter* input);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000292 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSpecularLightingImageFilter)
293
tomhudson@google.comd0c1a062012-07-12 17:23:52 +0000294 virtual bool asNewCustomStage(GrCustomStage** stage, GrTexture*) const SK_OVERRIDE;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000295 SkScalar ks() const { return fKS; }
296 SkScalar shininess() const { return fShininess; }
297
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000298protected:
299 explicit SkSpecularLightingImageFilter(SkFlattenableReadBuffer& buffer);
300 virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE;
301 virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
302 SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
303
304private:
305 typedef SkLightingImageFilter INHERITED;
306 SkScalar fKS;
307 SkScalar fShininess;
308};
309
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000310#if SK_SUPPORT_GPU
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000311
tomhudson@google.comd0c1a062012-07-12 17:23:52 +0000312class GrLightingEffect : public GrSingleTextureEffect {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000313public:
tomhudson@google.comd0c1a062012-07-12 17:23:52 +0000314 GrLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000315 virtual ~GrLightingEffect();
316
317 virtual bool isEqual(const GrCustomStage&) const SK_OVERRIDE;
318
319 const SkLight* light() const { return fLight; }
320 SkScalar surfaceScale() const { return fSurfaceScale; }
321private:
tomhudson@google.comd0c1a062012-07-12 17:23:52 +0000322 typedef GrSingleTextureEffect INHERITED;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000323 const SkLight* fLight;
324 SkScalar fSurfaceScale;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000325};
326
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000327class GrDiffuseLightingEffect : public GrLightingEffect {
328public:
tomhudson@google.comd0c1a062012-07-12 17:23:52 +0000329 GrDiffuseLightingEffect(GrTexture* texture,
330 const SkLight* light,
331 SkScalar surfaceScale,
332 SkScalar kd);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000333
334 static const char* Name() { return "DiffuseLighting"; }
335
336 typedef GrGLDiffuseLightingEffect GLProgramStage;
337
338 virtual const GrProgramStageFactory& getFactory() const SK_OVERRIDE;
339 virtual bool isEqual(const GrCustomStage&) const SK_OVERRIDE;
340 SkScalar kd() const { return fKD; }
341private:
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000342 GR_DECLARE_CUSTOM_STAGE_TEST;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000343 typedef GrLightingEffect INHERITED;
344 SkScalar fKD;
345};
346
347class GrSpecularLightingEffect : public GrLightingEffect {
348public:
tomhudson@google.comd0c1a062012-07-12 17:23:52 +0000349 GrSpecularLightingEffect(GrTexture* texture,
350 const SkLight* light,
351 SkScalar surfaceScale,
352 SkScalar ks,
353 SkScalar shininess);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000354
355 static const char* Name() { return "SpecularLighting"; }
356
357 typedef GrGLSpecularLightingEffect GLProgramStage;
358
359 virtual const GrProgramStageFactory& getFactory() const SK_OVERRIDE;
360 virtual bool isEqual(const GrCustomStage&) const SK_OVERRIDE;
361 SkScalar ks() const { return fKS; }
362 SkScalar shininess() const { return fShininess; }
363
364private:
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000365 GR_DECLARE_CUSTOM_STAGE_TEST;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000366 typedef GrLightingEffect INHERITED;
367 SkScalar fKS;
368 SkScalar fShininess;
369};
370
371///////////////////////////////////////////////////////////////////////////////
372
373class GrGLLight {
374public:
senorblanco@chromium.org6730cbb2012-07-11 16:35:00 +0000375 virtual ~GrGLLight() {}
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000376 virtual void setupVariables(GrGLShaderBuilder* builder);
bsalomon@google.com032b2212012-07-16 13:36:18 +0000377 virtual void emitVS(SkString* out) const {}
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000378 virtual void emitFuncs(GrGLShaderBuilder* builder) {}
bsalomon@google.com032b2212012-07-16 13:36:18 +0000379 virtual void emitSurfaceToLight(const GrGLShaderBuilder*,
380 SkString* out,
381 const char* z) const = 0;
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000382 virtual void emitLightColor(GrGLShaderBuilder*,
bsalomon@google.com032b2212012-07-16 13:36:18 +0000383 const char *surfaceToLight) const;
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000384 virtual void setData(const GrGLUniformManager&, const GrRenderTarget* rt, const SkLight* light) const;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000385
386private:
387 typedef SkRefCnt INHERITED;
388
389protected:
bsalomon@google.com032b2212012-07-16 13:36:18 +0000390 UniformHandle fColorUni;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000391};
392
393///////////////////////////////////////////////////////////////////////////////
394
395class GrGLDistantLight : public GrGLLight {
396public:
senorblanco@chromium.org6730cbb2012-07-11 16:35:00 +0000397 virtual ~GrGLDistantLight() {}
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000398 virtual void setupVariables(GrGLShaderBuilder* builder) SK_OVERRIDE;
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000399 virtual void setData(const GrGLUniformManager&, const GrRenderTarget* rt, const SkLight* light) const SK_OVERRIDE;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000400 virtual void emitSurfaceToLight(const GrGLShaderBuilder*,
401 SkString* out,
402 const char* z) const SK_OVERRIDE;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000403private:
404 typedef GrGLLight INHERITED;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000405 UniformHandle fDirectionUni;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000406};
407
408///////////////////////////////////////////////////////////////////////////////
409
410class GrGLPointLight : public GrGLLight {
411public:
senorblanco@chromium.org6730cbb2012-07-11 16:35:00 +0000412 virtual ~GrGLPointLight() {}
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000413 virtual void setupVariables(GrGLShaderBuilder* builder) SK_OVERRIDE;
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000414 virtual void setData(const GrGLUniformManager&, const GrRenderTarget* rt, const SkLight* light) const SK_OVERRIDE;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000415 virtual void emitVS(SkString* out) const SK_OVERRIDE;
416 virtual void emitSurfaceToLight(const GrGLShaderBuilder*,
417 SkString* out,
418 const char* z) const SK_OVERRIDE;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000419private:
420 typedef GrGLLight INHERITED;
421 SkPoint3 fLocation;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000422 UniformHandle fLocationUni;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000423};
424
425///////////////////////////////////////////////////////////////////////////////
426
427class GrGLSpotLight : public GrGLLight {
428public:
senorblanco@chromium.org6730cbb2012-07-11 16:35:00 +0000429 virtual ~GrGLSpotLight() {}
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000430 virtual void setupVariables(GrGLShaderBuilder* builder) SK_OVERRIDE;
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000431 virtual void setData(const GrGLUniformManager&, const GrRenderTarget* rt, const SkLight* light) const SK_OVERRIDE;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000432 virtual void emitVS(SkString* out) const SK_OVERRIDE;
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000433 virtual void emitFuncs(GrGLShaderBuilder* builder);
bsalomon@google.com032b2212012-07-16 13:36:18 +0000434 virtual void emitSurfaceToLight(const GrGLShaderBuilder* builder,
435 SkString* out,
436 const char* z) const SK_OVERRIDE;
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000437 virtual void emitLightColor(GrGLShaderBuilder*,
bsalomon@google.com032b2212012-07-16 13:36:18 +0000438 const char *surfaceToLight) const SK_OVERRIDE;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000439
440private:
441 typedef GrGLLight INHERITED;
442
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000443 SkString fLightColorFunc;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000444 UniformHandle fLocationUni;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000445 UniformHandle fExponentUni;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000446 UniformHandle fCosOuterConeAngleUni;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000447 UniformHandle fCosInnerConeAngleUni;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000448 UniformHandle fConeScaleUni;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000449 UniformHandle fSUni;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000450};
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000451#else
452
453class GrGLLight;
454
455#endif
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000456
457};
458
459///////////////////////////////////////////////////////////////////////////////
460
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000461class SkLight : public SkFlattenable {
462public:
robertphillips@google.com0456e0b2012-06-27 14:03:26 +0000463 SK_DECLARE_INST_COUNT(SkLight)
464
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000465 enum LightType {
466 kDistant_LightType,
467 kPoint_LightType,
468 kSpot_LightType,
469 };
470 virtual LightType type() const = 0;
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000471 const SkPoint3& color() const { return fColor; }
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000472 virtual GrGLLight* createGLLight() const = 0;
473 virtual bool isEqual(const SkLight& other) const {
474 return fColor == other.fColor;
475 }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000476
djsollen@google.com08337772012-06-26 14:33:13 +0000477protected:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000478 SkLight(SkColor color)
479 : fColor(SkIntToScalar(SkColorGetR(color)),
480 SkIntToScalar(SkColorGetG(color)),
481 SkIntToScalar(SkColorGetB(color))) {}
482 SkLight(SkFlattenableReadBuffer& buffer)
483 : INHERITED(buffer) {
484 fColor = readPoint3(buffer);
485 }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000486 virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
djsollen@google.com08337772012-06-26 14:33:13 +0000487 INHERITED::flatten(buffer);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000488 writePoint3(fColor, buffer);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000489 }
djsollen@google.com08337772012-06-26 14:33:13 +0000490
491private:
492 typedef SkFlattenable INHERITED;
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000493 SkPoint3 fColor;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000494};
495
robertphillips@google.com0456e0b2012-06-27 14:03:26 +0000496SK_DEFINE_INST_COUNT(SkLight)
497
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000498///////////////////////////////////////////////////////////////////////////////
499
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000500class SkDistantLight : public SkLight {
501public:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000502 SkDistantLight(const SkPoint3& direction, SkColor color)
503 : INHERITED(color), fDirection(direction) {
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000504 }
djsollen@google.com08337772012-06-26 14:33:13 +0000505
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000506 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
507 return fDirection;
508 };
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000509 SkPoint3 lightColor(const SkPoint3&) const { return color(); }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000510 virtual LightType type() const { return kDistant_LightType; }
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000511 const SkPoint3& direction() const { return fDirection; }
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000512 virtual GrGLLight* createGLLight() const SK_OVERRIDE {
513#if SK_SUPPORT_GPU
514 return SkNEW(GrGLDistantLight);
515#else
516 SkDEBUGFAIL("Should not call in GPU-less build");
517 return NULL;
518#endif
519 }
senorblanco@chromium.org6730cbb2012-07-11 16:35:00 +0000520 virtual bool isEqual(const SkLight& other) const SK_OVERRIDE {
521 if (other.type() != kDistant_LightType) {
522 return false;
523 }
524
525 const SkDistantLight& o = static_cast<const SkDistantLight&>(other);
526 return INHERITED::isEqual(other) &&
527 fDirection == o.fDirection;
528 }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000529
530 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDistantLight)
531
djsollen@google.com08337772012-06-26 14:33:13 +0000532protected:
533 SkDistantLight(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
534 fDirection = readPoint3(buffer);
535 }
536 virtual void flatten(SkFlattenableWriteBuffer& buffer) const {
537 INHERITED::flatten(buffer);
538 writePoint3(fDirection, buffer);
539 }
540
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000541private:
djsollen@google.com08337772012-06-26 14:33:13 +0000542 typedef SkLight INHERITED;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000543 SkPoint3 fDirection;
544};
545
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000546///////////////////////////////////////////////////////////////////////////////
547
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000548class SkPointLight : public SkLight {
549public:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000550 SkPointLight(const SkPoint3& location, SkColor color)
551 : INHERITED(color), fLocation(location) {}
djsollen@google.com08337772012-06-26 14:33:13 +0000552
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000553 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
554 SkPoint3 direction(fLocation.fX - SkIntToScalar(x),
555 fLocation.fY - SkIntToScalar(y),
556 fLocation.fZ - SkScalarMul(SkIntToScalar(z), surfaceScale));
557 direction.normalize();
558 return direction;
559 };
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000560 SkPoint3 lightColor(const SkPoint3&) const { return color(); }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000561 virtual LightType type() const { return kPoint_LightType; }
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000562 const SkPoint3& location() const { return fLocation; }
563 virtual GrGLLight* createGLLight() const SK_OVERRIDE {
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000564#if SK_SUPPORT_GPU
tomhudson@google.com300f5622012-07-20 14:15:22 +0000565 return SkNEW(GrGLPointLight);
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000566#else
567 SkDEBUGFAIL("Should not call in GPU-less build");
568 return NULL;
569#endif
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000570 }
senorblanco@chromium.org6730cbb2012-07-11 16:35:00 +0000571 virtual bool isEqual(const SkLight& other) const SK_OVERRIDE {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000572 if (other.type() != kPoint_LightType) {
573 return false;
574 }
575 const SkPointLight& o = static_cast<const SkPointLight&>(other);
576 return INHERITED::isEqual(other) &&
577 fLocation == o.fLocation;
578 }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000579
580 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkPointLight)
581
djsollen@google.com08337772012-06-26 14:33:13 +0000582protected:
583 SkPointLight(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
584 fLocation = readPoint3(buffer);
585 }
586 virtual void flatten(SkFlattenableWriteBuffer& buffer) const {
587 INHERITED::flatten(buffer);
588 writePoint3(fLocation, buffer);
589 }
590
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000591private:
djsollen@google.com08337772012-06-26 14:33:13 +0000592 typedef SkLight INHERITED;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000593 SkPoint3 fLocation;
594};
595
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000596///////////////////////////////////////////////////////////////////////////////
597
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000598class SkSpotLight : public SkLight {
599public:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000600 SkSpotLight(const SkPoint3& location, const SkPoint3& target, SkScalar specularExponent, SkScalar cutoffAngle, SkColor color)
601 : INHERITED(color),
602 fLocation(location),
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000603 fTarget(target),
604 fSpecularExponent(specularExponent)
605 {
606 fS = target - location;
607 fS.normalize();
608 fCosOuterConeAngle = SkScalarCos(SkDegreesToRadians(cutoffAngle));
609 const SkScalar antiAliasThreshold = SkFloatToScalar(0.016f);
610 fCosInnerConeAngle = fCosOuterConeAngle + antiAliasThreshold;
611 fConeScale = SkScalarInvert(antiAliasThreshold);
612 }
djsollen@google.com08337772012-06-26 14:33:13 +0000613
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000614 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
615 SkPoint3 direction(fLocation.fX - SkIntToScalar(x),
616 fLocation.fY - SkIntToScalar(y),
617 fLocation.fZ - SkScalarMul(SkIntToScalar(z), surfaceScale));
618 direction.normalize();
619 return direction;
620 };
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000621 SkPoint3 lightColor(const SkPoint3& surfaceToLight) const {
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000622 SkScalar cosAngle = -surfaceToLight.dot(fS);
623 if (cosAngle < fCosOuterConeAngle) {
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000624 return SkPoint3(0, 0, 0);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000625 }
626 SkScalar scale = SkScalarPow(cosAngle, fSpecularExponent);
627 if (cosAngle < fCosInnerConeAngle) {
628 scale = SkScalarMul(scale, cosAngle - fCosOuterConeAngle);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000629 return color() * SkScalarMul(scale, fConeScale);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000630 }
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000631 return color() * scale;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000632 }
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000633 virtual GrGLLight* createGLLight() const SK_OVERRIDE {
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000634#if SK_SUPPORT_GPU
tomhudson@google.com300f5622012-07-20 14:15:22 +0000635 return SkNEW(GrGLSpotLight);
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000636#else
637 SkDEBUGFAIL("Should not call in GPU-less build");
638 return NULL;
639#endif
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000640 }
djsollen@google.com08337772012-06-26 14:33:13 +0000641 virtual LightType type() const { return kSpot_LightType; }
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000642 const SkPoint3& location() const { return fLocation; }
643 const SkPoint3& target() const { return fTarget; }
644 SkScalar specularExponent() const { return fSpecularExponent; }
645 SkScalar cosInnerConeAngle() const { return fCosInnerConeAngle; }
646 SkScalar cosOuterConeAngle() const { return fCosOuterConeAngle; }
647 SkScalar coneScale() const { return fConeScale; }
senorblanco@chromium.orgeb311842012-07-11 20:49:26 +0000648 const SkPoint3& s() const { return fS; }
djsollen@google.com08337772012-06-26 14:33:13 +0000649
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000650 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSpotLight)
651
djsollen@google.com08337772012-06-26 14:33:13 +0000652protected:
653 SkSpotLight(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
654 fLocation = readPoint3(buffer);
655 fTarget = readPoint3(buffer);
656 fSpecularExponent = buffer.readScalar();
657 fCosOuterConeAngle = buffer.readScalar();
658 fCosInnerConeAngle = buffer.readScalar();
659 fConeScale = buffer.readScalar();
660 fS = readPoint3(buffer);
661 }
662 virtual void flatten(SkFlattenableWriteBuffer& buffer) const {
663 INHERITED::flatten(buffer);
664 writePoint3(fLocation, buffer);
665 writePoint3(fTarget, buffer);
666 buffer.writeScalar(fSpecularExponent);
667 buffer.writeScalar(fCosOuterConeAngle);
668 buffer.writeScalar(fCosInnerConeAngle);
669 buffer.writeScalar(fConeScale);
670 writePoint3(fS, buffer);
671 }
672
senorblanco@chromium.orgbd9fad62012-07-11 16:25:37 +0000673 virtual bool isEqual(const SkLight& other) const SK_OVERRIDE {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000674 if (other.type() != kSpot_LightType) {
675 return false;
676 }
677
678 const SkSpotLight& o = static_cast<const SkSpotLight&>(other);
679 return INHERITED::isEqual(other) &&
680 fLocation == o.fLocation &&
681 fTarget == o.fTarget &&
682 fSpecularExponent == o.fSpecularExponent &&
683 fCosOuterConeAngle == o.fCosOuterConeAngle;
684 }
685
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000686private:
djsollen@google.com08337772012-06-26 14:33:13 +0000687 typedef SkLight INHERITED;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000688 SkPoint3 fLocation;
689 SkPoint3 fTarget;
690 SkScalar fSpecularExponent;
691 SkScalar fCosOuterConeAngle;
692 SkScalar fCosInnerConeAngle;
693 SkScalar fConeScale;
694 SkPoint3 fS;
695};
696
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000697///////////////////////////////////////////////////////////////////////////////
698
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000699SkLightingImageFilter::SkLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkImageFilter* input)
700 : INHERITED(input),
701 fLight(light),
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000702 fSurfaceScale(SkScalarDiv(surfaceScale, SkIntToScalar(255)))
703{
704 SkASSERT(fLight);
reed@google.com51f38662012-06-27 14:24:29 +0000705 // our caller knows that we take ownership of the light, so we don't
706 // need to call ref() here.
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000707}
708
709SkImageFilter* SkLightingImageFilter::CreateDistantLitDiffuse(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000710 const SkPoint3& direction, SkColor lightColor, SkScalar surfaceScale,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000711 SkScalar kd, SkImageFilter* input) {
tomhudson@google.com300f5622012-07-20 14:15:22 +0000712 return SkNEW_ARGS(SkDiffuseLightingImageFilter,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000713 (SkNEW_ARGS(SkDistantLight, (direction, lightColor)), surfaceScale, kd,
714 input));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000715}
716
717SkImageFilter* SkLightingImageFilter::CreatePointLitDiffuse(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000718 const SkPoint3& location, SkColor lightColor, SkScalar surfaceScale,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000719 SkScalar kd, SkImageFilter* input) {
tomhudson@google.com300f5622012-07-20 14:15:22 +0000720 return SkNEW_ARGS(SkDiffuseLightingImageFilter,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000721 (SkNEW_ARGS(SkPointLight, (location, lightColor)), surfaceScale, kd,
722 input));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000723}
724
725SkImageFilter* SkLightingImageFilter::CreateSpotLitDiffuse(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000726 const SkPoint3& location, const SkPoint3& target,
727 SkScalar specularExponent, SkScalar cutoffAngle,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000728 SkColor lightColor, SkScalar surfaceScale, SkScalar kd,
729 SkImageFilter* input) {
tomhudson@google.com300f5622012-07-20 14:15:22 +0000730 return SkNEW_ARGS(SkDiffuseLightingImageFilter,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000731 (SkNEW_ARGS(SkSpotLight, (location, target, specularExponent,
732 cutoffAngle, lightColor)),
733 surfaceScale, kd, input));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000734}
735
736SkImageFilter* SkLightingImageFilter::CreateDistantLitSpecular(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000737 const SkPoint3& direction, SkColor lightColor, SkScalar surfaceScale,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000738 SkScalar ks, SkScalar shininess, SkImageFilter* input) {
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000739 return SkNEW_ARGS(SkSpecularLightingImageFilter,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000740 (SkNEW_ARGS(SkDistantLight, (direction, lightColor)),
741 surfaceScale, ks, shininess, input));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000742}
743
744SkImageFilter* SkLightingImageFilter::CreatePointLitSpecular(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000745 const SkPoint3& location, SkColor lightColor, SkScalar surfaceScale,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000746 SkScalar ks, SkScalar shininess, SkImageFilter* input) {
tomhudson@google.com300f5622012-07-20 14:15:22 +0000747 return SkNEW_ARGS(SkSpecularLightingImageFilter,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000748 (SkNEW_ARGS(SkPointLight, (location, lightColor)),
749 surfaceScale, ks, shininess, input));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000750}
751
752SkImageFilter* SkLightingImageFilter::CreateSpotLitSpecular(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000753 const SkPoint3& location, const SkPoint3& target,
754 SkScalar specularExponent, SkScalar cutoffAngle,
755 SkColor lightColor, SkScalar surfaceScale,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000756 SkScalar ks, SkScalar shininess, SkImageFilter* input) {
tomhudson@google.com300f5622012-07-20 14:15:22 +0000757 return SkNEW_ARGS(SkSpecularLightingImageFilter,
758 (SkNEW_ARGS(SkSpotLight, (location, target, specularExponent, cutoffAngle, lightColor)),
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000759 surfaceScale, ks, shininess, input));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000760}
761
762SkLightingImageFilter::~SkLightingImageFilter() {
763 fLight->unref();
764}
765
766SkLightingImageFilter::SkLightingImageFilter(SkFlattenableReadBuffer& buffer)
767 : INHERITED(buffer)
768{
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000769 fLight = buffer.readFlattenableT<SkLight>();
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000770 fSurfaceScale = buffer.readScalar();
771}
772
773void SkLightingImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
774 this->INHERITED::flatten(buffer);
djsollen@google.com08337772012-06-26 14:33:13 +0000775 buffer.writeFlattenable(fLight);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000776 buffer.writeScalar(fSurfaceScale);
777}
778
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000779///////////////////////////////////////////////////////////////////////////////
780
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000781SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar kd, SkImageFilter* input)
782 : SkLightingImageFilter(light, surfaceScale, input),
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000783 fKD(kd)
784{
785}
786
787SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkFlattenableReadBuffer& buffer)
788 : INHERITED(buffer)
789{
790 fKD = buffer.readScalar();
791}
792
793void SkDiffuseLightingImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
794 this->INHERITED::flatten(buffer);
795 buffer.writeScalar(fKD);
796}
797
798bool SkDiffuseLightingImageFilter::onFilterImage(Proxy*,
799 const SkBitmap& src,
800 const SkMatrix&,
801 SkBitmap* dst,
802 SkIPoint*) {
803 if (src.config() != SkBitmap::kARGB_8888_Config) {
804 return false;
805 }
806 SkAutoLockPixels alp(src);
807 if (!src.getPixels()) {
808 return false;
809 }
810 if (src.width() < 2 || src.height() < 2) {
811 return false;
812 }
813 dst->setConfig(src.config(), src.width(), src.height());
814 dst->allocPixels();
815
816 DiffuseLightingType lightingType(fKD);
817 switch (light()->type()) {
818 case SkLight::kDistant_LightType:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000819 lightBitmap<DiffuseLightingType, SkDistantLight>(lightingType, light(), src, dst, surfaceScale());
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000820 break;
821 case SkLight::kPoint_LightType:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000822 lightBitmap<DiffuseLightingType, SkPointLight>(lightingType, light(), src, dst, surfaceScale());
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000823 break;
824 case SkLight::kSpot_LightType:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000825 lightBitmap<DiffuseLightingType, SkSpotLight>(lightingType, light(), src, dst, surfaceScale());
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000826 break;
827 }
828 return true;
829}
830
tomhudson@google.comd0c1a062012-07-12 17:23:52 +0000831bool SkDiffuseLightingImageFilter::asNewCustomStage(GrCustomStage** stage,
832 GrTexture* texture) const {
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000833#if SK_SUPPORT_GPU
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000834 if (stage) {
835 SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255));
tomhudson@google.com300f5622012-07-20 14:15:22 +0000836 *stage = SkNEW_ARGS(GrDiffuseLightingEffect, (texture, light(), scale, kd()));
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000837 }
838 return true;
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000839#else
840 SkDEBUGFAIL("Should not call in GPU-less build");
841 return false;
842#endif
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000843}
844
845///////////////////////////////////////////////////////////////////////////////
846
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000847SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess, SkImageFilter* input)
848 : SkLightingImageFilter(light, surfaceScale, input),
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000849 fKS(ks),
850 fShininess(shininess)
851{
852}
853
854SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkFlattenableReadBuffer& buffer)
855 : INHERITED(buffer)
856{
857 fKS = buffer.readScalar();
858 fShininess = buffer.readScalar();
859}
860
861void SkSpecularLightingImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
862 this->INHERITED::flatten(buffer);
863 buffer.writeScalar(fKS);
864 buffer.writeScalar(fShininess);
865}
866
867bool SkSpecularLightingImageFilter::onFilterImage(Proxy*,
868 const SkBitmap& src,
869 const SkMatrix&,
870 SkBitmap* dst,
871 SkIPoint*) {
872 if (src.config() != SkBitmap::kARGB_8888_Config) {
873 return false;
874 }
875 SkAutoLockPixels alp(src);
876 if (!src.getPixels()) {
877 return false;
878 }
879 if (src.width() < 2 || src.height() < 2) {
880 return false;
881 }
882 dst->setConfig(src.config(), src.width(), src.height());
883 dst->allocPixels();
884
885 SpecularLightingType lightingType(fKS, fShininess);
886 switch (light()->type()) {
887 case SkLight::kDistant_LightType:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000888 lightBitmap<SpecularLightingType, SkDistantLight>(lightingType, light(), src, dst, surfaceScale());
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000889 break;
890 case SkLight::kPoint_LightType:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000891 lightBitmap<SpecularLightingType, SkPointLight>(lightingType, light(), src, dst, surfaceScale());
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000892 break;
893 case SkLight::kSpot_LightType:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000894 lightBitmap<SpecularLightingType, SkSpotLight>(lightingType, light(), src, dst, surfaceScale());
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000895 break;
896 }
897 return true;
898}
899
tomhudson@google.comd0c1a062012-07-12 17:23:52 +0000900bool SkSpecularLightingImageFilter::asNewCustomStage(GrCustomStage** stage,
901 GrTexture* texture) const {
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000902#if SK_SUPPORT_GPU
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000903 if (stage) {
904 SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255));
tomhudson@google.com300f5622012-07-20 14:15:22 +0000905 *stage = SkNEW_ARGS(GrSpecularLightingEffect, (texture, light(), scale, ks(), shininess()));
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000906 }
907 return true;
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000908#else
909 SkDEBUGFAIL("Should not call in GPU-less build");
910 return false;
911#endif
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000912}
913
914///////////////////////////////////////////////////////////////////////////////
915
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000916#if SK_SUPPORT_GPU
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000917
918namespace {
919SkPoint3 random_point3(SkRandom* random) {
920 return SkPoint3(SkScalarToFloat(random->nextSScalar1()),
921 SkScalarToFloat(random->nextSScalar1()),
922 SkScalarToFloat(random->nextSScalar1()));
923}
924
925SkLight* create_random_light(SkRandom* random) {
926 int type = random->nextULessThan(3);
927 switch (type) {
928 case 0: {
929 return SkNEW_ARGS(SkDistantLight, (random_point3(random), random->nextU()));
930 }
931 case 1: {
932 return SkNEW_ARGS(SkPointLight, (random_point3(random), random->nextU()));
933 }
934 case 2: {
935 return SkNEW_ARGS(SkSpotLight, (random_point3(random),
936 random_point3(random),
937 random->nextUScalar1(),
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000938 random->nextUScalar1(),
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000939 random->nextU()));
940 }
941 default:
942 GrCrash();
943 return NULL;
944 }
945}
946
947}
948
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000949class GrGLLightingEffect : public GrGLProgramStage {
950public:
951 GrGLLightingEffect(const GrProgramStageFactory& factory,
952 const GrCustomStage& stage);
953 virtual ~GrGLLightingEffect();
954
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000955 virtual void setupVariables(GrGLShaderBuilder* builder) SK_OVERRIDE;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000956 virtual void emitVS(GrGLShaderBuilder* builder,
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000957 const char* vertexCoords) SK_OVERRIDE;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000958 virtual void emitFS(GrGLShaderBuilder* builder,
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000959 const char* outputColor,
960 const char* inputColor,
bsalomon@google.comf06df1b2012-09-06 20:22:31 +0000961 const TextureSamplerArray&) SK_OVERRIDE;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000962
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000963 virtual void emitLightFunc(GrGLShaderBuilder*, SkString* funcName) = 0;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000964
twiz@google.coma5e65ec2012-08-02 15:15:16 +0000965 static inline StageKey GenKey(const GrCustomStage& s, const GrGLCaps& caps);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000966
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000967 virtual void setData(const GrGLUniformManager&,
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000968 const GrCustomStage&,
senorblanco@chromium.orgf4770d72012-07-13 18:25:06 +0000969 const GrRenderTarget*,
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000970 int stageNum) SK_OVERRIDE;
971
972private:
973 typedef GrGLProgramStage INHERITED;
974
bsalomon@google.com032b2212012-07-16 13:36:18 +0000975 UniformHandle fImageIncrementUni;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000976 UniformHandle fSurfaceScaleUni;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000977 GrGLLight* fLight;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000978};
979
980///////////////////////////////////////////////////////////////////////////////
981
982class GrGLDiffuseLightingEffect : public GrGLLightingEffect {
983public:
984 GrGLDiffuseLightingEffect(const GrProgramStageFactory& factory,
985 const GrCustomStage& stage);
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000986 virtual void setupVariables(GrGLShaderBuilder* builder) SK_OVERRIDE;
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000987 virtual void emitLightFunc(GrGLShaderBuilder*, SkString* funcName) SK_OVERRIDE;
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000988 virtual void setData(const GrGLUniformManager&,
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000989 const GrCustomStage&,
senorblanco@chromium.orgf4770d72012-07-13 18:25:06 +0000990 const GrRenderTarget*,
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000991 int stageNum) SK_OVERRIDE;
992
993private:
994 typedef GrGLLightingEffect INHERITED;
995
bsalomon@google.com032b2212012-07-16 13:36:18 +0000996 UniformHandle fKDUni;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000997};
998
999///////////////////////////////////////////////////////////////////////////////
1000
1001class GrGLSpecularLightingEffect : public GrGLLightingEffect {
1002public:
1003 GrGLSpecularLightingEffect(const GrProgramStageFactory& factory,
1004 const GrCustomStage& stage);
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001005 virtual void setupVariables(GrGLShaderBuilder* builder) SK_OVERRIDE;
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001006 virtual void emitLightFunc(GrGLShaderBuilder*, SkString* funcName) SK_OVERRIDE;
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001007 virtual void setData(const GrGLUniformManager&,
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001008 const GrCustomStage&,
senorblanco@chromium.orgf4770d72012-07-13 18:25:06 +00001009 const GrRenderTarget*,
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001010 int stageNum) SK_OVERRIDE;
1011
1012private:
1013 typedef GrGLLightingEffect INHERITED;
1014
bsalomon@google.com032b2212012-07-16 13:36:18 +00001015 UniformHandle fKSUni;
bsalomon@google.com032b2212012-07-16 13:36:18 +00001016 UniformHandle fShininessUni;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001017};
1018
1019///////////////////////////////////////////////////////////////////////////////
1020
tomhudson@google.comd0c1a062012-07-12 17:23:52 +00001021GrLightingEffect::GrLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale)
1022 : GrSingleTextureEffect(texture)
1023 , fLight(light)
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001024 , fSurfaceScale(surfaceScale) {
1025 fLight->ref();
1026}
1027
1028GrLightingEffect::~GrLightingEffect() {
1029 fLight->unref();
1030}
1031
1032bool GrLightingEffect::isEqual(const GrCustomStage& sBase) const {
1033 const GrLightingEffect& s =
1034 static_cast<const GrLightingEffect&>(sBase);
tomhudson@google.comd0c1a062012-07-12 17:23:52 +00001035 return INHERITED::isEqual(sBase) &&
1036 fLight->isEqual(*s.fLight) &&
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001037 fSurfaceScale == s.fSurfaceScale;
1038}
1039
1040///////////////////////////////////////////////////////////////////////////////
1041
tomhudson@google.comd0c1a062012-07-12 17:23:52 +00001042GrDiffuseLightingEffect::GrDiffuseLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale, SkScalar kd)
1043 : INHERITED(texture, light, surfaceScale), fKD(kd) {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001044}
1045
1046const GrProgramStageFactory& GrDiffuseLightingEffect::getFactory() const {
1047 return GrTProgramStageFactory<GrDiffuseLightingEffect>::getInstance();
1048}
1049
1050bool GrDiffuseLightingEffect::isEqual(const GrCustomStage& sBase) const {
1051 const GrDiffuseLightingEffect& s =
1052 static_cast<const GrDiffuseLightingEffect&>(sBase);
1053 return INHERITED::isEqual(sBase) &&
1054 this->kd() == s.kd();
1055}
1056
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001057GR_DEFINE_CUSTOM_STAGE_TEST(GrDiffuseLightingEffect);
1058
1059GrCustomStage* GrDiffuseLightingEffect::TestCreate(SkRandom* random,
1060 GrContext* context,
1061 GrTexture* textures[]) {
1062 SkScalar surfaceScale = random->nextSScalar1();
1063 SkScalar kd = random->nextUScalar1();
1064 SkAutoTUnref<SkLight> light(create_random_light(random));
1065 return SkNEW_ARGS(GrDiffuseLightingEffect, (textures[GrCustomStageUnitTest::kAlphaTextureIdx],
1066 light, surfaceScale, kd));
1067}
1068
1069
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001070///////////////////////////////////////////////////////////////////////////////
1071
1072GrGLLightingEffect::GrGLLightingEffect(const GrProgramStageFactory& factory,
1073 const GrCustomStage& stage)
1074 : GrGLProgramStage(factory)
bsalomon@google.com032b2212012-07-16 13:36:18 +00001075 , fImageIncrementUni(kInvalidUniformHandle)
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001076 , fSurfaceScaleUni(kInvalidUniformHandle) {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001077 const GrLightingEffect& m = static_cast<const GrLightingEffect&>(stage);
1078 fLight = m.light()->createGLLight();
1079}
1080
1081GrGLLightingEffect::~GrGLLightingEffect() {
1082 delete fLight;
1083}
1084
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001085void GrGLLightingEffect::setupVariables(GrGLShaderBuilder* builder) {
bsalomon@google.com032b2212012-07-16 13:36:18 +00001086 fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
1087 kVec2f_GrSLType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001088 "ImageIncrement");
bsalomon@google.com032b2212012-07-16 13:36:18 +00001089 fSurfaceScaleUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
1090 kFloat_GrSLType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001091 "SurfaceScale");
1092 fLight->setupVariables(builder);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001093}
1094
bsalomon@google.com032b2212012-07-16 13:36:18 +00001095void GrGLLightingEffect::emitVS(GrGLShaderBuilder* builder,
1096 const char* vertexCoords) {
1097 fLight->emitVS(&builder->fVSCode);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001098}
1099
bsalomon@google.com032b2212012-07-16 13:36:18 +00001100void GrGLLightingEffect::emitFS(GrGLShaderBuilder* builder,
1101 const char* outputColor,
1102 const char* inputColor,
bsalomon@google.comf06df1b2012-09-06 20:22:31 +00001103 const TextureSamplerArray& samplers) {
bsalomon@google.com032b2212012-07-16 13:36:18 +00001104 SkString* code = &builder->fFSCode;
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001105 fLight->emitFuncs(builder);
1106 SkString lightFunc;
1107 this->emitLightFunc(builder, &lightFunc);
1108 static const GrGLShaderVar gSobelArgs[] = {
1109 GrGLShaderVar("a", kFloat_GrSLType),
1110 GrGLShaderVar("b", kFloat_GrSLType),
1111 GrGLShaderVar("c", kFloat_GrSLType),
1112 GrGLShaderVar("d", kFloat_GrSLType),
1113 GrGLShaderVar("e", kFloat_GrSLType),
1114 GrGLShaderVar("f", kFloat_GrSLType),
1115 GrGLShaderVar("scale", kFloat_GrSLType),
1116 };
1117 SkString sobelFuncName;
1118 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1119 kFloat_GrSLType,
1120 "sobel",
1121 SK_ARRAY_COUNT(gSobelArgs),
1122 gSobelArgs,
1123 "\treturn (-a + b - 2.0 * c + 2.0 * d -e + f) * scale;\n",
1124 &sobelFuncName);
1125 static const GrGLShaderVar gPointToNormalArgs[] = {
1126 GrGLShaderVar("x", kFloat_GrSLType),
1127 GrGLShaderVar("y", kFloat_GrSLType),
1128 GrGLShaderVar("scale", kFloat_GrSLType),
1129 };
1130 SkString pointToNormalName;
1131 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1132 kVec3f_GrSLType,
1133 "pointToNormal",
1134 SK_ARRAY_COUNT(gPointToNormalArgs),
1135 gPointToNormalArgs,
1136 "\treturn normalize(vec3(-x * scale, -y * scale, 1));\n",
1137 &pointToNormalName);
1138
1139 static const GrGLShaderVar gInteriorNormalArgs[] = {
1140 GrGLShaderVar("m", kFloat_GrSLType, 9),
1141 GrGLShaderVar("surfaceScale", kFloat_GrSLType),
1142 };
1143 SkString interiorNormalBody;
1144 interiorNormalBody.appendf("\treturn %s(%s(m[0], m[2], m[3], m[5], m[6], m[8], 0.25),\n"
1145 "\t %s(m[0], m[6], m[1], m[7], m[2], m[8], 0.25),\n"
1146 "\t surfaceScale);\n",
1147 pointToNormalName.c_str(),
1148 sobelFuncName.c_str(),
1149 sobelFuncName.c_str());
1150 SkString interiorNormalName;
1151 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1152 kVec3f_GrSLType,
1153 "interiorNormal",
1154 SK_ARRAY_COUNT(gInteriorNormalArgs),
1155 gInteriorNormalArgs,
1156 interiorNormalBody.c_str(),
1157 &interiorNormalName);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001158
bsalomon@google.com34bcb9f2012-08-28 18:20:18 +00001159 code->appendf("\t\tvec2 coord = %s;\n", builder->defaultTexCoordsName());
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001160 code->appendf("\t\tfloat m[9];\n");
bsalomon@google.com032b2212012-07-16 13:36:18 +00001161
1162 const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
1163 const char* surfScale = builder->getUniformCStr(fSurfaceScaleUni);
1164
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001165 int index = 0;
1166 for (int dy = -1; dy <= 1; dy++) {
1167 for (int dx = -1; dx <= 1; dx++) {
1168 SkString texCoords;
bsalomon@google.com032b2212012-07-16 13:36:18 +00001169 texCoords.appendf("coord + vec2(%d, %d) * %s", dx, dy, imgInc);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001170 code->appendf("\t\tm[%d] = ", index++);
bsalomon@google.comf06df1b2012-09-06 20:22:31 +00001171 builder->appendTextureLookup(code, samplers[0], texCoords.c_str());
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001172 code->appendf(".a;\n");
1173 }
1174 }
1175 code->appendf("\t\tvec3 surfaceToLight = ");
1176 SkString arg;
bsalomon@google.com032b2212012-07-16 13:36:18 +00001177 arg.appendf("%s * m[4]", surfScale);
1178 fLight->emitSurfaceToLight(builder, code, arg.c_str());
bsalomon@google.com868a8e72012-08-30 19:11:34 +00001179 code->append(";\n");
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001180 code->appendf("\t\t%s = %s(%s(m, %s), surfaceToLight, ",
1181 outputColor, lightFunc.c_str(), interiorNormalName.c_str(), surfScale);
1182 fLight->emitLightColor(builder, "surfaceToLight");
bsalomon@google.com868a8e72012-08-30 19:11:34 +00001183 code->append(");\n");
1184 GrGLSLMulVarBy4f(code, 2, outputColor, inputColor);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001185}
1186
twiz@google.coma5e65ec2012-08-02 15:15:16 +00001187GrGLProgramStage::StageKey GrGLLightingEffect::GenKey(const GrCustomStage& s,
1188 const GrGLCaps& caps) {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001189 return static_cast<const GrLightingEffect&>(s).light()->type();
1190}
1191
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001192void GrGLLightingEffect::setData(const GrGLUniformManager& uman,
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001193 const GrCustomStage& data,
senorblanco@chromium.orgf4770d72012-07-13 18:25:06 +00001194 const GrRenderTarget* rt,
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001195 int stageNum) {
1196 const GrLightingEffect& effect =
1197 static_cast<const GrLightingEffect&>(data);
senorblanco@chromium.orgf4770d72012-07-13 18:25:06 +00001198 GrGLTexture* texture = static_cast<GrGLTexture*>(data.texture(0));
1199 float ySign = texture->orientation() == GrGLTexture::kTopDown_Orientation ? -1.0f : 1.0f;
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001200 uman.set2f(fImageIncrementUni, 1.0f / texture->width(), ySign / texture->height());
1201 uman.set1f(fSurfaceScaleUni, effect.surfaceScale());
1202 fLight->setData(uman, rt, effect.light());
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001203}
1204
1205///////////////////////////////////////////////////////////////////////////////
1206
1207///////////////////////////////////////////////////////////////////////////////
1208
1209GrGLDiffuseLightingEffect::GrGLDiffuseLightingEffect(const GrProgramStageFactory& factory,
1210 const GrCustomStage& stage)
1211 : INHERITED(factory, stage)
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001212 , fKDUni(kInvalidUniformHandle) {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001213}
1214
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001215void GrGLDiffuseLightingEffect::setupVariables(GrGLShaderBuilder* builder) {
1216 INHERITED::setupVariables(builder);
1217 fKDUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, kFloat_GrSLType, "KD");
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001218}
1219
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001220void GrGLDiffuseLightingEffect::emitLightFunc(GrGLShaderBuilder* builder, SkString* funcName) {
bsalomon@google.com032b2212012-07-16 13:36:18 +00001221 const char* kd = builder->getUniformCStr(fKDUni);
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001222 static const GrGLShaderVar gLightArgs[] = {
1223 GrGLShaderVar("normal", kVec3f_GrSLType),
1224 GrGLShaderVar("surfaceToLight", kVec3f_GrSLType),
1225 GrGLShaderVar("lightColor", kVec3f_GrSLType)
1226 };
1227 SkString lightBody;
1228 lightBody.appendf("\tfloat colorScale = %s * dot(normal, surfaceToLight);\n", kd);
1229 lightBody.appendf("\treturn vec4(lightColor * clamp(colorScale, 0.0, 1.0), 1.0);\n");
1230 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1231 kVec4f_GrSLType,
1232 "light",
1233 SK_ARRAY_COUNT(gLightArgs),
1234 gLightArgs,
1235 lightBody.c_str(),
1236 funcName);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001237}
1238
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001239void GrGLDiffuseLightingEffect::setData(const GrGLUniformManager& uman,
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001240 const GrCustomStage& data,
senorblanco@chromium.orgf4770d72012-07-13 18:25:06 +00001241 const GrRenderTarget* rt,
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001242 int stageNum) {
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001243 INHERITED::setData(uman, data, rt, stageNum);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001244 const GrDiffuseLightingEffect& effect =
1245 static_cast<const GrDiffuseLightingEffect&>(data);
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001246 uman.set1f(fKDUni, effect.kd());
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001247}
1248
1249///////////////////////////////////////////////////////////////////////////////
1250
tomhudson@google.comd0c1a062012-07-12 17:23:52 +00001251GrSpecularLightingEffect::GrSpecularLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess)
1252 : INHERITED(texture, light, surfaceScale),
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001253 fKS(ks),
1254 fShininess(shininess) {
1255}
1256
1257const GrProgramStageFactory& GrSpecularLightingEffect::getFactory() const {
1258 return GrTProgramStageFactory<GrSpecularLightingEffect>::getInstance();
1259}
1260
1261bool GrSpecularLightingEffect::isEqual(const GrCustomStage& sBase) const {
1262 const GrSpecularLightingEffect& s =
1263 static_cast<const GrSpecularLightingEffect&>(sBase);
1264 return INHERITED::isEqual(sBase) &&
1265 this->ks() == s.ks() &&
1266 this->shininess() == s.shininess();
1267}
1268
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001269GR_DEFINE_CUSTOM_STAGE_TEST(GrSpecularLightingEffect);
1270
1271GrCustomStage* GrSpecularLightingEffect::TestCreate(SkRandom* random,
1272 GrContext* context,
1273 GrTexture* textures[]) {
1274 SkScalar surfaceScale = random->nextSScalar1();
1275 SkScalar ks = random->nextUScalar1();
1276 SkScalar shininess = random->nextUScalar1();
1277 SkAutoTUnref<SkLight> light(create_random_light(random));
1278 return SkNEW_ARGS(GrSpecularLightingEffect, (textures[GrCustomStageUnitTest::kAlphaTextureIdx],
1279 light, surfaceScale, ks, shininess));
1280}
1281
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001282///////////////////////////////////////////////////////////////////////////////
1283
1284GrGLSpecularLightingEffect::GrGLSpecularLightingEffect(const GrProgramStageFactory& factory,
1285 const GrCustomStage& stage)
1286 : GrGLLightingEffect(factory, stage)
bsalomon@google.com032b2212012-07-16 13:36:18 +00001287 , fKSUni(kInvalidUniformHandle)
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001288 , fShininessUni(kInvalidUniformHandle) {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001289}
1290
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001291void GrGLSpecularLightingEffect::setupVariables(GrGLShaderBuilder* builder) {
1292 INHERITED::setupVariables(builder);
bsalomon@google.com032b2212012-07-16 13:36:18 +00001293 fKSUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001294 kFloat_GrSLType, "KS");
bsalomon@google.com032b2212012-07-16 13:36:18 +00001295 fShininessUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001296 kFloat_GrSLType, "Shininess");
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001297}
1298
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001299void GrGLSpecularLightingEffect::emitLightFunc(GrGLShaderBuilder* builder, SkString* funcName) {
bsalomon@google.com032b2212012-07-16 13:36:18 +00001300 const char* ks = builder->getUniformCStr(fKSUni);
1301 const char* shininess = builder->getUniformCStr(fShininessUni);
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001302
1303 static const GrGLShaderVar gLightArgs[] = {
1304 GrGLShaderVar("normal", kVec3f_GrSLType),
1305 GrGLShaderVar("surfaceToLight", kVec3f_GrSLType),
1306 GrGLShaderVar("lightColor", kVec3f_GrSLType)
1307 };
1308 SkString lightBody;
1309 lightBody.appendf("\tvec3 halfDir = vec3(normalize(surfaceToLight + vec3(0, 0, 1)));\n");
1310 lightBody.appendf("\tfloat colorScale = %s * pow(dot(normal, halfDir), %s);\n", ks, shininess);
1311 lightBody.appendf("\treturn vec4(lightColor * clamp(colorScale, 0.0, 1.0), 1.0);\n");
1312 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1313 kVec4f_GrSLType,
1314 "light",
1315 SK_ARRAY_COUNT(gLightArgs),
1316 gLightArgs,
1317 lightBody.c_str(),
1318 funcName);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001319}
1320
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001321void GrGLSpecularLightingEffect::setData(const GrGLUniformManager& uman,
tomhudson@google.comd0c1a062012-07-12 17:23:52 +00001322 const GrCustomStage& data,
senorblanco@chromium.orgf4770d72012-07-13 18:25:06 +00001323 const GrRenderTarget* rt,
tomhudson@google.comd0c1a062012-07-12 17:23:52 +00001324 int stageNum) {
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001325 INHERITED::setData(uman, data, rt, stageNum);
1326 const GrSpecularLightingEffect& effect = static_cast<const GrSpecularLightingEffect&>(data);
1327 uman.set1f(fKSUni, effect.ks());
1328 uman.set1f(fShininessUni, effect.shininess());
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001329}
1330
1331///////////////////////////////////////////////////////////////////////////////
1332
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001333void GrGLLight::emitLightColor(GrGLShaderBuilder* builder,
bsalomon@google.com032b2212012-07-16 13:36:18 +00001334 const char *surfaceToLight) const {
1335 const char* color = builder->getUniformCStr(fColorUni);
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001336 builder->fFSCode.append(color);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001337}
1338
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001339void GrGLLight::setupVariables(GrGLShaderBuilder* builder) {
bsalomon@google.com032b2212012-07-16 13:36:18 +00001340 fColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001341 kVec3f_GrSLType, "LightColor");
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001342}
1343
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001344void GrGLLight::setData(const GrGLUniformManager& uman,
1345 const GrRenderTarget* rt,
1346 const SkLight* light) const {
1347 setUniformPoint3(uman, fColorUni, light->color() * SkScalarInvert(SkIntToScalar(255)));
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001348}
1349
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001350///////////////////////////////////////////////////////////////////////////////
1351
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001352void GrGLDistantLight::setupVariables(GrGLShaderBuilder* builder) {
1353 INHERITED::setupVariables(builder);
bsalomon@google.com032b2212012-07-16 13:36:18 +00001354 fDirectionUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, kVec3f_GrSLType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001355 "LightDirection");
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001356}
1357
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001358void GrGLDistantLight::setData(const GrGLUniformManager& uman,
1359 const GrRenderTarget* rt,
1360 const SkLight* light) const {
1361 INHERITED::setData(uman, rt, light);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001362 SkASSERT(light->type() == SkLight::kDistant_LightType);
1363 const SkDistantLight* distantLight = static_cast<const SkDistantLight*>(light);
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001364 setUniformNormal3(uman, fDirectionUni, distantLight->direction());
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001365}
1366
bsalomon@google.com032b2212012-07-16 13:36:18 +00001367void GrGLDistantLight::emitSurfaceToLight(const GrGLShaderBuilder* builder,
1368 SkString* out,
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001369 const char* z) const {
bsalomon@google.com032b2212012-07-16 13:36:18 +00001370 const char* dir = builder->getUniformCStr(fDirectionUni);
1371 out->append(dir);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001372}
1373
1374///////////////////////////////////////////////////////////////////////////////
1375
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001376void GrGLPointLight::setupVariables(GrGLShaderBuilder* builder) {
1377 INHERITED::setupVariables(builder);
bsalomon@google.com032b2212012-07-16 13:36:18 +00001378 fLocationUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, kVec3f_GrSLType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001379 "LightLocation");
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001380}
1381
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001382void GrGLPointLight::setData(const GrGLUniformManager& uman,
1383 const GrRenderTarget* rt,
1384 const SkLight* light) const {
1385 INHERITED::setData(uman, rt, light);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001386 SkASSERT(light->type() == SkLight::kPoint_LightType);
1387 const SkPointLight* pointLight = static_cast<const SkPointLight*>(light);
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001388 setUniformPoint3FlipY(uman, fLocationUni, pointLight->location(), rt->height());
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001389}
1390
bsalomon@google.com032b2212012-07-16 13:36:18 +00001391void GrGLPointLight::emitVS(SkString* out) const {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001392}
1393
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001394void GrGLPointLight::emitSurfaceToLight(const GrGLShaderBuilder* builder,
1395 SkString* out,
1396 const char* z) const {
bsalomon@google.com032b2212012-07-16 13:36:18 +00001397 const char* loc = builder->getUniformCStr(fLocationUni);
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001398 out->appendf("normalize(%s - vec3(gl_FragCoord.xy, %s))", loc, z);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001399}
1400
1401///////////////////////////////////////////////////////////////////////////////
1402
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001403void GrGLSpotLight::setupVariables(GrGLShaderBuilder* builder) {
1404 INHERITED::setupVariables(builder);
bsalomon@google.com032b2212012-07-16 13:36:18 +00001405 fLocationUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001406 kVec3f_GrSLType, "LightLocation");
bsalomon@google.com032b2212012-07-16 13:36:18 +00001407 fExponentUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001408 kFloat_GrSLType, "Exponent");
bsalomon@google.com032b2212012-07-16 13:36:18 +00001409 fCosInnerConeAngleUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001410 kFloat_GrSLType, "CosInnerConeAngle");
bsalomon@google.com032b2212012-07-16 13:36:18 +00001411 fCosOuterConeAngleUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001412 kFloat_GrSLType, "CosOuterConeAngle");
bsalomon@google.com032b2212012-07-16 13:36:18 +00001413 fConeScaleUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001414 kFloat_GrSLType, "ConeScale");
bsalomon@google.com032b2212012-07-16 13:36:18 +00001415 fSUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001416 kVec3f_GrSLType, "S");
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001417}
1418
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001419void GrGLSpotLight::setData(const GrGLUniformManager& uman,
1420 const GrRenderTarget* rt,
1421 const SkLight* light) const {
1422 INHERITED::setData(uman, rt, light);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001423 SkASSERT(light->type() == SkLight::kSpot_LightType);
1424 const SkSpotLight* spotLight = static_cast<const SkSpotLight *>(light);
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001425 setUniformPoint3FlipY(uman, fLocationUni, spotLight->location(), rt->height());
1426 uman.set1f(fExponentUni, spotLight->specularExponent());
1427 uman.set1f(fCosInnerConeAngleUni, spotLight->cosInnerConeAngle());
1428 uman.set1f(fCosOuterConeAngleUni, spotLight->cosOuterConeAngle());
1429 uman.set1f(fConeScaleUni, spotLight->coneScale());
1430 setUniformNormal3(uman, fSUni, spotLight->s());
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001431}
1432
bsalomon@google.com032b2212012-07-16 13:36:18 +00001433void GrGLSpotLight::emitVS(SkString* out) const {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001434}
1435
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001436void GrGLSpotLight::emitFuncs(GrGLShaderBuilder* builder) {
bsalomon@google.com032b2212012-07-16 13:36:18 +00001437 const char* exponent = builder->getUniformCStr(fExponentUni);
1438 const char* cosInner = builder->getUniformCStr(fCosInnerConeAngleUni);
1439 const char* cosOuter = builder->getUniformCStr(fCosOuterConeAngleUni);
1440 const char* coneScale = builder->getUniformCStr(fConeScaleUni);
1441 const char* s = builder->getUniformCStr(fSUni);
1442 const char* color = builder->getUniformCStr(fColorUni);
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001443 static const GrGLShaderVar gLightColorArgs[] = {
1444 GrGLShaderVar("surfaceToLight", kVec3f_GrSLType)
1445 };
1446 SkString lightColorBody;
1447 lightColorBody.appendf("\tfloat cosAngle = -dot(surfaceToLight, %s);\n", s);
1448 lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosOuter);
1449 lightColorBody.appendf("\t\treturn vec3(0);\n");
1450 lightColorBody.appendf("\t}\n");
1451 lightColorBody.appendf("\tfloat scale = pow(cosAngle, %s);\n", exponent);
1452 lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosInner);
1453 lightColorBody.appendf("\t\treturn %s * scale * (cosAngle - %s) * %s;\n",
1454 color, cosOuter, coneScale);
1455 lightColorBody.appendf("\t}\n");
1456 lightColorBody.appendf("\treturn %s;\n", color);
1457 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1458 kVec3f_GrSLType,
1459 "lightColor",
1460 SK_ARRAY_COUNT(gLightColorArgs),
1461 gLightColorArgs,
1462 lightColorBody.c_str(),
1463 &fLightColorFunc);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001464}
1465
bsalomon@google.com032b2212012-07-16 13:36:18 +00001466void GrGLSpotLight::emitSurfaceToLight(const GrGLShaderBuilder* builder,
1467 SkString* out,
1468 const char* z) const {
1469 const char* location= builder->getUniformCStr(fLocationUni);
1470 out->appendf("normalize(%s - vec3(gl_FragCoord.xy, %s))", location, z);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001471}
1472
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001473void GrGLSpotLight::emitLightColor(GrGLShaderBuilder* builder,
1474 const char *surfaceToLight) const {
1475 builder->fFSCode.appendf("%s(%s)", fLightColorFunc.c_str(), surfaceToLight);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001476}
1477
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +00001478#endif
1479
djsollen@google.com08337772012-06-26 14:33:13 +00001480SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingImageFilter)
1481 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDiffuseLightingImageFilter)
1482 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSpecularLightingImageFilter)
1483 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDistantLight)
1484 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPointLight)
1485 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSpotLight)
1486SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END