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