blob: 929d62ba7ef3e62db71c726dc4f0dab9a8cfc035 [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:
vjiaoblack56f33ea2016-08-26 08:49:46 -070018 ShadowingView()
19 : fSceneChanged(true)
20 , fLightsChanged(true)
21 , fMoveLight(false)
22 , fClearShadowMaps(false)
23 , fSelectedRectID(-1)
24 , fSelectedSliderID(-1)
vjiaoblack1e5abf12016-09-07 07:48:12 -070025 , fLightDepth(400.0f) {
vjiaoblack955e8792016-08-05 07:55:01 -070026 this->setBGColor(0xFFCCCCCC);
vjiaoblack56f33ea2016-08-26 08:49:46 -070027
vjiaoblack1e5abf12016-09-07 07:48:12 -070028 this->updateLights(100, 100);
vjiaoblack955e8792016-08-05 07:55:01 -070029
30 fTestRects[0].fColor = 0xFFEE8888;
31 fTestRects[0].fDepth = 80;
vjiaoblackb2796fd2016-09-09 09:22:39 -070032 fTestRects[0].fGeometry = SkRect::MakeLTRB(300,200,350,250);
vjiaoblack955e8792016-08-05 07:55:01 -070033
34 fTestRects[1].fColor = 0xFF88EE88;
35 fTestRects[1].fDepth = 160;
vjiaoblackb2796fd2016-09-09 09:22:39 -070036 fTestRects[1].fGeometry = SkRect::MakeLTRB(200,300,250,350);
vjiaoblack955e8792016-08-05 07:55:01 -070037
38 fTestRects[2].fColor = 0xFF8888EE;
39 fTestRects[2].fDepth = 240;
vjiaoblackb2796fd2016-09-09 09:22:39 -070040 fTestRects[2].fGeometry = SkRect::MakeLTRB(100,100,150,150);
vjiaoblack955e8792016-08-05 07:55:01 -070041
vjiaoblacke6f5d562016-08-25 06:30:23 -070042 fSliders[0].fGeometry = SkRect::MakeLTRB(20, 400, 30, 420);
43 fSliders[0].fOffset = 0.0f;
44 fSliders[0].fScale = 0.1f;
45
46 fSliders[1].fGeometry = SkRect::MakeLTRB(100, 420, 110, 440);
47 fSliders[1].fOffset = 0.0f;
48 fSliders[1].fScale = 10.0f;
49
50 fSliders[2].fGeometry = SkRect::MakeLTRB(0, 440, 10, 460);
51 fSliders[2].fOffset = 0.0f;
52 fSliders[2].fScale = 0.0025f;
53
vjiaoblack56f33ea2016-08-26 08:49:46 -070054 fShadowParams.fShadowRadius = 4.0f;
vjiaoblacke6f5d562016-08-25 06:30:23 -070055 fShadowParams.fBiasingConstant = 0.3f;
vjiaoblack1e5abf12016-09-07 07:48:12 -070056 fShadowParams.fMinVariance = 2048; // we need a higher min variance for point lights
vjiaoblackb2796fd2016-09-09 09:22:39 -070057 fShadowParams.fType = SkShadowParams::kNoBlur_ShadowType;
vjiaoblack955e8792016-08-05 07:55:01 -070058 }
59
60protected:
61 bool onQuery(SkEvent *evt) override {
62 if (SampleCode::TitleQ(*evt)) {
63 SampleCode::TitleR(evt, "shadowing");
64 return true;
65 }
66
67 SkUnichar uni;
68 if (SampleCode::CharQ(*evt, &uni)) {
69 switch (uni) {
70 case 'L':
71 fMoveLight = !fMoveLight;
72 break;
vjiaoblack904527d2016-08-09 09:32:09 -070073 case 'd':
74 // Raster generated shadow maps have their origin in the UL corner
75 // GPU shadow maps can have an arbitrary origin.
76 // We override the 'd' keypress so that when the device is cycled,
77 // the shadow maps will be re-generated according to the new backend.
78 fClearShadowMaps = true;
79 break;
vjiaoblack56f33ea2016-08-26 08:49:46 -070080 case 'q':
81 fLightDepth += 5.0f;
82 fMoveLight = true;
vjiaoblackbb106062016-08-31 11:15:21 -070083 break;
vjiaoblacke6f5d562016-08-25 06:30:23 -070084 case 'B':
85 if (SkShadowParams::kVariance_ShadowType == fShadowParams.fType) {
86 fShadowParams.fType = SkShadowParams::kNoBlur_ShadowType;
87 } else if (SkShadowParams::kNoBlur_ShadowType ==
88 fShadowParams.fType) {
89 fShadowParams.fType = SkShadowParams::kVariance_ShadowType;
90 }
91 fLightsChanged = true;
92 break;
vjiaoblack56f33ea2016-08-26 08:49:46 -070093 case 'w':
94 fLightDepth -= 5.0f;
95 fMoveLight = true;
96 break;
vjiaoblack955e8792016-08-05 07:55:01 -070097 default:
98 break;
99 }
100 }
101 return this->INHERITED::onQuery(evt);
102 }
103
104 sk_sp<SkPicture> makeTestPicture(int width, int height) {
105 SkPictureRecorder recorder;
106
107 // LONG RANGE TODO: eventually add SkBBHFactory (bounding box factory)
108 SkCanvas* canvas = recorder.beginRecording(SkRect::MakeIWH(width, height));
109
110 SkASSERT(canvas->getTotalMatrix().isIdentity());
111 SkPaint paint;
112 paint.setColor(SK_ColorGRAY);
113
114 // LONG RANGE TODO: tag occluders
115 // LONG RANGE TODO: track number of IDs we need (hopefully less than 256)
116 // and determinate the mapping from z to id
117
118 // universal receiver, "ground"
119 canvas->drawRect(SkRect::MakeIWH(width, height), paint);
120
121 for (int i = 0; i < kNumTestRects; i++) {
122 paint.setColor(fTestRects[i].fColor);
123 if (i == 0) {
124 canvas->translateZ(fTestRects[0].fDepth);
125 } else {
126 canvas->translateZ(fTestRects[i].fDepth - fTestRects[i-1].fDepth);
127 }
128 canvas->drawRect(fTestRects[i].fGeometry, paint);
129 }
130
131 return recorder.finishRecordingAsPicture();
132 }
133
vjiaoblack955e8792016-08-05 07:55:01 -0700134 void onDrawContent(SkCanvas *canvas) override {
vjiaoblack904527d2016-08-09 09:32:09 -0700135 if (fSceneChanged) {
vjiaoblack955e8792016-08-05 07:55:01 -0700136 fPicture = this->makeTestPicture(kWidth, kHeight);
vjiaoblack955e8792016-08-05 07:55:01 -0700137 }
138
vjiaoblack904527d2016-08-09 09:32:09 -0700139 if (fSceneChanged || fLightsChanged || fClearShadowMaps) {
140 for (int i = 0; i < fLights->numLights(); i++) {
141 fLights->light(i).setShadowMap(nullptr);
142 }
vjiaoblacke6f5d562016-08-25 06:30:23 -0700143
vjiaoblack904527d2016-08-09 09:32:09 -0700144 fSceneChanged = false;
145 fLightsChanged = false;
146 fClearShadowMaps = false;
vjiaoblack955e8792016-08-05 07:55:01 -0700147 }
vjiaoblackd707f2d2016-08-16 05:38:45 -0700148
149 canvas->setLights(fLights);
vjiaoblacke6f5d562016-08-25 06:30:23 -0700150 canvas->drawShadowedPicture(fPicture, nullptr, nullptr, fShadowParams);
151
152 for (int i = 0; i < kNumSliders; i++) {
153 SkPaint paint;
154 paint.setColor(SK_ColorBLACK);
155 canvas->drawRect(fSliders[i].fGeometry, paint);
156 }
vjiaoblack955e8792016-08-05 07:55:01 -0700157 }
158
159 SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
160 return new SkView::Click(this);
161 }
162
vjiaoblack56f33ea2016-08-26 08:49:46 -0700163 void updateLights(int x, int y) {
164 SkLights::Builder builder;
vjiaoblackb2796fd2016-09-09 09:22:39 -0700165 builder.add(SkLights::Light::MakePoint(SkColor3f::Make(1.0f, 1.0f, 1.0f),
166 SkVector3::Make(x,
167 kHeight - y,
vjiaoblack56f33ea2016-08-26 08:49:46 -0700168 fLightDepth),
vjiaoblack95315f02016-09-09 11:58:19 -0700169 400, true));
vjiaoblack56f33ea2016-08-26 08:49:46 -0700170 fLights = builder.finish();
171 }
vjiaoblacke6f5d562016-08-25 06:30:23 -0700172
vjiaoblack56f33ea2016-08-26 08:49:46 -0700173 void updateFromSelectedSlider() {
174 SkScalar newValue = fSliders[fSelectedSliderID].fGeometry.fLeft *
175 fSliders[fSelectedSliderID].fScale +
176 fSliders[fSelectedSliderID].fOffset;
177
178 switch (fSelectedSliderID) {
vjiaoblacke6f5d562016-08-25 06:30:23 -0700179 case 0:
180 fShadowParams.fShadowRadius = newValue;
181 break;
182 case 1:
183 fShadowParams.fMinVariance = newValue;
184 break;
185 case 2:
186 fShadowParams.fBiasingConstant = newValue;
187 break;
188 default:
189 break;
190 }
191 }
192
vjiaoblack955e8792016-08-05 07:55:01 -0700193 bool onClick(Click *click) override {
194 SkScalar x = click->fCurr.fX;
195 SkScalar y = click->fCurr.fY;
196
197 SkScalar dx = x - click->fPrev.fX;
198 SkScalar dy = y - click->fPrev.fY;
199
200 if (fMoveLight) {
201 if (dx != 0 || dy != 0) {
vjiaoblack56f33ea2016-08-26 08:49:46 -0700202 this->updateLights(x, y);
vjiaoblack955e8792016-08-05 07:55:01 -0700203 fLightsChanged = true;
204 this->inval(nullptr);
205 }
206 return true;
207 }
208
209 if (click->fState == Click::State::kUp_State) {
vjiaoblack56f33ea2016-08-26 08:49:46 -0700210 fSelectedRectID = -1;
211 fSelectedSliderID = -1;
vjiaoblack955e8792016-08-05 07:55:01 -0700212 return true;
213 }
214
vjiaoblack56f33ea2016-08-26 08:49:46 -0700215 if (fSelectedRectID > -1) {
216 fTestRects[fSelectedRectID].fGeometry.offset(dx, dy);
vjiaoblack955e8792016-08-05 07:55:01 -0700217
218 fSceneChanged = true;
219 this->inval(nullptr);
220 return true;
221 }
222
vjiaoblack56f33ea2016-08-26 08:49:46 -0700223 if (fSelectedSliderID > -1) {
224 fSliders[fSelectedSliderID].fGeometry.offset(dx, 0);
vjiaoblacke6f5d562016-08-25 06:30:23 -0700225
226 this->updateFromSelectedSlider();
227
228 fLightsChanged = true;
229 this->inval(nullptr);
230 return true;
231 }
232
vjiaoblack955e8792016-08-05 07:55:01 -0700233 // assume last elements are highest
234 for (int i = kNumTestRects - 1; i >= 0; i--) {
235 if (fTestRects[i].fGeometry.contains(SkRect::MakeXYWH(x, y, 1, 1))) {
vjiaoblack56f33ea2016-08-26 08:49:46 -0700236 fSelectedRectID = i;
vjiaoblack955e8792016-08-05 07:55:01 -0700237 fTestRects[i].fGeometry.offset(dx, dy);
238
239 fSceneChanged = true;
240 this->inval(nullptr);
241 break;
242 }
243 }
244
vjiaoblacke6f5d562016-08-25 06:30:23 -0700245 for (int i = 0; i <= kNumSliders; i++) {
246 if (fSliders[i].fGeometry.contains(SkRect::MakeXYWH(x, y, 1, 1))) {
vjiaoblack56f33ea2016-08-26 08:49:46 -0700247 fSelectedSliderID = i;
vjiaoblacke6f5d562016-08-25 06:30:23 -0700248 fSliders[i].fGeometry.offset(dx, 0);
249
250 this->updateFromSelectedSlider();
251
252 fLightsChanged = true;
253
254 this->inval(nullptr);
255 break;
256 }
257 }
258
vjiaoblack955e8792016-08-05 07:55:01 -0700259 return true;
260 }
261
262private:
263 static constexpr int kNumTestRects = 3;
vjiaoblacke6f5d562016-08-25 06:30:23 -0700264 static constexpr int kNumSliders = 3;
vjiaoblack955e8792016-08-05 07:55:01 -0700265
266 static const int kWidth = 400;
267 static const int kHeight = 400;
268
vjiaoblack56f33ea2016-08-26 08:49:46 -0700269 bool fSceneChanged;
270 bool fLightsChanged;
271 bool fMoveLight;
272 bool fClearShadowMaps;
273
vjiaoblack955e8792016-08-05 07:55:01 -0700274 struct {
275 SkRect fGeometry;
276 int fDepth;
277 SkColor fColor;
278 } fTestRects[kNumTestRects];
vjiaoblack56f33ea2016-08-26 08:49:46 -0700279 int fSelectedRectID;
vjiaoblacke6f5d562016-08-25 06:30:23 -0700280
281 struct {
282 SkRect fGeometry;
283 SkScalar fOffset;
284 SkScalar fScale;
285 } fSliders[kNumSliders];
vjiaoblack56f33ea2016-08-26 08:49:46 -0700286 int fSelectedSliderID;
vjiaoblacke6f5d562016-08-25 06:30:23 -0700287
vjiaoblack56f33ea2016-08-26 08:49:46 -0700288 SkScalar fLightDepth;
vjiaoblack955e8792016-08-05 07:55:01 -0700289
vjiaoblacke6f5d562016-08-25 06:30:23 -0700290 sk_sp<SkPicture> fPicture;
291 SkShadowParams fShadowParams;
vjiaoblack955e8792016-08-05 07:55:01 -0700292 sk_sp<SkLights> fLights;
293
294 typedef SampleView INHERITED;
295};
296
297//////////////////////////////////////////////////////////////////////////////
298static SkView* MyFactory() { return new ShadowingView; }
299static SkViewRegister reg(MyFactory);
300
301#endif