blob: 2c2f65e58fe8d81d76badd4477fb5c089f85a742 [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
reed60c9b582016-04-03 09:11:13 -0700355sk_sp<SkFlattenable> SkPerlinNoiseShader2::CreateProc(SkReadBuffer& buffer) {
ethannicholas417011c2015-11-09 06:35:12 -0800356 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:
reed60c9b582016-04-03 09:11:13 -0700367 return SkPerlinNoiseShader2::MakeFractalNoise(freqX, freqY, octaves, seed, &tileSize);
ethannicholas417011c2015-11-09 06:35:12 -0800368 case kTurbulence_Type:
reed60c9b582016-04-03 09:11:13 -0700369 return SkPerlinNoiseShader2::MakeTubulence(freqX, freqY, octaves, seed, &tileSize);
ethannicholas417011c2015-11-09 06:35:12 -0800370 case kImprovedNoise_Type:
reed60c9b582016-04-03 09:11:13 -0700371 return SkPerlinNoiseShader2::MakeImprovedNoise(freqX, freqY, octaves, seed);
ethannicholas417011c2015-11-09 06:35:12 -0800372 default:
373 return nullptr;
374 }
375}
376
377void SkPerlinNoiseShader2::flatten(SkWriteBuffer& buffer) const {
378 buffer.writeInt((int) fType);
379 buffer.writeScalar(fBaseFrequencyX);
380 buffer.writeScalar(fBaseFrequencyY);
381 buffer.writeInt(fNumOctaves);
382 buffer.writeScalar(fSeed);
383 buffer.writeInt(fTileSize.fWidth);
384 buffer.writeInt(fTileSize.fHeight);
385}
386
387SkScalar SkPerlinNoiseShader2::PerlinNoiseShaderContext::noise2D(
388 int channel, const StitchData& stitchData, const SkPoint& noiseVector) const {
389 struct Noise {
390 int noisePositionIntegerValue;
391 int nextNoisePositionIntegerValue;
392 SkScalar noisePositionFractionValue;
393 Noise(SkScalar component)
394 {
395 SkScalar position = component + kPerlinNoise;
396 noisePositionIntegerValue = SkScalarFloorToInt(position);
397 noisePositionFractionValue = position - SkIntToScalar(noisePositionIntegerValue);
398 nextNoisePositionIntegerValue = noisePositionIntegerValue + 1;
399 }
400 };
401 Noise noiseX(noiseVector.x());
402 Noise noiseY(noiseVector.y());
403 SkScalar u, v;
404 const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNoiseShader2&>(fShader);
405 // If stitching, adjust lattice points accordingly.
406 if (perlinNoiseShader.fStitchTiles) {
407 noiseX.noisePositionIntegerValue =
408 checkNoise(noiseX.noisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth);
409 noiseY.noisePositionIntegerValue =
410 checkNoise(noiseY.noisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight);
411 noiseX.nextNoisePositionIntegerValue =
412 checkNoise(noiseX.nextNoisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth);
413 noiseY.nextNoisePositionIntegerValue =
414 checkNoise(noiseY.nextNoisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight);
415 }
416 noiseX.noisePositionIntegerValue &= kBlockMask;
417 noiseY.noisePositionIntegerValue &= kBlockMask;
418 noiseX.nextNoisePositionIntegerValue &= kBlockMask;
419 noiseY.nextNoisePositionIntegerValue &= kBlockMask;
420 int i =
421 fPaintingData->fLatticeSelector[noiseX.noisePositionIntegerValue];
422 int j =
423 fPaintingData->fLatticeSelector[noiseX.nextNoisePositionIntegerValue];
424 int b00 = (i + noiseY.noisePositionIntegerValue) & kBlockMask;
425 int b10 = (j + noiseY.noisePositionIntegerValue) & kBlockMask;
426 int b01 = (i + noiseY.nextNoisePositionIntegerValue) & kBlockMask;
427 int b11 = (j + noiseY.nextNoisePositionIntegerValue) & kBlockMask;
428 SkScalar sx = smoothCurve(noiseX.noisePositionFractionValue);
429 SkScalar sy = smoothCurve(noiseY.noisePositionFractionValue);
430 // This is taken 1:1 from SVG spec: http://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement
431 SkPoint fractionValue = SkPoint::Make(noiseX.noisePositionFractionValue,
432 noiseY.noisePositionFractionValue); // Offset (0,0)
433 u = fPaintingData->fGradient[channel][b00].dot(fractionValue);
434 fractionValue.fX -= SK_Scalar1; // Offset (-1,0)
435 v = fPaintingData->fGradient[channel][b10].dot(fractionValue);
436 SkScalar a = SkScalarInterp(u, v, sx);
437 fractionValue.fY -= SK_Scalar1; // Offset (-1,-1)
438 v = fPaintingData->fGradient[channel][b11].dot(fractionValue);
439 fractionValue.fX = noiseX.noisePositionFractionValue; // Offset (0,-1)
440 u = fPaintingData->fGradient[channel][b01].dot(fractionValue);
441 SkScalar b = SkScalarInterp(u, v, sx);
442 return SkScalarInterp(a, b, sy);
443}
444
445SkScalar SkPerlinNoiseShader2::PerlinNoiseShaderContext::calculateTurbulenceValueForPoint(
446 int channel, StitchData& stitchData, const SkPoint& point) const {
447 const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNoiseShader2&>(fShader);
448 if (perlinNoiseShader.fStitchTiles) {
449 // Set up TurbulenceInitial stitch values.
450 stitchData = fPaintingData->fStitchDataInit;
451 }
452 SkScalar turbulenceFunctionResult = 0;
453 SkPoint noiseVector(SkPoint::Make(SkScalarMul(point.x(), fPaintingData->fBaseFrequency.fX),
454 SkScalarMul(point.y(), fPaintingData->fBaseFrequency.fY)));
455 SkScalar ratio = SK_Scalar1;
456 for (int octave = 0; octave < perlinNoiseShader.fNumOctaves; ++octave) {
457 SkScalar noise = noise2D(channel, stitchData, noiseVector);
458 SkScalar numer = (perlinNoiseShader.fType == kFractalNoise_Type) ?
459 noise : SkScalarAbs(noise);
460 turbulenceFunctionResult += numer / ratio;
461 noiseVector.fX *= 2;
462 noiseVector.fY *= 2;
463 ratio *= 2;
464 if (perlinNoiseShader.fStitchTiles) {
465 // Update stitch values
466 stitchData.fWidth *= 2;
467 stitchData.fWrapX = stitchData.fWidth + kPerlinNoise;
468 stitchData.fHeight *= 2;
469 stitchData.fWrapY = stitchData.fHeight + kPerlinNoise;
470 }
471 }
472
473 // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
474 // by fractalNoise and (turbulenceFunctionResult) by turbulence.
475 if (perlinNoiseShader.fType == kFractalNoise_Type) {
476 turbulenceFunctionResult =
477 SkScalarMul(turbulenceFunctionResult, SK_ScalarHalf) + SK_ScalarHalf;
478 }
479
480 if (channel == 3) { // Scale alpha by paint value
481 turbulenceFunctionResult *= SkIntToScalar(getPaintAlpha()) / 255;
482 }
483
484 // Clamp result
485 return SkScalarPin(turbulenceFunctionResult, 0, SK_Scalar1);
486}
487
488////////////////////////////////////////////////////////////////////////////////////////////////////
489// Improved Perlin Noise based on Java implementation found at http://mrl.nyu.edu/~perlin/noise/
490static SkScalar fade(SkScalar t) {
491 return t * t * t * (t * (t * 6 - 15) + 10);
492}
493
494static SkScalar lerp(SkScalar t, SkScalar a, SkScalar b) {
495 return a + t * (b - a);
496}
497
498static SkScalar grad(int hash, SkScalar x, SkScalar y, SkScalar z) {
499 int h = hash & 15;
500 SkScalar u = h < 8 ? x : y;
501 SkScalar v = h < 4 ? y : h == 12 || h == 14 ? x : z;
502 return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
503}
504
505SkScalar SkPerlinNoiseShader2::PerlinNoiseShaderContext::calculateImprovedNoiseValueForPoint(
506 int channel, const SkPoint& point) const {
507 const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNoiseShader2&>(fShader);
508 SkScalar x = point.fX * perlinNoiseShader.fBaseFrequencyX;
509 SkScalar y = point.fY * perlinNoiseShader.fBaseFrequencyY;
510 // z offset between different channels, chosen arbitrarily
511 static const SkScalar CHANNEL_DELTA = 1000.0f;
512 SkScalar z = channel * CHANNEL_DELTA + perlinNoiseShader.fSeed;
513 SkScalar result = 0;
514 SkScalar ratio = SK_Scalar1;
515 for (int i = 0; i < perlinNoiseShader.fNumOctaves; i++) {
516 int X = SkScalarFloorToInt(x) & 255;
517 int Y = SkScalarFloorToInt(y) & 255;
518 int Z = SkScalarFloorToInt(z) & 255;
519 SkScalar px = x - SkScalarFloorToScalar(x);
520 SkScalar py = y - SkScalarFloorToScalar(y);
521 SkScalar pz = z - SkScalarFloorToScalar(z);
522 SkScalar u = fade(px);
523 SkScalar v = fade(py);
524 SkScalar w = fade(pz);
525 uint8_t* permutations = improved_noise_permutations;
526 int A = permutations[X] + Y;
527 int AA = permutations[A] + Z;
528 int AB = permutations[A + 1] + Z;
529 int B = permutations[X + 1] + Y;
530 int BA = permutations[B] + Z;
531 int BB = permutations[B + 1] + Z;
532 result += lerp(w, lerp(v, lerp(u, grad(permutations[AA ], px , py , pz ),
533 grad(permutations[BA ], px - 1, py , pz )),
534 lerp(u, grad(permutations[AB ], px , py - 1, pz ),
535 grad(permutations[BB ], px - 1, py - 1, pz ))),
536 lerp(v, lerp(u, grad(permutations[AA + 1], px , py , pz - 1),
537 grad(permutations[BA + 1], px - 1, py , pz - 1)),
538 lerp(u, grad(permutations[AB + 1], px , py - 1, pz - 1),
539 grad(permutations[BB + 1], px - 1, py - 1, pz - 1)))) /
540 ratio;
541 x *= 2;
542 y *= 2;
543 ratio *= 2;
544 }
545 result = SkScalarClampMax((result + 1.0f) / 2.0f, 1.0f);
546 return result;
547}
548////////////////////////////////////////////////////////////////////////////////////////////////////
549
550SkPMColor SkPerlinNoiseShader2::PerlinNoiseShaderContext::shade(
551 const SkPoint& point, StitchData& stitchData) const {
552 const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNoiseShader2&>(fShader);
553 SkPoint newPoint;
554 fMatrix.mapPoints(&newPoint, &point, 1);
555 newPoint.fX = SkScalarRoundToScalar(newPoint.fX);
556 newPoint.fY = SkScalarRoundToScalar(newPoint.fY);
557
558 U8CPU rgba[4];
559 for (int channel = 3; channel >= 0; --channel) {
560 SkScalar value;
561 if (perlinNoiseShader.fType == kImprovedNoise_Type) {
562 value = calculateImprovedNoiseValueForPoint(channel, newPoint);
563 }
564 else {
565 value = calculateTurbulenceValueForPoint(channel, stitchData, newPoint);
566 }
567 rgba[channel] = SkScalarFloorToInt(255 * value);
568 }
569 return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]);
570}
571
572SkShader::Context* SkPerlinNoiseShader2::onCreateContext(const ContextRec& rec,
573 void* storage) const {
574 return new (storage) PerlinNoiseShaderContext(*this, rec);
575}
576
reed773ceda2016-03-03 18:18:25 -0800577size_t SkPerlinNoiseShader2::onContextSize(const ContextRec&) const {
reeda0cee5f2016-03-04 07:38:11 -0800578 return sizeof(PerlinNoiseShaderContext);
ethannicholas417011c2015-11-09 06:35:12 -0800579}
580
581SkPerlinNoiseShader2::PerlinNoiseShaderContext::PerlinNoiseShaderContext(
582 const SkPerlinNoiseShader2& shader, const ContextRec& rec)
583 : INHERITED(shader, rec)
584{
585 SkMatrix newMatrix = *rec.fMatrix;
586 newMatrix.preConcat(shader.getLocalMatrix());
587 if (rec.fLocalMatrix) {
588 newMatrix.preConcat(*rec.fLocalMatrix);
589 }
590 // This (1,1) translation is due to WebKit's 1 based coordinates for the noise
591 // (as opposed to 0 based, usually). The same adjustment is in the setData() function.
592 fMatrix.setTranslate(-newMatrix.getTranslateX() + SK_Scalar1, -newMatrix.getTranslateY() + SK_Scalar1);
593 fPaintingData = new PaintingData(shader.fTileSize, shader.fSeed, shader.fBaseFrequencyX,
594 shader.fBaseFrequencyY, newMatrix);
595}
596
597SkPerlinNoiseShader2::PerlinNoiseShaderContext::~PerlinNoiseShaderContext() { delete fPaintingData; }
598
599void SkPerlinNoiseShader2::PerlinNoiseShaderContext::shadeSpan(
600 int x, int y, SkPMColor result[], int count) {
601 SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y));
602 StitchData stitchData;
603 for (int i = 0; i < count; ++i) {
604 result[i] = shade(point, stitchData);
605 point.fX += SK_Scalar1;
606 }
607}
608
ethannicholas417011c2015-11-09 06:35:12 -0800609/////////////////////////////////////////////////////////////////////
610
611#if SK_SUPPORT_GPU
612
egdaniel64c47282015-11-13 06:54:19 -0800613class GrGLPerlinNoise2 : public GrGLSLFragmentProcessor {
ethannicholas417011c2015-11-09 06:35:12 -0800614public:
robertphillipsbf536af2016-02-04 06:11:53 -0800615 void emitCode(EmitArgs&) override;
ethannicholas417011c2015-11-09 06:35:12 -0800616
617 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder* b);
618
619protected:
620 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
621
622private:
ethannicholas417011c2015-11-09 06:35:12 -0800623 GrGLSLProgramDataManager::UniformHandle fStitchDataUni;
ethannicholas417011c2015-11-09 06:35:12 -0800624 GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni;
625
egdaniel64c47282015-11-13 06:54:19 -0800626 typedef GrGLSLFragmentProcessor INHERITED;
ethannicholas417011c2015-11-09 06:35:12 -0800627};
628
629/////////////////////////////////////////////////////////////////////
630
631class GrPerlinNoise2Effect : public GrFragmentProcessor {
632public:
bungeman06ca8ec2016-06-09 08:01:03 -0700633 static sk_sp<GrFragmentProcessor> Make(SkPerlinNoiseShader2::Type type,
634 int numOctaves, bool stitchTiles,
635 SkPerlinNoiseShader2::PaintingData* paintingData,
636 GrTexture* permutationsTexture, GrTexture* noiseTexture,
637 const SkMatrix& matrix) {
638 return sk_sp<GrFragmentProcessor>(
639 new GrPerlinNoise2Effect(type, numOctaves, stitchTiles, paintingData,
640 permutationsTexture, noiseTexture, matrix));
ethannicholas417011c2015-11-09 06:35:12 -0800641 }
642
643 virtual ~GrPerlinNoise2Effect() { delete fPaintingData; }
644
645 const char* name() const override { return "PerlinNoise"; }
646
647 const SkPerlinNoiseShader2::StitchData& stitchData() const { return fPaintingData->fStitchDataInit; }
648
649 SkPerlinNoiseShader2::Type type() const { return fType; }
650 bool stitchTiles() const { return fStitchTiles; }
651 const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; }
652 int numOctaves() const { return fNumOctaves; }
653 const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
654
655private:
egdaniel57d3b032015-11-13 11:57:27 -0800656 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
robertphillipsd3b32bf2016-02-05 07:15:39 -0800657 return new GrGLPerlinNoise2;
ethannicholas417011c2015-11-09 06:35:12 -0800658 }
659
egdaniel57d3b032015-11-13 11:57:27 -0800660 virtual void onGetGLSLProcessorKey(const GrGLSLCaps& caps,
661 GrProcessorKeyBuilder* b) const override {
ethannicholas417011c2015-11-09 06:35:12 -0800662 GrGLPerlinNoise2::GenKey(*this, caps, b);
663 }
664
665 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
666 const GrPerlinNoise2Effect& s = sBase.cast<GrPerlinNoise2Effect>();
667 return fType == s.fType &&
668 fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency &&
669 fNumOctaves == s.fNumOctaves &&
670 fStitchTiles == s.fStitchTiles &&
671 fPaintingData->fStitchDataInit == s.fPaintingData->fStitchDataInit;
672 }
673
674 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
675 inout->setToUnknown(GrInvariantOutput::kWillNot_ReadInput);
676 }
677
678 GrPerlinNoise2Effect(SkPerlinNoiseShader2::Type type,
679 int numOctaves, bool stitchTiles,
680 SkPerlinNoiseShader2::PaintingData* paintingData,
681 GrTexture* permutationsTexture, GrTexture* noiseTexture,
682 const SkMatrix& matrix)
683 : fType(type)
684 , fNumOctaves(numOctaves)
685 , fStitchTiles(stitchTiles)
686 , fPermutationsAccess(permutationsTexture)
687 , fNoiseAccess(noiseTexture)
688 , fPaintingData(paintingData) {
689 this->initClassID<GrPerlinNoise2Effect>();
690 this->addTextureAccess(&fPermutationsAccess);
691 this->addTextureAccess(&fNoiseAccess);
692 fCoordTransform.reset(kLocal_GrCoordSet, matrix);
693 this->addCoordTransform(&fCoordTransform);
694 }
695
696 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
697
698 SkPerlinNoiseShader2::Type fType;
699 GrCoordTransform fCoordTransform;
700 int fNumOctaves;
701 bool fStitchTiles;
702 GrTextureAccess fPermutationsAccess;
703 GrTextureAccess fNoiseAccess;
704 SkPerlinNoiseShader2::PaintingData *fPaintingData;
705
706private:
707 typedef GrFragmentProcessor INHERITED;
708};
709
710/////////////////////////////////////////////////////////////////////
711GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrPerlinNoise2Effect);
712
bungeman06ca8ec2016-06-09 08:01:03 -0700713sk_sp<GrFragmentProcessor> GrPerlinNoise2Effect::TestCreate(GrProcessorTestData* d) {
ethannicholas417011c2015-11-09 06:35:12 -0800714 int numOctaves = d->fRandom->nextRangeU(2, 10);
715 bool stitchTiles = d->fRandom->nextBool();
716 SkScalar seed = SkIntToScalar(d->fRandom->nextU());
717 SkISize tileSize = SkISize::Make(d->fRandom->nextRangeU(4, 4096),
718 d->fRandom->nextRangeU(4, 4096));
719 SkScalar baseFrequencyX = d->fRandom->nextRangeScalar(0.01f,
720 0.99f);
721 SkScalar baseFrequencyY = d->fRandom->nextRangeScalar(0.01f,
722 0.99f);
723
reed8a21c9f2016-03-08 18:50:00 -0800724 sk_sp<SkShader> shader(d->fRandom->nextBool() ?
725 SkPerlinNoiseShader2::MakeFractalNoise(baseFrequencyX, baseFrequencyY, numOctaves, seed,
726 stitchTiles ? &tileSize : nullptr) :
727 SkPerlinNoiseShader2::MakeTurbulence(baseFrequencyX, baseFrequencyY, numOctaves, seed,
ethannicholas417011c2015-11-09 06:35:12 -0800728 stitchTiles ? &tileSize : nullptr));
729
730 GrPaint grPaint;
brianosman839345d2016-07-22 11:04:53 -0700731 SkMatrix viewMatrix = GrTest::TestMatrix(d->fRandom);
732 return shader->asFragmentProcessor(SkShader::AsFPArgs(d->fContext, &viewMatrix, nullptr,
brianosman1638c0d2016-07-25 05:12:53 -0700733 kNone_SkFilterQuality, nullptr,
brianosman839345d2016-07-22 11:04:53 -0700734 SkSourceGammaTreatment::kRespect));
ethannicholas417011c2015-11-09 06:35:12 -0800735}
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;
bsalomon1a1aa932016-09-12 09:30:36 -0700742 SkString vCoords = fsBuilder->ensureCoords2D(args.fTransformedCoords[0]);
ethannicholas417011c2015-11-09 06:35:12 -0800743
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);
cdalton3f6f76f2016-04-11 12:18:09 -0700824 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800825 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);
cdalton3f6f76f2016-04-11 12:18:09 -0700835 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800836 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);
cdalton3f6f76f2016-04-11 12:18:09 -0700860 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800861 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 = ");
cdalton3f6f76f2016-04-11 12:18:09 -0700872 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800873 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 = ");
cdalton3f6f76f2016-04-11 12:18:09 -0700888 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800889 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 = ");
cdalton3f6f76f2016-04-11 12:18:09 -0700900 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800901 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:
bungeman06ca8ec2016-06-09 08:01:03 -07001055 static sk_sp<GrFragmentProcessor> Make(int octaves, SkScalar z,
1056 SkPerlinNoiseShader2::PaintingData* paintingData,
1057 GrTexture* permutationsTexture,
1058 GrTexture* gradientTexture,
1059 const SkMatrix& matrix) {
1060 return sk_sp<GrFragmentProcessor>(
1061 new GrImprovedPerlinNoiseEffect(octaves, z, paintingData, permutationsTexture,
1062 gradientTexture, matrix));
ethannicholas417011c2015-11-09 06:35:12 -08001063 }
1064
1065 virtual ~GrImprovedPerlinNoiseEffect() { delete fPaintingData; }
1066
1067 const char* name() const override { return "ImprovedPerlinNoise"; }
1068
1069 const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; }
1070 SkScalar z() const { return fZ; }
1071 int octaves() const { return fOctaves; }
1072 const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
1073
1074private:
egdaniel57d3b032015-11-13 11:57:27 -08001075 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
robertphillipsbf536af2016-02-04 06:11:53 -08001076 return new GrGLImprovedPerlinNoise;
ethannicholas417011c2015-11-09 06:35:12 -08001077 }
1078
robertphillipsbf536af2016-02-04 06:11:53 -08001079 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
ethannicholas417011c2015-11-09 06:35:12 -08001080 GrGLImprovedPerlinNoise::GenKey(*this, caps, b);
1081 }
1082
1083 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
1084 const GrImprovedPerlinNoiseEffect& s = sBase.cast<GrImprovedPerlinNoiseEffect>();
1085 return fZ == fZ &&
1086 fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency;
1087 }
1088
1089 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
1090 inout->setToUnknown(GrInvariantOutput::kWillNot_ReadInput);
1091 }
1092
1093 GrImprovedPerlinNoiseEffect(int octaves, SkScalar z,
1094 SkPerlinNoiseShader2::PaintingData* paintingData,
1095 GrTexture* permutationsTexture, GrTexture* gradientTexture,
1096 const SkMatrix& matrix)
1097 : fOctaves(octaves)
1098 , fZ(z)
1099 , fPermutationsAccess(permutationsTexture)
1100 , fGradientAccess(gradientTexture)
1101 , fPaintingData(paintingData) {
1102 this->initClassID<GrImprovedPerlinNoiseEffect>();
1103 this->addTextureAccess(&fPermutationsAccess);
1104 this->addTextureAccess(&fGradientAccess);
1105 fCoordTransform.reset(kLocal_GrCoordSet, matrix);
1106 this->addCoordTransform(&fCoordTransform);
1107 }
1108
1109 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
1110
1111 GrCoordTransform fCoordTransform;
1112 int fOctaves;
1113 SkScalar fZ;
1114 GrTextureAccess fPermutationsAccess;
1115 GrTextureAccess fGradientAccess;
1116 SkPerlinNoiseShader2::PaintingData *fPaintingData;
1117
1118private:
1119 typedef GrFragmentProcessor INHERITED;
1120};
1121
1122/////////////////////////////////////////////////////////////////////
1123GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrImprovedPerlinNoiseEffect);
1124
bungeman06ca8ec2016-06-09 08:01:03 -07001125sk_sp<GrFragmentProcessor> GrImprovedPerlinNoiseEffect::TestCreate(GrProcessorTestData* d) {
ethannicholas417011c2015-11-09 06:35:12 -08001126 SkScalar baseFrequencyX = d->fRandom->nextRangeScalar(0.01f,
1127 0.99f);
1128 SkScalar baseFrequencyY = d->fRandom->nextRangeScalar(0.01f,
1129 0.99f);
1130 int numOctaves = d->fRandom->nextRangeU(2, 10);
1131 SkScalar z = SkIntToScalar(d->fRandom->nextU());
1132
reed8a21c9f2016-03-08 18:50:00 -08001133 sk_sp<SkShader> shader(SkPerlinNoiseShader2::MakeImprovedNoise(baseFrequencyX,
1134 baseFrequencyY,
1135 numOctaves,
1136 z));
ethannicholas417011c2015-11-09 06:35:12 -08001137
1138 GrPaint grPaint;
brianosman839345d2016-07-22 11:04:53 -07001139 SkMatrix viewMatrix = GrTest::TestMatrix(d->fRandom);
1140 return shader->asFragmentProcessor(SkShader::AsFPArgs(d->fContext, &viewMatrix, nullptr,
brianosman1638c0d2016-07-25 05:12:53 -07001141 kNone_SkFilterQuality, nullptr,
brianosman839345d2016-07-22 11:04:53 -07001142 SkSourceGammaTreatment::kRespect));
ethannicholas417011c2015-11-09 06:35:12 -08001143}
1144
ethannicholas417011c2015-11-09 06:35:12 -08001145void GrGLImprovedPerlinNoise::emitCode(EmitArgs& args) {
egdaniel4ca2e602015-11-18 08:01:26 -08001146 GrGLSLFragmentBuilder* fsBuilder = args.fFragBuilder;
egdaniel7ea439b2015-12-03 09:20:44 -08001147 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
bsalomon1a1aa932016-09-12 09:30:36 -07001148 SkString vCoords = fsBuilder->ensureCoords2D(args.fTransformedCoords[0]);
ethannicholas417011c2015-11-09 06:35:12 -08001149
cdalton5e58cee2016-02-11 12:49:47 -08001150 fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001151 kVec2f_GrSLType, kDefault_GrSLPrecision,
1152 "baseFrequency");
1153 const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);
ethannicholas417011c2015-11-09 06:35:12 -08001154
cdalton5e58cee2016-02-11 12:49:47 -08001155 fOctavesUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001156 kFloat_GrSLType, kDefault_GrSLPrecision,
1157 "octaves");
1158 const char* octavesUni = uniformHandler->getUniformCStr(fOctavesUni);
ethannicholas417011c2015-11-09 06:35:12 -08001159
cdalton5e58cee2016-02-11 12:49:47 -08001160 fZUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001161 kFloat_GrSLType, kDefault_GrSLPrecision,
1162 "z");
1163 const char* zUni = uniformHandler->getUniformCStr(fZUni);
ethannicholas417011c2015-11-09 06:35:12 -08001164
1165 // fade function
1166 static const GrGLSLShaderVar fadeArgs[] = {
1167 GrGLSLShaderVar("t", kVec3f_GrSLType)
1168 };
1169 SkString fadeFuncName;
1170 fsBuilder->emitFunction(kVec3f_GrSLType, "fade", SK_ARRAY_COUNT(fadeArgs),
1171 fadeArgs,
1172 "return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);",
1173 &fadeFuncName);
1174
1175 // perm function
1176 static const GrGLSLShaderVar permArgs[] = {
1177 GrGLSLShaderVar("x", kFloat_GrSLType)
1178 };
1179 SkString permFuncName;
1180 SkString permCode("return ");
1181 // FIXME even though I'm creating these textures with kRepeat_TileMode, they're clamped. Not
1182 // sure why. Using fract() (here and the next texture lookup) as a workaround.
cdalton3f6f76f2016-04-11 12:18:09 -07001183 fsBuilder->appendTextureLookup(&permCode, args.fTexSamplers[0], "vec2(fract(x / 256.0), 0.0)",
ethannicholas417011c2015-11-09 06:35:12 -08001184 kVec2f_GrSLType);
1185 permCode.append(".r * 255.0;");
1186 fsBuilder->emitFunction(kFloat_GrSLType, "perm", SK_ARRAY_COUNT(permArgs), permArgs,
1187 permCode.c_str(), &permFuncName);
1188
1189 // grad function
1190 static const GrGLSLShaderVar gradArgs[] = {
1191 GrGLSLShaderVar("x", kFloat_GrSLType),
1192 GrGLSLShaderVar("p", kVec3f_GrSLType)
1193 };
1194 SkString gradFuncName;
1195 SkString gradCode("return dot(");
cdalton3f6f76f2016-04-11 12:18:09 -07001196 fsBuilder->appendTextureLookup(&gradCode, args.fTexSamplers[1], "vec2(fract(x / 16.0), 0.0)",
ethannicholas417011c2015-11-09 06:35:12 -08001197 kVec2f_GrSLType);
1198 gradCode.append(".rgb * 255.0 - vec3(1.0), p);");
1199 fsBuilder->emitFunction(kFloat_GrSLType, "grad", SK_ARRAY_COUNT(gradArgs), gradArgs,
1200 gradCode.c_str(), &gradFuncName);
1201
1202 // lerp function
1203 static const GrGLSLShaderVar lerpArgs[] = {
1204 GrGLSLShaderVar("a", kFloat_GrSLType),
1205 GrGLSLShaderVar("b", kFloat_GrSLType),
1206 GrGLSLShaderVar("w", kFloat_GrSLType)
1207 };
1208 SkString lerpFuncName;
1209 fsBuilder->emitFunction(kFloat_GrSLType, "lerp", SK_ARRAY_COUNT(lerpArgs), lerpArgs,
1210 "return a + w * (b - a);", &lerpFuncName);
1211
1212 // noise function
1213 static const GrGLSLShaderVar noiseArgs[] = {
1214 GrGLSLShaderVar("p", kVec3f_GrSLType),
1215 };
1216 SkString noiseFuncName;
1217 SkString noiseCode;
1218 noiseCode.append("vec3 P = mod(floor(p), 256.0);");
1219 noiseCode.append("p -= floor(p);");
1220 noiseCode.appendf("vec3 f = %s(p);", fadeFuncName.c_str());
1221 noiseCode.appendf("float A = %s(P.x) + P.y;", permFuncName.c_str());
1222 noiseCode.appendf("float AA = %s(A) + P.z;", permFuncName.c_str());
1223 noiseCode.appendf("float AB = %s(A + 1.0) + P.z;", permFuncName.c_str());
1224 noiseCode.appendf("float B = %s(P.x + 1.0) + P.y;", permFuncName.c_str());
1225 noiseCode.appendf("float BA = %s(B) + P.z;", permFuncName.c_str());
1226 noiseCode.appendf("float BB = %s(B + 1.0) + P.z;", permFuncName.c_str());
1227 noiseCode.appendf("float result = %s(", lerpFuncName.c_str());
1228 noiseCode.appendf("%s(%s(%s(%s(AA), p),", lerpFuncName.c_str(), lerpFuncName.c_str(),
1229 gradFuncName.c_str(), permFuncName.c_str());
1230 noiseCode.appendf("%s(%s(BA), p + vec3(-1.0, 0.0, 0.0)), f.x),", gradFuncName.c_str(),
1231 permFuncName.c_str());
1232 noiseCode.appendf("%s(%s(%s(AB), p + vec3(0.0, -1.0, 0.0)),", lerpFuncName.c_str(),
1233 gradFuncName.c_str(), permFuncName.c_str());
1234 noiseCode.appendf("%s(%s(BB), p + vec3(-1.0, -1.0, 0.0)), f.x), f.y),",
1235 gradFuncName.c_str(), permFuncName.c_str());
1236 noiseCode.appendf("%s(%s(%s(%s(AA + 1.0), p + vec3(0.0, 0.0, -1.0)),",
1237 lerpFuncName.c_str(), lerpFuncName.c_str(), gradFuncName.c_str(),
1238 permFuncName.c_str());
1239 noiseCode.appendf("%s(%s(BA + 1.0), p + vec3(-1.0, 0.0, -1.0)), f.x),",
1240 gradFuncName.c_str(), permFuncName.c_str());
1241 noiseCode.appendf("%s(%s(%s(AB + 1.0), p + vec3(0.0, -1.0, -1.0)),",
1242 lerpFuncName.c_str(), gradFuncName.c_str(), permFuncName.c_str());
1243 noiseCode.appendf("%s(%s(BB + 1.0), p + vec3(-1.0, -1.0, -1.0)), f.x), f.y), f.z);",
1244 gradFuncName.c_str(), permFuncName.c_str());
1245 noiseCode.append("return result;");
1246 fsBuilder->emitFunction(kFloat_GrSLType, "noise", SK_ARRAY_COUNT(noiseArgs), noiseArgs,
1247 noiseCode.c_str(), &noiseFuncName);
1248
1249 // noiseOctaves function
1250 static const GrGLSLShaderVar noiseOctavesArgs[] = {
1251 GrGLSLShaderVar("p", kVec3f_GrSLType),
1252 GrGLSLShaderVar("octaves", kFloat_GrSLType),
1253 };
1254 SkString noiseOctavesFuncName;
1255 SkString noiseOctavesCode;
1256 noiseOctavesCode.append("float result = 0.0;");
1257 noiseOctavesCode.append("float ratio = 1.0;");
1258 noiseOctavesCode.append("for (float i = 0.0; i < octaves; i++) {");
1259 noiseOctavesCode.appendf("result += %s(p) / ratio;", noiseFuncName.c_str());
1260 noiseOctavesCode.append("p *= 2.0;");
1261 noiseOctavesCode.append("ratio *= 2.0;");
1262 noiseOctavesCode.append("}");
1263 noiseOctavesCode.append("return (result + 1.0) / 2.0;");
1264 fsBuilder->emitFunction(kFloat_GrSLType, "noiseOctaves", SK_ARRAY_COUNT(noiseOctavesArgs),
1265 noiseOctavesArgs, noiseOctavesCode.c_str(), &noiseOctavesFuncName);
1266
1267 fsBuilder->codeAppendf("vec2 coords = %s * %s;", vCoords.c_str(), baseFrequencyUni);
1268 fsBuilder->codeAppendf("float r = %s(vec3(coords, %s), %s);", noiseOctavesFuncName.c_str(),
1269 zUni, octavesUni);
egdaniel478c04e2015-11-09 07:40:49 -08001270 fsBuilder->codeAppendf("float g = %s(vec3(coords, %s + 0000.0), %s);",
ethannicholas417011c2015-11-09 06:35:12 -08001271 noiseOctavesFuncName.c_str(), zUni, octavesUni);
egdaniel478c04e2015-11-09 07:40:49 -08001272 fsBuilder->codeAppendf("float b = %s(vec3(coords, %s + 0000.0), %s);",
ethannicholas417011c2015-11-09 06:35:12 -08001273 noiseOctavesFuncName.c_str(), zUni, octavesUni);
egdaniel478c04e2015-11-09 07:40:49 -08001274 fsBuilder->codeAppendf("float a = %s(vec3(coords, %s + 0000.0), %s);",
ethannicholas417011c2015-11-09 06:35:12 -08001275 noiseOctavesFuncName.c_str(), zUni, octavesUni);
1276 fsBuilder->codeAppendf("%s = vec4(r, g, b, a);", args.fOutputColor);
1277
1278 // Clamp values
1279 fsBuilder->codeAppendf("%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor);
1280
1281 // Pre-multiply the result
1282 fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
1283 args.fOutputColor, args.fOutputColor,
1284 args.fOutputColor, args.fOutputColor);
1285}
1286
1287void GrGLImprovedPerlinNoise::GenKey(const GrProcessor& processor, const GrGLSLCaps&,
1288 GrProcessorKeyBuilder* b) {
1289}
1290
1291void GrGLImprovedPerlinNoise::onSetData(const GrGLSLProgramDataManager& pdman,
1292 const GrProcessor& processor) {
1293 INHERITED::onSetData(pdman, processor);
1294
1295 const GrImprovedPerlinNoiseEffect& noise = processor.cast<GrImprovedPerlinNoiseEffect>();
1296
1297 const SkVector& baseFrequency = noise.baseFrequency();
1298 pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
1299
egdaniel478c04e2015-11-09 07:40:49 -08001300 pdman.set1f(fOctavesUni, SkIntToScalar(noise.octaves()));
ethannicholas417011c2015-11-09 06:35:12 -08001301
1302 pdman.set1f(fZUni, noise.z());
1303}
1304
1305/////////////////////////////////////////////////////////////////////
brianosman839345d2016-07-22 11:04:53 -07001306sk_sp<GrFragmentProcessor> SkPerlinNoiseShader2::asFragmentProcessor(const AsFPArgs& args) const {
1307 SkASSERT(args.fContext);
ethannicholas417011c2015-11-09 06:35:12 -08001308
1309 SkMatrix localMatrix = this->getLocalMatrix();
brianosman839345d2016-07-22 11:04:53 -07001310 if (args.fLocalMatrix) {
1311 localMatrix.preConcat(*args.fLocalMatrix);
ethannicholas417011c2015-11-09 06:35:12 -08001312 }
1313
brianosman839345d2016-07-22 11:04:53 -07001314 SkMatrix matrix = *args.fViewMatrix;
ethannicholas417011c2015-11-09 06:35:12 -08001315 matrix.preConcat(localMatrix);
1316
1317 // Either we don't stitch tiles, either we have a valid tile size
1318 SkASSERT(!fStitchTiles || !fTileSize.isEmpty());
1319
1320 SkPerlinNoiseShader2::PaintingData* paintingData =
1321 new PaintingData(fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY, matrix);
1322
brianosman839345d2016-07-22 11:04:53 -07001323 SkMatrix m = *args.fViewMatrix;
ethannicholas417011c2015-11-09 06:35:12 -08001324 m.setTranslateX(-localMatrix.getTranslateX() + SK_Scalar1);
1325 m.setTranslateY(-localMatrix.getTranslateY() + SK_Scalar1);
1326
1327 if (fType == kImprovedNoise_Type) {
1328 GrTextureParams textureParams(SkShader::TileMode::kRepeat_TileMode,
1329 GrTextureParams::FilterMode::kNone_FilterMode);
1330 SkAutoTUnref<GrTexture> permutationsTexture(
brianosman839345d2016-07-22 11:04:53 -07001331 GrRefCachedBitmapTexture(args.fContext, paintingData->getImprovedPermutationsBitmap(),
1332 textureParams, args.fGammaTreatment));
ethannicholas417011c2015-11-09 06:35:12 -08001333 SkAutoTUnref<GrTexture> gradientTexture(
brianosman839345d2016-07-22 11:04:53 -07001334 GrRefCachedBitmapTexture(args.fContext, paintingData->getGradientBitmap(),
1335 textureParams, args.fGammaTreatment));
bungeman06ca8ec2016-06-09 08:01:03 -07001336 return GrImprovedPerlinNoiseEffect::Make(fNumOctaves, fSeed, paintingData,
ethannicholas417011c2015-11-09 06:35:12 -08001337 permutationsTexture, gradientTexture, m);
1338 }
1339
1340 if (0 == fNumOctaves) {
1341 if (kFractalNoise_Type == fType) {
1342 // Extract the incoming alpha and emit rgba = (a/4, a/4, a/4, a/2)
bungeman06ca8ec2016-06-09 08:01:03 -07001343 sk_sp<GrFragmentProcessor> inner(
1344 GrConstColorProcessor::Make(0x80404040,
1345 GrConstColorProcessor::kModulateRGBA_InputMode));
1346 return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner));
ethannicholas417011c2015-11-09 06:35:12 -08001347 }
1348 // Emit zero.
bungeman06ca8ec2016-06-09 08:01:03 -07001349 return GrConstColorProcessor::Make(0x0, GrConstColorProcessor::kIgnore_InputMode);
ethannicholas417011c2015-11-09 06:35:12 -08001350 }
1351
1352 SkAutoTUnref<GrTexture> permutationsTexture(
brianosman839345d2016-07-22 11:04:53 -07001353 GrRefCachedBitmapTexture(args.fContext, paintingData->getPermutationsBitmap(),
1354 GrTextureParams::ClampNoFilter(), args.fGammaTreatment));
ethannicholas417011c2015-11-09 06:35:12 -08001355 SkAutoTUnref<GrTexture> noiseTexture(
brianosman839345d2016-07-22 11:04:53 -07001356 GrRefCachedBitmapTexture(args.fContext, paintingData->getNoiseBitmap(),
1357 GrTextureParams::ClampNoFilter(), args.fGammaTreatment));
ethannicholas417011c2015-11-09 06:35:12 -08001358
1359 if ((permutationsTexture) && (noiseTexture)) {
bungeman06ca8ec2016-06-09 08:01:03 -07001360 sk_sp<GrFragmentProcessor> inner(
1361 GrPerlinNoise2Effect::Make(fType,
1362 fNumOctaves,
1363 fStitchTiles,
1364 paintingData,
1365 permutationsTexture, noiseTexture,
1366 m));
1367 return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner));
ethannicholas417011c2015-11-09 06:35:12 -08001368 }
1369 delete paintingData;
1370 return nullptr;
1371}
1372
1373#endif
1374
1375#ifndef SK_IGNORE_TO_STRING
1376void SkPerlinNoiseShader2::toString(SkString* str) const {
1377 str->append("SkPerlinNoiseShader2: (");
1378
1379 str->append("type: ");
1380 switch (fType) {
1381 case kFractalNoise_Type:
1382 str->append("\"fractal noise\"");
1383 break;
1384 case kTurbulence_Type:
1385 str->append("\"turbulence\"");
1386 break;
1387 default:
1388 str->append("\"unknown\"");
1389 break;
1390 }
1391 str->append(" base frequency: (");
1392 str->appendScalar(fBaseFrequencyX);
1393 str->append(", ");
1394 str->appendScalar(fBaseFrequencyY);
1395 str->append(") number of octaves: ");
1396 str->appendS32(fNumOctaves);
1397 str->append(" seed: ");
1398 str->appendScalar(fSeed);
1399 str->append(" stitch tiles: ");
1400 str->append(fStitchTiles ? "true " : "false ");
1401
1402 this->INHERITED::toString(str);
1403
1404 str->append(")");
1405}
1406#endif