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 "SkPerlinNoiseShader.h"
9
10 #include "SkArenaAlloc.h"
11 #include "SkColorFilter.h"
12 #include "SkMakeUnique.h"
13 #include "SkReadBuffer.h"
14 #include "SkShader.h"
15 #include "SkString.h"
16 #include "SkUnPreMultiply.h"
17 #include "SkWriteBuffer.h"
18
19 #if SK_SUPPORT_GPU
20 #include "GrContext.h"
21 #include "GrContextPriv.h"
22 #include "GrCoordTransform.h"
23 #include "SkGr.h"
24 #include "effects/GrConstColorProcessor.h"
25 #include "glsl/GrGLSLFragmentProcessor.h"
26 #include "glsl/GrGLSLFragmentShaderBuilder.h"
27 #include "glsl/GrGLSLProgramDataManager.h"
28 #include "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 return alloc->make<PerlinNoiseShaderContext>(*this, rec);
658 }
659 #endif
660
total_matrix(const SkShaderBase::ContextRec & rec,const SkShaderBase & shader)661 static 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
PerlinNoiseShaderContext(const SkPerlinNoiseShaderImpl & shader,const ContextRec & rec)671 SkPerlinNoiseShaderImpl::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
shadeSpan(int x,int y,SkPMColor result[],int count)684 void 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
698 class GrGLPerlinNoise : public GrGLSLFragmentProcessor {
699 public:
700 void emitCode(EmitArgs&) override;
701
702 static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder* b);
703
704 protected:
705 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
706
707 private:
708 GrGLSLProgramDataManager::UniformHandle fStitchDataUni;
709 GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni;
710
711 typedef GrGLSLFragmentProcessor INHERITED;
712 };
713
714 /////////////////////////////////////////////////////////////////////
715
716 class GrPerlinNoise2Effect : public GrFragmentProcessor {
717 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)718 static std::unique_ptr<GrFragmentProcessor> Make(
719 SkPerlinNoiseShaderImpl::Type type, int numOctaves, bool stitchTiles,
720 std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> paintingData,
721 sk_sp<GrTextureProxy> permutationsProxy, sk_sp<GrTextureProxy> noiseProxy,
722 const SkMatrix& matrix) {
723 return std::unique_ptr<GrFragmentProcessor>(new GrPerlinNoise2Effect(
724 type, numOctaves, stitchTiles, std::move(paintingData),
725 std::move(permutationsProxy), std::move(noiseProxy), matrix));
726 }
727
name() const728 const char* name() const override { return "PerlinNoise"; }
729
clone() const730 std::unique_ptr<GrFragmentProcessor> clone() const override {
731 return std::unique_ptr<GrFragmentProcessor>(new GrPerlinNoise2Effect(*this));
732 }
733
stitchData() const734 const SkPerlinNoiseShaderImpl::StitchData& stitchData() const { return fPaintingData->fStitchDataInit; }
735
type() const736 SkPerlinNoiseShaderImpl::Type type() const { return fType; }
stitchTiles() const737 bool stitchTiles() const { return fStitchTiles; }
baseFrequency() const738 const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; }
numOctaves() const739 int numOctaves() const { return fNumOctaves; }
matrix() const740 const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
741
742 private:
onCreateGLSLInstance() const743 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
744 return new GrGLPerlinNoise;
745 }
746
onGetGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const747 virtual void onGetGLSLProcessorKey(const GrShaderCaps& caps,
748 GrProcessorKeyBuilder* b) const override {
749 GrGLPerlinNoise::GenKey(*this, caps, b);
750 }
751
onIsEqual(const GrFragmentProcessor & sBase) const752 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
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)761 GrPerlinNoise2Effect(SkPerlinNoiseShaderImpl::Type type, int numOctaves, bool stitchTiles,
762 std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> paintingData,
763 sk_sp<GrTextureProxy> permutationsProxy,
764 sk_sp<GrTextureProxy> noiseProxy,
765 const SkMatrix& matrix)
766 : INHERITED(kGrPerlinNoise2Effect_ClassID, kNone_OptimizationFlags)
767 , fType(type)
768 , fNumOctaves(numOctaves)
769 , fStitchTiles(stitchTiles)
770 , fPermutationsSampler(std::move(permutationsProxy))
771 , fNoiseSampler(std::move(noiseProxy))
772 , fPaintingData(std::move(paintingData)) {
773 this->setTextureSamplerCnt(2);
774 fCoordTransform = GrCoordTransform(matrix);
775 this->addCoordTransform(&fCoordTransform);
776 }
777
GrPerlinNoise2Effect(const GrPerlinNoise2Effect & that)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
onTextureSampler(int i) const791 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 /////////////////////////////////////////////////////////////////////
809 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrPerlinNoise2Effect);
810
811 #if GR_TEST_UTILS
TestCreate(GrProcessorTestData * d)812 std::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
emitCode(EmitArgs & args)834 void 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]);
840
841 fBaseFrequencyUni = uniformHandler->addUniform(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(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 kHalf2_GrSLType);
921 noiseCode.append(".r;");
922 }
923
924 // Get permutation for x + 1
925 {
926 SkString xCoords("");
927 xCoords.appendf("half2(%s.z, 0.5)", floorVal);
928
929 noiseCode.appendf("\n\t%s.y = ", latticeIdx);
930 fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(),
931 kHalf2_GrSLType);
932 noiseCode.append(".r;");
933 }
934
935 #if defined(SK_BUILD_FOR_ANDROID)
936 // Android rounding for Tegra devices, like, for example: Xoom (Tegra 2), Nexus 7 (Tegra 3).
937 // The issue is that colors aren't accurate enough on Tegra devices. For example, if an 8 bit
938 // value of 124 (or 0.486275 here) is entered, we can get a texture value of 123.513725
939 // (or 0.484368 here). The following rounding operation prevents these precision issues from
940 // affecting the result of the noise by making sure that we only have multiples of 1/255.
941 // (Note that 1/255 is about 0.003921569, which is the value used here).
942 noiseCode.appendf("\n\t%s = floor(%s * half2(255.0) + half2(0.5)) * half2(0.003921569);",
943 latticeIdx, latticeIdx);
944 #endif
945
946 // Get (x,y) coordinates with the permutated x
947 noiseCode.appendf("\n\thalf4 %s = fract(%s.xyxy + %s.yyww);", bcoords, latticeIdx, floorVal);
948
949 noiseCode.appendf("\n\n\thalf2 %s;", uv);
950 // Compute u, at offset (0,0)
951 {
952 SkString latticeCoords("");
953 latticeCoords.appendf("half2(%s.x, %s)", bcoords, chanCoord);
954 noiseCode.appendf("\n\thalf4 %s = ", lattice);
955 fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
956 kHalf2_GrSLType);
957 noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
958 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
959 }
960
961 noiseCode.appendf("\n\t%s.x -= 1.0;", fractVal);
962 // Compute v, at offset (-1,0)
963 {
964 SkString latticeCoords("");
965 latticeCoords.appendf("half2(%s.y, %s)", bcoords, chanCoord);
966 noiseCode.append("\n\tlattice = ");
967 fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
968 kHalf2_GrSLType);
969 noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
970 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
971 }
972
973 // Compute 'a' as a linear interpolation of 'u' and 'v'
974 noiseCode.appendf("\n\thalf2 %s;", ab);
975 noiseCode.appendf("\n\t%s.x = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
976
977 noiseCode.appendf("\n\t%s.y -= 1.0;", fractVal);
978 // Compute v, at offset (-1,-1)
979 {
980 SkString latticeCoords("");
981 latticeCoords.appendf("half2(%s.w, %s)", bcoords, chanCoord);
982 noiseCode.append("\n\tlattice = ");
983 fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
984 kHalf2_GrSLType);
985 noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
986 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
987 }
988
989 noiseCode.appendf("\n\t%s.x += 1.0;", fractVal);
990 // Compute u, at offset (0,-1)
991 {
992 SkString latticeCoords("");
993 latticeCoords.appendf("half2(%s.z, %s)", bcoords, chanCoord);
994 noiseCode.append("\n\tlattice = ");
995 fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
996 kHalf2_GrSLType);
997 noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
998 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
999 }
1000
1001 // Compute 'b' as a linear interpolation of 'u' and 'v'
1002 noiseCode.appendf("\n\t%s.y = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
1003 // Compute the noise as a linear interpolation of 'a' and 'b'
1004 noiseCode.appendf("\n\treturn mix(%s.x, %s.y, %s.y);\n", ab, ab, noiseSmooth);
1005
1006 SkString noiseFuncName;
1007 if (pne.stitchTiles()) {
1008 fragBuilder->emitFunction(kHalf_GrSLType,
1009 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseStitchArgs),
1010 gPerlinNoiseStitchArgs, noiseCode.c_str(), &noiseFuncName);
1011 } else {
1012 fragBuilder->emitFunction(kHalf_GrSLType,
1013 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseArgs),
1014 gPerlinNoiseArgs, noiseCode.c_str(), &noiseFuncName);
1015 }
1016
1017 // There are rounding errors if the floor operation is not performed here
1018 fragBuilder->codeAppendf("\n\t\thalf2 %s = floor(%s.xy) * %s;",
1019 noiseVec, vCoords.c_str(), baseFrequencyUni);
1020
1021 // Clear the color accumulator
1022 fragBuilder->codeAppendf("\n\t\t%s = half4(0.0);", args.fOutputColor);
1023
1024 if (pne.stitchTiles()) {
1025 // Set up TurbulenceInitial stitch values.
1026 fragBuilder->codeAppendf("\n\t\thalf2 %s = %s;", stitchData, stitchDataUni);
1027 }
1028
1029 fragBuilder->codeAppendf("\n\t\thalf %s = 1.0;", ratio);
1030
1031 // Loop over all octaves
1032 fragBuilder->codeAppendf("for (int octave = 0; octave < %d; ++octave) {", pne.numOctaves());
1033
1034 fragBuilder->codeAppendf("\n\t\t\t%s += ", args.fOutputColor);
1035 if (pne.type() != SkPerlinNoiseShaderImpl::kFractalNoise_Type) {
1036 fragBuilder->codeAppend("abs(");
1037 }
1038 if (pne.stitchTiles()) {
1039 fragBuilder->codeAppendf(
1040 "half4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s),"
1041 "\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))",
1042 noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData,
1043 noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData,
1044 noiseFuncName.c_str(), chanCoordB, noiseVec, stitchData,
1045 noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData);
1046 } else {
1047 fragBuilder->codeAppendf(
1048 "half4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s),"
1049 "\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))",
1050 noiseFuncName.c_str(), chanCoordR, noiseVec,
1051 noiseFuncName.c_str(), chanCoordG, noiseVec,
1052 noiseFuncName.c_str(), chanCoordB, noiseVec,
1053 noiseFuncName.c_str(), chanCoordA, noiseVec);
1054 }
1055 if (pne.type() != SkPerlinNoiseShaderImpl::kFractalNoise_Type) {
1056 fragBuilder->codeAppendf(")"); // end of "abs("
1057 }
1058 fragBuilder->codeAppendf(" * %s;", ratio);
1059
1060 fragBuilder->codeAppendf("\n\t\t\t%s *= half2(2.0);", noiseVec);
1061 fragBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio);
1062
1063 if (pne.stitchTiles()) {
1064 fragBuilder->codeAppendf("\n\t\t\t%s *= half2(2.0);", stitchData);
1065 }
1066 fragBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves
1067
1068 if (pne.type() == SkPerlinNoiseShaderImpl::kFractalNoise_Type) {
1069 // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
1070 // by fractalNoise and (turbulenceFunctionResult) by turbulence.
1071 fragBuilder->codeAppendf("\n\t\t%s = %s * half4(0.5) + half4(0.5);",
1072 args.fOutputColor,args.fOutputColor);
1073 }
1074
1075 // Clamp values
1076 fragBuilder->codeAppendf("\n\t\t%s = saturate(%s);", args.fOutputColor, args.fOutputColor);
1077
1078 // Pre-multiply the result
1079 fragBuilder->codeAppendf("\n\t\t%s = half4(%s.rgb * %s.aaa, %s.a);\n",
1080 args.fOutputColor, args.fOutputColor,
1081 args.fOutputColor, args.fOutputColor);
1082 }
1083
GenKey(const GrProcessor & processor,const GrShaderCaps &,GrProcessorKeyBuilder * b)1084 void GrGLPerlinNoise::GenKey(const GrProcessor& processor, const GrShaderCaps&,
1085 GrProcessorKeyBuilder* b) {
1086 const GrPerlinNoise2Effect& turbulence = processor.cast<GrPerlinNoise2Effect>();
1087
1088 uint32_t key = turbulence.numOctaves();
1089
1090 key = key << 3; // Make room for next 3 bits
1091
1092 switch (turbulence.type()) {
1093 case SkPerlinNoiseShaderImpl::kFractalNoise_Type:
1094 key |= 0x1;
1095 break;
1096 case SkPerlinNoiseShaderImpl::kTurbulence_Type:
1097 key |= 0x2;
1098 break;
1099 default:
1100 // leave key at 0
1101 break;
1102 }
1103
1104 if (turbulence.stitchTiles()) {
1105 key |= 0x4; // Flip the 3rd bit if tile stitching is on
1106 }
1107
1108 b->add32(key);
1109 }
1110
onSetData(const GrGLSLProgramDataManager & pdman,const GrFragmentProcessor & processor)1111 void GrGLPerlinNoise::onSetData(const GrGLSLProgramDataManager& pdman,
1112 const GrFragmentProcessor& processor) {
1113 INHERITED::onSetData(pdman, processor);
1114
1115 const GrPerlinNoise2Effect& turbulence = processor.cast<GrPerlinNoise2Effect>();
1116
1117 const SkVector& baseFrequency = turbulence.baseFrequency();
1118 pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
1119
1120 if (turbulence.stitchTiles()) {
1121 const SkPerlinNoiseShaderImpl::StitchData& stitchData = turbulence.stitchData();
1122 pdman.set2f(fStitchDataUni, SkIntToScalar(stitchData.fWidth),
1123 SkIntToScalar(stitchData.fHeight));
1124 }
1125 }
1126
1127 /////////////////////////////////////////////////////////////////////
1128
1129 class GrGLImprovedPerlinNoise : public GrGLSLFragmentProcessor {
1130 public:
1131 void emitCode(EmitArgs&) override;
1132
1133 static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*);
1134
1135 protected:
1136 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
1137
1138 private:
1139 GrGLSLProgramDataManager::UniformHandle fZUni;
1140 GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni;
1141
1142 typedef GrGLSLFragmentProcessor INHERITED;
1143 };
1144
1145 /////////////////////////////////////////////////////////////////////
1146
1147 class GrImprovedPerlinNoiseEffect : public GrFragmentProcessor {
1148 public:
Make(int octaves,SkScalar z,std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> paintingData,sk_sp<GrTextureProxy> permutationsProxy,sk_sp<GrTextureProxy> gradientProxy,const SkMatrix & matrix)1149 static std::unique_ptr<GrFragmentProcessor> Make(
1150 int octaves, SkScalar z,
1151 std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> paintingData,
1152 sk_sp<GrTextureProxy> permutationsProxy, sk_sp<GrTextureProxy> gradientProxy,
1153 const SkMatrix& matrix) {
1154 return std::unique_ptr<GrFragmentProcessor>(new GrImprovedPerlinNoiseEffect(
1155 octaves, z, std::move(paintingData), std::move(permutationsProxy),
1156 std::move(gradientProxy), matrix));
1157 }
1158
name() const1159 const char* name() const override { return "ImprovedPerlinNoise"; }
1160
clone() const1161 std::unique_ptr<GrFragmentProcessor> clone() const override {
1162 return std::unique_ptr<GrFragmentProcessor>(new GrImprovedPerlinNoiseEffect(*this));
1163 }
1164
baseFrequency() const1165 const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; }
z() const1166 SkScalar z() const { return fZ; }
octaves() const1167 int octaves() const { return fOctaves; }
matrix() const1168 const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
1169
1170 private:
onCreateGLSLInstance() const1171 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
1172 return new GrGLImprovedPerlinNoise;
1173 }
1174
onGetGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const1175 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
1176 GrGLImprovedPerlinNoise::GenKey(*this, caps, b);
1177 }
1178
onIsEqual(const GrFragmentProcessor & sBase) const1179 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
1180 const GrImprovedPerlinNoiseEffect& s = sBase.cast<GrImprovedPerlinNoiseEffect>();
1181 return fZ == fZ &&
1182 fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency;
1183 }
1184
GrImprovedPerlinNoiseEffect(int octaves,SkScalar z,std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> paintingData,sk_sp<GrTextureProxy> permutationsProxy,sk_sp<GrTextureProxy> gradientProxy,const SkMatrix & matrix)1185 GrImprovedPerlinNoiseEffect(int octaves, SkScalar z,
1186 std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> paintingData,
1187 sk_sp<GrTextureProxy> permutationsProxy,
1188 sk_sp<GrTextureProxy> gradientProxy,
1189 const SkMatrix& matrix)
1190 : INHERITED(kGrImprovedPerlinNoiseEffect_ClassID, kNone_OptimizationFlags)
1191 , fOctaves(octaves)
1192 , fZ(z)
1193 , fPermutationsSampler(std::move(permutationsProxy))
1194 , fGradientSampler(std::move(gradientProxy))
1195 , fPaintingData(std::move(paintingData)) {
1196 this->setTextureSamplerCnt(2);
1197 fCoordTransform = GrCoordTransform(matrix);
1198 this->addCoordTransform(&fCoordTransform);
1199 }
1200
GrImprovedPerlinNoiseEffect(const GrImprovedPerlinNoiseEffect & that)1201 GrImprovedPerlinNoiseEffect(const GrImprovedPerlinNoiseEffect& that)
1202 : INHERITED(kGrImprovedPerlinNoiseEffect_ClassID, kNone_OptimizationFlags)
1203 , fCoordTransform(that.fCoordTransform)
1204 , fOctaves(that.fOctaves)
1205 , fZ(that.fZ)
1206 , fPermutationsSampler(that.fPermutationsSampler)
1207 , fGradientSampler(that.fGradientSampler)
1208 , fPaintingData(new SkPerlinNoiseShaderImpl::PaintingData(*that.fPaintingData)) {
1209 this->setTextureSamplerCnt(2);
1210 this->addCoordTransform(&fCoordTransform);
1211 }
1212
onTextureSampler(int i) const1213 const TextureSampler& onTextureSampler(int i) const override {
1214 return IthTextureSampler(i, fPermutationsSampler, fGradientSampler);
1215 }
1216
1217 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
1218
1219 GrCoordTransform fCoordTransform;
1220 int fOctaves;
1221 SkScalar fZ;
1222 TextureSampler fPermutationsSampler;
1223 TextureSampler fGradientSampler;
1224 std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> fPaintingData;
1225
1226 typedef GrFragmentProcessor INHERITED;
1227 };
1228
1229 /////////////////////////////////////////////////////////////////////
1230 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrImprovedPerlinNoiseEffect);
1231
1232 #if GR_TEST_UTILS
TestCreate(GrProcessorTestData * d)1233 std::unique_ptr<GrFragmentProcessor> GrImprovedPerlinNoiseEffect::TestCreate(
1234 GrProcessorTestData* d) {
1235 SkScalar baseFrequencyX = d->fRandom->nextRangeScalar(0.01f,
1236 0.99f);
1237 SkScalar baseFrequencyY = d->fRandom->nextRangeScalar(0.01f,
1238 0.99f);
1239 int numOctaves = d->fRandom->nextRangeU(2, 10);
1240 SkScalar z = SkIntToScalar(d->fRandom->nextU());
1241
1242 sk_sp<SkShader> shader(SkPerlinNoiseShader::MakeImprovedNoise(baseFrequencyX,
1243 baseFrequencyY,
1244 numOctaves,
1245 z));
1246
1247 GrTest::TestAsFPArgs asFPArgs(d);
1248 return as_SB(shader)->asFragmentProcessor(asFPArgs.args());
1249 }
1250 #endif
1251
emitCode(EmitArgs & args)1252 void GrGLImprovedPerlinNoise::emitCode(EmitArgs& args) {
1253 const GrImprovedPerlinNoiseEffect& pne = args.fFp.cast<GrImprovedPerlinNoiseEffect>();
1254 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
1255 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
1256 SkString vCoords = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
1257
1258 fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
1259 "baseFrequency");
1260 const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);
1261
1262 fZUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "z");
1263 const char* zUni = uniformHandler->getUniformCStr(fZUni);
1264
1265 // fade function
1266 const GrShaderVar fadeArgs[] = {
1267 GrShaderVar("t", kHalf3_GrSLType)
1268 };
1269 SkString fadeFuncName;
1270 fragBuilder->emitFunction(kHalf3_GrSLType, "fade", SK_ARRAY_COUNT(fadeArgs),
1271 fadeArgs,
1272 "return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);",
1273 &fadeFuncName);
1274
1275 // perm function
1276 const GrShaderVar permArgs[] = {
1277 GrShaderVar("x", kHalf_GrSLType)
1278 };
1279 SkString permFuncName;
1280 SkString permCode("return ");
1281 // FIXME even though I'm creating these textures with kRepeat_TileMode, they're clamped. Not
1282 // sure why. Using fract() (here and the next texture lookup) as a workaround.
1283 fragBuilder->appendTextureLookup(&permCode, args.fTexSamplers[0], "float2(fract(x / 256.0), 0.0)",
1284 kHalf2_GrSLType);
1285 permCode.append(".r * 255.0;");
1286 fragBuilder->emitFunction(kHalf_GrSLType, "perm", SK_ARRAY_COUNT(permArgs), permArgs,
1287 permCode.c_str(), &permFuncName);
1288
1289 // grad function
1290 const GrShaderVar gradArgs[] = {
1291 GrShaderVar("x", kHalf_GrSLType),
1292 GrShaderVar("p", kHalf3_GrSLType)
1293 };
1294 SkString gradFuncName;
1295 SkString gradCode("return dot(");
1296 fragBuilder->appendTextureLookup(&gradCode, args.fTexSamplers[1], "float2(fract(x / 16.0), 0.0)",
1297 kHalf2_GrSLType);
1298 gradCode.append(".rgb * 255.0 - float3(1.0), p);");
1299 fragBuilder->emitFunction(kHalf_GrSLType, "grad", SK_ARRAY_COUNT(gradArgs), gradArgs,
1300 gradCode.c_str(), &gradFuncName);
1301
1302 // lerp function
1303 const GrShaderVar lerpArgs[] = {
1304 GrShaderVar("a", kHalf_GrSLType),
1305 GrShaderVar("b", kHalf_GrSLType),
1306 GrShaderVar("w", kHalf_GrSLType)
1307 };
1308 SkString lerpFuncName;
1309 fragBuilder->emitFunction(kHalf_GrSLType, "lerp", SK_ARRAY_COUNT(lerpArgs), lerpArgs,
1310 "return a + w * (b - a);", &lerpFuncName);
1311
1312 // noise function
1313 const GrShaderVar noiseArgs[] = {
1314 GrShaderVar("p", kHalf3_GrSLType),
1315 };
1316 SkString noiseFuncName;
1317 SkString noiseCode;
1318 noiseCode.append("half3 P = mod(floor(p), 256.0);");
1319 noiseCode.append("p -= floor(p);");
1320 noiseCode.appendf("half3 f = %s(p);", fadeFuncName.c_str());
1321 noiseCode.appendf("half A = %s(P.x) + P.y;", permFuncName.c_str());
1322 noiseCode.appendf("half AA = %s(A) + P.z;", permFuncName.c_str());
1323 noiseCode.appendf("half AB = %s(A + 1.0) + P.z;", permFuncName.c_str());
1324 noiseCode.appendf("half B = %s(P.x + 1.0) + P.y;", permFuncName.c_str());
1325 noiseCode.appendf("half BA = %s(B) + P.z;", permFuncName.c_str());
1326 noiseCode.appendf("half BB = %s(B + 1.0) + P.z;", permFuncName.c_str());
1327 noiseCode.appendf("half result = %s(", lerpFuncName.c_str());
1328 noiseCode.appendf("%s(%s(%s(%s(AA), p),", lerpFuncName.c_str(), lerpFuncName.c_str(),
1329 gradFuncName.c_str(), permFuncName.c_str());
1330 noiseCode.appendf("%s(%s(BA), p + half3(-1.0, 0.0, 0.0)), f.x),", gradFuncName.c_str(),
1331 permFuncName.c_str());
1332 noiseCode.appendf("%s(%s(%s(AB), p + half3(0.0, -1.0, 0.0)),", lerpFuncName.c_str(),
1333 gradFuncName.c_str(), permFuncName.c_str());
1334 noiseCode.appendf("%s(%s(BB), p + half3(-1.0, -1.0, 0.0)), f.x), f.y),",
1335 gradFuncName.c_str(), permFuncName.c_str());
1336 noiseCode.appendf("%s(%s(%s(%s(AA + 1.0), p + half3(0.0, 0.0, -1.0)),",
1337 lerpFuncName.c_str(), lerpFuncName.c_str(), gradFuncName.c_str(),
1338 permFuncName.c_str());
1339 noiseCode.appendf("%s(%s(BA + 1.0), p + half3(-1.0, 0.0, -1.0)), f.x),",
1340 gradFuncName.c_str(), permFuncName.c_str());
1341 noiseCode.appendf("%s(%s(%s(AB + 1.0), p + half3(0.0, -1.0, -1.0)),",
1342 lerpFuncName.c_str(), gradFuncName.c_str(), permFuncName.c_str());
1343 noiseCode.appendf("%s(%s(BB + 1.0), p + half3(-1.0, -1.0, -1.0)), f.x), f.y), f.z);",
1344 gradFuncName.c_str(), permFuncName.c_str());
1345 noiseCode.append("return result;");
1346 fragBuilder->emitFunction(kHalf_GrSLType, "noise", SK_ARRAY_COUNT(noiseArgs), noiseArgs,
1347 noiseCode.c_str(), &noiseFuncName);
1348
1349 // noiseOctaves function
1350 const GrShaderVar noiseOctavesArgs[] = {
1351 GrShaderVar("p", kHalf3_GrSLType)
1352 };
1353 SkString noiseOctavesFuncName;
1354 SkString noiseOctavesCode;
1355 noiseOctavesCode.append("half result = 0.0;");
1356 noiseOctavesCode.append("half ratio = 1.0;");
1357 noiseOctavesCode.appendf("for (half i = 0.0; i < %d; i++) {", pne.octaves());
1358 noiseOctavesCode.appendf("result += %s(p) / ratio;", noiseFuncName.c_str());
1359 noiseOctavesCode.append("p *= 2.0;");
1360 noiseOctavesCode.append("ratio *= 2.0;");
1361 noiseOctavesCode.append("}");
1362 noiseOctavesCode.append("return (result + 1.0) / 2.0;");
1363 fragBuilder->emitFunction(kHalf_GrSLType, "noiseOctaves", SK_ARRAY_COUNT(noiseOctavesArgs),
1364 noiseOctavesArgs, noiseOctavesCode.c_str(), &noiseOctavesFuncName);
1365
1366 fragBuilder->codeAppendf("half2 coords = %s * %s;", vCoords.c_str(), baseFrequencyUni);
1367 fragBuilder->codeAppendf("half r = %s(half3(coords, %s));", noiseOctavesFuncName.c_str(),
1368 zUni);
1369 fragBuilder->codeAppendf("half g = %s(half3(coords, %s + 0000.0));",
1370 noiseOctavesFuncName.c_str(), zUni);
1371 fragBuilder->codeAppendf("half b = %s(half3(coords, %s + 0000.0));",
1372 noiseOctavesFuncName.c_str(), zUni);
1373 fragBuilder->codeAppendf("half a = %s(half3(coords, %s + 0000.0));",
1374 noiseOctavesFuncName.c_str(), zUni);
1375 fragBuilder->codeAppendf("%s = half4(r, g, b, a);", args.fOutputColor);
1376
1377 // Clamp values
1378 fragBuilder->codeAppendf("%s = saturate(%s);", args.fOutputColor, args.fOutputColor);
1379
1380 // Pre-multiply the result
1381 fragBuilder->codeAppendf("\n\t\t%s = half4(%s.rgb * %s.aaa, %s.a);\n",
1382 args.fOutputColor, args.fOutputColor,
1383 args.fOutputColor, args.fOutputColor);
1384 }
1385
GenKey(const GrProcessor & processor,const GrShaderCaps &,GrProcessorKeyBuilder * b)1386 void GrGLImprovedPerlinNoise::GenKey(const GrProcessor& processor, const GrShaderCaps&,
1387 GrProcessorKeyBuilder* b) {
1388 const GrImprovedPerlinNoiseEffect& pne = processor.cast<GrImprovedPerlinNoiseEffect>();
1389 b->add32(pne.octaves());
1390 }
1391
onSetData(const GrGLSLProgramDataManager & pdman,const GrFragmentProcessor & processor)1392 void GrGLImprovedPerlinNoise::onSetData(const GrGLSLProgramDataManager& pdman,
1393 const GrFragmentProcessor& processor) {
1394 INHERITED::onSetData(pdman, processor);
1395
1396 const GrImprovedPerlinNoiseEffect& noise = processor.cast<GrImprovedPerlinNoiseEffect>();
1397
1398 const SkVector& baseFrequency = noise.baseFrequency();
1399 pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
1400
1401 pdman.set1f(fZUni, noise.z());
1402 }
1403
1404 /////////////////////////////////////////////////////////////////////
asFragmentProcessor(const GrFPArgs & args) const1405 std::unique_ptr<GrFragmentProcessor> SkPerlinNoiseShaderImpl::asFragmentProcessor(
1406 const GrFPArgs& args) const {
1407 SkASSERT(args.fContext);
1408
1409 const auto localMatrix = this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix);
1410 const auto paintMatrix = SkMatrix::Concat(*args.fViewMatrix, *localMatrix);
1411
1412 // Either we don't stitch tiles, either we have a valid tile size
1413 SkASSERT(!fStitchTiles || !fTileSize.isEmpty());
1414
1415 std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> paintingData =
1416 skstd::make_unique<SkPerlinNoiseShaderImpl::PaintingData>(fTileSize,
1417 fSeed,
1418 fBaseFrequencyX,
1419 fBaseFrequencyY,
1420 paintMatrix);
1421
1422 SkMatrix m = *args.fViewMatrix;
1423 m.setTranslateX(-localMatrix->getTranslateX() + SK_Scalar1);
1424 m.setTranslateY(-localMatrix->getTranslateY() + SK_Scalar1);
1425
1426 auto proxyProvider = args.fContext->contextPriv().proxyProvider();
1427 if (fType == kImprovedNoise_Type) {
1428 // Need to assert that the textures we'll create are power of 2 so a copy isn't needed.
1429 // We also know that we will not be using mipmaps. If things things weren't true we should
1430 // go through GrBitmapTextureMaker to handle needed copies.
1431 const sk_sp<SkImage> permutationsImage = paintingData->getImprovedPermutationsImage();
1432 SkASSERT(SkIsPow2(permutationsImage->width()) && SkIsPow2(permutationsImage->height()));
1433 sk_sp<GrTextureProxy> permutationsTexture(
1434 GrMakeCachedImageProxy(proxyProvider, std::move(permutationsImage)));
1435
1436 const sk_sp<SkImage> gradientImage = paintingData->getGradientImage();
1437 SkASSERT(SkIsPow2(gradientImage->width()) && SkIsPow2(gradientImage->height()));
1438 sk_sp<GrTextureProxy> gradientTexture(
1439 GrMakeCachedImageProxy(proxyProvider, std::move(gradientImage)));
1440 return GrImprovedPerlinNoiseEffect::Make(fNumOctaves, fSeed, std::move(paintingData),
1441 std::move(permutationsTexture),
1442 std::move(gradientTexture), m);
1443 }
1444
1445 if (0 == fNumOctaves) {
1446 if (kFractalNoise_Type == fType) {
1447 // Extract the incoming alpha and emit rgba = (a/4, a/4, a/4, a/2)
1448 // TODO: Either treat the output of this shader as sRGB or allow client to specify a
1449 // color space of the noise. Either way, this case (and the GLSL) need to convert to
1450 // the destination.
1451 auto inner =
1452 GrConstColorProcessor::Make(SkPMColor4f::FromBytes_RGBA(0x80404040),
1453 GrConstColorProcessor::InputMode::kModulateRGBA);
1454 return GrFragmentProcessor::MulChildByInputAlpha(std::move(inner));
1455 }
1456 // Emit zero.
1457 return GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT,
1458 GrConstColorProcessor::InputMode::kIgnore);
1459 }
1460
1461 // Need to assert that the textures we'll create are power of 2 so that now copy is needed. We
1462 // also know that we will not be using mipmaps. If things things weren't true we should go
1463 // through GrBitmapTextureMaker to handle needed copies.
1464 const sk_sp<SkImage> permutationsImage = paintingData->getPermutationsImage();
1465 SkASSERT(SkIsPow2(permutationsImage->width()) && SkIsPow2(permutationsImage->height()));
1466 sk_sp<GrTextureProxy> permutationsProxy = GrMakeCachedImageProxy(proxyProvider,
1467 std::move(permutationsImage));
1468
1469 const sk_sp<SkImage> noiseImage = paintingData->getNoiseImage();
1470 SkASSERT(SkIsPow2(noiseImage->width()) && SkIsPow2(noiseImage->height()));
1471 sk_sp<GrTextureProxy> noiseProxy = GrMakeCachedImageProxy(proxyProvider,
1472 std::move(noiseImage));
1473
1474 if (permutationsProxy && noiseProxy) {
1475 auto inner = GrPerlinNoise2Effect::Make(fType,
1476 fNumOctaves,
1477 fStitchTiles,
1478 std::move(paintingData),
1479 std::move(permutationsProxy),
1480 std::move(noiseProxy),
1481 m);
1482 return GrFragmentProcessor::MulChildByInputAlpha(std::move(inner));
1483 }
1484 return nullptr;
1485 }
1486
1487 #endif
1488
1489 ///////////////////////////////////////////////////////////////////////////////////////////////////
1490
valid_input(SkScalar baseX,SkScalar baseY,int numOctaves,const SkISize * tileSize,SkScalar seed)1491 static bool valid_input(SkScalar baseX, SkScalar baseY, int numOctaves, const SkISize* tileSize,
1492 SkScalar seed) {
1493 if (!(baseX >= 0 && baseY >= 0)) {
1494 return false;
1495 }
1496 if (!(numOctaves >= 0 && numOctaves <= SkPerlinNoiseShaderImpl::kMaxOctaves)) {
1497 return false;
1498 }
1499 if (tileSize && !(tileSize->width() >= 0 && tileSize->height() >= 0)) {
1500 return false;
1501 }
1502 if (!SkScalarIsFinite(seed)) {
1503 return false;
1504 }
1505 return true;
1506 }
1507
MakeFractalNoise(SkScalar baseFrequencyX,SkScalar baseFrequencyY,int numOctaves,SkScalar seed,const SkISize * tileSize)1508 sk_sp<SkShader> SkPerlinNoiseShader::MakeFractalNoise(SkScalar baseFrequencyX,
1509 SkScalar baseFrequencyY,
1510 int numOctaves, SkScalar seed,
1511 const SkISize* tileSize) {
1512 if (!valid_input(baseFrequencyX, baseFrequencyY, numOctaves, tileSize, seed)) {
1513 return nullptr;
1514 }
1515 return sk_sp<SkShader>(new SkPerlinNoiseShaderImpl(SkPerlinNoiseShaderImpl::kFractalNoise_Type,
1516 baseFrequencyX, baseFrequencyY, numOctaves, seed,
1517 tileSize));
1518 }
1519
MakeTurbulence(SkScalar baseFrequencyX,SkScalar baseFrequencyY,int numOctaves,SkScalar seed,const SkISize * tileSize)1520 sk_sp<SkShader> SkPerlinNoiseShader::MakeTurbulence(SkScalar baseFrequencyX,
1521 SkScalar baseFrequencyY,
1522 int numOctaves, SkScalar seed,
1523 const SkISize* tileSize) {
1524 if (!valid_input(baseFrequencyX, baseFrequencyY, numOctaves, tileSize, seed)) {
1525 return nullptr;
1526 }
1527 return sk_sp<SkShader>(new SkPerlinNoiseShaderImpl(SkPerlinNoiseShaderImpl::kTurbulence_Type,
1528 baseFrequencyX, baseFrequencyY, numOctaves, seed,
1529 tileSize));
1530 }
1531
MakeImprovedNoise(SkScalar baseFrequencyX,SkScalar baseFrequencyY,int numOctaves,SkScalar z)1532 sk_sp<SkShader> SkPerlinNoiseShader::MakeImprovedNoise(SkScalar baseFrequencyX,
1533 SkScalar baseFrequencyY,
1534 int numOctaves, SkScalar z) {
1535 if (!valid_input(baseFrequencyX, baseFrequencyY, numOctaves, nullptr, z)) {
1536 return nullptr;
1537 }
1538 return sk_sp<SkShader>(new SkPerlinNoiseShaderImpl(SkPerlinNoiseShaderImpl::kImprovedNoise_Type,
1539 baseFrequencyX, baseFrequencyY, numOctaves, z,
1540 nullptr));
1541 }
1542
RegisterFlattenables()1543 void SkPerlinNoiseShader::RegisterFlattenables() {
1544 SK_REGISTER_FLATTENABLE(SkPerlinNoiseShaderImpl);
1545 }
1546