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