1 /* 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 8 #include "gm/gm.h" 9 #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" 14 #include "include/core/SkPoint3.h" 15 #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" 20 #include "include/effects/SkImageFilters.h" 21 #include "tools/ToolUtils.h" 22 #include "tools/timer/TimeUtils.h" 23 24 #define WIDTH 660 25 #define HEIGHT 660 26 27 namespace skiagm { 28 29 class ImageLightingGM : public GM { 30 public: ImageLightingGM()31 ImageLightingGM() 32 : fAzimuth(SkIntToScalar(kStartAzimuth)) { 33 this->setBGColor(0xFF000000); 34 } 35 36 protected: 37 onShortName()38 SkString onShortName() override { 39 return SkString("lighting"); 40 } 41 onISize()42 SkISize onISize() override { 43 return SkISize::Make(WIDTH, HEIGHT); 44 } 45 drawClippedBitmap(SkCanvas * canvas,const SkPaint & paint,int x,int y)46 void drawClippedBitmap(SkCanvas* canvas, const SkPaint& paint, int x, int y) { 47 canvas->save(); 48 canvas->translate(SkIntToScalar(x), SkIntToScalar(y)); 49 canvas->clipIRect(fBitmap.bounds()); 50 canvas->drawImage(fBitmap.asImage(), 0, 0, SkSamplingOptions(), &paint); 51 canvas->restore(); 52 } 53 onOnceBeforeDraw()54 void onOnceBeforeDraw() override { 55 fBitmap = ToolUtils::create_string_bitmap(100, 100, 0xFFFFFFFF, 20, 70, 96, "e"); 56 } 57 onDraw(SkCanvas * canvas)58 void onDraw(SkCanvas* canvas) override { 59 canvas->clear(0xFF101010); 60 SkPaint checkPaint; 61 checkPaint.setColor(0xFF202020); 62 for (int y = 0; y < HEIGHT; y += 16) { 63 for (int x = 0; x < WIDTH; x += 16) { 64 canvas->save(); 65 canvas->translate(SkIntToScalar(x), SkIntToScalar(y)); 66 canvas->drawRect(SkRect::MakeXYWH(8, 0, 8, 8), checkPaint); 67 canvas->drawRect(SkRect::MakeXYWH(0, 8, 8, 8), checkPaint); 68 canvas->restore(); 69 } 70 } 71 SkScalar sinAzimuth = SkScalarSin(SkDegreesToRadians(fAzimuth)), 72 cosAzimuth = SkScalarCos(SkDegreesToRadians(fAzimuth)); 73 74 SkPoint3 spotTarget = SkPoint3::Make(SkIntToScalar(40), SkIntToScalar(40), 0); 75 SkPoint3 spotLocation = SkPoint3::Make(spotTarget.fX + 70.7214f * cosAzimuth, 76 spotTarget.fY + 70.7214f * sinAzimuth, 77 spotTarget.fZ + SkIntToScalar(20)); 78 SkScalar spotExponent1 = SK_Scalar1; 79 SkScalar spotExponent10 = SkIntToScalar(10); 80 SkScalar cutoffAngleSmall = SkIntToScalar(15); 81 SkScalar cutoffAngleNone = SkIntToScalar(180); 82 83 SkPoint3 pointLocation = SkPoint3::Make(spotTarget.fX + 50 * cosAzimuth, 84 spotTarget.fY + 50 * sinAzimuth, 85 SkIntToScalar(10)); 86 SkScalar elevationRad = SkDegreesToRadians(SkIntToScalar(5)); 87 88 SkPoint3 distantDirection = SkPoint3::Make(cosAzimuth * SkScalarCos(elevationRad), 89 sinAzimuth * SkScalarCos(elevationRad), 90 SkScalarSin(elevationRad)); 91 SkScalar kd = SkIntToScalar(2); 92 SkScalar ks = SkIntToScalar(1); 93 SkScalar shininess = SkIntToScalar(8); 94 SkScalar surfaceScale = SkIntToScalar(1); 95 SkScalar surfaceScaleSmall = 0.1f; 96 SkColor greenYellow = SkColorSetARGB(255, 173, 255, 47); 97 SkPaint paint; 98 99 SkIRect cropRect = SkIRect::MakeXYWH(20, 10, 60, 65); 100 SkIRect fullSizeCropRect = SkIRect::MakeXYWH(0, 0, 100, 100); 101 sk_sp<SkImageFilter> noopCropped(SkImageFilters::Offset(0, 0, nullptr, &cropRect)); 102 103 int y = 0; 104 for (int i = 0; i < 3; i++) { 105 const SkIRect* cr = (i == 1) ? &cropRect : (i == 2) ? &fullSizeCropRect : nullptr; 106 sk_sp<SkImageFilter> input = (i == 2) ? noopCropped : nullptr; 107 // Basic point, distant and spot lights with diffuse lighting 108 paint.setImageFilter(SkImageFilters::PointLitDiffuse( 109 pointLocation, SK_ColorWHITE, surfaceScale, kd, input, cr)); 110 drawClippedBitmap(canvas, paint, 0, y); 111 112 paint.setImageFilter(SkImageFilters::DistantLitDiffuse( 113 distantDirection, SK_ColorWHITE, surfaceScale, kd, input, cr)); 114 drawClippedBitmap(canvas, paint, 110, y); 115 116 paint.setImageFilter(SkImageFilters::SpotLitDiffuse( 117 spotLocation, spotTarget, spotExponent1, cutoffAngleSmall, SK_ColorWHITE, 118 surfaceScale, kd, input, cr)); 119 drawClippedBitmap(canvas, paint, 220, y); 120 121 // Spot light with no angle cutoff 122 paint.setImageFilter(SkImageFilters::SpotLitDiffuse( 123 spotLocation, spotTarget, spotExponent10, cutoffAngleNone, SK_ColorWHITE, 124 surfaceScale, kd, input, cr)); 125 drawClippedBitmap(canvas, paint, 330, y); 126 127 // Spot light with falloff exponent 128 paint.setImageFilter(SkImageFilters::SpotLitDiffuse( 129 spotLocation, spotTarget, spotExponent1, cutoffAngleNone, SK_ColorWHITE, 130 surfaceScaleSmall, kd, input, cr)); 131 drawClippedBitmap(canvas, paint, 440, y); 132 133 // Large constant to show oversaturation 134 paint.setImageFilter(SkImageFilters::DistantLitDiffuse( 135 distantDirection, greenYellow, surfaceScale, 4.f * kd, input, cr)); 136 drawClippedBitmap(canvas, paint, 550, y); 137 138 y += 110; 139 140 // Basic point, distant and spot lights with specular lighting 141 paint.setImageFilter(SkImageFilters::PointLitSpecular( 142 pointLocation, SK_ColorWHITE, surfaceScale, ks, shininess, input, cr)); 143 drawClippedBitmap(canvas, paint, 0, y); 144 145 paint.setImageFilter(SkImageFilters::DistantLitSpecular( 146 distantDirection, SK_ColorWHITE, surfaceScale, ks, shininess, input, cr)); 147 drawClippedBitmap(canvas, paint, 110, y); 148 149 paint.setImageFilter(SkImageFilters::SpotLitSpecular( 150 spotLocation, spotTarget, spotExponent1, cutoffAngleSmall, SK_ColorWHITE, 151 surfaceScale, ks, shininess, input, cr)); 152 drawClippedBitmap(canvas, paint, 220, y); 153 154 // Spot light with no angle cutoff 155 paint.setImageFilter(SkImageFilters::SpotLitSpecular( 156 spotLocation, spotTarget, spotExponent10, cutoffAngleNone, SK_ColorWHITE, 157 surfaceScale, ks, shininess, input, cr)); 158 drawClippedBitmap(canvas, paint, 330, y); 159 160 // Spot light with falloff exponent 161 paint.setImageFilter(SkImageFilters::SpotLitSpecular( 162 spotLocation, spotTarget, spotExponent1, cutoffAngleNone, SK_ColorWHITE, 163 surfaceScaleSmall, ks, shininess, input, cr)); 164 drawClippedBitmap(canvas, paint, 440, y); 165 166 // Large constant to show oversaturation 167 paint.setImageFilter(SkImageFilters::DistantLitSpecular( 168 distantDirection, greenYellow, surfaceScale, 4.f * ks, shininess, input, cr)); 169 drawClippedBitmap(canvas, paint, 550, y); 170 171 y += 110; 172 } 173 } 174 onAnimate(double nanos)175 bool onAnimate(double nanos) override { 176 constexpr SkScalar kDesiredDurationSecs = 15.0f; 177 178 fAzimuth = kStartAzimuth + TimeUtils::Scaled(1e-9 * nanos, 360.0f/kDesiredDurationSecs, 360.0f); 179 return true; 180 } 181 182 private: 183 inline static constexpr int kStartAzimuth = 225; 184 185 SkBitmap fBitmap; 186 SkScalar fAzimuth; 187 188 using INHERITED = GM; 189 }; 190 191 ////////////////////////////////////////////////////////////////////////////// 192 193 DEF_GM(return new ImageLightingGM;) 194 } // namespace skiagm 195