lighting.cpp revision dbfd7ab10883f173f5c1b653a233e18dc6142002
1800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany/*
2800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany * Copyright 2012 Google Inc.
3800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany *
4800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany * Use of this source code is governed by a BSD-style license that can be
5800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany * found in the LICENSE file.
6800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany */
7800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany
8800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany#include "gm.h"
9800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany#include "SkAnimTimer.h"
10800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany#include "SkLightingImageFilter.h"
11800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany#include "SkOffsetImageFilter.h"
12800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany#include "SkPoint3.h"
13800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany
14800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany#define WIDTH 330
15800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany#define HEIGHT 660
16800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany
17800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryanynamespace skiagm {
18d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth
19800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryanyclass ImageLightingGM : public GM {
201c8b825c4396ad9cd38f713d9e9a51adae1d4c4eAlexey Samsonovpublic:
2159cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov    ImageLightingGM()
22800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany        : fAzimuth(SkIntToScalar(kStartAzimuth)) {
23800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany        this->setBGColor(0xFF000000);
24800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany    }
25800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany
26800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryanyprotected:
2706fdbaa9145f01a291d4981ca5120b7bdcad44c6Evgeniy Stepanov
281afbb517965e29b07cb42e2335d5eadd87de6535Alexey Samsonov    SkString onShortName() override {
290b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth        return SkString("lighting");
300b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth    }
310b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth
320b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth    SkISize onISize() override {
330b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth        return SkISize::Make(WIDTH, HEIGHT);
340b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth    }
350b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth
360b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth    void drawClippedBitmap(SkCanvas* canvas, const SkPaint& paint, int x, int y) {
3759cca13a80ed78ccbcdaa9bf20381bd48243f2f1Alexey Samsonov        canvas->save();
38800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany        canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
39800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany        canvas->clipRect(SkRect::MakeWH(
40800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany          SkIntToScalar(fBitmap.width()), SkIntToScalar(fBitmap.height())));
41800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany        canvas->drawBitmap(fBitmap, 0, 0, &paint);
42800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany        canvas->restore();
43800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany    }
44800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany
4590230c84668269fbd53d163e398cd16486d5d414Chandler Carruth    void onOnceBeforeDraw() override {
461afbb517965e29b07cb42e2335d5eadd87de6535Alexey Samsonov        fBitmap = sk_tool_utils::create_string_bitmap(100, 100, 0xFFFFFFFF, 20, 70, 96, "e");
47800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany    }
48800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany
49d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth    void onDraw(SkCanvas* canvas) override {
50800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany        canvas->clear(sk_tool_utils::color_to_565(0xFF101010));
51800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany        SkPaint checkPaint;
52800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany        checkPaint.setColor(sk_tool_utils::color_to_565(0xFF202020));
53800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany        for (int y = 0; y < HEIGHT; y += 16) {
54800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany          for (int x = 0; x < WIDTH; x += 16) {
55800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany            canvas->save();
56117de489a0d5f4ff280fb173fe45bd5ce8514d93Kostya Serebryany            canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
5748a615fee78c3c262c60147a65dc6fff5fd6bb3bKostya Serebryany            canvas->drawRect(SkRect::MakeXYWH(8, 0, 8, 8), checkPaint);
58800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany            canvas->drawRect(SkRect::MakeXYWH(0, 8, 8, 8), checkPaint);
59800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany            canvas->restore();
60800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany          }
61800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany        }
62800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany        SkScalar cosAzimuth;
63800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany        SkScalar sinAzimuth = SkScalarSinCos(SkDegreesToRadians(fAzimuth), &cosAzimuth);
647bcfc9950bac0f411f9671e8d6ce483bd219727eKostya Serebryany
657bcfc9950bac0f411f9671e8d6ce483bd219727eKostya Serebryany        SkPoint3 spotTarget = SkPoint3::Make(SkIntToScalar(40), SkIntToScalar(40), 0);
66800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany        SkPoint3 spotLocation = SkPoint3::Make(spotTarget.fX + 70.7214f * cosAzimuth,
67800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany                                               spotTarget.fY + 70.7214f * sinAzimuth,
687bcfc9950bac0f411f9671e8d6ce483bd219727eKostya Serebryany                                               spotTarget.fZ + SkIntToScalar(20));
699b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany        SkScalar spotExponent = SK_Scalar1;
709b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany
710bc55d517e8e64f0f441736fba2447781c405ef4Kostya Serebryany        SkPoint3 pointLocation = SkPoint3::Make(spotTarget.fX + 50 * cosAzimuth,
7295e3cf44a9d4672655dee3bd558bfeefa631dd55Kostya Serebryany                                                spotTarget.fY + 50 * sinAzimuth,
73800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany                                                SkIntToScalar(10));
74800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany        SkScalar elevationRad = SkDegreesToRadians(SkIntToScalar(5));
75800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany
76800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany        SkPoint3 distantDirection = SkPoint3::Make(SkScalarMul(cosAzimuth,
7751c7c65e32f76ec5a50cdecfe2b4c287c57da127Kostya Serebryany                                                               SkScalarCos(elevationRad)),
78f985f44b13681071e585acb7a5703a2c1c23b6ceAlexey Samsonov                                                   SkScalarMul(sinAzimuth,
79f985f44b13681071e585acb7a5703a2c1c23b6ceAlexey Samsonov                                                               SkScalarCos(elevationRad)),
80f985f44b13681071e585acb7a5703a2c1c23b6ceAlexey Samsonov                                                   SkScalarSin(elevationRad));
81800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany        SkScalar cutoffAngle = SkIntToScalar(15);
82800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany        SkScalar kd = SkIntToScalar(2);
83800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany        SkScalar ks = SkIntToScalar(1);
84800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany        SkScalar shininess = SkIntToScalar(8);
85800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany        SkScalar surfaceScale = SkIntToScalar(1);
86800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany        SkColor white(0xFFFFFFFF);
87c0ed3e548c6f688e22685de04e210c7b59ac3433Kostya Serebryany        SkPaint paint;
88c0ed3e548c6f688e22685de04e210c7b59ac3433Kostya Serebryany
89c0ed3e548c6f688e22685de04e210c7b59ac3433Kostya Serebryany        SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(20, 10, 60, 65));
90800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany        SkImageFilter::CropRect fullSizeCropRect(SkRect::MakeXYWH(0, 0, 100, 100));
91800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany        sk_sp<SkImageFilter> noopCropped(SkOffsetImageFilter::Make(0, 0, nullptr, &cropRect));
92800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany
93800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany        int y = 0;
94800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany        for (int i = 0; i < 3; i++) {
95800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany            const SkImageFilter::CropRect* cr = (i == 1) ? &cropRect : (i == 2) ? &fullSizeCropRect : nullptr;
96800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany            sk_sp<SkImageFilter> input = (i == 2) ? noopCropped : nullptr;
97e6cf2e0bd09544eeb69665deb908d264e62a71c2Kostya Serebryany            paint.setImageFilter(SkLightingImageFilter::MakePointLitDiffuse(pointLocation,
98e6cf2e0bd09544eeb69665deb908d264e62a71c2Kostya Serebryany                                                                            white,
99e6cf2e0bd09544eeb69665deb908d264e62a71c2Kostya Serebryany                                                                            surfaceScale,
1006e2d506dc962873a0e05092bbb034f9a615d1084Kostya Serebryany                                                                            kd,
1016e2d506dc962873a0e05092bbb034f9a615d1084Kostya Serebryany                                                                            input,
1026e2d506dc962873a0e05092bbb034f9a615d1084Kostya Serebryany                                                                            cr));
103c0ed3e548c6f688e22685de04e210c7b59ac3433Kostya Serebryany            drawClippedBitmap(canvas, paint, 0, y);
104324cbb89f2759fb9ad347bd2af4631e50c39c8f3Kostya Serebryany
105324cbb89f2759fb9ad347bd2af4631e50c39c8f3Kostya Serebryany            paint.setImageFilter(SkLightingImageFilter::MakeDistantLitDiffuse(distantDirection,
106324cbb89f2759fb9ad347bd2af4631e50c39c8f3Kostya Serebryany                                                                              white,
107324cbb89f2759fb9ad347bd2af4631e50c39c8f3Kostya Serebryany                                                                              surfaceScale,
108324cbb89f2759fb9ad347bd2af4631e50c39c8f3Kostya Serebryany                                                                              kd,
109324cbb89f2759fb9ad347bd2af4631e50c39c8f3Kostya Serebryany                                                                              input,
110324cbb89f2759fb9ad347bd2af4631e50c39c8f3Kostya Serebryany                                                                              cr));
111800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany            drawClippedBitmap(canvas, paint, 110, y);
112800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany
113800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany            paint.setImageFilter(SkLightingImageFilter::MakeSpotLitDiffuse(spotLocation,
114800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany                                                                           spotTarget,
115800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany                                                                           spotExponent,
116800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany                                                                           cutoffAngle,
117800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany                                                                           white,
118800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany                                                                           surfaceScale,
119800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany                                                                           kd,
1209b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany                                                                           input,
1219b9f87a87ac1b373c4c6a70904315bebbd01c50cKostya Serebryany                                                                           cr));
122800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany            drawClippedBitmap(canvas, paint, 220, y);
123800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany
1246c55412ea4b39103a3a5764d49ddfdf50e066d56Kostya Serebryany            y += 110;
1256c55412ea4b39103a3a5764d49ddfdf50e066d56Kostya Serebryany
126b0dcf61252e58715a3bea79f4c112572df361c30Alexey Samsonov            paint.setImageFilter(SkLightingImageFilter::MakePointLitSpecular(pointLocation,
127b0dcf61252e58715a3bea79f4c112572df361c30Alexey Samsonov                                                                             white,
128800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany                                                                             surfaceScale,
129800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany                                                                             ks,
130800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany                                                                             shininess,
131800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany                                                                             input,
132800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany                                                                             cr));
133800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany            drawClippedBitmap(canvas, paint, 0, y);
134800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany
135800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany            paint.setImageFilter(SkLightingImageFilter::MakeDistantLitSpecular(distantDirection,
136800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany                                                                               white,
137117de489a0d5f4ff280fb173fe45bd5ce8514d93Kostya Serebryany                                                                               surfaceScale,
138117de489a0d5f4ff280fb173fe45bd5ce8514d93Kostya Serebryany                                                                               ks,
1390bc55d517e8e64f0f441736fba2447781c405ef4Kostya Serebryany                                                                               shininess,
140800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany                                                                               input,
141800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany                                                                               cr));
142800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany            drawClippedBitmap(canvas, paint, 110, y);
143800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany
144800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany            paint.setImageFilter(SkLightingImageFilter::MakeSpotLitSpecular(spotLocation,
145800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany                                                                            spotTarget,
146800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany                                                                            spotExponent,
147800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany                                                                            cutoffAngle,
148800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany                                                                            white,
149800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany                                                                            surfaceScale,
150800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany                                                                            ks,
151ee548275c63a1eeffda9d3edd2bea04e1dadcc67Alexey Samsonov                                                                            shininess,
152ee548275c63a1eeffda9d3edd2bea04e1dadcc67Alexey Samsonov                                                                            input,
153ee548275c63a1eeffda9d3edd2bea04e1dadcc67Alexey Samsonov                                                                            cr));
154ee548275c63a1eeffda9d3edd2bea04e1dadcc67Alexey Samsonov            drawClippedBitmap(canvas, paint, 220, y);
155800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany
156800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany            y += 110;
157800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany        }
158800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany    }
159800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany
160800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany    bool onAnimate(const SkAnimTimer& timer) override {
161800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany        constexpr SkScalar kDesiredDurationSecs = 15.0f;
162800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany
163800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany        fAzimuth = kStartAzimuth + timer.scaled(360.0f/kDesiredDurationSecs, 360.0f);
164800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany        return true;
165800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany    }
166800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryany
167800e03f59896ef4b26d988f1878370bb5aeec0d8Kostya Serebryanyprivate:
168ca23d43084c45a7d6f4371d62f45be044650ce38Kostya Serebryany    static constexpr int kStartAzimuth = 225;
169ca23d43084c45a7d6f4371d62f45be044650ce38Kostya Serebryany
170ca23d43084c45a7d6f4371d62f45be044650ce38Kostya Serebryany    SkBitmap fBitmap;
171ca23d43084c45a7d6f4371d62f45be044650ce38Kostya Serebryany    SkScalar fAzimuth;
172ca23d43084c45a7d6f4371d62f45be044650ce38Kostya Serebryany
173ca23d43084c45a7d6f4371d62f45be044650ce38Kostya Serebryany    typedef GM INHERITED;
174ca23d43084c45a7d6f4371d62f45be044650ce38Kostya Serebryany};
175ca23d43084c45a7d6f4371d62f45be044650ce38Kostya Serebryany
176ca23d43084c45a7d6f4371d62f45be044650ce38Kostya Serebryany//////////////////////////////////////////////////////////////////////////////
177ca23d43084c45a7d6f4371d62f45be044650ce38Kostya Serebryany
178ca23d43084c45a7d6f4371d62f45be044650ce38Kostya SerebryanyDEF_GM(return new ImageLightingGM;)
179ca23d43084c45a7d6f4371d62f45be044650ce38Kostya Serebryany}
180ca23d43084c45a7d6f4371d62f45be044650ce38Kostya Serebryany