Chromium Code Reviews| Index: gm/lightingshaderbevel.cpp |
| diff --git a/gm/lightingshaderbevel.cpp b/gm/lightingshaderbevel.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..c7b597db040d7562b08a227567d93f2ca76b8195 |
| --- /dev/null |
| +++ b/gm/lightingshaderbevel.cpp |
| @@ -0,0 +1,212 @@ |
| +/* |
| + * Copyright 2016 Google Inc. |
| + * |
| + * Use of this source code is governed by a BSD-style license that can be |
| + * found in the LICENSE file. |
| + */ |
| + |
| +#include "gm.h" |
| + |
| +#include "SkBitmapProcShader.h" |
| +#include "SkLightingShader.h" |
| +#include "SkNormalSource.h" |
| +#include "SkPath.h" |
| +#include "SkPoint3.h" |
| +#include "SkShader.h" |
| + |
| + |
| +namespace skiagm { |
| + |
| +// This GM exercises lighting shaders when used with bevel SkNormalSource objects. |
| +class LightingShaderBevelGM : public GM { |
| +public: |
| + LightingShaderBevelGM() { |
| + this->setBGColor(sk_tool_utils::color_to_565(0xFFCCCCCC)); |
| + } |
| + |
| +protected: |
| + SkString onShortName() override { |
| + return SkString("lightingshaderbevel"); |
| + } |
| + |
| + SkISize onISize() override { |
| + return SkISize::Make(SkScalarCeilToInt(GRID_NUM_COLUMNS * GRID_CELL_WIDTH), |
| + SkScalarCeilToInt(GRID_NUM_ROWS * GRID_CELL_WIDTH)); |
| + } |
| + |
| + void onOnceBeforeDraw() override { |
| + SkLights::Builder builder; |
| + const SkVector3 kLightFromUpperRight = SkVector3::Make(0.788f, 0.394f, 0.473f); |
| + |
| + builder.add(SkLights::Light(SkColor3f::Make(1.0f, 1.0f, 1.0f), |
| + kLightFromUpperRight)); |
| + builder.add(SkLights::Light(SkColor3f::Make(0.2f, 0.2f, 0.2f))); |
| + fLights = builder.finish(); |
| + |
| + // fRect is assumed to be square throughout this file |
| + fRect = SkRect::MakeIWH(kTexSize, kTexSize); |
| + SkMatrix matrix; |
| + SkRect bitmapBounds = SkRect::MakeIWH(kTexSize, kTexSize); |
| + matrix.setRectToRect(bitmapBounds, fRect, SkMatrix::kFill_ScaleToFit); |
| + |
| + SkBitmap diffuseMap = sk_tool_utils::create_checkerboard_bitmap( |
| + kTexSize, kTexSize, |
| + sk_tool_utils::color_to_565(0x0), |
| + sk_tool_utils::color_to_565(0xFF804020), |
| + 8); |
| + fDiffuse = SkMakeBitmapShader(diffuseMap, SkShader::kClamp_TileMode, |
| + SkShader::kClamp_TileMode, &matrix, nullptr); |
| + |
| + fConvexPath.moveTo(fRect.width() / 2.0f, 0.0f); |
| + fConvexPath.lineTo(0.0f, fRect.height()); |
| + fConvexPath.lineTo(fRect.width(), fRect.height()); |
| + fConvexPath.close(); |
| + |
| + // Creating concave path |
| + { |
| + SkScalar x = 0.0f; |
| + SkScalar y = fRect.height() / 2.0f; |
| + |
| + const int NUM_SPIKES = 8; |
| + |
| + const SkScalar x0 = x; |
| + const SkScalar dx = fRect.width() / (NUM_SPIKES * 2); |
| + const SkScalar dy = SK_Scalar1 * 10; |
| + |
| + |
| + fConcavePath.moveTo(x, y + dy); |
| + for (int i = 0; i < NUM_SPIKES; i++) { |
| + x += dx; |
| + fConcavePath.lineTo(x, y - dy); |
| + x += dx; |
| + fConcavePath.lineTo(x, y + dy); |
| + } |
| + fConcavePath.lineTo(x, y + (2 * dy)); |
| + fConcavePath.lineTo(x0, y + (2 * dy)); |
| + fConcavePath.close(); |
| + } |
| + } |
| + |
| + // Scales shape around origin, rotates shape around origin, then translates shape to origin |
| + void positionCTM(SkCanvas *canvas, SkScalar scaleX, SkScalar scaleY, SkScalar rotate) const { |
| + canvas->translate(kTexSize/2.0f, kTexSize/2.0f); |
| + canvas->scale(scaleX, scaleY); |
| + canvas->rotate(rotate); |
| + canvas->translate(-kTexSize/2.0f, -kTexSize/2.0f); |
| + } |
| + |
| + enum Shape { |
| + kCircle_Shape, |
| + kRect_Shape, |
| + kRRect_Shape, |
| + kConvexPath_Shape, |
| + kConcavePath_Shape, |
| + |
| + kLast_Shape = kConcavePath_Shape |
| + }; |
| + void drawShape(enum Shape shape, SkCanvas* canvas, SkScalar scaleX, SkScalar scaleY, |
| + SkScalar rotate, SkNormalSource::BevelType bevelType, bool useNegativeHeight) { |
| + canvas->save(); |
| + |
| + this->positionCTM(canvas, scaleX, scaleY, rotate); |
| + |
| + SkPaint paint; |
| + |
| + int width = 10.0f; |
| + int height = useNegativeHeight ? -7.0f : 7.0f; |
| + sk_sp<SkNormalSource> normalSource = SkNormalSource::MakeBevel(bevelType, width, height); |
| + |
| + paint.setShader(SkLightingShader::Make(fDiffuse, std::move(normalSource), fLights)); |
| + switch(shape) { |
| + case kCircle_Shape: |
| + paint.setAntiAlias(true); |
|
egdaniel
2016/07/27 17:57:28
I would set AntiAlias for all the shapes
dvonbeck
2016/07/27 18:46:36
Done.
|
| + canvas->drawCircle(fRect.centerX(), fRect.centerY(), fRect.width()/2.0f, paint); |
| + break; |
| + case kRect_Shape: |
| + canvas->drawRect(fRect, paint); |
| + break; |
| + case kRRect_Shape: |
| + canvas->drawRoundRect(fRect, 5.0f, 5.0f, paint); |
| + break; |
| + case kConvexPath_Shape: |
| + canvas->drawPath(fConvexPath, paint); |
| + break; |
| + case kConcavePath_Shape: |
| + canvas->drawPath(fConcavePath, paint); |
| + break; |
| + default: |
| + SkDEBUGFAIL("Invalid shape enum for drawShape"); |
| + } |
| + |
| + canvas->restore(); |
| + } |
| + |
| + void onDraw(SkCanvas* canvas) override { |
| + SkPaint labelPaint; |
| + labelPaint.setTypeface(sk_tool_utils::create_portable_typeface("sans-serif", |
| + SkFontStyle())); |
| + labelPaint.setAntiAlias(true); |
| + labelPaint.setTextSize(LABEL_SIZE); |
| + |
| + int gridNum = 0; |
| + |
| + // Running through all possible parameter combinations |
| + for (int shapeInt = 0; shapeInt < NUM_SHAPES; shapeInt++) { |
| + Shape shape = (Shape)shapeInt; |
| + for (auto bevelType : {SkNormalSource::BevelType::kLinear, |
| + SkNormalSource::BevelType::kRoundedIn, |
| + SkNormalSource::BevelType::kRoundedOut}) { |
| + for (bool useNegativeHeight : {true, false}) { |
| + |
| + // Making sure NUM_COMBINATIONS_PER_SHAPE is set correctly |
| + SkASSERT(gridNum < (NUM_COMBINATIONS_PER_SHAPE*NUM_SHAPES)); |
| + |
| + // Determining position |
| + SkScalar xPos = (gridNum % GRID_NUM_COLUMNS) * GRID_CELL_WIDTH; |
| + SkScalar yPos = (gridNum / GRID_NUM_COLUMNS) * GRID_CELL_WIDTH; |
| + |
| + canvas->save(); |
| + |
| + canvas->translate(xPos, yPos); |
| + this->drawShape(shape, canvas, 1.0f, 1.0f, 0.f, bevelType, useNegativeHeight); |
| + // Drawing labels |
| + canvas->translate(0.0f, SkIntToScalar(kTexSize)); |
| + { |
| + canvas->translate(0.0f, LABEL_SIZE); |
| + SkString label; |
| + label.appendf("useNegativeHeight: %d", useNegativeHeight); |
|
egdaniel
2016/07/27 17:57:28
info on the bevel height would be interesting to r
dvonbeck
2016/07/27 18:46:36
Done.
|
| + canvas->drawText(label.c_str(), label.size(), 0.0f, 0.0f, labelPaint); |
| + } |
| + |
| + canvas->restore(); |
| + |
| + gridNum++; |
| + } |
| + } |
|
egdaniel
2016/07/27 17:57:28
lets also add a rotated column at the end, but we
dvonbeck
2016/07/27 18:46:36
Done.
|
| + } |
| + } |
| + |
| +private: |
| + static constexpr int kTexSize = 96; |
| + static constexpr int NUM_SHAPES = kLast_Shape + 1; |
| + static constexpr int NUM_COMBINATIONS_PER_SHAPE = 6; |
| + static constexpr int GRID_NUM_ROWS = NUM_SHAPES; |
| + static constexpr int GRID_NUM_COLUMNS = NUM_COMBINATIONS_PER_SHAPE; |
| + static constexpr SkScalar LABEL_SIZE = 10.0f; |
| + static constexpr int NUM_LABELS_PER_CELL = 2; |
| + static constexpr SkScalar GRID_CELL_WIDTH = kTexSize + 20.0f + NUM_LABELS_PER_CELL * LABEL_SIZE; |
| + |
| + sk_sp<SkShader> fDiffuse; |
| + |
| + SkRect fRect; |
| + SkPath fConvexPath; |
| + SkPath fConcavePath; |
| + sk_sp<SkLights> fLights; |
| + |
| + typedef GM INHERITED; |
| +}; |
| + |
| +////////////////////////////////////////////////////////////////////////////// |
| + |
| +DEF_GM(return new LightingShaderBevelGM;) |
| +} |