Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(401)

Side by Side Diff: src/core/Sk2DShadowMapShader.cpp

Issue 2311223004: added in radial shadows (Closed)
Patch Set: removed extra new line, also fixed some overlength lines Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 "Sk2DShadowMapShader.h"
9 #include "SkLights.h"
10 #include "SkPoint3.h"
11 #include "SkReadBuffer.h"
12 #include "SkShadowShader.h"
13
14 ////////////////////////////////////////////////////////////////////////////
15 #ifdef SK_EXPERIMENTAL_SHADOWING
16
17
18 /** \class Sk2DShadowMapShaderImpl
19 This subclass of shader applies shadowing
jvanverth1 2016/09/07 14:47:23 Needs a little more detail here. "... shadowing ra
vjiaoblack 2016/09/07 15:21:39 Done.
20 */
21 class Sk2DShadowMapShaderImpl : public SkShader {
22 public:
23 /** Create a new shadowing shader that shadows
jvanverth1 2016/09/07 14:47:23 "... shadows radially around a light"?
vjiaoblack 2016/09/07 15:21:39 Done.
24 */
25 Sk2DShadowMapShaderImpl(sk_sp<SkShader> occluderShader,
26 sk_sp<SkLights> lights,
jvanverth1 2016/09/07 14:47:23 Nit: indent to (
vjiaoblack 2016/09/07 15:21:39 Done.
27 int diffuseWidth, int diffuseHeight)
28 : fOccluderShader(std::move(occluderShader))
jvanverth1 2016/09/07 14:47:23 Nit: indent 4 spaces
vjiaoblack 2016/09/07 15:21:39 Done.
29 , fLight(std::move(lights))
30 , fWidth(diffuseWidth)
31 , fHeight(diffuseHeight) { }
32
33 bool isOpaque() const override;
34
35 #if SK_SUPPORT_GPU
36 sk_sp<GrFragmentProcessor> asFragmentProcessor(const AsFPArgs&) const overri de;
37 #endif
38
39 class ShadowMap2DShaderContext : public SkShader::Context {
40 public:
41 // The context takes ownership of the states. It will call their destruc tors
42 // but will NOT free the memory.
43 ShadowMap2DShaderContext(const Sk2DShadowMapShaderImpl&, const ContextRe c&,
44 SkShader::Context* occluderContext,
jvanverth1 2016/09/07 14:47:22 Nit: indent to (
vjiaoblack 2016/09/07 15:21:39 Done.
45 void* heapAllocated);
46
47 ~ShadowMap2DShaderContext() override;
48
49 void shadeSpan(int x, int y, SkPMColor[], int count) override;
50
51 uint32_t getFlags() const override { return fFlags; }
52
53 private:
54 SkShader::Context* fOccluderContext;
55 uint32_t fFlags;
56
57 void* fHeapAllocated;
58
59 typedef SkShader::Context INHERITED;
60 };
61
62 SK_TO_STRING_OVERRIDE()
63 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Sk2DShadowMapShaderImpl)
jvanverth1 2016/09/07 14:47:23 Indent
vjiaoblack 2016/09/07 15:21:39 Done.
64
65 protected:
66 void flatten(SkWriteBuffer&) const override;
67 size_t onContextSize(const ContextRec&) const override;
68 Context* onCreateContext(const ContextRec&, void*) const override;
69
70 private:
71 sk_sp<SkShader> fOccluderShader;
72 sk_sp<SkLights> fLight;
73
74 int fWidth;
75 int fHeight;
76
77 friend class Sk2DShadowMapShader;
78
79 typedef SkShader INHERITED;
80 };
81
82 ////////////////////////////////////////////////////////////////////////////
83
84 #if SK_SUPPORT_GPU
85
86 #include "GrContext.h"
87 #include "GrCoordTransform.h"
88 #include "GrFragmentProcessor.h"
89 #include "glsl/GrGLSLFragmentProcessor.h"
90 #include "glsl/GrGLSLFragmentShaderBuilder.h"
91 #include "SkGr.h"
92 #include "SkGrPriv.h"
93 #include "SkImage_Base.h"
94 #include "GrInvariantOutput.h"
95 #include "SkSpecialImage.h"
96
97 class TwoDShadowMapFP : public GrFragmentProcessor {
jvanverth1 2016/09/07 14:47:23 RadialShadowMapFP?
vjiaoblack 2016/09/07 15:21:39 Done.
98 public:
99 TwoDShadowMapFP(sk_sp<GrFragmentProcessor> occluder,
100 sk_sp<SkLights> light,
jvanverth1 2016/09/07 14:47:23 Indent to (
vjiaoblack 2016/09/07 15:21:39 Done.
101 int diffuseWidth, int diffuseHeight,
102 GrContext* context) {
103 fLightDir = light->light(0).pos();
104
105 fWidth = diffuseWidth;
106 fHeight = diffuseHeight;
107
108 this->registerChildProcessor(std::move(occluder));
109 this->initClassID<TwoDShadowMapFP>();
110 }
111
112 class GLSLTwoDShadowMapFP : public GrGLSLFragmentProcessor {
113 public:
114 GLSLTwoDShadowMapFP() { }
115
116 void emitCode(EmitArgs& args) override {
117
118 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
119 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
120
121 const char* lightDirUniName = nullptr;
jvanverth1 2016/09/07 14:47:23 lightPosUniName?
vjiaoblack 2016/09/07 15:21:39 Done.
122
123 fLightDirUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
124 kVec3f_GrSLType,
125 kDefault_GrSLPrecision,
126 "lightDir",
127 &lightDirUniName);
128
129 const char* widthUniName = nullptr;
130 const char* heightUniName = nullptr;
131
132 fWidthUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
133 kInt_GrSLType,
134 kDefault_GrSLPrecision,
135 "width", &widthUniName);
136 fHeightUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
137 kInt_GrSLType,
138 kDefault_GrSLPrecision,
139 "height", &heightUniName);
140
141
142 SkString occluder("occluder");
143 this->emitChild(0, nullptr, &occluder, args);
144
145 // the above isn't good enough. We need to modify the indexing coord inate.
jvanverth1 2016/09/07 14:47:22 Is this a TODO? Or do you plan to do it in this ch
vjiaoblack 2016/09/07 15:21:39 It's an explanation of what the code below does
146
147 fragBuilder->codeAppendf("float distHere;");
148 fragBuilder->codeAppendf("float closestDistHere = 0;");
149 fragBuilder->codeAppendf("vec2 coords = vMatrixCoord_0_0_Stage0;");
150 fragBuilder->codeAppendf("coords.y = 0;");
151 fragBuilder->codeAppendf("vec2 destCoords = vec2(0,0);");
152 fragBuilder->codeAppendf("float step = 0.0025;");
jvanverth1 2016/09/07 14:47:24 Is there an assumption of texture size here? Shoul
vjiaoblack 2016/09/07 15:21:39 Done.
153
154 // assume that we are at 0, 0 light pos
155 // TODO use correct light positions
jvanverth1 2016/09/07 14:47:23 Could use a comment explaining what this loop is d
vjiaoblack 2016/09/07 15:21:39 Done.
156 fragBuilder->codeAppendf("for (coords.y = 0; coords.y <= 1; coords.y += step) {");
157
158 fragBuilder->codeAppendf("vec2 norm = coords * 2.0 - 1.0;");
159 fragBuilder->codeAppendf("float theta = 3.1415 * 1.5 + norm.x * 3.1415;");
jvanverth1 2016/09/07 14:47:23 It looks like this will vary from pi/2 to 5*pi/2.
vjiaoblack 2016/09/07 15:21:39 Tis right for now. (The light is fixed)
160 fragBuilder->codeAppendf("float r = (1.0 + norm.y) * 0.5;");
jvanverth1 2016/09/07 14:47:23 I think this is just coords.y again.
161 fragBuilder->codeAppendf("destCoords = "
162 "vec2(-r * sin(theta), -r * cos(theta)) /2.0 + 0.5;");
jvanverth1 2016/09/07 14:47:23 The -r is odd to me -- negative polar coords? And
vjiaoblack 2016/09/07 15:21:39 That compiles to + vec(0.5, 0.5)
163 fragBuilder->codeAppendf("distHere = texture(uTextureSampler0_St age1, "
164 "destCoords).b;");
165 fragBuilder->codeAppendf("if (distHere > 0.0) {"
166 "closestDistHere = 1-coords.y;"
167 "break;}");
168 fragBuilder->codeAppendf("}");
169
170 fragBuilder->codeAppendf("%s = vec4(vec3(closestDistHere),1);", args .fOutputColor);
171 }
172
173 static void GenKey(const GrProcessor& proc, const GrGLSLCaps&,
174 GrProcessorKeyBuilder* b) {
175 b->add32(0); // nothing to add here
176 }
177
178 protected:
179 void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& proc) override {
180 const TwoDShadowMapFP &twoDShadowMapFP = proc.cast<TwoDShadowMapFP>( );
181
182 const SkVector3& lightDir = twoDShadowMapFP.lightDir();
183 if (lightDir != fLightDir) {
184 pdman.set3fv(fLightDirUni, 1, &lightDir.fX);
185 fLightDir = lightDir;
186 }
187
188 int width = twoDShadowMapFP.width();
189 if (width != fWidth) {
190 pdman.set1i(fWidthUni, width);
191 fWidth = width;
192 }
193 int height = twoDShadowMapFP.height();
194 if (height != fHeight) {
195 pdman.set1i(fHeightUni, height);
196 fHeight = height;
197 }
198 }
199
200 private:
201 SkVector3 fLightDir;
202 GrGLSLProgramDataManager::UniformHandle fLightDirUni;
203
204 int fWidth;
205 GrGLSLProgramDataManager::UniformHandle fWidthUni;
206 int fHeight;
207 GrGLSLProgramDataManager::UniformHandle fHeightUni;
208 };
209
210 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
211 GLSLTwoDShadowMapFP::GenKey(*this, caps, b);
212 }
213
214 const char* name() const override { return "twoDShadowMapFP"; }
jvanverth1 2016/09/07 14:47:23 "radialShadowMapFP"
vjiaoblack 2016/09/07 15:21:39 Done.
215
216 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
217 inout->mulByUnknownFourComponents();
218 }
219 const SkVector3& lightDir() const {
220 return fLightDir;
221 }
222
223 int width() const {return fWidth; }
224 int height() const {return fHeight; }
225
226 private:
227 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
228 return new GLSLTwoDShadowMapFP;
229 }
230
231 bool onIsEqual(const GrFragmentProcessor& proc) const override {
232 const TwoDShadowMapFP& twoDShadowMapFP = proc.cast<TwoDShadowMapFP>();
233
234 if (fWidth != twoDShadowMapFP.fWidth || fHeight != twoDShadowMapFP.fHeig ht) {
235 return false;
236 }
237
238 if (fLightDir != twoDShadowMapFP.fLightDir) {
239 return false;
240 }
241
242 return true;
243 }
244
245 SkVector3 fLightDir;
jvanverth1 2016/09/07 14:47:23 There's no direction in this case, so fLightPos?
vjiaoblack 2016/09/07 15:21:39 Done.
246
247 int fHeight;
248 int fWidth;
249 };
250
251 ////////////////////////////////////////////////////////////////////////////
252
253 sk_sp<GrFragmentProcessor> Sk2DShadowMapShaderImpl::asFragmentProcessor(const As FPArgs& fpargs)
254 const {
255
256 sk_sp<GrFragmentProcessor> occluderFP = fOccluderShader->asFragmentProcessor (fpargs);
257
258 sk_sp<GrFragmentProcessor> shadowfp = sk_make_sp<TwoDShadowMapFP>(std::move( occluderFP),
259 std::move(fLight) ,
260 fWidth, fHeight,
261 fpargs.fContext);
262 return shadowfp;
263 }
264
265 #endif
266
267 ////////////////////////////////////////////////////////////////////////////
268
269 bool Sk2DShadowMapShaderImpl::isOpaque() const {
270 return fOccluderShader->isOpaque();
271 }
272
273 Sk2DShadowMapShaderImpl::ShadowMap2DShaderContext::ShadowMap2DShaderContext(
jvanverth1 2016/09/07 14:47:23 SkRadialShadowMapShaderImpl
vjiaoblack 2016/09/07 15:21:39 Done.
274 const Sk2DShadowMapShaderImpl& shader, const ContextRec& rec,
275 SkShader::Context* occluderContext,
276 void* heapAllocated)
277 : INHERITED(shader, rec)
278 , fOccluderContext(occluderContext)
279 , fHeapAllocated(heapAllocated) {
280 bool isOpaque = shader.isOpaque();
281
282 // update fFlags
283 uint32_t flags = 0;
284 if (isOpaque && (255 == this->getPaintAlpha())) {
285 flags |= kOpaqueAlpha_Flag;
286 }
287
288 fFlags = flags;
289 }
290
291 Sk2DShadowMapShaderImpl::ShadowMap2DShaderContext::~ShadowMap2DShaderContext() {
292 // The dependencies have been created outside of the context on memory that was allocated by
293 // the onCreateContext() method. Call the destructors and free the memory.
294 fOccluderContext->~Context();
295
296 sk_free(fHeapAllocated);
297 }
298
299 static inline SkPMColor convert(SkColor3f color, U8CPU a) {
300 if (color.fX <= 0.0f) {
301 color.fX = 0.0f;
302 } else if (color.fX >= 255.0f) {
303 color.fX = 255.0f;
304 }
305
306 if (color.fY <= 0.0f) {
307 color.fY = 0.0f;
308 } else if (color.fY >= 255.0f) {
309 color.fY = 255.0f;
310 }
311
312 if (color.fZ <= 0.0f) {
313 color.fZ = 0.0f;
314 } else if (color.fZ >= 255.0f) {
315 color.fZ = 255.0f;
316 }
317
318 return SkPreMultiplyARGB(a, (int) color.fX, (int) color.fY, (int) color.fZ) ;
319 }
320
321 // larger is better (fewer times we have to loop), but we shouldn't
322 // take up too much stack-space (each one here costs 16 bytes)
323 #define BUFFER_MAX 16
324 void Sk2DShadowMapShaderImpl::ShadowMap2DShaderContext::shadeSpan(int x, int y,
325 SkPMColor result[], int count) {
326 do {
327 int n = SkTMin(count, BUFFER_MAX);
328
329 for (int i = 0; i < n; ++i) {
jvanverth1 2016/09/07 14:47:23 // Fill with white for now
vjiaoblack 2016/09/07 15:21:39 Done.
330 SkColor3f accum = SkColor3f::Make(1.0f, 1.0f, 1.0f);
jvanverth1 2016/09/07 14:47:23 This and the convert() could be outside the loop.
vjiaoblack 2016/09/07 15:21:39 Done.
331 result[i] = convert(accum, 0xFF);
332 }
333
334 result += n;
335 x += n;
336 count -= n;
337 } while (count > 0);
338 }
339
340 ////////////////////////////////////////////////////////////////////////////
341
342 #ifndef SK_IGNORE_TO_STRING
343 void Sk2DShadowMapShaderImpl::toString(SkString* str) const {
344 str->appendf("2DShadowMapShader: ()");
345 }
346 #endif
347
348 sk_sp<SkFlattenable> Sk2DShadowMapShaderImpl::CreateProc(SkReadBuffer& buf) {
349
350 // Discarding SkShader flattenable params
351 bool hasLocalMatrix = buf.readBool();
352 SkAssertResult(!hasLocalMatrix);
353
354 sk_sp<SkLights> light = SkLights::MakeFromBuffer(buf);
355
356 int diffuseWidth = buf.readInt();
357 int diffuseHeight = buf.readInt();
358
359 sk_sp<SkShader> occluderShader(buf.readFlattenable<SkShader>());
360
361 return sk_make_sp<Sk2DShadowMapShaderImpl>(std::move(occluderShader),
362 std::move(light),
363 diffuseWidth, diffuseHeight);
364 }
365
366 void Sk2DShadowMapShaderImpl::flatten(SkWriteBuffer& buf) const {
367 this->INHERITED::flatten(buf);
368
369 fLight->flatten(buf);
370
371 buf.writeInt(fWidth);
372 buf.writeInt(fHeight);
373
374 buf.writeFlattenable(fOccluderShader.get());
375 }
376
377 size_t Sk2DShadowMapShaderImpl::onContextSize(const ContextRec& rec) const {
378 return sizeof(ShadowMap2DShaderContext);
379 }
380
381 SkShader::Context* Sk2DShadowMapShaderImpl::onCreateContext(const ContextRec& re c,
382 void* storage) const {
383 size_t heapRequired = fOccluderShader->contextSize(rec);
384
385 void* heapAllocated = sk_malloc_throw(heapRequired);
386
387 void* occluderContextStorage = heapAllocated;
388
389 SkShader::Context* occluderContext =
390 fOccluderShader->createContext(rec, occluderContextStorage);
391
392 if (!occluderContext) {
393 sk_free(heapAllocated);
394 return nullptr;
395 }
396
397 return new (storage) ShadowMap2DShaderContext(*this, rec, occluderContext, h eapAllocated);
398 }
399
400 ///////////////////////////////////////////////////////////////////////////////
401
402 sk_sp<SkShader> Sk2DShadowMapShader::Make(sk_sp<SkShader> occluderShader,
403 sk_sp<SkLights> light,
404 int diffuseWidth, int diffuseHeight) {
405 if (!occluderShader) {
406 // TODO: Use paint's color in absence of a diffuseShader
407 // TODO: Use a default implementation of normalSource instead
408 return nullptr;
409 }
410
411 return sk_make_sp<Sk2DShadowMapShaderImpl>(std::move(occluderShader),
412 std::move(light),
413 diffuseWidth, diffuseHeight);
414 }
415
416 ///////////////////////////////////////////////////////////////////////////////
417
418 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(Sk2DShadowMapShader)
419 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(Sk2DShadowMapShaderImpl)
jvanverth1 2016/09/07 14:47:23 Indent
vjiaoblack 2016/09/07 15:21:39 Done.
420 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
421
422 ///////////////////////////////////////////////////////////////////////////////
423
424 #endif
OLDNEW
« src/core/Sk2DShadowMapShader.h ('K') | « src/core/Sk2DShadowMapShader.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698