blob: 980593f8fe8f056b1594bfb3caa4d5495a503397 [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
Robert Phillipsdd8b72a2017-02-07 17:28:15 +00008#include "SkPerlinNoiseShader2.h"
Herb Derby83e939b2017-02-07 14:25:11 -05009
10#include "SkArenaAlloc.h"
11#include "SkDither.h"
ethannicholas417011c2015-11-09 06:35:12 -080012#include "SkColorFilter.h"
13#include "SkReadBuffer.h"
14#include "SkWriteBuffer.h"
15#include "SkShader.h"
16#include "SkUnPreMultiply.h"
17#include "SkString.h"
18
19#if SK_SUPPORT_GPU
20#include "GrContext.h"
21#include "GrCoordTransform.h"
ethannicholas417011c2015-11-09 06:35:12 -080022#include "SkGr.h"
Robert Phillips6f9f7eb2017-02-18 15:15:51 -050023#include "SkGrPriv.h"
ethannicholas417011c2015-11-09 06:35:12 -080024#include "effects/GrConstColorProcessor.h"
egdaniel64c47282015-11-13 06:54:19 -080025#include "glsl/GrGLSLFragmentProcessor.h"
egdaniel2d721d32015-11-11 13:06:05 -080026#include "glsl/GrGLSLFragmentShaderBuilder.h"
ethannicholas417011c2015-11-09 06:35:12 -080027#include "glsl/GrGLSLProgramDataManager.h"
egdaniel7ea439b2015-12-03 09:20:44 -080028#include "glsl/GrGLSLUniformHandler.h"
ethannicholas417011c2015-11-09 06:35:12 -080029#endif
30
31static const int kBlockSize = 256;
32static const int kBlockMask = kBlockSize - 1;
33static const int kPerlinNoise = 4096;
34static const int kRandMaximum = SK_MaxS32; // 2**31 - 1
35
Herb Derby99d47212017-01-31 15:30:44 -050036static uint8_t improved_noise_permutations[] = {
37 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103,
38 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26,
39 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174,
40 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231,
41 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143,
42 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196,
43 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124,
44 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17,
45 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101,
46 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185,
47 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81,
48 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176,
49 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243,
ethannicholas417011c2015-11-09 06:35:12 -080050 141, 128, 195, 78, 66, 215, 61, 156, 180,
Herb Derby99d47212017-01-31 15:30:44 -050051 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103,
52 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26,
53 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174,
54 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231,
55 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143,
56 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196,
57 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124,
58 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17,
59 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101,
60 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185,
61 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81,
62 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176,
63 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243,
ethannicholas417011c2015-11-09 06:35:12 -080064 141, 128, 195, 78, 66, 215, 61, 156, 180
65};
66
67namespace {
68
69// noiseValue is the color component's value (or color)
70// limitValue is the maximum perlin noise array index value allowed
71// newValue is the current noise dimension (either width or height)
72inline int checkNoise(int noiseValue, int limitValue, int newValue) {
73 // If the noise value would bring us out of bounds of the current noise array while we are
74 // stiching noise tiles together, wrap the noise around the current dimension of the noise to
75 // stay within the array bounds in a continuous fashion (so that tiling lines are not visible)
76 if (noiseValue >= limitValue) {
77 noiseValue -= newValue;
78 }
79 return noiseValue;
80}
81
82inline SkScalar smoothCurve(SkScalar t) {
Mike Reeddf85c382017-02-14 10:59:19 -050083 return t * t * (3 - 2 * t);
ethannicholas417011c2015-11-09 06:35:12 -080084}
85
86} // end namespace
87
88struct SkPerlinNoiseShader2::StitchData {
89 StitchData()
90 : fWidth(0)
91 , fWrapX(0)
92 , fHeight(0)
93 , fWrapY(0)
94 {}
95
96 bool operator==(const StitchData& other) const {
97 return fWidth == other.fWidth &&
98 fWrapX == other.fWrapX &&
99 fHeight == other.fHeight &&
100 fWrapY == other.fWrapY;
101 }
102
103 int fWidth; // How much to subtract to wrap for stitching.
104 int fWrapX; // Minimum value to wrap.
105 int fHeight;
106 int fWrapY;
107};
108
109struct SkPerlinNoiseShader2::PaintingData {
110 PaintingData(const SkISize& tileSize, SkScalar seed,
111 SkScalar baseFrequencyX, SkScalar baseFrequencyY,
112 const SkMatrix& matrix)
113 {
114 SkVector vec[2] = {
115 { SkScalarInvert(baseFrequencyX), SkScalarInvert(baseFrequencyY) },
116 { SkIntToScalar(tileSize.fWidth), SkIntToScalar(tileSize.fHeight) },
117 };
118 matrix.mapVectors(vec, 2);
119
120 fBaseFrequency.set(SkScalarInvert(vec[0].fX), SkScalarInvert(vec[0].fY));
121 fTileSize.set(SkScalarRoundToInt(vec[1].fX), SkScalarRoundToInt(vec[1].fY));
122 this->init(seed);
123 if (!fTileSize.isEmpty()) {
124 this->stitch();
125 }
126
127#if SK_SUPPORT_GPU
128 fPermutationsBitmap.setInfo(SkImageInfo::MakeA8(kBlockSize, 1));
129 fPermutationsBitmap.setPixels(fLatticeSelector);
130
131 fNoiseBitmap.setInfo(SkImageInfo::MakeN32Premul(kBlockSize, 4));
132 fNoiseBitmap.setPixels(fNoise[0][0]);
133
134 fImprovedPermutationsBitmap.setInfo(SkImageInfo::MakeA8(256, 1));
135 fImprovedPermutationsBitmap.setPixels(improved_noise_permutations);
136
137 fGradientBitmap.setInfo(SkImageInfo::MakeN32Premul(16, 1));
138 static uint8_t gradients[] = { 2, 2, 1, 0,
Herb Derby99d47212017-01-31 15:30:44 -0500139 0, 2, 1, 0,
140 2, 0, 1, 0,
141 0, 0, 1, 0,
142 2, 1, 2, 0,
143 0, 1, 2, 0,
144 2, 1, 0, 0,
145 0, 1, 0, 0,
146 1, 2, 2, 0,
147 1, 0, 2, 0,
148 1, 2, 0, 0,
149 1, 0, 0, 0,
150 2, 2, 1, 0,
151 1, 0, 2, 0,
152 0, 2, 1, 0,
ethannicholas417011c2015-11-09 06:35:12 -0800153 1, 0, 0, 0 };
154 fGradientBitmap.setPixels(gradients);
155#endif
156 }
157
158 int fSeed;
159 uint8_t fLatticeSelector[kBlockSize];
160 uint16_t fNoise[4][kBlockSize][2];
161 SkPoint fGradient[4][kBlockSize];
162 SkISize fTileSize;
163 SkVector fBaseFrequency;
164 StitchData fStitchDataInit;
165
166private:
167
168#if SK_SUPPORT_GPU
169 SkBitmap fPermutationsBitmap;
170 SkBitmap fNoiseBitmap;
171 SkBitmap fImprovedPermutationsBitmap;
172 SkBitmap fGradientBitmap;
173#endif
174
175 inline int random() {
176 static const int gRandAmplitude = 16807; // 7**5; primitive root of m
177 static const int gRandQ = 127773; // m / a
178 static const int gRandR = 2836; // m % a
179
180 int result = gRandAmplitude * (fSeed % gRandQ) - gRandR * (fSeed / gRandQ);
181 if (result <= 0)
182 result += kRandMaximum;
183 fSeed = result;
184 return result;
185 }
186
187 // Only called once. Could be part of the constructor.
188 void init(SkScalar seed)
189 {
190 static const SkScalar gInvBlockSizef = SkScalarInvert(SkIntToScalar(kBlockSize));
191
192 // According to the SVG spec, we must truncate (not round) the seed value.
193 fSeed = SkScalarTruncToInt(seed);
194 // The seed value clamp to the range [1, kRandMaximum - 1].
195 if (fSeed <= 0) {
196 fSeed = -(fSeed % (kRandMaximum - 1)) + 1;
197 }
198 if (fSeed > kRandMaximum - 1) {
199 fSeed = kRandMaximum - 1;
200 }
201 for (int channel = 0; channel < 4; ++channel) {
202 for (int i = 0; i < kBlockSize; ++i) {
203 fLatticeSelector[i] = i;
204 fNoise[channel][i][0] = (random() % (2 * kBlockSize));
205 fNoise[channel][i][1] = (random() % (2 * kBlockSize));
206 }
207 }
208 for (int i = kBlockSize - 1; i > 0; --i) {
209 int k = fLatticeSelector[i];
210 int j = random() % kBlockSize;
211 SkASSERT(j >= 0);
212 SkASSERT(j < kBlockSize);
213 fLatticeSelector[i] = fLatticeSelector[j];
214 fLatticeSelector[j] = k;
215 }
216
217 // Perform the permutations now
218 {
219 // Copy noise data
220 uint16_t noise[4][kBlockSize][2];
221 for (int i = 0; i < kBlockSize; ++i) {
222 for (int channel = 0; channel < 4; ++channel) {
223 for (int j = 0; j < 2; ++j) {
224 noise[channel][i][j] = fNoise[channel][i][j];
225 }
226 }
227 }
228 // Do permutations on noise data
229 for (int i = 0; i < kBlockSize; ++i) {
230 for (int channel = 0; channel < 4; ++channel) {
231 for (int j = 0; j < 2; ++j) {
232 fNoise[channel][i][j] = noise[channel][fLatticeSelector[i]][j];
233 }
234 }
235 }
236 }
237
238 // Half of the largest possible value for 16 bit unsigned int
239 static const SkScalar gHalfMax16bits = 32767.5f;
240
241 // Compute gradients from permutated noise data
242 for (int channel = 0; channel < 4; ++channel) {
243 for (int i = 0; i < kBlockSize; ++i) {
244 fGradient[channel][i] = SkPoint::Make(
Mike Reeddf85c382017-02-14 10:59:19 -0500245 (fNoise[channel][i][0] - kBlockSize) * gInvBlockSizef,
246 (fNoise[channel][i][1] - kBlockSize) * gInvBlockSizef);
ethannicholas417011c2015-11-09 06:35:12 -0800247 fGradient[channel][i].normalize();
248 // Put the normalized gradient back into the noise data
Mike Reeddf85c382017-02-14 10:59:19 -0500249 fNoise[channel][i][0] = SkScalarRoundToInt(
250 (fGradient[channel][i].fX + 1) * gHalfMax16bits);
251 fNoise[channel][i][1] = SkScalarRoundToInt(
252 (fGradient[channel][i].fY + 1) * gHalfMax16bits);
ethannicholas417011c2015-11-09 06:35:12 -0800253 }
254 }
255 }
256
257 // Only called once. Could be part of the constructor.
258 void stitch() {
259 SkScalar tileWidth = SkIntToScalar(fTileSize.width());
260 SkScalar tileHeight = SkIntToScalar(fTileSize.height());
261 SkASSERT(tileWidth > 0 && tileHeight > 0);
262 // When stitching tiled turbulence, the frequencies must be adjusted
263 // so that the tile borders will be continuous.
264 if (fBaseFrequency.fX) {
265 SkScalar lowFrequencx =
266 SkScalarFloorToScalar(tileWidth * fBaseFrequency.fX) / tileWidth;
267 SkScalar highFrequencx =
268 SkScalarCeilToScalar(tileWidth * fBaseFrequency.fX) / tileWidth;
269 // BaseFrequency should be non-negative according to the standard.
270 if (fBaseFrequency.fX / lowFrequencx < highFrequencx / fBaseFrequency.fX) {
271 fBaseFrequency.fX = lowFrequencx;
272 } else {
273 fBaseFrequency.fX = highFrequencx;
274 }
275 }
276 if (fBaseFrequency.fY) {
277 SkScalar lowFrequency =
278 SkScalarFloorToScalar(tileHeight * fBaseFrequency.fY) / tileHeight;
279 SkScalar highFrequency =
280 SkScalarCeilToScalar(tileHeight * fBaseFrequency.fY) / tileHeight;
281 if (fBaseFrequency.fY / lowFrequency < highFrequency / fBaseFrequency.fY) {
282 fBaseFrequency.fY = lowFrequency;
283 } else {
284 fBaseFrequency.fY = highFrequency;
285 }
286 }
287 // Set up TurbulenceInitial stitch values.
288 fStitchDataInit.fWidth =
289 SkScalarRoundToInt(tileWidth * fBaseFrequency.fX);
290 fStitchDataInit.fWrapX = kPerlinNoise + fStitchDataInit.fWidth;
291 fStitchDataInit.fHeight =
292 SkScalarRoundToInt(tileHeight * fBaseFrequency.fY);
293 fStitchDataInit.fWrapY = kPerlinNoise + fStitchDataInit.fHeight;
294 }
295
296public:
297
298#if SK_SUPPORT_GPU
299 const SkBitmap& getPermutationsBitmap() const { return fPermutationsBitmap; }
300
301 const SkBitmap& getNoiseBitmap() const { return fNoiseBitmap; }
302
303 const SkBitmap& getImprovedPermutationsBitmap() const { return fImprovedPermutationsBitmap; }
304
305 const SkBitmap& getGradientBitmap() const { return fGradientBitmap; }
306#endif
307};
308
reed8a21c9f2016-03-08 18:50:00 -0800309sk_sp<SkShader> SkPerlinNoiseShader2::MakeFractalNoise(SkScalar baseFrequencyX,
310 SkScalar baseFrequencyY,
311 int numOctaves, SkScalar seed,
312 const SkISize* tileSize) {
313 return sk_sp<SkShader>(new SkPerlinNoiseShader2(kFractalNoise_Type, baseFrequencyX,
314 baseFrequencyY, numOctaves, seed, tileSize));
ethannicholas417011c2015-11-09 06:35:12 -0800315}
316
reed8a21c9f2016-03-08 18:50:00 -0800317sk_sp<SkShader> SkPerlinNoiseShader2::MakeTurbulence(SkScalar baseFrequencyX,
318 SkScalar baseFrequencyY,
319 int numOctaves, SkScalar seed,
320 const SkISize* tileSize) {
321 return sk_sp<SkShader>(new SkPerlinNoiseShader2(kTurbulence_Type, baseFrequencyX,
322 baseFrequencyY, numOctaves, seed, tileSize));
ethannicholas417011c2015-11-09 06:35:12 -0800323}
324
reed8a21c9f2016-03-08 18:50:00 -0800325sk_sp<SkShader> SkPerlinNoiseShader2::MakeImprovedNoise(SkScalar baseFrequencyX,
326 SkScalar baseFrequencyY,
327 int numOctaves, SkScalar z) {
328 return sk_sp<SkShader>(new SkPerlinNoiseShader2(kImprovedNoise_Type, baseFrequencyX,
329 baseFrequencyY, numOctaves, z, NULL));
ethannicholas417011c2015-11-09 06:35:12 -0800330}
331
332SkPerlinNoiseShader2::SkPerlinNoiseShader2(SkPerlinNoiseShader2::Type type,
333 SkScalar baseFrequencyX,
334 SkScalar baseFrequencyY,
335 int numOctaves,
336 SkScalar seed,
337 const SkISize* tileSize)
338 : fType(type)
339 , fBaseFrequencyX(baseFrequencyX)
340 , fBaseFrequencyY(baseFrequencyY)
341 , fNumOctaves(numOctaves > 255 ? 255 : numOctaves/*[0,255] octaves allowed*/)
342 , fSeed(seed)
343 , fTileSize(nullptr == tileSize ? SkISize::Make(0, 0) : *tileSize)
344 , fStitchTiles(!fTileSize.isEmpty())
345{
346 SkASSERT(numOctaves >= 0 && numOctaves < 256);
347}
348
349SkPerlinNoiseShader2::~SkPerlinNoiseShader2() {
350}
351
reed60c9b582016-04-03 09:11:13 -0700352sk_sp<SkFlattenable> SkPerlinNoiseShader2::CreateProc(SkReadBuffer& buffer) {
ethannicholas417011c2015-11-09 06:35:12 -0800353 Type type = (Type)buffer.readInt();
354 SkScalar freqX = buffer.readScalar();
355 SkScalar freqY = buffer.readScalar();
356 int octaves = buffer.readInt();
357 SkScalar seed = buffer.readScalar();
358 SkISize tileSize;
359 tileSize.fWidth = buffer.readInt();
360 tileSize.fHeight = buffer.readInt();
361
362 switch (type) {
363 case kFractalNoise_Type:
reed60c9b582016-04-03 09:11:13 -0700364 return SkPerlinNoiseShader2::MakeFractalNoise(freqX, freqY, octaves, seed, &tileSize);
ethannicholas417011c2015-11-09 06:35:12 -0800365 case kTurbulence_Type:
reed60c9b582016-04-03 09:11:13 -0700366 return SkPerlinNoiseShader2::MakeTubulence(freqX, freqY, octaves, seed, &tileSize);
ethannicholas417011c2015-11-09 06:35:12 -0800367 case kImprovedNoise_Type:
reed60c9b582016-04-03 09:11:13 -0700368 return SkPerlinNoiseShader2::MakeImprovedNoise(freqX, freqY, octaves, seed);
ethannicholas417011c2015-11-09 06:35:12 -0800369 default:
370 return nullptr;
371 }
372}
373
374void SkPerlinNoiseShader2::flatten(SkWriteBuffer& buffer) const {
375 buffer.writeInt((int) fType);
376 buffer.writeScalar(fBaseFrequencyX);
377 buffer.writeScalar(fBaseFrequencyY);
378 buffer.writeInt(fNumOctaves);
379 buffer.writeScalar(fSeed);
380 buffer.writeInt(fTileSize.fWidth);
381 buffer.writeInt(fTileSize.fHeight);
382}
383
384SkScalar SkPerlinNoiseShader2::PerlinNoiseShaderContext::noise2D(
385 int channel, const StitchData& stitchData, const SkPoint& noiseVector) const {
386 struct Noise {
387 int noisePositionIntegerValue;
388 int nextNoisePositionIntegerValue;
389 SkScalar noisePositionFractionValue;
390 Noise(SkScalar component)
391 {
392 SkScalar position = component + kPerlinNoise;
393 noisePositionIntegerValue = SkScalarFloorToInt(position);
394 noisePositionFractionValue = position - SkIntToScalar(noisePositionIntegerValue);
395 nextNoisePositionIntegerValue = noisePositionIntegerValue + 1;
396 }
397 };
398 Noise noiseX(noiseVector.x());
399 Noise noiseY(noiseVector.y());
400 SkScalar u, v;
401 const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNoiseShader2&>(fShader);
402 // If stitching, adjust lattice points accordingly.
403 if (perlinNoiseShader.fStitchTiles) {
404 noiseX.noisePositionIntegerValue =
405 checkNoise(noiseX.noisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth);
406 noiseY.noisePositionIntegerValue =
407 checkNoise(noiseY.noisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight);
408 noiseX.nextNoisePositionIntegerValue =
409 checkNoise(noiseX.nextNoisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth);
410 noiseY.nextNoisePositionIntegerValue =
411 checkNoise(noiseY.nextNoisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight);
412 }
413 noiseX.noisePositionIntegerValue &= kBlockMask;
414 noiseY.noisePositionIntegerValue &= kBlockMask;
415 noiseX.nextNoisePositionIntegerValue &= kBlockMask;
416 noiseY.nextNoisePositionIntegerValue &= kBlockMask;
417 int i =
418 fPaintingData->fLatticeSelector[noiseX.noisePositionIntegerValue];
419 int j =
420 fPaintingData->fLatticeSelector[noiseX.nextNoisePositionIntegerValue];
421 int b00 = (i + noiseY.noisePositionIntegerValue) & kBlockMask;
422 int b10 = (j + noiseY.noisePositionIntegerValue) & kBlockMask;
423 int b01 = (i + noiseY.nextNoisePositionIntegerValue) & kBlockMask;
424 int b11 = (j + noiseY.nextNoisePositionIntegerValue) & kBlockMask;
425 SkScalar sx = smoothCurve(noiseX.noisePositionFractionValue);
426 SkScalar sy = smoothCurve(noiseY.noisePositionFractionValue);
427 // This is taken 1:1 from SVG spec: http://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement
428 SkPoint fractionValue = SkPoint::Make(noiseX.noisePositionFractionValue,
429 noiseY.noisePositionFractionValue); // Offset (0,0)
430 u = fPaintingData->fGradient[channel][b00].dot(fractionValue);
431 fractionValue.fX -= SK_Scalar1; // Offset (-1,0)
432 v = fPaintingData->fGradient[channel][b10].dot(fractionValue);
433 SkScalar a = SkScalarInterp(u, v, sx);
434 fractionValue.fY -= SK_Scalar1; // Offset (-1,-1)
435 v = fPaintingData->fGradient[channel][b11].dot(fractionValue);
436 fractionValue.fX = noiseX.noisePositionFractionValue; // Offset (0,-1)
437 u = fPaintingData->fGradient[channel][b01].dot(fractionValue);
438 SkScalar b = SkScalarInterp(u, v, sx);
439 return SkScalarInterp(a, b, sy);
440}
441
442SkScalar SkPerlinNoiseShader2::PerlinNoiseShaderContext::calculateTurbulenceValueForPoint(
443 int channel, StitchData& stitchData, const SkPoint& point) const {
444 const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNoiseShader2&>(fShader);
445 if (perlinNoiseShader.fStitchTiles) {
446 // Set up TurbulenceInitial stitch values.
447 stitchData = fPaintingData->fStitchDataInit;
448 }
449 SkScalar turbulenceFunctionResult = 0;
Mike Reeddf85c382017-02-14 10:59:19 -0500450 SkPoint noiseVector(SkPoint::Make(point.x() * fPaintingData->fBaseFrequency.fX,
451 point.y() * fPaintingData->fBaseFrequency.fY));
ethannicholas417011c2015-11-09 06:35:12 -0800452 SkScalar ratio = SK_Scalar1;
453 for (int octave = 0; octave < perlinNoiseShader.fNumOctaves; ++octave) {
454 SkScalar noise = noise2D(channel, stitchData, noiseVector);
455 SkScalar numer = (perlinNoiseShader.fType == kFractalNoise_Type) ?
456 noise : SkScalarAbs(noise);
457 turbulenceFunctionResult += numer / ratio;
458 noiseVector.fX *= 2;
459 noiseVector.fY *= 2;
460 ratio *= 2;
461 if (perlinNoiseShader.fStitchTiles) {
462 // Update stitch values
463 stitchData.fWidth *= 2;
464 stitchData.fWrapX = stitchData.fWidth + kPerlinNoise;
465 stitchData.fHeight *= 2;
466 stitchData.fWrapY = stitchData.fHeight + kPerlinNoise;
467 }
468 }
469
470 // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
471 // by fractalNoise and (turbulenceFunctionResult) by turbulence.
472 if (perlinNoiseShader.fType == kFractalNoise_Type) {
Mike Reeddf85c382017-02-14 10:59:19 -0500473 turbulenceFunctionResult = SkScalarHalf(turbulenceFunctionResult + 1);
ethannicholas417011c2015-11-09 06:35:12 -0800474 }
475
476 if (channel == 3) { // Scale alpha by paint value
477 turbulenceFunctionResult *= SkIntToScalar(getPaintAlpha()) / 255;
478 }
479
480 // Clamp result
481 return SkScalarPin(turbulenceFunctionResult, 0, SK_Scalar1);
482}
483
484////////////////////////////////////////////////////////////////////////////////////////////////////
485// Improved Perlin Noise based on Java implementation found at http://mrl.nyu.edu/~perlin/noise/
Herb Derby99d47212017-01-31 15:30:44 -0500486static SkScalar fade(SkScalar t) {
487 return t * t * t * (t * (t * 6 - 15) + 10);
ethannicholas417011c2015-11-09 06:35:12 -0800488}
489
Herb Derby99d47212017-01-31 15:30:44 -0500490static SkScalar lerp(SkScalar t, SkScalar a, SkScalar b) {
491 return a + t * (b - a);
ethannicholas417011c2015-11-09 06:35:12 -0800492}
493
494static SkScalar grad(int hash, SkScalar x, SkScalar y, SkScalar z) {
495 int h = hash & 15;
496 SkScalar u = h < 8 ? x : y;
497 SkScalar v = h < 4 ? y : h == 12 || h == 14 ? x : z;
498 return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
499}
500
501SkScalar SkPerlinNoiseShader2::PerlinNoiseShaderContext::calculateImprovedNoiseValueForPoint(
502 int channel, const SkPoint& point) const {
503 const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNoiseShader2&>(fShader);
504 SkScalar x = point.fX * perlinNoiseShader.fBaseFrequencyX;
505 SkScalar y = point.fY * perlinNoiseShader.fBaseFrequencyY;
506 // z offset between different channels, chosen arbitrarily
507 static const SkScalar CHANNEL_DELTA = 1000.0f;
508 SkScalar z = channel * CHANNEL_DELTA + perlinNoiseShader.fSeed;
509 SkScalar result = 0;
510 SkScalar ratio = SK_Scalar1;
511 for (int i = 0; i < perlinNoiseShader.fNumOctaves; i++) {
512 int X = SkScalarFloorToInt(x) & 255;
513 int Y = SkScalarFloorToInt(y) & 255;
514 int Z = SkScalarFloorToInt(z) & 255;
515 SkScalar px = x - SkScalarFloorToScalar(x);
516 SkScalar py = y - SkScalarFloorToScalar(y);
517 SkScalar pz = z - SkScalarFloorToScalar(z);
518 SkScalar u = fade(px);
519 SkScalar v = fade(py);
520 SkScalar w = fade(pz);
521 uint8_t* permutations = improved_noise_permutations;
522 int A = permutations[X] + Y;
523 int AA = permutations[A] + Z;
524 int AB = permutations[A + 1] + Z;
525 int B = permutations[X + 1] + Y;
526 int BA = permutations[B] + Z;
527 int BB = permutations[B + 1] + Z;
528 result += lerp(w, lerp(v, lerp(u, grad(permutations[AA ], px , py , pz ),
529 grad(permutations[BA ], px - 1, py , pz )),
530 lerp(u, grad(permutations[AB ], px , py - 1, pz ),
531 grad(permutations[BB ], px - 1, py - 1, pz ))),
532 lerp(v, lerp(u, grad(permutations[AA + 1], px , py , pz - 1),
533 grad(permutations[BA + 1], px - 1, py , pz - 1)),
534 lerp(u, grad(permutations[AB + 1], px , py - 1, pz - 1),
535 grad(permutations[BB + 1], px - 1, py - 1, pz - 1)))) /
536 ratio;
537 x *= 2;
538 y *= 2;
539 ratio *= 2;
540 }
541 result = SkScalarClampMax((result + 1.0f) / 2.0f, 1.0f);
542 return result;
543}
544////////////////////////////////////////////////////////////////////////////////////////////////////
545
546SkPMColor SkPerlinNoiseShader2::PerlinNoiseShaderContext::shade(
547 const SkPoint& point, StitchData& stitchData) const {
548 const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNoiseShader2&>(fShader);
549 SkPoint newPoint;
550 fMatrix.mapPoints(&newPoint, &point, 1);
551 newPoint.fX = SkScalarRoundToScalar(newPoint.fX);
552 newPoint.fY = SkScalarRoundToScalar(newPoint.fY);
553
554 U8CPU rgba[4];
555 for (int channel = 3; channel >= 0; --channel) {
556 SkScalar value;
557 if (perlinNoiseShader.fType == kImprovedNoise_Type) {
558 value = calculateImprovedNoiseValueForPoint(channel, newPoint);
559 }
560 else {
561 value = calculateTurbulenceValueForPoint(channel, stitchData, newPoint);
562 }
563 rgba[channel] = SkScalarFloorToInt(255 * value);
564 }
565 return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]);
566}
567
Herb Derby83e939b2017-02-07 14:25:11 -0500568SkShader::Context* SkPerlinNoiseShader2::onMakeContext(const ContextRec& rec,
569 SkArenaAlloc* alloc) const {
570 return alloc->make<PerlinNoiseShaderContext>(*this, rec);
ethannicholas417011c2015-11-09 06:35:12 -0800571}
572
573SkPerlinNoiseShader2::PerlinNoiseShaderContext::PerlinNoiseShaderContext(
574 const SkPerlinNoiseShader2& shader, const ContextRec& rec)
575 : INHERITED(shader, rec)
576{
577 SkMatrix newMatrix = *rec.fMatrix;
578 newMatrix.preConcat(shader.getLocalMatrix());
579 if (rec.fLocalMatrix) {
580 newMatrix.preConcat(*rec.fLocalMatrix);
581 }
582 // This (1,1) translation is due to WebKit's 1 based coordinates for the noise
583 // (as opposed to 0 based, usually). The same adjustment is in the setData() function.
584 fMatrix.setTranslate(-newMatrix.getTranslateX() + SK_Scalar1, -newMatrix.getTranslateY() + SK_Scalar1);
585 fPaintingData = new PaintingData(shader.fTileSize, shader.fSeed, shader.fBaseFrequencyX,
586 shader.fBaseFrequencyY, newMatrix);
587}
588
589SkPerlinNoiseShader2::PerlinNoiseShaderContext::~PerlinNoiseShaderContext() { delete fPaintingData; }
590
591void SkPerlinNoiseShader2::PerlinNoiseShaderContext::shadeSpan(
592 int x, int y, SkPMColor result[], int count) {
593 SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y));
594 StitchData stitchData;
595 for (int i = 0; i < count; ++i) {
596 result[i] = shade(point, stitchData);
597 point.fX += SK_Scalar1;
598 }
599}
600
ethannicholas417011c2015-11-09 06:35:12 -0800601/////////////////////////////////////////////////////////////////////
602
603#if SK_SUPPORT_GPU
604
egdaniel64c47282015-11-13 06:54:19 -0800605class GrGLPerlinNoise2 : public GrGLSLFragmentProcessor {
ethannicholas417011c2015-11-09 06:35:12 -0800606public:
robertphillipsbf536af2016-02-04 06:11:53 -0800607 void emitCode(EmitArgs&) override;
ethannicholas417011c2015-11-09 06:35:12 -0800608
Brian Salomon94efbf52016-11-29 13:43:05 -0500609 static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder* b);
ethannicholas417011c2015-11-09 06:35:12 -0800610
611protected:
612 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
613
614private:
ethannicholas417011c2015-11-09 06:35:12 -0800615 GrGLSLProgramDataManager::UniformHandle fStitchDataUni;
ethannicholas417011c2015-11-09 06:35:12 -0800616 GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni;
617
egdaniel64c47282015-11-13 06:54:19 -0800618 typedef GrGLSLFragmentProcessor INHERITED;
ethannicholas417011c2015-11-09 06:35:12 -0800619};
620
621/////////////////////////////////////////////////////////////////////
622
623class GrPerlinNoise2Effect : public GrFragmentProcessor {
624public:
Robert Phillips6f9f7eb2017-02-18 15:15:51 -0500625 static sk_sp<GrFragmentProcessor> Make(GrTextureProvider* textureProvider,
626 SkPerlinNoiseShader2::Type type,
bungeman06ca8ec2016-06-09 08:01:03 -0700627 int numOctaves, bool stitchTiles,
628 SkPerlinNoiseShader2::PaintingData* paintingData,
Robert Phillips6f9f7eb2017-02-18 15:15:51 -0500629 sk_sp<GrTextureProxy> permutationsProxy,
630 sk_sp<GrTextureProxy> noiseProxy,
bungeman06ca8ec2016-06-09 08:01:03 -0700631 const SkMatrix& matrix) {
632 return sk_sp<GrFragmentProcessor>(
Robert Phillips6f9f7eb2017-02-18 15:15:51 -0500633 new GrPerlinNoise2Effect(textureProvider, type, numOctaves, stitchTiles, paintingData,
634 std::move(permutationsProxy), std::move(noiseProxy), matrix));
ethannicholas417011c2015-11-09 06:35:12 -0800635 }
636
637 virtual ~GrPerlinNoise2Effect() { delete fPaintingData; }
638
639 const char* name() const override { return "PerlinNoise"; }
640
641 const SkPerlinNoiseShader2::StitchData& stitchData() const { return fPaintingData->fStitchDataInit; }
642
643 SkPerlinNoiseShader2::Type type() const { return fType; }
644 bool stitchTiles() const { return fStitchTiles; }
645 const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; }
646 int numOctaves() const { return fNumOctaves; }
647 const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
648
649private:
egdaniel57d3b032015-11-13 11:57:27 -0800650 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
robertphillipsd3b32bf2016-02-05 07:15:39 -0800651 return new GrGLPerlinNoise2;
ethannicholas417011c2015-11-09 06:35:12 -0800652 }
653
Brian Salomon94efbf52016-11-29 13:43:05 -0500654 virtual void onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800655 GrProcessorKeyBuilder* b) const override {
ethannicholas417011c2015-11-09 06:35:12 -0800656 GrGLPerlinNoise2::GenKey(*this, caps, b);
657 }
658
659 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
660 const GrPerlinNoise2Effect& s = sBase.cast<GrPerlinNoise2Effect>();
661 return fType == s.fType &&
662 fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency &&
663 fNumOctaves == s.fNumOctaves &&
664 fStitchTiles == s.fStitchTiles &&
665 fPaintingData->fStitchDataInit == s.fPaintingData->fStitchDataInit;
666 }
667
Robert Phillips6f9f7eb2017-02-18 15:15:51 -0500668 GrPerlinNoise2Effect(GrTextureProvider* textureProvider,
669 SkPerlinNoiseShader2::Type type, int numOctaves, bool stitchTiles,
Brian Salomon587e08f2017-01-27 10:59:27 -0500670 SkPerlinNoiseShader2::PaintingData* paintingData,
Robert Phillips6f9f7eb2017-02-18 15:15:51 -0500671 sk_sp<GrTextureProxy> permutationsProxy,
672 sk_sp<GrTextureProxy> noiseProxy,
Brian Salomon587e08f2017-01-27 10:59:27 -0500673 const SkMatrix& matrix)
674 : INHERITED(kNone_OptimizationFlags)
675 , fType(type)
676 , fNumOctaves(numOctaves)
677 , fStitchTiles(stitchTiles)
Robert Phillips6f9f7eb2017-02-18 15:15:51 -0500678 , fPermutationsSampler(textureProvider, std::move(permutationsProxy))
679 , fNoiseSampler(textureProvider, std::move(noiseProxy))
Brian Salomon587e08f2017-01-27 10:59:27 -0500680 , fPaintingData(paintingData) {
ethannicholas417011c2015-11-09 06:35:12 -0800681 this->initClassID<GrPerlinNoise2Effect>();
Brian Salomon0bbecb22016-11-17 11:38:22 -0500682 this->addTextureSampler(&fPermutationsSampler);
683 this->addTextureSampler(&fNoiseSampler);
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400684 fCoordTransform.reset(matrix);
ethannicholas417011c2015-11-09 06:35:12 -0800685 this->addCoordTransform(&fCoordTransform);
686 }
687
688 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
689
Brian Salomon0bbecb22016-11-17 11:38:22 -0500690 SkPerlinNoiseShader2::Type fType;
691 GrCoordTransform fCoordTransform;
692 int fNumOctaves;
693 bool fStitchTiles;
694 TextureSampler fPermutationsSampler;
695 TextureSampler fNoiseSampler;
696 SkPerlinNoiseShader2::PaintingData* fPaintingData;
ethannicholas417011c2015-11-09 06:35:12 -0800697
ethannicholas417011c2015-11-09 06:35:12 -0800698 typedef GrFragmentProcessor INHERITED;
699};
700
701/////////////////////////////////////////////////////////////////////
702GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrPerlinNoise2Effect);
703
Hal Canary6f6961e2017-01-31 13:50:44 -0500704#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700705sk_sp<GrFragmentProcessor> GrPerlinNoise2Effect::TestCreate(GrProcessorTestData* d) {
ethannicholas417011c2015-11-09 06:35:12 -0800706 int numOctaves = d->fRandom->nextRangeU(2, 10);
707 bool stitchTiles = d->fRandom->nextBool();
708 SkScalar seed = SkIntToScalar(d->fRandom->nextU());
709 SkISize tileSize = SkISize::Make(d->fRandom->nextRangeU(4, 4096),
710 d->fRandom->nextRangeU(4, 4096));
711 SkScalar baseFrequencyX = d->fRandom->nextRangeScalar(0.01f,
712 0.99f);
713 SkScalar baseFrequencyY = d->fRandom->nextRangeScalar(0.01f,
714 0.99f);
715
reed8a21c9f2016-03-08 18:50:00 -0800716 sk_sp<SkShader> shader(d->fRandom->nextBool() ?
717 SkPerlinNoiseShader2::MakeFractalNoise(baseFrequencyX, baseFrequencyY, numOctaves, seed,
718 stitchTiles ? &tileSize : nullptr) :
719 SkPerlinNoiseShader2::MakeTurbulence(baseFrequencyX, baseFrequencyY, numOctaves, seed,
ethannicholas417011c2015-11-09 06:35:12 -0800720 stitchTiles ? &tileSize : nullptr));
721
Brian Osman9f532a32016-10-19 11:12:09 -0400722 GrTest::TestAsFPArgs asFPArgs(d);
723 return shader->asFragmentProcessor(asFPArgs.args());
ethannicholas417011c2015-11-09 06:35:12 -0800724}
Hal Canary6f6961e2017-01-31 13:50:44 -0500725#endif
ethannicholas417011c2015-11-09 06:35:12 -0800726
ethannicholas417011c2015-11-09 06:35:12 -0800727void GrGLPerlinNoise2::emitCode(EmitArgs& args) {
robertphillipsd3b32bf2016-02-05 07:15:39 -0800728 const GrPerlinNoise2Effect& pne = args.fFp.cast<GrPerlinNoise2Effect>();
729
egdaniel4ca2e602015-11-18 08:01:26 -0800730 GrGLSLFragmentBuilder* fsBuilder = args.fFragBuilder;
egdaniel7ea439b2015-12-03 09:20:44 -0800731 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
bsalomon1a1aa932016-09-12 09:30:36 -0700732 SkString vCoords = fsBuilder->ensureCoords2D(args.fTransformedCoords[0]);
ethannicholas417011c2015-11-09 06:35:12 -0800733
cdalton5e58cee2016-02-11 12:49:47 -0800734 fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800735 kVec2f_GrSLType, kDefault_GrSLPrecision,
736 "baseFrequency");
737 const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);
ethannicholas417011c2015-11-09 06:35:12 -0800738
739 const char* stitchDataUni = nullptr;
robertphillipsd3b32bf2016-02-05 07:15:39 -0800740 if (pne.stitchTiles()) {
cdalton5e58cee2016-02-11 12:49:47 -0800741 fStitchDataUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800742 kVec2f_GrSLType, kDefault_GrSLPrecision,
743 "stitchData");
744 stitchDataUni = uniformHandler->getUniformCStr(fStitchDataUni);
ethannicholas417011c2015-11-09 06:35:12 -0800745 }
746
747 // There are 4 lines, so the center of each line is 1/8, 3/8, 5/8 and 7/8
748 const char* chanCoordR = "0.125";
749 const char* chanCoordG = "0.375";
750 const char* chanCoordB = "0.625";
751 const char* chanCoordA = "0.875";
752 const char* chanCoord = "chanCoord";
753 const char* stitchData = "stitchData";
754 const char* ratio = "ratio";
755 const char* noiseVec = "noiseVec";
756 const char* noiseSmooth = "noiseSmooth";
757 const char* floorVal = "floorVal";
758 const char* fractVal = "fractVal";
759 const char* uv = "uv";
760 const char* ab = "ab";
761 const char* latticeIdx = "latticeIdx";
762 const char* bcoords = "bcoords";
763 const char* lattice = "lattice";
764 const char* inc8bit = "0.00390625"; // 1.0 / 256.0
765 // This is the math to convert the two 16bit integer packed into rgba 8 bit input into a
766 // [-1,1] vector and perform a dot product between that vector and the provided vector.
767 const char* dotLattice = "dot(((%s.ga + %s.rb * vec2(%s)) * vec2(2.0) - vec2(1.0)), %s);";
768
769 // Add noise function
Brian Salomon99938a82016-11-21 13:41:08 -0500770 static const GrShaderVar gPerlinNoiseArgs[] = {
771 GrShaderVar(chanCoord, kFloat_GrSLType),
772 GrShaderVar(noiseVec, kVec2f_GrSLType)
ethannicholas417011c2015-11-09 06:35:12 -0800773 };
774
Brian Salomon99938a82016-11-21 13:41:08 -0500775 static const GrShaderVar gPerlinNoiseStitchArgs[] = {
776 GrShaderVar(chanCoord, kFloat_GrSLType),
777 GrShaderVar(noiseVec, kVec2f_GrSLType),
778 GrShaderVar(stitchData, kVec2f_GrSLType)
ethannicholas417011c2015-11-09 06:35:12 -0800779 };
780
781 SkString noiseCode;
782
783 noiseCode.appendf("\tvec4 %s;\n", floorVal);
784 noiseCode.appendf("\t%s.xy = floor(%s);\n", floorVal, noiseVec);
785 noiseCode.appendf("\t%s.zw = %s.xy + vec2(1.0);\n", floorVal, floorVal);
786 noiseCode.appendf("\tvec2 %s = fract(%s);\n", fractVal, noiseVec);
787
788 // smooth curve : t * t * (3 - 2 * t)
789 noiseCode.appendf("\n\tvec2 %s = %s * %s * (vec2(3.0) - vec2(2.0) * %s);",
790 noiseSmooth, fractVal, fractVal, fractVal);
791
792 // Adjust frequencies if we're stitching tiles
robertphillipsd3b32bf2016-02-05 07:15:39 -0800793 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800794 noiseCode.appendf("\n\tif(%s.x >= %s.x) { %s.x -= %s.x; }",
795 floorVal, stitchData, floorVal, stitchData);
796 noiseCode.appendf("\n\tif(%s.y >= %s.y) { %s.y -= %s.y; }",
797 floorVal, stitchData, floorVal, stitchData);
798 noiseCode.appendf("\n\tif(%s.z >= %s.x) { %s.z -= %s.x; }",
799 floorVal, stitchData, floorVal, stitchData);
800 noiseCode.appendf("\n\tif(%s.w >= %s.y) { %s.w -= %s.y; }",
801 floorVal, stitchData, floorVal, stitchData);
802 }
803
804 // Get texture coordinates and normalize
805 noiseCode.appendf("\n\t%s = fract(floor(mod(%s, 256.0)) / vec4(256.0));\n",
806 floorVal, floorVal);
807
808 // Get permutation for x
809 {
810 SkString xCoords("");
811 xCoords.appendf("vec2(%s.x, 0.5)", floorVal);
812
813 noiseCode.appendf("\n\tvec2 %s;\n\t%s.x = ", latticeIdx, latticeIdx);
cdalton3f6f76f2016-04-11 12:18:09 -0700814 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800815 kVec2f_GrSLType);
816 noiseCode.append(".r;");
817 }
818
819 // Get permutation for x + 1
820 {
821 SkString xCoords("");
822 xCoords.appendf("vec2(%s.z, 0.5)", floorVal);
823
824 noiseCode.appendf("\n\t%s.y = ", latticeIdx);
cdalton3f6f76f2016-04-11 12:18:09 -0700825 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800826 kVec2f_GrSLType);
827 noiseCode.append(".r;");
828 }
829
830#if defined(SK_BUILD_FOR_ANDROID)
831 // Android rounding for Tegra devices, like, for example: Xoom (Tegra 2), Nexus 7 (Tegra 3).
832 // The issue is that colors aren't accurate enough on Tegra devices. For example, if an 8 bit
833 // value of 124 (or 0.486275 here) is entered, we can get a texture value of 123.513725
834 // (or 0.484368 here). The following rounding operation prevents these precision issues from
835 // affecting the result of the noise by making sure that we only have multiples of 1/255.
836 // (Note that 1/255 is about 0.003921569, which is the value used here).
837 noiseCode.appendf("\n\t%s = floor(%s * vec2(255.0) + vec2(0.5)) * vec2(0.003921569);",
838 latticeIdx, latticeIdx);
839#endif
840
841 // Get (x,y) coordinates with the permutated x
842 noiseCode.appendf("\n\tvec4 %s = fract(%s.xyxy + %s.yyww);", bcoords, latticeIdx, floorVal);
843
844 noiseCode.appendf("\n\n\tvec2 %s;", uv);
845 // Compute u, at offset (0,0)
846 {
847 SkString latticeCoords("");
848 latticeCoords.appendf("vec2(%s.x, %s)", bcoords, chanCoord);
849 noiseCode.appendf("\n\tvec4 %s = ", lattice);
cdalton3f6f76f2016-04-11 12:18:09 -0700850 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800851 kVec2f_GrSLType);
852 noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
853 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
854 }
855
856 noiseCode.appendf("\n\t%s.x -= 1.0;", fractVal);
857 // Compute v, at offset (-1,0)
858 {
859 SkString latticeCoords("");
860 latticeCoords.appendf("vec2(%s.y, %s)", bcoords, chanCoord);
861 noiseCode.append("\n\tlattice = ");
cdalton3f6f76f2016-04-11 12:18:09 -0700862 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800863 kVec2f_GrSLType);
864 noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
865 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
866 }
867
868 // Compute 'a' as a linear interpolation of 'u' and 'v'
869 noiseCode.appendf("\n\tvec2 %s;", ab);
870 noiseCode.appendf("\n\t%s.x = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
871
872 noiseCode.appendf("\n\t%s.y -= 1.0;", fractVal);
873 // Compute v, at offset (-1,-1)
874 {
875 SkString latticeCoords("");
876 latticeCoords.appendf("vec2(%s.w, %s)", bcoords, chanCoord);
877 noiseCode.append("\n\tlattice = ");
cdalton3f6f76f2016-04-11 12:18:09 -0700878 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800879 kVec2f_GrSLType);
880 noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
881 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
882 }
883
884 noiseCode.appendf("\n\t%s.x += 1.0;", fractVal);
885 // Compute u, at offset (0,-1)
886 {
887 SkString latticeCoords("");
888 latticeCoords.appendf("vec2(%s.z, %s)", bcoords, chanCoord);
889 noiseCode.append("\n\tlattice = ");
cdalton3f6f76f2016-04-11 12:18:09 -0700890 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800891 kVec2f_GrSLType);
892 noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
893 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
894 }
895
896 // Compute 'b' as a linear interpolation of 'u' and 'v'
897 noiseCode.appendf("\n\t%s.y = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
898 // Compute the noise as a linear interpolation of 'a' and 'b'
899 noiseCode.appendf("\n\treturn mix(%s.x, %s.y, %s.y);\n", ab, ab, noiseSmooth);
900
901 SkString noiseFuncName;
robertphillipsd3b32bf2016-02-05 07:15:39 -0800902 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800903 fsBuilder->emitFunction(kFloat_GrSLType,
904 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseStitchArgs),
905 gPerlinNoiseStitchArgs, noiseCode.c_str(), &noiseFuncName);
906 } else {
907 fsBuilder->emitFunction(kFloat_GrSLType,
908 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseArgs),
909 gPerlinNoiseArgs, noiseCode.c_str(), &noiseFuncName);
910 }
911
912 // There are rounding errors if the floor operation is not performed here
913 fsBuilder->codeAppendf("\n\t\tvec2 %s = floor(%s.xy) * %s;",
914 noiseVec, vCoords.c_str(), baseFrequencyUni);
915
916 // Clear the color accumulator
917 fsBuilder->codeAppendf("\n\t\t%s = vec4(0.0);", args.fOutputColor);
918
robertphillipsd3b32bf2016-02-05 07:15:39 -0800919 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800920 // Set up TurbulenceInitial stitch values.
921 fsBuilder->codeAppendf("\n\t\tvec2 %s = %s;", stitchData, stitchDataUni);
922 }
923
924 fsBuilder->codeAppendf("\n\t\tfloat %s = 1.0;", ratio);
925
926 // Loop over all octaves
robertphillipsd3b32bf2016-02-05 07:15:39 -0800927 fsBuilder->codeAppendf("for (int octave = 0; octave < %d; ++octave) {", pne.numOctaves());
ethannicholas417011c2015-11-09 06:35:12 -0800928
929 fsBuilder->codeAppendf("\n\t\t\t%s += ", args.fOutputColor);
robertphillipsd3b32bf2016-02-05 07:15:39 -0800930 if (pne.type() != SkPerlinNoiseShader2::kFractalNoise_Type) {
ethannicholas417011c2015-11-09 06:35:12 -0800931 fsBuilder->codeAppend("abs(");
932 }
robertphillipsd3b32bf2016-02-05 07:15:39 -0800933 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800934 fsBuilder->codeAppendf(
935 "vec4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s),"
936 "\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))",
937 noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData,
938 noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData,
939 noiseFuncName.c_str(), chanCoordB, noiseVec, stitchData,
940 noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData);
941 } else {
942 fsBuilder->codeAppendf(
943 "vec4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s),"
944 "\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))",
945 noiseFuncName.c_str(), chanCoordR, noiseVec,
946 noiseFuncName.c_str(), chanCoordG, noiseVec,
947 noiseFuncName.c_str(), chanCoordB, noiseVec,
948 noiseFuncName.c_str(), chanCoordA, noiseVec);
949 }
robertphillipsd3b32bf2016-02-05 07:15:39 -0800950 if (pne.type() != SkPerlinNoiseShader2::kFractalNoise_Type) {
ethannicholas417011c2015-11-09 06:35:12 -0800951 fsBuilder->codeAppendf(")"); // end of "abs("
952 }
953 fsBuilder->codeAppendf(" * %s;", ratio);
954
955 fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", noiseVec);
956 fsBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio);
957
robertphillipsd3b32bf2016-02-05 07:15:39 -0800958 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800959 fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", stitchData);
960 }
961 fsBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves
962
robertphillipsd3b32bf2016-02-05 07:15:39 -0800963 if (pne.type() == SkPerlinNoiseShader2::kFractalNoise_Type) {
ethannicholas417011c2015-11-09 06:35:12 -0800964 // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
965 // by fractalNoise and (turbulenceFunctionResult) by turbulence.
966 fsBuilder->codeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);",
967 args.fOutputColor,args.fOutputColor);
968 }
969
970 // Clamp values
971 fsBuilder->codeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor);
972
973 // Pre-multiply the result
974 fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
975 args.fOutputColor, args.fOutputColor,
976 args.fOutputColor, args.fOutputColor);
977}
978
Brian Salomon94efbf52016-11-29 13:43:05 -0500979void GrGLPerlinNoise2::GenKey(const GrProcessor& processor, const GrShaderCaps&,
egdaniel2d721d32015-11-11 13:06:05 -0800980 GrProcessorKeyBuilder* b) {
ethannicholas417011c2015-11-09 06:35:12 -0800981 const GrPerlinNoise2Effect& turbulence = processor.cast<GrPerlinNoise2Effect>();
982
983 uint32_t key = turbulence.numOctaves();
984
985 key = key << 3; // Make room for next 3 bits
986
987 switch (turbulence.type()) {
988 case SkPerlinNoiseShader2::kFractalNoise_Type:
989 key |= 0x1;
990 break;
991 case SkPerlinNoiseShader2::kTurbulence_Type:
992 key |= 0x2;
993 break;
994 default:
995 // leave key at 0
996 break;
997 }
998
999 if (turbulence.stitchTiles()) {
1000 key |= 0x4; // Flip the 3rd bit if tile stitching is on
1001 }
1002
1003 b->add32(key);
1004}
1005
1006void GrGLPerlinNoise2::onSetData(const GrGLSLProgramDataManager& pdman,
1007 const GrProcessor& processor) {
1008 INHERITED::onSetData(pdman, processor);
1009
1010 const GrPerlinNoise2Effect& turbulence = processor.cast<GrPerlinNoise2Effect>();
1011
1012 const SkVector& baseFrequency = turbulence.baseFrequency();
1013 pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
1014
1015 if (turbulence.stitchTiles()) {
1016 const SkPerlinNoiseShader2::StitchData& stitchData = turbulence.stitchData();
1017 pdman.set2f(fStitchDataUni, SkIntToScalar(stitchData.fWidth),
1018 SkIntToScalar(stitchData.fHeight));
1019 }
1020}
1021
1022/////////////////////////////////////////////////////////////////////
1023
egdaniel64c47282015-11-13 06:54:19 -08001024class GrGLImprovedPerlinNoise : public GrGLSLFragmentProcessor {
ethannicholas417011c2015-11-09 06:35:12 -08001025public:
robertphillipsbf536af2016-02-04 06:11:53 -08001026 void emitCode(EmitArgs&) override;
ethannicholas417011c2015-11-09 06:35:12 -08001027
Brian Salomon94efbf52016-11-29 13:43:05 -05001028 static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*);
ethannicholas417011c2015-11-09 06:35:12 -08001029
1030protected:
1031 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
1032
1033private:
ethannicholas417011c2015-11-09 06:35:12 -08001034 GrGLSLProgramDataManager::UniformHandle fZUni;
1035 GrGLSLProgramDataManager::UniformHandle fOctavesUni;
1036 GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni;
1037
egdaniel64c47282015-11-13 06:54:19 -08001038 typedef GrGLSLFragmentProcessor INHERITED;
ethannicholas417011c2015-11-09 06:35:12 -08001039};
1040
1041/////////////////////////////////////////////////////////////////////
1042
1043class GrImprovedPerlinNoiseEffect : public GrFragmentProcessor {
1044public:
bungeman06ca8ec2016-06-09 08:01:03 -07001045 static sk_sp<GrFragmentProcessor> Make(int octaves, SkScalar z,
1046 SkPerlinNoiseShader2::PaintingData* paintingData,
1047 GrTexture* permutationsTexture,
1048 GrTexture* gradientTexture,
1049 const SkMatrix& matrix) {
1050 return sk_sp<GrFragmentProcessor>(
1051 new GrImprovedPerlinNoiseEffect(octaves, z, paintingData, permutationsTexture,
1052 gradientTexture, matrix));
ethannicholas417011c2015-11-09 06:35:12 -08001053 }
1054
1055 virtual ~GrImprovedPerlinNoiseEffect() { delete fPaintingData; }
1056
1057 const char* name() const override { return "ImprovedPerlinNoise"; }
1058
1059 const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; }
1060 SkScalar z() const { return fZ; }
1061 int octaves() const { return fOctaves; }
1062 const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
1063
1064private:
egdaniel57d3b032015-11-13 11:57:27 -08001065 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
robertphillipsbf536af2016-02-04 06:11:53 -08001066 return new GrGLImprovedPerlinNoise;
ethannicholas417011c2015-11-09 06:35:12 -08001067 }
1068
Brian Salomon94efbf52016-11-29 13:43:05 -05001069 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
ethannicholas417011c2015-11-09 06:35:12 -08001070 GrGLImprovedPerlinNoise::GenKey(*this, caps, b);
1071 }
1072
1073 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
1074 const GrImprovedPerlinNoiseEffect& s = sBase.cast<GrImprovedPerlinNoiseEffect>();
1075 return fZ == fZ &&
1076 fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency;
1077 }
1078
Brian Salomon587e08f2017-01-27 10:59:27 -05001079 GrImprovedPerlinNoiseEffect(int octaves, SkScalar z,
ethannicholas417011c2015-11-09 06:35:12 -08001080 SkPerlinNoiseShader2::PaintingData* paintingData,
1081 GrTexture* permutationsTexture, GrTexture* gradientTexture,
1082 const SkMatrix& matrix)
Brian Salomon587e08f2017-01-27 10:59:27 -05001083 : INHERITED(kNone_OptimizationFlags)
1084 , fOctaves(octaves)
1085 , fZ(z)
1086 , fPermutationsSampler(permutationsTexture)
1087 , fGradientSampler(gradientTexture)
1088 , fPaintingData(paintingData) {
ethannicholas417011c2015-11-09 06:35:12 -08001089 this->initClassID<GrImprovedPerlinNoiseEffect>();
Brian Salomon0bbecb22016-11-17 11:38:22 -05001090 this->addTextureSampler(&fPermutationsSampler);
1091 this->addTextureSampler(&fGradientSampler);
Brian Salomon2ebd0c82016-10-03 17:15:28 -04001092 fCoordTransform.reset(matrix);
ethannicholas417011c2015-11-09 06:35:12 -08001093 this->addCoordTransform(&fCoordTransform);
1094 }
1095
1096 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
1097
Brian Salomon0bbecb22016-11-17 11:38:22 -05001098 GrCoordTransform fCoordTransform;
1099 int fOctaves;
1100 SkScalar fZ;
1101 TextureSampler fPermutationsSampler;
1102 TextureSampler fGradientSampler;
1103 SkPerlinNoiseShader2::PaintingData* fPaintingData;
ethannicholas417011c2015-11-09 06:35:12 -08001104
ethannicholas417011c2015-11-09 06:35:12 -08001105 typedef GrFragmentProcessor INHERITED;
1106};
1107
1108/////////////////////////////////////////////////////////////////////
1109GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrImprovedPerlinNoiseEffect);
1110
Hal Canary6f6961e2017-01-31 13:50:44 -05001111#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -07001112sk_sp<GrFragmentProcessor> GrImprovedPerlinNoiseEffect::TestCreate(GrProcessorTestData* d) {
ethannicholas417011c2015-11-09 06:35:12 -08001113 SkScalar baseFrequencyX = d->fRandom->nextRangeScalar(0.01f,
1114 0.99f);
1115 SkScalar baseFrequencyY = d->fRandom->nextRangeScalar(0.01f,
1116 0.99f);
1117 int numOctaves = d->fRandom->nextRangeU(2, 10);
1118 SkScalar z = SkIntToScalar(d->fRandom->nextU());
1119
reed8a21c9f2016-03-08 18:50:00 -08001120 sk_sp<SkShader> shader(SkPerlinNoiseShader2::MakeImprovedNoise(baseFrequencyX,
1121 baseFrequencyY,
1122 numOctaves,
1123 z));
ethannicholas417011c2015-11-09 06:35:12 -08001124
Brian Osman9f532a32016-10-19 11:12:09 -04001125 GrTest::TestAsFPArgs asFPArgs(d);
1126 return shader->asFragmentProcessor(asFPArgs.args());
ethannicholas417011c2015-11-09 06:35:12 -08001127}
Hal Canary6f6961e2017-01-31 13:50:44 -05001128#endif
ethannicholas417011c2015-11-09 06:35:12 -08001129
ethannicholas417011c2015-11-09 06:35:12 -08001130void GrGLImprovedPerlinNoise::emitCode(EmitArgs& args) {
egdaniel4ca2e602015-11-18 08:01:26 -08001131 GrGLSLFragmentBuilder* fsBuilder = args.fFragBuilder;
egdaniel7ea439b2015-12-03 09:20:44 -08001132 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
bsalomon1a1aa932016-09-12 09:30:36 -07001133 SkString vCoords = fsBuilder->ensureCoords2D(args.fTransformedCoords[0]);
ethannicholas417011c2015-11-09 06:35:12 -08001134
cdalton5e58cee2016-02-11 12:49:47 -08001135 fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001136 kVec2f_GrSLType, kDefault_GrSLPrecision,
1137 "baseFrequency");
1138 const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);
ethannicholas417011c2015-11-09 06:35:12 -08001139
cdalton5e58cee2016-02-11 12:49:47 -08001140 fOctavesUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001141 kFloat_GrSLType, kDefault_GrSLPrecision,
1142 "octaves");
1143 const char* octavesUni = uniformHandler->getUniformCStr(fOctavesUni);
ethannicholas417011c2015-11-09 06:35:12 -08001144
cdalton5e58cee2016-02-11 12:49:47 -08001145 fZUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001146 kFloat_GrSLType, kDefault_GrSLPrecision,
1147 "z");
1148 const char* zUni = uniformHandler->getUniformCStr(fZUni);
ethannicholas417011c2015-11-09 06:35:12 -08001149
1150 // fade function
Brian Salomon99938a82016-11-21 13:41:08 -05001151 static const GrShaderVar fadeArgs[] = {
1152 GrShaderVar("t", kVec3f_GrSLType)
ethannicholas417011c2015-11-09 06:35:12 -08001153 };
1154 SkString fadeFuncName;
1155 fsBuilder->emitFunction(kVec3f_GrSLType, "fade", SK_ARRAY_COUNT(fadeArgs),
Herb Derby99d47212017-01-31 15:30:44 -05001156 fadeArgs,
1157 "return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);",
ethannicholas417011c2015-11-09 06:35:12 -08001158 &fadeFuncName);
1159
1160 // perm function
Brian Salomon99938a82016-11-21 13:41:08 -05001161 static const GrShaderVar permArgs[] = {
1162 GrShaderVar("x", kFloat_GrSLType)
ethannicholas417011c2015-11-09 06:35:12 -08001163 };
1164 SkString permFuncName;
1165 SkString permCode("return ");
Herb Derby99d47212017-01-31 15:30:44 -05001166 // FIXME even though I'm creating these textures with kRepeat_TileMode, they're clamped. Not
ethannicholas417011c2015-11-09 06:35:12 -08001167 // sure why. Using fract() (here and the next texture lookup) as a workaround.
cdalton3f6f76f2016-04-11 12:18:09 -07001168 fsBuilder->appendTextureLookup(&permCode, args.fTexSamplers[0], "vec2(fract(x / 256.0), 0.0)",
ethannicholas417011c2015-11-09 06:35:12 -08001169 kVec2f_GrSLType);
1170 permCode.append(".r * 255.0;");
Herb Derby99d47212017-01-31 15:30:44 -05001171 fsBuilder->emitFunction(kFloat_GrSLType, "perm", SK_ARRAY_COUNT(permArgs), permArgs,
ethannicholas417011c2015-11-09 06:35:12 -08001172 permCode.c_str(), &permFuncName);
1173
1174 // grad function
Brian Salomon99938a82016-11-21 13:41:08 -05001175 static const GrShaderVar gradArgs[] = {
1176 GrShaderVar("x", kFloat_GrSLType),
1177 GrShaderVar("p", kVec3f_GrSLType)
ethannicholas417011c2015-11-09 06:35:12 -08001178 };
1179 SkString gradFuncName;
1180 SkString gradCode("return dot(");
cdalton3f6f76f2016-04-11 12:18:09 -07001181 fsBuilder->appendTextureLookup(&gradCode, args.fTexSamplers[1], "vec2(fract(x / 16.0), 0.0)",
ethannicholas417011c2015-11-09 06:35:12 -08001182 kVec2f_GrSLType);
1183 gradCode.append(".rgb * 255.0 - vec3(1.0), p);");
Herb Derby99d47212017-01-31 15:30:44 -05001184 fsBuilder->emitFunction(kFloat_GrSLType, "grad", SK_ARRAY_COUNT(gradArgs), gradArgs,
ethannicholas417011c2015-11-09 06:35:12 -08001185 gradCode.c_str(), &gradFuncName);
1186
1187 // lerp function
Brian Salomon99938a82016-11-21 13:41:08 -05001188 static const GrShaderVar lerpArgs[] = {
1189 GrShaderVar("a", kFloat_GrSLType),
1190 GrShaderVar("b", kFloat_GrSLType),
1191 GrShaderVar("w", kFloat_GrSLType)
ethannicholas417011c2015-11-09 06:35:12 -08001192 };
1193 SkString lerpFuncName;
Herb Derby99d47212017-01-31 15:30:44 -05001194 fsBuilder->emitFunction(kFloat_GrSLType, "lerp", SK_ARRAY_COUNT(lerpArgs), lerpArgs,
ethannicholas417011c2015-11-09 06:35:12 -08001195 "return a + w * (b - a);", &lerpFuncName);
1196
1197 // noise function
Brian Salomon99938a82016-11-21 13:41:08 -05001198 static const GrShaderVar noiseArgs[] = {
1199 GrShaderVar("p", kVec3f_GrSLType),
ethannicholas417011c2015-11-09 06:35:12 -08001200 };
1201 SkString noiseFuncName;
1202 SkString noiseCode;
1203 noiseCode.append("vec3 P = mod(floor(p), 256.0);");
1204 noiseCode.append("p -= floor(p);");
1205 noiseCode.appendf("vec3 f = %s(p);", fadeFuncName.c_str());
1206 noiseCode.appendf("float A = %s(P.x) + P.y;", permFuncName.c_str());
1207 noiseCode.appendf("float AA = %s(A) + P.z;", permFuncName.c_str());
1208 noiseCode.appendf("float AB = %s(A + 1.0) + P.z;", permFuncName.c_str());
1209 noiseCode.appendf("float B = %s(P.x + 1.0) + P.y;", permFuncName.c_str());
1210 noiseCode.appendf("float BA = %s(B) + P.z;", permFuncName.c_str());
1211 noiseCode.appendf("float BB = %s(B + 1.0) + P.z;", permFuncName.c_str());
1212 noiseCode.appendf("float result = %s(", lerpFuncName.c_str());
Herb Derby99d47212017-01-31 15:30:44 -05001213 noiseCode.appendf("%s(%s(%s(%s(AA), p),", lerpFuncName.c_str(), lerpFuncName.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -08001214 gradFuncName.c_str(), permFuncName.c_str());
Herb Derby99d47212017-01-31 15:30:44 -05001215 noiseCode.appendf("%s(%s(BA), p + vec3(-1.0, 0.0, 0.0)), f.x),", gradFuncName.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -08001216 permFuncName.c_str());
Herb Derby99d47212017-01-31 15:30:44 -05001217 noiseCode.appendf("%s(%s(%s(AB), p + vec3(0.0, -1.0, 0.0)),", lerpFuncName.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -08001218 gradFuncName.c_str(), permFuncName.c_str());
Herb Derby99d47212017-01-31 15:30:44 -05001219 noiseCode.appendf("%s(%s(BB), p + vec3(-1.0, -1.0, 0.0)), f.x), f.y),",
ethannicholas417011c2015-11-09 06:35:12 -08001220 gradFuncName.c_str(), permFuncName.c_str());
Herb Derby99d47212017-01-31 15:30:44 -05001221 noiseCode.appendf("%s(%s(%s(%s(AA + 1.0), p + vec3(0.0, 0.0, -1.0)),",
1222 lerpFuncName.c_str(), lerpFuncName.c_str(), gradFuncName.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -08001223 permFuncName.c_str());
Herb Derby99d47212017-01-31 15:30:44 -05001224 noiseCode.appendf("%s(%s(BA + 1.0), p + vec3(-1.0, 0.0, -1.0)), f.x),",
ethannicholas417011c2015-11-09 06:35:12 -08001225 gradFuncName.c_str(), permFuncName.c_str());
1226 noiseCode.appendf("%s(%s(%s(AB + 1.0), p + vec3(0.0, -1.0, -1.0)),",
1227 lerpFuncName.c_str(), gradFuncName.c_str(), permFuncName.c_str());
Herb Derby99d47212017-01-31 15:30:44 -05001228 noiseCode.appendf("%s(%s(BB + 1.0), p + vec3(-1.0, -1.0, -1.0)), f.x), f.y), f.z);",
ethannicholas417011c2015-11-09 06:35:12 -08001229 gradFuncName.c_str(), permFuncName.c_str());
1230 noiseCode.append("return result;");
Herb Derby99d47212017-01-31 15:30:44 -05001231 fsBuilder->emitFunction(kFloat_GrSLType, "noise", SK_ARRAY_COUNT(noiseArgs), noiseArgs,
ethannicholas417011c2015-11-09 06:35:12 -08001232 noiseCode.c_str(), &noiseFuncName);
Herb Derby99d47212017-01-31 15:30:44 -05001233
ethannicholas417011c2015-11-09 06:35:12 -08001234 // noiseOctaves function
Brian Salomon99938a82016-11-21 13:41:08 -05001235 static const GrShaderVar noiseOctavesArgs[] = {
1236 GrShaderVar("p", kVec3f_GrSLType),
1237 GrShaderVar("octaves", kFloat_GrSLType),
ethannicholas417011c2015-11-09 06:35:12 -08001238 };
1239 SkString noiseOctavesFuncName;
1240 SkString noiseOctavesCode;
1241 noiseOctavesCode.append("float result = 0.0;");
1242 noiseOctavesCode.append("float ratio = 1.0;");
1243 noiseOctavesCode.append("for (float i = 0.0; i < octaves; i++) {");
1244 noiseOctavesCode.appendf("result += %s(p) / ratio;", noiseFuncName.c_str());
1245 noiseOctavesCode.append("p *= 2.0;");
1246 noiseOctavesCode.append("ratio *= 2.0;");
1247 noiseOctavesCode.append("}");
1248 noiseOctavesCode.append("return (result + 1.0) / 2.0;");
Herb Derby99d47212017-01-31 15:30:44 -05001249 fsBuilder->emitFunction(kFloat_GrSLType, "noiseOctaves", SK_ARRAY_COUNT(noiseOctavesArgs),
ethannicholas417011c2015-11-09 06:35:12 -08001250 noiseOctavesArgs, noiseOctavesCode.c_str(), &noiseOctavesFuncName);
1251
1252 fsBuilder->codeAppendf("vec2 coords = %s * %s;", vCoords.c_str(), baseFrequencyUni);
Herb Derby99d47212017-01-31 15:30:44 -05001253 fsBuilder->codeAppendf("float r = %s(vec3(coords, %s), %s);", noiseOctavesFuncName.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -08001254 zUni, octavesUni);
Herb Derby99d47212017-01-31 15:30:44 -05001255 fsBuilder->codeAppendf("float g = %s(vec3(coords, %s + 0000.0), %s);",
ethannicholas417011c2015-11-09 06:35:12 -08001256 noiseOctavesFuncName.c_str(), zUni, octavesUni);
Herb Derby99d47212017-01-31 15:30:44 -05001257 fsBuilder->codeAppendf("float b = %s(vec3(coords, %s + 0000.0), %s);",
ethannicholas417011c2015-11-09 06:35:12 -08001258 noiseOctavesFuncName.c_str(), zUni, octavesUni);
Herb Derby99d47212017-01-31 15:30:44 -05001259 fsBuilder->codeAppendf("float a = %s(vec3(coords, %s + 0000.0), %s);",
ethannicholas417011c2015-11-09 06:35:12 -08001260 noiseOctavesFuncName.c_str(), zUni, octavesUni);
1261 fsBuilder->codeAppendf("%s = vec4(r, g, b, a);", args.fOutputColor);
1262
1263 // Clamp values
1264 fsBuilder->codeAppendf("%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor);
1265
1266 // Pre-multiply the result
1267 fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
1268 args.fOutputColor, args.fOutputColor,
1269 args.fOutputColor, args.fOutputColor);
1270}
1271
Brian Salomon94efbf52016-11-29 13:43:05 -05001272void GrGLImprovedPerlinNoise::GenKey(const GrProcessor& processor, const GrShaderCaps&,
ethannicholas417011c2015-11-09 06:35:12 -08001273 GrProcessorKeyBuilder* b) {
1274}
1275
1276void GrGLImprovedPerlinNoise::onSetData(const GrGLSLProgramDataManager& pdman,
1277 const GrProcessor& processor) {
1278 INHERITED::onSetData(pdman, processor);
1279
1280 const GrImprovedPerlinNoiseEffect& noise = processor.cast<GrImprovedPerlinNoiseEffect>();
1281
1282 const SkVector& baseFrequency = noise.baseFrequency();
1283 pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
1284
egdaniel478c04e2015-11-09 07:40:49 -08001285 pdman.set1f(fOctavesUni, SkIntToScalar(noise.octaves()));
ethannicholas417011c2015-11-09 06:35:12 -08001286
1287 pdman.set1f(fZUni, noise.z());
1288}
1289
1290/////////////////////////////////////////////////////////////////////
brianosman839345d2016-07-22 11:04:53 -07001291sk_sp<GrFragmentProcessor> SkPerlinNoiseShader2::asFragmentProcessor(const AsFPArgs& args) const {
1292 SkASSERT(args.fContext);
ethannicholas417011c2015-11-09 06:35:12 -08001293
1294 SkMatrix localMatrix = this->getLocalMatrix();
brianosman839345d2016-07-22 11:04:53 -07001295 if (args.fLocalMatrix) {
1296 localMatrix.preConcat(*args.fLocalMatrix);
ethannicholas417011c2015-11-09 06:35:12 -08001297 }
1298
brianosman839345d2016-07-22 11:04:53 -07001299 SkMatrix matrix = *args.fViewMatrix;
ethannicholas417011c2015-11-09 06:35:12 -08001300 matrix.preConcat(localMatrix);
1301
1302 // Either we don't stitch tiles, either we have a valid tile size
1303 SkASSERT(!fStitchTiles || !fTileSize.isEmpty());
1304
1305 SkPerlinNoiseShader2::PaintingData* paintingData =
1306 new PaintingData(fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY, matrix);
1307
brianosman839345d2016-07-22 11:04:53 -07001308 SkMatrix m = *args.fViewMatrix;
ethannicholas417011c2015-11-09 06:35:12 -08001309 m.setTranslateX(-localMatrix.getTranslateX() + SK_Scalar1);
1310 m.setTranslateY(-localMatrix.getTranslateY() + SK_Scalar1);
1311
1312 if (fType == kImprovedNoise_Type) {
Brian Salomon514baff2016-11-17 15:17:07 -05001313 GrSamplerParams textureParams(SkShader::TileMode::kRepeat_TileMode,
1314 GrSamplerParams::FilterMode::kNone_FilterMode);
Hal Canary2db83612016-11-04 13:02:54 -04001315 sk_sp<GrTexture> permutationsTexture(
brianosman839345d2016-07-22 11:04:53 -07001316 GrRefCachedBitmapTexture(args.fContext, paintingData->getImprovedPermutationsBitmap(),
Robert Phillips67c18d62017-01-20 12:44:06 -05001317 textureParams, nullptr));
Hal Canary2db83612016-11-04 13:02:54 -04001318 sk_sp<GrTexture> gradientTexture(
brianosman839345d2016-07-22 11:04:53 -07001319 GrRefCachedBitmapTexture(args.fContext, paintingData->getGradientBitmap(),
Robert Phillips67c18d62017-01-20 12:44:06 -05001320 textureParams, nullptr));
bungeman06ca8ec2016-06-09 08:01:03 -07001321 return GrImprovedPerlinNoiseEffect::Make(fNumOctaves, fSeed, paintingData,
Hal Canary2db83612016-11-04 13:02:54 -04001322 permutationsTexture.get(),
1323 gradientTexture.get(), m);
ethannicholas417011c2015-11-09 06:35:12 -08001324 }
1325
1326 if (0 == fNumOctaves) {
1327 if (kFractalNoise_Type == fType) {
1328 // Extract the incoming alpha and emit rgba = (a/4, a/4, a/4, a/2)
Brian Osman618d3042016-10-25 10:51:28 -04001329 // TODO: Either treat the output of this shader as sRGB or allow client to specify a
1330 // color space of the noise. Either way, this case (and the GLSL) need to convert to
1331 // the destination.
bungeman06ca8ec2016-06-09 08:01:03 -07001332 sk_sp<GrFragmentProcessor> inner(
Brian Osman618d3042016-10-25 10:51:28 -04001333 GrConstColorProcessor::Make(GrColor4f::FromGrColor(0x80404040),
bungeman06ca8ec2016-06-09 08:01:03 -07001334 GrConstColorProcessor::kModulateRGBA_InputMode));
1335 return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner));
ethannicholas417011c2015-11-09 06:35:12 -08001336 }
1337 // Emit zero.
Brian Osman618d3042016-10-25 10:51:28 -04001338 return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
1339 GrConstColorProcessor::kIgnore_InputMode);
ethannicholas417011c2015-11-09 06:35:12 -08001340 }
1341
Robert Phillips6f9f7eb2017-02-18 15:15:51 -05001342 sk_sp<GrTextureProxy> permutationsProxy = GrMakeCachedBitmapProxy(
1343 args.fContext,
1344 paintingData->getPermutationsBitmap());
1345 sk_sp<GrTextureProxy> noiseProxy = GrMakeCachedBitmapProxy(args.fContext,
1346 paintingData->getNoiseBitmap());
ethannicholas417011c2015-11-09 06:35:12 -08001347
Robert Phillips6f9f7eb2017-02-18 15:15:51 -05001348 if (permutationsProxy && noiseProxy) {
bungeman06ca8ec2016-06-09 08:01:03 -07001349 sk_sp<GrFragmentProcessor> inner(
Robert Phillips6f9f7eb2017-02-18 15:15:51 -05001350 GrPerlinNoise2Effect::Make(args.fContext->textureProvider(),
1351 fType,
bungeman06ca8ec2016-06-09 08:01:03 -07001352 fNumOctaves,
1353 fStitchTiles,
1354 paintingData,
Robert Phillips6f9f7eb2017-02-18 15:15:51 -05001355 std::move(permutationsProxy),
1356 std::move(noiseProxy),
bungeman06ca8ec2016-06-09 08:01:03 -07001357 m));
1358 return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner));
ethannicholas417011c2015-11-09 06:35:12 -08001359 }
1360 delete paintingData;
1361 return nullptr;
1362}
1363
1364#endif
1365
1366#ifndef SK_IGNORE_TO_STRING
1367void SkPerlinNoiseShader2::toString(SkString* str) const {
1368 str->append("SkPerlinNoiseShader2: (");
1369
1370 str->append("type: ");
1371 switch (fType) {
1372 case kFractalNoise_Type:
1373 str->append("\"fractal noise\"");
1374 break;
1375 case kTurbulence_Type:
1376 str->append("\"turbulence\"");
1377 break;
1378 default:
1379 str->append("\"unknown\"");
1380 break;
1381 }
1382 str->append(" base frequency: (");
1383 str->appendScalar(fBaseFrequencyX);
1384 str->append(", ");
1385 str->appendScalar(fBaseFrequencyY);
1386 str->append(") number of octaves: ");
1387 str->appendS32(fNumOctaves);
1388 str->append(" seed: ");
1389 str->appendScalar(fSeed);
1390 str->append(" stitch tiles: ");
1391 str->append(fStitchTiles ? "true " : "false ");
1392
1393 this->INHERITED::toString(str);
1394
1395 str->append(")");
1396}
1397#endif