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