From fca294b83b9ffd77cab6326a8a76eb472b2b78d6 Mon Sep 17 00:00:00 2001 From: egdaniel Date: Thu, 5 Nov 2015 13:09:08 -0800 Subject: Create Sample that combines combose shader and coons patch BUG=skia: Review URL: https://codereview.chromium.org/1417123004 --- samplecode/PerlinPatch.cpp | 208 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 samplecode/PerlinPatch.cpp (limited to 'samplecode/PerlinPatch.cpp') 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 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(); ) + -- cgit v1.2.3