OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SampleCode.h" | 8 #include "SampleCode.h" |
9 #include "SkAnimTimer.h" | 9 #include "SkAnimTimer.h" |
10 #include "SkView.h" | 10 #include "SkView.h" |
11 #include "SkCanvas.h" | 11 #include "SkCanvas.h" |
12 #include "SkDrawable.h" | 12 #include "SkDrawable.h" |
13 #include "SkLightingShader.h" | 13 #include "SkLightingShader.h" |
14 #include "SkLights.h" | 14 #include "SkLights.h" |
15 #include "SkRandom.h" | 15 #include "SkRandom.h" |
16 #include "SkRSXform.h" | 16 #include "SkRSXform.h" |
17 | 17 |
18 #include "sk_tool_utils.h" | 18 #include "sk_tool_utils.h" |
19 | 19 |
20 class DrawLitAtlasDrawable : public SkDrawable { | 20 class DrawLitAtlasDrawable : public SkDrawable { |
21 public: | 21 public: |
22 DrawLitAtlasDrawable(const SkRect& r) | 22 DrawLitAtlasDrawable(const SkRect& r) |
23 : fBounds(r) | 23 : fBounds(r) |
24 , fUseColors(false) { | 24 , fUseColors(false) |
| 25 , fLightDir(SkVector3::Make(1.0f, 0.0f, 0.0f)) { |
25 fAtlas = MakeAtlas(); | 26 fAtlas = MakeAtlas(); |
26 | 27 |
27 SkRandom rand; | 28 SkRandom rand; |
28 for (int i = 0; i < kNumAsteroids; ++i) { | 29 for (int i = 0; i < kNumAsteroids; ++i) { |
29 fAsteroids[i].initAsteroid(&rand, fBounds, &fDiffTex[i], &fNormTex[i
]); | 30 fAsteroids[i].initAsteroid(&rand, fBounds, &fDiffTex[i], &fNormTex[i
]); |
30 } | 31 } |
31 | 32 |
32 fShip.initShip(fBounds, &fDiffTex[kNumAsteroids], &fNormTex[kNumAsteroid
s]); | 33 fShip.initShip(fBounds, &fDiffTex[kNumAsteroids], &fNormTex[kNumAsteroid
s]); |
33 | 34 |
34 SkLights::Builder builder; | 35 this->updateLights(); |
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 } | 36 } |
42 | 37 |
43 void toggleUseColors() { | 38 void toggleUseColors() { |
44 fUseColors = !fUseColors; | 39 fUseColors = !fUseColors; |
45 } | 40 } |
46 | 41 |
| 42 void rotateLight() { |
| 43 SkScalar c; |
| 44 SkScalar s = SkScalarSinCos(SK_ScalarPI/6.0f, &c); |
| 45 |
| 46 SkScalar newX = c * fLightDir.fX - s * fLightDir.fY; |
| 47 SkScalar newY = s * fLightDir.fX + c * fLightDir.fY; |
| 48 |
| 49 fLightDir.set(newX, newY, 0.0f); |
| 50 |
| 51 this->updateLights(); |
| 52 } |
| 53 |
47 void left() { | 54 void left() { |
48 SkScalar newRot = SkScalarMod(fShip.rot() + (2*SK_ScalarPI - SK_ScalarPI
/32.0f), | 55 SkScalar newRot = SkScalarMod(fShip.rot() + (2*SK_ScalarPI - SK_ScalarPI
/32.0f), |
49 2 * SK_ScalarPI); | 56 2 * SK_ScalarPI); |
50 fShip.setRot(newRot); | 57 fShip.setRot(newRot); |
51 } | 58 } |
52 | 59 |
53 void right() { | 60 void right() { |
54 SkScalar newRot = SkScalarMod(fShip.rot() + SK_ScalarPI/32.0f, 2 * SK_Sc
alarPI); | 61 SkScalar newRot = SkScalarMod(fShip.rot() + SK_ScalarPI/32.0f, 2 * SK_Sc
alarPI); |
55 fShip.setRot(newRot); | 62 fShip.setRot(newRot); |
56 } | 63 } |
(...skipping 27 matching lines...) Expand all Loading... |
84 } | 91 } |
85 | 92 |
86 fShip.advance(fBounds); | 93 fShip.advance(fBounds); |
87 xforms[kNumAsteroids] = fShip.asRSXform(); | 94 xforms[kNumAsteroids] = fShip.asRSXform(); |
88 if (fUseColors) { | 95 if (fUseColors) { |
89 colors[kNumAsteroids] = SkColorSetARGB(0xFF, 0xFF, 0xFF, 0xFF); | 96 colors[kNumAsteroids] = SkColorSetARGB(0xFF, 0xFF, 0xFF, 0xFF); |
90 } | 97 } |
91 | 98 |
92 #ifdef SK_DEBUG | 99 #ifdef SK_DEBUG |
93 canvas->drawBitmap(fAtlas, 0, 0); // just to see the atlas | 100 canvas->drawBitmap(fAtlas, 0, 0); // just to see the atlas |
94 #endif | 101 |
| 102 this->drawLightDir(canvas, fBounds.centerX(), fBounds.centerY()); |
| 103 #endif |
95 | 104 |
96 #if 0 | 105 #if 0 |
97 // TODO: revitalize when drawLitAtlas API lands | 106 // TODO: revitalize when drawLitAtlas API lands |
98 SkPaint paint; | 107 SkPaint paint; |
99 paint.setFilterQuality(kLow_SkFilterQuality); | 108 paint.setFilterQuality(kLow_SkFilterQuality); |
100 | 109 |
101 const SkRect cull = this->getBounds(); | 110 const SkRect cull = this->getBounds(); |
102 const SkColor* colorsPtr = fUseColors ? colors : NULL; | 111 const SkColor* colorsPtr = fUseColors ? colors : NULL; |
103 | 112 |
104 canvas->drawLitAtlas(fAtlas, xforms, fDiffTex, fNormTex, colorsPtr, kNum
Asteroids+1, | 113 canvas->drawLitAtlas(fAtlas, xforms, fDiffTex, fNormTex, colorsPtr, kNum
Asteroids+1, |
105 SkXfermode::kModulate_Mode, &cull, &paint, fLights)
; | 114 SkXfermode::kModulate_Mode, &cull, &paint, fLights)
; |
106 #else | 115 #else |
107 SkMatrix diffMat, normalMat; | 116 SkMatrix diffMat, normalMat; |
108 | 117 |
109 for (int i = 0; i < kNumAsteroids+1; ++i) { | 118 for (int i = 0; i < kNumAsteroids+1; ++i) { |
110 colors[i] = colors[i] & 0xFF000000; // to silence compilers | 119 colors[i] = colors[i] & 0xFF000000; // to silence compilers |
111 SkPaint paint; | 120 SkPaint paint; |
112 | 121 |
113 SkRect r = fDiffTex[i]; | 122 SkRect r = fDiffTex[i]; |
114 r.offsetTo(0, 0); | 123 r.offsetTo(0, 0); |
115 | 124 |
116 diffMat.setRectToRect(fDiffTex[i], r, SkMatrix::kFill_ScaleToFit); | 125 diffMat.setRectToRect(fDiffTex[i], r, SkMatrix::kFill_ScaleToFit); |
117 normalMat.setRectToRect(fNormTex[i], r, SkMatrix::kFill_ScaleToFit); | 126 normalMat.setRectToRect(fNormTex[i], r, SkMatrix::kFill_ScaleToFit); |
118 | 127 |
119 SkMatrix m; | 128 SkMatrix m; |
120 m.setRSXform(xforms[i]); | 129 m.setRSXform(xforms[i]); |
121 | 130 |
122 // TODO: correctly pull out the pure rotation | 131 // TODO: correctly pull out the pure rotation |
123 SkVector invNormRotation = { m[SkMatrix::kMScaleX], m[SkMatrix::kMSk
ewY] }; | 132 SkVector invNormRotation = { m[SkMatrix::kMScaleX], m[SkMatrix::kMSk
ewY] }; |
| 133 SkASSERT(SkScalarNearlyEqual(invNormRotation.lengthSqd(), SK_Scalar1
)); |
124 | 134 |
125 paint.setShader(SkLightingShader::Make(fAtlas, fAtlas, fLights, | 135 paint.setShader(SkLightingShader::Make(fAtlas, fAtlas, fLights, |
126 invNormRotation, &diffMat, &n
ormalMat)); | 136 invNormRotation, &diffMat, &n
ormalMat)); |
127 | 137 |
128 canvas->save(); | 138 canvas->save(); |
129 canvas->setMatrix(m); | 139 canvas->setMatrix(m); |
130 canvas->drawRect(r, paint); | 140 canvas->drawRect(r, paint); |
131 canvas->restore(); | 141 canvas->restore(); |
132 } | 142 } |
133 #endif | 143 #endif |
(...skipping 24 matching lines...) Expand all Loading... |
158 kBigAsteroid_ObjType = 0, | 168 kBigAsteroid_ObjType = 0, |
159 kMedAsteroid_ObjType, | 169 kMedAsteroid_ObjType, |
160 kSmAsteroid_ObjType, | 170 kSmAsteroid_ObjType, |
161 kShip_ObjType, | 171 kShip_ObjType, |
162 | 172 |
163 kLast_ObjType = kShip_ObjType | 173 kLast_ObjType = kShip_ObjType |
164 }; | 174 }; |
165 | 175 |
166 static const int kObjTypeCount = kLast_ObjType + 1; | 176 static const int kObjTypeCount = kLast_ObjType + 1; |
167 | 177 |
| 178 void updateLights() { |
| 179 SkLights::Builder builder; |
| 180 |
| 181 builder.add(SkLights::Light(SkColor3f::Make(1.0f, 1.0f, 1.0f), fLightDir
)); |
| 182 builder.add(SkLights::Light(SkColor3f::Make(0.2f, 0.2f, 0.2f))); |
| 183 |
| 184 fLights = builder.finish(); |
| 185 } |
| 186 |
| 187 #ifdef SK_DEBUG |
| 188 // Draw a vector to the light |
| 189 void drawLightDir(SkCanvas* canvas, SkScalar centerX, SkScalar centerY) { |
| 190 static const int kBgLen = 30; |
| 191 static const int kSmLen = 5; |
| 192 |
| 193 // TODO: change the lighting coordinate system to be right handed |
| 194 SkPoint p1 = SkPoint::Make(centerX + kBgLen * fLightDir.fX, |
| 195 centerY - kBgLen * fLightDir.fY); |
| 196 SkPoint p2 = SkPoint::Make(centerX + (kBgLen-kSmLen) * fLightDir.fX, |
| 197 centerY - (kBgLen-kSmLen) * fLightDir.fY); |
| 198 |
| 199 SkPaint p; |
| 200 canvas->drawLine(centerX, centerY, p1.fX, p1.fY, p); |
| 201 canvas->drawLine(p1.fX, p1.fY, |
| 202 p2.fX - kSmLen * fLightDir.fY, p2.fY - kSmLen * fLightD
ir.fX, p); |
| 203 canvas->drawLine(p1.fX, p1.fY, |
| 204 p2.fX + kSmLen * fLightDir.fY, p2.fY + kSmLen * fLightD
ir.fX, p); |
| 205 } |
| 206 #endif |
| 207 |
168 // Create the mixed diffuse & normal atlas | 208 // Create the mixed diffuse & normal atlas |
169 // | 209 // |
170 // big color circle | big normal hemi | 210 // big color circle | big normal hemi |
171 // ------------------------------------ | 211 // ------------------------------------ |
172 // med color circle | med normal pyra | 212 // med color circle | med normal pyra |
173 // ------------------------------------ | 213 // ------------------------------------ |
174 // sm color circle | sm normal hemi | 214 // sm color circle | sm normal hemi |
175 // ------------------------------------ | 215 // ------------------------------------ |
176 // big ship | big tetra normal | 216 // big ship | big tetra normal |
177 static SkBitmap MakeAtlas() { | 217 static SkBitmap MakeAtlas() { |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
391 static const int kShipYOff = kSmYOff + kSmSize + kPad; | 431 static const int kShipYOff = kSmYOff + kSmSize + kPad; |
392 static const int kMaxShipSpeed = 5; | 432 static const int kMaxShipSpeed = 5; |
393 | 433 |
394 SkBitmap fAtlas; | 434 SkBitmap fAtlas; |
395 ObjectRecord fAsteroids[kNumAsteroids]; | 435 ObjectRecord fAsteroids[kNumAsteroids]; |
396 ObjectRecord fShip; | 436 ObjectRecord fShip; |
397 SkRect fDiffTex[kNumAsteroids+kNumShips]; | 437 SkRect fDiffTex[kNumAsteroids+kNumShips]; |
398 SkRect fNormTex[kNumAsteroids+kNumShips]; | 438 SkRect fNormTex[kNumAsteroids+kNumShips]; |
399 SkRect fBounds; | 439 SkRect fBounds; |
400 bool fUseColors; | 440 bool fUseColors; |
| 441 SkVector3 fLightDir; |
401 sk_sp<SkLights> fLights; | 442 sk_sp<SkLights> fLights; |
402 | 443 |
403 typedef SkDrawable INHERITED; | 444 typedef SkDrawable INHERITED; |
404 }; | 445 }; |
405 | 446 |
406 class DrawLitAtlasView : public SampleView { | 447 class DrawLitAtlasView : public SampleView { |
407 public: | 448 public: |
408 DrawLitAtlasView() | 449 DrawLitAtlasView() |
409 : fDrawable(new DrawLitAtlasDrawable(SkRect::MakeWH(640, 480))) { | 450 : fDrawable(new DrawLitAtlasDrawable(SkRect::MakeWH(640, 480))) { |
410 } | 451 } |
(...skipping 16 matching lines...) Expand all Loading... |
427 this->inval(NULL); | 468 this->inval(NULL); |
428 return true; | 469 return true; |
429 case 'k': | 470 case 'k': |
430 fDrawable->thrust(); | 471 fDrawable->thrust(); |
431 this->inval(NULL); | 472 this->inval(NULL); |
432 return true; | 473 return true; |
433 case 'l': | 474 case 'l': |
434 fDrawable->right(); | 475 fDrawable->right(); |
435 this->inval(NULL); | 476 this->inval(NULL); |
436 return true; | 477 return true; |
| 478 case 'o': |
| 479 fDrawable->rotateLight(); |
| 480 this->inval(NULL); |
| 481 return true; |
437 default: | 482 default: |
438 break; | 483 break; |
439 } | 484 } |
440 } | 485 } |
441 return this->INHERITED::onQuery(evt); | 486 return this->INHERITED::onQuery(evt); |
442 } | 487 } |
443 | 488 |
444 void onDrawContent(SkCanvas* canvas) override { | 489 void onDrawContent(SkCanvas* canvas) override { |
445 canvas->drawDrawable(fDrawable); | 490 canvas->drawDrawable(fDrawable); |
446 this->inval(NULL); | 491 this->inval(NULL); |
(...skipping 11 matching lines...) Expand all Loading... |
458 private: | 503 private: |
459 SkAutoTUnref<DrawLitAtlasDrawable> fDrawable; | 504 SkAutoTUnref<DrawLitAtlasDrawable> fDrawable; |
460 | 505 |
461 typedef SampleView INHERITED; | 506 typedef SampleView INHERITED; |
462 }; | 507 }; |
463 | 508 |
464 ////////////////////////////////////////////////////////////////////////////// | 509 ////////////////////////////////////////////////////////////////////////////// |
465 | 510 |
466 static SkView* MyFactory() { return new DrawLitAtlasView; } | 511 static SkView* MyFactory() { return new DrawLitAtlasView; } |
467 static SkViewRegister reg(MyFactory); | 512 static SkViewRegister reg(MyFactory); |
OLD | NEW |