2 * Copyright 2016 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
9 #include "sk_tool_utils.h"
10 #include "SkLightingShader.h"
11 #include "SkNormalSource.h"
19 // This GM exercises lighting shaders when used with bevel SkNormalSource objects.
20 class LightingShaderBevelGM : public GM {
22 LightingShaderBevelGM() {
23 this->setBGColor(sk_tool_utils::color_to_565(0xFFCCCCCC));
27 SkString onShortName() override {
28 return SkString("lightingshaderbevel");
31 SkISize onISize() override {
32 return SkISize::Make(SkScalarCeilToInt(GRID_NUM_COLUMNS * GRID_CELL_WIDTH),
33 SkScalarCeilToInt(GRID_NUM_ROWS * GRID_CELL_WIDTH));
36 void onOnceBeforeDraw() override {
37 SkLights::Builder builder;
38 const SkVector3 kLightFromUpperRight = SkVector3::Make(0.788f, 0.394f, 0.473f);
40 builder.add(SkLights::Light::MakeDirectional(SkColor3f::Make(1.0f, 1.0f, 1.0f),
41 kLightFromUpperRight));
42 builder.setAmbientLightColor(SkColor3f::Make(0.2f, 0.2f, 0.2f));
43 fLights = builder.finish();
45 // fRect is assumed to be square throughout this file
46 fRect = SkRect::MakeIWH(kTexSize, kTexSize);
48 SkRect bitmapBounds = SkRect::MakeIWH(kTexSize, kTexSize);
49 matrix.setRectToRect(bitmapBounds, fRect, SkMatrix::kFill_ScaleToFit);
51 SkBitmap diffuseMap = sk_tool_utils::create_checkerboard_bitmap(
53 sk_tool_utils::color_to_565(0x0),
54 sk_tool_utils::color_to_565(0xFF804020),
56 fDiffuse = SkShader::MakeBitmapShader(diffuseMap, SkShader::kClamp_TileMode,
57 SkShader::kClamp_TileMode, &matrix);
59 fConvexPath.moveTo(fRect.width() / 2.0f, 0.0f);
60 fConvexPath.lineTo(0.0f, fRect.height());
61 fConvexPath.lineTo(fRect.width(), fRect.height());
64 // Creating concave path
67 SkScalar y = fRect.height() / 2.0f;
69 const int NUM_SPIKES = 8;
71 const SkScalar x0 = x;
72 const SkScalar dx = fRect.width() / (NUM_SPIKES * 2);
73 const SkScalar dy = SK_Scalar1 * 10;
76 fConcavePath.moveTo(x, y + dy);
77 for (int i = 0; i < NUM_SPIKES; i++) {
79 fConcavePath.lineTo(x, y - dy);
81 fConcavePath.lineTo(x, y + dy);
83 fConcavePath.lineTo(x, y + (2 * dy));
84 fConcavePath.lineTo(x0, y + (2 * dy));
89 // Scales shape around origin, rotates shape around origin, then translates shape to origin
90 void positionCTM(SkCanvas *canvas, SkScalar scaleX, SkScalar scaleY, SkScalar rotate) const {
91 canvas->translate(kTexSize/2.0f, kTexSize/2.0f);
92 canvas->scale(scaleX, scaleY);
93 canvas->rotate(rotate);
94 canvas->translate(-kTexSize/2.0f, -kTexSize/2.0f);
104 kLast_Shape = kConcavePath_Shape
106 void drawShape(enum Shape shape, SkCanvas* canvas, SkScalar scaleX, SkScalar scaleY,
107 SkScalar rotate, SkNormalSource::BevelType bevelType, SkScalar bevelHeight) {
110 this->positionCTM(canvas, scaleX, scaleY, rotate);
114 SkScalar bevelWidth = 10.0f;
115 sk_sp<SkNormalSource> normalSource = SkNormalSource::MakeBevel(bevelType, bevelWidth,
118 paint.setShader(SkLightingShader::Make(fDiffuse, std::move(normalSource), fLights));
119 paint.setAntiAlias(true);
122 canvas->drawCircle(fRect.centerX(), fRect.centerY(), fRect.width()/2.0f, paint);
125 canvas->drawRect(fRect, paint);
128 canvas->drawRoundRect(fRect, 5.0f, 5.0f, paint);
130 case kConvexPath_Shape:
131 canvas->drawPath(fConvexPath, paint);
133 case kConcavePath_Shape:
134 canvas->drawPath(fConcavePath, paint);
137 SkDEBUGFAIL("Invalid shape enum for drawShape");
143 void onDraw(SkCanvas* canvas) override {
145 labelPaint.setTypeface(sk_tool_utils::create_portable_typeface("sans-serif",
147 labelPaint.setAntiAlias(true);
148 labelPaint.setTextSize(LABEL_SIZE);
152 // Running through all possible parameter combinations
153 for (auto bevelType : {SkNormalSource::BevelType::kLinear,
154 SkNormalSource::BevelType::kRoundedIn,
155 SkNormalSource::BevelType::kRoundedOut}) {
156 for (SkScalar bevelHeight: {-7.0f, 7.0f}) {
157 for (int shapeInt = 0; shapeInt < NUM_SHAPES; shapeInt++) {
158 Shape shape = (Shape)shapeInt;
160 // Determining position
161 SkScalar xPos = (gridNum / GRID_NUM_ROWS) * GRID_CELL_WIDTH;
162 SkScalar yPos = (gridNum % GRID_NUM_ROWS) * GRID_CELL_WIDTH;
166 canvas->translate(xPos, yPos);
167 this->drawShape(shape, canvas, 1.0f, 1.0f, 0.f, bevelType, bevelHeight);
169 canvas->translate(0.0f, SkIntToScalar(kTexSize));
171 canvas->translate(0.0f, LABEL_SIZE);
173 label.append("bevelType: ");
175 case SkNormalSource::BevelType::kLinear:
176 label.append("linear");
178 case SkNormalSource::BevelType::kRoundedIn:
179 label.append("roundedIn");
181 case SkNormalSource::BevelType::kRoundedOut:
182 label.append("roundedOut");
185 canvas->drawString(label, 0.0f, 0.0f, labelPaint);
188 canvas->translate(0.0f, LABEL_SIZE);
190 label.appendf("bevelHeight: %.1f", bevelHeight);
191 canvas->drawString(label, 0.0f, 0.0f, labelPaint);
202 for (int shapeInt = 0; shapeInt < NUM_SHAPES; shapeInt++) {
203 Shape shape = (Shape)shapeInt;
205 // Determining position
206 SkScalar xPos = (gridNum / GRID_NUM_ROWS) * GRID_CELL_WIDTH;
207 SkScalar yPos = (gridNum % GRID_NUM_ROWS) * GRID_CELL_WIDTH;
211 canvas->translate(xPos, yPos);
212 this->drawShape(shape, canvas, SK_ScalarRoot2Over2, SK_ScalarRoot2Over2, 45.0f,
213 SkNormalSource::BevelType::kLinear, 7.0f);
216 canvas->translate(0.0f, SkIntToScalar(kTexSize));
218 canvas->translate(0.0f, LABEL_SIZE);
220 label.appendf("bevelType: linear");
221 canvas->drawString(label, 0.0f, 0.0f, labelPaint);
224 canvas->translate(0.0f, LABEL_SIZE);
226 label.appendf("bevelHeight: %.1f", 7.0f);
227 canvas->drawString(label, 0.0f, 0.0f, labelPaint);
230 canvas->translate(0.0f, LABEL_SIZE);
232 label.appendf("rotated");
233 canvas->drawString(label, 0.0f, 0.0f, labelPaint);
241 // Making sure NUM_COMBINATIONS_PER_SHAPE is set correctly
242 SkASSERT(gridNum == (NUM_COMBINATIONS_PER_SHAPE*NUM_SHAPES));
246 static constexpr int kTexSize = 96;
247 static constexpr int NUM_SHAPES = kLast_Shape + 1;
248 static constexpr int NUM_COMBINATIONS_PER_SHAPE = 7;
249 static constexpr int GRID_NUM_ROWS = NUM_SHAPES;
250 static constexpr int GRID_NUM_COLUMNS = NUM_COMBINATIONS_PER_SHAPE;
251 static constexpr SkScalar LABEL_SIZE = 10.0f;
252 static constexpr int NUM_LABELS_PER_CELL = 3;
253 static constexpr SkScalar GRID_CELL_WIDTH = kTexSize + 10.0f + NUM_LABELS_PER_CELL * LABEL_SIZE;
255 sk_sp<SkShader> fDiffuse;
260 sk_sp<SkLights> fLights;
262 typedef GM INHERITED;
265 //////////////////////////////////////////////////////////////////////////////
267 DEF_GM(return new LightingShaderBevelGM;)