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