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/fonts/FontToolUtils.h" 23 #include "tools/timer/TimeUtils.h" 24 25 #define WIDTH 660 26 #define HEIGHT 660 27 28 namespace skiagm { 29 30 class ImageLightingGM : public GM { 31 public: ImageLightingGM()32 ImageLightingGM() 33 : fAzimuth(SkIntToScalar(kStartAzimuth)) { 34 this->setBGColor(0xFF000000); 35 } 36 37 protected: getName() const38 SkString getName() const override { return SkString("lighting"); } 39 getISize()40 SkISize getISize() override { return SkISize::Make(WIDTH, HEIGHT); } 41 drawClippedBitmap(SkCanvas * canvas,const SkPaint & paint,int x,int y)42 void drawClippedBitmap(SkCanvas* canvas, const SkPaint& paint, int x, int y) { 43 canvas->save(); 44 canvas->translate(SkIntToScalar(x), SkIntToScalar(y)); 45 canvas->clipIRect(fBitmap.bounds()); 46 canvas->drawImage(fBitmap.asImage(), 0, 0, SkSamplingOptions(), &paint); 47 canvas->restore(); 48 } 49 onOnceBeforeDraw()50 void onOnceBeforeDraw() override { 51 fBitmap = ToolUtils::CreateStringBitmap(100, 100, 0xFFFFFFFF, 20, 70, 96, "e"); 52 } 53 onDraw(SkCanvas * canvas)54 void onDraw(SkCanvas* canvas) override { 55 canvas->clear(0xFF101010); 56 SkPaint checkPaint; 57 checkPaint.setColor(0xFF202020); 58 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 } 67 SkScalar sinAzimuth = SkScalarSin(SkDegreesToRadians(fAzimuth)), 68 cosAzimuth = SkScalarCos(SkDegreesToRadians(fAzimuth)); 69 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)); 74 SkScalar spotExponent1 = SK_Scalar1; 75 SkScalar spotExponent10 = SkIntToScalar(10); 76 SkScalar cutoffAngleSmall = SkIntToScalar(15); 77 SkScalar cutoffAngleNone = SkIntToScalar(180); 78 79 SkPoint3 pointLocation = SkPoint3::Make(spotTarget.fX + 50 * cosAzimuth, 80 spotTarget.fY + 50 * sinAzimuth, 81 SkIntToScalar(10)); 82 SkScalar elevationRad = SkDegreesToRadians(SkIntToScalar(5)); 83 84 SkPoint3 distantDirection = SkPoint3::Make(cosAzimuth * SkScalarCos(elevationRad), 85 sinAzimuth * SkScalarCos(elevationRad), 86 SkScalarSin(elevationRad)); 87 SkScalar kd = SkIntToScalar(2); 88 SkScalar ks = SkIntToScalar(1); 89 SkScalar shininess = SkIntToScalar(8); 90 SkScalar surfaceScale = SkIntToScalar(1); 91 SkScalar surfaceScaleSmall = 0.1f; 92 SkColor greenYellow = SkColorSetARGB(255, 173, 255, 47); 93 SkPaint paint; 94 95 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)); 98 99 int y = 0; 100 for (int i = 0; i < 3; i++) { 101 const SkIRect* cr = (i == 1) ? &cropRect : (i == 2) ? &fullSizeCropRect : nullptr; 102 sk_sp<SkImageFilter> input = (i == 2) ? noopCropped : nullptr; 103 // Basic point, distant and spot lights with diffuse lighting 104 paint.setImageFilter(SkImageFilters::PointLitDiffuse( 105 pointLocation, SK_ColorWHITE, surfaceScale, kd, input, cr)); 106 drawClippedBitmap(canvas, paint, 0, y); 107 108 paint.setImageFilter(SkImageFilters::DistantLitDiffuse( 109 distantDirection, SK_ColorWHITE, surfaceScale, kd, input, cr)); 110 drawClippedBitmap(canvas, paint, 110, y); 111 112 paint.setImageFilter(SkImageFilters::SpotLitDiffuse( 113 spotLocation, spotTarget, spotExponent1, cutoffAngleSmall, SK_ColorWHITE, 114 surfaceScale, kd, input, cr)); 115 drawClippedBitmap(canvas, paint, 220, y); 116 117 // 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 134 y += 110; 135 136 // Basic point, distant and spot lights with specular lighting 137 paint.setImageFilter(SkImageFilters::PointLitSpecular( 138 pointLocation, SK_ColorWHITE, surfaceScale, ks, shininess, input, cr)); 139 drawClippedBitmap(canvas, paint, 0, y); 140 141 paint.setImageFilter(SkImageFilters::DistantLitSpecular( 142 distantDirection, SK_ColorWHITE, surfaceScale, ks, shininess, input, cr)); 143 drawClippedBitmap(canvas, paint, 110, y); 144 145 paint.setImageFilter(SkImageFilters::SpotLitSpecular( 146 spotLocation, spotTarget, spotExponent1, cutoffAngleSmall, SK_ColorWHITE, 147 surfaceScale, ks, shininess, input, cr)); 148 drawClippedBitmap(canvas, paint, 220, y); 149 150 // 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 167 y += 110; 168 } 169 } 170 onAnimate(double nanos)171 bool onAnimate(double nanos) override { 172 constexpr SkScalar kDesiredDurationSecs = 15.0f; 173 174 fAzimuth = kStartAzimuth + TimeUtils::Scaled(1e-9 * nanos, 360.0f/kDesiredDurationSecs, 360.0f); 175 return true; 176 } 177 178 private: 179 inline static constexpr int kStartAzimuth = 225; 180 181 SkBitmap fBitmap; 182 SkScalar fAzimuth; 183 184 using INHERITED = GM; 185 }; 186 187 ////////////////////////////////////////////////////////////////////////////// 188 189 DEF_GM(return new ImageLightingGM;) 190 } // namespace skiagm 191