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