blob: b0c60f71610e5e48b2dd9a07ad892bd475e5533d [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;
731 return shader->asFragmentProcessor(d->fContext,
732 GrTest::TestMatrix(d->fRandom), nullptr,
brianosman982eb7f2016-06-06 13:10:58 -0700733 kNone_SkFilterQuality, SkSourceGammaTreatment::kRespect);
ethannicholas417011c2015-11-09 06:35:12 -0800734}
735
ethannicholas417011c2015-11-09 06:35:12 -0800736void GrGLPerlinNoise2::emitCode(EmitArgs& args) {
robertphillipsd3b32bf2016-02-05 07:15:39 -0800737 const GrPerlinNoise2Effect& pne = args.fFp.cast<GrPerlinNoise2Effect>();
738
egdaniel4ca2e602015-11-18 08:01:26 -0800739 GrGLSLFragmentBuilder* fsBuilder = args.fFragBuilder;
egdaniel7ea439b2015-12-03 09:20:44 -0800740 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
ethannicholas417011c2015-11-09 06:35:12 -0800741 SkString vCoords = fsBuilder->ensureFSCoords2D(args.fCoords, 0);
742
cdalton5e58cee2016-02-11 12:49:47 -0800743 fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800744 kVec2f_GrSLType, kDefault_GrSLPrecision,
745 "baseFrequency");
746 const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);
ethannicholas417011c2015-11-09 06:35:12 -0800747
748 const char* stitchDataUni = nullptr;
robertphillipsd3b32bf2016-02-05 07:15:39 -0800749 if (pne.stitchTiles()) {
cdalton5e58cee2016-02-11 12:49:47 -0800750 fStitchDataUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800751 kVec2f_GrSLType, kDefault_GrSLPrecision,
752 "stitchData");
753 stitchDataUni = uniformHandler->getUniformCStr(fStitchDataUni);
ethannicholas417011c2015-11-09 06:35:12 -0800754 }
755
756 // There are 4 lines, so the center of each line is 1/8, 3/8, 5/8 and 7/8
757 const char* chanCoordR = "0.125";
758 const char* chanCoordG = "0.375";
759 const char* chanCoordB = "0.625";
760 const char* chanCoordA = "0.875";
761 const char* chanCoord = "chanCoord";
762 const char* stitchData = "stitchData";
763 const char* ratio = "ratio";
764 const char* noiseVec = "noiseVec";
765 const char* noiseSmooth = "noiseSmooth";
766 const char* floorVal = "floorVal";
767 const char* fractVal = "fractVal";
768 const char* uv = "uv";
769 const char* ab = "ab";
770 const char* latticeIdx = "latticeIdx";
771 const char* bcoords = "bcoords";
772 const char* lattice = "lattice";
773 const char* inc8bit = "0.00390625"; // 1.0 / 256.0
774 // This is the math to convert the two 16bit integer packed into rgba 8 bit input into a
775 // [-1,1] vector and perform a dot product between that vector and the provided vector.
776 const char* dotLattice = "dot(((%s.ga + %s.rb * vec2(%s)) * vec2(2.0) - vec2(1.0)), %s);";
777
778 // Add noise function
779 static const GrGLSLShaderVar gPerlinNoiseArgs[] = {
780 GrGLSLShaderVar(chanCoord, kFloat_GrSLType),
781 GrGLSLShaderVar(noiseVec, kVec2f_GrSLType)
782 };
783
784 static const GrGLSLShaderVar gPerlinNoiseStitchArgs[] = {
785 GrGLSLShaderVar(chanCoord, kFloat_GrSLType),
786 GrGLSLShaderVar(noiseVec, kVec2f_GrSLType),
787 GrGLSLShaderVar(stitchData, kVec2f_GrSLType)
788 };
789
790 SkString noiseCode;
791
792 noiseCode.appendf("\tvec4 %s;\n", floorVal);
793 noiseCode.appendf("\t%s.xy = floor(%s);\n", floorVal, noiseVec);
794 noiseCode.appendf("\t%s.zw = %s.xy + vec2(1.0);\n", floorVal, floorVal);
795 noiseCode.appendf("\tvec2 %s = fract(%s);\n", fractVal, noiseVec);
796
797 // smooth curve : t * t * (3 - 2 * t)
798 noiseCode.appendf("\n\tvec2 %s = %s * %s * (vec2(3.0) - vec2(2.0) * %s);",
799 noiseSmooth, fractVal, fractVal, fractVal);
800
801 // Adjust frequencies if we're stitching tiles
robertphillipsd3b32bf2016-02-05 07:15:39 -0800802 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800803 noiseCode.appendf("\n\tif(%s.x >= %s.x) { %s.x -= %s.x; }",
804 floorVal, stitchData, floorVal, stitchData);
805 noiseCode.appendf("\n\tif(%s.y >= %s.y) { %s.y -= %s.y; }",
806 floorVal, stitchData, floorVal, stitchData);
807 noiseCode.appendf("\n\tif(%s.z >= %s.x) { %s.z -= %s.x; }",
808 floorVal, stitchData, floorVal, stitchData);
809 noiseCode.appendf("\n\tif(%s.w >= %s.y) { %s.w -= %s.y; }",
810 floorVal, stitchData, floorVal, stitchData);
811 }
812
813 // Get texture coordinates and normalize
814 noiseCode.appendf("\n\t%s = fract(floor(mod(%s, 256.0)) / vec4(256.0));\n",
815 floorVal, floorVal);
816
817 // Get permutation for x
818 {
819 SkString xCoords("");
820 xCoords.appendf("vec2(%s.x, 0.5)", floorVal);
821
822 noiseCode.appendf("\n\tvec2 %s;\n\t%s.x = ", latticeIdx, latticeIdx);
cdalton3f6f76f2016-04-11 12:18:09 -0700823 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800824 kVec2f_GrSLType);
825 noiseCode.append(".r;");
826 }
827
828 // Get permutation for x + 1
829 {
830 SkString xCoords("");
831 xCoords.appendf("vec2(%s.z, 0.5)", floorVal);
832
833 noiseCode.appendf("\n\t%s.y = ", latticeIdx);
cdalton3f6f76f2016-04-11 12:18:09 -0700834 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800835 kVec2f_GrSLType);
836 noiseCode.append(".r;");
837 }
838
839#if defined(SK_BUILD_FOR_ANDROID)
840 // Android rounding for Tegra devices, like, for example: Xoom (Tegra 2), Nexus 7 (Tegra 3).
841 // The issue is that colors aren't accurate enough on Tegra devices. For example, if an 8 bit
842 // value of 124 (or 0.486275 here) is entered, we can get a texture value of 123.513725
843 // (or 0.484368 here). The following rounding operation prevents these precision issues from
844 // affecting the result of the noise by making sure that we only have multiples of 1/255.
845 // (Note that 1/255 is about 0.003921569, which is the value used here).
846 noiseCode.appendf("\n\t%s = floor(%s * vec2(255.0) + vec2(0.5)) * vec2(0.003921569);",
847 latticeIdx, latticeIdx);
848#endif
849
850 // Get (x,y) coordinates with the permutated x
851 noiseCode.appendf("\n\tvec4 %s = fract(%s.xyxy + %s.yyww);", bcoords, latticeIdx, floorVal);
852
853 noiseCode.appendf("\n\n\tvec2 %s;", uv);
854 // Compute u, at offset (0,0)
855 {
856 SkString latticeCoords("");
857 latticeCoords.appendf("vec2(%s.x, %s)", bcoords, chanCoord);
858 noiseCode.appendf("\n\tvec4 %s = ", lattice);
cdalton3f6f76f2016-04-11 12:18:09 -0700859 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800860 kVec2f_GrSLType);
861 noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
862 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
863 }
864
865 noiseCode.appendf("\n\t%s.x -= 1.0;", fractVal);
866 // Compute v, at offset (-1,0)
867 {
868 SkString latticeCoords("");
869 latticeCoords.appendf("vec2(%s.y, %s)", bcoords, chanCoord);
870 noiseCode.append("\n\tlattice = ");
cdalton3f6f76f2016-04-11 12:18:09 -0700871 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800872 kVec2f_GrSLType);
873 noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
874 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
875 }
876
877 // Compute 'a' as a linear interpolation of 'u' and 'v'
878 noiseCode.appendf("\n\tvec2 %s;", ab);
879 noiseCode.appendf("\n\t%s.x = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
880
881 noiseCode.appendf("\n\t%s.y -= 1.0;", fractVal);
882 // Compute v, at offset (-1,-1)
883 {
884 SkString latticeCoords("");
885 latticeCoords.appendf("vec2(%s.w, %s)", bcoords, chanCoord);
886 noiseCode.append("\n\tlattice = ");
cdalton3f6f76f2016-04-11 12:18:09 -0700887 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800888 kVec2f_GrSLType);
889 noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
890 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
891 }
892
893 noiseCode.appendf("\n\t%s.x += 1.0;", fractVal);
894 // Compute u, at offset (0,-1)
895 {
896 SkString latticeCoords("");
897 latticeCoords.appendf("vec2(%s.z, %s)", bcoords, chanCoord);
898 noiseCode.append("\n\tlattice = ");
cdalton3f6f76f2016-04-11 12:18:09 -0700899 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800900 kVec2f_GrSLType);
901 noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
902 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
903 }
904
905 // Compute 'b' as a linear interpolation of 'u' and 'v'
906 noiseCode.appendf("\n\t%s.y = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
907 // Compute the noise as a linear interpolation of 'a' and 'b'
908 noiseCode.appendf("\n\treturn mix(%s.x, %s.y, %s.y);\n", ab, ab, noiseSmooth);
909
910 SkString noiseFuncName;
robertphillipsd3b32bf2016-02-05 07:15:39 -0800911 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800912 fsBuilder->emitFunction(kFloat_GrSLType,
913 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseStitchArgs),
914 gPerlinNoiseStitchArgs, noiseCode.c_str(), &noiseFuncName);
915 } else {
916 fsBuilder->emitFunction(kFloat_GrSLType,
917 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseArgs),
918 gPerlinNoiseArgs, noiseCode.c_str(), &noiseFuncName);
919 }
920
921 // There are rounding errors if the floor operation is not performed here
922 fsBuilder->codeAppendf("\n\t\tvec2 %s = floor(%s.xy) * %s;",
923 noiseVec, vCoords.c_str(), baseFrequencyUni);
924
925 // Clear the color accumulator
926 fsBuilder->codeAppendf("\n\t\t%s = vec4(0.0);", args.fOutputColor);
927
robertphillipsd3b32bf2016-02-05 07:15:39 -0800928 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800929 // Set up TurbulenceInitial stitch values.
930 fsBuilder->codeAppendf("\n\t\tvec2 %s = %s;", stitchData, stitchDataUni);
931 }
932
933 fsBuilder->codeAppendf("\n\t\tfloat %s = 1.0;", ratio);
934
935 // Loop over all octaves
robertphillipsd3b32bf2016-02-05 07:15:39 -0800936 fsBuilder->codeAppendf("for (int octave = 0; octave < %d; ++octave) {", pne.numOctaves());
ethannicholas417011c2015-11-09 06:35:12 -0800937
938 fsBuilder->codeAppendf("\n\t\t\t%s += ", args.fOutputColor);
robertphillipsd3b32bf2016-02-05 07:15:39 -0800939 if (pne.type() != SkPerlinNoiseShader2::kFractalNoise_Type) {
ethannicholas417011c2015-11-09 06:35:12 -0800940 fsBuilder->codeAppend("abs(");
941 }
robertphillipsd3b32bf2016-02-05 07:15:39 -0800942 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800943 fsBuilder->codeAppendf(
944 "vec4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s),"
945 "\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))",
946 noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData,
947 noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData,
948 noiseFuncName.c_str(), chanCoordB, noiseVec, stitchData,
949 noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData);
950 } else {
951 fsBuilder->codeAppendf(
952 "vec4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s),"
953 "\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))",
954 noiseFuncName.c_str(), chanCoordR, noiseVec,
955 noiseFuncName.c_str(), chanCoordG, noiseVec,
956 noiseFuncName.c_str(), chanCoordB, noiseVec,
957 noiseFuncName.c_str(), chanCoordA, noiseVec);
958 }
robertphillipsd3b32bf2016-02-05 07:15:39 -0800959 if (pne.type() != SkPerlinNoiseShader2::kFractalNoise_Type) {
ethannicholas417011c2015-11-09 06:35:12 -0800960 fsBuilder->codeAppendf(")"); // end of "abs("
961 }
962 fsBuilder->codeAppendf(" * %s;", ratio);
963
964 fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", noiseVec);
965 fsBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio);
966
robertphillipsd3b32bf2016-02-05 07:15:39 -0800967 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800968 fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", stitchData);
969 }
970 fsBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves
971
robertphillipsd3b32bf2016-02-05 07:15:39 -0800972 if (pne.type() == SkPerlinNoiseShader2::kFractalNoise_Type) {
ethannicholas417011c2015-11-09 06:35:12 -0800973 // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
974 // by fractalNoise and (turbulenceFunctionResult) by turbulence.
975 fsBuilder->codeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);",
976 args.fOutputColor,args.fOutputColor);
977 }
978
979 // Clamp values
980 fsBuilder->codeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor);
981
982 // Pre-multiply the result
983 fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
984 args.fOutputColor, args.fOutputColor,
985 args.fOutputColor, args.fOutputColor);
986}
987
988void GrGLPerlinNoise2::GenKey(const GrProcessor& processor, const GrGLSLCaps&,
egdaniel2d721d32015-11-11 13:06:05 -0800989 GrProcessorKeyBuilder* b) {
ethannicholas417011c2015-11-09 06:35:12 -0800990 const GrPerlinNoise2Effect& turbulence = processor.cast<GrPerlinNoise2Effect>();
991
992 uint32_t key = turbulence.numOctaves();
993
994 key = key << 3; // Make room for next 3 bits
995
996 switch (turbulence.type()) {
997 case SkPerlinNoiseShader2::kFractalNoise_Type:
998 key |= 0x1;
999 break;
1000 case SkPerlinNoiseShader2::kTurbulence_Type:
1001 key |= 0x2;
1002 break;
1003 default:
1004 // leave key at 0
1005 break;
1006 }
1007
1008 if (turbulence.stitchTiles()) {
1009 key |= 0x4; // Flip the 3rd bit if tile stitching is on
1010 }
1011
1012 b->add32(key);
1013}
1014
1015void GrGLPerlinNoise2::onSetData(const GrGLSLProgramDataManager& pdman,
1016 const GrProcessor& processor) {
1017 INHERITED::onSetData(pdman, processor);
1018
1019 const GrPerlinNoise2Effect& turbulence = processor.cast<GrPerlinNoise2Effect>();
1020
1021 const SkVector& baseFrequency = turbulence.baseFrequency();
1022 pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
1023
1024 if (turbulence.stitchTiles()) {
1025 const SkPerlinNoiseShader2::StitchData& stitchData = turbulence.stitchData();
1026 pdman.set2f(fStitchDataUni, SkIntToScalar(stitchData.fWidth),
1027 SkIntToScalar(stitchData.fHeight));
1028 }
1029}
1030
1031/////////////////////////////////////////////////////////////////////
1032
egdaniel64c47282015-11-13 06:54:19 -08001033class GrGLImprovedPerlinNoise : public GrGLSLFragmentProcessor {
ethannicholas417011c2015-11-09 06:35:12 -08001034public:
robertphillipsbf536af2016-02-04 06:11:53 -08001035 void emitCode(EmitArgs&) override;
ethannicholas417011c2015-11-09 06:35:12 -08001036
robertphillipsbf536af2016-02-04 06:11:53 -08001037 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*);
ethannicholas417011c2015-11-09 06:35:12 -08001038
1039protected:
1040 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
1041
1042private:
ethannicholas417011c2015-11-09 06:35:12 -08001043 GrGLSLProgramDataManager::UniformHandle fZUni;
1044 GrGLSLProgramDataManager::UniformHandle fOctavesUni;
1045 GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni;
1046
egdaniel64c47282015-11-13 06:54:19 -08001047 typedef GrGLSLFragmentProcessor INHERITED;
ethannicholas417011c2015-11-09 06:35:12 -08001048};
1049
1050/////////////////////////////////////////////////////////////////////
1051
1052class GrImprovedPerlinNoiseEffect : public GrFragmentProcessor {
1053public:
bungeman06ca8ec2016-06-09 08:01:03 -07001054 static sk_sp<GrFragmentProcessor> Make(int octaves, SkScalar z,
1055 SkPerlinNoiseShader2::PaintingData* paintingData,
1056 GrTexture* permutationsTexture,
1057 GrTexture* gradientTexture,
1058 const SkMatrix& matrix) {
1059 return sk_sp<GrFragmentProcessor>(
1060 new GrImprovedPerlinNoiseEffect(octaves, z, paintingData, permutationsTexture,
1061 gradientTexture, matrix));
ethannicholas417011c2015-11-09 06:35:12 -08001062 }
1063
1064 virtual ~GrImprovedPerlinNoiseEffect() { delete fPaintingData; }
1065
1066 const char* name() const override { return "ImprovedPerlinNoise"; }
1067
1068 const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; }
1069 SkScalar z() const { return fZ; }
1070 int octaves() const { return fOctaves; }
1071 const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
1072
1073private:
egdaniel57d3b032015-11-13 11:57:27 -08001074 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
robertphillipsbf536af2016-02-04 06:11:53 -08001075 return new GrGLImprovedPerlinNoise;
ethannicholas417011c2015-11-09 06:35:12 -08001076 }
1077
robertphillipsbf536af2016-02-04 06:11:53 -08001078 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
ethannicholas417011c2015-11-09 06:35:12 -08001079 GrGLImprovedPerlinNoise::GenKey(*this, caps, b);
1080 }
1081
1082 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
1083 const GrImprovedPerlinNoiseEffect& s = sBase.cast<GrImprovedPerlinNoiseEffect>();
1084 return fZ == fZ &&
1085 fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency;
1086 }
1087
1088 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
1089 inout->setToUnknown(GrInvariantOutput::kWillNot_ReadInput);
1090 }
1091
1092 GrImprovedPerlinNoiseEffect(int octaves, SkScalar z,
1093 SkPerlinNoiseShader2::PaintingData* paintingData,
1094 GrTexture* permutationsTexture, GrTexture* gradientTexture,
1095 const SkMatrix& matrix)
1096 : fOctaves(octaves)
1097 , fZ(z)
1098 , fPermutationsAccess(permutationsTexture)
1099 , fGradientAccess(gradientTexture)
1100 , fPaintingData(paintingData) {
1101 this->initClassID<GrImprovedPerlinNoiseEffect>();
1102 this->addTextureAccess(&fPermutationsAccess);
1103 this->addTextureAccess(&fGradientAccess);
1104 fCoordTransform.reset(kLocal_GrCoordSet, matrix);
1105 this->addCoordTransform(&fCoordTransform);
1106 }
1107
1108 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
1109
1110 GrCoordTransform fCoordTransform;
1111 int fOctaves;
1112 SkScalar fZ;
1113 GrTextureAccess fPermutationsAccess;
1114 GrTextureAccess fGradientAccess;
1115 SkPerlinNoiseShader2::PaintingData *fPaintingData;
1116
1117private:
1118 typedef GrFragmentProcessor INHERITED;
1119};
1120
1121/////////////////////////////////////////////////////////////////////
1122GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrImprovedPerlinNoiseEffect);
1123
bungeman06ca8ec2016-06-09 08:01:03 -07001124sk_sp<GrFragmentProcessor> GrImprovedPerlinNoiseEffect::TestCreate(GrProcessorTestData* d) {
ethannicholas417011c2015-11-09 06:35:12 -08001125 SkScalar baseFrequencyX = d->fRandom->nextRangeScalar(0.01f,
1126 0.99f);
1127 SkScalar baseFrequencyY = d->fRandom->nextRangeScalar(0.01f,
1128 0.99f);
1129 int numOctaves = d->fRandom->nextRangeU(2, 10);
1130 SkScalar z = SkIntToScalar(d->fRandom->nextU());
1131
reed8a21c9f2016-03-08 18:50:00 -08001132 sk_sp<SkShader> shader(SkPerlinNoiseShader2::MakeImprovedNoise(baseFrequencyX,
1133 baseFrequencyY,
1134 numOctaves,
1135 z));
ethannicholas417011c2015-11-09 06:35:12 -08001136
1137 GrPaint grPaint;
1138 return shader->asFragmentProcessor(d->fContext,
1139 GrTest::TestMatrix(d->fRandom), nullptr,
brianosman982eb7f2016-06-06 13:10:58 -07001140 kNone_SkFilterQuality, SkSourceGammaTreatment::kRespect);
ethannicholas417011c2015-11-09 06:35:12 -08001141}
1142
ethannicholas417011c2015-11-09 06:35:12 -08001143void GrGLImprovedPerlinNoise::emitCode(EmitArgs& args) {
egdaniel4ca2e602015-11-18 08:01:26 -08001144 GrGLSLFragmentBuilder* fsBuilder = args.fFragBuilder;
egdaniel7ea439b2015-12-03 09:20:44 -08001145 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
ethannicholas417011c2015-11-09 06:35:12 -08001146 SkString vCoords = fsBuilder->ensureFSCoords2D(args.fCoords, 0);
1147
cdalton5e58cee2016-02-11 12:49:47 -08001148 fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001149 kVec2f_GrSLType, kDefault_GrSLPrecision,
1150 "baseFrequency");
1151 const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);
ethannicholas417011c2015-11-09 06:35:12 -08001152
cdalton5e58cee2016-02-11 12:49:47 -08001153 fOctavesUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001154 kFloat_GrSLType, kDefault_GrSLPrecision,
1155 "octaves");
1156 const char* octavesUni = uniformHandler->getUniformCStr(fOctavesUni);
ethannicholas417011c2015-11-09 06:35:12 -08001157
cdalton5e58cee2016-02-11 12:49:47 -08001158 fZUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001159 kFloat_GrSLType, kDefault_GrSLPrecision,
1160 "z");
1161 const char* zUni = uniformHandler->getUniformCStr(fZUni);
ethannicholas417011c2015-11-09 06:35:12 -08001162
1163 // fade function
1164 static const GrGLSLShaderVar fadeArgs[] = {
1165 GrGLSLShaderVar("t", kVec3f_GrSLType)
1166 };
1167 SkString fadeFuncName;
1168 fsBuilder->emitFunction(kVec3f_GrSLType, "fade", SK_ARRAY_COUNT(fadeArgs),
1169 fadeArgs,
1170 "return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);",
1171 &fadeFuncName);
1172
1173 // perm function
1174 static const GrGLSLShaderVar permArgs[] = {
1175 GrGLSLShaderVar("x", kFloat_GrSLType)
1176 };
1177 SkString permFuncName;
1178 SkString permCode("return ");
1179 // FIXME even though I'm creating these textures with kRepeat_TileMode, they're clamped. Not
1180 // sure why. Using fract() (here and the next texture lookup) as a workaround.
cdalton3f6f76f2016-04-11 12:18:09 -07001181 fsBuilder->appendTextureLookup(&permCode, args.fTexSamplers[0], "vec2(fract(x / 256.0), 0.0)",
ethannicholas417011c2015-11-09 06:35:12 -08001182 kVec2f_GrSLType);
1183 permCode.append(".r * 255.0;");
1184 fsBuilder->emitFunction(kFloat_GrSLType, "perm", SK_ARRAY_COUNT(permArgs), permArgs,
1185 permCode.c_str(), &permFuncName);
1186
1187 // grad function
1188 static const GrGLSLShaderVar gradArgs[] = {
1189 GrGLSLShaderVar("x", kFloat_GrSLType),
1190 GrGLSLShaderVar("p", kVec3f_GrSLType)
1191 };
1192 SkString gradFuncName;
1193 SkString gradCode("return dot(");
cdalton3f6f76f2016-04-11 12:18:09 -07001194 fsBuilder->appendTextureLookup(&gradCode, args.fTexSamplers[1], "vec2(fract(x / 16.0), 0.0)",
ethannicholas417011c2015-11-09 06:35:12 -08001195 kVec2f_GrSLType);
1196 gradCode.append(".rgb * 255.0 - vec3(1.0), p);");
1197 fsBuilder->emitFunction(kFloat_GrSLType, "grad", SK_ARRAY_COUNT(gradArgs), gradArgs,
1198 gradCode.c_str(), &gradFuncName);
1199
1200 // lerp function
1201 static const GrGLSLShaderVar lerpArgs[] = {
1202 GrGLSLShaderVar("a", kFloat_GrSLType),
1203 GrGLSLShaderVar("b", kFloat_GrSLType),
1204 GrGLSLShaderVar("w", kFloat_GrSLType)
1205 };
1206 SkString lerpFuncName;
1207 fsBuilder->emitFunction(kFloat_GrSLType, "lerp", SK_ARRAY_COUNT(lerpArgs), lerpArgs,
1208 "return a + w * (b - a);", &lerpFuncName);
1209
1210 // noise function
1211 static const GrGLSLShaderVar noiseArgs[] = {
1212 GrGLSLShaderVar("p", kVec3f_GrSLType),
1213 };
1214 SkString noiseFuncName;
1215 SkString noiseCode;
1216 noiseCode.append("vec3 P = mod(floor(p), 256.0);");
1217 noiseCode.append("p -= floor(p);");
1218 noiseCode.appendf("vec3 f = %s(p);", fadeFuncName.c_str());
1219 noiseCode.appendf("float A = %s(P.x) + P.y;", permFuncName.c_str());
1220 noiseCode.appendf("float AA = %s(A) + P.z;", permFuncName.c_str());
1221 noiseCode.appendf("float AB = %s(A + 1.0) + P.z;", permFuncName.c_str());
1222 noiseCode.appendf("float B = %s(P.x + 1.0) + P.y;", permFuncName.c_str());
1223 noiseCode.appendf("float BA = %s(B) + P.z;", permFuncName.c_str());
1224 noiseCode.appendf("float BB = %s(B + 1.0) + P.z;", permFuncName.c_str());
1225 noiseCode.appendf("float result = %s(", lerpFuncName.c_str());
1226 noiseCode.appendf("%s(%s(%s(%s(AA), p),", lerpFuncName.c_str(), lerpFuncName.c_str(),
1227 gradFuncName.c_str(), permFuncName.c_str());
1228 noiseCode.appendf("%s(%s(BA), p + vec3(-1.0, 0.0, 0.0)), f.x),", gradFuncName.c_str(),
1229 permFuncName.c_str());
1230 noiseCode.appendf("%s(%s(%s(AB), p + vec3(0.0, -1.0, 0.0)),", lerpFuncName.c_str(),
1231 gradFuncName.c_str(), permFuncName.c_str());
1232 noiseCode.appendf("%s(%s(BB), p + vec3(-1.0, -1.0, 0.0)), f.x), f.y),",
1233 gradFuncName.c_str(), permFuncName.c_str());
1234 noiseCode.appendf("%s(%s(%s(%s(AA + 1.0), p + vec3(0.0, 0.0, -1.0)),",
1235 lerpFuncName.c_str(), lerpFuncName.c_str(), gradFuncName.c_str(),
1236 permFuncName.c_str());
1237 noiseCode.appendf("%s(%s(BA + 1.0), p + vec3(-1.0, 0.0, -1.0)), f.x),",
1238 gradFuncName.c_str(), permFuncName.c_str());
1239 noiseCode.appendf("%s(%s(%s(AB + 1.0), p + vec3(0.0, -1.0, -1.0)),",
1240 lerpFuncName.c_str(), gradFuncName.c_str(), permFuncName.c_str());
1241 noiseCode.appendf("%s(%s(BB + 1.0), p + vec3(-1.0, -1.0, -1.0)), f.x), f.y), f.z);",
1242 gradFuncName.c_str(), permFuncName.c_str());
1243 noiseCode.append("return result;");
1244 fsBuilder->emitFunction(kFloat_GrSLType, "noise", SK_ARRAY_COUNT(noiseArgs), noiseArgs,
1245 noiseCode.c_str(), &noiseFuncName);
1246
1247 // noiseOctaves function
1248 static const GrGLSLShaderVar noiseOctavesArgs[] = {
1249 GrGLSLShaderVar("p", kVec3f_GrSLType),
1250 GrGLSLShaderVar("octaves", kFloat_GrSLType),
1251 };
1252 SkString noiseOctavesFuncName;
1253 SkString noiseOctavesCode;
1254 noiseOctavesCode.append("float result = 0.0;");
1255 noiseOctavesCode.append("float ratio = 1.0;");
1256 noiseOctavesCode.append("for (float i = 0.0; i < octaves; i++) {");
1257 noiseOctavesCode.appendf("result += %s(p) / ratio;", noiseFuncName.c_str());
1258 noiseOctavesCode.append("p *= 2.0;");
1259 noiseOctavesCode.append("ratio *= 2.0;");
1260 noiseOctavesCode.append("}");
1261 noiseOctavesCode.append("return (result + 1.0) / 2.0;");
1262 fsBuilder->emitFunction(kFloat_GrSLType, "noiseOctaves", SK_ARRAY_COUNT(noiseOctavesArgs),
1263 noiseOctavesArgs, noiseOctavesCode.c_str(), &noiseOctavesFuncName);
1264
1265 fsBuilder->codeAppendf("vec2 coords = %s * %s;", vCoords.c_str(), baseFrequencyUni);
1266 fsBuilder->codeAppendf("float r = %s(vec3(coords, %s), %s);", noiseOctavesFuncName.c_str(),
1267 zUni, octavesUni);
egdaniel478c04e2015-11-09 07:40:49 -08001268 fsBuilder->codeAppendf("float g = %s(vec3(coords, %s + 0000.0), %s);",
ethannicholas417011c2015-11-09 06:35:12 -08001269 noiseOctavesFuncName.c_str(), zUni, octavesUni);
egdaniel478c04e2015-11-09 07:40:49 -08001270 fsBuilder->codeAppendf("float b = %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 a = %s(vec3(coords, %s + 0000.0), %s);",
ethannicholas417011c2015-11-09 06:35:12 -08001273 noiseOctavesFuncName.c_str(), zUni, octavesUni);
1274 fsBuilder->codeAppendf("%s = vec4(r, g, b, a);", args.fOutputColor);
1275
1276 // Clamp values
1277 fsBuilder->codeAppendf("%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor);
1278
1279 // Pre-multiply the result
1280 fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
1281 args.fOutputColor, args.fOutputColor,
1282 args.fOutputColor, args.fOutputColor);
1283}
1284
1285void GrGLImprovedPerlinNoise::GenKey(const GrProcessor& processor, const GrGLSLCaps&,
1286 GrProcessorKeyBuilder* b) {
1287}
1288
1289void GrGLImprovedPerlinNoise::onSetData(const GrGLSLProgramDataManager& pdman,
1290 const GrProcessor& processor) {
1291 INHERITED::onSetData(pdman, processor);
1292
1293 const GrImprovedPerlinNoiseEffect& noise = processor.cast<GrImprovedPerlinNoiseEffect>();
1294
1295 const SkVector& baseFrequency = noise.baseFrequency();
1296 pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
1297
egdaniel478c04e2015-11-09 07:40:49 -08001298 pdman.set1f(fOctavesUni, SkIntToScalar(noise.octaves()));
ethannicholas417011c2015-11-09 06:35:12 -08001299
1300 pdman.set1f(fZUni, noise.z());
1301}
1302
1303/////////////////////////////////////////////////////////////////////
bungeman06ca8ec2016-06-09 08:01:03 -07001304sk_sp<GrFragmentProcessor> SkPerlinNoiseShader2::asFragmentProcessor(
ethannicholas417011c2015-11-09 06:35:12 -08001305 GrContext* context,
1306 const SkMatrix& viewM,
1307 const SkMatrix* externalLocalMatrix,
brianosman982eb7f2016-06-06 13:10:58 -07001308 SkFilterQuality,
1309 SkSourceGammaTreatment gammaTreatment) const {
ethannicholas417011c2015-11-09 06:35:12 -08001310 SkASSERT(context);
1311
1312 SkMatrix localMatrix = this->getLocalMatrix();
1313 if (externalLocalMatrix) {
1314 localMatrix.preConcat(*externalLocalMatrix);
1315 }
1316
1317 SkMatrix matrix = viewM;
1318 matrix.preConcat(localMatrix);
1319
1320 // Either we don't stitch tiles, either we have a valid tile size
1321 SkASSERT(!fStitchTiles || !fTileSize.isEmpty());
1322
1323 SkPerlinNoiseShader2::PaintingData* paintingData =
1324 new PaintingData(fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY, matrix);
1325
1326 SkMatrix m = viewM;
1327 m.setTranslateX(-localMatrix.getTranslateX() + SK_Scalar1);
1328 m.setTranslateY(-localMatrix.getTranslateY() + SK_Scalar1);
1329
1330 if (fType == kImprovedNoise_Type) {
1331 GrTextureParams textureParams(SkShader::TileMode::kRepeat_TileMode,
1332 GrTextureParams::FilterMode::kNone_FilterMode);
1333 SkAutoTUnref<GrTexture> permutationsTexture(
1334 GrRefCachedBitmapTexture(context, paintingData->getImprovedPermutationsBitmap(),
brianosman982eb7f2016-06-06 13:10:58 -07001335 textureParams, gammaTreatment));
ethannicholas417011c2015-11-09 06:35:12 -08001336 SkAutoTUnref<GrTexture> gradientTexture(
1337 GrRefCachedBitmapTexture(context, paintingData->getGradientBitmap(),
brianosman982eb7f2016-06-06 13:10:58 -07001338 textureParams, gammaTreatment));
bungeman06ca8ec2016-06-09 08:01:03 -07001339 return GrImprovedPerlinNoiseEffect::Make(fNumOctaves, fSeed, paintingData,
ethannicholas417011c2015-11-09 06:35:12 -08001340 permutationsTexture, gradientTexture, m);
1341 }
1342
1343 if (0 == fNumOctaves) {
1344 if (kFractalNoise_Type == fType) {
1345 // Extract the incoming alpha and emit rgba = (a/4, a/4, a/4, a/2)
bungeman06ca8ec2016-06-09 08:01:03 -07001346 sk_sp<GrFragmentProcessor> inner(
1347 GrConstColorProcessor::Make(0x80404040,
1348 GrConstColorProcessor::kModulateRGBA_InputMode));
1349 return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner));
ethannicholas417011c2015-11-09 06:35:12 -08001350 }
1351 // Emit zero.
bungeman06ca8ec2016-06-09 08:01:03 -07001352 return GrConstColorProcessor::Make(0x0, GrConstColorProcessor::kIgnore_InputMode);
ethannicholas417011c2015-11-09 06:35:12 -08001353 }
1354
1355 SkAutoTUnref<GrTexture> permutationsTexture(
1356 GrRefCachedBitmapTexture(context, paintingData->getPermutationsBitmap(),
brianosman982eb7f2016-06-06 13:10:58 -07001357 GrTextureParams::ClampNoFilter(), gammaTreatment));
ethannicholas417011c2015-11-09 06:35:12 -08001358 SkAutoTUnref<GrTexture> noiseTexture(
1359 GrRefCachedBitmapTexture(context, paintingData->getNoiseBitmap(),
brianosman982eb7f2016-06-06 13:10:58 -07001360 GrTextureParams::ClampNoFilter(), gammaTreatment));
ethannicholas417011c2015-11-09 06:35:12 -08001361
1362 if ((permutationsTexture) && (noiseTexture)) {
bungeman06ca8ec2016-06-09 08:01:03 -07001363 sk_sp<GrFragmentProcessor> inner(
1364 GrPerlinNoise2Effect::Make(fType,
1365 fNumOctaves,
1366 fStitchTiles,
1367 paintingData,
1368 permutationsTexture, noiseTexture,
1369 m));
1370 return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner));
ethannicholas417011c2015-11-09 06:35:12 -08001371 }
1372 delete paintingData;
1373 return nullptr;
1374}
1375
1376#endif
1377
1378#ifndef SK_IGNORE_TO_STRING
1379void SkPerlinNoiseShader2::toString(SkString* str) const {
1380 str->append("SkPerlinNoiseShader2: (");
1381
1382 str->append("type: ");
1383 switch (fType) {
1384 case kFractalNoise_Type:
1385 str->append("\"fractal noise\"");
1386 break;
1387 case kTurbulence_Type:
1388 str->append("\"turbulence\"");
1389 break;
1390 default:
1391 str->append("\"unknown\"");
1392 break;
1393 }
1394 str->append(" base frequency: (");
1395 str->appendScalar(fBaseFrequencyX);
1396 str->append(", ");
1397 str->appendScalar(fBaseFrequencyY);
1398 str->append(") number of octaves: ");
1399 str->appendS32(fNumOctaves);
1400 str->append(" seed: ");
1401 str->appendScalar(fSeed);
1402 str->append(" stitch tiles: ");
1403 str->append(fStitchTiles ? "true " : "false ");
1404
1405 this->INHERITED::toString(str);
1406
1407 str->append(")");
1408}
1409#endif