Remove Improved Perlin Noise
Is not used by a major client and can be implemented using runtime effects for users who want this noise. Bug: skia:10536 Change-Id: Iaa06e6e1406b808c7f8dc0f76621fecf2becabf5 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/352057 Reviewed-by: Brian Osman <brianosman@google.com> Reviewed-by: Kevin Lubick <kjlubick@google.com> Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
parent
70fa84a9bf
commit
4878b3e33c
@ -6,6 +6,9 @@ This file includes a list of high level updates for each milestone release.
|
||||
|
||||
Milestone 89
|
||||
------------
|
||||
* Removed SkPerlinNoiseShader::MakeImprovedNoise.
|
||||
https://review.skia.org/352057
|
||||
|
||||
* Removed deperated version of MakeFromYUVATextures. Use the version
|
||||
that takes GrYUVABackendTextures instead.
|
||||
https://review.skia.org/345174
|
||||
|
@ -25,7 +25,6 @@ namespace {
|
||||
enum class Type {
|
||||
kFractalNoise,
|
||||
kTurbulence,
|
||||
kImproved,
|
||||
};
|
||||
|
||||
class PerlinNoiseGM : public skiagm::GM {
|
||||
@ -35,7 +34,7 @@ class PerlinNoiseGM : public skiagm::GM {
|
||||
|
||||
SkString onShortName() override { return SkString("perlinnoise"); }
|
||||
|
||||
SkISize onISize() override { return {200, 600}; }
|
||||
SkISize onISize() override { return {200, 500}; }
|
||||
|
||||
void drawRect(SkCanvas* canvas, int x, int y, const SkPaint& paint, const SkISize& size) {
|
||||
canvas->save();
|
||||
@ -47,7 +46,7 @@ class PerlinNoiseGM : public skiagm::GM {
|
||||
}
|
||||
|
||||
void test(SkCanvas* canvas, int x, int y, Type type,
|
||||
float baseFrequencyX, float baseFrequencyY, int numOctaves, float seedOrZ,
|
||||
float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed,
|
||||
bool stitchTiles) {
|
||||
SkISize tileSize = SkISize::Make(fSize.width() / 2, fSize.height() / 2);
|
||||
sk_sp<SkShader> shader;
|
||||
@ -56,23 +55,16 @@ class PerlinNoiseGM : public skiagm::GM {
|
||||
shader = SkPerlinNoiseShader::MakeFractalNoise(baseFrequencyX,
|
||||
baseFrequencyY,
|
||||
numOctaves,
|
||||
seedOrZ,
|
||||
seed,
|
||||
stitchTiles ? &tileSize : nullptr);
|
||||
break;
|
||||
case Type::kTurbulence:
|
||||
shader = SkPerlinNoiseShader::MakeTurbulence(baseFrequencyX,
|
||||
baseFrequencyY,
|
||||
numOctaves,
|
||||
seedOrZ,
|
||||
seed,
|
||||
stitchTiles ? &tileSize : nullptr);
|
||||
break;
|
||||
case Type::kImproved:
|
||||
SkASSERT(!stitchTiles);
|
||||
shader = SkPerlinNoiseShader::MakeImprovedNoise(baseFrequencyX,
|
||||
baseFrequencyY,
|
||||
numOctaves,
|
||||
seedOrZ);
|
||||
break;
|
||||
}
|
||||
SkPaint paint;
|
||||
paint.setShader(std::move(shader));
|
||||
@ -111,16 +103,11 @@ class PerlinNoiseGM : public skiagm::GM {
|
||||
test(canvas, 100, 300, Type::kFractalNoise,
|
||||
0.1f, 0.1f, 3, 4, false);
|
||||
|
||||
test(canvas, 0, 400, Type::kImproved,
|
||||
0.0125f, 0.0125f, 4, 0, false);
|
||||
test(canvas, 100, 400, Type::kImproved,
|
||||
0.125f, 0.0075f, 2, 0, false);
|
||||
|
||||
canvas->scale(0.75f, 1.0f);
|
||||
|
||||
test(canvas, 0, 500, Type::kFractalNoise,
|
||||
test(canvas, 0, 400, Type::kFractalNoise,
|
||||
0.1f, 0.1f, 2, 0, false);
|
||||
test(canvas, 100, 500, Type::kFractalNoise,
|
||||
test(canvas, 100, 400, Type::kFractalNoise,
|
||||
0.1f, 0.05f, 1, 0, true);
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,6 @@
|
||||
_samplecode = get_path_info("../samplecode", "abspath")
|
||||
|
||||
samples_sources = [
|
||||
"$_samplecode/PerlinPatch.cpp",
|
||||
"$_samplecode/Sample.cpp",
|
||||
"$_samplecode/Sample.h",
|
||||
"$_samplecode/Sample2PtRadial.cpp",
|
||||
|
@ -44,12 +44,6 @@ public:
|
||||
static sk_sp<SkShader> MakeTurbulence(SkScalar baseFrequencyX, SkScalar baseFrequencyY,
|
||||
int numOctaves, SkScalar seed,
|
||||
const SkISize* tileSize = nullptr);
|
||||
/**
|
||||
* Creates an Improved Perlin Noise shader. The z value is roughly equivalent to the seed of the
|
||||
* other two types, but minor variations to z will only slightly change the noise.
|
||||
*/
|
||||
static sk_sp<SkShader> MakeImprovedNoise(SkScalar baseFrequencyX, SkScalar baseFrequencyY,
|
||||
int numOctaves, SkScalar z);
|
||||
|
||||
static void RegisterFlattenables();
|
||||
|
||||
|
@ -9,6 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
### Added
|
||||
- Constants for the shadow flags. Of note, some of these values can be used on previous releases.
|
||||
|
||||
### Breaking
|
||||
- `MakeImprovedNoise` is removed.
|
||||
|
||||
### Fixed
|
||||
- Improper error returned when a WebGL context could not be used.
|
||||
|
||||
|
@ -782,7 +782,6 @@ function shaderTests(CK: CanvasKit) {
|
||||
);
|
||||
const s12 = CK.Shader.MakeFractalNoise(0.1, 0.05, 2, 0, 80, 80); // $ExpectType Shader
|
||||
const s13 = CK.Shader.MakeTurbulence(0.1, 0.05, 2, 0, 80, 80); // $ExpectType Shader
|
||||
const s14 = CK.Shader.MakeImprovedNoise(0.1, 0.05, 2, 0); // $ExpectType Shader
|
||||
}
|
||||
|
||||
function shapedTextTests(CK: CanvasKit, textFont?: Font) {
|
||||
|
10
modules/canvaskit/canvaskit/types/index.d.ts
vendored
10
modules/canvaskit/canvaskit/types/index.d.ts
vendored
@ -3135,16 +3135,6 @@ export interface ShaderFactory {
|
||||
MakeFractalNoise(baseFreqX: number, baseFreqY: number, octaves: number, seed: number,
|
||||
tileW: number, tileH: number): Shader;
|
||||
|
||||
/**
|
||||
* Returns a shader with Improved Perlin Noise.
|
||||
* See SkPerlinNoiseShader.h for more details
|
||||
* @param baseFreqX - base frequency in the X direction; range [0.0, 1.0]
|
||||
* @param baseFreqY - base frequency in the Y direction; range [0.0, 1.0]
|
||||
* @param octaves
|
||||
* @param z - like seed, but minor variations to z will only slightly change the noise.
|
||||
*/
|
||||
MakeImprovedNoise(baseFreqX: number, baseFreqY: number, octaves: number, z: number): Shader;
|
||||
|
||||
/**
|
||||
* Returns a shader is a linear interpolation combines the given shaders with a BlendMode.
|
||||
* @param t - range of [0.0, 1.0], indicating how far we should be between one and two.
|
||||
|
@ -1555,7 +1555,6 @@ EMSCRIPTEN_BINDINGS(Skia) {
|
||||
return SkPerlinNoiseShader::MakeFractalNoise(baseFreqX, baseFreqY,
|
||||
numOctaves, seed, &tileSize);
|
||||
}))
|
||||
.class_function("MakeImprovedNoise", &SkPerlinNoiseShader::MakeImprovedNoise)
|
||||
// Here and in other gradient functions, cPtr is a pointer to an array of data
|
||||
// representing colors. whether this is an array of SkColor or SkColor4f is indicated
|
||||
// by the colorType argument. Only RGBA_8888 and RGBA_F32 are accepted.
|
||||
|
@ -625,7 +625,6 @@ var CanvasKit = {
|
||||
MakeBlend: function() {},
|
||||
MakeColor: function() {},
|
||||
MakeFractalNoise: function() {},
|
||||
MakeImprovedNoise: function() {},
|
||||
MakeLerp: function() {},
|
||||
MakeLinearGradient: function() {},
|
||||
MakeRadialGradient: function() {},
|
||||
|
@ -978,16 +978,6 @@ describe('Core canvas behavior', () => {
|
||||
shader.delete();
|
||||
});
|
||||
|
||||
gm('improved_noise_shader', (canvas) => {
|
||||
const shader = CanvasKit.Shader.MakeImprovedNoise(0.1, 0.05, 2, 10);
|
||||
const paint = new CanvasKit.Paint();
|
||||
paint.setColor(CanvasKit.BLACK);
|
||||
paint.setShader(shader);
|
||||
canvas.drawPaint(paint);
|
||||
paint.delete();
|
||||
shader.delete();
|
||||
});
|
||||
|
||||
describe('ColorSpace Support', () => {
|
||||
it('Can create an SRGB 8888 surface', () => {
|
||||
const colorSpace = CanvasKit.ColorSpace.SRGB;
|
||||
|
@ -1,209 +0,0 @@
|
||||
/*
|
||||
* 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 "include/core/SkCanvas.h"
|
||||
#include "include/effects/SkGradientShader.h"
|
||||
#include "include/effects/SkPerlinNoiseShader.h"
|
||||
#include "samplecode/Sample.h"
|
||||
#include "src/utils/SkPatchUtils.h"
|
||||
#include "tools/skui/ModifierKey.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 Sample {
|
||||
sk_sp<SkShader> fShader0;
|
||||
sk_sp<SkShader> fShader1;
|
||||
sk_sp<SkShader> fShaderCompose;
|
||||
SkScalar fXFreq;
|
||||
SkScalar fYFreq;
|
||||
SkScalar fSeed;
|
||||
SkPoint fPts[SkPatchUtils::kNumCtrlPts];
|
||||
SkScalar fTexX;
|
||||
SkScalar fTexY;
|
||||
SkScalar fTexScale;
|
||||
SkMatrix fInvMatrix;
|
||||
bool fShowGrid = false;
|
||||
|
||||
public:
|
||||
PerlinPatchView() : fXFreq(0.025f), fYFreq(0.025f), fSeed(0.0f),
|
||||
fTexX(100.0), fTexY(50.0), fTexScale(1.0f) {
|
||||
const SkScalar s = 2;
|
||||
// The order of the colors and points is clockwise starting at upper-left corner.
|
||||
//top points
|
||||
fPts[0].set(100 * s, 100 * s);
|
||||
fPts[1].set(150 * s, 50 * s);
|
||||
fPts[2].set(250 * s, 150 * s);
|
||||
fPts[3].set(300 * s, 100 * s);
|
||||
//right points
|
||||
fPts[4].set(275 * s, 150 * s);
|
||||
fPts[5].set(350 * s, 250 * s);
|
||||
//bottom points
|
||||
fPts[6].set(300 * s, 300 * s);
|
||||
fPts[7].set(250 * s, 250 * s);
|
||||
//left points
|
||||
fPts[8].set(150 * s, 350 * s);
|
||||
fPts[9].set(100 * s, 300 * s);
|
||||
fPts[10].set(50 * s, 250 * s);
|
||||
fPts[11].set(150 * s, 150 * s);
|
||||
|
||||
const SkColor colors[SkPatchUtils::kNumCorners] = {
|
||||
0xFF5555FF, 0xFF8888FF, 0xFFCCCCFF
|
||||
};
|
||||
const SkPoint points[2] = { SkPoint::Make(0.0f, 0.0f),
|
||||
SkPoint::Make(100.0f, 100.0f) };
|
||||
fShader0 = SkGradientShader::MakeLinear(points,
|
||||
colors,
|
||||
nullptr,
|
||||
3,
|
||||
SkTileMode::kMirror,
|
||||
0,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
protected:
|
||||
SkString name() override { return SkString("PerlinPatch"); }
|
||||
|
||||
bool onChar(SkUnichar uni) override {
|
||||
switch (uni) {
|
||||
case 'g': fShowGrid = !fShowGrid; return true;
|
||||
default: break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool onAnimate(double nanos) override {
|
||||
fSeed += 0.005f;
|
||||
return true;
|
||||
}
|
||||
|
||||
void onDrawContent(SkCanvas* canvas) override {
|
||||
if (!canvas->getLocalToDeviceAs3x3().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}}
|
||||
;
|
||||
|
||||
SkScalar scaleFreq = 2.0;
|
||||
fShader1 = SkPerlinNoiseShader::MakeImprovedNoise(fXFreq/scaleFreq, fYFreq/scaleFreq, 4,
|
||||
fSeed);
|
||||
fShaderCompose = SkShaders::Blend(SkBlendMode::kSrcOver, fShader0, fShader1);
|
||||
|
||||
paint.setShader(fShaderCompose);
|
||||
|
||||
const SkPoint* tex = texCoords;
|
||||
if (fShowGrid) {
|
||||
tex = nullptr;
|
||||
}
|
||||
canvas->drawPatch(fPts, nullptr, tex, SkBlendMode::kSrc, paint);
|
||||
|
||||
draw_control_points(canvas, fPts);
|
||||
}
|
||||
|
||||
class PtClick : public Click {
|
||||
public:
|
||||
int fIndex;
|
||||
PtClick(int index) : fIndex(index) {}
|
||||
};
|
||||
|
||||
static bool hittest(const SkPoint& pt, SkScalar x, SkScalar y) {
|
||||
return SkPoint::Length(pt.fX - x, pt.fY - y) < SkIntToScalar(5);
|
||||
}
|
||||
|
||||
Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey modi) override {
|
||||
modi &= ~skui::ModifierKey::kFirstPress; // ignore this
|
||||
if (skui::ModifierKey::kShift == modi) {
|
||||
return new PtClick(-1);
|
||||
}
|
||||
if (skui::ModifierKey::kControl == modi) {
|
||||
return new PtClick(-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((int)i);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
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 = std::max(0.1f, std::min(20.f, fTexScale));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
using INHERITED = Sample;
|
||||
};
|
||||
|
||||
DEF_SAMPLE( return new PerlinPatchView(); )
|
@ -147,7 +147,7 @@ SkTArray<GrXPFactoryTestFactory*, true>* GrXPFactoryTestFactory::GetFactories()
|
||||
* we verify the count is as expected. If a new factory is added, then these numbers must be
|
||||
* manually adjusted.
|
||||
*/
|
||||
static constexpr int kFPFactoryCount = 37;
|
||||
static constexpr int kFPFactoryCount = 36;
|
||||
static constexpr int kGPFactoryCount = 14;
|
||||
static constexpr int kXPFactoryCount = 4;
|
||||
|
||||
|
@ -36,37 +36,6 @@ static const int kBlockMask = kBlockSize - 1;
|
||||
static const int kPerlinNoise = 4096;
|
||||
static const int kRandMaximum = SK_MaxS32; // 2**31 - 1
|
||||
|
||||
static uint8_t improved_noise_permutations[] = {
|
||||
151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103,
|
||||
30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26,
|
||||
197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174,
|
||||
20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231,
|
||||
83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143,
|
||||
54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196,
|
||||
135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124,
|
||||
123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17,
|
||||
182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101,
|
||||
155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185,
|
||||
112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81,
|
||||
51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176,
|
||||
115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243,
|
||||
141, 128, 195, 78, 66, 215, 61, 156, 180,
|
||||
151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103,
|
||||
30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26,
|
||||
197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174,
|
||||
20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231,
|
||||
83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143,
|
||||
54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196,
|
||||
135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124,
|
||||
123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17,
|
||||
182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101,
|
||||
155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185,
|
||||
112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81,
|
||||
51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176,
|
||||
115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243,
|
||||
141, 128, 195, 78, 66, 215, 61, 156, 180
|
||||
};
|
||||
|
||||
class SkPerlinNoiseShaderImpl : public SkShaderBase {
|
||||
public:
|
||||
struct StitchData {
|
||||
@ -125,31 +94,6 @@ public:
|
||||
info = SkImageInfo::Make(kBlockSize, 4, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
|
||||
fNoiseBitmap.installPixels(info, fNoise[0][0], info.minRowBytes());
|
||||
fNoiseBitmap.setImmutable();
|
||||
|
||||
info = SkImageInfo::MakeA8(256, 1);
|
||||
fImprovedPermutationsBitmap.installPixels(info, improved_noise_permutations,
|
||||
info.minRowBytes());
|
||||
fImprovedPermutationsBitmap.setImmutable();
|
||||
|
||||
static uint8_t gradients[] = { 2, 2, 1, 0,
|
||||
0, 2, 1, 0,
|
||||
2, 0, 1, 0,
|
||||
0, 0, 1, 0,
|
||||
2, 1, 2, 0,
|
||||
0, 1, 2, 0,
|
||||
2, 1, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
1, 2, 2, 0,
|
||||
1, 0, 2, 0,
|
||||
1, 2, 0, 0,
|
||||
1, 0, 0, 0,
|
||||
2, 2, 1, 0,
|
||||
1, 0, 2, 0,
|
||||
0, 2, 1, 0,
|
||||
1, 0, 0, 0 };
|
||||
info = SkImageInfo::Make(16, 1, kBGRA_8888_SkColorType, kPremul_SkAlphaType);
|
||||
fGradientBitmap.installPixels(info, gradients, info.minRowBytes());
|
||||
fGradientBitmap.setImmutable();
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -160,9 +104,7 @@ public:
|
||||
, fBaseFrequency(that.fBaseFrequency)
|
||||
, fStitchDataInit(that.fStitchDataInit)
|
||||
, fPermutationsBitmap(that.fPermutationsBitmap)
|
||||
, fNoiseBitmap(that.fNoiseBitmap)
|
||||
, fImprovedPermutationsBitmap(that.fImprovedPermutationsBitmap)
|
||||
, fGradientBitmap(that.fGradientBitmap) {
|
||||
, fNoiseBitmap(that.fNoiseBitmap) {
|
||||
memcpy(fLatticeSelector, that.fLatticeSelector, sizeof(fLatticeSelector));
|
||||
memcpy(fNoise, that.fNoise, sizeof(fNoise));
|
||||
memcpy(fGradient, that.fGradient, sizeof(fGradient));
|
||||
@ -182,8 +124,6 @@ public:
|
||||
#if SK_SUPPORT_GPU
|
||||
SkBitmap fPermutationsBitmap;
|
||||
SkBitmap fNoiseBitmap;
|
||||
SkBitmap fImprovedPermutationsBitmap;
|
||||
SkBitmap fGradientBitmap;
|
||||
#endif
|
||||
|
||||
inline int random() {
|
||||
@ -313,12 +253,6 @@ public:
|
||||
const SkBitmap& getPermutationsBitmap() const { return fPermutationsBitmap; }
|
||||
|
||||
const SkBitmap& getNoiseBitmap() const { return fNoiseBitmap; }
|
||||
|
||||
const SkBitmap& getImprovedPermutationsBitmap() const {
|
||||
return fImprovedPermutationsBitmap;
|
||||
}
|
||||
|
||||
const SkBitmap& getGradientBitmap() const { return fGradientBitmap; }
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -330,16 +264,11 @@ public:
|
||||
* kFractalNoise_Type : noise * 0.5 + 0.5
|
||||
* kTurbulence_Type : abs(noise)
|
||||
* Very little differences between the 2 types, although you can tell the difference visually.
|
||||
* "Improved" is based on the Improved Perlin Noise algorithm described at
|
||||
* http://mrl.nyu.edu/~perlin/noise/. It is quite distinct from the other two, and the noise is
|
||||
* a 2D slice of a 3D noise texture. Minor changes to the Z coordinate will result in minor
|
||||
* changes to the noise, making it suitable for animated noise.
|
||||
*/
|
||||
enum Type {
|
||||
kFractalNoise_Type,
|
||||
kTurbulence_Type,
|
||||
kImprovedNoise_Type,
|
||||
kLast_Type = kImprovedNoise_Type
|
||||
kLast_Type = kTurbulence_Type
|
||||
};
|
||||
|
||||
static const int kMaxOctaves = 255; // numOctaves must be <= 0 and <= kMaxOctaves
|
||||
@ -359,7 +288,6 @@ public:
|
||||
SkScalar calculateTurbulenceValueForPoint(
|
||||
int channel,
|
||||
StitchData& stitchData, const SkPoint& point) const;
|
||||
SkScalar calculateImprovedNoiseValueForPoint(int channel, const SkPoint& point) const;
|
||||
SkScalar noise2D(int channel,
|
||||
const StitchData& stitchData, const SkPoint& noiseVector) const;
|
||||
|
||||
@ -452,8 +380,6 @@ sk_sp<SkFlattenable> SkPerlinNoiseShaderImpl::CreateProc(SkReadBuffer& buffer) {
|
||||
return SkPerlinNoiseShader::MakeFractalNoise(freqX, freqY, octaves, seed, &tileSize);
|
||||
case kTurbulence_Type:
|
||||
return SkPerlinNoiseShader::MakeTurbulence(freqX, freqY, octaves, seed, &tileSize);
|
||||
case kImprovedNoise_Type:
|
||||
return SkPerlinNoiseShader::MakeImprovedNoise(freqX, freqY, octaves, seed);
|
||||
default:
|
||||
// Really shouldn't get here b.c. of earlier check on type
|
||||
buffer.validate(false);
|
||||
@ -572,71 +498,10 @@ SkScalar SkPerlinNoiseShaderImpl::PerlinNoiseShaderContext::calculateTurbulenceV
|
||||
return SkTPin(turbulenceFunctionResult, 0.0f, SK_Scalar1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Improved Perlin Noise based on Java implementation found at http://mrl.nyu.edu/~perlin/noise/
|
||||
static SkScalar fade(SkScalar t) {
|
||||
return t * t * t * (t * (t * 6 - 15) + 10);
|
||||
}
|
||||
|
||||
static SkScalar lerp(SkScalar t, SkScalar a, SkScalar b) {
|
||||
return a + t * (b - a);
|
||||
}
|
||||
|
||||
static SkScalar grad(int hash, SkScalar x, SkScalar y, SkScalar z) {
|
||||
int h = hash & 15;
|
||||
SkScalar u = h < 8 ? x : y;
|
||||
SkScalar v = h < 4 ? y : h == 12 || h == 14 ? x : z;
|
||||
return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
|
||||
}
|
||||
|
||||
SkScalar SkPerlinNoiseShaderImpl::PerlinNoiseShaderContext::calculateImprovedNoiseValueForPoint(
|
||||
int channel, const SkPoint& point) const {
|
||||
const SkPerlinNoiseShaderImpl& perlinNoiseShader = static_cast<const SkPerlinNoiseShaderImpl&>(fShader);
|
||||
SkScalar x = point.fX * perlinNoiseShader.fBaseFrequencyX;
|
||||
SkScalar y = point.fY * perlinNoiseShader.fBaseFrequencyY;
|
||||
// z offset between different channels, chosen arbitrarily
|
||||
static const SkScalar CHANNEL_DELTA = 1000.0f;
|
||||
SkScalar z = channel * CHANNEL_DELTA + perlinNoiseShader.fSeed;
|
||||
SkScalar result = 0;
|
||||
SkScalar ratio = SK_Scalar1;
|
||||
for (int i = 0; i < perlinNoiseShader.fNumOctaves; i++) {
|
||||
int X = SkScalarFloorToInt(x) & 255;
|
||||
int Y = SkScalarFloorToInt(y) & 255;
|
||||
int Z = SkScalarFloorToInt(z) & 255;
|
||||
SkScalar px = x - SkScalarFloorToScalar(x);
|
||||
SkScalar py = y - SkScalarFloorToScalar(y);
|
||||
SkScalar pz = z - SkScalarFloorToScalar(z);
|
||||
SkScalar u = fade(px);
|
||||
SkScalar v = fade(py);
|
||||
SkScalar w = fade(pz);
|
||||
uint8_t* permutations = improved_noise_permutations;
|
||||
int A = permutations[X] + Y;
|
||||
int AA = permutations[A] + Z;
|
||||
int AB = permutations[A + 1] + Z;
|
||||
int B = permutations[X + 1] + Y;
|
||||
int BA = permutations[B] + Z;
|
||||
int BB = permutations[B + 1] + Z;
|
||||
result += lerp(w, lerp(v, lerp(u, grad(permutations[AA ], px , py , pz ),
|
||||
grad(permutations[BA ], px - 1, py , pz )),
|
||||
lerp(u, grad(permutations[AB ], px , py - 1, pz ),
|
||||
grad(permutations[BB ], px - 1, py - 1, pz ))),
|
||||
lerp(v, lerp(u, grad(permutations[AA + 1], px , py , pz - 1),
|
||||
grad(permutations[BA + 1], px - 1, py , pz - 1)),
|
||||
lerp(u, grad(permutations[AB + 1], px , py - 1, pz - 1),
|
||||
grad(permutations[BB + 1], px - 1, py - 1, pz - 1)))) /
|
||||
ratio;
|
||||
x *= 2;
|
||||
y *= 2;
|
||||
ratio *= 2;
|
||||
}
|
||||
result = SkTPin((result + 1.0f) / 2.0f, 0.0f, 1.0f);
|
||||
return result;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SkPMColor SkPerlinNoiseShaderImpl::PerlinNoiseShaderContext::shade(
|
||||
const SkPoint& point, StitchData& stitchData) const {
|
||||
const SkPerlinNoiseShaderImpl& perlinNoiseShader = static_cast<const SkPerlinNoiseShaderImpl&>(fShader);
|
||||
SkPoint newPoint;
|
||||
fMatrix.mapPoints(&newPoint, &point, 1);
|
||||
newPoint.fX = SkScalarRoundToScalar(newPoint.fX);
|
||||
@ -645,12 +510,7 @@ SkPMColor SkPerlinNoiseShaderImpl::PerlinNoiseShaderContext::shade(
|
||||
U8CPU rgba[4];
|
||||
for (int channel = 3; channel >= 0; --channel) {
|
||||
SkScalar value;
|
||||
if (perlinNoiseShader.fType == kImprovedNoise_Type) {
|
||||
value = calculateImprovedNoiseValueForPoint(channel, newPoint);
|
||||
}
|
||||
else {
|
||||
value = calculateTurbulenceValueForPoint(channel, stitchData, newPoint);
|
||||
}
|
||||
value = calculateTurbulenceValueForPoint(channel, stitchData, newPoint);
|
||||
rgba[channel] = SkScalarFloorToInt(255 * value);
|
||||
}
|
||||
return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]);
|
||||
@ -1070,275 +930,6 @@ void GrGLPerlinNoise::onSetData(const GrGLSLProgramDataManager& pdman,
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
class GrGLImprovedPerlinNoise : public GrGLSLFragmentProcessor {
|
||||
public:
|
||||
void emitCode(EmitArgs&) override;
|
||||
|
||||
static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*);
|
||||
|
||||
protected:
|
||||
void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
|
||||
|
||||
private:
|
||||
GrGLSLProgramDataManager::UniformHandle fZUni;
|
||||
GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni;
|
||||
|
||||
using INHERITED = GrGLSLFragmentProcessor;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
class GrImprovedPerlinNoiseEffect : public GrFragmentProcessor {
|
||||
public:
|
||||
static std::unique_ptr<GrFragmentProcessor> Make(
|
||||
int octaves,
|
||||
SkScalar z,
|
||||
std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> paintingData,
|
||||
GrSurfaceProxyView permutationsView,
|
||||
GrSurfaceProxyView gradientView,
|
||||
const SkMatrix& matrix,
|
||||
const GrCaps& caps) {
|
||||
static constexpr GrSamplerState kRepeatXSampler = {GrSamplerState::WrapMode::kRepeat,
|
||||
GrSamplerState::WrapMode::kClamp,
|
||||
GrSamplerState::Filter::kNearest};
|
||||
auto permutationsFP =
|
||||
GrTextureEffect::Make(std::move(permutationsView), kPremul_SkAlphaType,
|
||||
SkMatrix::I(), kRepeatXSampler, caps);
|
||||
auto gradientFP = GrTextureEffect::Make(std::move(gradientView), kPremul_SkAlphaType,
|
||||
SkMatrix::I(), kRepeatXSampler, caps);
|
||||
return GrMatrixEffect::Make(matrix, std::unique_ptr<GrFragmentProcessor>(
|
||||
new GrImprovedPerlinNoiseEffect(octaves, z, std::move(paintingData),
|
||||
std::move(permutationsFP),
|
||||
std::move(gradientFP))));
|
||||
}
|
||||
|
||||
const char* name() const override { return "ImprovedPerlinNoise"; }
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor> clone() const override {
|
||||
return std::unique_ptr<GrFragmentProcessor>(new GrImprovedPerlinNoiseEffect(*this));
|
||||
}
|
||||
|
||||
const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; }
|
||||
SkScalar z() const { return fZ; }
|
||||
int octaves() const { return fOctaves; }
|
||||
|
||||
private:
|
||||
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
|
||||
return new GrGLImprovedPerlinNoise;
|
||||
}
|
||||
|
||||
void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
|
||||
GrGLImprovedPerlinNoise::GenKey(*this, caps, b);
|
||||
}
|
||||
|
||||
bool onIsEqual(const GrFragmentProcessor& sBase) const override {
|
||||
const GrImprovedPerlinNoiseEffect& that = sBase.cast<GrImprovedPerlinNoiseEffect>();
|
||||
return this->z() == that.z() &&
|
||||
this->octaves() == that.octaves() &&
|
||||
this->baseFrequency() == that.baseFrequency();
|
||||
}
|
||||
|
||||
GrImprovedPerlinNoiseEffect(int octaves,
|
||||
SkScalar z,
|
||||
std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> paintingData,
|
||||
std::unique_ptr<GrFragmentProcessor> permutationsFP,
|
||||
std::unique_ptr<GrFragmentProcessor> gradientFP)
|
||||
: INHERITED(kGrImprovedPerlinNoiseEffect_ClassID, kNone_OptimizationFlags)
|
||||
, fOctaves(octaves)
|
||||
, fZ(z)
|
||||
, fPaintingData(std::move(paintingData)) {
|
||||
this->registerChild(std::move(permutationsFP), SkSL::SampleUsage::Explicit());
|
||||
this->registerChild(std::move(gradientFP), SkSL::SampleUsage::Explicit());
|
||||
this->setUsesSampleCoordsDirectly();
|
||||
}
|
||||
|
||||
GrImprovedPerlinNoiseEffect(const GrImprovedPerlinNoiseEffect& that)
|
||||
: INHERITED(kGrImprovedPerlinNoiseEffect_ClassID, kNone_OptimizationFlags)
|
||||
, fOctaves(that.fOctaves)
|
||||
, fZ(that.fZ)
|
||||
, fPaintingData(std::make_unique<SkPerlinNoiseShaderImpl::PaintingData>(
|
||||
*that.fPaintingData)) {
|
||||
this->cloneAndRegisterAllChildProcessors(that);
|
||||
this->setUsesSampleCoordsDirectly();
|
||||
}
|
||||
|
||||
GR_DECLARE_FRAGMENT_PROCESSOR_TEST
|
||||
|
||||
int fOctaves;
|
||||
SkScalar fZ;
|
||||
|
||||
std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> fPaintingData;
|
||||
|
||||
using INHERITED = GrFragmentProcessor;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrImprovedPerlinNoiseEffect);
|
||||
|
||||
#if GR_TEST_UTILS
|
||||
std::unique_ptr<GrFragmentProcessor> GrImprovedPerlinNoiseEffect::TestCreate(
|
||||
GrProcessorTestData* d) {
|
||||
SkScalar baseFrequencyX = d->fRandom->nextRangeScalar(0.01f,
|
||||
0.99f);
|
||||
SkScalar baseFrequencyY = d->fRandom->nextRangeScalar(0.01f,
|
||||
0.99f);
|
||||
int numOctaves = d->fRandom->nextRangeU(2, 10);
|
||||
SkScalar z = SkIntToScalar(d->fRandom->nextU());
|
||||
|
||||
sk_sp<SkShader> shader(SkPerlinNoiseShader::MakeImprovedNoise(baseFrequencyX,
|
||||
baseFrequencyY,
|
||||
numOctaves,
|
||||
z));
|
||||
|
||||
GrTest::TestAsFPArgs asFPArgs(d);
|
||||
return as_SB(shader)->asFragmentProcessor(asFPArgs.args());
|
||||
}
|
||||
#endif
|
||||
|
||||
void GrGLImprovedPerlinNoise::emitCode(EmitArgs& args) {
|
||||
const GrImprovedPerlinNoiseEffect& pne = args.fFp.cast<GrImprovedPerlinNoiseEffect>();
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
|
||||
|
||||
fBaseFrequencyUni = uniformHandler->addUniform(&pne, kFragment_GrShaderFlag, kHalf2_GrSLType,
|
||||
"baseFrequency");
|
||||
const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);
|
||||
|
||||
fZUni = uniformHandler->addUniform(&pne, kFragment_GrShaderFlag, kHalf_GrSLType, "z");
|
||||
const char* zUni = uniformHandler->getUniformCStr(fZUni);
|
||||
|
||||
// fade function
|
||||
const GrShaderVar fadeArgs[] = {
|
||||
GrShaderVar("t", kHalf3_GrSLType)
|
||||
};
|
||||
SkString fadeFuncName = fragBuilder->getMangledFunctionName("fade");
|
||||
fragBuilder->emitFunction(kHalf3_GrSLType, fadeFuncName.c_str(),
|
||||
{fadeArgs, SK_ARRAY_COUNT(fadeArgs)},
|
||||
"return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);");
|
||||
|
||||
// perm function
|
||||
const GrShaderVar permArgs[] = {
|
||||
{"x", kHalf_GrSLType}
|
||||
};
|
||||
SkString samplePerm = this->invokeChild(0, "half4(1)", args, "float2(x, 0.5)");
|
||||
SkString permFuncName = fragBuilder->getMangledFunctionName("perm");
|
||||
SkString permCode = SkStringPrintf("return %s.a * 255;", samplePerm.c_str());
|
||||
fragBuilder->emitFunction(kHalf_GrSLType, permFuncName.c_str(),
|
||||
{permArgs, SK_ARRAY_COUNT(permArgs)}, permCode.c_str());
|
||||
|
||||
// grad function
|
||||
const GrShaderVar gradArgs[] = {
|
||||
{"x", kHalf_GrSLType},
|
||||
{"p", kHalf3_GrSLType}
|
||||
};
|
||||
SkString sampleGrad = this->invokeChild(1, "half4(1)", args, "float2(x, 0.5)");
|
||||
SkString gradFuncName = fragBuilder->getMangledFunctionName("grad");
|
||||
SkString gradCode = SkStringPrintf("return half(dot(%s.rgb * 255.0 - float3(1.0), p));",
|
||||
sampleGrad.c_str());
|
||||
fragBuilder->emitFunction(kHalf_GrSLType, gradFuncName.c_str(),
|
||||
{gradArgs, SK_ARRAY_COUNT(gradArgs)}, gradCode.c_str());
|
||||
|
||||
// lerp function
|
||||
const GrShaderVar lerpArgs[] = {
|
||||
{"a", kHalf_GrSLType},
|
||||
{"b", kHalf_GrSLType},
|
||||
{"w", kHalf_GrSLType}
|
||||
};
|
||||
SkString lerpFuncName = fragBuilder->getMangledFunctionName("lerp");
|
||||
fragBuilder->emitFunction(kHalf_GrSLType, lerpFuncName.c_str(),
|
||||
{lerpArgs, SK_ARRAY_COUNT(lerpArgs)}, "return a + w * (b - a);");
|
||||
|
||||
// noise function
|
||||
const GrShaderVar noiseArgs[] = {
|
||||
{"p", kHalf3_GrSLType},
|
||||
};
|
||||
SkString noiseFuncName = fragBuilder->getMangledFunctionName("noise");
|
||||
SkString noiseCode;
|
||||
noiseCode.append("half3 P = mod(floor(p), 256.0);");
|
||||
noiseCode.append("p -= floor(p);");
|
||||
noiseCode.appendf("half3 f = %s(p);", fadeFuncName.c_str());
|
||||
noiseCode.appendf("half A = %s(P.x) + P.y;", permFuncName.c_str());
|
||||
noiseCode.appendf("half AA = %s(A) + P.z;", permFuncName.c_str());
|
||||
noiseCode.appendf("half AB = %s(A + 1.0) + P.z;", permFuncName.c_str());
|
||||
noiseCode.appendf("half B = %s(P.x + 1.0) + P.y;", permFuncName.c_str());
|
||||
noiseCode.appendf("half BA = %s(B) + P.z;", permFuncName.c_str());
|
||||
noiseCode.appendf("half BB = %s(B + 1.0) + P.z;", permFuncName.c_str());
|
||||
noiseCode.appendf("half result = %s(", lerpFuncName.c_str());
|
||||
noiseCode.appendf("%s(%s(%s(%s(AA), p),", lerpFuncName.c_str(), lerpFuncName.c_str(),
|
||||
gradFuncName.c_str(), permFuncName.c_str());
|
||||
noiseCode.appendf("%s(%s(BA), p + half3(-1.0, 0.0, 0.0)), f.x),", gradFuncName.c_str(),
|
||||
permFuncName.c_str());
|
||||
noiseCode.appendf("%s(%s(%s(AB), p + half3(0.0, -1.0, 0.0)),", lerpFuncName.c_str(),
|
||||
gradFuncName.c_str(), permFuncName.c_str());
|
||||
noiseCode.appendf("%s(%s(BB), p + half3(-1.0, -1.0, 0.0)), f.x), f.y),",
|
||||
gradFuncName.c_str(), permFuncName.c_str());
|
||||
noiseCode.appendf("%s(%s(%s(%s(AA + 1.0), p + half3(0.0, 0.0, -1.0)),",
|
||||
lerpFuncName.c_str(), lerpFuncName.c_str(), gradFuncName.c_str(),
|
||||
permFuncName.c_str());
|
||||
noiseCode.appendf("%s(%s(BA + 1.0), p + half3(-1.0, 0.0, -1.0)), f.x),",
|
||||
gradFuncName.c_str(), permFuncName.c_str());
|
||||
noiseCode.appendf("%s(%s(%s(AB + 1.0), p + half3(0.0, -1.0, -1.0)),",
|
||||
lerpFuncName.c_str(), gradFuncName.c_str(), permFuncName.c_str());
|
||||
noiseCode.appendf("%s(%s(BB + 1.0), p + half3(-1.0, -1.0, -1.0)), f.x), f.y), f.z);",
|
||||
gradFuncName.c_str(), permFuncName.c_str());
|
||||
noiseCode.append("return result;");
|
||||
fragBuilder->emitFunction(kHalf_GrSLType, noiseFuncName.c_str(),
|
||||
{noiseArgs, SK_ARRAY_COUNT(noiseArgs)}, noiseCode.c_str());
|
||||
|
||||
// noiseOctaves function
|
||||
const GrShaderVar noiseOctavesArgs[] = {
|
||||
{"p", kHalf3_GrSLType}
|
||||
};
|
||||
SkString noiseOctavesFuncName = fragBuilder->getMangledFunctionName("noiseOctaves");
|
||||
SkString noiseOctavesCode;
|
||||
noiseOctavesCode.append("half result = 0.0;");
|
||||
noiseOctavesCode.append("half ratio = 1.0;");
|
||||
noiseOctavesCode.appendf("for (half i = 0.0; i < %d; i++) {", pne.octaves());
|
||||
noiseOctavesCode.appendf("result += %s(p) / ratio;", noiseFuncName.c_str());
|
||||
noiseOctavesCode.append("p *= 2.0;");
|
||||
noiseOctavesCode.append("ratio *= 2.0;");
|
||||
noiseOctavesCode.append("}");
|
||||
noiseOctavesCode.append("return (result + 1.0) / 2.0;");
|
||||
fragBuilder->emitFunction(kHalf_GrSLType, noiseOctavesFuncName.c_str(),
|
||||
{noiseOctavesArgs, SK_ARRAY_COUNT(noiseOctavesArgs)},
|
||||
noiseOctavesCode.c_str());
|
||||
|
||||
fragBuilder->codeAppendf("half2 coords = half2(%s * %s);", args.fSampleCoord, baseFrequencyUni);
|
||||
fragBuilder->codeAppendf("half r = %s(half3(coords, %s));", noiseOctavesFuncName.c_str(),
|
||||
zUni);
|
||||
fragBuilder->codeAppendf("half g = %s(half3(coords, %s + 0000.0));",
|
||||
noiseOctavesFuncName.c_str(), zUni);
|
||||
fragBuilder->codeAppendf("half b = %s(half3(coords, %s + 0000.0));",
|
||||
noiseOctavesFuncName.c_str(), zUni);
|
||||
fragBuilder->codeAppendf("half a = %s(half3(coords, %s + 0000.0));",
|
||||
noiseOctavesFuncName.c_str(), zUni);
|
||||
|
||||
// Clamp values
|
||||
fragBuilder->codeAppendf("half4 color = saturate(half4(r, g, b, a));");
|
||||
|
||||
// Pre-multiply the result
|
||||
fragBuilder->codeAppendf("return half4(color.rgb * color.aaa, color.a);");
|
||||
}
|
||||
|
||||
void GrGLImprovedPerlinNoise::GenKey(const GrProcessor& processor, const GrShaderCaps&,
|
||||
GrProcessorKeyBuilder* b) {
|
||||
const GrImprovedPerlinNoiseEffect& pne = processor.cast<GrImprovedPerlinNoiseEffect>();
|
||||
b->add32(pne.octaves());
|
||||
}
|
||||
|
||||
void GrGLImprovedPerlinNoise::onSetData(const GrGLSLProgramDataManager& pdman,
|
||||
const GrFragmentProcessor& processor) {
|
||||
INHERITED::onSetData(pdman, processor);
|
||||
|
||||
const GrImprovedPerlinNoiseEffect& noise = processor.cast<GrImprovedPerlinNoiseEffect>();
|
||||
|
||||
const SkVector& baseFrequency = noise.baseFrequency();
|
||||
pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
|
||||
|
||||
pdman.set1f(fZUni, noise.z());
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
std::unique_ptr<GrFragmentProcessor> SkPerlinNoiseShaderImpl::asFragmentProcessor(
|
||||
const GrFPArgs& args) const {
|
||||
SkASSERT(args.fContext);
|
||||
@ -1361,28 +952,6 @@ std::unique_ptr<GrFragmentProcessor> SkPerlinNoiseShaderImpl::asFragmentProcesso
|
||||
m.setTranslateY(-localMatrix->getTranslateY() + SK_Scalar1);
|
||||
|
||||
auto context = args.fContext;
|
||||
if (fType == kImprovedNoise_Type) {
|
||||
// Need to assert that the textures we'll create are power of 2 so a copy isn't needed.
|
||||
// We also know that we will not be using mipmaps. If things things weren't true we should
|
||||
// go through GrBitmapTextureMaker to handle needed copies.
|
||||
const SkBitmap& permutationsBitmap = paintingData->getImprovedPermutationsBitmap();
|
||||
SkASSERT(SkIsPow2(permutationsBitmap.width()) && SkIsPow2(permutationsBitmap.height()));
|
||||
auto permutationsView = GrMakeCachedBitmapProxyView(context, permutationsBitmap);
|
||||
|
||||
const SkBitmap& gradientBitmap = paintingData->getGradientBitmap();
|
||||
SkASSERT(SkIsPow2(gradientBitmap.width()) && SkIsPow2(gradientBitmap.height()));
|
||||
auto gradientView = GrMakeCachedBitmapProxyView(context, gradientBitmap);
|
||||
if (!permutationsView || !gradientView) {
|
||||
return nullptr;
|
||||
}
|
||||
return GrImprovedPerlinNoiseEffect::Make(fNumOctaves,
|
||||
fSeed,
|
||||
std::move(paintingData),
|
||||
std::move(permutationsView),
|
||||
std::move(gradientView),
|
||||
m,
|
||||
*context->priv().caps());
|
||||
}
|
||||
|
||||
if (0 == fNumOctaves) {
|
||||
if (kFractalNoise_Type == fType) {
|
||||
@ -1468,17 +1037,6 @@ sk_sp<SkShader> SkPerlinNoiseShader::MakeTurbulence(SkScalar baseFrequencyX,
|
||||
tileSize));
|
||||
}
|
||||
|
||||
sk_sp<SkShader> SkPerlinNoiseShader::MakeImprovedNoise(SkScalar baseFrequencyX,
|
||||
SkScalar baseFrequencyY,
|
||||
int numOctaves, SkScalar z) {
|
||||
if (!valid_input(baseFrequencyX, baseFrequencyY, numOctaves, nullptr, z)) {
|
||||
return nullptr;
|
||||
}
|
||||
return sk_sp<SkShader>(new SkPerlinNoiseShaderImpl(SkPerlinNoiseShaderImpl::kImprovedNoise_Type,
|
||||
baseFrequencyX, baseFrequencyY, numOctaves, z,
|
||||
nullptr));
|
||||
}
|
||||
|
||||
void SkPerlinNoiseShader::RegisterFlattenables() {
|
||||
SK_REGISTER_FLATTENABLE(SkPerlinNoiseShaderImpl);
|
||||
}
|
||||
|
@ -70,9 +70,6 @@ void SkSLSlide::load(SkScalar winWidth, SkScalar winHeight) {
|
||||
shader = GetResourceAsImage("images/mandrill_256.png")->makeShader(SkSamplingOptions());
|
||||
fShaders.push_back(std::make_pair("Mandrill", shader));
|
||||
|
||||
shader = SkPerlinNoiseShader::MakeImprovedNoise(0.025f, 0.025f, 3, 0.0f);
|
||||
fShaders.push_back(std::make_pair("Perlin Noise", shader));
|
||||
|
||||
fResolution = { winWidth, winHeight, 1.0f };
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user