blob: e3c71a00c7a70089942225870d73d6570f2b684d [file] [log] [blame]
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +00001/*
2 * Copyright 2012 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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "gm/gm.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -04009#include "include/core/SkBitmap.h"
10#include "include/core/SkCanvas.h"
11#include "include/core/SkColor.h"
12#include "include/core/SkImageFilter.h"
13#include "include/core/SkPaint.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "include/core/SkPoint3.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040015#include "include/core/SkRect.h"
16#include "include/core/SkRefCnt.h"
17#include "include/core/SkScalar.h"
18#include "include/core/SkSize.h"
19#include "include/core/SkString.h"
Michael Ludwig898bbfa2019-08-02 15:21:23 -040020#include "include/effects/SkImageFilters.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050021#include "tools/ToolUtils.h"
Kevin Lubicke836c3a2023-10-20 06:55:35 -040022#include "tools/fonts/FontToolUtils.h"
Hal Canary41248072019-07-11 16:32:53 -040023#include "tools/timer/TimeUtils.h"
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +000024
Michael Ludwigf5774272021-01-21 18:43:58 -050025#define WIDTH 660
senorblancod0d37ca2015-04-02 04:54:56 -070026#define HEIGHT 660
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +000027
28namespace skiagm {
29
30class ImageLightingGM : public GM {
31public:
robertphillips651bb5f2016-04-08 13:35:14 -070032 ImageLightingGM()
33 : fAzimuth(SkIntToScalar(kStartAzimuth)) {
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +000034 this->setBGColor(0xFF000000);
35 }
rmistry@google.comae933ce2012-08-23 18:19:56 +000036
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +000037protected:
Leandro Lovisolo24fa2112023-08-15 19:05:17 +000038 SkString getName() const override { return SkString("lighting"); }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +000039
Leandro Lovisolo8f023882023-08-15 21:13:52 +000040 SkISize getISize() override { return SkISize::Make(WIDTH, HEIGHT); }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +000041
junov@chromium.orgff06af22013-01-14 16:27:50 +000042 void drawClippedBitmap(SkCanvas* canvas, const SkPaint& paint, int x, int y) {
43 canvas->save();
senorblanco@chromium.orgfbaea532013-08-27 21:37:01 +000044 canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
Mike Reed607a3822021-01-24 19:49:21 -050045 canvas->clipIRect(fBitmap.bounds());
46 canvas->drawImage(fBitmap.asImage(), 0, 0, SkSamplingOptions(), &paint);
junov@chromium.orgff06af22013-01-14 16:27:50 +000047 canvas->restore();
48 }
49
robertphillips943a4622015-09-03 13:32:33 -070050 void onOnceBeforeDraw() override {
Kevin Lubicke836c3a2023-10-20 06:55:35 -040051 fBitmap = ToolUtils::CreateStringBitmap(100, 100, 0xFFFFFFFF, 20, 70, 96, "e");
robertphillips943a4622015-09-03 13:32:33 -070052 }
53
mtklein36352bf2015-03-25 18:17:31 -070054 void onDraw(SkCanvas* canvas) override {
Mike Kleind46dce32018-08-16 10:17:03 -040055 canvas->clear(0xFF101010);
senorblanco@chromium.org7b734e02012-10-29 19:47:06 +000056 SkPaint checkPaint;
Mike Kleind46dce32018-08-16 10:17:03 -040057 checkPaint.setColor(0xFF202020);
senorblanco@chromium.org7b734e02012-10-29 19:47:06 +000058 for (int y = 0; y < HEIGHT; y += 16) {
59 for (int x = 0; x < WIDTH; x += 16) {
60 canvas->save();
61 canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
62 canvas->drawRect(SkRect::MakeXYWH(8, 0, 8, 8), checkPaint);
63 canvas->drawRect(SkRect::MakeXYWH(0, 8, 8, 8), checkPaint);
64 canvas->restore();
65 }
66 }
Brian Osman4428f2c2019-04-02 10:59:28 -040067 SkScalar sinAzimuth = SkScalarSin(SkDegreesToRadians(fAzimuth)),
68 cosAzimuth = SkScalarCos(SkDegreesToRadians(fAzimuth));
robertphillips651bb5f2016-04-08 13:35:14 -070069
70 SkPoint3 spotTarget = SkPoint3::Make(SkIntToScalar(40), SkIntToScalar(40), 0);
71 SkPoint3 spotLocation = SkPoint3::Make(spotTarget.fX + 70.7214f * cosAzimuth,
72 spotTarget.fY + 70.7214f * sinAzimuth,
73 spotTarget.fZ + SkIntToScalar(20));
Michael Ludwigf5774272021-01-21 18:43:58 -050074 SkScalar spotExponent1 = SK_Scalar1;
75 SkScalar spotExponent10 = SkIntToScalar(10);
76 SkScalar cutoffAngleSmall = SkIntToScalar(15);
77 SkScalar cutoffAngleNone = SkIntToScalar(180);
robertphillips651bb5f2016-04-08 13:35:14 -070078
79 SkPoint3 pointLocation = SkPoint3::Make(spotTarget.fX + 50 * cosAzimuth,
80 spotTarget.fY + 50 * sinAzimuth,
81 SkIntToScalar(10));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +000082 SkScalar elevationRad = SkDegreesToRadians(SkIntToScalar(5));
robertphillips651bb5f2016-04-08 13:35:14 -070083
Mike Reeddf85c382017-02-14 10:59:19 -050084 SkPoint3 distantDirection = SkPoint3::Make(cosAzimuth * SkScalarCos(elevationRad),
85 sinAzimuth * SkScalarCos(elevationRad),
robertphillips3d32d762015-07-13 13:16:44 -070086 SkScalarSin(elevationRad));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +000087 SkScalar kd = SkIntToScalar(2);
88 SkScalar ks = SkIntToScalar(1);
89 SkScalar shininess = SkIntToScalar(8);
90 SkScalar surfaceScale = SkIntToScalar(1);
Michael Ludwigf5774272021-01-21 18:43:58 -050091 SkScalar surfaceScaleSmall = 0.1f;
92 SkColor greenYellow = SkColorSetARGB(255, 173, 255, 47);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +000093 SkPaint paint;
senorblanco@chromium.org4e16bb22013-07-26 00:10:07 +000094
Michael Ludwig898bbfa2019-08-02 15:21:23 -040095 SkIRect cropRect = SkIRect::MakeXYWH(20, 10, 60, 65);
96 SkIRect fullSizeCropRect = SkIRect::MakeXYWH(0, 0, 100, 100);
97 sk_sp<SkImageFilter> noopCropped(SkImageFilters::Offset(0, 0, nullptr, &cropRect));
senorblanco@chromium.org4e16bb22013-07-26 00:10:07 +000098
99 int y = 0;
senorblancod0d37ca2015-04-02 04:54:56 -0700100 for (int i = 0; i < 3; i++) {
Michael Ludwig898bbfa2019-08-02 15:21:23 -0400101 const SkIRect* cr = (i == 1) ? &cropRect : (i == 2) ? &fullSizeCropRect : nullptr;
robertphillips12fa47d2016-04-08 16:28:09 -0700102 sk_sp<SkImageFilter> input = (i == 2) ? noopCropped : nullptr;
Michael Ludwigf5774272021-01-21 18:43:58 -0500103 // Basic point, distant and spot lights with diffuse lighting
Michael Ludwig898bbfa2019-08-02 15:21:23 -0400104 paint.setImageFilter(SkImageFilters::PointLitDiffuse(
Michael Ludwigf5774272021-01-21 18:43:58 -0500105 pointLocation, SK_ColorWHITE, surfaceScale, kd, input, cr));
robertphillips12fa47d2016-04-08 16:28:09 -0700106 drawClippedBitmap(canvas, paint, 0, y);
107
Michael Ludwig898bbfa2019-08-02 15:21:23 -0400108 paint.setImageFilter(SkImageFilters::DistantLitDiffuse(
Michael Ludwigf5774272021-01-21 18:43:58 -0500109 distantDirection, SK_ColorWHITE, surfaceScale, kd, input, cr));
senorblanco@chromium.org4e16bb22013-07-26 00:10:07 +0000110 drawClippedBitmap(canvas, paint, 110, y);
senorblanco@chromium.orgfbaea532013-08-27 21:37:01 +0000111
Michael Ludwig898bbfa2019-08-02 15:21:23 -0400112 paint.setImageFilter(SkImageFilters::SpotLitDiffuse(
Michael Ludwigf5774272021-01-21 18:43:58 -0500113 spotLocation, spotTarget, spotExponent1, cutoffAngleSmall, SK_ColorWHITE,
114 surfaceScale, kd, input, cr));
senorblanco@chromium.org4e16bb22013-07-26 00:10:07 +0000115 drawClippedBitmap(canvas, paint, 220, y);
116
Michael Ludwigf5774272021-01-21 18:43:58 -0500117 // Spot light with no angle cutoff
118 paint.setImageFilter(SkImageFilters::SpotLitDiffuse(
119 spotLocation, spotTarget, spotExponent10, cutoffAngleNone, SK_ColorWHITE,
120 surfaceScale, kd, input, cr));
121 drawClippedBitmap(canvas, paint, 330, y);
122
123 // Spot light with falloff exponent
124 paint.setImageFilter(SkImageFilters::SpotLitDiffuse(
125 spotLocation, spotTarget, spotExponent1, cutoffAngleNone, SK_ColorWHITE,
126 surfaceScaleSmall, kd, input, cr));
127 drawClippedBitmap(canvas, paint, 440, y);
128
129 // Large constant to show oversaturation
130 paint.setImageFilter(SkImageFilters::DistantLitDiffuse(
131 distantDirection, greenYellow, surfaceScale, 4.f * kd, input, cr));
132 drawClippedBitmap(canvas, paint, 550, y);
133
senorblanco@chromium.org4e16bb22013-07-26 00:10:07 +0000134 y += 110;
senorblanco@chromium.orgfbaea532013-08-27 21:37:01 +0000135
Michael Ludwigf5774272021-01-21 18:43:58 -0500136 // Basic point, distant and spot lights with specular lighting
Michael Ludwig898bbfa2019-08-02 15:21:23 -0400137 paint.setImageFilter(SkImageFilters::PointLitSpecular(
Michael Ludwigf5774272021-01-21 18:43:58 -0500138 pointLocation, SK_ColorWHITE, surfaceScale, ks, shininess, input, cr));
robertphillips12fa47d2016-04-08 16:28:09 -0700139 drawClippedBitmap(canvas, paint, 0, y);
140
Michael Ludwig898bbfa2019-08-02 15:21:23 -0400141 paint.setImageFilter(SkImageFilters::DistantLitSpecular(
Michael Ludwigf5774272021-01-21 18:43:58 -0500142 distantDirection, SK_ColorWHITE, surfaceScale, ks, shininess, input, cr));
senorblanco@chromium.org4e16bb22013-07-26 00:10:07 +0000143 drawClippedBitmap(canvas, paint, 110, y);
senorblanco@chromium.orgfbaea532013-08-27 21:37:01 +0000144
Michael Ludwig898bbfa2019-08-02 15:21:23 -0400145 paint.setImageFilter(SkImageFilters::SpotLitSpecular(
Michael Ludwigf5774272021-01-21 18:43:58 -0500146 spotLocation, spotTarget, spotExponent1, cutoffAngleSmall, SK_ColorWHITE,
147 surfaceScale, ks, shininess, input, cr));
senorblanco@chromium.org4e16bb22013-07-26 00:10:07 +0000148 drawClippedBitmap(canvas, paint, 220, y);
senorblanco@chromium.orgfbaea532013-08-27 21:37:01 +0000149
Michael Ludwigf5774272021-01-21 18:43:58 -0500150 // Spot light with no angle cutoff
151 paint.setImageFilter(SkImageFilters::SpotLitSpecular(
152 spotLocation, spotTarget, spotExponent10, cutoffAngleNone, SK_ColorWHITE,
153 surfaceScale, ks, shininess, input, cr));
154 drawClippedBitmap(canvas, paint, 330, y);
155
156 // Spot light with falloff exponent
157 paint.setImageFilter(SkImageFilters::SpotLitSpecular(
158 spotLocation, spotTarget, spotExponent1, cutoffAngleNone, SK_ColorWHITE,
159 surfaceScaleSmall, ks, shininess, input, cr));
160 drawClippedBitmap(canvas, paint, 440, y);
161
162 // Large constant to show oversaturation
163 paint.setImageFilter(SkImageFilters::DistantLitSpecular(
164 distantDirection, greenYellow, surfaceScale, 4.f * ks, shininess, input, cr));
165 drawClippedBitmap(canvas, paint, 550, y);
166
senorblanco@chromium.org4e16bb22013-07-26 00:10:07 +0000167 y += 110;
168 }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000169 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000170
Hal Canary41248072019-07-11 16:32:53 -0400171 bool onAnimate(double nanos) override {
mtkleindbfd7ab2016-09-01 11:24:54 -0700172 constexpr SkScalar kDesiredDurationSecs = 15.0f;
robertphillips651bb5f2016-04-08 13:35:14 -0700173
Hal Canary41248072019-07-11 16:32:53 -0400174 fAzimuth = kStartAzimuth + TimeUtils::Scaled(1e-9 * nanos, 360.0f/kDesiredDurationSecs, 360.0f);
robertphillips651bb5f2016-04-08 13:35:14 -0700175 return true;
176 }
177
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000178private:
Brian Salomon9fa47cc2021-10-08 18:48:26 -0400179 inline static constexpr int kStartAzimuth = 225;
robertphillips651bb5f2016-04-08 13:35:14 -0700180
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000181 SkBitmap fBitmap;
robertphillips651bb5f2016-04-08 13:35:14 -0700182 SkScalar fAzimuth;
robertphillips943a4622015-09-03 13:32:33 -0700183
John Stiles7571f9e2020-09-02 22:42:33 -0400184 using INHERITED = GM;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000185};
186
187//////////////////////////////////////////////////////////////////////////////
188
halcanary385fe4d2015-08-26 13:07:48 -0700189DEF_GM(return new ImageLightingGM;)
John Stilesa6841be2020-08-06 14:11:56 -0400190} // namespace skiagm