2013-04-05 13:47:09 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2013 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "gm/gm.h"
|
2019-05-01 21:28:53 +00:00
|
|
|
#include "include/core/SkCanvas.h"
|
|
|
|
#include "include/core/SkColor.h"
|
|
|
|
#include "include/core/SkMatrix.h"
|
|
|
|
#include "include/core/SkPaint.h"
|
|
|
|
#include "include/core/SkRect.h"
|
|
|
|
#include "include/core/SkRefCnt.h"
|
|
|
|
#include "include/core/SkScalar.h"
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "include/core/SkShader.h"
|
2019-05-01 21:28:53 +00:00
|
|
|
#include "include/core/SkSize.h"
|
|
|
|
#include "include/core/SkString.h"
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "include/effects/SkPerlinNoiseShader.h"
|
2017-05-18 15:52:59 +00:00
|
|
|
|
2019-05-01 21:28:53 +00:00
|
|
|
#include <utility>
|
|
|
|
|
2017-05-18 15:52:59 +00:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
enum class Type {
|
|
|
|
kFractalNoise,
|
|
|
|
kTurbulence,
|
|
|
|
};
|
|
|
|
|
2014-05-12 17:18:45 +00:00
|
|
|
class PerlinNoiseGM : public skiagm::GM {
|
2019-07-18 15:51:19 +00:00
|
|
|
SkISize fSize = {80, 80};
|
2013-04-05 13:47:09 +00:00
|
|
|
|
2019-07-18 15:51:19 +00:00
|
|
|
void onOnceBeforeDraw() override { this->setBGColor(0xFF000000); }
|
2013-04-05 13:47:09 +00:00
|
|
|
|
2019-07-18 15:51:19 +00:00
|
|
|
SkString onShortName() override { return SkString("perlinnoise"); }
|
|
|
|
|
2021-01-08 23:11:33 +00:00
|
|
|
SkISize onISize() override { return {200, 500}; }
|
2013-04-05 13:47:09 +00:00
|
|
|
|
Fix tiled perlin noise.
It turns out that the perlin implementation we inherited from WebKit
does not actually generate tileable noise (see Chromium bug
http://crbug.com/383495).
The main problem is that when generating coordinates for gradient
interpolation, it was attempting to wrap both x and (x + 1)
simultaneously at the tile boundary (that is, either both or neither
are wrapped). This obviously won't work, since along the tile seams,
(x + 1) should be wrapped, but x should not. The same is true in y.
This patch fixes both the CPU and GPU paths, renames some variables to
more closely match the spec, and modifies the perlin noise GM to
actually test tiling. (Note that the clipping the GM was doing was
removed, since it's superfluous: it used to be necessary for image
filters, but isn't anymore, and this isn't an image filter GM anyway.)
R=sugoi@google.com, sugoi
TBR=senorblanco
Author: senorblanco@chromium.org
Review URL: https://codereview.chromium.org/332523006
2014-06-12 18:24:19 +00:00
|
|
|
void drawRect(SkCanvas* canvas, int x, int y, const SkPaint& paint, const SkISize& size) {
|
2013-04-05 13:47:09 +00:00
|
|
|
canvas->save();
|
Fix tiled perlin noise.
It turns out that the perlin implementation we inherited from WebKit
does not actually generate tileable noise (see Chromium bug
http://crbug.com/383495).
The main problem is that when generating coordinates for gradient
interpolation, it was attempting to wrap both x and (x + 1)
simultaneously at the tile boundary (that is, either both or neither
are wrapped). This obviously won't work, since along the tile seams,
(x + 1) should be wrapped, but x should not. The same is true in y.
This patch fixes both the CPU and GPU paths, renames some variables to
more closely match the spec, and modifies the perlin noise GM to
actually test tiling. (Note that the clipping the GM was doing was
removed, since it's superfluous: it used to be necessary for image
filters, but isn't anymore, and this isn't an image filter GM anyway.)
R=sugoi@google.com, sugoi
TBR=senorblanco
Author: senorblanco@chromium.org
Review URL: https://codereview.chromium.org/332523006
2014-06-12 18:24:19 +00:00
|
|
|
canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
|
|
|
|
SkRect r = SkRect::MakeWH(SkIntToScalar(size.width()),
|
|
|
|
SkIntToScalar(size.height()));
|
2013-04-05 13:47:09 +00:00
|
|
|
canvas->drawRect(r, paint);
|
|
|
|
canvas->restore();
|
|
|
|
}
|
|
|
|
|
2017-05-18 15:52:59 +00:00
|
|
|
void test(SkCanvas* canvas, int x, int y, Type type,
|
2021-01-08 23:11:33 +00:00
|
|
|
float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed,
|
2013-04-17 13:46:56 +00:00
|
|
|
bool stitchTiles) {
|
Fix tiled perlin noise.
It turns out that the perlin implementation we inherited from WebKit
does not actually generate tileable noise (see Chromium bug
http://crbug.com/383495).
The main problem is that when generating coordinates for gradient
interpolation, it was attempting to wrap both x and (x + 1)
simultaneously at the tile boundary (that is, either both or neither
are wrapped). This obviously won't work, since along the tile seams,
(x + 1) should be wrapped, but x should not. The same is true in y.
This patch fixes both the CPU and GPU paths, renames some variables to
more closely match the spec, and modifies the perlin noise GM to
actually test tiling. (Note that the clipping the GM was doing was
removed, since it's superfluous: it used to be necessary for image
filters, but isn't anymore, and this isn't an image filter GM anyway.)
R=sugoi@google.com, sugoi
TBR=senorblanco
Author: senorblanco@chromium.org
Review URL: https://codereview.chromium.org/332523006
2014-06-12 18:24:19 +00:00
|
|
|
SkISize tileSize = SkISize::Make(fSize.width() / 2, fSize.height() / 2);
|
2021-01-07 00:30:00 +00:00
|
|
|
sk_sp<SkShader> shader;
|
|
|
|
switch (type) {
|
|
|
|
case Type::kFractalNoise:
|
|
|
|
shader = SkPerlinNoiseShader::MakeFractalNoise(baseFrequencyX,
|
|
|
|
baseFrequencyY,
|
|
|
|
numOctaves,
|
2021-01-08 23:11:33 +00:00
|
|
|
seed,
|
2021-01-07 00:30:00 +00:00
|
|
|
stitchTiles ? &tileSize : nullptr);
|
|
|
|
break;
|
|
|
|
case Type::kTurbulence:
|
|
|
|
shader = SkPerlinNoiseShader::MakeTurbulence(baseFrequencyX,
|
|
|
|
baseFrequencyY,
|
|
|
|
numOctaves,
|
2021-01-08 23:11:33 +00:00
|
|
|
seed,
|
2021-01-07 00:30:00 +00:00
|
|
|
stitchTiles ? &tileSize : nullptr);
|
|
|
|
break;
|
|
|
|
}
|
2013-04-05 13:47:09 +00:00
|
|
|
SkPaint paint;
|
2016-03-25 16:08:00 +00:00
|
|
|
paint.setShader(std::move(shader));
|
Fix tiled perlin noise.
It turns out that the perlin implementation we inherited from WebKit
does not actually generate tileable noise (see Chromium bug
http://crbug.com/383495).
The main problem is that when generating coordinates for gradient
interpolation, it was attempting to wrap both x and (x + 1)
simultaneously at the tile boundary (that is, either both or neither
are wrapped). This obviously won't work, since along the tile seams,
(x + 1) should be wrapped, but x should not. The same is true in y.
This patch fixes both the CPU and GPU paths, renames some variables to
more closely match the spec, and modifies the perlin noise GM to
actually test tiling. (Note that the clipping the GM was doing was
removed, since it's superfluous: it used to be necessary for image
filters, but isn't anymore, and this isn't an image filter GM anyway.)
R=sugoi@google.com, sugoi
TBR=senorblanco
Author: senorblanco@chromium.org
Review URL: https://codereview.chromium.org/332523006
2014-06-12 18:24:19 +00:00
|
|
|
if (stitchTiles) {
|
|
|
|
drawRect(canvas, x, y, paint, tileSize);
|
|
|
|
x += tileSize.width();
|
|
|
|
drawRect(canvas, x, y, paint, tileSize);
|
|
|
|
y += tileSize.width();
|
|
|
|
drawRect(canvas, x, y, paint, tileSize);
|
|
|
|
x -= tileSize.width();
|
|
|
|
drawRect(canvas, x, y, paint, tileSize);
|
|
|
|
} else {
|
|
|
|
drawRect(canvas, x, y, paint, fSize);
|
|
|
|
}
|
2013-04-05 13:47:09 +00:00
|
|
|
}
|
|
|
|
|
2019-07-18 15:51:19 +00:00
|
|
|
void onDraw(SkCanvas* canvas) override {
|
2015-04-09 18:13:24 +00:00
|
|
|
canvas->clear(SK_ColorBLACK);
|
2017-05-18 15:52:59 +00:00
|
|
|
test(canvas, 0, 0, Type::kFractalNoise,
|
2013-11-06 10:08:38 +00:00
|
|
|
0.1f, 0.1f, 0, 0, false);
|
2017-05-18 15:52:59 +00:00
|
|
|
test(canvas, 100, 0, Type::kTurbulence,
|
2013-11-06 10:08:38 +00:00
|
|
|
0.1f, 0.1f, 0, 0, false);
|
2013-04-06 07:01:10 +00:00
|
|
|
|
2017-05-18 15:52:59 +00:00
|
|
|
test(canvas, 0, 100, Type::kFractalNoise,
|
2013-04-05 13:47:09 +00:00
|
|
|
0.1f, 0.1f, 2, 0, false);
|
2017-05-18 15:52:59 +00:00
|
|
|
test(canvas, 100, 100, Type::kFractalNoise,
|
Fix tiled perlin noise.
It turns out that the perlin implementation we inherited from WebKit
does not actually generate tileable noise (see Chromium bug
http://crbug.com/383495).
The main problem is that when generating coordinates for gradient
interpolation, it was attempting to wrap both x and (x + 1)
simultaneously at the tile boundary (that is, either both or neither
are wrapped). This obviously won't work, since along the tile seams,
(x + 1) should be wrapped, but x should not. The same is true in y.
This patch fixes both the CPU and GPU paths, renames some variables to
more closely match the spec, and modifies the perlin noise GM to
actually test tiling. (Note that the clipping the GM was doing was
removed, since it's superfluous: it used to be necessary for image
filters, but isn't anymore, and this isn't an image filter GM anyway.)
R=sugoi@google.com, sugoi
TBR=senorblanco
Author: senorblanco@chromium.org
Review URL: https://codereview.chromium.org/332523006
2014-06-12 18:24:19 +00:00
|
|
|
0.05f, 0.1f, 1, 0, true);
|
2013-04-05 13:47:09 +00:00
|
|
|
|
2017-05-18 15:52:59 +00:00
|
|
|
test(canvas, 0, 200, Type::kTurbulence,
|
Fix tiled perlin noise.
It turns out that the perlin implementation we inherited from WebKit
does not actually generate tileable noise (see Chromium bug
http://crbug.com/383495).
The main problem is that when generating coordinates for gradient
interpolation, it was attempting to wrap both x and (x + 1)
simultaneously at the tile boundary (that is, either both or neither
are wrapped). This obviously won't work, since along the tile seams,
(x + 1) should be wrapped, but x should not. The same is true in y.
This patch fixes both the CPU and GPU paths, renames some variables to
more closely match the spec, and modifies the perlin noise GM to
actually test tiling. (Note that the clipping the GM was doing was
removed, since it's superfluous: it used to be necessary for image
filters, but isn't anymore, and this isn't an image filter GM anyway.)
R=sugoi@google.com, sugoi
TBR=senorblanco
Author: senorblanco@chromium.org
Review URL: https://codereview.chromium.org/332523006
2014-06-12 18:24:19 +00:00
|
|
|
0.1f, 0.1f, 1, 0, true);
|
2017-05-18 15:52:59 +00:00
|
|
|
test(canvas, 100, 200, Type::kTurbulence,
|
2013-04-05 13:47:09 +00:00
|
|
|
0.2f, 0.4f, 5, 0, false);
|
|
|
|
|
2017-05-18 15:52:59 +00:00
|
|
|
test(canvas, 0, 300, Type::kFractalNoise,
|
2013-04-05 13:47:09 +00:00
|
|
|
0.1f, 0.1f, 3, 1, false);
|
2017-05-18 15:52:59 +00:00
|
|
|
test(canvas, 100, 300, Type::kFractalNoise,
|
2013-04-05 13:47:09 +00:00
|
|
|
0.1f, 0.1f, 3, 4, false);
|
|
|
|
|
2013-11-25 19:44:07 +00:00
|
|
|
canvas->scale(0.75f, 1.0f);
|
2013-04-05 13:47:09 +00:00
|
|
|
|
2021-01-08 23:11:33 +00:00
|
|
|
test(canvas, 0, 400, Type::kFractalNoise,
|
2013-04-05 13:47:09 +00:00
|
|
|
0.1f, 0.1f, 2, 0, false);
|
2021-01-08 23:11:33 +00:00
|
|
|
test(canvas, 100, 400, Type::kFractalNoise,
|
Fix tiled perlin noise.
It turns out that the perlin implementation we inherited from WebKit
does not actually generate tileable noise (see Chromium bug
http://crbug.com/383495).
The main problem is that when generating coordinates for gradient
interpolation, it was attempting to wrap both x and (x + 1)
simultaneously at the tile boundary (that is, either both or neither
are wrapped). This obviously won't work, since along the tile seams,
(x + 1) should be wrapped, but x should not. The same is true in y.
This patch fixes both the CPU and GPU paths, renames some variables to
more closely match the spec, and modifies the perlin noise GM to
actually test tiling. (Note that the clipping the GM was doing was
removed, since it's superfluous: it used to be necessary for image
filters, but isn't anymore, and this isn't an image filter GM anyway.)
R=sugoi@google.com, sugoi
TBR=senorblanco
Author: senorblanco@chromium.org
Review URL: https://codereview.chromium.org/332523006
2014-06-12 18:24:19 +00:00
|
|
|
0.1f, 0.05f, 1, 0, true);
|
2013-04-05 13:47:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2020-09-03 02:42:33 +00:00
|
|
|
using INHERITED = GM;
|
2013-04-05 13:47:09 +00:00
|
|
|
};
|
|
|
|
|
2014-05-12 17:18:45 +00:00
|
|
|
class PerlinNoiseGM2 : public skiagm::GM {
|
2019-07-18 15:51:19 +00:00
|
|
|
SkISize fSize = {80, 80};
|
2014-05-13 03:06:05 +00:00
|
|
|
|
2019-07-18 15:51:19 +00:00
|
|
|
SkString onShortName() override { return SkString("perlinnoise_localmatrix"); }
|
2014-05-13 03:06:05 +00:00
|
|
|
|
2019-07-18 15:51:19 +00:00
|
|
|
SkISize onISize() override { return {640, 480}; }
|
2014-05-13 03:06:05 +00:00
|
|
|
|
2017-05-18 15:52:59 +00:00
|
|
|
void install(SkPaint* paint, Type type,
|
2014-05-12 17:18:45 +00:00
|
|
|
float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed,
|
|
|
|
bool stitchTiles) {
|
2017-05-18 15:52:59 +00:00
|
|
|
sk_sp<SkShader> shader = (type == Type::kFractalNoise) ?
|
2016-03-25 16:08:00 +00:00
|
|
|
SkPerlinNoiseShader::MakeFractalNoise(baseFrequencyX, baseFrequencyY, numOctaves,
|
|
|
|
seed, stitchTiles ? &fSize : nullptr) :
|
|
|
|
SkPerlinNoiseShader::MakeTurbulence(baseFrequencyX, baseFrequencyY, numOctaves,
|
|
|
|
seed, stitchTiles ? &fSize : nullptr);
|
|
|
|
paint->setShader(std::move(shader));
|
2014-05-12 17:18:45 +00:00
|
|
|
}
|
2014-05-13 03:06:05 +00:00
|
|
|
|
2019-07-18 15:51:19 +00:00
|
|
|
void onDraw(SkCanvas* canvas) override {
|
2014-05-12 17:18:45 +00:00
|
|
|
canvas->translate(10, 10);
|
|
|
|
|
|
|
|
SkPaint paint;
|
2018-01-23 14:58:18 +00:00
|
|
|
this->install(&paint, Type::kFractalNoise, 0.1f, 0.1f, 2, 0, false);
|
2014-05-12 17:18:45 +00:00
|
|
|
|
|
|
|
const SkScalar w = SkIntToScalar(fSize.width());
|
|
|
|
const SkScalar h = SkIntToScalar(fSize.height());
|
|
|
|
|
|
|
|
SkRect r = SkRect::MakeWH(w, h);
|
|
|
|
canvas->drawRect(r, paint);
|
|
|
|
|
|
|
|
canvas->save();
|
|
|
|
canvas->translate(w * 5/4, 0);
|
|
|
|
canvas->drawRect(r, paint);
|
|
|
|
canvas->restore();
|
2013-04-05 13:47:09 +00:00
|
|
|
|
2014-05-12 17:18:45 +00:00
|
|
|
canvas->save();
|
|
|
|
canvas->translate(0, h + 10);
|
|
|
|
canvas->scale(2, 2);
|
|
|
|
canvas->drawRect(r, paint);
|
|
|
|
canvas->restore();
|
2014-05-13 03:06:05 +00:00
|
|
|
|
2014-05-12 17:18:45 +00:00
|
|
|
canvas->save();
|
|
|
|
canvas->translate(w + 100, h + 10);
|
|
|
|
canvas->scale(2, 2);
|
|
|
|
canvas->drawRect(r, paint);
|
|
|
|
canvas->restore();
|
|
|
|
|
|
|
|
// The next row should draw the same as the previous, even though we are using a local
|
|
|
|
// matrix instead of the canvas.
|
|
|
|
|
|
|
|
canvas->translate(0, h * 2 + 10);
|
|
|
|
|
|
|
|
SkMatrix lm;
|
|
|
|
lm.setScale(2, 2);
|
2016-03-10 14:36:49 +00:00
|
|
|
paint.setShader(paint.getShader()->makeWithLocalMatrix(lm));
|
2014-05-12 17:18:45 +00:00
|
|
|
r.fRight += r.width();
|
|
|
|
r.fBottom += r.height();
|
|
|
|
|
|
|
|
canvas->save();
|
|
|
|
canvas->translate(0, h + 10);
|
|
|
|
canvas->drawRect(r, paint);
|
|
|
|
canvas->restore();
|
2014-05-13 03:06:05 +00:00
|
|
|
|
2014-05-12 17:18:45 +00:00
|
|
|
canvas->save();
|
|
|
|
canvas->translate(w + 100, h + 10);
|
|
|
|
canvas->drawRect(r, paint);
|
|
|
|
canvas->restore();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-07-18 15:51:19 +00:00
|
|
|
} // namespace
|
2013-04-05 13:47:09 +00:00
|
|
|
|
2014-05-12 17:18:45 +00:00
|
|
|
DEF_GM( return new PerlinNoiseGM; )
|
|
|
|
DEF_GM( return new PerlinNoiseGM2; )
|