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