blob: 37eec18ba43a120f591b20d6863f01480b453e7d [file] [log] [blame]
vjiaoblack955e8792016-08-05 07:55:01 -07001/*
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 "SkPictureRecorder.h"
10#include "SkShadowPaintFilterCanvas.h"
11#include "SkShadowShader.h"
12#include "SkSurface.h"
13
14#ifdef SK_EXPERIMENTAL_SHADOWING
15
vjiaoblack955e8792016-08-05 07:55:01 -070016class ShadowingView : public SampleView {
17public:
18 ShadowingView() {
19
20 this->setBGColor(0xFFCCCCCC);
21 SkLights::Builder builder;
vjiaoblack772b5ee2016-08-12 11:38:47 -070022 builder.add(SkLights::Light::MakeDirectional(SkColor3f::Make(0.2f, 0.3f, 0.4f),
23 SkVector3::Make(0.2f, 0.05f, 1.0f)));
24 builder.add(SkLights::Light::MakeDirectional(SkColor3f::Make(0.4f, 0.3f, 0.2f),
25 SkVector3::Make(0.05f, 0.2f, 1.0f)));
26 builder.add(SkLights::Light::MakeAmbient(SkColor3f::Make(0.4f, 0.4f, 0.4f)));
vjiaoblack955e8792016-08-05 07:55:01 -070027 fLights = builder.finish();
28
29 fTestRects[0].fColor = 0xFFEE8888;
30 fTestRects[0].fDepth = 80;
31 fTestRects[0].fGeometry = SkRect::MakeLTRB(200,150,350,300);
32
33 fTestRects[1].fColor = 0xFF88EE88;
34 fTestRects[1].fDepth = 160;
35 fTestRects[1].fGeometry = SkRect::MakeLTRB(150,200,300,350);
36
37 fTestRects[2].fColor = 0xFF8888EE;
38 fTestRects[2].fDepth = 240;
39 fTestRects[2].fGeometry = SkRect::MakeLTRB(100,100,250,250);
40
41 fSceneChanged = true;
42 fLightsChanged = true;
43
44 fSelectedRect = -1;
45 fMoveLight = false;
vjiaoblack904527d2016-08-09 09:32:09 -070046
47 fClearShadowMaps = false;
vjiaoblack955e8792016-08-05 07:55:01 -070048 }
49
50protected:
51 bool onQuery(SkEvent *evt) override {
52 if (SampleCode::TitleQ(*evt)) {
53 SampleCode::TitleR(evt, "shadowing");
54 return true;
55 }
56
57 SkUnichar uni;
58 if (SampleCode::CharQ(*evt, &uni)) {
59 switch (uni) {
60 case 'L':
61 fMoveLight = !fMoveLight;
62 break;
vjiaoblack904527d2016-08-09 09:32:09 -070063 case 'd':
64 // Raster generated shadow maps have their origin in the UL corner
65 // GPU shadow maps can have an arbitrary origin.
66 // We override the 'd' keypress so that when the device is cycled,
67 // the shadow maps will be re-generated according to the new backend.
68 fClearShadowMaps = true;
69 break;
vjiaoblack955e8792016-08-05 07:55:01 -070070 default:
71 break;
72 }
73 }
74 return this->INHERITED::onQuery(evt);
75 }
76
77 sk_sp<SkPicture> makeTestPicture(int width, int height) {
78 SkPictureRecorder recorder;
79
80 // LONG RANGE TODO: eventually add SkBBHFactory (bounding box factory)
81 SkCanvas* canvas = recorder.beginRecording(SkRect::MakeIWH(width, height));
82
83 SkASSERT(canvas->getTotalMatrix().isIdentity());
84 SkPaint paint;
85 paint.setColor(SK_ColorGRAY);
86
87 // LONG RANGE TODO: tag occluders
88 // LONG RANGE TODO: track number of IDs we need (hopefully less than 256)
89 // and determinate the mapping from z to id
90
91 // universal receiver, "ground"
92 canvas->drawRect(SkRect::MakeIWH(width, height), paint);
93
94 for (int i = 0; i < kNumTestRects; i++) {
95 paint.setColor(fTestRects[i].fColor);
96 if (i == 0) {
97 canvas->translateZ(fTestRects[0].fDepth);
98 } else {
99 canvas->translateZ(fTestRects[i].fDepth - fTestRects[i-1].fDepth);
100 }
101 canvas->drawRect(fTestRects[i].fGeometry, paint);
102 }
103
104 return recorder.finishRecordingAsPicture();
105 }
106
vjiaoblack955e8792016-08-05 07:55:01 -0700107 void onDrawContent(SkCanvas *canvas) override {
vjiaoblack904527d2016-08-09 09:32:09 -0700108 if (fSceneChanged) {
vjiaoblack955e8792016-08-05 07:55:01 -0700109 fPicture = this->makeTestPicture(kWidth, kHeight);
vjiaoblack955e8792016-08-05 07:55:01 -0700110 }
111
vjiaoblack904527d2016-08-09 09:32:09 -0700112 if (fSceneChanged || fLightsChanged || fClearShadowMaps) {
113 for (int i = 0; i < fLights->numLights(); i++) {
114 fLights->light(i).setShadowMap(nullptr);
115 }
116 fSceneChanged = false;
117 fLightsChanged = false;
118 fClearShadowMaps = false;
vjiaoblack955e8792016-08-05 07:55:01 -0700119 }
vjiaoblackd707f2d2016-08-16 05:38:45 -0700120
121 canvas->setLights(fLights);
122 canvas->drawShadowedPicture(fPicture, nullptr, nullptr);
vjiaoblack955e8792016-08-05 07:55:01 -0700123 }
124
125 SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
126 return new SkView::Click(this);
127 }
128
129 bool onClick(Click *click) override {
130 SkScalar x = click->fCurr.fX;
131 SkScalar y = click->fCurr.fY;
132
133 SkScalar dx = x - click->fPrev.fX;
134 SkScalar dy = y - click->fPrev.fY;
135
136 if (fMoveLight) {
137 if (dx != 0 || dy != 0) {
138 float recipX = 1.0f / kWidth;
139 float recipY = 1.0f / kHeight;
140
141 SkLights::Builder builder;
vjiaoblack772b5ee2016-08-12 11:38:47 -0700142 builder.add(SkLights::Light::MakeDirectional(
143 SkColor3f::Make(0.2f, 0.3f, 0.4f),
144 SkVector3::Make(0.2f + (200.0f - x) * recipX,
145 0.05f + (200.0f - y) * recipY,
146 1.0f)));
147 builder.add(SkLights::Light::MakeDirectional(
148 SkColor3f::Make(0.4f, 0.3f, 0.2f),
149 SkVector3::Make(0.05f + (200.0f - x) * recipX,
150 0.2f + (200.0f - y) * recipY,
151 1.0f)));
152 builder.add(SkLights::Light::MakeAmbient(
153 SkColor3f::Make(0.4f, 0.4f, 0.4f)));
vjiaoblack955e8792016-08-05 07:55:01 -0700154 fLights = builder.finish();
155
156 fLightsChanged = true;
157 this->inval(nullptr);
158 }
159 return true;
160 }
161
162 if (click->fState == Click::State::kUp_State) {
163 fSelectedRect = -1;
164 return true;
165 }
166
167 if (fSelectedRect > -1) {
168 fTestRects[fSelectedRect].fGeometry.offset(dx, dy);
169
170 fSceneChanged = true;
171 this->inval(nullptr);
172 return true;
173 }
174
175 // assume last elements are highest
176 for (int i = kNumTestRects - 1; i >= 0; i--) {
177 if (fTestRects[i].fGeometry.contains(SkRect::MakeXYWH(x, y, 1, 1))) {
178 fSelectedRect = i;
179 fTestRects[i].fGeometry.offset(dx, dy);
180
181 fSceneChanged = true;
182 this->inval(nullptr);
183 break;
184 }
185 }
186
187 return true;
188 }
189
190private:
191 static constexpr int kNumTestRects = 3;
192
193 static const int kWidth = 400;
194 static const int kHeight = 400;
vjiaoblack904527d2016-08-09 09:32:09 -0700195 bool fClearShadowMaps;
vjiaoblack955e8792016-08-05 07:55:01 -0700196
197 struct {
198 SkRect fGeometry;
199 int fDepth;
200 SkColor fColor;
201 } fTestRects[kNumTestRects];
202
203 int fSelectedRect;
204 bool fMoveLight;
205
vjiaoblack955e8792016-08-05 07:55:01 -0700206 sk_sp<SkPicture> fPicture;
vjiaoblack955e8792016-08-05 07:55:01 -0700207
208 bool fSceneChanged;
209 bool fLightsChanged;
210
211 sk_sp<SkLights> fLights;
212
213 typedef SampleView INHERITED;
214};
215
216//////////////////////////////////////////////////////////////////////////////
217static SkView* MyFactory() { return new ShadowingView; }
218static SkViewRegister reg(MyFactory);
219
220#endif