• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 Google Inc.
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 "SkCanvas.h"
9 #include "SkReadBuffer.h"
10 #include "SkShadowShader.h"
11 
12 ////////////////////////////////////////////////////////////////////////////
13 #ifdef SK_EXPERIMENTAL_SHADOWING
14 
15 
16 /** \class SkShadowShaderImpl
17     This subclass of shader applies shadowing
18 */
19 class SkShadowShaderImpl : public SkShader {
20 public:
21     /** Create a new shadowing shader that shadows
22         @param to do        to do
23     */
SkShadowShaderImpl(sk_sp<SkShader> povDepthShader,sk_sp<SkShader> diffuseShader,sk_sp<SkLights> lights,int diffuseWidth,int diffuseHeight,const SkShadowParams & params)24     SkShadowShaderImpl(sk_sp<SkShader> povDepthShader,
25                        sk_sp<SkShader> diffuseShader,
26                        sk_sp<SkLights> lights,
27                        int diffuseWidth, int diffuseHeight,
28                        const SkShadowParams& params)
29             : fPovDepthShader(std::move(povDepthShader))
30             , fDiffuseShader(std::move(diffuseShader))
31             , fLights(std::move(lights))
32             , fDiffuseWidth(diffuseWidth)
33             , fDiffuseHeight(diffuseHeight)
34             , fShadowParams(params) { }
35 
36     bool isOpaque() const override;
37 
38 #if SK_SUPPORT_GPU
39     sk_sp<GrFragmentProcessor> asFragmentProcessor(const AsFPArgs&) const override;
40 #endif
41 
42     class ShadowShaderContext : public SkShader::Context {
43     public:
44         // The context takes ownership of the states. It will call their destructors
45         // but will NOT free the memory.
46         ShadowShaderContext(const SkShadowShaderImpl&, const ContextRec&,
47                             SkShader::Context* povDepthContext,
48                             SkShader::Context* diffuseContext,
49                             void* heapAllocated);
50 
51         ~ShadowShaderContext() override;
52 
53         void shadeSpan(int x, int y, SkPMColor[], int count) override;
54 
getFlags() const55         uint32_t getFlags() const override { return fFlags; }
56 
57     private:
58         SkShader::Context*        fPovDepthContext;
59         SkShader::Context*        fDiffuseContext;
60         uint32_t                  fFlags;
61 
62         void* fHeapAllocated;
63 
64         int fNonAmbLightCnt;
65         SkPixmap* fShadowMapPixels;
66 
67 
68         typedef SkShader::Context INHERITED;
69     };
70 
71     SK_TO_STRING_OVERRIDE()
72     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkShadowShaderImpl)
73 
74 protected:
75     void flatten(SkWriteBuffer&) const override;
76     size_t onContextSize(const ContextRec&) const override;
77     Context* onCreateContext(const ContextRec&, void*) const override;
78 
79 private:
80     sk_sp<SkShader> fPovDepthShader;
81     sk_sp<SkShader> fDiffuseShader;
82     sk_sp<SkLights> fLights;
83 
84     int fDiffuseWidth;
85     int fDiffuseHeight;
86 
87     SkShadowParams fShadowParams;
88 
89     friend class SkShadowShader;
90 
91     typedef SkShader INHERITED;
92 };
93 
94 ////////////////////////////////////////////////////////////////////////////
95 
96 #if SK_SUPPORT_GPU
97 
98 #include "GrCoordTransform.h"
99 #include "GrFragmentProcessor.h"
100 #include "GrInvariantOutput.h"
101 #include "glsl/GrGLSLFragmentProcessor.h"
102 #include "glsl/GrGLSLFragmentShaderBuilder.h"
103 #include "SkGr.h"
104 #include "SkSpecialImage.h"
105 #include "SkImage_Base.h"
106 #include "GrContext.h"
107 
108 class ShadowFP : public GrFragmentProcessor {
109 public:
ShadowFP(sk_sp<GrFragmentProcessor> povDepth,sk_sp<GrFragmentProcessor> diffuse,sk_sp<SkLights> lights,int diffuseWidth,int diffuseHeight,const SkShadowParams & params,GrContext * context)110     ShadowFP(sk_sp<GrFragmentProcessor> povDepth,
111              sk_sp<GrFragmentProcessor> diffuse,
112              sk_sp<SkLights> lights,
113              int diffuseWidth, int diffuseHeight,
114              const SkShadowParams& params,
115              GrContext* context) {
116 
117         fAmbientColor = lights->ambientLightColor();
118 
119         fNumNonAmbLights = 0; // count of non-ambient lights
120         for (int i = 0; i < lights->numLights(); ++i) {
121             if (fNumNonAmbLights < SkShadowShader::kMaxNonAmbientLights) {
122                 fLightColor[fNumNonAmbLights] = lights->light(i).color();
123 
124                 if (SkLights::Light::kPoint_LightType == lights->light(i).type()) {
125                     fLightDirOrPos[fNumNonAmbLights] = lights->light(i).pos();
126                     fLightColor[fNumNonAmbLights].scale(lights->light(i).intensity());
127                 } else {
128                     fLightDirOrPos[fNumNonAmbLights] = lights->light(i).dir();
129                 }
130 
131                 fIsPointLight[fNumNonAmbLights] =
132                         SkLights::Light::kPoint_LightType == lights->light(i).type();
133 
134                 fIsRadialLight[fNumNonAmbLights] = lights->light(i).isRadial();
135 
136                 SkImage_Base* shadowMap = ((SkImage_Base*)lights->light(i).getShadowMap());
137 
138                 // gets deleted when the ShadowFP is destroyed, and frees the GrTexture*
139                 fTexture[fNumNonAmbLights] = sk_sp<GrTexture>(shadowMap->asTextureRef(context,
140                                                            GrSamplerParams::ClampNoFilter(),
141                                                            SkDestinationSurfaceColorMode::kLegacy,
142                                                            nullptr));
143                 fDepthMapSampler[fNumNonAmbLights].reset(fTexture[fNumNonAmbLights].get());
144                 this->addTextureSampler(&fDepthMapSampler[fNumNonAmbLights]);
145 
146                 fDepthMapHeight[fNumNonAmbLights] = shadowMap->height();
147                 fDepthMapWidth[fNumNonAmbLights] = shadowMap->width();
148 
149                 fNumNonAmbLights++;
150             }
151         }
152 
153         fWidth = diffuseWidth;
154         fHeight = diffuseHeight;
155 
156         fShadowParams = params;
157 
158         this->registerChildProcessor(std::move(povDepth));
159         this->registerChildProcessor(std::move(diffuse));
160         this->initClassID<ShadowFP>();
161     }
162 
163     class GLSLShadowFP : public GrGLSLFragmentProcessor {
164     public:
GLSLShadowFP()165         GLSLShadowFP() { }
166 
emitCode(EmitArgs & args)167         void emitCode(EmitArgs& args) override {
168             GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
169             GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
170             const ShadowFP& shadowFP = args.fFp.cast<ShadowFP>();
171 
172             SkASSERT(shadowFP.fNumNonAmbLights <= SkShadowShader::kMaxNonAmbientLights);
173 
174             // add uniforms
175             int32_t numLights = shadowFP.fNumNonAmbLights;
176             SkASSERT(numLights <= SkShadowShader::kMaxNonAmbientLights);
177 
178             int blurAlgorithm = shadowFP.fShadowParams.fType;
179 
180             const char* lightDirOrPosUniName[SkShadowShader::kMaxNonAmbientLights] = {nullptr};
181             const char* lightColorUniName[SkShadowShader::kMaxNonAmbientLights] = {nullptr};
182             const char* ambientColorUniName = nullptr;
183 
184             const char* depthMapWidthUniName[SkShadowShader::kMaxNonAmbientLights] = {nullptr};
185             const char* depthMapHeightUniName[SkShadowShader::kMaxNonAmbientLights] = {nullptr};
186             const char* widthUniName = nullptr; // dimensions of povDepth
187             const char* heightUniName = nullptr;
188 
189             const char* shBiasUniName = nullptr;
190             const char* minVarianceUniName = nullptr;
191 
192             // setting uniforms
193             for (int i = 0; i < shadowFP.fNumNonAmbLights; i++) {
194                 SkString lightDirOrPosUniNameStr("lightDir");
195                 lightDirOrPosUniNameStr.appendf("%d", i);
196                 SkString lightColorUniNameStr("lightColor");
197                 lightColorUniNameStr.appendf("%d", i);
198                 SkString lightIntensityUniNameStr("lightIntensity");
199                 lightIntensityUniNameStr.appendf("%d", i);
200 
201                 SkString depthMapWidthUniNameStr("dmapWidth");
202                 depthMapWidthUniNameStr.appendf("%d", i);
203                 SkString depthMapHeightUniNameStr("dmapHeight");
204                 depthMapHeightUniNameStr.appendf("%d", i);
205 
206                 fLightDirOrPosUni[i] = uniformHandler->addUniform(kFragment_GrShaderFlag,
207                                                              kVec3f_GrSLType,
208                                                              kDefault_GrSLPrecision,
209                                                              lightDirOrPosUniNameStr.c_str(),
210                                                              &lightDirOrPosUniName[i]);
211                 fLightColorUni[i] = uniformHandler->addUniform(kFragment_GrShaderFlag,
212                                                                kVec3f_GrSLType,
213                                                                kDefault_GrSLPrecision,
214                                                                lightColorUniNameStr.c_str(),
215                                                                &lightColorUniName[i]);
216 
217                 fDepthMapWidthUni[i]  = uniformHandler->addUniform(kFragment_GrShaderFlag,
218                                                    kInt_GrSLType,
219                                                    kDefault_GrSLPrecision,
220                                                    depthMapWidthUniNameStr.c_str(),
221                                                    &depthMapWidthUniName[i]);
222                 fDepthMapHeightUni[i] = uniformHandler->addUniform(kFragment_GrShaderFlag,
223                                                    kInt_GrSLType,
224                                                    kDefault_GrSLPrecision,
225                                                    depthMapHeightUniNameStr.c_str(),
226                                                    &depthMapHeightUniName[i]);
227             }
228 
229             fBiasingConstantUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
230                                                              kFloat_GrSLType,
231                                                              kDefault_GrSLPrecision,
232                                                              "shadowBias", &shBiasUniName);
233             fMinVarianceUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
234                                                          kFloat_GrSLType,
235                                                          kDefault_GrSLPrecision,
236                                                          "minVariance", &minVarianceUniName);
237 
238             fWidthUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
239                                                    kInt_GrSLType,
240                                                    kDefault_GrSLPrecision,
241                                                    "width", &widthUniName);
242             fHeightUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
243                                                     kInt_GrSLType,
244                                                     kDefault_GrSLPrecision,
245                                                     "height", &heightUniName);
246 
247             fAmbientColorUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
248                                                           kVec3f_GrSLType, kDefault_GrSLPrecision,
249                                                           "AmbientColor", &ambientColorUniName);
250 
251             SkString povDepthSampler("_povDepth");
252             SkString povDepth("povDepth");
253             this->emitChild(0, nullptr, &povDepthSampler, args);
254             fragBuilder->codeAppendf("vec4 %s = %s;", povDepth.c_str(), povDepthSampler.c_str());
255 
256             SkString diffuseColorSampler("_inDiffuseColor");
257             SkString diffuseColor("inDiffuseColor");
258             this->emitChild(1, nullptr, &diffuseColorSampler, args);
259             fragBuilder->codeAppendf("vec4 %s = %s;", diffuseColor.c_str(),
260                                      diffuseColorSampler.c_str());
261 
262             SkString depthMaps[SkShadowShader::kMaxNonAmbientLights];
263 
264             fragBuilder->codeAppendf("vec4 resultDiffuseColor = %s;", diffuseColor.c_str());
265             fragBuilder->codeAppend ("vec3 totalLightColor = vec3(0);");
266 
267             // probability that a fragment is lit. For each light, we multiply this by the
268             // light's color to get its contribution to totalLightColor.
269             fragBuilder->codeAppend ("float lightProbability;");
270 
271             // coordinates of current fragment in world space
272             fragBuilder->codeAppend ("vec3 worldCor;");
273 
274             // Multiply by 255 to transform from sampler coordinates to world
275             // coordinates (since 1 channel is 0xFF)
276             // Note: vMatrixCoord_0_1_Stage0 is the texture sampler coordinates.
277             fragBuilder->codeAppendf("worldCor = vec3(vMatrixCoord_0_1_Stage0 * "
278                                                 "vec2(%s, %s), %s.b * 255);",
279                                      widthUniName, heightUniName, povDepth.c_str());
280 
281             // Applies the offset indexing that goes from our view space into the light's space.
282             for (int i = 0; i < shadowFP.fNumNonAmbLights; i++) {
283                 SkString povCoord("povCoord");
284                 povCoord.appendf("%d", i);
285 
286                 SkString offset("offset");
287                 offset.appendf("%d", i);
288                 fragBuilder->codeAppendf("vec2 %s;", offset.c_str());
289 
290                 if (shadowFP.fIsPointLight[i]) {
291                     fragBuilder->codeAppendf("vec3 fragToLight%d = %s - worldCor;",
292                                              i, lightDirOrPosUniName[i]);
293                     fragBuilder->codeAppendf("float dist%d = length(fragToLight%d);",
294                                              i, i);
295                     fragBuilder->codeAppendf("%s = vec2(-fragToLight%d) * povDepth.b;",
296                                              offset.c_str(), i);
297                     fragBuilder->codeAppendf("fragToLight%d = normalize(fragToLight%d);",
298                                              i, i);
299                 }
300 
301                 if (shadowFP.fIsRadialLight[i]) {
302                     fragBuilder->codeAppendf("vec2 %s = vec2(vMatrixCoord_0_1_Stage0.x, "
303                                                             "1 - vMatrixCoord_0_1_Stage0.y);\n",
304                                              povCoord.c_str());
305 
306                     fragBuilder->codeAppendf("%s = (%s) * 2.0 - 1.0 + (vec2(%s)/vec2(%s,%s) - 0.5)"
307                                                                       "* vec2(-2.0, 2.0);\n",
308                                              povCoord.c_str(), povCoord.c_str(),
309                                              lightDirOrPosUniName[i],
310                                              widthUniName, heightUniName);
311 
312                     fragBuilder->codeAppendf("float theta = atan(%s.y, %s.x);",
313                                              povCoord.c_str(), povCoord.c_str());
314                     fragBuilder->codeAppendf("float r = length(%s);", povCoord.c_str());
315 
316                     // map output of atan to [0, 1]
317                     fragBuilder->codeAppendf("%s.x = (theta + 3.1415) / (2.0 * 3.1415);",
318                                              povCoord.c_str());
319                     fragBuilder->codeAppendf("%s.y = 0.0;", povCoord.c_str());
320                 } else {
321                     // note that we flip the y-coord of the offset and then later add
322                     // a value just to the y-coord of povCoord. This is to account for
323                     // the shifted origins from switching from raster into GPU.
324                     if (shadowFP.fIsPointLight[i]) {
325                         // the 0.375s are precalculated transform values, given that the depth
326                         // maps for pt lights are 4x the size (linearly) as diffuse maps.
327                         // The vec2(0.375, -0.375) is used to transform us to
328                         // the center of the map.
329                         fragBuilder->codeAppendf("vec2 %s = ((vec2(%s, %s) *"
330                                                          "vMatrixCoord_0_1_Stage0 +"
331                                                          "vec2(0,%s - %s)"
332                                                          "+ %s) / (vec2(%s, %s))) +"
333                                                          "vec2(0.375, -0.375);",
334                                                  povCoord.c_str(),
335                                                  widthUniName, heightUniName,
336                                                  depthMapHeightUniName[i], heightUniName,
337                                                  offset.c_str(),
338                                                  depthMapWidthUniName[i],
339                                                  depthMapWidthUniName[i]);
340                     } else {
341                         fragBuilder->codeAppendf("%s = vec2(%s) * povDepth.b * "
342                                                       "vec2(255.0, -255.0);",
343                                                  offset.c_str(), lightDirOrPosUniName[i]);
344 
345                         fragBuilder->codeAppendf("vec2 %s = ((vec2(%s, %s) *"
346                                                          "vMatrixCoord_0_1_Stage0 +"
347                                                          "vec2(0,%s - %s)"
348                                                          "+ %s) / vec2(%s, %s));",
349                                                  povCoord.c_str(),
350                                                  widthUniName, heightUniName,
351                                                  depthMapHeightUniName[i], heightUniName,
352                                                  offset.c_str(),
353                                                  depthMapWidthUniName[i],
354                                                  depthMapWidthUniName[i]);
355                     }
356                 }
357 
358                 fragBuilder->appendTextureLookup(&depthMaps[i], args.fTexSamplers[i],
359                                                  povCoord.c_str(),
360                                                  kVec2f_GrSLType);
361             }
362 
363             // helper variables for calculating shadowing
364 
365             // variance of depth at this fragment in the context of surrounding area
366             // (area size and weighting dependent on blur size and type)
367             fragBuilder->codeAppendf("float variance;");
368 
369             // the difference in depth between the user POV and light POV.
370             fragBuilder->codeAppendf("float d;");
371 
372             // add up light contributions from all lights to totalLightColor
373             for (int i = 0; i < numLights; i++) {
374                 fragBuilder->codeAppendf("lightProbability = 1;");
375 
376                 if (shadowFP.fIsRadialLight[i]) {
377                     fragBuilder->codeAppend("totalLightColor = vec3(0);");
378 
379                     fragBuilder->codeAppend("vec2 tc = vec2(povCoord0.x, 0.0);");
380                     fragBuilder->codeAppend("float depth = texture(uTextureSampler0_Stage1,"
381                                                                   "povCoord0).b * 2.0;");
382 
383                     fragBuilder->codeAppendf("lightProbability = step(r, depth);");
384 
385                     // 2 is the maximum depth. If this is reached, probably we have
386                     // not intersected anything. So values after this should be unshadowed.
387                     fragBuilder->codeAppendf("if (%s.b != 0 || depth == 2) {"
388                                                      "lightProbability = 1.0; }",
389                                              povDepth.c_str());
390                 } else {
391                     // 1/512 == .00195... is less than half a pixel; imperceptible
392                     fragBuilder->codeAppendf("if (%s.b <= %s.b + .001953125) {",
393                                              povDepth.c_str(), depthMaps[i].c_str());
394                     if (blurAlgorithm == SkShadowParams::kVariance_ShadowType) {
395                         // We mess with depth and depth^2 in their given scales.
396                         // (i.e. between 0 and 1)
397                         fragBuilder->codeAppendf("vec2 moments%d = vec2(%s.b, %s.g);",
398                                                  i, depthMaps[i].c_str(), depthMaps[i].c_str());
399 
400                         // variance biasing lessens light bleeding
401                         fragBuilder->codeAppendf("variance = max(moments%d.y - "
402                                                          "(moments%d.x * moments%d.x),"
403                                                          "%s);", i, i, i,
404                                                  minVarianceUniName);
405 
406                         fragBuilder->codeAppendf("d = (%s.b) - moments%d.x;",
407                                                  povDepth.c_str(), i);
408                         fragBuilder->codeAppendf("lightProbability = "
409                                                          "(variance / (variance + d * d));");
410 
411                         SkString clamp("clamp");
412                         clamp.appendf("%d", i);
413 
414                         // choosing between light artifacts or correct shape shadows
415                         // linstep
416                         fragBuilder->codeAppendf("float %s = clamp((lightProbability - %s) /"
417                                                          "(1 - %s), 0, 1);",
418                                                  clamp.c_str(), shBiasUniName, shBiasUniName);
419 
420                         fragBuilder->codeAppendf("lightProbability = %s;", clamp.c_str());
421                     } else {
422                         fragBuilder->codeAppendf("if (%s.b >= %s.b) {",
423                                                  povDepth.c_str(), depthMaps[i].c_str());
424                         fragBuilder->codeAppendf("lightProbability = 1;");
425                         fragBuilder->codeAppendf("} else { lightProbability = 0; }");
426                     }
427 
428                     // VSM: The curved shadows near plane edges are artifacts from blurring
429                     // lightDir.z is equal to the lightDir dot the surface normal.
430                     fragBuilder->codeAppendf("}");
431                 }
432 
433                 if (shadowFP.isPointLight(i)) {
434                     fragBuilder->codeAppendf("totalLightColor += max(fragToLight%d.z, 0) * %s /"
435                                                      "(1 + dist%d) * lightProbability;",
436                                              i, lightColorUniName[i], i);
437                 } else {
438                     fragBuilder->codeAppendf("totalLightColor += %s.z * %s * lightProbability;",
439                                              lightDirOrPosUniName[i],
440                                              lightColorUniName[i]);
441                 }
442 
443                 fragBuilder->codeAppendf("totalLightColor += %s;", ambientColorUniName);
444                 fragBuilder->codeAppendf("%s = resultDiffuseColor * vec4(totalLightColor, 1);",
445                                          args.fOutputColor);
446             }
447 
448         }
449 
GenKey(const GrProcessor & proc,const GrShaderCaps &,GrProcessorKeyBuilder * b)450         static void GenKey(const GrProcessor& proc, const GrShaderCaps&,
451                            GrProcessorKeyBuilder* b) {
452             const ShadowFP& shadowFP = proc.cast<ShadowFP>();
453             b->add32(shadowFP.fNumNonAmbLights);
454             int isPLR = 0;
455             for (int i = 0; i < SkShadowShader::kMaxNonAmbientLights; i++) {
456                 isPLR = isPLR | ((shadowFP.fIsPointLight[i] ? 1 : 0) << i);
457                 isPLR = isPLR | ((shadowFP.fIsRadialLight[i] ? 1 : 0) << (i+4));
458             }
459             b->add32(isPLR);
460             b->add32(shadowFP.fShadowParams.fType);
461         }
462 
463     protected:
onSetData(const GrGLSLProgramDataManager & pdman,const GrProcessor & proc)464         void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& proc) override {
465             const ShadowFP &shadowFP = proc.cast<ShadowFP>();
466 
467             for (int i = 0; i < shadowFP.numLights(); i++) {
468                 const SkVector3& lightDirOrPos = shadowFP.lightDirOrPos(i);
469                 if (lightDirOrPos != fLightDirOrPos[i]) {
470                     pdman.set3fv(fLightDirOrPosUni[i], 1, &lightDirOrPos.fX);
471                     fLightDirOrPos[i] = lightDirOrPos;
472                 }
473 
474                 const SkColor3f& lightColor = shadowFP.lightColor(i);
475                 if (lightColor != fLightColor[i]) {
476                     pdman.set3fv(fLightColorUni[i], 1, &lightColor.fX);
477                     fLightColor[i] = lightColor;
478                 }
479 
480                 int depthMapWidth = shadowFP.depthMapWidth(i);
481                 if (depthMapWidth != fDepthMapWidth[i]) {
482                     pdman.set1i(fDepthMapWidthUni[i], depthMapWidth);
483                     fDepthMapWidth[i] = depthMapWidth;
484                 }
485                 int depthMapHeight = shadowFP.depthMapHeight(i);
486                 if (depthMapHeight != fDepthMapHeight[i]) {
487                     pdman.set1i(fDepthMapHeightUni[i], depthMapHeight);
488                     fDepthMapHeight[i] = depthMapHeight;
489                 }
490             }
491 
492             SkScalar biasingConstant = shadowFP.shadowParams().fBiasingConstant;
493             if (biasingConstant != fBiasingConstant) {
494                 pdman.set1f(fBiasingConstantUni, biasingConstant);
495                 fBiasingConstant = biasingConstant;
496             }
497 
498             SkScalar minVariance = shadowFP.shadowParams().fMinVariance;
499             if (minVariance != fMinVariance) {
500                 // transform variance from pixel-scale to normalized scale
501                 pdman.set1f(fMinVarianceUni, minVariance / 65536.0f);
502                 fMinVariance = minVariance / 65536.0f;
503             }
504 
505             int width = shadowFP.width();
506             if (width != fWidth) {
507                 pdman.set1i(fWidthUni, width);
508                 fWidth = width;
509             }
510             int height = shadowFP.height();
511             if (height != fHeight) {
512                 pdman.set1i(fHeightUni, height);
513                 fHeight = height;
514             }
515 
516             const SkColor3f& ambientColor = shadowFP.ambientColor();
517             if (ambientColor != fAmbientColor) {
518                 pdman.set3fv(fAmbientColorUni, 1, &ambientColor.fX);
519                 fAmbientColor = ambientColor;
520             }
521         }
522 
523     private:
524         SkVector3 fLightDirOrPos[SkShadowShader::kMaxNonAmbientLights];
525         GrGLSLProgramDataManager::UniformHandle
526                 fLightDirOrPosUni[SkShadowShader::kMaxNonAmbientLights];
527 
528         SkColor3f fLightColor[SkShadowShader::kMaxNonAmbientLights];
529         GrGLSLProgramDataManager::UniformHandle
530                 fLightColorUni[SkShadowShader::kMaxNonAmbientLights];
531 
532         int fDepthMapWidth[SkShadowShader::kMaxNonAmbientLights];
533         GrGLSLProgramDataManager::UniformHandle
534                 fDepthMapWidthUni[SkShadowShader::kMaxNonAmbientLights];
535 
536         int fDepthMapHeight[SkShadowShader::kMaxNonAmbientLights];
537         GrGLSLProgramDataManager::UniformHandle
538                 fDepthMapHeightUni[SkShadowShader::kMaxNonAmbientLights];
539 
540         int fWidth;
541         GrGLSLProgramDataManager::UniformHandle fWidthUni;
542         int fHeight;
543         GrGLSLProgramDataManager::UniformHandle fHeightUni;
544 
545         SkScalar fBiasingConstant;
546         GrGLSLProgramDataManager::UniformHandle fBiasingConstantUni;
547         SkScalar fMinVariance;
548         GrGLSLProgramDataManager::UniformHandle fMinVarianceUni;
549 
550         SkColor3f fAmbientColor;
551         GrGLSLProgramDataManager::UniformHandle fAmbientColorUni;
552     };
553 
onGetGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const554     void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
555         GLSLShadowFP::GenKey(*this, caps, b);
556     }
557 
name() const558     const char* name() const override { return "shadowFP"; }
559 
numLights() const560     int32_t numLights() const { return fNumNonAmbLights; }
ambientColor() const561     const SkColor3f& ambientColor() const { return fAmbientColor; }
isPointLight(int i) const562     bool isPointLight(int i) const {
563         SkASSERT(i < fNumNonAmbLights);
564         return fIsPointLight[i];
565     }
isRadialLight(int i) const566     bool isRadialLight(int i) const {
567         SkASSERT(i < fNumNonAmbLights);
568         return fIsRadialLight[i];
569     }
lightDirOrPos(int i) const570     const SkVector3& lightDirOrPos(int i) const {
571         SkASSERT(i < fNumNonAmbLights);
572         return fLightDirOrPos[i];
573     }
lightColor(int i) const574     const SkVector3& lightColor(int i) const {
575         SkASSERT(i < fNumNonAmbLights);
576         return fLightColor[i];
577     }
depthMapWidth(int i) const578     int depthMapWidth(int i) const {
579         SkASSERT(i < fNumNonAmbLights);
580         return fDepthMapWidth[i];
581     }
depthMapHeight(int i) const582     int depthMapHeight(int i) const {
583         SkASSERT(i < fNumNonAmbLights);
584         return fDepthMapHeight[i];
585     }
width() const586     int width() const {return fWidth; }
height() const587     int height() const {return fHeight; }
588 
shadowParams() const589     const SkShadowParams& shadowParams() const {return fShadowParams; }
590 
591 private:
onCreateGLSLInstance() const592     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new GLSLShadowFP; }
593 
onIsEqual(const GrFragmentProcessor & proc) const594     bool onIsEqual(const GrFragmentProcessor& proc) const override {
595         const ShadowFP& shadowFP = proc.cast<ShadowFP>();
596         if (fAmbientColor != shadowFP.fAmbientColor ||
597             fNumNonAmbLights != shadowFP.fNumNonAmbLights) {
598             return false;
599         }
600 
601         if (fWidth != shadowFP.fWidth || fHeight != shadowFP.fHeight) {
602             return false;
603         }
604 
605         for (int i = 0; i < fNumNonAmbLights; i++) {
606             if (fLightDirOrPos[i] != shadowFP.fLightDirOrPos[i] ||
607                 fLightColor[i] != shadowFP.fLightColor[i] ||
608                 fIsPointLight[i] != shadowFP.fIsPointLight[i] ||
609                 fIsRadialLight[i] != shadowFP.fIsRadialLight[i]) {
610                 return false;
611             }
612 
613             if (fDepthMapWidth[i] != shadowFP.fDepthMapWidth[i] ||
614                 fDepthMapHeight[i] != shadowFP.fDepthMapHeight[i]) {
615                 return false;
616             }
617         }
618 
619         return true;
620     }
621 
622     int              fNumNonAmbLights;
623 
624     bool             fIsPointLight[SkShadowShader::kMaxNonAmbientLights];
625     bool             fIsRadialLight[SkShadowShader::kMaxNonAmbientLights];
626     SkVector3        fLightDirOrPos[SkShadowShader::kMaxNonAmbientLights];
627     SkColor3f        fLightColor[SkShadowShader::kMaxNonAmbientLights];
628     TextureSampler   fDepthMapSampler[SkShadowShader::kMaxNonAmbientLights];
629     sk_sp<GrTexture> fTexture[SkShadowShader::kMaxNonAmbientLights];
630 
631     int              fDepthMapWidth[SkShadowShader::kMaxNonAmbientLights];
632     int              fDepthMapHeight[SkShadowShader::kMaxNonAmbientLights];
633 
634     int              fHeight;
635     int              fWidth;
636 
637     SkShadowParams   fShadowParams;
638 
639     SkColor3f        fAmbientColor;
640 };
641 
642 ////////////////////////////////////////////////////////////////////////////
643 
asFragmentProcessor(const AsFPArgs & fpargs) const644 sk_sp<GrFragmentProcessor> SkShadowShaderImpl::asFragmentProcessor(const AsFPArgs& fpargs) const {
645 
646     sk_sp<GrFragmentProcessor> povDepthFP = fPovDepthShader->asFragmentProcessor(fpargs);
647 
648     sk_sp<GrFragmentProcessor> diffuseFP = fDiffuseShader->asFragmentProcessor(fpargs);
649 
650     sk_sp<GrFragmentProcessor> shadowfp = sk_make_sp<ShadowFP>(std::move(povDepthFP),
651                                                                std::move(diffuseFP),
652                                                                std::move(fLights),
653                                                                fDiffuseWidth, fDiffuseHeight,
654                                                                fShadowParams, fpargs.fContext);
655     return shadowfp;
656 }
657 
658 
659 #endif
660 
661 ////////////////////////////////////////////////////////////////////////////
662 
isOpaque() const663 bool SkShadowShaderImpl::isOpaque() const {
664     return fDiffuseShader->isOpaque();
665 }
666 
ShadowShaderContext(const SkShadowShaderImpl & shader,const ContextRec & rec,SkShader::Context * povDepthContext,SkShader::Context * diffuseContext,void * heapAllocated)667 SkShadowShaderImpl::ShadowShaderContext::ShadowShaderContext(
668         const SkShadowShaderImpl& shader, const ContextRec& rec,
669         SkShader::Context* povDepthContext,
670         SkShader::Context* diffuseContext,
671         void* heapAllocated)
672         : INHERITED(shader, rec)
673         , fPovDepthContext(povDepthContext)
674         , fDiffuseContext(diffuseContext)
675         , fHeapAllocated(heapAllocated) {
676     bool isOpaque = shader.isOpaque();
677 
678     // update fFlags
679     uint32_t flags = 0;
680     if (isOpaque && (255 == this->getPaintAlpha())) {
681         flags |= kOpaqueAlpha_Flag;
682     }
683 
684     fFlags = flags;
685 
686     const SkShadowShaderImpl& lightShader = static_cast<const SkShadowShaderImpl&>(fShader);
687 
688     fNonAmbLightCnt = lightShader.fLights->numLights();
689     fShadowMapPixels = new SkPixmap[fNonAmbLightCnt];
690 
691     for (int i = 0; i < fNonAmbLightCnt; i++) {
692         if (lightShader.fLights->light(i).type() == SkLights::Light::kDirectional_LightType) {
693             lightShader.fLights->light(i).getShadowMap()->
694                     peekPixels(&fShadowMapPixels[i]);
695         }
696     }
697 }
698 
~ShadowShaderContext()699 SkShadowShaderImpl::ShadowShaderContext::~ShadowShaderContext() {
700     delete[] fShadowMapPixels;
701 
702     // The dependencies have been created outside of the context on memory that was allocated by
703     // the onCreateContext() method. Call the destructors and free the memory.
704     fPovDepthContext->~Context();
705     fDiffuseContext->~Context();
706 
707     sk_free(fHeapAllocated);
708 }
709 
convert(SkColor3f color,U8CPU a)710 static inline SkPMColor convert(SkColor3f color, U8CPU a) {
711     if (color.fX <= 0.0f) {
712         color.fX = 0.0f;
713     } else if (color.fX >= 255.0f) {
714         color.fX = 255.0f;
715     }
716 
717     if (color.fY <= 0.0f) {
718         color.fY = 0.0f;
719     } else if (color.fY >= 255.0f) {
720         color.fY = 255.0f;
721     }
722 
723     if (color.fZ <= 0.0f) {
724         color.fZ = 0.0f;
725     } else if (color.fZ >= 255.0f) {
726         color.fZ = 255.0f;
727     }
728 
729     return SkPreMultiplyARGB(a, (int) color.fX,  (int) color.fY, (int) color.fZ);
730 }
731 
732 // larger is better (fewer times we have to loop), but we shouldn't
733 // take up too much stack-space (each one here costs 16 bytes)
734 #define BUFFER_MAX 16
shadeSpan(int x,int y,SkPMColor result[],int count)735 void SkShadowShaderImpl::ShadowShaderContext::shadeSpan(int x, int y,
736                                                         SkPMColor result[], int count) {
737     const SkShadowShaderImpl& lightShader = static_cast<const SkShadowShaderImpl&>(fShader);
738 
739     SkPMColor diffuse[BUFFER_MAX];
740     SkPMColor povDepth[BUFFER_MAX];
741 
742     do {
743         int n = SkTMin(count, BUFFER_MAX);
744 
745         fDiffuseContext->shadeSpan(x, y, diffuse, n);
746         fPovDepthContext->shadeSpan(x, y, povDepth, n);
747 
748         for (int i = 0; i < n; ++i) {
749             SkColor diffColor = SkUnPreMultiply::PMColorToColor(diffuse[i]);
750             SkColor povDepthColor = povDepth[i];
751 
752             SkColor3f totalLight = lightShader.fLights->ambientLightColor();
753             // This is all done in linear unpremul color space (each component 0..255.0f though)
754 
755             for (int l = 0; l < lightShader.fLights->numLights(); ++l) {
756                 const SkLights::Light& light = lightShader.fLights->light(l);
757 
758                 int pvDepth = SkColorGetB(povDepthColor); // depth stored in blue channel
759 
760                 if (light.type() == SkLights::Light::kDirectional_LightType) {
761 
762                     int xOffset = SkScalarRoundToInt(light.dir().fX * pvDepth);
763                     int yOffset = SkScalarRoundToInt(light.dir().fY * pvDepth);
764 
765                     int shX = SkClampMax(x + i + xOffset, light.getShadowMap()->width() - 1);
766                     int shY = SkClampMax(y + yOffset, light.getShadowMap()->height() - 1);
767 
768                     int shDepth = 0;
769                     int shDepthsq = 0;
770 
771                     // pixmaps that point to things have nonzero heights
772                     if (fShadowMapPixels[l].height() > 0) {
773                         uint32_t pix = *fShadowMapPixels[l].addr32(shX, shY);
774                         SkColor shColor(pix);
775 
776                         shDepth = SkColorGetB(shColor);
777                         shDepthsq = SkColorGetG(shColor) * 256;
778                     } else {
779                         // Make lights w/o a shadow map receive the full light contribution
780                         shDepth = pvDepth;
781                     }
782 
783                     SkScalar lightProb = 1.0f;
784                     if (pvDepth < shDepth) {
785                         if (lightShader.fShadowParams.fType ==
786                             SkShadowParams::ShadowType::kVariance_ShadowType) {
787                             int variance = SkMaxScalar(shDepthsq - shDepth * shDepth,
788                                                        lightShader.fShadowParams.fMinVariance);
789                             int d = pvDepth - shDepth;
790 
791                             lightProb = (SkScalar) variance / ((SkScalar) (variance + d * d));
792 
793                             SkScalar bias = lightShader.fShadowParams.fBiasingConstant;
794 
795                             lightProb = SkMaxScalar((lightProb - bias) / (1.0f - bias), 0.0f);
796                         } else {
797                             lightProb = 0.0f;
798                         }
799                     }
800 
801                     // assume object normals are pointing straight up
802                     totalLight.fX += light.dir().fZ * light.color().fX * lightProb;
803                     totalLight.fY += light.dir().fZ * light.color().fY * lightProb;
804                     totalLight.fZ += light.dir().fZ * light.color().fZ * lightProb;
805 
806                 } else {
807                     // right now we only expect directional and point light types.
808                     SkASSERT(light.type() == SkLights::Light::kPoint_LightType);
809 
810                     int height = lightShader.fDiffuseHeight;
811 
812                     SkVector3 fragToLight = SkVector3::Make(light.pos().fX - x - i,
813                                                             light.pos().fY - (height - y),
814                                                             light.pos().fZ - pvDepth);
815 
816                     SkScalar dist = fragToLight.length();
817                     SkScalar normalizedZ = fragToLight.fZ / dist;
818 
819                     SkScalar distAttenuation = light.intensity() / (1.0f + dist);
820 
821                     // assume object normals are pointing straight up
822                     totalLight.fX += normalizedZ * light.color().fX * distAttenuation;
823                     totalLight.fY += normalizedZ * light.color().fY * distAttenuation;
824                     totalLight.fZ += normalizedZ * light.color().fZ * distAttenuation;
825                 }
826             }
827 
828             SkColor3f totalColor = SkColor3f::Make(SkColorGetR(diffColor) * totalLight.fX,
829                                                    SkColorGetG(diffColor) * totalLight.fY,
830                                                    SkColorGetB(diffColor) * totalLight.fZ);
831 
832             result[i] = convert(totalColor, SkColorGetA(diffColor));
833         }
834 
835         result += n;
836         x += n;
837         count -= n;
838     } while (count > 0);
839 }
840 
841 ////////////////////////////////////////////////////////////////////////////
842 
843 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const844 void SkShadowShaderImpl::toString(SkString* str) const {
845     str->appendf("ShadowShader: ()");
846 }
847 #endif
848 
CreateProc(SkReadBuffer & buf)849 sk_sp<SkFlattenable> SkShadowShaderImpl::CreateProc(SkReadBuffer& buf) {
850 
851     // Discarding SkShader flattenable params
852     bool hasLocalMatrix = buf.readBool();
853     SkAssertResult(!hasLocalMatrix);
854 
855     sk_sp<SkLights> lights = SkLights::MakeFromBuffer(buf);
856 
857     SkShadowParams params;
858     params.fMinVariance = buf.readScalar();
859     params.fBiasingConstant = buf.readScalar();
860     params.fType = (SkShadowParams::ShadowType) buf.readInt();
861     params.fShadowRadius = buf.readScalar();
862 
863     int diffuseWidth = buf.readInt();
864     int diffuseHeight = buf.readInt();
865 
866     sk_sp<SkShader> povDepthShader(buf.readFlattenable<SkShader>());
867     sk_sp<SkShader> diffuseShader(buf.readFlattenable<SkShader>());
868 
869     return sk_make_sp<SkShadowShaderImpl>(std::move(povDepthShader),
870                                           std::move(diffuseShader),
871                                           std::move(lights),
872                                           diffuseWidth, diffuseHeight,
873                                           params);
874 }
875 
flatten(SkWriteBuffer & buf) const876 void SkShadowShaderImpl::flatten(SkWriteBuffer& buf) const {
877     this->INHERITED::flatten(buf);
878 
879     fLights->flatten(buf);
880 
881     buf.writeScalar(fShadowParams.fMinVariance);
882     buf.writeScalar(fShadowParams.fBiasingConstant);
883     buf.writeInt(fShadowParams.fType);
884     buf.writeScalar(fShadowParams.fShadowRadius);
885 
886     buf.writeInt(fDiffuseWidth);
887     buf.writeInt(fDiffuseHeight);
888 
889     buf.writeFlattenable(fPovDepthShader.get());
890     buf.writeFlattenable(fDiffuseShader.get());
891 }
892 
onContextSize(const ContextRec & rec) const893 size_t SkShadowShaderImpl::onContextSize(const ContextRec& rec) const {
894     return sizeof(ShadowShaderContext);
895 }
896 
onCreateContext(const ContextRec & rec,void * storage) const897 SkShader::Context* SkShadowShaderImpl::onCreateContext(const ContextRec& rec,
898                                                        void* storage) const {
899     size_t heapRequired = fPovDepthShader->contextSize(rec) +
900                           fDiffuseShader->contextSize(rec);
901 
902     void* heapAllocated = sk_malloc_throw(heapRequired);
903 
904     void* povDepthContextStorage = heapAllocated;
905 
906     SkShader::Context* povDepthContext =
907             fPovDepthShader->createContext(rec, povDepthContextStorage);
908 
909     if (!povDepthContext) {
910         sk_free(heapAllocated);
911         return nullptr;
912     }
913 
914     void* diffuseContextStorage = (char*)heapAllocated + fPovDepthShader->contextSize(rec);
915 
916     SkShader::Context* diffuseContext = fDiffuseShader->createContext(rec, diffuseContextStorage);
917     if (!diffuseContext) {
918         sk_free(heapAllocated);
919         return nullptr;
920     }
921 
922     return new (storage) ShadowShaderContext(*this, rec, povDepthContext, diffuseContext,
923                                              heapAllocated);
924 }
925 
926 ///////////////////////////////////////////////////////////////////////////////
927 
Make(sk_sp<SkShader> povDepthShader,sk_sp<SkShader> diffuseShader,sk_sp<SkLights> lights,int diffuseWidth,int diffuseHeight,const SkShadowParams & params)928 sk_sp<SkShader> SkShadowShader::Make(sk_sp<SkShader> povDepthShader,
929                                      sk_sp<SkShader> diffuseShader,
930                                      sk_sp<SkLights> lights,
931                                      int diffuseWidth, int diffuseHeight,
932                                      const SkShadowParams& params) {
933     if (!povDepthShader || !diffuseShader) {
934         // TODO: Use paint's color in absence of a diffuseShader
935         // TODO: Use a default implementation of normalSource instead
936         return nullptr;
937     }
938 
939     return sk_make_sp<SkShadowShaderImpl>(std::move(povDepthShader),
940                                           std::move(diffuseShader),
941                                           std::move(lights),
942                                           diffuseWidth, diffuseHeight,
943                                           params);
944 }
945 
946 ///////////////////////////////////////////////////////////////////////////////
947 
948 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkShadowShader)
949     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkShadowShaderImpl)
950 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
951 
952 ///////////////////////////////////////////////////////////////////////////////
953 
954 #endif
955