blob: 593fda12476fefeb3c79c32a1e3d9ca60dc60a3a [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);
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400692 fCoordTransform.reset(matrix);
ethannicholas417011c2015-11-09 06:35:12 -0800693 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);
Brian Osman0d9dfe92016-10-03 15:24:44 -0400732 auto colorSpace = GrTest::TestColorSpace(d->fRandom);
brianosman839345d2016-07-22 11:04:53 -0700733 return shader->asFragmentProcessor(SkShader::AsFPArgs(d->fContext, &viewMatrix, nullptr,
Brian Osman0d9dfe92016-10-03 15:24:44 -0400734 kNone_SkFilterQuality, colorSpace.get(),
brianosman839345d2016-07-22 11:04:53 -0700735 SkSourceGammaTreatment::kRespect));
ethannicholas417011c2015-11-09 06:35:12 -0800736}
737
ethannicholas417011c2015-11-09 06:35:12 -0800738void GrGLPerlinNoise2::emitCode(EmitArgs& args) {
robertphillipsd3b32bf2016-02-05 07:15:39 -0800739 const GrPerlinNoise2Effect& pne = args.fFp.cast<GrPerlinNoise2Effect>();
740
egdaniel4ca2e602015-11-18 08:01:26 -0800741 GrGLSLFragmentBuilder* fsBuilder = args.fFragBuilder;
egdaniel7ea439b2015-12-03 09:20:44 -0800742 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
bsalomon1a1aa932016-09-12 09:30:36 -0700743 SkString vCoords = fsBuilder->ensureCoords2D(args.fTransformedCoords[0]);
ethannicholas417011c2015-11-09 06:35:12 -0800744
cdalton5e58cee2016-02-11 12:49:47 -0800745 fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800746 kVec2f_GrSLType, kDefault_GrSLPrecision,
747 "baseFrequency");
748 const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);
ethannicholas417011c2015-11-09 06:35:12 -0800749
750 const char* stitchDataUni = nullptr;
robertphillipsd3b32bf2016-02-05 07:15:39 -0800751 if (pne.stitchTiles()) {
cdalton5e58cee2016-02-11 12:49:47 -0800752 fStitchDataUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800753 kVec2f_GrSLType, kDefault_GrSLPrecision,
754 "stitchData");
755 stitchDataUni = uniformHandler->getUniformCStr(fStitchDataUni);
ethannicholas417011c2015-11-09 06:35:12 -0800756 }
757
758 // There are 4 lines, so the center of each line is 1/8, 3/8, 5/8 and 7/8
759 const char* chanCoordR = "0.125";
760 const char* chanCoordG = "0.375";
761 const char* chanCoordB = "0.625";
762 const char* chanCoordA = "0.875";
763 const char* chanCoord = "chanCoord";
764 const char* stitchData = "stitchData";
765 const char* ratio = "ratio";
766 const char* noiseVec = "noiseVec";
767 const char* noiseSmooth = "noiseSmooth";
768 const char* floorVal = "floorVal";
769 const char* fractVal = "fractVal";
770 const char* uv = "uv";
771 const char* ab = "ab";
772 const char* latticeIdx = "latticeIdx";
773 const char* bcoords = "bcoords";
774 const char* lattice = "lattice";
775 const char* inc8bit = "0.00390625"; // 1.0 / 256.0
776 // This is the math to convert the two 16bit integer packed into rgba 8 bit input into a
777 // [-1,1] vector and perform a dot product between that vector and the provided vector.
778 const char* dotLattice = "dot(((%s.ga + %s.rb * vec2(%s)) * vec2(2.0) - vec2(1.0)), %s);";
779
780 // Add noise function
781 static const GrGLSLShaderVar gPerlinNoiseArgs[] = {
782 GrGLSLShaderVar(chanCoord, kFloat_GrSLType),
783 GrGLSLShaderVar(noiseVec, kVec2f_GrSLType)
784 };
785
786 static const GrGLSLShaderVar gPerlinNoiseStitchArgs[] = {
787 GrGLSLShaderVar(chanCoord, kFloat_GrSLType),
788 GrGLSLShaderVar(noiseVec, kVec2f_GrSLType),
789 GrGLSLShaderVar(stitchData, kVec2f_GrSLType)
790 };
791
792 SkString noiseCode;
793
794 noiseCode.appendf("\tvec4 %s;\n", floorVal);
795 noiseCode.appendf("\t%s.xy = floor(%s);\n", floorVal, noiseVec);
796 noiseCode.appendf("\t%s.zw = %s.xy + vec2(1.0);\n", floorVal, floorVal);
797 noiseCode.appendf("\tvec2 %s = fract(%s);\n", fractVal, noiseVec);
798
799 // smooth curve : t * t * (3 - 2 * t)
800 noiseCode.appendf("\n\tvec2 %s = %s * %s * (vec2(3.0) - vec2(2.0) * %s);",
801 noiseSmooth, fractVal, fractVal, fractVal);
802
803 // Adjust frequencies if we're stitching tiles
robertphillipsd3b32bf2016-02-05 07:15:39 -0800804 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800805 noiseCode.appendf("\n\tif(%s.x >= %s.x) { %s.x -= %s.x; }",
806 floorVal, stitchData, floorVal, stitchData);
807 noiseCode.appendf("\n\tif(%s.y >= %s.y) { %s.y -= %s.y; }",
808 floorVal, stitchData, floorVal, stitchData);
809 noiseCode.appendf("\n\tif(%s.z >= %s.x) { %s.z -= %s.x; }",
810 floorVal, stitchData, floorVal, stitchData);
811 noiseCode.appendf("\n\tif(%s.w >= %s.y) { %s.w -= %s.y; }",
812 floorVal, stitchData, floorVal, stitchData);
813 }
814
815 // Get texture coordinates and normalize
816 noiseCode.appendf("\n\t%s = fract(floor(mod(%s, 256.0)) / vec4(256.0));\n",
817 floorVal, floorVal);
818
819 // Get permutation for x
820 {
821 SkString xCoords("");
822 xCoords.appendf("vec2(%s.x, 0.5)", floorVal);
823
824 noiseCode.appendf("\n\tvec2 %s;\n\t%s.x = ", latticeIdx, latticeIdx);
cdalton3f6f76f2016-04-11 12:18:09 -0700825 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800826 kVec2f_GrSLType);
827 noiseCode.append(".r;");
828 }
829
830 // Get permutation for x + 1
831 {
832 SkString xCoords("");
833 xCoords.appendf("vec2(%s.z, 0.5)", floorVal);
834
835 noiseCode.appendf("\n\t%s.y = ", latticeIdx);
cdalton3f6f76f2016-04-11 12:18:09 -0700836 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800837 kVec2f_GrSLType);
838 noiseCode.append(".r;");
839 }
840
841#if defined(SK_BUILD_FOR_ANDROID)
842 // Android rounding for Tegra devices, like, for example: Xoom (Tegra 2), Nexus 7 (Tegra 3).
843 // The issue is that colors aren't accurate enough on Tegra devices. For example, if an 8 bit
844 // value of 124 (or 0.486275 here) is entered, we can get a texture value of 123.513725
845 // (or 0.484368 here). The following rounding operation prevents these precision issues from
846 // affecting the result of the noise by making sure that we only have multiples of 1/255.
847 // (Note that 1/255 is about 0.003921569, which is the value used here).
848 noiseCode.appendf("\n\t%s = floor(%s * vec2(255.0) + vec2(0.5)) * vec2(0.003921569);",
849 latticeIdx, latticeIdx);
850#endif
851
852 // Get (x,y) coordinates with the permutated x
853 noiseCode.appendf("\n\tvec4 %s = fract(%s.xyxy + %s.yyww);", bcoords, latticeIdx, floorVal);
854
855 noiseCode.appendf("\n\n\tvec2 %s;", uv);
856 // Compute u, at offset (0,0)
857 {
858 SkString latticeCoords("");
859 latticeCoords.appendf("vec2(%s.x, %s)", bcoords, chanCoord);
860 noiseCode.appendf("\n\tvec4 %s = ", lattice);
cdalton3f6f76f2016-04-11 12:18:09 -0700861 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800862 kVec2f_GrSLType);
863 noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
864 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
865 }
866
867 noiseCode.appendf("\n\t%s.x -= 1.0;", fractVal);
868 // Compute v, at offset (-1,0)
869 {
870 SkString latticeCoords("");
871 latticeCoords.appendf("vec2(%s.y, %s)", bcoords, chanCoord);
872 noiseCode.append("\n\tlattice = ");
cdalton3f6f76f2016-04-11 12:18:09 -0700873 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800874 kVec2f_GrSLType);
875 noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
876 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
877 }
878
879 // Compute 'a' as a linear interpolation of 'u' and 'v'
880 noiseCode.appendf("\n\tvec2 %s;", ab);
881 noiseCode.appendf("\n\t%s.x = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
882
883 noiseCode.appendf("\n\t%s.y -= 1.0;", fractVal);
884 // Compute v, at offset (-1,-1)
885 {
886 SkString latticeCoords("");
887 latticeCoords.appendf("vec2(%s.w, %s)", bcoords, chanCoord);
888 noiseCode.append("\n\tlattice = ");
cdalton3f6f76f2016-04-11 12:18:09 -0700889 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800890 kVec2f_GrSLType);
891 noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
892 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
893 }
894
895 noiseCode.appendf("\n\t%s.x += 1.0;", fractVal);
896 // Compute u, at offset (0,-1)
897 {
898 SkString latticeCoords("");
899 latticeCoords.appendf("vec2(%s.z, %s)", bcoords, chanCoord);
900 noiseCode.append("\n\tlattice = ");
cdalton3f6f76f2016-04-11 12:18:09 -0700901 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800902 kVec2f_GrSLType);
903 noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
904 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
905 }
906
907 // Compute 'b' as a linear interpolation of 'u' and 'v'
908 noiseCode.appendf("\n\t%s.y = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
909 // Compute the noise as a linear interpolation of 'a' and 'b'
910 noiseCode.appendf("\n\treturn mix(%s.x, %s.y, %s.y);\n", ab, ab, noiseSmooth);
911
912 SkString noiseFuncName;
robertphillipsd3b32bf2016-02-05 07:15:39 -0800913 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800914 fsBuilder->emitFunction(kFloat_GrSLType,
915 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseStitchArgs),
916 gPerlinNoiseStitchArgs, noiseCode.c_str(), &noiseFuncName);
917 } else {
918 fsBuilder->emitFunction(kFloat_GrSLType,
919 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseArgs),
920 gPerlinNoiseArgs, noiseCode.c_str(), &noiseFuncName);
921 }
922
923 // There are rounding errors if the floor operation is not performed here
924 fsBuilder->codeAppendf("\n\t\tvec2 %s = floor(%s.xy) * %s;",
925 noiseVec, vCoords.c_str(), baseFrequencyUni);
926
927 // Clear the color accumulator
928 fsBuilder->codeAppendf("\n\t\t%s = vec4(0.0);", args.fOutputColor);
929
robertphillipsd3b32bf2016-02-05 07:15:39 -0800930 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800931 // Set up TurbulenceInitial stitch values.
932 fsBuilder->codeAppendf("\n\t\tvec2 %s = %s;", stitchData, stitchDataUni);
933 }
934
935 fsBuilder->codeAppendf("\n\t\tfloat %s = 1.0;", ratio);
936
937 // Loop over all octaves
robertphillipsd3b32bf2016-02-05 07:15:39 -0800938 fsBuilder->codeAppendf("for (int octave = 0; octave < %d; ++octave) {", pne.numOctaves());
ethannicholas417011c2015-11-09 06:35:12 -0800939
940 fsBuilder->codeAppendf("\n\t\t\t%s += ", args.fOutputColor);
robertphillipsd3b32bf2016-02-05 07:15:39 -0800941 if (pne.type() != SkPerlinNoiseShader2::kFractalNoise_Type) {
ethannicholas417011c2015-11-09 06:35:12 -0800942 fsBuilder->codeAppend("abs(");
943 }
robertphillipsd3b32bf2016-02-05 07:15:39 -0800944 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800945 fsBuilder->codeAppendf(
946 "vec4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s),"
947 "\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))",
948 noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData,
949 noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData,
950 noiseFuncName.c_str(), chanCoordB, noiseVec, stitchData,
951 noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData);
952 } else {
953 fsBuilder->codeAppendf(
954 "vec4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s),"
955 "\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))",
956 noiseFuncName.c_str(), chanCoordR, noiseVec,
957 noiseFuncName.c_str(), chanCoordG, noiseVec,
958 noiseFuncName.c_str(), chanCoordB, noiseVec,
959 noiseFuncName.c_str(), chanCoordA, noiseVec);
960 }
robertphillipsd3b32bf2016-02-05 07:15:39 -0800961 if (pne.type() != SkPerlinNoiseShader2::kFractalNoise_Type) {
ethannicholas417011c2015-11-09 06:35:12 -0800962 fsBuilder->codeAppendf(")"); // end of "abs("
963 }
964 fsBuilder->codeAppendf(" * %s;", ratio);
965
966 fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", noiseVec);
967 fsBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio);
968
robertphillipsd3b32bf2016-02-05 07:15:39 -0800969 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800970 fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", stitchData);
971 }
972 fsBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves
973
robertphillipsd3b32bf2016-02-05 07:15:39 -0800974 if (pne.type() == SkPerlinNoiseShader2::kFractalNoise_Type) {
ethannicholas417011c2015-11-09 06:35:12 -0800975 // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
976 // by fractalNoise and (turbulenceFunctionResult) by turbulence.
977 fsBuilder->codeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);",
978 args.fOutputColor,args.fOutputColor);
979 }
980
981 // Clamp values
982 fsBuilder->codeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor);
983
984 // Pre-multiply the result
985 fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
986 args.fOutputColor, args.fOutputColor,
987 args.fOutputColor, args.fOutputColor);
988}
989
990void GrGLPerlinNoise2::GenKey(const GrProcessor& processor, const GrGLSLCaps&,
egdaniel2d721d32015-11-11 13:06:05 -0800991 GrProcessorKeyBuilder* b) {
ethannicholas417011c2015-11-09 06:35:12 -0800992 const GrPerlinNoise2Effect& turbulence = processor.cast<GrPerlinNoise2Effect>();
993
994 uint32_t key = turbulence.numOctaves();
995
996 key = key << 3; // Make room for next 3 bits
997
998 switch (turbulence.type()) {
999 case SkPerlinNoiseShader2::kFractalNoise_Type:
1000 key |= 0x1;
1001 break;
1002 case SkPerlinNoiseShader2::kTurbulence_Type:
1003 key |= 0x2;
1004 break;
1005 default:
1006 // leave key at 0
1007 break;
1008 }
1009
1010 if (turbulence.stitchTiles()) {
1011 key |= 0x4; // Flip the 3rd bit if tile stitching is on
1012 }
1013
1014 b->add32(key);
1015}
1016
1017void GrGLPerlinNoise2::onSetData(const GrGLSLProgramDataManager& pdman,
1018 const GrProcessor& processor) {
1019 INHERITED::onSetData(pdman, processor);
1020
1021 const GrPerlinNoise2Effect& turbulence = processor.cast<GrPerlinNoise2Effect>();
1022
1023 const SkVector& baseFrequency = turbulence.baseFrequency();
1024 pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
1025
1026 if (turbulence.stitchTiles()) {
1027 const SkPerlinNoiseShader2::StitchData& stitchData = turbulence.stitchData();
1028 pdman.set2f(fStitchDataUni, SkIntToScalar(stitchData.fWidth),
1029 SkIntToScalar(stitchData.fHeight));
1030 }
1031}
1032
1033/////////////////////////////////////////////////////////////////////
1034
egdaniel64c47282015-11-13 06:54:19 -08001035class GrGLImprovedPerlinNoise : public GrGLSLFragmentProcessor {
ethannicholas417011c2015-11-09 06:35:12 -08001036public:
robertphillipsbf536af2016-02-04 06:11:53 -08001037 void emitCode(EmitArgs&) override;
ethannicholas417011c2015-11-09 06:35:12 -08001038
robertphillipsbf536af2016-02-04 06:11:53 -08001039 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*);
ethannicholas417011c2015-11-09 06:35:12 -08001040
1041protected:
1042 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
1043
1044private:
ethannicholas417011c2015-11-09 06:35:12 -08001045 GrGLSLProgramDataManager::UniformHandle fZUni;
1046 GrGLSLProgramDataManager::UniformHandle fOctavesUni;
1047 GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni;
1048
egdaniel64c47282015-11-13 06:54:19 -08001049 typedef GrGLSLFragmentProcessor INHERITED;
ethannicholas417011c2015-11-09 06:35:12 -08001050};
1051
1052/////////////////////////////////////////////////////////////////////
1053
1054class GrImprovedPerlinNoiseEffect : public GrFragmentProcessor {
1055public:
bungeman06ca8ec2016-06-09 08:01:03 -07001056 static sk_sp<GrFragmentProcessor> Make(int octaves, SkScalar z,
1057 SkPerlinNoiseShader2::PaintingData* paintingData,
1058 GrTexture* permutationsTexture,
1059 GrTexture* gradientTexture,
1060 const SkMatrix& matrix) {
1061 return sk_sp<GrFragmentProcessor>(
1062 new GrImprovedPerlinNoiseEffect(octaves, z, paintingData, permutationsTexture,
1063 gradientTexture, matrix));
ethannicholas417011c2015-11-09 06:35:12 -08001064 }
1065
1066 virtual ~GrImprovedPerlinNoiseEffect() { delete fPaintingData; }
1067
1068 const char* name() const override { return "ImprovedPerlinNoise"; }
1069
1070 const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; }
1071 SkScalar z() const { return fZ; }
1072 int octaves() const { return fOctaves; }
1073 const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
1074
1075private:
egdaniel57d3b032015-11-13 11:57:27 -08001076 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
robertphillipsbf536af2016-02-04 06:11:53 -08001077 return new GrGLImprovedPerlinNoise;
ethannicholas417011c2015-11-09 06:35:12 -08001078 }
1079
robertphillipsbf536af2016-02-04 06:11:53 -08001080 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
ethannicholas417011c2015-11-09 06:35:12 -08001081 GrGLImprovedPerlinNoise::GenKey(*this, caps, b);
1082 }
1083
1084 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
1085 const GrImprovedPerlinNoiseEffect& s = sBase.cast<GrImprovedPerlinNoiseEffect>();
1086 return fZ == fZ &&
1087 fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency;
1088 }
1089
1090 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
1091 inout->setToUnknown(GrInvariantOutput::kWillNot_ReadInput);
1092 }
1093
1094 GrImprovedPerlinNoiseEffect(int octaves, SkScalar z,
1095 SkPerlinNoiseShader2::PaintingData* paintingData,
1096 GrTexture* permutationsTexture, GrTexture* gradientTexture,
1097 const SkMatrix& matrix)
1098 : fOctaves(octaves)
1099 , fZ(z)
1100 , fPermutationsAccess(permutationsTexture)
1101 , fGradientAccess(gradientTexture)
1102 , fPaintingData(paintingData) {
1103 this->initClassID<GrImprovedPerlinNoiseEffect>();
1104 this->addTextureAccess(&fPermutationsAccess);
1105 this->addTextureAccess(&fGradientAccess);
Brian Salomon2ebd0c82016-10-03 17:15:28 -04001106 fCoordTransform.reset(matrix);
ethannicholas417011c2015-11-09 06:35:12 -08001107 this->addCoordTransform(&fCoordTransform);
1108 }
1109
1110 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
1111
1112 GrCoordTransform fCoordTransform;
1113 int fOctaves;
1114 SkScalar fZ;
1115 GrTextureAccess fPermutationsAccess;
1116 GrTextureAccess fGradientAccess;
1117 SkPerlinNoiseShader2::PaintingData *fPaintingData;
1118
1119private:
1120 typedef GrFragmentProcessor INHERITED;
1121};
1122
1123/////////////////////////////////////////////////////////////////////
1124GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrImprovedPerlinNoiseEffect);
1125
bungeman06ca8ec2016-06-09 08:01:03 -07001126sk_sp<GrFragmentProcessor> GrImprovedPerlinNoiseEffect::TestCreate(GrProcessorTestData* d) {
ethannicholas417011c2015-11-09 06:35:12 -08001127 SkScalar baseFrequencyX = d->fRandom->nextRangeScalar(0.01f,
1128 0.99f);
1129 SkScalar baseFrequencyY = d->fRandom->nextRangeScalar(0.01f,
1130 0.99f);
1131 int numOctaves = d->fRandom->nextRangeU(2, 10);
1132 SkScalar z = SkIntToScalar(d->fRandom->nextU());
1133
reed8a21c9f2016-03-08 18:50:00 -08001134 sk_sp<SkShader> shader(SkPerlinNoiseShader2::MakeImprovedNoise(baseFrequencyX,
1135 baseFrequencyY,
1136 numOctaves,
1137 z));
ethannicholas417011c2015-11-09 06:35:12 -08001138
1139 GrPaint grPaint;
brianosman839345d2016-07-22 11:04:53 -07001140 SkMatrix viewMatrix = GrTest::TestMatrix(d->fRandom);
Brian Osman0d9dfe92016-10-03 15:24:44 -04001141 auto colorSpace = GrTest::TestColorSpace(d->fRandom);
brianosman839345d2016-07-22 11:04:53 -07001142 return shader->asFragmentProcessor(SkShader::AsFPArgs(d->fContext, &viewMatrix, nullptr,
Brian Osman0d9dfe92016-10-03 15:24:44 -04001143 kNone_SkFilterQuality, colorSpace.get(),
brianosman839345d2016-07-22 11:04:53 -07001144 SkSourceGammaTreatment::kRespect));
ethannicholas417011c2015-11-09 06:35:12 -08001145}
1146
ethannicholas417011c2015-11-09 06:35:12 -08001147void GrGLImprovedPerlinNoise::emitCode(EmitArgs& args) {
egdaniel4ca2e602015-11-18 08:01:26 -08001148 GrGLSLFragmentBuilder* fsBuilder = args.fFragBuilder;
egdaniel7ea439b2015-12-03 09:20:44 -08001149 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
bsalomon1a1aa932016-09-12 09:30:36 -07001150 SkString vCoords = fsBuilder->ensureCoords2D(args.fTransformedCoords[0]);
ethannicholas417011c2015-11-09 06:35:12 -08001151
cdalton5e58cee2016-02-11 12:49:47 -08001152 fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001153 kVec2f_GrSLType, kDefault_GrSLPrecision,
1154 "baseFrequency");
1155 const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);
ethannicholas417011c2015-11-09 06:35:12 -08001156
cdalton5e58cee2016-02-11 12:49:47 -08001157 fOctavesUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001158 kFloat_GrSLType, kDefault_GrSLPrecision,
1159 "octaves");
1160 const char* octavesUni = uniformHandler->getUniformCStr(fOctavesUni);
ethannicholas417011c2015-11-09 06:35:12 -08001161
cdalton5e58cee2016-02-11 12:49:47 -08001162 fZUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001163 kFloat_GrSLType, kDefault_GrSLPrecision,
1164 "z");
1165 const char* zUni = uniformHandler->getUniformCStr(fZUni);
ethannicholas417011c2015-11-09 06:35:12 -08001166
1167 // fade function
1168 static const GrGLSLShaderVar fadeArgs[] = {
1169 GrGLSLShaderVar("t", kVec3f_GrSLType)
1170 };
1171 SkString fadeFuncName;
1172 fsBuilder->emitFunction(kVec3f_GrSLType, "fade", SK_ARRAY_COUNT(fadeArgs),
1173 fadeArgs,
1174 "return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);",
1175 &fadeFuncName);
1176
1177 // perm function
1178 static const GrGLSLShaderVar permArgs[] = {
1179 GrGLSLShaderVar("x", kFloat_GrSLType)
1180 };
1181 SkString permFuncName;
1182 SkString permCode("return ");
1183 // FIXME even though I'm creating these textures with kRepeat_TileMode, they're clamped. Not
1184 // sure why. Using fract() (here and the next texture lookup) as a workaround.
cdalton3f6f76f2016-04-11 12:18:09 -07001185 fsBuilder->appendTextureLookup(&permCode, args.fTexSamplers[0], "vec2(fract(x / 256.0), 0.0)",
ethannicholas417011c2015-11-09 06:35:12 -08001186 kVec2f_GrSLType);
1187 permCode.append(".r * 255.0;");
1188 fsBuilder->emitFunction(kFloat_GrSLType, "perm", SK_ARRAY_COUNT(permArgs), permArgs,
1189 permCode.c_str(), &permFuncName);
1190
1191 // grad function
1192 static const GrGLSLShaderVar gradArgs[] = {
1193 GrGLSLShaderVar("x", kFloat_GrSLType),
1194 GrGLSLShaderVar("p", kVec3f_GrSLType)
1195 };
1196 SkString gradFuncName;
1197 SkString gradCode("return dot(");
cdalton3f6f76f2016-04-11 12:18:09 -07001198 fsBuilder->appendTextureLookup(&gradCode, args.fTexSamplers[1], "vec2(fract(x / 16.0), 0.0)",
ethannicholas417011c2015-11-09 06:35:12 -08001199 kVec2f_GrSLType);
1200 gradCode.append(".rgb * 255.0 - vec3(1.0), p);");
1201 fsBuilder->emitFunction(kFloat_GrSLType, "grad", SK_ARRAY_COUNT(gradArgs), gradArgs,
1202 gradCode.c_str(), &gradFuncName);
1203
1204 // lerp function
1205 static const GrGLSLShaderVar lerpArgs[] = {
1206 GrGLSLShaderVar("a", kFloat_GrSLType),
1207 GrGLSLShaderVar("b", kFloat_GrSLType),
1208 GrGLSLShaderVar("w", kFloat_GrSLType)
1209 };
1210 SkString lerpFuncName;
1211 fsBuilder->emitFunction(kFloat_GrSLType, "lerp", SK_ARRAY_COUNT(lerpArgs), lerpArgs,
1212 "return a + w * (b - a);", &lerpFuncName);
1213
1214 // noise function
1215 static const GrGLSLShaderVar noiseArgs[] = {
1216 GrGLSLShaderVar("p", kVec3f_GrSLType),
1217 };
1218 SkString noiseFuncName;
1219 SkString noiseCode;
1220 noiseCode.append("vec3 P = mod(floor(p), 256.0);");
1221 noiseCode.append("p -= floor(p);");
1222 noiseCode.appendf("vec3 f = %s(p);", fadeFuncName.c_str());
1223 noiseCode.appendf("float A = %s(P.x) + P.y;", permFuncName.c_str());
1224 noiseCode.appendf("float AA = %s(A) + P.z;", permFuncName.c_str());
1225 noiseCode.appendf("float AB = %s(A + 1.0) + P.z;", permFuncName.c_str());
1226 noiseCode.appendf("float B = %s(P.x + 1.0) + P.y;", permFuncName.c_str());
1227 noiseCode.appendf("float BA = %s(B) + P.z;", permFuncName.c_str());
1228 noiseCode.appendf("float BB = %s(B + 1.0) + P.z;", permFuncName.c_str());
1229 noiseCode.appendf("float result = %s(", lerpFuncName.c_str());
1230 noiseCode.appendf("%s(%s(%s(%s(AA), p),", lerpFuncName.c_str(), lerpFuncName.c_str(),
1231 gradFuncName.c_str(), permFuncName.c_str());
1232 noiseCode.appendf("%s(%s(BA), p + vec3(-1.0, 0.0, 0.0)), f.x),", gradFuncName.c_str(),
1233 permFuncName.c_str());
1234 noiseCode.appendf("%s(%s(%s(AB), p + vec3(0.0, -1.0, 0.0)),", lerpFuncName.c_str(),
1235 gradFuncName.c_str(), permFuncName.c_str());
1236 noiseCode.appendf("%s(%s(BB), p + vec3(-1.0, -1.0, 0.0)), f.x), f.y),",
1237 gradFuncName.c_str(), permFuncName.c_str());
1238 noiseCode.appendf("%s(%s(%s(%s(AA + 1.0), p + vec3(0.0, 0.0, -1.0)),",
1239 lerpFuncName.c_str(), lerpFuncName.c_str(), gradFuncName.c_str(),
1240 permFuncName.c_str());
1241 noiseCode.appendf("%s(%s(BA + 1.0), p + vec3(-1.0, 0.0, -1.0)), f.x),",
1242 gradFuncName.c_str(), permFuncName.c_str());
1243 noiseCode.appendf("%s(%s(%s(AB + 1.0), p + vec3(0.0, -1.0, -1.0)),",
1244 lerpFuncName.c_str(), gradFuncName.c_str(), permFuncName.c_str());
1245 noiseCode.appendf("%s(%s(BB + 1.0), p + vec3(-1.0, -1.0, -1.0)), f.x), f.y), f.z);",
1246 gradFuncName.c_str(), permFuncName.c_str());
1247 noiseCode.append("return result;");
1248 fsBuilder->emitFunction(kFloat_GrSLType, "noise", SK_ARRAY_COUNT(noiseArgs), noiseArgs,
1249 noiseCode.c_str(), &noiseFuncName);
1250
1251 // noiseOctaves function
1252 static const GrGLSLShaderVar noiseOctavesArgs[] = {
1253 GrGLSLShaderVar("p", kVec3f_GrSLType),
1254 GrGLSLShaderVar("octaves", kFloat_GrSLType),
1255 };
1256 SkString noiseOctavesFuncName;
1257 SkString noiseOctavesCode;
1258 noiseOctavesCode.append("float result = 0.0;");
1259 noiseOctavesCode.append("float ratio = 1.0;");
1260 noiseOctavesCode.append("for (float i = 0.0; i < octaves; i++) {");
1261 noiseOctavesCode.appendf("result += %s(p) / ratio;", noiseFuncName.c_str());
1262 noiseOctavesCode.append("p *= 2.0;");
1263 noiseOctavesCode.append("ratio *= 2.0;");
1264 noiseOctavesCode.append("}");
1265 noiseOctavesCode.append("return (result + 1.0) / 2.0;");
1266 fsBuilder->emitFunction(kFloat_GrSLType, "noiseOctaves", SK_ARRAY_COUNT(noiseOctavesArgs),
1267 noiseOctavesArgs, noiseOctavesCode.c_str(), &noiseOctavesFuncName);
1268
1269 fsBuilder->codeAppendf("vec2 coords = %s * %s;", vCoords.c_str(), baseFrequencyUni);
1270 fsBuilder->codeAppendf("float r = %s(vec3(coords, %s), %s);", noiseOctavesFuncName.c_str(),
1271 zUni, octavesUni);
egdaniel478c04e2015-11-09 07:40:49 -08001272 fsBuilder->codeAppendf("float g = %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 b = %s(vec3(coords, %s + 0000.0), %s);",
ethannicholas417011c2015-11-09 06:35:12 -08001275 noiseOctavesFuncName.c_str(), zUni, octavesUni);
egdaniel478c04e2015-11-09 07:40:49 -08001276 fsBuilder->codeAppendf("float a = %s(vec3(coords, %s + 0000.0), %s);",
ethannicholas417011c2015-11-09 06:35:12 -08001277 noiseOctavesFuncName.c_str(), zUni, octavesUni);
1278 fsBuilder->codeAppendf("%s = vec4(r, g, b, a);", args.fOutputColor);
1279
1280 // Clamp values
1281 fsBuilder->codeAppendf("%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor);
1282
1283 // Pre-multiply the result
1284 fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
1285 args.fOutputColor, args.fOutputColor,
1286 args.fOutputColor, args.fOutputColor);
1287}
1288
1289void GrGLImprovedPerlinNoise::GenKey(const GrProcessor& processor, const GrGLSLCaps&,
1290 GrProcessorKeyBuilder* b) {
1291}
1292
1293void GrGLImprovedPerlinNoise::onSetData(const GrGLSLProgramDataManager& pdman,
1294 const GrProcessor& processor) {
1295 INHERITED::onSetData(pdman, processor);
1296
1297 const GrImprovedPerlinNoiseEffect& noise = processor.cast<GrImprovedPerlinNoiseEffect>();
1298
1299 const SkVector& baseFrequency = noise.baseFrequency();
1300 pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
1301
egdaniel478c04e2015-11-09 07:40:49 -08001302 pdman.set1f(fOctavesUni, SkIntToScalar(noise.octaves()));
ethannicholas417011c2015-11-09 06:35:12 -08001303
1304 pdman.set1f(fZUni, noise.z());
1305}
1306
1307/////////////////////////////////////////////////////////////////////
brianosman839345d2016-07-22 11:04:53 -07001308sk_sp<GrFragmentProcessor> SkPerlinNoiseShader2::asFragmentProcessor(const AsFPArgs& args) const {
1309 SkASSERT(args.fContext);
ethannicholas417011c2015-11-09 06:35:12 -08001310
1311 SkMatrix localMatrix = this->getLocalMatrix();
brianosman839345d2016-07-22 11:04:53 -07001312 if (args.fLocalMatrix) {
1313 localMatrix.preConcat(*args.fLocalMatrix);
ethannicholas417011c2015-11-09 06:35:12 -08001314 }
1315
brianosman839345d2016-07-22 11:04:53 -07001316 SkMatrix matrix = *args.fViewMatrix;
ethannicholas417011c2015-11-09 06:35:12 -08001317 matrix.preConcat(localMatrix);
1318
1319 // Either we don't stitch tiles, either we have a valid tile size
1320 SkASSERT(!fStitchTiles || !fTileSize.isEmpty());
1321
1322 SkPerlinNoiseShader2::PaintingData* paintingData =
1323 new PaintingData(fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY, matrix);
1324
brianosman839345d2016-07-22 11:04:53 -07001325 SkMatrix m = *args.fViewMatrix;
ethannicholas417011c2015-11-09 06:35:12 -08001326 m.setTranslateX(-localMatrix.getTranslateX() + SK_Scalar1);
1327 m.setTranslateY(-localMatrix.getTranslateY() + SK_Scalar1);
1328
1329 if (fType == kImprovedNoise_Type) {
1330 GrTextureParams textureParams(SkShader::TileMode::kRepeat_TileMode,
1331 GrTextureParams::FilterMode::kNone_FilterMode);
1332 SkAutoTUnref<GrTexture> permutationsTexture(
brianosman839345d2016-07-22 11:04:53 -07001333 GrRefCachedBitmapTexture(args.fContext, paintingData->getImprovedPermutationsBitmap(),
1334 textureParams, args.fGammaTreatment));
ethannicholas417011c2015-11-09 06:35:12 -08001335 SkAutoTUnref<GrTexture> gradientTexture(
brianosman839345d2016-07-22 11:04:53 -07001336 GrRefCachedBitmapTexture(args.fContext, paintingData->getGradientBitmap(),
1337 textureParams, args.fGammaTreatment));
bungeman06ca8ec2016-06-09 08:01:03 -07001338 return GrImprovedPerlinNoiseEffect::Make(fNumOctaves, fSeed, paintingData,
ethannicholas417011c2015-11-09 06:35:12 -08001339 permutationsTexture, gradientTexture, m);
1340 }
1341
1342 if (0 == fNumOctaves) {
1343 if (kFractalNoise_Type == fType) {
1344 // Extract the incoming alpha and emit rgba = (a/4, a/4, a/4, a/2)
bungeman06ca8ec2016-06-09 08:01:03 -07001345 sk_sp<GrFragmentProcessor> inner(
1346 GrConstColorProcessor::Make(0x80404040,
1347 GrConstColorProcessor::kModulateRGBA_InputMode));
1348 return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner));
ethannicholas417011c2015-11-09 06:35:12 -08001349 }
1350 // Emit zero.
bungeman06ca8ec2016-06-09 08:01:03 -07001351 return GrConstColorProcessor::Make(0x0, GrConstColorProcessor::kIgnore_InputMode);
ethannicholas417011c2015-11-09 06:35:12 -08001352 }
1353
1354 SkAutoTUnref<GrTexture> permutationsTexture(
brianosman839345d2016-07-22 11:04:53 -07001355 GrRefCachedBitmapTexture(args.fContext, paintingData->getPermutationsBitmap(),
1356 GrTextureParams::ClampNoFilter(), args.fGammaTreatment));
ethannicholas417011c2015-11-09 06:35:12 -08001357 SkAutoTUnref<GrTexture> noiseTexture(
brianosman839345d2016-07-22 11:04:53 -07001358 GrRefCachedBitmapTexture(args.fContext, paintingData->getNoiseBitmap(),
1359 GrTextureParams::ClampNoFilter(), args.fGammaTreatment));
ethannicholas417011c2015-11-09 06:35:12 -08001360
1361 if ((permutationsTexture) && (noiseTexture)) {
bungeman06ca8ec2016-06-09 08:01:03 -07001362 sk_sp<GrFragmentProcessor> inner(
1363 GrPerlinNoise2Effect::Make(fType,
1364 fNumOctaves,
1365 fStitchTiles,
1366 paintingData,
1367 permutationsTexture, noiseTexture,
1368 m));
1369 return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner));
ethannicholas417011c2015-11-09 06:35:12 -08001370 }
1371 delete paintingData;
1372 return nullptr;
1373}
1374
1375#endif
1376
1377#ifndef SK_IGNORE_TO_STRING
1378void SkPerlinNoiseShader2::toString(SkString* str) const {
1379 str->append("SkPerlinNoiseShader2: (");
1380
1381 str->append("type: ");
1382 switch (fType) {
1383 case kFractalNoise_Type:
1384 str->append("\"fractal noise\"");
1385 break;
1386 case kTurbulence_Type:
1387 str->append("\"turbulence\"");
1388 break;
1389 default:
1390 str->append("\"unknown\"");
1391 break;
1392 }
1393 str->append(" base frequency: (");
1394 str->appendScalar(fBaseFrequencyX);
1395 str->append(", ");
1396 str->appendScalar(fBaseFrequencyY);
1397 str->append(") number of octaves: ");
1398 str->appendS32(fNumOctaves);
1399 str->append(" seed: ");
1400 str->appendScalar(fSeed);
1401 str->append(" stitch tiles: ");
1402 str->append(fStitchTiles ? "true " : "false ");
1403
1404 this->INHERITED::toString(str);
1405
1406 str->append(")");
1407}
1408#endif