blob: 83599d950d8c21c05465256d1f4f64dc523df099 [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"
25#include "glsl/GrGLSLProgramBuilder.h"
ethannicholas417011c2015-11-09 06:35:12 -080026#include "glsl/GrGLSLProgramDataManager.h"
27#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
606void SkPerlinNoiseShader2::PerlinNoiseShaderContext::shadeSpan16(
607 int x, int y, uint16_t result[], int count) {
608 SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y));
609 StitchData stitchData;
610 DITHER_565_SCAN(y);
611 for (int i = 0; i < count; ++i) {
612 unsigned dither = DITHER_VALUE(x);
613 result[i] = SkDitherRGB32To565(shade(point, stitchData), dither);
614 DITHER_INC_X(x);
615 point.fX += SK_Scalar1;
616 }
617}
618
619/////////////////////////////////////////////////////////////////////
620
621#if SK_SUPPORT_GPU
622
egdaniel64c47282015-11-13 06:54:19 -0800623class GrGLPerlinNoise2 : public GrGLSLFragmentProcessor {
ethannicholas417011c2015-11-09 06:35:12 -0800624public:
625 GrGLPerlinNoise2(const GrProcessor&);
626 virtual ~GrGLPerlinNoise2() {}
627
628 virtual void emitCode(EmitArgs&) override;
629
630 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder* b);
631
632protected:
633 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
634
635private:
636
637 GrGLSLProgramDataManager::UniformHandle fStitchDataUni;
638 SkPerlinNoiseShader2::Type fType;
639 bool fStitchTiles;
640 int fNumOctaves;
641 GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni;
642
643private:
egdaniel64c47282015-11-13 06:54:19 -0800644 typedef GrGLSLFragmentProcessor INHERITED;
ethannicholas417011c2015-11-09 06:35:12 -0800645};
646
647/////////////////////////////////////////////////////////////////////
648
649class GrPerlinNoise2Effect : public GrFragmentProcessor {
650public:
651 static GrFragmentProcessor* Create(SkPerlinNoiseShader2::Type type,
652 int numOctaves, bool stitchTiles,
653 SkPerlinNoiseShader2::PaintingData* paintingData,
654 GrTexture* permutationsTexture, GrTexture* noiseTexture,
655 const SkMatrix& matrix) {
656 return new GrPerlinNoise2Effect(type, numOctaves, stitchTiles, paintingData,
657 permutationsTexture, noiseTexture, matrix);
658 }
659
660 virtual ~GrPerlinNoise2Effect() { delete fPaintingData; }
661
662 const char* name() const override { return "PerlinNoise"; }
663
664 const SkPerlinNoiseShader2::StitchData& stitchData() const { return fPaintingData->fStitchDataInit; }
665
666 SkPerlinNoiseShader2::Type type() const { return fType; }
667 bool stitchTiles() const { return fStitchTiles; }
668 const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; }
669 int numOctaves() const { return fNumOctaves; }
670 const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
671
672private:
egdaniel57d3b032015-11-13 11:57:27 -0800673 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
ethannicholas417011c2015-11-09 06:35:12 -0800674 return new GrGLPerlinNoise2(*this);
675 }
676
egdaniel57d3b032015-11-13 11:57:27 -0800677 virtual void onGetGLSLProcessorKey(const GrGLSLCaps& caps,
678 GrProcessorKeyBuilder* b) const override {
ethannicholas417011c2015-11-09 06:35:12 -0800679 GrGLPerlinNoise2::GenKey(*this, caps, b);
680 }
681
682 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
683 const GrPerlinNoise2Effect& s = sBase.cast<GrPerlinNoise2Effect>();
684 return fType == s.fType &&
685 fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency &&
686 fNumOctaves == s.fNumOctaves &&
687 fStitchTiles == s.fStitchTiles &&
688 fPaintingData->fStitchDataInit == s.fPaintingData->fStitchDataInit;
689 }
690
691 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
692 inout->setToUnknown(GrInvariantOutput::kWillNot_ReadInput);
693 }
694
695 GrPerlinNoise2Effect(SkPerlinNoiseShader2::Type type,
696 int numOctaves, bool stitchTiles,
697 SkPerlinNoiseShader2::PaintingData* paintingData,
698 GrTexture* permutationsTexture, GrTexture* noiseTexture,
699 const SkMatrix& matrix)
700 : fType(type)
701 , fNumOctaves(numOctaves)
702 , fStitchTiles(stitchTiles)
703 , fPermutationsAccess(permutationsTexture)
704 , fNoiseAccess(noiseTexture)
705 , fPaintingData(paintingData) {
706 this->initClassID<GrPerlinNoise2Effect>();
707 this->addTextureAccess(&fPermutationsAccess);
708 this->addTextureAccess(&fNoiseAccess);
709 fCoordTransform.reset(kLocal_GrCoordSet, matrix);
710 this->addCoordTransform(&fCoordTransform);
711 }
712
713 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
714
715 SkPerlinNoiseShader2::Type fType;
716 GrCoordTransform fCoordTransform;
717 int fNumOctaves;
718 bool fStitchTiles;
719 GrTextureAccess fPermutationsAccess;
720 GrTextureAccess fNoiseAccess;
721 SkPerlinNoiseShader2::PaintingData *fPaintingData;
722
723private:
724 typedef GrFragmentProcessor INHERITED;
725};
726
727/////////////////////////////////////////////////////////////////////
728GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrPerlinNoise2Effect);
729
730const GrFragmentProcessor* GrPerlinNoise2Effect::TestCreate(GrProcessorTestData* d) {
731 int numOctaves = d->fRandom->nextRangeU(2, 10);
732 bool stitchTiles = d->fRandom->nextBool();
733 SkScalar seed = SkIntToScalar(d->fRandom->nextU());
734 SkISize tileSize = SkISize::Make(d->fRandom->nextRangeU(4, 4096),
735 d->fRandom->nextRangeU(4, 4096));
736 SkScalar baseFrequencyX = d->fRandom->nextRangeScalar(0.01f,
737 0.99f);
738 SkScalar baseFrequencyY = d->fRandom->nextRangeScalar(0.01f,
739 0.99f);
740
741 SkAutoTUnref<SkShader> shader(d->fRandom->nextBool() ?
742 SkPerlinNoiseShader2::CreateFractalNoise(baseFrequencyX, baseFrequencyY, numOctaves, seed,
743 stitchTiles ? &tileSize : nullptr) :
744 SkPerlinNoiseShader2::CreateTurbulence(baseFrequencyX, baseFrequencyY, numOctaves, seed,
745 stitchTiles ? &tileSize : nullptr));
746
747 GrPaint grPaint;
748 return shader->asFragmentProcessor(d->fContext,
749 GrTest::TestMatrix(d->fRandom), nullptr,
750 kNone_SkFilterQuality);
751}
752
753GrGLPerlinNoise2::GrGLPerlinNoise2(const GrProcessor& processor)
754 : fType(processor.cast<GrPerlinNoise2Effect>().type())
755 , fStitchTiles(processor.cast<GrPerlinNoise2Effect>().stitchTiles())
756 , fNumOctaves(processor.cast<GrPerlinNoise2Effect>().numOctaves()) {
757}
758
759void GrGLPerlinNoise2::emitCode(EmitArgs& args) {
egdaniel4ca2e602015-11-18 08:01:26 -0800760 GrGLSLFragmentBuilder* fsBuilder = args.fFragBuilder;
ethannicholas417011c2015-11-09 06:35:12 -0800761 SkString vCoords = fsBuilder->ensureFSCoords2D(args.fCoords, 0);
762
egdaniel2d721d32015-11-11 13:06:05 -0800763 fBaseFrequencyUni = args.fBuilder->addUniform(GrGLSLProgramBuilder::kFragment_Visibility,
ethannicholas417011c2015-11-09 06:35:12 -0800764 kVec2f_GrSLType, kDefault_GrSLPrecision,
765 "baseFrequency");
766 const char* baseFrequencyUni = args.fBuilder->getUniformCStr(fBaseFrequencyUni);
767
768 const char* stitchDataUni = nullptr;
769 if (fStitchTiles) {
egdaniel2d721d32015-11-11 13:06:05 -0800770 fStitchDataUni = args.fBuilder->addUniform(GrGLSLProgramBuilder::kFragment_Visibility,
ethannicholas417011c2015-11-09 06:35:12 -0800771 kVec2f_GrSLType, kDefault_GrSLPrecision,
772 "stitchData");
773 stitchDataUni = args.fBuilder->getUniformCStr(fStitchDataUni);
774 }
775
776 // There are 4 lines, so the center of each line is 1/8, 3/8, 5/8 and 7/8
777 const char* chanCoordR = "0.125";
778 const char* chanCoordG = "0.375";
779 const char* chanCoordB = "0.625";
780 const char* chanCoordA = "0.875";
781 const char* chanCoord = "chanCoord";
782 const char* stitchData = "stitchData";
783 const char* ratio = "ratio";
784 const char* noiseVec = "noiseVec";
785 const char* noiseSmooth = "noiseSmooth";
786 const char* floorVal = "floorVal";
787 const char* fractVal = "fractVal";
788 const char* uv = "uv";
789 const char* ab = "ab";
790 const char* latticeIdx = "latticeIdx";
791 const char* bcoords = "bcoords";
792 const char* lattice = "lattice";
793 const char* inc8bit = "0.00390625"; // 1.0 / 256.0
794 // This is the math to convert the two 16bit integer packed into rgba 8 bit input into a
795 // [-1,1] vector and perform a dot product between that vector and the provided vector.
796 const char* dotLattice = "dot(((%s.ga + %s.rb * vec2(%s)) * vec2(2.0) - vec2(1.0)), %s);";
797
798 // Add noise function
799 static const GrGLSLShaderVar gPerlinNoiseArgs[] = {
800 GrGLSLShaderVar(chanCoord, kFloat_GrSLType),
801 GrGLSLShaderVar(noiseVec, kVec2f_GrSLType)
802 };
803
804 static const GrGLSLShaderVar gPerlinNoiseStitchArgs[] = {
805 GrGLSLShaderVar(chanCoord, kFloat_GrSLType),
806 GrGLSLShaderVar(noiseVec, kVec2f_GrSLType),
807 GrGLSLShaderVar(stitchData, kVec2f_GrSLType)
808 };
809
810 SkString noiseCode;
811
812 noiseCode.appendf("\tvec4 %s;\n", floorVal);
813 noiseCode.appendf("\t%s.xy = floor(%s);\n", floorVal, noiseVec);
814 noiseCode.appendf("\t%s.zw = %s.xy + vec2(1.0);\n", floorVal, floorVal);
815 noiseCode.appendf("\tvec2 %s = fract(%s);\n", fractVal, noiseVec);
816
817 // smooth curve : t * t * (3 - 2 * t)
818 noiseCode.appendf("\n\tvec2 %s = %s * %s * (vec2(3.0) - vec2(2.0) * %s);",
819 noiseSmooth, fractVal, fractVal, fractVal);
820
821 // Adjust frequencies if we're stitching tiles
822 if (fStitchTiles) {
823 noiseCode.appendf("\n\tif(%s.x >= %s.x) { %s.x -= %s.x; }",
824 floorVal, stitchData, floorVal, stitchData);
825 noiseCode.appendf("\n\tif(%s.y >= %s.y) { %s.y -= %s.y; }",
826 floorVal, stitchData, floorVal, stitchData);
827 noiseCode.appendf("\n\tif(%s.z >= %s.x) { %s.z -= %s.x; }",
828 floorVal, stitchData, floorVal, stitchData);
829 noiseCode.appendf("\n\tif(%s.w >= %s.y) { %s.w -= %s.y; }",
830 floorVal, stitchData, floorVal, stitchData);
831 }
832
833 // Get texture coordinates and normalize
834 noiseCode.appendf("\n\t%s = fract(floor(mod(%s, 256.0)) / vec4(256.0));\n",
835 floorVal, floorVal);
836
837 // Get permutation for x
838 {
839 SkString xCoords("");
840 xCoords.appendf("vec2(%s.x, 0.5)", floorVal);
841
842 noiseCode.appendf("\n\tvec2 %s;\n\t%s.x = ", latticeIdx, latticeIdx);
843 fsBuilder->appendTextureLookup(&noiseCode, args.fSamplers[0], xCoords.c_str(),
844 kVec2f_GrSLType);
845 noiseCode.append(".r;");
846 }
847
848 // Get permutation for x + 1
849 {
850 SkString xCoords("");
851 xCoords.appendf("vec2(%s.z, 0.5)", floorVal);
852
853 noiseCode.appendf("\n\t%s.y = ", latticeIdx);
854 fsBuilder->appendTextureLookup(&noiseCode, args.fSamplers[0], xCoords.c_str(),
855 kVec2f_GrSLType);
856 noiseCode.append(".r;");
857 }
858
859#if defined(SK_BUILD_FOR_ANDROID)
860 // Android rounding for Tegra devices, like, for example: Xoom (Tegra 2), Nexus 7 (Tegra 3).
861 // The issue is that colors aren't accurate enough on Tegra devices. For example, if an 8 bit
862 // value of 124 (or 0.486275 here) is entered, we can get a texture value of 123.513725
863 // (or 0.484368 here). The following rounding operation prevents these precision issues from
864 // affecting the result of the noise by making sure that we only have multiples of 1/255.
865 // (Note that 1/255 is about 0.003921569, which is the value used here).
866 noiseCode.appendf("\n\t%s = floor(%s * vec2(255.0) + vec2(0.5)) * vec2(0.003921569);",
867 latticeIdx, latticeIdx);
868#endif
869
870 // Get (x,y) coordinates with the permutated x
871 noiseCode.appendf("\n\tvec4 %s = fract(%s.xyxy + %s.yyww);", bcoords, latticeIdx, floorVal);
872
873 noiseCode.appendf("\n\n\tvec2 %s;", uv);
874 // Compute u, at offset (0,0)
875 {
876 SkString latticeCoords("");
877 latticeCoords.appendf("vec2(%s.x, %s)", bcoords, chanCoord);
878 noiseCode.appendf("\n\tvec4 %s = ", lattice);
879 fsBuilder->appendTextureLookup(&noiseCode, args.fSamplers[1], latticeCoords.c_str(),
880 kVec2f_GrSLType);
881 noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
882 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
883 }
884
885 noiseCode.appendf("\n\t%s.x -= 1.0;", fractVal);
886 // Compute v, at offset (-1,0)
887 {
888 SkString latticeCoords("");
889 latticeCoords.appendf("vec2(%s.y, %s)", bcoords, chanCoord);
890 noiseCode.append("\n\tlattice = ");
891 fsBuilder->appendTextureLookup(&noiseCode, args.fSamplers[1], latticeCoords.c_str(),
892 kVec2f_GrSLType);
893 noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
894 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
895 }
896
897 // Compute 'a' as a linear interpolation of 'u' and 'v'
898 noiseCode.appendf("\n\tvec2 %s;", ab);
899 noiseCode.appendf("\n\t%s.x = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
900
901 noiseCode.appendf("\n\t%s.y -= 1.0;", fractVal);
902 // Compute v, at offset (-1,-1)
903 {
904 SkString latticeCoords("");
905 latticeCoords.appendf("vec2(%s.w, %s)", bcoords, chanCoord);
906 noiseCode.append("\n\tlattice = ");
907 fsBuilder->appendTextureLookup(&noiseCode, args.fSamplers[1], latticeCoords.c_str(),
908 kVec2f_GrSLType);
909 noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
910 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
911 }
912
913 noiseCode.appendf("\n\t%s.x += 1.0;", fractVal);
914 // Compute u, at offset (0,-1)
915 {
916 SkString latticeCoords("");
917 latticeCoords.appendf("vec2(%s.z, %s)", bcoords, chanCoord);
918 noiseCode.append("\n\tlattice = ");
919 fsBuilder->appendTextureLookup(&noiseCode, args.fSamplers[1], latticeCoords.c_str(),
920 kVec2f_GrSLType);
921 noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
922 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
923 }
924
925 // Compute 'b' as a linear interpolation of 'u' and 'v'
926 noiseCode.appendf("\n\t%s.y = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
927 // Compute the noise as a linear interpolation of 'a' and 'b'
928 noiseCode.appendf("\n\treturn mix(%s.x, %s.y, %s.y);\n", ab, ab, noiseSmooth);
929
930 SkString noiseFuncName;
931 if (fStitchTiles) {
932 fsBuilder->emitFunction(kFloat_GrSLType,
933 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseStitchArgs),
934 gPerlinNoiseStitchArgs, noiseCode.c_str(), &noiseFuncName);
935 } else {
936 fsBuilder->emitFunction(kFloat_GrSLType,
937 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseArgs),
938 gPerlinNoiseArgs, noiseCode.c_str(), &noiseFuncName);
939 }
940
941 // There are rounding errors if the floor operation is not performed here
942 fsBuilder->codeAppendf("\n\t\tvec2 %s = floor(%s.xy) * %s;",
943 noiseVec, vCoords.c_str(), baseFrequencyUni);
944
945 // Clear the color accumulator
946 fsBuilder->codeAppendf("\n\t\t%s = vec4(0.0);", args.fOutputColor);
947
948 if (fStitchTiles) {
949 // Set up TurbulenceInitial stitch values.
950 fsBuilder->codeAppendf("\n\t\tvec2 %s = %s;", stitchData, stitchDataUni);
951 }
952
953 fsBuilder->codeAppendf("\n\t\tfloat %s = 1.0;", ratio);
954
955 // Loop over all octaves
956 fsBuilder->codeAppendf("\n\t\tfor (int octave = 0; octave < %d; ++octave) {", fNumOctaves);
957
958 fsBuilder->codeAppendf("\n\t\t\t%s += ", args.fOutputColor);
959 if (fType != SkPerlinNoiseShader2::kFractalNoise_Type) {
960 fsBuilder->codeAppend("abs(");
961 }
962 if (fStitchTiles) {
963 fsBuilder->codeAppendf(
964 "vec4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s),"
965 "\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))",
966 noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData,
967 noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData,
968 noiseFuncName.c_str(), chanCoordB, noiseVec, stitchData,
969 noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData);
970 } else {
971 fsBuilder->codeAppendf(
972 "vec4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s),"
973 "\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))",
974 noiseFuncName.c_str(), chanCoordR, noiseVec,
975 noiseFuncName.c_str(), chanCoordG, noiseVec,
976 noiseFuncName.c_str(), chanCoordB, noiseVec,
977 noiseFuncName.c_str(), chanCoordA, noiseVec);
978 }
979 if (fType != SkPerlinNoiseShader2::kFractalNoise_Type) {
980 fsBuilder->codeAppendf(")"); // end of "abs("
981 }
982 fsBuilder->codeAppendf(" * %s;", ratio);
983
984 fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", noiseVec);
985 fsBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio);
986
987 if (fStitchTiles) {
988 fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", stitchData);
989 }
990 fsBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves
991
992 if (fType == SkPerlinNoiseShader2::kFractalNoise_Type) {
993 // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
994 // by fractalNoise and (turbulenceFunctionResult) by turbulence.
995 fsBuilder->codeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);",
996 args.fOutputColor,args.fOutputColor);
997 }
998
999 // Clamp values
1000 fsBuilder->codeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor);
1001
1002 // Pre-multiply the result
1003 fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
1004 args.fOutputColor, args.fOutputColor,
1005 args.fOutputColor, args.fOutputColor);
1006}
1007
1008void GrGLPerlinNoise2::GenKey(const GrProcessor& processor, const GrGLSLCaps&,
egdaniel2d721d32015-11-11 13:06:05 -08001009 GrProcessorKeyBuilder* b) {
ethannicholas417011c2015-11-09 06:35:12 -08001010 const GrPerlinNoise2Effect& turbulence = processor.cast<GrPerlinNoise2Effect>();
1011
1012 uint32_t key = turbulence.numOctaves();
1013
1014 key = key << 3; // Make room for next 3 bits
1015
1016 switch (turbulence.type()) {
1017 case SkPerlinNoiseShader2::kFractalNoise_Type:
1018 key |= 0x1;
1019 break;
1020 case SkPerlinNoiseShader2::kTurbulence_Type:
1021 key |= 0x2;
1022 break;
1023 default:
1024 // leave key at 0
1025 break;
1026 }
1027
1028 if (turbulence.stitchTiles()) {
1029 key |= 0x4; // Flip the 3rd bit if tile stitching is on
1030 }
1031
1032 b->add32(key);
1033}
1034
1035void GrGLPerlinNoise2::onSetData(const GrGLSLProgramDataManager& pdman,
1036 const GrProcessor& processor) {
1037 INHERITED::onSetData(pdman, processor);
1038
1039 const GrPerlinNoise2Effect& turbulence = processor.cast<GrPerlinNoise2Effect>();
1040
1041 const SkVector& baseFrequency = turbulence.baseFrequency();
1042 pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
1043
1044 if (turbulence.stitchTiles()) {
1045 const SkPerlinNoiseShader2::StitchData& stitchData = turbulence.stitchData();
1046 pdman.set2f(fStitchDataUni, SkIntToScalar(stitchData.fWidth),
1047 SkIntToScalar(stitchData.fHeight));
1048 }
1049}
1050
1051/////////////////////////////////////////////////////////////////////
1052
egdaniel64c47282015-11-13 06:54:19 -08001053class GrGLImprovedPerlinNoise : public GrGLSLFragmentProcessor {
ethannicholas417011c2015-11-09 06:35:12 -08001054public:
1055 GrGLImprovedPerlinNoise(const GrProcessor&);
1056 virtual ~GrGLImprovedPerlinNoise() {}
1057
1058 virtual void emitCode(EmitArgs&) override;
1059
1060 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder* b);
1061
1062protected:
1063 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
1064
1065private:
1066
1067 SkScalar fZ;
1068 GrGLSLProgramDataManager::UniformHandle fZUni;
1069 GrGLSLProgramDataManager::UniformHandle fOctavesUni;
1070 GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni;
1071
1072private:
egdaniel64c47282015-11-13 06:54:19 -08001073 typedef GrGLSLFragmentProcessor INHERITED;
ethannicholas417011c2015-11-09 06:35:12 -08001074};
1075
1076/////////////////////////////////////////////////////////////////////
1077
1078class GrImprovedPerlinNoiseEffect : public GrFragmentProcessor {
1079public:
egdaniel478c04e2015-11-09 07:40:49 -08001080 static GrFragmentProcessor* Create(int octaves, SkScalar z,
ethannicholas417011c2015-11-09 06:35:12 -08001081 SkPerlinNoiseShader2::PaintingData* paintingData,
1082 GrTexture* permutationsTexture, GrTexture* gradientTexture,
1083 const SkMatrix& matrix) {
1084 return new GrImprovedPerlinNoiseEffect(octaves, z, paintingData, permutationsTexture,
1085 gradientTexture, matrix);
1086 }
1087
1088 virtual ~GrImprovedPerlinNoiseEffect() { delete fPaintingData; }
1089
1090 const char* name() const override { return "ImprovedPerlinNoise"; }
1091
1092 const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; }
1093 SkScalar z() const { return fZ; }
1094 int octaves() const { return fOctaves; }
1095 const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
1096
1097private:
egdaniel57d3b032015-11-13 11:57:27 -08001098 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
ethannicholas417011c2015-11-09 06:35:12 -08001099 return new GrGLImprovedPerlinNoise(*this);
1100 }
1101
egdaniel57d3b032015-11-13 11:57:27 -08001102 virtual void onGetGLSLProcessorKey(const GrGLSLCaps& caps,
1103 GrProcessorKeyBuilder* b) const override {
ethannicholas417011c2015-11-09 06:35:12 -08001104 GrGLImprovedPerlinNoise::GenKey(*this, caps, b);
1105 }
1106
1107 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
1108 const GrImprovedPerlinNoiseEffect& s = sBase.cast<GrImprovedPerlinNoiseEffect>();
1109 return fZ == fZ &&
1110 fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency;
1111 }
1112
1113 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
1114 inout->setToUnknown(GrInvariantOutput::kWillNot_ReadInput);
1115 }
1116
1117 GrImprovedPerlinNoiseEffect(int octaves, SkScalar z,
1118 SkPerlinNoiseShader2::PaintingData* paintingData,
1119 GrTexture* permutationsTexture, GrTexture* gradientTexture,
1120 const SkMatrix& matrix)
1121 : fOctaves(octaves)
1122 , fZ(z)
1123 , fPermutationsAccess(permutationsTexture)
1124 , fGradientAccess(gradientTexture)
1125 , fPaintingData(paintingData) {
1126 this->initClassID<GrImprovedPerlinNoiseEffect>();
1127 this->addTextureAccess(&fPermutationsAccess);
1128 this->addTextureAccess(&fGradientAccess);
1129 fCoordTransform.reset(kLocal_GrCoordSet, matrix);
1130 this->addCoordTransform(&fCoordTransform);
1131 }
1132
1133 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
1134
1135 GrCoordTransform fCoordTransform;
1136 int fOctaves;
1137 SkScalar fZ;
1138 GrTextureAccess fPermutationsAccess;
1139 GrTextureAccess fGradientAccess;
1140 SkPerlinNoiseShader2::PaintingData *fPaintingData;
1141
1142private:
1143 typedef GrFragmentProcessor INHERITED;
1144};
1145
1146/////////////////////////////////////////////////////////////////////
1147GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrImprovedPerlinNoiseEffect);
1148
1149const GrFragmentProcessor* GrImprovedPerlinNoiseEffect::TestCreate(GrProcessorTestData* d) {
1150 SkScalar baseFrequencyX = d->fRandom->nextRangeScalar(0.01f,
1151 0.99f);
1152 SkScalar baseFrequencyY = d->fRandom->nextRangeScalar(0.01f,
1153 0.99f);
1154 int numOctaves = d->fRandom->nextRangeU(2, 10);
1155 SkScalar z = SkIntToScalar(d->fRandom->nextU());
1156
1157 SkAutoTUnref<SkShader> shader(SkPerlinNoiseShader2::CreateImprovedNoise(baseFrequencyX,
1158 baseFrequencyY,
1159 numOctaves,
1160 z));
1161
1162 GrPaint grPaint;
1163 return shader->asFragmentProcessor(d->fContext,
1164 GrTest::TestMatrix(d->fRandom), nullptr,
1165 kNone_SkFilterQuality);
1166}
1167
1168GrGLImprovedPerlinNoise::GrGLImprovedPerlinNoise(const GrProcessor& processor)
1169 : fZ(processor.cast<GrImprovedPerlinNoiseEffect>().z()) {
1170}
1171
1172void GrGLImprovedPerlinNoise::emitCode(EmitArgs& args) {
egdaniel4ca2e602015-11-18 08:01:26 -08001173 GrGLSLFragmentBuilder* fsBuilder = args.fFragBuilder;
ethannicholas417011c2015-11-09 06:35:12 -08001174 SkString vCoords = fsBuilder->ensureFSCoords2D(args.fCoords, 0);
1175
egdaniel2d721d32015-11-11 13:06:05 -08001176 fBaseFrequencyUni = args.fBuilder->addUniform(GrGLSLProgramBuilder::kFragment_Visibility,
ethannicholas417011c2015-11-09 06:35:12 -08001177 kVec2f_GrSLType, kDefault_GrSLPrecision,
1178 "baseFrequency");
1179 const char* baseFrequencyUni = args.fBuilder->getUniformCStr(fBaseFrequencyUni);
1180
egdaniel2d721d32015-11-11 13:06:05 -08001181 fOctavesUni = args.fBuilder->addUniform(GrGLSLProgramBuilder::kFragment_Visibility,
ethannicholas417011c2015-11-09 06:35:12 -08001182 kFloat_GrSLType, kDefault_GrSLPrecision,
1183 "octaves");
1184 const char* octavesUni = args.fBuilder->getUniformCStr(fOctavesUni);
1185
egdaniel2d721d32015-11-11 13:06:05 -08001186 fZUni = args.fBuilder->addUniform(GrGLSLProgramBuilder::kFragment_Visibility,
ethannicholas417011c2015-11-09 06:35:12 -08001187 kFloat_GrSLType, kDefault_GrSLPrecision,
1188 "z");
1189 const char* zUni = args.fBuilder->getUniformCStr(fZUni);
1190
1191 // fade function
1192 static const GrGLSLShaderVar fadeArgs[] = {
1193 GrGLSLShaderVar("t", kVec3f_GrSLType)
1194 };
1195 SkString fadeFuncName;
1196 fsBuilder->emitFunction(kVec3f_GrSLType, "fade", SK_ARRAY_COUNT(fadeArgs),
1197 fadeArgs,
1198 "return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);",
1199 &fadeFuncName);
1200
1201 // perm function
1202 static const GrGLSLShaderVar permArgs[] = {
1203 GrGLSLShaderVar("x", kFloat_GrSLType)
1204 };
1205 SkString permFuncName;
1206 SkString permCode("return ");
1207 // FIXME even though I'm creating these textures with kRepeat_TileMode, they're clamped. Not
1208 // sure why. Using fract() (here and the next texture lookup) as a workaround.
1209 fsBuilder->appendTextureLookup(&permCode, args.fSamplers[0], "vec2(fract(x / 256.0), 0.0)",
1210 kVec2f_GrSLType);
1211 permCode.append(".r * 255.0;");
1212 fsBuilder->emitFunction(kFloat_GrSLType, "perm", SK_ARRAY_COUNT(permArgs), permArgs,
1213 permCode.c_str(), &permFuncName);
1214
1215 // grad function
1216 static const GrGLSLShaderVar gradArgs[] = {
1217 GrGLSLShaderVar("x", kFloat_GrSLType),
1218 GrGLSLShaderVar("p", kVec3f_GrSLType)
1219 };
1220 SkString gradFuncName;
1221 SkString gradCode("return dot(");
1222 fsBuilder->appendTextureLookup(&gradCode, args.fSamplers[1], "vec2(fract(x / 16.0), 0.0)",
1223 kVec2f_GrSLType);
1224 gradCode.append(".rgb * 255.0 - vec3(1.0), p);");
1225 fsBuilder->emitFunction(kFloat_GrSLType, "grad", SK_ARRAY_COUNT(gradArgs), gradArgs,
1226 gradCode.c_str(), &gradFuncName);
1227
1228 // lerp function
1229 static const GrGLSLShaderVar lerpArgs[] = {
1230 GrGLSLShaderVar("a", kFloat_GrSLType),
1231 GrGLSLShaderVar("b", kFloat_GrSLType),
1232 GrGLSLShaderVar("w", kFloat_GrSLType)
1233 };
1234 SkString lerpFuncName;
1235 fsBuilder->emitFunction(kFloat_GrSLType, "lerp", SK_ARRAY_COUNT(lerpArgs), lerpArgs,
1236 "return a + w * (b - a);", &lerpFuncName);
1237
1238 // noise function
1239 static const GrGLSLShaderVar noiseArgs[] = {
1240 GrGLSLShaderVar("p", kVec3f_GrSLType),
1241 };
1242 SkString noiseFuncName;
1243 SkString noiseCode;
1244 noiseCode.append("vec3 P = mod(floor(p), 256.0);");
1245 noiseCode.append("p -= floor(p);");
1246 noiseCode.appendf("vec3 f = %s(p);", fadeFuncName.c_str());
1247 noiseCode.appendf("float A = %s(P.x) + P.y;", permFuncName.c_str());
1248 noiseCode.appendf("float AA = %s(A) + P.z;", permFuncName.c_str());
1249 noiseCode.appendf("float AB = %s(A + 1.0) + P.z;", permFuncName.c_str());
1250 noiseCode.appendf("float B = %s(P.x + 1.0) + P.y;", permFuncName.c_str());
1251 noiseCode.appendf("float BA = %s(B) + P.z;", permFuncName.c_str());
1252 noiseCode.appendf("float BB = %s(B + 1.0) + P.z;", permFuncName.c_str());
1253 noiseCode.appendf("float result = %s(", lerpFuncName.c_str());
1254 noiseCode.appendf("%s(%s(%s(%s(AA), p),", lerpFuncName.c_str(), lerpFuncName.c_str(),
1255 gradFuncName.c_str(), permFuncName.c_str());
1256 noiseCode.appendf("%s(%s(BA), p + vec3(-1.0, 0.0, 0.0)), f.x),", gradFuncName.c_str(),
1257 permFuncName.c_str());
1258 noiseCode.appendf("%s(%s(%s(AB), p + vec3(0.0, -1.0, 0.0)),", lerpFuncName.c_str(),
1259 gradFuncName.c_str(), permFuncName.c_str());
1260 noiseCode.appendf("%s(%s(BB), p + vec3(-1.0, -1.0, 0.0)), f.x), f.y),",
1261 gradFuncName.c_str(), permFuncName.c_str());
1262 noiseCode.appendf("%s(%s(%s(%s(AA + 1.0), p + vec3(0.0, 0.0, -1.0)),",
1263 lerpFuncName.c_str(), lerpFuncName.c_str(), gradFuncName.c_str(),
1264 permFuncName.c_str());
1265 noiseCode.appendf("%s(%s(BA + 1.0), p + vec3(-1.0, 0.0, -1.0)), f.x),",
1266 gradFuncName.c_str(), permFuncName.c_str());
1267 noiseCode.appendf("%s(%s(%s(AB + 1.0), p + vec3(0.0, -1.0, -1.0)),",
1268 lerpFuncName.c_str(), gradFuncName.c_str(), permFuncName.c_str());
1269 noiseCode.appendf("%s(%s(BB + 1.0), p + vec3(-1.0, -1.0, -1.0)), f.x), f.y), f.z);",
1270 gradFuncName.c_str(), permFuncName.c_str());
1271 noiseCode.append("return result;");
1272 fsBuilder->emitFunction(kFloat_GrSLType, "noise", SK_ARRAY_COUNT(noiseArgs), noiseArgs,
1273 noiseCode.c_str(), &noiseFuncName);
1274
1275 // noiseOctaves function
1276 static const GrGLSLShaderVar noiseOctavesArgs[] = {
1277 GrGLSLShaderVar("p", kVec3f_GrSLType),
1278 GrGLSLShaderVar("octaves", kFloat_GrSLType),
1279 };
1280 SkString noiseOctavesFuncName;
1281 SkString noiseOctavesCode;
1282 noiseOctavesCode.append("float result = 0.0;");
1283 noiseOctavesCode.append("float ratio = 1.0;");
1284 noiseOctavesCode.append("for (float i = 0.0; i < octaves; i++) {");
1285 noiseOctavesCode.appendf("result += %s(p) / ratio;", noiseFuncName.c_str());
1286 noiseOctavesCode.append("p *= 2.0;");
1287 noiseOctavesCode.append("ratio *= 2.0;");
1288 noiseOctavesCode.append("}");
1289 noiseOctavesCode.append("return (result + 1.0) / 2.0;");
1290 fsBuilder->emitFunction(kFloat_GrSLType, "noiseOctaves", SK_ARRAY_COUNT(noiseOctavesArgs),
1291 noiseOctavesArgs, noiseOctavesCode.c_str(), &noiseOctavesFuncName);
1292
1293 fsBuilder->codeAppendf("vec2 coords = %s * %s;", vCoords.c_str(), baseFrequencyUni);
1294 fsBuilder->codeAppendf("float r = %s(vec3(coords, %s), %s);", noiseOctavesFuncName.c_str(),
1295 zUni, octavesUni);
egdaniel478c04e2015-11-09 07:40:49 -08001296 fsBuilder->codeAppendf("float g = %s(vec3(coords, %s + 0000.0), %s);",
ethannicholas417011c2015-11-09 06:35:12 -08001297 noiseOctavesFuncName.c_str(), zUni, octavesUni);
egdaniel478c04e2015-11-09 07:40:49 -08001298 fsBuilder->codeAppendf("float b = %s(vec3(coords, %s + 0000.0), %s);",
ethannicholas417011c2015-11-09 06:35:12 -08001299 noiseOctavesFuncName.c_str(), zUni, octavesUni);
egdaniel478c04e2015-11-09 07:40:49 -08001300 fsBuilder->codeAppendf("float a = %s(vec3(coords, %s + 0000.0), %s);",
ethannicholas417011c2015-11-09 06:35:12 -08001301 noiseOctavesFuncName.c_str(), zUni, octavesUni);
1302 fsBuilder->codeAppendf("%s = vec4(r, g, b, a);", args.fOutputColor);
1303
1304 // Clamp values
1305 fsBuilder->codeAppendf("%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor);
1306
1307 // Pre-multiply the result
1308 fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
1309 args.fOutputColor, args.fOutputColor,
1310 args.fOutputColor, args.fOutputColor);
1311}
1312
1313void GrGLImprovedPerlinNoise::GenKey(const GrProcessor& processor, const GrGLSLCaps&,
1314 GrProcessorKeyBuilder* b) {
1315}
1316
1317void GrGLImprovedPerlinNoise::onSetData(const GrGLSLProgramDataManager& pdman,
1318 const GrProcessor& processor) {
1319 INHERITED::onSetData(pdman, processor);
1320
1321 const GrImprovedPerlinNoiseEffect& noise = processor.cast<GrImprovedPerlinNoiseEffect>();
1322
1323 const SkVector& baseFrequency = noise.baseFrequency();
1324 pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
1325
egdaniel478c04e2015-11-09 07:40:49 -08001326 pdman.set1f(fOctavesUni, SkIntToScalar(noise.octaves()));
ethannicholas417011c2015-11-09 06:35:12 -08001327
1328 pdman.set1f(fZUni, noise.z());
1329}
1330
1331/////////////////////////////////////////////////////////////////////
1332const GrFragmentProcessor* SkPerlinNoiseShader2::asFragmentProcessor(
1333 GrContext* context,
1334 const SkMatrix& viewM,
1335 const SkMatrix* externalLocalMatrix,
1336 SkFilterQuality) const {
1337 SkASSERT(context);
1338
1339 SkMatrix localMatrix = this->getLocalMatrix();
1340 if (externalLocalMatrix) {
1341 localMatrix.preConcat(*externalLocalMatrix);
1342 }
1343
1344 SkMatrix matrix = viewM;
1345 matrix.preConcat(localMatrix);
1346
1347 // Either we don't stitch tiles, either we have a valid tile size
1348 SkASSERT(!fStitchTiles || !fTileSize.isEmpty());
1349
1350 SkPerlinNoiseShader2::PaintingData* paintingData =
1351 new PaintingData(fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY, matrix);
1352
1353 SkMatrix m = viewM;
1354 m.setTranslateX(-localMatrix.getTranslateX() + SK_Scalar1);
1355 m.setTranslateY(-localMatrix.getTranslateY() + SK_Scalar1);
1356
1357 if (fType == kImprovedNoise_Type) {
1358 GrTextureParams textureParams(SkShader::TileMode::kRepeat_TileMode,
1359 GrTextureParams::FilterMode::kNone_FilterMode);
1360 SkAutoTUnref<GrTexture> permutationsTexture(
1361 GrRefCachedBitmapTexture(context, paintingData->getImprovedPermutationsBitmap(),
1362 textureParams));
1363 SkAutoTUnref<GrTexture> gradientTexture(
1364 GrRefCachedBitmapTexture(context, paintingData->getGradientBitmap(),
1365 textureParams));
1366 return GrImprovedPerlinNoiseEffect::Create(fNumOctaves, fSeed, paintingData,
1367 permutationsTexture, gradientTexture, m);
1368 }
1369
1370 if (0 == fNumOctaves) {
1371 if (kFractalNoise_Type == fType) {
1372 // Extract the incoming alpha and emit rgba = (a/4, a/4, a/4, a/2)
1373 SkAutoTUnref<const GrFragmentProcessor> inner(
1374 GrConstColorProcessor::Create(0x80404040,
1375 GrConstColorProcessor::kModulateRGBA_InputMode));
1376 return GrFragmentProcessor::MulOutputByInputAlpha(inner);
1377 }
1378 // Emit zero.
1379 return GrConstColorProcessor::Create(0x0, GrConstColorProcessor::kIgnore_InputMode);
1380 }
1381
1382 SkAutoTUnref<GrTexture> permutationsTexture(
1383 GrRefCachedBitmapTexture(context, paintingData->getPermutationsBitmap(),
1384 GrTextureParams::ClampNoFilter()));
1385 SkAutoTUnref<GrTexture> noiseTexture(
1386 GrRefCachedBitmapTexture(context, paintingData->getNoiseBitmap(),
1387 GrTextureParams::ClampNoFilter()));
1388
1389 if ((permutationsTexture) && (noiseTexture)) {
1390 SkAutoTUnref<GrFragmentProcessor> inner(
1391 GrPerlinNoise2Effect::Create(fType,
1392 fNumOctaves,
1393 fStitchTiles,
1394 paintingData,
1395 permutationsTexture, noiseTexture,
1396 m));
1397 return GrFragmentProcessor::MulOutputByInputAlpha(inner);
1398 }
1399 delete paintingData;
1400 return nullptr;
1401}
1402
1403#endif
1404
1405#ifndef SK_IGNORE_TO_STRING
1406void SkPerlinNoiseShader2::toString(SkString* str) const {
1407 str->append("SkPerlinNoiseShader2: (");
1408
1409 str->append("type: ");
1410 switch (fType) {
1411 case kFractalNoise_Type:
1412 str->append("\"fractal noise\"");
1413 break;
1414 case kTurbulence_Type:
1415 str->append("\"turbulence\"");
1416 break;
1417 default:
1418 str->append("\"unknown\"");
1419 break;
1420 }
1421 str->append(" base frequency: (");
1422 str->appendScalar(fBaseFrequencyX);
1423 str->append(", ");
1424 str->appendScalar(fBaseFrequencyY);
1425 str->append(") number of octaves: ");
1426 str->appendS32(fNumOctaves);
1427 str->append(" seed: ");
1428 str->appendScalar(fSeed);
1429 str->append(" stitch tiles: ");
1430 str->append(fStitchTiles ? "true " : "false ");
1431
1432 this->INHERITED::toString(str);
1433
1434 str->append(")");
1435}
1436#endif