OLD | NEW |
---|---|
(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 | |
robertphillips
2016/08/03 18:47:48
Why gm.h?
vjiaoblack
2016/08/04 13:36:22
Done.
| |
8 #include "gm.h" | |
9 #include "SampleCode.h" | |
10 #include "SkPictureRecorder.h" | |
11 #include "SkSurface.h" | |
12 #include "SkShadowPaintFilterCanvas.h" | |
13 #include "SkShadowShader.h" | |
14 | |
15 #ifdef SK_EXPERIMENTAL_SHADOWING | |
16 | |
robertphillips
2016/08/03 18:47:47
Can this be a class scope constant?
vjiaoblack
2016/08/04 13:36:22
Done.
| |
17 constexpr int NUM_TEST_RECTS = 3; | |
18 | |
19 static sk_sp<SkShader> make_shadow_shader(sk_sp<SkImage> povDepth, | |
20 sk_sp<SkImage> diffuse, | |
21 sk_sp<SkLights> lights) { | |
22 | |
23 sk_sp<SkShader> povDepthShader = povDepth->makeShader(SkShader::kClamp_TileM ode, | |
24 SkShader::kClamp_TileM ode); | |
25 | |
26 sk_sp<SkShader> diffuseShader = diffuse->makeShader(SkShader::kClamp_TileMod e, | |
27 SkShader::kClamp_TileMod e); | |
28 | |
29 return SkShadowShader::Make(std::move(povDepthShader), | |
30 std::move(diffuseShader), | |
31 std::move(lights), | |
32 diffuse->width(), diffuse->height()); | |
33 } | |
34 | |
35 | |
36 class IndexClick : public SkView::Click { | |
robertphillips
2016/08/03 18:47:47
move this to the private block ?
vjiaoblack
2016/08/04 13:36:22
Done.
| |
37 int fIndex; | |
38 public: | |
39 IndexClick(SkView* v, int index) : INHERITED(v), fIndex(index) {} | |
40 | |
41 static int GetIndex(SkView::Click* click) { | |
42 return ((IndexClick*)click)->fIndex; | |
43 } | |
44 | |
45 private: | |
46 typedef SkView::Click INHERITED; | |
47 }; | |
48 | |
49 class ShadowingView : public SampleView { | |
robertphillips
2016/08/03 18:47:48
Make this "static const int kZoom = 96;" down in t
vjiaoblack
2016/08/04 13:36:22
Done.
| |
50 enum { | |
51 kZoom = 96 | |
52 }; | |
53 | |
54 public: | |
55 ShadowingView() { | |
56 | |
57 this->setBGColor(sk_tool_utils::color_to_565(0xFFCCCCCC)); | |
58 SkLights::Builder builder; | |
59 builder.add(SkLights::Light(SkColor3f::Make(0.2f, 0.3f, 0.4f), | |
60 SkVector3::Make(0.27f, 0.07f, 1.0f))); | |
61 builder.add(SkLights::Light(SkColor3f::Make(0.4f, 0.3f, 0.2f), | |
62 SkVector3::Make(0.03f, 0.27f, 1.0f))); | |
63 builder.add(SkLights::Light(SkColor3f::Make(0.4f, 0.4f, 0.4f))); | |
64 fLights = builder.finish(); | |
65 | |
66 fColors[0] = 0xFFEE8888; | |
67 fDepths[0] = 80; | |
68 fRects[0] = SkRect::MakeLTRB(200,150,350,300); | |
69 | |
70 fColors[1] = 0xFF88EE88; | |
71 fDepths[1] = 160; | |
72 fRects[1] = SkRect::MakeLTRB(150,200,300,350); | |
73 | |
74 fColors[2] = 0xFF8888EE; | |
75 fDepths[2] = 240; | |
76 fRects[2] = SkRect::MakeLTRB(100,100,250,250); | |
77 | |
78 fUpdateDiffuseMap = true; | |
79 fUpdatePovDepthMap = true; | |
80 fUpdatePicture = true; | |
81 fUpdateDepthMaps = true; | |
82 | |
83 } | |
84 | |
85 protected: | |
robertphillips
2016/08/03 18:47:48
Can all these member variables be private ?
vjiaoblack
2016/08/04 13:36:22
Done.
| |
86 static const int kWidth = 400; | |
87 static const int kHeight = 400; | |
robertphillips
2016/08/03 18:47:48
Maybe have:
struct {
SkRect fGeometry;
int
vjiaoblack
2016/08/04 13:36:22
Done.
| |
88 SkRect fRects[NUM_TEST_RECTS]; | |
89 int fDepths[NUM_TEST_RECTS]; | |
90 SkColor fColors[NUM_TEST_RECTS]; | |
robertphillips
2016/08/03 18:47:48
You initialize all the other guys in the ctor.
vjiaoblack
2016/08/04 13:36:22
Done.
| |
91 int fSelectedRect = -1; | |
92 bool fMoveLight = false; | |
93 | |
94 sk_sp<SkImage> fPovDepthMap; | |
95 sk_sp<SkImage> fDiffuseMap; | |
96 sk_sp<SkPicture> fPicture; | |
97 | |
98 bool fUpdateDiffuseMap; | |
99 bool fUpdatePovDepthMap; | |
100 bool fUpdatePicture; | |
101 bool fUpdateDepthMaps; | |
102 | |
103 bool onQuery(SkEvent *evt) override { | |
104 if (SampleCode::TitleQ(*evt)) { | |
105 SampleCode::TitleR(evt, "shadowing"); | |
106 return true; | |
107 } | |
108 | |
109 SkUnichar uni; | |
110 if (SampleCode::CharQ(*evt, &uni)) { | |
111 switch (uni) { | |
112 case 'L': | |
113 fMoveLight = !fMoveLight; | |
114 break; | |
115 default: | |
116 break; | |
117 } | |
118 } | |
119 return this->INHERITED::onQuery(evt); | |
120 } | |
121 | |
122 sk_sp<SkPicture> makeTestPicture(int width, int height) { | |
123 SkPictureRecorder recorder; | |
124 | |
125 // LONG RANGE TODO: eventually add SkBBHFactory (bounding box factory) | |
126 SkCanvas* canvas = recorder.beginRecording(SkRect::MakeIWH(width, height )); | |
127 | |
128 SkASSERT(canvas->getTotalMatrix().isIdentity()); | |
129 SkPaint paint; | |
130 paint.setColor(SK_ColorGRAY); | |
131 | |
132 // LONG RANGE TODO: tag occluders | |
133 // LONG RANGE TODO: track number of IDs we need (hopefully less than 256 ) | |
134 // and determinate the mapping from z to id | |
135 | |
136 // universal receiver, "ground" | |
137 canvas->drawRect(SkRect::MakeIWH(width, height), paint); | |
138 | |
139 for (int i = 0; i < NUM_TEST_RECTS; i++) { | |
140 paint.setColor(fColors[i]); | |
141 if (i == 0) { | |
142 canvas->translateZ(fDepths[0]); | |
143 } else { | |
144 canvas->translateZ(fDepths[i] - fDepths[i-1]); | |
145 } | |
146 canvas->drawRect(fRects[i], paint); | |
147 } | |
148 | |
149 return recorder.finishRecordingAsPicture(); | |
150 } | |
151 | |
152 void updateDepthMaps(SkCanvas *canvas) { | |
153 for (int i = 0; i < fLights->numLights(); ++i) { | |
154 // skip over ambient lights; they don't cast shadows | |
155 if (SkLights::Light::kAmbient_LightType == fLights->light(i).type()) { | |
156 continue; | |
157 } | |
158 | |
159 // TODO: maybe add a kDepth_8_SkColorType when vertices have depth | |
160 | |
161 // assume max depth is 255. | |
162 // TODO: find actual max depth of picture | |
robertphillips
2016/08/03 18:47:48
Can this computation be a sub routine:
static SkI
vjiaoblack
2016/08/04 13:36:22
Done.
| |
163 int maxDepth = 255; | |
164 int dMapWidth = SkMin32(maxDepth * fabs(fLights->light(i).dir().fX) + kWidth, | |
robertphillips
2016/08/03 18:47:47
line up ?
vjiaoblack
2016/08/04 13:36:22
Done.
| |
165 kWidth * 2); | |
166 int dMapHeight = SkMin32(maxDepth * fabs(fLights->light(i).dir().fY) + kHeight, | |
robertphillips
2016/08/03 18:47:48
line up ?
vjiaoblack
2016/08/04 13:36:22
Done.
| |
167 kHeight * 2); | |
168 | |
169 SkImageInfo info = SkImageInfo::Make(dMapWidth, dMapHeight, | |
170 kBGRA_8888_SkColorType, | |
171 kOpaque_SkAlphaType); | |
172 | |
173 // Create a new surface (that matches the backend of canvas) | |
174 // for each shadow map | |
175 sk_sp<SkSurface> surf(canvas->makeSurface(info)); | |
176 | |
177 // Wrap another SPFCanvas around the surface | |
178 sk_sp<SkShadowPaintFilterCanvas> depthMapCanvas = | |
179 sk_make_sp<SkShadowPaintFilterCanvas>(surf->getCanvas()); | |
180 | |
181 // set the depth map canvas to have the light we're drawing. | |
182 SkLights::Builder builder; | |
183 builder.add(fLights->light(i)); | |
184 sk_sp<SkLights> curLight = builder.finish(); | |
185 | |
186 depthMapCanvas->setLights(std::move(curLight)); | |
187 depthMapCanvas->drawPicture(fPicture); | |
188 | |
189 fLights->light(i).setShadowMap(surf->makeImageSnapshot()); | |
190 } | |
191 } | |
192 | |
193 void updatePovDepthMap(SkCanvas* canvas) { | |
194 // TODO: pass the depth to the shader in vertices, or uniforms | |
195 // so we don't have to render depth and color separately | |
196 | |
197 SkLights::Builder builder; | |
198 builder.add(SkLights::Light(SkColor3f::Make(1.0f, 1.0f, 1.0f), | |
199 SkVector3::Make(0.0f, 0.0f, 1.0f))); | |
200 sk_sp<SkLights> povLight = builder.finish(); | |
201 | |
202 SkImageInfo info = SkImageInfo::Make(kWidth, kHeight, | |
203 kBGRA_8888_SkColorType, | |
204 kOpaque_SkAlphaType); | |
205 | |
206 // Create a new surface (that matches the backend of canvas) | |
207 // to create the povDepthMap | |
208 sk_sp<SkSurface> surf(canvas->makeSurface(info)); | |
209 | |
210 // Wrap another SPFCanvas around the surface | |
211 sk_sp<SkShadowPaintFilterCanvas> depthMapCanvas = | |
212 sk_make_sp<SkShadowPaintFilterCanvas>(surf->getCanvas()); | |
213 | |
214 // set the depth map canvas to have the light as the user's POV | |
215 depthMapCanvas->setLights(std::move(povLight)); | |
216 | |
217 depthMapCanvas->drawPicture(fPicture); | |
218 | |
219 fPovDepthMap = surf->makeImageSnapshot(); | |
220 } | |
221 | |
222 void updateDiffuseMap(SkCanvas* canvas) { | |
223 SkImageInfo info = SkImageInfo::Make(kWidth, kHeight, | |
224 kBGRA_8888_SkColorType, | |
225 kOpaque_SkAlphaType); | |
226 | |
227 sk_sp<SkSurface> surf(canvas->makeSurface(info)); | |
228 surf->getCanvas()->drawPicture(fPicture); | |
229 | |
230 fDiffuseMap = surf->makeImageSnapshot(); | |
231 } | |
232 | |
robertphillips
2016/08/03 18:47:48
rm this TODO ?
vjiaoblack
2016/08/04 13:36:22
Done.
| |
233 // TODO why does this get slower after time approaches | |
234 void onDrawContent(SkCanvas *canvas) override { | |
235 if (fUpdatePicture || !fPicture) { | |
robertphillips
2016/08/03 18:47:48
add this-> for member function calls here & below
vjiaoblack
2016/08/04 13:36:22
Done.
| |
236 fPicture = makeTestPicture(kWidth, kHeight); | |
237 fUpdatePicture = false; | |
238 } | |
239 | |
240 if (fUpdateDepthMaps || !fPovDepthMap) { | |
241 updateDepthMaps(canvas); | |
242 fUpdateDepthMaps = false; | |
243 } | |
244 | |
245 if (fUpdatePovDepthMap || !fPovDepthMap) { | |
246 updatePovDepthMap(canvas); | |
247 fUpdatePovDepthMap = false; | |
248 } | |
249 | |
250 if (fUpdateDiffuseMap || !fDiffuseMap) { | |
251 updateDiffuseMap(canvas); | |
252 fUpdateDiffuseMap = false; | |
253 } | |
254 | |
255 SkPaint paint; | |
robertphillips
2016/08/03 18:47:48
I don't think you want to std::move here
vjiaoblack
2016/08/04 13:36:22
I see. Since we need it next frame as well (perhap
| |
256 paint.setShader(make_shadow_shader(std::move(fPovDepthMap), | |
257 std::move(fDiffuseMap), | |
258 fLights)); | |
259 | |
260 canvas->drawRect(SkRect::MakeIWH(kWidth, kHeight), paint); | |
261 } | |
262 | |
263 SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) ove rride { | |
264 int index = 0; | |
265 | |
266 return new IndexClick(this, index); | |
267 } | |
268 | |
269 bool onClick(Click *click) override { | |
270 SkScalar x = click->fCurr.fX; | |
271 SkScalar y = click->fCurr.fY; | |
272 | |
273 SkScalar dx = x - click->fPrev.fX; | |
274 SkScalar dy = y - click->fPrev.fY; | |
275 | |
276 if (fMoveLight) { | |
277 if (dx != 0 && dy != 0) { | |
278 float recipX = 1.0f / kWidth; | |
279 float recipY = 1.0f / kHeight; | |
280 | |
281 SkLights::Builder builder; | |
282 builder.add(SkLights::Light(SkColor3f::Make(0.2f, 0.3f, 0.4f), | |
283 SkVector3::Make(0.12f + (200.0f - x) * recipX, | |
284 -0.08f + (200.0f - y ) * recipY, | |
285 1.0f))); | |
286 builder.add(SkLights::Light(SkColor3f::Make(0.4f, 0.3f, 0.2f), | |
287 SkVector3::Make(-0.12f + (200.0f - x ) * recipX, | |
288 0.12f + (200.0f - y) * recipY, | |
289 1.0f))); | |
290 builder.add(SkLights::Light(SkColor3f::Make(0.4f, 0.4f, 0.4f))); | |
291 fLights = builder.finish(); | |
292 | |
293 fUpdateDepthMaps = true; | |
294 } | |
295 | |
296 return true; | |
robertphillips
2016/08/03 18:47:48
extra '\n'
vjiaoblack
2016/08/04 13:36:22
Done.
| |
297 | |
298 } | |
299 | |
300 if (click->fState == Click::State::kUp_State) { | |
301 fSelectedRect = -1; | |
302 return true; | |
303 } | |
304 | |
305 if (fSelectedRect > -1) { | |
306 SkScalar x = click->fCurr.fX; | |
307 SkScalar y = click->fCurr.fY; | |
308 | |
309 SkScalar dx = x - click->fPrev.fX; | |
310 SkScalar dy = y - click->fPrev.fY; | |
311 | |
312 fRects[fSelectedRect].fLeft += dx; | |
313 fRects[fSelectedRect].fRight += dx; | |
314 fRects[fSelectedRect].fTop += dy; | |
315 fRects[fSelectedRect].fBottom += dy; | |
316 | |
robertphillips
2016/08/03 18:47:48
It seems like you actually have two states:
fScen
vjiaoblack
2016/08/04 13:36:22
Done.
Seems like the slowest part of the loop is
| |
317 fUpdateDepthMaps = true; | |
318 fUpdatePovDepthMap = true; | |
319 fUpdatePicture = true; | |
320 fUpdateDiffuseMap = true; | |
321 | |
322 return true; | |
323 } | |
324 | |
325 // assume last elements are highest | |
326 for (int i = NUM_TEST_RECTS - 1; i >= 0; i--) { | |
327 if (fRects[i].contains(SkRect::MakeXYWH(x, y, 1, 1))) { | |
328 fSelectedRect = i; | |
329 fRects[i].fLeft += dx; | |
330 fRects[i].fRight += dx; | |
331 fRects[i].fTop += dy; | |
332 fRects[i].fBottom += dy; | |
333 | |
334 fUpdateDepthMaps = true; | |
335 fUpdatePovDepthMap = true; | |
336 fUpdatePicture = true; | |
337 fUpdateDiffuseMap = true; | |
338 | |
339 break; | |
340 } | |
341 } | |
342 | |
343 return true; | |
344 } | |
345 | |
346 private: | |
347 sk_sp<SkLights> fLights; | |
348 | |
349 typedef SampleView INHERITED; | |
350 }; | |
351 | |
352 ////////////////////////////////////////////////////////////////////////////// | |
353 static SkView* MyFactory() { return new ShadowingView; } | |
354 static SkViewRegister reg(MyFactory); | |
355 | |
356 #endif | |
OLD | NEW |