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

Side by Side Diff: samplecode/SampleLitAtlas.cpp

Issue 2026393005: Add SampleApp slide with animating lightmapped objects & transparency (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: ... Created 4 years, 6 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
« include/core/SkLights.h ('K') | « include/core/SkLights.h ('k') | no next file » | no next file with comments »
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 "SampleCode.h"
9 #include "SkAnimTimer.h"
10 #include "SkView.h"
11 #include "SkCanvas.h"
12 #include "SkDrawable.h"
13 #include "SkLights.h"
egdaniel 2016/06/03 15:52:48 nit: flip Lights and Lighting in alpha order here
robertphillips 2016/06/03 16:35:31 Done.
14 #include "SkLightingShader.h"
15 #include "SkRandom.h"
16 #include "SkRSXform.h"
17
18 #include "sk_tool_utils.h"
19
20 class DrawLitAtlasDrawable : public SkDrawable {
21 public:
22 DrawLitAtlasDrawable(const SkRect& r)
23 : fBounds(r)
24 , fUseColors(false) {
25 fAtlas = MakeAtlas();
26
27 SkRandom rand;
28 for (int i = 0; i < kNumAsteroids; ++i) {
29 fAsteroids[i].initAsteroid(&rand, fBounds, &fDiffTex[i], &fNormTex[i ]);
30 }
31
32 fShip.initShip(fBounds, &fDiffTex[kNumAsteroids], &fNormTex[kNumAsteroid s]);
33
34 SkLights::Builder builder;
35
36 builder.add(SkLights::Light(SkColor3f::Make(1.0f, 1.0f, 1.0f),
37 SkVector3::Make(1.0f, 0.0f, 0.0f)));
38 builder.add(SkLights::Light(SkColor3f::Make(0.2f, 0.2f, 0.2f)));
39
40 fLights = builder.finish();
41 }
42
43 void toggleUseColors() {
44 fUseColors = !fUseColors;
45 }
46
47 void left() {
48 SkScalar newRot = SkScalarMod(fShip.rot() + (2*SK_ScalarPI - SK_ScalarPI /32.0f),
49 2 * SK_ScalarPI);
50 fShip.setRot(newRot);
51 }
52
53 void right() {
54 SkScalar newRot = SkScalarMod(fShip.rot() + SK_ScalarPI/32.0f, 2 * SK_Sc alarPI);
55 fShip.setRot(newRot);
56 }
57
58 void thrust() {
59 SkScalar c;
60 SkScalar s = SkScalarSinCos(fShip.rot(), &c);
61
62 SkVector newVel = fShip.velocity();
63 newVel.fX = s;
64 newVel.fY = -c;
egdaniel 2016/06/03 15:52:48 DON' NEED TO CHANGE: You might want to consider ca
robertphillips 2016/06/03 16:35:31 Done.
65
66 fShip.setVelocity(newVel);
67 }
68
69 protected:
70 void onDraw(SkCanvas* canvas) override {
71 SkRSXform xforms[kNumAsteroids+kNumShips];
72 SkColor colors[kNumAsteroids+kNumShips];
73
74 for (int i = 0; i < kNumAsteroids; ++i) {
75 fAsteroids[i].advance(fBounds);
76 xforms[i] = fAsteroids[i].asRSXform();
77 if (fUseColors) {
78 colors[i] = SkColorSetARGB(0xFF, 0xFF, 0xFF, 0xFF);
79 }
80 }
81
82 fShip.advance(fBounds);
83 xforms[kNumAsteroids] = fShip.asRSXform();
84 if (fUseColors) {
85 colors[kNumAsteroids] = SkColorSetARGB(0xFF, 0xFF, 0xFF, 0xFF);
86 }
87
88 #ifdef SK_DEBUG
89 canvas->drawBitmap(fAtlas, 0, 0); // just to see the atlas
90 #endif
91
92 #if 0
93 // TODO: revitalize when drawLitAtlas API lands
94 SkPaint paint;
95 paint.setFilterQuality(kLow_SkFilterQuality);
96
97 const SkRect cull = this->getBounds();
98 const SkColor* colorsPtr = fUseColors ? colors : NULL;
99
100 canvas->drawLitAtlas(fAtlas, xforms, fDiffTex, fNormTex, colorsPtr, kNum Asteroids+1,
101 SkXfermode::kModulate_Mode, &cull, &paint, fLights) ;
102 #else
103 SkMatrix diffMat, normalMat;
104
105 for (int i = 0; i < kNumAsteroids+1; ++i) {
106 colors[i] = colors[i] & 0xFF000000; // to silence compilers
107 SkPaint paint;
108
109 SkRect r = fDiffTex[i];
110 r.offsetTo(0, 0);
111
112 diffMat.setRectToRect(fDiffTex[i], r, SkMatrix::kFill_ScaleToFit);
113 normalMat.setRectToRect(fNormTex[i], r, SkMatrix::kFill_ScaleToFit);
114
115 SkMatrix m;
116 m.setRSXform(xforms[i]);
117
118 // TODO: correctly pull out the pure rotation
119 SkVector invNormRotation = { m[SkMatrix::kMScaleX], m[SkMatrix::kMSk ewY] };
120
121 paint.setShader(SkLightingShader::Make(fAtlas, fAtlas, fLights,
122 invNormRotation, &diffMat, &n ormalMat));
123
124 canvas->save();
125 canvas->setMatrix(m);
126 canvas->drawRect(r, paint);
127 canvas->restore();
128 }
129 #endif
130
131 #ifdef SK_DEBUG
132 {
133 SkPaint paint;
134 paint.setColor(SK_ColorRED);
135
136 for (int i = 0; i < kNumAsteroids; ++i) {
137 canvas->drawCircle(fAsteroids[i].pos().x(), fAsteroids[i].pos(). y(), 2, paint);
138 }
139 canvas->drawCircle(fShip.pos().x(), fShip.pos().y(), 2, paint);
140
141 paint.setStyle(SkPaint::kStroke_Style);
142 canvas->drawRect(this->getBounds(), paint);
143 }
144 #endif
145 }
146
147 SkRect onGetBounds() override {
148 return fBounds;
149 }
150
151 private:
152
153 enum ObjType {
154 kBigAsteroid_ObjType = 0,
155 kMedAsteroid_ObjType,
156 kSmAsteroid_ObjType,
157 kShip_ObjType,
158
159 kLast_ObjType = kShip_ObjType
160 };
161
162 static const int kObjTypeCount = kLast_ObjType + 1;
163
164 // Create the mixed diffuse & normal atlas
165 //
166 // big color circle | big normal hemi
167 // ------------------------------------
168 // med color circle | med normal pyra
169 // ------------------------------------
170 // sm color circle | sm normal hemi
171 // ------------------------------------
172 // big ship | big tetra normal
173 static SkBitmap MakeAtlas() {
174
175 SkBitmap atlas;
176 atlas.allocN32Pixels(kAtlasWidth, kAtlasHeight);
177
178 for (int y = 0; y < kAtlasHeight; ++y) {
179 int x = 0;
180 for ( ; x < kBigSize+kPad; ++x) {
181 *atlas.getAddr32(x, y) = SK_ColorTRANSPARENT;
182 }
183 for ( ; x < kAtlasWidth; ++x) {
184 *atlas.getAddr32(x, y) = SkPackARGB32(0xFF, 0x88, 0x88, 0xFF);
185 }
186 }
187
188 // big asteroid
189 {
190 SkPoint bigCenter = SkPoint::Make(kDiffXOff + kBigSize/2.0f, kBigYOf f + kBigSize/2.0f);
191
192 for (int y = kBigYOff; y < kBigYOff+kBigSize; ++y) {
193 for (int x = kDiffXOff; x < kDiffXOff+kBigSize; ++x) {
194 SkScalar distSq = (x - bigCenter.fX) * (x - bigCenter.fX) +
195 (y - bigCenter.fY) * (y - bigCenter.fY);
196 if (distSq > kBigSize*kBigSize/4.0f) {
197 *atlas.getAddr32(x, y) = SkPreMultiplyARGB(0, 0, 0, 0);
198 } else {
199 *atlas.getAddr32(x, y) = SkPackARGB32(0xFF, 0xFF, 0, 0);
200 }
201 }
202 }
203
204 sk_tool_utils::create_hemi_normal_map(&atlas,
205 SkIRect::MakeXYWH(kNormXOff, k BigYOff,
206 kBigSize, kB igSize));
207 }
208
209 // medium asteroid
210 {
211 for (int y = kMedYOff; y < kMedYOff+kMedSize; ++y) {
212 for (int x = kDiffXOff; x < kDiffXOff+kMedSize; ++x) {
213 *atlas.getAddr32(x, y) = SkPackARGB32(0xFF, 0, 0xFF, 0);
214 }
215 }
216
217 sk_tool_utils::create_frustum_normal_map(&atlas,
218 SkIRect::MakeXYWH(kNormXOff , kMedYOff,
219 kMedSize, kMedSize));
220 }
221
222 // small asteroid
223 {
224 SkPoint smCenter = SkPoint::Make(kDiffXOff + kSmSize/2.0f, kSmYOff + kSmSize/2.0f);
225
226 for (int y = kSmYOff; y < kSmYOff+kSmSize; ++y) {
227 for (int x = kDiffXOff; x < kDiffXOff+kSmSize; ++x) {
228 SkScalar distSq = (x - smCenter.fX) * (x - smCenter.fX) +
229 (y - smCenter.fY) * (y - smCenter.fY);
230 if (distSq > kSmSize*kSmSize/4.0f) {
231 *atlas.getAddr32(x, y) = SkPreMultiplyARGB(0, 0, 0, 0);
232 } else {
233 *atlas.getAddr32(x, y) = SkPackARGB32(0xFF, 0, 0, 0xFF);
234 }
235 }
236 }
237
238 sk_tool_utils::create_hemi_normal_map(&atlas,
239 SkIRect::MakeXYWH(kNormXOff, k SmYOff,
240 kSmSize, kSm Size));
241 }
242
243 // ship
244 {
245 SkScalar shipMidLine = kDiffXOff + kMedSize/2.0f;
246
247 for (int y = kShipYOff; y < kShipYOff+kMedSize; ++y) {
248 SkScalar scaledY = (y - kShipYOff)/(float)kMedSize; // 0..1
249
250 for (int x = kDiffXOff; x < kDiffXOff+kMedSize; ++x) {
251 SkScalar scaledX;
252
253 if (x < shipMidLine) {
254 scaledX = 1.0f - (x - kDiffXOff)/(kMedSize/2.0f); // 0.. 1
255 } else {
256 scaledX = (x - shipMidLine)/(kMedSize/2.0f); // 0.. 1
257 }
258
259 if (scaledX < scaledY) {
260 *atlas.getAddr32(x, y) = SkPackARGB32(0xFF, 0, 0xFF, 0xF F);
261 } else {
262 *atlas.getAddr32(x, y) = SkPackARGB32(0, 0, 0, 0);
263 }
264 }
265 }
266
267 sk_tool_utils::create_tetra_normal_map(&atlas,
268 SkIRect::MakeXYWH(kNormXOff, kShipYOff,
269 kMedSize, k MedSize));
270 }
271
272 return atlas;
273 }
274
275 class ObjectRecord {
276 public:
277 void initAsteroid(SkRandom *rand, const SkRect& bounds,
278 SkRect* diffTex, SkRect* normTex) {
279 static const SkScalar gMaxSpeeds[3] = { 1, 2, 5 }; // smaller astero ids can go faster
280 static const SkScalar gYOffs[3] = { kBigYOff, kMedYOff, kSmYOff };
281 static const SkScalar gSizes[3] = { kBigSize, kMedSize, kSmSize };
282
283 static unsigned int asteroidType = 0;
284 fObjType = static_cast<ObjType>(asteroidType++ % 3);
285
286 fPosition.set(bounds.fLeft + rand->nextUScalar1() * bounds.width(),
287 bounds.fTop + rand->nextUScalar1() * bounds.height());
288 fVelocity.fX = rand->nextSScalar1();
289 fVelocity.fY = sqrt(1.0f - fVelocity.fX * fVelocity.fX);
290 SkASSERT(SkScalarNearlyEqual(fVelocity.length(), 1.0f));
291 fVelocity *= gMaxSpeeds[fObjType];
292 fRot = 0;
293 fDeltaRot = rand->nextSScalar1() / 32;
294
295 diffTex->setXYWH(SkIntToScalar(kDiffXOff), gYOffs[fObjType],
296 gSizes[fObjType], gSizes[fObjType]);
297 normTex->setXYWH(SkIntToScalar(kNormXOff), gYOffs[fObjType],
298 gSizes[fObjType], gSizes[fObjType]);
299 }
300
301 void initShip(const SkRect& bounds, SkRect* diffTex, SkRect* normTex) {
302 fObjType = kShip_ObjType;
303 fPosition.set(bounds.centerX(), bounds.centerY());
304 fVelocity = SkVector::Make(0.0f, 0.0f);
305 fRot = 0.0f;
306 fDeltaRot = 0.0f;
307
308 diffTex->setXYWH(SkIntToScalar(kDiffXOff), SkIntToScalar(kShipYOff),
309 SkIntToScalar(kMedSize), SkIntToScalar(kMedSize));
310 normTex->setXYWH(SkIntToScalar(kNormXOff), SkIntToScalar(kShipYOff),
311 SkIntToScalar(kMedSize), SkIntToScalar(kMedSize));
312 }
313
314 void advance(const SkRect& bounds) {
315 fPosition += fVelocity;
316 if (fPosition.fX > bounds.right()) {
317 SkASSERT(fVelocity.fX > 0);
318 fVelocity.fX = -fVelocity.fX;
319 } else if (fPosition.fX < bounds.left()) {
320 SkASSERT(fVelocity.fX < 0);
321 fVelocity.fX = -fVelocity.fX;
322 }
323 if (fPosition.fY > bounds.bottom()) {
324 if (fVelocity.fY > 0) {
325 fVelocity.fY = -fVelocity.fY;
326 }
327 } else if (fPosition.fY < bounds.top()) {
328 if (fVelocity.fY < 0) {
329 fVelocity.fY = -fVelocity.fY;
330 }
331 }
332
333 fRot += fDeltaRot;
334 fRot = SkScalarMod(fRot, 2 * SK_ScalarPI);
335 }
336
337 const SkPoint& pos() const { return fPosition; }
338
339 SkScalar rot() const { return fRot; }
340 void setRot(SkScalar rot) { fRot = rot; }
341
342 const SkPoint& velocity() const { return fVelocity; }
343 void setVelocity(const SkPoint& velocity) { fVelocity = velocity; }
344
345 SkRSXform asRSXform() const {
346 static const SkScalar gHalfSizes[kObjTypeCount] = {
347 SkScalarHalf(kBigSize),
348 SkScalarHalf(kMedSize),
349 SkScalarHalf(kSmSize),
350 SkScalarHalf(kMedSize),
351 };
352
353 return SkRSXform::MakeFromRadians(1.0f, fRot, fPosition.x(), fPositi on.y(),
354 gHalfSizes[fObjType],
355 gHalfSizes[fObjType]);
356 }
357
358 private:
359 ObjType fObjType;
360 SkPoint fPosition;
361 SkVector fVelocity;
362 SkScalar fRot; // In radians.
363 SkScalar fDeltaRot; // In radiands. Not used by ship.
364 };
365
366
367
368
369 private:
370 static const int kNumLights = 2;
371 static const int kNumAsteroids = 6;
372 static const int kNumShips = 1;
373
374 static const int kBigSize = 128;
375 static const int kMedSize = 64;
376 static const int kSmSize = 32;
377 static const int kPad = 1;
378 static const int kAtlasWidth = kBigSize + kBigSize + 2 * kPad; // 2 pads in the middle
379 static const int kAtlasHeight = kBigSize + kMedSize + kSmSize + kMedSize + 3 * kPad;
380
381 static const int kDiffXOff = 0;
382 static const int kNormXOff = kBigSize + 2 * kPad;
383
384 static const int kBigYOff = 0;
385 static const int kMedYOff = kBigSize + kPad;
386 static const int kSmYOff = kMedYOff + kMedSize + kPad;
387 static const int kShipYOff = kSmYOff + kSmSize + kPad;
388
389 SkBitmap fAtlas;
390 ObjectRecord fAsteroids[kNumAsteroids];
391 ObjectRecord fShip;
392 SkRect fDiffTex[kNumAsteroids+kNumShips];
393 SkRect fNormTex[kNumAsteroids+kNumShips];
394 SkRect fBounds;
395 bool fUseColors;
396 sk_sp<SkLights> fLights;
397
398 typedef SkDrawable INHERITED;
399 };
400
401 class DrawLitAtlasView : public SampleView {
402 public:
403 DrawLitAtlasView()
404 : fDrawable(new DrawLitAtlasDrawable(SkRect::MakeWH(640, 480))) {
405 }
406
407 protected:
408 bool onQuery(SkEvent* evt) override {
409 if (SampleCode::TitleQ(*evt)) {
410 SampleCode::TitleR(evt, "DrawLitAtlas");
411 return true;
412 }
413 SkUnichar uni;
414 if (SampleCode::CharQ(*evt, &uni)) {
415 switch (uni) {
416 case 'C':
417 fDrawable->toggleUseColors();
418 this->inval(NULL);
419 return true;
420 case 'j':
421 fDrawable->left();
422 this->inval(NULL);
423 return true;
424 case 'k':
425 fDrawable->thrust();
426 this->inval(NULL);
427 return true;
428 case 'l':
429 fDrawable->right();
430 this->inval(NULL);
431 return true;
432 default:
433 break;
434 }
435 }
436 return this->INHERITED::onQuery(evt);
437 }
438
439 void onDrawContent(SkCanvas* canvas) override {
440 canvas->drawDrawable(fDrawable);
441 this->inval(NULL);
442 }
443
444 #if 0
445 // TODO: switch over to use this for our animation
446 bool onAnimate(const SkAnimTimer& timer) override {
447 SkScalar angle = SkDoubleToScalar(fmod(timer.secs() * 360 / 24, 360));
448 fAnimatingDrawable->setSweep(angle);
449 return true;
450 }
451 #endif
452
453 private:
454 SkAutoTUnref<DrawLitAtlasDrawable> fDrawable;
455
456 typedef SampleView INHERITED;
457 };
458
459 //////////////////////////////////////////////////////////////////////////////
460
461 static SkView* MyFactory() { return new DrawLitAtlasView; }
462 static SkViewRegister reg(MyFactory);
OLDNEW
« include/core/SkLights.h ('K') | « include/core/SkLights.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698