• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2013 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "include/effects/SkPerlinNoiseShader.h"
9 
10 #include "include/core/SkColorFilter.h"
11 #include "include/core/SkShader.h"
12 #include "include/core/SkString.h"
13 #include "include/core/SkUnPreMultiply.h"
14 #include "src/core/SkArenaAlloc.h"
15 #include "src/core/SkMakeUnique.h"
16 #include "src/core/SkReadBuffer.h"
17 #include "src/core/SkWriteBuffer.h"
18 
19 #if SK_SUPPORT_GPU
20 #include "include/private/GrRecordingContext.h"
21 #include "src/gpu/GrCoordTransform.h"
22 #include "src/gpu/GrRecordingContextPriv.h"
23 #include "src/gpu/SkGr.h"
24 #include "src/gpu/effects/generated/GrConstColorProcessor.h"
25 #include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
26 #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
27 #include "src/gpu/glsl/GrGLSLProgramDataManager.h"
28 #include "src/gpu/glsl/GrGLSLUniformHandler.h"
29 #endif
30 
31 static const int kBlockSize = 256;
32 static const int kBlockMask = kBlockSize - 1;
33 static const int kPerlinNoise = 4096;
34 static const int kRandMaximum = SK_MaxS32; // 2**31 - 1
35 
36 static uint8_t improved_noise_permutations[] = {
37     151, 160, 137,  91,  90,  15, 131,  13, 201,  95,  96,  53, 194, 233,   7, 225, 140,  36, 103,
38      30,  69, 142,   8,  99,  37, 240,  21,  10,  23, 190,   6, 148, 247, 120, 234,  75,   0,  26,
39     197,  62,  94, 252, 219, 203, 117,  35,  11,  32,  57, 177,  33,  88, 237, 149,  56,  87, 174,
40      20, 125, 136, 171, 168,  68, 175,  74, 165,  71, 134, 139,  48,  27, 166,  77, 146, 158, 231,
41      83, 111, 229, 122,  60, 211, 133, 230, 220, 105,  92,  41,  55,  46, 245,  40, 244, 102, 143,
42      54,  65,  25,  63, 161,   1, 216,  80,  73, 209,  76, 132, 187, 208,  89,  18, 169, 200, 196,
43     135, 130, 116, 188, 159,  86, 164, 100, 109, 198, 173, 186,   3,  64,  52, 217, 226, 250, 124,
44     123,   5, 202,  38, 147, 118, 126, 255,  82,  85, 212, 207, 206,  59, 227,  47,  16,  58,  17,
45     182, 189,  28,  42, 223, 183, 170, 213, 119, 248, 152,   2,  44, 154, 163,  70, 221, 153, 101,
46     155, 167,  43, 172,   9, 129,  22,  39, 253,  19,  98, 108, 110,  79, 113, 224, 232, 178, 185,
47     112, 104, 218, 246,  97, 228, 251,  34, 242, 193, 238, 210, 144,  12, 191, 179, 162, 241,  81,
48      51, 145, 235, 249,  14, 239, 107,  49, 192, 214,  31, 181, 199, 106, 157, 184,  84, 204, 176,
49     115, 121,  50,  45, 127,   4, 150, 254, 138, 236, 205,  93, 222, 114,  67,  29,  24,  72, 243,
50     141, 128, 195,  78,  66, 215,  61, 156, 180,
51     151, 160, 137,  91,  90,  15, 131,  13, 201,  95,  96,  53, 194, 233,   7, 225, 140,  36, 103,
52      30,  69, 142,   8,  99,  37, 240,  21,  10,  23, 190,   6, 148, 247, 120, 234,  75,   0,  26,
53     197,  62,  94, 252, 219, 203, 117,  35,  11,  32,  57, 177,  33,  88, 237, 149,  56,  87, 174,
54      20, 125, 136, 171, 168,  68, 175,  74, 165,  71, 134, 139,  48,  27, 166,  77, 146, 158, 231,
55      83, 111, 229, 122,  60, 211, 133, 230, 220, 105,  92,  41,  55,  46, 245,  40, 244, 102, 143,
56      54,  65,  25,  63, 161,   1, 216,  80,  73, 209,  76, 132, 187, 208,  89,  18, 169, 200, 196,
57     135, 130, 116, 188, 159,  86, 164, 100, 109, 198, 173, 186,   3,  64,  52, 217, 226, 250, 124,
58     123,   5, 202,  38, 147, 118, 126, 255,  82,  85, 212, 207, 206,  59, 227,  47,  16,  58,  17,
59     182, 189,  28,  42, 223, 183, 170, 213, 119, 248, 152,   2,  44, 154, 163,  70, 221, 153, 101,
60     155, 167,  43, 172,   9, 129,  22,  39, 253,  19,  98, 108, 110,  79, 113, 224, 232, 178, 185,
61     112, 104, 218, 246,  97, 228, 251,  34, 242, 193, 238, 210, 144,  12, 191, 179, 162, 241,  81,
62      51, 145, 235, 249,  14, 239, 107,  49, 192, 214,  31, 181, 199, 106, 157, 184,  84, 204, 176,
63     115, 121,  50,  45, 127,   4, 150, 254, 138, 236, 205,  93, 222, 114,  67,  29,  24,  72, 243,
64     141, 128, 195,  78,  66, 215,  61, 156, 180
65 };
66 
67 class SkPerlinNoiseShaderImpl : public SkShaderBase {
68 public:
69     struct StitchData {
StitchDataSkPerlinNoiseShaderImpl::StitchData70         StitchData()
71           : fWidth(0)
72           , fWrapX(0)
73           , fHeight(0)
74           , fWrapY(0)
75         {}
76 
StitchDataSkPerlinNoiseShaderImpl::StitchData77         StitchData(SkScalar w, SkScalar h)
78           : fWidth(SkTMin(SkScalarRoundToInt(w), SK_MaxS32 - kPerlinNoise))
79           , fWrapX(kPerlinNoise + fWidth)
80           , fHeight(SkTMin(SkScalarRoundToInt(h), SK_MaxS32 - kPerlinNoise))
81           , fWrapY(kPerlinNoise + fHeight) {}
82 
operator ==SkPerlinNoiseShaderImpl::StitchData83         bool operator==(const StitchData& other) const {
84             return fWidth == other.fWidth &&
85                    fWrapX == other.fWrapX &&
86                    fHeight == other.fHeight &&
87                    fWrapY == other.fWrapY;
88         }
89 
90         int fWidth; // How much to subtract to wrap for stitching.
91         int fWrapX; // Minimum value to wrap.
92         int fHeight;
93         int fWrapY;
94     };
95 
96     struct PaintingData {
PaintingDataSkPerlinNoiseShaderImpl::PaintingData97         PaintingData(const SkISize& tileSize, SkScalar seed,
98                      SkScalar baseFrequencyX, SkScalar baseFrequencyY,
99                      const SkMatrix& matrix)
100         {
101             SkVector tileVec;
102             matrix.mapVector(SkIntToScalar(tileSize.fWidth), SkIntToScalar(tileSize.fHeight),
103                              &tileVec);
104 
105             SkSize scale;
106             if (!matrix.decomposeScale(&scale, nullptr)) {
107                 scale.set(SK_ScalarNearlyZero, SK_ScalarNearlyZero);
108             }
109             fBaseFrequency.set(baseFrequencyX * SkScalarInvert(scale.width()),
110                                baseFrequencyY * SkScalarInvert(scale.height()));
111             fTileSize.set(SkScalarRoundToInt(tileVec.fX), SkScalarRoundToInt(tileVec.fY));
112             this->init(seed);
113             if (!fTileSize.isEmpty()) {
114                 this->stitch();
115             }
116 
117     #if SK_SUPPORT_GPU
118             SkImageInfo info = SkImageInfo::MakeA8(kBlockSize, 1);
119             SkPixmap permutationsPixmap(info, fLatticeSelector, info.minRowBytes());
120             fPermutationsImage = SkImage::MakeFromRaster(permutationsPixmap, nullptr, nullptr);
121 
122             info = SkImageInfo::MakeN32Premul(kBlockSize, 4);
123             SkPixmap noisePixmap(info, fNoise[0][0], info.minRowBytes());
124             fNoiseImage = SkImage::MakeFromRaster(noisePixmap, nullptr, nullptr);
125 
126             info = SkImageInfo::MakeA8(256, 1);
127             SkPixmap impPermutationsPixmap(info, improved_noise_permutations, info.minRowBytes());
128             fImprovedPermutationsImage = SkImage::MakeFromRaster(impPermutationsPixmap, nullptr,
129                                                                  nullptr);
130 
131             static uint8_t gradients[] = { 2, 2, 1, 0,
132                                            0, 2, 1, 0,
133                                            2, 0, 1, 0,
134                                            0, 0, 1, 0,
135                                            2, 1, 2, 0,
136                                            0, 1, 2, 0,
137                                            2, 1, 0, 0,
138                                            0, 1, 0, 0,
139                                            1, 2, 2, 0,
140                                            1, 0, 2, 0,
141                                            1, 2, 0, 0,
142                                            1, 0, 0, 0,
143                                            2, 2, 1, 0,
144                                            1, 0, 2, 0,
145                                            0, 2, 1, 0,
146                                            1, 0, 0, 0 };
147             info = SkImageInfo::MakeN32Premul(16, 1);
148             SkPixmap gradPixmap(info, gradients, info.minRowBytes());
149             fGradientImage = SkImage::MakeFromRaster(gradPixmap, nullptr, nullptr);
150     #endif
151         }
152 
153     #if SK_SUPPORT_GPU
PaintingDataSkPerlinNoiseShaderImpl::PaintingData154         PaintingData(const PaintingData& that)
155                 : fSeed(that.fSeed)
156                 , fTileSize(that.fTileSize)
157                 , fBaseFrequency(that.fBaseFrequency)
158                 , fStitchDataInit(that.fStitchDataInit)
159                 , fPermutationsImage(that.fPermutationsImage)
160                 , fNoiseImage(that.fNoiseImage)
161                 , fImprovedPermutationsImage(that.fImprovedPermutationsImage)
162                 , fGradientImage(that.fGradientImage) {
163             memcpy(fLatticeSelector, that.fLatticeSelector, sizeof(fLatticeSelector));
164             memcpy(fNoise, that.fNoise, sizeof(fNoise));
165             memcpy(fGradient, that.fGradient, sizeof(fGradient));
166         }
167     #endif
168 
169         int         fSeed;
170         uint8_t     fLatticeSelector[kBlockSize];
171         uint16_t    fNoise[4][kBlockSize][2];
172         SkPoint     fGradient[4][kBlockSize];
173         SkISize     fTileSize;
174         SkVector    fBaseFrequency;
175         StitchData  fStitchDataInit;
176 
177     private:
178 
179     #if SK_SUPPORT_GPU
180         sk_sp<SkImage> fPermutationsImage;
181         sk_sp<SkImage> fNoiseImage;
182         sk_sp<SkImage> fImprovedPermutationsImage;
183         sk_sp<SkImage> fGradientImage;
184     #endif
185 
randomSkPerlinNoiseShaderImpl::PaintingData186         inline int random()  {
187             static const int gRandAmplitude = 16807; // 7**5; primitive root of m
188             static const int gRandQ = 127773; // m / a
189             static const int gRandR = 2836; // m % a
190 
191             int result = gRandAmplitude * (fSeed % gRandQ) - gRandR * (fSeed / gRandQ);
192             if (result <= 0)
193                 result += kRandMaximum;
194             fSeed = result;
195             return result;
196         }
197 
198         // Only called once. Could be part of the constructor.
initSkPerlinNoiseShaderImpl::PaintingData199         void init(SkScalar seed)
200         {
201             static const SkScalar gInvBlockSizef = SkScalarInvert(SkIntToScalar(kBlockSize));
202 
203             // According to the SVG spec, we must truncate (not round) the seed value.
204             fSeed = SkScalarTruncToInt(seed);
205             // The seed value clamp to the range [1, kRandMaximum - 1].
206             if (fSeed <= 0) {
207                 fSeed = -(fSeed % (kRandMaximum - 1)) + 1;
208             }
209             if (fSeed > kRandMaximum - 1) {
210                 fSeed = kRandMaximum - 1;
211             }
212             for (int channel = 0; channel < 4; ++channel) {
213                 for (int i = 0; i < kBlockSize; ++i) {
214                     fLatticeSelector[i] = i;
215                     fNoise[channel][i][0] = (random() % (2 * kBlockSize));
216                     fNoise[channel][i][1] = (random() % (2 * kBlockSize));
217                 }
218             }
219             for (int i = kBlockSize - 1; i > 0; --i) {
220                 int k = fLatticeSelector[i];
221                 int j = random() % kBlockSize;
222                 SkASSERT(j >= 0);
223                 SkASSERT(j < kBlockSize);
224                 fLatticeSelector[i] = fLatticeSelector[j];
225                 fLatticeSelector[j] = k;
226             }
227 
228             // Perform the permutations now
229             {
230                 // Copy noise data
231                 uint16_t noise[4][kBlockSize][2];
232                 for (int i = 0; i < kBlockSize; ++i) {
233                     for (int channel = 0; channel < 4; ++channel) {
234                         for (int j = 0; j < 2; ++j) {
235                             noise[channel][i][j] = fNoise[channel][i][j];
236                         }
237                     }
238                 }
239                 // Do permutations on noise data
240                 for (int i = 0; i < kBlockSize; ++i) {
241                     for (int channel = 0; channel < 4; ++channel) {
242                         for (int j = 0; j < 2; ++j) {
243                             fNoise[channel][i][j] = noise[channel][fLatticeSelector[i]][j];
244                         }
245                     }
246                 }
247             }
248 
249             // Half of the largest possible value for 16 bit unsigned int
250             static const SkScalar gHalfMax16bits = 32767.5f;
251 
252             // Compute gradients from permutated noise data
253             for (int channel = 0; channel < 4; ++channel) {
254                 for (int i = 0; i < kBlockSize; ++i) {
255                     fGradient[channel][i] = SkPoint::Make(
256                         (fNoise[channel][i][0] - kBlockSize) * gInvBlockSizef,
257                         (fNoise[channel][i][1] - kBlockSize) * gInvBlockSizef);
258                     fGradient[channel][i].normalize();
259                     // Put the normalized gradient back into the noise data
260                     fNoise[channel][i][0] = SkScalarRoundToInt(
261                                                    (fGradient[channel][i].fX + 1) * gHalfMax16bits);
262                     fNoise[channel][i][1] = SkScalarRoundToInt(
263                                                    (fGradient[channel][i].fY + 1) * gHalfMax16bits);
264                 }
265             }
266         }
267 
268         // Only called once. Could be part of the constructor.
stitchSkPerlinNoiseShaderImpl::PaintingData269         void stitch() {
270             SkScalar tileWidth  = SkIntToScalar(fTileSize.width());
271             SkScalar tileHeight = SkIntToScalar(fTileSize.height());
272             SkASSERT(tileWidth > 0 && tileHeight > 0);
273             // When stitching tiled turbulence, the frequencies must be adjusted
274             // so that the tile borders will be continuous.
275             if (fBaseFrequency.fX) {
276                 SkScalar lowFrequencx =
277                     SkScalarFloorToScalar(tileWidth * fBaseFrequency.fX) / tileWidth;
278                 SkScalar highFrequencx =
279                     SkScalarCeilToScalar(tileWidth * fBaseFrequency.fX) / tileWidth;
280                 // BaseFrequency should be non-negative according to the standard.
281                 // lowFrequencx can be 0 if fBaseFrequency.fX is very small.
282                 if (sk_ieee_float_divide(fBaseFrequency.fX, lowFrequencx) < highFrequencx / fBaseFrequency.fX) {
283                     fBaseFrequency.fX = lowFrequencx;
284                 } else {
285                     fBaseFrequency.fX = highFrequencx;
286                 }
287             }
288             if (fBaseFrequency.fY) {
289                 SkScalar lowFrequency =
290                     SkScalarFloorToScalar(tileHeight * fBaseFrequency.fY) / tileHeight;
291                 SkScalar highFrequency =
292                     SkScalarCeilToScalar(tileHeight * fBaseFrequency.fY) / tileHeight;
293                 // lowFrequency can be 0 if fBaseFrequency.fY is very small.
294                 if (sk_ieee_float_divide(fBaseFrequency.fY, lowFrequency) < highFrequency / fBaseFrequency.fY) {
295                     fBaseFrequency.fY = lowFrequency;
296                 } else {
297                     fBaseFrequency.fY = highFrequency;
298                 }
299             }
300             // Set up TurbulenceInitial stitch values.
301             fStitchDataInit = StitchData(tileWidth * fBaseFrequency.fX,
302                                          tileHeight * fBaseFrequency.fY);
303         }
304 
305     public:
306 
307 #if SK_SUPPORT_GPU
getPermutationsImageSkPerlinNoiseShaderImpl::PaintingData308         const sk_sp<SkImage> getPermutationsImage() const { return fPermutationsImage; }
309 
getNoiseImageSkPerlinNoiseShaderImpl::PaintingData310         const sk_sp<SkImage> getNoiseImage() const { return fNoiseImage; }
311 
getImprovedPermutationsImageSkPerlinNoiseShaderImpl::PaintingData312         const sk_sp<SkImage> getImprovedPermutationsImage() const {
313             return fImprovedPermutationsImage;
314         }
315 
getGradientImageSkPerlinNoiseShaderImpl::PaintingData316         const sk_sp<SkImage> getGradientImage() const { return fGradientImage; }
317 #endif
318     };
319 
320     /**
321      *  About the noise types : the difference between the first 2 is just minor tweaks to the
322      *  algorithm, they're not 2 entirely different noises. The output looks different, but once the
323      *  noise is generated in the [1, -1] range, the output is brought back in the [0, 1] range by
324      *  doing :
325      *  kFractalNoise_Type : noise * 0.5 + 0.5
326      *  kTurbulence_Type   : abs(noise)
327      *  Very little differences between the 2 types, although you can tell the difference visually.
328      *  "Improved" is based on the Improved Perlin Noise algorithm described at
329      *  http://mrl.nyu.edu/~perlin/noise/. It is quite distinct from the other two, and the noise is
330      *  a 2D slice of a 3D noise texture. Minor changes to the Z coordinate will result in minor
331      *  changes to the noise, making it suitable for animated noise.
332      */
333     enum Type {
334         kFractalNoise_Type,
335         kTurbulence_Type,
336         kImprovedNoise_Type,
337         kLast_Type = kImprovedNoise_Type
338     };
339 
340     static const int kMaxOctaves = 255; // numOctaves must be <= 0 and <= kMaxOctaves
341 
342     SkPerlinNoiseShaderImpl(SkPerlinNoiseShaderImpl::Type type, SkScalar baseFrequencyX,
343                       SkScalar baseFrequencyY, int numOctaves, SkScalar seed,
344                       const SkISize* tileSize);
345 
346     class PerlinNoiseShaderContext : public Context {
347     public:
348         PerlinNoiseShaderContext(const SkPerlinNoiseShaderImpl& shader, const ContextRec&);
349 
350         void shadeSpan(int x, int y, SkPMColor[], int count) override;
351 
352     private:
353         SkPMColor shade(const SkPoint& point, StitchData& stitchData) const;
354         SkScalar calculateTurbulenceValueForPoint(
355                                                   int channel,
356                                                   StitchData& stitchData, const SkPoint& point) const;
357         SkScalar calculateImprovedNoiseValueForPoint(int channel, const SkPoint& point) const;
358         SkScalar noise2D(int channel,
359                          const StitchData& stitchData, const SkPoint& noiseVector) const;
360 
361         SkMatrix     fMatrix;
362         PaintingData fPaintingData;
363 
364         typedef Context INHERITED;
365     };
366 
367 #if SK_SUPPORT_GPU
368     std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(const GrFPArgs&) const override;
369 #endif
370 
371 protected:
372     void flatten(SkWriteBuffer&) const override;
373 #ifdef SK_ENABLE_LEGACY_SHADERCONTEXT
374     Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override;
375 #endif
376 
377 private:
378     SK_FLATTENABLE_HOOKS(SkPerlinNoiseShaderImpl)
379 
380     const SkPerlinNoiseShaderImpl::Type fType;
381     const SkScalar                  fBaseFrequencyX;
382     const SkScalar                  fBaseFrequencyY;
383     const int                       fNumOctaves;
384     const SkScalar                  fSeed;
385     const SkISize                   fTileSize;
386     const bool                      fStitchTiles;
387 
388     friend class ::SkPerlinNoiseShader;
389 
390     typedef SkShaderBase INHERITED;
391 };
392 
393 namespace {
394 
395 // noiseValue is the color component's value (or color)
396 // limitValue is the maximum perlin noise array index value allowed
397 // newValue is the current noise dimension (either width or height)
checkNoise(int noiseValue,int limitValue,int newValue)398 inline int checkNoise(int noiseValue, int limitValue, int newValue) {
399     // If the noise value would bring us out of bounds of the current noise array while we are
400     // stiching noise tiles together, wrap the noise around the current dimension of the noise to
401     // stay within the array bounds in a continuous fashion (so that tiling lines are not visible)
402     if (noiseValue >= limitValue) {
403         noiseValue -= newValue;
404     }
405     return noiseValue;
406 }
407 
smoothCurve(SkScalar t)408 inline SkScalar smoothCurve(SkScalar t) {
409     return t * t * (3 - 2 * t);
410 }
411 
412 } // end namespace
413 
SkPerlinNoiseShaderImpl(SkPerlinNoiseShaderImpl::Type type,SkScalar baseFrequencyX,SkScalar baseFrequencyY,int numOctaves,SkScalar seed,const SkISize * tileSize)414 SkPerlinNoiseShaderImpl::SkPerlinNoiseShaderImpl(SkPerlinNoiseShaderImpl::Type type,
415                                                  SkScalar baseFrequencyX,
416                                                  SkScalar baseFrequencyY,
417                                                  int numOctaves,
418                                                  SkScalar seed,
419                                                  const SkISize* tileSize)
420   : fType(type)
421   , fBaseFrequencyX(baseFrequencyX)
422   , fBaseFrequencyY(baseFrequencyY)
423   , fNumOctaves(numOctaves > kMaxOctaves ? kMaxOctaves : numOctaves/*[0,255] octaves allowed*/)
424   , fSeed(seed)
425   , fTileSize(nullptr == tileSize ? SkISize::Make(0, 0) : *tileSize)
426   , fStitchTiles(!fTileSize.isEmpty())
427 {
428     SkASSERT(numOctaves >= 0 && numOctaves <= kMaxOctaves);
429     SkASSERT(fBaseFrequencyX >= 0);
430     SkASSERT(fBaseFrequencyY >= 0);
431 }
432 
CreateProc(SkReadBuffer & buffer)433 sk_sp<SkFlattenable> SkPerlinNoiseShaderImpl::CreateProc(SkReadBuffer& buffer) {
434     Type type = buffer.read32LE(kLast_Type);
435 
436     SkScalar freqX = buffer.readScalar();
437     SkScalar freqY = buffer.readScalar();
438     int octaves = buffer.read32LE<int>(kMaxOctaves);
439 
440     SkScalar seed = buffer.readScalar();
441     SkISize tileSize;
442     tileSize.fWidth = buffer.readInt();
443     tileSize.fHeight = buffer.readInt();
444 
445     switch (type) {
446         case kFractalNoise_Type:
447             return SkPerlinNoiseShader::MakeFractalNoise(freqX, freqY, octaves, seed, &tileSize);
448         case kTurbulence_Type:
449             return SkPerlinNoiseShader::MakeTurbulence(freqX, freqY, octaves, seed, &tileSize);
450         case kImprovedNoise_Type:
451             return SkPerlinNoiseShader::MakeImprovedNoise(freqX, freqY, octaves, seed);
452         default:
453             // Really shouldn't get here b.c. of earlier check on type
454             buffer.validate(false);
455             return nullptr;
456     }
457 }
458 
flatten(SkWriteBuffer & buffer) const459 void SkPerlinNoiseShaderImpl::flatten(SkWriteBuffer& buffer) const {
460     buffer.writeInt((int) fType);
461     buffer.writeScalar(fBaseFrequencyX);
462     buffer.writeScalar(fBaseFrequencyY);
463     buffer.writeInt(fNumOctaves);
464     buffer.writeScalar(fSeed);
465     buffer.writeInt(fTileSize.fWidth);
466     buffer.writeInt(fTileSize.fHeight);
467 }
468 
noise2D(int channel,const StitchData & stitchData,const SkPoint & noiseVector) const469 SkScalar SkPerlinNoiseShaderImpl::PerlinNoiseShaderContext::noise2D(
470         int channel, const StitchData& stitchData, const SkPoint& noiseVector) const {
471     struct Noise {
472         int noisePositionIntegerValue;
473         int nextNoisePositionIntegerValue;
474         SkScalar noisePositionFractionValue;
475         Noise(SkScalar component)
476         {
477             SkScalar position = component + kPerlinNoise;
478             noisePositionIntegerValue = SkScalarFloorToInt(position);
479             noisePositionFractionValue = position - SkIntToScalar(noisePositionIntegerValue);
480             nextNoisePositionIntegerValue = noisePositionIntegerValue + 1;
481         }
482     };
483     Noise noiseX(noiseVector.x());
484     Noise noiseY(noiseVector.y());
485     SkScalar u, v;
486     const SkPerlinNoiseShaderImpl& perlinNoiseShader = static_cast<const SkPerlinNoiseShaderImpl&>(fShader);
487     // If stitching, adjust lattice points accordingly.
488     if (perlinNoiseShader.fStitchTiles) {
489         noiseX.noisePositionIntegerValue =
490             checkNoise(noiseX.noisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth);
491         noiseY.noisePositionIntegerValue =
492             checkNoise(noiseY.noisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight);
493         noiseX.nextNoisePositionIntegerValue =
494             checkNoise(noiseX.nextNoisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth);
495         noiseY.nextNoisePositionIntegerValue =
496             checkNoise(noiseY.nextNoisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight);
497     }
498     noiseX.noisePositionIntegerValue &= kBlockMask;
499     noiseY.noisePositionIntegerValue &= kBlockMask;
500     noiseX.nextNoisePositionIntegerValue &= kBlockMask;
501     noiseY.nextNoisePositionIntegerValue &= kBlockMask;
502     int i = fPaintingData.fLatticeSelector[noiseX.noisePositionIntegerValue];
503     int j = fPaintingData.fLatticeSelector[noiseX.nextNoisePositionIntegerValue];
504     int b00 = (i + noiseY.noisePositionIntegerValue) & kBlockMask;
505     int b10 = (j + noiseY.noisePositionIntegerValue) & kBlockMask;
506     int b01 = (i + noiseY.nextNoisePositionIntegerValue) & kBlockMask;
507     int b11 = (j + noiseY.nextNoisePositionIntegerValue) & kBlockMask;
508     SkScalar sx = smoothCurve(noiseX.noisePositionFractionValue);
509     SkScalar sy = smoothCurve(noiseY.noisePositionFractionValue);
510 
511     if (sx < 0 || sy < 0 || sx > 1 || sy > 1) {
512         return 0;  // Check for pathological inputs.
513     }
514 
515     // This is taken 1:1 from SVG spec: http://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement
516     SkPoint fractionValue = SkPoint::Make(noiseX.noisePositionFractionValue,
517                                           noiseY.noisePositionFractionValue); // Offset (0,0)
518     u = fPaintingData.fGradient[channel][b00].dot(fractionValue);
519     fractionValue.fX -= SK_Scalar1; // Offset (-1,0)
520     v = fPaintingData.fGradient[channel][b10].dot(fractionValue);
521     SkScalar a = SkScalarInterp(u, v, sx);
522     fractionValue.fY -= SK_Scalar1; // Offset (-1,-1)
523     v = fPaintingData.fGradient[channel][b11].dot(fractionValue);
524     fractionValue.fX = noiseX.noisePositionFractionValue; // Offset (0,-1)
525     u = fPaintingData.fGradient[channel][b01].dot(fractionValue);
526     SkScalar b = SkScalarInterp(u, v, sx);
527     return SkScalarInterp(a, b, sy);
528 }
529 
calculateTurbulenceValueForPoint(int channel,StitchData & stitchData,const SkPoint & point) const530 SkScalar SkPerlinNoiseShaderImpl::PerlinNoiseShaderContext::calculateTurbulenceValueForPoint(
531         int channel, StitchData& stitchData, const SkPoint& point) const {
532     const SkPerlinNoiseShaderImpl& perlinNoiseShader = static_cast<const SkPerlinNoiseShaderImpl&>(fShader);
533     if (perlinNoiseShader.fStitchTiles) {
534         // Set up TurbulenceInitial stitch values.
535         stitchData = fPaintingData.fStitchDataInit;
536     }
537     SkScalar turbulenceFunctionResult = 0;
538     SkPoint noiseVector(SkPoint::Make(point.x() * fPaintingData.fBaseFrequency.fX,
539                                       point.y() * fPaintingData.fBaseFrequency.fY));
540     SkScalar ratio = SK_Scalar1;
541     for (int octave = 0; octave < perlinNoiseShader.fNumOctaves; ++octave) {
542         SkScalar noise = noise2D(channel, stitchData, noiseVector);
543         SkScalar numer = (perlinNoiseShader.fType == kFractalNoise_Type) ?
544                             noise : SkScalarAbs(noise);
545         turbulenceFunctionResult += numer / ratio;
546         noiseVector.fX *= 2;
547         noiseVector.fY *= 2;
548         ratio *= 2;
549         if (perlinNoiseShader.fStitchTiles) {
550             // Update stitch values
551             stitchData = StitchData(SkIntToScalar(stitchData.fWidth)  * 2,
552                                     SkIntToScalar(stitchData.fHeight) * 2);
553         }
554     }
555 
556     // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
557     // by fractalNoise and (turbulenceFunctionResult) by turbulence.
558     if (perlinNoiseShader.fType == kFractalNoise_Type) {
559         turbulenceFunctionResult = SkScalarHalf(turbulenceFunctionResult + 1);
560     }
561 
562     if (channel == 3) { // Scale alpha by paint value
563         turbulenceFunctionResult *= SkIntToScalar(getPaintAlpha()) / 255;
564     }
565 
566     // Clamp result
567     return SkScalarPin(turbulenceFunctionResult, 0, SK_Scalar1);
568 }
569 
570 ////////////////////////////////////////////////////////////////////////////////////////////////////
571 // Improved Perlin Noise based on Java implementation found at http://mrl.nyu.edu/~perlin/noise/
fade(SkScalar t)572 static SkScalar fade(SkScalar t) {
573     return t * t * t * (t * (t * 6 - 15) + 10);
574 }
575 
lerp(SkScalar t,SkScalar a,SkScalar b)576 static SkScalar lerp(SkScalar t, SkScalar a, SkScalar b) {
577     return a + t * (b - a);
578 }
579 
grad(int hash,SkScalar x,SkScalar y,SkScalar z)580 static SkScalar grad(int hash, SkScalar x, SkScalar y, SkScalar z) {
581     int h = hash & 15;
582     SkScalar u = h < 8 ? x : y;
583     SkScalar v = h < 4 ? y : h == 12 || h == 14 ? x : z;
584     return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
585 }
586 
calculateImprovedNoiseValueForPoint(int channel,const SkPoint & point) const587 SkScalar SkPerlinNoiseShaderImpl::PerlinNoiseShaderContext::calculateImprovedNoiseValueForPoint(
588         int channel, const SkPoint& point) const {
589     const SkPerlinNoiseShaderImpl& perlinNoiseShader = static_cast<const SkPerlinNoiseShaderImpl&>(fShader);
590     SkScalar x = point.fX * perlinNoiseShader.fBaseFrequencyX;
591     SkScalar y = point.fY * perlinNoiseShader.fBaseFrequencyY;
592     // z offset between different channels, chosen arbitrarily
593     static const SkScalar CHANNEL_DELTA = 1000.0f;
594     SkScalar z = channel * CHANNEL_DELTA + perlinNoiseShader.fSeed;
595     SkScalar result = 0;
596     SkScalar ratio = SK_Scalar1;
597     for (int i = 0; i < perlinNoiseShader.fNumOctaves; i++) {
598         int X = SkScalarFloorToInt(x) & 255;
599         int Y = SkScalarFloorToInt(y) & 255;
600         int Z = SkScalarFloorToInt(z) & 255;
601         SkScalar px = x - SkScalarFloorToScalar(x);
602         SkScalar py = y - SkScalarFloorToScalar(y);
603         SkScalar pz = z - SkScalarFloorToScalar(z);
604         SkScalar u = fade(px);
605         SkScalar v = fade(py);
606         SkScalar w = fade(pz);
607         uint8_t* permutations = improved_noise_permutations;
608         int A  = permutations[X] + Y;
609         int AA = permutations[A] + Z;
610         int AB = permutations[A + 1] + Z;
611         int B  = permutations[X + 1] + Y;
612         int BA = permutations[B] + Z;
613         int BB = permutations[B + 1] + Z;
614         result += lerp(w, lerp(v, lerp(u, grad(permutations[AA    ], px    , py    , pz    ),
615                                           grad(permutations[BA    ], px - 1, py    , pz    )),
616                                   lerp(u, grad(permutations[AB    ], px    , py - 1, pz    ),
617                                           grad(permutations[BB    ], px - 1, py - 1, pz    ))),
618                           lerp(v, lerp(u, grad(permutations[AA + 1], px    , py    , pz - 1),
619                                           grad(permutations[BA + 1], px - 1, py    , pz - 1)),
620                                   lerp(u, grad(permutations[AB + 1], px    , py - 1, pz - 1),
621                                           grad(permutations[BB + 1], px - 1, py - 1, pz - 1)))) /
622                    ratio;
623         x *= 2;
624         y *= 2;
625         ratio *= 2;
626     }
627     result = SkScalarClampMax((result + 1.0f) / 2.0f, 1.0f);
628     return result;
629 }
630 ////////////////////////////////////////////////////////////////////////////////////////////////////
631 
shade(const SkPoint & point,StitchData & stitchData) const632 SkPMColor SkPerlinNoiseShaderImpl::PerlinNoiseShaderContext::shade(
633         const SkPoint& point, StitchData& stitchData) const {
634     const SkPerlinNoiseShaderImpl& perlinNoiseShader = static_cast<const SkPerlinNoiseShaderImpl&>(fShader);
635     SkPoint newPoint;
636     fMatrix.mapPoints(&newPoint, &point, 1);
637     newPoint.fX = SkScalarRoundToScalar(newPoint.fX);
638     newPoint.fY = SkScalarRoundToScalar(newPoint.fY);
639 
640     U8CPU rgba[4];
641     for (int channel = 3; channel >= 0; --channel) {
642         SkScalar value;
643         if (perlinNoiseShader.fType == kImprovedNoise_Type) {
644             value = calculateImprovedNoiseValueForPoint(channel, newPoint);
645         }
646         else {
647             value = calculateTurbulenceValueForPoint(channel, stitchData, newPoint);
648         }
649         rgba[channel] = SkScalarFloorToInt(255 * value);
650     }
651     return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]);
652 }
653 
654 #ifdef SK_ENABLE_LEGACY_SHADERCONTEXT
onMakeContext(const ContextRec & rec,SkArenaAlloc * alloc) const655 SkShaderBase::Context* SkPerlinNoiseShaderImpl::onMakeContext(const ContextRec& rec,
656                                                               SkArenaAlloc* alloc) const {
657     // should we pay attention to rec's device-colorspace?
658     return alloc->make<PerlinNoiseShaderContext>(*this, rec);
659 }
660 #endif
661 
total_matrix(const SkShaderBase::ContextRec & rec,const SkShaderBase & shader)662 static inline SkMatrix total_matrix(const SkShaderBase::ContextRec& rec,
663                                     const SkShaderBase& shader) {
664     SkMatrix matrix = SkMatrix::Concat(*rec.fMatrix, shader.getLocalMatrix());
665     if (rec.fLocalMatrix) {
666         matrix.preConcat(*rec.fLocalMatrix);
667     }
668 
669     return matrix;
670 }
671 
PerlinNoiseShaderContext(const SkPerlinNoiseShaderImpl & shader,const ContextRec & rec)672 SkPerlinNoiseShaderImpl::PerlinNoiseShaderContext::PerlinNoiseShaderContext(
673         const SkPerlinNoiseShaderImpl& shader, const ContextRec& rec)
674     : INHERITED(shader, rec)
675     , fMatrix(total_matrix(rec, shader)) // used for temp storage, adjusted below
676     , fPaintingData(shader.fTileSize, shader.fSeed, shader.fBaseFrequencyX,
677                     shader.fBaseFrequencyY, fMatrix)
678 {
679     // This (1,1) translation is due to WebKit's 1 based coordinates for the noise
680     // (as opposed to 0 based, usually). The same adjustment is in the setData() function.
681     fMatrix.setTranslate(-fMatrix.getTranslateX() + SK_Scalar1,
682                          -fMatrix.getTranslateY() + SK_Scalar1);
683 }
684 
shadeSpan(int x,int y,SkPMColor result[],int count)685 void SkPerlinNoiseShaderImpl::PerlinNoiseShaderContext::shadeSpan(
686         int x, int y, SkPMColor result[], int count) {
687     SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y));
688     StitchData stitchData;
689     for (int i = 0; i < count; ++i) {
690         result[i] = shade(point, stitchData);
691         point.fX += SK_Scalar1;
692     }
693 }
694 
695 /////////////////////////////////////////////////////////////////////
696 
697 #if SK_SUPPORT_GPU
698 
699 class GrGLPerlinNoise : public GrGLSLFragmentProcessor {
700 public:
701     void emitCode(EmitArgs&) override;
702 
703     static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder* b);
704 
705 protected:
706     void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
707 
708 private:
709     GrGLSLProgramDataManager::UniformHandle fStitchDataUni;
710     GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni;
711 
712     typedef GrGLSLFragmentProcessor INHERITED;
713 };
714 
715 /////////////////////////////////////////////////////////////////////
716 
717 class GrPerlinNoise2Effect : public GrFragmentProcessor {
718 public:
Make(SkPerlinNoiseShaderImpl::Type type,int numOctaves,bool stitchTiles,std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> paintingData,sk_sp<GrTextureProxy> permutationsProxy,sk_sp<GrTextureProxy> noiseProxy,const SkMatrix & matrix)719     static std::unique_ptr<GrFragmentProcessor> Make(
720             SkPerlinNoiseShaderImpl::Type type, int numOctaves, bool stitchTiles,
721             std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> paintingData,
722             sk_sp<GrTextureProxy> permutationsProxy, sk_sp<GrTextureProxy> noiseProxy,
723             const SkMatrix& matrix) {
724         return std::unique_ptr<GrFragmentProcessor>(new GrPerlinNoise2Effect(
725                 type, numOctaves, stitchTiles, std::move(paintingData),
726                 std::move(permutationsProxy), std::move(noiseProxy), matrix));
727     }
728 
name() const729     const char* name() const override { return "PerlinNoise"; }
730 
clone() const731     std::unique_ptr<GrFragmentProcessor> clone() const override {
732         return std::unique_ptr<GrFragmentProcessor>(new GrPerlinNoise2Effect(*this));
733     }
734 
stitchData() const735     const SkPerlinNoiseShaderImpl::StitchData& stitchData() const { return fPaintingData->fStitchDataInit; }
736 
type() const737     SkPerlinNoiseShaderImpl::Type type() const { return fType; }
stitchTiles() const738     bool stitchTiles() const { return fStitchTiles; }
baseFrequency() const739     const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; }
numOctaves() const740     int numOctaves() const { return fNumOctaves; }
matrix() const741     const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
742 
743 private:
onCreateGLSLInstance() const744     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
745         return new GrGLPerlinNoise;
746     }
747 
onGetGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const748     virtual void onGetGLSLProcessorKey(const GrShaderCaps& caps,
749                                        GrProcessorKeyBuilder* b) const override {
750         GrGLPerlinNoise::GenKey(*this, caps, b);
751     }
752 
onIsEqual(const GrFragmentProcessor & sBase) const753     bool onIsEqual(const GrFragmentProcessor& sBase) const override {
754         const GrPerlinNoise2Effect& s = sBase.cast<GrPerlinNoise2Effect>();
755         return fType == s.fType &&
756                fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency &&
757                fNumOctaves == s.fNumOctaves &&
758                fStitchTiles == s.fStitchTiles &&
759                fPaintingData->fStitchDataInit == s.fPaintingData->fStitchDataInit;
760     }
761 
GrPerlinNoise2Effect(SkPerlinNoiseShaderImpl::Type type,int numOctaves,bool stitchTiles,std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> paintingData,sk_sp<GrTextureProxy> permutationsProxy,sk_sp<GrTextureProxy> noiseProxy,const SkMatrix & matrix)762     GrPerlinNoise2Effect(SkPerlinNoiseShaderImpl::Type type, int numOctaves, bool stitchTiles,
763                          std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> paintingData,
764                          sk_sp<GrTextureProxy> permutationsProxy,
765                          sk_sp<GrTextureProxy> noiseProxy,
766                          const SkMatrix& matrix)
767             : INHERITED(kGrPerlinNoise2Effect_ClassID, kNone_OptimizationFlags)
768             , fType(type)
769             , fNumOctaves(numOctaves)
770             , fStitchTiles(stitchTiles)
771             , fPermutationsSampler(std::move(permutationsProxy))
772             , fNoiseSampler(std::move(noiseProxy))
773             , fPaintingData(std::move(paintingData)) {
774         this->setTextureSamplerCnt(2);
775         fCoordTransform = GrCoordTransform(matrix);
776         this->addCoordTransform(&fCoordTransform);
777     }
778 
GrPerlinNoise2Effect(const GrPerlinNoise2Effect & that)779     GrPerlinNoise2Effect(const GrPerlinNoise2Effect& that)
780             : INHERITED(kGrPerlinNoise2Effect_ClassID, kNone_OptimizationFlags)
781             , fType(that.fType)
782             , fCoordTransform(that.fCoordTransform)
783             , fNumOctaves(that.fNumOctaves)
784             , fStitchTiles(that.fStitchTiles)
785             , fPermutationsSampler(that.fPermutationsSampler)
786             , fNoiseSampler(that.fNoiseSampler)
787             , fPaintingData(new SkPerlinNoiseShaderImpl::PaintingData(*that.fPaintingData)) {
788         this->setTextureSamplerCnt(2);
789         this->addCoordTransform(&fCoordTransform);
790     }
791 
onTextureSampler(int i) const792     const TextureSampler& onTextureSampler(int i) const override {
793         return IthTextureSampler(i, fPermutationsSampler, fNoiseSampler);
794     }
795 
796     GR_DECLARE_FRAGMENT_PROCESSOR_TEST
797 
798     SkPerlinNoiseShaderImpl::Type       fType;
799     GrCoordTransform                    fCoordTransform;
800     int                                 fNumOctaves;
801     bool                                fStitchTiles;
802     TextureSampler                      fPermutationsSampler;
803     TextureSampler                      fNoiseSampler;
804     std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> fPaintingData;
805 
806     typedef GrFragmentProcessor INHERITED;
807 };
808 
809 /////////////////////////////////////////////////////////////////////
810 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrPerlinNoise2Effect);
811 
812 #if GR_TEST_UTILS
TestCreate(GrProcessorTestData * d)813 std::unique_ptr<GrFragmentProcessor> GrPerlinNoise2Effect::TestCreate(GrProcessorTestData* d) {
814     int      numOctaves = d->fRandom->nextRangeU(2, 10);
815     bool     stitchTiles = d->fRandom->nextBool();
816     SkScalar seed = SkIntToScalar(d->fRandom->nextU());
817     SkISize  tileSize = SkISize::Make(d->fRandom->nextRangeU(4, 4096),
818                                       d->fRandom->nextRangeU(4, 4096));
819     SkScalar baseFrequencyX = d->fRandom->nextRangeScalar(0.01f,
820                                                           0.99f);
821     SkScalar baseFrequencyY = d->fRandom->nextRangeScalar(0.01f,
822                                                           0.99f);
823 
824     sk_sp<SkShader> shader(d->fRandom->nextBool() ?
825         SkPerlinNoiseShader::MakeFractalNoise(baseFrequencyX, baseFrequencyY, numOctaves, seed,
826                                                stitchTiles ? &tileSize : nullptr) :
827         SkPerlinNoiseShader::MakeTurbulence(baseFrequencyX, baseFrequencyY, numOctaves, seed,
828                                              stitchTiles ? &tileSize : nullptr));
829 
830     GrTest::TestAsFPArgs asFPArgs(d);
831     return as_SB(shader)->asFragmentProcessor(asFPArgs.args());
832 }
833 #endif
834 
emitCode(EmitArgs & args)835 void GrGLPerlinNoise::emitCode(EmitArgs& args) {
836     const GrPerlinNoise2Effect& pne = args.fFp.cast<GrPerlinNoise2Effect>();
837 
838     GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
839     GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
840     SkString vCoords = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
841 
842     fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
843                                                    "baseFrequency");
844     const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);
845 
846     const char* stitchDataUni = nullptr;
847     if (pne.stitchTiles()) {
848         fStitchDataUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
849                                                     "stitchData");
850         stitchDataUni = uniformHandler->getUniformCStr(fStitchDataUni);
851     }
852 
853     // There are 4 lines, so the center of each line is 1/8, 3/8, 5/8 and 7/8
854     const char* chanCoordR  = "0.125";
855     const char* chanCoordG  = "0.375";
856     const char* chanCoordB  = "0.625";
857     const char* chanCoordA  = "0.875";
858     const char* chanCoord   = "chanCoord";
859     const char* stitchData  = "stitchData";
860     const char* ratio       = "ratio";
861     const char* noiseVec    = "noiseVec";
862     const char* noiseSmooth = "noiseSmooth";
863     const char* floorVal    = "floorVal";
864     const char* fractVal    = "fractVal";
865     const char* uv          = "uv";
866     const char* ab          = "ab";
867     const char* latticeIdx  = "latticeIdx";
868     const char* bcoords     = "bcoords";
869     const char* lattice     = "lattice";
870     const char* inc8bit     = "0.00390625";  // 1.0 / 256.0
871     // This is the math to convert the two 16bit integer packed into rgba 8 bit input into a
872     // [-1,1] vector and perform a dot product between that vector and the provided vector.
873     const char* dotLattice  = "dot(((%s.ga + %s.rb * half2(%s)) * half2(2.0) - half2(1.0)), %s);";
874 
875     // Add noise function
876     const GrShaderVar gPerlinNoiseArgs[] =  {
877         GrShaderVar(chanCoord, kHalf_GrSLType),
878         GrShaderVar(noiseVec, kHalf2_GrSLType)
879     };
880 
881     const GrShaderVar gPerlinNoiseStitchArgs[] =  {
882         GrShaderVar(chanCoord, kHalf_GrSLType),
883         GrShaderVar(noiseVec, kHalf2_GrSLType),
884         GrShaderVar(stitchData, kHalf2_GrSLType)
885     };
886 
887     SkString noiseCode;
888 
889     noiseCode.appendf("\thalf4 %s;\n", floorVal);
890     noiseCode.appendf("\t%s.xy = floor(%s);\n", floorVal, noiseVec);
891     noiseCode.appendf("\t%s.zw = %s.xy + half2(1.0);\n", floorVal, floorVal);
892     noiseCode.appendf("\thalf2 %s = fract(%s);\n", fractVal, noiseVec);
893 
894     // smooth curve : t * t * (3 - 2 * t)
895     noiseCode.appendf("\n\thalf2 %s = %s * %s * (half2(3.0) - half2(2.0) * %s);",
896         noiseSmooth, fractVal, fractVal, fractVal);
897 
898     // Adjust frequencies if we're stitching tiles
899     if (pne.stitchTiles()) {
900         noiseCode.appendf("\n\tif(%s.x >= %s.x) { %s.x -= %s.x; }",
901             floorVal, stitchData, floorVal, stitchData);
902         noiseCode.appendf("\n\tif(%s.y >= %s.y) { %s.y -= %s.y; }",
903             floorVal, stitchData, floorVal, stitchData);
904         noiseCode.appendf("\n\tif(%s.z >= %s.x) { %s.z -= %s.x; }",
905             floorVal, stitchData, floorVal, stitchData);
906         noiseCode.appendf("\n\tif(%s.w >= %s.y) { %s.w -= %s.y; }",
907             floorVal, stitchData, floorVal, stitchData);
908     }
909 
910     // Get texture coordinates and normalize
911     noiseCode.appendf("\n\t%s = fract(floor(mod(%s, 256.0)) / half4(256.0));\n",
912         floorVal, floorVal);
913 
914     // Get permutation for x
915     {
916         SkString xCoords("");
917         xCoords.appendf("half2(%s.x, 0.5)", floorVal);
918 
919         noiseCode.appendf("\n\thalf2 %s;\n\t%s.x = ", latticeIdx, latticeIdx);
920         fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(),
921                                          kHalf2_GrSLType);
922         noiseCode.append(".r;");
923     }
924 
925     // Get permutation for x + 1
926     {
927         SkString xCoords("");
928         xCoords.appendf("half2(%s.z, 0.5)", floorVal);
929 
930         noiseCode.appendf("\n\t%s.y = ", latticeIdx);
931         fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(),
932                                          kHalf2_GrSLType);
933         noiseCode.append(".r;");
934     }
935 
936 #if defined(SK_BUILD_FOR_ANDROID)
937     // Android rounding for Tegra devices, like, for example: Xoom (Tegra 2), Nexus 7 (Tegra 3).
938     // The issue is that colors aren't accurate enough on Tegra devices. For example, if an 8 bit
939     // value of 124 (or 0.486275 here) is entered, we can get a texture value of 123.513725
940     // (or 0.484368 here). The following rounding operation prevents these precision issues from
941     // affecting the result of the noise by making sure that we only have multiples of 1/255.
942     // (Note that 1/255 is about 0.003921569, which is the value used here).
943     noiseCode.appendf("\n\t%s = floor(%s * half2(255.0) + half2(0.5)) * half2(0.003921569);",
944                       latticeIdx, latticeIdx);
945 #endif
946 
947     // Get (x,y) coordinates with the permutated x
948     noiseCode.appendf("\n\thalf4 %s = fract(%s.xyxy + %s.yyww);", bcoords, latticeIdx, floorVal);
949 
950     noiseCode.appendf("\n\n\thalf2 %s;", uv);
951     // Compute u, at offset (0,0)
952     {
953         SkString latticeCoords("");
954         latticeCoords.appendf("half2(%s.x, %s)", bcoords, chanCoord);
955         noiseCode.appendf("\n\thalf4 %s = ", lattice);
956         fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
957                                          kHalf2_GrSLType);
958         noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
959         noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
960     }
961 
962     noiseCode.appendf("\n\t%s.x -= 1.0;", fractVal);
963     // Compute v, at offset (-1,0)
964     {
965         SkString latticeCoords("");
966         latticeCoords.appendf("half2(%s.y, %s)", bcoords, chanCoord);
967         noiseCode.append("\n\tlattice = ");
968         fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
969                                          kHalf2_GrSLType);
970         noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
971         noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
972     }
973 
974     // Compute 'a' as a linear interpolation of 'u' and 'v'
975     noiseCode.appendf("\n\thalf2 %s;", ab);
976     noiseCode.appendf("\n\t%s.x = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
977 
978     noiseCode.appendf("\n\t%s.y -= 1.0;", fractVal);
979     // Compute v, at offset (-1,-1)
980     {
981         SkString latticeCoords("");
982         latticeCoords.appendf("half2(%s.w, %s)", bcoords, chanCoord);
983         noiseCode.append("\n\tlattice = ");
984         fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
985                                          kHalf2_GrSLType);
986         noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
987         noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
988     }
989 
990     noiseCode.appendf("\n\t%s.x += 1.0;", fractVal);
991     // Compute u, at offset (0,-1)
992     {
993         SkString latticeCoords("");
994         latticeCoords.appendf("half2(%s.z, %s)", bcoords, chanCoord);
995         noiseCode.append("\n\tlattice = ");
996         fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
997                                          kHalf2_GrSLType);
998         noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
999         noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
1000     }
1001 
1002     // Compute 'b' as a linear interpolation of 'u' and 'v'
1003     noiseCode.appendf("\n\t%s.y = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
1004     // Compute the noise as a linear interpolation of 'a' and 'b'
1005     noiseCode.appendf("\n\treturn mix(%s.x, %s.y, %s.y);\n", ab, ab, noiseSmooth);
1006 
1007     SkString noiseFuncName;
1008     if (pne.stitchTiles()) {
1009         fragBuilder->emitFunction(kHalf_GrSLType,
1010                                   "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseStitchArgs),
1011                                   gPerlinNoiseStitchArgs, noiseCode.c_str(), &noiseFuncName);
1012     } else {
1013         fragBuilder->emitFunction(kHalf_GrSLType,
1014                                   "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseArgs),
1015                                   gPerlinNoiseArgs, noiseCode.c_str(), &noiseFuncName);
1016     }
1017 
1018     // There are rounding errors if the floor operation is not performed here
1019     fragBuilder->codeAppendf("\n\t\thalf2 %s = half2(floor(%s.xy) * %s);",
1020                              noiseVec, vCoords.c_str(), baseFrequencyUni);
1021 
1022     // Clear the color accumulator
1023     fragBuilder->codeAppendf("\n\t\t%s = half4(0.0);", args.fOutputColor);
1024 
1025     if (pne.stitchTiles()) {
1026         // Set up TurbulenceInitial stitch values.
1027         fragBuilder->codeAppendf("\n\t\thalf2 %s = %s;", stitchData, stitchDataUni);
1028     }
1029 
1030     fragBuilder->codeAppendf("\n\t\thalf %s = 1.0;", ratio);
1031 
1032     // Loop over all octaves
1033     fragBuilder->codeAppendf("for (int octave = 0; octave < %d; ++octave) {", pne.numOctaves());
1034 
1035     fragBuilder->codeAppendf("\n\t\t\t%s += ", args.fOutputColor);
1036     if (pne.type() != SkPerlinNoiseShaderImpl::kFractalNoise_Type) {
1037         fragBuilder->codeAppend("abs(");
1038     }
1039     if (pne.stitchTiles()) {
1040         fragBuilder->codeAppendf(
1041             "half4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s),"
1042                  "\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))",
1043             noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData,
1044             noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData,
1045             noiseFuncName.c_str(), chanCoordB, noiseVec, stitchData,
1046             noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData);
1047     } else {
1048         fragBuilder->codeAppendf(
1049             "half4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s),"
1050                  "\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))",
1051             noiseFuncName.c_str(), chanCoordR, noiseVec,
1052             noiseFuncName.c_str(), chanCoordG, noiseVec,
1053             noiseFuncName.c_str(), chanCoordB, noiseVec,
1054             noiseFuncName.c_str(), chanCoordA, noiseVec);
1055     }
1056     if (pne.type() != SkPerlinNoiseShaderImpl::kFractalNoise_Type) {
1057         fragBuilder->codeAppendf(")"); // end of "abs("
1058     }
1059     fragBuilder->codeAppendf(" * %s;", ratio);
1060 
1061     fragBuilder->codeAppendf("\n\t\t\t%s *= half2(2.0);", noiseVec);
1062     fragBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio);
1063 
1064     if (pne.stitchTiles()) {
1065         fragBuilder->codeAppendf("\n\t\t\t%s *= half2(2.0);", stitchData);
1066     }
1067     fragBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves
1068 
1069     if (pne.type() == SkPerlinNoiseShaderImpl::kFractalNoise_Type) {
1070         // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
1071         // by fractalNoise and (turbulenceFunctionResult) by turbulence.
1072         fragBuilder->codeAppendf("\n\t\t%s = %s * half4(0.5) + half4(0.5);",
1073                                args.fOutputColor,args.fOutputColor);
1074     }
1075 
1076     // Clamp values
1077     fragBuilder->codeAppendf("\n\t\t%s = saturate(%s);", args.fOutputColor, args.fOutputColor);
1078 
1079     // Pre-multiply the result
1080     fragBuilder->codeAppendf("\n\t\t%s = half4(%s.rgb * %s.aaa, %s.a);\n",
1081                              args.fOutputColor, args.fOutputColor,
1082                              args.fOutputColor, args.fOutputColor);
1083 }
1084 
GenKey(const GrProcessor & processor,const GrShaderCaps &,GrProcessorKeyBuilder * b)1085 void GrGLPerlinNoise::GenKey(const GrProcessor& processor, const GrShaderCaps&,
1086                              GrProcessorKeyBuilder* b) {
1087     const GrPerlinNoise2Effect& turbulence = processor.cast<GrPerlinNoise2Effect>();
1088 
1089     uint32_t key = turbulence.numOctaves();
1090 
1091     key = key << 3; // Make room for next 3 bits
1092 
1093     switch (turbulence.type()) {
1094         case SkPerlinNoiseShaderImpl::kFractalNoise_Type:
1095             key |= 0x1;
1096             break;
1097         case SkPerlinNoiseShaderImpl::kTurbulence_Type:
1098             key |= 0x2;
1099             break;
1100         default:
1101             // leave key at 0
1102             break;
1103     }
1104 
1105     if (turbulence.stitchTiles()) {
1106         key |= 0x4; // Flip the 3rd bit if tile stitching is on
1107     }
1108 
1109     b->add32(key);
1110 }
1111 
onSetData(const GrGLSLProgramDataManager & pdman,const GrFragmentProcessor & processor)1112 void GrGLPerlinNoise::onSetData(const GrGLSLProgramDataManager& pdman,
1113                                 const GrFragmentProcessor& processor) {
1114     INHERITED::onSetData(pdman, processor);
1115 
1116     const GrPerlinNoise2Effect& turbulence = processor.cast<GrPerlinNoise2Effect>();
1117 
1118     const SkVector& baseFrequency = turbulence.baseFrequency();
1119     pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
1120 
1121     if (turbulence.stitchTiles()) {
1122         const SkPerlinNoiseShaderImpl::StitchData& stitchData = turbulence.stitchData();
1123         pdman.set2f(fStitchDataUni, SkIntToScalar(stitchData.fWidth),
1124                                    SkIntToScalar(stitchData.fHeight));
1125     }
1126 }
1127 
1128 /////////////////////////////////////////////////////////////////////
1129 
1130 class GrGLImprovedPerlinNoise : public GrGLSLFragmentProcessor {
1131 public:
1132     void emitCode(EmitArgs&) override;
1133 
1134     static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*);
1135 
1136 protected:
1137     void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
1138 
1139 private:
1140     GrGLSLProgramDataManager::UniformHandle fZUni;
1141     GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni;
1142 
1143     typedef GrGLSLFragmentProcessor INHERITED;
1144 };
1145 
1146 /////////////////////////////////////////////////////////////////////
1147 
1148 class GrImprovedPerlinNoiseEffect : public GrFragmentProcessor {
1149 public:
Make(int octaves,SkScalar z,std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> paintingData,sk_sp<GrTextureProxy> permutationsProxy,sk_sp<GrTextureProxy> gradientProxy,const SkMatrix & matrix)1150     static std::unique_ptr<GrFragmentProcessor> Make(
1151             int octaves, SkScalar z,
1152             std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> paintingData,
1153             sk_sp<GrTextureProxy> permutationsProxy, sk_sp<GrTextureProxy> gradientProxy,
1154             const SkMatrix& matrix) {
1155         return std::unique_ptr<GrFragmentProcessor>(new GrImprovedPerlinNoiseEffect(
1156                 octaves, z, std::move(paintingData), std::move(permutationsProxy),
1157                 std::move(gradientProxy), matrix));
1158     }
1159 
name() const1160     const char* name() const override { return "ImprovedPerlinNoise"; }
1161 
clone() const1162     std::unique_ptr<GrFragmentProcessor> clone() const override {
1163         return std::unique_ptr<GrFragmentProcessor>(new GrImprovedPerlinNoiseEffect(*this));
1164     }
1165 
baseFrequency() const1166     const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; }
z() const1167     SkScalar z() const { return fZ; }
octaves() const1168     int octaves() const { return fOctaves; }
matrix() const1169     const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
1170 
1171 private:
onCreateGLSLInstance() const1172     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
1173         return new GrGLImprovedPerlinNoise;
1174     }
1175 
onGetGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const1176     void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
1177         GrGLImprovedPerlinNoise::GenKey(*this, caps, b);
1178     }
1179 
onIsEqual(const GrFragmentProcessor & sBase) const1180     bool onIsEqual(const GrFragmentProcessor& sBase) const override {
1181         const GrImprovedPerlinNoiseEffect& s = sBase.cast<GrImprovedPerlinNoiseEffect>();
1182         return fZ == fZ &&
1183                fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency;
1184     }
1185 
GrImprovedPerlinNoiseEffect(int octaves,SkScalar z,std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> paintingData,sk_sp<GrTextureProxy> permutationsProxy,sk_sp<GrTextureProxy> gradientProxy,const SkMatrix & matrix)1186     GrImprovedPerlinNoiseEffect(int octaves, SkScalar z,
1187                                 std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> paintingData,
1188                                 sk_sp<GrTextureProxy> permutationsProxy,
1189                                 sk_sp<GrTextureProxy> gradientProxy,
1190                                 const SkMatrix& matrix)
1191             : INHERITED(kGrImprovedPerlinNoiseEffect_ClassID, kNone_OptimizationFlags)
1192             , fOctaves(octaves)
1193             , fZ(z)
1194             , fPermutationsSampler(std::move(permutationsProxy))
1195             , fGradientSampler(std::move(gradientProxy))
1196             , fPaintingData(std::move(paintingData)) {
1197         this->setTextureSamplerCnt(2);
1198         fCoordTransform = GrCoordTransform(matrix);
1199         this->addCoordTransform(&fCoordTransform);
1200     }
1201 
GrImprovedPerlinNoiseEffect(const GrImprovedPerlinNoiseEffect & that)1202     GrImprovedPerlinNoiseEffect(const GrImprovedPerlinNoiseEffect& that)
1203             : INHERITED(kGrImprovedPerlinNoiseEffect_ClassID, kNone_OptimizationFlags)
1204             , fCoordTransform(that.fCoordTransform)
1205             , fOctaves(that.fOctaves)
1206             , fZ(that.fZ)
1207             , fPermutationsSampler(that.fPermutationsSampler)
1208             , fGradientSampler(that.fGradientSampler)
1209             , fPaintingData(new SkPerlinNoiseShaderImpl::PaintingData(*that.fPaintingData)) {
1210         this->setTextureSamplerCnt(2);
1211         this->addCoordTransform(&fCoordTransform);
1212     }
1213 
onTextureSampler(int i) const1214     const TextureSampler& onTextureSampler(int i) const override {
1215         return IthTextureSampler(i, fPermutationsSampler, fGradientSampler);
1216     }
1217 
1218     GR_DECLARE_FRAGMENT_PROCESSOR_TEST
1219 
1220     GrCoordTransform                    fCoordTransform;
1221     int                                 fOctaves;
1222     SkScalar                            fZ;
1223     TextureSampler                      fPermutationsSampler;
1224     TextureSampler                      fGradientSampler;
1225     std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> fPaintingData;
1226 
1227     typedef GrFragmentProcessor INHERITED;
1228 };
1229 
1230 /////////////////////////////////////////////////////////////////////
1231 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrImprovedPerlinNoiseEffect);
1232 
1233 #if GR_TEST_UTILS
TestCreate(GrProcessorTestData * d)1234 std::unique_ptr<GrFragmentProcessor> GrImprovedPerlinNoiseEffect::TestCreate(
1235         GrProcessorTestData* d) {
1236     SkScalar baseFrequencyX = d->fRandom->nextRangeScalar(0.01f,
1237                                                           0.99f);
1238     SkScalar baseFrequencyY = d->fRandom->nextRangeScalar(0.01f,
1239                                                           0.99f);
1240     int numOctaves = d->fRandom->nextRangeU(2, 10);
1241     SkScalar z = SkIntToScalar(d->fRandom->nextU());
1242 
1243     sk_sp<SkShader> shader(SkPerlinNoiseShader::MakeImprovedNoise(baseFrequencyX,
1244                                                                    baseFrequencyY,
1245                                                                    numOctaves,
1246                                                                    z));
1247 
1248     GrTest::TestAsFPArgs asFPArgs(d);
1249     return as_SB(shader)->asFragmentProcessor(asFPArgs.args());
1250 }
1251 #endif
1252 
emitCode(EmitArgs & args)1253 void GrGLImprovedPerlinNoise::emitCode(EmitArgs& args) {
1254     const GrImprovedPerlinNoiseEffect& pne = args.fFp.cast<GrImprovedPerlinNoiseEffect>();
1255     GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
1256     GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
1257     SkString vCoords = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
1258 
1259     fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
1260                                                    "baseFrequency");
1261     const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);
1262 
1263     fZUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "z");
1264     const char* zUni = uniformHandler->getUniformCStr(fZUni);
1265 
1266     // fade function
1267     const GrShaderVar fadeArgs[] =  {
1268         GrShaderVar("t", kHalf3_GrSLType)
1269     };
1270     SkString fadeFuncName;
1271     fragBuilder->emitFunction(kHalf3_GrSLType, "fade", SK_ARRAY_COUNT(fadeArgs),
1272                               fadeArgs,
1273                               "return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);",
1274                               &fadeFuncName);
1275 
1276     // perm function
1277     const GrShaderVar permArgs[] =  {
1278         GrShaderVar("x", kHalf_GrSLType)
1279     };
1280     SkString permFuncName;
1281     SkString permCode("return ");
1282     // FIXME even though I'm creating these textures with kRepeat_TileMode, they're clamped. Not
1283     // sure why. Using fract() (here and the next texture lookup) as a workaround.
1284     fragBuilder->appendTextureLookup(&permCode, args.fTexSamplers[0], "float2(fract(x / 256.0), 0.0)",
1285                                      kHalf2_GrSLType);
1286     permCode.append(".r * 255.0;");
1287     fragBuilder->emitFunction(kHalf_GrSLType, "perm", SK_ARRAY_COUNT(permArgs), permArgs,
1288                               permCode.c_str(), &permFuncName);
1289 
1290     // grad function
1291     const GrShaderVar gradArgs[] =  {
1292         GrShaderVar("x", kHalf_GrSLType),
1293         GrShaderVar("p", kHalf3_GrSLType)
1294     };
1295     SkString gradFuncName;
1296     SkString gradCode("return half(dot(");
1297     fragBuilder->appendTextureLookup(&gradCode, args.fTexSamplers[1], "float2(fract(x / 16.0), 0.0)",
1298                                      kHalf2_GrSLType);
1299     gradCode.append(".rgb * 255.0 - float3(1.0), p));");
1300     fragBuilder->emitFunction(kHalf_GrSLType, "grad", SK_ARRAY_COUNT(gradArgs), gradArgs,
1301                               gradCode.c_str(), &gradFuncName);
1302 
1303     // lerp function
1304     const GrShaderVar lerpArgs[] =  {
1305         GrShaderVar("a", kHalf_GrSLType),
1306         GrShaderVar("b", kHalf_GrSLType),
1307         GrShaderVar("w", kHalf_GrSLType)
1308     };
1309     SkString lerpFuncName;
1310     fragBuilder->emitFunction(kHalf_GrSLType, "lerp", SK_ARRAY_COUNT(lerpArgs), lerpArgs,
1311                               "return a + w * (b - a);", &lerpFuncName);
1312 
1313     // noise function
1314     const GrShaderVar noiseArgs[] =  {
1315         GrShaderVar("p", kHalf3_GrSLType),
1316     };
1317     SkString noiseFuncName;
1318     SkString noiseCode;
1319     noiseCode.append("half3 P = mod(floor(p), 256.0);");
1320     noiseCode.append("p -= floor(p);");
1321     noiseCode.appendf("half3 f = %s(p);", fadeFuncName.c_str());
1322     noiseCode.appendf("half A = %s(P.x) + P.y;", permFuncName.c_str());
1323     noiseCode.appendf("half AA = %s(A) + P.z;", permFuncName.c_str());
1324     noiseCode.appendf("half AB = %s(A + 1.0) + P.z;", permFuncName.c_str());
1325     noiseCode.appendf("half B =  %s(P.x + 1.0) + P.y;", permFuncName.c_str());
1326     noiseCode.appendf("half BA = %s(B) + P.z;", permFuncName.c_str());
1327     noiseCode.appendf("half BB = %s(B + 1.0) + P.z;", permFuncName.c_str());
1328     noiseCode.appendf("half result = %s(", lerpFuncName.c_str());
1329     noiseCode.appendf("%s(%s(%s(%s(AA), p),", lerpFuncName.c_str(), lerpFuncName.c_str(),
1330                       gradFuncName.c_str(), permFuncName.c_str());
1331     noiseCode.appendf("%s(%s(BA), p + half3(-1.0, 0.0, 0.0)), f.x),", gradFuncName.c_str(),
1332                       permFuncName.c_str());
1333     noiseCode.appendf("%s(%s(%s(AB), p + half3(0.0, -1.0, 0.0)),", lerpFuncName.c_str(),
1334                       gradFuncName.c_str(), permFuncName.c_str());
1335     noiseCode.appendf("%s(%s(BB), p + half3(-1.0, -1.0, 0.0)), f.x), f.y),",
1336                       gradFuncName.c_str(), permFuncName.c_str());
1337     noiseCode.appendf("%s(%s(%s(%s(AA + 1.0), p + half3(0.0, 0.0, -1.0)),",
1338                       lerpFuncName.c_str(), lerpFuncName.c_str(), gradFuncName.c_str(),
1339                       permFuncName.c_str());
1340     noiseCode.appendf("%s(%s(BA + 1.0), p + half3(-1.0, 0.0, -1.0)), f.x),",
1341                       gradFuncName.c_str(), permFuncName.c_str());
1342     noiseCode.appendf("%s(%s(%s(AB + 1.0), p + half3(0.0, -1.0, -1.0)),",
1343                       lerpFuncName.c_str(), gradFuncName.c_str(), permFuncName.c_str());
1344     noiseCode.appendf("%s(%s(BB + 1.0), p + half3(-1.0, -1.0, -1.0)), f.x), f.y), f.z);",
1345                       gradFuncName.c_str(), permFuncName.c_str());
1346     noiseCode.append("return result;");
1347     fragBuilder->emitFunction(kHalf_GrSLType, "noise", SK_ARRAY_COUNT(noiseArgs), noiseArgs,
1348                               noiseCode.c_str(), &noiseFuncName);
1349 
1350     // noiseOctaves function
1351     const GrShaderVar noiseOctavesArgs[] =  {
1352         GrShaderVar("p", kHalf3_GrSLType)
1353     };
1354     SkString noiseOctavesFuncName;
1355     SkString noiseOctavesCode;
1356     noiseOctavesCode.append("half result = 0.0;");
1357     noiseOctavesCode.append("half ratio = 1.0;");
1358     noiseOctavesCode.appendf("for (half i = 0.0; i < %d; i++) {", pne.octaves());
1359     noiseOctavesCode.appendf("result += %s(p) / ratio;", noiseFuncName.c_str());
1360     noiseOctavesCode.append("p *= 2.0;");
1361     noiseOctavesCode.append("ratio *= 2.0;");
1362     noiseOctavesCode.append("}");
1363     noiseOctavesCode.append("return (result + 1.0) / 2.0;");
1364     fragBuilder->emitFunction(kHalf_GrSLType, "noiseOctaves", SK_ARRAY_COUNT(noiseOctavesArgs),
1365                               noiseOctavesArgs, noiseOctavesCode.c_str(), &noiseOctavesFuncName);
1366 
1367     fragBuilder->codeAppendf("half2 coords = half2(%s * %s);", vCoords.c_str(), baseFrequencyUni);
1368     fragBuilder->codeAppendf("half r = %s(half3(coords, %s));", noiseOctavesFuncName.c_str(),
1369                              zUni);
1370     fragBuilder->codeAppendf("half g = %s(half3(coords, %s + 0000.0));",
1371                              noiseOctavesFuncName.c_str(), zUni);
1372     fragBuilder->codeAppendf("half b = %s(half3(coords, %s + 0000.0));",
1373                              noiseOctavesFuncName.c_str(), zUni);
1374     fragBuilder->codeAppendf("half a = %s(half3(coords, %s + 0000.0));",
1375                              noiseOctavesFuncName.c_str(), zUni);
1376     fragBuilder->codeAppendf("%s = half4(r, g, b, a);", args.fOutputColor);
1377 
1378     // Clamp values
1379     fragBuilder->codeAppendf("%s = saturate(%s);", args.fOutputColor, args.fOutputColor);
1380 
1381     // Pre-multiply the result
1382     fragBuilder->codeAppendf("\n\t\t%s = half4(%s.rgb * %s.aaa, %s.a);\n",
1383                              args.fOutputColor, args.fOutputColor,
1384                              args.fOutputColor, args.fOutputColor);
1385 }
1386 
GenKey(const GrProcessor & processor,const GrShaderCaps &,GrProcessorKeyBuilder * b)1387 void GrGLImprovedPerlinNoise::GenKey(const GrProcessor& processor, const GrShaderCaps&,
1388                                      GrProcessorKeyBuilder* b) {
1389     const GrImprovedPerlinNoiseEffect& pne = processor.cast<GrImprovedPerlinNoiseEffect>();
1390     b->add32(pne.octaves());
1391 }
1392 
onSetData(const GrGLSLProgramDataManager & pdman,const GrFragmentProcessor & processor)1393 void GrGLImprovedPerlinNoise::onSetData(const GrGLSLProgramDataManager& pdman,
1394                                         const GrFragmentProcessor& processor) {
1395     INHERITED::onSetData(pdman, processor);
1396 
1397     const GrImprovedPerlinNoiseEffect& noise = processor.cast<GrImprovedPerlinNoiseEffect>();
1398 
1399     const SkVector& baseFrequency = noise.baseFrequency();
1400     pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
1401 
1402     pdman.set1f(fZUni, noise.z());
1403 }
1404 
1405 /////////////////////////////////////////////////////////////////////
asFragmentProcessor(const GrFPArgs & args) const1406 std::unique_ptr<GrFragmentProcessor> SkPerlinNoiseShaderImpl::asFragmentProcessor(
1407         const GrFPArgs& args) const {
1408     SkASSERT(args.fContext);
1409 
1410     const auto localMatrix = this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix);
1411     const auto paintMatrix = SkMatrix::Concat(*args.fViewMatrix, *localMatrix);
1412 
1413     // Either we don't stitch tiles, either we have a valid tile size
1414     SkASSERT(!fStitchTiles || !fTileSize.isEmpty());
1415 
1416     std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> paintingData =
1417         skstd::make_unique<SkPerlinNoiseShaderImpl::PaintingData>(fTileSize,
1418                                                                   fSeed,
1419                                                                   fBaseFrequencyX,
1420                                                                   fBaseFrequencyY,
1421                                                                   paintMatrix);
1422 
1423     SkMatrix m = *args.fViewMatrix;
1424     m.setTranslateX(-localMatrix->getTranslateX() + SK_Scalar1);
1425     m.setTranslateY(-localMatrix->getTranslateY() + SK_Scalar1);
1426 
1427     auto proxyProvider = args.fContext->priv().proxyProvider();
1428     if (fType == kImprovedNoise_Type) {
1429         // Need to assert that the textures we'll create are power of 2 so a copy isn't needed.
1430         // We also know that we will not be using mipmaps. If things things weren't true we should
1431         // go through GrBitmapTextureMaker to handle needed copies.
1432         const sk_sp<SkImage> permutationsImage = paintingData->getImprovedPermutationsImage();
1433         SkASSERT(SkIsPow2(permutationsImage->width()) && SkIsPow2(permutationsImage->height()));
1434         sk_sp<GrTextureProxy> permutationsTexture(
1435                 GrMakeCachedImageProxy(proxyProvider, std::move(permutationsImage)));
1436 
1437         const sk_sp<SkImage> gradientImage = paintingData->getGradientImage();
1438         SkASSERT(SkIsPow2(gradientImage->width()) && SkIsPow2(gradientImage->height()));
1439         sk_sp<GrTextureProxy> gradientTexture(
1440                 GrMakeCachedImageProxy(proxyProvider, std::move(gradientImage)));
1441         return GrImprovedPerlinNoiseEffect::Make(fNumOctaves, fSeed, std::move(paintingData),
1442                                                  std::move(permutationsTexture),
1443                                                  std::move(gradientTexture), m);
1444     }
1445 
1446     if (0 == fNumOctaves) {
1447         if (kFractalNoise_Type == fType) {
1448             // Extract the incoming alpha and emit rgba = (a/4, a/4, a/4, a/2)
1449             // TODO: Either treat the output of this shader as sRGB or allow client to specify a
1450             // color space of the noise. Either way, this case (and the GLSL) need to convert to
1451             // the destination.
1452             auto inner =
1453                     GrConstColorProcessor::Make(SkPMColor4f::FromBytes_RGBA(0x80404040),
1454                                                 GrConstColorProcessor::InputMode::kModulateRGBA);
1455             return GrFragmentProcessor::MulChildByInputAlpha(std::move(inner));
1456         }
1457         // Emit zero.
1458         return GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT,
1459                                            GrConstColorProcessor::InputMode::kIgnore);
1460     }
1461 
1462     // Need to assert that the textures we'll create are power of 2 so that now copy is needed. We
1463     // also know that we will not be using mipmaps. If things things weren't true we should go
1464     // through GrBitmapTextureMaker to handle needed copies.
1465     const sk_sp<SkImage> permutationsImage = paintingData->getPermutationsImage();
1466     SkASSERT(SkIsPow2(permutationsImage->width()) && SkIsPow2(permutationsImage->height()));
1467     sk_sp<GrTextureProxy> permutationsProxy = GrMakeCachedImageProxy(proxyProvider,
1468                                                                      std::move(permutationsImage));
1469 
1470     const sk_sp<SkImage> noiseImage = paintingData->getNoiseImage();
1471     SkASSERT(SkIsPow2(noiseImage->width()) && SkIsPow2(noiseImage->height()));
1472     sk_sp<GrTextureProxy> noiseProxy = GrMakeCachedImageProxy(proxyProvider,
1473                                                               std::move(noiseImage));
1474 
1475     if (permutationsProxy && noiseProxy) {
1476         auto inner = GrPerlinNoise2Effect::Make(fType,
1477                                                 fNumOctaves,
1478                                                 fStitchTiles,
1479                                                 std::move(paintingData),
1480                                                 std::move(permutationsProxy),
1481                                                 std::move(noiseProxy),
1482                                                 m);
1483         return GrFragmentProcessor::MulChildByInputAlpha(std::move(inner));
1484     }
1485     return nullptr;
1486 }
1487 
1488 #endif
1489 
1490 ///////////////////////////////////////////////////////////////////////////////////////////////////
1491 
valid_input(SkScalar baseX,SkScalar baseY,int numOctaves,const SkISize * tileSize,SkScalar seed)1492 static bool valid_input(SkScalar baseX, SkScalar baseY, int numOctaves, const SkISize* tileSize,
1493                         SkScalar seed) {
1494     if (!(baseX >= 0 && baseY >= 0)) {
1495         return false;
1496     }
1497     if (!(numOctaves >= 0 && numOctaves <= SkPerlinNoiseShaderImpl::kMaxOctaves)) {
1498         return false;
1499     }
1500     if (tileSize && !(tileSize->width() >= 0 && tileSize->height() >= 0)) {
1501         return false;
1502     }
1503     if (!SkScalarIsFinite(seed)) {
1504         return false;
1505     }
1506     return true;
1507 }
1508 
MakeFractalNoise(SkScalar baseFrequencyX,SkScalar baseFrequencyY,int numOctaves,SkScalar seed,const SkISize * tileSize)1509 sk_sp<SkShader> SkPerlinNoiseShader::MakeFractalNoise(SkScalar baseFrequencyX,
1510                                                       SkScalar baseFrequencyY,
1511                                                       int numOctaves, SkScalar seed,
1512                                                       const SkISize* tileSize) {
1513     if (!valid_input(baseFrequencyX, baseFrequencyY, numOctaves, tileSize, seed)) {
1514         return nullptr;
1515     }
1516     return sk_sp<SkShader>(new SkPerlinNoiseShaderImpl(SkPerlinNoiseShaderImpl::kFractalNoise_Type,
1517                                                  baseFrequencyX, baseFrequencyY, numOctaves, seed,
1518                                                  tileSize));
1519 }
1520 
MakeTurbulence(SkScalar baseFrequencyX,SkScalar baseFrequencyY,int numOctaves,SkScalar seed,const SkISize * tileSize)1521 sk_sp<SkShader> SkPerlinNoiseShader::MakeTurbulence(SkScalar baseFrequencyX,
1522                                                     SkScalar baseFrequencyY,
1523                                                     int numOctaves, SkScalar seed,
1524                                                     const SkISize* tileSize) {
1525     if (!valid_input(baseFrequencyX, baseFrequencyY, numOctaves, tileSize, seed)) {
1526         return nullptr;
1527     }
1528     return sk_sp<SkShader>(new SkPerlinNoiseShaderImpl(SkPerlinNoiseShaderImpl::kTurbulence_Type,
1529                                                  baseFrequencyX, baseFrequencyY, numOctaves, seed,
1530                                                  tileSize));
1531 }
1532 
MakeImprovedNoise(SkScalar baseFrequencyX,SkScalar baseFrequencyY,int numOctaves,SkScalar z)1533 sk_sp<SkShader> SkPerlinNoiseShader::MakeImprovedNoise(SkScalar baseFrequencyX,
1534                                                        SkScalar baseFrequencyY,
1535                                                        int numOctaves, SkScalar z) {
1536     if (!valid_input(baseFrequencyX, baseFrequencyY, numOctaves, nullptr, z)) {
1537         return nullptr;
1538     }
1539     return sk_sp<SkShader>(new SkPerlinNoiseShaderImpl(SkPerlinNoiseShaderImpl::kImprovedNoise_Type,
1540                                                  baseFrequencyX, baseFrequencyY, numOctaves, z,
1541                                                  nullptr));
1542 }
1543 
RegisterFlattenables()1544 void SkPerlinNoiseShader::RegisterFlattenables() {
1545     SK_REGISTER_FLATTENABLE(SkPerlinNoiseShaderImpl);
1546 }
1547