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

Side by Side Diff: samplecode/SampleLitAtlas.cpp

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

Powered by Google App Engine
This is Rietveld 408576698