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

Side by Side Diff: samplecode/SampleShadowing.cpp

Issue 2198933002: Making a sample for shadow maps for more intensive development (Closed) Base URL: https://skia.googlesource.com/skia@shadow-gm
Patch Set: undo change 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
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 "SampleCode.h"
robertphillips 2016/08/02 16:05:06 Do we need SkDrawFilter.h ?
vjiaoblack 2016/08/03 14:04:21 Done.
10 #include "SkDrawFilter.h"
11 #include "SkNormalSource.h"
robertphillips 2016/08/02 16:05:06 Same for SkPathEffect.h
vjiaoblack 2016/08/03 14:04:21 Done.
12 #include "SkPathEffect.h"
13 #include "SkPictureRecorder.h"
14 #include "SkSurface.h"
15 #include "SkShadowPaintFilterCanvas.h"
16 #include "SkShadowShader.h"
17
18 #ifdef SK_EXPERIMENTAL_SHADOWING
19
20 constexpr int NUM_TEST_RECTS = 3;
21
22 static sk_sp<SkShader> make_shadow_shader(sk_sp<SkImage> povDepth,
23 sk_sp<SkImage> diffuse,
24 sk_sp<SkLights> lights) {
25
26 sk_sp<SkShader> povDepthShader = povDepth->makeShader(SkShader::kClamp_TileM ode,
27 SkShader::kClamp_TileM ode);
28
29 sk_sp<SkShader> diffuseShader = diffuse->makeShader(SkShader::kClamp_TileMod e,
30 SkShader::kClamp_TileMod e);
31
32 return SkShadowShader::Make(std::move(povDepthShader),
33 std::move(diffuseShader),
34 std::move(lights),
35 diffuse->width(), diffuse->height());
36 }
37
38
39 class IndexClick : public SkView::Click {
40 int fIndex;
41 public:
robertphillips 2016/08/02 16:05:06 add INHERITED and use it here
vjiaoblack 2016/08/03 14:04:21 Done.
42 IndexClick(SkView* v, int index) : SkView::Click(v), fIndex(index) {}
43
44 static int GetIndex(SkView::Click* click) {
45 return ((IndexClick*)click)->fIndex;
46 }
47 };
48
49 class ShadowingView : public SampleView {
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.1f, 0.2f, 0.3f),
60 SkVector3::Make(0.27f, 0.07f, 1.0f)));
61 builder.add(SkLights::Light(SkColor3f::Make(0.3f, 0.2f, 0.1f),
62 SkVector3::Make(0.03f, 0.27f, 1.0f)));
63 builder.add(SkLights::Light(SkColor3f::Make(0.2f, 0.15f, 0.1f),
64 SkVector3::Make(0.21f, 0.21f, 1.0f)));
65 builder.add(SkLights::Light(SkColor3f::Make(0.1f, 0.15f, 0.2f),
66 SkVector3::Make(0.09f, 0.09f, 1.0f)));
67 builder.add(SkLights::Light(SkColor3f::Make(0.3f, 0.3f, 0.3f)));
68 this->fLights = builder.finish();
69
robertphillips 2016/08/02 16:05:07 don't need this-> on member variables
vjiaoblack 2016/08/03 14:04:21 Done.
70 this->fColors[0] = 0xFFEE8888;
71 this->fDepths[0] = 80;
72 this->fRects[0] = SkRect::MakeLTRB(200,150,350,300);
73
74 this->fColors[1] = 0xFF88EE88;
75 this->fDepths[1] = 160;
76 this->fRects[1] = SkRect::MakeLTRB(150,200,300,350);
77
78 this->fColors[2] = 0xFF8888EE;
79 this->fDepths[2] = 240;
80 this->fRects[2] = SkRect::MakeLTRB(100,100,250,250);
81 }
82
83 protected:
84 static const int kWidth = 400;
85 static const int kHeight = 400;
86 SkRect fRects[NUM_TEST_RECTS];
87 int fDepths[NUM_TEST_RECTS];
88 SkColor fColors[NUM_TEST_RECTS];
89 int fSelectedRect = -1;
90 bool fMoveLight = false;
91
92 bool onQuery(SkEvent *evt) override {
93 if (SampleCode::TitleQ(*evt)) {
94 SampleCode::TitleR(evt, "shadowing");
95 return true;
96 }
97
98 SkUnichar uni;
99 if (SampleCode::CharQ(*evt, &uni)) {
100 switch (uni) {
101 case 'L':
102 fMoveLight = !fMoveLight;
103 break;
104 default:
105 break;
106 }
107 }
108 return this->INHERITED::onQuery(evt);
109 }
110
robertphillips 2016/08/02 16:05:06 This is file static naming. You either need to mak
vjiaoblack 2016/08/03 14:04:21 Done.
111 sk_sp<SkPicture> make_test_picture(int width, int height) {
112 SkPictureRecorder recorder;
113
114 // LONG RANGE TODO: eventually add SkBBHFactory (bounding box factory)
115 SkCanvas* canvas = recorder.beginRecording(SkRect::MakeIWH(width, height ));
116
117 SkASSERT(canvas->getTotalMatrix().isIdentity());
118 SkPaint paint;
119 paint.setColor(SK_ColorGRAY);
120
121 // LONG RANGE TODO: tag occluders
122 // LONG RANGE TODO: track number of IDs we need (hopefully less than 256 )
123 // and determinate the mapping from z to id
124
125 // universal receiver, "ground"
126 canvas->drawRect(SkRect::MakeIWH(width, height), paint);
127
128 for (int i = 0; i < NUM_TEST_RECTS; i++) {
129 paint.setColor(fColors[i]);
130 if (i == 0) {
131 canvas->translateZ(fDepths[0]);
132 } else {
133 canvas->translateZ(fDepths[i] - fDepths[i-1]);
134 }
135 canvas->drawRect(fRects[i], paint);
136 }
137
138 return recorder.finishRecordingAsPicture();
139 }
140
robertphillips 2016/08/02 16:05:07 SkTMin ?
vjiaoblack 2016/08/03 14:04:21 Done.
141 #define MIN(x,y) ((x) > (y) ? (y) : (x))
142 void onDrawContent(SkCanvas *canvas) override {
143 // This picture stores the picture of the scene.
144 // It's used to generate the depth maps.
robertphillips 2016/08/02 16:05:06 Do you need to recreate this every time ?
vjiaoblack 2016/08/03 14:04:21 Done.
145 sk_sp<SkPicture> pic(make_test_picture(kWidth, kHeight));
146
robertphillips 2016/08/02 16:05:07 Don't you only need to recreate the shadow map if
vjiaoblack 2016/08/03 14:04:21 Done.
147 for (int i = 0; i < fLights->numLights(); ++i) {
148 // skip over ambient lights; they don't cast shadows
149 if (SkLights::Light::kAmbient_LightType == fLights->light(i).type()) {
150 continue;
151 }
152
153 // TODO: maybe add a kDepth_8_SkColorType when vertices have depth
154
155 SkImageInfo info = SkImageInfo::Make(kWidth, kHeight,
156 kBGRA_8888_SkColorType,
157 kOpaque_SkAlphaType);
158
159 // Create a new surface (that matches the backend of canvas)
160 // for each shadow map
161 sk_sp<SkSurface> surf(canvas->makeSurface(info));
162
163 // Wrap another SPFCanvas around the surface
164 sk_sp<SkShadowPaintFilterCanvas> depthMapCanvas =
165 sk_make_sp<SkShadowPaintFilterCanvas>(surf->getCanvas());
166
167 // set the depth map canvas to have the light we're drawing.
168 SkLights::Builder builder;
169 builder.add(fLights->light(i));
170 sk_sp<SkLights> curLight = builder.finish();
171
172 depthMapCanvas->setLights(std::move(curLight));
173 depthMapCanvas->drawPicture(pic);
174
175 fLights->light(i).setShadowMap(surf->makeImageSnapshot());
176 }
177
178 sk_sp<SkImage> povDepthMap;
179 sk_sp<SkImage> diffuseMap;
180
181 // TODO: pass the depth to the shader in vertices, or uniforms
182 // so we don't have to render depth and color separately
183
184 // povDepthMap
185 {
186 SkLights::Builder builder;
187 builder.add(SkLights::Light(SkColor3f::Make(1.0f, 1.0f, 1.0f),
188 SkVector3::Make(0.0f, 0.0f, 1.0f)));
189 sk_sp<SkLights> povLight = builder.finish();
190
191 SkImageInfo info = SkImageInfo::Make(kWidth, kHeight,
192 kBGRA_8888_SkColorType,
193 kOpaque_SkAlphaType);
194
195 // Create a new surface (that matches the backend of canvas)
196 // to create the povDepthMap
197 sk_sp<SkSurface> surf(canvas->makeSurface(info));
198
199 // Wrap another SPFCanvas around the surface
200 sk_sp<SkShadowPaintFilterCanvas> depthMapCanvas =
201 sk_make_sp<SkShadowPaintFilterCanvas>(surf->getCanvas());
202
203 // set the depth map canvas to have the light as the user's POV
204 depthMapCanvas->setLights(std::move(povLight));
205
206 depthMapCanvas->drawPicture(pic);
207
208 povDepthMap = surf->makeImageSnapshot();
209 }
210
211 // diffuseMap
212 {
213 SkImageInfo info = SkImageInfo::Make(kWidth, kHeight,
214 kBGRA_8888_SkColorType,
215 kOpaque_SkAlphaType);
216
217 sk_sp<SkSurface> surf(canvas->makeSurface(info));
218 surf->getCanvas()->drawPicture(pic);
219
220 diffuseMap = surf->makeImageSnapshot();
221 }
222
223 SkPaint paint;
224 paint.setShader(make_shadow_shader(std::move(povDepthMap),
225 std::move(diffuseMap),
226 fLights));
227
228 canvas->drawRect(SkRect::MakeIWH(kWidth, kHeight), paint);
229 }
230
231 SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) ove rride {
232 int index = 0;
233
234 return new IndexClick(this, index);
235 }
236
237 bool onClick(Click *click) override {
238 SkScalar x = click->fCurr.fX;
239 SkScalar y = click->fCurr.fY;
240
241 SkScalar dx = x - click->fPrev.fX;
242 SkScalar dy = y - click->fPrev.fY;
243
244 if (fMoveLight) {
robertphillips 2016/08/02 16:05:07 Rebuild the object here ...
vjiaoblack 2016/08/03 14:04:21 Done.
245 fLights->light(0).setDir(SkVector3::Make( 0.12f + (200.0f - x) / 400 .0f,
246 -0.08f + (200.0f - y) / 400 .0f, 1.0f));
247 fLights->light(1).setDir(SkVector3::Make(-0.12f + (200.0f - x) / 400 .0f,
248 0.12f + (200.0f - y) / 400 .0f, 1.0f));
249 fLights->light(2).setDir(SkVector3::Make( 0.06f + (200.0f - x) / 400 .0f,
250 0.06f + (200.0f - y) / 400 .0f, 1.0f));
251 fLights->light(3).setDir(SkVector3::Make(-0.06f + (200.0f - x) / 400 .0f,
252 -0.06f + (200.0f - y) / 400 .0f, 1.0f));
253 return true;
254 }
255
256 if (click->fState == Click::State::kUp_State) {
257 fSelectedRect = -1;
258 return true;
259 }
260
261 if (fSelectedRect > -1) {
262 SkScalar x = click->fCurr.fX;
263 SkScalar y = click->fCurr.fY;
264
265 SkScalar dx = x - click->fPrev.fX;
266 SkScalar dy = y - click->fPrev.fY;
267
268 fRects[fSelectedRect].fLeft += dx;
269 fRects[fSelectedRect].fRight += dx;
270 fRects[fSelectedRect].fTop += dy;
271 fRects[fSelectedRect].fBottom += dy;
272
273 return true;
274 }
275
276 // assume last elements are highest
277 for (int i = NUM_TEST_RECTS - 1; i >= 0; i--) {
278 if (fRects[i].contains(SkRect::MakeXYWH(x, y, 1, 1))) {
279 fSelectedRect = i;
280 fRects[i].fLeft += dx;
281 fRects[i].fRight += dx;
282 fRects[i].fTop += dy;
283 fRects[i].fBottom += dy;
284
285 break;
286 }
287 }
288
289 return true;
290 }
291
292
293 private:
294 sk_sp<SkLights> fLights;
295
296 typedef SampleView INHERITED;
297 };
298
299
300 //////////////////////////////////////////////////////////////////////////////
301 static SkView* MyFactory() { return new ShadowingView; }
302 static SkViewRegister reg(MyFactory);
303
304 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698