blob: 09762b3326228d79775dc8c3e2ea709701e21cdb [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:
633 static GrFragmentProcessor* Create(SkPerlinNoiseShader2::Type type,
634 int numOctaves, bool stitchTiles,
635 SkPerlinNoiseShader2::PaintingData* paintingData,
636 GrTexture* permutationsTexture, GrTexture* noiseTexture,
637 const SkMatrix& matrix) {
638 return new GrPerlinNoise2Effect(type, numOctaves, stitchTiles, paintingData,
639 permutationsTexture, noiseTexture, matrix);
640 }
641
642 virtual ~GrPerlinNoise2Effect() { delete fPaintingData; }
643
644 const char* name() const override { return "PerlinNoise"; }
645
646 const SkPerlinNoiseShader2::StitchData& stitchData() const { return fPaintingData->fStitchDataInit; }
647
648 SkPerlinNoiseShader2::Type type() const { return fType; }
649 bool stitchTiles() const { return fStitchTiles; }
650 const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; }
651 int numOctaves() const { return fNumOctaves; }
652 const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
653
654private:
egdaniel57d3b032015-11-13 11:57:27 -0800655 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
robertphillipsd3b32bf2016-02-05 07:15:39 -0800656 return new GrGLPerlinNoise2;
ethannicholas417011c2015-11-09 06:35:12 -0800657 }
658
egdaniel57d3b032015-11-13 11:57:27 -0800659 virtual void onGetGLSLProcessorKey(const GrGLSLCaps& caps,
660 GrProcessorKeyBuilder* b) const override {
ethannicholas417011c2015-11-09 06:35:12 -0800661 GrGLPerlinNoise2::GenKey(*this, caps, b);
662 }
663
664 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
665 const GrPerlinNoise2Effect& s = sBase.cast<GrPerlinNoise2Effect>();
666 return fType == s.fType &&
667 fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency &&
668 fNumOctaves == s.fNumOctaves &&
669 fStitchTiles == s.fStitchTiles &&
670 fPaintingData->fStitchDataInit == s.fPaintingData->fStitchDataInit;
671 }
672
673 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
674 inout->setToUnknown(GrInvariantOutput::kWillNot_ReadInput);
675 }
676
677 GrPerlinNoise2Effect(SkPerlinNoiseShader2::Type type,
678 int numOctaves, bool stitchTiles,
679 SkPerlinNoiseShader2::PaintingData* paintingData,
680 GrTexture* permutationsTexture, GrTexture* noiseTexture,
681 const SkMatrix& matrix)
682 : fType(type)
683 , fNumOctaves(numOctaves)
684 , fStitchTiles(stitchTiles)
685 , fPermutationsAccess(permutationsTexture)
686 , fNoiseAccess(noiseTexture)
687 , fPaintingData(paintingData) {
688 this->initClassID<GrPerlinNoise2Effect>();
689 this->addTextureAccess(&fPermutationsAccess);
690 this->addTextureAccess(&fNoiseAccess);
691 fCoordTransform.reset(kLocal_GrCoordSet, matrix);
692 this->addCoordTransform(&fCoordTransform);
693 }
694
695 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
696
697 SkPerlinNoiseShader2::Type fType;
698 GrCoordTransform fCoordTransform;
699 int fNumOctaves;
700 bool fStitchTiles;
701 GrTextureAccess fPermutationsAccess;
702 GrTextureAccess fNoiseAccess;
703 SkPerlinNoiseShader2::PaintingData *fPaintingData;
704
705private:
706 typedef GrFragmentProcessor INHERITED;
707};
708
709/////////////////////////////////////////////////////////////////////
710GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrPerlinNoise2Effect);
711
712const GrFragmentProcessor* GrPerlinNoise2Effect::TestCreate(GrProcessorTestData* d) {
713 int numOctaves = d->fRandom->nextRangeU(2, 10);
714 bool stitchTiles = d->fRandom->nextBool();
715 SkScalar seed = SkIntToScalar(d->fRandom->nextU());
716 SkISize tileSize = SkISize::Make(d->fRandom->nextRangeU(4, 4096),
717 d->fRandom->nextRangeU(4, 4096));
718 SkScalar baseFrequencyX = d->fRandom->nextRangeScalar(0.01f,
719 0.99f);
720 SkScalar baseFrequencyY = d->fRandom->nextRangeScalar(0.01f,
721 0.99f);
722
reed8a21c9f2016-03-08 18:50:00 -0800723 sk_sp<SkShader> shader(d->fRandom->nextBool() ?
724 SkPerlinNoiseShader2::MakeFractalNoise(baseFrequencyX, baseFrequencyY, numOctaves, seed,
725 stitchTiles ? &tileSize : nullptr) :
726 SkPerlinNoiseShader2::MakeTurbulence(baseFrequencyX, baseFrequencyY, numOctaves, seed,
ethannicholas417011c2015-11-09 06:35:12 -0800727 stitchTiles ? &tileSize : nullptr));
728
729 GrPaint grPaint;
730 return shader->asFragmentProcessor(d->fContext,
731 GrTest::TestMatrix(d->fRandom), nullptr,
732 kNone_SkFilterQuality);
733}
734
ethannicholas417011c2015-11-09 06:35:12 -0800735void GrGLPerlinNoise2::emitCode(EmitArgs& args) {
robertphillipsd3b32bf2016-02-05 07:15:39 -0800736 const GrPerlinNoise2Effect& pne = args.fFp.cast<GrPerlinNoise2Effect>();
737
egdaniel4ca2e602015-11-18 08:01:26 -0800738 GrGLSLFragmentBuilder* fsBuilder = args.fFragBuilder;
egdaniel7ea439b2015-12-03 09:20:44 -0800739 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
ethannicholas417011c2015-11-09 06:35:12 -0800740 SkString vCoords = fsBuilder->ensureFSCoords2D(args.fCoords, 0);
741
cdalton5e58cee2016-02-11 12:49:47 -0800742 fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800743 kVec2f_GrSLType, kDefault_GrSLPrecision,
744 "baseFrequency");
745 const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);
ethannicholas417011c2015-11-09 06:35:12 -0800746
747 const char* stitchDataUni = nullptr;
robertphillipsd3b32bf2016-02-05 07:15:39 -0800748 if (pne.stitchTiles()) {
cdalton5e58cee2016-02-11 12:49:47 -0800749 fStitchDataUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800750 kVec2f_GrSLType, kDefault_GrSLPrecision,
751 "stitchData");
752 stitchDataUni = uniformHandler->getUniformCStr(fStitchDataUni);
ethannicholas417011c2015-11-09 06:35:12 -0800753 }
754
755 // There are 4 lines, so the center of each line is 1/8, 3/8, 5/8 and 7/8
756 const char* chanCoordR = "0.125";
757 const char* chanCoordG = "0.375";
758 const char* chanCoordB = "0.625";
759 const char* chanCoordA = "0.875";
760 const char* chanCoord = "chanCoord";
761 const char* stitchData = "stitchData";
762 const char* ratio = "ratio";
763 const char* noiseVec = "noiseVec";
764 const char* noiseSmooth = "noiseSmooth";
765 const char* floorVal = "floorVal";
766 const char* fractVal = "fractVal";
767 const char* uv = "uv";
768 const char* ab = "ab";
769 const char* latticeIdx = "latticeIdx";
770 const char* bcoords = "bcoords";
771 const char* lattice = "lattice";
772 const char* inc8bit = "0.00390625"; // 1.0 / 256.0
773 // This is the math to convert the two 16bit integer packed into rgba 8 bit input into a
774 // [-1,1] vector and perform a dot product between that vector and the provided vector.
775 const char* dotLattice = "dot(((%s.ga + %s.rb * vec2(%s)) * vec2(2.0) - vec2(1.0)), %s);";
776
777 // Add noise function
778 static const GrGLSLShaderVar gPerlinNoiseArgs[] = {
779 GrGLSLShaderVar(chanCoord, kFloat_GrSLType),
780 GrGLSLShaderVar(noiseVec, kVec2f_GrSLType)
781 };
782
783 static const GrGLSLShaderVar gPerlinNoiseStitchArgs[] = {
784 GrGLSLShaderVar(chanCoord, kFloat_GrSLType),
785 GrGLSLShaderVar(noiseVec, kVec2f_GrSLType),
786 GrGLSLShaderVar(stitchData, kVec2f_GrSLType)
787 };
788
789 SkString noiseCode;
790
791 noiseCode.appendf("\tvec4 %s;\n", floorVal);
792 noiseCode.appendf("\t%s.xy = floor(%s);\n", floorVal, noiseVec);
793 noiseCode.appendf("\t%s.zw = %s.xy + vec2(1.0);\n", floorVal, floorVal);
794 noiseCode.appendf("\tvec2 %s = fract(%s);\n", fractVal, noiseVec);
795
796 // smooth curve : t * t * (3 - 2 * t)
797 noiseCode.appendf("\n\tvec2 %s = %s * %s * (vec2(3.0) - vec2(2.0) * %s);",
798 noiseSmooth, fractVal, fractVal, fractVal);
799
800 // Adjust frequencies if we're stitching tiles
robertphillipsd3b32bf2016-02-05 07:15:39 -0800801 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800802 noiseCode.appendf("\n\tif(%s.x >= %s.x) { %s.x -= %s.x; }",
803 floorVal, stitchData, floorVal, stitchData);
804 noiseCode.appendf("\n\tif(%s.y >= %s.y) { %s.y -= %s.y; }",
805 floorVal, stitchData, floorVal, stitchData);
806 noiseCode.appendf("\n\tif(%s.z >= %s.x) { %s.z -= %s.x; }",
807 floorVal, stitchData, floorVal, stitchData);
808 noiseCode.appendf("\n\tif(%s.w >= %s.y) { %s.w -= %s.y; }",
809 floorVal, stitchData, floorVal, stitchData);
810 }
811
812 // Get texture coordinates and normalize
813 noiseCode.appendf("\n\t%s = fract(floor(mod(%s, 256.0)) / vec4(256.0));\n",
814 floorVal, floorVal);
815
816 // Get permutation for x
817 {
818 SkString xCoords("");
819 xCoords.appendf("vec2(%s.x, 0.5)", floorVal);
820
821 noiseCode.appendf("\n\tvec2 %s;\n\t%s.x = ", latticeIdx, latticeIdx);
822 fsBuilder->appendTextureLookup(&noiseCode, args.fSamplers[0], xCoords.c_str(),
823 kVec2f_GrSLType);
824 noiseCode.append(".r;");
825 }
826
827 // Get permutation for x + 1
828 {
829 SkString xCoords("");
830 xCoords.appendf("vec2(%s.z, 0.5)", floorVal);
831
832 noiseCode.appendf("\n\t%s.y = ", latticeIdx);
833 fsBuilder->appendTextureLookup(&noiseCode, args.fSamplers[0], xCoords.c_str(),
834 kVec2f_GrSLType);
835 noiseCode.append(".r;");
836 }
837
838#if defined(SK_BUILD_FOR_ANDROID)
839 // Android rounding for Tegra devices, like, for example: Xoom (Tegra 2), Nexus 7 (Tegra 3).
840 // The issue is that colors aren't accurate enough on Tegra devices. For example, if an 8 bit
841 // value of 124 (or 0.486275 here) is entered, we can get a texture value of 123.513725
842 // (or 0.484368 here). The following rounding operation prevents these precision issues from
843 // affecting the result of the noise by making sure that we only have multiples of 1/255.
844 // (Note that 1/255 is about 0.003921569, which is the value used here).
845 noiseCode.appendf("\n\t%s = floor(%s * vec2(255.0) + vec2(0.5)) * vec2(0.003921569);",
846 latticeIdx, latticeIdx);
847#endif
848
849 // Get (x,y) coordinates with the permutated x
850 noiseCode.appendf("\n\tvec4 %s = fract(%s.xyxy + %s.yyww);", bcoords, latticeIdx, floorVal);
851
852 noiseCode.appendf("\n\n\tvec2 %s;", uv);
853 // Compute u, at offset (0,0)
854 {
855 SkString latticeCoords("");
856 latticeCoords.appendf("vec2(%s.x, %s)", bcoords, chanCoord);
857 noiseCode.appendf("\n\tvec4 %s = ", lattice);
858 fsBuilder->appendTextureLookup(&noiseCode, args.fSamplers[1], latticeCoords.c_str(),
859 kVec2f_GrSLType);
860 noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
861 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
862 }
863
864 noiseCode.appendf("\n\t%s.x -= 1.0;", fractVal);
865 // Compute v, at offset (-1,0)
866 {
867 SkString latticeCoords("");
868 latticeCoords.appendf("vec2(%s.y, %s)", bcoords, chanCoord);
869 noiseCode.append("\n\tlattice = ");
870 fsBuilder->appendTextureLookup(&noiseCode, args.fSamplers[1], latticeCoords.c_str(),
871 kVec2f_GrSLType);
872 noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
873 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
874 }
875
876 // Compute 'a' as a linear interpolation of 'u' and 'v'
877 noiseCode.appendf("\n\tvec2 %s;", ab);
878 noiseCode.appendf("\n\t%s.x = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
879
880 noiseCode.appendf("\n\t%s.y -= 1.0;", fractVal);
881 // Compute v, at offset (-1,-1)
882 {
883 SkString latticeCoords("");
884 latticeCoords.appendf("vec2(%s.w, %s)", bcoords, chanCoord);
885 noiseCode.append("\n\tlattice = ");
886 fsBuilder->appendTextureLookup(&noiseCode, args.fSamplers[1], latticeCoords.c_str(),
887 kVec2f_GrSLType);
888 noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
889 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
890 }
891
892 noiseCode.appendf("\n\t%s.x += 1.0;", fractVal);
893 // Compute u, at offset (0,-1)
894 {
895 SkString latticeCoords("");
896 latticeCoords.appendf("vec2(%s.z, %s)", bcoords, chanCoord);
897 noiseCode.append("\n\tlattice = ");
898 fsBuilder->appendTextureLookup(&noiseCode, args.fSamplers[1], latticeCoords.c_str(),
899 kVec2f_GrSLType);
900 noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
901 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
902 }
903
904 // Compute 'b' as a linear interpolation of 'u' and 'v'
905 noiseCode.appendf("\n\t%s.y = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
906 // Compute the noise as a linear interpolation of 'a' and 'b'
907 noiseCode.appendf("\n\treturn mix(%s.x, %s.y, %s.y);\n", ab, ab, noiseSmooth);
908
909 SkString noiseFuncName;
robertphillipsd3b32bf2016-02-05 07:15:39 -0800910 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800911 fsBuilder->emitFunction(kFloat_GrSLType,
912 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseStitchArgs),
913 gPerlinNoiseStitchArgs, noiseCode.c_str(), &noiseFuncName);
914 } else {
915 fsBuilder->emitFunction(kFloat_GrSLType,
916 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseArgs),
917 gPerlinNoiseArgs, noiseCode.c_str(), &noiseFuncName);
918 }
919
920 // There are rounding errors if the floor operation is not performed here
921 fsBuilder->codeAppendf("\n\t\tvec2 %s = floor(%s.xy) * %s;",
922 noiseVec, vCoords.c_str(), baseFrequencyUni);
923
924 // Clear the color accumulator
925 fsBuilder->codeAppendf("\n\t\t%s = vec4(0.0);", args.fOutputColor);
926
robertphillipsd3b32bf2016-02-05 07:15:39 -0800927 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800928 // Set up TurbulenceInitial stitch values.
929 fsBuilder->codeAppendf("\n\t\tvec2 %s = %s;", stitchData, stitchDataUni);
930 }
931
932 fsBuilder->codeAppendf("\n\t\tfloat %s = 1.0;", ratio);
933
934 // Loop over all octaves
robertphillipsd3b32bf2016-02-05 07:15:39 -0800935 fsBuilder->codeAppendf("for (int octave = 0; octave < %d; ++octave) {", pne.numOctaves());
ethannicholas417011c2015-11-09 06:35:12 -0800936
937 fsBuilder->codeAppendf("\n\t\t\t%s += ", args.fOutputColor);
robertphillipsd3b32bf2016-02-05 07:15:39 -0800938 if (pne.type() != SkPerlinNoiseShader2::kFractalNoise_Type) {
ethannicholas417011c2015-11-09 06:35:12 -0800939 fsBuilder->codeAppend("abs(");
940 }
robertphillipsd3b32bf2016-02-05 07:15:39 -0800941 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800942 fsBuilder->codeAppendf(
943 "vec4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s),"
944 "\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))",
945 noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData,
946 noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData,
947 noiseFuncName.c_str(), chanCoordB, noiseVec, stitchData,
948 noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData);
949 } else {
950 fsBuilder->codeAppendf(
951 "vec4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s),"
952 "\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))",
953 noiseFuncName.c_str(), chanCoordR, noiseVec,
954 noiseFuncName.c_str(), chanCoordG, noiseVec,
955 noiseFuncName.c_str(), chanCoordB, noiseVec,
956 noiseFuncName.c_str(), chanCoordA, noiseVec);
957 }
robertphillipsd3b32bf2016-02-05 07:15:39 -0800958 if (pne.type() != SkPerlinNoiseShader2::kFractalNoise_Type) {
ethannicholas417011c2015-11-09 06:35:12 -0800959 fsBuilder->codeAppendf(")"); // end of "abs("
960 }
961 fsBuilder->codeAppendf(" * %s;", ratio);
962
963 fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", noiseVec);
964 fsBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio);
965
robertphillipsd3b32bf2016-02-05 07:15:39 -0800966 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800967 fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", stitchData);
968 }
969 fsBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves
970
robertphillipsd3b32bf2016-02-05 07:15:39 -0800971 if (pne.type() == SkPerlinNoiseShader2::kFractalNoise_Type) {
ethannicholas417011c2015-11-09 06:35:12 -0800972 // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
973 // by fractalNoise and (turbulenceFunctionResult) by turbulence.
974 fsBuilder->codeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);",
975 args.fOutputColor,args.fOutputColor);
976 }
977
978 // Clamp values
979 fsBuilder->codeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor);
980
981 // Pre-multiply the result
982 fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
983 args.fOutputColor, args.fOutputColor,
984 args.fOutputColor, args.fOutputColor);
985}
986
987void GrGLPerlinNoise2::GenKey(const GrProcessor& processor, const GrGLSLCaps&,
egdaniel2d721d32015-11-11 13:06:05 -0800988 GrProcessorKeyBuilder* b) {
ethannicholas417011c2015-11-09 06:35:12 -0800989 const GrPerlinNoise2Effect& turbulence = processor.cast<GrPerlinNoise2Effect>();
990
991 uint32_t key = turbulence.numOctaves();
992
993 key = key << 3; // Make room for next 3 bits
994
995 switch (turbulence.type()) {
996 case SkPerlinNoiseShader2::kFractalNoise_Type:
997 key |= 0x1;
998 break;
999 case SkPerlinNoiseShader2::kTurbulence_Type:
1000 key |= 0x2;
1001 break;
1002 default:
1003 // leave key at 0
1004 break;
1005 }
1006
1007 if (turbulence.stitchTiles()) {
1008 key |= 0x4; // Flip the 3rd bit if tile stitching is on
1009 }
1010
1011 b->add32(key);
1012}
1013
1014void GrGLPerlinNoise2::onSetData(const GrGLSLProgramDataManager& pdman,
1015 const GrProcessor& processor) {
1016 INHERITED::onSetData(pdman, processor);
1017
1018 const GrPerlinNoise2Effect& turbulence = processor.cast<GrPerlinNoise2Effect>();
1019
1020 const SkVector& baseFrequency = turbulence.baseFrequency();
1021 pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
1022
1023 if (turbulence.stitchTiles()) {
1024 const SkPerlinNoiseShader2::StitchData& stitchData = turbulence.stitchData();
1025 pdman.set2f(fStitchDataUni, SkIntToScalar(stitchData.fWidth),
1026 SkIntToScalar(stitchData.fHeight));
1027 }
1028}
1029
1030/////////////////////////////////////////////////////////////////////
1031
egdaniel64c47282015-11-13 06:54:19 -08001032class GrGLImprovedPerlinNoise : public GrGLSLFragmentProcessor {
ethannicholas417011c2015-11-09 06:35:12 -08001033public:
robertphillipsbf536af2016-02-04 06:11:53 -08001034 void emitCode(EmitArgs&) override;
ethannicholas417011c2015-11-09 06:35:12 -08001035
robertphillipsbf536af2016-02-04 06:11:53 -08001036 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*);
ethannicholas417011c2015-11-09 06:35:12 -08001037
1038protected:
1039 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
1040
1041private:
ethannicholas417011c2015-11-09 06:35:12 -08001042 GrGLSLProgramDataManager::UniformHandle fZUni;
1043 GrGLSLProgramDataManager::UniformHandle fOctavesUni;
1044 GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni;
1045
egdaniel64c47282015-11-13 06:54:19 -08001046 typedef GrGLSLFragmentProcessor INHERITED;
ethannicholas417011c2015-11-09 06:35:12 -08001047};
1048
1049/////////////////////////////////////////////////////////////////////
1050
1051class GrImprovedPerlinNoiseEffect : public GrFragmentProcessor {
1052public:
egdaniel478c04e2015-11-09 07:40:49 -08001053 static GrFragmentProcessor* Create(int octaves, SkScalar z,
ethannicholas417011c2015-11-09 06:35:12 -08001054 SkPerlinNoiseShader2::PaintingData* paintingData,
1055 GrTexture* permutationsTexture, GrTexture* gradientTexture,
1056 const SkMatrix& matrix) {
1057 return new GrImprovedPerlinNoiseEffect(octaves, z, paintingData, permutationsTexture,
1058 gradientTexture, matrix);
1059 }
1060
1061 virtual ~GrImprovedPerlinNoiseEffect() { delete fPaintingData; }
1062
1063 const char* name() const override { return "ImprovedPerlinNoise"; }
1064
1065 const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; }
1066 SkScalar z() const { return fZ; }
1067 int octaves() const { return fOctaves; }
1068 const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
1069
1070private:
egdaniel57d3b032015-11-13 11:57:27 -08001071 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
robertphillipsbf536af2016-02-04 06:11:53 -08001072 return new GrGLImprovedPerlinNoise;
ethannicholas417011c2015-11-09 06:35:12 -08001073 }
1074
robertphillipsbf536af2016-02-04 06:11:53 -08001075 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
ethannicholas417011c2015-11-09 06:35:12 -08001076 GrGLImprovedPerlinNoise::GenKey(*this, caps, b);
1077 }
1078
1079 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
1080 const GrImprovedPerlinNoiseEffect& s = sBase.cast<GrImprovedPerlinNoiseEffect>();
1081 return fZ == fZ &&
1082 fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency;
1083 }
1084
1085 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
1086 inout->setToUnknown(GrInvariantOutput::kWillNot_ReadInput);
1087 }
1088
1089 GrImprovedPerlinNoiseEffect(int octaves, SkScalar z,
1090 SkPerlinNoiseShader2::PaintingData* paintingData,
1091 GrTexture* permutationsTexture, GrTexture* gradientTexture,
1092 const SkMatrix& matrix)
1093 : fOctaves(octaves)
1094 , fZ(z)
1095 , fPermutationsAccess(permutationsTexture)
1096 , fGradientAccess(gradientTexture)
1097 , fPaintingData(paintingData) {
1098 this->initClassID<GrImprovedPerlinNoiseEffect>();
1099 this->addTextureAccess(&fPermutationsAccess);
1100 this->addTextureAccess(&fGradientAccess);
1101 fCoordTransform.reset(kLocal_GrCoordSet, matrix);
1102 this->addCoordTransform(&fCoordTransform);
1103 }
1104
1105 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
1106
1107 GrCoordTransform fCoordTransform;
1108 int fOctaves;
1109 SkScalar fZ;
1110 GrTextureAccess fPermutationsAccess;
1111 GrTextureAccess fGradientAccess;
1112 SkPerlinNoiseShader2::PaintingData *fPaintingData;
1113
1114private:
1115 typedef GrFragmentProcessor INHERITED;
1116};
1117
1118/////////////////////////////////////////////////////////////////////
1119GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrImprovedPerlinNoiseEffect);
1120
1121const GrFragmentProcessor* GrImprovedPerlinNoiseEffect::TestCreate(GrProcessorTestData* d) {
1122 SkScalar baseFrequencyX = d->fRandom->nextRangeScalar(0.01f,
1123 0.99f);
1124 SkScalar baseFrequencyY = d->fRandom->nextRangeScalar(0.01f,
1125 0.99f);
1126 int numOctaves = d->fRandom->nextRangeU(2, 10);
1127 SkScalar z = SkIntToScalar(d->fRandom->nextU());
1128
reed8a21c9f2016-03-08 18:50:00 -08001129 sk_sp<SkShader> shader(SkPerlinNoiseShader2::MakeImprovedNoise(baseFrequencyX,
1130 baseFrequencyY,
1131 numOctaves,
1132 z));
ethannicholas417011c2015-11-09 06:35:12 -08001133
1134 GrPaint grPaint;
1135 return shader->asFragmentProcessor(d->fContext,
1136 GrTest::TestMatrix(d->fRandom), nullptr,
1137 kNone_SkFilterQuality);
1138}
1139
ethannicholas417011c2015-11-09 06:35:12 -08001140void GrGLImprovedPerlinNoise::emitCode(EmitArgs& args) {
egdaniel4ca2e602015-11-18 08:01:26 -08001141 GrGLSLFragmentBuilder* fsBuilder = args.fFragBuilder;
egdaniel7ea439b2015-12-03 09:20:44 -08001142 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
ethannicholas417011c2015-11-09 06:35:12 -08001143 SkString vCoords = fsBuilder->ensureFSCoords2D(args.fCoords, 0);
1144
cdalton5e58cee2016-02-11 12:49:47 -08001145 fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001146 kVec2f_GrSLType, kDefault_GrSLPrecision,
1147 "baseFrequency");
1148 const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);
ethannicholas417011c2015-11-09 06:35:12 -08001149
cdalton5e58cee2016-02-11 12:49:47 -08001150 fOctavesUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001151 kFloat_GrSLType, kDefault_GrSLPrecision,
1152 "octaves");
1153 const char* octavesUni = uniformHandler->getUniformCStr(fOctavesUni);
ethannicholas417011c2015-11-09 06:35:12 -08001154
cdalton5e58cee2016-02-11 12:49:47 -08001155 fZUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001156 kFloat_GrSLType, kDefault_GrSLPrecision,
1157 "z");
1158 const char* zUni = uniformHandler->getUniformCStr(fZUni);
ethannicholas417011c2015-11-09 06:35:12 -08001159
1160 // fade function
1161 static const GrGLSLShaderVar fadeArgs[] = {
1162 GrGLSLShaderVar("t", kVec3f_GrSLType)
1163 };
1164 SkString fadeFuncName;
1165 fsBuilder->emitFunction(kVec3f_GrSLType, "fade", SK_ARRAY_COUNT(fadeArgs),
1166 fadeArgs,
1167 "return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);",
1168 &fadeFuncName);
1169
1170 // perm function
1171 static const GrGLSLShaderVar permArgs[] = {
1172 GrGLSLShaderVar("x", kFloat_GrSLType)
1173 };
1174 SkString permFuncName;
1175 SkString permCode("return ");
1176 // FIXME even though I'm creating these textures with kRepeat_TileMode, they're clamped. Not
1177 // sure why. Using fract() (here and the next texture lookup) as a workaround.
1178 fsBuilder->appendTextureLookup(&permCode, args.fSamplers[0], "vec2(fract(x / 256.0), 0.0)",
1179 kVec2f_GrSLType);
1180 permCode.append(".r * 255.0;");
1181 fsBuilder->emitFunction(kFloat_GrSLType, "perm", SK_ARRAY_COUNT(permArgs), permArgs,
1182 permCode.c_str(), &permFuncName);
1183
1184 // grad function
1185 static const GrGLSLShaderVar gradArgs[] = {
1186 GrGLSLShaderVar("x", kFloat_GrSLType),
1187 GrGLSLShaderVar("p", kVec3f_GrSLType)
1188 };
1189 SkString gradFuncName;
1190 SkString gradCode("return dot(");
1191 fsBuilder->appendTextureLookup(&gradCode, args.fSamplers[1], "vec2(fract(x / 16.0), 0.0)",
1192 kVec2f_GrSLType);
1193 gradCode.append(".rgb * 255.0 - vec3(1.0), p);");
1194 fsBuilder->emitFunction(kFloat_GrSLType, "grad", SK_ARRAY_COUNT(gradArgs), gradArgs,
1195 gradCode.c_str(), &gradFuncName);
1196
1197 // lerp function
1198 static const GrGLSLShaderVar lerpArgs[] = {
1199 GrGLSLShaderVar("a", kFloat_GrSLType),
1200 GrGLSLShaderVar("b", kFloat_GrSLType),
1201 GrGLSLShaderVar("w", kFloat_GrSLType)
1202 };
1203 SkString lerpFuncName;
1204 fsBuilder->emitFunction(kFloat_GrSLType, "lerp", SK_ARRAY_COUNT(lerpArgs), lerpArgs,
1205 "return a + w * (b - a);", &lerpFuncName);
1206
1207 // noise function
1208 static const GrGLSLShaderVar noiseArgs[] = {
1209 GrGLSLShaderVar("p", kVec3f_GrSLType),
1210 };
1211 SkString noiseFuncName;
1212 SkString noiseCode;
1213 noiseCode.append("vec3 P = mod(floor(p), 256.0);");
1214 noiseCode.append("p -= floor(p);");
1215 noiseCode.appendf("vec3 f = %s(p);", fadeFuncName.c_str());
1216 noiseCode.appendf("float A = %s(P.x) + P.y;", permFuncName.c_str());
1217 noiseCode.appendf("float AA = %s(A) + P.z;", permFuncName.c_str());
1218 noiseCode.appendf("float AB = %s(A + 1.0) + P.z;", permFuncName.c_str());
1219 noiseCode.appendf("float B = %s(P.x + 1.0) + P.y;", permFuncName.c_str());
1220 noiseCode.appendf("float BA = %s(B) + P.z;", permFuncName.c_str());
1221 noiseCode.appendf("float BB = %s(B + 1.0) + P.z;", permFuncName.c_str());
1222 noiseCode.appendf("float result = %s(", lerpFuncName.c_str());
1223 noiseCode.appendf("%s(%s(%s(%s(AA), p),", lerpFuncName.c_str(), lerpFuncName.c_str(),
1224 gradFuncName.c_str(), permFuncName.c_str());
1225 noiseCode.appendf("%s(%s(BA), p + vec3(-1.0, 0.0, 0.0)), f.x),", gradFuncName.c_str(),
1226 permFuncName.c_str());
1227 noiseCode.appendf("%s(%s(%s(AB), p + vec3(0.0, -1.0, 0.0)),", lerpFuncName.c_str(),
1228 gradFuncName.c_str(), permFuncName.c_str());
1229 noiseCode.appendf("%s(%s(BB), p + vec3(-1.0, -1.0, 0.0)), f.x), f.y),",
1230 gradFuncName.c_str(), permFuncName.c_str());
1231 noiseCode.appendf("%s(%s(%s(%s(AA + 1.0), p + vec3(0.0, 0.0, -1.0)),",
1232 lerpFuncName.c_str(), lerpFuncName.c_str(), gradFuncName.c_str(),
1233 permFuncName.c_str());
1234 noiseCode.appendf("%s(%s(BA + 1.0), p + vec3(-1.0, 0.0, -1.0)), f.x),",
1235 gradFuncName.c_str(), permFuncName.c_str());
1236 noiseCode.appendf("%s(%s(%s(AB + 1.0), p + vec3(0.0, -1.0, -1.0)),",
1237 lerpFuncName.c_str(), gradFuncName.c_str(), permFuncName.c_str());
1238 noiseCode.appendf("%s(%s(BB + 1.0), p + vec3(-1.0, -1.0, -1.0)), f.x), f.y), f.z);",
1239 gradFuncName.c_str(), permFuncName.c_str());
1240 noiseCode.append("return result;");
1241 fsBuilder->emitFunction(kFloat_GrSLType, "noise", SK_ARRAY_COUNT(noiseArgs), noiseArgs,
1242 noiseCode.c_str(), &noiseFuncName);
1243
1244 // noiseOctaves function
1245 static const GrGLSLShaderVar noiseOctavesArgs[] = {
1246 GrGLSLShaderVar("p", kVec3f_GrSLType),
1247 GrGLSLShaderVar("octaves", kFloat_GrSLType),
1248 };
1249 SkString noiseOctavesFuncName;
1250 SkString noiseOctavesCode;
1251 noiseOctavesCode.append("float result = 0.0;");
1252 noiseOctavesCode.append("float ratio = 1.0;");
1253 noiseOctavesCode.append("for (float i = 0.0; i < octaves; i++) {");
1254 noiseOctavesCode.appendf("result += %s(p) / ratio;", noiseFuncName.c_str());
1255 noiseOctavesCode.append("p *= 2.0;");
1256 noiseOctavesCode.append("ratio *= 2.0;");
1257 noiseOctavesCode.append("}");
1258 noiseOctavesCode.append("return (result + 1.0) / 2.0;");
1259 fsBuilder->emitFunction(kFloat_GrSLType, "noiseOctaves", SK_ARRAY_COUNT(noiseOctavesArgs),
1260 noiseOctavesArgs, noiseOctavesCode.c_str(), &noiseOctavesFuncName);
1261
1262 fsBuilder->codeAppendf("vec2 coords = %s * %s;", vCoords.c_str(), baseFrequencyUni);
1263 fsBuilder->codeAppendf("float r = %s(vec3(coords, %s), %s);", noiseOctavesFuncName.c_str(),
1264 zUni, octavesUni);
egdaniel478c04e2015-11-09 07:40:49 -08001265 fsBuilder->codeAppendf("float g = %s(vec3(coords, %s + 0000.0), %s);",
ethannicholas417011c2015-11-09 06:35:12 -08001266 noiseOctavesFuncName.c_str(), zUni, octavesUni);
egdaniel478c04e2015-11-09 07:40:49 -08001267 fsBuilder->codeAppendf("float b = %s(vec3(coords, %s + 0000.0), %s);",
ethannicholas417011c2015-11-09 06:35:12 -08001268 noiseOctavesFuncName.c_str(), zUni, octavesUni);
egdaniel478c04e2015-11-09 07:40:49 -08001269 fsBuilder->codeAppendf("float a = %s(vec3(coords, %s + 0000.0), %s);",
ethannicholas417011c2015-11-09 06:35:12 -08001270 noiseOctavesFuncName.c_str(), zUni, octavesUni);
1271 fsBuilder->codeAppendf("%s = vec4(r, g, b, a);", args.fOutputColor);
1272
1273 // Clamp values
1274 fsBuilder->codeAppendf("%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor);
1275
1276 // Pre-multiply the result
1277 fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
1278 args.fOutputColor, args.fOutputColor,
1279 args.fOutputColor, args.fOutputColor);
1280}
1281
1282void GrGLImprovedPerlinNoise::GenKey(const GrProcessor& processor, const GrGLSLCaps&,
1283 GrProcessorKeyBuilder* b) {
1284}
1285
1286void GrGLImprovedPerlinNoise::onSetData(const GrGLSLProgramDataManager& pdman,
1287 const GrProcessor& processor) {
1288 INHERITED::onSetData(pdman, processor);
1289
1290 const GrImprovedPerlinNoiseEffect& noise = processor.cast<GrImprovedPerlinNoiseEffect>();
1291
1292 const SkVector& baseFrequency = noise.baseFrequency();
1293 pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
1294
egdaniel478c04e2015-11-09 07:40:49 -08001295 pdman.set1f(fOctavesUni, SkIntToScalar(noise.octaves()));
ethannicholas417011c2015-11-09 06:35:12 -08001296
1297 pdman.set1f(fZUni, noise.z());
1298}
1299
1300/////////////////////////////////////////////////////////////////////
1301const GrFragmentProcessor* SkPerlinNoiseShader2::asFragmentProcessor(
1302 GrContext* context,
1303 const SkMatrix& viewM,
1304 const SkMatrix* externalLocalMatrix,
1305 SkFilterQuality) const {
1306 SkASSERT(context);
1307
1308 SkMatrix localMatrix = this->getLocalMatrix();
1309 if (externalLocalMatrix) {
1310 localMatrix.preConcat(*externalLocalMatrix);
1311 }
1312
1313 SkMatrix matrix = viewM;
1314 matrix.preConcat(localMatrix);
1315
1316 // Either we don't stitch tiles, either we have a valid tile size
1317 SkASSERT(!fStitchTiles || !fTileSize.isEmpty());
1318
1319 SkPerlinNoiseShader2::PaintingData* paintingData =
1320 new PaintingData(fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY, matrix);
1321
1322 SkMatrix m = viewM;
1323 m.setTranslateX(-localMatrix.getTranslateX() + SK_Scalar1);
1324 m.setTranslateY(-localMatrix.getTranslateY() + SK_Scalar1);
1325
1326 if (fType == kImprovedNoise_Type) {
1327 GrTextureParams textureParams(SkShader::TileMode::kRepeat_TileMode,
1328 GrTextureParams::FilterMode::kNone_FilterMode);
1329 SkAutoTUnref<GrTexture> permutationsTexture(
1330 GrRefCachedBitmapTexture(context, paintingData->getImprovedPermutationsBitmap(),
1331 textureParams));
1332 SkAutoTUnref<GrTexture> gradientTexture(
1333 GrRefCachedBitmapTexture(context, paintingData->getGradientBitmap(),
1334 textureParams));
1335 return GrImprovedPerlinNoiseEffect::Create(fNumOctaves, fSeed, paintingData,
1336 permutationsTexture, gradientTexture, m);
1337 }
1338
1339 if (0 == fNumOctaves) {
1340 if (kFractalNoise_Type == fType) {
1341 // Extract the incoming alpha and emit rgba = (a/4, a/4, a/4, a/2)
1342 SkAutoTUnref<const GrFragmentProcessor> inner(
1343 GrConstColorProcessor::Create(0x80404040,
1344 GrConstColorProcessor::kModulateRGBA_InputMode));
1345 return GrFragmentProcessor::MulOutputByInputAlpha(inner);
1346 }
1347 // Emit zero.
1348 return GrConstColorProcessor::Create(0x0, GrConstColorProcessor::kIgnore_InputMode);
1349 }
1350
1351 SkAutoTUnref<GrTexture> permutationsTexture(
1352 GrRefCachedBitmapTexture(context, paintingData->getPermutationsBitmap(),
1353 GrTextureParams::ClampNoFilter()));
1354 SkAutoTUnref<GrTexture> noiseTexture(
1355 GrRefCachedBitmapTexture(context, paintingData->getNoiseBitmap(),
1356 GrTextureParams::ClampNoFilter()));
1357
1358 if ((permutationsTexture) && (noiseTexture)) {
1359 SkAutoTUnref<GrFragmentProcessor> inner(
1360 GrPerlinNoise2Effect::Create(fType,
1361 fNumOctaves,
1362 fStitchTiles,
1363 paintingData,
1364 permutationsTexture, noiseTexture,
1365 m));
1366 return GrFragmentProcessor::MulOutputByInputAlpha(inner);
1367 }
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