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

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

Powered by Google App Engine
This is Rietveld 408576698