aboutsummaryrefslogtreecommitdiffhomepage
path: root/samplecode/PerlinPatch.cpp
diff options
context:
space:
mode:
authorGravatar egdaniel <egdaniel@google.com>2015-11-05 13:09:08 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2015-11-05 13:09:08 -0800
commitfca294b83b9ffd77cab6326a8a76eb472b2b78d6 (patch)
tree8d75c96b1ba7f3f73c12053adb59ab534c02038d /samplecode/PerlinPatch.cpp
parentb7ffe03b1283506d78310cf0fff17aa7e6d74e2a (diff)
Create Sample that combines combose shader and coons patch
Diffstat (limited to 'samplecode/PerlinPatch.cpp')
-rw-r--r--samplecode/PerlinPatch.cpp208
1 files changed, 208 insertions, 0 deletions
diff --git a/samplecode/PerlinPatch.cpp b/samplecode/PerlinPatch.cpp
new file mode 100644
index 0000000000..9f86f1f217
--- /dev/null
+++ b/samplecode/PerlinPatch.cpp
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SampleCode.h"
+#include "SkAnimTimer.h"
+#include "SkCanvas.h"
+#include "SkGradientShader.h"
+#include "SkPatchUtils.h"
+#include "SkPerlinNoiseShader.h"
+#include "SkComposeShader.h"
+
+static void draw_control_points(SkCanvas* canvas, const SkPoint cubics[12]) {
+ //draw control points
+ SkPaint paint;
+ SkPoint bottom[SkPatchUtils::kNumPtsCubic];
+ SkPatchUtils::getBottomCubic(cubics, bottom);
+ SkPoint top[SkPatchUtils::kNumPtsCubic];
+ SkPatchUtils::getTopCubic(cubics, top);
+ SkPoint left[SkPatchUtils::kNumPtsCubic];
+ SkPatchUtils::getLeftCubic(cubics, left);
+ SkPoint right[SkPatchUtils::kNumPtsCubic];
+ SkPatchUtils::getRightCubic(cubics, right);
+
+ paint.setColor(SK_ColorBLACK);
+ paint.setStrokeWidth(0.5f);
+ SkPoint corners[4] = { bottom[0], bottom[3], top[0], top[3] };
+ canvas->drawPoints(SkCanvas::kLines_PointMode, 4, bottom, paint);
+ canvas->drawPoints(SkCanvas::kLines_PointMode, 2, bottom + 1, paint);
+ canvas->drawPoints(SkCanvas::kLines_PointMode, 4, top, paint);
+ canvas->drawPoints(SkCanvas::kLines_PointMode, 4, left, paint);
+ canvas->drawPoints(SkCanvas::kLines_PointMode, 4, right, paint);
+
+ canvas->drawPoints(SkCanvas::kLines_PointMode, 2, top + 1, paint);
+ canvas->drawPoints(SkCanvas::kLines_PointMode, 2, left + 1, paint);
+ canvas->drawPoints(SkCanvas::kLines_PointMode, 2, right + 1, paint);
+
+ paint.setStrokeWidth(2);
+
+ paint.setColor(SK_ColorRED);
+ canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, corners, paint);
+
+ paint.setColor(SK_ColorBLUE);
+ canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, bottom + 1, paint);
+
+ paint.setColor(SK_ColorCYAN);
+ canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, top + 1, paint);
+
+ paint.setColor(SK_ColorYELLOW);
+ canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, left + 1, paint);
+
+ paint.setColor(SK_ColorGREEN);
+ canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, right + 1, paint);
+}
+
+// These are actually half the total width and hieghts
+const SkScalar TexWidth = 100.0f;
+const SkScalar TexHeight = 100.0f;
+
+class PerlinPatchView : public SampleView {
+ SkShader* fShader0;
+ SkShader* fShader1;
+ SkShader* fShaderCompose;
+ SkScalar fXFreq;
+ SkScalar fYFreq;
+ SkScalar fSeed;
+ SkPoint fPts[SkPatchUtils::kNumCtrlPts];
+ SkScalar fTexX;
+ SkScalar fTexY;
+ SkScalar fTexScale;
+ SkMatrix fInvMatrix;
+public:
+ PerlinPatchView() : fXFreq(0.025f), fYFreq(0.025f), fSeed(0.0f),
+ fTexX(100.0), fTexY(50.0), fTexScale(1.0f) {
+ // The order of the colors and points is clockwise starting at upper-left corner.
+ //top points
+ fPts[0].set(100, 100);
+ fPts[1].set(150, 50);
+ fPts[2].set(250, 150);
+ fPts[3].set(300, 100);
+ //right points
+ fPts[4].set(275, 150);
+ fPts[5].set(350, 250);
+ //bottom points
+ fPts[6].set(300, 300);
+ fPts[7].set(250, 250);
+ //left points
+ fPts[8].set(150, 350);
+ fPts[9].set(100, 300);
+ fPts[10].set(50, 250);
+ fPts[11].set(150, 150);
+
+ const SkColor colors[SkPatchUtils::kNumCorners] = {
+ SK_ColorBLUE, SK_ColorYELLOW
+ };
+
+ fShader0 = SkGradientShader::CreateRadial(SkPoint::Make(128.0f, 128.0f),
+ 180.0f,
+ colors,
+ NULL,
+ 2,
+ SkShader::kMirror_TileMode,
+ 0,
+ NULL);
+ fShader1 = SkPerlinNoiseShader::CreateTurbulence(fXFreq, fYFreq, 2, fSeed, NULL);
+ fShaderCompose = new SkComposeShader(fShader0, fShader1);
+ }
+
+ virtual ~PerlinPatchView() {
+ SkSafeUnref(fShader0);
+ SkSafeUnref(fShader1);
+ SkSafeUnref(fShaderCompose);
+ }
+protected:
+ // overrides from SkEventSink
+ bool onQuery(SkEvent* evt) override {
+ if (SampleCode::TitleQ(*evt)) {
+ SampleCode::TitleR(evt, "PerlinPatch");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ bool onAnimate(const SkAnimTimer& timer) override {
+ return true;
+ }
+
+
+ void onDrawContent(SkCanvas* canvas) override {
+ if (!canvas->getTotalMatrix().invert(&fInvMatrix)) {
+ return;
+ }
+
+ SkPaint paint;
+
+ SkScalar texWidth = fTexScale * TexWidth;
+ SkScalar texHeight = fTexScale * TexHeight;
+ const SkPoint texCoords[SkPatchUtils::kNumCorners] = {
+ { fTexX - texWidth, fTexY - texHeight},
+ { fTexX + texWidth, fTexY - texHeight},
+ { fTexX + texWidth, fTexY + texHeight},
+ { fTexX - texWidth, fTexY + texHeight}}
+ ;
+
+ SkAutoTUnref<SkXfermode> xfer(SkXfermode::Create(SkXfermode::kSrc_Mode));
+
+ paint.setShader(fShaderCompose);
+ canvas->drawPatch(fPts, nullptr, texCoords, xfer, paint);
+
+ draw_control_points(canvas, fPts);
+ }
+
+ class PtClick : public Click {
+ public:
+ int fIndex;
+ PtClick(SkView* view, int index) : Click(view), fIndex(index) {}
+ };
+
+ static bool hittest(const SkPoint& pt, SkScalar x, SkScalar y) {
+ return SkPoint::Length(pt.fX - x, pt.fY - y) < SkIntToScalar(5);
+ }
+
+ SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
+ // holding down shift
+ if (1 == modi) {
+ return new PtClick(this, -1);
+ }
+ // holding down ctrl
+ if (2 == modi) {
+ return new PtClick(this, -2);
+ }
+ SkPoint clickPoint = {x, y};
+ fInvMatrix.mapPoints(&clickPoint, 1);
+ for (size_t i = 0; i < SK_ARRAY_COUNT(fPts); i++) {
+ if (hittest(fPts[i], clickPoint.fX, clickPoint.fY)) {
+ return new PtClick(this, (int)i);
+ }
+ }
+ return this->INHERITED::onFindClickHandler(x, y, modi);
+ }
+
+ bool onClick(Click* click) override {
+ PtClick* ptClick = (PtClick*)click;
+ if (ptClick->fIndex >= 0) {
+ fPts[ptClick->fIndex].set(click->fCurr.fX , click->fCurr.fY );
+ } else if (-1 == ptClick->fIndex) {
+ SkScalar xDiff = click->fPrev.fX - click->fCurr.fX;
+ SkScalar yDiff = click->fPrev.fY - click->fCurr.fY;
+ fTexX += xDiff * fTexScale;
+ fTexY += yDiff * fTexScale;
+ } else if (-2 == ptClick->fIndex) {
+ SkScalar yDiff = click->fCurr.fY - click->fPrev.fY;
+ fTexScale += yDiff / 10.0f;
+ fTexScale = SkTMax(0.1f, SkTMin(20.f, fTexScale));
+ }
+ this->inval(nullptr);
+ return true;
+ }
+
+private:
+ typedef SampleView INHERITED;
+};
+
+DEF_SAMPLE( return new PerlinPatchView(); )
+