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