blob: f6885408ada800410f96024d759377dbcf33cee2 [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
reed8a21c9f2016-03-08 18:50:00 -0800312sk_sp<SkShader> SkPerlinNoiseShader2::MakeFractalNoise(SkScalar baseFrequencyX,
313 SkScalar baseFrequencyY,
314 int numOctaves, SkScalar seed,
315 const SkISize* tileSize) {
316 return sk_sp<SkShader>(new SkPerlinNoiseShader2(kFractalNoise_Type, baseFrequencyX,
317 baseFrequencyY, numOctaves, seed, tileSize));
ethannicholas417011c2015-11-09 06:35:12 -0800318}
319
reed8a21c9f2016-03-08 18:50:00 -0800320sk_sp<SkShader> SkPerlinNoiseShader2::MakeTurbulence(SkScalar baseFrequencyX,
321 SkScalar baseFrequencyY,
322 int numOctaves, SkScalar seed,
323 const SkISize* tileSize) {
324 return sk_sp<SkShader>(new SkPerlinNoiseShader2(kTurbulence_Type, baseFrequencyX,
325 baseFrequencyY, numOctaves, seed, tileSize));
ethannicholas417011c2015-11-09 06:35:12 -0800326}
327
reed8a21c9f2016-03-08 18:50:00 -0800328sk_sp<SkShader> SkPerlinNoiseShader2::MakeImprovedNoise(SkScalar baseFrequencyX,
329 SkScalar baseFrequencyY,
330 int numOctaves, SkScalar z) {
331 return sk_sp<SkShader>(new SkPerlinNoiseShader2(kImprovedNoise_Type, baseFrequencyX,
332 baseFrequencyY, numOctaves, z, NULL));
ethannicholas417011c2015-11-09 06:35:12 -0800333}
334
335SkPerlinNoiseShader2::SkPerlinNoiseShader2(SkPerlinNoiseShader2::Type type,
336 SkScalar baseFrequencyX,
337 SkScalar baseFrequencyY,
338 int numOctaves,
339 SkScalar seed,
340 const SkISize* tileSize)
341 : fType(type)
342 , fBaseFrequencyX(baseFrequencyX)
343 , fBaseFrequencyY(baseFrequencyY)
344 , fNumOctaves(numOctaves > 255 ? 255 : numOctaves/*[0,255] octaves allowed*/)
345 , fSeed(seed)
346 , fTileSize(nullptr == tileSize ? SkISize::Make(0, 0) : *tileSize)
347 , fStitchTiles(!fTileSize.isEmpty())
348{
349 SkASSERT(numOctaves >= 0 && numOctaves < 256);
350}
351
352SkPerlinNoiseShader2::~SkPerlinNoiseShader2() {
353}
354
355SkFlattenable* SkPerlinNoiseShader2::CreateProc(SkReadBuffer& buffer) {
356 Type type = (Type)buffer.readInt();
357 SkScalar freqX = buffer.readScalar();
358 SkScalar freqY = buffer.readScalar();
359 int octaves = buffer.readInt();
360 SkScalar seed = buffer.readScalar();
361 SkISize tileSize;
362 tileSize.fWidth = buffer.readInt();
363 tileSize.fHeight = buffer.readInt();
364
365 switch (type) {
366 case kFractalNoise_Type:
reed8a21c9f2016-03-08 18:50:00 -0800367 return SkPerlinNoiseShader2::MakeFractalNoise(freqX, freqY, octaves, seed,
368 &tileSize).release();
ethannicholas417011c2015-11-09 06:35:12 -0800369 case kTurbulence_Type:
reed8a21c9f2016-03-08 18:50:00 -0800370 return SkPerlinNoiseShader2::MakeTubulence(freqX, freqY, octaves, seed,
371 &tileSize).release();
ethannicholas417011c2015-11-09 06:35:12 -0800372 case kImprovedNoise_Type:
reed8a21c9f2016-03-08 18:50:00 -0800373 return SkPerlinNoiseShader2::MakeImprovedNoise(freqX, freqY, octaves, seed).release();
ethannicholas417011c2015-11-09 06:35:12 -0800374 default:
375 return nullptr;
376 }
377}
378
379void SkPerlinNoiseShader2::flatten(SkWriteBuffer& buffer) const {
380 buffer.writeInt((int) fType);
381 buffer.writeScalar(fBaseFrequencyX);
382 buffer.writeScalar(fBaseFrequencyY);
383 buffer.writeInt(fNumOctaves);
384 buffer.writeScalar(fSeed);
385 buffer.writeInt(fTileSize.fWidth);
386 buffer.writeInt(fTileSize.fHeight);
387}
388
389SkScalar SkPerlinNoiseShader2::PerlinNoiseShaderContext::noise2D(
390 int channel, const StitchData& stitchData, const SkPoint& noiseVector) const {
391 struct Noise {
392 int noisePositionIntegerValue;
393 int nextNoisePositionIntegerValue;
394 SkScalar noisePositionFractionValue;
395 Noise(SkScalar component)
396 {
397 SkScalar position = component + kPerlinNoise;
398 noisePositionIntegerValue = SkScalarFloorToInt(position);
399 noisePositionFractionValue = position - SkIntToScalar(noisePositionIntegerValue);
400 nextNoisePositionIntegerValue = noisePositionIntegerValue + 1;
401 }
402 };
403 Noise noiseX(noiseVector.x());
404 Noise noiseY(noiseVector.y());
405 SkScalar u, v;
406 const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNoiseShader2&>(fShader);
407 // If stitching, adjust lattice points accordingly.
408 if (perlinNoiseShader.fStitchTiles) {
409 noiseX.noisePositionIntegerValue =
410 checkNoise(noiseX.noisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth);
411 noiseY.noisePositionIntegerValue =
412 checkNoise(noiseY.noisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight);
413 noiseX.nextNoisePositionIntegerValue =
414 checkNoise(noiseX.nextNoisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth);
415 noiseY.nextNoisePositionIntegerValue =
416 checkNoise(noiseY.nextNoisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight);
417 }
418 noiseX.noisePositionIntegerValue &= kBlockMask;
419 noiseY.noisePositionIntegerValue &= kBlockMask;
420 noiseX.nextNoisePositionIntegerValue &= kBlockMask;
421 noiseY.nextNoisePositionIntegerValue &= kBlockMask;
422 int i =
423 fPaintingData->fLatticeSelector[noiseX.noisePositionIntegerValue];
424 int j =
425 fPaintingData->fLatticeSelector[noiseX.nextNoisePositionIntegerValue];
426 int b00 = (i + noiseY.noisePositionIntegerValue) & kBlockMask;
427 int b10 = (j + noiseY.noisePositionIntegerValue) & kBlockMask;
428 int b01 = (i + noiseY.nextNoisePositionIntegerValue) & kBlockMask;
429 int b11 = (j + noiseY.nextNoisePositionIntegerValue) & kBlockMask;
430 SkScalar sx = smoothCurve(noiseX.noisePositionFractionValue);
431 SkScalar sy = smoothCurve(noiseY.noisePositionFractionValue);
432 // This is taken 1:1 from SVG spec: http://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement
433 SkPoint fractionValue = SkPoint::Make(noiseX.noisePositionFractionValue,
434 noiseY.noisePositionFractionValue); // Offset (0,0)
435 u = fPaintingData->fGradient[channel][b00].dot(fractionValue);
436 fractionValue.fX -= SK_Scalar1; // Offset (-1,0)
437 v = fPaintingData->fGradient[channel][b10].dot(fractionValue);
438 SkScalar a = SkScalarInterp(u, v, sx);
439 fractionValue.fY -= SK_Scalar1; // Offset (-1,-1)
440 v = fPaintingData->fGradient[channel][b11].dot(fractionValue);
441 fractionValue.fX = noiseX.noisePositionFractionValue; // Offset (0,-1)
442 u = fPaintingData->fGradient[channel][b01].dot(fractionValue);
443 SkScalar b = SkScalarInterp(u, v, sx);
444 return SkScalarInterp(a, b, sy);
445}
446
447SkScalar SkPerlinNoiseShader2::PerlinNoiseShaderContext::calculateTurbulenceValueForPoint(
448 int channel, StitchData& stitchData, const SkPoint& point) const {
449 const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNoiseShader2&>(fShader);
450 if (perlinNoiseShader.fStitchTiles) {
451 // Set up TurbulenceInitial stitch values.
452 stitchData = fPaintingData->fStitchDataInit;
453 }
454 SkScalar turbulenceFunctionResult = 0;
455 SkPoint noiseVector(SkPoint::Make(SkScalarMul(point.x(), fPaintingData->fBaseFrequency.fX),
456 SkScalarMul(point.y(), fPaintingData->fBaseFrequency.fY)));
457 SkScalar ratio = SK_Scalar1;
458 for (int octave = 0; octave < perlinNoiseShader.fNumOctaves; ++octave) {
459 SkScalar noise = noise2D(channel, stitchData, noiseVector);
460 SkScalar numer = (perlinNoiseShader.fType == kFractalNoise_Type) ?
461 noise : SkScalarAbs(noise);
462 turbulenceFunctionResult += numer / ratio;
463 noiseVector.fX *= 2;
464 noiseVector.fY *= 2;
465 ratio *= 2;
466 if (perlinNoiseShader.fStitchTiles) {
467 // Update stitch values
468 stitchData.fWidth *= 2;
469 stitchData.fWrapX = stitchData.fWidth + kPerlinNoise;
470 stitchData.fHeight *= 2;
471 stitchData.fWrapY = stitchData.fHeight + kPerlinNoise;
472 }
473 }
474
475 // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
476 // by fractalNoise and (turbulenceFunctionResult) by turbulence.
477 if (perlinNoiseShader.fType == kFractalNoise_Type) {
478 turbulenceFunctionResult =
479 SkScalarMul(turbulenceFunctionResult, SK_ScalarHalf) + SK_ScalarHalf;
480 }
481
482 if (channel == 3) { // Scale alpha by paint value
483 turbulenceFunctionResult *= SkIntToScalar(getPaintAlpha()) / 255;
484 }
485
486 // Clamp result
487 return SkScalarPin(turbulenceFunctionResult, 0, SK_Scalar1);
488}
489
490////////////////////////////////////////////////////////////////////////////////////////////////////
491// Improved Perlin Noise based on Java implementation found at http://mrl.nyu.edu/~perlin/noise/
492static SkScalar fade(SkScalar t) {
493 return t * t * t * (t * (t * 6 - 15) + 10);
494}
495
496static SkScalar lerp(SkScalar t, SkScalar a, SkScalar b) {
497 return a + t * (b - a);
498}
499
500static SkScalar grad(int hash, SkScalar x, SkScalar y, SkScalar z) {
501 int h = hash & 15;
502 SkScalar u = h < 8 ? x : y;
503 SkScalar v = h < 4 ? y : h == 12 || h == 14 ? x : z;
504 return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
505}
506
507SkScalar SkPerlinNoiseShader2::PerlinNoiseShaderContext::calculateImprovedNoiseValueForPoint(
508 int channel, const SkPoint& point) const {
509 const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNoiseShader2&>(fShader);
510 SkScalar x = point.fX * perlinNoiseShader.fBaseFrequencyX;
511 SkScalar y = point.fY * perlinNoiseShader.fBaseFrequencyY;
512 // z offset between different channels, chosen arbitrarily
513 static const SkScalar CHANNEL_DELTA = 1000.0f;
514 SkScalar z = channel * CHANNEL_DELTA + perlinNoiseShader.fSeed;
515 SkScalar result = 0;
516 SkScalar ratio = SK_Scalar1;
517 for (int i = 0; i < perlinNoiseShader.fNumOctaves; i++) {
518 int X = SkScalarFloorToInt(x) & 255;
519 int Y = SkScalarFloorToInt(y) & 255;
520 int Z = SkScalarFloorToInt(z) & 255;
521 SkScalar px = x - SkScalarFloorToScalar(x);
522 SkScalar py = y - SkScalarFloorToScalar(y);
523 SkScalar pz = z - SkScalarFloorToScalar(z);
524 SkScalar u = fade(px);
525 SkScalar v = fade(py);
526 SkScalar w = fade(pz);
527 uint8_t* permutations = improved_noise_permutations;
528 int A = permutations[X] + Y;
529 int AA = permutations[A] + Z;
530 int AB = permutations[A + 1] + Z;
531 int B = permutations[X + 1] + Y;
532 int BA = permutations[B] + Z;
533 int BB = permutations[B + 1] + Z;
534 result += lerp(w, lerp(v, lerp(u, grad(permutations[AA ], px , py , pz ),
535 grad(permutations[BA ], px - 1, py , pz )),
536 lerp(u, grad(permutations[AB ], px , py - 1, pz ),
537 grad(permutations[BB ], px - 1, py - 1, pz ))),
538 lerp(v, lerp(u, grad(permutations[AA + 1], px , py , pz - 1),
539 grad(permutations[BA + 1], px - 1, py , pz - 1)),
540 lerp(u, grad(permutations[AB + 1], px , py - 1, pz - 1),
541 grad(permutations[BB + 1], px - 1, py - 1, pz - 1)))) /
542 ratio;
543 x *= 2;
544 y *= 2;
545 ratio *= 2;
546 }
547 result = SkScalarClampMax((result + 1.0f) / 2.0f, 1.0f);
548 return result;
549}
550////////////////////////////////////////////////////////////////////////////////////////////////////
551
552SkPMColor SkPerlinNoiseShader2::PerlinNoiseShaderContext::shade(
553 const SkPoint& point, StitchData& stitchData) const {
554 const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNoiseShader2&>(fShader);
555 SkPoint newPoint;
556 fMatrix.mapPoints(&newPoint, &point, 1);
557 newPoint.fX = SkScalarRoundToScalar(newPoint.fX);
558 newPoint.fY = SkScalarRoundToScalar(newPoint.fY);
559
560 U8CPU rgba[4];
561 for (int channel = 3; channel >= 0; --channel) {
562 SkScalar value;
563 if (perlinNoiseShader.fType == kImprovedNoise_Type) {
564 value = calculateImprovedNoiseValueForPoint(channel, newPoint);
565 }
566 else {
567 value = calculateTurbulenceValueForPoint(channel, stitchData, newPoint);
568 }
569 rgba[channel] = SkScalarFloorToInt(255 * value);
570 }
571 return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]);
572}
573
574SkShader::Context* SkPerlinNoiseShader2::onCreateContext(const ContextRec& rec,
575 void* storage) const {
576 return new (storage) PerlinNoiseShaderContext(*this, rec);
577}
578
reed773ceda2016-03-03 18:18:25 -0800579size_t SkPerlinNoiseShader2::onContextSize(const ContextRec&) const {
reeda0cee5f2016-03-04 07:38:11 -0800580 return sizeof(PerlinNoiseShaderContext);
ethannicholas417011c2015-11-09 06:35:12 -0800581}
582
583SkPerlinNoiseShader2::PerlinNoiseShaderContext::PerlinNoiseShaderContext(
584 const SkPerlinNoiseShader2& shader, const ContextRec& rec)
585 : INHERITED(shader, rec)
586{
587 SkMatrix newMatrix = *rec.fMatrix;
588 newMatrix.preConcat(shader.getLocalMatrix());
589 if (rec.fLocalMatrix) {
590 newMatrix.preConcat(*rec.fLocalMatrix);
591 }
592 // This (1,1) translation is due to WebKit's 1 based coordinates for the noise
593 // (as opposed to 0 based, usually). The same adjustment is in the setData() function.
594 fMatrix.setTranslate(-newMatrix.getTranslateX() + SK_Scalar1, -newMatrix.getTranslateY() + SK_Scalar1);
595 fPaintingData = new PaintingData(shader.fTileSize, shader.fSeed, shader.fBaseFrequencyX,
596 shader.fBaseFrequencyY, newMatrix);
597}
598
599SkPerlinNoiseShader2::PerlinNoiseShaderContext::~PerlinNoiseShaderContext() { delete fPaintingData; }
600
601void SkPerlinNoiseShader2::PerlinNoiseShaderContext::shadeSpan(
602 int x, int y, SkPMColor result[], int count) {
603 SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y));
604 StitchData stitchData;
605 for (int i = 0; i < count; ++i) {
606 result[i] = shade(point, stitchData);
607 point.fX += SK_Scalar1;
608 }
609}
610
ethannicholas417011c2015-11-09 06:35:12 -0800611/////////////////////////////////////////////////////////////////////
612
613#if SK_SUPPORT_GPU
614
egdaniel64c47282015-11-13 06:54:19 -0800615class GrGLPerlinNoise2 : public GrGLSLFragmentProcessor {
ethannicholas417011c2015-11-09 06:35:12 -0800616public:
robertphillipsbf536af2016-02-04 06:11:53 -0800617 void emitCode(EmitArgs&) override;
ethannicholas417011c2015-11-09 06:35:12 -0800618
619 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder* b);
620
621protected:
622 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
623
624private:
ethannicholas417011c2015-11-09 06:35:12 -0800625 GrGLSLProgramDataManager::UniformHandle fStitchDataUni;
ethannicholas417011c2015-11-09 06:35:12 -0800626 GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni;
627
egdaniel64c47282015-11-13 06:54:19 -0800628 typedef GrGLSLFragmentProcessor INHERITED;
ethannicholas417011c2015-11-09 06:35:12 -0800629};
630
631/////////////////////////////////////////////////////////////////////
632
633class GrPerlinNoise2Effect : public GrFragmentProcessor {
634public:
635 static GrFragmentProcessor* Create(SkPerlinNoiseShader2::Type type,
636 int numOctaves, bool stitchTiles,
637 SkPerlinNoiseShader2::PaintingData* paintingData,
638 GrTexture* permutationsTexture, GrTexture* noiseTexture,
639 const SkMatrix& matrix) {
640 return new GrPerlinNoise2Effect(type, numOctaves, stitchTiles, paintingData,
641 permutationsTexture, noiseTexture, matrix);
642 }
643
644 virtual ~GrPerlinNoise2Effect() { delete fPaintingData; }
645
646 const char* name() const override { return "PerlinNoise"; }
647
648 const SkPerlinNoiseShader2::StitchData& stitchData() const { return fPaintingData->fStitchDataInit; }
649
650 SkPerlinNoiseShader2::Type type() const { return fType; }
651 bool stitchTiles() const { return fStitchTiles; }
652 const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; }
653 int numOctaves() const { return fNumOctaves; }
654 const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
655
656private:
egdaniel57d3b032015-11-13 11:57:27 -0800657 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
robertphillipsd3b32bf2016-02-05 07:15:39 -0800658 return new GrGLPerlinNoise2;
ethannicholas417011c2015-11-09 06:35:12 -0800659 }
660
egdaniel57d3b032015-11-13 11:57:27 -0800661 virtual void onGetGLSLProcessorKey(const GrGLSLCaps& caps,
662 GrProcessorKeyBuilder* b) const override {
ethannicholas417011c2015-11-09 06:35:12 -0800663 GrGLPerlinNoise2::GenKey(*this, caps, b);
664 }
665
666 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
667 const GrPerlinNoise2Effect& s = sBase.cast<GrPerlinNoise2Effect>();
668 return fType == s.fType &&
669 fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency &&
670 fNumOctaves == s.fNumOctaves &&
671 fStitchTiles == s.fStitchTiles &&
672 fPaintingData->fStitchDataInit == s.fPaintingData->fStitchDataInit;
673 }
674
675 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
676 inout->setToUnknown(GrInvariantOutput::kWillNot_ReadInput);
677 }
678
679 GrPerlinNoise2Effect(SkPerlinNoiseShader2::Type type,
680 int numOctaves, bool stitchTiles,
681 SkPerlinNoiseShader2::PaintingData* paintingData,
682 GrTexture* permutationsTexture, GrTexture* noiseTexture,
683 const SkMatrix& matrix)
684 : fType(type)
685 , fNumOctaves(numOctaves)
686 , fStitchTiles(stitchTiles)
687 , fPermutationsAccess(permutationsTexture)
688 , fNoiseAccess(noiseTexture)
689 , fPaintingData(paintingData) {
690 this->initClassID<GrPerlinNoise2Effect>();
691 this->addTextureAccess(&fPermutationsAccess);
692 this->addTextureAccess(&fNoiseAccess);
693 fCoordTransform.reset(kLocal_GrCoordSet, matrix);
694 this->addCoordTransform(&fCoordTransform);
695 }
696
697 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
698
699 SkPerlinNoiseShader2::Type fType;
700 GrCoordTransform fCoordTransform;
701 int fNumOctaves;
702 bool fStitchTiles;
703 GrTextureAccess fPermutationsAccess;
704 GrTextureAccess fNoiseAccess;
705 SkPerlinNoiseShader2::PaintingData *fPaintingData;
706
707private:
708 typedef GrFragmentProcessor INHERITED;
709};
710
711/////////////////////////////////////////////////////////////////////
712GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrPerlinNoise2Effect);
713
714const GrFragmentProcessor* GrPerlinNoise2Effect::TestCreate(GrProcessorTestData* d) {
715 int numOctaves = d->fRandom->nextRangeU(2, 10);
716 bool stitchTiles = d->fRandom->nextBool();
717 SkScalar seed = SkIntToScalar(d->fRandom->nextU());
718 SkISize tileSize = SkISize::Make(d->fRandom->nextRangeU(4, 4096),
719 d->fRandom->nextRangeU(4, 4096));
720 SkScalar baseFrequencyX = d->fRandom->nextRangeScalar(0.01f,
721 0.99f);
722 SkScalar baseFrequencyY = d->fRandom->nextRangeScalar(0.01f,
723 0.99f);
724
reed8a21c9f2016-03-08 18:50:00 -0800725 sk_sp<SkShader> shader(d->fRandom->nextBool() ?
726 SkPerlinNoiseShader2::MakeFractalNoise(baseFrequencyX, baseFrequencyY, numOctaves, seed,
727 stitchTiles ? &tileSize : nullptr) :
728 SkPerlinNoiseShader2::MakeTurbulence(baseFrequencyX, baseFrequencyY, numOctaves, seed,
ethannicholas417011c2015-11-09 06:35:12 -0800729 stitchTiles ? &tileSize : nullptr));
730
731 GrPaint grPaint;
732 return shader->asFragmentProcessor(d->fContext,
733 GrTest::TestMatrix(d->fRandom), nullptr,
734 kNone_SkFilterQuality);
735}
736
ethannicholas417011c2015-11-09 06:35:12 -0800737void GrGLPerlinNoise2::emitCode(EmitArgs& args) {
robertphillipsd3b32bf2016-02-05 07:15:39 -0800738 const GrPerlinNoise2Effect& pne = args.fFp.cast<GrPerlinNoise2Effect>();
739
egdaniel4ca2e602015-11-18 08:01:26 -0800740 GrGLSLFragmentBuilder* fsBuilder = args.fFragBuilder;
egdaniel7ea439b2015-12-03 09:20:44 -0800741 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
ethannicholas417011c2015-11-09 06:35:12 -0800742 SkString vCoords = fsBuilder->ensureFSCoords2D(args.fCoords, 0);
743
cdalton5e58cee2016-02-11 12:49:47 -0800744 fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800745 kVec2f_GrSLType, kDefault_GrSLPrecision,
746 "baseFrequency");
747 const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);
ethannicholas417011c2015-11-09 06:35:12 -0800748
749 const char* stitchDataUni = nullptr;
robertphillipsd3b32bf2016-02-05 07:15:39 -0800750 if (pne.stitchTiles()) {
cdalton5e58cee2016-02-11 12:49:47 -0800751 fStitchDataUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800752 kVec2f_GrSLType, kDefault_GrSLPrecision,
753 "stitchData");
754 stitchDataUni = uniformHandler->getUniformCStr(fStitchDataUni);
ethannicholas417011c2015-11-09 06:35:12 -0800755 }
756
757 // There are 4 lines, so the center of each line is 1/8, 3/8, 5/8 and 7/8
758 const char* chanCoordR = "0.125";
759 const char* chanCoordG = "0.375";
760 const char* chanCoordB = "0.625";
761 const char* chanCoordA = "0.875";
762 const char* chanCoord = "chanCoord";
763 const char* stitchData = "stitchData";
764 const char* ratio = "ratio";
765 const char* noiseVec = "noiseVec";
766 const char* noiseSmooth = "noiseSmooth";
767 const char* floorVal = "floorVal";
768 const char* fractVal = "fractVal";
769 const char* uv = "uv";
770 const char* ab = "ab";
771 const char* latticeIdx = "latticeIdx";
772 const char* bcoords = "bcoords";
773 const char* lattice = "lattice";
774 const char* inc8bit = "0.00390625"; // 1.0 / 256.0
775 // This is the math to convert the two 16bit integer packed into rgba 8 bit input into a
776 // [-1,1] vector and perform a dot product between that vector and the provided vector.
777 const char* dotLattice = "dot(((%s.ga + %s.rb * vec2(%s)) * vec2(2.0) - vec2(1.0)), %s);";
778
779 // Add noise function
780 static const GrGLSLShaderVar gPerlinNoiseArgs[] = {
781 GrGLSLShaderVar(chanCoord, kFloat_GrSLType),
782 GrGLSLShaderVar(noiseVec, kVec2f_GrSLType)
783 };
784
785 static const GrGLSLShaderVar gPerlinNoiseStitchArgs[] = {
786 GrGLSLShaderVar(chanCoord, kFloat_GrSLType),
787 GrGLSLShaderVar(noiseVec, kVec2f_GrSLType),
788 GrGLSLShaderVar(stitchData, kVec2f_GrSLType)
789 };
790
791 SkString noiseCode;
792
793 noiseCode.appendf("\tvec4 %s;\n", floorVal);
794 noiseCode.appendf("\t%s.xy = floor(%s);\n", floorVal, noiseVec);
795 noiseCode.appendf("\t%s.zw = %s.xy + vec2(1.0);\n", floorVal, floorVal);
796 noiseCode.appendf("\tvec2 %s = fract(%s);\n", fractVal, noiseVec);
797
798 // smooth curve : t * t * (3 - 2 * t)
799 noiseCode.appendf("\n\tvec2 %s = %s * %s * (vec2(3.0) - vec2(2.0) * %s);",
800 noiseSmooth, fractVal, fractVal, fractVal);
801
802 // Adjust frequencies if we're stitching tiles
robertphillipsd3b32bf2016-02-05 07:15:39 -0800803 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800804 noiseCode.appendf("\n\tif(%s.x >= %s.x) { %s.x -= %s.x; }",
805 floorVal, stitchData, floorVal, stitchData);
806 noiseCode.appendf("\n\tif(%s.y >= %s.y) { %s.y -= %s.y; }",
807 floorVal, stitchData, floorVal, stitchData);
808 noiseCode.appendf("\n\tif(%s.z >= %s.x) { %s.z -= %s.x; }",
809 floorVal, stitchData, floorVal, stitchData);
810 noiseCode.appendf("\n\tif(%s.w >= %s.y) { %s.w -= %s.y; }",
811 floorVal, stitchData, floorVal, stitchData);
812 }
813
814 // Get texture coordinates and normalize
815 noiseCode.appendf("\n\t%s = fract(floor(mod(%s, 256.0)) / vec4(256.0));\n",
816 floorVal, floorVal);
817
818 // Get permutation for x
819 {
820 SkString xCoords("");
821 xCoords.appendf("vec2(%s.x, 0.5)", floorVal);
822
823 noiseCode.appendf("\n\tvec2 %s;\n\t%s.x = ", latticeIdx, latticeIdx);
824 fsBuilder->appendTextureLookup(&noiseCode, args.fSamplers[0], xCoords.c_str(),
825 kVec2f_GrSLType);
826 noiseCode.append(".r;");
827 }
828
829 // Get permutation for x + 1
830 {
831 SkString xCoords("");
832 xCoords.appendf("vec2(%s.z, 0.5)", floorVal);
833
834 noiseCode.appendf("\n\t%s.y = ", latticeIdx);
835 fsBuilder->appendTextureLookup(&noiseCode, args.fSamplers[0], xCoords.c_str(),
836 kVec2f_GrSLType);
837 noiseCode.append(".r;");
838 }
839
840#if defined(SK_BUILD_FOR_ANDROID)
841 // Android rounding for Tegra devices, like, for example: Xoom (Tegra 2), Nexus 7 (Tegra 3).
842 // The issue is that colors aren't accurate enough on Tegra devices. For example, if an 8 bit
843 // value of 124 (or 0.486275 here) is entered, we can get a texture value of 123.513725
844 // (or 0.484368 here). The following rounding operation prevents these precision issues from
845 // affecting the result of the noise by making sure that we only have multiples of 1/255.
846 // (Note that 1/255 is about 0.003921569, which is the value used here).
847 noiseCode.appendf("\n\t%s = floor(%s * vec2(255.0) + vec2(0.5)) * vec2(0.003921569);",
848 latticeIdx, latticeIdx);
849#endif
850
851 // Get (x,y) coordinates with the permutated x
852 noiseCode.appendf("\n\tvec4 %s = fract(%s.xyxy + %s.yyww);", bcoords, latticeIdx, floorVal);
853
854 noiseCode.appendf("\n\n\tvec2 %s;", uv);
855 // Compute u, at offset (0,0)
856 {
857 SkString latticeCoords("");
858 latticeCoords.appendf("vec2(%s.x, %s)", bcoords, chanCoord);
859 noiseCode.appendf("\n\tvec4 %s = ", lattice);
860 fsBuilder->appendTextureLookup(&noiseCode, args.fSamplers[1], latticeCoords.c_str(),
861 kVec2f_GrSLType);
862 noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
863 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
864 }
865
866 noiseCode.appendf("\n\t%s.x -= 1.0;", fractVal);
867 // Compute v, at offset (-1,0)
868 {
869 SkString latticeCoords("");
870 latticeCoords.appendf("vec2(%s.y, %s)", bcoords, chanCoord);
871 noiseCode.append("\n\tlattice = ");
872 fsBuilder->appendTextureLookup(&noiseCode, args.fSamplers[1], latticeCoords.c_str(),
873 kVec2f_GrSLType);
874 noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
875 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
876 }
877
878 // Compute 'a' as a linear interpolation of 'u' and 'v'
879 noiseCode.appendf("\n\tvec2 %s;", ab);
880 noiseCode.appendf("\n\t%s.x = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
881
882 noiseCode.appendf("\n\t%s.y -= 1.0;", fractVal);
883 // Compute v, at offset (-1,-1)
884 {
885 SkString latticeCoords("");
886 latticeCoords.appendf("vec2(%s.w, %s)", bcoords, chanCoord);
887 noiseCode.append("\n\tlattice = ");
888 fsBuilder->appendTextureLookup(&noiseCode, args.fSamplers[1], latticeCoords.c_str(),
889 kVec2f_GrSLType);
890 noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
891 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
892 }
893
894 noiseCode.appendf("\n\t%s.x += 1.0;", fractVal);
895 // Compute u, at offset (0,-1)
896 {
897 SkString latticeCoords("");
898 latticeCoords.appendf("vec2(%s.z, %s)", bcoords, chanCoord);
899 noiseCode.append("\n\tlattice = ");
900 fsBuilder->appendTextureLookup(&noiseCode, args.fSamplers[1], latticeCoords.c_str(),
901 kVec2f_GrSLType);
902 noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
903 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
904 }
905
906 // Compute 'b' as a linear interpolation of 'u' and 'v'
907 noiseCode.appendf("\n\t%s.y = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
908 // Compute the noise as a linear interpolation of 'a' and 'b'
909 noiseCode.appendf("\n\treturn mix(%s.x, %s.y, %s.y);\n", ab, ab, noiseSmooth);
910
911 SkString noiseFuncName;
robertphillipsd3b32bf2016-02-05 07:15:39 -0800912 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800913 fsBuilder->emitFunction(kFloat_GrSLType,
914 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseStitchArgs),
915 gPerlinNoiseStitchArgs, noiseCode.c_str(), &noiseFuncName);
916 } else {
917 fsBuilder->emitFunction(kFloat_GrSLType,
918 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseArgs),
919 gPerlinNoiseArgs, noiseCode.c_str(), &noiseFuncName);
920 }
921
922 // There are rounding errors if the floor operation is not performed here
923 fsBuilder->codeAppendf("\n\t\tvec2 %s = floor(%s.xy) * %s;",
924 noiseVec, vCoords.c_str(), baseFrequencyUni);
925
926 // Clear the color accumulator
927 fsBuilder->codeAppendf("\n\t\t%s = vec4(0.0);", args.fOutputColor);
928
robertphillipsd3b32bf2016-02-05 07:15:39 -0800929 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800930 // Set up TurbulenceInitial stitch values.
931 fsBuilder->codeAppendf("\n\t\tvec2 %s = %s;", stitchData, stitchDataUni);
932 }
933
934 fsBuilder->codeAppendf("\n\t\tfloat %s = 1.0;", ratio);
935
936 // Loop over all octaves
robertphillipsd3b32bf2016-02-05 07:15:39 -0800937 fsBuilder->codeAppendf("for (int octave = 0; octave < %d; ++octave) {", pne.numOctaves());
ethannicholas417011c2015-11-09 06:35:12 -0800938
939 fsBuilder->codeAppendf("\n\t\t\t%s += ", args.fOutputColor);
robertphillipsd3b32bf2016-02-05 07:15:39 -0800940 if (pne.type() != SkPerlinNoiseShader2::kFractalNoise_Type) {
ethannicholas417011c2015-11-09 06:35:12 -0800941 fsBuilder->codeAppend("abs(");
942 }
robertphillipsd3b32bf2016-02-05 07:15:39 -0800943 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800944 fsBuilder->codeAppendf(
945 "vec4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s),"
946 "\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))",
947 noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData,
948 noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData,
949 noiseFuncName.c_str(), chanCoordB, noiseVec, stitchData,
950 noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData);
951 } else {
952 fsBuilder->codeAppendf(
953 "vec4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s),"
954 "\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))",
955 noiseFuncName.c_str(), chanCoordR, noiseVec,
956 noiseFuncName.c_str(), chanCoordG, noiseVec,
957 noiseFuncName.c_str(), chanCoordB, noiseVec,
958 noiseFuncName.c_str(), chanCoordA, noiseVec);
959 }
robertphillipsd3b32bf2016-02-05 07:15:39 -0800960 if (pne.type() != SkPerlinNoiseShader2::kFractalNoise_Type) {
ethannicholas417011c2015-11-09 06:35:12 -0800961 fsBuilder->codeAppendf(")"); // end of "abs("
962 }
963 fsBuilder->codeAppendf(" * %s;", ratio);
964
965 fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", noiseVec);
966 fsBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio);
967
robertphillipsd3b32bf2016-02-05 07:15:39 -0800968 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800969 fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", stitchData);
970 }
971 fsBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves
972
robertphillipsd3b32bf2016-02-05 07:15:39 -0800973 if (pne.type() == SkPerlinNoiseShader2::kFractalNoise_Type) {
ethannicholas417011c2015-11-09 06:35:12 -0800974 // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
975 // by fractalNoise and (turbulenceFunctionResult) by turbulence.
976 fsBuilder->codeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);",
977 args.fOutputColor,args.fOutputColor);
978 }
979
980 // Clamp values
981 fsBuilder->codeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor);
982
983 // Pre-multiply the result
984 fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
985 args.fOutputColor, args.fOutputColor,
986 args.fOutputColor, args.fOutputColor);
987}
988
989void GrGLPerlinNoise2::GenKey(const GrProcessor& processor, const GrGLSLCaps&,
egdaniel2d721d32015-11-11 13:06:05 -0800990 GrProcessorKeyBuilder* b) {
ethannicholas417011c2015-11-09 06:35:12 -0800991 const GrPerlinNoise2Effect& turbulence = processor.cast<GrPerlinNoise2Effect>();
992
993 uint32_t key = turbulence.numOctaves();
994
995 key = key << 3; // Make room for next 3 bits
996
997 switch (turbulence.type()) {
998 case SkPerlinNoiseShader2::kFractalNoise_Type:
999 key |= 0x1;
1000 break;
1001 case SkPerlinNoiseShader2::kTurbulence_Type:
1002 key |= 0x2;
1003 break;
1004 default:
1005 // leave key at 0
1006 break;
1007 }
1008
1009 if (turbulence.stitchTiles()) {
1010 key |= 0x4; // Flip the 3rd bit if tile stitching is on
1011 }
1012
1013 b->add32(key);
1014}
1015
1016void GrGLPerlinNoise2::onSetData(const GrGLSLProgramDataManager& pdman,
1017 const GrProcessor& processor) {
1018 INHERITED::onSetData(pdman, processor);
1019
1020 const GrPerlinNoise2Effect& turbulence = processor.cast<GrPerlinNoise2Effect>();
1021
1022 const SkVector& baseFrequency = turbulence.baseFrequency();
1023 pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
1024
1025 if (turbulence.stitchTiles()) {
1026 const SkPerlinNoiseShader2::StitchData& stitchData = turbulence.stitchData();
1027 pdman.set2f(fStitchDataUni, SkIntToScalar(stitchData.fWidth),
1028 SkIntToScalar(stitchData.fHeight));
1029 }
1030}
1031
1032/////////////////////////////////////////////////////////////////////
1033
egdaniel64c47282015-11-13 06:54:19 -08001034class GrGLImprovedPerlinNoise : public GrGLSLFragmentProcessor {
ethannicholas417011c2015-11-09 06:35:12 -08001035public:
robertphillipsbf536af2016-02-04 06:11:53 -08001036 void emitCode(EmitArgs&) override;
ethannicholas417011c2015-11-09 06:35:12 -08001037
robertphillipsbf536af2016-02-04 06:11:53 -08001038 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*);
ethannicholas417011c2015-11-09 06:35:12 -08001039
1040protected:
1041 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
1042
1043private:
ethannicholas417011c2015-11-09 06:35:12 -08001044 GrGLSLProgramDataManager::UniformHandle fZUni;
1045 GrGLSLProgramDataManager::UniformHandle fOctavesUni;
1046 GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni;
1047
egdaniel64c47282015-11-13 06:54:19 -08001048 typedef GrGLSLFragmentProcessor INHERITED;
ethannicholas417011c2015-11-09 06:35:12 -08001049};
1050
1051/////////////////////////////////////////////////////////////////////
1052
1053class GrImprovedPerlinNoiseEffect : public GrFragmentProcessor {
1054public:
egdaniel478c04e2015-11-09 07:40:49 -08001055 static GrFragmentProcessor* Create(int octaves, SkScalar z,
ethannicholas417011c2015-11-09 06:35:12 -08001056 SkPerlinNoiseShader2::PaintingData* paintingData,
1057 GrTexture* permutationsTexture, GrTexture* gradientTexture,
1058 const SkMatrix& matrix) {
1059 return new GrImprovedPerlinNoiseEffect(octaves, z, paintingData, permutationsTexture,
1060 gradientTexture, matrix);
1061 }
1062
1063 virtual ~GrImprovedPerlinNoiseEffect() { delete fPaintingData; }
1064
1065 const char* name() const override { return "ImprovedPerlinNoise"; }
1066
1067 const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; }
1068 SkScalar z() const { return fZ; }
1069 int octaves() const { return fOctaves; }
1070 const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
1071
1072private:
egdaniel57d3b032015-11-13 11:57:27 -08001073 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
robertphillipsbf536af2016-02-04 06:11:53 -08001074 return new GrGLImprovedPerlinNoise;
ethannicholas417011c2015-11-09 06:35:12 -08001075 }
1076
robertphillipsbf536af2016-02-04 06:11:53 -08001077 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
ethannicholas417011c2015-11-09 06:35:12 -08001078 GrGLImprovedPerlinNoise::GenKey(*this, caps, b);
1079 }
1080
1081 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
1082 const GrImprovedPerlinNoiseEffect& s = sBase.cast<GrImprovedPerlinNoiseEffect>();
1083 return fZ == fZ &&
1084 fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency;
1085 }
1086
1087 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
1088 inout->setToUnknown(GrInvariantOutput::kWillNot_ReadInput);
1089 }
1090
1091 GrImprovedPerlinNoiseEffect(int octaves, SkScalar z,
1092 SkPerlinNoiseShader2::PaintingData* paintingData,
1093 GrTexture* permutationsTexture, GrTexture* gradientTexture,
1094 const SkMatrix& matrix)
1095 : fOctaves(octaves)
1096 , fZ(z)
1097 , fPermutationsAccess(permutationsTexture)
1098 , fGradientAccess(gradientTexture)
1099 , fPaintingData(paintingData) {
1100 this->initClassID<GrImprovedPerlinNoiseEffect>();
1101 this->addTextureAccess(&fPermutationsAccess);
1102 this->addTextureAccess(&fGradientAccess);
1103 fCoordTransform.reset(kLocal_GrCoordSet, matrix);
1104 this->addCoordTransform(&fCoordTransform);
1105 }
1106
1107 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
1108
1109 GrCoordTransform fCoordTransform;
1110 int fOctaves;
1111 SkScalar fZ;
1112 GrTextureAccess fPermutationsAccess;
1113 GrTextureAccess fGradientAccess;
1114 SkPerlinNoiseShader2::PaintingData *fPaintingData;
1115
1116private:
1117 typedef GrFragmentProcessor INHERITED;
1118};
1119
1120/////////////////////////////////////////////////////////////////////
1121GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrImprovedPerlinNoiseEffect);
1122
1123const GrFragmentProcessor* GrImprovedPerlinNoiseEffect::TestCreate(GrProcessorTestData* d) {
1124 SkScalar baseFrequencyX = d->fRandom->nextRangeScalar(0.01f,
1125 0.99f);
1126 SkScalar baseFrequencyY = d->fRandom->nextRangeScalar(0.01f,
1127 0.99f);
1128 int numOctaves = d->fRandom->nextRangeU(2, 10);
1129 SkScalar z = SkIntToScalar(d->fRandom->nextU());
1130
reed8a21c9f2016-03-08 18:50:00 -08001131 sk_sp<SkShader> shader(SkPerlinNoiseShader2::MakeImprovedNoise(baseFrequencyX,
1132 baseFrequencyY,
1133 numOctaves,
1134 z));
ethannicholas417011c2015-11-09 06:35:12 -08001135
1136 GrPaint grPaint;
1137 return shader->asFragmentProcessor(d->fContext,
1138 GrTest::TestMatrix(d->fRandom), nullptr,
1139 kNone_SkFilterQuality);
1140}
1141
ethannicholas417011c2015-11-09 06:35:12 -08001142void GrGLImprovedPerlinNoise::emitCode(EmitArgs& args) {
egdaniel4ca2e602015-11-18 08:01:26 -08001143 GrGLSLFragmentBuilder* fsBuilder = args.fFragBuilder;
egdaniel7ea439b2015-12-03 09:20:44 -08001144 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
ethannicholas417011c2015-11-09 06:35:12 -08001145 SkString vCoords = fsBuilder->ensureFSCoords2D(args.fCoords, 0);
1146
cdalton5e58cee2016-02-11 12:49:47 -08001147 fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001148 kVec2f_GrSLType, kDefault_GrSLPrecision,
1149 "baseFrequency");
1150 const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);
ethannicholas417011c2015-11-09 06:35:12 -08001151
cdalton5e58cee2016-02-11 12:49:47 -08001152 fOctavesUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001153 kFloat_GrSLType, kDefault_GrSLPrecision,
1154 "octaves");
1155 const char* octavesUni = uniformHandler->getUniformCStr(fOctavesUni);
ethannicholas417011c2015-11-09 06:35:12 -08001156
cdalton5e58cee2016-02-11 12:49:47 -08001157 fZUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001158 kFloat_GrSLType, kDefault_GrSLPrecision,
1159 "z");
1160 const char* zUni = uniformHandler->getUniformCStr(fZUni);
ethannicholas417011c2015-11-09 06:35:12 -08001161
1162 // fade function
1163 static const GrGLSLShaderVar fadeArgs[] = {
1164 GrGLSLShaderVar("t", kVec3f_GrSLType)
1165 };
1166 SkString fadeFuncName;
1167 fsBuilder->emitFunction(kVec3f_GrSLType, "fade", SK_ARRAY_COUNT(fadeArgs),
1168 fadeArgs,
1169 "return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);",
1170 &fadeFuncName);
1171
1172 // perm function
1173 static const GrGLSLShaderVar permArgs[] = {
1174 GrGLSLShaderVar("x", kFloat_GrSLType)
1175 };
1176 SkString permFuncName;
1177 SkString permCode("return ");
1178 // FIXME even though I'm creating these textures with kRepeat_TileMode, they're clamped. Not
1179 // sure why. Using fract() (here and the next texture lookup) as a workaround.
1180 fsBuilder->appendTextureLookup(&permCode, args.fSamplers[0], "vec2(fract(x / 256.0), 0.0)",
1181 kVec2f_GrSLType);
1182 permCode.append(".r * 255.0;");
1183 fsBuilder->emitFunction(kFloat_GrSLType, "perm", SK_ARRAY_COUNT(permArgs), permArgs,
1184 permCode.c_str(), &permFuncName);
1185
1186 // grad function
1187 static const GrGLSLShaderVar gradArgs[] = {
1188 GrGLSLShaderVar("x", kFloat_GrSLType),
1189 GrGLSLShaderVar("p", kVec3f_GrSLType)
1190 };
1191 SkString gradFuncName;
1192 SkString gradCode("return dot(");
1193 fsBuilder->appendTextureLookup(&gradCode, args.fSamplers[1], "vec2(fract(x / 16.0), 0.0)",
1194 kVec2f_GrSLType);
1195 gradCode.append(".rgb * 255.0 - vec3(1.0), p);");
1196 fsBuilder->emitFunction(kFloat_GrSLType, "grad", SK_ARRAY_COUNT(gradArgs), gradArgs,
1197 gradCode.c_str(), &gradFuncName);
1198
1199 // lerp function
1200 static const GrGLSLShaderVar lerpArgs[] = {
1201 GrGLSLShaderVar("a", kFloat_GrSLType),
1202 GrGLSLShaderVar("b", kFloat_GrSLType),
1203 GrGLSLShaderVar("w", kFloat_GrSLType)
1204 };
1205 SkString lerpFuncName;
1206 fsBuilder->emitFunction(kFloat_GrSLType, "lerp", SK_ARRAY_COUNT(lerpArgs), lerpArgs,
1207 "return a + w * (b - a);", &lerpFuncName);
1208
1209 // noise function
1210 static const GrGLSLShaderVar noiseArgs[] = {
1211 GrGLSLShaderVar("p", kVec3f_GrSLType),
1212 };
1213 SkString noiseFuncName;
1214 SkString noiseCode;
1215 noiseCode.append("vec3 P = mod(floor(p), 256.0);");
1216 noiseCode.append("p -= floor(p);");
1217 noiseCode.appendf("vec3 f = %s(p);", fadeFuncName.c_str());
1218 noiseCode.appendf("float A = %s(P.x) + P.y;", permFuncName.c_str());
1219 noiseCode.appendf("float AA = %s(A) + P.z;", permFuncName.c_str());
1220 noiseCode.appendf("float AB = %s(A + 1.0) + P.z;", permFuncName.c_str());
1221 noiseCode.appendf("float B = %s(P.x + 1.0) + P.y;", permFuncName.c_str());
1222 noiseCode.appendf("float BA = %s(B) + P.z;", permFuncName.c_str());
1223 noiseCode.appendf("float BB = %s(B + 1.0) + P.z;", permFuncName.c_str());
1224 noiseCode.appendf("float result = %s(", lerpFuncName.c_str());
1225 noiseCode.appendf("%s(%s(%s(%s(AA), p),", lerpFuncName.c_str(), lerpFuncName.c_str(),
1226 gradFuncName.c_str(), permFuncName.c_str());
1227 noiseCode.appendf("%s(%s(BA), p + vec3(-1.0, 0.0, 0.0)), f.x),", gradFuncName.c_str(),
1228 permFuncName.c_str());
1229 noiseCode.appendf("%s(%s(%s(AB), p + vec3(0.0, -1.0, 0.0)),", lerpFuncName.c_str(),
1230 gradFuncName.c_str(), permFuncName.c_str());
1231 noiseCode.appendf("%s(%s(BB), p + vec3(-1.0, -1.0, 0.0)), f.x), f.y),",
1232 gradFuncName.c_str(), permFuncName.c_str());
1233 noiseCode.appendf("%s(%s(%s(%s(AA + 1.0), p + vec3(0.0, 0.0, -1.0)),",
1234 lerpFuncName.c_str(), lerpFuncName.c_str(), gradFuncName.c_str(),
1235 permFuncName.c_str());
1236 noiseCode.appendf("%s(%s(BA + 1.0), p + vec3(-1.0, 0.0, -1.0)), f.x),",
1237 gradFuncName.c_str(), permFuncName.c_str());
1238 noiseCode.appendf("%s(%s(%s(AB + 1.0), p + vec3(0.0, -1.0, -1.0)),",
1239 lerpFuncName.c_str(), gradFuncName.c_str(), permFuncName.c_str());
1240 noiseCode.appendf("%s(%s(BB + 1.0), p + vec3(-1.0, -1.0, -1.0)), f.x), f.y), f.z);",
1241 gradFuncName.c_str(), permFuncName.c_str());
1242 noiseCode.append("return result;");
1243 fsBuilder->emitFunction(kFloat_GrSLType, "noise", SK_ARRAY_COUNT(noiseArgs), noiseArgs,
1244 noiseCode.c_str(), &noiseFuncName);
1245
1246 // noiseOctaves function
1247 static const GrGLSLShaderVar noiseOctavesArgs[] = {
1248 GrGLSLShaderVar("p", kVec3f_GrSLType),
1249 GrGLSLShaderVar("octaves", kFloat_GrSLType),
1250 };
1251 SkString noiseOctavesFuncName;
1252 SkString noiseOctavesCode;
1253 noiseOctavesCode.append("float result = 0.0;");
1254 noiseOctavesCode.append("float ratio = 1.0;");
1255 noiseOctavesCode.append("for (float i = 0.0; i < octaves; i++) {");
1256 noiseOctavesCode.appendf("result += %s(p) / ratio;", noiseFuncName.c_str());
1257 noiseOctavesCode.append("p *= 2.0;");
1258 noiseOctavesCode.append("ratio *= 2.0;");
1259 noiseOctavesCode.append("}");
1260 noiseOctavesCode.append("return (result + 1.0) / 2.0;");
1261 fsBuilder->emitFunction(kFloat_GrSLType, "noiseOctaves", SK_ARRAY_COUNT(noiseOctavesArgs),
1262 noiseOctavesArgs, noiseOctavesCode.c_str(), &noiseOctavesFuncName);
1263
1264 fsBuilder->codeAppendf("vec2 coords = %s * %s;", vCoords.c_str(), baseFrequencyUni);
1265 fsBuilder->codeAppendf("float r = %s(vec3(coords, %s), %s);", noiseOctavesFuncName.c_str(),
1266 zUni, octavesUni);
egdaniel478c04e2015-11-09 07:40:49 -08001267 fsBuilder->codeAppendf("float g = %s(vec3(coords, %s + 0000.0), %s);",
ethannicholas417011c2015-11-09 06:35:12 -08001268 noiseOctavesFuncName.c_str(), zUni, octavesUni);
egdaniel478c04e2015-11-09 07:40:49 -08001269 fsBuilder->codeAppendf("float b = %s(vec3(coords, %s + 0000.0), %s);",
ethannicholas417011c2015-11-09 06:35:12 -08001270 noiseOctavesFuncName.c_str(), zUni, octavesUni);
egdaniel478c04e2015-11-09 07:40:49 -08001271 fsBuilder->codeAppendf("float a = %s(vec3(coords, %s + 0000.0), %s);",
ethannicholas417011c2015-11-09 06:35:12 -08001272 noiseOctavesFuncName.c_str(), zUni, octavesUni);
1273 fsBuilder->codeAppendf("%s = vec4(r, g, b, a);", args.fOutputColor);
1274
1275 // Clamp values
1276 fsBuilder->codeAppendf("%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor);
1277
1278 // Pre-multiply the result
1279 fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
1280 args.fOutputColor, args.fOutputColor,
1281 args.fOutputColor, args.fOutputColor);
1282}
1283
1284void GrGLImprovedPerlinNoise::GenKey(const GrProcessor& processor, const GrGLSLCaps&,
1285 GrProcessorKeyBuilder* b) {
1286}
1287
1288void GrGLImprovedPerlinNoise::onSetData(const GrGLSLProgramDataManager& pdman,
1289 const GrProcessor& processor) {
1290 INHERITED::onSetData(pdman, processor);
1291
1292 const GrImprovedPerlinNoiseEffect& noise = processor.cast<GrImprovedPerlinNoiseEffect>();
1293
1294 const SkVector& baseFrequency = noise.baseFrequency();
1295 pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
1296
egdaniel478c04e2015-11-09 07:40:49 -08001297 pdman.set1f(fOctavesUni, SkIntToScalar(noise.octaves()));
ethannicholas417011c2015-11-09 06:35:12 -08001298
1299 pdman.set1f(fZUni, noise.z());
1300}
1301
1302/////////////////////////////////////////////////////////////////////
1303const GrFragmentProcessor* SkPerlinNoiseShader2::asFragmentProcessor(
1304 GrContext* context,
1305 const SkMatrix& viewM,
1306 const SkMatrix* externalLocalMatrix,
1307 SkFilterQuality) const {
1308 SkASSERT(context);
1309
1310 SkMatrix localMatrix = this->getLocalMatrix();
1311 if (externalLocalMatrix) {
1312 localMatrix.preConcat(*externalLocalMatrix);
1313 }
1314
1315 SkMatrix matrix = viewM;
1316 matrix.preConcat(localMatrix);
1317
1318 // Either we don't stitch tiles, either we have a valid tile size
1319 SkASSERT(!fStitchTiles || !fTileSize.isEmpty());
1320
1321 SkPerlinNoiseShader2::PaintingData* paintingData =
1322 new PaintingData(fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY, matrix);
1323
1324 SkMatrix m = viewM;
1325 m.setTranslateX(-localMatrix.getTranslateX() + SK_Scalar1);
1326 m.setTranslateY(-localMatrix.getTranslateY() + SK_Scalar1);
1327
1328 if (fType == kImprovedNoise_Type) {
1329 GrTextureParams textureParams(SkShader::TileMode::kRepeat_TileMode,
1330 GrTextureParams::FilterMode::kNone_FilterMode);
1331 SkAutoTUnref<GrTexture> permutationsTexture(
1332 GrRefCachedBitmapTexture(context, paintingData->getImprovedPermutationsBitmap(),
1333 textureParams));
1334 SkAutoTUnref<GrTexture> gradientTexture(
1335 GrRefCachedBitmapTexture(context, paintingData->getGradientBitmap(),
1336 textureParams));
1337 return GrImprovedPerlinNoiseEffect::Create(fNumOctaves, fSeed, paintingData,
1338 permutationsTexture, gradientTexture, m);
1339 }
1340
1341 if (0 == fNumOctaves) {
1342 if (kFractalNoise_Type == fType) {
1343 // Extract the incoming alpha and emit rgba = (a/4, a/4, a/4, a/2)
1344 SkAutoTUnref<const GrFragmentProcessor> inner(
1345 GrConstColorProcessor::Create(0x80404040,
1346 GrConstColorProcessor::kModulateRGBA_InputMode));
1347 return GrFragmentProcessor::MulOutputByInputAlpha(inner);
1348 }
1349 // Emit zero.
1350 return GrConstColorProcessor::Create(0x0, GrConstColorProcessor::kIgnore_InputMode);
1351 }
1352
1353 SkAutoTUnref<GrTexture> permutationsTexture(
1354 GrRefCachedBitmapTexture(context, paintingData->getPermutationsBitmap(),
1355 GrTextureParams::ClampNoFilter()));
1356 SkAutoTUnref<GrTexture> noiseTexture(
1357 GrRefCachedBitmapTexture(context, paintingData->getNoiseBitmap(),
1358 GrTextureParams::ClampNoFilter()));
1359
1360 if ((permutationsTexture) && (noiseTexture)) {
1361 SkAutoTUnref<GrFragmentProcessor> inner(
1362 GrPerlinNoise2Effect::Create(fType,
1363 fNumOctaves,
1364 fStitchTiles,
1365 paintingData,
1366 permutationsTexture, noiseTexture,
1367 m));
1368 return GrFragmentProcessor::MulOutputByInputAlpha(inner);
1369 }
1370 delete paintingData;
1371 return nullptr;
1372}
1373
1374#endif
1375
1376#ifndef SK_IGNORE_TO_STRING
1377void SkPerlinNoiseShader2::toString(SkString* str) const {
1378 str->append("SkPerlinNoiseShader2: (");
1379
1380 str->append("type: ");
1381 switch (fType) {
1382 case kFractalNoise_Type:
1383 str->append("\"fractal noise\"");
1384 break;
1385 case kTurbulence_Type:
1386 str->append("\"turbulence\"");
1387 break;
1388 default:
1389 str->append("\"unknown\"");
1390 break;
1391 }
1392 str->append(" base frequency: (");
1393 str->appendScalar(fBaseFrequencyX);
1394 str->append(", ");
1395 str->appendScalar(fBaseFrequencyY);
1396 str->append(") number of octaves: ");
1397 str->appendS32(fNumOctaves);
1398 str->append(" seed: ");
1399 str->appendScalar(fSeed);
1400 str->append(" stitch tiles: ");
1401 str->append(fStitchTiles ? "true " : "false ");
1402
1403 this->INHERITED::toString(str);
1404
1405 str->append(")");
1406}
1407#endif