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

Side by Side Diff: gm/shadowmaps.cpp

Issue 2118553002: adding new GM to demostrate new shadows (Closed) Base URL: https://skia.googlesource.com/skia@master
Patch Set: Made requested changes Created 4 years, 4 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
« no previous file with comments | « no previous file | gyp/common_variables.gypi » ('j') | src/core/SkShadowShader.cpp » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "gm.h"
9 #include "SkPaintFilterCanvas.h"
10 #include "SkPictureRecorder.h"
11 #include "SkShadowShader.h"
12 #include "SkSurface.h"
13
14 static sk_sp<SkShader> make_shadow_shader(sk_sp<SkImage> povDepth,
15 sk_sp<SkImage> diffuse,
16 sk_sp<SkLights> lights) {
17
18 sk_sp<SkShader> povDepthShader = povDepth->makeShader(SkShader::kClamp_TileM ode,
19 SkShader::kClamp_TileM ode);
20
21 sk_sp<SkShader> diffuseShader = diffuse->makeShader(SkShader::kClamp_TileMod e,
22 SkShader::kClamp_TileMod e);
23
24 return SkShadowShader::Make(std::move(povDepthShader),
25 std::move(diffuseShader),
26 std::move(lights));
27 }
28
29 static sk_sp<SkPicture> make_test_picture(int width, int height) {
30 SkPictureRecorder recorder;
31
32 // LONG RANGE TODO: eventually add SkBBHFactory (bounding box factory)
33 SkCanvas* canvas = recorder.beginRecording(SkRect::MakeIWH(width, height));
34
35 SkASSERT(canvas->getTotalMatrix().isIdentity());
36 SkPaint paint;
37 paint.setColor(SK_ColorGRAY);
38
39 // LONG RANGE TODO: tag occluders
40 // LONG RANGE TODO: track number of IDs we need (hopefully less than 256)
41 // and determinate the mapping from z to id
42
43 // universal receiver, "ground"
44 canvas->drawRect(SkRect::MakeIWH(width, height), paint);
45
46 // TODO: Maybe add the ID here along with the depth
47
48 paint.setColor(0xFFEE8888);
49
50 canvas->translateZ(80);
51 canvas->drawRect(SkRect::MakeLTRB(200,150,350,300), paint);
52
53 paint.setColor(0xFF88EE88);
54
55 canvas->translateZ(80);
56 canvas->drawRect(SkRect::MakeLTRB(150,200,300,350), paint);
57
58 paint.setColor(0xFF8888EE);
59
60 canvas->translateZ(80);
61 canvas->drawRect(SkRect::MakeLTRB(100,100,250,250), paint);
62 // TODO: Add an assert that Z order matches painter's order
63 // TODO: think about if the Z-order always matching painting order is too st rict
64
65 return recorder.finishRecordingAsPicture();
66 }
67
68 namespace skiagm {
69
70 /* We override the onFilter method to draw depths into the canvas
71 * depending on the current draw depth of the canvas, throwing out
72 * the actual draw color.
73 */
74 class SkShadowPaintFilterCanvas : public SkPaintFilterCanvas {
75 public:
76
77 SkShadowPaintFilterCanvas(SkCanvas* canvas) : INHERITED(canvas) { }
78
79 bool onFilter(SkTCopyOnFirstWrite<SkPaint>* paint, Type type) const override {
robertphillips 2016/07/28 19:47:25 So, what happens when paint is nullptr ?
vjiaoblack 2016/07/29 16:07:30 Then nothing is being drawn, and since our current
80 if (*paint) {
robertphillips 2016/07/28 19:47:25 So what happens if paint has an imageFilter or col
vjiaoblack 2016/07/29 16:07:29 Done.
81 int z = this->getZ();
82 SkASSERT(z <= 0xFF && z >= 0x00);
83 SkColor color = 0xFF000000; // init color to opaque black
84 color |= z; // Put the index into the blue component
85 paint->writable()->setColor(color);
86 }
87
88 return true;
89 }
90
91 void onDrawPicture(const SkPicture* picture, const SkMatrix* matrix, const S kPaint* paint) {
92 SkTCopyOnFirstWrite<SkPaint> filteredPaint(paint);
93 if (this->onFilter(&filteredPaint, kPicture_Type)) {
94 this->SkCanvas::onDrawPicture(picture, matrix, filteredPaint);
95 }
96 }
97
98 void updateMatrix() {
99 this->save();
100
101 // When we use the SkShadowPaintFilterCanvas, we can only render
102 // one depth map at a time. Thus, we leave it up to the user to
103 // set SkLights to only contain (or contain at the first position)
104 // the light they intend to use for the current depth rendering.
105 SkVector3 lightDir = this->fLights->light(0).dir();
106 SkScalar x = lightDir.fX * this->getZ();
107 SkScalar y = lightDir.fY * this->getZ();
108
109 this->translate(x, y);
110 }
111
112 void onDrawPaint(const SkPaint& paint) override {
113 this->updateMatrix();
114 this->INHERITED::onDrawPaint(paint);
115 this->restore();
116 }
117
118 void onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
119 const SkPaint& paint) override {
120 this->updateMatrix();
121 this->INHERITED::onDrawPoints(mode, count, pts, paint);
122 this->restore();
123 }
124
125 void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
126 this->updateMatrix();
127 this->INHERITED::onDrawRect(rect, paint);
128 this->restore();
129 }
130
131 void onDrawRRect(const SkRRect& rrect, const SkPaint& paint) override {
132 this->updateMatrix();
133 this->INHERITED::onDrawRRect(rrect, paint);
134 this->restore();
135 }
136
137 void onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
138 const SkPaint& paint) override {
139 this->updateMatrix();
140 this->INHERITED::onDrawDRRect(outer, inner, paint);
141 this->restore();
142 }
143
144 void onDrawOval(const SkRect& rect, const SkPaint& paint) override {
145 this->updateMatrix();
146 this->INHERITED::onDrawOval(rect, paint);
147 this->restore();
148 }
149
150 void onDrawPath(const SkPath& path, const SkPaint& paint) override {
151 this->updateMatrix();
152 this->INHERITED::onDrawPath(path, paint);
153 this->restore();
154 }
155
156 void onDrawBitmap(const SkBitmap& bm, SkScalar left, SkScalar top,
157 const SkPaint* paint) override {
158 this->updateMatrix();
159 this->INHERITED::onDrawBitmap(bm, left, top, paint);
160 this->restore();
161 }
162
163 void onDrawBitmapRect(const SkBitmap& bm, const SkRect* src, const SkRect& d st,
164 const SkPaint* paint, SrcRectConstraint constraint) ov erride {
165 this->updateMatrix();
166 this->INHERITED::onDrawBitmapRect(bm, src, dst, paint, constraint);
167 this->restore();
168 }
169
170 void onDrawBitmapNine(const SkBitmap& bm, const SkIRect& center,
171 const SkRect& dst, const SkPaint* paint) {
172 this->updateMatrix();
173 this->INHERITED::onDrawBitmapNine(bm, center, dst, paint);
174 this->restore();
175 }
176
177 void onDrawImage(const SkImage* image, SkScalar left, SkScalar top,
178 const SkPaint* paint) override {
179 this->updateMatrix();
180 this->INHERITED::onDrawImage(image, left, top, paint);
181 this->restore();
182 }
183
184 void onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
185 const SkPaint* paint, SrcRectConstraint constraint) ove rride {
186 this->updateMatrix();
187 this->INHERITED::onDrawImageRect(image, src, dst, paint, constraint);
188 this->restore();
189 }
190
191 void onDrawImageNine(const SkImage* image, const SkIRect& center,
192 const SkRect& dst, const SkPaint* paint) {
193 this->updateMatrix();
194 this->INHERITED::onDrawImageNine(image, center, dst, paint);
195 this->restore();
196 }
197
198 void onDrawVertices(VertexMode vmode, int vertexCount, const SkPoint vertice s[],
199 const SkPoint texs[], const SkColor colors[], SkXfermode * xmode,
200 const uint16_t indices[], int indexCount, const SkPaint& paint) override {
201 this->updateMatrix();
202 this->INHERITED::onDrawVertices(vmode, vertexCount, vertices, texs, colo rs,
203 xmode, indices, indexCount, paint);
204 this->restore();
205 }
206
207 void onDrawPatch(const SkPoint cubics[], const SkColor colors[], const SkPoi nt texCoords[],
208 SkXfermode* xmode, const SkPaint& paint) override {
209 this->updateMatrix();
210 this->INHERITED::onDrawPatch(cubics, colors, texCoords, xmode, paint);
211 this->restore();
212 }
213
214 void onDrawText(const void* text, size_t byteLength,
215 SkScalar x, SkScalar y, const SkPaint& paint) override {
216 this->updateMatrix();
217 this->INHERITED::onDrawText(text, byteLength, x, y, paint);
218 this->restore();
219 }
220
221 void onDrawPosText(const void* text, size_t byteLength,
222 const SkPoint pos[], const SkPaint& paint) override {
223 this->updateMatrix();
224 this->INHERITED::onDrawPosText(text, byteLength, pos, paint);
225 this->restore();
226 }
227
228 void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos [],
229 SkScalar constY, const SkPaint& paint) override {
230 this->updateMatrix();
231 this->INHERITED::onDrawPosTextH(text, byteLength, xpos, constY, paint);
232 this->restore();
233 }
234
235 void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& pat h,
236 const SkMatrix* matrix, const SkPaint& paint) override {
237 this->updateMatrix();
238 this->INHERITED::onDrawTextOnPath(text, byteLength, path, matrix, paint) ;
239 this->restore();
240 }
241
242 void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
243 const SkRect* cull, const SkPaint& paint) override {
244 this->updateMatrix();
245 this->INHERITED::onDrawTextRSXform(text, byteLength, xform, cull, paint) ;
246 this->restore();
247 }
248
249 void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
250 const SkPaint& paint) override {
251 this->updateMatrix();
252 this->INHERITED::onDrawTextBlob(blob, x, y, paint);
253 this->restore();
254 }
255
256 private:
257 typedef SkPaintFilterCanvas INHERITED;
258 };
259
260 class ShadowMapsGM : public GM {
261 public:
262 ShadowMapsGM() {
263 this->setBGColor(sk_tool_utils::color_to_565(0xFFCCCCCC));
264 }
265
266 void onOnceBeforeDraw() override {
267 // Create a light set consisting of
268 // - bluish directional light pointing more right than down
269 // - reddish directional light pointing more down than right
270 // - soft white ambient light
271
272 SkLights::Builder builder;
273 builder.add(SkLights::Light(SkColor3f::Make(0.2f, 0.3f, 0.4f),
274 SkVector3::Make(0.2f, 0.1f, 1.0f)));
275 builder.add(SkLights::Light(SkColor3f::Make(0.4f, 0.3f, 0.2f),
276 SkVector3::Make(0.1f, 0.2f, 1.0f)));
277 builder.add(SkLights::Light(SkColor3f::Make(0.4f, 0.4f, 0.4f)));
278 fLights = builder.finish();
279 }
280
281 protected:
282 static const int kWidth = 400;
283 static const int kHeight = 400;
284
285 SkString onShortName() override {
286 return SkString("shadowmaps");
287 }
288
289 SkISize onISize() override {
290 return SkISize::Make(kWidth, kHeight);
291 }
292
293 void onDraw(SkCanvas* canvas) override {
294 // This picture stores the picture of the scene.
295 // It's used to generate the depth maps.
296 sk_sp<SkPicture> pic(make_test_picture(kWidth, kHeight));
297
298 for (int i = 0; i < fLights->numLights(); ++i) {
299 // skip over ambient lights; they don't cast shadows
300 if (SkLights::Light::kAmbient_LightType == fLights->light(i).type()) {
301 continue;
302 }
303 // TODO: compute the correct size of the depth map from the light pr operties
304 // TODO: maybe add a kDepth_8_SkColorType
305
306 SkImageInfo info = SkImageInfo::Make(kWidth, kHeight,
307 kBGRA_8888_SkColorType,
308 kOpaque_SkAlphaType);
309
robertphillips 2016/07/28 19:47:25 SPFCanvas -> canvas now ?
vjiaoblack 2016/07/29 16:07:30 Done.
310 // Create a new surface (that matches the backend of SPFCanvas)
311 // for each shadow map
312 sk_sp<SkSurface> surf(canvas->makeSurface(info));
313
314 // Wrap another SPFCanvas around the surface
315 sk_sp<SkShadowPaintFilterCanvas> depthMapCanvas =
316 sk_make_sp<SkShadowPaintFilterCanvas>(surf->getCanvas());
317
318 // set the depth map canvas to have the light we're drawing.
319 SkLights::Builder builder;
320 builder.add(fLights->light(i));
321 sk_sp<SkLights> curLight = builder.finish();
322
robertphillips 2016/07/28 19:47:25 std::move(curLight) ?
vjiaoblack 2016/07/29 16:07:29 Done.
323 depthMapCanvas->setLights(curLight);
324 depthMapCanvas->drawPicture(pic);
325
326 fLights->light(i).setShadowMap(surf->makeImageSnapshot());
327 }
328
329 sk_sp<SkImage> povDepthMap;
330 sk_sp<SkImage> diffuseMap;
331
332 // TODO: pass the depth to the shader in vertices, or uniforms
333 // so we don't have to render depth and color separately
334
335 // povDepthMap
336 {
337 SkLights::Builder builder;
338 builder.add(SkLights::Light(SkColor3f::Make(1.0f, 1.0f, 1.0f),
339 SkVector3::Make(0.0f, 0.0f, 1.0f)));
340 sk_sp<SkLights> povLight = builder.finish();
341
342 SkImageInfo info = SkImageInfo::Make(kWidth, kHeight,
343 kBGRA_8888_SkColorType,
344 kOpaque_SkAlphaType);
345
346 // Create a new surface (that matches the backend of 'canvas')
347 // to create the povDepthMap
348 sk_sp<SkSurface> surf(canvas->makeSurface(info));
349
350 // Wrap another SPFCanvas around the surface
351 sk_sp<SkShadowPaintFilterCanvas> depthMapCanvas =
352 sk_make_sp<SkShadowPaintFilterCanvas>(surf->getCanvas());
353
354 // set the depth map canvas to have the light as the user's POV
robertphillips 2016/07/28 19:47:25 std::move(povLight) ?
vjiaoblack 2016/07/29 16:07:29 Done.
355 depthMapCanvas->setLights(povLight);
356
357 depthMapCanvas->drawPicture(pic);
358
359 povDepthMap = surf->makeImageSnapshot();
360 }
361
362 // diffuseMap
363 {
364 SkImageInfo info = SkImageInfo::Make(kWidth, kHeight,
365 kBGRA_8888_SkColorType,
366 kOpaque_SkAlphaType);
367
368 sk_sp<SkSurface> surf(canvas->makeSurface(info));
369 surf->getCanvas()->drawPicture(pic);
370
371 diffuseMap = surf->makeImageSnapshot();
372 }
373
374 SkPaint paint;
375 paint.setShader(make_shadow_shader(povDepthMap, diffuseMap, fLights));
376
377 canvas->drawRect(SkRect::MakeIWH(kWidth, kHeight), paint);
378 }
379
380 private:
381 sk_sp<SkLights> fLights;
382
383 typedef GM INHERITED;
384 };
385
386 //////////////////////////////////////////////////////////////////////////////
387
388 DEF_GM(return new ShadowMapsGM;)
389 }
OLDNEW
« no previous file with comments | « no previous file | gyp/common_variables.gypi » ('j') | src/core/SkShadowShader.cpp » ('J')

Powered by Google App Engine
This is Rietveld 408576698