blob: ab962fb2b77ce0703131c132abb4e6535446201b [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"
bsalomon@google.coma469c282012-10-24 18:28:34 +000021#include "GrEffect.h"
senorblanco@chromium.org894790d2012-07-11 16:01:22 +000022
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) {
bsalomon@google.com706f6682012-10-23 14:53:55 +000045 setUniformPoint3(uman, uni, SkPoint3(point.fX, point.fY, point.fZ));
senorblanco@chromium.orgf4770d72012-07-13 18:25:06 +000046}
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +000047#endif
senorblanco@chromium.orgf4770d72012-07-13 18:25:06 +000048
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +000049// Shift matrix components to the left, as we advance pixels to the right.
50inline void shiftMatrixLeft(int m[9]) {
51 m[0] = m[1];
52 m[3] = m[4];
53 m[6] = m[7];
54 m[1] = m[2];
55 m[4] = m[5];
56 m[7] = m[8];
57}
58
59class DiffuseLightingType {
60public:
61 DiffuseLightingType(SkScalar kd)
62 : fKD(kd) {}
63 SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight, const SkPoint3& lightColor) const {
64 SkScalar colorScale = SkScalarMul(fKD, normal.dot(surfaceTolight));
65 colorScale = SkScalarClampMax(colorScale, SK_Scalar1);
66 SkPoint3 color(lightColor * colorScale);
67 return SkPackARGB32(255,
68 SkScalarFloorToInt(color.fX),
69 SkScalarFloorToInt(color.fY),
70 SkScalarFloorToInt(color.fZ));
71 }
72private:
73 SkScalar fKD;
74};
75
76class SpecularLightingType {
77public:
78 SpecularLightingType(SkScalar ks, SkScalar shininess)
79 : fKS(ks), fShininess(shininess) {}
80 SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight, const SkPoint3& lightColor) const {
81 SkPoint3 halfDir(surfaceTolight);
82 halfDir.fZ += SK_Scalar1; // eye position is always (0, 0, 1)
83 halfDir.normalize();
84 SkScalar colorScale = SkScalarMul(fKS,
85 SkScalarPow(normal.dot(halfDir), fShininess));
86 colorScale = SkScalarClampMax(colorScale, SK_Scalar1);
87 SkPoint3 color(lightColor * colorScale);
88 return SkPackARGB32(SkScalarFloorToInt(color.maxComponent()),
89 SkScalarFloorToInt(color.fX),
90 SkScalarFloorToInt(color.fY),
91 SkScalarFloorToInt(color.fZ));
92 }
93private:
94 SkScalar fKS;
95 SkScalar fShininess;
96};
97
98inline SkScalar sobel(int a, int b, int c, int d, int e, int f, SkScalar scale) {
99 return SkScalarMul(SkIntToScalar(-a + b - 2 * c + 2 * d -e + f), scale);
100}
101
102inline SkPoint3 pointToNormal(SkScalar x, SkScalar y, SkScalar surfaceScale) {
103 SkPoint3 vector(SkScalarMul(-x, surfaceScale),
104 SkScalarMul(-y, surfaceScale),
105 SK_Scalar1);
106 vector.normalize();
107 return vector;
108}
109
110inline SkPoint3 topLeftNormal(int m[9], SkScalar surfaceScale) {
111 return pointToNormal(sobel(0, 0, m[4], m[5], m[7], m[8], gTwoThirds),
112 sobel(0, 0, m[4], m[7], m[5], m[8], gTwoThirds),
113 surfaceScale);
114}
115
116inline SkPoint3 topNormal(int m[9], SkScalar surfaceScale) {
117 return pointToNormal(sobel( 0, 0, m[3], m[5], m[6], m[8], gOneThird),
118 sobel(m[3], m[6], m[4], m[7], m[5], m[8], gOneHalf),
119 surfaceScale);
120}
121
122inline SkPoint3 topRightNormal(int m[9], SkScalar surfaceScale) {
123 return pointToNormal(sobel( 0, 0, m[3], m[4], m[6], m[7], gTwoThirds),
124 sobel(m[3], m[6], m[4], m[7], 0, 0, gTwoThirds),
125 surfaceScale);
126}
127
128inline SkPoint3 leftNormal(int m[9], SkScalar surfaceScale) {
129 return pointToNormal(sobel(m[1], m[2], m[4], m[5], m[7], m[8], gOneHalf),
130 sobel( 0, 0, m[1], m[7], m[2], m[8], gOneThird),
131 surfaceScale);
132}
133
134
135inline SkPoint3 interiorNormal(int m[9], SkScalar surfaceScale) {
136 return pointToNormal(sobel(m[0], m[2], m[3], m[5], m[6], m[8], gOneQuarter),
137 sobel(m[0], m[6], m[1], m[7], m[2], m[8], gOneQuarter),
138 surfaceScale);
139}
140
141inline SkPoint3 rightNormal(int m[9], SkScalar surfaceScale) {
142 return pointToNormal(sobel(m[0], m[1], m[3], m[4], m[6], m[7], gOneHalf),
143 sobel(m[0], m[6], m[1], m[7], 0, 0, gOneThird),
144 surfaceScale);
145}
146
147inline SkPoint3 bottomLeftNormal(int m[9], SkScalar surfaceScale) {
148 return pointToNormal(sobel(m[1], m[2], m[4], m[5], 0, 0, gTwoThirds),
149 sobel( 0, 0, m[1], m[4], m[2], m[5], gTwoThirds),
150 surfaceScale);
151}
152
153inline SkPoint3 bottomNormal(int m[9], SkScalar surfaceScale) {
154 return pointToNormal(sobel(m[0], m[2], m[3], m[5], 0, 0, gOneThird),
155 sobel(m[0], m[3], m[1], m[4], m[2], m[5], gOneHalf),
156 surfaceScale);
157}
158
159inline SkPoint3 bottomRightNormal(int m[9], SkScalar surfaceScale) {
160 return pointToNormal(sobel(m[0], m[1], m[3], m[4], 0, 0, gTwoThirds),
161 sobel(m[0], m[3], m[1], m[4], 0, 0, gTwoThirds),
162 surfaceScale);
163}
164
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000165template <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 +0000166 const LightType* l = static_cast<const LightType*>(light);
167 int y = 0;
168 {
169 const SkPMColor* row1 = src.getAddr32(0, 0);
170 const SkPMColor* row2 = src.getAddr32(0, 1);
171 SkPMColor* dptr = dst->getAddr32(0, 0);
172 int m[9];
173 int x = 0;
174 m[4] = SkGetPackedA32(*row1++);
175 m[5] = SkGetPackedA32(*row1++);
176 m[7] = SkGetPackedA32(*row2++);
177 m[8] = SkGetPackedA32(*row2++);
178 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000179 *dptr++ = lightingType.light(topLeftNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000180 for (x = 1; x < src.width() - 1; ++x)
181 {
182 shiftMatrixLeft(m);
183 m[5] = SkGetPackedA32(*row1++);
184 m[8] = SkGetPackedA32(*row2++);
185 surfaceToLight = l->surfaceToLight(x, 0, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000186 *dptr++ = lightingType.light(topNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000187 }
188 shiftMatrixLeft(m);
189 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000190 *dptr++ = lightingType.light(topRightNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000191 }
192
193 for (++y; y < src.height() - 1; ++y) {
194 const SkPMColor* row0 = src.getAddr32(0, y - 1);
195 const SkPMColor* row1 = src.getAddr32(0, y);
196 const SkPMColor* row2 = src.getAddr32(0, y + 1);
197 SkPMColor* dptr = dst->getAddr32(0, y);
198 int m[9];
199 int x = 0;
200 m[1] = SkGetPackedA32(*row0++);
201 m[2] = SkGetPackedA32(*row0++);
202 m[4] = SkGetPackedA32(*row1++);
203 m[5] = SkGetPackedA32(*row1++);
204 m[7] = SkGetPackedA32(*row2++);
205 m[8] = SkGetPackedA32(*row2++);
206 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000207 *dptr++ = lightingType.light(leftNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000208 for (x = 1; x < src.width() - 1; ++x) {
209 shiftMatrixLeft(m);
210 m[2] = SkGetPackedA32(*row0++);
211 m[5] = SkGetPackedA32(*row1++);
212 m[8] = SkGetPackedA32(*row2++);
213 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000214 *dptr++ = lightingType.light(interiorNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000215 }
216 shiftMatrixLeft(m);
217 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000218 *dptr++ = lightingType.light(rightNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000219 }
220
221 {
222 const SkPMColor* row0 = src.getAddr32(0, src.height() - 2);
223 const SkPMColor* row1 = src.getAddr32(0, src.height() - 1);
224 int x = 0;
225 SkPMColor* dptr = dst->getAddr32(0, src.height() - 1);
226 int m[9];
227 m[1] = SkGetPackedA32(*row0++);
228 m[2] = SkGetPackedA32(*row0++);
229 m[4] = SkGetPackedA32(*row1++);
230 m[5] = SkGetPackedA32(*row1++);
231 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000232 *dptr++ = lightingType.light(bottomLeftNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000233 for (x = 1; x < src.width() - 1; ++x)
234 {
235 shiftMatrixLeft(m);
236 m[2] = SkGetPackedA32(*row0++);
237 m[5] = SkGetPackedA32(*row1++);
238 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000239 *dptr++ = lightingType.light(bottomNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000240 }
241 shiftMatrixLeft(m);
242 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000243 *dptr++ = lightingType.light(bottomRightNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000244 }
245}
246
247SkPoint3 readPoint3(SkFlattenableReadBuffer& buffer) {
248 SkPoint3 point;
249 point.fX = buffer.readScalar();
250 point.fY = buffer.readScalar();
251 point.fZ = buffer.readScalar();
252 return point;
253};
254
255void writePoint3(const SkPoint3& point, SkFlattenableWriteBuffer& buffer) {
256 buffer.writeScalar(point.fX);
257 buffer.writeScalar(point.fY);
258 buffer.writeScalar(point.fZ);
259};
260
261class SkDiffuseLightingImageFilter : public SkLightingImageFilter {
262public:
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000263 SkDiffuseLightingImageFilter(SkLight* light, SkScalar surfaceScale,
264 SkScalar kd, SkImageFilter* input);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000265 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDiffuseLightingImageFilter)
266
bsalomon@google.coma469c282012-10-24 18:28:34 +0000267 virtual bool asNewCustomStage(GrEffect** stage, GrTexture*) const SK_OVERRIDE;
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000268 SkScalar kd() const { return fKD; }
269
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000270protected:
271 explicit SkDiffuseLightingImageFilter(SkFlattenableReadBuffer& buffer);
272 virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE;
273 virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
274 SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
275
276
277private:
278 typedef SkLightingImageFilter INHERITED;
279 SkScalar fKD;
280};
281
282class SkSpecularLightingImageFilter : public SkLightingImageFilter {
283public:
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000284 SkSpecularLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess, SkImageFilter* input);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000285 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSpecularLightingImageFilter)
286
bsalomon@google.coma469c282012-10-24 18:28:34 +0000287 virtual bool asNewCustomStage(GrEffect** stage, GrTexture*) const SK_OVERRIDE;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000288 SkScalar ks() const { return fKS; }
289 SkScalar shininess() const { return fShininess; }
290
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000291protected:
292 explicit SkSpecularLightingImageFilter(SkFlattenableReadBuffer& buffer);
293 virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE;
294 virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
295 SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
296
297private:
298 typedef SkLightingImageFilter INHERITED;
299 SkScalar fKS;
300 SkScalar fShininess;
301};
302
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000303#if SK_SUPPORT_GPU
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000304
tomhudson@google.comd0c1a062012-07-12 17:23:52 +0000305class GrLightingEffect : public GrSingleTextureEffect {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000306public:
tomhudson@google.comd0c1a062012-07-12 17:23:52 +0000307 GrLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000308 virtual ~GrLightingEffect();
309
bsalomon@google.coma469c282012-10-24 18:28:34 +0000310 virtual bool isEqual(const GrEffect&) const SK_OVERRIDE;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000311
312 const SkLight* light() const { return fLight; }
313 SkScalar surfaceScale() const { return fSurfaceScale; }
314private:
tomhudson@google.comd0c1a062012-07-12 17:23:52 +0000315 typedef GrSingleTextureEffect INHERITED;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000316 const SkLight* fLight;
317 SkScalar fSurfaceScale;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000318};
319
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000320class GrDiffuseLightingEffect : public GrLightingEffect {
321public:
tomhudson@google.comd0c1a062012-07-12 17:23:52 +0000322 GrDiffuseLightingEffect(GrTexture* texture,
323 const SkLight* light,
324 SkScalar surfaceScale,
325 SkScalar kd);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000326
327 static const char* Name() { return "DiffuseLighting"; }
328
329 typedef GrGLDiffuseLightingEffect GLProgramStage;
330
331 virtual const GrProgramStageFactory& getFactory() const SK_OVERRIDE;
bsalomon@google.coma469c282012-10-24 18:28:34 +0000332 virtual bool isEqual(const GrEffect&) const SK_OVERRIDE;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000333 SkScalar kd() const { return fKD; }
334private:
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000335 GR_DECLARE_CUSTOM_STAGE_TEST;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000336 typedef GrLightingEffect INHERITED;
337 SkScalar fKD;
338};
339
340class GrSpecularLightingEffect : public GrLightingEffect {
341public:
tomhudson@google.comd0c1a062012-07-12 17:23:52 +0000342 GrSpecularLightingEffect(GrTexture* texture,
343 const SkLight* light,
344 SkScalar surfaceScale,
345 SkScalar ks,
346 SkScalar shininess);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000347
348 static const char* Name() { return "SpecularLighting"; }
349
350 typedef GrGLSpecularLightingEffect GLProgramStage;
351
352 virtual const GrProgramStageFactory& getFactory() const SK_OVERRIDE;
bsalomon@google.coma469c282012-10-24 18:28:34 +0000353 virtual bool isEqual(const GrEffect&) const SK_OVERRIDE;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000354 SkScalar ks() const { return fKS; }
355 SkScalar shininess() const { return fShininess; }
356
357private:
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000358 GR_DECLARE_CUSTOM_STAGE_TEST;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000359 typedef GrLightingEffect INHERITED;
360 SkScalar fKS;
361 SkScalar fShininess;
362};
363
364///////////////////////////////////////////////////////////////////////////////
365
366class GrGLLight {
367public:
senorblanco@chromium.org6730cbb2012-07-11 16:35:00 +0000368 virtual ~GrGLLight() {}
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000369 virtual void setupVariables(GrGLShaderBuilder* builder);
bsalomon@google.com032b2212012-07-16 13:36:18 +0000370 virtual void emitVS(SkString* out) const {}
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000371 virtual void emitFuncs(GrGLShaderBuilder* builder) {}
bsalomon@google.com706f6682012-10-23 14:53:55 +0000372 virtual void emitSurfaceToLight(GrGLShaderBuilder*,
bsalomon@google.com032b2212012-07-16 13:36:18 +0000373 SkString* out,
374 const char* z) const = 0;
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000375 virtual void emitLightColor(GrGLShaderBuilder*,
bsalomon@google.com032b2212012-07-16 13:36:18 +0000376 const char *surfaceToLight) const;
bsalomon@google.com706f6682012-10-23 14:53:55 +0000377 virtual void setData(const GrGLUniformManager&, const SkLight* light) const;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000378
379private:
380 typedef SkRefCnt INHERITED;
381
382protected:
bsalomon@google.com032b2212012-07-16 13:36:18 +0000383 UniformHandle fColorUni;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000384};
385
386///////////////////////////////////////////////////////////////////////////////
387
388class GrGLDistantLight : public GrGLLight {
389public:
senorblanco@chromium.org6730cbb2012-07-11 16:35:00 +0000390 virtual ~GrGLDistantLight() {}
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000391 virtual void setupVariables(GrGLShaderBuilder* builder) SK_OVERRIDE;
bsalomon@google.com706f6682012-10-23 14:53:55 +0000392 virtual void setData(const GrGLUniformManager&, const SkLight* light) const SK_OVERRIDE;
393 virtual void emitSurfaceToLight(GrGLShaderBuilder*,
bsalomon@google.com032b2212012-07-16 13:36:18 +0000394 SkString* out,
395 const char* z) const SK_OVERRIDE;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000396private:
397 typedef GrGLLight INHERITED;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000398 UniformHandle fDirectionUni;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000399};
400
401///////////////////////////////////////////////////////////////////////////////
402
403class GrGLPointLight : public GrGLLight {
404public:
senorblanco@chromium.org6730cbb2012-07-11 16:35:00 +0000405 virtual ~GrGLPointLight() {}
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000406 virtual void setupVariables(GrGLShaderBuilder* builder) SK_OVERRIDE;
bsalomon@google.com706f6682012-10-23 14:53:55 +0000407 virtual void setData(const GrGLUniformManager&, const SkLight* light) const SK_OVERRIDE;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000408 virtual void emitVS(SkString* out) const SK_OVERRIDE;
bsalomon@google.com706f6682012-10-23 14:53:55 +0000409 virtual void emitSurfaceToLight(GrGLShaderBuilder*,
bsalomon@google.com032b2212012-07-16 13:36:18 +0000410 SkString* out,
411 const char* z) const SK_OVERRIDE;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000412private:
413 typedef GrGLLight INHERITED;
414 SkPoint3 fLocation;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000415 UniformHandle fLocationUni;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000416};
417
418///////////////////////////////////////////////////////////////////////////////
419
420class GrGLSpotLight : public GrGLLight {
421public:
senorblanco@chromium.org6730cbb2012-07-11 16:35:00 +0000422 virtual ~GrGLSpotLight() {}
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000423 virtual void setupVariables(GrGLShaderBuilder* builder) SK_OVERRIDE;
bsalomon@google.com706f6682012-10-23 14:53:55 +0000424 virtual void setData(const GrGLUniformManager&, const SkLight* light) const SK_OVERRIDE;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000425 virtual void emitVS(SkString* out) const SK_OVERRIDE;
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000426 virtual void emitFuncs(GrGLShaderBuilder* builder);
bsalomon@google.com706f6682012-10-23 14:53:55 +0000427 virtual void emitSurfaceToLight(GrGLShaderBuilder* builder,
bsalomon@google.com032b2212012-07-16 13:36:18 +0000428 SkString* out,
429 const char* z) const SK_OVERRIDE;
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000430 virtual void emitLightColor(GrGLShaderBuilder*,
bsalomon@google.com032b2212012-07-16 13:36:18 +0000431 const char *surfaceToLight) const SK_OVERRIDE;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000432
433private:
434 typedef GrGLLight INHERITED;
435
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000436 SkString fLightColorFunc;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000437 UniformHandle fLocationUni;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000438 UniformHandle fExponentUni;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000439 UniformHandle fCosOuterConeAngleUni;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000440 UniformHandle fCosInnerConeAngleUni;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000441 UniformHandle fConeScaleUni;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000442 UniformHandle fSUni;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000443};
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000444#else
445
446class GrGLLight;
447
448#endif
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000449
450};
451
452///////////////////////////////////////////////////////////////////////////////
453
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000454class SkLight : public SkFlattenable {
455public:
robertphillips@google.com0456e0b2012-06-27 14:03:26 +0000456 SK_DECLARE_INST_COUNT(SkLight)
457
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000458 enum LightType {
459 kDistant_LightType,
460 kPoint_LightType,
461 kSpot_LightType,
462 };
463 virtual LightType type() const = 0;
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000464 const SkPoint3& color() const { return fColor; }
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000465 virtual GrGLLight* createGLLight() const = 0;
466 virtual bool isEqual(const SkLight& other) const {
467 return fColor == other.fColor;
468 }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000469
djsollen@google.com08337772012-06-26 14:33:13 +0000470protected:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000471 SkLight(SkColor color)
472 : fColor(SkIntToScalar(SkColorGetR(color)),
473 SkIntToScalar(SkColorGetG(color)),
474 SkIntToScalar(SkColorGetB(color))) {}
475 SkLight(SkFlattenableReadBuffer& buffer)
476 : INHERITED(buffer) {
477 fColor = readPoint3(buffer);
478 }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000479 virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
djsollen@google.com08337772012-06-26 14:33:13 +0000480 INHERITED::flatten(buffer);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000481 writePoint3(fColor, buffer);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000482 }
djsollen@google.com08337772012-06-26 14:33:13 +0000483
484private:
485 typedef SkFlattenable INHERITED;
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000486 SkPoint3 fColor;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000487};
488
robertphillips@google.com0456e0b2012-06-27 14:03:26 +0000489SK_DEFINE_INST_COUNT(SkLight)
490
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000491///////////////////////////////////////////////////////////////////////////////
492
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000493class SkDistantLight : public SkLight {
494public:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000495 SkDistantLight(const SkPoint3& direction, SkColor color)
496 : INHERITED(color), fDirection(direction) {
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000497 }
djsollen@google.com08337772012-06-26 14:33:13 +0000498
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000499 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
500 return fDirection;
501 };
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000502 SkPoint3 lightColor(const SkPoint3&) const { return color(); }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000503 virtual LightType type() const { return kDistant_LightType; }
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000504 const SkPoint3& direction() const { return fDirection; }
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000505 virtual GrGLLight* createGLLight() const SK_OVERRIDE {
506#if SK_SUPPORT_GPU
507 return SkNEW(GrGLDistantLight);
508#else
509 SkDEBUGFAIL("Should not call in GPU-less build");
510 return NULL;
511#endif
512 }
senorblanco@chromium.org6730cbb2012-07-11 16:35:00 +0000513 virtual bool isEqual(const SkLight& other) const SK_OVERRIDE {
514 if (other.type() != kDistant_LightType) {
515 return false;
516 }
517
518 const SkDistantLight& o = static_cast<const SkDistantLight&>(other);
519 return INHERITED::isEqual(other) &&
520 fDirection == o.fDirection;
521 }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000522
523 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDistantLight)
524
djsollen@google.com08337772012-06-26 14:33:13 +0000525protected:
526 SkDistantLight(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
527 fDirection = readPoint3(buffer);
528 }
529 virtual void flatten(SkFlattenableWriteBuffer& buffer) const {
530 INHERITED::flatten(buffer);
531 writePoint3(fDirection, buffer);
532 }
533
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000534private:
djsollen@google.com08337772012-06-26 14:33:13 +0000535 typedef SkLight INHERITED;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000536 SkPoint3 fDirection;
537};
538
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000539///////////////////////////////////////////////////////////////////////////////
540
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000541class SkPointLight : public SkLight {
542public:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000543 SkPointLight(const SkPoint3& location, SkColor color)
544 : INHERITED(color), fLocation(location) {}
djsollen@google.com08337772012-06-26 14:33:13 +0000545
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000546 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
547 SkPoint3 direction(fLocation.fX - SkIntToScalar(x),
548 fLocation.fY - SkIntToScalar(y),
549 fLocation.fZ - SkScalarMul(SkIntToScalar(z), surfaceScale));
550 direction.normalize();
551 return direction;
552 };
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000553 SkPoint3 lightColor(const SkPoint3&) const { return color(); }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000554 virtual LightType type() const { return kPoint_LightType; }
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000555 const SkPoint3& location() const { return fLocation; }
556 virtual GrGLLight* createGLLight() const SK_OVERRIDE {
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000557#if SK_SUPPORT_GPU
tomhudson@google.com300f5622012-07-20 14:15:22 +0000558 return SkNEW(GrGLPointLight);
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000559#else
560 SkDEBUGFAIL("Should not call in GPU-less build");
561 return NULL;
562#endif
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000563 }
senorblanco@chromium.org6730cbb2012-07-11 16:35:00 +0000564 virtual bool isEqual(const SkLight& other) const SK_OVERRIDE {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000565 if (other.type() != kPoint_LightType) {
566 return false;
567 }
568 const SkPointLight& o = static_cast<const SkPointLight&>(other);
569 return INHERITED::isEqual(other) &&
570 fLocation == o.fLocation;
571 }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000572
573 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkPointLight)
574
djsollen@google.com08337772012-06-26 14:33:13 +0000575protected:
576 SkPointLight(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
577 fLocation = readPoint3(buffer);
578 }
579 virtual void flatten(SkFlattenableWriteBuffer& buffer) const {
580 INHERITED::flatten(buffer);
581 writePoint3(fLocation, buffer);
582 }
583
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000584private:
djsollen@google.com08337772012-06-26 14:33:13 +0000585 typedef SkLight INHERITED;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000586 SkPoint3 fLocation;
587};
588
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000589///////////////////////////////////////////////////////////////////////////////
590
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000591class SkSpotLight : public SkLight {
592public:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000593 SkSpotLight(const SkPoint3& location, const SkPoint3& target, SkScalar specularExponent, SkScalar cutoffAngle, SkColor color)
594 : INHERITED(color),
595 fLocation(location),
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000596 fTarget(target),
597 fSpecularExponent(specularExponent)
598 {
599 fS = target - location;
600 fS.normalize();
601 fCosOuterConeAngle = SkScalarCos(SkDegreesToRadians(cutoffAngle));
602 const SkScalar antiAliasThreshold = SkFloatToScalar(0.016f);
603 fCosInnerConeAngle = fCosOuterConeAngle + antiAliasThreshold;
604 fConeScale = SkScalarInvert(antiAliasThreshold);
605 }
djsollen@google.com08337772012-06-26 14:33:13 +0000606
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000607 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
608 SkPoint3 direction(fLocation.fX - SkIntToScalar(x),
609 fLocation.fY - SkIntToScalar(y),
610 fLocation.fZ - SkScalarMul(SkIntToScalar(z), surfaceScale));
611 direction.normalize();
612 return direction;
613 };
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000614 SkPoint3 lightColor(const SkPoint3& surfaceToLight) const {
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000615 SkScalar cosAngle = -surfaceToLight.dot(fS);
616 if (cosAngle < fCosOuterConeAngle) {
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000617 return SkPoint3(0, 0, 0);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000618 }
619 SkScalar scale = SkScalarPow(cosAngle, fSpecularExponent);
620 if (cosAngle < fCosInnerConeAngle) {
621 scale = SkScalarMul(scale, cosAngle - fCosOuterConeAngle);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000622 return color() * SkScalarMul(scale, fConeScale);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000623 }
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000624 return color() * scale;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000625 }
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000626 virtual GrGLLight* createGLLight() const SK_OVERRIDE {
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000627#if SK_SUPPORT_GPU
tomhudson@google.com300f5622012-07-20 14:15:22 +0000628 return SkNEW(GrGLSpotLight);
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000629#else
630 SkDEBUGFAIL("Should not call in GPU-less build");
631 return NULL;
632#endif
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000633 }
djsollen@google.com08337772012-06-26 14:33:13 +0000634 virtual LightType type() const { return kSpot_LightType; }
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000635 const SkPoint3& location() const { return fLocation; }
636 const SkPoint3& target() const { return fTarget; }
637 SkScalar specularExponent() const { return fSpecularExponent; }
638 SkScalar cosInnerConeAngle() const { return fCosInnerConeAngle; }
639 SkScalar cosOuterConeAngle() const { return fCosOuterConeAngle; }
640 SkScalar coneScale() const { return fConeScale; }
senorblanco@chromium.orgeb311842012-07-11 20:49:26 +0000641 const SkPoint3& s() const { return fS; }
djsollen@google.com08337772012-06-26 14:33:13 +0000642
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000643 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSpotLight)
644
djsollen@google.com08337772012-06-26 14:33:13 +0000645protected:
646 SkSpotLight(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
647 fLocation = readPoint3(buffer);
648 fTarget = readPoint3(buffer);
649 fSpecularExponent = buffer.readScalar();
650 fCosOuterConeAngle = buffer.readScalar();
651 fCosInnerConeAngle = buffer.readScalar();
652 fConeScale = buffer.readScalar();
653 fS = readPoint3(buffer);
654 }
655 virtual void flatten(SkFlattenableWriteBuffer& buffer) const {
656 INHERITED::flatten(buffer);
657 writePoint3(fLocation, buffer);
658 writePoint3(fTarget, buffer);
659 buffer.writeScalar(fSpecularExponent);
660 buffer.writeScalar(fCosOuterConeAngle);
661 buffer.writeScalar(fCosInnerConeAngle);
662 buffer.writeScalar(fConeScale);
663 writePoint3(fS, buffer);
664 }
665
senorblanco@chromium.orgbd9fad62012-07-11 16:25:37 +0000666 virtual bool isEqual(const SkLight& other) const SK_OVERRIDE {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000667 if (other.type() != kSpot_LightType) {
668 return false;
669 }
670
671 const SkSpotLight& o = static_cast<const SkSpotLight&>(other);
672 return INHERITED::isEqual(other) &&
673 fLocation == o.fLocation &&
674 fTarget == o.fTarget &&
675 fSpecularExponent == o.fSpecularExponent &&
676 fCosOuterConeAngle == o.fCosOuterConeAngle;
677 }
678
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000679private:
djsollen@google.com08337772012-06-26 14:33:13 +0000680 typedef SkLight INHERITED;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000681 SkPoint3 fLocation;
682 SkPoint3 fTarget;
683 SkScalar fSpecularExponent;
684 SkScalar fCosOuterConeAngle;
685 SkScalar fCosInnerConeAngle;
686 SkScalar fConeScale;
687 SkPoint3 fS;
688};
689
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000690///////////////////////////////////////////////////////////////////////////////
691
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000692SkLightingImageFilter::SkLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkImageFilter* input)
693 : INHERITED(input),
694 fLight(light),
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000695 fSurfaceScale(SkScalarDiv(surfaceScale, SkIntToScalar(255)))
696{
697 SkASSERT(fLight);
reed@google.com51f38662012-06-27 14:24:29 +0000698 // our caller knows that we take ownership of the light, so we don't
699 // need to call ref() here.
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000700}
701
702SkImageFilter* SkLightingImageFilter::CreateDistantLitDiffuse(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000703 const SkPoint3& direction, SkColor lightColor, SkScalar surfaceScale,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000704 SkScalar kd, SkImageFilter* input) {
tomhudson@google.com300f5622012-07-20 14:15:22 +0000705 return SkNEW_ARGS(SkDiffuseLightingImageFilter,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000706 (SkNEW_ARGS(SkDistantLight, (direction, lightColor)), surfaceScale, kd,
707 input));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000708}
709
710SkImageFilter* SkLightingImageFilter::CreatePointLitDiffuse(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000711 const SkPoint3& location, SkColor lightColor, SkScalar surfaceScale,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000712 SkScalar kd, SkImageFilter* input) {
tomhudson@google.com300f5622012-07-20 14:15:22 +0000713 return SkNEW_ARGS(SkDiffuseLightingImageFilter,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000714 (SkNEW_ARGS(SkPointLight, (location, lightColor)), surfaceScale, kd,
715 input));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000716}
717
718SkImageFilter* SkLightingImageFilter::CreateSpotLitDiffuse(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000719 const SkPoint3& location, const SkPoint3& target,
720 SkScalar specularExponent, SkScalar cutoffAngle,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000721 SkColor lightColor, SkScalar surfaceScale, SkScalar kd,
722 SkImageFilter* input) {
tomhudson@google.com300f5622012-07-20 14:15:22 +0000723 return SkNEW_ARGS(SkDiffuseLightingImageFilter,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000724 (SkNEW_ARGS(SkSpotLight, (location, target, specularExponent,
725 cutoffAngle, lightColor)),
726 surfaceScale, kd, input));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000727}
728
729SkImageFilter* SkLightingImageFilter::CreateDistantLitSpecular(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000730 const SkPoint3& direction, SkColor lightColor, SkScalar surfaceScale,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000731 SkScalar ks, SkScalar shininess, SkImageFilter* input) {
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000732 return SkNEW_ARGS(SkSpecularLightingImageFilter,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000733 (SkNEW_ARGS(SkDistantLight, (direction, lightColor)),
734 surfaceScale, ks, shininess, input));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000735}
736
737SkImageFilter* SkLightingImageFilter::CreatePointLitSpecular(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000738 const SkPoint3& location, SkColor lightColor, SkScalar surfaceScale,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000739 SkScalar ks, SkScalar shininess, SkImageFilter* input) {
tomhudson@google.com300f5622012-07-20 14:15:22 +0000740 return SkNEW_ARGS(SkSpecularLightingImageFilter,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000741 (SkNEW_ARGS(SkPointLight, (location, lightColor)),
742 surfaceScale, ks, shininess, input));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000743}
744
745SkImageFilter* SkLightingImageFilter::CreateSpotLitSpecular(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000746 const SkPoint3& location, const SkPoint3& target,
747 SkScalar specularExponent, SkScalar cutoffAngle,
748 SkColor lightColor, SkScalar surfaceScale,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000749 SkScalar ks, SkScalar shininess, SkImageFilter* input) {
tomhudson@google.com300f5622012-07-20 14:15:22 +0000750 return SkNEW_ARGS(SkSpecularLightingImageFilter,
751 (SkNEW_ARGS(SkSpotLight, (location, target, specularExponent, cutoffAngle, lightColor)),
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000752 surfaceScale, ks, shininess, input));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000753}
754
755SkLightingImageFilter::~SkLightingImageFilter() {
756 fLight->unref();
757}
758
759SkLightingImageFilter::SkLightingImageFilter(SkFlattenableReadBuffer& buffer)
760 : INHERITED(buffer)
761{
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000762 fLight = buffer.readFlattenableT<SkLight>();
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000763 fSurfaceScale = buffer.readScalar();
764}
765
766void SkLightingImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
767 this->INHERITED::flatten(buffer);
djsollen@google.com08337772012-06-26 14:33:13 +0000768 buffer.writeFlattenable(fLight);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000769 buffer.writeScalar(fSurfaceScale);
770}
771
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000772///////////////////////////////////////////////////////////////////////////////
773
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000774SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar kd, SkImageFilter* input)
775 : SkLightingImageFilter(light, surfaceScale, input),
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000776 fKD(kd)
777{
778}
779
780SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkFlattenableReadBuffer& buffer)
781 : INHERITED(buffer)
782{
783 fKD = buffer.readScalar();
784}
785
786void SkDiffuseLightingImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
787 this->INHERITED::flatten(buffer);
788 buffer.writeScalar(fKD);
789}
790
791bool SkDiffuseLightingImageFilter::onFilterImage(Proxy*,
792 const SkBitmap& src,
793 const SkMatrix&,
794 SkBitmap* dst,
795 SkIPoint*) {
796 if (src.config() != SkBitmap::kARGB_8888_Config) {
797 return false;
798 }
799 SkAutoLockPixels alp(src);
800 if (!src.getPixels()) {
801 return false;
802 }
803 if (src.width() < 2 || src.height() < 2) {
804 return false;
805 }
806 dst->setConfig(src.config(), src.width(), src.height());
807 dst->allocPixels();
808
809 DiffuseLightingType lightingType(fKD);
810 switch (light()->type()) {
811 case SkLight::kDistant_LightType:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000812 lightBitmap<DiffuseLightingType, SkDistantLight>(lightingType, light(), src, dst, surfaceScale());
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000813 break;
814 case SkLight::kPoint_LightType:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000815 lightBitmap<DiffuseLightingType, SkPointLight>(lightingType, light(), src, dst, surfaceScale());
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000816 break;
817 case SkLight::kSpot_LightType:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000818 lightBitmap<DiffuseLightingType, SkSpotLight>(lightingType, light(), src, dst, surfaceScale());
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000819 break;
820 }
821 return true;
822}
823
bsalomon@google.coma469c282012-10-24 18:28:34 +0000824bool SkDiffuseLightingImageFilter::asNewCustomStage(GrEffect** stage,
tomhudson@google.comd0c1a062012-07-12 17:23:52 +0000825 GrTexture* texture) const {
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000826#if SK_SUPPORT_GPU
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000827 if (stage) {
828 SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255));
tomhudson@google.com300f5622012-07-20 14:15:22 +0000829 *stage = SkNEW_ARGS(GrDiffuseLightingEffect, (texture, light(), scale, kd()));
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000830 }
831 return true;
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000832#else
833 SkDEBUGFAIL("Should not call in GPU-less build");
834 return false;
835#endif
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000836}
837
838///////////////////////////////////////////////////////////////////////////////
839
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000840SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess, SkImageFilter* input)
841 : SkLightingImageFilter(light, surfaceScale, input),
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000842 fKS(ks),
843 fShininess(shininess)
844{
845}
846
847SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkFlattenableReadBuffer& buffer)
848 : INHERITED(buffer)
849{
850 fKS = buffer.readScalar();
851 fShininess = buffer.readScalar();
852}
853
854void SkSpecularLightingImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
855 this->INHERITED::flatten(buffer);
856 buffer.writeScalar(fKS);
857 buffer.writeScalar(fShininess);
858}
859
860bool SkSpecularLightingImageFilter::onFilterImage(Proxy*,
861 const SkBitmap& src,
862 const SkMatrix&,
863 SkBitmap* dst,
864 SkIPoint*) {
865 if (src.config() != SkBitmap::kARGB_8888_Config) {
866 return false;
867 }
868 SkAutoLockPixels alp(src);
869 if (!src.getPixels()) {
870 return false;
871 }
872 if (src.width() < 2 || src.height() < 2) {
873 return false;
874 }
875 dst->setConfig(src.config(), src.width(), src.height());
876 dst->allocPixels();
877
878 SpecularLightingType lightingType(fKS, fShininess);
879 switch (light()->type()) {
880 case SkLight::kDistant_LightType:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000881 lightBitmap<SpecularLightingType, SkDistantLight>(lightingType, light(), src, dst, surfaceScale());
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000882 break;
883 case SkLight::kPoint_LightType:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000884 lightBitmap<SpecularLightingType, SkPointLight>(lightingType, light(), src, dst, surfaceScale());
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000885 break;
886 case SkLight::kSpot_LightType:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000887 lightBitmap<SpecularLightingType, SkSpotLight>(lightingType, light(), src, dst, surfaceScale());
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000888 break;
889 }
890 return true;
891}
892
bsalomon@google.coma469c282012-10-24 18:28:34 +0000893bool SkSpecularLightingImageFilter::asNewCustomStage(GrEffect** stage,
tomhudson@google.comd0c1a062012-07-12 17:23:52 +0000894 GrTexture* texture) const {
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000895#if SK_SUPPORT_GPU
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000896 if (stage) {
897 SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255));
tomhudson@google.com300f5622012-07-20 14:15:22 +0000898 *stage = SkNEW_ARGS(GrSpecularLightingEffect, (texture, light(), scale, ks(), shininess()));
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000899 }
900 return true;
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000901#else
902 SkDEBUGFAIL("Should not call in GPU-less build");
903 return false;
904#endif
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000905}
906
907///////////////////////////////////////////////////////////////////////////////
908
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000909#if SK_SUPPORT_GPU
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000910
911namespace {
912SkPoint3 random_point3(SkRandom* random) {
913 return SkPoint3(SkScalarToFloat(random->nextSScalar1()),
914 SkScalarToFloat(random->nextSScalar1()),
915 SkScalarToFloat(random->nextSScalar1()));
916}
917
918SkLight* create_random_light(SkRandom* random) {
919 int type = random->nextULessThan(3);
920 switch (type) {
921 case 0: {
922 return SkNEW_ARGS(SkDistantLight, (random_point3(random), random->nextU()));
923 }
924 case 1: {
925 return SkNEW_ARGS(SkPointLight, (random_point3(random), random->nextU()));
926 }
927 case 2: {
928 return SkNEW_ARGS(SkSpotLight, (random_point3(random),
929 random_point3(random),
930 random->nextUScalar1(),
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000931 random->nextUScalar1(),
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000932 random->nextU()));
933 }
934 default:
935 GrCrash();
936 return NULL;
937 }
938}
939
940}
941
bsalomon@google.com374e7592012-10-23 17:30:45 +0000942class GrGLLightingEffect : public GrGLLegacyProgramStage {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000943public:
944 GrGLLightingEffect(const GrProgramStageFactory& factory,
bsalomon@google.coma469c282012-10-24 18:28:34 +0000945 const GrEffect& stage);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000946 virtual ~GrGLLightingEffect();
947
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000948 virtual void setupVariables(GrGLShaderBuilder* builder) SK_OVERRIDE;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000949 virtual void emitVS(GrGLShaderBuilder* builder,
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000950 const char* vertexCoords) SK_OVERRIDE;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000951 virtual void emitFS(GrGLShaderBuilder* builder,
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000952 const char* outputColor,
953 const char* inputColor,
bsalomon@google.comf06df1b2012-09-06 20:22:31 +0000954 const TextureSamplerArray&) SK_OVERRIDE;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000955
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000956 virtual void emitLightFunc(GrGLShaderBuilder*, SkString* funcName) = 0;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000957
bsalomon@google.coma469c282012-10-24 18:28:34 +0000958 static inline StageKey GenKey(const GrEffect& s, const GrGLCaps& caps);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000959
bsalomon@google.coma469c282012-10-24 18:28:34 +0000960 virtual void setData(const GrGLUniformManager&, const GrEffect&) SK_OVERRIDE;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000961
962private:
bsalomon@google.com374e7592012-10-23 17:30:45 +0000963 typedef GrGLLegacyProgramStage INHERITED;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000964
bsalomon@google.com032b2212012-07-16 13:36:18 +0000965 UniformHandle fImageIncrementUni;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000966 UniformHandle fSurfaceScaleUni;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000967 GrGLLight* fLight;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000968};
969
970///////////////////////////////////////////////////////////////////////////////
971
972class GrGLDiffuseLightingEffect : public GrGLLightingEffect {
973public:
974 GrGLDiffuseLightingEffect(const GrProgramStageFactory& factory,
bsalomon@google.coma469c282012-10-24 18:28:34 +0000975 const GrEffect& stage);
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000976 virtual void setupVariables(GrGLShaderBuilder* builder) SK_OVERRIDE;
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000977 virtual void emitLightFunc(GrGLShaderBuilder*, SkString* funcName) SK_OVERRIDE;
bsalomon@google.coma469c282012-10-24 18:28:34 +0000978 virtual void setData(const GrGLUniformManager&, const GrEffect&) SK_OVERRIDE;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000979
980private:
981 typedef GrGLLightingEffect INHERITED;
982
bsalomon@google.com032b2212012-07-16 13:36:18 +0000983 UniformHandle fKDUni;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000984};
985
986///////////////////////////////////////////////////////////////////////////////
987
988class GrGLSpecularLightingEffect : public GrGLLightingEffect {
989public:
990 GrGLSpecularLightingEffect(const GrProgramStageFactory& factory,
bsalomon@google.coma469c282012-10-24 18:28:34 +0000991 const GrEffect& stage);
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000992 virtual void setupVariables(GrGLShaderBuilder* builder) SK_OVERRIDE;
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000993 virtual void emitLightFunc(GrGLShaderBuilder*, SkString* funcName) SK_OVERRIDE;
bsalomon@google.coma469c282012-10-24 18:28:34 +0000994 virtual void setData(const GrGLUniformManager&, const GrEffect&) SK_OVERRIDE;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000995
996private:
997 typedef GrGLLightingEffect INHERITED;
998
bsalomon@google.com032b2212012-07-16 13:36:18 +0000999 UniformHandle fKSUni;
bsalomon@google.com032b2212012-07-16 13:36:18 +00001000 UniformHandle fShininessUni;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001001};
1002
1003///////////////////////////////////////////////////////////////////////////////
1004
tomhudson@google.comd0c1a062012-07-12 17:23:52 +00001005GrLightingEffect::GrLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale)
1006 : GrSingleTextureEffect(texture)
1007 , fLight(light)
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001008 , fSurfaceScale(surfaceScale) {
1009 fLight->ref();
1010}
1011
1012GrLightingEffect::~GrLightingEffect() {
1013 fLight->unref();
1014}
1015
bsalomon@google.coma469c282012-10-24 18:28:34 +00001016bool GrLightingEffect::isEqual(const GrEffect& sBase) const {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001017 const GrLightingEffect& s =
1018 static_cast<const GrLightingEffect&>(sBase);
tomhudson@google.comd0c1a062012-07-12 17:23:52 +00001019 return INHERITED::isEqual(sBase) &&
1020 fLight->isEqual(*s.fLight) &&
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001021 fSurfaceScale == s.fSurfaceScale;
1022}
1023
1024///////////////////////////////////////////////////////////////////////////////
1025
tomhudson@google.comd0c1a062012-07-12 17:23:52 +00001026GrDiffuseLightingEffect::GrDiffuseLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale, SkScalar kd)
1027 : INHERITED(texture, light, surfaceScale), fKD(kd) {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001028}
1029
1030const GrProgramStageFactory& GrDiffuseLightingEffect::getFactory() const {
1031 return GrTProgramStageFactory<GrDiffuseLightingEffect>::getInstance();
1032}
1033
bsalomon@google.coma469c282012-10-24 18:28:34 +00001034bool GrDiffuseLightingEffect::isEqual(const GrEffect& sBase) const {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001035 const GrDiffuseLightingEffect& s =
1036 static_cast<const GrDiffuseLightingEffect&>(sBase);
1037 return INHERITED::isEqual(sBase) &&
1038 this->kd() == s.kd();
1039}
1040
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001041GR_DEFINE_CUSTOM_STAGE_TEST(GrDiffuseLightingEffect);
1042
bsalomon@google.coma469c282012-10-24 18:28:34 +00001043GrEffect* GrDiffuseLightingEffect::TestCreate(SkRandom* random,
1044 GrContext* context,
1045 GrTexture* textures[]) {
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001046 SkScalar surfaceScale = random->nextSScalar1();
1047 SkScalar kd = random->nextUScalar1();
1048 SkAutoTUnref<SkLight> light(create_random_light(random));
bsalomon@google.com6f261be2012-10-24 19:07:10 +00001049 return SkNEW_ARGS(GrDiffuseLightingEffect, (textures[GrEffectUnitTest::kAlphaTextureIdx],
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001050 light, surfaceScale, kd));
1051}
1052
1053
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001054///////////////////////////////////////////////////////////////////////////////
1055
1056GrGLLightingEffect::GrGLLightingEffect(const GrProgramStageFactory& factory,
bsalomon@google.coma469c282012-10-24 18:28:34 +00001057 const GrEffect& stage)
bsalomon@google.com374e7592012-10-23 17:30:45 +00001058 : INHERITED(factory)
bsalomon@google.com032b2212012-07-16 13:36:18 +00001059 , fImageIncrementUni(kInvalidUniformHandle)
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001060 , fSurfaceScaleUni(kInvalidUniformHandle) {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001061 const GrLightingEffect& m = static_cast<const GrLightingEffect&>(stage);
1062 fLight = m.light()->createGLLight();
1063}
1064
1065GrGLLightingEffect::~GrGLLightingEffect() {
1066 delete fLight;
1067}
1068
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001069void GrGLLightingEffect::setupVariables(GrGLShaderBuilder* builder) {
bsalomon@google.com032b2212012-07-16 13:36:18 +00001070 fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
1071 kVec2f_GrSLType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001072 "ImageIncrement");
bsalomon@google.com032b2212012-07-16 13:36:18 +00001073 fSurfaceScaleUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
1074 kFloat_GrSLType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001075 "SurfaceScale");
1076 fLight->setupVariables(builder);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001077}
1078
bsalomon@google.com032b2212012-07-16 13:36:18 +00001079void GrGLLightingEffect::emitVS(GrGLShaderBuilder* builder,
1080 const char* vertexCoords) {
1081 fLight->emitVS(&builder->fVSCode);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001082}
1083
bsalomon@google.com032b2212012-07-16 13:36:18 +00001084void GrGLLightingEffect::emitFS(GrGLShaderBuilder* builder,
1085 const char* outputColor,
1086 const char* inputColor,
bsalomon@google.comf06df1b2012-09-06 20:22:31 +00001087 const TextureSamplerArray& samplers) {
bsalomon@google.com032b2212012-07-16 13:36:18 +00001088 SkString* code = &builder->fFSCode;
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001089 fLight->emitFuncs(builder);
1090 SkString lightFunc;
1091 this->emitLightFunc(builder, &lightFunc);
1092 static const GrGLShaderVar gSobelArgs[] = {
1093 GrGLShaderVar("a", kFloat_GrSLType),
1094 GrGLShaderVar("b", kFloat_GrSLType),
1095 GrGLShaderVar("c", kFloat_GrSLType),
1096 GrGLShaderVar("d", kFloat_GrSLType),
1097 GrGLShaderVar("e", kFloat_GrSLType),
1098 GrGLShaderVar("f", kFloat_GrSLType),
1099 GrGLShaderVar("scale", kFloat_GrSLType),
1100 };
1101 SkString sobelFuncName;
1102 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1103 kFloat_GrSLType,
1104 "sobel",
1105 SK_ARRAY_COUNT(gSobelArgs),
1106 gSobelArgs,
1107 "\treturn (-a + b - 2.0 * c + 2.0 * d -e + f) * scale;\n",
1108 &sobelFuncName);
1109 static const GrGLShaderVar gPointToNormalArgs[] = {
1110 GrGLShaderVar("x", kFloat_GrSLType),
1111 GrGLShaderVar("y", kFloat_GrSLType),
1112 GrGLShaderVar("scale", kFloat_GrSLType),
1113 };
1114 SkString pointToNormalName;
1115 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1116 kVec3f_GrSLType,
1117 "pointToNormal",
1118 SK_ARRAY_COUNT(gPointToNormalArgs),
1119 gPointToNormalArgs,
bsalomon@google.com706f6682012-10-23 14:53:55 +00001120 "\treturn normalize(vec3(-x * scale, y * scale, 1));\n",
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001121 &pointToNormalName);
1122
1123 static const GrGLShaderVar gInteriorNormalArgs[] = {
1124 GrGLShaderVar("m", kFloat_GrSLType, 9),
1125 GrGLShaderVar("surfaceScale", kFloat_GrSLType),
1126 };
1127 SkString interiorNormalBody;
1128 interiorNormalBody.appendf("\treturn %s(%s(m[0], m[2], m[3], m[5], m[6], m[8], 0.25),\n"
1129 "\t %s(m[0], m[6], m[1], m[7], m[2], m[8], 0.25),\n"
1130 "\t surfaceScale);\n",
1131 pointToNormalName.c_str(),
1132 sobelFuncName.c_str(),
1133 sobelFuncName.c_str());
1134 SkString interiorNormalName;
1135 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1136 kVec3f_GrSLType,
1137 "interiorNormal",
1138 SK_ARRAY_COUNT(gInteriorNormalArgs),
1139 gInteriorNormalArgs,
1140 interiorNormalBody.c_str(),
1141 &interiorNormalName);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001142
bsalomon@google.com34bcb9f2012-08-28 18:20:18 +00001143 code->appendf("\t\tvec2 coord = %s;\n", builder->defaultTexCoordsName());
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001144 code->appendf("\t\tfloat m[9];\n");
bsalomon@google.com032b2212012-07-16 13:36:18 +00001145
1146 const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
1147 const char* surfScale = builder->getUniformCStr(fSurfaceScaleUni);
1148
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001149 int index = 0;
1150 for (int dy = -1; dy <= 1; dy++) {
1151 for (int dx = -1; dx <= 1; dx++) {
1152 SkString texCoords;
bsalomon@google.com032b2212012-07-16 13:36:18 +00001153 texCoords.appendf("coord + vec2(%d, %d) * %s", dx, dy, imgInc);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001154 code->appendf("\t\tm[%d] = ", index++);
bsalomon@google.comf06df1b2012-09-06 20:22:31 +00001155 builder->appendTextureLookup(code, samplers[0], texCoords.c_str());
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001156 code->appendf(".a;\n");
1157 }
1158 }
1159 code->appendf("\t\tvec3 surfaceToLight = ");
1160 SkString arg;
bsalomon@google.com032b2212012-07-16 13:36:18 +00001161 arg.appendf("%s * m[4]", surfScale);
1162 fLight->emitSurfaceToLight(builder, code, arg.c_str());
bsalomon@google.com868a8e72012-08-30 19:11:34 +00001163 code->append(";\n");
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001164 code->appendf("\t\t%s = %s(%s(m, %s), surfaceToLight, ",
1165 outputColor, lightFunc.c_str(), interiorNormalName.c_str(), surfScale);
1166 fLight->emitLightColor(builder, "surfaceToLight");
bsalomon@google.com868a8e72012-08-30 19:11:34 +00001167 code->append(");\n");
1168 GrGLSLMulVarBy4f(code, 2, outputColor, inputColor);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001169}
1170
bsalomon@google.coma469c282012-10-24 18:28:34 +00001171GrGLProgramStage::StageKey GrGLLightingEffect::GenKey(const GrEffect& s,
twiz@google.coma5e65ec2012-08-02 15:15:16 +00001172 const GrGLCaps& caps) {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001173 return static_cast<const GrLightingEffect&>(s).light()->type();
1174}
1175
bsalomon@google.coma469c282012-10-24 18:28:34 +00001176void GrGLLightingEffect::setData(const GrGLUniformManager& uman, const GrEffect& data) {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001177 const GrLightingEffect& effect =
1178 static_cast<const GrLightingEffect&>(data);
senorblanco@chromium.orgf4770d72012-07-13 18:25:06 +00001179 GrGLTexture* texture = static_cast<GrGLTexture*>(data.texture(0));
1180 float ySign = texture->orientation() == GrGLTexture::kTopDown_Orientation ? -1.0f : 1.0f;
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001181 uman.set2f(fImageIncrementUni, 1.0f / texture->width(), ySign / texture->height());
1182 uman.set1f(fSurfaceScaleUni, effect.surfaceScale());
bsalomon@google.com706f6682012-10-23 14:53:55 +00001183 fLight->setData(uman, effect.light());
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001184}
1185
1186///////////////////////////////////////////////////////////////////////////////
1187
1188///////////////////////////////////////////////////////////////////////////////
1189
1190GrGLDiffuseLightingEffect::GrGLDiffuseLightingEffect(const GrProgramStageFactory& factory,
bsalomon@google.coma469c282012-10-24 18:28:34 +00001191 const GrEffect& stage)
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001192 : INHERITED(factory, stage)
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001193 , fKDUni(kInvalidUniformHandle) {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001194}
1195
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001196void GrGLDiffuseLightingEffect::setupVariables(GrGLShaderBuilder* builder) {
1197 INHERITED::setupVariables(builder);
1198 fKDUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, kFloat_GrSLType, "KD");
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001199}
1200
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001201void GrGLDiffuseLightingEffect::emitLightFunc(GrGLShaderBuilder* builder, SkString* funcName) {
bsalomon@google.com032b2212012-07-16 13:36:18 +00001202 const char* kd = builder->getUniformCStr(fKDUni);
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001203 static const GrGLShaderVar gLightArgs[] = {
1204 GrGLShaderVar("normal", kVec3f_GrSLType),
1205 GrGLShaderVar("surfaceToLight", kVec3f_GrSLType),
1206 GrGLShaderVar("lightColor", kVec3f_GrSLType)
1207 };
1208 SkString lightBody;
1209 lightBody.appendf("\tfloat colorScale = %s * dot(normal, surfaceToLight);\n", kd);
1210 lightBody.appendf("\treturn vec4(lightColor * clamp(colorScale, 0.0, 1.0), 1.0);\n");
1211 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1212 kVec4f_GrSLType,
1213 "light",
1214 SK_ARRAY_COUNT(gLightArgs),
1215 gLightArgs,
1216 lightBody.c_str(),
1217 funcName);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001218}
1219
bsalomon@google.coma469c282012-10-24 18:28:34 +00001220void GrGLDiffuseLightingEffect::setData(const GrGLUniformManager& uman, const GrEffect& data) {
bsalomon@google.com706f6682012-10-23 14:53:55 +00001221 INHERITED::setData(uman, data);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001222 const GrDiffuseLightingEffect& effect =
1223 static_cast<const GrDiffuseLightingEffect&>(data);
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001224 uman.set1f(fKDUni, effect.kd());
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001225}
1226
1227///////////////////////////////////////////////////////////////////////////////
1228
tomhudson@google.comd0c1a062012-07-12 17:23:52 +00001229GrSpecularLightingEffect::GrSpecularLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess)
1230 : INHERITED(texture, light, surfaceScale),
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001231 fKS(ks),
1232 fShininess(shininess) {
1233}
1234
1235const GrProgramStageFactory& GrSpecularLightingEffect::getFactory() const {
1236 return GrTProgramStageFactory<GrSpecularLightingEffect>::getInstance();
1237}
1238
bsalomon@google.coma469c282012-10-24 18:28:34 +00001239bool GrSpecularLightingEffect::isEqual(const GrEffect& sBase) const {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001240 const GrSpecularLightingEffect& s =
1241 static_cast<const GrSpecularLightingEffect&>(sBase);
1242 return INHERITED::isEqual(sBase) &&
1243 this->ks() == s.ks() &&
1244 this->shininess() == s.shininess();
1245}
1246
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001247GR_DEFINE_CUSTOM_STAGE_TEST(GrSpecularLightingEffect);
1248
bsalomon@google.coma469c282012-10-24 18:28:34 +00001249GrEffect* GrSpecularLightingEffect::TestCreate(SkRandom* random,
1250 GrContext* context,
1251 GrTexture* textures[]) {
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001252 SkScalar surfaceScale = random->nextSScalar1();
1253 SkScalar ks = random->nextUScalar1();
1254 SkScalar shininess = random->nextUScalar1();
1255 SkAutoTUnref<SkLight> light(create_random_light(random));
bsalomon@google.com6f261be2012-10-24 19:07:10 +00001256 return SkNEW_ARGS(GrSpecularLightingEffect, (textures[GrEffectUnitTest::kAlphaTextureIdx],
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001257 light, surfaceScale, ks, shininess));
1258}
1259
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001260///////////////////////////////////////////////////////////////////////////////
1261
1262GrGLSpecularLightingEffect::GrGLSpecularLightingEffect(const GrProgramStageFactory& factory,
bsalomon@google.coma469c282012-10-24 18:28:34 +00001263 const GrEffect& stage)
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001264 : GrGLLightingEffect(factory, stage)
bsalomon@google.com032b2212012-07-16 13:36:18 +00001265 , fKSUni(kInvalidUniformHandle)
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001266 , fShininessUni(kInvalidUniformHandle) {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001267}
1268
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001269void GrGLSpecularLightingEffect::setupVariables(GrGLShaderBuilder* builder) {
1270 INHERITED::setupVariables(builder);
bsalomon@google.com032b2212012-07-16 13:36:18 +00001271 fKSUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001272 kFloat_GrSLType, "KS");
bsalomon@google.com032b2212012-07-16 13:36:18 +00001273 fShininessUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001274 kFloat_GrSLType, "Shininess");
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001275}
1276
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001277void GrGLSpecularLightingEffect::emitLightFunc(GrGLShaderBuilder* builder, SkString* funcName) {
bsalomon@google.com032b2212012-07-16 13:36:18 +00001278 const char* ks = builder->getUniformCStr(fKSUni);
1279 const char* shininess = builder->getUniformCStr(fShininessUni);
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001280
1281 static const GrGLShaderVar gLightArgs[] = {
1282 GrGLShaderVar("normal", kVec3f_GrSLType),
1283 GrGLShaderVar("surfaceToLight", kVec3f_GrSLType),
1284 GrGLShaderVar("lightColor", kVec3f_GrSLType)
1285 };
1286 SkString lightBody;
1287 lightBody.appendf("\tvec3 halfDir = vec3(normalize(surfaceToLight + vec3(0, 0, 1)));\n");
1288 lightBody.appendf("\tfloat colorScale = %s * pow(dot(normal, halfDir), %s);\n", ks, shininess);
1289 lightBody.appendf("\treturn vec4(lightColor * clamp(colorScale, 0.0, 1.0), 1.0);\n");
1290 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1291 kVec4f_GrSLType,
1292 "light",
1293 SK_ARRAY_COUNT(gLightArgs),
1294 gLightArgs,
1295 lightBody.c_str(),
1296 funcName);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001297}
1298
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001299void GrGLSpecularLightingEffect::setData(const GrGLUniformManager& uman,
bsalomon@google.coma469c282012-10-24 18:28:34 +00001300 const GrEffect& data) {
bsalomon@google.com706f6682012-10-23 14:53:55 +00001301 INHERITED::setData(uman, data);
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001302 const GrSpecularLightingEffect& effect = static_cast<const GrSpecularLightingEffect&>(data);
1303 uman.set1f(fKSUni, effect.ks());
1304 uman.set1f(fShininessUni, effect.shininess());
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001305}
1306
1307///////////////////////////////////////////////////////////////////////////////
1308
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001309void GrGLLight::emitLightColor(GrGLShaderBuilder* builder,
bsalomon@google.com032b2212012-07-16 13:36:18 +00001310 const char *surfaceToLight) const {
1311 const char* color = builder->getUniformCStr(fColorUni);
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001312 builder->fFSCode.append(color);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001313}
1314
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001315void GrGLLight::setupVariables(GrGLShaderBuilder* builder) {
bsalomon@google.com032b2212012-07-16 13:36:18 +00001316 fColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001317 kVec3f_GrSLType, "LightColor");
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001318}
1319
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001320void GrGLLight::setData(const GrGLUniformManager& uman,
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001321 const SkLight* light) const {
1322 setUniformPoint3(uman, fColorUni, light->color() * SkScalarInvert(SkIntToScalar(255)));
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001323}
1324
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001325///////////////////////////////////////////////////////////////////////////////
1326
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001327void GrGLDistantLight::setupVariables(GrGLShaderBuilder* builder) {
1328 INHERITED::setupVariables(builder);
bsalomon@google.com032b2212012-07-16 13:36:18 +00001329 fDirectionUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, kVec3f_GrSLType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001330 "LightDirection");
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001331}
1332
bsalomon@google.com706f6682012-10-23 14:53:55 +00001333void GrGLDistantLight::setData(const GrGLUniformManager& uman, const SkLight* light) const {
1334 INHERITED::setData(uman, light);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001335 SkASSERT(light->type() == SkLight::kDistant_LightType);
1336 const SkDistantLight* distantLight = static_cast<const SkDistantLight*>(light);
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001337 setUniformNormal3(uman, fDirectionUni, distantLight->direction());
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001338}
1339
bsalomon@google.com706f6682012-10-23 14:53:55 +00001340void GrGLDistantLight::emitSurfaceToLight(GrGLShaderBuilder* builder,
bsalomon@google.com032b2212012-07-16 13:36:18 +00001341 SkString* out,
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001342 const char* z) const {
bsalomon@google.com032b2212012-07-16 13:36:18 +00001343 const char* dir = builder->getUniformCStr(fDirectionUni);
1344 out->append(dir);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001345}
1346
1347///////////////////////////////////////////////////////////////////////////////
1348
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001349void GrGLPointLight::setupVariables(GrGLShaderBuilder* builder) {
1350 INHERITED::setupVariables(builder);
bsalomon@google.com032b2212012-07-16 13:36:18 +00001351 fLocationUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, kVec3f_GrSLType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001352 "LightLocation");
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001353}
1354
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001355void GrGLPointLight::setData(const GrGLUniformManager& uman,
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001356 const SkLight* light) const {
bsalomon@google.com706f6682012-10-23 14:53:55 +00001357 INHERITED::setData(uman, light);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001358 SkASSERT(light->type() == SkLight::kPoint_LightType);
1359 const SkPointLight* pointLight = static_cast<const SkPointLight*>(light);
bsalomon@google.com706f6682012-10-23 14:53:55 +00001360 setUniformPoint3(uman, fLocationUni, pointLight->location());
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001361}
1362
bsalomon@google.com032b2212012-07-16 13:36:18 +00001363void GrGLPointLight::emitVS(SkString* out) const {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001364}
1365
bsalomon@google.com706f6682012-10-23 14:53:55 +00001366void GrGLPointLight::emitSurfaceToLight(GrGLShaderBuilder* builder,
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001367 SkString* out,
1368 const char* z) const {
bsalomon@google.com032b2212012-07-16 13:36:18 +00001369 const char* loc = builder->getUniformCStr(fLocationUni);
bsalomon@google.com706f6682012-10-23 14:53:55 +00001370 out->appendf("normalize(%s - vec3(%s.xy, %s))", loc, builder->fragmentPosition(), z);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001371}
1372
1373///////////////////////////////////////////////////////////////////////////////
1374
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001375void GrGLSpotLight::setupVariables(GrGLShaderBuilder* builder) {
1376 INHERITED::setupVariables(builder);
bsalomon@google.com032b2212012-07-16 13:36:18 +00001377 fLocationUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001378 kVec3f_GrSLType, "LightLocation");
bsalomon@google.com032b2212012-07-16 13:36:18 +00001379 fExponentUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001380 kFloat_GrSLType, "Exponent");
bsalomon@google.com032b2212012-07-16 13:36:18 +00001381 fCosInnerConeAngleUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001382 kFloat_GrSLType, "CosInnerConeAngle");
bsalomon@google.com032b2212012-07-16 13:36:18 +00001383 fCosOuterConeAngleUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001384 kFloat_GrSLType, "CosOuterConeAngle");
bsalomon@google.com032b2212012-07-16 13:36:18 +00001385 fConeScaleUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001386 kFloat_GrSLType, "ConeScale");
bsalomon@google.com032b2212012-07-16 13:36:18 +00001387 fSUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001388 kVec3f_GrSLType, "S");
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001389}
1390
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001391void GrGLSpotLight::setData(const GrGLUniformManager& uman,
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001392 const SkLight* light) const {
bsalomon@google.com706f6682012-10-23 14:53:55 +00001393 INHERITED::setData(uman, light);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001394 SkASSERT(light->type() == SkLight::kSpot_LightType);
1395 const SkSpotLight* spotLight = static_cast<const SkSpotLight *>(light);
bsalomon@google.com706f6682012-10-23 14:53:55 +00001396 setUniformPoint3(uman, fLocationUni, spotLight->location());
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001397 uman.set1f(fExponentUni, spotLight->specularExponent());
1398 uman.set1f(fCosInnerConeAngleUni, spotLight->cosInnerConeAngle());
1399 uman.set1f(fCosOuterConeAngleUni, spotLight->cosOuterConeAngle());
1400 uman.set1f(fConeScaleUni, spotLight->coneScale());
1401 setUniformNormal3(uman, fSUni, spotLight->s());
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001402}
1403
bsalomon@google.com032b2212012-07-16 13:36:18 +00001404void GrGLSpotLight::emitVS(SkString* out) const {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001405}
1406
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001407void GrGLSpotLight::emitFuncs(GrGLShaderBuilder* builder) {
bsalomon@google.com032b2212012-07-16 13:36:18 +00001408 const char* exponent = builder->getUniformCStr(fExponentUni);
1409 const char* cosInner = builder->getUniformCStr(fCosInnerConeAngleUni);
1410 const char* cosOuter = builder->getUniformCStr(fCosOuterConeAngleUni);
1411 const char* coneScale = builder->getUniformCStr(fConeScaleUni);
1412 const char* s = builder->getUniformCStr(fSUni);
1413 const char* color = builder->getUniformCStr(fColorUni);
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001414 static const GrGLShaderVar gLightColorArgs[] = {
1415 GrGLShaderVar("surfaceToLight", kVec3f_GrSLType)
1416 };
1417 SkString lightColorBody;
1418 lightColorBody.appendf("\tfloat cosAngle = -dot(surfaceToLight, %s);\n", s);
1419 lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosOuter);
1420 lightColorBody.appendf("\t\treturn vec3(0);\n");
1421 lightColorBody.appendf("\t}\n");
1422 lightColorBody.appendf("\tfloat scale = pow(cosAngle, %s);\n", exponent);
1423 lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosInner);
1424 lightColorBody.appendf("\t\treturn %s * scale * (cosAngle - %s) * %s;\n",
1425 color, cosOuter, coneScale);
1426 lightColorBody.appendf("\t}\n");
1427 lightColorBody.appendf("\treturn %s;\n", color);
1428 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1429 kVec3f_GrSLType,
1430 "lightColor",
1431 SK_ARRAY_COUNT(gLightColorArgs),
1432 gLightColorArgs,
1433 lightColorBody.c_str(),
1434 &fLightColorFunc);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001435}
1436
bsalomon@google.com706f6682012-10-23 14:53:55 +00001437void GrGLSpotLight::emitSurfaceToLight(GrGLShaderBuilder* builder,
bsalomon@google.com032b2212012-07-16 13:36:18 +00001438 SkString* out,
1439 const char* z) const {
1440 const char* location= builder->getUniformCStr(fLocationUni);
bsalomon@google.com706f6682012-10-23 14:53:55 +00001441 out->appendf("normalize(%s - vec3(%s.xy, %s))", location, builder->fragmentPosition(), z);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001442}
1443
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001444void GrGLSpotLight::emitLightColor(GrGLShaderBuilder* builder,
1445 const char *surfaceToLight) const {
1446 builder->fFSCode.appendf("%s(%s)", fLightColorFunc.c_str(), surfaceToLight);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001447}
1448
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +00001449#endif
1450
djsollen@google.com08337772012-06-26 14:33:13 +00001451SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingImageFilter)
1452 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDiffuseLightingImageFilter)
1453 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSpecularLightingImageFilter)
1454 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDistantLight)
1455 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPointLight)
1456 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSpotLight)
1457SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END