| Index: experimental/SkPerlinNoiseShader2/SkPerlinNoiseShader2.cpp
|
| diff --git a/src/effects/SkPerlinNoiseShader.cpp b/experimental/SkPerlinNoiseShader2/SkPerlinNoiseShader2.cpp
|
| similarity index 57%
|
| copy from src/effects/SkPerlinNoiseShader.cpp
|
| copy to experimental/SkPerlinNoiseShader2/SkPerlinNoiseShader2.cpp
|
| index 0c455693c3a3f3b5a8385544de2c06f5171667fc..b0d1812951f253a26df9bf49fb4a081d50485542 100644
|
| --- a/src/effects/SkPerlinNoiseShader.cpp
|
| +++ b/experimental/SkPerlinNoiseShader2/SkPerlinNoiseShader2.cpp
|
| @@ -6,7 +6,7 @@
|
| */
|
|
|
| #include "SkDither.h"
|
| -#include "SkPerlinNoiseShader.h"
|
| +#include "SkPerlinNoiseShader2.h"
|
| #include "SkColorFilter.h"
|
| #include "SkReadBuffer.h"
|
| #include "SkWriteBuffer.h"
|
| @@ -30,6 +30,37 @@ 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
|
| +};
|
| +
|
| namespace {
|
|
|
| // noiseValue is the color component's value (or color)
|
| @@ -54,7 +85,7 @@ inline SkScalar smoothCurve(SkScalar t) {
|
|
|
| } // end namespace
|
|
|
| -struct SkPerlinNoiseShader::StitchData {
|
| +struct SkPerlinNoiseShader2::StitchData {
|
| StitchData()
|
| : fWidth(0)
|
| , fWrapX(0)
|
| @@ -75,7 +106,7 @@ struct SkPerlinNoiseShader::StitchData {
|
| int fWrapY;
|
| };
|
|
|
| -struct SkPerlinNoiseShader::PaintingData {
|
| +struct SkPerlinNoiseShader2::PaintingData {
|
| PaintingData(const SkISize& tileSize, SkScalar seed,
|
| SkScalar baseFrequencyX, SkScalar baseFrequencyY,
|
| const SkMatrix& matrix)
|
| @@ -99,6 +130,28 @@ struct SkPerlinNoiseShader::PaintingData {
|
|
|
| fNoiseBitmap.setInfo(SkImageInfo::MakeN32Premul(kBlockSize, 4));
|
| fNoiseBitmap.setPixels(fNoise[0][0]);
|
| +
|
| + fImprovedPermutationsBitmap.setInfo(SkImageInfo::MakeA8(256, 1));
|
| + fImprovedPermutationsBitmap.setPixels(improved_noise_permutations);
|
| +
|
| + fGradientBitmap.setInfo(SkImageInfo::MakeN32Premul(16, 1));
|
| + 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 };
|
| + fGradientBitmap.setPixels(gradients);
|
| #endif
|
| }
|
|
|
| @@ -115,6 +168,8 @@ private:
|
| #if SK_SUPPORT_GPU
|
| SkBitmap fPermutationsBitmap;
|
| SkBitmap fNoiseBitmap;
|
| + SkBitmap fImprovedPermutationsBitmap;
|
| + SkBitmap fGradientBitmap;
|
| #endif
|
|
|
| inline int random() {
|
| @@ -246,24 +301,34 @@ 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
|
| };
|
|
|
| -SkShader* SkPerlinNoiseShader::CreateFractalNoise(SkScalar baseFrequencyX, SkScalar baseFrequencyY,
|
| +SkShader* SkPerlinNoiseShader2::CreateFractalNoise(SkScalar baseFrequencyX, SkScalar baseFrequencyY,
|
| int numOctaves, SkScalar seed,
|
| const SkISize* tileSize) {
|
| - return new SkPerlinNoiseShader(kFractalNoise_Type, baseFrequencyX, baseFrequencyY, numOctaves,
|
| + return new SkPerlinNoiseShader2(kFractalNoise_Type, baseFrequencyX, baseFrequencyY, numOctaves,
|
| seed, tileSize);
|
| }
|
|
|
| -SkShader* SkPerlinNoiseShader::CreateTurbulence(SkScalar baseFrequencyX, SkScalar baseFrequencyY,
|
| +SkShader* SkPerlinNoiseShader2::CreateTurbulence(SkScalar baseFrequencyX, SkScalar baseFrequencyY,
|
| int numOctaves, SkScalar seed,
|
| const SkISize* tileSize) {
|
| - return new SkPerlinNoiseShader(kTurbulence_Type, baseFrequencyX, baseFrequencyY, numOctaves,
|
| + return new SkPerlinNoiseShader2(kTurbulence_Type, baseFrequencyX, baseFrequencyY, numOctaves,
|
| seed, tileSize);
|
| }
|
|
|
| -SkPerlinNoiseShader::SkPerlinNoiseShader(SkPerlinNoiseShader::Type type,
|
| +SkShader* SkPerlinNoiseShader2::CreateImprovedNoise(SkScalar baseFrequencyX, SkScalar baseFrequencyY,
|
| + int numOctaves, SkScalar z) {
|
| + return new SkPerlinNoiseShader2(kImprovedNoise_Type, baseFrequencyX, baseFrequencyY, numOctaves,
|
| + z, NULL);
|
| +}
|
| +
|
| +SkPerlinNoiseShader2::SkPerlinNoiseShader2(SkPerlinNoiseShader2::Type type,
|
| SkScalar baseFrequencyX,
|
| SkScalar baseFrequencyY,
|
| int numOctaves,
|
| @@ -280,10 +345,10 @@ SkPerlinNoiseShader::SkPerlinNoiseShader(SkPerlinNoiseShader::Type type,
|
| SkASSERT(numOctaves >= 0 && numOctaves < 256);
|
| }
|
|
|
| -SkPerlinNoiseShader::~SkPerlinNoiseShader() {
|
| +SkPerlinNoiseShader2::~SkPerlinNoiseShader2() {
|
| }
|
|
|
| -SkFlattenable* SkPerlinNoiseShader::CreateProc(SkReadBuffer& buffer) {
|
| +SkFlattenable* SkPerlinNoiseShader2::CreateProc(SkReadBuffer& buffer) {
|
| Type type = (Type)buffer.readInt();
|
| SkScalar freqX = buffer.readScalar();
|
| SkScalar freqY = buffer.readScalar();
|
| @@ -295,15 +360,17 @@ SkFlattenable* SkPerlinNoiseShader::CreateProc(SkReadBuffer& buffer) {
|
|
|
| switch (type) {
|
| case kFractalNoise_Type:
|
| - return SkPerlinNoiseShader::CreateFractalNoise(freqX, freqY, octaves, seed, &tileSize);
|
| + return SkPerlinNoiseShader2::CreateFractalNoise(freqX, freqY, octaves, seed, &tileSize);
|
| case kTurbulence_Type:
|
| - return SkPerlinNoiseShader::CreateTubulence(freqX, freqY, octaves, seed, &tileSize);
|
| + return SkPerlinNoiseShader2::CreateTubulence(freqX, freqY, octaves, seed, &tileSize);
|
| + case kImprovedNoise_Type:
|
| + return SkPerlinNoiseShader2::CreateImprovedNoise(freqX, freqY, octaves, seed);
|
| default:
|
| return nullptr;
|
| }
|
| }
|
|
|
| -void SkPerlinNoiseShader::flatten(SkWriteBuffer& buffer) const {
|
| +void SkPerlinNoiseShader2::flatten(SkWriteBuffer& buffer) const {
|
| buffer.writeInt((int) fType);
|
| buffer.writeScalar(fBaseFrequencyX);
|
| buffer.writeScalar(fBaseFrequencyY);
|
| @@ -313,7 +380,7 @@ void SkPerlinNoiseShader::flatten(SkWriteBuffer& buffer) const {
|
| buffer.writeInt(fTileSize.fHeight);
|
| }
|
|
|
| -SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::noise2D(
|
| +SkScalar SkPerlinNoiseShader2::PerlinNoiseShaderContext::noise2D(
|
| int channel, const StitchData& stitchData, const SkPoint& noiseVector) const {
|
| struct Noise {
|
| int noisePositionIntegerValue;
|
| @@ -330,7 +397,7 @@ SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::noise2D(
|
| Noise noiseX(noiseVector.x());
|
| Noise noiseY(noiseVector.y());
|
| SkScalar u, v;
|
| - const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoiseShader&>(fShader);
|
| + const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNoiseShader2&>(fShader);
|
| // If stitching, adjust lattice points accordingly.
|
| if (perlinNoiseShader.fStitchTiles) {
|
| noiseX.noisePositionIntegerValue =
|
| @@ -371,9 +438,9 @@ SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::noise2D(
|
| return SkScalarInterp(a, b, sy);
|
| }
|
|
|
| -SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::calculateTurbulenceValueForPoint(
|
| +SkScalar SkPerlinNoiseShader2::PerlinNoiseShaderContext::calculateTurbulenceValueForPoint(
|
| int channel, StitchData& stitchData, const SkPoint& point) const {
|
| - const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoiseShader&>(fShader);
|
| + const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNoiseShader2&>(fShader);
|
| if (perlinNoiseShader.fStitchTiles) {
|
| // Set up TurbulenceInitial stitch values.
|
| stitchData = fPaintingData->fStitchDataInit;
|
| @@ -414,8 +481,71 @@ SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::calculateTurbulenceValue
|
| return SkScalarPin(turbulenceFunctionResult, 0, SK_Scalar1);
|
| }
|
|
|
| -SkPMColor SkPerlinNoiseShader::PerlinNoiseShaderContext::shade(
|
| +////////////////////////////////////////////////////////////////////////////////////////////////////
|
| +// 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 SkPerlinNoiseShader2::PerlinNoiseShaderContext::calculateImprovedNoiseValueForPoint(
|
| + int channel, const SkPoint& point) const {
|
| + const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNoiseShader2&>(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 = SkScalarClampMax((result + 1.0f) / 2.0f, 1.0f);
|
| + return result;
|
| +}
|
| +////////////////////////////////////////////////////////////////////////////////////////////////////
|
| +
|
| +SkPMColor SkPerlinNoiseShader2::PerlinNoiseShaderContext::shade(
|
| const SkPoint& point, StitchData& stitchData) const {
|
| + const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNoiseShader2&>(fShader);
|
| SkPoint newPoint;
|
| fMatrix.mapPoints(&newPoint, &point, 1);
|
| newPoint.fX = SkScalarRoundToScalar(newPoint.fX);
|
| @@ -423,23 +553,29 @@ SkPMColor SkPerlinNoiseShader::PerlinNoiseShaderContext::shade(
|
|
|
| U8CPU rgba[4];
|
| for (int channel = 3; channel >= 0; --channel) {
|
| - rgba[channel] = SkScalarFloorToInt(255 *
|
| - calculateTurbulenceValueForPoint(channel, stitchData, newPoint));
|
| + SkScalar value;
|
| + if (perlinNoiseShader.fType == kImprovedNoise_Type) {
|
| + value = calculateImprovedNoiseValueForPoint(channel, newPoint);
|
| + }
|
| + else {
|
| + value = calculateTurbulenceValueForPoint(channel, stitchData, newPoint);
|
| + }
|
| + rgba[channel] = SkScalarFloorToInt(255 * value);
|
| }
|
| return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]);
|
| }
|
|
|
| -SkShader::Context* SkPerlinNoiseShader::onCreateContext(const ContextRec& rec,
|
| +SkShader::Context* SkPerlinNoiseShader2::onCreateContext(const ContextRec& rec,
|
| void* storage) const {
|
| return new (storage) PerlinNoiseShaderContext(*this, rec);
|
| }
|
|
|
| -size_t SkPerlinNoiseShader::contextSize() const {
|
| +size_t SkPerlinNoiseShader2::contextSize() const {
|
| return sizeof(PerlinNoiseShaderContext);
|
| }
|
|
|
| -SkPerlinNoiseShader::PerlinNoiseShaderContext::PerlinNoiseShaderContext(
|
| - const SkPerlinNoiseShader& shader, const ContextRec& rec)
|
| +SkPerlinNoiseShader2::PerlinNoiseShaderContext::PerlinNoiseShaderContext(
|
| + const SkPerlinNoiseShader2& shader, const ContextRec& rec)
|
| : INHERITED(shader, rec)
|
| {
|
| SkMatrix newMatrix = *rec.fMatrix;
|
| @@ -454,9 +590,9 @@ SkPerlinNoiseShader::PerlinNoiseShaderContext::PerlinNoiseShaderContext(
|
| shader.fBaseFrequencyY, newMatrix);
|
| }
|
|
|
| -SkPerlinNoiseShader::PerlinNoiseShaderContext::~PerlinNoiseShaderContext() { delete fPaintingData; }
|
| +SkPerlinNoiseShader2::PerlinNoiseShaderContext::~PerlinNoiseShaderContext() { delete fPaintingData; }
|
|
|
| -void SkPerlinNoiseShader::PerlinNoiseShaderContext::shadeSpan(
|
| +void SkPerlinNoiseShader2::PerlinNoiseShaderContext::shadeSpan(
|
| int x, int y, SkPMColor result[], int count) {
|
| SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y));
|
| StitchData stitchData;
|
| @@ -466,7 +602,7 @@ void SkPerlinNoiseShader::PerlinNoiseShaderContext::shadeSpan(
|
| }
|
| }
|
|
|
| -void SkPerlinNoiseShader::PerlinNoiseShaderContext::shadeSpan16(
|
| +void SkPerlinNoiseShader2::PerlinNoiseShaderContext::shadeSpan16(
|
| int x, int y, uint16_t result[], int count) {
|
| SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y));
|
| StitchData stitchData;
|
| @@ -483,10 +619,10 @@ void SkPerlinNoiseShader::PerlinNoiseShaderContext::shadeSpan16(
|
|
|
| #if SK_SUPPORT_GPU
|
|
|
| -class GrGLPerlinNoise : public GrGLFragmentProcessor {
|
| +class GrGLPerlinNoise2 : public GrGLFragmentProcessor {
|
| public:
|
| - GrGLPerlinNoise(const GrProcessor&);
|
| - virtual ~GrGLPerlinNoise() {}
|
| + GrGLPerlinNoise2(const GrProcessor&);
|
| + virtual ~GrGLPerlinNoise2() {}
|
|
|
| virtual void emitCode(EmitArgs&) override;
|
|
|
| @@ -498,7 +634,7 @@ protected:
|
| private:
|
|
|
| GrGLSLProgramDataManager::UniformHandle fStitchDataUni;
|
| - SkPerlinNoiseShader::Type fType;
|
| + SkPerlinNoiseShader2::Type fType;
|
| bool fStitchTiles;
|
| int fNumOctaves;
|
| GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni;
|
| @@ -509,24 +645,24 @@ private:
|
|
|
| /////////////////////////////////////////////////////////////////////
|
|
|
| -class GrPerlinNoiseEffect : public GrFragmentProcessor {
|
| +class GrPerlinNoise2Effect : public GrFragmentProcessor {
|
| public:
|
| - static GrFragmentProcessor* Create(SkPerlinNoiseShader::Type type,
|
| + static GrFragmentProcessor* Create(SkPerlinNoiseShader2::Type type,
|
| int numOctaves, bool stitchTiles,
|
| - SkPerlinNoiseShader::PaintingData* paintingData,
|
| + SkPerlinNoiseShader2::PaintingData* paintingData,
|
| GrTexture* permutationsTexture, GrTexture* noiseTexture,
|
| const SkMatrix& matrix) {
|
| - return new GrPerlinNoiseEffect(type, numOctaves, stitchTiles, paintingData,
|
| + return new GrPerlinNoise2Effect(type, numOctaves, stitchTiles, paintingData,
|
| permutationsTexture, noiseTexture, matrix);
|
| }
|
|
|
| - virtual ~GrPerlinNoiseEffect() { delete fPaintingData; }
|
| + virtual ~GrPerlinNoise2Effect() { delete fPaintingData; }
|
|
|
| const char* name() const override { return "PerlinNoise"; }
|
|
|
| - const SkPerlinNoiseShader::StitchData& stitchData() const { return fPaintingData->fStitchDataInit; }
|
| + const SkPerlinNoiseShader2::StitchData& stitchData() const { return fPaintingData->fStitchDataInit; }
|
|
|
| - SkPerlinNoiseShader::Type type() const { return fType; }
|
| + SkPerlinNoiseShader2::Type type() const { return fType; }
|
| bool stitchTiles() const { return fStitchTiles; }
|
| const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; }
|
| int numOctaves() const { return fNumOctaves; }
|
| @@ -534,16 +670,16 @@ public:
|
|
|
| private:
|
| GrGLFragmentProcessor* onCreateGLInstance() const override {
|
| - return new GrGLPerlinNoise(*this);
|
| + return new GrGLPerlinNoise2(*this);
|
| }
|
|
|
| virtual void onGetGLProcessorKey(const GrGLSLCaps& caps,
|
| GrProcessorKeyBuilder* b) const override {
|
| - GrGLPerlinNoise::GenKey(*this, caps, b);
|
| + GrGLPerlinNoise2::GenKey(*this, caps, b);
|
| }
|
|
|
| bool onIsEqual(const GrFragmentProcessor& sBase) const override {
|
| - const GrPerlinNoiseEffect& s = sBase.cast<GrPerlinNoiseEffect>();
|
| + const GrPerlinNoise2Effect& s = sBase.cast<GrPerlinNoise2Effect>();
|
| return fType == s.fType &&
|
| fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency &&
|
| fNumOctaves == s.fNumOctaves &&
|
| @@ -555,9 +691,9 @@ private:
|
| inout->setToUnknown(GrInvariantOutput::kWillNot_ReadInput);
|
| }
|
|
|
| - GrPerlinNoiseEffect(SkPerlinNoiseShader::Type type,
|
| + GrPerlinNoise2Effect(SkPerlinNoiseShader2::Type type,
|
| int numOctaves, bool stitchTiles,
|
| - SkPerlinNoiseShader::PaintingData* paintingData,
|
| + SkPerlinNoiseShader2::PaintingData* paintingData,
|
| GrTexture* permutationsTexture, GrTexture* noiseTexture,
|
| const SkMatrix& matrix)
|
| : fType(type)
|
| @@ -566,7 +702,7 @@ private:
|
| , fPermutationsAccess(permutationsTexture)
|
| , fNoiseAccess(noiseTexture)
|
| , fPaintingData(paintingData) {
|
| - this->initClassID<GrPerlinNoiseEffect>();
|
| + this->initClassID<GrPerlinNoise2Effect>();
|
| this->addTextureAccess(&fPermutationsAccess);
|
| this->addTextureAccess(&fNoiseAccess);
|
| fCoordTransform.reset(kLocal_GrCoordSet, matrix);
|
| @@ -575,22 +711,22 @@ private:
|
|
|
| GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
|
|
|
| - SkPerlinNoiseShader::Type fType;
|
| + SkPerlinNoiseShader2::Type fType;
|
| GrCoordTransform fCoordTransform;
|
| int fNumOctaves;
|
| bool fStitchTiles;
|
| GrTextureAccess fPermutationsAccess;
|
| GrTextureAccess fNoiseAccess;
|
| - SkPerlinNoiseShader::PaintingData *fPaintingData;
|
| + SkPerlinNoiseShader2::PaintingData *fPaintingData;
|
|
|
| private:
|
| typedef GrFragmentProcessor INHERITED;
|
| };
|
|
|
| /////////////////////////////////////////////////////////////////////
|
| -GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrPerlinNoiseEffect);
|
| +GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrPerlinNoise2Effect);
|
|
|
| -const GrFragmentProcessor* GrPerlinNoiseEffect::TestCreate(GrProcessorTestData* d) {
|
| +const GrFragmentProcessor* GrPerlinNoise2Effect::TestCreate(GrProcessorTestData* d) {
|
| int numOctaves = d->fRandom->nextRangeU(2, 10);
|
| bool stitchTiles = d->fRandom->nextBool();
|
| SkScalar seed = SkIntToScalar(d->fRandom->nextU());
|
| @@ -602,9 +738,9 @@ const GrFragmentProcessor* GrPerlinNoiseEffect::TestCreate(GrProcessorTestData*
|
| 0.99f);
|
|
|
| SkAutoTUnref<SkShader> shader(d->fRandom->nextBool() ?
|
| - SkPerlinNoiseShader::CreateFractalNoise(baseFrequencyX, baseFrequencyY, numOctaves, seed,
|
| + SkPerlinNoiseShader2::CreateFractalNoise(baseFrequencyX, baseFrequencyY, numOctaves, seed,
|
| stitchTiles ? &tileSize : nullptr) :
|
| - SkPerlinNoiseShader::CreateTurbulence(baseFrequencyX, baseFrequencyY, numOctaves, seed,
|
| + SkPerlinNoiseShader2::CreateTurbulence(baseFrequencyX, baseFrequencyY, numOctaves, seed,
|
| stitchTiles ? &tileSize : nullptr));
|
|
|
| GrPaint grPaint;
|
| @@ -613,13 +749,13 @@ const GrFragmentProcessor* GrPerlinNoiseEffect::TestCreate(GrProcessorTestData*
|
| kNone_SkFilterQuality);
|
| }
|
|
|
| -GrGLPerlinNoise::GrGLPerlinNoise(const GrProcessor& processor)
|
| - : fType(processor.cast<GrPerlinNoiseEffect>().type())
|
| - , fStitchTiles(processor.cast<GrPerlinNoiseEffect>().stitchTiles())
|
| - , fNumOctaves(processor.cast<GrPerlinNoiseEffect>().numOctaves()) {
|
| +GrGLPerlinNoise2::GrGLPerlinNoise2(const GrProcessor& processor)
|
| + : fType(processor.cast<GrPerlinNoise2Effect>().type())
|
| + , fStitchTiles(processor.cast<GrPerlinNoise2Effect>().stitchTiles())
|
| + , fNumOctaves(processor.cast<GrPerlinNoise2Effect>().numOctaves()) {
|
| }
|
|
|
| -void GrGLPerlinNoise::emitCode(EmitArgs& args) {
|
| +void GrGLPerlinNoise2::emitCode(EmitArgs& args) {
|
| GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
|
| SkString vCoords = fsBuilder->ensureFSCoords2D(args.fCoords, 0);
|
|
|
| @@ -819,7 +955,7 @@ void GrGLPerlinNoise::emitCode(EmitArgs& args) {
|
| fsBuilder->codeAppendf("\n\t\tfor (int octave = 0; octave < %d; ++octave) {", fNumOctaves);
|
|
|
| fsBuilder->codeAppendf("\n\t\t\t%s += ", args.fOutputColor);
|
| - if (fType != SkPerlinNoiseShader::kFractalNoise_Type) {
|
| + if (fType != SkPerlinNoiseShader2::kFractalNoise_Type) {
|
| fsBuilder->codeAppend("abs(");
|
| }
|
| if (fStitchTiles) {
|
| @@ -839,7 +975,7 @@ void GrGLPerlinNoise::emitCode(EmitArgs& args) {
|
| noiseFuncName.c_str(), chanCoordB, noiseVec,
|
| noiseFuncName.c_str(), chanCoordA, noiseVec);
|
| }
|
| - if (fType != SkPerlinNoiseShader::kFractalNoise_Type) {
|
| + if (fType != SkPerlinNoiseShader2::kFractalNoise_Type) {
|
| fsBuilder->codeAppendf(")"); // end of "abs("
|
| }
|
| fsBuilder->codeAppendf(" * %s;", ratio);
|
| @@ -852,7 +988,7 @@ void GrGLPerlinNoise::emitCode(EmitArgs& args) {
|
| }
|
| fsBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves
|
|
|
| - if (fType == SkPerlinNoiseShader::kFractalNoise_Type) {
|
| + if (fType == SkPerlinNoiseShader2::kFractalNoise_Type) {
|
| // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
|
| // by fractalNoise and (turbulenceFunctionResult) by turbulence.
|
| fsBuilder->codeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);",
|
| @@ -868,19 +1004,19 @@ void GrGLPerlinNoise::emitCode(EmitArgs& args) {
|
| args.fOutputColor, args.fOutputColor);
|
| }
|
|
|
| -void GrGLPerlinNoise::GenKey(const GrProcessor& processor, const GrGLSLCaps&,
|
| +void GrGLPerlinNoise2::GenKey(const GrProcessor& processor, const GrGLSLCaps&,
|
| GrProcessorKeyBuilder* b) {
|
| - const GrPerlinNoiseEffect& turbulence = processor.cast<GrPerlinNoiseEffect>();
|
| + const GrPerlinNoise2Effect& turbulence = processor.cast<GrPerlinNoise2Effect>();
|
|
|
| uint32_t key = turbulence.numOctaves();
|
|
|
| key = key << 3; // Make room for next 3 bits
|
|
|
| switch (turbulence.type()) {
|
| - case SkPerlinNoiseShader::kFractalNoise_Type:
|
| + case SkPerlinNoiseShader2::kFractalNoise_Type:
|
| key |= 0x1;
|
| break;
|
| - case SkPerlinNoiseShader::kTurbulence_Type:
|
| + case SkPerlinNoiseShader2::kTurbulence_Type:
|
| key |= 0x2;
|
| break;
|
| default:
|
| @@ -895,24 +1031,304 @@ void GrGLPerlinNoise::GenKey(const GrProcessor& processor, const GrGLSLCaps&,
|
| b->add32(key);
|
| }
|
|
|
| -void GrGLPerlinNoise::onSetData(const GrGLSLProgramDataManager& pdman,
|
| +void GrGLPerlinNoise2::onSetData(const GrGLSLProgramDataManager& pdman,
|
| const GrProcessor& processor) {
|
| INHERITED::onSetData(pdman, processor);
|
|
|
| - const GrPerlinNoiseEffect& turbulence = processor.cast<GrPerlinNoiseEffect>();
|
| + const GrPerlinNoise2Effect& turbulence = processor.cast<GrPerlinNoise2Effect>();
|
|
|
| const SkVector& baseFrequency = turbulence.baseFrequency();
|
| pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
|
|
|
| if (turbulence.stitchTiles()) {
|
| - const SkPerlinNoiseShader::StitchData& stitchData = turbulence.stitchData();
|
| + const SkPerlinNoiseShader2::StitchData& stitchData = turbulence.stitchData();
|
| pdman.set2f(fStitchDataUni, SkIntToScalar(stitchData.fWidth),
|
| SkIntToScalar(stitchData.fHeight));
|
| }
|
| }
|
|
|
| /////////////////////////////////////////////////////////////////////
|
| -const GrFragmentProcessor* SkPerlinNoiseShader::asFragmentProcessor(
|
| +
|
| +class GrGLImprovedPerlinNoise : public GrGLFragmentProcessor {
|
| +public:
|
| + GrGLImprovedPerlinNoise(const GrProcessor&);
|
| + virtual ~GrGLImprovedPerlinNoise() {}
|
| +
|
| + virtual void emitCode(EmitArgs&) override;
|
| +
|
| + static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder* b);
|
| +
|
| +protected:
|
| + void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
|
| +
|
| +private:
|
| +
|
| + SkScalar fZ;
|
| + GrGLSLProgramDataManager::UniformHandle fZUni;
|
| + GrGLSLProgramDataManager::UniformHandle fOctavesUni;
|
| + GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni;
|
| +
|
| +private:
|
| + typedef GrGLFragmentProcessor INHERITED;
|
| +};
|
| +
|
| +/////////////////////////////////////////////////////////////////////
|
| +
|
| +class GrImprovedPerlinNoiseEffect : public GrFragmentProcessor {
|
| +public:
|
| + static GrFragmentProcessor* Create(SkScalar octaves, SkScalar z,
|
| + SkPerlinNoiseShader2::PaintingData* paintingData,
|
| + GrTexture* permutationsTexture, GrTexture* gradientTexture,
|
| + const SkMatrix& matrix) {
|
| + return new GrImprovedPerlinNoiseEffect(octaves, z, paintingData, permutationsTexture,
|
| + gradientTexture, matrix);
|
| + }
|
| +
|
| + virtual ~GrImprovedPerlinNoiseEffect() { delete fPaintingData; }
|
| +
|
| + const char* name() const override { return "ImprovedPerlinNoise"; }
|
| +
|
| + const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; }
|
| + SkScalar z() const { return fZ; }
|
| + int octaves() const { return fOctaves; }
|
| + const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
|
| +
|
| +private:
|
| + GrGLFragmentProcessor* onCreateGLInstance() const override {
|
| + return new GrGLImprovedPerlinNoise(*this);
|
| + }
|
| +
|
| + virtual void onGetGLProcessorKey(const GrGLSLCaps& caps,
|
| + GrProcessorKeyBuilder* b) const override {
|
| + GrGLImprovedPerlinNoise::GenKey(*this, caps, b);
|
| + }
|
| +
|
| + bool onIsEqual(const GrFragmentProcessor& sBase) const override {
|
| + const GrImprovedPerlinNoiseEffect& s = sBase.cast<GrImprovedPerlinNoiseEffect>();
|
| + return fZ == fZ &&
|
| + fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency;
|
| + }
|
| +
|
| + void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
|
| + inout->setToUnknown(GrInvariantOutput::kWillNot_ReadInput);
|
| + }
|
| +
|
| + GrImprovedPerlinNoiseEffect(int octaves, SkScalar z,
|
| + SkPerlinNoiseShader2::PaintingData* paintingData,
|
| + GrTexture* permutationsTexture, GrTexture* gradientTexture,
|
| + const SkMatrix& matrix)
|
| + : fOctaves(octaves)
|
| + , fZ(z)
|
| + , fPermutationsAccess(permutationsTexture)
|
| + , fGradientAccess(gradientTexture)
|
| + , fPaintingData(paintingData) {
|
| + this->initClassID<GrImprovedPerlinNoiseEffect>();
|
| + this->addTextureAccess(&fPermutationsAccess);
|
| + this->addTextureAccess(&fGradientAccess);
|
| + fCoordTransform.reset(kLocal_GrCoordSet, matrix);
|
| + this->addCoordTransform(&fCoordTransform);
|
| + }
|
| +
|
| + GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
|
| +
|
| + GrCoordTransform fCoordTransform;
|
| + int fOctaves;
|
| + SkScalar fZ;
|
| + GrTextureAccess fPermutationsAccess;
|
| + GrTextureAccess fGradientAccess;
|
| + SkPerlinNoiseShader2::PaintingData *fPaintingData;
|
| +
|
| +private:
|
| + typedef GrFragmentProcessor INHERITED;
|
| +};
|
| +
|
| +/////////////////////////////////////////////////////////////////////
|
| +GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrImprovedPerlinNoiseEffect);
|
| +
|
| +const 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());
|
| +
|
| + SkAutoTUnref<SkShader> shader(SkPerlinNoiseShader2::CreateImprovedNoise(baseFrequencyX,
|
| + baseFrequencyY,
|
| + numOctaves,
|
| + z));
|
| +
|
| + GrPaint grPaint;
|
| + return shader->asFragmentProcessor(d->fContext,
|
| + GrTest::TestMatrix(d->fRandom), nullptr,
|
| + kNone_SkFilterQuality);
|
| +}
|
| +
|
| +GrGLImprovedPerlinNoise::GrGLImprovedPerlinNoise(const GrProcessor& processor)
|
| + : fZ(processor.cast<GrImprovedPerlinNoiseEffect>().z()) {
|
| +}
|
| +
|
| +void GrGLImprovedPerlinNoise::emitCode(EmitArgs& args) {
|
| + GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
|
| + SkString vCoords = fsBuilder->ensureFSCoords2D(args.fCoords, 0);
|
| +
|
| + fBaseFrequencyUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
|
| + kVec2f_GrSLType, kDefault_GrSLPrecision,
|
| + "baseFrequency");
|
| + const char* baseFrequencyUni = args.fBuilder->getUniformCStr(fBaseFrequencyUni);
|
| +
|
| + fOctavesUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
|
| + kFloat_GrSLType, kDefault_GrSLPrecision,
|
| + "octaves");
|
| + const char* octavesUni = args.fBuilder->getUniformCStr(fOctavesUni);
|
| +
|
| + fZUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
|
| + kFloat_GrSLType, kDefault_GrSLPrecision,
|
| + "z");
|
| + const char* zUni = args.fBuilder->getUniformCStr(fZUni);
|
| +
|
| + // fade function
|
| + static const GrGLSLShaderVar fadeArgs[] = {
|
| + GrGLSLShaderVar("t", kVec3f_GrSLType)
|
| + };
|
| + SkString fadeFuncName;
|
| + fsBuilder->emitFunction(kVec3f_GrSLType, "fade", SK_ARRAY_COUNT(fadeArgs),
|
| + fadeArgs,
|
| + "return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);",
|
| + &fadeFuncName);
|
| +
|
| + // perm function
|
| + static const GrGLSLShaderVar permArgs[] = {
|
| + GrGLSLShaderVar("x", kFloat_GrSLType)
|
| + };
|
| + SkString permFuncName;
|
| + SkString permCode("return ");
|
| + // FIXME even though I'm creating these textures with kRepeat_TileMode, they're clamped. Not
|
| + // sure why. Using fract() (here and the next texture lookup) as a workaround.
|
| + fsBuilder->appendTextureLookup(&permCode, args.fSamplers[0], "vec2(fract(x / 256.0), 0.0)",
|
| + kVec2f_GrSLType);
|
| + permCode.append(".r * 255.0;");
|
| + fsBuilder->emitFunction(kFloat_GrSLType, "perm", SK_ARRAY_COUNT(permArgs), permArgs,
|
| + permCode.c_str(), &permFuncName);
|
| +
|
| + // grad function
|
| + static const GrGLSLShaderVar gradArgs[] = {
|
| + GrGLSLShaderVar("x", kFloat_GrSLType),
|
| + GrGLSLShaderVar("p", kVec3f_GrSLType)
|
| + };
|
| + SkString gradFuncName;
|
| + SkString gradCode("return dot(");
|
| + fsBuilder->appendTextureLookup(&gradCode, args.fSamplers[1], "vec2(fract(x / 16.0), 0.0)",
|
| + kVec2f_GrSLType);
|
| + gradCode.append(".rgb * 255.0 - vec3(1.0), p);");
|
| + fsBuilder->emitFunction(kFloat_GrSLType, "grad", SK_ARRAY_COUNT(gradArgs), gradArgs,
|
| + gradCode.c_str(), &gradFuncName);
|
| +
|
| + // lerp function
|
| + static const GrGLSLShaderVar lerpArgs[] = {
|
| + GrGLSLShaderVar("a", kFloat_GrSLType),
|
| + GrGLSLShaderVar("b", kFloat_GrSLType),
|
| + GrGLSLShaderVar("w", kFloat_GrSLType)
|
| + };
|
| + SkString lerpFuncName;
|
| + fsBuilder->emitFunction(kFloat_GrSLType, "lerp", SK_ARRAY_COUNT(lerpArgs), lerpArgs,
|
| + "return a + w * (b - a);", &lerpFuncName);
|
| +
|
| + // noise function
|
| + static const GrGLSLShaderVar noiseArgs[] = {
|
| + GrGLSLShaderVar("p", kVec3f_GrSLType),
|
| + };
|
| + SkString noiseFuncName;
|
| + SkString noiseCode;
|
| + noiseCode.append("vec3 P = mod(floor(p), 256.0);");
|
| + noiseCode.append("p -= floor(p);");
|
| + noiseCode.appendf("vec3 f = %s(p);", fadeFuncName.c_str());
|
| + noiseCode.appendf("float A = %s(P.x) + P.y;", permFuncName.c_str());
|
| + noiseCode.appendf("float AA = %s(A) + P.z;", permFuncName.c_str());
|
| + noiseCode.appendf("float AB = %s(A + 1.0) + P.z;", permFuncName.c_str());
|
| + noiseCode.appendf("float B = %s(P.x + 1.0) + P.y;", permFuncName.c_str());
|
| + noiseCode.appendf("float BA = %s(B) + P.z;", permFuncName.c_str());
|
| + noiseCode.appendf("float BB = %s(B + 1.0) + P.z;", permFuncName.c_str());
|
| + noiseCode.appendf("float 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 + vec3(-1.0, 0.0, 0.0)), f.x),", gradFuncName.c_str(),
|
| + permFuncName.c_str());
|
| + noiseCode.appendf("%s(%s(%s(AB), p + vec3(0.0, -1.0, 0.0)),", lerpFuncName.c_str(),
|
| + gradFuncName.c_str(), permFuncName.c_str());
|
| + noiseCode.appendf("%s(%s(BB), p + vec3(-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 + vec3(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 + vec3(-1.0, 0.0, -1.0)), f.x),",
|
| + gradFuncName.c_str(), permFuncName.c_str());
|
| + noiseCode.appendf("%s(%s(%s(AB + 1.0), p + vec3(0.0, -1.0, -1.0)),",
|
| + lerpFuncName.c_str(), gradFuncName.c_str(), permFuncName.c_str());
|
| + noiseCode.appendf("%s(%s(BB + 1.0), p + vec3(-1.0, -1.0, -1.0)), f.x), f.y), f.z);",
|
| + gradFuncName.c_str(), permFuncName.c_str());
|
| + noiseCode.append("return result;");
|
| + fsBuilder->emitFunction(kFloat_GrSLType, "noise", SK_ARRAY_COUNT(noiseArgs), noiseArgs,
|
| + noiseCode.c_str(), &noiseFuncName);
|
| +
|
| + // noiseOctaves function
|
| + static const GrGLSLShaderVar noiseOctavesArgs[] = {
|
| + GrGLSLShaderVar("p", kVec3f_GrSLType),
|
| + GrGLSLShaderVar("octaves", kFloat_GrSLType),
|
| + };
|
| + SkString noiseOctavesFuncName;
|
| + SkString noiseOctavesCode;
|
| + noiseOctavesCode.append("float result = 0.0;");
|
| + noiseOctavesCode.append("float ratio = 1.0;");
|
| + noiseOctavesCode.append("for (float i = 0.0; i < octaves; i++) {");
|
| + 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;");
|
| + fsBuilder->emitFunction(kFloat_GrSLType, "noiseOctaves", SK_ARRAY_COUNT(noiseOctavesArgs),
|
| + noiseOctavesArgs, noiseOctavesCode.c_str(), &noiseOctavesFuncName);
|
| +
|
| + fsBuilder->codeAppendf("vec2 coords = %s * %s;", vCoords.c_str(), baseFrequencyUni);
|
| + fsBuilder->codeAppendf("float r = %s(vec3(coords, %s), %s);", noiseOctavesFuncName.c_str(),
|
| + zUni, octavesUni);
|
| + fsBuilder->codeAppendf("float g = %s(vec3(coords, %s + 1000.0), %s);",
|
| + noiseOctavesFuncName.c_str(), zUni, octavesUni);
|
| + fsBuilder->codeAppendf("float b = %s(vec3(coords, %s + 2000.0), %s);",
|
| + noiseOctavesFuncName.c_str(), zUni, octavesUni);
|
| + fsBuilder->codeAppendf("float a = %s(vec3(coords, %s + 3000.0), %s);",
|
| + noiseOctavesFuncName.c_str(), zUni, octavesUni);
|
| + fsBuilder->codeAppendf("%s = vec4(r, g, b, a);", args.fOutputColor);
|
| +
|
| + // Clamp values
|
| + fsBuilder->codeAppendf("%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor);
|
| +
|
| + // Pre-multiply the result
|
| + fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
|
| + args.fOutputColor, args.fOutputColor,
|
| + args.fOutputColor, args.fOutputColor);
|
| +}
|
| +
|
| +void GrGLImprovedPerlinNoise::GenKey(const GrProcessor& processor, const GrGLSLCaps&,
|
| + GrProcessorKeyBuilder* b) {
|
| +}
|
| +
|
| +void GrGLImprovedPerlinNoise::onSetData(const GrGLSLProgramDataManager& pdman,
|
| + const GrProcessor& 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(fOctavesUni, noise.octaves());
|
| +
|
| + pdman.set1f(fZUni, noise.z());
|
| +}
|
| +
|
| +/////////////////////////////////////////////////////////////////////
|
| +const GrFragmentProcessor* SkPerlinNoiseShader2::asFragmentProcessor(
|
| GrContext* context,
|
| const SkMatrix& viewM,
|
| const SkMatrix* externalLocalMatrix,
|
| @@ -927,6 +1343,29 @@ const GrFragmentProcessor* SkPerlinNoiseShader::asFragmentProcessor(
|
| SkMatrix matrix = viewM;
|
| matrix.preConcat(localMatrix);
|
|
|
| + // Either we don't stitch tiles, either we have a valid tile size
|
| + SkASSERT(!fStitchTiles || !fTileSize.isEmpty());
|
| +
|
| + SkPerlinNoiseShader2::PaintingData* paintingData =
|
| + new PaintingData(fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY, matrix);
|
| +
|
| + SkMatrix m = viewM;
|
| + m.setTranslateX(-localMatrix.getTranslateX() + SK_Scalar1);
|
| + m.setTranslateY(-localMatrix.getTranslateY() + SK_Scalar1);
|
| +
|
| + if (fType == kImprovedNoise_Type) {
|
| + GrTextureParams textureParams(SkShader::TileMode::kRepeat_TileMode,
|
| + GrTextureParams::FilterMode::kNone_FilterMode);
|
| + SkAutoTUnref<GrTexture> permutationsTexture(
|
| + GrRefCachedBitmapTexture(context, paintingData->getImprovedPermutationsBitmap(),
|
| + textureParams));
|
| + SkAutoTUnref<GrTexture> gradientTexture(
|
| + GrRefCachedBitmapTexture(context, paintingData->getGradientBitmap(),
|
| + textureParams));
|
| + return GrImprovedPerlinNoiseEffect::Create(fNumOctaves, fSeed, paintingData,
|
| + permutationsTexture, gradientTexture, m);
|
| + }
|
| +
|
| if (0 == fNumOctaves) {
|
| if (kFractalNoise_Type == fType) {
|
| // Extract the incoming alpha and emit rgba = (a/4, a/4, a/4, a/2)
|
| @@ -939,11 +1378,6 @@ const GrFragmentProcessor* SkPerlinNoiseShader::asFragmentProcessor(
|
| return GrConstColorProcessor::Create(0x0, GrConstColorProcessor::kIgnore_InputMode);
|
| }
|
|
|
| - // Either we don't stitch tiles, either we have a valid tile size
|
| - SkASSERT(!fStitchTiles || !fTileSize.isEmpty());
|
| -
|
| - SkPerlinNoiseShader::PaintingData* paintingData =
|
| - new PaintingData(fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY, matrix);
|
| SkAutoTUnref<GrTexture> permutationsTexture(
|
| GrRefCachedBitmapTexture(context, paintingData->getPermutationsBitmap(),
|
| GrTextureParams::ClampNoFilter()));
|
| @@ -951,12 +1385,9 @@ const GrFragmentProcessor* SkPerlinNoiseShader::asFragmentProcessor(
|
| GrRefCachedBitmapTexture(context, paintingData->getNoiseBitmap(),
|
| GrTextureParams::ClampNoFilter()));
|
|
|
| - SkMatrix m = viewM;
|
| - m.setTranslateX(-localMatrix.getTranslateX() + SK_Scalar1);
|
| - m.setTranslateY(-localMatrix.getTranslateY() + SK_Scalar1);
|
| if ((permutationsTexture) && (noiseTexture)) {
|
| SkAutoTUnref<GrFragmentProcessor> inner(
|
| - GrPerlinNoiseEffect::Create(fType,
|
| + GrPerlinNoise2Effect::Create(fType,
|
| fNumOctaves,
|
| fStitchTiles,
|
| paintingData,
|
| @@ -971,8 +1402,8 @@ const GrFragmentProcessor* SkPerlinNoiseShader::asFragmentProcessor(
|
| #endif
|
|
|
| #ifndef SK_IGNORE_TO_STRING
|
| -void SkPerlinNoiseShader::toString(SkString* str) const {
|
| - str->append("SkPerlinNoiseShader: (");
|
| +void SkPerlinNoiseShader2::toString(SkString* str) const {
|
| + str->append("SkPerlinNoiseShader2: (");
|
|
|
| str->append("type: ");
|
| switch (fType) {
|
|
|