blob: f3040673fcc20e9f71828a99366446d97ba400fb [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
Brian Salomon94efbf52016-11-29 13:43:05 -0500617 static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder* b);
ethannicholas417011c2015-11-09 06:35:12 -0800618
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
Brian Salomon94efbf52016-11-29 13:43:05 -0500660 virtual void onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800661 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)
Brian Salomon0bbecb22016-11-17 11:38:22 -0500686 , fPermutationsSampler(permutationsTexture)
687 , fNoiseSampler(noiseTexture)
ethannicholas417011c2015-11-09 06:35:12 -0800688 , fPaintingData(paintingData) {
689 this->initClassID<GrPerlinNoise2Effect>();
Brian Salomon0bbecb22016-11-17 11:38:22 -0500690 this->addTextureSampler(&fPermutationsSampler);
691 this->addTextureSampler(&fNoiseSampler);
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
Brian Salomon0bbecb22016-11-17 11:38:22 -0500698 SkPerlinNoiseShader2::Type fType;
699 GrCoordTransform fCoordTransform;
700 int fNumOctaves;
701 bool fStitchTiles;
702 TextureSampler fPermutationsSampler;
703 TextureSampler fNoiseSampler;
704 SkPerlinNoiseShader2::PaintingData* fPaintingData;
ethannicholas417011c2015-11-09 06:35:12 -0800705
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
Brian Osman9f532a32016-10-19 11:12:09 -0400730 GrTest::TestAsFPArgs asFPArgs(d);
731 return shader->asFragmentProcessor(asFPArgs.args());
ethannicholas417011c2015-11-09 06:35:12 -0800732}
733
ethannicholas417011c2015-11-09 06:35:12 -0800734void GrGLPerlinNoise2::emitCode(EmitArgs& args) {
robertphillipsd3b32bf2016-02-05 07:15:39 -0800735 const GrPerlinNoise2Effect& pne = args.fFp.cast<GrPerlinNoise2Effect>();
736
egdaniel4ca2e602015-11-18 08:01:26 -0800737 GrGLSLFragmentBuilder* fsBuilder = args.fFragBuilder;
egdaniel7ea439b2015-12-03 09:20:44 -0800738 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
bsalomon1a1aa932016-09-12 09:30:36 -0700739 SkString vCoords = fsBuilder->ensureCoords2D(args.fTransformedCoords[0]);
ethannicholas417011c2015-11-09 06:35:12 -0800740
cdalton5e58cee2016-02-11 12:49:47 -0800741 fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800742 kVec2f_GrSLType, kDefault_GrSLPrecision,
743 "baseFrequency");
744 const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);
ethannicholas417011c2015-11-09 06:35:12 -0800745
746 const char* stitchDataUni = nullptr;
robertphillipsd3b32bf2016-02-05 07:15:39 -0800747 if (pne.stitchTiles()) {
cdalton5e58cee2016-02-11 12:49:47 -0800748 fStitchDataUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800749 kVec2f_GrSLType, kDefault_GrSLPrecision,
750 "stitchData");
751 stitchDataUni = uniformHandler->getUniformCStr(fStitchDataUni);
ethannicholas417011c2015-11-09 06:35:12 -0800752 }
753
754 // There are 4 lines, so the center of each line is 1/8, 3/8, 5/8 and 7/8
755 const char* chanCoordR = "0.125";
756 const char* chanCoordG = "0.375";
757 const char* chanCoordB = "0.625";
758 const char* chanCoordA = "0.875";
759 const char* chanCoord = "chanCoord";
760 const char* stitchData = "stitchData";
761 const char* ratio = "ratio";
762 const char* noiseVec = "noiseVec";
763 const char* noiseSmooth = "noiseSmooth";
764 const char* floorVal = "floorVal";
765 const char* fractVal = "fractVal";
766 const char* uv = "uv";
767 const char* ab = "ab";
768 const char* latticeIdx = "latticeIdx";
769 const char* bcoords = "bcoords";
770 const char* lattice = "lattice";
771 const char* inc8bit = "0.00390625"; // 1.0 / 256.0
772 // This is the math to convert the two 16bit integer packed into rgba 8 bit input into a
773 // [-1,1] vector and perform a dot product between that vector and the provided vector.
774 const char* dotLattice = "dot(((%s.ga + %s.rb * vec2(%s)) * vec2(2.0) - vec2(1.0)), %s);";
775
776 // Add noise function
Brian Salomon99938a82016-11-21 13:41:08 -0500777 static const GrShaderVar gPerlinNoiseArgs[] = {
778 GrShaderVar(chanCoord, kFloat_GrSLType),
779 GrShaderVar(noiseVec, kVec2f_GrSLType)
ethannicholas417011c2015-11-09 06:35:12 -0800780 };
781
Brian Salomon99938a82016-11-21 13:41:08 -0500782 static const GrShaderVar gPerlinNoiseStitchArgs[] = {
783 GrShaderVar(chanCoord, kFloat_GrSLType),
784 GrShaderVar(noiseVec, kVec2f_GrSLType),
785 GrShaderVar(stitchData, kVec2f_GrSLType)
ethannicholas417011c2015-11-09 06:35:12 -0800786 };
787
788 SkString noiseCode;
789
790 noiseCode.appendf("\tvec4 %s;\n", floorVal);
791 noiseCode.appendf("\t%s.xy = floor(%s);\n", floorVal, noiseVec);
792 noiseCode.appendf("\t%s.zw = %s.xy + vec2(1.0);\n", floorVal, floorVal);
793 noiseCode.appendf("\tvec2 %s = fract(%s);\n", fractVal, noiseVec);
794
795 // smooth curve : t * t * (3 - 2 * t)
796 noiseCode.appendf("\n\tvec2 %s = %s * %s * (vec2(3.0) - vec2(2.0) * %s);",
797 noiseSmooth, fractVal, fractVal, fractVal);
798
799 // Adjust frequencies if we're stitching tiles
robertphillipsd3b32bf2016-02-05 07:15:39 -0800800 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800801 noiseCode.appendf("\n\tif(%s.x >= %s.x) { %s.x -= %s.x; }",
802 floorVal, stitchData, floorVal, stitchData);
803 noiseCode.appendf("\n\tif(%s.y >= %s.y) { %s.y -= %s.y; }",
804 floorVal, stitchData, floorVal, stitchData);
805 noiseCode.appendf("\n\tif(%s.z >= %s.x) { %s.z -= %s.x; }",
806 floorVal, stitchData, floorVal, stitchData);
807 noiseCode.appendf("\n\tif(%s.w >= %s.y) { %s.w -= %s.y; }",
808 floorVal, stitchData, floorVal, stitchData);
809 }
810
811 // Get texture coordinates and normalize
812 noiseCode.appendf("\n\t%s = fract(floor(mod(%s, 256.0)) / vec4(256.0));\n",
813 floorVal, floorVal);
814
815 // Get permutation for x
816 {
817 SkString xCoords("");
818 xCoords.appendf("vec2(%s.x, 0.5)", floorVal);
819
820 noiseCode.appendf("\n\tvec2 %s;\n\t%s.x = ", latticeIdx, latticeIdx);
cdalton3f6f76f2016-04-11 12:18:09 -0700821 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800822 kVec2f_GrSLType);
823 noiseCode.append(".r;");
824 }
825
826 // Get permutation for x + 1
827 {
828 SkString xCoords("");
829 xCoords.appendf("vec2(%s.z, 0.5)", floorVal);
830
831 noiseCode.appendf("\n\t%s.y = ", latticeIdx);
cdalton3f6f76f2016-04-11 12:18:09 -0700832 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800833 kVec2f_GrSLType);
834 noiseCode.append(".r;");
835 }
836
837#if defined(SK_BUILD_FOR_ANDROID)
838 // Android rounding for Tegra devices, like, for example: Xoom (Tegra 2), Nexus 7 (Tegra 3).
839 // The issue is that colors aren't accurate enough on Tegra devices. For example, if an 8 bit
840 // value of 124 (or 0.486275 here) is entered, we can get a texture value of 123.513725
841 // (or 0.484368 here). The following rounding operation prevents these precision issues from
842 // affecting the result of the noise by making sure that we only have multiples of 1/255.
843 // (Note that 1/255 is about 0.003921569, which is the value used here).
844 noiseCode.appendf("\n\t%s = floor(%s * vec2(255.0) + vec2(0.5)) * vec2(0.003921569);",
845 latticeIdx, latticeIdx);
846#endif
847
848 // Get (x,y) coordinates with the permutated x
849 noiseCode.appendf("\n\tvec4 %s = fract(%s.xyxy + %s.yyww);", bcoords, latticeIdx, floorVal);
850
851 noiseCode.appendf("\n\n\tvec2 %s;", uv);
852 // Compute u, at offset (0,0)
853 {
854 SkString latticeCoords("");
855 latticeCoords.appendf("vec2(%s.x, %s)", bcoords, chanCoord);
856 noiseCode.appendf("\n\tvec4 %s = ", lattice);
cdalton3f6f76f2016-04-11 12:18:09 -0700857 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800858 kVec2f_GrSLType);
859 noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
860 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
861 }
862
863 noiseCode.appendf("\n\t%s.x -= 1.0;", fractVal);
864 // Compute v, at offset (-1,0)
865 {
866 SkString latticeCoords("");
867 latticeCoords.appendf("vec2(%s.y, %s)", bcoords, chanCoord);
868 noiseCode.append("\n\tlattice = ");
cdalton3f6f76f2016-04-11 12:18:09 -0700869 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800870 kVec2f_GrSLType);
871 noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
872 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
873 }
874
875 // Compute 'a' as a linear interpolation of 'u' and 'v'
876 noiseCode.appendf("\n\tvec2 %s;", ab);
877 noiseCode.appendf("\n\t%s.x = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
878
879 noiseCode.appendf("\n\t%s.y -= 1.0;", fractVal);
880 // Compute v, at offset (-1,-1)
881 {
882 SkString latticeCoords("");
883 latticeCoords.appendf("vec2(%s.w, %s)", bcoords, chanCoord);
884 noiseCode.append("\n\tlattice = ");
cdalton3f6f76f2016-04-11 12:18:09 -0700885 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800886 kVec2f_GrSLType);
887 noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
888 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
889 }
890
891 noiseCode.appendf("\n\t%s.x += 1.0;", fractVal);
892 // Compute u, at offset (0,-1)
893 {
894 SkString latticeCoords("");
895 latticeCoords.appendf("vec2(%s.z, %s)", bcoords, chanCoord);
896 noiseCode.append("\n\tlattice = ");
cdalton3f6f76f2016-04-11 12:18:09 -0700897 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800898 kVec2f_GrSLType);
899 noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
900 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
901 }
902
903 // Compute 'b' as a linear interpolation of 'u' and 'v'
904 noiseCode.appendf("\n\t%s.y = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
905 // Compute the noise as a linear interpolation of 'a' and 'b'
906 noiseCode.appendf("\n\treturn mix(%s.x, %s.y, %s.y);\n", ab, ab, noiseSmooth);
907
908 SkString noiseFuncName;
robertphillipsd3b32bf2016-02-05 07:15:39 -0800909 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800910 fsBuilder->emitFunction(kFloat_GrSLType,
911 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseStitchArgs),
912 gPerlinNoiseStitchArgs, noiseCode.c_str(), &noiseFuncName);
913 } else {
914 fsBuilder->emitFunction(kFloat_GrSLType,
915 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseArgs),
916 gPerlinNoiseArgs, noiseCode.c_str(), &noiseFuncName);
917 }
918
919 // There are rounding errors if the floor operation is not performed here
920 fsBuilder->codeAppendf("\n\t\tvec2 %s = floor(%s.xy) * %s;",
921 noiseVec, vCoords.c_str(), baseFrequencyUni);
922
923 // Clear the color accumulator
924 fsBuilder->codeAppendf("\n\t\t%s = vec4(0.0);", args.fOutputColor);
925
robertphillipsd3b32bf2016-02-05 07:15:39 -0800926 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800927 // Set up TurbulenceInitial stitch values.
928 fsBuilder->codeAppendf("\n\t\tvec2 %s = %s;", stitchData, stitchDataUni);
929 }
930
931 fsBuilder->codeAppendf("\n\t\tfloat %s = 1.0;", ratio);
932
933 // Loop over all octaves
robertphillipsd3b32bf2016-02-05 07:15:39 -0800934 fsBuilder->codeAppendf("for (int octave = 0; octave < %d; ++octave) {", pne.numOctaves());
ethannicholas417011c2015-11-09 06:35:12 -0800935
936 fsBuilder->codeAppendf("\n\t\t\t%s += ", args.fOutputColor);
robertphillipsd3b32bf2016-02-05 07:15:39 -0800937 if (pne.type() != SkPerlinNoiseShader2::kFractalNoise_Type) {
ethannicholas417011c2015-11-09 06:35:12 -0800938 fsBuilder->codeAppend("abs(");
939 }
robertphillipsd3b32bf2016-02-05 07:15:39 -0800940 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800941 fsBuilder->codeAppendf(
942 "vec4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s),"
943 "\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))",
944 noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData,
945 noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData,
946 noiseFuncName.c_str(), chanCoordB, noiseVec, stitchData,
947 noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData);
948 } else {
949 fsBuilder->codeAppendf(
950 "vec4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s),"
951 "\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))",
952 noiseFuncName.c_str(), chanCoordR, noiseVec,
953 noiseFuncName.c_str(), chanCoordG, noiseVec,
954 noiseFuncName.c_str(), chanCoordB, noiseVec,
955 noiseFuncName.c_str(), chanCoordA, noiseVec);
956 }
robertphillipsd3b32bf2016-02-05 07:15:39 -0800957 if (pne.type() != SkPerlinNoiseShader2::kFractalNoise_Type) {
ethannicholas417011c2015-11-09 06:35:12 -0800958 fsBuilder->codeAppendf(")"); // end of "abs("
959 }
960 fsBuilder->codeAppendf(" * %s;", ratio);
961
962 fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", noiseVec);
963 fsBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio);
964
robertphillipsd3b32bf2016-02-05 07:15:39 -0800965 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800966 fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", stitchData);
967 }
968 fsBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves
969
robertphillipsd3b32bf2016-02-05 07:15:39 -0800970 if (pne.type() == SkPerlinNoiseShader2::kFractalNoise_Type) {
ethannicholas417011c2015-11-09 06:35:12 -0800971 // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
972 // by fractalNoise and (turbulenceFunctionResult) by turbulence.
973 fsBuilder->codeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);",
974 args.fOutputColor,args.fOutputColor);
975 }
976
977 // Clamp values
978 fsBuilder->codeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor);
979
980 // Pre-multiply the result
981 fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
982 args.fOutputColor, args.fOutputColor,
983 args.fOutputColor, args.fOutputColor);
984}
985
Brian Salomon94efbf52016-11-29 13:43:05 -0500986void GrGLPerlinNoise2::GenKey(const GrProcessor& processor, const GrShaderCaps&,
egdaniel2d721d32015-11-11 13:06:05 -0800987 GrProcessorKeyBuilder* b) {
ethannicholas417011c2015-11-09 06:35:12 -0800988 const GrPerlinNoise2Effect& turbulence = processor.cast<GrPerlinNoise2Effect>();
989
990 uint32_t key = turbulence.numOctaves();
991
992 key = key << 3; // Make room for next 3 bits
993
994 switch (turbulence.type()) {
995 case SkPerlinNoiseShader2::kFractalNoise_Type:
996 key |= 0x1;
997 break;
998 case SkPerlinNoiseShader2::kTurbulence_Type:
999 key |= 0x2;
1000 break;
1001 default:
1002 // leave key at 0
1003 break;
1004 }
1005
1006 if (turbulence.stitchTiles()) {
1007 key |= 0x4; // Flip the 3rd bit if tile stitching is on
1008 }
1009
1010 b->add32(key);
1011}
1012
1013void GrGLPerlinNoise2::onSetData(const GrGLSLProgramDataManager& pdman,
1014 const GrProcessor& processor) {
1015 INHERITED::onSetData(pdman, processor);
1016
1017 const GrPerlinNoise2Effect& turbulence = processor.cast<GrPerlinNoise2Effect>();
1018
1019 const SkVector& baseFrequency = turbulence.baseFrequency();
1020 pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
1021
1022 if (turbulence.stitchTiles()) {
1023 const SkPerlinNoiseShader2::StitchData& stitchData = turbulence.stitchData();
1024 pdman.set2f(fStitchDataUni, SkIntToScalar(stitchData.fWidth),
1025 SkIntToScalar(stitchData.fHeight));
1026 }
1027}
1028
1029/////////////////////////////////////////////////////////////////////
1030
egdaniel64c47282015-11-13 06:54:19 -08001031class GrGLImprovedPerlinNoise : public GrGLSLFragmentProcessor {
ethannicholas417011c2015-11-09 06:35:12 -08001032public:
robertphillipsbf536af2016-02-04 06:11:53 -08001033 void emitCode(EmitArgs&) override;
ethannicholas417011c2015-11-09 06:35:12 -08001034
Brian Salomon94efbf52016-11-29 13:43:05 -05001035 static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*);
ethannicholas417011c2015-11-09 06:35:12 -08001036
1037protected:
1038 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
1039
1040private:
ethannicholas417011c2015-11-09 06:35:12 -08001041 GrGLSLProgramDataManager::UniformHandle fZUni;
1042 GrGLSLProgramDataManager::UniformHandle fOctavesUni;
1043 GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni;
1044
egdaniel64c47282015-11-13 06:54:19 -08001045 typedef GrGLSLFragmentProcessor INHERITED;
ethannicholas417011c2015-11-09 06:35:12 -08001046};
1047
1048/////////////////////////////////////////////////////////////////////
1049
1050class GrImprovedPerlinNoiseEffect : public GrFragmentProcessor {
1051public:
bungeman06ca8ec2016-06-09 08:01:03 -07001052 static sk_sp<GrFragmentProcessor> Make(int octaves, SkScalar z,
1053 SkPerlinNoiseShader2::PaintingData* paintingData,
1054 GrTexture* permutationsTexture,
1055 GrTexture* gradientTexture,
1056 const SkMatrix& matrix) {
1057 return sk_sp<GrFragmentProcessor>(
1058 new GrImprovedPerlinNoiseEffect(octaves, z, paintingData, permutationsTexture,
1059 gradientTexture, matrix));
ethannicholas417011c2015-11-09 06:35:12 -08001060 }
1061
1062 virtual ~GrImprovedPerlinNoiseEffect() { delete fPaintingData; }
1063
1064 const char* name() const override { return "ImprovedPerlinNoise"; }
1065
1066 const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; }
1067 SkScalar z() const { return fZ; }
1068 int octaves() const { return fOctaves; }
1069 const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
1070
1071private:
egdaniel57d3b032015-11-13 11:57:27 -08001072 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
robertphillipsbf536af2016-02-04 06:11:53 -08001073 return new GrGLImprovedPerlinNoise;
ethannicholas417011c2015-11-09 06:35:12 -08001074 }
1075
Brian Salomon94efbf52016-11-29 13:43:05 -05001076 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
ethannicholas417011c2015-11-09 06:35:12 -08001077 GrGLImprovedPerlinNoise::GenKey(*this, caps, b);
1078 }
1079
1080 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
1081 const GrImprovedPerlinNoiseEffect& s = sBase.cast<GrImprovedPerlinNoiseEffect>();
1082 return fZ == fZ &&
1083 fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency;
1084 }
1085
1086 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
1087 inout->setToUnknown(GrInvariantOutput::kWillNot_ReadInput);
1088 }
1089
1090 GrImprovedPerlinNoiseEffect(int octaves, SkScalar z,
1091 SkPerlinNoiseShader2::PaintingData* paintingData,
1092 GrTexture* permutationsTexture, GrTexture* gradientTexture,
1093 const SkMatrix& matrix)
1094 : fOctaves(octaves)
1095 , fZ(z)
Brian Salomon0bbecb22016-11-17 11:38:22 -05001096 , fPermutationsSampler(permutationsTexture)
1097 , fGradientSampler(gradientTexture)
ethannicholas417011c2015-11-09 06:35:12 -08001098 , fPaintingData(paintingData) {
1099 this->initClassID<GrImprovedPerlinNoiseEffect>();
Brian Salomon0bbecb22016-11-17 11:38:22 -05001100 this->addTextureSampler(&fPermutationsSampler);
1101 this->addTextureSampler(&fGradientSampler);
Brian Salomon2ebd0c82016-10-03 17:15:28 -04001102 fCoordTransform.reset(matrix);
ethannicholas417011c2015-11-09 06:35:12 -08001103 this->addCoordTransform(&fCoordTransform);
1104 }
1105
1106 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
1107
Brian Salomon0bbecb22016-11-17 11:38:22 -05001108 GrCoordTransform fCoordTransform;
1109 int fOctaves;
1110 SkScalar fZ;
1111 TextureSampler fPermutationsSampler;
1112 TextureSampler fGradientSampler;
1113 SkPerlinNoiseShader2::PaintingData* fPaintingData;
ethannicholas417011c2015-11-09 06:35:12 -08001114
1115private:
1116 typedef GrFragmentProcessor INHERITED;
1117};
1118
1119/////////////////////////////////////////////////////////////////////
1120GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrImprovedPerlinNoiseEffect);
1121
bungeman06ca8ec2016-06-09 08:01:03 -07001122sk_sp<GrFragmentProcessor> GrImprovedPerlinNoiseEffect::TestCreate(GrProcessorTestData* d) {
ethannicholas417011c2015-11-09 06:35:12 -08001123 SkScalar baseFrequencyX = d->fRandom->nextRangeScalar(0.01f,
1124 0.99f);
1125 SkScalar baseFrequencyY = d->fRandom->nextRangeScalar(0.01f,
1126 0.99f);
1127 int numOctaves = d->fRandom->nextRangeU(2, 10);
1128 SkScalar z = SkIntToScalar(d->fRandom->nextU());
1129
reed8a21c9f2016-03-08 18:50:00 -08001130 sk_sp<SkShader> shader(SkPerlinNoiseShader2::MakeImprovedNoise(baseFrequencyX,
1131 baseFrequencyY,
1132 numOctaves,
1133 z));
ethannicholas417011c2015-11-09 06:35:12 -08001134
Brian Osman9f532a32016-10-19 11:12:09 -04001135 GrTest::TestAsFPArgs asFPArgs(d);
1136 return shader->asFragmentProcessor(asFPArgs.args());
ethannicholas417011c2015-11-09 06:35:12 -08001137}
1138
ethannicholas417011c2015-11-09 06:35:12 -08001139void GrGLImprovedPerlinNoise::emitCode(EmitArgs& args) {
egdaniel4ca2e602015-11-18 08:01:26 -08001140 GrGLSLFragmentBuilder* fsBuilder = args.fFragBuilder;
egdaniel7ea439b2015-12-03 09:20:44 -08001141 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
bsalomon1a1aa932016-09-12 09:30:36 -07001142 SkString vCoords = fsBuilder->ensureCoords2D(args.fTransformedCoords[0]);
ethannicholas417011c2015-11-09 06:35:12 -08001143
cdalton5e58cee2016-02-11 12:49:47 -08001144 fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001145 kVec2f_GrSLType, kDefault_GrSLPrecision,
1146 "baseFrequency");
1147 const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);
ethannicholas417011c2015-11-09 06:35:12 -08001148
cdalton5e58cee2016-02-11 12:49:47 -08001149 fOctavesUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001150 kFloat_GrSLType, kDefault_GrSLPrecision,
1151 "octaves");
1152 const char* octavesUni = uniformHandler->getUniformCStr(fOctavesUni);
ethannicholas417011c2015-11-09 06:35:12 -08001153
cdalton5e58cee2016-02-11 12:49:47 -08001154 fZUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001155 kFloat_GrSLType, kDefault_GrSLPrecision,
1156 "z");
1157 const char* zUni = uniformHandler->getUniformCStr(fZUni);
ethannicholas417011c2015-11-09 06:35:12 -08001158
1159 // fade function
Brian Salomon99938a82016-11-21 13:41:08 -05001160 static const GrShaderVar fadeArgs[] = {
1161 GrShaderVar("t", kVec3f_GrSLType)
ethannicholas417011c2015-11-09 06:35:12 -08001162 };
1163 SkString fadeFuncName;
1164 fsBuilder->emitFunction(kVec3f_GrSLType, "fade", SK_ARRAY_COUNT(fadeArgs),
1165 fadeArgs,
1166 "return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);",
1167 &fadeFuncName);
1168
1169 // perm function
Brian Salomon99938a82016-11-21 13:41:08 -05001170 static const GrShaderVar permArgs[] = {
1171 GrShaderVar("x", kFloat_GrSLType)
ethannicholas417011c2015-11-09 06:35:12 -08001172 };
1173 SkString permFuncName;
1174 SkString permCode("return ");
1175 // FIXME even though I'm creating these textures with kRepeat_TileMode, they're clamped. Not
1176 // sure why. Using fract() (here and the next texture lookup) as a workaround.
cdalton3f6f76f2016-04-11 12:18:09 -07001177 fsBuilder->appendTextureLookup(&permCode, args.fTexSamplers[0], "vec2(fract(x / 256.0), 0.0)",
ethannicholas417011c2015-11-09 06:35:12 -08001178 kVec2f_GrSLType);
1179 permCode.append(".r * 255.0;");
1180 fsBuilder->emitFunction(kFloat_GrSLType, "perm", SK_ARRAY_COUNT(permArgs), permArgs,
1181 permCode.c_str(), &permFuncName);
1182
1183 // grad function
Brian Salomon99938a82016-11-21 13:41:08 -05001184 static const GrShaderVar gradArgs[] = {
1185 GrShaderVar("x", kFloat_GrSLType),
1186 GrShaderVar("p", kVec3f_GrSLType)
ethannicholas417011c2015-11-09 06:35:12 -08001187 };
1188 SkString gradFuncName;
1189 SkString gradCode("return dot(");
cdalton3f6f76f2016-04-11 12:18:09 -07001190 fsBuilder->appendTextureLookup(&gradCode, args.fTexSamplers[1], "vec2(fract(x / 16.0), 0.0)",
ethannicholas417011c2015-11-09 06:35:12 -08001191 kVec2f_GrSLType);
1192 gradCode.append(".rgb * 255.0 - vec3(1.0), p);");
1193 fsBuilder->emitFunction(kFloat_GrSLType, "grad", SK_ARRAY_COUNT(gradArgs), gradArgs,
1194 gradCode.c_str(), &gradFuncName);
1195
1196 // lerp function
Brian Salomon99938a82016-11-21 13:41:08 -05001197 static const GrShaderVar lerpArgs[] = {
1198 GrShaderVar("a", kFloat_GrSLType),
1199 GrShaderVar("b", kFloat_GrSLType),
1200 GrShaderVar("w", kFloat_GrSLType)
ethannicholas417011c2015-11-09 06:35:12 -08001201 };
1202 SkString lerpFuncName;
1203 fsBuilder->emitFunction(kFloat_GrSLType, "lerp", SK_ARRAY_COUNT(lerpArgs), lerpArgs,
1204 "return a + w * (b - a);", &lerpFuncName);
1205
1206 // noise function
Brian Salomon99938a82016-11-21 13:41:08 -05001207 static const GrShaderVar noiseArgs[] = {
1208 GrShaderVar("p", kVec3f_GrSLType),
ethannicholas417011c2015-11-09 06:35:12 -08001209 };
1210 SkString noiseFuncName;
1211 SkString noiseCode;
1212 noiseCode.append("vec3 P = mod(floor(p), 256.0);");
1213 noiseCode.append("p -= floor(p);");
1214 noiseCode.appendf("vec3 f = %s(p);", fadeFuncName.c_str());
1215 noiseCode.appendf("float A = %s(P.x) + P.y;", permFuncName.c_str());
1216 noiseCode.appendf("float AA = %s(A) + P.z;", permFuncName.c_str());
1217 noiseCode.appendf("float AB = %s(A + 1.0) + P.z;", permFuncName.c_str());
1218 noiseCode.appendf("float B = %s(P.x + 1.0) + P.y;", permFuncName.c_str());
1219 noiseCode.appendf("float BA = %s(B) + P.z;", permFuncName.c_str());
1220 noiseCode.appendf("float BB = %s(B + 1.0) + P.z;", permFuncName.c_str());
1221 noiseCode.appendf("float result = %s(", lerpFuncName.c_str());
1222 noiseCode.appendf("%s(%s(%s(%s(AA), p),", lerpFuncName.c_str(), lerpFuncName.c_str(),
1223 gradFuncName.c_str(), permFuncName.c_str());
1224 noiseCode.appendf("%s(%s(BA), p + vec3(-1.0, 0.0, 0.0)), f.x),", gradFuncName.c_str(),
1225 permFuncName.c_str());
1226 noiseCode.appendf("%s(%s(%s(AB), p + vec3(0.0, -1.0, 0.0)),", lerpFuncName.c_str(),
1227 gradFuncName.c_str(), permFuncName.c_str());
1228 noiseCode.appendf("%s(%s(BB), p + vec3(-1.0, -1.0, 0.0)), f.x), f.y),",
1229 gradFuncName.c_str(), permFuncName.c_str());
1230 noiseCode.appendf("%s(%s(%s(%s(AA + 1.0), p + vec3(0.0, 0.0, -1.0)),",
1231 lerpFuncName.c_str(), lerpFuncName.c_str(), gradFuncName.c_str(),
1232 permFuncName.c_str());
1233 noiseCode.appendf("%s(%s(BA + 1.0), p + vec3(-1.0, 0.0, -1.0)), f.x),",
1234 gradFuncName.c_str(), permFuncName.c_str());
1235 noiseCode.appendf("%s(%s(%s(AB + 1.0), p + vec3(0.0, -1.0, -1.0)),",
1236 lerpFuncName.c_str(), gradFuncName.c_str(), permFuncName.c_str());
1237 noiseCode.appendf("%s(%s(BB + 1.0), p + vec3(-1.0, -1.0, -1.0)), f.x), f.y), f.z);",
1238 gradFuncName.c_str(), permFuncName.c_str());
1239 noiseCode.append("return result;");
1240 fsBuilder->emitFunction(kFloat_GrSLType, "noise", SK_ARRAY_COUNT(noiseArgs), noiseArgs,
1241 noiseCode.c_str(), &noiseFuncName);
1242
1243 // noiseOctaves function
Brian Salomon99938a82016-11-21 13:41:08 -05001244 static const GrShaderVar noiseOctavesArgs[] = {
1245 GrShaderVar("p", kVec3f_GrSLType),
1246 GrShaderVar("octaves", kFloat_GrSLType),
ethannicholas417011c2015-11-09 06:35:12 -08001247 };
1248 SkString noiseOctavesFuncName;
1249 SkString noiseOctavesCode;
1250 noiseOctavesCode.append("float result = 0.0;");
1251 noiseOctavesCode.append("float ratio = 1.0;");
1252 noiseOctavesCode.append("for (float i = 0.0; i < octaves; i++) {");
1253 noiseOctavesCode.appendf("result += %s(p) / ratio;", noiseFuncName.c_str());
1254 noiseOctavesCode.append("p *= 2.0;");
1255 noiseOctavesCode.append("ratio *= 2.0;");
1256 noiseOctavesCode.append("}");
1257 noiseOctavesCode.append("return (result + 1.0) / 2.0;");
1258 fsBuilder->emitFunction(kFloat_GrSLType, "noiseOctaves", SK_ARRAY_COUNT(noiseOctavesArgs),
1259 noiseOctavesArgs, noiseOctavesCode.c_str(), &noiseOctavesFuncName);
1260
1261 fsBuilder->codeAppendf("vec2 coords = %s * %s;", vCoords.c_str(), baseFrequencyUni);
1262 fsBuilder->codeAppendf("float r = %s(vec3(coords, %s), %s);", noiseOctavesFuncName.c_str(),
1263 zUni, octavesUni);
egdaniel478c04e2015-11-09 07:40:49 -08001264 fsBuilder->codeAppendf("float g = %s(vec3(coords, %s + 0000.0), %s);",
ethannicholas417011c2015-11-09 06:35:12 -08001265 noiseOctavesFuncName.c_str(), zUni, octavesUni);
egdaniel478c04e2015-11-09 07:40:49 -08001266 fsBuilder->codeAppendf("float b = %s(vec3(coords, %s + 0000.0), %s);",
ethannicholas417011c2015-11-09 06:35:12 -08001267 noiseOctavesFuncName.c_str(), zUni, octavesUni);
egdaniel478c04e2015-11-09 07:40:49 -08001268 fsBuilder->codeAppendf("float a = %s(vec3(coords, %s + 0000.0), %s);",
ethannicholas417011c2015-11-09 06:35:12 -08001269 noiseOctavesFuncName.c_str(), zUni, octavesUni);
1270 fsBuilder->codeAppendf("%s = vec4(r, g, b, a);", args.fOutputColor);
1271
1272 // Clamp values
1273 fsBuilder->codeAppendf("%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor);
1274
1275 // Pre-multiply the result
1276 fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
1277 args.fOutputColor, args.fOutputColor,
1278 args.fOutputColor, args.fOutputColor);
1279}
1280
Brian Salomon94efbf52016-11-29 13:43:05 -05001281void GrGLImprovedPerlinNoise::GenKey(const GrProcessor& processor, const GrShaderCaps&,
ethannicholas417011c2015-11-09 06:35:12 -08001282 GrProcessorKeyBuilder* b) {
1283}
1284
1285void GrGLImprovedPerlinNoise::onSetData(const GrGLSLProgramDataManager& pdman,
1286 const GrProcessor& processor) {
1287 INHERITED::onSetData(pdman, processor);
1288
1289 const GrImprovedPerlinNoiseEffect& noise = processor.cast<GrImprovedPerlinNoiseEffect>();
1290
1291 const SkVector& baseFrequency = noise.baseFrequency();
1292 pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
1293
egdaniel478c04e2015-11-09 07:40:49 -08001294 pdman.set1f(fOctavesUni, SkIntToScalar(noise.octaves()));
ethannicholas417011c2015-11-09 06:35:12 -08001295
1296 pdman.set1f(fZUni, noise.z());
1297}
1298
1299/////////////////////////////////////////////////////////////////////
brianosman839345d2016-07-22 11:04:53 -07001300sk_sp<GrFragmentProcessor> SkPerlinNoiseShader2::asFragmentProcessor(const AsFPArgs& args) const {
1301 SkASSERT(args.fContext);
ethannicholas417011c2015-11-09 06:35:12 -08001302
1303 SkMatrix localMatrix = this->getLocalMatrix();
brianosman839345d2016-07-22 11:04:53 -07001304 if (args.fLocalMatrix) {
1305 localMatrix.preConcat(*args.fLocalMatrix);
ethannicholas417011c2015-11-09 06:35:12 -08001306 }
1307
brianosman839345d2016-07-22 11:04:53 -07001308 SkMatrix matrix = *args.fViewMatrix;
ethannicholas417011c2015-11-09 06:35:12 -08001309 matrix.preConcat(localMatrix);
1310
1311 // Either we don't stitch tiles, either we have a valid tile size
1312 SkASSERT(!fStitchTiles || !fTileSize.isEmpty());
1313
1314 SkPerlinNoiseShader2::PaintingData* paintingData =
1315 new PaintingData(fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY, matrix);
1316
brianosman839345d2016-07-22 11:04:53 -07001317 SkMatrix m = *args.fViewMatrix;
ethannicholas417011c2015-11-09 06:35:12 -08001318 m.setTranslateX(-localMatrix.getTranslateX() + SK_Scalar1);
1319 m.setTranslateY(-localMatrix.getTranslateY() + SK_Scalar1);
1320
1321 if (fType == kImprovedNoise_Type) {
Brian Salomon514baff2016-11-17 15:17:07 -05001322 GrSamplerParams textureParams(SkShader::TileMode::kRepeat_TileMode,
1323 GrSamplerParams::FilterMode::kNone_FilterMode);
Hal Canary2db83612016-11-04 13:02:54 -04001324 sk_sp<GrTexture> permutationsTexture(
brianosman839345d2016-07-22 11:04:53 -07001325 GrRefCachedBitmapTexture(args.fContext, paintingData->getImprovedPermutationsBitmap(),
Brian Osman7b8400d2016-11-08 17:08:54 -05001326 textureParams, args.fColorMode));
Hal Canary2db83612016-11-04 13:02:54 -04001327 sk_sp<GrTexture> gradientTexture(
brianosman839345d2016-07-22 11:04:53 -07001328 GrRefCachedBitmapTexture(args.fContext, paintingData->getGradientBitmap(),
Brian Osman7b8400d2016-11-08 17:08:54 -05001329 textureParams, args.fColorMode));
bungeman06ca8ec2016-06-09 08:01:03 -07001330 return GrImprovedPerlinNoiseEffect::Make(fNumOctaves, fSeed, paintingData,
Hal Canary2db83612016-11-04 13:02:54 -04001331 permutationsTexture.get(),
1332 gradientTexture.get(), m);
ethannicholas417011c2015-11-09 06:35:12 -08001333 }
1334
1335 if (0 == fNumOctaves) {
1336 if (kFractalNoise_Type == fType) {
1337 // Extract the incoming alpha and emit rgba = (a/4, a/4, a/4, a/2)
Brian Osman618d3042016-10-25 10:51:28 -04001338 // TODO: Either treat the output of this shader as sRGB or allow client to specify a
1339 // color space of the noise. Either way, this case (and the GLSL) need to convert to
1340 // the destination.
bungeman06ca8ec2016-06-09 08:01:03 -07001341 sk_sp<GrFragmentProcessor> inner(
Brian Osman618d3042016-10-25 10:51:28 -04001342 GrConstColorProcessor::Make(GrColor4f::FromGrColor(0x80404040),
bungeman06ca8ec2016-06-09 08:01:03 -07001343 GrConstColorProcessor::kModulateRGBA_InputMode));
1344 return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner));
ethannicholas417011c2015-11-09 06:35:12 -08001345 }
1346 // Emit zero.
Brian Osman618d3042016-10-25 10:51:28 -04001347 return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
1348 GrConstColorProcessor::kIgnore_InputMode);
ethannicholas417011c2015-11-09 06:35:12 -08001349 }
1350
Hal Canary2db83612016-11-04 13:02:54 -04001351 sk_sp<GrTexture> permutationsTexture(
brianosman839345d2016-07-22 11:04:53 -07001352 GrRefCachedBitmapTexture(args.fContext, paintingData->getPermutationsBitmap(),
Brian Salomon514baff2016-11-17 15:17:07 -05001353 GrSamplerParams::ClampNoFilter(), args.fColorMode));
Hal Canary2db83612016-11-04 13:02:54 -04001354 sk_sp<GrTexture> noiseTexture(
brianosman839345d2016-07-22 11:04:53 -07001355 GrRefCachedBitmapTexture(args.fContext, paintingData->getNoiseBitmap(),
Brian Salomon514baff2016-11-17 15:17:07 -05001356 GrSamplerParams::ClampNoFilter(), args.fColorMode));
ethannicholas417011c2015-11-09 06:35:12 -08001357
1358 if ((permutationsTexture) && (noiseTexture)) {
bungeman06ca8ec2016-06-09 08:01:03 -07001359 sk_sp<GrFragmentProcessor> inner(
1360 GrPerlinNoise2Effect::Make(fType,
1361 fNumOctaves,
1362 fStitchTiles,
1363 paintingData,
Hal Canary2db83612016-11-04 13:02:54 -04001364 permutationsTexture.get(), noiseTexture.get(),
bungeman06ca8ec2016-06-09 08:01:03 -07001365 m));
1366 return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner));
ethannicholas417011c2015-11-09 06:35:12 -08001367 }
1368 delete paintingData;
1369 return nullptr;
1370}
1371
1372#endif
1373
1374#ifndef SK_IGNORE_TO_STRING
1375void SkPerlinNoiseShader2::toString(SkString* str) const {
1376 str->append("SkPerlinNoiseShader2: (");
1377
1378 str->append("type: ");
1379 switch (fType) {
1380 case kFractalNoise_Type:
1381 str->append("\"fractal noise\"");
1382 break;
1383 case kTurbulence_Type:
1384 str->append("\"turbulence\"");
1385 break;
1386 default:
1387 str->append("\"unknown\"");
1388 break;
1389 }
1390 str->append(" base frequency: (");
1391 str->appendScalar(fBaseFrequencyX);
1392 str->append(", ");
1393 str->appendScalar(fBaseFrequencyY);
1394 str->append(") number of octaves: ");
1395 str->appendS32(fNumOctaves);
1396 str->append(" seed: ");
1397 str->appendScalar(fSeed);
1398 str->append(" stitch tiles: ");
1399 str->append(fStitchTiles ? "true " : "false ");
1400
1401 this->INHERITED::toString(str);
1402
1403 str->append(")");
1404}
1405#endif