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*/
19class SkShadowShaderImpl : public SkShader {
20public:
21    /** Create a new shadowing shader that shadows
22        @param to do        to do
23    */
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
55        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
74protected:
75    void flatten(SkWriteBuffer&) const override;
76    size_t onContextSize(const ContextRec&) const override;
77    Context* onCreateContext(const ContextRec&, void*) const override;
78
79private:
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
108class ShadowFP : public GrFragmentProcessor {
109public:
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:
165        GLSLShadowFP() { }
166
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
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:
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
554    void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
555        GLSLShadowFP::GenKey(*this, caps, b);
556    }
557
558    const char* name() const override { return "shadowFP"; }
559
560    int32_t numLights() const { return fNumNonAmbLights; }
561    const SkColor3f& ambientColor() const { return fAmbientColor; }
562    bool isPointLight(int i) const {
563        SkASSERT(i < fNumNonAmbLights);
564        return fIsPointLight[i];
565    }
566    bool isRadialLight(int i) const {
567        SkASSERT(i < fNumNonAmbLights);
568        return fIsRadialLight[i];
569    }
570    const SkVector3& lightDirOrPos(int i) const {
571        SkASSERT(i < fNumNonAmbLights);
572        return fLightDirOrPos[i];
573    }
574    const SkVector3& lightColor(int i) const {
575        SkASSERT(i < fNumNonAmbLights);
576        return fLightColor[i];
577    }
578    int depthMapWidth(int i) const {
579        SkASSERT(i < fNumNonAmbLights);
580        return fDepthMapWidth[i];
581    }
582    int depthMapHeight(int i) const {
583        SkASSERT(i < fNumNonAmbLights);
584        return fDepthMapHeight[i];
585    }
586    int width() const {return fWidth; }
587    int height() const {return fHeight; }
588
589    const SkShadowParams& shadowParams() const {return fShadowParams; }
590
591private:
592    GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new GLSLShadowFP; }
593
594    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
644sk_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
663bool SkShadowShaderImpl::isOpaque() const {
664    return fDiffuseShader->isOpaque();
665}
666
667SkShadowShaderImpl::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
699SkShadowShaderImpl::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
710static 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
735void 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
844void SkShadowShaderImpl::toString(SkString* str) const {
845    str->appendf("ShadowShader: ()");
846}
847#endif
848
849sk_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
876void 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
893size_t SkShadowShaderImpl::onContextSize(const ContextRec& rec) const {
894    return sizeof(ShadowShaderContext);
895}
896
897SkShader::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
928sk_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
948SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkShadowShader)
949    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkShadowShaderImpl)
950SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
951
952///////////////////////////////////////////////////////////////////////////////
953
954#endif
955