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